# ========== Copyright Header Begin ==========================================
# OpenSPARC T2 Processor File: RunScript.py
# Copyright (c) 2006 Sun Microsystems, Inc. All Rights Reserved.
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES.
# The above named program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public
# License version 2 as published by the Free Software Foundation.
# The above named program is distributed in the hope that it will be
# useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
# General Public License for more details.
# You should have received a copy of the GNU General Public
# License along with this work; if not, write to the Free Software
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
# ========== Copyright Header End ============================================
# A collection of functions that help display executed instructions and
# collect informaiton leading to a specified breakpoint.
# Use execfile('RunScript.py') to load this module into samfe python
# environment. This script is valid only when the samfe is in python mode,
# it cannot be used in line-oriented command mode. When in line-oriented
# command mode, use 'pym' command to enter python mode. Use 'pym_off()' in
# python mode to switch back to line-oriented command mode.
# available functions at the SAM UI:
print 'loading RunScript...'
print 'need to import proper XX_Python module'
symbol_table_filename
= 'symbol.tbl'
if os
.path
.exists(symbol_table_filename
):
symbol_table
= Pfe_SymbolTbl
.Pfe_SymbolTbl()
# global instruction count
paddr
= sim
.s
[sid
].va2pa(va
)
paddr
= sim
.s
[sid
].ra2pa(va
)
paddr
= va
& 0xffffffffffff
return '[%08x] %s' % (iword
, Rk_Python
.dis(iword
,0x0))
# show the latest executed instruction. If the execution is continuing at
# the background, we may not get the pc & instrWord of the same execution,
# because we access pc and instrWord in two function calls, so there is a
# possibility that the values are not matched. In other case, if a va is
# provided, we will need to translate that into pa, which can be tricky, as
# the execution may be at a different state, which may affect the va->pa
sid: strand id, default is 0
# if va=0, use the instruction to be executed next, otherwise use the
# provided va to access the instruction word and disassemble it.
instr
= disassemble(sid
, sim
.s
[sid
].pc
)
print 'sid=%d, pc=%#x, %s' % (sid
, sim
.s
[sid
].pc
, instr
)
instr
= disassemble(sid
, va
)
print 'sid=%d, pc=%#x, %s' % (sid
, va
, instr
)
# if there are breakpoints set up by "break" command, hitting one of those
# breakpoints will terminate runshow(), runbreak(), or runbreak2() function
# and return control to UI prompt. The breakpoints list specified in runbreak()
# or runbreak2() function will have the same effect on execution.
# execute instructions and display executed instructions along the way
# e.g., "runshow(100,1)" will run 100 instructions on strand1 and display
# every instruction executed.
def runshow(step
=1,sid
=0,fd
=sys
.stdout
,sym
=1):
step: number of instruction to be executed, default is 1
sid: strand id, default is 0
fd: write the output to a file descriptor, default to stdout
sym: show (PC) symbol if available
sam>>> fd1=open('0-tmp','w')
sam>>> runshow(10,fd=fd1)
sam>>> runshow(100,fd=fd1)
while (done
== 0) and (i
< step
):
instr
= disassemble(sid
, newPC
)
# check for hitting breakpoint
if (newPC
!= prevPC
+4) or (newTL
!= prevTL
):
# display PC or related symbol when PC moves to a different
if (sym
== 1) and (symbol_table
!= None):
fd
.write('%s, TL=%d:\n' % (symbol_table
.va2id(newPC
), newTL
))
fd
.write('PC=%#x, TL=%d:\n' % (newPC
, newTL
))
fd
.write('sid=%d, ic=%d, pc=%#x, %s\n' % (sid
, icount
, newPC
, instr
))
# execute instructions and check for breakpoints along the way
# e.g., runbreak(100,bpoints=[0x40070,0x40078,0x83400]) will run 100
# instructions on strand0 and display every instruction executed, if PC has a
# hit with any value in bpoints, then the execution will stop.
def runbreak(step
=1,sid
=0,bpoints
=[0x83400,0xfffffffff0000080L
,0x00122000],fd
=sys
.stdout
,sym
=1):
step: number of instruction to be executed, default is 1
sid: strand id, default is 0
bpoints: a list of PC breakpoints, default is empty list
fd: output file descriptor, default to stdout
sym: show (PC) symbol if available
while (done
== 0) and (i
< step
):
instr
= disassemble(sid
, newPC
)
fd
.write('BREAKPOINT: sid=%d, pc=%#x [%s]\n' % (sid
, newPC
, symbol_table
.va2id(newPC
)))
fd
.write('BREAKPOINT: sid=%d, pc=%#x\n' % (sid
, newPC
))
# execute the next instr if no breakpoint is hit
if (newPC
!= prevPC
+4) or (newTL
!= prevTL
):
# display PC or related symbol when PC moves to a
if (sym
== 1) and (symbol_table
!= None):
fd
.write('%s, TL=%d:\n' % (symbol_table
.va2id(newPC
), newTL
))
fd
.write('PC=%#x, TL=%d:\n' % (newPC
, newTL
))
fd
.write('sid=%d, ic=%d, pc=%#x, %s\n' % (sid
, icount
, newPC
, instr
))
# execute instructions and check for breakpoints along the way
# e.g., runbreak2(100,bpoints=[0x40070,0x40078,0x83400],size=50) will run
# 100 instructions on strand0 and display every instruction executed, if PC
# has a hit with any value in bpoints, then the execution will stop. The last
# 'size' instructions will be kept in specified file.
def runbreak2(step
=1,sid
=0,bpoints
=[0x83400,0xfffffffff0000080L
,0x00122000],fd
=sys
.stdout
,size
=10000):
step: number of instruction to be executed, default is 1
sid: strand id, default is 0
bpoints: a list of PC breakpoints, default is empty list
fd: output file descriptor, default to stdout
size: instr buffer size, the last 'size' instructions before the breakpoint
sam>>> fd1=open('0-tmp','w')
sam>>> runbreak2(10,bpoints=[0x83400],fd=fd1,size=100)
while (done
== 0) and (i
< step
):
instr
= disassemble(sid
, newPC
)
# execute the next instr if no breakpoint is hit
buffer[index
] = 'PC=%#x, %s' % (newPC
, instr
)
# dump out buffer if hit a breakpoint
for ii
in range(index
+1, size
):
fd
.write('sid=%d, ic=%d, %s\n' % (sid
, jj
, buffer[ii
]))
for ii
in range(0,index
+1):
fd
.write('sid=%d, ic=%d, %s\n' % (sid
, jj
, buffer[ii
]))
fd
.write('BREAKPOINT: sid=%d, pc=%#x [%s]\n' % (bs
.strand_id
, bs
.pc
, symbol_table
.va2id(bs
.pc
)))
fd
.write('BREAKPOINT: sid=%d, pc=%#x\n' % (bs
.strand_id
, bs
.pc
))
# check PASS/FAIL at the end of an execution, and return exit code
def runforever(insts
=0x7fffffffffffffff,ss
=None,bout
=1,va_pass
=[0x122000],va_fail
=[0x122020]):
insts: number of instructions to run per strand, default is MAXINT
ss: array of strand-ids, e.g., [0,1,2]. default is None, means all strands
bout: upon hitting pass/fail, 1 means exit, 0 means returns to caller
va_pass: array of 'pass' VAs, default is 0x122000
va_fail: array of 'fail' VAs, default is 0x122020
# special case, step through all strands
# otherwise only step through specified strands
strands
.append(sim
.s
[sid
])
bp_pass
[s
.strand_id
] = []
bp_pass
[s
.strand_id
].append(s
.brk
.on_inst_va(va
))
bp_fail
[s
.strand_id
] = []
bp_fail
[s
.strand_id
].append(s
.brk
.on_inst_va(va
))
sam
.ui_exec('stepi %d' % insts
)
# check for pass/fail breakpoint
if bp
[0] in bp_pass
[s
.strand_id
]:
elif bp
[0] in bp_fail
[s
.strand_id
]:
# if nothing hit, consider it is good
# display the PC of all strands
print 'T%d: PC=%#x' % (s
.strand_id
, s
.pc
)
###############################################################################
### SAM UI workaround. Use old commands prefixed with python
###############################################################################
print "ERROR: command is/went wrong"
sam
.ui_register('python','python SAM UI fixer',python
)
###############################################################################
### python memory debugging, for developers' internal use.
###############################################################################
gc
.set_debug(gc
.DEBUG_LEAK|gc
.DEBUG_STATS
)
print '\nGARBAGE OBJECTS:'
print '%s ---> %s' % (type(x
), xx
)