-
Notifications
You must be signed in to change notification settings - Fork 46
/
Copy pathschemaValidator.py
341 lines (303 loc) · 13.1 KB
/
schemaValidator.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
from cerberus import Validator
from riscv_config.warl import warl_interpreter
import riscv_config.constants as constants
import re
import os
class schemaValidator(Validator):
''' Custom validator for schema having the custom rules necessary for implementation and checks.'''
def __init__(self, *args, **kwargs):
global rv32
global rv64
global extensions
global xlen
xlen = kwargs.get('xlen')
if 32 in xlen:
rv32 = True
else:
rv32 = False
if 64 in xlen:
rv64 = True
else:
rv64 = False
super(schemaValidator, self).__init__(*args, **kwargs)
def _check_with_phy_addr(self, field, value):
if rv32 and value > 34:
self._error(field, "Physical address size should not exceed 34 for RV32")
if rv64 and value > 56:
self._error(field, "Physical address size should not exceed 56 for RV64")
def _check_with_cannot_be_false_rv64(self, field, value):
''' Functions ensures that the field cannot be False in rv64 mode'''
if rv64 and not value:
self._error(field, "This field cannot be False")
def _check_with_cannot_be_false_rv32(self, field, value):
''' Functions ensures that the field cannot be False in rv32 mode'''
if rv32 and not value:
self._error(field, "This field cannot be False")
def _check_with_capture_isa_specifics(self, field, value):
'''
Function to extract and store ISA specific information(such as xlen,user
spec version and extensions present)
and check whether the dependencies in ISA extensions are satisfied.
'''
global xlen
global extensions
extension_enc = list("00000000000000000000000000")
if "32" in value:
xlen = 32
ext = value[4:]
elif "64" in value:
xlen = 64
ext = value[4:]
elif "128" in value:
xlen = 128
ext = value[5:]
else:
self._error(field, "Invalid width in ISA.")
#ISA checks
if any(x in value for x in "EI"):
if 'D' in value and not 'F' in value:
self._error(field, "D cannot exist without F.")
if 'Q' in value and not all(x in value for x in "FD"):
self._error(field, "Q cannot exist without F and D.")
if 'F' in value and not "Zicsr" in value:
self._error(field, "F cannot exist without Zicsr.")
if 'Zam' in value and not 'A' in value:
self._error(field, "Zam cannot exist without A.")
if 'N' in value and not 'U' in value:
self._error(field, "N cannot exist without U.")
if 'S' in value and not 'U' in value:
self._error(field, "S cannot exist without U.")
if 'Z' in value and not self.document['User_Spec_Version'] == "2.3":
self._error(
field, "Z is not supported in the User Spec given version.")
else:
self._error(field, "Neither of E or I extensions are present")
#ISA encoding for future use.
for x in "ABCDEFHIJLMNPQSTUVX":
if (x in ext):
extension_enc[25 - int(ord(x) - ord('A'))] = "1"
extensions = int("".join(extension_enc), 2)
extensions = int("".join(extension_enc), 2)
def _check_with_rv32_check(self, field, value):
global xlen
if value:
if not rv32:
self._error(
field,
"Register cannot be implemented in rv32 mode due to unsupported xlen."
)
def _check_with_rv64_check(self, field, value):
global xlen
if value:
if not rv64:
self._error(
field,
"Register cannot be implemented in rv64 mode due to unsupported xlen."
)
def _check_with_max_length(self, field, value):
'''Function to check whether the given value is less than the maximum value that can be stored(2^xlen-1).'''
global xlen
global extensions
maxv = max(xlen)
if value > (2**maxv) - 1:
self._error(field, "Value exceeds max supported length")
def _check_with_xtveccheck(self, field, value):
'''Function to check whether the inputs in range type in mtvec are valid.'''
global xlen
maxv = 2**(xlen - 2)
for list in value:
if (len(list) > 2):
self._error(field,
"Only two values are allowed in each sub list.")
for val in list:
if not (val < maxv):
self._error(field, "Invalid values.")
def _check_with_s_check(self, field, value):
s = 18
check = False
if 'implemented' in value:
if value['implemented']:
check = True
if 'accessible' in value:
if value['accessible']:
check = True
if rv64 and check:
mxl = format(extensions, '#066b')
if (mxl[65 - s:66 - s] != '1'):
self._error(field, "S is not present(64)")
elif rv32 and check:
mxl = format(extensions, '#034b')
if (mxl[33 - s:34 - s] != '1'):
self._error(field, "S is not present(32)")
def _check_with_u_check(self, field, value):
u = 20
check = False
if 'implemented' in value:
if value['implemented']:
check = True
if 'accessible' in value:
if value['accessible']:
check = True
if rv64 and check:
mxl = format(extensions, '#066b')
if (mxl[65 - u:66 - u] != '1'):
self._error(field, "U is not present(64)")
elif rv32 and check:
mxl = format(extensions, '#034b')
if (mxl[33 - u:34 - u] != '1'):
self._error(field, "U is not present(32)")
def _check_with_su_check(self, field, value):
s = 18
u = 20
check = False
if 'implemented' in value:
if value['implemented']:
check = True
if 'accessible' in value:
if value['accessible']:
check = True
if rv64 and check:
mxl = format(extensions, '#066b')
if (mxl[65 - s:66 - s] != '1') and (mxl[65 - u:66 - u] != '1'):
self._error(field, "neither S nor U is not present(64)")
elif rv32 and check:
mxl = format(extensions, '#034b')
if (mxl[33 - s:34 - s] != '1') and (mxl[33 - u:34 - u] != '1'):
self._error(field, "neither S nor U is not present(32)")
def _check_with_reset_ext(self, field, value):
if rv64:
mxl = format(extensions, '#066b')
reset = format(value, '#066b')
if (mxl[40:66] != reset[40:66] ):
self._error(field, "reset value does not match with extensions enabled(64)")
elif rv32 :
mxl = format(extensions, '#034b')
reset = format(value, '#034b')
if (mxl[8:34] != reset[8:34] ):
self._error(field, "reset value does not match with extensions enabled(32)")
def _check_with_sn_check(self, field, value):
s = 18
n = 13
check = False
if 'implemented' in value:
if value['implemented']:
check = True
if 'accessible' in value:
if value['accessible']:
check = True
if rv64 and check:
mxl = format(extensions, '#066b')
if (mxl[65 - s:66 - s] != '1') and (mxl[65 - n:66 - n] != '1'):
self._error(field, "neither S nor N is not present(64)")
elif rv32 and check:
mxl = format(extensions, '#034b')
if (mxl[33 - s:34 - s] != '1') and (mxl[33 - n:34 - n] != '1'):
self._error(field, "neither S nor N is not present(32)")
def _check_with_n_check(self, field, value):
n = 13
check = False
if 'implemented' in value:
if value['implemented']:
check = True
if 'accessible' in value:
if value['accessible']:
check = True
if rv64 and check:
mxl = format(extensions, '#066b')
if (mxl[65 - n:66 - n] != '1'):
self._error(field, "N is not present")
elif rv32 and check:
mxl = format(extensions, '#034b')
if (mxl[33 - n:34 - n] != '1'):
self._error(field, "N is not present")
def _check_with_mdeleg_checks(self, field, value):
if rv32:
if (value['rv32']['accessible'] == True and
(not 'S' in self.document['ISA'] and
not 'N' in self.document['ISA'])):
value['rv32']['accessible'] = False
self._error(field, "S and N are not present(32)")
if rv64:
if (value['rv64']['accessible'] == True and
(not 'S' in self.document['ISA'] and
not 'N' in self.document['ISA'])):
value['rv64']['accessible'] = False
self._error(field, "S and N are not present(64)")
def _check_with_ndeleg_checks(self, field, value):
if rv32:
if (value['rv32']['accessible'] == True and
not 'N' in self.document['ISA']):
value['rv32']['accessible'] = False
self._error(field, "N is not present(32)")
if rv64:
if (value['rv64']['accessible'] == True and
not 'N' in self.document['ISA']):
value['rv64']['accessible'] = False
self._error(field, "N is not present(64)")
def _check_with_xcause_check(self, field, value):
'''Function to verify the inputs for mcause.'''
if (min(value) < 16):
self._error(
field, "Invalid platform specific values for exception cause.")
def _check_with_wr_illegal(self, field, value):
pr = 0
pri = 0
if 'warl' not in value.keys():
return
for i in range(len(value['warl']['legal'])):
if ' -> ' in value['warl']['legal'][i]:
pr = 1
break
if value['warl']['wr_illegal'] != None:
for i in range(len(value['warl']['wr_illegal'])):
split = re.findall(r'^\s*\[(\d)]\s*',
value['warl']['wr_illegal'][i])
if split != []:
pri = 1
break
if value['warl']['dependency_fields'] != []:
l = (len(value['warl']['legal']))
f = 0
for i in range(l):
if "bitmask" in value['warl']['legal'][i]:
f = 1
splits = re.findall(
r'(\[\d\])\s*->\s*.*\s*\[.*\]\s*{}\s*\[.*?[,|:].*?]'.
format("bitmask"), value['warl']['legal'][i])
if value['warl']['wr_illegal'] != None:
for j in range(len(value['warl']['wr_illegal'])):
if splits[0] in value['warl']['wr_illegal'][j]:
self._error(
field,
"illegal value does not exist for the given mode{}(bitmask)"
.format(splits[0]))
if f == 0:
pass
elif value['warl']['dependency_fields'] == [] and pr == 1:
self._error(field, "no mode must exist(legal)")
elif value['warl']['dependency_fields'] == [] and len(
value['warl']['legal']) != 1:
self._error(field, "There should be only one legal value")
elif value['warl']['dependency_fields'] == [] and pri == 1:
self._error(field, "no mode must exist(illlegal)")
# elif value['warl']['dependency_fields'] == [] and len(
# value['warl']['legal']
# ) == 1 and value['warl']['wr_illegal'] != None and "bitmask" in value[
# 'warl']['legal'][0]:
# self._error(field, "illegal value cannot exist for bitmask type")
def _check_with_key_check(self, field, value):
if value['base']['type']['warl']['dependency_fields'] != []:
par = re.split(
"::", value['base']['type']['warl']['dependency_fields'][0])
if not par[1] in value:
self._error(field, " {} not present".format(par[1]))
def _check_with_medeleg_reset(self, field, value):
global xlen
s = format(value, '#{}b'.format(xlen[0] + 2))
if (s[-11:-10]) != '0' and value >= int("0x400", 16):
self._error(field, " 11th bit must be hardwired to 0")
def _check_with_sedeleg_reset(self, field, value):
global xlen
s = format(value, '#{}b'.format(xlen[0] + 2))
if (s[-11:-8]) != '000' and value >= int("400", 16):
self._error(field, " 11,10,9 bits should be hardwired to 0")