pytholite: move FSM management to separate module
[litex.git] / migen / pytholite / fsm.py
1 from migen.fhdl import visit as fhdl
2 from migen.corelogic.fsm import FSM
3
4 class AbstractNextState:
5 def __init__(self, target_state):
6 self.target_state = target_state
7
8 # entry state is first state returned
9 class StateAssembler:
10 def __init__(self):
11 self.states = []
12 self.exit_states = []
13
14 def assemble(self, n_states, n_exit_states):
15 self.states += n_states
16 for exit_state in self.exit_states:
17 exit_state.insert(0, AbstractNextState(n_states[0]))
18 self.exit_states = n_exit_states
19
20 def ret(self):
21 return self.states, self.exit_states
22
23 # like list.index, but using "is" instead of comparison
24 def _index_is(l, x):
25 for i, e in enumerate(l):
26 if e is x:
27 return i
28
29 class _LowerAbstractNextState(fhdl.NodeTransformer):
30 def __init__(self, fsm, states, stnames):
31 self.fsm = fsm
32 self.states = states
33 self.stnames = stnames
34
35 def visit_unknown(self, node):
36 if isinstance(node, AbstractNextState):
37 index = _index_is(self.states, node.target_state)
38 estate = getattr(self.fsm, self.stnames[index])
39 return self.fsm.next_state(estate)
40 else:
41 return node
42
43 def implement_fsm(states):
44 stnames = ["S" + str(i) for i in range(len(states))]
45 fsm = FSM(*stnames)
46 lans = _LowerAbstractNextState(fsm, states, stnames)
47 for i, state in enumerate(states):
48 actions = lans.visit(state)
49 fsm.act(getattr(fsm, stnames[i]), *actions)
50 return fsm