From 0a4b23a11351c0fa3057f853aaf2bfcd857b010b Mon Sep 17 00:00:00 2001 From: Luke Kenneth Casson Leighton Date: Thu, 14 May 2020 17:34:39 +0100 Subject: [PATCH] move inversion of cmp into output stage by inverting the is +ve and is -ve test this saves on 2x 64-bit MUXes if the actual operands A and B were swapped instead --- src/soc/alu/formal/proof_input_stage.py | 24 +++++------------------- src/soc/alu/input_stage.py | 19 +++++-------------- src/soc/alu/main_stage.py | 2 -- src/soc/alu/output_stage.py | 7 +++++-- src/soc/alu/test/test_pipe_caller.py | 9 +++++---- 5 files changed, 20 insertions(+), 41 deletions(-) diff --git a/src/soc/alu/formal/proof_input_stage.py b/src/soc/alu/formal/proof_input_stage.py index 98643a28..347ab7d4 100644 --- a/src/soc/alu/formal/proof_input_stage.py +++ b/src/soc/alu/formal/proof_input_stage.py @@ -41,11 +41,9 @@ class Driver(Elaboratable): dut.i.b.eq(b), a.eq(AnyConst(64)), b.eq(AnyConst(64))] - comb += dut.i.ctx.op.eq(rec) - # Assert that op gets copied from the input to output for p in rec.ports(): name = p.name @@ -53,28 +51,16 @@ class Driver(Elaboratable): dut_sig = getattr(dut.o.ctx.op, name) comb += Assert(dut_sig == rec_sig) - with m.If(rec.insn_type != InternalOp.OP_CMP): - with m.If(rec.invert_a): - comb += Assert(dut.o.a == ~a) - with m.Else(): - comb += Assert(dut.o.a == a) - - comb += Assert(dut.o.b == b) + with m.If(rec.invert_a): + comb += Assert(dut.o.a == ~a) with m.Else(): - with m.If(rec.invert_a): - comb += Assert(dut.o.a == ~b) - with m.Else(): - comb += Assert(dut.o.a == b) - - comb += Assert(dut.o.b == a) - - - - + comb += Assert(dut.o.a == a) + comb += Assert(dut.o.b == b) return m + class GTCombinerTestCase(FHDLTestCase): def test_formal(self): module = Driver() diff --git a/src/soc/alu/input_stage.py b/src/soc/alu/input_stage.py index ef26b977..5a325f51 100644 --- a/src/soc/alu/input_stage.py +++ b/src/soc/alu/input_stage.py @@ -29,22 +29,13 @@ class ALUInputStage(PipeModBase): # operand a to be as-is or inverted a = Signal.like(self.i.a) - with m.If(self.i.ctx.op.insn_type != InternalOp.OP_CMP): - with m.If(self.i.ctx.op.invert_a): - comb += a.eq(~self.i.a) - with m.Else(): - comb += a.eq(self.i.a) - - comb += self.o.a.eq(a) - comb += self.o.b.eq(self.i.b) + with m.If(self.i.ctx.op.invert_a): + comb += a.eq(~self.i.a) with m.Else(): - with m.If(self.i.ctx.op.invert_a): - comb += self.o.a.eq(~self.i.b) - with m.Else(): - comb += self.o.a.eq(self.i.b) - - comb += self.o.b.eq(self.i.a) + comb += a.eq(self.i.a) + comb += self.o.a.eq(a) + comb += self.o.b.eq(self.i.b) ##### carry-in ##### diff --git a/src/soc/alu/main_stage.py b/src/soc/alu/main_stage.py index 0e628e04..ad4e8e87 100644 --- a/src/soc/alu/main_stage.py +++ b/src/soc/alu/main_stage.py @@ -31,8 +31,6 @@ class ALUMainStage(PipeModBase): comb += is_32bit.eq(self.i.ctx.op.is_32bit) comb += sign_bit.eq(Mux(is_32bit, self.i.a[31], self.i.a[63])) - - # little trick: do the add using only one add (not 2) add_a = Signal(self.i.a.width + 2, reset_less=True) add_b = Signal(self.i.a.width + 2, reset_less=True) diff --git a/src/soc/alu/output_stage.py b/src/soc/alu/output_stage.py index 5de9bbd0..2f04ac9f 100644 --- a/src/soc/alu/output_stage.py +++ b/src/soc/alu/output_stage.py @@ -34,14 +34,17 @@ class ALUOutputStage(PipeModBase): is_positive = Signal(reset_less=True) 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) # TODO: if o[63] is XORed with "operand == OP_CMP" # that can be used as a test # see https://bugs.libre-soc.org/show_bug.cgi?id=305#c60 + comb += is_cmp.eq(self.i.ctx.op.insn_type == InternalOp.OP_CMP) + comb += msb_test.eq(o[-1] ^ is_cmp) comb += is_zero.eq(o == 0) - comb += is_positive.eq(~is_zero & ~o[63]) - comb += is_negative.eq(~is_zero & o[63]) + 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) comb += self.o.o.eq(o) diff --git a/src/soc/alu/test/test_pipe_caller.py b/src/soc/alu/test/test_pipe_caller.py index 95f721a4..c38d5c47 100644 --- a/src/soc/alu/test/test_pipe_caller.py +++ b/src/soc/alu/test/test_pipe_caller.py @@ -229,25 +229,26 @@ class TestRunner(FHDLTestCase): print(f"expected {expected:x}, actual: {alu_out:x}") self.assertEqual(expected, alu_out) yield from self.check_extra_alu_outputs(alu, pdecode2, - simulator) + simulator, code) sim.add_sync_process(process) with sim.write_vcd("simulator.vcd", "simulator.gtkw", traces=[]): sim.run() - def check_extra_alu_outputs(self, alu, dec2, sim): + + def check_extra_alu_outputs(self, alu, dec2, sim, code): rc = yield dec2.e.rc.data if rc: cr_expected = sim.crl[0].get_range().value cr_actual = yield alu.n.data_o.cr0 - self.assertEqual(cr_expected, cr_actual) + self.assertEqual(cr_expected, cr_actual, code) op = yield dec2.e.insn_type if op == InternalOp.OP_CMP.value: bf = yield dec2.dec.BF cr_actual = yield alu.n.data_o.cr0 cr_expected = sim.crl[bf].get_range().value - self.assertEqual(cr_expected, cr_actual) + self.assertEqual(cr_expected, cr_actual, code) -- 2.30.2