cavatools: initialize repository
[cavatools.git] / caveat / crunch_isa.py
1 import re
2 BinaryPattern = re.compile(r'([01]+)')
3 FieldPattern = re.compile(r'([a-zA-Z][a-zA-Z0-9]*)\[([0-9]+)\]')
4 ImmedPattern = re.compile(r'\{(\-?[0-9:|]+)\}')
5 RangePattern = re.compile(r'\|?([0-9]+):([0-9]+)')
6 SinglePattern = re.compile(r'\|?([0-9]+)')
7 ParamPattern = re.compile(r'([a-zA-Z][a-zA-Z0-9_]*)(.*)')
8
9 InsnFile = open('Instructions.def', 'r')
10 df = open('opcodes.h', 'w')
11 rf = open('decode_insn.h', 'w')
12 ef = open('execute_insn.h', 'w')
13 af = open('disasm_insn.h', 'w')
14 kf = open('opcodes_attr.h', 'w')
15
16 Field = {}
17 Opcode = {}
18 Mnemonic = {}
19 OriginalOrder = [ 'Op_zero' ]
20
21 for line in InsnFile:
22 CodeBits = []
23 Param = {}
24 Immed = []
25 signed = False
26 line = line.rstrip('\r\n')
27 # print(line)
28 if line == "" or line[0] != "@":
29 continue
30 line = line[1:]
31 tuples = re.split('\t+', line)
32 if len(tuples) < 5:
33 print(line)
34 print('Bad Line')
35 exit(-1)
36 (bitpattern, mnemonic, assembly, regspecs, action) = tuples
37 # Create opcode bitmask
38 tuples = bitpattern.split()
39 InsnLen = 0
40 for token in tuples:
41 token.strip()
42 m = BinaryPattern.match(token)
43 if m:
44 bits, = m.groups()
45 InsnLen += m.end()
46 CodeBits.append([InsnLen, bits])
47 continue
48 m = FieldPattern.match(token)
49 if m:
50 name, width = m.groups()
51 width = int(width)
52 InsnLen += width
53 Param[name] = [InsnLen, width]
54 continue
55 m = ImmedPattern.match(token)
56 if m:
57 bits, = m.groups()
58 if bits[0] == '-':
59 signed = True
60 bits = bits[1:]
61 while (bits != ""):
62 m = RangePattern.match(bits)
63 if m:
64 high, low = m.groups()
65 high = int(high)
66 low = int(low)
67 bits = bits[m.end():]
68 InsnLen += high-low+1
69 Immed.append([InsnLen, high, low])
70 # print "Range", high, low, bits
71 continue
72 m = SinglePattern.match(bits)
73 if m:
74 where, = m.groups()
75 where = int(where)
76 bits = bits[m.end():]
77 InsnLen += 1
78 Immed.append([InsnLen, where, where])
79 # print "Single", where, bits
80 continue
81 print()
82 print('Bad Token')
83 if not (InsnLen == 16 or InsnLen == 32):
84 print(line)
85 print('Illegal instruction length', InsnLen)
86 exit(-1)
87
88 code = 0
89 mask = 0
90 for pos, bits in CodeBits:
91 pos = InsnLen - pos
92 code |= int(bits, 2) << pos
93 mask |= (2**len(bits)-1) << pos
94
95 for f in Param:
96 Param[f][0] = InsnLen - Param[f][0]
97 if f in Field:
98 if Param[f][0] != Field[f][0] or Param[f][1] != Field[f][1]:
99 print(line)
100 print('Redefinition of field', f)
101 exit(-1)
102 else:
103 Field[f] = Param[f]
104
105 for i in range(0, len(Immed)):
106 Immed[i][0] = InsnLen - Immed[i][0]
107 mnemonic = mnemonic.strip()
108 mnemonic = mnemonic.lower()
109 op = 'Op_' + mnemonic.replace('.', '_')
110 OriginalOrder.append(op)
111 Opcode[op] = [ code, mask, signed, int(InsnLen/8), regspecs.strip(), Immed, action.strip(), assembly.strip() ]
112 Mnemonic[op] = mnemonic
113 InsnFile.close()
114
115 OriginalOrder.append('Op_illegal')
116
117
118 Opcode['Op_zero' ] = (0, 0, False, 0, '-,-,-', 0, '', 'UNKNOWN')
119 Opcode['Op_illegal'] = (0, 0, False, 0, '-,-,-', 0, '', 'ILLEGAL')
120 Mnemonic['Op_zero' ] = 'ZERO'
121 Mnemonic['Op_illegal'] = 'ILLEGAL'
122
123 for op in OriginalOrder:
124 code, mask, signed, len, regspecs, Immed, action, assembly = Opcode[op]
125 tokens = re.split('[,()]', assembly)
126 format = assembly
127 params = ''
128 have_immed = None
129 while tokens:
130 t = tokens.pop(0)
131 if t == '':
132 break
133 if t == 'immed' or t == 'constant':
134 format = format.replace(t, '%d')
135 if t == 'immed':
136 have_immed = ', p->op.immed'
137 else:
138 have_immed = ', p->op_constant'
139 params += have_immed
140 elif t[0] == 'r' or t[0] == 'f':
141 format = format.replace(t, '%s')
142 if t[0] == 'f':
143 t = t.replace('f', 'r')
144 regs = 'regName'
145 t = t.replace('rd', 'p->op_rd')
146 t = t.replace('rs1', 'p->op_rs1')
147 t = t.replace('rs2', 'p->op.rs2')
148 t = t.replace('rs3', 'p->op.rs3')
149 t = t.replace('immed', 'p->op.immed')
150 t = t.replace('constant', 'p->op_constant')
151 params += ', '+regs+'['+t+']'
152 if have_immed:
153 format += ' [0x%x]'
154 params += have_immed
155 af.write(' case {:s}: n += sprintf(buf, \"{:s}\"{:s}); break;\n'.format(op, format, params))
156
157
158 def ExpandField(x):
159 mo = ParamPattern.match(x)
160 if not mo:
161 return x
162 param, expr = mo.groups()
163 if not param in Field:
164 return x
165 pos, width = Field[param]
166 # extract = '((ir>>{:d})&0x{:x})'.format(32-pos-width, 32-width)
167 extract = '((ir>>{:d})&0x{:x})'.format(pos, (1<<width)-1)
168 return extract + expr
169
170 Flags = {}
171 ShortOp = []
172 LongOp = []
173 KonstOp = {}
174 ReadOp = {}
175 WriteOp = {}
176 ThreeOp = {}
177 for op in OriginalOrder:
178 if op == 'Op_zero' or op == 'Op_illegal':
179 continue
180 code, mask, signed, len, regspecs, Immed, action, assembly = Opcode[op]
181 rf.write(' if ((ir&0x{:08x})==0x{:08x}) {{ '.format(mask, code))
182
183 reglist = regspecs.split(',');
184 flagspecs = reglist[0].split(',')[0]
185 for f in flagspecs:
186 Flags[f] = 1
187 if f=='r':
188 ReadOp[op] = 1
189 if f=='w':
190 WriteOp[op] = 1
191 reg = [ '64', '64', '64', '64' ]
192 imm = '0'
193 for i, spec in enumerate(reglist[1:]):
194 if spec == '-':
195 continue
196 spec = spec.replace('cfd+8', 'crd+8+32')
197 spec = spec.replace('ds2+8', 'cs2+8+32')
198 spec = spec.replace('cfs2+8', 'crs2+8+32')
199 spec = spec.replace('fd', 'rd+32')
200 spec = spec.replace('fs1', 'rs1+32')
201 spec = spec.replace('fs2', 'rs2+32')
202 spec = spec.replace('fs3', 'fs3+32')
203 reg[i] = ExpandField(spec)
204 if spec.find('s3') != -1:
205 ThreeOp[op] = 1
206 if Immed:
207 if signed:
208 (pos, hi, lo) = Immed.pop(0)
209 width = hi-lo+1
210 imm += '|(((ir<<{:d})>>{:d})<<{:d})'.format(32-pos-width, 32-width, lo)
211 for (pos, hi, lo) in Immed:
212 width = hi-lo+1
213 mask = (2**width)-1
214 imm += '|(((ir>>{:d})&0x{:x})<<{:d})'.format(pos, mask, lo)
215 if assembly.find('constant') != -1:
216 KonstOp[op] = 1
217 rf.write("*p=fmtC({:s}, {:s}, {:s}, {:s})".format(op, reg[0], reg[1], imm))
218 else:
219 rf.write("*p=fmtR({:s}, {:s}, {:s}, {:s}, {:s}, {:s})".format(op, reg[0], reg[1], reg[2], reg[3], imm))
220 if (Opcode[op][3] == 2):
221 ShortOp.append(op)
222 else:
223 LongOp.append(op)
224 Opcode[op][4] = regspecs;
225 rf.write("; return; }\n")
226
227
228
229 InOrder = [ 'Op_zero' ]
230
231 # 1 short ops with long constants (cannot be memory)
232 for op in ShortOp:
233 if op in KonstOp and op not in ReadOp and op not in WriteOp:
234 if op in ReadOp or op in WriteOp:
235 print("Short op ", op, "in KonstOp and MemOp!")
236 exit(1)
237 InOrder.append(op)
238 lastShortKonstOp = op
239 # 2 short ops not memory read or write operations
240 for op in ShortOp:
241 if op not in ReadOp and op not in WriteOp and op not in KonstOp:
242 InOrder.append(op)
243 # 3 short ops that are memory read operations
244 firstShortMemOp = None
245 for op in ShortOp:
246 if op in ReadOp and op not in WriteOp and op not in KonstOp:
247 InOrder.append(op)
248 if firstShortMemOp == None:
249 firstShortMemOp = op
250 # 4 short ops that are memory write or read-modify-write operations
251 firstWriteOp = None
252 for op in ShortOp:
253 if op in WriteOp and op not in KonstOp:
254 InOrder.append(op)
255 lastShortOp = op
256 if firstWriteOp == None:
257 firstWriteOp = op
258
259 # 5 long ops that are memory write or read-modify-write operations
260 for op in LongOp:
261 if op in WriteOp and op not in KonstOp:
262 InOrder.append(op)
263 lastWriteOp = op
264
265 # 6 long ops that are memory read operations
266 for op in LongOp:
267 if op in ReadOp and op not in WriteOp and op not in KonstOp:
268 InOrder.append(op)
269 lastLongMemOp = op
270
271 # 7 long ops without long constants that do not have three operands
272 for op in LongOp:
273 if op not in ThreeOp and op not in ReadOp and op not in WriteOp and op not in KonstOp:
274 InOrder.append(op)
275
276 # 8 long ops without long constants that do have three operands
277 firstThreeOp = None
278 for op in LongOp:
279 if op in ThreeOp and op not in ReadOp and op not in WriteOp and op not in KonstOp:
280 InOrder.append(op)
281 if firstThreeOp == None:
282 firstThreeOp = op
283
284 # 9 long ops with long constants
285 firstLongKonstOp = None
286 for op in LongOp:
287 if op in KonstOp and op not in ReadOp and op not in WriteOp:
288 InOrder.append(op)
289 if firstLongKonstOp == None:
290 firstLongKonstOp = op
291
292 InOrder.append('Op_illegal')
293
294
295 df.write('enum Opcode_t {')
296 j = 0
297 for op in InOrder:
298 if j % 4 == 0:
299 df.write('\n ')
300 df.write('{:>20s},'.format(op))
301 j += 1
302 df.write('{:>20s},'.format('Number_of_opcodes'))
303 df.write('\n};\n\n')
304
305 df.write('#define validOp(op) (Op_zero < op && op < Op_illegal)\n')
306 df.write('#define shortOp(op) (op <= {:s})\n'.format(lastShortOp))
307 df.write('#define konstOp(op) (op <= {:s} || op >= {:s})\n'.format(lastShortKonstOp, firstLongKonstOp))
308 df.write('#define memOp(op) ({:s} <= op && op <= {:s})\n'.format(firstShortMemOp, lastLongMemOp))
309 df.write('#define writeOp(op) ({:s} <= op && op <= {:s})\n'.format(firstWriteOp, lastWriteOp))
310 df.write('#define threeOp(op) (op >= {:s})\n'.format(firstThreeOp))
311 df.write('\n\n')
312
313 FunctionalUnits = []
314 df.write('enum units_t {')
315 for u in sorted(Flags):
316 if f == '-' or not u.islower():
317 continue
318 unit = 'Unit_'+u
319 FunctionalUnits.append(unit)
320 df.write(' {:s},\n'.format(unit))
321 df.write(' {:s},\n'.format('Number_of_units'))
322 df.write('\n};\n\n')
323
324
325 val = 1
326 for f in sorted(Flags):
327 if f == '-' or f.islower():
328 continue
329 df.write('#define attr_{:s} 0x{:08x}\n'.format(f, val))
330 val = val << 1
331
332 # write opcodes_attr.h
333 for i, op in enumerate(InOrder):
334 init = '{:16s} 0'.format('"'+Mnemonic[op]+'",')
335 flags = Opcode[op][4]
336 flags = flags.split(',')
337 flags = flags[0]
338 for letter in flags:
339 if letter == '-' or letter.islower():
340 continue
341 init += ' | attr_' + letter
342 unit = ''
343 for letter in flags:
344 if letter == '-' or not letter.islower():
345 continue
346 unit += 'Unit_' + letter
347 kf.write(' {{ {:s}, {:s} }},\n'.format(init, unit))
348
349
350 for op in InOrder:
351 if op == 'Op_zero' or op == 'Op_illegal':
352 continue
353 code, mask, signed, len, regspecs, Immed, action, assembly = Opcode[op]
354 action = action.replace('rd', 'p->op_rd')
355 action = action.replace('rs1', 'p->op_rs1')
356 action = action.replace('rs2', 'p->op.rs2')
357 action = action.replace('rs3', 'p->op.rs3')
358 action = action.replace('immed', 'p->op.immed')
359 action = action.replace('constant', 'p->op_constant')
360 ef.write('case {:>20s}: {:s}; INCPC({:d}); break;\n'.format(op, action, len))
361
362 af.close()
363 df.close()
364 rf.close()
365 ef.close()