Look up spr length from spr table
[soc.git] / src / soc / decoder / isa / caller.py
1 from functools import wraps
2 from soc.decoder.orderedset import OrderedSet
3 from soc.decoder.selectable_int import (FieldSelectableInt, SelectableInt,
4 selectconcat)
5 from soc.decoder.power_enums import spr_dict
6 from collections import namedtuple
7 import math
8
9 instruction_info = namedtuple('instruction_info',
10 'func read_regs uninit_regs write_regs ' + \
11 'special_regs op_fields form asmregs')
12
13 special_sprs = {
14 'LR': 8,
15 'CTR': 9,
16 'TAR': 815,
17 'XER': 0,
18 'VRSAVE': 256}
19
20
21 def create_args(reglist, extra=None):
22 args = OrderedSet()
23 for reg in reglist:
24 args.add(reg)
25 args = list(args)
26 if extra:
27 args = [extra] + args
28 return args
29
30
31 class Mem:
32
33 def __init__(self, bytes_per_word=8):
34 self.mem = {}
35 self.bytes_per_word = bytes_per_word
36 self.word_log2 = math.ceil(math.log2(bytes_per_word))
37
38 def _get_shifter_mask(self, width, remainder):
39 shifter = ((self.bytes_per_word - width) - remainder) * \
40 8 # bits per byte
41 mask = (1 << (width * 8)) - 1
42 return shifter, mask
43
44 # TODO: Implement ld/st of lesser width
45 def ld(self, address, width=8):
46 remainder = address & (self.bytes_per_word - 1)
47 address = address >> self.word_log2
48 assert remainder & (width - 1) == 0, "Unaligned access unsupported!"
49 if address in self.mem:
50 val = self.mem[address]
51 else:
52 val = 0
53
54 if width != self.bytes_per_word:
55 shifter, mask = self._get_shifter_mask(width, remainder)
56 val = val & (mask << shifter)
57 val >>= shifter
58 print("Read {:x} from addr {:x}".format(val, address))
59 return val
60
61 def st(self, address, value, width=8):
62 remainder = address & (self.bytes_per_word - 1)
63 address = address >> self.word_log2
64 assert remainder & (width - 1) == 0, "Unaligned access unsupported!"
65 print("Writing {:x} to addr {:x}".format(value, address))
66 if width != self.bytes_per_word:
67 if address in self.mem:
68 val = self.mem[address]
69 else:
70 val = 0
71 shifter, mask = self._get_shifter_mask(width, remainder)
72 val &= ~(mask << shifter)
73 val |= value << shifter
74 self.mem[address] = val
75 else:
76 self.mem[address] = value
77
78 def __call__(self, addr, sz):
79 val = self.ld(addr.value, sz)
80 print ("memread", addr, sz, val)
81 return SelectableInt(val, sz*8)
82
83 def memassign(self, addr, sz, val):
84 print ("memassign", addr, sz, val)
85 self.st(addr.value, val.value, sz)
86
87
88 class GPR(dict):
89 def __init__(self, decoder, regfile):
90 dict.__init__(self)
91 self.sd = decoder
92 for i in range(32):
93 self[i] = SelectableInt(regfile[i], 64)
94
95 def __call__(self, ridx):
96 return self[ridx]
97
98 def set_form(self, form):
99 self.form = form
100
101 def getz(self, rnum):
102 #rnum = rnum.value # only SelectableInt allowed
103 print("GPR getzero", rnum)
104 if rnum == 0:
105 return SelectableInt(0, 64)
106 return self[rnum]
107
108 def _get_regnum(self, attr):
109 getform = self.sd.sigforms[self.form]
110 rnum = getattr(getform, attr)
111 return rnum
112
113 def ___getitem__(self, attr):
114 print("GPR getitem", attr)
115 rnum = self._get_regnum(attr)
116 return self.regfile[rnum]
117
118 def dump(self):
119 for i in range(0, len(self), 8):
120 s = []
121 for j in range(8):
122 s.append("%08x" % self[i+j].value)
123 s = ' '.join(s)
124 print("reg", "%2d" % i, s)
125
126 class PC:
127 def __init__(self, pc_init=0):
128 self.CIA = SelectableInt(pc_init, 64)
129 self.NIA = self.CIA + SelectableInt(4, 64)
130
131 def update(self, namespace):
132 self.CIA = namespace['NIA'].narrow(64)
133 self.NIA = self.CIA + SelectableInt(4, 64)
134 namespace['CIA'] = self.CIA
135 namespace['NIA'] = self.NIA
136
137
138 class SPR(dict):
139 def __init__(self, dec2):
140 self.sd = dec2
141 dict.__init__(self)
142
143 def __getitem__(self, key):
144 # if key in special_sprs get the special spr, otherwise return key
145 if isinstance(key, SelectableInt):
146 key = key.value
147 key = special_sprs.get(key, key)
148 if key in self:
149 return dict.__getitem__(self, key)
150 else:
151 info = spr_dict[key]
152 return SelectableInt(0, info.length)
153
154 def __setitem__(self, key, value):
155 if isinstance(key, SelectableInt):
156 key = key.value
157 key = special_sprs.get(key, key)
158 dict.__setitem__(self, key, value)
159
160 def __call__(self, ridx):
161 return self[ridx]
162
163
164
165 class ISACaller:
166 # decoder2 - an instance of power_decoder2
167 # regfile - a list of initial values for the registers
168 def __init__(self, decoder2, regfile):
169 self.gpr = GPR(decoder2, regfile)
170 self.mem = Mem()
171 self.pc = PC()
172 self.spr = SPR(decoder2)
173 # TODO, needed here:
174 # FPR (same as GPR except for FP nums)
175 # 4.2.2 p124 FPSCR (definitely "separate" - not in SPR)
176 # note that mffs, mcrfs, mtfsf "manage" this FPSCR
177 # 2.3.1 CR (and sub-fields CR0..CR6 - CR0 SO comes from XER.SO)
178 # note that mfocrf, mfcr, mtcr, mtocrf, mcrxrx "manage" CRs
179 # 2.3.2 LR (actually SPR #8)
180 # 2.3.3 CTR (actually SPR #9)
181 # 2.3.4 TAR (actually SPR #815)
182 # 3.2.2 p45 XER (actually SPR #0)
183 # 3.2.3 p46 p232 VRSAVE (actually SPR #256)
184
185 # create CR then allow portions of it to be "selectable" (below)
186 self._cr = SelectableInt(0, 64) # underlying reg
187 self.cr = FieldSelectableInt(self._cr, list(range(32,64)))
188
189 # "undefined", just set to variable-bit-width int (use exts "max")
190 self.undefined = SelectableInt(0, 256) # TODO, not hard-code 256!
191
192 self.namespace = {'GPR': self.gpr,
193 'MEM': self.mem,
194 'SPR': self.spr,
195 'memassign': self.memassign,
196 'NIA': self.pc.NIA,
197 'CIA': self.pc.CIA,
198 'CR': self.cr,
199 'undefined': self.undefined,
200 'mode_is_64bit': True,
201 }
202
203 # field-selectable versions of Condition Register TODO check bitranges?
204 self.crl = []
205 for i in range(8):
206 bits = tuple(range((7-i)*4, (8-i)*4))# errr... maybe?
207 _cr = FieldSelectableInt(self.cr, bits)
208 self.crl.append(_cr)
209 self.namespace["CR%d" % i] = _cr
210
211 self.decoder = decoder2
212
213 def memassign(self, ea, sz, val):
214 self.mem.memassign(ea, sz, val)
215
216 def prep_namespace(self, formname, op_fields):
217 # TODO: get field names from form in decoder*1* (not decoder2)
218 # decoder2 is hand-created, and decoder1.sigform is auto-generated
219 # from spec
220 # then "yield" fields only from op_fields rather than hard-coded
221 # list, here.
222 fields = self.decoder.sigforms[formname]
223 for name in op_fields:
224 if name == 'spr':
225 sig = getattr(fields, name.upper())
226 else:
227 sig = getattr(fields, name)
228 val = yield sig
229 self.namespace[name] = SelectableInt(val, sig.width)
230
231 def call(self, name):
232 # TODO, asmregs is from the spec, e.g. add RT,RA,RB
233 # see http://bugs.libre-riscv.org/show_bug.cgi?id=282
234 info = self.instrs[name]
235 yield from self.prep_namespace(info.form, info.op_fields)
236
237 # preserve order of register names
238 input_names = create_args(list(info.read_regs) + list(info.uninit_regs))
239 print(input_names)
240
241 # main registers (RT, RA ...)
242 inputs = []
243 for name in input_names:
244 regnum = yield getattr(self.decoder, name)
245 regname = "_" + name
246 self.namespace[regname] = regnum
247 print('reading reg %d' % regnum)
248 inputs.append(self.gpr(regnum))
249
250 # "special" registers
251 for special in info.special_regs:
252 if special in special_sprs:
253 inputs.append(self.spr[special])
254 else:
255 inputs.append(self.namespace[special])
256
257 print(inputs)
258 results = info.func(self, *inputs)
259 print(results)
260
261 # any modified return results?
262 if info.write_regs:
263 output_names = create_args(info.write_regs)
264 for name, output in zip(output_names, results):
265 if name in info.special_regs:
266 print('writing special %s' % name, output)
267 if name in special_sprs:
268 self.spr[name] = output
269 else:
270 self.namespace[name].eq(output)
271 else:
272 regnum = yield getattr(self.decoder, name)
273 print('writing reg %d' % regnum)
274 if output.bits > 64:
275 output = SelectableInt(output.value, 64)
276 self.gpr[regnum] = output
277
278 # update program counter
279 self.pc.update(self.namespace)
280
281
282 def inject():
283 """ Decorator factory. """
284 def variable_injector(func):
285 @wraps(func)
286 def decorator(*args, **kwargs):
287 try:
288 func_globals = func.__globals__ # Python 2.6+
289 except AttributeError:
290 func_globals = func.func_globals # Earlier versions.
291
292 context = args[0].namespace
293 saved_values = func_globals.copy() # Shallow copy of dict.
294 func_globals.update(context)
295 result = func(*args, **kwargs)
296 args[0].namespace = func_globals
297 #exec (func.__code__, func_globals)
298
299 #finally:
300 # func_globals = saved_values # Undo changes.
301
302 return result
303
304 return decorator
305
306 return variable_injector
307