convert alu output to use Data for XER and CR0
authorLuke Kenneth Casson Leighton <lkcl@lkcl.net>
Wed, 20 May 2020 04:42:45 +0000 (05:42 +0100)
committerLuke Kenneth Casson Leighton <lkcl@lkcl.net>
Wed, 20 May 2020 04:42:45 +0000 (05:42 +0100)
src/soc/fu/alu/main_stage.py
src/soc/fu/alu/output_stage.py
src/soc/fu/alu/pipe_data.py
src/soc/fu/alu/test/test_pipe_caller.py

index dd03b7865e8c938126daf849c2ef5d3d25f6307b..2457a750ced415499eff1f2a72e73cac50b5be5b 100644 (file)
@@ -23,7 +23,7 @@ class ALUMainStage(PipeModBase):
     def elaborate(self, platform):
         m = Module()
         comb = m.d.comb
-        carry_out, o = self.o.carry_out, self.o.o
+        carry_out, o = self.o.xer_co, self.o.o
 
         # check if op is 32-bit, and get sign bit from operand a
         is_32bit = Signal(reset_less=True)
@@ -58,7 +58,11 @@ class ALUMainStage(PipeModBase):
             with m.Case(InternalOp.OP_ADD):
                 # 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])
+                comb += carry_out.data[0].eq(add_output[-1]) # XER.CO
+
+                # XXX no!  wrongggg, see microwatt OP_ADD code
+                # https://bugs.libre-soc.org/show_bug.cgi?id=319#c5
+                comb += carry_out.data[1].eq(add_output[-1]) # XER.CO32
 
             #### exts (sign-extend) ####
             with m.Case(InternalOp.OP_EXTS):
@@ -78,7 +82,7 @@ class ALUMainStage(PipeModBase):
 
         ###### sticky overflow and context, both pass-through #####
 
-        comb += self.o.so.eq(self.i.so)
+        comb += self.o.xer_so.data.eq(self.i.so)
         comb += self.o.ctx.eq(self.i.ctx)
 
         return m
index 24a47ce7179a73b82c7fba848ca6901bdd70a95d..08946de12cb5e8dc3ab0d0fa67a6d92ec27a7026 100644 (file)
@@ -38,8 +38,8 @@ class ALUOutputStage(PipeModBase):
             comb += target.eq(o)
 
         # Handle carry_out
-        with m.If(self.i.ctx.op.output_carry):
-            comb += self.o.carry_out.eq(self.i.carry_out)
+        comb += self.o.xer_co.data.eq(self.i.xer_co.data)
+        comb += self.o.xer_co.ok.eq(op.output_carry)
 
         # create condition register cr0 and sticky-overflow
         is_zero = Signal(reset_less=True)
@@ -47,7 +47,9 @@ class ALUOutputStage(PipeModBase):
         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)
+        so = Signal(1, reset_less=True)
+        ov = Signal(2, reset_less=True) # OV, OV32
+        cr0 = Signal(4, reset_less=True)
 
         # TODO: if o[63] is XORed with "operand == OP_CMP"
         # that can be used as a test
@@ -58,16 +60,24 @@ class ALUOutputStage(PipeModBase):
         comb += is_zero.eq(target == 0)
         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)
+        # XXX see https://bugs.libre-soc.org/show_bug.cgi?id=319#c5
+        comb += ov[0].eq(self.i.xer_so.data | self.i.xer_ov.data[0]) # OV
+        comb += ov[1].eq(self.i.xer_so.data | self.i.xer_ov.data[1]) # OV32 XXX!
+        comb += so.eq(self.i.xer_so.data | self.i.xer_ov.data[0]) # OV
 
         with m.If(op.insn_type != InternalOp.OP_CMPEQB):
-            comb += self.o.cr0.eq(Cat(so, is_zero, is_positive, is_negative))
+            comb += cr0.eq(Cat(so, is_zero, is_positive, is_negative))
         with m.Else():
-            comb += self.o.cr0.eq(self.i.cr0)
+            comb += cr0.eq(self.i.cr0)
 
-        # copy [inverted] output, sticky-overflow and context out
+        # copy [inverted] cr0, output, sticky-overflow and context out
         comb += self.o.o.eq(o)
-        comb += self.o.so.eq(so)
+        comb += self.o.cr0.data.eq(cr0)
+        comb += self.o.cr0.ok.eq(op.rc.rc & op.rc.rc_ok) # CR0 to be set
+        comb += self.o.xer_so.data.eq(so)
+        comb += self.o.xer_so.ok.eq(op.oe.oe & op.oe.oe_ok) # SO is to be set
+        comb += self.o.xer_ov.data.eq(ov)
+        comb += self.o.xer_ov.ok.eq(op.oe.oe & op.oe.oe_ok) # OV/32 is to be set
         comb += self.o.ctx.eq(self.i.ctx)
 
         return m
index 7c91349a0789675c6a4e40883c5147a729736849..744db57a6c9e4678ffe689e7149aa1f04d98761b 100644 (file)
@@ -2,7 +2,7 @@ from nmigen import Signal, Const
 from nmutil.dynamicpipe import SimpleHandshakeRedir
 from soc.fu.alu.alu_input_record import CompALUOpSubset
 from ieee754.fpcommon.getop import FPPipeContext
-
+from soc.decoder.power_decoder2 import Data
 
 class IntegerData:
 
@@ -50,30 +50,25 @@ class ALUOutputData(IntegerData):
     def __init__(self, pspec):
         super().__init__(pspec)
         self.o = Signal(64, reset_less=True, name="stage_o")
-        self.carry_out = Signal(reset_less=True)
-        self.carry_out32 = Signal(reset_less=True)
-        self.cr0 = Signal(4, reset_less=True)
-        self.ov = Signal(reset_less=True)
-        self.ov32 = Signal(reset_less=True)
-        self.so = Signal(reset_less=True)
+        self.cr0 = Data(4, name="cr0")
+        self.xer_co = Data(2, name="xer_co") # bit0: co, bit1: co32
+        self.xer_ov = Data(2, name="xer_ov") # bit0: ov, bit1: ov32
+        self.xer_so = Data(1, name="xer_so")
 
     def __iter__(self):
         yield from super().__iter__()
         yield self.o
-        yield self.carry_out
-        yield self.carry_out32
+        yield self.xer_co
         yield self.cr0
-        yield self.ov
-        yield self.ov32
-        yield self.so
+        yield self.xer_ov
+        yield self.xer_so
 
     def eq(self, i):
         lst = super().eq(i)
         return lst + [self.o.eq(i.o),
-                      self.carry_out.eq(i.carry_out),
-                      self.carry_out32.eq(i.carry_out32),
-                      self.cr0.eq(i.cr0), self.ov.eq(i.ov),
-                      self.ov32.eq(i.ov32), self.so.eq(i.so)]
+                      self.xer_co.eq(i.xer_co),
+                      self.cr0.eq(i.cr0),
+                      self.xer_ov.eq(i.xer_ov), self.xer_so.eq(i.xer_so)]
 
 
 class IntPipeSpec:
index 94fcad78e03bb831de37e70e1f89a78f6b9f9b14..9a9e55714c6ac7cb286ec58fe7c04d8c0664f8be 100644 (file)
@@ -249,22 +249,25 @@ class TestRunner(FHDLTestCase):
         rc = yield dec2.e.rc.data
         if rc:
             cr_expected = sim.crl[0].get_range().value
-            cr_actual = yield alu.n.data_o.cr0
+            cr_actual = yield alu.n.data_o.cr0.data
             self.assertEqual(cr_expected, cr_actual, code)
 
         op = yield dec2.e.insn_type
         if op == InternalOp.OP_CMP.value or \
            op == InternalOp.OP_CMPEQB.value:
             bf = yield dec2.dec.BF
-            cr_actual = yield alu.n.data_o.cr0
+            cr_actual = yield alu.n.data_o.cr0.data
             cr_expected = sim.crl[bf].get_range().value
             self.assertEqual(cr_expected, cr_actual, code)
 
         cry_out = yield dec2.e.output_carry
         if cry_out:
             expected_carry = 1 if sim.spr['XER'][XER_bits['CA']] else 0
-            real_carry = yield alu.n.data_o.carry_out
-            self.assertEqual(expected_carry, real_carry)
+            real_carry = yield alu.n.data_o.xer_co.data[0] # XXX CO not CO32
+            self.assertEqual(expected_carry, real_carry, code)
+            expected_carry32 = 1 if sim.spr['XER'][XER_bits['CA32']] else 0
+            real_carry32 = yield alu.n.data_o.xer_co.data[1] # XXX CO32
+            self.assertEqual(expected_carry, real_carry, code)