From ca78c08e00dc775636a2d667b569c60572a28b07 Mon Sep 17 00:00:00 2001 From: Jacob Lifshay Date: Tue, 9 Jun 2020 23:53:06 -0700 Subject: [PATCH] create div pipe setup stage --- src/soc/fu/div/main_stage.py | 58 ------------------------- src/soc/fu/div/pipe_data.py | 45 ++++++++++++++++++- src/soc/fu/div/setup_stage.py | 82 +++++++++++++++++++++++++++++++++++ 3 files changed, 126 insertions(+), 59 deletions(-) delete mode 100644 src/soc/fu/div/main_stage.py create mode 100644 src/soc/fu/div/setup_stage.py diff --git a/src/soc/fu/div/main_stage.py b/src/soc/fu/div/main_stage.py deleted file mode 100644 index 5e5a8cdb..00000000 --- a/src/soc/fu/div/main_stage.py +++ /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 diff --git a/src/soc/fu/div/pipe_data.py b/src/soc/fu/div/pipe_data.py index 52ac0d92..c31641d6 100644 --- a/src/soc/fu/div/pipe_data.py +++ b/src/soc/fu/div/pipe_data.py @@ -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 index 00000000..6f04e839 --- /dev/null +++ b/src/soc/fu/div/setup_stage.py @@ -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 -- 2.30.2