forked from intelxed/xed
-
Notifications
You must be signed in to change notification settings - Fork 0
/
constraint_vec_gen.py
executable file
·191 lines (173 loc) · 7.12 KB
/
constraint_vec_gen.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
#!/usr/bin/env python
# -*- python -*-
#BEGIN_LEGAL
#
#Copyright (c) 2019 Intel Corporation
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
#END_LEGAL
from __future__ import print_function
import copy
import genutil
import encutil
class constraint_vec_gen_t(object):
'''this class receives and list of rules and creates:
(a) tuples that represents each constraint.
(b) the int value of each tuple.
(c) log
'''
def __init__(self,state_space,op_widths,rules,nt_name,default_action,log):
self.state_space = state_space
self.op_widths = op_widths
self.rules = rules
self.nt_name = nt_name
self.default_action = default_action
self.log = log
self.tuple2rule = {}
self.tuple2int = {}
self.tuple2conditions = {}
self.int2tuple = {}
def work(self):
self.cnames = self._capture_cnames()
self._make_tuple2rule()
self._gen_tuple2int()
self.strings_dict = encutil.enc_strings
def _capture_cnames(self):
''' capture the superset of all constraint names '''
if not self.rules:
return []
cnames = set()
for rule in self.rules:
cnames.update(set(rule.cdict.keys()))
cnames = list(cnames)
cnames.sort()
if not cnames:
msg = "XED found rules without any constraints in nt %s"
genutil.die(msg % self.nt_name)
return cnames
def _make_tuple2rule(self):
''' generate the tuple that represents the constraint
e.g.: for the constraint: MODE=0 EASZ=1
the tuple is (0,1)
if a rule does not have constraint over certain operand then
we splatter all the possible values '''
verbose=False
if verbose:
print("_make_tuple2rule")
for rule in self.rules:
#print "\t RULE", str(rule)
# ctup is a list of tuples of all possible value
# combinations for the constraints.
ctup = []
first = True
for cname in self.cnames:
if verbose:
print("CNAME: {}".format(cname))
new_ctup = []
if cname in rule.cdict:
vals = rule.cdict[cname]
if verbose:
print("\tTHIS RULE VALS: {}".format(vals))
else:
vals = self.state_space[cname]
if verbose:
print("\tSTATE SPACE VALS: {}".format(vals))
if first:
first = False
for val in vals:
ctup.append((val,))
if verbose:
print("\tFIRST CTUP: {}".format(ctup))
continue
else:
# cross product of constraints
for val in vals:
for c in ctup:
new_ctup.append(c+(val,))
if verbose:
print("\tNEW_CTUP: {}".format(new_ctup))
ctup = new_ctup
for tupl in ctup:
if tupl not in self.tuple2rule:
if verbose:
print("TUPLE: {} RULE: {}".format(tupl, rule))
self.tuple2rule[tupl] = rule
self.tuple2conditions[tupl] = rule.conditions
else:
err = "in nt {}\n".format(self.nt_name)
err += "generated tuple for constraint {} already exists\n"
err = err.format(str(rule.cdict))
if verbose:
print(err)
genutil.die(err)
def _gen_tuple2int(self):
''' generate the int value of each tuple.
we shift each element by the number of bits that the previous
element took '''
for tuple in self.tuple2rule:
res = 0
bit_shift = 0
for i,byte in enumerate(tuple):
if self.cnames[i] == 'UIMM0':
pass
opwidth = self.op_widths[self.cnames[i]]
res += byte << bit_shift
bit_shift += opwidth
if res not in self.int2tuple:
self.tuple2int[tuple] = res
self.int2tuple[res] = tuple
else:
conflict_tuple = self.int2tuple[res]
err = "conflict in nt: %s\n" % self.nt_name
err += "tuple %s = %s\n"
err =err % (str(tuple),self.tuple2conditions[tuple])
err += "and tuple: %s = %s\n"
err =err % (str(conflict_tuple),
self.tuple2conditions[conflict_tuple])
err += "generate the same int value: %d" % res
genutil.die(err)
def filter_tuples(self,tuples):
''' create new cvg that contains only the tuples in the input '''
new_cdict = copy.copy(self)
new_cdict.tuple2rule = {}
new_cdict.tuple2int = {}
new_cdict.tuple2conditions = {}
for t in tuples:
new_cdict.tuple2rule[t] = self.tuple2rule[t]
new_cdict.tuple2int[t] = self.tuple2int[t]
new_cdict.tuple2conditions[t] = self.tuple2conditions[t]
new_cdict.int2tuple = dict((i,t) for t,i in
new_cdict.tuple2int.items())
return new_cdict
def dump_log(self):
log = "nonterminal: %s\n" % self.nt_name
log += "cnames: %s\n" % str(self.cnames)
log += "{0:5} {1:15} {2}\n".format('int','tuple','conditions')
for val,tuple in sorted(self.int2tuple.items()):
log += "{0:<5} {1:<15} {2}\n".format(val, tuple,
self.tuple2conditions[tuple])
log += "------------------------------------------------------------\n"
self.log.write(log)
def no_constraints(self):
''' return True if there are no constraints '''
return len(self.tuple2conditions) == 0
def get_operand_accessor(self, cname):
''' return the full function in order to access the operand given
in cname '''
str = "%s_get_%s(%s)" % (self.strings_dict['op_accessor'],cname.lower(),
self.strings_dict['obj_str'])
return str, cname
def get_ptrn(self, tuple):
''' return the pattern for the give tuple '''
return self.tuple2rule[tuple]