From: Michael Nolan Date: Thu, 14 May 2020 15:40:22 +0000 (-0400) Subject: Implement OP_CMP X-Git-Tag: div_pipeline~1233 X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=c1b030839617b1ffd43d305bf702cdb2e10be8f9;p=soc.git Implement OP_CMP Had to reverse the a and b inputs if a cmp is detected though. Ugh --- diff --git a/src/soc/alu/formal/proof_input_stage.py b/src/soc/alu/formal/proof_input_stage.py index bb62fb67..98643a28 100644 --- a/src/soc/alu/formal/proof_input_stage.py +++ b/src/soc/alu/formal/proof_input_stage.py @@ -53,16 +53,22 @@ class Driver(Elaboratable): dut_sig = getattr(dut.o.ctx.op, name) comb += Assert(dut_sig == rec_sig) - with m.If(rec.invert_a): - comb += Assert(dut.o.a == ~a) - with m.Else(): - comb += Assert(dut.o.a == a) + 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) - with m.If(rec.imm_data.imm_ok & - ~(rec.insn_type == InternalOp.OP_RLC)): - comb += Assert(dut.o.b == rec.imm_data.imm) - with m.Else(): comb += Assert(dut.o.b == b) + 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) + + diff --git a/src/soc/alu/input_stage.py b/src/soc/alu/input_stage.py index e6ab48ea..ef26b977 100644 --- a/src/soc/alu/input_stage.py +++ b/src/soc/alu/input_stage.py @@ -29,20 +29,22 @@ class ALUInputStage(PipeModBase): # operand a to be as-is or inverted a = Signal.like(self.i.a) - with m.If(self.i.ctx.op.invert_a): - comb += a.eq(~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.Else(): - comb += a.eq(self.i.a) + 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.a.eq(a) + comb += self.o.b.eq(self.i.a) - ##### operand B ##### - - # TODO: see https://bugs.libre-soc.org/show_bug.cgi?id=305#c43 - # remove this, just do self.o.b.eq(self.i.b) and move the - # immediate-detection into set_alu_inputs in the unit test - # If there's an immediate, set the B operand to that - 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 456e652f..0e628e04 100644 --- a/src/soc/alu/main_stage.py +++ b/src/soc/alu/main_stage.py @@ -31,23 +31,29 @@ 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) + add_output = Signal(self.i.a.width + 2, reset_less=True) + with m.If((self.i.ctx.op.insn_type == InternalOp.OP_ADD) | + (self.i.ctx.op.insn_type == InternalOp.OP_CMP)): + # in bit 0, 1+carry_in creates carry into bit 1 and above + comb += add_a.eq(Cat(self.i.carry_in, self.i.a, Const(0, 1))) + comb += add_b.eq(Cat(Const(1, 1), self.i.b, Const(0, 1))) + comb += add_output.eq(add_a + add_b) + ########################## # main switch-statement for handling arithmetic operations with m.Switch(self.i.ctx.op.insn_type): #### CMP, CMPL #### - # TODO with m.Case(InternalOp.OP_CMP): + with m.Case(InternalOp.OP_CMP): + comb += o.eq(add_output[1:-1]) #### add #### with m.Case(InternalOp.OP_ADD): - # 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) - add_output = Signal(self.i.a.width + 2, reset_less=True) - # in bit 0, 1+carry_in creates carry into bit 1 and above - comb += add_a.eq(Cat(self.i.carry_in, self.i.a, Const(0, 1))) - comb += add_b.eq(Cat(Const(1, 1), self.i.b, Const(0, 1))) - comb += add_output.eq(add_a + add_b) # 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]) diff --git a/src/soc/alu/test/test_pipe_caller.py b/src/soc/alu/test/test_pipe_caller.py index c7afb9a6..95f721a4 100644 --- a/src/soc/alu/test/test_pipe_caller.py +++ b/src/soc/alu/test/test_pipe_caller.py @@ -6,7 +6,7 @@ import unittest from soc.decoder.isa.caller import ISACaller, special_sprs from soc.decoder.power_decoder import (create_pdecode) from soc.decoder.power_decoder2 import (PowerDecode2) -from soc.decoder.power_enums import (XER_bits, Function) +from soc.decoder.power_enums import (XER_bits, Function, InternalOp) from soc.decoder.selectable_int import SelectableInt from soc.simulator.program import Program from soc.decoder.isa.all import ISA @@ -70,7 +70,7 @@ def set_extra_alu_inputs(alu, dec2, sim): yield alu.p.data_i.carry_in.eq(carry) so = 1 if sim.spr['XER'][XER_bits['SO']] else 0 yield alu.p.data_i.so.eq(so) - + # This test bench is a bit different than is usual. Initially when I # was writing it, I had all of the tests call a function to create a @@ -134,10 +134,11 @@ class ALUTestCase(FHDLTestCase): self.run_tst_program(Program(lst), initial_regs, initial_sprs) def test_cmp(self): - lst = ["cmp cr2, 1, 6, 7"] + lst = ["subf. 1, 6, 7", + "cmp cr2, 1, 6, 7"] initial_regs = [0] * 32 - initial_regs[6] = random.randint(0, (1<<64)-1) - initial_regs[7] = random.randint(0, (1<<64)-1) + initial_regs[6] = 0x10 + initial_regs[7] = 0x05 self.run_tst_program(Program(lst), initial_regs, {}) def test_extsb(self): @@ -210,7 +211,7 @@ class TestRunner(FHDLTestCase): self.assertEqual(fn_unit, Function.ALU.value) yield from set_alu_inputs(alu, pdecode2, simulator) yield from set_extra_alu_inputs(alu, pdecode2, simulator) - yield + yield opname = code.split(' ')[0] yield from simulator.call(opname) index = simulator.pc.CIA.value//4 @@ -241,6 +242,14 @@ class TestRunner(FHDLTestCase): cr_actual = yield alu.n.data_o.cr0 self.assertEqual(cr_expected, cr_actual) + 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) + + if __name__ == "__main__": unittest.main(exit=False)