51 lines
1.3 KiB
Python
51 lines
1.3 KiB
Python
|
from migen.fhdl import visit as fhdl
|
||
|
from migen.corelogic.fsm import FSM
|
||
|
|
||
|
class AbstractNextState:
|
||
|
def __init__(self, target_state):
|
||
|
self.target_state = target_state
|
||
|
|
||
|
# entry state is first state returned
|
||
|
class StateAssembler:
|
||
|
def __init__(self):
|
||
|
self.states = []
|
||
|
self.exit_states = []
|
||
|
|
||
|
def assemble(self, n_states, n_exit_states):
|
||
|
self.states += n_states
|
||
|
for exit_state in self.exit_states:
|
||
|
exit_state.insert(0, AbstractNextState(n_states[0]))
|
||
|
self.exit_states = n_exit_states
|
||
|
|
||
|
def ret(self):
|
||
|
return self.states, self.exit_states
|
||
|
|
||
|
# like list.index, but using "is" instead of comparison
|
||
|
def _index_is(l, x):
|
||
|
for i, e in enumerate(l):
|
||
|
if e is x:
|
||
|
return i
|
||
|
|
||
|
class _LowerAbstractNextState(fhdl.NodeTransformer):
|
||
|
def __init__(self, fsm, states, stnames):
|
||
|
self.fsm = fsm
|
||
|
self.states = states
|
||
|
self.stnames = stnames
|
||
|
|
||
|
def visit_unknown(self, node):
|
||
|
if isinstance(node, AbstractNextState):
|
||
|
index = _index_is(self.states, node.target_state)
|
||
|
estate = getattr(self.fsm, self.stnames[index])
|
||
|
return self.fsm.next_state(estate)
|
||
|
else:
|
||
|
return node
|
||
|
|
||
|
def implement_fsm(states):
|
||
|
stnames = ["S" + str(i) for i in range(len(states))]
|
||
|
fsm = FSM(*stnames)
|
||
|
lans = _LowerAbstractNextState(fsm, states, stnames)
|
||
|
for i, state in enumerate(states):
|
||
|
actions = lans.visit(state)
|
||
|
fsm.act(getattr(fsm, stnames[i]), *actions)
|
||
|
return fsm
|