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):
|
def shape(self):
|
||||||
return 1, False
|
return 1, False
|
||||||
|
|
||||||
|
def _lhs_signals(self):
|
||||||
|
return ValueSet((self,))
|
||||||
|
|
||||||
def _rhs_signals(self):
|
def _rhs_signals(self):
|
||||||
raise NotImplementedError("ClockSignal must be lowered to a concrete signal") # :nocov:
|
raise NotImplementedError("ClockSignal must be lowered to a concrete signal") # :nocov:
|
||||||
|
|
||||||
|
@ -666,6 +669,9 @@ class ResetSignal(Value):
|
||||||
def shape(self):
|
def shape(self):
|
||||||
return 1, False
|
return 1, False
|
||||||
|
|
||||||
|
def _lhs_signals(self):
|
||||||
|
return ValueSet((self,))
|
||||||
|
|
||||||
def _rhs_signals(self):
|
def _rhs_signals(self):
|
||||||
raise NotImplementedError("ResetSignal must be lowered to a concrete signal") # :nocov:
|
raise NotImplementedError("ResetSignal must be lowered to a concrete signal") # :nocov:
|
||||||
|
|
||||||
|
@ -1038,6 +1044,8 @@ class ValueKey:
|
||||||
return hash(self.value.value)
|
return hash(self.value.value)
|
||||||
elif isinstance(self.value, Signal):
|
elif isinstance(self.value, Signal):
|
||||||
return hash(self.value.duid)
|
return hash(self.value.duid)
|
||||||
|
elif isinstance(self.value, (ClockSignal, ResetSignal)):
|
||||||
|
return hash(self.value.domain)
|
||||||
elif isinstance(self.value, Operator):
|
elif isinstance(self.value, Operator):
|
||||||
return hash((self.value.op, tuple(ValueKey(o) for o in self.value.operands)))
|
return hash((self.value.op, tuple(ValueKey(o) for o in self.value.operands)))
|
||||||
elif isinstance(self.value, Slice):
|
elif isinstance(self.value, Slice):
|
||||||
|
@ -1064,6 +1072,8 @@ class ValueKey:
|
||||||
return self.value.value == other.value.value
|
return self.value.value == other.value.value
|
||||||
elif isinstance(self.value, Signal):
|
elif isinstance(self.value, Signal):
|
||||||
return self.value is other.value
|
return self.value is other.value
|
||||||
|
elif isinstance(self.value, (ClockSignal, ResetSignal)):
|
||||||
|
return self.value.domain == other.value.domain
|
||||||
elif isinstance(self.value, Operator):
|
elif isinstance(self.value, Operator):
|
||||||
return (self.value.op == other.value.op and
|
return (self.value.op == other.value.op and
|
||||||
len(self.value.operands) == len(other.value.operands) and
|
len(self.value.operands) == len(other.value.operands) and
|
||||||
|
@ -1123,22 +1133,28 @@ class ValueSet(_MappedKeySet):
|
||||||
|
|
||||||
class SignalKey:
|
class SignalKey:
|
||||||
def __init__(self, signal):
|
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))
|
raise TypeError("Object '{!r}' is not an nMigen signal".format(signal))
|
||||||
self.signal = signal
|
self.signal = signal
|
||||||
|
|
||||||
def __hash__(self):
|
def __hash__(self):
|
||||||
return hash(self.signal.duid)
|
return hash(self._intern)
|
||||||
|
|
||||||
def __eq__(self, other):
|
def __eq__(self, other):
|
||||||
if type(other) is not SignalKey:
|
if type(other) is not SignalKey:
|
||||||
return False
|
return False
|
||||||
return self.signal is other.signal
|
return self._intern == other._intern
|
||||||
|
|
||||||
def __lt__(self, other):
|
def __lt__(self, other):
|
||||||
if type(other) is not SignalKey:
|
if type(other) is not SignalKey:
|
||||||
raise TypeError("Object '{!r}' cannot be compared to a SignalKey".format(signal))
|
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):
|
def __repr__(self):
|
||||||
return "<{}.SignalKey {!r}>".format(__name__, self.signal)
|
return "<{}.SignalKey {!r}>".format(__name__, self.signal)
|
||||||
|
|
|
@ -293,6 +293,10 @@ class DomainLowerer(FragmentTransformer, ValueTransformer, StatementTransformer)
|
||||||
.format(context, domain))
|
.format(context, domain))
|
||||||
return self.domains[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):
|
def on_ClockSignal(self, value):
|
||||||
cd = self._resolve(value.domain, value)
|
cd = self._resolve(value.domain, value)
|
||||||
return cd.clk
|
return cd.clk
|
||||||
|
|
|
@ -95,6 +95,24 @@ class DSLTestCase(FHDLTestCase):
|
||||||
msg="'Module' object has no attribute 'nonexistentattr'"):
|
msg="'Module' object has no attribute 'nonexistentattr'"):
|
||||||
m.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):
|
def test_If(self):
|
||||||
m = Module()
|
m = Module()
|
||||||
with m.If(self.s1):
|
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):
|
def test_lower_wrong_domain(self):
|
||||||
sync = ClockDomain()
|
sync = ClockDomain()
|
||||||
f = Fragment()
|
f = Fragment()
|
||||||
|
|
Loading…
Reference in a new issue