+++ /dev/null
-# 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
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)
--- /dev/null
+# 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