split out Logical Input and Output stages to common code, allows removal
authorLuke Kenneth Casson Leighton <lkcl@lkcl.net>
Fri, 22 May 2020 18:19:16 +0000 (19:19 +0100)
committerLuke Kenneth Casson Leighton <lkcl@lkcl.net>
Fri, 22 May 2020 18:19:16 +0000 (19:19 +0100)
of XER.SO from Logical pipeline

src/soc/fu/alu/output_stage.py
src/soc/fu/common_input_stage.py
src/soc/fu/common_output_stage.py [new file with mode: 0644]
src/soc/fu/logical/main_stage.py
src/soc/fu/logical/pipe_data.py
src/soc/fu/logical/pipeline.py
src/soc/fu/logical/test/test_pipe_caller.py

index 8b95334702bcc2d0969a017e1fab312c165c09a0..e228e8719019a85c80f49cd1fdada045cd9d9a0f 100644 (file)
@@ -2,82 +2,38 @@
 # out, summary overflow generation, and updating the condition
 # register
 from nmigen import (Module, Signal, Cat, Repl)
-from nmutil.pipemodbase import PipeModBase
 from soc.fu.alu.pipe_data import ALUInputData, ALUOutputData
+from soc.fu.common_output_stage import CommonOutputStage
 from ieee754.part.partsig import PartitionedSignal
 from soc.decoder.power_enums import InternalOp
 
 
-class ALUOutputStage(PipeModBase):
-    def __init__(self, pspec):
-        super().__init__(pspec, "output")
+class ALUOutputStage(CommonOutputStage):
 
     def ispec(self):
-        return ALUOutputData(self.pspec) # TODO: ALUIntermediateData
+        return ALUOutputData(self.pspec)
 
     def ospec(self):
         return ALUOutputData(self.pspec)
 
     def elaborate(self, platform):
-        m = Module()
+        m = super().elaborate(platform)
         comb = m.d.comb
         op = self.i.ctx.op
 
-        # op requests inversion of the output
-        o = Signal.like(self.i.o)
-        with m.If(op.invert_out):
-            comb += o.eq(~self.i.o)
-        with m.Else():
-            comb += o.eq(self.i.o)
-
-        # target register if 32-bit is only the 32 LSBs
-        target = Signal(64, reset_less=True)
-        with m.If(op.is_32bit):
-            comb += target.eq(o[:32])
-        with m.Else():
-            comb += target.eq(o)
-
-        # Handle carry_out
-        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)
-        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(1, reset_less=True)
+        # create overflow
         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
-        # see https://bugs.libre-soc.org/show_bug.cgi?id=305#c60
 
-        comb += is_cmp.eq(op.insn_type == InternalOp.OP_CMP)
-        comb += msb_test.eq(target[-1] ^ is_cmp)
-        comb += is_zero.eq(target == 0)
-        comb += is_positive.eq(~is_zero & ~msb_test)
-        comb += is_negative.eq(~is_zero & msb_test)
         # 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 += cr0.eq(Cat(so, is_zero, is_positive, is_negative))
-        with m.Else():
-            comb += cr0.eq(self.i.cr0)
+        comb += self.so.eq(self.i.xer_so.data | self.i.xer_ov.data[0]) # OV
 
-        # copy [inverted] cr0, output, sticky-overflow and context out
-        comb += self.o.o.eq(o)
-        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)
+        # copy overflow and sticky-overflow
+        comb += self.o.xer_so.data.eq(self.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 39c56a896457ecfb7ca121d064daa68b1008e1af..2f399b49e39b37b4bdf6e517e0850e8abe15ef85 100644 (file)
@@ -38,7 +38,8 @@ class CommonInputStage(PipeModBase):
 
         ##### sticky overflow and context (both pass-through) #####
 
-        comb += self.o.xer_so.eq(self.i.xer_so)
+        if hasattr(self.o, "xer_so"): # hack (for now - for LogicalInputData)
+            comb += self.o.xer_so.eq(self.i.xer_so)
         comb += self.o.ctx.eq(self.i.ctx)
 
         return m
diff --git a/src/soc/fu/common_output_stage.py b/src/soc/fu/common_output_stage.py
new file mode 100644 (file)
index 0000000..3a9916a
--- /dev/null
@@ -0,0 +1,66 @@
+# This stage is intended to handle the gating of carry out,
+# and updating the condition register
+from nmigen import (Module, Signal, Cat, Repl)
+from nmutil.pipemodbase import PipeModBase
+from ieee754.part.partsig import PartitionedSignal
+from soc.decoder.power_enums import InternalOp
+
+
+class CommonOutputStage(PipeModBase):
+    def __init__(self, pspec):
+        super().__init__(pspec, "output")
+
+    def elaborate(self, platform):
+        m = Module()
+        comb = m.d.comb
+        op = self.i.ctx.op
+
+        # op requests inversion of the output
+        o = Signal.like(self.i.o)
+        with m.If(op.invert_out):
+            comb += o.eq(~self.i.o)
+        with m.Else():
+            comb += o.eq(self.i.o)
+
+        # target register if 32-bit is only the 32 LSBs
+        target = Signal(64, reset_less=True)
+        with m.If(op.is_32bit):
+            comb += target.eq(o[:32])
+        with m.Else():
+            comb += target.eq(o)
+
+        # Handle carry_out
+        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)
+        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
+        self.so = Signal(1, reset_less=True)
+        cr0 = Signal(4, 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(op.insn_type == InternalOp.OP_CMP)
+        comb += msb_test.eq(target[-1] ^ is_cmp)
+        comb += is_zero.eq(target == 0)
+        comb += is_positive.eq(~is_zero & ~msb_test)
+        comb += is_negative.eq(~is_zero & msb_test)
+
+        with m.If(op.insn_type != InternalOp.OP_CMPEQB):
+            comb += cr0.eq(Cat(self.so, is_zero, is_positive, is_negative))
+        with m.Else():
+            comb += cr0.eq(self.i.cr0)
+
+        # copy out [inverted] cr0, output, and context out
+        comb += self.o.o.eq(o)
+        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.ctx.eq(self.i.ctx)
+
+        return m
index 8c3703e6f3b0ca872e45958c88a31756058ce6db..b40c91fdd85af11a0a2fb6b3f5c15432a91b5600 100644 (file)
@@ -10,7 +10,7 @@ from nmutil.pipemodbase import PipeModBase
 from nmutil.clz import CLZ
 from soc.fu.logical.pipe_data import LogicalInputData
 from soc.fu.logical.bpermd import Bpermd
-from soc.fu.alu.pipe_data import ALUOutputData
+from soc.fu.logical.pipe_data import LogicalOutputData
 from ieee754.part.partsig import PartitionedSignal
 from soc.decoder.power_enums import InternalOp
 
@@ -36,7 +36,7 @@ class LogicalMainStage(PipeModBase):
         return LogicalInputData(self.pspec)
 
     def ospec(self):
-        return ALUOutputData(self.pspec)  # TODO: ALUIntermediateData
+        return LogicalOutputData(self.pspec)
 
     def elaborate(self, platform):
         m = Module()
@@ -135,9 +135,8 @@ class LogicalMainStage(PipeModBase):
                 comb += bpermd.rb.eq(b)
                 comb += o.eq(bpermd.ra)
 
-        ###### sticky overflow and context, both pass-through #####
+        ###### context, pass-through #####
 
-        comb += self.o.xer_so.data.eq(self.i.xer_so)
         comb += self.o.ctx.eq(self.i.ctx)
 
         return m
index 332fd60e5db4ec434dd3423c7105dd15c94f7b67..9ded5f4ad357f129d1f5d6fcad51c16785db8479 100644 (file)
@@ -1,6 +1,7 @@
 from nmigen import Signal, Const
 from ieee754.fpcommon.getop import FPPipeContext
 from soc.fu.pipe_data import IntegerData
+from soc.decoder.power_decoder2 import Data
 from soc.fu.alu.pipe_data import ALUOutputData, CommonPipeSpec
 from soc.fu.logical.logical_input_record import CompLogicalOpSubset
 
@@ -8,13 +9,11 @@ from soc.fu.logical.logical_input_record import CompLogicalOpSubset
 class LogicalInputData(IntegerData):
     regspec = [('INT', 'a', '0:63'),
                ('INT', 'rb', '0:63'),
-               ('XER', 'xer_so', '32'),
                ('XER', 'xer_ca', '34,45')]
     def __init__(self, pspec):
         super().__init__(pspec)
         self.a = Signal(64, reset_less=True) # RA
         self.b = Signal(64, reset_less=True) # RB/immediate
-        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):
@@ -22,15 +21,40 @@ class LogicalInputData(IntegerData):
         yield self.a
         yield self.b
         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.xer_ca.eq(i.xer_ca) ]
+
+
+class LogicalOutputData(IntegerData):
+    regspec = [('INT', 'o', '0:63'),
+               ('CR', 'cr0', '0:3'),
+               ('XER', 'xer_ca', '34,45'),
+               ('XER', 'xer_so', '32')]
+    def __init__(self, pspec):
+        super().__init__(pspec)
+        self.o = Signal(64, reset_less=True, name="stage_o")
+        self.cr0 = Data(4, name="cr0")
+        self.xer_ca = Data(2, name="xer_co") # bit0: ca, bit1: ca32
+        self.xer_so = Data(1, name="xer_so")
+
+    def __iter__(self):
+        yield from super().__iter__()
+        yield self.o
+        yield self.xer_ca
+        yield self.cr0
+        yield self.xer_so
+
+    def eq(self, i):
+        lst = super().eq(i)
+        return lst + [self.o.eq(i.o),
                       self.xer_ca.eq(i.xer_ca),
+                      self.cr0.eq(i.cr0),
                       self.xer_so.eq(i.xer_so)]
 
 
 class LogicalPipeSpec(CommonPipeSpec):
-    regspec = (LogicalInputData.regspec, ALUOutputData.regspec)
+    regspec = (LogicalInputData.regspec, LogicalOutputData.regspec)
     opsubsetkls = CompLogicalOpSubset
index 1a2fd1fcc17d76a8d48525f509a9fe6331e99421..4ae1d1d42b8d89382c2a8e81118dbb7ee1c42082 100644 (file)
@@ -1,14 +1,14 @@
 from nmutil.singlepipe import ControlBase
 from nmutil.pipemodbase import PipeModBaseChain
-from soc.fu.alu.input_stage import ALUInputStage
+from soc.fu.logical.input_stage import LogicalInputStage
 from soc.fu.logical.main_stage import LogicalMainStage
-from soc.fu.alu.output_stage import ALUOutputStage
+from soc.fu.logical.output_stage import LogicalOutputStage
 
 class LogicalStages(PipeModBaseChain):
     def get_chain(self):
-        inp = ALUInputStage(self.pspec)
+        inp = LogicalInputStage(self.pspec)
         main = LogicalMainStage(self.pspec)
-        out = ALUOutputStage(self.pspec)
+        out = LogicalOutputStage(self.pspec)
         return [inp, main, out]
 
 
index 073aad72a47178f7dca60fff06fa40e8ca7985bb..adf0c4cc4b558107b1df07bc74fe4b5668e24d9a 100644 (file)
@@ -61,8 +61,6 @@ def set_extra_alu_inputs(alu, dec2, sim):
     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.xer_so.eq(so)
 
 
 # This test bench is a bit different than is usual. Initially when I