fsm: support complex targets in NextValue. Closes #27.
This commit is contained in:
parent
1857ec6c32
commit
31ffa8c18f
|
@ -5,6 +5,7 @@ class Example(Module):
|
|||
def __init__(self):
|
||||
self.s = Signal()
|
||||
self.counter = Signal(8)
|
||||
x = Array(Signal(name="a") for i in range(7))
|
||||
|
||||
myfsm = FSM()
|
||||
self.submodules += myfsm
|
||||
|
@ -16,6 +17,7 @@ class Example(Module):
|
|||
myfsm.act("BAR",
|
||||
self.s.eq(0),
|
||||
NextValue(self.counter, self.counter + 1),
|
||||
NextValue(x[self.counter], 89),
|
||||
NextState("FOO")
|
||||
)
|
||||
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
from collections import OrderedDict
|
||||
|
||||
from migen.fhdl.structure import *
|
||||
from migen.fhdl.structure import _Slice, _ArrayProxy
|
||||
from migen.fhdl.module import Module, FinalizeError
|
||||
from migen.fhdl.visit import NodeTransformer
|
||||
from migen.fhdl.bitcontainer import value_bits_sign
|
||||
|
@ -21,18 +22,46 @@ class NextState:
|
|||
|
||||
|
||||
class NextValue:
|
||||
def __init__(self, register, value):
|
||||
self.register = register
|
||||
def __init__(self, target, value):
|
||||
self.target = target
|
||||
self.value = value
|
||||
|
||||
|
||||
def _target_eq(a, b):
|
||||
if type(a) != type(b):
|
||||
return False
|
||||
ty = type(a)
|
||||
if ty == Constant:
|
||||
return a.value == b.value
|
||||
elif ty == Signal:
|
||||
return a is b
|
||||
elif ty == Cat:
|
||||
return all(_target_eq(x, y) for x, y in zip(a.l, b.l))
|
||||
elif ty == _Slice:
|
||||
return (_target_eq(a.value, b.value)
|
||||
and a.start == b.start
|
||||
and a.end == b.end)
|
||||
elif ty == _ArrayProxy:
|
||||
return (all(_target_eq(x, y) for x, y in zip(a.choices, b.choices))
|
||||
and _target_eq(a.key, b.key))
|
||||
else:
|
||||
raise ValueError("NextValue cannot be used with target type '{}'"
|
||||
.format(ty))
|
||||
|
||||
|
||||
class _LowerNext(NodeTransformer):
|
||||
def __init__(self, next_state_signal, encoding, aliases):
|
||||
self.next_state_signal = next_state_signal
|
||||
self.encoding = encoding
|
||||
self.aliases = aliases
|
||||
# register -> next_value_ce, next_value
|
||||
self.registers = OrderedDict()
|
||||
# (target, next_value_ce, next_value)
|
||||
self.registers = []
|
||||
|
||||
def _get_register_control(self, target):
|
||||
for x in self.registers:
|
||||
if _target_eq(target, x[0]):
|
||||
return x
|
||||
raise KeyError
|
||||
|
||||
def visit_unknown(self, node):
|
||||
if isinstance(node, NextState):
|
||||
|
@ -43,12 +72,12 @@ class _LowerNext(NodeTransformer):
|
|||
return self.next_state_signal.eq(self.encoding[actual_state])
|
||||
elif isinstance(node, NextValue):
|
||||
try:
|
||||
next_value_ce, next_value = self.registers[node.register]
|
||||
next_value_ce, next_value = self._get_register_control(node.target)
|
||||
except KeyError:
|
||||
related = node.register if isinstance(node.register, Signal) else None
|
||||
next_value = Signal(bits_sign=value_bits_sign(node.register), related=related)
|
||||
related = node.target if isinstance(node.target, Signal) else None
|
||||
next_value = Signal(bits_sign=value_bits_sign(node.target), related=related)
|
||||
next_value_ce = Signal(related=related)
|
||||
self.registers[node.register] = next_value_ce, next_value
|
||||
self.registers.append((node.target, next_value_ce, next_value))
|
||||
return next_value.eq(node.value), next_value_ce.eq(1)
|
||||
else:
|
||||
return node
|
||||
|
@ -133,7 +162,7 @@ class FSM(Module):
|
|||
Case(self.state, cases).makedefault(self.encoding[self.reset_state])
|
||||
]
|
||||
self.sync += self.state.eq(self.next_state)
|
||||
for register, (next_value_ce, next_value) in ln.registers.items():
|
||||
for register, next_value_ce, next_value in ln.registers:
|
||||
self.sync += If(next_value_ce, register.eq(next_value))
|
||||
|
||||
# drive entering/leaving signals
|
||||
|
|
Loading…
Reference in New Issue