code-morph regspecmap functions, split into separate read/write
authorLuke Kenneth Casson Leighton <lkcl@lkcl.net>
Wed, 10 Jun 2020 12:18:08 +0000 (13:18 +0100)
committerLuke Kenneth Casson Leighton <lkcl@lkcl.net>
Wed, 10 Jun 2020 12:18:08 +0000 (13:18 +0100)
src/soc/decoder/power_decoder2.py
src/soc/decoder/power_regspec_map.py
src/soc/simple/core.py

index 9ff553fa13e292cc64ce3865ed9af59cba649288..26a8f634abb54dbedbd29593ccbe0646028611cf 100644 (file)
@@ -9,7 +9,8 @@ from nmigen.cli import rtlil
 from nmutil.iocontrol import RecordObject
 from nmutil.extend import exts
 
-from soc.decoder.power_regspec_map import regspec_decode
+from soc.decoder.power_regspec_map import regspec_decode_read
+from soc.decoder.power_regspec_map import regspec_decode_write
 from soc.decoder.power_decoder import create_pdecode
 from soc.decoder.power_enums import (InternalOp, CryIn, Function,
                                      CRInSel, CROutSel,
@@ -663,18 +664,25 @@ class PowerDecode2(Elaboratable):
             comb += e.trapaddr.eq(0x70)    # addr=0x700 (strip first nibble)
         return m
 
-    def regspecmap(self, regfile, regname):
-        """regspecmap: provides PowerDecode2 with an encoding relationship
+    def regspecmap_read(self, regfile, regname):
+        """regspecmap_read: provides PowerDecode2 with an encoding relationship
         to Function Unit port regfiles (read-enable, read regnum, write regnum)
         regfile and regname arguments are fields 1 and 2 from a given regspec.
         """
-        return regspec_decode(self.e, regfile, regname)
+        return regspec_decode_read(self.e, regfile, regname)
+
+    def regspecmap_write(self, regfile, regname):
+        """regspecmap_write: provides PowerDecode2 with an encoding relationship
+        to Function Unit port regfiles (write port, write regnum)
+        regfile and regname arguments are fields 1 and 2 from a given regspec.
+        """
+        return regspec_decode_write(self.e, regfile, regname)
 
     def rdflags(self, cu):
         rdl = []
         for idx in range(cu.n_src):
             regfile, regname, _ = cu.get_in_spec(idx)
-            rdflag, read, write = self.regspecmap(regfile, regname)
+            rdflag, read = self.regspecmap_read(regfile, regname)
             rdl.append(rdflag)
         print ("rdflags", rdl)
         return Cat(*rdl)
index 4b01a1ca504381bd0772b62a4a833900d898252b..fdc9c323f11e1edad09c486e73a5a4f5cc04f0cb 100644 (file)
@@ -1,7 +1,34 @@
 """regspec_decode
 
-function for the relationship between regspecs and Decode2Execute1Type
+functions for the relationship between regspecs and Decode2Execute1Type
 
+these functions encodes the understanding (relationship) between
+Regfiles, Computation Units, and the Power ISA Decoder (PowerDecoder2).
+
+based on the regspec, which contains the register file name and register
+name, return a tuple of:
+
+* how the decoder should determine whether the Function Unit needs
+  access to a given Regport or not
+* which Regfile number on that port should be read to get that data
+* when it comes to writing: likewise, which Regfile num should be written
+
+Note that some of the port numbering encoding is *unary*.  in the case
+of "Full Condition Register", it's a full 8-bit mask of read/write-enables.
+This actually matches directly with the XFX field in MTCR, and at
+some point that 8-bit mask from the instruction could actually be passed        directly through to full_cr (TODO).
+
+For the INT and CR numbering, these are expressed in binary in the
+instruction (note however that XFX in MTCR is unary-masked!)
+
+XER is implicitly-encoded based on whether the operation has carry or
+overflow.
+
+FAST regfile is, again, implicitly encoded, back in PowerDecode2, based
+on the type of operation (see DecodeB for an example).
+
+The SPR regfile on the other hand is *binary*-encoded, and, furthermore,
+has to be "remapped".
 see https://libre-soc.org/3d_gpu/architecture/regfile/ section on regspecs
 """
 from nmigen import Const
@@ -9,62 +36,85 @@ from soc.regfile.regfiles import XERRegs, FastRegs
 from soc.decoder.power_enums import CryIn
 
 
-def regspec_decode(e, regfile, name):
-    """regspec_decode
-
-    this function encodes the understanding (relationship) between
-    Regfiles, Computation Units, and the Power ISA Decoder (PowerDecoder2).
+def regspec_decode_read(e, regfile, name):
+    """regspec_decode_read
+    """
 
-    based on the regspec, which contains the register file name and register
-    name, return a tuple of:
+    if regfile == 'INT':
+        # Int register numbering is *unary* encoded
+        if name == 'ra': # RA
+            return e.read_reg1.ok, 1<<e.read_reg1.data
+        if name == 'rb': # RB
+            return e.read_reg2.ok, 1<<e.read_reg2.data
+        if name == 'rc': # RS
+            return e.read_reg3.ok, 1<<e.read_reg3.data
 
-    * how the decoder should determine whether the Function Unit needs
-      access to a given Regport or not
-    * which Regfile number on that port should be read to get that data
-    * when it comes to writing: likewise, which Regfile num should be written
+    if regfile == 'CR':
+        # CRRegs register numbering is *unary* encoded
+        # *sigh*.  numbering inverted on part-CRs.  because POWER.
+        if name == 'full_cr': # full CR
+            return e.read_cr_whole, 0b11111111
+        if name == 'cr_a': # CR A
+            return e.read_cr1.ok, 1<<(7-e.read_cr1.data)
+        if name == 'cr_b': # CR B
+            return e.read_cr2.ok, 1<<(7-e.read_cr2.data)
+        if name == 'cr_c': # CR C
+            return e.read_cr3.ok, 1<<(7-e.read_cr3.data)
 
-    Note that some of the port numbering encoding is *unary*.  in the case
-    of "Full Condition Register", it's a full 8-bit mask of read/write-enables.
-    This actually matches directly with the XFX field in MTCR, and at
-    some point that 8-bit mask from the instruction could actually be passed        directly through to full_cr (TODO).
+    if regfile == 'XER':
+        # XERRegs register numbering is *unary* encoded
+        SO = 1<<XERRegs.SO
+        CA = 1<<XERRegs.CA
+        OV = 1<<XERRegs.OV
+        if name == 'xer_so':
+            return e.oe.oe[0] & e.oe.oe_ok, SO
+        if name == 'xer_ov':
+            return e.oe.oe[0] & e.oe.oe_ok, OV
+        if name == 'xer_ca':
+            return (e.input_carry == CryIn.CA.value), CA
 
-    For the INT and CR numbering, these are expressed in binary in the
-    instruction (note however that XFX in MTCR is unary-masked!)
+    if regfile == 'FAST':
+        # FAST register numbering is *unary* encoded
+        PC = 1<<FastRegs.PC
+        MSR = 1<<FastRegs.MSR
+        CTR = 1<<FastRegs.CTR
+        LR = 1<<FastRegs.LR
+        TAR = 1<<FastRegs.TAR
+        SRR0 = 1<<FastRegs.SRR0
+        SRR1 = 1<<FastRegs.SRR1
+        if name in ['cia', 'nia']:
+            return Const(1), PC # TODO: detect read-conditions
+        if name == 'msr':
+            return Const(1), MSR # TODO: detect read-conditions
+        # TODO: remap the SPR numbers to FAST regs
+        if name == 'spr1':
+            return e.read_fast1.ok, 1<<e.read_fast1.data
+        if name == 'spr2':
+            return e.read_fast2.ok, 1<<e.read_fast2.data
 
-    XER is implicitly-encoded based on whether the operation has carry or
-    overflow.
+    if regfile == 'SPR':
+        assert False, "regfile TODO %s %s" % (regfile, name)
+    assert False, "regspec not found %s %s" % (regfile, name)
 
-    FAST regfile is, again, implicitly encoded, back in PowerDecode2, based
-    on the type of operation (see DecodeB for an example).
 
-    The SPR regfile on the other hand is *binary*-encoded, and, furthermore,
-    has to be "remapped".
+def regspec_decode_write(e, regfile, name):
+    """regspec_decode_write
     """
 
     if regfile == 'INT':
         # Int register numbering is *unary* encoded
-        if name == 'ra': # RA
-            return e.read_reg1.ok, 1<<e.read_reg1.data, None
-        if name == 'rb': # RB
-            return e.read_reg2.ok, 1<<e.read_reg2.data, None
-        if name == 'rc': # RS
-            return e.read_reg3.ok, 1<<e.read_reg3.data, None
         if name == 'o': # RT
-            return e.write_reg.ok, None, 1<<e.write_reg.data
+            return e.write_reg, 1<<e.write_reg.data
         if name == 'o1': # RA (update mode: LD/ST EA)
-            return e.write_ea.ok, None, 1<<e.write_ea.data
+            return e.write_ea, 1<<e.write_ea.data
 
     if regfile == 'CR':
         # CRRegs register numbering is *unary* encoded
         # *sigh*.  numbering inverted on part-CRs.  because POWER.
         if name == 'full_cr': # full CR
-            return e.read_cr_whole, 0b11111111, 0b11111111
+            return e.write_cr_whole, 0b11111111
         if name == 'cr_a': # CR A
-            return e.read_cr1.ok, 1<<(7-e.read_cr1.data), 1<<(7-e.write_cr.data)
-        if name == 'cr_b': # CR B
-            return e.read_cr2.ok, 1<<(7-e.read_cr2.data), None
-        if name == 'cr_c': # CR C
-            return e.read_cr3.ok, 1<<(7-e.read_cr3.data), None
+            return e.write_cr, 1<<(7-e.write_cr.data)
 
     if regfile == 'XER':
         # XERRegs register numbering is *unary* encoded
@@ -72,11 +122,11 @@ def regspec_decode(e, regfile, name):
         CA = 1<<XERRegs.CA
         OV = 1<<XERRegs.OV
         if name == 'xer_so':
-            return e.oe.oe[0] & e.oe.oe_ok, SO, SO
+            return None, SO # hmmm
         if name == 'xer_ov':
-            return e.oe.oe[0] & e.oe.oe_ok, OV, OV
+            return None, OV # hmmm
         if name == 'xer_ca':
-            return (e.input_carry == CryIn.CA.value), CA, CA
+            return None, CA # hmmm
 
     if regfile == 'FAST':
         # FAST register numbering is *unary* encoded
@@ -88,15 +138,16 @@ def regspec_decode(e, regfile, name):
         SRR0 = 1<<FastRegs.SRR0
         SRR1 = 1<<FastRegs.SRR1
         if name in ['cia', 'nia']:
-            return Const(1), PC, PC # TODO: detect read-conditions
+            return None, PC # hmmm
         if name == 'msr':
-            return Const(1), MSR, MS # TODO: detect read-conditions
+            return None, MSR # hmmm
         # TODO: remap the SPR numbers to FAST regs
         if name == 'spr1':
-            return e.read_fast1.ok, 1<<e.read_fast1.data, 1<<e.write_fast1.data
+            return e.write_fast1, 1<<e.write_fast1.data
         if name == 'spr2':
-            return e.read_fast2.ok, 1<<e.read_fast2.data, 1<<e.write_fast2.data
+            return e.write_fast2, 1<<e.write_fast2.data
 
     if regfile == 'SPR':
-        assert False, "regfile TODO %s %s %d" % (refgile, repr(regspec), idx)
-    assert False, "regspec not found %s %s %d" % (refgile, repr(regspec), idx)
+        assert False, "regfile TODO %s %s" % (regfile, name)
+    assert False, "regspec not found %s %s" % (regfile, name)
+
index 14edbeab754644d5b1f65b6d37b90d43dad07126..4c5f4d788bb7950292a63d984032346dfc169f52 100644 (file)
@@ -247,7 +247,12 @@ class NonProductionCore(Elaboratable):
                 else:
                     (regfile, regname, wid) = fu.get_out_spec(idx)
                 print ("    %d %s %s %s" % (idx, regfile, regname, str(wid)))
-                rdflag, read, write = dec2.regspecmap(regfile, regname)
+                if readmode:
+                    rdflag, read = dec2.regspecmap_read(regfile, regname)
+                    write = None
+                else:
+                    rdflag, read = None, None
+                    wrport, write = dec2.regspecmap_write(regfile, regname)
                 if regfile not in byregfiles:
                     byregfiles[regfile] = {}
                     byregfiles_spec[regfile] = {}