radix: reading first page table entry
[soc.git] / src / soc / decoder / power_regspec_map.py
index 1bc486da2cc7014011dc6abaeb84876ecb6b25bd..05ff4814e2504e3acbc5924b614031b460f8bd7c 100644 (file)
@@ -1,69 +1,73 @@
 """regspec_decode
 
-function for the relationship between regspecs and Decode2Execute1Type
+functions for the relationship between regspecs and Decode2Execute1Type
 
-see https://libre-soc.org/3d_gpu/architecture/regfile/ section on regspecs
-"""
-from nmigen import Const
-from soc.regfile.regfiles import XERRegs, FastRegs
-from soc.decoder.power_enums import CryIn
+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:
 
-def regspec_decode(e, regfile, name):
-    """regspec_decode
+* 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
 
-    this function encodes the understanding (relationship) between
-    Regfiles, Computation Units, and the Power ISA Decoder (PowerDecoder2).
+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).
 
-    based on the regspec, which contains the register file name and register
-    name, return a tuple of:
+For the INT and CR numbering, these are expressed in binary in the
+instruction and need to be converted to unary (1<<read_reg1.data).
+Note however that XFX in MTCR is unary-masked!
 
-    * how the decoder should determine whether the Function Unit needs
-      a Regport or not
-    * which Regfile port should be read to get that data
-    * when it comes to writing: likewise, which Regfile port should be written
+XER regs are implicitly-encoded (hard-coded) based on whether the
+operation has carry or overflow.
 
-    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).
+FAST regfile is, again, implicitly encoded, back in PowerDecode2, based
+on the type of operation (see DecodeB for an example, where fast_out
+is set, then carried into read_fast2 in PowerDecode2).
 
-    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.
+The SPR regfile on the other hand is *binary*-encoded, and, furthermore,
+has to be "remapped" to internal SPR Enum indices (see SPRMap in PowerDecode2)
+see https://libre-soc.org/3d_gpu/architecture/regfile/ section on regspecs
+"""
+from nmigen import Const
+from soc.regfile.regfiles import XERRegs, FastRegs, StateRegs
+from soc.decoder.power_enums import CryIn
 
-    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_read(e, regfile, name):
+    """regspec_decode_read
     """
 
+    # INT regfile
+
     if regfile == 'INT':
         # Int register numbering is *unary* encoded
         if name == 'ra': # RA
-            return e.read_reg1.ok, 1<<e.read_reg1.data, None
+            return e.read_reg1.ok, e.read_reg1.data
         if name == 'rb': # RB
-            return e.read_reg2.ok, 1<<e.read_reg2.data, None
+            return e.read_reg2.ok, e.read_reg2.data
         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
-        if name == 'o1': # RA (update mode: LD/ST EA)
-            return e.write_ea.ok, None, 1<<e.write_ea.data
+            return e.read_reg3.ok, e.read_reg3.data
+
+    # CR regfile
 
     if regfile == 'CR':
         # CRRegs register numbering is *unary* encoded
-        if name == 'full_cr': # full CR
-            return e.read_cr_whole, 0b11111111, 0b11111111
+        if name == 'full_cr': # full CR (from FXM field)
+            return e.do.read_cr_whole.ok, e.do.read_cr_whole.data
         if name == 'cr_a': # CR A
-            return e.read_cr1.ok, 1<<e.read_cr1.data, 1<<e.write_cr.data
+            return e.read_cr1.ok, 1<<(7-e.read_cr1.data)
         if name == 'cr_b': # CR B
-            return e.read_cr2.ok, 1<<e.read_cr2.data, None
+            return e.read_cr2.ok, 1<<(7-e.read_cr2.data)
         if name == 'cr_c': # CR C
-            return e.read_cr3.ok, 1<<e.read_cr2.data, None
+            return e.read_cr3.ok, 1<<(7-e.read_cr3.data)
+
+    # XER regfile
 
     if regfile == 'XER':
         # XERRegs register numbering is *unary* encoded
@@ -71,31 +75,110 @@ 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
+            # SO needs to be read for overflow *and* for creation
+            # of CR0 and also for MFSPR
+            return ((e.do.oe.oe[0] & e.do.oe.ok) | (e.xer_in & SO == SO)|
+                     (e.do.rc.rc & e.do.rc.ok)), SO
         if name == 'xer_ov':
-            return e.oe.oe[0] & e.oe.oe_ok, OV, OV
+            return ((e.do.oe.oe[0] & e.do.oe.ok) |
+                    (e.xer_in & CA == CA)), OV
         if name == 'xer_ca':
-            return (e.input_carry == CryIn.CA.value), CA, CA
+            return ((e.do.input_carry == CryIn.CA.value) |
+                    (e.xer_in & OV == OV)), CA
+
+    # STATE regfile
+
+    if regfile == 'STATE':
+        # STATE register numbering is *unary* encoded
+        PC = 1<<StateRegs.PC
+        MSR = 1<<StateRegs.MSR
+        if name in ['cia', 'nia']:
+            return Const(1), PC # TODO: detect read-conditions
+        if name == 'msr':
+            return Const(1), MSR # TODO: detect read-conditions
+
+    # FAST regfile
 
     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
-        SRR1 = 1<<FastRegs.SRR1
-        SRR2 = 1<<FastRegs.SRR2
+        if name == 'fast1':
+            return e.read_fast1.ok, e.read_fast1.data
+        if name == 'fast2':
+            return e.read_fast2.ok, e.read_fast2.data
+
+    # SPR regfile
+
+    if regfile == 'SPR':
+        # SPR register numbering is *binary* encoded
+        if name == 'spr1':
+            return e.read_spr1.ok, e.read_spr1.data
+
+    assert False, "regspec not found %s %s" % (regfile, name)
+
+
+def regspec_decode_write(e, regfile, name):
+    """regspec_decode_write
+    """
+
+    # INT regfile
+
+    if regfile == 'INT':
+        # Int register numbering is *unary* encoded
+        if name == 'o': # RT
+            return e.write_reg, e.write_reg.data
+        if name == 'o1': # RA (update mode: LD/ST EA)
+            return e.write_ea, e.write_ea.data
+
+    # CR regfile
+
+    if regfile == 'CR':
+        # CRRegs register numbering is *unary* encoded
+        # *sigh*.  numbering inverted on part-CRs.  because POWER.
+        if name == 'full_cr': # full CR (from FXM field)
+            return e.do.write_cr_whole.ok, e.do.write_cr_whole.data
+        if name == 'cr_a': # CR A
+            return e.write_cr, 1<<(7-e.write_cr.data)
+
+    # XER regfile
+
+    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.xer_out, SO # hmmm
+        if name == 'xer_ov':
+            return e.xer_out, OV # hmmm
+        if name == 'xer_ca':
+            return e.xer_out, CA # hmmm
+
+    # STATE regfile
+
+    if regfile == 'STATE':
+        # STATE register numbering is *unary* encoded
+        PC = 1<<StateRegs.PC
+        MSR = 1<<StateRegs.MSR
         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
-        # 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
-        if name == 'spr2':
-            return e.read_fast2.ok, 1<<e.read_fast2.data, 1<<e.write_fast2.data
+            return None, MSR # hmmm
+
+    # FAST regfile
+
+    if regfile == 'FAST':
+        # FAST register numbering is *unary* encoded
+        if name == 'fast1':
+            return e.write_fast1, e.write_fast1.data
+        if name == 'fast2':
+            return e.write_fast2, e.write_fast2.data
+
+    # SPR regfile
 
     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)
+        # SPR register numbering is *binary* encoded
+        if name == 'spr1': # SPR1
+            return e.write_spr, e.write_spr.data
+
+    assert False, "regspec not found %s %s" % (regfile, name)
+