Initial commit of OpenSPARC T2 design and verification files.
[OpenSPARC-T2-DV] / tools / src / nas,5.n2.os.2 / pfe / SS_Strand.py
CommitLineData
86530b38
AT
1
2import re
3freg=re.compile('^f[0-9]$|^f[1-5][0-9]$|^f6[0-3]$')
4greg = re.compile('^g[0-7]$')
5wreg = re.compile('^[ilo][0-7]$')
6
7import Pfe_Strand
8import Pfe_Tlb
9
10from SS_Break import *
11
12
13class AsiStateError(Exception):
14 def __init__(self,asi,va):
15 Exception.__init__(self)
16 self.asi = asi
17 self.va = va
18
19 def __str__(self):
20 return "The strand has no mapping for: asi="+hex(self.asi)+" va="+hex(self.va)
21
22
23class AsiState:
24 def __init__(self,asi,va):
25 self.asi = asi
26 self.va = va
27
28 def get(self,strand):
29 data = strand.get_asi(self.asi,self.va)
30 if strand.asi_error != 0:
31 raise AsiStateError(self.asi,self.va)
32 return data
33
34 def set(self,strand,data):
35 strand.set_asi(self.asi,self.va,data)
36 if strand.asi_error != 0:
37 raise AsiStateError(self.asi,self.va)
38
39
40
41def __getreg__(index):
42 return lambda strand: strand.get_reg(index)
43
44def __setreg__(index):
45 return lambda strand,value: strand.set_reg(index,value)
46
47def __getreg_tl__(index):
48 return lambda strand,tl: strand.get_reg_tl(tl,index)
49
50def __setreg_tl__(index):
51 return lambda strand,tl,value: strand.set_reg_tl(tl,index,value)
52
53def __getreg_gl__(index):
54 return lambda strand,gl: strand.get_reg_gl(gl,index)
55
56def __setreg_gl__(index):
57 return lambda strand,gl,value: strand.set_reg_gl(gl,index,value)
58
59def __getreg_wp__(index):
60 return lambda strand,wp: strand.get_reg_wp(wp,index)
61
62def __setreg_wp__(index):
63 return lambda strand,wp,value: strand.set_reg_wp(wp,index,value)
64
65# Good old Python is a little sick. The Py_BuildValue api routine
66# does not treat uint64_t as unsigned and converts the unsigned value
67# to an signed value. The abs64 function below fixes this problem.
68# Currently the onlu code using By_BuildValue with K format is SS_PythonTracer
69
70def abs64(x):
71 if x < 0:
72 return 0x10000000000000000 + x
73 return x;
74
75
76class Tracer:
77 def __init__(self,strand,tracer):
78 self.strand = strand
79 self.__vonk__ = strand.__vonk__
80 self.__tracer__ = tracer
81 self.opt_exe_instr = False
82 self.opt_reg_value = False
83 self.opt_trap = False
84 self.opt_mem_access = 0
85 self.opt_tlb_update = 0
86 self.state = {}
87 self.trc_connected = False
88 # instruction count
89 self.icount = 0
90 # output in n2 sas.log format
91 self.n2_format = False
92
93 def set_format(self,format=None):
94 if format == None:
95 return self.n2_format
96 elif type(format) == bool:
97 self.n2_format = format
98 else:
99 raise TypeError
100
101 def set_tracer(self):
102 if self.opt_exe_instr or self.opt_reg_value or self.opt_trap or self.opt_mem_access or self.opt_tlb_update:
103 if not self.trc_connected:
104 self.strand.__strand__.add_tracer(self.__tracer__)
105 self.trc_connected = True
106 else:
107 if self.trc_connected:
108 self.strand.__strand__.del_tracer(self.__tracer__)
109 self.trc_connected = False
110
111 def exe_instr(self,on=None):
112 if on == None:
113 return self.opt_exe_instr
114 elif type(on) == bool:
115 self.opt_exe_instr = on
116 if on:
117 if not self.n2_format:
118 self.__tracer__.set_exe_instr(self.trc_exe_instr)
119 else:
120 self.__tracer__.set_exe_instr(self.trc_exe_instr_n2)
121 else:
122 self.__tracer__.clr_exe_instr()
123 else:
124 raise TypeError
125 self.set_tracer()
126
127 def trc_exe_instr(self,pc,tte,i):
128 pc = abs64(pc)
129 opc = self.__vonk__.ss_instr(i).get_opc() & 0xffffffffL
130 pa = self.__vonk__.ss_tte(tte).trans(pc)
131 self.icount += 1
132 str = self.__vonk__.dis(opc,pc)
133 print "%d:" % self.strand.strand_id,pc,':',pa,"[0x%08x] %s" % (opc,str)
134
135
136 def trc_exe_instr_n2(self,pc,tte,i):
137 """
138 N2 cosim sas.log format
139 """
140 # the function is embedded in SS_PliSocket.cc so that we have consistent
141 # content in sas.log and vcs.log
142 return
143
144
145 def reg_value(self,on=None):
146 if on == None:
147 return self.opt_reg_value
148 elif type(on) == bool:
149 self.opt_reg_value = on
150 if on:
151 if not self.n2_format:
152 self.__tracer__.set_reg_value(self.trc_reg_value)
153 else:
154 self.__tracer__.set_reg_value(self.trc_reg_value_n2)
155 else:
156 self.__tracer__.clr_reg_value()
157 else:
158 raise TypeError
159 self.set_tracer()
160
161
162 def trc_reg_value(self,index,value):
163 if index >= self.__vonk__.SS_Registers.ALIAS_END:
164 return
165 value = abs64(value)
166 reg = self.strand.__vonk__.SS_Registers.get_alias_name(index)
167 if reg == 'asi_reg':
168 reg = 'asi'
169 if self.state.has_key(index):
170 print "%d:\t%s:" % (self.strand.strand_id,reg),self.state[index],"->",value
171 else:
172 print "%d:\t%s: None ->" % (self.strand.strand_id,reg),value
173 self.state[index] = value
174
175
176 def trc_reg_value_n2(self,index,value):
177 """
178 N2 cosim sas.log format
179 """
180 # the function is embedded in SS_PliSocket.cc so that we have consistent
181 # content in sas.log and vcs.log
182 return
183
184
185 def trap(self,on=None):
186 if on == None:
187 return self.opt_trap
188 elif type(on) == bool:
189 self.opt_trap = on
190 if on:
191 self.__tracer__.set_trap(self.trc_trap)
192 else:
193 self.__tracer__.clr_trap()
194 else:
195 raise TypeError
196 self.set_tracer()
197
198 def trc_trap(self,type,mode,addr):
199 addr = abs64(addr)
200 if mode == self.__tracer__.TRAP:
201 print "%d: 0x%x trap: 0x%x" % (self.strand.strand_id,self.strand.pc,type)
202 elif mode == self.__tracer__.INST_TRAP:
203 print "%d: 0x%x trap: 0x%x inst mmu pc=0x%x" % (self.strand.strand_id,self.strand.pc,type,addr)
204 elif mode == self.__tracer__.DATA_TRAP:
205 print "%d: 0x%x trap: 0x%x data mmu ea=0x%x" % (self.strand.strand_id,self.strand.pc,type,addr)
206
207
208 MEM_CODE = 1
209 MEM_DATA = 2
210
211 def mem_access(self,on=None):
212 if on == None:
213 return self.opt_mem_access
214 elif type(on) == bool:
215 self.opt_mem_access = self.MEM_CODE | self.MEM_DATA
216 elif type(on) == int:
217 self.opt_mem_access = on
218 else:
219 raise TypeError
220 if (self.opt_mem_access & (self.MEM_CODE | self.MEM_DATA)) != 0:
221 self.__tracer__.set_mem_access(self.trc_mem_access)
222 else:
223 self.__tracer__.clr_mem_access()
224 self.set_tracer()
225
226 def trc_mem_access(self,type,va,tte,size,data):
227 va = abs64(va)
228 for i in len(data):
229 data[i] = abs64(data[i])
230
231 pa = self.__vonk__.ss_tte(tte).trans(va)
232 if type == self.__tracer__.LD_CODE:
233 if (self.opt_mem_access & self.MEM_CODE) == 0:
234 return
235 op = 'fetch'
236 elif (self.opt_mem_access & self.MEM_DATA) == 0:
237 return
238 elif type == self.__tracer__.LD_DATA:
239 op = 'ld'
240 elif type == self.__tracer__.ST_DATA:
241 op = 'st'
242 elif type == self.__tracer__.ST_PART:
243 op = 'st-partial'
244 elif type == self.__tracer__.ST_SWAP:
245 op = 'st-swap'
246 elif type == self.__tracer__.LD_SWAP:
247 op = 'ld-swap'
248 elif type == self.__tracer__.ST_CAS:
249 op = 'st-cas'
250 elif type == self.__tracer__.LD_CAS:
251 op = 'ld-cas'
252 elif type == self.__tracer__.ST_LDST:
253 op = 'st-ldst'
254 elif type == self.__tracer__.LD_LDST:
255 op = 'ld-ldst'
256 # ToDo need unsigned python function
257 print '%d: 0x%016x : 0x%015x %s%d' % (self.strand.strand_id,va,pa,op,size),data
258
259
260 TLB_INSERT = 1
261 TLB_REMOVE = 2
262
263 def tlb_update(self,on=None):
264 """
265 0 - tlb update traceing disable
266 1 - tlb insert traceing enable
267 2 - tlb remove traceing enable
268 3 - tlb update traceing enable
269 """
270 if on == None:
271 return self.opt_tlb_update
272 elif type(on) == bool:
273 self.opt_tlb_update = self.TLB_INSERT | self.TLB_REMOVE
274 elif type(on) == int:
275 self.opt_tlb_update = on
276 else:
277 raise TypeError
278 if (self.opt_tlb_update & (self.TLB_INSERT | self.TLB_REMOVE)) != 0:
279 self.__tracer__.set_tlb_update(self.trc_tlb_update)
280 else:
281 self.__tracer__.clr_tlb_update()
282 self.set_tracer()
283
284 def trc_tlb__fun__(self,tte):
285 return tte
286
287 def trc_tlb_update(self,insert,tlb,index,tte):
288 tte = Pfe_Tlb.TlbTte(None,self.trc_tlb__fun__,self.__vonk__.ss_tte(tte))
289 ss_tlb = self.__vonk__.ss_tlb(tlb)
290
291 if not ss_tlb.is_inst_tlb():
292 type = 'tlb.d%02x' % ss_tlb.tlb_id()
293 elif not ss_tlb.is_data_tlb():
294 type = 'tlb.i%02x' % ss_tlb.tlb_id()
295 else:
296 type = 'tlb.u%02x' % ss_tlb.tlb_id()
297
298 if insert == 1:
299 if (self.opt_tlb_update & self.TLB_INSERT) != 0:
300 print "%s: insert %03x: %s" % (type,index,str(tte))
301 else:
302 if (self.opt_tlb_update & self.TLB_REMOVE) != 0:
303 print "%s: remove %03x: %s" % (type,index,str(tte))
304
305
306class Strand(Pfe_Strand.Strand):
307 __first_strand__ = True
308
309 def __init__(self,strand,ref,vonk):
310 Pfe_Strand.Strand.__init__(self,strand,ref)
311 self.__dict__['__asierr__'] = vonk.SS_AsiSpace
312 self.__dict__['__vonk__'] = vonk
313 self.brk = BreakDict(strand,vonk)
314 self.__dict__['trc'] = Tracer(self,vonk.SS_PythonTracer())
315
316 if Strand.__first_strand__:
317 Strand.__first_strand__ = False
318
319 __getfun__ = Pfe_Strand.Strand.__getfun__
320 __setfun__ = Pfe_Strand.Strand.__setfun__
321
322 for index in range(vonk.SS_Registers.INDEX_BEGIN,vonk.SS_Registers.INDEX_END):
323 name = vonk.SS_Registers.get_name(index)
324 __getfun__[name] = __getreg__(index)
325 __setfun__[name] = __setreg__(index)
326
327 alias = strand.get_state_name(index)
328 if alias == "asi_reg":
329 alias = "asi"
330 if alias != 0:
331 __getfun__[alias] = __getreg__(index)
332 __setfun__[alias] = __setreg__(index)
333
334 for index in range(vonk.SS_Registers.ALIAS_BEGIN,vonk.SS_Registers.ALIAS_END):
335 name = vonk.SS_Registers.get_name(index)
336 __getfun__[name] = __getreg__(index)
337 __setfun__[name] = __setreg__(index)
338
339 for name in __asi_va__:
340 __getfun__[name] = __asi_va__[name].get
341 __setfun__[name] = __asi_va__[name].set
342
343 for i,g in enumerate(Pfe_Strand.Strand.__irf__[:8]):
344 Pfe_Strand.GlobalStack.__getfun__[g] = __getreg_gl__(i)
345 Pfe_Strand.GlobalStack.__getfun__[i] = __getreg_gl__(i)
346 Pfe_Strand.GlobalStack.__setfun__[g] = __setreg_gl__(i)
347 Pfe_Strand.GlobalStack.__setfun__[i] = __setreg_gl__(i)
348
349 for i,w in enumerate(Pfe_Strand.Strand.__irf__[8:]):
350 Pfe_Strand.WindowStack.__getfun__[w] = __getreg_wp__(i+8)
351 Pfe_Strand.WindowStack.__getfun__[i+8] = __getreg_wp__(i+8)
352 Pfe_Strand.WindowStack.__setfun__[w] = __setreg_wp__(i+8)
353 Pfe_Strand.WindowStack.__setfun__[i+8] = __setreg_wp__(i+8)
354
355 Pfe_Strand.TrapStack.__getfun__['tt'] = __getreg_tl__(vonk.SS_Registers.PR_TT)
356 Pfe_Strand.TrapStack.__setfun__['tt'] = __setreg_tl__(vonk.SS_Registers.PR_TT)
357 Pfe_Strand.TrapStack.__getfun__['tpc'] = __getreg_tl__(vonk.SS_Registers.PR_TPC)
358 Pfe_Strand.TrapStack.__setfun__['tpc'] = __setreg_tl__(vonk.SS_Registers.PR_TPC)
359 Pfe_Strand.TrapStack.__getfun__['tnpc'] = __getreg_tl__(vonk.SS_Registers.PR_TNPC)
360 Pfe_Strand.TrapStack.__setfun__['tnpc'] = __setreg_tl__(vonk.SS_Registers.PR_TNPC)
361 Pfe_Strand.TrapStack.__getfun__['tstate'] = __getreg_tl__(vonk.SS_Registers.PR_TSTATE)
362 Pfe_Strand.TrapStack.__setfun__['tstate'] = __setreg_tl__(vonk.SS_Registers.PR_TSTATE)
363 Pfe_Strand.TrapStack.__getfun__['htstate'] = __getreg_tl__(vonk.SS_Registers.HPR_HTSTATE)
364 Pfe_Strand.TrapStack.__setfun__['htstate'] = __setreg_tl__(vonk.SS_Registers.HPR_HTSTATE)
365
366 # default step attribute
367 self.step = self.__runstep__
368 self.__listing__ = 0
369 self.trc.exe_instr(False)
370 self.trc.reg_value(False)
371 self.trc.trap(False)
372
373 def rdasi(self,asi,va):
374 data = self.__strand__.get_asi(asi,va)
375 if self.__strand__.asi_error != self.__asierr__.OK:
376 raise AsiStateError(asi,va)
377 return data
378
379 def wrasi(self,asi,va,data):
380 self.__strand__.set_asi(asi,va,data)
381 if self.__strand__.asi_error != self.__asierr__.OK:
382 raise AsiStateError(asi,va)
383
384 def set_format(self,format=None):
385 if format == None:
386 return self.trc.set_format(format)
387 else:
388 self.trc.set_format(format)
389
390 def lstmode(self,on=None):
391 if on == None:
392 return Pfe_Strand.Strand.lstmode(self,on)
393 else:
394 Pfe_Strand.Strand.lstmode(self,on)
395 if on == 1:
396 self.trc.exe_instr(False)
397 self.trc.reg_value(False)
398 self.trc.trap(True)
399 elif on == 2:
400 self.trc.exe_instr(True)
401 self.trc.reg_value(False)
402 self.trc.trap(True)
403 elif on == 3:
404 self.trc.exe_instr(True)
405 self.trc.reg_value(True)
406 self.trc.trap(True)
407 elif on in [91,92,93,94]:
408 # on = -sas_run_args=-DPLI_DEBUG + 90
409 # set by cosim -sas_run_args=-DPLI_DEBUG option, in this case the
410 # instr & delta are handled in backend, not at pfe layer.
411 self.trc.exe_instr(False)
412 self.trc.reg_value(False)
413 self.trc.trap(True)
414 else:
415 self.trc.exe_instr(False)
416 self.trc.reg_value(False)
417 self.trc.trap(False)
418
419 def __runstep__(self,n=None):
420 if n == None:
421 n = 1
422 n = self.__strand__.run_step(n)
423 if n:
424 id = self.brk.hit_id()
425 if id == None:
426 pass # flush break loop for flush broadcast sync
427 elif self.brk.callback[id] == None:
428 print self.ref+': Stopped at pc='+hex(self.pc)+': '+str(self.brk.hit_bp())
429 else:
430 self.brk.callback[id](self)
431 return n
432 return 0
433
434 def __lststep__(self,n=None):
435 if n == None:
436 n = 1
437 while n > 0:
438 n = self.__strand__.trc_step(n)
439 if n:
440 id = self.brk.hit_id()
441 if id == None:
442 pass # flush break loop for flush broadcast sync
443 elif self.brk.callback[id] == None:
444 print self.ref+': Stopped at pc='+hex(self.pc)+': '+str(self.brk.hit_bp())
445 else:
446 self.brk.callback[id](self)
447 return n
448 return 0
449
450 def va2pa(self,va,ctx=None,pid=None):
451 if ctx == None:
452 return self.__strand__.va2pa(va)
453 elif pid == None:
454 return self.__strand__.va2pa(va,ctx)
455 else:
456 return self.__strand__.va2pa(va,ctx,pid)
457
458 def ra2pa(self,ra,pid=None):
459 if pid == None:
460 return self.__strand__.ra2pa(ra)
461 else:
462 return self.__strand__.ra2pa(ra,pid)
463
464 def icache_info(self,pa):
465 print self.__strand__.icache_info(pa)
466 return 0
467
468 def icache_set(self,set):
469 print self.__strand__.icache_set(set)
470 return 0
471
472 def dcache_set(self,set):
473 print self.__strand__.dcache_set(set)
474 return 0
475
476 def l2cache_set(self,set):
477 print self.__strand__.l2cache_set(set)
478 return 0
479