fe1edd9da87e30a95f2757dd4badf5ca3453ab81
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
101 fregs
= ['FRA', 'FRB', 'FRC', 'FRS', 'FRT']
104 def create_args(reglist
, extra
=None):
105 retval
= list(OrderedSet(reglist
))
106 retval
.sort(key
=lambda reg
: REG_SORT_ORDER
.get(reg
, 0))
107 if extra
is not None:
108 return [extra
] + retval
113 def __init__(self
, decoder
, isacaller
, svstate
, regfile
):
116 self
.isacaller
= isacaller
117 self
.svstate
= svstate
118 for i
in range(len(regfile
)):
119 self
[i
] = SelectableInt(regfile
[i
], 64)
121 def __call__(self
, ridx
):
122 if isinstance(ridx
, SelectableInt
):
126 def set_form(self
, form
):
129 def __setitem__(self
, rnum
, value
):
130 # rnum = rnum.value # only SelectableInt allowed
131 log("GPR setitem", rnum
, value
)
132 if isinstance(rnum
, SelectableInt
):
134 dict.__setitem
__(self
, rnum
, value
)
136 def getz(self
, rnum
):
137 # rnum = rnum.value # only SelectableInt allowed
138 log("GPR getzero?", rnum
)
140 return SelectableInt(0, 64)
143 def _get_regnum(self
, attr
):
144 getform
= self
.sd
.sigforms
[self
.form
]
145 rnum
= getattr(getform
, attr
)
148 def ___getitem__(self
, attr
):
149 """ XXX currently not used
151 rnum
= self
._get
_regnum
(attr
)
152 log("GPR getitem", attr
, rnum
)
153 return self
.regfile
[rnum
]
155 def dump(self
, printout
=True):
157 for i
in range(len(self
)):
158 res
.append(self
[i
].value
)
160 for i
in range(0, len(res
), 8):
163 s
.append("%08x" % res
[i
+j
])
165 print("reg", "%2d" % i
, s
)
170 def __init__(self
, dec2
, initial_sprs
={}):
173 for key
, v
in initial_sprs
.items():
174 if isinstance(key
, SelectableInt
):
176 key
= special_sprs
.get(key
, key
)
177 if isinstance(key
, int):
180 info
= spr_byname
[key
]
181 if not isinstance(v
, SelectableInt
):
182 v
= SelectableInt(v
, info
.length
)
185 def __getitem__(self
, key
):
187 log("dict", self
.items())
188 # if key in special_sprs get the special spr, otherwise return key
189 if isinstance(key
, SelectableInt
):
191 if isinstance(key
, int):
192 key
= spr_dict
[key
].SPR
193 key
= special_sprs
.get(key
, key
)
194 if key
== 'HSRR0': # HACK!
196 if key
== 'HSRR1': # HACK!
199 res
= dict.__getitem
__(self
, key
)
201 if isinstance(key
, int):
204 info
= spr_byname
[key
]
205 dict.__setitem
__(self
, key
, SelectableInt(0, info
.length
))
206 res
= dict.__getitem
__(self
, key
)
207 log("spr returning", key
, res
)
210 def __setitem__(self
, key
, value
):
211 if isinstance(key
, SelectableInt
):
213 if isinstance(key
, int):
214 key
= spr_dict
[key
].SPR
216 key
= special_sprs
.get(key
, key
)
217 if key
== 'HSRR0': # HACK!
218 self
.__setitem
__('SRR0', value
)
219 if key
== 'HSRR1': # HACK!
220 self
.__setitem
__('SRR1', value
)
221 log("setting spr", key
, value
)
222 dict.__setitem
__(self
, key
, value
)
224 def __call__(self
, ridx
):
227 def dump(self
, printout
=True):
229 keys
= list(self
.keys())
232 sprname
= spr_dict
.get(k
, None)
236 sprname
= sprname
.SPR
237 res
.append((sprname
, self
[k
].value
))
239 for sprname
, value
in res
:
240 print(" ", sprname
, hex(value
))
245 def __init__(self
, pc_init
=0):
246 self
.CIA
= SelectableInt(pc_init
, 64)
247 self
.NIA
= self
.CIA
+ SelectableInt(4, 64) # only true for v3.0B!
249 def update_nia(self
, is_svp64
):
250 increment
= 8 if is_svp64
else 4
251 self
.NIA
= self
.CIA
+ SelectableInt(increment
, 64)
253 def update(self
, namespace
, is_svp64
):
254 """updates the program counter (PC) by 4 if v3.0B mode or 8 if SVP64
256 self
.CIA
= namespace
['NIA'].narrow(64)
257 self
.update_nia(is_svp64
)
258 namespace
['CIA'] = self
.CIA
259 namespace
['NIA'] = self
.NIA
263 # See PowerISA Version 3.0 B Book 1
264 # Section 2.3.1 Condition Register pages 30 - 31
266 LT
= FL
= 0 # negative, less than, floating-point less than
267 GT
= FG
= 1 # positive, greater than, floating-point greater than
268 EQ
= FE
= 2 # equal, floating-point equal
269 SO
= FU
= 3 # summary overflow, floating-point unordered
271 def __init__(self
, init
=0):
272 # rev_cr = int('{:016b}'.format(initial_cr)[::-1], 2)
273 # self.cr = FieldSelectableInt(self._cr, list(range(32, 64)))
274 self
.cr
= SelectableInt(init
, 64) # underlying reg
275 # field-selectable versions of Condition Register TODO check bitranges?
278 bits
= tuple(range(i
*4+32, (i
+1)*4+32))
279 _cr
= FieldSelectableInt(self
.cr
, bits
)
282 # decode SVP64 predicate integer to reg number and invert
285 def get_predint(gpr
, mask
):
288 log("get_predint", mask
, SVP64PredInt
.ALWAYS
.value
)
289 if mask
== SVP64PredInt
.ALWAYS
.value
:
290 return 0xffff_ffff_ffff_ffff # 64 bits of 1
291 if mask
== SVP64PredInt
.R3_UNARY
.value
:
292 return 1 << (gpr(3).value
& 0b111111)
293 if mask
== SVP64PredInt
.R3
.value
:
295 if mask
== SVP64PredInt
.R3_N
.value
:
297 if mask
== SVP64PredInt
.R10
.value
:
299 if mask
== SVP64PredInt
.R10_N
.value
:
300 return ~
gpr(10).value
301 if mask
== SVP64PredInt
.R30
.value
:
303 if mask
== SVP64PredInt
.R30_N
.value
:
304 return ~
gpr(30).value
306 # decode SVP64 predicate CR to reg number and invert status
309 def _get_predcr(mask
):
310 if mask
== SVP64PredCR
.LT
.value
:
312 if mask
== SVP64PredCR
.GE
.value
:
314 if mask
== SVP64PredCR
.GT
.value
:
316 if mask
== SVP64PredCR
.LE
.value
:
318 if mask
== SVP64PredCR
.EQ
.value
:
320 if mask
== SVP64PredCR
.NE
.value
:
322 if mask
== SVP64PredCR
.SO
.value
:
324 if mask
== SVP64PredCR
.NS
.value
:
327 # read individual CR fields (0..VL-1), extract the required bit
328 # and construct the mask
331 def get_predcr(crl
, mask
, vl
):
332 idx
, noninv
= _get_predcr(mask
)
335 cr
= crl
[i
+SVP64CROffs
.CRPred
]
336 if cr
[idx
].value
== noninv
:
341 # TODO, really should just be using PowerDecoder2
342 def get_pdecode_idx_in(dec2
, name
):
344 in1_sel
= yield op
.in1_sel
345 in2_sel
= yield op
.in2_sel
346 in3_sel
= yield op
.in3_sel
347 # get the IN1/2/3 from the decoder (includes SVP64 remap and isvec)
348 in1
= yield dec2
.e
.read_reg1
.data
349 in2
= yield dec2
.e
.read_reg2
.data
350 in3
= yield dec2
.e
.read_reg3
.data
351 in1_isvec
= yield dec2
.in1_isvec
352 in2_isvec
= yield dec2
.in2_isvec
353 in3_isvec
= yield dec2
.in3_isvec
354 log("get_pdecode_idx_in in1", name
, in1_sel
, In1Sel
.RA
.value
,
356 log("get_pdecode_idx_in in2", name
, in2_sel
, In2Sel
.RB
.value
,
358 log("get_pdecode_idx_in in3", name
, in3_sel
, In3Sel
.RS
.value
,
360 log("get_pdecode_idx_in FRS in3", name
, in3_sel
, In3Sel
.FRS
.value
,
362 log("get_pdecode_idx_in FRB in2", name
, in2_sel
, In2Sel
.FRB
.value
,
364 log("get_pdecode_idx_in FRC in3", name
, in3_sel
, In3Sel
.FRC
.value
,
366 # identify which regnames map to in1/2/3
367 if name
== 'RA' or name
== 'RA_OR_ZERO':
368 if (in1_sel
== In1Sel
.RA
.value
or
369 (in1_sel
== In1Sel
.RA_OR_ZERO
.value
and in1
!= 0)):
370 return in1
, in1_isvec
371 if in1_sel
== In1Sel
.RA_OR_ZERO
.value
:
372 return in1
, in1_isvec
374 if in2_sel
== In2Sel
.RB
.value
:
375 return in2
, in2_isvec
376 if in3_sel
== In3Sel
.RB
.value
:
377 return in3
, in3_isvec
378 # XXX TODO, RC doesn't exist yet!
380 if in3_sel
== In3Sel
.RC
.value
:
381 return in3
, in3_isvec
382 assert False, "RC does not exist yet"
384 if in1_sel
== In1Sel
.RS
.value
:
385 return in1
, in1_isvec
386 if in2_sel
== In2Sel
.RS
.value
:
387 return in2
, in2_isvec
388 if in3_sel
== In3Sel
.RS
.value
:
389 return in3
, in3_isvec
391 if in1_sel
== In1Sel
.FRA
.value
:
392 return in1
, in1_isvec
394 if in2_sel
== In2Sel
.FRB
.value
:
395 return in2
, in2_isvec
397 if in3_sel
== In3Sel
.FRC
.value
:
398 return in3
, in3_isvec
400 if in1_sel
== In1Sel
.FRS
.value
:
401 return in1
, in1_isvec
402 if in3_sel
== In3Sel
.FRS
.value
:
403 return in3
, in3_isvec
407 # TODO, really should just be using PowerDecoder2
408 def get_pdecode_cr_in(dec2
, name
):
410 in_sel
= yield op
.cr_in
411 in_bitfield
= yield dec2
.dec_cr_in
.cr_bitfield
.data
412 sv_cr_in
= yield op
.sv_cr_in
413 spec
= yield dec2
.crin_svdec
.spec
414 sv_override
= yield dec2
.dec_cr_in
.sv_override
415 # get the IN1/2/3 from the decoder (includes SVP64 remap and isvec)
416 in1
= yield dec2
.e
.read_cr1
.data
417 cr_isvec
= yield dec2
.cr_in_isvec
418 log("get_pdecode_cr_in", in_sel
, CROutSel
.CR0
.value
, in1
, cr_isvec
)
419 log(" sv_cr_in", sv_cr_in
)
420 log(" cr_bf", in_bitfield
)
422 log(" override", sv_override
)
423 # identify which regnames map to in / o2
425 if in_sel
== CRInSel
.BI
.value
:
427 log("get_pdecode_cr_in not found", name
)
431 # TODO, really should just be using PowerDecoder2
432 def get_pdecode_cr_out(dec2
, name
):
434 out_sel
= yield op
.cr_out
435 out_bitfield
= yield dec2
.dec_cr_out
.cr_bitfield
.data
436 sv_cr_out
= yield op
.sv_cr_out
437 spec
= yield dec2
.crout_svdec
.spec
438 sv_override
= yield dec2
.dec_cr_out
.sv_override
439 # get the IN1/2/3 from the decoder (includes SVP64 remap and isvec)
440 out
= yield dec2
.e
.write_cr
.data
441 o_isvec
= yield dec2
.o_isvec
442 log("get_pdecode_cr_out", out_sel
, CROutSel
.CR0
.value
, out
, o_isvec
)
443 log(" sv_cr_out", sv_cr_out
)
444 log(" cr_bf", out_bitfield
)
446 log(" override", sv_override
)
447 # identify which regnames map to out / o2
449 if out_sel
== CROutSel
.CR0
.value
:
451 if name
== 'CR1': # these are not actually calculated correctly
452 if out_sel
== CROutSel
.CR1
.value
:
454 log("get_pdecode_cr_out not found", name
)
458 # TODO, really should just be using PowerDecoder2
459 def get_pdecode_idx_out(dec2
, name
):
461 out_sel
= yield op
.out_sel
462 # get the IN1/2/3 from the decoder (includes SVP64 remap and isvec)
463 out
= yield dec2
.e
.write_reg
.data
464 o_isvec
= yield dec2
.o_isvec
465 # identify which regnames map to out / o2
467 log("get_pdecode_idx_out", out_sel
, OutSel
.RA
.value
, out
, o_isvec
)
468 if out_sel
== OutSel
.RA
.value
:
471 log("get_pdecode_idx_out", out_sel
, OutSel
.RT
.value
,
472 OutSel
.RT_OR_ZERO
.value
, out
, o_isvec
,
474 if out_sel
== OutSel
.RT
.value
:
476 if out_sel
== OutSel
.RT_OR_ZERO
.value
and out
!= 0:
478 elif name
== 'RT_OR_ZERO':
479 log("get_pdecode_idx_out", out_sel
, OutSel
.RT
.value
,
480 OutSel
.RT_OR_ZERO
.value
, out
, o_isvec
,
482 if out_sel
== OutSel
.RT_OR_ZERO
.value
:
485 log("get_pdecode_idx_out", out_sel
, OutSel
.FRA
.value
, out
, o_isvec
)
486 if out_sel
== OutSel
.FRA
.value
:
489 log("get_pdecode_idx_out", out_sel
, OutSel
.FRT
.value
,
490 OutSel
.FRT
.value
, out
, o_isvec
)
491 if out_sel
== OutSel
.FRT
.value
:
493 log("get_pdecode_idx_out not found", name
, out_sel
, out
, o_isvec
)
497 # TODO, really should just be using PowerDecoder2
498 def get_pdecode_idx_out2(dec2
, name
):
499 # check first if register is activated for write
501 out_sel
= yield op
.out_sel
502 out
= yield dec2
.e
.write_ea
.data
503 o_isvec
= yield dec2
.o2_isvec
504 out_ok
= yield dec2
.e
.write_ea
.ok
505 log("get_pdecode_idx_out2", name
, out_sel
, out
, out_ok
, o_isvec
)
510 if hasattr(op
, "upd"):
511 # update mode LD/ST uses read-reg A also as an output
513 log("get_pdecode_idx_out2", upd
, LDSTMode
.update
.value
,
514 out_sel
, OutSel
.RA
.value
,
516 if upd
== LDSTMode
.update
.value
:
519 fft_en
= yield dec2
.implicit_rs
521 log("get_pdecode_idx_out2", out_sel
, OutSel
.RS
.value
,
525 fft_en
= yield dec2
.implicit_rs
527 log("get_pdecode_idx_out2", out_sel
, OutSel
.FRS
.value
,
534 """deals with svstate looping.
537 def __init__(self
, svstate
):
538 self
.svstate
= svstate
542 def new_iterators(self
):
543 self
.src_it
= self
.src_iterator()
544 self
.dst_it
= self
.dst_iterator()
549 self
.new_ssubstep
= 0
550 self
.new_dsubstep
= 0
551 self
.pred_dst_zero
= 0
552 self
.pred_src_zero
= 0
554 def src_iterator(self
):
555 """source-stepping iterator
557 pack
= self
.svstate
.pack
561 # pack advances subvl in *outer* loop
564 self
.svstate
.ssubstep
+= SelectableInt(1, 2)
565 self
.svstate
.srcstep
= SelectableInt(0, 7) # reset
567 self
.svstate
.srcstep
+= SelectableInt(1, 7) # advance srcstep
569 # these cannot be done as for-loops because SVSTATE may change
570 # (srcstep/substep may be modified, interrupted, subvl/vl change)
571 # but they *can* be done as while-loops as long as every SVSTATE
572 # "thing" is re-read every single time a yield gives indices
573 while True: # outer vl loop
574 while True: # inner subvl loop
576 srcmask
= self
.srcmask
577 srcstep
= self
.svstate
.srcstep
578 if self
.pred_sz
or ((1 << srcstep
) & srcmask
) != 0:
579 log(" advance src", srcstep
, self
.svstate
.vl
,
580 self
.svstate
.ssubstep
, subvl
)
581 # yield actual substep/srcstep
582 yield (self
.svstate
.ssubstep
, srcstep
)
583 if self
.svstate
.ssubstep
== subvl
: # end-point
584 self
.svstate
.ssubstep
= SelectableInt(0, 2) # reset
586 self
.svstate
.ssubstep
+= SelectableInt(1, 2)
588 if srcstep
== vl
-1: # end-point
589 self
.svstate
.srcstep
= SelectableInt(0, 7) # reset
590 break # trigger StopIteration
591 self
.svstate
.srcstep
+= SelectableInt(1, 7) # advance srcstep
593 def dst_iterator(self
):
594 """dest-stepping iterator
596 unpack
= self
.svstate
.unpack
600 # pack advances subvl in *outer* loop
603 # these cannot be done as for-loops because SVSTATE may change
604 # (dststep/substep may be modified, interrupted, subvl/vl change)
605 # but they *can* be done as while-loops as long as every SVSTATE
606 # "thing" is re-read every single time a yield gives indices
607 while True: # outer vl loop
608 while True: # inner subvl loop
610 dstmask
= self
.dstmask
611 dststep
= self
.svstate
.dststep
612 if self
.pred_dz
or ((1 << dststep
) & dstmask
) != 0:
613 log(" advance dst", dststep
, self
.svstate
.vl
,
614 self
.svstate
.dsubstep
, subvl
)
615 # yield actual substep/dststep
616 yield (self
.svstate
.dsubstep
, dststep
)
617 if self
.svstate
.dsubstep
== subvl
: # end-point
618 self
.svstate
.dsubstep
= SelectableInt(0, 2) # reset
620 self
.svstate
.dsubstep
+= SelectableInt(1, 2)
622 if dststep
== vl
-1: # end-point
623 self
.svstate
.dststep
= SelectableInt(0, 7) # reset
624 break # trigger StopIteration
625 self
.svstate
.dststep
+= SelectableInt(1, 7) # advance dststep
627 def src_iterate(self
):
628 """source-stepping iterator
632 pack
= self
.svstate
.pack
633 unpack
= self
.svstate
.unpack
634 ssubstep
= self
.svstate
.ssubstep
635 end_ssub
= ssubstep
== subvl
636 end_src
= self
.svstate
.srcstep
== vl
-1
637 log(" pack/unpack/subvl", pack
, unpack
, subvl
,
641 srcstep
= self
.svstate
.srcstep
642 srcmask
= self
.srcmask
644 # pack advances subvl in *outer* loop
646 assert srcstep
<= vl
-1
647 end_src
= srcstep
== vl
-1
652 self
.svstate
.ssubstep
+= SelectableInt(1, 2)
656 srcstep
+= 1 # advance srcstep
657 if not self
.srcstep_skip
:
659 if ((1 << srcstep
) & srcmask
) != 0:
662 log(" sskip", bin(srcmask
), bin(1 << srcstep
))
664 # advance subvl in *inner* loop
667 assert srcstep
<= vl
-1
668 end_src
= srcstep
== vl
-1
669 if end_src
: # end-point
674 if not self
.srcstep_skip
:
676 if ((1 << srcstep
) & srcmask
) != 0:
679 log(" sskip", bin(srcmask
), bin(1 << srcstep
))
680 self
.svstate
.ssubstep
= SelectableInt(0, 2) # reset
683 self
.svstate
.ssubstep
+= SelectableInt(1, 2)
685 self
.svstate
.srcstep
= SelectableInt(srcstep
, 7)
686 log(" advance src", self
.svstate
.srcstep
, self
.svstate
.ssubstep
,
689 def dst_iterate(self
):
690 """dest step iterator
694 pack
= self
.svstate
.pack
695 unpack
= self
.svstate
.unpack
696 dsubstep
= self
.svstate
.dsubstep
697 end_dsub
= dsubstep
== subvl
698 dststep
= self
.svstate
.dststep
699 end_dst
= dststep
== vl
-1
700 dstmask
= self
.dstmask
701 log(" pack/unpack/subvl", pack
, unpack
, subvl
,
706 # unpack advances subvl in *outer* loop
708 assert dststep
<= vl
-1
709 end_dst
= dststep
== vl
-1
714 self
.svstate
.dsubstep
+= SelectableInt(1, 2)
718 dststep
+= 1 # advance dststep
719 if not self
.dststep_skip
:
721 if ((1 << dststep
) & dstmask
) != 0:
724 log(" dskip", bin(dstmask
), bin(1 << dststep
))
726 # advance subvl in *inner* loop
729 assert dststep
<= vl
-1
730 end_dst
= dststep
== vl
-1
731 if end_dst
: # end-point
736 if not self
.dststep_skip
:
738 if ((1 << dststep
) & dstmask
) != 0:
741 log(" dskip", bin(dstmask
), bin(1 << dststep
))
742 self
.svstate
.dsubstep
= SelectableInt(0, 2) # reset
745 self
.svstate
.dsubstep
+= SelectableInt(1, 2)
747 self
.svstate
.dststep
= SelectableInt(dststep
, 7)
748 log(" advance dst", self
.svstate
.dststep
, self
.svstate
.dsubstep
,
751 def at_loopend(self
):
752 """tells if this is the last possible element. uses the cached values
753 for src/dst-step and sub-steps
757 srcstep
, dststep
= self
.new_srcstep
, self
.new_dststep
758 ssubstep
, dsubstep
= self
.new_ssubstep
, self
.new_dsubstep
759 end_ssub
= ssubstep
== subvl
760 end_dsub
= dsubstep
== subvl
761 if srcstep
== vl
-1 and end_ssub
:
763 if dststep
== vl
-1 and end_dsub
:
767 def advance_svstate_steps(self
):
768 """ advance sub/steps. note that Pack/Unpack *INVERTS* the order.
769 TODO when Pack/Unpack is set, substep becomes the *outer* loop
771 self
.subvl
= yield self
.dec2
.rm_dec
.rm_in
.subvl
772 if self
.loopend
: # huhn??
777 def read_src_mask(self
):
778 """read/update pred_sz and src mask
780 # get SVSTATE VL (oh and print out some debug stuff)
782 srcstep
= self
.svstate
.srcstep
783 ssubstep
= self
.svstate
.ssubstep
785 # get predicate mask (all 64 bits)
786 srcmask
= 0xffff_ffff_ffff_ffff
788 pmode
= yield self
.dec2
.rm_dec
.predmode
789 sv_ptype
= yield self
.dec2
.dec
.op
.SV_Ptype
790 srcpred
= yield self
.dec2
.rm_dec
.srcpred
791 dstpred
= yield self
.dec2
.rm_dec
.dstpred
792 pred_sz
= yield self
.dec2
.rm_dec
.pred_sz
793 if pmode
== SVP64PredMode
.INT
.value
:
794 srcmask
= dstmask
= get_predint(self
.gpr
, dstpred
)
795 if sv_ptype
== SVPtype
.P2
.value
:
796 srcmask
= get_predint(self
.gpr
, srcpred
)
797 elif pmode
== SVP64PredMode
.CR
.value
:
798 srcmask
= dstmask
= get_predcr(self
.crl
, dstpred
, vl
)
799 if sv_ptype
== SVPtype
.P2
.value
:
800 srcmask
= get_predcr(self
.crl
, srcpred
, vl
)
801 # work out if the ssubsteps are completed
802 ssubstart
= ssubstep
== 0
804 log(" ptype", sv_ptype
)
805 log(" srcpred", bin(srcpred
))
806 log(" srcmask", bin(srcmask
))
807 log(" pred_sz", bin(pred_sz
))
808 log(" ssubstart", ssubstart
)
810 # store all that above
811 self
.srcstep_skip
= False
812 self
.srcmask
= srcmask
813 self
.pred_sz
= pred_sz
814 self
.new_ssubstep
= ssubstep
815 log(" new ssubstep", ssubstep
)
816 # until the predicate mask has a "1" bit... or we run out of VL
817 # let srcstep==VL be the indicator to move to next instruction
819 self
.srcstep_skip
= True
821 def read_dst_mask(self
):
822 """same as read_src_mask - check and record everything needed
824 # get SVSTATE VL (oh and print out some debug stuff)
825 # yield Delay(1e-10) # make changes visible
827 dststep
= self
.svstate
.dststep
828 dsubstep
= self
.svstate
.dsubstep
830 # get predicate mask (all 64 bits)
831 dstmask
= 0xffff_ffff_ffff_ffff
833 pmode
= yield self
.dec2
.rm_dec
.predmode
834 reverse_gear
= yield self
.dec2
.rm_dec
.reverse_gear
835 sv_ptype
= yield self
.dec2
.dec
.op
.SV_Ptype
836 dstpred
= yield self
.dec2
.rm_dec
.dstpred
837 pred_dz
= yield self
.dec2
.rm_dec
.pred_dz
838 if pmode
== SVP64PredMode
.INT
.value
:
839 dstmask
= get_predint(self
.gpr
, dstpred
)
840 elif pmode
== SVP64PredMode
.CR
.value
:
841 dstmask
= get_predcr(self
.crl
, dstpred
, vl
)
842 # work out if the ssubsteps are completed
843 dsubstart
= dsubstep
== 0
845 log(" ptype", sv_ptype
)
846 log(" dstpred", bin(dstpred
))
847 log(" dstmask", bin(dstmask
))
848 log(" pred_dz", bin(pred_dz
))
849 log(" dsubstart", dsubstart
)
851 self
.dststep_skip
= False
852 self
.dstmask
= dstmask
853 self
.pred_dz
= pred_dz
854 self
.new_dsubstep
= dsubstep
855 log(" new dsubstep", dsubstep
)
857 self
.dststep_skip
= True
859 def svstate_pre_inc(self
):
860 """check if srcstep/dststep need to skip over masked-out predicate bits
861 note that this is not supposed to do anything to substep,
862 it is purely for skipping masked-out bits
865 self
.subvl
= yield self
.dec2
.rm_dec
.rm_in
.subvl
866 yield from self
.read_src_mask()
867 yield from self
.read_dst_mask()
874 srcstep
= self
.svstate
.srcstep
875 srcmask
= self
.srcmask
876 pred_src_zero
= self
.pred_sz
878 # srcstep-skipping opportunity identified
879 if self
.srcstep_skip
:
880 # cannot do this with sv.bc - XXX TODO
883 while (((1 << srcstep
) & srcmask
) == 0) and (srcstep
!= vl
):
884 log(" sskip", bin(1 << srcstep
))
887 # now work out if the relevant mask bits require zeroing
889 pred_src_zero
= ((1 << srcstep
) & srcmask
) == 0
891 # store new srcstep / dststep
892 self
.new_srcstep
= srcstep
893 self
.pred_src_zero
= pred_src_zero
894 log(" new srcstep", srcstep
)
897 # dststep-skipping opportunity identified
898 dststep
= self
.svstate
.dststep
899 dstmask
= self
.dstmask
900 pred_dst_zero
= self
.pred_dz
902 if self
.dststep_skip
:
903 # cannot do this with sv.bc - XXX TODO
906 while (((1 << dststep
) & dstmask
) == 0) and (dststep
!= vl
):
907 log(" dskip", bin(1 << dststep
))
910 # now work out if the relevant mask bits require zeroing
912 pred_dst_zero
= ((1 << dststep
) & dstmask
) == 0
914 # store new srcstep / dststep
915 self
.new_dststep
= dststep
916 self
.pred_dst_zero
= pred_dst_zero
917 log(" new dststep", dststep
)
920 class ISACaller(ISACallerHelper
, ISAFPHelpers
, StepLoop
):
921 # decoder2 - an instance of power_decoder2
922 # regfile - a list of initial values for the registers
923 # initial_{etc} - initial values for SPRs, Condition Register, Mem, MSR
924 # respect_pc - tracks the program counter. requires initial_insns
925 def __init__(self
, decoder2
, regfile
, initial_sprs
=None, initial_cr
=0,
926 initial_mem
=None, initial_msr
=0,
937 self
.bigendian
= bigendian
939 self
.is_svp64_mode
= False
940 self
.respect_pc
= respect_pc
941 if initial_sprs
is None:
943 if initial_mem
is None:
945 if fpregfile
is None:
947 if initial_insns
is None:
949 assert self
.respect_pc
== False, "instructions required to honor pc"
951 log("ISACaller insns", respect_pc
, initial_insns
, disassembly
)
952 log("ISACaller initial_msr", initial_msr
)
954 # "fake program counter" mode (for unit testing)
958 if isinstance(initial_mem
, tuple):
959 self
.fake_pc
= initial_mem
[0]
960 disasm_start
= self
.fake_pc
962 disasm_start
= initial_pc
964 # disassembly: we need this for now (not given from the decoder)
965 self
.disassembly
= {}
967 for i
, code
in enumerate(disassembly
):
968 self
.disassembly
[i
*4 + disasm_start
] = code
970 # set up registers, instruction memory, data memory, PC, SPRs, MSR, CR
971 self
.svp64rm
= SVP64RM()
972 if initial_svstate
is None:
974 if isinstance(initial_svstate
, int):
975 initial_svstate
= SVP64State(initial_svstate
)
976 # SVSTATE, MSR and PC
977 StepLoop
.__init
__(self
, initial_svstate
)
978 self
.msr
= SelectableInt(initial_msr
, 64) # underlying reg
980 # GPR FPR SPR registers
981 initial_sprs
= deepcopy(initial_sprs
) # so as not to get modified
982 self
.gpr
= GPR(decoder2
, self
, self
.svstate
, regfile
)
983 self
.fpr
= GPR(decoder2
, self
, self
.svstate
, fpregfile
)
984 self
.spr
= SPR(decoder2
, initial_sprs
) # initialise SPRs before MMU
986 # set up 4 dummy SVSHAPEs if they aren't already set up
988 sname
= 'SVSHAPE%d' % i
989 if sname
not in self
.spr
:
992 val
= self
.spr
[sname
].value
993 # make sure it's an SVSHAPE
994 self
.spr
[sname
] = SVSHAPE(val
, self
.gpr
)
995 self
.last_op_svshape
= False
998 self
.mem
= Mem(row_bytes
=8, initial_mem
=initial_mem
)
999 self
.mem
.log_fancy(kind
=LogKind
.InstrInOuts
)
1000 self
.imem
= Mem(row_bytes
=4, initial_mem
=initial_insns
)
1001 # MMU mode, redirect underlying Mem through RADIX
1003 self
.mem
= RADIX(self
.mem
, self
)
1005 self
.imem
= RADIX(self
.imem
, self
)
1007 # TODO, needed here:
1008 # FPR (same as GPR except for FP nums)
1009 # 4.2.2 p124 FPSCR (definitely "separate" - not in SPR)
1010 # note that mffs, mcrfs, mtfsf "manage" this FPSCR
1011 # 2.3.1 CR (and sub-fields CR0..CR6 - CR0 SO comes from XER.SO)
1012 # note that mfocrf, mfcr, mtcr, mtocrf, mcrxrx "manage" CRs
1014 # 2.3.2 LR (actually SPR #8) -- Done
1015 # 2.3.3 CTR (actually SPR #9) -- Done
1016 # 2.3.4 TAR (actually SPR #815)
1017 # 3.2.2 p45 XER (actually SPR #1) -- Done
1018 # 3.2.3 p46 p232 VRSAVE (actually SPR #256)
1020 # create CR then allow portions of it to be "selectable" (below)
1021 self
.cr_fields
= CRFields(initial_cr
)
1022 self
.cr
= self
.cr_fields
.cr
1024 # "undefined", just set to variable-bit-width int (use exts "max")
1025 # self.undefined = SelectableInt(0, 256) # TODO, not hard-code 256!
1028 self
.namespace
.update(self
.spr
)
1029 self
.namespace
.update({'GPR': self
.gpr
,
1033 'memassign': self
.memassign
,
1036 'SVSTATE': self
.svstate
,
1037 'SVSHAPE0': self
.spr
['SVSHAPE0'],
1038 'SVSHAPE1': self
.spr
['SVSHAPE1'],
1039 'SVSHAPE2': self
.spr
['SVSHAPE2'],
1040 'SVSHAPE3': self
.spr
['SVSHAPE3'],
1043 'undefined': undefined
,
1044 'mode_is_64bit': True,
1045 'SO': XER_bits
['SO'],
1046 'XLEN': 64 # elwidth overrides, later
1049 # update pc to requested start point
1050 self
.set_pc(initial_pc
)
1052 # field-selectable versions of Condition Register
1053 self
.crl
= self
.cr_fields
.crl
1055 self
.namespace
["CR%d" % i
] = self
.crl
[i
]
1057 self
.decoder
= decoder2
.dec
1058 self
.dec2
= decoder2
1060 super().__init
__(XLEN
=self
.namespace
["XLEN"])
1064 return self
.namespace
["XLEN"]
1066 def call_trap(self
, trap_addr
, trap_bit
):
1067 """calls TRAP and sets up NIA to the new execution location.
1068 next instruction will begin at trap_addr.
1070 self
.TRAP(trap_addr
, trap_bit
)
1071 self
.namespace
['NIA'] = self
.trap_nia
1072 self
.pc
.update(self
.namespace
, self
.is_svp64_mode
)
1074 def TRAP(self
, trap_addr
=0x700, trap_bit
=PIb
.TRAP
):
1075 """TRAP> saves PC, MSR (and TODO SVSTATE), and updates MSR
1077 TRAP function is callable from inside the pseudocode itself,
1078 hence the default arguments. when calling from inside ISACaller
1079 it is best to use call_trap()
1081 # https://bugs.libre-soc.org/show_bug.cgi?id=859
1082 kaivb
= self
.spr
['KAIVB'].value
1083 msr
= self
.namespace
['MSR'].value
1084 log("TRAP:", hex(trap_addr
), hex(msr
), "kaivb", hex(kaivb
))
1085 # store CIA(+4?) in SRR0, set NIA to 0x700
1086 # store MSR in SRR1, set MSR to um errr something, have to check spec
1087 # store SVSTATE (if enabled) in SVSRR0
1088 self
.spr
['SRR0'].value
= self
.pc
.CIA
.value
1089 self
.spr
['SRR1'].value
= msr
1090 if self
.is_svp64_mode
:
1091 self
.spr
['SVSRR0'] = self
.namespace
['SVSTATE'].value
1092 self
.trap_nia
= SelectableInt(trap_addr |
(kaivb
& ~
0x1fff), 64)
1093 self
.spr
['SRR1'][trap_bit
] = 1 # change *copy* of MSR in SRR1
1095 # set exception bits. TODO: this should, based on the address
1096 # in figure 66 p1065 V3.0B and the table figure 65 p1063 set these
1097 # bits appropriately. however it turns out that *for now* in all
1098 # cases (all trap_addrs) the exact same thing is needed.
1099 self
.msr
[MSRb
.IR
] = 0
1100 self
.msr
[MSRb
.DR
] = 0
1101 self
.msr
[MSRb
.FE0
] = 0
1102 self
.msr
[MSRb
.FE1
] = 0
1103 self
.msr
[MSRb
.EE
] = 0
1104 self
.msr
[MSRb
.RI
] = 0
1105 self
.msr
[MSRb
.SF
] = 1
1106 self
.msr
[MSRb
.TM
] = 0
1107 self
.msr
[MSRb
.VEC
] = 0
1108 self
.msr
[MSRb
.VSX
] = 0
1109 self
.msr
[MSRb
.PR
] = 0
1110 self
.msr
[MSRb
.FP
] = 0
1111 self
.msr
[MSRb
.PMM
] = 0
1112 self
.msr
[MSRb
.TEs
] = 0
1113 self
.msr
[MSRb
.TEe
] = 0
1114 self
.msr
[MSRb
.UND
] = 0
1115 self
.msr
[MSRb
.LE
] = 1
1117 def memassign(self
, ea
, sz
, val
):
1118 self
.mem
.memassign(ea
, sz
, val
)
1120 def prep_namespace(self
, insn_name
, formname
, op_fields
):
1121 # TODO: get field names from form in decoder*1* (not decoder2)
1122 # decoder2 is hand-created, and decoder1.sigform is auto-generated
1124 # then "yield" fields only from op_fields rather than hard-coded
1126 fields
= self
.decoder
.sigforms
[formname
]
1127 log("prep_namespace", formname
, op_fields
, insn_name
)
1128 for name
in op_fields
:
1129 # CR immediates. deal with separately. needs modifying
1131 if self
.is_svp64_mode
and name
in ['BI']: # TODO, more CRs
1132 # BI is a 5-bit, must reconstruct the value
1133 regnum
, is_vec
= yield from get_pdecode_cr_in(self
.dec2
, name
)
1134 sig
= getattr(fields
, name
)
1136 # low 2 LSBs (CR field selector) remain same, CR num extended
1137 assert regnum
<= 7, "sigh, TODO, 128 CR fields"
1138 val
= (val
& 0b11) |
(regnum
<< 2)
1140 sig
= getattr(fields
, name
)
1142 # these are all opcode fields involved in index-selection of CR,
1143 # and need to do "standard" arithmetic. CR[BA+32] for example
1144 # would, if using SelectableInt, only be 5-bit.
1145 if name
in ['BF', 'BFA', 'BC', 'BA', 'BB', 'BT', 'BI']:
1146 self
.namespace
[name
] = val
1148 self
.namespace
[name
] = SelectableInt(val
, sig
.width
)
1150 self
.namespace
['XER'] = self
.spr
['XER']
1151 self
.namespace
['CA'] = self
.spr
['XER'][XER_bits
['CA']].value
1152 self
.namespace
['CA32'] = self
.spr
['XER'][XER_bits
['CA32']].value
1154 # add some SVSTATE convenience variables
1155 vl
= self
.svstate
.vl
1156 srcstep
= self
.svstate
.srcstep
1157 self
.namespace
['VL'] = vl
1158 self
.namespace
['srcstep'] = srcstep
1160 # sv.bc* need some extra fields
1161 if self
.is_svp64_mode
and insn_name
.startswith("sv.bc"):
1162 # blegh grab bits manually
1163 mode
= yield self
.dec2
.rm_dec
.rm_in
.mode
1164 bc_vlset
= (mode
& SVP64MODE
.BC_VLSET
) != 0
1165 bc_vli
= (mode
& SVP64MODE
.BC_VLI
) != 0
1166 bc_snz
= (mode
& SVP64MODE
.BC_SNZ
) != 0
1167 bc_vsb
= yield self
.dec2
.rm_dec
.bc_vsb
1168 bc_lru
= yield self
.dec2
.rm_dec
.bc_lru
1169 bc_gate
= yield self
.dec2
.rm_dec
.bc_gate
1170 sz
= yield self
.dec2
.rm_dec
.pred_sz
1171 self
.namespace
['ALL'] = SelectableInt(bc_gate
, 1)
1172 self
.namespace
['VSb'] = SelectableInt(bc_vsb
, 1)
1173 self
.namespace
['LRu'] = SelectableInt(bc_lru
, 1)
1174 self
.namespace
['VLSET'] = SelectableInt(bc_vlset
, 1)
1175 self
.namespace
['VLI'] = SelectableInt(bc_vli
, 1)
1176 self
.namespace
['sz'] = SelectableInt(sz
, 1)
1177 self
.namespace
['SNZ'] = SelectableInt(bc_snz
, 1)
1179 def handle_carry_(self
, inputs
, outputs
, already_done
):
1180 inv_a
= yield self
.dec2
.e
.do
.invert_in
1182 inputs
[0] = ~inputs
[0]
1184 imm_ok
= yield self
.dec2
.e
.do
.imm_data
.ok
1186 imm
= yield self
.dec2
.e
.do
.imm_data
.data
1187 inputs
.append(SelectableInt(imm
, 64))
1188 assert len(outputs
) >= 1
1189 log("outputs", repr(outputs
))
1190 if isinstance(outputs
, list) or isinstance(outputs
, tuple):
1196 log("gt input", x
, output
)
1197 gt
= (gtu(x
, output
))
1200 cy
= 1 if any(gts
) else 0
1202 if not (1 & already_done
):
1203 self
.spr
['XER'][XER_bits
['CA']] = cy
1205 log("inputs", already_done
, inputs
)
1207 # ARGH... different for OP_ADD... *sigh*...
1208 op
= yield self
.dec2
.e
.do
.insn_type
1209 if op
== MicrOp
.OP_ADD
.value
:
1210 res32
= (output
.value
& (1 << 32)) != 0
1211 a32
= (inputs
[0].value
& (1 << 32)) != 0
1212 if len(inputs
) >= 2:
1213 b32
= (inputs
[1].value
& (1 << 32)) != 0
1216 cy32
= res32 ^ a32 ^ b32
1217 log("CA32 ADD", cy32
)
1221 log("input", x
, output
)
1222 log(" x[32:64]", x
, x
[32:64])
1223 log(" o[32:64]", output
, output
[32:64])
1224 gt
= (gtu(x
[32:64], output
[32:64])) == SelectableInt(1, 1)
1226 cy32
= 1 if any(gts
) else 0
1227 log("CA32", cy32
, gts
)
1228 if not (2 & already_done
):
1229 self
.spr
['XER'][XER_bits
['CA32']] = cy32
1231 def handle_overflow(self
, inputs
, outputs
, div_overflow
):
1232 if hasattr(self
.dec2
.e
.do
, "invert_in"):
1233 inv_a
= yield self
.dec2
.e
.do
.invert_in
1235 inputs
[0] = ~inputs
[0]
1237 imm_ok
= yield self
.dec2
.e
.do
.imm_data
.ok
1239 imm
= yield self
.dec2
.e
.do
.imm_data
.data
1240 inputs
.append(SelectableInt(imm
, 64))
1241 assert len(outputs
) >= 1
1242 log("handle_overflow", inputs
, outputs
, div_overflow
)
1243 if len(inputs
) < 2 and div_overflow
is None:
1246 # div overflow is different: it's returned by the pseudo-code
1247 # because it's more complex than can be done by analysing the output
1248 if div_overflow
is not None:
1249 ov
, ov32
= div_overflow
, div_overflow
1250 # arithmetic overflow can be done by analysing the input and output
1251 elif len(inputs
) >= 2:
1255 input_sgn
= [exts(x
.value
, x
.bits
) < 0 for x
in inputs
]
1256 output_sgn
= exts(output
.value
, output
.bits
) < 0
1257 ov
= 1 if input_sgn
[0] == input_sgn
[1] and \
1258 output_sgn
!= input_sgn
[0] else 0
1261 input32_sgn
= [exts(x
.value
, 32) < 0 for x
in inputs
]
1262 output32_sgn
= exts(output
.value
, 32) < 0
1263 ov32
= 1 if input32_sgn
[0] == input32_sgn
[1] and \
1264 output32_sgn
!= input32_sgn
[0] else 0
1266 # now update XER OV/OV32/SO
1267 so
= self
.spr
['XER'][XER_bits
['SO']]
1268 new_so
= so | ov
# sticky overflow ORs in old with new
1269 self
.spr
['XER'][XER_bits
['OV']] = ov
1270 self
.spr
['XER'][XER_bits
['OV32']] = ov32
1271 self
.spr
['XER'][XER_bits
['SO']] = new_so
1272 log(" set overflow", ov
, ov32
, so
, new_so
)
1274 def handle_comparison(self
, outputs
, cr_idx
=0, overflow
=None, no_so
=False):
1276 assert isinstance(out
, SelectableInt
), \
1277 "out zero not a SelectableInt %s" % repr(outputs
)
1278 log("handle_comparison", out
.bits
, hex(out
.value
))
1279 # TODO - XXX *processor* in 32-bit mode
1280 # https://bugs.libre-soc.org/show_bug.cgi?id=424
1282 # o32 = exts(out.value, 32)
1283 # print ("handle_comparison exts 32 bit", hex(o32))
1284 out
= exts(out
.value
, out
.bits
)
1285 log("handle_comparison exts", hex(out
))
1286 # create the three main CR flags, EQ GT LT
1287 zero
= SelectableInt(out
== 0, 1)
1288 positive
= SelectableInt(out
> 0, 1)
1289 negative
= SelectableInt(out
< 0, 1)
1290 # get (or not) XER.SO. for setvl this is important *not* to read SO
1292 SO
= SelectableInt(1, 0)
1294 SO
= self
.spr
['XER'][XER_bits
['SO']]
1295 log("handle_comparison SO overflow", SO
, overflow
)
1296 # alternative overflow checking (setvl mainly at the moment)
1297 if overflow
is not None and overflow
== 1:
1298 SO
= SelectableInt(1, 1)
1299 # create the four CR field values and set the required CR field
1300 cr_field
= selectconcat(negative
, positive
, zero
, SO
)
1301 log("handle_comparison cr_field", self
.cr
, cr_idx
, cr_field
)
1302 self
.crl
[cr_idx
].eq(cr_field
)
1304 def set_pc(self
, pc_val
):
1305 self
.namespace
['NIA'] = SelectableInt(pc_val
, 64)
1306 self
.pc
.update(self
.namespace
, self
.is_svp64_mode
)
1308 def get_next_insn(self
):
1309 """check instruction
1312 pc
= self
.pc
.CIA
.value
1315 ins
= self
.imem
.ld(pc
, 4, False, True, instr_fetch
=True)
1317 raise KeyError("no instruction at 0x%x" % pc
)
1320 def setup_one(self
):
1321 """set up one instruction
1323 pc
, insn
= self
.get_next_insn()
1324 yield from self
.setup_next_insn(pc
, insn
)
1326 def setup_next_insn(self
, pc
, ins
):
1327 """set up next instruction
1330 log("setup: 0x%x 0x%x %s" % (pc
, ins
& 0xffffffff, bin(ins
)))
1331 log("CIA NIA", self
.respect_pc
, self
.pc
.CIA
.value
, self
.pc
.NIA
.value
)
1333 yield self
.dec2
.sv_rm
.eq(0)
1334 yield self
.dec2
.dec
.raw_opcode_in
.eq(ins
& 0xffffffff)
1335 yield self
.dec2
.dec
.bigendian
.eq(self
.bigendian
)
1336 yield self
.dec2
.state
.msr
.eq(self
.msr
.value
)
1337 yield self
.dec2
.state
.pc
.eq(pc
)
1338 if self
.svstate
is not None:
1339 yield self
.dec2
.state
.svstate
.eq(self
.svstate
.value
)
1341 # SVP64. first, check if the opcode is EXT001, and SVP64 id bits set
1343 opcode
= yield self
.dec2
.dec
.opcode_in
1344 opcode
= SelectableInt(value
=opcode
, bits
=32)
1345 pfx
= SVP64Instruction
.Prefix(opcode
)
1346 log("prefix test: opcode:", pfx
.po
, bin(pfx
.po
), pfx
.id)
1347 self
.is_svp64_mode
= bool((pfx
.po
== 0b000001) and (pfx
.id == 0b11))
1348 self
.pc
.update_nia(self
.is_svp64_mode
)
1350 yield self
.dec2
.is_svp64_mode
.eq(self
.is_svp64_mode
)
1351 self
.namespace
['NIA'] = self
.pc
.NIA
1352 self
.namespace
['SVSTATE'] = self
.svstate
1353 if not self
.is_svp64_mode
:
1356 # in SVP64 mode. decode/print out svp64 prefix, get v3.0B instruction
1357 log("svp64.rm", bin(pfx
.rm
))
1358 log(" svstate.vl", self
.svstate
.vl
)
1359 log(" svstate.mvl", self
.svstate
.maxvl
)
1360 ins
= self
.imem
.ld(pc
+4, 4, False, True, instr_fetch
=True)
1361 log(" svsetup: 0x%x 0x%x %s" % (pc
+4, ins
& 0xffffffff, bin(ins
)))
1362 yield self
.dec2
.dec
.raw_opcode_in
.eq(ins
& 0xffffffff) # v3.0B suffix
1363 yield self
.dec2
.sv_rm
.eq(int(pfx
.rm
)) # svp64 prefix
1366 def execute_one(self
):
1367 """execute one instruction
1369 # get the disassembly code for this instruction
1370 if self
.is_svp64_mode
:
1371 if not self
.disassembly
:
1372 code
= yield from self
.get_assembly_name()
1374 code
= self
.disassembly
[self
._pc
+4]
1375 log(" svp64 sim-execute", hex(self
._pc
), code
)
1377 if not self
.disassembly
:
1378 code
= yield from self
.get_assembly_name()
1380 code
= self
.disassembly
[self
._pc
]
1381 log("sim-execute", hex(self
._pc
), code
)
1382 opname
= code
.split(' ')[0]
1384 yield from self
.call(opname
) # execute the instruction
1385 except MemException
as e
: # check for memory errors
1386 if e
.args
[0] == 'unaligned': # alignment error
1387 # run a Trap but set DAR first
1388 print("memory unaligned exception, DAR", e
.dar
)
1389 self
.spr
['DAR'] = SelectableInt(e
.dar
, 64)
1390 self
.call_trap(0x600, PIb
.PRIV
) # 0x600, privileged
1392 elif e
.args
[0] == 'invalid': # invalid
1393 # run a Trap but set DAR first
1394 log("RADIX MMU memory invalid error, mode %s" % e
.mode
)
1395 if e
.mode
== 'EXECUTE':
1396 # XXX TODO: must set a few bits in SRR1,
1397 # see microwatt loadstore1.vhdl
1398 # if m_in.segerr = '0' then
1399 # v.srr1(47 - 33) := m_in.invalid;
1400 # v.srr1(47 - 35) := m_in.perm_error; -- noexec fault
1401 # v.srr1(47 - 44) := m_in.badtree;
1402 # v.srr1(47 - 45) := m_in.rc_error;
1403 # v.intr_vec := 16#400#;
1405 # v.intr_vec := 16#480#;
1406 self
.call_trap(0x400, PIb
.PRIV
) # 0x400, privileged
1408 self
.call_trap(0x300, PIb
.PRIV
) # 0x300, privileged
1410 # not supported yet:
1411 raise e
# ... re-raise
1413 # don't use this except in special circumstances
1414 if not self
.respect_pc
:
1417 log("execute one, CIA NIA", hex(self
.pc
.CIA
.value
),
1418 hex(self
.pc
.NIA
.value
))
1420 def get_assembly_name(self
):
1421 # TODO, asmregs is from the spec, e.g. add RT,RA,RB
1422 # see http://bugs.libre-riscv.org/show_bug.cgi?id=282
1423 dec_insn
= yield self
.dec2
.e
.do
.insn
1424 insn_1_11
= yield self
.dec2
.e
.do
.insn
[1:11]
1425 asmcode
= yield self
.dec2
.dec
.op
.asmcode
1426 int_op
= yield self
.dec2
.dec
.op
.internal_op
1427 log("get assembly name asmcode", asmcode
, int_op
,
1428 hex(dec_insn
), bin(insn_1_11
))
1429 asmop
= insns
.get(asmcode
, None)
1431 # sigh reconstruct the assembly instruction name
1432 if hasattr(self
.dec2
.e
.do
, "oe"):
1433 ov_en
= yield self
.dec2
.e
.do
.oe
.oe
1434 ov_ok
= yield self
.dec2
.e
.do
.oe
.ok
1438 if hasattr(self
.dec2
.e
.do
, "rc"):
1439 rc_en
= yield self
.dec2
.e
.do
.rc
.rc
1440 rc_ok
= yield self
.dec2
.e
.do
.rc
.ok
1444 # annoying: ignore rc_ok if RC1 is set (for creating *assembly name*)
1445 RC1
= yield self
.dec2
.rm_dec
.RC1
1449 # grrrr have to special-case MUL op (see DecodeOE)
1450 log("ov %d en %d rc %d en %d op %d" %
1451 (ov_ok
, ov_en
, rc_ok
, rc_en
, int_op
))
1452 if int_op
in [MicrOp
.OP_MUL_H64
.value
, MicrOp
.OP_MUL_H32
.value
]:
1457 if not asmop
.endswith("."): # don't add "." to "andis."
1460 if hasattr(self
.dec2
.e
.do
, "lk"):
1461 lk
= yield self
.dec2
.e
.do
.lk
1464 log("int_op", int_op
)
1465 if int_op
in [MicrOp
.OP_B
.value
, MicrOp
.OP_BC
.value
]:
1466 AA
= yield self
.dec2
.dec
.fields
.FormI
.AA
[0:-1]
1470 spr_msb
= yield from self
.get_spr_msb()
1471 if int_op
== MicrOp
.OP_MFCR
.value
:
1476 # XXX TODO: for whatever weird reason this doesn't work
1477 # https://bugs.libre-soc.org/show_bug.cgi?id=390
1478 if int_op
== MicrOp
.OP_MTCRF
.value
:
1485 def reset_remaps(self
):
1486 self
.remap_loopends
= [0] * 4
1487 self
.remap_idxs
= [0, 1, 2, 3]
1489 def get_remap_indices(self
):
1490 """WARNING, this function stores remap_idxs and remap_loopends
1491 in the class for later use. this to avoid problems with yield
1493 # go through all iterators in lock-step, advance to next remap_idx
1494 srcstep
, dststep
, ssubstep
, dsubstep
= self
.get_src_dststeps()
1495 # get four SVSHAPEs. here we are hard-coding
1497 SVSHAPE0
= self
.spr
['SVSHAPE0']
1498 SVSHAPE1
= self
.spr
['SVSHAPE1']
1499 SVSHAPE2
= self
.spr
['SVSHAPE2']
1500 SVSHAPE3
= self
.spr
['SVSHAPE3']
1501 # set up the iterators
1502 remaps
= [(SVSHAPE0
, SVSHAPE0
.get_iterator()),
1503 (SVSHAPE1
, SVSHAPE1
.get_iterator()),
1504 (SVSHAPE2
, SVSHAPE2
.get_iterator()),
1505 (SVSHAPE3
, SVSHAPE3
.get_iterator()),
1509 for i
, (shape
, remap
) in enumerate(remaps
):
1510 # zero is "disabled"
1511 if shape
.value
== 0x0:
1512 self
.remap_idxs
[i
] = 0
1513 # pick src or dststep depending on reg num (0-2=in, 3-4=out)
1514 step
= dststep
if (i
in [3, 4]) else srcstep
1515 # this is terrible. O(N^2) looking for the match. but hey.
1516 for idx
, (remap_idx
, loopends
) in enumerate(remap
):
1519 self
.remap_idxs
[i
] = remap_idx
1520 self
.remap_loopends
[i
] = loopends
1521 dbg
.append((i
, step
, remap_idx
, loopends
))
1522 for (i
, step
, remap_idx
, loopends
) in dbg
:
1523 log("SVSHAPE %d idx, end" % i
, step
, remap_idx
, bin(loopends
))
1526 def get_spr_msb(self
):
1527 dec_insn
= yield self
.dec2
.e
.do
.insn
1528 return dec_insn
& (1 << 20) != 0 # sigh - XFF.spr[-1]?
1530 def call(self
, name
):
1531 """call(opcode) - the primary execution point for instructions
1533 self
.last_st_addr
= None # reset the last known store address
1534 self
.last_ld_addr
= None # etc.
1536 ins_name
= name
.strip() # remove spaces if not already done so
1538 log("halted - not executing", ins_name
)
1541 # TODO, asmregs is from the spec, e.g. add RT,RA,RB
1542 # see http://bugs.libre-riscv.org/show_bug.cgi?id=282
1543 asmop
= yield from self
.get_assembly_name()
1544 log("call", ins_name
, asmop
)
1546 # sv.setvl is *not* a loop-function. sigh
1547 log("is_svp64_mode", self
.is_svp64_mode
, asmop
)
1550 int_op
= yield self
.dec2
.dec
.op
.internal_op
1551 spr_msb
= yield from self
.get_spr_msb()
1553 instr_is_privileged
= False
1554 if int_op
in [MicrOp
.OP_ATTN
.value
,
1555 MicrOp
.OP_MFMSR
.value
,
1556 MicrOp
.OP_MTMSR
.value
,
1557 MicrOp
.OP_MTMSRD
.value
,
1559 MicrOp
.OP_RFID
.value
]:
1560 instr_is_privileged
= True
1561 if int_op
in [MicrOp
.OP_MFSPR
.value
,
1562 MicrOp
.OP_MTSPR
.value
] and spr_msb
:
1563 instr_is_privileged
= True
1565 log("is priv", instr_is_privileged
, hex(self
.msr
.value
),
1567 # check MSR priv bit and whether op is privileged: if so, throw trap
1568 if instr_is_privileged
and self
.msr
[MSRb
.PR
] == 1:
1569 self
.call_trap(0x700, PIb
.PRIV
)
1572 # check halted condition
1573 if ins_name
== 'attn':
1577 # check illegal instruction
1579 if ins_name
not in ['mtcrf', 'mtocrf']:
1580 illegal
= ins_name
!= asmop
1582 # list of instructions not being supported by binutils (.long)
1583 dotstrp
= asmop
[:-1] if asmop
[-1] == '.' else asmop
1584 if dotstrp
in [*FPTRANS_INSNS
,
1585 'ffmadds', 'fdmadds', 'ffadds',
1586 'mins', 'maxs', 'minu', 'maxu',
1587 'setvl', 'svindex', 'svremap', 'svstep',
1588 'svshape', 'svshape2',
1589 'grev', 'ternlogi', 'bmask', 'cprop',
1590 'absdu', 'absds', 'absdacs', 'absdacu', 'avgadd',
1591 'fmvis', 'fishmv', 'pcdec', "madded", "divrem2du",
1597 # branch-conditional redirects to sv.bc
1598 if asmop
.startswith('bc') and self
.is_svp64_mode
:
1599 ins_name
= 'sv.%s' % ins_name
1601 log(" post-processed name", dotstrp
, ins_name
, asmop
)
1603 # illegal instructions call TRAP at 0x700
1605 print("illegal", ins_name
, asmop
)
1606 self
.call_trap(0x700, PIb
.ILLEG
)
1607 print("name %s != %s - calling ILLEGAL trap, PC: %x" %
1608 (ins_name
, asmop
, self
.pc
.CIA
.value
))
1611 # this is for setvl "Vertical" mode: if set true,
1612 # srcstep/dststep is explicitly advanced. mode says which SVSTATE to
1613 # test for Rc=1 end condition. 3 bits of all 3 loops are put into CR0
1614 self
.allow_next_step_inc
= False
1615 self
.svstate_next_mode
= 0
1617 # nop has to be supported, we could let the actual op calculate
1618 # but PowerDecoder has a pattern for nop
1619 if ins_name
== 'nop':
1620 self
.update_pc_next()
1623 # look up instruction in ISA.instrs, prepare namespace
1624 if ins_name
== 'pcdec': # grrrr yes there are others ("stbcx." etc.)
1625 info
= self
.instrs
[ins_name
+"."]
1627 info
= self
.instrs
[ins_name
]
1628 yield from self
.prep_namespace(ins_name
, info
.form
, info
.op_fields
)
1630 # preserve order of register names
1631 input_names
= create_args(list(info
.read_regs
) +
1632 list(info
.uninit_regs
))
1633 log("input names", input_names
)
1635 # get SVP64 entry for the current instruction
1636 sv_rm
= self
.svp64rm
.instrs
.get(ins_name
)
1637 if sv_rm
is not None:
1638 dest_cr
, src_cr
, src_byname
, dest_byname
= decode_extra(sv_rm
)
1640 dest_cr
, src_cr
, src_byname
, dest_byname
= False, False, {}, {}
1641 log("sv rm", sv_rm
, dest_cr
, src_cr
, src_byname
, dest_byname
)
1643 # see if srcstep/dststep need skipping over masked-out predicate bits
1645 if (self
.is_svp64_mode
or ins_name
in ['setvl', 'svremap', 'svstate']):
1646 yield from self
.svstate_pre_inc()
1647 if self
.is_svp64_mode
:
1648 pre
= yield from self
.update_new_svstate_steps()
1650 self
.svp64_reset_loop()
1652 self
.update_pc_next()
1654 srcstep
, dststep
, ssubstep
, dsubstep
= self
.get_src_dststeps()
1655 pred_dst_zero
= self
.pred_dst_zero
1656 pred_src_zero
= self
.pred_src_zero
1657 vl
= self
.svstate
.vl
1658 subvl
= yield self
.dec2
.rm_dec
.rm_in
.subvl
1660 # VL=0 in SVP64 mode means "do nothing: skip instruction"
1661 if self
.is_svp64_mode
and vl
== 0:
1662 self
.pc
.update(self
.namespace
, self
.is_svp64_mode
)
1663 log("SVP64: VL=0, end of call", self
.namespace
['CIA'],
1664 self
.namespace
['NIA'], kind
=LogKind
.InstrInOuts
)
1667 # for when SVREMAP is active, using pre-arranged schedule.
1668 # note: modifying PowerDecoder2 needs to "settle"
1669 remap_en
= self
.svstate
.SVme
1670 persist
= self
.svstate
.RMpst
1671 active
= (persist
or self
.last_op_svshape
) and remap_en
!= 0
1672 if self
.is_svp64_mode
:
1673 yield self
.dec2
.remap_active
.eq(remap_en
if active
else 0)
1675 if persist
or self
.last_op_svshape
:
1676 remaps
= self
.get_remap_indices()
1677 if self
.is_svp64_mode
and (persist
or self
.last_op_svshape
):
1678 yield from self
.remap_set_steps(remaps
)
1679 # after that, settle down (combinatorial) to let Vector reg numbers
1680 # work themselves out
1682 if self
.is_svp64_mode
:
1683 remap_active
= yield self
.dec2
.remap_active
1685 remap_active
= False
1686 log("remap active", bin(remap_active
))
1688 # main input registers (RT, RA ...)
1690 for name
in input_names
:
1692 regval
= (yield from self
.get_input(name
))
1693 log("regval", regval
)
1694 inputs
.append(regval
)
1696 # arrrrgh, awful hack, to get _RT into namespace
1697 if ins_name
in ['setvl', 'svstep']:
1699 RT
= yield self
.dec2
.dec
.RT
1700 self
.namespace
[regname
] = SelectableInt(RT
, 5)
1702 self
.namespace
["RT"] = SelectableInt(0, 5)
1703 regnum
, is_vec
= yield from get_pdecode_idx_out(self
.dec2
, "RT")
1704 log('hack input reg %s %s' % (name
, str(regnum
)), is_vec
)
1706 # in SVP64 mode for LD/ST work out immediate
1707 # XXX TODO: replace_ds for DS-Form rather than D-Form.
1708 # use info.form to detect
1709 if self
.is_svp64_mode
:
1710 yield from self
.check_replace_d(info
, remap_active
)
1712 # "special" registers
1713 for special
in info
.special_regs
:
1714 if special
in special_sprs
:
1715 inputs
.append(self
.spr
[special
])
1717 inputs
.append(self
.namespace
[special
])
1719 # clear trap (trap) NIA
1720 self
.trap_nia
= None
1722 # check if this was an sv.bc* and create an indicator that
1723 # this is the last check to be made as a loop. combined with
1724 # the ALL/ANY mode we can early-exit
1725 if self
.is_svp64_mode
and ins_name
.startswith("sv.bc"):
1726 no_in_vec
= yield self
.dec2
.no_in_vec
# BI is scalar
1727 end_loop
= no_in_vec
or srcstep
== vl
-1 or dststep
== vl
-1
1728 self
.namespace
['end_loop'] = SelectableInt(end_loop
, 1)
1730 # execute actual instruction here (finally)
1731 log("inputs", inputs
)
1732 results
= info
.func(self
, *inputs
)
1733 log("results", results
)
1735 # "inject" decorator takes namespace from function locals: we need to
1736 # overwrite NIA being overwritten (sigh)
1737 if self
.trap_nia
is not None:
1738 self
.namespace
['NIA'] = self
.trap_nia
1740 log("after func", self
.namespace
['CIA'], self
.namespace
['NIA'])
1742 # check if op was a LD/ST so that debugging can check the
1744 if int_op
in [MicrOp
.OP_STORE
.value
,
1746 self
.last_st_addr
= self
.mem
.last_st_addr
1747 if int_op
in [MicrOp
.OP_LOAD
.value
,
1749 self
.last_ld_addr
= self
.mem
.last_ld_addr
1750 log("op", int_op
, MicrOp
.OP_STORE
.value
, MicrOp
.OP_LOAD
.value
,
1751 self
.last_st_addr
, self
.last_ld_addr
)
1753 # detect if CA/CA32 already in outputs (sra*, basically)
1757 output_names
= create_args(info
.write_regs
)
1758 for name
in output_names
:
1764 log("carry already done?", bin(already_done
), output_names
)
1765 carry_en
= yield self
.dec2
.e
.do
.output_carry
1767 yield from self
.handle_carry_(inputs
, results
, already_done
)
1769 # check if one of the regs was named "overflow"
1772 for name
, output
in zip(output_names
, results
):
1773 if name
== 'overflow':
1776 # and one called CR0
1779 for name
, output
in zip(output_names
, results
):
1783 if not self
.is_svp64_mode
: # yeah just no. not in parallel processing
1784 # detect if overflow was in return result
1785 ov_en
= yield self
.dec2
.e
.do
.oe
.oe
1786 ov_ok
= yield self
.dec2
.e
.do
.oe
.ok
1787 log("internal overflow", ins_name
, overflow
, "en?", ov_en
, ov_ok
)
1789 yield from self
.handle_overflow(inputs
, results
, overflow
)
1791 # only do SVP64 dest predicated Rc=1 if dest-pred is not enabled
1793 if not self
.is_svp64_mode
or not pred_dst_zero
:
1794 if hasattr(self
.dec2
.e
.do
, "rc"):
1795 rc_en
= yield self
.dec2
.e
.do
.rc
.rc
1796 # don't do Rc=1 for svstep it is handled explicitly.
1797 # XXX TODO: now that CR0 is supported, sort out svstep's pseudocode
1798 # to write directly to CR0 instead of in ISACaller. hooyahh.
1799 if rc_en
and ins_name
not in ['svstep']:
1800 yield from self
.do_rc_ov(ins_name
, results
, overflow
, cr0
)
1804 if self
.is_svp64_mode
:
1805 ffirst_hit
= (yield from self
.check_ffirst(rc_en
, srcstep
))
1807 # any modified return results?
1808 yield from self
.do_outregs_nia(asmop
, ins_name
, info
,
1809 output_names
, results
,
1810 carry_en
, rc_en
, ffirst_hit
)
1812 def check_ffirst(self
, rc_en
, srcstep
):
1813 rm_mode
= yield self
.dec2
.rm_dec
.mode
1814 ff_inv
= yield self
.dec2
.rm_dec
.inv
1815 cr_bit
= yield self
.dec2
.rm_dec
.cr_sel
1816 RC1
= yield self
.dec2
.rm_dec
.RC1
1817 vli
= yield self
.dec2
.rm_dec
.vli
# VL inclusive if truncated
1818 log(" ff rm_mode", rc_en
, rm_mode
, SVP64RMMode
.FFIRST
.value
)
1822 log(" cr_bit", cr_bit
)
1823 if not rc_en
or rm_mode
!= SVP64RMMode
.FFIRST
.value
:
1825 regnum
, is_vec
= yield from get_pdecode_cr_out(self
.dec2
, "CR0")
1826 crtest
= self
.crl
[regnum
]
1827 ffirst_hit
= crtest
[cr_bit
] != ff_inv
1828 log("cr test", regnum
, int(crtest
), crtest
, cr_bit
, ff_inv
)
1829 log("cr test?", ffirst_hit
)
1832 vli
= SelectableInt(int(vli
), 7)
1833 self
.svstate
.vl
= srcstep
+ vli
1834 yield self
.dec2
.state
.svstate
.eq(self
.svstate
.value
)
1835 yield Settle() # let decoder update
1838 def do_rc_ov(self
, ins_name
, results
, overflow
, cr0
):
1839 if ins_name
.startswith("f"):
1840 rc_reg
= "CR1" # not calculated correctly yet (not FP compares)
1843 regnum
, is_vec
= yield from get_pdecode_cr_out(self
.dec2
, rc_reg
)
1845 # hang on... for `setvl` actually you want to test SVSTATE.VL
1846 is_setvl
= ins_name
== 'setvl'
1849 cmps
= (SelectableInt(vl
, 64), overflow
,)
1851 overflow
= None # do not override overflow except in setvl
1853 # if there was not an explicit CR0 in the pseudocode, do implicit Rc=1
1855 self
.handle_comparison(cmps
, regnum
, overflow
, no_so
=is_setvl
)
1857 # otherwise we just blat CR0 into the required regnum
1858 log("explicit rc0", cr0
)
1859 self
.crl
[regnum
].eq(cr0
)
1861 def do_outregs_nia(self
, asmop
, ins_name
, info
, output_names
, results
,
1862 carry_en
, rc_en
, ffirst_hit
):
1863 # write out any regs for this instruction
1865 for name
, output
in zip(output_names
, results
):
1866 yield from self
.check_write(info
, name
, output
, carry_en
)
1869 self
.svp64_reset_loop()
1872 # check advancement of src/dst/sub-steps and if PC needs updating
1873 nia_update
= (yield from self
.check_step_increment(results
, rc_en
,
1876 self
.update_pc_next()
1878 def check_replace_d(self
, info
, remap_active
):
1879 replace_d
= False # update / replace constant in pseudocode
1880 ldstmode
= yield self
.dec2
.rm_dec
.ldstmode
1881 vl
= self
.svstate
.vl
1882 subvl
= yield self
.dec2
.rm_dec
.rm_in
.subvl
1883 srcstep
, dststep
= self
.new_srcstep
, self
.new_dststep
1884 ssubstep
, dsubstep
= self
.new_ssubstep
, self
.new_dsubstep
1885 if info
.form
== 'DS':
1886 # DS-Form, multiply by 4 then knock 2 bits off after
1887 imm
= yield self
.dec2
.dec
.fields
.FormDS
.DS
[0:14] * 4
1889 imm
= yield self
.dec2
.dec
.fields
.FormD
.D
[0:16]
1890 imm
= exts(imm
, 16) # sign-extend to integer
1891 # get the right step. LD is from srcstep, ST is dststep
1892 op
= yield self
.dec2
.e
.do
.insn_type
1894 if op
== MicrOp
.OP_LOAD
.value
:
1896 offsmul
= yield self
.dec2
.in1_step
1897 log("D-field REMAP src", imm
, offsmul
)
1899 offsmul
= (srcstep
* (subvl
+1)) + ssubstep
1900 log("D-field src", imm
, offsmul
)
1901 elif op
== MicrOp
.OP_STORE
.value
:
1902 # XXX NOTE! no bit-reversed STORE! this should not ever be used
1903 offsmul
= (dststep
* (subvl
+1)) + dsubstep
1904 log("D-field dst", imm
, offsmul
)
1905 # Unit-Strided LD/ST adds offset*width to immediate
1906 if ldstmode
== SVP64LDSTmode
.UNITSTRIDE
.value
:
1907 ldst_len
= yield self
.dec2
.e
.do
.data_len
1908 imm
= SelectableInt(imm
+ offsmul
* ldst_len
, 32)
1910 # Element-strided multiplies the immediate by element step
1911 elif ldstmode
== SVP64LDSTmode
.ELSTRIDE
.value
:
1912 imm
= SelectableInt(imm
* offsmul
, 32)
1915 ldst_ra_vec
= yield self
.dec2
.rm_dec
.ldst_ra_vec
1916 ldst_imz_in
= yield self
.dec2
.rm_dec
.ldst_imz_in
1917 log("LDSTmode", SVP64LDSTmode(ldstmode
),
1918 offsmul
, imm
, ldst_ra_vec
, ldst_imz_in
)
1919 # new replacement D... errr.. DS
1921 if info
.form
== 'DS':
1922 # TODO: assert 2 LSBs are zero?
1923 log("DS-Form, TODO, assert 2 LSBs zero?", bin(imm
.value
))
1924 imm
.value
= imm
.value
>> 2
1925 self
.namespace
['DS'] = imm
1927 self
.namespace
['D'] = imm
1929 def get_input(self
, name
):
1930 # using PowerDecoder2, first, find the decoder index.
1931 # (mapping name RA RB RC RS to in1, in2, in3)
1932 regnum
, is_vec
= yield from get_pdecode_idx_in(self
.dec2
, name
)
1934 # doing this is not part of svp64, it's because output
1935 # registers, to be modified, need to be in the namespace.
1936 regnum
, is_vec
= yield from get_pdecode_idx_out(self
.dec2
, name
)
1938 regnum
, is_vec
= yield from get_pdecode_idx_out2(self
.dec2
, name
)
1940 # in case getting the register number is needed, _RA, _RB
1941 regname
= "_" + name
1942 self
.namespace
[regname
] = regnum
1943 if not self
.is_svp64_mode
or not self
.pred_src_zero
:
1944 log('reading reg %s %s' % (name
, str(regnum
)), is_vec
)
1946 reg_val
= SelectableInt(self
.fpr(regnum
))
1947 log("read reg %d: 0x%x" % (regnum
, reg_val
.value
))
1948 elif name
is not None:
1949 reg_val
= SelectableInt(self
.gpr(regnum
))
1950 log("read reg %d: 0x%x" % (regnum
, reg_val
.value
))
1952 log('zero input reg %s %s' % (name
, str(regnum
)), is_vec
)
1956 def remap_set_steps(self
, remaps
):
1957 """remap_set_steps sets up the in1/2/3 and out1/2 steps.
1958 they work in concert with PowerDecoder2 at the moment,
1959 there is no HDL implementation of REMAP. therefore this
1960 function, because ISACaller still uses PowerDecoder2,
1961 will *explicitly* write the dec2.XX_step values. this has
1964 # just some convenient debug info
1966 sname
= 'SVSHAPE%d' % i
1967 shape
= self
.spr
[sname
]
1968 log(sname
, bin(shape
.value
))
1969 log(" lims", shape
.lims
)
1970 log(" mode", shape
.mode
)
1971 log(" skip", shape
.skip
)
1973 # set up the list of steps to remap
1974 mi0
= self
.svstate
.mi0
1975 mi1
= self
.svstate
.mi1
1976 mi2
= self
.svstate
.mi2
1977 mo0
= self
.svstate
.mo0
1978 mo1
= self
.svstate
.mo1
1979 steps
= [(self
.dec2
.in1_step
, mi0
), # RA
1980 (self
.dec2
.in2_step
, mi1
), # RB
1981 (self
.dec2
.in3_step
, mi2
), # RC
1982 (self
.dec2
.o_step
, mo0
), # RT
1983 (self
.dec2
.o2_step
, mo1
), # EA
1985 remap_idxs
= self
.remap_idxs
1987 # now cross-index the required SHAPE for each of 3-in 2-out regs
1988 rnames
= ['RA', 'RB', 'RC', 'RT', 'EA']
1989 for i
, (dstep
, shape_idx
) in enumerate(steps
):
1990 (shape
, remap
) = remaps
[shape_idx
]
1991 remap_idx
= remap_idxs
[shape_idx
]
1992 # zero is "disabled"
1993 if shape
.value
== 0x0:
1995 # now set the actual requested step to the current index
1996 yield dstep
.eq(remap_idx
)
1998 # debug printout info
1999 rremaps
.append((shape
.mode
, i
, rnames
[i
], shape_idx
, remap_idx
))
2001 log("shape remap", x
)
2003 def check_write(self
, info
, name
, output
, carry_en
):
2004 if name
== 'overflow': # ignore, done already (above)
2006 if name
== 'CR0': # ignore, done already (above)
2008 if isinstance(output
, int):
2009 output
= SelectableInt(output
, 256)
2011 if name
in ['CA', 'CA32']:
2013 log("writing %s to XER" % name
, output
)
2014 log("write XER %s 0x%x" % (name
, output
.value
))
2015 self
.spr
['XER'][XER_bits
[name
]] = output
.value
2017 log("NOT writing %s to XER" % name
, output
)
2019 # write special SPRs
2020 if name
in info
.special_regs
:
2021 log('writing special %s' % name
, output
, special_sprs
)
2022 log("write reg %s 0x%x" % (name
, output
.value
))
2023 if name
in special_sprs
:
2024 self
.spr
[name
] = output
2026 self
.namespace
[name
].eq(output
)
2028 log('msr written', hex(self
.msr
.value
))
2030 # find out1/out2 PR/FPR
2031 regnum
, is_vec
= yield from get_pdecode_idx_out(self
.dec2
, name
)
2033 regnum
, is_vec
= yield from get_pdecode_idx_out2(self
.dec2
, name
)
2035 # temporary hack for not having 2nd output
2036 regnum
= yield getattr(self
.decoder
, name
)
2038 # convenient debug prefix
2043 # check zeroing due to predicate bit being zero
2044 if self
.is_svp64_mode
and self
.pred_dst_zero
:
2045 log('zeroing reg %d %s' % (regnum
, str(output
)), is_vec
)
2046 output
= SelectableInt(0, 256)
2047 log("write reg %s%d 0x%x" % (reg_prefix
, regnum
, output
.value
),
2048 kind
=LogKind
.InstrInOuts
)
2049 # zero-extend tov64 bit begore storing (should use EXT oh well)
2050 if output
.bits
> 64:
2051 output
= SelectableInt(output
.value
, 64)
2053 self
.fpr
[regnum
] = output
2055 self
.gpr
[regnum
] = output
2057 def check_step_increment(self
, results
, rc_en
, asmop
, ins_name
):
2058 # check if it is the SVSTATE.src/dest step that needs incrementing
2059 # this is our Sub-Program-Counter loop from 0 to VL-1
2060 if not self
.allow_next_step_inc
:
2061 if self
.is_svp64_mode
:
2062 return (yield from self
.svstate_post_inc(ins_name
))
2064 # XXX only in non-SVP64 mode!
2065 # record state of whether the current operation was an svshape,
2067 # to be able to know if it should apply in the next instruction.
2068 # also (if going to use this instruction) should disable ability
2069 # to interrupt in between. sigh.
2070 self
.last_op_svshape
= asmop
in ['svremap', 'svindex',
2077 log("SVSTATE_NEXT: inc requested, mode",
2078 self
.svstate_next_mode
, self
.allow_next_step_inc
)
2079 yield from self
.svstate_pre_inc()
2080 pre
= yield from self
.update_new_svstate_steps()
2082 # reset at end of loop including exit Vertical Mode
2083 log("SVSTATE_NEXT: end of loop, reset")
2084 self
.svp64_reset_loop()
2085 self
.svstate
.vfirst
= 0
2089 results
= [SelectableInt(0, 64)]
2090 self
.handle_comparison(results
) # CR0
2092 if self
.allow_next_step_inc
== 2:
2093 log("SVSTATE_NEXT: read")
2094 nia_update
= (yield from self
.svstate_post_inc(ins_name
))
2096 log("SVSTATE_NEXT: post-inc")
2097 # use actual (cached) src/dst-step here to check end
2098 remaps
= self
.get_remap_indices()
2099 remap_idxs
= self
.remap_idxs
2100 vl
= self
.svstate
.vl
2101 subvl
= yield self
.dec2
.rm_dec
.rm_in
.subvl
2102 if self
.allow_next_step_inc
!= 2:
2103 yield from self
.advance_svstate_steps()
2104 #self.namespace['SVSTATE'] = self.svstate.spr
2105 # set CR0 (if Rc=1) based on end
2106 endtest
= 1 if self
.at_loopend() else 0
2108 #results = [SelectableInt(endtest, 64)]
2109 # self.handle_comparison(results) # CR0
2111 # see if svstep was requested, if so, which SVSTATE
2113 if self
.svstate_next_mode
> 0:
2114 shape_idx
= self
.svstate_next_mode
.value
-1
2115 endings
= self
.remap_loopends
[shape_idx
]
2116 cr_field
= SelectableInt((~endings
) << 1 | endtest
, 4)
2117 log("svstep Rc=1, CR0", cr_field
, endtest
)
2118 self
.crl
[0].eq(cr_field
) # CR0
2120 # reset at end of loop including exit Vertical Mode
2121 log("SVSTATE_NEXT: after increments, reset")
2122 self
.svp64_reset_loop()
2123 self
.svstate
.vfirst
= 0
2126 def SVSTATE_NEXT(self
, mode
, submode
):
2127 """explicitly moves srcstep/dststep on to next element, for
2128 "Vertical-First" mode. this function is called from
2129 setvl pseudo-code, as a pseudo-op "svstep"
2131 WARNING: this function uses information that was created EARLIER
2132 due to it being in the middle of a yield, but this function is
2133 *NOT* called from yield (it's called from compiled pseudocode).
2135 self
.allow_next_step_inc
= submode
.value
+ 1
2136 log("SVSTATE_NEXT mode", mode
, submode
, self
.allow_next_step_inc
)
2137 self
.svstate_next_mode
= mode
2138 if self
.svstate_next_mode
> 0 and self
.svstate_next_mode
< 5:
2139 shape_idx
= self
.svstate_next_mode
.value
-1
2140 return SelectableInt(self
.remap_idxs
[shape_idx
], 7)
2141 if self
.svstate_next_mode
== 5:
2142 self
.svstate_next_mode
= 0
2143 return SelectableInt(self
.svstate
.srcstep
, 7)
2144 if self
.svstate_next_mode
== 6:
2145 self
.svstate_next_mode
= 0
2146 return SelectableInt(self
.svstate
.dststep
, 7)
2147 if self
.svstate_next_mode
== 7:
2148 self
.svstate_next_mode
= 0
2149 return SelectableInt(self
.svstate
.ssubstep
, 7)
2150 if self
.svstate_next_mode
== 8:
2151 self
.svstate_next_mode
= 0
2152 return SelectableInt(self
.svstate
.dsubstep
, 7)
2153 return SelectableInt(0, 7)
2155 def get_src_dststeps(self
):
2156 """gets srcstep, dststep, and ssubstep, dsubstep
2158 return (self
.new_srcstep
, self
.new_dststep
,
2159 self
.new_ssubstep
, self
.new_dsubstep
)
2161 def update_svstate_namespace(self
, overwrite_svstate
=True):
2162 if overwrite_svstate
:
2163 # note, do not get the bit-reversed srcstep here!
2164 srcstep
, dststep
= self
.new_srcstep
, self
.new_dststep
2165 ssubstep
, dsubstep
= self
.new_ssubstep
, self
.new_dsubstep
2167 # update SVSTATE with new srcstep
2168 self
.svstate
.srcstep
= srcstep
2169 self
.svstate
.dststep
= dststep
2170 self
.svstate
.ssubstep
= ssubstep
2171 self
.svstate
.dsubstep
= dsubstep
2172 self
.namespace
['SVSTATE'] = self
.svstate
2173 yield self
.dec2
.state
.svstate
.eq(self
.svstate
.value
)
2174 yield Settle() # let decoder update
2176 def update_new_svstate_steps(self
, overwrite_svstate
=True):
2177 yield from self
.update_svstate_namespace(overwrite_svstate
)
2178 srcstep
= self
.svstate
.srcstep
2179 dststep
= self
.svstate
.dststep
2180 ssubstep
= self
.svstate
.ssubstep
2181 dsubstep
= self
.svstate
.dsubstep
2182 pack
= self
.svstate
.pack
2183 unpack
= self
.svstate
.unpack
2184 vl
= self
.svstate
.vl
2185 subvl
= yield self
.dec2
.rm_dec
.rm_in
.subvl
2186 rm_mode
= yield self
.dec2
.rm_dec
.mode
2187 ff_inv
= yield self
.dec2
.rm_dec
.inv
2188 cr_bit
= yield self
.dec2
.rm_dec
.cr_sel
2189 log(" srcstep", srcstep
)
2190 log(" dststep", dststep
)
2192 log(" unpack", unpack
)
2193 log(" ssubstep", ssubstep
)
2194 log(" dsubstep", dsubstep
)
2196 log(" subvl", subvl
)
2197 log(" rm_mode", rm_mode
)
2199 log(" cr_bit", cr_bit
)
2201 # check if end reached (we let srcstep overrun, above)
2202 # nothing needs doing (TODO zeroing): just do next instruction
2205 return ((ssubstep
== subvl
and srcstep
== vl
) or
2206 (dsubstep
== subvl
and dststep
== vl
))
2208 def svstate_post_inc(self
, insn_name
, vf
=0):
2209 # check if SV "Vertical First" mode is enabled
2210 vfirst
= self
.svstate
.vfirst
2211 log(" SV Vertical First", vf
, vfirst
)
2212 if not vf
and vfirst
== 1:
2216 # check if it is the SVSTATE.src/dest step that needs incrementing
2217 # this is our Sub-Program-Counter loop from 0 to VL-1
2218 # XXX twin predication TODO
2219 vl
= self
.svstate
.vl
2220 subvl
= yield self
.dec2
.rm_dec
.rm_in
.subvl
2221 mvl
= self
.svstate
.maxvl
2222 srcstep
= self
.svstate
.srcstep
2223 dststep
= self
.svstate
.dststep
2224 ssubstep
= self
.svstate
.ssubstep
2225 dsubstep
= self
.svstate
.dsubstep
2226 pack
= self
.svstate
.pack
2227 unpack
= self
.svstate
.unpack
2228 rm_mode
= yield self
.dec2
.rm_dec
.mode
2229 reverse_gear
= yield self
.dec2
.rm_dec
.reverse_gear
2230 sv_ptype
= yield self
.dec2
.dec
.op
.SV_Ptype
2231 out_vec
= not (yield self
.dec2
.no_out_vec
)
2232 in_vec
= not (yield self
.dec2
.no_in_vec
)
2233 log(" svstate.vl", vl
)
2234 log(" svstate.mvl", mvl
)
2235 log(" rm.subvl", subvl
)
2236 log(" svstate.srcstep", srcstep
)
2237 log(" svstate.dststep", dststep
)
2238 log(" svstate.ssubstep", ssubstep
)
2239 log(" svstate.dsubstep", dsubstep
)
2240 log(" svstate.pack", pack
)
2241 log(" svstate.unpack", unpack
)
2242 log(" mode", rm_mode
)
2243 log(" reverse", reverse_gear
)
2244 log(" out_vec", out_vec
)
2245 log(" in_vec", in_vec
)
2246 log(" sv_ptype", sv_ptype
, sv_ptype
== SVPtype
.P2
.value
)
2247 # check if this was an sv.bc* and if so did it succeed
2248 if self
.is_svp64_mode
and insn_name
.startswith("sv.bc"):
2249 end_loop
= self
.namespace
['end_loop']
2250 log("branch %s end_loop" % insn_name
, end_loop
)
2252 self
.svp64_reset_loop()
2253 self
.update_pc_next()
2255 # check if srcstep needs incrementing by one, stop PC advancing
2256 # but for 2-pred both src/dest have to be checked.
2257 # XXX this might not be true! it may just be LD/ST
2258 if sv_ptype
== SVPtype
.P2
.value
:
2259 svp64_is_vector
= (out_vec
or in_vec
)
2261 svp64_is_vector
= out_vec
2262 # loops end at the first "hit" (source or dest)
2263 yield from self
.advance_svstate_steps()
2264 loopend
= self
.loopend
2265 log("loopend", svp64_is_vector
, loopend
)
2266 if not svp64_is_vector
or loopend
:
2267 # reset loop to zero and update NIA
2268 self
.svp64_reset_loop()
2273 # still looping, advance and update NIA
2274 self
.namespace
['SVSTATE'] = self
.svstate
2276 # not an SVP64 branch, so fix PC (NIA==CIA) for next loop
2277 # (by default, NIA is CIA+4 if v3.0B or CIA+8 if SVP64)
2278 # this way we keep repeating the same instruction (with new steps)
2279 self
.pc
.NIA
.value
= self
.pc
.CIA
.value
2280 self
.namespace
['NIA'] = self
.pc
.NIA
2281 log("end of sub-pc call", self
.namespace
['CIA'], self
.namespace
['NIA'])
2282 return False # DO NOT allow PC update whilst Sub-PC loop running
2284 def update_pc_next(self
):
2285 # UPDATE program counter
2286 self
.pc
.update(self
.namespace
, self
.is_svp64_mode
)
2287 #self.svstate.spr = self.namespace['SVSTATE']
2288 log("end of call", self
.namespace
['CIA'],
2289 self
.namespace
['NIA'],
2290 self
.namespace
['SVSTATE'])
2292 def svp64_reset_loop(self
):
2293 self
.svstate
.srcstep
= 0
2294 self
.svstate
.dststep
= 0
2295 self
.svstate
.ssubstep
= 0
2296 self
.svstate
.dsubstep
= 0
2297 self
.loopend
= False
2298 log(" svstate.srcstep loop end (PC to update)")
2299 self
.namespace
['SVSTATE'] = self
.svstate
2301 def update_nia(self
):
2302 self
.pc
.update_nia(self
.is_svp64_mode
)
2303 self
.namespace
['NIA'] = self
.pc
.NIA
2307 """Decorator factory.
2309 this decorator will "inject" variables into the function's namespace,
2310 from the *dictionary* in self.namespace. it therefore becomes possible
2311 to make it look like a whole stack of variables which would otherwise
2312 need "self." inserted in front of them (*and* for those variables to be
2313 added to the instance) "appear" in the function.
2315 "self.namespace['SI']" for example becomes accessible as just "SI" but
2316 *only* inside the function, when decorated.
2318 def variable_injector(func
):
2320 def decorator(*args
, **kwargs
):
2322 func_globals
= func
.__globals
__ # Python 2.6+
2323 except AttributeError:
2324 func_globals
= func
.func_globals
# Earlier versions.
2326 context
= args
[0].namespace
# variables to be injected
2327 saved_values
= func_globals
.copy() # Shallow copy of dict.
2328 log("globals before", context
.keys())
2329 func_globals
.update(context
)
2330 result
= func(*args
, **kwargs
)
2331 log("globals after", func_globals
['CIA'], func_globals
['NIA'])
2332 log("args[0]", args
[0].namespace
['CIA'],
2333 args
[0].namespace
['NIA'],
2334 args
[0].namespace
['SVSTATE'])
2335 if 'end_loop' in func_globals
:
2336 log("args[0] end_loop", func_globals
['end_loop'])
2337 args
[0].namespace
= func_globals
2338 #exec (func.__code__, func_globals)
2341 # func_globals = saved_values # Undo changes.
2347 return variable_injector