From: Luke Kenneth Casson Leighton Date: Tue, 30 Jun 2020 10:57:00 +0000 (+0100) Subject: code-morph on div pipeline X-Git-Tag: div_pipeline~195 X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=387adb06229a96bcba9aee4c470d09244fda77d2;p=soc.git code-morph on div pipeline --- diff --git a/src/soc/fu/README.md b/src/soc/fu/README.md index fad4daef..dc09399f 100644 --- a/src/soc/fu/README.md +++ b/src/soc/fu/README.md @@ -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 diff --git a/src/soc/fu/div/output_stage.py b/src/soc/fu/div/output_stage.py index 88a9ec1e..1db0bbb2 100644 --- a/src/soc/fu/div/output_stage.py +++ b/src/soc/fu/div/output_stage.py @@ -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 diff --git a/src/soc/fu/div/pipe_data.py b/src/soc/fu/div/pipe_data.py index fcaa7341..035290ab 100644 --- a/src/soc/fu/div/pipe_data.py +++ b/src/soc/fu/div/pipe_data.py @@ -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__() diff --git a/src/soc/fu/div/setup_stage.py b/src/soc/fu/div/setup_stage.py index 79d170b2..a0ea42ed 100644 --- a/src/soc/fu/div/setup_stage.py +++ b/src/soc/fu/div/setup_stage.py @@ -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