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