diff --git a/litescope/core.py b/litescope/core.py index 91a08ac..817ba30 100644 --- a/litescope/core.py +++ b/litescope/core.py @@ -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.mux = AnalyzerMux(self.dw, len(self.groups)) + for i, signals in self.groups.items(): + self.comb += [ + 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.core_dw, depth, cd_ratio) - + self.submodules.storage = AnalyzerStorage(self.dw*cd_ratio, depth, cd_ratio) self.comb += [ - self.frontend.sink.valid.eq(1), - self.frontend.sink.data.eq(Cat(self.signals)), + 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) diff --git a/litescope/software/driver/analyzer.py b/litescope/software/driver/analyzer.py index ef4670a..f875033 100644 --- a/litescope/software/driver/analyzer.py +++ b/litescope/software/driver/analyzer.py @@ -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,13 +51,19 @@ class LiteScopeAnalyzerDriver(): key = key.replace(self.name + "_", "") setattr(self, key, value) value = 1 - for name, length in self.layout: - setattr(self, name + "_o", value) - value = value*(2**length) + 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: - setattr(self, name + "_m", (2**length-1) << value) - value += length + 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: @@ -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)