-# sigh create little-ended versions of bitfield flags
-from nmigen import Cat
-
-
-def botchify(bekls, lekls, msb=63):
- for attr in dir(bekls):
- if attr[0] == '_':
- continue
- setattr(lekls, attr, msb-getattr(bekls, attr))
+import enum
# Can't think of a better place to put these functions.
return r[field_slice(msb0_start, msb0_end, field_width)]
+# just... don't ask. MSB0 is a massive pain in the neck.
+# this module, aside from creating various field constants,
+# helps out by creating alternative (identical) classes with
+# a "b" name to indicate "MSB0 big-endian".
+class _Const(enum.IntEnum):
+ pass
+
+
+class _ConstLEMeta(enum.EnumMeta):
+ def __call__(metacls, *args, **kwargs):
+ if len(args) > 1:
+ names = args[1]
+ else:
+ names = kwargs.pop("names")
+
+ if isinstance(names, type) and issubclass(names, enum.Enum):
+ names = dict(names.__members__)
+ if isinstance(names, dict):
+ names = tuple(names.items())
+
+ msb = kwargs.pop("msb")
+ names = {key:(msb - value) for (key, value) in names}
+
+ return super().__call__(*args, names=names, **kwargs)
+
+
+class _ConstLE(_Const, metaclass=_ConstLEMeta):
+ pass
+
+
# Listed in V3.0B Book III Chap 4.2.1
# MSR bit numbers, *bigendian* order (PowerISA format)
# use this in the simulator
-class MSRb:
+class MSRb(_Const):
SF = 0 # Sixty-Four bit mode
HV = 3 # Hypervisor state
UND = 5 # Undefined behavior state (see Bk 2, Sect. 3.2.1)
LE = 63 # Little Endian
# use this inside the HDL (where everything is little-endian)
-class MSR:
- pass
+MSR = _ConstLE("MSR", names=MSRb, msb=63)
-botchify(MSRb, MSR)
+# default MSR value for unit tests, since 0 isn't a good default
+DEFAULT_MSR = sum(1 << i for i in (
+ MSR.SF, MSR.HV, MSR.FP, MSR.FE0, MSR.FE1, MSR.RI, MSR.LE))
# Listed in V3.0B Book III 7.5.9 "Program Interrupt"
# to expand traptype to cope with the increased range
# use this in the simulator
-class PIb:
+class PIb(_Const):
INVALID = 33 # 1 for an invalid mem err
PERMERR = 35 # 1 for an permanent mem err
TM_BAD_THING = 42 # 1 for a TM Bad Thing type interrupt
ADR = 47 # 0 if SRR0 = address of instruction causing exception
# and use this in the HDL
-class PI:
- pass
+PI = _ConstLE("PI", names=PIb, msb=63)
-botchify(PIb, PI)
# see traptype (and trap main_stage.py)
# IMPORTANT: when adding extra bits here it is CRITICALLY IMPORTANT
# EXTRA3 3-bit subfield (spec)
-class SPECb:
+class SPECb(_Const):
VEC = 0 # 1 for vector, 0 for scalar
MSB = 1 # augmented register number, MSB
LSB = 2 # augmented register number, LSB
SPEC_SIZE = 3
SPEC_AUG_SIZE = 2 # augmented subfield size (MSB+LSB above)
-class SPEC:
- pass
-botchify(SPECb, SPEC, SPEC_SIZE-1)
+SPEC = _ConstLE("SPEC", names=SPECb, msb=SPEC_SIZE-1)
+
# EXTRA field, with EXTRA2 subfield encoding
-class EXTRA2b:
+class EXTRA2b(_Const):
IDX0_VEC = 0
IDX0_MSB = 1
IDX1_VEC = 2
EXTRA2_SIZE = 9
-class EXTRA2:
- pass
-botchify(EXTRA2b, EXTRA2, EXTRA2_SIZE-1)
+EXTRA2 = _ConstLE("EXTRA2", names=EXTRA2b, msb=EXTRA2_SIZE-1)
+
+# sigh, make these convenience-modifications afterwards (aliases)
+# see RM-2P-1S1D-PU in https://libre-soc.org/openpower/sv/svp64
+EXTRA2b.PACK_en = EXTRA2b.IDX2_VEC
+EXTRA2b.UNPACK_en = EXTRA2b.IDX2_MSB
+EXTRA2.PACK_en = EXTRA2.IDX2_VEC
+EXTRA2.UNPACK_en = EXTRA2.IDX2_MSB
# EXTRA field, with EXTRA3 subfield encoding
CRPred = 4 # TODO: increase when CRs are expanded to 128
-class SVP64MODEb:
+class SVP64MODEb(_Const):
# mode bits
MOD2_MSB = 0
MOD2_LSB = 1
+ MOD3 = 3
+ SEA = 2
# when predicate not set: 0=ignore/skip 1=zero
DZ = 3 # for destination
SZ = 4 # for source
+ ZZ = 3 # for both sz/dz, on all but CR-ops, which, whoops, is RM bit 6.
+ # for branch-conditional
+ BC_SNZ = 3 # for branch-conditional mode
+ BC_VLI = 2 # for VL include/exclude on VLSET mode
+ BC_VLSET = 1 # VLSET mode
+ BC_CTRTEST = 0 # CTR-test mode
# reduce mode
REDUCE = 2 # 0=normal predication 1=reduce mode
- SVM = 3 # subvector reduce mode 0=independent 1=horizontal
CRM = 4 # CR mode on reduce (Rc=1) 0=some 1=all
+ RG = 4 # Reverse-gear on reduce
+ CROP_RG = 3 # Reverse-gear on reduce CR-ops
# saturation mode
N = 2 # saturation signed mode 0=signed 1=unsigned
# ffirst and predicate result modes
INV = 2 # invert CR sense 0=set 1=unset
CR_MSB = 3 # CR bit to update (with Rc=1)
CR_LSB = 4
+ VLI = 0
RC1 = 4 # update CR as if Rc=1 (when Rc=0)
# LD immediate els (element-stride) locations, depending on mode
- ELS_NORMAL = 2
+ ELS_NORMAL = 4
ELS_FFIRST_PRED = 3
- ELS_SAT = 4
+ LDI_PI = 2 # LD-Immediate Post-Increment
+ LDI_FF = 4 # LD-Immediate Fault-First
+ # LDST element-strided
+ LDST_ELS = 0 # Indexed element-strided
+ # LDST VLI for ffirst is in bit 0
+ LDST_VLI = 0
# BO bits
BO_MSB = 2
BO_LSB = 4
SVP64MODE_SIZE = 5
-class SVP64MODE:
- pass
-
+SVP64MODE = _ConstLE("SVP64MODE", names=SVP64MODEb, msb=SVP64MODE_SIZE-1)
-botchify(SVP64MODEb, SVP64MODE, SVP64MODE_SIZE-1)
# add subfields to use with nmutil.sel
SVP64MODE.MOD2 = [0, 1]
# CR sub-fields
-class CRb:
+class CRb(_Const):
LT = 0
GT = 1
EQ = 2
CR_SIZE = 4
-class CR:
- pass
-
-
-botchify(CRb, CR, CR_SIZE-1)
+CR = _ConstLE("CR", names=CRb, msb=CR_SIZE-1)
+
+
+# POWER9 Register Files
+# XXX these are specific to Libre-SOC's decoder. really, they
+# should be in libre-soc. however... long story: because the
+# PowerDecoder2 has been moved to openpower-isa, and its decoding
+# depends on that, then... whoops.
+
+# "State" Regfile
+class StateRegsEnum:
+ PC = 0
+ MSR = 1
+ SVSTATE = 2
+ DEC = 3
+ TB = 4
+ N_REGS = 5 # maximum number of regs
+
+# Fast SPRs Regfile
+class FastRegsEnum:
+ LR = 0
+ CTR = 1
+ SRR0 = 2
+ SRR1 = 3
+ HSRR0 = 4
+ HSRR1 = 5
+ SPRG0 = 6
+ SPRG1 = 7
+ SPRG2 = 8
+ SPRG3 = 9
+ HSPRG0 = 10
+ HSPRG1 = 11
+ XER = 12 # non-XER bits
+ TAR = 13
+ SVSRR0 = 14
+ # only one spare!
+ N_REGS = 15 # maximum number of regs
+
+# XER Regfile
+class XERRegsEnum:
+ SO=0 # this is actually 2-bit but we ignore 1 bit of it
+ CA=1 # CA and CA32
+ OV=2 # OV and OV32
+ N_REGS = 3 # maximum number of regs
+
+
+if __name__ == '__main__':
+ print("EXTRA2 pack", EXTRA2.PACK_en, EXTRA2.PACK_en.value)
+ for field in MSR:
+ if DEFAULT_MSR & (1 << field.value):
+ print(field)