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
16 from collections
import namedtuple
17 from copy
import deepcopy
18 from functools
import wraps
20 from nmigen
.sim
import Settle
22 import openpower
.syscalls
23 from openpower
.consts
import (MSRb
, PIb
, # big-endian (PowerISA versions)
24 SVP64CROffs
, SVP64MODEb
)
25 from openpower
.decoder
.helpers
import (ISACallerHelper
, ISAFPHelpers
, exts
,
27 from openpower
.decoder
.isa
.mem
import Mem
, MemMMap
, MemException
28 from openpower
.decoder
.isa
.radixmmu
import RADIX
29 from openpower
.decoder
.isa
.svshape
import SVSHAPE
30 from openpower
.decoder
.isa
.svstate
import SVP64State
31 from openpower
.decoder
.orderedset
import OrderedSet
32 from openpower
.decoder
.power_enums
import (FPTRANS_INSNS
, CRInSel
, CROutSel
,
33 In1Sel
, In2Sel
, In3Sel
, LDSTMode
,
34 MicrOp
, OutSel
, SVMode
,
35 SVP64LDSTmode
, SVP64PredCR
,
36 SVP64PredInt
, SVP64PredMode
,
37 SVP64RMMode
, SVPType
, XER_bits
,
38 insns
, spr_byname
, spr_dict
,
40 from openpower
.insndb
.core
import SVP64Instruction
41 from openpower
.decoder
.power_svp64
import SVP64RM
, decode_extra
42 from openpower
.decoder
.selectable_int
import (FieldSelectableInt
,
43 SelectableInt
, selectconcat
,
44 EFFECTIVELY_UNLIMITED
)
45 from openpower
.fpscr
import FPSCRState
46 from openpower
.xer
import XERState
47 from openpower
.util
import LogKind
, log
49 LDST_UPDATE_INSNS
= ['ldu', 'lwzu', 'lbzu', 'lhzu', 'lhau', 'lfsu', 'lfdu',
50 'stwu', 'stbu', 'sthu', 'stfsu', 'stfdu', 'stdu',
54 instruction_info
= namedtuple('instruction_info',
55 'func read_regs uninit_regs write_regs ' +
56 'special_regs op_fields form asmregs')
66 # rrright. this is here basically because the compiler pywriter returns
67 # results in a specific priority order. to make sure regs match up they
68 # need partial sorting. sigh.
70 # TODO (lkcl): adjust other registers that should be in a particular order
71 # probably CA, CA32, and CR
99 "overflow": 7, # should definitely be last
103 fregs
= ['FRA', 'FRB', 'FRC', 'FRS', 'FRT']
106 def get_masked_reg(regs
, base
, offs
, ew_bits
):
107 # rrrright. start by breaking down into row/col, based on elwidth
108 gpr_offs
= offs
// (64 // ew_bits
)
109 gpr_col
= offs
% (64 // ew_bits
)
110 # compute the mask based on ew_bits
111 mask
= (1 << ew_bits
) - 1
112 # now select the 64-bit register, but get its value (easier)
113 val
= regs
[base
+ gpr_offs
]
114 # shift down so element we want is at LSB
115 val
>>= gpr_col
* ew_bits
116 # mask so we only return the LSB element
120 def set_masked_reg(regs
, base
, offs
, ew_bits
, value
):
121 # rrrright. start by breaking down into row/col, based on elwidth
122 gpr_offs
= offs
// (64//ew_bits
)
123 gpr_col
= offs
% (64//ew_bits
)
124 # compute the mask based on ew_bits
125 mask
= (1 << ew_bits
)-1
126 # now select the 64-bit register, but get its value (easier)
127 val
= regs
[base
+gpr_offs
]
128 # now mask out the bit we don't want
129 val
= val
& ~
(mask
<< (gpr_col
*ew_bits
))
130 # then wipe the bit we don't want from the value
132 # OR the new value in, shifted up
133 val |
= value
<< (gpr_col
*ew_bits
)
134 regs
[base
+gpr_offs
] = val
137 def create_args(reglist
, extra
=None):
138 retval
= list(OrderedSet(reglist
))
139 retval
.sort(key
=lambda reg
: REG_SORT_ORDER
.get(reg
, 0))
140 if extra
is not None:
141 return [extra
] + retval
146 def __init__(self
, decoder
, isacaller
, svstate
, regfile
):
149 self
.isacaller
= isacaller
150 self
.svstate
= svstate
151 for i
in range(len(regfile
)):
152 self
[i
] = SelectableInt(regfile
[i
], 64)
154 def __call__(self
, ridx
, is_vec
=False, offs
=0, elwidth
=64):
155 if isinstance(ridx
, SelectableInt
):
158 return self
[ridx
+offs
]
159 # rrrright. start by breaking down into row/col, based on elwidth
160 gpr_offs
= offs
// (64//elwidth
)
161 gpr_col
= offs
% (64//elwidth
)
162 # now select the 64-bit register, but get its value (easier)
163 val
= self
[ridx
+gpr_offs
].value
164 # now shift down and mask out
165 val
= val
>> (gpr_col
*elwidth
) & ((1 << elwidth
)-1)
166 # finally, return a SelectableInt at the required elwidth
167 log("GPR call", ridx
, "isvec", is_vec
, "offs", offs
,
168 "elwid", elwidth
, "offs/col", gpr_offs
, gpr_col
, "val", hex(val
))
169 return SelectableInt(val
, elwidth
)
171 def set_form(self
, form
):
174 def write(self
, rnum
, value
, is_vec
=False, elwidth
=64):
176 if isinstance(rnum
, SelectableInt
):
178 if isinstance(value
, SelectableInt
):
181 if isinstance(rnum
, tuple):
182 rnum
, base
, offs
= rnum
185 # rrrright. start by breaking down into row/col, based on elwidth
186 gpr_offs
= offs
// (64//elwidth
)
187 gpr_col
= offs
% (64//elwidth
)
188 # compute the mask based on elwidth
189 mask
= (1 << elwidth
)-1
190 # now select the 64-bit register, but get its value (easier)
191 val
= self
[base
+gpr_offs
].value
192 # now mask out the bit we don't want
193 val
= val
& ~
(mask
<< (gpr_col
*elwidth
))
194 # then wipe the bit we don't want from the value
196 # OR the new value in, shifted up
197 val |
= value
<< (gpr_col
*elwidth
)
198 # finally put the damn value into the regfile
199 log("GPR write", base
, "isvec", is_vec
, "offs", offs
,
200 "elwid", elwidth
, "offs/col", gpr_offs
, gpr_col
, "val", hex(val
),
202 dict.__setitem
__(self
, base
+gpr_offs
, SelectableInt(val
, 64))
204 def __setitem__(self
, rnum
, value
):
205 # rnum = rnum.value # only SelectableInt allowed
206 log("GPR setitem", rnum
, value
)
207 if isinstance(rnum
, SelectableInt
):
209 dict.__setitem
__(self
, rnum
, value
)
211 def getz(self
, rnum
):
212 # rnum = rnum.value # only SelectableInt allowed
213 log("GPR getzero?", rnum
)
215 return SelectableInt(0, 64)
218 def _get_regnum(self
, attr
):
219 getform
= self
.sd
.sigforms
[self
.form
]
220 rnum
= getattr(getform
, attr
)
223 def ___getitem__(self
, attr
):
224 """ XXX currently not used
226 rnum
= self
._get
_regnum
(attr
)
227 log("GPR getitem", attr
, rnum
)
228 return self
.regfile
[rnum
]
230 def dump(self
, printout
=True):
232 for i
in range(len(self
)):
233 res
.append(self
[i
].value
)
235 for i
in range(0, len(res
), 8):
238 s
.append("%08x" % res
[i
+j
])
240 print("reg", "%2d" % i
, s
)
245 def __init__(self
, dec2
, initial_sprs
={}):
248 for key
, v
in initial_sprs
.items():
249 if isinstance(key
, SelectableInt
):
251 key
= special_sprs
.get(key
, key
)
252 if isinstance(key
, int):
255 info
= spr_byname
[key
]
256 if not isinstance(v
, SelectableInt
):
257 v
= SelectableInt(v
, info
.length
)
260 def __getitem__(self
, key
):
262 #log("dict", self.items())
263 # if key in special_sprs get the special spr, otherwise return key
264 if isinstance(key
, SelectableInt
):
266 if isinstance(key
, int):
267 key
= spr_dict
[key
].SPR
268 key
= special_sprs
.get(key
, key
)
269 if key
== 'HSRR0': # HACK!
271 if key
== 'HSRR1': # HACK!
274 res
= dict.__getitem
__(self
, key
)
276 if isinstance(key
, int):
279 info
= spr_byname
[key
]
280 self
[key
] = SelectableInt(0, info
.length
)
281 res
= dict.__getitem
__(self
, key
)
282 #log("spr returning", key, res)
285 def __setitem__(self
, key
, value
):
286 if isinstance(key
, SelectableInt
):
288 if isinstance(key
, int):
289 key
= spr_dict
[key
].SPR
291 key
= special_sprs
.get(key
, key
)
292 if key
== 'HSRR0': # HACK!
293 self
.__setitem
__('SRR0', value
)
294 if key
== 'HSRR1': # HACK!
295 self
.__setitem
__('SRR1', value
)
297 value
= XERState(value
)
298 log("setting spr", key
, value
)
299 dict.__setitem
__(self
, key
, value
)
301 def __call__(self
, ridx
):
304 def dump(self
, printout
=True):
306 keys
= list(self
.keys())
309 sprname
= spr_dict
.get(k
, None)
313 sprname
= sprname
.SPR
314 res
.append((sprname
, self
[k
].value
))
316 for sprname
, value
in res
:
317 print(" ", sprname
, hex(value
))
322 def __init__(self
, pc_init
=0):
323 self
.CIA
= SelectableInt(pc_init
, 64)
324 self
.NIA
= self
.CIA
+ SelectableInt(4, 64) # only true for v3.0B!
326 def update_nia(self
, is_svp64
):
327 increment
= 8 if is_svp64
else 4
328 self
.NIA
= self
.CIA
+ SelectableInt(increment
, 64)
330 def update(self
, namespace
, is_svp64
):
331 """updates the program counter (PC) by 4 if v3.0B mode or 8 if SVP64
333 self
.CIA
= namespace
['NIA'].narrow(64)
334 self
.update_nia(is_svp64
)
335 namespace
['CIA'] = self
.CIA
336 namespace
['NIA'] = self
.NIA
340 # See PowerISA Version 3.0 B Book 1
341 # Section 2.3.1 Condition Register pages 30 - 31
343 LT
= FL
= 0 # negative, less than, floating-point less than
344 GT
= FG
= 1 # positive, greater than, floating-point greater than
345 EQ
= FE
= 2 # equal, floating-point equal
346 SO
= FU
= 3 # summary overflow, floating-point unordered
348 def __init__(self
, init
=0):
349 # rev_cr = int('{:016b}'.format(initial_cr)[::-1], 2)
350 # self.cr = FieldSelectableInt(self._cr, list(range(32, 64)))
351 self
.cr
= SelectableInt(init
, 64) # underlying reg
352 # field-selectable versions of Condition Register TODO check bitranges?
355 bits
= tuple(range(i
*4+32, (i
+1)*4+32))
356 _cr
= FieldSelectableInt(self
.cr
, bits
)
360 # decode SVP64 predicate integer to reg number and invert
361 def get_predint(gpr
, mask
):
365 log("get_predint", mask
, SVP64PredInt
.ALWAYS
.value
)
366 if mask
== SVP64PredInt
.ALWAYS
.value
:
367 return 0xffff_ffff_ffff_ffff # 64 bits of 1
368 if mask
== SVP64PredInt
.R3_UNARY
.value
:
369 return 1 << (r3
.value
& 0b111111)
370 if mask
== SVP64PredInt
.R3
.value
:
372 if mask
== SVP64PredInt
.R3_N
.value
:
374 if mask
== SVP64PredInt
.R10
.value
:
376 if mask
== SVP64PredInt
.R10_N
.value
:
378 if mask
== SVP64PredInt
.R30
.value
:
380 if mask
== SVP64PredInt
.R30_N
.value
:
384 # decode SVP64 predicate CR to reg number and invert status
385 def _get_predcr(mask
):
386 if mask
== SVP64PredCR
.LT
.value
:
388 if mask
== SVP64PredCR
.GE
.value
:
390 if mask
== SVP64PredCR
.GT
.value
:
392 if mask
== SVP64PredCR
.LE
.value
:
394 if mask
== SVP64PredCR
.EQ
.value
:
396 if mask
== SVP64PredCR
.NE
.value
:
398 if mask
== SVP64PredCR
.SO
.value
:
400 if mask
== SVP64PredCR
.NS
.value
:
404 # read individual CR fields (0..VL-1), extract the required bit
405 # and construct the mask
406 def get_predcr(crl
, mask
, vl
):
407 idx
, noninv
= _get_predcr(mask
)
410 cr
= crl
[i
+SVP64CROffs
.CRPred
]
411 if cr
[idx
].value
== noninv
:
416 # TODO, really should just be using PowerDecoder2
417 def get_idx_map(dec2
, name
):
419 in1_sel
= yield op
.in1_sel
420 in2_sel
= yield op
.in2_sel
421 in3_sel
= yield op
.in3_sel
422 in1
= yield dec2
.e
.read_reg1
.data
423 # identify which regnames map to in1/2/3
424 if name
== 'RA' or name
== 'RA_OR_ZERO':
425 if (in1_sel
== In1Sel
.RA
.value
or
426 (in1_sel
== In1Sel
.RA_OR_ZERO
.value
and in1
!= 0)):
428 if in1_sel
== In1Sel
.RA_OR_ZERO
.value
:
431 if in2_sel
== In2Sel
.RB
.value
:
433 if in3_sel
== In3Sel
.RB
.value
:
435 # XXX TODO, RC doesn't exist yet!
437 if in3_sel
== In3Sel
.RC
.value
:
439 elif name
in ['EA', 'RS']:
440 if in1_sel
== In1Sel
.RS
.value
:
442 if in2_sel
== In2Sel
.RS
.value
:
444 if in3_sel
== In3Sel
.RS
.value
:
447 if in1_sel
== In1Sel
.FRA
.value
:
449 if in3_sel
== In3Sel
.FRA
.value
:
452 if in2_sel
== In2Sel
.FRB
.value
:
455 if in3_sel
== In3Sel
.FRC
.value
:
458 if in1_sel
== In1Sel
.FRS
.value
:
460 if in3_sel
== In3Sel
.FRS
.value
:
463 if in1_sel
== In1Sel
.FRT
.value
:
466 if in1_sel
== In1Sel
.RT
.value
:
471 # TODO, really should just be using PowerDecoder2
472 def get_idx_in(dec2
, name
, ewmode
=False):
473 idx
= yield from get_idx_map(dec2
, name
)
477 in1_sel
= yield op
.in1_sel
478 in2_sel
= yield op
.in2_sel
479 in3_sel
= yield op
.in3_sel
480 # get the IN1/2/3 from the decoder (includes SVP64 remap and isvec)
481 in1
= yield dec2
.e
.read_reg1
.data
482 in2
= yield dec2
.e
.read_reg2
.data
483 in3
= yield dec2
.e
.read_reg3
.data
485 in1_base
= yield dec2
.e
.read_reg1
.base
486 in2_base
= yield dec2
.e
.read_reg2
.base
487 in3_base
= yield dec2
.e
.read_reg3
.base
488 in1_offs
= yield dec2
.e
.read_reg1
.offs
489 in2_offs
= yield dec2
.e
.read_reg2
.offs
490 in3_offs
= yield dec2
.e
.read_reg3
.offs
491 in1
= (in1
, in1_base
, in1_offs
)
492 in2
= (in2
, in2_base
, in2_offs
)
493 in3
= (in3
, in3_base
, in3_offs
)
495 in1_isvec
= yield dec2
.in1_isvec
496 in2_isvec
= yield dec2
.in2_isvec
497 in3_isvec
= yield dec2
.in3_isvec
498 log("get_idx_in in1", name
, in1_sel
, In1Sel
.RA
.value
,
500 log("get_idx_in in2", name
, in2_sel
, In2Sel
.RB
.value
,
502 log("get_idx_in in3", name
, in3_sel
, In3Sel
.RS
.value
,
504 log("get_idx_in FRS in3", name
, in3_sel
, In3Sel
.FRS
.value
,
506 log("get_idx_in FRB in2", name
, in2_sel
, In2Sel
.FRB
.value
,
508 log("get_idx_in FRC in3", name
, in3_sel
, In3Sel
.FRC
.value
,
511 return in1
, in1_isvec
513 return in2
, in2_isvec
515 return in3
, in3_isvec
519 # TODO, really should just be using PowerDecoder2
520 def get_cr_in(dec2
, name
):
522 in_sel
= yield op
.cr_in
523 in_bitfield
= yield dec2
.dec_cr_in
.cr_bitfield
.data
524 sv_cr_in
= yield op
.sv_cr_in
525 spec
= yield dec2
.crin_svdec
.spec
526 sv_override
= yield dec2
.dec_cr_in
.sv_override
527 # get the IN1/2/3 from the decoder (includes SVP64 remap and isvec)
528 in1
= yield dec2
.e
.read_cr1
.data
529 cr_isvec
= yield dec2
.cr_in_isvec
530 log("get_cr_in", in_sel
, CROutSel
.CR0
.value
, in1
, cr_isvec
)
531 log(" sv_cr_in", sv_cr_in
)
532 log(" cr_bf", in_bitfield
)
534 log(" override", sv_override
)
535 # identify which regnames map to in / o2
537 if in_sel
== CRInSel
.BI
.value
:
539 log("get_cr_in not found", name
)
543 # TODO, really should just be using PowerDecoder2
544 def get_cr_out(dec2
, name
):
546 out_sel
= yield op
.cr_out
547 out_bitfield
= yield dec2
.dec_cr_out
.cr_bitfield
.data
548 sv_cr_out
= yield op
.sv_cr_out
549 spec
= yield dec2
.crout_svdec
.spec
550 sv_override
= yield dec2
.dec_cr_out
.sv_override
551 # get the IN1/2/3 from the decoder (includes SVP64 remap and isvec)
552 out
= yield dec2
.e
.write_cr
.data
553 o_isvec
= yield dec2
.cr_out_isvec
554 log("get_cr_out", out_sel
, CROutSel
.CR0
.value
, out
, o_isvec
)
555 log(" sv_cr_out", sv_cr_out
)
556 log(" cr_bf", out_bitfield
)
558 log(" override", sv_override
)
559 # identify which regnames map to out / o2
561 if out_sel
== CROutSel
.BF
.value
:
564 if out_sel
== CROutSel
.CR0
.value
:
566 if name
== 'CR1': # these are not actually calculated correctly
567 if out_sel
== CROutSel
.CR1
.value
:
569 # check RC1 set? if so return implicit vector, this is a REAL bad hack
570 RC1
= yield dec2
.rm_dec
.RC1
572 log("get_cr_out RC1 mode")
574 return 0, True # XXX TODO: offset CR0 from SVSTATE SPR
576 return 1, True # XXX TODO: offset CR1 from SVSTATE SPR
578 log("get_cr_out not found", name
)
582 # TODO, really should just be using PowerDecoder2
583 def get_out_map(dec2
, name
):
585 out_sel
= yield op
.out_sel
586 # get the IN1/2/3 from the decoder (includes SVP64 remap and isvec)
587 out
= yield dec2
.e
.write_reg
.data
588 # identify which regnames map to out / o2
590 if out_sel
== OutSel
.RA
.value
:
593 if out_sel
== OutSel
.RT
.value
:
595 if out_sel
== OutSel
.RT_OR_ZERO
.value
and out
!= 0:
597 elif name
== 'RT_OR_ZERO':
598 if out_sel
== OutSel
.RT_OR_ZERO
.value
:
601 if out_sel
== OutSel
.FRA
.value
:
604 if out_sel
== OutSel
.FRS
.value
:
607 if out_sel
== OutSel
.FRT
.value
:
612 # TODO, really should just be using PowerDecoder2
613 def get_idx_out(dec2
, name
, ewmode
=False):
615 out_sel
= yield op
.out_sel
616 # get the IN1/2/3 from the decoder (includes SVP64 remap and isvec)
617 out
= yield dec2
.e
.write_reg
.data
618 o_isvec
= yield dec2
.o_isvec
620 offs
= yield dec2
.e
.write_reg
.offs
621 base
= yield dec2
.e
.write_reg
.base
622 out
= (out
, base
, offs
)
623 # identify which regnames map to out / o2
624 ismap
= yield from get_out_map(dec2
, name
)
626 log("get_idx_out", name
, out_sel
, out
, o_isvec
)
628 log("get_idx_out not found", name
, out_sel
, out
, o_isvec
)
632 # TODO, really should just be using PowerDecoder2
633 def get_out2_map(dec2
, name
):
634 # check first if register is activated for write
636 out_sel
= yield op
.out_sel
637 out
= yield dec2
.e
.write_ea
.data
638 out_ok
= yield dec2
.e
.write_ea
.ok
642 if name
in ['EA', 'RA']:
643 if hasattr(op
, "upd"):
644 # update mode LD/ST uses read-reg A also as an output
646 log("get_idx_out2", upd
, LDSTMode
.update
.value
,
647 out_sel
, OutSel
.RA
.value
,
649 if upd
== LDSTMode
.update
.value
:
652 fft_en
= yield dec2
.implicit_rs
654 log("get_idx_out2", out_sel
, OutSel
.RS
.value
,
658 fft_en
= yield dec2
.implicit_rs
660 log("get_idx_out2", out_sel
, OutSel
.FRS
.value
,
666 # TODO, really should just be using PowerDecoder2
667 def get_idx_out2(dec2
, name
, ewmode
=False):
668 # check first if register is activated for write
670 out_sel
= yield op
.out_sel
671 out
= yield dec2
.e
.write_ea
.data
673 offs
= yield dec2
.e
.write_ea
.offs
674 base
= yield dec2
.e
.write_ea
.base
675 out
= (out
, base
, offs
)
676 o_isvec
= yield dec2
.o2_isvec
677 ismap
= yield from get_out2_map(dec2
, name
)
679 log("get_idx_out2", name
, out_sel
, out
, o_isvec
)
685 """deals with svstate looping.
688 def __init__(self
, svstate
):
689 self
.svstate
= svstate
692 def new_iterators(self
):
693 self
.src_it
= self
.src_iterator()
694 self
.dst_it
= self
.dst_iterator()
698 self
.new_ssubstep
= 0
699 self
.new_dsubstep
= 0
700 self
.pred_dst_zero
= 0
701 self
.pred_src_zero
= 0
703 def src_iterator(self
):
704 """source-stepping iterator
706 pack
= self
.svstate
.pack
710 # pack advances subvl in *outer* loop
711 while True: # outer subvl loop
712 while True: # inner vl loop
715 srcmask
= self
.srcmask
716 srcstep
= self
.svstate
.srcstep
717 pred_src_zero
= ((1 << srcstep
) & srcmask
) != 0
718 if self
.pred_sz
or pred_src_zero
:
719 self
.pred_src_zero
= not pred_src_zero
720 log(" advance src", srcstep
, vl
,
721 self
.svstate
.ssubstep
, subvl
)
722 # yield actual substep/srcstep
723 yield (self
.svstate
.ssubstep
, srcstep
)
724 # the way yield works these could have been modified.
727 srcstep
= self
.svstate
.srcstep
728 log(" advance src check", srcstep
, vl
,
729 self
.svstate
.ssubstep
, subvl
, srcstep
== vl
-1,
730 self
.svstate
.ssubstep
== subvl
)
731 if srcstep
== vl
-1: # end-point
732 self
.svstate
.srcstep
= SelectableInt(0, 7) # reset
733 if self
.svstate
.ssubstep
== subvl
: # end-point
734 log(" advance pack stop")
736 break # exit inner loop
737 self
.svstate
.srcstep
+= SelectableInt(1, 7) # advance ss
739 if self
.svstate
.ssubstep
== subvl
: # end-point
740 self
.svstate
.ssubstep
= SelectableInt(0, 2) # reset
741 log(" advance pack stop")
743 self
.svstate
.ssubstep
+= SelectableInt(1, 2)
746 # these cannot be done as for-loops because SVSTATE may change
747 # (srcstep/substep may be modified, interrupted, subvl/vl change)
748 # but they *can* be done as while-loops as long as every SVSTATE
749 # "thing" is re-read every single time a yield gives indices
750 while True: # outer vl loop
751 while True: # inner subvl loop
754 srcmask
= self
.srcmask
755 srcstep
= self
.svstate
.srcstep
756 pred_src_zero
= ((1 << srcstep
) & srcmask
) != 0
757 if self
.pred_sz
or pred_src_zero
:
758 self
.pred_src_zero
= not pred_src_zero
759 log(" advance src", srcstep
, vl
,
760 self
.svstate
.ssubstep
, subvl
)
761 # yield actual substep/srcstep
762 yield (self
.svstate
.ssubstep
, srcstep
)
763 if self
.svstate
.ssubstep
== subvl
: # end-point
764 self
.svstate
.ssubstep
= SelectableInt(0, 2) # reset
765 break # exit inner loop
766 self
.svstate
.ssubstep
+= SelectableInt(1, 2)
768 if srcstep
== vl
-1: # end-point
769 self
.svstate
.srcstep
= SelectableInt(0, 7) # reset
772 self
.svstate
.srcstep
+= SelectableInt(1, 7) # advance srcstep
774 def dst_iterator(self
):
775 """dest-stepping iterator
777 unpack
= self
.svstate
.unpack
781 # pack advances subvl in *outer* loop
782 while True: # outer subvl loop
783 while True: # inner vl loop
786 dstmask
= self
.dstmask
787 dststep
= self
.svstate
.dststep
788 pred_dst_zero
= ((1 << dststep
) & dstmask
) != 0
789 if self
.pred_dz
or pred_dst_zero
:
790 self
.pred_dst_zero
= not pred_dst_zero
791 log(" advance dst", dststep
, vl
,
792 self
.svstate
.dsubstep
, subvl
)
793 # yield actual substep/dststep
794 yield (self
.svstate
.dsubstep
, dststep
)
795 # the way yield works these could have been modified.
797 dststep
= self
.svstate
.dststep
798 log(" advance dst check", dststep
, vl
,
799 self
.svstate
.ssubstep
, subvl
)
800 if dststep
== vl
-1: # end-point
801 self
.svstate
.dststep
= SelectableInt(0, 7) # reset
802 if self
.svstate
.dsubstep
== subvl
: # end-point
803 log(" advance unpack stop")
806 self
.svstate
.dststep
+= SelectableInt(1, 7) # advance ds
808 if self
.svstate
.dsubstep
== subvl
: # end-point
809 self
.svstate
.dsubstep
= SelectableInt(0, 2) # reset
810 log(" advance unpack stop")
812 self
.svstate
.dsubstep
+= SelectableInt(1, 2)
814 # these cannot be done as for-loops because SVSTATE may change
815 # (dststep/substep may be modified, interrupted, subvl/vl change)
816 # but they *can* be done as while-loops as long as every SVSTATE
817 # "thing" is re-read every single time a yield gives indices
818 while True: # outer vl loop
819 while True: # inner subvl loop
821 dstmask
= self
.dstmask
822 dststep
= self
.svstate
.dststep
823 pred_dst_zero
= ((1 << dststep
) & dstmask
) != 0
824 if self
.pred_dz
or pred_dst_zero
:
825 self
.pred_dst_zero
= not pred_dst_zero
826 log(" advance dst", dststep
, self
.svstate
.vl
,
827 self
.svstate
.dsubstep
, subvl
)
828 # yield actual substep/dststep
829 yield (self
.svstate
.dsubstep
, dststep
)
830 if self
.svstate
.dsubstep
== subvl
: # end-point
831 self
.svstate
.dsubstep
= SelectableInt(0, 2) # reset
833 self
.svstate
.dsubstep
+= SelectableInt(1, 2)
836 if dststep
== vl
-1: # end-point
837 self
.svstate
.dststep
= SelectableInt(0, 7) # reset
839 self
.svstate
.dststep
+= SelectableInt(1, 7) # advance dststep
841 def src_iterate(self
):
842 """source-stepping iterator
846 pack
= self
.svstate
.pack
847 unpack
= self
.svstate
.unpack
848 ssubstep
= self
.svstate
.ssubstep
849 end_ssub
= ssubstep
== subvl
850 end_src
= self
.svstate
.srcstep
== vl
-1
851 log(" pack/unpack/subvl", pack
, unpack
, subvl
,
855 srcstep
= self
.svstate
.srcstep
856 srcmask
= self
.srcmask
858 # pack advances subvl in *outer* loop
860 assert srcstep
<= vl
-1
861 end_src
= srcstep
== vl
-1
866 self
.svstate
.ssubstep
+= SelectableInt(1, 2)
870 srcstep
+= 1 # advance srcstep
871 if not self
.srcstep_skip
:
873 if ((1 << srcstep
) & srcmask
) != 0:
876 log(" sskip", bin(srcmask
), bin(1 << srcstep
))
878 # advance subvl in *inner* loop
881 assert srcstep
<= vl
-1
882 end_src
= srcstep
== vl
-1
883 if end_src
: # end-point
889 if not self
.srcstep_skip
:
891 if ((1 << srcstep
) & srcmask
) != 0:
894 log(" sskip", bin(srcmask
), bin(1 << srcstep
))
895 self
.svstate
.ssubstep
= SelectableInt(0, 2) # reset
898 self
.svstate
.ssubstep
+= SelectableInt(1, 2)
900 self
.svstate
.srcstep
= SelectableInt(srcstep
, 7)
901 log(" advance src", self
.svstate
.srcstep
, self
.svstate
.ssubstep
,
904 def dst_iterate(self
):
905 """dest step iterator
909 pack
= self
.svstate
.pack
910 unpack
= self
.svstate
.unpack
911 dsubstep
= self
.svstate
.dsubstep
912 end_dsub
= dsubstep
== subvl
913 dststep
= self
.svstate
.dststep
914 end_dst
= dststep
== vl
-1
915 dstmask
= self
.dstmask
916 log(" pack/unpack/subvl", pack
, unpack
, subvl
,
921 # unpack advances subvl in *outer* loop
923 assert dststep
<= vl
-1
924 end_dst
= dststep
== vl
-1
929 self
.svstate
.dsubstep
+= SelectableInt(1, 2)
933 dststep
+= 1 # advance dststep
934 if not self
.dststep_skip
:
936 if ((1 << dststep
) & dstmask
) != 0:
939 log(" dskip", bin(dstmask
), bin(1 << dststep
))
941 # advance subvl in *inner* loop
944 assert dststep
<= vl
-1
945 end_dst
= dststep
== vl
-1
946 if end_dst
: # end-point
952 if not self
.dststep_skip
:
954 if ((1 << dststep
) & dstmask
) != 0:
957 log(" dskip", bin(dstmask
), bin(1 << dststep
))
958 self
.svstate
.dsubstep
= SelectableInt(0, 2) # reset
961 self
.svstate
.dsubstep
+= SelectableInt(1, 2)
963 self
.svstate
.dststep
= SelectableInt(dststep
, 7)
964 log(" advance dst", self
.svstate
.dststep
, self
.svstate
.dsubstep
,
967 def at_loopend(self
):
968 """tells if this is the last possible element. uses the cached values
969 for src/dst-step and sub-steps
973 srcstep
, dststep
= self
.new_srcstep
, self
.new_dststep
974 ssubstep
, dsubstep
= self
.new_ssubstep
, self
.new_dsubstep
975 end_ssub
= ssubstep
== subvl
976 end_dsub
= dsubstep
== subvl
977 if srcstep
== vl
-1 and end_ssub
:
979 if dststep
== vl
-1 and end_dsub
:
983 def advance_svstate_steps(self
):
984 """ advance sub/steps. note that Pack/Unpack *INVERTS* the order.
985 TODO when Pack/Unpack is set, substep becomes the *outer* loop
987 self
.subvl
= yield self
.dec2
.rm_dec
.rm_in
.subvl
988 if self
.loopend
: # huhn??
993 def read_src_mask(self
):
994 """read/update pred_sz and src mask
996 # get SVSTATE VL (oh and print out some debug stuff)
998 srcstep
= self
.svstate
.srcstep
999 ssubstep
= self
.svstate
.ssubstep
1001 # get predicate mask (all 64 bits)
1002 srcmask
= 0xffff_ffff_ffff_ffff
1004 pmode
= yield self
.dec2
.rm_dec
.predmode
1005 sv_ptype
= yield self
.dec2
.dec
.op
.SV_Ptype
1006 srcpred
= yield self
.dec2
.rm_dec
.srcpred
1007 dstpred
= yield self
.dec2
.rm_dec
.dstpred
1008 pred_sz
= yield self
.dec2
.rm_dec
.pred_sz
1009 if pmode
== SVP64PredMode
.INT
.value
:
1010 srcmask
= dstmask
= get_predint(self
.gpr
, dstpred
)
1011 if sv_ptype
== SVPType
.P2
.value
:
1012 srcmask
= get_predint(self
.gpr
, srcpred
)
1013 elif pmode
== SVP64PredMode
.CR
.value
:
1014 srcmask
= dstmask
= get_predcr(self
.crl
, dstpred
, vl
)
1015 if sv_ptype
== SVPType
.P2
.value
:
1016 srcmask
= get_predcr(self
.crl
, srcpred
, vl
)
1017 # work out if the ssubsteps are completed
1018 ssubstart
= ssubstep
== 0
1019 log(" pmode", pmode
)
1020 log(" ptype", sv_ptype
)
1021 log(" srcpred", bin(srcpred
))
1022 log(" srcmask", bin(srcmask
))
1023 log(" pred_sz", bin(pred_sz
))
1024 log(" ssubstart", ssubstart
)
1026 # store all that above
1027 self
.srcstep_skip
= False
1028 self
.srcmask
= srcmask
1029 self
.pred_sz
= pred_sz
1030 self
.new_ssubstep
= ssubstep
1031 log(" new ssubstep", ssubstep
)
1032 # until the predicate mask has a "1" bit... or we run out of VL
1033 # let srcstep==VL be the indicator to move to next instruction
1035 self
.srcstep_skip
= True
1037 def read_dst_mask(self
):
1038 """same as read_src_mask - check and record everything needed
1040 # get SVSTATE VL (oh and print out some debug stuff)
1041 # yield Delay(1e-10) # make changes visible
1042 vl
= self
.svstate
.vl
1043 dststep
= self
.svstate
.dststep
1044 dsubstep
= self
.svstate
.dsubstep
1046 # get predicate mask (all 64 bits)
1047 dstmask
= 0xffff_ffff_ffff_ffff
1049 pmode
= yield self
.dec2
.rm_dec
.predmode
1050 reverse_gear
= yield self
.dec2
.rm_dec
.reverse_gear
1051 sv_ptype
= yield self
.dec2
.dec
.op
.SV_Ptype
1052 dstpred
= yield self
.dec2
.rm_dec
.dstpred
1053 pred_dz
= yield self
.dec2
.rm_dec
.pred_dz
1054 if pmode
== SVP64PredMode
.INT
.value
:
1055 dstmask
= get_predint(self
.gpr
, dstpred
)
1056 elif pmode
== SVP64PredMode
.CR
.value
:
1057 dstmask
= get_predcr(self
.crl
, dstpred
, vl
)
1058 # work out if the ssubsteps are completed
1059 dsubstart
= dsubstep
== 0
1060 log(" pmode", pmode
)
1061 log(" ptype", sv_ptype
)
1062 log(" dstpred", bin(dstpred
))
1063 log(" dstmask", bin(dstmask
))
1064 log(" pred_dz", bin(pred_dz
))
1065 log(" dsubstart", dsubstart
)
1067 self
.dststep_skip
= False
1068 self
.dstmask
= dstmask
1069 self
.pred_dz
= pred_dz
1070 self
.new_dsubstep
= dsubstep
1071 log(" new dsubstep", dsubstep
)
1073 self
.dststep_skip
= True
1075 def svstate_pre_inc(self
):
1076 """check if srcstep/dststep need to skip over masked-out predicate bits
1077 note that this is not supposed to do anything to substep,
1078 it is purely for skipping masked-out bits
1081 self
.subvl
= yield self
.dec2
.rm_dec
.rm_in
.subvl
1082 yield from self
.read_src_mask()
1083 yield from self
.read_dst_mask()
1090 srcstep
= self
.svstate
.srcstep
1091 srcmask
= self
.srcmask
1092 pred_src_zero
= self
.pred_sz
1093 vl
= self
.svstate
.vl
1094 # srcstep-skipping opportunity identified
1095 if self
.srcstep_skip
:
1096 # cannot do this with sv.bc - XXX TODO
1099 while (((1 << srcstep
) & srcmask
) == 0) and (srcstep
!= vl
):
1100 log(" sskip", bin(1 << srcstep
))
1103 # now work out if the relevant mask bits require zeroing
1105 pred_src_zero
= ((1 << srcstep
) & srcmask
) == 0
1107 # store new srcstep / dststep
1108 self
.new_srcstep
= srcstep
1109 self
.pred_src_zero
= pred_src_zero
1110 log(" new srcstep", srcstep
)
1113 # dststep-skipping opportunity identified
1114 dststep
= self
.svstate
.dststep
1115 dstmask
= self
.dstmask
1116 pred_dst_zero
= self
.pred_dz
1117 vl
= self
.svstate
.vl
1118 if self
.dststep_skip
:
1119 # cannot do this with sv.bc - XXX TODO
1122 while (((1 << dststep
) & dstmask
) == 0) and (dststep
!= vl
):
1123 log(" dskip", bin(1 << dststep
))
1126 # now work out if the relevant mask bits require zeroing
1128 pred_dst_zero
= ((1 << dststep
) & dstmask
) == 0
1130 # store new srcstep / dststep
1131 self
.new_dststep
= dststep
1132 self
.pred_dst_zero
= pred_dst_zero
1133 log(" new dststep", dststep
)
1136 class SyscallEmulator(openpower
.syscalls
.Dispatcher
):
1137 def __init__(self
, isacaller
):
1138 machine
= uname().machine
1141 }.get(machine
, machine
)
1143 self
.__isacaller
= isacaller
1145 return super().__init
__(guest
="ppc64", host
=host
)
1147 def __call__(self
, identifier
, *arguments
):
1148 (identifier
, *arguments
) = map(int, (identifier
, *arguments
))
1149 return super().__call
__(identifier
, *arguments
)
1152 class ISACaller(ISACallerHelper
, ISAFPHelpers
, StepLoop
):
1153 # decoder2 - an instance of power_decoder2
1154 # regfile - a list of initial values for the registers
1155 # initial_{etc} - initial values for SPRs, Condition Register, Mem, MSR
1156 # respect_pc - tracks the program counter. requires initial_insns
1157 def __init__(self
, decoder2
, regfile
, initial_sprs
=None, initial_cr
=0,
1158 initial_mem
=None, initial_msr
=0,
1171 use_syscall_emu
=False):
1173 self
.syscall
= SyscallEmulator(isacaller
=self
)
1174 if not use_mmap_mem
:
1175 log("forcing use_mmap_mem due to use_syscall_emu active")
1180 # trace log file for model output. if None do nothing
1181 self
.insnlog
= insnlog
1182 self
.insnlog_is_file
= hasattr(insnlog
, "write")
1183 if not self
.insnlog_is_file
and self
.insnlog
:
1184 self
.insnlog
= open(self
.insnlog
, "w")
1186 self
.bigendian
= bigendian
1188 self
.is_svp64_mode
= False
1189 self
.respect_pc
= respect_pc
1190 if initial_sprs
is None:
1192 if initial_mem
is None:
1194 if fpregfile
is None:
1195 fpregfile
= [0] * 32
1196 if initial_insns
is None:
1198 assert self
.respect_pc
== False, "instructions required to honor pc"
1200 log("ISACaller insns", respect_pc
, initial_insns
, disassembly
)
1201 log("ISACaller initial_msr", initial_msr
)
1203 # "fake program counter" mode (for unit testing)
1207 if isinstance(initial_mem
, tuple):
1208 self
.fake_pc
= initial_mem
[0]
1209 disasm_start
= self
.fake_pc
1211 disasm_start
= initial_pc
1213 # disassembly: we need this for now (not given from the decoder)
1214 self
.disassembly
= {}
1216 for i
, code
in enumerate(disassembly
):
1217 self
.disassembly
[i
*4 + disasm_start
] = code
1219 # set up registers, instruction memory, data memory, PC, SPRs, MSR, CR
1220 self
.svp64rm
= SVP64RM()
1221 if initial_svstate
is None:
1223 if isinstance(initial_svstate
, int):
1224 initial_svstate
= SVP64State(initial_svstate
)
1225 # SVSTATE, MSR and PC
1226 StepLoop
.__init
__(self
, initial_svstate
)
1227 self
.msr
= SelectableInt(initial_msr
, 64) # underlying reg
1229 # GPR FPR SPR registers
1230 initial_sprs
= deepcopy(initial_sprs
) # so as not to get modified
1231 self
.gpr
= GPR(decoder2
, self
, self
.svstate
, regfile
)
1232 self
.fpr
= GPR(decoder2
, self
, self
.svstate
, fpregfile
)
1233 self
.spr
= SPR(decoder2
, initial_sprs
) # initialise SPRs before MMU
1235 # set up 4 dummy SVSHAPEs if they aren't already set up
1237 sname
= 'SVSHAPE%d' % i
1238 val
= self
.spr
.get(sname
, 0)
1239 # make sure it's an SVSHAPE
1240 self
.spr
[sname
] = SVSHAPE(val
, self
.gpr
)
1241 self
.last_op_svshape
= False
1245 self
.mem
= MemMMap(row_bytes
=8,
1246 initial_mem
=initial_mem
,
1248 self
.imem
= self
.mem
1249 self
.mem
.initialize(row_bytes
=4, initial_mem
=initial_insns
)
1250 self
.mem
.log_fancy(kind
=LogKind
.InstrInOuts
)
1252 self
.mem
= Mem(row_bytes
=8, initial_mem
=initial_mem
,
1254 self
.mem
.log_fancy(kind
=LogKind
.InstrInOuts
)
1255 self
.imem
= Mem(row_bytes
=4, initial_mem
=initial_insns
)
1256 # MMU mode, redirect underlying Mem through RADIX
1258 self
.mem
= RADIX(self
.mem
, self
)
1260 self
.imem
= RADIX(self
.imem
, self
)
1262 # TODO, needed here:
1263 # FPR (same as GPR except for FP nums)
1264 # 4.2.2 p124 FPSCR (definitely "separate" - not in SPR)
1265 # note that mffs, mcrfs, mtfsf "manage" this FPSCR
1266 self
.fpscr
= FPSCRState(initial_fpscr
)
1268 # 2.3.1 CR (and sub-fields CR0..CR6 - CR0 SO comes from XER.SO)
1269 # note that mfocrf, mfcr, mtcr, mtocrf, mcrxrx "manage" CRs
1271 # 2.3.2 LR (actually SPR #8) -- Done
1272 # 2.3.3 CTR (actually SPR #9) -- Done
1273 # 2.3.4 TAR (actually SPR #815)
1274 # 3.2.2 p45 XER (actually SPR #1) -- Done
1275 # 3.2.3 p46 p232 VRSAVE (actually SPR #256)
1277 # create CR then allow portions of it to be "selectable" (below)
1278 self
.cr_fields
= CRFields(initial_cr
)
1279 self
.cr
= self
.cr_fields
.cr
1280 self
.cr_backup
= 0 # sigh, dreadful hack: for fail-first (VLi)
1282 # "undefined", just set to variable-bit-width int (use exts "max")
1283 # self.undefined = SelectableInt(0, EFFECTIVELY_UNLIMITED)
1286 self
.namespace
.update(self
.spr
)
1287 self
.namespace
.update({'GPR': self
.gpr
,
1291 'memassign': self
.memassign
,
1294 'SVSTATE': self
.svstate
,
1295 'SVSHAPE0': self
.spr
['SVSHAPE0'],
1296 'SVSHAPE1': self
.spr
['SVSHAPE1'],
1297 'SVSHAPE2': self
.spr
['SVSHAPE2'],
1298 'SVSHAPE3': self
.spr
['SVSHAPE3'],
1301 'FPSCR': self
.fpscr
,
1302 'undefined': undefined
,
1303 'mode_is_64bit': True,
1304 'SO': XER_bits
['SO'],
1305 'XLEN': 64 # elwidth overrides
1308 for name
in BFP_FLAG_NAMES
:
1309 setattr(self
, name
, 0)
1311 # update pc to requested start point
1312 self
.set_pc(initial_pc
)
1314 # field-selectable versions of Condition Register
1315 self
.crl
= self
.cr_fields
.crl
1317 self
.namespace
["CR%d" % i
] = self
.crl
[i
]
1319 self
.decoder
= decoder2
.dec
1320 self
.dec2
= decoder2
1322 super().__init
__(XLEN
=self
.namespace
["XLEN"], FPSCR
=self
.fpscr
)
1324 def trace(self
, out
):
1325 if self
.insnlog
is None: return
1326 self
.insnlog
.write(out
)
1330 return self
.namespace
["XLEN"]
1336 def call_trap(self
, trap_addr
, trap_bit
):
1337 """calls TRAP and sets up NIA to the new execution location.
1338 next instruction will begin at trap_addr.
1340 self
.TRAP(trap_addr
, trap_bit
)
1341 self
.namespace
['NIA'] = self
.trap_nia
1342 self
.pc
.update(self
.namespace
, self
.is_svp64_mode
)
1344 def TRAP(self
, trap_addr
=0x700, trap_bit
=PIb
.TRAP
):
1345 """TRAP> saves PC, MSR (and TODO SVSTATE), and updates MSR
1347 TRAP function is callable from inside the pseudocode itself,
1348 hence the default arguments. when calling from inside ISACaller
1349 it is best to use call_trap()
1351 if isinstance(trap_addr
, SelectableInt
):
1352 trap_addr
= trap_addr
.value
1353 # https://bugs.libre-soc.org/show_bug.cgi?id=859
1354 kaivb
= self
.spr
['KAIVB'].value
1355 msr
= self
.namespace
['MSR'].value
1356 log("TRAP:", hex(trap_addr
), hex(msr
), "kaivb", hex(kaivb
))
1357 # store CIA(+4?) in SRR0, set NIA to 0x700
1358 # store MSR in SRR1, set MSR to um errr something, have to check spec
1359 # store SVSTATE (if enabled) in SVSRR0
1360 self
.spr
['SRR0'].value
= self
.pc
.CIA
.value
1361 self
.spr
['SRR1'].value
= msr
1362 if self
.is_svp64_mode
:
1363 self
.spr
['SVSRR0'] = self
.namespace
['SVSTATE'].value
1364 self
.trap_nia
= SelectableInt(trap_addr |
(kaivb
& ~
0x1fff), 64)
1365 self
.spr
['SRR1'][trap_bit
] = 1 # change *copy* of MSR in SRR1
1367 # set exception bits. TODO: this should, based on the address
1368 # in figure 66 p1065 V3.0B and the table figure 65 p1063 set these
1369 # bits appropriately. however it turns out that *for now* in all
1370 # cases (all trap_addrs) the exact same thing is needed.
1371 self
.msr
[MSRb
.IR
] = 0
1372 self
.msr
[MSRb
.DR
] = 0
1373 self
.msr
[MSRb
.FE0
] = 0
1374 self
.msr
[MSRb
.FE1
] = 0
1375 self
.msr
[MSRb
.EE
] = 0
1376 self
.msr
[MSRb
.RI
] = 0
1377 self
.msr
[MSRb
.SF
] = 1
1378 self
.msr
[MSRb
.TM
] = 0
1379 self
.msr
[MSRb
.VEC
] = 0
1380 self
.msr
[MSRb
.VSX
] = 0
1381 self
.msr
[MSRb
.PR
] = 0
1382 self
.msr
[MSRb
.FP
] = 0
1383 self
.msr
[MSRb
.PMM
] = 0
1384 self
.msr
[MSRb
.TEs
] = 0
1385 self
.msr
[MSRb
.TEe
] = 0
1386 self
.msr
[MSRb
.UND
] = 0
1387 self
.msr
[MSRb
.LE
] = 1
1389 def memassign(self
, ea
, sz
, val
):
1390 self
.mem
.memassign(ea
, sz
, val
)
1392 def prep_namespace(self
, insn_name
, formname
, op_fields
, xlen
):
1393 # TODO: get field names from form in decoder*1* (not decoder2)
1394 # decoder2 is hand-created, and decoder1.sigform is auto-generated
1396 # then "yield" fields only from op_fields rather than hard-coded
1398 fields
= self
.decoder
.sigforms
[formname
]
1399 log("prep_namespace", formname
, op_fields
, insn_name
)
1400 for name
in op_fields
:
1401 # CR immediates. deal with separately. needs modifying
1403 if self
.is_svp64_mode
and name
in ['BI']: # TODO, more CRs
1404 # BI is a 5-bit, must reconstruct the value
1405 regnum
, is_vec
= yield from get_cr_in(self
.dec2
, name
)
1406 sig
= getattr(fields
, name
)
1408 # low 2 LSBs (CR field selector) remain same, CR num extended
1409 assert regnum
<= 7, "sigh, TODO, 128 CR fields"
1410 val
= (val
& 0b11) |
(regnum
<< 2)
1411 elif self
.is_svp64_mode
and name
in ['BF']: # TODO, more CRs
1412 regnum
, is_vec
= yield from get_cr_out(self
.dec2
, "BF")
1413 log('hack %s' % name
, regnum
, is_vec
)
1416 sig
= getattr(fields
, name
)
1418 # these are all opcode fields involved in index-selection of CR,
1419 # and need to do "standard" arithmetic. CR[BA+32] for example
1420 # would, if using SelectableInt, only be 5-bit.
1421 if name
in ['BF', 'BFA', 'BC', 'BA', 'BB', 'BT', 'BI']:
1422 self
.namespace
[name
] = val
1424 self
.namespace
[name
] = SelectableInt(val
, sig
.width
)
1426 self
.namespace
['XER'] = self
.spr
['XER']
1427 self
.namespace
['CA'] = self
.spr
['XER'][XER_bits
['CA']].value
1428 self
.namespace
['CA32'] = self
.spr
['XER'][XER_bits
['CA32']].value
1429 self
.namespace
['OV'] = self
.spr
['XER'][XER_bits
['OV']].value
1430 self
.namespace
['OV32'] = self
.spr
['XER'][XER_bits
['OV32']].value
1431 self
.namespace
['XLEN'] = xlen
1433 # add some SVSTATE convenience variables
1434 vl
= self
.svstate
.vl
1435 srcstep
= self
.svstate
.srcstep
1436 self
.namespace
['VL'] = vl
1437 self
.namespace
['srcstep'] = srcstep
1439 # take a copy of the CR field value: if non-VLi fail-first fails
1440 # this is because the pseudocode writes *directly* to CR. sigh
1441 self
.cr_backup
= self
.cr
.value
1443 # sv.bc* need some extra fields
1444 if self
.is_svp64_mode
and insn_name
.startswith("sv.bc"):
1445 # blegh grab bits manually
1446 mode
= yield self
.dec2
.rm_dec
.rm_in
.mode
1447 # convert to SelectableInt before test
1448 mode
= SelectableInt(mode
, 5)
1449 bc_vlset
= mode
[SVP64MODEb
.BC_VLSET
] != 0
1450 bc_vli
= mode
[SVP64MODEb
.BC_VLI
] != 0
1451 bc_snz
= mode
[SVP64MODEb
.BC_SNZ
] != 0
1452 bc_vsb
= yield self
.dec2
.rm_dec
.bc_vsb
1453 bc_lru
= yield self
.dec2
.rm_dec
.bc_lru
1454 bc_gate
= yield self
.dec2
.rm_dec
.bc_gate
1455 sz
= yield self
.dec2
.rm_dec
.pred_sz
1456 self
.namespace
['mode'] = SelectableInt(mode
, 5)
1457 self
.namespace
['ALL'] = SelectableInt(bc_gate
, 1)
1458 self
.namespace
['VSb'] = SelectableInt(bc_vsb
, 1)
1459 self
.namespace
['LRu'] = SelectableInt(bc_lru
, 1)
1460 self
.namespace
['VLSET'] = SelectableInt(bc_vlset
, 1)
1461 self
.namespace
['VLI'] = SelectableInt(bc_vli
, 1)
1462 self
.namespace
['sz'] = SelectableInt(sz
, 1)
1463 self
.namespace
['SNZ'] = SelectableInt(bc_snz
, 1)
1465 def get_kludged_op_add_ca_ov(self
, inputs
, inp_ca_ov
):
1466 """ this was not at all necessary to do. this function massively
1467 duplicates - in a laborious and complex fashion - the contents of
1468 the CSV files that were extracted two years ago from microwatt's
1469 source code. A-inversion is the "inv A" column, output inversion
1470 is the "inv out" column, carry-in equal to 0 or 1 or CA is the
1473 all of that information is available in
1474 self.instrs[ins_name].op_fields
1475 where info is usually assigned to self.instrs[ins_name]
1477 https://git.libre-soc.org/?p=openpower-isa.git;a=blob;f=openpower/isatables/minor_31.csv;hb=HEAD
1479 the immediate constants are *also* decoded correctly and placed
1480 usually by DecodeIn2Imm into operand2, as part of power_decoder2.py
1482 def ca(a
, b
, ca_in
, width
):
1483 mask
= (1 << width
) - 1
1484 y
= (a
& mask
) + (b
& mask
) + ca_in
1487 asmcode
= yield self
.dec2
.dec
.op
.asmcode
1488 insn
= insns
.get(asmcode
)
1489 SI
= yield self
.dec2
.dec
.SI
1492 inputs
= [i
.value
for i
in inputs
]
1495 if insn
in ("add", "addo", "addc", "addco"):
1499 elif insn
== "addic" or insn
== "addic.":
1503 elif insn
in ("subf", "subfo", "subfc", "subfco"):
1507 elif insn
== "subfic":
1511 elif insn
== "adde" or insn
== "addeo":
1515 elif insn
== "subfe" or insn
== "subfeo":
1519 elif insn
== "addme" or insn
== "addmeo":
1523 elif insn
== "addze" or insn
== "addzeo":
1527 elif insn
== "subfme" or insn
== "subfmeo":
1531 elif insn
== "subfze" or insn
== "subfzeo":
1535 elif insn
== "addex":
1536 # CA[32] aren't actually written, just generate so we have
1537 # something to return
1538 ca64
= ov64
= ca(inputs
[0], inputs
[1], OV
, 64)
1539 ca32
= ov32
= ca(inputs
[0], inputs
[1], OV
, 32)
1540 return ca64
, ca32
, ov64
, ov32
1541 elif insn
== "neg" or insn
== "nego":
1546 raise NotImplementedError(
1547 "op_add kludge unimplemented instruction: ", asmcode
, insn
)
1549 ca64
= ca(a
, b
, ca_in
, 64)
1550 ca32
= ca(a
, b
, ca_in
, 32)
1551 ov64
= ca64
!= ca(a
, b
, ca_in
, 63)
1552 ov32
= ca32
!= ca(a
, b
, ca_in
, 31)
1553 return ca64
, ca32
, ov64
, ov32
1555 def handle_carry_(self
, inputs
, output
, ca
, ca32
, inp_ca_ov
):
1556 op
= yield self
.dec2
.e
.do
.insn_type
1557 if op
== MicrOp
.OP_ADD
.value
and ca
is None and ca32
is None:
1558 retval
= yield from self
.get_kludged_op_add_ca_ov(
1560 ca
, ca32
, ov
, ov32
= retval
1561 asmcode
= yield self
.dec2
.dec
.op
.asmcode
1562 if insns
.get(asmcode
) == 'addex':
1563 # TODO: if 32-bit mode, set ov to ov32
1564 self
.spr
['XER'][XER_bits
['OV']] = ov
1565 self
.spr
['XER'][XER_bits
['OV32']] = ov32
1566 log(f
"write OV/OV32 OV={ov} OV32={ov32}",
1567 kind
=LogKind
.InstrInOuts
)
1569 # TODO: if 32-bit mode, set ca to ca32
1570 self
.spr
['XER'][XER_bits
['CA']] = ca
1571 self
.spr
['XER'][XER_bits
['CA32']] = ca32
1572 log(f
"write CA/CA32 CA={ca} CA32={ca32}",
1573 kind
=LogKind
.InstrInOuts
)
1575 inv_a
= yield self
.dec2
.e
.do
.invert_in
1577 inputs
[0] = ~inputs
[0]
1579 imm_ok
= yield self
.dec2
.e
.do
.imm_data
.ok
1581 imm
= yield self
.dec2
.e
.do
.imm_data
.data
1582 inputs
.append(SelectableInt(imm
, 64))
1585 log("gt input", x
, output
)
1586 gt
= (gtu(x
, output
))
1589 cy
= 1 if any(gts
) else 0
1591 if ca
is None: # already written
1592 self
.spr
['XER'][XER_bits
['CA']] = cy
1595 # ARGH... different for OP_ADD... *sigh*...
1596 op
= yield self
.dec2
.e
.do
.insn_type
1597 if op
== MicrOp
.OP_ADD
.value
:
1598 res32
= (output
.value
& (1 << 32)) != 0
1599 a32
= (inputs
[0].value
& (1 << 32)) != 0
1600 if len(inputs
) >= 2:
1601 b32
= (inputs
[1].value
& (1 << 32)) != 0
1604 cy32
= res32 ^ a32 ^ b32
1605 log("CA32 ADD", cy32
)
1609 log("input", x
, output
)
1610 log(" x[32:64]", x
, x
[32:64])
1611 log(" o[32:64]", output
, output
[32:64])
1612 gt
= (gtu(x
[32:64], output
[32:64])) == SelectableInt(1, 1)
1614 cy32
= 1 if any(gts
) else 0
1615 log("CA32", cy32
, gts
)
1616 if ca32
is None: # already written
1617 self
.spr
['XER'][XER_bits
['CA32']] = cy32
1619 def handle_overflow(self
, inputs
, output
, div_overflow
, inp_ca_ov
):
1620 op
= yield self
.dec2
.e
.do
.insn_type
1621 if op
== MicrOp
.OP_ADD
.value
:
1622 retval
= yield from self
.get_kludged_op_add_ca_ov(
1624 ca
, ca32
, ov
, ov32
= retval
1625 # TODO: if 32-bit mode, set ov to ov32
1626 self
.spr
['XER'][XER_bits
['OV']] = ov
1627 self
.spr
['XER'][XER_bits
['OV32']] = ov32
1628 self
.spr
['XER'][XER_bits
['SO']] |
= ov
1630 if hasattr(self
.dec2
.e
.do
, "invert_in"):
1631 inv_a
= yield self
.dec2
.e
.do
.invert_in
1633 inputs
[0] = ~inputs
[0]
1635 imm_ok
= yield self
.dec2
.e
.do
.imm_data
.ok
1637 imm
= yield self
.dec2
.e
.do
.imm_data
.data
1638 inputs
.append(SelectableInt(imm
, 64))
1639 log("handle_overflow", inputs
, output
, div_overflow
)
1640 if len(inputs
) < 2 and div_overflow
is None:
1643 # div overflow is different: it's returned by the pseudo-code
1644 # because it's more complex than can be done by analysing the output
1645 if div_overflow
is not None:
1646 ov
, ov32
= div_overflow
, div_overflow
1647 # arithmetic overflow can be done by analysing the input and output
1648 elif len(inputs
) >= 2:
1650 input_sgn
= [exts(x
.value
, x
.bits
) < 0 for x
in inputs
]
1651 output_sgn
= exts(output
.value
, output
.bits
) < 0
1652 ov
= 1 if input_sgn
[0] == input_sgn
[1] and \
1653 output_sgn
!= input_sgn
[0] else 0
1656 input32_sgn
= [exts(x
.value
, 32) < 0 for x
in inputs
]
1657 output32_sgn
= exts(output
.value
, 32) < 0
1658 ov32
= 1 if input32_sgn
[0] == input32_sgn
[1] and \
1659 output32_sgn
!= input32_sgn
[0] else 0
1661 # now update XER OV/OV32/SO
1662 so
= self
.spr
['XER'][XER_bits
['SO']]
1663 new_so
= so | ov
# sticky overflow ORs in old with new
1664 self
.spr
['XER'][XER_bits
['OV']] = ov
1665 self
.spr
['XER'][XER_bits
['OV32']] = ov32
1666 self
.spr
['XER'][XER_bits
['SO']] = new_so
1667 log(" set overflow", ov
, ov32
, so
, new_so
)
1669 def handle_comparison(self
, out
, cr_idx
=0, overflow
=None, no_so
=False):
1670 assert isinstance(out
, SelectableInt
), \
1671 "out zero not a SelectableInt %s" % repr(outputs
)
1672 log("handle_comparison", out
.bits
, hex(out
.value
))
1673 # TODO - XXX *processor* in 32-bit mode
1674 # https://bugs.libre-soc.org/show_bug.cgi?id=424
1676 # o32 = exts(out.value, 32)
1677 # print ("handle_comparison exts 32 bit", hex(o32))
1678 out
= exts(out
.value
, out
.bits
)
1679 log("handle_comparison exts", hex(out
))
1680 # create the three main CR flags, EQ GT LT
1681 zero
= SelectableInt(out
== 0, 1)
1682 positive
= SelectableInt(out
> 0, 1)
1683 negative
= SelectableInt(out
< 0, 1)
1684 # get (or not) XER.SO. for setvl this is important *not* to read SO
1686 SO
= SelectableInt(1, 0)
1688 SO
= self
.spr
['XER'][XER_bits
['SO']]
1689 log("handle_comparison SO", SO
.value
,
1690 "overflow", overflow
,
1692 "+ve", positive
.value
,
1693 "-ve", negative
.value
)
1694 # alternative overflow checking (setvl mainly at the moment)
1695 if overflow
is not None and overflow
== 1:
1696 SO
= SelectableInt(1, 1)
1697 # create the four CR field values and set the required CR field
1698 cr_field
= selectconcat(negative
, positive
, zero
, SO
)
1699 log("handle_comparison cr_field", self
.cr
, cr_idx
, cr_field
)
1700 self
.crl
[cr_idx
].eq(cr_field
)
1702 def set_pc(self
, pc_val
):
1703 self
.namespace
['NIA'] = SelectableInt(pc_val
, 64)
1704 self
.pc
.update(self
.namespace
, self
.is_svp64_mode
)
1706 def get_next_insn(self
):
1707 """check instruction
1710 pc
= self
.pc
.CIA
.value
1713 ins
= self
.imem
.ld(pc
, 4, False, True, instr_fetch
=True)
1715 raise KeyError("no instruction at 0x%x" % pc
)
1718 def setup_one(self
):
1719 """set up one instruction
1721 pc
, insn
= self
.get_next_insn()
1722 yield from self
.setup_next_insn(pc
, insn
)
1724 # cache since it's really slow to construct
1725 __PREFIX_CACHE
= SVP64Instruction
.Prefix(SelectableInt(value
=0, bits
=32))
1727 def __decode_prefix(self
, opcode
):
1728 pfx
= self
.__PREFIX
_CACHE
1729 pfx
.storage
.eq(opcode
)
1732 def setup_next_insn(self
, pc
, ins
):
1733 """set up next instruction
1736 log("setup: 0x%x 0x%x %s" % (pc
, ins
& 0xffffffff, bin(ins
)))
1737 log("CIA NIA", self
.respect_pc
, self
.pc
.CIA
.value
, self
.pc
.NIA
.value
)
1739 yield self
.dec2
.sv_rm
.eq(0)
1740 yield self
.dec2
.dec
.raw_opcode_in
.eq(ins
& 0xffffffff)
1741 yield self
.dec2
.dec
.bigendian
.eq(self
.bigendian
)
1742 yield self
.dec2
.state
.msr
.eq(self
.msr
.value
)
1743 yield self
.dec2
.state
.pc
.eq(pc
)
1744 if self
.svstate
is not None:
1745 yield self
.dec2
.state
.svstate
.eq(self
.svstate
.value
)
1747 # SVP64. first, check if the opcode is EXT001, and SVP64 id bits set
1749 opcode
= yield self
.dec2
.dec
.opcode_in
1750 opcode
= SelectableInt(value
=opcode
, bits
=32)
1751 pfx
= self
.__decode
_prefix
(opcode
)
1752 log("prefix test: opcode:", pfx
.PO
, bin(pfx
.PO
), pfx
.id)
1753 self
.is_svp64_mode
= bool((pfx
.PO
== 0b000001) and (pfx
.id == 0b11))
1754 self
.pc
.update_nia(self
.is_svp64_mode
)
1756 yield self
.dec2
.is_svp64_mode
.eq(self
.is_svp64_mode
)
1757 self
.namespace
['NIA'] = self
.pc
.NIA
1758 self
.namespace
['SVSTATE'] = self
.svstate
1759 if not self
.is_svp64_mode
:
1762 # in SVP64 mode. decode/print out svp64 prefix, get v3.0B instruction
1763 log("svp64.rm", bin(pfx
.rm
))
1764 log(" svstate.vl", self
.svstate
.vl
)
1765 log(" svstate.mvl", self
.svstate
.maxvl
)
1766 ins
= self
.imem
.ld(pc
+4, 4, False, True, instr_fetch
=True)
1767 log(" svsetup: 0x%x 0x%x %s" % (pc
+4, ins
& 0xffffffff, bin(ins
)))
1768 yield self
.dec2
.dec
.raw_opcode_in
.eq(ins
& 0xffffffff) # v3.0B suffix
1769 yield self
.dec2
.sv_rm
.eq(int(pfx
.rm
)) # svp64 prefix
1772 def execute_one(self
):
1773 """execute one instruction
1775 # get the disassembly code for this instruction
1776 if not self
.disassembly
:
1777 code
= yield from self
.get_assembly_name()
1780 if self
.is_svp64_mode
:
1781 offs
, dbg
= 4, "svp64 "
1782 code
= self
.disassembly
[self
._pc
+offs
]
1783 log(" %s sim-execute" % dbg
, hex(self
._pc
), code
)
1784 opname
= code
.split(' ')[0]
1786 yield from self
.call(opname
) # execute the instruction
1787 except MemException
as e
: # check for memory errors
1788 if e
.args
[0] == 'unaligned': # alignment error
1789 # run a Trap but set DAR first
1790 print("memory unaligned exception, DAR", e
.dar
, repr(e
))
1791 self
.spr
['DAR'] = SelectableInt(e
.dar
, 64)
1792 self
.call_trap(0x600, PIb
.PRIV
) # 0x600, privileged
1794 elif e
.args
[0] == 'invalid': # invalid
1795 # run a Trap but set DAR first
1796 log("RADIX MMU memory invalid error, mode %s" % e
.mode
)
1797 if e
.mode
== 'EXECUTE':
1798 # XXX TODO: must set a few bits in SRR1,
1799 # see microwatt loadstore1.vhdl
1800 # if m_in.segerr = '0' then
1801 # v.srr1(47 - 33) := m_in.invalid;
1802 # v.srr1(47 - 35) := m_in.perm_error; -- noexec fault
1803 # v.srr1(47 - 44) := m_in.badtree;
1804 # v.srr1(47 - 45) := m_in.rc_error;
1805 # v.intr_vec := 16#400#;
1807 # v.intr_vec := 16#480#;
1808 self
.call_trap(0x400, PIb
.PRIV
) # 0x400, privileged
1810 self
.call_trap(0x300, PIb
.PRIV
) # 0x300, privileged
1812 # not supported yet:
1813 raise e
# ... re-raise
1815 # append to the trace log file
1816 self
.trace(" # %s\n" % code
)
1818 log("gprs after code", code
)
1821 for i
in range(len(self
.crl
)):
1822 crs
.append(bin(self
.crl
[i
].asint()))
1823 log("crs", " ".join(crs
))
1824 log("vl,maxvl", self
.svstate
.vl
, self
.svstate
.maxvl
)
1826 # don't use this except in special circumstances
1827 if not self
.respect_pc
:
1830 log("execute one, CIA NIA", hex(self
.pc
.CIA
.value
),
1831 hex(self
.pc
.NIA
.value
))
1833 def get_assembly_name(self
):
1834 # TODO, asmregs is from the spec, e.g. add RT,RA,RB
1835 # see http://bugs.libre-riscv.org/show_bug.cgi?id=282
1836 dec_insn
= yield self
.dec2
.e
.do
.insn
1837 insn_1_11
= yield self
.dec2
.e
.do
.insn
[1:11]
1838 asmcode
= yield self
.dec2
.dec
.op
.asmcode
1839 int_op
= yield self
.dec2
.dec
.op
.internal_op
1840 log("get assembly name asmcode", asmcode
, int_op
,
1841 hex(dec_insn
), bin(insn_1_11
))
1842 asmop
= insns
.get(asmcode
, None)
1844 # sigh reconstruct the assembly instruction name
1845 if hasattr(self
.dec2
.e
.do
, "oe"):
1846 ov_en
= yield self
.dec2
.e
.do
.oe
.oe
1847 ov_ok
= yield self
.dec2
.e
.do
.oe
.ok
1851 if hasattr(self
.dec2
.e
.do
, "rc"):
1852 rc_en
= yield self
.dec2
.e
.do
.rc
.rc
1853 rc_ok
= yield self
.dec2
.e
.do
.rc
.ok
1857 # annoying: ignore rc_ok if RC1 is set (for creating *assembly name*)
1858 RC1
= yield self
.dec2
.rm_dec
.RC1
1862 # grrrr have to special-case MUL op (see DecodeOE)
1863 log("ov %d en %d rc %d en %d op %d" %
1864 (ov_ok
, ov_en
, rc_ok
, rc_en
, int_op
))
1865 if int_op
in [MicrOp
.OP_MUL_H64
.value
, MicrOp
.OP_MUL_H32
.value
]:
1870 if not asmop
.endswith("."): # don't add "." to "andis."
1873 if hasattr(self
.dec2
.e
.do
, "lk"):
1874 lk
= yield self
.dec2
.e
.do
.lk
1877 log("int_op", int_op
)
1878 if int_op
in [MicrOp
.OP_B
.value
, MicrOp
.OP_BC
.value
]:
1879 AA
= yield self
.dec2
.dec
.fields
.FormI
.AA
[0:-1]
1883 spr_msb
= yield from self
.get_spr_msb()
1884 if int_op
== MicrOp
.OP_MFCR
.value
:
1889 # XXX TODO: for whatever weird reason this doesn't work
1890 # https://bugs.libre-soc.org/show_bug.cgi?id=390
1891 if int_op
== MicrOp
.OP_MTCRF
.value
:
1898 def reset_remaps(self
):
1899 self
.remap_loopends
= [0] * 4
1900 self
.remap_idxs
= [0, 1, 2, 3]
1902 def get_remap_indices(self
):
1903 """WARNING, this function stores remap_idxs and remap_loopends
1904 in the class for later use. this to avoid problems with yield
1906 # go through all iterators in lock-step, advance to next remap_idx
1907 srcstep
, dststep
, ssubstep
, dsubstep
= self
.get_src_dststeps()
1908 # get four SVSHAPEs. here we are hard-coding
1910 SVSHAPE0
= self
.spr
['SVSHAPE0']
1911 SVSHAPE1
= self
.spr
['SVSHAPE1']
1912 SVSHAPE2
= self
.spr
['SVSHAPE2']
1913 SVSHAPE3
= self
.spr
['SVSHAPE3']
1914 # set up the iterators
1915 remaps
= [(SVSHAPE0
, SVSHAPE0
.get_iterator()),
1916 (SVSHAPE1
, SVSHAPE1
.get_iterator()),
1917 (SVSHAPE2
, SVSHAPE2
.get_iterator()),
1918 (SVSHAPE3
, SVSHAPE3
.get_iterator()),
1922 for i
, (shape
, remap
) in enumerate(remaps
):
1923 # zero is "disabled"
1924 if shape
.value
== 0x0:
1925 self
.remap_idxs
[i
] = 0
1926 # pick src or dststep depending on reg num (0-2=in, 3-4=out)
1927 step
= dststep
if (i
in [3, 4]) else srcstep
1928 # this is terrible. O(N^2) looking for the match. but hey.
1929 for idx
, (remap_idx
, loopends
) in enumerate(remap
):
1932 self
.remap_idxs
[i
] = remap_idx
1933 self
.remap_loopends
[i
] = loopends
1934 dbg
.append((i
, step
, remap_idx
, loopends
))
1935 for (i
, step
, remap_idx
, loopends
) in dbg
:
1936 log("SVSHAPE %d idx, end" % i
, step
, remap_idx
, bin(loopends
))
1939 def get_spr_msb(self
):
1940 dec_insn
= yield self
.dec2
.e
.do
.insn
1941 return dec_insn
& (1 << 20) != 0 # sigh - XFF.spr[-1]?
1943 def call(self
, name
, syscall_emu_active
=False):
1944 """call(opcode) - the primary execution point for instructions
1946 self
.last_st_addr
= None # reset the last known store address
1947 self
.last_ld_addr
= None # etc.
1949 ins_name
= name
.strip() # remove spaces if not already done so
1951 log("halted - not executing", ins_name
)
1954 # TODO, asmregs is from the spec, e.g. add RT,RA,RB
1955 # see http://bugs.libre-riscv.org/show_bug.cgi?id=282
1956 asmop
= yield from self
.get_assembly_name()
1957 log("call", ins_name
, asmop
,
1958 kind
=LogKind
.InstrInOuts
)
1960 # sv.setvl is *not* a loop-function. sigh
1961 log("is_svp64_mode", self
.is_svp64_mode
, asmop
)
1964 int_op
= yield self
.dec2
.dec
.op
.internal_op
1965 spr_msb
= yield from self
.get_spr_msb()
1967 instr_is_privileged
= False
1968 if int_op
in [MicrOp
.OP_ATTN
.value
,
1969 MicrOp
.OP_MFMSR
.value
,
1970 MicrOp
.OP_MTMSR
.value
,
1971 MicrOp
.OP_MTMSRD
.value
,
1973 MicrOp
.OP_RFID
.value
]:
1974 instr_is_privileged
= True
1975 if int_op
in [MicrOp
.OP_MFSPR
.value
,
1976 MicrOp
.OP_MTSPR
.value
] and spr_msb
:
1977 instr_is_privileged
= True
1979 log("is priv", instr_is_privileged
, hex(self
.msr
.value
),
1981 # check MSR priv bit and whether op is privileged: if so, throw trap
1982 if instr_is_privileged
and self
.msr
[MSRb
.PR
] == 1:
1983 self
.call_trap(0x700, PIb
.PRIV
)
1986 # check halted condition
1987 if ins_name
== 'attn':
1991 # User mode system call emulation consists of several steps:
1992 # 1. Detect whether instruction is sc or scv.
1993 # 2. Call the HDL implementation which invokes trap.
1994 # 3. Reroute the guest system call to host system call.
1995 # 4. Force return from the interrupt as if we had guest OS.
1996 if ((asmop
in ("sc", "scv")) and
1997 (self
.syscall
is not None) and
1998 not syscall_emu_active
):
1999 # Memoize PC and trigger an interrupt
2001 pc
= self
.pc
.CIA
.value
2004 yield from self
.call(asmop
, syscall_emu_active
=True)
2006 # Reroute the syscall to host OS
2007 identifier
= self
.gpr(0)
2008 arguments
= map(self
.gpr
, range(3, 9))
2009 result
= self
.syscall(identifier
, *arguments
)
2010 self
.gpr
.write(3, result
, False, self
.namespace
["XLEN"])
2012 # Return from interrupt
2013 backup
= self
.imem
.ld(pc
, 4, False, True, instr_fetch
=True)
2014 self
.imem
.st(pc
, 0x4c000024, width
=4, swap
=True)
2015 yield from self
.call("rfid", syscall_emu_active
=True)
2016 self
.imem
.st(pc
, backup
, width
=4, swap
=True)
2017 elif ((name
in ("rfid", "hrfid")) and syscall_emu_active
):
2020 # check illegal instruction
2022 if ins_name
not in ['mtcrf', 'mtocrf']:
2023 illegal
= ins_name
!= asmop
2025 # list of instructions not being supported by binutils (.long)
2026 dotstrp
= asmop
[:-1] if asmop
[-1] == '.' else asmop
2027 if dotstrp
in [*FPTRANS_INSNS
,
2029 'ffmadds', 'fdmadds', 'ffadds',
2031 "brh", "brw", "brd",
2032 'setvl', 'svindex', 'svremap', 'svstep',
2033 'svshape', 'svshape2',
2034 'ternlogi', 'bmask', 'cprop',
2035 'absdu', 'absds', 'absdacs', 'absdacu', 'avgadd',
2036 'fmvis', 'fishmv', 'pcdec', "maddedu", "divmod2du",
2037 "dsld", "dsrd", "maddedus",
2038 "sadd", "saddw", "sadduw",
2043 "maddsubrs", "maddrs", "msubrs",
2044 "cfuged", "cntlzdm", "cnttzdm", "pdepd", "pextd",
2045 "setbc", "setbcr", "setnbc", "setnbcr",
2050 # branch-conditional redirects to sv.bc
2051 if asmop
.startswith('bc') and self
.is_svp64_mode
:
2052 ins_name
= 'sv.%s' % ins_name
2054 # ld-immediate-with-pi mode redirects to ld-with-postinc
2055 ldst_imm_postinc
= False
2056 if 'u' in ins_name
and self
.is_svp64_mode
:
2057 ldst_pi
= yield self
.dec2
.rm_dec
.ldst_postinc
2059 ins_name
= ins_name
.replace("u", "up")
2060 ldst_imm_postinc
= True
2061 log(" enable ld/st postinc", ins_name
)
2063 log(" post-processed name", dotstrp
, ins_name
, asmop
)
2065 # illegal instructions call TRAP at 0x700
2067 print("illegal", ins_name
, asmop
)
2068 self
.call_trap(0x700, PIb
.ILLEG
)
2069 print("name %s != %s - calling ILLEGAL trap, PC: %x" %
2070 (ins_name
, asmop
, self
.pc
.CIA
.value
))
2073 # this is for setvl "Vertical" mode: if set true,
2074 # srcstep/dststep is explicitly advanced. mode says which SVSTATE to
2075 # test for Rc=1 end condition. 3 bits of all 3 loops are put into CR0
2076 self
.allow_next_step_inc
= False
2077 self
.svstate_next_mode
= 0
2079 # nop has to be supported, we could let the actual op calculate
2080 # but PowerDecoder has a pattern for nop
2081 if ins_name
== 'nop':
2082 self
.update_pc_next()
2085 # get elwidths, defaults to 64
2089 if self
.is_svp64_mode
:
2090 ew_src
= yield self
.dec2
.rm_dec
.ew_src
2091 ew_dst
= yield self
.dec2
.rm_dec
.ew_dst
2092 ew_src
= 8 << (3-int(ew_src
)) # convert to bitlength
2093 ew_dst
= 8 << (3-int(ew_dst
)) # convert to bitlength
2094 xlen
= max(ew_src
, ew_dst
)
2095 log("elwdith", ew_src
, ew_dst
)
2096 log("XLEN:", self
.is_svp64_mode
, xlen
)
2098 # look up instruction in ISA.instrs, prepare namespace
2099 if ins_name
== 'pcdec': # grrrr yes there are others ("stbcx." etc.)
2100 info
= self
.instrs
[ins_name
+"."]
2101 elif asmop
[-1] == '.' and asmop
in self
.instrs
:
2102 info
= self
.instrs
[asmop
]
2104 info
= self
.instrs
[ins_name
]
2105 yield from self
.prep_namespace(ins_name
, info
.form
, info
.op_fields
,
2108 # preserve order of register names
2109 input_names
= create_args(list(info
.read_regs
) +
2110 list(info
.uninit_regs
))
2111 log("input names", input_names
)
2113 # get SVP64 entry for the current instruction
2114 sv_rm
= self
.svp64rm
.instrs
.get(ins_name
)
2115 if sv_rm
is not None:
2116 dest_cr
, src_cr
, src_byname
, dest_byname
= decode_extra(sv_rm
)
2118 dest_cr
, src_cr
, src_byname
, dest_byname
= False, False, {}, {}
2119 log("sv rm", sv_rm
, dest_cr
, src_cr
, src_byname
, dest_byname
)
2121 # see if srcstep/dststep need skipping over masked-out predicate bits
2122 # svstep also needs advancement because it calls SVSTATE_NEXT.
2123 # bit the remaps get computed just after pre_inc moves them on
2124 # with remap_set_steps substituting for PowerDecider2 not doing it,
2125 # and SVSTATE_NEXT not being able to.use yield, the preinc on
2126 # svstep is necessary for now.
2128 if (self
.is_svp64_mode
or ins_name
in ['svstep']):
2129 yield from self
.svstate_pre_inc()
2130 if self
.is_svp64_mode
:
2131 pre
= yield from self
.update_new_svstate_steps()
2133 self
.svp64_reset_loop()
2135 self
.update_pc_next()
2137 srcstep
, dststep
, ssubstep
, dsubstep
= self
.get_src_dststeps()
2138 pred_dst_zero
= self
.pred_dst_zero
2139 pred_src_zero
= self
.pred_src_zero
2140 vl
= self
.svstate
.vl
2141 subvl
= yield self
.dec2
.rm_dec
.rm_in
.subvl
2143 # VL=0 in SVP64 mode means "do nothing: skip instruction"
2144 if self
.is_svp64_mode
and vl
== 0:
2145 self
.pc
.update(self
.namespace
, self
.is_svp64_mode
)
2146 log("SVP64: VL=0, end of call", self
.namespace
['CIA'],
2147 self
.namespace
['NIA'], kind
=LogKind
.InstrInOuts
)
2150 # for when SVREMAP is active, using pre-arranged schedule.
2151 # note: modifying PowerDecoder2 needs to "settle"
2152 remap_en
= self
.svstate
.SVme
2153 persist
= self
.svstate
.RMpst
2154 active
= (persist
or self
.last_op_svshape
) and remap_en
!= 0
2155 if self
.is_svp64_mode
:
2156 yield self
.dec2
.remap_active
.eq(remap_en
if active
else 0)
2158 if persist
or self
.last_op_svshape
:
2159 remaps
= self
.get_remap_indices()
2160 if self
.is_svp64_mode
and (persist
or self
.last_op_svshape
):
2161 yield from self
.remap_set_steps(remaps
)
2162 # after that, settle down (combinatorial) to let Vector reg numbers
2163 # work themselves out
2165 if self
.is_svp64_mode
:
2166 remap_active
= yield self
.dec2
.remap_active
2168 remap_active
= False
2169 log("remap active", bin(remap_active
))
2171 # main input registers (RT, RA ...)
2173 for name
in input_names
:
2174 regval
= (yield from self
.get_input(name
, ew_src
))
2175 log("regval name", name
, regval
)
2176 inputs
.append(regval
)
2178 # arrrrgh, awful hack, to get _RT into namespace
2179 if ins_name
in ['setvl', 'svstep']:
2181 RT
= yield self
.dec2
.dec
.RT
2182 self
.namespace
[regname
] = SelectableInt(RT
, 5)
2184 self
.namespace
["RT"] = SelectableInt(0, 5)
2185 regnum
, is_vec
= yield from get_idx_out(self
.dec2
, "RT")
2186 log('hack input reg %s %s' % (name
, str(regnum
)), is_vec
)
2188 # in SVP64 mode for LD/ST work out immediate
2189 # XXX TODO: replace_ds for DS-Form rather than D-Form.
2190 # use info.form to detect
2191 if self
.is_svp64_mode
and not ldst_imm_postinc
:
2192 yield from self
.check_replace_d(info
, remap_active
)
2194 # "special" registers
2195 for special
in info
.special_regs
:
2196 if special
in special_sprs
:
2197 inputs
.append(self
.spr
[special
])
2199 inputs
.append(self
.namespace
[special
])
2201 # clear trap (trap) NIA
2202 self
.trap_nia
= None
2204 # check if this was an sv.bc* and create an indicator that
2205 # this is the last check to be made as a loop. combined with
2206 # the ALL/ANY mode we can early-exit
2207 if self
.is_svp64_mode
and ins_name
.startswith("sv.bc"):
2208 no_in_vec
= yield self
.dec2
.no_in_vec
# BI is scalar
2209 end_loop
= no_in_vec
or srcstep
== vl
-1 or dststep
== vl
-1
2210 self
.namespace
['end_loop'] = SelectableInt(end_loop
, 1)
2212 inp_ca_ov
= (self
.spr
['XER'][XER_bits
['CA']].value
,
2213 self
.spr
['XER'][XER_bits
['OV']].value
)
2215 # execute actual instruction here (finally)
2216 log("inputs", inputs
)
2217 results
= info
.func(self
, *inputs
)
2218 output_names
= create_args(info
.write_regs
)
2220 for out
, n
in zip(results
or [], output_names
):
2222 log("results", outs
)
2224 # "inject" decorator takes namespace from function locals: we need to
2225 # overwrite NIA being overwritten (sigh)
2226 if self
.trap_nia
is not None:
2227 self
.namespace
['NIA'] = self
.trap_nia
2229 log("after func", self
.namespace
['CIA'], self
.namespace
['NIA'])
2231 # check if op was a LD/ST so that debugging can check the
2233 if int_op
in [MicrOp
.OP_STORE
.value
,
2235 self
.last_st_addr
= self
.mem
.last_st_addr
2236 if int_op
in [MicrOp
.OP_LOAD
.value
,
2238 self
.last_ld_addr
= self
.mem
.last_ld_addr
2239 log("op", int_op
, MicrOp
.OP_STORE
.value
, MicrOp
.OP_LOAD
.value
,
2240 self
.last_st_addr
, self
.last_ld_addr
)
2242 # detect if CA/CA32 already in outputs (sra*, basically)
2244 ca32
= outs
.get("CA32")
2246 log("carry already done?", ca
, ca32
, output_names
)
2247 # soc test_pipe_caller tests don't have output_carry
2248 has_output_carry
= hasattr(self
.dec2
.e
.do
, "output_carry")
2249 carry_en
= has_output_carry
and (yield self
.dec2
.e
.do
.output_carry
)
2251 yield from self
.handle_carry_(
2252 inputs
, results
[0], ca
, ca32
, inp_ca_ov
=inp_ca_ov
)
2254 # get output named "overflow" and "CR0"
2255 overflow
= outs
.get('overflow')
2256 cr0
= outs
.get('CR0')
2257 cr1
= outs
.get('CR1')
2259 # soc test_pipe_caller tests don't have oe
2260 has_oe
= hasattr(self
.dec2
.e
.do
, "oe")
2261 # yeah just no. not in parallel processing
2262 if has_oe
and not self
.is_svp64_mode
:
2263 # detect if overflow was in return result
2264 ov_en
= yield self
.dec2
.e
.do
.oe
.oe
2265 ov_ok
= yield self
.dec2
.e
.do
.oe
.ok
2266 log("internal overflow", ins_name
, overflow
, "en?", ov_en
, ov_ok
)
2268 yield from self
.handle_overflow(
2269 inputs
, results
[0], overflow
, inp_ca_ov
=inp_ca_ov
)
2271 # only do SVP64 dest predicated Rc=1 if dest-pred is not enabled
2273 if not self
.is_svp64_mode
or not pred_dst_zero
:
2274 if hasattr(self
.dec2
.e
.do
, "rc"):
2275 rc_en
= yield self
.dec2
.e
.do
.rc
.rc
2276 # don't do Rc=1 for svstep it is handled explicitly.
2277 # XXX TODO: now that CR0 is supported, sort out svstep's pseudocode
2278 # to write directly to CR0 instead of in ISACaller. hooyahh.
2279 if rc_en
and ins_name
not in ['svstep']:
2280 yield from self
.do_rc_ov(
2281 ins_name
, results
[0], overflow
, cr0
, cr1
, output_names
)
2284 ffirst_hit
= False, False
2285 if self
.is_svp64_mode
:
2286 sv_mode
= yield self
.dec2
.rm_dec
.sv_mode
2287 is_cr
= sv_mode
== SVMode
.CROP
.value
2288 chk
= rc_en
or is_cr
2289 ffirst_hit
= (yield from self
.check_ffirst(info
, chk
, srcstep
))
2291 # check if a FP Exception occurred. TODO for DD-FFirst, check VLi
2292 # and raise the exception *after* if VLi=1 but if VLi=0 then
2293 # truncate and make the exception "disappear".
2294 if self
.FPSCR
.FEX
and (self
.msr
[MSRb
.FE0
] or self
.msr
[MSRb
.FE1
]):
2295 self
.call_trap(0x700, PIb
.FP
)
2298 # any modified return results?
2299 yield from self
.do_outregs_nia(asmop
, ins_name
, info
, outs
,
2300 carry_en
, rc_en
, ffirst_hit
, ew_dst
)
2302 def check_ffirst(self
, info
, rc_en
, srcstep
):
2303 """fail-first mode: checks a bit of Rc Vector, truncates VL
2305 rm_mode
= yield self
.dec2
.rm_dec
.mode
2306 ff_inv
= yield self
.dec2
.rm_dec
.inv
2307 cr_bit
= yield self
.dec2
.rm_dec
.cr_sel
2308 RC1
= yield self
.dec2
.rm_dec
.RC1
2309 vli_
= yield self
.dec2
.rm_dec
.vli
# VL inclusive if truncated
2310 log(" ff rm_mode", rc_en
, rm_mode
, SVP64RMMode
.FFIRST
.value
)
2314 log(" cr_bit", cr_bit
)
2315 log(" rc_en", rc_en
)
2316 if not rc_en
or rm_mode
!= SVP64RMMode
.FFIRST
.value
:
2318 # get the CR vevtor, do BO-test
2320 log("asmregs", info
.asmregs
[0], info
.write_regs
)
2321 if 'CR' in info
.write_regs
and 'BF' in info
.asmregs
[0]:
2323 regnum
, is_vec
= yield from get_cr_out(self
.dec2
, crf
)
2324 crtest
= self
.crl
[regnum
]
2325 ffirst_hit
= crtest
[cr_bit
] != ff_inv
2326 log("cr test", crf
, regnum
, int(crtest
), crtest
, cr_bit
, ff_inv
)
2327 log("cr test?", ffirst_hit
)
2330 # Fail-first activated, truncate VL
2331 vli
= SelectableInt(int(vli_
), 7)
2332 self
.svstate
.vl
= srcstep
+ vli
2333 yield self
.dec2
.state
.svstate
.eq(self
.svstate
.value
)
2334 yield Settle() # let decoder update
2337 def do_rc_ov(self
, ins_name
, result
, overflow
, cr0
, cr1
, output_names
):
2338 cr_out
= yield self
.dec2
.op
.cr_out
2339 if cr_out
== CROutSel
.CR1
.value
:
2343 regnum
, is_vec
= yield from get_cr_out(self
.dec2
, rc_reg
)
2344 # hang on... for `setvl` actually you want to test SVSTATE.VL
2345 is_setvl
= ins_name
in ('svstep', 'setvl')
2347 result
= SelectableInt(result
.vl
, 64)
2349 # overflow = None # do not override overflow except in setvl
2353 cr1
= int(self
.FPSCR
.FX
) << 3
2354 cr1 |
= int(self
.FPSCR
.FEX
) << 2
2355 cr1 |
= int(self
.FPSCR
.VX
) << 1
2356 cr1 |
= int(self
.FPSCR
.OX
)
2357 log("default fp cr1", cr1
)
2359 log("explicit cr1", cr1
)
2360 self
.crl
[regnum
].eq(cr1
)
2362 # if there was not an explicit CR0 in the pseudocode,
2364 self
.handle_comparison(result
, regnum
, overflow
, no_so
=is_setvl
)
2366 # otherwise we just blat CR0 into the required regnum
2367 log("explicit rc0", cr0
)
2368 self
.crl
[regnum
].eq(cr0
)
2370 def do_outregs_nia(self
, asmop
, ins_name
, info
, outs
,
2371 ca_en
, rc_en
, ffirst_hit
, ew_dst
):
2372 ffirst_hit
, vli
= ffirst_hit
2373 # write out any regs for this instruction, but only if fail-first is ok
2374 # XXX TODO: allow CR-vector to be written out even if ffirst fails
2375 if not ffirst_hit
or vli
:
2376 for name
, output
in outs
.items():
2377 yield from self
.check_write(info
, name
, output
, ca_en
, ew_dst
)
2378 # restore the CR value on non-VLI failfirst (from sv.cmp and others
2379 # which write directly to CR in the pseudocode (gah, what a mess)
2380 # if ffirst_hit and not vli:
2381 # self.cr.value = self.cr_backup
2384 self
.svp64_reset_loop()
2387 # check advancement of src/dst/sub-steps and if PC needs updating
2388 nia_update
= (yield from self
.check_step_increment(rc_en
,
2391 self
.update_pc_next()
2393 def check_replace_d(self
, info
, remap_active
):
2394 replace_d
= False # update / replace constant in pseudocode
2395 ldstmode
= yield self
.dec2
.rm_dec
.ldstmode
2396 vl
= self
.svstate
.vl
2397 subvl
= yield self
.dec2
.rm_dec
.rm_in
.subvl
2398 srcstep
, dststep
= self
.new_srcstep
, self
.new_dststep
2399 ssubstep
, dsubstep
= self
.new_ssubstep
, self
.new_dsubstep
2400 if info
.form
== 'DS':
2401 # DS-Form, multiply by 4 then knock 2 bits off after
2402 imm
= yield self
.dec2
.dec
.fields
.FormDS
.DS
[0:14] * 4
2404 imm
= yield self
.dec2
.dec
.fields
.FormD
.D
[0:16]
2405 imm
= exts(imm
, 16) # sign-extend to integer
2406 # get the right step. LD is from srcstep, ST is dststep
2407 op
= yield self
.dec2
.e
.do
.insn_type
2409 if op
== MicrOp
.OP_LOAD
.value
:
2411 offsmul
= yield self
.dec2
.in1_step
2412 log("D-field REMAP src", imm
, offsmul
, ldstmode
)
2414 offsmul
= (srcstep
* (subvl
+1)) + ssubstep
2415 log("D-field src", imm
, offsmul
, ldstmode
)
2416 elif op
== MicrOp
.OP_STORE
.value
:
2417 # XXX NOTE! no bit-reversed STORE! this should not ever be used
2418 offsmul
= (dststep
* (subvl
+1)) + dsubstep
2419 log("D-field dst", imm
, offsmul
, ldstmode
)
2420 # Unit-Strided LD/ST adds offset*width to immediate
2421 if ldstmode
== SVP64LDSTmode
.UNITSTRIDE
.value
:
2422 ldst_len
= yield self
.dec2
.e
.do
.data_len
2423 imm
= SelectableInt(imm
+ offsmul
* ldst_len
, 32)
2425 # Element-strided multiplies the immediate by element step
2426 elif ldstmode
== SVP64LDSTmode
.ELSTRIDE
.value
:
2427 imm
= SelectableInt(imm
* offsmul
, 32)
2430 ldst_ra_vec
= yield self
.dec2
.rm_dec
.ldst_ra_vec
2431 ldst_imz_in
= yield self
.dec2
.rm_dec
.ldst_imz_in
2432 log("LDSTmode", SVP64LDSTmode(ldstmode
),
2433 offsmul
, imm
, ldst_ra_vec
, ldst_imz_in
)
2434 # new replacement D... errr.. DS
2436 if info
.form
== 'DS':
2437 # TODO: assert 2 LSBs are zero?
2438 log("DS-Form, TODO, assert 2 LSBs zero?", bin(imm
.value
))
2439 imm
.value
= imm
.value
>> 2
2440 self
.namespace
['DS'] = imm
2442 self
.namespace
['D'] = imm
2444 def get_input(self
, name
, ew_src
):
2445 # using PowerDecoder2, first, find the decoder index.
2446 # (mapping name RA RB RC RS to in1, in2, in3)
2447 regnum
, is_vec
= yield from get_idx_in(self
.dec2
, name
, True)
2449 # doing this is not part of svp64, it's because output
2450 # registers, to be modified, need to be in the namespace.
2451 regnum
, is_vec
= yield from get_idx_out(self
.dec2
, name
, True)
2453 regnum
, is_vec
= yield from get_idx_out2(self
.dec2
, name
, True)
2455 if isinstance(regnum
, tuple):
2456 (regnum
, base
, offs
) = regnum
2458 base
, offs
= regnum
, 0 # temporary HACK
2460 # in case getting the register number is needed, _RA, _RB
2461 # (HACK: only in straight non-svp64-mode for now, or elwidth == 64)
2462 regname
= "_" + name
2463 if not self
.is_svp64_mode
or ew_src
== 64:
2464 self
.namespace
[regname
] = regnum
2465 elif regname
in self
.namespace
:
2466 del self
.namespace
[regname
]
2468 if not self
.is_svp64_mode
or not self
.pred_src_zero
:
2469 log('reading reg %s %s' % (name
, str(regnum
)), is_vec
)
2471 reg_val
= SelectableInt(self
.fpr(base
, is_vec
, offs
, ew_src
))
2472 log("read reg %d/%d: 0x%x" % (base
, offs
, reg_val
.value
),
2473 kind
=LogKind
.InstrInOuts
)
2474 self
.trace("r:FPR:%d:%d:%d " % (base
, offs
, ew_src
))
2475 elif name
is not None:
2476 reg_val
= SelectableInt(self
.gpr(base
, is_vec
, offs
, ew_src
))
2477 self
.trace("r:GPR:%d:%d:%d " % (base
, offs
, ew_src
))
2478 log("read reg %d/%d: 0x%x" % (base
, offs
, reg_val
.value
),
2479 kind
=LogKind
.InstrInOuts
)
2481 log('zero input reg %s %s' % (name
, str(regnum
)), is_vec
)
2482 reg_val
= SelectableInt(0, ew_src
)
2485 def remap_set_steps(self
, remaps
):
2486 """remap_set_steps sets up the in1/2/3 and out1/2 steps.
2487 they work in concert with PowerDecoder2 at the moment,
2488 there is no HDL implementation of REMAP. therefore this
2489 function, because ISACaller still uses PowerDecoder2,
2490 will *explicitly* write the dec2.XX_step values. this has
2493 # just some convenient debug info
2495 sname
= 'SVSHAPE%d' % i
2496 shape
= self
.spr
[sname
]
2497 log(sname
, bin(shape
.value
))
2498 log(" lims", shape
.lims
)
2499 log(" mode", shape
.mode
)
2500 log(" skip", shape
.skip
)
2502 # set up the list of steps to remap
2503 mi0
= self
.svstate
.mi0
2504 mi1
= self
.svstate
.mi1
2505 mi2
= self
.svstate
.mi2
2506 mo0
= self
.svstate
.mo0
2507 mo1
= self
.svstate
.mo1
2508 steps
= [[self
.dec2
.in1_step
, mi0
], # RA
2509 [self
.dec2
.in2_step
, mi1
], # RB
2510 [self
.dec2
.in3_step
, mi2
], # RC
2511 [self
.dec2
.o_step
, mo0
], # RT
2512 [self
.dec2
.o2_step
, mo1
], # EA
2515 rnames
= ['RA', 'RB', 'RC', 'RT', 'RS']
2516 for i
, reg
in enumerate(rnames
):
2517 idx
= yield from get_idx_map(self
.dec2
, reg
)
2519 idx
= yield from get_idx_map(self
.dec2
, "F"+reg
)
2521 steps
[i
][0] = self
.dec2
.in1_step
2523 steps
[i
][0] = self
.dec2
.in2_step
2525 steps
[i
][0] = self
.dec2
.in3_step
2526 log("remap step", i
, reg
, idx
, steps
[i
][1])
2527 remap_idxs
= self
.remap_idxs
2529 # now cross-index the required SHAPE for each of 3-in 2-out regs
2530 rnames
= ['RA', 'RB', 'RC', 'RT', 'EA']
2531 for i
, (dstep
, shape_idx
) in enumerate(steps
):
2532 (shape
, remap
) = remaps
[shape_idx
]
2533 remap_idx
= remap_idxs
[shape_idx
]
2534 # zero is "disabled"
2535 if shape
.value
== 0x0:
2537 # now set the actual requested step to the current index
2538 if dstep
is not None:
2539 yield dstep
.eq(remap_idx
)
2541 # debug printout info
2542 rremaps
.append((shape
.mode
, hex(shape
.value
), dstep
,
2543 i
, rnames
[i
], shape_idx
, remap_idx
))
2545 log("shape remap", x
)
2547 def check_write(self
, info
, name
, output
, carry_en
, ew_dst
):
2548 if name
== 'overflow': # ignore, done already (above)
2550 if name
== 'CR0': # ignore, done already (above)
2552 if isinstance(output
, int):
2553 output
= SelectableInt(output
, EFFECTIVELY_UNLIMITED
)
2555 if name
in ['FPSCR', ]:
2556 log("write FPSCR 0x%x" % (output
.value
))
2557 self
.FPSCR
.eq(output
)
2560 if name
in ['CA', 'CA32']:
2562 log("writing %s to XER" % name
, output
)
2563 log("write XER %s 0x%x" % (name
, output
.value
))
2564 self
.spr
['XER'][XER_bits
[name
]] = output
.value
2566 log("NOT writing %s to XER" % name
, output
)
2568 # write special SPRs
2569 if name
in info
.special_regs
:
2570 log('writing special %s' % name
, output
, special_sprs
)
2571 log("write reg %s 0x%x" % (name
, output
.value
),
2572 kind
=LogKind
.InstrInOuts
)
2573 if name
in special_sprs
:
2574 self
.spr
[name
] = output
2576 self
.namespace
[name
].eq(output
)
2578 log('msr written', hex(self
.msr
.value
))
2580 # find out1/out2 PR/FPR
2581 regnum
, is_vec
= yield from get_idx_out(self
.dec2
, name
, True)
2583 regnum
, is_vec
= yield from get_idx_out2(self
.dec2
, name
, True)
2585 # temporary hack for not having 2nd output
2586 regnum
= yield getattr(self
.decoder
, name
)
2588 # convenient debug prefix
2593 # check zeroing due to predicate bit being zero
2594 if self
.is_svp64_mode
and self
.pred_dst_zero
:
2595 log('zeroing reg %s %s' % (str(regnum
), str(output
)), is_vec
)
2596 output
= SelectableInt(0, EFFECTIVELY_UNLIMITED
)
2597 log("write reg %s%s 0x%x ew %d" % (reg_prefix
, str(regnum
),
2598 output
.value
, ew_dst
),
2599 kind
=LogKind
.InstrInOuts
)
2600 # zero-extend tov64 bit begore storing (should use EXT oh well)
2601 if output
.bits
> 64:
2602 output
= SelectableInt(output
.value
, 64)
2603 rnum
, base
, offset
= regnum
2605 self
.fpr
.write(regnum
, output
, is_vec
, ew_dst
)
2606 self
.trace("w:FPR:%d:%d:%d " % (rnum
, offset
, ew_dst
))
2608 self
.gpr
.write(regnum
, output
, is_vec
, ew_dst
)
2609 self
.trace("w:GPR:%d:%d:%d " % (rnum
, offset
, ew_dst
))
2611 def check_step_increment(self
, rc_en
, asmop
, ins_name
):
2612 # check if it is the SVSTATE.src/dest step that needs incrementing
2613 # this is our Sub-Program-Counter loop from 0 to VL-1
2614 if not self
.allow_next_step_inc
:
2615 if self
.is_svp64_mode
:
2616 return (yield from self
.svstate_post_inc(ins_name
))
2618 # XXX only in non-SVP64 mode!
2619 # record state of whether the current operation was an svshape,
2621 # to be able to know if it should apply in the next instruction.
2622 # also (if going to use this instruction) should disable ability
2623 # to interrupt in between. sigh.
2624 self
.last_op_svshape
= asmop
in ['svremap', 'svindex',
2631 log("SVSTATE_NEXT: inc requested, mode",
2632 self
.svstate_next_mode
, self
.allow_next_step_inc
)
2633 yield from self
.svstate_pre_inc()
2634 pre
= yield from self
.update_new_svstate_steps()
2636 # reset at end of loop including exit Vertical Mode
2637 log("SVSTATE_NEXT: end of loop, reset")
2638 self
.svp64_reset_loop()
2639 self
.svstate
.vfirst
= 0
2643 self
.handle_comparison(SelectableInt(0, 64)) # CR0
2645 if self
.allow_next_step_inc
== 2:
2646 log("SVSTATE_NEXT: read")
2647 nia_update
= (yield from self
.svstate_post_inc(ins_name
))
2649 log("SVSTATE_NEXT: post-inc")
2650 # use actual (cached) src/dst-step here to check end
2651 remaps
= self
.get_remap_indices()
2652 remap_idxs
= self
.remap_idxs
2653 vl
= self
.svstate
.vl
2654 subvl
= yield self
.dec2
.rm_dec
.rm_in
.subvl
2655 if self
.allow_next_step_inc
!= 2:
2656 yield from self
.advance_svstate_steps()
2657 #self.namespace['SVSTATE'] = self.svstate.spr
2658 # set CR0 (if Rc=1) based on end
2659 endtest
= 1 if self
.at_loopend() else 0
2661 #results = [SelectableInt(endtest, 64)]
2662 # self.handle_comparison(results) # CR0
2664 # see if svstep was requested, if so, which SVSTATE
2666 if self
.svstate_next_mode
> 0:
2667 shape_idx
= self
.svstate_next_mode
.value
-1
2668 endings
= self
.remap_loopends
[shape_idx
]
2669 cr_field
= SelectableInt((~endings
) << 1 | endtest
, 4)
2670 log("svstep Rc=1, CR0", cr_field
, endtest
)
2671 self
.crl
[0].eq(cr_field
) # CR0
2673 # reset at end of loop including exit Vertical Mode
2674 log("SVSTATE_NEXT: after increments, reset")
2675 self
.svp64_reset_loop()
2676 self
.svstate
.vfirst
= 0
2679 def SVSTATE_NEXT(self
, mode
, submode
):
2680 """explicitly moves srcstep/dststep on to next element, for
2681 "Vertical-First" mode. this function is called from
2682 setvl pseudo-code, as a pseudo-op "svstep"
2684 WARNING: this function uses information that was created EARLIER
2685 due to it being in the middle of a yield, but this function is
2686 *NOT* called from yield (it's called from compiled pseudocode).
2688 self
.allow_next_step_inc
= submode
.value
+ 1
2689 log("SVSTATE_NEXT mode", mode
, submode
, self
.allow_next_step_inc
)
2690 self
.svstate_next_mode
= mode
2691 if self
.svstate_next_mode
> 0 and self
.svstate_next_mode
< 5:
2692 shape_idx
= self
.svstate_next_mode
.value
-1
2693 return SelectableInt(self
.remap_idxs
[shape_idx
], 7)
2694 if self
.svstate_next_mode
== 5:
2695 self
.svstate_next_mode
= 0
2696 return SelectableInt(self
.svstate
.srcstep
, 7)
2697 if self
.svstate_next_mode
== 6:
2698 self
.svstate_next_mode
= 0
2699 return SelectableInt(self
.svstate
.dststep
, 7)
2700 if self
.svstate_next_mode
== 7:
2701 self
.svstate_next_mode
= 0
2702 return SelectableInt(self
.svstate
.ssubstep
, 7)
2703 if self
.svstate_next_mode
== 8:
2704 self
.svstate_next_mode
= 0
2705 return SelectableInt(self
.svstate
.dsubstep
, 7)
2706 return SelectableInt(0, 7)
2708 def get_src_dststeps(self
):
2709 """gets srcstep, dststep, and ssubstep, dsubstep
2711 return (self
.new_srcstep
, self
.new_dststep
,
2712 self
.new_ssubstep
, self
.new_dsubstep
)
2714 def update_svstate_namespace(self
, overwrite_svstate
=True):
2715 if overwrite_svstate
:
2716 # note, do not get the bit-reversed srcstep here!
2717 srcstep
, dststep
= self
.new_srcstep
, self
.new_dststep
2718 ssubstep
, dsubstep
= self
.new_ssubstep
, self
.new_dsubstep
2720 # update SVSTATE with new srcstep
2721 self
.svstate
.srcstep
= srcstep
2722 self
.svstate
.dststep
= dststep
2723 self
.svstate
.ssubstep
= ssubstep
2724 self
.svstate
.dsubstep
= dsubstep
2725 self
.namespace
['SVSTATE'] = self
.svstate
2726 yield self
.dec2
.state
.svstate
.eq(self
.svstate
.value
)
2727 yield Settle() # let decoder update
2729 def update_new_svstate_steps(self
, overwrite_svstate
=True):
2730 yield from self
.update_svstate_namespace(overwrite_svstate
)
2731 srcstep
= self
.svstate
.srcstep
2732 dststep
= self
.svstate
.dststep
2733 ssubstep
= self
.svstate
.ssubstep
2734 dsubstep
= self
.svstate
.dsubstep
2735 pack
= self
.svstate
.pack
2736 unpack
= self
.svstate
.unpack
2737 vl
= self
.svstate
.vl
2738 sv_mode
= yield self
.dec2
.rm_dec
.sv_mode
2739 subvl
= yield self
.dec2
.rm_dec
.rm_in
.subvl
2740 rm_mode
= yield self
.dec2
.rm_dec
.mode
2741 ff_inv
= yield self
.dec2
.rm_dec
.inv
2742 cr_bit
= yield self
.dec2
.rm_dec
.cr_sel
2743 log(" srcstep", srcstep
)
2744 log(" dststep", dststep
)
2746 log(" unpack", unpack
)
2747 log(" ssubstep", ssubstep
)
2748 log(" dsubstep", dsubstep
)
2750 log(" subvl", subvl
)
2751 log(" rm_mode", rm_mode
)
2752 log(" sv_mode", sv_mode
)
2754 log(" cr_bit", cr_bit
)
2756 # check if end reached (we let srcstep overrun, above)
2757 # nothing needs doing (TODO zeroing): just do next instruction
2760 return ((ssubstep
== subvl
and srcstep
== vl
) or
2761 (dsubstep
== subvl
and dststep
== vl
))
2763 def svstate_post_inc(self
, insn_name
, vf
=0):
2764 # check if SV "Vertical First" mode is enabled
2765 vfirst
= self
.svstate
.vfirst
2766 log(" SV Vertical First", vf
, vfirst
)
2767 if not vf
and vfirst
== 1:
2771 # check if it is the SVSTATE.src/dest step that needs incrementing
2772 # this is our Sub-Program-Counter loop from 0 to VL-1
2773 # XXX twin predication TODO
2774 vl
= self
.svstate
.vl
2775 subvl
= yield self
.dec2
.rm_dec
.rm_in
.subvl
2776 mvl
= self
.svstate
.maxvl
2777 srcstep
= self
.svstate
.srcstep
2778 dststep
= self
.svstate
.dststep
2779 ssubstep
= self
.svstate
.ssubstep
2780 dsubstep
= self
.svstate
.dsubstep
2781 pack
= self
.svstate
.pack
2782 unpack
= self
.svstate
.unpack
2783 rm_mode
= yield self
.dec2
.rm_dec
.mode
2784 reverse_gear
= yield self
.dec2
.rm_dec
.reverse_gear
2785 sv_ptype
= yield self
.dec2
.dec
.op
.SV_Ptype
2786 out_vec
= not (yield self
.dec2
.no_out_vec
)
2787 in_vec
= not (yield self
.dec2
.no_in_vec
)
2788 log(" svstate.vl", vl
)
2789 log(" svstate.mvl", mvl
)
2790 log(" rm.subvl", subvl
)
2791 log(" svstate.srcstep", srcstep
)
2792 log(" svstate.dststep", dststep
)
2793 log(" svstate.ssubstep", ssubstep
)
2794 log(" svstate.dsubstep", dsubstep
)
2795 log(" svstate.pack", pack
)
2796 log(" svstate.unpack", unpack
)
2797 log(" mode", rm_mode
)
2798 log(" reverse", reverse_gear
)
2799 log(" out_vec", out_vec
)
2800 log(" in_vec", in_vec
)
2801 log(" sv_ptype", sv_ptype
, sv_ptype
== SVPType
.P2
.value
)
2802 # check if this was an sv.bc* and if so did it succeed
2803 if self
.is_svp64_mode
and insn_name
.startswith("sv.bc"):
2804 end_loop
= self
.namespace
['end_loop']
2805 log("branch %s end_loop" % insn_name
, end_loop
)
2807 self
.svp64_reset_loop()
2808 self
.update_pc_next()
2810 # check if srcstep needs incrementing by one, stop PC advancing
2811 # but for 2-pred both src/dest have to be checked.
2812 # XXX this might not be true! it may just be LD/ST
2813 if sv_ptype
== SVPType
.P2
.value
:
2814 svp64_is_vector
= (out_vec
or in_vec
)
2816 svp64_is_vector
= out_vec
2817 # loops end at the first "hit" (source or dest)
2818 yield from self
.advance_svstate_steps()
2819 loopend
= self
.loopend
2820 log("loopend", svp64_is_vector
, loopend
)
2821 if not svp64_is_vector
or loopend
:
2822 # reset loop to zero and update NIA
2823 self
.svp64_reset_loop()
2828 # still looping, advance and update NIA
2829 self
.namespace
['SVSTATE'] = self
.svstate
2831 # not an SVP64 branch, so fix PC (NIA==CIA) for next loop
2832 # (by default, NIA is CIA+4 if v3.0B or CIA+8 if SVP64)
2833 # this way we keep repeating the same instruction (with new steps)
2834 self
.pc
.NIA
.value
= self
.pc
.CIA
.value
2835 self
.namespace
['NIA'] = self
.pc
.NIA
2836 log("end of sub-pc call", self
.namespace
['CIA'], self
.namespace
['NIA'])
2837 return False # DO NOT allow PC update whilst Sub-PC loop running
2839 def update_pc_next(self
):
2840 # UPDATE program counter
2841 self
.pc
.update(self
.namespace
, self
.is_svp64_mode
)
2842 #self.svstate.spr = self.namespace['SVSTATE']
2843 log("end of call", self
.namespace
['CIA'],
2844 self
.namespace
['NIA'],
2845 self
.namespace
['SVSTATE'])
2847 def svp64_reset_loop(self
):
2848 self
.svstate
.srcstep
= 0
2849 self
.svstate
.dststep
= 0
2850 self
.svstate
.ssubstep
= 0
2851 self
.svstate
.dsubstep
= 0
2852 self
.loopend
= False
2853 log(" svstate.srcstep loop end (PC to update)")
2854 self
.namespace
['SVSTATE'] = self
.svstate
2856 def update_nia(self
):
2857 self
.pc
.update_nia(self
.is_svp64_mode
)
2858 self
.namespace
['NIA'] = self
.pc
.NIA
2862 """Decorator factory.
2864 this decorator will "inject" variables into the function's namespace,
2865 from the *dictionary* in self.namespace. it therefore becomes possible
2866 to make it look like a whole stack of variables which would otherwise
2867 need "self." inserted in front of them (*and* for those variables to be
2868 added to the instance) "appear" in the function.
2870 "self.namespace['SI']" for example becomes accessible as just "SI" but
2871 *only* inside the function, when decorated.
2873 def variable_injector(func
):
2875 def decorator(*args
, **kwargs
):
2877 func_globals
= func
.__globals
__ # Python 2.6+
2878 except AttributeError:
2879 func_globals
= func
.func_globals
# Earlier versions.
2881 context
= args
[0].namespace
# variables to be injected
2882 saved_values
= func_globals
.copy() # Shallow copy of dict.
2883 log("globals before", context
.keys())
2884 func_globals
.update(context
)
2885 result
= func(*args
, **kwargs
)
2886 log("globals after", func_globals
['CIA'], func_globals
['NIA'])
2887 log("args[0]", args
[0].namespace
['CIA'],
2888 args
[0].namespace
['NIA'],
2889 args
[0].namespace
['SVSTATE'])
2890 if 'end_loop' in func_globals
:
2891 log("args[0] end_loop", func_globals
['end_loop'])
2892 args
[0].namespace
= func_globals
2893 #exec (func.__code__, func_globals)
2896 # func_globals = saved_values # Undo changes.
2902 return variable_injector