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