+# nmigen: UnusedElaboratable=no
+
from ..hdl.ast import *
from ..hdl.cd import *
from ..hdl.ir import *
from ..hdl.xfrm import *
-from .tools import *
+from ..hdl.mem import *
+from .utils import *
class DomainRenamerTestCase(FHDLTestCase):
"pix": cd_pix,
})
+ def test_rename_cd_preserves_allow_reset_less(self):
+ cd_pix = ClockDomain(reset_less=True)
+
+ f = Fragment()
+ f.add_domains(cd_pix)
+ f.add_statements(
+ self.s1.eq(ResetSignal(allow_reset_less=True)),
+ )
+
+ f = DomainRenamer("pix")(f)
+ f = DomainLowerer()(f)
+ self.assertRepr(f.statements, """
+ (
+ (eq (sig s1) (const 1'd0))
+ )
+ """)
+
+
def test_rename_cd_subfragment(self):
cd_sync = ClockDomain()
cd_pix = ClockDomain()
"pix": cd_pix,
})
+ def test_rename_wrong_to_comb(self):
+ with self.assertRaisesRegex(ValueError,
+ r"^Domain 'sync' may not be renamed to 'comb'$"):
+ DomainRenamer("comb")
+
+ def test_rename_wrong_from_comb(self):
+ with self.assertRaisesRegex(ValueError,
+ r"^Domain 'comb' may not be renamed$"):
+ DomainRenamer({"comb": "sync"})
+
class DomainLowererTestCase(FHDLTestCase):
def setUp(self):
def test_lower_clk(self):
sync = ClockDomain()
f = Fragment()
+ f.add_domains(sync)
f.add_statements(
self.s.eq(ClockSignal("sync"))
)
- f = DomainLowerer({"sync": sync})(f)
+ f = DomainLowerer()(f)
self.assertRepr(f.statements, """
(
(eq (sig s) (sig clk))
def test_lower_rst(self):
sync = ClockDomain()
f = Fragment()
+ f.add_domains(sync)
f.add_statements(
self.s.eq(ResetSignal("sync"))
)
- f = DomainLowerer({"sync": sync})(f)
+ f = DomainLowerer()(f)
self.assertRepr(f.statements, """
(
(eq (sig s) (sig rst))
def test_lower_rst_reset_less(self):
sync = ClockDomain(reset_less=True)
f = Fragment()
+ f.add_domains(sync)
f.add_statements(
self.s.eq(ResetSignal("sync", allow_reset_less=True))
)
- f = DomainLowerer({"sync": sync})(f)
+ f = DomainLowerer()(f)
self.assertRepr(f.statements, """
(
(eq (sig s) (const 1'd0))
""")
def test_lower_drivers(self):
+ sync = ClockDomain()
pix = ClockDomain()
f = Fragment()
+ f.add_domains(sync, pix)
f.add_driver(ClockSignal("pix"), None)
f.add_driver(ResetSignal("pix"), "sync")
- f = DomainLowerer({"pix": pix})(f)
+ f = DomainLowerer()(f)
self.assertEqual(f.drivers, {
None: SignalSet((pix.clk,)),
"sync": SignalSet((pix.rst,))
})
def test_lower_wrong_domain(self):
- sync = ClockDomain()
f = Fragment()
f.add_statements(
self.s.eq(ClockSignal("xxx"))
)
- with self.assertRaises(DomainError,
- msg="Signal (clk xxx) refers to nonexistent domain 'xxx'"):
- DomainLowerer({"sync": sync})(f)
+ with self.assertRaisesRegex(DomainError,
+ r"^Signal \(clk xxx\) refers to nonexistent domain 'xxx'$"):
+ DomainLowerer()(f)
def test_lower_wrong_reset_less_domain(self):
sync = ClockDomain(reset_less=True)
f = Fragment()
+ f.add_domains(sync)
f.add_statements(
self.s.eq(ResetSignal("sync"))
)
- with self.assertRaises(DomainError,
- msg="Signal (rst sync) refers to reset of reset-less domain 'sync'"):
- DomainLowerer({"sync": sync})(f)
+ with self.assertRaisesRegex(DomainError,
+ r"^Signal \(rst sync\) refers to reset of reset-less domain 'sync'$"):
+ DomainLowerer()(f)
class SampleLowererTestCase(FHDLTestCase):
SignalSet((b,)),
])
+ def test_lhs_empty(self):
+ stmts = [
+ Cat().eq(0)
+ ]
+
+ groups = LHSGroupAnalyzer()(stmts)
+ self.assertEqual(list(groups.values()), [
+ ])
+
class LHSGroupFilterTestCase(FHDLTestCase):
def test_filter(self):
)
""")
+ def test_lhs_empty(self):
+ stmts = [
+ Cat().eq(0)
+ ]
+
+ self.assertRepr(LHSGroupFilter(SignalSet())(stmts), "()")
+
class ResetInserterTestCase(FHDLTestCase):
def setUp(self):
""")
-class CEInserterTestCase(FHDLTestCase):
+class EnableInserterTestCase(FHDLTestCase):
def setUp(self):
self.s1 = Signal()
self.s2 = Signal()
self.s3 = Signal()
self.c1 = Signal()
- def test_ce_default(self):
+ def test_enable_default(self):
f = Fragment()
f.add_statements(
self.s1.eq(1)
)
f.add_driver(self.s1, "sync")
- f = CEInserter(self.c1)(f)
+ f = EnableInserter(self.c1)(f)
self.assertRepr(f.statements, """
(
(eq (sig s1) (const 1'd1))
)
""")
- def test_ce_cd(self):
+ def test_enable_cd(self):
f = Fragment()
f.add_statements(
self.s1.eq(1),
f.add_driver(self.s1, "sync")
f.add_driver(self.s2, "pix")
- f = CEInserter({"pix": self.c1})(f)
+ f = EnableInserter({"pix": self.c1})(f)
self.assertRepr(f.statements, """
(
(eq (sig s1) (const 1'd1))
)
""")
- def test_ce_subfragment(self):
+ def test_enable_subfragment(self):
f1 = Fragment()
f1.add_statements(
self.s1.eq(1)
f2.add_driver(self.s2, "sync")
f1.add_subfragment(f2)
- f1 = CEInserter(self.c1)(f1)
+ f1 = EnableInserter(self.c1)(f1)
(f2, _), = f1.subfragments
self.assertRepr(f1.statements, """
(
)
""")
+ def test_enable_read_port(self):
+ mem = Memory(width=8, depth=4)
+ f = EnableInserter(self.c1)(mem.read_port(transparent=False)).elaborate(platform=None)
+ self.assertRepr(f.named_ports["EN"][0], """
+ (m (sig c1) (sig mem_r_en) (const 1'd0))
+ """)
+
+ def test_enable_write_port(self):
+ mem = Memory(width=8, depth=4)
+ f = EnableInserter(self.c1)(mem.write_port()).elaborate(platform=None)
+ self.assertRepr(f.named_ports["EN"][0], """
+ (m (sig c1) (cat (repl (slice (sig mem_w_en) 0:1) 8)) (const 8'd0))
+ """)
+
-class _MockElaboratable:
+class _MockElaboratable(Elaboratable):
def __init__(self):
self.s1 = Signal()
def test_getattr(self):
e = _MockElaboratable()
- te = CEInserter(self.c1)(e)
+ te = EnableInserter(self.c1)(e)
self.assertIs(te.s1, e.s1)
def test_composition(self):
e = _MockElaboratable()
- te1 = CEInserter(self.c1)(e)
+ te1 = EnableInserter(self.c1)(e)
te2 = ResetInserter(self.c2)(te1)
self.assertIsInstance(te1, TransformedElaboratable)
)
)
""")
+
+
+class MockUserValue(UserValue):
+ def __init__(self, lowered):
+ super().__init__()
+ self.lowered = lowered
+
+ def lower(self):
+ return self.lowered
+
+
+class UserValueTestCase(FHDLTestCase):
+ def setUp(self):
+ self.s = Signal()
+ self.c = Signal()
+ self.uv = MockUserValue(self.s)
+
+ def test_lower(self):
+ sync = ClockDomain()
+ f = Fragment()
+ f.add_domains(sync)
+ f.add_statements(
+ self.uv.eq(1)
+ )
+ for signal in self.uv._lhs_signals():
+ f.add_driver(signal, "sync")
+
+ f = ResetInserter(self.c)(f)
+ f = DomainLowerer()(f)
+ self.assertRepr(f.statements, """
+ (
+ (eq (sig s) (const 1'd1))
+ (switch (sig c)
+ (case 1 (eq (sig s) (const 1'd0)))
+ )
+ (switch (sig rst)
+ (case 1 (eq (sig s) (const 1'd0)))
+ )
+ )
+ """)
+
+
+class UserValueRecursiveTestCase(UserValueTestCase):
+ def setUp(self):
+ self.s = Signal()
+ self.c = Signal()
+ self.uv = MockUserValue(MockUserValue(self.s))
+
+ # inherit the test_lower method from UserValueTestCase because the checks are the same