1 # SPDX-License: LGPLv3+
2 # Copyright (C) 2020, 2021 Luke Kenneth Casson Leighton <lkcl@lkcl.net>
3 # Copyright (C) 2020, Michael Nolan
5 """Enums used in OpenPOWER ISA decoding
7 Note: for SV, from v3.1B p12:
9 The designated SPR sandbox consists of non-privileged SPRs 704-719 and
10 privileged SPRs 720-735.
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
17 from enum
import Enum
, unique
20 from os
.path
import dirname
, join
21 from collections
import namedtuple
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)
33 def find_wiki_file(name
):
34 return join(find_wiki_dir(), name
)
38 file_path
= find_wiki_file(name
)
39 with
open(file_path
, 'r') as csvfile
:
40 reader
= csv
.DictReader(csvfile
)
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']
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',
55 'rc': 'NONE', 'cry in': 'ZERO', 'form': 'NONE'}
58 def get_signal_name(name
):
61 return name
.lower().replace(' ', '_')
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.)
82 SV
= 1 << 12 # Simple-V https://libre-soc.org/openpower/sv
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
124 # Simple-V svp64 fields https://libre-soc.org/openpower/sv/svp64/
148 Idx_1_2
= 5 # due to weird BA/BB for crops
152 class SVP64PredMode(Enum
):
159 class SVP64PredInt(Enum
):
171 class SVP64PredCR(Enum
):
183 class SVP64RMMode(Enum
):
193 class SVP64BCPredMode(Enum
):
200 class SVP64BCVLSETMode(Enum
):
206 # note that these are chosen to be exactly the same as
207 # SVP64 RM bit 4. ALL=1 => bit4=1
209 class SVP64BCGate(Enum
):
214 class SVP64BCCTRMode(Enum
):
221 class SVP64width(Enum
):
229 class SVP64subvl(Enum
):
237 class SVP64sat(Enum
):
244 class SVP64LDSTmode(Enum
):
252 # supported instructions: make sure to keep up-to-date with CSV files
253 # just like everything else
255 "NONE", "add", "addc", "addco", "adde", "addeo",
256 "addi", "addic", "addic.", "addis",
257 "addme", "addmeo", "addo", "addze", "addzeo",
259 "and", "andc", "andi.", "andis.",
261 "b", "bc", "bcctr", "bclr", "bctar",
265 "cmp", "cmpb", "cmpeqb", "cmpi", "cmpl", "cmpli", "cmprb",
266 "cntlzd", "cntlzw", "cnttzd", "cnttzw",
267 "crand", "crandc", "creqv",
268 "crnand", "crnor", "cror", "crorc", "crxor",
270 "dcbf", "dcbst", "dcbt", "dcbtst", "dcbz",
271 "divd", "divde", "divdeo", "divdeu",
272 "divdeuo", "divdo", "divdu", "divduo", "divw", "divwe", "divweo",
273 "divweu", "divweuo", "divwo", "divwu", "divwuo",
275 "extsb", "extsh", "extsw", "extswsli",
276 "fadd", "fadds", "fsub", "fsubs", # FP add / sub
277 "fcfids", "fcfidus", "fsqrts", "fres", "frsqrtes", # FP stuff
278 "fdmadds", # DCT FP 3-arg
279 "fmsubs", "fmadds", "fnmsubs", "fnmadds", # FP 3-arg
280 "ffadds", "ffsubs", "ffmuls", "ffdivs", # FFT FP 2-arg
281 "ffmsubs", "ffmadds", "ffnmsubs", "ffnmadds", # FFT FP 3-arg
282 "fmul", "fmuls", "fdiv", "fdivs", # FP mul / div
283 "fmr", "fabs", "fnabs", "fneg", "fcpsgn", # FP move/abs/neg
284 "fsins", "fcoss", # FP SIN/COS
285 "hrfid", "icbi", "icbt", "isel", "isync",
286 "lbarx", "lbz", "lbzu", "lbzux", "lbzx", # load byte
287 "ld", "ldarx", "ldbrx", "ldu", "ldux", "ldx", # load double
288 # "lbzbr", "lbzubr", # load byte SVP64 bit-reversed
289 # "ldbr", "ldubr", # load double SVP64 bit-reversed
290 "lfs", "lfsx", "lfsu", "lfsux", # FP load single
291 "lfd", "lfdx", "lfdu", "lfdux", "lfiwzx", "lfiwax", # FP load double
292 "lha", "lharx", "lhau", "lhaux", "lhax", # load half
293 "lhbrx", "lhz", "lhzu", "lhzux", "lhzx", # more load half
294 # "lhabr", "lhaubr", # load half SVP64 bit-reversed
295 # "lhzbr", "lhzubr", # more load half SVP64 bit-reversed
296 "lwa", "lwarx", "lwaux", "lwax", "lwbrx", # load word
297 "lwz", "lwzcix", "lwzu", "lwzux", "lwzx", # more load word
298 # "lwabr", # load word SVP64 bit-reversed
299 # "lwzbr", "lwzubr", # more load word SVP64 bit-reversed
300 "maddhd", "maddhdu", "maddld", # INT multiply-and-add
301 "mcrf", "mcrxr", "mcrxrx", "mfcr/mfocrf", # CR mvs
303 "modsd", "modsw", "modud", "moduw",
304 "mtcrf/mtocrf", "mtmsr", "mtmsrd", "mtspr",
305 "mulhd", "mulhdu", "mulhw", "mulhwu", "mulld", "mulldo",
306 "mulli", "mullw", "mullwo",
307 "nand", "neg", "nego",
309 "nor", "or", "orc", "ori", "oris",
310 "popcntb", "popcntd", "popcntw",
313 "rldcl", "rldcr", "rldic", "rldicl", "rldicr", "rldimi",
314 "rlwimi", "rlwinm", "rlwnm",
316 "setvl", # https://libre-soc.org/openpower/sv/setvl
317 "svremap", # https://libre-soc.org/openpower/sv/remap - TEMPORARY
318 "svshape", # https://libre-soc.org/openpower/sv/remap
319 "svstep", # https://libre-soc.org/openpower/sv/setvl
321 "slbia", "sld", "slw", "srad", "sradi",
322 "sraw", "srawi", "srd", "srw",
323 "stb", "stbcix", "stbcx", "stbu", "stbux", "stbx",
324 "std", "stdbrx", "stdcx", "stdu", "stdux", "stdx",
325 "stfs", "stfsx", "stfsu", "stfux", "stfsux", # FP store single
326 "stfd", "stfdx", "stfdu", "stfdux", "stfiwx", # FP store double
327 "sth", "sthbrx", "sthcx", "sthu", "sthux", "sthx",
328 "stw", "stwbrx", "stwcx", "stwu", "stwux", "stwx",
329 "subf", "subfc", "subfco", "subfe", "subfeo", "subfic",
330 "subfme", "subfmeo", "subfo", "subfze", "subfzeo",
335 "xor", "xori", "xoris",
338 # two-way lookup of instruction-to-index and vice-versa
341 for i
, insn
in enumerate(_insns
):
345 # must be long enough to cover all instructions
346 asmlen
= len(_insns
).bit_length()
348 # Internal Operation numbering. Add new opcodes here (FPADD, FPMUL etc.)
353 OP_ILLEGAL
= 0 # important that this is zero (see power_decoder.py)
427 OP_FPOP
= 77 # temporary: replace with actual ops
428 OP_FPOP_I
= 78 # temporary: replace with actual ops
444 RS
= 4 # for some ALU/Logical operations
464 RS
= 13 # for shiftrot (M-Form)
466 CONST_SVD
= 15 # for SVD-Form
467 CONST_SVDS
= 16 # for SVDS-Form
474 RB
= 2 # for shiftrot (M-Form)
477 RC
= 5 # for SVP64 bit-reverse LD/ST
501 class LDSTMode(Enum
):
536 class CROutSel(Enum
):
545 # SPRs - Special-Purpose Registers. See V3.0B Figure 18 p971 and
546 # http://libre-riscv.org/openpower/isatables/sprs.csv
547 # http://bugs.libre-riscv.org/show_bug.cgi?id=261
549 def get_spr_enum(full_file
):
550 """get_spr_enum - creates an Enum of SPRs, dynamically
551 has the option to reduce the enum to a much shorter list.
552 this saves drastically on the size of the regfile
554 short_list
= {'PIDR', 'DAR', 'PRTBL', 'DSISR', 'SVSRR0', 'SVSTATE',
555 'SVSTATE0', 'SVSTATE1', 'SVSTATE2', 'SVSTATE3',
556 'SPRG0_priv', 'SPRG1_priv', 'SPRG2_priv', 'SPRG3_priv',
560 for row
in get_csv("sprs.csv"):
561 if full_file
or row
['SPR'] in short_list
:
564 spr_info
= namedtuple('spr_info', 'SPR priv_mtspr priv_mfspr length idx')
568 info
= spr_info(SPR
=row
['SPR'], priv_mtspr
=row
['priv_mtspr'],
569 priv_mfspr
=row
['priv_mfspr'], length
=int(row
['len']),
571 spr_dict
[int(row
['Idx'])] = info
572 spr_byname
[row
['SPR']] = info
573 fields
= [(row
['SPR'], int(row
['Idx'])) for row
in spr_csv
]
574 SPR
= Enum('SPR', fields
)
575 return SPR
, spr_dict
, spr_byname
578 SPRfull
, spr_dict
, spr_byname
= get_spr_enum(full_file
=True)
579 SPRreduced
, _
, _
= get_spr_enum(full_file
=False)
589 if __name__
== '__main__':
590 # find out what the heck is in SPR enum :)
591 print("sprs full", len(SPRfull
))
593 print("sprs reduced", len(SPRreduced
))
594 print(dir(SPRreduced
))
596 print(SPRfull
.__members
__['TAR'])
598 print("full", x
, x
.value
, str(x
), x
.name
)
600 print("reduced", x
, x
.value
, str(x
), x
.name
)
602 print("function", Function
.ALU
.name
)