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
, SVP64MODEb
,
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')
69 # rrright. this is here basically because the compiler pywriter returns
70 # results in a specific priority order. to make sure regs match up they
71 # need partial sorting. sigh.
73 # TODO (lkcl): adjust other registers that should be in a particular order
74 # probably CA, CA32, and CR
100 "overflow": 7, # should definitely be last
104 fregs
= ['FRA', 'FRB', 'FRC', 'FRS', 'FRT']
107 def create_args(reglist
, extra
=None):
108 retval
= list(OrderedSet(reglist
))
109 retval
.sort(key
=lambda reg
: REG_SORT_ORDER
.get(reg
, 0))
110 if extra
is not None:
111 return [extra
] + retval
116 def __init__(self
, decoder
, isacaller
, svstate
, regfile
):
119 self
.isacaller
= isacaller
120 self
.svstate
= svstate
121 for i
in range(len(regfile
)):
122 self
[i
] = SelectableInt(regfile
[i
], 64)
124 def __call__(self
, ridx
):
125 if isinstance(ridx
, SelectableInt
):
129 def set_form(self
, form
):
132 def __setitem__(self
, rnum
, value
):
133 # rnum = rnum.value # only SelectableInt allowed
134 log("GPR setitem", rnum
, value
)
135 if isinstance(rnum
, SelectableInt
):
137 dict.__setitem
__(self
, rnum
, value
)
139 def getz(self
, rnum
):
140 # rnum = rnum.value # only SelectableInt allowed
141 log("GPR getzero?", rnum
)
143 return SelectableInt(0, 64)
146 def _get_regnum(self
, attr
):
147 getform
= self
.sd
.sigforms
[self
.form
]
148 rnum
= getattr(getform
, attr
)
151 def ___getitem__(self
, attr
):
152 """ XXX currently not used
154 rnum
= self
._get
_regnum
(attr
)
155 log("GPR getitem", attr
, rnum
)
156 return self
.regfile
[rnum
]
158 def dump(self
, printout
=True):
160 for i
in range(len(self
)):
161 res
.append(self
[i
].value
)
163 for i
in range(0, len(res
), 8):
166 s
.append("%08x" % res
[i
+j
])
168 print("reg", "%2d" % i
, s
)
173 def __init__(self
, dec2
, initial_sprs
={}):
176 for key
, v
in initial_sprs
.items():
177 if isinstance(key
, SelectableInt
):
179 key
= special_sprs
.get(key
, key
)
180 if isinstance(key
, int):
183 info
= spr_byname
[key
]
184 if not isinstance(v
, SelectableInt
):
185 v
= SelectableInt(v
, info
.length
)
188 def __getitem__(self
, key
):
190 log("dict", self
.items())
191 # if key in special_sprs get the special spr, otherwise return key
192 if isinstance(key
, SelectableInt
):
194 if isinstance(key
, int):
195 key
= spr_dict
[key
].SPR
196 key
= special_sprs
.get(key
, key
)
197 if key
== 'HSRR0': # HACK!
199 if key
== 'HSRR1': # HACK!
202 res
= dict.__getitem
__(self
, key
)
204 if isinstance(key
, int):
207 info
= spr_byname
[key
]
208 dict.__setitem
__(self
, key
, SelectableInt(0, info
.length
))
209 res
= dict.__getitem
__(self
, key
)
210 log("spr returning", key
, res
)
213 def __setitem__(self
, key
, value
):
214 if isinstance(key
, SelectableInt
):
216 if isinstance(key
, int):
217 key
= spr_dict
[key
].SPR
219 key
= special_sprs
.get(key
, key
)
220 if key
== 'HSRR0': # HACK!
221 self
.__setitem
__('SRR0', value
)
222 if key
== 'HSRR1': # HACK!
223 self
.__setitem
__('SRR1', value
)
224 log("setting spr", key
, value
)
225 dict.__setitem
__(self
, key
, value
)
227 def __call__(self
, ridx
):
230 def dump(self
, printout
=True):
232 keys
= list(self
.keys())
235 sprname
= spr_dict
.get(k
, None)
239 sprname
= sprname
.SPR
240 res
.append((sprname
, self
[k
].value
))
242 for sprname
, value
in res
:
243 print(" ", sprname
, hex(value
))
248 def __init__(self
, pc_init
=0):
249 self
.CIA
= SelectableInt(pc_init
, 64)
250 self
.NIA
= self
.CIA
+ SelectableInt(4, 64) # only true for v3.0B!
252 def update_nia(self
, is_svp64
):
253 increment
= 8 if is_svp64
else 4
254 self
.NIA
= self
.CIA
+ SelectableInt(increment
, 64)
256 def update(self
, namespace
, is_svp64
):
257 """updates the program counter (PC) by 4 if v3.0B mode or 8 if SVP64
259 self
.CIA
= namespace
['NIA'].narrow(64)
260 self
.update_nia(is_svp64
)
261 namespace
['CIA'] = self
.CIA
262 namespace
['NIA'] = self
.NIA
266 # See PowerISA Version 3.0 B Book 1
267 # Section 2.3.1 Condition Register pages 30 - 31
269 LT
= FL
= 0 # negative, less than, floating-point less than
270 GT
= FG
= 1 # positive, greater than, floating-point greater than
271 EQ
= FE
= 2 # equal, floating-point equal
272 SO
= FU
= 3 # summary overflow, floating-point unordered
274 def __init__(self
, init
=0):
275 # rev_cr = int('{:016b}'.format(initial_cr)[::-1], 2)
276 # self.cr = FieldSelectableInt(self._cr, list(range(32, 64)))
277 self
.cr
= SelectableInt(init
, 64) # underlying reg
278 # field-selectable versions of Condition Register TODO check bitranges?
281 bits
= tuple(range(i
*4+32, (i
+1)*4+32))
282 _cr
= FieldSelectableInt(self
.cr
, bits
)
286 # decode SVP64 predicate integer to reg number and invert
287 def get_predint(gpr
, mask
):
291 log("get_predint", mask
, SVP64PredInt
.ALWAYS
.value
)
292 if mask
== SVP64PredInt
.ALWAYS
.value
:
293 return 0xffff_ffff_ffff_ffff # 64 bits of 1
294 if mask
== SVP64PredInt
.R3_UNARY
.value
:
295 return 1 << (r3
.value
& 0b111111)
296 if mask
== SVP64PredInt
.R3
.value
:
298 if mask
== SVP64PredInt
.R3_N
.value
:
300 if mask
== SVP64PredInt
.R10
.value
:
302 if mask
== SVP64PredInt
.R10_N
.value
:
304 if mask
== SVP64PredInt
.R30
.value
:
306 if mask
== SVP64PredInt
.R30_N
.value
:
310 # decode SVP64 predicate CR to reg number and invert status
311 def _get_predcr(mask
):
312 if mask
== SVP64PredCR
.LT
.value
:
314 if mask
== SVP64PredCR
.GE
.value
:
316 if mask
== SVP64PredCR
.GT
.value
:
318 if mask
== SVP64PredCR
.LE
.value
:
320 if mask
== SVP64PredCR
.EQ
.value
:
322 if mask
== SVP64PredCR
.NE
.value
:
324 if mask
== SVP64PredCR
.SO
.value
:
326 if mask
== SVP64PredCR
.NS
.value
:
330 # read individual CR fields (0..VL-1), extract the required bit
331 # and construct the mask
332 def get_predcr(crl
, mask
, vl
):
333 idx
, noninv
= _get_predcr(mask
)
336 cr
= crl
[i
+SVP64CROffs
.CRPred
]
337 if cr
[idx
].value
== noninv
:
342 # TODO, really should just be using PowerDecoder2
343 def get_pdecode_idx_in(dec2
, name
):
345 in1_sel
= yield op
.in1_sel
346 in2_sel
= yield op
.in2_sel
347 in3_sel
= yield op
.in3_sel
348 # get the IN1/2/3 from the decoder (includes SVP64 remap and isvec)
349 in1
= yield dec2
.e
.read_reg1
.data
350 in2
= yield dec2
.e
.read_reg2
.data
351 in3
= yield dec2
.e
.read_reg3
.data
352 in1_isvec
= yield dec2
.in1_isvec
353 in2_isvec
= yield dec2
.in2_isvec
354 in3_isvec
= yield dec2
.in3_isvec
355 log("get_pdecode_idx_in in1", name
, in1_sel
, In1Sel
.RA
.value
,
357 log("get_pdecode_idx_in in2", name
, in2_sel
, In2Sel
.RB
.value
,
359 log("get_pdecode_idx_in in3", name
, in3_sel
, In3Sel
.RS
.value
,
361 log("get_pdecode_idx_in FRS in3", name
, in3_sel
, In3Sel
.FRS
.value
,
363 log("get_pdecode_idx_in FRB in2", name
, in2_sel
, In2Sel
.FRB
.value
,
365 log("get_pdecode_idx_in FRC in3", name
, in3_sel
, In3Sel
.FRC
.value
,
367 # identify which regnames map to in1/2/3
368 if name
== 'RA' or name
== 'RA_OR_ZERO':
369 if (in1_sel
== In1Sel
.RA
.value
or
370 (in1_sel
== In1Sel
.RA_OR_ZERO
.value
and in1
!= 0)):
371 return in1
, in1_isvec
372 if in1_sel
== In1Sel
.RA_OR_ZERO
.value
:
373 return in1
, in1_isvec
375 if in2_sel
== In2Sel
.RB
.value
:
376 return in2
, in2_isvec
377 if in3_sel
== In3Sel
.RB
.value
:
378 return in3
, in3_isvec
379 # XXX TODO, RC doesn't exist yet!
381 if in3_sel
== In3Sel
.RC
.value
:
382 return in3
, in3_isvec
383 assert False, "RC does not exist yet"
385 if in1_sel
== In1Sel
.RS
.value
:
386 return in1
, in1_isvec
387 if in2_sel
== In2Sel
.RS
.value
:
388 return in2
, in2_isvec
389 if in3_sel
== In3Sel
.RS
.value
:
390 return in3
, in3_isvec
392 if in1_sel
== In1Sel
.FRA
.value
:
393 return in1
, in1_isvec
395 if in2_sel
== In2Sel
.FRB
.value
:
396 return in2
, in2_isvec
398 if in3_sel
== In3Sel
.FRC
.value
:
399 return in3
, in3_isvec
401 if in1_sel
== In1Sel
.FRS
.value
:
402 return in1
, in1_isvec
403 if in3_sel
== In3Sel
.FRS
.value
:
404 return in3
, in3_isvec
408 # TODO, really should just be using PowerDecoder2
409 def get_pdecode_cr_in(dec2
, name
):
411 in_sel
= yield op
.cr_in
412 in_bitfield
= yield dec2
.dec_cr_in
.cr_bitfield
.data
413 sv_cr_in
= yield op
.sv_cr_in
414 spec
= yield dec2
.crin_svdec
.spec
415 sv_override
= yield dec2
.dec_cr_in
.sv_override
416 # get the IN1/2/3 from the decoder (includes SVP64 remap and isvec)
417 in1
= yield dec2
.e
.read_cr1
.data
418 cr_isvec
= yield dec2
.cr_in_isvec
419 log("get_pdecode_cr_in", in_sel
, CROutSel
.CR0
.value
, in1
, cr_isvec
)
420 log(" sv_cr_in", sv_cr_in
)
421 log(" cr_bf", in_bitfield
)
423 log(" override", sv_override
)
424 # identify which regnames map to in / o2
426 if in_sel
== CRInSel
.BI
.value
:
428 log("get_pdecode_cr_in not found", name
)
432 # TODO, really should just be using PowerDecoder2
433 def get_pdecode_cr_out(dec2
, name
):
435 out_sel
= yield op
.cr_out
436 out_bitfield
= yield dec2
.dec_cr_out
.cr_bitfield
.data
437 sv_cr_out
= yield op
.sv_cr_out
438 spec
= yield dec2
.crout_svdec
.spec
439 sv_override
= yield dec2
.dec_cr_out
.sv_override
440 # get the IN1/2/3 from the decoder (includes SVP64 remap and isvec)
441 out
= yield dec2
.e
.write_cr
.data
442 o_isvec
= yield dec2
.o_isvec
443 log("get_pdecode_cr_out", out_sel
, CROutSel
.CR0
.value
, out
, o_isvec
)
444 log(" sv_cr_out", sv_cr_out
)
445 log(" cr_bf", out_bitfield
)
447 log(" override", sv_override
)
448 # identify which regnames map to out / o2
450 if out_sel
== CROutSel
.CR0
.value
:
452 if name
== 'CR1': # these are not actually calculated correctly
453 if out_sel
== CROutSel
.CR1
.value
:
455 log("get_pdecode_cr_out not found", name
)
459 # TODO, really should just be using PowerDecoder2
460 def get_pdecode_idx_out(dec2
, name
):
462 out_sel
= yield op
.out_sel
463 # get the IN1/2/3 from the decoder (includes SVP64 remap and isvec)
464 out
= yield dec2
.e
.write_reg
.data
465 o_isvec
= yield dec2
.o_isvec
466 # identify which regnames map to out / o2
468 log("get_pdecode_idx_out", out_sel
, OutSel
.RA
.value
, out
, o_isvec
)
469 if out_sel
== OutSel
.RA
.value
:
472 log("get_pdecode_idx_out", out_sel
, OutSel
.RT
.value
,
473 OutSel
.RT_OR_ZERO
.value
, out
, o_isvec
,
475 if out_sel
== OutSel
.RT
.value
:
477 if out_sel
== OutSel
.RT_OR_ZERO
.value
and out
!= 0:
479 elif name
== 'RT_OR_ZERO':
480 log("get_pdecode_idx_out", out_sel
, OutSel
.RT
.value
,
481 OutSel
.RT_OR_ZERO
.value
, out
, o_isvec
,
483 if out_sel
== OutSel
.RT_OR_ZERO
.value
:
486 log("get_pdecode_idx_out", out_sel
, OutSel
.FRA
.value
, out
, o_isvec
)
487 if out_sel
== OutSel
.FRA
.value
:
490 log("get_pdecode_idx_out", out_sel
, OutSel
.FRT
.value
,
491 OutSel
.FRT
.value
, out
, o_isvec
)
492 if out_sel
== OutSel
.FRT
.value
:
494 log("get_pdecode_idx_out not found", name
, out_sel
, out
, o_isvec
)
498 # TODO, really should just be using PowerDecoder2
499 def get_pdecode_idx_out2(dec2
, name
):
500 # check first if register is activated for write
502 out_sel
= yield op
.out_sel
503 out
= yield dec2
.e
.write_ea
.data
504 o_isvec
= yield dec2
.o2_isvec
505 out_ok
= yield dec2
.e
.write_ea
.ok
506 log("get_pdecode_idx_out2", name
, out_sel
, out
, out_ok
, o_isvec
)
511 if hasattr(op
, "upd"):
512 # update mode LD/ST uses read-reg A also as an output
514 log("get_pdecode_idx_out2", upd
, LDSTMode
.update
.value
,
515 out_sel
, OutSel
.RA
.value
,
517 if upd
== LDSTMode
.update
.value
:
520 fft_en
= yield dec2
.implicit_rs
522 log("get_pdecode_idx_out2", out_sel
, OutSel
.RS
.value
,
526 fft_en
= yield dec2
.implicit_rs
528 log("get_pdecode_idx_out2", out_sel
, OutSel
.FRS
.value
,
535 """deals with svstate looping.
538 def __init__(self
, svstate
):
539 self
.svstate
= svstate
542 def new_iterators(self
):
543 self
.src_it
= self
.src_iterator()
544 self
.dst_it
= self
.dst_iterator()
548 self
.new_ssubstep
= 0
549 self
.new_dsubstep
= 0
550 self
.pred_dst_zero
= 0
551 self
.pred_src_zero
= 0
553 def src_iterator(self
):
554 """source-stepping iterator
556 pack
= self
.svstate
.pack
560 # pack advances subvl in *outer* loop
561 while True: # outer subvl loop
562 while True: # inner vl loop
565 srcmask
= self
.srcmask
566 srcstep
= self
.svstate
.srcstep
567 pred_src_zero
= ((1 << srcstep
) & srcmask
) != 0
568 if self
.pred_sz
or pred_src_zero
:
569 self
.pred_src_zero
= not pred_src_zero
570 log(" advance src", srcstep
, vl
,
571 self
.svstate
.ssubstep
, subvl
)
572 # yield actual substep/srcstep
573 yield (self
.svstate
.ssubstep
, srcstep
)
574 # the way yield works these could have been modified.
577 srcstep
= self
.svstate
.srcstep
578 log(" advance src check", srcstep
, vl
,
579 self
.svstate
.ssubstep
, subvl
, srcstep
== vl
-1,
580 self
.svstate
.ssubstep
== subvl
)
581 if srcstep
== vl
-1: # end-point
582 self
.svstate
.srcstep
= SelectableInt(0, 7) # reset
583 if self
.svstate
.ssubstep
== subvl
: # end-point
584 log(" advance pack stop")
586 break # exit inner loop
587 self
.svstate
.srcstep
+= SelectableInt(1, 7) # advance ss
589 if self
.svstate
.ssubstep
== subvl
: # end-point
590 self
.svstate
.ssubstep
= SelectableInt(0, 2) # reset
591 log(" advance pack stop")
593 self
.svstate
.ssubstep
+= SelectableInt(1, 2)
596 # these cannot be done as for-loops because SVSTATE may change
597 # (srcstep/substep may be modified, interrupted, subvl/vl change)
598 # but they *can* be done as while-loops as long as every SVSTATE
599 # "thing" is re-read every single time a yield gives indices
600 while True: # outer vl loop
601 while True: # inner subvl loop
604 srcmask
= self
.srcmask
605 srcstep
= self
.svstate
.srcstep
606 pred_src_zero
= ((1 << srcstep
) & srcmask
) != 0
607 if self
.pred_sz
or pred_src_zero
:
608 self
.pred_src_zero
= not pred_src_zero
609 log(" advance src", srcstep
, vl
,
610 self
.svstate
.ssubstep
, subvl
)
611 # yield actual substep/srcstep
612 yield (self
.svstate
.ssubstep
, srcstep
)
613 if self
.svstate
.ssubstep
== subvl
: # end-point
614 self
.svstate
.ssubstep
= SelectableInt(0, 2) # reset
615 break # exit inner loop
616 self
.svstate
.ssubstep
+= SelectableInt(1, 2)
618 if srcstep
== vl
-1: # end-point
619 self
.svstate
.srcstep
= SelectableInt(0, 7) # reset
622 self
.svstate
.srcstep
+= SelectableInt(1, 7) # advance srcstep
624 def dst_iterator(self
):
625 """dest-stepping iterator
627 unpack
= self
.svstate
.unpack
631 # pack advances subvl in *outer* loop
632 while True: # outer subvl loop
633 while True: # inner vl loop
636 dstmask
= self
.dstmask
637 dststep
= self
.svstate
.dststep
638 pred_dst_zero
= ((1 << dststep
) & dstmask
) != 0
639 if self
.pred_dz
or pred_dst_zero
:
640 self
.pred_dst_zero
= not pred_dst_zero
641 log(" advance dst", dststep
, vl
,
642 self
.svstate
.dsubstep
, subvl
)
643 # yield actual substep/dststep
644 yield (self
.svstate
.dsubstep
, dststep
)
645 # the way yield works these could have been modified.
647 dststep
= self
.svstate
.dststep
648 log(" advance dst check", dststep
, vl
,
649 self
.svstate
.ssubstep
, subvl
)
650 if dststep
== vl
-1: # end-point
651 self
.svstate
.dststep
= SelectableInt(0, 7) # reset
652 if self
.svstate
.dsubstep
== subvl
: # end-point
653 log(" advance unpack stop")
656 self
.svstate
.dststep
+= SelectableInt(1, 7) # advance ds
658 if self
.svstate
.dsubstep
== subvl
: # end-point
659 self
.svstate
.dsubstep
= SelectableInt(0, 2) # reset
660 log(" advance unpack stop")
662 self
.svstate
.dsubstep
+= SelectableInt(1, 2)
664 # these cannot be done as for-loops because SVSTATE may change
665 # (dststep/substep may be modified, interrupted, subvl/vl change)
666 # but they *can* be done as while-loops as long as every SVSTATE
667 # "thing" is re-read every single time a yield gives indices
668 while True: # outer vl loop
669 while True: # inner subvl loop
671 dstmask
= self
.dstmask
672 dststep
= self
.svstate
.dststep
673 pred_dst_zero
= ((1 << dststep
) & dstmask
) != 0
674 if self
.pred_dz
or pred_dst_zero
:
675 self
.pred_dst_zero
= not pred_dst_zero
676 log(" advance dst", dststep
, self
.svstate
.vl
,
677 self
.svstate
.dsubstep
, subvl
)
678 # yield actual substep/dststep
679 yield (self
.svstate
.dsubstep
, dststep
)
680 if self
.svstate
.dsubstep
== subvl
: # end-point
681 self
.svstate
.dsubstep
= SelectableInt(0, 2) # reset
683 self
.svstate
.dsubstep
+= SelectableInt(1, 2)
686 if dststep
== vl
-1: # end-point
687 self
.svstate
.dststep
= SelectableInt(0, 7) # reset
689 self
.svstate
.dststep
+= SelectableInt(1, 7) # advance dststep
691 def src_iterate(self
):
692 """source-stepping iterator
696 pack
= self
.svstate
.pack
697 unpack
= self
.svstate
.unpack
698 ssubstep
= self
.svstate
.ssubstep
699 end_ssub
= ssubstep
== subvl
700 end_src
= self
.svstate
.srcstep
== vl
-1
701 log(" pack/unpack/subvl", pack
, unpack
, subvl
,
705 srcstep
= self
.svstate
.srcstep
706 srcmask
= self
.srcmask
708 # pack advances subvl in *outer* loop
710 assert srcstep
<= vl
-1
711 end_src
= srcstep
== vl
-1
716 self
.svstate
.ssubstep
+= SelectableInt(1, 2)
720 srcstep
+= 1 # advance srcstep
721 if not self
.srcstep_skip
:
723 if ((1 << srcstep
) & srcmask
) != 0:
726 log(" sskip", bin(srcmask
), bin(1 << srcstep
))
728 # advance subvl in *inner* loop
731 assert srcstep
<= vl
-1
732 end_src
= srcstep
== vl
-1
733 if end_src
: # end-point
739 if not self
.srcstep_skip
:
741 if ((1 << srcstep
) & srcmask
) != 0:
744 log(" sskip", bin(srcmask
), bin(1 << srcstep
))
745 self
.svstate
.ssubstep
= SelectableInt(0, 2) # reset
748 self
.svstate
.ssubstep
+= SelectableInt(1, 2)
750 self
.svstate
.srcstep
= SelectableInt(srcstep
, 7)
751 log(" advance src", self
.svstate
.srcstep
, self
.svstate
.ssubstep
,
754 def dst_iterate(self
):
755 """dest step iterator
759 pack
= self
.svstate
.pack
760 unpack
= self
.svstate
.unpack
761 dsubstep
= self
.svstate
.dsubstep
762 end_dsub
= dsubstep
== subvl
763 dststep
= self
.svstate
.dststep
764 end_dst
= dststep
== vl
-1
765 dstmask
= self
.dstmask
766 log(" pack/unpack/subvl", pack
, unpack
, subvl
,
771 # unpack advances subvl in *outer* loop
773 assert dststep
<= vl
-1
774 end_dst
= dststep
== vl
-1
779 self
.svstate
.dsubstep
+= SelectableInt(1, 2)
783 dststep
+= 1 # advance dststep
784 if not self
.dststep_skip
:
786 if ((1 << dststep
) & dstmask
) != 0:
789 log(" dskip", bin(dstmask
), bin(1 << dststep
))
791 # advance subvl in *inner* loop
794 assert dststep
<= vl
-1
795 end_dst
= dststep
== vl
-1
796 if end_dst
: # end-point
802 if not self
.dststep_skip
:
804 if ((1 << dststep
) & dstmask
) != 0:
807 log(" dskip", bin(dstmask
), bin(1 << dststep
))
808 self
.svstate
.dsubstep
= SelectableInt(0, 2) # reset
811 self
.svstate
.dsubstep
+= SelectableInt(1, 2)
813 self
.svstate
.dststep
= SelectableInt(dststep
, 7)
814 log(" advance dst", self
.svstate
.dststep
, self
.svstate
.dsubstep
,
817 def at_loopend(self
):
818 """tells if this is the last possible element. uses the cached values
819 for src/dst-step and sub-steps
823 srcstep
, dststep
= self
.new_srcstep
, self
.new_dststep
824 ssubstep
, dsubstep
= self
.new_ssubstep
, self
.new_dsubstep
825 end_ssub
= ssubstep
== subvl
826 end_dsub
= dsubstep
== subvl
827 if srcstep
== vl
-1 and end_ssub
:
829 if dststep
== vl
-1 and end_dsub
:
833 def advance_svstate_steps(self
):
834 """ advance sub/steps. note that Pack/Unpack *INVERTS* the order.
835 TODO when Pack/Unpack is set, substep becomes the *outer* loop
837 self
.subvl
= yield self
.dec2
.rm_dec
.rm_in
.subvl
838 if self
.loopend
: # huhn??
843 def read_src_mask(self
):
844 """read/update pred_sz and src mask
846 # get SVSTATE VL (oh and print out some debug stuff)
848 srcstep
= self
.svstate
.srcstep
849 ssubstep
= self
.svstate
.ssubstep
851 # get predicate mask (all 64 bits)
852 srcmask
= 0xffff_ffff_ffff_ffff
854 pmode
= yield self
.dec2
.rm_dec
.predmode
855 sv_ptype
= yield self
.dec2
.dec
.op
.SV_Ptype
856 srcpred
= yield self
.dec2
.rm_dec
.srcpred
857 dstpred
= yield self
.dec2
.rm_dec
.dstpred
858 pred_sz
= yield self
.dec2
.rm_dec
.pred_sz
859 if pmode
== SVP64PredMode
.INT
.value
:
860 srcmask
= dstmask
= get_predint(self
.gpr
, dstpred
)
861 if sv_ptype
== SVPtype
.P2
.value
:
862 srcmask
= get_predint(self
.gpr
, srcpred
)
863 elif pmode
== SVP64PredMode
.CR
.value
:
864 srcmask
= dstmask
= get_predcr(self
.crl
, dstpred
, vl
)
865 if sv_ptype
== SVPtype
.P2
.value
:
866 srcmask
= get_predcr(self
.crl
, srcpred
, vl
)
867 # work out if the ssubsteps are completed
868 ssubstart
= ssubstep
== 0
870 log(" ptype", sv_ptype
)
871 log(" srcpred", bin(srcpred
))
872 log(" srcmask", bin(srcmask
))
873 log(" pred_sz", bin(pred_sz
))
874 log(" ssubstart", ssubstart
)
876 # store all that above
877 self
.srcstep_skip
= False
878 self
.srcmask
= srcmask
879 self
.pred_sz
= pred_sz
880 self
.new_ssubstep
= ssubstep
881 log(" new ssubstep", ssubstep
)
882 # until the predicate mask has a "1" bit... or we run out of VL
883 # let srcstep==VL be the indicator to move to next instruction
885 self
.srcstep_skip
= True
887 def read_dst_mask(self
):
888 """same as read_src_mask - check and record everything needed
890 # get SVSTATE VL (oh and print out some debug stuff)
891 # yield Delay(1e-10) # make changes visible
893 dststep
= self
.svstate
.dststep
894 dsubstep
= self
.svstate
.dsubstep
896 # get predicate mask (all 64 bits)
897 dstmask
= 0xffff_ffff_ffff_ffff
899 pmode
= yield self
.dec2
.rm_dec
.predmode
900 reverse_gear
= yield self
.dec2
.rm_dec
.reverse_gear
901 sv_ptype
= yield self
.dec2
.dec
.op
.SV_Ptype
902 dstpred
= yield self
.dec2
.rm_dec
.dstpred
903 pred_dz
= yield self
.dec2
.rm_dec
.pred_dz
904 if pmode
== SVP64PredMode
.INT
.value
:
905 dstmask
= get_predint(self
.gpr
, dstpred
)
906 elif pmode
== SVP64PredMode
.CR
.value
:
907 dstmask
= get_predcr(self
.crl
, dstpred
, vl
)
908 # work out if the ssubsteps are completed
909 dsubstart
= dsubstep
== 0
911 log(" ptype", sv_ptype
)
912 log(" dstpred", bin(dstpred
))
913 log(" dstmask", bin(dstmask
))
914 log(" pred_dz", bin(pred_dz
))
915 log(" dsubstart", dsubstart
)
917 self
.dststep_skip
= False
918 self
.dstmask
= dstmask
919 self
.pred_dz
= pred_dz
920 self
.new_dsubstep
= dsubstep
921 log(" new dsubstep", dsubstep
)
923 self
.dststep_skip
= True
925 def svstate_pre_inc(self
):
926 """check if srcstep/dststep need to skip over masked-out predicate bits
927 note that this is not supposed to do anything to substep,
928 it is purely for skipping masked-out bits
931 self
.subvl
= yield self
.dec2
.rm_dec
.rm_in
.subvl
932 yield from self
.read_src_mask()
933 yield from self
.read_dst_mask()
940 srcstep
= self
.svstate
.srcstep
941 srcmask
= self
.srcmask
942 pred_src_zero
= self
.pred_sz
944 # srcstep-skipping opportunity identified
945 if self
.srcstep_skip
:
946 # cannot do this with sv.bc - XXX TODO
949 while (((1 << srcstep
) & srcmask
) == 0) and (srcstep
!= vl
):
950 log(" sskip", bin(1 << srcstep
))
953 # now work out if the relevant mask bits require zeroing
955 pred_src_zero
= ((1 << srcstep
) & srcmask
) == 0
957 # store new srcstep / dststep
958 self
.new_srcstep
= srcstep
959 self
.pred_src_zero
= pred_src_zero
960 log(" new srcstep", srcstep
)
963 # dststep-skipping opportunity identified
964 dststep
= self
.svstate
.dststep
965 dstmask
= self
.dstmask
966 pred_dst_zero
= self
.pred_dz
968 if self
.dststep_skip
:
969 # cannot do this with sv.bc - XXX TODO
972 while (((1 << dststep
) & dstmask
) == 0) and (dststep
!= vl
):
973 log(" dskip", bin(1 << dststep
))
976 # now work out if the relevant mask bits require zeroing
978 pred_dst_zero
= ((1 << dststep
) & dstmask
) == 0
980 # store new srcstep / dststep
981 self
.new_dststep
= dststep
982 self
.pred_dst_zero
= pred_dst_zero
983 log(" new dststep", dststep
)
986 class ISACaller(ISACallerHelper
, ISAFPHelpers
, StepLoop
):
987 # decoder2 - an instance of power_decoder2
988 # regfile - a list of initial values for the registers
989 # initial_{etc} - initial values for SPRs, Condition Register, Mem, MSR
990 # respect_pc - tracks the program counter. requires initial_insns
991 def __init__(self
, decoder2
, regfile
, initial_sprs
=None, initial_cr
=0,
992 initial_mem
=None, initial_msr
=0,
1003 self
.bigendian
= bigendian
1005 self
.is_svp64_mode
= False
1006 self
.respect_pc
= respect_pc
1007 if initial_sprs
is None:
1009 if initial_mem
is None:
1011 if fpregfile
is None:
1012 fpregfile
= [0] * 32
1013 if initial_insns
is None:
1015 assert self
.respect_pc
== False, "instructions required to honor pc"
1017 log("ISACaller insns", respect_pc
, initial_insns
, disassembly
)
1018 log("ISACaller initial_msr", initial_msr
)
1020 # "fake program counter" mode (for unit testing)
1024 if isinstance(initial_mem
, tuple):
1025 self
.fake_pc
= initial_mem
[0]
1026 disasm_start
= self
.fake_pc
1028 disasm_start
= initial_pc
1030 # disassembly: we need this for now (not given from the decoder)
1031 self
.disassembly
= {}
1033 for i
, code
in enumerate(disassembly
):
1034 self
.disassembly
[i
*4 + disasm_start
] = code
1036 # set up registers, instruction memory, data memory, PC, SPRs, MSR, CR
1037 self
.svp64rm
= SVP64RM()
1038 if initial_svstate
is None:
1040 if isinstance(initial_svstate
, int):
1041 initial_svstate
= SVP64State(initial_svstate
)
1042 # SVSTATE, MSR and PC
1043 StepLoop
.__init
__(self
, initial_svstate
)
1044 self
.msr
= SelectableInt(initial_msr
, 64) # underlying reg
1046 # GPR FPR SPR registers
1047 initial_sprs
= deepcopy(initial_sprs
) # so as not to get modified
1048 self
.gpr
= GPR(decoder2
, self
, self
.svstate
, regfile
)
1049 self
.fpr
= GPR(decoder2
, self
, self
.svstate
, fpregfile
)
1050 self
.spr
= SPR(decoder2
, initial_sprs
) # initialise SPRs before MMU
1052 # set up 4 dummy SVSHAPEs if they aren't already set up
1054 sname
= 'SVSHAPE%d' % i
1055 val
= self
.spr
.get(sname
, 0)
1056 # make sure it's an SVSHAPE
1057 self
.spr
[sname
] = SVSHAPE(val
, self
.gpr
)
1058 self
.last_op_svshape
= False
1061 self
.mem
= Mem(row_bytes
=8, initial_mem
=initial_mem
)
1062 self
.mem
.log_fancy(kind
=LogKind
.InstrInOuts
)
1063 self
.imem
= Mem(row_bytes
=4, initial_mem
=initial_insns
)
1064 # MMU mode, redirect underlying Mem through RADIX
1066 self
.mem
= RADIX(self
.mem
, self
)
1068 self
.imem
= RADIX(self
.imem
, self
)
1070 # TODO, needed here:
1071 # FPR (same as GPR except for FP nums)
1072 # 4.2.2 p124 FPSCR (definitely "separate" - not in SPR)
1073 # note that mffs, mcrfs, mtfsf "manage" this FPSCR
1074 # 2.3.1 CR (and sub-fields CR0..CR6 - CR0 SO comes from XER.SO)
1075 # note that mfocrf, mfcr, mtcr, mtocrf, mcrxrx "manage" CRs
1077 # 2.3.2 LR (actually SPR #8) -- Done
1078 # 2.3.3 CTR (actually SPR #9) -- Done
1079 # 2.3.4 TAR (actually SPR #815)
1080 # 3.2.2 p45 XER (actually SPR #1) -- Done
1081 # 3.2.3 p46 p232 VRSAVE (actually SPR #256)
1083 # create CR then allow portions of it to be "selectable" (below)
1084 self
.cr_fields
= CRFields(initial_cr
)
1085 self
.cr
= self
.cr_fields
.cr
1087 # "undefined", just set to variable-bit-width int (use exts "max")
1088 # self.undefined = SelectableInt(0, 256) # TODO, not hard-code 256!
1091 self
.namespace
.update(self
.spr
)
1092 self
.namespace
.update({'GPR': self
.gpr
,
1096 'memassign': self
.memassign
,
1099 'SVSTATE': self
.svstate
,
1100 'SVSHAPE0': self
.spr
['SVSHAPE0'],
1101 'SVSHAPE1': self
.spr
['SVSHAPE1'],
1102 'SVSHAPE2': self
.spr
['SVSHAPE2'],
1103 'SVSHAPE3': self
.spr
['SVSHAPE3'],
1106 'undefined': undefined
,
1107 'mode_is_64bit': True,
1108 'SO': XER_bits
['SO'],
1109 'XLEN': 64 # elwidth overrides, later
1112 # update pc to requested start point
1113 self
.set_pc(initial_pc
)
1115 # field-selectable versions of Condition Register
1116 self
.crl
= self
.cr_fields
.crl
1118 self
.namespace
["CR%d" % i
] = self
.crl
[i
]
1120 self
.decoder
= decoder2
.dec
1121 self
.dec2
= decoder2
1123 super().__init
__(XLEN
=self
.namespace
["XLEN"])
1127 return self
.namespace
["XLEN"]
1129 def call_trap(self
, trap_addr
, trap_bit
):
1130 """calls TRAP and sets up NIA to the new execution location.
1131 next instruction will begin at trap_addr.
1133 self
.TRAP(trap_addr
, trap_bit
)
1134 self
.namespace
['NIA'] = self
.trap_nia
1135 self
.pc
.update(self
.namespace
, self
.is_svp64_mode
)
1137 def TRAP(self
, trap_addr
=0x700, trap_bit
=PIb
.TRAP
):
1138 """TRAP> saves PC, MSR (and TODO SVSTATE), and updates MSR
1140 TRAP function is callable from inside the pseudocode itself,
1141 hence the default arguments. when calling from inside ISACaller
1142 it is best to use call_trap()
1144 # https://bugs.libre-soc.org/show_bug.cgi?id=859
1145 kaivb
= self
.spr
['KAIVB'].value
1146 msr
= self
.namespace
['MSR'].value
1147 log("TRAP:", hex(trap_addr
), hex(msr
), "kaivb", hex(kaivb
))
1148 # store CIA(+4?) in SRR0, set NIA to 0x700
1149 # store MSR in SRR1, set MSR to um errr something, have to check spec
1150 # store SVSTATE (if enabled) in SVSRR0
1151 self
.spr
['SRR0'].value
= self
.pc
.CIA
.value
1152 self
.spr
['SRR1'].value
= msr
1153 if self
.is_svp64_mode
:
1154 self
.spr
['SVSRR0'] = self
.namespace
['SVSTATE'].value
1155 self
.trap_nia
= SelectableInt(trap_addr |
(kaivb
& ~
0x1fff), 64)
1156 self
.spr
['SRR1'][trap_bit
] = 1 # change *copy* of MSR in SRR1
1158 # set exception bits. TODO: this should, based on the address
1159 # in figure 66 p1065 V3.0B and the table figure 65 p1063 set these
1160 # bits appropriately. however it turns out that *for now* in all
1161 # cases (all trap_addrs) the exact same thing is needed.
1162 self
.msr
[MSRb
.IR
] = 0
1163 self
.msr
[MSRb
.DR
] = 0
1164 self
.msr
[MSRb
.FE0
] = 0
1165 self
.msr
[MSRb
.FE1
] = 0
1166 self
.msr
[MSRb
.EE
] = 0
1167 self
.msr
[MSRb
.RI
] = 0
1168 self
.msr
[MSRb
.SF
] = 1
1169 self
.msr
[MSRb
.TM
] = 0
1170 self
.msr
[MSRb
.VEC
] = 0
1171 self
.msr
[MSRb
.VSX
] = 0
1172 self
.msr
[MSRb
.PR
] = 0
1173 self
.msr
[MSRb
.FP
] = 0
1174 self
.msr
[MSRb
.PMM
] = 0
1175 self
.msr
[MSRb
.TEs
] = 0
1176 self
.msr
[MSRb
.TEe
] = 0
1177 self
.msr
[MSRb
.UND
] = 0
1178 self
.msr
[MSRb
.LE
] = 1
1180 def memassign(self
, ea
, sz
, val
):
1181 self
.mem
.memassign(ea
, sz
, val
)
1183 def prep_namespace(self
, insn_name
, formname
, op_fields
):
1184 # TODO: get field names from form in decoder*1* (not decoder2)
1185 # decoder2 is hand-created, and decoder1.sigform is auto-generated
1187 # then "yield" fields only from op_fields rather than hard-coded
1189 fields
= self
.decoder
.sigforms
[formname
]
1190 log("prep_namespace", formname
, op_fields
, insn_name
)
1191 for name
in op_fields
:
1192 # CR immediates. deal with separately. needs modifying
1194 if self
.is_svp64_mode
and name
in ['BI']: # TODO, more CRs
1195 # BI is a 5-bit, must reconstruct the value
1196 regnum
, is_vec
= yield from get_pdecode_cr_in(self
.dec2
, name
)
1197 sig
= getattr(fields
, name
)
1199 # low 2 LSBs (CR field selector) remain same, CR num extended
1200 assert regnum
<= 7, "sigh, TODO, 128 CR fields"
1201 val
= (val
& 0b11) |
(regnum
<< 2)
1203 sig
= getattr(fields
, name
)
1205 # these are all opcode fields involved in index-selection of CR,
1206 # and need to do "standard" arithmetic. CR[BA+32] for example
1207 # would, if using SelectableInt, only be 5-bit.
1208 if name
in ['BF', 'BFA', 'BC', 'BA', 'BB', 'BT', 'BI']:
1209 self
.namespace
[name
] = val
1211 self
.namespace
[name
] = SelectableInt(val
, sig
.width
)
1213 self
.namespace
['XER'] = self
.spr
['XER']
1214 self
.namespace
['CA'] = self
.spr
['XER'][XER_bits
['CA']].value
1215 self
.namespace
['CA32'] = self
.spr
['XER'][XER_bits
['CA32']].value
1217 # add some SVSTATE convenience variables
1218 vl
= self
.svstate
.vl
1219 srcstep
= self
.svstate
.srcstep
1220 self
.namespace
['VL'] = vl
1221 self
.namespace
['srcstep'] = srcstep
1223 # sv.bc* need some extra fields
1224 if self
.is_svp64_mode
and insn_name
.startswith("sv.bc"):
1225 # blegh grab bits manually
1226 mode
= yield self
.dec2
.rm_dec
.rm_in
.mode
1227 mode
= SelectableInt(mode
, 5) # convert to SelectableInt before test
1228 bc_vlset
= mode
[SVP64MODEb
.BC_VLSET
] != 0
1229 bc_vli
= mode
[SVP64MODEb
.BC_VLI
] != 0
1230 bc_snz
= mode
[SVP64MODEb
.BC_SNZ
] != 0
1231 bc_vsb
= yield self
.dec2
.rm_dec
.bc_vsb
1232 bc_lru
= yield self
.dec2
.rm_dec
.bc_lru
1233 bc_gate
= yield self
.dec2
.rm_dec
.bc_gate
1234 sz
= yield self
.dec2
.rm_dec
.pred_sz
1235 self
.namespace
['mode'] = SelectableInt(mode
, 5)
1236 self
.namespace
['ALL'] = SelectableInt(bc_gate
, 1)
1237 self
.namespace
['VSb'] = SelectableInt(bc_vsb
, 1)
1238 self
.namespace
['LRu'] = SelectableInt(bc_lru
, 1)
1239 self
.namespace
['VLSET'] = SelectableInt(bc_vlset
, 1)
1240 self
.namespace
['VLI'] = SelectableInt(bc_vli
, 1)
1241 self
.namespace
['sz'] = SelectableInt(sz
, 1)
1242 self
.namespace
['SNZ'] = SelectableInt(bc_snz
, 1)
1244 def handle_carry_(self
, inputs
, output
, ca
, ca32
):
1245 inv_a
= yield self
.dec2
.e
.do
.invert_in
1247 inputs
[0] = ~inputs
[0]
1249 imm_ok
= yield self
.dec2
.e
.do
.imm_data
.ok
1251 imm
= yield self
.dec2
.e
.do
.imm_data
.data
1252 inputs
.append(SelectableInt(imm
, 64))
1255 log("gt input", x
, output
)
1256 gt
= (gtu(x
, output
))
1259 cy
= 1 if any(gts
) else 0
1261 if ca
is None: # already written
1262 self
.spr
['XER'][XER_bits
['CA']] = cy
1265 # ARGH... different for OP_ADD... *sigh*...
1266 op
= yield self
.dec2
.e
.do
.insn_type
1267 if op
== MicrOp
.OP_ADD
.value
:
1268 res32
= (output
.value
& (1 << 32)) != 0
1269 a32
= (inputs
[0].value
& (1 << 32)) != 0
1270 if len(inputs
) >= 2:
1271 b32
= (inputs
[1].value
& (1 << 32)) != 0
1274 cy32
= res32 ^ a32 ^ b32
1275 log("CA32 ADD", cy32
)
1279 log("input", x
, output
)
1280 log(" x[32:64]", x
, x
[32:64])
1281 log(" o[32:64]", output
, output
[32:64])
1282 gt
= (gtu(x
[32:64], output
[32:64])) == SelectableInt(1, 1)
1284 cy32
= 1 if any(gts
) else 0
1285 log("CA32", cy32
, gts
)
1286 if ca32
is None: # already written
1287 self
.spr
['XER'][XER_bits
['CA32']] = cy32
1289 def handle_overflow(self
, inputs
, output
, div_overflow
):
1290 if hasattr(self
.dec2
.e
.do
, "invert_in"):
1291 inv_a
= yield self
.dec2
.e
.do
.invert_in
1293 inputs
[0] = ~inputs
[0]
1295 imm_ok
= yield self
.dec2
.e
.do
.imm_data
.ok
1297 imm
= yield self
.dec2
.e
.do
.imm_data
.data
1298 inputs
.append(SelectableInt(imm
, 64))
1299 log("handle_overflow", inputs
, output
, div_overflow
)
1300 if len(inputs
) < 2 and div_overflow
is None:
1303 # div overflow is different: it's returned by the pseudo-code
1304 # because it's more complex than can be done by analysing the output
1305 if div_overflow
is not None:
1306 ov
, ov32
= div_overflow
, div_overflow
1307 # arithmetic overflow can be done by analysing the input and output
1308 elif len(inputs
) >= 2:
1310 input_sgn
= [exts(x
.value
, x
.bits
) < 0 for x
in inputs
]
1311 output_sgn
= exts(output
.value
, output
.bits
) < 0
1312 ov
= 1 if input_sgn
[0] == input_sgn
[1] and \
1313 output_sgn
!= input_sgn
[0] else 0
1316 input32_sgn
= [exts(x
.value
, 32) < 0 for x
in inputs
]
1317 output32_sgn
= exts(output
.value
, 32) < 0
1318 ov32
= 1 if input32_sgn
[0] == input32_sgn
[1] and \
1319 output32_sgn
!= input32_sgn
[0] else 0
1321 # now update XER OV/OV32/SO
1322 so
= self
.spr
['XER'][XER_bits
['SO']]
1323 new_so
= so | ov
# sticky overflow ORs in old with new
1324 self
.spr
['XER'][XER_bits
['OV']] = ov
1325 self
.spr
['XER'][XER_bits
['OV32']] = ov32
1326 self
.spr
['XER'][XER_bits
['SO']] = new_so
1327 log(" set overflow", ov
, ov32
, so
, new_so
)
1329 def handle_comparison(self
, out
, cr_idx
=0, overflow
=None, no_so
=False):
1330 assert isinstance(out
, SelectableInt
), \
1331 "out zero not a SelectableInt %s" % repr(outputs
)
1332 log("handle_comparison", out
.bits
, hex(out
.value
))
1333 # TODO - XXX *processor* in 32-bit mode
1334 # https://bugs.libre-soc.org/show_bug.cgi?id=424
1336 # o32 = exts(out.value, 32)
1337 # print ("handle_comparison exts 32 bit", hex(o32))
1338 out
= exts(out
.value
, out
.bits
)
1339 log("handle_comparison exts", hex(out
))
1340 # create the three main CR flags, EQ GT LT
1341 zero
= SelectableInt(out
== 0, 1)
1342 positive
= SelectableInt(out
> 0, 1)
1343 negative
= SelectableInt(out
< 0, 1)
1344 # get (or not) XER.SO. for setvl this is important *not* to read SO
1346 SO
= SelectableInt(1, 0)
1348 SO
= self
.spr
['XER'][XER_bits
['SO']]
1349 log("handle_comparison SO overflow", SO
, overflow
)
1350 # alternative overflow checking (setvl mainly at the moment)
1351 if overflow
is not None and overflow
== 1:
1352 SO
= SelectableInt(1, 1)
1353 # create the four CR field values and set the required CR field
1354 cr_field
= selectconcat(negative
, positive
, zero
, SO
)
1355 log("handle_comparison cr_field", self
.cr
, cr_idx
, cr_field
)
1356 self
.crl
[cr_idx
].eq(cr_field
)
1358 def set_pc(self
, pc_val
):
1359 self
.namespace
['NIA'] = SelectableInt(pc_val
, 64)
1360 self
.pc
.update(self
.namespace
, self
.is_svp64_mode
)
1362 def get_next_insn(self
):
1363 """check instruction
1366 pc
= self
.pc
.CIA
.value
1369 ins
= self
.imem
.ld(pc
, 4, False, True, instr_fetch
=True)
1371 raise KeyError("no instruction at 0x%x" % pc
)
1374 def setup_one(self
):
1375 """set up one instruction
1377 pc
, insn
= self
.get_next_insn()
1378 yield from self
.setup_next_insn(pc
, insn
)
1380 def setup_next_insn(self
, pc
, ins
):
1381 """set up next instruction
1384 log("setup: 0x%x 0x%x %s" % (pc
, ins
& 0xffffffff, bin(ins
)))
1385 log("CIA NIA", self
.respect_pc
, self
.pc
.CIA
.value
, self
.pc
.NIA
.value
)
1387 yield self
.dec2
.sv_rm
.eq(0)
1388 yield self
.dec2
.dec
.raw_opcode_in
.eq(ins
& 0xffffffff)
1389 yield self
.dec2
.dec
.bigendian
.eq(self
.bigendian
)
1390 yield self
.dec2
.state
.msr
.eq(self
.msr
.value
)
1391 yield self
.dec2
.state
.pc
.eq(pc
)
1392 if self
.svstate
is not None:
1393 yield self
.dec2
.state
.svstate
.eq(self
.svstate
.value
)
1395 # SVP64. first, check if the opcode is EXT001, and SVP64 id bits set
1397 opcode
= yield self
.dec2
.dec
.opcode_in
1398 opcode
= SelectableInt(value
=opcode
, bits
=32)
1399 pfx
= SVP64Instruction
.Prefix(opcode
)
1400 log("prefix test: opcode:", pfx
.po
, bin(pfx
.po
), pfx
.id)
1401 self
.is_svp64_mode
= bool((pfx
.po
== 0b000001) and (pfx
.id == 0b11))
1402 self
.pc
.update_nia(self
.is_svp64_mode
)
1404 yield self
.dec2
.is_svp64_mode
.eq(self
.is_svp64_mode
)
1405 self
.namespace
['NIA'] = self
.pc
.NIA
1406 self
.namespace
['SVSTATE'] = self
.svstate
1407 if not self
.is_svp64_mode
:
1410 # in SVP64 mode. decode/print out svp64 prefix, get v3.0B instruction
1411 log("svp64.rm", bin(pfx
.rm
))
1412 log(" svstate.vl", self
.svstate
.vl
)
1413 log(" svstate.mvl", self
.svstate
.maxvl
)
1414 ins
= self
.imem
.ld(pc
+4, 4, False, True, instr_fetch
=True)
1415 log(" svsetup: 0x%x 0x%x %s" % (pc
+4, ins
& 0xffffffff, bin(ins
)))
1416 yield self
.dec2
.dec
.raw_opcode_in
.eq(ins
& 0xffffffff) # v3.0B suffix
1417 yield self
.dec2
.sv_rm
.eq(int(pfx
.rm
)) # svp64 prefix
1420 def execute_one(self
):
1421 """execute one instruction
1423 # get the disassembly code for this instruction
1424 if not self
.disassembly
:
1425 code
= yield from self
.get_assembly_name()
1428 if self
.is_svp64_mode
:
1429 offs
, dbg
= 4, "svp64 "
1430 code
= self
.disassembly
[self
._pc
+offs
]
1431 log(" %s sim-execute" % dbg
, hex(self
._pc
), code
)
1432 opname
= code
.split(' ')[0]
1434 yield from self
.call(opname
) # execute the instruction
1435 except MemException
as e
: # check for memory errors
1436 if e
.args
[0] == 'unaligned': # alignment error
1437 # run a Trap but set DAR first
1438 print("memory unaligned exception, DAR", e
.dar
)
1439 self
.spr
['DAR'] = SelectableInt(e
.dar
, 64)
1440 self
.call_trap(0x600, PIb
.PRIV
) # 0x600, privileged
1442 elif e
.args
[0] == 'invalid': # invalid
1443 # run a Trap but set DAR first
1444 log("RADIX MMU memory invalid error, mode %s" % e
.mode
)
1445 if e
.mode
== 'EXECUTE':
1446 # XXX TODO: must set a few bits in SRR1,
1447 # see microwatt loadstore1.vhdl
1448 # if m_in.segerr = '0' then
1449 # v.srr1(47 - 33) := m_in.invalid;
1450 # v.srr1(47 - 35) := m_in.perm_error; -- noexec fault
1451 # v.srr1(47 - 44) := m_in.badtree;
1452 # v.srr1(47 - 45) := m_in.rc_error;
1453 # v.intr_vec := 16#400#;
1455 # v.intr_vec := 16#480#;
1456 self
.call_trap(0x400, PIb
.PRIV
) # 0x400, privileged
1458 self
.call_trap(0x300, PIb
.PRIV
) # 0x300, privileged
1460 # not supported yet:
1461 raise e
# ... re-raise
1463 # don't use this except in special circumstances
1464 if not self
.respect_pc
:
1467 log("execute one, CIA NIA", hex(self
.pc
.CIA
.value
),
1468 hex(self
.pc
.NIA
.value
))
1470 def get_assembly_name(self
):
1471 # TODO, asmregs is from the spec, e.g. add RT,RA,RB
1472 # see http://bugs.libre-riscv.org/show_bug.cgi?id=282
1473 dec_insn
= yield self
.dec2
.e
.do
.insn
1474 insn_1_11
= yield self
.dec2
.e
.do
.insn
[1:11]
1475 asmcode
= yield self
.dec2
.dec
.op
.asmcode
1476 int_op
= yield self
.dec2
.dec
.op
.internal_op
1477 log("get assembly name asmcode", asmcode
, int_op
,
1478 hex(dec_insn
), bin(insn_1_11
))
1479 asmop
= insns
.get(asmcode
, None)
1481 # sigh reconstruct the assembly instruction name
1482 if hasattr(self
.dec2
.e
.do
, "oe"):
1483 ov_en
= yield self
.dec2
.e
.do
.oe
.oe
1484 ov_ok
= yield self
.dec2
.e
.do
.oe
.ok
1488 if hasattr(self
.dec2
.e
.do
, "rc"):
1489 rc_en
= yield self
.dec2
.e
.do
.rc
.rc
1490 rc_ok
= yield self
.dec2
.e
.do
.rc
.ok
1494 # annoying: ignore rc_ok if RC1 is set (for creating *assembly name*)
1495 RC1
= yield self
.dec2
.rm_dec
.RC1
1499 # grrrr have to special-case MUL op (see DecodeOE)
1500 log("ov %d en %d rc %d en %d op %d" %
1501 (ov_ok
, ov_en
, rc_ok
, rc_en
, int_op
))
1502 if int_op
in [MicrOp
.OP_MUL_H64
.value
, MicrOp
.OP_MUL_H32
.value
]:
1507 if not asmop
.endswith("."): # don't add "." to "andis."
1510 if hasattr(self
.dec2
.e
.do
, "lk"):
1511 lk
= yield self
.dec2
.e
.do
.lk
1514 log("int_op", int_op
)
1515 if int_op
in [MicrOp
.OP_B
.value
, MicrOp
.OP_BC
.value
]:
1516 AA
= yield self
.dec2
.dec
.fields
.FormI
.AA
[0:-1]
1520 spr_msb
= yield from self
.get_spr_msb()
1521 if int_op
== MicrOp
.OP_MFCR
.value
:
1526 # XXX TODO: for whatever weird reason this doesn't work
1527 # https://bugs.libre-soc.org/show_bug.cgi?id=390
1528 if int_op
== MicrOp
.OP_MTCRF
.value
:
1535 def reset_remaps(self
):
1536 self
.remap_loopends
= [0] * 4
1537 self
.remap_idxs
= [0, 1, 2, 3]
1539 def get_remap_indices(self
):
1540 """WARNING, this function stores remap_idxs and remap_loopends
1541 in the class for later use. this to avoid problems with yield
1543 # go through all iterators in lock-step, advance to next remap_idx
1544 srcstep
, dststep
, ssubstep
, dsubstep
= self
.get_src_dststeps()
1545 # get four SVSHAPEs. here we are hard-coding
1547 SVSHAPE0
= self
.spr
['SVSHAPE0']
1548 SVSHAPE1
= self
.spr
['SVSHAPE1']
1549 SVSHAPE2
= self
.spr
['SVSHAPE2']
1550 SVSHAPE3
= self
.spr
['SVSHAPE3']
1551 # set up the iterators
1552 remaps
= [(SVSHAPE0
, SVSHAPE0
.get_iterator()),
1553 (SVSHAPE1
, SVSHAPE1
.get_iterator()),
1554 (SVSHAPE2
, SVSHAPE2
.get_iterator()),
1555 (SVSHAPE3
, SVSHAPE3
.get_iterator()),
1559 for i
, (shape
, remap
) in enumerate(remaps
):
1560 # zero is "disabled"
1561 if shape
.value
== 0x0:
1562 self
.remap_idxs
[i
] = 0
1563 # pick src or dststep depending on reg num (0-2=in, 3-4=out)
1564 step
= dststep
if (i
in [3, 4]) else srcstep
1565 # this is terrible. O(N^2) looking for the match. but hey.
1566 for idx
, (remap_idx
, loopends
) in enumerate(remap
):
1569 self
.remap_idxs
[i
] = remap_idx
1570 self
.remap_loopends
[i
] = loopends
1571 dbg
.append((i
, step
, remap_idx
, loopends
))
1572 for (i
, step
, remap_idx
, loopends
) in dbg
:
1573 log("SVSHAPE %d idx, end" % i
, step
, remap_idx
, bin(loopends
))
1576 def get_spr_msb(self
):
1577 dec_insn
= yield self
.dec2
.e
.do
.insn
1578 return dec_insn
& (1 << 20) != 0 # sigh - XFF.spr[-1]?
1580 def call(self
, name
):
1581 """call(opcode) - the primary execution point for instructions
1583 self
.last_st_addr
= None # reset the last known store address
1584 self
.last_ld_addr
= None # etc.
1586 ins_name
= name
.strip() # remove spaces if not already done so
1588 log("halted - not executing", ins_name
)
1591 # TODO, asmregs is from the spec, e.g. add RT,RA,RB
1592 # see http://bugs.libre-riscv.org/show_bug.cgi?id=282
1593 asmop
= yield from self
.get_assembly_name()
1594 log("call", ins_name
, asmop
)
1596 # sv.setvl is *not* a loop-function. sigh
1597 log("is_svp64_mode", self
.is_svp64_mode
, asmop
)
1600 int_op
= yield self
.dec2
.dec
.op
.internal_op
1601 spr_msb
= yield from self
.get_spr_msb()
1603 instr_is_privileged
= False
1604 if int_op
in [MicrOp
.OP_ATTN
.value
,
1605 MicrOp
.OP_MFMSR
.value
,
1606 MicrOp
.OP_MTMSR
.value
,
1607 MicrOp
.OP_MTMSRD
.value
,
1609 MicrOp
.OP_RFID
.value
]:
1610 instr_is_privileged
= True
1611 if int_op
in [MicrOp
.OP_MFSPR
.value
,
1612 MicrOp
.OP_MTSPR
.value
] and spr_msb
:
1613 instr_is_privileged
= True
1615 log("is priv", instr_is_privileged
, hex(self
.msr
.value
),
1617 # check MSR priv bit and whether op is privileged: if so, throw trap
1618 if instr_is_privileged
and self
.msr
[MSRb
.PR
] == 1:
1619 self
.call_trap(0x700, PIb
.PRIV
)
1622 # check halted condition
1623 if ins_name
== 'attn':
1627 # check illegal instruction
1629 if ins_name
not in ['mtcrf', 'mtocrf']:
1630 illegal
= ins_name
!= asmop
1632 # list of instructions not being supported by binutils (.long)
1633 dotstrp
= asmop
[:-1] if asmop
[-1] == '.' else asmop
1634 if dotstrp
in [*FPTRANS_INSNS
,
1635 'ffmadds', 'fdmadds', 'ffadds',
1636 'mins', 'maxs', 'minu', 'maxu',
1637 'setvl', 'svindex', 'svremap', 'svstep',
1638 'svshape', 'svshape2',
1639 'grev', 'ternlogi', 'bmask', 'cprop',
1640 'absdu', 'absds', 'absdacs', 'absdacu', 'avgadd',
1641 'fmvis', 'fishmv', 'pcdec', "maddedu", "divmod2du",
1647 # branch-conditional redirects to sv.bc
1648 if asmop
.startswith('bc') and self
.is_svp64_mode
:
1649 ins_name
= 'sv.%s' % ins_name
1651 log(" post-processed name", dotstrp
, ins_name
, asmop
)
1653 # illegal instructions call TRAP at 0x700
1655 print("illegal", ins_name
, asmop
)
1656 self
.call_trap(0x700, PIb
.ILLEG
)
1657 print("name %s != %s - calling ILLEGAL trap, PC: %x" %
1658 (ins_name
, asmop
, self
.pc
.CIA
.value
))
1661 # this is for setvl "Vertical" mode: if set true,
1662 # srcstep/dststep is explicitly advanced. mode says which SVSTATE to
1663 # test for Rc=1 end condition. 3 bits of all 3 loops are put into CR0
1664 self
.allow_next_step_inc
= False
1665 self
.svstate_next_mode
= 0
1667 # nop has to be supported, we could let the actual op calculate
1668 # but PowerDecoder has a pattern for nop
1669 if ins_name
== 'nop':
1670 self
.update_pc_next()
1673 # look up instruction in ISA.instrs, prepare namespace
1674 if ins_name
== 'pcdec': # grrrr yes there are others ("stbcx." etc.)
1675 info
= self
.instrs
[ins_name
+"."]
1677 info
= self
.instrs
[ins_name
]
1678 yield from self
.prep_namespace(ins_name
, info
.form
, info
.op_fields
)
1680 # preserve order of register names
1681 input_names
= create_args(list(info
.read_regs
) +
1682 list(info
.uninit_regs
))
1683 log("input names", input_names
)
1685 # get SVP64 entry for the current instruction
1686 sv_rm
= self
.svp64rm
.instrs
.get(ins_name
)
1687 if sv_rm
is not None:
1688 dest_cr
, src_cr
, src_byname
, dest_byname
= decode_extra(sv_rm
)
1690 dest_cr
, src_cr
, src_byname
, dest_byname
= False, False, {}, {}
1691 log("sv rm", sv_rm
, dest_cr
, src_cr
, src_byname
, dest_byname
)
1693 # see if srcstep/dststep need skipping over masked-out predicate bits
1694 # svstep also needs advancement because it calls SVSTATE_NEXT.
1695 # bit the remaps get computed just after pre_inc moves them on
1696 # with remap_set_steps substituting for PowerDecider2 not doing it,
1697 # and SVSTATE_NEXT not being able to.use yield, the preinc on
1698 # svstep is necessary for now.
1700 if (self
.is_svp64_mode
or ins_name
in ['svstep']):
1701 yield from self
.svstate_pre_inc()
1702 if self
.is_svp64_mode
:
1703 pre
= yield from self
.update_new_svstate_steps()
1705 self
.svp64_reset_loop()
1707 self
.update_pc_next()
1709 srcstep
, dststep
, ssubstep
, dsubstep
= self
.get_src_dststeps()
1710 pred_dst_zero
= self
.pred_dst_zero
1711 pred_src_zero
= self
.pred_src_zero
1712 vl
= self
.svstate
.vl
1713 subvl
= yield self
.dec2
.rm_dec
.rm_in
.subvl
1715 # VL=0 in SVP64 mode means "do nothing: skip instruction"
1716 if self
.is_svp64_mode
and vl
== 0:
1717 self
.pc
.update(self
.namespace
, self
.is_svp64_mode
)
1718 log("SVP64: VL=0, end of call", self
.namespace
['CIA'],
1719 self
.namespace
['NIA'], kind
=LogKind
.InstrInOuts
)
1722 # for when SVREMAP is active, using pre-arranged schedule.
1723 # note: modifying PowerDecoder2 needs to "settle"
1724 remap_en
= self
.svstate
.SVme
1725 persist
= self
.svstate
.RMpst
1726 active
= (persist
or self
.last_op_svshape
) and remap_en
!= 0
1727 if self
.is_svp64_mode
:
1728 yield self
.dec2
.remap_active
.eq(remap_en
if active
else 0)
1730 if persist
or self
.last_op_svshape
:
1731 remaps
= self
.get_remap_indices()
1732 if self
.is_svp64_mode
and (persist
or self
.last_op_svshape
):
1733 yield from self
.remap_set_steps(remaps
)
1734 # after that, settle down (combinatorial) to let Vector reg numbers
1735 # work themselves out
1737 if self
.is_svp64_mode
:
1738 remap_active
= yield self
.dec2
.remap_active
1740 remap_active
= False
1741 log("remap active", bin(remap_active
))
1743 # main input registers (RT, RA ...)
1745 for name
in input_names
:
1747 regval
= (yield from self
.get_input(name
))
1748 log("regval", regval
)
1749 inputs
.append(regval
)
1751 # arrrrgh, awful hack, to get _RT into namespace
1752 if ins_name
in ['setvl', 'svstep']:
1754 RT
= yield self
.dec2
.dec
.RT
1755 self
.namespace
[regname
] = SelectableInt(RT
, 5)
1757 self
.namespace
["RT"] = SelectableInt(0, 5)
1758 regnum
, is_vec
= yield from get_pdecode_idx_out(self
.dec2
, "RT")
1759 log('hack input reg %s %s' % (name
, str(regnum
)), is_vec
)
1761 # in SVP64 mode for LD/ST work out immediate
1762 # XXX TODO: replace_ds for DS-Form rather than D-Form.
1763 # use info.form to detect
1764 if self
.is_svp64_mode
:
1765 yield from self
.check_replace_d(info
, remap_active
)
1767 # "special" registers
1768 for special
in info
.special_regs
:
1769 if special
in special_sprs
:
1770 inputs
.append(self
.spr
[special
])
1772 inputs
.append(self
.namespace
[special
])
1774 # clear trap (trap) NIA
1775 self
.trap_nia
= None
1777 # check if this was an sv.bc* and create an indicator that
1778 # this is the last check to be made as a loop. combined with
1779 # the ALL/ANY mode we can early-exit
1780 if self
.is_svp64_mode
and ins_name
.startswith("sv.bc"):
1781 no_in_vec
= yield self
.dec2
.no_in_vec
# BI is scalar
1782 end_loop
= no_in_vec
or srcstep
== vl
-1 or dststep
== vl
-1
1783 self
.namespace
['end_loop'] = SelectableInt(end_loop
, 1)
1785 # execute actual instruction here (finally)
1786 log("inputs", inputs
)
1787 results
= info
.func(self
, *inputs
)
1788 output_names
= create_args(info
.write_regs
)
1790 for out
, n
in zip(results
or [], output_names
):
1792 log("results", outs
)
1794 # "inject" decorator takes namespace from function locals: we need to
1795 # overwrite NIA being overwritten (sigh)
1796 if self
.trap_nia
is not None:
1797 self
.namespace
['NIA'] = self
.trap_nia
1799 log("after func", self
.namespace
['CIA'], self
.namespace
['NIA'])
1801 # check if op was a LD/ST so that debugging can check the
1803 if int_op
in [MicrOp
.OP_STORE
.value
,
1805 self
.last_st_addr
= self
.mem
.last_st_addr
1806 if int_op
in [MicrOp
.OP_LOAD
.value
,
1808 self
.last_ld_addr
= self
.mem
.last_ld_addr
1809 log("op", int_op
, MicrOp
.OP_STORE
.value
, MicrOp
.OP_LOAD
.value
,
1810 self
.last_st_addr
, self
.last_ld_addr
)
1812 # detect if CA/CA32 already in outputs (sra*, basically)
1814 ca32
= outs
.get("CA32 ")
1816 log("carry already done?", ca
, ca32
, output_names
)
1817 carry_en
= yield self
.dec2
.e
.do
.output_carry
1819 yield from self
.handle_carry_(inputs
, results
[0], ca
, ca32
)
1821 # get outout named "overflow" and "CR0"
1822 overflow
= outs
.get('overflow')
1823 cr0
= outs
.get('CR0')
1825 if not self
.is_svp64_mode
: # yeah just no. not in parallel processing
1826 # detect if overflow was in return result
1827 ov_en
= yield self
.dec2
.e
.do
.oe
.oe
1828 ov_ok
= yield self
.dec2
.e
.do
.oe
.ok
1829 log("internal overflow", ins_name
, overflow
, "en?", ov_en
, ov_ok
)
1831 yield from self
.handle_overflow(inputs
, results
[0], overflow
)
1833 # only do SVP64 dest predicated Rc=1 if dest-pred is not enabled
1835 if not self
.is_svp64_mode
or not pred_dst_zero
:
1836 if hasattr(self
.dec2
.e
.do
, "rc"):
1837 rc_en
= yield self
.dec2
.e
.do
.rc
.rc
1838 # don't do Rc=1 for svstep it is handled explicitly.
1839 # XXX TODO: now that CR0 is supported, sort out svstep's pseudocode
1840 # to write directly to CR0 instead of in ISACaller. hooyahh.
1841 if rc_en
and ins_name
not in ['svstep']:
1842 yield from self
.do_rc_ov(ins_name
, results
[0], overflow
, cr0
)
1846 if self
.is_svp64_mode
:
1847 ffirst_hit
= (yield from self
.check_ffirst(rc_en
, srcstep
))
1849 # any modified return results?
1850 yield from self
.do_outregs_nia(asmop
, ins_name
, info
, outs
,
1851 carry_en
, rc_en
, ffirst_hit
)
1853 def check_ffirst(self
, rc_en
, srcstep
):
1854 """fail-first mode: checks a bit of Rc Vector, truncates VL
1856 rm_mode
= yield self
.dec2
.rm_dec
.mode
1857 ff_inv
= yield self
.dec2
.rm_dec
.inv
1858 cr_bit
= yield self
.dec2
.rm_dec
.cr_sel
1859 RC1
= yield self
.dec2
.rm_dec
.RC1
1860 vli
= yield self
.dec2
.rm_dec
.vli
# VL inclusive if truncated
1861 log(" ff rm_mode", rc_en
, rm_mode
, SVP64RMMode
.FFIRST
.value
)
1865 log(" cr_bit", cr_bit
)
1866 if not rc_en
or rm_mode
!= SVP64RMMode
.FFIRST
.value
:
1868 # get the CR vevtor, do BO-test
1869 regnum
, is_vec
= yield from get_pdecode_cr_out(self
.dec2
, "CR0")
1870 crtest
= self
.crl
[regnum
]
1871 ffirst_hit
= crtest
[cr_bit
] != ff_inv
1872 log("cr test", regnum
, int(crtest
), crtest
, cr_bit
, ff_inv
)
1873 log("cr test?", ffirst_hit
)
1876 # Fail-first activated, truncate VL
1877 vli
= SelectableInt(int(vli
), 7)
1878 self
.svstate
.vl
= srcstep
+ vli
1879 yield self
.dec2
.state
.svstate
.eq(self
.svstate
.value
)
1880 yield Settle() # let decoder update
1883 def do_rc_ov(self
, ins_name
, result
, overflow
, cr0
):
1884 if ins_name
.startswith("f"):
1885 rc_reg
= "CR1" # not calculated correctly yet (not FP compares)
1888 regnum
, is_vec
= yield from get_pdecode_cr_out(self
.dec2
, rc_reg
)
1889 # hang on... for `setvl` actually you want to test SVSTATE.VL
1890 is_setvl
= ins_name
in ('svstep', 'setvl')
1892 result
= SelectableInt(result
.vl
, 64)
1894 overflow
= None # do not override overflow except in setvl
1896 # if there was not an explicit CR0 in the pseudocode, do implicit Rc=1
1898 self
.handle_comparison(result
, regnum
, overflow
, no_so
=is_setvl
)
1900 # otherwise we just blat CR0 into the required regnum
1901 log("explicit rc0", cr0
)
1902 self
.crl
[regnum
].eq(cr0
)
1904 def do_outregs_nia(self
, asmop
, ins_name
, info
, outs
,
1905 carry_en
, rc_en
, ffirst_hit
):
1906 # write out any regs for this instruction
1907 for name
, output
in outs
.items():
1908 yield from self
.check_write(info
, name
, output
, carry_en
)
1911 self
.svp64_reset_loop()
1914 # check advancement of src/dst/sub-steps and if PC needs updating
1915 nia_update
= (yield from self
.check_step_increment(rc_en
,
1918 self
.update_pc_next()
1920 def check_replace_d(self
, info
, remap_active
):
1921 replace_d
= False # update / replace constant in pseudocode
1922 ldstmode
= yield self
.dec2
.rm_dec
.ldstmode
1923 vl
= self
.svstate
.vl
1924 subvl
= yield self
.dec2
.rm_dec
.rm_in
.subvl
1925 srcstep
, dststep
= self
.new_srcstep
, self
.new_dststep
1926 ssubstep
, dsubstep
= self
.new_ssubstep
, self
.new_dsubstep
1927 if info
.form
== 'DS':
1928 # DS-Form, multiply by 4 then knock 2 bits off after
1929 imm
= yield self
.dec2
.dec
.fields
.FormDS
.DS
[0:14] * 4
1931 imm
= yield self
.dec2
.dec
.fields
.FormD
.D
[0:16]
1932 imm
= exts(imm
, 16) # sign-extend to integer
1933 # get the right step. LD is from srcstep, ST is dststep
1934 op
= yield self
.dec2
.e
.do
.insn_type
1936 if op
== MicrOp
.OP_LOAD
.value
:
1938 offsmul
= yield self
.dec2
.in1_step
1939 log("D-field REMAP src", imm
, offsmul
)
1941 offsmul
= (srcstep
* (subvl
+1)) + ssubstep
1942 log("D-field src", imm
, offsmul
)
1943 elif op
== MicrOp
.OP_STORE
.value
:
1944 # XXX NOTE! no bit-reversed STORE! this should not ever be used
1945 offsmul
= (dststep
* (subvl
+1)) + dsubstep
1946 log("D-field dst", imm
, offsmul
)
1947 # Unit-Strided LD/ST adds offset*width to immediate
1948 if ldstmode
== SVP64LDSTmode
.UNITSTRIDE
.value
:
1949 ldst_len
= yield self
.dec2
.e
.do
.data_len
1950 imm
= SelectableInt(imm
+ offsmul
* ldst_len
, 32)
1952 # Element-strided multiplies the immediate by element step
1953 elif ldstmode
== SVP64LDSTmode
.ELSTRIDE
.value
:
1954 imm
= SelectableInt(imm
* offsmul
, 32)
1957 ldst_ra_vec
= yield self
.dec2
.rm_dec
.ldst_ra_vec
1958 ldst_imz_in
= yield self
.dec2
.rm_dec
.ldst_imz_in
1959 log("LDSTmode", SVP64LDSTmode(ldstmode
),
1960 offsmul
, imm
, ldst_ra_vec
, ldst_imz_in
)
1961 # new replacement D... errr.. DS
1963 if info
.form
== 'DS':
1964 # TODO: assert 2 LSBs are zero?
1965 log("DS-Form, TODO, assert 2 LSBs zero?", bin(imm
.value
))
1966 imm
.value
= imm
.value
>> 2
1967 self
.namespace
['DS'] = imm
1969 self
.namespace
['D'] = imm
1971 def get_input(self
, name
):
1972 # using PowerDecoder2, first, find the decoder index.
1973 # (mapping name RA RB RC RS to in1, in2, in3)
1974 regnum
, is_vec
= yield from get_pdecode_idx_in(self
.dec2
, name
)
1976 # doing this is not part of svp64, it's because output
1977 # registers, to be modified, need to be in the namespace.
1978 regnum
, is_vec
= yield from get_pdecode_idx_out(self
.dec2
, name
)
1980 regnum
, is_vec
= yield from get_pdecode_idx_out2(self
.dec2
, name
)
1982 # in case getting the register number is needed, _RA, _RB
1983 regname
= "_" + name
1984 self
.namespace
[regname
] = regnum
1985 if not self
.is_svp64_mode
or not self
.pred_src_zero
:
1986 log('reading reg %s %s' % (name
, str(regnum
)), is_vec
)
1988 reg_val
= SelectableInt(self
.fpr(regnum
))
1989 log("read reg %d: 0x%x" % (regnum
, reg_val
.value
))
1990 elif name
is not None:
1991 reg_val
= SelectableInt(self
.gpr(regnum
))
1992 log("read reg %d: 0x%x" % (regnum
, reg_val
.value
))
1994 log('zero input reg %s %s' % (name
, str(regnum
)), is_vec
)
1998 def remap_set_steps(self
, remaps
):
1999 """remap_set_steps sets up the in1/2/3 and out1/2 steps.
2000 they work in concert with PowerDecoder2 at the moment,
2001 there is no HDL implementation of REMAP. therefore this
2002 function, because ISACaller still uses PowerDecoder2,
2003 will *explicitly* write the dec2.XX_step values. this has
2006 # just some convenient debug info
2008 sname
= 'SVSHAPE%d' % i
2009 shape
= self
.spr
[sname
]
2010 log(sname
, bin(shape
.value
))
2011 log(" lims", shape
.lims
)
2012 log(" mode", shape
.mode
)
2013 log(" skip", shape
.skip
)
2015 # set up the list of steps to remap
2016 mi0
= self
.svstate
.mi0
2017 mi1
= self
.svstate
.mi1
2018 mi2
= self
.svstate
.mi2
2019 mo0
= self
.svstate
.mo0
2020 mo1
= self
.svstate
.mo1
2021 steps
= [(self
.dec2
.in1_step
, mi0
), # RA
2022 (self
.dec2
.in2_step
, mi1
), # RB
2023 (self
.dec2
.in3_step
, mi2
), # RC
2024 (self
.dec2
.o_step
, mo0
), # RT
2025 (self
.dec2
.o2_step
, mo1
), # EA
2027 remap_idxs
= self
.remap_idxs
2029 # now cross-index the required SHAPE for each of 3-in 2-out regs
2030 rnames
= ['RA', 'RB', 'RC', 'RT', 'EA']
2031 for i
, (dstep
, shape_idx
) in enumerate(steps
):
2032 (shape
, remap
) = remaps
[shape_idx
]
2033 remap_idx
= remap_idxs
[shape_idx
]
2034 # zero is "disabled"
2035 if shape
.value
== 0x0:
2037 # now set the actual requested step to the current index
2038 yield dstep
.eq(remap_idx
)
2040 # debug printout info
2041 rremaps
.append((shape
.mode
, i
, rnames
[i
], shape_idx
, remap_idx
))
2043 log("shape remap", x
)
2045 def check_write(self
, info
, name
, output
, carry_en
):
2046 if name
== 'overflow': # ignore, done already (above)
2048 if name
== 'CR0': # ignore, done already (above)
2050 if isinstance(output
, int):
2051 output
= SelectableInt(output
, 256)
2053 if name
in ['CA', 'CA32']:
2055 log("writing %s to XER" % name
, output
)
2056 log("write XER %s 0x%x" % (name
, output
.value
))
2057 self
.spr
['XER'][XER_bits
[name
]] = output
.value
2059 log("NOT writing %s to XER" % name
, output
)
2061 # write special SPRs
2062 if name
in info
.special_regs
:
2063 log('writing special %s' % name
, output
, special_sprs
)
2064 log("write reg %s 0x%x" % (name
, output
.value
))
2065 if name
in special_sprs
:
2066 self
.spr
[name
] = output
2068 self
.namespace
[name
].eq(output
)
2070 log('msr written', hex(self
.msr
.value
))
2072 # find out1/out2 PR/FPR
2073 regnum
, is_vec
= yield from get_pdecode_idx_out(self
.dec2
, name
)
2075 regnum
, is_vec
= yield from get_pdecode_idx_out2(self
.dec2
, name
)
2077 # temporary hack for not having 2nd output
2078 regnum
= yield getattr(self
.decoder
, name
)
2080 # convenient debug prefix
2085 # check zeroing due to predicate bit being zero
2086 if self
.is_svp64_mode
and self
.pred_dst_zero
:
2087 log('zeroing reg %d %s' % (regnum
, str(output
)), is_vec
)
2088 output
= SelectableInt(0, 256)
2089 log("write reg %s%d 0x%x" % (reg_prefix
, regnum
, output
.value
),
2090 kind
=LogKind
.InstrInOuts
)
2091 # zero-extend tov64 bit begore storing (should use EXT oh well)
2092 if output
.bits
> 64:
2093 output
= SelectableInt(output
.value
, 64)
2095 self
.fpr
[regnum
] = output
2097 self
.gpr
[regnum
] = output
2099 def check_step_increment(self
, rc_en
, asmop
, ins_name
):
2100 # check if it is the SVSTATE.src/dest step that needs incrementing
2101 # this is our Sub-Program-Counter loop from 0 to VL-1
2102 if not self
.allow_next_step_inc
:
2103 if self
.is_svp64_mode
:
2104 return (yield from self
.svstate_post_inc(ins_name
))
2106 # XXX only in non-SVP64 mode!
2107 # record state of whether the current operation was an svshape,
2109 # to be able to know if it should apply in the next instruction.
2110 # also (if going to use this instruction) should disable ability
2111 # to interrupt in between. sigh.
2112 self
.last_op_svshape
= asmop
in ['svremap', 'svindex',
2119 log("SVSTATE_NEXT: inc requested, mode",
2120 self
.svstate_next_mode
, self
.allow_next_step_inc
)
2121 yield from self
.svstate_pre_inc()
2122 pre
= yield from self
.update_new_svstate_steps()
2124 # reset at end of loop including exit Vertical Mode
2125 log("SVSTATE_NEXT: end of loop, reset")
2126 self
.svp64_reset_loop()
2127 self
.svstate
.vfirst
= 0
2131 self
.handle_comparison(SelectableInt(0, 64)) # CR0
2133 if self
.allow_next_step_inc
== 2:
2134 log("SVSTATE_NEXT: read")
2135 nia_update
= (yield from self
.svstate_post_inc(ins_name
))
2137 log("SVSTATE_NEXT: post-inc")
2138 # use actual (cached) src/dst-step here to check end
2139 remaps
= self
.get_remap_indices()
2140 remap_idxs
= self
.remap_idxs
2141 vl
= self
.svstate
.vl
2142 subvl
= yield self
.dec2
.rm_dec
.rm_in
.subvl
2143 if self
.allow_next_step_inc
!= 2:
2144 yield from self
.advance_svstate_steps()
2145 #self.namespace['SVSTATE'] = self.svstate.spr
2146 # set CR0 (if Rc=1) based on end
2147 endtest
= 1 if self
.at_loopend() else 0
2149 #results = [SelectableInt(endtest, 64)]
2150 # self.handle_comparison(results) # CR0
2152 # see if svstep was requested, if so, which SVSTATE
2154 if self
.svstate_next_mode
> 0:
2155 shape_idx
= self
.svstate_next_mode
.value
-1
2156 endings
= self
.remap_loopends
[shape_idx
]
2157 cr_field
= SelectableInt((~endings
) << 1 | endtest
, 4)
2158 log("svstep Rc=1, CR0", cr_field
, endtest
)
2159 self
.crl
[0].eq(cr_field
) # CR0
2161 # reset at end of loop including exit Vertical Mode
2162 log("SVSTATE_NEXT: after increments, reset")
2163 self
.svp64_reset_loop()
2164 self
.svstate
.vfirst
= 0
2167 def SVSTATE_NEXT(self
, mode
, submode
):
2168 """explicitly moves srcstep/dststep on to next element, for
2169 "Vertical-First" mode. this function is called from
2170 setvl pseudo-code, as a pseudo-op "svstep"
2172 WARNING: this function uses information that was created EARLIER
2173 due to it being in the middle of a yield, but this function is
2174 *NOT* called from yield (it's called from compiled pseudocode).
2176 self
.allow_next_step_inc
= submode
.value
+ 1
2177 log("SVSTATE_NEXT mode", mode
, submode
, self
.allow_next_step_inc
)
2178 self
.svstate_next_mode
= mode
2179 if self
.svstate_next_mode
> 0 and self
.svstate_next_mode
< 5:
2180 shape_idx
= self
.svstate_next_mode
.value
-1
2181 return SelectableInt(self
.remap_idxs
[shape_idx
], 7)
2182 if self
.svstate_next_mode
== 5:
2183 self
.svstate_next_mode
= 0
2184 return SelectableInt(self
.svstate
.srcstep
, 7)
2185 if self
.svstate_next_mode
== 6:
2186 self
.svstate_next_mode
= 0
2187 return SelectableInt(self
.svstate
.dststep
, 7)
2188 if self
.svstate_next_mode
== 7:
2189 self
.svstate_next_mode
= 0
2190 return SelectableInt(self
.svstate
.ssubstep
, 7)
2191 if self
.svstate_next_mode
== 8:
2192 self
.svstate_next_mode
= 0
2193 return SelectableInt(self
.svstate
.dsubstep
, 7)
2194 return SelectableInt(0, 7)
2196 def get_src_dststeps(self
):
2197 """gets srcstep, dststep, and ssubstep, dsubstep
2199 return (self
.new_srcstep
, self
.new_dststep
,
2200 self
.new_ssubstep
, self
.new_dsubstep
)
2202 def update_svstate_namespace(self
, overwrite_svstate
=True):
2203 if overwrite_svstate
:
2204 # note, do not get the bit-reversed srcstep here!
2205 srcstep
, dststep
= self
.new_srcstep
, self
.new_dststep
2206 ssubstep
, dsubstep
= self
.new_ssubstep
, self
.new_dsubstep
2208 # update SVSTATE with new srcstep
2209 self
.svstate
.srcstep
= srcstep
2210 self
.svstate
.dststep
= dststep
2211 self
.svstate
.ssubstep
= ssubstep
2212 self
.svstate
.dsubstep
= dsubstep
2213 self
.namespace
['SVSTATE'] = self
.svstate
2214 yield self
.dec2
.state
.svstate
.eq(self
.svstate
.value
)
2215 yield Settle() # let decoder update
2217 def update_new_svstate_steps(self
, overwrite_svstate
=True):
2218 yield from self
.update_svstate_namespace(overwrite_svstate
)
2219 srcstep
= self
.svstate
.srcstep
2220 dststep
= self
.svstate
.dststep
2221 ssubstep
= self
.svstate
.ssubstep
2222 dsubstep
= self
.svstate
.dsubstep
2223 pack
= self
.svstate
.pack
2224 unpack
= self
.svstate
.unpack
2225 vl
= self
.svstate
.vl
2226 subvl
= yield self
.dec2
.rm_dec
.rm_in
.subvl
2227 rm_mode
= yield self
.dec2
.rm_dec
.mode
2228 ff_inv
= yield self
.dec2
.rm_dec
.inv
2229 cr_bit
= yield self
.dec2
.rm_dec
.cr_sel
2230 log(" srcstep", srcstep
)
2231 log(" dststep", dststep
)
2233 log(" unpack", unpack
)
2234 log(" ssubstep", ssubstep
)
2235 log(" dsubstep", dsubstep
)
2237 log(" subvl", subvl
)
2238 log(" rm_mode", rm_mode
)
2240 log(" cr_bit", cr_bit
)
2242 # check if end reached (we let srcstep overrun, above)
2243 # nothing needs doing (TODO zeroing): just do next instruction
2246 return ((ssubstep
== subvl
and srcstep
== vl
) or
2247 (dsubstep
== subvl
and dststep
== vl
))
2249 def svstate_post_inc(self
, insn_name
, vf
=0):
2250 # check if SV "Vertical First" mode is enabled
2251 vfirst
= self
.svstate
.vfirst
2252 log(" SV Vertical First", vf
, vfirst
)
2253 if not vf
and vfirst
== 1:
2257 # check if it is the SVSTATE.src/dest step that needs incrementing
2258 # this is our Sub-Program-Counter loop from 0 to VL-1
2259 # XXX twin predication TODO
2260 vl
= self
.svstate
.vl
2261 subvl
= yield self
.dec2
.rm_dec
.rm_in
.subvl
2262 mvl
= self
.svstate
.maxvl
2263 srcstep
= self
.svstate
.srcstep
2264 dststep
= self
.svstate
.dststep
2265 ssubstep
= self
.svstate
.ssubstep
2266 dsubstep
= self
.svstate
.dsubstep
2267 pack
= self
.svstate
.pack
2268 unpack
= self
.svstate
.unpack
2269 rm_mode
= yield self
.dec2
.rm_dec
.mode
2270 reverse_gear
= yield self
.dec2
.rm_dec
.reverse_gear
2271 sv_ptype
= yield self
.dec2
.dec
.op
.SV_Ptype
2272 out_vec
= not (yield self
.dec2
.no_out_vec
)
2273 in_vec
= not (yield self
.dec2
.no_in_vec
)
2274 log(" svstate.vl", vl
)
2275 log(" svstate.mvl", mvl
)
2276 log(" rm.subvl", subvl
)
2277 log(" svstate.srcstep", srcstep
)
2278 log(" svstate.dststep", dststep
)
2279 log(" svstate.ssubstep", ssubstep
)
2280 log(" svstate.dsubstep", dsubstep
)
2281 log(" svstate.pack", pack
)
2282 log(" svstate.unpack", unpack
)
2283 log(" mode", rm_mode
)
2284 log(" reverse", reverse_gear
)
2285 log(" out_vec", out_vec
)
2286 log(" in_vec", in_vec
)
2287 log(" sv_ptype", sv_ptype
, sv_ptype
== SVPtype
.P2
.value
)
2288 # check if this was an sv.bc* and if so did it succeed
2289 if self
.is_svp64_mode
and insn_name
.startswith("sv.bc"):
2290 end_loop
= self
.namespace
['end_loop']
2291 log("branch %s end_loop" % insn_name
, end_loop
)
2293 self
.svp64_reset_loop()
2294 self
.update_pc_next()
2296 # check if srcstep needs incrementing by one, stop PC advancing
2297 # but for 2-pred both src/dest have to be checked.
2298 # XXX this might not be true! it may just be LD/ST
2299 if sv_ptype
== SVPtype
.P2
.value
:
2300 svp64_is_vector
= (out_vec
or in_vec
)
2302 svp64_is_vector
= out_vec
2303 # loops end at the first "hit" (source or dest)
2304 yield from self
.advance_svstate_steps()
2305 loopend
= self
.loopend
2306 log("loopend", svp64_is_vector
, loopend
)
2307 if not svp64_is_vector
or loopend
:
2308 # reset loop to zero and update NIA
2309 self
.svp64_reset_loop()
2314 # still looping, advance and update NIA
2315 self
.namespace
['SVSTATE'] = self
.svstate
2317 # not an SVP64 branch, so fix PC (NIA==CIA) for next loop
2318 # (by default, NIA is CIA+4 if v3.0B or CIA+8 if SVP64)
2319 # this way we keep repeating the same instruction (with new steps)
2320 self
.pc
.NIA
.value
= self
.pc
.CIA
.value
2321 self
.namespace
['NIA'] = self
.pc
.NIA
2322 log("end of sub-pc call", self
.namespace
['CIA'], self
.namespace
['NIA'])
2323 return False # DO NOT allow PC update whilst Sub-PC loop running
2325 def update_pc_next(self
):
2326 # UPDATE program counter
2327 self
.pc
.update(self
.namespace
, self
.is_svp64_mode
)
2328 #self.svstate.spr = self.namespace['SVSTATE']
2329 log("end of call", self
.namespace
['CIA'],
2330 self
.namespace
['NIA'],
2331 self
.namespace
['SVSTATE'])
2333 def svp64_reset_loop(self
):
2334 self
.svstate
.srcstep
= 0
2335 self
.svstate
.dststep
= 0
2336 self
.svstate
.ssubstep
= 0
2337 self
.svstate
.dsubstep
= 0
2338 self
.loopend
= False
2339 log(" svstate.srcstep loop end (PC to update)")
2340 self
.namespace
['SVSTATE'] = self
.svstate
2342 def update_nia(self
):
2343 self
.pc
.update_nia(self
.is_svp64_mode
)
2344 self
.namespace
['NIA'] = self
.pc
.NIA
2348 """Decorator factory.
2350 this decorator will "inject" variables into the function's namespace,
2351 from the *dictionary* in self.namespace. it therefore becomes possible
2352 to make it look like a whole stack of variables which would otherwise
2353 need "self." inserted in front of them (*and* for those variables to be
2354 added to the instance) "appear" in the function.
2356 "self.namespace['SI']" for example becomes accessible as just "SI" but
2357 *only* inside the function, when decorated.
2359 def variable_injector(func
):
2361 def decorator(*args
, **kwargs
):
2363 func_globals
= func
.__globals
__ # Python 2.6+
2364 except AttributeError:
2365 func_globals
= func
.func_globals
# Earlier versions.
2367 context
= args
[0].namespace
# variables to be injected
2368 saved_values
= func_globals
.copy() # Shallow copy of dict.
2369 log("globals before", context
.keys())
2370 func_globals
.update(context
)
2371 result
= func(*args
, **kwargs
)
2372 log("globals after", func_globals
['CIA'], func_globals
['NIA'])
2373 log("args[0]", args
[0].namespace
['CIA'],
2374 args
[0].namespace
['NIA'],
2375 args
[0].namespace
['SVSTATE'])
2376 if 'end_loop' in func_globals
:
2377 log("args[0] end_loop", func_globals
['end_loop'])
2378 args
[0].namespace
= func_globals
2379 #exec (func.__code__, func_globals)
2382 # func_globals = saved_values # Undo changes.
2388 return variable_injector