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,
1170 use_mmap_mem
=False):
1172 # trace log file for model output. if None do nothing
1173 self
.syscall
= SyscallEmulator(isacaller
=self
)
1174 self
.insnlog
= insnlog
1175 self
.insnlog_is_file
= hasattr(insnlog
, "write")
1176 if not self
.insnlog_is_file
and self
.insnlog
:
1177 self
.insnlog
= open(self
.insnlog
, "w")
1179 self
.bigendian
= bigendian
1181 self
.is_svp64_mode
= False
1182 self
.respect_pc
= respect_pc
1183 if initial_sprs
is None:
1185 if initial_mem
is None:
1187 if fpregfile
is None:
1188 fpregfile
= [0] * 32
1189 if initial_insns
is None:
1191 assert self
.respect_pc
== False, "instructions required to honor pc"
1193 log("ISACaller insns", respect_pc
, initial_insns
, disassembly
)
1194 log("ISACaller initial_msr", initial_msr
)
1196 # "fake program counter" mode (for unit testing)
1200 if isinstance(initial_mem
, tuple):
1201 self
.fake_pc
= initial_mem
[0]
1202 disasm_start
= self
.fake_pc
1204 disasm_start
= initial_pc
1206 # disassembly: we need this for now (not given from the decoder)
1207 self
.disassembly
= {}
1209 for i
, code
in enumerate(disassembly
):
1210 self
.disassembly
[i
*4 + disasm_start
] = code
1212 # set up registers, instruction memory, data memory, PC, SPRs, MSR, CR
1213 self
.svp64rm
= SVP64RM()
1214 if initial_svstate
is None:
1216 if isinstance(initial_svstate
, int):
1217 initial_svstate
= SVP64State(initial_svstate
)
1218 # SVSTATE, MSR and PC
1219 StepLoop
.__init
__(self
, initial_svstate
)
1220 self
.msr
= SelectableInt(initial_msr
, 64) # underlying reg
1222 # GPR FPR SPR registers
1223 initial_sprs
= deepcopy(initial_sprs
) # so as not to get modified
1224 self
.gpr
= GPR(decoder2
, self
, self
.svstate
, regfile
)
1225 self
.fpr
= GPR(decoder2
, self
, self
.svstate
, fpregfile
)
1226 self
.spr
= SPR(decoder2
, initial_sprs
) # initialise SPRs before MMU
1228 # set up 4 dummy SVSHAPEs if they aren't already set up
1230 sname
= 'SVSHAPE%d' % i
1231 val
= self
.spr
.get(sname
, 0)
1232 # make sure it's an SVSHAPE
1233 self
.spr
[sname
] = SVSHAPE(val
, self
.gpr
)
1234 self
.last_op_svshape
= False
1238 self
.mem
= MemMMap(row_bytes
=8,
1239 initial_mem
=initial_mem
,
1241 self
.imem
= self
.mem
1242 self
.mem
.initialize(row_bytes
=4, initial_mem
=initial_insns
)
1243 self
.mem
.log_fancy(kind
=LogKind
.InstrInOuts
)
1245 self
.mem
= Mem(row_bytes
=8, initial_mem
=initial_mem
,
1247 self
.mem
.log_fancy(kind
=LogKind
.InstrInOuts
)
1248 self
.imem
= Mem(row_bytes
=4, initial_mem
=initial_insns
)
1249 # MMU mode, redirect underlying Mem through RADIX
1251 self
.mem
= RADIX(self
.mem
, self
)
1253 self
.imem
= RADIX(self
.imem
, self
)
1255 # TODO, needed here:
1256 # FPR (same as GPR except for FP nums)
1257 # 4.2.2 p124 FPSCR (definitely "separate" - not in SPR)
1258 # note that mffs, mcrfs, mtfsf "manage" this FPSCR
1259 self
.fpscr
= FPSCRState(initial_fpscr
)
1261 # 2.3.1 CR (and sub-fields CR0..CR6 - CR0 SO comes from XER.SO)
1262 # note that mfocrf, mfcr, mtcr, mtocrf, mcrxrx "manage" CRs
1264 # 2.3.2 LR (actually SPR #8) -- Done
1265 # 2.3.3 CTR (actually SPR #9) -- Done
1266 # 2.3.4 TAR (actually SPR #815)
1267 # 3.2.2 p45 XER (actually SPR #1) -- Done
1268 # 3.2.3 p46 p232 VRSAVE (actually SPR #256)
1270 # create CR then allow portions of it to be "selectable" (below)
1271 self
.cr_fields
= CRFields(initial_cr
)
1272 self
.cr
= self
.cr_fields
.cr
1273 self
.cr_backup
= 0 # sigh, dreadful hack: for fail-first (VLi)
1275 # "undefined", just set to variable-bit-width int (use exts "max")
1276 # self.undefined = SelectableInt(0, EFFECTIVELY_UNLIMITED)
1279 self
.namespace
.update(self
.spr
)
1280 self
.namespace
.update({'GPR': self
.gpr
,
1284 'memassign': self
.memassign
,
1287 'SVSTATE': self
.svstate
,
1288 'SVSHAPE0': self
.spr
['SVSHAPE0'],
1289 'SVSHAPE1': self
.spr
['SVSHAPE1'],
1290 'SVSHAPE2': self
.spr
['SVSHAPE2'],
1291 'SVSHAPE3': self
.spr
['SVSHAPE3'],
1294 'FPSCR': self
.fpscr
,
1295 'undefined': undefined
,
1296 'mode_is_64bit': True,
1297 'SO': XER_bits
['SO'],
1298 'XLEN': 64 # elwidth overrides
1301 for name
in BFP_FLAG_NAMES
:
1302 setattr(self
, name
, 0)
1304 # update pc to requested start point
1305 self
.set_pc(initial_pc
)
1307 # field-selectable versions of Condition Register
1308 self
.crl
= self
.cr_fields
.crl
1310 self
.namespace
["CR%d" % i
] = self
.crl
[i
]
1312 self
.decoder
= decoder2
.dec
1313 self
.dec2
= decoder2
1315 super().__init
__(XLEN
=self
.namespace
["XLEN"], FPSCR
=self
.fpscr
)
1317 def trace(self
, out
):
1318 if self
.insnlog
is None: return
1319 self
.insnlog
.write(out
)
1323 return self
.namespace
["XLEN"]
1329 def call_trap(self
, trap_addr
, trap_bit
):
1330 """calls TRAP and sets up NIA to the new execution location.
1331 next instruction will begin at trap_addr.
1333 self
.TRAP(trap_addr
, trap_bit
)
1334 self
.namespace
['NIA'] = self
.trap_nia
1335 self
.pc
.update(self
.namespace
, self
.is_svp64_mode
)
1337 def TRAP(self
, trap_addr
=0x700, trap_bit
=PIb
.TRAP
):
1338 """TRAP> saves PC, MSR (and TODO SVSTATE), and updates MSR
1340 TRAP function is callable from inside the pseudocode itself,
1341 hence the default arguments. when calling from inside ISACaller
1342 it is best to use call_trap()
1344 if isinstance(trap_addr
, SelectableInt
):
1345 trap_addr
= trap_addr
.value
1346 # https://bugs.libre-soc.org/show_bug.cgi?id=859
1347 kaivb
= self
.spr
['KAIVB'].value
1348 msr
= self
.namespace
['MSR'].value
1349 log("TRAP:", hex(trap_addr
), hex(msr
), "kaivb", hex(kaivb
))
1350 # store CIA(+4?) in SRR0, set NIA to 0x700
1351 # store MSR in SRR1, set MSR to um errr something, have to check spec
1352 # store SVSTATE (if enabled) in SVSRR0
1353 self
.spr
['SRR0'].value
= self
.pc
.CIA
.value
1354 self
.spr
['SRR1'].value
= msr
1355 if self
.is_svp64_mode
:
1356 self
.spr
['SVSRR0'] = self
.namespace
['SVSTATE'].value
1357 self
.trap_nia
= SelectableInt(trap_addr |
(kaivb
& ~
0x1fff), 64)
1358 self
.spr
['SRR1'][trap_bit
] = 1 # change *copy* of MSR in SRR1
1360 # set exception bits. TODO: this should, based on the address
1361 # in figure 66 p1065 V3.0B and the table figure 65 p1063 set these
1362 # bits appropriately. however it turns out that *for now* in all
1363 # cases (all trap_addrs) the exact same thing is needed.
1364 self
.msr
[MSRb
.IR
] = 0
1365 self
.msr
[MSRb
.DR
] = 0
1366 self
.msr
[MSRb
.FE0
] = 0
1367 self
.msr
[MSRb
.FE1
] = 0
1368 self
.msr
[MSRb
.EE
] = 0
1369 self
.msr
[MSRb
.RI
] = 0
1370 self
.msr
[MSRb
.SF
] = 1
1371 self
.msr
[MSRb
.TM
] = 0
1372 self
.msr
[MSRb
.VEC
] = 0
1373 self
.msr
[MSRb
.VSX
] = 0
1374 self
.msr
[MSRb
.PR
] = 0
1375 self
.msr
[MSRb
.FP
] = 0
1376 self
.msr
[MSRb
.PMM
] = 0
1377 self
.msr
[MSRb
.TEs
] = 0
1378 self
.msr
[MSRb
.TEe
] = 0
1379 self
.msr
[MSRb
.UND
] = 0
1380 self
.msr
[MSRb
.LE
] = 1
1382 def memassign(self
, ea
, sz
, val
):
1383 self
.mem
.memassign(ea
, sz
, val
)
1385 def prep_namespace(self
, insn_name
, formname
, op_fields
, xlen
):
1386 # TODO: get field names from form in decoder*1* (not decoder2)
1387 # decoder2 is hand-created, and decoder1.sigform is auto-generated
1389 # then "yield" fields only from op_fields rather than hard-coded
1391 fields
= self
.decoder
.sigforms
[formname
]
1392 log("prep_namespace", formname
, op_fields
, insn_name
)
1393 for name
in op_fields
:
1394 # CR immediates. deal with separately. needs modifying
1396 if self
.is_svp64_mode
and name
in ['BI']: # TODO, more CRs
1397 # BI is a 5-bit, must reconstruct the value
1398 regnum
, is_vec
= yield from get_cr_in(self
.dec2
, name
)
1399 sig
= getattr(fields
, name
)
1401 # low 2 LSBs (CR field selector) remain same, CR num extended
1402 assert regnum
<= 7, "sigh, TODO, 128 CR fields"
1403 val
= (val
& 0b11) |
(regnum
<< 2)
1404 elif self
.is_svp64_mode
and name
in ['BF']: # TODO, more CRs
1405 regnum
, is_vec
= yield from get_cr_out(self
.dec2
, "BF")
1406 log('hack %s' % name
, regnum
, is_vec
)
1409 sig
= getattr(fields
, name
)
1411 # these are all opcode fields involved in index-selection of CR,
1412 # and need to do "standard" arithmetic. CR[BA+32] for example
1413 # would, if using SelectableInt, only be 5-bit.
1414 if name
in ['BF', 'BFA', 'BC', 'BA', 'BB', 'BT', 'BI']:
1415 self
.namespace
[name
] = val
1417 self
.namespace
[name
] = SelectableInt(val
, sig
.width
)
1419 self
.namespace
['XER'] = self
.spr
['XER']
1420 self
.namespace
['CA'] = self
.spr
['XER'][XER_bits
['CA']].value
1421 self
.namespace
['CA32'] = self
.spr
['XER'][XER_bits
['CA32']].value
1422 self
.namespace
['OV'] = self
.spr
['XER'][XER_bits
['OV']].value
1423 self
.namespace
['OV32'] = self
.spr
['XER'][XER_bits
['OV32']].value
1424 self
.namespace
['XLEN'] = xlen
1426 # add some SVSTATE convenience variables
1427 vl
= self
.svstate
.vl
1428 srcstep
= self
.svstate
.srcstep
1429 self
.namespace
['VL'] = vl
1430 self
.namespace
['srcstep'] = srcstep
1432 # take a copy of the CR field value: if non-VLi fail-first fails
1433 # this is because the pseudocode writes *directly* to CR. sigh
1434 self
.cr_backup
= self
.cr
.value
1436 # sv.bc* need some extra fields
1437 if self
.is_svp64_mode
and insn_name
.startswith("sv.bc"):
1438 # blegh grab bits manually
1439 mode
= yield self
.dec2
.rm_dec
.rm_in
.mode
1440 # convert to SelectableInt before test
1441 mode
= SelectableInt(mode
, 5)
1442 bc_vlset
= mode
[SVP64MODEb
.BC_VLSET
] != 0
1443 bc_vli
= mode
[SVP64MODEb
.BC_VLI
] != 0
1444 bc_snz
= mode
[SVP64MODEb
.BC_SNZ
] != 0
1445 bc_vsb
= yield self
.dec2
.rm_dec
.bc_vsb
1446 bc_lru
= yield self
.dec2
.rm_dec
.bc_lru
1447 bc_gate
= yield self
.dec2
.rm_dec
.bc_gate
1448 sz
= yield self
.dec2
.rm_dec
.pred_sz
1449 self
.namespace
['mode'] = SelectableInt(mode
, 5)
1450 self
.namespace
['ALL'] = SelectableInt(bc_gate
, 1)
1451 self
.namespace
['VSb'] = SelectableInt(bc_vsb
, 1)
1452 self
.namespace
['LRu'] = SelectableInt(bc_lru
, 1)
1453 self
.namespace
['VLSET'] = SelectableInt(bc_vlset
, 1)
1454 self
.namespace
['VLI'] = SelectableInt(bc_vli
, 1)
1455 self
.namespace
['sz'] = SelectableInt(sz
, 1)
1456 self
.namespace
['SNZ'] = SelectableInt(bc_snz
, 1)
1458 def get_kludged_op_add_ca_ov(self
, inputs
, inp_ca_ov
):
1459 """ this was not at all necessary to do. this function massively
1460 duplicates - in a laborious and complex fashion - the contents of
1461 the CSV files that were extracted two years ago from microwatt's
1462 source code. A-inversion is the "inv A" column, output inversion
1463 is the "inv out" column, carry-in equal to 0 or 1 or CA is the
1466 all of that information is available in
1467 self.instrs[ins_name].op_fields
1468 where info is usually assigned to self.instrs[ins_name]
1470 https://git.libre-soc.org/?p=openpower-isa.git;a=blob;f=openpower/isatables/minor_31.csv;hb=HEAD
1472 the immediate constants are *also* decoded correctly and placed
1473 usually by DecodeIn2Imm into operand2, as part of power_decoder2.py
1475 def ca(a
, b
, ca_in
, width
):
1476 mask
= (1 << width
) - 1
1477 y
= (a
& mask
) + (b
& mask
) + ca_in
1480 asmcode
= yield self
.dec2
.dec
.op
.asmcode
1481 insn
= insns
.get(asmcode
)
1482 SI
= yield self
.dec2
.dec
.SI
1485 inputs
= [i
.value
for i
in inputs
]
1488 if insn
in ("add", "addo", "addc", "addco"):
1492 elif insn
== "addic" or insn
== "addic.":
1496 elif insn
in ("subf", "subfo", "subfc", "subfco"):
1500 elif insn
== "subfic":
1504 elif insn
== "adde" or insn
== "addeo":
1508 elif insn
== "subfe" or insn
== "subfeo":
1512 elif insn
== "addme" or insn
== "addmeo":
1516 elif insn
== "addze" or insn
== "addzeo":
1520 elif insn
== "subfme" or insn
== "subfmeo":
1524 elif insn
== "subfze" or insn
== "subfzeo":
1528 elif insn
== "addex":
1529 # CA[32] aren't actually written, just generate so we have
1530 # something to return
1531 ca64
= ov64
= ca(inputs
[0], inputs
[1], OV
, 64)
1532 ca32
= ov32
= ca(inputs
[0], inputs
[1], OV
, 32)
1533 return ca64
, ca32
, ov64
, ov32
1534 elif insn
== "neg" or insn
== "nego":
1539 raise NotImplementedError(
1540 "op_add kludge unimplemented instruction: ", asmcode
, insn
)
1542 ca64
= ca(a
, b
, ca_in
, 64)
1543 ca32
= ca(a
, b
, ca_in
, 32)
1544 ov64
= ca64
!= ca(a
, b
, ca_in
, 63)
1545 ov32
= ca32
!= ca(a
, b
, ca_in
, 31)
1546 return ca64
, ca32
, ov64
, ov32
1548 def handle_carry_(self
, inputs
, output
, ca
, ca32
, inp_ca_ov
):
1549 op
= yield self
.dec2
.e
.do
.insn_type
1550 if op
== MicrOp
.OP_ADD
.value
and ca
is None and ca32
is None:
1551 retval
= yield from self
.get_kludged_op_add_ca_ov(
1553 ca
, ca32
, ov
, ov32
= retval
1554 asmcode
= yield self
.dec2
.dec
.op
.asmcode
1555 if insns
.get(asmcode
) == 'addex':
1556 # TODO: if 32-bit mode, set ov to ov32
1557 self
.spr
['XER'][XER_bits
['OV']] = ov
1558 self
.spr
['XER'][XER_bits
['OV32']] = ov32
1559 log(f
"write OV/OV32 OV={ov} OV32={ov32}",
1560 kind
=LogKind
.InstrInOuts
)
1562 # TODO: if 32-bit mode, set ca to ca32
1563 self
.spr
['XER'][XER_bits
['CA']] = ca
1564 self
.spr
['XER'][XER_bits
['CA32']] = ca32
1565 log(f
"write CA/CA32 CA={ca} CA32={ca32}",
1566 kind
=LogKind
.InstrInOuts
)
1568 inv_a
= yield self
.dec2
.e
.do
.invert_in
1570 inputs
[0] = ~inputs
[0]
1572 imm_ok
= yield self
.dec2
.e
.do
.imm_data
.ok
1574 imm
= yield self
.dec2
.e
.do
.imm_data
.data
1575 inputs
.append(SelectableInt(imm
, 64))
1578 log("gt input", x
, output
)
1579 gt
= (gtu(x
, output
))
1582 cy
= 1 if any(gts
) else 0
1584 if ca
is None: # already written
1585 self
.spr
['XER'][XER_bits
['CA']] = cy
1588 # ARGH... different for OP_ADD... *sigh*...
1589 op
= yield self
.dec2
.e
.do
.insn_type
1590 if op
== MicrOp
.OP_ADD
.value
:
1591 res32
= (output
.value
& (1 << 32)) != 0
1592 a32
= (inputs
[0].value
& (1 << 32)) != 0
1593 if len(inputs
) >= 2:
1594 b32
= (inputs
[1].value
& (1 << 32)) != 0
1597 cy32
= res32 ^ a32 ^ b32
1598 log("CA32 ADD", cy32
)
1602 log("input", x
, output
)
1603 log(" x[32:64]", x
, x
[32:64])
1604 log(" o[32:64]", output
, output
[32:64])
1605 gt
= (gtu(x
[32:64], output
[32:64])) == SelectableInt(1, 1)
1607 cy32
= 1 if any(gts
) else 0
1608 log("CA32", cy32
, gts
)
1609 if ca32
is None: # already written
1610 self
.spr
['XER'][XER_bits
['CA32']] = cy32
1612 def handle_overflow(self
, inputs
, output
, div_overflow
, inp_ca_ov
):
1613 op
= yield self
.dec2
.e
.do
.insn_type
1614 if op
== MicrOp
.OP_ADD
.value
:
1615 retval
= yield from self
.get_kludged_op_add_ca_ov(
1617 ca
, ca32
, ov
, ov32
= retval
1618 # TODO: if 32-bit mode, set ov to ov32
1619 self
.spr
['XER'][XER_bits
['OV']] = ov
1620 self
.spr
['XER'][XER_bits
['OV32']] = ov32
1621 self
.spr
['XER'][XER_bits
['SO']] |
= ov
1623 if hasattr(self
.dec2
.e
.do
, "invert_in"):
1624 inv_a
= yield self
.dec2
.e
.do
.invert_in
1626 inputs
[0] = ~inputs
[0]
1628 imm_ok
= yield self
.dec2
.e
.do
.imm_data
.ok
1630 imm
= yield self
.dec2
.e
.do
.imm_data
.data
1631 inputs
.append(SelectableInt(imm
, 64))
1632 log("handle_overflow", inputs
, output
, div_overflow
)
1633 if len(inputs
) < 2 and div_overflow
is None:
1636 # div overflow is different: it's returned by the pseudo-code
1637 # because it's more complex than can be done by analysing the output
1638 if div_overflow
is not None:
1639 ov
, ov32
= div_overflow
, div_overflow
1640 # arithmetic overflow can be done by analysing the input and output
1641 elif len(inputs
) >= 2:
1643 input_sgn
= [exts(x
.value
, x
.bits
) < 0 for x
in inputs
]
1644 output_sgn
= exts(output
.value
, output
.bits
) < 0
1645 ov
= 1 if input_sgn
[0] == input_sgn
[1] and \
1646 output_sgn
!= input_sgn
[0] else 0
1649 input32_sgn
= [exts(x
.value
, 32) < 0 for x
in inputs
]
1650 output32_sgn
= exts(output
.value
, 32) < 0
1651 ov32
= 1 if input32_sgn
[0] == input32_sgn
[1] and \
1652 output32_sgn
!= input32_sgn
[0] else 0
1654 # now update XER OV/OV32/SO
1655 so
= self
.spr
['XER'][XER_bits
['SO']]
1656 new_so
= so | ov
# sticky overflow ORs in old with new
1657 self
.spr
['XER'][XER_bits
['OV']] = ov
1658 self
.spr
['XER'][XER_bits
['OV32']] = ov32
1659 self
.spr
['XER'][XER_bits
['SO']] = new_so
1660 log(" set overflow", ov
, ov32
, so
, new_so
)
1662 def handle_comparison(self
, out
, cr_idx
=0, overflow
=None, no_so
=False):
1663 assert isinstance(out
, SelectableInt
), \
1664 "out zero not a SelectableInt %s" % repr(outputs
)
1665 log("handle_comparison", out
.bits
, hex(out
.value
))
1666 # TODO - XXX *processor* in 32-bit mode
1667 # https://bugs.libre-soc.org/show_bug.cgi?id=424
1669 # o32 = exts(out.value, 32)
1670 # print ("handle_comparison exts 32 bit", hex(o32))
1671 out
= exts(out
.value
, out
.bits
)
1672 log("handle_comparison exts", hex(out
))
1673 # create the three main CR flags, EQ GT LT
1674 zero
= SelectableInt(out
== 0, 1)
1675 positive
= SelectableInt(out
> 0, 1)
1676 negative
= SelectableInt(out
< 0, 1)
1677 # get (or not) XER.SO. for setvl this is important *not* to read SO
1679 SO
= SelectableInt(1, 0)
1681 SO
= self
.spr
['XER'][XER_bits
['SO']]
1682 log("handle_comparison SO", SO
.value
,
1683 "overflow", overflow
,
1685 "+ve", positive
.value
,
1686 "-ve", negative
.value
)
1687 # alternative overflow checking (setvl mainly at the moment)
1688 if overflow
is not None and overflow
== 1:
1689 SO
= SelectableInt(1, 1)
1690 # create the four CR field values and set the required CR field
1691 cr_field
= selectconcat(negative
, positive
, zero
, SO
)
1692 log("handle_comparison cr_field", self
.cr
, cr_idx
, cr_field
)
1693 self
.crl
[cr_idx
].eq(cr_field
)
1695 def set_pc(self
, pc_val
):
1696 self
.namespace
['NIA'] = SelectableInt(pc_val
, 64)
1697 self
.pc
.update(self
.namespace
, self
.is_svp64_mode
)
1699 def get_next_insn(self
):
1700 """check instruction
1703 pc
= self
.pc
.CIA
.value
1706 ins
= self
.imem
.ld(pc
, 4, False, True, instr_fetch
=True)
1708 raise KeyError("no instruction at 0x%x" % pc
)
1711 def setup_one(self
):
1712 """set up one instruction
1714 pc
, insn
= self
.get_next_insn()
1715 yield from self
.setup_next_insn(pc
, insn
)
1717 # cache since it's really slow to construct
1718 __PREFIX_CACHE
= SVP64Instruction
.Prefix(SelectableInt(value
=0, bits
=32))
1720 def __decode_prefix(self
, opcode
):
1721 pfx
= self
.__PREFIX
_CACHE
1722 pfx
.storage
.eq(opcode
)
1725 def setup_next_insn(self
, pc
, ins
):
1726 """set up next instruction
1729 log("setup: 0x%x 0x%x %s" % (pc
, ins
& 0xffffffff, bin(ins
)))
1730 log("CIA NIA", self
.respect_pc
, self
.pc
.CIA
.value
, self
.pc
.NIA
.value
)
1732 yield self
.dec2
.sv_rm
.eq(0)
1733 yield self
.dec2
.dec
.raw_opcode_in
.eq(ins
& 0xffffffff)
1734 yield self
.dec2
.dec
.bigendian
.eq(self
.bigendian
)
1735 yield self
.dec2
.state
.msr
.eq(self
.msr
.value
)
1736 yield self
.dec2
.state
.pc
.eq(pc
)
1737 if self
.svstate
is not None:
1738 yield self
.dec2
.state
.svstate
.eq(self
.svstate
.value
)
1740 # SVP64. first, check if the opcode is EXT001, and SVP64 id bits set
1742 opcode
= yield self
.dec2
.dec
.opcode_in
1743 opcode
= SelectableInt(value
=opcode
, bits
=32)
1744 pfx
= self
.__decode
_prefix
(opcode
)
1745 log("prefix test: opcode:", pfx
.PO
, bin(pfx
.PO
), pfx
.id)
1746 self
.is_svp64_mode
= bool((pfx
.PO
== 0b000001) and (pfx
.id == 0b11))
1747 self
.pc
.update_nia(self
.is_svp64_mode
)
1749 yield self
.dec2
.is_svp64_mode
.eq(self
.is_svp64_mode
)
1750 self
.namespace
['NIA'] = self
.pc
.NIA
1751 self
.namespace
['SVSTATE'] = self
.svstate
1752 if not self
.is_svp64_mode
:
1755 # in SVP64 mode. decode/print out svp64 prefix, get v3.0B instruction
1756 log("svp64.rm", bin(pfx
.rm
))
1757 log(" svstate.vl", self
.svstate
.vl
)
1758 log(" svstate.mvl", self
.svstate
.maxvl
)
1759 ins
= self
.imem
.ld(pc
+4, 4, False, True, instr_fetch
=True)
1760 log(" svsetup: 0x%x 0x%x %s" % (pc
+4, ins
& 0xffffffff, bin(ins
)))
1761 yield self
.dec2
.dec
.raw_opcode_in
.eq(ins
& 0xffffffff) # v3.0B suffix
1762 yield self
.dec2
.sv_rm
.eq(int(pfx
.rm
)) # svp64 prefix
1765 def execute_one(self
):
1766 """execute one instruction
1768 # get the disassembly code for this instruction
1769 if not self
.disassembly
:
1770 code
= yield from self
.get_assembly_name()
1773 if self
.is_svp64_mode
:
1774 offs
, dbg
= 4, "svp64 "
1775 code
= self
.disassembly
[self
._pc
+offs
]
1776 log(" %s sim-execute" % dbg
, hex(self
._pc
), code
)
1777 opname
= code
.split(' ')[0]
1779 yield from self
.call(opname
) # execute the instruction
1780 except MemException
as e
: # check for memory errors
1781 if e
.args
[0] == 'unaligned': # alignment error
1782 # run a Trap but set DAR first
1783 print("memory unaligned exception, DAR", e
.dar
, repr(e
))
1784 self
.spr
['DAR'] = SelectableInt(e
.dar
, 64)
1785 self
.call_trap(0x600, PIb
.PRIV
) # 0x600, privileged
1787 elif e
.args
[0] == 'invalid': # invalid
1788 # run a Trap but set DAR first
1789 log("RADIX MMU memory invalid error, mode %s" % e
.mode
)
1790 if e
.mode
== 'EXECUTE':
1791 # XXX TODO: must set a few bits in SRR1,
1792 # see microwatt loadstore1.vhdl
1793 # if m_in.segerr = '0' then
1794 # v.srr1(47 - 33) := m_in.invalid;
1795 # v.srr1(47 - 35) := m_in.perm_error; -- noexec fault
1796 # v.srr1(47 - 44) := m_in.badtree;
1797 # v.srr1(47 - 45) := m_in.rc_error;
1798 # v.intr_vec := 16#400#;
1800 # v.intr_vec := 16#480#;
1801 self
.call_trap(0x400, PIb
.PRIV
) # 0x400, privileged
1803 self
.call_trap(0x300, PIb
.PRIV
) # 0x300, privileged
1805 # not supported yet:
1806 raise e
# ... re-raise
1808 # append to the trace log file
1809 self
.trace(" # %s\n" % code
)
1811 log("gprs after code", code
)
1814 for i
in range(len(self
.crl
)):
1815 crs
.append(bin(self
.crl
[i
].asint()))
1816 log("crs", " ".join(crs
))
1817 log("vl,maxvl", self
.svstate
.vl
, self
.svstate
.maxvl
)
1819 # don't use this except in special circumstances
1820 if not self
.respect_pc
:
1823 log("execute one, CIA NIA", hex(self
.pc
.CIA
.value
),
1824 hex(self
.pc
.NIA
.value
))
1826 def get_assembly_name(self
):
1827 # TODO, asmregs is from the spec, e.g. add RT,RA,RB
1828 # see http://bugs.libre-riscv.org/show_bug.cgi?id=282
1829 dec_insn
= yield self
.dec2
.e
.do
.insn
1830 insn_1_11
= yield self
.dec2
.e
.do
.insn
[1:11]
1831 asmcode
= yield self
.dec2
.dec
.op
.asmcode
1832 int_op
= yield self
.dec2
.dec
.op
.internal_op
1833 log("get assembly name asmcode", asmcode
, int_op
,
1834 hex(dec_insn
), bin(insn_1_11
))
1835 asmop
= insns
.get(asmcode
, None)
1837 # sigh reconstruct the assembly instruction name
1838 if hasattr(self
.dec2
.e
.do
, "oe"):
1839 ov_en
= yield self
.dec2
.e
.do
.oe
.oe
1840 ov_ok
= yield self
.dec2
.e
.do
.oe
.ok
1844 if hasattr(self
.dec2
.e
.do
, "rc"):
1845 rc_en
= yield self
.dec2
.e
.do
.rc
.rc
1846 rc_ok
= yield self
.dec2
.e
.do
.rc
.ok
1850 # annoying: ignore rc_ok if RC1 is set (for creating *assembly name*)
1851 RC1
= yield self
.dec2
.rm_dec
.RC1
1855 # grrrr have to special-case MUL op (see DecodeOE)
1856 log("ov %d en %d rc %d en %d op %d" %
1857 (ov_ok
, ov_en
, rc_ok
, rc_en
, int_op
))
1858 if int_op
in [MicrOp
.OP_MUL_H64
.value
, MicrOp
.OP_MUL_H32
.value
]:
1863 if not asmop
.endswith("."): # don't add "." to "andis."
1866 if hasattr(self
.dec2
.e
.do
, "lk"):
1867 lk
= yield self
.dec2
.e
.do
.lk
1870 log("int_op", int_op
)
1871 if int_op
in [MicrOp
.OP_B
.value
, MicrOp
.OP_BC
.value
]:
1872 AA
= yield self
.dec2
.dec
.fields
.FormI
.AA
[0:-1]
1876 spr_msb
= yield from self
.get_spr_msb()
1877 if int_op
== MicrOp
.OP_MFCR
.value
:
1882 # XXX TODO: for whatever weird reason this doesn't work
1883 # https://bugs.libre-soc.org/show_bug.cgi?id=390
1884 if int_op
== MicrOp
.OP_MTCRF
.value
:
1891 def reset_remaps(self
):
1892 self
.remap_loopends
= [0] * 4
1893 self
.remap_idxs
= [0, 1, 2, 3]
1895 def get_remap_indices(self
):
1896 """WARNING, this function stores remap_idxs and remap_loopends
1897 in the class for later use. this to avoid problems with yield
1899 # go through all iterators in lock-step, advance to next remap_idx
1900 srcstep
, dststep
, ssubstep
, dsubstep
= self
.get_src_dststeps()
1901 # get four SVSHAPEs. here we are hard-coding
1903 SVSHAPE0
= self
.spr
['SVSHAPE0']
1904 SVSHAPE1
= self
.spr
['SVSHAPE1']
1905 SVSHAPE2
= self
.spr
['SVSHAPE2']
1906 SVSHAPE3
= self
.spr
['SVSHAPE3']
1907 # set up the iterators
1908 remaps
= [(SVSHAPE0
, SVSHAPE0
.get_iterator()),
1909 (SVSHAPE1
, SVSHAPE1
.get_iterator()),
1910 (SVSHAPE2
, SVSHAPE2
.get_iterator()),
1911 (SVSHAPE3
, SVSHAPE3
.get_iterator()),
1915 for i
, (shape
, remap
) in enumerate(remaps
):
1916 # zero is "disabled"
1917 if shape
.value
== 0x0:
1918 self
.remap_idxs
[i
] = 0
1919 # pick src or dststep depending on reg num (0-2=in, 3-4=out)
1920 step
= dststep
if (i
in [3, 4]) else srcstep
1921 # this is terrible. O(N^2) looking for the match. but hey.
1922 for idx
, (remap_idx
, loopends
) in enumerate(remap
):
1925 self
.remap_idxs
[i
] = remap_idx
1926 self
.remap_loopends
[i
] = loopends
1927 dbg
.append((i
, step
, remap_idx
, loopends
))
1928 for (i
, step
, remap_idx
, loopends
) in dbg
:
1929 log("SVSHAPE %d idx, end" % i
, step
, remap_idx
, bin(loopends
))
1932 def get_spr_msb(self
):
1933 dec_insn
= yield self
.dec2
.e
.do
.insn
1934 return dec_insn
& (1 << 20) != 0 # sigh - XFF.spr[-1]?
1936 def call(self
, name
):
1937 """call(opcode) - the primary execution point for instructions
1939 self
.last_st_addr
= None # reset the last known store address
1940 self
.last_ld_addr
= None # etc.
1942 ins_name
= name
.strip() # remove spaces if not already done so
1944 log("halted - not executing", ins_name
)
1947 # TODO, asmregs is from the spec, e.g. add RT,RA,RB
1948 # see http://bugs.libre-riscv.org/show_bug.cgi?id=282
1949 asmop
= yield from self
.get_assembly_name()
1950 log("call", ins_name
, asmop
,
1951 kind
=LogKind
.InstrInOuts
)
1953 if asmop
in ("sc", "scv"):
1954 identifier
= self
.gpr(0)
1955 arguments
= map(self
.gpr
, range(3, 9))
1956 result
= self
.syscall(identifier
, *arguments
)
1957 self
.gpr
.write(3, result
, False, self
.namespace
["XLEN"])
1958 self
.update_pc_next()
1961 # sv.setvl is *not* a loop-function. sigh
1962 log("is_svp64_mode", self
.is_svp64_mode
, asmop
)
1965 int_op
= yield self
.dec2
.dec
.op
.internal_op
1966 spr_msb
= yield from self
.get_spr_msb()
1968 instr_is_privileged
= False
1969 if int_op
in [MicrOp
.OP_ATTN
.value
,
1970 MicrOp
.OP_MFMSR
.value
,
1971 MicrOp
.OP_MTMSR
.value
,
1972 MicrOp
.OP_MTMSRD
.value
,
1974 MicrOp
.OP_RFID
.value
]:
1975 instr_is_privileged
= True
1976 if int_op
in [MicrOp
.OP_MFSPR
.value
,
1977 MicrOp
.OP_MTSPR
.value
] and spr_msb
:
1978 instr_is_privileged
= True
1980 log("is priv", instr_is_privileged
, hex(self
.msr
.value
),
1982 # check MSR priv bit and whether op is privileged: if so, throw trap
1983 if instr_is_privileged
and self
.msr
[MSRb
.PR
] == 1:
1984 self
.call_trap(0x700, PIb
.PRIV
)
1987 # check halted condition
1988 if ins_name
== 'attn':
1992 # check illegal instruction
1994 if ins_name
not in ['mtcrf', 'mtocrf']:
1995 illegal
= ins_name
!= asmop
1997 # list of instructions not being supported by binutils (.long)
1998 dotstrp
= asmop
[:-1] if asmop
[-1] == '.' else asmop
1999 if dotstrp
in [*FPTRANS_INSNS
,
2001 'ffmadds', 'fdmadds', 'ffadds',
2003 "brh", "brw", "brd",
2004 'setvl', 'svindex', 'svremap', 'svstep',
2005 'svshape', 'svshape2',
2006 'ternlogi', 'bmask', 'cprop',
2007 'absdu', 'absds', 'absdacs', 'absdacu', 'avgadd',
2008 'fmvis', 'fishmv', 'pcdec', "maddedu", "divmod2du",
2009 "dsld", "dsrd", "maddedus",
2010 "sadd", "saddw", "sadduw",
2015 "maddsubrs", "maddrs", "msubrs",
2016 "cfuged", "cntlzdm", "cnttzdm", "pdepd", "pextd",
2017 "setbc", "setbcr", "setnbc", "setnbcr",
2022 # branch-conditional redirects to sv.bc
2023 if asmop
.startswith('bc') and self
.is_svp64_mode
:
2024 ins_name
= 'sv.%s' % ins_name
2026 # ld-immediate-with-pi mode redirects to ld-with-postinc
2027 ldst_imm_postinc
= False
2028 if 'u' in ins_name
and self
.is_svp64_mode
:
2029 ldst_pi
= yield self
.dec2
.rm_dec
.ldst_postinc
2031 ins_name
= ins_name
.replace("u", "up")
2032 ldst_imm_postinc
= True
2033 log(" enable ld/st postinc", ins_name
)
2035 log(" post-processed name", dotstrp
, ins_name
, asmop
)
2037 # illegal instructions call TRAP at 0x700
2039 print("illegal", ins_name
, asmop
)
2040 self
.call_trap(0x700, PIb
.ILLEG
)
2041 print("name %s != %s - calling ILLEGAL trap, PC: %x" %
2042 (ins_name
, asmop
, self
.pc
.CIA
.value
))
2045 # this is for setvl "Vertical" mode: if set true,
2046 # srcstep/dststep is explicitly advanced. mode says which SVSTATE to
2047 # test for Rc=1 end condition. 3 bits of all 3 loops are put into CR0
2048 self
.allow_next_step_inc
= False
2049 self
.svstate_next_mode
= 0
2051 # nop has to be supported, we could let the actual op calculate
2052 # but PowerDecoder has a pattern for nop
2053 if ins_name
== 'nop':
2054 self
.update_pc_next()
2057 # get elwidths, defaults to 64
2061 if self
.is_svp64_mode
:
2062 ew_src
= yield self
.dec2
.rm_dec
.ew_src
2063 ew_dst
= yield self
.dec2
.rm_dec
.ew_dst
2064 ew_src
= 8 << (3-int(ew_src
)) # convert to bitlength
2065 ew_dst
= 8 << (3-int(ew_dst
)) # convert to bitlength
2066 xlen
= max(ew_src
, ew_dst
)
2067 log("elwdith", ew_src
, ew_dst
)
2068 log("XLEN:", self
.is_svp64_mode
, xlen
)
2070 # look up instruction in ISA.instrs, prepare namespace
2071 if ins_name
== 'pcdec': # grrrr yes there are others ("stbcx." etc.)
2072 info
= self
.instrs
[ins_name
+"."]
2073 elif asmop
[-1] == '.' and asmop
in self
.instrs
:
2074 info
= self
.instrs
[asmop
]
2076 info
= self
.instrs
[ins_name
]
2077 yield from self
.prep_namespace(ins_name
, info
.form
, info
.op_fields
,
2080 # preserve order of register names
2081 input_names
= create_args(list(info
.read_regs
) +
2082 list(info
.uninit_regs
))
2083 log("input names", input_names
)
2085 # get SVP64 entry for the current instruction
2086 sv_rm
= self
.svp64rm
.instrs
.get(ins_name
)
2087 if sv_rm
is not None:
2088 dest_cr
, src_cr
, src_byname
, dest_byname
= decode_extra(sv_rm
)
2090 dest_cr
, src_cr
, src_byname
, dest_byname
= False, False, {}, {}
2091 log("sv rm", sv_rm
, dest_cr
, src_cr
, src_byname
, dest_byname
)
2093 # see if srcstep/dststep need skipping over masked-out predicate bits
2094 # svstep also needs advancement because it calls SVSTATE_NEXT.
2095 # bit the remaps get computed just after pre_inc moves them on
2096 # with remap_set_steps substituting for PowerDecider2 not doing it,
2097 # and SVSTATE_NEXT not being able to.use yield, the preinc on
2098 # svstep is necessary for now.
2100 if (self
.is_svp64_mode
or ins_name
in ['svstep']):
2101 yield from self
.svstate_pre_inc()
2102 if self
.is_svp64_mode
:
2103 pre
= yield from self
.update_new_svstate_steps()
2105 self
.svp64_reset_loop()
2107 self
.update_pc_next()
2109 srcstep
, dststep
, ssubstep
, dsubstep
= self
.get_src_dststeps()
2110 pred_dst_zero
= self
.pred_dst_zero
2111 pred_src_zero
= self
.pred_src_zero
2112 vl
= self
.svstate
.vl
2113 subvl
= yield self
.dec2
.rm_dec
.rm_in
.subvl
2115 # VL=0 in SVP64 mode means "do nothing: skip instruction"
2116 if self
.is_svp64_mode
and vl
== 0:
2117 self
.pc
.update(self
.namespace
, self
.is_svp64_mode
)
2118 log("SVP64: VL=0, end of call", self
.namespace
['CIA'],
2119 self
.namespace
['NIA'], kind
=LogKind
.InstrInOuts
)
2122 # for when SVREMAP is active, using pre-arranged schedule.
2123 # note: modifying PowerDecoder2 needs to "settle"
2124 remap_en
= self
.svstate
.SVme
2125 persist
= self
.svstate
.RMpst
2126 active
= (persist
or self
.last_op_svshape
) and remap_en
!= 0
2127 if self
.is_svp64_mode
:
2128 yield self
.dec2
.remap_active
.eq(remap_en
if active
else 0)
2130 if persist
or self
.last_op_svshape
:
2131 remaps
= self
.get_remap_indices()
2132 if self
.is_svp64_mode
and (persist
or self
.last_op_svshape
):
2133 yield from self
.remap_set_steps(remaps
)
2134 # after that, settle down (combinatorial) to let Vector reg numbers
2135 # work themselves out
2137 if self
.is_svp64_mode
:
2138 remap_active
= yield self
.dec2
.remap_active
2140 remap_active
= False
2141 log("remap active", bin(remap_active
))
2143 # main input registers (RT, RA ...)
2145 for name
in input_names
:
2146 regval
= (yield from self
.get_input(name
, ew_src
))
2147 log("regval name", name
, regval
)
2148 inputs
.append(regval
)
2150 # arrrrgh, awful hack, to get _RT into namespace
2151 if ins_name
in ['setvl', 'svstep']:
2153 RT
= yield self
.dec2
.dec
.RT
2154 self
.namespace
[regname
] = SelectableInt(RT
, 5)
2156 self
.namespace
["RT"] = SelectableInt(0, 5)
2157 regnum
, is_vec
= yield from get_idx_out(self
.dec2
, "RT")
2158 log('hack input reg %s %s' % (name
, str(regnum
)), is_vec
)
2160 # in SVP64 mode for LD/ST work out immediate
2161 # XXX TODO: replace_ds for DS-Form rather than D-Form.
2162 # use info.form to detect
2163 if self
.is_svp64_mode
and not ldst_imm_postinc
:
2164 yield from self
.check_replace_d(info
, remap_active
)
2166 # "special" registers
2167 for special
in info
.special_regs
:
2168 if special
in special_sprs
:
2169 inputs
.append(self
.spr
[special
])
2171 inputs
.append(self
.namespace
[special
])
2173 # clear trap (trap) NIA
2174 self
.trap_nia
= None
2176 # check if this was an sv.bc* and create an indicator that
2177 # this is the last check to be made as a loop. combined with
2178 # the ALL/ANY mode we can early-exit
2179 if self
.is_svp64_mode
and ins_name
.startswith("sv.bc"):
2180 no_in_vec
= yield self
.dec2
.no_in_vec
# BI is scalar
2181 end_loop
= no_in_vec
or srcstep
== vl
-1 or dststep
== vl
-1
2182 self
.namespace
['end_loop'] = SelectableInt(end_loop
, 1)
2184 inp_ca_ov
= (self
.spr
['XER'][XER_bits
['CA']].value
,
2185 self
.spr
['XER'][XER_bits
['OV']].value
)
2187 # execute actual instruction here (finally)
2188 log("inputs", inputs
)
2189 results
= info
.func(self
, *inputs
)
2190 output_names
= create_args(info
.write_regs
)
2192 for out
, n
in zip(results
or [], output_names
):
2194 log("results", outs
)
2196 # "inject" decorator takes namespace from function locals: we need to
2197 # overwrite NIA being overwritten (sigh)
2198 if self
.trap_nia
is not None:
2199 self
.namespace
['NIA'] = self
.trap_nia
2201 log("after func", self
.namespace
['CIA'], self
.namespace
['NIA'])
2203 # check if op was a LD/ST so that debugging can check the
2205 if int_op
in [MicrOp
.OP_STORE
.value
,
2207 self
.last_st_addr
= self
.mem
.last_st_addr
2208 if int_op
in [MicrOp
.OP_LOAD
.value
,
2210 self
.last_ld_addr
= self
.mem
.last_ld_addr
2211 log("op", int_op
, MicrOp
.OP_STORE
.value
, MicrOp
.OP_LOAD
.value
,
2212 self
.last_st_addr
, self
.last_ld_addr
)
2214 # detect if CA/CA32 already in outputs (sra*, basically)
2216 ca32
= outs
.get("CA32")
2218 log("carry already done?", ca
, ca32
, output_names
)
2219 # soc test_pipe_caller tests don't have output_carry
2220 has_output_carry
= hasattr(self
.dec2
.e
.do
, "output_carry")
2221 carry_en
= has_output_carry
and (yield self
.dec2
.e
.do
.output_carry
)
2223 yield from self
.handle_carry_(
2224 inputs
, results
[0], ca
, ca32
, inp_ca_ov
=inp_ca_ov
)
2226 # get output named "overflow" and "CR0"
2227 overflow
= outs
.get('overflow')
2228 cr0
= outs
.get('CR0')
2229 cr1
= outs
.get('CR1')
2231 # soc test_pipe_caller tests don't have oe
2232 has_oe
= hasattr(self
.dec2
.e
.do
, "oe")
2233 # yeah just no. not in parallel processing
2234 if has_oe
and not self
.is_svp64_mode
:
2235 # detect if overflow was in return result
2236 ov_en
= yield self
.dec2
.e
.do
.oe
.oe
2237 ov_ok
= yield self
.dec2
.e
.do
.oe
.ok
2238 log("internal overflow", ins_name
, overflow
, "en?", ov_en
, ov_ok
)
2240 yield from self
.handle_overflow(
2241 inputs
, results
[0], overflow
, inp_ca_ov
=inp_ca_ov
)
2243 # only do SVP64 dest predicated Rc=1 if dest-pred is not enabled
2245 if not self
.is_svp64_mode
or not pred_dst_zero
:
2246 if hasattr(self
.dec2
.e
.do
, "rc"):
2247 rc_en
= yield self
.dec2
.e
.do
.rc
.rc
2248 # don't do Rc=1 for svstep it is handled explicitly.
2249 # XXX TODO: now that CR0 is supported, sort out svstep's pseudocode
2250 # to write directly to CR0 instead of in ISACaller. hooyahh.
2251 if rc_en
and ins_name
not in ['svstep']:
2252 yield from self
.do_rc_ov(
2253 ins_name
, results
[0], overflow
, cr0
, cr1
, output_names
)
2256 ffirst_hit
= False, False
2257 if self
.is_svp64_mode
:
2258 sv_mode
= yield self
.dec2
.rm_dec
.sv_mode
2259 is_cr
= sv_mode
== SVMode
.CROP
.value
2260 chk
= rc_en
or is_cr
2261 ffirst_hit
= (yield from self
.check_ffirst(info
, chk
, srcstep
))
2263 # check if a FP Exception occurred. TODO for DD-FFirst, check VLi
2264 # and raise the exception *after* if VLi=1 but if VLi=0 then
2265 # truncate and make the exception "disappear".
2266 if self
.FPSCR
.FEX
and (self
.msr
[MSRb
.FE0
] or self
.msr
[MSRb
.FE1
]):
2267 self
.call_trap(0x700, PIb
.FP
)
2270 # any modified return results?
2271 yield from self
.do_outregs_nia(asmop
, ins_name
, info
, outs
,
2272 carry_en
, rc_en
, ffirst_hit
, ew_dst
)
2274 def check_ffirst(self
, info
, rc_en
, srcstep
):
2275 """fail-first mode: checks a bit of Rc Vector, truncates VL
2277 rm_mode
= yield self
.dec2
.rm_dec
.mode
2278 ff_inv
= yield self
.dec2
.rm_dec
.inv
2279 cr_bit
= yield self
.dec2
.rm_dec
.cr_sel
2280 RC1
= yield self
.dec2
.rm_dec
.RC1
2281 vli_
= yield self
.dec2
.rm_dec
.vli
# VL inclusive if truncated
2282 log(" ff rm_mode", rc_en
, rm_mode
, SVP64RMMode
.FFIRST
.value
)
2286 log(" cr_bit", cr_bit
)
2287 log(" rc_en", rc_en
)
2288 if not rc_en
or rm_mode
!= SVP64RMMode
.FFIRST
.value
:
2290 # get the CR vevtor, do BO-test
2292 log("asmregs", info
.asmregs
[0], info
.write_regs
)
2293 if 'CR' in info
.write_regs
and 'BF' in info
.asmregs
[0]:
2295 regnum
, is_vec
= yield from get_cr_out(self
.dec2
, crf
)
2296 crtest
= self
.crl
[regnum
]
2297 ffirst_hit
= crtest
[cr_bit
] != ff_inv
2298 log("cr test", crf
, regnum
, int(crtest
), crtest
, cr_bit
, ff_inv
)
2299 log("cr test?", ffirst_hit
)
2302 # Fail-first activated, truncate VL
2303 vli
= SelectableInt(int(vli_
), 7)
2304 self
.svstate
.vl
= srcstep
+ vli
2305 yield self
.dec2
.state
.svstate
.eq(self
.svstate
.value
)
2306 yield Settle() # let decoder update
2309 def do_rc_ov(self
, ins_name
, result
, overflow
, cr0
, cr1
, output_names
):
2310 cr_out
= yield self
.dec2
.op
.cr_out
2311 if cr_out
== CROutSel
.CR1
.value
:
2315 regnum
, is_vec
= yield from get_cr_out(self
.dec2
, rc_reg
)
2316 # hang on... for `setvl` actually you want to test SVSTATE.VL
2317 is_setvl
= ins_name
in ('svstep', 'setvl')
2319 result
= SelectableInt(result
.vl
, 64)
2321 # overflow = None # do not override overflow except in setvl
2325 cr1
= int(self
.FPSCR
.FX
) << 3
2326 cr1 |
= int(self
.FPSCR
.FEX
) << 2
2327 cr1 |
= int(self
.FPSCR
.VX
) << 1
2328 cr1 |
= int(self
.FPSCR
.OX
)
2329 log("default fp cr1", cr1
)
2331 log("explicit cr1", cr1
)
2332 self
.crl
[regnum
].eq(cr1
)
2334 # if there was not an explicit CR0 in the pseudocode,
2336 self
.handle_comparison(result
, regnum
, overflow
, no_so
=is_setvl
)
2338 # otherwise we just blat CR0 into the required regnum
2339 log("explicit rc0", cr0
)
2340 self
.crl
[regnum
].eq(cr0
)
2342 def do_outregs_nia(self
, asmop
, ins_name
, info
, outs
,
2343 ca_en
, rc_en
, ffirst_hit
, ew_dst
):
2344 ffirst_hit
, vli
= ffirst_hit
2345 # write out any regs for this instruction, but only if fail-first is ok
2346 # XXX TODO: allow CR-vector to be written out even if ffirst fails
2347 if not ffirst_hit
or vli
:
2348 for name
, output
in outs
.items():
2349 yield from self
.check_write(info
, name
, output
, ca_en
, ew_dst
)
2350 # restore the CR value on non-VLI failfirst (from sv.cmp and others
2351 # which write directly to CR in the pseudocode (gah, what a mess)
2352 # if ffirst_hit and not vli:
2353 # self.cr.value = self.cr_backup
2356 self
.svp64_reset_loop()
2359 # check advancement of src/dst/sub-steps and if PC needs updating
2360 nia_update
= (yield from self
.check_step_increment(rc_en
,
2363 self
.update_pc_next()
2365 def check_replace_d(self
, info
, remap_active
):
2366 replace_d
= False # update / replace constant in pseudocode
2367 ldstmode
= yield self
.dec2
.rm_dec
.ldstmode
2368 vl
= self
.svstate
.vl
2369 subvl
= yield self
.dec2
.rm_dec
.rm_in
.subvl
2370 srcstep
, dststep
= self
.new_srcstep
, self
.new_dststep
2371 ssubstep
, dsubstep
= self
.new_ssubstep
, self
.new_dsubstep
2372 if info
.form
== 'DS':
2373 # DS-Form, multiply by 4 then knock 2 bits off after
2374 imm
= yield self
.dec2
.dec
.fields
.FormDS
.DS
[0:14] * 4
2376 imm
= yield self
.dec2
.dec
.fields
.FormD
.D
[0:16]
2377 imm
= exts(imm
, 16) # sign-extend to integer
2378 # get the right step. LD is from srcstep, ST is dststep
2379 op
= yield self
.dec2
.e
.do
.insn_type
2381 if op
== MicrOp
.OP_LOAD
.value
:
2383 offsmul
= yield self
.dec2
.in1_step
2384 log("D-field REMAP src", imm
, offsmul
, ldstmode
)
2386 offsmul
= (srcstep
* (subvl
+1)) + ssubstep
2387 log("D-field src", imm
, offsmul
, ldstmode
)
2388 elif op
== MicrOp
.OP_STORE
.value
:
2389 # XXX NOTE! no bit-reversed STORE! this should not ever be used
2390 offsmul
= (dststep
* (subvl
+1)) + dsubstep
2391 log("D-field dst", imm
, offsmul
, ldstmode
)
2392 # Unit-Strided LD/ST adds offset*width to immediate
2393 if ldstmode
== SVP64LDSTmode
.UNITSTRIDE
.value
:
2394 ldst_len
= yield self
.dec2
.e
.do
.data_len
2395 imm
= SelectableInt(imm
+ offsmul
* ldst_len
, 32)
2397 # Element-strided multiplies the immediate by element step
2398 elif ldstmode
== SVP64LDSTmode
.ELSTRIDE
.value
:
2399 imm
= SelectableInt(imm
* offsmul
, 32)
2402 ldst_ra_vec
= yield self
.dec2
.rm_dec
.ldst_ra_vec
2403 ldst_imz_in
= yield self
.dec2
.rm_dec
.ldst_imz_in
2404 log("LDSTmode", SVP64LDSTmode(ldstmode
),
2405 offsmul
, imm
, ldst_ra_vec
, ldst_imz_in
)
2406 # new replacement D... errr.. DS
2408 if info
.form
== 'DS':
2409 # TODO: assert 2 LSBs are zero?
2410 log("DS-Form, TODO, assert 2 LSBs zero?", bin(imm
.value
))
2411 imm
.value
= imm
.value
>> 2
2412 self
.namespace
['DS'] = imm
2414 self
.namespace
['D'] = imm
2416 def get_input(self
, name
, ew_src
):
2417 # using PowerDecoder2, first, find the decoder index.
2418 # (mapping name RA RB RC RS to in1, in2, in3)
2419 regnum
, is_vec
= yield from get_idx_in(self
.dec2
, name
, True)
2421 # doing this is not part of svp64, it's because output
2422 # registers, to be modified, need to be in the namespace.
2423 regnum
, is_vec
= yield from get_idx_out(self
.dec2
, name
, True)
2425 regnum
, is_vec
= yield from get_idx_out2(self
.dec2
, name
, True)
2427 if isinstance(regnum
, tuple):
2428 (regnum
, base
, offs
) = regnum
2430 base
, offs
= regnum
, 0 # temporary HACK
2432 # in case getting the register number is needed, _RA, _RB
2433 # (HACK: only in straight non-svp64-mode for now, or elwidth == 64)
2434 regname
= "_" + name
2435 if not self
.is_svp64_mode
or ew_src
== 64:
2436 self
.namespace
[regname
] = regnum
2437 elif regname
in self
.namespace
:
2438 del self
.namespace
[regname
]
2440 if not self
.is_svp64_mode
or not self
.pred_src_zero
:
2441 log('reading reg %s %s' % (name
, str(regnum
)), is_vec
)
2443 reg_val
= SelectableInt(self
.fpr(base
, is_vec
, offs
, ew_src
))
2444 log("read reg %d/%d: 0x%x" % (base
, offs
, reg_val
.value
),
2445 kind
=LogKind
.InstrInOuts
)
2446 self
.trace("r:FPR:%d:%d:%d " % (base
, offs
, ew_src
))
2447 elif name
is not None:
2448 reg_val
= SelectableInt(self
.gpr(base
, is_vec
, offs
, ew_src
))
2449 self
.trace("r:GPR:%d:%d:%d " % (base
, offs
, ew_src
))
2450 log("read reg %d/%d: 0x%x" % (base
, offs
, reg_val
.value
),
2451 kind
=LogKind
.InstrInOuts
)
2453 log('zero input reg %s %s' % (name
, str(regnum
)), is_vec
)
2454 reg_val
= SelectableInt(0, ew_src
)
2457 def remap_set_steps(self
, remaps
):
2458 """remap_set_steps sets up the in1/2/3 and out1/2 steps.
2459 they work in concert with PowerDecoder2 at the moment,
2460 there is no HDL implementation of REMAP. therefore this
2461 function, because ISACaller still uses PowerDecoder2,
2462 will *explicitly* write the dec2.XX_step values. this has
2465 # just some convenient debug info
2467 sname
= 'SVSHAPE%d' % i
2468 shape
= self
.spr
[sname
]
2469 log(sname
, bin(shape
.value
))
2470 log(" lims", shape
.lims
)
2471 log(" mode", shape
.mode
)
2472 log(" skip", shape
.skip
)
2474 # set up the list of steps to remap
2475 mi0
= self
.svstate
.mi0
2476 mi1
= self
.svstate
.mi1
2477 mi2
= self
.svstate
.mi2
2478 mo0
= self
.svstate
.mo0
2479 mo1
= self
.svstate
.mo1
2480 steps
= [[self
.dec2
.in1_step
, mi0
], # RA
2481 [self
.dec2
.in2_step
, mi1
], # RB
2482 [self
.dec2
.in3_step
, mi2
], # RC
2483 [self
.dec2
.o_step
, mo0
], # RT
2484 [self
.dec2
.o2_step
, mo1
], # EA
2487 rnames
= ['RA', 'RB', 'RC', 'RT', 'RS']
2488 for i
, reg
in enumerate(rnames
):
2489 idx
= yield from get_idx_map(self
.dec2
, reg
)
2491 idx
= yield from get_idx_map(self
.dec2
, "F"+reg
)
2493 steps
[i
][0] = self
.dec2
.in1_step
2495 steps
[i
][0] = self
.dec2
.in2_step
2497 steps
[i
][0] = self
.dec2
.in3_step
2498 log("remap step", i
, reg
, idx
, steps
[i
][1])
2499 remap_idxs
= self
.remap_idxs
2501 # now cross-index the required SHAPE for each of 3-in 2-out regs
2502 rnames
= ['RA', 'RB', 'RC', 'RT', 'EA']
2503 for i
, (dstep
, shape_idx
) in enumerate(steps
):
2504 (shape
, remap
) = remaps
[shape_idx
]
2505 remap_idx
= remap_idxs
[shape_idx
]
2506 # zero is "disabled"
2507 if shape
.value
== 0x0:
2509 # now set the actual requested step to the current index
2510 if dstep
is not None:
2511 yield dstep
.eq(remap_idx
)
2513 # debug printout info
2514 rremaps
.append((shape
.mode
, hex(shape
.value
), dstep
,
2515 i
, rnames
[i
], shape_idx
, remap_idx
))
2517 log("shape remap", x
)
2519 def check_write(self
, info
, name
, output
, carry_en
, ew_dst
):
2520 if name
== 'overflow': # ignore, done already (above)
2522 if name
== 'CR0': # ignore, done already (above)
2524 if isinstance(output
, int):
2525 output
= SelectableInt(output
, EFFECTIVELY_UNLIMITED
)
2527 if name
in ['FPSCR', ]:
2528 log("write FPSCR 0x%x" % (output
.value
))
2529 self
.FPSCR
.eq(output
)
2532 if name
in ['CA', 'CA32']:
2534 log("writing %s to XER" % name
, output
)
2535 log("write XER %s 0x%x" % (name
, output
.value
))
2536 self
.spr
['XER'][XER_bits
[name
]] = output
.value
2538 log("NOT writing %s to XER" % name
, output
)
2540 # write special SPRs
2541 if name
in info
.special_regs
:
2542 log('writing special %s' % name
, output
, special_sprs
)
2543 log("write reg %s 0x%x" % (name
, output
.value
),
2544 kind
=LogKind
.InstrInOuts
)
2545 if name
in special_sprs
:
2546 self
.spr
[name
] = output
2548 self
.namespace
[name
].eq(output
)
2550 log('msr written', hex(self
.msr
.value
))
2552 # find out1/out2 PR/FPR
2553 regnum
, is_vec
= yield from get_idx_out(self
.dec2
, name
, True)
2555 regnum
, is_vec
= yield from get_idx_out2(self
.dec2
, name
, True)
2557 # temporary hack for not having 2nd output
2558 regnum
= yield getattr(self
.decoder
, name
)
2560 # convenient debug prefix
2565 # check zeroing due to predicate bit being zero
2566 if self
.is_svp64_mode
and self
.pred_dst_zero
:
2567 log('zeroing reg %s %s' % (str(regnum
), str(output
)), is_vec
)
2568 output
= SelectableInt(0, EFFECTIVELY_UNLIMITED
)
2569 log("write reg %s%s 0x%x ew %d" % (reg_prefix
, str(regnum
),
2570 output
.value
, ew_dst
),
2571 kind
=LogKind
.InstrInOuts
)
2572 # zero-extend tov64 bit begore storing (should use EXT oh well)
2573 if output
.bits
> 64:
2574 output
= SelectableInt(output
.value
, 64)
2575 rnum
, base
, offset
= regnum
2577 self
.fpr
.write(regnum
, output
, is_vec
, ew_dst
)
2578 self
.trace("w:FPR:%d:%d:%d " % (rnum
, offset
, ew_dst
))
2580 self
.gpr
.write(regnum
, output
, is_vec
, ew_dst
)
2581 self
.trace("w:GPR:%d:%d:%d " % (rnum
, offset
, ew_dst
))
2583 def check_step_increment(self
, rc_en
, asmop
, ins_name
):
2584 # check if it is the SVSTATE.src/dest step that needs incrementing
2585 # this is our Sub-Program-Counter loop from 0 to VL-1
2586 if not self
.allow_next_step_inc
:
2587 if self
.is_svp64_mode
:
2588 return (yield from self
.svstate_post_inc(ins_name
))
2590 # XXX only in non-SVP64 mode!
2591 # record state of whether the current operation was an svshape,
2593 # to be able to know if it should apply in the next instruction.
2594 # also (if going to use this instruction) should disable ability
2595 # to interrupt in between. sigh.
2596 self
.last_op_svshape
= asmop
in ['svremap', 'svindex',
2603 log("SVSTATE_NEXT: inc requested, mode",
2604 self
.svstate_next_mode
, self
.allow_next_step_inc
)
2605 yield from self
.svstate_pre_inc()
2606 pre
= yield from self
.update_new_svstate_steps()
2608 # reset at end of loop including exit Vertical Mode
2609 log("SVSTATE_NEXT: end of loop, reset")
2610 self
.svp64_reset_loop()
2611 self
.svstate
.vfirst
= 0
2615 self
.handle_comparison(SelectableInt(0, 64)) # CR0
2617 if self
.allow_next_step_inc
== 2:
2618 log("SVSTATE_NEXT: read")
2619 nia_update
= (yield from self
.svstate_post_inc(ins_name
))
2621 log("SVSTATE_NEXT: post-inc")
2622 # use actual (cached) src/dst-step here to check end
2623 remaps
= self
.get_remap_indices()
2624 remap_idxs
= self
.remap_idxs
2625 vl
= self
.svstate
.vl
2626 subvl
= yield self
.dec2
.rm_dec
.rm_in
.subvl
2627 if self
.allow_next_step_inc
!= 2:
2628 yield from self
.advance_svstate_steps()
2629 #self.namespace['SVSTATE'] = self.svstate.spr
2630 # set CR0 (if Rc=1) based on end
2631 endtest
= 1 if self
.at_loopend() else 0
2633 #results = [SelectableInt(endtest, 64)]
2634 # self.handle_comparison(results) # CR0
2636 # see if svstep was requested, if so, which SVSTATE
2638 if self
.svstate_next_mode
> 0:
2639 shape_idx
= self
.svstate_next_mode
.value
-1
2640 endings
= self
.remap_loopends
[shape_idx
]
2641 cr_field
= SelectableInt((~endings
) << 1 | endtest
, 4)
2642 log("svstep Rc=1, CR0", cr_field
, endtest
)
2643 self
.crl
[0].eq(cr_field
) # CR0
2645 # reset at end of loop including exit Vertical Mode
2646 log("SVSTATE_NEXT: after increments, reset")
2647 self
.svp64_reset_loop()
2648 self
.svstate
.vfirst
= 0
2651 def SVSTATE_NEXT(self
, mode
, submode
):
2652 """explicitly moves srcstep/dststep on to next element, for
2653 "Vertical-First" mode. this function is called from
2654 setvl pseudo-code, as a pseudo-op "svstep"
2656 WARNING: this function uses information that was created EARLIER
2657 due to it being in the middle of a yield, but this function is
2658 *NOT* called from yield (it's called from compiled pseudocode).
2660 self
.allow_next_step_inc
= submode
.value
+ 1
2661 log("SVSTATE_NEXT mode", mode
, submode
, self
.allow_next_step_inc
)
2662 self
.svstate_next_mode
= mode
2663 if self
.svstate_next_mode
> 0 and self
.svstate_next_mode
< 5:
2664 shape_idx
= self
.svstate_next_mode
.value
-1
2665 return SelectableInt(self
.remap_idxs
[shape_idx
], 7)
2666 if self
.svstate_next_mode
== 5:
2667 self
.svstate_next_mode
= 0
2668 return SelectableInt(self
.svstate
.srcstep
, 7)
2669 if self
.svstate_next_mode
== 6:
2670 self
.svstate_next_mode
= 0
2671 return SelectableInt(self
.svstate
.dststep
, 7)
2672 if self
.svstate_next_mode
== 7:
2673 self
.svstate_next_mode
= 0
2674 return SelectableInt(self
.svstate
.ssubstep
, 7)
2675 if self
.svstate_next_mode
== 8:
2676 self
.svstate_next_mode
= 0
2677 return SelectableInt(self
.svstate
.dsubstep
, 7)
2678 return SelectableInt(0, 7)
2680 def get_src_dststeps(self
):
2681 """gets srcstep, dststep, and ssubstep, dsubstep
2683 return (self
.new_srcstep
, self
.new_dststep
,
2684 self
.new_ssubstep
, self
.new_dsubstep
)
2686 def update_svstate_namespace(self
, overwrite_svstate
=True):
2687 if overwrite_svstate
:
2688 # note, do not get the bit-reversed srcstep here!
2689 srcstep
, dststep
= self
.new_srcstep
, self
.new_dststep
2690 ssubstep
, dsubstep
= self
.new_ssubstep
, self
.new_dsubstep
2692 # update SVSTATE with new srcstep
2693 self
.svstate
.srcstep
= srcstep
2694 self
.svstate
.dststep
= dststep
2695 self
.svstate
.ssubstep
= ssubstep
2696 self
.svstate
.dsubstep
= dsubstep
2697 self
.namespace
['SVSTATE'] = self
.svstate
2698 yield self
.dec2
.state
.svstate
.eq(self
.svstate
.value
)
2699 yield Settle() # let decoder update
2701 def update_new_svstate_steps(self
, overwrite_svstate
=True):
2702 yield from self
.update_svstate_namespace(overwrite_svstate
)
2703 srcstep
= self
.svstate
.srcstep
2704 dststep
= self
.svstate
.dststep
2705 ssubstep
= self
.svstate
.ssubstep
2706 dsubstep
= self
.svstate
.dsubstep
2707 pack
= self
.svstate
.pack
2708 unpack
= self
.svstate
.unpack
2709 vl
= self
.svstate
.vl
2710 sv_mode
= yield self
.dec2
.rm_dec
.sv_mode
2711 subvl
= yield self
.dec2
.rm_dec
.rm_in
.subvl
2712 rm_mode
= yield self
.dec2
.rm_dec
.mode
2713 ff_inv
= yield self
.dec2
.rm_dec
.inv
2714 cr_bit
= yield self
.dec2
.rm_dec
.cr_sel
2715 log(" srcstep", srcstep
)
2716 log(" dststep", dststep
)
2718 log(" unpack", unpack
)
2719 log(" ssubstep", ssubstep
)
2720 log(" dsubstep", dsubstep
)
2722 log(" subvl", subvl
)
2723 log(" rm_mode", rm_mode
)
2724 log(" sv_mode", sv_mode
)
2726 log(" cr_bit", cr_bit
)
2728 # check if end reached (we let srcstep overrun, above)
2729 # nothing needs doing (TODO zeroing): just do next instruction
2732 return ((ssubstep
== subvl
and srcstep
== vl
) or
2733 (dsubstep
== subvl
and dststep
== vl
))
2735 def svstate_post_inc(self
, insn_name
, vf
=0):
2736 # check if SV "Vertical First" mode is enabled
2737 vfirst
= self
.svstate
.vfirst
2738 log(" SV Vertical First", vf
, vfirst
)
2739 if not vf
and vfirst
== 1:
2743 # check if it is the SVSTATE.src/dest step that needs incrementing
2744 # this is our Sub-Program-Counter loop from 0 to VL-1
2745 # XXX twin predication TODO
2746 vl
= self
.svstate
.vl
2747 subvl
= yield self
.dec2
.rm_dec
.rm_in
.subvl
2748 mvl
= self
.svstate
.maxvl
2749 srcstep
= self
.svstate
.srcstep
2750 dststep
= self
.svstate
.dststep
2751 ssubstep
= self
.svstate
.ssubstep
2752 dsubstep
= self
.svstate
.dsubstep
2753 pack
= self
.svstate
.pack
2754 unpack
= self
.svstate
.unpack
2755 rm_mode
= yield self
.dec2
.rm_dec
.mode
2756 reverse_gear
= yield self
.dec2
.rm_dec
.reverse_gear
2757 sv_ptype
= yield self
.dec2
.dec
.op
.SV_Ptype
2758 out_vec
= not (yield self
.dec2
.no_out_vec
)
2759 in_vec
= not (yield self
.dec2
.no_in_vec
)
2760 log(" svstate.vl", vl
)
2761 log(" svstate.mvl", mvl
)
2762 log(" rm.subvl", subvl
)
2763 log(" svstate.srcstep", srcstep
)
2764 log(" svstate.dststep", dststep
)
2765 log(" svstate.ssubstep", ssubstep
)
2766 log(" svstate.dsubstep", dsubstep
)
2767 log(" svstate.pack", pack
)
2768 log(" svstate.unpack", unpack
)
2769 log(" mode", rm_mode
)
2770 log(" reverse", reverse_gear
)
2771 log(" out_vec", out_vec
)
2772 log(" in_vec", in_vec
)
2773 log(" sv_ptype", sv_ptype
, sv_ptype
== SVPType
.P2
.value
)
2774 # check if this was an sv.bc* and if so did it succeed
2775 if self
.is_svp64_mode
and insn_name
.startswith("sv.bc"):
2776 end_loop
= self
.namespace
['end_loop']
2777 log("branch %s end_loop" % insn_name
, end_loop
)
2779 self
.svp64_reset_loop()
2780 self
.update_pc_next()
2782 # check if srcstep needs incrementing by one, stop PC advancing
2783 # but for 2-pred both src/dest have to be checked.
2784 # XXX this might not be true! it may just be LD/ST
2785 if sv_ptype
== SVPType
.P2
.value
:
2786 svp64_is_vector
= (out_vec
or in_vec
)
2788 svp64_is_vector
= out_vec
2789 # loops end at the first "hit" (source or dest)
2790 yield from self
.advance_svstate_steps()
2791 loopend
= self
.loopend
2792 log("loopend", svp64_is_vector
, loopend
)
2793 if not svp64_is_vector
or loopend
:
2794 # reset loop to zero and update NIA
2795 self
.svp64_reset_loop()
2800 # still looping, advance and update NIA
2801 self
.namespace
['SVSTATE'] = self
.svstate
2803 # not an SVP64 branch, so fix PC (NIA==CIA) for next loop
2804 # (by default, NIA is CIA+4 if v3.0B or CIA+8 if SVP64)
2805 # this way we keep repeating the same instruction (with new steps)
2806 self
.pc
.NIA
.value
= self
.pc
.CIA
.value
2807 self
.namespace
['NIA'] = self
.pc
.NIA
2808 log("end of sub-pc call", self
.namespace
['CIA'], self
.namespace
['NIA'])
2809 return False # DO NOT allow PC update whilst Sub-PC loop running
2811 def update_pc_next(self
):
2812 # UPDATE program counter
2813 self
.pc
.update(self
.namespace
, self
.is_svp64_mode
)
2814 #self.svstate.spr = self.namespace['SVSTATE']
2815 log("end of call", self
.namespace
['CIA'],
2816 self
.namespace
['NIA'],
2817 self
.namespace
['SVSTATE'])
2819 def svp64_reset_loop(self
):
2820 self
.svstate
.srcstep
= 0
2821 self
.svstate
.dststep
= 0
2822 self
.svstate
.ssubstep
= 0
2823 self
.svstate
.dsubstep
= 0
2824 self
.loopend
= False
2825 log(" svstate.srcstep loop end (PC to update)")
2826 self
.namespace
['SVSTATE'] = self
.svstate
2828 def update_nia(self
):
2829 self
.pc
.update_nia(self
.is_svp64_mode
)
2830 self
.namespace
['NIA'] = self
.pc
.NIA
2834 """Decorator factory.
2836 this decorator will "inject" variables into the function's namespace,
2837 from the *dictionary* in self.namespace. it therefore becomes possible
2838 to make it look like a whole stack of variables which would otherwise
2839 need "self." inserted in front of them (*and* for those variables to be
2840 added to the instance) "appear" in the function.
2842 "self.namespace['SI']" for example becomes accessible as just "SI" but
2843 *only* inside the function, when decorated.
2845 def variable_injector(func
):
2847 def decorator(*args
, **kwargs
):
2849 func_globals
= func
.__globals
__ # Python 2.6+
2850 except AttributeError:
2851 func_globals
= func
.func_globals
# Earlier versions.
2853 context
= args
[0].namespace
# variables to be injected
2854 saved_values
= func_globals
.copy() # Shallow copy of dict.
2855 log("globals before", context
.keys())
2856 func_globals
.update(context
)
2857 result
= func(*args
, **kwargs
)
2858 log("globals after", func_globals
['CIA'], func_globals
['NIA'])
2859 log("args[0]", args
[0].namespace
['CIA'],
2860 args
[0].namespace
['NIA'],
2861 args
[0].namespace
['SVSTATE'])
2862 if 'end_loop' in func_globals
:
2863 log("args[0] end_loop", func_globals
['end_loop'])
2864 args
[0].namespace
= func_globals
2865 #exec (func.__code__, func_globals)
2868 # func_globals = saved_values # Undo changes.
2874 return variable_injector