litescope: add support for groups of signals and dynamic muxing between them
allow multiple debug configuration in a single bitstream
This commit is contained in:
parent
2f625c58b2
commit
cf7ea12ec8
|
@ -66,6 +66,21 @@ class FrontendSubSampler(Module, AutoCSR):
|
|||
]
|
||||
|
||||
|
||||
class AnalyzerMux(Module, AutoCSR):
|
||||
def __init__(self, dw, n):
|
||||
self.sinks = [stream.Endpoint(core_layout(dw)) for i in range(n)]
|
||||
self.source = stream.Endpoint(core_layout(dw))
|
||||
|
||||
self.value = CSRStorage(bits_for(n))
|
||||
|
||||
# # #
|
||||
|
||||
cases = {}
|
||||
for i in range(n):
|
||||
cases[i] = self.sinks[i].connect(self.source)
|
||||
self.comb += Case(self.value.storage, cases)
|
||||
|
||||
|
||||
class AnalyzerFrontend(Module, AutoCSR):
|
||||
def __init__(self, dw, cd, cd_ratio):
|
||||
self.sink = stream.Endpoint(core_layout(dw))
|
||||
|
@ -160,8 +175,11 @@ class LiteScopeIO(Module, AutoCSR):
|
|||
return self.gpio.get_csrs()
|
||||
|
||||
|
||||
class LiteScopeAnalyzer(Module, AutoCSR):
|
||||
def __init__(self, signals, depth, cd="sys", cd_ratio=1):
|
||||
def _format_groups(groups):
|
||||
if not isinstance(groups, dict):
|
||||
groups = {0 : groups}
|
||||
new_groups = {}
|
||||
for n, signals in groups.items():
|
||||
if not isinstance(signals, list):
|
||||
signals = [signals]
|
||||
|
||||
|
@ -171,32 +189,40 @@ class LiteScopeAnalyzer(Module, AutoCSR):
|
|||
split_signals.extend(s.flatten())
|
||||
else:
|
||||
split_signals.append(s)
|
||||
signals = split_signals
|
||||
new_groups[n] = split_signals
|
||||
return new_groups
|
||||
|
||||
self.signals = signals
|
||||
self.dw = sum([len(s) for s in signals])
|
||||
self.core_dw = self.dw*cd_ratio
|
||||
|
||||
class LiteScopeAnalyzer(Module, AutoCSR):
|
||||
def __init__(self, groups, depth, cd="sys", cd_ratio=1):
|
||||
self.groups = _format_groups(groups)
|
||||
self.dw = max([sum([len(s) for s in g]) for g in self.groups.values()])
|
||||
|
||||
self.depth = depth
|
||||
self.cd_ratio = cd_ratio
|
||||
|
||||
# # #
|
||||
|
||||
self.submodules.frontend = AnalyzerFrontend(self.dw, cd, cd_ratio)
|
||||
self.submodules.storage = AnalyzerStorage(self.core_dw, depth, cd_ratio)
|
||||
|
||||
self.submodules.mux = AnalyzerMux(self.dw, len(self.groups))
|
||||
for i, signals in self.groups.items():
|
||||
self.comb += [
|
||||
self.frontend.sink.valid.eq(1),
|
||||
self.frontend.sink.data.eq(Cat(self.signals)),
|
||||
self.mux.sinks[i].valid.eq(1),
|
||||
self.mux.sinks[i].data.eq(Cat(signals))
|
||||
]
|
||||
self.submodules.frontend = AnalyzerFrontend(self.dw, cd, cd_ratio)
|
||||
self.submodules.storage = AnalyzerStorage(self.dw*cd_ratio, depth, cd_ratio)
|
||||
self.comb += [
|
||||
self.mux.source.connect(self.frontend.sink),
|
||||
self.frontend.source.connect(self.storage.sink)
|
||||
]
|
||||
|
||||
def export_csv(self, vns, filename):
|
||||
def format_line(*args):
|
||||
return ",".join(args) + "\n"
|
||||
r = format_line("config", "dw", str(self.dw))
|
||||
r += format_line("config", "depth", str(self.depth))
|
||||
r += format_line("config", "cd_ratio", str(int(self.cd_ratio)))
|
||||
for s in self.signals:
|
||||
r += format_line("signal", vns.get_name(s), str(len(s)))
|
||||
r = format_line("config", "None", "dw", str(self.dw))
|
||||
r += format_line("config", "None", "depth", str(self.depth))
|
||||
r += format_line("config", "None", "cd_ratio", str(int(self.cd_ratio)))
|
||||
for i, signals in self.groups.items():
|
||||
for s in signals:
|
||||
r += format_line("signal", str(i), vns.get_name(s), str(len(s)))
|
||||
write_to_file(filename, r)
|
||||
|
|
|
@ -6,7 +6,8 @@ from litescope.software.dump import *
|
|||
|
||||
import csv
|
||||
|
||||
class LiteScopeAnalyzerDriver():
|
||||
|
||||
class LiteScopeAnalyzerDriver:
|
||||
def __init__(self, regs, name, config_csv=None, clk_freq=None, debug=False):
|
||||
self.regs = regs
|
||||
self.name = name
|
||||
|
@ -21,24 +22,28 @@ class LiteScopeAnalyzerDriver():
|
|||
self.samplerate = clk_freq
|
||||
self.debug = debug
|
||||
self.get_config()
|
||||
self.get_layout()
|
||||
self.get_layouts()
|
||||
self.build()
|
||||
self.group = 0
|
||||
self.data = DumpData(self.dw)
|
||||
|
||||
def get_config(self):
|
||||
csv_reader = csv.reader(open(self.config_csv), delimiter=',', quotechar='#')
|
||||
for item in csv_reader:
|
||||
t, n, v = item
|
||||
t, g, n, v = item
|
||||
if t == "config":
|
||||
setattr(self, n, int(v))
|
||||
|
||||
def get_layout(self):
|
||||
self.layout = []
|
||||
def get_layouts(self):
|
||||
self.layouts = {}
|
||||
csv_reader = csv.reader(open(self.config_csv), delimiter=',', quotechar='#')
|
||||
for item in csv_reader:
|
||||
t, n, v = item
|
||||
t, g, n, v = item
|
||||
if t == "signal":
|
||||
self.layout.append((n, int(v)))
|
||||
try:
|
||||
self.layouts[int(g)].append((n, int(v)))
|
||||
except:
|
||||
self.layouts[int(g)] = [(n, int(v))]
|
||||
|
||||
def build(self):
|
||||
for key, value in self.regs.d.items():
|
||||
|
@ -46,14 +51,20 @@ class LiteScopeAnalyzerDriver():
|
|||
key = key.replace(self.name + "_", "")
|
||||
setattr(self, key, value)
|
||||
value = 1
|
||||
for name, length in self.layout:
|
||||
for signals in self.layouts.values():
|
||||
for name, length in signals:
|
||||
setattr(self, name + "_o", value)
|
||||
value = value*(2**length)
|
||||
value = 0
|
||||
for name, length in self.layout:
|
||||
for signals in self.layouts.values():
|
||||
for name, length in signals:
|
||||
setattr(self, name + "_m", (2**length-1) << value)
|
||||
value += length
|
||||
|
||||
def configure_group(self, value):
|
||||
self.group = value
|
||||
self.mux_value.write(value)
|
||||
|
||||
def configure_trigger(self, value=0, mask=0, cond=None):
|
||||
if cond is not None:
|
||||
for k, v in cond.items():
|
||||
|
@ -113,5 +124,5 @@ class LiteScopeAnalyzerDriver():
|
|||
dump = SigrokDump(samplerate=self.samplerate)
|
||||
else:
|
||||
raise NotImplementedError
|
||||
dump.add_from_layout(self.layout, self.data)
|
||||
dump.add_from_layout(self.layouts[self.group], self.data)
|
||||
dump.write(filename)
|
||||
|
|
Loading…
Reference in New Issue