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