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