ast, back.pysim: allow specifying user-defined decoders for signals.
This commit is contained in:
parent
bb843cb40c
commit
b58715c5dc
|
@ -295,6 +295,14 @@ class Simulator:
|
||||||
self._vcd_signals[signal] = set()
|
self._vcd_signals[signal] = set()
|
||||||
name = self._signal_name_in_fragment(fragment, signal)
|
name = self._signal_name_in_fragment(fragment, signal)
|
||||||
suffix = None
|
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:
|
while True:
|
||||||
try:
|
try:
|
||||||
if suffix is None:
|
if suffix is None:
|
||||||
|
@ -303,7 +311,7 @@ class Simulator:
|
||||||
name_suffix = "{}${}".format(name, suffix)
|
name_suffix = "{}${}".format(name, suffix)
|
||||||
self._vcd_signals[signal].add(self._vcd_writer.register_var(
|
self._vcd_signals[signal].add(self._vcd_writer.register_var(
|
||||||
scope=".".join(self._fragments[fragment]), name=name_suffix,
|
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:
|
if signal not in self._vcd_names:
|
||||||
self._vcd_names[signal] = \
|
self._vcd_names[signal] = \
|
||||||
".".join(self._fragments[fragment] + (name_suffix,))
|
".".join(self._fragments[fragment] + (name_suffix,))
|
||||||
|
@ -356,10 +364,14 @@ class Simulator:
|
||||||
if (old, new) == (0, 1) and signal in self._domain_triggers:
|
if (old, new) == (0, 1) and signal in self._domain_triggers:
|
||||||
domains.add(self._domain_triggers[signal])
|
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.
|
# Finally, dump the new value to the VCD file.
|
||||||
for vcd_signal in self._vcd_signals[signal]:
|
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):
|
def _commit_comb_signals(self, domains):
|
||||||
"""Perform the comb part of IR processes (aka RTLIL always)."""
|
"""Perform the comb part of IR processes (aka RTLIL always)."""
|
||||||
|
|
|
@ -156,10 +156,9 @@ class FSM(CompatModule):
|
||||||
self.encoding = dict((s, n) for n, s in enumerate(self.actions.keys()))
|
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.decoding = {n: s for s, n in self.encoding.items()}
|
||||||
|
|
||||||
self.state = Signal(max=nstates, reset=self.encoding[self.reset_state])
|
decoder = lambda n: "{}/{}".format(self.decoding[n], n)
|
||||||
self.state._enumeration = self.decoding
|
self.state = Signal(max=nstates, reset=self.encoding[self.reset_state], decoder=decoder)
|
||||||
self.next_state = Signal(max=nstates)
|
self.next_state = Signal.like(self.state)
|
||||||
self.next_state._enumeration = {n: "{}:{}".format(n, s) for n, s in self.decoding.items()}
|
|
||||||
|
|
||||||
for state, signal in self.before_leaving_signals.items():
|
for state, signal in self.before_leaving_signals.items():
|
||||||
encoded = self.encoding[state]
|
encoded = self.encoding[state]
|
||||||
|
|
|
@ -512,6 +512,9 @@ class Signal(Value, DUID):
|
||||||
defaults to 0) and ``max`` (exclusive, defaults to 2).
|
defaults to 0) and ``max`` (exclusive, defaults to 2).
|
||||||
attrs : dict
|
attrs : dict
|
||||||
Dictionary of synthesis attributes.
|
Dictionary of synthesis attributes.
|
||||||
|
decoder : function
|
||||||
|
A function converting integer signal values to human-readable strings (e.g. FSM state
|
||||||
|
names).
|
||||||
|
|
||||||
Attributes
|
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,
|
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)
|
super().__init__(src_loc_at=src_loc_at)
|
||||||
|
|
||||||
if name is None:
|
if name is None:
|
||||||
|
@ -560,6 +563,7 @@ class Signal(Value, DUID):
|
||||||
self.reset_less = bool(reset_less)
|
self.reset_less = bool(reset_less)
|
||||||
|
|
||||||
self.attrs = OrderedDict(() if attrs is None else attrs)
|
self.attrs = OrderedDict(() if attrs is None else attrs)
|
||||||
|
self.decoder = decoder
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def like(cls, other, src_loc_at=0, **kwargs):
|
def like(cls, other, src_loc_at=0, **kwargs):
|
||||||
|
@ -573,7 +577,8 @@ class Signal(Value, DUID):
|
||||||
kw = dict(shape=cls.wrap(other).shape(),
|
kw = dict(shape=cls.wrap(other).shape(),
|
||||||
name=tracer.get_var_name(depth=2 + src_loc_at))
|
name=tracer.get_var_name(depth=2 + src_loc_at))
|
||||||
if isinstance(other, cls):
|
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)
|
kw.update(kwargs)
|
||||||
return cls(**kw, src_loc_at=1 + src_loc_at)
|
return cls(**kw, src_loc_at=1 + src_loc_at)
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue