From c150af84a0c52f5297e55dbcfdaf334f05a6e994 Mon Sep 17 00:00:00 2001 From: Luke Kenneth Casson Leighton Date: Fri, 22 May 2020 16:32:44 +0100 Subject: [PATCH] create common input pipe spec to avoid code-duplication --- src/soc/fu/common_input_stage.py | 44 +++++++++++++++++++ .../fu/shift_rot/formal/proof_main_stage.py | 9 ++-- src/soc/fu/shift_rot/input_stage.py | 39 ++-------------- src/soc/fu/shift_rot/main_stage.py | 9 ++-- src/soc/fu/shift_rot/pipe_data.py | 8 ++-- src/soc/fu/shift_rot/test/test_pipe_caller.py | 2 +- 6 files changed, 61 insertions(+), 50 deletions(-) create mode 100644 src/soc/fu/common_input_stage.py diff --git a/src/soc/fu/common_input_stage.py b/src/soc/fu/common_input_stage.py new file mode 100644 index 00000000..39c56a89 --- /dev/null +++ b/src/soc/fu/common_input_stage.py @@ -0,0 +1,44 @@ +# This stage is intended to adjust the input data before sending it to +# the acutal ALU. Things like handling inverting the input, carry_in +# generation for subtraction, should happen here +from nmigen import (Module, Signal) +from nmutil.pipemodbase import PipeModBase +from soc.decoder.power_enums import InternalOp +from soc.decoder.power_enums import CryIn + + +class CommonInputStage(PipeModBase): + + def elaborate(self, platform): + m = Module() + comb = m.d.comb + + ##### operand A ##### + + # 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.Else(): + comb += a.eq(self.i.a) + + comb += self.o.a.eq(a) + + ##### carry-in ##### + + # either copy incoming carry or set to 1/0 as defined by op + with m.Switch(self.i.ctx.op.input_carry): + with m.Case(CryIn.ZERO): + comb += self.o.xer_ca.eq(0b00) + with m.Case(CryIn.ONE): + comb += self.o.xer_ca.eq(0b11) # XER CA/CA32 + with m.Case(CryIn.CA): + comb += self.o.xer_ca.eq(self.i.xer_ca) + + ##### 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) + + return m diff --git a/src/soc/fu/shift_rot/formal/proof_main_stage.py b/src/soc/fu/shift_rot/formal/proof_main_stage.py index afcf12e7..129a9579 100644 --- a/src/soc/fu/shift_rot/formal/proof_main_stage.py +++ b/src/soc/fu/shift_rot/formal/proof_main_stage.py @@ -26,20 +26,17 @@ class Driver(Elaboratable): comb = m.d.comb rec = CompALUOpSubset() - recwidth = 0 # Setup random inputs for dut.op for p in rec.ports(): - width = p.width - recwidth += width - comb += p.eq(AnyConst(width)) + comb += p.eq(AnyConst(p.width)) - pspec = ALUPipeSpec(id_wid=2, op_wid=recwidth) + pspec = ALUPipeSpec(id_wid=2) m.submodules.dut = dut = ShiftRotMainStage(pspec) # convenience variables a = dut.i.rs b = dut.i.rb - ra = dut.i.ra + ra = dut.i.a carry_in = dut.i.xer_ca[0] carry_in32 = dut.i.xer_ca[1] so_in = dut.i.xer_so diff --git a/src/soc/fu/shift_rot/input_stage.py b/src/soc/fu/shift_rot/input_stage.py index 83df5a7f..f195b40e 100644 --- a/src/soc/fu/shift_rot/input_stage.py +++ b/src/soc/fu/shift_rot/input_stage.py @@ -2,15 +2,11 @@ # the acutal ALU. Things like handling inverting the input, carry_in # generation for subtraction, and handling of immediates should happen # here -from nmigen import (Module, Signal, Cat, Const, Mux, Repl, signed, - unsigned) -from nmutil.pipemodbase import PipeModBase -from soc.decoder.power_enums import InternalOp +from soc.fu.common_input_stage import CommonInputStage from soc.fu.shift_rot.pipe_data import ShiftRotInputData -from soc.decoder.power_enums import CryIn -class ShiftRotInputStage(PipeModBase): +class ShiftRotInputStage(CommonInputStage): def __init__(self, pspec): super().__init__(pspec, "input") @@ -21,38 +17,11 @@ class ShiftRotInputStage(PipeModBase): return ShiftRotInputData(self.pspec) def elaborate(self, platform): - m = Module() + m = super().elaborate(platform) # handles A, carry and sticky overflow comb = m.d.comb - ##### operand A ##### - - # operand a to be as-is or inverted - a = Signal.like(self.i.ra) - - with m.If(self.i.ctx.op.invert_a): - comb += a.eq(~self.i.ra) - with m.Else(): - comb += a.eq(self.i.ra) - - comb += self.o.ra.eq(a) + # operands ra and rb comb += self.o.rb.eq(self.i.rb) comb += self.o.rs.eq(self.i.rs) - - ##### carry-in ##### - - # either copy incoming carry or set to 1/0 as defined by op - with m.Switch(self.i.ctx.op.input_carry): - with m.Case(CryIn.ZERO): - comb += self.o.xer_ca.eq(0b00) - with m.Case(CryIn.ONE): - comb += self.o.xer_ca.eq(0b11) # XER CA/CA32 - with m.Case(CryIn.CA): - comb += self.o.xer_ca.eq(self.i.xer_ca) - - ##### 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) - return m diff --git a/src/soc/fu/shift_rot/main_stage.py b/src/soc/fu/shift_rot/main_stage.py index be5b47d5..10949c55 100644 --- a/src/soc/fu/shift_rot/main_stage.py +++ b/src/soc/fu/shift_rot/main_stage.py @@ -29,6 +29,7 @@ class ShiftRotMainStage(PipeModBase): def elaborate(self, platform): m = Module() comb = m.d.comb + op = self.i.ctx.op # obtain me and mb fields from instruction. m_fields = self.fields.instrs['M'] @@ -47,15 +48,15 @@ class ShiftRotMainStage(PipeModBase): rotator.mb.eq(mb), rotator.mb_extra.eq(mb_extra), rotator.rs.eq(self.i.rs), - rotator.ra.eq(self.i.ra), + rotator.ra.eq(self.i.a), rotator.shift.eq(self.i.rb), - rotator.is_32bit.eq(self.i.ctx.op.is_32bit), - rotator.arith.eq(self.i.ctx.op.is_signed), + rotator.is_32bit.eq(op.is_32bit), + rotator.arith.eq(op.is_signed), ] # instruction rotate type mode = Signal(3, reset_less=True) - with m.Switch(self.i.ctx.op.insn_type): + with m.Switch(op.insn_type): with m.Case(InternalOp.OP_SHL): comb += mode.eq(0b000) with m.Case(InternalOp.OP_SHR): comb += mode.eq(0b001) # R-shift with m.Case(InternalOp.OP_RLC): comb += mode.eq(0b110) # clear LR diff --git a/src/soc/fu/shift_rot/pipe_data.py b/src/soc/fu/shift_rot/pipe_data.py index 8b0139e1..1375ae0a 100644 --- a/src/soc/fu/shift_rot/pipe_data.py +++ b/src/soc/fu/shift_rot/pipe_data.py @@ -8,14 +8,14 @@ from nmutil.dynamicpipe import SimpleHandshakeRedir class ShiftRotInputData(IntegerData): - regspec = [('INT', 'ra', '0:63'), + regspec = [('INT', 'a', '0:63'), ('INT', 'rs', '0:63'), ('INT', 'rb', '0:63'), ('XER', 'xer_so', '32'), ('XER', 'xer_ca', '34,45')] def __init__(self, pspec): super().__init__(pspec) - self.ra = Signal(64, reset_less=True) # RA + self.a = Signal(64, reset_less=True) # RA self.rs = Signal(64, reset_less=True) # RS self.rb = Signal(64, reset_less=True) # RB/immediate self.xer_so = Signal(reset_less=True) # XER bit 32: SO @@ -23,7 +23,7 @@ class ShiftRotInputData(IntegerData): def __iter__(self): yield from super().__iter__() - yield self.ra + yield self.a yield self.rs yield self.rb yield self.xer_ca @@ -31,7 +31,7 @@ class ShiftRotInputData(IntegerData): def eq(self, i): lst = super().eq(i) - return lst + [self.rs.eq(i.rs), self.ra.eq(i.ra), + return lst + [self.rs.eq(i.rs), self.a.eq(i.a), self.rb.eq(i.rb), self.xer_ca.eq(i.xer_ca), self.xer_so.eq(i.xer_so)] diff --git a/src/soc/fu/shift_rot/test/test_pipe_caller.py b/src/soc/fu/shift_rot/test/test_pipe_caller.py index bddda219..fb370525 100644 --- a/src/soc/fu/shift_rot/test/test_pipe_caller.py +++ b/src/soc/fu/shift_rot/test/test_pipe_caller.py @@ -53,7 +53,7 @@ def set_alu_inputs(alu, dec2, sim): else: data2 = 0 - yield alu.p.data_i.ra.eq(data1) + yield alu.p.data_i.a.eq(data1) yield alu.p.data_i.rb.eq(data2) yield alu.p.data_i.rs.eq(data3) -- 2.30.2