code-morph on div pipeline
authorLuke Kenneth Casson Leighton <lkcl@lkcl.net>
Tue, 30 Jun 2020 10:57:00 +0000 (11:57 +0100)
committerLuke Kenneth Casson Leighton <lkcl@lkcl.net>
Tue, 30 Jun 2020 10:57:00 +0000 (11:57 +0100)
src/soc/fu/README.md
src/soc/fu/div/output_stage.py
src/soc/fu/div/pipe_data.py
src/soc/fu/div/setup_stage.py

index fad4daef7856bd55d9555788cff51232ae24227c..dc09399f5f1af1307b6236d29140af2590dc3684 100644 (file)
@@ -8,6 +8,18 @@ as follows:
 * XXX_input_record.py: a PowerISA decoded instruction subset for this pipeline
 * pipeline.py: the actual pipeline chain, which brings all stages together
 
+# Computation Units
+
+A subdirectory named compunits contains the 6600 style "Comp Units".
+These are pipeline managers whose sole job is to monitor the operation
+in its entirety from start to finish, including receiving of all
+operands and the storage of all results. AT NO TIME does a Comp Unit
+"abandon" data to a pipeline.
+
+Each pipeline is given a Como Umit frontend.  The base class uses regsoecs
+to construct the required latches in order to send and receive dsta to
+and from the required Register Files.
+
 # Common files
 
 * regspec.py: the register specification API.  used by each pipe_data.py
index 88a9ec1eec4bbc4ebb3fece42bbe235a13ae57ff..1db0bbb25d3c93eb58268ae9f2cdca36c7d0f027 100644 (file)
@@ -74,9 +74,9 @@ class DivOutputStage(PipeModBase):
                 comb += xer_ov.eq(overflow)
 
         with m.If(op.is_32bit):
-            calc_overflow(self.i.dive_abs_overflow_32, 0x8000_0000)
+            calc_overflow(self.i.dive_abs_ov32, 0x80000000)
         with m.Else():
-            calc_overflow(self.i.dive_abs_overflow_64, 0x8000_0000_0000_0000)
+            calc_overflow(self.i.dive_abs_ov64, 0x8000000000000000)
 
         ##########################
         # main switch for DIV
index fcaa734152c38d77ce2be08c20c218e34600cdb9..035290ab6dc50c99d36039b966e65bb048d9677b 100644 (file)
@@ -38,8 +38,8 @@ class CoreBaseData(DIVInputData):
         # set if an overflow for divide extended instructions is detected
         # because `abs_dividend >= abs_divisor` for the appropriate bit width;
         # 0 if the instruction is not a divide extended instruction
-        self.dive_abs_overflow_32 = Signal(reset_less=True)
-        self.dive_abs_overflow_64 = Signal(reset_less=True)
+        self.dive_abs_ov32 = Signal(reset_less=True)
+        self.dive_abs_ov64 = Signal(reset_less=True)
 
     def __iter__(self):
         yield from super().__iter__()
index 79d170b2a60dfd462c47a0608c357b87bab899e8..a0ea42edf914527a1936f4bec85d772258cc2e1e 100644 (file)
@@ -13,14 +13,16 @@ from soc.decoder.power_fieldsn import SignalBitRange
 from soc.fu.div.pipe_data import CoreInputData
 from ieee754.div_rem_sqrt_rsqrt.core import DivPipeCoreOperation
 
+def eq32(is_32bit, dest, src):
+    return [dest[0:32].eq(src[0:32]),
+            dest[32:64].eq(Mux(is_32bit, 0, src[32:64]))]
+
 
 class DivSetupStage(PipeModBase):
     def __init__(self, pspec):
         super().__init__(pspec, "setup_stage")
         self.fields = DecodeFields(SignalBitRange, [self.i.ctx.op.insn])
         self.fields.create_specs()
-        self.abs_divisor = Signal(64)
-        self.abs_dividend = Signal(64)
 
     def ispec(self):
         return DIVInputData(self.pspec)
@@ -31,61 +33,59 @@ class DivSetupStage(PipeModBase):
     def elaborate(self, platform):
         m = Module()
         comb = m.d.comb
+        # convenience variables
         op, a, b = self.i.ctx.op, self.i.a, self.i.b
         core_o = self.o.core
-        dividend_neg = self.o.dividend_neg
-        divisor_neg = self.o.divisor_neg
+        dividend_neg_o = self.o.dividend_neg
+        divisor_neg_o = self.o.divisor_neg
         dividend_o = core_o.dividend
         divisor_o = core_o.divisor_radicand
 
+        # set operation to unsigned div/remainder
         comb += core_o.operation.eq(int(DivPipeCoreOperation.UDivRem))
 
-        comb += dividend_neg.eq(Mux(op.is_32bit, a[31], a[63]) & op.is_signed)
-        comb += divisor_neg.eq(Mux(op.is_32bit, b[31], b[63]) & op.is_signed)
+        # work out if a/b are negative (check 32-bit / signed)
+        comb += dividend_neg_o.eq(Mux(op.is_32bit, a[31], a[63]) & op.is_signed)
+        comb += divisor_neg_o.eq(Mux(op.is_32bit, b[31], b[63]) & op.is_signed)
 
         # negation of a 64-bit value produces the same lower 32-bit
         # result as negation of just the lower 32-bits, so we don't
         # need to do anything special before negating
-        comb += self.abs_divisor.eq(Mux(divisor_neg, -b, b))
-        comb += self.abs_dividend.eq(Mux(dividend_neg, -a, a))
+        abs_dor = Signal(64, reset_less=True) # absolute of divisor
+        abs_dend = Signal(64, reset_less=True) # absolute of dividend
+        comb += abs_dor.eq(Mux(divisor_neg_o, -b, b))
+        comb += abs_dend.eq(Mux(dividend_neg_o, -a, a))
 
-        comb += self.o.dive_abs_overflow_64.eq(
-            (self.abs_dividend >= self.abs_divisor)
-            & (op.insn_type == InternalOp.OP_DIVE))
+        # check for absolute overflow condition (32/64)
+        comb += self.o.dive_abs_ov64.eq((abs_dend >= abs_dor)
+                                        & (op.insn_type == InternalOp.OP_DIVE))
 
-        comb += self.o.dive_abs_overflow_32.eq(
-            (self.abs_dividend[0:32] >= self.abs_divisor[0:32])
-            & (op.insn_type == InternalOp.OP_DIVE))
+        comb += self.o.dive_abs_ov32.eq((abs_dend[0:32] >= abs_dor[0:32])
+                                        & (op.insn_type == InternalOp.OP_DIVE))
 
-        with m.If(op.is_32bit):
-            comb += divisor_o.eq(self.abs_divisor[0:32])
-        with m.Else():
-            comb += divisor_o.eq(self.abs_divisor[0:64])
+        # set divisor based on 32/64 bit mode (must be absolute)
+        comb += eq32(op.is_32bit, divisor_o, abs_dor)
 
+        # divide by zero error detection
         comb += self.o.div_by_zero.eq(divisor_o == 0)
 
         ##########################
         # main switch for DIV
 
         with m.Switch(op.insn_type):
+            # div/mod takes straight (absolute) dividend
             with m.Case(InternalOp.OP_DIV, InternalOp.OP_MOD):
-                with m.If(op.is_32bit):
-                    comb += dividend_o.eq(self.abs_dividend[0:32])
-                with m.Else():
-                    comb += dividend_o.eq(self.abs_dividend[0:64])
+                comb += eq32(op.is_32bit, dividend_o, abs_dend)
+            # extended div shifts dividend up
             with m.Case(InternalOp.OP_DIVE):
                 with m.If(op.is_32bit):
-                    comb += dividend_o.eq(self.abs_dividend[0:32] << 32)
+                    comb += dividend_o.eq(abs_dend[0:32] << 32)
                 with m.Else():
-                    comb += dividend_o.eq(self.abs_dividend[0:64] << 64)
+                    comb += dividend_o.eq(abs_dend[0:64] << 64)
 
         ###### sticky overflow and context, both pass-through #####
 
         comb += self.o.xer_so.eq(self.i.xer_so)
         comb += self.o.ctx.eq(self.i.ctx)
 
-        # pass through core data
-
-        comb += self.o.core.eq(core_o)
-
         return m