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