move inversion of cmp into output stage by inverting the is +ve and is -ve test
authorLuke Kenneth Casson Leighton <lkcl@lkcl.net>
Thu, 14 May 2020 16:34:39 +0000 (17:34 +0100)
committerLuke Kenneth Casson Leighton <lkcl@lkcl.net>
Thu, 14 May 2020 16:34:39 +0000 (17:34 +0100)
this saves on 2x 64-bit MUXes if the actual operands A and B were swapped
instead

src/soc/alu/formal/proof_input_stage.py
src/soc/alu/input_stage.py
src/soc/alu/main_stage.py
src/soc/alu/output_stage.py
src/soc/alu/test/test_pipe_caller.py

index 98643a28a9b8b75cc90002660300d3daf3751d59..347ab7d42e6be01d7ad8dd0daf0e62b6d3865aa1 100644 (file)
@@ -41,11 +41,9 @@ class Driver(Elaboratable):
                  dut.i.b.eq(b),
                  a.eq(AnyConst(64)),
                  b.eq(AnyConst(64))]
-                      
 
         comb += dut.i.ctx.op.eq(rec)
 
-
         # Assert that op gets copied from the input to output
         for p in rec.ports():
             name = p.name
@@ -53,28 +51,16 @@ class Driver(Elaboratable):
             dut_sig = getattr(dut.o.ctx.op, name)
             comb += Assert(dut_sig == rec_sig)
 
-        with m.If(rec.insn_type != InternalOp.OP_CMP):
-            with m.If(rec.invert_a):
-                comb += Assert(dut.o.a == ~a)
-            with m.Else():
-                comb += Assert(dut.o.a == a)
-
-            comb += Assert(dut.o.b == b)
+        with m.If(rec.invert_a):
+            comb += Assert(dut.o.a == ~a)
         with m.Else():
-            with m.If(rec.invert_a):
-                comb += Assert(dut.o.a == ~b)
-            with m.Else():
-                comb += Assert(dut.o.a == b)
-
-            comb += Assert(dut.o.b == a)
-
-            
-
-
+            comb += Assert(dut.o.a == a)
 
+        comb += Assert(dut.o.b == b)
 
         return m
 
+
 class GTCombinerTestCase(FHDLTestCase):
     def test_formal(self):
         module = Driver()
index ef26b97716597d7a3b490e562500bbd0a07ea239..5a325f51dec7d6f573d6cbb20a7d45b990911df0 100644 (file)
@@ -29,22 +29,13 @@ class ALUInputStage(PipeModBase):
         # operand a to be as-is or inverted
         a = Signal.like(self.i.a)
 
-        with m.If(self.i.ctx.op.insn_type != InternalOp.OP_CMP):
-            with m.If(self.i.ctx.op.invert_a):
-                comb += a.eq(~self.i.a)
-            with m.Else():
-                comb += a.eq(self.i.a)
-
-            comb += self.o.a.eq(a)
-            comb += self.o.b.eq(self.i.b)
+        with m.If(self.i.ctx.op.invert_a):
+            comb += a.eq(~self.i.a)
         with m.Else():
-            with m.If(self.i.ctx.op.invert_a):
-                comb += self.o.a.eq(~self.i.b)
-            with m.Else():
-                comb += self.o.a.eq(self.i.b)
-
-            comb += self.o.b.eq(self.i.a)
+            comb += a.eq(self.i.a)
 
+        comb += self.o.a.eq(a)
+        comb += self.o.b.eq(self.i.b)
 
         ##### carry-in #####
 
index 0e628e043840d14c1d4826896e21c540ac4f6732..ad4e8e878dc66c3c204dedd36371eb66db02f006 100644 (file)
@@ -31,8 +31,6 @@ class ALUMainStage(PipeModBase):
         comb += is_32bit.eq(self.i.ctx.op.is_32bit)
         comb += sign_bit.eq(Mux(is_32bit, self.i.a[31], self.i.a[63]))
 
-
-
         # little trick: do the add using only one add (not 2)
         add_a = Signal(self.i.a.width + 2, reset_less=True)
         add_b = Signal(self.i.a.width + 2, reset_less=True)
index 5de9bbd0e50f99b761acbf3f799e7d5a01f49608..2f04ac9f7efc17780a87776be7709a8365a63b8d 100644 (file)
@@ -34,14 +34,17 @@ class ALUOutputStage(PipeModBase):
         is_positive = Signal(reset_less=True)
         is_negative = Signal(reset_less=True)
         msb_test = Signal(reset_less=True) # set equal to MSB, invert if OP=CMP
+        is_cmp = Signal(reset_less=True)   # true if OP=CMP
         so = Signal(reset_less=True)
 
         # TODO: if o[63] is XORed with "operand == OP_CMP"
         # that can be used as a test
         # see https://bugs.libre-soc.org/show_bug.cgi?id=305#c60
+        comb += is_cmp.eq(self.i.ctx.op.insn_type == InternalOp.OP_CMP)
+        comb += msb_test.eq(o[-1] ^ is_cmp)
         comb += is_zero.eq(o == 0)
-        comb += is_positive.eq(~is_zero & ~o[63])
-        comb += is_negative.eq(~is_zero & o[63])
+        comb += is_positive.eq(~is_zero & ~msb_test)
+        comb += is_negative.eq(~is_zero & msb_test)
         comb += so.eq(self.i.so | self.i.ov)
 
         comb += self.o.o.eq(o)
index 95f721a487963e5b11d0a528c9ec1473ec0bf6a6..c38d5c47cf14a0de38fbad66c2646d6d15b6faa4 100644 (file)
@@ -229,25 +229,26 @@ class TestRunner(FHDLTestCase):
                         print(f"expected {expected:x}, actual: {alu_out:x}")
                         self.assertEqual(expected, alu_out)
                     yield from self.check_extra_alu_outputs(alu, pdecode2,
-                                                            simulator)
+                                                            simulator, code)
 
         sim.add_sync_process(process)
         with sim.write_vcd("simulator.vcd", "simulator.gtkw",
                             traces=[]):
             sim.run()
-    def check_extra_alu_outputs(self, alu, dec2, sim):
+
+    def check_extra_alu_outputs(self, alu, dec2, sim, code):
         rc = yield dec2.e.rc.data
         if rc:
             cr_expected = sim.crl[0].get_range().value
             cr_actual = yield alu.n.data_o.cr0
-            self.assertEqual(cr_expected, cr_actual)
+            self.assertEqual(cr_expected, cr_actual, code)
 
         op = yield dec2.e.insn_type
         if op == InternalOp.OP_CMP.value:
             bf = yield dec2.dec.BF
             cr_actual = yield alu.n.data_o.cr0
             cr_expected = sim.crl[bf].get_range().value
-            self.assertEqual(cr_expected, cr_actual)
+            self.assertEqual(cr_expected, cr_actual, code)