From c69a2020074b394f556fd720212cb175df66c0dc Mon Sep 17 00:00:00 2001 From: Luke Kenneth Casson Leighton Date: Wed, 20 May 2020 05:42:45 +0100 Subject: [PATCH] convert alu output to use Data for XER and CR0 --- src/soc/fu/alu/main_stage.py | 10 ++++++--- src/soc/fu/alu/output_stage.py | 26 ++++++++++++++++-------- src/soc/fu/alu/pipe_data.py | 27 ++++++++++--------------- src/soc/fu/alu/test/test_pipe_caller.py | 11 ++++++---- 4 files changed, 43 insertions(+), 31 deletions(-) diff --git a/src/soc/fu/alu/main_stage.py b/src/soc/fu/alu/main_stage.py index dd03b786..2457a750 100644 --- a/src/soc/fu/alu/main_stage.py +++ b/src/soc/fu/alu/main_stage.py @@ -23,7 +23,7 @@ class ALUMainStage(PipeModBase): def elaborate(self, platform): m = Module() comb = m.d.comb - carry_out, o = self.o.carry_out, self.o.o + carry_out, o = self.o.xer_co, self.o.o # check if op is 32-bit, and get sign bit from operand a is_32bit = Signal(reset_less=True) @@ -58,7 +58,11 @@ class ALUMainStage(PipeModBase): with m.Case(InternalOp.OP_ADD): # bit 0 is not part of the result, top bit is the carry-out comb += o.eq(add_output[1:-1]) - comb += carry_out.eq(add_output[-1]) + comb += carry_out.data[0].eq(add_output[-1]) # XER.CO + + # XXX no! wrongggg, see microwatt OP_ADD code + # https://bugs.libre-soc.org/show_bug.cgi?id=319#c5 + comb += carry_out.data[1].eq(add_output[-1]) # XER.CO32 #### exts (sign-extend) #### with m.Case(InternalOp.OP_EXTS): @@ -78,7 +82,7 @@ class ALUMainStage(PipeModBase): ###### sticky overflow and context, both pass-through ##### - comb += self.o.so.eq(self.i.so) + comb += self.o.xer_so.data.eq(self.i.so) comb += self.o.ctx.eq(self.i.ctx) return m diff --git a/src/soc/fu/alu/output_stage.py b/src/soc/fu/alu/output_stage.py index 24a47ce7..08946de1 100644 --- a/src/soc/fu/alu/output_stage.py +++ b/src/soc/fu/alu/output_stage.py @@ -38,8 +38,8 @@ class ALUOutputStage(PipeModBase): comb += target.eq(o) # Handle carry_out - with m.If(self.i.ctx.op.output_carry): - comb += self.o.carry_out.eq(self.i.carry_out) + comb += self.o.xer_co.data.eq(self.i.xer_co.data) + comb += self.o.xer_co.ok.eq(op.output_carry) # create condition register cr0 and sticky-overflow is_zero = Signal(reset_less=True) @@ -47,7 +47,9 @@ class ALUOutputStage(PipeModBase): is_negative = Signal(reset_less=True) msb_test = Signal(reset_less=True) # set equal to MSB, invert if OP=CMP is_cmp = Signal(reset_less=True) # true if OP=CMP - so = Signal(reset_less=True) + so = Signal(1, reset_less=True) + ov = Signal(2, reset_less=True) # OV, OV32 + cr0 = Signal(4, reset_less=True) # TODO: if o[63] is XORed with "operand == OP_CMP" # that can be used as a test @@ -58,16 +60,24 @@ class ALUOutputStage(PipeModBase): comb += is_zero.eq(target == 0) comb += is_positive.eq(~is_zero & ~msb_test) comb += is_negative.eq(~is_zero & msb_test) - comb += so.eq(self.i.so | self.i.ov) + # XXX see https://bugs.libre-soc.org/show_bug.cgi?id=319#c5 + comb += ov[0].eq(self.i.xer_so.data | self.i.xer_ov.data[0]) # OV + comb += ov[1].eq(self.i.xer_so.data | self.i.xer_ov.data[1]) # OV32 XXX! + comb += so.eq(self.i.xer_so.data | self.i.xer_ov.data[0]) # OV with m.If(op.insn_type != InternalOp.OP_CMPEQB): - comb += self.o.cr0.eq(Cat(so, is_zero, is_positive, is_negative)) + comb += cr0.eq(Cat(so, is_zero, is_positive, is_negative)) with m.Else(): - comb += self.o.cr0.eq(self.i.cr0) + comb += cr0.eq(self.i.cr0) - # copy [inverted] output, sticky-overflow and context out + # copy [inverted] cr0, output, sticky-overflow and context out comb += self.o.o.eq(o) - comb += self.o.so.eq(so) + comb += self.o.cr0.data.eq(cr0) + comb += self.o.cr0.ok.eq(op.rc.rc & op.rc.rc_ok) # CR0 to be set + comb += self.o.xer_so.data.eq(so) + comb += self.o.xer_so.ok.eq(op.oe.oe & op.oe.oe_ok) # SO is to be set + comb += self.o.xer_ov.data.eq(ov) + comb += self.o.xer_ov.ok.eq(op.oe.oe & op.oe.oe_ok) # OV/32 is to be set comb += self.o.ctx.eq(self.i.ctx) return m diff --git a/src/soc/fu/alu/pipe_data.py b/src/soc/fu/alu/pipe_data.py index 7c91349a..744db57a 100644 --- a/src/soc/fu/alu/pipe_data.py +++ b/src/soc/fu/alu/pipe_data.py @@ -2,7 +2,7 @@ from nmigen import Signal, Const from nmutil.dynamicpipe import SimpleHandshakeRedir from soc.fu.alu.alu_input_record import CompALUOpSubset from ieee754.fpcommon.getop import FPPipeContext - +from soc.decoder.power_decoder2 import Data class IntegerData: @@ -50,30 +50,25 @@ class ALUOutputData(IntegerData): def __init__(self, pspec): super().__init__(pspec) self.o = Signal(64, reset_less=True, name="stage_o") - self.carry_out = Signal(reset_less=True) - self.carry_out32 = Signal(reset_less=True) - self.cr0 = Signal(4, reset_less=True) - self.ov = Signal(reset_less=True) - self.ov32 = Signal(reset_less=True) - self.so = Signal(reset_less=True) + self.cr0 = Data(4, name="cr0") + self.xer_co = Data(2, name="xer_co") # bit0: co, bit1: co32 + self.xer_ov = Data(2, name="xer_ov") # bit0: ov, bit1: ov32 + self.xer_so = Data(1, name="xer_so") def __iter__(self): yield from super().__iter__() yield self.o - yield self.carry_out - yield self.carry_out32 + yield self.xer_co yield self.cr0 - yield self.ov - yield self.ov32 - yield self.so + yield self.xer_ov + yield self.xer_so def eq(self, i): lst = super().eq(i) return lst + [self.o.eq(i.o), - self.carry_out.eq(i.carry_out), - self.carry_out32.eq(i.carry_out32), - self.cr0.eq(i.cr0), self.ov.eq(i.ov), - self.ov32.eq(i.ov32), self.so.eq(i.so)] + self.xer_co.eq(i.xer_co), + self.cr0.eq(i.cr0), + self.xer_ov.eq(i.xer_ov), self.xer_so.eq(i.xer_so)] class IntPipeSpec: diff --git a/src/soc/fu/alu/test/test_pipe_caller.py b/src/soc/fu/alu/test/test_pipe_caller.py index 94fcad78..9a9e5571 100644 --- a/src/soc/fu/alu/test/test_pipe_caller.py +++ b/src/soc/fu/alu/test/test_pipe_caller.py @@ -249,22 +249,25 @@ class TestRunner(FHDLTestCase): rc = yield dec2.e.rc.data if rc: cr_expected = sim.crl[0].get_range().value - cr_actual = yield alu.n.data_o.cr0 + cr_actual = yield alu.n.data_o.cr0.data self.assertEqual(cr_expected, cr_actual, code) op = yield dec2.e.insn_type if op == InternalOp.OP_CMP.value or \ op == InternalOp.OP_CMPEQB.value: bf = yield dec2.dec.BF - cr_actual = yield alu.n.data_o.cr0 + cr_actual = yield alu.n.data_o.cr0.data cr_expected = sim.crl[bf].get_range().value self.assertEqual(cr_expected, cr_actual, code) cry_out = yield dec2.e.output_carry if cry_out: expected_carry = 1 if sim.spr['XER'][XER_bits['CA']] else 0 - real_carry = yield alu.n.data_o.carry_out - self.assertEqual(expected_carry, real_carry) + real_carry = yield alu.n.data_o.xer_co.data[0] # XXX CO not CO32 + self.assertEqual(expected_carry, real_carry, code) + expected_carry32 = 1 if sim.spr['XER'][XER_bits['CA32']] else 0 + real_carry32 = yield alu.n.data_o.xer_co.data[1] # XXX CO32 + self.assertEqual(expected_carry, real_carry, code) -- 2.30.2