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)
670 self
.srcstep_skip
= False
671 self
.srcmask
= srcmask
672 self
.pred_src_zero
= pred_src_zero
673 self
.new_ssubstep
= ssubstep
674 log(" new ssubstep", ssubstep
)
676 # until the predicate mask has a "1" bit... or we run out of VL
677 # let srcstep==VL be the indicator to move to next instruction
678 if not pred_src_zero
:
679 self
.srcstep_skip
= True
683 self
.dststep_skip
= False
684 self
.dstmask
= dstmask
685 self
.pred_dst_zero
= pred_dst_zero
686 self
.new_dsubstep
= dsubstep
687 log(" new dsubstep", dsubstep
)
690 if not pred_dst_zero
:
691 self
.dststep_skip
= True
697 srcstep
= self
.svstate
.srcstep
698 srcmask
= self
.srcmask
699 pred_src_zero
= self
.pred_src_zero
701 # srcstep-skipping opportunity identified
702 if self
.srcstep_skip
:
703 while (((1 << srcstep
) & srcmask
) == 0) and (srcstep
!= vl
):
704 log(" sskip", bin(1 << srcstep
))
707 # now work out if the relevant mask bits require zeroing
709 pred_src_zero
= ((1 << srcstep
) & srcmask
) == 0
711 # store new srcstep / dststep
712 self
.new_srcstep
= srcstep
713 self
.pred_src_zero
= pred_src_zero
714 log(" new srcstep", srcstep
)
717 # dststep-skipping opportunity identified
718 dststep
= self
.svstate
.dststep
719 dstmask
= self
.dstmask
720 pred_dst_zero
= self
.pred_dst_zero
722 if self
.dststep_skip
:
723 while (((1 << dststep
) & dstmask
) == 0) and (dststep
!= vl
):
724 log(" dskip", bin(1 << dststep
))
727 # now work out if the relevant mask bits require zeroing
729 pred_dst_zero
= ((1 << dststep
) & dstmask
) == 0
731 # store new srcstep / dststep
732 self
.new_dststep
= dststep
733 self
.pred_dst_zero
= pred_dst_zero
734 log(" new dststep", dststep
)
737 class ISACaller(ISACallerHelper
, ISAFPHelpers
, StepLoop
):
738 # decoder2 - an instance of power_decoder2
739 # regfile - a list of initial values for the registers
740 # initial_{etc} - initial values for SPRs, Condition Register, Mem, MSR
741 # respect_pc - tracks the program counter. requires initial_insns
742 def __init__(self
, decoder2
, regfile
, initial_sprs
=None, initial_cr
=0,
743 initial_mem
=None, initial_msr
=0,
754 self
.bigendian
= bigendian
756 self
.is_svp64_mode
= False
757 self
.respect_pc
= respect_pc
758 if initial_sprs
is None:
760 if initial_mem
is None:
762 if fpregfile
is None:
764 if initial_insns
is None:
766 assert self
.respect_pc
== False, "instructions required to honor pc"
768 log("ISACaller insns", respect_pc
, initial_insns
, disassembly
)
769 log("ISACaller initial_msr", initial_msr
)
771 # "fake program counter" mode (for unit testing)
775 if isinstance(initial_mem
, tuple):
776 self
.fake_pc
= initial_mem
[0]
777 disasm_start
= self
.fake_pc
779 disasm_start
= initial_pc
781 # disassembly: we need this for now (not given from the decoder)
782 self
.disassembly
= {}
784 for i
, code
in enumerate(disassembly
):
785 self
.disassembly
[i
*4 + disasm_start
] = code
787 # set up registers, instruction memory, data memory, PC, SPRs, MSR, CR
788 self
.svp64rm
= SVP64RM()
789 if initial_svstate
is None:
791 if isinstance(initial_svstate
, int):
792 initial_svstate
= SVP64State(initial_svstate
)
793 # SVSTATE, MSR and PC
794 StepLoop
.__init
__(self
, initial_svstate
)
795 self
.msr
= SelectableInt(initial_msr
, 64) # underlying reg
797 # GPR FPR SPR registers
798 initial_sprs
= deepcopy(initial_sprs
) # so as not to get modified
799 self
.gpr
= GPR(decoder2
, self
, self
.svstate
, regfile
)
800 self
.fpr
= GPR(decoder2
, self
, self
.svstate
, fpregfile
)
801 self
.spr
= SPR(decoder2
, initial_sprs
) # initialise SPRs before MMU
803 # set up 4 dummy SVSHAPEs if they aren't already set up
805 sname
= 'SVSHAPE%d' % i
806 if sname
not in self
.spr
:
809 val
= self
.spr
[sname
].value
810 # make sure it's an SVSHAPE
811 self
.spr
[sname
] = SVSHAPE(val
, self
.gpr
)
812 self
.last_op_svshape
= False
815 self
.mem
= Mem(row_bytes
=8, initial_mem
=initial_mem
)
816 self
.mem
.log_fancy(kind
=LogKind
.InstrInOuts
)
817 self
.imem
= Mem(row_bytes
=4, initial_mem
=initial_insns
)
818 # MMU mode, redirect underlying Mem through RADIX
820 self
.mem
= RADIX(self
.mem
, self
)
822 self
.imem
= RADIX(self
.imem
, self
)
825 # FPR (same as GPR except for FP nums)
826 # 4.2.2 p124 FPSCR (definitely "separate" - not in SPR)
827 # note that mffs, mcrfs, mtfsf "manage" this FPSCR
828 # 2.3.1 CR (and sub-fields CR0..CR6 - CR0 SO comes from XER.SO)
829 # note that mfocrf, mfcr, mtcr, mtocrf, mcrxrx "manage" CRs
831 # 2.3.2 LR (actually SPR #8) -- Done
832 # 2.3.3 CTR (actually SPR #9) -- Done
833 # 2.3.4 TAR (actually SPR #815)
834 # 3.2.2 p45 XER (actually SPR #1) -- Done
835 # 3.2.3 p46 p232 VRSAVE (actually SPR #256)
837 # create CR then allow portions of it to be "selectable" (below)
838 self
.cr_fields
= CRFields(initial_cr
)
839 self
.cr
= self
.cr_fields
.cr
841 # "undefined", just set to variable-bit-width int (use exts "max")
842 # self.undefined = SelectableInt(0, 256) # TODO, not hard-code 256!
845 self
.namespace
.update(self
.spr
)
846 self
.namespace
.update({'GPR': self
.gpr
,
850 'memassign': self
.memassign
,
853 'SVSTATE': self
.svstate
,
854 'SVSHAPE0': self
.spr
['SVSHAPE0'],
855 'SVSHAPE1': self
.spr
['SVSHAPE1'],
856 'SVSHAPE2': self
.spr
['SVSHAPE2'],
857 'SVSHAPE3': self
.spr
['SVSHAPE3'],
860 'undefined': undefined
,
861 'mode_is_64bit': True,
862 'SO': XER_bits
['SO'],
863 'XLEN': 64 # elwidth overrides, later
866 # update pc to requested start point
867 self
.set_pc(initial_pc
)
869 # field-selectable versions of Condition Register
870 self
.crl
= self
.cr_fields
.crl
872 self
.namespace
["CR%d" % i
] = self
.crl
[i
]
874 self
.decoder
= decoder2
.dec
877 super().__init
__(XLEN
=self
.namespace
["XLEN"])
881 return self
.namespace
["XLEN"]
883 def call_trap(self
, trap_addr
, trap_bit
):
884 """calls TRAP and sets up NIA to the new execution location.
885 next instruction will begin at trap_addr.
887 self
.TRAP(trap_addr
, trap_bit
)
888 self
.namespace
['NIA'] = self
.trap_nia
889 self
.pc
.update(self
.namespace
, self
.is_svp64_mode
)
891 def TRAP(self
, trap_addr
=0x700, trap_bit
=PIb
.TRAP
):
892 """TRAP> saves PC, MSR (and TODO SVSTATE), and updates MSR
894 TRAP function is callable from inside the pseudocode itself,
895 hence the default arguments. when calling from inside ISACaller
896 it is best to use call_trap()
898 # https://bugs.libre-soc.org/show_bug.cgi?id=859
899 kaivb
= self
.spr
['KAIVB'].value
900 msr
= self
.namespace
['MSR'].value
901 log("TRAP:", hex(trap_addr
), hex(msr
), "kaivb", hex(kaivb
))
902 # store CIA(+4?) in SRR0, set NIA to 0x700
903 # store MSR in SRR1, set MSR to um errr something, have to check spec
904 # store SVSTATE (if enabled) in SVSRR0
905 self
.spr
['SRR0'].value
= self
.pc
.CIA
.value
906 self
.spr
['SRR1'].value
= msr
907 if self
.is_svp64_mode
:
908 self
.spr
['SVSRR0'] = self
.namespace
['SVSTATE'].value
909 self
.trap_nia
= SelectableInt(trap_addr |
(kaivb
&~
0x1fff), 64)
910 self
.spr
['SRR1'][trap_bit
] = 1 # change *copy* of MSR in SRR1
912 # set exception bits. TODO: this should, based on the address
913 # in figure 66 p1065 V3.0B and the table figure 65 p1063 set these
914 # bits appropriately. however it turns out that *for now* in all
915 # cases (all trap_addrs) the exact same thing is needed.
916 self
.msr
[MSRb
.IR
] = 0
917 self
.msr
[MSRb
.DR
] = 0
918 self
.msr
[MSRb
.FE0
] = 0
919 self
.msr
[MSRb
.FE1
] = 0
920 self
.msr
[MSRb
.EE
] = 0
921 self
.msr
[MSRb
.RI
] = 0
922 self
.msr
[MSRb
.SF
] = 1
923 self
.msr
[MSRb
.TM
] = 0
924 self
.msr
[MSRb
.VEC
] = 0
925 self
.msr
[MSRb
.VSX
] = 0
926 self
.msr
[MSRb
.PR
] = 0
927 self
.msr
[MSRb
.FP
] = 0
928 self
.msr
[MSRb
.PMM
] = 0
929 self
.msr
[MSRb
.TEs
] = 0
930 self
.msr
[MSRb
.TEe
] = 0
931 self
.msr
[MSRb
.UND
] = 0
932 self
.msr
[MSRb
.LE
] = 1
934 def memassign(self
, ea
, sz
, val
):
935 self
.mem
.memassign(ea
, sz
, val
)
937 def prep_namespace(self
, insn_name
, formname
, op_fields
):
938 # TODO: get field names from form in decoder*1* (not decoder2)
939 # decoder2 is hand-created, and decoder1.sigform is auto-generated
941 # then "yield" fields only from op_fields rather than hard-coded
943 fields
= self
.decoder
.sigforms
[formname
]
944 log("prep_namespace", formname
, op_fields
, insn_name
)
945 for name
in op_fields
:
946 # CR immediates. deal with separately. needs modifying
948 if self
.is_svp64_mode
and name
in ['BI']: # TODO, more CRs
949 # BI is a 5-bit, must reconstruct the value
950 regnum
, is_vec
= yield from get_pdecode_cr_in(self
.dec2
, name
)
951 sig
= getattr(fields
, name
)
953 # low 2 LSBs (CR field selector) remain same, CR num extended
954 assert regnum
<= 7, "sigh, TODO, 128 CR fields"
955 val
= (val
& 0b11) |
(regnum
<< 2)
957 sig
= getattr(fields
, name
)
959 # these are all opcode fields involved in index-selection of CR,
960 # and need to do "standard" arithmetic. CR[BA+32] for example
961 # would, if using SelectableInt, only be 5-bit.
962 if name
in ['BF', 'BFA', 'BC', 'BA', 'BB', 'BT', 'BI']:
963 self
.namespace
[name
] = val
965 self
.namespace
[name
] = SelectableInt(val
, sig
.width
)
967 self
.namespace
['XER'] = self
.spr
['XER']
968 self
.namespace
['CA'] = self
.spr
['XER'][XER_bits
['CA']].value
969 self
.namespace
['CA32'] = self
.spr
['XER'][XER_bits
['CA32']].value
971 # add some SVSTATE convenience variables
973 srcstep
= self
.svstate
.srcstep
974 self
.namespace
['VL'] = vl
975 self
.namespace
['srcstep'] = srcstep
977 # sv.bc* need some extra fields
978 if self
.is_svp64_mode
and insn_name
.startswith("sv.bc"):
979 # blegh grab bits manually
980 mode
= yield self
.dec2
.rm_dec
.rm_in
.mode
981 bc_vlset
= (mode
& SVP64MODE
.BC_VLSET
) != 0
982 bc_vli
= (mode
& SVP64MODE
.BC_VLI
) != 0
983 bc_snz
= (mode
& SVP64MODE
.BC_SNZ
) != 0
984 bc_vsb
= yield self
.dec2
.rm_dec
.bc_vsb
985 bc_lru
= yield self
.dec2
.rm_dec
.bc_lru
986 bc_gate
= yield self
.dec2
.rm_dec
.bc_gate
987 sz
= yield self
.dec2
.rm_dec
.pred_sz
988 self
.namespace
['ALL'] = SelectableInt(bc_gate
, 1)
989 self
.namespace
['VSb'] = SelectableInt(bc_vsb
, 1)
990 self
.namespace
['LRu'] = SelectableInt(bc_lru
, 1)
991 self
.namespace
['VLSET'] = SelectableInt(bc_vlset
, 1)
992 self
.namespace
['VLI'] = SelectableInt(bc_vli
, 1)
993 self
.namespace
['sz'] = SelectableInt(sz
, 1)
994 self
.namespace
['SNZ'] = SelectableInt(bc_snz
, 1)
996 def handle_carry_(self
, inputs
, outputs
, already_done
):
997 inv_a
= yield self
.dec2
.e
.do
.invert_in
999 inputs
[0] = ~inputs
[0]
1001 imm_ok
= yield self
.dec2
.e
.do
.imm_data
.ok
1003 imm
= yield self
.dec2
.e
.do
.imm_data
.data
1004 inputs
.append(SelectableInt(imm
, 64))
1005 assert len(outputs
) >= 1
1006 log("outputs", repr(outputs
))
1007 if isinstance(outputs
, list) or isinstance(outputs
, tuple):
1013 log("gt input", x
, output
)
1014 gt
= (gtu(x
, output
))
1017 cy
= 1 if any(gts
) else 0
1019 if not (1 & already_done
):
1020 self
.spr
['XER'][XER_bits
['CA']] = cy
1022 log("inputs", already_done
, inputs
)
1024 # ARGH... different for OP_ADD... *sigh*...
1025 op
= yield self
.dec2
.e
.do
.insn_type
1026 if op
== MicrOp
.OP_ADD
.value
:
1027 res32
= (output
.value
& (1 << 32)) != 0
1028 a32
= (inputs
[0].value
& (1 << 32)) != 0
1029 if len(inputs
) >= 2:
1030 b32
= (inputs
[1].value
& (1 << 32)) != 0
1033 cy32
= res32 ^ a32 ^ b32
1034 log("CA32 ADD", cy32
)
1038 log("input", x
, output
)
1039 log(" x[32:64]", x
, x
[32:64])
1040 log(" o[32:64]", output
, output
[32:64])
1041 gt
= (gtu(x
[32:64], output
[32:64])) == SelectableInt(1, 1)
1043 cy32
= 1 if any(gts
) else 0
1044 log("CA32", cy32
, gts
)
1045 if not (2 & already_done
):
1046 self
.spr
['XER'][XER_bits
['CA32']] = cy32
1048 def handle_overflow(self
, inputs
, outputs
, div_overflow
):
1049 if hasattr(self
.dec2
.e
.do
, "invert_in"):
1050 inv_a
= yield self
.dec2
.e
.do
.invert_in
1052 inputs
[0] = ~inputs
[0]
1054 imm_ok
= yield self
.dec2
.e
.do
.imm_data
.ok
1056 imm
= yield self
.dec2
.e
.do
.imm_data
.data
1057 inputs
.append(SelectableInt(imm
, 64))
1058 assert len(outputs
) >= 1
1059 log("handle_overflow", inputs
, outputs
, div_overflow
)
1060 if len(inputs
) < 2 and div_overflow
is None:
1063 # div overflow is different: it's returned by the pseudo-code
1064 # because it's more complex than can be done by analysing the output
1065 if div_overflow
is not None:
1066 ov
, ov32
= div_overflow
, div_overflow
1067 # arithmetic overflow can be done by analysing the input and output
1068 elif len(inputs
) >= 2:
1072 input_sgn
= [exts(x
.value
, x
.bits
) < 0 for x
in inputs
]
1073 output_sgn
= exts(output
.value
, output
.bits
) < 0
1074 ov
= 1 if input_sgn
[0] == input_sgn
[1] and \
1075 output_sgn
!= input_sgn
[0] else 0
1078 input32_sgn
= [exts(x
.value
, 32) < 0 for x
in inputs
]
1079 output32_sgn
= exts(output
.value
, 32) < 0
1080 ov32
= 1 if input32_sgn
[0] == input32_sgn
[1] and \
1081 output32_sgn
!= input32_sgn
[0] else 0
1083 # now update XER OV/OV32/SO
1084 so
= self
.spr
['XER'][XER_bits
['SO']]
1085 new_so
= so | ov
# sticky overflow ORs in old with new
1086 self
.spr
['XER'][XER_bits
['OV']] = ov
1087 self
.spr
['XER'][XER_bits
['OV32']] = ov32
1088 self
.spr
['XER'][XER_bits
['SO']] = new_so
1089 log(" set overflow", ov
, ov32
, so
, new_so
)
1091 def handle_comparison(self
, outputs
, cr_idx
=0, overflow
=None, no_so
=False):
1093 assert isinstance(out
, SelectableInt
), \
1094 "out zero not a SelectableInt %s" % repr(outputs
)
1095 log("handle_comparison", out
.bits
, hex(out
.value
))
1096 # TODO - XXX *processor* in 32-bit mode
1097 # https://bugs.libre-soc.org/show_bug.cgi?id=424
1099 # o32 = exts(out.value, 32)
1100 # print ("handle_comparison exts 32 bit", hex(o32))
1101 out
= exts(out
.value
, out
.bits
)
1102 log("handle_comparison exts", hex(out
))
1103 # create the three main CR flags, EQ GT LT
1104 zero
= SelectableInt(out
== 0, 1)
1105 positive
= SelectableInt(out
> 0, 1)
1106 negative
= SelectableInt(out
< 0, 1)
1107 # get (or not) XER.SO. for setvl this is important *not* to read SO
1109 SO
= SelectableInt(1, 0)
1111 SO
= self
.spr
['XER'][XER_bits
['SO']]
1112 log("handle_comparison SO overflow", SO
, overflow
)
1113 # alternative overflow checking (setvl mainly at the moment)
1114 if overflow
is not None and overflow
== 1:
1115 SO
= SelectableInt(1, 1)
1116 # create the four CR field values and set the required CR field
1117 cr_field
= selectconcat(negative
, positive
, zero
, SO
)
1118 log("handle_comparison cr_field", self
.cr
, cr_idx
, cr_field
)
1119 self
.crl
[cr_idx
].eq(cr_field
)
1121 def set_pc(self
, pc_val
):
1122 self
.namespace
['NIA'] = SelectableInt(pc_val
, 64)
1123 self
.pc
.update(self
.namespace
, self
.is_svp64_mode
)
1125 def get_next_insn(self
):
1126 """check instruction
1129 pc
= self
.pc
.CIA
.value
1132 ins
= self
.imem
.ld(pc
, 4, False, True, instr_fetch
=True)
1134 raise KeyError("no instruction at 0x%x" % pc
)
1137 def setup_one(self
):
1138 """set up one instruction
1140 pc
, insn
= self
.get_next_insn()
1141 yield from self
.setup_next_insn(pc
, insn
)
1143 def setup_next_insn(self
, pc
, ins
):
1144 """set up next instruction
1147 log("setup: 0x%x 0x%x %s" % (pc
, ins
& 0xffffffff, bin(ins
)))
1148 log("CIA NIA", self
.respect_pc
, self
.pc
.CIA
.value
, self
.pc
.NIA
.value
)
1150 yield self
.dec2
.sv_rm
.eq(0)
1151 yield self
.dec2
.dec
.raw_opcode_in
.eq(ins
& 0xffffffff)
1152 yield self
.dec2
.dec
.bigendian
.eq(self
.bigendian
)
1153 yield self
.dec2
.state
.msr
.eq(self
.msr
.value
)
1154 yield self
.dec2
.state
.pc
.eq(pc
)
1155 if self
.svstate
is not None:
1156 yield self
.dec2
.state
.svstate
.eq(self
.svstate
.value
)
1158 # SVP64. first, check if the opcode is EXT001, and SVP64 id bits set
1160 opcode
= yield self
.dec2
.dec
.opcode_in
1161 opcode
= SelectableInt(value
=opcode
, bits
=32)
1162 pfx
= SVP64Instruction
.Prefix(opcode
)
1163 log("prefix test: opcode:", pfx
.po
, bin(pfx
.po
), pfx
.id)
1164 self
.is_svp64_mode
= bool((pfx
.po
== 0b000001) and (pfx
.id == 0b11))
1165 self
.pc
.update_nia(self
.is_svp64_mode
)
1167 yield self
.dec2
.is_svp64_mode
.eq(self
.is_svp64_mode
)
1168 self
.namespace
['NIA'] = self
.pc
.NIA
1169 self
.namespace
['SVSTATE'] = self
.svstate
1170 if not self
.is_svp64_mode
:
1173 # in SVP64 mode. decode/print out svp64 prefix, get v3.0B instruction
1174 log("svp64.rm", bin(pfx
.rm
))
1175 log(" svstate.vl", self
.svstate
.vl
)
1176 log(" svstate.mvl", self
.svstate
.maxvl
)
1177 ins
= self
.imem
.ld(pc
+4, 4, False, True, instr_fetch
=True)
1178 log(" svsetup: 0x%x 0x%x %s" % (pc
+4, ins
& 0xffffffff, bin(ins
)))
1179 yield self
.dec2
.dec
.raw_opcode_in
.eq(ins
& 0xffffffff) # v3.0B suffix
1180 yield self
.dec2
.sv_rm
.eq(int(pfx
.rm
)) # svp64 prefix
1183 def execute_one(self
):
1184 """execute one instruction
1186 # get the disassembly code for this instruction
1187 if self
.is_svp64_mode
:
1188 if not self
.disassembly
:
1189 code
= yield from self
.get_assembly_name()
1191 code
= self
.disassembly
[self
._pc
+4]
1192 log(" svp64 sim-execute", hex(self
._pc
), code
)
1194 if not self
.disassembly
:
1195 code
= yield from self
.get_assembly_name()
1197 code
= self
.disassembly
[self
._pc
]
1198 log("sim-execute", hex(self
._pc
), code
)
1199 opname
= code
.split(' ')[0]
1201 yield from self
.call(opname
) # execute the instruction
1202 except MemException
as e
: # check for memory errors
1203 if e
.args
[0] == 'unaligned': # alignment error
1204 # run a Trap but set DAR first
1205 print("memory unaligned exception, DAR", e
.dar
)
1206 self
.spr
['DAR'] = SelectableInt(e
.dar
, 64)
1207 self
.call_trap(0x600, PIb
.PRIV
) # 0x600, privileged
1209 elif e
.args
[0] == 'invalid': # invalid
1210 # run a Trap but set DAR first
1211 log("RADIX MMU memory invalid error, mode %s" % e
.mode
)
1212 if e
.mode
== 'EXECUTE':
1213 # XXX TODO: must set a few bits in SRR1,
1214 # see microwatt loadstore1.vhdl
1215 # if m_in.segerr = '0' then
1216 # v.srr1(47 - 33) := m_in.invalid;
1217 # v.srr1(47 - 35) := m_in.perm_error; -- noexec fault
1218 # v.srr1(47 - 44) := m_in.badtree;
1219 # v.srr1(47 - 45) := m_in.rc_error;
1220 # v.intr_vec := 16#400#;
1222 # v.intr_vec := 16#480#;
1223 self
.call_trap(0x400, PIb
.PRIV
) # 0x400, privileged
1225 self
.call_trap(0x300, PIb
.PRIV
) # 0x300, privileged
1227 # not supported yet:
1228 raise e
# ... re-raise
1230 # don't use this except in special circumstances
1231 if not self
.respect_pc
:
1234 log("execute one, CIA NIA", hex(self
.pc
.CIA
.value
),
1235 hex(self
.pc
.NIA
.value
))
1237 def get_assembly_name(self
):
1238 # TODO, asmregs is from the spec, e.g. add RT,RA,RB
1239 # see http://bugs.libre-riscv.org/show_bug.cgi?id=282
1240 dec_insn
= yield self
.dec2
.e
.do
.insn
1241 insn_1_11
= yield self
.dec2
.e
.do
.insn
[1:11]
1242 asmcode
= yield self
.dec2
.dec
.op
.asmcode
1243 int_op
= yield self
.dec2
.dec
.op
.internal_op
1244 log("get assembly name asmcode", asmcode
, int_op
,
1245 hex(dec_insn
), bin(insn_1_11
))
1246 asmop
= insns
.get(asmcode
, None)
1248 # sigh reconstruct the assembly instruction name
1249 if hasattr(self
.dec2
.e
.do
, "oe"):
1250 ov_en
= yield self
.dec2
.e
.do
.oe
.oe
1251 ov_ok
= yield self
.dec2
.e
.do
.oe
.ok
1255 if hasattr(self
.dec2
.e
.do
, "rc"):
1256 rc_en
= yield self
.dec2
.e
.do
.rc
.rc
1257 rc_ok
= yield self
.dec2
.e
.do
.rc
.ok
1261 # grrrr have to special-case MUL op (see DecodeOE)
1262 log("ov %d en %d rc %d en %d op %d" %
1263 (ov_ok
, ov_en
, rc_ok
, rc_en
, int_op
))
1264 if int_op
in [MicrOp
.OP_MUL_H64
.value
, MicrOp
.OP_MUL_H32
.value
]:
1269 if not asmop
.endswith("."): # don't add "." to "andis."
1272 if hasattr(self
.dec2
.e
.do
, "lk"):
1273 lk
= yield self
.dec2
.e
.do
.lk
1276 log("int_op", int_op
)
1277 if int_op
in [MicrOp
.OP_B
.value
, MicrOp
.OP_BC
.value
]:
1278 AA
= yield self
.dec2
.dec
.fields
.FormI
.AA
[0:-1]
1282 spr_msb
= yield from self
.get_spr_msb()
1283 if int_op
== MicrOp
.OP_MFCR
.value
:
1288 # XXX TODO: for whatever weird reason this doesn't work
1289 # https://bugs.libre-soc.org/show_bug.cgi?id=390
1290 if int_op
== MicrOp
.OP_MTCRF
.value
:
1297 def get_remap_indices(self
):
1298 """WARNING, this function stores remap_idxs and remap_loopends
1299 in the class for later use. this to avoid problems with yield
1301 # go through all iterators in lock-step, advance to next remap_idx
1302 srcstep
, dststep
, ssubstep
, dsubstep
= self
.get_src_dststeps()
1303 # get four SVSHAPEs. here we are hard-coding
1304 SVSHAPE0
= self
.spr
['SVSHAPE0']
1305 SVSHAPE1
= self
.spr
['SVSHAPE1']
1306 SVSHAPE2
= self
.spr
['SVSHAPE2']
1307 SVSHAPE3
= self
.spr
['SVSHAPE3']
1308 # set up the iterators
1309 remaps
= [(SVSHAPE0
, SVSHAPE0
.get_iterator()),
1310 (SVSHAPE1
, SVSHAPE1
.get_iterator()),
1311 (SVSHAPE2
, SVSHAPE2
.get_iterator()),
1312 (SVSHAPE3
, SVSHAPE3
.get_iterator()),
1315 self
.remap_loopends
= [0] * 4
1316 self
.remap_idxs
= [0, 1, 2, 3]
1318 for i
, (shape
, remap
) in enumerate(remaps
):
1319 # zero is "disabled"
1320 if shape
.value
== 0x0:
1321 self
.remap_idxs
[i
] = 0
1322 # pick src or dststep depending on reg num (0-2=in, 3-4=out)
1323 step
= dststep
if (i
in [3, 4]) else srcstep
1324 # this is terrible. O(N^2) looking for the match. but hey.
1325 for idx
, (remap_idx
, loopends
) in enumerate(remap
):
1328 self
.remap_idxs
[i
] = remap_idx
1329 self
.remap_loopends
[i
] = loopends
1330 dbg
.append((i
, step
, remap_idx
, loopends
))
1331 for (i
, step
, remap_idx
, loopends
) in dbg
:
1332 log("SVSHAPE %d idx, end" % i
, step
, remap_idx
, bin(loopends
))
1335 def get_spr_msb(self
):
1336 dec_insn
= yield self
.dec2
.e
.do
.insn
1337 return dec_insn
& (1 << 20) != 0 # sigh - XFF.spr[-1]?
1339 def call(self
, name
):
1340 """call(opcode) - the primary execution point for instructions
1342 self
.last_st_addr
= None # reset the last known store address
1343 self
.last_ld_addr
= None # etc.
1345 ins_name
= name
.strip() # remove spaces if not already done so
1347 log("halted - not executing", ins_name
)
1350 # TODO, asmregs is from the spec, e.g. add RT,RA,RB
1351 # see http://bugs.libre-riscv.org/show_bug.cgi?id=282
1352 asmop
= yield from self
.get_assembly_name()
1353 log("call", ins_name
, asmop
)
1355 # sv.setvl is *not* a loop-function. sigh
1356 log("is_svp64_mode", self
.is_svp64_mode
, asmop
)
1359 int_op
= yield self
.dec2
.dec
.op
.internal_op
1360 spr_msb
= yield from self
.get_spr_msb()
1362 instr_is_privileged
= False
1363 if int_op
in [MicrOp
.OP_ATTN
.value
,
1364 MicrOp
.OP_MFMSR
.value
,
1365 MicrOp
.OP_MTMSR
.value
,
1366 MicrOp
.OP_MTMSRD
.value
,
1368 MicrOp
.OP_RFID
.value
]:
1369 instr_is_privileged
= True
1370 if int_op
in [MicrOp
.OP_MFSPR
.value
,
1371 MicrOp
.OP_MTSPR
.value
] and spr_msb
:
1372 instr_is_privileged
= True
1374 log("is priv", instr_is_privileged
, hex(self
.msr
.value
),
1376 # check MSR priv bit and whether op is privileged: if so, throw trap
1377 if instr_is_privileged
and self
.msr
[MSRb
.PR
] == 1:
1378 self
.call_trap(0x700, PIb
.PRIV
)
1381 # check halted condition
1382 if ins_name
== 'attn':
1386 # check illegal instruction
1388 if ins_name
not in ['mtcrf', 'mtocrf']:
1389 illegal
= ins_name
!= asmop
1391 # list of instructions not being supported by binutils (.long)
1392 dotstrp
= asmop
[:-1] if asmop
[-1] == '.' else asmop
1393 if dotstrp
in [*FPTRANS_INSNS
,
1394 'ffmadds', 'fdmadds', 'ffadds',
1395 'mins', 'maxs', 'minu', 'maxu',
1396 'setvl', 'svindex', 'svremap', 'svstep',
1397 'svshape', 'svshape2',
1398 'grev', 'ternlogi', 'bmask', 'cprop',
1399 'absdu', 'absds', 'absdacs', 'absdacu', 'avgadd',
1405 # branch-conditional redirects to sv.bc
1406 if asmop
.startswith('bc') and self
.is_svp64_mode
:
1407 ins_name
= 'sv.%s' % ins_name
1409 log(" post-processed name", dotstrp
, ins_name
, asmop
)
1411 # illegal instructions call TRAP at 0x700
1413 print("illegal", ins_name
, asmop
)
1414 self
.call_trap(0x700, PIb
.ILLEG
)
1415 print("name %s != %s - calling ILLEGAL trap, PC: %x" %
1416 (ins_name
, asmop
, self
.pc
.CIA
.value
))
1419 # this is for setvl "Vertical" mode: if set true,
1420 # srcstep/dststep is explicitly advanced. mode says which SVSTATE to
1421 # test for Rc=1 end condition. 3 bits of all 3 loops are put into CR0
1422 self
.allow_next_step_inc
= False
1423 self
.svstate_next_mode
= 0
1425 # nop has to be supported, we could let the actual op calculate
1426 # but PowerDecoder has a pattern for nop
1427 if ins_name
== 'nop':
1428 self
.update_pc_next()
1431 # look up instruction in ISA.instrs, prepare namespace
1432 info
= self
.instrs
[ins_name
]
1433 yield from self
.prep_namespace(ins_name
, info
.form
, info
.op_fields
)
1435 # preserve order of register names
1436 input_names
= create_args(list(info
.read_regs
) +
1437 list(info
.uninit_regs
))
1438 log("input names", input_names
)
1440 # get SVP64 entry for the current instruction
1441 sv_rm
= self
.svp64rm
.instrs
.get(ins_name
)
1442 if sv_rm
is not None:
1443 dest_cr
, src_cr
, src_byname
, dest_byname
= decode_extra(sv_rm
)
1445 dest_cr
, src_cr
, src_byname
, dest_byname
= False, False, {}, {}
1446 log("sv rm", sv_rm
, dest_cr
, src_cr
, src_byname
, dest_byname
)
1448 # see if srcstep/dststep need skipping over masked-out predicate bits
1449 if (self
.is_svp64_mode
or ins_name
in ['setvl', 'svremap', 'svstate']):
1450 yield from self
.svstate_pre_inc()
1451 if self
.is_svp64_mode
:
1452 pre
= yield from self
.update_new_svstate_steps()
1454 self
.svp64_reset_loop()
1456 self
.update_pc_next()
1458 srcstep
, dststep
, ssubstep
, dsubstep
= self
.get_src_dststeps()
1459 pred_dst_zero
= self
.pred_dst_zero
1460 pred_src_zero
= self
.pred_src_zero
1461 vl
= self
.svstate
.vl
1462 subvl
= yield self
.dec2
.rm_dec
.rm_in
.subvl
1464 # VL=0 in SVP64 mode means "do nothing: skip instruction"
1465 if self
.is_svp64_mode
and vl
== 0:
1466 self
.pc
.update(self
.namespace
, self
.is_svp64_mode
)
1467 log("SVP64: VL=0, end of call", self
.namespace
['CIA'],
1468 self
.namespace
['NIA'], kind
=LogKind
.InstrInOuts
)
1471 # for when SVREMAP is active, using pre-arranged schedule.
1472 # note: modifying PowerDecoder2 needs to "settle"
1473 remap_en
= self
.svstate
.SVme
1474 persist
= self
.svstate
.RMpst
1475 active
= (persist
or self
.last_op_svshape
) and remap_en
!= 0
1476 if self
.is_svp64_mode
:
1477 yield self
.dec2
.remap_active
.eq(remap_en
if active
else 0)
1479 if persist
or self
.last_op_svshape
:
1480 remaps
= self
.get_remap_indices()
1481 if self
.is_svp64_mode
and (persist
or self
.last_op_svshape
):
1482 yield from self
.remap_set_steps(remaps
)
1483 # after that, settle down (combinatorial) to let Vector reg numbers
1484 # work themselves out
1486 if self
.is_svp64_mode
:
1487 remap_active
= yield self
.dec2
.remap_active
1489 remap_active
= False
1490 log("remap active", bin(remap_active
))
1492 # main input registers (RT, RA ...)
1494 for name
in input_names
:
1496 regval
= (yield from self
.get_input(name
))
1497 log("regval", regval
)
1498 inputs
.append(regval
)
1500 # arrrrgh, awful hack, to get _RT into namespace
1501 if ins_name
in ['setvl', 'svstep']:
1503 RT
= yield self
.dec2
.dec
.RT
1504 self
.namespace
[regname
] = SelectableInt(RT
, 5)
1506 self
.namespace
["RT"] = SelectableInt(0, 5)
1507 regnum
, is_vec
= yield from get_pdecode_idx_out(self
.dec2
, "RT")
1508 log('hack input reg %s %s' % (name
, str(regnum
)), is_vec
)
1510 # in SVP64 mode for LD/ST work out immediate
1511 # XXX TODO: replace_ds for DS-Form rather than D-Form.
1512 # use info.form to detect
1513 if self
.is_svp64_mode
:
1514 yield from self
.check_replace_d(info
, remap_active
)
1516 # "special" registers
1517 for special
in info
.special_regs
:
1518 if special
in special_sprs
:
1519 inputs
.append(self
.spr
[special
])
1521 inputs
.append(self
.namespace
[special
])
1523 # clear trap (trap) NIA
1524 self
.trap_nia
= None
1526 # check if this was an sv.bc* and create an indicator that
1527 # this is the last check to be made as a loop. combined with
1528 # the ALL/ANY mode we can early-exit
1529 if self
.is_svp64_mode
and ins_name
.startswith("sv.bc"):
1530 no_in_vec
= yield self
.dec2
.no_in_vec
# BI is scalar
1531 # XXX TODO - pack/unpack here
1532 end_loop
= no_in_vec
or srcstep
== vl
-1 or dststep
== vl
-1
1533 self
.namespace
['end_loop'] = SelectableInt(end_loop
, 1)
1535 # execute actual instruction here (finally)
1536 log("inputs", inputs
)
1537 results
= info
.func(self
, *inputs
)
1538 log("results", results
)
1540 # "inject" decorator takes namespace from function locals: we need to
1541 # overwrite NIA being overwritten (sigh)
1542 if self
.trap_nia
is not None:
1543 self
.namespace
['NIA'] = self
.trap_nia
1545 log("after func", self
.namespace
['CIA'], self
.namespace
['NIA'])
1547 # check if op was a LD/ST so that debugging can check the
1549 if int_op
in [MicrOp
.OP_STORE
.value
,
1551 self
.last_st_addr
= self
.mem
.last_st_addr
1552 if int_op
in [MicrOp
.OP_LOAD
.value
,
1554 self
.last_ld_addr
= self
.mem
.last_ld_addr
1555 log("op", int_op
, MicrOp
.OP_STORE
.value
, MicrOp
.OP_LOAD
.value
,
1556 self
.last_st_addr
, self
.last_ld_addr
)
1558 # detect if CA/CA32 already in outputs (sra*, basically)
1561 output_names
= create_args(info
.write_regs
)
1562 for name
in output_names
:
1568 log("carry already done?", bin(already_done
))
1569 if hasattr(self
.dec2
.e
.do
, "output_carry"):
1570 carry_en
= yield self
.dec2
.e
.do
.output_carry
1574 yield from self
.handle_carry_(inputs
, results
, already_done
)
1576 # check if one of the regs was named "overflow"
1579 for name
, output
in zip(output_names
, results
):
1580 if name
== 'overflow':
1583 if not self
.is_svp64_mode
: # yeah just no. not in parallel processing
1584 # detect if overflow was in return result
1585 if hasattr(self
.dec2
.e
.do
, "oe"):
1586 ov_en
= yield self
.dec2
.e
.do
.oe
.oe
1587 ov_ok
= yield self
.dec2
.e
.do
.oe
.ok
1591 log("internal overflow", ins_name
, overflow
, "en?", ov_en
, ov_ok
)
1593 yield from self
.handle_overflow(inputs
, results
, overflow
)
1595 # only do SVP64 dest predicated Rc=1 if dest-pred is not enabled
1597 if not self
.is_svp64_mode
or not pred_dst_zero
:
1598 if hasattr(self
.dec2
.e
.do
, "rc"):
1599 rc_en
= yield self
.dec2
.e
.do
.rc
.rc
1600 if rc_en
and ins_name
not in ['svstep']:
1601 if ins_name
.startswith("f"):
1602 rc_reg
= "CR1" # not calculated correctly yet (not FP compares)
1605 regnum
, is_vec
= yield from get_pdecode_cr_out(self
.dec2
, rc_reg
)
1607 # hang on... for `setvl` actually you want to test SVSTATE.VL
1608 is_setvl
= ins_name
== 'setvl'
1611 cmps
= (SelectableInt(vl
, 64), overflow
,)
1613 overflow
= None # do not override overflow except in setvl
1614 self
.handle_comparison(cmps
, regnum
, overflow
, no_so
=is_setvl
)
1616 # any modified return results?
1618 for name
, output
in zip(output_names
, results
):
1619 yield from self
.check_write(info
, name
, output
, carry_en
)
1621 nia_update
= (yield from self
.check_step_increment(results
, rc_en
,
1624 self
.update_pc_next()
1626 def check_replace_d(self
, info
, remap_active
):
1627 replace_d
= False # update / replace constant in pseudocode
1628 ldstmode
= yield self
.dec2
.rm_dec
.ldstmode
1629 vl
= self
.svstate
.vl
1630 subvl
= yield self
.dec2
.rm_dec
.rm_in
.subvl
1631 srcstep
, dststep
= self
.new_srcstep
, self
.new_dststep
1632 ssubstep
, dsubstep
= self
.new_ssubstep
, self
.new_dsubstep
1633 if info
.form
== 'DS':
1634 # DS-Form, multiply by 4 then knock 2 bits off after
1635 imm
= yield self
.dec2
.dec
.fields
.FormDS
.DS
[0:14] * 4
1637 imm
= yield self
.dec2
.dec
.fields
.FormD
.D
[0:16]
1638 imm
= exts(imm
, 16) # sign-extend to integer
1639 # get the right step. LD is from srcstep, ST is dststep
1640 op
= yield self
.dec2
.e
.do
.insn_type
1642 if op
== MicrOp
.OP_LOAD
.value
:
1644 offsmul
= yield self
.dec2
.in1_step
1645 log("D-field REMAP src", imm
, offsmul
)
1647 offsmul
= (srcstep
* (subvl
+1)) + ssubstep
1648 log("D-field src", imm
, offsmul
)
1649 elif op
== MicrOp
.OP_STORE
.value
:
1650 # XXX NOTE! no bit-reversed STORE! this should not ever be used
1651 offsmul
= (dststep
* (subvl
+1)) + dsubstep
1652 log("D-field dst", imm
, offsmul
)
1653 # Unit-Strided LD/ST adds offset*width to immediate
1654 if ldstmode
== SVP64LDSTmode
.UNITSTRIDE
.value
:
1655 ldst_len
= yield self
.dec2
.e
.do
.data_len
1656 imm
= SelectableInt(imm
+ offsmul
* ldst_len
, 32)
1658 # Element-strided multiplies the immediate by element step
1659 elif ldstmode
== SVP64LDSTmode
.ELSTRIDE
.value
:
1660 imm
= SelectableInt(imm
* offsmul
, 32)
1663 ldst_ra_vec
= yield self
.dec2
.rm_dec
.ldst_ra_vec
1664 ldst_imz_in
= yield self
.dec2
.rm_dec
.ldst_imz_in
1665 log("LDSTmode", SVP64LDSTmode(ldstmode
),
1666 offsmul
, imm
, ldst_ra_vec
, ldst_imz_in
)
1667 # new replacement D... errr.. DS
1669 if info
.form
== 'DS':
1670 # TODO: assert 2 LSBs are zero?
1671 log("DS-Form, TODO, assert 2 LSBs zero?", bin(imm
.value
))
1672 imm
.value
= imm
.value
>> 2
1673 self
.namespace
['DS'] = imm
1675 self
.namespace
['D'] = imm
1677 def get_input(self
, name
):
1678 # using PowerDecoder2, first, find the decoder index.
1679 # (mapping name RA RB RC RS to in1, in2, in3)
1680 regnum
, is_vec
= yield from get_pdecode_idx_in(self
.dec2
, name
)
1682 # doing this is not part of svp64, it's because output
1683 # registers, to be modified, need to be in the namespace.
1684 regnum
, is_vec
= yield from get_pdecode_idx_out(self
.dec2
, name
)
1686 regnum
, is_vec
= yield from get_pdecode_idx_out2(self
.dec2
, name
)
1688 # in case getting the register number is needed, _RA, _RB
1689 regname
= "_" + name
1690 self
.namespace
[regname
] = regnum
1691 if not self
.is_svp64_mode
or not self
.pred_src_zero
:
1692 log('reading reg %s %s' % (name
, str(regnum
)), is_vec
)
1694 reg_val
= SelectableInt(self
.fpr(regnum
))
1695 log("read reg %d: 0x%x" % (regnum
, reg_val
.value
))
1696 elif name
is not None:
1697 reg_val
= SelectableInt(self
.gpr(regnum
))
1698 log("read reg %d: 0x%x" % (regnum
, reg_val
.value
))
1700 log('zero input reg %s %s' % (name
, str(regnum
)), is_vec
)
1704 def remap_set_steps(self
, remaps
):
1705 """remap_set_steps sets up the in1/2/3 and out1/2 steps.
1706 they work in concert with PowerDecoder2 at the moment,
1707 there is no HDL implementation of REMAP. therefore this
1708 function, because ISACaller still uses PowerDecoder2,
1709 will *explicitly* write the dec2.XX_step values. this has
1712 # just some convenient debug info
1714 sname
= 'SVSHAPE%d' % i
1715 shape
= self
.spr
[sname
]
1716 log(sname
, bin(shape
.value
))
1717 log(" lims", shape
.lims
)
1718 log(" mode", shape
.mode
)
1719 log(" skip", shape
.skip
)
1721 # set up the list of steps to remap
1722 mi0
= self
.svstate
.mi0
1723 mi1
= self
.svstate
.mi1
1724 mi2
= self
.svstate
.mi2
1725 mo0
= self
.svstate
.mo0
1726 mo1
= self
.svstate
.mo1
1727 steps
= [(self
.dec2
.in1_step
, mi0
), # RA
1728 (self
.dec2
.in2_step
, mi1
), # RB
1729 (self
.dec2
.in3_step
, mi2
), # RC
1730 (self
.dec2
.o_step
, mo0
), # RT
1731 (self
.dec2
.o2_step
, mo1
), # EA
1733 remap_idxs
= self
.remap_idxs
1735 # now cross-index the required SHAPE for each of 3-in 2-out regs
1736 rnames
= ['RA', 'RB', 'RC', 'RT', 'EA']
1737 for i
, (dstep
, shape_idx
) in enumerate(steps
):
1738 (shape
, remap
) = remaps
[shape_idx
]
1739 remap_idx
= remap_idxs
[shape_idx
]
1740 # zero is "disabled"
1741 if shape
.value
== 0x0:
1743 # now set the actual requested step to the current index
1744 yield dstep
.eq(remap_idx
)
1746 # debug printout info
1747 rremaps
.append((shape
.mode
, i
, rnames
[i
], shape_idx
, remap_idx
))
1749 log("shape remap", x
)
1751 def check_write(self
, info
, name
, output
, carry_en
):
1752 if name
== 'overflow': # ignore, done already (above)
1754 if isinstance(output
, int):
1755 output
= SelectableInt(output
, 256)
1756 if name
in ['CA', 'CA32']:
1758 log("writing %s to XER" % name
, output
)
1759 log("write XER %s 0x%x" % (name
, output
.value
))
1760 self
.spr
['XER'][XER_bits
[name
]] = output
.value
1762 log("NOT writing %s to XER" % name
, output
)
1763 elif name
in info
.special_regs
:
1764 log('writing special %s' % name
, output
, special_sprs
)
1765 log("write reg %s 0x%x" % (name
, output
.value
))
1766 if name
in special_sprs
:
1767 self
.spr
[name
] = output
1769 self
.namespace
[name
].eq(output
)
1771 log('msr written', hex(self
.msr
.value
))
1773 regnum
, is_vec
= yield from get_pdecode_idx_out(self
.dec2
, name
)
1775 regnum
, is_vec
= yield from get_pdecode_idx_out2(
1778 # temporary hack for not having 2nd output
1779 regnum
= yield getattr(self
.decoder
, name
)
1781 if self
.is_svp64_mode
and self
.pred_dst_zero
:
1782 log('zeroing reg %d %s' % (regnum
, str(output
)),
1784 output
= SelectableInt(0, 256)
1790 log("write reg %s%d %0xx" % (reg_prefix
, regnum
, output
.value
))
1791 if output
.bits
> 64:
1792 output
= SelectableInt(output
.value
, 64)
1794 self
.fpr
[regnum
] = output
1796 self
.gpr
[regnum
] = output
1798 def check_step_increment(self
, results
, rc_en
, asmop
, ins_name
):
1799 # check if it is the SVSTATE.src/dest step that needs incrementing
1800 # this is our Sub-Program-Counter loop from 0 to VL-1
1804 if self
.allow_next_step_inc
:
1805 log("SVSTATE_NEXT: inc requested, mode",
1806 self
.svstate_next_mode
, self
.allow_next_step_inc
)
1807 yield from self
.svstate_pre_inc()
1808 pre
= yield from self
.update_new_svstate_steps()
1810 # reset at end of loop including exit Vertical Mode
1811 log("SVSTATE_NEXT: end of loop, reset")
1812 self
.svp64_reset_loop()
1813 self
.svstate
.vfirst
= 0
1817 results
= [SelectableInt(0, 64)]
1818 self
.handle_comparison(results
) # CR0
1820 if self
.allow_next_step_inc
== 2:
1821 log("SVSTATE_NEXT: read")
1822 nia_update
= (yield from self
.svstate_post_inc(ins_name
))
1824 log("SVSTATE_NEXT: post-inc")
1825 # use actual src/dst-step here to check end, do NOT
1826 # use bit-reversed version
1827 srcstep
, dststep
= self
.new_srcstep
, self
.new_dststep
1828 ssubstep
, dsubstep
= self
.new_ssubstep
, self
.new_dsubstep
1829 remaps
= self
.get_remap_indices()
1830 remap_idxs
= self
.remap_idxs
1831 vl
= self
.svstate
.vl
1832 subvl
= yield self
.dec2
.rm_dec
.rm_in
.subvl
1833 end_src
= srcstep
== vl
-1
1834 end_dst
= dststep
== vl
-1
1835 if self
.allow_next_step_inc
!= 2:
1836 yield from self
.advance_svstate_steps(end_src
, end_dst
)
1837 #self.namespace['SVSTATE'] = self.svstate.spr
1838 # set CR0 (if Rc=1) based on end
1840 endtest
= 1 if (end_src
or end_dst
) else 0
1841 #results = [SelectableInt(endtest, 64)]
1842 # self.handle_comparison(results) # CR0
1844 # see if svstep was requested, if so, which SVSTATE
1846 if self
.svstate_next_mode
> 0:
1847 shape_idx
= self
.svstate_next_mode
.value
-1
1848 endings
= self
.remap_loopends
[shape_idx
]
1849 cr_field
= SelectableInt((~endings
) << 1 | endtest
, 4)
1850 log("svstep Rc=1, CR0", cr_field
)
1851 self
.crl
[0].eq(cr_field
) # CR0
1852 if end_src
or end_dst
:
1853 # reset at end of loop including exit Vertical Mode
1854 log("SVSTATE_NEXT: after increments, reset")
1855 self
.svp64_reset_loop()
1856 self
.svstate
.vfirst
= 0
1859 if self
.is_svp64_mode
:
1860 return (yield from self
.svstate_post_inc(ins_name
))
1862 # XXX only in non-SVP64 mode!
1863 # record state of whether the current operation was an svshape,
1865 # to be able to know if it should apply in the next instruction.
1866 # also (if going to use this instruction) should disable ability
1867 # to interrupt in between. sigh.
1868 self
.last_op_svshape
= asmop
in ['svremap', 'svindex', 'svshape2']
1872 def SVSTATE_NEXT(self
, mode
, submode
):
1873 """explicitly moves srcstep/dststep on to next element, for
1874 "Vertical-First" mode. this function is called from
1875 setvl pseudo-code, as a pseudo-op "svstep"
1877 WARNING: this function uses information that was created EARLIER
1878 due to it being in the middle of a yield, but this function is
1879 *NOT* called from yield (it's called from compiled pseudocode).
1881 self
.allow_next_step_inc
= submode
.value
+ 1
1882 log("SVSTATE_NEXT mode", mode
, submode
, self
.allow_next_step_inc
)
1883 self
.svstate_next_mode
= mode
1884 if self
.svstate_next_mode
> 0 and self
.svstate_next_mode
< 5:
1885 shape_idx
= self
.svstate_next_mode
.value
-1
1886 return SelectableInt(self
.remap_idxs
[shape_idx
], 7)
1887 if self
.svstate_next_mode
== 5:
1888 self
.svstate_next_mode
= 0
1889 return SelectableInt(self
.svstate
.srcstep
, 7)
1890 if self
.svstate_next_mode
== 6:
1891 self
.svstate_next_mode
= 0
1892 return SelectableInt(self
.svstate
.dststep
, 7)
1893 return SelectableInt(0, 7)
1895 def get_src_dststeps(self
):
1896 """gets srcstep, dststep, and ssubstep, dsubstep
1898 return (self
.new_srcstep
, self
.new_dststep
,
1899 self
.new_ssubstep
, self
.new_dsubstep
)
1901 def update_new_svstate_steps(self
):
1902 # note, do not get the bit-reversed srcstep here!
1903 srcstep
, dststep
= self
.new_srcstep
, self
.new_dststep
1904 ssubstep
, dsubstep
= self
.new_ssubstep
, self
.new_dsubstep
1906 # update SVSTATE with new srcstep
1907 self
.svstate
.srcstep
= srcstep
1908 self
.svstate
.dststep
= dststep
1909 self
.svstate
.ssubstep
= ssubstep
1910 self
.svstate
.dsubstep
= dsubstep
1911 self
.namespace
['SVSTATE'] = self
.svstate
1912 yield self
.dec2
.state
.svstate
.eq(self
.svstate
.value
)
1913 yield Settle() # let decoder update
1914 srcstep
= self
.svstate
.srcstep
1915 dststep
= self
.svstate
.dststep
1916 ssubstep
= self
.svstate
.ssubstep
1917 dsubstep
= self
.svstate
.dsubstep
1918 pack
= self
.svstate
.pack
1919 unpack
= self
.svstate
.unpack
1920 vl
= self
.svstate
.vl
1921 subvl
= yield self
.dec2
.rm_dec
.rm_in
.subvl
1922 log(" srcstep", srcstep
)
1923 log(" dststep", dststep
)
1925 log(" unpack", unpack
)
1926 log(" ssubstep", ssubstep
)
1927 log(" dsubstep", dsubstep
)
1929 log(" subvl", subvl
)
1931 # check if end reached (we let srcstep overrun, above)
1932 # nothing needs doing (TODO zeroing): just do next instruction
1933 return ((ssubstep
== subvl
and srcstep
== vl
) or
1934 (dsubstep
== subvl
and dststep
== vl
))
1936 def svstate_post_inc(self
, insn_name
, vf
=0):
1937 # check if SV "Vertical First" mode is enabled
1938 vfirst
= self
.svstate
.vfirst
1939 log(" SV Vertical First", vf
, vfirst
)
1940 if not vf
and vfirst
== 1:
1944 # check if it is the SVSTATE.src/dest step that needs incrementing
1945 # this is our Sub-Program-Counter loop from 0 to VL-1
1946 # XXX twin predication TODO
1947 vl
= self
.svstate
.vl
1948 subvl
= yield self
.dec2
.rm_dec
.rm_in
.subvl
1949 mvl
= self
.svstate
.maxvl
1950 srcstep
= self
.svstate
.srcstep
1951 dststep
= self
.svstate
.dststep
1952 ssubstep
= self
.svstate
.ssubstep
1953 dsubstep
= self
.svstate
.dsubstep
1954 pack
= self
.svstate
.pack
1955 unpack
= self
.svstate
.unpack
1956 rm_mode
= yield self
.dec2
.rm_dec
.mode
1957 reverse_gear
= yield self
.dec2
.rm_dec
.reverse_gear
1958 sv_ptype
= yield self
.dec2
.dec
.op
.SV_Ptype
1959 out_vec
= not (yield self
.dec2
.no_out_vec
)
1960 in_vec
= not (yield self
.dec2
.no_in_vec
)
1961 log(" svstate.vl", vl
)
1962 log(" svstate.mvl", mvl
)
1963 log(" rm.subvl", subvl
)
1964 log(" svstate.srcstep", srcstep
)
1965 log(" svstate.dststep", dststep
)
1966 log(" svstate.ssubstep", ssubstep
)
1967 log(" svstate.dsubstep", dsubstep
)
1968 log(" svstate.pack", pack
)
1969 log(" svstate.unpack", unpack
)
1970 log(" mode", rm_mode
)
1971 log(" reverse", reverse_gear
)
1972 log(" out_vec", out_vec
)
1973 log(" in_vec", in_vec
)
1974 log(" sv_ptype", sv_ptype
, sv_ptype
== SVPtype
.P2
.value
)
1975 # check if this was an sv.bc* and if so did it succeed
1976 if self
.is_svp64_mode
and insn_name
.startswith("sv.bc"):
1977 end_loop
= self
.namespace
['end_loop']
1978 log("branch %s end_loop" % insn_name
, end_loop
)
1980 self
.svp64_reset_loop()
1981 self
.update_pc_next()
1983 # check if srcstep needs incrementing by one, stop PC advancing
1984 # but for 2-pred both src/dest have to be checked.
1985 # XXX this might not be true! it may just be LD/ST
1986 if sv_ptype
== SVPtype
.P2
.value
:
1987 svp64_is_vector
= (out_vec
or in_vec
)
1989 svp64_is_vector
= out_vec
1990 # loops end at the first "hit" (source or dest)
1991 end_src
= srcstep
== vl
-1
1992 end_dst
= dststep
== vl
-1
1993 loopend
= ((end_src
and ssubstep
== subvl
) or
1994 (end_dst
and dsubstep
== subvl
))
1995 log("loopend", loopend
, end_src
, end_dst
,
1996 ssubstep
== subvl
, dsubstep
== subvl
)
1997 if not svp64_is_vector
or loopend
:
1998 # reset loop to zero and update NIA
1999 self
.svp64_reset_loop()
2004 # still looping, advance and update NIA
2005 yield from self
.advance_svstate_steps(end_src
, end_dst
)
2006 self
.namespace
['SVSTATE'] = self
.svstate
2008 # not an SVP64 branch, so fix PC (NIA==CIA) for next loop
2009 # (by default, NIA is CIA+4 if v3.0B or CIA+8 if SVP64)
2010 # this way we keep repeating the same instruction (with new steps)
2011 self
.pc
.NIA
.value
= self
.pc
.CIA
.value
2012 self
.namespace
['NIA'] = self
.pc
.NIA
2013 log("end of sub-pc call", self
.namespace
['CIA'], self
.namespace
['NIA'])
2014 return False # DO NOT allow PC update whilst Sub-PC loop running
2016 def update_pc_next(self
):
2017 # UPDATE program counter
2018 self
.pc
.update(self
.namespace
, self
.is_svp64_mode
)
2019 #self.svstate.spr = self.namespace['SVSTATE']
2020 log("end of call", self
.namespace
['CIA'],
2021 self
.namespace
['NIA'],
2022 self
.namespace
['SVSTATE'])
2024 def svp64_reset_loop(self
):
2025 self
.svstate
.srcstep
= 0
2026 self
.svstate
.dststep
= 0
2027 self
.svstate
.ssubstep
= 0
2028 self
.svstate
.dsubstep
= 0
2029 log(" svstate.srcstep loop end (PC to update)")
2030 self
.namespace
['SVSTATE'] = self
.svstate
2032 def update_nia(self
):
2033 self
.pc
.update_nia(self
.is_svp64_mode
)
2034 self
.namespace
['NIA'] = self
.pc
.NIA
2038 """Decorator factory.
2040 this decorator will "inject" variables into the function's namespace,
2041 from the *dictionary* in self.namespace. it therefore becomes possible
2042 to make it look like a whole stack of variables which would otherwise
2043 need "self." inserted in front of them (*and* for those variables to be
2044 added to the instance) "appear" in the function.
2046 "self.namespace['SI']" for example becomes accessible as just "SI" but
2047 *only* inside the function, when decorated.
2049 def variable_injector(func
):
2051 def decorator(*args
, **kwargs
):
2053 func_globals
= func
.__globals
__ # Python 2.6+
2054 except AttributeError:
2055 func_globals
= func
.func_globals
# Earlier versions.
2057 context
= args
[0].namespace
# variables to be injected
2058 saved_values
= func_globals
.copy() # Shallow copy of dict.
2059 log("globals before", context
.keys())
2060 func_globals
.update(context
)
2061 result
= func(*args
, **kwargs
)
2062 log("globals after", func_globals
['CIA'], func_globals
['NIA'])
2063 log("args[0]", args
[0].namespace
['CIA'],
2064 args
[0].namespace
['NIA'],
2065 args
[0].namespace
['SVSTATE'])
2066 if 'end_loop' in func_globals
:
2067 log("args[0] end_loop", func_globals
['end_loop'])
2068 args
[0].namespace
= func_globals
2069 #exec (func.__code__, func_globals)
2072 # func_globals = saved_values # Undo changes.
2078 return variable_injector