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/
178 NONE
= 0 # for non-SV instructions only
193 def _missing_(cls
, value
):
194 return {"1P": SVPtype
.P1
, "2P": SVPtype
.P2
}[value
]
198 SVPtype
.NONE
: "NONE",
215 class SVmask_src(Enum
):
230 Idx_1_2
= 5 # due to weird BA/BB for crops
234 SVExtra
.NONE
: "NONE",
239 SVExtra
.Idx_1_2
: "[1:2]",
242 # Backward compatibility
246 class SVExtraRegType(Enum
):
252 class SVExtraReg(Enum
):
281 def _missing_(cls
, value
):
283 In1Sel
, In2Sel
, In3Sel
, CRInSel
, CRIn2Sel
,
286 if isinstance(value
, selectors
):
287 return cls
.__members
__[value
.name
]
288 return super()._missing
_(value
)
292 class SVP64PredMode(Enum
):
299 class SVP64PredInt(Enum
):
311 class SVP64PredCR(Enum
):
323 class SVP64RMMode(Enum
):
333 class SVP64BCPredMode(Enum
):
340 class SVP64BCVLSETMode(Enum
):
346 # note that these are chosen to be exactly the same as
347 # SVP64 RM bit 4. ALL=1 => bit4=1
349 class SVP64BCGate(Enum
):
354 class SVP64BCCTRMode(Enum
):
361 class SVP64width(Enum
):
369 class SVP64subvl(Enum
):
377 class SVP64sat(Enum
):
384 class SVP64LDSTmode(Enum
):
406 CR_REG
= 2 # actually CR Field. the CR register is 32-bit.
410 CR_BIT
= 3 # refers to one bit of the 32-bit CR register
417 XER_BIT
= 4 # XER bits, includes OV, OV32, SO, CA, CA32
425 def _missing_(cls
, value
):
426 if isinstance(value
, SVExtraReg
):
427 return cls
.__members
__[value
.name
]
428 return super()._missing
_(value
)
433 "fatan2pi", "fatan2pis",
442 "fexp2m1", "fexp2m1s",
443 "flog2p1", "flog2p1s",
450 "fexp10m1", "fexp10m1s",
451 "flog10p1", "flog10p1s",
463 "fasinpi", "fasinpis",
464 "facospi", "facospis",
465 "fatanpi", "fatanpis",
472 "fminnum08", "fminnum08s",
473 "fmaxnum08", "fmaxnum08s",
476 "fminnum19", "fminnum19s",
477 "fmaxnum19", "fmaxnum19s",
480 "fminmagnum08", "fminmagnum08s",
481 "fmaxmagnum08", "fmaxmagnum08s",
482 "fminmag19", "fminmag19s",
483 "fmaxmag19", "fmaxmag19s",
484 "fminmagnum19", "fminmagnum19s",
485 "fmaxmagnum19", "fmaxmagnum19s",
486 "fminmagc", "fminmagcs",
487 "fmaxmagc", "fmaxmagcs",
489 "fremainder", "fremainders",
493 # supported instructions: make sure to keep up-to-date with CSV files
494 # just like everything else
496 "NONE", "add", "addc", "addco", "adde", "addeo",
497 "addi", "addic", "addic.", "addis",
498 "addme", "addmeo", "addo", "addze", "addzeo",
500 "and", "andc", "andi.", "andis.",
502 "absdu", "absds", # AV bitmanip
503 "absdacs", "absdacu", # AV bitmanip
504 "avgadd", # AV bitmanip
505 "b", "bc", "bcctr", "bclr", "bctar",
506 "bmask", # AV bitmanip
510 "cmp", "cmpb", "cmpeqb", "cmpi", "cmpl", "cmpli", "cmprb",
511 "cntlzd", "cntlzw", "cnttzd", "cnttzw",
512 "cprop", # AV bitmanip
513 "crand", "crandc", "creqv",
514 "crnand", "crnor", "cror", "crorc", "crxor",
516 "dcbf", "dcbst", "dcbt", "dcbtst", "dcbz",
517 "divd", "divde", "divdeo", "divdeu",
518 "divdeuo", "divdo", "divdu", "divduo",
520 "divw", "divwe", "divweo",
521 "divweu", "divweuo", "divwo", "divwu", "divwuo",
524 "extsb", "extsh", "extsw", "extswsli",
525 "fadd", "fadds", "fsub", "fsubs", # FP add / sub
526 "fcfids", "fcfidus", "fsqrts", "fres", "frsqrtes", # FP stuff
527 "fdmadds", # DCT FP 3-arg
528 "fmsubs", "fmadds", "fnmsubs", "fnmadds", # FP 3-arg
529 "ffadds", "ffsubs", "ffmuls", "ffdivs", # FFT FP 2-arg
530 "ffmsubs", "ffmadds", "ffnmsubs", "ffnmadds", # FFT FP 3-arg
531 "fmul", "fmuls", "fdiv", "fdivs", # FP mul / div
532 "fmr", "fabs", "fnabs", "fneg", "fcpsgn", # FP move/abs/neg
533 "fmvis", # FP load immediate
534 "fishmv", # Float Replace Lower-Half Single, Immediate
535 'grev', 'grev.', 'grevi', 'grevi.',
536 'grevw', 'grevw.', 'grevwi', 'grevwi.',
537 "hrfid", "icbi", "icbt", "isel", "isync",
538 "lbarx", "lbz", "lbzcix", "lbzu", "lbzux", "lbzx", # load byte
539 "ld", "ldarx", "ldbrx", "ldu", "ldux", "ldx", # load double
540 # "lbzbr", "lbzubr", # load byte SVP64 bit-reversed
541 # "ldbr", "ldubr", # load double SVP64 bit-reversed
542 "lfs", "lfsx", "lfsu", "lfsux", # FP load single
543 "lfd", "lfdx", "lfdu", "lfdux", "lfiwzx", "lfiwax", # FP load double
544 "lha", "lharx", "lhau", "lhaux", "lhax", # load half
545 "lhbrx", "lhz", "lhzu", "lhzux", "lhzx", # more load half
546 # "lhabr", "lhaubr", # load half SVP64 bit-reversed
547 # "lhzbr", "lhzubr", # more load half SVP64 bit-reversed
548 "lwa", "lwarx", "lwaux", "lwax", "lwbrx", # load word
549 "lwz", "lwzcix", "lwzu", "lwzux", "lwzx", # more load word
550 # "lwabr", # load word SVP64 bit-reversed
551 # "lwzbr", "lwzubr", # more load word SVP64 bit-reversed
553 "maddhd", "maddhdu", "maddld", # INT multiply-and-add
554 "mcrf", "mcrxr", "mcrxrx", "mfcr/mfocrf", # CR mvs
556 "mins", "maxs", "minu", "maxu", # AV bitmanip
557 "modsd", "modsw", "modud", "moduw",
558 "mtcrf/mtocrf", "mtmsr", "mtmsrd", "mtspr",
559 "mulhd", "mulhdu", "mulhw", "mulhwu", "mulld", "mulldo",
560 "mulli", "mullw", "mullwo",
561 "nand", "neg", "nego",
563 "nor", "or", "orc", "ori", "oris",
565 "popcntb", "popcntd", "popcntw",
568 "rldcl", "rldcr", "rldic", "rldicl", "rldicr", "rldimi",
569 "rlwimi", "rlwinm", "rlwnm",
571 "setvl", # https://libre-soc.org/openpower/sv/setvl
572 "svindex", # https://libre-soc.org/openpower/sv/remap
573 "svremap", # https://libre-soc.org/openpower/sv/remap - TEMPORARY
574 "svshape", # https://libre-soc.org/openpower/sv/remap/#svshape
575 "svshape2", # https://libre-soc.org/openpower/sv/remap/discussion TODO
576 "svstep", # https://libre-soc.org/openpower/sv/setvl
578 "slbia", "sld", "slw", "srad", "sradi",
579 "sraw", "srawi", "srd", "srw",
580 "stb", "stbcix", "stbcx", "stbu", "stbux", "stbx",
581 "std", "stdbrx", "stdcx", "stdu", "stdux", "stdx",
582 "stfs", "stfsx", "stfsu", "stfux", "stfsux", # FP store single
583 "stfd", "stfdx", "stfdu", "stfdux", "stfiwx", # FP store double
584 "sth", "sthbrx", "sthcx", "sthu", "sthux", "sthx",
585 "stw", "stwbrx", "stwcx", "stwu", "stwux", "stwx",
586 "subf", "subfc", "subfco", "subfe", "subfeo", "subfic",
587 "subfme", "subfmeo", "subfo", "subfze", "subfzeo",
591 "tlbie", "tlbiel", "tlbsync",
594 "xor", "xori", "xoris",
598 # two-way lookup of instruction-to-index and vice-versa
601 for i
, insn
in enumerate(_insns
):
605 # must be long enough to cover all instructions
606 asmlen
= len(_insns
).bit_length()
608 # Internal Operation numbering. Add new opcodes here (FPADD, FPMUL etc.)
613 OP_ILLEGAL
= 0 # important that this is zero (see power_decoder.py)
687 OP_FPOP
= 77 # temporary: replace with actual ops
688 OP_FPOP_I
= 78 # temporary: replace with actual ops
721 RS
= 4 # for some ALU/Logical operations
724 CIA
= 7 # for addpcis
742 RS
= 13 # for shiftrot (M-Form)
744 CONST_SVD
= 15 # for SVD-Form
745 CONST_SVDS
= 16 # for SVDS-Form
747 CONST_DXHI4
= 18 # for addpcis
748 CONST_DQ
= 19 # for ld/st-quad
755 RB
= 2 # for shiftrot (M-Form)
758 RC
= 5 # for SVP64 bit-reverse LD/ST
759 RT
= 6 # for ternlog[i]
782 # Backward compatibility
787 class LDSTMode(Enum
):
799 RC_ONLY
= 3 # does not include OE
824 class CRIn2Sel(Enum
):
830 class CROutSel(Enum
):
839 # SPRs - Special-Purpose Registers. See V3.0B Figure 18 p971 and
840 # http://libre-riscv.org/openpower/isatables/sprs.csv
841 # http://bugs.libre-riscv.org/show_bug.cgi?id=261
842 # http://bugs.libre-riscv.org/show_bug.cgi?id=859 - KAIVB
844 def get_spr_enum(full_file
):
845 """get_spr_enum - creates an Enum of SPRs, dynamically
846 has the option to reduce the enum to a much shorter list.
847 this saves drastically on the size of the regfile
849 short_list
= {'PIDR', 'DAR', 'PRTBL', 'DSISR', 'SVSRR0', 'SVSTATE',
850 'SVSTATE0', 'SVSTATE1', 'SVSTATE2', 'SVSTATE3',
851 'SPRG0_priv', 'SPRG1_priv', 'SPRG2_priv', 'SPRG3_priv',
852 'SPRG0', 'SPRG1', 'SPRG2', 'SPRG3', 'KAIVB',
853 # hmmm should not be including these, they are FAST regs
854 'CTR', 'LR', 'TAR', 'SRR0', 'SRR1', 'XER', 'DEC', 'TB', 'TBU',
855 'HSRR0', 'HSRR1', 'HSPRG0', 'HSPRG1',
858 for row
in get_csv("sprs.csv"):
859 if full_file
or row
['SPR'] in short_list
:
862 spr_info
= namedtuple('spr_info', 'SPR priv_mtspr priv_mfspr length idx')
866 info
= spr_info(SPR
=row
['SPR'], priv_mtspr
=row
['priv_mtspr'],
867 priv_mfspr
=row
['priv_mfspr'], length
=int(row
['len']),
869 spr_dict
[int(row
['Idx'])] = info
870 spr_byname
[row
['SPR']] = info
871 fields
= [(row
['SPR'], int(row
['Idx'])) for row
in spr_csv
]
872 SPR
= Enum('SPR', fields
)
873 return SPR
, spr_dict
, spr_byname
876 SPRfull
, spr_dict
, spr_byname
= get_spr_enum(full_file
=True)
877 SPRreduced
, _
, _
= get_spr_enum(full_file
=False)
887 MSRSpec
= namedtuple("MSRSpec", ["dr", "pr", "sf"])
889 if __name__
== '__main__':
890 # find out what the heck is in SPR enum :)
891 print("sprs full", len(SPRfull
))
893 print("sprs reduced", len(SPRreduced
))
894 print(dir(SPRreduced
))
896 print(SPRfull
.__members
__['TAR'])
898 print("full", x
, x
.value
, str(x
), x
.name
)
900 print("reduced", x
, x
.value
, str(x
), x
.name
)
902 print("function", Function
.ALU
.name
)