--- /dev/null
+from nmigen import *
+from nmigen.cli import main
+
+
+m = Module()
+cd_por = ClockDomain(reset_less=True)
+cd_sync = ClockDomain()
+m.domains += cd_por, cd_sync
+
+delay = Signal(max=255, reset=255)
+with m.If(delay != 0):
+ m.d.por += delay.eq(delay - 1)
+m.d.comb += [
+ ClockSignal().eq(cd_por.clk),
+ ResetSignal().eq(delay == 0),
+]
+
+if __name__ == "__main__":
+ main(m.lower(platform=None), ports=[cd_por.clk])
def shape(self):
return 1, False
+ def _lhs_signals(self):
+ return ValueSet((self,))
+
def _rhs_signals(self):
raise NotImplementedError("ClockSignal must be lowered to a concrete signal") # :nocov:
def shape(self):
return 1, False
+ def _lhs_signals(self):
+ return ValueSet((self,))
+
def _rhs_signals(self):
raise NotImplementedError("ResetSignal must be lowered to a concrete signal") # :nocov:
return hash(self.value.value)
elif isinstance(self.value, Signal):
return hash(self.value.duid)
+ elif isinstance(self.value, (ClockSignal, ResetSignal)):
+ return hash(self.value.domain)
elif isinstance(self.value, Operator):
return hash((self.value.op, tuple(ValueKey(o) for o in self.value.operands)))
elif isinstance(self.value, Slice):
return self.value.value == other.value.value
elif isinstance(self.value, Signal):
return self.value is other.value
+ elif isinstance(self.value, (ClockSignal, ResetSignal)):
+ return self.value.domain == other.value.domain
elif isinstance(self.value, Operator):
return (self.value.op == other.value.op and
len(self.value.operands) == len(other.value.operands) and
class SignalKey:
def __init__(self, signal):
- if type(signal) is not Signal:
+ if type(signal) is Signal:
+ self._intern = (0, signal.duid)
+ elif type(signal) is ClockSignal:
+ self._intern = (1, signal.domain)
+ elif type(signal) is ResetSignal:
+ self._intern = (2, signal.domain)
+ else:
raise TypeError("Object '{!r}' is not an nMigen signal".format(signal))
self.signal = signal
def __hash__(self):
- return hash(self.signal.duid)
+ return hash(self._intern)
def __eq__(self, other):
if type(other) is not SignalKey:
return False
- return self.signal is other.signal
+ return self._intern == other._intern
def __lt__(self, other):
if type(other) is not SignalKey:
raise TypeError("Object '{!r}' cannot be compared to a SignalKey".format(signal))
- return self.signal.duid < other.signal.duid
+ return self._intern < other._intern
def __repr__(self):
return "<{}.SignalKey {!r}>".format(__name__, self.signal)
.format(context, domain))
return self.domains[domain]
+ def map_drivers(self, fragment, new_fragment):
+ for domain, signal in fragment.iter_drivers():
+ new_fragment.add_driver(self.on_value(signal), domain)
+
def on_ClockSignal(self, value):
cd = self._resolve(value.domain, value)
return cd.clk
msg="'Module' object has no attribute 'nonexistentattr'"):
m.nonexistentattr
+ def test_clock_signal(self):
+ m = Module()
+ m.d.comb += ClockSignal("pix").eq(ClockSignal())
+ self.assertRepr(m._statements, """
+ (
+ (eq (clk pix) (clk sync))
+ )
+ """)
+
+ def test_reset_signal(self):
+ m = Module()
+ m.d.comb += ResetSignal("pix").eq(1)
+ self.assertRepr(m._statements, """
+ (
+ (eq (rst pix) (const 1'd1))
+ )
+ """)
+
def test_If(self):
m = Module()
with m.If(self.s1):
)
""")
+ def test_lower_drivers(self):
+ pix = ClockDomain()
+ f = Fragment()
+ f.add_driver(ClockSignal("pix"), None)
+ f.add_driver(ResetSignal("pix"), "sync")
+
+ f = DomainLowerer({"pix": pix})(f)
+ self.assertEqual(f.drivers, {
+ None: SignalSet((pix.clk,)),
+ "sync": SignalSet((pix.rst,))
+ })
+
def test_lower_wrong_domain(self):
sync = ClockDomain()
f = Fragment()