5089942ae60b204257bb1befa90c9103bf1d14df
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
24 from os
.path
import dirname
, join
25 from collections
import namedtuple
30 filedir
= os
.path
.dirname(os
.path
.abspath(__file__
))
31 basedir
= dirname(dirname(dirname(filedir
)))
32 tabledir
= join(basedir
, 'openpower')
33 isatables
= join(tabledir
, 'isatables')
34 #print ("find_wiki_dir", isatables)
38 def find_wiki_file(name
):
39 return join(find_wiki_dir(), name
)
43 """gets a not-entirely-csv-file-formatted database, which allows comments
45 file_path
= find_wiki_file(name
)
46 with
open(file_path
, 'r') as csvfile
:
47 csvfile
= filter(lambda row
: row
[0] !='#', csvfile
) # strip "#..."
48 reader
= csv
.DictReader(csvfile
)
52 # names of the fields in the tables that don't correspond to an enum
53 single_bit_flags
= ['inv A', 'inv out',
54 'cry out', 'BR', 'sgn ext', 'rsrv', '32b',
55 'sgn', 'lk', 'sgl pipe']
57 # default values for fields in the table
58 default_values
= {'unit': "NONE", 'internal op': "OP_ILLEGAL",
59 'in1': "RA", 'in2': 'NONE', 'in3': 'NONE', 'out': 'NONE',
63 'rc': 'NONE', 'cry in': 'ZERO', 'form': 'NONE'}
66 def get_signal_name(name
):
69 return name
.lower().replace(' ', '_')
74 def _missing_(cls
, value
):
75 if isinstance(value
, str):
83 keys
= {item
.name
:item
for item
in cls
}
84 values
= {item
.value
:item
for item
in cls
}
85 item
= keys
.get(value
, values
.get(value
))
87 raise ValueError(value
)
91 # this corresponds to which Function Unit (pipeline-with-Reservation-Stations)
92 # is to process and guard the operation. they are roughly divided by having
93 # the same register input/output signature (X-Form, etc.)
110 SV
= 1 << 12 # Simple-V https://libre-soc.org/openpower/sv
114 @functools.lru_cache(maxsize
=None)
117 value
= int(self
.value
)
123 desc
= f
"(1 << {counter})"
126 return f
"<{self.__class__.__name__}.{self.name}: {desc}>"
160 SVL
= 29 # Simple-V for setvl instruction
161 SVD
= 30 # Simple-V for LD/ST bit-reverse, variant of D-Form
162 SVDS
= 31 # Simple-V for LD/ST bit-reverse, variant of DS-Form
163 SVM
= 32 # Simple-V SHAPE mode
164 SVM2
= 33 # Simple-V SHAPE2 mode - fits into SVM
165 SVRM
= 34 # Simple-V REMAP mode
169 SVI
= 38 # Simple-V Index Mode
174 # Simple-V svp64 fields https://libre-soc.org/openpower/sv/svp64/
192 def _missing_(cls
, value
):
193 return {"1P": SVPtype
.P1
, "2P": SVPtype
.P2
}[value
]
197 SVPtype
.NONE
: "NONE",
220 Idx_1_2
= 5 # due to weird BA/BB for crops
224 SVExtra
.NONE
: "NONE",
229 SVExtra
.Idx_1_2
: "[1:2]",
232 # Backward compatibility
236 class SVExtraRegType(Enum
):
242 class SVExtraReg(Enum
):
271 def _missing_(cls
, value
):
273 In1Sel
, In2Sel
, In3Sel
, CRInSel
, CRIn2Sel
,
276 if isinstance(value
, selectors
):
277 return cls
.__members
__[value
.name
]
278 return super()._missing
_(value
)
282 class SVP64PredMode(Enum
):
289 class SVP64PredInt(Enum
):
301 class SVP64PredCR(Enum
):
313 class SVP64RMMode(Enum
):
323 class SVP64BCPredMode(Enum
):
330 class SVP64BCVLSETMode(Enum
):
336 # note that these are chosen to be exactly the same as
337 # SVP64 RM bit 4. ALL=1 => bit4=1
339 class SVP64BCGate(Enum
):
344 class SVP64BCCTRMode(Enum
):
351 class SVP64width(Enum
):
359 class SVP64subvl(Enum
):
367 class SVP64sat(Enum
):
374 class SVP64LDSTmode(Enum
):
396 CR_REG
= 2 # actually CR Field. the CR register is 32-bit.
400 CR_BIT
= 3 # refers to one bit of the 32-bit CR register
408 # supported instructions: make sure to keep up-to-date with CSV files
409 # just like everything else
411 "NONE", "add", "addc", "addco", "adde", "addeo",
412 "addi", "addic", "addic.", "addis",
413 "addme", "addmeo", "addo", "addze", "addzeo",
415 "and", "andc", "andi.", "andis.",
417 "absdu", "absds", # AV bitmanip
418 "absdacs", "absdacu", # AV bitmanip
419 "avgadd", # AV bitmanip
420 "b", "bc", "bcctr", "bclr", "bctar",
421 "bmask", # AV bitmanip
425 "cmp", "cmpb", "cmpeqb", "cmpi", "cmpl", "cmpli", "cmprb",
426 "cntlzd", "cntlzw", "cnttzd", "cnttzw",
427 "cprop", # AV bitmanip
428 "crand", "crandc", "creqv",
429 "crnand", "crnor", "cror", "crorc", "crxor",
431 "dcbf", "dcbst", "dcbt", "dcbtst", "dcbz",
432 "divd", "divde", "divdeo", "divdeu",
433 "divdeuo", "divdo", "divdu", "divduo", "divw", "divwe", "divweo",
434 "divweu", "divweuo", "divwo", "divwu", "divwuo",
436 "extsb", "extsh", "extsw", "extswsli",
437 "fadd", "fadds", "fsub", "fsubs", # FP add / sub
438 "fcfids", "fcfidus", "fsqrts", "fres", "frsqrtes", # FP stuff
439 "fdmadds", # DCT FP 3-arg
440 "fmsubs", "fmadds", "fnmsubs", "fnmadds", # FP 3-arg
441 "ffadds", "ffsubs", "ffmuls", "ffdivs", # FFT FP 2-arg
442 "ffmsubs", "ffmadds", "ffnmsubs", "ffnmadds", # FFT FP 3-arg
443 "fmul", "fmuls", "fdiv", "fdivs", # FP mul / div
444 "fmr", "fabs", "fnabs", "fneg", "fcpsgn", # FP move/abs/neg
445 "fsins", "fcoss", # FP SIN/COS
446 "fmvis", # FP load immediate
447 "fishmv", # Float Replace Lower-Half Single, Immediate
448 'grev', 'grev.', 'grevi', 'grevi.',
449 'grevw', 'grevw.', 'grevwi', 'grevwi.',
450 "hrfid", "icbi", "icbt", "isel", "isync",
451 "lbarx", "lbz", "lbzcix", "lbzu", "lbzux", "lbzx", # load byte
452 "ld", "ldarx", "ldbrx", "ldu", "ldux", "ldx", # load double
453 # "lbzbr", "lbzubr", # load byte SVP64 bit-reversed
454 # "ldbr", "ldubr", # load double SVP64 bit-reversed
455 "lfs", "lfsx", "lfsu", "lfsux", # FP load single
456 "lfd", "lfdx", "lfdu", "lfdux", "lfiwzx", "lfiwax", # FP load double
457 "lha", "lharx", "lhau", "lhaux", "lhax", # load half
458 "lhbrx", "lhz", "lhzu", "lhzux", "lhzx", # more load half
459 # "lhabr", "lhaubr", # load half SVP64 bit-reversed
460 # "lhzbr", "lhzubr", # more load half SVP64 bit-reversed
461 "lwa", "lwarx", "lwaux", "lwax", "lwbrx", # load word
462 "lwz", "lwzcix", "lwzu", "lwzux", "lwzx", # more load word
463 # "lwabr", # load word SVP64 bit-reversed
464 # "lwzbr", "lwzubr", # more load word SVP64 bit-reversed
465 "maddhd", "maddhdu", "maddld", # INT multiply-and-add
466 "mcrf", "mcrxr", "mcrxrx", "mfcr/mfocrf", # CR mvs
468 "mins", "maxs", "minu", "maxu", # AV bitmanip
469 "modsd", "modsw", "modud", "moduw",
470 "mtcrf/mtocrf", "mtmsr", "mtmsrd", "mtspr",
471 "mulhd", "mulhdu", "mulhw", "mulhwu", "mulld", "mulldo",
472 "mulli", "mullw", "mullwo",
473 "nand", "neg", "nego",
475 "nor", "or", "orc", "ori", "oris",
476 "popcntb", "popcntd", "popcntw",
479 "rldcl", "rldcr", "rldic", "rldicl", "rldicr", "rldimi",
480 "rlwimi", "rlwinm", "rlwnm",
482 "setvl", # https://libre-soc.org/openpower/sv/setvl
483 "svindex", # https://libre-soc.org/openpower/sv/remap
484 "svremap", # https://libre-soc.org/openpower/sv/remap - TEMPORARY
485 "svshape", # https://libre-soc.org/openpower/sv/remap/#svshape
486 "svshape2", # https://libre-soc.org/openpower/sv/remap/discussion TODO
487 "svstep", # https://libre-soc.org/openpower/sv/setvl
489 "slbia", "sld", "slw", "srad", "sradi",
490 "sraw", "srawi", "srd", "srw",
491 "stb", "stbcix", "stbcx", "stbu", "stbux", "stbx",
492 "std", "stdbrx", "stdcx", "stdu", "stdux", "stdx",
493 "stfs", "stfsx", "stfsu", "stfux", "stfsux", # FP store single
494 "stfd", "stfdx", "stfdu", "stfdux", "stfiwx", # FP store double
495 "sth", "sthbrx", "sthcx", "sthu", "sthux", "sthx",
496 "stw", "stwbrx", "stwcx", "stwu", "stwux", "stwx",
497 "subf", "subfc", "subfco", "subfe", "subfeo", "subfic",
498 "subfme", "subfmeo", "subfo", "subfze", "subfzeo",
502 "tlbie", "tlbiel", "tlbsync",
505 "xor", "xori", "xoris",
508 # two-way lookup of instruction-to-index and vice-versa
511 for i
, insn
in enumerate(_insns
):
515 # must be long enough to cover all instructions
516 asmlen
= len(_insns
).bit_length()
518 # Internal Operation numbering. Add new opcodes here (FPADD, FPMUL etc.)
523 OP_ILLEGAL
= 0 # important that this is zero (see power_decoder.py)
597 OP_FPOP
= 77 # temporary: replace with actual ops
598 OP_FPOP_I
= 78 # temporary: replace with actual ops
626 RS
= 4 # for some ALU/Logical operations
629 CIA
= 7 # for addpcis
647 RS
= 13 # for shiftrot (M-Form)
649 CONST_SVD
= 15 # for SVD-Form
650 CONST_SVDS
= 16 # for SVDS-Form
652 CONST_DXHI4
= 18 # for addpcis
659 RB
= 2 # for shiftrot (M-Form)
662 RC
= 5 # for SVP64 bit-reverse LD/ST
663 RT
= 6 # for ternlog[i]
685 # Backward compatibility
690 class LDSTMode(Enum
):
702 RC_ONLY
= 3 # does not include OE
727 class CRIn2Sel(Enum
):
733 class CROutSel(Enum
):
742 # SPRs - Special-Purpose Registers. See V3.0B Figure 18 p971 and
743 # http://libre-riscv.org/openpower/isatables/sprs.csv
744 # http://bugs.libre-riscv.org/show_bug.cgi?id=261
745 # http://bugs.libre-riscv.org/show_bug.cgi?id=859 - KAIVB
747 def get_spr_enum(full_file
):
748 """get_spr_enum - creates an Enum of SPRs, dynamically
749 has the option to reduce the enum to a much shorter list.
750 this saves drastically on the size of the regfile
752 short_list
= {'PIDR', 'DAR', 'PRTBL', 'DSISR', 'SVSRR0', 'SVSTATE',
753 'SVSTATE0', 'SVSTATE1', 'SVSTATE2', 'SVSTATE3',
754 'SPRG0_priv', 'SPRG1_priv', 'SPRG2_priv', 'SPRG3_priv',
755 'SPRG0', 'SPRG1', 'SPRG2', 'SPRG3', 'KAIVB',
756 # hmmm should not be including these, they are FAST regs
757 'CTR', 'LR', 'TAR', 'SRR0', 'SRR1', 'XER', 'DEC', 'TB', 'TBU',
758 'HSRR0', 'HSRR1', 'HSPRG0', 'HSPRG1',
761 for row
in get_csv("sprs.csv"):
762 if full_file
or row
['SPR'] in short_list
:
765 spr_info
= namedtuple('spr_info', 'SPR priv_mtspr priv_mfspr length idx')
769 info
= spr_info(SPR
=row
['SPR'], priv_mtspr
=row
['priv_mtspr'],
770 priv_mfspr
=row
['priv_mfspr'], length
=int(row
['len']),
772 spr_dict
[int(row
['Idx'])] = info
773 spr_byname
[row
['SPR']] = info
774 fields
= [(row
['SPR'], int(row
['Idx'])) for row
in spr_csv
]
775 SPR
= Enum('SPR', fields
)
776 return SPR
, spr_dict
, spr_byname
779 SPRfull
, spr_dict
, spr_byname
= get_spr_enum(full_file
=True)
780 SPRreduced
, _
, _
= get_spr_enum(full_file
=False)
790 MSRSpec
= namedtuple("MSRSpec", ["dr", "pr", "sf"])
792 if __name__
== '__main__':
793 # find out what the heck is in SPR enum :)
794 print("sprs full", len(SPRfull
))
796 print("sprs reduced", len(SPRreduced
))
797 print(dir(SPRreduced
))
799 print(SPRfull
.__members
__['TAR'])
801 print("full", x
, x
.value
, str(x
), x
.name
)
803 print("reduced", x
, x
.value
, str(x
), x
.name
)
805 print("function", Function
.ALU
.name
)