power_fields: move BitRange to selectable_int
[openpower-isa.git] / src / openpower / decoder / power_fields.py
1 from collections import namedtuple
2
3 from openpower.decoder.power_enums import find_wiki_file as _find_wiki_file
4 from openpower.decoder.selectable_int import BitRange as _BitRange
5
6
7 def decode_instructions(form):
8 res = {}
9 accum = []
10 for l in form:
11 if l.strip().startswith("Formats"):
12 l = l.strip().split(":")[-1]
13 l = l.replace(" ", "")
14 l = l.split(",")
15 for fmt in l:
16 if fmt not in res:
17 res[fmt] = [accum[0]]
18 else:
19 res[fmt].append(accum[0])
20 accum = []
21 else:
22 accum.append(l.strip())
23 return res
24
25
26 def decode_form_header(hdr):
27 res = {}
28 count = 0
29 hdr = hdr.strip()
30 for f in hdr.split("|"):
31 if not f:
32 continue
33 if f[0].isdigit():
34 idx = int(f.strip().split(' ')[0])
35 res[count] = idx
36 count += len(f) + 1
37 return res
38
39
40 def find_unique(d, key):
41 if key not in d:
42 return key
43 idx = 1
44 while "%s_%d" % (key, idx) in d:
45 idx += 1
46 return "%s_%d" % (key, idx)
47
48
49 def decode_line(header, line):
50 line = line.strip()
51 res = {}
52 count = 0
53 prev_fieldname = None
54 for f in line.split("|"):
55 if not f:
56 continue
57 end = count + len(f) + 1
58 fieldname = f.strip()
59 if not fieldname or fieldname.startswith('/'):
60 if prev_fieldname is not None:
61 res[prev_fieldname] = (res[prev_fieldname], header[count])
62 prev_fieldname = None
63 count = end
64 continue
65 bitstart = header[count]
66 if prev_fieldname is not None:
67 res[prev_fieldname] = (res[prev_fieldname], bitstart)
68 res[fieldname] = bitstart
69 count = end
70 prev_fieldname = fieldname
71 res[prev_fieldname] = (bitstart, 32)
72 return res
73
74
75 def decode_form(form):
76 header = decode_form_header(form[0])
77 res = []
78 for line in form[1:]:
79 dec = decode_line(header, line)
80 if dec:
81 res.append(dec)
82 fields = {}
83 falternate = {}
84 for l in res:
85 for k, (start, end) in l.items():
86 if k in fields:
87 if (start, end) == fields[k]:
88 continue # already in and matching for this Form
89 if k in falternate:
90 alternate = "%s_%d" % (k, falternate[k])
91 if (start, end) == fields[alternate]:
92 continue
93 falternate[k] = fidx = falternate.get(k, 0) + 1
94 fields["%s_%d" % (k, fidx)] = (start, end)
95 else:
96 fields[k] = (start, end)
97 return fields
98
99
100 class DecodeFields:
101
102 def __init__(self, bitkls=BitRange, bitargs=(), fname=None,
103 name_on_wiki=None):
104 self.bitkls = bitkls
105 self.bitargs = bitargs
106 if fname is None:
107 assert name_on_wiki is None
108 fname = "fields.txt"
109 name_on_wiki = "fields.text"
110 self.fname = _find_wiki_file(name_on_wiki)
111
112 @property
113 def form_names(self):
114 return self.instrs.keys()
115
116 def create_specs(self):
117 self.forms, self.instrs = self.decode_fields()
118 forms = self.form_names
119 #print ("specs", self.forms, forms)
120 for form in forms:
121 fields = self.instrs[form]
122 fk = fields.keys()
123 Fields = namedtuple("Fields", fk)
124 instr = Fields(**fields)
125 setattr(self, "Form%s" % form, instr)
126 # now add in some commonly-used fields (should be done automatically)
127 # note that these should only be ones which are the same on all Forms
128 # note: these are from microwatt insn_helpers.vhdl
129 self.common_fields = {
130 "PO": self.Formall.PO,
131 "FRS": self.FormX.FRS,
132 "FRT": self.FormX.FRT,
133 "FRA": self.FormX.FRA,
134 "FRB": self.FormX.FRB,
135 "FRC": self.FormA.FRC,
136 "RS": self.FormX.RS,
137 "RT": self.FormX.RT,
138 "RA": self.FormX.RA,
139 "RB": self.FormX.RB,
140 "RC": self.FormVA.RC,
141 "SI": self.FormD.SI,
142 "UI": self.FormD.UI,
143 "L": self.FormD.L,
144 "SH32": self.FormM.SH,
145 "sh": self.FormMD.sh,
146 "MB32": self.FormM.MB,
147 "ME32": self.FormM.ME,
148 "LI": self.FormI.LI,
149 "LK": self.FormI.LK,
150 "AA": self.FormB.AA,
151 "Rc": self.FormX.Rc,
152 "OE": self.FormXO.OE,
153 "BD": self.FormB.BD,
154 "BF": self.FormX.BF,
155 "CR": self.FormXL.XO,
156 "BB": self.FormXL.BB,
157 "BA": self.FormXL.BA,
158 "BT": self.FormXL.BT,
159 "FXM": self.FormXFX.FXM,
160 "BO": self.FormXL.BO,
161 "BI": self.FormXL.BI,
162 "BH": self.FormXL.BH,
163 "D": self.FormD.D,
164 "DS": self.FormDS.DS,
165 "TO": self.FormX.TO,
166 "BC": self.FormA.BC,
167 "SH": self.FormX.SH,
168 "ME": self.FormM.ME,
169 "MB": self.FormM.MB,
170 "SPR": self.FormXFX.SPR}
171 for k, v in self.common_fields.items():
172 setattr(self, k, v)
173
174 def decode_fields(self):
175 with open(self.fname) as f:
176 txt = f.readlines()
177 #print ("decode", txt)
178 forms = {}
179 reading_data = False
180 for l in txt:
181 l = l.strip()
182 if len(l) == 0:
183 continue
184 if reading_data:
185 if l[0] == '#':
186 reading_data = False
187 else:
188 forms[heading].append(l)
189 if not reading_data:
190 assert l[0] == '#'
191 heading = l[1:].strip()
192 # if heading.startswith('1.6.28'): # skip instr fields for now
193 # break
194 heading = heading.split(' ')[-1]
195 reading_data = True
196 forms[heading] = []
197
198 res = {}
199 inst = {}
200
201 for hdr, form in forms.items():
202 if heading == 'Fields':
203 i = decode_instructions(form)
204 for form, field in i.items():
205 inst[form] = self.decode_instruction_fields(field)
206 # else:
207 # res[hdr] = decode_form(form)
208 return res, inst
209
210 def decode_instruction_fields(self, fields):
211 res = {}
212 for field in fields:
213 f, spec = field.strip().split(" ")
214 ss = spec[1:-1].split(",")
215 fs = f.split(",")
216 if len(fs) > 1:
217 individualfields = []
218 for f0, s0 in zip(fs, ss):
219 txt = "%s (%s)" % (f0, s0)
220 individualfields.append(txt)
221 if len(fs) > 1:
222 res.update(self.decode_instruction_fields(
223 individualfields))
224 d = self.bitkls(*self.bitargs)
225 idx = 0
226 for s in ss:
227 s = s.split(':')
228 if len(s) == 1:
229 d[idx] = int(s[0])
230 idx += 1
231 else:
232 start = int(s[0])
233 end = int(s[1])
234 while start <= end:
235 d[idx] = start
236 idx += 1
237 start += 1
238 f = f.replace(",", "_")
239 unique = find_unique(res, f)
240 res[unique] = d
241
242 return res
243
244
245 if __name__ == '__main__':
246 dec = DecodeFields()
247 dec.create_specs()
248 forms, instrs = dec.forms, dec.instrs
249 for form, fields in instrs.items():
250 print("Form", form)
251 for field, bits in fields.items():
252 print("\tfield", field, bits)