normalise XER regs carry/32 and SO
authorLuke Kenneth Casson Leighton <lkcl@lkcl.net>
Wed, 20 May 2020 16:47:41 +0000 (17:47 +0100)
committerLuke Kenneth Casson Leighton <lkcl@lkcl.net>
Wed, 20 May 2020 16:47:41 +0000 (17:47 +0100)
src/soc/fu/alu/input_stage.py
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
src/soc/fu/logical/main_stage.py
src/soc/fu/logical/pipe_data.py
src/soc/fu/logical/test/test_pipe_caller.py

index fd3fd1edd78c097acc7d242781e52ac317fac6dc..426f1248a5fbea6db594df71c2d9464f836c714e 100644 (file)
@@ -1,5 +1,5 @@
 # This stage is intended to adjust the input data before sending it to
-# the acutal ALU. Things like handling inverting the input, carry_in
+# the acutal ALU. Things like handling inverting the input, xer_ca
 # generation for subtraction, and handling of immediates should happen
 # here
 from nmigen import (Module, Signal, Cat, Const, Mux, Repl, signed,
@@ -43,15 +43,15 @@ class ALUInputStage(PipeModBase):
         # either copy incoming carry or set to 1/0 as defined by op
         with m.Switch(ctx.op.input_carry):
             with m.Case(CryIn.ZERO):
-                comb += self.o.carry_in.eq(0)
+                comb += self.o.xer_ca.eq(0b00)
             with m.Case(CryIn.ONE):
-                comb += self.o.carry_in.eq(1)
+                comb += self.o.xer_ca.eq(0b11) # set both CA and CA32
             with m.Case(CryIn.CA):
-                comb += self.o.carry_in.eq(self.i.carry_in)
+                comb += self.o.xer_ca.eq(self.i.xer_ca)
 
         ##### sticky overflow and context (both pass-through) #####
 
-        comb += self.o.so.eq(self.i.so)
+        comb += self.o.xer_so.eq(self.i.xer_so)
         comb += self.o.ctx.eq(ctx)
 
         return m
index 6eeb2ca388de123e8c8012ef077133c35ed3ae27..2173814465efa1b014248849c4ee1d240e226c30 100644 (file)
@@ -24,8 +24,8 @@ class ALUMainStage(PipeModBase):
     def elaborate(self, platform):
         m = Module()
         comb = m.d.comb
-        cry_o, o, cr0 = self.o.xer_co, self.o.o, self.o.cr0
-        a, b, cry_i, op = self.i.a, self.i.b, self.i.carry_in, self.i.ctx.op
+        cry_o, o, cr0 = self.o.xer_ca, self.o.o, self.o.cr0
+        a, b, cry_i, op = self.i.a, self.i.b, self.i.xer_ca, self.i.ctx.op
 
         # check if op is 32-bit, and get sign bit from operand a
         is_32bit = Signal(reset_less=True)
@@ -40,7 +40,7 @@ class ALUMainStage(PipeModBase):
         with m.If((op.insn_type == InternalOp.OP_ADD) |
                   (op.insn_type == InternalOp.OP_CMP)):
             # in bit 0, 1+carry_in creates carry into bit 1 and above
-            comb += add_a.eq(Cat(cry_i, a, Const(0, 1)))
+            comb += add_a.eq(Cat(cry_i[0], a, Const(0, 1)))
             comb += add_b.eq(Cat(Const(1, 1), b, Const(0, 1)))
             comb += add_o.eq(add_a + add_b)
 
@@ -86,7 +86,7 @@ class ALUMainStage(PipeModBase):
 
         ###### sticky overflow and context, both pass-through #####
 
-        comb += self.o.xer_so.data.eq(self.i.so)
+        comb += self.o.xer_so.data.eq(self.i.xer_so)
         comb += self.o.ctx.eq(self.i.ctx)
 
         return m
index 08946de12cb5e8dc3ab0d0fa67a6d92ec27a7026..8b95334702bcc2d0969a017e1fab312c165c09a0 100644 (file)
@@ -38,8 +38,8 @@ class ALUOutputStage(PipeModBase):
             comb += target.eq(o)
 
         # Handle carry_out
-        comb += self.o.xer_co.data.eq(self.i.xer_co.data)
-        comb += self.o.xer_co.ok.eq(op.output_carry)
+        comb += self.o.xer_ca.data.eq(self.i.xer_ca.data)
+        comb += self.o.xer_ca.ok.eq(op.output_carry)
 
         # create condition register cr0 and sticky-overflow
         is_zero = Signal(reset_less=True)
index 744db57a6c9e4678ffe689e7149aa1f04d98761b..0d299ef477e987d466d5e5fcda0e3e6cc836b39a 100644 (file)
@@ -25,21 +25,21 @@ class ALUInputData(IntegerData):
         super().__init__(pspec)
         self.a = Signal(64, reset_less=True) # RA
         self.b = Signal(64, reset_less=True) # RB/immediate
-        self.so = Signal(reset_less=True)
-        self.carry_in = Signal(reset_less=True)
+        self.xer_so = Signal(reset_less=True) # XER bit 32: SO
+        self.xer_ca = Signal(2, reset_less=True) # XER bit 34/45: CA/CA32
 
     def __iter__(self):
         yield from super().__iter__()
         yield self.a
         yield self.b
-        yield self.carry_in
-        yield self.so
+        yield self.xer_ca
+        yield self.xer_so
 
     def eq(self, i):
         lst = super().eq(i)
         return lst + [self.a.eq(i.a), self.b.eq(i.b),
-                      self.carry_in.eq(i.carry_in),
-                      self.so.eq(i.so)]
+                      self.xer_ca.eq(i.xer_ca),
+                      self.xer_so.eq(i.xer_so)]
 
 # TODO: ALUIntermediateData which does not have
 # cr0, ov, ov32 in it (because they are generated as outputs by
@@ -51,14 +51,14 @@ class ALUOutputData(IntegerData):
         super().__init__(pspec)
         self.o = Signal(64, reset_less=True, name="stage_o")
         self.cr0 = Data(4, name="cr0")
-        self.xer_co = Data(2, name="xer_co") # bit0: co, bit1: co32
+        self.xer_ca = Data(2, name="xer_co") # bit0: ca, bit1: ca32
         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.xer_co
+        yield self.xer_ca
         yield self.cr0
         yield self.xer_ov
         yield self.xer_so
@@ -66,7 +66,7 @@ class ALUOutputData(IntegerData):
     def eq(self, i):
         lst = super().eq(i)
         return lst + [self.o.eq(i.o),
-                      self.xer_co.eq(i.xer_co),
+                      self.xer_ca.eq(i.xer_ca),
                       self.cr0.eq(i.cr0),
                       self.xer_ov.eq(i.xer_ov), self.xer_so.eq(i.xer_so)]
 
index 4f682f6751373ebd1d3dfef00cd4f8ae04a1baa5..875bfab43bcea61ee85e94fe28d7b3b3ee4458cf 100644 (file)
@@ -67,9 +67,11 @@ def set_alu_inputs(alu, dec2, sim):
 
 def set_extra_alu_inputs(alu, dec2, sim):
     carry = 1 if sim.spr['XER'][XER_bits['CA']] else 0
-    yield alu.p.data_i.carry_in.eq(carry)
+    carry32 = 1 if sim.spr['XER'][XER_bits['CA32']] else 0
+    yield alu.p.data_i.xer_ca[0].eq(carry)
+    yield alu.p.data_i.xer_ca[1].eq(carry32)
     so = 1 if sim.spr['XER'][XER_bits['SO']] else 0
-    yield alu.p.data_i.so.eq(so)
+    yield alu.p.data_i.xer_so.eq(so)
 
 
 # This test bench is a bit different than is usual. Initially when I
@@ -236,7 +238,7 @@ class TestRunner(FHDLTestCase):
                         write_reg_idx = yield pdecode2.e.write_reg.data
                         expected = simulator.gpr(write_reg_idx).value
                         print(f"expected {expected:x}, actual: {alu_out:x}")
-                        self.assertEqual(expected, alu_out)
+                        self.assertEqual(expected, alu_out, code)
                     yield from self.check_extra_alu_outputs(alu, pdecode2,
                                                             simulator, code)
 
@@ -263,10 +265,10 @@ class TestRunner(FHDLTestCase):
         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.xer_co.data[0] # XXX CO not CO32
+            real_carry = yield alu.n.data_o.xer_ca.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
+            real_carry32 = yield alu.n.data_o.xer_ca.data[1] # XXX CO32
             self.assertEqual(expected_carry32, real_carry32, code)
 
 
index 9c223ddceaa979363c21341f2d9f721e347da5ea..4885708997b835b62a0be10b25bb2c5ee8cdf7ac 100644 (file)
@@ -132,7 +132,7 @@ class LogicalMainStage(PipeModBase):
 
         ###### sticky overflow and context, both pass-through #####
 
-        comb += self.o.xer_so.data.eq(self.i.so)
+        comb += self.o.xer_so.data.eq(self.i.xer_so)
         comb += self.o.ctx.eq(self.i.ctx)
 
         return m
index 3b1b13513a4a6b07ea549623f02c42a6c4821335..aed7868977d08e06aaaadf9cca38b19036153d1d 100644 (file)
@@ -8,18 +8,18 @@ class LogicalInputData(IntegerData):
         super().__init__(pspec)
         self.a = Signal(64, reset_less=True) # RA
         self.b = Signal(64, reset_less=True) # RB/immediate
-        self.so = Signal(reset_less=True)
-        self.carry_in = Signal(reset_less=True)
+        self.xer_so = Signal(reset_less=True)    # XER bit 32: SO
+        self.xer_ca = Signal(2, reset_less=True) # XER bit 34/45: CA/CA32
 
     def __iter__(self):
         yield from super().__iter__()
         yield self.a
         yield self.b
-        yield self.carry_in
-        yield self.so
+        yield self.xer_ca
+        yield self.xer_so
 
     def eq(self, i):
         lst = super().eq(i)
         return lst + [self.a.eq(i.a), self.b.eq(i.b),
-                      self.carry_in.eq(i.carry_in),
-                      self.so.eq(i.so)]
+                      self.xer_ca.eq(i.xer_ca),
+                      self.xer_so.eq(i.xer_so)]
index 05e1a816967ac3f019c8a407ce348bb72688a1c8..4a22308c071ef86cde9bfd8f2e3b5a1d4b348f48 100644 (file)
@@ -68,9 +68,11 @@ def set_alu_inputs(alu, dec2, sim):
 
 def set_extra_alu_inputs(alu, dec2, sim):
     carry = 1 if sim.spr['XER'][XER_bits['CA']] else 0
-    yield alu.p.data_i.carry_in.eq(carry)
+    carry32 = 1 if sim.spr['XER'][XER_bits['CA32']] else 0
+    yield alu.p.data_i.xer_ca[0].eq(carry)
+    yield alu.p.data_i.xer_ca[1].eq(carry32)
     so = 1 if sim.spr['XER'][XER_bits['SO']] else 0
-    yield alu.p.data_i.so.eq(so)
+    yield alu.p.data_i.xer_so.eq(so)
     
 
 # This test bench is a bit different than is usual. Initially when I