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