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
22 from openpower
.syscalls
import ppc_flags
24 from elftools
.elf
.elffile
import ELFFile
# for isinstance
26 from nmigen
.sim
import Settle
27 import openpower
.syscalls
28 from openpower
.consts
import (MSRb
, PIb
, # big-endian (PowerISA versions)
29 SVP64CROffs
, SVP64MODEb
)
30 from openpower
.decoder
.helpers
import (ISACallerHelper
, ISAFPHelpers
, exts
,
31 gtu
, undefined
, copy_assign_rhs
)
32 from openpower
.decoder
.isa
.mem
import Mem
, MemMMap
, MemException
, LoadedELF
33 from openpower
.decoder
.isa
.radixmmu
import RADIX
34 from openpower
.decoder
.isa
.svshape
import SVSHAPE
35 from openpower
.decoder
.isa
.svstate
import SVP64State
36 from openpower
.decoder
.orderedset
import OrderedSet
37 from openpower
.decoder
.power_enums
import (FPTRANS_INSNS
, CRInSel
, CROutSel
,
38 In1Sel
, In2Sel
, In3Sel
, LDSTMode
,
39 MicrOp
, OutSel
, SVMode
,
40 SVP64LDSTmode
, SVP64PredCR
,
41 SVP64PredInt
, SVP64PredMode
,
42 SVP64RMMode
, SVPType
, XER_bits
,
43 insns
, spr_byname
, spr_dict
,
45 from openpower
.insndb
.core
import SVP64Instruction
46 from openpower
.decoder
.power_svp64
import SVP64RM
, decode_extra
47 from openpower
.decoder
.selectable_int
import (FieldSelectableInt
,
48 SelectableInt
, selectconcat
,
49 EFFECTIVELY_UNLIMITED
)
50 from openpower
.consts
import DEFAULT_MSR
51 from openpower
.fpscr
import FPSCRState
52 from openpower
.xer
import XERState
53 from openpower
.util
import LogType
, log
55 LDST_UPDATE_INSNS
= ['ldu', 'lwzu', 'lbzu', 'lhzu', 'lhau', 'lfsu', 'lfdu',
56 'stwu', 'stbu', 'sthu', 'stfsu', 'stfdu', 'stdu',
60 instruction_info
= namedtuple('instruction_info',
61 'func read_regs uninit_regs write_regs ' +
62 'special_regs op_fields form asmregs')
72 # rrright. this is here basically because the compiler pywriter returns
73 # results in a specific priority order. to make sure regs match up they
74 # need partial sorting. sigh.
76 # TODO (lkcl): adjust other registers that should be in a particular order
77 # probably CA, CA32, and CR
105 "overflow": 7, # should definitely be last
109 fregs
= ['FRA', 'FRB', 'FRC', 'FRS', 'FRT']
112 def get_masked_reg(regs
, base
, offs
, ew_bits
):
113 # rrrright. start by breaking down into row/col, based on elwidth
114 gpr_offs
= offs
// (64 // ew_bits
)
115 gpr_col
= offs
% (64 // ew_bits
)
116 # compute the mask based on ew_bits
117 mask
= (1 << ew_bits
) - 1
118 # now select the 64-bit register, but get its value (easier)
119 val
= regs
[base
+ gpr_offs
]
120 # shift down so element we want is at LSB
121 val
>>= gpr_col
* ew_bits
122 # mask so we only return the LSB element
126 def set_masked_reg(regs
, base
, offs
, ew_bits
, value
):
127 # rrrright. start by breaking down into row/col, based on elwidth
128 gpr_offs
= offs
// (64//ew_bits
)
129 gpr_col
= offs
% (64//ew_bits
)
130 # compute the mask based on ew_bits
131 mask
= (1 << ew_bits
)-1
132 # now select the 64-bit register, but get its value (easier)
133 val
= regs
[base
+gpr_offs
]
134 # now mask out the bit we don't want
135 val
= val
& ~
(mask
<< (gpr_col
*ew_bits
))
136 # then wipe the bit we don't want from the value
138 # OR the new value in, shifted up
139 val |
= value
<< (gpr_col
*ew_bits
)
140 regs
[base
+gpr_offs
] = val
143 def create_args(reglist
, extra
=None):
144 retval
= list(OrderedSet(reglist
))
145 retval
.sort(key
=lambda reg
: REG_SORT_ORDER
.get(reg
, 0))
146 if extra
is not None:
147 return [extra
] + retval
151 def create_full_args(*, read_regs
, special_regs
, uninit_regs
, write_regs
,
154 *read_regs
, *uninit_regs
, *write_regs
, *special_regs
], extra
=extra
)
157 def is_ffirst_mode(dec2
):
158 rm_mode
= yield dec2
.rm_dec
.mode
159 return rm_mode
== SVP64RMMode
.FFIRST
.value
163 def __init__(self
, decoder
, isacaller
, svstate
, regfile
):
166 self
.isacaller
= isacaller
167 self
.svstate
= svstate
168 for i
in range(len(regfile
)):
169 self
[i
] = SelectableInt(regfile
[i
], 64)
171 def __call__(self
, ridx
, is_vec
=False, offs
=0, elwidth
=64):
172 if isinstance(ridx
, SelectableInt
):
174 # scalar is enforced here
178 return self
[ridx
+offs
]
179 # rrrright. start by breaking down into row/col, based on elwidth
180 gpr_offs
= offs
// (64//elwidth
)
181 gpr_col
= offs
% (64//elwidth
)
182 # now select the 64-bit register, but get its value (easier)
183 val
= self
[ridx
+gpr_offs
].value
184 # now shift down and mask out
185 val
= val
>> (gpr_col
*elwidth
) & ((1 << elwidth
)-1)
186 # finally, return a SelectableInt at the required elwidth
187 log("GPR call", ridx
, "isvec", is_vec
, "offs", offs
,
188 "elwid", elwidth
, "offs/col", gpr_offs
, gpr_col
, "val", hex(val
))
189 return SelectableInt(val
, elwidth
)
191 def set_form(self
, form
):
194 def write(self
, rnum
, value
, is_vec
=False, elwidth
=64):
196 if isinstance(rnum
, SelectableInt
):
198 if isinstance(value
, SelectableInt
):
201 if isinstance(rnum
, tuple):
202 rnum
, base
, offs
= rnum
205 # rrrright. start by breaking down into row/col, based on elwidth
206 gpr_offs
= offs
// (64//elwidth
)
207 gpr_col
= offs
% (64//elwidth
)
208 # compute the mask based on elwidth
209 mask
= (1 << elwidth
)-1
210 # now select the 64-bit register, but get its value (easier)
211 val
= self
[base
+gpr_offs
].value
212 # now mask out the bit we don't want
213 val
= val
& ~
(mask
<< (gpr_col
*elwidth
))
214 # then wipe the bit we don't want from the value
216 # OR the new value in, shifted up
217 val |
= value
<< (gpr_col
*elwidth
)
218 # finally put the damn value into the regfile
219 log("GPR write", base
, "isvec", is_vec
, "offs", offs
,
220 "elwid", elwidth
, "offs/col", gpr_offs
, gpr_col
, "val", hex(val
),
222 dict.__setitem
__(self
, base
+gpr_offs
, SelectableInt(val
, 64))
224 def __setitem__(self
, rnum
, value
):
225 # rnum = rnum.value # only SelectableInt allowed
226 log("GPR setitem", rnum
, value
)
227 if isinstance(rnum
, SelectableInt
):
229 dict.__setitem
__(self
, rnum
, value
)
231 def getz(self
, rnum
, rvalue
=None):
232 # rnum = rnum.value # only SelectableInt allowed
233 log("GPR getzero?", rnum
, rvalue
)
234 if rvalue
is not None:
236 return SelectableInt(0, rvalue
.bits
)
239 return SelectableInt(0, 64)
242 def _get_regnum(self
, attr
):
243 getform
= self
.sd
.sigforms
[self
.form
]
244 rnum
= getattr(getform
, attr
)
247 def ___getitem__(self
, attr
):
248 """ XXX currently not used
250 rnum
= self
._get
_regnum
(attr
)
251 log("GPR getitem", attr
, rnum
)
252 return self
.regfile
[rnum
]
254 def dump(self
, printout
=True, heading
="reg"):
256 for i
in range(len(self
)):
257 res
.append(self
[i
].value
)
259 for i
in range(0, len(res
), 8):
262 s
.append("%08x" % res
[i
+j
])
264 log(heading
, "%2d" % i
, s
, kind
=LogType
.InstrInOuts
)
269 def __init__(self
, dec2
, initial_sprs
={}, gpr
=None):
271 self
.gpr
= gpr
# for SVSHAPE[0-3]
273 for key
, v
in initial_sprs
.items():
274 if isinstance(key
, SelectableInt
):
276 key
= special_sprs
.get(key
, key
)
277 if isinstance(key
, int):
280 info
= spr_byname
[key
]
281 if not isinstance(v
, SelectableInt
):
282 v
= SelectableInt(v
, info
.length
)
285 def __getitem__(self
, key
):
287 #log("dict", self.items())
288 # if key in special_sprs get the special spr, otherwise return key
289 if isinstance(key
, SelectableInt
):
291 if isinstance(key
, int):
292 key
= spr_dict
[key
].SPR
293 key
= special_sprs
.get(key
, key
)
294 if key
== 'HSRR0': # HACK!
296 if key
== 'HSRR1': # HACK!
299 res
= dict.__getitem
__(self
, key
)
301 if isinstance(key
, int):
304 info
= spr_byname
[key
]
305 self
[key
] = SelectableInt(0, info
.length
)
306 res
= dict.__getitem
__(self
, key
)
307 #log("spr returning", key, res)
310 def __setitem__(self
, key
, value
):
311 if isinstance(key
, SelectableInt
):
313 if isinstance(key
, int):
314 key
= spr_dict
[key
].SPR
316 key
= special_sprs
.get(key
, key
)
317 if key
== 'HSRR0': # HACK!
318 self
.__setitem
__('SRR0', value
)
319 if key
== 'HSRR1': # HACK!
320 self
.__setitem
__('SRR1', value
)
322 value
= XERState(value
)
323 if key
in ('SVSHAPE0', 'SVSHAPE1', 'SVSHAPE2', 'SVSHAPE3'):
324 value
= SVSHAPE(value
, self
.gpr
)
325 log("setting spr", key
, value
)
326 dict.__setitem
__(self
, key
, value
)
328 def __call__(self
, ridx
):
331 def dump(self
, printout
=True):
333 keys
= list(self
.keys())
336 sprname
= spr_dict
.get(k
, None)
340 sprname
= sprname
.SPR
341 res
.append((sprname
, self
[k
].value
))
343 for sprname
, value
in res
:
344 print(" ", sprname
, hex(value
))
349 def __init__(self
, pc_init
=0):
350 self
.CIA
= SelectableInt(pc_init
, 64)
351 self
.NIA
= self
.CIA
+ SelectableInt(4, 64) # only true for v3.0B!
353 def update_nia(self
, is_svp64
):
354 increment
= 8 if is_svp64
else 4
355 self
.NIA
= self
.CIA
+ SelectableInt(increment
, 64)
357 def update(self
, namespace
, is_svp64
):
358 """updates the program counter (PC) by 4 if v3.0B mode or 8 if SVP64
360 self
.CIA
= namespace
['NIA'].narrow(64)
361 self
.update_nia(is_svp64
)
362 namespace
['CIA'] = self
.CIA
363 namespace
['NIA'] = self
.NIA
367 # See PowerISA Version 3.0 B Book 1
368 # Section 2.3.1 Condition Register pages 30 - 31
370 LT
= FL
= 0 # negative, less than, floating-point less than
371 GT
= FG
= 1 # positive, greater than, floating-point greater than
372 EQ
= FE
= 2 # equal, floating-point equal
373 SO
= FU
= 3 # summary overflow, floating-point unordered
375 def __init__(self
, init
=0):
376 # rev_cr = int('{:016b}'.format(initial_cr)[::-1], 2)
377 # self.cr = FieldSelectableInt(self._cr, list(range(32, 64)))
378 self
.cr
= SelectableInt(init
, 64) # underlying reg
379 # field-selectable versions of Condition Register TODO check bitranges?
382 bits
= tuple(range(i
*4+32, (i
+1)*4+32))
383 _cr
= FieldSelectableInt(self
.cr
, bits
)
387 # decode SVP64 predicate integer to reg number and invert
388 def get_predint(gpr
, mask
):
392 log("get_predint", mask
, SVP64PredInt
.ALWAYS
.value
)
393 if mask
== SVP64PredInt
.ALWAYS
.value
:
394 return 0xffff_ffff_ffff_ffff # 64 bits of 1
395 if mask
== SVP64PredInt
.R3_UNARY
.value
:
396 return 1 << (r3
.value
& 0b111111)
397 if mask
== SVP64PredInt
.R3
.value
:
399 if mask
== SVP64PredInt
.R3_N
.value
:
401 if mask
== SVP64PredInt
.R10
.value
:
403 if mask
== SVP64PredInt
.R10_N
.value
:
405 if mask
== SVP64PredInt
.R30
.value
:
407 if mask
== SVP64PredInt
.R30_N
.value
:
411 # decode SVP64 predicate CR to reg number and invert status
412 def _get_predcr(mask
):
413 if mask
== SVP64PredCR
.LT
.value
:
415 if mask
== SVP64PredCR
.GE
.value
:
417 if mask
== SVP64PredCR
.GT
.value
:
419 if mask
== SVP64PredCR
.LE
.value
:
421 if mask
== SVP64PredCR
.EQ
.value
:
423 if mask
== SVP64PredCR
.NE
.value
:
425 if mask
== SVP64PredCR
.SO
.value
:
427 if mask
== SVP64PredCR
.NS
.value
:
431 # read individual CR fields (0..VL-1), extract the required bit
432 # and construct the mask
433 def get_predcr(crl
, predselect
, vl
):
434 idx
, noninv
= _get_predcr(predselect
)
437 cr
= crl
[i
+SVP64CROffs
.CRPred
]
438 if cr
[idx
].value
== noninv
:
440 log("get_predcr", vl
, idx
, noninv
, i
+SVP64CROffs
.CRPred
,
441 bin(cr
.asint()), cr
[idx
].value
, bin(mask
))
445 # TODO, really should just be using PowerDecoder2
446 def get_idx_map(dec2
, name
):
448 in1_sel
= yield op
.in1_sel
449 in2_sel
= yield op
.in2_sel
450 in3_sel
= yield op
.in3_sel
451 in1
= yield dec2
.e
.read_reg1
.data
452 # identify which regnames map to in1/2/3
453 if name
== 'RA' or name
== 'RA_OR_ZERO':
454 if (in1_sel
== In1Sel
.RA
.value
or
455 (in1_sel
== In1Sel
.RA_OR_ZERO
.value
and in1
!= 0)):
457 if in1_sel
== In1Sel
.RA_OR_ZERO
.value
:
460 if in2_sel
== In2Sel
.RB
.value
:
462 if in3_sel
== In3Sel
.RB
.value
:
464 # XXX TODO, RC doesn't exist yet!
466 if in3_sel
== In3Sel
.RC
.value
:
468 elif name
in ['EA', 'RS']:
469 if in1_sel
== In1Sel
.RS
.value
:
471 if in2_sel
== In2Sel
.RS
.value
:
473 if in3_sel
== In3Sel
.RS
.value
:
476 if in1_sel
== In1Sel
.FRA
.value
:
478 if in3_sel
== In3Sel
.FRA
.value
:
481 if in2_sel
== In2Sel
.FRB
.value
:
484 if in3_sel
== In3Sel
.FRC
.value
:
487 if in1_sel
== In1Sel
.FRS
.value
:
489 if in3_sel
== In3Sel
.FRS
.value
:
492 if in1_sel
== In1Sel
.FRT
.value
:
495 if in1_sel
== In1Sel
.RT
.value
:
500 # TODO, really should just be using PowerDecoder2
501 def get_idx_in(dec2
, name
, ewmode
=False):
502 idx
= yield from get_idx_map(dec2
, name
)
506 in1_sel
= yield op
.in1_sel
507 in2_sel
= yield op
.in2_sel
508 in3_sel
= yield op
.in3_sel
509 # get the IN1/2/3 from the decoder (includes SVP64 remap and isvec)
510 in1
= yield dec2
.e
.read_reg1
.data
511 in2
= yield dec2
.e
.read_reg2
.data
512 in3
= yield dec2
.e
.read_reg3
.data
514 in1_base
= yield dec2
.e
.read_reg1
.base
515 in2_base
= yield dec2
.e
.read_reg2
.base
516 in3_base
= yield dec2
.e
.read_reg3
.base
517 in1_offs
= yield dec2
.e
.read_reg1
.offs
518 in2_offs
= yield dec2
.e
.read_reg2
.offs
519 in3_offs
= yield dec2
.e
.read_reg3
.offs
520 in1
= (in1
, in1_base
, in1_offs
)
521 in2
= (in2
, in2_base
, in2_offs
)
522 in3
= (in3
, in3_base
, in3_offs
)
524 in1_isvec
= yield dec2
.in1_isvec
525 in2_isvec
= yield dec2
.in2_isvec
526 in3_isvec
= yield dec2
.in3_isvec
527 log("get_idx_in in1", name
, in1_sel
, In1Sel
.RA
.value
,
529 log("get_idx_in in2", name
, in2_sel
, In2Sel
.RB
.value
,
531 log("get_idx_in in3", name
, in3_sel
, In3Sel
.RS
.value
,
533 log("get_idx_in FRS in3", name
, in3_sel
, In3Sel
.FRS
.value
,
535 log("get_idx_in FRB in2", name
, in2_sel
, In2Sel
.FRB
.value
,
537 log("get_idx_in FRC in3", name
, in3_sel
, In3Sel
.FRC
.value
,
540 return in1
, in1_isvec
542 return in2
, in2_isvec
544 return in3
, in3_isvec
548 # TODO, really should just be using PowerDecoder2
549 def get_cr_in(dec2
, name
):
551 in_sel
= yield op
.cr_in
552 in_bitfield
= yield dec2
.dec_cr_in
.cr_bitfield
.data
553 sv_cr_in
= yield op
.sv_cr_in
554 spec
= yield dec2
.crin_svdec
.spec
555 sv_override
= yield dec2
.dec_cr_in
.sv_override
556 # get the IN1/2/3 from the decoder (includes SVP64 remap and isvec)
557 in1
= yield dec2
.e
.read_cr1
.data
558 in2
= yield dec2
.e
.read_cr2
.data
559 cr_isvec
= yield dec2
.cr_in_isvec
560 log("get_cr_in", name
, in_sel
, CROutSel
.CR0
.value
, in1
, in2
, cr_isvec
)
561 log(" sv_cr_in", sv_cr_in
)
562 log(" cr_bf", in_bitfield
)
564 log(" override", sv_override
)
565 # identify which regnames map to in / o2
567 if in_sel
== CRInSel
.BI
.value
:
570 if in_sel
== CRInSel
.BA_BB
.value
:
573 if in_sel
== CRInSel
.BA_BB
.value
:
576 if in_sel
== CRInSel
.BFA
.value
:
578 log("get_cr_in not found", name
)
582 # TODO, really should just be using PowerDecoder2
583 def get_cr_out(dec2
, name
):
585 out_sel
= yield op
.cr_out
586 out_bitfield
= yield dec2
.dec_cr_out
.cr_bitfield
.data
587 sv_cr_out
= yield op
.sv_cr_out
588 spec
= yield dec2
.crout_svdec
.spec
589 sv_override
= yield dec2
.dec_cr_out
.sv_override
590 # get the IN1/2/3 from the decoder (includes SVP64 remap and isvec)
591 out
= yield dec2
.e
.write_cr
.data
592 o_isvec
= yield dec2
.cr_out_isvec
593 log("get_cr_out", out_sel
, CROutSel
.CR0
.value
, out
, o_isvec
)
594 log(" sv_cr_out", sv_cr_out
)
595 log(" cr_bf", out_bitfield
)
597 log(" override", sv_override
)
598 # identify which regnames map to out / o2
600 if out_sel
== CROutSel
.BF
.value
:
603 if out_sel
== CROutSel
.BT
.value
:
606 if out_sel
== CROutSel
.CR0
.value
:
608 if name
== 'CR1': # these are not actually calculated correctly
609 if out_sel
== CROutSel
.CR1
.value
:
611 # check RC1 set? if so return implicit vector, this is a REAL bad hack
612 RC1
= yield dec2
.rm_dec
.RC1
614 log("get_cr_out RC1 mode")
616 return 0, True # XXX TODO: offset CR0 from SVSTATE SPR
618 return 1, True # XXX TODO: offset CR1 from SVSTATE SPR
620 log("get_cr_out not found", name
)
624 # TODO, really should just be using PowerDecoder2
625 def get_out_map(dec2
, name
):
627 out_sel
= yield op
.out_sel
628 # get the IN1/2/3 from the decoder (includes SVP64 remap and isvec)
629 out
= yield dec2
.e
.write_reg
.data
630 # identify which regnames map to out / o2
632 if out_sel
== OutSel
.RA
.value
:
635 if out_sel
== OutSel
.RT
.value
:
637 if out_sel
== OutSel
.RT_OR_ZERO
.value
and out
!= 0:
639 elif name
== 'RT_OR_ZERO':
640 if out_sel
== OutSel
.RT_OR_ZERO
.value
:
643 if out_sel
== OutSel
.FRA
.value
:
646 if out_sel
== OutSel
.FRS
.value
:
649 if out_sel
== OutSel
.FRT
.value
:
654 # TODO, really should just be using PowerDecoder2
655 def get_idx_out(dec2
, name
, ewmode
=False):
657 out_sel
= yield op
.out_sel
658 # get the IN1/2/3 from the decoder (includes SVP64 remap and isvec)
659 out
= yield dec2
.e
.write_reg
.data
660 o_isvec
= yield dec2
.o_isvec
662 offs
= yield dec2
.e
.write_reg
.offs
663 base
= yield dec2
.e
.write_reg
.base
664 out
= (out
, base
, offs
)
665 # identify which regnames map to out / o2
666 ismap
= yield from get_out_map(dec2
, name
)
668 log("get_idx_out", name
, out_sel
, out
, o_isvec
)
670 log("get_idx_out not found", name
, out_sel
, out
, o_isvec
)
674 # TODO, really should just be using PowerDecoder2
675 def get_out2_map(dec2
, name
):
676 # check first if register is activated for write
678 out_sel
= yield op
.out_sel
679 out
= yield dec2
.e
.write_ea
.data
680 out_ok
= yield dec2
.e
.write_ea
.ok
684 if name
in ['EA', 'RA']:
685 if hasattr(op
, "upd"):
686 # update mode LD/ST uses read-reg A also as an output
688 log("get_idx_out2", upd
, LDSTMode
.update
.value
,
689 out_sel
, OutSel
.RA
.value
,
691 if upd
== LDSTMode
.update
.value
:
694 fft_en
= yield dec2
.implicit_rs
696 log("get_idx_out2", out_sel
, OutSel
.RS
.value
,
700 fft_en
= yield dec2
.implicit_rs
702 log("get_idx_out2", out_sel
, OutSel
.FRS
.value
,
708 # TODO, really should just be using PowerDecoder2
709 def get_idx_out2(dec2
, name
, ewmode
=False):
710 # check first if register is activated for write
712 out_sel
= yield op
.out_sel
713 out
= yield dec2
.e
.write_ea
.data
715 offs
= yield dec2
.e
.write_ea
.offs
716 base
= yield dec2
.e
.write_ea
.base
717 out
= (out
, base
, offs
)
718 o_isvec
= yield dec2
.o2_isvec
719 ismap
= yield from get_out2_map(dec2
, name
)
721 log("get_idx_out2", name
, out_sel
, out
, o_isvec
)
727 """deals with svstate looping.
730 def __init__(self
, svstate
):
731 self
.svstate
= svstate
734 def new_iterators(self
):
735 self
.src_it
= self
.src_iterator()
736 self
.dst_it
= self
.dst_iterator()
740 self
.new_ssubstep
= 0
741 self
.new_dsubstep
= 0
742 self
.pred_dst_zero
= 0
743 self
.pred_src_zero
= 0
745 def src_iterator(self
):
746 """source-stepping iterator
748 pack
= self
.svstate
.pack
752 # pack advances subvl in *outer* loop
753 while True: # outer subvl loop
754 while True: # inner vl loop
757 srcmask
= self
.srcmask
758 srcstep
= self
.svstate
.srcstep
759 pred_src_zero
= ((1 << srcstep
) & srcmask
) != 0
760 if self
.pred_sz
or pred_src_zero
:
761 self
.pred_src_zero
= not pred_src_zero
762 log(" advance src", srcstep
, vl
,
763 self
.svstate
.ssubstep
, subvl
)
764 # yield actual substep/srcstep
765 yield (self
.svstate
.ssubstep
, srcstep
)
766 # the way yield works these could have been modified.
769 srcstep
= self
.svstate
.srcstep
770 log(" advance src check", srcstep
, vl
,
771 self
.svstate
.ssubstep
, subvl
, srcstep
== vl
-1,
772 self
.svstate
.ssubstep
== subvl
)
773 if srcstep
== vl
-1: # end-point
774 self
.svstate
.srcstep
= SelectableInt(0, 7) # reset
775 if self
.svstate
.ssubstep
== subvl
: # end-point
776 log(" advance pack stop")
778 break # exit inner loop
779 self
.svstate
.srcstep
+= SelectableInt(1, 7) # advance ss
781 if self
.svstate
.ssubstep
== subvl
: # end-point
782 self
.svstate
.ssubstep
= SelectableInt(0, 2) # reset
783 log(" advance pack stop")
785 self
.svstate
.ssubstep
+= SelectableInt(1, 2)
788 # these cannot be done as for-loops because SVSTATE may change
789 # (srcstep/substep may be modified, interrupted, subvl/vl change)
790 # but they *can* be done as while-loops as long as every SVSTATE
791 # "thing" is re-read every single time a yield gives indices
792 while True: # outer vl loop
793 while True: # inner subvl loop
796 srcmask
= self
.srcmask
797 srcstep
= self
.svstate
.srcstep
798 pred_src_zero
= ((1 << srcstep
) & srcmask
) != 0
799 if self
.pred_sz
or pred_src_zero
:
800 self
.pred_src_zero
= not pred_src_zero
801 log(" advance src", srcstep
, vl
,
802 self
.svstate
.ssubstep
, subvl
)
803 # yield actual substep/srcstep
804 yield (self
.svstate
.ssubstep
, srcstep
)
805 if self
.svstate
.ssubstep
== subvl
: # end-point
806 self
.svstate
.ssubstep
= SelectableInt(0, 2) # reset
807 break # exit inner loop
808 self
.svstate
.ssubstep
+= SelectableInt(1, 2)
810 if srcstep
== vl
-1: # end-point
811 self
.svstate
.srcstep
= SelectableInt(0, 7) # reset
814 self
.svstate
.srcstep
+= SelectableInt(1, 7) # advance srcstep
816 def dst_iterator(self
):
817 """dest-stepping iterator
819 unpack
= self
.svstate
.unpack
823 # pack advances subvl in *outer* loop
824 while True: # outer subvl loop
825 while True: # inner vl loop
828 dstmask
= self
.dstmask
829 dststep
= self
.svstate
.dststep
830 pred_dst_zero
= ((1 << dststep
) & dstmask
) != 0
831 if self
.pred_dz
or pred_dst_zero
:
832 self
.pred_dst_zero
= not pred_dst_zero
833 log(" advance dst", dststep
, vl
,
834 self
.svstate
.dsubstep
, subvl
)
835 # yield actual substep/dststep
836 yield (self
.svstate
.dsubstep
, dststep
)
837 # the way yield works these could have been modified.
839 dststep
= self
.svstate
.dststep
840 log(" advance dst check", dststep
, vl
,
841 self
.svstate
.ssubstep
, subvl
)
842 if dststep
== vl
-1: # end-point
843 self
.svstate
.dststep
= SelectableInt(0, 7) # reset
844 if self
.svstate
.dsubstep
== subvl
: # end-point
845 log(" advance unpack stop")
848 self
.svstate
.dststep
+= SelectableInt(1, 7) # advance ds
850 if self
.svstate
.dsubstep
== subvl
: # end-point
851 self
.svstate
.dsubstep
= SelectableInt(0, 2) # reset
852 log(" advance unpack stop")
854 self
.svstate
.dsubstep
+= SelectableInt(1, 2)
856 # these cannot be done as for-loops because SVSTATE may change
857 # (dststep/substep may be modified, interrupted, subvl/vl change)
858 # but they *can* be done as while-loops as long as every SVSTATE
859 # "thing" is re-read every single time a yield gives indices
860 while True: # outer vl loop
861 while True: # inner subvl loop
863 dstmask
= self
.dstmask
864 dststep
= self
.svstate
.dststep
865 pred_dst_zero
= ((1 << dststep
) & dstmask
) != 0
866 if self
.pred_dz
or pred_dst_zero
:
867 self
.pred_dst_zero
= not pred_dst_zero
868 log(" advance dst", dststep
, self
.svstate
.vl
,
869 self
.svstate
.dsubstep
, subvl
)
870 # yield actual substep/dststep
871 yield (self
.svstate
.dsubstep
, dststep
)
872 if self
.svstate
.dsubstep
== subvl
: # end-point
873 self
.svstate
.dsubstep
= SelectableInt(0, 2) # reset
875 self
.svstate
.dsubstep
+= SelectableInt(1, 2)
878 if dststep
== vl
-1: # end-point
879 self
.svstate
.dststep
= SelectableInt(0, 7) # reset
881 self
.svstate
.dststep
+= SelectableInt(1, 7) # advance dststep
883 def src_iterate(self
):
884 """source-stepping iterator
888 pack
= self
.svstate
.pack
889 unpack
= self
.svstate
.unpack
890 ssubstep
= self
.svstate
.ssubstep
891 end_ssub
= ssubstep
== subvl
892 end_src
= self
.svstate
.srcstep
== vl
-1
893 log(" pack/unpack/subvl", pack
, unpack
, subvl
,
897 srcstep
= self
.svstate
.srcstep
898 srcmask
= self
.srcmask
900 # pack advances subvl in *outer* loop
902 assert srcstep
<= vl
-1
903 end_src
= srcstep
== vl
-1
908 self
.svstate
.ssubstep
+= SelectableInt(1, 2)
912 srcstep
+= 1 # advance srcstep
913 if not self
.srcstep_skip
:
915 if ((1 << srcstep
) & srcmask
) != 0:
918 log(" sskip", bin(srcmask
), bin(1 << srcstep
))
920 # advance subvl in *inner* loop
923 assert srcstep
<= vl
-1
924 end_src
= srcstep
== vl
-1
925 if end_src
: # end-point
931 if not self
.srcstep_skip
:
933 if ((1 << srcstep
) & srcmask
) != 0:
936 log(" sskip", bin(srcmask
), bin(1 << srcstep
))
937 self
.svstate
.ssubstep
= SelectableInt(0, 2) # reset
940 self
.svstate
.ssubstep
+= SelectableInt(1, 2)
942 self
.svstate
.srcstep
= SelectableInt(srcstep
, 7)
943 log(" advance src", self
.svstate
.srcstep
, self
.svstate
.ssubstep
,
946 def dst_iterate(self
):
947 """dest step iterator
951 pack
= self
.svstate
.pack
952 unpack
= self
.svstate
.unpack
953 dsubstep
= self
.svstate
.dsubstep
954 end_dsub
= dsubstep
== subvl
955 dststep
= self
.svstate
.dststep
956 end_dst
= dststep
== vl
-1
957 dstmask
= self
.dstmask
958 log(" pack/unpack/subvl", pack
, unpack
, subvl
,
963 # unpack advances subvl in *outer* loop
965 assert dststep
<= vl
-1
966 end_dst
= dststep
== vl
-1
971 self
.svstate
.dsubstep
+= SelectableInt(1, 2)
975 dststep
+= 1 # advance dststep
976 if not self
.dststep_skip
:
978 if ((1 << dststep
) & dstmask
) != 0:
981 log(" dskip", bin(dstmask
), bin(1 << dststep
))
983 # advance subvl in *inner* loop
986 assert dststep
<= vl
-1
987 end_dst
= dststep
== vl
-1
988 if end_dst
: # end-point
994 if not self
.dststep_skip
:
996 if ((1 << dststep
) & dstmask
) != 0:
999 log(" dskip", bin(dstmask
), bin(1 << dststep
))
1000 self
.svstate
.dsubstep
= SelectableInt(0, 2) # reset
1003 self
.svstate
.dsubstep
+= SelectableInt(1, 2)
1005 self
.svstate
.dststep
= SelectableInt(dststep
, 7)
1006 log(" advance dst", self
.svstate
.dststep
, self
.svstate
.dsubstep
,
1009 def at_loopend(self
):
1010 """tells if this is the last possible element. uses the cached values
1011 for src/dst-step and sub-steps
1014 vl
= self
.svstate
.vl
1015 srcstep
, dststep
= self
.new_srcstep
, self
.new_dststep
1016 ssubstep
, dsubstep
= self
.new_ssubstep
, self
.new_dsubstep
1017 end_ssub
= ssubstep
== subvl
1018 end_dsub
= dsubstep
== subvl
1019 if srcstep
== vl
-1 and end_ssub
:
1021 if dststep
== vl
-1 and end_dsub
:
1025 def advance_svstate_steps(self
):
1026 """ advance sub/steps. note that Pack/Unpack *INVERTS* the order.
1027 TODO when Pack/Unpack is set, substep becomes the *outer* loop
1029 self
.subvl
= yield self
.dec2
.rm_dec
.rm_in
.subvl
1030 if self
.loopend
: # huhn??
1035 def read_src_mask(self
):
1036 """read/update pred_sz and src mask
1038 # get SVSTATE VL (oh and print out some debug stuff)
1039 vl
= self
.svstate
.vl
1040 srcstep
= self
.svstate
.srcstep
1041 ssubstep
= self
.svstate
.ssubstep
1043 # get predicate mask (all 64 bits)
1044 srcmask
= 0xffff_ffff_ffff_ffff
1046 pmode
= yield self
.dec2
.rm_dec
.predmode
1047 sv_ptype
= yield self
.dec2
.dec
.op
.SV_Ptype
1048 srcpred
= yield self
.dec2
.rm_dec
.srcpred
1049 dstpred
= yield self
.dec2
.rm_dec
.dstpred
1050 pred_sz
= yield self
.dec2
.rm_dec
.pred_sz
1051 if pmode
== SVP64PredMode
.INT
.value
:
1052 srcmask
= dstmask
= get_predint(self
.gpr
, dstpred
)
1053 if sv_ptype
== SVPType
.P2
.value
:
1054 srcmask
= get_predint(self
.gpr
, srcpred
)
1055 elif pmode
== SVP64PredMode
.CR
.value
:
1056 srcmask
= dstmask
= get_predcr(self
.crl
, dstpred
, vl
)
1057 if sv_ptype
== SVPType
.P2
.value
:
1058 srcmask
= get_predcr(self
.crl
, srcpred
, vl
)
1059 # work out if the ssubsteps are completed
1060 ssubstart
= ssubstep
== 0
1061 log(" pmode", pmode
)
1062 log(" ptype", sv_ptype
)
1063 log(" srcpred", bin(srcpred
))
1064 log(" srcmask", bin(srcmask
))
1065 log(" pred_sz", bin(pred_sz
))
1066 log(" ssubstart", ssubstart
)
1068 # store all that above
1069 self
.srcstep_skip
= False
1070 self
.srcmask
= srcmask
1071 self
.pred_sz
= pred_sz
1072 self
.new_ssubstep
= ssubstep
1073 log(" new ssubstep", ssubstep
)
1074 # until the predicate mask has a "1" bit... or we run out of VL
1075 # let srcstep==VL be the indicator to move to next instruction
1077 self
.srcstep_skip
= True
1079 def read_dst_mask(self
):
1080 """same as read_src_mask - check and record everything needed
1082 # get SVSTATE VL (oh and print out some debug stuff)
1083 # yield Delay(1e-10) # make changes visible
1084 vl
= self
.svstate
.vl
1085 dststep
= self
.svstate
.dststep
1086 dsubstep
= self
.svstate
.dsubstep
1088 # get predicate mask (all 64 bits)
1089 dstmask
= 0xffff_ffff_ffff_ffff
1091 pmode
= yield self
.dec2
.rm_dec
.predmode
1092 reverse_gear
= yield self
.dec2
.rm_dec
.reverse_gear
1093 sv_ptype
= yield self
.dec2
.dec
.op
.SV_Ptype
1094 dstpred
= yield self
.dec2
.rm_dec
.dstpred
1095 pred_dz
= yield self
.dec2
.rm_dec
.pred_dz
1096 if pmode
== SVP64PredMode
.INT
.value
:
1097 dstmask
= get_predint(self
.gpr
, dstpred
)
1098 elif pmode
== SVP64PredMode
.CR
.value
:
1099 dstmask
= get_predcr(self
.crl
, dstpred
, vl
)
1100 # work out if the ssubsteps are completed
1101 dsubstart
= dsubstep
== 0
1102 log(" pmode", pmode
)
1103 log(" ptype", sv_ptype
)
1104 log(" dstpred", bin(dstpred
))
1105 log(" dstmask", bin(dstmask
))
1106 log(" pred_dz", bin(pred_dz
))
1107 log(" dsubstart", dsubstart
)
1109 self
.dststep_skip
= False
1110 self
.dstmask
= dstmask
1111 self
.pred_dz
= pred_dz
1112 self
.new_dsubstep
= dsubstep
1113 log(" new dsubstep", dsubstep
)
1115 self
.dststep_skip
= True
1117 def svstate_pre_inc(self
):
1118 """check if srcstep/dststep need to skip over masked-out predicate bits
1119 note that this is not supposed to do anything to substep,
1120 it is purely for skipping masked-out bits
1123 self
.subvl
= yield self
.dec2
.rm_dec
.rm_in
.subvl
1124 yield from self
.read_src_mask()
1125 yield from self
.read_dst_mask()
1132 srcstep
= self
.svstate
.srcstep
1133 srcmask
= self
.srcmask
1134 pred_src_zero
= self
.pred_sz
1135 vl
= self
.svstate
.vl
1136 # srcstep-skipping opportunity identified
1137 if self
.srcstep_skip
:
1138 # cannot do this with sv.bc - XXX TODO
1141 while (((1 << srcstep
) & srcmask
) == 0) and (srcstep
!= vl
):
1142 log(" sskip", bin(1 << srcstep
))
1145 # now work out if the relevant mask bits require zeroing
1147 pred_src_zero
= ((1 << srcstep
) & srcmask
) == 0
1149 # store new srcstep / dststep
1150 self
.new_srcstep
= srcstep
1151 self
.pred_src_zero
= pred_src_zero
1152 log(" new srcstep", srcstep
)
1155 # dststep-skipping opportunity identified
1156 dststep
= self
.svstate
.dststep
1157 dstmask
= self
.dstmask
1158 pred_dst_zero
= self
.pred_dz
1159 vl
= self
.svstate
.vl
1160 if self
.dststep_skip
:
1161 # cannot do this with sv.bc - XXX TODO
1164 while (((1 << dststep
) & dstmask
) == 0) and (dststep
!= vl
):
1165 log(" dskip", bin(1 << dststep
))
1168 # now work out if the relevant mask bits require zeroing
1170 pred_dst_zero
= ((1 << dststep
) & dstmask
) == 0
1172 # store new srcstep / dststep
1173 self
.new_dststep
= dststep
1174 self
.pred_dst_zero
= pred_dst_zero
1175 log(" new dststep", dststep
)
1178 class ExitSyscallCalled(Exception):
1182 class SyscallEmulator(openpower
.syscalls
.Dispatcher
):
1183 def __init__(self
, isacaller
):
1184 self
.__isacaller
= isacaller
1186 host
= os
.uname().machine
1187 bits
= (64 if (sys
.maxsize
> (2**32)) else 32)
1188 host
= openpower
.syscalls
.architecture(arch
=host
, bits
=bits
)
1190 return super().__init
__(guest
="ppc64", host
=host
)
1192 def __call__(self
, identifier
, *arguments
):
1193 (identifier
, *arguments
) = map(int, (identifier
, *arguments
))
1194 return super().__call
__(identifier
, *arguments
)
1196 def sys_exit_group(self
, status
, *rest
):
1197 self
.__isacaller
.halted
= True
1198 raise ExitSyscallCalled(status
)
1200 def sys_write(self
, fd
, buf
, count
, *rest
):
1202 buf
= self
.__isacaller
.mem
.get_ctypes(buf
, count
, is_write
=False)
1206 return os
.write(fd
, buf
)
1207 except OSError as e
:
1210 def sys_writev(self
, fd
, iov
, iovcnt
, *rest
):
1212 if iovcnt
< 0 or iovcnt
> IOV_MAX
:
1213 return -errno
.EINVAL
1214 struct_iovec
= struct
.Struct("<QQ")
1217 iov
= self
.__isacaller
.mem
.get_ctypes(
1218 iov
, struct_iovec
.size
* iovcnt
, is_write
=False)
1219 iov
= list(struct_iovec
.iter_unpack(iov
))
1222 for i
, iovec
in enumerate(iov
):
1223 iov_base
, iov_len
= iovec
1224 iov
[i
] = self
.__isacaller
.mem
.get_ctypes(
1225 iov_base
, iov_len
, is_write
=False)
1226 except (ValueError, MemException
):
1227 return -errno
.EFAULT
1229 return os
.writev(fd
, iov
)
1230 except OSError as e
:
1233 def sys_read(self
, fd
, buf
, count
, *rest
):
1235 buf
= self
.__isacaller
.mem
.get_ctypes(buf
, count
, is_write
=True)
1239 return os
.readv(fd
, [buf
])
1240 except OSError as e
:
1243 def sys_mmap(self
, addr
, length
, prot
, flags
, fd
, offset
, *rest
):
1244 return self
.__isacaller
.mem
.mmap_syscall(
1245 addr
, length
, prot
, flags
, fd
, offset
, is_mmap2
=False)
1247 def sys_mmap2(self
, addr
, length
, prot
, flags
, fd
, offset
, *rest
):
1248 return self
.__isacaller
.mem
.mmap_syscall(
1249 addr
, length
, prot
, flags
, fd
, offset
, is_mmap2
=True)
1251 def sys_brk(self
, addr
, *rest
):
1252 return self
.__isacaller
.mem
.brk_syscall(addr
)
1254 def sys_munmap(self
, addr
, length
, *rest
):
1255 return -errno
.ENOSYS
# TODO: implement
1257 def sys_mprotect(self
, addr
, length
, prot
, *rest
):
1258 return -errno
.ENOSYS
# TODO: implement
1260 def sys_pkey_mprotect(self
, addr
, length
, prot
, pkey
, *rest
):
1261 return -errno
.ENOSYS
# TODO: implement
1263 def sys_openat(self
, dirfd
, pathname
, flags
, mode
, *rest
):
1265 path
= self
.__isacaller
.mem
.read_cstr(pathname
)
1266 except (ValueError, MemException
):
1267 return -errno
.EFAULT
1269 if dirfd
== ppc_flags
.AT_FDCWD
:
1270 return os
.open(path
, flags
, mode
)
1272 return os
.open(path
, flags
, mode
, dir_fd
=dirfd
)
1273 except OSError as e
:
1279 nodename
= uname
.nodename
.encode()
1280 release
= b
'5.6.0-1-powerpc64le'
1281 version
= b
'#1 SMP Debian 5.6.7-1 (2020-04-29)'
1282 machine
= b
'ppc64le'
1284 return sysname
, nodename
, release
, version
, machine
, domainname
1286 def sys_uname(self
, buf
, *rest
):
1287 s
= struct
.Struct("<65s65s65s65s65s")
1289 buf
= self
.__isacaller
.mem
.get_ctypes(buf
, s
.size
, is_write
=True)
1290 except (ValueError, MemException
):
1291 return -errno
.EFAULT
1292 sysname
, nodename
, release
, version
, machine
, domainname
= \
1294 s
.pack_into(buf
, 0, sysname
, nodename
, release
, version
, machine
)
1297 def sys_newuname(self
, buf
, *rest
):
1298 name_len
= ppc_flags
.__NEW
_UTS
_LEN
+ 1
1299 s
= struct
.Struct("<%ds%ds%ds%ds%ds%ds" % ((name_len
,) * 6))
1301 buf
= self
.__isacaller
.mem
.get_ctypes(buf
, s
.size
, is_write
=True)
1302 except (ValueError, MemException
):
1303 return -errno
.EFAULT
1304 sysname
, nodename
, release
, version
, machine
, domainname
= \
1307 sysname
, nodename
, release
, version
, machine
, domainname
)
1310 def sys_readlink(self
, pathname
, buf
, bufsiz
, *rest
):
1311 dirfd
= ppc_flags
.AT_FDCWD
1312 return self
.sys_readlinkat(dirfd
, pathname
, buf
, bufsiz
)
1314 def sys_readlinkat(self
, dirfd
, pathname
, buf
, bufsiz
, *rest
):
1316 path
= self
.__isacaller
.mem
.read_cstr(pathname
)
1318 buf
= self
.__isacaller
.mem
.get_ctypes(
1319 buf
, bufsiz
, is_write
=True)
1322 except (ValueError, MemException
):
1323 return -errno
.EFAULT
1325 if dirfd
== ppc_flags
.AT_FDCWD
:
1326 result
= os
.readlink(path
)
1328 result
= os
.readlink(path
, dir_fd
=dirfd
)
1329 retval
= min(len(result
), len(buf
))
1330 buf
[:retval
] = result
[:retval
]
1332 except OSError as e
:
1336 class ISACaller(ISACallerHelper
, ISAFPHelpers
, StepLoop
):
1337 # decoder2 - an instance of power_decoder2
1338 # regfile - a list of initial values for the registers
1339 # initial_{etc} - initial values for SPRs, Condition Register, Mem, MSR
1340 # respect_pc - tracks the program counter. requires initial_insns
1341 def __init__(self
, decoder2
, regfile
, initial_sprs
=None, initial_cr
=0,
1342 initial_mem
=None, initial_msr
=0,
1355 use_syscall_emu
=False,
1356 emulating_mmap
=False,
1357 real_page_size
=None):
1359 self
.syscall
= SyscallEmulator(isacaller
=self
)
1360 if not use_mmap_mem
:
1361 log("forcing use_mmap_mem due to use_syscall_emu active")
1366 # we will eventually be able to load ELF files without use_syscall_emu
1367 # (e.g. the linux kernel), so do it in a separate if block
1368 if isinstance(initial_insns
, ELFFile
):
1369 if not use_mmap_mem
:
1370 log("forcing use_mmap_mem due to loading an ELF file")
1372 if not emulating_mmap
:
1373 log("forcing emulating_mmap due to loading an ELF file")
1374 emulating_mmap
= True
1376 # trace log file for model output. if None do nothing
1377 self
.insnlog
= insnlog
1378 self
.insnlog_is_file
= hasattr(insnlog
, "write")
1379 if not self
.insnlog_is_file
and self
.insnlog
:
1380 self
.insnlog
= open(self
.insnlog
, "w")
1382 self
.bigendian
= bigendian
1384 self
.is_svp64_mode
= False
1385 self
.respect_pc
= respect_pc
1386 if initial_sprs
is None:
1388 if initial_mem
is None:
1390 if fpregfile
is None:
1391 fpregfile
= [0] * 32
1392 if initial_insns
is None:
1394 assert self
.respect_pc
== False, "instructions required to honor pc"
1395 if initial_msr
is None:
1396 initial_msr
= DEFAULT_MSR
1398 log("ISACaller insns", respect_pc
, initial_insns
, disassembly
)
1399 log("ISACaller initial_msr", initial_msr
)
1401 # "fake program counter" mode (for unit testing)
1405 if isinstance(initial_mem
, tuple):
1406 self
.fake_pc
= initial_mem
[0]
1407 disasm_start
= self
.fake_pc
1409 disasm_start
= initial_pc
1411 # disassembly: we need this for now (not given from the decoder)
1412 self
.disassembly
= {}
1414 for i
, code
in enumerate(disassembly
):
1415 self
.disassembly
[i
*4 + disasm_start
] = code
1417 # set up registers, instruction memory, data memory, PC, SPRs, MSR, CR
1418 self
.svp64rm
= SVP64RM()
1419 if initial_svstate
is None:
1421 if isinstance(initial_svstate
, int):
1422 initial_svstate
= SVP64State(initial_svstate
)
1423 # SVSTATE, MSR and PC
1424 StepLoop
.__init
__(self
, initial_svstate
)
1425 self
.msr
= SelectableInt(initial_msr
, 64) # underlying reg
1427 # GPR FPR SPR registers
1428 initial_sprs
= deepcopy(initial_sprs
) # so as not to get modified
1429 self
.gpr
= GPR(decoder2
, self
, self
.svstate
, regfile
)
1430 self
.fpr
= GPR(decoder2
, self
, self
.svstate
, fpregfile
)
1431 # initialise SPRs before MMU
1432 self
.spr
= SPR(decoder2
, initial_sprs
, gpr
=self
.gpr
)
1434 # set up 4 dummy SVSHAPEs if they aren't already set up
1436 sname
= 'SVSHAPE%d' % i
1437 val
= self
.spr
.get(sname
, 0)
1438 # make sure it's an SVSHAPE -- conversion done by SPR.__setitem__
1439 self
.spr
[sname
] = val
1440 self
.last_op_svshape
= False
1444 self
.mem
= MemMMap(row_bytes
=8,
1445 initial_mem
=initial_mem
,
1447 emulating_mmap
=emulating_mmap
)
1448 self
.imem
= self
.mem
1449 lelf
= self
.mem
.initialize(row_bytes
=4, initial_mem
=initial_insns
)
1450 if isinstance(lelf
, LoadedELF
): # stuff parsed from ELF
1451 initial_pc
= lelf
.pc
1452 for k
, v
in lelf
.gprs
.items():
1453 self
.gpr
[k
] = SelectableInt(v
, 64)
1454 initial_fpscr
= lelf
.fpscr
1455 self
.mem
.log_fancy(kind
=LogType
.InstrInOuts
)
1457 self
.mem
= Mem(row_bytes
=8, initial_mem
=initial_mem
,
1459 self
.mem
.log_fancy(kind
=LogType
.InstrInOuts
)
1460 self
.imem
= Mem(row_bytes
=4, initial_mem
=initial_insns
)
1461 # MMU mode, redirect underlying Mem through RADIX
1463 self
.mem
= RADIX(self
.mem
, self
)
1465 self
.imem
= RADIX(self
.imem
, self
)
1467 # TODO, needed here:
1468 # FPR (same as GPR except for FP nums)
1469 # 4.2.2 p124 FPSCR (definitely "separate" - not in SPR)
1470 # note that mffs, mcrfs, mtfsf "manage" this FPSCR
1471 self
.fpscr
= FPSCRState(initial_fpscr
)
1473 # 2.3.1 CR (and sub-fields CR0..CR6 - CR0 SO comes from XER.SO)
1474 # note that mfocrf, mfcr, mtcr, mtocrf, mcrxrx "manage" CRs
1476 # 2.3.2 LR (actually SPR #8) -- Done
1477 # 2.3.3 CTR (actually SPR #9) -- Done
1478 # 2.3.4 TAR (actually SPR #815)
1479 # 3.2.2 p45 XER (actually SPR #1) -- Done
1480 # 3.2.3 p46 p232 VRSAVE (actually SPR #256)
1482 # create CR then allow portions of it to be "selectable" (below)
1483 self
.cr_fields
= CRFields(initial_cr
)
1484 self
.cr
= self
.cr_fields
.cr
1485 self
.cr_backup
= 0 # sigh, dreadful hack: for fail-first (VLi)
1487 # "undefined", just set to variable-bit-width int (use exts "max")
1488 # self.undefined = SelectableInt(0, EFFECTIVELY_UNLIMITED)
1491 self
.namespace
.update(self
.spr
)
1492 self
.namespace
.update({'GPR': self
.gpr
,
1496 'memassign': self
.memassign
,
1499 'SVSTATE': self
.svstate
,
1500 'SVSHAPE0': self
.spr
['SVSHAPE0'],
1501 'SVSHAPE1': self
.spr
['SVSHAPE1'],
1502 'SVSHAPE2': self
.spr
['SVSHAPE2'],
1503 'SVSHAPE3': self
.spr
['SVSHAPE3'],
1506 'FPSCR': self
.fpscr
,
1507 'undefined': undefined
,
1508 'mode_is_64bit': True,
1509 'SO': XER_bits
['SO'],
1510 'XLEN': 64, # elwidth overrides
1514 if real_page_size
is None:
1515 # PowerISA v3.1B Book III Section 6.7 page 1191 (1217)
1516 # defines real page size as 2 ** 12 bytes (4KiB)
1517 real_page_size
= 2 ** 12
1518 self
.real_page_size
= real_page_size
1519 self
.reserve_addr
= SelectableInt(0, self
.XLEN
)
1520 self
.reserve
= SelectableInt(0, 1)
1521 self
.reserve_length
= SelectableInt(0, 4)
1523 self
.namespace
.update({'RESERVE': self
.RESERVE
,
1524 'RESERVE_ADDR': self
.RESERVE_ADDR
,
1525 'RESERVE_LENGTH': self
.RESERVE_LENGTH
,
1526 'REAL_PAGE_SIZE': self
.REAL_PAGE_SIZE
,
1529 for name
in BFP_FLAG_NAMES
:
1530 setattr(self
, name
, 0)
1532 # update pc to requested start point
1533 self
.set_pc(initial_pc
)
1535 # field-selectable versions of Condition Register
1536 self
.crl
= self
.cr_fields
.crl
1538 self
.namespace
["CR%d" % i
] = self
.crl
[i
]
1540 self
.decoder
= decoder2
.dec
1541 self
.dec2
= decoder2
1543 super().__init
__(XLEN
=self
.namespace
["XLEN"], FPSCR
=self
.fpscr
)
1545 def trace(self
, out
):
1546 if self
.insnlog
is None:
1548 self
.insnlog
.write(out
)
1552 return self
.namespace
["XLEN"]
1559 def RESERVE_LENGTH(self
):
1560 return self
.reserve_length
1563 def RESERVE_ADDR(self
):
1564 return self
.reserve_addr
1567 def REAL_PAGE_SIZE(self
):
1568 return self
.real_page_size
1570 def real_addr(self
, EA
):
1571 """ get the "real address to which `EA` maps"
1573 Specified in PowerISA v3.1B Book II Section 1.7.2.1 page 1049 (1075)
1575 # FIXME: translate EA to a physical address
1582 def call_trap(self
, trap_addr
, trap_bit
):
1583 """calls TRAP and sets up NIA to the new execution location.
1584 next instruction will begin at trap_addr.
1586 self
.TRAP(trap_addr
, trap_bit
)
1587 self
.namespace
['NIA'] = self
.trap_nia
1588 self
.pc
.update(self
.namespace
, self
.is_svp64_mode
)
1590 def TRAP(self
, trap_addr
=0x700, trap_bit
=PIb
.TRAP
):
1591 """TRAP> saves PC, MSR (and TODO SVSTATE), and updates MSR
1593 TRAP function is callable from inside the pseudocode itself,
1594 hence the default arguments. when calling from inside ISACaller
1595 it is best to use call_trap()
1597 trap_addr: int | SelectableInt
1598 the address to go to (before any modifications from `KAIVB`)
1599 trap_bit: int | None
1600 the bit in `SRR1` to set, `None` means don't set any bits.
1602 if isinstance(trap_addr
, SelectableInt
):
1603 trap_addr
= trap_addr
.value
1604 # https://bugs.libre-soc.org/show_bug.cgi?id=859
1605 kaivb
= self
.spr
['KAIVB'].value
1606 msr
= self
.namespace
['MSR'].value
1607 log("TRAP:", hex(trap_addr
), hex(msr
), "kaivb", hex(kaivb
))
1608 # store CIA(+4?) in SRR0, set NIA to 0x700
1609 # store MSR in SRR1, set MSR to um errr something, have to check spec
1610 # store SVSTATE (if enabled) in SVSRR0
1611 self
.spr
['SRR0'].value
= self
.pc
.CIA
.value
1612 self
.spr
['SRR1'].value
= msr
1613 if self
.is_svp64_mode
:
1614 self
.spr
['SVSRR0'] = self
.namespace
['SVSTATE'].value
1615 self
.trap_nia
= SelectableInt(trap_addr |
(kaivb
& ~
0x1fff), 64)
1616 if trap_bit
is not None:
1617 self
.spr
['SRR1'][trap_bit
] = 1 # change *copy* of MSR in SRR1
1619 # set exception bits. TODO: this should, based on the address
1620 # in figure 66 p1065 V3.0B and the table figure 65 p1063 set these
1621 # bits appropriately. however it turns out that *for now* in all
1622 # cases (all trap_addrs) the exact same thing is needed.
1623 self
.msr
[MSRb
.IR
] = 0
1624 self
.msr
[MSRb
.DR
] = 0
1625 self
.msr
[MSRb
.FE0
] = 0
1626 self
.msr
[MSRb
.FE1
] = 0
1627 self
.msr
[MSRb
.EE
] = 0
1628 self
.msr
[MSRb
.RI
] = 0
1629 self
.msr
[MSRb
.SF
] = 1
1630 self
.msr
[MSRb
.TM
] = 0
1631 self
.msr
[MSRb
.VEC
] = 0
1632 self
.msr
[MSRb
.VSX
] = 0
1633 self
.msr
[MSRb
.PR
] = 0
1634 self
.msr
[MSRb
.FP
] = 0
1635 self
.msr
[MSRb
.PMM
] = 0
1636 self
.msr
[MSRb
.TEs
] = 0
1637 self
.msr
[MSRb
.TEe
] = 0
1638 self
.msr
[MSRb
.UND
] = 0
1639 self
.msr
[MSRb
.LE
] = 1
1641 def memassign(self
, ea
, sz
, val
):
1642 self
.mem
.memassign(ea
, sz
, val
)
1644 def prep_namespace(self
, insn_name
, formname
, op_fields
, xlen
):
1645 # TODO: get field names from form in decoder*1* (not decoder2)
1646 # decoder2 is hand-created, and decoder1.sigform is auto-generated
1648 # then "yield" fields only from op_fields rather than hard-coded
1650 fields
= self
.decoder
.sigforms
[formname
]
1651 log("prep_namespace", formname
, op_fields
, insn_name
)
1652 for name
in op_fields
:
1653 # CR immediates. deal with separately. needs modifying
1655 crlen5
= ['BC', 'BA', 'BB', 'BT', 'BI'] # 5-bit
1656 crlen3
= ['BF', 'BFA'] # 3-bit (BF: bit-field)
1657 if self
.is_svp64_mode
and name
in crlen5
:
1658 # 5-bit, must reconstruct the value
1660 regnum
, is_vec
= yield from get_cr_out(self
.dec2
, name
)
1662 regnum
, is_vec
= yield from get_cr_in(self
.dec2
, name
)
1663 sig
= getattr(fields
, name
)
1665 # low 2 LSBs (CR field selector) remain same, CR num extended
1666 assert regnum
<= 7, "sigh, TODO, 128 CR fields"
1667 val
= (val
& 0b11) |
(regnum
<< 2)
1668 elif self
.is_svp64_mode
and name
in crlen3
:
1670 regnum
, is_vec
= yield from get_cr_out(self
.dec2
, name
)
1672 regnum
, is_vec
= yield from get_cr_in(self
.dec2
, name
)
1673 log('hack %s' % name
, regnum
, is_vec
)
1676 sig
= getattr(fields
, name
)
1678 # these are all opcode fields involved in index-selection of CR,
1679 # and need to do "standard" arithmetic. CR[BA+32] for example
1680 # would, if using SelectableInt, only be 5-bit.
1681 if name
not in crlen3
and name
not in crlen5
:
1682 val
= SelectableInt(val
, sig
.width
)
1684 # finally put the field into the namespace
1685 self
.namespace
[name
] = val
1687 self
.namespace
['XER'] = self
.spr
['XER']
1688 self
.namespace
['CA'] = self
.spr
['XER'][XER_bits
['CA']].value
1689 self
.namespace
['CA32'] = self
.spr
['XER'][XER_bits
['CA32']].value
1690 self
.namespace
['OV'] = self
.spr
['XER'][XER_bits
['OV']].value
1691 self
.namespace
['OV32'] = self
.spr
['XER'][XER_bits
['OV32']].value
1692 self
.namespace
['XLEN'] = xlen
1693 self
.namespace
['RESERVE'] = self
.reserve
1694 self
.namespace
['RESERVE_ADDR'] = self
.reserve_addr
1695 self
.namespace
['RESERVE_LENGTH'] = self
.reserve_length
1697 # add some SVSTATE convenience variables
1698 vl
= self
.svstate
.vl
1699 srcstep
= self
.svstate
.srcstep
1700 self
.namespace
['VL'] = vl
1701 self
.namespace
['srcstep'] = srcstep
1703 # take a copy of the CR field value: if non-VLi fail-first fails
1704 # this is because the pseudocode writes *directly* to CR. sigh
1705 self
.cr_backup
= self
.cr
.value
1707 # sv.bc* need some extra fields
1708 if not self
.is_svp64_mode
or not insn_name
.startswith("sv.bc"):
1711 # blegh grab bits manually
1712 mode
= yield self
.dec2
.rm_dec
.rm_in
.mode
1713 # convert to SelectableInt before test
1714 mode
= SelectableInt(mode
, 5)
1715 bc_vlset
= mode
[SVP64MODEb
.BC_VLSET
] != 0
1716 bc_vli
= mode
[SVP64MODEb
.BC_VLI
] != 0
1717 bc_snz
= mode
[SVP64MODEb
.BC_SNZ
] != 0
1718 bc_vsb
= yield self
.dec2
.rm_dec
.bc_vsb
1719 bc_ctrtest
= yield self
.dec2
.rm_dec
.bc_ctrtest
1720 bc_lru
= yield self
.dec2
.rm_dec
.bc_lru
1721 bc_gate
= yield self
.dec2
.rm_dec
.bc_gate
1722 sz
= yield self
.dec2
.rm_dec
.pred_sz
1723 self
.namespace
['mode'] = SelectableInt(mode
, 5)
1724 self
.namespace
['ALL'] = SelectableInt(bc_gate
, 1)
1725 self
.namespace
['VSb'] = SelectableInt(bc_vsb
, 1)
1726 self
.namespace
['LRu'] = SelectableInt(bc_lru
, 1)
1727 self
.namespace
['CTRtest'] = SelectableInt(bc_ctrtest
, 1)
1728 self
.namespace
['VLSET'] = SelectableInt(bc_vlset
, 1)
1729 self
.namespace
['VLI'] = SelectableInt(bc_vli
, 1)
1730 self
.namespace
['sz'] = SelectableInt(sz
, 1)
1731 self
.namespace
['SNZ'] = SelectableInt(bc_snz
, 1)
1733 def get_kludged_op_add_ca_ov(self
, inputs
, inp_ca_ov
):
1734 """ this was not at all necessary to do. this function massively
1735 duplicates - in a laborious and complex fashion - the contents of
1736 the CSV files that were extracted two years ago from microwatt's
1737 source code. A-inversion is the "inv A" column, output inversion
1738 is the "inv out" column, carry-in equal to 0 or 1 or CA is the
1741 all of that information is available in
1742 self.instrs[ins_name].op_fields
1743 where info is usually assigned to self.instrs[ins_name]
1745 https://git.libre-soc.org/?p=openpower-isa.git;a=blob;f=openpower/isatables/minor_31.csv;hb=HEAD
1747 the immediate constants are *also* decoded correctly and placed
1748 usually by DecodeIn2Imm into operand2, as part of power_decoder2.py
1750 def ca(a
, b
, ca_in
, width
):
1751 mask
= (1 << width
) - 1
1752 y
= (a
& mask
) + (b
& mask
) + ca_in
1755 asmcode
= yield self
.dec2
.dec
.op
.asmcode
1756 insn
= insns
.get(asmcode
)
1757 SI
= yield self
.dec2
.dec
.SI
1760 inputs
= [i
.value
for i
in inputs
]
1763 if insn
in ("add", "addo", "addc", "addco"):
1767 elif insn
== "addic" or insn
== "addic.":
1771 elif insn
in ("subf", "subfo", "subfc", "subfco"):
1775 elif insn
== "subfic":
1779 elif insn
== "adde" or insn
== "addeo":
1783 elif insn
== "subfe" or insn
== "subfeo":
1787 elif insn
== "addme" or insn
== "addmeo":
1791 elif insn
== "addze" or insn
== "addzeo":
1795 elif insn
== "subfme" or insn
== "subfmeo":
1799 elif insn
== "subfze" or insn
== "subfzeo":
1803 elif insn
== "addex":
1804 # CA[32] aren't actually written, just generate so we have
1805 # something to return
1806 ca64
= ov64
= ca(inputs
[0], inputs
[1], OV
, 64)
1807 ca32
= ov32
= ca(inputs
[0], inputs
[1], OV
, 32)
1808 return ca64
, ca32
, ov64
, ov32
1809 elif insn
== "neg" or insn
== "nego":
1814 raise NotImplementedError(
1815 "op_add kludge unimplemented instruction: ", asmcode
, insn
)
1817 ca64
= ca(a
, b
, ca_in
, 64)
1818 ca32
= ca(a
, b
, ca_in
, 32)
1819 ov64
= ca64
!= ca(a
, b
, ca_in
, 63)
1820 ov32
= ca32
!= ca(a
, b
, ca_in
, 31)
1821 return ca64
, ca32
, ov64
, ov32
1823 def handle_carry_(self
, inputs
, output
, ca
, ca32
, inp_ca_ov
):
1824 if ca
is not None and ca32
is not None:
1826 op
= yield self
.dec2
.e
.do
.insn_type
1827 if op
== MicrOp
.OP_ADD
.value
and ca
is None and ca32
is None:
1828 retval
= yield from self
.get_kludged_op_add_ca_ov(
1830 ca
, ca32
, ov
, ov32
= retval
1831 asmcode
= yield self
.dec2
.dec
.op
.asmcode
1832 if insns
.get(asmcode
) == 'addex':
1833 # TODO: if 32-bit mode, set ov to ov32
1834 self
.spr
['XER'][XER_bits
['OV']] = ov
1835 self
.spr
['XER'][XER_bits
['OV32']] = ov32
1836 log(f
"write OV/OV32 OV={ov} OV32={ov32}",
1837 kind
=LogType
.InstrInOuts
)
1839 # TODO: if 32-bit mode, set ca to ca32
1840 self
.spr
['XER'][XER_bits
['CA']] = ca
1841 self
.spr
['XER'][XER_bits
['CA32']] = ca32
1842 log(f
"write CA/CA32 CA={ca} CA32={ca32}",
1843 kind
=LogType
.InstrInOuts
)
1845 inv_a
= yield self
.dec2
.e
.do
.invert_in
1847 inputs
[0] = ~inputs
[0]
1849 imm_ok
= yield self
.dec2
.e
.do
.imm_data
.ok
1851 imm
= yield self
.dec2
.e
.do
.imm_data
.data
1852 inputs
.append(SelectableInt(imm
, 64))
1855 log("gt input", x
, output
)
1856 gt
= (gtu(x
, output
))
1859 cy
= 1 if any(gts
) else 0
1861 if ca
is None: # already written
1862 self
.spr
['XER'][XER_bits
['CA']] = cy
1865 # ARGH... different for OP_ADD... *sigh*...
1866 op
= yield self
.dec2
.e
.do
.insn_type
1867 if op
== MicrOp
.OP_ADD
.value
:
1868 res32
= (output
.value
& (1 << 32)) != 0
1869 a32
= (inputs
[0].value
& (1 << 32)) != 0
1870 if len(inputs
) >= 2:
1871 b32
= (inputs
[1].value
& (1 << 32)) != 0
1874 cy32
= res32 ^ a32 ^ b32
1875 log("CA32 ADD", cy32
)
1879 log("input", x
, output
)
1880 log(" x[32:64]", x
, x
[32:64])
1881 log(" o[32:64]", output
, output
[32:64])
1882 gt
= (gtu(x
[32:64], output
[32:64])) == SelectableInt(1, 1)
1884 cy32
= 1 if any(gts
) else 0
1885 log("CA32", cy32
, gts
)
1886 if ca32
is None: # already written
1887 self
.spr
['XER'][XER_bits
['CA32']] = cy32
1889 def handle_overflow(self
, inputs
, output
, div_overflow
, inp_ca_ov
):
1890 op
= yield self
.dec2
.e
.do
.insn_type
1891 if op
== MicrOp
.OP_ADD
.value
:
1892 retval
= yield from self
.get_kludged_op_add_ca_ov(
1894 ca
, ca32
, ov
, ov32
= retval
1895 # TODO: if 32-bit mode, set ov to ov32
1896 self
.spr
['XER'][XER_bits
['OV']] = ov
1897 self
.spr
['XER'][XER_bits
['OV32']] = ov32
1898 self
.spr
['XER'][XER_bits
['SO']] |
= ov
1900 if hasattr(self
.dec2
.e
.do
, "invert_in"):
1901 inv_a
= yield self
.dec2
.e
.do
.invert_in
1903 inputs
[0] = ~inputs
[0]
1905 imm_ok
= yield self
.dec2
.e
.do
.imm_data
.ok
1907 imm
= yield self
.dec2
.e
.do
.imm_data
.data
1908 inputs
.append(SelectableInt(imm
, 64))
1909 log("handle_overflow", inputs
, output
, div_overflow
)
1910 if len(inputs
) < 2 and div_overflow
is None:
1913 # div overflow is different: it's returned by the pseudo-code
1914 # because it's more complex than can be done by analysing the output
1915 if div_overflow
is not None:
1916 ov
, ov32
= div_overflow
, div_overflow
1917 # arithmetic overflow can be done by analysing the input and output
1918 elif len(inputs
) >= 2:
1920 input_sgn
= [exts(x
.value
, x
.bits
) < 0 for x
in inputs
]
1921 output_sgn
= exts(output
.value
, output
.bits
) < 0
1922 ov
= 1 if input_sgn
[0] == input_sgn
[1] and \
1923 output_sgn
!= input_sgn
[0] else 0
1926 input32_sgn
= [exts(x
.value
, 32) < 0 for x
in inputs
]
1927 output32_sgn
= exts(output
.value
, 32) < 0
1928 ov32
= 1 if input32_sgn
[0] == input32_sgn
[1] and \
1929 output32_sgn
!= input32_sgn
[0] else 0
1931 # now update XER OV/OV32/SO
1932 so
= self
.spr
['XER'][XER_bits
['SO']]
1933 new_so
= so | ov
# sticky overflow ORs in old with new
1934 self
.spr
['XER'][XER_bits
['OV']] = ov
1935 self
.spr
['XER'][XER_bits
['OV32']] = ov32
1936 self
.spr
['XER'][XER_bits
['SO']] = new_so
1937 log(" set overflow", ov
, ov32
, so
, new_so
)
1939 def handle_comparison(self
, out
, cr_idx
=0, overflow
=None, no_so
=False):
1940 assert isinstance(out
, SelectableInt
), \
1941 "out zero not a SelectableInt %s" % repr(outputs
)
1942 log("handle_comparison", out
.bits
, hex(out
.value
))
1943 # TODO - XXX *processor* in 32-bit mode
1944 # https://bugs.libre-soc.org/show_bug.cgi?id=424
1946 # o32 = exts(out.value, 32)
1947 # print ("handle_comparison exts 32 bit", hex(o32))
1948 out
= exts(out
.value
, out
.bits
)
1949 log("handle_comparison exts", hex(out
))
1950 # create the three main CR flags, EQ GT LT
1951 zero
= SelectableInt(out
== 0, 1)
1952 positive
= SelectableInt(out
> 0, 1)
1953 negative
= SelectableInt(out
< 0, 1)
1954 # get (or not) XER.SO. for setvl this is important *not* to read SO
1956 SO
= SelectableInt(1, 0)
1958 SO
= self
.spr
['XER'][XER_bits
['SO']]
1959 log("handle_comparison SO", SO
.value
,
1960 "overflow", overflow
,
1962 "+ve", positive
.value
,
1963 "-ve", negative
.value
)
1964 # alternative overflow checking (setvl mainly at the moment)
1965 if overflow
is not None and overflow
== 1:
1966 SO
= SelectableInt(1, 1)
1967 # create the four CR field values and set the required CR field
1968 cr_field
= selectconcat(negative
, positive
, zero
, SO
)
1969 log("handle_comparison cr_field", self
.cr
, cr_idx
, cr_field
)
1970 self
.crl
[cr_idx
].eq(cr_field
)
1973 def set_pc(self
, pc_val
):
1974 self
.namespace
['NIA'] = SelectableInt(pc_val
, 64)
1975 self
.pc
.update(self
.namespace
, self
.is_svp64_mode
)
1977 def get_next_insn(self
):
1978 """check instruction
1981 pc
= self
.pc
.CIA
.value
1984 ins
= self
.imem
.ld(pc
, 4, False, True, instr_fetch
=True)
1986 raise KeyError("no instruction at 0x%x" % pc
)
1989 def setup_one(self
):
1990 """set up one instruction
1992 pc
, insn
= self
.get_next_insn()
1993 yield from self
.setup_next_insn(pc
, insn
)
1995 # cache since it's really slow to construct
1996 __PREFIX_CACHE
= SVP64Instruction
.Prefix(SelectableInt(value
=0, bits
=32))
1998 def __decode_prefix(self
, opcode
):
1999 pfx
= self
.__PREFIX
_CACHE
2000 pfx
.storage
.eq(opcode
)
2003 def setup_next_insn(self
, pc
, ins
):
2004 """set up next instruction
2007 log("setup: 0x%x 0x%x %s" % (pc
, ins
& 0xffffffff, bin(ins
)))
2008 log("CIA NIA", self
.respect_pc
, self
.pc
.CIA
.value
, self
.pc
.NIA
.value
)
2010 yield self
.dec2
.sv_rm
.eq(0)
2011 yield self
.dec2
.dec
.raw_opcode_in
.eq(ins
& 0xffffffff)
2012 yield self
.dec2
.dec
.bigendian
.eq(self
.bigendian
)
2013 yield self
.dec2
.state
.msr
.eq(self
.msr
.value
)
2014 yield self
.dec2
.state
.pc
.eq(pc
)
2015 if self
.svstate
is not None:
2016 yield self
.dec2
.state
.svstate
.eq(self
.svstate
.value
)
2018 # SVP64. first, check if the opcode is EXT001, and SVP64 id bits set
2020 opcode
= yield self
.dec2
.dec
.opcode_in
2021 opcode
= SelectableInt(value
=opcode
, bits
=32)
2022 pfx
= self
.__decode
_prefix
(opcode
)
2023 log("prefix test: opcode:", pfx
.PO
, bin(pfx
.PO
), pfx
.id)
2024 self
.is_svp64_mode
= bool((pfx
.PO
== 0b000001) and (pfx
.id == 0b11))
2025 self
.pc
.update_nia(self
.is_svp64_mode
)
2027 yield self
.dec2
.is_svp64_mode
.eq(self
.is_svp64_mode
)
2028 self
.namespace
['NIA'] = self
.pc
.NIA
2029 self
.namespace
['SVSTATE'] = self
.svstate
2030 if not self
.is_svp64_mode
:
2033 # in SVP64 mode. decode/print out svp64 prefix, get v3.0B instruction
2034 log("svp64.rm", bin(pfx
.rm
))
2035 log(" svstate.vl", self
.svstate
.vl
)
2036 log(" svstate.mvl", self
.svstate
.maxvl
)
2037 ins
= self
.imem
.ld(pc
+4, 4, False, True, instr_fetch
=True)
2038 log(" svsetup: 0x%x 0x%x %s" % (pc
+4, ins
& 0xffffffff, bin(ins
)))
2039 yield self
.dec2
.dec
.raw_opcode_in
.eq(ins
& 0xffffffff) # v3.0B suffix
2040 yield self
.dec2
.sv_rm
.eq(int(pfx
.rm
)) # svp64 prefix
2043 def execute_one(self
):
2044 """execute one instruction
2046 # get the disassembly code for this instruction
2047 if not self
.disassembly
:
2048 code
= yield from self
.get_assembly_name()
2051 if self
.is_svp64_mode
:
2052 offs
, dbg
= 4, "svp64 "
2053 code
= self
.disassembly
[self
._pc
+offs
]
2054 log(" %s sim-execute" % dbg
, hex(self
._pc
), code
)
2055 opname
= code
.split(' ')[0]
2057 asmop
= yield from self
.call(opname
) # execute the instruction
2058 except MemException
as e
: # check for memory errors
2059 if e
.args
[0] == 'unaligned': # alignment error
2060 # run a Trap but set DAR first
2061 print("memory unaligned exception, DAR", e
.dar
, repr(e
))
2062 self
.spr
['DAR'] = SelectableInt(e
.dar
, 64)
2063 self
.call_trap(0x600, PIb
.PRIV
) # 0x600, privileged
2065 elif e
.args
[0] == 'invalid': # invalid
2066 # run a Trap but set DAR first
2067 log("RADIX MMU memory invalid error, mode %s" % e
.mode
)
2068 if e
.mode
== 'EXECUTE':
2069 # XXX TODO: must set a few bits in SRR1,
2070 # see microwatt loadstore1.vhdl
2071 # if m_in.segerr = '0' then
2072 # v.srr1(47 - 33) := m_in.invalid;
2073 # v.srr1(47 - 35) := m_in.perm_error; -- noexec fault
2074 # v.srr1(47 - 44) := m_in.badtree;
2075 # v.srr1(47 - 45) := m_in.rc_error;
2076 # v.intr_vec := 16#400#;
2078 # v.intr_vec := 16#480#;
2079 self
.call_trap(0x400, PIb
.PRIV
) # 0x400, privileged
2081 self
.call_trap(0x300, PIb
.PRIV
) # 0x300, privileged
2083 # not supported yet:
2084 raise e
# ... re-raise
2086 # append to the trace log file
2087 self
.trace(" # %s %s\n" % (asmop
, code
))
2089 log("gprs after insn %s - code" % asmop
, code
)
2092 for i
in range(len(self
.crl
)):
2093 crs
.append(bin(self
.crl
[i
].asint()))
2094 log("crs", " ".join(crs
))
2095 log("vl,maxvl", self
.svstate
.vl
, self
.svstate
.maxvl
)
2097 # don't use this except in special circumstances
2098 if not self
.respect_pc
:
2101 log("execute one, CIA NIA", hex(self
.pc
.CIA
.value
),
2102 hex(self
.pc
.NIA
.value
))
2104 def get_assembly_name(self
):
2105 # TODO, asmregs is from the spec, e.g. add RT,RA,RB
2106 # see http://bugs.libre-riscv.org/show_bug.cgi?id=282
2107 dec_insn
= yield self
.dec2
.e
.do
.insn
2108 insn_1_11
= yield self
.dec2
.e
.do
.insn
[1:11]
2109 asmcode
= yield self
.dec2
.dec
.op
.asmcode
2110 int_op
= yield self
.dec2
.dec
.op
.internal_op
2111 log("get assembly name asmcode", asmcode
, int_op
,
2112 hex(dec_insn
), bin(insn_1_11
))
2113 asmop
= insns
.get(asmcode
, None)
2115 # sigh reconstruct the assembly instruction name
2116 if hasattr(self
.dec2
.e
.do
, "oe"):
2117 ov_en
= yield self
.dec2
.e
.do
.oe
.oe
2118 ov_ok
= yield self
.dec2
.e
.do
.oe
.ok
2122 if hasattr(self
.dec2
.e
.do
, "rc"):
2123 rc_en
= yield self
.dec2
.e
.do
.rc
.rc
2124 rc_ok
= yield self
.dec2
.e
.do
.rc
.ok
2128 # annoying: ignore rc_ok if RC1 is set (for creating *assembly name*)
2129 RC1
= yield self
.dec2
.rm_dec
.RC1
2133 # grrrr have to special-case MUL op (see DecodeOE)
2134 log("ov %d en %d rc %d en %d op %d" %
2135 (ov_ok
, ov_en
, rc_ok
, rc_en
, int_op
))
2136 if int_op
in [MicrOp
.OP_MUL_H64
.value
, MicrOp
.OP_MUL_H32
.value
]:
2141 if not asmop
.endswith("."): # don't add "." to "andis."
2144 if hasattr(self
.dec2
.e
.do
, "lk"):
2145 lk
= yield self
.dec2
.e
.do
.lk
2148 log("int_op", int_op
)
2149 if int_op
in [MicrOp
.OP_B
.value
, MicrOp
.OP_BC
.value
]:
2150 AA
= yield self
.dec2
.dec
.fields
.FormI
.AA
[0:-1]
2154 spr_msb
= yield from self
.get_spr_msb()
2155 if int_op
== MicrOp
.OP_MFCR
.value
:
2160 # XXX TODO: for whatever weird reason this doesn't work
2161 # https://bugs.libre-soc.org/show_bug.cgi?id=390
2162 if int_op
== MicrOp
.OP_MTCRF
.value
:
2169 def reset_remaps(self
):
2170 self
.remap_loopends
= [0] * 4
2171 self
.remap_idxs
= [0, 1, 2, 3]
2173 def get_remap_indices(self
):
2174 """WARNING, this function stores remap_idxs and remap_loopends
2175 in the class for later use. this to avoid problems with yield
2177 # go through all iterators in lock-step, advance to next remap_idx
2178 srcstep
, dststep
, ssubstep
, dsubstep
= self
.get_src_dststeps()
2179 # get four SVSHAPEs. here we are hard-coding
2181 SVSHAPE0
= self
.spr
['SVSHAPE0']
2182 SVSHAPE1
= self
.spr
['SVSHAPE1']
2183 SVSHAPE2
= self
.spr
['SVSHAPE2']
2184 SVSHAPE3
= self
.spr
['SVSHAPE3']
2185 # set up the iterators
2186 remaps
= [(SVSHAPE0
, SVSHAPE0
.get_iterator()),
2187 (SVSHAPE1
, SVSHAPE1
.get_iterator()),
2188 (SVSHAPE2
, SVSHAPE2
.get_iterator()),
2189 (SVSHAPE3
, SVSHAPE3
.get_iterator()),
2193 for i
, (shape
, remap
) in enumerate(remaps
):
2194 # zero is "disabled"
2195 if shape
.value
== 0x0:
2196 self
.remap_idxs
[i
] = 0
2197 # pick src or dststep depending on reg num (0-2=in, 3-4=out)
2198 step
= dststep
if (i
in [3, 4]) else srcstep
2199 # this is terrible. O(N^2) looking for the match. but hey.
2200 for idx
, (remap_idx
, loopends
) in enumerate(remap
):
2203 self
.remap_idxs
[i
] = remap_idx
2204 self
.remap_loopends
[i
] = loopends
2205 dbg
.append((i
, step
, remap_idx
, loopends
))
2206 for (i
, step
, remap_idx
, loopends
) in dbg
:
2207 log("SVSHAPE %d idx, end" % i
, step
, remap_idx
, bin(loopends
))
2210 def get_spr_msb(self
):
2211 dec_insn
= yield self
.dec2
.e
.do
.insn
2212 return dec_insn
& (1 << 20) != 0 # sigh - XFF.spr[-1]?
2214 def call(self
, name
, syscall_emu_active
=False):
2215 """call(opcode) - the primary execution point for instructions
2217 self
.last_st_addr
= None # reset the last known store address
2218 self
.last_ld_addr
= None # etc.
2220 ins_name
= name
.strip() # remove spaces if not already done so
2222 log("halted - not executing", ins_name
)
2225 # TODO, asmregs is from the spec, e.g. add RT,RA,RB
2226 # see http://bugs.libre-riscv.org/show_bug.cgi?id=282
2227 asmop
= yield from self
.get_assembly_name()
2228 log("call", ins_name
, asmop
, kind
=LogType
.InstrInOuts
)
2230 # sv.setvl is *not* a loop-function. sigh
2231 log("is_svp64_mode", self
.is_svp64_mode
, asmop
)
2234 int_op
= yield self
.dec2
.dec
.op
.internal_op
2235 spr_msb
= yield from self
.get_spr_msb()
2237 instr_is_privileged
= False
2238 if int_op
in [MicrOp
.OP_ATTN
.value
,
2239 MicrOp
.OP_MFMSR
.value
,
2240 MicrOp
.OP_MTMSR
.value
,
2241 MicrOp
.OP_MTMSRD
.value
,
2243 MicrOp
.OP_RFID
.value
]:
2244 instr_is_privileged
= True
2245 if int_op
in [MicrOp
.OP_MFSPR
.value
,
2246 MicrOp
.OP_MTSPR
.value
] and spr_msb
:
2247 instr_is_privileged
= True
2249 # check MSR priv bit and whether op is privileged: if so, throw trap
2250 PR
= self
.msr
[MSRb
.PR
]
2251 log("is priv", instr_is_privileged
, hex(self
.msr
.value
), PR
)
2252 if instr_is_privileged
and PR
== 1:
2253 self
.call_trap(0x700, PIb
.PRIV
)
2256 # check halted condition
2257 if ins_name
== 'attn':
2261 # User mode system call emulation consists of several steps:
2262 # 1. Detect whether instruction is sc or scv.
2263 # 2. Call the HDL implementation which invokes trap.
2264 # 3. Reroute the guest system call to host system call.
2265 # 4. Force return from the interrupt as if we had guest OS.
2266 # FIXME: enable PPC_FEATURE2_SCV in mem.py DEFAULT_AT_HWCAP2 when
2267 # scv emulation works.
2268 if ((asmop
in ("sc", "scv")) and
2269 (self
.syscall
is not None) and
2270 not syscall_emu_active
):
2271 # Memoize PC and trigger an interrupt
2273 pc
= self
.pc
.CIA
.value
2276 yield from self
.call(asmop
, syscall_emu_active
=True)
2278 # Reroute the syscall to host OS
2279 identifier
= self
.gpr(0)
2280 arguments
= map(self
.gpr
, range(3, 9))
2281 result
= self
.syscall(identifier
, *arguments
)
2282 self
.gpr
.write(3, result
, False, self
.namespace
["XLEN"])
2284 # Return from interrupt
2285 yield from self
.call("rfid", syscall_emu_active
=True)
2287 elif ((name
in ("rfid", "hrfid")) and syscall_emu_active
):
2290 # check illegal instruction
2292 if ins_name
not in ['mtcrf', 'mtocrf']:
2293 illegal
= ins_name
!= asmop
2295 # list of instructions not being supported by binutils (.long)
2296 dotstrp
= asmop
[:-1] if asmop
[-1] == '.' else asmop
2297 if dotstrp
in [*FPTRANS_INSNS
,
2299 'ffmadds', 'fdmadds', 'ffadds',
2301 "brh", "brw", "brd",
2302 'setvl', 'svindex', 'svremap', 'svstep',
2303 'svshape', 'svshape2',
2304 'ternlogi', 'bmask', 'cprop', 'gbbd',
2305 'absdu', 'absds', 'absdacs', 'absdacu', 'avgadd',
2306 'fmvis', 'fishmv', 'pcdec', "maddedu", "divmod2du",
2307 "dsld", "dsrd", "maddedus",
2308 "sadd", "saddw", "sadduw",
2313 "maddsubrs", "maddrs", "msubrs",
2314 "cfuged", "cntlzdm", "cnttzdm", "pdepd", "pextd",
2315 "setbc", "setbcr", "setnbc", "setnbcr",
2320 # match against instructions treated as nop, see nop below
2321 if asmop
.startswith("dcbt"):
2325 # branch-conditional redirects to sv.bc
2326 if asmop
.startswith('bc') and self
.is_svp64_mode
:
2327 ins_name
= 'sv.%s' % ins_name
2329 # ld-immediate-with-pi mode redirects to ld-with-postinc
2330 ldst_imm_postinc
= False
2331 if 'u' in ins_name
and self
.is_svp64_mode
:
2332 ldst_pi
= yield self
.dec2
.rm_dec
.ldst_postinc
2334 ins_name
= ins_name
.replace("u", "up")
2335 ldst_imm_postinc
= True
2336 log(" enable ld/st postinc", ins_name
)
2338 log(" post-processed name", dotstrp
, ins_name
, asmop
)
2340 # illegal instructions call TRAP at 0x700
2342 print("illegal", ins_name
, asmop
)
2343 self
.call_trap(0x700, PIb
.ILLEG
)
2344 print("name %s != %s - calling ILLEGAL trap, PC: %x" %
2345 (ins_name
, asmop
, self
.pc
.CIA
.value
))
2348 # this is for setvl "Vertical" mode: if set true,
2349 # srcstep/dststep is explicitly advanced. mode says which SVSTATE to
2350 # test for Rc=1 end condition. 3 bits of all 3 loops are put into CR0
2351 self
.allow_next_step_inc
= False
2352 self
.svstate_next_mode
= 0
2354 # nop has to be supported, we could let the actual op calculate
2355 # but PowerDecoder has a pattern for nop
2356 if ins_name
== 'nop':
2357 self
.update_pc_next()
2360 # get elwidths, defaults to 64
2364 if self
.is_svp64_mode
:
2365 ew_src
= yield self
.dec2
.rm_dec
.ew_src
2366 ew_dst
= yield self
.dec2
.rm_dec
.ew_dst
2367 ew_src
= 8 << (3-int(ew_src
)) # convert to bitlength
2368 ew_dst
= 8 << (3-int(ew_dst
)) # convert to bitlength
2369 xlen
= max(ew_src
, ew_dst
)
2370 log("elwidth", ew_src
, ew_dst
)
2371 log("XLEN:", self
.is_svp64_mode
, xlen
)
2373 # look up instruction in ISA.instrs, prepare namespace
2374 if ins_name
== 'pcdec': # grrrr yes there are others ("stbcx." etc.)
2375 info
= self
.instrs
[ins_name
+"."]
2376 elif asmop
[-1] == '.' and asmop
in self
.instrs
:
2377 info
= self
.instrs
[asmop
]
2379 info
= self
.instrs
[ins_name
]
2380 yield from self
.prep_namespace(ins_name
, info
.form
, info
.op_fields
,
2383 # dict retains order
2384 inputs
= dict.fromkeys(create_full_args(
2385 read_regs
=info
.read_regs
, special_regs
=info
.special_regs
,
2386 uninit_regs
=info
.uninit_regs
, write_regs
=info
.write_regs
))
2388 # preserve order of register names
2389 write_without_special_regs
= OrderedSet(info
.write_regs
)
2390 write_without_special_regs
-= OrderedSet(info
.special_regs
)
2391 input_names
= create_args([
2392 *info
.read_regs
, *info
.uninit_regs
, *write_without_special_regs
])
2393 log("input names", input_names
)
2395 # get SVP64 entry for the current instruction
2396 sv_rm
= self
.svp64rm
.instrs
.get(ins_name
)
2397 if sv_rm
is not None:
2398 dest_cr
, src_cr
, src_byname
, dest_byname
= decode_extra(sv_rm
)
2400 dest_cr
, src_cr
, src_byname
, dest_byname
= False, False, {}, {}
2401 log("sv rm", sv_rm
, dest_cr
, src_cr
, src_byname
, dest_byname
)
2403 # see if srcstep/dststep need skipping over masked-out predicate bits
2404 # svstep also needs advancement because it calls SVSTATE_NEXT.
2405 # bit the remaps get computed just after pre_inc moves them on
2406 # with remap_set_steps substituting for PowerDecider2 not doing it,
2407 # and SVSTATE_NEXT not being able to.use yield, the preinc on
2408 # svstep is necessary for now.
2410 if (self
.is_svp64_mode
or ins_name
in ['svstep']):
2411 yield from self
.svstate_pre_inc()
2412 if self
.is_svp64_mode
:
2413 pre
= yield from self
.update_new_svstate_steps()
2415 self
.svp64_reset_loop()
2417 self
.update_pc_next()
2419 srcstep
, dststep
, ssubstep
, dsubstep
= self
.get_src_dststeps()
2420 pred_dst_zero
= self
.pred_dst_zero
2421 pred_src_zero
= self
.pred_src_zero
2422 vl
= self
.svstate
.vl
2423 subvl
= yield self
.dec2
.rm_dec
.rm_in
.subvl
2425 # VL=0 in SVP64 mode means "do nothing: skip instruction"
2426 if self
.is_svp64_mode
and vl
== 0:
2427 self
.pc
.update(self
.namespace
, self
.is_svp64_mode
)
2428 log("SVP64: VL=0, end of call", self
.namespace
['CIA'],
2429 self
.namespace
['NIA'], kind
=LogType
.InstrInOuts
)
2432 # for when SVREMAP is active, using pre-arranged schedule.
2433 # note: modifying PowerDecoder2 needs to "settle"
2434 remap_en
= self
.svstate
.SVme
2435 persist
= self
.svstate
.RMpst
2436 active
= (persist
or self
.last_op_svshape
) and remap_en
!= 0
2437 if self
.is_svp64_mode
:
2438 yield self
.dec2
.remap_active
.eq(remap_en
if active
else 0)
2440 if persist
or self
.last_op_svshape
:
2441 remaps
= self
.get_remap_indices()
2442 if self
.is_svp64_mode
and (persist
or self
.last_op_svshape
):
2443 yield from self
.remap_set_steps(remaps
)
2444 # after that, settle down (combinatorial) to let Vector reg numbers
2445 # work themselves out
2447 if self
.is_svp64_mode
:
2448 remap_active
= yield self
.dec2
.remap_active
2450 remap_active
= False
2451 log("remap active", bin(remap_active
), self
.is_svp64_mode
)
2453 # LDST does *not* allow elwidth overrides on RA (Effective Address).
2454 # this has to be detected. XXX TODO: RB for ldst-idx *may* need
2455 # conversion (to 64-bit) also.
2456 # see write reg this *HAS* to also override XLEN to 64 on LDST/Update
2457 sv_mode
= yield self
.dec2
.rm_dec
.sv_mode
2458 is_ldst
= (sv_mode
in [SVMode
.LDST_IDX
.value
, SVMode
.LDST_IMM
.value
] \
2459 and self
.is_svp64_mode
)
2460 log("is_ldst", sv_mode
, is_ldst
)
2462 # main input registers (RT, RA ...)
2463 for name
in input_names
:
2464 if name
== "overflow":
2465 inputs
[name
] = SelectableInt(0, 1)
2466 elif name
.startswith("RESERVE"):
2467 inputs
[name
] = getattr(self
, name
)
2468 elif name
== "FPSCR":
2469 inputs
[name
] = self
.FPSCR
2470 elif name
in ("CA", "CA32", "OV", "OV32"):
2471 inputs
[name
] = self
.spr
['XER'][XER_bits
[name
]]
2473 inputs
[name
] = self
.crl
[0]
2474 elif name
in spr_byname
:
2475 inputs
[name
] = self
.spr
[name
]
2476 elif is_ldst
and name
== 'RA':
2477 regval
= (yield from self
.get_input(name
, ew_src
, 64))
2478 log("EA (RA) regval name", name
, regval
)
2479 inputs
[name
] = regval
2481 regval
= (yield from self
.get_input(name
, ew_src
, xlen
))
2482 log("regval name", name
, regval
)
2483 inputs
[name
] = regval
2485 # arrrrgh, awful hack, to get _RT into namespace
2486 if ins_name
in ['setvl', 'svstep']:
2488 RT
= yield self
.dec2
.dec
.RT
2489 self
.namespace
[regname
] = SelectableInt(RT
, 5)
2491 self
.namespace
["RT"] = SelectableInt(0, 5)
2492 regnum
, is_vec
= yield from get_idx_out(self
.dec2
, "RT")
2493 log('hack input reg %s %s' % (name
, str(regnum
)), is_vec
)
2495 # in SVP64 mode for LD/ST work out immediate
2496 # XXX TODO: replace_ds for DS-Form rather than D-Form.
2497 # use info.form to detect
2498 if self
.is_svp64_mode
and not ldst_imm_postinc
:
2499 yield from self
.check_replace_d(info
, remap_active
)
2501 # "special" registers
2502 for special
in info
.special_regs
:
2503 if special
in special_sprs
:
2504 inputs
[special
] = self
.spr
[special
]
2506 inputs
[special
] = self
.namespace
[special
]
2508 # clear trap (trap) NIA
2509 self
.trap_nia
= None
2511 # check if this was an sv.bc* and create an indicator that
2512 # this is the last check to be made as a loop. combined with
2513 # the ALL/ANY mode we can early-exit. note that BI (to test)
2514 # is an input so there is no termination if BI is scalar
2515 # (because early-termination is for *output* scalars)
2516 if self
.is_svp64_mode
and ins_name
.startswith("sv.bc"):
2517 end_loop
= srcstep
== vl
-1 or dststep
== vl
-1
2518 self
.namespace
['end_loop'] = SelectableInt(end_loop
, 1)
2520 inp_ca_ov
= (self
.spr
['XER'][XER_bits
['CA']].value
,
2521 self
.spr
['XER'][XER_bits
['OV']].value
)
2523 for k
, v
in inputs
.items():
2525 v
= SelectableInt(0, self
.XLEN
)
2526 # prevent pseudo-code from modifying input registers
2527 v
= copy_assign_rhs(v
)
2528 if isinstance(v
, SelectableInt
):
2532 # execute actual instruction here (finally)
2533 log("inputs", inputs
)
2534 inputs
= list(inputs
.values())
2535 results
= info
.func(self
, *inputs
)
2536 output_names
= create_args(info
.write_regs
)
2538 # record .ok before anything after the pseudo-code can modify it
2540 for out
, n
in zip(results
or [], output_names
):
2543 if isinstance(out
, SelectableInt
):
2545 log("results", outs
)
2546 log("results ok", outs_ok
)
2548 # "inject" decorator takes namespace from function locals: we need to
2549 # overwrite NIA being overwritten (sigh)
2550 if self
.trap_nia
is not None:
2551 self
.namespace
['NIA'] = self
.trap_nia
2553 log("after func", self
.namespace
['CIA'], self
.namespace
['NIA'])
2555 # check if op was a LD/ST so that debugging can check the
2557 if int_op
in [MicrOp
.OP_STORE
.value
,
2559 self
.last_st_addr
= self
.mem
.last_st_addr
2560 if int_op
in [MicrOp
.OP_LOAD
.value
,
2562 self
.last_ld_addr
= self
.mem
.last_ld_addr
2563 log("op", int_op
, MicrOp
.OP_STORE
.value
, MicrOp
.OP_LOAD
.value
,
2564 self
.last_st_addr
, self
.last_ld_addr
)
2566 # detect if CA/CA32 already in outputs (sra*, basically)
2568 ca32
= outs
.get("CA32")
2570 log("carry already done?", ca
, ca32
, output_names
)
2571 # soc test_pipe_caller tests don't have output_carry
2572 has_output_carry
= hasattr(self
.dec2
.e
.do
, "output_carry")
2573 carry_en
= has_output_carry
and (yield self
.dec2
.e
.do
.output_carry
)
2575 yield from self
.handle_carry_(
2576 inputs
, results
[0], ca
, ca32
, inp_ca_ov
=inp_ca_ov
)
2578 # get output named "overflow" and "CR0"
2579 overflow
= outs
.get('overflow')
2580 cr0
= outs
.get('CR0')
2581 cr1
= outs
.get('CR1')
2583 # soc test_pipe_caller tests don't have oe
2584 has_oe
= hasattr(self
.dec2
.e
.do
, "oe")
2585 # yeah just no. not in parallel processing
2586 if has_oe
and not self
.is_svp64_mode
:
2587 # detect if overflow was in return result
2588 ov_en
= yield self
.dec2
.e
.do
.oe
.oe
2589 ov_ok
= yield self
.dec2
.e
.do
.oe
.ok
2590 log("internal overflow", ins_name
, overflow
, "en?", ov_en
, ov_ok
)
2592 yield from self
.handle_overflow(
2593 inputs
, results
[0], overflow
, inp_ca_ov
=inp_ca_ov
)
2595 # only do SVP64 dest predicated Rc=1 if dest-pred is not enabled
2597 if not self
.is_svp64_mode
or not pred_dst_zero
:
2598 if hasattr(self
.dec2
.e
.do
, "rc"):
2599 rc_en
= yield self
.dec2
.e
.do
.rc
.rc
2600 # don't do Rc=1 for svstep it is handled explicitly.
2601 # XXX TODO: now that CR0 is supported, sort out svstep's pseudocode
2602 # to write directly to CR0 instead of in ISACaller. hooyahh.
2603 if rc_en
and ins_name
not in ['svstep']:
2604 if outs_ok
.get('FPSCR', False):
2605 FPSCR
= outs
['FPSCR']
2608 yield from self
.do_rc_ov(
2609 ins_name
, results
[0], overflow
, cr0
, cr1
, FPSCR
)
2612 ffirst_hit
= False, False
2613 if self
.is_svp64_mode
:
2614 sv_mode
= yield self
.dec2
.rm_dec
.sv_mode
2615 is_cr
= sv_mode
== SVMode
.CROP
.value
2616 chk
= rc_en
or is_cr
2617 if outs_ok
.get('CR', False):
2618 # early write so check_ffirst can see value
2619 self
.namespace
['CR'].eq(outs
['CR'])
2620 ffirst_hit
= (yield from self
.check_ffirst(info
, chk
, srcstep
))
2622 # any modified return results?
2623 yield from self
.do_outregs(
2624 info
, outs
, carry_en
, ffirst_hit
, ew_dst
, outs_ok
)
2626 # check if a FP Exception occurred. TODO for DD-FFirst, check VLi
2627 # and raise the exception *after* if VLi=1 but if VLi=0 then
2628 # truncate and make the exception "disappear".
2629 if self
.FPSCR
.FEX
and (self
.msr
[MSRb
.FE0
] or self
.msr
[MSRb
.FE1
]):
2630 self
.call_trap(0x700, PIb
.FP
)
2633 yield from self
.do_nia(asmop
, ins_name
, rc_en
, ffirst_hit
)
2636 def check_ffirst(self
, info
, rc_en
, srcstep
):
2637 """fail-first mode: checks a bit of Rc Vector, truncates VL
2639 rm_mode
= yield self
.dec2
.rm_dec
.mode
2640 ff_inv
= yield self
.dec2
.rm_dec
.inv
2641 cr_bit
= yield self
.dec2
.rm_dec
.cr_sel
2642 RC1
= yield self
.dec2
.rm_dec
.RC1
2643 vli_
= yield self
.dec2
.rm_dec
.vli
# VL inclusive if truncated
2644 log(" ff rm_mode", rc_en
, rm_mode
, SVP64RMMode
.FFIRST
.value
)
2648 log(" cr_bit", cr_bit
)
2649 log(" rc_en", rc_en
)
2650 ffirst
= yield from is_ffirst_mode(self
.dec2
)
2651 if not rc_en
or not ffirst
:
2653 # get the CR vevtor, do BO-test
2655 log("asmregs", info
.asmregs
[0], info
.write_regs
)
2656 if 'CR' in info
.write_regs
and 'BF' in info
.asmregs
[0]:
2658 regnum
, is_vec
= yield from get_cr_out(self
.dec2
, crf
)
2659 crtest
= self
.crl
[regnum
]
2660 ffirst_hit
= crtest
[cr_bit
] != ff_inv
2661 log("cr test", crf
, regnum
, int(crtest
), crtest
, cr_bit
, ff_inv
)
2662 log("cr test?", ffirst_hit
)
2665 # Fail-first activated, truncate VL
2666 vli
= SelectableInt(int(vli_
), 7)
2667 self
.svstate
.vl
= srcstep
+ vli
2668 yield self
.dec2
.state
.svstate
.eq(self
.svstate
.value
)
2669 yield Settle() # let decoder update
2672 def do_rc_ov(self
, ins_name
, result
, overflow
, cr0
, cr1
, FPSCR
):
2673 cr_out
= yield self
.dec2
.op
.cr_out
2674 if cr_out
== CROutSel
.CR1
.value
:
2678 regnum
, is_vec
= yield from get_cr_out(self
.dec2
, rc_reg
)
2679 # hang on... for `setvl` actually you want to test SVSTATE.VL
2680 is_setvl
= ins_name
in ('svstep', 'setvl')
2682 result
= SelectableInt(result
.vl
, 64)
2684 # overflow = None # do not override overflow except in setvl
2688 cr1
= int(FPSCR
.FX
) << 3
2689 cr1 |
= int(FPSCR
.FEX
) << 2
2690 cr1 |
= int(FPSCR
.VX
) << 1
2691 cr1 |
= int(FPSCR
.OX
)
2692 log("default fp cr1", cr1
)
2694 log("explicit cr1", cr1
)
2695 self
.crl
[regnum
].eq(cr1
)
2697 # if there was not an explicit CR0 in the pseudocode,
2699 c
= self
.handle_comparison(result
, regnum
, overflow
, no_so
=is_setvl
)
2700 log("implicit cr0 %d" % regnum
, c
)
2702 # otherwise we just blat CR0 into the required regnum
2703 log("explicit cr0 %d" % regnum
, cr0
)
2704 self
.crl
[regnum
].eq(cr0
)
2706 def do_outregs(self
, info
, outs
, ca_en
, ffirst_hit
, ew_dst
, outs_ok
):
2707 ffirst_hit
, vli
= ffirst_hit
2708 # write out any regs for this instruction, but only if fail-first is ok
2709 # XXX TODO: allow CR-vector to be written out even if ffirst fails
2710 if not ffirst_hit
or vli
:
2711 for name
, output
in outs
.items():
2712 if not outs_ok
[name
]:
2713 log("skipping writing output with .ok=False", name
, output
)
2715 yield from self
.check_write(info
, name
, output
, ca_en
, ew_dst
)
2716 # restore the CR value on non-VLI failfirst (from sv.cmp and others
2717 # which write directly to CR in the pseudocode (gah, what a mess)
2718 # if ffirst_hit and not vli:
2719 # self.cr.value = self.cr_backup
2721 def do_nia(self
, asmop
, ins_name
, rc_en
, ffirst_hit
):
2722 ffirst_hit
, vli
= ffirst_hit
2724 self
.svp64_reset_loop()
2727 # check advancement of src/dst/sub-steps and if PC needs updating
2728 nia_update
= (yield from self
.check_step_increment(
2729 rc_en
, asmop
, ins_name
))
2731 self
.update_pc_next()
2733 def check_replace_d(self
, info
, remap_active
):
2734 replace_d
= False # update / replace constant in pseudocode
2735 ldstmode
= yield self
.dec2
.rm_dec
.ldstmode
2736 vl
= self
.svstate
.vl
2737 subvl
= yield self
.dec2
.rm_dec
.rm_in
.subvl
2738 srcstep
, dststep
= self
.new_srcstep
, self
.new_dststep
2739 ssubstep
, dsubstep
= self
.new_ssubstep
, self
.new_dsubstep
2740 if info
.form
== 'DS':
2741 # DS-Form, multiply by 4 then knock 2 bits off after
2742 imm
= yield self
.dec2
.dec
.fields
.FormDS
.DS
[0:14] * 4
2744 imm
= yield self
.dec2
.dec
.fields
.FormD
.D
[0:16]
2745 imm
= exts(imm
, 16) # sign-extend to integer
2746 # get the right step. LD is from srcstep, ST is dststep
2747 op
= yield self
.dec2
.e
.do
.insn_type
2749 if op
== MicrOp
.OP_LOAD
.value
:
2751 offsmul
= yield self
.dec2
.in1_step
2752 log("D-field REMAP src", imm
, offsmul
, ldstmode
)
2754 offsmul
= (srcstep
* (subvl
+1)) + ssubstep
2755 log("D-field src", imm
, offsmul
, ldstmode
)
2756 elif op
== MicrOp
.OP_STORE
.value
:
2757 # XXX NOTE! no bit-reversed STORE! this should not ever be used
2758 offsmul
= (dststep
* (subvl
+1)) + dsubstep
2759 log("D-field dst", imm
, offsmul
, ldstmode
)
2760 # Unit-Strided LD/ST adds offset*width to immediate
2761 if ldstmode
== SVP64LDSTmode
.UNITSTRIDE
.value
:
2762 ldst_len
= yield self
.dec2
.e
.do
.data_len
2763 imm
= SelectableInt(imm
+ offsmul
* ldst_len
, 32)
2765 # Element-strided multiplies the immediate by element step
2766 elif ldstmode
== SVP64LDSTmode
.ELSTRIDE
.value
:
2767 imm
= SelectableInt(imm
* offsmul
, 32)
2770 ldst_ra_vec
= yield self
.dec2
.rm_dec
.ldst_ra_vec
2771 ldst_imz_in
= yield self
.dec2
.rm_dec
.ldst_imz_in
2772 log("LDSTmode", SVP64LDSTmode(ldstmode
),
2773 offsmul
, imm
, ldst_ra_vec
, ldst_imz_in
)
2774 # new replacement D... errr.. DS
2776 if info
.form
== 'DS':
2777 # TODO: assert 2 LSBs are zero?
2778 log("DS-Form, TODO, assert 2 LSBs zero?", bin(imm
.value
))
2779 imm
.value
= imm
.value
>> 2
2780 self
.namespace
['DS'] = imm
2782 self
.namespace
['D'] = imm
2784 def get_input(self
, name
, ew_src
, xlen
):
2785 # using PowerDecoder2, first, find the decoder index.
2786 # (mapping name RA RB RC RS to in1, in2, in3)
2787 regnum
, is_vec
= yield from get_idx_in(self
.dec2
, name
, True)
2789 # doing this is not part of svp64, it's because output
2790 # registers, to be modified, need to be in the namespace.
2791 regnum
, is_vec
= yield from get_idx_out(self
.dec2
, name
, True)
2793 regnum
, is_vec
= yield from get_idx_out2(self
.dec2
, name
, True)
2795 if isinstance(regnum
, tuple):
2796 (regnum
, base
, offs
) = regnum
2798 base
, offs
= regnum
, 0 # temporary HACK
2800 # in case getting the register number is needed, _RA, _RB
2801 # (HACK: only in straight non-svp64-mode for now, or elwidth == 64)
2802 regname
= "_" + name
2803 if not self
.is_svp64_mode
or ew_src
== 64:
2804 self
.namespace
[regname
] = regnum
2806 # FIXME: we're trying to access a sub-register, plain register
2807 # numbers don't work for that. for now, just pass something that
2808 # can be compared to 0 and probably will cause an error if misused.
2809 # see https://bugs.libre-soc.org/show_bug.cgi?id=1221
2810 self
.namespace
[regname
] = regnum
* 10000
2812 if not self
.is_svp64_mode
or not self
.pred_src_zero
:
2813 log('reading reg %s %s' % (name
, str(regnum
)), is_vec
)
2815 fval
= self
.fpr(base
, is_vec
, offs
, ew_src
)
2816 reg_val
= SelectableInt(fval
)
2817 assert ew_src
== self
.XLEN
, "TODO fix elwidth conversion"
2818 self
.trace("r:FPR:%d:%d:%d " % (base
, offs
, ew_src
))
2819 log("read fp reg %d/%d: 0x%x" % (base
, offs
, reg_val
.value
),
2820 kind
=LogType
.InstrInOuts
)
2821 elif name
is not None:
2822 gval
= self
.gpr(base
, is_vec
, offs
, ew_src
)
2823 reg_val
= SelectableInt(gval
.value
, bits
=xlen
)
2824 self
.trace("r:GPR:%d:%d:%d " % (base
, offs
, ew_src
))
2825 log("read int reg %d/%d: 0x%x" % (base
, offs
, reg_val
.value
),
2826 kind
=LogType
.InstrInOuts
)
2828 log('zero input reg %s %s' % (name
, str(regnum
)), is_vec
)
2829 reg_val
= SelectableInt(0, ew_src
)
2832 def remap_set_steps(self
, remaps
):
2833 """remap_set_steps sets up the in1/2/3 and out1/2 steps.
2834 they work in concert with PowerDecoder2 at the moment,
2835 there is no HDL implementation of REMAP. therefore this
2836 function, because ISACaller still uses PowerDecoder2,
2837 will *explicitly* write the dec2.XX_step values. this has
2840 # just some convenient debug info
2842 sname
= 'SVSHAPE%d' % i
2843 shape
= self
.spr
[sname
]
2844 log(sname
, bin(shape
.value
))
2845 log(" lims", shape
.lims
)
2846 log(" mode", shape
.mode
)
2847 log(" skip", shape
.skip
)
2849 # set up the list of steps to remap
2850 mi0
= self
.svstate
.mi0
2851 mi1
= self
.svstate
.mi1
2852 mi2
= self
.svstate
.mi2
2853 mo0
= self
.svstate
.mo0
2854 mo1
= self
.svstate
.mo1
2855 steps
= [[self
.dec2
.in1_step
, mi0
], # RA
2856 [self
.dec2
.in2_step
, mi1
], # RB
2857 [self
.dec2
.in3_step
, mi2
], # RC
2858 [self
.dec2
.o_step
, mo0
], # RT
2859 [self
.dec2
.o2_step
, mo1
], # EA
2862 rnames
= ['RA', 'RB', 'RC', 'RT', 'RS']
2863 for i
, reg
in enumerate(rnames
):
2864 idx
= yield from get_idx_map(self
.dec2
, reg
)
2866 idx
= yield from get_idx_map(self
.dec2
, "F"+reg
)
2868 steps
[i
][0] = self
.dec2
.in1_step
2870 steps
[i
][0] = self
.dec2
.in2_step
2872 steps
[i
][0] = self
.dec2
.in3_step
2873 log("remap step", i
, reg
, idx
, steps
[i
][1])
2874 remap_idxs
= self
.remap_idxs
2876 # now cross-index the required SHAPE for each of 3-in 2-out regs
2877 rnames
= ['RA', 'RB', 'RC', 'RT', 'EA']
2878 for i
, (dstep
, shape_idx
) in enumerate(steps
):
2879 (shape
, remap
) = remaps
[shape_idx
]
2880 remap_idx
= remap_idxs
[shape_idx
]
2881 # zero is "disabled"
2882 if shape
.value
== 0x0:
2884 # now set the actual requested step to the current index
2885 if dstep
is not None:
2886 yield dstep
.eq(remap_idx
)
2888 # debug printout info
2889 rremaps
.append((shape
.mode
, hex(shape
.value
), dstep
,
2890 i
, rnames
[i
], shape_idx
, remap_idx
))
2892 log("shape remap", x
)
2894 def check_write(self
, info
, name
, output
, carry_en
, ew_dst
):
2895 if name
== 'overflow': # ignore, done already (above)
2897 if name
== 'CR0': # ignore, done already (above)
2899 if isinstance(output
, int):
2900 output
= SelectableInt(output
, EFFECTIVELY_UNLIMITED
)
2902 if name
.startswith("RESERVE"):
2903 log("write %s 0x%x" % (name
, output
.value
))
2904 getattr(self
, name
).eq(output
)
2906 if name
in ['FPSCR', ]:
2907 log("write FPSCR 0x%x" % (output
.value
))
2908 self
.FPSCR
.eq(output
)
2911 if name
in ['CA', 'CA32']:
2913 log("writing %s to XER" % name
, output
)
2914 log("write XER %s 0x%x" % (name
, output
.value
))
2915 self
.spr
['XER'][XER_bits
[name
]] = output
.value
2917 log("NOT writing %s to XER" % name
, output
)
2919 # write special SPRs
2920 if name
in info
.special_regs
:
2921 log('writing special %s' % name
, output
, special_sprs
)
2922 log("write reg %s 0x%x" % (name
, output
.value
),
2923 kind
=LogType
.InstrInOuts
)
2924 if name
in special_sprs
:
2925 self
.spr
[name
] = output
2927 self
.namespace
[name
].eq(output
)
2929 log('msr written', hex(self
.msr
.value
))
2931 # find out1/out2 PR/FPR
2932 regnum
, is_vec
= yield from get_idx_out(self
.dec2
, name
, True)
2934 regnum
, is_vec
= yield from get_idx_out2(self
.dec2
, name
, True)
2936 # temporary hack for not having 2nd output
2937 regnum
= yield getattr(self
.decoder
, name
)
2939 # convenient debug prefix
2944 # check zeroing due to predicate bit being zero
2945 if self
.is_svp64_mode
and self
.pred_dst_zero
:
2946 log('zeroing reg %s %s' % (str(regnum
), str(output
)), is_vec
)
2947 output
= SelectableInt(0, EFFECTIVELY_UNLIMITED
)
2948 log("write reg %s%s 0x%x ew %d" % (reg_prefix
, str(regnum
),
2949 output
.value
, ew_dst
),
2950 kind
=LogType
.InstrInOuts
)
2951 # zero-extend tov64 bit begore storing (should use EXT oh well)
2952 if output
.bits
> 64:
2953 output
= SelectableInt(output
.value
, 64)
2954 rnum
, base
, offset
= regnum
2956 self
.fpr
.write(regnum
, output
, is_vec
, ew_dst
)
2957 self
.trace("w:FPR:%d:%d:%d " % (rnum
, offset
, ew_dst
))
2960 # LDST/Update does *not* allow elwidths on RA (Effective Address).
2961 # this has to be detected, and overridden. see get_input (related)
2962 sv_mode
= yield self
.dec2
.rm_dec
.sv_mode
2963 is_ldst
= (sv_mode
in [SVMode
.LDST_IDX
.value
, SVMode
.LDST_IMM
.value
] \
2964 and self
.is_svp64_mode
)
2965 if is_ldst
and name
in ['EA', 'RA']:
2966 op
= self
.dec2
.dec
.op
2967 if hasattr(op
, "upd"):
2968 # update mode LD/ST uses read-reg A also as an output
2970 log("write is_ldst is_update", sv_mode
, is_ldst
, upd
)
2971 if upd
== LDSTMode
.update
.value
:
2972 ew_dst
= 64 # override for RA (EA) to 64-bit
2974 self
.gpr
.write(regnum
, output
, is_vec
, ew_dst
)
2975 self
.trace("w:GPR:%d:%d:%d " % (rnum
, offset
, ew_dst
))
2977 def check_step_increment(self
, rc_en
, asmop
, ins_name
):
2978 # check if it is the SVSTATE.src/dest step that needs incrementing
2979 # this is our Sub-Program-Counter loop from 0 to VL-1
2980 if not self
.allow_next_step_inc
:
2981 if self
.is_svp64_mode
:
2982 return (yield from self
.svstate_post_inc(ins_name
))
2984 # XXX only in non-SVP64 mode!
2985 # record state of whether the current operation was an svshape,
2987 # to be able to know if it should apply in the next instruction.
2988 # also (if going to use this instruction) should disable ability
2989 # to interrupt in between. sigh.
2990 self
.last_op_svshape
= asmop
in ['svremap', 'svindex',
2997 log("SVSTATE_NEXT: inc requested, mode",
2998 self
.svstate_next_mode
, self
.allow_next_step_inc
)
2999 yield from self
.svstate_pre_inc()
3000 pre
= yield from self
.update_new_svstate_steps()
3002 # reset at end of loop including exit Vertical Mode
3003 log("SVSTATE_NEXT: end of loop, reset")
3004 self
.svp64_reset_loop()
3005 self
.svstate
.vfirst
= 0
3009 self
.handle_comparison(SelectableInt(0, 64)) # CR0
3011 if self
.allow_next_step_inc
== 2:
3012 log("SVSTATE_NEXT: read")
3013 nia_update
= (yield from self
.svstate_post_inc(ins_name
))
3015 log("SVSTATE_NEXT: post-inc")
3016 # use actual (cached) src/dst-step here to check end
3017 remaps
= self
.get_remap_indices()
3018 remap_idxs
= self
.remap_idxs
3019 vl
= self
.svstate
.vl
3020 subvl
= yield self
.dec2
.rm_dec
.rm_in
.subvl
3021 if self
.allow_next_step_inc
!= 2:
3022 yield from self
.advance_svstate_steps()
3023 #self.namespace['SVSTATE'] = self.svstate.spr
3024 # set CR0 (if Rc=1) based on end
3025 endtest
= 1 if self
.at_loopend() else 0
3027 #results = [SelectableInt(endtest, 64)]
3028 # self.handle_comparison(results) # CR0
3030 # see if svstep was requested, if so, which SVSTATE
3032 if self
.svstate_next_mode
> 0:
3033 shape_idx
= self
.svstate_next_mode
.value
-1
3034 endings
= self
.remap_loopends
[shape_idx
]
3035 cr_field
= SelectableInt((~endings
) << 1 | endtest
, 4)
3036 log("svstep Rc=1, CR0", cr_field
, endtest
)
3037 self
.crl
[0].eq(cr_field
) # CR0
3039 # reset at end of loop including exit Vertical Mode
3040 log("SVSTATE_NEXT: after increments, reset")
3041 self
.svp64_reset_loop()
3042 self
.svstate
.vfirst
= 0
3045 def SVSTATE_NEXT(self
, mode
, submode
, RA
=None):
3046 """explicitly moves srcstep/dststep on to next element, for
3047 "Vertical-First" mode. this function is called from
3048 setvl pseudo-code, as a pseudo-op "svstep"
3050 WARNING: this function uses information that was created EARLIER
3051 due to it being in the middle of a yield, but this function is
3052 *NOT* called from yield (it's called from compiled pseudocode).
3054 self
.allow_next_step_inc
= submode
.value
+ 1
3055 log("SVSTATE_NEXT mode", mode
, submode
, self
.allow_next_step_inc
)
3056 self
.svstate_next_mode
= mode
3057 if self
.svstate_next_mode
> 0 and self
.svstate_next_mode
< 5:
3058 shape_idx
= self
.svstate_next_mode
.value
-1
3059 return SelectableInt(self
.remap_idxs
[shape_idx
], 7)
3060 if self
.svstate_next_mode
== 5:
3061 self
.svstate_next_mode
= 0
3062 return SelectableInt(self
.svstate
.srcstep
, 7)
3063 if self
.svstate_next_mode
== 6:
3064 self
.svstate_next_mode
= 0
3065 return SelectableInt(self
.svstate
.dststep
, 7)
3066 if self
.svstate_next_mode
== 7:
3067 self
.svstate_next_mode
= 0
3068 return SelectableInt(self
.svstate
.ssubstep
, 7)
3069 if self
.svstate_next_mode
== 8:
3070 self
.svstate_next_mode
= 0
3071 return SelectableInt(self
.svstate
.dsubstep
, 7)
3072 return SelectableInt(0, 7)
3074 def get_src_dststeps(self
):
3075 """gets srcstep, dststep, and ssubstep, dsubstep
3077 return (self
.new_srcstep
, self
.new_dststep
,
3078 self
.new_ssubstep
, self
.new_dsubstep
)
3080 def update_svstate_namespace(self
, overwrite_svstate
=True):
3081 if overwrite_svstate
:
3082 # note, do not get the bit-reversed srcstep here!
3083 srcstep
, dststep
= self
.new_srcstep
, self
.new_dststep
3084 ssubstep
, dsubstep
= self
.new_ssubstep
, self
.new_dsubstep
3086 # update SVSTATE with new srcstep
3087 self
.svstate
.srcstep
= srcstep
3088 self
.svstate
.dststep
= dststep
3089 self
.svstate
.ssubstep
= ssubstep
3090 self
.svstate
.dsubstep
= dsubstep
3091 self
.namespace
['SVSTATE'] = self
.svstate
3092 yield self
.dec2
.state
.svstate
.eq(self
.svstate
.value
)
3093 yield Settle() # let decoder update
3095 def update_new_svstate_steps(self
, overwrite_svstate
=True):
3096 yield from self
.update_svstate_namespace(overwrite_svstate
)
3097 srcstep
= self
.svstate
.srcstep
3098 dststep
= self
.svstate
.dststep
3099 ssubstep
= self
.svstate
.ssubstep
3100 dsubstep
= self
.svstate
.dsubstep
3101 pack
= self
.svstate
.pack
3102 unpack
= self
.svstate
.unpack
3103 vl
= self
.svstate
.vl
3104 sv_mode
= yield self
.dec2
.rm_dec
.sv_mode
3105 subvl
= yield self
.dec2
.rm_dec
.rm_in
.subvl
3106 rm_mode
= yield self
.dec2
.rm_dec
.mode
3107 ff_inv
= yield self
.dec2
.rm_dec
.inv
3108 cr_bit
= yield self
.dec2
.rm_dec
.cr_sel
3109 log(" srcstep", srcstep
)
3110 log(" dststep", dststep
)
3112 log(" unpack", unpack
)
3113 log(" ssubstep", ssubstep
)
3114 log(" dsubstep", dsubstep
)
3116 log(" subvl", subvl
)
3117 log(" rm_mode", rm_mode
)
3118 log(" sv_mode", sv_mode
)
3120 log(" cr_bit", cr_bit
)
3122 # check if end reached (we let srcstep overrun, above)
3123 # nothing needs doing (TODO zeroing): just do next instruction
3126 return ((ssubstep
== subvl
and srcstep
== vl
) or
3127 (dsubstep
== subvl
and dststep
== vl
))
3129 def svstate_post_inc(self
, insn_name
, vf
=0):
3130 # check if SV "Vertical First" mode is enabled
3131 vfirst
= self
.svstate
.vfirst
3132 log(" SV Vertical First", vf
, vfirst
)
3133 if not vf
and vfirst
== 1:
3134 # SV Branch-Conditional required to be as-if-vector
3135 # because there *is* no destination register
3136 # (SV normally only terminates on 1st scalar reg written
3137 # except in [slightly-misnamed] mapreduce mode)
3138 ffirst
= yield from is_ffirst_mode(self
.dec2
)
3139 if insn_name
.startswith("sv.bc") or ffirst
:
3140 self
.update_pc_next()
3145 # check if it is the SVSTATE.src/dest step that needs incrementing
3146 # this is our Sub-Program-Counter loop from 0 to VL-1
3147 # XXX twin predication TODO
3148 vl
= self
.svstate
.vl
3149 subvl
= yield self
.dec2
.rm_dec
.rm_in
.subvl
3150 mvl
= self
.svstate
.maxvl
3151 srcstep
= self
.svstate
.srcstep
3152 dststep
= self
.svstate
.dststep
3153 ssubstep
= self
.svstate
.ssubstep
3154 dsubstep
= self
.svstate
.dsubstep
3155 pack
= self
.svstate
.pack
3156 unpack
= self
.svstate
.unpack
3157 rm_mode
= yield self
.dec2
.rm_dec
.mode
3158 reverse_gear
= yield self
.dec2
.rm_dec
.reverse_gear
3159 sv_ptype
= yield self
.dec2
.dec
.op
.SV_Ptype
3160 out_vec
= not (yield self
.dec2
.no_out_vec
)
3161 in_vec
= not (yield self
.dec2
.no_in_vec
)
3162 rm_mode
= yield self
.dec2
.rm_dec
.mode
3163 log(" svstate.vl", vl
)
3164 log(" svstate.mvl", mvl
)
3165 log(" rm.subvl", subvl
)
3166 log(" svstate.srcstep", srcstep
)
3167 log(" svstate.dststep", dststep
)
3168 log(" svstate.ssubstep", ssubstep
)
3169 log(" svstate.dsubstep", dsubstep
)
3170 log(" svstate.pack", pack
)
3171 log(" svstate.unpack", unpack
)
3172 log(" mode", rm_mode
)
3173 log(" reverse", reverse_gear
)
3174 log(" out_vec", out_vec
)
3175 log(" in_vec", in_vec
)
3176 log(" sv_ptype", sv_ptype
, sv_ptype
== SVPType
.P2
.value
)
3177 log(" rm_mode", rm_mode
)
3178 # check if this was an sv.bc* and if so did it succeed
3179 if self
.is_svp64_mode
and insn_name
.startswith("sv.bc"):
3180 end_loop
= self
.namespace
['end_loop']
3181 log("branch %s end_loop" % insn_name
, end_loop
)
3183 self
.svp64_reset_loop()
3184 self
.update_pc_next()
3186 # check if srcstep needs incrementing by one, stop PC advancing
3187 # but for 2-pred both src/dest have to be checked.
3188 # XXX this might not be true! it may just be LD/ST
3189 if sv_ptype
== SVPType
.P2
.value
:
3190 svp64_is_vector
= (out_vec
or in_vec
)
3192 svp64_is_vector
= out_vec
3193 # also if data-dependent fail-first is used, only in_vec is tested,
3194 # allowing *scalar destinations* to be used as an accumulator.
3195 # effectively this implies /mr (mapreduce mode) is 100% on with ddffirst
3196 # see https://bugs.libre-soc.org/show_bug.cgi?id=1183#c16
3197 ffirst
= yield from is_ffirst_mode(self
.dec2
)
3199 svp64_is_vector
= in_vec
3201 # loops end at the first "hit" (source or dest)
3202 yield from self
.advance_svstate_steps()
3203 loopend
= self
.loopend
3204 log("loopend", svp64_is_vector
, loopend
)
3205 if not svp64_is_vector
or loopend
:
3206 # reset loop to zero and update NIA
3207 self
.svp64_reset_loop()
3212 # still looping, advance and update NIA
3213 self
.namespace
['SVSTATE'] = self
.svstate
3215 # not an SVP64 branch, so fix PC (NIA==CIA) for next loop
3216 # (by default, NIA is CIA+4 if v3.0B or CIA+8 if SVP64)
3217 # this way we keep repeating the same instruction (with new steps)
3218 self
.pc
.NIA
.eq(self
.pc
.CIA
)
3219 self
.namespace
['NIA'] = self
.pc
.NIA
3220 log("end of sub-pc call", self
.namespace
['CIA'], self
.namespace
['NIA'])
3221 return False # DO NOT allow PC update whilst Sub-PC loop running
3223 def update_pc_next(self
):
3224 # UPDATE program counter
3225 self
.pc
.update(self
.namespace
, self
.is_svp64_mode
)
3226 #self.svstate.spr = self.namespace['SVSTATE']
3227 log("end of call", self
.namespace
['CIA'],
3228 self
.namespace
['NIA'],
3229 self
.namespace
['SVSTATE'])
3231 def svp64_reset_loop(self
):
3232 self
.svstate
.srcstep
= 0
3233 self
.svstate
.dststep
= 0
3234 self
.svstate
.ssubstep
= 0
3235 self
.svstate
.dsubstep
= 0
3236 self
.loopend
= False
3237 log(" svstate.srcstep loop end (PC to update)")
3238 self
.namespace
['SVSTATE'] = self
.svstate
3240 def update_nia(self
):
3241 self
.pc
.update_nia(self
.is_svp64_mode
)
3242 self
.namespace
['NIA'] = self
.pc
.NIA
3246 """Decorator factory.
3248 this decorator will "inject" variables into the function's namespace,
3249 from the *dictionary* in self.namespace. it therefore becomes possible
3250 to make it look like a whole stack of variables which would otherwise
3251 need "self." inserted in front of them (*and* for those variables to be
3252 added to the instance) "appear" in the function.
3254 "self.namespace['SI']" for example becomes accessible as just "SI" but
3255 *only* inside the function, when decorated.
3257 def variable_injector(func
):
3259 def decorator(*args
, **kwargs
):
3261 func_globals
= func
.__globals
__ # Python 2.6+
3262 except AttributeError:
3263 func_globals
= func
.func_globals
# Earlier versions.
3265 context
= args
[0].namespace
# variables to be injected
3266 saved_values
= func_globals
.copy() # Shallow copy of dict.
3267 log("globals before", context
.keys())
3268 func_globals
.update(context
)
3269 result
= func(*args
, **kwargs
)
3270 log("globals after", func_globals
['CIA'], func_globals
['NIA'])
3271 log("args[0]", args
[0].namespace
['CIA'],
3272 args
[0].namespace
['NIA'],
3273 args
[0].namespace
['SVSTATE'])
3274 if 'end_loop' in func_globals
:
3275 log("args[0] end_loop", func_globals
['end_loop'])
3276 args
[0].namespace
= func_globals
3277 #exec (func.__code__, func_globals)
3280 # func_globals = saved_values # Undo changes.
3286 return variable_injector