reorganise twin-predication
[riscv-isa-sim.git] / id_regs.py
index 54443557e2f6e2c7022eca7f087e2874ec043b98..cd82b60a1affcef49d37c91d28eea360b3228b59 100644 (file)
 """
 
 import os
+import sys
 
 insns_dir = "./riscv/insns"
 def list_insns():
+    if len(sys.argv) == 2:
+        fullfname = sys.argv[1]
+        pth, fname = os.path.split(fullfname)
+        insn = fname[:-2]
+        return [(fullfname, insn)]
+
     res = []
     for fname in os.listdir(insns_dir):
         if not fname.endswith(".h"):
@@ -32,13 +39,42 @@ def list_insns():
         res.append((os.path.join(insns_dir, fname), insn))
     return res
 
-patterns = ['WRITE_RD', 'RS1', 'RS2', 'RS3',
-            'WRITE_FRD', 'FRS1', 'FRS2', 'FRS3']
+cintpatterns = [ 'WRITE_RVC_RS1S', 'WRITE_RVC_RS2S',
+                 'RVC_RS1', 'RVC_RS2', 'RVC_RS1S', 'RVC_RS2S', ]
+cfloatpatterns = [ 'WRITE_RVC_FRS2S', 'RVC_FRS2 ', 'RVC_FRS2S ']
+intpatterns   = ['WRITE_RD' , 'RS1', 'RS2', 'RS3']
+floatpatterns = ['WRITE_FRD', 'FRS1', 'FRS2', 'FRS3']
+patterns = intpatterns + floatpatterns
+patterns += cintpatterns
+patterns += cfloatpatterns
+
+allfloats = floatpatterns + cfloatpatterns
+floatmask = (1<<len(allfloats)-1)
+allints = intpatterns + cintpatterns[2:]
 
-def find_registers(fname):
+skip = '#define USING_NOREGS\n' \
+       '#define REGS_PATTERN 0x0\n'
+
+# this matches the order of the 4 predication arguments to
+drlookup = { 'rd': 0, 'frd': 0, 'rs1': 1, 'rs2': 2, 'rs3': 3,
+             'rvc_rs1': 1, 'rvc_rs1s': 1,
+             'rvc_rs2': 2, 'rvc_rs2s': 2,
+             'rvc_frs2': 2, 'rvc_frs2s': 2,
+             }
+
+def find_registers(fname, twin_predication):
+    # HACK! macro-skipping of instructions too painful
+    for notparallel in ['csr', 'lui', 'c_j', 'wfi', 'auipc',
+                        'dret', 'uret', 'mret', 'sret',
+                        'lr_d', 'lr_w', 'sc_d', 'sc_w']:
+        if notparallel in fname:
+            return skip
     res = []
+    regs = []
+    isintfloat = 0x0 + floatmask << len(allints)
     with open(fname) as f:
         f = f.read()
+        dest_reg = None
         for pattern in patterns:
             x = f.find(pattern)
             if x == -1:
@@ -47,10 +83,69 @@ def find_registers(fname):
                 # botch-job/hack: RS1 also matches against FRS1 (etc.)
                 # check letter before match: if "F", skip it.
                 continue
+            if pattern.startswith('R') and x != 0 and f[x-1] == '_':
+                # RS1 also matches against RVC_RS1 (etc.)
+                # check letter before match: if "_", skip it.
+                continue
+            if pattern.startswith('FR') and x != 0 and f[x-1] == '_':
+                # RS1 also matches against RVC_FRS1 (etc.)
+                # check letter before match: if "_", skip it.
+                continue
+            if 'RVC_' in pattern and f[x+len(pattern)] == 'S':
+                # RVC_RS2S also matches against RVC_RS2 (etc.)
+                # check letter at end of match: if "S", skip it.
+                continue
             p = pattern
             if p.startswith('WRITE_'):
                 p = p[6:]
+                dest_reg = p
+            if pattern in allints:
+                idx = allints.index(pattern)
+                isintfloat += 1 << idx
+            if pattern in allfloats:
+                idx = allfloats.index(pattern)
+                isintfloat &= ~(1 << (idx+len(allints)))
+            regs.append(p)
             res.append('#define USING_REG_%s' % p)
+        if dest_reg:
+            dr = dest_reg
+            fdest = False
+            if dest_reg.startswith('RVC_F'):
+                fdest = True
+                dr = 'RVC_' + dest_reg[5:]
+            if dest_reg == 'FRD':
+                fdest = True
+                dr = 'RD'
+            dridx = drlookup[dest_reg.lower()]
+            res.append('#define DEST_REG %s' % dr.lower())
+            res.append('#define _DEST_REG _%s' % dr.lower())
+            res.append('#define DEST_PREDINT %d' % (0 if fdest else 1))
+    if not res:
+        return skip
+    res.append('#define REGS_PATTERN 0x%x' % isintfloat)
+
+    predargs = ['dest_pred'] * 4
+    if twin_predication:
+        found = None
+        for search in ['rs1', 'rs2', 'rs3', 'rvc_rs1', 'rvc_rs1s',
+                       'rvc_rs2', 'rvc_rs2s',
+                       'frs1', 'frs2', 'frs3',
+                       'rvc_frs2', 'rvc_frs2s']:
+            if search.upper() in regs:
+                found = search
+        if found:
+            predargs[drlookup[found]] = 'src_pred'
+            fsrc = 'f' in found
+            found = found.replace('f', '')
+            res.append('#define SRC_PREDINT %d' % (0 if fsrc else 1))
+            res.append('#define SRC_REG %s' % found)
+
+    res.append('#define PRED_ARGS %s' % ','.join(predargs))
+    offsargs = []
+    for i in range(4):
+        offsargs.append(predargs[i].replace('pred', 'offs'))
+    res.append('#define OFFS_ARGS %s' % ','.join(offsargs))
+
     return '\n'.join(res)
 
 if __name__ == '__main__':
@@ -58,5 +153,40 @@ if __name__ == '__main__':
     for (fname, insn) in files:
         regsname = "regs_%s.h" % insn
         regsname = os.path.join(insns_dir, regsname)
+        twin_predication = False
         with open(regsname, "w") as f:
-            f.write(find_registers(fname))
+            txt = "\n#define INSN_%s\n" % insn.upper()
+            # help identify type of register
+            if insn in ['beq', 'bne', 'blt', 'bltu', 'bge', 'bgeu']:
+                txt += "#define INSN_TYPE_BRANCH\n"
+            if insn in ['lb', 'lbu', 'lw', 'lwu', 'ld', 'ldu']:
+                twin_predication = True
+                txt += "#define INSN_TYPE_LOAD\n"
+            elif insn in ['c_lwsp', 'c_ldsp', 'c_lqsp', 'c_flwsp', 'c_fldsp']:
+                txt += "\n#define INSN_TYPE_C_STACK_LD\n"
+            elif insn in ['c_swsp', 'c_sdsp', 'c_sqsp', 'c_fswsp', 'c_fsdsp']:
+                txt += "\n#define INSN_TYPE_C_STACK_ST\n"
+            elif insn in ['c_lw', 'c_ld', 'c_lq', 'c_flw', 'c_fld']:
+                txt += "\n#define INSN_TYPE_C_LD\n"
+                twin_predication = True
+            elif insn in ['c_sw', 'c_sd', 'c_sq', 'c_fsw', 'c_fsd']:
+                txt += "\n#define INSN_TYPE_C_ST\n"
+                twin_predication = True
+            elif insn in ['c_beqz', 'c_bnez']:
+                txt += "\n#define INSN_TYPE_C_BRANCH\n"
+            elif insn in ['c_mv']:
+                twin_predication = True
+            elif insn.startswith("c_"):
+                txt += "#define INSN_TYPE_C\n"
+            elif insn.startswith("fmv") or \
+                 insn.startswith("fcvt") or \
+                 insn.startswith("fsgn"):
+                txt += "#define INSN_TYPE_FP_DUALOP\n"
+            elif insn.startswith("feq") or \
+                 insn.startswith("flt") or \
+                 insn.startswith("fle"):
+                txt += "#define INSN_TYPE_FP_BRANCH\n"
+            if twin_predication:
+                txt += "\n#define INSN_CATEGORY_TWINPREDICATION\n"
+            txt += find_registers(fname, twin_predication)
+            f.write(txt)