1 # SPDX-License-Identifier: LGPLv3+
2 # Copyright (C) 2021 Luke Kenneth Casson Leighton <lkcl@lkcl.net>
3 # Funded by NLnet http://nlnet.nl
5 from openpower
.decoder
.power_enums
import get_csv
, find_wiki_dir
6 from openpower
.util
import log
9 # identifies register by type
10 def is_CR_3bit(regname
):
11 return regname
in ['BF', 'BFA']
13 def is_CR_5bit(regname
):
14 return regname
in ['BA', 'BB', 'BC', 'BI', 'BT']
17 return regname
in ['RA', 'RB', 'RC', 'RS', 'RT']
20 return regname
in ['FRA', 'FRB', 'FRC', 'FRS', 'FRT']
22 def get_regtype(regname
):
23 if is_CR_3bit(regname
):
25 if is_CR_5bit(regname
):
33 def decode_extra(rm
, prefix
=''):
34 # first turn the svp64 rm into a "by name" dict, recording
35 # which position in the RM EXTRA it goes into
36 # also: record if the src or dest was a CR, for sanity-checking
37 # (elwidth overrides on CRs are banned)
38 dest_reg_cr
, src_reg_cr
= False, False
39 svp64_srcreg_byname
= {}
40 svp64_destreg_byname
= {}
41 log ("decode_extra RM", rm
)
43 rfield
= rm
[prefix
+str(i
)]
44 if not rfield
or rfield
== '0':
46 log ("EXTRA field", i
, rfield
)
47 rfield
= rfield
.split(";") # s:RA;d:CR1 etc.
50 # TODO: ignoring s/d makes it impossible to do
52 r
= r
[2:] # ignore s: and d:
54 svp64_destreg_byname
[r
] = i
# dest reg in EXTRA position 0-3
56 svp64_srcreg_byname
[r
] = i
# src reg in EXTRA position 0-3
57 # check the regtype (if CR, record that)
58 regtype
= get_regtype(r
)
59 if regtype
in ['CR_3bit', 'CR_5bit']:
65 return dest_reg_cr
, src_reg_cr
, svp64_srcreg_byname
, svp64_destreg_byname
68 # gets SVP64 ReMap information
70 def __init__(self
, microwatt_format
=False):
71 """SVP64RM: gets micro-opcode information
73 microwatt_format: moves RS to in1 (to match decode1.vhdl)
76 self
.svp64_instrs
= {}
78 for fname
in os
.listdir(pth
):
79 if fname
.startswith("RM") or fname
.startswith("LDSTRM"):
80 for entry
in get_csv(fname
):
81 entry
['insn'] = entry
['insn'].split("=")[-1]
83 # move RS from position 1 to position 3, to match
84 # microwatt decode1.vhdl format
85 if entry
['in1'] == 'RS' and entry
['in3'] == 'NONE':
88 self
.instrs
[entry
['insn']] = entry
91 def get_svp64_csv(self
, fname
):
92 # first get the v3.0B entries
95 # now add the RM fields (for each instruction)
97 # FP entries have a format NN/NN=insn
98 entry
['comment'] = entry
['comment'].split("=")[-1]
99 # *sigh* create extra field "out2" based on LD/ST update
100 # KEEP TRACK HERE https://bugs.libre-soc.org/show_bug.cgi?id=619
101 entry
['out2'] = 'NONE'
102 if entry
['upd'] == '1':
105 # dummy (blank) fields, first
106 entry
.update({'EXTRA0': '0', 'EXTRA1': '0', 'EXTRA2': '0',
108 'SV_Ptype': 'NONE', 'SV_Etype': 'NONE',
109 'sv_cr_in': 'NONE', 'sv_cr_out': 'NONE'})
110 for fname
in ['in1', 'in2', 'in3', 'out', 'out2']:
111 entry
['sv_%s' % fname
] = 'NONE'
113 # is this SVP64-augmented?
114 asmcode
= entry
['comment']
115 if asmcode
not in self
.instrs
:
118 # start updating the fields, merge relevant info
119 svp64
= self
.instrs
[asmcode
]
120 for k
, v
in {'EXTRA0': '0', 'EXTRA1': '1', 'EXTRA2': '2',
122 'SV_Ptype': 'Ptype', 'SV_Etype': 'Etype'}.items():
125 # hmm, we need something more useful: a cross-association
126 # of the in1/2/3 and CR in/out with the EXTRA0-3 fields
127 decode
= decode_extra(entry
, "EXTRA")
128 dest_reg_cr
, src_reg_cr
, svp64_src
, svp64_dest
= decode
130 # now examine in1/2/3/out, create sv_in1/2/3/out
131 for fname
in ['in1', 'in2', 'in3', 'out', 'out2']:
132 regfield
= entry
[fname
]
134 if regfield
== 'RA_OR_ZERO':
136 log (asmcode
, regfield
, fname
, svp64_dest
, svp64_src
)
137 # find the reg in the SVP64 extra map
138 if (fname
in ['out', 'out2'] and regfield
in svp64_dest
):
139 extra_index
= svp64_dest
[regfield
]
140 if (fname
not in ['out', 'out2'] and regfield
in svp64_src
):
141 extra_index
= svp64_src
[regfield
]
142 # ta-daa, we know in1/2/3/out's bit-offset
143 if extra_index
is not None:
144 entry
['sv_%s' % fname
] = "Idx"+str(extra_index
)
146 # TODO: CRs a little tricky, the power_enums.CRInSel is a bit odd.
147 # ignore WHOLE_REG for now
148 cr_in
= entry
['CR in']
150 if cr_in
in svp64_src
:
151 entry
['sv_cr_in'] = "Idx"+str(svp64_src
[cr_in
])
152 elif cr_in
== 'BA_BB':
153 index1
= svp64_src
.get('BA', None)
154 index2
= svp64_src
.get('BB', None)
155 entry
['sv_cr_in'] = "Idx_%d_%d" % (index1
, index2
)
157 # CRout a lot easier. ignore WHOLE_REG for now
158 cr_out
= entry
['CR out']
159 extra_index
= svp64_dest
.get(cr_out
, None)
160 if extra_index
is not None:
161 entry
['sv_cr_out'] = 'Idx%d' % extra_index
163 # more enum-friendly Ptype names. should have done this in
164 # sv_analysis.py, oh well
165 if entry
['SV_Ptype'] == '1P':
166 entry
['SV_Ptype'] = 'P1'
167 if entry
['SV_Ptype'] == '2P':
168 entry
['SV_Ptype'] = 'P2'
169 self
.svp64_instrs
[asmcode
] = entry
173 if __name__
== '__main__':
175 minor_31
= isa
.get_svp64_csv("minor_31.csv")
176 for entry
in minor_31
:
177 if entry
['comment'].startswith('ldu'):
178 print ("entry", entry
)
179 minor_19
= isa
.get_svp64_csv("minor_19.csv")
180 for entry
in minor_19
:
181 if entry
['comment'].startswith('cr'):
183 minor_31
= isa
.get_svp64_csv("minor_31.csv")
184 for entry
in minor_31
: