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 nmigen
.sim
import Settle
23 import openpower
.syscalls
24 from openpower
.consts
import (MSRb
, PIb
, # big-endian (PowerISA versions)
25 SVP64CROffs
, SVP64MODEb
)
26 from openpower
.decoder
.helpers
import (ISACallerHelper
, ISAFPHelpers
, exts
,
27 gtu
, undefined
, copy_assign_rhs
)
28 from openpower
.decoder
.isa
.mem
import Mem
, MemMMap
, MemException
29 from openpower
.decoder
.isa
.radixmmu
import RADIX
30 from openpower
.decoder
.isa
.svshape
import SVSHAPE
31 from openpower
.decoder
.isa
.svstate
import SVP64State
32 from openpower
.decoder
.orderedset
import OrderedSet
33 from openpower
.decoder
.power_enums
import (FPTRANS_INSNS
, CRInSel
, CROutSel
,
34 In1Sel
, In2Sel
, In3Sel
, LDSTMode
,
35 MicrOp
, OutSel
, SVMode
,
36 SVP64LDSTmode
, SVP64PredCR
,
37 SVP64PredInt
, SVP64PredMode
,
38 SVP64RMMode
, SVPType
, XER_bits
,
39 insns
, spr_byname
, spr_dict
,
41 from openpower
.insndb
.core
import SVP64Instruction
42 from openpower
.decoder
.power_svp64
import SVP64RM
, decode_extra
43 from openpower
.decoder
.selectable_int
import (FieldSelectableInt
,
44 SelectableInt
, selectconcat
,
45 EFFECTIVELY_UNLIMITED
)
46 from openpower
.consts
import DEFAULT_MSR
47 from openpower
.fpscr
import FPSCRState
48 from openpower
.xer
import XERState
49 from openpower
.util
import LogType
, log
51 LDST_UPDATE_INSNS
= ['ldu', 'lwzu', 'lbzu', 'lhzu', 'lhau', 'lfsu', 'lfdu',
52 'stwu', 'stbu', 'sthu', 'stfsu', 'stfdu', 'stdu',
56 instruction_info
= namedtuple('instruction_info',
57 'func read_regs uninit_regs write_regs ' +
58 'special_regs op_fields form asmregs')
68 # rrright. this is here basically because the compiler pywriter returns
69 # results in a specific priority order. to make sure regs match up they
70 # need partial sorting. sigh.
72 # TODO (lkcl): adjust other registers that should be in a particular order
73 # probably CA, CA32, and CR
101 "overflow": 7, # should definitely be last
105 fregs
= ['FRA', 'FRB', 'FRC', 'FRS', 'FRT']
108 def get_masked_reg(regs
, base
, offs
, ew_bits
):
109 # rrrright. start by breaking down into row/col, based on elwidth
110 gpr_offs
= offs
// (64 // ew_bits
)
111 gpr_col
= offs
% (64 // ew_bits
)
112 # compute the mask based on ew_bits
113 mask
= (1 << ew_bits
) - 1
114 # now select the 64-bit register, but get its value (easier)
115 val
= regs
[base
+ gpr_offs
]
116 # shift down so element we want is at LSB
117 val
>>= gpr_col
* ew_bits
118 # mask so we only return the LSB element
122 def set_masked_reg(regs
, base
, offs
, ew_bits
, value
):
123 # rrrright. start by breaking down into row/col, based on elwidth
124 gpr_offs
= offs
// (64//ew_bits
)
125 gpr_col
= offs
% (64//ew_bits
)
126 # compute the mask based on ew_bits
127 mask
= (1 << ew_bits
)-1
128 # now select the 64-bit register, but get its value (easier)
129 val
= regs
[base
+gpr_offs
]
130 # now mask out the bit we don't want
131 val
= val
& ~
(mask
<< (gpr_col
*ew_bits
))
132 # then wipe the bit we don't want from the value
134 # OR the new value in, shifted up
135 val |
= value
<< (gpr_col
*ew_bits
)
136 regs
[base
+gpr_offs
] = val
139 def create_args(reglist
, extra
=None):
140 retval
= list(OrderedSet(reglist
))
141 retval
.sort(key
=lambda reg
: REG_SORT_ORDER
.get(reg
, 0))
142 if extra
is not None:
143 return [extra
] + retval
147 def create_full_args(*, read_regs
, special_regs
, uninit_regs
, write_regs
,
150 *read_regs
, *uninit_regs
, *write_regs
, *special_regs
], extra
=extra
)
154 def __init__(self
, decoder
, isacaller
, svstate
, regfile
):
157 self
.isacaller
= isacaller
158 self
.svstate
= svstate
159 for i
in range(len(regfile
)):
160 self
[i
] = SelectableInt(regfile
[i
], 64)
162 def __call__(self
, ridx
, is_vec
=False, offs
=0, elwidth
=64):
163 if isinstance(ridx
, SelectableInt
):
166 return self
[ridx
+offs
]
167 # rrrright. start by breaking down into row/col, based on elwidth
168 gpr_offs
= offs
// (64//elwidth
)
169 gpr_col
= offs
% (64//elwidth
)
170 # now select the 64-bit register, but get its value (easier)
171 val
= self
[ridx
+gpr_offs
].value
172 # now shift down and mask out
173 val
= val
>> (gpr_col
*elwidth
) & ((1 << elwidth
)-1)
174 # finally, return a SelectableInt at the required elwidth
175 log("GPR call", ridx
, "isvec", is_vec
, "offs", offs
,
176 "elwid", elwidth
, "offs/col", gpr_offs
, gpr_col
, "val", hex(val
))
177 return SelectableInt(val
, elwidth
)
179 def set_form(self
, form
):
182 def write(self
, rnum
, value
, is_vec
=False, elwidth
=64):
184 if isinstance(rnum
, SelectableInt
):
186 if isinstance(value
, SelectableInt
):
189 if isinstance(rnum
, tuple):
190 rnum
, base
, offs
= rnum
193 # rrrright. start by breaking down into row/col, based on elwidth
194 gpr_offs
= offs
// (64//elwidth
)
195 gpr_col
= offs
% (64//elwidth
)
196 # compute the mask based on elwidth
197 mask
= (1 << elwidth
)-1
198 # now select the 64-bit register, but get its value (easier)
199 val
= self
[base
+gpr_offs
].value
200 # now mask out the bit we don't want
201 val
= val
& ~
(mask
<< (gpr_col
*elwidth
))
202 # then wipe the bit we don't want from the value
204 # OR the new value in, shifted up
205 val |
= value
<< (gpr_col
*elwidth
)
206 # finally put the damn value into the regfile
207 log("GPR write", base
, "isvec", is_vec
, "offs", offs
,
208 "elwid", elwidth
, "offs/col", gpr_offs
, gpr_col
, "val", hex(val
),
210 dict.__setitem
__(self
, base
+gpr_offs
, SelectableInt(val
, 64))
212 def __setitem__(self
, rnum
, value
):
213 # rnum = rnum.value # only SelectableInt allowed
214 log("GPR setitem", rnum
, value
)
215 if isinstance(rnum
, SelectableInt
):
217 dict.__setitem
__(self
, rnum
, value
)
219 def getz(self
, rnum
):
220 # rnum = rnum.value # only SelectableInt allowed
221 log("GPR getzero?", rnum
)
223 return SelectableInt(0, 64)
226 def _get_regnum(self
, attr
):
227 getform
= self
.sd
.sigforms
[self
.form
]
228 rnum
= getattr(getform
, attr
)
231 def ___getitem__(self
, attr
):
232 """ XXX currently not used
234 rnum
= self
._get
_regnum
(attr
)
235 log("GPR getitem", attr
, rnum
)
236 return self
.regfile
[rnum
]
238 def dump(self
, printout
=True):
240 for i
in range(len(self
)):
241 res
.append(self
[i
].value
)
243 for i
in range(0, len(res
), 8):
246 s
.append("%08x" % res
[i
+j
])
248 log("reg", "%2d" % i
, s
, kind
=LogType
.InstrInOuts
)
253 def __init__(self
, dec2
, initial_sprs
={}, gpr
=None):
255 self
.gpr
= gpr
# for SVSHAPE[0-3]
257 for key
, v
in initial_sprs
.items():
258 if isinstance(key
, SelectableInt
):
260 key
= special_sprs
.get(key
, key
)
261 if isinstance(key
, int):
264 info
= spr_byname
[key
]
265 if not isinstance(v
, SelectableInt
):
266 v
= SelectableInt(v
, info
.length
)
269 def __getitem__(self
, key
):
271 #log("dict", self.items())
272 # if key in special_sprs get the special spr, otherwise return key
273 if isinstance(key
, SelectableInt
):
275 if isinstance(key
, int):
276 key
= spr_dict
[key
].SPR
277 key
= special_sprs
.get(key
, key
)
278 if key
== 'HSRR0': # HACK!
280 if key
== 'HSRR1': # HACK!
283 res
= dict.__getitem
__(self
, key
)
285 if isinstance(key
, int):
288 info
= spr_byname
[key
]
289 self
[key
] = SelectableInt(0, info
.length
)
290 res
= dict.__getitem
__(self
, key
)
291 #log("spr returning", key, res)
294 def __setitem__(self
, key
, value
):
295 if isinstance(key
, SelectableInt
):
297 if isinstance(key
, int):
298 key
= spr_dict
[key
].SPR
300 key
= special_sprs
.get(key
, key
)
301 if key
== 'HSRR0': # HACK!
302 self
.__setitem
__('SRR0', value
)
303 if key
== 'HSRR1': # HACK!
304 self
.__setitem
__('SRR1', value
)
306 value
= XERState(value
)
307 if key
in ('SVSHAPE0', 'SVSHAPE1', 'SVSHAPE2', 'SVSHAPE3'):
308 value
= SVSHAPE(value
, self
.gpr
)
309 log("setting spr", key
, value
)
310 dict.__setitem
__(self
, key
, value
)
312 def __call__(self
, ridx
):
315 def dump(self
, printout
=True):
317 keys
= list(self
.keys())
320 sprname
= spr_dict
.get(k
, None)
324 sprname
= sprname
.SPR
325 res
.append((sprname
, self
[k
].value
))
327 for sprname
, value
in res
:
328 print(" ", sprname
, hex(value
))
333 def __init__(self
, pc_init
=0):
334 self
.CIA
= SelectableInt(pc_init
, 64)
335 self
.NIA
= self
.CIA
+ SelectableInt(4, 64) # only true for v3.0B!
337 def update_nia(self
, is_svp64
):
338 increment
= 8 if is_svp64
else 4
339 self
.NIA
= self
.CIA
+ SelectableInt(increment
, 64)
341 def update(self
, namespace
, is_svp64
):
342 """updates the program counter (PC) by 4 if v3.0B mode or 8 if SVP64
344 self
.CIA
= namespace
['NIA'].narrow(64)
345 self
.update_nia(is_svp64
)
346 namespace
['CIA'] = self
.CIA
347 namespace
['NIA'] = self
.NIA
351 # See PowerISA Version 3.0 B Book 1
352 # Section 2.3.1 Condition Register pages 30 - 31
354 LT
= FL
= 0 # negative, less than, floating-point less than
355 GT
= FG
= 1 # positive, greater than, floating-point greater than
356 EQ
= FE
= 2 # equal, floating-point equal
357 SO
= FU
= 3 # summary overflow, floating-point unordered
359 def __init__(self
, init
=0):
360 # rev_cr = int('{:016b}'.format(initial_cr)[::-1], 2)
361 # self.cr = FieldSelectableInt(self._cr, list(range(32, 64)))
362 self
.cr
= SelectableInt(init
, 64) # underlying reg
363 # field-selectable versions of Condition Register TODO check bitranges?
366 bits
= tuple(range(i
*4+32, (i
+1)*4+32))
367 _cr
= FieldSelectableInt(self
.cr
, bits
)
371 # decode SVP64 predicate integer to reg number and invert
372 def get_predint(gpr
, mask
):
376 log("get_predint", mask
, SVP64PredInt
.ALWAYS
.value
)
377 if mask
== SVP64PredInt
.ALWAYS
.value
:
378 return 0xffff_ffff_ffff_ffff # 64 bits of 1
379 if mask
== SVP64PredInt
.R3_UNARY
.value
:
380 return 1 << (r3
.value
& 0b111111)
381 if mask
== SVP64PredInt
.R3
.value
:
383 if mask
== SVP64PredInt
.R3_N
.value
:
385 if mask
== SVP64PredInt
.R10
.value
:
387 if mask
== SVP64PredInt
.R10_N
.value
:
389 if mask
== SVP64PredInt
.R30
.value
:
391 if mask
== SVP64PredInt
.R30_N
.value
:
395 # decode SVP64 predicate CR to reg number and invert status
396 def _get_predcr(mask
):
397 if mask
== SVP64PredCR
.LT
.value
:
399 if mask
== SVP64PredCR
.GE
.value
:
401 if mask
== SVP64PredCR
.GT
.value
:
403 if mask
== SVP64PredCR
.LE
.value
:
405 if mask
== SVP64PredCR
.EQ
.value
:
407 if mask
== SVP64PredCR
.NE
.value
:
409 if mask
== SVP64PredCR
.SO
.value
:
411 if mask
== SVP64PredCR
.NS
.value
:
415 # read individual CR fields (0..VL-1), extract the required bit
416 # and construct the mask
417 def get_predcr(crl
, mask
, vl
):
418 idx
, noninv
= _get_predcr(mask
)
421 cr
= crl
[i
+SVP64CROffs
.CRPred
]
422 if cr
[idx
].value
== noninv
:
427 # TODO, really should just be using PowerDecoder2
428 def get_idx_map(dec2
, name
):
430 in1_sel
= yield op
.in1_sel
431 in2_sel
= yield op
.in2_sel
432 in3_sel
= yield op
.in3_sel
433 in1
= yield dec2
.e
.read_reg1
.data
434 # identify which regnames map to in1/2/3
435 if name
== 'RA' or name
== 'RA_OR_ZERO':
436 if (in1_sel
== In1Sel
.RA
.value
or
437 (in1_sel
== In1Sel
.RA_OR_ZERO
.value
and in1
!= 0)):
439 if in1_sel
== In1Sel
.RA_OR_ZERO
.value
:
442 if in2_sel
== In2Sel
.RB
.value
:
444 if in3_sel
== In3Sel
.RB
.value
:
446 # XXX TODO, RC doesn't exist yet!
448 if in3_sel
== In3Sel
.RC
.value
:
450 elif name
in ['EA', 'RS']:
451 if in1_sel
== In1Sel
.RS
.value
:
453 if in2_sel
== In2Sel
.RS
.value
:
455 if in3_sel
== In3Sel
.RS
.value
:
458 if in1_sel
== In1Sel
.FRA
.value
:
460 if in3_sel
== In3Sel
.FRA
.value
:
463 if in2_sel
== In2Sel
.FRB
.value
:
466 if in3_sel
== In3Sel
.FRC
.value
:
469 if in1_sel
== In1Sel
.FRS
.value
:
471 if in3_sel
== In3Sel
.FRS
.value
:
474 if in1_sel
== In1Sel
.FRT
.value
:
477 if in1_sel
== In1Sel
.RT
.value
:
482 # TODO, really should just be using PowerDecoder2
483 def get_idx_in(dec2
, name
, ewmode
=False):
484 idx
= yield from get_idx_map(dec2
, name
)
488 in1_sel
= yield op
.in1_sel
489 in2_sel
= yield op
.in2_sel
490 in3_sel
= yield op
.in3_sel
491 # get the IN1/2/3 from the decoder (includes SVP64 remap and isvec)
492 in1
= yield dec2
.e
.read_reg1
.data
493 in2
= yield dec2
.e
.read_reg2
.data
494 in3
= yield dec2
.e
.read_reg3
.data
496 in1_base
= yield dec2
.e
.read_reg1
.base
497 in2_base
= yield dec2
.e
.read_reg2
.base
498 in3_base
= yield dec2
.e
.read_reg3
.base
499 in1_offs
= yield dec2
.e
.read_reg1
.offs
500 in2_offs
= yield dec2
.e
.read_reg2
.offs
501 in3_offs
= yield dec2
.e
.read_reg3
.offs
502 in1
= (in1
, in1_base
, in1_offs
)
503 in2
= (in2
, in2_base
, in2_offs
)
504 in3
= (in3
, in3_base
, in3_offs
)
506 in1_isvec
= yield dec2
.in1_isvec
507 in2_isvec
= yield dec2
.in2_isvec
508 in3_isvec
= yield dec2
.in3_isvec
509 log("get_idx_in in1", name
, in1_sel
, In1Sel
.RA
.value
,
511 log("get_idx_in in2", name
, in2_sel
, In2Sel
.RB
.value
,
513 log("get_idx_in in3", name
, in3_sel
, In3Sel
.RS
.value
,
515 log("get_idx_in FRS in3", name
, in3_sel
, In3Sel
.FRS
.value
,
517 log("get_idx_in FRB in2", name
, in2_sel
, In2Sel
.FRB
.value
,
519 log("get_idx_in FRC in3", name
, in3_sel
, In3Sel
.FRC
.value
,
522 return in1
, in1_isvec
524 return in2
, in2_isvec
526 return in3
, in3_isvec
530 # TODO, really should just be using PowerDecoder2
531 def get_cr_in(dec2
, name
):
533 in_sel
= yield op
.cr_in
534 in_bitfield
= yield dec2
.dec_cr_in
.cr_bitfield
.data
535 sv_cr_in
= yield op
.sv_cr_in
536 spec
= yield dec2
.crin_svdec
.spec
537 sv_override
= yield dec2
.dec_cr_in
.sv_override
538 # get the IN1/2/3 from the decoder (includes SVP64 remap and isvec)
539 in1
= yield dec2
.e
.read_cr1
.data
540 cr_isvec
= yield dec2
.cr_in_isvec
541 log("get_cr_in", in_sel
, CROutSel
.CR0
.value
, in1
, cr_isvec
)
542 log(" sv_cr_in", sv_cr_in
)
543 log(" cr_bf", in_bitfield
)
545 log(" override", sv_override
)
546 # identify which regnames map to in / o2
548 if in_sel
== CRInSel
.BI
.value
:
550 log("get_cr_in not found", name
)
554 # TODO, really should just be using PowerDecoder2
555 def get_cr_out(dec2
, name
):
557 out_sel
= yield op
.cr_out
558 out_bitfield
= yield dec2
.dec_cr_out
.cr_bitfield
.data
559 sv_cr_out
= yield op
.sv_cr_out
560 spec
= yield dec2
.crout_svdec
.spec
561 sv_override
= yield dec2
.dec_cr_out
.sv_override
562 # get the IN1/2/3 from the decoder (includes SVP64 remap and isvec)
563 out
= yield dec2
.e
.write_cr
.data
564 o_isvec
= yield dec2
.cr_out_isvec
565 log("get_cr_out", out_sel
, CROutSel
.CR0
.value
, out
, o_isvec
)
566 log(" sv_cr_out", sv_cr_out
)
567 log(" cr_bf", out_bitfield
)
569 log(" override", sv_override
)
570 # identify which regnames map to out / o2
572 if out_sel
== CROutSel
.BF
.value
:
575 if out_sel
== CROutSel
.CR0
.value
:
577 if name
== 'CR1': # these are not actually calculated correctly
578 if out_sel
== CROutSel
.CR1
.value
:
580 # check RC1 set? if so return implicit vector, this is a REAL bad hack
581 RC1
= yield dec2
.rm_dec
.RC1
583 log("get_cr_out RC1 mode")
585 return 0, True # XXX TODO: offset CR0 from SVSTATE SPR
587 return 1, True # XXX TODO: offset CR1 from SVSTATE SPR
589 log("get_cr_out not found", name
)
593 # TODO, really should just be using PowerDecoder2
594 def get_out_map(dec2
, name
):
596 out_sel
= yield op
.out_sel
597 # get the IN1/2/3 from the decoder (includes SVP64 remap and isvec)
598 out
= yield dec2
.e
.write_reg
.data
599 # identify which regnames map to out / o2
601 if out_sel
== OutSel
.RA
.value
:
604 if out_sel
== OutSel
.RT
.value
:
606 if out_sel
== OutSel
.RT_OR_ZERO
.value
and out
!= 0:
608 elif name
== 'RT_OR_ZERO':
609 if out_sel
== OutSel
.RT_OR_ZERO
.value
:
612 if out_sel
== OutSel
.FRA
.value
:
615 if out_sel
== OutSel
.FRS
.value
:
618 if out_sel
== OutSel
.FRT
.value
:
623 # TODO, really should just be using PowerDecoder2
624 def get_idx_out(dec2
, name
, ewmode
=False):
626 out_sel
= yield op
.out_sel
627 # get the IN1/2/3 from the decoder (includes SVP64 remap and isvec)
628 out
= yield dec2
.e
.write_reg
.data
629 o_isvec
= yield dec2
.o_isvec
631 offs
= yield dec2
.e
.write_reg
.offs
632 base
= yield dec2
.e
.write_reg
.base
633 out
= (out
, base
, offs
)
634 # identify which regnames map to out / o2
635 ismap
= yield from get_out_map(dec2
, name
)
637 log("get_idx_out", name
, out_sel
, out
, o_isvec
)
639 log("get_idx_out not found", name
, out_sel
, out
, o_isvec
)
643 # TODO, really should just be using PowerDecoder2
644 def get_out2_map(dec2
, name
):
645 # check first if register is activated for write
647 out_sel
= yield op
.out_sel
648 out
= yield dec2
.e
.write_ea
.data
649 out_ok
= yield dec2
.e
.write_ea
.ok
653 if name
in ['EA', 'RA']:
654 if hasattr(op
, "upd"):
655 # update mode LD/ST uses read-reg A also as an output
657 log("get_idx_out2", upd
, LDSTMode
.update
.value
,
658 out_sel
, OutSel
.RA
.value
,
660 if upd
== LDSTMode
.update
.value
:
663 fft_en
= yield dec2
.implicit_rs
665 log("get_idx_out2", out_sel
, OutSel
.RS
.value
,
669 fft_en
= yield dec2
.implicit_rs
671 log("get_idx_out2", out_sel
, OutSel
.FRS
.value
,
677 # TODO, really should just be using PowerDecoder2
678 def get_idx_out2(dec2
, name
, ewmode
=False):
679 # check first if register is activated for write
681 out_sel
= yield op
.out_sel
682 out
= yield dec2
.e
.write_ea
.data
684 offs
= yield dec2
.e
.write_ea
.offs
685 base
= yield dec2
.e
.write_ea
.base
686 out
= (out
, base
, offs
)
687 o_isvec
= yield dec2
.o2_isvec
688 ismap
= yield from get_out2_map(dec2
, name
)
690 log("get_idx_out2", name
, out_sel
, out
, o_isvec
)
696 """deals with svstate looping.
699 def __init__(self
, svstate
):
700 self
.svstate
= svstate
703 def new_iterators(self
):
704 self
.src_it
= self
.src_iterator()
705 self
.dst_it
= self
.dst_iterator()
709 self
.new_ssubstep
= 0
710 self
.new_dsubstep
= 0
711 self
.pred_dst_zero
= 0
712 self
.pred_src_zero
= 0
714 def src_iterator(self
):
715 """source-stepping iterator
717 pack
= self
.svstate
.pack
721 # pack advances subvl in *outer* loop
722 while True: # outer subvl loop
723 while True: # inner vl loop
726 srcmask
= self
.srcmask
727 srcstep
= self
.svstate
.srcstep
728 pred_src_zero
= ((1 << srcstep
) & srcmask
) != 0
729 if self
.pred_sz
or pred_src_zero
:
730 self
.pred_src_zero
= not pred_src_zero
731 log(" advance src", srcstep
, vl
,
732 self
.svstate
.ssubstep
, subvl
)
733 # yield actual substep/srcstep
734 yield (self
.svstate
.ssubstep
, srcstep
)
735 # the way yield works these could have been modified.
738 srcstep
= self
.svstate
.srcstep
739 log(" advance src check", srcstep
, vl
,
740 self
.svstate
.ssubstep
, subvl
, srcstep
== vl
-1,
741 self
.svstate
.ssubstep
== subvl
)
742 if srcstep
== vl
-1: # end-point
743 self
.svstate
.srcstep
= SelectableInt(0, 7) # reset
744 if self
.svstate
.ssubstep
== subvl
: # end-point
745 log(" advance pack stop")
747 break # exit inner loop
748 self
.svstate
.srcstep
+= SelectableInt(1, 7) # advance ss
750 if self
.svstate
.ssubstep
== subvl
: # end-point
751 self
.svstate
.ssubstep
= SelectableInt(0, 2) # reset
752 log(" advance pack stop")
754 self
.svstate
.ssubstep
+= SelectableInt(1, 2)
757 # these cannot be done as for-loops because SVSTATE may change
758 # (srcstep/substep may be modified, interrupted, subvl/vl change)
759 # but they *can* be done as while-loops as long as every SVSTATE
760 # "thing" is re-read every single time a yield gives indices
761 while True: # outer vl loop
762 while True: # inner subvl loop
765 srcmask
= self
.srcmask
766 srcstep
= self
.svstate
.srcstep
767 pred_src_zero
= ((1 << srcstep
) & srcmask
) != 0
768 if self
.pred_sz
or pred_src_zero
:
769 self
.pred_src_zero
= not pred_src_zero
770 log(" advance src", srcstep
, vl
,
771 self
.svstate
.ssubstep
, subvl
)
772 # yield actual substep/srcstep
773 yield (self
.svstate
.ssubstep
, srcstep
)
774 if self
.svstate
.ssubstep
== subvl
: # end-point
775 self
.svstate
.ssubstep
= SelectableInt(0, 2) # reset
776 break # exit inner loop
777 self
.svstate
.ssubstep
+= SelectableInt(1, 2)
779 if srcstep
== vl
-1: # end-point
780 self
.svstate
.srcstep
= SelectableInt(0, 7) # reset
783 self
.svstate
.srcstep
+= SelectableInt(1, 7) # advance srcstep
785 def dst_iterator(self
):
786 """dest-stepping iterator
788 unpack
= self
.svstate
.unpack
792 # pack advances subvl in *outer* loop
793 while True: # outer subvl loop
794 while True: # inner vl loop
797 dstmask
= self
.dstmask
798 dststep
= self
.svstate
.dststep
799 pred_dst_zero
= ((1 << dststep
) & dstmask
) != 0
800 if self
.pred_dz
or pred_dst_zero
:
801 self
.pred_dst_zero
= not pred_dst_zero
802 log(" advance dst", dststep
, vl
,
803 self
.svstate
.dsubstep
, subvl
)
804 # yield actual substep/dststep
805 yield (self
.svstate
.dsubstep
, dststep
)
806 # the way yield works these could have been modified.
808 dststep
= self
.svstate
.dststep
809 log(" advance dst check", dststep
, vl
,
810 self
.svstate
.ssubstep
, subvl
)
811 if dststep
== vl
-1: # end-point
812 self
.svstate
.dststep
= SelectableInt(0, 7) # reset
813 if self
.svstate
.dsubstep
== subvl
: # end-point
814 log(" advance unpack stop")
817 self
.svstate
.dststep
+= SelectableInt(1, 7) # advance ds
819 if self
.svstate
.dsubstep
== subvl
: # end-point
820 self
.svstate
.dsubstep
= SelectableInt(0, 2) # reset
821 log(" advance unpack stop")
823 self
.svstate
.dsubstep
+= SelectableInt(1, 2)
825 # these cannot be done as for-loops because SVSTATE may change
826 # (dststep/substep may be modified, interrupted, subvl/vl change)
827 # but they *can* be done as while-loops as long as every SVSTATE
828 # "thing" is re-read every single time a yield gives indices
829 while True: # outer vl loop
830 while True: # inner subvl loop
832 dstmask
= self
.dstmask
833 dststep
= self
.svstate
.dststep
834 pred_dst_zero
= ((1 << dststep
) & dstmask
) != 0
835 if self
.pred_dz
or pred_dst_zero
:
836 self
.pred_dst_zero
= not pred_dst_zero
837 log(" advance dst", dststep
, self
.svstate
.vl
,
838 self
.svstate
.dsubstep
, subvl
)
839 # yield actual substep/dststep
840 yield (self
.svstate
.dsubstep
, dststep
)
841 if self
.svstate
.dsubstep
== subvl
: # end-point
842 self
.svstate
.dsubstep
= SelectableInt(0, 2) # reset
844 self
.svstate
.dsubstep
+= SelectableInt(1, 2)
847 if dststep
== vl
-1: # end-point
848 self
.svstate
.dststep
= SelectableInt(0, 7) # reset
850 self
.svstate
.dststep
+= SelectableInt(1, 7) # advance dststep
852 def src_iterate(self
):
853 """source-stepping iterator
857 pack
= self
.svstate
.pack
858 unpack
= self
.svstate
.unpack
859 ssubstep
= self
.svstate
.ssubstep
860 end_ssub
= ssubstep
== subvl
861 end_src
= self
.svstate
.srcstep
== vl
-1
862 log(" pack/unpack/subvl", pack
, unpack
, subvl
,
866 srcstep
= self
.svstate
.srcstep
867 srcmask
= self
.srcmask
869 # pack advances subvl in *outer* loop
871 assert srcstep
<= vl
-1
872 end_src
= srcstep
== vl
-1
877 self
.svstate
.ssubstep
+= SelectableInt(1, 2)
881 srcstep
+= 1 # advance srcstep
882 if not self
.srcstep_skip
:
884 if ((1 << srcstep
) & srcmask
) != 0:
887 log(" sskip", bin(srcmask
), bin(1 << srcstep
))
889 # advance subvl in *inner* loop
892 assert srcstep
<= vl
-1
893 end_src
= srcstep
== vl
-1
894 if end_src
: # end-point
900 if not self
.srcstep_skip
:
902 if ((1 << srcstep
) & srcmask
) != 0:
905 log(" sskip", bin(srcmask
), bin(1 << srcstep
))
906 self
.svstate
.ssubstep
= SelectableInt(0, 2) # reset
909 self
.svstate
.ssubstep
+= SelectableInt(1, 2)
911 self
.svstate
.srcstep
= SelectableInt(srcstep
, 7)
912 log(" advance src", self
.svstate
.srcstep
, self
.svstate
.ssubstep
,
915 def dst_iterate(self
):
916 """dest step iterator
920 pack
= self
.svstate
.pack
921 unpack
= self
.svstate
.unpack
922 dsubstep
= self
.svstate
.dsubstep
923 end_dsub
= dsubstep
== subvl
924 dststep
= self
.svstate
.dststep
925 end_dst
= dststep
== vl
-1
926 dstmask
= self
.dstmask
927 log(" pack/unpack/subvl", pack
, unpack
, subvl
,
932 # unpack advances subvl in *outer* loop
934 assert dststep
<= vl
-1
935 end_dst
= dststep
== vl
-1
940 self
.svstate
.dsubstep
+= SelectableInt(1, 2)
944 dststep
+= 1 # advance dststep
945 if not self
.dststep_skip
:
947 if ((1 << dststep
) & dstmask
) != 0:
950 log(" dskip", bin(dstmask
), bin(1 << dststep
))
952 # advance subvl in *inner* loop
955 assert dststep
<= vl
-1
956 end_dst
= dststep
== vl
-1
957 if end_dst
: # end-point
963 if not self
.dststep_skip
:
965 if ((1 << dststep
) & dstmask
) != 0:
968 log(" dskip", bin(dstmask
), bin(1 << dststep
))
969 self
.svstate
.dsubstep
= SelectableInt(0, 2) # reset
972 self
.svstate
.dsubstep
+= SelectableInt(1, 2)
974 self
.svstate
.dststep
= SelectableInt(dststep
, 7)
975 log(" advance dst", self
.svstate
.dststep
, self
.svstate
.dsubstep
,
978 def at_loopend(self
):
979 """tells if this is the last possible element. uses the cached values
980 for src/dst-step and sub-steps
984 srcstep
, dststep
= self
.new_srcstep
, self
.new_dststep
985 ssubstep
, dsubstep
= self
.new_ssubstep
, self
.new_dsubstep
986 end_ssub
= ssubstep
== subvl
987 end_dsub
= dsubstep
== subvl
988 if srcstep
== vl
-1 and end_ssub
:
990 if dststep
== vl
-1 and end_dsub
:
994 def advance_svstate_steps(self
):
995 """ advance sub/steps. note that Pack/Unpack *INVERTS* the order.
996 TODO when Pack/Unpack is set, substep becomes the *outer* loop
998 self
.subvl
= yield self
.dec2
.rm_dec
.rm_in
.subvl
999 if self
.loopend
: # huhn??
1004 def read_src_mask(self
):
1005 """read/update pred_sz and src mask
1007 # get SVSTATE VL (oh and print out some debug stuff)
1008 vl
= self
.svstate
.vl
1009 srcstep
= self
.svstate
.srcstep
1010 ssubstep
= self
.svstate
.ssubstep
1012 # get predicate mask (all 64 bits)
1013 srcmask
= 0xffff_ffff_ffff_ffff
1015 pmode
= yield self
.dec2
.rm_dec
.predmode
1016 sv_ptype
= yield self
.dec2
.dec
.op
.SV_Ptype
1017 srcpred
= yield self
.dec2
.rm_dec
.srcpred
1018 dstpred
= yield self
.dec2
.rm_dec
.dstpred
1019 pred_sz
= yield self
.dec2
.rm_dec
.pred_sz
1020 if pmode
== SVP64PredMode
.INT
.value
:
1021 srcmask
= dstmask
= get_predint(self
.gpr
, dstpred
)
1022 if sv_ptype
== SVPType
.P2
.value
:
1023 srcmask
= get_predint(self
.gpr
, srcpred
)
1024 elif pmode
== SVP64PredMode
.CR
.value
:
1025 srcmask
= dstmask
= get_predcr(self
.crl
, dstpred
, vl
)
1026 if sv_ptype
== SVPType
.P2
.value
:
1027 srcmask
= get_predcr(self
.crl
, srcpred
, vl
)
1028 # work out if the ssubsteps are completed
1029 ssubstart
= ssubstep
== 0
1030 log(" pmode", pmode
)
1031 log(" ptype", sv_ptype
)
1032 log(" srcpred", bin(srcpred
))
1033 log(" srcmask", bin(srcmask
))
1034 log(" pred_sz", bin(pred_sz
))
1035 log(" ssubstart", ssubstart
)
1037 # store all that above
1038 self
.srcstep_skip
= False
1039 self
.srcmask
= srcmask
1040 self
.pred_sz
= pred_sz
1041 self
.new_ssubstep
= ssubstep
1042 log(" new ssubstep", ssubstep
)
1043 # until the predicate mask has a "1" bit... or we run out of VL
1044 # let srcstep==VL be the indicator to move to next instruction
1046 self
.srcstep_skip
= True
1048 def read_dst_mask(self
):
1049 """same as read_src_mask - check and record everything needed
1051 # get SVSTATE VL (oh and print out some debug stuff)
1052 # yield Delay(1e-10) # make changes visible
1053 vl
= self
.svstate
.vl
1054 dststep
= self
.svstate
.dststep
1055 dsubstep
= self
.svstate
.dsubstep
1057 # get predicate mask (all 64 bits)
1058 dstmask
= 0xffff_ffff_ffff_ffff
1060 pmode
= yield self
.dec2
.rm_dec
.predmode
1061 reverse_gear
= yield self
.dec2
.rm_dec
.reverse_gear
1062 sv_ptype
= yield self
.dec2
.dec
.op
.SV_Ptype
1063 dstpred
= yield self
.dec2
.rm_dec
.dstpred
1064 pred_dz
= yield self
.dec2
.rm_dec
.pred_dz
1065 if pmode
== SVP64PredMode
.INT
.value
:
1066 dstmask
= get_predint(self
.gpr
, dstpred
)
1067 elif pmode
== SVP64PredMode
.CR
.value
:
1068 dstmask
= get_predcr(self
.crl
, dstpred
, vl
)
1069 # work out if the ssubsteps are completed
1070 dsubstart
= dsubstep
== 0
1071 log(" pmode", pmode
)
1072 log(" ptype", sv_ptype
)
1073 log(" dstpred", bin(dstpred
))
1074 log(" dstmask", bin(dstmask
))
1075 log(" pred_dz", bin(pred_dz
))
1076 log(" dsubstart", dsubstart
)
1078 self
.dststep_skip
= False
1079 self
.dstmask
= dstmask
1080 self
.pred_dz
= pred_dz
1081 self
.new_dsubstep
= dsubstep
1082 log(" new dsubstep", dsubstep
)
1084 self
.dststep_skip
= True
1086 def svstate_pre_inc(self
):
1087 """check if srcstep/dststep need to skip over masked-out predicate bits
1088 note that this is not supposed to do anything to substep,
1089 it is purely for skipping masked-out bits
1092 self
.subvl
= yield self
.dec2
.rm_dec
.rm_in
.subvl
1093 yield from self
.read_src_mask()
1094 yield from self
.read_dst_mask()
1101 srcstep
= self
.svstate
.srcstep
1102 srcmask
= self
.srcmask
1103 pred_src_zero
= self
.pred_sz
1104 vl
= self
.svstate
.vl
1105 # srcstep-skipping opportunity identified
1106 if self
.srcstep_skip
:
1107 # cannot do this with sv.bc - XXX TODO
1110 while (((1 << srcstep
) & srcmask
) == 0) and (srcstep
!= vl
):
1111 log(" sskip", bin(1 << srcstep
))
1114 # now work out if the relevant mask bits require zeroing
1116 pred_src_zero
= ((1 << srcstep
) & srcmask
) == 0
1118 # store new srcstep / dststep
1119 self
.new_srcstep
= srcstep
1120 self
.pred_src_zero
= pred_src_zero
1121 log(" new srcstep", srcstep
)
1124 # dststep-skipping opportunity identified
1125 dststep
= self
.svstate
.dststep
1126 dstmask
= self
.dstmask
1127 pred_dst_zero
= self
.pred_dz
1128 vl
= self
.svstate
.vl
1129 if self
.dststep_skip
:
1130 # cannot do this with sv.bc - XXX TODO
1133 while (((1 << dststep
) & dstmask
) == 0) and (dststep
!= vl
):
1134 log(" dskip", bin(1 << dststep
))
1137 # now work out if the relevant mask bits require zeroing
1139 pred_dst_zero
= ((1 << dststep
) & dstmask
) == 0
1141 # store new srcstep / dststep
1142 self
.new_dststep
= dststep
1143 self
.pred_dst_zero
= pred_dst_zero
1144 log(" new dststep", dststep
)
1147 class SyscallEmulator(openpower
.syscalls
.Dispatcher
):
1148 def __init__(self
, isacaller
):
1149 self
.__isacaller
= isacaller
1151 host
= os
.uname().machine
1152 bits
= (64 if (sys
.maxsize
> (2**32)) else 32)
1153 host
= openpower
.syscalls
.architecture(arch
=host
, bits
=bits
)
1155 return super().__init
__(guest
="ppc64", host
=host
)
1157 def __call__(self
, identifier
, *arguments
):
1158 (identifier
, *arguments
) = map(int, (identifier
, *arguments
))
1159 return super().__call
__(identifier
, *arguments
)
1162 class ISACaller(ISACallerHelper
, ISAFPHelpers
, StepLoop
):
1163 # decoder2 - an instance of power_decoder2
1164 # regfile - a list of initial values for the registers
1165 # initial_{etc} - initial values for SPRs, Condition Register, Mem, MSR
1166 # respect_pc - tracks the program counter. requires initial_insns
1167 def __init__(self
, decoder2
, regfile
, initial_sprs
=None, initial_cr
=0,
1168 initial_mem
=None, initial_msr
=0,
1181 use_syscall_emu
=False):
1183 self
.syscall
= SyscallEmulator(isacaller
=self
)
1184 if not use_mmap_mem
:
1185 log("forcing use_mmap_mem due to use_syscall_emu active")
1190 # trace log file for model output. if None do nothing
1191 self
.insnlog
= insnlog
1192 self
.insnlog_is_file
= hasattr(insnlog
, "write")
1193 if not self
.insnlog_is_file
and self
.insnlog
:
1194 self
.insnlog
= open(self
.insnlog
, "w")
1196 self
.bigendian
= bigendian
1198 self
.is_svp64_mode
= False
1199 self
.respect_pc
= respect_pc
1200 if initial_sprs
is None:
1202 if initial_mem
is None:
1204 if fpregfile
is None:
1205 fpregfile
= [0] * 32
1206 if initial_insns
is None:
1208 assert self
.respect_pc
== False, "instructions required to honor pc"
1209 if initial_msr
is None:
1210 initial_msr
= DEFAULT_MSR
1212 log("ISACaller insns", respect_pc
, initial_insns
, disassembly
)
1213 log("ISACaller initial_msr", initial_msr
)
1215 # "fake program counter" mode (for unit testing)
1219 if isinstance(initial_mem
, tuple):
1220 self
.fake_pc
= initial_mem
[0]
1221 disasm_start
= self
.fake_pc
1223 disasm_start
= initial_pc
1225 # disassembly: we need this for now (not given from the decoder)
1226 self
.disassembly
= {}
1228 for i
, code
in enumerate(disassembly
):
1229 self
.disassembly
[i
*4 + disasm_start
] = code
1231 # set up registers, instruction memory, data memory, PC, SPRs, MSR, CR
1232 self
.svp64rm
= SVP64RM()
1233 if initial_svstate
is None:
1235 if isinstance(initial_svstate
, int):
1236 initial_svstate
= SVP64State(initial_svstate
)
1237 # SVSTATE, MSR and PC
1238 StepLoop
.__init
__(self
, initial_svstate
)
1239 self
.msr
= SelectableInt(initial_msr
, 64) # underlying reg
1241 # GPR FPR SPR registers
1242 initial_sprs
= deepcopy(initial_sprs
) # so as not to get modified
1243 self
.gpr
= GPR(decoder2
, self
, self
.svstate
, regfile
)
1244 self
.fpr
= GPR(decoder2
, self
, self
.svstate
, fpregfile
)
1245 # initialise SPRs before MMU
1246 self
.spr
= SPR(decoder2
, initial_sprs
, gpr
=self
.gpr
)
1248 # set up 4 dummy SVSHAPEs if they aren't already set up
1250 sname
= 'SVSHAPE%d' % i
1251 val
= self
.spr
.get(sname
, 0)
1252 # make sure it's an SVSHAPE -- conversion done by SPR.__setitem__
1253 self
.spr
[sname
] = val
1254 self
.last_op_svshape
= False
1258 self
.mem
= MemMMap(row_bytes
=8,
1259 initial_mem
=initial_mem
,
1261 self
.imem
= self
.mem
1262 self
.mem
.initialize(row_bytes
=4, initial_mem
=initial_insns
)
1263 self
.mem
.log_fancy(kind
=LogType
.InstrInOuts
)
1265 self
.mem
= Mem(row_bytes
=8, initial_mem
=initial_mem
,
1267 self
.mem
.log_fancy(kind
=LogType
.InstrInOuts
)
1268 self
.imem
= Mem(row_bytes
=4, initial_mem
=initial_insns
)
1269 # MMU mode, redirect underlying Mem through RADIX
1271 self
.mem
= RADIX(self
.mem
, self
)
1273 self
.imem
= RADIX(self
.imem
, self
)
1275 # TODO, needed here:
1276 # FPR (same as GPR except for FP nums)
1277 # 4.2.2 p124 FPSCR (definitely "separate" - not in SPR)
1278 # note that mffs, mcrfs, mtfsf "manage" this FPSCR
1279 self
.fpscr
= FPSCRState(initial_fpscr
)
1281 # 2.3.1 CR (and sub-fields CR0..CR6 - CR0 SO comes from XER.SO)
1282 # note that mfocrf, mfcr, mtcr, mtocrf, mcrxrx "manage" CRs
1284 # 2.3.2 LR (actually SPR #8) -- Done
1285 # 2.3.3 CTR (actually SPR #9) -- Done
1286 # 2.3.4 TAR (actually SPR #815)
1287 # 3.2.2 p45 XER (actually SPR #1) -- Done
1288 # 3.2.3 p46 p232 VRSAVE (actually SPR #256)
1290 # create CR then allow portions of it to be "selectable" (below)
1291 self
.cr_fields
= CRFields(initial_cr
)
1292 self
.cr
= self
.cr_fields
.cr
1293 self
.cr_backup
= 0 # sigh, dreadful hack: for fail-first (VLi)
1295 # "undefined", just set to variable-bit-width int (use exts "max")
1296 # self.undefined = SelectableInt(0, EFFECTIVELY_UNLIMITED)
1299 self
.namespace
.update(self
.spr
)
1300 self
.namespace
.update({'GPR': self
.gpr
,
1304 'memassign': self
.memassign
,
1307 'SVSTATE': self
.svstate
,
1308 'SVSHAPE0': self
.spr
['SVSHAPE0'],
1309 'SVSHAPE1': self
.spr
['SVSHAPE1'],
1310 'SVSHAPE2': self
.spr
['SVSHAPE2'],
1311 'SVSHAPE3': self
.spr
['SVSHAPE3'],
1314 'FPSCR': self
.fpscr
,
1315 'undefined': undefined
,
1316 'mode_is_64bit': True,
1317 'SO': XER_bits
['SO'],
1318 'XLEN': 64 # elwidth overrides
1321 for name
in BFP_FLAG_NAMES
:
1322 setattr(self
, name
, 0)
1324 # update pc to requested start point
1325 self
.set_pc(initial_pc
)
1327 # field-selectable versions of Condition Register
1328 self
.crl
= self
.cr_fields
.crl
1330 self
.namespace
["CR%d" % i
] = self
.crl
[i
]
1332 self
.decoder
= decoder2
.dec
1333 self
.dec2
= decoder2
1335 super().__init
__(XLEN
=self
.namespace
["XLEN"], FPSCR
=self
.fpscr
)
1337 def trace(self
, out
):
1338 if self
.insnlog
is None:
1340 self
.insnlog
.write(out
)
1344 return self
.namespace
["XLEN"]
1350 def call_trap(self
, trap_addr
, trap_bit
):
1351 """calls TRAP and sets up NIA to the new execution location.
1352 next instruction will begin at trap_addr.
1354 self
.TRAP(trap_addr
, trap_bit
)
1355 self
.namespace
['NIA'] = self
.trap_nia
1356 self
.pc
.update(self
.namespace
, self
.is_svp64_mode
)
1358 def TRAP(self
, trap_addr
=0x700, trap_bit
=PIb
.TRAP
):
1359 """TRAP> saves PC, MSR (and TODO SVSTATE), and updates MSR
1361 TRAP function is callable from inside the pseudocode itself,
1362 hence the default arguments. when calling from inside ISACaller
1363 it is best to use call_trap()
1365 trap_addr: int | SelectableInt
1366 the address to go to (before any modifications from `KAIVB`)
1367 trap_bit: int | None
1368 the bit in `SRR1` to set, `None` means don't set any bits.
1370 if isinstance(trap_addr
, SelectableInt
):
1371 trap_addr
= trap_addr
.value
1372 # https://bugs.libre-soc.org/show_bug.cgi?id=859
1373 kaivb
= self
.spr
['KAIVB'].value
1374 msr
= self
.namespace
['MSR'].value
1375 log("TRAP:", hex(trap_addr
), hex(msr
), "kaivb", hex(kaivb
))
1376 # store CIA(+4?) in SRR0, set NIA to 0x700
1377 # store MSR in SRR1, set MSR to um errr something, have to check spec
1378 # store SVSTATE (if enabled) in SVSRR0
1379 self
.spr
['SRR0'].value
= self
.pc
.CIA
.value
1380 self
.spr
['SRR1'].value
= msr
1381 if self
.is_svp64_mode
:
1382 self
.spr
['SVSRR0'] = self
.namespace
['SVSTATE'].value
1383 self
.trap_nia
= SelectableInt(trap_addr |
(kaivb
& ~
0x1fff), 64)
1384 if trap_bit
is not None:
1385 self
.spr
['SRR1'][trap_bit
] = 1 # change *copy* of MSR in SRR1
1387 # set exception bits. TODO: this should, based on the address
1388 # in figure 66 p1065 V3.0B and the table figure 65 p1063 set these
1389 # bits appropriately. however it turns out that *for now* in all
1390 # cases (all trap_addrs) the exact same thing is needed.
1391 self
.msr
[MSRb
.IR
] = 0
1392 self
.msr
[MSRb
.DR
] = 0
1393 self
.msr
[MSRb
.FE0
] = 0
1394 self
.msr
[MSRb
.FE1
] = 0
1395 self
.msr
[MSRb
.EE
] = 0
1396 self
.msr
[MSRb
.RI
] = 0
1397 self
.msr
[MSRb
.SF
] = 1
1398 self
.msr
[MSRb
.TM
] = 0
1399 self
.msr
[MSRb
.VEC
] = 0
1400 self
.msr
[MSRb
.VSX
] = 0
1401 self
.msr
[MSRb
.PR
] = 0
1402 self
.msr
[MSRb
.FP
] = 0
1403 self
.msr
[MSRb
.PMM
] = 0
1404 self
.msr
[MSRb
.TEs
] = 0
1405 self
.msr
[MSRb
.TEe
] = 0
1406 self
.msr
[MSRb
.UND
] = 0
1407 self
.msr
[MSRb
.LE
] = 1
1409 def memassign(self
, ea
, sz
, val
):
1410 self
.mem
.memassign(ea
, sz
, val
)
1412 def prep_namespace(self
, insn_name
, formname
, op_fields
, xlen
):
1413 # TODO: get field names from form in decoder*1* (not decoder2)
1414 # decoder2 is hand-created, and decoder1.sigform is auto-generated
1416 # then "yield" fields only from op_fields rather than hard-coded
1418 fields
= self
.decoder
.sigforms
[formname
]
1419 log("prep_namespace", formname
, op_fields
, insn_name
)
1420 for name
in op_fields
:
1421 # CR immediates. deal with separately. needs modifying
1423 if self
.is_svp64_mode
and name
in ['BI']: # TODO, more CRs
1424 # BI is a 5-bit, must reconstruct the value
1425 regnum
, is_vec
= yield from get_cr_in(self
.dec2
, name
)
1426 sig
= getattr(fields
, name
)
1428 # low 2 LSBs (CR field selector) remain same, CR num extended
1429 assert regnum
<= 7, "sigh, TODO, 128 CR fields"
1430 val
= (val
& 0b11) |
(regnum
<< 2)
1431 elif self
.is_svp64_mode
and name
in ['BF']: # TODO, more CRs
1432 regnum
, is_vec
= yield from get_cr_out(self
.dec2
, "BF")
1433 log('hack %s' % name
, regnum
, is_vec
)
1436 sig
= getattr(fields
, name
)
1438 # these are all opcode fields involved in index-selection of CR,
1439 # and need to do "standard" arithmetic. CR[BA+32] for example
1440 # would, if using SelectableInt, only be 5-bit.
1441 if name
in ['BF', 'BFA', 'BC', 'BA', 'BB', 'BT', 'BI']:
1442 self
.namespace
[name
] = val
1444 self
.namespace
[name
] = SelectableInt(val
, sig
.width
)
1446 self
.namespace
['XER'] = self
.spr
['XER']
1447 self
.namespace
['CA'] = self
.spr
['XER'][XER_bits
['CA']].value
1448 self
.namespace
['CA32'] = self
.spr
['XER'][XER_bits
['CA32']].value
1449 self
.namespace
['OV'] = self
.spr
['XER'][XER_bits
['OV']].value
1450 self
.namespace
['OV32'] = self
.spr
['XER'][XER_bits
['OV32']].value
1451 self
.namespace
['XLEN'] = xlen
1453 # add some SVSTATE convenience variables
1454 vl
= self
.svstate
.vl
1455 srcstep
= self
.svstate
.srcstep
1456 self
.namespace
['VL'] = vl
1457 self
.namespace
['srcstep'] = srcstep
1459 # take a copy of the CR field value: if non-VLi fail-first fails
1460 # this is because the pseudocode writes *directly* to CR. sigh
1461 self
.cr_backup
= self
.cr
.value
1463 # sv.bc* need some extra fields
1464 if not self
.is_svp64_mode
or not insn_name
.startswith("sv.bc"):
1467 # blegh grab bits manually
1468 mode
= yield self
.dec2
.rm_dec
.rm_in
.mode
1469 # convert to SelectableInt before test
1470 mode
= SelectableInt(mode
, 5)
1471 bc_vlset
= mode
[SVP64MODEb
.BC_VLSET
] != 0
1472 bc_vli
= mode
[SVP64MODEb
.BC_VLI
] != 0
1473 bc_snz
= mode
[SVP64MODEb
.BC_SNZ
] != 0
1474 bc_vsb
= yield self
.dec2
.rm_dec
.bc_vsb
1475 bc_ctrtest
= yield self
.dec2
.rm_dec
.bc_ctrtest
1476 bc_lru
= yield self
.dec2
.rm_dec
.bc_lru
1477 bc_gate
= yield self
.dec2
.rm_dec
.bc_gate
1478 sz
= yield self
.dec2
.rm_dec
.pred_sz
1479 self
.namespace
['mode'] = SelectableInt(mode
, 5)
1480 self
.namespace
['ALL'] = SelectableInt(bc_gate
, 1)
1481 self
.namespace
['VSb'] = SelectableInt(bc_vsb
, 1)
1482 self
.namespace
['LRu'] = SelectableInt(bc_lru
, 1)
1483 self
.namespace
['CTRtest'] = SelectableInt(bc_ctrtest
, 1)
1484 self
.namespace
['VLSET'] = SelectableInt(bc_vlset
, 1)
1485 self
.namespace
['VLI'] = SelectableInt(bc_vli
, 1)
1486 self
.namespace
['sz'] = SelectableInt(sz
, 1)
1487 self
.namespace
['SNZ'] = SelectableInt(bc_snz
, 1)
1489 def get_kludged_op_add_ca_ov(self
, inputs
, inp_ca_ov
):
1490 """ this was not at all necessary to do. this function massively
1491 duplicates - in a laborious and complex fashion - the contents of
1492 the CSV files that were extracted two years ago from microwatt's
1493 source code. A-inversion is the "inv A" column, output inversion
1494 is the "inv out" column, carry-in equal to 0 or 1 or CA is the
1497 all of that information is available in
1498 self.instrs[ins_name].op_fields
1499 where info is usually assigned to self.instrs[ins_name]
1501 https://git.libre-soc.org/?p=openpower-isa.git;a=blob;f=openpower/isatables/minor_31.csv;hb=HEAD
1503 the immediate constants are *also* decoded correctly and placed
1504 usually by DecodeIn2Imm into operand2, as part of power_decoder2.py
1506 def ca(a
, b
, ca_in
, width
):
1507 mask
= (1 << width
) - 1
1508 y
= (a
& mask
) + (b
& mask
) + ca_in
1511 asmcode
= yield self
.dec2
.dec
.op
.asmcode
1512 insn
= insns
.get(asmcode
)
1513 SI
= yield self
.dec2
.dec
.SI
1516 inputs
= [i
.value
for i
in inputs
]
1519 if insn
in ("add", "addo", "addc", "addco"):
1523 elif insn
== "addic" or insn
== "addic.":
1527 elif insn
in ("subf", "subfo", "subfc", "subfco"):
1531 elif insn
== "subfic":
1535 elif insn
== "adde" or insn
== "addeo":
1539 elif insn
== "subfe" or insn
== "subfeo":
1543 elif insn
== "addme" or insn
== "addmeo":
1547 elif insn
== "addze" or insn
== "addzeo":
1551 elif insn
== "subfme" or insn
== "subfmeo":
1555 elif insn
== "subfze" or insn
== "subfzeo":
1559 elif insn
== "addex":
1560 # CA[32] aren't actually written, just generate so we have
1561 # something to return
1562 ca64
= ov64
= ca(inputs
[0], inputs
[1], OV
, 64)
1563 ca32
= ov32
= ca(inputs
[0], inputs
[1], OV
, 32)
1564 return ca64
, ca32
, ov64
, ov32
1565 elif insn
== "neg" or insn
== "nego":
1570 raise NotImplementedError(
1571 "op_add kludge unimplemented instruction: ", asmcode
, insn
)
1573 ca64
= ca(a
, b
, ca_in
, 64)
1574 ca32
= ca(a
, b
, ca_in
, 32)
1575 ov64
= ca64
!= ca(a
, b
, ca_in
, 63)
1576 ov32
= ca32
!= ca(a
, b
, ca_in
, 31)
1577 return ca64
, ca32
, ov64
, ov32
1579 def handle_carry_(self
, inputs
, output
, ca
, ca32
, inp_ca_ov
):
1580 if ca
is not None and ca32
is not None:
1582 op
= yield self
.dec2
.e
.do
.insn_type
1583 if op
== MicrOp
.OP_ADD
.value
and ca
is None and ca32
is None:
1584 retval
= yield from self
.get_kludged_op_add_ca_ov(
1586 ca
, ca32
, ov
, ov32
= retval
1587 asmcode
= yield self
.dec2
.dec
.op
.asmcode
1588 if insns
.get(asmcode
) == 'addex':
1589 # TODO: if 32-bit mode, set ov to ov32
1590 self
.spr
['XER'][XER_bits
['OV']] = ov
1591 self
.spr
['XER'][XER_bits
['OV32']] = ov32
1592 log(f
"write OV/OV32 OV={ov} OV32={ov32}",
1593 kind
=LogType
.InstrInOuts
)
1595 # TODO: if 32-bit mode, set ca to ca32
1596 self
.spr
['XER'][XER_bits
['CA']] = ca
1597 self
.spr
['XER'][XER_bits
['CA32']] = ca32
1598 log(f
"write CA/CA32 CA={ca} CA32={ca32}",
1599 kind
=LogType
.InstrInOuts
)
1601 inv_a
= yield self
.dec2
.e
.do
.invert_in
1603 inputs
[0] = ~inputs
[0]
1605 imm_ok
= yield self
.dec2
.e
.do
.imm_data
.ok
1607 imm
= yield self
.dec2
.e
.do
.imm_data
.data
1608 inputs
.append(SelectableInt(imm
, 64))
1611 log("gt input", x
, output
)
1612 gt
= (gtu(x
, output
))
1615 cy
= 1 if any(gts
) else 0
1617 if ca
is None: # already written
1618 self
.spr
['XER'][XER_bits
['CA']] = cy
1621 # ARGH... different for OP_ADD... *sigh*...
1622 op
= yield self
.dec2
.e
.do
.insn_type
1623 if op
== MicrOp
.OP_ADD
.value
:
1624 res32
= (output
.value
& (1 << 32)) != 0
1625 a32
= (inputs
[0].value
& (1 << 32)) != 0
1626 if len(inputs
) >= 2:
1627 b32
= (inputs
[1].value
& (1 << 32)) != 0
1630 cy32
= res32 ^ a32 ^ b32
1631 log("CA32 ADD", cy32
)
1635 log("input", x
, output
)
1636 log(" x[32:64]", x
, x
[32:64])
1637 log(" o[32:64]", output
, output
[32:64])
1638 gt
= (gtu(x
[32:64], output
[32:64])) == SelectableInt(1, 1)
1640 cy32
= 1 if any(gts
) else 0
1641 log("CA32", cy32
, gts
)
1642 if ca32
is None: # already written
1643 self
.spr
['XER'][XER_bits
['CA32']] = cy32
1645 def handle_overflow(self
, inputs
, output
, div_overflow
, inp_ca_ov
):
1646 op
= yield self
.dec2
.e
.do
.insn_type
1647 if op
== MicrOp
.OP_ADD
.value
:
1648 retval
= yield from self
.get_kludged_op_add_ca_ov(
1650 ca
, ca32
, ov
, ov32
= retval
1651 # TODO: if 32-bit mode, set ov to ov32
1652 self
.spr
['XER'][XER_bits
['OV']] = ov
1653 self
.spr
['XER'][XER_bits
['OV32']] = ov32
1654 self
.spr
['XER'][XER_bits
['SO']] |
= ov
1656 if hasattr(self
.dec2
.e
.do
, "invert_in"):
1657 inv_a
= yield self
.dec2
.e
.do
.invert_in
1659 inputs
[0] = ~inputs
[0]
1661 imm_ok
= yield self
.dec2
.e
.do
.imm_data
.ok
1663 imm
= yield self
.dec2
.e
.do
.imm_data
.data
1664 inputs
.append(SelectableInt(imm
, 64))
1665 log("handle_overflow", inputs
, output
, div_overflow
)
1666 if len(inputs
) < 2 and div_overflow
is None:
1669 # div overflow is different: it's returned by the pseudo-code
1670 # because it's more complex than can be done by analysing the output
1671 if div_overflow
is not None:
1672 ov
, ov32
= div_overflow
, div_overflow
1673 # arithmetic overflow can be done by analysing the input and output
1674 elif len(inputs
) >= 2:
1676 input_sgn
= [exts(x
.value
, x
.bits
) < 0 for x
in inputs
]
1677 output_sgn
= exts(output
.value
, output
.bits
) < 0
1678 ov
= 1 if input_sgn
[0] == input_sgn
[1] and \
1679 output_sgn
!= input_sgn
[0] else 0
1682 input32_sgn
= [exts(x
.value
, 32) < 0 for x
in inputs
]
1683 output32_sgn
= exts(output
.value
, 32) < 0
1684 ov32
= 1 if input32_sgn
[0] == input32_sgn
[1] and \
1685 output32_sgn
!= input32_sgn
[0] else 0
1687 # now update XER OV/OV32/SO
1688 so
= self
.spr
['XER'][XER_bits
['SO']]
1689 new_so
= so | ov
# sticky overflow ORs in old with new
1690 self
.spr
['XER'][XER_bits
['OV']] = ov
1691 self
.spr
['XER'][XER_bits
['OV32']] = ov32
1692 self
.spr
['XER'][XER_bits
['SO']] = new_so
1693 log(" set overflow", ov
, ov32
, so
, new_so
)
1695 def handle_comparison(self
, out
, cr_idx
=0, overflow
=None, no_so
=False):
1696 assert isinstance(out
, SelectableInt
), \
1697 "out zero not a SelectableInt %s" % repr(outputs
)
1698 log("handle_comparison", out
.bits
, hex(out
.value
))
1699 # TODO - XXX *processor* in 32-bit mode
1700 # https://bugs.libre-soc.org/show_bug.cgi?id=424
1702 # o32 = exts(out.value, 32)
1703 # print ("handle_comparison exts 32 bit", hex(o32))
1704 out
= exts(out
.value
, out
.bits
)
1705 log("handle_comparison exts", hex(out
))
1706 # create the three main CR flags, EQ GT LT
1707 zero
= SelectableInt(out
== 0, 1)
1708 positive
= SelectableInt(out
> 0, 1)
1709 negative
= SelectableInt(out
< 0, 1)
1710 # get (or not) XER.SO. for setvl this is important *not* to read SO
1712 SO
= SelectableInt(1, 0)
1714 SO
= self
.spr
['XER'][XER_bits
['SO']]
1715 log("handle_comparison SO", SO
.value
,
1716 "overflow", overflow
,
1718 "+ve", positive
.value
,
1719 "-ve", negative
.value
)
1720 # alternative overflow checking (setvl mainly at the moment)
1721 if overflow
is not None and overflow
== 1:
1722 SO
= SelectableInt(1, 1)
1723 # create the four CR field values and set the required CR field
1724 cr_field
= selectconcat(negative
, positive
, zero
, SO
)
1725 log("handle_comparison cr_field", self
.cr
, cr_idx
, cr_field
)
1726 self
.crl
[cr_idx
].eq(cr_field
)
1728 def set_pc(self
, pc_val
):
1729 self
.namespace
['NIA'] = SelectableInt(pc_val
, 64)
1730 self
.pc
.update(self
.namespace
, self
.is_svp64_mode
)
1732 def get_next_insn(self
):
1733 """check instruction
1736 pc
= self
.pc
.CIA
.value
1739 ins
= self
.imem
.ld(pc
, 4, False, True, instr_fetch
=True)
1741 raise KeyError("no instruction at 0x%x" % pc
)
1744 def setup_one(self
):
1745 """set up one instruction
1747 pc
, insn
= self
.get_next_insn()
1748 yield from self
.setup_next_insn(pc
, insn
)
1750 # cache since it's really slow to construct
1751 __PREFIX_CACHE
= SVP64Instruction
.Prefix(SelectableInt(value
=0, bits
=32))
1753 def __decode_prefix(self
, opcode
):
1754 pfx
= self
.__PREFIX
_CACHE
1755 pfx
.storage
.eq(opcode
)
1758 def setup_next_insn(self
, pc
, ins
):
1759 """set up next instruction
1762 log("setup: 0x%x 0x%x %s" % (pc
, ins
& 0xffffffff, bin(ins
)))
1763 log("CIA NIA", self
.respect_pc
, self
.pc
.CIA
.value
, self
.pc
.NIA
.value
)
1765 yield self
.dec2
.sv_rm
.eq(0)
1766 yield self
.dec2
.dec
.raw_opcode_in
.eq(ins
& 0xffffffff)
1767 yield self
.dec2
.dec
.bigendian
.eq(self
.bigendian
)
1768 yield self
.dec2
.state
.msr
.eq(self
.msr
.value
)
1769 yield self
.dec2
.state
.pc
.eq(pc
)
1770 if self
.svstate
is not None:
1771 yield self
.dec2
.state
.svstate
.eq(self
.svstate
.value
)
1773 # SVP64. first, check if the opcode is EXT001, and SVP64 id bits set
1775 opcode
= yield self
.dec2
.dec
.opcode_in
1776 opcode
= SelectableInt(value
=opcode
, bits
=32)
1777 pfx
= self
.__decode
_prefix
(opcode
)
1778 log("prefix test: opcode:", pfx
.PO
, bin(pfx
.PO
), pfx
.id)
1779 self
.is_svp64_mode
= bool((pfx
.PO
== 0b000001) and (pfx
.id == 0b11))
1780 self
.pc
.update_nia(self
.is_svp64_mode
)
1782 yield self
.dec2
.is_svp64_mode
.eq(self
.is_svp64_mode
)
1783 self
.namespace
['NIA'] = self
.pc
.NIA
1784 self
.namespace
['SVSTATE'] = self
.svstate
1785 if not self
.is_svp64_mode
:
1788 # in SVP64 mode. decode/print out svp64 prefix, get v3.0B instruction
1789 log("svp64.rm", bin(pfx
.rm
))
1790 log(" svstate.vl", self
.svstate
.vl
)
1791 log(" svstate.mvl", self
.svstate
.maxvl
)
1792 ins
= self
.imem
.ld(pc
+4, 4, False, True, instr_fetch
=True)
1793 log(" svsetup: 0x%x 0x%x %s" % (pc
+4, ins
& 0xffffffff, bin(ins
)))
1794 yield self
.dec2
.dec
.raw_opcode_in
.eq(ins
& 0xffffffff) # v3.0B suffix
1795 yield self
.dec2
.sv_rm
.eq(int(pfx
.rm
)) # svp64 prefix
1798 def execute_one(self
):
1799 """execute one instruction
1801 # get the disassembly code for this instruction
1802 if not self
.disassembly
:
1803 code
= yield from self
.get_assembly_name()
1806 if self
.is_svp64_mode
:
1807 offs
, dbg
= 4, "svp64 "
1808 code
= self
.disassembly
[self
._pc
+offs
]
1809 log(" %s sim-execute" % dbg
, hex(self
._pc
), code
)
1810 opname
= code
.split(' ')[0]
1812 yield from self
.call(opname
) # execute the instruction
1813 except MemException
as e
: # check for memory errors
1814 if e
.args
[0] == 'unaligned': # alignment error
1815 # run a Trap but set DAR first
1816 print("memory unaligned exception, DAR", e
.dar
, repr(e
))
1817 self
.spr
['DAR'] = SelectableInt(e
.dar
, 64)
1818 self
.call_trap(0x600, PIb
.PRIV
) # 0x600, privileged
1820 elif e
.args
[0] == 'invalid': # invalid
1821 # run a Trap but set DAR first
1822 log("RADIX MMU memory invalid error, mode %s" % e
.mode
)
1823 if e
.mode
== 'EXECUTE':
1824 # XXX TODO: must set a few bits in SRR1,
1825 # see microwatt loadstore1.vhdl
1826 # if m_in.segerr = '0' then
1827 # v.srr1(47 - 33) := m_in.invalid;
1828 # v.srr1(47 - 35) := m_in.perm_error; -- noexec fault
1829 # v.srr1(47 - 44) := m_in.badtree;
1830 # v.srr1(47 - 45) := m_in.rc_error;
1831 # v.intr_vec := 16#400#;
1833 # v.intr_vec := 16#480#;
1834 self
.call_trap(0x400, PIb
.PRIV
) # 0x400, privileged
1836 self
.call_trap(0x300, PIb
.PRIV
) # 0x300, privileged
1838 # not supported yet:
1839 raise e
# ... re-raise
1841 # append to the trace log file
1842 self
.trace(" # %s\n" % code
)
1844 log("gprs after code", code
)
1847 for i
in range(len(self
.crl
)):
1848 crs
.append(bin(self
.crl
[i
].asint()))
1849 log("crs", " ".join(crs
))
1850 log("vl,maxvl", self
.svstate
.vl
, self
.svstate
.maxvl
)
1852 # don't use this except in special circumstances
1853 if not self
.respect_pc
:
1856 log("execute one, CIA NIA", hex(self
.pc
.CIA
.value
),
1857 hex(self
.pc
.NIA
.value
))
1859 def get_assembly_name(self
):
1860 # TODO, asmregs is from the spec, e.g. add RT,RA,RB
1861 # see http://bugs.libre-riscv.org/show_bug.cgi?id=282
1862 dec_insn
= yield self
.dec2
.e
.do
.insn
1863 insn_1_11
= yield self
.dec2
.e
.do
.insn
[1:11]
1864 asmcode
= yield self
.dec2
.dec
.op
.asmcode
1865 int_op
= yield self
.dec2
.dec
.op
.internal_op
1866 log("get assembly name asmcode", asmcode
, int_op
,
1867 hex(dec_insn
), bin(insn_1_11
))
1868 asmop
= insns
.get(asmcode
, None)
1870 # sigh reconstruct the assembly instruction name
1871 if hasattr(self
.dec2
.e
.do
, "oe"):
1872 ov_en
= yield self
.dec2
.e
.do
.oe
.oe
1873 ov_ok
= yield self
.dec2
.e
.do
.oe
.ok
1877 if hasattr(self
.dec2
.e
.do
, "rc"):
1878 rc_en
= yield self
.dec2
.e
.do
.rc
.rc
1879 rc_ok
= yield self
.dec2
.e
.do
.rc
.ok
1883 # annoying: ignore rc_ok if RC1 is set (for creating *assembly name*)
1884 RC1
= yield self
.dec2
.rm_dec
.RC1
1888 # grrrr have to special-case MUL op (see DecodeOE)
1889 log("ov %d en %d rc %d en %d op %d" %
1890 (ov_ok
, ov_en
, rc_ok
, rc_en
, int_op
))
1891 if int_op
in [MicrOp
.OP_MUL_H64
.value
, MicrOp
.OP_MUL_H32
.value
]:
1896 if not asmop
.endswith("."): # don't add "." to "andis."
1899 if hasattr(self
.dec2
.e
.do
, "lk"):
1900 lk
= yield self
.dec2
.e
.do
.lk
1903 log("int_op", int_op
)
1904 if int_op
in [MicrOp
.OP_B
.value
, MicrOp
.OP_BC
.value
]:
1905 AA
= yield self
.dec2
.dec
.fields
.FormI
.AA
[0:-1]
1909 spr_msb
= yield from self
.get_spr_msb()
1910 if int_op
== MicrOp
.OP_MFCR
.value
:
1915 # XXX TODO: for whatever weird reason this doesn't work
1916 # https://bugs.libre-soc.org/show_bug.cgi?id=390
1917 if int_op
== MicrOp
.OP_MTCRF
.value
:
1924 def reset_remaps(self
):
1925 self
.remap_loopends
= [0] * 4
1926 self
.remap_idxs
= [0, 1, 2, 3]
1928 def get_remap_indices(self
):
1929 """WARNING, this function stores remap_idxs and remap_loopends
1930 in the class for later use. this to avoid problems with yield
1932 # go through all iterators in lock-step, advance to next remap_idx
1933 srcstep
, dststep
, ssubstep
, dsubstep
= self
.get_src_dststeps()
1934 # get four SVSHAPEs. here we are hard-coding
1936 SVSHAPE0
= self
.spr
['SVSHAPE0']
1937 SVSHAPE1
= self
.spr
['SVSHAPE1']
1938 SVSHAPE2
= self
.spr
['SVSHAPE2']
1939 SVSHAPE3
= self
.spr
['SVSHAPE3']
1940 # set up the iterators
1941 remaps
= [(SVSHAPE0
, SVSHAPE0
.get_iterator()),
1942 (SVSHAPE1
, SVSHAPE1
.get_iterator()),
1943 (SVSHAPE2
, SVSHAPE2
.get_iterator()),
1944 (SVSHAPE3
, SVSHAPE3
.get_iterator()),
1948 for i
, (shape
, remap
) in enumerate(remaps
):
1949 # zero is "disabled"
1950 if shape
.value
== 0x0:
1951 self
.remap_idxs
[i
] = 0
1952 # pick src or dststep depending on reg num (0-2=in, 3-4=out)
1953 step
= dststep
if (i
in [3, 4]) else srcstep
1954 # this is terrible. O(N^2) looking for the match. but hey.
1955 for idx
, (remap_idx
, loopends
) in enumerate(remap
):
1958 self
.remap_idxs
[i
] = remap_idx
1959 self
.remap_loopends
[i
] = loopends
1960 dbg
.append((i
, step
, remap_idx
, loopends
))
1961 for (i
, step
, remap_idx
, loopends
) in dbg
:
1962 log("SVSHAPE %d idx, end" % i
, step
, remap_idx
, bin(loopends
))
1965 def get_spr_msb(self
):
1966 dec_insn
= yield self
.dec2
.e
.do
.insn
1967 return dec_insn
& (1 << 20) != 0 # sigh - XFF.spr[-1]?
1969 def call(self
, name
, syscall_emu_active
=False):
1970 """call(opcode) - the primary execution point for instructions
1972 self
.last_st_addr
= None # reset the last known store address
1973 self
.last_ld_addr
= None # etc.
1975 ins_name
= name
.strip() # remove spaces if not already done so
1977 log("halted - not executing", ins_name
)
1980 # TODO, asmregs is from the spec, e.g. add RT,RA,RB
1981 # see http://bugs.libre-riscv.org/show_bug.cgi?id=282
1982 asmop
= yield from self
.get_assembly_name()
1983 log("call", ins_name
, asmop
,
1984 kind
=LogType
.InstrInOuts
)
1986 # sv.setvl is *not* a loop-function. sigh
1987 log("is_svp64_mode", self
.is_svp64_mode
, asmop
)
1990 int_op
= yield self
.dec2
.dec
.op
.internal_op
1991 spr_msb
= yield from self
.get_spr_msb()
1993 instr_is_privileged
= False
1994 if int_op
in [MicrOp
.OP_ATTN
.value
,
1995 MicrOp
.OP_MFMSR
.value
,
1996 MicrOp
.OP_MTMSR
.value
,
1997 MicrOp
.OP_MTMSRD
.value
,
1999 MicrOp
.OP_RFID
.value
]:
2000 instr_is_privileged
= True
2001 if int_op
in [MicrOp
.OP_MFSPR
.value
,
2002 MicrOp
.OP_MTSPR
.value
] and spr_msb
:
2003 instr_is_privileged
= True
2005 log("is priv", instr_is_privileged
, hex(self
.msr
.value
),
2007 # check MSR priv bit and whether op is privileged: if so, throw trap
2008 if instr_is_privileged
and self
.msr
[MSRb
.PR
] == 1:
2009 self
.call_trap(0x700, PIb
.PRIV
)
2012 # check halted condition
2013 if ins_name
== 'attn':
2017 # User mode system call emulation consists of several steps:
2018 # 1. Detect whether instruction is sc or scv.
2019 # 2. Call the HDL implementation which invokes trap.
2020 # 3. Reroute the guest system call to host system call.
2021 # 4. Force return from the interrupt as if we had guest OS.
2022 if ((asmop
in ("sc", "scv")) and
2023 (self
.syscall
is not None) and
2024 not syscall_emu_active
):
2025 # Memoize PC and trigger an interrupt
2027 pc
= self
.pc
.CIA
.value
2030 yield from self
.call(asmop
, syscall_emu_active
=True)
2032 # Reroute the syscall to host OS
2033 identifier
= self
.gpr(0)
2034 arguments
= map(self
.gpr
, range(3, 9))
2035 result
= self
.syscall(identifier
, *arguments
)
2036 self
.gpr
.write(3, result
, False, self
.namespace
["XLEN"])
2038 # Return from interrupt
2039 yield from self
.call("rfid", syscall_emu_active
=True)
2041 elif ((name
in ("rfid", "hrfid")) and syscall_emu_active
):
2044 # check illegal instruction
2046 if ins_name
not in ['mtcrf', 'mtocrf']:
2047 illegal
= ins_name
!= asmop
2049 # list of instructions not being supported by binutils (.long)
2050 dotstrp
= asmop
[:-1] if asmop
[-1] == '.' else asmop
2051 if dotstrp
in [*FPTRANS_INSNS
,
2053 'ffmadds', 'fdmadds', 'ffadds',
2055 "brh", "brw", "brd",
2056 'setvl', 'svindex', 'svremap', 'svstep',
2057 'svshape', 'svshape2',
2058 'ternlogi', 'bmask', 'cprop',
2059 'absdu', 'absds', 'absdacs', 'absdacu', 'avgadd',
2060 'fmvis', 'fishmv', 'pcdec', "maddedu", "divmod2du",
2061 "dsld", "dsrd", "maddedus",
2062 "sadd", "saddw", "sadduw",
2067 "maddsubrs", "maddrs", "msubrs",
2068 "cfuged", "cntlzdm", "cnttzdm", "pdepd", "pextd",
2069 "setbc", "setbcr", "setnbc", "setnbcr",
2074 # branch-conditional redirects to sv.bc
2075 if asmop
.startswith('bc') and self
.is_svp64_mode
:
2076 ins_name
= 'sv.%s' % ins_name
2078 # ld-immediate-with-pi mode redirects to ld-with-postinc
2079 ldst_imm_postinc
= False
2080 if 'u' in ins_name
and self
.is_svp64_mode
:
2081 ldst_pi
= yield self
.dec2
.rm_dec
.ldst_postinc
2083 ins_name
= ins_name
.replace("u", "up")
2084 ldst_imm_postinc
= True
2085 log(" enable ld/st postinc", ins_name
)
2087 log(" post-processed name", dotstrp
, ins_name
, asmop
)
2089 # illegal instructions call TRAP at 0x700
2091 print("illegal", ins_name
, asmop
)
2092 self
.call_trap(0x700, PIb
.ILLEG
)
2093 print("name %s != %s - calling ILLEGAL trap, PC: %x" %
2094 (ins_name
, asmop
, self
.pc
.CIA
.value
))
2097 # this is for setvl "Vertical" mode: if set true,
2098 # srcstep/dststep is explicitly advanced. mode says which SVSTATE to
2099 # test for Rc=1 end condition. 3 bits of all 3 loops are put into CR0
2100 self
.allow_next_step_inc
= False
2101 self
.svstate_next_mode
= 0
2103 # nop has to be supported, we could let the actual op calculate
2104 # but PowerDecoder has a pattern for nop
2105 if ins_name
== 'nop':
2106 self
.update_pc_next()
2109 # get elwidths, defaults to 64
2113 if self
.is_svp64_mode
:
2114 ew_src
= yield self
.dec2
.rm_dec
.ew_src
2115 ew_dst
= yield self
.dec2
.rm_dec
.ew_dst
2116 ew_src
= 8 << (3-int(ew_src
)) # convert to bitlength
2117 ew_dst
= 8 << (3-int(ew_dst
)) # convert to bitlength
2118 xlen
= max(ew_src
, ew_dst
)
2119 log("elwdith", ew_src
, ew_dst
)
2120 log("XLEN:", self
.is_svp64_mode
, xlen
)
2122 # look up instruction in ISA.instrs, prepare namespace
2123 if ins_name
== 'pcdec': # grrrr yes there are others ("stbcx." etc.)
2124 info
= self
.instrs
[ins_name
+"."]
2125 elif asmop
[-1] == '.' and asmop
in self
.instrs
:
2126 info
= self
.instrs
[asmop
]
2128 info
= self
.instrs
[ins_name
]
2129 yield from self
.prep_namespace(ins_name
, info
.form
, info
.op_fields
,
2132 # dict retains order
2133 inputs
= dict.fromkeys(create_full_args(
2134 read_regs
=info
.read_regs
, special_regs
=info
.special_regs
,
2135 uninit_regs
=info
.uninit_regs
, write_regs
=info
.write_regs
))
2137 # preserve order of register names
2138 write_without_special_regs
= OrderedSet(info
.write_regs
)
2139 write_without_special_regs
-= OrderedSet(info
.special_regs
)
2140 input_names
= create_args([
2141 *info
.read_regs
, *info
.uninit_regs
, *write_without_special_regs
])
2142 log("input names", input_names
)
2144 # get SVP64 entry for the current instruction
2145 sv_rm
= self
.svp64rm
.instrs
.get(ins_name
)
2146 if sv_rm
is not None:
2147 dest_cr
, src_cr
, src_byname
, dest_byname
= decode_extra(sv_rm
)
2149 dest_cr
, src_cr
, src_byname
, dest_byname
= False, False, {}, {}
2150 log("sv rm", sv_rm
, dest_cr
, src_cr
, src_byname
, dest_byname
)
2152 # see if srcstep/dststep need skipping over masked-out predicate bits
2153 # svstep also needs advancement because it calls SVSTATE_NEXT.
2154 # bit the remaps get computed just after pre_inc moves them on
2155 # with remap_set_steps substituting for PowerDecider2 not doing it,
2156 # and SVSTATE_NEXT not being able to.use yield, the preinc on
2157 # svstep is necessary for now.
2159 if (self
.is_svp64_mode
or ins_name
in ['svstep']):
2160 yield from self
.svstate_pre_inc()
2161 if self
.is_svp64_mode
:
2162 pre
= yield from self
.update_new_svstate_steps()
2164 self
.svp64_reset_loop()
2166 self
.update_pc_next()
2168 srcstep
, dststep
, ssubstep
, dsubstep
= self
.get_src_dststeps()
2169 pred_dst_zero
= self
.pred_dst_zero
2170 pred_src_zero
= self
.pred_src_zero
2171 vl
= self
.svstate
.vl
2172 subvl
= yield self
.dec2
.rm_dec
.rm_in
.subvl
2174 # VL=0 in SVP64 mode means "do nothing: skip instruction"
2175 if self
.is_svp64_mode
and vl
== 0:
2176 self
.pc
.update(self
.namespace
, self
.is_svp64_mode
)
2177 log("SVP64: VL=0, end of call", self
.namespace
['CIA'],
2178 self
.namespace
['NIA'], kind
=LogType
.InstrInOuts
)
2181 # for when SVREMAP is active, using pre-arranged schedule.
2182 # note: modifying PowerDecoder2 needs to "settle"
2183 remap_en
= self
.svstate
.SVme
2184 persist
= self
.svstate
.RMpst
2185 active
= (persist
or self
.last_op_svshape
) and remap_en
!= 0
2186 if self
.is_svp64_mode
:
2187 yield self
.dec2
.remap_active
.eq(remap_en
if active
else 0)
2189 if persist
or self
.last_op_svshape
:
2190 remaps
= self
.get_remap_indices()
2191 if self
.is_svp64_mode
and (persist
or self
.last_op_svshape
):
2192 yield from self
.remap_set_steps(remaps
)
2193 # after that, settle down (combinatorial) to let Vector reg numbers
2194 # work themselves out
2196 if self
.is_svp64_mode
:
2197 remap_active
= yield self
.dec2
.remap_active
2199 remap_active
= False
2200 log("remap active", bin(remap_active
))
2202 # main input registers (RT, RA ...)
2203 for name
in input_names
:
2204 if name
== "overflow":
2205 inputs
[name
] = SelectableInt(0, 1)
2206 elif name
== "FPSCR":
2207 inputs
[name
] = self
.FPSCR
2208 elif name
in ("CA", "CA32", "OV", "OV32"):
2209 inputs
[name
] = self
.spr
['XER'][XER_bits
[name
]]
2211 inputs
[name
] = self
.crl
[0]
2212 elif name
in spr_byname
:
2213 inputs
[name
] = self
.spr
[name
]
2215 regval
= (yield from self
.get_input(name
, ew_src
))
2216 log("regval name", name
, regval
)
2217 inputs
[name
] = regval
2219 # arrrrgh, awful hack, to get _RT into namespace
2220 if ins_name
in ['setvl', 'svstep']:
2222 RT
= yield self
.dec2
.dec
.RT
2223 self
.namespace
[regname
] = SelectableInt(RT
, 5)
2225 self
.namespace
["RT"] = SelectableInt(0, 5)
2226 regnum
, is_vec
= yield from get_idx_out(self
.dec2
, "RT")
2227 log('hack input reg %s %s' % (name
, str(regnum
)), is_vec
)
2229 # in SVP64 mode for LD/ST work out immediate
2230 # XXX TODO: replace_ds for DS-Form rather than D-Form.
2231 # use info.form to detect
2232 if self
.is_svp64_mode
and not ldst_imm_postinc
:
2233 yield from self
.check_replace_d(info
, remap_active
)
2235 # "special" registers
2236 for special
in info
.special_regs
:
2237 if special
in special_sprs
:
2238 inputs
[special
] = self
.spr
[special
]
2240 inputs
[special
] = self
.namespace
[special
]
2242 # clear trap (trap) NIA
2243 self
.trap_nia
= None
2245 # check if this was an sv.bc* and create an indicator that
2246 # this is the last check to be made as a loop. combined with
2247 # the ALL/ANY mode we can early-exit. note that BI (to test)
2248 # is an input so there is no termination if BI is scalar
2249 # (because early-termination is for *output* scalars)
2250 if self
.is_svp64_mode
and ins_name
.startswith("sv.bc"):
2251 end_loop
= srcstep
== vl
-1 or dststep
== vl
-1
2252 self
.namespace
['end_loop'] = SelectableInt(end_loop
, 1)
2254 inp_ca_ov
= (self
.spr
['XER'][XER_bits
['CA']].value
,
2255 self
.spr
['XER'][XER_bits
['OV']].value
)
2257 for k
, v
in inputs
.items():
2259 v
= SelectableInt(0, self
.XLEN
)
2260 # prevent pseudo-code from modifying input registers
2261 v
= copy_assign_rhs(v
)
2262 if isinstance(v
, SelectableInt
):
2266 # execute actual instruction here (finally)
2267 log("inputs", inputs
)
2268 inputs
= list(inputs
.values())
2269 results
= info
.func(self
, *inputs
)
2270 output_names
= create_args(info
.write_regs
)
2272 # record .ok before anything after the pseudo-code can modify it
2274 for out
, n
in zip(results
or [], output_names
):
2277 if isinstance(out
, SelectableInt
):
2279 log("results", outs
)
2280 log("results ok", outs_ok
)
2282 # "inject" decorator takes namespace from function locals: we need to
2283 # overwrite NIA being overwritten (sigh)
2284 if self
.trap_nia
is not None:
2285 self
.namespace
['NIA'] = self
.trap_nia
2287 log("after func", self
.namespace
['CIA'], self
.namespace
['NIA'])
2289 # check if op was a LD/ST so that debugging can check the
2291 if int_op
in [MicrOp
.OP_STORE
.value
,
2293 self
.last_st_addr
= self
.mem
.last_st_addr
2294 if int_op
in [MicrOp
.OP_LOAD
.value
,
2296 self
.last_ld_addr
= self
.mem
.last_ld_addr
2297 log("op", int_op
, MicrOp
.OP_STORE
.value
, MicrOp
.OP_LOAD
.value
,
2298 self
.last_st_addr
, self
.last_ld_addr
)
2300 # detect if CA/CA32 already in outputs (sra*, basically)
2302 ca32
= outs
.get("CA32")
2304 log("carry already done?", ca
, ca32
, output_names
)
2305 # soc test_pipe_caller tests don't have output_carry
2306 has_output_carry
= hasattr(self
.dec2
.e
.do
, "output_carry")
2307 carry_en
= has_output_carry
and (yield self
.dec2
.e
.do
.output_carry
)
2309 yield from self
.handle_carry_(
2310 inputs
, results
[0], ca
, ca32
, inp_ca_ov
=inp_ca_ov
)
2312 # get output named "overflow" and "CR0"
2313 overflow
= outs
.get('overflow')
2314 cr0
= outs
.get('CR0')
2315 cr1
= outs
.get('CR1')
2317 # soc test_pipe_caller tests don't have oe
2318 has_oe
= hasattr(self
.dec2
.e
.do
, "oe")
2319 # yeah just no. not in parallel processing
2320 if has_oe
and not self
.is_svp64_mode
:
2321 # detect if overflow was in return result
2322 ov_en
= yield self
.dec2
.e
.do
.oe
.oe
2323 ov_ok
= yield self
.dec2
.e
.do
.oe
.ok
2324 log("internal overflow", ins_name
, overflow
, "en?", ov_en
, ov_ok
)
2326 yield from self
.handle_overflow(
2327 inputs
, results
[0], overflow
, inp_ca_ov
=inp_ca_ov
)
2329 # only do SVP64 dest predicated Rc=1 if dest-pred is not enabled
2331 if not self
.is_svp64_mode
or not pred_dst_zero
:
2332 if hasattr(self
.dec2
.e
.do
, "rc"):
2333 rc_en
= yield self
.dec2
.e
.do
.rc
.rc
2334 # don't do Rc=1 for svstep it is handled explicitly.
2335 # XXX TODO: now that CR0 is supported, sort out svstep's pseudocode
2336 # to write directly to CR0 instead of in ISACaller. hooyahh.
2337 if rc_en
and ins_name
not in ['svstep']:
2338 if outs_ok
.get('FPSCR', False):
2339 FPSCR
= outs
['FPSCR']
2342 yield from self
.do_rc_ov(
2343 ins_name
, results
[0], overflow
, cr0
, cr1
, FPSCR
)
2346 ffirst_hit
= False, False
2347 if self
.is_svp64_mode
:
2348 sv_mode
= yield self
.dec2
.rm_dec
.sv_mode
2349 is_cr
= sv_mode
== SVMode
.CROP
.value
2350 chk
= rc_en
or is_cr
2351 if outs_ok
.get('CR', False):
2352 # early write so check_ffirst can see value
2353 self
.namespace
['CR'].eq(outs
['CR'])
2354 ffirst_hit
= (yield from self
.check_ffirst(info
, chk
, srcstep
))
2356 # any modified return results?
2357 yield from self
.do_outregs(
2358 info
, outs
, carry_en
, ffirst_hit
, ew_dst
, outs_ok
)
2360 # check if a FP Exception occurred. TODO for DD-FFirst, check VLi
2361 # and raise the exception *after* if VLi=1 but if VLi=0 then
2362 # truncate and make the exception "disappear".
2363 if self
.FPSCR
.FEX
and (self
.msr
[MSRb
.FE0
] or self
.msr
[MSRb
.FE1
]):
2364 self
.call_trap(0x700, PIb
.FP
)
2367 yield from self
.do_nia(asmop
, ins_name
, rc_en
, ffirst_hit
)
2369 def check_ffirst(self
, info
, rc_en
, srcstep
):
2370 """fail-first mode: checks a bit of Rc Vector, truncates VL
2372 rm_mode
= yield self
.dec2
.rm_dec
.mode
2373 ff_inv
= yield self
.dec2
.rm_dec
.inv
2374 cr_bit
= yield self
.dec2
.rm_dec
.cr_sel
2375 RC1
= yield self
.dec2
.rm_dec
.RC1
2376 vli_
= yield self
.dec2
.rm_dec
.vli
# VL inclusive if truncated
2377 log(" ff rm_mode", rc_en
, rm_mode
, SVP64RMMode
.FFIRST
.value
)
2381 log(" cr_bit", cr_bit
)
2382 log(" rc_en", rc_en
)
2383 if not rc_en
or rm_mode
!= SVP64RMMode
.FFIRST
.value
:
2385 # get the CR vevtor, do BO-test
2387 log("asmregs", info
.asmregs
[0], info
.write_regs
)
2388 if 'CR' in info
.write_regs
and 'BF' in info
.asmregs
[0]:
2390 regnum
, is_vec
= yield from get_cr_out(self
.dec2
, crf
)
2391 crtest
= self
.crl
[regnum
]
2392 ffirst_hit
= crtest
[cr_bit
] != ff_inv
2393 log("cr test", crf
, regnum
, int(crtest
), crtest
, cr_bit
, ff_inv
)
2394 log("cr test?", ffirst_hit
)
2397 # Fail-first activated, truncate VL
2398 vli
= SelectableInt(int(vli_
), 7)
2399 self
.svstate
.vl
= srcstep
+ vli
2400 yield self
.dec2
.state
.svstate
.eq(self
.svstate
.value
)
2401 yield Settle() # let decoder update
2404 def do_rc_ov(self
, ins_name
, result
, overflow
, cr0
, cr1
, FPSCR
):
2405 cr_out
= yield self
.dec2
.op
.cr_out
2406 if cr_out
== CROutSel
.CR1
.value
:
2410 regnum
, is_vec
= yield from get_cr_out(self
.dec2
, rc_reg
)
2411 # hang on... for `setvl` actually you want to test SVSTATE.VL
2412 is_setvl
= ins_name
in ('svstep', 'setvl')
2414 result
= SelectableInt(result
.vl
, 64)
2416 # overflow = None # do not override overflow except in setvl
2420 cr1
= int(FPSCR
.FX
) << 3
2421 cr1 |
= int(FPSCR
.FEX
) << 2
2422 cr1 |
= int(FPSCR
.VX
) << 1
2423 cr1 |
= int(FPSCR
.OX
)
2424 log("default fp cr1", cr1
)
2426 log("explicit cr1", cr1
)
2427 self
.crl
[regnum
].eq(cr1
)
2429 # if there was not an explicit CR0 in the pseudocode,
2431 self
.handle_comparison(result
, regnum
, overflow
, no_so
=is_setvl
)
2433 # otherwise we just blat CR0 into the required regnum
2434 log("explicit rc0", cr0
)
2435 self
.crl
[regnum
].eq(cr0
)
2437 def do_outregs(self
, info
, outs
, ca_en
, ffirst_hit
, ew_dst
, outs_ok
):
2438 ffirst_hit
, vli
= ffirst_hit
2439 # write out any regs for this instruction, but only if fail-first is ok
2440 # XXX TODO: allow CR-vector to be written out even if ffirst fails
2441 if not ffirst_hit
or vli
:
2442 for name
, output
in outs
.items():
2443 if not outs_ok
[name
]:
2444 log("skipping writing output with .ok=False", name
, output
)
2446 yield from self
.check_write(info
, name
, output
, ca_en
, ew_dst
)
2447 # restore the CR value on non-VLI failfirst (from sv.cmp and others
2448 # which write directly to CR in the pseudocode (gah, what a mess)
2449 # if ffirst_hit and not vli:
2450 # self.cr.value = self.cr_backup
2452 def do_nia(self
, asmop
, ins_name
, rc_en
, ffirst_hit
):
2453 ffirst_hit
, vli
= ffirst_hit
2455 self
.svp64_reset_loop()
2458 # check advancement of src/dst/sub-steps and if PC needs updating
2459 nia_update
= (yield from self
.check_step_increment(
2460 rc_en
, asmop
, ins_name
))
2462 self
.update_pc_next()
2464 def check_replace_d(self
, info
, remap_active
):
2465 replace_d
= False # update / replace constant in pseudocode
2466 ldstmode
= yield self
.dec2
.rm_dec
.ldstmode
2467 vl
= self
.svstate
.vl
2468 subvl
= yield self
.dec2
.rm_dec
.rm_in
.subvl
2469 srcstep
, dststep
= self
.new_srcstep
, self
.new_dststep
2470 ssubstep
, dsubstep
= self
.new_ssubstep
, self
.new_dsubstep
2471 if info
.form
== 'DS':
2472 # DS-Form, multiply by 4 then knock 2 bits off after
2473 imm
= yield self
.dec2
.dec
.fields
.FormDS
.DS
[0:14] * 4
2475 imm
= yield self
.dec2
.dec
.fields
.FormD
.D
[0:16]
2476 imm
= exts(imm
, 16) # sign-extend to integer
2477 # get the right step. LD is from srcstep, ST is dststep
2478 op
= yield self
.dec2
.e
.do
.insn_type
2480 if op
== MicrOp
.OP_LOAD
.value
:
2482 offsmul
= yield self
.dec2
.in1_step
2483 log("D-field REMAP src", imm
, offsmul
, ldstmode
)
2485 offsmul
= (srcstep
* (subvl
+1)) + ssubstep
2486 log("D-field src", imm
, offsmul
, ldstmode
)
2487 elif op
== MicrOp
.OP_STORE
.value
:
2488 # XXX NOTE! no bit-reversed STORE! this should not ever be used
2489 offsmul
= (dststep
* (subvl
+1)) + dsubstep
2490 log("D-field dst", imm
, offsmul
, ldstmode
)
2491 # Unit-Strided LD/ST adds offset*width to immediate
2492 if ldstmode
== SVP64LDSTmode
.UNITSTRIDE
.value
:
2493 ldst_len
= yield self
.dec2
.e
.do
.data_len
2494 imm
= SelectableInt(imm
+ offsmul
* ldst_len
, 32)
2496 # Element-strided multiplies the immediate by element step
2497 elif ldstmode
== SVP64LDSTmode
.ELSTRIDE
.value
:
2498 imm
= SelectableInt(imm
* offsmul
, 32)
2501 ldst_ra_vec
= yield self
.dec2
.rm_dec
.ldst_ra_vec
2502 ldst_imz_in
= yield self
.dec2
.rm_dec
.ldst_imz_in
2503 log("LDSTmode", SVP64LDSTmode(ldstmode
),
2504 offsmul
, imm
, ldst_ra_vec
, ldst_imz_in
)
2505 # new replacement D... errr.. DS
2507 if info
.form
== 'DS':
2508 # TODO: assert 2 LSBs are zero?
2509 log("DS-Form, TODO, assert 2 LSBs zero?", bin(imm
.value
))
2510 imm
.value
= imm
.value
>> 2
2511 self
.namespace
['DS'] = imm
2513 self
.namespace
['D'] = imm
2515 def get_input(self
, name
, ew_src
):
2516 # using PowerDecoder2, first, find the decoder index.
2517 # (mapping name RA RB RC RS to in1, in2, in3)
2518 regnum
, is_vec
= yield from get_idx_in(self
.dec2
, name
, True)
2520 # doing this is not part of svp64, it's because output
2521 # registers, to be modified, need to be in the namespace.
2522 regnum
, is_vec
= yield from get_idx_out(self
.dec2
, name
, True)
2524 regnum
, is_vec
= yield from get_idx_out2(self
.dec2
, name
, True)
2526 if isinstance(regnum
, tuple):
2527 (regnum
, base
, offs
) = regnum
2529 base
, offs
= regnum
, 0 # temporary HACK
2531 # in case getting the register number is needed, _RA, _RB
2532 # (HACK: only in straight non-svp64-mode for now, or elwidth == 64)
2533 regname
= "_" + name
2534 if not self
.is_svp64_mode
or ew_src
== 64:
2535 self
.namespace
[regname
] = regnum
2536 elif regname
in self
.namespace
:
2537 del self
.namespace
[regname
]
2539 if not self
.is_svp64_mode
or not self
.pred_src_zero
:
2540 log('reading reg %s %s' % (name
, str(regnum
)), is_vec
)
2542 reg_val
= SelectableInt(self
.fpr(base
, is_vec
, offs
, ew_src
))
2543 log("read reg %d/%d: 0x%x" % (base
, offs
, reg_val
.value
),
2544 kind
=LogType
.InstrInOuts
)
2545 self
.trace("r:FPR:%d:%d:%d " % (base
, offs
, ew_src
))
2546 elif name
is not None:
2547 reg_val
= SelectableInt(self
.gpr(base
, is_vec
, offs
, ew_src
))
2548 self
.trace("r:GPR:%d:%d:%d " % (base
, offs
, ew_src
))
2549 log("read reg %d/%d: 0x%x" % (base
, offs
, reg_val
.value
),
2550 kind
=LogType
.InstrInOuts
)
2552 log('zero input reg %s %s' % (name
, str(regnum
)), is_vec
)
2553 reg_val
= SelectableInt(0, ew_src
)
2556 def remap_set_steps(self
, remaps
):
2557 """remap_set_steps sets up the in1/2/3 and out1/2 steps.
2558 they work in concert with PowerDecoder2 at the moment,
2559 there is no HDL implementation of REMAP. therefore this
2560 function, because ISACaller still uses PowerDecoder2,
2561 will *explicitly* write the dec2.XX_step values. this has
2564 # just some convenient debug info
2566 sname
= 'SVSHAPE%d' % i
2567 shape
= self
.spr
[sname
]
2568 log(sname
, bin(shape
.value
))
2569 log(" lims", shape
.lims
)
2570 log(" mode", shape
.mode
)
2571 log(" skip", shape
.skip
)
2573 # set up the list of steps to remap
2574 mi0
= self
.svstate
.mi0
2575 mi1
= self
.svstate
.mi1
2576 mi2
= self
.svstate
.mi2
2577 mo0
= self
.svstate
.mo0
2578 mo1
= self
.svstate
.mo1
2579 steps
= [[self
.dec2
.in1_step
, mi0
], # RA
2580 [self
.dec2
.in2_step
, mi1
], # RB
2581 [self
.dec2
.in3_step
, mi2
], # RC
2582 [self
.dec2
.o_step
, mo0
], # RT
2583 [self
.dec2
.o2_step
, mo1
], # EA
2586 rnames
= ['RA', 'RB', 'RC', 'RT', 'RS']
2587 for i
, reg
in enumerate(rnames
):
2588 idx
= yield from get_idx_map(self
.dec2
, reg
)
2590 idx
= yield from get_idx_map(self
.dec2
, "F"+reg
)
2592 steps
[i
][0] = self
.dec2
.in1_step
2594 steps
[i
][0] = self
.dec2
.in2_step
2596 steps
[i
][0] = self
.dec2
.in3_step
2597 log("remap step", i
, reg
, idx
, steps
[i
][1])
2598 remap_idxs
= self
.remap_idxs
2600 # now cross-index the required SHAPE for each of 3-in 2-out regs
2601 rnames
= ['RA', 'RB', 'RC', 'RT', 'EA']
2602 for i
, (dstep
, shape_idx
) in enumerate(steps
):
2603 (shape
, remap
) = remaps
[shape_idx
]
2604 remap_idx
= remap_idxs
[shape_idx
]
2605 # zero is "disabled"
2606 if shape
.value
== 0x0:
2608 # now set the actual requested step to the current index
2609 if dstep
is not None:
2610 yield dstep
.eq(remap_idx
)
2612 # debug printout info
2613 rremaps
.append((shape
.mode
, hex(shape
.value
), dstep
,
2614 i
, rnames
[i
], shape_idx
, remap_idx
))
2616 log("shape remap", x
)
2618 def check_write(self
, info
, name
, output
, carry_en
, ew_dst
):
2619 if name
== 'overflow': # ignore, done already (above)
2621 if name
== 'CR0': # ignore, done already (above)
2623 if isinstance(output
, int):
2624 output
= SelectableInt(output
, EFFECTIVELY_UNLIMITED
)
2626 if name
in ['FPSCR', ]:
2627 log("write FPSCR 0x%x" % (output
.value
))
2628 self
.FPSCR
.eq(output
)
2631 if name
in ['CA', 'CA32']:
2633 log("writing %s to XER" % name
, output
)
2634 log("write XER %s 0x%x" % (name
, output
.value
))
2635 self
.spr
['XER'][XER_bits
[name
]] = output
.value
2637 log("NOT writing %s to XER" % name
, output
)
2639 # write special SPRs
2640 if name
in info
.special_regs
:
2641 log('writing special %s' % name
, output
, special_sprs
)
2642 log("write reg %s 0x%x" % (name
, output
.value
),
2643 kind
=LogType
.InstrInOuts
)
2644 if name
in special_sprs
:
2645 self
.spr
[name
] = output
2647 self
.namespace
[name
].eq(output
)
2649 log('msr written', hex(self
.msr
.value
))
2651 # find out1/out2 PR/FPR
2652 regnum
, is_vec
= yield from get_idx_out(self
.dec2
, name
, True)
2654 regnum
, is_vec
= yield from get_idx_out2(self
.dec2
, name
, True)
2656 # temporary hack for not having 2nd output
2657 regnum
= yield getattr(self
.decoder
, name
)
2659 # convenient debug prefix
2664 # check zeroing due to predicate bit being zero
2665 if self
.is_svp64_mode
and self
.pred_dst_zero
:
2666 log('zeroing reg %s %s' % (str(regnum
), str(output
)), is_vec
)
2667 output
= SelectableInt(0, EFFECTIVELY_UNLIMITED
)
2668 log("write reg %s%s 0x%x ew %d" % (reg_prefix
, str(regnum
),
2669 output
.value
, ew_dst
),
2670 kind
=LogType
.InstrInOuts
)
2671 # zero-extend tov64 bit begore storing (should use EXT oh well)
2672 if output
.bits
> 64:
2673 output
= SelectableInt(output
.value
, 64)
2674 rnum
, base
, offset
= regnum
2676 self
.fpr
.write(regnum
, output
, is_vec
, ew_dst
)
2677 self
.trace("w:FPR:%d:%d:%d " % (rnum
, offset
, ew_dst
))
2679 self
.gpr
.write(regnum
, output
, is_vec
, ew_dst
)
2680 self
.trace("w:GPR:%d:%d:%d " % (rnum
, offset
, ew_dst
))
2682 def check_step_increment(self
, rc_en
, asmop
, ins_name
):
2683 # check if it is the SVSTATE.src/dest step that needs incrementing
2684 # this is our Sub-Program-Counter loop from 0 to VL-1
2685 if not self
.allow_next_step_inc
:
2686 if self
.is_svp64_mode
:
2687 return (yield from self
.svstate_post_inc(ins_name
))
2689 # XXX only in non-SVP64 mode!
2690 # record state of whether the current operation was an svshape,
2692 # to be able to know if it should apply in the next instruction.
2693 # also (if going to use this instruction) should disable ability
2694 # to interrupt in between. sigh.
2695 self
.last_op_svshape
= asmop
in ['svremap', 'svindex',
2702 log("SVSTATE_NEXT: inc requested, mode",
2703 self
.svstate_next_mode
, self
.allow_next_step_inc
)
2704 yield from self
.svstate_pre_inc()
2705 pre
= yield from self
.update_new_svstate_steps()
2707 # reset at end of loop including exit Vertical Mode
2708 log("SVSTATE_NEXT: end of loop, reset")
2709 self
.svp64_reset_loop()
2710 self
.svstate
.vfirst
= 0
2714 self
.handle_comparison(SelectableInt(0, 64)) # CR0
2716 if self
.allow_next_step_inc
== 2:
2717 log("SVSTATE_NEXT: read")
2718 nia_update
= (yield from self
.svstate_post_inc(ins_name
))
2720 log("SVSTATE_NEXT: post-inc")
2721 # use actual (cached) src/dst-step here to check end
2722 remaps
= self
.get_remap_indices()
2723 remap_idxs
= self
.remap_idxs
2724 vl
= self
.svstate
.vl
2725 subvl
= yield self
.dec2
.rm_dec
.rm_in
.subvl
2726 if self
.allow_next_step_inc
!= 2:
2727 yield from self
.advance_svstate_steps()
2728 #self.namespace['SVSTATE'] = self.svstate.spr
2729 # set CR0 (if Rc=1) based on end
2730 endtest
= 1 if self
.at_loopend() else 0
2732 #results = [SelectableInt(endtest, 64)]
2733 # self.handle_comparison(results) # CR0
2735 # see if svstep was requested, if so, which SVSTATE
2737 if self
.svstate_next_mode
> 0:
2738 shape_idx
= self
.svstate_next_mode
.value
-1
2739 endings
= self
.remap_loopends
[shape_idx
]
2740 cr_field
= SelectableInt((~endings
) << 1 | endtest
, 4)
2741 log("svstep Rc=1, CR0", cr_field
, endtest
)
2742 self
.crl
[0].eq(cr_field
) # CR0
2744 # reset at end of loop including exit Vertical Mode
2745 log("SVSTATE_NEXT: after increments, reset")
2746 self
.svp64_reset_loop()
2747 self
.svstate
.vfirst
= 0
2750 def SVSTATE_NEXT(self
, mode
, submode
):
2751 """explicitly moves srcstep/dststep on to next element, for
2752 "Vertical-First" mode. this function is called from
2753 setvl pseudo-code, as a pseudo-op "svstep"
2755 WARNING: this function uses information that was created EARLIER
2756 due to it being in the middle of a yield, but this function is
2757 *NOT* called from yield (it's called from compiled pseudocode).
2759 self
.allow_next_step_inc
= submode
.value
+ 1
2760 log("SVSTATE_NEXT mode", mode
, submode
, self
.allow_next_step_inc
)
2761 self
.svstate_next_mode
= mode
2762 if self
.svstate_next_mode
> 0 and self
.svstate_next_mode
< 5:
2763 shape_idx
= self
.svstate_next_mode
.value
-1
2764 return SelectableInt(self
.remap_idxs
[shape_idx
], 7)
2765 if self
.svstate_next_mode
== 5:
2766 self
.svstate_next_mode
= 0
2767 return SelectableInt(self
.svstate
.srcstep
, 7)
2768 if self
.svstate_next_mode
== 6:
2769 self
.svstate_next_mode
= 0
2770 return SelectableInt(self
.svstate
.dststep
, 7)
2771 if self
.svstate_next_mode
== 7:
2772 self
.svstate_next_mode
= 0
2773 return SelectableInt(self
.svstate
.ssubstep
, 7)
2774 if self
.svstate_next_mode
== 8:
2775 self
.svstate_next_mode
= 0
2776 return SelectableInt(self
.svstate
.dsubstep
, 7)
2777 return SelectableInt(0, 7)
2779 def get_src_dststeps(self
):
2780 """gets srcstep, dststep, and ssubstep, dsubstep
2782 return (self
.new_srcstep
, self
.new_dststep
,
2783 self
.new_ssubstep
, self
.new_dsubstep
)
2785 def update_svstate_namespace(self
, overwrite_svstate
=True):
2786 if overwrite_svstate
:
2787 # note, do not get the bit-reversed srcstep here!
2788 srcstep
, dststep
= self
.new_srcstep
, self
.new_dststep
2789 ssubstep
, dsubstep
= self
.new_ssubstep
, self
.new_dsubstep
2791 # update SVSTATE with new srcstep
2792 self
.svstate
.srcstep
= srcstep
2793 self
.svstate
.dststep
= dststep
2794 self
.svstate
.ssubstep
= ssubstep
2795 self
.svstate
.dsubstep
= dsubstep
2796 self
.namespace
['SVSTATE'] = self
.svstate
2797 yield self
.dec2
.state
.svstate
.eq(self
.svstate
.value
)
2798 yield Settle() # let decoder update
2800 def update_new_svstate_steps(self
, overwrite_svstate
=True):
2801 yield from self
.update_svstate_namespace(overwrite_svstate
)
2802 srcstep
= self
.svstate
.srcstep
2803 dststep
= self
.svstate
.dststep
2804 ssubstep
= self
.svstate
.ssubstep
2805 dsubstep
= self
.svstate
.dsubstep
2806 pack
= self
.svstate
.pack
2807 unpack
= self
.svstate
.unpack
2808 vl
= self
.svstate
.vl
2809 sv_mode
= yield self
.dec2
.rm_dec
.sv_mode
2810 subvl
= yield self
.dec2
.rm_dec
.rm_in
.subvl
2811 rm_mode
= yield self
.dec2
.rm_dec
.mode
2812 ff_inv
= yield self
.dec2
.rm_dec
.inv
2813 cr_bit
= yield self
.dec2
.rm_dec
.cr_sel
2814 log(" srcstep", srcstep
)
2815 log(" dststep", dststep
)
2817 log(" unpack", unpack
)
2818 log(" ssubstep", ssubstep
)
2819 log(" dsubstep", dsubstep
)
2821 log(" subvl", subvl
)
2822 log(" rm_mode", rm_mode
)
2823 log(" sv_mode", sv_mode
)
2825 log(" cr_bit", cr_bit
)
2827 # check if end reached (we let srcstep overrun, above)
2828 # nothing needs doing (TODO zeroing): just do next instruction
2831 return ((ssubstep
== subvl
and srcstep
== vl
) or
2832 (dsubstep
== subvl
and dststep
== vl
))
2834 def svstate_post_inc(self
, insn_name
, vf
=0):
2835 # check if SV "Vertical First" mode is enabled
2836 vfirst
= self
.svstate
.vfirst
2837 log(" SV Vertical First", vf
, vfirst
)
2838 if not vf
and vfirst
== 1:
2839 if insn_name
.startswith("sv.bc"):
2840 self
.update_pc_next()
2845 # check if it is the SVSTATE.src/dest step that needs incrementing
2846 # this is our Sub-Program-Counter loop from 0 to VL-1
2847 # XXX twin predication TODO
2848 vl
= self
.svstate
.vl
2849 subvl
= yield self
.dec2
.rm_dec
.rm_in
.subvl
2850 mvl
= self
.svstate
.maxvl
2851 srcstep
= self
.svstate
.srcstep
2852 dststep
= self
.svstate
.dststep
2853 ssubstep
= self
.svstate
.ssubstep
2854 dsubstep
= self
.svstate
.dsubstep
2855 pack
= self
.svstate
.pack
2856 unpack
= self
.svstate
.unpack
2857 rm_mode
= yield self
.dec2
.rm_dec
.mode
2858 reverse_gear
= yield self
.dec2
.rm_dec
.reverse_gear
2859 sv_ptype
= yield self
.dec2
.dec
.op
.SV_Ptype
2860 out_vec
= not (yield self
.dec2
.no_out_vec
)
2861 in_vec
= not (yield self
.dec2
.no_in_vec
)
2862 log(" svstate.vl", vl
)
2863 log(" svstate.mvl", mvl
)
2864 log(" rm.subvl", subvl
)
2865 log(" svstate.srcstep", srcstep
)
2866 log(" svstate.dststep", dststep
)
2867 log(" svstate.ssubstep", ssubstep
)
2868 log(" svstate.dsubstep", dsubstep
)
2869 log(" svstate.pack", pack
)
2870 log(" svstate.unpack", unpack
)
2871 log(" mode", rm_mode
)
2872 log(" reverse", reverse_gear
)
2873 log(" out_vec", out_vec
)
2874 log(" in_vec", in_vec
)
2875 log(" sv_ptype", sv_ptype
, sv_ptype
== SVPType
.P2
.value
)
2876 # check if this was an sv.bc* and if so did it succeed
2877 if self
.is_svp64_mode
and insn_name
.startswith("sv.bc"):
2878 end_loop
= self
.namespace
['end_loop']
2879 log("branch %s end_loop" % insn_name
, end_loop
)
2881 self
.svp64_reset_loop()
2882 self
.update_pc_next()
2884 # check if srcstep needs incrementing by one, stop PC advancing
2885 # but for 2-pred both src/dest have to be checked.
2886 # XXX this might not be true! it may just be LD/ST
2887 if sv_ptype
== SVPType
.P2
.value
:
2888 svp64_is_vector
= (out_vec
or in_vec
)
2890 svp64_is_vector
= out_vec
2891 # loops end at the first "hit" (source or dest)
2892 yield from self
.advance_svstate_steps()
2893 loopend
= self
.loopend
2894 log("loopend", svp64_is_vector
, loopend
)
2895 if not svp64_is_vector
or loopend
:
2896 # reset loop to zero and update NIA
2897 self
.svp64_reset_loop()
2902 # still looping, advance and update NIA
2903 self
.namespace
['SVSTATE'] = self
.svstate
2905 # not an SVP64 branch, so fix PC (NIA==CIA) for next loop
2906 # (by default, NIA is CIA+4 if v3.0B or CIA+8 if SVP64)
2907 # this way we keep repeating the same instruction (with new steps)
2908 self
.pc
.NIA
.eq(self
.pc
.CIA
)
2909 self
.namespace
['NIA'] = self
.pc
.NIA
2910 log("end of sub-pc call", self
.namespace
['CIA'], self
.namespace
['NIA'])
2911 return False # DO NOT allow PC update whilst Sub-PC loop running
2913 def update_pc_next(self
):
2914 # UPDATE program counter
2915 self
.pc
.update(self
.namespace
, self
.is_svp64_mode
)
2916 #self.svstate.spr = self.namespace['SVSTATE']
2917 log("end of call", self
.namespace
['CIA'],
2918 self
.namespace
['NIA'],
2919 self
.namespace
['SVSTATE'])
2921 def svp64_reset_loop(self
):
2922 self
.svstate
.srcstep
= 0
2923 self
.svstate
.dststep
= 0
2924 self
.svstate
.ssubstep
= 0
2925 self
.svstate
.dsubstep
= 0
2926 self
.loopend
= False
2927 log(" svstate.srcstep loop end (PC to update)")
2928 self
.namespace
['SVSTATE'] = self
.svstate
2930 def update_nia(self
):
2931 self
.pc
.update_nia(self
.is_svp64_mode
)
2932 self
.namespace
['NIA'] = self
.pc
.NIA
2936 """Decorator factory.
2938 this decorator will "inject" variables into the function's namespace,
2939 from the *dictionary* in self.namespace. it therefore becomes possible
2940 to make it look like a whole stack of variables which would otherwise
2941 need "self." inserted in front of them (*and* for those variables to be
2942 added to the instance) "appear" in the function.
2944 "self.namespace['SI']" for example becomes accessible as just "SI" but
2945 *only* inside the function, when decorated.
2947 def variable_injector(func
):
2949 def decorator(*args
, **kwargs
):
2951 func_globals
= func
.__globals
__ # Python 2.6+
2952 except AttributeError:
2953 func_globals
= func
.func_globals
# Earlier versions.
2955 context
= args
[0].namespace
# variables to be injected
2956 saved_values
= func_globals
.copy() # Shallow copy of dict.
2957 log("globals before", context
.keys())
2958 func_globals
.update(context
)
2959 result
= func(*args
, **kwargs
)
2960 log("globals after", func_globals
['CIA'], func_globals
['NIA'])
2961 log("args[0]", args
[0].namespace
['CIA'],
2962 args
[0].namespace
['NIA'],
2963 args
[0].namespace
['SVSTATE'])
2964 if 'end_loop' in func_globals
:
2965 log("args[0] end_loop", func_globals
['end_loop'])
2966 args
[0].namespace
= func_globals
2967 #exec (func.__code__, func_globals)
2970 # func_globals = saved_values # Undo changes.
2976 return variable_injector