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