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
, mask
, vl
):
431 idx
, noninv
= _get_predcr(mask
)
434 cr
= crl
[i
+SVP64CROffs
.CRPred
]
435 if cr
[idx
].value
== noninv
:
440 # TODO, really should just be using PowerDecoder2
441 def get_idx_map(dec2
, name
):
443 in1_sel
= yield op
.in1_sel
444 in2_sel
= yield op
.in2_sel
445 in3_sel
= yield op
.in3_sel
446 in1
= yield dec2
.e
.read_reg1
.data
447 # identify which regnames map to in1/2/3
448 if name
== 'RA' or name
== 'RA_OR_ZERO':
449 if (in1_sel
== In1Sel
.RA
.value
or
450 (in1_sel
== In1Sel
.RA_OR_ZERO
.value
and in1
!= 0)):
452 if in1_sel
== In1Sel
.RA_OR_ZERO
.value
:
455 if in2_sel
== In2Sel
.RB
.value
:
457 if in3_sel
== In3Sel
.RB
.value
:
459 # XXX TODO, RC doesn't exist yet!
461 if in3_sel
== In3Sel
.RC
.value
:
463 elif name
in ['EA', 'RS']:
464 if in1_sel
== In1Sel
.RS
.value
:
466 if in2_sel
== In2Sel
.RS
.value
:
468 if in3_sel
== In3Sel
.RS
.value
:
471 if in1_sel
== In1Sel
.FRA
.value
:
473 if in3_sel
== In3Sel
.FRA
.value
:
476 if in2_sel
== In2Sel
.FRB
.value
:
479 if in3_sel
== In3Sel
.FRC
.value
:
482 if in1_sel
== In1Sel
.FRS
.value
:
484 if in3_sel
== In3Sel
.FRS
.value
:
487 if in1_sel
== In1Sel
.FRT
.value
:
490 if in1_sel
== In1Sel
.RT
.value
:
495 # TODO, really should just be using PowerDecoder2
496 def get_idx_in(dec2
, name
, ewmode
=False):
497 idx
= yield from get_idx_map(dec2
, name
)
501 in1_sel
= yield op
.in1_sel
502 in2_sel
= yield op
.in2_sel
503 in3_sel
= yield op
.in3_sel
504 # get the IN1/2/3 from the decoder (includes SVP64 remap and isvec)
505 in1
= yield dec2
.e
.read_reg1
.data
506 in2
= yield dec2
.e
.read_reg2
.data
507 in3
= yield dec2
.e
.read_reg3
.data
509 in1_base
= yield dec2
.e
.read_reg1
.base
510 in2_base
= yield dec2
.e
.read_reg2
.base
511 in3_base
= yield dec2
.e
.read_reg3
.base
512 in1_offs
= yield dec2
.e
.read_reg1
.offs
513 in2_offs
= yield dec2
.e
.read_reg2
.offs
514 in3_offs
= yield dec2
.e
.read_reg3
.offs
515 in1
= (in1
, in1_base
, in1_offs
)
516 in2
= (in2
, in2_base
, in2_offs
)
517 in3
= (in3
, in3_base
, in3_offs
)
519 in1_isvec
= yield dec2
.in1_isvec
520 in2_isvec
= yield dec2
.in2_isvec
521 in3_isvec
= yield dec2
.in3_isvec
522 log("get_idx_in in1", name
, in1_sel
, In1Sel
.RA
.value
,
524 log("get_idx_in in2", name
, in2_sel
, In2Sel
.RB
.value
,
526 log("get_idx_in in3", name
, in3_sel
, In3Sel
.RS
.value
,
528 log("get_idx_in FRS in3", name
, in3_sel
, In3Sel
.FRS
.value
,
530 log("get_idx_in FRB in2", name
, in2_sel
, In2Sel
.FRB
.value
,
532 log("get_idx_in FRC in3", name
, in3_sel
, In3Sel
.FRC
.value
,
535 return in1
, in1_isvec
537 return in2
, in2_isvec
539 return in3
, in3_isvec
543 # TODO, really should just be using PowerDecoder2
544 def get_cr_in(dec2
, name
):
546 in_sel
= yield op
.cr_in
547 in_bitfield
= yield dec2
.dec_cr_in
.cr_bitfield
.data
548 sv_cr_in
= yield op
.sv_cr_in
549 spec
= yield dec2
.crin_svdec
.spec
550 sv_override
= yield dec2
.dec_cr_in
.sv_override
551 # get the IN1/2/3 from the decoder (includes SVP64 remap and isvec)
552 in1
= yield dec2
.e
.read_cr1
.data
553 cr_isvec
= yield dec2
.cr_in_isvec
554 log("get_cr_in", in_sel
, CROutSel
.CR0
.value
, in1
, cr_isvec
)
555 log(" sv_cr_in", sv_cr_in
)
556 log(" cr_bf", in_bitfield
)
558 log(" override", sv_override
)
559 # identify which regnames map to in / o2
561 if in_sel
== CRInSel
.BI
.value
:
563 log("get_cr_in not found", name
)
567 # TODO, really should just be using PowerDecoder2
568 def get_cr_out(dec2
, name
):
570 out_sel
= yield op
.cr_out
571 out_bitfield
= yield dec2
.dec_cr_out
.cr_bitfield
.data
572 sv_cr_out
= yield op
.sv_cr_out
573 spec
= yield dec2
.crout_svdec
.spec
574 sv_override
= yield dec2
.dec_cr_out
.sv_override
575 # get the IN1/2/3 from the decoder (includes SVP64 remap and isvec)
576 out
= yield dec2
.e
.write_cr
.data
577 o_isvec
= yield dec2
.cr_out_isvec
578 log("get_cr_out", out_sel
, CROutSel
.CR0
.value
, out
, o_isvec
)
579 log(" sv_cr_out", sv_cr_out
)
580 log(" cr_bf", out_bitfield
)
582 log(" override", sv_override
)
583 # identify which regnames map to out / o2
585 if out_sel
== CROutSel
.BF
.value
:
588 if out_sel
== CROutSel
.CR0
.value
:
590 if name
== 'CR1': # these are not actually calculated correctly
591 if out_sel
== CROutSel
.CR1
.value
:
593 # check RC1 set? if so return implicit vector, this is a REAL bad hack
594 RC1
= yield dec2
.rm_dec
.RC1
596 log("get_cr_out RC1 mode")
598 return 0, True # XXX TODO: offset CR0 from SVSTATE SPR
600 return 1, True # XXX TODO: offset CR1 from SVSTATE SPR
602 log("get_cr_out not found", name
)
606 # TODO, really should just be using PowerDecoder2
607 def get_out_map(dec2
, name
):
609 out_sel
= yield op
.out_sel
610 # get the IN1/2/3 from the decoder (includes SVP64 remap and isvec)
611 out
= yield dec2
.e
.write_reg
.data
612 # identify which regnames map to out / o2
614 if out_sel
== OutSel
.RA
.value
:
617 if out_sel
== OutSel
.RT
.value
:
619 if out_sel
== OutSel
.RT_OR_ZERO
.value
and out
!= 0:
621 elif name
== 'RT_OR_ZERO':
622 if out_sel
== OutSel
.RT_OR_ZERO
.value
:
625 if out_sel
== OutSel
.FRA
.value
:
628 if out_sel
== OutSel
.FRS
.value
:
631 if out_sel
== OutSel
.FRT
.value
:
636 # TODO, really should just be using PowerDecoder2
637 def get_idx_out(dec2
, name
, ewmode
=False):
639 out_sel
= yield op
.out_sel
640 # get the IN1/2/3 from the decoder (includes SVP64 remap and isvec)
641 out
= yield dec2
.e
.write_reg
.data
642 o_isvec
= yield dec2
.o_isvec
644 offs
= yield dec2
.e
.write_reg
.offs
645 base
= yield dec2
.e
.write_reg
.base
646 out
= (out
, base
, offs
)
647 # identify which regnames map to out / o2
648 ismap
= yield from get_out_map(dec2
, name
)
650 log("get_idx_out", name
, out_sel
, out
, o_isvec
)
652 log("get_idx_out not found", name
, out_sel
, out
, o_isvec
)
656 # TODO, really should just be using PowerDecoder2
657 def get_out2_map(dec2
, name
):
658 # check first if register is activated for write
660 out_sel
= yield op
.out_sel
661 out
= yield dec2
.e
.write_ea
.data
662 out_ok
= yield dec2
.e
.write_ea
.ok
666 if name
in ['EA', 'RA']:
667 if hasattr(op
, "upd"):
668 # update mode LD/ST uses read-reg A also as an output
670 log("get_idx_out2", upd
, LDSTMode
.update
.value
,
671 out_sel
, OutSel
.RA
.value
,
673 if upd
== LDSTMode
.update
.value
:
676 fft_en
= yield dec2
.implicit_rs
678 log("get_idx_out2", out_sel
, OutSel
.RS
.value
,
682 fft_en
= yield dec2
.implicit_rs
684 log("get_idx_out2", out_sel
, OutSel
.FRS
.value
,
690 # TODO, really should just be using PowerDecoder2
691 def get_idx_out2(dec2
, name
, ewmode
=False):
692 # check first if register is activated for write
694 out_sel
= yield op
.out_sel
695 out
= yield dec2
.e
.write_ea
.data
697 offs
= yield dec2
.e
.write_ea
.offs
698 base
= yield dec2
.e
.write_ea
.base
699 out
= (out
, base
, offs
)
700 o_isvec
= yield dec2
.o2_isvec
701 ismap
= yield from get_out2_map(dec2
, name
)
703 log("get_idx_out2", name
, out_sel
, out
, o_isvec
)
709 """deals with svstate looping.
712 def __init__(self
, svstate
):
713 self
.svstate
= svstate
716 def new_iterators(self
):
717 self
.src_it
= self
.src_iterator()
718 self
.dst_it
= self
.dst_iterator()
722 self
.new_ssubstep
= 0
723 self
.new_dsubstep
= 0
724 self
.pred_dst_zero
= 0
725 self
.pred_src_zero
= 0
727 def src_iterator(self
):
728 """source-stepping iterator
730 pack
= self
.svstate
.pack
734 # pack advances subvl in *outer* loop
735 while True: # outer subvl loop
736 while True: # inner vl loop
739 srcmask
= self
.srcmask
740 srcstep
= self
.svstate
.srcstep
741 pred_src_zero
= ((1 << srcstep
) & srcmask
) != 0
742 if self
.pred_sz
or pred_src_zero
:
743 self
.pred_src_zero
= not pred_src_zero
744 log(" advance src", srcstep
, vl
,
745 self
.svstate
.ssubstep
, subvl
)
746 # yield actual substep/srcstep
747 yield (self
.svstate
.ssubstep
, srcstep
)
748 # the way yield works these could have been modified.
751 srcstep
= self
.svstate
.srcstep
752 log(" advance src check", srcstep
, vl
,
753 self
.svstate
.ssubstep
, subvl
, srcstep
== vl
-1,
754 self
.svstate
.ssubstep
== subvl
)
755 if srcstep
== vl
-1: # end-point
756 self
.svstate
.srcstep
= SelectableInt(0, 7) # reset
757 if self
.svstate
.ssubstep
== subvl
: # end-point
758 log(" advance pack stop")
760 break # exit inner loop
761 self
.svstate
.srcstep
+= SelectableInt(1, 7) # advance ss
763 if self
.svstate
.ssubstep
== subvl
: # end-point
764 self
.svstate
.ssubstep
= SelectableInt(0, 2) # reset
765 log(" advance pack stop")
767 self
.svstate
.ssubstep
+= SelectableInt(1, 2)
770 # these cannot be done as for-loops because SVSTATE may change
771 # (srcstep/substep may be modified, interrupted, subvl/vl change)
772 # but they *can* be done as while-loops as long as every SVSTATE
773 # "thing" is re-read every single time a yield gives indices
774 while True: # outer vl loop
775 while True: # inner subvl loop
778 srcmask
= self
.srcmask
779 srcstep
= self
.svstate
.srcstep
780 pred_src_zero
= ((1 << srcstep
) & srcmask
) != 0
781 if self
.pred_sz
or pred_src_zero
:
782 self
.pred_src_zero
= not pred_src_zero
783 log(" advance src", srcstep
, vl
,
784 self
.svstate
.ssubstep
, subvl
)
785 # yield actual substep/srcstep
786 yield (self
.svstate
.ssubstep
, srcstep
)
787 if self
.svstate
.ssubstep
== subvl
: # end-point
788 self
.svstate
.ssubstep
= SelectableInt(0, 2) # reset
789 break # exit inner loop
790 self
.svstate
.ssubstep
+= SelectableInt(1, 2)
792 if srcstep
== vl
-1: # end-point
793 self
.svstate
.srcstep
= SelectableInt(0, 7) # reset
796 self
.svstate
.srcstep
+= SelectableInt(1, 7) # advance srcstep
798 def dst_iterator(self
):
799 """dest-stepping iterator
801 unpack
= self
.svstate
.unpack
805 # pack advances subvl in *outer* loop
806 while True: # outer subvl loop
807 while True: # inner vl loop
810 dstmask
= self
.dstmask
811 dststep
= self
.svstate
.dststep
812 pred_dst_zero
= ((1 << dststep
) & dstmask
) != 0
813 if self
.pred_dz
or pred_dst_zero
:
814 self
.pred_dst_zero
= not pred_dst_zero
815 log(" advance dst", dststep
, vl
,
816 self
.svstate
.dsubstep
, subvl
)
817 # yield actual substep/dststep
818 yield (self
.svstate
.dsubstep
, dststep
)
819 # the way yield works these could have been modified.
821 dststep
= self
.svstate
.dststep
822 log(" advance dst check", dststep
, vl
,
823 self
.svstate
.ssubstep
, subvl
)
824 if dststep
== vl
-1: # end-point
825 self
.svstate
.dststep
= SelectableInt(0, 7) # reset
826 if self
.svstate
.dsubstep
== subvl
: # end-point
827 log(" advance unpack stop")
830 self
.svstate
.dststep
+= SelectableInt(1, 7) # advance ds
832 if self
.svstate
.dsubstep
== subvl
: # end-point
833 self
.svstate
.dsubstep
= SelectableInt(0, 2) # reset
834 log(" advance unpack stop")
836 self
.svstate
.dsubstep
+= SelectableInt(1, 2)
838 # these cannot be done as for-loops because SVSTATE may change
839 # (dststep/substep may be modified, interrupted, subvl/vl change)
840 # but they *can* be done as while-loops as long as every SVSTATE
841 # "thing" is re-read every single time a yield gives indices
842 while True: # outer vl loop
843 while True: # inner subvl loop
845 dstmask
= self
.dstmask
846 dststep
= self
.svstate
.dststep
847 pred_dst_zero
= ((1 << dststep
) & dstmask
) != 0
848 if self
.pred_dz
or pred_dst_zero
:
849 self
.pred_dst_zero
= not pred_dst_zero
850 log(" advance dst", dststep
, self
.svstate
.vl
,
851 self
.svstate
.dsubstep
, subvl
)
852 # yield actual substep/dststep
853 yield (self
.svstate
.dsubstep
, dststep
)
854 if self
.svstate
.dsubstep
== subvl
: # end-point
855 self
.svstate
.dsubstep
= SelectableInt(0, 2) # reset
857 self
.svstate
.dsubstep
+= SelectableInt(1, 2)
860 if dststep
== vl
-1: # end-point
861 self
.svstate
.dststep
= SelectableInt(0, 7) # reset
863 self
.svstate
.dststep
+= SelectableInt(1, 7) # advance dststep
865 def src_iterate(self
):
866 """source-stepping iterator
870 pack
= self
.svstate
.pack
871 unpack
= self
.svstate
.unpack
872 ssubstep
= self
.svstate
.ssubstep
873 end_ssub
= ssubstep
== subvl
874 end_src
= self
.svstate
.srcstep
== vl
-1
875 log(" pack/unpack/subvl", pack
, unpack
, subvl
,
879 srcstep
= self
.svstate
.srcstep
880 srcmask
= self
.srcmask
882 # pack advances subvl in *outer* loop
884 assert srcstep
<= vl
-1
885 end_src
= srcstep
== vl
-1
890 self
.svstate
.ssubstep
+= SelectableInt(1, 2)
894 srcstep
+= 1 # advance srcstep
895 if not self
.srcstep_skip
:
897 if ((1 << srcstep
) & srcmask
) != 0:
900 log(" sskip", bin(srcmask
), bin(1 << srcstep
))
902 # advance subvl in *inner* loop
905 assert srcstep
<= vl
-1
906 end_src
= srcstep
== vl
-1
907 if end_src
: # end-point
913 if not self
.srcstep_skip
:
915 if ((1 << srcstep
) & srcmask
) != 0:
918 log(" sskip", bin(srcmask
), bin(1 << srcstep
))
919 self
.svstate
.ssubstep
= SelectableInt(0, 2) # reset
922 self
.svstate
.ssubstep
+= SelectableInt(1, 2)
924 self
.svstate
.srcstep
= SelectableInt(srcstep
, 7)
925 log(" advance src", self
.svstate
.srcstep
, self
.svstate
.ssubstep
,
928 def dst_iterate(self
):
929 """dest step iterator
933 pack
= self
.svstate
.pack
934 unpack
= self
.svstate
.unpack
935 dsubstep
= self
.svstate
.dsubstep
936 end_dsub
= dsubstep
== subvl
937 dststep
= self
.svstate
.dststep
938 end_dst
= dststep
== vl
-1
939 dstmask
= self
.dstmask
940 log(" pack/unpack/subvl", pack
, unpack
, subvl
,
945 # unpack advances subvl in *outer* loop
947 assert dststep
<= vl
-1
948 end_dst
= dststep
== vl
-1
953 self
.svstate
.dsubstep
+= SelectableInt(1, 2)
957 dststep
+= 1 # advance dststep
958 if not self
.dststep_skip
:
960 if ((1 << dststep
) & dstmask
) != 0:
963 log(" dskip", bin(dstmask
), bin(1 << dststep
))
965 # advance subvl in *inner* loop
968 assert dststep
<= vl
-1
969 end_dst
= dststep
== vl
-1
970 if end_dst
: # end-point
976 if not self
.dststep_skip
:
978 if ((1 << dststep
) & dstmask
) != 0:
981 log(" dskip", bin(dstmask
), bin(1 << dststep
))
982 self
.svstate
.dsubstep
= SelectableInt(0, 2) # reset
985 self
.svstate
.dsubstep
+= SelectableInt(1, 2)
987 self
.svstate
.dststep
= SelectableInt(dststep
, 7)
988 log(" advance dst", self
.svstate
.dststep
, self
.svstate
.dsubstep
,
991 def at_loopend(self
):
992 """tells if this is the last possible element. uses the cached values
993 for src/dst-step and sub-steps
997 srcstep
, dststep
= self
.new_srcstep
, self
.new_dststep
998 ssubstep
, dsubstep
= self
.new_ssubstep
, self
.new_dsubstep
999 end_ssub
= ssubstep
== subvl
1000 end_dsub
= dsubstep
== subvl
1001 if srcstep
== vl
-1 and end_ssub
:
1003 if dststep
== vl
-1 and end_dsub
:
1007 def advance_svstate_steps(self
):
1008 """ advance sub/steps. note that Pack/Unpack *INVERTS* the order.
1009 TODO when Pack/Unpack is set, substep becomes the *outer* loop
1011 self
.subvl
= yield self
.dec2
.rm_dec
.rm_in
.subvl
1012 if self
.loopend
: # huhn??
1017 def read_src_mask(self
):
1018 """read/update pred_sz and src mask
1020 # get SVSTATE VL (oh and print out some debug stuff)
1021 vl
= self
.svstate
.vl
1022 srcstep
= self
.svstate
.srcstep
1023 ssubstep
= self
.svstate
.ssubstep
1025 # get predicate mask (all 64 bits)
1026 srcmask
= 0xffff_ffff_ffff_ffff
1028 pmode
= yield self
.dec2
.rm_dec
.predmode
1029 sv_ptype
= yield self
.dec2
.dec
.op
.SV_Ptype
1030 srcpred
= yield self
.dec2
.rm_dec
.srcpred
1031 dstpred
= yield self
.dec2
.rm_dec
.dstpred
1032 pred_sz
= yield self
.dec2
.rm_dec
.pred_sz
1033 if pmode
== SVP64PredMode
.INT
.value
:
1034 srcmask
= dstmask
= get_predint(self
.gpr
, dstpred
)
1035 if sv_ptype
== SVPType
.P2
.value
:
1036 srcmask
= get_predint(self
.gpr
, srcpred
)
1037 elif pmode
== SVP64PredMode
.CR
.value
:
1038 srcmask
= dstmask
= get_predcr(self
.crl
, dstpred
, vl
)
1039 if sv_ptype
== SVPType
.P2
.value
:
1040 srcmask
= get_predcr(self
.crl
, srcpred
, vl
)
1041 # work out if the ssubsteps are completed
1042 ssubstart
= ssubstep
== 0
1043 log(" pmode", pmode
)
1044 log(" ptype", sv_ptype
)
1045 log(" srcpred", bin(srcpred
))
1046 log(" srcmask", bin(srcmask
))
1047 log(" pred_sz", bin(pred_sz
))
1048 log(" ssubstart", ssubstart
)
1050 # store all that above
1051 self
.srcstep_skip
= False
1052 self
.srcmask
= srcmask
1053 self
.pred_sz
= pred_sz
1054 self
.new_ssubstep
= ssubstep
1055 log(" new ssubstep", ssubstep
)
1056 # until the predicate mask has a "1" bit... or we run out of VL
1057 # let srcstep==VL be the indicator to move to next instruction
1059 self
.srcstep_skip
= True
1061 def read_dst_mask(self
):
1062 """same as read_src_mask - check and record everything needed
1064 # get SVSTATE VL (oh and print out some debug stuff)
1065 # yield Delay(1e-10) # make changes visible
1066 vl
= self
.svstate
.vl
1067 dststep
= self
.svstate
.dststep
1068 dsubstep
= self
.svstate
.dsubstep
1070 # get predicate mask (all 64 bits)
1071 dstmask
= 0xffff_ffff_ffff_ffff
1073 pmode
= yield self
.dec2
.rm_dec
.predmode
1074 reverse_gear
= yield self
.dec2
.rm_dec
.reverse_gear
1075 sv_ptype
= yield self
.dec2
.dec
.op
.SV_Ptype
1076 dstpred
= yield self
.dec2
.rm_dec
.dstpred
1077 pred_dz
= yield self
.dec2
.rm_dec
.pred_dz
1078 if pmode
== SVP64PredMode
.INT
.value
:
1079 dstmask
= get_predint(self
.gpr
, dstpred
)
1080 elif pmode
== SVP64PredMode
.CR
.value
:
1081 dstmask
= get_predcr(self
.crl
, dstpred
, vl
)
1082 # work out if the ssubsteps are completed
1083 dsubstart
= dsubstep
== 0
1084 log(" pmode", pmode
)
1085 log(" ptype", sv_ptype
)
1086 log(" dstpred", bin(dstpred
))
1087 log(" dstmask", bin(dstmask
))
1088 log(" pred_dz", bin(pred_dz
))
1089 log(" dsubstart", dsubstart
)
1091 self
.dststep_skip
= False
1092 self
.dstmask
= dstmask
1093 self
.pred_dz
= pred_dz
1094 self
.new_dsubstep
= dsubstep
1095 log(" new dsubstep", dsubstep
)
1097 self
.dststep_skip
= True
1099 def svstate_pre_inc(self
):
1100 """check if srcstep/dststep need to skip over masked-out predicate bits
1101 note that this is not supposed to do anything to substep,
1102 it is purely for skipping masked-out bits
1105 self
.subvl
= yield self
.dec2
.rm_dec
.rm_in
.subvl
1106 yield from self
.read_src_mask()
1107 yield from self
.read_dst_mask()
1114 srcstep
= self
.svstate
.srcstep
1115 srcmask
= self
.srcmask
1116 pred_src_zero
= self
.pred_sz
1117 vl
= self
.svstate
.vl
1118 # srcstep-skipping opportunity identified
1119 if self
.srcstep_skip
:
1120 # cannot do this with sv.bc - XXX TODO
1123 while (((1 << srcstep
) & srcmask
) == 0) and (srcstep
!= vl
):
1124 log(" sskip", bin(1 << srcstep
))
1127 # now work out if the relevant mask bits require zeroing
1129 pred_src_zero
= ((1 << srcstep
) & srcmask
) == 0
1131 # store new srcstep / dststep
1132 self
.new_srcstep
= srcstep
1133 self
.pred_src_zero
= pred_src_zero
1134 log(" new srcstep", srcstep
)
1137 # dststep-skipping opportunity identified
1138 dststep
= self
.svstate
.dststep
1139 dstmask
= self
.dstmask
1140 pred_dst_zero
= self
.pred_dz
1141 vl
= self
.svstate
.vl
1142 if self
.dststep_skip
:
1143 # cannot do this with sv.bc - XXX TODO
1146 while (((1 << dststep
) & dstmask
) == 0) and (dststep
!= vl
):
1147 log(" dskip", bin(1 << dststep
))
1150 # now work out if the relevant mask bits require zeroing
1152 pred_dst_zero
= ((1 << dststep
) & dstmask
) == 0
1154 # store new srcstep / dststep
1155 self
.new_dststep
= dststep
1156 self
.pred_dst_zero
= pred_dst_zero
1157 log(" new dststep", dststep
)
1160 class ExitSyscallCalled(Exception):
1164 class SyscallEmulator(openpower
.syscalls
.Dispatcher
):
1165 def __init__(self
, isacaller
):
1166 self
.__isacaller
= isacaller
1168 host
= os
.uname().machine
1169 bits
= (64 if (sys
.maxsize
> (2**32)) else 32)
1170 host
= openpower
.syscalls
.architecture(arch
=host
, bits
=bits
)
1172 return super().__init
__(guest
="ppc64", host
=host
)
1174 def __call__(self
, identifier
, *arguments
):
1175 (identifier
, *arguments
) = map(int, (identifier
, *arguments
))
1176 return super().__call
__(identifier
, *arguments
)
1178 def sys_exit_group(self
, status
, *rest
):
1179 self
.__isacaller
.halted
= True
1180 raise ExitSyscallCalled(status
)
1182 def sys_write(self
, fd
, buf
, count
, *rest
):
1184 buf
= self
.__isacaller
.mem
.get_ctypes(buf
, count
, is_write
=False)
1188 return os
.write(fd
, buf
)
1189 except OSError as e
:
1192 def sys_writev(self
, fd
, iov
, iovcnt
, *rest
):
1194 if iovcnt
< 0 or iovcnt
> IOV_MAX
:
1195 return -errno
.EINVAL
1196 struct_iovec
= struct
.Struct("<QQ")
1199 iov
= self
.__isacaller
.mem
.get_ctypes(
1200 iov
, struct_iovec
.size
* iovcnt
, is_write
=False)
1201 iov
= list(struct_iovec
.iter_unpack(iov
))
1204 for i
, iovec
in enumerate(iov
):
1205 iov_base
, iov_len
= iovec
1206 iov
[i
] = self
.__isacaller
.mem
.get_ctypes(
1207 iov_base
, iov_len
, is_write
=False)
1208 except (ValueError, MemException
):
1209 return -errno
.EFAULT
1211 return os
.writev(fd
, iov
)
1212 except OSError as e
:
1215 def sys_read(self
, fd
, buf
, count
, *rest
):
1217 buf
= self
.__isacaller
.mem
.get_ctypes(buf
, count
, is_write
=True)
1221 return os
.readv(fd
, [buf
])
1222 except OSError as e
:
1225 def sys_mmap(self
, addr
, length
, prot
, flags
, fd
, offset
, *rest
):
1226 return self
.__isacaller
.mem
.mmap_syscall(
1227 addr
, length
, prot
, flags
, fd
, offset
, is_mmap2
=False)
1229 def sys_mmap2(self
, addr
, length
, prot
, flags
, fd
, offset
, *rest
):
1230 return self
.__isacaller
.mem
.mmap_syscall(
1231 addr
, length
, prot
, flags
, fd
, offset
, is_mmap2
=True)
1233 def sys_brk(self
, addr
, *rest
):
1234 return self
.__isacaller
.mem
.brk_syscall(addr
)
1236 def sys_munmap(self
, addr
, length
, *rest
):
1237 return -errno
.ENOSYS
# TODO: implement
1239 def sys_mprotect(self
, addr
, length
, prot
, *rest
):
1240 return -errno
.ENOSYS
# TODO: implement
1242 def sys_pkey_mprotect(self
, addr
, length
, prot
, pkey
, *rest
):
1243 return -errno
.ENOSYS
# TODO: implement
1245 def sys_openat(self
, dirfd
, pathname
, flags
, mode
, *rest
):
1247 path
= self
.__isacaller
.mem
.read_cstr(pathname
)
1248 except (ValueError, MemException
):
1249 return -errno
.EFAULT
1251 if dirfd
== ppc_flags
.AT_FDCWD
:
1252 return os
.open(path
, flags
, mode
)
1254 return os
.open(path
, flags
, mode
, dir_fd
=dirfd
)
1255 except OSError as e
:
1261 nodename
= uname
.nodename
.encode()
1262 release
= b
'5.6.0-1-powerpc64le'
1263 version
= b
'#1 SMP Debian 5.6.7-1 (2020-04-29)'
1264 machine
= b
'ppc64le'
1266 return sysname
, nodename
, release
, version
, machine
, domainname
1268 def sys_uname(self
, buf
, *rest
):
1269 s
= struct
.Struct("<65s65s65s65s65s")
1271 buf
= self
.__isacaller
.mem
.get_ctypes(buf
, s
.size
, is_write
=True)
1272 except (ValueError, MemException
):
1273 return -errno
.EFAULT
1274 sysname
, nodename
, release
, version
, machine
, domainname
= \
1276 s
.pack_into(buf
, 0, sysname
, nodename
, release
, version
, machine
)
1279 def sys_newuname(self
, buf
, *rest
):
1280 name_len
= ppc_flags
.__NEW
_UTS
_LEN
+ 1
1281 s
= struct
.Struct("<%ds%ds%ds%ds%ds%ds" % ((name_len
,) * 6))
1283 buf
= self
.__isacaller
.mem
.get_ctypes(buf
, s
.size
, is_write
=True)
1284 except (ValueError, MemException
):
1285 return -errno
.EFAULT
1286 sysname
, nodename
, release
, version
, machine
, domainname
= \
1289 sysname
, nodename
, release
, version
, machine
, domainname
)
1292 def sys_readlink(self
, pathname
, buf
, bufsiz
, *rest
):
1293 dirfd
= ppc_flags
.AT_FDCWD
1294 return self
.sys_readlinkat(dirfd
, pathname
, buf
, bufsiz
)
1296 def sys_readlinkat(self
, dirfd
, pathname
, buf
, bufsiz
, *rest
):
1298 path
= self
.__isacaller
.mem
.read_cstr(pathname
)
1300 buf
= self
.__isacaller
.mem
.get_ctypes(
1301 buf
, bufsiz
, is_write
=True)
1304 except (ValueError, MemException
):
1305 return -errno
.EFAULT
1307 if dirfd
== ppc_flags
.AT_FDCWD
:
1308 result
= os
.readlink(path
)
1310 result
= os
.readlink(path
, dir_fd
=dirfd
)
1311 retval
= min(len(result
), len(buf
))
1312 buf
[:retval
] = result
[:retval
]
1314 except OSError as e
:
1318 class ISACaller(ISACallerHelper
, ISAFPHelpers
, StepLoop
):
1319 # decoder2 - an instance of power_decoder2
1320 # regfile - a list of initial values for the registers
1321 # initial_{etc} - initial values for SPRs, Condition Register, Mem, MSR
1322 # respect_pc - tracks the program counter. requires initial_insns
1323 def __init__(self
, decoder2
, regfile
, initial_sprs
=None, initial_cr
=0,
1324 initial_mem
=None, initial_msr
=0,
1337 use_syscall_emu
=False,
1338 emulating_mmap
=False,
1339 real_page_size
=None):
1341 self
.syscall
= SyscallEmulator(isacaller
=self
)
1342 if not use_mmap_mem
:
1343 log("forcing use_mmap_mem due to use_syscall_emu active")
1348 # we will eventually be able to load ELF files without use_syscall_emu
1349 # (e.g. the linux kernel), so do it in a separate if block
1350 if isinstance(initial_insns
, ELFFile
):
1351 if not use_mmap_mem
:
1352 log("forcing use_mmap_mem due to loading an ELF file")
1354 if not emulating_mmap
:
1355 log("forcing emulating_mmap due to loading an ELF file")
1356 emulating_mmap
= True
1358 # trace log file for model output. if None do nothing
1359 self
.insnlog
= insnlog
1360 self
.insnlog_is_file
= hasattr(insnlog
, "write")
1361 if not self
.insnlog_is_file
and self
.insnlog
:
1362 self
.insnlog
= open(self
.insnlog
, "w")
1364 self
.bigendian
= bigendian
1366 self
.is_svp64_mode
= False
1367 self
.respect_pc
= respect_pc
1368 if initial_sprs
is None:
1370 if initial_mem
is None:
1372 if fpregfile
is None:
1373 fpregfile
= [0] * 32
1374 if initial_insns
is None:
1376 assert self
.respect_pc
== False, "instructions required to honor pc"
1377 if initial_msr
is None:
1378 initial_msr
= DEFAULT_MSR
1380 log("ISACaller insns", respect_pc
, initial_insns
, disassembly
)
1381 log("ISACaller initial_msr", initial_msr
)
1383 # "fake program counter" mode (for unit testing)
1387 if isinstance(initial_mem
, tuple):
1388 self
.fake_pc
= initial_mem
[0]
1389 disasm_start
= self
.fake_pc
1391 disasm_start
= initial_pc
1393 # disassembly: we need this for now (not given from the decoder)
1394 self
.disassembly
= {}
1396 for i
, code
in enumerate(disassembly
):
1397 self
.disassembly
[i
*4 + disasm_start
] = code
1399 # set up registers, instruction memory, data memory, PC, SPRs, MSR, CR
1400 self
.svp64rm
= SVP64RM()
1401 if initial_svstate
is None:
1403 if isinstance(initial_svstate
, int):
1404 initial_svstate
= SVP64State(initial_svstate
)
1405 # SVSTATE, MSR and PC
1406 StepLoop
.__init
__(self
, initial_svstate
)
1407 self
.msr
= SelectableInt(initial_msr
, 64) # underlying reg
1409 # GPR FPR SPR registers
1410 initial_sprs
= deepcopy(initial_sprs
) # so as not to get modified
1411 self
.gpr
= GPR(decoder2
, self
, self
.svstate
, regfile
)
1412 self
.fpr
= GPR(decoder2
, self
, self
.svstate
, fpregfile
)
1413 # initialise SPRs before MMU
1414 self
.spr
= SPR(decoder2
, initial_sprs
, gpr
=self
.gpr
)
1416 # set up 4 dummy SVSHAPEs if they aren't already set up
1418 sname
= 'SVSHAPE%d' % i
1419 val
= self
.spr
.get(sname
, 0)
1420 # make sure it's an SVSHAPE -- conversion done by SPR.__setitem__
1421 self
.spr
[sname
] = val
1422 self
.last_op_svshape
= False
1426 self
.mem
= MemMMap(row_bytes
=8,
1427 initial_mem
=initial_mem
,
1429 emulating_mmap
=emulating_mmap
)
1430 self
.imem
= self
.mem
1431 lelf
= self
.mem
.initialize(row_bytes
=4, initial_mem
=initial_insns
)
1432 if isinstance(lelf
, LoadedELF
): # stuff parsed from ELF
1433 initial_pc
= lelf
.pc
1434 for k
, v
in lelf
.gprs
.items():
1435 self
.gpr
[k
] = SelectableInt(v
, 64)
1436 initial_fpscr
= lelf
.fpscr
1437 self
.mem
.log_fancy(kind
=LogType
.InstrInOuts
)
1439 self
.mem
= Mem(row_bytes
=8, initial_mem
=initial_mem
,
1441 self
.mem
.log_fancy(kind
=LogType
.InstrInOuts
)
1442 self
.imem
= Mem(row_bytes
=4, initial_mem
=initial_insns
)
1443 # MMU mode, redirect underlying Mem through RADIX
1445 self
.mem
= RADIX(self
.mem
, self
)
1447 self
.imem
= RADIX(self
.imem
, self
)
1449 # TODO, needed here:
1450 # FPR (same as GPR except for FP nums)
1451 # 4.2.2 p124 FPSCR (definitely "separate" - not in SPR)
1452 # note that mffs, mcrfs, mtfsf "manage" this FPSCR
1453 self
.fpscr
= FPSCRState(initial_fpscr
)
1455 # 2.3.1 CR (and sub-fields CR0..CR6 - CR0 SO comes from XER.SO)
1456 # note that mfocrf, mfcr, mtcr, mtocrf, mcrxrx "manage" CRs
1458 # 2.3.2 LR (actually SPR #8) -- Done
1459 # 2.3.3 CTR (actually SPR #9) -- Done
1460 # 2.3.4 TAR (actually SPR #815)
1461 # 3.2.2 p45 XER (actually SPR #1) -- Done
1462 # 3.2.3 p46 p232 VRSAVE (actually SPR #256)
1464 # create CR then allow portions of it to be "selectable" (below)
1465 self
.cr_fields
= CRFields(initial_cr
)
1466 self
.cr
= self
.cr_fields
.cr
1467 self
.cr_backup
= 0 # sigh, dreadful hack: for fail-first (VLi)
1469 # "undefined", just set to variable-bit-width int (use exts "max")
1470 # self.undefined = SelectableInt(0, EFFECTIVELY_UNLIMITED)
1473 self
.namespace
.update(self
.spr
)
1474 self
.namespace
.update({'GPR': self
.gpr
,
1478 'memassign': self
.memassign
,
1481 'SVSTATE': self
.svstate
,
1482 'SVSHAPE0': self
.spr
['SVSHAPE0'],
1483 'SVSHAPE1': self
.spr
['SVSHAPE1'],
1484 'SVSHAPE2': self
.spr
['SVSHAPE2'],
1485 'SVSHAPE3': self
.spr
['SVSHAPE3'],
1488 'FPSCR': self
.fpscr
,
1489 'undefined': undefined
,
1490 'mode_is_64bit': True,
1491 'SO': XER_bits
['SO'],
1492 'XLEN': 64, # elwidth overrides
1496 if real_page_size
is None:
1497 # PowerISA v3.1B Book III Section 6.7 page 1191 (1217)
1498 # defines real page size as 2 ** 12 bytes (4KiB)
1499 real_page_size
= 2 ** 12
1500 self
.real_page_size
= real_page_size
1501 self
.reserve_addr
= SelectableInt(0, self
.XLEN
)
1502 self
.reserve
= SelectableInt(0, 1)
1503 self
.reserve_length
= SelectableInt(0, 4)
1505 self
.namespace
.update({'RESERVE': self
.RESERVE
,
1506 'RESERVE_ADDR': self
.RESERVE_ADDR
,
1507 'RESERVE_LENGTH': self
.RESERVE_LENGTH
,
1508 'REAL_PAGE_SIZE': self
.REAL_PAGE_SIZE
,
1511 for name
in BFP_FLAG_NAMES
:
1512 setattr(self
, name
, 0)
1514 # update pc to requested start point
1515 self
.set_pc(initial_pc
)
1517 # field-selectable versions of Condition Register
1518 self
.crl
= self
.cr_fields
.crl
1520 self
.namespace
["CR%d" % i
] = self
.crl
[i
]
1522 self
.decoder
= decoder2
.dec
1523 self
.dec2
= decoder2
1525 super().__init
__(XLEN
=self
.namespace
["XLEN"], FPSCR
=self
.fpscr
)
1527 def trace(self
, out
):
1528 if self
.insnlog
is None:
1530 self
.insnlog
.write(out
)
1534 return self
.namespace
["XLEN"]
1541 def RESERVE_LENGTH(self
):
1542 return self
.reserve_length
1545 def RESERVE_ADDR(self
):
1546 return self
.reserve_addr
1549 def REAL_PAGE_SIZE(self
):
1550 return self
.real_page_size
1552 def real_addr(self
, EA
):
1553 """ get the "real address to which `EA` maps"
1555 Specified in PowerISA v3.1B Book II Section 1.7.2.1 page 1049 (1075)
1557 # FIXME: translate EA to a physical address
1564 def call_trap(self
, trap_addr
, trap_bit
):
1565 """calls TRAP and sets up NIA to the new execution location.
1566 next instruction will begin at trap_addr.
1568 self
.TRAP(trap_addr
, trap_bit
)
1569 self
.namespace
['NIA'] = self
.trap_nia
1570 self
.pc
.update(self
.namespace
, self
.is_svp64_mode
)
1572 def TRAP(self
, trap_addr
=0x700, trap_bit
=PIb
.TRAP
):
1573 """TRAP> saves PC, MSR (and TODO SVSTATE), and updates MSR
1575 TRAP function is callable from inside the pseudocode itself,
1576 hence the default arguments. when calling from inside ISACaller
1577 it is best to use call_trap()
1579 trap_addr: int | SelectableInt
1580 the address to go to (before any modifications from `KAIVB`)
1581 trap_bit: int | None
1582 the bit in `SRR1` to set, `None` means don't set any bits.
1584 if isinstance(trap_addr
, SelectableInt
):
1585 trap_addr
= trap_addr
.value
1586 # https://bugs.libre-soc.org/show_bug.cgi?id=859
1587 kaivb
= self
.spr
['KAIVB'].value
1588 msr
= self
.namespace
['MSR'].value
1589 log("TRAP:", hex(trap_addr
), hex(msr
), "kaivb", hex(kaivb
))
1590 # store CIA(+4?) in SRR0, set NIA to 0x700
1591 # store MSR in SRR1, set MSR to um errr something, have to check spec
1592 # store SVSTATE (if enabled) in SVSRR0
1593 self
.spr
['SRR0'].value
= self
.pc
.CIA
.value
1594 self
.spr
['SRR1'].value
= msr
1595 if self
.is_svp64_mode
:
1596 self
.spr
['SVSRR0'] = self
.namespace
['SVSTATE'].value
1597 self
.trap_nia
= SelectableInt(trap_addr |
(kaivb
& ~
0x1fff), 64)
1598 if trap_bit
is not None:
1599 self
.spr
['SRR1'][trap_bit
] = 1 # change *copy* of MSR in SRR1
1601 # set exception bits. TODO: this should, based on the address
1602 # in figure 66 p1065 V3.0B and the table figure 65 p1063 set these
1603 # bits appropriately. however it turns out that *for now* in all
1604 # cases (all trap_addrs) the exact same thing is needed.
1605 self
.msr
[MSRb
.IR
] = 0
1606 self
.msr
[MSRb
.DR
] = 0
1607 self
.msr
[MSRb
.FE0
] = 0
1608 self
.msr
[MSRb
.FE1
] = 0
1609 self
.msr
[MSRb
.EE
] = 0
1610 self
.msr
[MSRb
.RI
] = 0
1611 self
.msr
[MSRb
.SF
] = 1
1612 self
.msr
[MSRb
.TM
] = 0
1613 self
.msr
[MSRb
.VEC
] = 0
1614 self
.msr
[MSRb
.VSX
] = 0
1615 self
.msr
[MSRb
.PR
] = 0
1616 self
.msr
[MSRb
.FP
] = 0
1617 self
.msr
[MSRb
.PMM
] = 0
1618 self
.msr
[MSRb
.TEs
] = 0
1619 self
.msr
[MSRb
.TEe
] = 0
1620 self
.msr
[MSRb
.UND
] = 0
1621 self
.msr
[MSRb
.LE
] = 1
1623 def memassign(self
, ea
, sz
, val
):
1624 self
.mem
.memassign(ea
, sz
, val
)
1626 def prep_namespace(self
, insn_name
, formname
, op_fields
, xlen
):
1627 # TODO: get field names from form in decoder*1* (not decoder2)
1628 # decoder2 is hand-created, and decoder1.sigform is auto-generated
1630 # then "yield" fields only from op_fields rather than hard-coded
1632 fields
= self
.decoder
.sigforms
[formname
]
1633 log("prep_namespace", formname
, op_fields
, insn_name
)
1634 for name
in op_fields
:
1635 # CR immediates. deal with separately. needs modifying
1637 if self
.is_svp64_mode
and name
in ['BI']: # TODO, more CRs
1638 # BI is a 5-bit, must reconstruct the value
1639 regnum
, is_vec
= yield from get_cr_in(self
.dec2
, name
)
1640 sig
= getattr(fields
, name
)
1642 # low 2 LSBs (CR field selector) remain same, CR num extended
1643 assert regnum
<= 7, "sigh, TODO, 128 CR fields"
1644 val
= (val
& 0b11) |
(regnum
<< 2)
1645 elif self
.is_svp64_mode
and name
in ['BF']: # TODO, more CRs
1646 regnum
, is_vec
= yield from get_cr_out(self
.dec2
, "BF")
1647 log('hack %s' % name
, regnum
, is_vec
)
1650 sig
= getattr(fields
, name
)
1652 # these are all opcode fields involved in index-selection of CR,
1653 # and need to do "standard" arithmetic. CR[BA+32] for example
1654 # would, if using SelectableInt, only be 5-bit.
1655 if name
in ['BF', 'BFA', 'BFB', 'BC', 'BA', 'BB', 'BT', 'BI']:
1656 self
.namespace
[name
] = val
1658 self
.namespace
[name
] = SelectableInt(val
, sig
.width
)
1660 self
.namespace
['XER'] = self
.spr
['XER']
1661 self
.namespace
['CA'] = self
.spr
['XER'][XER_bits
['CA']].value
1662 self
.namespace
['CA32'] = self
.spr
['XER'][XER_bits
['CA32']].value
1663 self
.namespace
['OV'] = self
.spr
['XER'][XER_bits
['OV']].value
1664 self
.namespace
['OV32'] = self
.spr
['XER'][XER_bits
['OV32']].value
1665 self
.namespace
['XLEN'] = xlen
1666 self
.namespace
['RESERVE'] = self
.reserve
1667 self
.namespace
['RESERVE_ADDR'] = self
.reserve_addr
1668 self
.namespace
['RESERVE_LENGTH'] = self
.reserve_length
1670 # add some SVSTATE convenience variables
1671 vl
= self
.svstate
.vl
1672 srcstep
= self
.svstate
.srcstep
1673 self
.namespace
['VL'] = vl
1674 self
.namespace
['srcstep'] = srcstep
1676 # take a copy of the CR field value: if non-VLi fail-first fails
1677 # this is because the pseudocode writes *directly* to CR. sigh
1678 self
.cr_backup
= self
.cr
.value
1680 # sv.bc* need some extra fields
1681 if not self
.is_svp64_mode
or not insn_name
.startswith("sv.bc"):
1684 # blegh grab bits manually
1685 mode
= yield self
.dec2
.rm_dec
.rm_in
.mode
1686 # convert to SelectableInt before test
1687 mode
= SelectableInt(mode
, 5)
1688 bc_vlset
= mode
[SVP64MODEb
.BC_VLSET
] != 0
1689 bc_vli
= mode
[SVP64MODEb
.BC_VLI
] != 0
1690 bc_snz
= mode
[SVP64MODEb
.BC_SNZ
] != 0
1691 bc_vsb
= yield self
.dec2
.rm_dec
.bc_vsb
1692 bc_ctrtest
= yield self
.dec2
.rm_dec
.bc_ctrtest
1693 bc_lru
= yield self
.dec2
.rm_dec
.bc_lru
1694 bc_gate
= yield self
.dec2
.rm_dec
.bc_gate
1695 sz
= yield self
.dec2
.rm_dec
.pred_sz
1696 self
.namespace
['mode'] = SelectableInt(mode
, 5)
1697 self
.namespace
['ALL'] = SelectableInt(bc_gate
, 1)
1698 self
.namespace
['VSb'] = SelectableInt(bc_vsb
, 1)
1699 self
.namespace
['LRu'] = SelectableInt(bc_lru
, 1)
1700 self
.namespace
['CTRtest'] = SelectableInt(bc_ctrtest
, 1)
1701 self
.namespace
['VLSET'] = SelectableInt(bc_vlset
, 1)
1702 self
.namespace
['VLI'] = SelectableInt(bc_vli
, 1)
1703 self
.namespace
['sz'] = SelectableInt(sz
, 1)
1704 self
.namespace
['SNZ'] = SelectableInt(bc_snz
, 1)
1706 def get_kludged_op_add_ca_ov(self
, inputs
, inp_ca_ov
):
1707 """ this was not at all necessary to do. this function massively
1708 duplicates - in a laborious and complex fashion - the contents of
1709 the CSV files that were extracted two years ago from microwatt's
1710 source code. A-inversion is the "inv A" column, output inversion
1711 is the "inv out" column, carry-in equal to 0 or 1 or CA is the
1714 all of that information is available in
1715 self.instrs[ins_name].op_fields
1716 where info is usually assigned to self.instrs[ins_name]
1718 https://git.libre-soc.org/?p=openpower-isa.git;a=blob;f=openpower/isatables/minor_31.csv;hb=HEAD
1720 the immediate constants are *also* decoded correctly and placed
1721 usually by DecodeIn2Imm into operand2, as part of power_decoder2.py
1723 def ca(a
, b
, ca_in
, width
):
1724 mask
= (1 << width
) - 1
1725 y
= (a
& mask
) + (b
& mask
) + ca_in
1728 asmcode
= yield self
.dec2
.dec
.op
.asmcode
1729 insn
= insns
.get(asmcode
)
1730 SI
= yield self
.dec2
.dec
.SI
1733 inputs
= [i
.value
for i
in inputs
]
1736 if insn
in ("add", "addo", "addc", "addco"):
1740 elif insn
== "addic" or insn
== "addic.":
1744 elif insn
in ("subf", "subfo", "subfc", "subfco"):
1748 elif insn
== "subfic":
1752 elif insn
== "adde" or insn
== "addeo":
1756 elif insn
== "subfe" or insn
== "subfeo":
1760 elif insn
== "addme" or insn
== "addmeo":
1764 elif insn
== "addze" or insn
== "addzeo":
1768 elif insn
== "subfme" or insn
== "subfmeo":
1772 elif insn
== "subfze" or insn
== "subfzeo":
1776 elif insn
== "addex":
1777 # CA[32] aren't actually written, just generate so we have
1778 # something to return
1779 ca64
= ov64
= ca(inputs
[0], inputs
[1], OV
, 64)
1780 ca32
= ov32
= ca(inputs
[0], inputs
[1], OV
, 32)
1781 return ca64
, ca32
, ov64
, ov32
1782 elif insn
== "neg" or insn
== "nego":
1787 raise NotImplementedError(
1788 "op_add kludge unimplemented instruction: ", asmcode
, insn
)
1790 ca64
= ca(a
, b
, ca_in
, 64)
1791 ca32
= ca(a
, b
, ca_in
, 32)
1792 ov64
= ca64
!= ca(a
, b
, ca_in
, 63)
1793 ov32
= ca32
!= ca(a
, b
, ca_in
, 31)
1794 return ca64
, ca32
, ov64
, ov32
1796 def handle_carry_(self
, inputs
, output
, ca
, ca32
, inp_ca_ov
):
1797 if ca
is not None and ca32
is not None:
1799 op
= yield self
.dec2
.e
.do
.insn_type
1800 if op
== MicrOp
.OP_ADD
.value
and ca
is None and ca32
is None:
1801 retval
= yield from self
.get_kludged_op_add_ca_ov(
1803 ca
, ca32
, ov
, ov32
= retval
1804 asmcode
= yield self
.dec2
.dec
.op
.asmcode
1805 if insns
.get(asmcode
) == 'addex':
1806 # TODO: if 32-bit mode, set ov to ov32
1807 self
.spr
['XER'][XER_bits
['OV']] = ov
1808 self
.spr
['XER'][XER_bits
['OV32']] = ov32
1809 log(f
"write OV/OV32 OV={ov} OV32={ov32}",
1810 kind
=LogType
.InstrInOuts
)
1812 # TODO: if 32-bit mode, set ca to ca32
1813 self
.spr
['XER'][XER_bits
['CA']] = ca
1814 self
.spr
['XER'][XER_bits
['CA32']] = ca32
1815 log(f
"write CA/CA32 CA={ca} CA32={ca32}",
1816 kind
=LogType
.InstrInOuts
)
1818 inv_a
= yield self
.dec2
.e
.do
.invert_in
1820 inputs
[0] = ~inputs
[0]
1822 imm_ok
= yield self
.dec2
.e
.do
.imm_data
.ok
1824 imm
= yield self
.dec2
.e
.do
.imm_data
.data
1825 inputs
.append(SelectableInt(imm
, 64))
1828 log("gt input", x
, output
)
1829 gt
= (gtu(x
, output
))
1832 cy
= 1 if any(gts
) else 0
1834 if ca
is None: # already written
1835 self
.spr
['XER'][XER_bits
['CA']] = cy
1838 # ARGH... different for OP_ADD... *sigh*...
1839 op
= yield self
.dec2
.e
.do
.insn_type
1840 if op
== MicrOp
.OP_ADD
.value
:
1841 res32
= (output
.value
& (1 << 32)) != 0
1842 a32
= (inputs
[0].value
& (1 << 32)) != 0
1843 if len(inputs
) >= 2:
1844 b32
= (inputs
[1].value
& (1 << 32)) != 0
1847 cy32
= res32 ^ a32 ^ b32
1848 log("CA32 ADD", cy32
)
1852 log("input", x
, output
)
1853 log(" x[32:64]", x
, x
[32:64])
1854 log(" o[32:64]", output
, output
[32:64])
1855 gt
= (gtu(x
[32:64], output
[32:64])) == SelectableInt(1, 1)
1857 cy32
= 1 if any(gts
) else 0
1858 log("CA32", cy32
, gts
)
1859 if ca32
is None: # already written
1860 self
.spr
['XER'][XER_bits
['CA32']] = cy32
1862 def handle_overflow(self
, inputs
, output
, div_overflow
, inp_ca_ov
):
1863 op
= yield self
.dec2
.e
.do
.insn_type
1864 if op
== MicrOp
.OP_ADD
.value
:
1865 retval
= yield from self
.get_kludged_op_add_ca_ov(
1867 ca
, ca32
, ov
, ov32
= retval
1868 # TODO: if 32-bit mode, set ov to ov32
1869 self
.spr
['XER'][XER_bits
['OV']] = ov
1870 self
.spr
['XER'][XER_bits
['OV32']] = ov32
1871 self
.spr
['XER'][XER_bits
['SO']] |
= ov
1873 if hasattr(self
.dec2
.e
.do
, "invert_in"):
1874 inv_a
= yield self
.dec2
.e
.do
.invert_in
1876 inputs
[0] = ~inputs
[0]
1878 imm_ok
= yield self
.dec2
.e
.do
.imm_data
.ok
1880 imm
= yield self
.dec2
.e
.do
.imm_data
.data
1881 inputs
.append(SelectableInt(imm
, 64))
1882 log("handle_overflow", inputs
, output
, div_overflow
)
1883 if len(inputs
) < 2 and div_overflow
is None:
1886 # div overflow is different: it's returned by the pseudo-code
1887 # because it's more complex than can be done by analysing the output
1888 if div_overflow
is not None:
1889 ov
, ov32
= div_overflow
, div_overflow
1890 # arithmetic overflow can be done by analysing the input and output
1891 elif len(inputs
) >= 2:
1893 input_sgn
= [exts(x
.value
, x
.bits
) < 0 for x
in inputs
]
1894 output_sgn
= exts(output
.value
, output
.bits
) < 0
1895 ov
= 1 if input_sgn
[0] == input_sgn
[1] and \
1896 output_sgn
!= input_sgn
[0] else 0
1899 input32_sgn
= [exts(x
.value
, 32) < 0 for x
in inputs
]
1900 output32_sgn
= exts(output
.value
, 32) < 0
1901 ov32
= 1 if input32_sgn
[0] == input32_sgn
[1] and \
1902 output32_sgn
!= input32_sgn
[0] else 0
1904 # now update XER OV/OV32/SO
1905 so
= self
.spr
['XER'][XER_bits
['SO']]
1906 new_so
= so | ov
# sticky overflow ORs in old with new
1907 self
.spr
['XER'][XER_bits
['OV']] = ov
1908 self
.spr
['XER'][XER_bits
['OV32']] = ov32
1909 self
.spr
['XER'][XER_bits
['SO']] = new_so
1910 log(" set overflow", ov
, ov32
, so
, new_so
)
1912 def handle_comparison(self
, out
, cr_idx
=0, overflow
=None, no_so
=False):
1913 assert isinstance(out
, SelectableInt
), \
1914 "out zero not a SelectableInt %s" % repr(outputs
)
1915 log("handle_comparison", out
.bits
, hex(out
.value
))
1916 # TODO - XXX *processor* in 32-bit mode
1917 # https://bugs.libre-soc.org/show_bug.cgi?id=424
1919 # o32 = exts(out.value, 32)
1920 # print ("handle_comparison exts 32 bit", hex(o32))
1921 out
= exts(out
.value
, out
.bits
)
1922 log("handle_comparison exts", hex(out
))
1923 # create the three main CR flags, EQ GT LT
1924 zero
= SelectableInt(out
== 0, 1)
1925 positive
= SelectableInt(out
> 0, 1)
1926 negative
= SelectableInt(out
< 0, 1)
1927 # get (or not) XER.SO. for setvl this is important *not* to read SO
1929 SO
= SelectableInt(1, 0)
1931 SO
= self
.spr
['XER'][XER_bits
['SO']]
1932 log("handle_comparison SO", SO
.value
,
1933 "overflow", overflow
,
1935 "+ve", positive
.value
,
1936 "-ve", negative
.value
)
1937 # alternative overflow checking (setvl mainly at the moment)
1938 if overflow
is not None and overflow
== 1:
1939 SO
= SelectableInt(1, 1)
1940 # create the four CR field values and set the required CR field
1941 cr_field
= selectconcat(negative
, positive
, zero
, SO
)
1942 log("handle_comparison cr_field", self
.cr
, cr_idx
, cr_field
)
1943 self
.crl
[cr_idx
].eq(cr_field
)
1946 def set_pc(self
, pc_val
):
1947 self
.namespace
['NIA'] = SelectableInt(pc_val
, 64)
1948 self
.pc
.update(self
.namespace
, self
.is_svp64_mode
)
1950 def get_next_insn(self
):
1951 """check instruction
1954 pc
= self
.pc
.CIA
.value
1957 ins
= self
.imem
.ld(pc
, 4, False, True, instr_fetch
=True)
1959 raise KeyError("no instruction at 0x%x" % pc
)
1962 def setup_one(self
):
1963 """set up one instruction
1965 pc
, insn
= self
.get_next_insn()
1966 yield from self
.setup_next_insn(pc
, insn
)
1968 # cache since it's really slow to construct
1969 __PREFIX_CACHE
= SVP64Instruction
.Prefix(SelectableInt(value
=0, bits
=32))
1971 def __decode_prefix(self
, opcode
):
1972 pfx
= self
.__PREFIX
_CACHE
1973 pfx
.storage
.eq(opcode
)
1976 def setup_next_insn(self
, pc
, ins
):
1977 """set up next instruction
1980 log("setup: 0x%x 0x%x %s" % (pc
, ins
& 0xffffffff, bin(ins
)))
1981 log("CIA NIA", self
.respect_pc
, self
.pc
.CIA
.value
, self
.pc
.NIA
.value
)
1983 yield self
.dec2
.sv_rm
.eq(0)
1984 yield self
.dec2
.dec
.raw_opcode_in
.eq(ins
& 0xffffffff)
1985 yield self
.dec2
.dec
.bigendian
.eq(self
.bigendian
)
1986 yield self
.dec2
.state
.msr
.eq(self
.msr
.value
)
1987 yield self
.dec2
.state
.pc
.eq(pc
)
1988 if self
.svstate
is not None:
1989 yield self
.dec2
.state
.svstate
.eq(self
.svstate
.value
)
1991 # SVP64. first, check if the opcode is EXT001, and SVP64 id bits set
1993 opcode
= yield self
.dec2
.dec
.opcode_in
1994 opcode
= SelectableInt(value
=opcode
, bits
=32)
1995 pfx
= self
.__decode
_prefix
(opcode
)
1996 log("prefix test: opcode:", pfx
.PO
, bin(pfx
.PO
), pfx
.id)
1997 self
.is_svp64_mode
= bool((pfx
.PO
== 0b000001) and (pfx
.id == 0b11))
1998 self
.pc
.update_nia(self
.is_svp64_mode
)
2000 yield self
.dec2
.is_svp64_mode
.eq(self
.is_svp64_mode
)
2001 self
.namespace
['NIA'] = self
.pc
.NIA
2002 self
.namespace
['SVSTATE'] = self
.svstate
2003 if not self
.is_svp64_mode
:
2006 # in SVP64 mode. decode/print out svp64 prefix, get v3.0B instruction
2007 log("svp64.rm", bin(pfx
.rm
))
2008 log(" svstate.vl", self
.svstate
.vl
)
2009 log(" svstate.mvl", self
.svstate
.maxvl
)
2010 ins
= self
.imem
.ld(pc
+4, 4, False, True, instr_fetch
=True)
2011 log(" svsetup: 0x%x 0x%x %s" % (pc
+4, ins
& 0xffffffff, bin(ins
)))
2012 yield self
.dec2
.dec
.raw_opcode_in
.eq(ins
& 0xffffffff) # v3.0B suffix
2013 yield self
.dec2
.sv_rm
.eq(int(pfx
.rm
)) # svp64 prefix
2016 def execute_one(self
):
2017 """execute one instruction
2019 # get the disassembly code for this instruction
2020 if not self
.disassembly
:
2021 code
= yield from self
.get_assembly_name()
2024 if self
.is_svp64_mode
:
2025 offs
, dbg
= 4, "svp64 "
2026 code
= self
.disassembly
[self
._pc
+offs
]
2027 log(" %s sim-execute" % dbg
, hex(self
._pc
), code
)
2028 opname
= code
.split(' ')[0]
2030 yield from self
.call(opname
) # execute the instruction
2031 except MemException
as e
: # check for memory errors
2032 if e
.args
[0] == 'unaligned': # alignment error
2033 # run a Trap but set DAR first
2034 print("memory unaligned exception, DAR", e
.dar
, repr(e
))
2035 self
.spr
['DAR'] = SelectableInt(e
.dar
, 64)
2036 self
.call_trap(0x600, PIb
.PRIV
) # 0x600, privileged
2038 elif e
.args
[0] == 'invalid': # invalid
2039 # run a Trap but set DAR first
2040 log("RADIX MMU memory invalid error, mode %s" % e
.mode
)
2041 if e
.mode
== 'EXECUTE':
2042 # XXX TODO: must set a few bits in SRR1,
2043 # see microwatt loadstore1.vhdl
2044 # if m_in.segerr = '0' then
2045 # v.srr1(47 - 33) := m_in.invalid;
2046 # v.srr1(47 - 35) := m_in.perm_error; -- noexec fault
2047 # v.srr1(47 - 44) := m_in.badtree;
2048 # v.srr1(47 - 45) := m_in.rc_error;
2049 # v.intr_vec := 16#400#;
2051 # v.intr_vec := 16#480#;
2052 self
.call_trap(0x400, PIb
.PRIV
) # 0x400, privileged
2054 self
.call_trap(0x300, PIb
.PRIV
) # 0x300, privileged
2056 # not supported yet:
2057 raise e
# ... re-raise
2059 # append to the trace log file
2060 self
.trace(" # %s\n" % code
)
2062 log("gprs after code", code
)
2065 for i
in range(len(self
.crl
)):
2066 crs
.append(bin(self
.crl
[i
].asint()))
2067 log("crs", " ".join(crs
))
2068 log("vl,maxvl", self
.svstate
.vl
, self
.svstate
.maxvl
)
2070 # don't use this except in special circumstances
2071 if not self
.respect_pc
:
2074 log("execute one, CIA NIA", hex(self
.pc
.CIA
.value
),
2075 hex(self
.pc
.NIA
.value
))
2077 def get_assembly_name(self
):
2078 # TODO, asmregs is from the spec, e.g. add RT,RA,RB
2079 # see http://bugs.libre-riscv.org/show_bug.cgi?id=282
2080 dec_insn
= yield self
.dec2
.e
.do
.insn
2081 insn_1_11
= yield self
.dec2
.e
.do
.insn
[1:11]
2082 asmcode
= yield self
.dec2
.dec
.op
.asmcode
2083 int_op
= yield self
.dec2
.dec
.op
.internal_op
2084 log("get assembly name asmcode", asmcode
, int_op
,
2085 hex(dec_insn
), bin(insn_1_11
))
2086 asmop
= insns
.get(asmcode
, None)
2088 # sigh reconstruct the assembly instruction name
2089 if hasattr(self
.dec2
.e
.do
, "oe"):
2090 ov_en
= yield self
.dec2
.e
.do
.oe
.oe
2091 ov_ok
= yield self
.dec2
.e
.do
.oe
.ok
2095 if hasattr(self
.dec2
.e
.do
, "rc"):
2096 rc_en
= yield self
.dec2
.e
.do
.rc
.rc
2097 rc_ok
= yield self
.dec2
.e
.do
.rc
.ok
2101 # annoying: ignore rc_ok if RC1 is set (for creating *assembly name*)
2102 RC1
= yield self
.dec2
.rm_dec
.RC1
2106 # grrrr have to special-case MUL op (see DecodeOE)
2107 log("ov %d en %d rc %d en %d op %d" %
2108 (ov_ok
, ov_en
, rc_ok
, rc_en
, int_op
))
2109 if int_op
in [MicrOp
.OP_MUL_H64
.value
, MicrOp
.OP_MUL_H32
.value
]:
2114 if not asmop
.endswith("."): # don't add "." to "andis."
2117 if hasattr(self
.dec2
.e
.do
, "lk"):
2118 lk
= yield self
.dec2
.e
.do
.lk
2121 log("int_op", int_op
)
2122 if int_op
in [MicrOp
.OP_B
.value
, MicrOp
.OP_BC
.value
]:
2123 AA
= yield self
.dec2
.dec
.fields
.FormI
.AA
[0:-1]
2127 spr_msb
= yield from self
.get_spr_msb()
2128 if int_op
== MicrOp
.OP_MFCR
.value
:
2133 # XXX TODO: for whatever weird reason this doesn't work
2134 # https://bugs.libre-soc.org/show_bug.cgi?id=390
2135 if int_op
== MicrOp
.OP_MTCRF
.value
:
2142 def reset_remaps(self
):
2143 self
.remap_loopends
= [0] * 4
2144 self
.remap_idxs
= [0, 1, 2, 3]
2146 def get_remap_indices(self
):
2147 """WARNING, this function stores remap_idxs and remap_loopends
2148 in the class for later use. this to avoid problems with yield
2150 # go through all iterators in lock-step, advance to next remap_idx
2151 srcstep
, dststep
, ssubstep
, dsubstep
= self
.get_src_dststeps()
2152 # get four SVSHAPEs. here we are hard-coding
2154 SVSHAPE0
= self
.spr
['SVSHAPE0']
2155 SVSHAPE1
= self
.spr
['SVSHAPE1']
2156 SVSHAPE2
= self
.spr
['SVSHAPE2']
2157 SVSHAPE3
= self
.spr
['SVSHAPE3']
2158 # set up the iterators
2159 remaps
= [(SVSHAPE0
, SVSHAPE0
.get_iterator()),
2160 (SVSHAPE1
, SVSHAPE1
.get_iterator()),
2161 (SVSHAPE2
, SVSHAPE2
.get_iterator()),
2162 (SVSHAPE3
, SVSHAPE3
.get_iterator()),
2166 for i
, (shape
, remap
) in enumerate(remaps
):
2167 # zero is "disabled"
2168 if shape
.value
== 0x0:
2169 self
.remap_idxs
[i
] = 0
2170 # pick src or dststep depending on reg num (0-2=in, 3-4=out)
2171 step
= dststep
if (i
in [3, 4]) else srcstep
2172 # this is terrible. O(N^2) looking for the match. but hey.
2173 for idx
, (remap_idx
, loopends
) in enumerate(remap
):
2176 self
.remap_idxs
[i
] = remap_idx
2177 self
.remap_loopends
[i
] = loopends
2178 dbg
.append((i
, step
, remap_idx
, loopends
))
2179 for (i
, step
, remap_idx
, loopends
) in dbg
:
2180 log("SVSHAPE %d idx, end" % i
, step
, remap_idx
, bin(loopends
))
2183 def get_spr_msb(self
):
2184 dec_insn
= yield self
.dec2
.e
.do
.insn
2185 return dec_insn
& (1 << 20) != 0 # sigh - XFF.spr[-1]?
2187 def call(self
, name
, syscall_emu_active
=False):
2188 """call(opcode) - the primary execution point for instructions
2190 self
.last_st_addr
= None # reset the last known store address
2191 self
.last_ld_addr
= None # etc.
2193 ins_name
= name
.strip() # remove spaces if not already done so
2195 log("halted - not executing", ins_name
)
2198 # TODO, asmregs is from the spec, e.g. add RT,RA,RB
2199 # see http://bugs.libre-riscv.org/show_bug.cgi?id=282
2200 asmop
= yield from self
.get_assembly_name()
2201 log("call", ins_name
, asmop
,
2202 kind
=LogType
.InstrInOuts
)
2204 # sv.setvl is *not* a loop-function. sigh
2205 log("is_svp64_mode", self
.is_svp64_mode
, asmop
)
2208 int_op
= yield self
.dec2
.dec
.op
.internal_op
2209 spr_msb
= yield from self
.get_spr_msb()
2211 instr_is_privileged
= False
2212 if int_op
in [MicrOp
.OP_ATTN
.value
,
2213 MicrOp
.OP_MFMSR
.value
,
2214 MicrOp
.OP_MTMSR
.value
,
2215 MicrOp
.OP_MTMSRD
.value
,
2217 MicrOp
.OP_RFID
.value
]:
2218 instr_is_privileged
= True
2219 if int_op
in [MicrOp
.OP_MFSPR
.value
,
2220 MicrOp
.OP_MTSPR
.value
] and spr_msb
:
2221 instr_is_privileged
= True
2223 # check MSR priv bit and whether op is privileged: if so, throw trap
2224 PR
= self
.msr
[MSRb
.PR
]
2225 log("is priv", instr_is_privileged
, hex(self
.msr
.value
), PR
)
2226 if instr_is_privileged
and PR
== 1:
2227 self
.call_trap(0x700, PIb
.PRIV
)
2230 # check halted condition
2231 if ins_name
== 'attn':
2235 # User mode system call emulation consists of several steps:
2236 # 1. Detect whether instruction is sc or scv.
2237 # 2. Call the HDL implementation which invokes trap.
2238 # 3. Reroute the guest system call to host system call.
2239 # 4. Force return from the interrupt as if we had guest OS.
2240 # FIXME: enable PPC_FEATURE2_SCV in mem.py DEFAULT_AT_HWCAP2 when
2241 # scv emulation works.
2242 if ((asmop
in ("sc", "scv")) and
2243 (self
.syscall
is not None) and
2244 not syscall_emu_active
):
2245 # Memoize PC and trigger an interrupt
2247 pc
= self
.pc
.CIA
.value
2250 yield from self
.call(asmop
, syscall_emu_active
=True)
2252 # Reroute the syscall to host OS
2253 identifier
= self
.gpr(0)
2254 arguments
= map(self
.gpr
, range(3, 9))
2255 result
= self
.syscall(identifier
, *arguments
)
2256 self
.gpr
.write(3, result
, False, self
.namespace
["XLEN"])
2258 # Return from interrupt
2259 yield from self
.call("rfid", syscall_emu_active
=True)
2261 elif ((name
in ("rfid", "hrfid")) and syscall_emu_active
):
2264 # check illegal instruction
2266 if ins_name
not in ['mtcrf', 'mtocrf']:
2267 illegal
= ins_name
!= asmop
2269 # list of instructions not being supported by binutils (.long)
2270 dotstrp
= asmop
[:-1] if asmop
[-1] == '.' else asmop
2271 if dotstrp
in [*FPTRANS_INSNS
,
2273 'ffmadds', 'fdmadds', 'ffadds',
2275 "brh", "brw", "brd",
2276 'setvl', 'svindex', 'svremap', 'svstep',
2277 'svshape', 'svshape2',
2278 'binlog', 'crbinlog', 'crternlogi', 'ternlogi',
2279 'bmask', 'cprop', 'gbbd',
2280 'absdu', 'absds', 'absdacs', 'absdacu', 'avgadd',
2281 'fmvis', 'fishmv', 'pcdec', "maddedu", "divmod2du",
2282 "dsld", "dsrd", "maddedus",
2283 "sadd", "saddw", "sadduw",
2288 "maddsubrs", "maddrs", "msubrs",
2289 "cfuged", "cntlzdm", "cnttzdm", "pdepd", "pextd",
2290 "setbc", "setbcr", "setnbc", "setnbcr",
2295 # match against instructions treated as nop, see nop below
2296 if asmop
.startswith("dcbt"):
2300 # branch-conditional redirects to sv.bc
2301 if asmop
.startswith('bc') and self
.is_svp64_mode
:
2302 ins_name
= 'sv.%s' % ins_name
2304 # ld-immediate-with-pi mode redirects to ld-with-postinc
2305 ldst_imm_postinc
= False
2306 if 'u' in ins_name
and self
.is_svp64_mode
:
2307 ldst_pi
= yield self
.dec2
.rm_dec
.ldst_postinc
2309 ins_name
= ins_name
.replace("u", "up")
2310 ldst_imm_postinc
= True
2311 log(" enable ld/st postinc", ins_name
)
2313 log(" post-processed name", dotstrp
, ins_name
, asmop
)
2315 # illegal instructions call TRAP at 0x700
2317 print("illegal", ins_name
, asmop
)
2318 self
.call_trap(0x700, PIb
.ILLEG
)
2319 print("name %s != %s - calling ILLEGAL trap, PC: %x" %
2320 (ins_name
, asmop
, self
.pc
.CIA
.value
))
2323 # this is for setvl "Vertical" mode: if set true,
2324 # srcstep/dststep is explicitly advanced. mode says which SVSTATE to
2325 # test for Rc=1 end condition. 3 bits of all 3 loops are put into CR0
2326 self
.allow_next_step_inc
= False
2327 self
.svstate_next_mode
= 0
2329 # nop has to be supported, we could let the actual op calculate
2330 # but PowerDecoder has a pattern for nop
2331 if ins_name
== 'nop':
2332 self
.update_pc_next()
2335 # get elwidths, defaults to 64
2339 if self
.is_svp64_mode
:
2340 ew_src
= yield self
.dec2
.rm_dec
.ew_src
2341 ew_dst
= yield self
.dec2
.rm_dec
.ew_dst
2342 ew_src
= 8 << (3-int(ew_src
)) # convert to bitlength
2343 ew_dst
= 8 << (3-int(ew_dst
)) # convert to bitlength
2344 xlen
= max(ew_src
, ew_dst
)
2345 log("elwidth", ew_src
, ew_dst
)
2346 log("XLEN:", self
.is_svp64_mode
, xlen
)
2348 # look up instruction in ISA.instrs, prepare namespace
2349 if ins_name
== 'pcdec': # grrrr yes there are others ("stbcx." etc.)
2350 info
= self
.instrs
[ins_name
+"."]
2351 elif asmop
[-1] == '.' and asmop
in self
.instrs
:
2352 info
= self
.instrs
[asmop
]
2354 info
= self
.instrs
[ins_name
]
2355 yield from self
.prep_namespace(ins_name
, info
.form
, info
.op_fields
,
2358 # dict retains order
2359 inputs
= dict.fromkeys(create_full_args(
2360 read_regs
=info
.read_regs
, special_regs
=info
.special_regs
,
2361 uninit_regs
=info
.uninit_regs
, write_regs
=info
.write_regs
))
2363 # preserve order of register names
2364 write_without_special_regs
= OrderedSet(info
.write_regs
)
2365 write_without_special_regs
-= OrderedSet(info
.special_regs
)
2366 input_names
= create_args([
2367 *info
.read_regs
, *info
.uninit_regs
, *write_without_special_regs
])
2368 log("input names", input_names
)
2370 # get SVP64 entry for the current instruction
2371 sv_rm
= self
.svp64rm
.instrs
.get(ins_name
)
2372 if sv_rm
is not None:
2373 dest_cr
, src_cr
, src_byname
, dest_byname
= decode_extra(sv_rm
)
2375 dest_cr
, src_cr
, src_byname
, dest_byname
= False, False, {}, {}
2376 log("sv rm", sv_rm
, dest_cr
, src_cr
, src_byname
, dest_byname
)
2378 # see if srcstep/dststep need skipping over masked-out predicate bits
2379 # svstep also needs advancement because it calls SVSTATE_NEXT.
2380 # bit the remaps get computed just after pre_inc moves them on
2381 # with remap_set_steps substituting for PowerDecider2 not doing it,
2382 # and SVSTATE_NEXT not being able to.use yield, the preinc on
2383 # svstep is necessary for now.
2385 if (self
.is_svp64_mode
or ins_name
in ['svstep']):
2386 yield from self
.svstate_pre_inc()
2387 if self
.is_svp64_mode
:
2388 pre
= yield from self
.update_new_svstate_steps()
2390 self
.svp64_reset_loop()
2392 self
.update_pc_next()
2394 srcstep
, dststep
, ssubstep
, dsubstep
= self
.get_src_dststeps()
2395 pred_dst_zero
= self
.pred_dst_zero
2396 pred_src_zero
= self
.pred_src_zero
2397 vl
= self
.svstate
.vl
2398 subvl
= yield self
.dec2
.rm_dec
.rm_in
.subvl
2400 # VL=0 in SVP64 mode means "do nothing: skip instruction"
2401 if self
.is_svp64_mode
and vl
== 0:
2402 self
.pc
.update(self
.namespace
, self
.is_svp64_mode
)
2403 log("SVP64: VL=0, end of call", self
.namespace
['CIA'],
2404 self
.namespace
['NIA'], kind
=LogType
.InstrInOuts
)
2407 # for when SVREMAP is active, using pre-arranged schedule.
2408 # note: modifying PowerDecoder2 needs to "settle"
2409 remap_en
= self
.svstate
.SVme
2410 persist
= self
.svstate
.RMpst
2411 active
= (persist
or self
.last_op_svshape
) and remap_en
!= 0
2412 if self
.is_svp64_mode
:
2413 yield self
.dec2
.remap_active
.eq(remap_en
if active
else 0)
2415 if persist
or self
.last_op_svshape
:
2416 remaps
= self
.get_remap_indices()
2417 if self
.is_svp64_mode
and (persist
or self
.last_op_svshape
):
2418 yield from self
.remap_set_steps(remaps
)
2419 # after that, settle down (combinatorial) to let Vector reg numbers
2420 # work themselves out
2422 if self
.is_svp64_mode
:
2423 remap_active
= yield self
.dec2
.remap_active
2425 remap_active
= False
2426 log("remap active", bin(remap_active
), self
.is_svp64_mode
)
2428 # LDST does *not* allow elwidth overrides on RA (Effective Address).
2429 # this has to be detected. XXX TODO: RB for ldst-idx *may* need
2430 # conversion (to 64-bit) also.
2431 # see write reg this *HAS* to also override XLEN to 64 on LDST/Update
2432 sv_mode
= yield self
.dec2
.rm_dec
.sv_mode
2433 is_ldst
= (sv_mode
in [SVMode
.LDST_IDX
.value
, SVMode
.LDST_IMM
.value
] \
2434 and self
.is_svp64_mode
)
2435 log("is_ldst", sv_mode
, is_ldst
)
2437 # main input registers (RT, RA ...)
2438 for name
in input_names
:
2439 if name
== "overflow":
2440 inputs
[name
] = SelectableInt(0, 1)
2441 elif name
.startswith("RESERVE"):
2442 inputs
[name
] = getattr(self
, name
)
2443 elif name
== "FPSCR":
2444 inputs
[name
] = self
.FPSCR
2445 elif name
in ("CA", "CA32", "OV", "OV32"):
2446 inputs
[name
] = self
.spr
['XER'][XER_bits
[name
]]
2448 inputs
[name
] = self
.crl
[0]
2449 elif name
in spr_byname
:
2450 inputs
[name
] = self
.spr
[name
]
2451 elif is_ldst
and name
== 'RA':
2452 regval
= (yield from self
.get_input(name
, ew_src
, 64))
2453 log("EA (RA) regval name", name
, regval
)
2454 inputs
[name
] = regval
2456 regval
= (yield from self
.get_input(name
, ew_src
, xlen
))
2457 log("regval name", name
, regval
)
2458 inputs
[name
] = regval
2460 # arrrrgh, awful hack, to get _RT into namespace
2461 if ins_name
in ['setvl', 'svstep']:
2463 RT
= yield self
.dec2
.dec
.RT
2464 self
.namespace
[regname
] = SelectableInt(RT
, 5)
2466 self
.namespace
["RT"] = SelectableInt(0, 5)
2467 regnum
, is_vec
= yield from get_idx_out(self
.dec2
, "RT")
2468 log('hack input reg %s %s' % (name
, str(regnum
)), is_vec
)
2470 # in SVP64 mode for LD/ST work out immediate
2471 # XXX TODO: replace_ds for DS-Form rather than D-Form.
2472 # use info.form to detect
2473 if self
.is_svp64_mode
and not ldst_imm_postinc
:
2474 yield from self
.check_replace_d(info
, remap_active
)
2476 # "special" registers
2477 for special
in info
.special_regs
:
2478 if special
in special_sprs
:
2479 inputs
[special
] = self
.spr
[special
]
2481 inputs
[special
] = self
.namespace
[special
]
2483 # clear trap (trap) NIA
2484 self
.trap_nia
= None
2486 # check if this was an sv.bc* and create an indicator that
2487 # this is the last check to be made as a loop. combined with
2488 # the ALL/ANY mode we can early-exit. note that BI (to test)
2489 # is an input so there is no termination if BI is scalar
2490 # (because early-termination is for *output* scalars)
2491 if self
.is_svp64_mode
and ins_name
.startswith("sv.bc"):
2492 end_loop
= srcstep
== vl
-1 or dststep
== vl
-1
2493 self
.namespace
['end_loop'] = SelectableInt(end_loop
, 1)
2495 inp_ca_ov
= (self
.spr
['XER'][XER_bits
['CA']].value
,
2496 self
.spr
['XER'][XER_bits
['OV']].value
)
2498 for k
, v
in inputs
.items():
2500 v
= SelectableInt(0, self
.XLEN
)
2501 # prevent pseudo-code from modifying input registers
2502 v
= copy_assign_rhs(v
)
2503 if isinstance(v
, SelectableInt
):
2507 # execute actual instruction here (finally)
2508 log("inputs", inputs
)
2509 inputs
= list(inputs
.values())
2510 results
= info
.func(self
, *inputs
)
2511 output_names
= create_args(info
.write_regs
)
2513 # record .ok before anything after the pseudo-code can modify it
2515 for out
, n
in zip(results
or [], output_names
):
2518 if isinstance(out
, SelectableInt
):
2520 log("results", outs
)
2521 log("results ok", outs_ok
)
2523 # "inject" decorator takes namespace from function locals: we need to
2524 # overwrite NIA being overwritten (sigh)
2525 if self
.trap_nia
is not None:
2526 self
.namespace
['NIA'] = self
.trap_nia
2528 log("after func", self
.namespace
['CIA'], self
.namespace
['NIA'])
2530 # check if op was a LD/ST so that debugging can check the
2532 if int_op
in [MicrOp
.OP_STORE
.value
,
2534 self
.last_st_addr
= self
.mem
.last_st_addr
2535 if int_op
in [MicrOp
.OP_LOAD
.value
,
2537 self
.last_ld_addr
= self
.mem
.last_ld_addr
2538 log("op", int_op
, MicrOp
.OP_STORE
.value
, MicrOp
.OP_LOAD
.value
,
2539 self
.last_st_addr
, self
.last_ld_addr
)
2541 # detect if CA/CA32 already in outputs (sra*, basically)
2543 ca32
= outs
.get("CA32")
2545 log("carry already done?", ca
, ca32
, output_names
)
2546 # soc test_pipe_caller tests don't have output_carry
2547 has_output_carry
= hasattr(self
.dec2
.e
.do
, "output_carry")
2548 carry_en
= has_output_carry
and (yield self
.dec2
.e
.do
.output_carry
)
2550 yield from self
.handle_carry_(
2551 inputs
, results
[0], ca
, ca32
, inp_ca_ov
=inp_ca_ov
)
2553 # get output named "overflow" and "CR0"
2554 overflow
= outs
.get('overflow')
2555 cr0
= outs
.get('CR0')
2556 cr1
= outs
.get('CR1')
2558 # soc test_pipe_caller tests don't have oe
2559 has_oe
= hasattr(self
.dec2
.e
.do
, "oe")
2560 # yeah just no. not in parallel processing
2561 if has_oe
and not self
.is_svp64_mode
:
2562 # detect if overflow was in return result
2563 ov_en
= yield self
.dec2
.e
.do
.oe
.oe
2564 ov_ok
= yield self
.dec2
.e
.do
.oe
.ok
2565 log("internal overflow", ins_name
, overflow
, "en?", ov_en
, ov_ok
)
2567 yield from self
.handle_overflow(
2568 inputs
, results
[0], overflow
, inp_ca_ov
=inp_ca_ov
)
2570 # only do SVP64 dest predicated Rc=1 if dest-pred is not enabled
2572 if not self
.is_svp64_mode
or not pred_dst_zero
:
2573 if hasattr(self
.dec2
.e
.do
, "rc"):
2574 rc_en
= yield self
.dec2
.e
.do
.rc
.rc
2575 # don't do Rc=1 for svstep it is handled explicitly.
2576 # XXX TODO: now that CR0 is supported, sort out svstep's pseudocode
2577 # to write directly to CR0 instead of in ISACaller. hooyahh.
2578 if rc_en
and ins_name
not in ['svstep']:
2579 if outs_ok
.get('FPSCR', False):
2580 FPSCR
= outs
['FPSCR']
2583 yield from self
.do_rc_ov(
2584 ins_name
, results
[0], overflow
, cr0
, cr1
, FPSCR
)
2587 ffirst_hit
= False, False
2588 if self
.is_svp64_mode
:
2589 sv_mode
= yield self
.dec2
.rm_dec
.sv_mode
2590 is_cr
= sv_mode
== SVMode
.CROP
.value
2591 chk
= rc_en
or is_cr
2592 if outs_ok
.get('CR', False):
2593 # early write so check_ffirst can see value
2594 self
.namespace
['CR'].eq(outs
['CR'])
2595 ffirst_hit
= (yield from self
.check_ffirst(info
, chk
, srcstep
))
2597 # any modified return results?
2598 yield from self
.do_outregs(
2599 info
, outs
, carry_en
, ffirst_hit
, ew_dst
, outs_ok
)
2601 # check if a FP Exception occurred. TODO for DD-FFirst, check VLi
2602 # and raise the exception *after* if VLi=1 but if VLi=0 then
2603 # truncate and make the exception "disappear".
2604 if self
.FPSCR
.FEX
and (self
.msr
[MSRb
.FE0
] or self
.msr
[MSRb
.FE1
]):
2605 self
.call_trap(0x700, PIb
.FP
)
2608 yield from self
.do_nia(asmop
, ins_name
, rc_en
, ffirst_hit
)
2610 def check_ffirst(self
, info
, rc_en
, srcstep
):
2611 """fail-first mode: checks a bit of Rc Vector, truncates VL
2613 rm_mode
= yield self
.dec2
.rm_dec
.mode
2614 ff_inv
= yield self
.dec2
.rm_dec
.inv
2615 cr_bit
= yield self
.dec2
.rm_dec
.cr_sel
2616 RC1
= yield self
.dec2
.rm_dec
.RC1
2617 vli_
= yield self
.dec2
.rm_dec
.vli
# VL inclusive if truncated
2618 log(" ff rm_mode", rc_en
, rm_mode
, SVP64RMMode
.FFIRST
.value
)
2622 log(" cr_bit", cr_bit
)
2623 log(" rc_en", rc_en
)
2624 ffirst
= yield from is_ffirst_mode(self
.dec2
)
2625 if not rc_en
or not ffirst
:
2627 # get the CR vevtor, do BO-test
2629 log("asmregs", info
.asmregs
[0], info
.write_regs
)
2630 if 'CR' in info
.write_regs
and 'BF' in info
.asmregs
[0]:
2632 regnum
, is_vec
= yield from get_cr_out(self
.dec2
, crf
)
2633 crtest
= self
.crl
[regnum
]
2634 ffirst_hit
= crtest
[cr_bit
] != ff_inv
2635 log("cr test", crf
, regnum
, int(crtest
), crtest
, cr_bit
, ff_inv
)
2636 log("cr test?", ffirst_hit
)
2639 # Fail-first activated, truncate VL
2640 vli
= SelectableInt(int(vli_
), 7)
2641 self
.svstate
.vl
= srcstep
+ vli
2642 yield self
.dec2
.state
.svstate
.eq(self
.svstate
.value
)
2643 yield Settle() # let decoder update
2646 def do_rc_ov(self
, ins_name
, result
, overflow
, cr0
, cr1
, FPSCR
):
2647 cr_out
= yield self
.dec2
.op
.cr_out
2648 if cr_out
== CROutSel
.CR1
.value
:
2652 regnum
, is_vec
= yield from get_cr_out(self
.dec2
, rc_reg
)
2653 # hang on... for `setvl` actually you want to test SVSTATE.VL
2654 is_setvl
= ins_name
in ('svstep', 'setvl')
2656 result
= SelectableInt(result
.vl
, 64)
2658 # overflow = None # do not override overflow except in setvl
2662 cr1
= int(FPSCR
.FX
) << 3
2663 cr1 |
= int(FPSCR
.FEX
) << 2
2664 cr1 |
= int(FPSCR
.VX
) << 1
2665 cr1 |
= int(FPSCR
.OX
)
2666 log("default fp cr1", cr1
)
2668 log("explicit cr1", cr1
)
2669 self
.crl
[regnum
].eq(cr1
)
2671 # if there was not an explicit CR0 in the pseudocode,
2673 c
= self
.handle_comparison(result
, regnum
, overflow
, no_so
=is_setvl
)
2674 log("implicit cr0", c
)
2676 # otherwise we just blat CR0 into the required regnum
2677 log("explicit cr0", cr0
)
2678 self
.crl
[regnum
].eq(cr0
)
2680 def do_outregs(self
, info
, outs
, ca_en
, ffirst_hit
, ew_dst
, outs_ok
):
2681 ffirst_hit
, vli
= ffirst_hit
2682 # write out any regs for this instruction, but only if fail-first is ok
2683 # XXX TODO: allow CR-vector to be written out even if ffirst fails
2684 if not ffirst_hit
or vli
:
2685 for name
, output
in outs
.items():
2686 if not outs_ok
[name
]:
2687 log("skipping writing output with .ok=False", name
, output
)
2689 yield from self
.check_write(info
, name
, output
, ca_en
, ew_dst
)
2690 # restore the CR value on non-VLI failfirst (from sv.cmp and others
2691 # which write directly to CR in the pseudocode (gah, what a mess)
2692 # if ffirst_hit and not vli:
2693 # self.cr.value = self.cr_backup
2695 def do_nia(self
, asmop
, ins_name
, rc_en
, ffirst_hit
):
2696 ffirst_hit
, vli
= ffirst_hit
2698 self
.svp64_reset_loop()
2701 # check advancement of src/dst/sub-steps and if PC needs updating
2702 nia_update
= (yield from self
.check_step_increment(
2703 rc_en
, asmop
, ins_name
))
2705 self
.update_pc_next()
2707 def check_replace_d(self
, info
, remap_active
):
2708 replace_d
= False # update / replace constant in pseudocode
2709 ldstmode
= yield self
.dec2
.rm_dec
.ldstmode
2710 vl
= self
.svstate
.vl
2711 subvl
= yield self
.dec2
.rm_dec
.rm_in
.subvl
2712 srcstep
, dststep
= self
.new_srcstep
, self
.new_dststep
2713 ssubstep
, dsubstep
= self
.new_ssubstep
, self
.new_dsubstep
2714 if info
.form
== 'DS':
2715 # DS-Form, multiply by 4 then knock 2 bits off after
2716 imm
= yield self
.dec2
.dec
.fields
.FormDS
.DS
[0:14] * 4
2718 imm
= yield self
.dec2
.dec
.fields
.FormD
.D
[0:16]
2719 imm
= exts(imm
, 16) # sign-extend to integer
2720 # get the right step. LD is from srcstep, ST is dststep
2721 op
= yield self
.dec2
.e
.do
.insn_type
2723 if op
== MicrOp
.OP_LOAD
.value
:
2725 offsmul
= yield self
.dec2
.in1_step
2726 log("D-field REMAP src", imm
, offsmul
, ldstmode
)
2728 offsmul
= (srcstep
* (subvl
+1)) + ssubstep
2729 log("D-field src", imm
, offsmul
, ldstmode
)
2730 elif op
== MicrOp
.OP_STORE
.value
:
2731 # XXX NOTE! no bit-reversed STORE! this should not ever be used
2732 offsmul
= (dststep
* (subvl
+1)) + dsubstep
2733 log("D-field dst", imm
, offsmul
, ldstmode
)
2734 # Unit-Strided LD/ST adds offset*width to immediate
2735 if ldstmode
== SVP64LDSTmode
.UNITSTRIDE
.value
:
2736 ldst_len
= yield self
.dec2
.e
.do
.data_len
2737 imm
= SelectableInt(imm
+ offsmul
* ldst_len
, 32)
2739 # Element-strided multiplies the immediate by element step
2740 elif ldstmode
== SVP64LDSTmode
.ELSTRIDE
.value
:
2741 imm
= SelectableInt(imm
* offsmul
, 32)
2744 ldst_ra_vec
= yield self
.dec2
.rm_dec
.ldst_ra_vec
2745 ldst_imz_in
= yield self
.dec2
.rm_dec
.ldst_imz_in
2746 log("LDSTmode", SVP64LDSTmode(ldstmode
),
2747 offsmul
, imm
, ldst_ra_vec
, ldst_imz_in
)
2748 # new replacement D... errr.. DS
2750 if info
.form
== 'DS':
2751 # TODO: assert 2 LSBs are zero?
2752 log("DS-Form, TODO, assert 2 LSBs zero?", bin(imm
.value
))
2753 imm
.value
= imm
.value
>> 2
2754 self
.namespace
['DS'] = imm
2756 self
.namespace
['D'] = imm
2758 def get_input(self
, name
, ew_src
, xlen
):
2759 # using PowerDecoder2, first, find the decoder index.
2760 # (mapping name RA RB RC RS to in1, in2, in3)
2761 regnum
, is_vec
= yield from get_idx_in(self
.dec2
, name
, True)
2763 # doing this is not part of svp64, it's because output
2764 # registers, to be modified, need to be in the namespace.
2765 regnum
, is_vec
= yield from get_idx_out(self
.dec2
, name
, True)
2767 regnum
, is_vec
= yield from get_idx_out2(self
.dec2
, name
, True)
2769 if isinstance(regnum
, tuple):
2770 (regnum
, base
, offs
) = regnum
2772 base
, offs
= regnum
, 0 # temporary HACK
2774 # in case getting the register number is needed, _RA, _RB
2775 # (HACK: only in straight non-svp64-mode for now, or elwidth == 64)
2776 regname
= "_" + name
2777 if not self
.is_svp64_mode
or ew_src
== 64:
2778 self
.namespace
[regname
] = regnum
2780 # FIXME: we're trying to access a sub-register, plain register
2781 # numbers don't work for that. for now, just pass something that
2782 # can be compared to 0 and probably will cause an error if misused.
2783 # see https://bugs.libre-soc.org/show_bug.cgi?id=1221
2784 self
.namespace
[regname
] = regnum
* 10000
2786 if not self
.is_svp64_mode
or not self
.pred_src_zero
:
2787 log('reading reg %s %s' % (name
, str(regnum
)), is_vec
)
2789 fval
= self
.fpr(base
, is_vec
, offs
, ew_src
)
2790 reg_val
= SelectableInt(fval
)
2791 assert ew_src
== self
.XLEN
, "TODO fix elwidth conversion"
2792 self
.trace("r:FPR:%d:%d:%d " % (base
, offs
, ew_src
))
2793 log("read fp reg %d/%d: 0x%x" % (base
, offs
, reg_val
.value
),
2794 kind
=LogType
.InstrInOuts
)
2795 elif name
is not None:
2796 gval
= self
.gpr(base
, is_vec
, offs
, ew_src
)
2797 reg_val
= SelectableInt(gval
.value
, bits
=xlen
)
2798 self
.trace("r:GPR:%d:%d:%d " % (base
, offs
, ew_src
))
2799 log("read int reg %d/%d: 0x%x" % (base
, offs
, reg_val
.value
),
2800 kind
=LogType
.InstrInOuts
)
2802 log('zero input reg %s %s' % (name
, str(regnum
)), is_vec
)
2803 reg_val
= SelectableInt(0, ew_src
)
2806 def remap_set_steps(self
, remaps
):
2807 """remap_set_steps sets up the in1/2/3 and out1/2 steps.
2808 they work in concert with PowerDecoder2 at the moment,
2809 there is no HDL implementation of REMAP. therefore this
2810 function, because ISACaller still uses PowerDecoder2,
2811 will *explicitly* write the dec2.XX_step values. this has
2814 # just some convenient debug info
2816 sname
= 'SVSHAPE%d' % i
2817 shape
= self
.spr
[sname
]
2818 log(sname
, bin(shape
.value
))
2819 log(" lims", shape
.lims
)
2820 log(" mode", shape
.mode
)
2821 log(" skip", shape
.skip
)
2823 # set up the list of steps to remap
2824 mi0
= self
.svstate
.mi0
2825 mi1
= self
.svstate
.mi1
2826 mi2
= self
.svstate
.mi2
2827 mo0
= self
.svstate
.mo0
2828 mo1
= self
.svstate
.mo1
2829 steps
= [[self
.dec2
.in1_step
, mi0
], # RA
2830 [self
.dec2
.in2_step
, mi1
], # RB
2831 [self
.dec2
.in3_step
, mi2
], # RC
2832 [self
.dec2
.o_step
, mo0
], # RT
2833 [self
.dec2
.o2_step
, mo1
], # EA
2836 rnames
= ['RA', 'RB', 'RC', 'RT', 'RS']
2837 for i
, reg
in enumerate(rnames
):
2838 idx
= yield from get_idx_map(self
.dec2
, reg
)
2840 idx
= yield from get_idx_map(self
.dec2
, "F"+reg
)
2842 steps
[i
][0] = self
.dec2
.in1_step
2844 steps
[i
][0] = self
.dec2
.in2_step
2846 steps
[i
][0] = self
.dec2
.in3_step
2847 log("remap step", i
, reg
, idx
, steps
[i
][1])
2848 remap_idxs
= self
.remap_idxs
2850 # now cross-index the required SHAPE for each of 3-in 2-out regs
2851 rnames
= ['RA', 'RB', 'RC', 'RT', 'EA']
2852 for i
, (dstep
, shape_idx
) in enumerate(steps
):
2853 (shape
, remap
) = remaps
[shape_idx
]
2854 remap_idx
= remap_idxs
[shape_idx
]
2855 # zero is "disabled"
2856 if shape
.value
== 0x0:
2858 # now set the actual requested step to the current index
2859 if dstep
is not None:
2860 yield dstep
.eq(remap_idx
)
2862 # debug printout info
2863 rremaps
.append((shape
.mode
, hex(shape
.value
), dstep
,
2864 i
, rnames
[i
], shape_idx
, remap_idx
))
2866 log("shape remap", x
)
2868 def check_write(self
, info
, name
, output
, carry_en
, ew_dst
):
2869 if name
== 'overflow': # ignore, done already (above)
2871 if name
== 'CR0': # ignore, done already (above)
2873 if isinstance(output
, int):
2874 output
= SelectableInt(output
, EFFECTIVELY_UNLIMITED
)
2876 if name
.startswith("RESERVE"):
2877 log("write %s 0x%x" % (name
, output
.value
))
2878 getattr(self
, name
).eq(output
)
2880 if name
in ['FPSCR', ]:
2881 log("write FPSCR 0x%x" % (output
.value
))
2882 self
.FPSCR
.eq(output
)
2885 if name
in ['CA', 'CA32']:
2887 log("writing %s to XER" % name
, output
)
2888 log("write XER %s 0x%x" % (name
, output
.value
))
2889 self
.spr
['XER'][XER_bits
[name
]] = output
.value
2891 log("NOT writing %s to XER" % name
, output
)
2893 # write special SPRs
2894 if name
in info
.special_regs
:
2895 log('writing special %s' % name
, output
, special_sprs
)
2896 log("write reg %s 0x%x" % (name
, output
.value
),
2897 kind
=LogType
.InstrInOuts
)
2898 if name
in special_sprs
:
2899 self
.spr
[name
] = output
2901 self
.namespace
[name
].eq(output
)
2903 log('msr written', hex(self
.msr
.value
))
2905 # find out1/out2 PR/FPR
2906 regnum
, is_vec
= yield from get_idx_out(self
.dec2
, name
, True)
2908 regnum
, is_vec
= yield from get_idx_out2(self
.dec2
, name
, True)
2910 # temporary hack for not having 2nd output
2911 regnum
= yield getattr(self
.decoder
, name
)
2913 # convenient debug prefix
2918 # check zeroing due to predicate bit being zero
2919 if self
.is_svp64_mode
and self
.pred_dst_zero
:
2920 log('zeroing reg %s %s' % (str(regnum
), str(output
)), is_vec
)
2921 output
= SelectableInt(0, EFFECTIVELY_UNLIMITED
)
2922 log("write reg %s%s 0x%x ew %d" % (reg_prefix
, str(regnum
),
2923 output
.value
, ew_dst
),
2924 kind
=LogType
.InstrInOuts
)
2925 # zero-extend tov64 bit begore storing (should use EXT oh well)
2926 if output
.bits
> 64:
2927 output
= SelectableInt(output
.value
, 64)
2928 rnum
, base
, offset
= regnum
2930 self
.fpr
.write(regnum
, output
, is_vec
, ew_dst
)
2931 self
.trace("w:FPR:%d:%d:%d " % (rnum
, offset
, ew_dst
))
2934 # LDST/Update does *not* allow elwidths on RA (Effective Address).
2935 # this has to be detected, and overridden. see get_input (related)
2936 sv_mode
= yield self
.dec2
.rm_dec
.sv_mode
2937 is_ldst
= (sv_mode
in [SVMode
.LDST_IDX
.value
, SVMode
.LDST_IMM
.value
] \
2938 and self
.is_svp64_mode
)
2939 if is_ldst
and name
in ['EA', 'RA']:
2940 op
= self
.dec2
.dec
.op
2941 if hasattr(op
, "upd"):
2942 # update mode LD/ST uses read-reg A also as an output
2944 log("write is_ldst is_update", sv_mode
, is_ldst
, upd
)
2945 if upd
== LDSTMode
.update
.value
:
2946 ew_dst
= 64 # override for RA (EA) to 64-bit
2948 self
.gpr
.write(regnum
, output
, is_vec
, ew_dst
)
2949 self
.trace("w:GPR:%d:%d:%d " % (rnum
, offset
, ew_dst
))
2951 def check_step_increment(self
, rc_en
, asmop
, ins_name
):
2952 # check if it is the SVSTATE.src/dest step that needs incrementing
2953 # this is our Sub-Program-Counter loop from 0 to VL-1
2954 if not self
.allow_next_step_inc
:
2955 if self
.is_svp64_mode
:
2956 return (yield from self
.svstate_post_inc(ins_name
))
2958 # XXX only in non-SVP64 mode!
2959 # record state of whether the current operation was an svshape,
2961 # to be able to know if it should apply in the next instruction.
2962 # also (if going to use this instruction) should disable ability
2963 # to interrupt in between. sigh.
2964 self
.last_op_svshape
= asmop
in ['svremap', 'svindex',
2971 log("SVSTATE_NEXT: inc requested, mode",
2972 self
.svstate_next_mode
, self
.allow_next_step_inc
)
2973 yield from self
.svstate_pre_inc()
2974 pre
= yield from self
.update_new_svstate_steps()
2976 # reset at end of loop including exit Vertical Mode
2977 log("SVSTATE_NEXT: end of loop, reset")
2978 self
.svp64_reset_loop()
2979 self
.svstate
.vfirst
= 0
2983 self
.handle_comparison(SelectableInt(0, 64)) # CR0
2985 if self
.allow_next_step_inc
== 2:
2986 log("SVSTATE_NEXT: read")
2987 nia_update
= (yield from self
.svstate_post_inc(ins_name
))
2989 log("SVSTATE_NEXT: post-inc")
2990 # use actual (cached) src/dst-step here to check end
2991 remaps
= self
.get_remap_indices()
2992 remap_idxs
= self
.remap_idxs
2993 vl
= self
.svstate
.vl
2994 subvl
= yield self
.dec2
.rm_dec
.rm_in
.subvl
2995 if self
.allow_next_step_inc
!= 2:
2996 yield from self
.advance_svstate_steps()
2997 #self.namespace['SVSTATE'] = self.svstate.spr
2998 # set CR0 (if Rc=1) based on end
2999 endtest
= 1 if self
.at_loopend() else 0
3001 #results = [SelectableInt(endtest, 64)]
3002 # self.handle_comparison(results) # CR0
3004 # see if svstep was requested, if so, which SVSTATE
3006 if self
.svstate_next_mode
> 0:
3007 shape_idx
= self
.svstate_next_mode
.value
-1
3008 endings
= self
.remap_loopends
[shape_idx
]
3009 cr_field
= SelectableInt((~endings
) << 1 | endtest
, 4)
3010 log("svstep Rc=1, CR0", cr_field
, endtest
)
3011 self
.crl
[0].eq(cr_field
) # CR0
3013 # reset at end of loop including exit Vertical Mode
3014 log("SVSTATE_NEXT: after increments, reset")
3015 self
.svp64_reset_loop()
3016 self
.svstate
.vfirst
= 0
3019 def SVSTATE_NEXT(self
, mode
, submode
):
3020 """explicitly moves srcstep/dststep on to next element, for
3021 "Vertical-First" mode. this function is called from
3022 setvl pseudo-code, as a pseudo-op "svstep"
3024 WARNING: this function uses information that was created EARLIER
3025 due to it being in the middle of a yield, but this function is
3026 *NOT* called from yield (it's called from compiled pseudocode).
3028 self
.allow_next_step_inc
= submode
.value
+ 1
3029 log("SVSTATE_NEXT mode", mode
, submode
, self
.allow_next_step_inc
)
3030 self
.svstate_next_mode
= mode
3031 if self
.svstate_next_mode
> 0 and self
.svstate_next_mode
< 5:
3032 shape_idx
= self
.svstate_next_mode
.value
-1
3033 return SelectableInt(self
.remap_idxs
[shape_idx
], 7)
3034 if self
.svstate_next_mode
== 5:
3035 self
.svstate_next_mode
= 0
3036 return SelectableInt(self
.svstate
.srcstep
, 7)
3037 if self
.svstate_next_mode
== 6:
3038 self
.svstate_next_mode
= 0
3039 return SelectableInt(self
.svstate
.dststep
, 7)
3040 if self
.svstate_next_mode
== 7:
3041 self
.svstate_next_mode
= 0
3042 return SelectableInt(self
.svstate
.ssubstep
, 7)
3043 if self
.svstate_next_mode
== 8:
3044 self
.svstate_next_mode
= 0
3045 return SelectableInt(self
.svstate
.dsubstep
, 7)
3046 return SelectableInt(0, 7)
3048 def get_src_dststeps(self
):
3049 """gets srcstep, dststep, and ssubstep, dsubstep
3051 return (self
.new_srcstep
, self
.new_dststep
,
3052 self
.new_ssubstep
, self
.new_dsubstep
)
3054 def update_svstate_namespace(self
, overwrite_svstate
=True):
3055 if overwrite_svstate
:
3056 # note, do not get the bit-reversed srcstep here!
3057 srcstep
, dststep
= self
.new_srcstep
, self
.new_dststep
3058 ssubstep
, dsubstep
= self
.new_ssubstep
, self
.new_dsubstep
3060 # update SVSTATE with new srcstep
3061 self
.svstate
.srcstep
= srcstep
3062 self
.svstate
.dststep
= dststep
3063 self
.svstate
.ssubstep
= ssubstep
3064 self
.svstate
.dsubstep
= dsubstep
3065 self
.namespace
['SVSTATE'] = self
.svstate
3066 yield self
.dec2
.state
.svstate
.eq(self
.svstate
.value
)
3067 yield Settle() # let decoder update
3069 def update_new_svstate_steps(self
, overwrite_svstate
=True):
3070 yield from self
.update_svstate_namespace(overwrite_svstate
)
3071 srcstep
= self
.svstate
.srcstep
3072 dststep
= self
.svstate
.dststep
3073 ssubstep
= self
.svstate
.ssubstep
3074 dsubstep
= self
.svstate
.dsubstep
3075 pack
= self
.svstate
.pack
3076 unpack
= self
.svstate
.unpack
3077 vl
= self
.svstate
.vl
3078 sv_mode
= yield self
.dec2
.rm_dec
.sv_mode
3079 subvl
= yield self
.dec2
.rm_dec
.rm_in
.subvl
3080 rm_mode
= yield self
.dec2
.rm_dec
.mode
3081 ff_inv
= yield self
.dec2
.rm_dec
.inv
3082 cr_bit
= yield self
.dec2
.rm_dec
.cr_sel
3083 log(" srcstep", srcstep
)
3084 log(" dststep", dststep
)
3086 log(" unpack", unpack
)
3087 log(" ssubstep", ssubstep
)
3088 log(" dsubstep", dsubstep
)
3090 log(" subvl", subvl
)
3091 log(" rm_mode", rm_mode
)
3092 log(" sv_mode", sv_mode
)
3094 log(" cr_bit", cr_bit
)
3096 # check if end reached (we let srcstep overrun, above)
3097 # nothing needs doing (TODO zeroing): just do next instruction
3100 return ((ssubstep
== subvl
and srcstep
== vl
) or
3101 (dsubstep
== subvl
and dststep
== vl
))
3103 def svstate_post_inc(self
, insn_name
, vf
=0):
3104 # check if SV "Vertical First" mode is enabled
3105 vfirst
= self
.svstate
.vfirst
3106 log(" SV Vertical First", vf
, vfirst
)
3107 if not vf
and vfirst
== 1:
3108 # SV Branch-Conditional required to be as-if-vector
3109 # because there *is* no destination register
3110 # (SV normally only terminates on 1st scalar reg written
3111 # except in [slightly-misnamed] mapreduce mode)
3112 ffirst
= yield from is_ffirst_mode(self
.dec2
)
3113 if insn_name
.startswith("sv.bc") or ffirst
:
3114 self
.update_pc_next()
3119 # check if it is the SVSTATE.src/dest step that needs incrementing
3120 # this is our Sub-Program-Counter loop from 0 to VL-1
3121 # XXX twin predication TODO
3122 vl
= self
.svstate
.vl
3123 subvl
= yield self
.dec2
.rm_dec
.rm_in
.subvl
3124 mvl
= self
.svstate
.maxvl
3125 srcstep
= self
.svstate
.srcstep
3126 dststep
= self
.svstate
.dststep
3127 ssubstep
= self
.svstate
.ssubstep
3128 dsubstep
= self
.svstate
.dsubstep
3129 pack
= self
.svstate
.pack
3130 unpack
= self
.svstate
.unpack
3131 rm_mode
= yield self
.dec2
.rm_dec
.mode
3132 reverse_gear
= yield self
.dec2
.rm_dec
.reverse_gear
3133 sv_ptype
= yield self
.dec2
.dec
.op
.SV_Ptype
3134 out_vec
= not (yield self
.dec2
.no_out_vec
)
3135 in_vec
= not (yield self
.dec2
.no_in_vec
)
3136 rm_mode
= yield self
.dec2
.rm_dec
.mode
3137 log(" svstate.vl", vl
)
3138 log(" svstate.mvl", mvl
)
3139 log(" rm.subvl", subvl
)
3140 log(" svstate.srcstep", srcstep
)
3141 log(" svstate.dststep", dststep
)
3142 log(" svstate.ssubstep", ssubstep
)
3143 log(" svstate.dsubstep", dsubstep
)
3144 log(" svstate.pack", pack
)
3145 log(" svstate.unpack", unpack
)
3146 log(" mode", rm_mode
)
3147 log(" reverse", reverse_gear
)
3148 log(" out_vec", out_vec
)
3149 log(" in_vec", in_vec
)
3150 log(" sv_ptype", sv_ptype
, sv_ptype
== SVPType
.P2
.value
)
3151 log(" rm_mode", rm_mode
)
3152 # check if this was an sv.bc* and if so did it succeed
3153 if self
.is_svp64_mode
and insn_name
.startswith("sv.bc"):
3154 end_loop
= self
.namespace
['end_loop']
3155 log("branch %s end_loop" % insn_name
, end_loop
)
3157 self
.svp64_reset_loop()
3158 self
.update_pc_next()
3160 # check if srcstep needs incrementing by one, stop PC advancing
3161 # but for 2-pred both src/dest have to be checked.
3162 # XXX this might not be true! it may just be LD/ST
3163 if sv_ptype
== SVPType
.P2
.value
:
3164 svp64_is_vector
= (out_vec
or in_vec
)
3166 svp64_is_vector
= out_vec
3167 # also if data-dependent fail-first is used, only in_vec is tested,
3168 # allowing *scalar destinations* to be used as an accumulator.
3169 # effectively this implies /mr (mapreduce mode) is 100% on with ddffirst
3170 # see https://bugs.libre-soc.org/show_bug.cgi?id=1183#c16
3171 ffirst
= yield from is_ffirst_mode(self
.dec2
)
3173 svp64_is_vector
= in_vec
3175 # loops end at the first "hit" (source or dest)
3176 yield from self
.advance_svstate_steps()
3177 loopend
= self
.loopend
3178 log("loopend", svp64_is_vector
, loopend
)
3179 if not svp64_is_vector
or loopend
:
3180 # reset loop to zero and update NIA
3181 self
.svp64_reset_loop()
3186 # still looping, advance and update NIA
3187 self
.namespace
['SVSTATE'] = self
.svstate
3189 # not an SVP64 branch, so fix PC (NIA==CIA) for next loop
3190 # (by default, NIA is CIA+4 if v3.0B or CIA+8 if SVP64)
3191 # this way we keep repeating the same instruction (with new steps)
3192 self
.pc
.NIA
.eq(self
.pc
.CIA
)
3193 self
.namespace
['NIA'] = self
.pc
.NIA
3194 log("end of sub-pc call", self
.namespace
['CIA'], self
.namespace
['NIA'])
3195 return False # DO NOT allow PC update whilst Sub-PC loop running
3197 def update_pc_next(self
):
3198 # UPDATE program counter
3199 self
.pc
.update(self
.namespace
, self
.is_svp64_mode
)
3200 #self.svstate.spr = self.namespace['SVSTATE']
3201 log("end of call", self
.namespace
['CIA'],
3202 self
.namespace
['NIA'],
3203 self
.namespace
['SVSTATE'])
3205 def svp64_reset_loop(self
):
3206 self
.svstate
.srcstep
= 0
3207 self
.svstate
.dststep
= 0
3208 self
.svstate
.ssubstep
= 0
3209 self
.svstate
.dsubstep
= 0
3210 self
.loopend
= False
3211 log(" svstate.srcstep loop end (PC to update)")
3212 self
.namespace
['SVSTATE'] = self
.svstate
3214 def update_nia(self
):
3215 self
.pc
.update_nia(self
.is_svp64_mode
)
3216 self
.namespace
['NIA'] = self
.pc
.NIA
3220 """Decorator factory.
3222 this decorator will "inject" variables into the function's namespace,
3223 from the *dictionary* in self.namespace. it therefore becomes possible
3224 to make it look like a whole stack of variables which would otherwise
3225 need "self." inserted in front of them (*and* for those variables to be
3226 added to the instance) "appear" in the function.
3228 "self.namespace['SI']" for example becomes accessible as just "SI" but
3229 *only* inside the function, when decorated.
3231 def variable_injector(func
):
3233 def decorator(*args
, **kwargs
):
3235 func_globals
= func
.__globals
__ # Python 2.6+
3236 except AttributeError:
3237 func_globals
= func
.func_globals
# Earlier versions.
3239 context
= args
[0].namespace
# variables to be injected
3240 saved_values
= func_globals
.copy() # Shallow copy of dict.
3241 log("globals before", context
.keys())
3242 func_globals
.update(context
)
3243 result
= func(*args
, **kwargs
)
3244 log("globals after", func_globals
['CIA'], func_globals
['NIA'])
3245 log("args[0]", args
[0].namespace
['CIA'],
3246 args
[0].namespace
['NIA'],
3247 args
[0].namespace
['SVSTATE'])
3248 if 'end_loop' in func_globals
:
3249 log("args[0] end_loop", func_globals
['end_loop'])
3250 args
[0].namespace
= func_globals
3251 #exec (func.__code__, func_globals)
3254 # func_globals = saved_values # Undo changes.
3260 return variable_injector