create div pipe setup stage
authorJacob Lifshay <programmerjake@gmail.com>
Wed, 10 Jun 2020 06:53:06 +0000 (23:53 -0700)
committerJacob Lifshay <programmerjake@gmail.com>
Wed, 10 Jun 2020 06:53:06 +0000 (23:53 -0700)
src/soc/fu/div/main_stage.py [deleted file]
src/soc/fu/div/pipe_data.py
src/soc/fu/div/setup_stage.py [new file with mode: 0644]

diff --git a/src/soc/fu/div/main_stage.py b/src/soc/fu/div/main_stage.py
deleted file mode 100644 (file)
index 5e5a8cd..0000000
+++ /dev/null
@@ -1,58 +0,0 @@
-# This stage is intended to do most of the work of executing DIV
-# This module however should not gate the carry or overflow, that's up
-# to the output stage
-
-from nmigen import (Module, Signal, Cat, Repl, Mux, Const, Array)
-from nmutil.pipemodbase import PipeModBase
-from soc.fu.logical.pipe_data import LogicalInputData
-from soc.fu.alu.pipe_data import ALUOutputData
-from ieee754.part.partsig import PartitionedSignal
-from soc.decoder.power_enums import InternalOp
-
-from soc.decoder.power_fields import DecodeFields
-from soc.decoder.power_fieldsn import SignalBitRange
-
-
-class DivMainStage(PipeModBase):
-    def __init__(self, pspec):
-        super().__init__(pspec, "main")
-        self.fields = DecodeFields(SignalBitRange, [self.i.ctx.op.insn])
-        self.fields.create_specs()
-
-    def ispec(self):
-        return LogicalInputData(self.pspec)
-
-    def ospec(self):
-        return ALUOutputData(self.pspec)
-
-    def elaborate(self, platform):
-        m = Module()
-        comb = m.d.comb
-        op, a, b, o = self.i.ctx.op, self.i.a, self.i.b, self.o.o
-
-        ##########################
-        # main switch for DIV
-
-        with m.Switch(op.insn_type):
-
-            ###### AND, OR, XOR #######
-            with m.Case(InternalOp.OP_AND):
-                comb += o.eq(a & b)
-            with m.Case(InternalOp.OP_OR):
-                comb += o.eq(a | b)
-            with m.Case(InternalOp.OP_XOR):
-                comb += o.eq(a ^ b)
-
-            ###### bpermd #######
-            with m.Case(InternalOp.OP_BPERM):
-                m.submodules.bpermd = bpermd = Bpermd(64)
-                comb += bpermd.rs.eq(a)
-                comb += bpermd.rb.eq(b)
-                comb += o.eq(bpermd.ra)
-
-        ###### sticky overflow and context, both pass-through #####
-
-        comb += self.o.xer_so.data.eq(self.i.xer_so)
-        comb += self.o.ctx.eq(self.i.ctx)
-
-        return m
index 52ac0d92bd540c1de4338856984d74246960cd70..c31641d678dc50a47d22371cd07a67c42f00613b 100644 (file)
@@ -1,10 +1,53 @@
 from nmigen import Signal, Const
 from soc.fu.pipe_data import IntegerData
 from soc.fu.alu.pipe_data import ALUOutputData, CommonPipeSpec
-from soc.fu.alu.pipe_data import ALUInputData # TODO: check this
+from soc.fu.alu.pipe_data import ALUInputData  # TODO: check this
 from soc.fu.logical.logical_input_record import CompLogicalOpSubset
+from ieee754.div_rem_sqrt_rsqrt.core import (
+    DivPipeCoreConfig, DivPipeCoreInputData,
+    DivPipeCoreInterstageData, DivPipeCoreOutputData)
 
 
 class DivPipeSpec(CommonPipeSpec):
     regspec = (ALUInputData.regspec, ALUOutputData.regspec)
     opsubsetkls = CompLogicalOpSubset
+    core_config = DivPipeCoreConfig(
+        bit_width=64,
+        fract_width=64,
+        log2_radix=3,
+    )
+
+
+class CoreBaseData(ALUInputData):
+    def __init__(self, pspec, core_data_class):
+        super().__init__(pspec)
+        self.core = core_data_class(pspec.core_config)
+        self.divisor_neg = Signal(1, reset_less=True)
+        self.dividend_neg = Signal(1, reset_less=True)
+
+    def __iter__(self):
+        yield from super().__iter__()
+        yield from self.core.__iter__(self)
+        yield self.divisor_neg
+        yield self.dividend_neg
+
+    def eq(self, rhs):
+        return super().eq(rhs) + \
+            self.core.eq(rhs.core) + \
+            [self.divisor_neg.eq(rhs.divisor_neg),
+             self.dividend_neg.eq(rhs.dividend_neg)]
+
+
+class CoreInputData(CoreBaseData):
+    def __init__(self, pspec):
+        super().__init__(pspec, DivPipeCoreInputData)
+
+
+class CoreInterstageData(CoreBaseData):
+    def __init__(self, pspec):
+        super().__init__(pspec, DivPipeCoreInterstageData)
+
+
+class CoreOutputData(CoreBaseData):
+    def __init__(self, pspec):
+        super().__init__(pspec, DivPipeCoreOutputData)
diff --git a/src/soc/fu/div/setup_stage.py b/src/soc/fu/div/setup_stage.py
new file mode 100644 (file)
index 0000000..6f04e83
--- /dev/null
@@ -0,0 +1,82 @@
+# This stage is the setup stage that converts the inputs
+# into the values expected by DivPipeCore
+
+from nmigen import (Module, Signal, Cat, Repl, Mux, Const, Array)
+from nmutil.pipemodbase import PipeModBase
+from soc.fu.logical.pipe_data import LogicalInputData
+from soc.fu.alu.pipe_data import ALUOutputData
+from ieee754.part.partsig import PartitionedSignal
+from soc.decoder.power_enums import InternalOp
+
+from soc.decoder.power_fields import DecodeFields
+from soc.decoder.power_fieldsn import SignalBitRange
+from soc.fu.div.pipe_data import CoreInputData
+from ieee754.div_rem_sqrt_rsqrt.core import DivPipeCoreOperation
+
+
+class DivSetupStage(PipeModBase):
+    def __init__(self, pspec):
+        super().__init__(pspec, "main")
+        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 LogicalInputData(self.pspec)
+
+    def ospec(self):
+        return CoreInputData(self.pspec)
+
+    def elaborate(self, platform):
+        m = Module()
+        comb = m.d.comb
+        op, a, b = self.i.ctx.op, self.i.a, self.i.b
+        core_input_data = self.o.core
+        dividend_neg = self.o.dividend_neg
+        divisor_neg = self.o.divisor_neg
+        dividend_in = core_input_data.dividend
+        divisor_in = core_input_data.divisor_radicand
+
+        comb += core_input_data.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)
+
+        # 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))
+
+        with m.If(op.is_32bit):
+            comb += divisor_in.eq(self.abs_divisor[0:32])
+        with m.Else():
+            comb += divisor_in.eq(self.abs_divisor[0:64])
+
+        ##########################
+        # main switch for DIV
+
+        with m.Switch(op.insn_type):
+            with m.Case(InternalOp.OP_DIV, InternalOp.OP_MOD):
+                with m.If(op.is_32bit):
+                    comb += dividend_in.eq(self.abs_dividend[0:32])
+                with m.Else():
+                    comb += dividend_in.eq(self.abs_dividend[0:64])
+            with m.Case(InternalOp.OP_DIVE):
+                with m.If(op.is_32bit):
+                    comb += dividend_in.eq(self.abs_dividend[0:32] << 32)
+                with m.Else():
+                    comb += dividend_in.eq(self.abs_dividend[0:64] << 64)
+
+        ###### sticky overflow and context, both pass-through #####
+
+        comb += self.o.xer_so.data.eq(self.i.xer_so)
+        comb += self.o.ctx.eq(self.i.ctx)
+
+        # pass through op
+
+        comb += self.o.op.eq(op)
+
+        return m