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