From: Luke Kenneth Casson Leighton Date: Mon, 17 Aug 2020 09:57:30 +0000 (+0100) Subject: fix signed variants of cmp in alu X-Git-Tag: semi_working_ecp5~306 X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=29d0566fd104ab8b9ffd0c460fc7c588a72a340b;p=soc.git fix signed variants of cmp in alu --- diff --git a/src/soc/fu/alu/main_stage.py b/src/soc/fu/alu/main_stage.py index c7901042..b2d2279c 100644 --- a/src/soc/fu/alu/main_stage.py +++ b/src/soc/fu/alu/main_stage.py @@ -10,6 +10,9 @@ from soc.fu.alu.pipe_data import ALUInputData, ALUOutputData from ieee754.part.partsig import PartitionedSignal from soc.decoder.power_enums import MicrOp +from soc.decoder.power_fields import DecodeFields +from soc.decoder.power_fieldsn import SignalBitRange + # microwatt calc_ov function. def calc_ov(msb_a, msb_b, ca, msb_r): @@ -19,6 +22,8 @@ def calc_ov(msb_a, msb_b, ca, msb_r): class ALUMainStage(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 ALUInputData(self.pspec) # defines pipeline stage input format @@ -35,22 +40,36 @@ class ALUMainStage(PipeModBase): ov_o = self.o.xer_ov a, b, cry_i, op = self.i.a, self.i.b, self.i.xer_ca, self.i.ctx.op + # get L-field for OP_CMP + x_fields = self.fields.FormX + L = x_fields.L[0] + # check if op is 32-bit, and get sign bit from operand a is_32bit = Signal(reset_less=True) - sign_bit = Signal(reset_less=True) - comb += is_32bit.eq(op.is_32bit) - comb += sign_bit.eq(Mux(is_32bit, a[31], a[63])) + + with m.If(op.insn_type == MicrOp.OP_CMP): + comb += is_32bit.eq(~L) # little trick: do the add using only one add (not 2) # LSB: carry-in [0]. op/result: [1:-1]. MSB: carry-out [-1] add_a = Signal(a.width + 2, reset_less=True) add_b = Signal(a.width + 2, reset_less=True) add_o = Signal(a.width + 2, reset_less=True) + + a_i = Signal.like(a) + b_i = Signal.like(b) + with m.If(is_32bit): + comb += a_i.eq(exts(a, 32, 64)) + comb += b_i.eq(exts(b, 32, 64)) + with m.Else(): + comb += a_i.eq(a) + comb += b_i.eq(b) + with m.If((op.insn_type == MicrOp.OP_ADD) | (op.insn_type == MicrOp.OP_CMP)): # in bit 0, 1+carry_in creates carry into bit 1 and above - comb += add_a.eq(Cat(cry_i[0], a, Const(0, 1))) - comb += add_b.eq(Cat(Const(1, 1), b, Const(0, 1))) + comb += add_a.eq(Cat(cry_i[0], a_i, Const(0, 1))) + comb += add_b.eq(Cat(Const(1, 1), b_i, Const(0, 1))) comb += add_o.eq(add_a + add_b) ########################## @@ -81,13 +100,13 @@ class ALUMainStage(PipeModBase): # https://bugs.libre-soc.org/show_bug.cgi?id=319#c5 ca = Signal(2, reset_less=True) comb += ca[0].eq(add_o[-1]) # XER.CA - comb += ca[1].eq(add_o[33] ^ (a[32] ^ b[32])) # XER.CA32 + comb += ca[1].eq(add_o[33] ^ (a_i[32] ^ b_i[32])) # XER.CA32 comb += cry_o.data.eq(ca) comb += cry_o.ok.eq(1) # 32-bit (ov[1]) and 64-bit (ov[0]) overflow ov = Signal(2, reset_less=True) - comb += ov[0].eq(calc_ov(a[-1], b[-1], ca[0], add_o[-2])) - comb += ov[1].eq(calc_ov(a[31], b[31], ca[1], add_o[32])) + comb += ov[0].eq(calc_ov(a_i[-1], b_i[-1], ca[0], add_o[-2])) + comb += ov[1].eq(calc_ov(a_i[31], b_i[31], ca[1], add_o[32])) comb += ov_o.data.eq(ov) comb += ov_o.ok.eq(1)