From b58715c5dc25499b46f301a59a35fed3a1a744cb Mon Sep 17 00:00:00 2001 From: whitequark Date: Fri, 14 Dec 2018 09:02:29 +0000 Subject: [PATCH] ast, back.pysim: allow specifying user-defined decoders for signals. --- nmigen/back/pysim.py | 18 +++++++++++++++--- nmigen/compat/genlib/fsm.py | 7 +++---- nmigen/fhdl/ast.py | 9 +++++++-- 3 files changed, 25 insertions(+), 9 deletions(-) diff --git a/nmigen/back/pysim.py b/nmigen/back/pysim.py index d740ebd..9716ff2 100644 --- a/nmigen/back/pysim.py +++ b/nmigen/back/pysim.py @@ -295,6 +295,14 @@ class Simulator: self._vcd_signals[signal] = set() name = self._signal_name_in_fragment(fragment, signal) suffix = None + if signal.decoder: + var_type = "string" + var_size = 1 + var_init = signal.decoder(signal.reset).replace(" ", "_") + else: + var_type = "wire" + var_size = signal.nbits + var_init = signal.reset while True: try: if suffix is None: @@ -303,7 +311,7 @@ class Simulator: name_suffix = "{}${}".format(name, suffix) self._vcd_signals[signal].add(self._vcd_writer.register_var( scope=".".join(self._fragments[fragment]), name=name_suffix, - var_type="wire", size=signal.nbits, init=signal.reset)) + var_type=var_type, size=var_size, init=var_init)) if signal not in self._vcd_names: self._vcd_names[signal] = \ ".".join(self._fragments[fragment] + (name_suffix,)) @@ -356,10 +364,14 @@ class Simulator: if (old, new) == (0, 1) and signal in self._domain_triggers: domains.add(self._domain_triggers[signal]) - if self._vcd_writer: + if self._vcd_writer and old != new: # Finally, dump the new value to the VCD file. for vcd_signal in self._vcd_signals[signal]: - self._vcd_writer.change(vcd_signal, self._timestamp / self._epsilon, new) + if signal.decoder: + var_value = signal.decoder(new).replace(" ", "_") + else: + var_value = new + self._vcd_writer.change(vcd_signal, self._timestamp / self._epsilon, var_value) def _commit_comb_signals(self, domains): """Perform the comb part of IR processes (aka RTLIL always).""" diff --git a/nmigen/compat/genlib/fsm.py b/nmigen/compat/genlib/fsm.py index 548eb6a..b6d2c88 100644 --- a/nmigen/compat/genlib/fsm.py +++ b/nmigen/compat/genlib/fsm.py @@ -156,10 +156,9 @@ class FSM(CompatModule): self.encoding = dict((s, n) for n, s in enumerate(self.actions.keys())) self.decoding = {n: s for s, n in self.encoding.items()} - self.state = Signal(max=nstates, reset=self.encoding[self.reset_state]) - self.state._enumeration = self.decoding - self.next_state = Signal(max=nstates) - self.next_state._enumeration = {n: "{}:{}".format(n, s) for n, s in self.decoding.items()} + decoder = lambda n: "{}/{}".format(self.decoding[n], n) + self.state = Signal(max=nstates, reset=self.encoding[self.reset_state], decoder=decoder) + self.next_state = Signal.like(self.state) for state, signal in self.before_leaving_signals.items(): encoded = self.encoding[state] diff --git a/nmigen/fhdl/ast.py b/nmigen/fhdl/ast.py index 3b51441..cbfa799 100644 --- a/nmigen/fhdl/ast.py +++ b/nmigen/fhdl/ast.py @@ -512,6 +512,9 @@ class Signal(Value, DUID): defaults to 0) and ``max`` (exclusive, defaults to 2). attrs : dict Dictionary of synthesis attributes. + decoder : function + A function converting integer signal values to human-readable strings (e.g. FSM state + names). Attributes ---------- @@ -524,7 +527,7 @@ class Signal(Value, DUID): """ def __init__(self, shape=None, name=None, reset=0, reset_less=False, min=None, max=None, - attrs=None, src_loc_at=0): + attrs=None, decoder=None, src_loc_at=0): super().__init__(src_loc_at=src_loc_at) if name is None: @@ -560,6 +563,7 @@ class Signal(Value, DUID): self.reset_less = bool(reset_less) self.attrs = OrderedDict(() if attrs is None else attrs) + self.decoder = decoder @classmethod def like(cls, other, src_loc_at=0, **kwargs): @@ -573,7 +577,8 @@ class Signal(Value, DUID): kw = dict(shape=cls.wrap(other).shape(), name=tracer.get_var_name(depth=2 + src_loc_at)) if isinstance(other, cls): - kw.update(reset=other.reset, reset_less=other.reset_less, attrs=other.attrs) + kw.update(reset=other.reset, reset_less=other.reset_less, + attrs=other.attrs, decoder=other.decoder) kw.update(kwargs) return cls(**kw, src_loc_at=1 + src_loc_at) -- 2.30.2