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