From 6740541ea82112ead5eee6c0d2806b3f5dbbfb1f Mon Sep 17 00:00:00 2001 From: Michael Nolan Date: Sat, 9 May 2020 13:00:14 -0400 Subject: [PATCH] Change shift left to be implemented with rotate and mask --- src/soc/alu/main_stage.py | 32 ++++++++++++++++++++++++++-- src/soc/alu/rotl.py | 24 +++++++++++++++++++++ src/soc/alu/test/test_pipe_caller.py | 6 +++--- 3 files changed, 57 insertions(+), 5 deletions(-) create mode 100644 src/soc/alu/rotl.py diff --git a/src/soc/alu/main_stage.py b/src/soc/alu/main_stage.py index 6ba4b0b2..5b469e80 100644 --- a/src/soc/alu/main_stage.py +++ b/src/soc/alu/main_stage.py @@ -3,11 +3,13 @@ # and shifting, 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) +from nmigen import (Module, Signal, Cat, Repl) from nmutil.pipemodbase import PipeModBase from soc.alu.pipe_data import ALUInputData, ALUOutputData from ieee754.part.partsig import PartitionedSignal from soc.decoder.power_enums import InternalOp +from soc.alu.maskgen import MaskGen +from soc.alu.rotl import ROTL class ALUMainStage(PipeModBase): @@ -27,6 +29,25 @@ class ALUMainStage(PipeModBase): add_output = Signal(self.i.a.width + 1, reset_less=True) comb += add_output.eq(self.i.a + self.i.b + self.i.carry_in) + # Signals for rotates and shifts + rotl_out = Signal.like(self.i.a) + mask = Signal.like(self.i.a) + m.submodules.maskgen = maskgen = MaskGen(64) + m.submodules.rotl = rotl = ROTL(64) + m.submodules.rotl32 = rotl32 = ROTL(32) + + comb += [ + rotl.a.eq(self.i.a), + rotl.b.eq(self.i.b), + rotl32.a.eq(self.i.a[0:32]), + rotl32.b.eq(self.i.b)] + + with m.If(self.i.ctx.op.is_32bit): + comb += rotl_out.eq(Cat(rotl32.o, Repl(0, 32))) + with m.Else(): + comb += rotl_out.eq(rotl.o) + + with m.Switch(self.i.ctx.op.insn_type): with m.Case(InternalOp.OP_ADD): @@ -39,7 +60,14 @@ class ALUMainStage(PipeModBase): with m.Case(InternalOp.OP_XOR): comb += self.o.o.eq(self.i.a ^ self.i.b) with m.Case(InternalOp.OP_SHL): - comb += self.o.o.eq(self.i.a << self.i.b) + comb += maskgen.mb.eq(32) + comb += maskgen.me.eq(63-self.i.b[0:5]) + with m.If(self.i.ctx.op.is_32bit): + with m.If(self.i.b[5]): + comb += mask.eq(0) + with m.Else(): + comb += mask.eq(maskgen.o) + comb += self.o.o.eq(rotl_out & mask) ###### sticky overflow and context, both pass-through ##### diff --git a/src/soc/alu/rotl.py b/src/soc/alu/rotl.py new file mode 100644 index 00000000..d2ebfcf7 --- /dev/null +++ b/src/soc/alu/rotl.py @@ -0,0 +1,24 @@ +from nmigen import (Elaboratable, Signal, Module) +import math + +class ROTL(Elaboratable): + def __init__(self, width): + self.width = width + self.shiftwidth = math.ceil(math.log2(width)) + self.a = Signal(width, reset_less=True) + self.b = Signal(self.shiftwidth, reset_less=True) + + self.o = Signal(width, reset_less=True) + + def elaborate(self, platform): + m = Module() + comb = m.d.comb + + shl = Signal.like(self.a) + shr = Signal.like(self.a) + + comb += shl.eq(self.a << self.b) + comb += shr.eq(self.a >> (self.width - self.b)) + + comb += self.o.eq(shl | shr) + return m diff --git a/src/soc/alu/test/test_pipe_caller.py b/src/soc/alu/test/test_pipe_caller.py index 899b764f..7235aaa2 100644 --- a/src/soc/alu/test/test_pipe_caller.py +++ b/src/soc/alu/test/test_pipe_caller.py @@ -124,13 +124,13 @@ class ALUTestCase(FHDLTestCase): with Program(lst) as program: sim = self.run_tst_program(program, initial_regs) - def test_rlwinm(self): - for i in range(0, 10): - + def test_shift(self): + for i in range(10): lst = ["slw 3, 1, 2"] initial_regs = [0] * 32 initial_regs[1] = random.randint(0, (1<<64)-1) initial_regs[2] = random.randint(0, 63) + print(initial_regs[1], initial_regs[2]) with Program(lst) as program: sim = self.run_tst_program(program, initial_regs) -- 2.30.2