amaranth/tests/test_hdl_ir.py

3564 lines
118 KiB
Python
Raw Normal View History

2021-12-09 22:39:50 -07:00
# amaranth: UnusedElaboratable=no
from collections import OrderedDict
from amaranth.hdl._ast import *
from amaranth.hdl._cd import *
from amaranth.hdl._dsl import *
from amaranth.hdl._ir import *
from amaranth.hdl._mem import *
from amaranth.hdl._nir import SignalField, CombinationalCycle
from amaranth.lib import enum, data
from .utils import *
class ElaboratesToNone(Elaboratable):
def elaborate(self, platform):
return
class ElaboratesToSelf(Elaboratable):
def elaborate(self, platform):
return self
class FragmentGetTestCase(FHDLTestCase):
def test_get_wrong_none(self):
with self.assertRaisesRegex(TypeError,
r"^Object None is not an 'Elaboratable' nor 'Fragment'$"):
Fragment.get(None, platform=None)
with self.assertWarnsRegex(UserWarning,
r"^\.elaborate\(\) returned None; missing return statement\?$"):
with self.assertRaisesRegex(TypeError,
r"^Object None is not an 'Elaboratable' nor 'Fragment'$"):
Fragment.get(ElaboratesToNone(), platform=None)
def test_get_wrong_self(self):
with self.assertRaisesRegex(RecursionError,
r"^Object <.+?ElaboratesToSelf.+?> elaborates to itself$"):
Fragment.get(ElaboratesToSelf(), platform=None)
class FragmentGeneratedTestCase(FHDLTestCase):
def test_find_subfragment(self):
f1 = Fragment()
f2 = Fragment()
f1.add_subfragment(f2, "f2")
self.assertEqual(f1.find_subfragment(0), f2)
self.assertEqual(f1.find_subfragment("f2"), f2)
def test_find_subfragment_wrong(self):
f1 = Fragment()
f2 = Fragment()
f1.add_subfragment(f2, "f2")
with self.assertRaisesRegex(NameError,
r"^No subfragment at index #1$"):
f1.find_subfragment(1)
with self.assertRaisesRegex(NameError,
r"^No subfragment with name 'fx'$"):
f1.find_subfragment("fx")
def test_find_generated(self):
f1 = Fragment()
f2 = Fragment()
f2.generated["sig"] = sig = Signal()
f1.add_subfragment(f2, "f2")
self.assertEqual(SignalKey(f1.find_generated("f2", "sig")),
SignalKey(sig))
class DuplicateElaboratableTestCase(FHDLTestCase):
def test_duplicate(self):
sub = Module()
m = Module()
m.submodules.a = sub
m.submodules.b = sub
with self.assertRaisesRegex(DuplicateElaboratable,
r"^Elaboratable .* is included twice in the hierarchy, as "
r"top\.a and top\.b$"):
Fragment.get(m, None).prepare()
2018-12-13 02:19:16 -07:00
class FragmentPortsTestCase(FHDLTestCase):
def setUp(self):
self.s1 = Signal()
self.s2 = Signal()
self.s3 = Signal()
self.c1 = Signal()
self.c2 = Signal()
self.c3 = Signal()
def test_empty(self):
f = Fragment()
2024-02-11 04:07:45 -07:00
nl = build_netlist(f, ports=[])
self.assertRepr(nl, """
(
(module 0 None ('top'))
(cell 0 0 (top))
)
2024-02-11 04:07:45 -07:00
""")
2024-02-11 04:07:45 -07:00
def test_loopback(self):
f = Fragment()
f.add_statements(
"comb",
2024-02-11 04:07:45 -07:00
self.c1.eq(self.s1),
)
2024-02-11 04:07:45 -07:00
nl = build_netlist(f, ports=[self.c1, self.s1])
self.assertRepr(nl, """
(
(module 0 None ('top') (input 's1' 0.2) (output 'c1' 0.2))
(cell 0 0 (top (input 's1' 2:3) (output 'c1' 0.2)))
)
2024-02-11 04:07:45 -07:00
""")
2024-02-11 04:07:45 -07:00
def test_subfragment_simple(self):
f1 = Fragment()
f2 = Fragment()
f2.add_statements(
"comb",
2024-02-11 04:07:45 -07:00
self.c1.eq(~self.s1),
)
2024-02-11 04:07:45 -07:00
f1.add_subfragment(f2, "f2")
nl = build_netlist(f1, ports=[self.c1, self.s1])
self.assertRepr(nl, """
(
(module 0 None ('top') (input 's1' 0.2) (output 'c1' 1.0))
(module 1 0 ('top' 'f2') (input 's1' 0.2) (output 'c1' 1.0))
(cell 0 0 (top (input 's1' 2:3) (output 'c1' 1.0)))
2024-02-11 04:07:45 -07:00
(cell 1 1 (~ 0.2))
)
2024-02-11 04:07:45 -07:00
""")
2024-02-11 04:07:45 -07:00
def test_tree(self):
f = Fragment()
f1 = Fragment()
2024-02-11 04:07:45 -07:00
f.add_subfragment(f1, "f1")
f11 = Fragment()
f1.add_subfragment(f11, "f11")
f111 = Fragment()
f11.add_subfragment(f111, "f111")
f1111 = Fragment()
f111.add_subfragment(f1111, "f1111")
f12 = Fragment()
f1.add_subfragment(f12, "f12")
f13 = Fragment()
f1.add_subfragment(f13, "f13")
f131 = Fragment()
f13.add_subfragment(f131, "f131")
f2 = Fragment()
2024-02-11 04:07:45 -07:00
f.add_subfragment(f2, "f2")
f2.add_statements(
"comb",
2024-02-11 04:07:45 -07:00
self.s2.eq(~self.s1),
)
2024-02-11 04:07:45 -07:00
f131.add_statements(
"comb",
2024-02-11 04:07:45 -07:00
self.s3.eq(~self.s2),
Assert(~self.s1),
)
2024-02-11 04:07:45 -07:00
f12.add_statements(
"comb",
2024-02-11 04:07:45 -07:00
self.c1.eq(~self.s3),
)
2024-02-11 04:07:45 -07:00
f1111.add_statements(
"comb",
2024-02-11 04:07:45 -07:00
self.c2.eq(~self.s3),
Assert(self.s1),
)
2024-02-11 04:07:45 -07:00
f111.add_statements(
"comb",
2024-02-11 04:07:45 -07:00
self.c3.eq(~self.c2),
)
2024-02-11 04:07:45 -07:00
nl = build_netlist(f, ports=[self.c1, self.c2, self.c3, self.s1])
self.assertRepr(nl, """
(
(module 0 None ('top')
(input 's1' 0.2)
(output 'c1' 5.0)
(output 'c2' 2.0)
(output 'c3' 1.0))
(module 1 0 ('top' 'f1')
(input 's1' 0.2)
(output 'c3' 1.0)
(output 'c2' 2.0)
(output 'c1' 5.0)
(input 's2' 10.0))
2024-02-11 04:07:45 -07:00
(module 2 1 ('top' 'f1' 'f11')
(input 's1' 0.2)
(output 'c3' 1.0)
(output 'c2' 2.0)
(input 's3' 6.0))
2024-02-11 04:07:45 -07:00
(module 3 2 ('top' 'f1' 'f11' 'f111')
(input 's1' 0.2)
2024-02-11 04:07:45 -07:00
(output 'c3' 1.0)
(output 'c2' 2.0)
(input 's3' 6.0))
2024-02-11 04:07:45 -07:00
(module 4 3 ('top' 'f1' 'f11' 'f111' 'f1111')
(input 's1' 0.2)
(output 'c2' 2.0)
(input 's3' 6.0))
(module 5 1 ('top' 'f1' 'f12')
(output 'c1' 5.0)
(input 's3' 6.0))
(module 6 1 ('top' 'f1' 'f13')
(input 's1' 0.2)
(output 's3' 6.0)
(input 's2' 10.0))
2024-02-11 04:07:45 -07:00
(module 7 6 ('top' 'f1' 'f13' 'f131')
(input 's1' 0.2)
(output 's3' 6.0)
(input 's2' 10.0))
(module 8 0 ('top' 'f2')
(input 's1' 0.2)
(output 's2' 10.0))
(cell 0 0 (top (input 's1' 2:3) (output 'c1' 5.0) (output 'c2' 2.0) (output 'c3' 1.0)))
2024-02-11 04:07:45 -07:00
(cell 1 3 (~ 2.0))
(cell 2 4 (~ 6.0))
(cell 3 4 (assignment_list 1'd0 (1 0:1 1'd1)))
(cell 4 4 (assert 0.2 3.0 None))
2024-02-11 04:07:45 -07:00
(cell 5 5 (~ 6.0))
(cell 6 7 (~ 10.0))
(cell 7 7 (~ 0.2))
(cell 8 7 (assignment_list 1'd0 (1 0:1 1'd1)))
(cell 9 7 (assert 7.0 8.0 None))
2024-02-11 04:07:45 -07:00
(cell 10 8 (~ 0.2))
)
2024-02-11 04:07:45 -07:00
""")
2024-02-11 04:07:45 -07:00
def test_port_dict(self):
f = Fragment()
nl = build_netlist(f, ports={
"a": (self.s1, PortDirection.Output),
"b": (self.s2, PortDirection.Input),
"c": (IOPort(1, name="io3"), PortDirection.Inout),
2024-02-11 04:07:45 -07:00
})
self.assertRepr(nl, """
(
(module 0 None ('top') (input 'b' 0.2) (output 'a' 1'd0) (io inout 'c' 0.0))
(cell 0 0 (top (input 'b' 2:3) (output 'a' 1'd0)))
)
2024-02-11 04:07:45 -07:00
""")
2024-02-11 04:07:45 -07:00
def test_port_domain(self):
f = Fragment()
2024-02-11 04:07:45 -07:00
cd_sync = ClockDomain()
ctr = Signal(4)
f.add_domains(cd_sync)
f.add_statements("sync", ctr.eq(ctr + 1))
nl = build_netlist(f, ports=[
ClockSignal("sync"),
ResetSignal("sync"),
ctr,
])
self.assertRepr(nl, """
(
(module 0 None ('top') (input 'clk' 0.2) (input 'rst' 0.3) (output 'ctr' 5.0:4))
(cell 0 0 (top (input 'clk' 2:3) (input 'rst' 3:4) (output 'ctr' 5.0:4)))
2024-02-11 04:07:45 -07:00
(cell 1 0 (+ (cat 5.0:4 1'd0) 5'd1))
(cell 2 0 (matches 0.3 1))
(cell 3 0 (priority_match 1 2.0))
(cell 4 0 (assignment_list 5.0:4 (1 0:4 1.0:4) (3.0 0:4 4'd0)))
(cell 5 0 (flipflop 4.0:4 0 pos 0.2 0))
)
2024-02-11 04:07:45 -07:00
""")
2024-02-11 04:07:45 -07:00
def test_port_autodomain(self):
f = Fragment()
2024-02-11 04:07:45 -07:00
ctr = Signal(4)
f.add_statements("sync", ctr.eq(ctr + 1))
nl = build_netlist(f, ports=[ctr])
self.assertRepr(nl, """
(
(module 0 None ('top') (input 'clk' 0.2) (input 'rst' 0.3) (output 'ctr' 5.0:4))
(cell 0 0 (top (input 'clk' 2:3) (input 'rst' 3:4) (output 'ctr' 5.0:4)))
2024-02-11 04:07:45 -07:00
(cell 1 0 (+ (cat 5.0:4 1'd0) 5'd1))
(cell 2 0 (matches 0.3 1))
(cell 3 0 (priority_match 1 2.0))
(cell 4 0 (assignment_list 5.0:4 (1 0:4 1.0:4) (3.0 0:4 4'd0)))
(cell 5 0 (flipflop 4.0:4 0 pos 0.2 0))
)
2024-02-11 04:07:45 -07:00
""")
2024-02-11 04:07:45 -07:00
def test_port_partial(self):
f = Fragment()
f1 = Fragment()
2024-02-11 04:07:45 -07:00
f.add_subfragment(f1, "f1")
a = Signal(4)
b = Signal(4)
c = Signal(3)
f1.add_statements("comb", c.eq((a * b).shift_right(4)))
nl = build_netlist(f, ports=[a, b, c])
self.assertRepr(nl, """
(
(module 0 None ('top')
(input 'a' 0.2:6)
(input 'b' 0.6:10)
(output 'c' 1.4:7))
(module 1 0 ('top' 'f1')
(input 'a' 0.2:6)
(input 'b' 0.6:10)
(output 'c' 1.4:7))
(cell 0 0 (top
(input 'a' 2:6)
(input 'b' 6:10)
(output 'c' 1.4:7)))
2024-02-11 04:07:45 -07:00
(cell 1 1 (* (cat 0.2:6 4'd0) (cat 0.6:10 4'd0)))
)
""")
def test_port_io(self):
io = IOPort(8)
f = Fragment()
f1 = Fragment()
f1.add_subfragment(Instance("t", i_io=io[:2]), "i")
f.add_subfragment(f1, "f1")
f2 = Fragment()
f2.add_subfragment(Instance("t", o_io=io[2:4]), "i")
f.add_subfragment(f2, "f2")
f3 = Fragment()
f3.add_subfragment(Instance("t", io_io=io[4:6]), "i")
f.add_subfragment(f3, "f3")
nl = build_netlist(f, ports=[])
self.assertRepr(nl, """
(
(module 0 None ('top')
(io inout 'io' 0.0:8)
)
(module 1 0 ('top' 'f1')
(io input 'ioport$0$0' 0.0:2)
)
(module 2 0 ('top' 'f2')
(io output 'ioport$0$2' 0.2:4)
)
(module 3 0 ('top' 'f3')
(io inout 'ioport$0$4' 0.4:6)
)
(cell 0 0 (top))
(cell 1 1 (instance 't' 'i' (io input 'io' 0.0:2)))
(cell 2 2 (instance 't' 'i' (io output 'io' 0.2:4)))
(cell 3 3 (instance 't' 'i' (io inout 'io' 0.4:6)))
)
""")
def test_port_io_part(self):
io = IOPort(4)
f = Fragment()
f1 = Fragment()
f1.add_subfragment(Instance("t", i_i=io[0], o_o=io[1], io_io=io[2]), "i")
f.add_subfragment(f1, "f1")
nl = build_netlist(f, ports=[])
self.assertRepr(nl, """
(
(module 0 None ('top')
(io inout 'io' 0.0:4)
)
(module 1 0 ('top' 'f1')
(io input 'ioport$0$0' 0.0)
(io output 'ioport$0$1' 0.1)
(io inout 'ioport$0$2' 0.2)
)
(cell 0 0 (top))
(cell 1 1 (instance 't' 'i'
(io input 'i' 0.0)
(io output 'o' 0.1)
(io inout 'io' 0.2)
))
)
""")
2024-02-11 04:07:45 -07:00
def test_port_instance(self):
f = Fragment()
2024-02-11 04:07:45 -07:00
f1 = Fragment()
f.add_subfragment(f1, "f1")
a = Signal(4)
b = Signal(4)
c = Signal(4)
ioa = IOPort(4)
iob = IOPort(4)
ioc = IOPort(4)
2024-02-11 04:07:45 -07:00
f1.add_subfragment(Instance("t",
p_p = "meow",
a_a = True,
i_aa=a,
o_bb=b,
2024-02-11 04:07:45 -07:00
o_cc=c,
i_aaa=ioa,
o_bbb=iob,
io_ccc=ioc,
2024-02-11 04:07:45 -07:00
), "i")
nl = build_netlist(f, ports=[a, b, c])
2024-02-11 04:07:45 -07:00
self.assertRepr(nl, """
(
(module 0 None ('top')
(input 'a' 0.2:6)
(output 'b' 1.0:4)
(output 'c' 1.4:8)
(io input 'ioa' 0.0:4)
(io output 'iob' 1.0:4)
(io inout 'ioc' 2.0:4)
)
2024-02-11 04:07:45 -07:00
(module 1 0 ('top' 'f1')
(input 'a' 0.2:6)
(output 'b' 1.0:4)
(output 'c' 1.4:8)
(io input 'ioa' 0.0:4)
(io output 'iob' 1.0:4)
(io inout 'ioc' 2.0:4)
)
2024-02-11 04:07:45 -07:00
(cell 0 0 (top
(input 'a' 2:6)
(output 'b' 1.0:4)
(output 'c' 1.4:8)
))
2024-02-11 04:07:45 -07:00
(cell 1 1 (instance 't' 'i'
(param 'p' 'meow')
(attr 'a' True)
(input 'aa' 0.2:6)
(output 'bb' 0:4)
(output 'cc' 4:8)
(io input 'aaa' 0.0:4)
(io output 'bbb' 1.0:4)
(io inout 'ccc' 2.0:4)
))
2024-02-11 04:07:45 -07:00
)
""")
2020-02-06 10:33:41 -07:00
def test_port_wrong(self):
f = Fragment()
2024-02-11 04:07:45 -07:00
a = Signal()
with self.assertRaisesRegex(TypeError,
r"^Only signals and IO ports may be added as ports, not \(const 1'd1\)$"):
2024-02-11 04:07:45 -07:00
build_netlist(f, ports=(Const(1),))
with self.assertRaisesRegex(TypeError,
r"^Port name must be a string, not 1$"):
build_netlist(f, ports={1: (a, PortDirection.Input)})
with self.assertRaisesRegex(TypeError,
r"^Port direction must be a `PortDirection` instance or None, not 'i'$"):
build_netlist(f, ports={"a": (a, "i")})
def test_port_not_iterable(self):
f = Fragment()
with self.assertRaisesRegex(TypeError,
2024-02-11 04:07:45 -07:00
r"^`ports` must be a dict, a list or a tuple, not 1$"):
build_netlist(f, ports=1)
with self.assertRaisesRegex(TypeError,
2024-02-11 04:07:45 -07:00
(r"^`ports` must be a dict, a list or a tuple, not \(const 1'd1\)"
r" \(did you mean `ports=\(<signal>,\)`, rather than `ports=<signal>`\?\)$")):
2024-02-11 04:07:45 -07:00
build_netlist(f, ports=Const(1))
2024-03-05 02:34:58 -07:00
class FragmentDomainsTestCase(FHDLTestCase):
def test_propagate_up(self):
cd = ClockDomain()
f1 = Fragment()
f2 = Fragment()
f1.add_subfragment(f2)
f2.add_domains(cd)
f1._propagate_domains_up()
self.assertEqual(f1.domains, {"cd": cd})
def test_propagate_up_local(self):
cd = ClockDomain(local=True)
f1 = Fragment()
f2 = Fragment()
f1.add_subfragment(f2)
f2.add_domains(cd)
f1._propagate_domains_up()
self.assertEqual(f1.domains, {})
def test_domain_conflict(self):
cda = ClockDomain("sync")
cdb = ClockDomain("sync")
fa = Fragment()
fa.add_domains(cda)
fb = Fragment()
fb.add_domains(cdb)
f = Fragment()
f.add_subfragment(fa, "a")
f.add_subfragment(fb, "b")
f._propagate_domains_up()
self.assertEqual(f.domains, {"a_sync": cda, "b_sync": cdb})
(fa, _, _), (fb, _, _) = f.subfragments
self.assertEqual(fa.domains, {"a_sync": cda})
self.assertEqual(fb.domains, {"b_sync": cdb})
def test_domain_conflict_anon(self):
cda = ClockDomain("sync")
cdb = ClockDomain("sync")
fa = Fragment()
fa.add_domains(cda)
fb = Fragment()
fb.add_domains(cdb)
f = Fragment()
f.add_subfragment(fa, "a")
f.add_subfragment(fb)
with self.assertRaisesRegex(DomainError,
(r"^Domain 'sync' is defined by subfragments 'a', <unnamed #1> of fragment "
r"'top'; it is necessary to either rename subfragment domains explicitly, "
r"or give names to subfragments$")):
f._propagate_domains_up()
def test_domain_conflict_name(self):
cda = ClockDomain("sync")
cdb = ClockDomain("sync")
fa = Fragment()
fa.add_domains(cda)
fb = Fragment()
fb.add_domains(cdb)
f = Fragment()
f.add_subfragment(fa, "x")
f.add_subfragment(fb, "x")
with self.assertRaisesRegex(DomainError,
(r"^Domain 'sync' is defined by subfragments #0, #1 of fragment 'top', some "
r"of which have identical names; it is necessary to either rename subfragment "
r"domains explicitly, or give distinct names to subfragments$")):
f._propagate_domains_up()
def test_domain_conflict_rename_drivers(self):
cda = ClockDomain("sync")
cdb = ClockDomain("sync")
fa = Fragment()
fa.add_domains(cda)
fb = Fragment()
fb.add_domains(cdb)
2024-04-03 16:19:37 -06:00
fb.add_statements("comb", ResetSignal("sync").eq(1))
f = Fragment()
f.add_subfragment(fa, "a")
f.add_subfragment(fb, "b")
f._propagate_domains_up()
fb_new, _, _ = f.subfragments[1]
2024-04-03 16:19:37 -06:00
self.assertRepr(fb_new.statements["comb"], "((eq (rst b_sync) (const 1'd1)))")
def test_domain_conflict_rename_drivers_before_creating_missing(self):
cda = ClockDomain("sync")
cdb = ClockDomain("sync")
s = Signal()
fa = Fragment()
fa.add_domains(cda)
fb = Fragment()
fb.add_domains(cdb)
f = Fragment()
f.add_subfragment(fa, "a")
f.add_subfragment(fb, "b")
2024-04-03 16:19:37 -06:00
f.add_statements("b_sync", s.eq(1))
f._propagate_domains(lambda name: ClockDomain(name))
def test_propagate_down(self):
cd = ClockDomain()
f1 = Fragment()
f2 = Fragment()
f1.add_domains(cd)
f1.add_subfragment(f2)
f1._propagate_domains_down()
self.assertEqual(f2.domains, {"cd": cd})
def test_propagate_down_idempotent(self):
cd = ClockDomain()
f1 = Fragment()
f1.add_domains(cd)
f2 = Fragment()
f2.add_domains(cd)
f1.add_subfragment(f2)
f1._propagate_domains_down()
self.assertEqual(f1.domains, {"cd": cd})
self.assertEqual(f2.domains, {"cd": cd})
def test_propagate(self):
cd = ClockDomain()
f1 = Fragment()
f2 = Fragment()
f1.add_domains(cd)
f1.add_subfragment(f2)
new_domains = f1._propagate_domains(missing_domain=lambda name: None)
self.assertEqual(f1.domains, {"cd": cd})
self.assertEqual(f2.domains, {"cd": cd})
self.assertEqual(new_domains, [])
def test_propagate_missing(self):
s1 = Signal()
f1 = Fragment()
f1.add_statements("sync", s1.eq(1))
with self.assertRaisesRegex(DomainError,
r"^Domain 'sync' is used but not defined$"):
f1._propagate_domains(missing_domain=lambda name: None)
def test_propagate_create_missing(self):
s1 = Signal()
f1 = Fragment()
f1.add_statements("sync", s1.eq(1))
f2 = Fragment()
f1.add_subfragment(f2)
new_domains = f1._propagate_domains(missing_domain=lambda name: ClockDomain(name))
self.assertEqual(f1.domains.keys(), {"sync"})
self.assertEqual(f2.domains.keys(), {"sync"})
self.assertEqual(f1.domains["sync"], f2.domains["sync"])
self.assertEqual(new_domains, [f1.domains["sync"]])
def test_propagate_create_missing_fragment(self):
s1 = Signal()
f1 = Fragment()
f1.add_statements("sync", s1.eq(1))
cd = ClockDomain("sync")
f2 = Fragment()
f2.add_domains(cd)
new_domains = f1._propagate_domains(missing_domain=lambda name: f2)
self.assertEqual(f1.domains.keys(), {"sync"})
self.assertEqual(f1.domains["sync"], f2.domains["sync"])
self.assertEqual(new_domains, [])
self.assertEqual(f1.subfragments, [
(f2, "cd_sync", None)
])
def test_propagate_create_missing_fragment_many_domains(self):
s1 = Signal()
f1 = Fragment()
f1.add_statements("sync", s1.eq(1))
cd_por = ClockDomain("por")
cd_sync = ClockDomain("sync")
f2 = Fragment()
f2.add_domains(cd_por, cd_sync)
new_domains = f1._propagate_domains(missing_domain=lambda name: f2)
self.assertEqual(f1.domains.keys(), {"sync", "por"})
self.assertEqual(f2.domains.keys(), {"sync", "por"})
self.assertEqual(f1.domains["sync"], f2.domains["sync"])
self.assertEqual(new_domains, [])
self.assertEqual(f1.subfragments, [
(f2, "cd_sync", None)
])
def test_propagate_create_missing_fragment_wrong(self):
s1 = Signal()
f1 = Fragment()
f1.add_statements("sync", s1.eq(1))
f2 = Fragment()
f2.add_domains(ClockDomain("foo"))
with self.assertRaisesRegex(DomainError,
(r"^Fragment returned by missing domain callback does not define requested "
r"domain 'sync' \(defines 'foo'\)\.$")):
f1._propagate_domains(missing_domain=lambda name: f2)
def test_propagate_up_use(self):
a = Signal()
m = Module()
m1 = Module()
m2 = Module()
m.submodules.m1 = m1
m.submodules.m2 = m2
m1.d.test += a.eq(1)
m2.domains.test = ClockDomain()
with self.assertWarnsRegex(DeprecationWarning,
r"^Domain 'test' is used in 'top.m1', but defined in 'top.m2', which will not be "
r"supported in Amaranth 0.6; define the domain in 'top' or one of its parents$"):
Fragment.get(m, None).prepare()
class FragmentHierarchyConflictTestCase(FHDLTestCase):
def test_no_conflict_local_domains(self):
f1 = Fragment()
cd1 = ClockDomain("d", local=True)
f1.add_domains(cd1)
2024-04-03 16:19:37 -06:00
f1.add_statements("comb", ClockSignal("d").eq(1))
f2 = Fragment()
cd2 = ClockDomain("d", local=True)
f2.add_domains(cd2)
2024-04-03 16:19:37 -06:00
f2.add_statements("comb", ClockSignal("d").eq(1))
f3 = Fragment()
f3.add_subfragment(f1)
f3.add_subfragment(f2)
f3.prepare()
class InstanceTestCase(FHDLTestCase):
def test_construct(self):
s1 = Signal()
s2 = Signal()
s3 = Signal()
s4 = Signal()
io1 = IOPort(1)
io2 = IOPort(1)
io3 = IOPort(1)
io4 = IOPort(1)
io5 = IOPort(1)
io6 = IOPort(1)
inst = Instance("foo",
("a", "ATTR1", 1),
("p", "PARAM1", 0x1234),
("i", "s1", s1),
("o", "s2", s2),
("i", "io1", io1),
("o", "io2", io2),
("io", "io3", io3),
a_ATTR2=2,
p_PARAM2=0x5678,
i_s3=s3,
o_s4=s4,
i_io4=io4,
o_io5=io5,
io_io6=io6,
)
self.assertEqual(inst.attrs, OrderedDict([
("ATTR1", 1),
("ATTR2", 2),
]))
self.assertEqual(inst.parameters, OrderedDict([
("PARAM1", 0x1234),
("PARAM2", 0x5678),
]))
self.assertEqual(inst.ports, OrderedDict([
("s1", (s1, "i")),
("s2", (s2, "o")),
("io1", (io1, "i")),
("io2", (io2, "o")),
("io3", (io3, "io")),
("s3", (s3, "i")),
("s4", (s4, "o")),
("io4", (io4, "i")),
("io5", (io5, "o")),
("io6", (io6, "io")),
]))
def test_cast_ports(self):
inst = Instance("foo",
("i", "s1", 1),
("io", "s2", Cat()),
i_s3=3,
io_s4=Cat(),
)
self.assertRepr(inst.ports["s1"][0], "(const 1'd1)")
self.assertRepr(inst.ports["s2"][0], "(io-cat )")
self.assertRepr(inst.ports["s3"][0], "(const 2'd3)")
self.assertRepr(inst.ports["s4"][0], "(io-cat )")
def test_wrong_construct_arg(self):
s = Signal()
with self.assertRaisesRegex(NameError,
(r"^Instance argument \('', 's1', \(sig s\)\) should be a tuple "
r"\(kind, name, value\) where kind is one of \"a\", \"p\", \"i\", \"o\", or \"io\"$")):
Instance("foo", ("", "s1", s))
def test_wrong_construct_kwarg(self):
s = Signal()
with self.assertRaisesRegex(NameError,
(r"^Instance keyword argument x_s1=\(sig s\) does not start with one of "
r"\"a_\", \"p_\", \"i_\", \"o_\", or \"io_\"$")):
Instance("foo", x_s1=s)
def setUp_cpu(self):
self.rst = Signal()
self.stb = Signal()
self.pins = IOPort(8)
self.datal = Signal(4)
self.datah = Signal(4)
self.inst = Instance("cpu",
p_RESET=0x1234,
i_clk=ClockSignal(),
i_rst=self.rst,
o_stb=self.stb,
o_data=Cat(self.datal, self.datah),
io_pins=self.pins[:]
)
self.wrap = Fragment()
self.wrap.add_subfragment(self.inst)
def test_init(self):
self.setUp_cpu()
f = self.inst
self.assertEqual(f.type, "cpu")
self.assertEqual(f.parameters, OrderedDict([("RESET", 0x1234)]))
self.assertEqual(list(f.ports.keys()), ["clk", "rst", "stb", "data", "pins"])
def test_prepare_attrs(self):
self.setUp_cpu()
self.inst.attrs["ATTR"] = 1
2024-02-11 04:07:45 -07:00
design = self.inst.prepare()
self.assertEqual(design.fragment.attrs, OrderedDict([
("ATTR", 1),
]))
def test_nir_simple(self):
f = Fragment()
i = Signal(3)
o = Signal(4)
ioa = IOPort(5)
iob = IOPort(6)
ioc = IOPort(7)
f.add_subfragment(Instance("gadget",
i_i=i,
o_o=o,
i_ioa=ioa,
o_iob=iob,
io_ioc=ioc,
p_param="TEST",
a_attr=1234,
), "my_gadget")
nl = build_netlist(f, [i, o])
self.assertRepr(nl, """
(
(module 0 None ('top')
(input 'i' 0.2:5)
(output 'o' 1.0:4)
(io input 'ioa' 0.0:5)
(io output 'iob' 1.0:6)
(io inout 'ioc' 2.0:7)
)
(cell 0 0 (top
(input 'i' 2:5)
(output 'o' 1.0:4)
))
(cell 1 0 (instance 'gadget' 'my_gadget'
(param 'param' 'TEST')
(attr 'attr' 1234)
(input 'i' 0.2:5)
(output 'o' 0:4)
(io input 'ioa' 0.0:5)
(io output 'iob' 1.0:6)
(io inout 'ioc' 2.0:7)
))
)
""")
def test_nir_out_slice(self):
f = Fragment()
o = Signal(6)
f.add_subfragment(Instance("test",
o_o=o[:2],
), "t1")
f.add_subfragment(Instance("test",
o_o=o[2:4],
), "t2")
nl = build_netlist(f, [o])
self.assertRepr(nl, """
(
(module 0 None ('top')
(output 'o' (cat 1.0:2 2.0:2 2'd0))
)
(cell 0 0 (top
(output 'o' (cat 1.0:2 2.0:2 2'd0))
))
(cell 1 0 (instance 'test' 't1'
(output 'o' 0:2)
))
(cell 2 0 (instance 'test' 't2'
(output 'o' 0:2)
))
)
""")
def test_nir_out_concat(self):
f = Fragment()
o1 = Signal(4)
o2 = Signal(4)
f.add_subfragment(Instance("test",
o_o=Cat(o1, o2),
))
nl = build_netlist(f, [o1, o2])
self.assertRepr(nl, """
(
(module 0 None ('top')
(output 'o1' 1.0:4)
(output 'o2' 1.4:8)
)
(cell 0 0 (top
(output 'o1' 1.0:4)
(output 'o2' 1.4:8)
))
(cell 1 0 (instance 'test' 'U$0'
(output 'o' 0:8)
))
)
""")
def test_nir_io_slice(self):
f = Fragment()
io = IOPort(8)
f.add_subfragment(Instance("test",
i_i=io[:2],
o_o=io[2:4],
io_io=io[4:6],
), "t1")
nl = build_netlist(f, [])
self.assertRepr(nl, """
(
(module 0 None ('top')
(io inout 'io' 0.0:8)
)
(cell 0 0 (top))
(cell 1 0 (instance 'test' 't1'
(io input 'i' 0.0:2)
(io output 'o' 0.2:4)
(io inout 'io' 0.4:6)
))
)
""")
def test_nir_io_concat(self):
f = Fragment()
io1 = IOPort(4)
io2 = IOPort(4)
f.add_subfragment(Instance("test",
io_io=Cat(io1, io2),
))
nl = build_netlist(f, [io1, io2])
self.assertRepr(nl, """
(
(module 0 None ('top')
(io inout 'io1' 0.0:4)
(io inout 'io2' 1.0:4)
)
(cell 0 0 (top))
(cell 1 0 (instance 'test' 'U$0'
(io inout 'io' (io-cat 0.0:4 1.0:4))
))
)
""")
def test_nir_operator(self):
f = Fragment()
i = Signal(3)
o = Signal(4)
f.add_subfragment(Instance("gadget",
i_i=i.as_signed(),
o_o=o.as_signed(),
), "my_gadget")
nl = build_netlist(f, [i, o])
self.assertRepr(nl, """
(
(module 0 None ('top')
(input 'i' 0.2:5)
(output 'o' 1.0:4)
)
(cell 0 0 (top
(input 'i' 2:5)
(output 'o' 1.0:4)
))
(cell 1 0 (instance 'gadget' 'my_gadget'
(input 'i' 0.2:5)
(output 'o' 0:4)
))
)
""")
2024-02-11 04:07:45 -07:00
2024-03-05 02:34:58 -07:00
2024-02-11 04:07:45 -07:00
class NamesTestCase(FHDLTestCase):
def test_assign_names_to_signals(self):
i = Signal()
rst = Signal()
o1 = Signal()
o2 = Signal()
o3 = Signal()
o4 = Signal(name="")
i1 = Signal(name="i")
f = Fragment()
f.add_domains(cd_sync := ClockDomain())
f.add_domains(cd_sync_norst := ClockDomain(reset_less=True))
f.add_statements("comb", [o1.eq(0)])
f.add_statements("sync", [o2.eq(i1)])
f.add_statements("sync_norst", [o3.eq(i1)])
2024-02-11 04:07:45 -07:00
ports = {
"i": (i, PortDirection.Input),
"rst": (rst, PortDirection.Input),
"o1": (o1, PortDirection.Output),
"o2": (o2, PortDirection.Output),
"o3": (o3, PortDirection.Output),
"o4": (o4, PortDirection.Output),
2024-02-11 04:07:45 -07:00
}
design = f.prepare(ports)
self.assertEqual(design.fragments[design.fragment].signal_names, SignalDict([
(i, "i"),
(rst, "rst"),
(o1, "o1"),
(o2, "o2"),
(o3, "o3"),
# (o4, "o4"), # Signal has a private name.
(cd_sync.clk, "clk"),
(cd_sync.rst, "rst$7"),
(cd_sync_norst.clk, "sync_norst_clk"),
(i1, "i$8"),
]))
def test_wrong_private_unnamed_toplevel_ports(self):
s = Signal(name="")
f = Fragment()
with self.assertRaisesRegex(TypeError,
r"^Signals with private names cannot be used in unnamed top-level ports$"):
Design(f, ports=((None, s, None),), hierarchy=("top",))
def test_assign_names_to_fragments(self):
f = Fragment()
f.add_subfragment(a := Fragment())
f.add_subfragment(b := Fragment(), name="b")
2024-02-11 04:07:45 -07:00
design = Design(f, ports=(), hierarchy=("top",))
self.assertEqual(design.fragments[f].name, ("top",))
self.assertEqual(design.fragments[a].name, ("top", "U$0"))
self.assertEqual(design.fragments[b].name, ("top", "b"))
def test_assign_names_to_fragments_rename_top(self):
f = Fragment()
f.add_subfragment(a := Fragment())
f.add_subfragment(b := Fragment(), name="b")
2024-02-11 04:07:45 -07:00
design = Design(f, ports=[], hierarchy=("bench", "cpu"))
self.assertEqual(design.fragments[f].name, ("bench", "cpu",))
self.assertEqual(design.fragments[a].name, ("bench", "cpu", "U$0"))
self.assertEqual(design.fragments[b].name, ("bench", "cpu", "b"))
def test_assign_names_to_fragments_collide_with_signal(self):
f = Fragment()
f.add_subfragment(a_f := Fragment(), name="a")
2024-02-11 04:07:45 -07:00
a_s = Signal(name="a")
2024-02-11 04:07:45 -07:00
design = Design(f, ports=[("a", a_s, None)], hierarchy=("top",))
self.assertEqual(design.fragments[f].name, ("top",))
self.assertEqual(design.fragments[a_f].name, ("top", "a$1"))
def test_assign_names_to_fragments_duplicate(self):
f = Fragment()
f.add_subfragment(a1_f := Fragment(), name="a")
f.add_subfragment(a2_f := Fragment(), name="a")
design = Design(f, ports=[], hierarchy=("top",))
self.assertEqual(design.fragments[f].name, ("top",))
self.assertEqual(design.fragments[a1_f].name, ("top", "a"))
self.assertEqual(design.fragments[a2_f].name, ("top", "a$1"))
class ElaboratesTo(Elaboratable):
def __init__(self, lower):
self.lower = lower
def elaborate(self, platform):
return self.lower
class OriginsTestCase(FHDLTestCase):
def test_origins(self):
elab1 = ElaboratesTo(elab2 := ElaboratesTo(m := Module()))
frag = Fragment.get(elab1, platform=None)
self.assertEqual(len(frag.origins), 3)
self.assertIsInstance(frag.origins, tuple)
self.assertIs(frag.origins[0], elab1)
self.assertIs(frag.origins[1], elab2)
self.assertIs(frag.origins[2], m)
def test_origins_disable(self):
inst = Instance("test")
del inst.origins
elab = ElaboratesTo(inst)
frag = Fragment.get(elab, platform=None)
2024-02-12 07:11:42 -07:00
self.assertFalse(hasattr(frag, "_origins"))
class IOBufferTestCase(FHDLTestCase):
def test_nir_i(self):
port = IOPort(4)
2024-02-12 07:11:42 -07:00
i = Signal(4)
f = Fragment()
f.add_subfragment(IOBufferInstance(port, i=i))
nl = build_netlist(f, ports=[i])
2024-02-12 07:11:42 -07:00
self.assertRepr(nl, """
(
(module 0 None ('top')
(output 'i' 1.0:4)
(io input 'port' 0.0:4)
2024-02-12 07:11:42 -07:00
)
(cell 0 0 (top
(output 'i' 1.0:4)
))
(cell 1 0 (iob input 0.0:4))
2024-02-12 07:11:42 -07:00
)
""")
def test_nir_o(self):
port = IOPort(4)
2024-02-12 07:11:42 -07:00
o = Signal(4)
f = Fragment()
f.add_subfragment(IOBufferInstance(port, o=o))
nl = build_netlist(f, ports=[o])
2024-02-12 07:11:42 -07:00
self.assertRepr(nl, """
(
(module 0 None ('top')
(input 'o' 0.2:6)
(io output 'port' 0.0:4)
2024-02-12 07:11:42 -07:00
)
(cell 0 0 (top
(input 'o' 2:6)
2024-02-12 07:11:42 -07:00
))
(cell 1 0 (iob output 0.0:4 0.2:6 1))
2024-02-12 07:11:42 -07:00
)
""")
def test_nir_oe(self):
port = IOPort(4)
2024-02-12 07:11:42 -07:00
o = Signal(4)
oe = Signal()
f = Fragment()
f.add_subfragment(IOBufferInstance(port, o=o, oe=oe))
nl = build_netlist(f, ports=[ o, oe])
2024-02-12 07:11:42 -07:00
self.assertRepr(nl, """
(
(module 0 None ('top')
(input 'o' 0.2:6)
(input 'oe' 0.6)
(io output 'port' 0.0:4)
2024-02-12 07:11:42 -07:00
)
(cell 0 0 (top
(input 'o' 2:6)
(input 'oe' 6:7)
2024-02-12 07:11:42 -07:00
))
(cell 1 0 (iob output 0.0:4 0.2:6 0.6))
2024-02-12 07:11:42 -07:00
)
""")
def test_nir_io(self):
port = IOPort(4)
2024-02-12 07:11:42 -07:00
i = Signal(4)
o = Signal(4)
oe = Signal()
f = Fragment()
f.add_subfragment(IOBufferInstance(port, i=i, o=o, oe=oe))
nl = build_netlist(f, ports=[i, o, oe])
2024-02-12 07:11:42 -07:00
self.assertRepr(nl, """
(
(module 0 None ('top')
(input 'o' 0.2:6)
(input 'oe' 0.6)
2024-02-12 07:11:42 -07:00
(output 'i' 1.0:4)
(io inout 'port' 0.0:4)
2024-02-12 07:11:42 -07:00
)
(cell 0 0 (top
(input 'o' 2:6)
(input 'oe' 6:7)
(output 'i' 1.0:4)
2024-02-12 07:11:42 -07:00
))
(cell 1 0 (iob inout 0.0:4 0.2:6 0.6))
2024-02-12 07:11:42 -07:00
)
""")
def test_wrong_port(self):
port = Signal(4)
i = Signal(4)
with self.assertRaisesRegex(TypeError,
r"^Object \(sig port\) cannot be converted to an IO value"):
IOBufferInstance(port, i=i)
2024-02-12 07:11:42 -07:00
def test_wrong_i(self):
port = IOPort(4)
2024-02-12 07:11:42 -07:00
i = Signal()
with self.assertRaisesRegex(ValueError,
r"^'port' length \(4\) doesn't match 'i' length \(1\)"):
IOBufferInstance(port, i=i)
2024-02-12 07:11:42 -07:00
def test_wrong_o(self):
port = IOPort(4)
2024-02-12 07:11:42 -07:00
o = Signal()
with self.assertRaisesRegex(ValueError,
r"^'port' length \(4\) doesn't match 'o' length \(1\)"):
IOBufferInstance(port, o=o)
2024-02-12 07:11:42 -07:00
def test_wrong_oe(self):
port = IOPort(4)
2024-02-12 07:11:42 -07:00
o = Signal(4)
oe = Signal(4)
with self.assertRaisesRegex(ValueError,
r"^'oe' length \(4\) must be 1"):
IOBufferInstance(port, o=o, oe=oe)
2024-02-12 07:11:42 -07:00
def test_wrong_oe_without_o(self):
port = IOPort(4)
2024-02-12 07:11:42 -07:00
oe = Signal()
with self.assertRaisesRegex(ValueError,
r"^'oe' must not be used if 'o' is not used"):
IOBufferInstance(port, oe=oe)
def test_conflict(self):
port = IOPort(4)
i1 = Signal(4)
i2 = Signal(4)
f = Fragment()
f.add_subfragment(IOBufferInstance(port, i=i1))
f.add_subfragment(IOBufferInstance(port, i=i2))
with self.assertRaisesRegex(DriverConflict,
r"^Bit 0 of I/O port \(io-port port\) used twice, at .*test_hdl_ir.py:\d+ and "
r".*test_hdl_ir.py:\d+$"):
build_netlist(f, ports=[i1, i2])
class AssignTestCase(FHDLTestCase):
def test_simple(self):
s1 = Signal(8)
s2 = Signal(8)
f = Fragment()
f.add_statements(
"comb",
s1.eq(s2)
)
nl = build_netlist(f, ports=[s1, s2])
self.assertRepr(nl, """
(
(module 0 None ('top')
(input 's2' 0.2:10)
(output 's1' 0.2:10)
)
(cell 0 0 (top
(input 's2' 2:10)
(output 's1' 0.2:10)
))
)
""")
def test_simple_trunc(self):
s1 = Signal(8)
s2 = Signal(10)
f = Fragment()
f.add_statements(
"comb",
s1.eq(s2)
)
nl = build_netlist(f, ports=[s1, s2])
self.assertRepr(nl, """
(
(module 0 None ('top')
(input 's2' 0.2:12)
(output 's1' 0.2:10)
)
(cell 0 0 (top
(input 's2' 2:12)
(output 's1' 0.2:10)
))
)
""")
def test_simple_zext(self):
s1 = Signal(8)
s2 = Signal(6)
f = Fragment()
f.add_statements(
"comb",
s1.eq(s2)
)
nl = build_netlist(f, ports=[s1, s2])
self.assertRepr(nl, """
(
(module 0 None ('top')
(input 's2' 0.2:8)
(output 's1' (cat 0.2:8 2'd0))
)
(cell 0 0 (top
(input 's2' 2:8)
(output 's1' (cat 0.2:8 2'd0))
))
)
""")
def test_simple_sext(self):
s1 = Signal(8)
s2 = Signal(signed(6))
f = Fragment()
f.add_statements(
"comb",
s1.eq(s2)
)
nl = build_netlist(f, ports=[s1, s2])
self.assertRepr(nl, """
(
(module 0 None ('top')
(input 's2' 0.2:8)
(output 's1' (cat 0.2:8 0.7 0.7))
)
(cell 0 0 (top
(input 's2' 2:8)
(output 's1' (cat 0.2:8 0.7 0.7))
))
)
""")
def test_simple_slice(self):
s1 = Signal(8)
s2 = Signal(4)
f = Fragment()
f.add_statements(
"comb",
s1[2:6].eq(s2)
)
nl = build_netlist(f, ports=[s1, s2])
self.assertRepr(nl, """
(
(module 0 None ('top')
(input 's2' 0.2:6)
(output 's1' 1.0:8)
)
(cell 0 0 (top
(input 's2' 2:6)
(output 's1' 1.0:8)
))
(cell 1 0 (assignment_list 8'd0 (1 2:6 0.2:6)))
)
""")
def test_simple_part(self):
s1 = Signal(8)
s2 = Signal(4)
s3 = Signal(4)
f = Fragment()
f.add_statements(
"comb",
s1.bit_select(s3, 4).eq(s2)
)
nl = build_netlist(f, ports=[s1, s2, s3])
self.assertRepr(nl, """
(
(module 0 None ('top')
(input 's2' 0.2:6)
(input 's3' 0.6:10)
(output 's1' 10.0:8)
)
(cell 0 0 (top
(input 's2' 2:6)
(input 's3' 6:10)
(output 's1' 10.0:8)
))
(cell 1 0 (matches 0.6:10 0000))
(cell 2 0 (matches 0.6:10 0001))
(cell 3 0 (matches 0.6:10 0010))
(cell 4 0 (matches 0.6:10 0011))
(cell 5 0 (matches 0.6:10 0100))
(cell 6 0 (matches 0.6:10 0101))
(cell 7 0 (matches 0.6:10 0110))
(cell 8 0 (matches 0.6:10 0111))
(cell 9 0 (priority_match 1 (cat 1.0 2.0 3.0 4.0 5.0 6.0 7.0 8.0)))
(cell 10 0 (assignment_list 8'd0
(9.0 0:4 0.2:6)
(9.1 1:5 0.2:6)
(9.2 2:6 0.2:6)
(9.3 3:7 0.2:6)
(9.4 4:8 0.2:6)
(9.5 5:8 0.2:5)
(9.6 6:8 0.2:4)
(9.7 7:8 0.2)
))
)
""")
def test_simple_part_short(self):
s1 = Signal(8)
s2 = Signal(4)
s3 = Signal(2)
f = Fragment()
f.add_statements(
"comb",
s1.bit_select(s3, 4).eq(s2)
)
nl = build_netlist(f, ports=[s1, s2, s3])
self.assertRepr(nl, """
(
(module 0 None ('top')
(input 's2' 0.2:6)
(input 's3' 0.6:8)
(output 's1' 6.0:8)
)
(cell 0 0 (top
(input 's2' 2:6)
(input 's3' 6:8)
(output 's1' 6.0:8)
))
(cell 1 0 (matches 0.6:8 00))
(cell 2 0 (matches 0.6:8 01))
(cell 3 0 (matches 0.6:8 10))
(cell 4 0 (matches 0.6:8 11))
(cell 5 0 (priority_match 1 (cat 1.0 2.0 3.0 4.0)))
(cell 6 0 (assignment_list 8'd0
(5.0 0:4 0.2:6)
(5.1 1:5 0.2:6)
(5.2 2:6 0.2:6)
(5.3 3:7 0.2:6)
))
)
""")
def test_simple_part_word(self):
s1 = Signal(16)
s2 = Signal(4)
s3 = Signal(4)
f = Fragment()
f.add_statements(
"comb",
s1.word_select(s3, 4).eq(s2)
)
nl = build_netlist(f, ports=[s1, s2, s3])
self.assertRepr(nl, """
(
(module 0 None ('top')
(input 's2' 0.2:6)
(input 's3' 0.6:10)
(output 's1' 6.0:16)
)
(cell 0 0 (top
(input 's2' 2:6)
(input 's3' 6:10)
(output 's1' 6.0:16)
))
(cell 1 0 (matches 0.6:10 0000))
(cell 2 0 (matches 0.6:10 0001))
(cell 3 0 (matches 0.6:10 0010))
(cell 4 0 (matches 0.6:10 0011))
(cell 5 0 (priority_match 1 (cat 1.0 2.0 3.0 4.0)))
(cell 6 0 (assignment_list 16'd0
(5.0 0:4 0.2:6)
(5.1 4:8 0.2:6)
(5.2 8:12 0.2:6)
(5.3 12:16 0.2:6)
))
)
""")
def test_simple_part_word_misalign(self):
s1 = Signal(17)
s2 = Signal(4)
s3 = Signal(4)
f = Fragment()
f.add_statements(
"comb",
s1.word_select(s3, 4).eq(s2)
)
nl = build_netlist(f, ports=[s1, s2, s3])
self.assertRepr(nl, """
(
(module 0 None ('top')
(input 's2' 0.2:6)
(input 's3' 0.6:10)
(output 's1' 7.0:17)
)
(cell 0 0 (top
(input 's2' 2:6)
(input 's3' 6:10)
(output 's1' 7.0:17)
))
(cell 1 0 (matches 0.6:10 0000))
(cell 2 0 (matches 0.6:10 0001))
(cell 3 0 (matches 0.6:10 0010))
(cell 4 0 (matches 0.6:10 0011))
(cell 5 0 (matches 0.6:10 0100))
(cell 6 0 (priority_match 1 (cat 1.0 2.0 3.0 4.0 5.0)))
(cell 7 0 (assignment_list 17'd0
(6.0 0:4 0.2:6)
(6.1 4:8 0.2:6)
(6.2 8:12 0.2:6)
(6.3 12:16 0.2:6)
(6.4 16:17 0.2)
))
)
""")
def test_simple_concat(self):
s1 = Signal(4)
s2 = Signal(4)
s3 = Signal(4)
s4 = Signal(12)
f = Fragment()
f.add_statements(
"comb",
Cat(s1, s2, s3).eq(s4)
)
nl = build_netlist(f, ports=[s1, s2, s3, s4])
self.assertRepr(nl, """
(
(module 0 None ('top')
(input 's4' 0.2:14)
(output 's1' 0.2:6)
(output 's2' 0.6:10)
(output 's3' 0.10:14)
)
(cell 0 0 (top
(input 's4' 2:14)
(output 's1' 0.2:6)
(output 's2' 0.6:10)
(output 's3' 0.10:14)
))
)
""")
def test_simple_concat_narrow(self):
s1 = Signal(4)
s2 = Signal(4)
s3 = Signal(4)
s4 = Signal(signed(6))
f = Fragment()
f.add_statements(
"comb",
Cat(s1, s2, s3).eq(s4)
)
nl = build_netlist(f, ports=[s1, s2, s3, s4])
self.assertRepr(nl, """
(
(module 0 None ('top')
(input 's4' 0.2:8)
(output 's1' 0.2:6)
(output 's2' (cat 0.6:8 0.7 0.7))
(output 's3' (cat 0.7 0.7 0.7 0.7))
)
(cell 0 0 (top
(input 's4' 2:8)
(output 's1' 0.2:6)
(output 's2' (cat 0.6:8 0.7 0.7))
(output 's3' (cat 0.7 0.7 0.7 0.7))
))
)
""")
def test_simple_operator(self):
s1 = Signal(8)
s2 = Signal(8)
s3 = Signal(8)
f = Fragment()
f.add_statements("comb", [
s1.as_signed().eq(s3),
s2.as_unsigned().eq(s3),
])
nl = build_netlist(f, ports=[s1, s2, s3])
self.assertRepr(nl, """
(
(module 0 None ('top')
(input 's3' 0.2:10)
(output 's1' 0.2:10)
(output 's2' 0.2:10)
)
(cell 0 0 (top
(input 's3' 2:10)
(output 's1' 0.2:10)
(output 's2' 0.2:10)
))
)
""")
def test_simple_array(self):
s1 = Signal(8)
s2 = Signal(8)
s3 = Signal(8)
s4 = Signal(8)
s5 = Signal(8)
f = Fragment()
f.add_statements("comb", [
Array([s1, s2, s3])[s4].eq(s5),
])
nl = build_netlist(f, ports=[s1, s2, s3, s4, s5])
self.assertRepr(nl, """
(
(module 0 None ('top')
(input 's4' 0.2:10)
(input 's5' 0.10:18)
(output 's1' 5.0:8)
(output 's2' 6.0:8)
(output 's3' 7.0:8)
)
(cell 0 0 (top
(input 's4' 2:10)
(input 's5' 10:18)
(output 's1' 5.0:8)
(output 's2' 6.0:8)
(output 's3' 7.0:8)
))
(cell 1 0 (matches 0.2:10 00000000))
(cell 2 0 (matches 0.2:10 00000001))
(cell 3 0 (matches 0.2:10 00000010))
(cell 4 0 (priority_match 1 (cat 1.0 2.0 3.0)))
(cell 5 0 (assignment_list 8'd0 (4.0 0:8 0.10:18)))
(cell 6 0 (assignment_list 8'd0 (4.1 0:8 0.10:18)))
(cell 7 0 (assignment_list 8'd0 (4.2 0:8 0.10:18)))
)
""")
def test_switchvalue(self):
s1 = Signal(8)
s2 = Signal(8)
s3 = Signal(8)
s4 = Signal(8)
s5 = Signal(8)
s6 = Signal(8)
s7 = Signal(8)
f = Fragment()
f.add_statements("comb", [
SwitchValue(s5[:4], [
(1, s1),
((2, 3), s2),
((), s3),
('11--', s4),
]).eq(s6),
SwitchValue(s5[4:], [
(4, s1),
(5, s2),
(6, s3),
(None, s4),
]).eq(s7),
])
nl = build_netlist(f, ports=[s1, s2, s3, s4, s5, s6, s7])
self.assertRepr(nl, """
(
(module 0 None ('top')
(input 's5' 0.2:10)
(input 's6' 0.10:18)
(input 's7' 0.18:26)
(output 's1' 10.0:8)
(output 's2' 11.0:8)
(output 's3' 12.0:8)
(output 's4' 13.0:8)
)
(cell 0 0 (top
(input 's5' 2:10)
(input 's6' 10:18)
(input 's7' 18:26)
(output 's1' 10.0:8)
(output 's2' 11.0:8)
(output 's3' 12.0:8)
(output 's4' 13.0:8)
))
(cell 1 0 (matches 0.2:6 0001))
(cell 2 0 (matches 0.2:6 0010 0011))
(cell 3 0 (matches 0.2:6 ))
(cell 4 0 (matches 0.2:6 11--))
(cell 5 0 (priority_match 1 (cat 1.0 2.0 3.0 4.0)))
(cell 6 0 (matches 0.6:10 0100))
(cell 7 0 (matches 0.6:10 0101))
(cell 8 0 (matches 0.6:10 0110))
(cell 9 0 (priority_match 1 (cat 6.0 7.0 8.0 1'd1)))
(cell 10 0 (assignment_list 8'd0 (5.0 0:8 0.10:18) (9.0 0:8 0.18:26)))
(cell 11 0 (assignment_list 8'd0 (5.1 0:8 0.10:18) (9.1 0:8 0.18:26)))
(cell 12 0 (assignment_list 8'd0 (5.2 0:8 0.10:18) (9.2 0:8 0.18:26)))
(cell 13 0 (assignment_list 8'd0 (5.3 0:8 0.10:18) (9.3 0:8 0.18:26)))
)
""")
def test_mux_en(self):
s1 = Signal(8)
s2 = Signal(8)
s3 = Signal(8)
s4 = Signal(8)
en = Signal()
m = Module()
with m.If(en):
m.d.comb += Mux(s1, s2, s3).eq(s4)
nl = build_netlist(Fragment.get(m, None), ports=[s1, s2, s3, s4, en])
self.assertRepr(nl, """
(
(module 0 None ('top')
(input 's1' 0.2:10)
(input 's4' 0.10:18)
(input 'en' 0.18)
(output 's2' 6.0:8)
(output 's3' 5.0:8)
)
(cell 0 0 (top
(input 's1' 2:10)
(input 's4' 10:18)
(input 'en' 18:19)
(output 's2' 6.0:8)
(output 's3' 5.0:8)
))
(cell 1 0 (matches 0.18 1))
(cell 2 0 (priority_match 1 1.0))
(cell 3 0 (matches 0.2:10 00000000))
(cell 4 0 (priority_match 2.0 (cat 3.0 1'd1)))
(cell 5 0 (assignment_list 8'd0 (4.0 0:8 0.10:18)))
(cell 6 0 (assignment_list 8'd0 (4.1 0:8 0.10:18)))
)
""")
def test_sliced_slice(self):
s1 = Signal(12)
s2 = Signal(4)
f = Fragment()
f.add_statements(
"comb",
s1[1:11][2:6].eq(s2)
)
nl = build_netlist(f, ports=[s1, s2])
self.assertRepr(nl, """
(
(module 0 None ('top')
(input 's2' 0.2:6)
(output 's1' 1.0:12)
)
(cell 0 0 (top
(input 's2' 2:6)
(output 's1' 1.0:12)
))
(cell 1 0 (assignment_list 12'd0 (1 3:7 0.2:6)))
)
""")
def test_sliced_concat(self):
s1 = Signal(4)
s2 = Signal(4)
s3 = Signal(4)
s4 = Signal(4)
s5 = Signal(4)
s6 = Signal(8)
f = Fragment()
f.add_statements(
"comb",
Cat(s1, s2, s3, s4, s5)[5:14].eq(s6)
)
nl = build_netlist(f, ports=[s1, s2, s3, s4, s5, s6])
self.assertRepr(nl, """
(
(module 0 None ('top')
(input 's1' 0.2:6)
(input 's5' 0.6:10)
(input 's6' 0.10:18)
(output 's2' 1.0:4)
(output 's3' 0.13:17)
(output 's4' 2.0:4)
)
(cell 0 0 (top
(input 's1' 2:6)
(input 's5' 6:10)
(input 's6' 10:18)
(output 's2' 1.0:4)
(output 's3' 0.13:17)
(output 's4' 2.0:4)
))
(cell 1 0 (assignment_list 4'd0 (1 1:4 0.10:13)))
(cell 2 0 (assignment_list 4'd0 (1 0:2 (cat 0.17 1'd0))))
)
""")
def test_sliced_part(self):
s1 = Signal(8)
s2 = Signal(4)
s3 = Signal(4)
f = Fragment()
f.add_statements(
"comb",
s1.bit_select(s3, 6)[2:4].eq(s2)
)
nl = build_netlist(f, ports=[s1, s2, s3])
self.assertRepr(nl, """
(
(module 0 None ('top')
(input 's2' 0.2:6)
(input 's3' 0.6:10)
(output 's1' 10.0:8)
)
(cell 0 0 (top
(input 's2' 2:6)
(input 's3' 6:10)
(output 's1' 10.0:8)
))
(cell 1 0 (matches 0.6:10 0000))
(cell 2 0 (matches 0.6:10 0001))
(cell 3 0 (matches 0.6:10 0010))
(cell 4 0 (matches 0.6:10 0011))
(cell 5 0 (matches 0.6:10 0100))
(cell 6 0 (matches 0.6:10 0101))
(cell 7 0 (matches 0.6:10 0110))
(cell 8 0 (matches 0.6:10 0111))
(cell 9 0 (priority_match 1 (cat 1.0 2.0 3.0 4.0 5.0 6.0 7.0 8.0)))
(cell 10 0 (assignment_list 8'd0
(9.0 2:4 0.2:4)
(9.1 3:5 0.2:4)
(9.2 4:6 0.2:4)
(9.3 5:7 0.2:4)
(9.4 6:8 0.2:4)
(9.5 7:8 0.2)
))
)
""")
def test_sliced_part_word(self):
s1 = Signal(8)
s2 = Signal(4)
s3 = Signal(4)
f = Fragment()
f.add_statements(
"comb",
s1.word_select(s3, 4)[1:3].eq(s2)
)
nl = build_netlist(f, ports=[s1, s2, s3])
self.assertRepr(nl, """
(
(module 0 None ('top')
(input 's2' 0.2:6)
(input 's3' 0.6:10)
(output 's1' 4.0:8)
)
(cell 0 0 (top
(input 's2' 2:6)
(input 's3' 6:10)
(output 's1' 4.0:8)
))
(cell 1 0 (matches 0.6:10 0000))
(cell 2 0 (matches 0.6:10 0001))
(cell 3 0 (priority_match 1 (cat 1.0 2.0)))
(cell 4 0 (assignment_list 8'd0
(3.0 1:3 0.2:4)
(3.1 5:7 0.2:4)
))
)
""")
def test_sliced_array(self):
s1 = Signal(8)
s2 = Signal(8)
s3 = Signal(8)
s4 = Signal(8)
s5 = Signal(8)
f = Fragment()
f.add_statements("comb", [
Array([s1, s2, s3])[s4][2:7].eq(s5),
])
nl = build_netlist(f, ports=[s1, s2, s3, s4, s5])
self.assertRepr(nl, """
(
(module 0 None ('top')
(input 's4' 0.2:10)
(input 's5' 0.10:18)
(output 's1' 5.0:8)
(output 's2' 6.0:8)
(output 's3' 7.0:8)
)
(cell 0 0 (top
(input 's4' 2:10)
(input 's5' 10:18)
(output 's1' 5.0:8)
(output 's2' 6.0:8)
(output 's3' 7.0:8)
))
(cell 1 0 (matches 0.2:10 00000000))
(cell 2 0 (matches 0.2:10 00000001))
(cell 3 0 (matches 0.2:10 00000010))
(cell 4 0 (priority_match 1 (cat 1.0 2.0 3.0)))
(cell 5 0 (assignment_list 8'd0 (4.0 2:7 0.10:15)))
(cell 6 0 (assignment_list 8'd0 (4.1 2:7 0.10:15)))
(cell 7 0 (assignment_list 8'd0 (4.2 2:7 0.10:15)))
)
""")
def test_part_slice(self):
s1 = Signal(8)
s2 = Signal(4)
s3 = Signal(4)
f = Fragment()
f.add_statements(
"comb",
s1[1:7].bit_select(s3, 4).eq(s2)
)
nl = build_netlist(f, ports=[s1, s2, s3])
self.assertRepr(nl, """
(
(module 0 None ('top')
(input 's2' 0.2:6)
(input 's3' 0.6:10)
(output 's1' 8.0:8)
)
(cell 0 0 (top
(input 's2' 2:6)
(input 's3' 6:10)
(output 's1' 8.0:8)
))
(cell 1 0 (matches 0.6:10 0000))
(cell 2 0 (matches 0.6:10 0001))
(cell 3 0 (matches 0.6:10 0010))
(cell 4 0 (matches 0.6:10 0011))
(cell 5 0 (matches 0.6:10 0100))
(cell 6 0 (matches 0.6:10 0101))
(cell 7 0 (priority_match 1 (cat 1.0 2.0 3.0 4.0 5.0 6.0)))
(cell 8 0 (assignment_list 8'd0
(7.0 1:5 0.2:6)
(7.1 2:6 0.2:6)
(7.2 3:7 0.2:6)
(7.3 4:7 0.2:5)
(7.4 5:7 0.2:4)
(7.5 6:7 0.2)
))
)
""")
def test_sliced_part_slice(self):
s1 = Signal(12)
s2 = Signal(4)
s3 = Signal(4)
f = Fragment()
f.add_statements(
"comb",
s1[3:9].bit_select(s3, 4)[1:3].eq(s2)
)
nl = build_netlist(f, ports=[s1, s2, s3])
self.assertRepr(nl, """
(
(module 0 None ('top')
(input 's2' 0.2:6)
(input 's3' 0.6:10)
(output 's1' 8.0:12)
)
(cell 0 0 (top
(input 's2' 2:6)
(input 's3' 6:10)
(output 's1' 8.0:12)
))
(cell 1 0 (matches 0.6:10 0000))
(cell 2 0 (matches 0.6:10 0001))
(cell 3 0 (matches 0.6:10 0010))
(cell 4 0 (matches 0.6:10 0011))
(cell 5 0 (matches 0.6:10 0100))
(cell 6 0 (matches 0.6:10 0101))
(cell 7 0 (priority_match 1 (cat 1.0 2.0 3.0 4.0 5.0 6.0)))
(cell 8 0 (assignment_list 12'd0
(7.0 4:6 0.2:4)
(7.1 5:7 0.2:4)
(7.2 6:8 0.2:4)
(7.3 7:9 0.2:4)
(7.4 8:9 0.2)
))
)
""")
def test_sliced_operator(self):
s1 = Signal(8)
s2 = Signal(8)
s3 = Signal(8)
f = Fragment()
f.add_statements("comb", [
s1.as_signed()[2:7].eq(s3),
s2.as_unsigned()[2:7].eq(s3),
])
nl = build_netlist(f, ports=[s1, s2, s3])
self.assertRepr(nl, """
(
(module 0 None ('top')
(input 's3' 0.2:10)
(output 's1' 1.0:8)
(output 's2' 2.0:8)
)
(cell 0 0 (top
(input 's3' 2:10)
(output 's1' 1.0:8)
(output 's2' 2.0:8)
))
(cell 1 0 (assignment_list 8'd0 (1 2:7 0.2:7)))
(cell 2 0 (assignment_list 8'd0 (1 2:7 0.2:7)))
)
""")
2024-03-05 02:34:58 -07:00
class RhsTestCase(FHDLTestCase):
def test_const(self):
o1 = Signal(8)
o2 = Signal(8)
m = Module()
m.d.comb += o1.eq(13)
m.d.comb += o2.eq(-13)
nl = build_netlist(Fragment.get(m, None), [o1, o2])
self.assertRepr(nl, """
(
(module 0 None ('top')
(output 'o1' 8'd13)
(output 'o2' 8'd243)
)
(cell 0 0 (top
(output 'o1' 8'd13)
(output 'o2' 8'd243)
))
)
""")
def test_operator_signed(self):
o1 = Signal(8)
o2 = Signal(8)
i1 = Signal(unsigned(4))
i2 = Signal(signed(4))
m = Module()
m.d.comb += o1.eq(i1.as_signed())
m.d.comb += o2.eq(i2.as_unsigned())
nl = build_netlist(Fragment.get(m, None), [i1, i2, o1, o2])
self.assertRepr(nl, """
(
(module 0 None ('top')
(input 'i1' 0.2:6)
(input 'i2' 0.6:10)
(output 'o1' (cat 0.2:6 0.5 0.5 0.5 0.5))
(output 'o2' (cat 0.6:10 4'd0))
)
(cell 0 0 (top
(input 'i1' 2:6)
(input 'i2' 6:10)
(output 'o1' (cat 0.2:6 0.5 0.5 0.5 0.5))
(output 'o2' (cat 0.6:10 4'd0))
))
)
""")
def test_operator_unary(self):
o1 = Signal(8)
o2 = Signal(8)
o3 = Signal(8)
o4 = Signal(8)
o5 = Signal(8)
o6 = Signal(8)
o7 = Signal(2)
o8 = Signal(2)
o9 = Signal(2)
o10 = Signal(2)
o11 = Signal(2)
o12 = Signal(2)
o13 = Signal(2)
o14 = Signal(2)
i1 = Signal(unsigned(4))
i2 = Signal(signed(4))
m = Module()
m.d.comb += o1.eq(+i1)
m.d.comb += o2.eq(+i2)
m.d.comb += o3.eq(-i1)
m.d.comb += o4.eq(-i2)
m.d.comb += o5.eq(~i1)
m.d.comb += o6.eq(~i2)
m.d.comb += o7.eq(i1.all())
m.d.comb += o8.eq(i2.all())
m.d.comb += o9.eq(i1.any())
m.d.comb += o10.eq(i2.any())
m.d.comb += o11.eq(i1.xor())
m.d.comb += o12.eq(i2.xor())
m.d.comb += o13.eq(i1.bool())
m.d.comb += o14.eq(i2.bool())
nl = build_netlist(Fragment.get(m, None),
[i1, i2, o1, o2, o3, o4, o5, o6, o7, o8, o9, o10, o11, o12, o13, o14])
self.assertRepr(nl, """
(
(module 0 None ('top')
(input 'i1' 0.2:6)
(input 'i2' 0.6:10)
(output 'o1' (cat 0.2:6 4'd0))
(output 'o2' (cat 0.6:10 0.9 0.9 0.9 0.9))
(output 'o3' (cat 1.0:5 1.4 1.4 1.4))
(output 'o4' (cat 2.0:5 2.4 2.4 2.4))
(output 'o5' (cat 3.0:4 4'd0))
(output 'o6' (cat 4.0:4 4.3 4.3 4.3 4.3))
(output 'o7' (cat 5.0 1'd0))
(output 'o8' (cat 6.0 1'd0))
(output 'o9' (cat 7.0 1'd0))
(output 'o10' (cat 8.0 1'd0))
(output 'o11' (cat 9.0 1'd0))
(output 'o12' (cat 10.0 1'd0))
(output 'o13' (cat 11.0 1'd0))
(output 'o14' (cat 12.0 1'd0))
)
(cell 0 0 (top
(input 'i1' 2:6)
(input 'i2' 6:10)
(output 'o1' (cat 0.2:6 4'd0))
(output 'o2' (cat 0.6:10 0.9 0.9 0.9 0.9))
(output 'o3' (cat 1.0:5 1.4 1.4 1.4))
(output 'o4' (cat 2.0:5 2.4 2.4 2.4))
(output 'o5' (cat 3.0:4 4'd0))
(output 'o6' (cat 4.0:4 4.3 4.3 4.3 4.3))
(output 'o7' (cat 5.0 1'd0))
(output 'o8' (cat 6.0 1'd0))
(output 'o9' (cat 7.0 1'd0))
(output 'o10' (cat 8.0 1'd0))
(output 'o11' (cat 9.0 1'd0))
(output 'o12' (cat 10.0 1'd0))
(output 'o13' (cat 11.0 1'd0))
(output 'o14' (cat 12.0 1'd0))
))
(cell 1 0 (- (cat 0.2:6 1'd0)))
(cell 2 0 (- (cat 0.6:10 0.9)))
(cell 3 0 (~ 0.2:6))
(cell 4 0 (~ 0.6:10))
(cell 5 0 (r& 0.2:6))
(cell 6 0 (r& 0.6:10))
(cell 7 0 (r| 0.2:6))
(cell 8 0 (r| 0.6:10))
(cell 9 0 (r^ 0.2:6))
(cell 10 0 (r^ 0.6:10))
(cell 11 0 (b 0.2:6))
(cell 12 0 (b 0.6:10))
)
""")
def test_operator_binary_bitwise(self):
i8u = Signal(8)
i9u = Signal(9)
i8s = Signal(signed(8))
i9s = Signal(signed(9))
i1 = Signal()
o1 = Signal(12)
o2 = Signal(12)
o3 = Signal(12)
o4 = Signal(12)
o5 = Signal(12)
o6 = Signal(12)
o7 = Signal(12)
o8 = Signal(12)
o9 = Signal(12)
o10 = Signal(12)
o11 = Signal(12)
o12 = Signal(12)
o13 = Signal(12)
o14 = Signal(12)
o15 = Signal(12)
o16 = Signal(12)
m = Module()
m.d.comb += o1.eq(i8u & i8u)
m.d.comb += o2.eq(i8u & i9u)
m.d.comb += o3.eq(i8u & i8s)
m.d.comb += o4.eq(i8u & i9s)
m.d.comb += o5.eq(i9u | i8u)
m.d.comb += o6.eq(i9u | i9u)
m.d.comb += o7.eq(i9u | i8s)
m.d.comb += o8.eq(i9u | i9s)
m.d.comb += o9.eq(i8s ^ i8u)
m.d.comb += o10.eq(i8s ^ i9u)
m.d.comb += o11.eq(i8s ^ i8s)
m.d.comb += o12.eq(i8s ^ i9s)
m.d.comb += o13.eq(Mux(i1, i9s, i8u))
m.d.comb += o14.eq(Mux(i1, i9s, i9u))
m.d.comb += o15.eq(Mux(i1, i9s, i8s))
m.d.comb += o16.eq(Mux(i1, i9s, i9s))
nl = build_netlist(Fragment.get(m, None), [
i8u, i9u, i8s, i9s, i1,
o1, o2, o3, o4, o5, o6, o7, o8, o9, o10, o11, o12, o13, o14, o15, o16,
])
self.assertRepr(nl, """
(
(module 0 None ('top')
(input 'i8u' 0.2:10)
(input 'i9u' 0.10:19)
(input 'i8s' 0.19:27)
(input 'i9s' 0.27:36)
(input 'i1' 0.36)
(output 'o1' (cat 1.0:8 4'd0))
(output 'o2' (cat 2.0:9 3'd0))
(output 'o3' (cat 3.0:9 3.8 3.8 3.8))
(output 'o4' (cat 4.0:9 4.8 4.8 4.8))
(output 'o5' (cat 5.0:9 3'd0))
(output 'o6' (cat 6.0:9 3'd0))
(output 'o7' (cat 7.0:10 7.9 7.9))
(output 'o8' (cat 8.0:10 8.9 8.9))
(output 'o9' (cat 9.0:9 9.8 9.8 9.8))
(output 'o10' (cat 10.0:10 10.9 10.9))
(output 'o11' (cat 11.0:8 11.7 11.7 11.7 11.7))
(output 'o12' (cat 12.0:9 12.8 12.8 12.8))
(output 'o13' (cat 13.0:9 13.8 13.8 13.8))
(output 'o14' (cat 14.0:10 14.9 14.9))
(output 'o15' (cat 15.0:9 15.8 15.8 15.8))
(output 'o16' (cat 16.0:9 16.8 16.8 16.8))
)
(cell 0 0 (top
(input 'i8u' 2:10)
(input 'i9u' 10:19)
(input 'i8s' 19:27)
(input 'i9s' 27:36)
(input 'i1' 36:37)
(output 'o1' (cat 1.0:8 4'd0))
(output 'o2' (cat 2.0:9 3'd0))
(output 'o3' (cat 3.0:9 3.8 3.8 3.8))
(output 'o4' (cat 4.0:9 4.8 4.8 4.8))
(output 'o5' (cat 5.0:9 3'd0))
(output 'o6' (cat 6.0:9 3'd0))
(output 'o7' (cat 7.0:10 7.9 7.9))
(output 'o8' (cat 8.0:10 8.9 8.9))
(output 'o9' (cat 9.0:9 9.8 9.8 9.8))
(output 'o10' (cat 10.0:10 10.9 10.9))
(output 'o11' (cat 11.0:8 11.7 11.7 11.7 11.7))
(output 'o12' (cat 12.0:9 12.8 12.8 12.8))
(output 'o13' (cat 13.0:9 13.8 13.8 13.8))
(output 'o14' (cat 14.0:10 14.9 14.9))
(output 'o15' (cat 15.0:9 15.8 15.8 15.8))
(output 'o16' (cat 16.0:9 16.8 16.8 16.8))
))
(cell 1 0 (& 0.2:10 0.2:10))
(cell 2 0 (& (cat 0.2:10 1'd0) 0.10:19))
(cell 3 0 (& (cat 0.2:10 1'd0) (cat 0.19:27 0.26)))
(cell 4 0 (& (cat 0.2:10 1'd0) 0.27:36))
(cell 5 0 (| 0.10:19 (cat 0.2:10 1'd0)))
(cell 6 0 (| 0.10:19 0.10:19))
(cell 7 0 (| (cat 0.10:19 1'd0) (cat 0.19:27 0.26 0.26)))
(cell 8 0 (| (cat 0.10:19 1'd0) (cat 0.27:36 0.35)))
(cell 9 0 (^ (cat 0.19:27 0.26) (cat 0.2:10 1'd0)))
(cell 10 0 (^ (cat 0.19:27 0.26 0.26) (cat 0.10:19 1'd0)))
(cell 11 0 (^ 0.19:27 0.19:27))
(cell 12 0 (^ (cat 0.19:27 0.26) 0.27:36))
(cell 13 0 (m 0.36 0.27:36 (cat 0.2:10 1'd0)))
(cell 14 0 (m 0.36 (cat 0.27:36 0.35) (cat 0.10:19 1'd0)))
(cell 15 0 (m 0.36 0.27:36 (cat 0.19:27 0.26)))
(cell 16 0 (m 0.36 0.27:36 0.27:36))
)
""")
def test_operator_binary_add(self):
i8u = Signal(8)
i9u = Signal(9)
i8s = Signal(signed(8))
i9s = Signal(signed(9))
o1 = Signal(12)
o2 = Signal(12)
o3 = Signal(12)
o4 = Signal(12)
o5 = Signal(12)
o6 = Signal(12)
o7 = Signal(12)
o8 = Signal(12)
o9 = Signal(12)
o10 = Signal(12)
o11 = Signal(12)
o12 = Signal(12)
o13 = Signal(12)
o14 = Signal(12)
o15 = Signal(12)
o16 = Signal(12)
m = Module()
m.d.comb += o1.eq(i8u + i8u)
m.d.comb += o2.eq(i8u + i9u)
m.d.comb += o3.eq(i8u + i8s)
m.d.comb += o4.eq(i8u + i9s)
m.d.comb += o5.eq(i9u + i8u)
m.d.comb += o6.eq(i9u + i9u)
m.d.comb += o7.eq(i9u + i8s)
m.d.comb += o8.eq(i9u + i9s)
m.d.comb += o9.eq(i8s + i8u)
m.d.comb += o10.eq(i8s + i9u)
m.d.comb += o11.eq(i8s + i8s)
m.d.comb += o12.eq(i8s + i9s)
m.d.comb += o13.eq(i9s + i8u)
m.d.comb += o14.eq(i9s + i9u)
m.d.comb += o15.eq(i9s + i8s)
m.d.comb += o16.eq(i9s + i9s)
nl = build_netlist(Fragment.get(m, None), [
i8u, i9u, i8s, i9s,
o1, o2, o3, o4, o5, o6, o7, o8, o9, o10, o11, o12, o13, o14, o15, o16,
])
self.assertRepr(nl, """
(
(module 0 None ('top')
(input 'i8u' 0.2:10)
(input 'i9u' 0.10:19)
(input 'i8s' 0.19:27)
(input 'i9s' 0.27:36)
(output 'o1' (cat 1.0:9 3'd0))
(output 'o2' (cat 2.0:10 2'd0))
(output 'o3' (cat 3.0:10 3.9 3.9))
(output 'o4' (cat 4.0:10 4.9 4.9))
(output 'o5' (cat 5.0:10 2'd0))
(output 'o6' (cat 6.0:10 2'd0))
(output 'o7' (cat 7.0:11 7.10))
(output 'o8' (cat 8.0:11 8.10))
(output 'o9' (cat 9.0:10 9.9 9.9))
(output 'o10' (cat 10.0:11 10.10))
(output 'o11' (cat 11.0:9 11.8 11.8 11.8))
(output 'o12' (cat 12.0:10 12.9 12.9))
(output 'o13' (cat 13.0:10 13.9 13.9))
(output 'o14' (cat 14.0:11 14.10))
(output 'o15' (cat 15.0:10 15.9 15.9))
(output 'o16' (cat 16.0:10 16.9 16.9))
)
(cell 0 0 (top
(input 'i8u' 2:10)
(input 'i9u' 10:19)
(input 'i8s' 19:27)
(input 'i9s' 27:36)
(output 'o1' (cat 1.0:9 3'd0))
(output 'o2' (cat 2.0:10 2'd0))
(output 'o3' (cat 3.0:10 3.9 3.9))
(output 'o4' (cat 4.0:10 4.9 4.9))
(output 'o5' (cat 5.0:10 2'd0))
(output 'o6' (cat 6.0:10 2'd0))
(output 'o7' (cat 7.0:11 7.10))
(output 'o8' (cat 8.0:11 8.10))
(output 'o9' (cat 9.0:10 9.9 9.9))
(output 'o10' (cat 10.0:11 10.10))
(output 'o11' (cat 11.0:9 11.8 11.8 11.8))
(output 'o12' (cat 12.0:10 12.9 12.9))
(output 'o13' (cat 13.0:10 13.9 13.9))
(output 'o14' (cat 14.0:11 14.10))
(output 'o15' (cat 15.0:10 15.9 15.9))
(output 'o16' (cat 16.0:10 16.9 16.9))
))
(cell 1 0 (+ (cat 0.2:10 1'd0) (cat 0.2:10 1'd0)))
(cell 2 0 (+ (cat 0.2:10 2'd0) (cat 0.10:19 1'd0)))
(cell 3 0 (+ (cat 0.2:10 2'd0) (cat 0.19:27 0.26 0.26)))
(cell 4 0 (+ (cat 0.2:10 2'd0) (cat 0.27:36 0.35)))
(cell 5 0 (+ (cat 0.10:19 1'd0) (cat 0.2:10 2'd0)))
(cell 6 0 (+ (cat 0.10:19 1'd0) (cat 0.10:19 1'd0)))
(cell 7 0 (+ (cat 0.10:19 2'd0) (cat 0.19:27 0.26 0.26 0.26)))
(cell 8 0 (+ (cat 0.10:19 2'd0) (cat 0.27:36 0.35 0.35)))
(cell 9 0 (+ (cat 0.19:27 0.26 0.26) (cat 0.2:10 2'd0)))
(cell 10 0 (+ (cat 0.19:27 0.26 0.26 0.26) (cat 0.10:19 2'd0)))
(cell 11 0 (+ (cat 0.19:27 0.26) (cat 0.19:27 0.26)))
(cell 12 0 (+ (cat 0.19:27 0.26 0.26) (cat 0.27:36 0.35)))
(cell 13 0 (+ (cat 0.27:36 0.35) (cat 0.2:10 2'd0)))
(cell 14 0 (+ (cat 0.27:36 0.35 0.35) (cat 0.10:19 2'd0)))
(cell 15 0 (+ (cat 0.27:36 0.35) (cat 0.19:27 0.26 0.26)))
(cell 16 0 (+ (cat 0.27:36 0.35) (cat 0.27:36 0.35)))
)
""")
def test_operator_binary_sub(self):
i8u = Signal(8)
i9u = Signal(9)
i8s = Signal(signed(8))
i9s = Signal(signed(9))
o1 = Signal(12)
o2 = Signal(12)
o3 = Signal(12)
o4 = Signal(12)
o5 = Signal(12)
o6 = Signal(12)
o7 = Signal(12)
o8 = Signal(12)
o9 = Signal(12)
o10 = Signal(12)
o11 = Signal(12)
o12 = Signal(12)
o13 = Signal(12)
o14 = Signal(12)
o15 = Signal(12)
o16 = Signal(12)
m = Module()
m.d.comb += o1.eq(i8u - i8u)
m.d.comb += o2.eq(i8u - i9u)
m.d.comb += o3.eq(i8u - i8s)
m.d.comb += o4.eq(i8u - i9s)
m.d.comb += o5.eq(i9u - i8u)
m.d.comb += o6.eq(i9u - i9u)
m.d.comb += o7.eq(i9u - i8s)
m.d.comb += o8.eq(i9u - i9s)
m.d.comb += o9.eq(i8s - i8u)
m.d.comb += o10.eq(i8s - i9u)
m.d.comb += o11.eq(i8s - i8s)
m.d.comb += o12.eq(i8s - i9s)
m.d.comb += o13.eq(i9s - i8u)
m.d.comb += o14.eq(i9s - i9u)
m.d.comb += o15.eq(i9s - i8s)
m.d.comb += o16.eq(i9s - i9s)
nl = build_netlist(Fragment.get(m, None), [
i8u, i9u, i8s, i9s,
o1, o2, o3, o4, o5, o6, o7, o8, o9, o10, o11, o12, o13, o14, o15, o16,
])
self.assertRepr(nl, """
(
(module 0 None ('top')
(input 'i8u' 0.2:10)
(input 'i9u' 0.10:19)
(input 'i8s' 0.19:27)
(input 'i9s' 0.27:36)
(output 'o1' (cat 1.0:9 1.8 1.8 1.8))
(output 'o2' (cat 2.0:10 2.9 2.9))
(output 'o3' (cat 3.0:10 3.9 3.9))
(output 'o4' (cat 4.0:10 4.9 4.9))
(output 'o5' (cat 5.0:10 5.9 5.9))
(output 'o6' (cat 6.0:10 6.9 6.9))
(output 'o7' (cat 7.0:11 7.10))
(output 'o8' (cat 8.0:11 8.10))
(output 'o9' (cat 9.0:10 9.9 9.9))
(output 'o10' (cat 10.0:11 10.10))
(output 'o11' (cat 11.0:9 11.8 11.8 11.8))
(output 'o12' (cat 12.0:10 12.9 12.9))
(output 'o13' (cat 13.0:10 13.9 13.9))
(output 'o14' (cat 14.0:11 14.10))
(output 'o15' (cat 15.0:10 15.9 15.9))
(output 'o16' (cat 16.0:10 16.9 16.9))
)
(cell 0 0 (top
(input 'i8u' 2:10)
(input 'i9u' 10:19)
(input 'i8s' 19:27)
(input 'i9s' 27:36)
(output 'o1' (cat 1.0:9 1.8 1.8 1.8))
(output 'o2' (cat 2.0:10 2.9 2.9))
(output 'o3' (cat 3.0:10 3.9 3.9))
(output 'o4' (cat 4.0:10 4.9 4.9))
(output 'o5' (cat 5.0:10 5.9 5.9))
(output 'o6' (cat 6.0:10 6.9 6.9))
(output 'o7' (cat 7.0:11 7.10))
(output 'o8' (cat 8.0:11 8.10))
(output 'o9' (cat 9.0:10 9.9 9.9))
(output 'o10' (cat 10.0:11 10.10))
(output 'o11' (cat 11.0:9 11.8 11.8 11.8))
(output 'o12' (cat 12.0:10 12.9 12.9))
(output 'o13' (cat 13.0:10 13.9 13.9))
(output 'o14' (cat 14.0:11 14.10))
(output 'o15' (cat 15.0:10 15.9 15.9))
(output 'o16' (cat 16.0:10 16.9 16.9))
))
(cell 1 0 (- (cat 0.2:10 1'd0) (cat 0.2:10 1'd0)))
(cell 2 0 (- (cat 0.2:10 2'd0) (cat 0.10:19 1'd0)))
(cell 3 0 (- (cat 0.2:10 2'd0) (cat 0.19:27 0.26 0.26)))
(cell 4 0 (- (cat 0.2:10 2'd0) (cat 0.27:36 0.35)))
(cell 5 0 (- (cat 0.10:19 1'd0) (cat 0.2:10 2'd0)))
(cell 6 0 (- (cat 0.10:19 1'd0) (cat 0.10:19 1'd0)))
(cell 7 0 (- (cat 0.10:19 2'd0) (cat 0.19:27 0.26 0.26 0.26)))
(cell 8 0 (- (cat 0.10:19 2'd0) (cat 0.27:36 0.35 0.35)))
(cell 9 0 (- (cat 0.19:27 0.26 0.26) (cat 0.2:10 2'd0)))
(cell 10 0 (- (cat 0.19:27 0.26 0.26 0.26) (cat 0.10:19 2'd0)))
(cell 11 0 (- (cat 0.19:27 0.26) (cat 0.19:27 0.26)))
(cell 12 0 (- (cat 0.19:27 0.26 0.26) (cat 0.27:36 0.35)))
(cell 13 0 (- (cat 0.27:36 0.35) (cat 0.2:10 2'd0)))
(cell 14 0 (- (cat 0.27:36 0.35 0.35) (cat 0.10:19 2'd0)))
(cell 15 0 (- (cat 0.27:36 0.35) (cat 0.19:27 0.26 0.26)))
(cell 16 0 (- (cat 0.27:36 0.35) (cat 0.27:36 0.35)))
)
""")
def test_operator_binary_mul(self):
i8u = Signal(8)
i8s = Signal(signed(8))
i10u = Signal(10)
i10s = Signal(signed(10))
o1 = Signal(24)
o2 = Signal(24)
o3 = Signal(24)
o4 = Signal(24)
m = Module()
m.d.comb += o1.eq(i8u * i10u)
m.d.comb += o2.eq(i8u * i10s)
m.d.comb += o3.eq(i8s * i10u)
m.d.comb += o4.eq(i8s * i10s)
nl = build_netlist(Fragment.get(m, None), [
i8u, i8s, i10u, i10s,
o1, o2, o3, o4,
])
self.assertRepr(nl, """
(
(module 0 None ('top')
(input 'i8u' 0.2:10)
(input 'i8s' 0.10:18)
(input 'i10u' 0.18:28)
(input 'i10s' 0.28:38)
(output 'o1' (cat 1.0:18 6'd0))
(output 'o2' (cat 2.0:18 2.17 2.17 2.17 2.17 2.17 2.17))
(output 'o3' (cat 3.0:18 3.17 3.17 3.17 3.17 3.17 3.17))
(output 'o4' (cat 4.0:18 4.17 4.17 4.17 4.17 4.17 4.17))
)
(cell 0 0 (top
(input 'i8u' 2:10)
(input 'i8s' 10:18)
(input 'i10u' 18:28)
(input 'i10s' 28:38)
(output 'o1' (cat 1.0:18 6'd0))
(output 'o2' (cat 2.0:18 2.17 2.17 2.17 2.17 2.17 2.17))
(output 'o3' (cat 3.0:18 3.17 3.17 3.17 3.17 3.17 3.17))
(output 'o4' (cat 4.0:18 4.17 4.17 4.17 4.17 4.17 4.17))
))
(cell 1 0 (* (cat 0.2:10 10'd0) (cat 0.18:28 8'd0)))
(cell 2 0 (* (cat 0.2:10 10'd0) (cat 0.28:38 0.37 0.37 0.37 0.37 0.37 0.37 0.37 0.37)))
(cell 3 0 (* (cat 0.10:18 0.17 0.17 0.17 0.17 0.17 0.17 0.17 0.17 0.17 0.17) (cat 0.18:28 8'd0)))
(cell 4 0 (* (cat 0.10:18 0.17 0.17 0.17 0.17 0.17 0.17 0.17 0.17 0.17 0.17) (cat 0.28:38 0.37 0.37 0.37 0.37 0.37 0.37 0.37 0.37)))
)
""")
def test_operator_binary_divmod(self):
i8u = Signal(8)
i8s = Signal(signed(8))
i6u = Signal(6)
i6s = Signal(signed(6))
m = Module()
o1 = Signal(10)
o2 = Signal(10)
o3 = Signal(10)
o4 = Signal(10)
o5 = Signal(10)
o6 = Signal(10)
o7 = Signal(10)
o8 = Signal(10)
o9 = Signal(10)
o10 = Signal(10)
o11 = Signal(10)
o12 = Signal(10)
o13 = Signal(10)
o14 = Signal(10)
o15 = Signal(10)
o16 = Signal(10)
m.d.comb += o1.eq(i8u // i6u)
m.d.comb += o2.eq(i8u % i6u)
m.d.comb += o3.eq(i8u // i6s)
m.d.comb += o4.eq(i8u % i6s)
m.d.comb += o5.eq(i8s // i6u)
m.d.comb += o6.eq(i8s % i6u)
m.d.comb += o7.eq(i8s // i6s)
m.d.comb += o8.eq(i8s % i6s)
m.d.comb += o9.eq(i6u // i8u)
m.d.comb += o10.eq(i6u % i8u)
m.d.comb += o11.eq(i6u // i8s)
m.d.comb += o12.eq(i6u % i8s)
m.d.comb += o13.eq(i6s // i8u)
m.d.comb += o14.eq(i6s % i8u)
m.d.comb += o15.eq(i6s // i8s)
m.d.comb += o16.eq(i6s % i8s)
nl = build_netlist(Fragment.get(m, None), [
i8u, i8s, i6u, i6s,
o1, o2, o3, o4, o5, o6, o7, o8, o9, o10, o11, o12, o13, o14, o15, o16,
])
self.assertRepr(nl, """
(
(module 0 None ('top')
(input 'i8u' 0.2:10)
(input 'i8s' 0.10:18)
(input 'i6u' 0.18:24)
(input 'i6s' 0.24:30)
(output 'o1' (cat 1.0:8 2'd0))
(output 'o2' (cat 2.0:6 4'd0))
(output 'o3' (cat 3.0:9 3.8))
(output 'o4' (cat 4.0:6 4.5 4.5 4.5 4.5))
(output 'o5' (cat 5.0:8 5.7 5.7))
(output 'o6' (cat 6.0:6 4'd0))
(output 'o7' (cat 7.0:9 7.8))
(output 'o8' (cat 8.0:6 8.5 8.5 8.5 8.5))
(output 'o9' (cat 9.0:6 4'd0))
(output 'o10' (cat 10.0:8 2'd0))
(output 'o11' (cat 11.0:7 11.6 11.6 11.6))
(output 'o12' (cat 12.0:8 12.7 12.7))
(output 'o13' (cat 13.0:6 13.5 13.5 13.5 13.5))
(output 'o14' (cat 14.0:8 2'd0))
(output 'o15' (cat 15.0:7 15.6 15.6 15.6))
(output 'o16' (cat 16.0:8 16.7 16.7))
)
(cell 0 0 (top
(input 'i8u' 2:10)
(input 'i8s' 10:18)
(input 'i6u' 18:24)
(input 'i6s' 24:30)
(output 'o1' (cat 1.0:8 2'd0))
(output 'o2' (cat 2.0:6 4'd0))
(output 'o3' (cat 3.0:9 3.8))
(output 'o4' (cat 4.0:6 4.5 4.5 4.5 4.5))
(output 'o5' (cat 5.0:8 5.7 5.7))
(output 'o6' (cat 6.0:6 4'd0))
(output 'o7' (cat 7.0:9 7.8))
(output 'o8' (cat 8.0:6 8.5 8.5 8.5 8.5))
(output 'o9' (cat 9.0:6 4'd0))
(output 'o10' (cat 10.0:8 2'd0))
(output 'o11' (cat 11.0:7 11.6 11.6 11.6))
(output 'o12' (cat 12.0:8 12.7 12.7))
(output 'o13' (cat 13.0:6 13.5 13.5 13.5 13.5))
(output 'o14' (cat 14.0:8 2'd0))
(output 'o15' (cat 15.0:7 15.6 15.6 15.6))
(output 'o16' (cat 16.0:8 16.7 16.7))
))
(cell 1 0 (u// 0.2:10 (cat 0.18:24 2'd0)))
(cell 2 0 (u% 0.2:10 (cat 0.18:24 2'd0)))
(cell 3 0 (s// (cat 0.2:10 1'd0) (cat 0.24:30 0.29 0.29 0.29)))
(cell 4 0 (s% (cat 0.2:10 1'd0) (cat 0.24:30 0.29 0.29 0.29)))
(cell 5 0 (s// 0.10:18 (cat 0.18:24 2'd0)))
(cell 6 0 (s% 0.10:18 (cat 0.18:24 2'd0)))
(cell 7 0 (s// (cat 0.10:18 0.17) (cat 0.24:30 0.29 0.29 0.29)))
(cell 8 0 (s% 0.10:18 (cat 0.24:30 0.29 0.29)))
(cell 9 0 (u// (cat 0.18:24 2'd0) 0.2:10))
(cell 10 0 (u% (cat 0.18:24 2'd0) 0.2:10))
(cell 11 0 (s// (cat 0.18:24 2'd0) 0.10:18))
(cell 12 0 (s% (cat 0.18:24 2'd0) 0.10:18))
(cell 13 0 (s// (cat 0.24:30 0.29 0.29 0.29) (cat 0.2:10 1'd0)))
(cell 14 0 (s% (cat 0.24:30 0.29 0.29 0.29) (cat 0.2:10 1'd0)))
(cell 15 0 (s// (cat 0.24:30 0.29 0.29) 0.10:18))
(cell 16 0 (s% (cat 0.24:30 0.29 0.29) 0.10:18))
)
""")
def test_operator_binary_shift(self):
i8u = Signal(8)
i8s = Signal(signed(8))
i4 = Signal(4)
o1 = Signal(32)
o2 = Signal(32)
o3 = Signal(12)
o4 = Signal(12)
m = Module()
m.d.comb += o1.eq(i8u << i4)
m.d.comb += o2.eq(i8s << i4)
m.d.comb += o3.eq(i8u >> i4)
m.d.comb += o4.eq(i8s >> i4)
nl = build_netlist(Fragment.get(m, None), [
i8u, i8s, i4, o1, o2, o3, o4,
])
self.assertRepr(nl, """
(
(module 0 None ('top')
(input 'i8u' 0.2:10)
(input 'i8s' 0.10:18)
(input 'i4' 0.18:22)
(output 'o1' (cat 1.0:23 9'd0))
(output 'o2' (cat 2.0:23 2.22 2.22 2.22 2.22 2.22 2.22 2.22 2.22 2.22))
(output 'o3' (cat 3.0:8 4'd0))
(output 'o4' (cat 4.0:8 4.7 4.7 4.7 4.7))
)
(cell 0 0 (top
(input 'i8u' 2:10)
(input 'i8s' 10:18)
(input 'i4' 18:22)
(output 'o1' (cat 1.0:23 9'd0))
(output 'o2' (cat 2.0:23 2.22 2.22 2.22 2.22 2.22 2.22 2.22 2.22 2.22))
(output 'o3' (cat 3.0:8 4'd0))
(output 'o4' (cat 4.0:8 4.7 4.7 4.7 4.7))
))
(cell 1 0 (<< (cat 0.2:10 15'd0) 0.18:22))
(cell 2 0 (<< (cat 0.10:18 0.17 0.17 0.17 0.17 0.17 0.17 0.17 0.17 0.17 0.17 0.17 0.17 0.17 0.17 0.17) 0.18:22))
(cell 3 0 (u>> 0.2:10 0.18:22))
(cell 4 0 (s>> 0.10:18 0.18:22))
)
""")
def test_operator_binary_eq(self):
i8u = Signal(8)
i9u = Signal(9)
i8s = Signal(signed(8))
i9s = Signal(signed(9))
o1 = Signal(2)
o2 = Signal(2)
o3 = Signal(2)
o4 = Signal(2)
o5 = Signal(2)
o6 = Signal(2)
o7 = Signal(2)
o8 = Signal(2)
o9 = Signal(2)
o10 = Signal(2)
o11 = Signal(2)
o12 = Signal(2)
o13 = Signal(2)
o14 = Signal(2)
o15 = Signal(2)
o16 = Signal(2)
m = Module()
m.d.comb += o1.eq(i8u == i8u)
m.d.comb += o2.eq(i8u != i9u)
m.d.comb += o3.eq(i8u != i8s)
m.d.comb += o4.eq(i8u == i9s)
m.d.comb += o5.eq(i9u != i8u)
m.d.comb += o6.eq(i9u == i9u)
m.d.comb += o7.eq(i9u == i8s)
m.d.comb += o8.eq(i9u != i9s)
m.d.comb += o9.eq(i8s != i8u)
m.d.comb += o10.eq(i8s == i9u)
m.d.comb += o11.eq(i8s == i8s)
m.d.comb += o12.eq(i8s != i9s)
m.d.comb += o13.eq(i9s == i8u)
m.d.comb += o14.eq(i9s != i9u)
m.d.comb += o15.eq(i9s != i8s)
m.d.comb += o16.eq(i9s == i9s)
nl = build_netlist(Fragment.get(m, None), [
i8u, i9u, i8s, i9s,
o1, o2, o3, o4, o5, o6, o7, o8, o9, o10, o11, o12, o13, o14, o15, o16,
])
self.assertRepr(nl, """
(
(module 0 None ('top')
(input 'i8u' 0.2:10)
(input 'i9u' 0.10:19)
(input 'i8s' 0.19:27)
(input 'i9s' 0.27:36)
(output 'o1' (cat 1.0 1'd0))
(output 'o2' (cat 2.0 1'd0))
(output 'o3' (cat 3.0 1'd0))
(output 'o4' (cat 4.0 1'd0))
(output 'o5' (cat 5.0 1'd0))
(output 'o6' (cat 6.0 1'd0))
(output 'o7' (cat 7.0 1'd0))
(output 'o8' (cat 8.0 1'd0))
(output 'o9' (cat 9.0 1'd0))
(output 'o10' (cat 10.0 1'd0))
(output 'o11' (cat 11.0 1'd0))
(output 'o12' (cat 12.0 1'd0))
(output 'o13' (cat 13.0 1'd0))
(output 'o14' (cat 14.0 1'd0))
(output 'o15' (cat 15.0 1'd0))
(output 'o16' (cat 16.0 1'd0))
)
(cell 0 0 (top
(input 'i8u' 2:10)
(input 'i9u' 10:19)
(input 'i8s' 19:27)
(input 'i9s' 27:36)
(output 'o1' (cat 1.0 1'd0))
(output 'o2' (cat 2.0 1'd0))
(output 'o3' (cat 3.0 1'd0))
(output 'o4' (cat 4.0 1'd0))
(output 'o5' (cat 5.0 1'd0))
(output 'o6' (cat 6.0 1'd0))
(output 'o7' (cat 7.0 1'd0))
(output 'o8' (cat 8.0 1'd0))
(output 'o9' (cat 9.0 1'd0))
(output 'o10' (cat 10.0 1'd0))
(output 'o11' (cat 11.0 1'd0))
(output 'o12' (cat 12.0 1'd0))
(output 'o13' (cat 13.0 1'd0))
(output 'o14' (cat 14.0 1'd0))
(output 'o15' (cat 15.0 1'd0))
(output 'o16' (cat 16.0 1'd0))
))
(cell 1 0 (== 0.2:10 0.2:10))
(cell 2 0 (!= (cat 0.2:10 1'd0) 0.10:19))
(cell 3 0 (!= (cat 0.2:10 1'd0) (cat 0.19:27 0.26)))
(cell 4 0 (== (cat 0.2:10 1'd0) 0.27:36))
(cell 5 0 (!= 0.10:19 (cat 0.2:10 1'd0)))
(cell 6 0 (== 0.10:19 0.10:19))
(cell 7 0 (== (cat 0.10:19 1'd0) (cat 0.19:27 0.26 0.26)))
(cell 8 0 (!= (cat 0.10:19 1'd0) (cat 0.27:36 0.35)))
(cell 9 0 (!= (cat 0.19:27 0.26) (cat 0.2:10 1'd0)))
(cell 10 0 (== (cat 0.19:27 0.26 0.26) (cat 0.10:19 1'd0)))
(cell 11 0 (== 0.19:27 0.19:27))
(cell 12 0 (!= (cat 0.19:27 0.26) 0.27:36))
(cell 13 0 (== 0.27:36 (cat 0.2:10 1'd0)))
(cell 14 0 (!= (cat 0.27:36 0.35) (cat 0.10:19 1'd0)))
(cell 15 0 (!= 0.27:36 (cat 0.19:27 0.26)))
(cell 16 0 (== 0.27:36 0.27:36))
)
""")
def test_operator_binary_ord(self):
i8u = Signal(8)
i9u = Signal(9)
i8s = Signal(signed(8))
i9s = Signal(signed(9))
o1 = Signal(2)
o2 = Signal(2)
o3 = Signal(2)
o4 = Signal(2)
o5 = Signal(2)
o6 = Signal(2)
o7 = Signal(2)
o8 = Signal(2)
o9 = Signal(2)
o10 = Signal(2)
o11 = Signal(2)
o12 = Signal(2)
o13 = Signal(2)
o14 = Signal(2)
o15 = Signal(2)
o16 = Signal(2)
m = Module()
m.d.comb += o1.eq(i8u < i8u)
m.d.comb += o2.eq(i8u < i9u)
m.d.comb += o3.eq(i8u < i8s)
m.d.comb += o4.eq(i8u < i9s)
m.d.comb += o5.eq(i9u > i8u)
m.d.comb += o6.eq(i9u > i9u)
m.d.comb += o7.eq(i9u > i8s)
m.d.comb += o8.eq(i9u > i9s)
m.d.comb += o9.eq(i8s <= i8u)
m.d.comb += o10.eq(i8s <= i9u)
m.d.comb += o11.eq(i8s <= i8s)
m.d.comb += o12.eq(i8s <= i9s)
m.d.comb += o13.eq(i9s >= i8u)
m.d.comb += o14.eq(i9s >= i9u)
m.d.comb += o15.eq(i9s >= i8s)
m.d.comb += o16.eq(i9s >= i9s)
nl = build_netlist(Fragment.get(m, None), [
i8u, i9u, i8s, i9s,
o1, o2, o3, o4, o5, o6, o7, o8, o9, o10, o11, o12, o13, o14, o15, o16,
])
self.assertRepr(nl, """
(
(module 0 None ('top')
(input 'i8u' 0.2:10)
(input 'i9u' 0.10:19)
(input 'i8s' 0.19:27)
(input 'i9s' 0.27:36)
(output 'o1' (cat 1.0 1'd0))
(output 'o2' (cat 2.0 1'd0))
(output 'o3' (cat 3.0 1'd0))
(output 'o4' (cat 4.0 1'd0))
(output 'o5' (cat 5.0 1'd0))
(output 'o6' (cat 6.0 1'd0))
(output 'o7' (cat 7.0 1'd0))
(output 'o8' (cat 8.0 1'd0))
(output 'o9' (cat 9.0 1'd0))
(output 'o10' (cat 10.0 1'd0))
(output 'o11' (cat 11.0 1'd0))
(output 'o12' (cat 12.0 1'd0))
(output 'o13' (cat 13.0 1'd0))
(output 'o14' (cat 14.0 1'd0))
(output 'o15' (cat 15.0 1'd0))
(output 'o16' (cat 16.0 1'd0))
)
(cell 0 0 (top
(input 'i8u' 2:10)
(input 'i9u' 10:19)
(input 'i8s' 19:27)
(input 'i9s' 27:36)
(output 'o1' (cat 1.0 1'd0))
(output 'o2' (cat 2.0 1'd0))
(output 'o3' (cat 3.0 1'd0))
(output 'o4' (cat 4.0 1'd0))
(output 'o5' (cat 5.0 1'd0))
(output 'o6' (cat 6.0 1'd0))
(output 'o7' (cat 7.0 1'd0))
(output 'o8' (cat 8.0 1'd0))
(output 'o9' (cat 9.0 1'd0))
(output 'o10' (cat 10.0 1'd0))
(output 'o11' (cat 11.0 1'd0))
(output 'o12' (cat 12.0 1'd0))
(output 'o13' (cat 13.0 1'd0))
(output 'o14' (cat 14.0 1'd0))
(output 'o15' (cat 15.0 1'd0))
(output 'o16' (cat 16.0 1'd0))
))
(cell 1 0 (u< 0.2:10 0.2:10))
(cell 2 0 (u< (cat 0.2:10 1'd0) 0.10:19))
(cell 3 0 (s< (cat 0.2:10 1'd0) (cat 0.19:27 0.26)))
(cell 4 0 (s< (cat 0.2:10 1'd0) 0.27:36))
(cell 5 0 (u> 0.10:19 (cat 0.2:10 1'd0)))
(cell 6 0 (u> 0.10:19 0.10:19))
(cell 7 0 (s> (cat 0.10:19 1'd0) (cat 0.19:27 0.26 0.26)))
(cell 8 0 (s> (cat 0.10:19 1'd0) (cat 0.27:36 0.35)))
(cell 9 0 (s<= (cat 0.19:27 0.26) (cat 0.2:10 1'd0)))
(cell 10 0 (s<= (cat 0.19:27 0.26 0.26) (cat 0.10:19 1'd0)))
(cell 11 0 (s<= 0.19:27 0.19:27))
(cell 12 0 (s<= (cat 0.19:27 0.26) 0.27:36))
(cell 13 0 (s>= 0.27:36 (cat 0.2:10 1'd0)))
(cell 14 0 (s>= (cat 0.27:36 0.35) (cat 0.10:19 1'd0)))
(cell 15 0 (s>= 0.27:36 (cat 0.19:27 0.26)))
(cell 16 0 (s>= 0.27:36 0.27:36))
)
""")
def test_operator_mux(self):
i8a = Signal(8)
i8b = Signal(8)
i1 = Signal()
i4 = Signal(4)
o1 = Signal(8)
o2 = Signal(8)
m = Module()
m.d.comb += o1.eq(Mux(i1, i8a, i8b))
m.d.comb += o2.eq(Mux(i4, i8a, i8b))
nl = build_netlist(Fragment.get(m, None), [i8a, i8b, i1, i4, o1, o2])
self.assertRepr(nl, """
(
(module 0 None ('top')
(input 'i8a' 0.2:10)
(input 'i8b' 0.10:18)
(input 'i1' 0.18)
(input 'i4' 0.19:23)
(output 'o1' 1.0:8)
(output 'o2' 3.0:8)
)
(cell 0 0 (top
(input 'i8a' 2:10)
(input 'i8b' 10:18)
(input 'i1' 18:19)
(input 'i4' 19:23)
(output 'o1' 1.0:8)
(output 'o2' 3.0:8)
))
(cell 1 0 (m 0.18 0.2:10 0.10:18))
(cell 2 0 (b 0.19:23))
(cell 3 0 (m 2.0 0.2:10 0.10:18))
)
""")
def test_slice(self):
i = Signal(8)
o = Signal(8)
m = Module()
m.d.comb += o.eq(i[2:5])
nl = build_netlist(Fragment.get(m, None), [i, o])
self.assertRepr(nl, """
(
(module 0 None ('top')
(input 'i' 0.2:10)
(output 'o' (cat 0.4:7 5'd0))
)
(cell 0 0 (top
(input 'i' 2:10)
(output 'o' (cat 0.4:7 5'd0))
))
)
""")
def test_part(self):
i8u = Signal(8)
i8s = Signal(signed(8))
i4 = Signal(4)
o1 = Signal(4)
o2 = Signal(4)
o3 = Signal(4)
o4 = Signal(4)
m = Module()
m.d.comb += o1.eq(i8u.bit_select(i4, 3))
m.d.comb += o2.eq(i8s.bit_select(i4, 3))
m.d.comb += o3.eq(i8u.word_select(i4, 3))
m.d.comb += o4.eq(i8s.word_select(i4, 3))
nl = build_netlist(Fragment.get(m, None), [i8u, i8s, i4, o1, o2, o3, o4])
self.assertRepr(nl, """
(
(module 0 None ('top')
(input 'i8u' 0.2:10)
(input 'i8s' 0.10:18)
(input 'i4' 0.18:22)
(output 'o1' (cat 1.0:3 1'd0))
(output 'o2' (cat 2.0:3 1'd0))
(output 'o3' (cat 3.0:3 1'd0))
(output 'o4' (cat 4.0:3 1'd0))
)
(cell 0 0 (top
(input 'i8u' 2:10)
(input 'i8s' 10:18)
(input 'i4' 18:22)
(output 'o1' (cat 1.0:3 1'd0))
(output 'o2' (cat 2.0:3 1'd0))
(output 'o3' (cat 3.0:3 1'd0))
(output 'o4' (cat 4.0:3 1'd0))
))
(cell 1 0 (part 0.2:10 unsigned 0.18:22 3 1))
(cell 2 0 (part 0.10:18 signed 0.18:22 3 1))
(cell 3 0 (part 0.2:10 unsigned 0.18:22 3 3))
(cell 4 0 (part 0.10:18 signed 0.18:22 3 3))
)
""")
def test_cat(self):
i1 = Signal()
i2 = Signal(8)
i3 = Signal(3)
o = Signal(16)
m = Module()
m.d.comb += o.eq(Cat(i1, i2, i3))
nl = build_netlist(Fragment.get(m, None), [i1, i2, i3, o])
self.assertRepr(nl, """
(
(module 0 None ('top')
(input 'i1' 0.2)
(input 'i2' 0.3:11)
(input 'i3' 0.11:14)
(output 'o' (cat 0.2:14 4'd0))
)
(cell 0 0 (top
(input 'i1' 2:3)
(input 'i2' 3:11)
(input 'i3' 11:14)
(output 'o' (cat 0.2:14 4'd0))
))
)
""")
def test_arrayproxy(self):
i8ua = Signal(8)
i8ub = Signal(8)
i8uc = Signal(8)
i8sa = Signal(signed(8))
i8sb = Signal(signed(8))
i8sc = Signal(signed(8))
i4 = Signal(4)
o1 = Signal(10)
o2 = Signal(10)
o3 = Signal(10)
o4 = Signal(10)
m = Module()
m.d.comb += o1.eq(Array([i8ua, i8ub, i8uc])[i4])
m.d.comb += o2.eq(Array([i8ua, i8ub, i8sc])[i4])
m.d.comb += o3.eq(Array([i8sa, i8sb, i8sc])[i4])
m.d.comb += o4.eq(Array([i8sa, i8sb, i4])[i4])
nl = build_netlist(Fragment.get(m, None), [i8ua, i8ub, i8uc, i8sa, i8sb, i8sc, i4, o1, o2, o3, o4])
self.assertRepr(nl, """
(
(module 0 None ('top')
(input 'i8ua' 0.2:10)
(input 'i8ub' 0.10:18)
(input 'i8uc' 0.18:26)
(input 'i8sa' 0.26:34)
(input 'i8sb' 0.34:42)
(input 'i8sc' 0.42:50)
(input 'i4' 0.50:54)
(output 'o1' (cat 5.0:8 2'd0))
(output 'o2' (cat 10.0:9 10.8))
(output 'o3' (cat 15.0:8 15.7 15.7))
(output 'o4' (cat 20.0:8 20.7 20.7))
)
(cell 0 0 (top
(input 'i8ua' 2:10)
(input 'i8ub' 10:18)
(input 'i8uc' 18:26)
(input 'i8sa' 26:34)
(input 'i8sb' 34:42)
(input 'i8sc' 42:50)
(input 'i4' 50:54)
(output 'o1' (cat 5.0:8 2'd0))
(output 'o2' (cat 10.0:9 10.8))
(output 'o3' (cat 15.0:8 15.7 15.7))
(output 'o4' (cat 20.0:8 20.7 20.7))
))
(cell 1 0 (matches 0.50:54 0000))
(cell 2 0 (matches 0.50:54 0001))
(cell 3 0 (matches 0.50:54 0010))
(cell 4 0 (priority_match 1 (cat 1.0 2.0 3.0)))
(cell 5 0 (assignment_list 8'd0
(4.0 0:8 0.2:10)
(4.1 0:8 0.10:18)
(4.2 0:8 0.18:26)
))
(cell 6 0 (matches 0.50:54 0000))
(cell 7 0 (matches 0.50:54 0001))
(cell 8 0 (matches 0.50:54 0010))
(cell 9 0 (priority_match 1 (cat 6.0 7.0 8.0)))
(cell 10 0 (assignment_list 9'd0
(9.0 0:9 (cat 0.2:10 1'd0))
(9.1 0:9 (cat 0.10:18 1'd0))
(9.2 0:9 (cat 0.42:50 0.49))
))
(cell 11 0 (matches 0.50:54 0000))
(cell 12 0 (matches 0.50:54 0001))
(cell 13 0 (matches 0.50:54 0010))
(cell 14 0 (priority_match 1 (cat 11.0 12.0 13.0)))
(cell 15 0 (assignment_list 8'd0
(14.0 0:8 0.26:34)
(14.1 0:8 0.34:42)
(14.2 0:8 0.42:50)
))
(cell 16 0 (matches 0.50:54 0000))
(cell 17 0 (matches 0.50:54 0001))
(cell 18 0 (matches 0.50:54 0010))
(cell 19 0 (priority_match 1 (cat 16.0 17.0 18.0)))
(cell 20 0 (assignment_list 8'd0
(19.0 0:8 0.26:34)
(19.1 0:8 0.34:42)
(19.2 0:8 (cat 0.50:54 4'd0))
))
)
""")
def test_switchvalue(self):
i8ua = Signal(8)
i8ub = Signal(8)
i8uc = Signal(8)
i8ud = Signal(8)
i4 = Signal(4)
o1 = Signal(10)
o2 = Signal(10)
m = Module()
m.d.comb += o1.eq(SwitchValue(i4, [
(1, i8ua),
((2, 3), i8ub),
('11--', i8uc),
]))
m.d.comb += o2.eq(SwitchValue(i4, [
((4, 5), i8ua),
((), i8ub),
((6, 7), i8uc),
(None, i8ud),
]))
nl = build_netlist(Fragment.get(m, None), [i8ua, i8ub, i8uc, i8ud, i4, o1, o2])
self.assertRepr(nl, """
(
(module 0 None ('top')
(input 'i8ua' 0.2:10)
(input 'i8ub' 0.10:18)
(input 'i8uc' 0.18:26)
(input 'i8ud' 0.26:34)
(input 'i4' 0.34:38)
(output 'o1' (cat 5.0:8 2'd0))
(output 'o2' (cat 10.0:8 2'd0))
)
(cell 0 0 (top
(input 'i8ua' 2:10)
(input 'i8ub' 10:18)
(input 'i8uc' 18:26)
(input 'i8ud' 26:34)
(input 'i4' 34:38)
(output 'o1' (cat 5.0:8 2'd0))
(output 'o2' (cat 10.0:8 2'd0))
))
(cell 1 0 (matches 0.34:38 0001))
(cell 2 0 (matches 0.34:38 0010 0011))
(cell 3 0 (matches 0.34:38 11--))
(cell 4 0 (priority_match 1 (cat 1.0 2.0 3.0)))
(cell 5 0 (assignment_list 8'd0
(4.0 0:8 0.2:10)
(4.1 0:8 0.10:18)
(4.2 0:8 0.18:26)
))
(cell 6 0 (matches 0.34:38 0100 0101))
(cell 7 0 (matches 0.34:38 ))
(cell 8 0 (matches 0.34:38 0110 0111))
(cell 9 0 (priority_match 1 (cat 6.0 7.0 8.0 1'd1)))
(cell 10 0 (assignment_list 8'd0
(9.0 0:8 0.2:10)
(9.1 0:8 0.10:18)
(9.2 0:8 0.18:26)
(9.3 0:8 0.26:34)
))
)
""")
def test_anyvalue(self):
o1 = Signal(12)
o2 = Signal(12)
o3 = Signal(12)
o4 = Signal(12)
m = Module()
m.d.comb += o1.eq(AnyConst(8))
m.d.comb += o2.eq(AnyConst(signed(8)))
m.d.comb += o3.eq(AnySeq(8))
m.d.comb += o4.eq(AnySeq(signed(8)))
nl = build_netlist(Fragment.get(m, None), [o1, o2, o3, o4])
self.assertRepr(nl, """
(
(module 0 None ('top')
(output 'o1' (cat 1.0:8 4'd0))
(output 'o2' (cat 2.0:8 2.7 2.7 2.7 2.7))
(output 'o3' (cat 3.0:8 4'd0))
(output 'o4' (cat 4.0:8 4.7 4.7 4.7 4.7))
)
(cell 0 0 (top
(output 'o1' (cat 1.0:8 4'd0))
(output 'o2' (cat 2.0:8 2.7 2.7 2.7 2.7))
(output 'o3' (cat 3.0:8 4'd0))
(output 'o4' (cat 4.0:8 4.7 4.7 4.7 4.7))
))
(cell 1 0 (anyconst 8))
(cell 2 0 (anyconst 8))
(cell 3 0 (anyseq 8))
(cell 4 0 (anyseq 8))
)
""")
def test_initial(self):
o1 = Signal(12)
m = Module()
m.d.comb += o1.eq(Initial())
nl = build_netlist(Fragment.get(m, None), [o1])
self.assertRepr(nl, """
(
(module 0 None ('top')
(output 'o1' (cat 1.0 11'd0))
)
(cell 0 0 (top
(output 'o1' (cat 1.0 11'd0))
))
(cell 1 0 (initial))
)
""")
2024-03-05 02:34:58 -07:00
class SwitchTestCase(FHDLTestCase):
def test_comb(self):
o1 = Signal(8)
o2 = Signal(8, init=123)
i = Signal(4)
i2 = Signal(4)
m = Module()
with m.If(i[0]):
m.d.comb += o1.eq(1)
with m.Elif(i[1]):
m.d.comb += o1[2:4].eq(2)
m.d.comb += o2.eq(3)
with m.If(i[2]):
with m.Switch(i2):
with m.Case(1):
m.d.comb += o2.eq(4)
with m.Case(2, 4):
m.d.comb += o2.eq(5)
with m.Case('11--'):
m.d.comb += o2.eq(6)
with m.If(i[3]):
m.d.comb += o1.eq(7)
nl = build_netlist(Fragment.get(m, None), [i, i2, o1, o2])
self.assertRepr(nl, """
(
(module 0 None ('top')
(input 'i' 0.2:6)
(input 'i2' 0.6:10)
(output 'o1' 12.0:8)
(output 'o2' 13.0:8)
)
(cell 0 0 (top
(input 'i' 2:6)
(input 'i2' 6:10)
(output 'o1' 12.0:8)
(output 'o2' 13.0:8)
))
(cell 1 0 (matches 0.2:4 -1))
(cell 2 0 (matches 0.2:4 1-))
(cell 3 0 (priority_match 1 (cat 1.0 2.0)))
(cell 4 0 (matches 0.4 1))
(cell 5 0 (priority_match 1 4.0))
(cell 6 0 (matches 0.6:10 0001))
(cell 7 0 (matches 0.6:10 0010 0100))
(cell 8 0 (matches 0.6:10 11--))
(cell 9 0 (priority_match 5.0 (cat 6.0 7.0 8.0)))
(cell 10 0 (matches 0.5 1))
(cell 11 0 (priority_match 9.2 10.0))
(cell 12 0 (assignment_list 8'd0
(3.0 0:8 8'd1)
(3.1 2:4 2'd2)
(11.0 0:8 8'd7)
))
(cell 13 0 (assignment_list 8'd123
(3.1 0:8 8'd3)
(9.0 0:8 8'd4)
(9.1 0:8 8'd5)
(9.2 0:8 8'd6)
))
)
""")
def test_sync(self):
o1 = Signal(8, reset_less=True)
o2 = Signal(8, init=123)
o3 = Signal(8, init=45, reset_less=True)
o4 = Signal(8, init=67)
o5 = Signal(8, init=89)
i1 = Signal(8)
i2 = Signal()
m = Module()
m.domains.a = ClockDomain()
m.domains.b = ClockDomain(async_reset=True)
m.domains.c = ClockDomain(reset_less=True, clk_edge="neg")
with m.If(i2):
m.d.a += o1.eq(i1)
m.d.a += o2.eq(i1)
m.d.b += o3.eq(i1)
m.d.b += o4.eq(i1)
m.d.c += o5.eq(i1)
nl = build_netlist(Fragment.get(m, None), [
i1, i2, o1, o2, o3, o4, o5,
ClockSignal("a"), ResetSignal("a"),
ClockSignal("b"), ResetSignal("b"),
ClockSignal("c"),
])
self.assertRepr(nl, """
(
(module 0 None ('top')
(input 'i1' 0.2:10)
(input 'i2' 0.10)
(input 'a_clk' 0.11)
(input 'a_rst' 0.12)
(input 'b_clk' 0.13)
(input 'b_rst' 0.14)
(input 'c_clk' 0.15)
(output 'o1' 4.0:8)
(output 'o2' 8.0:8)
(output 'o3' 10.0:8)
(output 'o4' 12.0:8)
(output 'o5' 14.0:8)
)
(cell 0 0 (top
(input 'i1' 2:10)
(input 'i2' 10:11)
(input 'a_clk' 11:12)
(input 'a_rst' 12:13)
(input 'b_clk' 13:14)
(input 'b_rst' 14:15)
(input 'c_clk' 15:16)
(output 'o1' 4.0:8)
(output 'o2' 8.0:8)
(output 'o3' 10.0:8)
(output 'o4' 12.0:8)
(output 'o5' 14.0:8)
))
(cell 1 0 (matches 0.10 1))
(cell 2 0 (priority_match 1 1.0))
(cell 3 0 (assignment_list 4.0:8 (2.0 0:8 0.2:10)))
(cell 4 0 (flipflop 3.0:8 0 pos 0.11 0))
(cell 5 0 (matches 0.12 1))
(cell 6 0 (priority_match 1 5.0))
(cell 7 0 (assignment_list 8.0:8 (2.0 0:8 0.2:10) (6.0 0:8 8'd123)))
(cell 8 0 (flipflop 7.0:8 123 pos 0.11 0))
(cell 9 0 (assignment_list 10.0:8 (2.0 0:8 0.2:10)))
(cell 10 0 (flipflop 9.0:8 45 pos 0.13 0))
(cell 11 0 (assignment_list 12.0:8 (2.0 0:8 0.2:10)))
(cell 12 0 (flipflop 11.0:8 67 pos 0.13 0.14))
(cell 13 0 (assignment_list 14.0:8 (2.0 0:8 0.2:10)))
(cell 14 0 (flipflop 13.0:8 89 neg 0.15 0))
)
""")
def test_print(self):
m = Module()
a = Signal(6)
b = Signal(signed(8))
en = Signal()
m.domains.a = ClockDomain()
m.domains.b = ClockDomain(async_reset=True)
m.domains.c = ClockDomain(reset_less=True, clk_edge="neg")
with m.If(en):
m.d.comb += Print(a, end="")
m.d.comb += Print(b)
m.d.a += Print(a, b)
m.d.b += Print(Format("values: {:02x}, {:+d}", a, b))
m.d.c += Print("meow")
nl = build_netlist(Fragment.get(m, None), [
a, b, en,
ClockSignal("a"), ResetSignal("a"),
ClockSignal("b"), ResetSignal("b"),
ClockSignal("c"),
])
self.assertRepr(nl, """
(
(module 0 None ('top')
(input 'a' 0.2:8)
(input 'b' 0.8:16)
(input 'en' 0.16)
(input 'a_clk' 0.17)
(input 'a_rst' 0.18)
(input 'b_clk' 0.19)
(input 'b_rst' 0.20)
(input 'c_clk' 0.21)
)
(cell 0 0 (top
(input 'a' 2:8)
(input 'b' 8:16)
(input 'en' 16:17)
(input 'a_clk' 17:18)
(input 'a_rst' 18:19)
(input 'b_clk' 19:20)
(input 'b_rst' 20:21)
(input 'c_clk' 21:22)
))
(cell 1 0 (matches 0.16 1))
(cell 2 0 (priority_match 1 1.0))
(cell 3 0 (assignment_list 1'd0 (2.0 0:1 1'd1)))
(cell 4 0 (print 3.0 ((u 0.2:8 ''))))
(cell 5 0 (assignment_list 1'd0 (2.0 0:1 1'd1)))
(cell 6 0 (print 5.0 ((s 0.8:16 '') '\\n')))
(cell 7 0 (assignment_list 1'd0 (2.0 0:1 1'd1)))
(cell 8 0 (print 7.0 pos 0.17 ((u 0.2:8 '') ' ' (s 0.8:16 '') '\\n')))
(cell 9 0 (assignment_list 1'd0 (2.0 0:1 1'd1)))
(cell 10 0 (print 9.0 pos 0.19 ('values: ' (u 0.2:8 '02x') ', ' (s 0.8:16 '+d') '\\n')))
(cell 11 0 (assignment_list 1'd0 (2.0 0:1 1'd1)))
(cell 12 0 (print 11.0 neg 0.21 ('meow\\n')))
)
""")
def test_assert(self):
m = Module()
i = Signal(6)
m.domains.a = ClockDomain()
m.domains.b = ClockDomain(async_reset=True)
m.domains.c = ClockDomain(reset_less=True, clk_edge="neg")
with m.If(i[5]):
m.d.comb += Assert(i[0])
m.d.comb += Assume(i[1], "aaa")
m.d.a += Assert(i[2])
m.d.b += Assume(i[3], Format("value: {}", i))
m.d.c += Cover(i[4], "c")
m.d.comb += Cover(i, "d")
nl = build_netlist(Fragment.get(m, None), [
i,
ClockSignal("a"), ResetSignal("a"),
ClockSignal("b"), ResetSignal("b"),
ClockSignal("c"),
])
self.assertRepr(nl, """
(
(module 0 None ('top')
(input 'i' 0.2:8)
(input 'a_clk' 0.8)
(input 'a_rst' 0.9)
(input 'b_clk' 0.10)
(input 'b_rst' 0.11)
(input 'c_clk' 0.12)
)
(cell 0 0 (top
(input 'i' 2:8)
(input 'a_clk' 8:9)
(input 'a_rst' 9:10)
(input 'b_clk' 10:11)
(input 'b_rst' 11:12)
(input 'c_clk' 12:13)
))
(cell 1 0 (matches 0.7 1))
(cell 2 0 (priority_match 1 1.0))
(cell 3 0 (assignment_list 1'd0 (2.0 0:1 1'd1)))
(cell 4 0 (assert 0.2 3.0 None))
(cell 5 0 (assignment_list 1'd0 (2.0 0:1 1'd1)))
(cell 6 0 (assume 0.3 5.0 ('aaa')))
(cell 7 0 (b 0.2:8))
(cell 8 0 (assignment_list 1'd0 (2.0 0:1 1'd1)))
(cell 9 0 (cover 7.0 8.0 ('d')))
(cell 10 0 (assignment_list 1'd0 (2.0 0:1 1'd1)))
(cell 11 0 (assert 0.4 10.0 pos 0.8 None))
(cell 12 0 (assignment_list 1'd0 (2.0 0:1 1'd1)))
(cell 13 0 (assume 0.5 12.0 pos 0.10 ('value: ' (u 0.2:8 ''))))
(cell 14 0 (assignment_list 1'd0 (2.0 0:1 1'd1)))
(cell 15 0 (cover 0.6 14.0 neg 0.12 ('c')))
)
""")
2024-03-05 02:34:58 -07:00
class ConflictTestCase(FHDLTestCase):
def test_domain_conflict(self):
s = Signal()
m = Module()
m.d.sync += s.eq(1)
m1 = Module()
m1.d.comb += s.eq(2)
m.submodules.m1 = m1
with self.assertRaisesRegex(DriverConflict,
r"^Signal \(sig s\) driven from domain comb at "
r".*test_hdl_ir.py:\d+ and domain sync at "
r".*test_hdl_ir.py:\d+$"):
build_netlist(Fragment.get(m, None), [])
def test_module_conflict(self):
s = Signal()
m = Module()
m.d.sync += s.eq(1)
m1 = Module()
m1.d.sync += s.eq(2)
m.submodules.m1 = m1
with self.assertRaisesRegex(DriverConflict,
r"^Signal \(sig s\) driven from module top\.m1 at "
r".*test_hdl_ir.py:\d+ and module top at "
r".*test_hdl_ir.py:\d+$"):
build_netlist(Fragment.get(m, None), [])
def test_instance_conflict(self):
s = Signal()
m = Module()
m.d.sync += s.eq(1)
m.submodules.t = Instance("tt", o_s=s)
with self.assertRaisesRegex(DriverConflict,
r"^Bit 0 of signal \(sig s\) has multiple drivers: "
r".*test_hdl_ir.py:\d+ and .*test_hdl_ir.py:\d+$"):
build_netlist(Fragment.get(m, None), [])
2024-03-05 02:34:58 -07:00
class UndrivenTestCase(FHDLTestCase):
def test_undriven(self):
o = Signal(8)
m = Module()
nl = build_netlist(Fragment.get(m, None), [
("o", o, PortDirection.Output),
])
self.assertRepr(nl, """
(
(module 0 None ('top')
(output 'o' 8'd0)
)
(cell 0 0 (top
(output 'o' 8'd0)
))
)
""")
def test_undef_to_ff(self):
o = Signal(8, init=0x55)
m = Module()
nl = build_netlist(Fragment.get(m, None), [
("o", o, PortDirection.Output),
], all_undef_to_ff=True)
self.assertRepr(nl, """
(
(module 0 None ('top')
(output 'o' 1.0:8)
)
(cell 0 0 (top
(output 'o' 1.0:8)
))
(cell 1 0 (flipflop 1.0:8 85 pos 0 0))
)
""")
def test_undef_to_ff_partial(self):
o = Signal(8, init=0x55)
m = Module()
m.submodules.inst = Instance("t", o_o=o[2])
nl = build_netlist(Fragment.get(m, None), [
("o", o, PortDirection.Output),
], all_undef_to_ff=True)
self.assertRepr(nl, """
(
(module 0 None ('top')
(output 'o' (cat 2.0:2 1.0 3.0:5))
)
(cell 0 0 (top
(output 'o' (cat 2.0:2 1.0 3.0:5))
))
(cell 1 0 (instance 't' 'inst' (output 'o' 0:1)))
(cell 2 0 (flipflop 2.0:2 1 pos 0 0))
(cell 3 0 (flipflop 3.0:5 10 pos 0 0))
)
""")
class FieldsTestCase(FHDLTestCase):
def test_fields(self):
class MyEnum(enum.Enum, shape=unsigned(2)):
A = 0
B = 1
C = 2
l = data.StructLayout({"a": MyEnum, "b": signed(3)})
s1 = Signal(l)
s2 = Signal(MyEnum)
s3 = Signal(signed(3))
s4 = Signal(unsigned(4))
nl = build_netlist(Fragment.get(Module(), None), [
s1.as_value(), s2.as_value(), s3, s4,
])
self.assertEqual(nl.signal_fields[s1.as_value()], {
(): SignalField(nl.signals[s1.as_value()], signed=False),
('a',): SignalField(nl.signals[s1.as_value()][0:2], signed=False, enum_name="MyEnum", enum_variants={
0: "A",
1: "B",
2: "C",
}),
('b',): SignalField(nl.signals[s1.as_value()][2:5], signed=True)
})
self.assertEqual(nl.signal_fields[s2.as_value()], {
(): SignalField(nl.signals[s2.as_value()], signed=False, enum_name="MyEnum", enum_variants={
0: "A",
1: "B",
2: "C",
}),
})
self.assertEqual(nl.signal_fields[s3], {
(): SignalField(nl.signals[s3], signed=True),
})
self.assertEqual(nl.signal_fields[s4], {
(): SignalField(nl.signals[s4], signed=False),
})
class CycleTestCase(FHDLTestCase):
def test_cycle(self):
a = Signal()
b = Signal()
m = Module()
m.d.comb += [
a.eq(~b),
b.eq(~a),
]
with self.assertRaisesRegex(CombinationalCycle,
r"^Combinational cycle detected, path:\n"
r".*test_hdl_ir.py:\d+: operator ~ bit 0\n"
r".*test_hdl_ir.py:\d+: signal b bit 0\n"
r".*test_hdl_ir.py:\d+: operator ~ bit 0\n"
r".*test_hdl_ir.py:\d+: signal a bit 0\n"
r"$"):
build_netlist(Fragment.get(m, None), [])