code-munge on CR pipeline
authorLuke Kenneth Casson Leighton <lkcl@lkcl.net>
Sat, 16 May 2020 18:17:13 +0000 (19:17 +0100)
committerLuke Kenneth Casson Leighton <lkcl@lkcl.net>
Sat, 16 May 2020 18:21:27 +0000 (19:21 +0100)
src/soc/cr/main_stage.py

index 1552c4b1f216cd0ea8b9d1ecbc4a42df21670017..97120123be29a817c4867faea1c2d6974343455d 100644 (file)
@@ -5,6 +5,14 @@
 # This module however should not gate the carry or overflow, that's up
 # to the output stage
 
+# NOTE: we really should be doing the field decoding which
+# selectswhich bits of CR are to be read / written, back in the
+# decoder / insn-isue, have both self.i.cr and self.o.cr
+# be broken down into 4-bit-wide "registers", with their
+# own "Register File" (indexed by bt, ba and bb),
+# exactly how INT regs are done (by RA, RB, RS and RT)
+# however we are pushed for time so do it as *one* register.
+
 from nmigen import (Module, Signal, Cat, Repl, Mux, Const, Array)
 from nmutil.pipemodbase import PipeModBase
 from soc.cr.pipe_data import CRInputData, CROutputData
@@ -40,8 +48,9 @@ class CRMainStage(PipeModBase):
         xl_fields = self.fields.instrs['XL']
         xfx_fields = self.fields.instrs['XFX']
 
-        cr_output = Signal.like(self.i.cr)
-        comb += cr_output.eq(self.i.cr)
+        # default: cr_o remains same as cr input unless modified, below
+        cr_o = Signal.like(self.i.cr)
+        comb += cr_o.eq(self.i.cr)
 
         # Generate array for cr input so bits can be selected
         cr_arr = Array([Signal(name=f"cr_arr_{i}") for i in range(32)])
@@ -52,20 +61,9 @@ class CRMainStage(PipeModBase):
         # selected by a signal
         cr_out_arr = Array([Signal(name=f"cr_out_{i}") for i in range(32)])
         for i in range(32):
-            comb += cr_output[31-i].eq(cr_out_arr[i])
+            comb += cr_o[31-i].eq(cr_out_arr[i])
             comb += cr_out_arr[i].eq(cr_arr[i])
 
-        # crand/cror and friends get decoded to the same opcode, but
-        # one of the fields inside the instruction is a 4 bit lookup
-        # table. This lookup table gets indexed by bits a and b from
-        # the CR to determine what the resulting bit should be.
-
-        # Grab the lookup table for cr_op type instructions
-        lut = Signal(4, reset_less=True)
-        # There's no field, just have to grab it directly from the insn
-        comb += lut.eq(self.i.ctx.op.insn[6:10])
-
-
         # Ugh. mtocrf and mtcrf have one random bit differentiating
         # them. This bit is not in any particular field, so this
         # extracts that bit from the instruction
@@ -73,6 +71,7 @@ class CRMainStage(PipeModBase):
         comb += move_one.eq(self.i.ctx.op.insn[20])
 
         with m.Switch(op.insn_type):
+            ##### mcrf #####
             with m.Case(InternalOp.OP_MCRF):
                 # MCRF copies the 4 bits of crA to crB (for instance
                 # copying cr2 to cr1)
@@ -86,13 +85,15 @@ class CRMainStage(PipeModBase):
 
                 for i in range(4):
                     comb += cr_out_arr[bf*4 + i].eq(cr_arr[bfa*4 + i])
+
+            ##### crand, cror, crnor etc. #####
             with m.Case(InternalOp.OP_CROP):
                 # Get the bit selector fields from the instruction
                 bt = Signal(xl_fields['BT'][0:-1].shape())
-                comb += bt.eq(xl_fields['BT'][0:-1])
                 ba = Signal(xl_fields['BA'][0:-1].shape())
-                comb += ba.eq(xl_fields['BA'][0:-1])
                 bb = Signal(xl_fields['BB'][0:-1].shape())
+                comb += bt.eq(xl_fields['BT'][0:-1])
+                comb += ba.eq(xl_fields['BA'][0:-1])
                 comb += bb.eq(xl_fields['BB'][0:-1])
 
                 # Extract the two input bits from the CR
@@ -101,31 +102,40 @@ class CRMainStage(PipeModBase):
                 comb += bit_a.eq(cr_arr[ba])
                 comb += bit_b.eq(cr_arr[bb])
 
-                bit_out = Signal(reset_less=True)
+                # crand/cror and friends get decoded to the same opcode, but
+                # one of the fields inside the instruction is a 4 bit lookup
+                # table. This lookup table gets indexed by bits a and b from
+                # the CR to determine what the resulting bit should be.
+
+                # Grab the lookup table for cr_op type instructions
+                lut = Signal(4, reset_less=True)
+                # There's no field, just have to grab it directly from the insn
+                comb += lut.eq(self.i.ctx.op.insn[6:10])
 
                 # Use the two input bits to look up the result in the
                 # lookup table
+                bit_out = Signal(reset_less=True)
                 comb += bit_out.eq(Mux(bit_b,
                                        Mux(bit_a, lut[3], lut[1]),
                                        Mux(bit_a, lut[2], lut[0])))
                 # Set the output to the result above
                 comb += cr_out_arr[bt].eq(bit_out)
 
+            ##### mtcrf #####
             with m.Case(InternalOp.OP_MTCRF):
                 fxm = Signal(xfx_fields['FXM'][0:-1].shape())
                 comb += fxm.eq(xfx_fields['FXM'][0:-1])
 
-                # mtcrf
+                # replicate every fxm field in the insn to 4-bit, as a mask
+                fxl = [Repl(fxm[i], 4) for i in range(8)]
                 mask = Signal(32, reset_less=True)
+                comb += mask.eq(Cat(*fxl))
 
-                for i in range(8):
-                    comb += mask[i*4:(i+1)*4].eq(Repl(fxm[i], 4))
-
-                comb += cr_output.eq((self.i.a[0:32] & mask) |
-                                     (self.i.cr & ~mask))
-                    
+                # put input (RA) - mask-selected - into output CR, leave
+                # rest of CR alone.
+                comb += cr_o.eq((self.i.a[0:32] & mask) | (self.i.cr & ~mask))
 
-        comb += self.o.cr.eq(cr_output)
+        comb += self.o.cr.eq(cr_o)
         comb += self.o.ctx.eq(self.i.ctx)
 
         return m