fix sprset mtspr/mfspr pseudocode with wrong definition of
[openpower-isa.git] / src / openpower / util.py
1 from enum import Enum
2 from fnmatch import fnmatchcase
3 import os
4 import random
5 from openpower.consts import FastRegsEnum, StateRegsEnum
6 from openpower.decoder.power_enums import SPRfull as SPR, spr_dict
7
8
9 # note that we can get away with using SPRfull here because the values
10 # (numerical values) are what is used for lookup.
11 spr_to_fast = {
12 SPR.LR: FastRegsEnum.LR,
13 SPR.CTR: FastRegsEnum.CTR,
14 SPR.SRR0: FastRegsEnum.SRR0,
15 SPR.SRR1: FastRegsEnum.SRR1,
16 SPR.HSRR0: FastRegsEnum.HSRR0,
17 SPR.HSRR1: FastRegsEnum.HSRR1,
18 SPR.SPRG0_priv: FastRegsEnum.SPRG0,
19 SPR.SPRG1_priv: FastRegsEnum.SPRG1,
20 SPR.SPRG2_priv: FastRegsEnum.SPRG2,
21 SPR.SPRG3: FastRegsEnum.SPRG3,
22 SPR.HSPRG0: FastRegsEnum.HSPRG0,
23 SPR.HSPRG1: FastRegsEnum.HSPRG1,
24 SPR.XER: FastRegsEnum.XER,
25 SPR.TAR: FastRegsEnum.TAR,
26 SPR.SVSRR0: FastRegsEnum.SVSRR0,
27 }
28
29 spr_to_state = { SPR.DEC: StateRegsEnum.DEC,
30 SPR.TB: StateRegsEnum.TB,
31 }
32
33 sprstr_to_state = {}
34 state_to_spr = {}
35 for (k, v) in spr_to_state.items():
36 sprstr_to_state[k.name] = v
37 state_to_spr[v] = k
38
39 def state_reg_to_spr(spr_num):
40 return state_to_spr[spr_num].value
41
42
43 def spr_to_state_reg(spr_num):
44 if not isinstance(spr_num, str):
45 spr_num = spr_dict[spr_num].SPR
46 return sprstr_to_state.get(spr_num, None)
47
48
49 sprstr_to_fast = {}
50 fast_to_spr = {}
51 for (k, v) in spr_to_fast.items():
52 sprstr_to_fast[k.name] = v
53 fast_to_spr[v] = k
54
55 def fast_reg_to_spr(spr_num):
56 return fast_to_spr[spr_num].value
57
58
59 def spr_to_fast_reg(spr_num):
60 if not isinstance(spr_num, str):
61 spr_num = spr_dict[spr_num].SPR
62 return sprstr_to_fast.get(spr_num, None)
63
64
65 def slow_reg_to_spr(slow_reg):
66 for i, x in enumerate(SPR):
67 if slow_reg == i:
68 return x.value
69
70
71 def spr_to_slow_reg(spr_num):
72 for i, x in enumerate(SPR):
73 if spr_num == x.value:
74 return i
75
76
77 # TODO: make this a util routine (somewhere)
78 def mask_extend(x, nbits, repeat):
79 res = 0
80 extended = (1<<repeat)-1
81 for i in range(nbits):
82 if x & (1<<i):
83 res |= extended << (i*repeat)
84 return res
85
86
87 # makes a logarithmically-skewed random number
88 def log_rand(n, min_val=1):
89 logrange = random.randint(1, n)
90 return random.randint(min_val, (1 << logrange)-1)
91
92
93 class LogKind(Enum):
94 Default = "default"
95 InstrInOuts = "instr_in_outs"
96 SkipCase = "skip_case"
97
98
99 def parse_log_env_vars():
100 silencelog = os.environ.get("SILENCELOG", None)
101 if silencelog is None:
102 return {k: False for k in LogKind}
103 silencelog = silencelog.lower().split(",")
104 for i, v in enumerate(silencelog):
105 silencelog[i] = v.strip()
106 retval = {k: True for k in LogKind}
107 if len(silencelog) > 1 and silencelog[-1] == "":
108 # allow trailing comma
109 silencelog.pop()
110 if len(silencelog) == 1:
111 if silencelog[0] in ("0", "false"):
112 for k in LogKind:
113 retval[k] = False
114 silencelog.pop()
115 if silencelog[0] in ("1", "true", ""):
116 silencelog.pop()
117 for v in silencelog:
118 silenced = True
119 if v.startswith("!"):
120 v = v[1:]
121 silenced = False
122 matches = False
123 for k in LogKind:
124 if fnmatchcase(k.value, v):
125 matches = True
126 retval[k] = silenced
127 assert matches, (f"SILENCELOG: {v!r} did not match any known LogKind: "
128 f"LogKinds: {' '.join(i.value for i in LogKind)}")
129 # for k, v in retval.items():
130 # print(repr(k), "silenced" if v else "active")
131 return retval
132
133
134
135
136 def log(*args, kind=LogKind.Default, **kwargs):
137 """verbose printing, can be disabled by setting env var "SILENCELOG".
138 """
139 # look up in a dict rather than os.environ so we don't
140 # trigger breakpoints on raising exceptions.
141 # read os.environ so that modifications to os.environ at runtime
142 # are picked up
143 LOG_KINDS_SILENCED = parse_log_env_vars()
144 if LOG_KINDS_SILENCED[kind]:
145 return
146 print(*args, **kwargs)