Implement rlwinm in alu
authorMichael Nolan <mtnolan2640@gmail.com>
Sun, 10 May 2020 20:05:23 +0000 (16:05 -0400)
committerMichael Nolan <mtnolan2640@gmail.com>
Sun, 10 May 2020 20:05:29 +0000 (16:05 -0400)
src/soc/alu/alu_input_record.py
src/soc/alu/main_stage.py
src/soc/alu/test/test_pipe_caller.py

index 0ce965b5470dafe75670b6b4a7a27111c3dde9fd..2c3dcc488ad19d321b7281b8cb328b21cd800b77 100644 (file)
@@ -29,6 +29,7 @@ class CompALUOpSubset(Record):
                   ('is_32bit', 1),
                   ('is_signed', 1),
                   ('data_len', 4), # TODO: should be in separate CompLDSTSubset
+                  ('insn', 32),
                   ('byte_reverse', 1),
                   ('sign_extend', 1))
 
index 6d4bf78014e47480d7b381c791700eb1f7a14de9..173ca78fe3abe3bc24f2fc2494f575a2d61bda9c 100644 (file)
@@ -11,10 +11,15 @@ from soc.decoder.power_enums import InternalOp
 from soc.alu.maskgen import MaskGen
 from soc.alu.rotl import ROTL
 
+from soc.decoder.power_fields import DecodeFields
+from soc.decoder.power_fieldsn import SignalBitRange
+
 
 class ALUMainStage(PipeModBase):
     def __init__(self, pspec):
         super().__init__(pspec, "main")
+        self.fields = DecodeFields(SignalBitRange, [self.i.ctx.op.insn])
+        self.fields.create_specs()
 
     def ispec(self):
         return ALUInputData(self.pspec)
@@ -26,6 +31,13 @@ class ALUMainStage(PipeModBase):
         m = Module()
         comb = m.d.comb
 
+
+        fields = self.fields.instrs['M']
+        mb = Signal(fields['MB'][0:-1].shape())
+        comb += mb.eq(fields['MB'][0:-1])
+        me = Signal(fields['ME'][0:-1].shape())
+        comb += me.eq(fields['ME'][0:-1])
+
         # check if op is 32-bit, and get sign bit from operand a
         is_32bit = Signal(reset_less=True)
         sign_bit = Signal(reset_less=True)
@@ -121,6 +133,14 @@ class ALUMainStage(PipeModBase):
                 with m.Else():
                     comb += self.o.o.eq(rotl_out & mask)
 
+            with m.Case(InternalOp.OP_RLC):
+                comb += rotate_amt.eq(self.i.b[0:5])
+                comb += maskgen.mb.eq(mb+32)
+                comb += maskgen.me.eq(me+32)
+                comb += mask.eq(maskgen.o)
+                comb += self.o.o.eq(rotl_out & mask)
+                
+
         ###### sticky overflow and context, both pass-through #####
 
         comb += self.o.so.eq(self.i.so)
index 9fff62c9d6ab74df2fdeb8b971d86e5d36ee9251..04363ab853b58d6c80364ce45ab266e9980e74e8 100644 (file)
@@ -76,6 +76,7 @@ class ALUTestCase(FHDLTestCase):
                     vld = yield alu.n.valid_o
                 yield
                 alu_out = yield alu.n.data_o.o
+                print(f"expected {simulator.gpr(3).value:x}, actual: {alu_out:x}")
                 self.assertEqual(simulator.gpr(3).value, alu_out)
 
         sim.add_sync_process(process)
@@ -145,6 +146,17 @@ class ALUTestCase(FHDLTestCase):
         with Program(lst) as program:
             sim = self.run_tst_program(program, initial_regs)
 
+    def test_rlwinm(self):
+        for i in range(10):
+            mb = random.randint(0,31)
+            me = random.randint(0,31)
+            sh = random.randint(0,31)
+            lst = [f"rlwinm 3, 1, {mb}, {me}, {sh}"]
+            initial_regs = [0] * 32
+            initial_regs[1] = random.randint(0, (1<<64)-1)
+            with Program(lst) as program:
+                sim = self.run_tst_program(program, initial_regs)
+
     def test_ilang(self):
         rec = CompALUOpSubset()