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
, Delay
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 (
26 from openpower
.decoder
.power_insn
import SVP64Instruction
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 # See PowerISA Version 3.0 B Book 1
263 # Section 2.3.1 Condition Register pages 30 - 31
265 LT
= FL
= 0 # negative, less than, floating-point less than
266 GT
= FG
= 1 # positive, greater than, floating-point greater than
267 EQ
= FE
= 2 # equal, floating-point equal
268 SO
= FU
= 3 # summary overflow, floating-point unordered
270 def __init__(self
, init
=0):
271 # rev_cr = int('{:016b}'.format(initial_cr)[::-1], 2)
272 # self.cr = FieldSelectableInt(self._cr, list(range(32, 64)))
273 self
.cr
= SelectableInt(init
, 64) # underlying reg
274 # field-selectable versions of Condition Register TODO check bitranges?
277 bits
= tuple(range(i
*4+32, (i
+1)*4+32))
278 _cr
= FieldSelectableInt(self
.cr
, bits
)
281 # decode SVP64 predicate integer to reg number and invert
284 def get_predint(gpr
, mask
):
287 log("get_predint", mask
, SVP64PredInt
.ALWAYS
.value
)
288 if mask
== SVP64PredInt
.ALWAYS
.value
:
289 return 0xffff_ffff_ffff_ffff # 64 bits of 1
290 if mask
== SVP64PredInt
.R3_UNARY
.value
:
291 return 1 << (gpr(3).value
& 0b111111)
292 if mask
== SVP64PredInt
.R3
.value
:
294 if mask
== SVP64PredInt
.R3_N
.value
:
296 if mask
== SVP64PredInt
.R10
.value
:
298 if mask
== SVP64PredInt
.R10_N
.value
:
299 return ~
gpr(10).value
300 if mask
== SVP64PredInt
.R30
.value
:
302 if mask
== SVP64PredInt
.R30_N
.value
:
303 return ~
gpr(30).value
305 # decode SVP64 predicate CR to reg number and invert status
308 def _get_predcr(mask
):
309 if mask
== SVP64PredCR
.LT
.value
:
311 if mask
== SVP64PredCR
.GE
.value
:
313 if mask
== SVP64PredCR
.GT
.value
:
315 if mask
== SVP64PredCR
.LE
.value
:
317 if mask
== SVP64PredCR
.EQ
.value
:
319 if mask
== SVP64PredCR
.NE
.value
:
321 if mask
== SVP64PredCR
.SO
.value
:
323 if mask
== SVP64PredCR
.NS
.value
:
326 # read individual CR fields (0..VL-1), extract the required bit
327 # and construct the mask
330 def get_predcr(crl
, mask
, vl
):
331 idx
, noninv
= _get_predcr(mask
)
334 cr
= crl
[i
+SVP64CROffs
.CRPred
]
335 if cr
[idx
].value
== noninv
:
340 # TODO, really should just be using PowerDecoder2
341 def get_pdecode_idx_in(dec2
, name
):
343 in1_sel
= yield op
.in1_sel
344 in2_sel
= yield op
.in2_sel
345 in3_sel
= yield op
.in3_sel
346 # get the IN1/2/3 from the decoder (includes SVP64 remap and isvec)
347 in1
= yield dec2
.e
.read_reg1
.data
348 in2
= yield dec2
.e
.read_reg2
.data
349 in3
= yield dec2
.e
.read_reg3
.data
350 in1_isvec
= yield dec2
.in1_isvec
351 in2_isvec
= yield dec2
.in2_isvec
352 in3_isvec
= yield dec2
.in3_isvec
353 log("get_pdecode_idx_in in1", name
, in1_sel
, In1Sel
.RA
.value
,
355 log("get_pdecode_idx_in in2", name
, in2_sel
, In2Sel
.RB
.value
,
357 log("get_pdecode_idx_in in3", name
, in3_sel
, In3Sel
.RS
.value
,
359 log("get_pdecode_idx_in FRS in3", name
, in3_sel
, In3Sel
.FRS
.value
,
361 log("get_pdecode_idx_in FRB in2", name
, in2_sel
, In2Sel
.FRB
.value
,
363 log("get_pdecode_idx_in FRC in3", name
, in3_sel
, In3Sel
.FRC
.value
,
365 # identify which regnames map to in1/2/3
366 if name
== 'RA' or name
== 'RA_OR_ZERO':
367 if (in1_sel
== In1Sel
.RA
.value
or
368 (in1_sel
== In1Sel
.RA_OR_ZERO
.value
and in1
!= 0)):
369 return in1
, in1_isvec
370 if in1_sel
== In1Sel
.RA_OR_ZERO
.value
:
371 return in1
, in1_isvec
373 if in2_sel
== In2Sel
.RB
.value
:
374 return in2
, in2_isvec
375 if in3_sel
== In3Sel
.RB
.value
:
376 return in3
, in3_isvec
377 # XXX TODO, RC doesn't exist yet!
379 assert False, "RC does not exist yet"
381 if in1_sel
== In1Sel
.RS
.value
:
382 return in1
, in1_isvec
383 if in2_sel
== In2Sel
.RS
.value
:
384 return in2
, in2_isvec
385 if in3_sel
== In3Sel
.RS
.value
:
386 return in3
, in3_isvec
388 if in1_sel
== In1Sel
.FRA
.value
:
389 return in1
, in1_isvec
391 if in2_sel
== In2Sel
.FRB
.value
:
392 return in2
, in2_isvec
394 if in3_sel
== In3Sel
.FRC
.value
:
395 return in3
, in3_isvec
397 if in1_sel
== In1Sel
.FRS
.value
:
398 return in1
, in1_isvec
399 if in3_sel
== In3Sel
.FRS
.value
:
400 return in3
, in3_isvec
404 # TODO, really should just be using PowerDecoder2
405 def get_pdecode_cr_in(dec2
, name
):
407 in_sel
= yield op
.cr_in
408 in_bitfield
= yield dec2
.dec_cr_in
.cr_bitfield
.data
409 sv_cr_in
= yield op
.sv_cr_in
410 spec
= yield dec2
.crin_svdec
.spec
411 sv_override
= yield dec2
.dec_cr_in
.sv_override
412 # get the IN1/2/3 from the decoder (includes SVP64 remap and isvec)
413 in1
= yield dec2
.e
.read_cr1
.data
414 cr_isvec
= yield dec2
.cr_in_isvec
415 log("get_pdecode_cr_in", in_sel
, CROutSel
.CR0
.value
, in1
, cr_isvec
)
416 log(" sv_cr_in", sv_cr_in
)
417 log(" cr_bf", in_bitfield
)
419 log(" override", sv_override
)
420 # identify which regnames map to in / o2
422 if in_sel
== CRInSel
.BI
.value
:
424 log("get_pdecode_cr_in not found", name
)
428 # TODO, really should just be using PowerDecoder2
429 def get_pdecode_cr_out(dec2
, name
):
431 out_sel
= yield op
.cr_out
432 out_bitfield
= yield dec2
.dec_cr_out
.cr_bitfield
.data
433 sv_cr_out
= yield op
.sv_cr_out
434 spec
= yield dec2
.crout_svdec
.spec
435 sv_override
= yield dec2
.dec_cr_out
.sv_override
436 # get the IN1/2/3 from the decoder (includes SVP64 remap and isvec)
437 out
= yield dec2
.e
.write_cr
.data
438 o_isvec
= yield dec2
.o_isvec
439 log("get_pdecode_cr_out", out_sel
, CROutSel
.CR0
.value
, out
, o_isvec
)
440 log(" sv_cr_out", sv_cr_out
)
441 log(" cr_bf", out_bitfield
)
443 log(" override", sv_override
)
444 # identify which regnames map to out / o2
446 if out_sel
== CROutSel
.CR0
.value
:
448 if name
== 'CR1': # these are not actually calculated correctly
449 if out_sel
== CROutSel
.CR1
.value
:
451 log("get_pdecode_cr_out not found", name
)
455 # TODO, really should just be using PowerDecoder2
456 def get_pdecode_idx_out(dec2
, name
):
458 out_sel
= yield op
.out_sel
459 # get the IN1/2/3 from the decoder (includes SVP64 remap and isvec)
460 out
= yield dec2
.e
.write_reg
.data
461 o_isvec
= yield dec2
.o_isvec
462 # identify which regnames map to out / o2
464 log("get_pdecode_idx_out", out_sel
, OutSel
.RA
.value
, out
, o_isvec
)
465 if out_sel
== OutSel
.RA
.value
:
468 log("get_pdecode_idx_out", out_sel
, OutSel
.RT
.value
,
469 OutSel
.RT_OR_ZERO
.value
, out
, o_isvec
,
471 if out_sel
== OutSel
.RT
.value
:
473 if out_sel
== OutSel
.RT_OR_ZERO
.value
and out
!= 0:
475 elif name
== 'RT_OR_ZERO':
476 log("get_pdecode_idx_out", out_sel
, OutSel
.RT
.value
,
477 OutSel
.RT_OR_ZERO
.value
, out
, o_isvec
,
479 if out_sel
== OutSel
.RT_OR_ZERO
.value
:
482 log("get_pdecode_idx_out", out_sel
, OutSel
.FRA
.value
, out
, o_isvec
)
483 if out_sel
== OutSel
.FRA
.value
:
486 log("get_pdecode_idx_out", out_sel
, OutSel
.FRT
.value
,
487 OutSel
.FRT
.value
, out
, o_isvec
)
488 if out_sel
== OutSel
.FRT
.value
:
490 log("get_pdecode_idx_out not found", name
, out_sel
, out
, o_isvec
)
494 # TODO, really should just be using PowerDecoder2
495 def get_pdecode_idx_out2(dec2
, name
):
496 # check first if register is activated for write
498 out_sel
= yield op
.out_sel
499 out
= yield dec2
.e
.write_ea
.data
500 o_isvec
= yield dec2
.o2_isvec
501 out_ok
= yield dec2
.e
.write_ea
.ok
502 log("get_pdecode_idx_out2", name
, out_sel
, out
, out_ok
, o_isvec
)
507 if hasattr(op
, "upd"):
508 # update mode LD/ST uses read-reg A also as an output
510 log("get_pdecode_idx_out2", upd
, LDSTMode
.update
.value
,
511 out_sel
, OutSel
.RA
.value
,
513 if upd
== LDSTMode
.update
.value
:
516 int_op
= yield dec2
.dec
.op
.internal_op
517 fft_en
= yield dec2
.use_svp64_fft
518 # if int_op == MicrOp.OP_FP_MADD.value and fft_en:
520 log("get_pdecode_idx_out2", out_sel
, OutSel
.FRS
.value
,
526 class ISACaller(ISACallerHelper
, ISAFPHelpers
):
527 # decoder2 - an instance of power_decoder2
528 # regfile - a list of initial values for the registers
529 # initial_{etc} - initial values for SPRs, Condition Register, Mem, MSR
530 # respect_pc - tracks the program counter. requires initial_insns
531 def __init__(self
, decoder2
, regfile
, initial_sprs
=None, initial_cr
=0,
532 initial_mem
=None, initial_msr
=0,
543 self
.bigendian
= bigendian
545 self
.is_svp64_mode
= False
546 self
.respect_pc
= respect_pc
547 if initial_sprs
is None:
549 if initial_mem
is None:
551 if fpregfile
is None:
553 if initial_insns
is None:
555 assert self
.respect_pc
== False, "instructions required to honor pc"
557 log("ISACaller insns", respect_pc
, initial_insns
, disassembly
)
558 log("ISACaller initial_msr", initial_msr
)
560 # "fake program counter" mode (for unit testing)
564 if isinstance(initial_mem
, tuple):
565 self
.fake_pc
= initial_mem
[0]
566 disasm_start
= self
.fake_pc
568 disasm_start
= initial_pc
570 # disassembly: we need this for now (not given from the decoder)
571 self
.disassembly
= {}
573 for i
, code
in enumerate(disassembly
):
574 self
.disassembly
[i
*4 + disasm_start
] = code
576 # set up registers, instruction memory, data memory, PC, SPRs, MSR, CR
577 self
.svp64rm
= SVP64RM()
578 if initial_svstate
is None:
580 if isinstance(initial_svstate
, int):
581 initial_svstate
= SVP64State(initial_svstate
)
582 # SVSTATE, MSR and PC
583 self
.svstate
= initial_svstate
584 self
.msr
= SelectableInt(initial_msr
, 64) # underlying reg
586 # GPR FPR SPR registers
587 initial_sprs
= deepcopy(initial_sprs
) # so as not to get modified
588 self
.gpr
= GPR(decoder2
, self
, self
.svstate
, regfile
)
589 self
.fpr
= GPR(decoder2
, self
, self
.svstate
, fpregfile
)
590 self
.spr
= SPR(decoder2
, initial_sprs
) # initialise SPRs before MMU
592 # set up 4 dummy SVSHAPEs if they aren't already set up
594 sname
= 'SVSHAPE%d' % i
595 if sname
not in self
.spr
:
598 val
= self
.spr
[sname
].value
599 # make sure it's an SVSHAPE
600 self
.spr
[sname
] = SVSHAPE(val
, self
.gpr
)
601 self
.last_op_svshape
= False
604 self
.mem
= Mem(row_bytes
=8, initial_mem
=initial_mem
)
605 self
.mem
.log_fancy(kind
=LogKind
.InstrInOuts
)
606 self
.imem
= Mem(row_bytes
=4, initial_mem
=initial_insns
)
607 # MMU mode, redirect underlying Mem through RADIX
609 self
.mem
= RADIX(self
.mem
, self
)
611 self
.imem
= RADIX(self
.imem
, self
)
614 # FPR (same as GPR except for FP nums)
615 # 4.2.2 p124 FPSCR (definitely "separate" - not in SPR)
616 # note that mffs, mcrfs, mtfsf "manage" this FPSCR
617 # 2.3.1 CR (and sub-fields CR0..CR6 - CR0 SO comes from XER.SO)
618 # note that mfocrf, mfcr, mtcr, mtocrf, mcrxrx "manage" CRs
620 # 2.3.2 LR (actually SPR #8) -- Done
621 # 2.3.3 CTR (actually SPR #9) -- Done
622 # 2.3.4 TAR (actually SPR #815)
623 # 3.2.2 p45 XER (actually SPR #1) -- Done
624 # 3.2.3 p46 p232 VRSAVE (actually SPR #256)
626 # create CR then allow portions of it to be "selectable" (below)
627 self
.cr_fields
= CRFields(initial_cr
)
628 self
.cr
= self
.cr_fields
.cr
630 # "undefined", just set to variable-bit-width int (use exts "max")
631 # self.undefined = SelectableInt(0, 256) # TODO, not hard-code 256!
634 self
.namespace
.update(self
.spr
)
635 self
.namespace
.update({'GPR': self
.gpr
,
639 'memassign': self
.memassign
,
642 'SVSTATE': self
.svstate
,
643 'SVSHAPE0': self
.spr
['SVSHAPE0'],
644 'SVSHAPE1': self
.spr
['SVSHAPE1'],
645 'SVSHAPE2': self
.spr
['SVSHAPE2'],
646 'SVSHAPE3': self
.spr
['SVSHAPE3'],
649 'undefined': undefined
,
650 'mode_is_64bit': True,
651 'SO': XER_bits
['SO'],
652 'XLEN': 64 # elwidth overrides, later
655 # update pc to requested start point
656 self
.set_pc(initial_pc
)
658 # field-selectable versions of Condition Register
659 self
.crl
= self
.cr_fields
.crl
661 self
.namespace
["CR%d" % i
] = self
.crl
[i
]
663 self
.decoder
= decoder2
.dec
666 super().__init
__(XLEN
=self
.namespace
["XLEN"])
670 return self
.namespace
["XLEN"]
672 def call_trap(self
, trap_addr
, trap_bit
):
673 """calls TRAP and sets up NIA to the new execution location.
674 next instruction will begin at trap_addr.
676 self
.TRAP(trap_addr
, trap_bit
)
677 self
.namespace
['NIA'] = self
.trap_nia
678 self
.pc
.update(self
.namespace
, self
.is_svp64_mode
)
680 def TRAP(self
, trap_addr
=0x700, trap_bit
=PIb
.TRAP
):
681 """TRAP> saves PC, MSR (and TODO SVSTATE), and updates MSR
683 TRAP function is callable from inside the pseudocode itself,
684 hence the default arguments. when calling from inside ISACaller
685 it is best to use call_trap()
687 # https://bugs.libre-soc.org/show_bug.cgi?id=859
688 kaivb
= self
.spr
['KAIVB'].value
689 msr
= self
.namespace
['MSR'].value
690 log("TRAP:", hex(trap_addr
), hex(msr
), "kaivb", hex(kaivb
))
691 # store CIA(+4?) in SRR0, set NIA to 0x700
692 # store MSR in SRR1, set MSR to um errr something, have to check spec
693 # store SVSTATE (if enabled) in SVSRR0
694 self
.spr
['SRR0'].value
= self
.pc
.CIA
.value
695 self
.spr
['SRR1'].value
= msr
696 if self
.is_svp64_mode
:
697 self
.spr
['SVSRR0'] = self
.namespace
['SVSTATE'].value
698 self
.trap_nia
= SelectableInt(trap_addr |
(kaivb
&~
0x1fff), 64)
699 self
.spr
['SRR1'][trap_bit
] = 1 # change *copy* of MSR in SRR1
701 # set exception bits. TODO: this should, based on the address
702 # in figure 66 p1065 V3.0B and the table figure 65 p1063 set these
703 # bits appropriately. however it turns out that *for now* in all
704 # cases (all trap_addrs) the exact same thing is needed.
705 self
.msr
[MSRb
.IR
] = 0
706 self
.msr
[MSRb
.DR
] = 0
707 self
.msr
[MSRb
.FE0
] = 0
708 self
.msr
[MSRb
.FE1
] = 0
709 self
.msr
[MSRb
.EE
] = 0
710 self
.msr
[MSRb
.RI
] = 0
711 self
.msr
[MSRb
.SF
] = 1
712 self
.msr
[MSRb
.TM
] = 0
713 self
.msr
[MSRb
.VEC
] = 0
714 self
.msr
[MSRb
.VSX
] = 0
715 self
.msr
[MSRb
.PR
] = 0
716 self
.msr
[MSRb
.FP
] = 0
717 self
.msr
[MSRb
.PMM
] = 0
718 self
.msr
[MSRb
.TEs
] = 0
719 self
.msr
[MSRb
.TEe
] = 0
720 self
.msr
[MSRb
.UND
] = 0
721 self
.msr
[MSRb
.LE
] = 1
723 def memassign(self
, ea
, sz
, val
):
724 self
.mem
.memassign(ea
, sz
, val
)
726 def prep_namespace(self
, insn_name
, formname
, op_fields
):
727 # TODO: get field names from form in decoder*1* (not decoder2)
728 # decoder2 is hand-created, and decoder1.sigform is auto-generated
730 # then "yield" fields only from op_fields rather than hard-coded
732 fields
= self
.decoder
.sigforms
[formname
]
733 log("prep_namespace", formname
, op_fields
)
734 for name
in op_fields
:
735 # CR immediates. deal with separately. needs modifying
737 if self
.is_svp64_mode
and name
in ['BI']: # TODO, more CRs
738 # BI is a 5-bit, must reconstruct the value
739 regnum
, is_vec
= yield from get_pdecode_cr_in(self
.dec2
, name
)
740 sig
= getattr(fields
, name
)
742 # low 2 LSBs (CR field selector) remain same, CR num extended
743 assert regnum
<= 7, "sigh, TODO, 128 CR fields"
744 val
= (val
& 0b11) |
(regnum
<< 2)
747 sig
= getattr(fields
, name
.upper())
749 sig
= getattr(fields
, name
)
751 # these are all opcode fields involved in index-selection of CR,
752 # and need to do "standard" arithmetic. CR[BA+32] for example
753 # would, if using SelectableInt, only be 5-bit.
754 if name
in ['BF', 'BFA', 'BC', 'BA', 'BB', 'BT', 'BI']:
755 self
.namespace
[name
] = val
757 self
.namespace
[name
] = SelectableInt(val
, sig
.width
)
759 self
.namespace
['XER'] = self
.spr
['XER']
760 self
.namespace
['CA'] = self
.spr
['XER'][XER_bits
['CA']].value
761 self
.namespace
['CA32'] = self
.spr
['XER'][XER_bits
['CA32']].value
763 # add some SVSTATE convenience variables
765 srcstep
= self
.svstate
.srcstep
766 self
.namespace
['VL'] = vl
767 self
.namespace
['srcstep'] = srcstep
769 # sv.bc* need some extra fields
770 if self
.is_svp64_mode
and insn_name
.startswith("sv.bc"):
771 # blegh grab bits manually
772 mode
= yield self
.dec2
.rm_dec
.rm_in
.mode
773 bc_vlset
= (mode
& SVP64MODE
.BC_VLSET
) != 0
774 bc_vli
= (mode
& SVP64MODE
.BC_VLI
) != 0
775 bc_snz
= (mode
& SVP64MODE
.BC_SNZ
) != 0
776 bc_vsb
= yield self
.dec2
.rm_dec
.bc_vsb
777 bc_lru
= yield self
.dec2
.rm_dec
.bc_lru
778 bc_gate
= yield self
.dec2
.rm_dec
.bc_gate
779 sz
= yield self
.dec2
.rm_dec
.pred_sz
780 self
.namespace
['ALL'] = SelectableInt(bc_gate
, 1)
781 self
.namespace
['VSb'] = SelectableInt(bc_vsb
, 1)
782 self
.namespace
['LRu'] = SelectableInt(bc_lru
, 1)
783 self
.namespace
['VLSET'] = SelectableInt(bc_vlset
, 1)
784 self
.namespace
['VLI'] = SelectableInt(bc_vli
, 1)
785 self
.namespace
['sz'] = SelectableInt(sz
, 1)
786 self
.namespace
['SNZ'] = SelectableInt(bc_snz
, 1)
788 def handle_carry_(self
, inputs
, outputs
, already_done
):
789 inv_a
= yield self
.dec2
.e
.do
.invert_in
791 inputs
[0] = ~inputs
[0]
793 imm_ok
= yield self
.dec2
.e
.do
.imm_data
.ok
795 imm
= yield self
.dec2
.e
.do
.imm_data
.data
796 inputs
.append(SelectableInt(imm
, 64))
797 assert len(outputs
) >= 1
798 log("outputs", repr(outputs
))
799 if isinstance(outputs
, list) or isinstance(outputs
, tuple):
805 log("gt input", x
, output
)
806 gt
= (gtu(x
, output
))
809 cy
= 1 if any(gts
) else 0
811 if not (1 & already_done
):
812 self
.spr
['XER'][XER_bits
['CA']] = cy
814 log("inputs", already_done
, inputs
)
816 # ARGH... different for OP_ADD... *sigh*...
817 op
= yield self
.dec2
.e
.do
.insn_type
818 if op
== MicrOp
.OP_ADD
.value
:
819 res32
= (output
.value
& (1 << 32)) != 0
820 a32
= (inputs
[0].value
& (1 << 32)) != 0
822 b32
= (inputs
[1].value
& (1 << 32)) != 0
825 cy32
= res32 ^ a32 ^ b32
826 log("CA32 ADD", cy32
)
830 log("input", x
, output
)
831 log(" x[32:64]", x
, x
[32:64])
832 log(" o[32:64]", output
, output
[32:64])
833 gt
= (gtu(x
[32:64], output
[32:64])) == SelectableInt(1, 1)
835 cy32
= 1 if any(gts
) else 0
836 log("CA32", cy32
, gts
)
837 if not (2 & already_done
):
838 self
.spr
['XER'][XER_bits
['CA32']] = cy32
840 def handle_overflow(self
, inputs
, outputs
, div_overflow
):
841 if hasattr(self
.dec2
.e
.do
, "invert_in"):
842 inv_a
= yield self
.dec2
.e
.do
.invert_in
844 inputs
[0] = ~inputs
[0]
846 imm_ok
= yield self
.dec2
.e
.do
.imm_data
.ok
848 imm
= yield self
.dec2
.e
.do
.imm_data
.data
849 inputs
.append(SelectableInt(imm
, 64))
850 assert len(outputs
) >= 1
851 log("handle_overflow", inputs
, outputs
, div_overflow
)
852 if len(inputs
) < 2 and div_overflow
is None:
855 # div overflow is different: it's returned by the pseudo-code
856 # because it's more complex than can be done by analysing the output
857 if div_overflow
is not None:
858 ov
, ov32
= div_overflow
, div_overflow
859 # arithmetic overflow can be done by analysing the input and output
860 elif len(inputs
) >= 2:
864 input_sgn
= [exts(x
.value
, x
.bits
) < 0 for x
in inputs
]
865 output_sgn
= exts(output
.value
, output
.bits
) < 0
866 ov
= 1 if input_sgn
[0] == input_sgn
[1] and \
867 output_sgn
!= input_sgn
[0] else 0
870 input32_sgn
= [exts(x
.value
, 32) < 0 for x
in inputs
]
871 output32_sgn
= exts(output
.value
, 32) < 0
872 ov32
= 1 if input32_sgn
[0] == input32_sgn
[1] and \
873 output32_sgn
!= input32_sgn
[0] else 0
875 # now update XER OV/OV32/SO
876 so
= self
.spr
['XER'][XER_bits
['SO']]
877 new_so
= so | ov
# sticky overflow ORs in old with new
878 self
.spr
['XER'][XER_bits
['OV']] = ov
879 self
.spr
['XER'][XER_bits
['OV32']] = ov32
880 self
.spr
['XER'][XER_bits
['SO']] = new_so
881 log(" set overflow", ov
, ov32
, so
, new_so
)
883 def handle_comparison(self
, outputs
, cr_idx
=0, overflow
=None, no_so
=False):
885 assert isinstance(out
, SelectableInt
), \
886 "out zero not a SelectableInt %s" % repr(outputs
)
887 log("handle_comparison", out
.bits
, hex(out
.value
))
888 # TODO - XXX *processor* in 32-bit mode
889 # https://bugs.libre-soc.org/show_bug.cgi?id=424
891 # o32 = exts(out.value, 32)
892 # print ("handle_comparison exts 32 bit", hex(o32))
893 out
= exts(out
.value
, out
.bits
)
894 log("handle_comparison exts", hex(out
))
895 # create the three main CR flags, EQ GT LT
896 zero
= SelectableInt(out
== 0, 1)
897 positive
= SelectableInt(out
> 0, 1)
898 negative
= SelectableInt(out
< 0, 1)
899 # get (or not) XER.SO. for setvl this is important *not* to read SO
901 SO
= SelectableInt(1, 0)
903 SO
= self
.spr
['XER'][XER_bits
['SO']]
904 log("handle_comparison SO overflow", SO
, overflow
)
905 # alternative overflow checking (setvl mainly at the moment)
906 if overflow
is not None and overflow
== 1:
907 SO
= SelectableInt(1, 1)
908 # create the four CR field values and set the required CR field
909 cr_field
= selectconcat(negative
, positive
, zero
, SO
)
910 log("handle_comparison cr_field", self
.cr
, cr_idx
, cr_field
)
911 self
.crl
[cr_idx
].eq(cr_field
)
913 def set_pc(self
, pc_val
):
914 self
.namespace
['NIA'] = SelectableInt(pc_val
, 64)
915 self
.pc
.update(self
.namespace
, self
.is_svp64_mode
)
917 def get_next_insn(self
):
921 pc
= self
.pc
.CIA
.value
924 ins
= self
.imem
.ld(pc
, 4, False, True, instr_fetch
=True)
926 raise KeyError("no instruction at 0x%x" % pc
)
930 """set up one instruction
932 pc
, insn
= self
.get_next_insn()
933 yield from self
.setup_next_insn(pc
, insn
)
935 def setup_next_insn(self
, pc
, ins
):
936 """set up next instruction
939 log("setup: 0x%x 0x%x %s" % (pc
, ins
& 0xffffffff, bin(ins
)))
940 log("CIA NIA", self
.respect_pc
, self
.pc
.CIA
.value
, self
.pc
.NIA
.value
)
942 yield self
.dec2
.sv_rm
.eq(0)
943 yield self
.dec2
.dec
.raw_opcode_in
.eq(ins
& 0xffffffff)
944 yield self
.dec2
.dec
.bigendian
.eq(self
.bigendian
)
945 yield self
.dec2
.state
.msr
.eq(self
.msr
.value
)
946 yield self
.dec2
.state
.pc
.eq(pc
)
947 if self
.svstate
is not None:
948 yield self
.dec2
.state
.svstate
.eq(self
.svstate
.value
)
950 # SVP64. first, check if the opcode is EXT001, and SVP64 id bits set
952 opcode
= yield self
.dec2
.dec
.opcode_in
953 opcode
= SelectableInt(value
=opcode
, bits
=32)
954 pfx
= SVP64Instruction
.Prefix(opcode
)
955 log("prefix test: opcode:", pfx
.po
, bin(pfx
.po
), pfx
.id)
956 self
.is_svp64_mode
= bool((pfx
.po
== 0b000001) and (pfx
.id == 0b11))
957 self
.pc
.update_nia(self
.is_svp64_mode
)
959 yield self
.dec2
.is_svp64_mode
.eq(self
.is_svp64_mode
)
960 self
.namespace
['NIA'] = self
.pc
.NIA
961 self
.namespace
['SVSTATE'] = self
.svstate
962 if not self
.is_svp64_mode
:
965 # in SVP64 mode. decode/print out svp64 prefix, get v3.0B instruction
966 log("svp64.rm", bin(pfx
.rm
))
967 log(" svstate.vl", self
.svstate
.vl
)
968 log(" svstate.mvl", self
.svstate
.maxvl
)
969 ins
= self
.imem
.ld(pc
+4, 4, False, True, instr_fetch
=True)
970 log(" svsetup: 0x%x 0x%x %s" % (pc
+4, ins
& 0xffffffff, bin(ins
)))
971 yield self
.dec2
.dec
.raw_opcode_in
.eq(ins
& 0xffffffff) # v3.0B suffix
972 yield self
.dec2
.sv_rm
.eq(int(pfx
.rm
)) # svp64 prefix
975 def execute_one(self
):
976 """execute one instruction
978 # get the disassembly code for this instruction
979 if self
.is_svp64_mode
:
980 if not self
.disassembly
:
981 code
= yield from self
.get_assembly_name()
983 code
= self
.disassembly
[self
._pc
+4]
984 log(" svp64 sim-execute", hex(self
._pc
), code
)
986 if not self
.disassembly
:
987 code
= yield from self
.get_assembly_name()
989 code
= self
.disassembly
[self
._pc
]
990 log("sim-execute", hex(self
._pc
), code
)
991 opname
= code
.split(' ')[0]
993 yield from self
.call(opname
) # execute the instruction
994 except MemException
as e
: # check for memory errors
995 if e
.args
[0] == 'unaligned': # alignment error
996 # run a Trap but set DAR first
997 print("memory unaligned exception, DAR", e
.dar
)
998 self
.spr
['DAR'] = SelectableInt(e
.dar
, 64)
999 self
.call_trap(0x600, PIb
.PRIV
) # 0x600, privileged
1001 elif e
.args
[0] == 'invalid': # invalid
1002 # run a Trap but set DAR first
1003 log("RADIX MMU memory invalid error, mode %s" % e
.mode
)
1004 if e
.mode
== 'EXECUTE':
1005 # XXX TODO: must set a few bits in SRR1,
1006 # see microwatt loadstore1.vhdl
1007 # if m_in.segerr = '0' then
1008 # v.srr1(47 - 33) := m_in.invalid;
1009 # v.srr1(47 - 35) := m_in.perm_error; -- noexec fault
1010 # v.srr1(47 - 44) := m_in.badtree;
1011 # v.srr1(47 - 45) := m_in.rc_error;
1012 # v.intr_vec := 16#400#;
1014 # v.intr_vec := 16#480#;
1015 self
.call_trap(0x400, PIb
.PRIV
) # 0x400, privileged
1017 self
.call_trap(0x300, PIb
.PRIV
) # 0x300, privileged
1019 # not supported yet:
1020 raise e
# ... re-raise
1022 # don't use this except in special circumstances
1023 if not self
.respect_pc
:
1026 log("execute one, CIA NIA", hex(self
.pc
.CIA
.value
),
1027 hex(self
.pc
.NIA
.value
))
1029 def get_assembly_name(self
):
1030 # TODO, asmregs is from the spec, e.g. add RT,RA,RB
1031 # see http://bugs.libre-riscv.org/show_bug.cgi?id=282
1032 dec_insn
= yield self
.dec2
.e
.do
.insn
1033 insn_1_11
= yield self
.dec2
.e
.do
.insn
[1:11]
1034 asmcode
= yield self
.dec2
.dec
.op
.asmcode
1035 int_op
= yield self
.dec2
.dec
.op
.internal_op
1036 log("get assembly name asmcode", asmcode
, int_op
,
1037 hex(dec_insn
), bin(insn_1_11
))
1038 asmop
= insns
.get(asmcode
, None)
1040 # sigh reconstruct the assembly instruction name
1041 if hasattr(self
.dec2
.e
.do
, "oe"):
1042 ov_en
= yield self
.dec2
.e
.do
.oe
.oe
1043 ov_ok
= yield self
.dec2
.e
.do
.oe
.ok
1047 if hasattr(self
.dec2
.e
.do
, "rc"):
1048 rc_en
= yield self
.dec2
.e
.do
.rc
.rc
1049 rc_ok
= yield self
.dec2
.e
.do
.rc
.ok
1053 # grrrr have to special-case MUL op (see DecodeOE)
1054 log("ov %d en %d rc %d en %d op %d" %
1055 (ov_ok
, ov_en
, rc_ok
, rc_en
, int_op
))
1056 if int_op
in [MicrOp
.OP_MUL_H64
.value
, MicrOp
.OP_MUL_H32
.value
]:
1061 if not asmop
.endswith("."): # don't add "." to "andis."
1064 if hasattr(self
.dec2
.e
.do
, "lk"):
1065 lk
= yield self
.dec2
.e
.do
.lk
1068 log("int_op", int_op
)
1069 if int_op
in [MicrOp
.OP_B
.value
, MicrOp
.OP_BC
.value
]:
1070 AA
= yield self
.dec2
.dec
.fields
.FormI
.AA
[0:-1]
1074 spr_msb
= yield from self
.get_spr_msb()
1075 if int_op
== MicrOp
.OP_MFCR
.value
:
1080 # XXX TODO: for whatever weird reason this doesn't work
1081 # https://bugs.libre-soc.org/show_bug.cgi?id=390
1082 if int_op
== MicrOp
.OP_MTCRF
.value
:
1089 def get_remap_indices(self
):
1090 """WARNING, this function stores remap_idxs and remap_loopends
1091 in the class for later use. this to avoid problems with yield
1093 # go through all iterators in lock-step, advance to next remap_idx
1094 srcstep
, dststep
, ssubstep
, dsubstep
= self
.get_src_dststeps()
1095 # get four SVSHAPEs. here we are hard-coding
1096 SVSHAPE0
= self
.spr
['SVSHAPE0']
1097 SVSHAPE1
= self
.spr
['SVSHAPE1']
1098 SVSHAPE2
= self
.spr
['SVSHAPE2']
1099 SVSHAPE3
= self
.spr
['SVSHAPE3']
1100 # set up the iterators
1101 remaps
= [(SVSHAPE0
, SVSHAPE0
.get_iterator()),
1102 (SVSHAPE1
, SVSHAPE1
.get_iterator()),
1103 (SVSHAPE2
, SVSHAPE2
.get_iterator()),
1104 (SVSHAPE3
, SVSHAPE3
.get_iterator()),
1107 self
.remap_loopends
= [0] * 4
1108 self
.remap_idxs
= [0, 1, 2, 3]
1110 for i
, (shape
, remap
) in enumerate(remaps
):
1111 # zero is "disabled"
1112 if shape
.value
== 0x0:
1113 self
.remap_idxs
[i
] = 0
1114 # pick src or dststep depending on reg num (0-2=in, 3-4=out)
1115 step
= dststep
if (i
in [3, 4]) else srcstep
1116 # this is terrible. O(N^2) looking for the match. but hey.
1117 for idx
, (remap_idx
, loopends
) in enumerate(remap
):
1120 self
.remap_idxs
[i
] = remap_idx
1121 self
.remap_loopends
[i
] = loopends
1122 dbg
.append((i
, step
, remap_idx
, loopends
))
1123 for (i
, step
, remap_idx
, loopends
) in dbg
:
1124 log("SVSHAPE %d idx, end" % i
, step
, remap_idx
, bin(loopends
))
1127 def get_spr_msb(self
):
1128 dec_insn
= yield self
.dec2
.e
.do
.insn
1129 return dec_insn
& (1 << 20) != 0 # sigh - XFF.spr[-1]?
1131 def call(self
, name
):
1132 """call(opcode) - the primary execution point for instructions
1134 self
.last_st_addr
= None # reset the last known store address
1135 self
.last_ld_addr
= None # etc.
1137 ins_name
= name
.strip() # remove spaces if not already done so
1139 log("halted - not executing", ins_name
)
1142 # TODO, asmregs is from the spec, e.g. add RT,RA,RB
1143 # see http://bugs.libre-riscv.org/show_bug.cgi?id=282
1144 asmop
= yield from self
.get_assembly_name()
1145 log("call", ins_name
, asmop
)
1148 int_op
= yield self
.dec2
.dec
.op
.internal_op
1149 spr_msb
= yield from self
.get_spr_msb()
1151 instr_is_privileged
= False
1152 if int_op
in [MicrOp
.OP_ATTN
.value
,
1153 MicrOp
.OP_MFMSR
.value
,
1154 MicrOp
.OP_MTMSR
.value
,
1155 MicrOp
.OP_MTMSRD
.value
,
1157 MicrOp
.OP_RFID
.value
]:
1158 instr_is_privileged
= True
1159 if int_op
in [MicrOp
.OP_MFSPR
.value
,
1160 MicrOp
.OP_MTSPR
.value
] and spr_msb
:
1161 instr_is_privileged
= True
1163 log("is priv", instr_is_privileged
, hex(self
.msr
.value
),
1165 # check MSR priv bit and whether op is privileged: if so, throw trap
1166 if instr_is_privileged
and self
.msr
[MSRb
.PR
] == 1:
1167 self
.call_trap(0x700, PIb
.PRIV
)
1170 # check halted condition
1171 if ins_name
== 'attn':
1175 # check illegal instruction
1177 if ins_name
not in ['mtcrf', 'mtocrf']:
1178 illegal
= ins_name
!= asmop
1180 # list of instructions not being supported by binutils (.long)
1181 dotstrp
= asmop
[:-1] if asmop
[-1] == '.' else asmop
1182 if dotstrp
in [ 'fsins', 'fcoss',
1183 'ffmadds', 'fdmadds', 'ffadds',
1184 'mins', 'maxs', 'minu', 'maxu',
1185 'setvl', 'svindex', 'svremap', 'svstep',
1186 'svshape', 'svshape2',
1187 'grev', 'ternlogi', 'bmask', 'cprop',
1188 'absdu', 'absds', 'absdacs', 'absdacu', 'avgadd',
1194 # branch-conditional redirects to sv.bc
1195 if asmop
.startswith('bc') and self
.is_svp64_mode
:
1196 ins_name
= 'sv.%s' % ins_name
1198 log(" post-processed name", dotstrp
, ins_name
, asmop
)
1200 # illegal instructions call TRAP at 0x700
1202 print("illegal", ins_name
, asmop
)
1203 self
.call_trap(0x700, PIb
.ILLEG
)
1204 print("name %s != %s - calling ILLEGAL trap, PC: %x" %
1205 (ins_name
, asmop
, self
.pc
.CIA
.value
))
1208 # this is for setvl "Vertical" mode: if set true,
1209 # srcstep/dststep is explicitly advanced. mode says which SVSTATE to
1210 # test for Rc=1 end condition. 3 bits of all 3 loops are put into CR0
1211 self
.allow_next_step_inc
= False
1212 self
.svstate_next_mode
= 0
1214 # nop has to be supported, we could let the actual op calculate
1215 # but PowerDecoder has a pattern for nop
1216 if ins_name
== 'nop':
1217 self
.update_pc_next()
1220 # look up instruction in ISA.instrs, prepare namespace
1221 info
= self
.instrs
[ins_name
]
1222 yield from self
.prep_namespace(ins_name
, info
.form
, info
.op_fields
)
1224 # preserve order of register names
1225 input_names
= create_args(list(info
.read_regs
) +
1226 list(info
.uninit_regs
))
1227 log("input names", input_names
)
1229 # get SVP64 entry for the current instruction
1230 sv_rm
= self
.svp64rm
.instrs
.get(ins_name
)
1231 if sv_rm
is not None:
1232 dest_cr
, src_cr
, src_byname
, dest_byname
= decode_extra(sv_rm
)
1234 dest_cr
, src_cr
, src_byname
, dest_byname
= False, False, {}, {}
1235 log("sv rm", sv_rm
, dest_cr
, src_cr
, src_byname
, dest_byname
)
1237 # see if srcstep/dststep need skipping over masked-out predicate bits
1238 if (self
.is_svp64_mode
or ins_name
== 'setvl' or
1239 ins_name
in ['svremap', 'svstate']):
1240 yield from self
.svstate_pre_inc()
1241 if self
.is_svp64_mode
:
1242 pre
= yield from self
.update_new_svstate_steps()
1244 self
.svp64_reset_loop()
1246 self
.update_pc_next()
1248 srcstep
, dststep
, ssubstep
, dsubstep
= self
.get_src_dststeps()
1249 pred_dst_zero
= self
.pred_dst_zero
1250 pred_src_zero
= self
.pred_src_zero
1251 vl
= self
.svstate
.vl
1252 subvl
= yield self
.dec2
.rm_dec
.rm_in
.subvl
1254 # VL=0 in SVP64 mode means "do nothing: skip instruction"
1255 if self
.is_svp64_mode
and vl
== 0:
1256 self
.pc
.update(self
.namespace
, self
.is_svp64_mode
)
1257 log("SVP64: VL=0, end of call", self
.namespace
['CIA'],
1258 self
.namespace
['NIA'], kind
=LogKind
.InstrInOuts
)
1261 # for when SVREMAP is active, using pre-arranged schedule.
1262 # note: modifying PowerDecoder2 needs to "settle"
1263 remap_en
= self
.svstate
.SVme
1264 persist
= self
.svstate
.RMpst
1265 active
= (persist
or self
.last_op_svshape
) and remap_en
!= 0
1266 if self
.is_svp64_mode
:
1267 yield self
.dec2
.remap_active
.eq(remap_en
if active
else 0)
1269 if persist
or self
.last_op_svshape
:
1270 remaps
= self
.get_remap_indices()
1271 if self
.is_svp64_mode
and (persist
or self
.last_op_svshape
):
1272 yield from self
.remap_set_steps(remaps
)
1273 # after that, settle down (combinatorial) to let Vector reg numbers
1274 # work themselves out
1276 if self
.is_svp64_mode
:
1277 remap_active
= yield self
.dec2
.remap_active
1279 remap_active
= False
1280 log("remap active", bin(remap_active
))
1282 # main input registers (RT, RA ...)
1284 for name
in input_names
:
1286 regval
= (yield from self
.get_input(name
))
1287 log("regval", regval
)
1288 inputs
.append(regval
)
1290 # arrrrgh, awful hack, to get _RT into namespace
1291 if ins_name
in ['setvl', 'svstep']:
1293 RT
= yield self
.dec2
.dec
.RT
1294 self
.namespace
[regname
] = SelectableInt(RT
, 5)
1296 self
.namespace
["RT"] = SelectableInt(0, 5)
1297 regnum
, is_vec
= yield from get_pdecode_idx_out(self
.dec2
, "RT")
1298 log('hack input reg %s %s' % (name
, str(regnum
)), is_vec
)
1300 # in SVP64 mode for LD/ST work out immediate
1301 # XXX TODO: replace_ds for DS-Form rather than D-Form.
1302 # use info.form to detect
1303 if self
.is_svp64_mode
:
1304 yield from self
.check_replace_d(info
, remap_active
)
1306 # "special" registers
1307 for special
in info
.special_regs
:
1308 if special
in special_sprs
:
1309 inputs
.append(self
.spr
[special
])
1311 inputs
.append(self
.namespace
[special
])
1313 # clear trap (trap) NIA
1314 self
.trap_nia
= None
1316 # check if this was an sv.bc* and create an indicator that
1317 # this is the last check to be made as a loop. combined with
1318 # the ALL/ANY mode we can early-exit
1319 if self
.is_svp64_mode
and ins_name
.startswith("sv.bc"):
1320 no_in_vec
= yield self
.dec2
.no_in_vec
# BI is scalar
1321 end_loop
= no_in_vec
or srcstep
== vl
-1 or dststep
== vl
-1
1322 self
.namespace
['end_loop'] = SelectableInt(end_loop
, 1)
1324 # execute actual instruction here (finally)
1325 log("inputs", inputs
)
1326 results
= info
.func(self
, *inputs
)
1327 log("results", results
)
1329 # "inject" decorator takes namespace from function locals: we need to
1330 # overwrite NIA being overwritten (sigh)
1331 if self
.trap_nia
is not None:
1332 self
.namespace
['NIA'] = self
.trap_nia
1334 log("after func", self
.namespace
['CIA'], self
.namespace
['NIA'])
1336 # check if op was a LD/ST so that debugging can check the
1338 if int_op
in [MicrOp
.OP_STORE
.value
,
1340 self
.last_st_addr
= self
.mem
.last_st_addr
1341 if int_op
in [MicrOp
.OP_LOAD
.value
,
1343 self
.last_ld_addr
= self
.mem
.last_ld_addr
1344 log("op", int_op
, MicrOp
.OP_STORE
.value
, MicrOp
.OP_LOAD
.value
,
1345 self
.last_st_addr
, self
.last_ld_addr
)
1347 # detect if CA/CA32 already in outputs (sra*, basically)
1350 output_names
= create_args(info
.write_regs
)
1351 for name
in output_names
:
1357 log("carry already done?", bin(already_done
))
1358 if hasattr(self
.dec2
.e
.do
, "output_carry"):
1359 carry_en
= yield self
.dec2
.e
.do
.output_carry
1363 yield from self
.handle_carry_(inputs
, results
, already_done
)
1365 # check if one of the regs was named "overflow"
1368 for name
, output
in zip(output_names
, results
):
1369 if name
== 'overflow':
1372 if not self
.is_svp64_mode
: # yeah just no. not in parallel processing
1373 # detect if overflow was in return result
1374 if hasattr(self
.dec2
.e
.do
, "oe"):
1375 ov_en
= yield self
.dec2
.e
.do
.oe
.oe
1376 ov_ok
= yield self
.dec2
.e
.do
.oe
.ok
1380 log("internal overflow", ins_name
, overflow
, "en?", ov_en
, ov_ok
)
1382 yield from self
.handle_overflow(inputs
, results
, overflow
)
1384 # only do SVP64 dest predicated Rc=1 if dest-pred is not enabled
1386 if not self
.is_svp64_mode
or not pred_dst_zero
:
1387 if hasattr(self
.dec2
.e
.do
, "rc"):
1388 rc_en
= yield self
.dec2
.e
.do
.rc
.rc
1389 if rc_en
and ins_name
not in ['svstep']:
1390 if ins_name
.startswith("f"):
1391 rc_reg
= "CR1" # not calculated correctly yet (not FP compares)
1394 regnum
, is_vec
= yield from get_pdecode_cr_out(self
.dec2
, rc_reg
)
1396 # hang on... for `setvl` actually you want to test SVSTATE.VL
1397 is_setvl
= ins_name
== 'setvl'
1400 cmps
= (SelectableInt(vl
, 64), overflow
,)
1402 overflow
= None # do not override overflow except in setvl
1403 self
.handle_comparison(cmps
, regnum
, overflow
, no_so
=is_setvl
)
1405 # any modified return results?
1407 for name
, output
in zip(output_names
, results
):
1408 yield from self
.check_write(info
, name
, output
, carry_en
)
1410 nia_update
= (yield from self
.check_step_increment(results
, rc_en
,
1413 self
.update_pc_next()
1415 def check_replace_d(self
, info
, remap_active
):
1416 replace_d
= False # update / replace constant in pseudocode
1417 ldstmode
= yield self
.dec2
.rm_dec
.ldstmode
1418 vl
= self
.svstate
.vl
1419 subvl
= yield self
.dec2
.rm_dec
.rm_in
.subvl
1420 srcstep
, dststep
= self
.new_srcstep
, self
.new_dststep
1421 ssubstep
, dsubstep
= self
.new_ssubstep
, self
.new_dsubstep
1422 if info
.form
== 'DS':
1423 # DS-Form, multiply by 4 then knock 2 bits off after
1424 imm
= yield self
.dec2
.dec
.fields
.FormDS
.DS
[0:14] * 4
1426 imm
= yield self
.dec2
.dec
.fields
.FormD
.D
[0:16]
1427 imm
= exts(imm
, 16) # sign-extend to integer
1428 # get the right step. LD is from srcstep, ST is dststep
1429 op
= yield self
.dec2
.e
.do
.insn_type
1431 if op
== MicrOp
.OP_LOAD
.value
:
1433 offsmul
= yield self
.dec2
.in1_step
1434 log("D-field REMAP src", imm
, offsmul
)
1436 offsmul
= (srcstep
* (subvl
+1)) + ssubstep
1437 log("D-field src", imm
, offsmul
)
1438 elif op
== MicrOp
.OP_STORE
.value
:
1439 # XXX NOTE! no bit-reversed STORE! this should not ever be used
1440 offsmul
= (dststep
* (subvl
+1)) + dsubstep
1441 log("D-field dst", imm
, offsmul
)
1442 # Unit-Strided LD/ST adds offset*width to immediate
1443 if ldstmode
== SVP64LDSTmode
.UNITSTRIDE
.value
:
1444 ldst_len
= yield self
.dec2
.e
.do
.data_len
1445 imm
= SelectableInt(imm
+ offsmul
* ldst_len
, 32)
1447 # Element-strided multiplies the immediate by element step
1448 elif ldstmode
== SVP64LDSTmode
.ELSTRIDE
.value
:
1449 imm
= SelectableInt(imm
* offsmul
, 32)
1452 ldst_ra_vec
= yield self
.dec2
.rm_dec
.ldst_ra_vec
1453 ldst_imz_in
= yield self
.dec2
.rm_dec
.ldst_imz_in
1454 log("LDSTmode", SVP64LDSTmode(ldstmode
),
1455 offsmul
, imm
, ldst_ra_vec
, ldst_imz_in
)
1456 # new replacement D... errr.. DS
1458 if info
.form
== 'DS':
1459 # TODO: assert 2 LSBs are zero?
1460 log("DS-Form, TODO, assert 2 LSBs zero?", bin(imm
.value
))
1461 imm
.value
= imm
.value
>> 2
1462 self
.namespace
['DS'] = imm
1464 self
.namespace
['D'] = imm
1466 def get_input(self
, name
):
1467 # using PowerDecoder2, first, find the decoder index.
1468 # (mapping name RA RB RC RS to in1, in2, in3)
1469 regnum
, is_vec
= yield from get_pdecode_idx_in(self
.dec2
, name
)
1471 # doing this is not part of svp64, it's because output
1472 # registers, to be modified, need to be in the namespace.
1473 regnum
, is_vec
= yield from get_pdecode_idx_out(self
.dec2
, name
)
1475 regnum
, is_vec
= yield from get_pdecode_idx_out2(self
.dec2
, name
)
1477 # in case getting the register number is needed, _RA, _RB
1478 regname
= "_" + name
1479 self
.namespace
[regname
] = regnum
1480 if not self
.is_svp64_mode
or not self
.pred_src_zero
:
1481 log('reading reg %s %s' % (name
, str(regnum
)), is_vec
)
1483 reg_val
= SelectableInt(self
.fpr(regnum
))
1484 log("read reg %d: 0x%x" % (regnum
, reg_val
.value
))
1485 elif name
is not None:
1486 reg_val
= SelectableInt(self
.gpr(regnum
))
1487 log("read reg %d: 0x%x" % (regnum
, reg_val
.value
))
1489 log('zero input reg %s %s' % (name
, str(regnum
)), is_vec
)
1493 def remap_set_steps(self
, remaps
):
1494 """remap_set_steps sets up the in1/2/3 and out1/2 steps.
1495 they work in concert with PowerDecoder2 at the moment,
1496 there is no HDL implementation of REMAP. therefore this
1497 function, because ISACaller still uses PowerDecoder2,
1498 will *explicitly* write the dec2.XX_step values. this has
1501 # just some convenient debug info
1503 sname
= 'SVSHAPE%d' % i
1504 shape
= self
.spr
[sname
]
1505 log(sname
, bin(shape
.value
))
1506 log(" lims", shape
.lims
)
1507 log(" mode", shape
.mode
)
1508 log(" skip", shape
.skip
)
1510 # set up the list of steps to remap
1511 mi0
= self
.svstate
.mi0
1512 mi1
= self
.svstate
.mi1
1513 mi2
= self
.svstate
.mi2
1514 mo0
= self
.svstate
.mo0
1515 mo1
= self
.svstate
.mo1
1516 steps
= [(self
.dec2
.in1_step
, mi0
), # RA
1517 (self
.dec2
.in2_step
, mi1
), # RB
1518 (self
.dec2
.in3_step
, mi2
), # RC
1519 (self
.dec2
.o_step
, mo0
), # RT
1520 (self
.dec2
.o2_step
, mo1
), # EA
1522 remap_idxs
= self
.remap_idxs
1524 # now cross-index the required SHAPE for each of 3-in 2-out regs
1525 rnames
= ['RA', 'RB', 'RC', 'RT', 'EA']
1526 for i
, (dstep
, shape_idx
) in enumerate(steps
):
1527 (shape
, remap
) = remaps
[shape_idx
]
1528 remap_idx
= remap_idxs
[shape_idx
]
1529 # zero is "disabled"
1530 if shape
.value
== 0x0:
1532 # now set the actual requested step to the current index
1533 yield dstep
.eq(remap_idx
)
1535 # debug printout info
1536 rremaps
.append((shape
.mode
, i
, rnames
[i
], shape_idx
, remap_idx
))
1538 log("shape remap", x
)
1540 def check_write(self
, info
, name
, output
, carry_en
):
1541 if name
== 'overflow': # ignore, done already (above)
1543 if isinstance(output
, int):
1544 output
= SelectableInt(output
, 256)
1545 if name
in ['CA', 'CA32']:
1547 log("writing %s to XER" % name
, output
)
1548 log("write XER %s 0x%x" % (name
, output
.value
))
1549 self
.spr
['XER'][XER_bits
[name
]] = output
.value
1551 log("NOT writing %s to XER" % name
, output
)
1552 elif name
in info
.special_regs
:
1553 log('writing special %s' % name
, output
, special_sprs
)
1554 log("write reg %s 0x%x" % (name
, output
.value
))
1555 if name
in special_sprs
:
1556 self
.spr
[name
] = output
1558 self
.namespace
[name
].eq(output
)
1560 log('msr written', hex(self
.msr
.value
))
1562 regnum
, is_vec
= yield from get_pdecode_idx_out(self
.dec2
, name
)
1564 regnum
, is_vec
= yield from get_pdecode_idx_out2(
1567 # temporary hack for not having 2nd output
1568 regnum
= yield getattr(self
.decoder
, name
)
1570 if self
.is_svp64_mode
and self
.pred_dst_zero
:
1571 log('zeroing reg %d %s' % (regnum
, str(output
)),
1573 output
= SelectableInt(0, 256)
1579 log("write reg %s%d %0xx" % (reg_prefix
, regnum
, output
.value
))
1580 if output
.bits
> 64:
1581 output
= SelectableInt(output
.value
, 64)
1583 self
.fpr
[regnum
] = output
1585 self
.gpr
[regnum
] = output
1587 def check_step_increment(self
, results
, rc_en
, asmop
, ins_name
):
1588 # check if it is the SVSTATE.src/dest step that needs incrementing
1589 # this is our Sub-Program-Counter loop from 0 to VL-1
1593 if self
.allow_next_step_inc
:
1594 log("SVSTATE_NEXT: inc requested, mode",
1595 self
.svstate_next_mode
, self
.allow_next_step_inc
)
1596 yield from self
.svstate_pre_inc()
1597 pre
= yield from self
.update_new_svstate_steps()
1599 # reset at end of loop including exit Vertical Mode
1600 log("SVSTATE_NEXT: end of loop, reset")
1601 self
.svp64_reset_loop()
1602 self
.svstate
.vfirst
= 0
1606 results
= [SelectableInt(0, 64)]
1607 self
.handle_comparison(results
) # CR0
1609 if self
.allow_next_step_inc
== 2:
1610 log("SVSTATE_NEXT: read")
1611 nia_update
= (yield from self
.svstate_post_inc(ins_name
))
1613 log("SVSTATE_NEXT: post-inc")
1614 # use actual src/dst-step here to check end, do NOT
1615 # use bit-reversed version
1616 srcstep
, dststep
= self
.new_srcstep
, self
.new_dststep
1617 ssubstep
, dsubstep
= self
.new_ssubstep
, self
.new_dsubstep
1618 remaps
= self
.get_remap_indices()
1619 remap_idxs
= self
.remap_idxs
1620 vl
= self
.svstate
.vl
1621 subvl
= yield self
.dec2
.rm_dec
.rm_in
.subvl
1622 end_src
= srcstep
== vl
-1
1623 end_dst
= dststep
== vl
-1
1624 if self
.allow_next_step_inc
!= 2:
1625 yield from self
.advance_svstate_steps(end_src
, end_dst
)
1626 self
.namespace
['SVSTATE'] = self
.svstate
.spr
1627 # set CR0 (if Rc=1) based on end
1629 endtest
= 1 if (end_src
or end_dst
) else 0
1630 #results = [SelectableInt(endtest, 64)]
1631 # self.handle_comparison(results) # CR0
1633 # see if svstep was requested, if so, which SVSTATE
1635 if self
.svstate_next_mode
> 0:
1636 shape_idx
= self
.svstate_next_mode
.value
-1
1637 endings
= self
.remap_loopends
[shape_idx
]
1638 cr_field
= SelectableInt((~endings
) << 1 | endtest
, 4)
1639 log("svstep Rc=1, CR0", cr_field
)
1640 self
.crl
[0].eq(cr_field
) # CR0
1641 if end_src
or end_dst
:
1642 # reset at end of loop including exit Vertical Mode
1643 log("SVSTATE_NEXT: after increments, reset")
1644 self
.svp64_reset_loop()
1645 self
.svstate
.vfirst
= 0
1648 if self
.is_svp64_mode
:
1649 return (yield from self
.svstate_post_inc(ins_name
))
1651 # XXX only in non-SVP64 mode!
1652 # record state of whether the current operation was an svshape,
1654 # to be able to know if it should apply in the next instruction.
1655 # also (if going to use this instruction) should disable ability
1656 # to interrupt in between. sigh.
1657 self
.last_op_svshape
= asmop
in ['svremap', 'svindex', 'svshape2']
1661 def SVSTATE_NEXT(self
, mode
, submode
):
1662 """explicitly moves srcstep/dststep on to next element, for
1663 "Vertical-First" mode. this function is called from
1664 setvl pseudo-code, as a pseudo-op "svstep"
1666 WARNING: this function uses information that was created EARLIER
1667 due to it being in the middle of a yield, but this function is
1668 *NOT* called from yield (it's called from compiled pseudocode).
1670 self
.allow_next_step_inc
= submode
.value
+ 1
1671 log("SVSTATE_NEXT mode", mode
, submode
, self
.allow_next_step_inc
)
1672 self
.svstate_next_mode
= mode
1673 if self
.svstate_next_mode
> 0 and self
.svstate_next_mode
< 5:
1674 shape_idx
= self
.svstate_next_mode
.value
-1
1675 return SelectableInt(self
.remap_idxs
[shape_idx
], 7)
1676 if self
.svstate_next_mode
== 5:
1677 self
.svstate_next_mode
= 0
1678 return SelectableInt(self
.svstate
.srcstep
, 7)
1679 if self
.svstate_next_mode
== 6:
1680 self
.svstate_next_mode
= 0
1681 return SelectableInt(self
.svstate
.dststep
, 7)
1682 return SelectableInt(0, 7)
1684 def svstate_pre_inc(self
):
1685 """check if srcstep/dststep need to skip over masked-out predicate bits
1686 note that this is not supposed to do anything to substep,
1687 it is purely for skipping masked-out bits
1689 # get SVSTATE VL (oh and print out some debug stuff)
1690 # yield Delay(1e-10) # make changes visible
1691 vl
= self
.svstate
.vl
1692 subvl
= yield self
.dec2
.rm_dec
.rm_in
.subvl
1693 srcstep
= self
.svstate
.srcstep
1694 dststep
= self
.svstate
.dststep
1695 ssubstep
= self
.svstate
.ssubstep
1696 dsubstep
= self
.svstate
.dsubstep
1697 sv_a_nz
= yield self
.dec2
.sv_a_nz
1698 fft_mode
= yield self
.dec2
.use_svp64_fft
1699 in1
= yield self
.dec2
.e
.read_reg1
.data
1700 log("SVP64: VL, subvl, srcstep, dststep, ssubstep, dsybstep, sv_a_nz, "
1702 vl
, subvl
, srcstep
, dststep
, ssubstep
, dsubstep
,
1703 sv_a_nz
, in1
, fft_mode
,
1706 # get predicate mask (all 64 bits)
1707 srcmask
= dstmask
= 0xffff_ffff_ffff_ffff
1709 pmode
= yield self
.dec2
.rm_dec
.predmode
1710 pack
= yield self
.dec2
.rm_dec
.pack
1711 unpack
= yield self
.dec2
.rm_dec
.unpack
1712 reverse_gear
= yield self
.dec2
.rm_dec
.reverse_gear
1713 sv_ptype
= yield self
.dec2
.dec
.op
.SV_Ptype
1714 srcpred
= yield self
.dec2
.rm_dec
.srcpred
1715 dstpred
= yield self
.dec2
.rm_dec
.dstpred
1716 pred_src_zero
= yield self
.dec2
.rm_dec
.pred_sz
1717 pred_dst_zero
= yield self
.dec2
.rm_dec
.pred_dz
1718 if pmode
== SVP64PredMode
.INT
.value
:
1719 srcmask
= dstmask
= get_predint(self
.gpr
, dstpred
)
1720 if sv_ptype
== SVPtype
.P2
.value
:
1721 srcmask
= get_predint(self
.gpr
, srcpred
)
1722 elif pmode
== SVP64PredMode
.CR
.value
:
1723 srcmask
= dstmask
= get_predcr(self
.crl
, dstpred
, vl
)
1724 if sv_ptype
== SVPtype
.P2
.value
:
1725 srcmask
= get_predcr(self
.crl
, srcpred
, vl
)
1726 # work out if the ssubsteps are completed
1727 ssubstart
= ssubstep
== 0
1728 dsubstart
= dsubstep
== 0
1729 log(" pmode", pmode
)
1730 log(" pack/unpack", pack
, unpack
)
1731 log(" reverse", reverse_gear
)
1732 log(" ptype", sv_ptype
)
1733 log(" srcpred", bin(srcpred
))
1734 log(" dstpred", bin(dstpred
))
1735 log(" srcmask", bin(srcmask
))
1736 log(" dstmask", bin(dstmask
))
1737 log(" pred_sz", bin(pred_src_zero
))
1738 log(" pred_dz", bin(pred_dst_zero
))
1739 log(" ssubstart", ssubstart
)
1740 log(" dsubstart", dsubstart
)
1742 # okaaay, so here we simply advance srcstep (TODO dststep)
1743 # this can ONLY be done at the beginning of the "for" loop
1744 # (this is all actually a FSM so it's hell to keep track sigh)
1746 # until the predicate mask has a "1" bit... or we run out of VL
1747 # let srcstep==VL be the indicator to move to next instruction
1748 if not pred_src_zero
:
1749 while (((1 << srcstep
) & srcmask
) == 0) and (srcstep
!= vl
):
1750 log(" sskip", bin(1 << srcstep
))
1754 if not pred_dst_zero
:
1755 while (((1 << dststep
) & dstmask
) == 0) and (dststep
!= vl
):
1756 log(" dskip", bin(1 << dststep
))
1759 # now work out if the relevant mask bits require zeroing
1761 pred_dst_zero
= ((1 << dststep
) & dstmask
) == 0
1763 pred_src_zero
= ((1 << srcstep
) & srcmask
) == 0
1765 # store new srcstep / dststep
1766 self
.new_srcstep
, self
.new_dststep
= (srcstep
, dststep
)
1767 self
.new_ssubstep
, self
.new_dsubstep
= (ssubstep
, dsubstep
)
1768 self
.pred_dst_zero
, self
.pred_src_zero
= (pred_dst_zero
, pred_src_zero
)
1769 log(" new srcstep", srcstep
)
1770 log(" new dststep", dststep
)
1771 log(" new ssubstep", ssubstep
)
1772 log(" new dsubstep", dsubstep
)
1774 def get_src_dststeps(self
):
1775 """gets srcstep, dststep, and ssubstep, dsubstep
1777 return (self
.new_srcstep
, self
.new_dststep
,
1778 self
.new_ssubstep
, self
.new_dsubstep
)
1780 def update_new_svstate_steps(self
):
1781 # note, do not get the bit-reversed srcstep here!
1782 srcstep
, dststep
= self
.new_srcstep
, self
.new_dststep
1783 ssubstep
, dsubstep
= self
.new_ssubstep
, self
.new_dsubstep
1785 # update SVSTATE with new srcstep
1786 self
.svstate
.srcstep
= srcstep
1787 self
.svstate
.dststep
= dststep
1788 self
.svstate
.ssubstep
= ssubstep
1789 self
.svstate
.dsubstep
= dsubstep
1790 self
.namespace
['SVSTATE'] = self
.svstate
1791 yield self
.dec2
.state
.svstate
.eq(self
.svstate
.value
)
1792 yield Settle() # let decoder update
1793 srcstep
= self
.svstate
.srcstep
1794 dststep
= self
.svstate
.dststep
1795 ssubstep
= self
.svstate
.ssubstep
1796 dsubstep
= self
.svstate
.dsubstep
1797 vl
= self
.svstate
.vl
1798 subvl
= yield self
.dec2
.rm_dec
.rm_in
.subvl
1799 log(" srcstep", srcstep
)
1800 log(" dststep", dststep
)
1801 log(" ssubstep", ssubstep
)
1802 log(" dsubstep", dsubstep
)
1804 log(" subvl", subvl
)
1806 # check if end reached (we let srcstep overrun, above)
1807 # nothing needs doing (TODO zeroing): just do next instruction
1808 return srcstep
== vl
or dststep
== vl
1810 def svstate_post_inc(self
, insn_name
, vf
=0):
1811 # check if SV "Vertical First" mode is enabled
1812 vfirst
= self
.svstate
.vfirst
1813 log(" SV Vertical First", vf
, vfirst
)
1814 if not vf
and vfirst
== 1:
1818 # check if it is the SVSTATE.src/dest step that needs incrementing
1819 # this is our Sub-Program-Counter loop from 0 to VL-1
1820 # XXX twin predication TODO
1821 vl
= self
.svstate
.vl
1822 subvl
= yield self
.dec2
.rm_dec
.rm_in
.subvl
1823 mvl
= self
.svstate
.maxvl
1824 srcstep
= self
.svstate
.srcstep
1825 dststep
= self
.svstate
.dststep
1826 ssubstep
= self
.svstate
.ssubstep
1827 dsubstep
= self
.svstate
.dsubstep
1828 rm_mode
= yield self
.dec2
.rm_dec
.mode
1829 reverse_gear
= yield self
.dec2
.rm_dec
.reverse_gear
1830 sv_ptype
= yield self
.dec2
.dec
.op
.SV_Ptype
1831 out_vec
= not (yield self
.dec2
.no_out_vec
)
1832 in_vec
= not (yield self
.dec2
.no_in_vec
)
1833 log(" svstate.vl", vl
)
1834 log(" svstate.mvl", mvl
)
1835 log(" rm.subvl", subvl
)
1836 log(" svstate.srcstep", srcstep
)
1837 log(" svstate.dststep", dststep
)
1838 log(" svstate.ssubstep", ssubstep
)
1839 log(" svstate.dsubstep", dsubstep
)
1840 log(" mode", rm_mode
)
1841 log(" reverse", reverse_gear
)
1842 log(" out_vec", out_vec
)
1843 log(" in_vec", in_vec
)
1844 log(" sv_ptype", sv_ptype
, sv_ptype
== SVPtype
.P2
.value
)
1845 # check if this was an sv.bc* and if so did it succeed
1846 if self
.is_svp64_mode
and insn_name
.startswith("sv.bc"):
1847 end_loop
= self
.namespace
['end_loop']
1848 log("branch %s end_loop" % insn_name
, end_loop
)
1850 self
.svp64_reset_loop()
1851 self
.update_pc_next()
1853 # check if srcstep needs incrementing by one, stop PC advancing
1854 # but for 2-pred both src/dest have to be checked.
1855 # XXX this might not be true! it may just be LD/ST
1856 if sv_ptype
== SVPtype
.P2
.value
:
1857 svp64_is_vector
= (out_vec
or in_vec
)
1859 svp64_is_vector
= out_vec
1860 # loops end at the first "hit" (source or dest)
1861 loopend
= ((srcstep
== vl
-1 and ssubstep
== subvl
) or
1862 (dststep
== vl
-1 and dsubstep
== subvl
))
1863 if not svp64_is_vector
or loopend
:
1864 # reset loop to zero and update NIA
1865 self
.svp64_reset_loop()
1870 # still looping, advance and update NIA
1871 yield from self
.advance_svstate_steps()
1872 self
.namespace
['SVSTATE'] = self
.svstate
1873 # not an SVP64 branch, so fix PC (NIA==CIA) for next loop
1874 # (by default, NIA is CIA+4 if v3.0B or CIA+8 if SVP64)
1875 # this way we keep repeating the same instruction (with new steps)
1876 self
.pc
.NIA
.value
= self
.pc
.CIA
.value
1877 self
.namespace
['NIA'] = self
.pc
.NIA
1878 log("end of sub-pc call", self
.namespace
['CIA'], self
.namespace
['NIA'])
1879 return False # DO NOT allow PC update whilst Sub-PC loop running
1881 def advance_svstate_steps(self
, end_src
=False, end_dst
=False):
1882 """ advance sub/steps. note that Pack/Unpack *INVERTS* the order.
1883 TODO when Pack/Unpack is set, substep becomes the *outer* loop
1885 subvl
= yield self
.dec2
.rm_dec
.rm_in
.subvl
1887 ssubstep
= self
.svstate
.ssubstep
1888 end_sub
= ssubstep
== subvl
1891 self
.svstate
.srcstep
+= SelectableInt(1, 7)
1892 self
.svstate
.ssubstep
= SelectableInt(0, 2) # reset
1894 self
.svstate
.ssubstep
+= SelectableInt(1, 2) # advance ssubstep
1896 dsubstep
= self
.svstate
.dsubstep
1897 end_sub
= dsubstep
== subvl
1900 self
.svstate
.dststep
+= SelectableInt(1, 7)
1901 self
.svstate
.dsubstep
= SelectableInt(0, 2) # reset
1903 self
.svstate
.dsubstep
+= SelectableInt(1, 2) # advance ssubstep
1905 def update_pc_next(self
):
1906 # UPDATE program counter
1907 self
.pc
.update(self
.namespace
, self
.is_svp64_mode
)
1908 self
.svstate
.spr
= self
.namespace
['SVSTATE']
1909 log("end of call", self
.namespace
['CIA'],
1910 self
.namespace
['NIA'],
1911 self
.namespace
['SVSTATE'])
1913 def svp64_reset_loop(self
):
1914 self
.svstate
.srcstep
= 0
1915 self
.svstate
.dststep
= 0
1916 self
.svstate
.ssubstep
= 0
1917 self
.svstate
.dsubstep
= 0
1918 log(" svstate.srcstep loop end (PC to update)")
1919 self
.namespace
['SVSTATE'] = self
.svstate
1921 def update_nia(self
):
1922 self
.pc
.update_nia(self
.is_svp64_mode
)
1923 self
.namespace
['NIA'] = self
.pc
.NIA
1927 """Decorator factory.
1929 this decorator will "inject" variables into the function's namespace,
1930 from the *dictionary* in self.namespace. it therefore becomes possible
1931 to make it look like a whole stack of variables which would otherwise
1932 need "self." inserted in front of them (*and* for those variables to be
1933 added to the instance) "appear" in the function.
1935 "self.namespace['SI']" for example becomes accessible as just "SI" but
1936 *only* inside the function, when decorated.
1938 def variable_injector(func
):
1940 def decorator(*args
, **kwargs
):
1942 func_globals
= func
.__globals
__ # Python 2.6+
1943 except AttributeError:
1944 func_globals
= func
.func_globals
# Earlier versions.
1946 context
= args
[0].namespace
# variables to be injected
1947 saved_values
= func_globals
.copy() # Shallow copy of dict.
1948 log("globals before", context
.keys())
1949 func_globals
.update(context
)
1950 result
= func(*args
, **kwargs
)
1951 log("globals after", func_globals
['CIA'], func_globals
['NIA'])
1952 log("args[0]", args
[0].namespace
['CIA'],
1953 args
[0].namespace
['NIA'],
1954 args
[0].namespace
['SVSTATE'])
1955 if 'end_loop' in func_globals
:
1956 log("args[0] end_loop", func_globals
['end_loop'])
1957 args
[0].namespace
= func_globals
1958 #exec (func.__code__, func_globals)
1961 # func_globals = saved_values # Undo changes.
1967 return variable_injector