hdl.dsl: provide generated values for FSMs.
This commit is contained in:
parent
040811c2e5
commit
934546e633
|
@ -1,4 +1,4 @@
|
||||||
from collections import OrderedDict
|
from collections import OrderedDict, namedtuple
|
||||||
from collections.abc import Iterable
|
from collections.abc import Iterable
|
||||||
from contextlib import contextmanager
|
from contextlib import contextmanager
|
||||||
|
|
||||||
|
@ -92,6 +92,9 @@ class _ModuleBuilderDomainSet:
|
||||||
self._builder._add_domain(domain)
|
self._builder._add_domain(domain)
|
||||||
|
|
||||||
|
|
||||||
|
_FSM = namedtuple("_FSM", ("state", "encoding", "decoding"))
|
||||||
|
|
||||||
|
|
||||||
class Module(_ModuleBuilderRoot):
|
class Module(_ModuleBuilderRoot):
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
_ModuleBuilderRoot.__init__(self, self, depth=0)
|
_ModuleBuilderRoot.__init__(self, self, depth=0)
|
||||||
|
@ -105,6 +108,7 @@ class Module(_ModuleBuilderRoot):
|
||||||
self._driving = SignalDict()
|
self._driving = SignalDict()
|
||||||
self._submodules = []
|
self._submodules = []
|
||||||
self._domains = []
|
self._domains = []
|
||||||
|
self._generated = {}
|
||||||
|
|
||||||
def _check_context(self, construct, context):
|
def _check_context(self, construct, context):
|
||||||
if self._ctrl_context != context:
|
if self._ctrl_context != context:
|
||||||
|
@ -215,6 +219,7 @@ class Module(_ModuleBuilderRoot):
|
||||||
def FSM(self, reset=None, domain="sync", name="fsm"):
|
def FSM(self, reset=None, domain="sync", name="fsm"):
|
||||||
self._check_context("FSM", context=None)
|
self._check_context("FSM", context=None)
|
||||||
fsm_data = self._set_ctrl("FSM", {
|
fsm_data = self._set_ctrl("FSM", {
|
||||||
|
"name": name,
|
||||||
"signal": Signal(name="{}_state".format(name)),
|
"signal": Signal(name="{}_state".format(name)),
|
||||||
"domain": domain,
|
"domain": domain,
|
||||||
"encoding": OrderedDict(),
|
"encoding": OrderedDict(),
|
||||||
|
@ -298,11 +303,14 @@ class Module(_ModuleBuilderRoot):
|
||||||
fsm_signal, fsm_encoding, fsm_states = data["signal"], data["encoding"], data["states"]
|
fsm_signal, fsm_encoding, fsm_states = data["signal"], data["encoding"], data["states"]
|
||||||
fsm_signal.nbits = bits_for(len(fsm_encoding) - 1)
|
fsm_signal.nbits = bits_for(len(fsm_encoding) - 1)
|
||||||
# The FSM is encoded such that the state with encoding 0 is always the reset state.
|
# The FSM is encoded such that the state with encoding 0 is always the reset state.
|
||||||
fsm_decoding = {n: s for s, n in fsm_encoding.items()}
|
fsm_decoding = OrderedDict({n: s for s, n in fsm_encoding.items()})
|
||||||
fsm_signal.decoder = lambda n: "{}/{}".format(fsm_decoding[n], n)
|
fsm_signal.decoder = lambda n: "{}/{}".format(fsm_decoding[n], n)
|
||||||
self._statements.append(Switch(fsm_signal,
|
self._statements.append(Switch(fsm_signal,
|
||||||
OrderedDict((fsm_encoding[name], stmts) for name, stmts in fsm_states.items())))
|
OrderedDict((fsm_encoding[name], stmts) for name, stmts in fsm_states.items())))
|
||||||
|
|
||||||
|
fsm_name = data["name"]
|
||||||
|
self._generated[fsm_name] = _FSM(fsm_signal, fsm_encoding, fsm_decoding)
|
||||||
|
|
||||||
def _add_statement(self, assigns, domain, depth, compat_mode=False):
|
def _add_statement(self, assigns, domain, depth, compat_mode=False):
|
||||||
def domain_name(domain):
|
def domain_name(domain):
|
||||||
if domain is None:
|
if domain is None:
|
||||||
|
@ -354,6 +362,7 @@ class Module(_ModuleBuilderRoot):
|
||||||
for signal, domain in self._driving.items():
|
for signal, domain in self._driving.items():
|
||||||
fragment.add_driver(signal, domain)
|
fragment.add_driver(signal, domain)
|
||||||
fragment.add_domains(self._domains)
|
fragment.add_domains(self._domains)
|
||||||
|
fragment.generated.update(self._generated)
|
||||||
return fragment
|
return fragment
|
||||||
|
|
||||||
get_fragment = lower
|
get_fragment = lower
|
||||||
|
|
|
@ -1,3 +1,5 @@
|
||||||
|
from collections import OrderedDict
|
||||||
|
|
||||||
from ..hdl.ast import *
|
from ..hdl.ast import *
|
||||||
from ..hdl.cd import *
|
from ..hdl.cd import *
|
||||||
from ..hdl.dsl import *
|
from ..hdl.dsl import *
|
||||||
|
@ -338,6 +340,18 @@ class DSLTestCase(FHDLTestCase):
|
||||||
"(sig b)": "sync",
|
"(sig b)": "sync",
|
||||||
})
|
})
|
||||||
|
|
||||||
|
frag = m.lower(platform=None)
|
||||||
|
fsm = frag.find_generated("fsm")
|
||||||
|
self.assertIsInstance(fsm.state, Signal)
|
||||||
|
self.assertEqual(fsm.encoding, OrderedDict({
|
||||||
|
"FIRST": 0,
|
||||||
|
"SECOND": 1,
|
||||||
|
}))
|
||||||
|
self.assertEqual(fsm.decoding, OrderedDict({
|
||||||
|
0: "FIRST",
|
||||||
|
1: "SECOND"
|
||||||
|
}))
|
||||||
|
|
||||||
def test_FSM_reset(self):
|
def test_FSM_reset(self):
|
||||||
a = Signal()
|
a = Signal()
|
||||||
m = Module()
|
m = Module()
|
||||||
|
|
Loading…
Reference in a new issue