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 print("reg", "%2d" % i
, s
)
253 def __init__(self
, dec2
, initial_sprs
={}):
256 for key
, v
in initial_sprs
.items():
257 if isinstance(key
, SelectableInt
):
259 key
= special_sprs
.get(key
, key
)
260 if isinstance(key
, int):
263 info
= spr_byname
[key
]
264 if not isinstance(v
, SelectableInt
):
265 v
= SelectableInt(v
, info
.length
)
268 def __getitem__(self
, key
):
270 #log("dict", self.items())
271 # if key in special_sprs get the special spr, otherwise return key
272 if isinstance(key
, SelectableInt
):
274 if isinstance(key
, int):
275 key
= spr_dict
[key
].SPR
276 key
= special_sprs
.get(key
, key
)
277 if key
== 'HSRR0': # HACK!
279 if key
== 'HSRR1': # HACK!
282 res
= dict.__getitem
__(self
, key
)
284 if isinstance(key
, int):
287 info
= spr_byname
[key
]
288 self
[key
] = SelectableInt(0, info
.length
)
289 res
= dict.__getitem
__(self
, key
)
290 #log("spr returning", key, res)
293 def __setitem__(self
, key
, value
):
294 if isinstance(key
, SelectableInt
):
296 if isinstance(key
, int):
297 key
= spr_dict
[key
].SPR
299 key
= special_sprs
.get(key
, key
)
300 if key
== 'HSRR0': # HACK!
301 self
.__setitem
__('SRR0', value
)
302 if key
== 'HSRR1': # HACK!
303 self
.__setitem
__('SRR1', value
)
305 value
= XERState(value
)
306 log("setting spr", key
, value
)
307 dict.__setitem
__(self
, key
, value
)
309 def __call__(self
, ridx
):
312 def dump(self
, printout
=True):
314 keys
= list(self
.keys())
317 sprname
= spr_dict
.get(k
, None)
321 sprname
= sprname
.SPR
322 res
.append((sprname
, self
[k
].value
))
324 for sprname
, value
in res
:
325 print(" ", sprname
, hex(value
))
330 def __init__(self
, pc_init
=0):
331 self
.CIA
= SelectableInt(pc_init
, 64)
332 self
.NIA
= self
.CIA
+ SelectableInt(4, 64) # only true for v3.0B!
334 def update_nia(self
, is_svp64
):
335 increment
= 8 if is_svp64
else 4
336 self
.NIA
= self
.CIA
+ SelectableInt(increment
, 64)
338 def update(self
, namespace
, is_svp64
):
339 """updates the program counter (PC) by 4 if v3.0B mode or 8 if SVP64
341 self
.CIA
= namespace
['NIA'].narrow(64)
342 self
.update_nia(is_svp64
)
343 namespace
['CIA'] = self
.CIA
344 namespace
['NIA'] = self
.NIA
348 # See PowerISA Version 3.0 B Book 1
349 # Section 2.3.1 Condition Register pages 30 - 31
351 LT
= FL
= 0 # negative, less than, floating-point less than
352 GT
= FG
= 1 # positive, greater than, floating-point greater than
353 EQ
= FE
= 2 # equal, floating-point equal
354 SO
= FU
= 3 # summary overflow, floating-point unordered
356 def __init__(self
, init
=0):
357 # rev_cr = int('{:016b}'.format(initial_cr)[::-1], 2)
358 # self.cr = FieldSelectableInt(self._cr, list(range(32, 64)))
359 self
.cr
= SelectableInt(init
, 64) # underlying reg
360 # field-selectable versions of Condition Register TODO check bitranges?
363 bits
= tuple(range(i
*4+32, (i
+1)*4+32))
364 _cr
= FieldSelectableInt(self
.cr
, bits
)
368 # decode SVP64 predicate integer to reg number and invert
369 def get_predint(gpr
, mask
):
373 log("get_predint", mask
, SVP64PredInt
.ALWAYS
.value
)
374 if mask
== SVP64PredInt
.ALWAYS
.value
:
375 return 0xffff_ffff_ffff_ffff # 64 bits of 1
376 if mask
== SVP64PredInt
.R3_UNARY
.value
:
377 return 1 << (r3
.value
& 0b111111)
378 if mask
== SVP64PredInt
.R3
.value
:
380 if mask
== SVP64PredInt
.R3_N
.value
:
382 if mask
== SVP64PredInt
.R10
.value
:
384 if mask
== SVP64PredInt
.R10_N
.value
:
386 if mask
== SVP64PredInt
.R30
.value
:
388 if mask
== SVP64PredInt
.R30_N
.value
:
392 # decode SVP64 predicate CR to reg number and invert status
393 def _get_predcr(mask
):
394 if mask
== SVP64PredCR
.LT
.value
:
396 if mask
== SVP64PredCR
.GE
.value
:
398 if mask
== SVP64PredCR
.GT
.value
:
400 if mask
== SVP64PredCR
.LE
.value
:
402 if mask
== SVP64PredCR
.EQ
.value
:
404 if mask
== SVP64PredCR
.NE
.value
:
406 if mask
== SVP64PredCR
.SO
.value
:
408 if mask
== SVP64PredCR
.NS
.value
:
412 # read individual CR fields (0..VL-1), extract the required bit
413 # and construct the mask
414 def get_predcr(crl
, mask
, vl
):
415 idx
, noninv
= _get_predcr(mask
)
418 cr
= crl
[i
+SVP64CROffs
.CRPred
]
419 if cr
[idx
].value
== noninv
:
424 # TODO, really should just be using PowerDecoder2
425 def get_idx_map(dec2
, name
):
427 in1_sel
= yield op
.in1_sel
428 in2_sel
= yield op
.in2_sel
429 in3_sel
= yield op
.in3_sel
430 in1
= yield dec2
.e
.read_reg1
.data
431 # identify which regnames map to in1/2/3
432 if name
== 'RA' or name
== 'RA_OR_ZERO':
433 if (in1_sel
== In1Sel
.RA
.value
or
434 (in1_sel
== In1Sel
.RA_OR_ZERO
.value
and in1
!= 0)):
436 if in1_sel
== In1Sel
.RA_OR_ZERO
.value
:
439 if in2_sel
== In2Sel
.RB
.value
:
441 if in3_sel
== In3Sel
.RB
.value
:
443 # XXX TODO, RC doesn't exist yet!
445 if in3_sel
== In3Sel
.RC
.value
:
447 elif name
in ['EA', 'RS']:
448 if in1_sel
== In1Sel
.RS
.value
:
450 if in2_sel
== In2Sel
.RS
.value
:
452 if in3_sel
== In3Sel
.RS
.value
:
455 if in1_sel
== In1Sel
.FRA
.value
:
457 if in3_sel
== In3Sel
.FRA
.value
:
460 if in2_sel
== In2Sel
.FRB
.value
:
463 if in3_sel
== In3Sel
.FRC
.value
:
466 if in1_sel
== In1Sel
.FRS
.value
:
468 if in3_sel
== In3Sel
.FRS
.value
:
471 if in1_sel
== In1Sel
.FRT
.value
:
474 if in1_sel
== In1Sel
.RT
.value
:
479 # TODO, really should just be using PowerDecoder2
480 def get_idx_in(dec2
, name
, ewmode
=False):
481 idx
= yield from get_idx_map(dec2
, name
)
485 in1_sel
= yield op
.in1_sel
486 in2_sel
= yield op
.in2_sel
487 in3_sel
= yield op
.in3_sel
488 # get the IN1/2/3 from the decoder (includes SVP64 remap and isvec)
489 in1
= yield dec2
.e
.read_reg1
.data
490 in2
= yield dec2
.e
.read_reg2
.data
491 in3
= yield dec2
.e
.read_reg3
.data
493 in1_base
= yield dec2
.e
.read_reg1
.base
494 in2_base
= yield dec2
.e
.read_reg2
.base
495 in3_base
= yield dec2
.e
.read_reg3
.base
496 in1_offs
= yield dec2
.e
.read_reg1
.offs
497 in2_offs
= yield dec2
.e
.read_reg2
.offs
498 in3_offs
= yield dec2
.e
.read_reg3
.offs
499 in1
= (in1
, in1_base
, in1_offs
)
500 in2
= (in2
, in2_base
, in2_offs
)
501 in3
= (in3
, in3_base
, in3_offs
)
503 in1_isvec
= yield dec2
.in1_isvec
504 in2_isvec
= yield dec2
.in2_isvec
505 in3_isvec
= yield dec2
.in3_isvec
506 log("get_idx_in in1", name
, in1_sel
, In1Sel
.RA
.value
,
508 log("get_idx_in in2", name
, in2_sel
, In2Sel
.RB
.value
,
510 log("get_idx_in in3", name
, in3_sel
, In3Sel
.RS
.value
,
512 log("get_idx_in FRS in3", name
, in3_sel
, In3Sel
.FRS
.value
,
514 log("get_idx_in FRB in2", name
, in2_sel
, In2Sel
.FRB
.value
,
516 log("get_idx_in FRC in3", name
, in3_sel
, In3Sel
.FRC
.value
,
519 return in1
, in1_isvec
521 return in2
, in2_isvec
523 return in3
, in3_isvec
527 # TODO, really should just be using PowerDecoder2
528 def get_cr_in(dec2
, name
):
530 in_sel
= yield op
.cr_in
531 in_bitfield
= yield dec2
.dec_cr_in
.cr_bitfield
.data
532 sv_cr_in
= yield op
.sv_cr_in
533 spec
= yield dec2
.crin_svdec
.spec
534 sv_override
= yield dec2
.dec_cr_in
.sv_override
535 # get the IN1/2/3 from the decoder (includes SVP64 remap and isvec)
536 in1
= yield dec2
.e
.read_cr1
.data
537 cr_isvec
= yield dec2
.cr_in_isvec
538 log("get_cr_in", in_sel
, CROutSel
.CR0
.value
, in1
, cr_isvec
)
539 log(" sv_cr_in", sv_cr_in
)
540 log(" cr_bf", in_bitfield
)
542 log(" override", sv_override
)
543 # identify which regnames map to in / o2
545 if in_sel
== CRInSel
.BI
.value
:
547 log("get_cr_in not found", name
)
551 # TODO, really should just be using PowerDecoder2
552 def get_cr_out(dec2
, name
):
554 out_sel
= yield op
.cr_out
555 out_bitfield
= yield dec2
.dec_cr_out
.cr_bitfield
.data
556 sv_cr_out
= yield op
.sv_cr_out
557 spec
= yield dec2
.crout_svdec
.spec
558 sv_override
= yield dec2
.dec_cr_out
.sv_override
559 # get the IN1/2/3 from the decoder (includes SVP64 remap and isvec)
560 out
= yield dec2
.e
.write_cr
.data
561 o_isvec
= yield dec2
.cr_out_isvec
562 log("get_cr_out", out_sel
, CROutSel
.CR0
.value
, out
, o_isvec
)
563 log(" sv_cr_out", sv_cr_out
)
564 log(" cr_bf", out_bitfield
)
566 log(" override", sv_override
)
567 # identify which regnames map to out / o2
569 if out_sel
== CROutSel
.BF
.value
:
572 if out_sel
== CROutSel
.CR0
.value
:
574 if name
== 'CR1': # these are not actually calculated correctly
575 if out_sel
== CROutSel
.CR1
.value
:
577 # check RC1 set? if so return implicit vector, this is a REAL bad hack
578 RC1
= yield dec2
.rm_dec
.RC1
580 log("get_cr_out RC1 mode")
582 return 0, True # XXX TODO: offset CR0 from SVSTATE SPR
584 return 1, True # XXX TODO: offset CR1 from SVSTATE SPR
586 log("get_cr_out not found", name
)
590 # TODO, really should just be using PowerDecoder2
591 def get_out_map(dec2
, name
):
593 out_sel
= yield op
.out_sel
594 # get the IN1/2/3 from the decoder (includes SVP64 remap and isvec)
595 out
= yield dec2
.e
.write_reg
.data
596 # identify which regnames map to out / o2
598 if out_sel
== OutSel
.RA
.value
:
601 if out_sel
== OutSel
.RT
.value
:
603 if out_sel
== OutSel
.RT_OR_ZERO
.value
and out
!= 0:
605 elif name
== 'RT_OR_ZERO':
606 if out_sel
== OutSel
.RT_OR_ZERO
.value
:
609 if out_sel
== OutSel
.FRA
.value
:
612 if out_sel
== OutSel
.FRS
.value
:
615 if out_sel
== OutSel
.FRT
.value
:
620 # TODO, really should just be using PowerDecoder2
621 def get_idx_out(dec2
, name
, ewmode
=False):
623 out_sel
= yield op
.out_sel
624 # get the IN1/2/3 from the decoder (includes SVP64 remap and isvec)
625 out
= yield dec2
.e
.write_reg
.data
626 o_isvec
= yield dec2
.o_isvec
628 offs
= yield dec2
.e
.write_reg
.offs
629 base
= yield dec2
.e
.write_reg
.base
630 out
= (out
, base
, offs
)
631 # identify which regnames map to out / o2
632 ismap
= yield from get_out_map(dec2
, name
)
634 log("get_idx_out", name
, out_sel
, out
, o_isvec
)
636 log("get_idx_out not found", name
, out_sel
, out
, o_isvec
)
640 # TODO, really should just be using PowerDecoder2
641 def get_out2_map(dec2
, name
):
642 # check first if register is activated for write
644 out_sel
= yield op
.out_sel
645 out
= yield dec2
.e
.write_ea
.data
646 out_ok
= yield dec2
.e
.write_ea
.ok
650 if name
in ['EA', 'RA']:
651 if hasattr(op
, "upd"):
652 # update mode LD/ST uses read-reg A also as an output
654 log("get_idx_out2", upd
, LDSTMode
.update
.value
,
655 out_sel
, OutSel
.RA
.value
,
657 if upd
== LDSTMode
.update
.value
:
660 fft_en
= yield dec2
.implicit_rs
662 log("get_idx_out2", out_sel
, OutSel
.RS
.value
,
666 fft_en
= yield dec2
.implicit_rs
668 log("get_idx_out2", out_sel
, OutSel
.FRS
.value
,
674 # TODO, really should just be using PowerDecoder2
675 def get_idx_out2(dec2
, name
, ewmode
=False):
676 # check first if register is activated for write
678 out_sel
= yield op
.out_sel
679 out
= yield dec2
.e
.write_ea
.data
681 offs
= yield dec2
.e
.write_ea
.offs
682 base
= yield dec2
.e
.write_ea
.base
683 out
= (out
, base
, offs
)
684 o_isvec
= yield dec2
.o2_isvec
685 ismap
= yield from get_out2_map(dec2
, name
)
687 log("get_idx_out2", name
, out_sel
, out
, o_isvec
)
693 """deals with svstate looping.
696 def __init__(self
, svstate
):
697 self
.svstate
= svstate
700 def new_iterators(self
):
701 self
.src_it
= self
.src_iterator()
702 self
.dst_it
= self
.dst_iterator()
706 self
.new_ssubstep
= 0
707 self
.new_dsubstep
= 0
708 self
.pred_dst_zero
= 0
709 self
.pred_src_zero
= 0
711 def src_iterator(self
):
712 """source-stepping iterator
714 pack
= self
.svstate
.pack
718 # pack advances subvl in *outer* loop
719 while True: # outer subvl loop
720 while True: # inner vl loop
723 srcmask
= self
.srcmask
724 srcstep
= self
.svstate
.srcstep
725 pred_src_zero
= ((1 << srcstep
) & srcmask
) != 0
726 if self
.pred_sz
or pred_src_zero
:
727 self
.pred_src_zero
= not pred_src_zero
728 log(" advance src", srcstep
, vl
,
729 self
.svstate
.ssubstep
, subvl
)
730 # yield actual substep/srcstep
731 yield (self
.svstate
.ssubstep
, srcstep
)
732 # the way yield works these could have been modified.
735 srcstep
= self
.svstate
.srcstep
736 log(" advance src check", srcstep
, vl
,
737 self
.svstate
.ssubstep
, subvl
, srcstep
== vl
-1,
738 self
.svstate
.ssubstep
== subvl
)
739 if srcstep
== vl
-1: # end-point
740 self
.svstate
.srcstep
= SelectableInt(0, 7) # reset
741 if self
.svstate
.ssubstep
== subvl
: # end-point
742 log(" advance pack stop")
744 break # exit inner loop
745 self
.svstate
.srcstep
+= SelectableInt(1, 7) # advance ss
747 if self
.svstate
.ssubstep
== subvl
: # end-point
748 self
.svstate
.ssubstep
= SelectableInt(0, 2) # reset
749 log(" advance pack stop")
751 self
.svstate
.ssubstep
+= SelectableInt(1, 2)
754 # these cannot be done as for-loops because SVSTATE may change
755 # (srcstep/substep may be modified, interrupted, subvl/vl change)
756 # but they *can* be done as while-loops as long as every SVSTATE
757 # "thing" is re-read every single time a yield gives indices
758 while True: # outer vl loop
759 while True: # inner subvl loop
762 srcmask
= self
.srcmask
763 srcstep
= self
.svstate
.srcstep
764 pred_src_zero
= ((1 << srcstep
) & srcmask
) != 0
765 if self
.pred_sz
or pred_src_zero
:
766 self
.pred_src_zero
= not pred_src_zero
767 log(" advance src", srcstep
, vl
,
768 self
.svstate
.ssubstep
, subvl
)
769 # yield actual substep/srcstep
770 yield (self
.svstate
.ssubstep
, srcstep
)
771 if self
.svstate
.ssubstep
== subvl
: # end-point
772 self
.svstate
.ssubstep
= SelectableInt(0, 2) # reset
773 break # exit inner loop
774 self
.svstate
.ssubstep
+= SelectableInt(1, 2)
776 if srcstep
== vl
-1: # end-point
777 self
.svstate
.srcstep
= SelectableInt(0, 7) # reset
780 self
.svstate
.srcstep
+= SelectableInt(1, 7) # advance srcstep
782 def dst_iterator(self
):
783 """dest-stepping iterator
785 unpack
= self
.svstate
.unpack
789 # pack advances subvl in *outer* loop
790 while True: # outer subvl loop
791 while True: # inner vl loop
794 dstmask
= self
.dstmask
795 dststep
= self
.svstate
.dststep
796 pred_dst_zero
= ((1 << dststep
) & dstmask
) != 0
797 if self
.pred_dz
or pred_dst_zero
:
798 self
.pred_dst_zero
= not pred_dst_zero
799 log(" advance dst", dststep
, vl
,
800 self
.svstate
.dsubstep
, subvl
)
801 # yield actual substep/dststep
802 yield (self
.svstate
.dsubstep
, dststep
)
803 # the way yield works these could have been modified.
805 dststep
= self
.svstate
.dststep
806 log(" advance dst check", dststep
, vl
,
807 self
.svstate
.ssubstep
, subvl
)
808 if dststep
== vl
-1: # end-point
809 self
.svstate
.dststep
= SelectableInt(0, 7) # reset
810 if self
.svstate
.dsubstep
== subvl
: # end-point
811 log(" advance unpack stop")
814 self
.svstate
.dststep
+= SelectableInt(1, 7) # advance ds
816 if self
.svstate
.dsubstep
== subvl
: # end-point
817 self
.svstate
.dsubstep
= SelectableInt(0, 2) # reset
818 log(" advance unpack stop")
820 self
.svstate
.dsubstep
+= SelectableInt(1, 2)
822 # these cannot be done as for-loops because SVSTATE may change
823 # (dststep/substep may be modified, interrupted, subvl/vl change)
824 # but they *can* be done as while-loops as long as every SVSTATE
825 # "thing" is re-read every single time a yield gives indices
826 while True: # outer vl loop
827 while True: # inner subvl loop
829 dstmask
= self
.dstmask
830 dststep
= self
.svstate
.dststep
831 pred_dst_zero
= ((1 << dststep
) & dstmask
) != 0
832 if self
.pred_dz
or pred_dst_zero
:
833 self
.pred_dst_zero
= not pred_dst_zero
834 log(" advance dst", dststep
, self
.svstate
.vl
,
835 self
.svstate
.dsubstep
, subvl
)
836 # yield actual substep/dststep
837 yield (self
.svstate
.dsubstep
, dststep
)
838 if self
.svstate
.dsubstep
== subvl
: # end-point
839 self
.svstate
.dsubstep
= SelectableInt(0, 2) # reset
841 self
.svstate
.dsubstep
+= SelectableInt(1, 2)
844 if dststep
== vl
-1: # end-point
845 self
.svstate
.dststep
= SelectableInt(0, 7) # reset
847 self
.svstate
.dststep
+= SelectableInt(1, 7) # advance dststep
849 def src_iterate(self
):
850 """source-stepping iterator
854 pack
= self
.svstate
.pack
855 unpack
= self
.svstate
.unpack
856 ssubstep
= self
.svstate
.ssubstep
857 end_ssub
= ssubstep
== subvl
858 end_src
= self
.svstate
.srcstep
== vl
-1
859 log(" pack/unpack/subvl", pack
, unpack
, subvl
,
863 srcstep
= self
.svstate
.srcstep
864 srcmask
= self
.srcmask
866 # pack advances subvl in *outer* loop
868 assert srcstep
<= vl
-1
869 end_src
= srcstep
== vl
-1
874 self
.svstate
.ssubstep
+= SelectableInt(1, 2)
878 srcstep
+= 1 # advance srcstep
879 if not self
.srcstep_skip
:
881 if ((1 << srcstep
) & srcmask
) != 0:
884 log(" sskip", bin(srcmask
), bin(1 << srcstep
))
886 # advance subvl in *inner* loop
889 assert srcstep
<= vl
-1
890 end_src
= srcstep
== vl
-1
891 if end_src
: # end-point
897 if not self
.srcstep_skip
:
899 if ((1 << srcstep
) & srcmask
) != 0:
902 log(" sskip", bin(srcmask
), bin(1 << srcstep
))
903 self
.svstate
.ssubstep
= SelectableInt(0, 2) # reset
906 self
.svstate
.ssubstep
+= SelectableInt(1, 2)
908 self
.svstate
.srcstep
= SelectableInt(srcstep
, 7)
909 log(" advance src", self
.svstate
.srcstep
, self
.svstate
.ssubstep
,
912 def dst_iterate(self
):
913 """dest step iterator
917 pack
= self
.svstate
.pack
918 unpack
= self
.svstate
.unpack
919 dsubstep
= self
.svstate
.dsubstep
920 end_dsub
= dsubstep
== subvl
921 dststep
= self
.svstate
.dststep
922 end_dst
= dststep
== vl
-1
923 dstmask
= self
.dstmask
924 log(" pack/unpack/subvl", pack
, unpack
, subvl
,
929 # unpack advances subvl in *outer* loop
931 assert dststep
<= vl
-1
932 end_dst
= dststep
== vl
-1
937 self
.svstate
.dsubstep
+= SelectableInt(1, 2)
941 dststep
+= 1 # advance dststep
942 if not self
.dststep_skip
:
944 if ((1 << dststep
) & dstmask
) != 0:
947 log(" dskip", bin(dstmask
), bin(1 << dststep
))
949 # advance subvl in *inner* loop
952 assert dststep
<= vl
-1
953 end_dst
= dststep
== vl
-1
954 if end_dst
: # end-point
960 if not self
.dststep_skip
:
962 if ((1 << dststep
) & dstmask
) != 0:
965 log(" dskip", bin(dstmask
), bin(1 << dststep
))
966 self
.svstate
.dsubstep
= SelectableInt(0, 2) # reset
969 self
.svstate
.dsubstep
+= SelectableInt(1, 2)
971 self
.svstate
.dststep
= SelectableInt(dststep
, 7)
972 log(" advance dst", self
.svstate
.dststep
, self
.svstate
.dsubstep
,
975 def at_loopend(self
):
976 """tells if this is the last possible element. uses the cached values
977 for src/dst-step and sub-steps
981 srcstep
, dststep
= self
.new_srcstep
, self
.new_dststep
982 ssubstep
, dsubstep
= self
.new_ssubstep
, self
.new_dsubstep
983 end_ssub
= ssubstep
== subvl
984 end_dsub
= dsubstep
== subvl
985 if srcstep
== vl
-1 and end_ssub
:
987 if dststep
== vl
-1 and end_dsub
:
991 def advance_svstate_steps(self
):
992 """ advance sub/steps. note that Pack/Unpack *INVERTS* the order.
993 TODO when Pack/Unpack is set, substep becomes the *outer* loop
995 self
.subvl
= yield self
.dec2
.rm_dec
.rm_in
.subvl
996 if self
.loopend
: # huhn??
1001 def read_src_mask(self
):
1002 """read/update pred_sz and src mask
1004 # get SVSTATE VL (oh and print out some debug stuff)
1005 vl
= self
.svstate
.vl
1006 srcstep
= self
.svstate
.srcstep
1007 ssubstep
= self
.svstate
.ssubstep
1009 # get predicate mask (all 64 bits)
1010 srcmask
= 0xffff_ffff_ffff_ffff
1012 pmode
= yield self
.dec2
.rm_dec
.predmode
1013 sv_ptype
= yield self
.dec2
.dec
.op
.SV_Ptype
1014 srcpred
= yield self
.dec2
.rm_dec
.srcpred
1015 dstpred
= yield self
.dec2
.rm_dec
.dstpred
1016 pred_sz
= yield self
.dec2
.rm_dec
.pred_sz
1017 if pmode
== SVP64PredMode
.INT
.value
:
1018 srcmask
= dstmask
= get_predint(self
.gpr
, dstpred
)
1019 if sv_ptype
== SVPType
.P2
.value
:
1020 srcmask
= get_predint(self
.gpr
, srcpred
)
1021 elif pmode
== SVP64PredMode
.CR
.value
:
1022 srcmask
= dstmask
= get_predcr(self
.crl
, dstpred
, vl
)
1023 if sv_ptype
== SVPType
.P2
.value
:
1024 srcmask
= get_predcr(self
.crl
, srcpred
, vl
)
1025 # work out if the ssubsteps are completed
1026 ssubstart
= ssubstep
== 0
1027 log(" pmode", pmode
)
1028 log(" ptype", sv_ptype
)
1029 log(" srcpred", bin(srcpred
))
1030 log(" srcmask", bin(srcmask
))
1031 log(" pred_sz", bin(pred_sz
))
1032 log(" ssubstart", ssubstart
)
1034 # store all that above
1035 self
.srcstep_skip
= False
1036 self
.srcmask
= srcmask
1037 self
.pred_sz
= pred_sz
1038 self
.new_ssubstep
= ssubstep
1039 log(" new ssubstep", ssubstep
)
1040 # until the predicate mask has a "1" bit... or we run out of VL
1041 # let srcstep==VL be the indicator to move to next instruction
1043 self
.srcstep_skip
= True
1045 def read_dst_mask(self
):
1046 """same as read_src_mask - check and record everything needed
1048 # get SVSTATE VL (oh and print out some debug stuff)
1049 # yield Delay(1e-10) # make changes visible
1050 vl
= self
.svstate
.vl
1051 dststep
= self
.svstate
.dststep
1052 dsubstep
= self
.svstate
.dsubstep
1054 # get predicate mask (all 64 bits)
1055 dstmask
= 0xffff_ffff_ffff_ffff
1057 pmode
= yield self
.dec2
.rm_dec
.predmode
1058 reverse_gear
= yield self
.dec2
.rm_dec
.reverse_gear
1059 sv_ptype
= yield self
.dec2
.dec
.op
.SV_Ptype
1060 dstpred
= yield self
.dec2
.rm_dec
.dstpred
1061 pred_dz
= yield self
.dec2
.rm_dec
.pred_dz
1062 if pmode
== SVP64PredMode
.INT
.value
:
1063 dstmask
= get_predint(self
.gpr
, dstpred
)
1064 elif pmode
== SVP64PredMode
.CR
.value
:
1065 dstmask
= get_predcr(self
.crl
, dstpred
, vl
)
1066 # work out if the ssubsteps are completed
1067 dsubstart
= dsubstep
== 0
1068 log(" pmode", pmode
)
1069 log(" ptype", sv_ptype
)
1070 log(" dstpred", bin(dstpred
))
1071 log(" dstmask", bin(dstmask
))
1072 log(" pred_dz", bin(pred_dz
))
1073 log(" dsubstart", dsubstart
)
1075 self
.dststep_skip
= False
1076 self
.dstmask
= dstmask
1077 self
.pred_dz
= pred_dz
1078 self
.new_dsubstep
= dsubstep
1079 log(" new dsubstep", dsubstep
)
1081 self
.dststep_skip
= True
1083 def svstate_pre_inc(self
):
1084 """check if srcstep/dststep need to skip over masked-out predicate bits
1085 note that this is not supposed to do anything to substep,
1086 it is purely for skipping masked-out bits
1089 self
.subvl
= yield self
.dec2
.rm_dec
.rm_in
.subvl
1090 yield from self
.read_src_mask()
1091 yield from self
.read_dst_mask()
1098 srcstep
= self
.svstate
.srcstep
1099 srcmask
= self
.srcmask
1100 pred_src_zero
= self
.pred_sz
1101 vl
= self
.svstate
.vl
1102 # srcstep-skipping opportunity identified
1103 if self
.srcstep_skip
:
1104 # cannot do this with sv.bc - XXX TODO
1107 while (((1 << srcstep
) & srcmask
) == 0) and (srcstep
!= vl
):
1108 log(" sskip", bin(1 << srcstep
))
1111 # now work out if the relevant mask bits require zeroing
1113 pred_src_zero
= ((1 << srcstep
) & srcmask
) == 0
1115 # store new srcstep / dststep
1116 self
.new_srcstep
= srcstep
1117 self
.pred_src_zero
= pred_src_zero
1118 log(" new srcstep", srcstep
)
1121 # dststep-skipping opportunity identified
1122 dststep
= self
.svstate
.dststep
1123 dstmask
= self
.dstmask
1124 pred_dst_zero
= self
.pred_dz
1125 vl
= self
.svstate
.vl
1126 if self
.dststep_skip
:
1127 # cannot do this with sv.bc - XXX TODO
1130 while (((1 << dststep
) & dstmask
) == 0) and (dststep
!= vl
):
1131 log(" dskip", bin(1 << dststep
))
1134 # now work out if the relevant mask bits require zeroing
1136 pred_dst_zero
= ((1 << dststep
) & dstmask
) == 0
1138 # store new srcstep / dststep
1139 self
.new_dststep
= dststep
1140 self
.pred_dst_zero
= pred_dst_zero
1141 log(" new dststep", dststep
)
1144 class SyscallEmulator(openpower
.syscalls
.Dispatcher
):
1145 def __init__(self
, isacaller
):
1146 self
.__isacaller
= isacaller
1148 host
= os
.uname().machine
1149 bits
= (64 if (sys
.maxsize
> (2**32)) else 32)
1150 host
= openpower
.syscalls
.architecture(arch
=host
, bits
=bits
)
1152 return super().__init
__(guest
="ppc64", host
=host
)
1154 def __call__(self
, identifier
, *arguments
):
1155 (identifier
, *arguments
) = map(int, (identifier
, *arguments
))
1156 return super().__call
__(identifier
, *arguments
)
1159 class ISACaller(ISACallerHelper
, ISAFPHelpers
, StepLoop
):
1160 # decoder2 - an instance of power_decoder2
1161 # regfile - a list of initial values for the registers
1162 # initial_{etc} - initial values for SPRs, Condition Register, Mem, MSR
1163 # respect_pc - tracks the program counter. requires initial_insns
1164 def __init__(self
, decoder2
, regfile
, initial_sprs
=None, initial_cr
=0,
1165 initial_mem
=None, initial_msr
=0,
1178 use_syscall_emu
=False):
1180 self
.syscall
= SyscallEmulator(isacaller
=self
)
1181 if not use_mmap_mem
:
1182 log("forcing use_mmap_mem due to use_syscall_emu active")
1187 # trace log file for model output. if None do nothing
1188 self
.insnlog
= insnlog
1189 self
.insnlog_is_file
= hasattr(insnlog
, "write")
1190 if not self
.insnlog_is_file
and self
.insnlog
:
1191 self
.insnlog
= open(self
.insnlog
, "w")
1193 self
.bigendian
= bigendian
1195 self
.is_svp64_mode
= False
1196 self
.respect_pc
= respect_pc
1197 if initial_sprs
is None:
1199 if initial_mem
is None:
1201 if fpregfile
is None:
1202 fpregfile
= [0] * 32
1203 if initial_insns
is None:
1205 assert self
.respect_pc
== False, "instructions required to honor pc"
1206 if initial_msr
is None:
1207 initial_msr
= DEFAULT_MSR
1209 log("ISACaller insns", respect_pc
, initial_insns
, disassembly
)
1210 log("ISACaller initial_msr", initial_msr
)
1212 # "fake program counter" mode (for unit testing)
1216 if isinstance(initial_mem
, tuple):
1217 self
.fake_pc
= initial_mem
[0]
1218 disasm_start
= self
.fake_pc
1220 disasm_start
= initial_pc
1222 # disassembly: we need this for now (not given from the decoder)
1223 self
.disassembly
= {}
1225 for i
, code
in enumerate(disassembly
):
1226 self
.disassembly
[i
*4 + disasm_start
] = code
1228 # set up registers, instruction memory, data memory, PC, SPRs, MSR, CR
1229 self
.svp64rm
= SVP64RM()
1230 if initial_svstate
is None:
1232 if isinstance(initial_svstate
, int):
1233 initial_svstate
= SVP64State(initial_svstate
)
1234 # SVSTATE, MSR and PC
1235 StepLoop
.__init
__(self
, initial_svstate
)
1236 self
.msr
= SelectableInt(initial_msr
, 64) # underlying reg
1238 # GPR FPR SPR registers
1239 initial_sprs
= deepcopy(initial_sprs
) # so as not to get modified
1240 self
.gpr
= GPR(decoder2
, self
, self
.svstate
, regfile
)
1241 self
.fpr
= GPR(decoder2
, self
, self
.svstate
, fpregfile
)
1242 self
.spr
= SPR(decoder2
, initial_sprs
) # initialise SPRs before MMU
1244 # set up 4 dummy SVSHAPEs if they aren't already set up
1246 sname
= 'SVSHAPE%d' % i
1247 val
= self
.spr
.get(sname
, 0)
1248 # make sure it's an SVSHAPE
1249 self
.spr
[sname
] = SVSHAPE(val
, self
.gpr
)
1250 self
.last_op_svshape
= False
1254 self
.mem
= MemMMap(row_bytes
=8,
1255 initial_mem
=initial_mem
,
1257 self
.imem
= self
.mem
1258 self
.mem
.initialize(row_bytes
=4, initial_mem
=initial_insns
)
1259 self
.mem
.log_fancy(kind
=LogType
.InstrInOuts
)
1261 self
.mem
= Mem(row_bytes
=8, initial_mem
=initial_mem
,
1263 self
.mem
.log_fancy(kind
=LogType
.InstrInOuts
)
1264 self
.imem
= Mem(row_bytes
=4, initial_mem
=initial_insns
)
1265 # MMU mode, redirect underlying Mem through RADIX
1267 self
.mem
= RADIX(self
.mem
, self
)
1269 self
.imem
= RADIX(self
.imem
, self
)
1271 # TODO, needed here:
1272 # FPR (same as GPR except for FP nums)
1273 # 4.2.2 p124 FPSCR (definitely "separate" - not in SPR)
1274 # note that mffs, mcrfs, mtfsf "manage" this FPSCR
1275 self
.fpscr
= FPSCRState(initial_fpscr
)
1277 # 2.3.1 CR (and sub-fields CR0..CR6 - CR0 SO comes from XER.SO)
1278 # note that mfocrf, mfcr, mtcr, mtocrf, mcrxrx "manage" CRs
1280 # 2.3.2 LR (actually SPR #8) -- Done
1281 # 2.3.3 CTR (actually SPR #9) -- Done
1282 # 2.3.4 TAR (actually SPR #815)
1283 # 3.2.2 p45 XER (actually SPR #1) -- Done
1284 # 3.2.3 p46 p232 VRSAVE (actually SPR #256)
1286 # create CR then allow portions of it to be "selectable" (below)
1287 self
.cr_fields
= CRFields(initial_cr
)
1288 self
.cr
= self
.cr_fields
.cr
1289 self
.cr_backup
= 0 # sigh, dreadful hack: for fail-first (VLi)
1291 # "undefined", just set to variable-bit-width int (use exts "max")
1292 # self.undefined = SelectableInt(0, EFFECTIVELY_UNLIMITED)
1295 self
.namespace
.update(self
.spr
)
1296 self
.namespace
.update({'GPR': self
.gpr
,
1300 'memassign': self
.memassign
,
1303 'SVSTATE': self
.svstate
,
1304 'SVSHAPE0': self
.spr
['SVSHAPE0'],
1305 'SVSHAPE1': self
.spr
['SVSHAPE1'],
1306 'SVSHAPE2': self
.spr
['SVSHAPE2'],
1307 'SVSHAPE3': self
.spr
['SVSHAPE3'],
1310 'FPSCR': self
.fpscr
,
1311 'undefined': undefined
,
1312 'mode_is_64bit': True,
1313 'SO': XER_bits
['SO'],
1314 'XLEN': 64 # elwidth overrides
1317 for name
in BFP_FLAG_NAMES
:
1318 setattr(self
, name
, 0)
1320 # update pc to requested start point
1321 self
.set_pc(initial_pc
)
1323 # field-selectable versions of Condition Register
1324 self
.crl
= self
.cr_fields
.crl
1326 self
.namespace
["CR%d" % i
] = self
.crl
[i
]
1328 self
.decoder
= decoder2
.dec
1329 self
.dec2
= decoder2
1331 super().__init
__(XLEN
=self
.namespace
["XLEN"], FPSCR
=self
.fpscr
)
1333 def trace(self
, out
):
1334 if self
.insnlog
is None:
1336 self
.insnlog
.write(out
)
1340 return self
.namespace
["XLEN"]
1346 def call_trap(self
, trap_addr
, trap_bit
):
1347 """calls TRAP and sets up NIA to the new execution location.
1348 next instruction will begin at trap_addr.
1350 self
.TRAP(trap_addr
, trap_bit
)
1351 self
.namespace
['NIA'] = self
.trap_nia
1352 self
.pc
.update(self
.namespace
, self
.is_svp64_mode
)
1354 def TRAP(self
, trap_addr
=0x700, trap_bit
=PIb
.TRAP
):
1355 """TRAP> saves PC, MSR (and TODO SVSTATE), and updates MSR
1357 TRAP function is callable from inside the pseudocode itself,
1358 hence the default arguments. when calling from inside ISACaller
1359 it is best to use call_trap()
1361 trap_addr: int | SelectableInt
1362 the address to go to (before any modifications from `KAIVB`)
1363 trap_bit: int | None
1364 the bit in `SRR1` to set, `None` means don't set any bits.
1366 if isinstance(trap_addr
, SelectableInt
):
1367 trap_addr
= trap_addr
.value
1368 # https://bugs.libre-soc.org/show_bug.cgi?id=859
1369 kaivb
= self
.spr
['KAIVB'].value
1370 msr
= self
.namespace
['MSR'].value
1371 log("TRAP:", hex(trap_addr
), hex(msr
), "kaivb", hex(kaivb
))
1372 # store CIA(+4?) in SRR0, set NIA to 0x700
1373 # store MSR in SRR1, set MSR to um errr something, have to check spec
1374 # store SVSTATE (if enabled) in SVSRR0
1375 self
.spr
['SRR0'].value
= self
.pc
.CIA
.value
1376 self
.spr
['SRR1'].value
= msr
1377 if self
.is_svp64_mode
:
1378 self
.spr
['SVSRR0'] = self
.namespace
['SVSTATE'].value
1379 self
.trap_nia
= SelectableInt(trap_addr |
(kaivb
& ~
0x1fff), 64)
1380 if trap_bit
is not None:
1381 self
.spr
['SRR1'][trap_bit
] = 1 # change *copy* of MSR in SRR1
1383 # set exception bits. TODO: this should, based on the address
1384 # in figure 66 p1065 V3.0B and the table figure 65 p1063 set these
1385 # bits appropriately. however it turns out that *for now* in all
1386 # cases (all trap_addrs) the exact same thing is needed.
1387 self
.msr
[MSRb
.IR
] = 0
1388 self
.msr
[MSRb
.DR
] = 0
1389 self
.msr
[MSRb
.FE0
] = 0
1390 self
.msr
[MSRb
.FE1
] = 0
1391 self
.msr
[MSRb
.EE
] = 0
1392 self
.msr
[MSRb
.RI
] = 0
1393 self
.msr
[MSRb
.SF
] = 1
1394 self
.msr
[MSRb
.TM
] = 0
1395 self
.msr
[MSRb
.VEC
] = 0
1396 self
.msr
[MSRb
.VSX
] = 0
1397 self
.msr
[MSRb
.PR
] = 0
1398 self
.msr
[MSRb
.FP
] = 0
1399 self
.msr
[MSRb
.PMM
] = 0
1400 self
.msr
[MSRb
.TEs
] = 0
1401 self
.msr
[MSRb
.TEe
] = 0
1402 self
.msr
[MSRb
.UND
] = 0
1403 self
.msr
[MSRb
.LE
] = 1
1405 def memassign(self
, ea
, sz
, val
):
1406 self
.mem
.memassign(ea
, sz
, val
)
1408 def prep_namespace(self
, insn_name
, formname
, op_fields
, xlen
):
1409 # TODO: get field names from form in decoder*1* (not decoder2)
1410 # decoder2 is hand-created, and decoder1.sigform is auto-generated
1412 # then "yield" fields only from op_fields rather than hard-coded
1414 fields
= self
.decoder
.sigforms
[formname
]
1415 log("prep_namespace", formname
, op_fields
, insn_name
)
1416 for name
in op_fields
:
1417 # CR immediates. deal with separately. needs modifying
1419 if self
.is_svp64_mode
and name
in ['BI']: # TODO, more CRs
1420 # BI is a 5-bit, must reconstruct the value
1421 regnum
, is_vec
= yield from get_cr_in(self
.dec2
, name
)
1422 sig
= getattr(fields
, name
)
1424 # low 2 LSBs (CR field selector) remain same, CR num extended
1425 assert regnum
<= 7, "sigh, TODO, 128 CR fields"
1426 val
= (val
& 0b11) |
(regnum
<< 2)
1427 elif self
.is_svp64_mode
and name
in ['BF']: # TODO, more CRs
1428 regnum
, is_vec
= yield from get_cr_out(self
.dec2
, "BF")
1429 log('hack %s' % name
, regnum
, is_vec
)
1432 sig
= getattr(fields
, name
)
1434 # these are all opcode fields involved in index-selection of CR,
1435 # and need to do "standard" arithmetic. CR[BA+32] for example
1436 # would, if using SelectableInt, only be 5-bit.
1437 if name
in ['BF', 'BFA', 'BC', 'BA', 'BB', 'BT', 'BI']:
1438 self
.namespace
[name
] = val
1440 self
.namespace
[name
] = SelectableInt(val
, sig
.width
)
1442 self
.namespace
['XER'] = self
.spr
['XER']
1443 self
.namespace
['CA'] = self
.spr
['XER'][XER_bits
['CA']].value
1444 self
.namespace
['CA32'] = self
.spr
['XER'][XER_bits
['CA32']].value
1445 self
.namespace
['OV'] = self
.spr
['XER'][XER_bits
['OV']].value
1446 self
.namespace
['OV32'] = self
.spr
['XER'][XER_bits
['OV32']].value
1447 self
.namespace
['XLEN'] = xlen
1449 # add some SVSTATE convenience variables
1450 vl
= self
.svstate
.vl
1451 srcstep
= self
.svstate
.srcstep
1452 self
.namespace
['VL'] = vl
1453 self
.namespace
['srcstep'] = srcstep
1455 # take a copy of the CR field value: if non-VLi fail-first fails
1456 # this is because the pseudocode writes *directly* to CR. sigh
1457 self
.cr_backup
= self
.cr
.value
1459 # sv.bc* need some extra fields
1460 if self
.is_svp64_mode
and insn_name
.startswith("sv.bc"):
1461 # blegh grab bits manually
1462 mode
= yield self
.dec2
.rm_dec
.rm_in
.mode
1463 # convert to SelectableInt before test
1464 mode
= SelectableInt(mode
, 5)
1465 bc_vlset
= mode
[SVP64MODEb
.BC_VLSET
] != 0
1466 bc_vli
= mode
[SVP64MODEb
.BC_VLI
] != 0
1467 bc_snz
= mode
[SVP64MODEb
.BC_SNZ
] != 0
1468 bc_vsb
= yield self
.dec2
.rm_dec
.bc_vsb
1469 bc_lru
= yield self
.dec2
.rm_dec
.bc_lru
1470 bc_gate
= yield self
.dec2
.rm_dec
.bc_gate
1471 sz
= yield self
.dec2
.rm_dec
.pred_sz
1472 self
.namespace
['mode'] = SelectableInt(mode
, 5)
1473 self
.namespace
['ALL'] = SelectableInt(bc_gate
, 1)
1474 self
.namespace
['VSb'] = SelectableInt(bc_vsb
, 1)
1475 self
.namespace
['LRu'] = SelectableInt(bc_lru
, 1)
1476 self
.namespace
['VLSET'] = SelectableInt(bc_vlset
, 1)
1477 self
.namespace
['VLI'] = SelectableInt(bc_vli
, 1)
1478 self
.namespace
['sz'] = SelectableInt(sz
, 1)
1479 self
.namespace
['SNZ'] = SelectableInt(bc_snz
, 1)
1481 def get_kludged_op_add_ca_ov(self
, inputs
, inp_ca_ov
):
1482 """ this was not at all necessary to do. this function massively
1483 duplicates - in a laborious and complex fashion - the contents of
1484 the CSV files that were extracted two years ago from microwatt's
1485 source code. A-inversion is the "inv A" column, output inversion
1486 is the "inv out" column, carry-in equal to 0 or 1 or CA is the
1489 all of that information is available in
1490 self.instrs[ins_name].op_fields
1491 where info is usually assigned to self.instrs[ins_name]
1493 https://git.libre-soc.org/?p=openpower-isa.git;a=blob;f=openpower/isatables/minor_31.csv;hb=HEAD
1495 the immediate constants are *also* decoded correctly and placed
1496 usually by DecodeIn2Imm into operand2, as part of power_decoder2.py
1498 def ca(a
, b
, ca_in
, width
):
1499 mask
= (1 << width
) - 1
1500 y
= (a
& mask
) + (b
& mask
) + ca_in
1503 asmcode
= yield self
.dec2
.dec
.op
.asmcode
1504 insn
= insns
.get(asmcode
)
1505 SI
= yield self
.dec2
.dec
.SI
1508 inputs
= [i
.value
for i
in inputs
]
1511 if insn
in ("add", "addo", "addc", "addco"):
1515 elif insn
== "addic" or insn
== "addic.":
1519 elif insn
in ("subf", "subfo", "subfc", "subfco"):
1523 elif insn
== "subfic":
1527 elif insn
== "adde" or insn
== "addeo":
1531 elif insn
== "subfe" or insn
== "subfeo":
1535 elif insn
== "addme" or insn
== "addmeo":
1539 elif insn
== "addze" or insn
== "addzeo":
1543 elif insn
== "subfme" or insn
== "subfmeo":
1547 elif insn
== "subfze" or insn
== "subfzeo":
1551 elif insn
== "addex":
1552 # CA[32] aren't actually written, just generate so we have
1553 # something to return
1554 ca64
= ov64
= ca(inputs
[0], inputs
[1], OV
, 64)
1555 ca32
= ov32
= ca(inputs
[0], inputs
[1], OV
, 32)
1556 return ca64
, ca32
, ov64
, ov32
1557 elif insn
== "neg" or insn
== "nego":
1562 raise NotImplementedError(
1563 "op_add kludge unimplemented instruction: ", asmcode
, insn
)
1565 ca64
= ca(a
, b
, ca_in
, 64)
1566 ca32
= ca(a
, b
, ca_in
, 32)
1567 ov64
= ca64
!= ca(a
, b
, ca_in
, 63)
1568 ov32
= ca32
!= ca(a
, b
, ca_in
, 31)
1569 return ca64
, ca32
, ov64
, ov32
1571 def handle_carry_(self
, inputs
, output
, ca
, ca32
, inp_ca_ov
):
1572 if ca
is not None and ca32
is not None:
1574 op
= yield self
.dec2
.e
.do
.insn_type
1575 if op
== MicrOp
.OP_ADD
.value
and ca
is None and ca32
is None:
1576 retval
= yield from self
.get_kludged_op_add_ca_ov(
1578 ca
, ca32
, ov
, ov32
= retval
1579 asmcode
= yield self
.dec2
.dec
.op
.asmcode
1580 if insns
.get(asmcode
) == 'addex':
1581 # TODO: if 32-bit mode, set ov to ov32
1582 self
.spr
['XER'][XER_bits
['OV']] = ov
1583 self
.spr
['XER'][XER_bits
['OV32']] = ov32
1584 log(f
"write OV/OV32 OV={ov} OV32={ov32}",
1585 kind
=LogType
.InstrInOuts
)
1587 # TODO: if 32-bit mode, set ca to ca32
1588 self
.spr
['XER'][XER_bits
['CA']] = ca
1589 self
.spr
['XER'][XER_bits
['CA32']] = ca32
1590 log(f
"write CA/CA32 CA={ca} CA32={ca32}",
1591 kind
=LogType
.InstrInOuts
)
1593 inv_a
= yield self
.dec2
.e
.do
.invert_in
1595 inputs
[0] = ~inputs
[0]
1597 imm_ok
= yield self
.dec2
.e
.do
.imm_data
.ok
1599 imm
= yield self
.dec2
.e
.do
.imm_data
.data
1600 inputs
.append(SelectableInt(imm
, 64))
1603 log("gt input", x
, output
)
1604 gt
= (gtu(x
, output
))
1607 cy
= 1 if any(gts
) else 0
1609 if ca
is None: # already written
1610 self
.spr
['XER'][XER_bits
['CA']] = cy
1613 # ARGH... different for OP_ADD... *sigh*...
1614 op
= yield self
.dec2
.e
.do
.insn_type
1615 if op
== MicrOp
.OP_ADD
.value
:
1616 res32
= (output
.value
& (1 << 32)) != 0
1617 a32
= (inputs
[0].value
& (1 << 32)) != 0
1618 if len(inputs
) >= 2:
1619 b32
= (inputs
[1].value
& (1 << 32)) != 0
1622 cy32
= res32 ^ a32 ^ b32
1623 log("CA32 ADD", cy32
)
1627 log("input", x
, output
)
1628 log(" x[32:64]", x
, x
[32:64])
1629 log(" o[32:64]", output
, output
[32:64])
1630 gt
= (gtu(x
[32:64], output
[32:64])) == SelectableInt(1, 1)
1632 cy32
= 1 if any(gts
) else 0
1633 log("CA32", cy32
, gts
)
1634 if ca32
is None: # already written
1635 self
.spr
['XER'][XER_bits
['CA32']] = cy32
1637 def handle_overflow(self
, inputs
, output
, div_overflow
, inp_ca_ov
):
1638 op
= yield self
.dec2
.e
.do
.insn_type
1639 if op
== MicrOp
.OP_ADD
.value
:
1640 retval
= yield from self
.get_kludged_op_add_ca_ov(
1642 ca
, ca32
, ov
, ov32
= retval
1643 # TODO: if 32-bit mode, set ov to ov32
1644 self
.spr
['XER'][XER_bits
['OV']] = ov
1645 self
.spr
['XER'][XER_bits
['OV32']] = ov32
1646 self
.spr
['XER'][XER_bits
['SO']] |
= ov
1648 if hasattr(self
.dec2
.e
.do
, "invert_in"):
1649 inv_a
= yield self
.dec2
.e
.do
.invert_in
1651 inputs
[0] = ~inputs
[0]
1653 imm_ok
= yield self
.dec2
.e
.do
.imm_data
.ok
1655 imm
= yield self
.dec2
.e
.do
.imm_data
.data
1656 inputs
.append(SelectableInt(imm
, 64))
1657 log("handle_overflow", inputs
, output
, div_overflow
)
1658 if len(inputs
) < 2 and div_overflow
is None:
1661 # div overflow is different: it's returned by the pseudo-code
1662 # because it's more complex than can be done by analysing the output
1663 if div_overflow
is not None:
1664 ov
, ov32
= div_overflow
, div_overflow
1665 # arithmetic overflow can be done by analysing the input and output
1666 elif len(inputs
) >= 2:
1668 input_sgn
= [exts(x
.value
, x
.bits
) < 0 for x
in inputs
]
1669 output_sgn
= exts(output
.value
, output
.bits
) < 0
1670 ov
= 1 if input_sgn
[0] == input_sgn
[1] and \
1671 output_sgn
!= input_sgn
[0] else 0
1674 input32_sgn
= [exts(x
.value
, 32) < 0 for x
in inputs
]
1675 output32_sgn
= exts(output
.value
, 32) < 0
1676 ov32
= 1 if input32_sgn
[0] == input32_sgn
[1] and \
1677 output32_sgn
!= input32_sgn
[0] else 0
1679 # now update XER OV/OV32/SO
1680 so
= self
.spr
['XER'][XER_bits
['SO']]
1681 new_so
= so | ov
# sticky overflow ORs in old with new
1682 self
.spr
['XER'][XER_bits
['OV']] = ov
1683 self
.spr
['XER'][XER_bits
['OV32']] = ov32
1684 self
.spr
['XER'][XER_bits
['SO']] = new_so
1685 log(" set overflow", ov
, ov32
, so
, new_so
)
1687 def handle_comparison(self
, out
, cr_idx
=0, overflow
=None, no_so
=False):
1688 assert isinstance(out
, SelectableInt
), \
1689 "out zero not a SelectableInt %s" % repr(outputs
)
1690 log("handle_comparison", out
.bits
, hex(out
.value
))
1691 # TODO - XXX *processor* in 32-bit mode
1692 # https://bugs.libre-soc.org/show_bug.cgi?id=424
1694 # o32 = exts(out.value, 32)
1695 # print ("handle_comparison exts 32 bit", hex(o32))
1696 out
= exts(out
.value
, out
.bits
)
1697 log("handle_comparison exts", hex(out
))
1698 # create the three main CR flags, EQ GT LT
1699 zero
= SelectableInt(out
== 0, 1)
1700 positive
= SelectableInt(out
> 0, 1)
1701 negative
= SelectableInt(out
< 0, 1)
1702 # get (or not) XER.SO. for setvl this is important *not* to read SO
1704 SO
= SelectableInt(1, 0)
1706 SO
= self
.spr
['XER'][XER_bits
['SO']]
1707 log("handle_comparison SO", SO
.value
,
1708 "overflow", overflow
,
1710 "+ve", positive
.value
,
1711 "-ve", negative
.value
)
1712 # alternative overflow checking (setvl mainly at the moment)
1713 if overflow
is not None and overflow
== 1:
1714 SO
= SelectableInt(1, 1)
1715 # create the four CR field values and set the required CR field
1716 cr_field
= selectconcat(negative
, positive
, zero
, SO
)
1717 log("handle_comparison cr_field", self
.cr
, cr_idx
, cr_field
)
1718 self
.crl
[cr_idx
].eq(cr_field
)
1720 def set_pc(self
, pc_val
):
1721 self
.namespace
['NIA'] = SelectableInt(pc_val
, 64)
1722 self
.pc
.update(self
.namespace
, self
.is_svp64_mode
)
1724 def get_next_insn(self
):
1725 """check instruction
1728 pc
= self
.pc
.CIA
.value
1731 ins
= self
.imem
.ld(pc
, 4, False, True, instr_fetch
=True)
1733 raise KeyError("no instruction at 0x%x" % pc
)
1736 def setup_one(self
):
1737 """set up one instruction
1739 pc
, insn
= self
.get_next_insn()
1740 yield from self
.setup_next_insn(pc
, insn
)
1742 # cache since it's really slow to construct
1743 __PREFIX_CACHE
= SVP64Instruction
.Prefix(SelectableInt(value
=0, bits
=32))
1745 def __decode_prefix(self
, opcode
):
1746 pfx
= self
.__PREFIX
_CACHE
1747 pfx
.storage
.eq(opcode
)
1750 def setup_next_insn(self
, pc
, ins
):
1751 """set up next instruction
1754 log("setup: 0x%x 0x%x %s" % (pc
, ins
& 0xffffffff, bin(ins
)))
1755 log("CIA NIA", self
.respect_pc
, self
.pc
.CIA
.value
, self
.pc
.NIA
.value
)
1757 yield self
.dec2
.sv_rm
.eq(0)
1758 yield self
.dec2
.dec
.raw_opcode_in
.eq(ins
& 0xffffffff)
1759 yield self
.dec2
.dec
.bigendian
.eq(self
.bigendian
)
1760 yield self
.dec2
.state
.msr
.eq(self
.msr
.value
)
1761 yield self
.dec2
.state
.pc
.eq(pc
)
1762 if self
.svstate
is not None:
1763 yield self
.dec2
.state
.svstate
.eq(self
.svstate
.value
)
1765 # SVP64. first, check if the opcode is EXT001, and SVP64 id bits set
1767 opcode
= yield self
.dec2
.dec
.opcode_in
1768 opcode
= SelectableInt(value
=opcode
, bits
=32)
1769 pfx
= self
.__decode
_prefix
(opcode
)
1770 log("prefix test: opcode:", pfx
.PO
, bin(pfx
.PO
), pfx
.id)
1771 self
.is_svp64_mode
= bool((pfx
.PO
== 0b000001) and (pfx
.id == 0b11))
1772 self
.pc
.update_nia(self
.is_svp64_mode
)
1774 yield self
.dec2
.is_svp64_mode
.eq(self
.is_svp64_mode
)
1775 self
.namespace
['NIA'] = self
.pc
.NIA
1776 self
.namespace
['SVSTATE'] = self
.svstate
1777 if not self
.is_svp64_mode
:
1780 # in SVP64 mode. decode/print out svp64 prefix, get v3.0B instruction
1781 log("svp64.rm", bin(pfx
.rm
))
1782 log(" svstate.vl", self
.svstate
.vl
)
1783 log(" svstate.mvl", self
.svstate
.maxvl
)
1784 ins
= self
.imem
.ld(pc
+4, 4, False, True, instr_fetch
=True)
1785 log(" svsetup: 0x%x 0x%x %s" % (pc
+4, ins
& 0xffffffff, bin(ins
)))
1786 yield self
.dec2
.dec
.raw_opcode_in
.eq(ins
& 0xffffffff) # v3.0B suffix
1787 yield self
.dec2
.sv_rm
.eq(int(pfx
.rm
)) # svp64 prefix
1790 def execute_one(self
):
1791 """execute one instruction
1793 # get the disassembly code for this instruction
1794 if not self
.disassembly
:
1795 code
= yield from self
.get_assembly_name()
1798 if self
.is_svp64_mode
:
1799 offs
, dbg
= 4, "svp64 "
1800 code
= self
.disassembly
[self
._pc
+offs
]
1801 log(" %s sim-execute" % dbg
, hex(self
._pc
), code
)
1802 opname
= code
.split(' ')[0]
1804 yield from self
.call(opname
) # execute the instruction
1805 except MemException
as e
: # check for memory errors
1806 if e
.args
[0] == 'unaligned': # alignment error
1807 # run a Trap but set DAR first
1808 print("memory unaligned exception, DAR", e
.dar
, repr(e
))
1809 self
.spr
['DAR'] = SelectableInt(e
.dar
, 64)
1810 self
.call_trap(0x600, PIb
.PRIV
) # 0x600, privileged
1812 elif e
.args
[0] == 'invalid': # invalid
1813 # run a Trap but set DAR first
1814 log("RADIX MMU memory invalid error, mode %s" % e
.mode
)
1815 if e
.mode
== 'EXECUTE':
1816 # XXX TODO: must set a few bits in SRR1,
1817 # see microwatt loadstore1.vhdl
1818 # if m_in.segerr = '0' then
1819 # v.srr1(47 - 33) := m_in.invalid;
1820 # v.srr1(47 - 35) := m_in.perm_error; -- noexec fault
1821 # v.srr1(47 - 44) := m_in.badtree;
1822 # v.srr1(47 - 45) := m_in.rc_error;
1823 # v.intr_vec := 16#400#;
1825 # v.intr_vec := 16#480#;
1826 self
.call_trap(0x400, PIb
.PRIV
) # 0x400, privileged
1828 self
.call_trap(0x300, PIb
.PRIV
) # 0x300, privileged
1830 # not supported yet:
1831 raise e
# ... re-raise
1833 # append to the trace log file
1834 self
.trace(" # %s\n" % code
)
1836 log("gprs after code", code
)
1839 for i
in range(len(self
.crl
)):
1840 crs
.append(bin(self
.crl
[i
].asint()))
1841 log("crs", " ".join(crs
))
1842 log("vl,maxvl", self
.svstate
.vl
, self
.svstate
.maxvl
)
1844 # don't use this except in special circumstances
1845 if not self
.respect_pc
:
1848 log("execute one, CIA NIA", hex(self
.pc
.CIA
.value
),
1849 hex(self
.pc
.NIA
.value
))
1851 def get_assembly_name(self
):
1852 # TODO, asmregs is from the spec, e.g. add RT,RA,RB
1853 # see http://bugs.libre-riscv.org/show_bug.cgi?id=282
1854 dec_insn
= yield self
.dec2
.e
.do
.insn
1855 insn_1_11
= yield self
.dec2
.e
.do
.insn
[1:11]
1856 asmcode
= yield self
.dec2
.dec
.op
.asmcode
1857 int_op
= yield self
.dec2
.dec
.op
.internal_op
1858 log("get assembly name asmcode", asmcode
, int_op
,
1859 hex(dec_insn
), bin(insn_1_11
))
1860 asmop
= insns
.get(asmcode
, None)
1862 # sigh reconstruct the assembly instruction name
1863 if hasattr(self
.dec2
.e
.do
, "oe"):
1864 ov_en
= yield self
.dec2
.e
.do
.oe
.oe
1865 ov_ok
= yield self
.dec2
.e
.do
.oe
.ok
1869 if hasattr(self
.dec2
.e
.do
, "rc"):
1870 rc_en
= yield self
.dec2
.e
.do
.rc
.rc
1871 rc_ok
= yield self
.dec2
.e
.do
.rc
.ok
1875 # annoying: ignore rc_ok if RC1 is set (for creating *assembly name*)
1876 RC1
= yield self
.dec2
.rm_dec
.RC1
1880 # grrrr have to special-case MUL op (see DecodeOE)
1881 log("ov %d en %d rc %d en %d op %d" %
1882 (ov_ok
, ov_en
, rc_ok
, rc_en
, int_op
))
1883 if int_op
in [MicrOp
.OP_MUL_H64
.value
, MicrOp
.OP_MUL_H32
.value
]:
1888 if not asmop
.endswith("."): # don't add "." to "andis."
1891 if hasattr(self
.dec2
.e
.do
, "lk"):
1892 lk
= yield self
.dec2
.e
.do
.lk
1895 log("int_op", int_op
)
1896 if int_op
in [MicrOp
.OP_B
.value
, MicrOp
.OP_BC
.value
]:
1897 AA
= yield self
.dec2
.dec
.fields
.FormI
.AA
[0:-1]
1901 spr_msb
= yield from self
.get_spr_msb()
1902 if int_op
== MicrOp
.OP_MFCR
.value
:
1907 # XXX TODO: for whatever weird reason this doesn't work
1908 # https://bugs.libre-soc.org/show_bug.cgi?id=390
1909 if int_op
== MicrOp
.OP_MTCRF
.value
:
1916 def reset_remaps(self
):
1917 self
.remap_loopends
= [0] * 4
1918 self
.remap_idxs
= [0, 1, 2, 3]
1920 def get_remap_indices(self
):
1921 """WARNING, this function stores remap_idxs and remap_loopends
1922 in the class for later use. this to avoid problems with yield
1924 # go through all iterators in lock-step, advance to next remap_idx
1925 srcstep
, dststep
, ssubstep
, dsubstep
= self
.get_src_dststeps()
1926 # get four SVSHAPEs. here we are hard-coding
1928 SVSHAPE0
= self
.spr
['SVSHAPE0']
1929 SVSHAPE1
= self
.spr
['SVSHAPE1']
1930 SVSHAPE2
= self
.spr
['SVSHAPE2']
1931 SVSHAPE3
= self
.spr
['SVSHAPE3']
1932 # set up the iterators
1933 remaps
= [(SVSHAPE0
, SVSHAPE0
.get_iterator()),
1934 (SVSHAPE1
, SVSHAPE1
.get_iterator()),
1935 (SVSHAPE2
, SVSHAPE2
.get_iterator()),
1936 (SVSHAPE3
, SVSHAPE3
.get_iterator()),
1940 for i
, (shape
, remap
) in enumerate(remaps
):
1941 # zero is "disabled"
1942 if shape
.value
== 0x0:
1943 self
.remap_idxs
[i
] = 0
1944 # pick src or dststep depending on reg num (0-2=in, 3-4=out)
1945 step
= dststep
if (i
in [3, 4]) else srcstep
1946 # this is terrible. O(N^2) looking for the match. but hey.
1947 for idx
, (remap_idx
, loopends
) in enumerate(remap
):
1950 self
.remap_idxs
[i
] = remap_idx
1951 self
.remap_loopends
[i
] = loopends
1952 dbg
.append((i
, step
, remap_idx
, loopends
))
1953 for (i
, step
, remap_idx
, loopends
) in dbg
:
1954 log("SVSHAPE %d idx, end" % i
, step
, remap_idx
, bin(loopends
))
1957 def get_spr_msb(self
):
1958 dec_insn
= yield self
.dec2
.e
.do
.insn
1959 return dec_insn
& (1 << 20) != 0 # sigh - XFF.spr[-1]?
1961 def call(self
, name
, syscall_emu_active
=False):
1962 """call(opcode) - the primary execution point for instructions
1964 self
.last_st_addr
= None # reset the last known store address
1965 self
.last_ld_addr
= None # etc.
1967 ins_name
= name
.strip() # remove spaces if not already done so
1969 log("halted - not executing", ins_name
)
1972 # TODO, asmregs is from the spec, e.g. add RT,RA,RB
1973 # see http://bugs.libre-riscv.org/show_bug.cgi?id=282
1974 asmop
= yield from self
.get_assembly_name()
1975 log("call", ins_name
, asmop
,
1976 kind
=LogType
.InstrInOuts
)
1978 # sv.setvl is *not* a loop-function. sigh
1979 log("is_svp64_mode", self
.is_svp64_mode
, asmop
)
1982 int_op
= yield self
.dec2
.dec
.op
.internal_op
1983 spr_msb
= yield from self
.get_spr_msb()
1985 instr_is_privileged
= False
1986 if int_op
in [MicrOp
.OP_ATTN
.value
,
1987 MicrOp
.OP_MFMSR
.value
,
1988 MicrOp
.OP_MTMSR
.value
,
1989 MicrOp
.OP_MTMSRD
.value
,
1991 MicrOp
.OP_RFID
.value
]:
1992 instr_is_privileged
= True
1993 if int_op
in [MicrOp
.OP_MFSPR
.value
,
1994 MicrOp
.OP_MTSPR
.value
] and spr_msb
:
1995 instr_is_privileged
= True
1997 log("is priv", instr_is_privileged
, hex(self
.msr
.value
),
1999 # check MSR priv bit and whether op is privileged: if so, throw trap
2000 if instr_is_privileged
and self
.msr
[MSRb
.PR
] == 1:
2001 self
.call_trap(0x700, PIb
.PRIV
)
2004 # check halted condition
2005 if ins_name
== 'attn':
2009 # User mode system call emulation consists of several steps:
2010 # 1. Detect whether instruction is sc or scv.
2011 # 2. Call the HDL implementation which invokes trap.
2012 # 3. Reroute the guest system call to host system call.
2013 # 4. Force return from the interrupt as if we had guest OS.
2014 # "executing" rfid requires putting 0x4c000024 temporarily
2015 # into the program at the PC. TODO investigate and remove
2016 if ((asmop
in ("sc", "scv")) and
2017 (self
.syscall
is not None) and
2018 not syscall_emu_active
):
2019 # Memoize PC and trigger an interrupt
2021 pc
= self
.pc
.CIA
.value
2024 yield from self
.call(asmop
, syscall_emu_active
=True)
2026 # Reroute the syscall to host OS
2027 identifier
= self
.gpr(0)
2028 arguments
= map(self
.gpr
, range(3, 9))
2029 result
= self
.syscall(identifier
, *arguments
)
2030 self
.gpr
.write(3, result
, False, self
.namespace
["XLEN"])
2032 # Return from interrupt
2033 backup
= self
.imem
.ld(pc
, 4, False, True, instr_fetch
=True)
2034 self
.imem
.st(pc
, 0x4c000024, width
=4, swap
=True)
2035 yield from self
.call("rfid", syscall_emu_active
=True)
2036 self
.imem
.st(pc
, backup
, width
=4, swap
=True)
2037 elif ((name
in ("rfid", "hrfid")) and syscall_emu_active
):
2040 # check illegal instruction
2042 if ins_name
not in ['mtcrf', 'mtocrf']:
2043 illegal
= ins_name
!= asmop
2045 # list of instructions not being supported by binutils (.long)
2046 dotstrp
= asmop
[:-1] if asmop
[-1] == '.' else asmop
2047 if dotstrp
in [*FPTRANS_INSNS
,
2049 'ffmadds', 'fdmadds', 'ffadds',
2051 "brh", "brw", "brd",
2052 'setvl', 'svindex', 'svremap', 'svstep',
2053 'svshape', 'svshape2',
2054 'ternlogi', 'bmask', 'cprop',
2055 'absdu', 'absds', 'absdacs', 'absdacu', 'avgadd',
2056 'fmvis', 'fishmv', 'pcdec', "maddedu", "divmod2du",
2057 "dsld", "dsrd", "maddedus",
2058 "sadd", "saddw", "sadduw",
2063 "maddsubrs", "maddrs", "msubrs",
2064 "cfuged", "cntlzdm", "cnttzdm", "pdepd", "pextd",
2065 "setbc", "setbcr", "setnbc", "setnbcr",
2070 # branch-conditional redirects to sv.bc
2071 if asmop
.startswith('bc') and self
.is_svp64_mode
:
2072 ins_name
= 'sv.%s' % ins_name
2074 # ld-immediate-with-pi mode redirects to ld-with-postinc
2075 ldst_imm_postinc
= False
2076 if 'u' in ins_name
and self
.is_svp64_mode
:
2077 ldst_pi
= yield self
.dec2
.rm_dec
.ldst_postinc
2079 ins_name
= ins_name
.replace("u", "up")
2080 ldst_imm_postinc
= True
2081 log(" enable ld/st postinc", ins_name
)
2083 log(" post-processed name", dotstrp
, ins_name
, asmop
)
2085 # illegal instructions call TRAP at 0x700
2087 print("illegal", ins_name
, asmop
)
2088 self
.call_trap(0x700, PIb
.ILLEG
)
2089 print("name %s != %s - calling ILLEGAL trap, PC: %x" %
2090 (ins_name
, asmop
, self
.pc
.CIA
.value
))
2093 # this is for setvl "Vertical" mode: if set true,
2094 # srcstep/dststep is explicitly advanced. mode says which SVSTATE to
2095 # test for Rc=1 end condition. 3 bits of all 3 loops are put into CR0
2096 self
.allow_next_step_inc
= False
2097 self
.svstate_next_mode
= 0
2099 # nop has to be supported, we could let the actual op calculate
2100 # but PowerDecoder has a pattern for nop
2101 if ins_name
== 'nop':
2102 self
.update_pc_next()
2105 # get elwidths, defaults to 64
2109 if self
.is_svp64_mode
:
2110 ew_src
= yield self
.dec2
.rm_dec
.ew_src
2111 ew_dst
= yield self
.dec2
.rm_dec
.ew_dst
2112 ew_src
= 8 << (3-int(ew_src
)) # convert to bitlength
2113 ew_dst
= 8 << (3-int(ew_dst
)) # convert to bitlength
2114 xlen
= max(ew_src
, ew_dst
)
2115 log("elwdith", ew_src
, ew_dst
)
2116 log("XLEN:", self
.is_svp64_mode
, xlen
)
2118 # look up instruction in ISA.instrs, prepare namespace
2119 if ins_name
== 'pcdec': # grrrr yes there are others ("stbcx." etc.)
2120 info
= self
.instrs
[ins_name
+"."]
2121 elif asmop
[-1] == '.' and asmop
in self
.instrs
:
2122 info
= self
.instrs
[asmop
]
2124 info
= self
.instrs
[ins_name
]
2125 yield from self
.prep_namespace(ins_name
, info
.form
, info
.op_fields
,
2128 # dict retains order
2129 inputs
= dict.fromkeys(create_full_args(
2130 read_regs
=info
.read_regs
, special_regs
=info
.special_regs
,
2131 uninit_regs
=info
.uninit_regs
, write_regs
=info
.write_regs
))
2133 # preserve order of register names
2134 write_without_special_regs
= OrderedSet(info
.write_regs
)
2135 write_without_special_regs
-= OrderedSet(info
.special_regs
)
2136 input_names
= create_args([
2137 *info
.read_regs
, *info
.uninit_regs
, *write_without_special_regs
])
2138 log("input names", input_names
)
2140 # get SVP64 entry for the current instruction
2141 sv_rm
= self
.svp64rm
.instrs
.get(ins_name
)
2142 if sv_rm
is not None:
2143 dest_cr
, src_cr
, src_byname
, dest_byname
= decode_extra(sv_rm
)
2145 dest_cr
, src_cr
, src_byname
, dest_byname
= False, False, {}, {}
2146 log("sv rm", sv_rm
, dest_cr
, src_cr
, src_byname
, dest_byname
)
2148 # see if srcstep/dststep need skipping over masked-out predicate bits
2149 # svstep also needs advancement because it calls SVSTATE_NEXT.
2150 # bit the remaps get computed just after pre_inc moves them on
2151 # with remap_set_steps substituting for PowerDecider2 not doing it,
2152 # and SVSTATE_NEXT not being able to.use yield, the preinc on
2153 # svstep is necessary for now.
2155 if (self
.is_svp64_mode
or ins_name
in ['svstep']):
2156 yield from self
.svstate_pre_inc()
2157 if self
.is_svp64_mode
:
2158 pre
= yield from self
.update_new_svstate_steps()
2160 self
.svp64_reset_loop()
2162 self
.update_pc_next()
2164 srcstep
, dststep
, ssubstep
, dsubstep
= self
.get_src_dststeps()
2165 pred_dst_zero
= self
.pred_dst_zero
2166 pred_src_zero
= self
.pred_src_zero
2167 vl
= self
.svstate
.vl
2168 subvl
= yield self
.dec2
.rm_dec
.rm_in
.subvl
2170 # VL=0 in SVP64 mode means "do nothing: skip instruction"
2171 if self
.is_svp64_mode
and vl
== 0:
2172 self
.pc
.update(self
.namespace
, self
.is_svp64_mode
)
2173 log("SVP64: VL=0, end of call", self
.namespace
['CIA'],
2174 self
.namespace
['NIA'], kind
=LogType
.InstrInOuts
)
2177 # for when SVREMAP is active, using pre-arranged schedule.
2178 # note: modifying PowerDecoder2 needs to "settle"
2179 remap_en
= self
.svstate
.SVme
2180 persist
= self
.svstate
.RMpst
2181 active
= (persist
or self
.last_op_svshape
) and remap_en
!= 0
2182 if self
.is_svp64_mode
:
2183 yield self
.dec2
.remap_active
.eq(remap_en
if active
else 0)
2185 if persist
or self
.last_op_svshape
:
2186 remaps
= self
.get_remap_indices()
2187 if self
.is_svp64_mode
and (persist
or self
.last_op_svshape
):
2188 yield from self
.remap_set_steps(remaps
)
2189 # after that, settle down (combinatorial) to let Vector reg numbers
2190 # work themselves out
2192 if self
.is_svp64_mode
:
2193 remap_active
= yield self
.dec2
.remap_active
2195 remap_active
= False
2196 log("remap active", bin(remap_active
))
2198 # main input registers (RT, RA ...)
2199 for name
in input_names
:
2200 if name
== "overflow":
2201 inputs
[name
] = SelectableInt(0, 1)
2202 elif name
== "FPSCR":
2203 inputs
[name
] = self
.FPSCR
2204 elif name
in ("CA", "CA32", "OV", "OV32"):
2205 inputs
[name
] = self
.spr
['XER'][XER_bits
[name
]]
2207 inputs
[name
] = self
.crl
[0]
2208 elif name
in spr_byname
:
2209 inputs
[name
] = self
.spr
[name
]
2211 regval
= (yield from self
.get_input(name
, ew_src
))
2212 log("regval name", name
, regval
)
2213 inputs
[name
] = regval
2215 # arrrrgh, awful hack, to get _RT into namespace
2216 if ins_name
in ['setvl', 'svstep']:
2218 RT
= yield self
.dec2
.dec
.RT
2219 self
.namespace
[regname
] = SelectableInt(RT
, 5)
2221 self
.namespace
["RT"] = SelectableInt(0, 5)
2222 regnum
, is_vec
= yield from get_idx_out(self
.dec2
, "RT")
2223 log('hack input reg %s %s' % (name
, str(regnum
)), is_vec
)
2225 # in SVP64 mode for LD/ST work out immediate
2226 # XXX TODO: replace_ds for DS-Form rather than D-Form.
2227 # use info.form to detect
2228 if self
.is_svp64_mode
and not ldst_imm_postinc
:
2229 yield from self
.check_replace_d(info
, remap_active
)
2231 # "special" registers
2232 for special
in info
.special_regs
:
2233 if special
in special_sprs
:
2234 inputs
[special
] = self
.spr
[special
]
2236 inputs
[special
] = self
.namespace
[special
]
2238 # clear trap (trap) NIA
2239 self
.trap_nia
= None
2241 # check if this was an sv.bc* and create an indicator that
2242 # this is the last check to be made as a loop. combined with
2243 # the ALL/ANY mode we can early-exit
2244 if self
.is_svp64_mode
and ins_name
.startswith("sv.bc"):
2245 no_in_vec
= yield self
.dec2
.no_in_vec
# BI is scalar
2246 end_loop
= no_in_vec
or srcstep
== vl
-1 or dststep
== vl
-1
2247 self
.namespace
['end_loop'] = SelectableInt(end_loop
, 1)
2249 inp_ca_ov
= (self
.spr
['XER'][XER_bits
['CA']].value
,
2250 self
.spr
['XER'][XER_bits
['OV']].value
)
2252 for k
, v
in inputs
.items():
2254 v
= SelectableInt(0, self
.XLEN
)
2255 # prevent pseudo-code from modifying input registers
2256 v
= copy_assign_rhs(v
)
2257 if isinstance(v
, SelectableInt
):
2261 # execute actual instruction here (finally)
2262 log("inputs", inputs
)
2263 inputs
= list(inputs
.values())
2264 results
= info
.func(self
, *inputs
)
2265 output_names
= create_args(info
.write_regs
)
2267 # record .ok before anything after the pseudo-code can modify it
2269 for out
, n
in zip(results
or [], output_names
):
2272 if isinstance(out
, SelectableInt
):
2274 log("results", outs
)
2275 log("results ok", outs_ok
)
2277 # "inject" decorator takes namespace from function locals: we need to
2278 # overwrite NIA being overwritten (sigh)
2279 if self
.trap_nia
is not None:
2280 self
.namespace
['NIA'] = self
.trap_nia
2282 log("after func", self
.namespace
['CIA'], self
.namespace
['NIA'])
2284 # check if op was a LD/ST so that debugging can check the
2286 if int_op
in [MicrOp
.OP_STORE
.value
,
2288 self
.last_st_addr
= self
.mem
.last_st_addr
2289 if int_op
in [MicrOp
.OP_LOAD
.value
,
2291 self
.last_ld_addr
= self
.mem
.last_ld_addr
2292 log("op", int_op
, MicrOp
.OP_STORE
.value
, MicrOp
.OP_LOAD
.value
,
2293 self
.last_st_addr
, self
.last_ld_addr
)
2295 # detect if CA/CA32 already in outputs (sra*, basically)
2297 ca32
= outs
.get("CA32")
2299 log("carry already done?", ca
, ca32
, output_names
)
2300 # soc test_pipe_caller tests don't have output_carry
2301 has_output_carry
= hasattr(self
.dec2
.e
.do
, "output_carry")
2302 carry_en
= has_output_carry
and (yield self
.dec2
.e
.do
.output_carry
)
2304 yield from self
.handle_carry_(
2305 inputs
, results
[0], ca
, ca32
, inp_ca_ov
=inp_ca_ov
)
2307 # get output named "overflow" and "CR0"
2308 overflow
= outs
.get('overflow')
2309 cr0
= outs
.get('CR0')
2310 cr1
= outs
.get('CR1')
2312 # soc test_pipe_caller tests don't have oe
2313 has_oe
= hasattr(self
.dec2
.e
.do
, "oe")
2314 # yeah just no. not in parallel processing
2315 if has_oe
and not self
.is_svp64_mode
:
2316 # detect if overflow was in return result
2317 ov_en
= yield self
.dec2
.e
.do
.oe
.oe
2318 ov_ok
= yield self
.dec2
.e
.do
.oe
.ok
2319 log("internal overflow", ins_name
, overflow
, "en?", ov_en
, ov_ok
)
2321 yield from self
.handle_overflow(
2322 inputs
, results
[0], overflow
, inp_ca_ov
=inp_ca_ov
)
2324 # only do SVP64 dest predicated Rc=1 if dest-pred is not enabled
2326 if not self
.is_svp64_mode
or not pred_dst_zero
:
2327 if hasattr(self
.dec2
.e
.do
, "rc"):
2328 rc_en
= yield self
.dec2
.e
.do
.rc
.rc
2329 # don't do Rc=1 for svstep it is handled explicitly.
2330 # XXX TODO: now that CR0 is supported, sort out svstep's pseudocode
2331 # to write directly to CR0 instead of in ISACaller. hooyahh.
2332 if rc_en
and ins_name
not in ['svstep']:
2333 if outs_ok
.get('FPSCR', False):
2334 FPSCR
= outs
['FPSCR']
2337 yield from self
.do_rc_ov(
2338 ins_name
, results
[0], overflow
, cr0
, cr1
, FPSCR
)
2341 ffirst_hit
= False, False
2342 if self
.is_svp64_mode
:
2343 sv_mode
= yield self
.dec2
.rm_dec
.sv_mode
2344 is_cr
= sv_mode
== SVMode
.CROP
.value
2345 chk
= rc_en
or is_cr
2346 if outs_ok
.get('CR', False):
2347 # early write so check_ffirst can see value
2348 self
.namespace
['CR'].eq(outs
['CR'])
2349 ffirst_hit
= (yield from self
.check_ffirst(info
, chk
, srcstep
))
2351 # any modified return results?
2352 yield from self
.do_outregs(
2353 info
, outs
, carry_en
, ffirst_hit
, ew_dst
, outs_ok
)
2355 # check if a FP Exception occurred. TODO for DD-FFirst, check VLi
2356 # and raise the exception *after* if VLi=1 but if VLi=0 then
2357 # truncate and make the exception "disappear".
2358 if self
.FPSCR
.FEX
and (self
.msr
[MSRb
.FE0
] or self
.msr
[MSRb
.FE1
]):
2359 self
.call_trap(0x700, PIb
.FP
)
2362 yield from self
.do_nia(asmop
, ins_name
, rc_en
, ffirst_hit
)
2364 def check_ffirst(self
, info
, rc_en
, srcstep
):
2365 """fail-first mode: checks a bit of Rc Vector, truncates VL
2367 rm_mode
= yield self
.dec2
.rm_dec
.mode
2368 ff_inv
= yield self
.dec2
.rm_dec
.inv
2369 cr_bit
= yield self
.dec2
.rm_dec
.cr_sel
2370 RC1
= yield self
.dec2
.rm_dec
.RC1
2371 vli_
= yield self
.dec2
.rm_dec
.vli
# VL inclusive if truncated
2372 log(" ff rm_mode", rc_en
, rm_mode
, SVP64RMMode
.FFIRST
.value
)
2376 log(" cr_bit", cr_bit
)
2377 log(" rc_en", rc_en
)
2378 if not rc_en
or rm_mode
!= SVP64RMMode
.FFIRST
.value
:
2380 # get the CR vevtor, do BO-test
2382 log("asmregs", info
.asmregs
[0], info
.write_regs
)
2383 if 'CR' in info
.write_regs
and 'BF' in info
.asmregs
[0]:
2385 regnum
, is_vec
= yield from get_cr_out(self
.dec2
, crf
)
2386 crtest
= self
.crl
[regnum
]
2387 ffirst_hit
= crtest
[cr_bit
] != ff_inv
2388 log("cr test", crf
, regnum
, int(crtest
), crtest
, cr_bit
, ff_inv
)
2389 log("cr test?", ffirst_hit
)
2392 # Fail-first activated, truncate VL
2393 vli
= SelectableInt(int(vli_
), 7)
2394 self
.svstate
.vl
= srcstep
+ vli
2395 yield self
.dec2
.state
.svstate
.eq(self
.svstate
.value
)
2396 yield Settle() # let decoder update
2399 def do_rc_ov(self
, ins_name
, result
, overflow
, cr0
, cr1
, FPSCR
):
2400 cr_out
= yield self
.dec2
.op
.cr_out
2401 if cr_out
== CROutSel
.CR1
.value
:
2405 regnum
, is_vec
= yield from get_cr_out(self
.dec2
, rc_reg
)
2406 # hang on... for `setvl` actually you want to test SVSTATE.VL
2407 is_setvl
= ins_name
in ('svstep', 'setvl')
2409 result
= SelectableInt(result
.vl
, 64)
2411 # overflow = None # do not override overflow except in setvl
2415 cr1
= int(FPSCR
.FX
) << 3
2416 cr1 |
= int(FPSCR
.FEX
) << 2
2417 cr1 |
= int(FPSCR
.VX
) << 1
2418 cr1 |
= int(FPSCR
.OX
)
2419 log("default fp cr1", cr1
)
2421 log("explicit cr1", cr1
)
2422 self
.crl
[regnum
].eq(cr1
)
2424 # if there was not an explicit CR0 in the pseudocode,
2426 self
.handle_comparison(result
, regnum
, overflow
, no_so
=is_setvl
)
2428 # otherwise we just blat CR0 into the required regnum
2429 log("explicit rc0", cr0
)
2430 self
.crl
[regnum
].eq(cr0
)
2432 def do_outregs(self
, info
, outs
, ca_en
, ffirst_hit
, ew_dst
, outs_ok
):
2433 ffirst_hit
, vli
= ffirst_hit
2434 # write out any regs for this instruction, but only if fail-first is ok
2435 # XXX TODO: allow CR-vector to be written out even if ffirst fails
2436 if not ffirst_hit
or vli
:
2437 for name
, output
in outs
.items():
2438 if not outs_ok
[name
]:
2439 log("skipping writing output with .ok=False", name
, output
)
2441 yield from self
.check_write(info
, name
, output
, ca_en
, ew_dst
)
2442 # restore the CR value on non-VLI failfirst (from sv.cmp and others
2443 # which write directly to CR in the pseudocode (gah, what a mess)
2444 # if ffirst_hit and not vli:
2445 # self.cr.value = self.cr_backup
2447 def do_nia(self
, asmop
, ins_name
, rc_en
, ffirst_hit
):
2448 ffirst_hit
, vli
= ffirst_hit
2450 self
.svp64_reset_loop()
2453 # check advancement of src/dst/sub-steps and if PC needs updating
2454 nia_update
= (yield from self
.check_step_increment(
2455 rc_en
, asmop
, ins_name
))
2457 self
.update_pc_next()
2459 def check_replace_d(self
, info
, remap_active
):
2460 replace_d
= False # update / replace constant in pseudocode
2461 ldstmode
= yield self
.dec2
.rm_dec
.ldstmode
2462 vl
= self
.svstate
.vl
2463 subvl
= yield self
.dec2
.rm_dec
.rm_in
.subvl
2464 srcstep
, dststep
= self
.new_srcstep
, self
.new_dststep
2465 ssubstep
, dsubstep
= self
.new_ssubstep
, self
.new_dsubstep
2466 if info
.form
== 'DS':
2467 # DS-Form, multiply by 4 then knock 2 bits off after
2468 imm
= yield self
.dec2
.dec
.fields
.FormDS
.DS
[0:14] * 4
2470 imm
= yield self
.dec2
.dec
.fields
.FormD
.D
[0:16]
2471 imm
= exts(imm
, 16) # sign-extend to integer
2472 # get the right step. LD is from srcstep, ST is dststep
2473 op
= yield self
.dec2
.e
.do
.insn_type
2475 if op
== MicrOp
.OP_LOAD
.value
:
2477 offsmul
= yield self
.dec2
.in1_step
2478 log("D-field REMAP src", imm
, offsmul
, ldstmode
)
2480 offsmul
= (srcstep
* (subvl
+1)) + ssubstep
2481 log("D-field src", imm
, offsmul
, ldstmode
)
2482 elif op
== MicrOp
.OP_STORE
.value
:
2483 # XXX NOTE! no bit-reversed STORE! this should not ever be used
2484 offsmul
= (dststep
* (subvl
+1)) + dsubstep
2485 log("D-field dst", imm
, offsmul
, ldstmode
)
2486 # Unit-Strided LD/ST adds offset*width to immediate
2487 if ldstmode
== SVP64LDSTmode
.UNITSTRIDE
.value
:
2488 ldst_len
= yield self
.dec2
.e
.do
.data_len
2489 imm
= SelectableInt(imm
+ offsmul
* ldst_len
, 32)
2491 # Element-strided multiplies the immediate by element step
2492 elif ldstmode
== SVP64LDSTmode
.ELSTRIDE
.value
:
2493 imm
= SelectableInt(imm
* offsmul
, 32)
2496 ldst_ra_vec
= yield self
.dec2
.rm_dec
.ldst_ra_vec
2497 ldst_imz_in
= yield self
.dec2
.rm_dec
.ldst_imz_in
2498 log("LDSTmode", SVP64LDSTmode(ldstmode
),
2499 offsmul
, imm
, ldst_ra_vec
, ldst_imz_in
)
2500 # new replacement D... errr.. DS
2502 if info
.form
== 'DS':
2503 # TODO: assert 2 LSBs are zero?
2504 log("DS-Form, TODO, assert 2 LSBs zero?", bin(imm
.value
))
2505 imm
.value
= imm
.value
>> 2
2506 self
.namespace
['DS'] = imm
2508 self
.namespace
['D'] = imm
2510 def get_input(self
, name
, ew_src
):
2511 # using PowerDecoder2, first, find the decoder index.
2512 # (mapping name RA RB RC RS to in1, in2, in3)
2513 regnum
, is_vec
= yield from get_idx_in(self
.dec2
, name
, True)
2515 # doing this is not part of svp64, it's because output
2516 # registers, to be modified, need to be in the namespace.
2517 regnum
, is_vec
= yield from get_idx_out(self
.dec2
, name
, True)
2519 regnum
, is_vec
= yield from get_idx_out2(self
.dec2
, name
, True)
2521 if isinstance(regnum
, tuple):
2522 (regnum
, base
, offs
) = regnum
2524 base
, offs
= regnum
, 0 # temporary HACK
2526 # in case getting the register number is needed, _RA, _RB
2527 # (HACK: only in straight non-svp64-mode for now, or elwidth == 64)
2528 regname
= "_" + name
2529 if not self
.is_svp64_mode
or ew_src
== 64:
2530 self
.namespace
[regname
] = regnum
2531 elif regname
in self
.namespace
:
2532 del self
.namespace
[regname
]
2534 if not self
.is_svp64_mode
or not self
.pred_src_zero
:
2535 log('reading reg %s %s' % (name
, str(regnum
)), is_vec
)
2537 reg_val
= SelectableInt(self
.fpr(base
, is_vec
, offs
, ew_src
))
2538 log("read reg %d/%d: 0x%x" % (base
, offs
, reg_val
.value
),
2539 kind
=LogType
.InstrInOuts
)
2540 self
.trace("r:FPR:%d:%d:%d " % (base
, offs
, ew_src
))
2541 elif name
is not None:
2542 reg_val
= SelectableInt(self
.gpr(base
, is_vec
, offs
, ew_src
))
2543 self
.trace("r:GPR:%d:%d:%d " % (base
, offs
, ew_src
))
2544 log("read reg %d/%d: 0x%x" % (base
, offs
, reg_val
.value
),
2545 kind
=LogType
.InstrInOuts
)
2547 log('zero input reg %s %s' % (name
, str(regnum
)), is_vec
)
2548 reg_val
= SelectableInt(0, ew_src
)
2551 def remap_set_steps(self
, remaps
):
2552 """remap_set_steps sets up the in1/2/3 and out1/2 steps.
2553 they work in concert with PowerDecoder2 at the moment,
2554 there is no HDL implementation of REMAP. therefore this
2555 function, because ISACaller still uses PowerDecoder2,
2556 will *explicitly* write the dec2.XX_step values. this has
2559 # just some convenient debug info
2561 sname
= 'SVSHAPE%d' % i
2562 shape
= self
.spr
[sname
]
2563 log(sname
, bin(shape
.value
))
2564 log(" lims", shape
.lims
)
2565 log(" mode", shape
.mode
)
2566 log(" skip", shape
.skip
)
2568 # set up the list of steps to remap
2569 mi0
= self
.svstate
.mi0
2570 mi1
= self
.svstate
.mi1
2571 mi2
= self
.svstate
.mi2
2572 mo0
= self
.svstate
.mo0
2573 mo1
= self
.svstate
.mo1
2574 steps
= [[self
.dec2
.in1_step
, mi0
], # RA
2575 [self
.dec2
.in2_step
, mi1
], # RB
2576 [self
.dec2
.in3_step
, mi2
], # RC
2577 [self
.dec2
.o_step
, mo0
], # RT
2578 [self
.dec2
.o2_step
, mo1
], # EA
2581 rnames
= ['RA', 'RB', 'RC', 'RT', 'RS']
2582 for i
, reg
in enumerate(rnames
):
2583 idx
= yield from get_idx_map(self
.dec2
, reg
)
2585 idx
= yield from get_idx_map(self
.dec2
, "F"+reg
)
2587 steps
[i
][0] = self
.dec2
.in1_step
2589 steps
[i
][0] = self
.dec2
.in2_step
2591 steps
[i
][0] = self
.dec2
.in3_step
2592 log("remap step", i
, reg
, idx
, steps
[i
][1])
2593 remap_idxs
= self
.remap_idxs
2595 # now cross-index the required SHAPE for each of 3-in 2-out regs
2596 rnames
= ['RA', 'RB', 'RC', 'RT', 'EA']
2597 for i
, (dstep
, shape_idx
) in enumerate(steps
):
2598 (shape
, remap
) = remaps
[shape_idx
]
2599 remap_idx
= remap_idxs
[shape_idx
]
2600 # zero is "disabled"
2601 if shape
.value
== 0x0:
2603 # now set the actual requested step to the current index
2604 if dstep
is not None:
2605 yield dstep
.eq(remap_idx
)
2607 # debug printout info
2608 rremaps
.append((shape
.mode
, hex(shape
.value
), dstep
,
2609 i
, rnames
[i
], shape_idx
, remap_idx
))
2611 log("shape remap", x
)
2613 def check_write(self
, info
, name
, output
, carry_en
, ew_dst
):
2614 if name
== 'overflow': # ignore, done already (above)
2616 if name
== 'CR0': # ignore, done already (above)
2618 if isinstance(output
, int):
2619 output
= SelectableInt(output
, EFFECTIVELY_UNLIMITED
)
2621 if name
in ['FPSCR', ]:
2622 log("write FPSCR 0x%x" % (output
.value
))
2623 self
.FPSCR
.eq(output
)
2626 if name
in ['CA', 'CA32']:
2628 log("writing %s to XER" % name
, output
)
2629 log("write XER %s 0x%x" % (name
, output
.value
))
2630 self
.spr
['XER'][XER_bits
[name
]] = output
.value
2632 log("NOT writing %s to XER" % name
, output
)
2634 # write special SPRs
2635 if name
in info
.special_regs
:
2636 log('writing special %s' % name
, output
, special_sprs
)
2637 log("write reg %s 0x%x" % (name
, output
.value
),
2638 kind
=LogType
.InstrInOuts
)
2639 if name
in special_sprs
:
2640 self
.spr
[name
] = output
2642 self
.namespace
[name
].eq(output
)
2644 log('msr written', hex(self
.msr
.value
))
2646 # find out1/out2 PR/FPR
2647 regnum
, is_vec
= yield from get_idx_out(self
.dec2
, name
, True)
2649 regnum
, is_vec
= yield from get_idx_out2(self
.dec2
, name
, True)
2651 # temporary hack for not having 2nd output
2652 regnum
= yield getattr(self
.decoder
, name
)
2654 # convenient debug prefix
2659 # check zeroing due to predicate bit being zero
2660 if self
.is_svp64_mode
and self
.pred_dst_zero
:
2661 log('zeroing reg %s %s' % (str(regnum
), str(output
)), is_vec
)
2662 output
= SelectableInt(0, EFFECTIVELY_UNLIMITED
)
2663 log("write reg %s%s 0x%x ew %d" % (reg_prefix
, str(regnum
),
2664 output
.value
, ew_dst
),
2665 kind
=LogType
.InstrInOuts
)
2666 # zero-extend tov64 bit begore storing (should use EXT oh well)
2667 if output
.bits
> 64:
2668 output
= SelectableInt(output
.value
, 64)
2669 rnum
, base
, offset
= regnum
2671 self
.fpr
.write(regnum
, output
, is_vec
, ew_dst
)
2672 self
.trace("w:FPR:%d:%d:%d " % (rnum
, offset
, ew_dst
))
2674 self
.gpr
.write(regnum
, output
, is_vec
, ew_dst
)
2675 self
.trace("w:GPR:%d:%d:%d " % (rnum
, offset
, ew_dst
))
2677 def check_step_increment(self
, rc_en
, asmop
, ins_name
):
2678 # check if it is the SVSTATE.src/dest step that needs incrementing
2679 # this is our Sub-Program-Counter loop from 0 to VL-1
2680 if not self
.allow_next_step_inc
:
2681 if self
.is_svp64_mode
:
2682 return (yield from self
.svstate_post_inc(ins_name
))
2684 # XXX only in non-SVP64 mode!
2685 # record state of whether the current operation was an svshape,
2687 # to be able to know if it should apply in the next instruction.
2688 # also (if going to use this instruction) should disable ability
2689 # to interrupt in between. sigh.
2690 self
.last_op_svshape
= asmop
in ['svremap', 'svindex',
2697 log("SVSTATE_NEXT: inc requested, mode",
2698 self
.svstate_next_mode
, self
.allow_next_step_inc
)
2699 yield from self
.svstate_pre_inc()
2700 pre
= yield from self
.update_new_svstate_steps()
2702 # reset at end of loop including exit Vertical Mode
2703 log("SVSTATE_NEXT: end of loop, reset")
2704 self
.svp64_reset_loop()
2705 self
.svstate
.vfirst
= 0
2709 self
.handle_comparison(SelectableInt(0, 64)) # CR0
2711 if self
.allow_next_step_inc
== 2:
2712 log("SVSTATE_NEXT: read")
2713 nia_update
= (yield from self
.svstate_post_inc(ins_name
))
2715 log("SVSTATE_NEXT: post-inc")
2716 # use actual (cached) src/dst-step here to check end
2717 remaps
= self
.get_remap_indices()
2718 remap_idxs
= self
.remap_idxs
2719 vl
= self
.svstate
.vl
2720 subvl
= yield self
.dec2
.rm_dec
.rm_in
.subvl
2721 if self
.allow_next_step_inc
!= 2:
2722 yield from self
.advance_svstate_steps()
2723 #self.namespace['SVSTATE'] = self.svstate.spr
2724 # set CR0 (if Rc=1) based on end
2725 endtest
= 1 if self
.at_loopend() else 0
2727 #results = [SelectableInt(endtest, 64)]
2728 # self.handle_comparison(results) # CR0
2730 # see if svstep was requested, if so, which SVSTATE
2732 if self
.svstate_next_mode
> 0:
2733 shape_idx
= self
.svstate_next_mode
.value
-1
2734 endings
= self
.remap_loopends
[shape_idx
]
2735 cr_field
= SelectableInt((~endings
) << 1 | endtest
, 4)
2736 log("svstep Rc=1, CR0", cr_field
, endtest
)
2737 self
.crl
[0].eq(cr_field
) # CR0
2739 # reset at end of loop including exit Vertical Mode
2740 log("SVSTATE_NEXT: after increments, reset")
2741 self
.svp64_reset_loop()
2742 self
.svstate
.vfirst
= 0
2745 def SVSTATE_NEXT(self
, mode
, submode
):
2746 """explicitly moves srcstep/dststep on to next element, for
2747 "Vertical-First" mode. this function is called from
2748 setvl pseudo-code, as a pseudo-op "svstep"
2750 WARNING: this function uses information that was created EARLIER
2751 due to it being in the middle of a yield, but this function is
2752 *NOT* called from yield (it's called from compiled pseudocode).
2754 self
.allow_next_step_inc
= submode
.value
+ 1
2755 log("SVSTATE_NEXT mode", mode
, submode
, self
.allow_next_step_inc
)
2756 self
.svstate_next_mode
= mode
2757 if self
.svstate_next_mode
> 0 and self
.svstate_next_mode
< 5:
2758 shape_idx
= self
.svstate_next_mode
.value
-1
2759 return SelectableInt(self
.remap_idxs
[shape_idx
], 7)
2760 if self
.svstate_next_mode
== 5:
2761 self
.svstate_next_mode
= 0
2762 return SelectableInt(self
.svstate
.srcstep
, 7)
2763 if self
.svstate_next_mode
== 6:
2764 self
.svstate_next_mode
= 0
2765 return SelectableInt(self
.svstate
.dststep
, 7)
2766 if self
.svstate_next_mode
== 7:
2767 self
.svstate_next_mode
= 0
2768 return SelectableInt(self
.svstate
.ssubstep
, 7)
2769 if self
.svstate_next_mode
== 8:
2770 self
.svstate_next_mode
= 0
2771 return SelectableInt(self
.svstate
.dsubstep
, 7)
2772 return SelectableInt(0, 7)
2774 def get_src_dststeps(self
):
2775 """gets srcstep, dststep, and ssubstep, dsubstep
2777 return (self
.new_srcstep
, self
.new_dststep
,
2778 self
.new_ssubstep
, self
.new_dsubstep
)
2780 def update_svstate_namespace(self
, overwrite_svstate
=True):
2781 if overwrite_svstate
:
2782 # note, do not get the bit-reversed srcstep here!
2783 srcstep
, dststep
= self
.new_srcstep
, self
.new_dststep
2784 ssubstep
, dsubstep
= self
.new_ssubstep
, self
.new_dsubstep
2786 # update SVSTATE with new srcstep
2787 self
.svstate
.srcstep
= srcstep
2788 self
.svstate
.dststep
= dststep
2789 self
.svstate
.ssubstep
= ssubstep
2790 self
.svstate
.dsubstep
= dsubstep
2791 self
.namespace
['SVSTATE'] = self
.svstate
2792 yield self
.dec2
.state
.svstate
.eq(self
.svstate
.value
)
2793 yield Settle() # let decoder update
2795 def update_new_svstate_steps(self
, overwrite_svstate
=True):
2796 yield from self
.update_svstate_namespace(overwrite_svstate
)
2797 srcstep
= self
.svstate
.srcstep
2798 dststep
= self
.svstate
.dststep
2799 ssubstep
= self
.svstate
.ssubstep
2800 dsubstep
= self
.svstate
.dsubstep
2801 pack
= self
.svstate
.pack
2802 unpack
= self
.svstate
.unpack
2803 vl
= self
.svstate
.vl
2804 sv_mode
= yield self
.dec2
.rm_dec
.sv_mode
2805 subvl
= yield self
.dec2
.rm_dec
.rm_in
.subvl
2806 rm_mode
= yield self
.dec2
.rm_dec
.mode
2807 ff_inv
= yield self
.dec2
.rm_dec
.inv
2808 cr_bit
= yield self
.dec2
.rm_dec
.cr_sel
2809 log(" srcstep", srcstep
)
2810 log(" dststep", dststep
)
2812 log(" unpack", unpack
)
2813 log(" ssubstep", ssubstep
)
2814 log(" dsubstep", dsubstep
)
2816 log(" subvl", subvl
)
2817 log(" rm_mode", rm_mode
)
2818 log(" sv_mode", sv_mode
)
2820 log(" cr_bit", cr_bit
)
2822 # check if end reached (we let srcstep overrun, above)
2823 # nothing needs doing (TODO zeroing): just do next instruction
2826 return ((ssubstep
== subvl
and srcstep
== vl
) or
2827 (dsubstep
== subvl
and dststep
== vl
))
2829 def svstate_post_inc(self
, insn_name
, vf
=0):
2830 # check if SV "Vertical First" mode is enabled
2831 vfirst
= self
.svstate
.vfirst
2832 log(" SV Vertical First", vf
, vfirst
)
2833 if not vf
and vfirst
== 1:
2837 # check if it is the SVSTATE.src/dest step that needs incrementing
2838 # this is our Sub-Program-Counter loop from 0 to VL-1
2839 # XXX twin predication TODO
2840 vl
= self
.svstate
.vl
2841 subvl
= yield self
.dec2
.rm_dec
.rm_in
.subvl
2842 mvl
= self
.svstate
.maxvl
2843 srcstep
= self
.svstate
.srcstep
2844 dststep
= self
.svstate
.dststep
2845 ssubstep
= self
.svstate
.ssubstep
2846 dsubstep
= self
.svstate
.dsubstep
2847 pack
= self
.svstate
.pack
2848 unpack
= self
.svstate
.unpack
2849 rm_mode
= yield self
.dec2
.rm_dec
.mode
2850 reverse_gear
= yield self
.dec2
.rm_dec
.reverse_gear
2851 sv_ptype
= yield self
.dec2
.dec
.op
.SV_Ptype
2852 out_vec
= not (yield self
.dec2
.no_out_vec
)
2853 in_vec
= not (yield self
.dec2
.no_in_vec
)
2854 log(" svstate.vl", vl
)
2855 log(" svstate.mvl", mvl
)
2856 log(" rm.subvl", subvl
)
2857 log(" svstate.srcstep", srcstep
)
2858 log(" svstate.dststep", dststep
)
2859 log(" svstate.ssubstep", ssubstep
)
2860 log(" svstate.dsubstep", dsubstep
)
2861 log(" svstate.pack", pack
)
2862 log(" svstate.unpack", unpack
)
2863 log(" mode", rm_mode
)
2864 log(" reverse", reverse_gear
)
2865 log(" out_vec", out_vec
)
2866 log(" in_vec", in_vec
)
2867 log(" sv_ptype", sv_ptype
, sv_ptype
== SVPType
.P2
.value
)
2868 # check if this was an sv.bc* and if so did it succeed
2869 if self
.is_svp64_mode
and insn_name
.startswith("sv.bc"):
2870 end_loop
= self
.namespace
['end_loop']
2871 log("branch %s end_loop" % insn_name
, end_loop
)
2873 self
.svp64_reset_loop()
2874 self
.update_pc_next()
2876 # check if srcstep needs incrementing by one, stop PC advancing
2877 # but for 2-pred both src/dest have to be checked.
2878 # XXX this might not be true! it may just be LD/ST
2879 if sv_ptype
== SVPType
.P2
.value
:
2880 svp64_is_vector
= (out_vec
or in_vec
)
2882 svp64_is_vector
= out_vec
2883 # loops end at the first "hit" (source or dest)
2884 yield from self
.advance_svstate_steps()
2885 loopend
= self
.loopend
2886 log("loopend", svp64_is_vector
, loopend
)
2887 if not svp64_is_vector
or loopend
:
2888 # reset loop to zero and update NIA
2889 self
.svp64_reset_loop()
2894 # still looping, advance and update NIA
2895 self
.namespace
['SVSTATE'] = self
.svstate
2897 # not an SVP64 branch, so fix PC (NIA==CIA) for next loop
2898 # (by default, NIA is CIA+4 if v3.0B or CIA+8 if SVP64)
2899 # this way we keep repeating the same instruction (with new steps)
2900 self
.pc
.NIA
.eq(self
.pc
.CIA
)
2901 self
.namespace
['NIA'] = self
.pc
.NIA
2902 log("end of sub-pc call", self
.namespace
['CIA'], self
.namespace
['NIA'])
2903 return False # DO NOT allow PC update whilst Sub-PC loop running
2905 def update_pc_next(self
):
2906 # UPDATE program counter
2907 self
.pc
.update(self
.namespace
, self
.is_svp64_mode
)
2908 #self.svstate.spr = self.namespace['SVSTATE']
2909 log("end of call", self
.namespace
['CIA'],
2910 self
.namespace
['NIA'],
2911 self
.namespace
['SVSTATE'])
2913 def svp64_reset_loop(self
):
2914 self
.svstate
.srcstep
= 0
2915 self
.svstate
.dststep
= 0
2916 self
.svstate
.ssubstep
= 0
2917 self
.svstate
.dsubstep
= 0
2918 self
.loopend
= False
2919 log(" svstate.srcstep loop end (PC to update)")
2920 self
.namespace
['SVSTATE'] = self
.svstate
2922 def update_nia(self
):
2923 self
.pc
.update_nia(self
.is_svp64_mode
)
2924 self
.namespace
['NIA'] = self
.pc
.NIA
2928 """Decorator factory.
2930 this decorator will "inject" variables into the function's namespace,
2931 from the *dictionary* in self.namespace. it therefore becomes possible
2932 to make it look like a whole stack of variables which would otherwise
2933 need "self." inserted in front of them (*and* for those variables to be
2934 added to the instance) "appear" in the function.
2936 "self.namespace['SI']" for example becomes accessible as just "SI" but
2937 *only* inside the function, when decorated.
2939 def variable_injector(func
):
2941 def decorator(*args
, **kwargs
):
2943 func_globals
= func
.__globals
__ # Python 2.6+
2944 except AttributeError:
2945 func_globals
= func
.func_globals
# Earlier versions.
2947 context
= args
[0].namespace
# variables to be injected
2948 saved_values
= func_globals
.copy() # Shallow copy of dict.
2949 log("globals before", context
.keys())
2950 func_globals
.update(context
)
2951 result
= func(*args
, **kwargs
)
2952 log("globals after", func_globals
['CIA'], func_globals
['NIA'])
2953 log("args[0]", args
[0].namespace
['CIA'],
2954 args
[0].namespace
['NIA'],
2955 args
[0].namespace
['SVSTATE'])
2956 if 'end_loop' in func_globals
:
2957 log("args[0] end_loop", func_globals
['end_loop'])
2958 args
[0].namespace
= func_globals
2959 #exec (func.__code__, func_globals)
2962 # func_globals = saved_values # Undo changes.
2968 return variable_injector