Initial commit of OpenSPARC T2 architecture model.
[OpenSPARC-T2-SAM] / sam-t2 / sam / cpus / vonk / ss / api / samfe / src / RunScript.py
CommitLineData
920dae64
AT
1# ========== Copyright Header Begin ==========================================
2#
3# OpenSPARC T2 Processor File: RunScript.py
4# Copyright (c) 2006 Sun Microsystems, Inc. All Rights Reserved.
5# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES.
6#
7# The above named program is free software; you can redistribute it and/or
8# modify it under the terms of the GNU General Public
9# License version 2 as published by the Free Software Foundation.
10#
11# The above named program is distributed in the hope that it will be
12# useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
13# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14# General Public License for more details.
15#
16# You should have received a copy of the GNU General Public
17# License along with this work; if not, write to the Free Software
18# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
19#
20# ========== Copyright Header End ============================================
21#
22# A collection of functions that help display executed instructions and
23# collect informaiton leading to a specified breakpoint.
24# Use execfile('RunScript.py') to load this module into samfe python
25# environment. This script is valid only when the samfe is in python mode,
26# it cannot be used in line-oriented command mode. When in line-oriented
27# command mode, use 'pym' command to enter python mode. Use 'pym_off()' in
28# python mode to switch back to line-oriented command mode.
29#
30
31# available functions at the SAM UI:
32# python showi()
33# python runshow()
34# python runbreak()
35# python runbreak2()
36# python runforever()
37# python allpc()
38
39print 'loading RunScript...'
40
41import os, sys
42import sam
43
44# change this as needed
45try:
46 import Rk_Python
47except:
48 print 'need to import proper XX_Python module'
49 sys.exit(1)
50
51
52symbol_table_filename = 'symbol.tbl'
53symbol_table = None
54
55if os.path.exists(symbol_table_filename):
56 try:
57 import Pfe_SymbolTbl
58 symbol_table = Pfe_SymbolTbl.Pfe_SymbolTbl()
59 except:
60 symbol_table = None
61
62# global instruction count
63icount = 0L
64
65def disassemble(sid,va):
66 paddr = sim.s[sid].va2pa(va)
67 if paddr == 0:
68 paddr = sim.s[sid].ra2pa(va)
69 if paddr == 0:
70 paddr = va & 0xffffffffffff
71 iword = sim.mem.w[paddr]
72 return '[%08x] %s' % (iword, Rk_Python.dis(iword,0x0))
73
74
75#
76# show the latest executed instruction. If the execution is continuing at
77# the background, we may not get the pc & instrWord of the same execution,
78# because we access pc and instrWord in two function calls, so there is a
79# possibility that the values are not matched. In other case, if a va is
80# provided, we will need to translate that into pa, which can be tricky, as
81# the execution may be at a different state, which may affect the va->pa
82# translation.
83#
84def showi(sid=0,va=0):
85 """
86 sid: strand id, default is 0
87 """
88 # if va=0, use the instruction to be executed next, otherwise use the
89 # provided va to access the instruction word and disassemble it.
90 if va == 0:
91 instr = disassemble(sid, sim.s[sid].pc)
92 print 'sid=%d, pc=%#x, %s' % (sid, sim.s[sid].pc, instr)
93 else:
94 instr = disassemble(sid, va)
95 print 'sid=%d, pc=%#x, %s' % (sid, va, instr)
96
97#
98# if there are breakpoints set up by "break" command, hitting one of those
99# breakpoints will terminate runshow(), runbreak(), or runbreak2() function
100# and return control to UI prompt. The breakpoints list specified in runbreak()
101# or runbreak2() function will have the same effect on execution.
102#
103
104# execute instructions and display executed instructions along the way
105# e.g., "runshow(100,1)" will run 100 instructions on strand1 and display
106# every instruction executed.
107#
108def runshow(step=1,sid=0,fd=sys.stdout,sym=1):
109 """
110 step: number of instruction to be executed, default is 1
111 sid: strand id, default is 0
112 fd: write the output to a file descriptor, default to stdout
113 sym: show (PC) symbol if available
114
115 example:
116 sam>>> fd1=open('0-tmp','w')
117 sam>>> runshow(10,fd=fd1)
118 sam>>> runshow(100,fd=fd1)
119 sam>>> fd1.close()
120 """
121 global icount
122 global symbol_table
123 prevPC = 0x0L
124 newPC = 0x0L
125 prevTL = 0
126 newTL = 0
127 i = 0
128 done = 0
129 while (done == 0) and (i < step):
130 i += 1
131 icount += 1
132 newPC = sim.s[sid].pc
133 instr = disassemble(sid, newPC)
134 sam.ui_exec('stepi')
135 newTL = sim.s[sid].tl
136 # check for hitting breakpoint
137 for s in sim.s:
138 if s.brk.hit():
139 done = 1
140 break
141 if done == 0:
142 if (newPC != prevPC+4) or (newTL != prevTL):
143 # display PC or related symbol when PC moves to a different
144 # path
145 if (sym == 1) and (symbol_table != None):
146 fd.write('%s, TL=%d:\n' % (symbol_table.va2id(newPC), newTL))
147 else:
148 fd.write('PC=%#x, TL=%d:\n' % (newPC, newTL))
149 fd.write('sid=%d, ic=%d, pc=%#x, %s\n' % (sid, icount, newPC, instr))
150 prevPC = newPC
151 prevTL = newTL
152
153#
154# execute instructions and check for breakpoints along the way
155# e.g., runbreak(100,bpoints=[0x40070,0x40078,0x83400]) will run 100
156# instructions on strand0 and display every instruction executed, if PC has a
157# hit with any value in bpoints, then the execution will stop.
158#
159def runbreak(step=1,sid=0,bpoints=[0x83400,0xfffffffff0000080L,0x00122000],fd=sys.stdout,sym=1):
160 """
161 step: number of instruction to be executed, default is 1
162 sid: strand id, default is 0
163 bpoints: a list of PC breakpoints, default is empty list
164 fd: output file descriptor, default to stdout
165 sym: show (PC) symbol if available
166 """
167 global symbol_table
168 global icount
169 prevPC = 0x0L
170 newPC = 0x0L
171 prevTL = 0
172 newTL = 0
173 i = 0
174 done = 0
175 while (done == 0) and (i < step):
176 i += 1
177 icount += 1
178 newPC = sim.s[sid].pc
179 instr = disassemble(sid, newPC)
180 # check breakpoints
181 if newPC in bpoints:
182 if symbol_table != None:
183 fd.write('BREAKPOINT: sid=%d, pc=%#x [%s]\n' % (sid, newPC, symbol_table.va2id(newPC)))
184 else:
185 fd.write('BREAKPOINT: sid=%d, pc=%#x\n' % (sid, newPC))
186 done = 1
187 else:
188 # execute the next instr if no breakpoint is hit
189 sam.ui_exec('stepi')
190 newTL = sim.s[sid].tl
191 for s in sim.s:
192 if s.brk.hit():
193 done = 1
194 break
195 if done == 0:
196 if (newPC != prevPC+4) or (newTL != prevTL):
197 # display PC or related symbol when PC moves to a
198 # different path
199 if (sym == 1) and (symbol_table != None):
200 fd.write('%s, TL=%d:\n' % (symbol_table.va2id(newPC), newTL))
201 else:
202 fd.write('PC=%#x, TL=%d:\n' % (newPC, newTL))
203 fd.write('sid=%d, ic=%d, pc=%#x, %s\n' % (sid, icount, newPC, instr))
204 prevPC = newPC
205 prevTL = newTL
206
207#
208# execute instructions and check for breakpoints along the way
209# e.g., runbreak2(100,bpoints=[0x40070,0x40078,0x83400],size=50) will run
210# 100 instructions on strand0 and display every instruction executed, if PC
211# has a hit with any value in bpoints, then the execution will stop. The last
212# 'size' instructions will be kept in specified file.
213#
214def runbreak2(step=1,sid=0,bpoints=[0x83400,0xfffffffff0000080L,0x00122000],fd=sys.stdout,size=10000):
215 """
216 step: number of instruction to be executed, default is 1
217 sid: strand id, default is 0
218 bpoints: a list of PC breakpoints, default is empty list
219 fd: output file descriptor, default to stdout
220 size: instr buffer size, the last 'size' instructions before the breakpoint
221 will be written to fd
222
223 example:
224 sam>>> fd1=open('0-tmp','w')
225 sam>>> runbreak2(10,bpoints=[0x83400],fd=fd1,size=100)
226 sam>>> fd1.close()
227 """
228 global symbol_table
229 global icount
230 buffer = { }
231 index = 0
232 prevPC = 0x0L
233 newPC = 0x0L
234 prevTL = 0
235 newTL = 0
236 i = 0
237 done = 0
238 while (done == 0) and (i < step):
239 i += 1
240 icount += 1
241 newPC = sim.s[sid].pc
242 instr = disassemble(sid, newPC)
243 # check breakpoints
244 if newPC in bpoints:
245 bs = sim.s[sid]
246 done = 1
247 else:
248 # execute the next instr if no breakpoint is hit
249 sam.ui_exec('stepi')
250 for s in sim.s:
251 if s.brk.hit():
252 done = 1
253 bs = s
254 break
255 if done == 0:
256 index = (i-1) % size
257 buffer[index] = 'PC=%#x, %s' % (newPC, instr)
258 # dump out buffer if hit a breakpoint
259 if done == 1:
260 jj = 1
261 for ii in range(index+1, size):
262 if buffer.has_key(ii):
263 fd.write('sid=%d, ic=%d, %s\n' % (sid, jj, buffer[ii]))
264 jj += 1
265 for ii in range(0,index+1):
266 if buffer.has_key(ii):
267 fd.write('sid=%d, ic=%d, %s\n' % (sid, jj, buffer[ii]))
268 jj += 1
269 if symbol_table != None:
270 fd.write('BREAKPOINT: sid=%d, pc=%#x [%s]\n' % (bs.strand_id, bs.pc, symbol_table.va2id(bs.pc)))
271 else:
272 fd.write('BREAKPOINT: sid=%d, pc=%#x\n' % (bs.strand_id, bs.pc))
273
274#
275# check PASS/FAIL at the end of an execution, and return exit code
276# accordingly.
277#
278def runforever(insts=0x7fffffffffffffff,ss=None,bout=1,va_pass=[0x122000],va_fail=[0x122020]):
279 """
280 insts: number of instructions to run per strand, default is MAXINT
281 ss: array of strand-ids, e.g., [0,1,2]. default is None, means all strands
282 bout: upon hitting pass/fail, 1 means exit, 0 means returns to caller
283 va_pass: array of 'pass' VAs, default is 0x122000
284 va_fail: array of 'fail' VAs, default is 0x122020
285 """
286 strands = []
287 if ss == None:
288 # special case, step through all strands
289 for s in sim.s:
290 strands.append(s)
291 else:
292 # otherwise only step through specified strands
293 for sid in ss:
294 strands.append(sim.s[sid])
295 # set 'pass' breakpoints
296 bp_pass = {}
297 for s in strands:
298 bp_pass[s.strand_id] = []
299 for va in va_pass:
300 bp_pass[s.strand_id].append(s.brk.on_inst_va(va))
301 # set 'fail' breakpoints
302 bp_fail = {}
303 for s in strands:
304 bp_fail[s.strand_id] = []
305 for va in va_fail:
306 bp_fail[s.strand_id].append(s.brk.on_inst_va(va))
307 # step through strands
308 sam.ui_exec('stepi %d' % insts)
309 # check for pass/fail breakpoint
310 for s in strands:
311 bp = s.brk.hit()
312 if bp:
313 if bp[0] in bp_pass[s.strand_id]:
314 if bout:
315 sys.exit(0)
316 else:
317 return 0
318 elif bp[0] in bp_fail[s.strand_id]:
319 if bout:
320 sys.exit(1)
321 else:
322 return 1
323 # if nothing hit, consider it is good
324 if bout:
325 sys.exit(0)
326 else:
327 return 0
328
329#
330# display the PC of all strands
331#
332def allpc():
333 for s in sim.s:
334 print 'T%d: PC=%#x' % (s.strand_id, s.pc)
335
336###############################################################################
337### SAM UI workaround. Use old commands prefixed with python
338###############################################################################
339
340def python(*args):
341 try:
342 exec(" ".join(args[1:]))
343 except:
344 print "ERROR: command is/went wrong"
345
346sam.ui_register('python','python SAM UI fixer',python)
347
348###############################################################################
349### python memory debugging, for developers' internal use.
350###############################################################################
351
352import gc
353
354def gc_dbx_on():
355 """
356 """
357 gc.enable()
358 gc.set_debug(gc.DEBUG_LEAK|gc.DEBUG_STATS)
359
360def gc_dbx_off():
361 """
362 """
363 gc.set_debug(0x0)
364
365def gc_dump():
366 """
367 """
368 gc.collect()
369 print '\nGARBAGE OBJECTS:'
370 for x in gc.garbage:
371 xx = str(x)
372 if len(xx) > 80:
373 xx = xx[:77]+'...'
374 print '%s ---> %s' % (type(x), xx)
375
376