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