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