parent
664b4bcb3a
commit
011bf2258e
19
examples/por.py
Normal file
19
examples/por.py
Normal file
|
@ -0,0 +1,19 @@
|
|||
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])
|
|
@ -635,6 +635,9 @@ class ClockSignal(Value):
|
|||
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:
|
||||
|
||||
|
@ -666,6 +669,9 @@ class ResetSignal(Value):
|
|||
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:
|
||||
|
||||
|
@ -1038,6 +1044,8 @@ class ValueKey:
|
|||
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):
|
||||
|
@ -1064,6 +1072,8 @@ class ValueKey:
|
|||
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
|
||||
|
@ -1123,22 +1133,28 @@ class ValueSet(_MappedKeySet):
|
|||
|
||||
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)
|
||||
|
|
|
@ -293,6 +293,10 @@ class DomainLowerer(FragmentTransformer, ValueTransformer, StatementTransformer)
|
|||
.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
|
||||
|
|
|
@ -95,6 +95,24 @@ class DSLTestCase(FHDLTestCase):
|
|||
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):
|
||||
|
|
|
@ -135,6 +135,18 @@ class DomainLowererTestCase(FHDLTestCase):
|
|||
)
|
||||
""")
|
||||
|
||||
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()
|
||||
|
|
Loading…
Reference in a new issue