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
19 from os
.path
import dirname
, join
21 from collections
import OrderedDict
22 from openpower
.decoder
.power_svp64
import SVP64RM
23 from openpower
.decoder
.power_enums
import find_wiki_file
, get_csv
26 # Write an array of dictionaries to the CSV file name:
27 def write_csv(name
, items
, headers
):
28 file_path
= find_wiki_file(name
)
29 with
open(file_path
, 'w') as csvfile
:
30 writer
= csv
.DictWriter(csvfile
, headers
, lineterminator
="\n")
32 writer
.writerows(items
)
34 # This will return True if all values are true.
35 # Not sure what this is about
39 # for v in row.values():
40 # if 'SPR' in v: # skip all SPRs
42 for v
in row
.values():
47 # General purpose registers have names like: RA, RT, R1, ...
48 # Floating point registers names like: FRT, FRA, FR1, ..., FRTp, ...
49 # Return True if field is a register
53 return (field
.startswith('R') or field
.startswith('FR') or
57 # These are the attributes of the instructions,
59 keycolumns
= ['unit', 'in1', 'in2', 'in3', 'out', 'CR in', 'CR out',
60 ] # don't think we need these: 'ldst len', 'rc', 'lk']
62 tablecols
= ['unit', 'in', 'outcnt', 'CR in', 'CR out', 'imm'
63 ] # don't think we need these: 'ldst len', 'rc', 'lk']
69 for key
in keycolumns
:
70 # registers IN - special-case: count number of regs RA/RB/RC/RS
71 if key
in ['in1', 'in2', 'in3']:
74 if row
['unit'] == 'BRANCH': # branches must not include Vector SPRs
81 # If upd is 1 then increment the count of outputs
82 if 'outcnt' not in res
:
89 # CRs (Condition Register) (CR0 .. CR7)
90 if key
.startswith('CR'):
91 if row
[key
].startswith('NONE'):
95 if row
['comment'].startswith('cr'):
99 if row
[key
] == 'LDST': # we care about LDST units
103 # LDST len (LoadStore length)
104 if key
.startswith('ldst'):
105 if row
[key
].startswith('NONE'):
110 if key
in ['rc', 'lk']:
111 if row
[key
] == 'ONE':
113 elif row
[key
] == 'NONE':
120 # Convert the numerics 'in' & 'outcnt' to strings
121 res
['in'] = str(res
['in'])
122 res
['outcnt'] = str(res
['outcnt'])
125 if row
['in2'].startswith('CONST_'):
126 res
['imm'] = "1" # row['in2'].split("_")[1]
137 for k
, v
in d
.items():
138 res
.append("%s: %s" % (k
, v
))
143 return ' | '.join(d
) + " |"
148 if row
['unit'] != 'OTHER':
149 res
.append(row
['unit'])
151 res
.append('%sR' % row
['in'])
152 if row
['outcnt'] != '0':
153 res
.append('%sW' % row
['outcnt'])
154 if row
['CR in'] == '1' and row
['CR out'] == '1':
156 res
.append("CR=2R1W")
159 elif row
['CR in'] == '1':
161 elif row
['CR out'] == '1':
163 elif 'imm' in row
and row
['imm']:
168 class Format(enum
.Enum
):
172 def _missing_(cls
, value
):
178 return self
.name
.lower()
181 def process_csvs(format
):
186 dictkeys
= OrderedDict()
188 insns
= {} # dictionary of CSV row, by instruction
191 print("# OpenPOWER ISA register 'profile's")
193 print("this page is auto-generated, do not edit")
194 print("created by http://libre-soc.org/openpower/sv_analysis.py")
197 # Expand that (all .csv files)
198 pth
= find_wiki_file("*.csv")
200 # Ignore those containing: valid test sprs
201 for fname
in glob(pth
):
202 print("sv analysis checking", fname
)
203 _
, name
= os
.path
.split(fname
)
210 if fname
.endswith('sprs.csv'):
212 if fname
.endswith('minor_19_valid.csv'):
216 csvname
= os
.path
.split(fname
)[1]
217 csvname_
= csvname
.split(".")[0]
218 # csvname is something like: minor_59.csv, fname the whole path
221 csvs_svp64
[csvname_
] = []
226 insn_name
= row
['comment']
227 condition
= row
['CONDITIONS']
228 # skip instructions that are not suitable
229 if insn_name
.startswith("l") and insn_name
.endswith("br"):
230 continue # skip pseudo-alias lxxxbr
231 if insn_name
in ['mcrxr', 'mcrxrx', 'darn']:
233 if insn_name
in ['bctar', 'bcctr']:
235 if 'rfid' in insn_name
:
237 if insn_name
in ['setvl', ]: # SVP64 opcodes
240 insns
[(insn_name
, condition
)] = row
# accumulate csv data
241 insn_to_csv
[insn_name
] = csvname_
# CSV file name by instruction
242 dkey
= create_key(row
)
243 key
= tuple(dkey
.values())
249 bykey
[key
].append((csvname
, row
['opcode'], insn_name
, condition
,
250 row
['form'].upper() + '-Form'))
252 # detect immediates, collate them (useful info)
253 if row
['in2'].startswith('CONST_'):
254 imm
= row
['in2'].split("_")[1]
255 if key
not in immediates
:
256 immediates
[key
] = set()
257 immediates
[key
].add(imm
)
259 primarykeys
= list(primarykeys
)
262 # mapping to old SVPrefix "Forms"
263 mapsto
= {'3R-1W-CRo': 'RM-1P-3S1D',
264 '2R-1W-CRio': 'RM-1P-2S1D',
265 '2R-1W-CRi': 'RM-1P-3S1D',
266 '2R-1W-CRo': 'RM-1P-2S1D',
268 '2R-1W': 'RM-1P-2S1D',
269 '1R-CRio': 'RM-2P-2S1D',
270 '2R-CRio': 'RM-1P-2S1D',
271 '2R-CRo': 'RM-1P-2S1D',
273 '1R-1W-CRio': 'RM-2P-1S1D',
274 '1R-1W-CRo': 'RM-2P-1S1D',
275 '1R-1W': 'RM-2P-1S1D',
276 '1R-1W-imm': 'RM-2P-1S1D',
277 '1R-CRo': 'RM-2P-1S1D',
279 '1W-CRo': 'RM-1P-1D',
281 '1W-CRi': 'RM-2P-1S1D',
282 'CRio': 'RM-2P-1S1D',
283 'CR=2R1W': 'RM-1P-2S1D',
287 'LDST-2R-imm': 'LDSTRM-2P-2S',
288 'LDST-2R-1W-imm': 'LDSTRM-2P-2S1D',
289 'LDST-2R-1W': 'LDSTRM-2P-2S1D',
290 'LDST-2R-2W': 'LDSTRM-2P-2S1D',
291 'LDST-1R-1W-imm': 'LDSTRM-2P-1S1D',
292 'LDST-1R-2W-imm': 'LDSTRM-2P-1S2D',
293 'LDST-3R': 'LDSTRM-2P-3S',
294 'LDST-3R-CRo': 'LDSTRM-2P-3S', # st*x
295 'LDST-3R-1W': 'LDSTRM-2P-2S1D', # st*x
297 print("# map to old SV Prefix")
299 print('[[!table data="""')
300 for key
in primarykeys
:
301 name
= keyname(dictkeys
[key
])
302 value
= mapsto
.get(name
, "-")
303 print(tformat([name
, value
+ " "]))
309 print('[[!table data="""')
310 print(tformat(tablecols
) + " imms | name |")
312 # print out the keys and the table from which they're derived
313 for key
in primarykeys
:
314 name
= keyname(dictkeys
[key
])
315 row
= tformat(dictkeys
[key
].values())
316 imms
= list(immediates
.get(key
, ""))
318 row
+= " %s | " % ("/".join(imms
))
319 row
+= " %s |" % name
324 # print out, by remap name, all the instructions under that category
325 for key
in primarykeys
:
326 name
= keyname(dictkeys
[key
])
327 value
= mapsto
.get(name
, "-")
328 print("## %s (%s)" % (name
, value
))
330 print('[[!table data="""')
331 print(tformat(['CSV', 'opcode', 'asm', 'form']))
339 # for fname, csv in csvs.items():
342 # for insn, row in insns.items():
345 print("# svp64 remaps")
346 svp64
= OrderedDict()
347 # create a CSV file, per category, with SV "augmentation" info
348 # XXX note: 'out2' not added here, needs to be added to CSV files
349 # KEEP TRACK OF THESE https://bugs.libre-soc.org/show_bug.cgi?id=619
350 csvcols
= ['insn', 'CONDITIONS', 'Ptype', 'Etype', '0', '1', '2', '3']
351 csvcols
+= ['in1', 'in2', 'in3', 'out', 'CR in', 'CR out'] # temporary
352 for key
in primarykeys
:
353 # get the decoded key containing row-analysis, and name/value
356 value
= mapsto
.get(name
, "-")
357 if value
== 'non-SV':
360 # print out svp64 tables by category
361 print("* **%s**: %s" % (name
, value
))
363 # store csv entries by svp64 RM category
364 if value
not in svp64
:
371 # for idx in range(len(row)):
372 # if row[idx] == 'NONE':
374 # get the instruction
378 insn
= insns
[(insn_name
, condition
)]
379 # start constructing svp64 CSV row
381 res
['insn'] = insn_name
382 res
['CONDITIONS'] = condition
383 res
['Ptype'] = value
.split('-')[1] # predication type (RM-xN-xxx)
384 # get whether R_xxx_EXTRAn fields are 2-bit or 3-bit
385 res
['Etype'] = 'EXTRA2'
386 # go through each register matching to Rxxxx_EXTRAx
387 for k
in ['0', '1', '2', '3']:
389 # create "fake" out2 (TODO, needs to be added to CSV files)
390 # KEEP TRACK HERE https://bugs.libre-soc.org/show_bug.cgi?id=619
392 if insn
['upd'] == '1': # LD/ST with update has RA as out2
395 # temporary useful info
397 for k
in ['in1', 'in2', 'in3', 'out', 'CR in', 'CR out']:
398 if insn
[k
].startswith('CONST'):
403 if insn
[k
] == 'RA_OR_ZERO':
405 elif insn
[k
] != 'NONE':
410 print("regs", insn_name
, regs
)
412 # for LD/ST FP, use FRT/FRS not RT/RS, and use CR1 not CR0
413 if insn_name
.startswith("lf"):
419 if insn_name
.startswith("stf"):
426 # sigh now the fun begins. this isn't the sanest way to do it
427 # but the patterns are pretty regular.
429 if value
== 'LDSTRM-2P-1S1D':
430 res
['Etype'] = 'EXTRA3' # RM EXTRA3 type
431 res
['0'] = dRT
# RT: Rdest_EXTRA3
432 res
['1'] = 's:RA' # RA: Rsrc1_EXTRA3
434 elif value
== 'LDSTRM-2P-1S2D':
435 res
['Etype'] = 'EXTRA2' # RM EXTRA2 type
436 res
['0'] = dRT
# RT: Rdest_EXTRA3
437 res
['1'] = 'd:RA' # RA: Rdest2_EXTRA2
438 res
['2'] = 's:RA' # RA: Rsrc1_EXTRA2
440 elif value
== 'LDSTRM-2P-2S':
442 res
['Etype'] = 'EXTRA3' # RM EXTRA2 type
443 res
['0'] = sRS
# RS: Rdest1_EXTRA2
444 res
['1'] = 's:RA' # RA: Rsrc1_EXTRA2
446 elif value
== 'LDSTRM-2P-2S1D':
447 if 'st' in insn_name
and 'x' not in insn_name
: # stwu/stbu etc
448 res
['Etype'] = 'EXTRA2' # RM EXTRA2 type
449 res
['0'] = 'd:RA' # RA: Rdest1_EXTRA2
450 res
['1'] = sRS
# RS: Rdsrc1_EXTRA2
451 res
['2'] = 's:RA' # RA: Rsrc2_EXTRA2
452 elif 'st' in insn_name
and 'x' in insn_name
: # stwux
453 res
['Etype'] = 'EXTRA2' # RM EXTRA2 type
454 res
['0'] = 'd:RA' # RA: Rdest1_EXTRA2
455 # RS: Rdest2_EXTRA2, RA: Rsrc1_EXTRA2
456 res
['1'] = sRS
+'s:RA'
457 res
['2'] = 's:RB' # RB: Rsrc2_EXTRA2
458 elif 'u' in insn_name
: # ldux etc.
459 res
['Etype'] = 'EXTRA2' # RM EXTRA2 type
460 res
['0'] = dRT
# RT: Rdest1_EXTRA2
461 res
['1'] = 'd:RA' # RA: Rdest2_EXTRA2
462 res
['2'] = 's:RB' # RB: Rsrc1_EXTRA2
464 res
['Etype'] = 'EXTRA2' # RM EXTRA2 type
465 res
['0'] = dRT
# RT: Rdest1_EXTRA2
466 res
['1'] = 's:RA' # RA: Rsrc1_EXTRA2
467 res
['2'] = 's:RB' # RB: Rsrc2_EXTRA2
469 elif value
== 'LDSTRM-2P-3S':
470 res
['Etype'] = 'EXTRA2' # RM EXTRA2 type
471 if 'cx' in insn_name
:
472 res
['0'] = sRS
+dCR
# RS: Rsrc1_EXTRA2 CR0: dest
474 res
['0'] = sRS
# RS: Rsrc1_EXTRA2
475 res
['1'] = 's:RA' # RA: Rsrc2_EXTRA2
476 res
['2'] = 's:RB' # RA: Rsrc3_EXTRA2
478 elif value
== 'RM-2P-1S1D':
479 res
['Etype'] = 'EXTRA3' # RM EXTRA3 type
480 if insn_name
== 'mtspr':
481 res
['0'] = 'd:SPR' # SPR: Rdest1_EXTRA3
482 res
['1'] = 's:RS' # RS: Rsrc1_EXTRA3
483 elif insn_name
== 'mfspr':
484 res
['0'] = 'd:RS' # RS: Rdest1_EXTRA3
485 res
['1'] = 's:SPR' # SPR: Rsrc1_EXTRA3
486 elif name
== 'CRio' and insn_name
== 'mcrf':
487 res
['0'] = 'd:BF' # BFA: Rdest1_EXTRA3
488 res
['1'] = 's:BFA' # BFA: Rsrc1_EXTRA3
489 elif 'mfcr' in insn_name
or 'mfocrf' in insn_name
:
490 res
['0'] = 'd:RT' # RT: Rdest1_EXTRA3
491 res
['1'] = 's:CR' # CR: Rsrc1_EXTRA3
492 elif insn_name
== 'setb':
493 res
['0'] = 'd:RT' # RT: Rdest1_EXTRA3
494 res
['1'] = 's:BFA' # BFA: Rsrc1_EXTRA3
495 elif insn_name
.startswith('cmp'): # cmpi
496 res
['0'] = 'd:BF' # BF: Rdest1_EXTRA3
497 res
['1'] = 's:RA' # RA: Rsrc1_EXTRA3
498 elif regs
== ['RA', '', '', 'RT', '', '']:
499 res
['0'] = 'd:RT' # RT: Rdest1_EXTRA3
500 res
['1'] = 's:RA' # RA: Rsrc1_EXTRA3
501 elif regs
== ['RA', '', '', 'RT', '', 'CR0']:
502 res
['0'] = 'd:RT;d:CR0' # RT,CR0: Rdest1_EXTRA3
503 res
['1'] = 's:RA' # RA: Rsrc1_EXTRA3
504 elif (regs
== ['RS', '', '', 'RA', '', 'CR0'] or
505 regs
== ['', '', 'RS', 'RA', '', 'CR0']):
506 res
['0'] = 'd:RA;d:CR0' # RA,CR0: Rdest1_EXTRA3
507 res
['1'] = 's:RS' # RS: Rsrc1_EXTRA3
508 elif regs
== ['RS', '', '', 'RA', '', '']:
509 res
['0'] = 'd:RA' # RA: Rdest1_EXTRA3
510 res
['1'] = 's:RS' # RS: Rsrc1_EXTRA3
511 elif regs
== ['', 'FRB', '', 'FRT', '0', 'CR1']:
512 res
['0'] = 'd:FRT;d:CR1' # FRT,CR1: Rdest1_EXTRA3
513 res
['1'] = 's:FRA' # FRA: Rsrc1_EXTRA3
514 elif regs
== ['', 'FRB', '', '', '', 'CR1']:
515 res
['0'] = 'd:CR1' # CR1: Rdest1_EXTRA3
516 res
['1'] = 's:FRB' # FRA: Rsrc1_EXTRA3
517 elif regs
== ['', 'FRB', '', '', '', 'BF']:
518 res
['0'] = 'd:BF' # BF: Rdest1_EXTRA3
519 res
['1'] = 's:FRB' # FRA: Rsrc1_EXTRA3
520 elif regs
== ['', 'FRB', '', 'FRT', '', 'CR1']:
521 res
['0'] = 'd:FRT;d:CR1' # FRT,CR1: Rdest1_EXTRA3
522 res
['1'] = 's:FRB' # FRB: Rsrc1_EXTRA3
523 elif insn_name
.startswith('bc'):
524 res
['0'] = 'd:BI' # BI: Rdest1_EXTRA3
525 res
['1'] = 's:BI' # BI: Rsrc1_EXTRA3
529 elif value
== 'RM-1P-2S1D':
530 res
['Etype'] = 'EXTRA3' # RM EXTRA3 type
531 if insn_name
.startswith('cr'):
532 res
['0'] = 'd:BT' # BT: Rdest1_EXTRA3
533 res
['1'] = 's:BA' # BA: Rsrc1_EXTRA3
534 res
['2'] = 's:BB' # BB: Rsrc2_EXTRA3
535 elif regs
== ['FRA', '', 'FRC', 'FRT', '', 'CR1']:
536 res
['0'] = 'd:FRT;d:CR1' # FRT,CR1: Rdest1_EXTRA3
537 res
['1'] = 's:FRA' # FRA: Rsrc1_EXTRA3
538 res
['2'] = 's:FRC' # FRC: Rsrc1_EXTRA3
540 elif regs
== ['FRA', 'FRB', '', '', '', 'BF']:
541 res
['0'] = 'd:BF' # BF: Rdest1_EXTRA3
542 res
['1'] = 's:FRA' # FRA: Rsrc1_EXTRA3
543 res
['2'] = 's:FRB' # FRB: Rsrc1_EXTRA3
544 elif regs
== ['FRA', 'FRB', '', 'FRT', '', '']:
545 res
['0'] = 'd:FRT' # FRT: Rdest1_EXTRA3
546 res
['1'] = 's:FRA' # FRA: Rsrc1_EXTRA3
547 res
['2'] = 's:FRB' # FRB: Rsrc1_EXTRA3
548 elif regs
== ['FRA', 'FRB', '', 'FRT', '', 'CR1']:
549 res
['0'] = 'd:FRT;d:CR1' # FRT,CR1: Rdest1_EXTRA3
550 res
['1'] = 's:FRA' # FRA: Rsrc1_EXTRA3
551 res
['2'] = 's:FRB' # FRB: Rsrc1_EXTRA3
552 elif name
== '2R-1W' or insn_name
== 'cmpb': # cmpb
553 if insn_name
in ['bpermd', 'cmpb']:
554 res
['0'] = 'd:RA' # RA: Rdest1_EXTRA3
555 res
['1'] = 's:RS' # RS: Rsrc1_EXTRA3
557 res
['0'] = 'd:RT' # RT: Rdest1_EXTRA3
558 res
['1'] = 's:RA' # RA: Rsrc1_EXTRA3
559 res
['2'] = 's:RB' # RB: Rsrc1_EXTRA3
560 elif insn_name
.startswith('cmp'): # cmp
561 res
['0'] = 'd:BF' # BF: Rdest1_EXTRA3
562 res
['1'] = 's:RA' # RA: Rsrc1_EXTRA3
563 res
['2'] = 's:RB' # RB: Rsrc1_EXTRA3
564 elif (regs
== ['', 'RB', 'RS', 'RA', '', 'CR0'] or
565 regs
== ['RS', 'RB', '', 'RA', '', 'CR0']):
566 res
['0'] = 'd:RA;d:CR0' # RA,CR0: Rdest1_EXTRA3
567 res
['1'] = 's:RB' # RB: Rsrc1_EXTRA3
568 res
['2'] = 's:RS' # RS: Rsrc1_EXTRA3
569 elif regs
== ['RA', 'RB', '', 'RT', '', 'CR0']:
570 res
['0'] = 'd:RT;d:CR0' # RT,CR0: Rdest1_EXTRA3
571 res
['1'] = 's:RA' # RA: Rsrc1_EXTRA3
572 res
['2'] = 's:RB' # RB: Rsrc1_EXTRA3
573 elif regs
== ['RA', '', 'RS', 'RA', '', 'CR0']:
574 res
['0'] = 'd:RA;d:CR0' # RA,CR0: Rdest1_EXTRA3
575 res
['1'] = 's:RA' # RA: Rsrc1_EXTRA3
576 res
['2'] = 's:RS' # RS: Rsrc1_EXTRA3
580 elif value
== 'RM-2P-2S1D':
581 res
['Etype'] = 'EXTRA2' # RM EXTRA2 type
582 if insn_name
.startswith('mt'): # mtcrf
583 res
['0'] = 'd:CR' # CR: Rdest1_EXTRA2
584 res
['1'] = 's:RS' # RS: Rsrc1_EXTRA2
585 res
['2'] = 's:CR' # CR: Rsrc2_EXTRA2
589 elif value
== 'RM-1P-3S1D':
590 res
['Etype'] = 'EXTRA2' # RM EXTRA2 type
591 if regs
== ['RA', 'RB', 'RT', 'RT', '', 'CR0']:
592 res
['0'] = 'd:RT;d:CR0' # RT,CR0: Rdest1_EXTRA2
593 res
['1'] = 's:RA' # RA: Rsrc1_EXTRA2
594 res
['2'] = 's:RB' # RT: Rsrc2_EXTRA2
595 res
['3'] = 's:RT' # RT: Rsrc3_EXTRA2
596 elif insn_name
== 'isel':
597 res
['0'] = 'd:RT' # RT: Rdest1_EXTRA2
598 res
['1'] = 's:RA' # RA: Rsrc1_EXTRA2
599 res
['2'] = 's:RB' # RT: Rsrc2_EXTRA2
600 res
['3'] = 's:BC' # BC: Rsrc3_EXTRA2
602 res
['0'] = 'd:FRT;d:CR1' # FRT, CR1: Rdest1_EXTRA2
603 res
['1'] = 's:FRA' # FRA: Rsrc1_EXTRA2
604 res
['2'] = 's:FRB' # FRB: Rsrc2_EXTRA2
605 res
['3'] = 's:FRC' # FRC: Rsrc3_EXTRA2
607 elif value
== 'RM-1P-1D':
608 res
['Etype'] = 'EXTRA3' # RM EXTRA3 type
609 if insn_name
== 'svstep':
610 res
['0'] = 'd:RT;d:CR0' # RT,CR0: Rdest1_EXTRA2
613 # for k in ['in1', 'in2', 'in3', 'out', 'CR in', 'CR out']:
615 # if res['0'] != 'TODO':
617 if k
== 'CONDITIONS':
619 if res
[k
] == 'NONE' or res
[k
] == '':
621 svp64
[value
].append(res
)
622 # also add to by-CSV version
623 csv_fname
= insn_to_csv
[insn_name
]
624 csvs_svp64
[csv_fname
].append(res
)
628 # now write out the csv files
629 for value
, csv
in svp64
.items():
630 # print out svp64 tables by category
631 print("## %s" % value
)
633 print('[[!table format=csv file="openpower/isatables/%s.csv"]]' %
637 #csvcols = ['insn', 'Ptype', 'Etype', '0', '1', '2', '3']
638 write_csv("%s.csv" % value
, csv
, csvcols
+ ['out2'])
640 # okaaay, now we re-read them back in for producing microwatt SV
642 # get SVP64 augmented CSV files
643 svt
= SVP64RM(microwatt_format
=True)
644 # Expand that (all .csv files)
645 pth
= find_wiki_file("*.csv")
647 # Ignore those containing: valid test sprs
648 for fname
in glob(pth
):
649 print("post-checking", fname
)
650 _
, name
= os
.path
.split(fname
)
657 if fname
.endswith('sprs.csv'):
659 if fname
.endswith('minor_19_valid.csv'):
663 svp64_csv
= svt
.get_svp64_csv(fname
)
665 csvcols
= ['insn', 'Ptype', 'Etype']
666 csvcols
+= ['in1', 'in2', 'in3', 'out', 'out2', 'CR in', 'CR out']
668 if format
== Format
.VHDL
:
669 # and a nice microwatt VHDL file
670 file_path
= find_wiki_file("sv_decode.vhdl")
672 with
open(file_path
, 'w') as stream
:
673 output(format
, svt
, csvcols
, insns
, csvs_svp64
, stream
)
676 def output(format
, svt
, csvcols
, insns
, csvs_svp64
, stream
):
679 # autogeneration warning
680 stream
.write("-- this file is auto-generated, do not edit\n")
681 stream
.write("-- http://libre-soc.org/openpower/sv_analysis.py\n")
682 stream
.write("-- part of Libre-SOC, sponsored by NLnet\n")
685 # first create array types
697 for value
, csv
in csvs_svp64
.items():
699 value
= value
.lower()
700 value
= value
.replace("-", "_")
701 if value
not in lens
:
702 todo
= " -- TODO %s (or no SVP64 augmentation)\n"
703 stream
.write(todo
% value
)
706 typarray
= " type sv_%s_rom_array_t is " \
707 "array(0 to %d) of sv_decode_rom_t;\n"
708 stream
.write(typarray
% (value
, width
))
711 sv_cols
= ['sv_in1', 'sv_in2', 'sv_in3', 'sv_out', 'sv_out2',
712 'sv_cr_in', 'sv_cr_out']
713 fullcols
= csvcols
+ sv_cols
715 " constant sv_%s_decode_rom_array :\n" \
716 " sv_%s_rom_array_t := (\n" \
718 ftr
= " others => sv_illegal_inst\n" \
720 for value
, csv
in csvs_svp64
.items():
722 value
= value
.lower()
723 value
= value
.replace("-", "_")
724 if value
not in lens
:
726 stream
.write(hdr
% (value
, value
, " ".join(fullcols
)))
728 insn
= str(entry
['insn'])
729 condition
= str(entry
['CONDITIONS'])
730 sventry
= svt
.svp64_instrs
.get(insn
, None)
731 op
= insns
[(insn
, condition
)]['opcode']
732 # binary-to-vhdl-binary
733 if op
.startswith("0b"):
734 op
= "2#%s#" % op
[2:]
736 for colname
in csvcols
[1:]:
738 # zero replace with NONE
742 re
= re
.replace("1P", "P1")
743 re
= re
.replace("2P", "P2")
745 print("sventry", sventry
)
746 for colname
in sv_cols
:
750 re
= sventry
[colname
]
753 stream
.write(" %13s => (%s), -- %s\n" % (op
, row
, insn
))
757 if __name__
== '__main__':
758 parser
= argparse
.ArgumentParser()
759 parser
.add_argument("-f", "--format",
760 type=Format
, choices
=Format
, default
=Format
.VHDL
,
761 help="format to be used (VHDL)")
762 args
= parser
.parse_args()
763 process_csvs(args
.format
)