Implement OP_CMP
authorMichael Nolan <mtnolan2640@gmail.com>
Thu, 14 May 2020 15:40:22 +0000 (11:40 -0400)
committerMichael Nolan <mtnolan2640@gmail.com>
Thu, 14 May 2020 15:40:22 +0000 (11:40 -0400)
Had to reverse the a and b inputs if a cmp is detected though. Ugh

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

index bb62fb67c5a392c824e8afaf8b97e90723d88377..98643a28a9b8b75cc90002660300d3daf3751d59 100644 (file)
@@ -53,16 +53,22 @@ class Driver(Elaboratable):
             dut_sig = getattr(dut.o.ctx.op, name)
             comb += Assert(dut_sig == rec_sig)
 
-        with m.If(rec.invert_a):
-            comb += Assert(dut.o.a == ~a)
-        with m.Else():
-            comb += Assert(dut.o.a == a)
+        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)
 
-        with m.If(rec.imm_data.imm_ok &
-                  ~(rec.insn_type == InternalOp.OP_RLC)):
-            comb += Assert(dut.o.b == rec.imm_data.imm)
-        with m.Else():
             comb += Assert(dut.o.b == b)
+        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)
+
+            
 
 
 
index e6ab48ea32dba22bf55831b33b42891118b524e1..ef26b97716597d7a3b490e562500bbd0a07ea239 100644 (file)
@@ -29,20 +29,22 @@ class ALUInputStage(PipeModBase):
         # operand a to be as-is or inverted
         a = Signal.like(self.i.a)
 
-        with m.If(self.i.ctx.op.invert_a):
-            comb += a.eq(~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.Else():
-            comb += a.eq(self.i.a)
+            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.a.eq(a)
+            comb += self.o.b.eq(self.i.a)
 
-        ##### operand B #####
-
-        # TODO: see https://bugs.libre-soc.org/show_bug.cgi?id=305#c43
-        # remove this, just do self.o.b.eq(self.i.b) and move the
-        # immediate-detection into set_alu_inputs in the unit test
-        # If there's an immediate, set the B operand to that
-        comb += self.o.b.eq(self.i.b)
 
         ##### carry-in #####
 
index 456e652fe3770b0399b862285898661dae1a4927..0e628e043840d14c1d4826896e21c540ac4f6732 100644 (file)
@@ -31,23 +31,29 @@ 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)
+        add_output = Signal(self.i.a.width + 2, reset_less=True)
+        with m.If((self.i.ctx.op.insn_type == InternalOp.OP_ADD) |
+                  (self.i.ctx.op.insn_type == InternalOp.OP_CMP)):
+            # in bit 0, 1+carry_in creates carry into bit 1 and above
+            comb += add_a.eq(Cat(self.i.carry_in, self.i.a, Const(0, 1)))
+            comb += add_b.eq(Cat(Const(1, 1), self.i.b, Const(0, 1)))
+            comb += add_output.eq(add_a + add_b)
+
         ##########################
         # main switch-statement for handling arithmetic operations
 
         with m.Switch(self.i.ctx.op.insn_type):
             #### CMP, CMPL ####
-            # TODO with m.Case(InternalOp.OP_CMP):
+            with m.Case(InternalOp.OP_CMP):
+                comb += o.eq(add_output[1:-1])
 
             #### add ####
             with m.Case(InternalOp.OP_ADD):
-                # 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)
-                add_output = Signal(self.i.a.width + 2, reset_less=True)
-                # in bit 0, 1+carry_in creates carry into bit 1 and above
-                comb += add_a.eq(Cat(self.i.carry_in, self.i.a, Const(0, 1)))
-                comb += add_b.eq(Cat(Const(1, 1), self.i.b, Const(0, 1)))
-                comb += add_output.eq(add_a + add_b)
                 # bit 0 is not part of the result, top bit is the carry-out
                 comb += o.eq(add_output[1:-1])
                 comb += carry_out.eq(add_output[-1])
index c7afb9a634d96dd7f68a557ef33ce886e061aab1..95f721a487963e5b11d0a528c9ec1473ec0bf6a6 100644 (file)
@@ -6,7 +6,7 @@ import unittest
 from soc.decoder.isa.caller import ISACaller, special_sprs
 from soc.decoder.power_decoder import (create_pdecode)
 from soc.decoder.power_decoder2 import (PowerDecode2)
-from soc.decoder.power_enums import (XER_bits, Function)
+from soc.decoder.power_enums import (XER_bits, Function, InternalOp)
 from soc.decoder.selectable_int import SelectableInt
 from soc.simulator.program import Program
 from soc.decoder.isa.all import ISA
@@ -70,7 +70,7 @@ def set_extra_alu_inputs(alu, dec2, sim):
     yield alu.p.data_i.carry_in.eq(carry)
     so = 1 if sim.spr['XER'][XER_bits['SO']] else 0
     yield alu.p.data_i.so.eq(so)
-    
+
 
 # This test bench is a bit different than is usual. Initially when I
 # was writing it, I had all of the tests call a function to create a
@@ -134,10 +134,11 @@ class ALUTestCase(FHDLTestCase):
         self.run_tst_program(Program(lst), initial_regs, initial_sprs)
 
     def test_cmp(self):
-        lst = ["cmp cr2, 1, 6, 7"]
+        lst = ["subf. 1, 6, 7",
+               "cmp cr2, 1, 6, 7"]
         initial_regs = [0] * 32
-        initial_regs[6] = random.randint(0, (1<<64)-1)
-        initial_regs[7] = random.randint(0, (1<<64)-1)
+        initial_regs[6] = 0x10
+        initial_regs[7] = 0x05
         self.run_tst_program(Program(lst), initial_regs, {})
 
     def test_extsb(self):
@@ -210,7 +211,7 @@ class TestRunner(FHDLTestCase):
                     self.assertEqual(fn_unit, Function.ALU.value)
                     yield from set_alu_inputs(alu, pdecode2, simulator)
                     yield from set_extra_alu_inputs(alu, pdecode2, simulator)
-                    yield 
+                    yield
                     opname = code.split(' ')[0]
                     yield from simulator.call(opname)
                     index = simulator.pc.CIA.value//4
@@ -241,6 +242,14 @@ class TestRunner(FHDLTestCase):
             cr_actual = yield alu.n.data_o.cr0
             self.assertEqual(cr_expected, cr_actual)
 
+        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)
+
+
 
 if __name__ == "__main__":
     unittest.main(exit=False)