1 # SPDX-License-Identifier: LGPL-3-or-later
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
23 from os
.path
import dirname
, join
24 from collections
import namedtuple
29 filedir
= os
.path
.dirname(os
.path
.abspath(__file__
))
30 basedir
= dirname(dirname(dirname(filedir
)))
31 tabledir
= join(basedir
, 'openpower')
32 isatables
= join(tabledir
, 'isatables')
33 #print ("find_wiki_dir", isatables)
37 def find_wiki_file(name
):
38 return join(find_wiki_dir(), name
)
42 """gets a not-entirely-csv-file-formatted database, which allows comments
44 file_path
= find_wiki_file(name
)
45 with
open(file_path
, 'r') as csvfile
:
46 csvfile
= filter(lambda row
: row
[0] !='#', csvfile
) # strip "#..."
47 reader
= csv
.DictReader(csvfile
)
51 # names of the fields in the tables that don't correspond to an enum
52 single_bit_flags
= ['inv A', 'inv out',
53 'cry out', 'BR', 'sgn ext', 'rsrv', '32b',
54 'sgn', 'lk', 'sgl pipe']
56 # default values for fields in the table
57 default_values
= {'unit': "NONE", 'internal op': "OP_ILLEGAL",
58 'in1': "RA", 'in2': 'NONE', 'in3': 'NONE', 'out': 'NONE',
62 'rc': 'NONE', 'cry in': 'ZERO', 'form': 'NONE'}
65 def get_signal_name(name
):
68 return name
.lower().replace(' ', '_')
73 def _missing_(cls
, value
):
74 if isinstance(value
, str):
82 keys
= {item
.name
:item
for item
in cls
}
83 values
= {item
.value
:item
for item
in cls
}
84 item
= keys
.get(value
, values
.get(value
))
86 raise ValueError(value
)
90 # this corresponds to which Function Unit (pipeline-with-Reservation-Stations)
91 # is to process and guard the operation. they are roughly divided by having
92 # the same register input/output signature (X-Form, etc.)
109 SV
= 1 << 12 # Simple-V https://libre-soc.org/openpower/sv
113 @functools.lru_cache(maxsize
=None)
116 value
= int(self
.value
)
122 desc
= f
"(1 << {counter})"
125 return f
"<{self.__class__.__name__}.{self.name}: {desc}>"
159 SVL
= 29 # Simple-V for setvl instruction
160 SVD
= 30 # Simple-V for LD/ST bit-reverse, variant of D-Form
161 SVDS
= 31 # Simple-V for LD/ST bit-reverse, variant of DS-Form
162 SVM
= 32 # Simple-V SHAPE mode - TEMPORARY TEMPORARY TEMPORARY
163 SVRM
= 33 # Simple-V REMAP mode
167 SVI
= 37 # Simple-V Index Mode
172 # Simple-V svp64 fields https://libre-soc.org/openpower/sv/svp64/
182 def _missing_(cls
, value
):
183 return {"1P": SVPtype
.P1
, "2P": SVPtype
.P2
}[value
]
200 Idx_1_2
= 5 # due to weird BA/BB for crops
204 class SVP64PredMode(Enum
):
211 class SVP64PredInt(Enum
):
223 class SVP64PredCR(Enum
):
235 class SVP64RMMode(Enum
):
245 class SVP64BCPredMode(Enum
):
252 class SVP64BCVLSETMode(Enum
):
258 # note that these are chosen to be exactly the same as
259 # SVP64 RM bit 4. ALL=1 => bit4=1
261 class SVP64BCGate(Enum
):
266 class SVP64BCCTRMode(Enum
):
273 class SVP64width(Enum
):
281 class SVP64subvl(Enum
):
289 class SVP64sat(Enum
):
296 class SVP64LDSTmode(Enum
):
331 # supported instructions: make sure to keep up-to-date with CSV files
332 # just like everything else
334 "NONE", "add", "addc", "addco", "adde", "addeo",
335 "addi", "addic", "addic.", "addis",
336 "addme", "addmeo", "addo", "addze", "addzeo",
338 "and", "andc", "andi.", "andis.",
340 "absdu", "absds", # AV bitmanip
341 "absdacs", "absdacu", # AV bitmanip
342 "avgadd", # AV bitmanip
343 "b", "bc", "bcctr", "bclr", "bctar",
344 "bmask", # AV bitmanip
348 "cmp", "cmpb", "cmpeqb", "cmpi", "cmpl", "cmpli", "cmprb",
349 "cntlzd", "cntlzw", "cnttzd", "cnttzw",
350 "cprop", # AV bitmanip
351 "crand", "crandc", "creqv",
352 "crnand", "crnor", "cror", "crorc", "crxor",
354 "dcbf", "dcbst", "dcbt", "dcbtst", "dcbz",
355 "divd", "divde", "divdeo", "divdeu",
356 "divdeuo", "divdo", "divdu", "divduo", "divw", "divwe", "divweo",
357 "divweu", "divweuo", "divwo", "divwu", "divwuo",
359 "extsb", "extsh", "extsw", "extswsli",
360 "fadd", "fadds", "fsub", "fsubs", # FP add / sub
361 "fcfids", "fcfidus", "fsqrts", "fres", "frsqrtes", # FP stuff
362 "fdmadds", # DCT FP 3-arg
363 "fmsubs", "fmadds", "fnmsubs", "fnmadds", # FP 3-arg
364 "ffadds", "ffsubs", "ffmuls", "ffdivs", # FFT FP 2-arg
365 "ffmsubs", "ffmadds", "ffnmsubs", "ffnmadds", # FFT FP 3-arg
366 "fmul", "fmuls", "fdiv", "fdivs", # FP mul / div
367 "fmr", "fabs", "fnabs", "fneg", "fcpsgn", # FP move/abs/neg
368 "fsins", "fcoss", # FP SIN/COS
369 "fmvis", # FP load immediate
370 "fishmv", # Float Replace Lower-Half Single, Immediate
371 'grev', 'grev.', 'grevi', 'grevi.',
372 'grevw', 'grevw.', 'grevwi', 'grevwi.',
373 "hrfid", "icbi", "icbt", "isel", "isync",
374 "lbarx", "lbz", "lbzcix", "lbzu", "lbzux", "lbzx", # load byte
375 "ld", "ldarx", "ldbrx", "ldu", "ldux", "ldx", # load double
376 # "lbzbr", "lbzubr", # load byte SVP64 bit-reversed
377 # "ldbr", "ldubr", # load double SVP64 bit-reversed
378 "lfs", "lfsx", "lfsu", "lfsux", # FP load single
379 "lfd", "lfdx", "lfdu", "lfdux", "lfiwzx", "lfiwax", # FP load double
380 "lha", "lharx", "lhau", "lhaux", "lhax", # load half
381 "lhbrx", "lhz", "lhzu", "lhzux", "lhzx", # more load half
382 # "lhabr", "lhaubr", # load half SVP64 bit-reversed
383 # "lhzbr", "lhzubr", # more load half SVP64 bit-reversed
384 "lwa", "lwarx", "lwaux", "lwax", "lwbrx", # load word
385 "lwz", "lwzcix", "lwzu", "lwzux", "lwzx", # more load word
386 # "lwabr", # load word SVP64 bit-reversed
387 # "lwzbr", "lwzubr", # more load word SVP64 bit-reversed
388 "maddhd", "maddhdu", "maddld", # INT multiply-and-add
389 "mcrf", "mcrxr", "mcrxrx", "mfcr/mfocrf", # CR mvs
391 "mins", "maxs", "minu", "maxu", # AV bitmanip
392 "modsd", "modsw", "modud", "moduw",
393 "mtcrf/mtocrf", "mtmsr", "mtmsrd", "mtspr",
394 "mulhd", "mulhdu", "mulhw", "mulhwu", "mulld", "mulldo",
395 "mulli", "mullw", "mullwo",
396 "nand", "neg", "nego",
398 "nor", "or", "orc", "ori", "oris",
399 "popcntb", "popcntd", "popcntw",
402 "rldcl", "rldcr", "rldic", "rldicl", "rldicr", "rldimi",
403 "rlwimi", "rlwinm", "rlwnm",
405 "setvl", # https://libre-soc.org/openpower/sv/setvl
406 "svindex", # https://libre-soc.org/openpower/sv/remap
407 "svremap", # https://libre-soc.org/openpower/sv/remap - TEMPORARY
408 "svshape", # https://libre-soc.org/openpower/sv/remap
409 "svstep", # https://libre-soc.org/openpower/sv/setvl
411 "slbia", "sld", "slw", "srad", "sradi",
412 "sraw", "srawi", "srd", "srw",
413 "stb", "stbcix", "stbcx", "stbu", "stbux", "stbx",
414 "std", "stdbrx", "stdcx", "stdu", "stdux", "stdx",
415 "stfs", "stfsx", "stfsu", "stfux", "stfsux", # FP store single
416 "stfd", "stfdx", "stfdu", "stfdux", "stfiwx", # FP store double
417 "sth", "sthbrx", "sthcx", "sthu", "sthux", "sthx",
418 "stw", "stwbrx", "stwcx", "stwu", "stwux", "stwx",
419 "subf", "subfc", "subfco", "subfe", "subfeo", "subfic",
420 "subfme", "subfmeo", "subfo", "subfze", "subfzeo",
424 "tlbie", "tlbiel", "tlbsync",
427 "xor", "xori", "xoris",
430 # two-way lookup of instruction-to-index and vice-versa
433 for i
, insn
in enumerate(_insns
):
437 # must be long enough to cover all instructions
438 asmlen
= len(_insns
).bit_length()
440 # Internal Operation numbering. Add new opcodes here (FPADD, FPMUL etc.)
445 OP_ILLEGAL
= 0 # important that this is zero (see power_decoder.py)
519 OP_FPOP
= 77 # temporary: replace with actual ops
520 OP_FPOP_I
= 78 # temporary: replace with actual ops
548 RS
= 4 # for some ALU/Logical operations
568 RS
= 13 # for shiftrot (M-Form)
570 CONST_SVD
= 15 # for SVD-Form
571 CONST_SVDS
= 16 # for SVDS-Form
579 RB
= 2 # for shiftrot (M-Form)
582 RC
= 5 # for SVP64 bit-reverse LD/ST
583 RT
= 6 # for ternlog[i]
605 # Backward compatibility
610 class LDSTMode(Enum
):
645 class CROutSel(Enum
):
654 # SPRs - Special-Purpose Registers. See V3.0B Figure 18 p971 and
655 # http://libre-riscv.org/openpower/isatables/sprs.csv
656 # http://bugs.libre-riscv.org/show_bug.cgi?id=261
657 # http://bugs.libre-riscv.org/show_bug.cgi?id=859 - KAIVB
659 def get_spr_enum(full_file
):
660 """get_spr_enum - creates an Enum of SPRs, dynamically
661 has the option to reduce the enum to a much shorter list.
662 this saves drastically on the size of the regfile
664 short_list
= {'PIDR', 'DAR', 'PRTBL', 'DSISR', 'SVSRR0', 'SVSTATE',
665 'SVSTATE0', 'SVSTATE1', 'SVSTATE2', 'SVSTATE3',
666 'SPRG0_priv', 'SPRG1_priv', 'SPRG2_priv', 'SPRG3_priv',
667 'SPRG0', 'SPRG1', 'SPRG2', 'SPRG3', 'KAIVB',
668 # hmmm should not be including these, they are FAST regs
669 'CTR', 'LR', 'TAR', 'SRR0', 'SRR1', 'XER', 'DEC', 'TB', 'TBU',
670 'HSRR0', 'HSRR1', 'HSPRG0', 'HSPRG1',
673 for row
in get_csv("sprs.csv"):
674 if full_file
or row
['SPR'] in short_list
:
677 spr_info
= namedtuple('spr_info', 'SPR priv_mtspr priv_mfspr length idx')
681 info
= spr_info(SPR
=row
['SPR'], priv_mtspr
=row
['priv_mtspr'],
682 priv_mfspr
=row
['priv_mfspr'], length
=int(row
['len']),
684 spr_dict
[int(row
['Idx'])] = info
685 spr_byname
[row
['SPR']] = info
686 fields
= [(row
['SPR'], int(row
['Idx'])) for row
in spr_csv
]
687 SPR
= Enum('SPR', fields
)
688 return SPR
, spr_dict
, spr_byname
691 SPRfull
, spr_dict
, spr_byname
= get_spr_enum(full_file
=True)
692 SPRreduced
, _
, _
= get_spr_enum(full_file
=False)
702 MSRSpec
= namedtuple("MSRSpec", ["dr", "pr", "sf"])
704 if __name__
== '__main__':
705 # find out what the heck is in SPR enum :)
706 print("sprs full", len(SPRfull
))
708 print("sprs reduced", len(SPRreduced
))
709 print(dir(SPRreduced
))
711 print(SPRfull
.__members
__['TAR'])
713 print("full", x
, x
.value
, str(x
), x
.name
)
715 print("reduced", x
, x
.value
, str(x
), x
.name
)
717 print("function", Function
.ALU
.name
)