X-Git-Url: https://git.libre-soc.org/?a=blobdiff_plain;f=src%2Fsoc%2Ffu%2Fshift_rot%2Fmain_stage.py;h=1a3b8eff0aadf54ade1b3d8819b5f0b0843103a7;hb=9486ce5933b5a20031166a1caffa0821b2af883f;hp=f237528397b0cea040266eaca4b21e1b66b1cad6;hpb=6e30af026706829d5af7820c4bd23111aeb012e9;p=soc.git diff --git a/src/soc/fu/shift_rot/main_stage.py b/src/soc/fu/shift_rot/main_stage.py index f2375283..1a3b8eff 100644 --- a/src/soc/fu/shift_rot/main_stage.py +++ b/src/soc/fu/shift_rot/main_stage.py @@ -1,14 +1,18 @@ +# License: LGPLv3 +# Copyright (C) 2020 Michael Nolan +# Copyright (C) 2020 Luke Kenneth Casson Leighton + # This stage is intended to do most of the work of executing shift # instructions, as well as carry and overflow generation. This module # however should not gate the carry or overflow, that's up to the # output stage from nmigen import (Module, Signal, Cat, Repl, Mux, Const) from nmutil.pipemodbase import PipeModBase -from soc.alu.pipe_data import ALUOutputData -from soc.shift_rot.pipe_data import ShiftRotInputData +from soc.fu.shift_rot.pipe_data import (ShiftRotOutputData, + ShiftRotInputData) from ieee754.part.partsig import PartitionedSignal -from soc.decoder.power_enums import InternalOp -from soc.shift_rot.rotator import Rotator +from soc.decoder.power_enums import MicrOp +from soc.fu.shift_rot.rotator import Rotator from soc.decoder.power_fields import DecodeFields from soc.decoder.power_fieldsn import SignalBitRange @@ -24,11 +28,17 @@ class ShiftRotMainStage(PipeModBase): return ShiftRotInputData(self.pspec) def ospec(self): - return ALUOutputData(self.pspec) # TODO: ALUIntermediateData + return ShiftRotOutputData(self.pspec) def elaborate(self, platform): m = Module() comb = m.d.comb + op = self.i.ctx.op + o = self.o.o + + # NOTE: the sh field immediate is read in by PowerDecode2 + # (actually DecodeRB), whereupon by way of rb "immediate" mode + # it ends up in self.i.rb. # obtain me and mb fields from instruction. m_fields = self.fields.instrs['M'] @@ -47,32 +57,38 @@ 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.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.ra.eq(self.i.a), + rotator.shift.eq(self.i.rb), # can also be sh (in immediate mode) + rotator.is_32bit.eq(op.is_32bit), + rotator.arith.eq(op.is_signed), ] + comb += o.ok.eq(1) # defaults to enabled + # instruction rotate type - mode = Signal(3, reset_less=True) - with m.Switch(self.i.ctx.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 - with m.Case(InternalOp.OP_RLCL): comb += mode.eq(0b010) # clear L - with m.Case(InternalOp.OP_RLCR): comb += mode.eq(0b100) # clear R + mode = Signal(4, reset_less=True) + with m.Switch(op.insn_type): + with m.Case(MicrOp.OP_SHL): comb += mode.eq(0b0000) # L-shift + with m.Case(MicrOp.OP_SHR): comb += mode.eq(0b0001) # R-shift + with m.Case(MicrOp.OP_RLC): comb += mode.eq(0b0110) # clear LR + with m.Case(MicrOp.OP_RLCL): comb += mode.eq(0b0010) # clear L + with m.Case(MicrOp.OP_RLCR): comb += mode.eq(0b0100) # clear R + with m.Case(MicrOp.OP_EXTSWSLI): comb += mode.eq(0b1000) # L-ext + with m.Default(): + comb += o.ok.eq(0) # otherwise disable comb += Cat(rotator.right_shift, rotator.clear_left, - rotator.clear_right).eq(mode) - + rotator.clear_right, + rotator.sign_ext_rs).eq(mode) + # outputs from the microwatt rotator module - comb += [self.o.o.eq(rotator.result_o), - self.o.carry_out.eq(rotator.carry_out_o)] + comb += [o.data.eq(rotator.result_o), + self.o.xer_ca.data.eq(Repl(rotator.carry_out_o, 2))] ###### sticky overflow and context, both pass-through ##### - comb += self.o.so.eq(self.i.so) + comb += self.o.xer_so.data.eq(self.i.xer_so) comb += self.o.ctx.eq(self.i.ctx) return m