power_insn: slightly change table checking style
[openpower-isa.git] / src / openpower / decoder / power_regspec_map.py
index a7f150ecb79bc015f769978b00d2c094042e2521..71fbb2823961976574dd9c596eac761b4278086b 100644 (file)
@@ -34,39 +34,46 @@ 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 nmigen import Const, Signal
 from openpower.consts import XERRegsEnum, FastRegsEnum, StateRegsEnum
 from openpower.decoder.power_enums import CryIn
 from openpower.util import log
+from collections import namedtuple
 
+RegDecodeInfo = namedtuple("RedDecodeInfo", ['okflag', 'regport', 'portlen'])
 
-def regspec_decode_read(e, regfile, name):
+# XXX TODO: these portlen numbers *must* increase / adapt for SVP64.
+
+def regspec_decode_read(m, e, regfile, name):
     """regspec_decode_read
     """
 
+    rd = None
+
     # INT regfile
 
     if regfile == 'INT':
         # Int register numbering is *unary* encoded
         if name == 'ra': # RA
-            return e.read_reg1.ok, e.read_reg1.data
+            rd = RegDecodeInfo(e.read_reg1.ok, e.read_reg1.data, 5)
         if name == 'rb': # RB
-            return e.read_reg2.ok, e.read_reg2.data
+            rd = RegDecodeInfo(e.read_reg2.ok, e.read_reg2.data, 5)
         if name == 'rc': # RS
-            return e.read_reg3.ok, e.read_reg3.data
+            rd = RegDecodeInfo(e.read_reg3.ok, e.read_reg3.data, 5)
 
     # CR regfile
 
     if regfile == 'CR':
         # CRRegs register numbering is *unary* encoded
         if name == 'full_cr': # full CR (from FXM field)
-            return e.do.read_cr_whole.ok, e.do.read_cr_whole.data
+            rd = RegDecodeInfo(e.do.read_cr_whole.ok,
+                               e.do.read_cr_whole.data, 8)
         if name == 'cr_a': # CR A
-            return e.read_cr1.ok, 1<<(7-e.read_cr1.data)
+            rd = RegDecodeInfo(e.read_cr1.ok, 1<<(7-e.read_cr1.data), 8)
         if name == 'cr_b': # CR B
-            return e.read_cr2.ok, 1<<(7-e.read_cr2.data)
+            rd = RegDecodeInfo(e.read_cr2.ok, 1<<(7-e.read_cr2.data), 8)
         if name == 'cr_c': # CR C
-            return e.read_cr3.ok, 1<<(7-e.read_cr3.data)
+            rd = RegDecodeInfo(e.read_cr3.ok, 1<<(7-e.read_cr3.data), 8)
 
     # XER regfile
 
@@ -78,14 +85,15 @@ def regspec_decode_read(e, regfile, name):
         if name == 'xer_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
+            rd = RegDecodeInfo(((e.do.oe.oe[0] & e.do.oe.ok) |
+                                  (e.xer_in & SO == SO)|
+                                  (e.do.rc.rc & e.do.rc.ok)), SO, 3)
         if name == 'xer_ov':
-            return ((e.do.oe.oe[0] & e.do.oe.ok) |
-                    (e.xer_in & CA == CA)), OV
+            rd = RegDecodeInfo(((e.do.oe.oe[0] & e.do.oe.ok) |
+                                  (e.xer_in & CA == CA)), OV, 3)
         if name == 'xer_ca':
-            return ((e.do.input_carry == CryIn.CA.value) |
-                    (e.xer_in & OV == OV)), CA
+            rd = RegDecodeInfo(((e.do.input_carry == CryIn.CA.value) |
+                                  (e.xer_in & OV == OV)), CA, 3)
 
     # STATE regfile
 
@@ -95,47 +103,61 @@ def regspec_decode_read(e, regfile, name):
         MSR = 1<<StateRegsEnum.MSR
         SVSTATE = 1<<StateRegsEnum.SVSTATE
         if name in ['cia', 'nia']:
-            return Const(1), PC # TODO: detect read-conditions
+            # TODO: detect read-conditions
+            rd = RegDecodeInfo(Const(1), PC, 5)
         if name == 'msr':
-            return Const(1), MSR # TODO: detect read-conditions
+            # TODO: detect read-conditions
+            rd = RegDecodeInfo(Const(1), MSR, 5)
         if name == 'svstate':
-            return Const(1), SVSTATE # TODO: detect read-conditions
+            # TODO: detect read-conditions
+            rd = RegDecodeInfo(Const(1), SVSTATE, 5)
+        if name == 'state1':
+            rd = RegDecodeInfo(e.read_state1.ok, 1<<e.read_state1.data, 5)
 
     # FAST regfile
 
     if regfile == 'FAST':
-        # FAST register numbering is *unary* encoded
+        # FAST register numbering is *binary* encoded
         if name == 'fast1':
-            return e.read_fast1.ok, e.read_fast1.data
+            rd = RegDecodeInfo(e.read_fast1.ok, e.read_fast1.data, 4)
         if name == 'fast2':
-            return e.read_fast2.ok, e.read_fast2.data
+            rd = RegDecodeInfo(e.read_fast2.ok, e.read_fast2.data, 4)
         if name == 'fast3':
-            return e.read_fast3.ok, e.read_fast3.data
+            rd = RegDecodeInfo(e.read_fast3.ok, e.read_fast3.data, 4)
 
     # SPR regfile
 
     if regfile == 'SPR':
         # SPR register numbering is *binary* encoded
         if name == 'spr1':
-            return e.read_spr1.ok, e.read_spr1.data
+            rd = RegDecodeInfo(e.read_spr1.ok, e.read_spr1.data, 10)
+
+    assert rd is not None, "regspec not found %s %s" % (regfile, name)
+
+    rname="rd_decode_%s_%s" % (regfile, name)
+    ok = Signal(name=rname+"_ok", reset_less=True)
+    data = Signal(rd.portlen, name=rname+"_port", reset_less=True)
+    m.d.comb += ok.eq(rd.okflag)
+    m.d.comb += data.eq(rd.regport)
 
-    assert False, "regspec not found %s %s" % (regfile, name)
+    return RegDecodeInfo(ok, data, rd.portlen)
 
 
-def regspec_decode_write(e, regfile, name):
+def regspec_decode_write(m, e, regfile, name):
     """regspec_decode_write
     """
 
     #log("regspec_decode_write", regfile, name, e.__class__.__name__)
+    wr = None
 
     # INT regfile
 
     if regfile == 'INT':
         # Int register numbering is *unary* encoded
         if name == 'o': # RT
-            return e.write_reg.ok, e.write_reg.data
+            wr = RegDecodeInfo(e.write_reg.ok, e.write_reg.data, 5)
         if name == 'o1': # RA (update mode: LD/ST EA)
-            return e.write_ea.ok, e.write_ea.data
+            wr = RegDecodeInfo(e.write_ea.ok, e.write_ea.data, 5)
 
     # CR regfile
 
@@ -143,9 +165,11 @@ def regspec_decode_write(e, regfile, name):
         # 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
+            wr = RegDecodeInfo(e.do.write_cr_whole.ok,
+                                 e.do.write_cr_whole.data, 8)
         if name == 'cr_a': # CR A
-            return e.write_cr.ok, 1<<(7-e.write_cr.data)
+            wr = RegDecodeInfo(e.write_cr.ok,
+                               1<<(7-e.write_cr.data), 8)
 
     # XER regfile
 
@@ -155,11 +179,14 @@ def regspec_decode_write(e, regfile, name):
         CA = 1<<XERRegsEnum.CA
         OV = 1<<XERRegsEnum.OV
         if name == 'xer_so':
-            return e.xer_out, SO # hmmm
+            wr = RegDecodeInfo(e.xer_out | (e.do.oe.oe[0] & e.do.oe.ok),
+                                    SO, 3) # hmmm
         if name == 'xer_ov':
-            return e.xer_out, OV # hmmm
+            wr = RegDecodeInfo(e.xer_out | (e.do.oe.oe[0] & e.do.oe.ok),
+                                    OV, 3) # hmmm
         if name == 'xer_ca':
-            return e.xer_out, CA # hmmm
+            wr = RegDecodeInfo(e.xer_out | (e.do.output_carry),
+                                    CA, 3) # hmmm
 
     # STATE regfile
 
@@ -169,29 +196,49 @@ def regspec_decode_write(e, regfile, name):
         MSR = 1<<StateRegsEnum.MSR
         SVSTATE = 1<<StateRegsEnum.SVSTATE
         if name in ['cia', 'nia']:
-            return None, PC # hmmm
+            wr = RegDecodeInfo(None, PC, 5) # hmmm
         if name == 'msr':
-            return None, MSR # hmmm
+            wr = RegDecodeInfo(None, MSR, 5) # hmmm
         if name == 'svstate':
-            return None, SVSTATE # hmmm
+            wr = RegDecodeInfo(None, SVSTATE, 5) # hmmm
+        if name == 'state1':
+            wr = RegDecodeInfo(e.write_state1.ok, 1<<e.write_state1.data, 5)
 
     # FAST regfile
 
     if regfile == 'FAST':
-        # FAST register numbering is *unary* encoded
+        # FAST register numbering is *binary* encoded
         if name == 'fast1':
-            return e.write_fast1.ok, e.write_fast1.data
+            wr = RegDecodeInfo(e.write_fast1.ok, e.write_fast1.data, 4)
         if name == 'fast2':
-            return e.write_fast2.ok, e.write_fast2.data
+            wr = RegDecodeInfo(e.write_fast2.ok, e.write_fast2.data, 4)
         if name == 'fast3':
-            return e.write_fast3.ok, e.write_fast3.data
+            wr = RegDecodeInfo(e.write_fast3.ok, e.write_fast3.data, 4)
 
     # SPR regfile
 
     if regfile == 'SPR':
         # SPR register numbering is *binary* encoded
         if name == 'spr1': # SPR1
-            return e.write_spr.ok, e.write_spr.data
+            wr = RegDecodeInfo(e.write_spr.ok, e.write_spr.data, 10)
+
+    assert wr is not None, "regspec not found %s %s" % (regfile, name)
+
+    rname="wr_decode_%s_%s" % (regfile, name)
+    if wr.okflag is not None:
+        ok = Signal(name=rname+"_ok", reset_less=True)
+        m.d.comb += ok.eq(wr.okflag)
+    else:
+        # XXX urrrr, really do have to deal with this some time
+        ok = None
+    data = Signal(wr.portlen, name=rname+"_port", reset_less=True)
+    m.d.comb += data.eq(wr.regport)
+
+    return RegDecodeInfo(ok, data, wr.portlen)
+
 
-    assert False, "regspec not found %s %s" % (regfile, name)
+def regspec_decode(m, readmode, e, regfile, name):
+    if readmode:
+        return regspec_decode_read(m, e, regfile, name)
+    return regspec_decode_write(m, e, regfile, name)