add auto-generation of out2 column in SVP64RM
[soc.git] / src / soc / decoder / power_svp64.py
index b7c7cde1ef1ed37f2837a0723818f75f87e88dcf..26e782b390b2bfd0c507089e66de541ea00c0bad 100644 (file)
 from soc.decoder.power_enums import get_csv, find_wiki_dir
 import os
 
+# identifies register by type
+def is_CR_3bit(regname):
+    return regname in ['BF', 'BFA']
+
+def is_CR_5bit(regname):
+    return regname in ['BA', 'BB', 'BC', 'BI', 'BT']
+
+def is_GPR(regname):
+    return regname in ['RA', 'RB', 'RC', 'RS', 'RT']
+
+def get_regtype(regname):
+    if is_CR_3bit(regname):
+        return "CR_3bit"
+    if is_CR_5bit(regname):
+        return "CR_5bit"
+    if is_GPR(regname):
+        return "GPR"
+
+
+def decode_extra(rm, prefix=''):
+    # first turn the svp64 rm into a "by name" dict, recording
+    # which position in the RM EXTRA it goes into
+    # also: record if the src or dest was a CR, for sanity-checking
+    # (elwidth overrides on CRs are banned)
+    dest_reg_cr, src_reg_cr = False, False
+    svp64_srcreg_byname = {}
+    svp64_destreg_byname = {}
+    for i in range(4):
+        print (rm)
+        rfield = rm[prefix+str(i)]
+        if not rfield or rfield == '0':
+            continue
+        print ("EXTRA field", i, rfield)
+        rfield = rfield.split(";") # s:RA;d:CR1 etc.
+        for r in rfield:
+            rtype = r[0]
+            # TODO: ignoring s/d makes it impossible to do
+            # LD/ST-with-update.
+            r = r[2:] # ignore s: and d:
+            if rtype == 'd':
+                svp64_destreg_byname[r] = i # dest reg in EXTRA position 0-3
+            else:
+                svp64_srcreg_byname[r] = i # src reg in EXTRA position 0-3
+            # check the regtype (if CR, record that)
+            regtype = get_regtype(r)
+            if regtype in ['CR_3bit', 'CR_5bit']:
+                if rtype == 'd':
+                    dest_reg_cr = True
+                if rtype == 's':
+                    src_reg_cr = True
+
+    return dest_reg_cr, src_reg_cr, svp64_srcreg_byname, svp64_destreg_byname
+
+
 # gets SVP64 ReMap information
 class SVP64RM:
-    def __init__(self):
+    def __init__(self, microwatt_format=False):
+        """SVP64RM: gets micro-opcode information
+
+        microwatt_format: moves RS to in1 (to match decode1.vhdl)
+        """
         self.instrs = {}
+        self.svp64_instrs = {}
         pth = find_wiki_dir()
         for fname in os.listdir(pth):
             if fname.startswith("RM") or fname.startswith("LDSTRM"):
                 for entry in get_csv(fname):
+                    if microwatt_format:
+                        # move RS from position 1 to position 3, to match
+                        # microwatt decode1.vhdl format
+                        if entry['in1'] == 'RS' and entry['in3'] == 'NONE':
+                            entry['in1'] = 'NONE'
+                            entry['in3'] = 'RS'
                     self.instrs[entry['insn']] = entry
 
 
+    def get_svp64_csv(self, fname):
+        # first get the v3.0B entries
+        v30b = get_csv(fname)
+
+        # now add the RM fields (for each instruction)
+        for entry in v30b:
+            # *sigh* create extra field "out2" based on LD/ST update
+            entry['out2'] = 'NONE'
+            if entry['upd'] == '1':
+                entry['out2'] = 'RA'
+            # dummy (blank) fields, first
+            entry.update({'EXTRA0': '0', 'EXTRA1': '0', 'EXTRA2': '0',
+                          'EXTRA3': '0',
+                          'SV_Ptype': 'NONE', 'SV_Etype': 'NONE',
+                          'sv_cr_in': 'NONE', 'sv_cr_out': 'NONE'})
+            for fname in ['in1', 'in2', 'in3', 'out', 'out2']:
+                entry['sv_%s' % fname] = 'NONE'
+
+            # is this SVP64-augmented?
+            asmcode = entry['comment']
+            if asmcode not in self.instrs:
+                continue
+
+            # start updating the fields, merge relevant info
+            svp64 = self.instrs[asmcode]
+            for k, v in {'EXTRA0': '0', 'EXTRA1': '1', 'EXTRA2': '2',
+                          'EXTRA3': '3',
+                          'SV_Ptype': 'Ptype', 'SV_Etype': 'Etype'}.items():
+                entry[k] = svp64[v]
+
+            # hmm, we need something more useful: a cross-association
+            # of the in1/2/3 and CR in/out with the EXTRA0-3 fields
+            decode = decode_extra(entry, "EXTRA")
+            dest_reg_cr, src_reg_cr, svp64_src, svp64_dest = decode
+
+            # now examine in1/2/3/out, create sv_in1/2/3/out
+            for fname in ['in1', 'in2', 'in3', 'out', 'out2']:
+                regfield = entry[fname]
+                extra_index = None
+                if regfield == 'RA_OR_ZERO':
+                    regfield = 'RA'
+                print (asmcode, regfield, fname, svp64_dest, svp64_src)
+                # find the reg in the SVP64 extra map
+                if (fname in ['out', 'out2'] and regfield in svp64_dest):
+                    extra_index = svp64_dest[regfield]
+                if (fname not in ['out', 'out2'] and regfield in svp64_src):
+                    extra_index = svp64_src[regfield]
+                # ta-daa, we know in1/2/3/out's bit-offset
+                if extra_index is not None:
+                    entry['sv_%s' % fname] = "Idx"+str(extra_index)
+
+            # TODO: CRs a little tricky, the power_enums.CRInSel is a bit odd.
+            # ignore WHOLE_REG for now
+            cr_in = entry['CR in']
+            extra_index = 'NONE'
+            if cr_in in svp64_src:
+                entry['sv_cr_in'] = "Idx"+str(svp64_src[cr_in])
+            elif cr_in == 'BA_BB':
+                index1 = svp64_src.get('BA', None)
+                index2 = svp64_src.get('BB', None)
+                entry['sv_cr_in'] = "Idx_%d_%d" % (index1, index2)
+
+            # CRout a lot easier.  ignore WHOLE_REG for now
+            cr_out = entry['CR out']
+            extra_index = svp64_dest.get(cr_out, None)
+            if extra_index is not None:
+                entry['sv_cr_out'] = 'Idx%d' % extra_index
+
+            # more enum-friendly Ptype names.  should have done this in
+            # sv_analysis.py, oh well
+            if entry['SV_Ptype'] == '1P':
+                entry['SV_Ptype'] = 'P1'
+            if entry['SV_Ptype'] == '2P':
+                entry['SV_Ptype'] = 'P2'
+            self.svp64_instrs[asmcode] = entry
+
+        return v30b
 
+if __name__ == '__main__':
+    isa = SVP64RM()
+    minor_31 = isa.get_svp64_csv("minor_31.csv")
+    for entry in minor_31:
+        if entry['comment'].startswith('ldu'):
+            print ("entry", entry)
+    minor_19 = isa.get_svp64_csv("minor_19.csv")
+    for entry in minor_19:
+        if entry['comment'].startswith('cr'):
+            print (entry)
+    minor_31 = isa.get_svp64_csv("minor_31.csv")
+    for entry in minor_31:
+        print (entry)