Commit | Line | Data |
---|---|---|
86530b38 AT |
1 | # |
2 | # A collection of functions that help display executed instructions and | |
3 | # collect informaiton leading to a specified breakpoint. | |
4 | # Use execfile('RunScript.py') to load this module into samfe python | |
5 | # environment. This script is valid only when the samfe is in python mode, | |
6 | # it cannot be used in line-oriented command mode. When in line-oriented | |
7 | # command mode, use 'pym' command to enter python mode. Use 'pym_off()' in | |
8 | # python mode to switch back to line-oriented command mode. | |
9 | # | |
10 | ||
11 | # available functions: | |
12 | # showi() | |
13 | # runshow() | |
14 | # runbreak() | |
15 | # runbreak2() | |
16 | # runforever() | |
17 | # allpc() | |
18 | ||
19 | print 'loading RunScript...' | |
20 | ||
21 | import os, sys | |
22 | import sam | |
23 | ||
24 | # change this as needed | |
25 | try: | |
26 | import Rk_Python as pyobj | |
27 | except: | |
28 | print 'need to import proper XX_Python module' | |
29 | sys.exit(1) | |
30 | ||
31 | symFile = 'symbol.tbl' | |
32 | symTable = None | |
33 | if os.path.exists(symFile): | |
34 | try: | |
35 | import SymbolTableNi | |
36 | symTable = SymbolTableNi.SymbolTableNi() | |
37 | symTable.load(symFile) | |
38 | except: | |
39 | symTable = None | |
40 | ||
41 | # global instruction count | |
42 | icount = 0L | |
43 | ||
44 | # | |
45 | # show the latest executed instruction. If the execution is continuing at | |
46 | # the background, we may not get the pc & instrWord of the same execution, | |
47 | # because we access pc and instrWord in two function calls, so there is a | |
48 | # possibility that the values are not matched. In other case, if a va is | |
49 | # provided, we will need to translate that into pa, which can be tricky, as | |
50 | # the execution may be at a different state, which may affect the va->pa | |
51 | # translation. | |
52 | # | |
53 | def showi(sid=0,va=0): | |
54 | """ | |
55 | sid: strand id, default is 0 | |
56 | """ | |
57 | global pyobj | |
58 | # if va=0, use the instruction to be executed next, otherwise use the | |
59 | # provided va to access the instruction word and disassemble it. | |
60 | if va == 0: | |
61 | (len,instr,type) = RS_disassemblePC(sid, pyobj) | |
62 | print 'sid=%d, pc=%#x, %s' % (sid, sim.s[sid].pc, instr) | |
63 | else: | |
64 | (len,instr,type) = RS_disassemble(sid, va, 2, pyobj) | |
65 | print 'sid=%d, pc=%#x, %s' % (sid, va, instr) | |
66 | ||
67 | # | |
68 | # if there are breakpoints set up by "break" command, hitting one of those | |
69 | # breakpoints will terminate runshow(), runbreak(), or runbreak2() function | |
70 | # and return control to UI prompt. The breakpoints list specified in runbreak() | |
71 | # or runbreak2() function will have the same effect on execution. | |
72 | # | |
73 | ||
74 | # execute instructions and display executed instructions along the way | |
75 | # e.g., "runshow(100,1)" will run 100 instructions on strand1 and display | |
76 | # every instruction executed. | |
77 | # | |
78 | def runshow(step=1,sid=0,fd=sys.stdout,sym=1): | |
79 | """ | |
80 | step: number of instruction to be executed, default is 1 | |
81 | sid: strand id, default is 0 | |
82 | fd: write the output to a file descriptor, default to stdout | |
83 | sym: show (PC) symbol if available | |
84 | ||
85 | example: | |
86 | sam>>> fd1=open('0-tmp','w') | |
87 | sam>>> runshow(10,fd=fd1) | |
88 | sam>>> runshow(100,fd=fd1) | |
89 | sam>>> fd1.close() | |
90 | """ | |
91 | global pyobj | |
92 | global icount | |
93 | global symTable | |
94 | prevPC = 0x0L | |
95 | newPC = 0x0L | |
96 | prevTL = 0 | |
97 | newTL = 0 | |
98 | i = 0 | |
99 | done = 0 | |
100 | while (done == 0) and (i < step): | |
101 | i += 1 | |
102 | icount += 1 | |
103 | newPC = sim.s[sid].pc | |
104 | (len,instr,type) = RS_disassemblePC(sid, pyobj) | |
105 | sam.ui_exec('stepi') | |
106 | newTL = sim.s[sid].tl | |
107 | # check for hitting breakpoint | |
108 | for s in sim.s: | |
109 | if s.brk.hit(): | |
110 | done = 1 | |
111 | break | |
112 | if done == 0: | |
113 | if (newPC != prevPC+4) or (newTL != prevTL): | |
114 | # display PC or related symbol when PC moves to a different | |
115 | # path | |
116 | if (sym == 1) and (symTable != None): | |
117 | fd.write('%s, TL=%d:\n' % (symTable.va2symbol(newPC), newTL)) | |
118 | else: | |
119 | fd.write('PC=%#x, TL=%d:\n' % (newPC, newTL)) | |
120 | fd.write('sid=%d, ic=%d, pc=%#x, %s\n' % (sid, icount, newPC, instr)) | |
121 | prevPC = newPC | |
122 | prevTL = newTL | |
123 | ||
124 | # | |
125 | # execute instructions and check for breakpoints along the way | |
126 | # e.g., runbreak(100,bpoints=[0x40070,0x40078,0x83400]) will run 100 | |
127 | # instructions on strand0 and display every instruction executed, if PC has a | |
128 | # hit with any value in bpoints, then the execution will stop. | |
129 | # | |
130 | def runbreak(step=1,sid=0,bpoints=[0x83400,0xfffffffff0000080L,0x00122000],fd=sys.stdout,sym=1): | |
131 | """ | |
132 | step: number of instruction to be executed, default is 1 | |
133 | sid: strand id, default is 0 | |
134 | bpoints: a list of PC breakpoints, default is empty list | |
135 | fd: output file descriptor, default to stdout | |
136 | sym: show (PC) symbol if available | |
137 | """ | |
138 | global pyobj | |
139 | global symTable | |
140 | global icount | |
141 | prevPC = 0x0L | |
142 | newPC = 0x0L | |
143 | prevTL = 0 | |
144 | newTL = 0 | |
145 | i = 0 | |
146 | done = 0 | |
147 | while (done == 0) and (i < step): | |
148 | i += 1 | |
149 | icount += 1 | |
150 | newPC = sim.s[sid].pc | |
151 | (len,instr,type) = RS_disassemblePC(sid, pyobj) | |
152 | # check breakpoints | |
153 | if newPC in bpoints: | |
154 | if symTable != None: | |
155 | fd.write('BREAKPOINT: sid=%d, pc=%#x [%s]\n' % (sid, newPC, symTable.va2symbol(newPC))) | |
156 | else: | |
157 | fd.write('BREAKPOINT: sid=%d, pc=%#x\n' % (sid, newPC)) | |
158 | done = 1 | |
159 | else: | |
160 | # execute the next instr if no breakpoint is hit | |
161 | sam.ui_exec('stepi') | |
162 | newTL = sim.s[sid].tl | |
163 | for s in sim.s: | |
164 | if s.brk.hit(): | |
165 | done = 1 | |
166 | break | |
167 | if done == 0: | |
168 | if (newPC != prevPC+4) or (newTL != prevTL): | |
169 | # display PC or related symbol when PC moves to a | |
170 | # different path | |
171 | if (sym == 1) and (symTable != None): | |
172 | fd.write('%s, TL=%d:\n' % (symTable.va2symbol(newPC), newTL)) | |
173 | else: | |
174 | fd.write('PC=%#x, TL=%d:\n' % (newPC, newTL)) | |
175 | fd.write('sid=%d, ic=%d, pc=%#x, %s\n' % (sid, icount, newPC, instr)) | |
176 | prevPC = newPC | |
177 | prevTL = newTL | |
178 | ||
179 | # | |
180 | # execute instructions and check for breakpoints along the way | |
181 | # e.g., runbreak2(100,bpoints=[0x40070,0x40078,0x83400],size=50) will run | |
182 | # 100 instructions on strand0 and display every instruction executed, if PC | |
183 | # has a hit with any value in bpoints, then the execution will stop. The last | |
184 | # 'size' instructions will be kept in specified file. | |
185 | # | |
186 | def runbreak2(step=1,sid=0,bpoints=[0x83400,0xfffffffff0000080L,0x00122000],fd=sys.stdout,size=10000): | |
187 | """ | |
188 | step: number of instruction to be executed, default is 1 | |
189 | sid: strand id, default is 0 | |
190 | bpoints: a list of PC breakpoints, default is empty list | |
191 | fd: output file descriptor, default to stdout | |
192 | size: instr buffer size, the last 'size' instructions before the breakpoint | |
193 | will be written to fd | |
194 | ||
195 | example: | |
196 | sam>>> fd1=open('0-tmp','w') | |
197 | sam>>> runbreak2(10,bpoints=[0x83400],fd=fd1,size=100) | |
198 | sam>>> fd1.close() | |
199 | """ | |
200 | global pyobj | |
201 | global symTable | |
202 | global icount | |
203 | buffer = { } | |
204 | index = 0 | |
205 | prevPC = 0x0L | |
206 | newPC = 0x0L | |
207 | prevTL = 0 | |
208 | newTL = 0 | |
209 | i = 0 | |
210 | done = 0 | |
211 | while (done == 0) and (i < step): | |
212 | i += 1 | |
213 | icount += 1 | |
214 | newPC = sim.s[sid].pc | |
215 | (len,instr,type) = RS_disassemblePC(sid, pyobj) | |
216 | # check breakpoints | |
217 | if newPC in bpoints: | |
218 | bs = sim.s[sid] | |
219 | done = 1 | |
220 | else: | |
221 | # execute the next instr if no breakpoint is hit | |
222 | sam.ui_exec('stepi') | |
223 | for s in sim.s: | |
224 | if s.brk.hit(): | |
225 | done = 1 | |
226 | bs = s | |
227 | break | |
228 | if done == 0: | |
229 | index = (i-1) % size | |
230 | buffer[index] = 'PC=%#x, %s' % (newPC, instr) | |
231 | # dump out buffer if hit a breakpoint | |
232 | if done == 1: | |
233 | jj = 1 | |
234 | for ii in range(index+1, size): | |
235 | if buffer.has_key(ii): | |
236 | fd.write('sid=%d, ic=%d, %s\n' % (sid, jj, buffer[ii])) | |
237 | jj += 1 | |
238 | for ii in range(0,index+1): | |
239 | if buffer.has_key(ii): | |
240 | fd.write('sid=%d, ic=%d, %s\n' % (sid, jj, buffer[ii])) | |
241 | jj += 1 | |
242 | if symTable != None: | |
243 | fd.write('BREAKPOINT: sid=%d, pc=%#x [%s]\n' % (bs.strand_id, bs.pc, symTable.va2symbol(bs.pc))) | |
244 | else: | |
245 | fd.write('BREAKPOINT: sid=%d, pc=%#x\n' % (bs.strand_id, bs.pc)) | |
246 | ||
247 | # | |
248 | # check PASS/FAIL at the end of an execution, and return exit code | |
249 | # accordingly. | |
250 | # | |
251 | def runforever(insts=0x7fffffffffffffff,ss=None,bout=1,va_pass=[0x122000],va_fail=[0x122020]): | |
252 | """ | |
253 | insts: number of instructions to run per strand, default is MAXINT | |
254 | ss: array of strand-ids, e.g., [0,1,2]. default is None, means all strands | |
255 | bout: upon hitting pass/fail, 1 means exit, 0 means returns to caller | |
256 | va_pass: array of 'pass' VAs, default is 0x122000 | |
257 | va_fail: array of 'fail' VAs, default is 0x122020 | |
258 | """ | |
259 | strands = [] | |
260 | if ss == None: | |
261 | # special case, step through all strands | |
262 | for s in sim.s: | |
263 | strands.append(s) | |
264 | else: | |
265 | # otherwise only step through specified strands | |
266 | for sid in ss: | |
267 | strands.append(sim.s[sid]) | |
268 | # set 'pass' breakpoints | |
269 | bp_pass = {} | |
270 | for s in strands: | |
271 | bp_pass[s.strand_id] = [] | |
272 | for va in va_pass: | |
273 | bp_pass[s.strand_id].append(s.brk.on_inst_va(va)) | |
274 | # set 'fail' breakpoints | |
275 | bp_fail = {} | |
276 | for s in strands: | |
277 | bp_fail[s.strand_id] = [] | |
278 | for va in va_fail: | |
279 | bp_fail[s.strand_id].append(s.brk.on_inst_va(va)) | |
280 | # step through strands | |
281 | sam.ui_exec('stepi %d' % insts) | |
282 | # check for pass/fail breakpoint | |
283 | for s in strands: | |
284 | bp = s.brk.hit() | |
285 | if bp: | |
286 | if bp[0] in bp_pass[s.strand_id]: | |
287 | if bout: | |
288 | sys.exit(0) | |
289 | else: | |
290 | return 0 | |
291 | elif bp[0] in bp_fail[s.strand_id]: | |
292 | if bout: | |
293 | sys.exit(1) | |
294 | else: | |
295 | return 1 | |
296 | # if nothing hit, consider it is good | |
297 | if bout: | |
298 | sys.exit(0) | |
299 | else: | |
300 | return 0 | |
301 | ||
302 | # | |
303 | # display the PC of all strands | |
304 | # | |
305 | def allpc(): | |
306 | for s in sim.s: | |
307 | print 'T%d: PC=%#x' % (s.strand_id, s.pc) | |
308 | ||
309 | ||
310 | ############################################################################### | |
311 | ### python memory debugging, for developers' internal use. | |
312 | ############################################################################### | |
313 | ||
314 | import gc | |
315 | ||
316 | def gc_dbx_on(): | |
317 | """ | |
318 | """ | |
319 | gc.enable() | |
320 | gc.set_debug(gc.DEBUG_LEAK|gc.DEBUG_STATS) | |
321 | ||
322 | def gc_dbx_off(): | |
323 | """ | |
324 | """ | |
325 | gc.set_debug(0x0) | |
326 | ||
327 | def gc_dump(): | |
328 | """ | |
329 | """ | |
330 | gc.collect() | |
331 | print '\nGARBAGE OBJECTS:' | |
332 | for x in gc.garbage: | |
333 | xx = str(x) | |
334 | if len(xx) > 80: | |
335 | xx = xx[:77]+'...' | |
336 | print '%s ---> %s' % (type(x), xx) |