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
.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 (
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 LogKind
, 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
):
263 """SVP64 RM: https://libre-soc.org/openpower/sv/svp64/"""
267 elwidth
= range(4, 6)
270 extra
= range(10, 19)
272 extra2
= dict(enumerate([
278 smask
= range(16, 19)
279 extra3
= dict(enumerate([
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
)
298 class SVP64PrefixFields(SelectableIntMapping
):
299 """SVP64 Prefix: https://libre-soc.org/openpower/sv/svp64/"""
303 rm
= ((6, 8) + tuple(range(10, 32)))
305 SV64P_MAJOR_SIZE
= len(SVP64PrefixFields
.major
)
306 SV64P_PID_SIZE
= len(SVP64PrefixFields
.pid
)
307 SV64P_RM_SIZE
= len(SVP64PrefixFields
.rm
)
311 # See PowerISA Version 3.0 B Book 1
312 # Section 2.3.1 Condition Register pages 30 - 31
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
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?
326 bits
= tuple(range(i
*4+32, (i
+1)*4+32))
327 _cr
= FieldSelectableInt(self
.cr
, bits
)
330 # decode SVP64 predicate integer to reg number and invert
333 def get_predint(gpr
, mask
):
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
:
343 if mask
== SVP64PredInt
.R3_N
.value
:
345 if mask
== SVP64PredInt
.R10
.value
:
347 if mask
== SVP64PredInt
.R10_N
.value
:
348 return ~
gpr(10).value
349 if mask
== SVP64PredInt
.R30
.value
:
351 if mask
== SVP64PredInt
.R30_N
.value
:
352 return ~
gpr(30).value
354 # decode SVP64 predicate CR to reg number and invert status
357 def _get_predcr(mask
):
358 if mask
== SVP64PredCR
.LT
.value
:
360 if mask
== SVP64PredCR
.GE
.value
:
362 if mask
== SVP64PredCR
.GT
.value
:
364 if mask
== SVP64PredCR
.LE
.value
:
366 if mask
== SVP64PredCR
.EQ
.value
:
368 if mask
== SVP64PredCR
.NE
.value
:
370 if mask
== SVP64PredCR
.SO
.value
:
372 if mask
== SVP64PredCR
.NS
.value
:
375 # read individual CR fields (0..VL-1), extract the required bit
376 # and construct the mask
379 def get_predcr(crl
, mask
, vl
):
380 idx
, noninv
= _get_predcr(mask
)
383 cr
= crl
[i
+SVP64CROffs
.CRPred
]
384 if cr
[idx
].value
== noninv
:
389 # TODO, really should just be using PowerDecoder2
390 def get_pdecode_idx_in(dec2
, name
):
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
,
404 log("get_pdecode_idx_in in2", name
, in2_sel
, In2Sel
.RB
.value
,
406 log("get_pdecode_idx_in in3", name
, in3_sel
, In3Sel
.RS
.value
,
408 log("get_pdecode_idx_in FRS in3", name
, in3_sel
, In3Sel
.FRS
.value
,
410 log("get_pdecode_idx_in FRB in2", name
, in2_sel
, In2Sel
.FRB
.value
,
412 log("get_pdecode_idx_in FRC in3", name
, in3_sel
, In3Sel
.FRC
.value
,
414 # identify which regnames map to in1/2/3
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
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!
428 assert False, "RC does not exist yet"
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
437 if in1_sel
== In1Sel
.FRA
.value
:
438 return in1
, in1_isvec
440 if in2_sel
== In2Sel
.FRB
.value
:
441 return in2
, in2_isvec
443 if in3_sel
== In3Sel
.FRC
.value
:
444 return in3
, in3_isvec
446 if in1_sel
== In1Sel
.FRS
.value
:
447 return in1
, in1_isvec
448 if in3_sel
== In3Sel
.FRS
.value
:
449 return in3
, in3_isvec
453 # TODO, really should just be using PowerDecoder2
454 def get_pdecode_cr_in(dec2
, name
):
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
)
468 log(" override", sv_override
)
469 # identify which regnames map to in / o2
471 if in_sel
== CRInSel
.BI
.value
:
473 log("get_pdecode_cr_in not found", name
)
477 # TODO, really should just be using PowerDecoder2
478 def get_pdecode_cr_out(dec2
, name
):
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
)
492 log(" override", sv_override
)
493 # identify which regnames map to out / o2
495 if out_sel
== CROutSel
.CR0
.value
:
497 log("get_pdecode_cr_out not found", name
)
501 # TODO, really should just be using PowerDecoder2
502 def get_pdecode_idx_out(dec2
, name
):
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
510 log("get_pdecode_idx_out", out_sel
, OutSel
.RA
.value
, out
, o_isvec
)
511 if out_sel
== OutSel
.RA
.value
:
514 log("get_pdecode_idx_out", out_sel
, OutSel
.RT
.value
,
515 OutSel
.RT_OR_ZERO
.value
, out
, o_isvec
,
517 if out_sel
== OutSel
.RT
.value
:
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
,
523 if out_sel
== OutSel
.RT_OR_ZERO
.value
:
526 log("get_pdecode_idx_out", out_sel
, OutSel
.FRA
.value
, out
, o_isvec
)
527 if out_sel
== OutSel
.FRA
.value
:
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
:
534 log("get_pdecode_idx_out not found", name
, out_sel
, out
, o_isvec
)
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
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
)
551 if hasattr(op
, "upd"):
552 # update mode LD/ST uses read-reg A also as an output
554 log("get_pdecode_idx_out2", upd
, LDSTMode
.update
.value
,
555 out_sel
, OutSel
.RA
.value
,
557 if upd
== LDSTMode
.update
.value
:
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:
564 log("get_pdecode_idx_out2", out_sel
, OutSel
.FRS
.value
,
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,
587 self
.bigendian
= bigendian
589 self
.is_svp64_mode
= False
590 self
.respect_pc
= respect_pc
591 if initial_sprs
is None:
593 if initial_mem
is None:
595 if fpregfile
is None:
597 if initial_insns
is None:
599 assert self
.respect_pc
== False, "instructions required to honor pc"
601 log("ISACaller insns", respect_pc
, initial_insns
, disassembly
)
602 log("ISACaller initial_msr", initial_msr
)
604 # "fake program counter" mode (for unit testing)
608 if isinstance(initial_mem
, tuple):
609 self
.fake_pc
= initial_mem
[0]
610 disasm_start
= self
.fake_pc
612 disasm_start
= initial_pc
614 # disassembly: we need this for now (not given from the decoder)
615 self
.disassembly
= {}
617 for i
, code
in enumerate(disassembly
):
618 self
.disassembly
[i
*4 + disasm_start
] = code
620 # set up registers, instruction memory, data memory, PC, SPRs, MSR, CR
621 self
.svp64rm
= SVP64RM()
622 if initial_svstate
is None:
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
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
636 # set up 4 dummy SVSHAPEs if they aren't already set up
638 sname
= 'SVSHAPE%d' % i
639 if sname
not in self
.spr
:
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
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
653 self
.mem
= RADIX(self
.mem
, self
)
655 self
.imem
= RADIX(self
.imem
, self
)
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
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)
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
674 # "undefined", just set to variable-bit-width int (use exts "max")
675 # self.undefined = SelectableInt(0, 256) # TODO, not hard-code 256!
678 self
.namespace
.update(self
.spr
)
679 self
.namespace
.update({'GPR': self
.gpr
,
683 'memassign': self
.memassign
,
686 'SVSTATE': self
.svstate
,
687 'SVSHAPE0': self
.spr
['SVSHAPE0'],
688 'SVSHAPE1': self
.spr
['SVSHAPE1'],
689 'SVSHAPE2': self
.spr
['SVSHAPE2'],
690 'SVSHAPE3': self
.spr
['SVSHAPE3'],
693 'undefined': undefined
,
694 'mode_is_64bit': True,
695 'SO': XER_bits
['SO'],
696 'XLEN': 64 # elwidth overrides, later
699 # update pc to requested start point
700 self
.set_pc(initial_pc
)
702 # field-selectable versions of Condition Register
703 self
.crl
= self
.cr_fields
.crl
705 self
.namespace
["CR%d" % i
] = self
.crl
[i
]
707 self
.decoder
= decoder2
.dec
710 super().__init
__(XLEN
=self
.namespace
["XLEN"])
714 return self
.namespace
["XLEN"]
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.
720 self
.TRAP(trap_addr
, trap_bit
)
721 self
.namespace
['NIA'] = self
.trap_nia
722 self
.pc
.update(self
.namespace
, self
.is_svp64_mode
)
724 def TRAP(self
, trap_addr
=0x700, trap_bit
=PIb
.TRAP
):
725 """TRAP> saves PC, MSR (and TODO SVSTATE), and updates MSR
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()
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
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
767 def memassign(self
, ea
, sz
, val
):
768 self
.mem
.memassign(ea
, sz
, val
)
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
774 # then "yield" fields only from op_fields rather than hard-coded
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
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
)
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)
791 sig
= getattr(fields
, name
.upper())
793 sig
= getattr(fields
, name
)
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
801 self
.namespace
[name
] = SelectableInt(val
, sig
.width
)
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
807 # add some SVSTATE convenience variables
809 srcstep
= self
.svstate
.srcstep
810 self
.namespace
['VL'] = vl
811 self
.namespace
['srcstep'] = srcstep
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)
832 def handle_carry_(self
, inputs
, outputs
, already_done
):
833 inv_a
= yield self
.dec2
.e
.do
.invert_in
835 inputs
[0] = ~inputs
[0]
837 imm_ok
= yield self
.dec2
.e
.do
.imm_data
.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):
849 log("gt input", x
, output
)
850 gt
= (gtu(x
, output
))
853 cy
= 1 if any(gts
) else 0
855 if not (1 & already_done
):
856 self
.spr
['XER'][XER_bits
['CA']] = cy
858 log("inputs", already_done
, inputs
)
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
866 b32
= (inputs
[1].value
& (1 << 32)) != 0
869 cy32
= res32 ^ a32 ^ b32
870 log("CA32 ADD", cy32
)
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)
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
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
888 inputs
[0] = ~inputs
[0]
890 imm_ok
= yield self
.dec2
.e
.do
.imm_data
.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:
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:
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
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
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
)
927 def handle_comparison(self
, outputs
, cr_idx
=0, overflow
=None, no_so
=False):
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
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
945 SO
= SelectableInt(1, 0)
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
)
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
)
961 def get_next_insn(self
):
965 pc
= self
.pc
.CIA
.value
968 ins
= self
.imem
.ld(pc
, 4, False, True, instr_fetch
=True)
970 raise KeyError("no instruction at 0x%x" % pc
)
974 """set up one instruction
976 pc
, insn
= self
.get_next_insn()
977 yield from self
.setup_next_insn(pc
, insn
)
979 def setup_next_insn(self
, pc
, ins
):
980 """set up next instruction
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
)
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
)
994 # SVP64. first, check if the opcode is EXT001, and SVP64 id bits set
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
)
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
:
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
1023 def execute_one(self
):
1024 """execute one instruction
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()
1031 code
= self
.disassembly
[self
._pc
+4]
1032 log(" svp64 sim-execute", hex(self
._pc
), code
)
1034 if not self
.disassembly
:
1035 code
= yield from self
.get_assembly_name()
1037 code
= self
.disassembly
[self
._pc
]
1038 log("sim-execute", hex(self
._pc
), code
)
1039 opname
= code
.split(' ')[0]
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
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#;
1062 # v.intr_vec := 16#480#;
1063 self
.call_trap(0x400, PIb
.PRIV
) # 0x400, privileged
1065 self
.call_trap(0x300, PIb
.PRIV
) # 0x300, privileged
1067 # not supported yet:
1068 raise e
# ... re-raise
1070 # don't use this except in special circumstances
1071 if not self
.respect_pc
:
1074 log("execute one, CIA NIA", hex(self
.pc
.CIA
.value
),
1075 hex(self
.pc
.NIA
.value
))
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)
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
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
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
]:
1109 if not asmop
.endswith("."): # don't add "." to "andis."
1112 if hasattr(self
.dec2
.e
.do
, "lk"):
1113 lk
= yield self
.dec2
.e
.do
.lk
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]
1122 spr_msb
= yield from self
.get_spr_msb()
1123 if int_op
== MicrOp
.OP_MFCR
.value
:
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
:
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
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()),
1155 self
.remap_loopends
= [0] * 4
1156 self
.remap_idxs
= [0, 1, 2, 3]
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
):
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
))
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]?
1179 def call(self
, name
):
1180 """call(opcode) - the primary execution point for instructions
1182 self
.last_st_addr
= None # reset the last known store address
1183 self
.last_ld_addr
= None # etc.
1185 ins_name
= name
.strip() # remove spaces if not already done so
1187 log("halted - not executing", ins_name
)
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
)
1196 int_op
= yield self
.dec2
.dec
.op
.internal_op
1197 spr_msb
= yield from self
.get_spr_msb()
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
,
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
1211 log("is priv", instr_is_privileged
, hex(self
.msr
.value
),
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
)
1218 # check halted condition
1219 if ins_name
== 'attn':
1223 # check illegal instruction
1225 if ins_name
not in ['mtcrf', 'mtocrf']:
1226 illegal
= ins_name
!= asmop
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',
1241 # branch-conditional redirects to sv.bc
1242 if asmop
.startswith('bc') and self
.is_svp64_mode
:
1243 ins_name
= 'sv.%s' % ins_name
1245 log(" post-processed name", dotstrp
, ins_name
, asmop
)
1247 # illegal instructions call TRAP at 0x700
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
))
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
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()
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
)
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
)
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
)
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
)
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()
1291 self
.svp64_reset_loop()
1293 self
.update_pc_next()
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
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
)
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)
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
1323 if self
.is_svp64_mode
:
1324 remap_active
= yield self
.dec2
.remap_active
1326 remap_active
= False
1327 log("remap active", bin(remap_active
))
1329 # main input registers (RT, RA ...)
1331 for name
in input_names
:
1333 regval
= (yield from self
.get_input(name
))
1334 log("regval", regval
)
1335 inputs
.append(regval
)
1337 # arrrrgh, awful hack, to get _RT into namespace
1338 if ins_name
in ['setvl', 'svstep']:
1340 RT
= yield self
.dec2
.dec
.RT
1341 self
.namespace
[regname
] = SelectableInt(RT
, 5)
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
)
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
)
1353 # "special" registers
1354 for special
in info
.special_regs
:
1355 if special
in special_sprs
:
1356 inputs
.append(self
.spr
[special
])
1358 inputs
.append(self
.namespace
[special
])
1360 # clear trap (trap) NIA
1361 self
.trap_nia
= None
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)
1371 # execute actual instruction here (finally)
1372 log("inputs", inputs
)
1373 results
= info
.func(self
, *inputs
)
1374 log("results", results
)
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
1381 log("after func", self
.namespace
['CIA'], self
.namespace
['NIA'])
1383 # check if op was a LD/ST so that debugging can check the
1385 if int_op
in [MicrOp
.OP_STORE
.value
,
1387 self
.last_st_addr
= self
.mem
.last_st_addr
1388 if int_op
in [MicrOp
.OP_LOAD
.value
,
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
)
1394 # detect if CA/CA32 already in outputs (sra*, basically)
1397 output_names
= create_args(info
.write_regs
)
1398 for name
in output_names
:
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
1410 yield from self
.handle_carry_(inputs
, results
, already_done
)
1412 # check if one of the regs was named "overflow"
1415 for name
, output
in zip(output_names
, results
):
1416 if name
== 'overflow':
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
1427 log("internal overflow", ins_name
, overflow
, "en?", ov_en
, ov_ok
)
1429 yield from self
.handle_overflow(inputs
, results
, overflow
)
1431 # only do SVP64 dest predicated Rc=1 if dest-pred is not enabled
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")
1439 # hang on... for `setvl` actually you want to test SVSTATE.VL
1440 is_setvl
= ins_name
== 'setvl'
1443 cmps
= (SelectableInt(vl
, 64), overflow
,)
1444 self
.handle_comparison(cmps
, regnum
, overflow
, no_so
=is_setvl
)
1446 # any modified return results?
1448 for name
, output
in zip(output_names
, results
):
1449 yield from self
.check_write(info
, name
, output
, carry_en
)
1451 nia_update
= (yield from self
.check_step_increment(results
, rc_en
,
1454 self
.update_pc_next()
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
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
1472 if op
== MicrOp
.OP_LOAD
.value
:
1474 offsmul
= yield self
.dec2
.in1_step
1475 log("D-field REMAP src", imm
, offsmul
)
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)
1488 # Element-strided multiplies the immediate by element step
1489 elif ldstmode
== SVP64LDSTmode
.ELSTRIDE
.value
:
1490 imm
= SelectableInt(imm
* offsmul
, 32)
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
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
1505 self
.namespace
['D'] = imm
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
)
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
)
1516 regnum
, is_vec
= yield from get_pdecode_idx_out2(self
.dec2
, name
)
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
)
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
)
1532 log('zero input reg %s %s' % (name
, str(regnum
)), is_vec
)
1536 def remap_debug(self
, remaps
):
1537 # just some convenient debug info
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
)
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
1558 remap_idxs
= self
.remap_idxs
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:
1568 # now set the actual requested step to the current index
1569 yield dstep
.eq(remap_idx
)
1571 # debug printout info
1572 rremaps
.append((shape
.mode
, i
, rnames
[i
], shape_idx
, remap_idx
))
1574 log("shape remap", x
)
1576 def check_write(self
, info
, name
, output
, carry_en
):
1577 if name
== 'overflow': # ignore, done already (above)
1579 if isinstance(output
, int):
1580 output
= SelectableInt(output
, 256)
1581 if name
in ['CA', 'CA32']:
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
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
1598 self
.namespace
[name
].eq(output
)
1600 log('msr written', hex(self
.msr
.value
))
1602 regnum
, is_vec
= yield from get_pdecode_idx_out(self
.dec2
, name
)
1604 regnum
, is_vec
= yield from get_pdecode_idx_out2(
1607 # temporary hack for not having 2nd output
1608 regnum
= yield getattr(self
.decoder
, name
)
1610 if self
.is_svp64_mode
and self
.pred_dst_zero
:
1611 log('zeroing reg %d %s' % (regnum
, str(output
)),
1613 output
= SelectableInt(0, 256)
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)
1625 self
.fpr
[regnum
] = output
1627 self
.gpr
[regnum
] = output
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
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()
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
1648 results
= [SelectableInt(0, 64)]
1649 self
.handle_comparison(results
) # CR0
1651 if self
.allow_next_step_inc
== 2:
1652 log("SVSTATE_NEXT: read")
1653 nia_update
= (yield from self
.svstate_post_inc(ins_name
))
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
1671 endtest
= 1 if (end_src
or end_dst
) else 0
1672 #results = [SelectableInt(endtest, 64)]
1673 # self.handle_comparison(results) # CR0
1675 # see if svstep was requested, if so, which SVSTATE
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
1690 if self
.is_svp64_mode
:
1691 return (yield from self
.svstate_post_inc(ins_name
))
1693 # XXX only in non-SVP64 mode!
1694 # record state of whether the current operation was an svshape,
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']
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"
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).
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)
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
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, "
1743 vl
, subvl
, srcstep
, dststep
, ssubstep
, dsubstep
,
1744 sv_a_nz
, in1
, fft_mode
,
1747 # get predicate mask (all 64 bits)
1748 srcmask
= dstmask
= 0xffff_ffff_ffff_ffff
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
)
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)
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
))
1795 if not pred_dst_zero
:
1796 while (((1 << dststep
) & dstmask
) == 0) and (dststep
!= vl
):
1797 log(" dskip", bin(1 << dststep
))
1800 # now work out if the relevant mask bits require zeroing
1802 pred_dst_zero
= ((1 << dststep
) & dstmask
) == 0
1804 pred_src_zero
= ((1 << srcstep
) & srcmask
) == 0
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
)
1815 def get_src_dststeps(self
):
1816 """gets srcstep, dststep, and ssubstep, dsubstep
1818 return (self
.new_srcstep
, self
.new_dststep
,
1819 self
.new_ssubstep
, self
.new_dsubstep
)
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
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
)
1845 log(" subvl", subvl
)
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
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:
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
)
1891 self
.svp64_reset_loop()
1892 self
.update_pc_next()
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
)
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()
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
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
1926 subvl
= yield self
.dec2
.rm_dec
.rm_in
.subvl
1928 ssubstep
= self
.svstate
.ssubstep
1929 end_sub
= ssubstep
== subvl
1932 self
.svstate
.srcstep
+= SelectableInt(1, 7)
1933 self
.svstate
.ssubstep
= SelectableInt(0, 2) # reset
1935 self
.svstate
.ssubstep
+= SelectableInt(1, 2) # advance ssubstep
1937 dsubstep
= self
.svstate
.dsubstep
1938 end_sub
= dsubstep
== subvl
1941 self
.svstate
.dststep
+= SelectableInt(1, 7)
1942 self
.svstate
.dsubstep
= SelectableInt(0, 2) # reset
1944 self
.svstate
.dsubstep
+= SelectableInt(1, 2) # advance ssubstep
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'])
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
1962 def update_nia(self
):
1963 self
.pc
.update_nia(self
.is_svp64_mode
)
1964 self
.namespace
['NIA'] = self
.pc
.NIA
1968 """Decorator factory.
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.
1976 "self.namespace['SI']" for example becomes accessible as just "SI" but
1977 *only* inside the function, when decorated.
1979 def variable_injector(func
):
1981 def decorator(*args
, **kwargs
):
1983 func_globals
= func
.__globals
__ # Python 2.6+
1984 except AttributeError:
1985 func_globals
= func
.func_globals
# Earlier versions.
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)
2002 # func_globals = saved_values # Undo changes.
2008 return variable_injector