selectable_int: refactor fields mappings
[openpower-isa.git] / src / openpower / decoder / isa / caller.py
1 # SPDX-License-Identifier: LGPLv3+
2 # Copyright (C) 2020, 2021 Luke Kenneth Casson Leighton <lkcl@lkcl.net>
3 # Copyright (C) 2020 Michael Nolan
4 # Funded by NLnet http://nlnet.nl
5 """core of the python-based POWER9 simulator
6
7 this is part of a cycle-accurate POWER9 simulator. its primary purpose is
8 not speed, it is for both learning and educational purposes, as well as
9 a method of verifying the HDL.
10
11 related bugs:
12
13 * https://bugs.libre-soc.org/show_bug.cgi?id=424
14 """
15
16 import re
17 from nmigen.sim import Settle
18 from functools import wraps
19 from copy import copy, deepcopy
20 from openpower.decoder.orderedset import OrderedSet
21 from openpower.decoder.selectable_int import (
22 SelectableIntMapping,
23 FieldSelectableInt,
24 SelectableInt,
25 selectconcat,
26 )
27 from openpower.decoder.power_enums import (spr_dict, spr_byname, XER_bits,
28 insns, MicrOp,
29 In1Sel, In2Sel, In3Sel,
30 OutSel, CRInSel, CROutSel, LDSTMode,
31 SVP64RMMode, SVP64PredMode,
32 SVP64PredInt, SVP64PredCR,
33 SVP64LDSTmode)
34
35 from openpower.decoder.power_enums import SVPtype
36
37 from openpower.decoder.helpers import (exts, gtu, ltu, undefined,
38 ISACallerHelper, ISAFPHelpers)
39 from openpower.consts import PIb, MSRb # big-endian (PowerISA versions)
40 from openpower.consts import (SVP64MODE,
41 SVP64CROffs,
42 )
43 from openpower.decoder.power_svp64 import SVP64RM, decode_extra
44
45 from openpower.decoder.isa.radixmmu import RADIX
46 from openpower.decoder.isa.mem import Mem, swap_order, MemException
47 from openpower.decoder.isa.svshape import SVSHAPE
48 from openpower.decoder.isa.svstate import SVP64State
49
50
51 from openpower.util import LogKind, log
52
53 from collections import namedtuple
54 import math
55 import sys
56
57 instruction_info = namedtuple('instruction_info',
58 'func read_regs uninit_regs write_regs ' +
59 'special_regs op_fields form asmregs')
60
61 special_sprs = {
62 'LR': 8,
63 'CTR': 9,
64 'TAR': 815,
65 'XER': 1,
66 'VRSAVE': 256}
67
68
69 REG_SORT_ORDER = {
70 # TODO (lkcl): adjust other registers that should be in a particular order
71 # probably CA, CA32, and CR
72 "FRT": 0,
73 "FRA": 0,
74 "FRB": 0,
75 "FRC": 0,
76 "FRS": 0,
77 "RT": 0,
78 "RA": 0,
79 "RB": 0,
80 "RC": 0,
81 "RS": 0,
82 "BI": 0,
83 "CR": 0,
84 "LR": 0,
85 "CTR": 0,
86 "TAR": 0,
87 "MSR": 0,
88 "SVSTATE": 0,
89 "SVSHAPE0": 0,
90 "SVSHAPE1": 0,
91 "SVSHAPE2": 0,
92 "SVSHAPE3": 0,
93
94 "CA": 0,
95 "CA32": 0,
96
97 "overflow": 7, # should definitely be last
98 }
99
100 fregs = ['FRA', 'FRB', 'FRC', 'FRS', 'FRT']
101
102
103 def create_args(reglist, extra=None):
104 retval = list(OrderedSet(reglist))
105 retval.sort(key=lambda reg: REG_SORT_ORDER.get(reg, 0))
106 if extra is not None:
107 return [extra] + retval
108 return retval
109
110
111 class GPR(dict):
112 def __init__(self, decoder, isacaller, svstate, regfile):
113 dict.__init__(self)
114 self.sd = decoder
115 self.isacaller = isacaller
116 self.svstate = svstate
117 for i in range(len(regfile)):
118 self[i] = SelectableInt(regfile[i], 64)
119
120 def __call__(self, ridx):
121 if isinstance(ridx, SelectableInt):
122 ridx = ridx.value
123 return self[ridx]
124
125 def set_form(self, form):
126 self.form = form
127
128 def __setitem__(self, rnum, value):
129 # rnum = rnum.value # only SelectableInt allowed
130 log("GPR setitem", rnum, value)
131 if isinstance(rnum, SelectableInt):
132 rnum = rnum.value
133 dict.__setitem__(self, rnum, value)
134
135 def getz(self, rnum):
136 # rnum = rnum.value # only SelectableInt allowed
137 log("GPR getzero?", rnum)
138 if rnum == 0:
139 return SelectableInt(0, 64)
140 return self[rnum]
141
142 def _get_regnum(self, attr):
143 getform = self.sd.sigforms[self.form]
144 rnum = getattr(getform, attr)
145 return rnum
146
147 def ___getitem__(self, attr):
148 """ XXX currently not used
149 """
150 rnum = self._get_regnum(attr)
151 log("GPR getitem", attr, rnum)
152 return self.regfile[rnum]
153
154 def dump(self, printout=True):
155 res = []
156 for i in range(len(self)):
157 res.append(self[i].value)
158 if printout:
159 for i in range(0, len(res), 8):
160 s = []
161 for j in range(8):
162 s.append("%08x" % res[i+j])
163 s = ' '.join(s)
164 print("reg", "%2d" % i, s)
165 return res
166
167
168 class SPR(dict):
169 def __init__(self, dec2, initial_sprs={}):
170 self.sd = dec2
171 dict.__init__(self)
172 for key, v in initial_sprs.items():
173 if isinstance(key, SelectableInt):
174 key = key.value
175 key = special_sprs.get(key, key)
176 if isinstance(key, int):
177 info = spr_dict[key]
178 else:
179 info = spr_byname[key]
180 if not isinstance(v, SelectableInt):
181 v = SelectableInt(v, info.length)
182 self[key] = v
183
184 def __getitem__(self, key):
185 log("get spr", key)
186 log("dict", self.items())
187 # if key in special_sprs get the special spr, otherwise return key
188 if isinstance(key, SelectableInt):
189 key = key.value
190 if isinstance(key, int):
191 key = spr_dict[key].SPR
192 key = special_sprs.get(key, key)
193 if key == 'HSRR0': # HACK!
194 key = 'SRR0'
195 if key == 'HSRR1': # HACK!
196 key = 'SRR1'
197 if key in self:
198 res = dict.__getitem__(self, key)
199 else:
200 if isinstance(key, int):
201 info = spr_dict[key]
202 else:
203 info = spr_byname[key]
204 dict.__setitem__(self, key, SelectableInt(0, info.length))
205 res = dict.__getitem__(self, key)
206 log("spr returning", key, res)
207 return res
208
209 def __setitem__(self, key, value):
210 if isinstance(key, SelectableInt):
211 key = key.value
212 if isinstance(key, int):
213 key = spr_dict[key].SPR
214 log("spr key", key)
215 key = special_sprs.get(key, key)
216 if key == 'HSRR0': # HACK!
217 self.__setitem__('SRR0', value)
218 if key == 'HSRR1': # HACK!
219 self.__setitem__('SRR1', value)
220 log("setting spr", key, value)
221 dict.__setitem__(self, key, value)
222
223 def __call__(self, ridx):
224 return self[ridx]
225
226 def dump(self, printout=True):
227 res = []
228 keys = list(self.keys())
229 # keys.sort()
230 for k in keys:
231 sprname = spr_dict.get(k, None)
232 if sprname is None:
233 sprname = k
234 else:
235 sprname = sprname.SPR
236 res.append((sprname, self[k].value))
237 if printout:
238 for sprname, value in res:
239 print(" ", sprname, hex(value))
240 return res
241
242
243 class PC:
244 def __init__(self, pc_init=0):
245 self.CIA = SelectableInt(pc_init, 64)
246 self.NIA = self.CIA + SelectableInt(4, 64) # only true for v3.0B!
247
248 def update_nia(self, is_svp64):
249 increment = 8 if is_svp64 else 4
250 self.NIA = self.CIA + SelectableInt(increment, 64)
251
252 def update(self, namespace, is_svp64):
253 """updates the program counter (PC) by 4 if v3.0B mode or 8 if SVP64
254 """
255 self.CIA = namespace['NIA'].narrow(64)
256 self.update_nia(is_svp64)
257 namespace['CIA'] = self.CIA
258 namespace['NIA'] = self.NIA
259
260
261 # SVP64 ReMap field
262 class SVP64RMFields(SelectableIntMapping):
263 """SVP64 RM: https://libre-soc.org/openpower/sv/svp64/"""
264 spr = range(24)
265 mmode = (0,)
266 mask = range(1, 4)
267 elwidth = range(4, 6)
268 ewsrc = range(6, 8)
269 subvl = range(8, 10)
270 extra = range(10, 19)
271 mode = range(19, 24)
272 extra2 = dict(enumerate([
273 range(10, 12),
274 range(12, 14),
275 range(14, 16),
276 range(16, 18),
277 ]))
278 smask = range(16, 19)
279 extra3 = dict(enumerate([
280 range(10, 13),
281 range(13, 16),
282 range(16, 19),
283 ]))
284
285
286
287 SVP64RM_MMODE_SIZE = len(SVP64RMFields.mmode)
288 SVP64RM_MASK_SIZE = len(SVP64RMFields.mask)
289 SVP64RM_ELWIDTH_SIZE = len(SVP64RMFields.elwidth)
290 SVP64RM_EWSRC_SIZE = len(SVP64RMFields.ewsrc)
291 SVP64RM_SUBVL_SIZE = len(SVP64RMFields.subvl)
292 SVP64RM_EXTRA2_SPEC_SIZE = len(SVP64RMFields.extra2[0])
293 SVP64RM_EXTRA3_SPEC_SIZE = len(SVP64RMFields.extra3[0])
294 SVP64RM_SMASK_SIZE = len(SVP64RMFields.smask)
295 SVP64RM_MODE_SIZE = len(SVP64RMFields.mode)
296
297
298 class SVP64PrefixFields(SelectableIntMapping):
299 """SVP64 Prefix: https://libre-soc.org/openpower/sv/svp64/"""
300 insn = range(32)
301 major = range(0, 6)
302 pid = (7, 9)
303 rm = ((6, 8) + tuple(range(10, 32)))
304
305 SV64P_MAJOR_SIZE = len(SVP64PrefixFields.major)
306 SV64P_PID_SIZE = len(SVP64PrefixFields.pid)
307 SV64P_RM_SIZE = len(SVP64PrefixFields.rm)
308
309
310 # CR register fields
311 # See PowerISA Version 3.0 B Book 1
312 # Section 2.3.1 Condition Register pages 30 - 31
313 class CRFields:
314 LT = FL = 0 # negative, less than, floating-point less than
315 GT = FG = 1 # positive, greater than, floating-point greater than
316 EQ = FE = 2 # equal, floating-point equal
317 SO = FU = 3 # summary overflow, floating-point unordered
318
319 def __init__(self, init=0):
320 # rev_cr = int('{:016b}'.format(initial_cr)[::-1], 2)
321 # self.cr = FieldSelectableInt(self._cr, list(range(32, 64)))
322 self.cr = SelectableInt(init, 64) # underlying reg
323 # field-selectable versions of Condition Register TODO check bitranges?
324 self.crl = []
325 for i in range(8):
326 bits = tuple(range(i*4+32, (i+1)*4+32))
327 _cr = FieldSelectableInt(self.cr, bits)
328 self.crl.append(_cr)
329
330 # decode SVP64 predicate integer to reg number and invert
331
332
333 def get_predint(gpr, mask):
334 r10 = gpr(10)
335 r30 = gpr(30)
336 log("get_predint", mask, SVP64PredInt.ALWAYS.value)
337 if mask == SVP64PredInt.ALWAYS.value:
338 return 0xffff_ffff_ffff_ffff # 64 bits of 1
339 if mask == SVP64PredInt.R3_UNARY.value:
340 return 1 << (gpr(3).value & 0b111111)
341 if mask == SVP64PredInt.R3.value:
342 return gpr(3).value
343 if mask == SVP64PredInt.R3_N.value:
344 return ~gpr(3).value
345 if mask == SVP64PredInt.R10.value:
346 return gpr(10).value
347 if mask == SVP64PredInt.R10_N.value:
348 return ~gpr(10).value
349 if mask == SVP64PredInt.R30.value:
350 return gpr(30).value
351 if mask == SVP64PredInt.R30_N.value:
352 return ~gpr(30).value
353
354 # decode SVP64 predicate CR to reg number and invert status
355
356
357 def _get_predcr(mask):
358 if mask == SVP64PredCR.LT.value:
359 return 0, 1
360 if mask == SVP64PredCR.GE.value:
361 return 0, 0
362 if mask == SVP64PredCR.GT.value:
363 return 1, 1
364 if mask == SVP64PredCR.LE.value:
365 return 1, 0
366 if mask == SVP64PredCR.EQ.value:
367 return 2, 1
368 if mask == SVP64PredCR.NE.value:
369 return 2, 0
370 if mask == SVP64PredCR.SO.value:
371 return 3, 1
372 if mask == SVP64PredCR.NS.value:
373 return 3, 0
374
375 # read individual CR fields (0..VL-1), extract the required bit
376 # and construct the mask
377
378
379 def get_predcr(crl, mask, vl):
380 idx, noninv = _get_predcr(mask)
381 mask = 0
382 for i in range(vl):
383 cr = crl[i+SVP64CROffs.CRPred]
384 if cr[idx].value == noninv:
385 mask |= (1 << i)
386 return mask
387
388
389 # TODO, really should just be using PowerDecoder2
390 def get_pdecode_idx_in(dec2, name):
391 op = dec2.dec.op
392 in1_sel = yield op.in1_sel
393 in2_sel = yield op.in2_sel
394 in3_sel = yield op.in3_sel
395 # get the IN1/2/3 from the decoder (includes SVP64 remap and isvec)
396 in1 = yield dec2.e.read_reg1.data
397 in2 = yield dec2.e.read_reg2.data
398 in3 = yield dec2.e.read_reg3.data
399 in1_isvec = yield dec2.in1_isvec
400 in2_isvec = yield dec2.in2_isvec
401 in3_isvec = yield dec2.in3_isvec
402 log("get_pdecode_idx_in in1", name, in1_sel, In1Sel.RA.value,
403 in1, in1_isvec)
404 log("get_pdecode_idx_in in2", name, in2_sel, In2Sel.RB.value,
405 in2, in2_isvec)
406 log("get_pdecode_idx_in in3", name, in3_sel, In3Sel.RS.value,
407 in3, in3_isvec)
408 log("get_pdecode_idx_in FRS in3", name, in3_sel, In3Sel.FRS.value,
409 in3, in3_isvec)
410 log("get_pdecode_idx_in FRB in2", name, in2_sel, In2Sel.FRB.value,
411 in2, in2_isvec)
412 log("get_pdecode_idx_in FRC in3", name, in3_sel, In3Sel.FRC.value,
413 in3, in3_isvec)
414 # identify which regnames map to in1/2/3
415 if name == 'RA':
416 if (in1_sel == In1Sel.RA.value or
417 (in1_sel == In1Sel.RA_OR_ZERO.value and in1 != 0)):
418 return in1, in1_isvec
419 if in1_sel == In1Sel.RA_OR_ZERO.value:
420 return in1, in1_isvec
421 elif name == 'RB':
422 if in2_sel == In2Sel.RB.value:
423 return in2, in2_isvec
424 if in3_sel == In3Sel.RB.value:
425 return in3, in3_isvec
426 # XXX TODO, RC doesn't exist yet!
427 elif name == 'RC':
428 assert False, "RC does not exist yet"
429 elif name == 'RS':
430 if in1_sel == In1Sel.RS.value:
431 return in1, in1_isvec
432 if in2_sel == In2Sel.RS.value:
433 return in2, in2_isvec
434 if in3_sel == In3Sel.RS.value:
435 return in3, in3_isvec
436 elif name == 'FRA':
437 if in1_sel == In1Sel.FRA.value:
438 return in1, in1_isvec
439 elif name == 'FRB':
440 if in2_sel == In2Sel.FRB.value:
441 return in2, in2_isvec
442 elif name == 'FRC':
443 if in3_sel == In3Sel.FRC.value:
444 return in3, in3_isvec
445 elif name == 'FRS':
446 if in1_sel == In1Sel.FRS.value:
447 return in1, in1_isvec
448 if in3_sel == In3Sel.FRS.value:
449 return in3, in3_isvec
450 return None, False
451
452
453 # TODO, really should just be using PowerDecoder2
454 def get_pdecode_cr_in(dec2, name):
455 op = dec2.dec.op
456 in_sel = yield op.cr_in
457 in_bitfield = yield dec2.dec_cr_in.cr_bitfield.data
458 sv_cr_in = yield op.sv_cr_in
459 spec = yield dec2.crin_svdec.spec
460 sv_override = yield dec2.dec_cr_in.sv_override
461 # get the IN1/2/3 from the decoder (includes SVP64 remap and isvec)
462 in1 = yield dec2.e.read_cr1.data
463 cr_isvec = yield dec2.cr_in_isvec
464 log("get_pdecode_cr_in", in_sel, CROutSel.CR0.value, in1, cr_isvec)
465 log(" sv_cr_in", sv_cr_in)
466 log(" cr_bf", in_bitfield)
467 log(" spec", spec)
468 log(" override", sv_override)
469 # identify which regnames map to in / o2
470 if name == 'BI':
471 if in_sel == CRInSel.BI.value:
472 return in1, cr_isvec
473 log("get_pdecode_cr_in not found", name)
474 return None, False
475
476
477 # TODO, really should just be using PowerDecoder2
478 def get_pdecode_cr_out(dec2, name):
479 op = dec2.dec.op
480 out_sel = yield op.cr_out
481 out_bitfield = yield dec2.dec_cr_out.cr_bitfield.data
482 sv_cr_out = yield op.sv_cr_out
483 spec = yield dec2.crout_svdec.spec
484 sv_override = yield dec2.dec_cr_out.sv_override
485 # get the IN1/2/3 from the decoder (includes SVP64 remap and isvec)
486 out = yield dec2.e.write_cr.data
487 o_isvec = yield dec2.o_isvec
488 log("get_pdecode_cr_out", out_sel, CROutSel.CR0.value, out, o_isvec)
489 log(" sv_cr_out", sv_cr_out)
490 log(" cr_bf", out_bitfield)
491 log(" spec", spec)
492 log(" override", sv_override)
493 # identify which regnames map to out / o2
494 if name == 'CR0':
495 if out_sel == CROutSel.CR0.value:
496 return out, o_isvec
497 log("get_pdecode_cr_out not found", name)
498 return None, False
499
500
501 # TODO, really should just be using PowerDecoder2
502 def get_pdecode_idx_out(dec2, name):
503 op = dec2.dec.op
504 out_sel = yield op.out_sel
505 # get the IN1/2/3 from the decoder (includes SVP64 remap and isvec)
506 out = yield dec2.e.write_reg.data
507 o_isvec = yield dec2.o_isvec
508 # identify which regnames map to out / o2
509 if name == 'RA':
510 log("get_pdecode_idx_out", out_sel, OutSel.RA.value, out, o_isvec)
511 if out_sel == OutSel.RA.value:
512 return out, o_isvec
513 elif name == 'RT':
514 log("get_pdecode_idx_out", out_sel, OutSel.RT.value,
515 OutSel.RT_OR_ZERO.value, out, o_isvec,
516 dec2.dec.RT)
517 if out_sel == OutSel.RT.value:
518 return out, o_isvec
519 elif name == 'RT_OR_ZERO':
520 log("get_pdecode_idx_out", out_sel, OutSel.RT.value,
521 OutSel.RT_OR_ZERO.value, out, o_isvec,
522 dec2.dec.RT)
523 if out_sel == OutSel.RT_OR_ZERO.value:
524 return out, o_isvec
525 elif name == 'FRA':
526 log("get_pdecode_idx_out", out_sel, OutSel.FRA.value, out, o_isvec)
527 if out_sel == OutSel.FRA.value:
528 return out, o_isvec
529 elif name == 'FRT':
530 log("get_pdecode_idx_out", out_sel, OutSel.FRT.value,
531 OutSel.FRT.value, out, o_isvec)
532 if out_sel == OutSel.FRT.value:
533 return out, o_isvec
534 log("get_pdecode_idx_out not found", name, out_sel, out, o_isvec)
535 return None, False
536
537
538 # TODO, really should just be using PowerDecoder2
539 def get_pdecode_idx_out2(dec2, name):
540 # check first if register is activated for write
541 op = dec2.dec.op
542 out_sel = yield op.out_sel
543 out = yield dec2.e.write_ea.data
544 o_isvec = yield dec2.o2_isvec
545 out_ok = yield dec2.e.write_ea.ok
546 log("get_pdecode_idx_out2", name, out_sel, out, out_ok, o_isvec)
547 if not out_ok:
548 return None, False
549
550 if name == 'RA':
551 if hasattr(op, "upd"):
552 # update mode LD/ST uses read-reg A also as an output
553 upd = yield op.upd
554 log("get_pdecode_idx_out2", upd, LDSTMode.update.value,
555 out_sel, OutSel.RA.value,
556 out, o_isvec)
557 if upd == LDSTMode.update.value:
558 return out, o_isvec
559 if name == 'FRS':
560 int_op = yield dec2.dec.op.internal_op
561 fft_en = yield dec2.use_svp64_fft
562 # if int_op == MicrOp.OP_FP_MADD.value and fft_en:
563 if fft_en:
564 log("get_pdecode_idx_out2", out_sel, OutSel.FRS.value,
565 out, o_isvec)
566 return out, o_isvec
567 return None, False
568
569
570 class ISACaller(ISACallerHelper, ISAFPHelpers):
571 # decoder2 - an instance of power_decoder2
572 # regfile - a list of initial values for the registers
573 # initial_{etc} - initial values for SPRs, Condition Register, Mem, MSR
574 # respect_pc - tracks the program counter. requires initial_insns
575 def __init__(self, decoder2, regfile, initial_sprs=None, initial_cr=0,
576 initial_mem=None, initial_msr=0,
577 initial_svstate=0,
578 initial_insns=None,
579 fpregfile=None,
580 respect_pc=False,
581 disassembly=None,
582 initial_pc=0,
583 bigendian=False,
584 mmu=False,
585 icachemmu=False):
586
587 self.bigendian = bigendian
588 self.halted = False
589 self.is_svp64_mode = False
590 self.respect_pc = respect_pc
591 if initial_sprs is None:
592 initial_sprs = {}
593 if initial_mem is None:
594 initial_mem = {}
595 if fpregfile is None:
596 fpregfile = [0] * 32
597 if initial_insns is None:
598 initial_insns = {}
599 assert self.respect_pc == False, "instructions required to honor pc"
600
601 log("ISACaller insns", respect_pc, initial_insns, disassembly)
602 log("ISACaller initial_msr", initial_msr)
603
604 # "fake program counter" mode (for unit testing)
605 self.fake_pc = 0
606 disasm_start = 0
607 if not respect_pc:
608 if isinstance(initial_mem, tuple):
609 self.fake_pc = initial_mem[0]
610 disasm_start = self.fake_pc
611 else:
612 disasm_start = initial_pc
613
614 # disassembly: we need this for now (not given from the decoder)
615 self.disassembly = {}
616 if disassembly:
617 for i, code in enumerate(disassembly):
618 self.disassembly[i*4 + disasm_start] = code
619
620 # set up registers, instruction memory, data memory, PC, SPRs, MSR, CR
621 self.svp64rm = SVP64RM()
622 if initial_svstate is None:
623 initial_svstate = 0
624 if isinstance(initial_svstate, int):
625 initial_svstate = SVP64State(initial_svstate)
626 # SVSTATE, MSR and PC
627 self.svstate = initial_svstate
628 self.msr = SelectableInt(initial_msr, 64) # underlying reg
629 self.pc = PC()
630 # GPR FPR SPR registers
631 initial_sprs = deepcopy(initial_sprs) # so as not to get modified
632 self.gpr = GPR(decoder2, self, self.svstate, regfile)
633 self.fpr = GPR(decoder2, self, self.svstate, fpregfile)
634 self.spr = SPR(decoder2, initial_sprs) # initialise SPRs before MMU
635
636 # set up 4 dummy SVSHAPEs if they aren't already set up
637 for i in range(4):
638 sname = 'SVSHAPE%d' % i
639 if sname not in self.spr:
640 val = 0
641 else:
642 val = self.spr[sname].value
643 # make sure it's an SVSHAPE
644 self.spr[sname] = SVSHAPE(val, self.gpr)
645 self.last_op_svshape = False
646
647 # "raw" memory
648 self.mem = Mem(row_bytes=8, initial_mem=initial_mem)
649 self.mem.log_fancy(kind=LogKind.InstrInOuts)
650 self.imem = Mem(row_bytes=4, initial_mem=initial_insns)
651 # MMU mode, redirect underlying Mem through RADIX
652 if mmu:
653 self.mem = RADIX(self.mem, self)
654 if icachemmu:
655 self.imem = RADIX(self.imem, self)
656
657 # TODO, needed here:
658 # FPR (same as GPR except for FP nums)
659 # 4.2.2 p124 FPSCR (definitely "separate" - not in SPR)
660 # note that mffs, mcrfs, mtfsf "manage" this FPSCR
661 # 2.3.1 CR (and sub-fields CR0..CR6 - CR0 SO comes from XER.SO)
662 # note that mfocrf, mfcr, mtcr, mtocrf, mcrxrx "manage" CRs
663 # -- Done
664 # 2.3.2 LR (actually SPR #8) -- Done
665 # 2.3.3 CTR (actually SPR #9) -- Done
666 # 2.3.4 TAR (actually SPR #815)
667 # 3.2.2 p45 XER (actually SPR #1) -- Done
668 # 3.2.3 p46 p232 VRSAVE (actually SPR #256)
669
670 # create CR then allow portions of it to be "selectable" (below)
671 self.cr_fields = CRFields(initial_cr)
672 self.cr = self.cr_fields.cr
673
674 # "undefined", just set to variable-bit-width int (use exts "max")
675 # self.undefined = SelectableInt(0, 256) # TODO, not hard-code 256!
676
677 self.namespace = {}
678 self.namespace.update(self.spr)
679 self.namespace.update({'GPR': self.gpr,
680 'FPR': self.fpr,
681 'MEM': self.mem,
682 'SPR': self.spr,
683 'memassign': self.memassign,
684 'NIA': self.pc.NIA,
685 'CIA': self.pc.CIA,
686 'SVSTATE': self.svstate,
687 'SVSHAPE0': self.spr['SVSHAPE0'],
688 'SVSHAPE1': self.spr['SVSHAPE1'],
689 'SVSHAPE2': self.spr['SVSHAPE2'],
690 'SVSHAPE3': self.spr['SVSHAPE3'],
691 'CR': self.cr,
692 'MSR': self.msr,
693 'undefined': undefined,
694 'mode_is_64bit': True,
695 'SO': XER_bits['SO'],
696 'XLEN': 64 # elwidth overrides, later
697 })
698
699 # update pc to requested start point
700 self.set_pc(initial_pc)
701
702 # field-selectable versions of Condition Register
703 self.crl = self.cr_fields.crl
704 for i in range(8):
705 self.namespace["CR%d" % i] = self.crl[i]
706
707 self.decoder = decoder2.dec
708 self.dec2 = decoder2
709
710 super().__init__(XLEN=self.namespace["XLEN"])
711
712 @property
713 def XLEN(self):
714 return self.namespace["XLEN"]
715
716 def call_trap(self, trap_addr, trap_bit):
717 """calls TRAP and sets up NIA to the new execution location.
718 next instruction will begin at trap_addr.
719 """
720 self.TRAP(trap_addr, trap_bit)
721 self.namespace['NIA'] = self.trap_nia
722 self.pc.update(self.namespace, self.is_svp64_mode)
723
724 def TRAP(self, trap_addr=0x700, trap_bit=PIb.TRAP):
725 """TRAP> saves PC, MSR (and TODO SVSTATE), and updates MSR
726
727 TRAP function is callable from inside the pseudocode itself,
728 hence the default arguments. when calling from inside ISACaller
729 it is best to use call_trap()
730 """
731 # https://bugs.libre-soc.org/show_bug.cgi?id=859
732 kaivb = self.spr['KAIVB'].value
733 msr = self.namespace['MSR'].value
734 log("TRAP:", hex(trap_addr), hex(msr), "kaivb", hex(kaivb))
735 # store CIA(+4?) in SRR0, set NIA to 0x700
736 # store MSR in SRR1, set MSR to um errr something, have to check spec
737 # store SVSTATE (if enabled) in SVSRR0
738 self.spr['SRR0'].value = self.pc.CIA.value
739 self.spr['SRR1'].value = msr
740 if self.is_svp64_mode:
741 self.spr['SVSRR0'] = self.namespace['SVSTATE'].value
742 self.trap_nia = SelectableInt(trap_addr | (kaivb&~0x1fff), 64)
743 self.spr['SRR1'][trap_bit] = 1 # change *copy* of MSR in SRR1
744
745 # set exception bits. TODO: this should, based on the address
746 # in figure 66 p1065 V3.0B and the table figure 65 p1063 set these
747 # bits appropriately. however it turns out that *for now* in all
748 # cases (all trap_addrs) the exact same thing is needed.
749 self.msr[MSRb.IR] = 0
750 self.msr[MSRb.DR] = 0
751 self.msr[MSRb.FE0] = 0
752 self.msr[MSRb.FE1] = 0
753 self.msr[MSRb.EE] = 0
754 self.msr[MSRb.RI] = 0
755 self.msr[MSRb.SF] = 1
756 self.msr[MSRb.TM] = 0
757 self.msr[MSRb.VEC] = 0
758 self.msr[MSRb.VSX] = 0
759 self.msr[MSRb.PR] = 0
760 self.msr[MSRb.FP] = 0
761 self.msr[MSRb.PMM] = 0
762 self.msr[MSRb.TEs] = 0
763 self.msr[MSRb.TEe] = 0
764 self.msr[MSRb.UND] = 0
765 self.msr[MSRb.LE] = 1
766
767 def memassign(self, ea, sz, val):
768 self.mem.memassign(ea, sz, val)
769
770 def prep_namespace(self, insn_name, formname, op_fields):
771 # TODO: get field names from form in decoder*1* (not decoder2)
772 # decoder2 is hand-created, and decoder1.sigform is auto-generated
773 # from spec
774 # then "yield" fields only from op_fields rather than hard-coded
775 # list, here.
776 fields = self.decoder.sigforms[formname]
777 log("prep_namespace", formname, op_fields)
778 for name in op_fields:
779 # CR immediates. deal with separately. needs modifying
780 # pseudocode
781 if self.is_svp64_mode and name in ['BI']: # TODO, more CRs
782 # BI is a 5-bit, must reconstruct the value
783 regnum, is_vec = yield from get_pdecode_cr_in(self.dec2, name)
784 sig = getattr(fields, name)
785 val = yield sig
786 # low 2 LSBs (CR field selector) remain same, CR num extended
787 assert regnum <= 7, "sigh, TODO, 128 CR fields"
788 val = (val & 0b11) | (regnum << 2)
789 else:
790 if name == 'spr':
791 sig = getattr(fields, name.upper())
792 else:
793 sig = getattr(fields, name)
794 val = yield sig
795 # these are all opcode fields involved in index-selection of CR,
796 # and need to do "standard" arithmetic. CR[BA+32] for example
797 # would, if using SelectableInt, only be 5-bit.
798 if name in ['BF', 'BFA', 'BC', 'BA', 'BB', 'BT', 'BI']:
799 self.namespace[name] = val
800 else:
801 self.namespace[name] = SelectableInt(val, sig.width)
802
803 self.namespace['XER'] = self.spr['XER']
804 self.namespace['CA'] = self.spr['XER'][XER_bits['CA']].value
805 self.namespace['CA32'] = self.spr['XER'][XER_bits['CA32']].value
806
807 # add some SVSTATE convenience variables
808 vl = self.svstate.vl
809 srcstep = self.svstate.srcstep
810 self.namespace['VL'] = vl
811 self.namespace['srcstep'] = srcstep
812
813 # sv.bc* need some extra fields
814 if self.is_svp64_mode and insn_name.startswith("sv.bc"):
815 # blegh grab bits manually
816 mode = yield self.dec2.rm_dec.rm_in.mode
817 bc_vlset = (mode & SVP64MODE.BC_VLSET) != 0
818 bc_vli = (mode & SVP64MODE.BC_VLI) != 0
819 bc_snz = (mode & SVP64MODE.BC_SNZ) != 0
820 bc_vsb = yield self.dec2.rm_dec.bc_vsb
821 bc_lru = yield self.dec2.rm_dec.bc_lru
822 bc_gate = yield self.dec2.rm_dec.bc_gate
823 sz = yield self.dec2.rm_dec.pred_sz
824 self.namespace['ALL'] = SelectableInt(bc_gate, 1)
825 self.namespace['VSb'] = SelectableInt(bc_vsb, 1)
826 self.namespace['LRu'] = SelectableInt(bc_lru, 1)
827 self.namespace['VLSET'] = SelectableInt(bc_vlset, 1)
828 self.namespace['VLI'] = SelectableInt(bc_vli, 1)
829 self.namespace['sz'] = SelectableInt(sz, 1)
830 self.namespace['SNZ'] = SelectableInt(bc_snz, 1)
831
832 def handle_carry_(self, inputs, outputs, already_done):
833 inv_a = yield self.dec2.e.do.invert_in
834 if inv_a:
835 inputs[0] = ~inputs[0]
836
837 imm_ok = yield self.dec2.e.do.imm_data.ok
838 if imm_ok:
839 imm = yield self.dec2.e.do.imm_data.data
840 inputs.append(SelectableInt(imm, 64))
841 assert len(outputs) >= 1
842 log("outputs", repr(outputs))
843 if isinstance(outputs, list) or isinstance(outputs, tuple):
844 output = outputs[0]
845 else:
846 output = outputs
847 gts = []
848 for x in inputs:
849 log("gt input", x, output)
850 gt = (gtu(x, output))
851 gts.append(gt)
852 log(gts)
853 cy = 1 if any(gts) else 0
854 log("CA", cy, gts)
855 if not (1 & already_done):
856 self.spr['XER'][XER_bits['CA']] = cy
857
858 log("inputs", already_done, inputs)
859 # 32 bit carry
860 # ARGH... different for OP_ADD... *sigh*...
861 op = yield self.dec2.e.do.insn_type
862 if op == MicrOp.OP_ADD.value:
863 res32 = (output.value & (1 << 32)) != 0
864 a32 = (inputs[0].value & (1 << 32)) != 0
865 if len(inputs) >= 2:
866 b32 = (inputs[1].value & (1 << 32)) != 0
867 else:
868 b32 = False
869 cy32 = res32 ^ a32 ^ b32
870 log("CA32 ADD", cy32)
871 else:
872 gts = []
873 for x in inputs:
874 log("input", x, output)
875 log(" x[32:64]", x, x[32:64])
876 log(" o[32:64]", output, output[32:64])
877 gt = (gtu(x[32:64], output[32:64])) == SelectableInt(1, 1)
878 gts.append(gt)
879 cy32 = 1 if any(gts) else 0
880 log("CA32", cy32, gts)
881 if not (2 & already_done):
882 self.spr['XER'][XER_bits['CA32']] = cy32
883
884 def handle_overflow(self, inputs, outputs, div_overflow):
885 if hasattr(self.dec2.e.do, "invert_in"):
886 inv_a = yield self.dec2.e.do.invert_in
887 if inv_a:
888 inputs[0] = ~inputs[0]
889
890 imm_ok = yield self.dec2.e.do.imm_data.ok
891 if imm_ok:
892 imm = yield self.dec2.e.do.imm_data.data
893 inputs.append(SelectableInt(imm, 64))
894 assert len(outputs) >= 1
895 log("handle_overflow", inputs, outputs, div_overflow)
896 if len(inputs) < 2 and div_overflow is None:
897 return
898
899 # div overflow is different: it's returned by the pseudo-code
900 # because it's more complex than can be done by analysing the output
901 if div_overflow is not None:
902 ov, ov32 = div_overflow, div_overflow
903 # arithmetic overflow can be done by analysing the input and output
904 elif len(inputs) >= 2:
905 output = outputs[0]
906
907 # OV (64-bit)
908 input_sgn = [exts(x.value, x.bits) < 0 for x in inputs]
909 output_sgn = exts(output.value, output.bits) < 0
910 ov = 1 if input_sgn[0] == input_sgn[1] and \
911 output_sgn != input_sgn[0] else 0
912
913 # OV (32-bit)
914 input32_sgn = [exts(x.value, 32) < 0 for x in inputs]
915 output32_sgn = exts(output.value, 32) < 0
916 ov32 = 1 if input32_sgn[0] == input32_sgn[1] and \
917 output32_sgn != input32_sgn[0] else 0
918
919 # now update XER OV/OV32/SO
920 so = self.spr['XER'][XER_bits['SO']]
921 new_so = so | ov # sticky overflow ORs in old with new
922 self.spr['XER'][XER_bits['OV']] = ov
923 self.spr['XER'][XER_bits['OV32']] = ov32
924 self.spr['XER'][XER_bits['SO']] = new_so
925 log(" set overflow", ov, ov32, so, new_so)
926
927 def handle_comparison(self, outputs, cr_idx=0, overflow=None, no_so=False):
928 out = outputs[0]
929 assert isinstance(out, SelectableInt), \
930 "out zero not a SelectableInt %s" % repr(outputs)
931 log("handle_comparison", out.bits, hex(out.value))
932 # TODO - XXX *processor* in 32-bit mode
933 # https://bugs.libre-soc.org/show_bug.cgi?id=424
934 # if is_32bit:
935 # o32 = exts(out.value, 32)
936 # print ("handle_comparison exts 32 bit", hex(o32))
937 out = exts(out.value, out.bits)
938 log("handle_comparison exts", hex(out))
939 # create the three main CR flags, EQ GT LT
940 zero = SelectableInt(out == 0, 1)
941 positive = SelectableInt(out > 0, 1)
942 negative = SelectableInt(out < 0, 1)
943 # get (or not) XER.SO. for setvl this is important *not* to read SO
944 if no_so:
945 SO = SelectableInt(1, 0)
946 else:
947 SO = self.spr['XER'][XER_bits['SO']]
948 log("handle_comparison SO overflow", SO, overflow)
949 # alternative overflow checking (setvl mainly at the moment)
950 if overflow is not None and overflow == 1:
951 SO = SelectableInt(1, 1)
952 # create the four CR field values and set the required CR field
953 cr_field = selectconcat(negative, positive, zero, SO)
954 log("handle_comparison cr_field", self.cr, cr_idx, cr_field)
955 self.crl[cr_idx].eq(cr_field)
956
957 def set_pc(self, pc_val):
958 self.namespace['NIA'] = SelectableInt(pc_val, 64)
959 self.pc.update(self.namespace, self.is_svp64_mode)
960
961 def get_next_insn(self):
962 """check instruction
963 """
964 if self.respect_pc:
965 pc = self.pc.CIA.value
966 else:
967 pc = self.fake_pc
968 ins = self.imem.ld(pc, 4, False, True, instr_fetch=True)
969 if ins is None:
970 raise KeyError("no instruction at 0x%x" % pc)
971 return pc, ins
972
973 def setup_one(self):
974 """set up one instruction
975 """
976 pc, insn = self.get_next_insn()
977 yield from self.setup_next_insn(pc, insn)
978
979 def setup_next_insn(self, pc, ins):
980 """set up next instruction
981 """
982 self._pc = pc
983 log("setup: 0x%x 0x%x %s" % (pc, ins & 0xffffffff, bin(ins)))
984 log("CIA NIA", self.respect_pc, self.pc.CIA.value, self.pc.NIA.value)
985
986 yield self.dec2.sv_rm.eq(0)
987 yield self.dec2.dec.raw_opcode_in.eq(ins & 0xffffffff)
988 yield self.dec2.dec.bigendian.eq(self.bigendian)
989 yield self.dec2.state.msr.eq(self.msr.value)
990 yield self.dec2.state.pc.eq(pc)
991 if self.svstate is not None:
992 yield self.dec2.state.svstate.eq(self.svstate.value)
993
994 # SVP64. first, check if the opcode is EXT001, and SVP64 id bits set
995 yield Settle()
996 opcode = yield self.dec2.dec.opcode_in
997 pfx = SVP64PrefixFields(opcode)
998 major = pfx.major.asint(msb0=True) # MSB0 inversion
999 log("prefix test: opcode:", major, bin(major),
1000 pfx.insn[7] == 0b1, pfx.insn[9] == 0b1)
1001 self.is_svp64_mode = ((major == 0b000001) and
1002 pfx.insn[7].value == 0b1 and
1003 pfx.insn[9].value == 0b1)
1004 self.pc.update_nia(self.is_svp64_mode)
1005 # set SVP64 decode
1006 yield self.dec2.is_svp64_mode.eq(self.is_svp64_mode)
1007 self.namespace['NIA'] = self.pc.NIA
1008 self.namespace['SVSTATE'] = self.svstate
1009 if not self.is_svp64_mode:
1010 return
1011
1012 # in SVP64 mode. decode/print out svp64 prefix, get v3.0B instruction
1013 log("svp64.rm", bin(pfx.rm.asint(msb0=True)))
1014 log(" svstate.vl", self.svstate.vl)
1015 log(" svstate.mvl", self.svstate.maxvl)
1016 sv_rm = pfx.rm.asint(msb0=True)
1017 ins = self.imem.ld(pc+4, 4, False, True, instr_fetch=True)
1018 log(" svsetup: 0x%x 0x%x %s" % (pc+4, ins & 0xffffffff, bin(ins)))
1019 yield self.dec2.dec.raw_opcode_in.eq(ins & 0xffffffff) # v3.0B suffix
1020 yield self.dec2.sv_rm.eq(sv_rm) # svp64 prefix
1021 yield Settle()
1022
1023 def execute_one(self):
1024 """execute one instruction
1025 """
1026 # get the disassembly code for this instruction
1027 if self.is_svp64_mode:
1028 if not self.disassembly:
1029 code = yield from self.get_assembly_name()
1030 else:
1031 code = self.disassembly[self._pc+4]
1032 log(" svp64 sim-execute", hex(self._pc), code)
1033 else:
1034 if not self.disassembly:
1035 code = yield from self.get_assembly_name()
1036 else:
1037 code = self.disassembly[self._pc]
1038 log("sim-execute", hex(self._pc), code)
1039 opname = code.split(' ')[0]
1040 try:
1041 yield from self.call(opname) # execute the instruction
1042 except MemException as e: # check for memory errors
1043 if e.args[0] == 'unaligned': # alignment error
1044 # run a Trap but set DAR first
1045 print("memory unaligned exception, DAR", e.dar)
1046 self.spr['DAR'] = SelectableInt(e.dar, 64)
1047 self.call_trap(0x600, PIb.PRIV) # 0x600, privileged
1048 return
1049 elif e.args[0] == 'invalid': # invalid
1050 # run a Trap but set DAR first
1051 log("RADIX MMU memory invalid error, mode %s" % e.mode)
1052 if e.mode == 'EXECUTE':
1053 # XXX TODO: must set a few bits in SRR1,
1054 # see microwatt loadstore1.vhdl
1055 # if m_in.segerr = '0' then
1056 # v.srr1(47 - 33) := m_in.invalid;
1057 # v.srr1(47 - 35) := m_in.perm_error; -- noexec fault
1058 # v.srr1(47 - 44) := m_in.badtree;
1059 # v.srr1(47 - 45) := m_in.rc_error;
1060 # v.intr_vec := 16#400#;
1061 # else
1062 # v.intr_vec := 16#480#;
1063 self.call_trap(0x400, PIb.PRIV) # 0x400, privileged
1064 else:
1065 self.call_trap(0x300, PIb.PRIV) # 0x300, privileged
1066 return
1067 # not supported yet:
1068 raise e # ... re-raise
1069
1070 # don't use this except in special circumstances
1071 if not self.respect_pc:
1072 self.fake_pc += 4
1073
1074 log("execute one, CIA NIA", hex(self.pc.CIA.value),
1075 hex(self.pc.NIA.value))
1076
1077 def get_assembly_name(self):
1078 # TODO, asmregs is from the spec, e.g. add RT,RA,RB
1079 # see http://bugs.libre-riscv.org/show_bug.cgi?id=282
1080 dec_insn = yield self.dec2.e.do.insn
1081 insn_1_11 = yield self.dec2.e.do.insn[1:11]
1082 asmcode = yield self.dec2.dec.op.asmcode
1083 int_op = yield self.dec2.dec.op.internal_op
1084 log("get assembly name asmcode", asmcode, int_op,
1085 hex(dec_insn), bin(insn_1_11))
1086 asmop = insns.get(asmcode, None)
1087
1088 # sigh reconstruct the assembly instruction name
1089 if hasattr(self.dec2.e.do, "oe"):
1090 ov_en = yield self.dec2.e.do.oe.oe
1091 ov_ok = yield self.dec2.e.do.oe.ok
1092 else:
1093 ov_en = False
1094 ov_ok = False
1095 if hasattr(self.dec2.e.do, "rc"):
1096 rc_en = yield self.dec2.e.do.rc.rc
1097 rc_ok = yield self.dec2.e.do.rc.ok
1098 else:
1099 rc_en = False
1100 rc_ok = False
1101 # grrrr have to special-case MUL op (see DecodeOE)
1102 log("ov %d en %d rc %d en %d op %d" %
1103 (ov_ok, ov_en, rc_ok, rc_en, int_op))
1104 if int_op in [MicrOp.OP_MUL_H64.value, MicrOp.OP_MUL_H32.value]:
1105 log("mul op")
1106 if rc_en & rc_ok:
1107 asmop += "."
1108 else:
1109 if not asmop.endswith("."): # don't add "." to "andis."
1110 if rc_en & rc_ok:
1111 asmop += "."
1112 if hasattr(self.dec2.e.do, "lk"):
1113 lk = yield self.dec2.e.do.lk
1114 if lk:
1115 asmop += "l"
1116 log("int_op", int_op)
1117 if int_op in [MicrOp.OP_B.value, MicrOp.OP_BC.value]:
1118 AA = yield self.dec2.dec.fields.FormI.AA[0:-1]
1119 log("AA", AA)
1120 if AA:
1121 asmop += "a"
1122 spr_msb = yield from self.get_spr_msb()
1123 if int_op == MicrOp.OP_MFCR.value:
1124 if spr_msb:
1125 asmop = 'mfocrf'
1126 else:
1127 asmop = 'mfcr'
1128 # XXX TODO: for whatever weird reason this doesn't work
1129 # https://bugs.libre-soc.org/show_bug.cgi?id=390
1130 if int_op == MicrOp.OP_MTCRF.value:
1131 if spr_msb:
1132 asmop = 'mtocrf'
1133 else:
1134 asmop = 'mtcrf'
1135 return asmop
1136
1137 def get_remap_indices(self):
1138 """WARNING, this function stores remap_idxs and remap_loopends
1139 in the class for later use. this to avoid problems with yield
1140 """
1141 # go through all iterators in lock-step, advance to next remap_idx
1142 srcstep, dststep, ssubstep, dsubstep = self.get_src_dststeps()
1143 # get four SVSHAPEs. here we are hard-coding
1144 SVSHAPE0 = self.spr['SVSHAPE0']
1145 SVSHAPE1 = self.spr['SVSHAPE1']
1146 SVSHAPE2 = self.spr['SVSHAPE2']
1147 SVSHAPE3 = self.spr['SVSHAPE3']
1148 # set up the iterators
1149 remaps = [(SVSHAPE0, SVSHAPE0.get_iterator()),
1150 (SVSHAPE1, SVSHAPE1.get_iterator()),
1151 (SVSHAPE2, SVSHAPE2.get_iterator()),
1152 (SVSHAPE3, SVSHAPE3.get_iterator()),
1153 ]
1154
1155 self.remap_loopends = [0] * 4
1156 self.remap_idxs = [0, 1, 2, 3]
1157 dbg = []
1158 for i, (shape, remap) in enumerate(remaps):
1159 # zero is "disabled"
1160 if shape.value == 0x0:
1161 self.remap_idxs[i] = 0
1162 # pick src or dststep depending on reg num (0-2=in, 3-4=out)
1163 step = dststep if (i in [3, 4]) else srcstep
1164 # this is terrible. O(N^2) looking for the match. but hey.
1165 for idx, (remap_idx, loopends) in enumerate(remap):
1166 if idx == step:
1167 break
1168 self.remap_idxs[i] = remap_idx
1169 self.remap_loopends[i] = loopends
1170 dbg.append((i, step, remap_idx, loopends))
1171 for (i, step, remap_idx, loopends) in dbg:
1172 log("SVSHAPE %d idx, end" % i, step, remap_idx, bin(loopends))
1173 return remaps
1174
1175 def get_spr_msb(self):
1176 dec_insn = yield self.dec2.e.do.insn
1177 return dec_insn & (1 << 20) != 0 # sigh - XFF.spr[-1]?
1178
1179 def call(self, name):
1180 """call(opcode) - the primary execution point for instructions
1181 """
1182 self.last_st_addr = None # reset the last known store address
1183 self.last_ld_addr = None # etc.
1184
1185 ins_name = name.strip() # remove spaces if not already done so
1186 if self.halted:
1187 log("halted - not executing", ins_name)
1188 return
1189
1190 # TODO, asmregs is from the spec, e.g. add RT,RA,RB
1191 # see http://bugs.libre-riscv.org/show_bug.cgi?id=282
1192 asmop = yield from self.get_assembly_name()
1193 log("call", ins_name, asmop)
1194
1195 # check privileged
1196 int_op = yield self.dec2.dec.op.internal_op
1197 spr_msb = yield from self.get_spr_msb()
1198
1199 instr_is_privileged = False
1200 if int_op in [MicrOp.OP_ATTN.value,
1201 MicrOp.OP_MFMSR.value,
1202 MicrOp.OP_MTMSR.value,
1203 MicrOp.OP_MTMSRD.value,
1204 # TODO: OP_TLBIE
1205 MicrOp.OP_RFID.value]:
1206 instr_is_privileged = True
1207 if int_op in [MicrOp.OP_MFSPR.value,
1208 MicrOp.OP_MTSPR.value] and spr_msb:
1209 instr_is_privileged = True
1210
1211 log("is priv", instr_is_privileged, hex(self.msr.value),
1212 self.msr[MSRb.PR])
1213 # check MSR priv bit and whether op is privileged: if so, throw trap
1214 if instr_is_privileged and self.msr[MSRb.PR] == 1:
1215 self.call_trap(0x700, PIb.PRIV)
1216 return
1217
1218 # check halted condition
1219 if ins_name == 'attn':
1220 self.halted = True
1221 return
1222
1223 # check illegal instruction
1224 illegal = False
1225 if ins_name not in ['mtcrf', 'mtocrf']:
1226 illegal = ins_name != asmop
1227
1228 # list of instructions not being supported by binutils (.long)
1229 dotstrp = asmop[:-1] if asmop[-1] == '.' else asmop
1230 if dotstrp in [ 'fsins', 'fcoss',
1231 'ffmadds', 'fdmadds', 'ffadds',
1232 'mins', 'maxs', 'minu', 'maxu',
1233 'setvl', 'svindex', 'svremap', 'svstep', 'svshape',
1234 'grev', 'ternlogi', 'bmask', 'cprop',
1235 'absdu', 'absds', 'absdacs', 'absdacu', 'avgadd',
1236 'fmvis', 'fishmv',
1237 ]:
1238 illegal = False
1239 ins_name = dotstrp
1240
1241 # branch-conditional redirects to sv.bc
1242 if asmop.startswith('bc') and self.is_svp64_mode:
1243 ins_name = 'sv.%s' % ins_name
1244
1245 log(" post-processed name", dotstrp, ins_name, asmop)
1246
1247 # illegal instructions call TRAP at 0x700
1248 if illegal:
1249 print("illegal", ins_name, asmop)
1250 self.call_trap(0x700, PIb.ILLEG)
1251 print("name %s != %s - calling ILLEGAL trap, PC: %x" %
1252 (ins_name, asmop, self.pc.CIA.value))
1253 return
1254
1255 # this is for setvl "Vertical" mode: if set true,
1256 # srcstep/dststep is explicitly advanced. mode says which SVSTATE to
1257 # test for Rc=1 end condition. 3 bits of all 3 loops are put into CR0
1258 self.allow_next_step_inc = False
1259 self.svstate_next_mode = 0
1260
1261 # nop has to be supported, we could let the actual op calculate
1262 # but PowerDecoder has a pattern for nop
1263 if ins_name == 'nop':
1264 self.update_pc_next()
1265 return
1266
1267 # look up instruction in ISA.instrs, prepare namespace
1268 info = self.instrs[ins_name]
1269 yield from self.prep_namespace(ins_name, info.form, info.op_fields)
1270
1271 # preserve order of register names
1272 input_names = create_args(list(info.read_regs) +
1273 list(info.uninit_regs))
1274 log("input names", input_names)
1275
1276 # get SVP64 entry for the current instruction
1277 sv_rm = self.svp64rm.instrs.get(ins_name)
1278 if sv_rm is not None:
1279 dest_cr, src_cr, src_byname, dest_byname = decode_extra(sv_rm)
1280 else:
1281 dest_cr, src_cr, src_byname, dest_byname = False, False, {}, {}
1282 log("sv rm", sv_rm, dest_cr, src_cr, src_byname, dest_byname)
1283
1284 # see if srcstep/dststep need skipping over masked-out predicate bits
1285 if (self.is_svp64_mode or ins_name == 'setvl' or
1286 ins_name in ['svremap', 'svstate']):
1287 yield from self.svstate_pre_inc()
1288 if self.is_svp64_mode:
1289 pre = yield from self.update_new_svstate_steps()
1290 if pre:
1291 self.svp64_reset_loop()
1292 self.update_nia()
1293 self.update_pc_next()
1294 return
1295 srcstep, dststep, ssubstep, dsubstep = self.get_src_dststeps()
1296 pred_dst_zero = self.pred_dst_zero
1297 pred_src_zero = self.pred_src_zero
1298 vl = self.svstate.vl
1299 subvl = yield self.dec2.rm_dec.rm_in.subvl
1300
1301 # VL=0 in SVP64 mode means "do nothing: skip instruction"
1302 if self.is_svp64_mode and vl == 0:
1303 self.pc.update(self.namespace, self.is_svp64_mode)
1304 log("SVP64: VL=0, end of call", self.namespace['CIA'],
1305 self.namespace['NIA'], kind=LogKind.InstrInOuts)
1306 return
1307
1308 # for when SVREMAP is active, using pre-arranged schedule.
1309 # note: modifying PowerDecoder2 needs to "settle"
1310 remap_en = self.svstate.SVme
1311 persist = self.svstate.RMpst
1312 active = (persist or self.last_op_svshape) and remap_en != 0
1313 if self.is_svp64_mode:
1314 yield self.dec2.remap_active.eq(remap_en if active else 0)
1315 yield Settle()
1316 if persist or self.last_op_svshape:
1317 remaps = self.get_remap_indices()
1318 if self.is_svp64_mode and (persist or self.last_op_svshape):
1319 yield from self.remap_debug(remaps)
1320 # after that, settle down (combinatorial) to let Vector reg numbers
1321 # work themselves out
1322 yield Settle()
1323 if self.is_svp64_mode:
1324 remap_active = yield self.dec2.remap_active
1325 else:
1326 remap_active = False
1327 log("remap active", bin(remap_active))
1328
1329 # main input registers (RT, RA ...)
1330 inputs = []
1331 for name in input_names:
1332 log("name", name)
1333 regval = (yield from self.get_input(name))
1334 log("regval", regval)
1335 inputs.append(regval)
1336
1337 # arrrrgh, awful hack, to get _RT into namespace
1338 if ins_name in ['setvl', 'svstep']:
1339 regname = "_RT"
1340 RT = yield self.dec2.dec.RT
1341 self.namespace[regname] = SelectableInt(RT, 5)
1342 if RT == 0:
1343 self.namespace["RT"] = SelectableInt(0, 5)
1344 regnum, is_vec = yield from get_pdecode_idx_out(self.dec2, "RT")
1345 log('hack input reg %s %s' % (name, str(regnum)), is_vec)
1346
1347 # in SVP64 mode for LD/ST work out immediate
1348 # XXX TODO: replace_ds for DS-Form rather than D-Form.
1349 # use info.form to detect
1350 if self.is_svp64_mode:
1351 yield from self.check_replace_d(info, remap_active)
1352
1353 # "special" registers
1354 for special in info.special_regs:
1355 if special in special_sprs:
1356 inputs.append(self.spr[special])
1357 else:
1358 inputs.append(self.namespace[special])
1359
1360 # clear trap (trap) NIA
1361 self.trap_nia = None
1362
1363 # check if this was an sv.bc* and create an indicator that
1364 # this is the last check to be made as a loop. combined with
1365 # the ALL/ANY mode we can early-exit
1366 if self.is_svp64_mode and ins_name.startswith("sv.bc"):
1367 no_in_vec = yield self.dec2.no_in_vec # BI is scalar
1368 end_loop = no_in_vec or srcstep == vl-1 or dststep == vl-1
1369 self.namespace['end_loop'] = SelectableInt(end_loop, 1)
1370
1371 # execute actual instruction here (finally)
1372 log("inputs", inputs)
1373 results = info.func(self, *inputs)
1374 log("results", results)
1375
1376 # "inject" decorator takes namespace from function locals: we need to
1377 # overwrite NIA being overwritten (sigh)
1378 if self.trap_nia is not None:
1379 self.namespace['NIA'] = self.trap_nia
1380
1381 log("after func", self.namespace['CIA'], self.namespace['NIA'])
1382
1383 # check if op was a LD/ST so that debugging can check the
1384 # address
1385 if int_op in [MicrOp.OP_STORE.value,
1386 ]:
1387 self.last_st_addr = self.mem.last_st_addr
1388 if int_op in [MicrOp.OP_LOAD.value,
1389 ]:
1390 self.last_ld_addr = self.mem.last_ld_addr
1391 log("op", int_op, MicrOp.OP_STORE.value, MicrOp.OP_LOAD.value,
1392 self.last_st_addr, self.last_ld_addr)
1393
1394 # detect if CA/CA32 already in outputs (sra*, basically)
1395 already_done = 0
1396 if info.write_regs:
1397 output_names = create_args(info.write_regs)
1398 for name in output_names:
1399 if name == 'CA':
1400 already_done |= 1
1401 if name == 'CA32':
1402 already_done |= 2
1403
1404 log("carry already done?", bin(already_done))
1405 if hasattr(self.dec2.e.do, "output_carry"):
1406 carry_en = yield self.dec2.e.do.output_carry
1407 else:
1408 carry_en = False
1409 if carry_en:
1410 yield from self.handle_carry_(inputs, results, already_done)
1411
1412 # check if one of the regs was named "overflow"
1413 overflow = None
1414 if info.write_regs:
1415 for name, output in zip(output_names, results):
1416 if name == 'overflow':
1417 overflow = output
1418
1419 if not self.is_svp64_mode: # yeah just no. not in parallel processing
1420 # detect if overflow was in return result
1421 if hasattr(self.dec2.e.do, "oe"):
1422 ov_en = yield self.dec2.e.do.oe.oe
1423 ov_ok = yield self.dec2.e.do.oe.ok
1424 else:
1425 ov_en = False
1426 ov_ok = False
1427 log("internal overflow", ins_name, overflow, "en?", ov_en, ov_ok)
1428 if ov_en & ov_ok:
1429 yield from self.handle_overflow(inputs, results, overflow)
1430
1431 # only do SVP64 dest predicated Rc=1 if dest-pred is not enabled
1432 rc_en = False
1433 if not self.is_svp64_mode or not pred_dst_zero:
1434 if hasattr(self.dec2.e.do, "rc"):
1435 rc_en = yield self.dec2.e.do.rc.rc
1436 if rc_en and ins_name not in ['svstep']:
1437 regnum, is_vec = yield from get_pdecode_cr_out(self.dec2, "CR0")
1438 cmps = results
1439 # hang on... for `setvl` actually you want to test SVSTATE.VL
1440 is_setvl = ins_name == 'setvl'
1441 if is_setvl:
1442 vl = results[0].vl
1443 cmps = (SelectableInt(vl, 64), overflow,)
1444 self.handle_comparison(cmps, regnum, overflow, no_so=is_setvl)
1445
1446 # any modified return results?
1447 if info.write_regs:
1448 for name, output in zip(output_names, results):
1449 yield from self.check_write(info, name, output, carry_en)
1450
1451 nia_update = (yield from self.check_step_increment(results, rc_en,
1452 asmop, ins_name))
1453 if nia_update:
1454 self.update_pc_next()
1455
1456 def check_replace_d(self, info, remap_active):
1457 replace_d = False # update / replace constant in pseudocode
1458 ldstmode = yield self.dec2.rm_dec.ldstmode
1459 vl = self.svstate.vl
1460 subvl = yield self.dec2.rm_dec.rm_in.subvl
1461 srcstep, dststep = self.new_srcstep, self.new_dststep
1462 ssubstep, dsubstep = self.new_ssubstep, self.new_dsubstep
1463 if info.form == 'DS':
1464 # DS-Form, multiply by 4 then knock 2 bits off after
1465 imm = yield self.dec2.dec.fields.FormDS.DS[0:14] * 4
1466 else:
1467 imm = yield self.dec2.dec.fields.FormD.D[0:16]
1468 imm = exts(imm, 16) # sign-extend to integer
1469 # get the right step. LD is from srcstep, ST is dststep
1470 op = yield self.dec2.e.do.insn_type
1471 offsmul = 0
1472 if op == MicrOp.OP_LOAD.value:
1473 if remap_active:
1474 offsmul = yield self.dec2.in1_step
1475 log("D-field REMAP src", imm, offsmul)
1476 else:
1477 offsmul = (srcstep * (subvl+1)) + ssubstep
1478 log("D-field src", imm, offsmul)
1479 elif op == MicrOp.OP_STORE.value:
1480 # XXX NOTE! no bit-reversed STORE! this should not ever be used
1481 offsmul = (dststep * (subvl+1)) + dsubstep
1482 log("D-field dst", imm, offsmul)
1483 # Unit-Strided LD/ST adds offset*width to immediate
1484 if ldstmode == SVP64LDSTmode.UNITSTRIDE.value:
1485 ldst_len = yield self.dec2.e.do.data_len
1486 imm = SelectableInt(imm + offsmul * ldst_len, 32)
1487 replace_d = True
1488 # Element-strided multiplies the immediate by element step
1489 elif ldstmode == SVP64LDSTmode.ELSTRIDE.value:
1490 imm = SelectableInt(imm * offsmul, 32)
1491 replace_d = True
1492 if replace_d:
1493 ldst_ra_vec = yield self.dec2.rm_dec.ldst_ra_vec
1494 ldst_imz_in = yield self.dec2.rm_dec.ldst_imz_in
1495 log("LDSTmode", SVP64LDSTmode(ldstmode),
1496 offsmul, imm, ldst_ra_vec, ldst_imz_in)
1497 # new replacement D... errr.. DS
1498 if replace_d:
1499 if info.form == 'DS':
1500 # TODO: assert 2 LSBs are zero?
1501 log("DS-Form, TODO, assert 2 LSBs zero?", bin(imm.value))
1502 imm.value = imm.value >> 2
1503 self.namespace['DS'] = imm
1504 else:
1505 self.namespace['D'] = imm
1506
1507 def get_input(self, name):
1508 # using PowerDecoder2, first, find the decoder index.
1509 # (mapping name RA RB RC RS to in1, in2, in3)
1510 regnum, is_vec = yield from get_pdecode_idx_in(self.dec2, name)
1511 if regnum is None:
1512 # doing this is not part of svp64, it's because output
1513 # registers, to be modified, need to be in the namespace.
1514 regnum, is_vec = yield from get_pdecode_idx_out(self.dec2, name)
1515 if regnum is None:
1516 regnum, is_vec = yield from get_pdecode_idx_out2(self.dec2, name)
1517
1518 # in case getting the register number is needed, _RA, _RB
1519 regname = "_" + name
1520 self.namespace[regname] = regnum
1521 if not self.is_svp64_mode or not self.pred_src_zero:
1522 log('reading reg %s %s' % (name, str(regnum)), is_vec)
1523 if name in fregs:
1524 reg_val = SelectableInt(self.fpr(regnum))
1525 log(f"read reg f{regnum}: 0x{reg_val.value:X}",
1526 kind=LogKind.InstrInOuts)
1527 elif name is not None:
1528 reg_val = SelectableInt(self.gpr(regnum))
1529 log(f"read reg r{regnum}: 0x{reg_val.value:X}",
1530 kind=LogKind.InstrInOuts)
1531 else:
1532 log('zero input reg %s %s' % (name, str(regnum)), is_vec)
1533 reg_val = 0
1534 return reg_val
1535
1536 def remap_debug(self, remaps):
1537 # just some convenient debug info
1538 for i in range(4):
1539 sname = 'SVSHAPE%d' % i
1540 shape = self.spr[sname]
1541 log(sname, bin(shape.value))
1542 log(" lims", shape.lims)
1543 log(" mode", shape.mode)
1544 log(" skip", shape.skip)
1545
1546 # set up the list of steps to remap
1547 mi0 = self.svstate.mi0
1548 mi1 = self.svstate.mi1
1549 mi2 = self.svstate.mi2
1550 mo0 = self.svstate.mo0
1551 mo1 = self.svstate.mo1
1552 steps = [(self.dec2.in1_step, mi0), # RA
1553 (self.dec2.in2_step, mi1), # RB
1554 (self.dec2.in3_step, mi2), # RC
1555 (self.dec2.o_step, mo0), # RT
1556 (self.dec2.o2_step, mo1), # EA
1557 ]
1558 remap_idxs = self.remap_idxs
1559 rremaps = []
1560 # now cross-index the required SHAPE for each of 3-in 2-out regs
1561 rnames = ['RA', 'RB', 'RC', 'RT', 'EA']
1562 for i, (dstep, shape_idx) in enumerate(steps):
1563 (shape, remap) = remaps[shape_idx]
1564 remap_idx = remap_idxs[shape_idx]
1565 # zero is "disabled"
1566 if shape.value == 0x0:
1567 continue
1568 # now set the actual requested step to the current index
1569 yield dstep.eq(remap_idx)
1570
1571 # debug printout info
1572 rremaps.append((shape.mode, i, rnames[i], shape_idx, remap_idx))
1573 for x in rremaps:
1574 log("shape remap", x)
1575
1576 def check_write(self, info, name, output, carry_en):
1577 if name == 'overflow': # ignore, done already (above)
1578 return
1579 if isinstance(output, int):
1580 output = SelectableInt(output, 256)
1581 if name in ['CA', 'CA32']:
1582 if carry_en:
1583 log("writing %s to XER" % name, output)
1584 log(f"write XER field {name}: "
1585 f"0x{output.value % (1 << 64):X}",
1586 kind=LogKind.InstrInOuts)
1587 self.spr['XER'][XER_bits[name]] = output.value
1588 else:
1589 log("NOT writing %s to XER" % name, output)
1590 elif name in info.special_regs:
1591 log('writing special %s' % name, output, special_sprs)
1592 log(f"write reg {name}: "
1593 f"0x{output.value % (1 << 64):X}",
1594 kind=LogKind.InstrInOuts)
1595 if name in special_sprs:
1596 self.spr[name] = output
1597 else:
1598 self.namespace[name].eq(output)
1599 if name == 'MSR':
1600 log('msr written', hex(self.msr.value))
1601 else:
1602 regnum, is_vec = yield from get_pdecode_idx_out(self.dec2, name)
1603 if regnum is None:
1604 regnum, is_vec = yield from get_pdecode_idx_out2(
1605 self.dec2, name)
1606 if regnum is None:
1607 # temporary hack for not having 2nd output
1608 regnum = yield getattr(self.decoder, name)
1609 is_vec = False
1610 if self.is_svp64_mode and self.pred_dst_zero:
1611 log('zeroing reg %d %s' % (regnum, str(output)),
1612 is_vec)
1613 output = SelectableInt(0, 256)
1614 else:
1615 if name in fregs:
1616 reg_prefix = 'f'
1617 else:
1618 reg_prefix = 'r'
1619 log(f"write reg {reg_prefix}{regnum}: "
1620 f"0x{output.value % (1 << 64):X}",
1621 kind=LogKind.InstrInOuts)
1622 if output.bits > 64:
1623 output = SelectableInt(output.value, 64)
1624 if name in fregs:
1625 self.fpr[regnum] = output
1626 else:
1627 self.gpr[regnum] = output
1628
1629 def check_step_increment(self, results, rc_en, asmop, ins_name):
1630 # check if it is the SVSTATE.src/dest step that needs incrementing
1631 # this is our Sub-Program-Counter loop from 0 to VL-1
1632 pre = False
1633 post = False
1634 nia_update = True
1635 if self.allow_next_step_inc:
1636 log("SVSTATE_NEXT: inc requested, mode",
1637 self.svstate_next_mode, self.allow_next_step_inc)
1638 yield from self.svstate_pre_inc()
1639 pre = yield from self.update_new_svstate_steps()
1640 if pre:
1641 # reset at end of loop including exit Vertical Mode
1642 log("SVSTATE_NEXT: end of loop, reset")
1643 self.svp64_reset_loop()
1644 self.svstate.vfirst = 0
1645 self.update_nia()
1646 if not rc_en:
1647 return True
1648 results = [SelectableInt(0, 64)]
1649 self.handle_comparison(results) # CR0
1650 return True
1651 if self.allow_next_step_inc == 2:
1652 log("SVSTATE_NEXT: read")
1653 nia_update = (yield from self.svstate_post_inc(ins_name))
1654 else:
1655 log("SVSTATE_NEXT: post-inc")
1656 # use actual src/dst-step here to check end, do NOT
1657 # use bit-reversed version
1658 srcstep, dststep = self.new_srcstep, self.new_dststep
1659 ssubstep, dsubstep = self.new_ssubstep, self.new_dsubstep
1660 remaps = self.get_remap_indices()
1661 remap_idxs = self.remap_idxs
1662 vl = self.svstate.vl
1663 subvl = yield self.dec2.rm_dec.rm_in.subvl
1664 end_src = srcstep == vl-1
1665 end_dst = dststep == vl-1
1666 if self.allow_next_step_inc != 2:
1667 yield from self.advance_svstate_steps(end_src, end_dst)
1668 self.namespace['SVSTATE'] = self.svstate.spr
1669 # set CR0 (if Rc=1) based on end
1670 if rc_en:
1671 endtest = 1 if (end_src or end_dst) else 0
1672 #results = [SelectableInt(endtest, 64)]
1673 # self.handle_comparison(results) # CR0
1674
1675 # see if svstep was requested, if so, which SVSTATE
1676 endings = 0b111
1677 if self.svstate_next_mode > 0:
1678 shape_idx = self.svstate_next_mode.value-1
1679 endings = self.remap_loopends[shape_idx]
1680 cr_field = SelectableInt((~endings) << 1 | endtest, 4)
1681 log("svstep Rc=1, CR0", cr_field)
1682 self.crl[0].eq(cr_field) # CR0
1683 if end_src or end_dst:
1684 # reset at end of loop including exit Vertical Mode
1685 log("SVSTATE_NEXT: after increments, reset")
1686 self.svp64_reset_loop()
1687 self.svstate.vfirst = 0
1688 return nia_update
1689
1690 if self.is_svp64_mode:
1691 return (yield from self.svstate_post_inc(ins_name))
1692
1693 # XXX only in non-SVP64 mode!
1694 # record state of whether the current operation was an svshape,
1695 # OR svindex!
1696 # to be able to know if it should apply in the next instruction.
1697 # also (if going to use this instruction) should disable ability
1698 # to interrupt in between. sigh.
1699 self.last_op_svshape = asmop in ['svremap', 'svindex']
1700
1701 return True
1702
1703 def SVSTATE_NEXT(self, mode, submode):
1704 """explicitly moves srcstep/dststep on to next element, for
1705 "Vertical-First" mode. this function is called from
1706 setvl pseudo-code, as a pseudo-op "svstep"
1707
1708 WARNING: this function uses information that was created EARLIER
1709 due to it being in the middle of a yield, but this function is
1710 *NOT* called from yield (it's called from compiled pseudocode).
1711 """
1712 self.allow_next_step_inc = submode.value + 1
1713 log("SVSTATE_NEXT mode", mode, submode, self.allow_next_step_inc)
1714 self.svstate_next_mode = mode
1715 if self.svstate_next_mode > 0 and self.svstate_next_mode < 5:
1716 shape_idx = self.svstate_next_mode.value-1
1717 return SelectableInt(self.remap_idxs[shape_idx], 7)
1718 if self.svstate_next_mode == 5:
1719 self.svstate_next_mode = 0
1720 return SelectableInt(self.svstate.srcstep, 7)
1721 if self.svstate_next_mode == 6:
1722 self.svstate_next_mode = 0
1723 return SelectableInt(self.svstate.dststep, 7)
1724 return SelectableInt(0, 7)
1725
1726 def svstate_pre_inc(self):
1727 """check if srcstep/dststep need to skip over masked-out predicate bits
1728 note that this is not supposed to do anything to substep,
1729 it is purely for skipping masked-out bits
1730 """
1731 # get SVSTATE VL (oh and print out some debug stuff)
1732 vl = self.svstate.vl
1733 subvl = yield self.dec2.rm_dec.rm_in.subvl
1734 srcstep = self.svstate.srcstep
1735 dststep = self.svstate.dststep
1736 ssubstep = self.svstate.ssubstep
1737 dsubstep = self.svstate.dsubstep
1738 sv_a_nz = yield self.dec2.sv_a_nz
1739 fft_mode = yield self.dec2.use_svp64_fft
1740 in1 = yield self.dec2.e.read_reg1.data
1741 log("SVP64: VL, subvl, srcstep, dststep, ssubstep, dsybstep, sv_a_nz, "
1742 "in1 fft, svp64",
1743 vl, subvl, srcstep, dststep, ssubstep, dsubstep,
1744 sv_a_nz, in1, fft_mode,
1745 self.is_svp64_mode)
1746
1747 # get predicate mask (all 64 bits)
1748 srcmask = dstmask = 0xffff_ffff_ffff_ffff
1749
1750 pmode = yield self.dec2.rm_dec.predmode
1751 pack = yield self.dec2.rm_dec.pack
1752 unpack = yield self.dec2.rm_dec.unpack
1753 reverse_gear = yield self.dec2.rm_dec.reverse_gear
1754 sv_ptype = yield self.dec2.dec.op.SV_Ptype
1755 srcpred = yield self.dec2.rm_dec.srcpred
1756 dstpred = yield self.dec2.rm_dec.dstpred
1757 pred_src_zero = yield self.dec2.rm_dec.pred_sz
1758 pred_dst_zero = yield self.dec2.rm_dec.pred_dz
1759 if pmode == SVP64PredMode.INT.value:
1760 srcmask = dstmask = get_predint(self.gpr, dstpred)
1761 if sv_ptype == SVPtype.P2.value:
1762 srcmask = get_predint(self.gpr, srcpred)
1763 elif pmode == SVP64PredMode.CR.value:
1764 srcmask = dstmask = get_predcr(self.crl, dstpred, vl)
1765 if sv_ptype == SVPtype.P2.value:
1766 srcmask = get_predcr(self.crl, srcpred, vl)
1767 # work out if the ssubsteps are completed
1768 ssubstart = ssubstep == 0
1769 dsubstart = dsubstep == 0
1770 log(" pmode", pmode)
1771 log(" pack/unpack", pack, unpack)
1772 log(" reverse", reverse_gear)
1773 log(" ptype", sv_ptype)
1774 log(" srcpred", bin(srcpred))
1775 log(" dstpred", bin(dstpred))
1776 log(" srcmask", bin(srcmask))
1777 log(" dstmask", bin(dstmask))
1778 log(" pred_sz", bin(pred_src_zero))
1779 log(" pred_dz", bin(pred_dst_zero))
1780 log(" ssubstart", ssubstart)
1781 log(" dsubstart", dsubstart)
1782
1783 # okaaay, so here we simply advance srcstep (TODO dststep)
1784 # this can ONLY be done at the beginning of the "for" loop
1785 # (this is all actually a FSM so it's hell to keep track sigh)
1786 if ssubstart:
1787 # until the predicate mask has a "1" bit... or we run out of VL
1788 # let srcstep==VL be the indicator to move to next instruction
1789 if not pred_src_zero:
1790 while (((1 << srcstep) & srcmask) == 0) and (srcstep != vl):
1791 log(" sskip", bin(1 << srcstep))
1792 srcstep += 1
1793 if dsubstart:
1794 # same for dststep
1795 if not pred_dst_zero:
1796 while (((1 << dststep) & dstmask) == 0) and (dststep != vl):
1797 log(" dskip", bin(1 << dststep))
1798 dststep += 1
1799
1800 # now work out if the relevant mask bits require zeroing
1801 if pred_dst_zero:
1802 pred_dst_zero = ((1 << dststep) & dstmask) == 0
1803 if pred_src_zero:
1804 pred_src_zero = ((1 << srcstep) & srcmask) == 0
1805
1806 # store new srcstep / dststep
1807 self.new_srcstep, self.new_dststep = (srcstep, dststep)
1808 self.new_ssubstep, self.new_dsubstep = (ssubstep, dsubstep)
1809 self.pred_dst_zero, self.pred_src_zero = (pred_dst_zero, pred_src_zero)
1810 log(" new srcstep", srcstep)
1811 log(" new dststep", dststep)
1812 log(" new ssubstep", ssubstep)
1813 log(" new dsubstep", dsubstep)
1814
1815 def get_src_dststeps(self):
1816 """gets srcstep, dststep, and ssubstep, dsubstep
1817 """
1818 return (self.new_srcstep, self.new_dststep,
1819 self.new_ssubstep, self.new_dsubstep)
1820
1821 def update_new_svstate_steps(self):
1822 # note, do not get the bit-reversed srcstep here!
1823 srcstep, dststep = self.new_srcstep, self.new_dststep
1824 ssubstep, dsubstep = self.new_ssubstep, self.new_dsubstep
1825
1826 # update SVSTATE with new srcstep
1827 self.svstate.srcstep = srcstep
1828 self.svstate.dststep = dststep
1829 self.svstate.ssubstep = ssubstep
1830 self.svstate.dsubstep = dsubstep
1831 self.namespace['SVSTATE'] = self.svstate
1832 yield self.dec2.state.svstate.eq(self.svstate.value)
1833 yield Settle() # let decoder update
1834 srcstep = self.svstate.srcstep
1835 dststep = self.svstate.dststep
1836 ssubstep = self.svstate.ssubstep
1837 dsubstep = self.svstate.dsubstep
1838 vl = self.svstate.vl
1839 subvl = yield self.dec2.rm_dec.rm_in.subvl
1840 log(" srcstep", srcstep)
1841 log(" dststep", dststep)
1842 log(" ssubstep", ssubstep)
1843 log(" dsubstep", dsubstep)
1844 log(" vl", vl)
1845 log(" subvl", subvl)
1846
1847 # check if end reached (we let srcstep overrun, above)
1848 # nothing needs doing (TODO zeroing): just do next instruction
1849 return srcstep == vl or dststep == vl
1850
1851 def svstate_post_inc(self, insn_name, vf=0):
1852 # check if SV "Vertical First" mode is enabled
1853 vfirst = self.svstate.vfirst
1854 log(" SV Vertical First", vf, vfirst)
1855 if not vf and vfirst == 1:
1856 self.update_nia()
1857 return True
1858
1859 # check if it is the SVSTATE.src/dest step that needs incrementing
1860 # this is our Sub-Program-Counter loop from 0 to VL-1
1861 # XXX twin predication TODO
1862 vl = self.svstate.vl
1863 subvl = yield self.dec2.rm_dec.rm_in.subvl
1864 mvl = self.svstate.maxvl
1865 srcstep = self.svstate.srcstep
1866 dststep = self.svstate.dststep
1867 ssubstep = self.svstate.ssubstep
1868 dsubstep = self.svstate.dsubstep
1869 rm_mode = yield self.dec2.rm_dec.mode
1870 reverse_gear = yield self.dec2.rm_dec.reverse_gear
1871 sv_ptype = yield self.dec2.dec.op.SV_Ptype
1872 out_vec = not (yield self.dec2.no_out_vec)
1873 in_vec = not (yield self.dec2.no_in_vec)
1874 log(" svstate.vl", vl)
1875 log(" svstate.mvl", mvl)
1876 log(" rm.subvl", subvl)
1877 log(" svstate.srcstep", srcstep)
1878 log(" svstate.dststep", dststep)
1879 log(" svstate.ssubstep", ssubstep)
1880 log(" svstate.dsubstep", dsubstep)
1881 log(" mode", rm_mode)
1882 log(" reverse", reverse_gear)
1883 log(" out_vec", out_vec)
1884 log(" in_vec", in_vec)
1885 log(" sv_ptype", sv_ptype, sv_ptype == SVPtype.P2.value)
1886 # check if this was an sv.bc* and if so did it succeed
1887 if self.is_svp64_mode and insn_name.startswith("sv.bc"):
1888 end_loop = self.namespace['end_loop']
1889 log("branch %s end_loop" % insn_name, end_loop)
1890 if end_loop.value:
1891 self.svp64_reset_loop()
1892 self.update_pc_next()
1893 return False
1894 # check if srcstep needs incrementing by one, stop PC advancing
1895 # but for 2-pred both src/dest have to be checked.
1896 # XXX this might not be true! it may just be LD/ST
1897 if sv_ptype == SVPtype.P2.value:
1898 svp64_is_vector = (out_vec or in_vec)
1899 else:
1900 svp64_is_vector = out_vec
1901 # loops end at the first "hit" (source or dest)
1902 loopend = ((srcstep == vl-1 and ssubstep == subvl) or
1903 (dststep == vl-1 and dsubstep == subvl))
1904 if not svp64_is_vector or loopend:
1905 # reset loop to zero and update NIA
1906 self.svp64_reset_loop()
1907 self.update_nia()
1908
1909 return True
1910
1911 # still looping, advance and update NIA
1912 yield from self.advance_svstate_steps()
1913 self.namespace['SVSTATE'] = self.svstate
1914 # not an SVP64 branch, so fix PC (NIA==CIA) for next loop
1915 # (by default, NIA is CIA+4 if v3.0B or CIA+8 if SVP64)
1916 # this way we keep repeating the same instruction (with new steps)
1917 self.pc.NIA.value = self.pc.CIA.value
1918 self.namespace['NIA'] = self.pc.NIA
1919 log("end of sub-pc call", self.namespace['CIA'], self.namespace['NIA'])
1920 return False # DO NOT allow PC update whilst Sub-PC loop running
1921
1922 def advance_svstate_steps(self, end_src=False, end_dst=False):
1923 """ advance sub/steps. note that Pack/Unpack *INVERTS* the order.
1924 TODO when Pack/Unpack is set, substep becomes the *outer* loop
1925 """
1926 subvl = yield self.dec2.rm_dec.rm_in.subvl
1927 # first source step
1928 ssubstep = self.svstate.ssubstep
1929 end_sub = ssubstep == subvl
1930 if end_sub:
1931 if not end_src:
1932 self.svstate.srcstep += SelectableInt(1, 7)
1933 self.svstate.ssubstep = SelectableInt(0, 2) # reset
1934 else:
1935 self.svstate.ssubstep += SelectableInt(1, 2) # advance ssubstep
1936 # now dest step
1937 dsubstep = self.svstate.dsubstep
1938 end_sub = dsubstep == subvl
1939 if end_sub:
1940 if not end_dst:
1941 self.svstate.dststep += SelectableInt(1, 7)
1942 self.svstate.dsubstep = SelectableInt(0, 2) # reset
1943 else:
1944 self.svstate.dsubstep += SelectableInt(1, 2) # advance ssubstep
1945
1946 def update_pc_next(self):
1947 # UPDATE program counter
1948 self.pc.update(self.namespace, self.is_svp64_mode)
1949 self.svstate.spr = self.namespace['SVSTATE']
1950 log("end of call", self.namespace['CIA'],
1951 self.namespace['NIA'],
1952 self.namespace['SVSTATE'])
1953
1954 def svp64_reset_loop(self):
1955 self.svstate.srcstep = 0
1956 self.svstate.dststep = 0
1957 self.svstate.ssubstep = 0
1958 self.svstate.dsubstep = 0
1959 log(" svstate.srcstep loop end (PC to update)")
1960 self.namespace['SVSTATE'] = self.svstate
1961
1962 def update_nia(self):
1963 self.pc.update_nia(self.is_svp64_mode)
1964 self.namespace['NIA'] = self.pc.NIA
1965
1966
1967 def inject():
1968 """Decorator factory.
1969
1970 this decorator will "inject" variables into the function's namespace,
1971 from the *dictionary* in self.namespace. it therefore becomes possible
1972 to make it look like a whole stack of variables which would otherwise
1973 need "self." inserted in front of them (*and* for those variables to be
1974 added to the instance) "appear" in the function.
1975
1976 "self.namespace['SI']" for example becomes accessible as just "SI" but
1977 *only* inside the function, when decorated.
1978 """
1979 def variable_injector(func):
1980 @wraps(func)
1981 def decorator(*args, **kwargs):
1982 try:
1983 func_globals = func.__globals__ # Python 2.6+
1984 except AttributeError:
1985 func_globals = func.func_globals # Earlier versions.
1986
1987 context = args[0].namespace # variables to be injected
1988 saved_values = func_globals.copy() # Shallow copy of dict.
1989 log("globals before", context.keys())
1990 func_globals.update(context)
1991 result = func(*args, **kwargs)
1992 log("globals after", func_globals['CIA'], func_globals['NIA'])
1993 log("args[0]", args[0].namespace['CIA'],
1994 args[0].namespace['NIA'],
1995 args[0].namespace['SVSTATE'])
1996 if 'end_loop' in func_globals:
1997 log("args[0] end_loop", func_globals['end_loop'])
1998 args[0].namespace = func_globals
1999 #exec (func.__code__, func_globals)
2000
2001 # finally:
2002 # func_globals = saved_values # Undo changes.
2003
2004 return result
2005
2006 return decorator
2007
2008 return variable_injector