Merge pull request #40 from jevinskie/jev/vcd-timescale-fix
VCD: Add samplerate support to fix displayed timestamps
This commit is contained in:
commit
71187f8bd0
|
@ -48,6 +48,7 @@ class LiteScopeSoC(BaseSoC):
|
||||||
self.submodules.analyzer = LiteScopeAnalyzer(analyzer_signals,
|
self.submodules.analyzer = LiteScopeAnalyzer(analyzer_signals,
|
||||||
depth = 1024,
|
depth = 1024,
|
||||||
clock_domain = "sys",
|
clock_domain = "sys",
|
||||||
|
samplerate = self.sys_clk_freq,
|
||||||
csr_csv = "analyzer.csv")
|
csr_csv = "analyzer.csv")
|
||||||
self.add_csr("analyzer")
|
self.add_csr("analyzer")
|
||||||
|
|
||||||
|
|
|
@ -226,9 +226,10 @@ class _Storage(Module, AutoCSR):
|
||||||
|
|
||||||
|
|
||||||
class LiteScopeAnalyzer(Module, AutoCSR):
|
class LiteScopeAnalyzer(Module, AutoCSR):
|
||||||
def __init__(self, groups, depth, clock_domain="sys", trigger_depth=16, register=False, csr_csv="analyzer.csv"):
|
def __init__(self, groups, depth, samplerate=1e-12, clock_domain="sys", trigger_depth=16, register=False, csr_csv="analyzer.csv"):
|
||||||
self.groups = groups = self.format_groups(groups)
|
self.groups = groups = self.format_groups(groups)
|
||||||
self.depth = depth
|
self.depth = depth
|
||||||
|
self.samplerate = samplerate
|
||||||
|
|
||||||
self.data_width = data_width = max([sum([len(s) for s in g]) for g in groups.values()])
|
self.data_width = data_width = max([sum([len(s) for s in g]) for g in groups.values()])
|
||||||
|
|
||||||
|
@ -294,6 +295,7 @@ class LiteScopeAnalyzer(Module, AutoCSR):
|
||||||
return ",".join(args) + "\n"
|
return ",".join(args) + "\n"
|
||||||
r = format_line("config", "None", "data_width", str(self.data_width))
|
r = format_line("config", "None", "data_width", str(self.data_width))
|
||||||
r += format_line("config", "None", "depth", str(self.depth))
|
r += format_line("config", "None", "depth", str(self.depth))
|
||||||
|
r += format_line("config", "None", "samplerate", str(self.samplerate))
|
||||||
for i, signals in self.groups.items():
|
for i, signals in self.groups.items():
|
||||||
for s in signals:
|
for s in signals:
|
||||||
r += format_line("signal", str(i), vns.get_name(s), str(len(s)))
|
r += format_line("signal", str(i), vns.get_name(s), str(len(s)))
|
||||||
|
|
|
@ -118,6 +118,7 @@ class LiteScopeAnalyzerDriver:
|
||||||
self.add_trigger(value, mask, cond)
|
self.add_trigger(value, mask, cond)
|
||||||
|
|
||||||
def configure_subsampler(self, value):
|
def configure_subsampler(self, value):
|
||||||
|
self.subsampling = value
|
||||||
self.subsampler_value.write(value-1)
|
self.subsampler_value.write(value-1)
|
||||||
|
|
||||||
def run(self, offset=0, length=None):
|
def run(self, offset=0, length=None):
|
||||||
|
@ -166,11 +167,13 @@ class LiteScopeAnalyzerDriver:
|
||||||
return self.data
|
return self.data
|
||||||
|
|
||||||
def save(self, filename, samplerate=None, flatten=False):
|
def save(self, filename, samplerate=None, flatten=False):
|
||||||
|
if samplerate is None:
|
||||||
|
samplerate = self.samplerate / self.subsampling
|
||||||
if self.debug:
|
if self.debug:
|
||||||
print("[writing to " + filename + "]...")
|
print("[writing to " + filename + "]...")
|
||||||
name, ext = os.path.splitext(filename)
|
name, ext = os.path.splitext(filename)
|
||||||
if ext == ".vcd":
|
if ext == ".vcd":
|
||||||
dump = VCDDump()
|
dump = VCDDump(samplerate=samplerate)
|
||||||
elif ext == ".csv":
|
elif ext == ".csv":
|
||||||
dump = CSVDump()
|
dump = CSVDump()
|
||||||
elif ext == ".py":
|
elif ext == ".py":
|
||||||
|
|
|
@ -6,6 +6,7 @@
|
||||||
|
|
||||||
from itertools import count
|
from itertools import count
|
||||||
import datetime
|
import datetime
|
||||||
|
import re
|
||||||
from litescope.software.dump.common import Dump, dec2bin
|
from litescope.software.dump.common import Dump, dec2bin
|
||||||
|
|
||||||
|
|
||||||
|
@ -19,14 +20,37 @@ def vcd_codes():
|
||||||
code = codechars[r] + code
|
code = codechars[r] + code
|
||||||
yield code
|
yield code
|
||||||
|
|
||||||
|
_si_prefix2exp = {
|
||||||
|
"": 0,
|
||||||
|
"m": -3,
|
||||||
|
"u": -6,
|
||||||
|
"n": -9,
|
||||||
|
"p": -12,
|
||||||
|
"f": -15,
|
||||||
|
}
|
||||||
|
|
||||||
|
def _timescale_str2num(timescale):
|
||||||
|
match = re.fullmatch("(\d+)(\w{0,1})s", timescale)
|
||||||
|
num = int(match.group(1))
|
||||||
|
si_prefix = match.group(2)
|
||||||
|
exp = _si_prefix2exp[si_prefix]
|
||||||
|
return num * 10**exp, si_prefix
|
||||||
|
|
||||||
|
|
||||||
class VCDDump(Dump):
|
class VCDDump(Dump):
|
||||||
def __init__(self, dump=None, timescale="1ps", comment=""):
|
def __init__(self, dump=None, samplerate=1e-12, timescale="1ps", comment=""):
|
||||||
Dump.__init__(self)
|
Dump.__init__(self)
|
||||||
self.variables = [] if dump is None else dump.variables
|
self.variables = [] if dump is None else dump.variables
|
||||||
self.timescale = timescale
|
self.timescale = timescale
|
||||||
self.comment = comment
|
self.comment = comment
|
||||||
self.cnt = -1
|
self.cnt = -1
|
||||||
|
# rescale the timescale from the provided one to one where it is equal to the samplerate
|
||||||
|
# this lets us output sequential change timestamps which helps with software like PulseView
|
||||||
|
# that slow down if a much smaller timescale than necessary is used
|
||||||
|
timescale_seconds, si_prefix = _timescale_str2num(timescale)
|
||||||
|
# factor of 2 scale is because of 2x samples from fake clock
|
||||||
|
self.count_timescale = int(1 / (timescale_seconds * samplerate * 2))
|
||||||
|
self.timescale_unit_str = si_prefix + "s"
|
||||||
|
|
||||||
def change(self):
|
def change(self):
|
||||||
r = ""
|
r = ""
|
||||||
|
@ -65,14 +89,12 @@ class VCDDump(Dump):
|
||||||
|
|
||||||
def generate_timescale(self):
|
def generate_timescale(self):
|
||||||
r = "$timescale "
|
r = "$timescale "
|
||||||
r += self.timescale
|
r += str(self.count_timescale) + self.timescale_unit_str
|
||||||
r += " $end\n"
|
r += " $end\n"
|
||||||
return r
|
return r
|
||||||
|
|
||||||
def generate_vars(self):
|
def generate_vars(self):
|
||||||
r = "$scope "
|
r = "$scope dumped_signals $end\n"
|
||||||
r += self.timescale
|
|
||||||
r += " $end\n"
|
|
||||||
for v in self.variables:
|
for v in self.variables:
|
||||||
r += "$var wire "
|
r += "$var wire "
|
||||||
r += str(v.width)
|
r += str(v.width)
|
||||||
|
|
Loading…
Reference in New Issue