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