5b9c888a25f9e8a1d888f856a11d6e94eae8c9df
[openpower-isa.git] / src / openpower / decoder / power_enums.py
1 # SPDX-License-Identifier: LGPL-3-or-later
2 # Copyright (C) 2020, 2021 Luke Kenneth Casson Leighton <lkcl@lkcl.net>
3 # Copyright (C) 2020, Michael Nolan
4
5 """Enums used in OpenPOWER ISA decoding
6
7 Note: for SV, from v3.1B p12:
8
9 The designated SPR sandbox consists of non-privileged SPRs 704-719 and
10 privileged SPRs 720-735.
11
12 Note: the option exists to select a much shorter list of SPRs, to reduce
13 regfile size in HDL. this is SPRreduced and the supported list is in
14 get_spr_enum
15 """
16
17 from enum import Enum, unique
18 import csv
19 import os
20 from os.path import dirname, join
21 from collections import namedtuple
22
23
24 def find_wiki_dir():
25 filedir = os.path.dirname(os.path.abspath(__file__))
26 basedir = dirname(dirname(dirname(filedir)))
27 tabledir = join(basedir, 'openpower')
28 isatables = join(tabledir, 'isatables')
29 #print ("find_wiki_dir", isatables)
30 return isatables
31
32
33 def find_wiki_file(name):
34 return join(find_wiki_dir(), name)
35
36
37 def get_csv(name):
38 """gets a not-entirely-csv-file-formatted database, which allows comments
39 """
40 file_path = find_wiki_file(name)
41 with open(file_path, 'r') as csvfile:
42 csvfile = filter(lambda row: row[0] !='#', csvfile) # strip "#..."
43 reader = csv.DictReader(csvfile)
44 return list(reader)
45
46
47 # names of the fields in the tables that don't correspond to an enum
48 single_bit_flags = ['inv A', 'inv out',
49 'cry out', 'BR', 'sgn ext', 'rsrv', '32b',
50 'sgn', 'lk', 'sgl pipe']
51
52 # default values for fields in the table
53 default_values = {'unit': "NONE", 'internal op': "OP_ILLEGAL",
54 'in1': "RA", 'in2': 'NONE', 'in3': 'NONE', 'out': 'NONE',
55 'CR in': 'NONE',
56 'ldst len': 'NONE',
57 'upd': '0',
58 'rc': 'NONE', 'cry in': 'ZERO', 'form': 'NONE'}
59
60
61 def get_signal_name(name):
62 if name[0].isdigit():
63 name = "is_" + name
64 return name.lower().replace(' ', '_')
65
66 # this corresponds to which Function Unit (pipeline-with-Reservation-Stations)
67 # is to process and guard the operation. they are roughly divided by having
68 # the same register input/output signature (X-Form, etc.)
69
70
71 @unique
72 class Function(Enum):
73 NONE = 0
74 ALU = 1 << 1
75 LDST = 1 << 2
76 SHIFT_ROT = 1 << 3
77 LOGICAL = 1 << 4
78 BRANCH = 1 << 5
79 CR = 1 << 6
80 TRAP = 1 << 7
81 MUL = 1 << 8
82 DIV = 1 << 9
83 SPR = 1 << 10
84 MMU = 1 << 11
85 SV = 1 << 12 # Simple-V https://libre-soc.org/openpower/sv
86 VL = 1 << 13 # setvl
87 FPU = 1 << 14 # FPU
88
89
90 @unique
91 class Form(Enum):
92 NONE = 0
93 I = 1
94 B = 2
95 SC = 3
96 D = 4
97 DS = 5
98 DQ = 6
99 DX = 7
100 X = 8
101 XL = 9
102 XFX = 10
103 XFL = 11
104 XX1 = 12
105 XX2 = 13
106 XX3 = 14
107 XX4 = 15
108 XS = 16
109 XO = 17
110 A = 18
111 M = 19
112 MD = 20
113 MDS = 21
114 VA = 22
115 VC = 23
116 VX = 24
117 EVX = 25
118 EVS = 26
119 Z22 = 27
120 Z23 = 28
121 SVL = 29 # Simple-V for setvl instruction
122 SVD = 30 # Simple-V for LD/ST bit-reverse, variant of D-Form
123 SVDS = 31 # Simple-V for LD/ST bit-reverse, variant of DS-Form
124 SVM = 32 # Simple-V SHAPE mode - TEMPORARY TEMPORARY TEMPORARY
125 SVRM = 33 # Simple-V REMAP mode - TEMPORARY TEMPORARY TEMPORARY
126 TLI = 34 # ternlogi
127 XB = 35
128
129 # Simple-V svp64 fields https://libre-soc.org/openpower/sv/svp64/
130
131
132 @unique
133 class SVPtype(Enum):
134 NONE = 0
135 P1 = 1
136 P2 = 2
137
138
139 @unique
140 class SVEtype(Enum):
141 NONE = 0
142 EXTRA2 = 1
143 EXTRA3 = 2
144
145
146 @unique
147 class SVEXTRA(Enum):
148 NONE = 0
149 Idx0 = 1
150 Idx1 = 2
151 Idx2 = 3
152 Idx3 = 4
153 Idx_1_2 = 5 # due to weird BA/BB for crops
154
155
156 @unique
157 class SVP64PredMode(Enum):
158 ALWAYS = 0
159 INT = 1
160 CR = 2
161
162
163 @unique
164 class SVP64PredInt(Enum):
165 ALWAYS = 0
166 R3_UNARY = 1
167 R3 = 2
168 R3_N = 3
169 R10 = 4
170 R10_N = 5
171 R30 = 6
172 R30_N = 7
173
174
175 @unique
176 class SVP64PredCR(Enum):
177 LT = 0
178 GE = 1
179 GT = 2
180 LE = 3
181 EQ = 4
182 NE = 5
183 SO = 6
184 NS = 7
185
186
187 @unique
188 class SVP64RMMode(Enum):
189 NORMAL = 0
190 MAPREDUCE = 1
191 FFIRST = 2
192 SATURATE = 3
193 PREDRES = 4
194 BRANCH = 5
195
196
197 @unique
198 class SVP64BCPredMode(Enum):
199 NONE = 0
200 MASKZERO = 1
201 MASKONE = 2
202
203
204 @unique
205 class SVP64BCVLSETMode(Enum):
206 NONE = 0
207 VL_INCL = 1
208 VL_EXCL = 2
209
210
211 # note that these are chosen to be exactly the same as
212 # SVP64 RM bit 4. ALL=1 => bit4=1
213 @unique
214 class SVP64BCGate(Enum):
215 ANY = 0
216 ALL = 1
217
218
219 class SVP64BCCTRMode(Enum):
220 NONE = 0
221 TEST = 1
222 TEST_INV = 2
223
224
225 @unique
226 class SVP64width(Enum):
227 DEFAULT = 0
228 EW_32 = 1
229 EW_16 = 2
230 EW_8 = 3
231
232
233 @unique
234 class SVP64subvl(Enum):
235 VEC1 = 0
236 VEC2 = 1
237 VEC3 = 2
238 VEC4 = 3
239
240
241 @unique
242 class SVP64sat(Enum):
243 NONE = 0
244 SIGNED = 1
245 UNSIGNED = 2
246
247
248 @unique
249 class SVP64LDSTmode(Enum):
250 NONE = 0
251 INDEXED = 1
252 ELSTRIDE = 2
253 UNITSTRIDE = 3
254 SHIFT = 4
255
256
257 # supported instructions: make sure to keep up-to-date with CSV files
258 # just like everything else
259 _insns = [
260 "NONE", "add", "addc", "addco", "adde", "addeo",
261 "addi", "addic", "addic.", "addis",
262 "addme", "addmeo", "addo", "addze", "addzeo",
263 "addg6s",
264 "and", "andc", "andi.", "andis.",
265 "attn",
266 "absdu", "absds", # AV bitmanip
267 "absdacs", "absdacu", # AV bitmanip
268 "avgadd", # AV bitmanip
269 "b", "bc", "bcctr", "bclr", "bctar",
270 "bpermd",
271 "cbcdtd",
272 "cdtbcd",
273 "cmp", "cmpb", "cmpeqb", "cmpi", "cmpl", "cmpli", "cmprb",
274 "cntlzd", "cntlzw", "cnttzd", "cnttzw",
275 "cprop", # AV bitmanip
276 "crand", "crandc", "creqv",
277 "crnand", "crnor", "cror", "crorc", "crxor",
278 "darn",
279 "dcbf", "dcbst", "dcbt", "dcbtst", "dcbz",
280 "divd", "divde", "divdeo", "divdeu",
281 "divdeuo", "divdo", "divdu", "divduo", "divw", "divwe", "divweo",
282 "divweu", "divweuo", "divwo", "divwu", "divwuo",
283 "eieio", "eqv",
284 "extsb", "extsh", "extsw", "extswsli",
285 "fadd", "fadds", "fsub", "fsubs", # FP add / sub
286 "fcfids", "fcfidus", "fsqrts", "fres", "frsqrtes", # FP stuff
287 "fdmadds", # DCT FP 3-arg
288 "fmsubs", "fmadds", "fnmsubs", "fnmadds", # FP 3-arg
289 "ffadds", "ffsubs", "ffmuls", "ffdivs", # FFT FP 2-arg
290 "ffmsubs", "ffmadds", "ffnmsubs", "ffnmadds", # FFT FP 3-arg
291 "fmul", "fmuls", "fdiv", "fdivs", # FP mul / div
292 "fmr", "fabs", "fnabs", "fneg", "fcpsgn", # FP move/abs/neg
293 "fsins", "fcoss", # FP SIN/COS
294 'grev', 'grev.', 'grevi', 'grevi.',
295 'grevw', 'grevw.', 'grevwi', 'grevwi.',
296 "hrfid", "icbi", "icbt", "isel", "isync",
297 "lbarx", "lbz", "lbzcix", "lbzu", "lbzux", "lbzx", # load byte
298 "ld", "ldarx", "ldbrx", "ldu", "ldux", "ldx", # load double
299 # "lbzbr", "lbzubr", # load byte SVP64 bit-reversed
300 # "ldbr", "ldubr", # load double SVP64 bit-reversed
301 "lfs", "lfsx", "lfsu", "lfsux", # FP load single
302 "lfd", "lfdx", "lfdu", "lfdux", "lfiwzx", "lfiwax", # FP load double
303 "lha", "lharx", "lhau", "lhaux", "lhax", # load half
304 "lhbrx", "lhz", "lhzu", "lhzux", "lhzx", # more load half
305 # "lhabr", "lhaubr", # load half SVP64 bit-reversed
306 # "lhzbr", "lhzubr", # more load half SVP64 bit-reversed
307 "lwa", "lwarx", "lwaux", "lwax", "lwbrx", # load word
308 "lwz", "lwzcix", "lwzu", "lwzux", "lwzx", # more load word
309 # "lwabr", # load word SVP64 bit-reversed
310 # "lwzbr", "lwzubr", # more load word SVP64 bit-reversed
311 "maddhd", "maddhdu", "maddld", # INT multiply-and-add
312 "mcrf", "mcrxr", "mcrxrx", "mfcr/mfocrf", # CR mvs
313 "mfmsr", "mfspr",
314 "mins", "maxs", "minu", "maxu", # AV bitmanip
315 "modsd", "modsw", "modud", "moduw",
316 "mtcrf/mtocrf", "mtmsr", "mtmsrd", "mtspr",
317 "mulhd", "mulhdu", "mulhw", "mulhwu", "mulld", "mulldo",
318 "mulli", "mullw", "mullwo",
319 "nand", "neg", "nego",
320 "nop",
321 "nor", "or", "orc", "ori", "oris",
322 "popcntb", "popcntd", "popcntw",
323 "prtyd", "prtyw",
324 "rfid",
325 "rldcl", "rldcr", "rldic", "rldicl", "rldicr", "rldimi",
326 "rlwimi", "rlwinm", "rlwnm",
327 "setb",
328 "setvl", # https://libre-soc.org/openpower/sv/setvl
329 "svremap", # https://libre-soc.org/openpower/sv/remap - TEMPORARY
330 "svshape", # https://libre-soc.org/openpower/sv/remap
331 "svstep", # https://libre-soc.org/openpower/sv/setvl
332 "sim_cfg",
333 "slbia", "sld", "slw", "srad", "sradi",
334 "sraw", "srawi", "srd", "srw",
335 "stb", "stbcix", "stbcx", "stbu", "stbux", "stbx",
336 "std", "stdbrx", "stdcx", "stdu", "stdux", "stdx",
337 "stfs", "stfsx", "stfsu", "stfux", "stfsux", # FP store single
338 "stfd", "stfdx", "stfdu", "stfdux", "stfiwx", # FP store double
339 "sth", "sthbrx", "sthcx", "sthu", "sthux", "sthx",
340 "stw", "stwbrx", "stwcx", "stwu", "stwux", "stwx",
341 "subf", "subfc", "subfco", "subfe", "subfeo", "subfic",
342 "subfme", "subfmeo", "subfo", "subfze", "subfzeo",
343 "sync",
344 "ternlogi",
345 "td", "tdi",
346 "tlbie", "tlbiel", "tlbsync",
347 "tw", "twi",
348 "wait",
349 "xor", "xori", "xoris",
350 ]
351
352 # two-way lookup of instruction-to-index and vice-versa
353 insns = {}
354 asmidx = {}
355 for i, insn in enumerate(_insns):
356 insns[i] = insn
357 asmidx[insn] = i
358
359 # must be long enough to cover all instructions
360 asmlen = len(_insns).bit_length()
361
362 # Internal Operation numbering. Add new opcodes here (FPADD, FPMUL etc.)
363
364
365 @unique
366 class MicrOp(Enum):
367 OP_ILLEGAL = 0 # important that this is zero (see power_decoder.py)
368 OP_NOP = 1
369 OP_ADD = 2
370 OP_ADDPCIS = 3
371 OP_AND = 4
372 OP_ATTN = 5
373 OP_B = 6
374 OP_BC = 7
375 OP_BCREG = 8
376 OP_BPERM = 9
377 OP_CMP = 10
378 OP_CMPB = 11
379 OP_CMPEQB = 12
380 OP_CMPRB = 13
381 OP_CNTZ = 14
382 OP_CRAND = 15
383 OP_CRANDC = 16
384 OP_CREQV = 17
385 OP_CRNAND = 18
386 OP_CRNOR = 19
387 OP_CROR = 20
388 OP_CRORC = 21
389 OP_CRXOR = 22
390 OP_DARN = 23
391 OP_DCBF = 24
392 OP_DCBST = 25
393 OP_DCBT = 26
394 OP_DCBTST = 27
395 OP_DCBZ = 28
396 OP_DIV = 29
397 OP_DIVE = 30
398 OP_EXTS = 31
399 OP_EXTSWSLI = 32
400 OP_ICBI = 33
401 OP_ICBT = 34
402 OP_ISEL = 35
403 OP_ISYNC = 36
404 OP_LOAD = 37
405 OP_STORE = 38
406 OP_MADDHD = 39
407 OP_MADDHDU = 40
408 OP_MADDLD = 41
409 OP_MCRF = 42
410 OP_MCRXR = 43
411 OP_MCRXRX = 44
412 OP_MFCR = 45
413 OP_MFSPR = 46
414 OP_MOD = 47
415 OP_MTCRF = 48
416 OP_MTSPR = 49
417 OP_MUL_L64 = 50
418 OP_MUL_H64 = 51
419 OP_MUL_H32 = 52
420 OP_OR = 53
421 OP_POPCNT = 54
422 OP_PRTY = 55
423 OP_RLC = 56
424 OP_RLCL = 57
425 OP_RLCR = 58
426 OP_SETB = 59
427 OP_SHL = 60
428 OP_SHR = 61
429 OP_SYNC = 62
430 OP_TRAP = 63
431 OP_XOR = 67
432 OP_SIM_CONFIG = 68
433 OP_CROP = 69
434 OP_RFID = 70
435 OP_MFMSR = 71
436 OP_MTMSRD = 72
437 OP_SC = 73
438 OP_MTMSR = 74
439 OP_TLBIE = 75
440 OP_SETVL = 76
441 OP_FPOP = 77 # temporary: replace with actual ops
442 OP_FPOP_I = 78 # temporary: replace with actual ops
443 OP_FP_MADD = 79
444 OP_SVREMAP = 80
445 OP_SVSHAPE = 81
446 OP_SVSTEP = 82
447 OP_ADDG6S = 83
448 OP_CDTBCD = 84
449 OP_CBCDTD = 85
450 OP_TERNLOG = 86
451 OP_FETCH_FAILED = 87
452 OP_GREV = 88
453 OP_MINMAX = 89
454 OP_AVGADD = 90
455 OP_ABSDIFF = 91
456 OP_ABSADD = 92
457 OP_CPROP = 93
458
459
460 @unique
461 class In1Sel(Enum):
462 NONE = 0
463 RA = 1
464 RA_OR_ZERO = 2
465 SPR = 3
466 RS = 4 # for some ALU/Logical operations
467 FRA = 5
468 FRS = 6
469
470
471 @unique
472 class In2Sel(Enum):
473 NONE = 0
474 RB = 1
475 CONST_UI = 2
476 CONST_SI = 3
477 CONST_UI_HI = 4
478 CONST_SI_HI = 5
479 CONST_LI = 6
480 CONST_BD = 7
481 CONST_DS = 8
482 CONST_M1 = 9
483 CONST_SH = 10
484 CONST_SH32 = 11
485 SPR = 12
486 RS = 13 # for shiftrot (M-Form)
487 FRB = 14
488 CONST_SVD = 15 # for SVD-Form
489 CONST_SVDS = 16 # for SVDS-Form
490 CONST_XBI = 17
491
492
493 @unique
494 class In3Sel(Enum):
495 NONE = 0
496 RS = 1
497 RB = 2 # for shiftrot (M-Form)
498 FRS = 3
499 FRC = 4
500 RC = 5 # for SVP64 bit-reverse LD/ST
501 RT = 6 # for ternlog[i]
502
503
504 @unique
505 class OutSel(Enum):
506 NONE = 0
507 RT = 1
508 RA = 2
509 SPR = 3
510 RT_OR_ZERO = 4
511 FRT = 5
512 FRS = 6
513
514
515 @unique
516 class LdstLen(Enum):
517 NONE = 0
518 is1B = 1
519 is2B = 2
520 is4B = 4
521 is8B = 8
522
523
524 @unique
525 class LDSTMode(Enum):
526 NONE = 0
527 update = 1
528 cix = 2
529 cx = 3
530
531
532 @unique
533 class RC(Enum):
534 NONE = 0
535 ONE = 1
536 RC = 2
537
538
539 @unique
540 class CryIn(Enum):
541 ZERO = 0
542 ONE = 1
543 CA = 2
544 # TODO OV = 3
545
546
547 @unique
548 class CRInSel(Enum):
549 NONE = 0
550 CR0 = 1
551 BI = 2
552 BFA = 3
553 BA_BB = 4
554 BC = 5
555 WHOLE_REG = 6
556 CR1 = 7
557
558
559 @unique
560 class CROutSel(Enum):
561 NONE = 0
562 CR0 = 1
563 BF = 2
564 BT = 3
565 WHOLE_REG = 4
566 CR1 = 5
567
568
569 # SPRs - Special-Purpose Registers. See V3.0B Figure 18 p971 and
570 # http://libre-riscv.org/openpower/isatables/sprs.csv
571 # http://bugs.libre-riscv.org/show_bug.cgi?id=261
572 # http://bugs.libre-riscv.org/show_bug.cgi?id=859 - KAIVB
573
574 def get_spr_enum(full_file):
575 """get_spr_enum - creates an Enum of SPRs, dynamically
576 has the option to reduce the enum to a much shorter list.
577 this saves drastically on the size of the regfile
578 """
579 short_list = {'PIDR', 'DAR', 'PRTBL', 'DSISR', 'SVSRR0', 'SVSTATE',
580 'SVSTATE0', 'SVSTATE1', 'SVSTATE2', 'SVSTATE3',
581 'SPRG0_priv', 'SPRG1_priv', 'SPRG2_priv', 'SPRG3_priv',
582 'SPRG0', 'SPRG1', 'SPRG2', 'SPRG3', 'KAIVB',
583 # hmmm should not be including these, they are FAST regs
584 'CTR', 'LR', 'TAR', 'SRR0', 'SRR1', 'XER', 'DEC', 'TB', 'TBU',
585 'HSRR0', 'HSRR1', 'HSPRG0', 'HSPRG1',
586 }
587 spr_csv = []
588 for row in get_csv("sprs.csv"):
589 if full_file or row['SPR'] in short_list:
590 spr_csv.append(row)
591
592 spr_info = namedtuple('spr_info', 'SPR priv_mtspr priv_mfspr length idx')
593 spr_dict = {}
594 spr_byname = {}
595 for row in spr_csv:
596 info = spr_info(SPR=row['SPR'], priv_mtspr=row['priv_mtspr'],
597 priv_mfspr=row['priv_mfspr'], length=int(row['len']),
598 idx=int(row['Idx']))
599 spr_dict[int(row['Idx'])] = info
600 spr_byname[row['SPR']] = info
601 fields = [(row['SPR'], int(row['Idx'])) for row in spr_csv]
602 SPR = Enum('SPR', fields)
603 return SPR, spr_dict, spr_byname
604
605
606 SPRfull, spr_dict, spr_byname = get_spr_enum(full_file=True)
607 SPRreduced, _, _ = get_spr_enum(full_file=False)
608
609 XER_bits = {
610 'SO': 32,
611 'OV': 33,
612 'CA': 34,
613 'OV32': 44,
614 'CA32': 45
615 }
616
617 MSRSpec = namedtuple("MSRSpec", ["dr", "pr", "sf"])
618
619 if __name__ == '__main__':
620 # find out what the heck is in SPR enum :)
621 print("sprs full", len(SPRfull))
622 print(dir(SPRfull))
623 print("sprs reduced", len(SPRreduced))
624 print(dir(SPRreduced))
625 print(dir(Enum))
626 print(SPRfull.__members__['TAR'])
627 for x in SPRfull:
628 print("full", x, x.value, str(x), x.name)
629 for x in SPRreduced:
630 print("reduced", x, x.value, str(x), x.name)
631
632 print("function", Function.ALU.name)