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
):
175 return self
[ridx
+offs
]
176 # rrrright. start by breaking down into row/col, based on elwidth
177 gpr_offs
= offs
// (64//elwidth
)
178 gpr_col
= offs
% (64//elwidth
)
179 # now select the 64-bit register, but get its value (easier)
180 val
= self
[ridx
+gpr_offs
].value
181 # now shift down and mask out
182 val
= val
>> (gpr_col
*elwidth
) & ((1 << elwidth
)-1)
183 # finally, return a SelectableInt at the required elwidth
184 log("GPR call", ridx
, "isvec", is_vec
, "offs", offs
,
185 "elwid", elwidth
, "offs/col", gpr_offs
, gpr_col
, "val", hex(val
))
186 return SelectableInt(val
, elwidth
)
188 def set_form(self
, form
):
191 def write(self
, rnum
, value
, is_vec
=False, elwidth
=64):
193 if isinstance(rnum
, SelectableInt
):
195 if isinstance(value
, SelectableInt
):
198 if isinstance(rnum
, tuple):
199 rnum
, base
, offs
= rnum
202 # rrrright. start by breaking down into row/col, based on elwidth
203 gpr_offs
= offs
// (64//elwidth
)
204 gpr_col
= offs
% (64//elwidth
)
205 # compute the mask based on elwidth
206 mask
= (1 << elwidth
)-1
207 # now select the 64-bit register, but get its value (easier)
208 val
= self
[base
+gpr_offs
].value
209 # now mask out the bit we don't want
210 val
= val
& ~
(mask
<< (gpr_col
*elwidth
))
211 # then wipe the bit we don't want from the value
213 # OR the new value in, shifted up
214 val |
= value
<< (gpr_col
*elwidth
)
215 # finally put the damn value into the regfile
216 log("GPR write", base
, "isvec", is_vec
, "offs", offs
,
217 "elwid", elwidth
, "offs/col", gpr_offs
, gpr_col
, "val", hex(val
),
219 dict.__setitem
__(self
, base
+gpr_offs
, SelectableInt(val
, 64))
221 def __setitem__(self
, rnum
, value
):
222 # rnum = rnum.value # only SelectableInt allowed
223 log("GPR setitem", rnum
, value
)
224 if isinstance(rnum
, SelectableInt
):
226 dict.__setitem
__(self
, rnum
, value
)
228 def getz(self
, rnum
, rvalue
=None):
229 # rnum = rnum.value # only SelectableInt allowed
230 log("GPR getzero?", rnum
, rvalue
)
231 if rvalue
is not None:
233 return SelectableInt(0, rvalue
.bits
)
236 return SelectableInt(0, 64)
239 def _get_regnum(self
, attr
):
240 getform
= self
.sd
.sigforms
[self
.form
]
241 rnum
= getattr(getform
, attr
)
244 def ___getitem__(self
, attr
):
245 """ XXX currently not used
247 rnum
= self
._get
_regnum
(attr
)
248 log("GPR getitem", attr
, rnum
)
249 return self
.regfile
[rnum
]
251 def dump(self
, printout
=True, heading
="log"):
253 for i
in range(len(self
)):
254 res
.append(self
[i
].value
)
256 for i
in range(0, len(res
), 8):
259 s
.append("%08x" % res
[i
+j
])
261 log(heading
, "%2d" % i
, s
, kind
=LogType
.InstrInOuts
)
266 def __init__(self
, dec2
, initial_sprs
={}, gpr
=None):
268 self
.gpr
= gpr
# for SVSHAPE[0-3]
270 for key
, v
in initial_sprs
.items():
271 if isinstance(key
, SelectableInt
):
273 key
= special_sprs
.get(key
, key
)
274 if isinstance(key
, int):
277 info
= spr_byname
[key
]
278 if not isinstance(v
, SelectableInt
):
279 v
= SelectableInt(v
, info
.length
)
282 def __getitem__(self
, key
):
284 #log("dict", self.items())
285 # if key in special_sprs get the special spr, otherwise return key
286 if isinstance(key
, SelectableInt
):
288 if isinstance(key
, int):
289 key
= spr_dict
[key
].SPR
290 key
= special_sprs
.get(key
, key
)
291 if key
== 'HSRR0': # HACK!
293 if key
== 'HSRR1': # HACK!
296 res
= dict.__getitem
__(self
, key
)
298 if isinstance(key
, int):
301 info
= spr_byname
[key
]
302 self
[key
] = SelectableInt(0, info
.length
)
303 res
= dict.__getitem
__(self
, key
)
304 #log("spr returning", key, res)
307 def __setitem__(self
, key
, value
):
308 if isinstance(key
, SelectableInt
):
310 if isinstance(key
, int):
311 key
= spr_dict
[key
].SPR
313 key
= special_sprs
.get(key
, key
)
314 if key
== 'HSRR0': # HACK!
315 self
.__setitem
__('SRR0', value
)
316 if key
== 'HSRR1': # HACK!
317 self
.__setitem
__('SRR1', value
)
319 value
= XERState(value
)
320 if key
in ('SVSHAPE0', 'SVSHAPE1', 'SVSHAPE2', 'SVSHAPE3'):
321 value
= SVSHAPE(value
, self
.gpr
)
322 log("setting spr", key
, value
)
323 dict.__setitem
__(self
, key
, value
)
325 def __call__(self
, ridx
):
328 def dump(self
, printout
=True):
330 keys
= list(self
.keys())
333 sprname
= spr_dict
.get(k
, None)
337 sprname
= sprname
.SPR
338 res
.append((sprname
, self
[k
].value
))
340 for sprname
, value
in res
:
341 print(" ", sprname
, hex(value
))
346 def __init__(self
, pc_init
=0):
347 self
.CIA
= SelectableInt(pc_init
, 64)
348 self
.NIA
= self
.CIA
+ SelectableInt(4, 64) # only true for v3.0B!
350 def update_nia(self
, is_svp64
):
351 increment
= 8 if is_svp64
else 4
352 self
.NIA
= self
.CIA
+ SelectableInt(increment
, 64)
354 def update(self
, namespace
, is_svp64
):
355 """updates the program counter (PC) by 4 if v3.0B mode or 8 if SVP64
357 self
.CIA
= namespace
['NIA'].narrow(64)
358 self
.update_nia(is_svp64
)
359 namespace
['CIA'] = self
.CIA
360 namespace
['NIA'] = self
.NIA
364 # See PowerISA Version 3.0 B Book 1
365 # Section 2.3.1 Condition Register pages 30 - 31
367 LT
= FL
= 0 # negative, less than, floating-point less than
368 GT
= FG
= 1 # positive, greater than, floating-point greater than
369 EQ
= FE
= 2 # equal, floating-point equal
370 SO
= FU
= 3 # summary overflow, floating-point unordered
372 def __init__(self
, init
=0):
373 # rev_cr = int('{:016b}'.format(initial_cr)[::-1], 2)
374 # self.cr = FieldSelectableInt(self._cr, list(range(32, 64)))
375 self
.cr
= SelectableInt(init
, 64) # underlying reg
376 # field-selectable versions of Condition Register TODO check bitranges?
379 bits
= tuple(range(i
*4+32, (i
+1)*4+32))
380 _cr
= FieldSelectableInt(self
.cr
, bits
)
384 # decode SVP64 predicate integer to reg number and invert
385 def get_predint(gpr
, mask
):
389 log("get_predint", mask
, SVP64PredInt
.ALWAYS
.value
)
390 if mask
== SVP64PredInt
.ALWAYS
.value
:
391 return 0xffff_ffff_ffff_ffff # 64 bits of 1
392 if mask
== SVP64PredInt
.R3_UNARY
.value
:
393 return 1 << (r3
.value
& 0b111111)
394 if mask
== SVP64PredInt
.R3
.value
:
396 if mask
== SVP64PredInt
.R3_N
.value
:
398 if mask
== SVP64PredInt
.R10
.value
:
400 if mask
== SVP64PredInt
.R10_N
.value
:
402 if mask
== SVP64PredInt
.R30
.value
:
404 if mask
== SVP64PredInt
.R30_N
.value
:
408 # decode SVP64 predicate CR to reg number and invert status
409 def _get_predcr(mask
):
410 if mask
== SVP64PredCR
.LT
.value
:
412 if mask
== SVP64PredCR
.GE
.value
:
414 if mask
== SVP64PredCR
.GT
.value
:
416 if mask
== SVP64PredCR
.LE
.value
:
418 if mask
== SVP64PredCR
.EQ
.value
:
420 if mask
== SVP64PredCR
.NE
.value
:
422 if mask
== SVP64PredCR
.SO
.value
:
424 if mask
== SVP64PredCR
.NS
.value
:
428 # read individual CR fields (0..VL-1), extract the required bit
429 # and construct the mask
430 def get_predcr(crl
, predselect
, vl
):
431 idx
, noninv
= _get_predcr(predselect
)
434 cr
= crl
[i
+SVP64CROffs
.CRPred
]
435 if cr
[idx
].value
== noninv
:
437 log("get_predcr", vl
, idx
, noninv
, i
+SVP64CROffs
.CRPred
,
438 bin(cr
.asint()), cr
[idx
].value
, bin(mask
))
442 # TODO, really should just be using PowerDecoder2
443 def get_idx_map(dec2
, name
):
445 in1_sel
= yield op
.in1_sel
446 in2_sel
= yield op
.in2_sel
447 in3_sel
= yield op
.in3_sel
448 in1
= yield dec2
.e
.read_reg1
.data
449 # identify which regnames map to in1/2/3
450 if name
== 'RA' or name
== 'RA_OR_ZERO':
451 if (in1_sel
== In1Sel
.RA
.value
or
452 (in1_sel
== In1Sel
.RA_OR_ZERO
.value
and in1
!= 0)):
454 if in1_sel
== In1Sel
.RA_OR_ZERO
.value
:
457 if in2_sel
== In2Sel
.RB
.value
:
459 if in3_sel
== In3Sel
.RB
.value
:
461 # XXX TODO, RC doesn't exist yet!
463 if in3_sel
== In3Sel
.RC
.value
:
465 elif name
in ['EA', 'RS']:
466 if in1_sel
== In1Sel
.RS
.value
:
468 if in2_sel
== In2Sel
.RS
.value
:
470 if in3_sel
== In3Sel
.RS
.value
:
473 if in1_sel
== In1Sel
.FRA
.value
:
475 if in3_sel
== In3Sel
.FRA
.value
:
478 if in2_sel
== In2Sel
.FRB
.value
:
481 if in3_sel
== In3Sel
.FRC
.value
:
484 if in1_sel
== In1Sel
.FRS
.value
:
486 if in3_sel
== In3Sel
.FRS
.value
:
489 if in1_sel
== In1Sel
.FRT
.value
:
492 if in1_sel
== In1Sel
.RT
.value
:
497 # TODO, really should just be using PowerDecoder2
498 def get_idx_in(dec2
, name
, ewmode
=False):
499 idx
= yield from get_idx_map(dec2
, name
)
503 in1_sel
= yield op
.in1_sel
504 in2_sel
= yield op
.in2_sel
505 in3_sel
= yield op
.in3_sel
506 # get the IN1/2/3 from the decoder (includes SVP64 remap and isvec)
507 in1
= yield dec2
.e
.read_reg1
.data
508 in2
= yield dec2
.e
.read_reg2
.data
509 in3
= yield dec2
.e
.read_reg3
.data
511 in1_base
= yield dec2
.e
.read_reg1
.base
512 in2_base
= yield dec2
.e
.read_reg2
.base
513 in3_base
= yield dec2
.e
.read_reg3
.base
514 in1_offs
= yield dec2
.e
.read_reg1
.offs
515 in2_offs
= yield dec2
.e
.read_reg2
.offs
516 in3_offs
= yield dec2
.e
.read_reg3
.offs
517 in1
= (in1
, in1_base
, in1_offs
)
518 in2
= (in2
, in2_base
, in2_offs
)
519 in3
= (in3
, in3_base
, in3_offs
)
521 in1_isvec
= yield dec2
.in1_isvec
522 in2_isvec
= yield dec2
.in2_isvec
523 in3_isvec
= yield dec2
.in3_isvec
524 log("get_idx_in in1", name
, in1_sel
, In1Sel
.RA
.value
,
526 log("get_idx_in in2", name
, in2_sel
, In2Sel
.RB
.value
,
528 log("get_idx_in in3", name
, in3_sel
, In3Sel
.RS
.value
,
530 log("get_idx_in FRS in3", name
, in3_sel
, In3Sel
.FRS
.value
,
532 log("get_idx_in FRB in2", name
, in2_sel
, In2Sel
.FRB
.value
,
534 log("get_idx_in FRC in3", name
, in3_sel
, In3Sel
.FRC
.value
,
537 return in1
, in1_isvec
539 return in2
, in2_isvec
541 return in3
, in3_isvec
545 # TODO, really should just be using PowerDecoder2
546 def get_cr_in(dec2
, name
):
548 in_sel
= yield op
.cr_in
549 in_bitfield
= yield dec2
.dec_cr_in
.cr_bitfield
.data
550 sv_cr_in
= yield op
.sv_cr_in
551 spec
= yield dec2
.crin_svdec
.spec
552 sv_override
= yield dec2
.dec_cr_in
.sv_override
553 # get the IN1/2/3 from the decoder (includes SVP64 remap and isvec)
554 in1
= yield dec2
.e
.read_cr1
.data
555 cr_isvec
= yield dec2
.cr_in_isvec
556 log("get_cr_in", in_sel
, CROutSel
.CR0
.value
, in1
, cr_isvec
)
557 log(" sv_cr_in", sv_cr_in
)
558 log(" cr_bf", in_bitfield
)
560 log(" override", sv_override
)
561 # identify which regnames map to in / o2
563 if in_sel
== CRInSel
.BI
.value
:
565 if name
in ['BA', 'BB']:
566 if in_sel
== CRInSel
.BA_BB
.value
:
569 if in_sel
== CRInSel
.BFA
.value
:
571 log("get_cr_in not found", name
)
575 # TODO, really should just be using PowerDecoder2
576 def get_cr_out(dec2
, name
):
578 out_sel
= yield op
.cr_out
579 out_bitfield
= yield dec2
.dec_cr_out
.cr_bitfield
.data
580 sv_cr_out
= yield op
.sv_cr_out
581 spec
= yield dec2
.crout_svdec
.spec
582 sv_override
= yield dec2
.dec_cr_out
.sv_override
583 # get the IN1/2/3 from the decoder (includes SVP64 remap and isvec)
584 out
= yield dec2
.e
.write_cr
.data
585 o_isvec
= yield dec2
.cr_out_isvec
586 log("get_cr_out", out_sel
, CROutSel
.CR0
.value
, out
, o_isvec
)
587 log(" sv_cr_out", sv_cr_out
)
588 log(" cr_bf", out_bitfield
)
590 log(" override", sv_override
)
591 # identify which regnames map to out / o2
593 if out_sel
== CROutSel
.BF
.value
:
596 if out_sel
== CROutSel
.BT
.value
:
599 if out_sel
== CROutSel
.CR0
.value
:
601 if name
== 'CR1': # these are not actually calculated correctly
602 if out_sel
== CROutSel
.CR1
.value
:
604 # check RC1 set? if so return implicit vector, this is a REAL bad hack
605 RC1
= yield dec2
.rm_dec
.RC1
607 log("get_cr_out RC1 mode")
609 return 0, True # XXX TODO: offset CR0 from SVSTATE SPR
611 return 1, True # XXX TODO: offset CR1 from SVSTATE SPR
613 log("get_cr_out not found", name
)
617 # TODO, really should just be using PowerDecoder2
618 def get_out_map(dec2
, name
):
620 out_sel
= yield op
.out_sel
621 # get the IN1/2/3 from the decoder (includes SVP64 remap and isvec)
622 out
= yield dec2
.e
.write_reg
.data
623 # identify which regnames map to out / o2
625 if out_sel
== OutSel
.RA
.value
:
628 if out_sel
== OutSel
.RT
.value
:
630 if out_sel
== OutSel
.RT_OR_ZERO
.value
and out
!= 0:
632 elif name
== 'RT_OR_ZERO':
633 if out_sel
== OutSel
.RT_OR_ZERO
.value
:
636 if out_sel
== OutSel
.FRA
.value
:
639 if out_sel
== OutSel
.FRS
.value
:
642 if out_sel
== OutSel
.FRT
.value
:
647 # TODO, really should just be using PowerDecoder2
648 def get_idx_out(dec2
, name
, ewmode
=False):
650 out_sel
= yield op
.out_sel
651 # get the IN1/2/3 from the decoder (includes SVP64 remap and isvec)
652 out
= yield dec2
.e
.write_reg
.data
653 o_isvec
= yield dec2
.o_isvec
655 offs
= yield dec2
.e
.write_reg
.offs
656 base
= yield dec2
.e
.write_reg
.base
657 out
= (out
, base
, offs
)
658 # identify which regnames map to out / o2
659 ismap
= yield from get_out_map(dec2
, name
)
661 log("get_idx_out", name
, out_sel
, out
, o_isvec
)
663 log("get_idx_out not found", name
, out_sel
, out
, o_isvec
)
667 # TODO, really should just be using PowerDecoder2
668 def get_out2_map(dec2
, name
):
669 # check first if register is activated for write
671 out_sel
= yield op
.out_sel
672 out
= yield dec2
.e
.write_ea
.data
673 out_ok
= yield dec2
.e
.write_ea
.ok
677 if name
in ['EA', 'RA']:
678 if hasattr(op
, "upd"):
679 # update mode LD/ST uses read-reg A also as an output
681 log("get_idx_out2", upd
, LDSTMode
.update
.value
,
682 out_sel
, OutSel
.RA
.value
,
684 if upd
== LDSTMode
.update
.value
:
687 fft_en
= yield dec2
.implicit_rs
689 log("get_idx_out2", out_sel
, OutSel
.RS
.value
,
693 fft_en
= yield dec2
.implicit_rs
695 log("get_idx_out2", out_sel
, OutSel
.FRS
.value
,
701 # TODO, really should just be using PowerDecoder2
702 def get_idx_out2(dec2
, name
, ewmode
=False):
703 # check first if register is activated for write
705 out_sel
= yield op
.out_sel
706 out
= yield dec2
.e
.write_ea
.data
708 offs
= yield dec2
.e
.write_ea
.offs
709 base
= yield dec2
.e
.write_ea
.base
710 out
= (out
, base
, offs
)
711 o_isvec
= yield dec2
.o2_isvec
712 ismap
= yield from get_out2_map(dec2
, name
)
714 log("get_idx_out2", name
, out_sel
, out
, o_isvec
)
720 """deals with svstate looping.
723 def __init__(self
, svstate
):
724 self
.svstate
= svstate
727 def new_iterators(self
):
728 self
.src_it
= self
.src_iterator()
729 self
.dst_it
= self
.dst_iterator()
733 self
.new_ssubstep
= 0
734 self
.new_dsubstep
= 0
735 self
.pred_dst_zero
= 0
736 self
.pred_src_zero
= 0
738 def src_iterator(self
):
739 """source-stepping iterator
741 pack
= self
.svstate
.pack
745 # pack advances subvl in *outer* loop
746 while True: # outer subvl loop
747 while True: # inner vl loop
750 srcmask
= self
.srcmask
751 srcstep
= self
.svstate
.srcstep
752 pred_src_zero
= ((1 << srcstep
) & srcmask
) != 0
753 if self
.pred_sz
or pred_src_zero
:
754 self
.pred_src_zero
= not pred_src_zero
755 log(" advance src", srcstep
, vl
,
756 self
.svstate
.ssubstep
, subvl
)
757 # yield actual substep/srcstep
758 yield (self
.svstate
.ssubstep
, srcstep
)
759 # the way yield works these could have been modified.
762 srcstep
= self
.svstate
.srcstep
763 log(" advance src check", srcstep
, vl
,
764 self
.svstate
.ssubstep
, subvl
, srcstep
== vl
-1,
765 self
.svstate
.ssubstep
== subvl
)
766 if srcstep
== vl
-1: # end-point
767 self
.svstate
.srcstep
= SelectableInt(0, 7) # reset
768 if self
.svstate
.ssubstep
== subvl
: # end-point
769 log(" advance pack stop")
771 break # exit inner loop
772 self
.svstate
.srcstep
+= SelectableInt(1, 7) # advance ss
774 if self
.svstate
.ssubstep
== subvl
: # end-point
775 self
.svstate
.ssubstep
= SelectableInt(0, 2) # reset
776 log(" advance pack stop")
778 self
.svstate
.ssubstep
+= SelectableInt(1, 2)
781 # these cannot be done as for-loops because SVSTATE may change
782 # (srcstep/substep may be modified, interrupted, subvl/vl change)
783 # but they *can* be done as while-loops as long as every SVSTATE
784 # "thing" is re-read every single time a yield gives indices
785 while True: # outer vl loop
786 while True: # inner subvl loop
789 srcmask
= self
.srcmask
790 srcstep
= self
.svstate
.srcstep
791 pred_src_zero
= ((1 << srcstep
) & srcmask
) != 0
792 if self
.pred_sz
or pred_src_zero
:
793 self
.pred_src_zero
= not pred_src_zero
794 log(" advance src", srcstep
, vl
,
795 self
.svstate
.ssubstep
, subvl
)
796 # yield actual substep/srcstep
797 yield (self
.svstate
.ssubstep
, srcstep
)
798 if self
.svstate
.ssubstep
== subvl
: # end-point
799 self
.svstate
.ssubstep
= SelectableInt(0, 2) # reset
800 break # exit inner loop
801 self
.svstate
.ssubstep
+= SelectableInt(1, 2)
803 if srcstep
== vl
-1: # end-point
804 self
.svstate
.srcstep
= SelectableInt(0, 7) # reset
807 self
.svstate
.srcstep
+= SelectableInt(1, 7) # advance srcstep
809 def dst_iterator(self
):
810 """dest-stepping iterator
812 unpack
= self
.svstate
.unpack
816 # pack advances subvl in *outer* loop
817 while True: # outer subvl loop
818 while True: # inner vl loop
821 dstmask
= self
.dstmask
822 dststep
= self
.svstate
.dststep
823 pred_dst_zero
= ((1 << dststep
) & dstmask
) != 0
824 if self
.pred_dz
or pred_dst_zero
:
825 self
.pred_dst_zero
= not pred_dst_zero
826 log(" advance dst", dststep
, vl
,
827 self
.svstate
.dsubstep
, subvl
)
828 # yield actual substep/dststep
829 yield (self
.svstate
.dsubstep
, dststep
)
830 # the way yield works these could have been modified.
832 dststep
= self
.svstate
.dststep
833 log(" advance dst check", dststep
, vl
,
834 self
.svstate
.ssubstep
, subvl
)
835 if dststep
== vl
-1: # end-point
836 self
.svstate
.dststep
= SelectableInt(0, 7) # reset
837 if self
.svstate
.dsubstep
== subvl
: # end-point
838 log(" advance unpack stop")
841 self
.svstate
.dststep
+= SelectableInt(1, 7) # advance ds
843 if self
.svstate
.dsubstep
== subvl
: # end-point
844 self
.svstate
.dsubstep
= SelectableInt(0, 2) # reset
845 log(" advance unpack stop")
847 self
.svstate
.dsubstep
+= SelectableInt(1, 2)
849 # these cannot be done as for-loops because SVSTATE may change
850 # (dststep/substep may be modified, interrupted, subvl/vl change)
851 # but they *can* be done as while-loops as long as every SVSTATE
852 # "thing" is re-read every single time a yield gives indices
853 while True: # outer vl loop
854 while True: # inner subvl loop
856 dstmask
= self
.dstmask
857 dststep
= self
.svstate
.dststep
858 pred_dst_zero
= ((1 << dststep
) & dstmask
) != 0
859 if self
.pred_dz
or pred_dst_zero
:
860 self
.pred_dst_zero
= not pred_dst_zero
861 log(" advance dst", dststep
, self
.svstate
.vl
,
862 self
.svstate
.dsubstep
, subvl
)
863 # yield actual substep/dststep
864 yield (self
.svstate
.dsubstep
, dststep
)
865 if self
.svstate
.dsubstep
== subvl
: # end-point
866 self
.svstate
.dsubstep
= SelectableInt(0, 2) # reset
868 self
.svstate
.dsubstep
+= SelectableInt(1, 2)
871 if dststep
== vl
-1: # end-point
872 self
.svstate
.dststep
= SelectableInt(0, 7) # reset
874 self
.svstate
.dststep
+= SelectableInt(1, 7) # advance dststep
876 def src_iterate(self
):
877 """source-stepping iterator
881 pack
= self
.svstate
.pack
882 unpack
= self
.svstate
.unpack
883 ssubstep
= self
.svstate
.ssubstep
884 end_ssub
= ssubstep
== subvl
885 end_src
= self
.svstate
.srcstep
== vl
-1
886 log(" pack/unpack/subvl", pack
, unpack
, subvl
,
890 srcstep
= self
.svstate
.srcstep
891 srcmask
= self
.srcmask
893 # pack advances subvl in *outer* loop
895 assert srcstep
<= vl
-1
896 end_src
= srcstep
== vl
-1
901 self
.svstate
.ssubstep
+= SelectableInt(1, 2)
905 srcstep
+= 1 # advance srcstep
906 if not self
.srcstep_skip
:
908 if ((1 << srcstep
) & srcmask
) != 0:
911 log(" sskip", bin(srcmask
), bin(1 << srcstep
))
913 # advance subvl in *inner* loop
916 assert srcstep
<= vl
-1
917 end_src
= srcstep
== vl
-1
918 if end_src
: # end-point
924 if not self
.srcstep_skip
:
926 if ((1 << srcstep
) & srcmask
) != 0:
929 log(" sskip", bin(srcmask
), bin(1 << srcstep
))
930 self
.svstate
.ssubstep
= SelectableInt(0, 2) # reset
933 self
.svstate
.ssubstep
+= SelectableInt(1, 2)
935 self
.svstate
.srcstep
= SelectableInt(srcstep
, 7)
936 log(" advance src", self
.svstate
.srcstep
, self
.svstate
.ssubstep
,
939 def dst_iterate(self
):
940 """dest step iterator
944 pack
= self
.svstate
.pack
945 unpack
= self
.svstate
.unpack
946 dsubstep
= self
.svstate
.dsubstep
947 end_dsub
= dsubstep
== subvl
948 dststep
= self
.svstate
.dststep
949 end_dst
= dststep
== vl
-1
950 dstmask
= self
.dstmask
951 log(" pack/unpack/subvl", pack
, unpack
, subvl
,
956 # unpack advances subvl in *outer* loop
958 assert dststep
<= vl
-1
959 end_dst
= dststep
== vl
-1
964 self
.svstate
.dsubstep
+= SelectableInt(1, 2)
968 dststep
+= 1 # advance dststep
969 if not self
.dststep_skip
:
971 if ((1 << dststep
) & dstmask
) != 0:
974 log(" dskip", bin(dstmask
), bin(1 << dststep
))
976 # advance subvl in *inner* loop
979 assert dststep
<= vl
-1
980 end_dst
= dststep
== vl
-1
981 if end_dst
: # end-point
987 if not self
.dststep_skip
:
989 if ((1 << dststep
) & dstmask
) != 0:
992 log(" dskip", bin(dstmask
), bin(1 << dststep
))
993 self
.svstate
.dsubstep
= SelectableInt(0, 2) # reset
996 self
.svstate
.dsubstep
+= SelectableInt(1, 2)
998 self
.svstate
.dststep
= SelectableInt(dststep
, 7)
999 log(" advance dst", self
.svstate
.dststep
, self
.svstate
.dsubstep
,
1002 def at_loopend(self
):
1003 """tells if this is the last possible element. uses the cached values
1004 for src/dst-step and sub-steps
1007 vl
= self
.svstate
.vl
1008 srcstep
, dststep
= self
.new_srcstep
, self
.new_dststep
1009 ssubstep
, dsubstep
= self
.new_ssubstep
, self
.new_dsubstep
1010 end_ssub
= ssubstep
== subvl
1011 end_dsub
= dsubstep
== subvl
1012 if srcstep
== vl
-1 and end_ssub
:
1014 if dststep
== vl
-1 and end_dsub
:
1018 def advance_svstate_steps(self
):
1019 """ advance sub/steps. note that Pack/Unpack *INVERTS* the order.
1020 TODO when Pack/Unpack is set, substep becomes the *outer* loop
1022 self
.subvl
= yield self
.dec2
.rm_dec
.rm_in
.subvl
1023 if self
.loopend
: # huhn??
1028 def read_src_mask(self
):
1029 """read/update pred_sz and src mask
1031 # get SVSTATE VL (oh and print out some debug stuff)
1032 vl
= self
.svstate
.vl
1033 srcstep
= self
.svstate
.srcstep
1034 ssubstep
= self
.svstate
.ssubstep
1036 # get predicate mask (all 64 bits)
1037 srcmask
= 0xffff_ffff_ffff_ffff
1039 pmode
= yield self
.dec2
.rm_dec
.predmode
1040 sv_ptype
= yield self
.dec2
.dec
.op
.SV_Ptype
1041 srcpred
= yield self
.dec2
.rm_dec
.srcpred
1042 dstpred
= yield self
.dec2
.rm_dec
.dstpred
1043 pred_sz
= yield self
.dec2
.rm_dec
.pred_sz
1044 if pmode
== SVP64PredMode
.INT
.value
:
1045 srcmask
= dstmask
= get_predint(self
.gpr
, dstpred
)
1046 if sv_ptype
== SVPType
.P2
.value
:
1047 srcmask
= get_predint(self
.gpr
, srcpred
)
1048 elif pmode
== SVP64PredMode
.CR
.value
:
1049 srcmask
= dstmask
= get_predcr(self
.crl
, dstpred
, vl
)
1050 if sv_ptype
== SVPType
.P2
.value
:
1051 srcmask
= get_predcr(self
.crl
, srcpred
, vl
)
1052 # work out if the ssubsteps are completed
1053 ssubstart
= ssubstep
== 0
1054 log(" pmode", pmode
)
1055 log(" ptype", sv_ptype
)
1056 log(" srcpred", bin(srcpred
))
1057 log(" srcmask", bin(srcmask
))
1058 log(" pred_sz", bin(pred_sz
))
1059 log(" ssubstart", ssubstart
)
1061 # store all that above
1062 self
.srcstep_skip
= False
1063 self
.srcmask
= srcmask
1064 self
.pred_sz
= pred_sz
1065 self
.new_ssubstep
= ssubstep
1066 log(" new ssubstep", ssubstep
)
1067 # until the predicate mask has a "1" bit... or we run out of VL
1068 # let srcstep==VL be the indicator to move to next instruction
1070 self
.srcstep_skip
= True
1072 def read_dst_mask(self
):
1073 """same as read_src_mask - check and record everything needed
1075 # get SVSTATE VL (oh and print out some debug stuff)
1076 # yield Delay(1e-10) # make changes visible
1077 vl
= self
.svstate
.vl
1078 dststep
= self
.svstate
.dststep
1079 dsubstep
= self
.svstate
.dsubstep
1081 # get predicate mask (all 64 bits)
1082 dstmask
= 0xffff_ffff_ffff_ffff
1084 pmode
= yield self
.dec2
.rm_dec
.predmode
1085 reverse_gear
= yield self
.dec2
.rm_dec
.reverse_gear
1086 sv_ptype
= yield self
.dec2
.dec
.op
.SV_Ptype
1087 dstpred
= yield self
.dec2
.rm_dec
.dstpred
1088 pred_dz
= yield self
.dec2
.rm_dec
.pred_dz
1089 if pmode
== SVP64PredMode
.INT
.value
:
1090 dstmask
= get_predint(self
.gpr
, dstpred
)
1091 elif pmode
== SVP64PredMode
.CR
.value
:
1092 dstmask
= get_predcr(self
.crl
, dstpred
, vl
)
1093 # work out if the ssubsteps are completed
1094 dsubstart
= dsubstep
== 0
1095 log(" pmode", pmode
)
1096 log(" ptype", sv_ptype
)
1097 log(" dstpred", bin(dstpred
))
1098 log(" dstmask", bin(dstmask
))
1099 log(" pred_dz", bin(pred_dz
))
1100 log(" dsubstart", dsubstart
)
1102 self
.dststep_skip
= False
1103 self
.dstmask
= dstmask
1104 self
.pred_dz
= pred_dz
1105 self
.new_dsubstep
= dsubstep
1106 log(" new dsubstep", dsubstep
)
1108 self
.dststep_skip
= True
1110 def svstate_pre_inc(self
):
1111 """check if srcstep/dststep need to skip over masked-out predicate bits
1112 note that this is not supposed to do anything to substep,
1113 it is purely for skipping masked-out bits
1116 self
.subvl
= yield self
.dec2
.rm_dec
.rm_in
.subvl
1117 yield from self
.read_src_mask()
1118 yield from self
.read_dst_mask()
1125 srcstep
= self
.svstate
.srcstep
1126 srcmask
= self
.srcmask
1127 pred_src_zero
= self
.pred_sz
1128 vl
= self
.svstate
.vl
1129 # srcstep-skipping opportunity identified
1130 if self
.srcstep_skip
:
1131 # cannot do this with sv.bc - XXX TODO
1134 while (((1 << srcstep
) & srcmask
) == 0) and (srcstep
!= vl
):
1135 log(" sskip", bin(1 << srcstep
))
1138 # now work out if the relevant mask bits require zeroing
1140 pred_src_zero
= ((1 << srcstep
) & srcmask
) == 0
1142 # store new srcstep / dststep
1143 self
.new_srcstep
= srcstep
1144 self
.pred_src_zero
= pred_src_zero
1145 log(" new srcstep", srcstep
)
1148 # dststep-skipping opportunity identified
1149 dststep
= self
.svstate
.dststep
1150 dstmask
= self
.dstmask
1151 pred_dst_zero
= self
.pred_dz
1152 vl
= self
.svstate
.vl
1153 if self
.dststep_skip
:
1154 # cannot do this with sv.bc - XXX TODO
1157 while (((1 << dststep
) & dstmask
) == 0) and (dststep
!= vl
):
1158 log(" dskip", bin(1 << dststep
))
1161 # now work out if the relevant mask bits require zeroing
1163 pred_dst_zero
= ((1 << dststep
) & dstmask
) == 0
1165 # store new srcstep / dststep
1166 self
.new_dststep
= dststep
1167 self
.pred_dst_zero
= pred_dst_zero
1168 log(" new dststep", dststep
)
1171 class ExitSyscallCalled(Exception):
1175 class SyscallEmulator(openpower
.syscalls
.Dispatcher
):
1176 def __init__(self
, isacaller
):
1177 self
.__isacaller
= isacaller
1179 host
= os
.uname().machine
1180 bits
= (64 if (sys
.maxsize
> (2**32)) else 32)
1181 host
= openpower
.syscalls
.architecture(arch
=host
, bits
=bits
)
1183 return super().__init
__(guest
="ppc64", host
=host
)
1185 def __call__(self
, identifier
, *arguments
):
1186 (identifier
, *arguments
) = map(int, (identifier
, *arguments
))
1187 return super().__call
__(identifier
, *arguments
)
1189 def sys_exit_group(self
, status
, *rest
):
1190 self
.__isacaller
.halted
= True
1191 raise ExitSyscallCalled(status
)
1193 def sys_write(self
, fd
, buf
, count
, *rest
):
1195 buf
= self
.__isacaller
.mem
.get_ctypes(buf
, count
, is_write
=False)
1199 return os
.write(fd
, buf
)
1200 except OSError as e
:
1203 def sys_writev(self
, fd
, iov
, iovcnt
, *rest
):
1205 if iovcnt
< 0 or iovcnt
> IOV_MAX
:
1206 return -errno
.EINVAL
1207 struct_iovec
= struct
.Struct("<QQ")
1210 iov
= self
.__isacaller
.mem
.get_ctypes(
1211 iov
, struct_iovec
.size
* iovcnt
, is_write
=False)
1212 iov
= list(struct_iovec
.iter_unpack(iov
))
1215 for i
, iovec
in enumerate(iov
):
1216 iov_base
, iov_len
= iovec
1217 iov
[i
] = self
.__isacaller
.mem
.get_ctypes(
1218 iov_base
, iov_len
, is_write
=False)
1219 except (ValueError, MemException
):
1220 return -errno
.EFAULT
1222 return os
.writev(fd
, iov
)
1223 except OSError as e
:
1226 def sys_read(self
, fd
, buf
, count
, *rest
):
1228 buf
= self
.__isacaller
.mem
.get_ctypes(buf
, count
, is_write
=True)
1232 return os
.readv(fd
, [buf
])
1233 except OSError as e
:
1236 def sys_mmap(self
, addr
, length
, prot
, flags
, fd
, offset
, *rest
):
1237 return self
.__isacaller
.mem
.mmap_syscall(
1238 addr
, length
, prot
, flags
, fd
, offset
, is_mmap2
=False)
1240 def sys_mmap2(self
, addr
, length
, prot
, flags
, fd
, offset
, *rest
):
1241 return self
.__isacaller
.mem
.mmap_syscall(
1242 addr
, length
, prot
, flags
, fd
, offset
, is_mmap2
=True)
1244 def sys_brk(self
, addr
, *rest
):
1245 return self
.__isacaller
.mem
.brk_syscall(addr
)
1247 def sys_munmap(self
, addr
, length
, *rest
):
1248 return -errno
.ENOSYS
# TODO: implement
1250 def sys_mprotect(self
, addr
, length
, prot
, *rest
):
1251 return -errno
.ENOSYS
# TODO: implement
1253 def sys_pkey_mprotect(self
, addr
, length
, prot
, pkey
, *rest
):
1254 return -errno
.ENOSYS
# TODO: implement
1256 def sys_openat(self
, dirfd
, pathname
, flags
, mode
, *rest
):
1258 path
= self
.__isacaller
.mem
.read_cstr(pathname
)
1259 except (ValueError, MemException
):
1260 return -errno
.EFAULT
1262 if dirfd
== ppc_flags
.AT_FDCWD
:
1263 return os
.open(path
, flags
, mode
)
1265 return os
.open(path
, flags
, mode
, dir_fd
=dirfd
)
1266 except OSError as e
:
1272 nodename
= uname
.nodename
.encode()
1273 release
= b
'5.6.0-1-powerpc64le'
1274 version
= b
'#1 SMP Debian 5.6.7-1 (2020-04-29)'
1275 machine
= b
'ppc64le'
1277 return sysname
, nodename
, release
, version
, machine
, domainname
1279 def sys_uname(self
, buf
, *rest
):
1280 s
= struct
.Struct("<65s65s65s65s65s")
1282 buf
= self
.__isacaller
.mem
.get_ctypes(buf
, s
.size
, is_write
=True)
1283 except (ValueError, MemException
):
1284 return -errno
.EFAULT
1285 sysname
, nodename
, release
, version
, machine
, domainname
= \
1287 s
.pack_into(buf
, 0, sysname
, nodename
, release
, version
, machine
)
1290 def sys_newuname(self
, buf
, *rest
):
1291 name_len
= ppc_flags
.__NEW
_UTS
_LEN
+ 1
1292 s
= struct
.Struct("<%ds%ds%ds%ds%ds%ds" % ((name_len
,) * 6))
1294 buf
= self
.__isacaller
.mem
.get_ctypes(buf
, s
.size
, is_write
=True)
1295 except (ValueError, MemException
):
1296 return -errno
.EFAULT
1297 sysname
, nodename
, release
, version
, machine
, domainname
= \
1300 sysname
, nodename
, release
, version
, machine
, domainname
)
1303 def sys_readlink(self
, pathname
, buf
, bufsiz
, *rest
):
1304 dirfd
= ppc_flags
.AT_FDCWD
1305 return self
.sys_readlinkat(dirfd
, pathname
, buf
, bufsiz
)
1307 def sys_readlinkat(self
, dirfd
, pathname
, buf
, bufsiz
, *rest
):
1309 path
= self
.__isacaller
.mem
.read_cstr(pathname
)
1311 buf
= self
.__isacaller
.mem
.get_ctypes(
1312 buf
, bufsiz
, is_write
=True)
1315 except (ValueError, MemException
):
1316 return -errno
.EFAULT
1318 if dirfd
== ppc_flags
.AT_FDCWD
:
1319 result
= os
.readlink(path
)
1321 result
= os
.readlink(path
, dir_fd
=dirfd
)
1322 retval
= min(len(result
), len(buf
))
1323 buf
[:retval
] = result
[:retval
]
1325 except OSError as e
:
1329 class ISACaller(ISACallerHelper
, ISAFPHelpers
, StepLoop
):
1330 # decoder2 - an instance of power_decoder2
1331 # regfile - a list of initial values for the registers
1332 # initial_{etc} - initial values for SPRs, Condition Register, Mem, MSR
1333 # respect_pc - tracks the program counter. requires initial_insns
1334 def __init__(self
, decoder2
, regfile
, initial_sprs
=None, initial_cr
=0,
1335 initial_mem
=None, initial_msr
=0,
1348 use_syscall_emu
=False,
1349 emulating_mmap
=False,
1350 real_page_size
=None):
1352 self
.syscall
= SyscallEmulator(isacaller
=self
)
1353 if not use_mmap_mem
:
1354 log("forcing use_mmap_mem due to use_syscall_emu active")
1359 # we will eventually be able to load ELF files without use_syscall_emu
1360 # (e.g. the linux kernel), so do it in a separate if block
1361 if isinstance(initial_insns
, ELFFile
):
1362 if not use_mmap_mem
:
1363 log("forcing use_mmap_mem due to loading an ELF file")
1365 if not emulating_mmap
:
1366 log("forcing emulating_mmap due to loading an ELF file")
1367 emulating_mmap
= True
1369 # trace log file for model output. if None do nothing
1370 self
.insnlog
= insnlog
1371 self
.insnlog_is_file
= hasattr(insnlog
, "write")
1372 if not self
.insnlog_is_file
and self
.insnlog
:
1373 self
.insnlog
= open(self
.insnlog
, "w")
1375 self
.bigendian
= bigendian
1377 self
.is_svp64_mode
= False
1378 self
.respect_pc
= respect_pc
1379 if initial_sprs
is None:
1381 if initial_mem
is None:
1383 if fpregfile
is None:
1384 fpregfile
= [0] * 32
1385 if initial_insns
is None:
1387 assert self
.respect_pc
== False, "instructions required to honor pc"
1388 if initial_msr
is None:
1389 initial_msr
= DEFAULT_MSR
1391 log("ISACaller insns", respect_pc
, initial_insns
, disassembly
)
1392 log("ISACaller initial_msr", initial_msr
)
1394 # "fake program counter" mode (for unit testing)
1398 if isinstance(initial_mem
, tuple):
1399 self
.fake_pc
= initial_mem
[0]
1400 disasm_start
= self
.fake_pc
1402 disasm_start
= initial_pc
1404 # disassembly: we need this for now (not given from the decoder)
1405 self
.disassembly
= {}
1407 for i
, code
in enumerate(disassembly
):
1408 self
.disassembly
[i
*4 + disasm_start
] = code
1410 # set up registers, instruction memory, data memory, PC, SPRs, MSR, CR
1411 self
.svp64rm
= SVP64RM()
1412 if initial_svstate
is None:
1414 if isinstance(initial_svstate
, int):
1415 initial_svstate
= SVP64State(initial_svstate
)
1416 # SVSTATE, MSR and PC
1417 StepLoop
.__init
__(self
, initial_svstate
)
1418 self
.msr
= SelectableInt(initial_msr
, 64) # underlying reg
1420 # GPR FPR SPR registers
1421 initial_sprs
= deepcopy(initial_sprs
) # so as not to get modified
1422 self
.gpr
= GPR(decoder2
, self
, self
.svstate
, regfile
)
1423 self
.fpr
= GPR(decoder2
, self
, self
.svstate
, fpregfile
)
1424 # initialise SPRs before MMU
1425 self
.spr
= SPR(decoder2
, initial_sprs
, gpr
=self
.gpr
)
1427 # set up 4 dummy SVSHAPEs if they aren't already set up
1429 sname
= 'SVSHAPE%d' % i
1430 val
= self
.spr
.get(sname
, 0)
1431 # make sure it's an SVSHAPE -- conversion done by SPR.__setitem__
1432 self
.spr
[sname
] = val
1433 self
.last_op_svshape
= False
1437 self
.mem
= MemMMap(row_bytes
=8,
1438 initial_mem
=initial_mem
,
1440 emulating_mmap
=emulating_mmap
)
1441 self
.imem
= self
.mem
1442 lelf
= self
.mem
.initialize(row_bytes
=4, initial_mem
=initial_insns
)
1443 if isinstance(lelf
, LoadedELF
): # stuff parsed from ELF
1444 initial_pc
= lelf
.pc
1445 for k
, v
in lelf
.gprs
.items():
1446 self
.gpr
[k
] = SelectableInt(v
, 64)
1447 initial_fpscr
= lelf
.fpscr
1448 self
.mem
.log_fancy(kind
=LogType
.InstrInOuts
)
1450 self
.mem
= Mem(row_bytes
=8, initial_mem
=initial_mem
,
1452 self
.mem
.log_fancy(kind
=LogType
.InstrInOuts
)
1453 self
.imem
= Mem(row_bytes
=4, initial_mem
=initial_insns
)
1454 # MMU mode, redirect underlying Mem through RADIX
1456 self
.mem
= RADIX(self
.mem
, self
)
1458 self
.imem
= RADIX(self
.imem
, self
)
1460 # TODO, needed here:
1461 # FPR (same as GPR except for FP nums)
1462 # 4.2.2 p124 FPSCR (definitely "separate" - not in SPR)
1463 # note that mffs, mcrfs, mtfsf "manage" this FPSCR
1464 self
.fpscr
= FPSCRState(initial_fpscr
)
1466 # 2.3.1 CR (and sub-fields CR0..CR6 - CR0 SO comes from XER.SO)
1467 # note that mfocrf, mfcr, mtcr, mtocrf, mcrxrx "manage" CRs
1469 # 2.3.2 LR (actually SPR #8) -- Done
1470 # 2.3.3 CTR (actually SPR #9) -- Done
1471 # 2.3.4 TAR (actually SPR #815)
1472 # 3.2.2 p45 XER (actually SPR #1) -- Done
1473 # 3.2.3 p46 p232 VRSAVE (actually SPR #256)
1475 # create CR then allow portions of it to be "selectable" (below)
1476 self
.cr_fields
= CRFields(initial_cr
)
1477 self
.cr
= self
.cr_fields
.cr
1478 self
.cr_backup
= 0 # sigh, dreadful hack: for fail-first (VLi)
1480 # "undefined", just set to variable-bit-width int (use exts "max")
1481 # self.undefined = SelectableInt(0, EFFECTIVELY_UNLIMITED)
1484 self
.namespace
.update(self
.spr
)
1485 self
.namespace
.update({'GPR': self
.gpr
,
1489 'memassign': self
.memassign
,
1492 'SVSTATE': self
.svstate
,
1493 'SVSHAPE0': self
.spr
['SVSHAPE0'],
1494 'SVSHAPE1': self
.spr
['SVSHAPE1'],
1495 'SVSHAPE2': self
.spr
['SVSHAPE2'],
1496 'SVSHAPE3': self
.spr
['SVSHAPE3'],
1499 'FPSCR': self
.fpscr
,
1500 'undefined': undefined
,
1501 'mode_is_64bit': True,
1502 'SO': XER_bits
['SO'],
1503 'XLEN': 64, # elwidth overrides
1507 if real_page_size
is None:
1508 # PowerISA v3.1B Book III Section 6.7 page 1191 (1217)
1509 # defines real page size as 2 ** 12 bytes (4KiB)
1510 real_page_size
= 2 ** 12
1511 self
.real_page_size
= real_page_size
1512 self
.reserve_addr
= SelectableInt(0, self
.XLEN
)
1513 self
.reserve
= SelectableInt(0, 1)
1514 self
.reserve_length
= SelectableInt(0, 4)
1516 self
.namespace
.update({'RESERVE': self
.RESERVE
,
1517 'RESERVE_ADDR': self
.RESERVE_ADDR
,
1518 'RESERVE_LENGTH': self
.RESERVE_LENGTH
,
1519 'REAL_PAGE_SIZE': self
.REAL_PAGE_SIZE
,
1522 for name
in BFP_FLAG_NAMES
:
1523 setattr(self
, name
, 0)
1525 # update pc to requested start point
1526 self
.set_pc(initial_pc
)
1528 # field-selectable versions of Condition Register
1529 self
.crl
= self
.cr_fields
.crl
1531 self
.namespace
["CR%d" % i
] = self
.crl
[i
]
1533 self
.decoder
= decoder2
.dec
1534 self
.dec2
= decoder2
1536 super().__init
__(XLEN
=self
.namespace
["XLEN"], FPSCR
=self
.fpscr
)
1538 def trace(self
, out
):
1539 if self
.insnlog
is None:
1541 self
.insnlog
.write(out
)
1545 return self
.namespace
["XLEN"]
1552 def RESERVE_LENGTH(self
):
1553 return self
.reserve_length
1556 def RESERVE_ADDR(self
):
1557 return self
.reserve_addr
1560 def REAL_PAGE_SIZE(self
):
1561 return self
.real_page_size
1563 def real_addr(self
, EA
):
1564 """ get the "real address to which `EA` maps"
1566 Specified in PowerISA v3.1B Book II Section 1.7.2.1 page 1049 (1075)
1568 # FIXME: translate EA to a physical address
1575 def call_trap(self
, trap_addr
, trap_bit
):
1576 """calls TRAP and sets up NIA to the new execution location.
1577 next instruction will begin at trap_addr.
1579 self
.TRAP(trap_addr
, trap_bit
)
1580 self
.namespace
['NIA'] = self
.trap_nia
1581 self
.pc
.update(self
.namespace
, self
.is_svp64_mode
)
1583 def TRAP(self
, trap_addr
=0x700, trap_bit
=PIb
.TRAP
):
1584 """TRAP> saves PC, MSR (and TODO SVSTATE), and updates MSR
1586 TRAP function is callable from inside the pseudocode itself,
1587 hence the default arguments. when calling from inside ISACaller
1588 it is best to use call_trap()
1590 trap_addr: int | SelectableInt
1591 the address to go to (before any modifications from `KAIVB`)
1592 trap_bit: int | None
1593 the bit in `SRR1` to set, `None` means don't set any bits.
1595 if isinstance(trap_addr
, SelectableInt
):
1596 trap_addr
= trap_addr
.value
1597 # https://bugs.libre-soc.org/show_bug.cgi?id=859
1598 kaivb
= self
.spr
['KAIVB'].value
1599 msr
= self
.namespace
['MSR'].value
1600 log("TRAP:", hex(trap_addr
), hex(msr
), "kaivb", hex(kaivb
))
1601 # store CIA(+4?) in SRR0, set NIA to 0x700
1602 # store MSR in SRR1, set MSR to um errr something, have to check spec
1603 # store SVSTATE (if enabled) in SVSRR0
1604 self
.spr
['SRR0'].value
= self
.pc
.CIA
.value
1605 self
.spr
['SRR1'].value
= msr
1606 if self
.is_svp64_mode
:
1607 self
.spr
['SVSRR0'] = self
.namespace
['SVSTATE'].value
1608 self
.trap_nia
= SelectableInt(trap_addr |
(kaivb
& ~
0x1fff), 64)
1609 if trap_bit
is not None:
1610 self
.spr
['SRR1'][trap_bit
] = 1 # change *copy* of MSR in SRR1
1612 # set exception bits. TODO: this should, based on the address
1613 # in figure 66 p1065 V3.0B and the table figure 65 p1063 set these
1614 # bits appropriately. however it turns out that *for now* in all
1615 # cases (all trap_addrs) the exact same thing is needed.
1616 self
.msr
[MSRb
.IR
] = 0
1617 self
.msr
[MSRb
.DR
] = 0
1618 self
.msr
[MSRb
.FE0
] = 0
1619 self
.msr
[MSRb
.FE1
] = 0
1620 self
.msr
[MSRb
.EE
] = 0
1621 self
.msr
[MSRb
.RI
] = 0
1622 self
.msr
[MSRb
.SF
] = 1
1623 self
.msr
[MSRb
.TM
] = 0
1624 self
.msr
[MSRb
.VEC
] = 0
1625 self
.msr
[MSRb
.VSX
] = 0
1626 self
.msr
[MSRb
.PR
] = 0
1627 self
.msr
[MSRb
.FP
] = 0
1628 self
.msr
[MSRb
.PMM
] = 0
1629 self
.msr
[MSRb
.TEs
] = 0
1630 self
.msr
[MSRb
.TEe
] = 0
1631 self
.msr
[MSRb
.UND
] = 0
1632 self
.msr
[MSRb
.LE
] = 1
1634 def memassign(self
, ea
, sz
, val
):
1635 self
.mem
.memassign(ea
, sz
, val
)
1637 def prep_namespace(self
, insn_name
, formname
, op_fields
, xlen
):
1638 # TODO: get field names from form in decoder*1* (not decoder2)
1639 # decoder2 is hand-created, and decoder1.sigform is auto-generated
1641 # then "yield" fields only from op_fields rather than hard-coded
1643 fields
= self
.decoder
.sigforms
[formname
]
1644 log("prep_namespace", formname
, op_fields
, insn_name
)
1645 for name
in op_fields
:
1646 # CR immediates. deal with separately. needs modifying
1648 crlen5
= ['BC', 'BA', 'BB', 'BT', 'BI'] # 5-bit
1649 crlen3
= ['BF', 'BFA'] # 3-bit (BF: bit-field)
1650 if self
.is_svp64_mode
and name
in crlen5
:
1651 # 5-bit, must reconstruct the value
1653 regnum
, is_vec
= yield from get_cr_out(self
.dec2
, name
)
1655 regnum
, is_vec
= yield from get_cr_in(self
.dec2
, name
)
1656 sig
= getattr(fields
, name
)
1658 # low 2 LSBs (CR field selector) remain same, CR num extended
1659 assert regnum
<= 7, "sigh, TODO, 128 CR fields"
1660 val
= (val
& 0b11) |
(regnum
<< 2)
1661 elif self
.is_svp64_mode
and name
in crlen3
:
1663 regnum
, is_vec
= yield from get_cr_out(self
.dec2
, name
)
1665 regnum
, is_vec
= yield from get_cr_in(self
.dec2
, name
)
1666 log('hack %s' % name
, regnum
, is_vec
)
1669 sig
= getattr(fields
, name
)
1671 # these are all opcode fields involved in index-selection of CR,
1672 # and need to do "standard" arithmetic. CR[BA+32] for example
1673 # would, if using SelectableInt, only be 5-bit.
1674 if name
not in crlen3
and name
not in crlen5
:
1675 val
= SelectableInt(val
, sig
.width
)
1677 # finally put the field into the namespace
1678 self
.namespace
[name
] = val
1680 self
.namespace
['XER'] = self
.spr
['XER']
1681 self
.namespace
['CA'] = self
.spr
['XER'][XER_bits
['CA']].value
1682 self
.namespace
['CA32'] = self
.spr
['XER'][XER_bits
['CA32']].value
1683 self
.namespace
['OV'] = self
.spr
['XER'][XER_bits
['OV']].value
1684 self
.namespace
['OV32'] = self
.spr
['XER'][XER_bits
['OV32']].value
1685 self
.namespace
['XLEN'] = xlen
1686 self
.namespace
['RESERVE'] = self
.reserve
1687 self
.namespace
['RESERVE_ADDR'] = self
.reserve_addr
1688 self
.namespace
['RESERVE_LENGTH'] = self
.reserve_length
1690 # add some SVSTATE convenience variables
1691 vl
= self
.svstate
.vl
1692 srcstep
= self
.svstate
.srcstep
1693 self
.namespace
['VL'] = vl
1694 self
.namespace
['srcstep'] = srcstep
1696 # take a copy of the CR field value: if non-VLi fail-first fails
1697 # this is because the pseudocode writes *directly* to CR. sigh
1698 self
.cr_backup
= self
.cr
.value
1700 # sv.bc* need some extra fields
1701 if not self
.is_svp64_mode
or not insn_name
.startswith("sv.bc"):
1704 # blegh grab bits manually
1705 mode
= yield self
.dec2
.rm_dec
.rm_in
.mode
1706 # convert to SelectableInt before test
1707 mode
= SelectableInt(mode
, 5)
1708 bc_vlset
= mode
[SVP64MODEb
.BC_VLSET
] != 0
1709 bc_vli
= mode
[SVP64MODEb
.BC_VLI
] != 0
1710 bc_snz
= mode
[SVP64MODEb
.BC_SNZ
] != 0
1711 bc_vsb
= yield self
.dec2
.rm_dec
.bc_vsb
1712 bc_ctrtest
= yield self
.dec2
.rm_dec
.bc_ctrtest
1713 bc_lru
= yield self
.dec2
.rm_dec
.bc_lru
1714 bc_gate
= yield self
.dec2
.rm_dec
.bc_gate
1715 sz
= yield self
.dec2
.rm_dec
.pred_sz
1716 self
.namespace
['mode'] = SelectableInt(mode
, 5)
1717 self
.namespace
['ALL'] = SelectableInt(bc_gate
, 1)
1718 self
.namespace
['VSb'] = SelectableInt(bc_vsb
, 1)
1719 self
.namespace
['LRu'] = SelectableInt(bc_lru
, 1)
1720 self
.namespace
['CTRtest'] = SelectableInt(bc_ctrtest
, 1)
1721 self
.namespace
['VLSET'] = SelectableInt(bc_vlset
, 1)
1722 self
.namespace
['VLI'] = SelectableInt(bc_vli
, 1)
1723 self
.namespace
['sz'] = SelectableInt(sz
, 1)
1724 self
.namespace
['SNZ'] = SelectableInt(bc_snz
, 1)
1726 def get_kludged_op_add_ca_ov(self
, inputs
, inp_ca_ov
):
1727 """ this was not at all necessary to do. this function massively
1728 duplicates - in a laborious and complex fashion - the contents of
1729 the CSV files that were extracted two years ago from microwatt's
1730 source code. A-inversion is the "inv A" column, output inversion
1731 is the "inv out" column, carry-in equal to 0 or 1 or CA is the
1734 all of that information is available in
1735 self.instrs[ins_name].op_fields
1736 where info is usually assigned to self.instrs[ins_name]
1738 https://git.libre-soc.org/?p=openpower-isa.git;a=blob;f=openpower/isatables/minor_31.csv;hb=HEAD
1740 the immediate constants are *also* decoded correctly and placed
1741 usually by DecodeIn2Imm into operand2, as part of power_decoder2.py
1743 def ca(a
, b
, ca_in
, width
):
1744 mask
= (1 << width
) - 1
1745 y
= (a
& mask
) + (b
& mask
) + ca_in
1748 asmcode
= yield self
.dec2
.dec
.op
.asmcode
1749 insn
= insns
.get(asmcode
)
1750 SI
= yield self
.dec2
.dec
.SI
1753 inputs
= [i
.value
for i
in inputs
]
1756 if insn
in ("add", "addo", "addc", "addco"):
1760 elif insn
== "addic" or insn
== "addic.":
1764 elif insn
in ("subf", "subfo", "subfc", "subfco"):
1768 elif insn
== "subfic":
1772 elif insn
== "adde" or insn
== "addeo":
1776 elif insn
== "subfe" or insn
== "subfeo":
1780 elif insn
== "addme" or insn
== "addmeo":
1784 elif insn
== "addze" or insn
== "addzeo":
1788 elif insn
== "subfme" or insn
== "subfmeo":
1792 elif insn
== "subfze" or insn
== "subfzeo":
1796 elif insn
== "addex":
1797 # CA[32] aren't actually written, just generate so we have
1798 # something to return
1799 ca64
= ov64
= ca(inputs
[0], inputs
[1], OV
, 64)
1800 ca32
= ov32
= ca(inputs
[0], inputs
[1], OV
, 32)
1801 return ca64
, ca32
, ov64
, ov32
1802 elif insn
== "neg" or insn
== "nego":
1807 raise NotImplementedError(
1808 "op_add kludge unimplemented instruction: ", asmcode
, insn
)
1810 ca64
= ca(a
, b
, ca_in
, 64)
1811 ca32
= ca(a
, b
, ca_in
, 32)
1812 ov64
= ca64
!= ca(a
, b
, ca_in
, 63)
1813 ov32
= ca32
!= ca(a
, b
, ca_in
, 31)
1814 return ca64
, ca32
, ov64
, ov32
1816 def handle_carry_(self
, inputs
, output
, ca
, ca32
, inp_ca_ov
):
1817 if ca
is not None and ca32
is not None:
1819 op
= yield self
.dec2
.e
.do
.insn_type
1820 if op
== MicrOp
.OP_ADD
.value
and ca
is None and ca32
is None:
1821 retval
= yield from self
.get_kludged_op_add_ca_ov(
1823 ca
, ca32
, ov
, ov32
= retval
1824 asmcode
= yield self
.dec2
.dec
.op
.asmcode
1825 if insns
.get(asmcode
) == 'addex':
1826 # TODO: if 32-bit mode, set ov to ov32
1827 self
.spr
['XER'][XER_bits
['OV']] = ov
1828 self
.spr
['XER'][XER_bits
['OV32']] = ov32
1829 log(f
"write OV/OV32 OV={ov} OV32={ov32}",
1830 kind
=LogType
.InstrInOuts
)
1832 # TODO: if 32-bit mode, set ca to ca32
1833 self
.spr
['XER'][XER_bits
['CA']] = ca
1834 self
.spr
['XER'][XER_bits
['CA32']] = ca32
1835 log(f
"write CA/CA32 CA={ca} CA32={ca32}",
1836 kind
=LogType
.InstrInOuts
)
1838 inv_a
= yield self
.dec2
.e
.do
.invert_in
1840 inputs
[0] = ~inputs
[0]
1842 imm_ok
= yield self
.dec2
.e
.do
.imm_data
.ok
1844 imm
= yield self
.dec2
.e
.do
.imm_data
.data
1845 inputs
.append(SelectableInt(imm
, 64))
1848 log("gt input", x
, output
)
1849 gt
= (gtu(x
, output
))
1852 cy
= 1 if any(gts
) else 0
1854 if ca
is None: # already written
1855 self
.spr
['XER'][XER_bits
['CA']] = cy
1858 # ARGH... different for OP_ADD... *sigh*...
1859 op
= yield self
.dec2
.e
.do
.insn_type
1860 if op
== MicrOp
.OP_ADD
.value
:
1861 res32
= (output
.value
& (1 << 32)) != 0
1862 a32
= (inputs
[0].value
& (1 << 32)) != 0
1863 if len(inputs
) >= 2:
1864 b32
= (inputs
[1].value
& (1 << 32)) != 0
1867 cy32
= res32 ^ a32 ^ b32
1868 log("CA32 ADD", cy32
)
1872 log("input", x
, output
)
1873 log(" x[32:64]", x
, x
[32:64])
1874 log(" o[32:64]", output
, output
[32:64])
1875 gt
= (gtu(x
[32:64], output
[32:64])) == SelectableInt(1, 1)
1877 cy32
= 1 if any(gts
) else 0
1878 log("CA32", cy32
, gts
)
1879 if ca32
is None: # already written
1880 self
.spr
['XER'][XER_bits
['CA32']] = cy32
1882 def handle_overflow(self
, inputs
, output
, div_overflow
, inp_ca_ov
):
1883 op
= yield self
.dec2
.e
.do
.insn_type
1884 if op
== MicrOp
.OP_ADD
.value
:
1885 retval
= yield from self
.get_kludged_op_add_ca_ov(
1887 ca
, ca32
, ov
, ov32
= retval
1888 # TODO: if 32-bit mode, set ov to ov32
1889 self
.spr
['XER'][XER_bits
['OV']] = ov
1890 self
.spr
['XER'][XER_bits
['OV32']] = ov32
1891 self
.spr
['XER'][XER_bits
['SO']] |
= ov
1893 if hasattr(self
.dec2
.e
.do
, "invert_in"):
1894 inv_a
= yield self
.dec2
.e
.do
.invert_in
1896 inputs
[0] = ~inputs
[0]
1898 imm_ok
= yield self
.dec2
.e
.do
.imm_data
.ok
1900 imm
= yield self
.dec2
.e
.do
.imm_data
.data
1901 inputs
.append(SelectableInt(imm
, 64))
1902 log("handle_overflow", inputs
, output
, div_overflow
)
1903 if len(inputs
) < 2 and div_overflow
is None:
1906 # div overflow is different: it's returned by the pseudo-code
1907 # because it's more complex than can be done by analysing the output
1908 if div_overflow
is not None:
1909 ov
, ov32
= div_overflow
, div_overflow
1910 # arithmetic overflow can be done by analysing the input and output
1911 elif len(inputs
) >= 2:
1913 input_sgn
= [exts(x
.value
, x
.bits
) < 0 for x
in inputs
]
1914 output_sgn
= exts(output
.value
, output
.bits
) < 0
1915 ov
= 1 if input_sgn
[0] == input_sgn
[1] and \
1916 output_sgn
!= input_sgn
[0] else 0
1919 input32_sgn
= [exts(x
.value
, 32) < 0 for x
in inputs
]
1920 output32_sgn
= exts(output
.value
, 32) < 0
1921 ov32
= 1 if input32_sgn
[0] == input32_sgn
[1] and \
1922 output32_sgn
!= input32_sgn
[0] else 0
1924 # now update XER OV/OV32/SO
1925 so
= self
.spr
['XER'][XER_bits
['SO']]
1926 new_so
= so | ov
# sticky overflow ORs in old with new
1927 self
.spr
['XER'][XER_bits
['OV']] = ov
1928 self
.spr
['XER'][XER_bits
['OV32']] = ov32
1929 self
.spr
['XER'][XER_bits
['SO']] = new_so
1930 log(" set overflow", ov
, ov32
, so
, new_so
)
1932 def handle_comparison(self
, out
, cr_idx
=0, overflow
=None, no_so
=False):
1933 assert isinstance(out
, SelectableInt
), \
1934 "out zero not a SelectableInt %s" % repr(outputs
)
1935 log("handle_comparison", out
.bits
, hex(out
.value
))
1936 # TODO - XXX *processor* in 32-bit mode
1937 # https://bugs.libre-soc.org/show_bug.cgi?id=424
1939 # o32 = exts(out.value, 32)
1940 # print ("handle_comparison exts 32 bit", hex(o32))
1941 out
= exts(out
.value
, out
.bits
)
1942 log("handle_comparison exts", hex(out
))
1943 # create the three main CR flags, EQ GT LT
1944 zero
= SelectableInt(out
== 0, 1)
1945 positive
= SelectableInt(out
> 0, 1)
1946 negative
= SelectableInt(out
< 0, 1)
1947 # get (or not) XER.SO. for setvl this is important *not* to read SO
1949 SO
= SelectableInt(1, 0)
1951 SO
= self
.spr
['XER'][XER_bits
['SO']]
1952 log("handle_comparison SO", SO
.value
,
1953 "overflow", overflow
,
1955 "+ve", positive
.value
,
1956 "-ve", negative
.value
)
1957 # alternative overflow checking (setvl mainly at the moment)
1958 if overflow
is not None and overflow
== 1:
1959 SO
= SelectableInt(1, 1)
1960 # create the four CR field values and set the required CR field
1961 cr_field
= selectconcat(negative
, positive
, zero
, SO
)
1962 log("handle_comparison cr_field", self
.cr
, cr_idx
, cr_field
)
1963 self
.crl
[cr_idx
].eq(cr_field
)
1966 def set_pc(self
, pc_val
):
1967 self
.namespace
['NIA'] = SelectableInt(pc_val
, 64)
1968 self
.pc
.update(self
.namespace
, self
.is_svp64_mode
)
1970 def get_next_insn(self
):
1971 """check instruction
1974 pc
= self
.pc
.CIA
.value
1977 ins
= self
.imem
.ld(pc
, 4, False, True, instr_fetch
=True)
1979 raise KeyError("no instruction at 0x%x" % pc
)
1982 def setup_one(self
):
1983 """set up one instruction
1985 pc
, insn
= self
.get_next_insn()
1986 yield from self
.setup_next_insn(pc
, insn
)
1988 # cache since it's really slow to construct
1989 __PREFIX_CACHE
= SVP64Instruction
.Prefix(SelectableInt(value
=0, bits
=32))
1991 def __decode_prefix(self
, opcode
):
1992 pfx
= self
.__PREFIX
_CACHE
1993 pfx
.storage
.eq(opcode
)
1996 def setup_next_insn(self
, pc
, ins
):
1997 """set up next instruction
2000 log("setup: 0x%x 0x%x %s" % (pc
, ins
& 0xffffffff, bin(ins
)))
2001 log("CIA NIA", self
.respect_pc
, self
.pc
.CIA
.value
, self
.pc
.NIA
.value
)
2003 yield self
.dec2
.sv_rm
.eq(0)
2004 yield self
.dec2
.dec
.raw_opcode_in
.eq(ins
& 0xffffffff)
2005 yield self
.dec2
.dec
.bigendian
.eq(self
.bigendian
)
2006 yield self
.dec2
.state
.msr
.eq(self
.msr
.value
)
2007 yield self
.dec2
.state
.pc
.eq(pc
)
2008 if self
.svstate
is not None:
2009 yield self
.dec2
.state
.svstate
.eq(self
.svstate
.value
)
2011 # SVP64. first, check if the opcode is EXT001, and SVP64 id bits set
2013 opcode
= yield self
.dec2
.dec
.opcode_in
2014 opcode
= SelectableInt(value
=opcode
, bits
=32)
2015 pfx
= self
.__decode
_prefix
(opcode
)
2016 log("prefix test: opcode:", pfx
.PO
, bin(pfx
.PO
), pfx
.id)
2017 self
.is_svp64_mode
= bool((pfx
.PO
== 0b000001) and (pfx
.id == 0b11))
2018 self
.pc
.update_nia(self
.is_svp64_mode
)
2020 yield self
.dec2
.is_svp64_mode
.eq(self
.is_svp64_mode
)
2021 self
.namespace
['NIA'] = self
.pc
.NIA
2022 self
.namespace
['SVSTATE'] = self
.svstate
2023 if not self
.is_svp64_mode
:
2026 # in SVP64 mode. decode/print out svp64 prefix, get v3.0B instruction
2027 log("svp64.rm", bin(pfx
.rm
))
2028 log(" svstate.vl", self
.svstate
.vl
)
2029 log(" svstate.mvl", self
.svstate
.maxvl
)
2030 ins
= self
.imem
.ld(pc
+4, 4, False, True, instr_fetch
=True)
2031 log(" svsetup: 0x%x 0x%x %s" % (pc
+4, ins
& 0xffffffff, bin(ins
)))
2032 yield self
.dec2
.dec
.raw_opcode_in
.eq(ins
& 0xffffffff) # v3.0B suffix
2033 yield self
.dec2
.sv_rm
.eq(int(pfx
.rm
)) # svp64 prefix
2036 def execute_one(self
):
2037 """execute one instruction
2039 # get the disassembly code for this instruction
2040 if not self
.disassembly
:
2041 code
= yield from self
.get_assembly_name()
2044 if self
.is_svp64_mode
:
2045 offs
, dbg
= 4, "svp64 "
2046 code
= self
.disassembly
[self
._pc
+offs
]
2047 log(" %s sim-execute" % dbg
, hex(self
._pc
), code
)
2048 opname
= code
.split(' ')[0]
2050 asmop
= yield from self
.call(opname
) # execute the instruction
2051 except MemException
as e
: # check for memory errors
2052 if e
.args
[0] == 'unaligned': # alignment error
2053 # run a Trap but set DAR first
2054 print("memory unaligned exception, DAR", e
.dar
, repr(e
))
2055 self
.spr
['DAR'] = SelectableInt(e
.dar
, 64)
2056 self
.call_trap(0x600, PIb
.PRIV
) # 0x600, privileged
2058 elif e
.args
[0] == 'invalid': # invalid
2059 # run a Trap but set DAR first
2060 log("RADIX MMU memory invalid error, mode %s" % e
.mode
)
2061 if e
.mode
== 'EXECUTE':
2062 # XXX TODO: must set a few bits in SRR1,
2063 # see microwatt loadstore1.vhdl
2064 # if m_in.segerr = '0' then
2065 # v.srr1(47 - 33) := m_in.invalid;
2066 # v.srr1(47 - 35) := m_in.perm_error; -- noexec fault
2067 # v.srr1(47 - 44) := m_in.badtree;
2068 # v.srr1(47 - 45) := m_in.rc_error;
2069 # v.intr_vec := 16#400#;
2071 # v.intr_vec := 16#480#;
2072 self
.call_trap(0x400, PIb
.PRIV
) # 0x400, privileged
2074 self
.call_trap(0x300, PIb
.PRIV
) # 0x300, privileged
2076 # not supported yet:
2077 raise e
# ... re-raise
2079 # append to the trace log file
2080 self
.trace(" # %s %s\n" % (asmop
, code
))
2082 log("gprs after insn %s - code" % asmop
, code
)
2085 for i
in range(len(self
.crl
)):
2086 crs
.append(bin(self
.crl
[i
].asint()))
2087 log("crs", " ".join(crs
))
2088 log("vl,maxvl", self
.svstate
.vl
, self
.svstate
.maxvl
)
2090 # don't use this except in special circumstances
2091 if not self
.respect_pc
:
2094 log("execute one, CIA NIA", hex(self
.pc
.CIA
.value
),
2095 hex(self
.pc
.NIA
.value
))
2097 def get_assembly_name(self
):
2098 # TODO, asmregs is from the spec, e.g. add RT,RA,RB
2099 # see http://bugs.libre-riscv.org/show_bug.cgi?id=282
2100 dec_insn
= yield self
.dec2
.e
.do
.insn
2101 insn_1_11
= yield self
.dec2
.e
.do
.insn
[1:11]
2102 asmcode
= yield self
.dec2
.dec
.op
.asmcode
2103 int_op
= yield self
.dec2
.dec
.op
.internal_op
2104 log("get assembly name asmcode", asmcode
, int_op
,
2105 hex(dec_insn
), bin(insn_1_11
))
2106 asmop
= insns
.get(asmcode
, None)
2108 # sigh reconstruct the assembly instruction name
2109 if hasattr(self
.dec2
.e
.do
, "oe"):
2110 ov_en
= yield self
.dec2
.e
.do
.oe
.oe
2111 ov_ok
= yield self
.dec2
.e
.do
.oe
.ok
2115 if hasattr(self
.dec2
.e
.do
, "rc"):
2116 rc_en
= yield self
.dec2
.e
.do
.rc
.rc
2117 rc_ok
= yield self
.dec2
.e
.do
.rc
.ok
2121 # annoying: ignore rc_ok if RC1 is set (for creating *assembly name*)
2122 RC1
= yield self
.dec2
.rm_dec
.RC1
2126 # grrrr have to special-case MUL op (see DecodeOE)
2127 log("ov %d en %d rc %d en %d op %d" %
2128 (ov_ok
, ov_en
, rc_ok
, rc_en
, int_op
))
2129 if int_op
in [MicrOp
.OP_MUL_H64
.value
, MicrOp
.OP_MUL_H32
.value
]:
2134 if not asmop
.endswith("."): # don't add "." to "andis."
2137 if hasattr(self
.dec2
.e
.do
, "lk"):
2138 lk
= yield self
.dec2
.e
.do
.lk
2141 log("int_op", int_op
)
2142 if int_op
in [MicrOp
.OP_B
.value
, MicrOp
.OP_BC
.value
]:
2143 AA
= yield self
.dec2
.dec
.fields
.FormI
.AA
[0:-1]
2147 spr_msb
= yield from self
.get_spr_msb()
2148 if int_op
== MicrOp
.OP_MFCR
.value
:
2153 # XXX TODO: for whatever weird reason this doesn't work
2154 # https://bugs.libre-soc.org/show_bug.cgi?id=390
2155 if int_op
== MicrOp
.OP_MTCRF
.value
:
2162 def reset_remaps(self
):
2163 self
.remap_loopends
= [0] * 4
2164 self
.remap_idxs
= [0, 1, 2, 3]
2166 def get_remap_indices(self
):
2167 """WARNING, this function stores remap_idxs and remap_loopends
2168 in the class for later use. this to avoid problems with yield
2170 # go through all iterators in lock-step, advance to next remap_idx
2171 srcstep
, dststep
, ssubstep
, dsubstep
= self
.get_src_dststeps()
2172 # get four SVSHAPEs. here we are hard-coding
2174 SVSHAPE0
= self
.spr
['SVSHAPE0']
2175 SVSHAPE1
= self
.spr
['SVSHAPE1']
2176 SVSHAPE2
= self
.spr
['SVSHAPE2']
2177 SVSHAPE3
= self
.spr
['SVSHAPE3']
2178 # set up the iterators
2179 remaps
= [(SVSHAPE0
, SVSHAPE0
.get_iterator()),
2180 (SVSHAPE1
, SVSHAPE1
.get_iterator()),
2181 (SVSHAPE2
, SVSHAPE2
.get_iterator()),
2182 (SVSHAPE3
, SVSHAPE3
.get_iterator()),
2186 for i
, (shape
, remap
) in enumerate(remaps
):
2187 # zero is "disabled"
2188 if shape
.value
== 0x0:
2189 self
.remap_idxs
[i
] = 0
2190 # pick src or dststep depending on reg num (0-2=in, 3-4=out)
2191 step
= dststep
if (i
in [3, 4]) else srcstep
2192 # this is terrible. O(N^2) looking for the match. but hey.
2193 for idx
, (remap_idx
, loopends
) in enumerate(remap
):
2196 self
.remap_idxs
[i
] = remap_idx
2197 self
.remap_loopends
[i
] = loopends
2198 dbg
.append((i
, step
, remap_idx
, loopends
))
2199 for (i
, step
, remap_idx
, loopends
) in dbg
:
2200 log("SVSHAPE %d idx, end" % i
, step
, remap_idx
, bin(loopends
))
2203 def get_spr_msb(self
):
2204 dec_insn
= yield self
.dec2
.e
.do
.insn
2205 return dec_insn
& (1 << 20) != 0 # sigh - XFF.spr[-1]?
2207 def call(self
, name
, syscall_emu_active
=False):
2208 """call(opcode) - the primary execution point for instructions
2210 self
.last_st_addr
= None # reset the last known store address
2211 self
.last_ld_addr
= None # etc.
2213 ins_name
= name
.strip() # remove spaces if not already done so
2215 log("halted - not executing", ins_name
)
2218 # TODO, asmregs is from the spec, e.g. add RT,RA,RB
2219 # see http://bugs.libre-riscv.org/show_bug.cgi?id=282
2220 asmop
= yield from self
.get_assembly_name()
2221 log("call", ins_name
, asmop
, kind
=LogType
.InstrInOuts
)
2223 # sv.setvl is *not* a loop-function. sigh
2224 log("is_svp64_mode", self
.is_svp64_mode
, asmop
)
2227 int_op
= yield self
.dec2
.dec
.op
.internal_op
2228 spr_msb
= yield from self
.get_spr_msb()
2230 instr_is_privileged
= False
2231 if int_op
in [MicrOp
.OP_ATTN
.value
,
2232 MicrOp
.OP_MFMSR
.value
,
2233 MicrOp
.OP_MTMSR
.value
,
2234 MicrOp
.OP_MTMSRD
.value
,
2236 MicrOp
.OP_RFID
.value
]:
2237 instr_is_privileged
= True
2238 if int_op
in [MicrOp
.OP_MFSPR
.value
,
2239 MicrOp
.OP_MTSPR
.value
] and spr_msb
:
2240 instr_is_privileged
= True
2242 # check MSR priv bit and whether op is privileged: if so, throw trap
2243 PR
= self
.msr
[MSRb
.PR
]
2244 log("is priv", instr_is_privileged
, hex(self
.msr
.value
), PR
)
2245 if instr_is_privileged
and PR
== 1:
2246 self
.call_trap(0x700, PIb
.PRIV
)
2249 # check halted condition
2250 if ins_name
== 'attn':
2254 # User mode system call emulation consists of several steps:
2255 # 1. Detect whether instruction is sc or scv.
2256 # 2. Call the HDL implementation which invokes trap.
2257 # 3. Reroute the guest system call to host system call.
2258 # 4. Force return from the interrupt as if we had guest OS.
2259 # FIXME: enable PPC_FEATURE2_SCV in mem.py DEFAULT_AT_HWCAP2 when
2260 # scv emulation works.
2261 if ((asmop
in ("sc", "scv")) and
2262 (self
.syscall
is not None) and
2263 not syscall_emu_active
):
2264 # Memoize PC and trigger an interrupt
2266 pc
= self
.pc
.CIA
.value
2269 yield from self
.call(asmop
, syscall_emu_active
=True)
2271 # Reroute the syscall to host OS
2272 identifier
= self
.gpr(0)
2273 arguments
= map(self
.gpr
, range(3, 9))
2274 result
= self
.syscall(identifier
, *arguments
)
2275 self
.gpr
.write(3, result
, False, self
.namespace
["XLEN"])
2277 # Return from interrupt
2278 yield from self
.call("rfid", syscall_emu_active
=True)
2280 elif ((name
in ("rfid", "hrfid")) and syscall_emu_active
):
2283 # check illegal instruction
2285 if ins_name
not in ['mtcrf', 'mtocrf']:
2286 illegal
= ins_name
!= asmop
2288 # list of instructions not being supported by binutils (.long)
2289 dotstrp
= asmop
[:-1] if asmop
[-1] == '.' else asmop
2290 if dotstrp
in [*FPTRANS_INSNS
,
2292 'ffmadds', 'fdmadds', 'ffadds',
2294 "brh", "brw", "brd",
2295 'setvl', 'svindex', 'svremap', 'svstep',
2296 'svshape', 'svshape2',
2297 'ternlogi', 'bmask', 'cprop', 'gbbd',
2298 'absdu', 'absds', 'absdacs', 'absdacu', 'avgadd',
2299 'fmvis', 'fishmv', 'pcdec', "maddedu", "divmod2du",
2300 "dsld", "dsrd", "maddedus",
2301 "sadd", "saddw", "sadduw",
2306 "maddsubrs", "maddrs", "msubrs",
2307 "cfuged", "cntlzdm", "cnttzdm", "pdepd", "pextd",
2308 "setbc", "setbcr", "setnbc", "setnbcr",
2313 # match against instructions treated as nop, see nop below
2314 if asmop
.startswith("dcbt"):
2318 # branch-conditional redirects to sv.bc
2319 if asmop
.startswith('bc') and self
.is_svp64_mode
:
2320 ins_name
= 'sv.%s' % ins_name
2322 # ld-immediate-with-pi mode redirects to ld-with-postinc
2323 ldst_imm_postinc
= False
2324 if 'u' in ins_name
and self
.is_svp64_mode
:
2325 ldst_pi
= yield self
.dec2
.rm_dec
.ldst_postinc
2327 ins_name
= ins_name
.replace("u", "up")
2328 ldst_imm_postinc
= True
2329 log(" enable ld/st postinc", ins_name
)
2331 log(" post-processed name", dotstrp
, ins_name
, asmop
)
2333 # illegal instructions call TRAP at 0x700
2335 print("illegal", ins_name
, asmop
)
2336 self
.call_trap(0x700, PIb
.ILLEG
)
2337 print("name %s != %s - calling ILLEGAL trap, PC: %x" %
2338 (ins_name
, asmop
, self
.pc
.CIA
.value
))
2341 # this is for setvl "Vertical" mode: if set true,
2342 # srcstep/dststep is explicitly advanced. mode says which SVSTATE to
2343 # test for Rc=1 end condition. 3 bits of all 3 loops are put into CR0
2344 self
.allow_next_step_inc
= False
2345 self
.svstate_next_mode
= 0
2347 # nop has to be supported, we could let the actual op calculate
2348 # but PowerDecoder has a pattern for nop
2349 if ins_name
== 'nop':
2350 self
.update_pc_next()
2353 # get elwidths, defaults to 64
2357 if self
.is_svp64_mode
:
2358 ew_src
= yield self
.dec2
.rm_dec
.ew_src
2359 ew_dst
= yield self
.dec2
.rm_dec
.ew_dst
2360 ew_src
= 8 << (3-int(ew_src
)) # convert to bitlength
2361 ew_dst
= 8 << (3-int(ew_dst
)) # convert to bitlength
2362 xlen
= max(ew_src
, ew_dst
)
2363 log("elwidth", ew_src
, ew_dst
)
2364 log("XLEN:", self
.is_svp64_mode
, xlen
)
2366 # look up instruction in ISA.instrs, prepare namespace
2367 if ins_name
== 'pcdec': # grrrr yes there are others ("stbcx." etc.)
2368 info
= self
.instrs
[ins_name
+"."]
2369 elif asmop
[-1] == '.' and asmop
in self
.instrs
:
2370 info
= self
.instrs
[asmop
]
2372 info
= self
.instrs
[ins_name
]
2373 yield from self
.prep_namespace(ins_name
, info
.form
, info
.op_fields
,
2376 # dict retains order
2377 inputs
= dict.fromkeys(create_full_args(
2378 read_regs
=info
.read_regs
, special_regs
=info
.special_regs
,
2379 uninit_regs
=info
.uninit_regs
, write_regs
=info
.write_regs
))
2381 # preserve order of register names
2382 write_without_special_regs
= OrderedSet(info
.write_regs
)
2383 write_without_special_regs
-= OrderedSet(info
.special_regs
)
2384 input_names
= create_args([
2385 *info
.read_regs
, *info
.uninit_regs
, *write_without_special_regs
])
2386 log("input names", input_names
)
2388 # get SVP64 entry for the current instruction
2389 sv_rm
= self
.svp64rm
.instrs
.get(ins_name
)
2390 if sv_rm
is not None:
2391 dest_cr
, src_cr
, src_byname
, dest_byname
= decode_extra(sv_rm
)
2393 dest_cr
, src_cr
, src_byname
, dest_byname
= False, False, {}, {}
2394 log("sv rm", sv_rm
, dest_cr
, src_cr
, src_byname
, dest_byname
)
2396 # see if srcstep/dststep need skipping over masked-out predicate bits
2397 # svstep also needs advancement because it calls SVSTATE_NEXT.
2398 # bit the remaps get computed just after pre_inc moves them on
2399 # with remap_set_steps substituting for PowerDecider2 not doing it,
2400 # and SVSTATE_NEXT not being able to.use yield, the preinc on
2401 # svstep is necessary for now.
2403 if (self
.is_svp64_mode
or ins_name
in ['svstep']):
2404 yield from self
.svstate_pre_inc()
2405 if self
.is_svp64_mode
:
2406 pre
= yield from self
.update_new_svstate_steps()
2408 self
.svp64_reset_loop()
2410 self
.update_pc_next()
2412 srcstep
, dststep
, ssubstep
, dsubstep
= self
.get_src_dststeps()
2413 pred_dst_zero
= self
.pred_dst_zero
2414 pred_src_zero
= self
.pred_src_zero
2415 vl
= self
.svstate
.vl
2416 subvl
= yield self
.dec2
.rm_dec
.rm_in
.subvl
2418 # VL=0 in SVP64 mode means "do nothing: skip instruction"
2419 if self
.is_svp64_mode
and vl
== 0:
2420 self
.pc
.update(self
.namespace
, self
.is_svp64_mode
)
2421 log("SVP64: VL=0, end of call", self
.namespace
['CIA'],
2422 self
.namespace
['NIA'], kind
=LogType
.InstrInOuts
)
2425 # for when SVREMAP is active, using pre-arranged schedule.
2426 # note: modifying PowerDecoder2 needs to "settle"
2427 remap_en
= self
.svstate
.SVme
2428 persist
= self
.svstate
.RMpst
2429 active
= (persist
or self
.last_op_svshape
) and remap_en
!= 0
2430 if self
.is_svp64_mode
:
2431 yield self
.dec2
.remap_active
.eq(remap_en
if active
else 0)
2433 if persist
or self
.last_op_svshape
:
2434 remaps
= self
.get_remap_indices()
2435 if self
.is_svp64_mode
and (persist
or self
.last_op_svshape
):
2436 yield from self
.remap_set_steps(remaps
)
2437 # after that, settle down (combinatorial) to let Vector reg numbers
2438 # work themselves out
2440 if self
.is_svp64_mode
:
2441 remap_active
= yield self
.dec2
.remap_active
2443 remap_active
= False
2444 log("remap active", bin(remap_active
), self
.is_svp64_mode
)
2446 # LDST does *not* allow elwidth overrides on RA (Effective Address).
2447 # this has to be detected. XXX TODO: RB for ldst-idx *may* need
2448 # conversion (to 64-bit) also.
2449 # see write reg this *HAS* to also override XLEN to 64 on LDST/Update
2450 sv_mode
= yield self
.dec2
.rm_dec
.sv_mode
2451 is_ldst
= (sv_mode
in [SVMode
.LDST_IDX
.value
, SVMode
.LDST_IMM
.value
] \
2452 and self
.is_svp64_mode
)
2453 log("is_ldst", sv_mode
, is_ldst
)
2455 # main input registers (RT, RA ...)
2456 for name
in input_names
:
2457 if name
== "overflow":
2458 inputs
[name
] = SelectableInt(0, 1)
2459 elif name
.startswith("RESERVE"):
2460 inputs
[name
] = getattr(self
, name
)
2461 elif name
== "FPSCR":
2462 inputs
[name
] = self
.FPSCR
2463 elif name
in ("CA", "CA32", "OV", "OV32"):
2464 inputs
[name
] = self
.spr
['XER'][XER_bits
[name
]]
2466 inputs
[name
] = self
.crl
[0]
2467 elif name
in spr_byname
:
2468 inputs
[name
] = self
.spr
[name
]
2469 elif is_ldst
and name
== 'RA':
2470 regval
= (yield from self
.get_input(name
, ew_src
, 64))
2471 log("EA (RA) regval name", name
, regval
)
2472 inputs
[name
] = regval
2474 regval
= (yield from self
.get_input(name
, ew_src
, xlen
))
2475 log("regval name", name
, regval
)
2476 inputs
[name
] = regval
2478 # arrrrgh, awful hack, to get _RT into namespace
2479 if ins_name
in ['setvl', 'svstep']:
2481 RT
= yield self
.dec2
.dec
.RT
2482 self
.namespace
[regname
] = SelectableInt(RT
, 5)
2484 self
.namespace
["RT"] = SelectableInt(0, 5)
2485 regnum
, is_vec
= yield from get_idx_out(self
.dec2
, "RT")
2486 log('hack input reg %s %s' % (name
, str(regnum
)), is_vec
)
2488 # in SVP64 mode for LD/ST work out immediate
2489 # XXX TODO: replace_ds for DS-Form rather than D-Form.
2490 # use info.form to detect
2491 if self
.is_svp64_mode
and not ldst_imm_postinc
:
2492 yield from self
.check_replace_d(info
, remap_active
)
2494 # "special" registers
2495 for special
in info
.special_regs
:
2496 if special
in special_sprs
:
2497 inputs
[special
] = self
.spr
[special
]
2499 inputs
[special
] = self
.namespace
[special
]
2501 # clear trap (trap) NIA
2502 self
.trap_nia
= None
2504 # check if this was an sv.bc* and create an indicator that
2505 # this is the last check to be made as a loop. combined with
2506 # the ALL/ANY mode we can early-exit. note that BI (to test)
2507 # is an input so there is no termination if BI is scalar
2508 # (because early-termination is for *output* scalars)
2509 if self
.is_svp64_mode
and ins_name
.startswith("sv.bc"):
2510 end_loop
= srcstep
== vl
-1 or dststep
== vl
-1
2511 self
.namespace
['end_loop'] = SelectableInt(end_loop
, 1)
2513 inp_ca_ov
= (self
.spr
['XER'][XER_bits
['CA']].value
,
2514 self
.spr
['XER'][XER_bits
['OV']].value
)
2516 for k
, v
in inputs
.items():
2518 v
= SelectableInt(0, self
.XLEN
)
2519 # prevent pseudo-code from modifying input registers
2520 v
= copy_assign_rhs(v
)
2521 if isinstance(v
, SelectableInt
):
2525 # execute actual instruction here (finally)
2526 log("inputs", inputs
)
2527 inputs
= list(inputs
.values())
2528 results
= info
.func(self
, *inputs
)
2529 output_names
= create_args(info
.write_regs
)
2531 # record .ok before anything after the pseudo-code can modify it
2533 for out
, n
in zip(results
or [], output_names
):
2536 if isinstance(out
, SelectableInt
):
2538 log("results", outs
)
2539 log("results ok", outs_ok
)
2541 # "inject" decorator takes namespace from function locals: we need to
2542 # overwrite NIA being overwritten (sigh)
2543 if self
.trap_nia
is not None:
2544 self
.namespace
['NIA'] = self
.trap_nia
2546 log("after func", self
.namespace
['CIA'], self
.namespace
['NIA'])
2548 # check if op was a LD/ST so that debugging can check the
2550 if int_op
in [MicrOp
.OP_STORE
.value
,
2552 self
.last_st_addr
= self
.mem
.last_st_addr
2553 if int_op
in [MicrOp
.OP_LOAD
.value
,
2555 self
.last_ld_addr
= self
.mem
.last_ld_addr
2556 log("op", int_op
, MicrOp
.OP_STORE
.value
, MicrOp
.OP_LOAD
.value
,
2557 self
.last_st_addr
, self
.last_ld_addr
)
2559 # detect if CA/CA32 already in outputs (sra*, basically)
2561 ca32
= outs
.get("CA32")
2563 log("carry already done?", ca
, ca32
, output_names
)
2564 # soc test_pipe_caller tests don't have output_carry
2565 has_output_carry
= hasattr(self
.dec2
.e
.do
, "output_carry")
2566 carry_en
= has_output_carry
and (yield self
.dec2
.e
.do
.output_carry
)
2568 yield from self
.handle_carry_(
2569 inputs
, results
[0], ca
, ca32
, inp_ca_ov
=inp_ca_ov
)
2571 # get output named "overflow" and "CR0"
2572 overflow
= outs
.get('overflow')
2573 cr0
= outs
.get('CR0')
2574 cr1
= outs
.get('CR1')
2576 # soc test_pipe_caller tests don't have oe
2577 has_oe
= hasattr(self
.dec2
.e
.do
, "oe")
2578 # yeah just no. not in parallel processing
2579 if has_oe
and not self
.is_svp64_mode
:
2580 # detect if overflow was in return result
2581 ov_en
= yield self
.dec2
.e
.do
.oe
.oe
2582 ov_ok
= yield self
.dec2
.e
.do
.oe
.ok
2583 log("internal overflow", ins_name
, overflow
, "en?", ov_en
, ov_ok
)
2585 yield from self
.handle_overflow(
2586 inputs
, results
[0], overflow
, inp_ca_ov
=inp_ca_ov
)
2588 # only do SVP64 dest predicated Rc=1 if dest-pred is not enabled
2590 if not self
.is_svp64_mode
or not pred_dst_zero
:
2591 if hasattr(self
.dec2
.e
.do
, "rc"):
2592 rc_en
= yield self
.dec2
.e
.do
.rc
.rc
2593 # don't do Rc=1 for svstep it is handled explicitly.
2594 # XXX TODO: now that CR0 is supported, sort out svstep's pseudocode
2595 # to write directly to CR0 instead of in ISACaller. hooyahh.
2596 if rc_en
and ins_name
not in ['svstep']:
2597 if outs_ok
.get('FPSCR', False):
2598 FPSCR
= outs
['FPSCR']
2601 yield from self
.do_rc_ov(
2602 ins_name
, results
[0], overflow
, cr0
, cr1
, FPSCR
)
2605 ffirst_hit
= False, False
2606 if self
.is_svp64_mode
:
2607 sv_mode
= yield self
.dec2
.rm_dec
.sv_mode
2608 is_cr
= sv_mode
== SVMode
.CROP
.value
2609 chk
= rc_en
or is_cr
2610 if outs_ok
.get('CR', False):
2611 # early write so check_ffirst can see value
2612 self
.namespace
['CR'].eq(outs
['CR'])
2613 ffirst_hit
= (yield from self
.check_ffirst(info
, chk
, srcstep
))
2615 # any modified return results?
2616 yield from self
.do_outregs(
2617 info
, outs
, carry_en
, ffirst_hit
, ew_dst
, outs_ok
)
2619 # check if a FP Exception occurred. TODO for DD-FFirst, check VLi
2620 # and raise the exception *after* if VLi=1 but if VLi=0 then
2621 # truncate and make the exception "disappear".
2622 if self
.FPSCR
.FEX
and (self
.msr
[MSRb
.FE0
] or self
.msr
[MSRb
.FE1
]):
2623 self
.call_trap(0x700, PIb
.FP
)
2626 yield from self
.do_nia(asmop
, ins_name
, rc_en
, ffirst_hit
)
2629 def check_ffirst(self
, info
, rc_en
, srcstep
):
2630 """fail-first mode: checks a bit of Rc Vector, truncates VL
2632 rm_mode
= yield self
.dec2
.rm_dec
.mode
2633 ff_inv
= yield self
.dec2
.rm_dec
.inv
2634 cr_bit
= yield self
.dec2
.rm_dec
.cr_sel
2635 RC1
= yield self
.dec2
.rm_dec
.RC1
2636 vli_
= yield self
.dec2
.rm_dec
.vli
# VL inclusive if truncated
2637 log(" ff rm_mode", rc_en
, rm_mode
, SVP64RMMode
.FFIRST
.value
)
2641 log(" cr_bit", cr_bit
)
2642 log(" rc_en", rc_en
)
2643 ffirst
= yield from is_ffirst_mode(self
.dec2
)
2644 if not rc_en
or not ffirst
:
2646 # get the CR vevtor, do BO-test
2648 log("asmregs", info
.asmregs
[0], info
.write_regs
)
2649 if 'CR' in info
.write_regs
and 'BF' in info
.asmregs
[0]:
2651 regnum
, is_vec
= yield from get_cr_out(self
.dec2
, crf
)
2652 crtest
= self
.crl
[regnum
]
2653 ffirst_hit
= crtest
[cr_bit
] != ff_inv
2654 log("cr test", crf
, regnum
, int(crtest
), crtest
, cr_bit
, ff_inv
)
2655 log("cr test?", ffirst_hit
)
2658 # Fail-first activated, truncate VL
2659 vli
= SelectableInt(int(vli_
), 7)
2660 self
.svstate
.vl
= srcstep
+ vli
2661 yield self
.dec2
.state
.svstate
.eq(self
.svstate
.value
)
2662 yield Settle() # let decoder update
2665 def do_rc_ov(self
, ins_name
, result
, overflow
, cr0
, cr1
, FPSCR
):
2666 cr_out
= yield self
.dec2
.op
.cr_out
2667 if cr_out
== CROutSel
.CR1
.value
:
2671 regnum
, is_vec
= yield from get_cr_out(self
.dec2
, rc_reg
)
2672 # hang on... for `setvl` actually you want to test SVSTATE.VL
2673 is_setvl
= ins_name
in ('svstep', 'setvl')
2675 result
= SelectableInt(result
.vl
, 64)
2677 # overflow = None # do not override overflow except in setvl
2681 cr1
= int(FPSCR
.FX
) << 3
2682 cr1 |
= int(FPSCR
.FEX
) << 2
2683 cr1 |
= int(FPSCR
.VX
) << 1
2684 cr1 |
= int(FPSCR
.OX
)
2685 log("default fp cr1", cr1
)
2687 log("explicit cr1", cr1
)
2688 self
.crl
[regnum
].eq(cr1
)
2690 # if there was not an explicit CR0 in the pseudocode,
2692 c
= self
.handle_comparison(result
, regnum
, overflow
, no_so
=is_setvl
)
2693 log("implicit cr0 %d" % regnum
, c
)
2695 # otherwise we just blat CR0 into the required regnum
2696 log("explicit cr0 %d" % regnum
, cr0
)
2697 self
.crl
[regnum
].eq(cr0
)
2699 def do_outregs(self
, info
, outs
, ca_en
, ffirst_hit
, ew_dst
, outs_ok
):
2700 ffirst_hit
, vli
= ffirst_hit
2701 # write out any regs for this instruction, but only if fail-first is ok
2702 # XXX TODO: allow CR-vector to be written out even if ffirst fails
2703 if not ffirst_hit
or vli
:
2704 for name
, output
in outs
.items():
2705 if not outs_ok
[name
]:
2706 log("skipping writing output with .ok=False", name
, output
)
2708 yield from self
.check_write(info
, name
, output
, ca_en
, ew_dst
)
2709 # restore the CR value on non-VLI failfirst (from sv.cmp and others
2710 # which write directly to CR in the pseudocode (gah, what a mess)
2711 # if ffirst_hit and not vli:
2712 # self.cr.value = self.cr_backup
2714 def do_nia(self
, asmop
, ins_name
, rc_en
, ffirst_hit
):
2715 ffirst_hit
, vli
= ffirst_hit
2717 self
.svp64_reset_loop()
2720 # check advancement of src/dst/sub-steps and if PC needs updating
2721 nia_update
= (yield from self
.check_step_increment(
2722 rc_en
, asmop
, ins_name
))
2724 self
.update_pc_next()
2726 def check_replace_d(self
, info
, remap_active
):
2727 replace_d
= False # update / replace constant in pseudocode
2728 ldstmode
= yield self
.dec2
.rm_dec
.ldstmode
2729 vl
= self
.svstate
.vl
2730 subvl
= yield self
.dec2
.rm_dec
.rm_in
.subvl
2731 srcstep
, dststep
= self
.new_srcstep
, self
.new_dststep
2732 ssubstep
, dsubstep
= self
.new_ssubstep
, self
.new_dsubstep
2733 if info
.form
== 'DS':
2734 # DS-Form, multiply by 4 then knock 2 bits off after
2735 imm
= yield self
.dec2
.dec
.fields
.FormDS
.DS
[0:14] * 4
2737 imm
= yield self
.dec2
.dec
.fields
.FormD
.D
[0:16]
2738 imm
= exts(imm
, 16) # sign-extend to integer
2739 # get the right step. LD is from srcstep, ST is dststep
2740 op
= yield self
.dec2
.e
.do
.insn_type
2742 if op
== MicrOp
.OP_LOAD
.value
:
2744 offsmul
= yield self
.dec2
.in1_step
2745 log("D-field REMAP src", imm
, offsmul
, ldstmode
)
2747 offsmul
= (srcstep
* (subvl
+1)) + ssubstep
2748 log("D-field src", imm
, offsmul
, ldstmode
)
2749 elif op
== MicrOp
.OP_STORE
.value
:
2750 # XXX NOTE! no bit-reversed STORE! this should not ever be used
2751 offsmul
= (dststep
* (subvl
+1)) + dsubstep
2752 log("D-field dst", imm
, offsmul
, ldstmode
)
2753 # Unit-Strided LD/ST adds offset*width to immediate
2754 if ldstmode
== SVP64LDSTmode
.UNITSTRIDE
.value
:
2755 ldst_len
= yield self
.dec2
.e
.do
.data_len
2756 imm
= SelectableInt(imm
+ offsmul
* ldst_len
, 32)
2758 # Element-strided multiplies the immediate by element step
2759 elif ldstmode
== SVP64LDSTmode
.ELSTRIDE
.value
:
2760 imm
= SelectableInt(imm
* offsmul
, 32)
2763 ldst_ra_vec
= yield self
.dec2
.rm_dec
.ldst_ra_vec
2764 ldst_imz_in
= yield self
.dec2
.rm_dec
.ldst_imz_in
2765 log("LDSTmode", SVP64LDSTmode(ldstmode
),
2766 offsmul
, imm
, ldst_ra_vec
, ldst_imz_in
)
2767 # new replacement D... errr.. DS
2769 if info
.form
== 'DS':
2770 # TODO: assert 2 LSBs are zero?
2771 log("DS-Form, TODO, assert 2 LSBs zero?", bin(imm
.value
))
2772 imm
.value
= imm
.value
>> 2
2773 self
.namespace
['DS'] = imm
2775 self
.namespace
['D'] = imm
2777 def get_input(self
, name
, ew_src
, xlen
):
2778 # using PowerDecoder2, first, find the decoder index.
2779 # (mapping name RA RB RC RS to in1, in2, in3)
2780 regnum
, is_vec
= yield from get_idx_in(self
.dec2
, name
, True)
2782 # doing this is not part of svp64, it's because output
2783 # registers, to be modified, need to be in the namespace.
2784 regnum
, is_vec
= yield from get_idx_out(self
.dec2
, name
, True)
2786 regnum
, is_vec
= yield from get_idx_out2(self
.dec2
, name
, True)
2788 if isinstance(regnum
, tuple):
2789 (regnum
, base
, offs
) = regnum
2791 base
, offs
= regnum
, 0 # temporary HACK
2793 # in case getting the register number is needed, _RA, _RB
2794 # (HACK: only in straight non-svp64-mode for now, or elwidth == 64)
2795 regname
= "_" + name
2796 if not self
.is_svp64_mode
or ew_src
== 64:
2797 self
.namespace
[regname
] = regnum
2799 # FIXME: we're trying to access a sub-register, plain register
2800 # numbers don't work for that. for now, just pass something that
2801 # can be compared to 0 and probably will cause an error if misused.
2802 # see https://bugs.libre-soc.org/show_bug.cgi?id=1221
2803 self
.namespace
[regname
] = regnum
* 10000
2805 if not self
.is_svp64_mode
or not self
.pred_src_zero
:
2806 log('reading reg %s %s' % (name
, str(regnum
)), is_vec
)
2808 fval
= self
.fpr(base
, is_vec
, offs
, ew_src
)
2809 reg_val
= SelectableInt(fval
)
2810 assert ew_src
== self
.XLEN
, "TODO fix elwidth conversion"
2811 self
.trace("r:FPR:%d:%d:%d " % (base
, offs
, ew_src
))
2812 log("read fp reg %d/%d: 0x%x" % (base
, offs
, reg_val
.value
),
2813 kind
=LogType
.InstrInOuts
)
2814 elif name
is not None:
2815 gval
= self
.gpr(base
, is_vec
, offs
, ew_src
)
2816 reg_val
= SelectableInt(gval
.value
, bits
=xlen
)
2817 self
.trace("r:GPR:%d:%d:%d " % (base
, offs
, ew_src
))
2818 log("read int reg %d/%d: 0x%x" % (base
, offs
, reg_val
.value
),
2819 kind
=LogType
.InstrInOuts
)
2821 log('zero input reg %s %s' % (name
, str(regnum
)), is_vec
)
2822 reg_val
= SelectableInt(0, ew_src
)
2825 def remap_set_steps(self
, remaps
):
2826 """remap_set_steps sets up the in1/2/3 and out1/2 steps.
2827 they work in concert with PowerDecoder2 at the moment,
2828 there is no HDL implementation of REMAP. therefore this
2829 function, because ISACaller still uses PowerDecoder2,
2830 will *explicitly* write the dec2.XX_step values. this has
2833 # just some convenient debug info
2835 sname
= 'SVSHAPE%d' % i
2836 shape
= self
.spr
[sname
]
2837 log(sname
, bin(shape
.value
))
2838 log(" lims", shape
.lims
)
2839 log(" mode", shape
.mode
)
2840 log(" skip", shape
.skip
)
2842 # set up the list of steps to remap
2843 mi0
= self
.svstate
.mi0
2844 mi1
= self
.svstate
.mi1
2845 mi2
= self
.svstate
.mi2
2846 mo0
= self
.svstate
.mo0
2847 mo1
= self
.svstate
.mo1
2848 steps
= [[self
.dec2
.in1_step
, mi0
], # RA
2849 [self
.dec2
.in2_step
, mi1
], # RB
2850 [self
.dec2
.in3_step
, mi2
], # RC
2851 [self
.dec2
.o_step
, mo0
], # RT
2852 [self
.dec2
.o2_step
, mo1
], # EA
2855 rnames
= ['RA', 'RB', 'RC', 'RT', 'RS']
2856 for i
, reg
in enumerate(rnames
):
2857 idx
= yield from get_idx_map(self
.dec2
, reg
)
2859 idx
= yield from get_idx_map(self
.dec2
, "F"+reg
)
2861 steps
[i
][0] = self
.dec2
.in1_step
2863 steps
[i
][0] = self
.dec2
.in2_step
2865 steps
[i
][0] = self
.dec2
.in3_step
2866 log("remap step", i
, reg
, idx
, steps
[i
][1])
2867 remap_idxs
= self
.remap_idxs
2869 # now cross-index the required SHAPE for each of 3-in 2-out regs
2870 rnames
= ['RA', 'RB', 'RC', 'RT', 'EA']
2871 for i
, (dstep
, shape_idx
) in enumerate(steps
):
2872 (shape
, remap
) = remaps
[shape_idx
]
2873 remap_idx
= remap_idxs
[shape_idx
]
2874 # zero is "disabled"
2875 if shape
.value
== 0x0:
2877 # now set the actual requested step to the current index
2878 if dstep
is not None:
2879 yield dstep
.eq(remap_idx
)
2881 # debug printout info
2882 rremaps
.append((shape
.mode
, hex(shape
.value
), dstep
,
2883 i
, rnames
[i
], shape_idx
, remap_idx
))
2885 log("shape remap", x
)
2887 def check_write(self
, info
, name
, output
, carry_en
, ew_dst
):
2888 if name
== 'overflow': # ignore, done already (above)
2890 if name
== 'CR0': # ignore, done already (above)
2892 if isinstance(output
, int):
2893 output
= SelectableInt(output
, EFFECTIVELY_UNLIMITED
)
2895 if name
.startswith("RESERVE"):
2896 log("write %s 0x%x" % (name
, output
.value
))
2897 getattr(self
, name
).eq(output
)
2899 if name
in ['FPSCR', ]:
2900 log("write FPSCR 0x%x" % (output
.value
))
2901 self
.FPSCR
.eq(output
)
2904 if name
in ['CA', 'CA32']:
2906 log("writing %s to XER" % name
, output
)
2907 log("write XER %s 0x%x" % (name
, output
.value
))
2908 self
.spr
['XER'][XER_bits
[name
]] = output
.value
2910 log("NOT writing %s to XER" % name
, output
)
2912 # write special SPRs
2913 if name
in info
.special_regs
:
2914 log('writing special %s' % name
, output
, special_sprs
)
2915 log("write reg %s 0x%x" % (name
, output
.value
),
2916 kind
=LogType
.InstrInOuts
)
2917 if name
in special_sprs
:
2918 self
.spr
[name
] = output
2920 self
.namespace
[name
].eq(output
)
2922 log('msr written', hex(self
.msr
.value
))
2924 # find out1/out2 PR/FPR
2925 regnum
, is_vec
= yield from get_idx_out(self
.dec2
, name
, True)
2927 regnum
, is_vec
= yield from get_idx_out2(self
.dec2
, name
, True)
2929 # temporary hack for not having 2nd output
2930 regnum
= yield getattr(self
.decoder
, name
)
2932 # convenient debug prefix
2937 # check zeroing due to predicate bit being zero
2938 if self
.is_svp64_mode
and self
.pred_dst_zero
:
2939 log('zeroing reg %s %s' % (str(regnum
), str(output
)), is_vec
)
2940 output
= SelectableInt(0, EFFECTIVELY_UNLIMITED
)
2941 log("write reg %s%s 0x%x ew %d" % (reg_prefix
, str(regnum
),
2942 output
.value
, ew_dst
),
2943 kind
=LogType
.InstrInOuts
)
2944 # zero-extend tov64 bit begore storing (should use EXT oh well)
2945 if output
.bits
> 64:
2946 output
= SelectableInt(output
.value
, 64)
2947 rnum
, base
, offset
= regnum
2949 self
.fpr
.write(regnum
, output
, is_vec
, ew_dst
)
2950 self
.trace("w:FPR:%d:%d:%d " % (rnum
, offset
, ew_dst
))
2953 # LDST/Update does *not* allow elwidths on RA (Effective Address).
2954 # this has to be detected, and overridden. see get_input (related)
2955 sv_mode
= yield self
.dec2
.rm_dec
.sv_mode
2956 is_ldst
= (sv_mode
in [SVMode
.LDST_IDX
.value
, SVMode
.LDST_IMM
.value
] \
2957 and self
.is_svp64_mode
)
2958 if is_ldst
and name
in ['EA', 'RA']:
2959 op
= self
.dec2
.dec
.op
2960 if hasattr(op
, "upd"):
2961 # update mode LD/ST uses read-reg A also as an output
2963 log("write is_ldst is_update", sv_mode
, is_ldst
, upd
)
2964 if upd
== LDSTMode
.update
.value
:
2965 ew_dst
= 64 # override for RA (EA) to 64-bit
2967 self
.gpr
.write(regnum
, output
, is_vec
, ew_dst
)
2968 self
.trace("w:GPR:%d:%d:%d " % (rnum
, offset
, ew_dst
))
2970 def check_step_increment(self
, rc_en
, asmop
, ins_name
):
2971 # check if it is the SVSTATE.src/dest step that needs incrementing
2972 # this is our Sub-Program-Counter loop from 0 to VL-1
2973 if not self
.allow_next_step_inc
:
2974 if self
.is_svp64_mode
:
2975 return (yield from self
.svstate_post_inc(ins_name
))
2977 # XXX only in non-SVP64 mode!
2978 # record state of whether the current operation was an svshape,
2980 # to be able to know if it should apply in the next instruction.
2981 # also (if going to use this instruction) should disable ability
2982 # to interrupt in between. sigh.
2983 self
.last_op_svshape
= asmop
in ['svremap', 'svindex',
2990 log("SVSTATE_NEXT: inc requested, mode",
2991 self
.svstate_next_mode
, self
.allow_next_step_inc
)
2992 yield from self
.svstate_pre_inc()
2993 pre
= yield from self
.update_new_svstate_steps()
2995 # reset at end of loop including exit Vertical Mode
2996 log("SVSTATE_NEXT: end of loop, reset")
2997 self
.svp64_reset_loop()
2998 self
.svstate
.vfirst
= 0
3002 self
.handle_comparison(SelectableInt(0, 64)) # CR0
3004 if self
.allow_next_step_inc
== 2:
3005 log("SVSTATE_NEXT: read")
3006 nia_update
= (yield from self
.svstate_post_inc(ins_name
))
3008 log("SVSTATE_NEXT: post-inc")
3009 # use actual (cached) src/dst-step here to check end
3010 remaps
= self
.get_remap_indices()
3011 remap_idxs
= self
.remap_idxs
3012 vl
= self
.svstate
.vl
3013 subvl
= yield self
.dec2
.rm_dec
.rm_in
.subvl
3014 if self
.allow_next_step_inc
!= 2:
3015 yield from self
.advance_svstate_steps()
3016 #self.namespace['SVSTATE'] = self.svstate.spr
3017 # set CR0 (if Rc=1) based on end
3018 endtest
= 1 if self
.at_loopend() else 0
3020 #results = [SelectableInt(endtest, 64)]
3021 # self.handle_comparison(results) # CR0
3023 # see if svstep was requested, if so, which SVSTATE
3025 if self
.svstate_next_mode
> 0:
3026 shape_idx
= self
.svstate_next_mode
.value
-1
3027 endings
= self
.remap_loopends
[shape_idx
]
3028 cr_field
= SelectableInt((~endings
) << 1 | endtest
, 4)
3029 log("svstep Rc=1, CR0", cr_field
, endtest
)
3030 self
.crl
[0].eq(cr_field
) # CR0
3032 # reset at end of loop including exit Vertical Mode
3033 log("SVSTATE_NEXT: after increments, reset")
3034 self
.svp64_reset_loop()
3035 self
.svstate
.vfirst
= 0
3038 def SVSTATE_NEXT(self
, mode
, submode
, RA
=None):
3039 """explicitly moves srcstep/dststep on to next element, for
3040 "Vertical-First" mode. this function is called from
3041 setvl pseudo-code, as a pseudo-op "svstep"
3043 WARNING: this function uses information that was created EARLIER
3044 due to it being in the middle of a yield, but this function is
3045 *NOT* called from yield (it's called from compiled pseudocode).
3047 self
.allow_next_step_inc
= submode
.value
+ 1
3048 log("SVSTATE_NEXT mode", mode
, submode
, self
.allow_next_step_inc
)
3049 self
.svstate_next_mode
= mode
3050 if self
.svstate_next_mode
> 0 and self
.svstate_next_mode
< 5:
3051 shape_idx
= self
.svstate_next_mode
.value
-1
3052 return SelectableInt(self
.remap_idxs
[shape_idx
], 7)
3053 if self
.svstate_next_mode
== 5:
3054 self
.svstate_next_mode
= 0
3055 return SelectableInt(self
.svstate
.srcstep
, 7)
3056 if self
.svstate_next_mode
== 6:
3057 self
.svstate_next_mode
= 0
3058 return SelectableInt(self
.svstate
.dststep
, 7)
3059 if self
.svstate_next_mode
== 7:
3060 self
.svstate_next_mode
= 0
3061 return SelectableInt(self
.svstate
.ssubstep
, 7)
3062 if self
.svstate_next_mode
== 8:
3063 self
.svstate_next_mode
= 0
3064 return SelectableInt(self
.svstate
.dsubstep
, 7)
3065 return SelectableInt(0, 7)
3067 def get_src_dststeps(self
):
3068 """gets srcstep, dststep, and ssubstep, dsubstep
3070 return (self
.new_srcstep
, self
.new_dststep
,
3071 self
.new_ssubstep
, self
.new_dsubstep
)
3073 def update_svstate_namespace(self
, overwrite_svstate
=True):
3074 if overwrite_svstate
:
3075 # note, do not get the bit-reversed srcstep here!
3076 srcstep
, dststep
= self
.new_srcstep
, self
.new_dststep
3077 ssubstep
, dsubstep
= self
.new_ssubstep
, self
.new_dsubstep
3079 # update SVSTATE with new srcstep
3080 self
.svstate
.srcstep
= srcstep
3081 self
.svstate
.dststep
= dststep
3082 self
.svstate
.ssubstep
= ssubstep
3083 self
.svstate
.dsubstep
= dsubstep
3084 self
.namespace
['SVSTATE'] = self
.svstate
3085 yield self
.dec2
.state
.svstate
.eq(self
.svstate
.value
)
3086 yield Settle() # let decoder update
3088 def update_new_svstate_steps(self
, overwrite_svstate
=True):
3089 yield from self
.update_svstate_namespace(overwrite_svstate
)
3090 srcstep
= self
.svstate
.srcstep
3091 dststep
= self
.svstate
.dststep
3092 ssubstep
= self
.svstate
.ssubstep
3093 dsubstep
= self
.svstate
.dsubstep
3094 pack
= self
.svstate
.pack
3095 unpack
= self
.svstate
.unpack
3096 vl
= self
.svstate
.vl
3097 sv_mode
= yield self
.dec2
.rm_dec
.sv_mode
3098 subvl
= yield self
.dec2
.rm_dec
.rm_in
.subvl
3099 rm_mode
= yield self
.dec2
.rm_dec
.mode
3100 ff_inv
= yield self
.dec2
.rm_dec
.inv
3101 cr_bit
= yield self
.dec2
.rm_dec
.cr_sel
3102 log(" srcstep", srcstep
)
3103 log(" dststep", dststep
)
3105 log(" unpack", unpack
)
3106 log(" ssubstep", ssubstep
)
3107 log(" dsubstep", dsubstep
)
3109 log(" subvl", subvl
)
3110 log(" rm_mode", rm_mode
)
3111 log(" sv_mode", sv_mode
)
3113 log(" cr_bit", cr_bit
)
3115 # check if end reached (we let srcstep overrun, above)
3116 # nothing needs doing (TODO zeroing): just do next instruction
3119 return ((ssubstep
== subvl
and srcstep
== vl
) or
3120 (dsubstep
== subvl
and dststep
== vl
))
3122 def svstate_post_inc(self
, insn_name
, vf
=0):
3123 # check if SV "Vertical First" mode is enabled
3124 vfirst
= self
.svstate
.vfirst
3125 log(" SV Vertical First", vf
, vfirst
)
3126 if not vf
and vfirst
== 1:
3127 # SV Branch-Conditional required to be as-if-vector
3128 # because there *is* no destination register
3129 # (SV normally only terminates on 1st scalar reg written
3130 # except in [slightly-misnamed] mapreduce mode)
3131 ffirst
= yield from is_ffirst_mode(self
.dec2
)
3132 if insn_name
.startswith("sv.bc") or ffirst
:
3133 self
.update_pc_next()
3138 # check if it is the SVSTATE.src/dest step that needs incrementing
3139 # this is our Sub-Program-Counter loop from 0 to VL-1
3140 # XXX twin predication TODO
3141 vl
= self
.svstate
.vl
3142 subvl
= yield self
.dec2
.rm_dec
.rm_in
.subvl
3143 mvl
= self
.svstate
.maxvl
3144 srcstep
= self
.svstate
.srcstep
3145 dststep
= self
.svstate
.dststep
3146 ssubstep
= self
.svstate
.ssubstep
3147 dsubstep
= self
.svstate
.dsubstep
3148 pack
= self
.svstate
.pack
3149 unpack
= self
.svstate
.unpack
3150 rm_mode
= yield self
.dec2
.rm_dec
.mode
3151 reverse_gear
= yield self
.dec2
.rm_dec
.reverse_gear
3152 sv_ptype
= yield self
.dec2
.dec
.op
.SV_Ptype
3153 out_vec
= not (yield self
.dec2
.no_out_vec
)
3154 in_vec
= not (yield self
.dec2
.no_in_vec
)
3155 rm_mode
= yield self
.dec2
.rm_dec
.mode
3156 log(" svstate.vl", vl
)
3157 log(" svstate.mvl", mvl
)
3158 log(" rm.subvl", subvl
)
3159 log(" svstate.srcstep", srcstep
)
3160 log(" svstate.dststep", dststep
)
3161 log(" svstate.ssubstep", ssubstep
)
3162 log(" svstate.dsubstep", dsubstep
)
3163 log(" svstate.pack", pack
)
3164 log(" svstate.unpack", unpack
)
3165 log(" mode", rm_mode
)
3166 log(" reverse", reverse_gear
)
3167 log(" out_vec", out_vec
)
3168 log(" in_vec", in_vec
)
3169 log(" sv_ptype", sv_ptype
, sv_ptype
== SVPType
.P2
.value
)
3170 log(" rm_mode", rm_mode
)
3171 # check if this was an sv.bc* and if so did it succeed
3172 if self
.is_svp64_mode
and insn_name
.startswith("sv.bc"):
3173 end_loop
= self
.namespace
['end_loop']
3174 log("branch %s end_loop" % insn_name
, end_loop
)
3176 self
.svp64_reset_loop()
3177 self
.update_pc_next()
3179 # check if srcstep needs incrementing by one, stop PC advancing
3180 # but for 2-pred both src/dest have to be checked.
3181 # XXX this might not be true! it may just be LD/ST
3182 if sv_ptype
== SVPType
.P2
.value
:
3183 svp64_is_vector
= (out_vec
or in_vec
)
3185 svp64_is_vector
= out_vec
3186 # also if data-dependent fail-first is used, only in_vec is tested,
3187 # allowing *scalar destinations* to be used as an accumulator.
3188 # effectively this implies /mr (mapreduce mode) is 100% on with ddffirst
3189 # see https://bugs.libre-soc.org/show_bug.cgi?id=1183#c16
3190 ffirst
= yield from is_ffirst_mode(self
.dec2
)
3192 svp64_is_vector
= in_vec
3194 # loops end at the first "hit" (source or dest)
3195 yield from self
.advance_svstate_steps()
3196 loopend
= self
.loopend
3197 log("loopend", svp64_is_vector
, loopend
)
3198 if not svp64_is_vector
or loopend
:
3199 # reset loop to zero and update NIA
3200 self
.svp64_reset_loop()
3205 # still looping, advance and update NIA
3206 self
.namespace
['SVSTATE'] = self
.svstate
3208 # not an SVP64 branch, so fix PC (NIA==CIA) for next loop
3209 # (by default, NIA is CIA+4 if v3.0B or CIA+8 if SVP64)
3210 # this way we keep repeating the same instruction (with new steps)
3211 self
.pc
.NIA
.eq(self
.pc
.CIA
)
3212 self
.namespace
['NIA'] = self
.pc
.NIA
3213 log("end of sub-pc call", self
.namespace
['CIA'], self
.namespace
['NIA'])
3214 return False # DO NOT allow PC update whilst Sub-PC loop running
3216 def update_pc_next(self
):
3217 # UPDATE program counter
3218 self
.pc
.update(self
.namespace
, self
.is_svp64_mode
)
3219 #self.svstate.spr = self.namespace['SVSTATE']
3220 log("end of call", self
.namespace
['CIA'],
3221 self
.namespace
['NIA'],
3222 self
.namespace
['SVSTATE'])
3224 def svp64_reset_loop(self
):
3225 self
.svstate
.srcstep
= 0
3226 self
.svstate
.dststep
= 0
3227 self
.svstate
.ssubstep
= 0
3228 self
.svstate
.dsubstep
= 0
3229 self
.loopend
= False
3230 log(" svstate.srcstep loop end (PC to update)")
3231 self
.namespace
['SVSTATE'] = self
.svstate
3233 def update_nia(self
):
3234 self
.pc
.update_nia(self
.is_svp64_mode
)
3235 self
.namespace
['NIA'] = self
.pc
.NIA
3239 """Decorator factory.
3241 this decorator will "inject" variables into the function's namespace,
3242 from the *dictionary* in self.namespace. it therefore becomes possible
3243 to make it look like a whole stack of variables which would otherwise
3244 need "self." inserted in front of them (*and* for those variables to be
3245 added to the instance) "appear" in the function.
3247 "self.namespace['SI']" for example becomes accessible as just "SI" but
3248 *only* inside the function, when decorated.
3250 def variable_injector(func
):
3252 def decorator(*args
, **kwargs
):
3254 func_globals
= func
.__globals
__ # Python 2.6+
3255 except AttributeError:
3256 func_globals
= func
.func_globals
# Earlier versions.
3258 context
= args
[0].namespace
# variables to be injected
3259 saved_values
= func_globals
.copy() # Shallow copy of dict.
3260 log("globals before", context
.keys())
3261 func_globals
.update(context
)
3262 result
= func(*args
, **kwargs
)
3263 log("globals after", func_globals
['CIA'], func_globals
['NIA'])
3264 log("args[0]", args
[0].namespace
['CIA'],
3265 args
[0].namespace
['NIA'],
3266 args
[0].namespace
['SVSTATE'])
3267 if 'end_loop' in func_globals
:
3268 log("args[0] end_loop", func_globals
['end_loop'])
3269 args
[0].namespace
= func_globals
3270 #exec (func.__code__, func_globals)
3273 # func_globals = saved_values # Undo changes.
3279 return variable_injector