Repository: amaranth-lang/amaranth
Pull request #1180 (2024-03-03 17:57:19)

test_hdl_ir: Add a bunch of tests for NIR emitter.

codecov[bot]: ## [Codecov](https://app.codecov.io/gh/amaranth-lang/amaranth/pull/1180?src=pr&el=h1&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=amaranth-lang) Report
All modified and coverable lines are covered by tests :white_check_mark:
> Project coverage is 89.07%. Comparing base [(`2400d39`)](https://app.codecov.io/gh/amaranth-lang/amaranth/commit/2400d3973076f69d75c5299d7e6e7c181e0b5980?el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=amaranth-lang) to head [(`27fb473`)](https://app.codecov.io/gh/amaranth-lang/amaranth/pull/1180?src=pr&el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=amaranth-lang).

> :exclamation: Current head 27fb473 differs from pull request most recent head 27b2ac6. Consider uploading reports for the commit 27b2ac6 to get more accurate results


<details><summary>Additional details and impacted files</summary>


```diff
@@            Coverage Diff             @@
##             main    #1180      +/-   ##
==========================================
+ Coverage   87.92%   89.07%   +1.15%     
==========================================
  Files          43       43              
  Lines        8794     8797       +3     
  Branches     2086     2089       +3     
==========================================
+ Hits         7732     7836     +104     
+ Misses        872      782      -90     
+ Partials      190      179      -11     
```



</details>

[:umbrella: View full report in Codecov by Sentry](https://app.codecov.io/gh/amaranth-lang/amaranth/pull/1180?src=pr&el=continue&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=amaranth-lang).   
:loudspeaker: Have feedback on the report? [Share it here](https://about.codecov.io/codecov-pr-comment-feedback/?utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=amaranth-lang).


Patch:
diff --git a/amaranth/hdl/_dsl.py b/amaranth/hdl/_dsl.py
index 506ba8d..b753ae1 100644
--- a/amaranth/hdl/_dsl.py
+++ b/amaranth/hdl/_dsl.py
@@ -503,9 +503,11 @@ class Module(_ModuleBuilderRoot, Elaboratable):
             if_tests, if_bodies = data["tests"], data["bodies"]
             if_src_locs = data["src_locs"]
 
-            domains = set()
+            # Use dict to ensure deterministic iteration.
+            domains = {}
             for if_case in if_bodies:
-                domains |= set(if_case)
+                for domain in if_case:
+                    domains[domain] = None
 
             for domain in domains:
                 tests, cases = [], OrderedDict()
@@ -528,9 +530,10 @@ class Module(_ModuleBuilderRoot, Elaboratable):
             switch_test, switch_cases = data["test"], data["cases"]
             switch_case_src_locs = data["case_src_locs"]
 
-            domains = set()
+            domains = {}
             for stmts in switch_cases.values():
-                domains |= set(stmts)
+                for domain in stmts:
+                    domains[domain] = None
 
             for domain in domains:
                 domain_cases = OrderedDict()
@@ -561,9 +564,10 @@ class Module(_ModuleBuilderRoot, Elaboratable):
                 self._top_comb_statements.append(
                     sig.eq(Operator("==", [fsm_signal, fsm_encoding[name]], src_loc_at=0)))
 
-            domains = set()
+            domains = {}
             for stmts in fsm_states.values():
-                domains |= set(stmts)
+                for domain in stmts:
+                    domains[domain] = None
 
             for domain in domains:
                 domain_states = OrderedDict()
diff --git a/amaranth/hdl/_ir.py b/amaranth/hdl/_ir.py
index 2eed406..bace04a 100644
--- a/amaranth/hdl/_ir.py
+++ b/amaranth/hdl/_ir.py
@@ -1184,7 +1184,7 @@ class NetlistEmitter:
             value = driver.emit_value(self)
             if driver.domain is not None:
                 clk, = self.emit_signal(driver.domain.clk)
-                if driver.domain.rst is not None and driver.domain.async_reset:
+                if driver.domain.rst is not None and driver.domain.async_reset and not driver.signal.reset_less:
                     arst, = self.emit_signal(driver.domain.rst)
                 else:
                     arst = _nir.Net.from_const(0)
diff --git a/amaranth/hdl/_nir.py b/amaranth/hdl/_nir.py
index 6e5aee1..eefce58 100644
--- a/amaranth/hdl/_nir.py
+++ b/amaranth/hdl/_nir.py
@@ -383,10 +383,10 @@ class Top(Cell):
 
     def __repr__(self):
         ports = []
-        for (name, val) in self.ports_o.items():
-            ports.append(f"(output {name!r} {val})")
         for (name, (start, width)) in self.ports_i.items():
             ports.append(f"(input {name!r} {start}:{start+width})")
+        for (name, val) in self.ports_o.items():
+            ports.append(f"(output {name!r} {val})")
         for (name, (start, width)) in self.ports_io.items():
             ports.append(f"(inout {name!r} {start}:{start+width})")
         ports = " ".join(ports)
@@ -533,7 +533,7 @@ class ArrayMux(Cell):
         self.index = netlist.resolve_value(self.index)
 
     def __repr__(self):
-        elems = " ".join(repr(elem) for elem in elems)
+        elems = " ".join(repr(elem) for elem in self.elems)
         return f"(array_mux {self.width} {self.index} ({elems}))"
 
 


Test patch:
diff --git a/tests/test_hdl_ir.py b/tests/test_hdl_ir.py
index 299344a..8c37a7a 100644
--- a/tests/test_hdl_ir.py
+++ b/tests/test_hdl_ir.py
@@ -106,7 +106,7 @@ class FragmentPortsTestCase(FHDLTestCase):
         self.assertRepr(nl, """
         (
             (module 0 None ('top') (input 's1' 0.2) (output 'c1' 0.2))
-            (cell 0 0 (top (output 'c1' 0.2) (input 's1' 2:3)))
+            (cell 0 0 (top (input 's1' 2:3) (output 'c1' 0.2)))
         )
         """)
 
@@ -123,7 +123,7 @@ class FragmentPortsTestCase(FHDLTestCase):
         (
             (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 (output 'c1' 1.0) (input 's1' 2:3)))
+            (cell 0 0 (top (input 's1' 2:3) (output 'c1' 1.0)))
             (cell 1 1 (~ 0.2))
         )
         """)
@@ -210,7 +210,7 @@ class FragmentPortsTestCase(FHDLTestCase):
             (module 8 0 ('top' 'f2')
                 (input 's1' 0.2)
                 (output 's2' 10.0))
-            (cell 0 0 (top (output 'c1' 5.0) (output 'c2' 2.0) (output 'c3' 1.0) (input 's1' 2:3)))
+            (cell 0 0 (top (input 's1' 2:3) (output 'c1' 5.0) (output 'c2' 2.0) (output 'c3' 1.0)))
             (cell 1 3 (~ 2.0))
             (cell 2 4 (~ 6.0))
             (cell 3 4 (assignment_list 1'd0 (1 0:1 1'd1)))
@@ -234,7 +234,7 @@ class FragmentPortsTestCase(FHDLTestCase):
         self.assertRepr(nl, """
         (
             (module 0 None ('top') (input 'b' 0.2) (inout 'c' 0.3) (output 'a' 1'd0))
-            (cell 0 0 (top (output 'a' 1'd0) (input 'b' 2:3) (inout 'c' 3:4)))
+            (cell 0 0 (top (input 'b' 2:3) (output 'a' 1'd0) (inout 'c' 3:4)))
         )
         """)
 
@@ -253,7 +253,7 @@ class FragmentPortsTestCase(FHDLTestCase):
         self.assertRepr(nl, """
         (
             (module 0 None ('top') (input 'clk' 0.2) (input 'rst' 0.3) (output 'ctr' 5.0:4))
-            (cell 0 0 (top (output 'ctr' 5.0:4) (input 'clk' 2:3) (input 'rst' 3:4)))
+            (cell 0 0 (top (input 'clk' 2:3) (input 'rst' 3:4) (output 'ctr' 5.0:4)))
             (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))
@@ -271,7 +271,7 @@ class FragmentPortsTestCase(FHDLTestCase):
         self.assertRepr(nl, """
         (
             (module 0 None ('top') (input 'clk' 0.2) (input 'rst' 0.3) (output 'ctr' 5.0:4))
-            (cell 0 0 (top (output 'ctr' 5.0:4) (input 'clk' 2:3) (input 'rst' 3:4)))
+            (cell 0 0 (top (input 'clk' 2:3) (input 'rst' 3:4) (output 'ctr' 5.0:4)))
             (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))
@@ -301,9 +301,9 @@ class FragmentPortsTestCase(FHDLTestCase):
                 (input 'b' 0.6:10)
                 (output 'c' 1.4:7))
             (cell 0 0 (top
-                (output 'c' 1.4:7)
                 (input 'a' 2:6)
-                (input 'b' 6:10)))
+                (input 'b' 6:10)
+                (output 'c' 1.4:7)))
             (cell 1 1 (* (cat 0.2:6 4'd0) (cat 0.6:10 4'd0)))
         )
         """)
@@ -339,9 +339,9 @@ class FragmentPortsTestCase(FHDLTestCase):
                 (output 'port$1$0' 1.0:4)
                 (output 'port$1$4' 1.4:8))
             (cell 0 0 (top
+                (input 'a' 2:6)
                 (output 'c' 1.0:4)
                 (output 'd' 1.4:8)
-                (input 'a' 2:6)
                 (inout 'b' 6:10)))
             (cell 1 1 (instance 't' 'i'
                 (param 'p' 'meow')
@@ -860,8 +860,8 @@ class InstanceTestCase(FHDLTestCase):
                 (output 'o' 1.0:4)
             )
             (cell 0 0 (top
-                (output 'o' 1.0:4)
                 (input 'i' 2:5)
+                (output 'o' 1.0:4)
                 (inout 'io' 5:10)
             ))
             (cell 1 0 (instance 'gadget' 'my_gadget'
@@ -944,8 +944,8 @@ class InstanceTestCase(FHDLTestCase):
                 (output 'o' 1.0:4)
             )
             (cell 0 0 (top
-                (output 'o' 1.0:4)
                 (input 'i' 2:5)
+                (output 'o' 1.0:4)
                 (inout 'io' 5:10)
             ))
             (cell 1 0 (instance 'gadget' 'my_gadget'
@@ -1150,9 +1150,9 @@ class IOBufferTestCase(FHDLTestCase):
                 (output 'i' 1.0:4)
             )
             (cell 0 0 (top
-                (output 'i' 1.0:4)
                 (input 'o' 6:10)
                 (input 'oe' 10:11)
+                (output 'i' 1.0:4)
                 (inout 'pad' 2:6)
             ))
             (cell 1 0 (iob 0.2:6 0.6:10 0.10))
@@ -1207,8 +1207,8 @@ class AssignTestCase(FHDLTestCase):
                 (output 's1' 0.2:10)
             )
             (cell 0 0 (top
-                (output 's1' 0.2:10)
                 (input 's2' 2:10)
+                (output 's1' 0.2:10)
             ))
         )
         """)
@@ -1230,8 +1230,8 @@ class AssignTestCase(FHDLTestCase):
                 (output 's1' 0.2:10)
             )
             (cell 0 0 (top
-                (output 's1' 0.2:10)
                 (input 's2' 2:12)
+                (output 's1' 0.2:10)
             ))
         )
         """)
@@ -1253,8 +1253,8 @@ class AssignTestCase(FHDLTestCase):
                 (output 's1' (cat 0.2:8 2'd0))
             )
             (cell 0 0 (top
-                (output 's1' (cat 0.2:8 2'd0))
                 (input 's2' 2:8)
+                (output 's1' (cat 0.2:8 2'd0))
             ))
         )
         """)
@@ -1276,8 +1276,8 @@ class AssignTestCase(FHDLTestCase):
                 (output 's1' (cat 0.2:8 0.7 0.7))
             )
             (cell 0 0 (top
-                (output 's1' (cat 0.2:8 0.7 0.7))
                 (input 's2' 2:8)
+                (output 's1' (cat 0.2:8 0.7 0.7))
             ))
         )
         """)
@@ -1299,8 +1299,8 @@ class AssignTestCase(FHDLTestCase):
                 (output 's1' 1.0:8)
             )
             (cell 0 0 (top
-                (output 's1' 1.0:8)
                 (input 's2' 2:6)
+                (output 's1' 1.0:8)
             ))
             (cell 1 0 (assignment_list 8'd0 (1 2:6 0.2:6)))
         )
@@ -1325,9 +1325,9 @@ class AssignTestCase(FHDLTestCase):
                 (output 's1' 10.0:8)
             )
             (cell 0 0 (top
-                (output 's1' 10.0:8)
                 (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))
@@ -1370,9 +1370,9 @@ class AssignTestCase(FHDLTestCase):
                 (output 's1' 6.0:8)
             )
             (cell 0 0 (top
-                (output 's1' 6.0:8)
                 (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))
@@ -1407,9 +1407,9 @@ class AssignTestCase(FHDLTestCase):
                 (output 's1' 6.0:16)
             )
             (cell 0 0 (top
-                (output 's1' 6.0:16)
                 (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))
@@ -1444,9 +1444,9 @@ class AssignTestCase(FHDLTestCase):
                 (output 's1' 7.0:17)
             )
             (cell 0 0 (top
-                (output 's1' 7.0:17)
                 (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))
@@ -1487,10 +1487,10 @@ class AssignTestCase(FHDLTestCase):
                 (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)
-                (input 's4' 2:14)
             ))
         )
         """)
@@ -1518,10 +1518,10 @@ class AssignTestCase(FHDLTestCase):
                 (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))
-                (input 's4' 2:8)
             ))
         )
         """)
@@ -1546,9 +1546,9 @@ class AssignTestCase(FHDLTestCase):
                 (output 's2' 0.2:10)
             )
             (cell 0 0 (top
+                (input 's3' 2:10)
                 (output 's1' 0.2:10)
                 (output 's2' 0.2:10)
-                (input 's3' 2:10)
             ))
         )
         """)
@@ -1577,11 +1577,11 @@ class AssignTestCase(FHDLTestCase):
                 (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)
-                (input 's4' 2:10)
-                (input 's5' 10:18)
             ))
             (cell 1 0 (matches 0.2:10 00000000))
             (cell 2 0 (matches 0.2:10 00000001))
@@ -1610,8 +1610,8 @@ class AssignTestCase(FHDLTestCase):
                 (output 's1' 1.0:12)
             )
             (cell 0 0 (top
-                (output 's1' 1.0:12)
                 (input 's2' 2:6)
+                (output 's1' 1.0:12)
             ))
             (cell 1 0 (assignment_list 12'd0 (1 3:7 0.2:6)))
         )
@@ -1646,12 +1646,12 @@ class AssignTestCase(FHDLTestCase):
                 (output 's4' 2.0:4)
             )
             (cell 0 0 (top
-                (output 's2' 1.0:4)
-                (output 's3' 0.13:17)
-                (output 's4' 2.0:4)
                 (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))))
@@ -1677,9 +1677,9 @@ class AssignTestCase(FHDLTestCase):
                 (output 's1' 10.0:8)
             )
             (cell 0 0 (top
-                (output 's1' 10.0:8)
                 (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))
@@ -1720,9 +1720,9 @@ class AssignTestCase(FHDLTestCase):
                 (output 's1' 4.0:8)
             )
             (cell 0 0 (top
-                (output 's1' 4.0:8)
                 (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))
@@ -1758,11 +1758,11 @@ class AssignTestCase(FHDLTestCase):
                 (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)
-                (input 's4' 2:10)
-                (input 's5' 10:18)
             ))
             (cell 1 0 (matches 0.2:10 00000000))
             (cell 2 0 (matches 0.2:10 00000001))
@@ -1793,9 +1793,9 @@ class AssignTestCase(FHDLTestCase):
                 (output 's1' 8.0:8)
             )
             (cell 0 0 (top
-                (output 's1' 8.0:8)
                 (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))
@@ -1834,9 +1834,9 @@ class AssignTestCase(FHDLTestCase):
                 (output 's1' 8.0:12)
             )
             (cell 0 0 (top
-                (output 's1' 8.0:12)
                 (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))
@@ -1875,11 +1875,1307 @@ class AssignTestCase(FHDLTestCase):
                 (output 's2' 2.0:8)
             )
             (cell 0 0 (top
+                (input 's3' 2:10)
                 (output 's1' 1.0:8)
                 (output 's2' 2.0:8)
-                (input 's3' 2:10)
             ))
             (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)))
         )
         """)
+
+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 1.0:8 2'd0))
+                (output 'o2' (cat 2.0:9 2.8))
+                (output 'o3' (cat 3.0:8 3.7 3.7))
+                (output 'o4' (cat 4.0:8 4.7 4.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 1.0:8 2'd0))
+                (output 'o2' (cat 2.0:9 2.8))
+                (output 'o3' (cat 3.0:8 3.7 3.7))
+                (output 'o4' (cat 4.0:8 4.7 4.7))
+            ))
+            (cell 1 0 (array_mux 8 0.50:54 (0.2:10 0.10:18 0.18:26)))
+            (cell 2 0 (array_mux 9 0.50:54 ((cat 0.2:10 1'd0) (cat 0.10:18 1'd0) (cat 0.42:50 0.49))))
+            (cell 3 0 (array_mux 8 0.50:54 (0.26:34 0.34:42 0.42:50)))
+            (cell 4 0 (array_mux 8 0.50:54 (0.26:34 0.34:42 (cat 0.50:54 4'd0))))
+        )
+        """)
+
+    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))
+        )
+        """)
+
+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"),
+        ])
+        # TODO: two inefficiencies in NIR emitter:
+        # - _ignore_resets inserts useless redundant Switch for async reset
+        # - matches and priority_match duplicated between clock domains — add cache?
+        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' 12.0:8)
+                (output 'o2' 14.0:8)
+                (output 'o3' 16.0:8)
+                (output 'o4' 18.0:8)
+                (output 'o5' 20.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' 12.0:8)
+                (output 'o2' 14.0:8)
+                (output 'o3' 16.0:8)
+                (output 'o4' 18.0:8)
+                (output 'o5' 20.0:8)
+            ))
+            (cell 1 0 (matches 0.10 1))
+            (cell 2 0 (priority_match 1 1.0))
+            (cell 3 0 (matches 0.12 1))
+            (cell 4 0 (priority_match 1 3.0))
+            (cell 5 0 (matches 0.10 1))
+            (cell 6 0 (priority_match 1 5.0))
+            (cell 7 0 (matches 0.14 1))
+            (cell 8 0 (priority_match 1 7.0))
+            (cell 9 0 (matches 0.10 1))
+            (cell 10 0 (priority_match 1 9.0))
+            (cell 11 0 (assignment_list 12.0:8 (2.0 0:8 0.2:10)))
+            (cell 12 0 (flipflop 11.0:8 0 pos 0.11 0))
+            (cell 13 0 (assignment_list 14.0:8 (2.0 0:8 0.2:10) (4.0 0:8 8'd123)))
+            (cell 14 0 (flipflop 13.0:8 123 pos 0.11 0))
+            (cell 15 0 (assignment_list 16.0:8 (6.0 0:8 0.2:10)))
+            (cell 16 0 (flipflop 15.0:8 45 pos 0.13 0))
+            (cell 17 0 (assignment_list 18.0:8 (6.0 0:8 0.2:10) (8.0 0:8 8'd67)))
+            (cell 18 0 (flipflop 17.0:8 67 pos 0.13 0.14))
+            (cell 19 0 (assignment_list 20.0:8 (10.0 0:8 0.2:10)))
+            (cell 20 0 (flipflop 19.0:8 89 neg 0.15 0))
+        )
+        """)
+
+    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], name="a")
+            m.d.a += Assert(i[2])
+            m.d.b += Assume(i[3], name="b")
+            m.d.c += Cover(i[4], name="c")
+            m.d.comb += Cover(i, name="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 None 0.2 3.0))
+            (cell 5 0 (assignment_list 1'd0 (2.0 0:1 1'd1)))
+            (cell 6 0 (assume 'a' 0.3 5.0))
+            (cell 7 0 (b 0.2:8))
+            (cell 8 0 (assignment_list 1'd0 (2.0 0:1 1'd1)))
+            (cell 9 0 (cover 'd' 7.0 8.0))
+            (cell 10 0 (matches 0.7 1))
+            (cell 11 0 (priority_match 1 10.0))
+            (cell 12 0 (assignment_list 1'd0 (11.0 0:1 1'd1)))
+            (cell 13 0 (assert None 0.4 12.0 pos 0.8))
+            (cell 14 0 (matches 0.7 1))
+            (cell 15 0 (priority_match 1 14.0))
+            (cell 16 0 (assignment_list 1'd0 (15.0 0:1 1'd1)))
+            (cell 17 0 (assume 'b' 0.5 16.0 pos 0.10))
+            (cell 18 0 (matches 0.7 1))
+            (cell 19 0 (priority_match 1 18.0))
+            (cell 20 0 (assignment_list 1'd0 (19.0 0:1 1'd1)))
+            (cell 21 0 (cover 'c' 0.6 20.0 neg 0.12))
+
+
+        )
+        """)