e51d24f62a731e006e0cab22f7ce1615c80964d4
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
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.
13 * https://bugs.libre-soc.org/show_bug.cgi?id=424
17 from nmigen
.back
.pysim
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 (
27 from openpower
.decoder
.power_enums
import (spr_dict
, spr_byname
, XER_bits
,
29 In1Sel
, In2Sel
, In3Sel
,
30 OutSel
, CRInSel
, CROutSel
, LDSTMode
,
31 SVP64RMMode
, SVP64PredMode
,
32 SVP64PredInt
, SVP64PredCR
,
35 from openpower
.decoder
.power_enums
import SVPtype
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
,
43 from openpower
.decoder
.power_svp64
import SVP64RM
, decode_extra
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
51 from openpower
.util
import log
53 from collections
import namedtuple
57 instruction_info
= namedtuple('instruction_info',
58 'func read_regs uninit_regs write_regs ' +
59 'special_regs op_fields form asmregs')
70 # TODO (lkcl): adjust other registers that should be in a particular order
71 # probably CA, CA32, and CR
97 "overflow": 7, # should definitely be last
100 fregs
= ['FRA', 'FRB', 'FRC', 'FRS', 'FRT']
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
112 def __init__(self
, decoder
, isacaller
, svstate
, regfile
):
115 self
.isacaller
= isacaller
116 self
.svstate
= svstate
117 for i
in range(len(regfile
)):
118 self
[i
] = SelectableInt(regfile
[i
], 64)
120 def __call__(self
, ridx
):
121 if isinstance(ridx
, SelectableInt
):
125 def set_form(self
, form
):
128 def __setitem__(self
, rnum
, value
):
129 # rnum = rnum.value # only SelectableInt allowed
130 log("GPR setitem", rnum
, value
)
131 if isinstance(rnum
, SelectableInt
):
133 dict.__setitem
__(self
, rnum
, value
)
135 def getz(self
, rnum
):
136 # rnum = rnum.value # only SelectableInt allowed
137 log("GPR getzero?", rnum
)
139 return SelectableInt(0, 64)
142 def _get_regnum(self
, attr
):
143 getform
= self
.sd
.sigforms
[self
.form
]
144 rnum
= getattr(getform
, attr
)
147 def ___getitem__(self
, attr
):
148 """ XXX currently not used
150 rnum
= self
._get
_regnum
(attr
)
151 log("GPR getitem", attr
, rnum
)
152 return self
.regfile
[rnum
]
154 def dump(self
, printout
=True):
156 for i
in range(len(self
)):
157 res
.append(self
[i
].value
)
159 for i
in range(0, len(res
), 8):
162 s
.append("%08x" % res
[i
+j
])
164 print("reg", "%2d" % i
, s
)
169 def __init__(self
, dec2
, initial_sprs
={}):
172 for key
, v
in initial_sprs
.items():
173 if isinstance(key
, SelectableInt
):
175 key
= special_sprs
.get(key
, key
)
176 if isinstance(key
, int):
179 info
= spr_byname
[key
]
180 if not isinstance(v
, SelectableInt
):
181 v
= SelectableInt(v
, info
.length
)
184 def __getitem__(self
, key
):
186 log("dict", self
.items())
187 # if key in special_sprs get the special spr, otherwise return key
188 if isinstance(key
, SelectableInt
):
190 if isinstance(key
, int):
191 key
= spr_dict
[key
].SPR
192 key
= special_sprs
.get(key
, key
)
193 if key
== 'HSRR0': # HACK!
195 if key
== 'HSRR1': # HACK!
198 res
= dict.__getitem
__(self
, key
)
200 if isinstance(key
, int):
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
)
209 def __setitem__(self
, key
, value
):
210 if isinstance(key
, SelectableInt
):
212 if isinstance(key
, int):
213 key
= spr_dict
[key
].SPR
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
)
223 def __call__(self
, ridx
):
226 def dump(self
, printout
=True):
228 keys
= list(self
.keys())
231 sprname
= spr_dict
.get(k
, None)
235 sprname
= sprname
.SPR
236 res
.append((sprname
, self
[k
].value
))
238 for sprname
, value
in res
:
239 print(" ", sprname
, hex(value
))
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!
248 def update_nia(self
, is_svp64
):
249 increment
= 8 if is_svp64
else 4
250 self
.NIA
= self
.CIA
+ SelectableInt(increment
, 64)
252 def update(self
, namespace
, is_svp64
):
253 """updates the program counter (PC) by 4 if v3.0B mode or 8 if SVP64
255 self
.CIA
= namespace
['NIA'].narrow(64)
256 self
.update_nia(is_svp64
)
257 namespace
['CIA'] = self
.CIA
258 namespace
['NIA'] = self
.NIA
262 class SVP64RMFields(SelectableIntMapping
, bits
=24, fields
={
264 # SVP64 RM fields: see https://libre-soc.org/openpower/sv/svp64/
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 # these cover the same extra field, split into parts as EXTRA2
273 "extra2": dict(enumerate([
279 "smask": range(16, 19),
280 # and here as well, but EXTRA3
281 "extra3": dict(enumerate([
288 def __init__(self
, value
=0):
289 super().__init
__(value
=value
)
293 SVP64RM_MMODE_SIZE
= len(SVP64RMFields
.mmode
)
294 SVP64RM_MASK_SIZE
= len(SVP64RMFields
.mask
)
295 SVP64RM_ELWIDTH_SIZE
= len(SVP64RMFields
.elwidth
)
296 SVP64RM_EWSRC_SIZE
= len(SVP64RMFields
.ewsrc
)
297 SVP64RM_SUBVL_SIZE
= len(SVP64RMFields
.subvl
)
298 SVP64RM_EXTRA2_SPEC_SIZE
= len(SVP64RMFields
.extra2
[0])
299 SVP64RM_EXTRA3_SPEC_SIZE
= len(SVP64RMFields
.extra3
[0])
300 SVP64RM_SMASK_SIZE
= len(SVP64RMFields
.smask
)
301 SVP64RM_MODE_SIZE
= len(SVP64RMFields
.mode
)
304 # SVP64 Prefix fields: see https://libre-soc.org/openpower/sv/svp64/
305 class SVP64PrefixFields(SelectableIntMapping
, bits
=32, fields
={
307 # 6 bit major opcode EXT001, 2 bits "identifying" (7, 9), 24 SV ReMap
308 "major": range(0, 6),
310 # SVP64 24-bit RM (ReMap)
311 "rm": ((6, 8) + tuple(range(10, 32))),
314 def __init__(self
, value
=0):
315 super().__init
__(value
=value
)
319 SV64P_MAJOR_SIZE
= len(SVP64PrefixFields
.major
)
320 SV64P_PID_SIZE
= len(SVP64PrefixFields
.pid
)
321 SV64P_RM_SIZE
= len(SVP64PrefixFields
.rm
)
325 # See PowerISA Version 3.0 B Book 1
326 # Section 2.3.1 Condition Register pages 30 - 31
328 LT
= FL
= 0 # negative, less than, floating-point less than
329 GT
= FG
= 1 # positive, greater than, floating-point greater than
330 EQ
= FE
= 2 # equal, floating-point equal
331 SO
= FU
= 3 # summary overflow, floating-point unordered
333 def __init__(self
, init
=0):
334 # rev_cr = int('{:016b}'.format(initial_cr)[::-1], 2)
335 # self.cr = FieldSelectableInt(self._cr, list(range(32, 64)))
336 self
.cr
= SelectableInt(init
, 64) # underlying reg
337 # field-selectable versions of Condition Register TODO check bitranges?
340 bits
= tuple(range(i
*4+32, (i
+1)*4+32))
341 _cr
= FieldSelectableInt(self
.cr
, bits
)
344 # decode SVP64 predicate integer to reg number and invert
347 def get_predint(gpr
, mask
):
350 log("get_predint", mask
, SVP64PredInt
.ALWAYS
.value
)
351 if mask
== SVP64PredInt
.ALWAYS
.value
:
352 return 0xffff_ffff_ffff_ffff # 64 bits of 1
353 if mask
== SVP64PredInt
.R3_UNARY
.value
:
354 return 1 << (gpr(3).value
& 0b111111)
355 if mask
== SVP64PredInt
.R3
.value
:
357 if mask
== SVP64PredInt
.R3_N
.value
:
359 if mask
== SVP64PredInt
.R10
.value
:
361 if mask
== SVP64PredInt
.R10_N
.value
:
362 return ~
gpr(10).value
363 if mask
== SVP64PredInt
.R30
.value
:
365 if mask
== SVP64PredInt
.R30_N
.value
:
366 return ~
gpr(30).value
368 # decode SVP64 predicate CR to reg number and invert status
371 def _get_predcr(mask
):
372 if mask
== SVP64PredCR
.LT
.value
:
374 if mask
== SVP64PredCR
.GE
.value
:
376 if mask
== SVP64PredCR
.GT
.value
:
378 if mask
== SVP64PredCR
.LE
.value
:
380 if mask
== SVP64PredCR
.EQ
.value
:
382 if mask
== SVP64PredCR
.NE
.value
:
384 if mask
== SVP64PredCR
.SO
.value
:
386 if mask
== SVP64PredCR
.NS
.value
:
389 # read individual CR fields (0..VL-1), extract the required bit
390 # and construct the mask
393 def get_predcr(crl
, mask
, vl
):
394 idx
, noninv
= _get_predcr(mask
)
397 cr
= crl
[i
+SVP64CROffs
.CRPred
]
398 if cr
[idx
].value
== noninv
:
403 # TODO, really should just be using PowerDecoder2
404 def get_pdecode_idx_in(dec2
, name
):
406 in1_sel
= yield op
.in1_sel
407 in2_sel
= yield op
.in2_sel
408 in3_sel
= yield op
.in3_sel
409 # get the IN1/2/3 from the decoder (includes SVP64 remap and isvec)
410 in1
= yield dec2
.e
.read_reg1
.data
411 in2
= yield dec2
.e
.read_reg2
.data
412 in3
= yield dec2
.e
.read_reg3
.data
413 in1_isvec
= yield dec2
.in1_isvec
414 in2_isvec
= yield dec2
.in2_isvec
415 in3_isvec
= yield dec2
.in3_isvec
416 log("get_pdecode_idx_in in1", name
, in1_sel
, In1Sel
.RA
.value
,
418 log("get_pdecode_idx_in in2", name
, in2_sel
, In2Sel
.RB
.value
,
420 log("get_pdecode_idx_in in3", name
, in3_sel
, In3Sel
.RS
.value
,
422 log("get_pdecode_idx_in FRS in3", name
, in3_sel
, In3Sel
.FRS
.value
,
424 log("get_pdecode_idx_in FRB in2", name
, in2_sel
, In2Sel
.FRB
.value
,
426 log("get_pdecode_idx_in FRC in3", name
, in3_sel
, In3Sel
.FRC
.value
,
428 # identify which regnames map to in1/2/3
430 if (in1_sel
== In1Sel
.RA
.value
or
431 (in1_sel
== In1Sel
.RA_OR_ZERO
.value
and in1
!= 0)):
432 return in1
, in1_isvec
433 if in1_sel
== In1Sel
.RA_OR_ZERO
.value
:
434 return in1
, in1_isvec
436 if in2_sel
== In2Sel
.RB
.value
:
437 return in2
, in2_isvec
438 if in3_sel
== In3Sel
.RB
.value
:
439 return in3
, in3_isvec
440 # XXX TODO, RC doesn't exist yet!
442 assert False, "RC does not exist yet"
444 if in1_sel
== In1Sel
.RS
.value
:
445 return in1
, in1_isvec
446 if in2_sel
== In2Sel
.RS
.value
:
447 return in2
, in2_isvec
448 if in3_sel
== In3Sel
.RS
.value
:
449 return in3
, in3_isvec
451 if in1_sel
== In1Sel
.FRA
.value
:
452 return in1
, in1_isvec
454 if in2_sel
== In2Sel
.FRB
.value
:
455 return in2
, in2_isvec
457 if in3_sel
== In3Sel
.FRC
.value
:
458 return in3
, in3_isvec
460 if in1_sel
== In1Sel
.FRS
.value
:
461 return in1
, in1_isvec
462 if in3_sel
== In3Sel
.FRS
.value
:
463 return in3
, in3_isvec
467 # TODO, really should just be using PowerDecoder2
468 def get_pdecode_cr_in(dec2
, name
):
470 in_sel
= yield op
.cr_in
471 in_bitfield
= yield dec2
.dec_cr_in
.cr_bitfield
.data
472 sv_cr_in
= yield op
.sv_cr_in
473 spec
= yield dec2
.crin_svdec
.spec
474 sv_override
= yield dec2
.dec_cr_in
.sv_override
475 # get the IN1/2/3 from the decoder (includes SVP64 remap and isvec)
476 in1
= yield dec2
.e
.read_cr1
.data
477 cr_isvec
= yield dec2
.cr_in_isvec
478 log("get_pdecode_cr_in", in_sel
, CROutSel
.CR0
.value
, in1
, cr_isvec
)
479 log(" sv_cr_in", sv_cr_in
)
480 log(" cr_bf", in_bitfield
)
482 log(" override", sv_override
)
483 # identify which regnames map to in / o2
485 if in_sel
== CRInSel
.BI
.value
:
487 log("get_pdecode_cr_in not found", name
)
491 # TODO, really should just be using PowerDecoder2
492 def get_pdecode_cr_out(dec2
, name
):
494 out_sel
= yield op
.cr_out
495 out_bitfield
= yield dec2
.dec_cr_out
.cr_bitfield
.data
496 sv_cr_out
= yield op
.sv_cr_out
497 spec
= yield dec2
.crout_svdec
.spec
498 sv_override
= yield dec2
.dec_cr_out
.sv_override
499 # get the IN1/2/3 from the decoder (includes SVP64 remap and isvec)
500 out
= yield dec2
.e
.write_cr
.data
501 o_isvec
= yield dec2
.o_isvec
502 log("get_pdecode_cr_out", out_sel
, CROutSel
.CR0
.value
, out
, o_isvec
)
503 log(" sv_cr_out", sv_cr_out
)
504 log(" cr_bf", out_bitfield
)
506 log(" override", sv_override
)
507 # identify which regnames map to out / o2
509 if out_sel
== CROutSel
.CR0
.value
:
511 log("get_pdecode_cr_out not found", name
)
515 # TODO, really should just be using PowerDecoder2
516 def get_pdecode_idx_out(dec2
, name
):
518 out_sel
= yield op
.out_sel
519 # get the IN1/2/3 from the decoder (includes SVP64 remap and isvec)
520 out
= yield dec2
.e
.write_reg
.data
521 o_isvec
= yield dec2
.o_isvec
522 # identify which regnames map to out / o2
524 log("get_pdecode_idx_out", out_sel
, OutSel
.RA
.value
, out
, o_isvec
)
525 if out_sel
== OutSel
.RA
.value
:
528 log("get_pdecode_idx_out", out_sel
, OutSel
.RT
.value
,
529 OutSel
.RT_OR_ZERO
.value
, out
, o_isvec
,
531 if out_sel
== OutSel
.RT
.value
:
533 elif name
== 'RT_OR_ZERO':
534 log("get_pdecode_idx_out", out_sel
, OutSel
.RT
.value
,
535 OutSel
.RT_OR_ZERO
.value
, out
, o_isvec
,
537 if out_sel
== OutSel
.RT_OR_ZERO
.value
:
540 log("get_pdecode_idx_out", out_sel
, OutSel
.FRA
.value
, out
, o_isvec
)
541 if out_sel
== OutSel
.FRA
.value
:
544 log("get_pdecode_idx_out", out_sel
, OutSel
.FRT
.value
,
545 OutSel
.FRT
.value
, out
, o_isvec
)
546 if out_sel
== OutSel
.FRT
.value
:
548 log("get_pdecode_idx_out not found", name
, out_sel
, out
, o_isvec
)
552 # TODO, really should just be using PowerDecoder2
553 def get_pdecode_idx_out2(dec2
, name
):
554 # check first if register is activated for write
556 out_sel
= yield op
.out_sel
557 out
= yield dec2
.e
.write_ea
.data
558 o_isvec
= yield dec2
.o2_isvec
559 out_ok
= yield dec2
.e
.write_ea
.ok
560 log("get_pdecode_idx_out2", name
, out_sel
, out
, out_ok
, o_isvec
)
565 if hasattr(op
, "upd"):
566 # update mode LD/ST uses read-reg A also as an output
568 log("get_pdecode_idx_out2", upd
, LDSTMode
.update
.value
,
569 out_sel
, OutSel
.RA
.value
,
571 if upd
== LDSTMode
.update
.value
:
574 int_op
= yield dec2
.dec
.op
.internal_op
575 fft_en
= yield dec2
.use_svp64_fft
576 # if int_op == MicrOp.OP_FP_MADD.value and fft_en:
578 log("get_pdecode_idx_out2", out_sel
, OutSel
.FRS
.value
,
584 class ISACaller(ISACallerHelper
, ISAFPHelpers
):
585 # decoder2 - an instance of power_decoder2
586 # regfile - a list of initial values for the registers
587 # initial_{etc} - initial values for SPRs, Condition Register, Mem, MSR
588 # respect_pc - tracks the program counter. requires initial_insns
589 def __init__(self
, decoder2
, regfile
, initial_sprs
=None, initial_cr
=0,
590 initial_mem
=None, initial_msr
=0,
601 self
.bigendian
= bigendian
603 self
.is_svp64_mode
= False
604 self
.respect_pc
= respect_pc
605 if initial_sprs
is None:
607 if initial_mem
is None:
609 if fpregfile
is None:
611 if initial_insns
is None:
613 assert self
.respect_pc
== False, "instructions required to honor pc"
615 log("ISACaller insns", respect_pc
, initial_insns
, disassembly
)
616 log("ISACaller initial_msr", initial_msr
)
618 # "fake program counter" mode (for unit testing)
622 if isinstance(initial_mem
, tuple):
623 self
.fake_pc
= initial_mem
[0]
624 disasm_start
= self
.fake_pc
626 disasm_start
= initial_pc
628 # disassembly: we need this for now (not given from the decoder)
629 self
.disassembly
= {}
631 for i
, code
in enumerate(disassembly
):
632 self
.disassembly
[i
*4 + disasm_start
] = code
634 # set up registers, instruction memory, data memory, PC, SPRs, MSR, CR
635 self
.svp64rm
= SVP64RM()
636 if initial_svstate
is None:
638 if isinstance(initial_svstate
, int):
639 initial_svstate
= SVP64State(initial_svstate
)
640 # SVSTATE, MSR and PC
641 self
.svstate
= initial_svstate
642 self
.msr
= SelectableInt(initial_msr
, 64) # underlying reg
644 # GPR FPR SPR registers
645 initial_sprs
= deepcopy(initial_sprs
) # so as not to get modified
646 self
.gpr
= GPR(decoder2
, self
, self
.svstate
, regfile
)
647 self
.fpr
= GPR(decoder2
, self
, self
.svstate
, fpregfile
)
648 self
.spr
= SPR(decoder2
, initial_sprs
) # initialise SPRs before MMU
650 # set up 4 dummy SVSHAPEs if they aren't already set up
652 sname
= 'SVSHAPE%d' % i
653 if sname
not in self
.spr
:
656 val
= self
.spr
[sname
].value
657 # make sure it's an SVSHAPE
658 self
.spr
[sname
] = SVSHAPE(val
, self
.gpr
)
659 self
.last_op_svshape
= False
662 self
.mem
= Mem(row_bytes
=8, initial_mem
=initial_mem
)
663 self
.imem
= Mem(row_bytes
=4, initial_mem
=initial_insns
)
664 # MMU mode, redirect underlying Mem through RADIX
666 self
.mem
= RADIX(self
.mem
, self
)
668 self
.imem
= RADIX(self
.imem
, self
)
671 # FPR (same as GPR except for FP nums)
672 # 4.2.2 p124 FPSCR (definitely "separate" - not in SPR)
673 # note that mffs, mcrfs, mtfsf "manage" this FPSCR
674 # 2.3.1 CR (and sub-fields CR0..CR6 - CR0 SO comes from XER.SO)
675 # note that mfocrf, mfcr, mtcr, mtocrf, mcrxrx "manage" CRs
677 # 2.3.2 LR (actually SPR #8) -- Done
678 # 2.3.3 CTR (actually SPR #9) -- Done
679 # 2.3.4 TAR (actually SPR #815)
680 # 3.2.2 p45 XER (actually SPR #1) -- Done
681 # 3.2.3 p46 p232 VRSAVE (actually SPR #256)
683 # create CR then allow portions of it to be "selectable" (below)
684 self
.cr_fields
= CRFields(initial_cr
)
685 self
.cr
= self
.cr_fields
.cr
687 # "undefined", just set to variable-bit-width int (use exts "max")
688 # self.undefined = SelectableInt(0, 256) # TODO, not hard-code 256!
691 self
.namespace
.update(self
.spr
)
692 self
.namespace
.update({'GPR': self
.gpr
,
696 'memassign': self
.memassign
,
699 'SVSTATE': self
.svstate
,
700 'SVSHAPE0': self
.spr
['SVSHAPE0'],
701 'SVSHAPE1': self
.spr
['SVSHAPE1'],
702 'SVSHAPE2': self
.spr
['SVSHAPE2'],
703 'SVSHAPE3': self
.spr
['SVSHAPE3'],
706 'undefined': undefined
,
707 'mode_is_64bit': True,
708 'SO': XER_bits
['SO'],
709 'XLEN': 64 # elwidth overrides, later
712 # update pc to requested start point
713 self
.set_pc(initial_pc
)
715 # field-selectable versions of Condition Register
716 self
.crl
= self
.cr_fields
.crl
718 self
.namespace
["CR%d" % i
] = self
.crl
[i
]
720 self
.decoder
= decoder2
.dec
723 super().__init
__(XLEN
=self
.namespace
["XLEN"])
727 return self
.namespace
["XLEN"]
729 def call_trap(self
, trap_addr
, trap_bit
):
730 """calls TRAP and sets up NIA to the new execution location.
731 next instruction will begin at trap_addr.
733 self
.TRAP(trap_addr
, trap_bit
)
734 self
.namespace
['NIA'] = self
.trap_nia
735 self
.pc
.update(self
.namespace
, self
.is_svp64_mode
)
737 def TRAP(self
, trap_addr
=0x700, trap_bit
=PIb
.TRAP
):
738 """TRAP> saves PC, MSR (and TODO SVSTATE), and updates MSR
740 TRAP function is callable from inside the pseudocode itself,
741 hence the default arguments. when calling from inside ISACaller
742 it is best to use call_trap()
744 # https://bugs.libre-soc.org/show_bug.cgi?id=859
745 kaivb
= self
.spr
['KAIVB'].value
746 msr
= self
.namespace
['MSR'].value
747 log("TRAP:", hex(trap_addr
), hex(msr
), "kaivb", hex(kaivb
))
748 # store CIA(+4?) in SRR0, set NIA to 0x700
749 # store MSR in SRR1, set MSR to um errr something, have to check spec
750 # store SVSTATE (if enabled) in SVSRR0
751 self
.spr
['SRR0'].value
= self
.pc
.CIA
.value
752 self
.spr
['SRR1'].value
= msr
753 if self
.is_svp64_mode
:
754 self
.spr
['SVSRR0'] = self
.namespace
['SVSTATE'].value
755 self
.trap_nia
= SelectableInt(trap_addr |
(kaivb
&~
0x1fff), 64)
756 self
.spr
['SRR1'][trap_bit
] = 1 # change *copy* of MSR in SRR1
758 # set exception bits. TODO: this should, based on the address
759 # in figure 66 p1065 V3.0B and the table figure 65 p1063 set these
760 # bits appropriately. however it turns out that *for now* in all
761 # cases (all trap_addrs) the exact same thing is needed.
762 self
.msr
[MSRb
.IR
] = 0
763 self
.msr
[MSRb
.DR
] = 0
764 self
.msr
[MSRb
.FE0
] = 0
765 self
.msr
[MSRb
.FE1
] = 0
766 self
.msr
[MSRb
.EE
] = 0
767 self
.msr
[MSRb
.RI
] = 0
768 self
.msr
[MSRb
.SF
] = 1
769 self
.msr
[MSRb
.TM
] = 0
770 self
.msr
[MSRb
.VEC
] = 0
771 self
.msr
[MSRb
.VSX
] = 0
772 self
.msr
[MSRb
.PR
] = 0
773 self
.msr
[MSRb
.FP
] = 0
774 self
.msr
[MSRb
.PMM
] = 0
775 self
.msr
[MSRb
.TEs
] = 0
776 self
.msr
[MSRb
.TEe
] = 0
777 self
.msr
[MSRb
.UND
] = 0
778 self
.msr
[MSRb
.LE
] = 1
780 def memassign(self
, ea
, sz
, val
):
781 self
.mem
.memassign(ea
, sz
, val
)
783 def prep_namespace(self
, insn_name
, formname
, op_fields
):
784 # TODO: get field names from form in decoder*1* (not decoder2)
785 # decoder2 is hand-created, and decoder1.sigform is auto-generated
787 # then "yield" fields only from op_fields rather than hard-coded
789 fields
= self
.decoder
.sigforms
[formname
]
790 log("prep_namespace", formname
, op_fields
)
791 for name
in op_fields
:
792 # CR immediates. deal with separately. needs modifying
794 if self
.is_svp64_mode
and name
in ['BI']: # TODO, more CRs
795 # BI is a 5-bit, must reconstruct the value
796 regnum
, is_vec
= yield from get_pdecode_cr_in(self
.dec2
, name
)
797 sig
= getattr(fields
, name
)
799 # low 2 LSBs (CR field selector) remain same, CR num extended
800 assert regnum
<= 7, "sigh, TODO, 128 CR fields"
801 val
= (val
& 0b11) |
(regnum
<< 2)
804 sig
= getattr(fields
, name
.upper())
806 sig
= getattr(fields
, name
)
808 # these are all opcode fields involved in index-selection of CR,
809 # and need to do "standard" arithmetic. CR[BA+32] for example
810 # would, if using SelectableInt, only be 5-bit.
811 if name
in ['BF', 'BFA', 'BC', 'BA', 'BB', 'BT', 'BI']:
812 self
.namespace
[name
] = val
814 self
.namespace
[name
] = SelectableInt(val
, sig
.width
)
816 self
.namespace
['XER'] = self
.spr
['XER']
817 self
.namespace
['CA'] = self
.spr
['XER'][XER_bits
['CA']].value
818 self
.namespace
['CA32'] = self
.spr
['XER'][XER_bits
['CA32']].value
820 # add some SVSTATE convenience variables
822 srcstep
= self
.svstate
.srcstep
823 self
.namespace
['VL'] = vl
824 self
.namespace
['srcstep'] = srcstep
826 # sv.bc* need some extra fields
827 if self
.is_svp64_mode
and insn_name
.startswith("sv.bc"):
828 # blegh grab bits manually
829 mode
= yield self
.dec2
.rm_dec
.rm_in
.mode
830 bc_vlset
= (mode
& SVP64MODE
.BC_VLSET
) != 0
831 bc_vli
= (mode
& SVP64MODE
.BC_VLI
) != 0
832 bc_snz
= (mode
& SVP64MODE
.BC_SNZ
) != 0
833 bc_vsb
= yield self
.dec2
.rm_dec
.bc_vsb
834 bc_lru
= yield self
.dec2
.rm_dec
.bc_lru
835 bc_gate
= yield self
.dec2
.rm_dec
.bc_gate
836 sz
= yield self
.dec2
.rm_dec
.pred_sz
837 self
.namespace
['ALL'] = SelectableInt(bc_gate
, 1)
838 self
.namespace
['VSb'] = SelectableInt(bc_vsb
, 1)
839 self
.namespace
['LRu'] = SelectableInt(bc_lru
, 1)
840 self
.namespace
['VLSET'] = SelectableInt(bc_vlset
, 1)
841 self
.namespace
['VLI'] = SelectableInt(bc_vli
, 1)
842 self
.namespace
['sz'] = SelectableInt(sz
, 1)
843 self
.namespace
['SNZ'] = SelectableInt(bc_snz
, 1)
845 def handle_carry_(self
, inputs
, outputs
, already_done
):
846 inv_a
= yield self
.dec2
.e
.do
.invert_in
848 inputs
[0] = ~inputs
[0]
850 imm_ok
= yield self
.dec2
.e
.do
.imm_data
.ok
852 imm
= yield self
.dec2
.e
.do
.imm_data
.data
853 inputs
.append(SelectableInt(imm
, 64))
854 assert len(outputs
) >= 1
855 log("outputs", repr(outputs
))
856 if isinstance(outputs
, list) or isinstance(outputs
, tuple):
862 log("gt input", x
, output
)
863 gt
= (gtu(x
, output
))
866 cy
= 1 if any(gts
) else 0
868 if not (1 & already_done
):
869 self
.spr
['XER'][XER_bits
['CA']] = cy
871 log("inputs", already_done
, inputs
)
873 # ARGH... different for OP_ADD... *sigh*...
874 op
= yield self
.dec2
.e
.do
.insn_type
875 if op
== MicrOp
.OP_ADD
.value
:
876 res32
= (output
.value
& (1 << 32)) != 0
877 a32
= (inputs
[0].value
& (1 << 32)) != 0
879 b32
= (inputs
[1].value
& (1 << 32)) != 0
882 cy32
= res32 ^ a32 ^ b32
883 log("CA32 ADD", cy32
)
887 log("input", x
, output
)
888 log(" x[32:64]", x
, x
[32:64])
889 log(" o[32:64]", output
, output
[32:64])
890 gt
= (gtu(x
[32:64], output
[32:64])) == SelectableInt(1, 1)
892 cy32
= 1 if any(gts
) else 0
893 log("CA32", cy32
, gts
)
894 if not (2 & already_done
):
895 self
.spr
['XER'][XER_bits
['CA32']] = cy32
897 def handle_overflow(self
, inputs
, outputs
, div_overflow
):
898 if hasattr(self
.dec2
.e
.do
, "invert_in"):
899 inv_a
= yield self
.dec2
.e
.do
.invert_in
901 inputs
[0] = ~inputs
[0]
903 imm_ok
= yield self
.dec2
.e
.do
.imm_data
.ok
905 imm
= yield self
.dec2
.e
.do
.imm_data
.data
906 inputs
.append(SelectableInt(imm
, 64))
907 assert len(outputs
) >= 1
908 log("handle_overflow", inputs
, outputs
, div_overflow
)
909 if len(inputs
) < 2 and div_overflow
is None:
912 # div overflow is different: it's returned by the pseudo-code
913 # because it's more complex than can be done by analysing the output
914 if div_overflow
is not None:
915 ov
, ov32
= div_overflow
, div_overflow
916 # arithmetic overflow can be done by analysing the input and output
917 elif len(inputs
) >= 2:
921 input_sgn
= [exts(x
.value
, x
.bits
) < 0 for x
in inputs
]
922 output_sgn
= exts(output
.value
, output
.bits
) < 0
923 ov
= 1 if input_sgn
[0] == input_sgn
[1] and \
924 output_sgn
!= input_sgn
[0] else 0
927 input32_sgn
= [exts(x
.value
, 32) < 0 for x
in inputs
]
928 output32_sgn
= exts(output
.value
, 32) < 0
929 ov32
= 1 if input32_sgn
[0] == input32_sgn
[1] and \
930 output32_sgn
!= input32_sgn
[0] else 0
932 self
.spr
['XER'][XER_bits
['OV']] = ov
933 self
.spr
['XER'][XER_bits
['OV32']] = ov32
934 so
= self
.spr
['XER'][XER_bits
['SO']]
936 self
.spr
['XER'][XER_bits
['SO']] = so
938 def handle_comparison(self
, outputs
, cr_idx
=0):
940 assert isinstance(out
, SelectableInt
), \
941 "out zero not a SelectableInt %s" % repr(outputs
)
942 log("handle_comparison", out
.bits
, hex(out
.value
))
943 # TODO - XXX *processor* in 32-bit mode
944 # https://bugs.libre-soc.org/show_bug.cgi?id=424
946 # o32 = exts(out.value, 32)
947 # print ("handle_comparison exts 32 bit", hex(o32))
948 out
= exts(out
.value
, out
.bits
)
949 log("handle_comparison exts", hex(out
))
950 zero
= SelectableInt(out
== 0, 1)
951 positive
= SelectableInt(out
> 0, 1)
952 negative
= SelectableInt(out
< 0, 1)
953 SO
= self
.spr
['XER'][XER_bits
['SO']]
954 log("handle_comparison SO", SO
)
955 cr_field
= selectconcat(negative
, positive
, zero
, SO
)
956 log("handle_comparison cr_field", self
.cr
, cr_idx
, cr_field
)
957 self
.crl
[cr_idx
].eq(cr_field
)
959 def set_pc(self
, pc_val
):
960 self
.namespace
['NIA'] = SelectableInt(pc_val
, 64)
961 self
.pc
.update(self
.namespace
, self
.is_svp64_mode
)
963 def get_next_insn(self
):
967 pc
= self
.pc
.CIA
.value
970 ins
= self
.imem
.ld(pc
, 4, False, True, instr_fetch
=True)
972 raise KeyError("no instruction at 0x%x" % pc
)
976 """set up one instruction
978 pc
, insn
= self
.get_next_insn()
979 yield from self
.setup_next_insn(pc
, insn
)
981 def setup_next_insn(self
, pc
, ins
):
982 """set up next instruction
985 log("setup: 0x%x 0x%x %s" % (pc
, ins
& 0xffffffff, bin(ins
)))
986 log("CIA NIA", self
.respect_pc
, self
.pc
.CIA
.value
, self
.pc
.NIA
.value
)
988 yield self
.dec2
.sv_rm
.eq(0)
989 yield self
.dec2
.dec
.raw_opcode_in
.eq(ins
& 0xffffffff)
990 yield self
.dec2
.dec
.bigendian
.eq(self
.bigendian
)
991 yield self
.dec2
.state
.msr
.eq(self
.msr
.value
)
992 yield self
.dec2
.state
.pc
.eq(pc
)
993 if self
.svstate
is not None:
994 yield self
.dec2
.state
.svstate
.eq(self
.svstate
.value
)
996 # SVP64. first, check if the opcode is EXT001, and SVP64 id bits set
998 opcode
= yield self
.dec2
.dec
.opcode_in
999 pfx
= SVP64PrefixFields() # TODO should probably use SVP64PrefixDecoder
1000 pfx
.insn
.value
= opcode
1001 major
= pfx
.major
.asint(msb0
=True) # MSB0 inversion
1002 log("prefix test: opcode:", major
, bin(major
),
1003 pfx
.insn
[7] == 0b1, pfx
.insn
[9] == 0b1)
1004 self
.is_svp64_mode
= ((major
== 0b000001) and
1005 pfx
.insn
[7].value
== 0b1 and
1006 pfx
.insn
[9].value
== 0b1)
1007 self
.pc
.update_nia(self
.is_svp64_mode
)
1009 yield self
.dec2
.is_svp64_mode
.eq(self
.is_svp64_mode
)
1010 self
.namespace
['NIA'] = self
.pc
.NIA
1011 self
.namespace
['SVSTATE'] = self
.svstate
1012 if not self
.is_svp64_mode
:
1015 # in SVP64 mode. decode/print out svp64 prefix, get v3.0B instruction
1016 log("svp64.rm", bin(pfx
.rm
.asint(msb0
=True)))
1017 log(" svstate.vl", self
.svstate
.vl
)
1018 log(" svstate.mvl", self
.svstate
.maxvl
)
1019 sv_rm
= pfx
.rm
.asint(msb0
=True)
1020 ins
= self
.imem
.ld(pc
+4, 4, False, True, instr_fetch
=True)
1021 log(" svsetup: 0x%x 0x%x %s" % (pc
+4, ins
& 0xffffffff, bin(ins
)))
1022 yield self
.dec2
.dec
.raw_opcode_in
.eq(ins
& 0xffffffff) # v3.0B suffix
1023 yield self
.dec2
.sv_rm
.eq(sv_rm
) # svp64 prefix
1026 def execute_one(self
):
1027 """execute one instruction
1029 # get the disassembly code for this instruction
1030 if self
.is_svp64_mode
:
1031 if not self
.disassembly
:
1032 code
= yield from self
.get_assembly_name()
1034 code
= self
.disassembly
[self
._pc
+4]
1035 log(" svp64 sim-execute", hex(self
._pc
), code
)
1037 if not self
.disassembly
:
1038 code
= yield from self
.get_assembly_name()
1040 code
= self
.disassembly
[self
._pc
]
1041 log("sim-execute", hex(self
._pc
), code
)
1042 opname
= code
.split(' ')[0]
1044 yield from self
.call(opname
) # execute the instruction
1045 except MemException
as e
: # check for memory errors
1046 if e
.args
[0] == 'unaligned': # alignment error
1047 # run a Trap but set DAR first
1048 print("memory unaligned exception, DAR", e
.dar
)
1049 self
.spr
['DAR'] = SelectableInt(e
.dar
, 64)
1050 self
.call_trap(0x600, PIb
.PRIV
) # 0x600, privileged
1052 elif e
.args
[0] == 'invalid': # invalid
1053 # run a Trap but set DAR first
1054 log("RADIX MMU memory invalid error, mode %s" % e
.mode
)
1055 if e
.mode
== 'EXECUTE':
1056 # XXX TODO: must set a few bits in SRR1,
1057 # see microwatt loadstore1.vhdl
1058 # if m_in.segerr = '0' then
1059 # v.srr1(47 - 33) := m_in.invalid;
1060 # v.srr1(47 - 35) := m_in.perm_error; -- noexec fault
1061 # v.srr1(47 - 44) := m_in.badtree;
1062 # v.srr1(47 - 45) := m_in.rc_error;
1063 # v.intr_vec := 16#400#;
1065 # v.intr_vec := 16#480#;
1066 self
.call_trap(0x400, PIb
.PRIV
) # 0x400, privileged
1068 self
.call_trap(0x300, PIb
.PRIV
) # 0x300, privileged
1070 # not supported yet:
1071 raise e
# ... re-raise
1073 # don't use this except in special circumstances
1074 if not self
.respect_pc
:
1077 log("execute one, CIA NIA", hex(self
.pc
.CIA
.value
),
1078 hex(self
.pc
.NIA
.value
))
1080 def get_assembly_name(self
):
1081 # TODO, asmregs is from the spec, e.g. add RT,RA,RB
1082 # see http://bugs.libre-riscv.org/show_bug.cgi?id=282
1083 dec_insn
= yield self
.dec2
.e
.do
.insn
1084 insn_1_11
= yield self
.dec2
.e
.do
.insn
[1:11]
1085 asmcode
= yield self
.dec2
.dec
.op
.asmcode
1086 int_op
= yield self
.dec2
.dec
.op
.internal_op
1087 log("get assembly name asmcode", asmcode
, int_op
,
1088 hex(dec_insn
), bin(insn_1_11
))
1089 asmop
= insns
.get(asmcode
, None)
1091 # sigh reconstruct the assembly instruction name
1092 if hasattr(self
.dec2
.e
.do
, "oe"):
1093 ov_en
= yield self
.dec2
.e
.do
.oe
.oe
1094 ov_ok
= yield self
.dec2
.e
.do
.oe
.ok
1098 if hasattr(self
.dec2
.e
.do
, "rc"):
1099 rc_en
= yield self
.dec2
.e
.do
.rc
.rc
1100 rc_ok
= yield self
.dec2
.e
.do
.rc
.ok
1104 # grrrr have to special-case MUL op (see DecodeOE)
1105 log("ov %d en %d rc %d en %d op %d" %
1106 (ov_ok
, ov_en
, rc_ok
, rc_en
, int_op
))
1107 if int_op
in [MicrOp
.OP_MUL_H64
.value
, MicrOp
.OP_MUL_H32
.value
]:
1112 if not asmop
.endswith("."): # don't add "." to "andis."
1115 if hasattr(self
.dec2
.e
.do
, "lk"):
1116 lk
= yield self
.dec2
.e
.do
.lk
1119 log("int_op", int_op
)
1120 if int_op
in [MicrOp
.OP_B
.value
, MicrOp
.OP_BC
.value
]:
1121 AA
= yield self
.dec2
.dec
.fields
.FormI
.AA
[0:-1]
1125 spr_msb
= yield from self
.get_spr_msb()
1126 if int_op
== MicrOp
.OP_MFCR
.value
:
1131 # XXX TODO: for whatever weird reason this doesn't work
1132 # https://bugs.libre-soc.org/show_bug.cgi?id=390
1133 if int_op
== MicrOp
.OP_MTCRF
.value
:
1140 def get_remap_indices(self
):
1141 """WARNING, this function stores remap_idxs and remap_loopends
1142 in the class for later use. this to avoid problems with yield
1144 # go through all iterators in lock-step, advance to next remap_idx
1145 srcstep
, dststep
, ssubstep
, dsubstep
= self
.get_src_dststeps()
1146 # get four SVSHAPEs. here we are hard-coding
1147 SVSHAPE0
= self
.spr
['SVSHAPE0']
1148 SVSHAPE1
= self
.spr
['SVSHAPE1']
1149 SVSHAPE2
= self
.spr
['SVSHAPE2']
1150 SVSHAPE3
= self
.spr
['SVSHAPE3']
1151 # set up the iterators
1152 remaps
= [(SVSHAPE0
, SVSHAPE0
.get_iterator()),
1153 (SVSHAPE1
, SVSHAPE1
.get_iterator()),
1154 (SVSHAPE2
, SVSHAPE2
.get_iterator()),
1155 (SVSHAPE3
, SVSHAPE3
.get_iterator()),
1158 self
.remap_loopends
= [0] * 4
1159 self
.remap_idxs
= [0, 1, 2, 3]
1161 for i
, (shape
, remap
) in enumerate(remaps
):
1162 # zero is "disabled"
1163 if shape
.value
== 0x0:
1164 self
.remap_idxs
[i
] = 0
1165 # pick src or dststep depending on reg num (0-2=in, 3-4=out)
1166 step
= dststep
if (i
in [3, 4]) else srcstep
1167 # this is terrible. O(N^2) looking for the match. but hey.
1168 for idx
, (remap_idx
, loopends
) in enumerate(remap
):
1171 self
.remap_idxs
[i
] = remap_idx
1172 self
.remap_loopends
[i
] = loopends
1173 dbg
.append((i
, step
, remap_idx
, loopends
))
1174 for (i
, step
, remap_idx
, loopends
) in dbg
:
1175 log("SVSHAPE %d idx, end" % i
, step
, remap_idx
, bin(loopends
))
1178 def get_spr_msb(self
):
1179 dec_insn
= yield self
.dec2
.e
.do
.insn
1180 return dec_insn
& (1 << 20) != 0 # sigh - XFF.spr[-1]?
1182 def call(self
, name
):
1183 """call(opcode) - the primary execution point for instructions
1185 self
.last_st_addr
= None # reset the last known store address
1186 self
.last_ld_addr
= None # etc.
1188 ins_name
= name
.strip() # remove spaces if not already done so
1190 log("halted - not executing", ins_name
)
1193 # TODO, asmregs is from the spec, e.g. add RT,RA,RB
1194 # see http://bugs.libre-riscv.org/show_bug.cgi?id=282
1195 asmop
= yield from self
.get_assembly_name()
1196 log("call", ins_name
, asmop
)
1199 int_op
= yield self
.dec2
.dec
.op
.internal_op
1200 spr_msb
= yield from self
.get_spr_msb()
1202 instr_is_privileged
= False
1203 if int_op
in [MicrOp
.OP_ATTN
.value
,
1204 MicrOp
.OP_MFMSR
.value
,
1205 MicrOp
.OP_MTMSR
.value
,
1206 MicrOp
.OP_MTMSRD
.value
,
1208 MicrOp
.OP_RFID
.value
]:
1209 instr_is_privileged
= True
1210 if int_op
in [MicrOp
.OP_MFSPR
.value
,
1211 MicrOp
.OP_MTSPR
.value
] and spr_msb
:
1212 instr_is_privileged
= True
1214 log("is priv", instr_is_privileged
, hex(self
.msr
.value
),
1216 # check MSR priv bit and whether op is privileged: if so, throw trap
1217 if instr_is_privileged
and self
.msr
[MSRb
.PR
] == 1:
1218 self
.call_trap(0x700, PIb
.PRIV
)
1221 # check halted condition
1222 if ins_name
== 'attn':
1226 # check illegal instruction
1228 if ins_name
not in ['mtcrf', 'mtocrf']:
1229 illegal
= ins_name
!= asmop
1231 # list of instructions not being supported by binutils (.long)
1232 dotstrp
= asmop
[:-1] if asmop
[-1] == '.' else asmop
1233 if dotstrp
in [ 'fsins', 'fcoss',
1234 'ffmadds', 'fdmadds', 'ffadds',
1235 'mins', 'maxs', 'minu', 'maxu',
1236 'setvl', 'svindex', 'svremap', 'svstep', 'svshape',
1237 'grev', 'ternlogi', 'bmask', 'cprop',
1238 'absdu', 'absds', 'absdacs', 'absdacu', 'avgadd',
1244 # branch-conditional redirects to sv.bc
1245 if asmop
.startswith('bc') and self
.is_svp64_mode
:
1246 ins_name
= 'sv.%s' % ins_name
1248 log(" post-processed name", dotstrp
, ins_name
, asmop
)
1250 # illegal instructions call TRAP at 0x700
1252 print("illegal", ins_name
, asmop
)
1253 self
.call_trap(0x700, PIb
.ILLEG
)
1254 print("name %s != %s - calling ILLEGAL trap, PC: %x" %
1255 (ins_name
, asmop
, self
.pc
.CIA
.value
))
1258 # this is for setvl "Vertical" mode: if set true,
1259 # srcstep/dststep is explicitly advanced. mode says which SVSTATE to
1260 # test for Rc=1 end condition. 3 bits of all 3 loops are put into CR0
1261 self
.allow_next_step_inc
= False
1262 self
.svstate_next_mode
= 0
1264 # nop has to be supported, we could let the actual op calculate
1265 # but PowerDecoder has a pattern for nop
1266 if ins_name
is 'nop':
1267 self
.update_pc_next()
1270 # look up instruction in ISA.instrs, prepare namespace
1271 info
= self
.instrs
[ins_name
]
1272 yield from self
.prep_namespace(ins_name
, info
.form
, info
.op_fields
)
1274 # preserve order of register names
1275 input_names
= create_args(list(info
.read_regs
) +
1276 list(info
.uninit_regs
))
1277 log("input names", input_names
)
1279 # get SVP64 entry for the current instruction
1280 sv_rm
= self
.svp64rm
.instrs
.get(ins_name
)
1281 if sv_rm
is not None:
1282 dest_cr
, src_cr
, src_byname
, dest_byname
= decode_extra(sv_rm
)
1284 dest_cr
, src_cr
, src_byname
, dest_byname
= False, False, {}, {}
1285 log("sv rm", sv_rm
, dest_cr
, src_cr
, src_byname
, dest_byname
)
1287 # see if srcstep/dststep need skipping over masked-out predicate bits
1288 if (self
.is_svp64_mode
or ins_name
== 'setvl' or
1289 ins_name
in ['svremap', 'svstate']):
1290 yield from self
.svstate_pre_inc()
1291 if self
.is_svp64_mode
:
1292 pre
= yield from self
.update_new_svstate_steps()
1294 self
.svp64_reset_loop()
1296 self
.update_pc_next()
1298 srcstep
, dststep
, ssubstep
, dsubstep
= self
.get_src_dststeps()
1299 pred_dst_zero
= self
.pred_dst_zero
1300 pred_src_zero
= self
.pred_src_zero
1301 vl
= self
.svstate
.vl
1302 subvl
= yield self
.dec2
.rm_dec
.rm_in
.subvl
1304 # VL=0 in SVP64 mode means "do nothing: skip instruction"
1305 if self
.is_svp64_mode
and vl
== 0:
1306 self
.pc
.update(self
.namespace
, self
.is_svp64_mode
)
1307 log("SVP64: VL=0, end of call", self
.namespace
['CIA'],
1308 self
.namespace
['NIA'])
1311 # for when SVREMAP is active, using pre-arranged schedule.
1312 # note: modifying PowerDecoder2 needs to "settle"
1313 remap_en
= self
.svstate
.SVme
1314 persist
= self
.svstate
.RMpst
1315 active
= (persist
or self
.last_op_svshape
) and remap_en
!= 0
1316 if self
.is_svp64_mode
:
1317 yield self
.dec2
.remap_active
.eq(remap_en
if active
else 0)
1319 if persist
or self
.last_op_svshape
:
1320 remaps
= self
.get_remap_indices()
1321 if self
.is_svp64_mode
and (persist
or self
.last_op_svshape
):
1322 yield from self
.remap_debug(remaps
)
1323 # after that, settle down (combinatorial) to let Vector reg numbers
1324 # work themselves out
1326 if self
.is_svp64_mode
:
1327 remap_active
= yield self
.dec2
.remap_active
1329 remap_active
= False
1330 log("remap active", bin(remap_active
))
1332 # main input registers (RT, RA ...)
1334 for name
in input_names
:
1336 regval
= (yield from self
.get_input(name
))
1337 print("regval", regval
)
1338 inputs
.append(regval
)
1340 # arrrrgh, awful hack, to get _RT into namespace
1341 if ins_name
in ['setvl', 'svstep']:
1343 RT
= yield self
.dec2
.dec
.RT
1344 self
.namespace
[regname
] = SelectableInt(RT
, 5)
1346 self
.namespace
["RT"] = SelectableInt(0, 5)
1347 regnum
, is_vec
= yield from get_pdecode_idx_out(self
.dec2
, "RT")
1348 log('hack input reg %s %s' % (name
, str(regnum
)), is_vec
)
1350 # in SVP64 mode for LD/ST work out immediate
1351 # XXX TODO: replace_ds for DS-Form rather than D-Form.
1352 # use info.form to detect
1353 if self
.is_svp64_mode
:
1354 yield from self
.check_replace_d(info
, remap_active
)
1356 # "special" registers
1357 for special
in info
.special_regs
:
1358 if special
in special_sprs
:
1359 inputs
.append(self
.spr
[special
])
1361 inputs
.append(self
.namespace
[special
])
1363 # clear trap (trap) NIA
1364 self
.trap_nia
= None
1366 # check if this was an sv.bc* and create an indicator that
1367 # this is the last check to be made as a loop. combined with
1368 # the ALL/ANY mode we can early-exit
1369 if self
.is_svp64_mode
and ins_name
.startswith("sv.bc"):
1370 no_in_vec
= yield self
.dec2
.no_in_vec
# BI is scalar
1371 end_loop
= no_in_vec
or srcstep
== vl
-1 or dststep
== vl
-1
1372 self
.namespace
['end_loop'] = SelectableInt(end_loop
, 1)
1374 # execute actual instruction here (finally)
1375 log("inputs", inputs
)
1376 results
= info
.func(self
, *inputs
)
1377 log("results", results
)
1379 # "inject" decorator takes namespace from function locals: we need to
1380 # overwrite NIA being overwritten (sigh)
1381 if self
.trap_nia
is not None:
1382 self
.namespace
['NIA'] = self
.trap_nia
1384 log("after func", self
.namespace
['CIA'], self
.namespace
['NIA'])
1386 # check if op was a LD/ST so that debugging can check the
1388 if int_op
in [MicrOp
.OP_STORE
.value
,
1390 self
.last_st_addr
= self
.mem
.last_st_addr
1391 if int_op
in [MicrOp
.OP_LOAD
.value
,
1393 self
.last_ld_addr
= self
.mem
.last_ld_addr
1394 log("op", int_op
, MicrOp
.OP_STORE
.value
, MicrOp
.OP_LOAD
.value
,
1395 self
.last_st_addr
, self
.last_ld_addr
)
1397 # detect if CA/CA32 already in outputs (sra*, basically)
1400 output_names
= create_args(info
.write_regs
)
1401 for name
in output_names
:
1407 log("carry already done?", bin(already_done
))
1408 if hasattr(self
.dec2
.e
.do
, "output_carry"):
1409 carry_en
= yield self
.dec2
.e
.do
.output_carry
1413 yield from self
.handle_carry_(inputs
, results
, already_done
)
1415 if not self
.is_svp64_mode
: # yeah just no. not in parallel processing
1416 # detect if overflow was in return result
1419 for name
, output
in zip(output_names
, results
):
1420 if name
== 'overflow':
1423 if hasattr(self
.dec2
.e
.do
, "oe"):
1424 ov_en
= yield self
.dec2
.e
.do
.oe
.oe
1425 ov_ok
= yield self
.dec2
.e
.do
.oe
.ok
1429 log("internal overflow", overflow
, ov_en
, ov_ok
)
1431 yield from self
.handle_overflow(inputs
, results
, overflow
)
1433 # only do SVP64 dest predicated Rc=1 if dest-pred is not enabled
1435 if not self
.is_svp64_mode
or not pred_dst_zero
:
1436 if hasattr(self
.dec2
.e
.do
, "rc"):
1437 rc_en
= yield self
.dec2
.e
.do
.rc
.rc
1438 if rc_en
and ins_name
not in ['svstep']:
1439 regnum
, is_vec
= yield from get_pdecode_cr_out(self
.dec2
, "CR0")
1440 self
.handle_comparison(results
, regnum
)
1442 # any modified return results?
1444 for name
, output
in zip(output_names
, results
):
1445 yield from self
.check_write(info
, name
, output
, carry_en
)
1447 nia_update
= (yield from self
.check_step_increment(results
, rc_en
,
1450 self
.update_pc_next()
1452 def check_replace_d(self
, info
, remap_active
):
1453 replace_d
= False # update / replace constant in pseudocode
1454 ldstmode
= yield self
.dec2
.rm_dec
.ldstmode
1455 vl
= self
.svstate
.vl
1456 subvl
= yield self
.dec2
.rm_dec
.rm_in
.subvl
1457 srcstep
, dststep
= self
.new_srcstep
, self
.new_dststep
1458 ssubstep
, dsubstep
= self
.new_ssubstep
, self
.new_dsubstep
1459 if info
.form
== 'DS':
1460 # DS-Form, multiply by 4 then knock 2 bits off after
1461 imm
= yield self
.dec2
.dec
.fields
.FormDS
.DS
[0:14] * 4
1463 imm
= yield self
.dec2
.dec
.fields
.FormD
.D
[0:16]
1464 imm
= exts(imm
, 16) # sign-extend to integer
1465 # get the right step. LD is from srcstep, ST is dststep
1466 op
= yield self
.dec2
.e
.do
.insn_type
1468 if op
== MicrOp
.OP_LOAD
.value
:
1470 offsmul
= yield self
.dec2
.in1_step
1471 log("D-field REMAP src", imm
, offsmul
)
1473 offsmul
= (srcstep
* (subvl
+1)) + ssubstep
1474 log("D-field src", imm
, offsmul
)
1475 elif op
== MicrOp
.OP_STORE
.value
:
1476 # XXX NOTE! no bit-reversed STORE! this should not ever be used
1477 offsmul
= (dststep
* (subvl
+1)) + dsubstep
1478 log("D-field dst", imm
, offsmul
)
1479 # Unit-Strided LD/ST adds offset*width to immediate
1480 if ldstmode
== SVP64LDSTmode
.UNITSTRIDE
.value
:
1481 ldst_len
= yield self
.dec2
.e
.do
.data_len
1482 imm
= SelectableInt(imm
+ offsmul
* ldst_len
, 32)
1484 # Element-strided multiplies the immediate by element step
1485 elif ldstmode
== SVP64LDSTmode
.ELSTRIDE
.value
:
1486 imm
= SelectableInt(imm
* offsmul
, 32)
1489 ldst_ra_vec
= yield self
.dec2
.rm_dec
.ldst_ra_vec
1490 ldst_imz_in
= yield self
.dec2
.rm_dec
.ldst_imz_in
1491 log("LDSTmode", SVP64LDSTmode(ldstmode
),
1492 offsmul
, imm
, ldst_ra_vec
, ldst_imz_in
)
1493 # new replacement D... errr.. DS
1495 if info
.form
== 'DS':
1496 # TODO: assert 2 LSBs are zero?
1497 log("DS-Form, TODO, assert 2 LSBs zero?", bin(imm
.value
))
1498 imm
.value
= imm
.value
>> 2
1499 self
.namespace
['DS'] = imm
1501 self
.namespace
['D'] = imm
1503 def get_input(self
, name
):
1504 # using PowerDecoder2, first, find the decoder index.
1505 # (mapping name RA RB RC RS to in1, in2, in3)
1506 regnum
, is_vec
= yield from get_pdecode_idx_in(self
.dec2
, name
)
1508 # doing this is not part of svp64, it's because output
1509 # registers, to be modified, need to be in the namespace.
1510 regnum
, is_vec
= yield from get_pdecode_idx_out(self
.dec2
, name
)
1512 regnum
, is_vec
= yield from get_pdecode_idx_out2(self
.dec2
, name
)
1514 # in case getting the register number is needed, _RA, _RB
1515 regname
= "_" + name
1516 self
.namespace
[regname
] = regnum
1517 if not self
.is_svp64_mode
or not self
.pred_src_zero
:
1518 log('reading reg %s %s' % (name
, str(regnum
)), is_vec
)
1520 reg_val
= SelectableInt(self
.fpr(regnum
))
1521 elif name
is not None:
1522 reg_val
= SelectableInt(self
.gpr(regnum
))
1524 log('zero input reg %s %s' % (name
, str(regnum
)), is_vec
)
1528 def remap_debug(self
, remaps
):
1529 # just some convenient debug info
1531 sname
= 'SVSHAPE%d' % i
1532 shape
= self
.spr
[sname
]
1533 log(sname
, bin(shape
.value
))
1534 log(" lims", shape
.lims
)
1535 log(" mode", shape
.mode
)
1536 log(" skip", shape
.skip
)
1538 # set up the list of steps to remap
1539 mi0
= self
.svstate
.mi0
1540 mi1
= self
.svstate
.mi1
1541 mi2
= self
.svstate
.mi2
1542 mo0
= self
.svstate
.mo0
1543 mo1
= self
.svstate
.mo1
1544 steps
= [(self
.dec2
.in1_step
, mi0
), # RA
1545 (self
.dec2
.in2_step
, mi1
), # RB
1546 (self
.dec2
.in3_step
, mi2
), # RC
1547 (self
.dec2
.o_step
, mo0
), # RT
1548 (self
.dec2
.o2_step
, mo1
), # EA
1550 remap_idxs
= self
.remap_idxs
1552 # now cross-index the required SHAPE for each of 3-in 2-out regs
1553 rnames
= ['RA', 'RB', 'RC', 'RT', 'EA']
1554 for i
, (dstep
, shape_idx
) in enumerate(steps
):
1555 (shape
, remap
) = remaps
[shape_idx
]
1556 remap_idx
= remap_idxs
[shape_idx
]
1557 # zero is "disabled"
1558 if shape
.value
== 0x0:
1560 # now set the actual requested step to the current index
1561 yield dstep
.eq(remap_idx
)
1563 # debug printout info
1564 rremaps
.append((shape
.mode
, i
, rnames
[i
], shape_idx
, remap_idx
))
1566 log("shape remap", x
)
1568 def check_write(self
, info
, name
, output
, carry_en
):
1569 if name
== 'overflow': # ignore, done already (above)
1571 if isinstance(output
, int):
1572 output
= SelectableInt(output
, 256)
1573 if name
in ['CA', 'CA32']:
1575 log("writing %s to XER" % name
, output
)
1576 self
.spr
['XER'][XER_bits
[name
]] = output
.value
1578 log("NOT writing %s to XER" % name
, output
)
1579 elif name
in info
.special_regs
:
1580 log('writing special %s' % name
, output
, special_sprs
)
1581 if name
in special_sprs
:
1582 self
.spr
[name
] = output
1584 self
.namespace
[name
].eq(output
)
1586 log('msr written', hex(self
.msr
.value
))
1588 regnum
, is_vec
= yield from get_pdecode_idx_out(self
.dec2
, name
)
1590 regnum
, is_vec
= yield from get_pdecode_idx_out2(
1593 # temporary hack for not having 2nd output
1594 regnum
= yield getattr(self
.decoder
, name
)
1596 if self
.is_svp64_mode
and self
.pred_dst_zero
:
1597 log('zeroing reg %d %s' % (regnum
, str(output
)),
1599 output
= SelectableInt(0, 256)
1605 log('writing %s %s %s' % (ftype
, regnum
, str(output
)),
1607 if output
.bits
> 64:
1608 output
= SelectableInt(output
.value
, 64)
1610 self
.fpr
[regnum
] = output
1612 self
.gpr
[regnum
] = output
1614 def check_step_increment(self
, results
, rc_en
, asmop
, ins_name
):
1615 # check if it is the SVSTATE.src/dest step that needs incrementing
1616 # this is our Sub-Program-Counter loop from 0 to VL-1
1620 if self
.allow_next_step_inc
:
1621 log("SVSTATE_NEXT: inc requested, mode",
1622 self
.svstate_next_mode
, self
.allow_next_step_inc
)
1623 yield from self
.svstate_pre_inc()
1624 pre
= yield from self
.update_new_svstate_steps()
1626 # reset at end of loop including exit Vertical Mode
1627 log("SVSTATE_NEXT: end of loop, reset")
1628 self
.svp64_reset_loop()
1629 self
.svstate
.vfirst
= 0
1633 results
= [SelectableInt(0, 64)]
1634 self
.handle_comparison(results
) # CR0
1636 if self
.allow_next_step_inc
== 2:
1637 log("SVSTATE_NEXT: read")
1638 nia_update
= (yield from self
.svstate_post_inc(ins_name
))
1640 log("SVSTATE_NEXT: post-inc")
1641 # use actual src/dst-step here to check end, do NOT
1642 # use bit-reversed version
1643 srcstep
, dststep
= self
.new_srcstep
, self
.new_dststep
1644 ssubstep
, dsubstep
= self
.new_ssubstep
, self
.new_dsubstep
1645 remaps
= self
.get_remap_indices()
1646 remap_idxs
= self
.remap_idxs
1647 vl
= self
.svstate
.vl
1648 subvl
= yield self
.dec2
.rm_dec
.rm_in
.subvl
1649 end_src
= srcstep
== vl
-1
1650 end_dst
= dststep
== vl
-1
1651 if self
.allow_next_step_inc
!= 2:
1652 yield from self
.advance_svstate_steps(end_src
, end_dst
)
1653 self
.namespace
['SVSTATE'] = self
.svstate
.spr
1654 # set CR0 (if Rc=1) based on end
1656 endtest
= 1 if (end_src
or end_dst
) else 0
1657 #results = [SelectableInt(endtest, 64)]
1658 # self.handle_comparison(results) # CR0
1660 # see if svstep was requested, if so, which SVSTATE
1662 if self
.svstate_next_mode
> 0:
1663 shape_idx
= self
.svstate_next_mode
.value
-1
1664 endings
= self
.remap_loopends
[shape_idx
]
1665 cr_field
= SelectableInt((~endings
) << 1 | endtest
, 4)
1666 print("svstep Rc=1, CR0", cr_field
)
1667 self
.crl
[0].eq(cr_field
) # CR0
1668 if end_src
or end_dst
:
1669 # reset at end of loop including exit Vertical Mode
1670 log("SVSTATE_NEXT: after increments, reset")
1671 self
.svp64_reset_loop()
1672 self
.svstate
.vfirst
= 0
1675 if self
.is_svp64_mode
:
1676 return (yield from self
.svstate_post_inc(ins_name
))
1678 # XXX only in non-SVP64 mode!
1679 # record state of whether the current operation was an svshape,
1681 # to be able to know if it should apply in the next instruction.
1682 # also (if going to use this instruction) should disable ability
1683 # to interrupt in between. sigh.
1684 self
.last_op_svshape
= asmop
in ['svremap', 'svindex']
1688 def SVSTATE_NEXT(self
, mode
, submode
):
1689 """explicitly moves srcstep/dststep on to next element, for
1690 "Vertical-First" mode. this function is called from
1691 setvl pseudo-code, as a pseudo-op "svstep"
1693 WARNING: this function uses information that was created EARLIER
1694 due to it being in the middle of a yield, but this function is
1695 *NOT* called from yield (it's called from compiled pseudocode).
1697 self
.allow_next_step_inc
= submode
.value
+ 1
1698 log("SVSTATE_NEXT mode", mode
, submode
, self
.allow_next_step_inc
)
1699 self
.svstate_next_mode
= mode
1700 if self
.svstate_next_mode
> 0 and self
.svstate_next_mode
< 5:
1701 shape_idx
= self
.svstate_next_mode
.value
-1
1702 return SelectableInt(self
.remap_idxs
[shape_idx
], 7)
1703 if self
.svstate_next_mode
== 5:
1704 self
.svstate_next_mode
= 0
1705 return SelectableInt(self
.svstate
.srcstep
, 7)
1706 if self
.svstate_next_mode
== 6:
1707 self
.svstate_next_mode
= 0
1708 return SelectableInt(self
.svstate
.dststep
, 7)
1709 return SelectableInt(0, 7)
1711 def svstate_pre_inc(self
):
1712 """check if srcstep/dststep need to skip over masked-out predicate bits
1713 note that this is not supposed to do anything to substep,
1714 it is purely for skipping masked-out bits
1716 # get SVSTATE VL (oh and print out some debug stuff)
1717 vl
= self
.svstate
.vl
1718 subvl
= yield self
.dec2
.rm_dec
.rm_in
.subvl
1719 srcstep
= self
.svstate
.srcstep
1720 dststep
= self
.svstate
.dststep
1721 ssubstep
= self
.svstate
.ssubstep
1722 dsubstep
= self
.svstate
.dsubstep
1723 sv_a_nz
= yield self
.dec2
.sv_a_nz
1724 fft_mode
= yield self
.dec2
.use_svp64_fft
1725 in1
= yield self
.dec2
.e
.read_reg1
.data
1726 log("SVP64: VL, subvl, srcstep, dststep, ssubstep, dsybstep, sv_a_nz, "
1728 vl
, subvl
, srcstep
, dststep
, ssubstep
, dsubstep
,
1729 sv_a_nz
, in1
, fft_mode
,
1732 # get predicate mask (all 64 bits)
1733 srcmask
= dstmask
= 0xffff_ffff_ffff_ffff
1735 pmode
= yield self
.dec2
.rm_dec
.predmode
1736 pack
= yield self
.dec2
.rm_dec
.pack
1737 unpack
= yield self
.dec2
.rm_dec
.unpack
1738 reverse_gear
= yield self
.dec2
.rm_dec
.reverse_gear
1739 sv_ptype
= yield self
.dec2
.dec
.op
.SV_Ptype
1740 srcpred
= yield self
.dec2
.rm_dec
.srcpred
1741 dstpred
= yield self
.dec2
.rm_dec
.dstpred
1742 pred_src_zero
= yield self
.dec2
.rm_dec
.pred_sz
1743 pred_dst_zero
= yield self
.dec2
.rm_dec
.pred_dz
1744 if pmode
== SVP64PredMode
.INT
.value
:
1745 srcmask
= dstmask
= get_predint(self
.gpr
, dstpred
)
1746 if sv_ptype
== SVPtype
.P2
.value
:
1747 srcmask
= get_predint(self
.gpr
, srcpred
)
1748 elif pmode
== SVP64PredMode
.CR
.value
:
1749 srcmask
= dstmask
= get_predcr(self
.crl
, dstpred
, vl
)
1750 if sv_ptype
== SVPtype
.P2
.value
:
1751 srcmask
= get_predcr(self
.crl
, srcpred
, vl
)
1752 # work out if the ssubsteps are completed
1753 ssubstart
= ssubstep
== 0
1754 dsubstart
= dsubstep
== 0
1755 log(" pmode", pmode
)
1756 log(" pack/unpack", pack
, unpack
)
1757 log(" reverse", reverse_gear
)
1758 log(" ptype", sv_ptype
)
1759 log(" srcpred", bin(srcpred
))
1760 log(" dstpred", bin(dstpred
))
1761 log(" srcmask", bin(srcmask
))
1762 log(" dstmask", bin(dstmask
))
1763 log(" pred_sz", bin(pred_src_zero
))
1764 log(" pred_dz", bin(pred_dst_zero
))
1765 log(" ssubstart", ssubstart
)
1766 log(" dsubstart", dsubstart
)
1768 # okaaay, so here we simply advance srcstep (TODO dststep)
1769 # this can ONLY be done at the beginning of the "for" loop
1770 # (this is all actually a FSM so it's hell to keep track sigh)
1772 # until the predicate mask has a "1" bit... or we run out of VL
1773 # let srcstep==VL be the indicator to move to next instruction
1774 if not pred_src_zero
:
1775 while (((1 << srcstep
) & srcmask
) == 0) and (srcstep
!= vl
):
1776 log(" sskip", bin(1 << srcstep
))
1780 if not pred_dst_zero
:
1781 while (((1 << dststep
) & dstmask
) == 0) and (dststep
!= vl
):
1782 log(" dskip", bin(1 << dststep
))
1785 # now work out if the relevant mask bits require zeroing
1787 pred_dst_zero
= ((1 << dststep
) & dstmask
) == 0
1789 pred_src_zero
= ((1 << srcstep
) & srcmask
) == 0
1791 # store new srcstep / dststep
1792 self
.new_srcstep
, self
.new_dststep
= (srcstep
, dststep
)
1793 self
.new_ssubstep
, self
.new_dsubstep
= (ssubstep
, dsubstep
)
1794 self
.pred_dst_zero
, self
.pred_src_zero
= (pred_dst_zero
, pred_src_zero
)
1795 log(" new srcstep", srcstep
)
1796 log(" new dststep", dststep
)
1797 log(" new ssubstep", ssubstep
)
1798 log(" new dsubstep", dsubstep
)
1800 def get_src_dststeps(self
):
1801 """gets srcstep, dststep, and ssubstep, dsubstep
1803 return (self
.new_srcstep
, self
.new_dststep
,
1804 self
.new_ssubstep
, self
.new_dsubstep
)
1806 def update_new_svstate_steps(self
):
1807 # note, do not get the bit-reversed srcstep here!
1808 srcstep
, dststep
= self
.new_srcstep
, self
.new_dststep
1809 ssubstep
, dsubstep
= self
.new_ssubstep
, self
.new_dsubstep
1811 # update SVSTATE with new srcstep
1812 self
.svstate
.srcstep
= srcstep
1813 self
.svstate
.dststep
= dststep
1814 self
.svstate
.ssubstep
= ssubstep
1815 self
.svstate
.dsubstep
= dsubstep
1816 self
.namespace
['SVSTATE'] = self
.svstate
1817 yield self
.dec2
.state
.svstate
.eq(self
.svstate
.value
)
1818 yield Settle() # let decoder update
1819 srcstep
= self
.svstate
.srcstep
1820 dststep
= self
.svstate
.dststep
1821 ssubstep
= self
.svstate
.ssubstep
1822 dsubstep
= self
.svstate
.dsubstep
1823 vl
= self
.svstate
.vl
1824 subvl
= yield self
.dec2
.rm_dec
.rm_in
.subvl
1825 log(" srcstep", srcstep
)
1826 log(" dststep", dststep
)
1827 log(" ssubstep", ssubstep
)
1828 log(" dsubstep", dsubstep
)
1830 log(" subvl", subvl
)
1832 # check if end reached (we let srcstep overrun, above)
1833 # nothing needs doing (TODO zeroing): just do next instruction
1834 return srcstep
== vl
or dststep
== vl
1836 def svstate_post_inc(self
, insn_name
, vf
=0):
1837 # check if SV "Vertical First" mode is enabled
1838 vfirst
= self
.svstate
.vfirst
1839 log(" SV Vertical First", vf
, vfirst
)
1840 if not vf
and vfirst
== 1:
1844 # check if it is the SVSTATE.src/dest step that needs incrementing
1845 # this is our Sub-Program-Counter loop from 0 to VL-1
1846 # XXX twin predication TODO
1847 vl
= self
.svstate
.vl
1848 subvl
= yield self
.dec2
.rm_dec
.rm_in
.subvl
1849 mvl
= self
.svstate
.maxvl
1850 srcstep
= self
.svstate
.srcstep
1851 dststep
= self
.svstate
.dststep
1852 ssubstep
= self
.svstate
.ssubstep
1853 dsubstep
= self
.svstate
.dsubstep
1854 rm_mode
= yield self
.dec2
.rm_dec
.mode
1855 reverse_gear
= yield self
.dec2
.rm_dec
.reverse_gear
1856 sv_ptype
= yield self
.dec2
.dec
.op
.SV_Ptype
1857 out_vec
= not (yield self
.dec2
.no_out_vec
)
1858 in_vec
= not (yield self
.dec2
.no_in_vec
)
1859 log(" svstate.vl", vl
)
1860 log(" svstate.mvl", mvl
)
1861 log(" rm.subvl", subvl
)
1862 log(" svstate.srcstep", srcstep
)
1863 log(" svstate.dststep", dststep
)
1864 log(" svstate.ssubstep", ssubstep
)
1865 log(" svstate.dsubstep", dsubstep
)
1866 log(" mode", rm_mode
)
1867 log(" reverse", reverse_gear
)
1868 log(" out_vec", out_vec
)
1869 log(" in_vec", in_vec
)
1870 log(" sv_ptype", sv_ptype
, sv_ptype
== SVPtype
.P2
.value
)
1871 # check if srcstep needs incrementing by one, stop PC advancing
1872 # svp64 loop can end early if the dest is scalar for single-pred
1873 # but for 2-pred both src/dest have to be checked.
1874 # XXX this might not be true! it may just be LD/ST
1875 if sv_ptype
== SVPtype
.P2
.value
:
1876 svp64_is_vector
= (out_vec
or in_vec
)
1878 svp64_is_vector
= out_vec
1879 # check if this was an sv.bc* and if so did it succeed
1880 if self
.is_svp64_mode
and insn_name
.startswith("sv.bc"):
1881 end_loop
= self
.namespace
['end_loop']
1882 log("branch %s end_loop" % insn_name
, end_loop
)
1884 self
.svp64_reset_loop()
1885 self
.update_pc_next()
1887 # loops end at the first "hit" (source or dest)
1888 loopend
= ((srcstep
== vl
-1 and ssubstep
== subvl
) or
1889 (dststep
== vl
-1 and dsubstep
== subvl
))
1890 if not svp64_is_vector
or loopend
:
1891 # reset loop to zero and update NIA
1892 self
.svp64_reset_loop()
1897 # still looping, advance and update NIA
1898 yield from self
.advance_svstate_steps()
1899 self
.namespace
['SVSTATE'] = self
.svstate
1900 # not an SVP64 branch, so fix PC (NIA==CIA) for next loop
1901 # (by default, NIA is CIA+4 if v3.0B or CIA+8 if SVP64)
1902 # this way we keep repeating the same instruction (with new steps)
1903 self
.pc
.NIA
.value
= self
.pc
.CIA
.value
1904 self
.namespace
['NIA'] = self
.pc
.NIA
1905 log("end of sub-pc call", self
.namespace
['CIA'], self
.namespace
['NIA'])
1906 return False # DO NOT allow PC update whilst Sub-PC loop running
1908 def advance_svstate_steps(self
, end_src
=False, end_dst
=False):
1909 """ advance sub/steps. note that Pack/Unpack *INVERTS* the order.
1910 TODO when Pack/Unpack is set, substep becomes the *outer* loop
1912 subvl
= yield self
.dec2
.rm_dec
.rm_in
.subvl
1914 ssubstep
= self
.svstate
.ssubstep
1915 end_sub
= ssubstep
== subvl
1918 self
.svstate
.srcstep
+= SelectableInt(1, 7)
1919 self
.svstate
.ssubstep
= SelectableInt(0, 2) # reset
1921 self
.svstate
.ssubstep
+= SelectableInt(1, 2) # advance ssubstep
1923 dsubstep
= self
.svstate
.dsubstep
1924 end_sub
= dsubstep
== subvl
1927 self
.svstate
.dststep
+= SelectableInt(1, 7)
1928 self
.svstate
.dsubstep
= SelectableInt(0, 2) # reset
1930 self
.svstate
.dsubstep
+= SelectableInt(1, 2) # advance ssubstep
1932 def update_pc_next(self
):
1933 # UPDATE program counter
1934 self
.pc
.update(self
.namespace
, self
.is_svp64_mode
)
1935 self
.svstate
.spr
= self
.namespace
['SVSTATE']
1936 log("end of call", self
.namespace
['CIA'],
1937 self
.namespace
['NIA'],
1938 self
.namespace
['SVSTATE'])
1940 def svp64_reset_loop(self
):
1941 self
.svstate
.srcstep
= 0
1942 self
.svstate
.dststep
= 0
1943 self
.svstate
.ssubstep
= 0
1944 self
.svstate
.dsubstep
= 0
1945 log(" svstate.srcstep loop end (PC to update)")
1946 self
.namespace
['SVSTATE'] = self
.svstate
1948 def update_nia(self
):
1949 self
.pc
.update_nia(self
.is_svp64_mode
)
1950 self
.namespace
['NIA'] = self
.pc
.NIA
1954 """Decorator factory.
1956 this decorator will "inject" variables into the function's namespace,
1957 from the *dictionary* in self.namespace. it therefore becomes possible
1958 to make it look like a whole stack of variables which would otherwise
1959 need "self." inserted in front of them (*and* for those variables to be
1960 added to the instance) "appear" in the function.
1962 "self.namespace['SI']" for example becomes accessible as just "SI" but
1963 *only* inside the function, when decorated.
1965 def variable_injector(func
):
1967 def decorator(*args
, **kwargs
):
1969 func_globals
= func
.__globals
__ # Python 2.6+
1970 except AttributeError:
1971 func_globals
= func
.func_globals
# Earlier versions.
1973 context
= args
[0].namespace
# variables to be injected
1974 saved_values
= func_globals
.copy() # Shallow copy of dict.
1975 log("globals before", context
.keys())
1976 func_globals
.update(context
)
1977 result
= func(*args
, **kwargs
)
1978 log("globals after", func_globals
['CIA'], func_globals
['NIA'])
1979 log("args[0]", args
[0].namespace
['CIA'],
1980 args
[0].namespace
['NIA'],
1981 args
[0].namespace
['SVSTATE'])
1982 if 'end_loop' in func_globals
:
1983 log("args[0] end_loop", func_globals
['end_loop'])
1984 args
[0].namespace
= func_globals
1985 #exec (func.__code__, func_globals)
1988 # func_globals = saved_values # Undo changes.
1994 return variable_injector