Change shift left to be implemented with rotate and mask
authorMichael Nolan <mtnolan2640@gmail.com>
Sat, 9 May 2020 17:00:14 +0000 (13:00 -0400)
committerMichael Nolan <mtnolan2640@gmail.com>
Sat, 9 May 2020 17:00:14 +0000 (13:00 -0400)
src/soc/alu/main_stage.py
src/soc/alu/rotl.py [new file with mode: 0644]
src/soc/alu/test/test_pipe_caller.py

index 6ba4b0b285a041299c9abc7650f1444858c40972..5b469e80f553a959e4a0c77fe5f994e337face21 100644 (file)
@@ -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 (file)
index 0000000..d2ebfcf
--- /dev/null
@@ -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
index 899b764fa644b41fdb85f4c829662857c6db4f0b..7235aaa2ce82fc20522685d5dd8696756d49ffb4 100644 (file)
@@ -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)