mirror of
https://github.com/enjoy-digital/litex.git
synced 2025-01-04 09:52:26 -05:00
gen/sim/vcd: allow continous update of vcd file and dynamic signals
With continous update, VCD header needs to be writen at the beginning of the simulation. When a new signal is created, we rewrite the header and the content.
This commit is contained in:
parent
fa7ac6c9a2
commit
6a35337a09
1 changed files with 38 additions and 13 deletions
|
@ -21,13 +21,16 @@ def vcd_codes():
|
|||
class VCDWriter:
|
||||
def __init__(self, filename):
|
||||
self.filename = filename
|
||||
self.out_file = open(self.filename, "w")
|
||||
self.out_file = None
|
||||
self.buffer_file = tempfile.TemporaryFile(
|
||||
dir=os.path.dirname(filename), mode="w+")
|
||||
self.initialized = False
|
||||
self.codegen = vcd_codes()
|
||||
self.codes = OrderedDict()
|
||||
self.signal_values = dict()
|
||||
self.t = 0
|
||||
|
||||
def _write_value(self, f, signal, value):
|
||||
def _write_value(self, signal, value):
|
||||
l = len(signal)
|
||||
if value < 0:
|
||||
value += 2**l
|
||||
|
@ -35,10 +38,22 @@ class VCDWriter:
|
|||
fmtstr = "b{:0" + str(l) + "b} {}\n"
|
||||
else:
|
||||
fmtstr = "{}{}\n"
|
||||
code = self.codes[signal]
|
||||
f.write(fmtstr.format(value, code))
|
||||
try:
|
||||
code = self.codes[signal]
|
||||
except KeyError:
|
||||
code = next(self.codegen)
|
||||
self.codes[signal] = code
|
||||
self.init(self.codes.keys())
|
||||
|
||||
return fmtstr.format(value, code)
|
||||
|
||||
def _write(self, s):
|
||||
self.out_file.write(s)
|
||||
self.buffer_file.write(s)
|
||||
|
||||
def init(self, signals):
|
||||
self.out_file = open(self.filename, "w")
|
||||
|
||||
# generate codes
|
||||
for signal in signals:
|
||||
try:
|
||||
|
@ -48,30 +63,40 @@ class VCDWriter:
|
|||
self.codes[signal] = code
|
||||
|
||||
# write vcd header
|
||||
out = self.out_file
|
||||
header = ""
|
||||
ns = build_namespace(self.codes.keys())
|
||||
for signal, code in self.codes.items():
|
||||
name = ns.get_name(signal)
|
||||
out.write("$var wire {len} {code} {name} $end\n"
|
||||
.format(name=name, code=code, len=len(signal)))
|
||||
out.write("$dumpvars\n")
|
||||
header += "$var wire {len} {code} {name} $end\n".format(name=name, code=code, len=len(signal))
|
||||
header += "$dumpvars\n"
|
||||
for signal in self.codes.keys():
|
||||
self._write_value(out, signal, signal.reset.value)
|
||||
out.write("$end\n")
|
||||
out.write("#0\n")
|
||||
header += self._write_value(signal, signal.reset.value)
|
||||
header += "$end\n"
|
||||
self.out_file.write(header)
|
||||
|
||||
if self.initialized:
|
||||
self.buffer_file.seek(0)
|
||||
shutil.copyfileobj(self.buffer_file, self.out_file)
|
||||
self.buffer_file.seek(0, 2)
|
||||
else:
|
||||
# init time
|
||||
self._write("#0\n")
|
||||
|
||||
self.initialized = True
|
||||
|
||||
def set(self, signal, value):
|
||||
if (signal not in self.signal_values
|
||||
or self.signal_values[signal] != value):
|
||||
self._write_value(self.out_file, signal, value)
|
||||
self._write(self._write_value(signal, value))
|
||||
self.signal_values[signal] = value
|
||||
|
||||
def delay(self, delay):
|
||||
self.t += delay
|
||||
self.out_file.write("#{}\n".format(self.t))
|
||||
self._write("#{}\n".format(self.t))
|
||||
|
||||
def close(self):
|
||||
self.out_file.close()
|
||||
self.buffer_file.close()
|
||||
|
||||
|
||||
class DummyVCDWriter:
|
||||
|
|
Loading…
Reference in a new issue