import string, sys class Trace: def __init__(self, name, type, width): self.name = name self.type = type self.width = width self.lastvalue = 0 self.lasttime = -0.1 self.events = [] def addEvent(self, t, value): assert(t>=self.lasttime) if value!=self.lastvalue: if t==self.lasttime: self.events[-1] = (t, value) else: self.events.append((t, value)) self.lasttime = t self.lastvalue = value def writeSignal(self, fp, parent=""): t = self fp.write('SIGNAL("%s")\n'%(t.name)) fp.write('{\n') fp.write(' VALUE_TYPE = NINE_LEVEL_BIT;\n') if t.width==1: fp.write(' SIGNAL_TYPE = SINGLE_BIT;\n') else: fp.write(' SIGNAL_TYPE = BUS;\n') fp.write(' WIDTH = %d;\n'%(t.width)) if t.width==1: fp.write(' LSB_INDEX = -1;\n') else: fp.write(' LSB_INDEX = 0;\n') if t.type=='i' or t.type=='I': fp.write(' DIRECTION = INPUT;\n') elif t.type=='o' or t.type=='O': fp.write(' DIRECTION = OUTPUT;\n') elif t.type=='b' or t.type=='B': fp.write(' DIRECTION = BIDIR;\n') elif t.type=='r' or t.type=='R': fp.write(' DIRECTION = REGISTERED;\n') else: assert(0) fp.write(' PARENT = "%s";\n'%(parent)) fp.write('}\n\n') if t.width>1: for i in range(t.width): tt = Trace("%s[%d]"%(t.name, t.width-1-i), t.type, 1) tt.writeSignal(fp, t.name) def levels(self, tend, bit=-1): l = [] tlast = 0.0 vlast = 0 for t, value in self.events: if bit>=0 and value!=None: value = value>>bit & 1 dt = t-tlast if t>0: l.append((dt, vlast)) tlast = t vlast = value if tend>tlast: dt = tend-tlast l.append(dt, vlast) return l def writeTrans(self, fp, tend, bit=-1): t = self if t.width>1 and bit==-1: for i in range(t.width): t.writeTrans(fp, tend, t.width-1-i) return if t.width>1: name = "%s[%d]"%(t.name, bit) else: name = t.name levels = self.levels(tend, bit) bit = 0 fp.write('TRANSITION_LIST("%s")\n'%(name)) fp.write('{\n') fp.write(' NODE\n') fp.write(' {\n') fp.write(' REPEAT = 1;\n') for dt,v in levels: if v==None: fp.write(" LEVEL Z FOR %f;\n"%(dt)) else: fp.write(" LEVEL %d FOR %f;\n"%(v, dt)) fp.write(' }\n') fp.write('}\n\n') def writeDisplay(self, fp, index=0, bit=-1, parent=-1): t = self fp.write('DISPLAY_LINE\n') fp.write('{\n') fp.write('\tCHANNEL = "%s";\n'%(t.name)) fp.write('\tEXPAND_STATUS = COLLAPSED;\n') fp.write('\tRADIX = Hexadecimal;\n') fp.write('\tTREE_INDEX = %d;\n'%(index)) if t.width>1 and bit!=-1: fp.write('\tTREE_LEVEL = 1;\n') fp.write('\tPARENT = %d;\n'%(parent)) elif t.width>1: fp.write('\tTREE_LEVEL = 0;\n') fp.write('\tCHILDREN = ') for i in range(t.width): fp.write('%d'%(index+1+i)) if i==t.width-1: fp.write(';\n') else: fp.write(', ') else: fp.write('\tTREE_LEVEL = 0;\n') fp.write('}\n\n') if t.width>1 and bit==-1: for i in range(t.width): tt = Trace("%s[%d]"%(t.name, t.width-1-i), t.type, t.width) tt.writeDisplay(fp, index+1+i, i, index) class Sim: def __init__(self): self.traces = {} self.tracelist = [] self.clocks = [] self.clkdict = {} self.nsec = 0.0 def advTime(self, dt): self.nsec = self.nsec+dt def addClock(self, net, t0, tf, period): clk = (net, t0, tf, period) self.clocks.append(clk) self.clkdict[net] = clk def clockNext(self, net, t=None): if t==None: t = self.nsec clk = self.clkdict[net] t0 = clk[1] dt = clk[3] next = t+dt-(t-t0)%dt print "clknext: net=%s t=%.1f t0=%.1f dt=%.1f next=%.1f"% \ (net, t, t0, dt, next) return next def force(self, net, value, dt=None, t=None): trace = self.traces[net] if t==None: t = self.nsec trace.addEvent(t, value) if dt!=None: self.advTime(dt) def flushClocks(self): for net, t0, tf, period in self.clocks: if tf==None: tf = self.nsec t = t0 print "clock '%s' start %.2f end %.2f freq %.3f MHz"% \ (net, t0, tf, 1000.0/period) while t