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):
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("reg", "%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
:
566 if in_sel
== CRInSel
.BFA
.value
:
568 log("get_cr_in not found", name
)
572 # TODO, really should just be using PowerDecoder2
573 def get_cr_out(dec2
, name
):
575 out_sel
= yield op
.cr_out
576 out_bitfield
= yield dec2
.dec_cr_out
.cr_bitfield
.data
577 sv_cr_out
= yield op
.sv_cr_out
578 spec
= yield dec2
.crout_svdec
.spec
579 sv_override
= yield dec2
.dec_cr_out
.sv_override
580 # get the IN1/2/3 from the decoder (includes SVP64 remap and isvec)
581 out
= yield dec2
.e
.write_cr
.data
582 o_isvec
= yield dec2
.cr_out_isvec
583 log("get_cr_out", out_sel
, CROutSel
.CR0
.value
, out
, o_isvec
)
584 log(" sv_cr_out", sv_cr_out
)
585 log(" cr_bf", out_bitfield
)
587 log(" override", sv_override
)
588 # identify which regnames map to out / o2
590 if out_sel
== CROutSel
.BF
.value
:
593 if out_sel
== CROutSel
.CR0
.value
:
595 if name
== 'CR1': # these are not actually calculated correctly
596 if out_sel
== CROutSel
.CR1
.value
:
598 # check RC1 set? if so return implicit vector, this is a REAL bad hack
599 RC1
= yield dec2
.rm_dec
.RC1
601 log("get_cr_out RC1 mode")
603 return 0, True # XXX TODO: offset CR0 from SVSTATE SPR
605 return 1, True # XXX TODO: offset CR1 from SVSTATE SPR
607 log("get_cr_out not found", name
)
611 # TODO, really should just be using PowerDecoder2
612 def get_out_map(dec2
, name
):
614 out_sel
= yield op
.out_sel
615 # get the IN1/2/3 from the decoder (includes SVP64 remap and isvec)
616 out
= yield dec2
.e
.write_reg
.data
617 # identify which regnames map to out / o2
619 if out_sel
== OutSel
.RA
.value
:
622 if out_sel
== OutSel
.RT
.value
:
624 if out_sel
== OutSel
.RT_OR_ZERO
.value
and out
!= 0:
626 elif name
== 'RT_OR_ZERO':
627 if out_sel
== OutSel
.RT_OR_ZERO
.value
:
630 if out_sel
== OutSel
.FRA
.value
:
633 if out_sel
== OutSel
.FRS
.value
:
636 if out_sel
== OutSel
.FRT
.value
:
641 # TODO, really should just be using PowerDecoder2
642 def get_idx_out(dec2
, name
, ewmode
=False):
644 out_sel
= yield op
.out_sel
645 # get the IN1/2/3 from the decoder (includes SVP64 remap and isvec)
646 out
= yield dec2
.e
.write_reg
.data
647 o_isvec
= yield dec2
.o_isvec
649 offs
= yield dec2
.e
.write_reg
.offs
650 base
= yield dec2
.e
.write_reg
.base
651 out
= (out
, base
, offs
)
652 # identify which regnames map to out / o2
653 ismap
= yield from get_out_map(dec2
, name
)
655 log("get_idx_out", name
, out_sel
, out
, o_isvec
)
657 log("get_idx_out not found", name
, out_sel
, out
, o_isvec
)
661 # TODO, really should just be using PowerDecoder2
662 def get_out2_map(dec2
, name
):
663 # check first if register is activated for write
665 out_sel
= yield op
.out_sel
666 out
= yield dec2
.e
.write_ea
.data
667 out_ok
= yield dec2
.e
.write_ea
.ok
671 if name
in ['EA', 'RA']:
672 if hasattr(op
, "upd"):
673 # update mode LD/ST uses read-reg A also as an output
675 log("get_idx_out2", upd
, LDSTMode
.update
.value
,
676 out_sel
, OutSel
.RA
.value
,
678 if upd
== LDSTMode
.update
.value
:
681 fft_en
= yield dec2
.implicit_rs
683 log("get_idx_out2", out_sel
, OutSel
.RS
.value
,
687 fft_en
= yield dec2
.implicit_rs
689 log("get_idx_out2", out_sel
, OutSel
.FRS
.value
,
695 # TODO, really should just be using PowerDecoder2
696 def get_idx_out2(dec2
, name
, ewmode
=False):
697 # check first if register is activated for write
699 out_sel
= yield op
.out_sel
700 out
= yield dec2
.e
.write_ea
.data
702 offs
= yield dec2
.e
.write_ea
.offs
703 base
= yield dec2
.e
.write_ea
.base
704 out
= (out
, base
, offs
)
705 o_isvec
= yield dec2
.o2_isvec
706 ismap
= yield from get_out2_map(dec2
, name
)
708 log("get_idx_out2", name
, out_sel
, out
, o_isvec
)
714 """deals with svstate looping.
717 def __init__(self
, svstate
):
718 self
.svstate
= svstate
721 def new_iterators(self
):
722 self
.src_it
= self
.src_iterator()
723 self
.dst_it
= self
.dst_iterator()
727 self
.new_ssubstep
= 0
728 self
.new_dsubstep
= 0
729 self
.pred_dst_zero
= 0
730 self
.pred_src_zero
= 0
732 def src_iterator(self
):
733 """source-stepping iterator
735 pack
= self
.svstate
.pack
739 # pack advances subvl in *outer* loop
740 while True: # outer subvl loop
741 while True: # inner vl loop
744 srcmask
= self
.srcmask
745 srcstep
= self
.svstate
.srcstep
746 pred_src_zero
= ((1 << srcstep
) & srcmask
) != 0
747 if self
.pred_sz
or pred_src_zero
:
748 self
.pred_src_zero
= not pred_src_zero
749 log(" advance src", srcstep
, vl
,
750 self
.svstate
.ssubstep
, subvl
)
751 # yield actual substep/srcstep
752 yield (self
.svstate
.ssubstep
, srcstep
)
753 # the way yield works these could have been modified.
756 srcstep
= self
.svstate
.srcstep
757 log(" advance src check", srcstep
, vl
,
758 self
.svstate
.ssubstep
, subvl
, srcstep
== vl
-1,
759 self
.svstate
.ssubstep
== subvl
)
760 if srcstep
== vl
-1: # end-point
761 self
.svstate
.srcstep
= SelectableInt(0, 7) # reset
762 if self
.svstate
.ssubstep
== subvl
: # end-point
763 log(" advance pack stop")
765 break # exit inner loop
766 self
.svstate
.srcstep
+= SelectableInt(1, 7) # advance ss
768 if self
.svstate
.ssubstep
== subvl
: # end-point
769 self
.svstate
.ssubstep
= SelectableInt(0, 2) # reset
770 log(" advance pack stop")
772 self
.svstate
.ssubstep
+= SelectableInt(1, 2)
775 # these cannot be done as for-loops because SVSTATE may change
776 # (srcstep/substep may be modified, interrupted, subvl/vl change)
777 # but they *can* be done as while-loops as long as every SVSTATE
778 # "thing" is re-read every single time a yield gives indices
779 while True: # outer vl loop
780 while True: # inner subvl loop
783 srcmask
= self
.srcmask
784 srcstep
= self
.svstate
.srcstep
785 pred_src_zero
= ((1 << srcstep
) & srcmask
) != 0
786 if self
.pred_sz
or pred_src_zero
:
787 self
.pred_src_zero
= not pred_src_zero
788 log(" advance src", srcstep
, vl
,
789 self
.svstate
.ssubstep
, subvl
)
790 # yield actual substep/srcstep
791 yield (self
.svstate
.ssubstep
, srcstep
)
792 if self
.svstate
.ssubstep
== subvl
: # end-point
793 self
.svstate
.ssubstep
= SelectableInt(0, 2) # reset
794 break # exit inner loop
795 self
.svstate
.ssubstep
+= SelectableInt(1, 2)
797 if srcstep
== vl
-1: # end-point
798 self
.svstate
.srcstep
= SelectableInt(0, 7) # reset
801 self
.svstate
.srcstep
+= SelectableInt(1, 7) # advance srcstep
803 def dst_iterator(self
):
804 """dest-stepping iterator
806 unpack
= self
.svstate
.unpack
810 # pack advances subvl in *outer* loop
811 while True: # outer subvl loop
812 while True: # inner vl loop
815 dstmask
= self
.dstmask
816 dststep
= self
.svstate
.dststep
817 pred_dst_zero
= ((1 << dststep
) & dstmask
) != 0
818 if self
.pred_dz
or pred_dst_zero
:
819 self
.pred_dst_zero
= not pred_dst_zero
820 log(" advance dst", dststep
, vl
,
821 self
.svstate
.dsubstep
, subvl
)
822 # yield actual substep/dststep
823 yield (self
.svstate
.dsubstep
, dststep
)
824 # the way yield works these could have been modified.
826 dststep
= self
.svstate
.dststep
827 log(" advance dst check", dststep
, vl
,
828 self
.svstate
.ssubstep
, subvl
)
829 if dststep
== vl
-1: # end-point
830 self
.svstate
.dststep
= SelectableInt(0, 7) # reset
831 if self
.svstate
.dsubstep
== subvl
: # end-point
832 log(" advance unpack stop")
835 self
.svstate
.dststep
+= SelectableInt(1, 7) # advance ds
837 if self
.svstate
.dsubstep
== subvl
: # end-point
838 self
.svstate
.dsubstep
= SelectableInt(0, 2) # reset
839 log(" advance unpack stop")
841 self
.svstate
.dsubstep
+= SelectableInt(1, 2)
843 # these cannot be done as for-loops because SVSTATE may change
844 # (dststep/substep may be modified, interrupted, subvl/vl change)
845 # but they *can* be done as while-loops as long as every SVSTATE
846 # "thing" is re-read every single time a yield gives indices
847 while True: # outer vl loop
848 while True: # inner subvl loop
850 dstmask
= self
.dstmask
851 dststep
= self
.svstate
.dststep
852 pred_dst_zero
= ((1 << dststep
) & dstmask
) != 0
853 if self
.pred_dz
or pred_dst_zero
:
854 self
.pred_dst_zero
= not pred_dst_zero
855 log(" advance dst", dststep
, self
.svstate
.vl
,
856 self
.svstate
.dsubstep
, subvl
)
857 # yield actual substep/dststep
858 yield (self
.svstate
.dsubstep
, dststep
)
859 if self
.svstate
.dsubstep
== subvl
: # end-point
860 self
.svstate
.dsubstep
= SelectableInt(0, 2) # reset
862 self
.svstate
.dsubstep
+= SelectableInt(1, 2)
865 if dststep
== vl
-1: # end-point
866 self
.svstate
.dststep
= SelectableInt(0, 7) # reset
868 self
.svstate
.dststep
+= SelectableInt(1, 7) # advance dststep
870 def src_iterate(self
):
871 """source-stepping iterator
875 pack
= self
.svstate
.pack
876 unpack
= self
.svstate
.unpack
877 ssubstep
= self
.svstate
.ssubstep
878 end_ssub
= ssubstep
== subvl
879 end_src
= self
.svstate
.srcstep
== vl
-1
880 log(" pack/unpack/subvl", pack
, unpack
, subvl
,
884 srcstep
= self
.svstate
.srcstep
885 srcmask
= self
.srcmask
887 # pack advances subvl in *outer* loop
889 assert srcstep
<= vl
-1
890 end_src
= srcstep
== vl
-1
895 self
.svstate
.ssubstep
+= SelectableInt(1, 2)
899 srcstep
+= 1 # advance srcstep
900 if not self
.srcstep_skip
:
902 if ((1 << srcstep
) & srcmask
) != 0:
905 log(" sskip", bin(srcmask
), bin(1 << srcstep
))
907 # advance subvl in *inner* loop
910 assert srcstep
<= vl
-1
911 end_src
= srcstep
== vl
-1
912 if end_src
: # end-point
918 if not self
.srcstep_skip
:
920 if ((1 << srcstep
) & srcmask
) != 0:
923 log(" sskip", bin(srcmask
), bin(1 << srcstep
))
924 self
.svstate
.ssubstep
= SelectableInt(0, 2) # reset
927 self
.svstate
.ssubstep
+= SelectableInt(1, 2)
929 self
.svstate
.srcstep
= SelectableInt(srcstep
, 7)
930 log(" advance src", self
.svstate
.srcstep
, self
.svstate
.ssubstep
,
933 def dst_iterate(self
):
934 """dest step iterator
938 pack
= self
.svstate
.pack
939 unpack
= self
.svstate
.unpack
940 dsubstep
= self
.svstate
.dsubstep
941 end_dsub
= dsubstep
== subvl
942 dststep
= self
.svstate
.dststep
943 end_dst
= dststep
== vl
-1
944 dstmask
= self
.dstmask
945 log(" pack/unpack/subvl", pack
, unpack
, subvl
,
950 # unpack advances subvl in *outer* loop
952 assert dststep
<= vl
-1
953 end_dst
= dststep
== vl
-1
958 self
.svstate
.dsubstep
+= SelectableInt(1, 2)
962 dststep
+= 1 # advance dststep
963 if not self
.dststep_skip
:
965 if ((1 << dststep
) & dstmask
) != 0:
968 log(" dskip", bin(dstmask
), bin(1 << dststep
))
970 # advance subvl in *inner* loop
973 assert dststep
<= vl
-1
974 end_dst
= dststep
== vl
-1
975 if end_dst
: # end-point
981 if not self
.dststep_skip
:
983 if ((1 << dststep
) & dstmask
) != 0:
986 log(" dskip", bin(dstmask
), bin(1 << dststep
))
987 self
.svstate
.dsubstep
= SelectableInt(0, 2) # reset
990 self
.svstate
.dsubstep
+= SelectableInt(1, 2)
992 self
.svstate
.dststep
= SelectableInt(dststep
, 7)
993 log(" advance dst", self
.svstate
.dststep
, self
.svstate
.dsubstep
,
996 def at_loopend(self
):
997 """tells if this is the last possible element. uses the cached values
998 for src/dst-step and sub-steps
1001 vl
= self
.svstate
.vl
1002 srcstep
, dststep
= self
.new_srcstep
, self
.new_dststep
1003 ssubstep
, dsubstep
= self
.new_ssubstep
, self
.new_dsubstep
1004 end_ssub
= ssubstep
== subvl
1005 end_dsub
= dsubstep
== subvl
1006 if srcstep
== vl
-1 and end_ssub
:
1008 if dststep
== vl
-1 and end_dsub
:
1012 def advance_svstate_steps(self
):
1013 """ advance sub/steps. note that Pack/Unpack *INVERTS* the order.
1014 TODO when Pack/Unpack is set, substep becomes the *outer* loop
1016 self
.subvl
= yield self
.dec2
.rm_dec
.rm_in
.subvl
1017 if self
.loopend
: # huhn??
1022 def read_src_mask(self
):
1023 """read/update pred_sz and src mask
1025 # get SVSTATE VL (oh and print out some debug stuff)
1026 vl
= self
.svstate
.vl
1027 srcstep
= self
.svstate
.srcstep
1028 ssubstep
= self
.svstate
.ssubstep
1030 # get predicate mask (all 64 bits)
1031 srcmask
= 0xffff_ffff_ffff_ffff
1033 pmode
= yield self
.dec2
.rm_dec
.predmode
1034 sv_ptype
= yield self
.dec2
.dec
.op
.SV_Ptype
1035 srcpred
= yield self
.dec2
.rm_dec
.srcpred
1036 dstpred
= yield self
.dec2
.rm_dec
.dstpred
1037 pred_sz
= yield self
.dec2
.rm_dec
.pred_sz
1038 if pmode
== SVP64PredMode
.INT
.value
:
1039 srcmask
= dstmask
= get_predint(self
.gpr
, dstpred
)
1040 if sv_ptype
== SVPType
.P2
.value
:
1041 srcmask
= get_predint(self
.gpr
, srcpred
)
1042 elif pmode
== SVP64PredMode
.CR
.value
:
1043 srcmask
= dstmask
= get_predcr(self
.crl
, dstpred
, vl
)
1044 if sv_ptype
== SVPType
.P2
.value
:
1045 srcmask
= get_predcr(self
.crl
, srcpred
, vl
)
1046 # work out if the ssubsteps are completed
1047 ssubstart
= ssubstep
== 0
1048 log(" pmode", pmode
)
1049 log(" ptype", sv_ptype
)
1050 log(" srcpred", bin(srcpred
))
1051 log(" srcmask", bin(srcmask
))
1052 log(" pred_sz", bin(pred_sz
))
1053 log(" ssubstart", ssubstart
)
1055 # store all that above
1056 self
.srcstep_skip
= False
1057 self
.srcmask
= srcmask
1058 self
.pred_sz
= pred_sz
1059 self
.new_ssubstep
= ssubstep
1060 log(" new ssubstep", ssubstep
)
1061 # until the predicate mask has a "1" bit... or we run out of VL
1062 # let srcstep==VL be the indicator to move to next instruction
1064 self
.srcstep_skip
= True
1066 def read_dst_mask(self
):
1067 """same as read_src_mask - check and record everything needed
1069 # get SVSTATE VL (oh and print out some debug stuff)
1070 # yield Delay(1e-10) # make changes visible
1071 vl
= self
.svstate
.vl
1072 dststep
= self
.svstate
.dststep
1073 dsubstep
= self
.svstate
.dsubstep
1075 # get predicate mask (all 64 bits)
1076 dstmask
= 0xffff_ffff_ffff_ffff
1078 pmode
= yield self
.dec2
.rm_dec
.predmode
1079 reverse_gear
= yield self
.dec2
.rm_dec
.reverse_gear
1080 sv_ptype
= yield self
.dec2
.dec
.op
.SV_Ptype
1081 dstpred
= yield self
.dec2
.rm_dec
.dstpred
1082 pred_dz
= yield self
.dec2
.rm_dec
.pred_dz
1083 if pmode
== SVP64PredMode
.INT
.value
:
1084 dstmask
= get_predint(self
.gpr
, dstpred
)
1085 elif pmode
== SVP64PredMode
.CR
.value
:
1086 dstmask
= get_predcr(self
.crl
, dstpred
, vl
)
1087 # work out if the ssubsteps are completed
1088 dsubstart
= dsubstep
== 0
1089 log(" pmode", pmode
)
1090 log(" ptype", sv_ptype
)
1091 log(" dstpred", bin(dstpred
))
1092 log(" dstmask", bin(dstmask
))
1093 log(" pred_dz", bin(pred_dz
))
1094 log(" dsubstart", dsubstart
)
1096 self
.dststep_skip
= False
1097 self
.dstmask
= dstmask
1098 self
.pred_dz
= pred_dz
1099 self
.new_dsubstep
= dsubstep
1100 log(" new dsubstep", dsubstep
)
1102 self
.dststep_skip
= True
1104 def svstate_pre_inc(self
):
1105 """check if srcstep/dststep need to skip over masked-out predicate bits
1106 note that this is not supposed to do anything to substep,
1107 it is purely for skipping masked-out bits
1110 self
.subvl
= yield self
.dec2
.rm_dec
.rm_in
.subvl
1111 yield from self
.read_src_mask()
1112 yield from self
.read_dst_mask()
1119 srcstep
= self
.svstate
.srcstep
1120 srcmask
= self
.srcmask
1121 pred_src_zero
= self
.pred_sz
1122 vl
= self
.svstate
.vl
1123 # srcstep-skipping opportunity identified
1124 if self
.srcstep_skip
:
1125 # cannot do this with sv.bc - XXX TODO
1128 while (((1 << srcstep
) & srcmask
) == 0) and (srcstep
!= vl
):
1129 log(" sskip", bin(1 << srcstep
))
1132 # now work out if the relevant mask bits require zeroing
1134 pred_src_zero
= ((1 << srcstep
) & srcmask
) == 0
1136 # store new srcstep / dststep
1137 self
.new_srcstep
= srcstep
1138 self
.pred_src_zero
= pred_src_zero
1139 log(" new srcstep", srcstep
)
1142 # dststep-skipping opportunity identified
1143 dststep
= self
.svstate
.dststep
1144 dstmask
= self
.dstmask
1145 pred_dst_zero
= self
.pred_dz
1146 vl
= self
.svstate
.vl
1147 if self
.dststep_skip
:
1148 # cannot do this with sv.bc - XXX TODO
1151 while (((1 << dststep
) & dstmask
) == 0) and (dststep
!= vl
):
1152 log(" dskip", bin(1 << dststep
))
1155 # now work out if the relevant mask bits require zeroing
1157 pred_dst_zero
= ((1 << dststep
) & dstmask
) == 0
1159 # store new srcstep / dststep
1160 self
.new_dststep
= dststep
1161 self
.pred_dst_zero
= pred_dst_zero
1162 log(" new dststep", dststep
)
1165 class ExitSyscallCalled(Exception):
1169 class SyscallEmulator(openpower
.syscalls
.Dispatcher
):
1170 def __init__(self
, isacaller
):
1171 self
.__isacaller
= isacaller
1173 host
= os
.uname().machine
1174 bits
= (64 if (sys
.maxsize
> (2**32)) else 32)
1175 host
= openpower
.syscalls
.architecture(arch
=host
, bits
=bits
)
1177 return super().__init
__(guest
="ppc64", host
=host
)
1179 def __call__(self
, identifier
, *arguments
):
1180 (identifier
, *arguments
) = map(int, (identifier
, *arguments
))
1181 return super().__call
__(identifier
, *arguments
)
1183 def sys_exit_group(self
, status
, *rest
):
1184 self
.__isacaller
.halted
= True
1185 raise ExitSyscallCalled(status
)
1187 def sys_write(self
, fd
, buf
, count
, *rest
):
1189 buf
= self
.__isacaller
.mem
.get_ctypes(buf
, count
, is_write
=False)
1193 return os
.write(fd
, buf
)
1194 except OSError as e
:
1197 def sys_writev(self
, fd
, iov
, iovcnt
, *rest
):
1199 if iovcnt
< 0 or iovcnt
> IOV_MAX
:
1200 return -errno
.EINVAL
1201 struct_iovec
= struct
.Struct("<QQ")
1204 iov
= self
.__isacaller
.mem
.get_ctypes(
1205 iov
, struct_iovec
.size
* iovcnt
, is_write
=False)
1206 iov
= list(struct_iovec
.iter_unpack(iov
))
1209 for i
, iovec
in enumerate(iov
):
1210 iov_base
, iov_len
= iovec
1211 iov
[i
] = self
.__isacaller
.mem
.get_ctypes(
1212 iov_base
, iov_len
, is_write
=False)
1213 except (ValueError, MemException
):
1214 return -errno
.EFAULT
1216 return os
.writev(fd
, iov
)
1217 except OSError as e
:
1220 def sys_read(self
, fd
, buf
, count
, *rest
):
1222 buf
= self
.__isacaller
.mem
.get_ctypes(buf
, count
, is_write
=True)
1226 return os
.readv(fd
, [buf
])
1227 except OSError as e
:
1230 def sys_mmap(self
, addr
, length
, prot
, flags
, fd
, offset
, *rest
):
1231 return self
.__isacaller
.mem
.mmap_syscall(
1232 addr
, length
, prot
, flags
, fd
, offset
, is_mmap2
=False)
1234 def sys_mmap2(self
, addr
, length
, prot
, flags
, fd
, offset
, *rest
):
1235 return self
.__isacaller
.mem
.mmap_syscall(
1236 addr
, length
, prot
, flags
, fd
, offset
, is_mmap2
=True)
1238 def sys_brk(self
, addr
, *rest
):
1239 return self
.__isacaller
.mem
.brk_syscall(addr
)
1241 def sys_munmap(self
, addr
, length
, *rest
):
1242 return -errno
.ENOSYS
# TODO: implement
1244 def sys_mprotect(self
, addr
, length
, prot
, *rest
):
1245 return -errno
.ENOSYS
# TODO: implement
1247 def sys_pkey_mprotect(self
, addr
, length
, prot
, pkey
, *rest
):
1248 return -errno
.ENOSYS
# TODO: implement
1250 def sys_openat(self
, dirfd
, pathname
, flags
, mode
, *rest
):
1252 path
= self
.__isacaller
.mem
.read_cstr(pathname
)
1253 except (ValueError, MemException
):
1254 return -errno
.EFAULT
1256 if dirfd
== ppc_flags
.AT_FDCWD
:
1257 return os
.open(path
, flags
, mode
)
1259 return os
.open(path
, flags
, mode
, dir_fd
=dirfd
)
1260 except OSError as e
:
1266 nodename
= uname
.nodename
.encode()
1267 release
= b
'5.6.0-1-powerpc64le'
1268 version
= b
'#1 SMP Debian 5.6.7-1 (2020-04-29)'
1269 machine
= b
'ppc64le'
1271 return sysname
, nodename
, release
, version
, machine
, domainname
1273 def sys_uname(self
, buf
, *rest
):
1274 s
= struct
.Struct("<65s65s65s65s65s")
1276 buf
= self
.__isacaller
.mem
.get_ctypes(buf
, s
.size
, is_write
=True)
1277 except (ValueError, MemException
):
1278 return -errno
.EFAULT
1279 sysname
, nodename
, release
, version
, machine
, domainname
= \
1281 s
.pack_into(buf
, 0, sysname
, nodename
, release
, version
, machine
)
1284 def sys_newuname(self
, buf
, *rest
):
1285 name_len
= ppc_flags
.__NEW
_UTS
_LEN
+ 1
1286 s
= struct
.Struct("<%ds%ds%ds%ds%ds%ds" % ((name_len
,) * 6))
1288 buf
= self
.__isacaller
.mem
.get_ctypes(buf
, s
.size
, is_write
=True)
1289 except (ValueError, MemException
):
1290 return -errno
.EFAULT
1291 sysname
, nodename
, release
, version
, machine
, domainname
= \
1294 sysname
, nodename
, release
, version
, machine
, domainname
)
1297 def sys_readlink(self
, pathname
, buf
, bufsiz
, *rest
):
1298 dirfd
= ppc_flags
.AT_FDCWD
1299 return self
.sys_readlinkat(dirfd
, pathname
, buf
, bufsiz
)
1301 def sys_readlinkat(self
, dirfd
, pathname
, buf
, bufsiz
, *rest
):
1303 path
= self
.__isacaller
.mem
.read_cstr(pathname
)
1305 buf
= self
.__isacaller
.mem
.get_ctypes(
1306 buf
, bufsiz
, is_write
=True)
1309 except (ValueError, MemException
):
1310 return -errno
.EFAULT
1312 if dirfd
== ppc_flags
.AT_FDCWD
:
1313 result
= os
.readlink(path
)
1315 result
= os
.readlink(path
, dir_fd
=dirfd
)
1316 retval
= min(len(result
), len(buf
))
1317 buf
[:retval
] = result
[:retval
]
1319 except OSError as e
:
1323 class ISACaller(ISACallerHelper
, ISAFPHelpers
, StepLoop
):
1324 # decoder2 - an instance of power_decoder2
1325 # regfile - a list of initial values for the registers
1326 # initial_{etc} - initial values for SPRs, Condition Register, Mem, MSR
1327 # respect_pc - tracks the program counter. requires initial_insns
1328 def __init__(self
, decoder2
, regfile
, initial_sprs
=None, initial_cr
=0,
1329 initial_mem
=None, initial_msr
=0,
1342 use_syscall_emu
=False,
1343 emulating_mmap
=False,
1344 real_page_size
=None):
1346 self
.syscall
= SyscallEmulator(isacaller
=self
)
1347 if not use_mmap_mem
:
1348 log("forcing use_mmap_mem due to use_syscall_emu active")
1353 # we will eventually be able to load ELF files without use_syscall_emu
1354 # (e.g. the linux kernel), so do it in a separate if block
1355 if isinstance(initial_insns
, ELFFile
):
1356 if not use_mmap_mem
:
1357 log("forcing use_mmap_mem due to loading an ELF file")
1359 if not emulating_mmap
:
1360 log("forcing emulating_mmap due to loading an ELF file")
1361 emulating_mmap
= True
1363 # trace log file for model output. if None do nothing
1364 self
.insnlog
= insnlog
1365 self
.insnlog_is_file
= hasattr(insnlog
, "write")
1366 if not self
.insnlog_is_file
and self
.insnlog
:
1367 self
.insnlog
= open(self
.insnlog
, "w")
1369 self
.bigendian
= bigendian
1371 self
.is_svp64_mode
= False
1372 self
.respect_pc
= respect_pc
1373 if initial_sprs
is None:
1375 if initial_mem
is None:
1377 if fpregfile
is None:
1378 fpregfile
= [0] * 32
1379 if initial_insns
is None:
1381 assert self
.respect_pc
== False, "instructions required to honor pc"
1382 if initial_msr
is None:
1383 initial_msr
= DEFAULT_MSR
1385 log("ISACaller insns", respect_pc
, initial_insns
, disassembly
)
1386 log("ISACaller initial_msr", initial_msr
)
1388 # "fake program counter" mode (for unit testing)
1392 if isinstance(initial_mem
, tuple):
1393 self
.fake_pc
= initial_mem
[0]
1394 disasm_start
= self
.fake_pc
1396 disasm_start
= initial_pc
1398 # disassembly: we need this for now (not given from the decoder)
1399 self
.disassembly
= {}
1401 for i
, code
in enumerate(disassembly
):
1402 self
.disassembly
[i
*4 + disasm_start
] = code
1404 # set up registers, instruction memory, data memory, PC, SPRs, MSR, CR
1405 self
.svp64rm
= SVP64RM()
1406 if initial_svstate
is None:
1408 if isinstance(initial_svstate
, int):
1409 initial_svstate
= SVP64State(initial_svstate
)
1410 # SVSTATE, MSR and PC
1411 StepLoop
.__init
__(self
, initial_svstate
)
1412 self
.msr
= SelectableInt(initial_msr
, 64) # underlying reg
1414 # GPR FPR SPR registers
1415 initial_sprs
= deepcopy(initial_sprs
) # so as not to get modified
1416 self
.gpr
= GPR(decoder2
, self
, self
.svstate
, regfile
)
1417 self
.fpr
= GPR(decoder2
, self
, self
.svstate
, fpregfile
)
1418 # initialise SPRs before MMU
1419 self
.spr
= SPR(decoder2
, initial_sprs
, gpr
=self
.gpr
)
1421 # set up 4 dummy SVSHAPEs if they aren't already set up
1423 sname
= 'SVSHAPE%d' % i
1424 val
= self
.spr
.get(sname
, 0)
1425 # make sure it's an SVSHAPE -- conversion done by SPR.__setitem__
1426 self
.spr
[sname
] = val
1427 self
.last_op_svshape
= False
1431 self
.mem
= MemMMap(row_bytes
=8,
1432 initial_mem
=initial_mem
,
1434 emulating_mmap
=emulating_mmap
)
1435 self
.imem
= self
.mem
1436 lelf
= self
.mem
.initialize(row_bytes
=4, initial_mem
=initial_insns
)
1437 if isinstance(lelf
, LoadedELF
): # stuff parsed from ELF
1438 initial_pc
= lelf
.pc
1439 for k
, v
in lelf
.gprs
.items():
1440 self
.gpr
[k
] = SelectableInt(v
, 64)
1441 initial_fpscr
= lelf
.fpscr
1442 self
.mem
.log_fancy(kind
=LogType
.InstrInOuts
)
1444 self
.mem
= Mem(row_bytes
=8, initial_mem
=initial_mem
,
1446 self
.mem
.log_fancy(kind
=LogType
.InstrInOuts
)
1447 self
.imem
= Mem(row_bytes
=4, initial_mem
=initial_insns
)
1448 # MMU mode, redirect underlying Mem through RADIX
1450 self
.mem
= RADIX(self
.mem
, self
)
1452 self
.imem
= RADIX(self
.imem
, self
)
1454 # TODO, needed here:
1455 # FPR (same as GPR except for FP nums)
1456 # 4.2.2 p124 FPSCR (definitely "separate" - not in SPR)
1457 # note that mffs, mcrfs, mtfsf "manage" this FPSCR
1458 self
.fpscr
= FPSCRState(initial_fpscr
)
1460 # 2.3.1 CR (and sub-fields CR0..CR6 - CR0 SO comes from XER.SO)
1461 # note that mfocrf, mfcr, mtcr, mtocrf, mcrxrx "manage" CRs
1463 # 2.3.2 LR (actually SPR #8) -- Done
1464 # 2.3.3 CTR (actually SPR #9) -- Done
1465 # 2.3.4 TAR (actually SPR #815)
1466 # 3.2.2 p45 XER (actually SPR #1) -- Done
1467 # 3.2.3 p46 p232 VRSAVE (actually SPR #256)
1469 # create CR then allow portions of it to be "selectable" (below)
1470 self
.cr_fields
= CRFields(initial_cr
)
1471 self
.cr
= self
.cr_fields
.cr
1472 self
.cr_backup
= 0 # sigh, dreadful hack: for fail-first (VLi)
1474 # "undefined", just set to variable-bit-width int (use exts "max")
1475 # self.undefined = SelectableInt(0, EFFECTIVELY_UNLIMITED)
1478 self
.namespace
.update(self
.spr
)
1479 self
.namespace
.update({'GPR': self
.gpr
,
1483 'memassign': self
.memassign
,
1486 'SVSTATE': self
.svstate
,
1487 'SVSHAPE0': self
.spr
['SVSHAPE0'],
1488 'SVSHAPE1': self
.spr
['SVSHAPE1'],
1489 'SVSHAPE2': self
.spr
['SVSHAPE2'],
1490 'SVSHAPE3': self
.spr
['SVSHAPE3'],
1493 'FPSCR': self
.fpscr
,
1494 'undefined': undefined
,
1495 'mode_is_64bit': True,
1496 'SO': XER_bits
['SO'],
1497 'XLEN': 64, # elwidth overrides
1501 if real_page_size
is None:
1502 # PowerISA v3.1B Book III Section 6.7 page 1191 (1217)
1503 # defines real page size as 2 ** 12 bytes (4KiB)
1504 real_page_size
= 2 ** 12
1505 self
.real_page_size
= real_page_size
1506 self
.reserve_addr
= SelectableInt(0, self
.XLEN
)
1507 self
.reserve
= SelectableInt(0, 1)
1508 self
.reserve_length
= SelectableInt(0, 4)
1510 self
.namespace
.update({'RESERVE': self
.RESERVE
,
1511 'RESERVE_ADDR': self
.RESERVE_ADDR
,
1512 'RESERVE_LENGTH': self
.RESERVE_LENGTH
,
1513 'REAL_PAGE_SIZE': self
.REAL_PAGE_SIZE
,
1516 for name
in BFP_FLAG_NAMES
:
1517 setattr(self
, name
, 0)
1519 # update pc to requested start point
1520 self
.set_pc(initial_pc
)
1522 # field-selectable versions of Condition Register
1523 self
.crl
= self
.cr_fields
.crl
1525 self
.namespace
["CR%d" % i
] = self
.crl
[i
]
1527 self
.decoder
= decoder2
.dec
1528 self
.dec2
= decoder2
1530 super().__init
__(XLEN
=self
.namespace
["XLEN"], FPSCR
=self
.fpscr
)
1532 def trace(self
, out
):
1533 if self
.insnlog
is None:
1535 self
.insnlog
.write(out
)
1539 return self
.namespace
["XLEN"]
1546 def RESERVE_LENGTH(self
):
1547 return self
.reserve_length
1550 def RESERVE_ADDR(self
):
1551 return self
.reserve_addr
1554 def REAL_PAGE_SIZE(self
):
1555 return self
.real_page_size
1557 def real_addr(self
, EA
):
1558 """ get the "real address to which `EA` maps"
1560 Specified in PowerISA v3.1B Book II Section 1.7.2.1 page 1049 (1075)
1562 # FIXME: translate EA to a physical address
1569 def call_trap(self
, trap_addr
, trap_bit
):
1570 """calls TRAP and sets up NIA to the new execution location.
1571 next instruction will begin at trap_addr.
1573 self
.TRAP(trap_addr
, trap_bit
)
1574 self
.namespace
['NIA'] = self
.trap_nia
1575 self
.pc
.update(self
.namespace
, self
.is_svp64_mode
)
1577 def TRAP(self
, trap_addr
=0x700, trap_bit
=PIb
.TRAP
):
1578 """TRAP> saves PC, MSR (and TODO SVSTATE), and updates MSR
1580 TRAP function is callable from inside the pseudocode itself,
1581 hence the default arguments. when calling from inside ISACaller
1582 it is best to use call_trap()
1584 trap_addr: int | SelectableInt
1585 the address to go to (before any modifications from `KAIVB`)
1586 trap_bit: int | None
1587 the bit in `SRR1` to set, `None` means don't set any bits.
1589 if isinstance(trap_addr
, SelectableInt
):
1590 trap_addr
= trap_addr
.value
1591 # https://bugs.libre-soc.org/show_bug.cgi?id=859
1592 kaivb
= self
.spr
['KAIVB'].value
1593 msr
= self
.namespace
['MSR'].value
1594 log("TRAP:", hex(trap_addr
), hex(msr
), "kaivb", hex(kaivb
))
1595 # store CIA(+4?) in SRR0, set NIA to 0x700
1596 # store MSR in SRR1, set MSR to um errr something, have to check spec
1597 # store SVSTATE (if enabled) in SVSRR0
1598 self
.spr
['SRR0'].value
= self
.pc
.CIA
.value
1599 self
.spr
['SRR1'].value
= msr
1600 if self
.is_svp64_mode
:
1601 self
.spr
['SVSRR0'] = self
.namespace
['SVSTATE'].value
1602 self
.trap_nia
= SelectableInt(trap_addr |
(kaivb
& ~
0x1fff), 64)
1603 if trap_bit
is not None:
1604 self
.spr
['SRR1'][trap_bit
] = 1 # change *copy* of MSR in SRR1
1606 # set exception bits. TODO: this should, based on the address
1607 # in figure 66 p1065 V3.0B and the table figure 65 p1063 set these
1608 # bits appropriately. however it turns out that *for now* in all
1609 # cases (all trap_addrs) the exact same thing is needed.
1610 self
.msr
[MSRb
.IR
] = 0
1611 self
.msr
[MSRb
.DR
] = 0
1612 self
.msr
[MSRb
.FE0
] = 0
1613 self
.msr
[MSRb
.FE1
] = 0
1614 self
.msr
[MSRb
.EE
] = 0
1615 self
.msr
[MSRb
.RI
] = 0
1616 self
.msr
[MSRb
.SF
] = 1
1617 self
.msr
[MSRb
.TM
] = 0
1618 self
.msr
[MSRb
.VEC
] = 0
1619 self
.msr
[MSRb
.VSX
] = 0
1620 self
.msr
[MSRb
.PR
] = 0
1621 self
.msr
[MSRb
.FP
] = 0
1622 self
.msr
[MSRb
.PMM
] = 0
1623 self
.msr
[MSRb
.TEs
] = 0
1624 self
.msr
[MSRb
.TEe
] = 0
1625 self
.msr
[MSRb
.UND
] = 0
1626 self
.msr
[MSRb
.LE
] = 1
1628 def memassign(self
, ea
, sz
, val
):
1629 self
.mem
.memassign(ea
, sz
, val
)
1631 def prep_namespace(self
, insn_name
, formname
, op_fields
, xlen
):
1632 # TODO: get field names from form in decoder*1* (not decoder2)
1633 # decoder2 is hand-created, and decoder1.sigform is auto-generated
1635 # then "yield" fields only from op_fields rather than hard-coded
1637 fields
= self
.decoder
.sigforms
[formname
]
1638 log("prep_namespace", formname
, op_fields
, insn_name
)
1639 for name
in op_fields
:
1640 # CR immediates. deal with separately. needs modifying
1642 if self
.is_svp64_mode
and name
in ['BI']: # TODO, more CRs
1643 # BI is a 5-bit, must reconstruct the value
1644 regnum
, is_vec
= yield from get_cr_in(self
.dec2
, name
)
1645 sig
= getattr(fields
, name
)
1647 # low 2 LSBs (CR field selector) remain same, CR num extended
1648 assert regnum
<= 7, "sigh, TODO, 128 CR fields"
1649 val
= (val
& 0b11) |
(regnum
<< 2)
1650 elif self
.is_svp64_mode
and name
in ['BFA']: # TODO, more CRs
1651 regnum
, is_vec
= yield from get_cr_in(self
.dec2
, name
)
1652 log('hack %s' % name
, regnum
, is_vec
)
1654 elif self
.is_svp64_mode
and name
in ['BF']: # TODO, more CRs
1655 regnum
, is_vec
= yield from get_cr_out(self
.dec2
, "BF")
1656 log('hack %s' % name
, regnum
, is_vec
)
1659 sig
= getattr(fields
, name
)
1661 # these are all opcode fields involved in index-selection of CR,
1662 # and need to do "standard" arithmetic. CR[BA+32] for example
1663 # would, if using SelectableInt, only be 5-bit.
1664 if name
in ['BF', 'BFA', 'BC', 'BA', 'BB', 'BT', 'BI']:
1665 self
.namespace
[name
] = val
1667 self
.namespace
[name
] = SelectableInt(val
, sig
.width
)
1669 self
.namespace
['XER'] = self
.spr
['XER']
1670 self
.namespace
['CA'] = self
.spr
['XER'][XER_bits
['CA']].value
1671 self
.namespace
['CA32'] = self
.spr
['XER'][XER_bits
['CA32']].value
1672 self
.namespace
['OV'] = self
.spr
['XER'][XER_bits
['OV']].value
1673 self
.namespace
['OV32'] = self
.spr
['XER'][XER_bits
['OV32']].value
1674 self
.namespace
['XLEN'] = xlen
1675 self
.namespace
['RESERVE'] = self
.reserve
1676 self
.namespace
['RESERVE_ADDR'] = self
.reserve_addr
1677 self
.namespace
['RESERVE_LENGTH'] = self
.reserve_length
1679 # add some SVSTATE convenience variables
1680 vl
= self
.svstate
.vl
1681 srcstep
= self
.svstate
.srcstep
1682 self
.namespace
['VL'] = vl
1683 self
.namespace
['srcstep'] = srcstep
1685 # take a copy of the CR field value: if non-VLi fail-first fails
1686 # this is because the pseudocode writes *directly* to CR. sigh
1687 self
.cr_backup
= self
.cr
.value
1689 # sv.bc* need some extra fields
1690 if not self
.is_svp64_mode
or not insn_name
.startswith("sv.bc"):
1693 # blegh grab bits manually
1694 mode
= yield self
.dec2
.rm_dec
.rm_in
.mode
1695 # convert to SelectableInt before test
1696 mode
= SelectableInt(mode
, 5)
1697 bc_vlset
= mode
[SVP64MODEb
.BC_VLSET
] != 0
1698 bc_vli
= mode
[SVP64MODEb
.BC_VLI
] != 0
1699 bc_snz
= mode
[SVP64MODEb
.BC_SNZ
] != 0
1700 bc_vsb
= yield self
.dec2
.rm_dec
.bc_vsb
1701 bc_ctrtest
= yield self
.dec2
.rm_dec
.bc_ctrtest
1702 bc_lru
= yield self
.dec2
.rm_dec
.bc_lru
1703 bc_gate
= yield self
.dec2
.rm_dec
.bc_gate
1704 sz
= yield self
.dec2
.rm_dec
.pred_sz
1705 self
.namespace
['mode'] = SelectableInt(mode
, 5)
1706 self
.namespace
['ALL'] = SelectableInt(bc_gate
, 1)
1707 self
.namespace
['VSb'] = SelectableInt(bc_vsb
, 1)
1708 self
.namespace
['LRu'] = SelectableInt(bc_lru
, 1)
1709 self
.namespace
['CTRtest'] = SelectableInt(bc_ctrtest
, 1)
1710 self
.namespace
['VLSET'] = SelectableInt(bc_vlset
, 1)
1711 self
.namespace
['VLI'] = SelectableInt(bc_vli
, 1)
1712 self
.namespace
['sz'] = SelectableInt(sz
, 1)
1713 self
.namespace
['SNZ'] = SelectableInt(bc_snz
, 1)
1715 def get_kludged_op_add_ca_ov(self
, inputs
, inp_ca_ov
):
1716 """ this was not at all necessary to do. this function massively
1717 duplicates - in a laborious and complex fashion - the contents of
1718 the CSV files that were extracted two years ago from microwatt's
1719 source code. A-inversion is the "inv A" column, output inversion
1720 is the "inv out" column, carry-in equal to 0 or 1 or CA is the
1723 all of that information is available in
1724 self.instrs[ins_name].op_fields
1725 where info is usually assigned to self.instrs[ins_name]
1727 https://git.libre-soc.org/?p=openpower-isa.git;a=blob;f=openpower/isatables/minor_31.csv;hb=HEAD
1729 the immediate constants are *also* decoded correctly and placed
1730 usually by DecodeIn2Imm into operand2, as part of power_decoder2.py
1732 def ca(a
, b
, ca_in
, width
):
1733 mask
= (1 << width
) - 1
1734 y
= (a
& mask
) + (b
& mask
) + ca_in
1737 asmcode
= yield self
.dec2
.dec
.op
.asmcode
1738 insn
= insns
.get(asmcode
)
1739 SI
= yield self
.dec2
.dec
.SI
1742 inputs
= [i
.value
for i
in inputs
]
1745 if insn
in ("add", "addo", "addc", "addco"):
1749 elif insn
== "addic" or insn
== "addic.":
1753 elif insn
in ("subf", "subfo", "subfc", "subfco"):
1757 elif insn
== "subfic":
1761 elif insn
== "adde" or insn
== "addeo":
1765 elif insn
== "subfe" or insn
== "subfeo":
1769 elif insn
== "addme" or insn
== "addmeo":
1773 elif insn
== "addze" or insn
== "addzeo":
1777 elif insn
== "subfme" or insn
== "subfmeo":
1781 elif insn
== "subfze" or insn
== "subfzeo":
1785 elif insn
== "addex":
1786 # CA[32] aren't actually written, just generate so we have
1787 # something to return
1788 ca64
= ov64
= ca(inputs
[0], inputs
[1], OV
, 64)
1789 ca32
= ov32
= ca(inputs
[0], inputs
[1], OV
, 32)
1790 return ca64
, ca32
, ov64
, ov32
1791 elif insn
== "neg" or insn
== "nego":
1796 raise NotImplementedError(
1797 "op_add kludge unimplemented instruction: ", asmcode
, insn
)
1799 ca64
= ca(a
, b
, ca_in
, 64)
1800 ca32
= ca(a
, b
, ca_in
, 32)
1801 ov64
= ca64
!= ca(a
, b
, ca_in
, 63)
1802 ov32
= ca32
!= ca(a
, b
, ca_in
, 31)
1803 return ca64
, ca32
, ov64
, ov32
1805 def handle_carry_(self
, inputs
, output
, ca
, ca32
, inp_ca_ov
):
1806 if ca
is not None and ca32
is not None:
1808 op
= yield self
.dec2
.e
.do
.insn_type
1809 if op
== MicrOp
.OP_ADD
.value
and ca
is None and ca32
is None:
1810 retval
= yield from self
.get_kludged_op_add_ca_ov(
1812 ca
, ca32
, ov
, ov32
= retval
1813 asmcode
= yield self
.dec2
.dec
.op
.asmcode
1814 if insns
.get(asmcode
) == 'addex':
1815 # TODO: if 32-bit mode, set ov to ov32
1816 self
.spr
['XER'][XER_bits
['OV']] = ov
1817 self
.spr
['XER'][XER_bits
['OV32']] = ov32
1818 log(f
"write OV/OV32 OV={ov} OV32={ov32}",
1819 kind
=LogType
.InstrInOuts
)
1821 # TODO: if 32-bit mode, set ca to ca32
1822 self
.spr
['XER'][XER_bits
['CA']] = ca
1823 self
.spr
['XER'][XER_bits
['CA32']] = ca32
1824 log(f
"write CA/CA32 CA={ca} CA32={ca32}",
1825 kind
=LogType
.InstrInOuts
)
1827 inv_a
= yield self
.dec2
.e
.do
.invert_in
1829 inputs
[0] = ~inputs
[0]
1831 imm_ok
= yield self
.dec2
.e
.do
.imm_data
.ok
1833 imm
= yield self
.dec2
.e
.do
.imm_data
.data
1834 inputs
.append(SelectableInt(imm
, 64))
1837 log("gt input", x
, output
)
1838 gt
= (gtu(x
, output
))
1841 cy
= 1 if any(gts
) else 0
1843 if ca
is None: # already written
1844 self
.spr
['XER'][XER_bits
['CA']] = cy
1847 # ARGH... different for OP_ADD... *sigh*...
1848 op
= yield self
.dec2
.e
.do
.insn_type
1849 if op
== MicrOp
.OP_ADD
.value
:
1850 res32
= (output
.value
& (1 << 32)) != 0
1851 a32
= (inputs
[0].value
& (1 << 32)) != 0
1852 if len(inputs
) >= 2:
1853 b32
= (inputs
[1].value
& (1 << 32)) != 0
1856 cy32
= res32 ^ a32 ^ b32
1857 log("CA32 ADD", cy32
)
1861 log("input", x
, output
)
1862 log(" x[32:64]", x
, x
[32:64])
1863 log(" o[32:64]", output
, output
[32:64])
1864 gt
= (gtu(x
[32:64], output
[32:64])) == SelectableInt(1, 1)
1866 cy32
= 1 if any(gts
) else 0
1867 log("CA32", cy32
, gts
)
1868 if ca32
is None: # already written
1869 self
.spr
['XER'][XER_bits
['CA32']] = cy32
1871 def handle_overflow(self
, inputs
, output
, div_overflow
, inp_ca_ov
):
1872 op
= yield self
.dec2
.e
.do
.insn_type
1873 if op
== MicrOp
.OP_ADD
.value
:
1874 retval
= yield from self
.get_kludged_op_add_ca_ov(
1876 ca
, ca32
, ov
, ov32
= retval
1877 # TODO: if 32-bit mode, set ov to ov32
1878 self
.spr
['XER'][XER_bits
['OV']] = ov
1879 self
.spr
['XER'][XER_bits
['OV32']] = ov32
1880 self
.spr
['XER'][XER_bits
['SO']] |
= ov
1882 if hasattr(self
.dec2
.e
.do
, "invert_in"):
1883 inv_a
= yield self
.dec2
.e
.do
.invert_in
1885 inputs
[0] = ~inputs
[0]
1887 imm_ok
= yield self
.dec2
.e
.do
.imm_data
.ok
1889 imm
= yield self
.dec2
.e
.do
.imm_data
.data
1890 inputs
.append(SelectableInt(imm
, 64))
1891 log("handle_overflow", inputs
, output
, div_overflow
)
1892 if len(inputs
) < 2 and div_overflow
is None:
1895 # div overflow is different: it's returned by the pseudo-code
1896 # because it's more complex than can be done by analysing the output
1897 if div_overflow
is not None:
1898 ov
, ov32
= div_overflow
, div_overflow
1899 # arithmetic overflow can be done by analysing the input and output
1900 elif len(inputs
) >= 2:
1902 input_sgn
= [exts(x
.value
, x
.bits
) < 0 for x
in inputs
]
1903 output_sgn
= exts(output
.value
, output
.bits
) < 0
1904 ov
= 1 if input_sgn
[0] == input_sgn
[1] and \
1905 output_sgn
!= input_sgn
[0] else 0
1908 input32_sgn
= [exts(x
.value
, 32) < 0 for x
in inputs
]
1909 output32_sgn
= exts(output
.value
, 32) < 0
1910 ov32
= 1 if input32_sgn
[0] == input32_sgn
[1] and \
1911 output32_sgn
!= input32_sgn
[0] else 0
1913 # now update XER OV/OV32/SO
1914 so
= self
.spr
['XER'][XER_bits
['SO']]
1915 new_so
= so | ov
# sticky overflow ORs in old with new
1916 self
.spr
['XER'][XER_bits
['OV']] = ov
1917 self
.spr
['XER'][XER_bits
['OV32']] = ov32
1918 self
.spr
['XER'][XER_bits
['SO']] = new_so
1919 log(" set overflow", ov
, ov32
, so
, new_so
)
1921 def handle_comparison(self
, out
, cr_idx
=0, overflow
=None, no_so
=False):
1922 assert isinstance(out
, SelectableInt
), \
1923 "out zero not a SelectableInt %s" % repr(outputs
)
1924 log("handle_comparison", out
.bits
, hex(out
.value
))
1925 # TODO - XXX *processor* in 32-bit mode
1926 # https://bugs.libre-soc.org/show_bug.cgi?id=424
1928 # o32 = exts(out.value, 32)
1929 # print ("handle_comparison exts 32 bit", hex(o32))
1930 out
= exts(out
.value
, out
.bits
)
1931 log("handle_comparison exts", hex(out
))
1932 # create the three main CR flags, EQ GT LT
1933 zero
= SelectableInt(out
== 0, 1)
1934 positive
= SelectableInt(out
> 0, 1)
1935 negative
= SelectableInt(out
< 0, 1)
1936 # get (or not) XER.SO. for setvl this is important *not* to read SO
1938 SO
= SelectableInt(1, 0)
1940 SO
= self
.spr
['XER'][XER_bits
['SO']]
1941 log("handle_comparison SO", SO
.value
,
1942 "overflow", overflow
,
1944 "+ve", positive
.value
,
1945 "-ve", negative
.value
)
1946 # alternative overflow checking (setvl mainly at the moment)
1947 if overflow
is not None and overflow
== 1:
1948 SO
= SelectableInt(1, 1)
1949 # create the four CR field values and set the required CR field
1950 cr_field
= selectconcat(negative
, positive
, zero
, SO
)
1951 log("handle_comparison cr_field", self
.cr
, cr_idx
, cr_field
)
1952 self
.crl
[cr_idx
].eq(cr_field
)
1955 def set_pc(self
, pc_val
):
1956 self
.namespace
['NIA'] = SelectableInt(pc_val
, 64)
1957 self
.pc
.update(self
.namespace
, self
.is_svp64_mode
)
1959 def get_next_insn(self
):
1960 """check instruction
1963 pc
= self
.pc
.CIA
.value
1966 ins
= self
.imem
.ld(pc
, 4, False, True, instr_fetch
=True)
1968 raise KeyError("no instruction at 0x%x" % pc
)
1971 def setup_one(self
):
1972 """set up one instruction
1974 pc
, insn
= self
.get_next_insn()
1975 yield from self
.setup_next_insn(pc
, insn
)
1977 # cache since it's really slow to construct
1978 __PREFIX_CACHE
= SVP64Instruction
.Prefix(SelectableInt(value
=0, bits
=32))
1980 def __decode_prefix(self
, opcode
):
1981 pfx
= self
.__PREFIX
_CACHE
1982 pfx
.storage
.eq(opcode
)
1985 def setup_next_insn(self
, pc
, ins
):
1986 """set up next instruction
1989 log("setup: 0x%x 0x%x %s" % (pc
, ins
& 0xffffffff, bin(ins
)))
1990 log("CIA NIA", self
.respect_pc
, self
.pc
.CIA
.value
, self
.pc
.NIA
.value
)
1992 yield self
.dec2
.sv_rm
.eq(0)
1993 yield self
.dec2
.dec
.raw_opcode_in
.eq(ins
& 0xffffffff)
1994 yield self
.dec2
.dec
.bigendian
.eq(self
.bigendian
)
1995 yield self
.dec2
.state
.msr
.eq(self
.msr
.value
)
1996 yield self
.dec2
.state
.pc
.eq(pc
)
1997 if self
.svstate
is not None:
1998 yield self
.dec2
.state
.svstate
.eq(self
.svstate
.value
)
2000 # SVP64. first, check if the opcode is EXT001, and SVP64 id bits set
2002 opcode
= yield self
.dec2
.dec
.opcode_in
2003 opcode
= SelectableInt(value
=opcode
, bits
=32)
2004 pfx
= self
.__decode
_prefix
(opcode
)
2005 log("prefix test: opcode:", pfx
.PO
, bin(pfx
.PO
), pfx
.id)
2006 self
.is_svp64_mode
= bool((pfx
.PO
== 0b000001) and (pfx
.id == 0b11))
2007 self
.pc
.update_nia(self
.is_svp64_mode
)
2009 yield self
.dec2
.is_svp64_mode
.eq(self
.is_svp64_mode
)
2010 self
.namespace
['NIA'] = self
.pc
.NIA
2011 self
.namespace
['SVSTATE'] = self
.svstate
2012 if not self
.is_svp64_mode
:
2015 # in SVP64 mode. decode/print out svp64 prefix, get v3.0B instruction
2016 log("svp64.rm", bin(pfx
.rm
))
2017 log(" svstate.vl", self
.svstate
.vl
)
2018 log(" svstate.mvl", self
.svstate
.maxvl
)
2019 ins
= self
.imem
.ld(pc
+4, 4, False, True, instr_fetch
=True)
2020 log(" svsetup: 0x%x 0x%x %s" % (pc
+4, ins
& 0xffffffff, bin(ins
)))
2021 yield self
.dec2
.dec
.raw_opcode_in
.eq(ins
& 0xffffffff) # v3.0B suffix
2022 yield self
.dec2
.sv_rm
.eq(int(pfx
.rm
)) # svp64 prefix
2025 def execute_one(self
):
2026 """execute one instruction
2028 # get the disassembly code for this instruction
2029 if not self
.disassembly
:
2030 code
= yield from self
.get_assembly_name()
2033 if self
.is_svp64_mode
:
2034 offs
, dbg
= 4, "svp64 "
2035 code
= self
.disassembly
[self
._pc
+offs
]
2036 log(" %s sim-execute" % dbg
, hex(self
._pc
), code
)
2037 opname
= code
.split(' ')[0]
2039 yield from self
.call(opname
) # execute the instruction
2040 except MemException
as e
: # check for memory errors
2041 if e
.args
[0] == 'unaligned': # alignment error
2042 # run a Trap but set DAR first
2043 print("memory unaligned exception, DAR", e
.dar
, repr(e
))
2044 self
.spr
['DAR'] = SelectableInt(e
.dar
, 64)
2045 self
.call_trap(0x600, PIb
.PRIV
) # 0x600, privileged
2047 elif e
.args
[0] == 'invalid': # invalid
2048 # run a Trap but set DAR first
2049 log("RADIX MMU memory invalid error, mode %s" % e
.mode
)
2050 if e
.mode
== 'EXECUTE':
2051 # XXX TODO: must set a few bits in SRR1,
2052 # see microwatt loadstore1.vhdl
2053 # if m_in.segerr = '0' then
2054 # v.srr1(47 - 33) := m_in.invalid;
2055 # v.srr1(47 - 35) := m_in.perm_error; -- noexec fault
2056 # v.srr1(47 - 44) := m_in.badtree;
2057 # v.srr1(47 - 45) := m_in.rc_error;
2058 # v.intr_vec := 16#400#;
2060 # v.intr_vec := 16#480#;
2061 self
.call_trap(0x400, PIb
.PRIV
) # 0x400, privileged
2063 self
.call_trap(0x300, PIb
.PRIV
) # 0x300, privileged
2065 # not supported yet:
2066 raise e
# ... re-raise
2068 # append to the trace log file
2069 self
.trace(" # %s\n" % code
)
2071 log("gprs after code", code
)
2074 for i
in range(len(self
.crl
)):
2075 crs
.append(bin(self
.crl
[i
].asint()))
2076 log("crs", " ".join(crs
))
2077 log("vl,maxvl", self
.svstate
.vl
, self
.svstate
.maxvl
)
2079 # don't use this except in special circumstances
2080 if not self
.respect_pc
:
2083 log("execute one, CIA NIA", hex(self
.pc
.CIA
.value
),
2084 hex(self
.pc
.NIA
.value
))
2086 def get_assembly_name(self
):
2087 # TODO, asmregs is from the spec, e.g. add RT,RA,RB
2088 # see http://bugs.libre-riscv.org/show_bug.cgi?id=282
2089 dec_insn
= yield self
.dec2
.e
.do
.insn
2090 insn_1_11
= yield self
.dec2
.e
.do
.insn
[1:11]
2091 asmcode
= yield self
.dec2
.dec
.op
.asmcode
2092 int_op
= yield self
.dec2
.dec
.op
.internal_op
2093 log("get assembly name asmcode", asmcode
, int_op
,
2094 hex(dec_insn
), bin(insn_1_11
))
2095 asmop
= insns
.get(asmcode
, None)
2097 # sigh reconstruct the assembly instruction name
2098 if hasattr(self
.dec2
.e
.do
, "oe"):
2099 ov_en
= yield self
.dec2
.e
.do
.oe
.oe
2100 ov_ok
= yield self
.dec2
.e
.do
.oe
.ok
2104 if hasattr(self
.dec2
.e
.do
, "rc"):
2105 rc_en
= yield self
.dec2
.e
.do
.rc
.rc
2106 rc_ok
= yield self
.dec2
.e
.do
.rc
.ok
2110 # annoying: ignore rc_ok if RC1 is set (for creating *assembly name*)
2111 RC1
= yield self
.dec2
.rm_dec
.RC1
2115 # grrrr have to special-case MUL op (see DecodeOE)
2116 log("ov %d en %d rc %d en %d op %d" %
2117 (ov_ok
, ov_en
, rc_ok
, rc_en
, int_op
))
2118 if int_op
in [MicrOp
.OP_MUL_H64
.value
, MicrOp
.OP_MUL_H32
.value
]:
2123 if not asmop
.endswith("."): # don't add "." to "andis."
2126 if hasattr(self
.dec2
.e
.do
, "lk"):
2127 lk
= yield self
.dec2
.e
.do
.lk
2130 log("int_op", int_op
)
2131 if int_op
in [MicrOp
.OP_B
.value
, MicrOp
.OP_BC
.value
]:
2132 AA
= yield self
.dec2
.dec
.fields
.FormI
.AA
[0:-1]
2136 spr_msb
= yield from self
.get_spr_msb()
2137 if int_op
== MicrOp
.OP_MFCR
.value
:
2142 # XXX TODO: for whatever weird reason this doesn't work
2143 # https://bugs.libre-soc.org/show_bug.cgi?id=390
2144 if int_op
== MicrOp
.OP_MTCRF
.value
:
2151 def reset_remaps(self
):
2152 self
.remap_loopends
= [0] * 4
2153 self
.remap_idxs
= [0, 1, 2, 3]
2155 def get_remap_indices(self
):
2156 """WARNING, this function stores remap_idxs and remap_loopends
2157 in the class for later use. this to avoid problems with yield
2159 # go through all iterators in lock-step, advance to next remap_idx
2160 srcstep
, dststep
, ssubstep
, dsubstep
= self
.get_src_dststeps()
2161 # get four SVSHAPEs. here we are hard-coding
2163 SVSHAPE0
= self
.spr
['SVSHAPE0']
2164 SVSHAPE1
= self
.spr
['SVSHAPE1']
2165 SVSHAPE2
= self
.spr
['SVSHAPE2']
2166 SVSHAPE3
= self
.spr
['SVSHAPE3']
2167 # set up the iterators
2168 remaps
= [(SVSHAPE0
, SVSHAPE0
.get_iterator()),
2169 (SVSHAPE1
, SVSHAPE1
.get_iterator()),
2170 (SVSHAPE2
, SVSHAPE2
.get_iterator()),
2171 (SVSHAPE3
, SVSHAPE3
.get_iterator()),
2175 for i
, (shape
, remap
) in enumerate(remaps
):
2176 # zero is "disabled"
2177 if shape
.value
== 0x0:
2178 self
.remap_idxs
[i
] = 0
2179 # pick src or dststep depending on reg num (0-2=in, 3-4=out)
2180 step
= dststep
if (i
in [3, 4]) else srcstep
2181 # this is terrible. O(N^2) looking for the match. but hey.
2182 for idx
, (remap_idx
, loopends
) in enumerate(remap
):
2185 self
.remap_idxs
[i
] = remap_idx
2186 self
.remap_loopends
[i
] = loopends
2187 dbg
.append((i
, step
, remap_idx
, loopends
))
2188 for (i
, step
, remap_idx
, loopends
) in dbg
:
2189 log("SVSHAPE %d idx, end" % i
, step
, remap_idx
, bin(loopends
))
2192 def get_spr_msb(self
):
2193 dec_insn
= yield self
.dec2
.e
.do
.insn
2194 return dec_insn
& (1 << 20) != 0 # sigh - XFF.spr[-1]?
2196 def call(self
, name
, syscall_emu_active
=False):
2197 """call(opcode) - the primary execution point for instructions
2199 self
.last_st_addr
= None # reset the last known store address
2200 self
.last_ld_addr
= None # etc.
2202 ins_name
= name
.strip() # remove spaces if not already done so
2204 log("halted - not executing", ins_name
)
2207 # TODO, asmregs is from the spec, e.g. add RT,RA,RB
2208 # see http://bugs.libre-riscv.org/show_bug.cgi?id=282
2209 asmop
= yield from self
.get_assembly_name()
2210 log("call", ins_name
, asmop
,
2211 kind
=LogType
.InstrInOuts
)
2213 # sv.setvl is *not* a loop-function. sigh
2214 log("is_svp64_mode", self
.is_svp64_mode
, asmop
)
2217 int_op
= yield self
.dec2
.dec
.op
.internal_op
2218 spr_msb
= yield from self
.get_spr_msb()
2220 instr_is_privileged
= False
2221 if int_op
in [MicrOp
.OP_ATTN
.value
,
2222 MicrOp
.OP_MFMSR
.value
,
2223 MicrOp
.OP_MTMSR
.value
,
2224 MicrOp
.OP_MTMSRD
.value
,
2226 MicrOp
.OP_RFID
.value
]:
2227 instr_is_privileged
= True
2228 if int_op
in [MicrOp
.OP_MFSPR
.value
,
2229 MicrOp
.OP_MTSPR
.value
] and spr_msb
:
2230 instr_is_privileged
= True
2232 # check MSR priv bit and whether op is privileged: if so, throw trap
2233 PR
= self
.msr
[MSRb
.PR
]
2234 log("is priv", instr_is_privileged
, hex(self
.msr
.value
), PR
)
2235 if instr_is_privileged
and PR
== 1:
2236 self
.call_trap(0x700, PIb
.PRIV
)
2239 # check halted condition
2240 if ins_name
== 'attn':
2244 # User mode system call emulation consists of several steps:
2245 # 1. Detect whether instruction is sc or scv.
2246 # 2. Call the HDL implementation which invokes trap.
2247 # 3. Reroute the guest system call to host system call.
2248 # 4. Force return from the interrupt as if we had guest OS.
2249 # FIXME: enable PPC_FEATURE2_SCV in mem.py DEFAULT_AT_HWCAP2 when
2250 # scv emulation works.
2251 if ((asmop
in ("sc", "scv")) and
2252 (self
.syscall
is not None) and
2253 not syscall_emu_active
):
2254 # Memoize PC and trigger an interrupt
2256 pc
= self
.pc
.CIA
.value
2259 yield from self
.call(asmop
, syscall_emu_active
=True)
2261 # Reroute the syscall to host OS
2262 identifier
= self
.gpr(0)
2263 arguments
= map(self
.gpr
, range(3, 9))
2264 result
= self
.syscall(identifier
, *arguments
)
2265 self
.gpr
.write(3, result
, False, self
.namespace
["XLEN"])
2267 # Return from interrupt
2268 yield from self
.call("rfid", syscall_emu_active
=True)
2270 elif ((name
in ("rfid", "hrfid")) and syscall_emu_active
):
2273 # check illegal instruction
2275 if ins_name
not in ['mtcrf', 'mtocrf']:
2276 illegal
= ins_name
!= asmop
2278 # list of instructions not being supported by binutils (.long)
2279 dotstrp
= asmop
[:-1] if asmop
[-1] == '.' else asmop
2280 if dotstrp
in [*FPTRANS_INSNS
,
2282 'ffmadds', 'fdmadds', 'ffadds',
2284 "brh", "brw", "brd",
2285 'setvl', 'svindex', 'svremap', 'svstep',
2286 'svshape', 'svshape2',
2287 'ternlogi', 'bmask', 'cprop', 'gbbd',
2288 'absdu', 'absds', 'absdacs', 'absdacu', 'avgadd',
2289 'fmvis', 'fishmv', 'pcdec', "maddedu", "divmod2du",
2290 "dsld", "dsrd", "maddedus",
2291 "sadd", "saddw", "sadduw",
2296 "maddsubrs", "maddrs", "msubrs",
2297 "cfuged", "cntlzdm", "cnttzdm", "pdepd", "pextd",
2298 "setbc", "setbcr", "setnbc", "setnbcr",
2303 # match against instructions treated as nop, see nop below
2304 if asmop
.startswith("dcbt"):
2308 # branch-conditional redirects to sv.bc
2309 if asmop
.startswith('bc') and self
.is_svp64_mode
:
2310 ins_name
= 'sv.%s' % ins_name
2312 # ld-immediate-with-pi mode redirects to ld-with-postinc
2313 ldst_imm_postinc
= False
2314 if 'u' in ins_name
and self
.is_svp64_mode
:
2315 ldst_pi
= yield self
.dec2
.rm_dec
.ldst_postinc
2317 ins_name
= ins_name
.replace("u", "up")
2318 ldst_imm_postinc
= True
2319 log(" enable ld/st postinc", ins_name
)
2321 log(" post-processed name", dotstrp
, ins_name
, asmop
)
2323 # illegal instructions call TRAP at 0x700
2325 print("illegal", ins_name
, asmop
)
2326 self
.call_trap(0x700, PIb
.ILLEG
)
2327 print("name %s != %s - calling ILLEGAL trap, PC: %x" %
2328 (ins_name
, asmop
, self
.pc
.CIA
.value
))
2331 # this is for setvl "Vertical" mode: if set true,
2332 # srcstep/dststep is explicitly advanced. mode says which SVSTATE to
2333 # test for Rc=1 end condition. 3 bits of all 3 loops are put into CR0
2334 self
.allow_next_step_inc
= False
2335 self
.svstate_next_mode
= 0
2337 # nop has to be supported, we could let the actual op calculate
2338 # but PowerDecoder has a pattern for nop
2339 if ins_name
== 'nop':
2340 self
.update_pc_next()
2343 # get elwidths, defaults to 64
2347 if self
.is_svp64_mode
:
2348 ew_src
= yield self
.dec2
.rm_dec
.ew_src
2349 ew_dst
= yield self
.dec2
.rm_dec
.ew_dst
2350 ew_src
= 8 << (3-int(ew_src
)) # convert to bitlength
2351 ew_dst
= 8 << (3-int(ew_dst
)) # convert to bitlength
2352 xlen
= max(ew_src
, ew_dst
)
2353 log("elwidth", ew_src
, ew_dst
)
2354 log("XLEN:", self
.is_svp64_mode
, xlen
)
2356 # look up instruction in ISA.instrs, prepare namespace
2357 if ins_name
== 'pcdec': # grrrr yes there are others ("stbcx." etc.)
2358 info
= self
.instrs
[ins_name
+"."]
2359 elif asmop
[-1] == '.' and asmop
in self
.instrs
:
2360 info
= self
.instrs
[asmop
]
2362 info
= self
.instrs
[ins_name
]
2363 yield from self
.prep_namespace(ins_name
, info
.form
, info
.op_fields
,
2366 # dict retains order
2367 inputs
= dict.fromkeys(create_full_args(
2368 read_regs
=info
.read_regs
, special_regs
=info
.special_regs
,
2369 uninit_regs
=info
.uninit_regs
, write_regs
=info
.write_regs
))
2371 # preserve order of register names
2372 write_without_special_regs
= OrderedSet(info
.write_regs
)
2373 write_without_special_regs
-= OrderedSet(info
.special_regs
)
2374 input_names
= create_args([
2375 *info
.read_regs
, *info
.uninit_regs
, *write_without_special_regs
])
2376 log("input names", input_names
)
2378 # get SVP64 entry for the current instruction
2379 sv_rm
= self
.svp64rm
.instrs
.get(ins_name
)
2380 if sv_rm
is not None:
2381 dest_cr
, src_cr
, src_byname
, dest_byname
= decode_extra(sv_rm
)
2383 dest_cr
, src_cr
, src_byname
, dest_byname
= False, False, {}, {}
2384 log("sv rm", sv_rm
, dest_cr
, src_cr
, src_byname
, dest_byname
)
2386 # see if srcstep/dststep need skipping over masked-out predicate bits
2387 # svstep also needs advancement because it calls SVSTATE_NEXT.
2388 # bit the remaps get computed just after pre_inc moves them on
2389 # with remap_set_steps substituting for PowerDecider2 not doing it,
2390 # and SVSTATE_NEXT not being able to.use yield, the preinc on
2391 # svstep is necessary for now.
2393 if (self
.is_svp64_mode
or ins_name
in ['svstep']):
2394 yield from self
.svstate_pre_inc()
2395 if self
.is_svp64_mode
:
2396 pre
= yield from self
.update_new_svstate_steps()
2398 self
.svp64_reset_loop()
2400 self
.update_pc_next()
2402 srcstep
, dststep
, ssubstep
, dsubstep
= self
.get_src_dststeps()
2403 pred_dst_zero
= self
.pred_dst_zero
2404 pred_src_zero
= self
.pred_src_zero
2405 vl
= self
.svstate
.vl
2406 subvl
= yield self
.dec2
.rm_dec
.rm_in
.subvl
2408 # VL=0 in SVP64 mode means "do nothing: skip instruction"
2409 if self
.is_svp64_mode
and vl
== 0:
2410 self
.pc
.update(self
.namespace
, self
.is_svp64_mode
)
2411 log("SVP64: VL=0, end of call", self
.namespace
['CIA'],
2412 self
.namespace
['NIA'], kind
=LogType
.InstrInOuts
)
2415 # for when SVREMAP is active, using pre-arranged schedule.
2416 # note: modifying PowerDecoder2 needs to "settle"
2417 remap_en
= self
.svstate
.SVme
2418 persist
= self
.svstate
.RMpst
2419 active
= (persist
or self
.last_op_svshape
) and remap_en
!= 0
2420 if self
.is_svp64_mode
:
2421 yield self
.dec2
.remap_active
.eq(remap_en
if active
else 0)
2423 if persist
or self
.last_op_svshape
:
2424 remaps
= self
.get_remap_indices()
2425 if self
.is_svp64_mode
and (persist
or self
.last_op_svshape
):
2426 yield from self
.remap_set_steps(remaps
)
2427 # after that, settle down (combinatorial) to let Vector reg numbers
2428 # work themselves out
2430 if self
.is_svp64_mode
:
2431 remap_active
= yield self
.dec2
.remap_active
2433 remap_active
= False
2434 log("remap active", bin(remap_active
), self
.is_svp64_mode
)
2436 # LDST does *not* allow elwidth overrides on RA (Effective Address).
2437 # this has to be detected. XXX TODO: RB for ldst-idx *may* need
2438 # conversion (to 64-bit) also.
2439 # see write reg this *HAS* to also override XLEN to 64 on LDST/Update
2440 sv_mode
= yield self
.dec2
.rm_dec
.sv_mode
2441 is_ldst
= (sv_mode
in [SVMode
.LDST_IDX
.value
, SVMode
.LDST_IMM
.value
] \
2442 and self
.is_svp64_mode
)
2443 log("is_ldst", sv_mode
, is_ldst
)
2445 # main input registers (RT, RA ...)
2446 for name
in input_names
:
2447 if name
== "overflow":
2448 inputs
[name
] = SelectableInt(0, 1)
2449 elif name
.startswith("RESERVE"):
2450 inputs
[name
] = getattr(self
, name
)
2451 elif name
== "FPSCR":
2452 inputs
[name
] = self
.FPSCR
2453 elif name
in ("CA", "CA32", "OV", "OV32"):
2454 inputs
[name
] = self
.spr
['XER'][XER_bits
[name
]]
2456 inputs
[name
] = self
.crl
[0]
2457 elif name
in spr_byname
:
2458 inputs
[name
] = self
.spr
[name
]
2459 elif is_ldst
and name
== 'RA':
2460 regval
= (yield from self
.get_input(name
, ew_src
, 64))
2461 log("EA (RA) regval name", name
, regval
)
2462 inputs
[name
] = regval
2464 regval
= (yield from self
.get_input(name
, ew_src
, xlen
))
2465 log("regval name", name
, regval
)
2466 inputs
[name
] = regval
2468 # arrrrgh, awful hack, to get _RT into namespace
2469 if ins_name
in ['setvl', 'svstep']:
2471 RT
= yield self
.dec2
.dec
.RT
2472 self
.namespace
[regname
] = SelectableInt(RT
, 5)
2474 self
.namespace
["RT"] = SelectableInt(0, 5)
2475 regnum
, is_vec
= yield from get_idx_out(self
.dec2
, "RT")
2476 log('hack input reg %s %s' % (name
, str(regnum
)), is_vec
)
2478 # in SVP64 mode for LD/ST work out immediate
2479 # XXX TODO: replace_ds for DS-Form rather than D-Form.
2480 # use info.form to detect
2481 if self
.is_svp64_mode
and not ldst_imm_postinc
:
2482 yield from self
.check_replace_d(info
, remap_active
)
2484 # "special" registers
2485 for special
in info
.special_regs
:
2486 if special
in special_sprs
:
2487 inputs
[special
] = self
.spr
[special
]
2489 inputs
[special
] = self
.namespace
[special
]
2491 # clear trap (trap) NIA
2492 self
.trap_nia
= None
2494 # check if this was an sv.bc* and create an indicator that
2495 # this is the last check to be made as a loop. combined with
2496 # the ALL/ANY mode we can early-exit. note that BI (to test)
2497 # is an input so there is no termination if BI is scalar
2498 # (because early-termination is for *output* scalars)
2499 if self
.is_svp64_mode
and ins_name
.startswith("sv.bc"):
2500 end_loop
= srcstep
== vl
-1 or dststep
== vl
-1
2501 self
.namespace
['end_loop'] = SelectableInt(end_loop
, 1)
2503 inp_ca_ov
= (self
.spr
['XER'][XER_bits
['CA']].value
,
2504 self
.spr
['XER'][XER_bits
['OV']].value
)
2506 for k
, v
in inputs
.items():
2508 v
= SelectableInt(0, self
.XLEN
)
2509 # prevent pseudo-code from modifying input registers
2510 v
= copy_assign_rhs(v
)
2511 if isinstance(v
, SelectableInt
):
2515 # execute actual instruction here (finally)
2516 log("inputs", inputs
)
2517 inputs
= list(inputs
.values())
2518 results
= info
.func(self
, *inputs
)
2519 output_names
= create_args(info
.write_regs
)
2521 # record .ok before anything after the pseudo-code can modify it
2523 for out
, n
in zip(results
or [], output_names
):
2526 if isinstance(out
, SelectableInt
):
2528 log("results", outs
)
2529 log("results ok", outs_ok
)
2531 # "inject" decorator takes namespace from function locals: we need to
2532 # overwrite NIA being overwritten (sigh)
2533 if self
.trap_nia
is not None:
2534 self
.namespace
['NIA'] = self
.trap_nia
2536 log("after func", self
.namespace
['CIA'], self
.namespace
['NIA'])
2538 # check if op was a LD/ST so that debugging can check the
2540 if int_op
in [MicrOp
.OP_STORE
.value
,
2542 self
.last_st_addr
= self
.mem
.last_st_addr
2543 if int_op
in [MicrOp
.OP_LOAD
.value
,
2545 self
.last_ld_addr
= self
.mem
.last_ld_addr
2546 log("op", int_op
, MicrOp
.OP_STORE
.value
, MicrOp
.OP_LOAD
.value
,
2547 self
.last_st_addr
, self
.last_ld_addr
)
2549 # detect if CA/CA32 already in outputs (sra*, basically)
2551 ca32
= outs
.get("CA32")
2553 log("carry already done?", ca
, ca32
, output_names
)
2554 # soc test_pipe_caller tests don't have output_carry
2555 has_output_carry
= hasattr(self
.dec2
.e
.do
, "output_carry")
2556 carry_en
= has_output_carry
and (yield self
.dec2
.e
.do
.output_carry
)
2558 yield from self
.handle_carry_(
2559 inputs
, results
[0], ca
, ca32
, inp_ca_ov
=inp_ca_ov
)
2561 # get output named "overflow" and "CR0"
2562 overflow
= outs
.get('overflow')
2563 cr0
= outs
.get('CR0')
2564 cr1
= outs
.get('CR1')
2566 # soc test_pipe_caller tests don't have oe
2567 has_oe
= hasattr(self
.dec2
.e
.do
, "oe")
2568 # yeah just no. not in parallel processing
2569 if has_oe
and not self
.is_svp64_mode
:
2570 # detect if overflow was in return result
2571 ov_en
= yield self
.dec2
.e
.do
.oe
.oe
2572 ov_ok
= yield self
.dec2
.e
.do
.oe
.ok
2573 log("internal overflow", ins_name
, overflow
, "en?", ov_en
, ov_ok
)
2575 yield from self
.handle_overflow(
2576 inputs
, results
[0], overflow
, inp_ca_ov
=inp_ca_ov
)
2578 # only do SVP64 dest predicated Rc=1 if dest-pred is not enabled
2580 if not self
.is_svp64_mode
or not pred_dst_zero
:
2581 if hasattr(self
.dec2
.e
.do
, "rc"):
2582 rc_en
= yield self
.dec2
.e
.do
.rc
.rc
2583 # don't do Rc=1 for svstep it is handled explicitly.
2584 # XXX TODO: now that CR0 is supported, sort out svstep's pseudocode
2585 # to write directly to CR0 instead of in ISACaller. hooyahh.
2586 if rc_en
and ins_name
not in ['svstep']:
2587 if outs_ok
.get('FPSCR', False):
2588 FPSCR
= outs
['FPSCR']
2591 yield from self
.do_rc_ov(
2592 ins_name
, results
[0], overflow
, cr0
, cr1
, FPSCR
)
2595 ffirst_hit
= False, False
2596 if self
.is_svp64_mode
:
2597 sv_mode
= yield self
.dec2
.rm_dec
.sv_mode
2598 is_cr
= sv_mode
== SVMode
.CROP
.value
2599 chk
= rc_en
or is_cr
2600 if outs_ok
.get('CR', False):
2601 # early write so check_ffirst can see value
2602 self
.namespace
['CR'].eq(outs
['CR'])
2603 ffirst_hit
= (yield from self
.check_ffirst(info
, chk
, srcstep
))
2605 # any modified return results?
2606 yield from self
.do_outregs(
2607 info
, outs
, carry_en
, ffirst_hit
, ew_dst
, outs_ok
)
2609 # check if a FP Exception occurred. TODO for DD-FFirst, check VLi
2610 # and raise the exception *after* if VLi=1 but if VLi=0 then
2611 # truncate and make the exception "disappear".
2612 if self
.FPSCR
.FEX
and (self
.msr
[MSRb
.FE0
] or self
.msr
[MSRb
.FE1
]):
2613 self
.call_trap(0x700, PIb
.FP
)
2616 yield from self
.do_nia(asmop
, ins_name
, rc_en
, ffirst_hit
)
2618 def check_ffirst(self
, info
, rc_en
, srcstep
):
2619 """fail-first mode: checks a bit of Rc Vector, truncates VL
2621 rm_mode
= yield self
.dec2
.rm_dec
.mode
2622 ff_inv
= yield self
.dec2
.rm_dec
.inv
2623 cr_bit
= yield self
.dec2
.rm_dec
.cr_sel
2624 RC1
= yield self
.dec2
.rm_dec
.RC1
2625 vli_
= yield self
.dec2
.rm_dec
.vli
# VL inclusive if truncated
2626 log(" ff rm_mode", rc_en
, rm_mode
, SVP64RMMode
.FFIRST
.value
)
2630 log(" cr_bit", cr_bit
)
2631 log(" rc_en", rc_en
)
2632 ffirst
= yield from is_ffirst_mode(self
.dec2
)
2633 if not rc_en
or not ffirst
:
2635 # get the CR vevtor, do BO-test
2637 log("asmregs", info
.asmregs
[0], info
.write_regs
)
2638 if 'CR' in info
.write_regs
and 'BF' in info
.asmregs
[0]:
2640 regnum
, is_vec
= yield from get_cr_out(self
.dec2
, crf
)
2641 crtest
= self
.crl
[regnum
]
2642 ffirst_hit
= crtest
[cr_bit
] != ff_inv
2643 log("cr test", crf
, regnum
, int(crtest
), crtest
, cr_bit
, ff_inv
)
2644 log("cr test?", ffirst_hit
)
2647 # Fail-first activated, truncate VL
2648 vli
= SelectableInt(int(vli_
), 7)
2649 self
.svstate
.vl
= srcstep
+ vli
2650 yield self
.dec2
.state
.svstate
.eq(self
.svstate
.value
)
2651 yield Settle() # let decoder update
2654 def do_rc_ov(self
, ins_name
, result
, overflow
, cr0
, cr1
, FPSCR
):
2655 cr_out
= yield self
.dec2
.op
.cr_out
2656 if cr_out
== CROutSel
.CR1
.value
:
2660 regnum
, is_vec
= yield from get_cr_out(self
.dec2
, rc_reg
)
2661 # hang on... for `setvl` actually you want to test SVSTATE.VL
2662 is_setvl
= ins_name
in ('svstep', 'setvl')
2664 result
= SelectableInt(result
.vl
, 64)
2666 # overflow = None # do not override overflow except in setvl
2670 cr1
= int(FPSCR
.FX
) << 3
2671 cr1 |
= int(FPSCR
.FEX
) << 2
2672 cr1 |
= int(FPSCR
.VX
) << 1
2673 cr1 |
= int(FPSCR
.OX
)
2674 log("default fp cr1", cr1
)
2676 log("explicit cr1", cr1
)
2677 self
.crl
[regnum
].eq(cr1
)
2679 # if there was not an explicit CR0 in the pseudocode,
2681 c
= self
.handle_comparison(result
, regnum
, overflow
, no_so
=is_setvl
)
2682 log("implicit cr0 %d" % regnum
, c
)
2684 # otherwise we just blat CR0 into the required regnum
2685 log("explicit cr0 %d" % regnum
, cr0
)
2686 self
.crl
[regnum
].eq(cr0
)
2688 def do_outregs(self
, info
, outs
, ca_en
, ffirst_hit
, ew_dst
, outs_ok
):
2689 ffirst_hit
, vli
= ffirst_hit
2690 # write out any regs for this instruction, but only if fail-first is ok
2691 # XXX TODO: allow CR-vector to be written out even if ffirst fails
2692 if not ffirst_hit
or vli
:
2693 for name
, output
in outs
.items():
2694 if not outs_ok
[name
]:
2695 log("skipping writing output with .ok=False", name
, output
)
2697 yield from self
.check_write(info
, name
, output
, ca_en
, ew_dst
)
2698 # restore the CR value on non-VLI failfirst (from sv.cmp and others
2699 # which write directly to CR in the pseudocode (gah, what a mess)
2700 # if ffirst_hit and not vli:
2701 # self.cr.value = self.cr_backup
2703 def do_nia(self
, asmop
, ins_name
, rc_en
, ffirst_hit
):
2704 ffirst_hit
, vli
= ffirst_hit
2706 self
.svp64_reset_loop()
2709 # check advancement of src/dst/sub-steps and if PC needs updating
2710 nia_update
= (yield from self
.check_step_increment(
2711 rc_en
, asmop
, ins_name
))
2713 self
.update_pc_next()
2715 def check_replace_d(self
, info
, remap_active
):
2716 replace_d
= False # update / replace constant in pseudocode
2717 ldstmode
= yield self
.dec2
.rm_dec
.ldstmode
2718 vl
= self
.svstate
.vl
2719 subvl
= yield self
.dec2
.rm_dec
.rm_in
.subvl
2720 srcstep
, dststep
= self
.new_srcstep
, self
.new_dststep
2721 ssubstep
, dsubstep
= self
.new_ssubstep
, self
.new_dsubstep
2722 if info
.form
== 'DS':
2723 # DS-Form, multiply by 4 then knock 2 bits off after
2724 imm
= yield self
.dec2
.dec
.fields
.FormDS
.DS
[0:14] * 4
2726 imm
= yield self
.dec2
.dec
.fields
.FormD
.D
[0:16]
2727 imm
= exts(imm
, 16) # sign-extend to integer
2728 # get the right step. LD is from srcstep, ST is dststep
2729 op
= yield self
.dec2
.e
.do
.insn_type
2731 if op
== MicrOp
.OP_LOAD
.value
:
2733 offsmul
= yield self
.dec2
.in1_step
2734 log("D-field REMAP src", imm
, offsmul
, ldstmode
)
2736 offsmul
= (srcstep
* (subvl
+1)) + ssubstep
2737 log("D-field src", imm
, offsmul
, ldstmode
)
2738 elif op
== MicrOp
.OP_STORE
.value
:
2739 # XXX NOTE! no bit-reversed STORE! this should not ever be used
2740 offsmul
= (dststep
* (subvl
+1)) + dsubstep
2741 log("D-field dst", imm
, offsmul
, ldstmode
)
2742 # Unit-Strided LD/ST adds offset*width to immediate
2743 if ldstmode
== SVP64LDSTmode
.UNITSTRIDE
.value
:
2744 ldst_len
= yield self
.dec2
.e
.do
.data_len
2745 imm
= SelectableInt(imm
+ offsmul
* ldst_len
, 32)
2747 # Element-strided multiplies the immediate by element step
2748 elif ldstmode
== SVP64LDSTmode
.ELSTRIDE
.value
:
2749 imm
= SelectableInt(imm
* offsmul
, 32)
2752 ldst_ra_vec
= yield self
.dec2
.rm_dec
.ldst_ra_vec
2753 ldst_imz_in
= yield self
.dec2
.rm_dec
.ldst_imz_in
2754 log("LDSTmode", SVP64LDSTmode(ldstmode
),
2755 offsmul
, imm
, ldst_ra_vec
, ldst_imz_in
)
2756 # new replacement D... errr.. DS
2758 if info
.form
== 'DS':
2759 # TODO: assert 2 LSBs are zero?
2760 log("DS-Form, TODO, assert 2 LSBs zero?", bin(imm
.value
))
2761 imm
.value
= imm
.value
>> 2
2762 self
.namespace
['DS'] = imm
2764 self
.namespace
['D'] = imm
2766 def get_input(self
, name
, ew_src
, xlen
):
2767 # using PowerDecoder2, first, find the decoder index.
2768 # (mapping name RA RB RC RS to in1, in2, in3)
2769 regnum
, is_vec
= yield from get_idx_in(self
.dec2
, name
, True)
2771 # doing this is not part of svp64, it's because output
2772 # registers, to be modified, need to be in the namespace.
2773 regnum
, is_vec
= yield from get_idx_out(self
.dec2
, name
, True)
2775 regnum
, is_vec
= yield from get_idx_out2(self
.dec2
, name
, True)
2777 if isinstance(regnum
, tuple):
2778 (regnum
, base
, offs
) = regnum
2780 base
, offs
= regnum
, 0 # temporary HACK
2782 # in case getting the register number is needed, _RA, _RB
2783 # (HACK: only in straight non-svp64-mode for now, or elwidth == 64)
2784 regname
= "_" + name
2785 if not self
.is_svp64_mode
or ew_src
== 64:
2786 self
.namespace
[regname
] = regnum
2788 # FIXME: we're trying to access a sub-register, plain register
2789 # numbers don't work for that. for now, just pass something that
2790 # can be compared to 0 and probably will cause an error if misused.
2791 # see https://bugs.libre-soc.org/show_bug.cgi?id=1221
2792 self
.namespace
[regname
] = regnum
* 10000
2794 if not self
.is_svp64_mode
or not self
.pred_src_zero
:
2795 log('reading reg %s %s' % (name
, str(regnum
)), is_vec
)
2797 fval
= self
.fpr(base
, is_vec
, offs
, ew_src
)
2798 reg_val
= SelectableInt(fval
)
2799 assert ew_src
== self
.XLEN
, "TODO fix elwidth conversion"
2800 self
.trace("r:FPR:%d:%d:%d " % (base
, offs
, ew_src
))
2801 log("read fp reg %d/%d: 0x%x" % (base
, offs
, reg_val
.value
),
2802 kind
=LogType
.InstrInOuts
)
2803 elif name
is not None:
2804 gval
= self
.gpr(base
, is_vec
, offs
, ew_src
)
2805 reg_val
= SelectableInt(gval
.value
, bits
=xlen
)
2806 self
.trace("r:GPR:%d:%d:%d " % (base
, offs
, ew_src
))
2807 log("read int reg %d/%d: 0x%x" % (base
, offs
, reg_val
.value
),
2808 kind
=LogType
.InstrInOuts
)
2810 log('zero input reg %s %s' % (name
, str(regnum
)), is_vec
)
2811 reg_val
= SelectableInt(0, ew_src
)
2814 def remap_set_steps(self
, remaps
):
2815 """remap_set_steps sets up the in1/2/3 and out1/2 steps.
2816 they work in concert with PowerDecoder2 at the moment,
2817 there is no HDL implementation of REMAP. therefore this
2818 function, because ISACaller still uses PowerDecoder2,
2819 will *explicitly* write the dec2.XX_step values. this has
2822 # just some convenient debug info
2824 sname
= 'SVSHAPE%d' % i
2825 shape
= self
.spr
[sname
]
2826 log(sname
, bin(shape
.value
))
2827 log(" lims", shape
.lims
)
2828 log(" mode", shape
.mode
)
2829 log(" skip", shape
.skip
)
2831 # set up the list of steps to remap
2832 mi0
= self
.svstate
.mi0
2833 mi1
= self
.svstate
.mi1
2834 mi2
= self
.svstate
.mi2
2835 mo0
= self
.svstate
.mo0
2836 mo1
= self
.svstate
.mo1
2837 steps
= [[self
.dec2
.in1_step
, mi0
], # RA
2838 [self
.dec2
.in2_step
, mi1
], # RB
2839 [self
.dec2
.in3_step
, mi2
], # RC
2840 [self
.dec2
.o_step
, mo0
], # RT
2841 [self
.dec2
.o2_step
, mo1
], # EA
2844 rnames
= ['RA', 'RB', 'RC', 'RT', 'RS']
2845 for i
, reg
in enumerate(rnames
):
2846 idx
= yield from get_idx_map(self
.dec2
, reg
)
2848 idx
= yield from get_idx_map(self
.dec2
, "F"+reg
)
2850 steps
[i
][0] = self
.dec2
.in1_step
2852 steps
[i
][0] = self
.dec2
.in2_step
2854 steps
[i
][0] = self
.dec2
.in3_step
2855 log("remap step", i
, reg
, idx
, steps
[i
][1])
2856 remap_idxs
= self
.remap_idxs
2858 # now cross-index the required SHAPE for each of 3-in 2-out regs
2859 rnames
= ['RA', 'RB', 'RC', 'RT', 'EA']
2860 for i
, (dstep
, shape_idx
) in enumerate(steps
):
2861 (shape
, remap
) = remaps
[shape_idx
]
2862 remap_idx
= remap_idxs
[shape_idx
]
2863 # zero is "disabled"
2864 if shape
.value
== 0x0:
2866 # now set the actual requested step to the current index
2867 if dstep
is not None:
2868 yield dstep
.eq(remap_idx
)
2870 # debug printout info
2871 rremaps
.append((shape
.mode
, hex(shape
.value
), dstep
,
2872 i
, rnames
[i
], shape_idx
, remap_idx
))
2874 log("shape remap", x
)
2876 def check_write(self
, info
, name
, output
, carry_en
, ew_dst
):
2877 if name
== 'overflow': # ignore, done already (above)
2879 if name
== 'CR0': # ignore, done already (above)
2881 if isinstance(output
, int):
2882 output
= SelectableInt(output
, EFFECTIVELY_UNLIMITED
)
2884 if name
.startswith("RESERVE"):
2885 log("write %s 0x%x" % (name
, output
.value
))
2886 getattr(self
, name
).eq(output
)
2888 if name
in ['FPSCR', ]:
2889 log("write FPSCR 0x%x" % (output
.value
))
2890 self
.FPSCR
.eq(output
)
2893 if name
in ['CA', 'CA32']:
2895 log("writing %s to XER" % name
, output
)
2896 log("write XER %s 0x%x" % (name
, output
.value
))
2897 self
.spr
['XER'][XER_bits
[name
]] = output
.value
2899 log("NOT writing %s to XER" % name
, output
)
2901 # write special SPRs
2902 if name
in info
.special_regs
:
2903 log('writing special %s' % name
, output
, special_sprs
)
2904 log("write reg %s 0x%x" % (name
, output
.value
),
2905 kind
=LogType
.InstrInOuts
)
2906 if name
in special_sprs
:
2907 self
.spr
[name
] = output
2909 self
.namespace
[name
].eq(output
)
2911 log('msr written', hex(self
.msr
.value
))
2913 # find out1/out2 PR/FPR
2914 regnum
, is_vec
= yield from get_idx_out(self
.dec2
, name
, True)
2916 regnum
, is_vec
= yield from get_idx_out2(self
.dec2
, name
, True)
2918 # temporary hack for not having 2nd output
2919 regnum
= yield getattr(self
.decoder
, name
)
2921 # convenient debug prefix
2926 # check zeroing due to predicate bit being zero
2927 if self
.is_svp64_mode
and self
.pred_dst_zero
:
2928 log('zeroing reg %s %s' % (str(regnum
), str(output
)), is_vec
)
2929 output
= SelectableInt(0, EFFECTIVELY_UNLIMITED
)
2930 log("write reg %s%s 0x%x ew %d" % (reg_prefix
, str(regnum
),
2931 output
.value
, ew_dst
),
2932 kind
=LogType
.InstrInOuts
)
2933 # zero-extend tov64 bit begore storing (should use EXT oh well)
2934 if output
.bits
> 64:
2935 output
= SelectableInt(output
.value
, 64)
2936 rnum
, base
, offset
= regnum
2938 self
.fpr
.write(regnum
, output
, is_vec
, ew_dst
)
2939 self
.trace("w:FPR:%d:%d:%d " % (rnum
, offset
, ew_dst
))
2942 # LDST/Update does *not* allow elwidths on RA (Effective Address).
2943 # this has to be detected, and overridden. see get_input (related)
2944 sv_mode
= yield self
.dec2
.rm_dec
.sv_mode
2945 is_ldst
= (sv_mode
in [SVMode
.LDST_IDX
.value
, SVMode
.LDST_IMM
.value
] \
2946 and self
.is_svp64_mode
)
2947 if is_ldst
and name
in ['EA', 'RA']:
2948 op
= self
.dec2
.dec
.op
2949 if hasattr(op
, "upd"):
2950 # update mode LD/ST uses read-reg A also as an output
2952 log("write is_ldst is_update", sv_mode
, is_ldst
, upd
)
2953 if upd
== LDSTMode
.update
.value
:
2954 ew_dst
= 64 # override for RA (EA) to 64-bit
2956 self
.gpr
.write(regnum
, output
, is_vec
, ew_dst
)
2957 self
.trace("w:GPR:%d:%d:%d " % (rnum
, offset
, ew_dst
))
2959 def check_step_increment(self
, rc_en
, asmop
, ins_name
):
2960 # check if it is the SVSTATE.src/dest step that needs incrementing
2961 # this is our Sub-Program-Counter loop from 0 to VL-1
2962 if not self
.allow_next_step_inc
:
2963 if self
.is_svp64_mode
:
2964 return (yield from self
.svstate_post_inc(ins_name
))
2966 # XXX only in non-SVP64 mode!
2967 # record state of whether the current operation was an svshape,
2969 # to be able to know if it should apply in the next instruction.
2970 # also (if going to use this instruction) should disable ability
2971 # to interrupt in between. sigh.
2972 self
.last_op_svshape
= asmop
in ['svremap', 'svindex',
2979 log("SVSTATE_NEXT: inc requested, mode",
2980 self
.svstate_next_mode
, self
.allow_next_step_inc
)
2981 yield from self
.svstate_pre_inc()
2982 pre
= yield from self
.update_new_svstate_steps()
2984 # reset at end of loop including exit Vertical Mode
2985 log("SVSTATE_NEXT: end of loop, reset")
2986 self
.svp64_reset_loop()
2987 self
.svstate
.vfirst
= 0
2991 self
.handle_comparison(SelectableInt(0, 64)) # CR0
2993 if self
.allow_next_step_inc
== 2:
2994 log("SVSTATE_NEXT: read")
2995 nia_update
= (yield from self
.svstate_post_inc(ins_name
))
2997 log("SVSTATE_NEXT: post-inc")
2998 # use actual (cached) src/dst-step here to check end
2999 remaps
= self
.get_remap_indices()
3000 remap_idxs
= self
.remap_idxs
3001 vl
= self
.svstate
.vl
3002 subvl
= yield self
.dec2
.rm_dec
.rm_in
.subvl
3003 if self
.allow_next_step_inc
!= 2:
3004 yield from self
.advance_svstate_steps()
3005 #self.namespace['SVSTATE'] = self.svstate.spr
3006 # set CR0 (if Rc=1) based on end
3007 endtest
= 1 if self
.at_loopend() else 0
3009 #results = [SelectableInt(endtest, 64)]
3010 # self.handle_comparison(results) # CR0
3012 # see if svstep was requested, if so, which SVSTATE
3014 if self
.svstate_next_mode
> 0:
3015 shape_idx
= self
.svstate_next_mode
.value
-1
3016 endings
= self
.remap_loopends
[shape_idx
]
3017 cr_field
= SelectableInt((~endings
) << 1 | endtest
, 4)
3018 log("svstep Rc=1, CR0", cr_field
, endtest
)
3019 self
.crl
[0].eq(cr_field
) # CR0
3021 # reset at end of loop including exit Vertical Mode
3022 log("SVSTATE_NEXT: after increments, reset")
3023 self
.svp64_reset_loop()
3024 self
.svstate
.vfirst
= 0
3027 def SVSTATE_NEXT(self
, mode
, submode
, RA
=None):
3028 """explicitly moves srcstep/dststep on to next element, for
3029 "Vertical-First" mode. this function is called from
3030 setvl pseudo-code, as a pseudo-op "svstep"
3032 WARNING: this function uses information that was created EARLIER
3033 due to it being in the middle of a yield, but this function is
3034 *NOT* called from yield (it's called from compiled pseudocode).
3036 self
.allow_next_step_inc
= submode
.value
+ 1
3037 log("SVSTATE_NEXT mode", mode
, submode
, self
.allow_next_step_inc
)
3038 self
.svstate_next_mode
= mode
3039 if self
.svstate_next_mode
> 0 and self
.svstate_next_mode
< 5:
3040 shape_idx
= self
.svstate_next_mode
.value
-1
3041 return SelectableInt(self
.remap_idxs
[shape_idx
], 7)
3042 if self
.svstate_next_mode
== 5:
3043 self
.svstate_next_mode
= 0
3044 return SelectableInt(self
.svstate
.srcstep
, 7)
3045 if self
.svstate_next_mode
== 6:
3046 self
.svstate_next_mode
= 0
3047 return SelectableInt(self
.svstate
.dststep
, 7)
3048 if self
.svstate_next_mode
== 7:
3049 self
.svstate_next_mode
= 0
3050 return SelectableInt(self
.svstate
.ssubstep
, 7)
3051 if self
.svstate_next_mode
== 8:
3052 self
.svstate_next_mode
= 0
3053 return SelectableInt(self
.svstate
.dsubstep
, 7)
3054 return SelectableInt(0, 7)
3056 def get_src_dststeps(self
):
3057 """gets srcstep, dststep, and ssubstep, dsubstep
3059 return (self
.new_srcstep
, self
.new_dststep
,
3060 self
.new_ssubstep
, self
.new_dsubstep
)
3062 def update_svstate_namespace(self
, overwrite_svstate
=True):
3063 if overwrite_svstate
:
3064 # note, do not get the bit-reversed srcstep here!
3065 srcstep
, dststep
= self
.new_srcstep
, self
.new_dststep
3066 ssubstep
, dsubstep
= self
.new_ssubstep
, self
.new_dsubstep
3068 # update SVSTATE with new srcstep
3069 self
.svstate
.srcstep
= srcstep
3070 self
.svstate
.dststep
= dststep
3071 self
.svstate
.ssubstep
= ssubstep
3072 self
.svstate
.dsubstep
= dsubstep
3073 self
.namespace
['SVSTATE'] = self
.svstate
3074 yield self
.dec2
.state
.svstate
.eq(self
.svstate
.value
)
3075 yield Settle() # let decoder update
3077 def update_new_svstate_steps(self
, overwrite_svstate
=True):
3078 yield from self
.update_svstate_namespace(overwrite_svstate
)
3079 srcstep
= self
.svstate
.srcstep
3080 dststep
= self
.svstate
.dststep
3081 ssubstep
= self
.svstate
.ssubstep
3082 dsubstep
= self
.svstate
.dsubstep
3083 pack
= self
.svstate
.pack
3084 unpack
= self
.svstate
.unpack
3085 vl
= self
.svstate
.vl
3086 sv_mode
= yield self
.dec2
.rm_dec
.sv_mode
3087 subvl
= yield self
.dec2
.rm_dec
.rm_in
.subvl
3088 rm_mode
= yield self
.dec2
.rm_dec
.mode
3089 ff_inv
= yield self
.dec2
.rm_dec
.inv
3090 cr_bit
= yield self
.dec2
.rm_dec
.cr_sel
3091 log(" srcstep", srcstep
)
3092 log(" dststep", dststep
)
3094 log(" unpack", unpack
)
3095 log(" ssubstep", ssubstep
)
3096 log(" dsubstep", dsubstep
)
3098 log(" subvl", subvl
)
3099 log(" rm_mode", rm_mode
)
3100 log(" sv_mode", sv_mode
)
3102 log(" cr_bit", cr_bit
)
3104 # check if end reached (we let srcstep overrun, above)
3105 # nothing needs doing (TODO zeroing): just do next instruction
3108 return ((ssubstep
== subvl
and srcstep
== vl
) or
3109 (dsubstep
== subvl
and dststep
== vl
))
3111 def svstate_post_inc(self
, insn_name
, vf
=0):
3112 # check if SV "Vertical First" mode is enabled
3113 vfirst
= self
.svstate
.vfirst
3114 log(" SV Vertical First", vf
, vfirst
)
3115 if not vf
and vfirst
== 1:
3116 # SV Branch-Conditional required to be as-if-vector
3117 # because there *is* no destination register
3118 # (SV normally only terminates on 1st scalar reg written
3119 # except in [slightly-misnamed] mapreduce mode)
3120 ffirst
= yield from is_ffirst_mode(self
.dec2
)
3121 if insn_name
.startswith("sv.bc") or ffirst
:
3122 self
.update_pc_next()
3127 # check if it is the SVSTATE.src/dest step that needs incrementing
3128 # this is our Sub-Program-Counter loop from 0 to VL-1
3129 # XXX twin predication TODO
3130 vl
= self
.svstate
.vl
3131 subvl
= yield self
.dec2
.rm_dec
.rm_in
.subvl
3132 mvl
= self
.svstate
.maxvl
3133 srcstep
= self
.svstate
.srcstep
3134 dststep
= self
.svstate
.dststep
3135 ssubstep
= self
.svstate
.ssubstep
3136 dsubstep
= self
.svstate
.dsubstep
3137 pack
= self
.svstate
.pack
3138 unpack
= self
.svstate
.unpack
3139 rm_mode
= yield self
.dec2
.rm_dec
.mode
3140 reverse_gear
= yield self
.dec2
.rm_dec
.reverse_gear
3141 sv_ptype
= yield self
.dec2
.dec
.op
.SV_Ptype
3142 out_vec
= not (yield self
.dec2
.no_out_vec
)
3143 in_vec
= not (yield self
.dec2
.no_in_vec
)
3144 rm_mode
= yield self
.dec2
.rm_dec
.mode
3145 log(" svstate.vl", vl
)
3146 log(" svstate.mvl", mvl
)
3147 log(" rm.subvl", subvl
)
3148 log(" svstate.srcstep", srcstep
)
3149 log(" svstate.dststep", dststep
)
3150 log(" svstate.ssubstep", ssubstep
)
3151 log(" svstate.dsubstep", dsubstep
)
3152 log(" svstate.pack", pack
)
3153 log(" svstate.unpack", unpack
)
3154 log(" mode", rm_mode
)
3155 log(" reverse", reverse_gear
)
3156 log(" out_vec", out_vec
)
3157 log(" in_vec", in_vec
)
3158 log(" sv_ptype", sv_ptype
, sv_ptype
== SVPType
.P2
.value
)
3159 log(" rm_mode", rm_mode
)
3160 # check if this was an sv.bc* and if so did it succeed
3161 if self
.is_svp64_mode
and insn_name
.startswith("sv.bc"):
3162 end_loop
= self
.namespace
['end_loop']
3163 log("branch %s end_loop" % insn_name
, end_loop
)
3165 self
.svp64_reset_loop()
3166 self
.update_pc_next()
3168 # check if srcstep needs incrementing by one, stop PC advancing
3169 # but for 2-pred both src/dest have to be checked.
3170 # XXX this might not be true! it may just be LD/ST
3171 if sv_ptype
== SVPType
.P2
.value
:
3172 svp64_is_vector
= (out_vec
or in_vec
)
3174 svp64_is_vector
= out_vec
3175 # also if data-dependent fail-first is used, only in_vec is tested,
3176 # allowing *scalar destinations* to be used as an accumulator.
3177 # effectively this implies /mr (mapreduce mode) is 100% on with ddffirst
3178 # see https://bugs.libre-soc.org/show_bug.cgi?id=1183#c16
3179 ffirst
= yield from is_ffirst_mode(self
.dec2
)
3181 svp64_is_vector
= in_vec
3183 # loops end at the first "hit" (source or dest)
3184 yield from self
.advance_svstate_steps()
3185 loopend
= self
.loopend
3186 log("loopend", svp64_is_vector
, loopend
)
3187 if not svp64_is_vector
or loopend
:
3188 # reset loop to zero and update NIA
3189 self
.svp64_reset_loop()
3194 # still looping, advance and update NIA
3195 self
.namespace
['SVSTATE'] = self
.svstate
3197 # not an SVP64 branch, so fix PC (NIA==CIA) for next loop
3198 # (by default, NIA is CIA+4 if v3.0B or CIA+8 if SVP64)
3199 # this way we keep repeating the same instruction (with new steps)
3200 self
.pc
.NIA
.eq(self
.pc
.CIA
)
3201 self
.namespace
['NIA'] = self
.pc
.NIA
3202 log("end of sub-pc call", self
.namespace
['CIA'], self
.namespace
['NIA'])
3203 return False # DO NOT allow PC update whilst Sub-PC loop running
3205 def update_pc_next(self
):
3206 # UPDATE program counter
3207 self
.pc
.update(self
.namespace
, self
.is_svp64_mode
)
3208 #self.svstate.spr = self.namespace['SVSTATE']
3209 log("end of call", self
.namespace
['CIA'],
3210 self
.namespace
['NIA'],
3211 self
.namespace
['SVSTATE'])
3213 def svp64_reset_loop(self
):
3214 self
.svstate
.srcstep
= 0
3215 self
.svstate
.dststep
= 0
3216 self
.svstate
.ssubstep
= 0
3217 self
.svstate
.dsubstep
= 0
3218 self
.loopend
= False
3219 log(" svstate.srcstep loop end (PC to update)")
3220 self
.namespace
['SVSTATE'] = self
.svstate
3222 def update_nia(self
):
3223 self
.pc
.update_nia(self
.is_svp64_mode
)
3224 self
.namespace
['NIA'] = self
.pc
.NIA
3228 """Decorator factory.
3230 this decorator will "inject" variables into the function's namespace,
3231 from the *dictionary* in self.namespace. it therefore becomes possible
3232 to make it look like a whole stack of variables which would otherwise
3233 need "self." inserted in front of them (*and* for those variables to be
3234 added to the instance) "appear" in the function.
3236 "self.namespace['SI']" for example becomes accessible as just "SI" but
3237 *only* inside the function, when decorated.
3239 def variable_injector(func
):
3241 def decorator(*args
, **kwargs
):
3243 func_globals
= func
.__globals
__ # Python 2.6+
3244 except AttributeError:
3245 func_globals
= func
.func_globals
# Earlier versions.
3247 context
= args
[0].namespace
# variables to be injected
3248 saved_values
= func_globals
.copy() # Shallow copy of dict.
3249 log("globals before", context
.keys())
3250 func_globals
.update(context
)
3251 result
= func(*args
, **kwargs
)
3252 log("globals after", func_globals
['CIA'], func_globals
['NIA'])
3253 log("args[0]", args
[0].namespace
['CIA'],
3254 args
[0].namespace
['NIA'],
3255 args
[0].namespace
['SVSTATE'])
3256 if 'end_loop' in func_globals
:
3257 log("args[0] end_loop", func_globals
['end_loop'])
3258 args
[0].namespace
= func_globals
3259 #exec (func.__code__, func_globals)
3262 # func_globals = saved_values # Undo changes.
3268 return variable_injector