4706479431bc8debb1b683b22b4e0c16e5b00f56
3 # NOTE that this program is python2 compatible, please do not stop it
4 # from working by adding syntax that prevents that.
6 # Initial version written by lkcl Oct 2020
7 # This program analyses the Power 9 op codes and looks at in/out register uses
8 # The results are displayed:
9 # https://libre-soc.org/openpower/opcode_regs_deduped/
11 # It finds .csv files in the directory isatables/
12 # then goes through the categories and creates svp64 CSV augmentation
13 # tables on a per-opcode basis
17 from os
.path
import dirname
, join
19 from collections
import OrderedDict
21 # Return absolute path (ie $PWD) + isatables + name
22 def find_wiki_file(name
):
23 filedir
= os
.path
.dirname(os
.path
.abspath(__file__
))
24 tabledir
= join(filedir
, 'isatables')
25 file_path
= join(tabledir
, name
)
28 # Return an array of dictionaries from the CSV file name:
30 file_path
= find_wiki_file(name
)
31 with
open(file_path
, 'r') as csvfile
:
32 reader
= csv
.DictReader(csvfile
)
35 # Write an array of dictionaries to the CSV file name:
36 def write_csv(name
, items
, headers
):
37 file_path
= find_wiki_file(name
)
38 with
open(file_path
, 'w') as csvfile
:
39 writer
= csv
.DictWriter(csvfile
, fieldnames
)
41 writer
.writerows(items
)
43 # This will return True if all values are true.
44 # Not sure what this is about
46 #for v in row.values():
47 # if 'SPR' in v: # skip all SPRs
49 for v
in row
.values():
54 # General purpose registers have names like: RA, RT, R1, ...
55 # Floating point registers names like: FRT, FRA, FR1, ..., FRTp, ...
56 # Return True if field is a register
58 return field
.startswith('R') or field
.startswith('FR')
61 # These are the attributes of the instructions,
63 keycolumns
= ['unit', 'in1', 'in2', 'in3', 'out', 'CR in', 'CR out',
64 ] # don't think we need these: 'ldst len', 'rc', 'lk']
66 tablecols
= ['unit', 'in', 'outcnt', 'CR in', 'CR out', 'imm'
67 ] # don't think we need these: 'ldst len', 'rc', 'lk']
72 for key
in keycolumns
:
73 # registers IN - special-case: count number of regs RA/RB/RC/RS
74 if key
in ['in1', 'in2', 'in3']:
82 # If upd is 1 then increment the count of outputs
83 if 'outcnt' not in res
:
90 # CRs (Condition Register) (CR0 .. CR7)
91 if key
.startswith('CR'):
92 if row
[key
].startswith('NONE'):
96 if row
['comment'].startswith('cr'):
100 if row
[key
] == 'LDST': # we care about LDST units
104 # LDST len (LoadStore length)
105 if key
.startswith('ldst'):
106 if row
[key
].startswith('NONE'):
111 if key
in ['rc', 'lk']:
112 if row
[key
] == 'ONE':
114 elif row
[key
] == 'NONE':
121 # Convert the numerics 'in' & 'outcnt' to strings
122 res
['in'] = str(res
['in'])
123 res
['outcnt'] = str(res
['outcnt'])
127 if row
['in2'].startswith('CONST_'):
128 res
['imm'] = "1" # row['in2'].split("_")[1]
137 for k
, v
in d
.items():
138 res
.append("%s: %s" % (k
, v
))
142 return ' | '.join(d
) + " |"
146 if row
['unit'] != 'OTHER':
147 res
.append(row
['unit'])
149 res
.append('%sR' % row
['in'])
150 if row
['outcnt'] != '0':
151 res
.append('%sW' % row
['outcnt'])
152 if row
['CR in'] == '1' and row
['CR out'] == '1':
154 res
.append("CR=2R1W")
157 elif row
['CR in'] == '1':
159 elif row
['CR out'] == '1':
161 elif 'imm' in row
and row
['imm']:
170 dictkeys
= OrderedDict()
172 insns
= {} # dictionary of CSV row, by instruction
174 print ("# OpenPOWER ISA register 'profile's")
176 print ("this page is auto-generated, do not edit")
177 print ("created by http://libre-soc.org/openpower/sv_analysis.py")
180 # Expand that (all .csv files)
181 pth
= find_wiki_file("*.csv")
183 # Ignore those containing: valid test sprs
184 for fname
in glob(pth
):
193 csvname
= os
.path
.split(fname
)[1]
194 # csvname is something like: minor_59.csv, fname the whole path
200 insns
[row
['comment']] = row
# accumulate csv data by instruction
201 dkey
= create_key(row
)
202 key
= tuple(dkey
.values())
208 bykey
[key
].append((csvname
, row
['opcode'], row
['comment'],
209 row
['form'].upper() + '-Form'))
211 # detect immediates, collate them (useful info)
212 if row
['in2'].startswith('CONST_'):
213 imm
= row
['in2'].split("_")[1]
214 if key
not in immediates
:
215 immediates
[key
] = set()
216 immediates
[key
].add(imm
)
218 primarykeys
= list(primarykeys
)
221 # mapping to old SVPrefix "Forms"
222 mapsto
= {'3R-1W-CRio': 'RM-1P-3S1D',
223 '2R-1W-CRio': 'RM-1P-2S1D',
224 '2R-1W-CRi': 'RM-1P-3S1D',
225 '2R-1W-CRo': 'RM-1P-2S1D',
227 '2R-1W': 'RM-1P-2S1D',
228 '1R-CRio': 'RM-2P-2S1D',
229 '2R-CRio': 'RM-1P-2S1D',
230 '2R-CRo': 'RM-1P-2S1D',
232 '1R-1W-CRio': 'RM-2P-1S1D',
233 '1R-1W-CRo': 'RM-2P-1S1D',
234 '1R-1W': 'RM-2P-1S1D',
235 '1R-1W-imm': 'RM-2P-1S1D',
236 '1R-CRo': 'RM-2P-1S1D',
239 '1W-CRi': 'RM-2P-1S1D',
240 'CRio': 'RM-2P-1S1D',
241 'CR=2R1W': 'RM-1P-2S1D',
245 'LDST-2R-imm': 'RM-2P-2S',
246 'LDST-2R-1W-imm': 'RM-2P-2S1D',
247 'LDST-2R-1W': 'RM-2P-2S1D',
248 'LDST-2R-2W': 'RM-2P-2S1D',
249 'LDST-1R-1W-imm': 'RM-2P-1S1D',
250 'LDST-1R-2W-imm': 'RM-2P-1S2D',
251 'LDST-3R': 'RM-2P-3S',
252 'LDST-3R-CRo': 'RM-2P-3S', # st*x
253 'LDST-3R-1W': 'RM-2P-2S1D', # st*x
255 print ("# map to old SV Prefix")
257 print ('[[!table data="""')
258 for key
in primarykeys
:
259 name
= keyname(dictkeys
[key
])
260 value
= mapsto
.get(name
, "-")
261 print (tformat([name
, value
+ " "]))
267 print ('[[!table data="""')
268 print (tformat(tablecols
) + " imms | name |")
270 # print out the keys and the table from which they're derived
271 for key
in primarykeys
:
272 name
= keyname(dictkeys
[key
])
273 row
= tformat(dictkeys
[key
].values())
274 imms
= list(immediates
.get(key
, ""))
276 row
+= " %s | " % ("/".join(imms
))
277 row
+= " %s |" % name
282 # print out, by remap name, all the instructions under that category
283 for key
in primarykeys
:
284 name
= keyname(dictkeys
[key
])
285 value
= mapsto
.get(name
, "-")
286 print ("## %s (%s)" % (name
, value
))
288 print ('[[!table data="""')
289 print (tformat(['CSV', 'opcode', 'asm', 'form']))
297 #for fname, csv in csvs.items():
300 #for insn, row in insns.items():
303 print ("# svp64 remaps")
304 # create a CSV file, per category, with SV "augmentation" info
305 csvcols
= ['insn', 'Ptype', 'in1', 'in2', 'in3', 'out', 'CR in', 'CR out']
306 for key
in primarykeys
:
307 name
= keyname(dictkeys
[key
])
308 value
= mapsto
.get(name
, "-")
309 if value
== 'non-SV':
311 print ("## %s (%s)" % (name
, value
))
313 print ('[[!table data="""')
314 print (tformat(csvcols
))
318 # get the instruction
320 insn
= insns
[insn_name
]
321 # start constructing svp64 CSV row
323 res
['insn'] = insn_name
324 res
['Ptype'] = value
.split('-')[1] # predication type (RM-xN-xxx)
325 # go through each register matching to Rxxxx_EXTRAx
326 for k
in ['in1', 'in2', 'in3', 'out', 'CR in', 'CR out']:
327 if insn
[k
].startswith('CONST'):
331 print (tformat(res
.values()))
335 if __name__
== '__main__':