add CR_ISEL (and unit test) to CR pipeline
authorLuke Kenneth Casson Leighton <lkcl@lkcl.net>
Sat, 23 May 2020 10:35:24 +0000 (11:35 +0100)
committerLuke Kenneth Casson Leighton <lkcl@lkcl.net>
Sat, 23 May 2020 10:35:24 +0000 (11:35 +0100)
src/soc/fu/cr/main_stage.py
src/soc/fu/cr/test/test_pipe_caller.py

index efb821e5bcee6588357d5a638d0b7b5225a295f5..41a0acd0901ddd15491b7c3dd0a4ce901b707828 100644 (file)
@@ -1,4 +1,4 @@
-# This stage is intended to do Condition Register instructions
+# This stage is intended to do Condition Register instructions (and ISEL)
 # and output, as well as carry and overflow generation.
 # NOTE: with the exception of mtcrf and mfcr, we really should be doing
 # the field decoding which
@@ -34,7 +34,7 @@ class CRMainStage(PipeModBase):
         m = Module()
         comb = m.d.comb
         op = self.i.ctx.op
-        a, full_cr = self.i.a, self.i.full_cr
+        a, b, full_cr = self.i.a, self.i.b, self.i.full_cr
         cr_a, cr_b, cr_c = self.i.cr_a, self.i.cr_b, self.i.cr_c
         cr_o, full_cr_o, rt_o = self.o.cr_o, self.o.full_cr, self.o.o
 
@@ -133,6 +133,21 @@ class CRMainStage(PipeModBase):
                     # output register RT
                     comb += rt_o.eq(full_cr)
 
+            # ##### isel #####
+            with m.Case(InternalOp.OP_ISEL):
+                # just like in branch, CR0-7 is incoming into cr_a, we
+                # need to select from the last 2 bits of BC
+                a_fields = self.fields.FormA
+                BC = a_fields.BC[0:-1][0:2]
+                cr_bits = Array([cr_a[3-i] for i in range(4)])
+
+                # The bit of (cr_a=CR0-7) selected by BC
+                cr_bit = Signal(reset_less=True)
+                comb += cr_bit.eq(cr_bits[BC])
+
+                # select a or b as output
+                comb += rt_o.eq(Mux(cr_bit, a, b))
+
         comb += self.o.ctx.eq(self.i.ctx)
 
         return m
index 67b67b6e48c929250430687e867958f4e1963fc5..1f2a183e4ba22e487fb04e619e76fee6e95c5af8 100644 (file)
@@ -58,6 +58,18 @@ class CRTestCase(FHDLTestCase):
                       self.test_name)
         test_data.append(tc)
 
+    def test_isel(self):
+        for i in range(40):
+            bi = random.randint(0, 31)
+            lst = [f"isel 3, 1, 2, {bi}"]
+            cr = random.randint(0, (1<<32)-1)
+            initial_regs = [0] * 32
+            initial_regs[1] = random.randint(0, (1<<32)-1)
+            initial_regs[2] = random.randint(0, (1<<32)-1)
+            initial_regs[3] = random.randint(0, (1<<32)-1)
+            self.run_tst_program(Program(lst), initial_regs=initial_regs,
+                                 initial_cr=cr)
+
     def test_crop(self):
         insns = ["crand", "cror", "crnand", "crnor", "crxor", "creqv",
                  "crandc", "crorc"]
@@ -112,7 +124,6 @@ class CRTestCase(FHDLTestCase):
             lst = [f"mfocrf 2, {mask}"]
             cr = random.randint(0, (1<<32)-1)
             self.run_tst_program(Program(lst), initial_cr=cr)
-        
 
     def test_ilang(self):
         pspec = CRPipeSpec(id_wid=2)
@@ -168,7 +179,6 @@ class TestRunner(FHDLTestCase):
             expected_cr = simulator.crl[cr_sel].get_range().value
             real_cr = yield alu.n.data_o.cr_o.data
             self.assertEqual(expected_cr, real_cr)
-            
 
     def run_all(self):
         m = Module()
@@ -212,7 +222,7 @@ class TestRunner(FHDLTestCase):
                     yield alu.p.valid_i.eq(1)
                     fn_unit = yield pdecode2.e.fn_unit
                     self.assertEqual(fn_unit, Function.CR.value, code)
-                    yield 
+                    yield
                     opname = code.split(' ')[0]
                     yield from simulator.call(opname)
                     index = simulator.pc.CIA.value//4
@@ -228,6 +238,7 @@ class TestRunner(FHDLTestCase):
         with sim.write_vcd("simulator.vcd", "simulator.gtkw",
                             traces=[]):
             sim.run()
+
     def check_extra_alu_outputs(self, alu, dec2, sim):
         rc = yield dec2.e.rc.data
         if rc: