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
,
33 SVP64LDSTmode
, FPTRANS_INSNS
)
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
,
527 """deals with svstate looping.
530 def __init__(self
, svstate
):
531 self
.svstate
= svstate
532 #self.src_it = self.src_iterator()
533 #self.dst_it = self.dst_iterator()
535 def src_iterator(self
):
536 """source-stepping iterator
538 end_src
= self
.end_src
540 pack
= self
.svstate
.pack
541 unpack
= self
.svstate
.unpack
542 ssubstep
= self
.svstate
.ssubstep
543 end_ssub
= ssubstep
== subvl
544 log(" pack/unpack/subvl", pack
, unpack
, subvl
,
548 srcstep
= self
.svstate
.srcstep
550 # pack advances subvl in *outer* loop
553 self
.svstate
.ssubstep
+= SelectableInt(1, 2)
554 self
.svstate
.srcstep
= SelectableInt(0, 7) # reset
556 self
.svstate
.srcstep
+= SelectableInt(1, 7) # advance srcstep
558 # advance subvl in *inner* loop
561 self
.svstate
.srcstep
+= SelectableInt(1, 7)
562 self
.svstate
.ssubstep
= SelectableInt(0, 2) # reset
564 self
.svstate
.ssubstep
+= SelectableInt(1, 2) # advance ssubstep
566 log(" advance src", self
.svstate
.srcstep
, self
.svstate
.ssubstep
)
568 def dst_iterator(self
):
569 """dest step iterator
571 end_dst
= self
.end_dst
573 pack
= self
.svstate
.pack
574 unpack
= self
.svstate
.unpack
575 dsubstep
= self
.svstate
.dsubstep
576 end_dsub
= dsubstep
== subvl
577 log(" pack/unpack/subvl", pack
, unpack
, subvl
,
582 # unpack advances subvl in *outer* loop
585 self
.svstate
.dsubstep
+= SelectableInt(1, 2)
586 self
.svstate
.dststep
= SelectableInt(0, 7) # reset
588 self
.svstate
.dststep
+= SelectableInt(1, 7) # advance dststep
590 # advance subvl in *inner* loop
593 self
.svstate
.dststep
+= SelectableInt(1, 7)
594 self
.svstate
.dsubstep
= SelectableInt(0, 2) # reset
596 self
.svstate
.dsubstep
+= SelectableInt(1, 2) # advance ssubstep
597 log(" advance dst", self
.svstate
.dststep
, self
.svstate
.dsubstep
)
599 def advance_svstate_steps(self
, end_src
=False, end_dst
=False):
600 """ advance sub/steps. note that Pack/Unpack *INVERTS* the order.
601 TODO when Pack/Unpack is set, substep becomes the *outer* loop
603 self
.subvl
= yield self
.dec2
.rm_dec
.rm_in
.subvl
604 self
.end_src
= end_src
605 self
.end_dst
= end_dst
609 def svstate_pre_inc(self
):
610 """check if srcstep/dststep need to skip over masked-out predicate bits
611 note that this is not supposed to do anything to substep,
612 it is purely for skipping masked-out bits
614 # get SVSTATE VL (oh and print out some debug stuff)
615 # yield Delay(1e-10) # make changes visible
617 subvl
= yield self
.dec2
.rm_dec
.rm_in
.subvl
618 srcstep
= self
.svstate
.srcstep
619 dststep
= self
.svstate
.dststep
620 ssubstep
= self
.svstate
.ssubstep
621 dsubstep
= self
.svstate
.dsubstep
622 pack
= self
.svstate
.pack
623 unpack
= self
.svstate
.unpack
624 sv_a_nz
= yield self
.dec2
.sv_a_nz
625 fft_mode
= yield self
.dec2
.use_svp64_fft
626 in1
= yield self
.dec2
.e
.read_reg1
.data
627 log("SVP64: VL, subvl, srcstep, dststep, ssubstep, dsybstep, sv_a_nz, "
629 vl
, subvl
, srcstep
, dststep
, ssubstep
, dsubstep
,
630 sv_a_nz
, in1
, fft_mode
,
633 # get predicate mask (all 64 bits)
634 srcmask
= dstmask
= 0xffff_ffff_ffff_ffff
636 pmode
= yield self
.dec2
.rm_dec
.predmode
637 reverse_gear
= yield self
.dec2
.rm_dec
.reverse_gear
638 sv_ptype
= yield self
.dec2
.dec
.op
.SV_Ptype
639 srcpred
= yield self
.dec2
.rm_dec
.srcpred
640 dstpred
= yield self
.dec2
.rm_dec
.dstpred
641 pred_src_zero
= yield self
.dec2
.rm_dec
.pred_sz
642 pred_dst_zero
= yield self
.dec2
.rm_dec
.pred_dz
643 if pmode
== SVP64PredMode
.INT
.value
:
644 srcmask
= dstmask
= get_predint(self
.gpr
, dstpred
)
645 if sv_ptype
== SVPtype
.P2
.value
:
646 srcmask
= get_predint(self
.gpr
, srcpred
)
647 elif pmode
== SVP64PredMode
.CR
.value
:
648 srcmask
= dstmask
= get_predcr(self
.crl
, dstpred
, vl
)
649 if sv_ptype
== SVPtype
.P2
.value
:
650 srcmask
= get_predcr(self
.crl
, srcpred
, vl
)
651 # work out if the ssubsteps are completed
652 ssubstart
= ssubstep
== 0
653 dsubstart
= dsubstep
== 0
655 log(" pack/unpack", pack
, unpack
)
656 log(" reverse", reverse_gear
)
657 log(" ptype", sv_ptype
)
658 log(" srcpred", bin(srcpred
))
659 log(" dstpred", bin(dstpred
))
660 log(" srcmask", bin(srcmask
))
661 log(" dstmask", bin(dstmask
))
662 log(" pred_sz", bin(pred_src_zero
))
663 log(" pred_dz", bin(pred_dst_zero
))
664 log(" ssubstart", ssubstart
)
665 log(" dsubstart", dsubstart
)
667 # okaaay, so here we simply advance srcstep (TODO dststep)
668 # this can ONLY be done at the beginning of the "for" loop
669 # (this is all actually a FSM so it's hell to keep track sigh)
672 # until the predicate mask has a "1" bit... or we run out of VL
673 # let srcstep==VL be the indicator to move to next instruction
674 if not pred_src_zero
:
677 # srcstep-skipping opportunity identified
679 while (((1 << srcstep
) & srcmask
) == 0) and (srcstep
!= vl
):
680 log(" sskip", bin(1 << srcstep
))
686 if not pred_dst_zero
:
689 # dststep-skipping opportunity identified
691 while (((1 << dststep
) & dstmask
) == 0) and (dststep
!= vl
):
692 log(" dskip", bin(1 << dststep
))
695 # now work out if the relevant mask bits require zeroing
697 pred_dst_zero
= ((1 << dststep
) & dstmask
) == 0
699 pred_src_zero
= ((1 << srcstep
) & srcmask
) == 0
701 # store new srcstep / dststep
702 self
.new_srcstep
, self
.new_dststep
= (srcstep
, dststep
)
703 self
.new_ssubstep
, self
.new_dsubstep
= (ssubstep
, dsubstep
)
704 self
.pred_dst_zero
, self
.pred_src_zero
= (pred_dst_zero
, pred_src_zero
)
705 log(" new srcstep", srcstep
)
706 log(" new dststep", dststep
)
707 log(" new ssubstep", ssubstep
)
708 log(" new dsubstep", dsubstep
)
711 class ISACaller(ISACallerHelper
, ISAFPHelpers
, StepLoop
):
712 # decoder2 - an instance of power_decoder2
713 # regfile - a list of initial values for the registers
714 # initial_{etc} - initial values for SPRs, Condition Register, Mem, MSR
715 # respect_pc - tracks the program counter. requires initial_insns
716 def __init__(self
, decoder2
, regfile
, initial_sprs
=None, initial_cr
=0,
717 initial_mem
=None, initial_msr
=0,
728 self
.bigendian
= bigendian
730 self
.is_svp64_mode
= False
731 self
.respect_pc
= respect_pc
732 if initial_sprs
is None:
734 if initial_mem
is None:
736 if fpregfile
is None:
738 if initial_insns
is None:
740 assert self
.respect_pc
== False, "instructions required to honor pc"
742 log("ISACaller insns", respect_pc
, initial_insns
, disassembly
)
743 log("ISACaller initial_msr", initial_msr
)
745 # "fake program counter" mode (for unit testing)
749 if isinstance(initial_mem
, tuple):
750 self
.fake_pc
= initial_mem
[0]
751 disasm_start
= self
.fake_pc
753 disasm_start
= initial_pc
755 # disassembly: we need this for now (not given from the decoder)
756 self
.disassembly
= {}
758 for i
, code
in enumerate(disassembly
):
759 self
.disassembly
[i
*4 + disasm_start
] = code
761 # set up registers, instruction memory, data memory, PC, SPRs, MSR, CR
762 self
.svp64rm
= SVP64RM()
763 if initial_svstate
is None:
765 if isinstance(initial_svstate
, int):
766 initial_svstate
= SVP64State(initial_svstate
)
767 # SVSTATE, MSR and PC
768 StepLoop
.__init
__(self
, initial_svstate
)
769 self
.msr
= SelectableInt(initial_msr
, 64) # underlying reg
771 # GPR FPR SPR registers
772 initial_sprs
= deepcopy(initial_sprs
) # so as not to get modified
773 self
.gpr
= GPR(decoder2
, self
, self
.svstate
, regfile
)
774 self
.fpr
= GPR(decoder2
, self
, self
.svstate
, fpregfile
)
775 self
.spr
= SPR(decoder2
, initial_sprs
) # initialise SPRs before MMU
777 # set up 4 dummy SVSHAPEs if they aren't already set up
779 sname
= 'SVSHAPE%d' % i
780 if sname
not in self
.spr
:
783 val
= self
.spr
[sname
].value
784 # make sure it's an SVSHAPE
785 self
.spr
[sname
] = SVSHAPE(val
, self
.gpr
)
786 self
.last_op_svshape
= False
789 self
.mem
= Mem(row_bytes
=8, initial_mem
=initial_mem
)
790 self
.mem
.log_fancy(kind
=LogKind
.InstrInOuts
)
791 self
.imem
= Mem(row_bytes
=4, initial_mem
=initial_insns
)
792 # MMU mode, redirect underlying Mem through RADIX
794 self
.mem
= RADIX(self
.mem
, self
)
796 self
.imem
= RADIX(self
.imem
, self
)
799 # FPR (same as GPR except for FP nums)
800 # 4.2.2 p124 FPSCR (definitely "separate" - not in SPR)
801 # note that mffs, mcrfs, mtfsf "manage" this FPSCR
802 # 2.3.1 CR (and sub-fields CR0..CR6 - CR0 SO comes from XER.SO)
803 # note that mfocrf, mfcr, mtcr, mtocrf, mcrxrx "manage" CRs
805 # 2.3.2 LR (actually SPR #8) -- Done
806 # 2.3.3 CTR (actually SPR #9) -- Done
807 # 2.3.4 TAR (actually SPR #815)
808 # 3.2.2 p45 XER (actually SPR #1) -- Done
809 # 3.2.3 p46 p232 VRSAVE (actually SPR #256)
811 # create CR then allow portions of it to be "selectable" (below)
812 self
.cr_fields
= CRFields(initial_cr
)
813 self
.cr
= self
.cr_fields
.cr
815 # "undefined", just set to variable-bit-width int (use exts "max")
816 # self.undefined = SelectableInt(0, 256) # TODO, not hard-code 256!
819 self
.namespace
.update(self
.spr
)
820 self
.namespace
.update({'GPR': self
.gpr
,
824 'memassign': self
.memassign
,
827 'SVSTATE': self
.svstate
,
828 'SVSHAPE0': self
.spr
['SVSHAPE0'],
829 'SVSHAPE1': self
.spr
['SVSHAPE1'],
830 'SVSHAPE2': self
.spr
['SVSHAPE2'],
831 'SVSHAPE3': self
.spr
['SVSHAPE3'],
834 'undefined': undefined
,
835 'mode_is_64bit': True,
836 'SO': XER_bits
['SO'],
837 'XLEN': 64 # elwidth overrides, later
840 # update pc to requested start point
841 self
.set_pc(initial_pc
)
843 # field-selectable versions of Condition Register
844 self
.crl
= self
.cr_fields
.crl
846 self
.namespace
["CR%d" % i
] = self
.crl
[i
]
848 self
.decoder
= decoder2
.dec
851 super().__init
__(XLEN
=self
.namespace
["XLEN"])
855 return self
.namespace
["XLEN"]
857 def call_trap(self
, trap_addr
, trap_bit
):
858 """calls TRAP and sets up NIA to the new execution location.
859 next instruction will begin at trap_addr.
861 self
.TRAP(trap_addr
, trap_bit
)
862 self
.namespace
['NIA'] = self
.trap_nia
863 self
.pc
.update(self
.namespace
, self
.is_svp64_mode
)
865 def TRAP(self
, trap_addr
=0x700, trap_bit
=PIb
.TRAP
):
866 """TRAP> saves PC, MSR (and TODO SVSTATE), and updates MSR
868 TRAP function is callable from inside the pseudocode itself,
869 hence the default arguments. when calling from inside ISACaller
870 it is best to use call_trap()
872 # https://bugs.libre-soc.org/show_bug.cgi?id=859
873 kaivb
= self
.spr
['KAIVB'].value
874 msr
= self
.namespace
['MSR'].value
875 log("TRAP:", hex(trap_addr
), hex(msr
), "kaivb", hex(kaivb
))
876 # store CIA(+4?) in SRR0, set NIA to 0x700
877 # store MSR in SRR1, set MSR to um errr something, have to check spec
878 # store SVSTATE (if enabled) in SVSRR0
879 self
.spr
['SRR0'].value
= self
.pc
.CIA
.value
880 self
.spr
['SRR1'].value
= msr
881 if self
.is_svp64_mode
:
882 self
.spr
['SVSRR0'] = self
.namespace
['SVSTATE'].value
883 self
.trap_nia
= SelectableInt(trap_addr |
(kaivb
&~
0x1fff), 64)
884 self
.spr
['SRR1'][trap_bit
] = 1 # change *copy* of MSR in SRR1
886 # set exception bits. TODO: this should, based on the address
887 # in figure 66 p1065 V3.0B and the table figure 65 p1063 set these
888 # bits appropriately. however it turns out that *for now* in all
889 # cases (all trap_addrs) the exact same thing is needed.
890 self
.msr
[MSRb
.IR
] = 0
891 self
.msr
[MSRb
.DR
] = 0
892 self
.msr
[MSRb
.FE0
] = 0
893 self
.msr
[MSRb
.FE1
] = 0
894 self
.msr
[MSRb
.EE
] = 0
895 self
.msr
[MSRb
.RI
] = 0
896 self
.msr
[MSRb
.SF
] = 1
897 self
.msr
[MSRb
.TM
] = 0
898 self
.msr
[MSRb
.VEC
] = 0
899 self
.msr
[MSRb
.VSX
] = 0
900 self
.msr
[MSRb
.PR
] = 0
901 self
.msr
[MSRb
.FP
] = 0
902 self
.msr
[MSRb
.PMM
] = 0
903 self
.msr
[MSRb
.TEs
] = 0
904 self
.msr
[MSRb
.TEe
] = 0
905 self
.msr
[MSRb
.UND
] = 0
906 self
.msr
[MSRb
.LE
] = 1
908 def memassign(self
, ea
, sz
, val
):
909 self
.mem
.memassign(ea
, sz
, val
)
911 def prep_namespace(self
, insn_name
, formname
, op_fields
):
912 # TODO: get field names from form in decoder*1* (not decoder2)
913 # decoder2 is hand-created, and decoder1.sigform is auto-generated
915 # then "yield" fields only from op_fields rather than hard-coded
917 fields
= self
.decoder
.sigforms
[formname
]
918 log("prep_namespace", formname
, op_fields
, insn_name
)
919 for name
in op_fields
:
920 # CR immediates. deal with separately. needs modifying
922 if self
.is_svp64_mode
and name
in ['BI']: # TODO, more CRs
923 # BI is a 5-bit, must reconstruct the value
924 regnum
, is_vec
= yield from get_pdecode_cr_in(self
.dec2
, name
)
925 sig
= getattr(fields
, name
)
927 # low 2 LSBs (CR field selector) remain same, CR num extended
928 assert regnum
<= 7, "sigh, TODO, 128 CR fields"
929 val
= (val
& 0b11) |
(regnum
<< 2)
931 sig
= getattr(fields
, name
)
933 # these are all opcode fields involved in index-selection of CR,
934 # and need to do "standard" arithmetic. CR[BA+32] for example
935 # would, if using SelectableInt, only be 5-bit.
936 if name
in ['BF', 'BFA', 'BC', 'BA', 'BB', 'BT', 'BI']:
937 self
.namespace
[name
] = val
939 self
.namespace
[name
] = SelectableInt(val
, sig
.width
)
941 self
.namespace
['XER'] = self
.spr
['XER']
942 self
.namespace
['CA'] = self
.spr
['XER'][XER_bits
['CA']].value
943 self
.namespace
['CA32'] = self
.spr
['XER'][XER_bits
['CA32']].value
945 # add some SVSTATE convenience variables
947 srcstep
= self
.svstate
.srcstep
948 self
.namespace
['VL'] = vl
949 self
.namespace
['srcstep'] = srcstep
951 # sv.bc* need some extra fields
952 if self
.is_svp64_mode
and insn_name
.startswith("sv.bc"):
953 # blegh grab bits manually
954 mode
= yield self
.dec2
.rm_dec
.rm_in
.mode
955 bc_vlset
= (mode
& SVP64MODE
.BC_VLSET
) != 0
956 bc_vli
= (mode
& SVP64MODE
.BC_VLI
) != 0
957 bc_snz
= (mode
& SVP64MODE
.BC_SNZ
) != 0
958 bc_vsb
= yield self
.dec2
.rm_dec
.bc_vsb
959 bc_lru
= yield self
.dec2
.rm_dec
.bc_lru
960 bc_gate
= yield self
.dec2
.rm_dec
.bc_gate
961 sz
= yield self
.dec2
.rm_dec
.pred_sz
962 self
.namespace
['ALL'] = SelectableInt(bc_gate
, 1)
963 self
.namespace
['VSb'] = SelectableInt(bc_vsb
, 1)
964 self
.namespace
['LRu'] = SelectableInt(bc_lru
, 1)
965 self
.namespace
['VLSET'] = SelectableInt(bc_vlset
, 1)
966 self
.namespace
['VLI'] = SelectableInt(bc_vli
, 1)
967 self
.namespace
['sz'] = SelectableInt(sz
, 1)
968 self
.namespace
['SNZ'] = SelectableInt(bc_snz
, 1)
970 def handle_carry_(self
, inputs
, outputs
, already_done
):
971 inv_a
= yield self
.dec2
.e
.do
.invert_in
973 inputs
[0] = ~inputs
[0]
975 imm_ok
= yield self
.dec2
.e
.do
.imm_data
.ok
977 imm
= yield self
.dec2
.e
.do
.imm_data
.data
978 inputs
.append(SelectableInt(imm
, 64))
979 assert len(outputs
) >= 1
980 log("outputs", repr(outputs
))
981 if isinstance(outputs
, list) or isinstance(outputs
, tuple):
987 log("gt input", x
, output
)
988 gt
= (gtu(x
, output
))
991 cy
= 1 if any(gts
) else 0
993 if not (1 & already_done
):
994 self
.spr
['XER'][XER_bits
['CA']] = cy
996 log("inputs", already_done
, inputs
)
998 # ARGH... different for OP_ADD... *sigh*...
999 op
= yield self
.dec2
.e
.do
.insn_type
1000 if op
== MicrOp
.OP_ADD
.value
:
1001 res32
= (output
.value
& (1 << 32)) != 0
1002 a32
= (inputs
[0].value
& (1 << 32)) != 0
1003 if len(inputs
) >= 2:
1004 b32
= (inputs
[1].value
& (1 << 32)) != 0
1007 cy32
= res32 ^ a32 ^ b32
1008 log("CA32 ADD", cy32
)
1012 log("input", x
, output
)
1013 log(" x[32:64]", x
, x
[32:64])
1014 log(" o[32:64]", output
, output
[32:64])
1015 gt
= (gtu(x
[32:64], output
[32:64])) == SelectableInt(1, 1)
1017 cy32
= 1 if any(gts
) else 0
1018 log("CA32", cy32
, gts
)
1019 if not (2 & already_done
):
1020 self
.spr
['XER'][XER_bits
['CA32']] = cy32
1022 def handle_overflow(self
, inputs
, outputs
, div_overflow
):
1023 if hasattr(self
.dec2
.e
.do
, "invert_in"):
1024 inv_a
= yield self
.dec2
.e
.do
.invert_in
1026 inputs
[0] = ~inputs
[0]
1028 imm_ok
= yield self
.dec2
.e
.do
.imm_data
.ok
1030 imm
= yield self
.dec2
.e
.do
.imm_data
.data
1031 inputs
.append(SelectableInt(imm
, 64))
1032 assert len(outputs
) >= 1
1033 log("handle_overflow", inputs
, outputs
, div_overflow
)
1034 if len(inputs
) < 2 and div_overflow
is None:
1037 # div overflow is different: it's returned by the pseudo-code
1038 # because it's more complex than can be done by analysing the output
1039 if div_overflow
is not None:
1040 ov
, ov32
= div_overflow
, div_overflow
1041 # arithmetic overflow can be done by analysing the input and output
1042 elif len(inputs
) >= 2:
1046 input_sgn
= [exts(x
.value
, x
.bits
) < 0 for x
in inputs
]
1047 output_sgn
= exts(output
.value
, output
.bits
) < 0
1048 ov
= 1 if input_sgn
[0] == input_sgn
[1] and \
1049 output_sgn
!= input_sgn
[0] else 0
1052 input32_sgn
= [exts(x
.value
, 32) < 0 for x
in inputs
]
1053 output32_sgn
= exts(output
.value
, 32) < 0
1054 ov32
= 1 if input32_sgn
[0] == input32_sgn
[1] and \
1055 output32_sgn
!= input32_sgn
[0] else 0
1057 # now update XER OV/OV32/SO
1058 so
= self
.spr
['XER'][XER_bits
['SO']]
1059 new_so
= so | ov
# sticky overflow ORs in old with new
1060 self
.spr
['XER'][XER_bits
['OV']] = ov
1061 self
.spr
['XER'][XER_bits
['OV32']] = ov32
1062 self
.spr
['XER'][XER_bits
['SO']] = new_so
1063 log(" set overflow", ov
, ov32
, so
, new_so
)
1065 def handle_comparison(self
, outputs
, cr_idx
=0, overflow
=None, no_so
=False):
1067 assert isinstance(out
, SelectableInt
), \
1068 "out zero not a SelectableInt %s" % repr(outputs
)
1069 log("handle_comparison", out
.bits
, hex(out
.value
))
1070 # TODO - XXX *processor* in 32-bit mode
1071 # https://bugs.libre-soc.org/show_bug.cgi?id=424
1073 # o32 = exts(out.value, 32)
1074 # print ("handle_comparison exts 32 bit", hex(o32))
1075 out
= exts(out
.value
, out
.bits
)
1076 log("handle_comparison exts", hex(out
))
1077 # create the three main CR flags, EQ GT LT
1078 zero
= SelectableInt(out
== 0, 1)
1079 positive
= SelectableInt(out
> 0, 1)
1080 negative
= SelectableInt(out
< 0, 1)
1081 # get (or not) XER.SO. for setvl this is important *not* to read SO
1083 SO
= SelectableInt(1, 0)
1085 SO
= self
.spr
['XER'][XER_bits
['SO']]
1086 log("handle_comparison SO overflow", SO
, overflow
)
1087 # alternative overflow checking (setvl mainly at the moment)
1088 if overflow
is not None and overflow
== 1:
1089 SO
= SelectableInt(1, 1)
1090 # create the four CR field values and set the required CR field
1091 cr_field
= selectconcat(negative
, positive
, zero
, SO
)
1092 log("handle_comparison cr_field", self
.cr
, cr_idx
, cr_field
)
1093 self
.crl
[cr_idx
].eq(cr_field
)
1095 def set_pc(self
, pc_val
):
1096 self
.namespace
['NIA'] = SelectableInt(pc_val
, 64)
1097 self
.pc
.update(self
.namespace
, self
.is_svp64_mode
)
1099 def get_next_insn(self
):
1100 """check instruction
1103 pc
= self
.pc
.CIA
.value
1106 ins
= self
.imem
.ld(pc
, 4, False, True, instr_fetch
=True)
1108 raise KeyError("no instruction at 0x%x" % pc
)
1111 def setup_one(self
):
1112 """set up one instruction
1114 pc
, insn
= self
.get_next_insn()
1115 yield from self
.setup_next_insn(pc
, insn
)
1117 def setup_next_insn(self
, pc
, ins
):
1118 """set up next instruction
1121 log("setup: 0x%x 0x%x %s" % (pc
, ins
& 0xffffffff, bin(ins
)))
1122 log("CIA NIA", self
.respect_pc
, self
.pc
.CIA
.value
, self
.pc
.NIA
.value
)
1124 yield self
.dec2
.sv_rm
.eq(0)
1125 yield self
.dec2
.dec
.raw_opcode_in
.eq(ins
& 0xffffffff)
1126 yield self
.dec2
.dec
.bigendian
.eq(self
.bigendian
)
1127 yield self
.dec2
.state
.msr
.eq(self
.msr
.value
)
1128 yield self
.dec2
.state
.pc
.eq(pc
)
1129 if self
.svstate
is not None:
1130 yield self
.dec2
.state
.svstate
.eq(self
.svstate
.value
)
1132 # SVP64. first, check if the opcode is EXT001, and SVP64 id bits set
1134 opcode
= yield self
.dec2
.dec
.opcode_in
1135 opcode
= SelectableInt(value
=opcode
, bits
=32)
1136 pfx
= SVP64Instruction
.Prefix(opcode
)
1137 log("prefix test: opcode:", pfx
.po
, bin(pfx
.po
), pfx
.id)
1138 self
.is_svp64_mode
= bool((pfx
.po
== 0b000001) and (pfx
.id == 0b11))
1139 self
.pc
.update_nia(self
.is_svp64_mode
)
1141 yield self
.dec2
.is_svp64_mode
.eq(self
.is_svp64_mode
)
1142 self
.namespace
['NIA'] = self
.pc
.NIA
1143 self
.namespace
['SVSTATE'] = self
.svstate
1144 if not self
.is_svp64_mode
:
1147 # in SVP64 mode. decode/print out svp64 prefix, get v3.0B instruction
1148 log("svp64.rm", bin(pfx
.rm
))
1149 log(" svstate.vl", self
.svstate
.vl
)
1150 log(" svstate.mvl", self
.svstate
.maxvl
)
1151 ins
= self
.imem
.ld(pc
+4, 4, False, True, instr_fetch
=True)
1152 log(" svsetup: 0x%x 0x%x %s" % (pc
+4, ins
& 0xffffffff, bin(ins
)))
1153 yield self
.dec2
.dec
.raw_opcode_in
.eq(ins
& 0xffffffff) # v3.0B suffix
1154 yield self
.dec2
.sv_rm
.eq(int(pfx
.rm
)) # svp64 prefix
1157 def execute_one(self
):
1158 """execute one instruction
1160 # get the disassembly code for this instruction
1161 if self
.is_svp64_mode
:
1162 if not self
.disassembly
:
1163 code
= yield from self
.get_assembly_name()
1165 code
= self
.disassembly
[self
._pc
+4]
1166 log(" svp64 sim-execute", hex(self
._pc
), code
)
1168 if not self
.disassembly
:
1169 code
= yield from self
.get_assembly_name()
1171 code
= self
.disassembly
[self
._pc
]
1172 log("sim-execute", hex(self
._pc
), code
)
1173 opname
= code
.split(' ')[0]
1175 yield from self
.call(opname
) # execute the instruction
1176 except MemException
as e
: # check for memory errors
1177 if e
.args
[0] == 'unaligned': # alignment error
1178 # run a Trap but set DAR first
1179 print("memory unaligned exception, DAR", e
.dar
)
1180 self
.spr
['DAR'] = SelectableInt(e
.dar
, 64)
1181 self
.call_trap(0x600, PIb
.PRIV
) # 0x600, privileged
1183 elif e
.args
[0] == 'invalid': # invalid
1184 # run a Trap but set DAR first
1185 log("RADIX MMU memory invalid error, mode %s" % e
.mode
)
1186 if e
.mode
== 'EXECUTE':
1187 # XXX TODO: must set a few bits in SRR1,
1188 # see microwatt loadstore1.vhdl
1189 # if m_in.segerr = '0' then
1190 # v.srr1(47 - 33) := m_in.invalid;
1191 # v.srr1(47 - 35) := m_in.perm_error; -- noexec fault
1192 # v.srr1(47 - 44) := m_in.badtree;
1193 # v.srr1(47 - 45) := m_in.rc_error;
1194 # v.intr_vec := 16#400#;
1196 # v.intr_vec := 16#480#;
1197 self
.call_trap(0x400, PIb
.PRIV
) # 0x400, privileged
1199 self
.call_trap(0x300, PIb
.PRIV
) # 0x300, privileged
1201 # not supported yet:
1202 raise e
# ... re-raise
1204 # don't use this except in special circumstances
1205 if not self
.respect_pc
:
1208 log("execute one, CIA NIA", hex(self
.pc
.CIA
.value
),
1209 hex(self
.pc
.NIA
.value
))
1211 def get_assembly_name(self
):
1212 # TODO, asmregs is from the spec, e.g. add RT,RA,RB
1213 # see http://bugs.libre-riscv.org/show_bug.cgi?id=282
1214 dec_insn
= yield self
.dec2
.e
.do
.insn
1215 insn_1_11
= yield self
.dec2
.e
.do
.insn
[1:11]
1216 asmcode
= yield self
.dec2
.dec
.op
.asmcode
1217 int_op
= yield self
.dec2
.dec
.op
.internal_op
1218 log("get assembly name asmcode", asmcode
, int_op
,
1219 hex(dec_insn
), bin(insn_1_11
))
1220 asmop
= insns
.get(asmcode
, None)
1222 # sigh reconstruct the assembly instruction name
1223 if hasattr(self
.dec2
.e
.do
, "oe"):
1224 ov_en
= yield self
.dec2
.e
.do
.oe
.oe
1225 ov_ok
= yield self
.dec2
.e
.do
.oe
.ok
1229 if hasattr(self
.dec2
.e
.do
, "rc"):
1230 rc_en
= yield self
.dec2
.e
.do
.rc
.rc
1231 rc_ok
= yield self
.dec2
.e
.do
.rc
.ok
1235 # grrrr have to special-case MUL op (see DecodeOE)
1236 log("ov %d en %d rc %d en %d op %d" %
1237 (ov_ok
, ov_en
, rc_ok
, rc_en
, int_op
))
1238 if int_op
in [MicrOp
.OP_MUL_H64
.value
, MicrOp
.OP_MUL_H32
.value
]:
1243 if not asmop
.endswith("."): # don't add "." to "andis."
1246 if hasattr(self
.dec2
.e
.do
, "lk"):
1247 lk
= yield self
.dec2
.e
.do
.lk
1250 log("int_op", int_op
)
1251 if int_op
in [MicrOp
.OP_B
.value
, MicrOp
.OP_BC
.value
]:
1252 AA
= yield self
.dec2
.dec
.fields
.FormI
.AA
[0:-1]
1256 spr_msb
= yield from self
.get_spr_msb()
1257 if int_op
== MicrOp
.OP_MFCR
.value
:
1262 # XXX TODO: for whatever weird reason this doesn't work
1263 # https://bugs.libre-soc.org/show_bug.cgi?id=390
1264 if int_op
== MicrOp
.OP_MTCRF
.value
:
1271 def get_remap_indices(self
):
1272 """WARNING, this function stores remap_idxs and remap_loopends
1273 in the class for later use. this to avoid problems with yield
1275 # go through all iterators in lock-step, advance to next remap_idx
1276 srcstep
, dststep
, ssubstep
, dsubstep
= self
.get_src_dststeps()
1277 # get four SVSHAPEs. here we are hard-coding
1278 SVSHAPE0
= self
.spr
['SVSHAPE0']
1279 SVSHAPE1
= self
.spr
['SVSHAPE1']
1280 SVSHAPE2
= self
.spr
['SVSHAPE2']
1281 SVSHAPE3
= self
.spr
['SVSHAPE3']
1282 # set up the iterators
1283 remaps
= [(SVSHAPE0
, SVSHAPE0
.get_iterator()),
1284 (SVSHAPE1
, SVSHAPE1
.get_iterator()),
1285 (SVSHAPE2
, SVSHAPE2
.get_iterator()),
1286 (SVSHAPE3
, SVSHAPE3
.get_iterator()),
1289 self
.remap_loopends
= [0] * 4
1290 self
.remap_idxs
= [0, 1, 2, 3]
1292 for i
, (shape
, remap
) in enumerate(remaps
):
1293 # zero is "disabled"
1294 if shape
.value
== 0x0:
1295 self
.remap_idxs
[i
] = 0
1296 # pick src or dststep depending on reg num (0-2=in, 3-4=out)
1297 step
= dststep
if (i
in [3, 4]) else srcstep
1298 # this is terrible. O(N^2) looking for the match. but hey.
1299 for idx
, (remap_idx
, loopends
) in enumerate(remap
):
1302 self
.remap_idxs
[i
] = remap_idx
1303 self
.remap_loopends
[i
] = loopends
1304 dbg
.append((i
, step
, remap_idx
, loopends
))
1305 for (i
, step
, remap_idx
, loopends
) in dbg
:
1306 log("SVSHAPE %d idx, end" % i
, step
, remap_idx
, bin(loopends
))
1309 def get_spr_msb(self
):
1310 dec_insn
= yield self
.dec2
.e
.do
.insn
1311 return dec_insn
& (1 << 20) != 0 # sigh - XFF.spr[-1]?
1313 def call(self
, name
):
1314 """call(opcode) - the primary execution point for instructions
1316 self
.last_st_addr
= None # reset the last known store address
1317 self
.last_ld_addr
= None # etc.
1319 ins_name
= name
.strip() # remove spaces if not already done so
1321 log("halted - not executing", ins_name
)
1324 # TODO, asmregs is from the spec, e.g. add RT,RA,RB
1325 # see http://bugs.libre-riscv.org/show_bug.cgi?id=282
1326 asmop
= yield from self
.get_assembly_name()
1327 log("call", ins_name
, asmop
)
1329 # sv.setvl is *not* a loop-function. sigh
1330 log("is_svp64_mode", self
.is_svp64_mode
, asmop
)
1333 int_op
= yield self
.dec2
.dec
.op
.internal_op
1334 spr_msb
= yield from self
.get_spr_msb()
1336 instr_is_privileged
= False
1337 if int_op
in [MicrOp
.OP_ATTN
.value
,
1338 MicrOp
.OP_MFMSR
.value
,
1339 MicrOp
.OP_MTMSR
.value
,
1340 MicrOp
.OP_MTMSRD
.value
,
1342 MicrOp
.OP_RFID
.value
]:
1343 instr_is_privileged
= True
1344 if int_op
in [MicrOp
.OP_MFSPR
.value
,
1345 MicrOp
.OP_MTSPR
.value
] and spr_msb
:
1346 instr_is_privileged
= True
1348 log("is priv", instr_is_privileged
, hex(self
.msr
.value
),
1350 # check MSR priv bit and whether op is privileged: if so, throw trap
1351 if instr_is_privileged
and self
.msr
[MSRb
.PR
] == 1:
1352 self
.call_trap(0x700, PIb
.PRIV
)
1355 # check halted condition
1356 if ins_name
== 'attn':
1360 # check illegal instruction
1362 if ins_name
not in ['mtcrf', 'mtocrf']:
1363 illegal
= ins_name
!= asmop
1365 # list of instructions not being supported by binutils (.long)
1366 dotstrp
= asmop
[:-1] if asmop
[-1] == '.' else asmop
1367 if dotstrp
in [*FPTRANS_INSNS
,
1368 'ffmadds', 'fdmadds', 'ffadds',
1369 'mins', 'maxs', 'minu', 'maxu',
1370 'setvl', 'svindex', 'svremap', 'svstep',
1371 'svshape', 'svshape2',
1372 'grev', 'ternlogi', 'bmask', 'cprop',
1373 'absdu', 'absds', 'absdacs', 'absdacu', 'avgadd',
1379 # branch-conditional redirects to sv.bc
1380 if asmop
.startswith('bc') and self
.is_svp64_mode
:
1381 ins_name
= 'sv.%s' % ins_name
1383 log(" post-processed name", dotstrp
, ins_name
, asmop
)
1385 # illegal instructions call TRAP at 0x700
1387 print("illegal", ins_name
, asmop
)
1388 self
.call_trap(0x700, PIb
.ILLEG
)
1389 print("name %s != %s - calling ILLEGAL trap, PC: %x" %
1390 (ins_name
, asmop
, self
.pc
.CIA
.value
))
1393 # this is for setvl "Vertical" mode: if set true,
1394 # srcstep/dststep is explicitly advanced. mode says which SVSTATE to
1395 # test for Rc=1 end condition. 3 bits of all 3 loops are put into CR0
1396 self
.allow_next_step_inc
= False
1397 self
.svstate_next_mode
= 0
1399 # nop has to be supported, we could let the actual op calculate
1400 # but PowerDecoder has a pattern for nop
1401 if ins_name
== 'nop':
1402 self
.update_pc_next()
1405 # look up instruction in ISA.instrs, prepare namespace
1406 info
= self
.instrs
[ins_name
]
1407 yield from self
.prep_namespace(ins_name
, info
.form
, info
.op_fields
)
1409 # preserve order of register names
1410 input_names
= create_args(list(info
.read_regs
) +
1411 list(info
.uninit_regs
))
1412 log("input names", input_names
)
1414 # get SVP64 entry for the current instruction
1415 sv_rm
= self
.svp64rm
.instrs
.get(ins_name
)
1416 if sv_rm
is not None:
1417 dest_cr
, src_cr
, src_byname
, dest_byname
= decode_extra(sv_rm
)
1419 dest_cr
, src_cr
, src_byname
, dest_byname
= False, False, {}, {}
1420 log("sv rm", sv_rm
, dest_cr
, src_cr
, src_byname
, dest_byname
)
1422 # see if srcstep/dststep need skipping over masked-out predicate bits
1423 if (self
.is_svp64_mode
or ins_name
in ['setvl', 'svremap', 'svstate']):
1424 yield from self
.svstate_pre_inc()
1425 if self
.is_svp64_mode
:
1426 pre
= yield from self
.update_new_svstate_steps()
1428 self
.svp64_reset_loop()
1430 self
.update_pc_next()
1432 srcstep
, dststep
, ssubstep
, dsubstep
= self
.get_src_dststeps()
1433 pred_dst_zero
= self
.pred_dst_zero
1434 pred_src_zero
= self
.pred_src_zero
1435 vl
= self
.svstate
.vl
1436 subvl
= yield self
.dec2
.rm_dec
.rm_in
.subvl
1438 # VL=0 in SVP64 mode means "do nothing: skip instruction"
1439 if self
.is_svp64_mode
and vl
== 0:
1440 self
.pc
.update(self
.namespace
, self
.is_svp64_mode
)
1441 log("SVP64: VL=0, end of call", self
.namespace
['CIA'],
1442 self
.namespace
['NIA'], kind
=LogKind
.InstrInOuts
)
1445 # for when SVREMAP is active, using pre-arranged schedule.
1446 # note: modifying PowerDecoder2 needs to "settle"
1447 remap_en
= self
.svstate
.SVme
1448 persist
= self
.svstate
.RMpst
1449 active
= (persist
or self
.last_op_svshape
) and remap_en
!= 0
1450 if self
.is_svp64_mode
:
1451 yield self
.dec2
.remap_active
.eq(remap_en
if active
else 0)
1453 if persist
or self
.last_op_svshape
:
1454 remaps
= self
.get_remap_indices()
1455 if self
.is_svp64_mode
and (persist
or self
.last_op_svshape
):
1456 yield from self
.remap_set_steps(remaps
)
1457 # after that, settle down (combinatorial) to let Vector reg numbers
1458 # work themselves out
1460 if self
.is_svp64_mode
:
1461 remap_active
= yield self
.dec2
.remap_active
1463 remap_active
= False
1464 log("remap active", bin(remap_active
))
1466 # main input registers (RT, RA ...)
1468 for name
in input_names
:
1470 regval
= (yield from self
.get_input(name
))
1471 log("regval", regval
)
1472 inputs
.append(regval
)
1474 # arrrrgh, awful hack, to get _RT into namespace
1475 if ins_name
in ['setvl', 'svstep']:
1477 RT
= yield self
.dec2
.dec
.RT
1478 self
.namespace
[regname
] = SelectableInt(RT
, 5)
1480 self
.namespace
["RT"] = SelectableInt(0, 5)
1481 regnum
, is_vec
= yield from get_pdecode_idx_out(self
.dec2
, "RT")
1482 log('hack input reg %s %s' % (name
, str(regnum
)), is_vec
)
1484 # in SVP64 mode for LD/ST work out immediate
1485 # XXX TODO: replace_ds for DS-Form rather than D-Form.
1486 # use info.form to detect
1487 if self
.is_svp64_mode
:
1488 yield from self
.check_replace_d(info
, remap_active
)
1490 # "special" registers
1491 for special
in info
.special_regs
:
1492 if special
in special_sprs
:
1493 inputs
.append(self
.spr
[special
])
1495 inputs
.append(self
.namespace
[special
])
1497 # clear trap (trap) NIA
1498 self
.trap_nia
= None
1500 # check if this was an sv.bc* and create an indicator that
1501 # this is the last check to be made as a loop. combined with
1502 # the ALL/ANY mode we can early-exit
1503 if self
.is_svp64_mode
and ins_name
.startswith("sv.bc"):
1504 no_in_vec
= yield self
.dec2
.no_in_vec
# BI is scalar
1505 # XXX TODO - pack/unpack here
1506 end_loop
= no_in_vec
or srcstep
== vl
-1 or dststep
== vl
-1
1507 self
.namespace
['end_loop'] = SelectableInt(end_loop
, 1)
1509 # execute actual instruction here (finally)
1510 log("inputs", inputs
)
1511 results
= info
.func(self
, *inputs
)
1512 log("results", results
)
1514 # "inject" decorator takes namespace from function locals: we need to
1515 # overwrite NIA being overwritten (sigh)
1516 if self
.trap_nia
is not None:
1517 self
.namespace
['NIA'] = self
.trap_nia
1519 log("after func", self
.namespace
['CIA'], self
.namespace
['NIA'])
1521 # check if op was a LD/ST so that debugging can check the
1523 if int_op
in [MicrOp
.OP_STORE
.value
,
1525 self
.last_st_addr
= self
.mem
.last_st_addr
1526 if int_op
in [MicrOp
.OP_LOAD
.value
,
1528 self
.last_ld_addr
= self
.mem
.last_ld_addr
1529 log("op", int_op
, MicrOp
.OP_STORE
.value
, MicrOp
.OP_LOAD
.value
,
1530 self
.last_st_addr
, self
.last_ld_addr
)
1532 # detect if CA/CA32 already in outputs (sra*, basically)
1535 output_names
= create_args(info
.write_regs
)
1536 for name
in output_names
:
1542 log("carry already done?", bin(already_done
))
1543 if hasattr(self
.dec2
.e
.do
, "output_carry"):
1544 carry_en
= yield self
.dec2
.e
.do
.output_carry
1548 yield from self
.handle_carry_(inputs
, results
, already_done
)
1550 # check if one of the regs was named "overflow"
1553 for name
, output
in zip(output_names
, results
):
1554 if name
== 'overflow':
1557 if not self
.is_svp64_mode
: # yeah just no. not in parallel processing
1558 # detect if overflow was in return result
1559 if hasattr(self
.dec2
.e
.do
, "oe"):
1560 ov_en
= yield self
.dec2
.e
.do
.oe
.oe
1561 ov_ok
= yield self
.dec2
.e
.do
.oe
.ok
1565 log("internal overflow", ins_name
, overflow
, "en?", ov_en
, ov_ok
)
1567 yield from self
.handle_overflow(inputs
, results
, overflow
)
1569 # only do SVP64 dest predicated Rc=1 if dest-pred is not enabled
1571 if not self
.is_svp64_mode
or not pred_dst_zero
:
1572 if hasattr(self
.dec2
.e
.do
, "rc"):
1573 rc_en
= yield self
.dec2
.e
.do
.rc
.rc
1574 if rc_en
and ins_name
not in ['svstep']:
1575 if ins_name
.startswith("f"):
1576 rc_reg
= "CR1" # not calculated correctly yet (not FP compares)
1579 regnum
, is_vec
= yield from get_pdecode_cr_out(self
.dec2
, rc_reg
)
1581 # hang on... for `setvl` actually you want to test SVSTATE.VL
1582 is_setvl
= ins_name
== 'setvl'
1585 cmps
= (SelectableInt(vl
, 64), overflow
,)
1587 overflow
= None # do not override overflow except in setvl
1588 self
.handle_comparison(cmps
, regnum
, overflow
, no_so
=is_setvl
)
1590 # any modified return results?
1592 for name
, output
in zip(output_names
, results
):
1593 yield from self
.check_write(info
, name
, output
, carry_en
)
1595 nia_update
= (yield from self
.check_step_increment(results
, rc_en
,
1598 self
.update_pc_next()
1600 def check_replace_d(self
, info
, remap_active
):
1601 replace_d
= False # update / replace constant in pseudocode
1602 ldstmode
= yield self
.dec2
.rm_dec
.ldstmode
1603 vl
= self
.svstate
.vl
1604 subvl
= yield self
.dec2
.rm_dec
.rm_in
.subvl
1605 srcstep
, dststep
= self
.new_srcstep
, self
.new_dststep
1606 ssubstep
, dsubstep
= self
.new_ssubstep
, self
.new_dsubstep
1607 if info
.form
== 'DS':
1608 # DS-Form, multiply by 4 then knock 2 bits off after
1609 imm
= yield self
.dec2
.dec
.fields
.FormDS
.DS
[0:14] * 4
1611 imm
= yield self
.dec2
.dec
.fields
.FormD
.D
[0:16]
1612 imm
= exts(imm
, 16) # sign-extend to integer
1613 # get the right step. LD is from srcstep, ST is dststep
1614 op
= yield self
.dec2
.e
.do
.insn_type
1616 if op
== MicrOp
.OP_LOAD
.value
:
1618 offsmul
= yield self
.dec2
.in1_step
1619 log("D-field REMAP src", imm
, offsmul
)
1621 offsmul
= (srcstep
* (subvl
+1)) + ssubstep
1622 log("D-field src", imm
, offsmul
)
1623 elif op
== MicrOp
.OP_STORE
.value
:
1624 # XXX NOTE! no bit-reversed STORE! this should not ever be used
1625 offsmul
= (dststep
* (subvl
+1)) + dsubstep
1626 log("D-field dst", imm
, offsmul
)
1627 # Unit-Strided LD/ST adds offset*width to immediate
1628 if ldstmode
== SVP64LDSTmode
.UNITSTRIDE
.value
:
1629 ldst_len
= yield self
.dec2
.e
.do
.data_len
1630 imm
= SelectableInt(imm
+ offsmul
* ldst_len
, 32)
1632 # Element-strided multiplies the immediate by element step
1633 elif ldstmode
== SVP64LDSTmode
.ELSTRIDE
.value
:
1634 imm
= SelectableInt(imm
* offsmul
, 32)
1637 ldst_ra_vec
= yield self
.dec2
.rm_dec
.ldst_ra_vec
1638 ldst_imz_in
= yield self
.dec2
.rm_dec
.ldst_imz_in
1639 log("LDSTmode", SVP64LDSTmode(ldstmode
),
1640 offsmul
, imm
, ldst_ra_vec
, ldst_imz_in
)
1641 # new replacement D... errr.. DS
1643 if info
.form
== 'DS':
1644 # TODO: assert 2 LSBs are zero?
1645 log("DS-Form, TODO, assert 2 LSBs zero?", bin(imm
.value
))
1646 imm
.value
= imm
.value
>> 2
1647 self
.namespace
['DS'] = imm
1649 self
.namespace
['D'] = imm
1651 def get_input(self
, name
):
1652 # using PowerDecoder2, first, find the decoder index.
1653 # (mapping name RA RB RC RS to in1, in2, in3)
1654 regnum
, is_vec
= yield from get_pdecode_idx_in(self
.dec2
, name
)
1656 # doing this is not part of svp64, it's because output
1657 # registers, to be modified, need to be in the namespace.
1658 regnum
, is_vec
= yield from get_pdecode_idx_out(self
.dec2
, name
)
1660 regnum
, is_vec
= yield from get_pdecode_idx_out2(self
.dec2
, name
)
1662 # in case getting the register number is needed, _RA, _RB
1663 regname
= "_" + name
1664 self
.namespace
[regname
] = regnum
1665 if not self
.is_svp64_mode
or not self
.pred_src_zero
:
1666 log('reading reg %s %s' % (name
, str(regnum
)), is_vec
)
1668 reg_val
= SelectableInt(self
.fpr(regnum
))
1669 log("read reg %d: 0x%x" % (regnum
, reg_val
.value
))
1670 elif name
is not None:
1671 reg_val
= SelectableInt(self
.gpr(regnum
))
1672 log("read reg %d: 0x%x" % (regnum
, reg_val
.value
))
1674 log('zero input reg %s %s' % (name
, str(regnum
)), is_vec
)
1678 def remap_set_steps(self
, remaps
):
1679 """remap_set_steps sets up the in1/2/3 and out1/2 steps.
1680 they work in concert with PowerDecoder2 at the moment,
1681 there is no HDL implementation of REMAP. therefore this
1682 function, because ISACaller still uses PowerDecoder2,
1683 will *explicitly* write the dec2.XX_step values. this has
1686 # just some convenient debug info
1688 sname
= 'SVSHAPE%d' % i
1689 shape
= self
.spr
[sname
]
1690 log(sname
, bin(shape
.value
))
1691 log(" lims", shape
.lims
)
1692 log(" mode", shape
.mode
)
1693 log(" skip", shape
.skip
)
1695 # set up the list of steps to remap
1696 mi0
= self
.svstate
.mi0
1697 mi1
= self
.svstate
.mi1
1698 mi2
= self
.svstate
.mi2
1699 mo0
= self
.svstate
.mo0
1700 mo1
= self
.svstate
.mo1
1701 steps
= [(self
.dec2
.in1_step
, mi0
), # RA
1702 (self
.dec2
.in2_step
, mi1
), # RB
1703 (self
.dec2
.in3_step
, mi2
), # RC
1704 (self
.dec2
.o_step
, mo0
), # RT
1705 (self
.dec2
.o2_step
, mo1
), # EA
1707 remap_idxs
= self
.remap_idxs
1709 # now cross-index the required SHAPE for each of 3-in 2-out regs
1710 rnames
= ['RA', 'RB', 'RC', 'RT', 'EA']
1711 for i
, (dstep
, shape_idx
) in enumerate(steps
):
1712 (shape
, remap
) = remaps
[shape_idx
]
1713 remap_idx
= remap_idxs
[shape_idx
]
1714 # zero is "disabled"
1715 if shape
.value
== 0x0:
1717 # now set the actual requested step to the current index
1718 yield dstep
.eq(remap_idx
)
1720 # debug printout info
1721 rremaps
.append((shape
.mode
, i
, rnames
[i
], shape_idx
, remap_idx
))
1723 log("shape remap", x
)
1725 def check_write(self
, info
, name
, output
, carry_en
):
1726 if name
== 'overflow': # ignore, done already (above)
1728 if isinstance(output
, int):
1729 output
= SelectableInt(output
, 256)
1730 if name
in ['CA', 'CA32']:
1732 log("writing %s to XER" % name
, output
)
1733 log("write XER %s 0x%x" % (name
, output
.value
))
1734 self
.spr
['XER'][XER_bits
[name
]] = output
.value
1736 log("NOT writing %s to XER" % name
, output
)
1737 elif name
in info
.special_regs
:
1738 log('writing special %s' % name
, output
, special_sprs
)
1739 log("write reg %s 0x%x" % (name
, output
.value
))
1740 if name
in special_sprs
:
1741 self
.spr
[name
] = output
1743 self
.namespace
[name
].eq(output
)
1745 log('msr written', hex(self
.msr
.value
))
1747 regnum
, is_vec
= yield from get_pdecode_idx_out(self
.dec2
, name
)
1749 regnum
, is_vec
= yield from get_pdecode_idx_out2(
1752 # temporary hack for not having 2nd output
1753 regnum
= yield getattr(self
.decoder
, name
)
1755 if self
.is_svp64_mode
and self
.pred_dst_zero
:
1756 log('zeroing reg %d %s' % (regnum
, str(output
)),
1758 output
= SelectableInt(0, 256)
1764 log("write reg %s%d %0xx" % (reg_prefix
, regnum
, output
.value
))
1765 if output
.bits
> 64:
1766 output
= SelectableInt(output
.value
, 64)
1768 self
.fpr
[regnum
] = output
1770 self
.gpr
[regnum
] = output
1772 def check_step_increment(self
, results
, rc_en
, asmop
, ins_name
):
1773 # check if it is the SVSTATE.src/dest step that needs incrementing
1774 # this is our Sub-Program-Counter loop from 0 to VL-1
1778 if self
.allow_next_step_inc
:
1779 log("SVSTATE_NEXT: inc requested, mode",
1780 self
.svstate_next_mode
, self
.allow_next_step_inc
)
1781 yield from self
.svstate_pre_inc()
1782 pre
= yield from self
.update_new_svstate_steps()
1784 # reset at end of loop including exit Vertical Mode
1785 log("SVSTATE_NEXT: end of loop, reset")
1786 self
.svp64_reset_loop()
1787 self
.svstate
.vfirst
= 0
1791 results
= [SelectableInt(0, 64)]
1792 self
.handle_comparison(results
) # CR0
1794 if self
.allow_next_step_inc
== 2:
1795 log("SVSTATE_NEXT: read")
1796 nia_update
= (yield from self
.svstate_post_inc(ins_name
))
1798 log("SVSTATE_NEXT: post-inc")
1799 # use actual src/dst-step here to check end, do NOT
1800 # use bit-reversed version
1801 srcstep
, dststep
= self
.new_srcstep
, self
.new_dststep
1802 ssubstep
, dsubstep
= self
.new_ssubstep
, self
.new_dsubstep
1803 remaps
= self
.get_remap_indices()
1804 remap_idxs
= self
.remap_idxs
1805 vl
= self
.svstate
.vl
1806 subvl
= yield self
.dec2
.rm_dec
.rm_in
.subvl
1807 end_src
= srcstep
== vl
-1
1808 end_dst
= dststep
== vl
-1
1809 if self
.allow_next_step_inc
!= 2:
1810 yield from self
.advance_svstate_steps(end_src
, end_dst
)
1811 #self.namespace['SVSTATE'] = self.svstate.spr
1812 # set CR0 (if Rc=1) based on end
1814 endtest
= 1 if (end_src
or end_dst
) else 0
1815 #results = [SelectableInt(endtest, 64)]
1816 # self.handle_comparison(results) # CR0
1818 # see if svstep was requested, if so, which SVSTATE
1820 if self
.svstate_next_mode
> 0:
1821 shape_idx
= self
.svstate_next_mode
.value
-1
1822 endings
= self
.remap_loopends
[shape_idx
]
1823 cr_field
= SelectableInt((~endings
) << 1 | endtest
, 4)
1824 log("svstep Rc=1, CR0", cr_field
)
1825 self
.crl
[0].eq(cr_field
) # CR0
1826 if end_src
or end_dst
:
1827 # reset at end of loop including exit Vertical Mode
1828 log("SVSTATE_NEXT: after increments, reset")
1829 self
.svp64_reset_loop()
1830 self
.svstate
.vfirst
= 0
1833 if self
.is_svp64_mode
:
1834 return (yield from self
.svstate_post_inc(ins_name
))
1836 # XXX only in non-SVP64 mode!
1837 # record state of whether the current operation was an svshape,
1839 # to be able to know if it should apply in the next instruction.
1840 # also (if going to use this instruction) should disable ability
1841 # to interrupt in between. sigh.
1842 self
.last_op_svshape
= asmop
in ['svremap', 'svindex', 'svshape2']
1846 def SVSTATE_NEXT(self
, mode
, submode
):
1847 """explicitly moves srcstep/dststep on to next element, for
1848 "Vertical-First" mode. this function is called from
1849 setvl pseudo-code, as a pseudo-op "svstep"
1851 WARNING: this function uses information that was created EARLIER
1852 due to it being in the middle of a yield, but this function is
1853 *NOT* called from yield (it's called from compiled pseudocode).
1855 self
.allow_next_step_inc
= submode
.value
+ 1
1856 log("SVSTATE_NEXT mode", mode
, submode
, self
.allow_next_step_inc
)
1857 self
.svstate_next_mode
= mode
1858 if self
.svstate_next_mode
> 0 and self
.svstate_next_mode
< 5:
1859 shape_idx
= self
.svstate_next_mode
.value
-1
1860 return SelectableInt(self
.remap_idxs
[shape_idx
], 7)
1861 if self
.svstate_next_mode
== 5:
1862 self
.svstate_next_mode
= 0
1863 return SelectableInt(self
.svstate
.srcstep
, 7)
1864 if self
.svstate_next_mode
== 6:
1865 self
.svstate_next_mode
= 0
1866 return SelectableInt(self
.svstate
.dststep
, 7)
1867 return SelectableInt(0, 7)
1869 def get_src_dststeps(self
):
1870 """gets srcstep, dststep, and ssubstep, dsubstep
1872 return (self
.new_srcstep
, self
.new_dststep
,
1873 self
.new_ssubstep
, self
.new_dsubstep
)
1875 def update_new_svstate_steps(self
):
1876 # note, do not get the bit-reversed srcstep here!
1877 srcstep
, dststep
= self
.new_srcstep
, self
.new_dststep
1878 ssubstep
, dsubstep
= self
.new_ssubstep
, self
.new_dsubstep
1880 # update SVSTATE with new srcstep
1881 self
.svstate
.srcstep
= srcstep
1882 self
.svstate
.dststep
= dststep
1883 self
.svstate
.ssubstep
= ssubstep
1884 self
.svstate
.dsubstep
= dsubstep
1885 self
.namespace
['SVSTATE'] = self
.svstate
1886 yield self
.dec2
.state
.svstate
.eq(self
.svstate
.value
)
1887 yield Settle() # let decoder update
1888 srcstep
= self
.svstate
.srcstep
1889 dststep
= self
.svstate
.dststep
1890 ssubstep
= self
.svstate
.ssubstep
1891 dsubstep
= self
.svstate
.dsubstep
1892 pack
= self
.svstate
.pack
1893 unpack
= self
.svstate
.unpack
1894 vl
= self
.svstate
.vl
1895 subvl
= yield self
.dec2
.rm_dec
.rm_in
.subvl
1896 log(" srcstep", srcstep
)
1897 log(" dststep", dststep
)
1899 log(" unpack", unpack
)
1900 log(" ssubstep", ssubstep
)
1901 log(" dsubstep", dsubstep
)
1903 log(" subvl", subvl
)
1905 # check if end reached (we let srcstep overrun, above)
1906 # nothing needs doing (TODO zeroing): just do next instruction
1907 return ((ssubstep
== subvl
and srcstep
== vl
) or
1908 (dsubstep
== subvl
and dststep
== vl
))
1910 def svstate_post_inc(self
, insn_name
, vf
=0):
1911 # check if SV "Vertical First" mode is enabled
1912 vfirst
= self
.svstate
.vfirst
1913 log(" SV Vertical First", vf
, vfirst
)
1914 if not vf
and vfirst
== 1:
1918 # check if it is the SVSTATE.src/dest step that needs incrementing
1919 # this is our Sub-Program-Counter loop from 0 to VL-1
1920 # XXX twin predication TODO
1921 vl
= self
.svstate
.vl
1922 subvl
= yield self
.dec2
.rm_dec
.rm_in
.subvl
1923 mvl
= self
.svstate
.maxvl
1924 srcstep
= self
.svstate
.srcstep
1925 dststep
= self
.svstate
.dststep
1926 ssubstep
= self
.svstate
.ssubstep
1927 dsubstep
= self
.svstate
.dsubstep
1928 pack
= self
.svstate
.pack
1929 unpack
= self
.svstate
.unpack
1930 rm_mode
= yield self
.dec2
.rm_dec
.mode
1931 reverse_gear
= yield self
.dec2
.rm_dec
.reverse_gear
1932 sv_ptype
= yield self
.dec2
.dec
.op
.SV_Ptype
1933 out_vec
= not (yield self
.dec2
.no_out_vec
)
1934 in_vec
= not (yield self
.dec2
.no_in_vec
)
1935 log(" svstate.vl", vl
)
1936 log(" svstate.mvl", mvl
)
1937 log(" rm.subvl", subvl
)
1938 log(" svstate.srcstep", srcstep
)
1939 log(" svstate.dststep", dststep
)
1940 log(" svstate.ssubstep", ssubstep
)
1941 log(" svstate.dsubstep", dsubstep
)
1942 log(" svstate.pack", pack
)
1943 log(" svstate.unpack", unpack
)
1944 log(" mode", rm_mode
)
1945 log(" reverse", reverse_gear
)
1946 log(" out_vec", out_vec
)
1947 log(" in_vec", in_vec
)
1948 log(" sv_ptype", sv_ptype
, sv_ptype
== SVPtype
.P2
.value
)
1949 # check if this was an sv.bc* and if so did it succeed
1950 if self
.is_svp64_mode
and insn_name
.startswith("sv.bc"):
1951 end_loop
= self
.namespace
['end_loop']
1952 log("branch %s end_loop" % insn_name
, end_loop
)
1954 self
.svp64_reset_loop()
1955 self
.update_pc_next()
1957 # check if srcstep needs incrementing by one, stop PC advancing
1958 # but for 2-pred both src/dest have to be checked.
1959 # XXX this might not be true! it may just be LD/ST
1960 if sv_ptype
== SVPtype
.P2
.value
:
1961 svp64_is_vector
= (out_vec
or in_vec
)
1963 svp64_is_vector
= out_vec
1964 # loops end at the first "hit" (source or dest)
1965 end_src
= srcstep
== vl
-1
1966 end_dst
= dststep
== vl
-1
1967 loopend
= ((end_src
and ssubstep
== subvl
) or
1968 (end_dst
and dsubstep
== subvl
))
1969 log("loopend", loopend
, end_src
, end_dst
,
1970 ssubstep
== subvl
, dsubstep
== subvl
)
1971 if not svp64_is_vector
or loopend
:
1972 # reset loop to zero and update NIA
1973 self
.svp64_reset_loop()
1978 # still looping, advance and update NIA
1979 yield from self
.advance_svstate_steps(end_src
, end_dst
)
1980 self
.namespace
['SVSTATE'] = self
.svstate
1982 # not an SVP64 branch, so fix PC (NIA==CIA) for next loop
1983 # (by default, NIA is CIA+4 if v3.0B or CIA+8 if SVP64)
1984 # this way we keep repeating the same instruction (with new steps)
1985 self
.pc
.NIA
.value
= self
.pc
.CIA
.value
1986 self
.namespace
['NIA'] = self
.pc
.NIA
1987 log("end of sub-pc call", self
.namespace
['CIA'], self
.namespace
['NIA'])
1988 return False # DO NOT allow PC update whilst Sub-PC loop running
1990 def update_pc_next(self
):
1991 # UPDATE program counter
1992 self
.pc
.update(self
.namespace
, self
.is_svp64_mode
)
1993 #self.svstate.spr = self.namespace['SVSTATE']
1994 log("end of call", self
.namespace
['CIA'],
1995 self
.namespace
['NIA'],
1996 self
.namespace
['SVSTATE'])
1998 def svp64_reset_loop(self
):
1999 self
.svstate
.srcstep
= 0
2000 self
.svstate
.dststep
= 0
2001 self
.svstate
.ssubstep
= 0
2002 self
.svstate
.dsubstep
= 0
2003 log(" svstate.srcstep loop end (PC to update)")
2004 self
.namespace
['SVSTATE'] = self
.svstate
2006 def update_nia(self
):
2007 self
.pc
.update_nia(self
.is_svp64_mode
)
2008 self
.namespace
['NIA'] = self
.pc
.NIA
2012 """Decorator factory.
2014 this decorator will "inject" variables into the function's namespace,
2015 from the *dictionary* in self.namespace. it therefore becomes possible
2016 to make it look like a whole stack of variables which would otherwise
2017 need "self." inserted in front of them (*and* for those variables to be
2018 added to the instance) "appear" in the function.
2020 "self.namespace['SI']" for example becomes accessible as just "SI" but
2021 *only* inside the function, when decorated.
2023 def variable_injector(func
):
2025 def decorator(*args
, **kwargs
):
2027 func_globals
= func
.__globals
__ # Python 2.6+
2028 except AttributeError:
2029 func_globals
= func
.func_globals
# Earlier versions.
2031 context
= args
[0].namespace
# variables to be injected
2032 saved_values
= func_globals
.copy() # Shallow copy of dict.
2033 log("globals before", context
.keys())
2034 func_globals
.update(context
)
2035 result
= func(*args
, **kwargs
)
2036 log("globals after", func_globals
['CIA'], func_globals
['NIA'])
2037 log("args[0]", args
[0].namespace
['CIA'],
2038 args
[0].namespace
['NIA'],
2039 args
[0].namespace
['SVSTATE'])
2040 if 'end_loop' in func_globals
:
2041 log("args[0] end_loop", func_globals
['end_loop'])
2042 args
[0].namespace
= func_globals
2043 #exec (func.__code__, func_globals)
2046 # func_globals = saved_values # Undo changes.
2052 return variable_injector