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
):
169 BINUTILS
= enum
.auto()
173 def _missing_(cls
, value
):
175 "binutils": Format
.BINUTILS
,
180 return self
.name
.lower()
182 def wrap_comment(self
, lines
):
183 def wrap_comment_binutils(lines
):
185 yield from map(lambda line
: f
" * {line}", lines
)
188 def wrap_comment_vhdl(lines
):
189 yield from map(lambda line
: f
"-- {line}", lines
)
192 Format
.BINUTILS
: wrap_comment_binutils
,
193 Format
.VHDL
: wrap_comment_vhdl
,
197 def process_csvs(format
):
202 dictkeys
= OrderedDict()
204 insns
= {} # dictionary of CSV row, by instruction
207 print("# OpenPOWER ISA register 'profile's")
209 print("this page is auto-generated, do not edit")
210 print("created by http://libre-soc.org/openpower/sv_analysis.py")
213 # Expand that (all .csv files)
214 pth
= find_wiki_file("*.csv")
216 # Ignore those containing: valid test sprs
217 for fname
in glob(pth
):
218 print("sv analysis checking", fname
)
219 _
, name
= os
.path
.split(fname
)
226 if fname
.endswith('sprs.csv'):
228 if fname
.endswith('minor_19_valid.csv'):
232 csvname
= os
.path
.split(fname
)[1]
233 csvname_
= csvname
.split(".")[0]
234 # csvname is something like: minor_59.csv, fname the whole path
237 csvs_svp64
[csvname_
] = []
242 insn_name
= row
['comment']
243 condition
= row
['CONDITIONS']
244 # skip instructions that are not suitable
245 if insn_name
.startswith("l") and insn_name
.endswith("br"):
246 continue # skip pseudo-alias lxxxbr
247 if insn_name
in ['mcrxr', 'mcrxrx', 'darn']:
249 if insn_name
in ['bctar', 'bcctr']:
251 if 'rfid' in insn_name
:
253 if insn_name
in ['setvl', ]: # SVP64 opcodes
256 insns
[(insn_name
, condition
)] = row
# accumulate csv data
257 insn_to_csv
[insn_name
] = csvname_
# CSV file name by instruction
258 dkey
= create_key(row
)
259 key
= tuple(dkey
.values())
265 bykey
[key
].append((csvname
, row
['opcode'], insn_name
, condition
,
266 row
['form'].upper() + '-Form'))
268 # detect immediates, collate them (useful info)
269 if row
['in2'].startswith('CONST_'):
270 imm
= row
['in2'].split("_")[1]
271 if key
not in immediates
:
272 immediates
[key
] = set()
273 immediates
[key
].add(imm
)
275 primarykeys
= list(primarykeys
)
278 # mapping to old SVPrefix "Forms"
279 mapsto
= {'3R-1W-CRo': 'RM-1P-3S1D',
280 '2R-1W-CRio': 'RM-1P-2S1D',
281 '2R-1W-CRi': 'RM-1P-3S1D',
282 '2R-1W-CRo': 'RM-1P-2S1D',
284 '2R-1W': 'RM-1P-2S1D',
285 '1R-CRio': 'RM-2P-2S1D',
286 '2R-CRio': 'RM-1P-2S1D',
287 '2R-CRo': 'RM-1P-2S1D',
289 '1R-1W-CRio': 'RM-2P-1S1D',
290 '1R-1W-CRo': 'RM-2P-1S1D',
291 '1R-1W': 'RM-2P-1S1D',
292 '1R-1W-imm': 'RM-2P-1S1D',
293 '1R-CRo': 'RM-2P-1S1D',
295 '1W-CRo': 'RM-1P-1D',
297 '1W-CRi': 'RM-2P-1S1D',
298 'CRio': 'RM-2P-1S1D',
299 'CR=2R1W': 'RM-1P-2S1D',
303 'LDST-2R-imm': 'LDSTRM-2P-2S',
304 'LDST-2R-1W-imm': 'LDSTRM-2P-2S1D',
305 'LDST-2R-1W': 'LDSTRM-2P-2S1D',
306 'LDST-2R-2W': 'LDSTRM-2P-2S1D',
307 'LDST-1R-1W-imm': 'LDSTRM-2P-1S1D',
308 'LDST-1R-2W-imm': 'LDSTRM-2P-1S2D',
309 'LDST-3R': 'LDSTRM-2P-3S',
310 'LDST-3R-CRo': 'LDSTRM-2P-3S', # st*x
311 'LDST-3R-1W': 'LDSTRM-2P-2S1D', # st*x
313 print("# map to old SV Prefix")
315 print('[[!table data="""')
316 for key
in primarykeys
:
317 name
= keyname(dictkeys
[key
])
318 value
= mapsto
.get(name
, "-")
319 print(tformat([name
, value
+ " "]))
325 print('[[!table data="""')
326 print(tformat(tablecols
) + " imms | name |")
328 # print out the keys and the table from which they're derived
329 for key
in primarykeys
:
330 name
= keyname(dictkeys
[key
])
331 row
= tformat(dictkeys
[key
].values())
332 imms
= list(immediates
.get(key
, ""))
334 row
+= " %s | " % ("/".join(imms
))
335 row
+= " %s |" % name
340 # print out, by remap name, all the instructions under that category
341 for key
in primarykeys
:
342 name
= keyname(dictkeys
[key
])
343 value
= mapsto
.get(name
, "-")
344 print("## %s (%s)" % (name
, value
))
346 print('[[!table data="""')
347 print(tformat(['CSV', 'opcode', 'asm', 'form']))
355 # for fname, csv in csvs.items():
358 # for insn, row in insns.items():
361 print("# svp64 remaps")
362 svp64
= OrderedDict()
363 # create a CSV file, per category, with SV "augmentation" info
364 # XXX note: 'out2' not added here, needs to be added to CSV files
365 # KEEP TRACK OF THESE https://bugs.libre-soc.org/show_bug.cgi?id=619
366 csvcols
= ['insn', 'CONDITIONS', 'Ptype', 'Etype', '0', '1', '2', '3']
367 csvcols
+= ['in1', 'in2', 'in3', 'out', 'CR in', 'CR out'] # temporary
368 for key
in primarykeys
:
369 # get the decoded key containing row-analysis, and name/value
372 value
= mapsto
.get(name
, "-")
373 if value
== 'non-SV':
376 # print out svp64 tables by category
377 print("* **%s**: %s" % (name
, value
))
379 # store csv entries by svp64 RM category
380 if value
not in svp64
:
387 # for idx in range(len(row)):
388 # if row[idx] == 'NONE':
390 # get the instruction
394 insn
= insns
[(insn_name
, condition
)]
395 # start constructing svp64 CSV row
397 res
['insn'] = insn_name
398 res
['CONDITIONS'] = condition
399 res
['Ptype'] = value
.split('-')[1] # predication type (RM-xN-xxx)
400 # get whether R_xxx_EXTRAn fields are 2-bit or 3-bit
401 res
['Etype'] = 'EXTRA2'
402 # go through each register matching to Rxxxx_EXTRAx
403 for k
in ['0', '1', '2', '3']:
405 # create "fake" out2 (TODO, needs to be added to CSV files)
406 # KEEP TRACK HERE https://bugs.libre-soc.org/show_bug.cgi?id=619
408 if insn
['upd'] == '1': # LD/ST with update has RA as out2
411 # temporary useful info
413 for k
in ['in1', 'in2', 'in3', 'out', 'CR in', 'CR out']:
414 if insn
[k
].startswith('CONST'):
419 if insn
[k
] == 'RA_OR_ZERO':
421 elif insn
[k
] != 'NONE':
426 print("regs", insn_name
, regs
)
428 # for LD/ST FP, use FRT/FRS not RT/RS, and use CR1 not CR0
429 if insn_name
.startswith("lf"):
435 if insn_name
.startswith("stf"):
442 # sigh now the fun begins. this isn't the sanest way to do it
443 # but the patterns are pretty regular.
445 if value
== 'LDSTRM-2P-1S1D':
446 res
['Etype'] = 'EXTRA3' # RM EXTRA3 type
447 res
['0'] = dRT
# RT: Rdest_EXTRA3
448 res
['1'] = 's:RA' # RA: Rsrc1_EXTRA3
450 elif value
== 'LDSTRM-2P-1S2D':
451 res
['Etype'] = 'EXTRA2' # RM EXTRA2 type
452 res
['0'] = dRT
# RT: Rdest_EXTRA3
453 res
['1'] = 'd:RA' # RA: Rdest2_EXTRA2
454 res
['2'] = 's:RA' # RA: Rsrc1_EXTRA2
456 elif value
== 'LDSTRM-2P-2S':
458 res
['Etype'] = 'EXTRA3' # RM EXTRA2 type
459 res
['0'] = sRS
# RS: Rdest1_EXTRA2
460 res
['1'] = 's:RA' # RA: Rsrc1_EXTRA2
462 elif value
== 'LDSTRM-2P-2S1D':
463 if 'st' in insn_name
and 'x' not in insn_name
: # stwu/stbu etc
464 res
['Etype'] = 'EXTRA2' # RM EXTRA2 type
465 res
['0'] = 'd:RA' # RA: Rdest1_EXTRA2
466 res
['1'] = sRS
# RS: Rdsrc1_EXTRA2
467 res
['2'] = 's:RA' # RA: Rsrc2_EXTRA2
468 elif 'st' in insn_name
and 'x' in insn_name
: # stwux
469 res
['Etype'] = 'EXTRA2' # RM EXTRA2 type
470 res
['0'] = 'd:RA' # RA: Rdest1_EXTRA2
471 # RS: Rdest2_EXTRA2, RA: Rsrc1_EXTRA2
472 res
['1'] = sRS
+'s:RA'
473 res
['2'] = 's:RB' # RB: Rsrc2_EXTRA2
474 elif 'u' in insn_name
: # ldux etc.
475 res
['Etype'] = 'EXTRA2' # RM EXTRA2 type
476 res
['0'] = dRT
# RT: Rdest1_EXTRA2
477 res
['1'] = 'd:RA' # RA: Rdest2_EXTRA2
478 res
['2'] = 's:RB' # RB: Rsrc1_EXTRA2
480 res
['Etype'] = 'EXTRA2' # RM EXTRA2 type
481 res
['0'] = dRT
# RT: Rdest1_EXTRA2
482 res
['1'] = 's:RA' # RA: Rsrc1_EXTRA2
483 res
['2'] = 's:RB' # RB: Rsrc2_EXTRA2
485 elif value
== 'LDSTRM-2P-3S':
486 res
['Etype'] = 'EXTRA2' # RM EXTRA2 type
487 if 'cx' in insn_name
:
488 res
['0'] = sRS
+dCR
# RS: Rsrc1_EXTRA2 CR0: dest
490 res
['0'] = sRS
# RS: Rsrc1_EXTRA2
491 res
['1'] = 's:RA' # RA: Rsrc2_EXTRA2
492 res
['2'] = 's:RB' # RA: Rsrc3_EXTRA2
494 elif value
== 'RM-2P-1S1D':
495 res
['Etype'] = 'EXTRA3' # RM EXTRA3 type
496 if insn_name
== 'mtspr':
497 res
['0'] = 'd:SPR' # SPR: Rdest1_EXTRA3
498 res
['1'] = 's:RS' # RS: Rsrc1_EXTRA3
499 elif insn_name
== 'mfspr':
500 res
['0'] = 'd:RS' # RS: Rdest1_EXTRA3
501 res
['1'] = 's:SPR' # SPR: Rsrc1_EXTRA3
502 elif name
== 'CRio' and insn_name
== 'mcrf':
503 res
['0'] = 'd:BF' # BFA: Rdest1_EXTRA3
504 res
['1'] = 's:BFA' # BFA: Rsrc1_EXTRA3
505 elif 'mfcr' in insn_name
or 'mfocrf' in insn_name
:
506 res
['0'] = 'd:RT' # RT: Rdest1_EXTRA3
507 res
['1'] = 's:CR' # CR: Rsrc1_EXTRA3
508 elif insn_name
== 'setb':
509 res
['0'] = 'd:RT' # RT: Rdest1_EXTRA3
510 res
['1'] = 's:BFA' # BFA: Rsrc1_EXTRA3
511 elif insn_name
.startswith('cmp'): # cmpi
512 res
['0'] = 'd:BF' # BF: Rdest1_EXTRA3
513 res
['1'] = 's:RA' # RA: Rsrc1_EXTRA3
514 elif regs
== ['RA', '', '', 'RT', '', '']:
515 res
['0'] = 'd:RT' # RT: Rdest1_EXTRA3
516 res
['1'] = 's:RA' # RA: Rsrc1_EXTRA3
517 elif regs
== ['RA', '', '', 'RT', '', 'CR0']:
518 res
['0'] = 'd:RT;d:CR0' # RT,CR0: Rdest1_EXTRA3
519 res
['1'] = 's:RA' # RA: Rsrc1_EXTRA3
520 elif (regs
== ['RS', '', '', 'RA', '', 'CR0'] or
521 regs
== ['', '', 'RS', 'RA', '', 'CR0']):
522 res
['0'] = 'd:RA;d:CR0' # RA,CR0: Rdest1_EXTRA3
523 res
['1'] = 's:RS' # RS: Rsrc1_EXTRA3
524 elif regs
== ['RS', '', '', 'RA', '', '']:
525 res
['0'] = 'd:RA' # RA: Rdest1_EXTRA3
526 res
['1'] = 's:RS' # RS: Rsrc1_EXTRA3
527 elif regs
== ['', 'FRB', '', 'FRT', '0', 'CR1']:
528 res
['0'] = 'd:FRT;d:CR1' # FRT,CR1: Rdest1_EXTRA3
529 res
['1'] = 's:FRA' # FRA: Rsrc1_EXTRA3
530 elif regs
== ['', 'FRB', '', '', '', 'CR1']:
531 res
['0'] = 'd:CR1' # CR1: Rdest1_EXTRA3
532 res
['1'] = 's:FRB' # FRA: Rsrc1_EXTRA3
533 elif regs
== ['', 'FRB', '', '', '', 'BF']:
534 res
['0'] = 'd:BF' # BF: Rdest1_EXTRA3
535 res
['1'] = 's:FRB' # FRA: Rsrc1_EXTRA3
536 elif regs
== ['', 'FRB', '', 'FRT', '', 'CR1']:
537 res
['0'] = 'd:FRT;d:CR1' # FRT,CR1: Rdest1_EXTRA3
538 res
['1'] = 's:FRB' # FRB: Rsrc1_EXTRA3
539 elif insn_name
.startswith('bc'):
540 res
['0'] = 'd:BI' # BI: Rdest1_EXTRA3
541 res
['1'] = 's:BI' # BI: Rsrc1_EXTRA3
545 elif value
== 'RM-1P-2S1D':
546 res
['Etype'] = 'EXTRA3' # RM EXTRA3 type
547 if insn_name
.startswith('cr'):
548 res
['0'] = 'd:BT' # BT: Rdest1_EXTRA3
549 res
['1'] = 's:BA' # BA: Rsrc1_EXTRA3
550 res
['2'] = 's:BB' # BB: Rsrc2_EXTRA3
551 elif regs
== ['FRA', '', 'FRC', 'FRT', '', 'CR1']:
552 res
['0'] = 'd:FRT;d:CR1' # FRT,CR1: Rdest1_EXTRA3
553 res
['1'] = 's:FRA' # FRA: Rsrc1_EXTRA3
554 res
['2'] = 's:FRC' # FRC: Rsrc1_EXTRA3
556 elif regs
== ['FRA', 'FRB', '', '', '', 'BF']:
557 res
['0'] = 'd:BF' # BF: Rdest1_EXTRA3
558 res
['1'] = 's:FRA' # FRA: Rsrc1_EXTRA3
559 res
['2'] = 's:FRB' # FRB: Rsrc1_EXTRA3
560 elif regs
== ['FRA', 'FRB', '', 'FRT', '', '']:
561 res
['0'] = 'd:FRT' # FRT: Rdest1_EXTRA3
562 res
['1'] = 's:FRA' # FRA: Rsrc1_EXTRA3
563 res
['2'] = 's:FRB' # FRB: Rsrc1_EXTRA3
564 elif regs
== ['FRA', 'FRB', '', 'FRT', '', 'CR1']:
565 res
['0'] = 'd:FRT;d:CR1' # FRT,CR1: Rdest1_EXTRA3
566 res
['1'] = 's:FRA' # FRA: Rsrc1_EXTRA3
567 res
['2'] = 's:FRB' # FRB: Rsrc1_EXTRA3
568 elif name
== '2R-1W' or insn_name
== 'cmpb': # cmpb
569 if insn_name
in ['bpermd', 'cmpb']:
570 res
['0'] = 'd:RA' # RA: Rdest1_EXTRA3
571 res
['1'] = 's:RS' # RS: Rsrc1_EXTRA3
573 res
['0'] = 'd:RT' # RT: Rdest1_EXTRA3
574 res
['1'] = 's:RA' # RA: Rsrc1_EXTRA3
575 res
['2'] = 's:RB' # RB: Rsrc1_EXTRA3
576 elif insn_name
.startswith('cmp'): # cmp
577 res
['0'] = 'd:BF' # BF: Rdest1_EXTRA3
578 res
['1'] = 's:RA' # RA: Rsrc1_EXTRA3
579 res
['2'] = 's:RB' # RB: Rsrc1_EXTRA3
580 elif (regs
== ['', 'RB', 'RS', 'RA', '', 'CR0'] or
581 regs
== ['RS', 'RB', '', 'RA', '', 'CR0']):
582 res
['0'] = 'd:RA;d:CR0' # RA,CR0: Rdest1_EXTRA3
583 res
['1'] = 's:RB' # RB: Rsrc1_EXTRA3
584 res
['2'] = 's:RS' # RS: Rsrc1_EXTRA3
585 elif regs
== ['RA', 'RB', '', 'RT', '', 'CR0']:
586 res
['0'] = 'd:RT;d:CR0' # RT,CR0: Rdest1_EXTRA3
587 res
['1'] = 's:RA' # RA: Rsrc1_EXTRA3
588 res
['2'] = 's:RB' # RB: Rsrc1_EXTRA3
589 elif regs
== ['RA', '', 'RS', 'RA', '', 'CR0']:
590 res
['0'] = 'd:RA;d:CR0' # RA,CR0: Rdest1_EXTRA3
591 res
['1'] = 's:RA' # RA: Rsrc1_EXTRA3
592 res
['2'] = 's:RS' # RS: Rsrc1_EXTRA3
596 elif value
== 'RM-2P-2S1D':
597 res
['Etype'] = 'EXTRA2' # RM EXTRA2 type
598 if insn_name
.startswith('mt'): # mtcrf
599 res
['0'] = 'd:CR' # CR: Rdest1_EXTRA2
600 res
['1'] = 's:RS' # RS: Rsrc1_EXTRA2
601 res
['2'] = 's:CR' # CR: Rsrc2_EXTRA2
605 elif value
== 'RM-1P-3S1D':
606 res
['Etype'] = 'EXTRA2' # RM EXTRA2 type
607 if regs
== ['RA', 'RB', 'RT', 'RT', '', 'CR0']:
608 res
['0'] = 'd:RT;d:CR0' # RT,CR0: Rdest1_EXTRA2
609 res
['1'] = 's:RA' # RA: Rsrc1_EXTRA2
610 res
['2'] = 's:RB' # RT: Rsrc2_EXTRA2
611 res
['3'] = 's:RT' # RT: Rsrc3_EXTRA2
612 elif insn_name
== 'isel':
613 res
['0'] = 'd:RT' # RT: Rdest1_EXTRA2
614 res
['1'] = 's:RA' # RA: Rsrc1_EXTRA2
615 res
['2'] = 's:RB' # RT: Rsrc2_EXTRA2
616 res
['3'] = 's:BC' # BC: Rsrc3_EXTRA2
618 res
['0'] = 'd:FRT;d:CR1' # FRT, CR1: Rdest1_EXTRA2
619 res
['1'] = 's:FRA' # FRA: Rsrc1_EXTRA2
620 res
['2'] = 's:FRB' # FRB: Rsrc2_EXTRA2
621 res
['3'] = 's:FRC' # FRC: Rsrc3_EXTRA2
623 elif value
== 'RM-1P-1D':
624 res
['Etype'] = 'EXTRA3' # RM EXTRA3 type
625 if insn_name
== 'svstep':
626 res
['0'] = 'd:RT;d:CR0' # RT,CR0: Rdest1_EXTRA2
629 # for k in ['in1', 'in2', 'in3', 'out', 'CR in', 'CR out']:
631 # if res['0'] != 'TODO':
633 if k
== 'CONDITIONS':
635 if res
[k
] == 'NONE' or res
[k
] == '':
637 svp64
[value
].append(res
)
638 # also add to by-CSV version
639 csv_fname
= insn_to_csv
[insn_name
]
640 csvs_svp64
[csv_fname
].append(res
)
644 # now write out the csv files
645 for value
, csv
in svp64
.items():
646 # print out svp64 tables by category
647 print("## %s" % value
)
649 print('[[!table format=csv file="openpower/isatables/%s.csv"]]' %
653 #csvcols = ['insn', 'Ptype', 'Etype', '0', '1', '2', '3']
654 write_csv("%s.csv" % value
, csv
, csvcols
+ ['out2'])
656 # okaaay, now we re-read them back in for producing microwatt SV
658 # get SVP64 augmented CSV files
659 svt
= SVP64RM(microwatt_format
=True)
660 # Expand that (all .csv files)
661 pth
= find_wiki_file("*.csv")
663 # Ignore those containing: valid test sprs
664 for fname
in glob(pth
):
665 print("post-checking", fname
)
666 _
, name
= os
.path
.split(fname
)
673 if fname
.endswith('sprs.csv'):
675 if fname
.endswith('minor_19_valid.csv'):
679 svp64_csv
= svt
.get_svp64_csv(fname
)
681 csvcols
= ['insn', 'Ptype', 'Etype']
682 csvcols
+= ['in1', 'in2', 'in3', 'out', 'out2', 'CR in', 'CR out']
684 if format
== Format
.VHDL
:
685 # and a nice microwatt VHDL file
686 file_path
= find_wiki_file("sv_decode.vhdl")
687 elif format
== Format
.BINUTILS
:
688 file_path
= find_wiki_file("binutils.c")
690 with
open(file_path
, 'w') as stream
:
691 output(format
, svt
, csvcols
, insns
, csvs_svp64
, stream
)
694 def output_autogen_disclaimer(format
, stream
):
696 "this file is auto-generated, do not edit",
697 "http://libre-soc.org/openpower/sv_analysis.py",
698 "part of Libre-SOC, sponsored by NLnet",
700 for line
in format
.wrap_comment(lines
):
706 def output(format
, svt
, csvcols
, insns
, csvs_svp64
, stream
):
707 output_autogen_disclaimer(format
, stream
)
709 if format
== Format
.BINUTILS
:
710 stream
.write("/* TODO: implement proper support */\n")
713 # first create array types
725 for value
, csv
in csvs_svp64
.items():
727 value
= value
.lower()
728 value
= value
.replace("-", "_")
729 if value
not in lens
:
730 todo
= " -- TODO %s (or no SVP64 augmentation)\n"
731 stream
.write(todo
% value
)
734 typarray
= " type sv_%s_rom_array_t is " \
735 "array(0 to %d) of sv_decode_rom_t;\n"
736 stream
.write(typarray
% (value
, width
))
739 sv_cols
= ['sv_in1', 'sv_in2', 'sv_in3', 'sv_out', 'sv_out2',
740 'sv_cr_in', 'sv_cr_out']
741 fullcols
= csvcols
+ sv_cols
743 " constant sv_%s_decode_rom_array :\n" \
744 " sv_%s_rom_array_t := (\n" \
746 ftr
= " others => sv_illegal_inst\n" \
748 for value
, csv
in csvs_svp64
.items():
750 value
= value
.lower()
751 value
= value
.replace("-", "_")
752 if value
not in lens
:
754 stream
.write(hdr
% (value
, value
, " ".join(fullcols
)))
756 insn
= str(entry
['insn'])
757 condition
= str(entry
['CONDITIONS'])
758 sventry
= svt
.svp64_instrs
.get(insn
, None)
759 op
= insns
[(insn
, condition
)]['opcode']
760 # binary-to-vhdl-binary
761 if op
.startswith("0b"):
762 op
= "2#%s#" % op
[2:]
764 for colname
in csvcols
[1:]:
766 # zero replace with NONE
770 re
= re
.replace("1P", "P1")
771 re
= re
.replace("2P", "P2")
773 print("sventry", sventry
)
774 for colname
in sv_cols
:
778 re
= sventry
[colname
]
781 stream
.write(" %13s => (%s), -- %s\n" % (op
, row
, insn
))
785 if __name__
== '__main__':
786 parser
= argparse
.ArgumentParser()
787 parser
.add_argument("-f", "--format",
788 type=Format
, choices
=Format
, default
=Format
.VHDL
,
789 help="format to be used (binutils or VHDL)")
790 args
= parser
.parse_args()
791 process_csvs(args
.format
)