48e437ba88d0fce30d2c4365eeeddb09ae48b5a5
[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 "sim_cfg",
283 "slbia", "sld", "slw", "srad", "sradi",
284 "sraw", "srawi", "srd", "srw",
285 "stb", "stbcix", "stbcx", "stbu", "stbux", "stbx",
286 "std", "stdbrx", "stdcx", "stdu", "stdux", "stdx",
287 "stfs", "stfsx", "stfsu", "stfux", # FP store single
288 "stfd", "stfdx", "stfdu", "stfdux", "stfiwx", # FP store double
289 "sth", "sthbrx", "sthcx", "sthu", "sthux", "sthx",
290 "stw", "stwbrx", "stwcx", "stwu", "stwux", "stwx",
291 "subf", "subfc", "subfco", "subfe", "subfeo", "subfic",
292 "subfme", "subfmeo", "subfo", "subfze", "subfzeo",
293 "sync",
294 "td", "tdi",
295 "tlbie", "tlbiel",
296 "tw", "twi",
297 "xor", "xori", "xoris",
298 ]
299
300 # two-way lookup of instruction-to-index and vice-versa
301 insns = {}
302 asmidx = {}
303 for i, insn in enumerate(_insns):
304 insns[i] = insn
305 asmidx[insn] = i
306
307 # must be long enough to cover all instructions
308 asmlen = len(_insns).bit_length()
309
310 # Internal Operation numbering. Add new opcodes here (FPADD, FPMUL etc.)
311
312
313 @unique
314 class MicrOp(Enum):
315 OP_ILLEGAL = 0 # important that this is zero (see power_decoder.py)
316 OP_NOP = 1
317 OP_ADD = 2
318 OP_ADDPCIS = 3
319 OP_AND = 4
320 OP_ATTN = 5
321 OP_B = 6
322 OP_BC = 7
323 OP_BCREG = 8
324 OP_BPERM = 9
325 OP_CMP = 10
326 OP_CMPB = 11
327 OP_CMPEQB = 12
328 OP_CMPRB = 13
329 OP_CNTZ = 14
330 OP_CRAND = 15
331 OP_CRANDC = 16
332 OP_CREQV = 17
333 OP_CRNAND = 18
334 OP_CRNOR = 19
335 OP_CROR = 20
336 OP_CRORC = 21
337 OP_CRXOR = 22
338 OP_DARN = 23
339 OP_DCBF = 24
340 OP_DCBST = 25
341 OP_DCBT = 26
342 OP_DCBTST = 27
343 OP_DCBZ = 28
344 OP_DIV = 29
345 OP_DIVE = 30
346 OP_EXTS = 31
347 OP_EXTSWSLI = 32
348 OP_ICBI = 33
349 OP_ICBT = 34
350 OP_ISEL = 35
351 OP_ISYNC = 36
352 OP_LOAD = 37
353 OP_STORE = 38
354 OP_MADDHD = 39
355 OP_MADDHDU = 40
356 OP_MADDLD = 41
357 OP_MCRF = 42
358 OP_MCRXR = 43
359 OP_MCRXRX = 44
360 OP_MFCR = 45
361 OP_MFSPR = 46
362 OP_MOD = 47
363 OP_MTCRF = 48
364 OP_MTSPR = 49
365 OP_MUL_L64 = 50
366 OP_MUL_H64 = 51
367 OP_MUL_H32 = 52
368 OP_OR = 53
369 OP_POPCNT = 54
370 OP_PRTY = 55
371 OP_RLC = 56
372 OP_RLCL = 57
373 OP_RLCR = 58
374 OP_SETB = 59
375 OP_SHL = 60
376 OP_SHR = 61
377 OP_SYNC = 62
378 OP_TRAP = 63
379 OP_XOR = 67
380 OP_SIM_CONFIG = 68
381 OP_CROP = 69
382 OP_RFID = 70
383 OP_MFMSR = 71
384 OP_MTMSRD = 72
385 OP_SC = 73
386 OP_MTMSR = 74
387 OP_TLBIE = 75
388 OP_SETVL = 76
389 OP_FPOP = 77 # temporary: replace with actual ops
390 OP_FPOP_I = 78 # temporary: replace with actual ops
391 OP_FP_MADD = 79
392 OP_SVREMAP = 80
393
394
395 @unique
396 class In1Sel(Enum):
397 NONE = 0
398 RA = 1
399 RA_OR_ZERO = 2
400 SPR = 3
401 RS = 4 # for some ALU/Logical operations
402 FRA = 5
403 FRS = 6
404
405
406 @unique
407 class In2Sel(Enum):
408 NONE = 0
409 RB = 1
410 CONST_UI = 2
411 CONST_SI = 3
412 CONST_UI_HI = 4
413 CONST_SI_HI = 5
414 CONST_LI = 6
415 CONST_BD = 7
416 CONST_DS = 8
417 CONST_M1 = 9
418 CONST_SH = 10
419 CONST_SH32 = 11
420 SPR = 12
421 RS = 13 # for shiftrot (M-Form)
422 FRB = 14
423 CONST_SVD = 15 # for SVD-Form
424 CONST_SVDS = 16 # for SVDS-Form
425
426
427 @unique
428 class In3Sel(Enum):
429 NONE = 0
430 RS = 1
431 RB = 2 # for shiftrot (M-Form)
432 FRS = 3
433 FRC = 4
434 RC = 5 # for SVP64 bit-reverse LD/ST
435
436
437 @unique
438 class OutSel(Enum):
439 NONE = 0
440 RT = 1
441 RA = 2
442 SPR = 3
443 RT_OR_ZERO = 4
444 FRT = 5
445 FRS = 6
446
447
448 @unique
449 class LdstLen(Enum):
450 NONE = 0
451 is1B = 1
452 is2B = 2
453 is4B = 4
454 is8B = 8
455
456
457 @unique
458 class LDSTMode(Enum):
459 NONE = 0
460 update = 1
461 cix = 2
462 cx = 3
463
464
465 @unique
466 class RC(Enum):
467 NONE = 0
468 ONE = 1
469 RC = 2
470
471
472 @unique
473 class CryIn(Enum):
474 ZERO = 0
475 ONE = 1
476 CA = 2
477 # TODO OV = 3
478
479
480 @unique
481 class CRInSel(Enum):
482 NONE = 0
483 CR0 = 1
484 BI = 2
485 BFA = 3
486 BA_BB = 4
487 BC = 5
488 WHOLE_REG = 6
489 CR1 = 7
490
491
492 @unique
493 class CROutSel(Enum):
494 NONE = 0
495 CR0 = 1
496 BF = 2
497 BT = 3
498 WHOLE_REG = 4
499 CR1 = 5
500
501
502 # SPRs - Special-Purpose Registers. See V3.0B Figure 18 p971 and
503 # http://libre-riscv.org/openpower/isatables/sprs.csv
504 # http://bugs.libre-riscv.org/show_bug.cgi?id=261
505
506 def get_spr_enum(full_file):
507 """get_spr_enum - creates an Enum of SPRs, dynamically
508 has the option to reduce the enum to a much shorter list.
509 this saves drastically on the size of the regfile
510 """
511 short_list = {'PIDR', 'DAR', 'PRTBL', 'DSISR', 'SVSRR0', 'SVSTATE',
512 'SVSTATE0', 'SVSTATE1', 'SVSTATE2', 'SVSTATE3',
513 'SPRG0_priv', 'SPRG1_priv', 'SPRG2_priv', 'SPRG3_priv',
514 'SPRG3'
515 }
516 spr_csv = []
517 for row in get_csv("sprs.csv"):
518 if full_file or row['SPR'] in short_list:
519 spr_csv.append(row)
520
521 spr_info = namedtuple('spr_info', 'SPR priv_mtspr priv_mfspr length idx')
522 spr_dict = {}
523 spr_byname = {}
524 for row in spr_csv:
525 info = spr_info(SPR=row['SPR'], priv_mtspr=row['priv_mtspr'],
526 priv_mfspr=row['priv_mfspr'], length=int(row['len']),
527 idx=int(row['Idx']))
528 spr_dict[int(row['Idx'])] = info
529 spr_byname[row['SPR']] = info
530 fields = [(row['SPR'], int(row['Idx'])) for row in spr_csv]
531 SPR = Enum('SPR', fields)
532 return SPR, spr_dict, spr_byname
533
534 SPRfull, spr_dict, spr_byname = get_spr_enum(full_file=True)
535 SPRreduced, _, _ = get_spr_enum(full_file=False)
536
537 XER_bits = {
538 'SO': 32,
539 'OV': 33,
540 'CA': 34,
541 'OV32': 44,
542 'CA32': 45
543 }
544
545 if __name__ == '__main__':
546 # find out what the heck is in SPR enum :)
547 print("sprs full", len(SPRfull))
548 print(dir(SPRfull))
549 print("sprs reduced", len(SPRreduced))
550 print(dir(SPRreduced))
551 print(dir(Enum))
552 print(SPRfull.__members__['TAR'])
553 for x in SPRfull:
554 print("full", x, x.value, str(x), x.name)
555 for x in SPRreduced:
556 print("reduced", x, x.value, str(x), x.name)
557
558 print("function", Function.ALU.name)