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
17 from nmigen
.back
.pysim
import Settle
18 from functools
import wraps
19 from copy
import copy
, deepcopy
20 from openpower
.decoder
.orderedset
import OrderedSet
21 from openpower
.decoder
.selectable_int
import (FieldSelectableInt
, SelectableInt
,
23 from openpower
.decoder
.power_enums
import (spr_dict
, spr_byname
, XER_bits
,
25 In1Sel
, In2Sel
, In3Sel
,
26 OutSel
, CRInSel
, CROutSel
, LDSTMode
,
27 SVP64RMMode
, SVP64PredMode
,
28 SVP64PredInt
, SVP64PredCR
,
31 from openpower
.decoder
.power_enums
import SVPtype
33 from openpower
.decoder
.helpers
import (exts
, gtu
, ltu
, undefined
,
34 ISACallerHelper
, ISAFPHelpers
)
35 from openpower
.consts
import PIb
, MSRb
# big-endian (PowerISA versions)
36 from openpower
.consts
import (SVP64MODE
,
39 from openpower
.decoder
.power_svp64
import SVP64RM
, decode_extra
41 from openpower
.decoder
.isa
.radixmmu
import RADIX
42 from openpower
.decoder
.isa
.mem
import Mem
, swap_order
, MemException
43 from openpower
.decoder
.isa
.svshape
import SVSHAPE
44 from openpower
.decoder
.isa
.svstate
import SVP64State
47 from openpower
.util
import log
49 from collections
import namedtuple
53 instruction_info
= namedtuple('instruction_info',
54 'func read_regs uninit_regs write_regs ' +
55 'special_regs op_fields form asmregs')
66 # TODO (lkcl): adjust other registers that should be in a particular order
67 # probably CA, CA32, and CR
93 "overflow": 7, # should definitely be last
96 fregs
= ['FRA', 'FRB', 'FRC', 'FRS', 'FRT']
99 def create_args(reglist
, extra
=None):
100 retval
= list(OrderedSet(reglist
))
101 retval
.sort(key
=lambda reg
: REG_SORT_ORDER
.get(reg
, 0))
102 if extra
is not None:
103 return [extra
] + retval
108 def __init__(self
, decoder
, isacaller
, svstate
, regfile
):
111 self
.isacaller
= isacaller
112 self
.svstate
= svstate
113 for i
in range(len(regfile
)):
114 self
[i
] = SelectableInt(regfile
[i
], 64)
116 def __call__(self
, ridx
):
117 if isinstance(ridx
, SelectableInt
):
121 def set_form(self
, form
):
124 def __setitem__(self
, rnum
, value
):
125 # rnum = rnum.value # only SelectableInt allowed
126 log("GPR setitem", rnum
, value
)
127 if isinstance(rnum
, SelectableInt
):
129 dict.__setitem
__(self
, rnum
, value
)
131 def getz(self
, rnum
):
132 # rnum = rnum.value # only SelectableInt allowed
133 log("GPR getzero?", rnum
)
135 return SelectableInt(0, 64)
138 def _get_regnum(self
, attr
):
139 getform
= self
.sd
.sigforms
[self
.form
]
140 rnum
= getattr(getform
, attr
)
143 def ___getitem__(self
, attr
):
144 """ XXX currently not used
146 rnum
= self
._get
_regnum
(attr
)
147 log("GPR getitem", attr
, rnum
)
148 return self
.regfile
[rnum
]
150 def dump(self
, printout
=True):
152 for i
in range(len(self
)):
153 res
.append(self
[i
].value
)
155 for i
in range(0, len(res
), 8):
158 s
.append("%08x" % res
[i
+j
])
160 print("reg", "%2d" % i
, s
)
165 def __init__(self
, dec2
, initial_sprs
={}):
168 for key
, v
in initial_sprs
.items():
169 if isinstance(key
, SelectableInt
):
171 key
= special_sprs
.get(key
, key
)
172 if isinstance(key
, int):
175 info
= spr_byname
[key
]
176 if not isinstance(v
, SelectableInt
):
177 v
= SelectableInt(v
, info
.length
)
180 def __getitem__(self
, key
):
182 log("dict", self
.items())
183 # if key in special_sprs get the special spr, otherwise return key
184 if isinstance(key
, SelectableInt
):
186 if isinstance(key
, int):
187 key
= spr_dict
[key
].SPR
188 key
= special_sprs
.get(key
, key
)
189 if key
== 'HSRR0': # HACK!
191 if key
== 'HSRR1': # HACK!
194 res
= dict.__getitem
__(self
, key
)
196 if isinstance(key
, int):
199 info
= spr_byname
[key
]
200 dict.__setitem
__(self
, key
, SelectableInt(0, info
.length
))
201 res
= dict.__getitem
__(self
, key
)
202 log("spr returning", key
, res
)
205 def __setitem__(self
, key
, value
):
206 if isinstance(key
, SelectableInt
):
208 if isinstance(key
, int):
209 key
= spr_dict
[key
].SPR
211 key
= special_sprs
.get(key
, key
)
212 if key
== 'HSRR0': # HACK!
213 self
.__setitem
__('SRR0', value
)
214 if key
== 'HSRR1': # HACK!
215 self
.__setitem
__('SRR1', value
)
216 log("setting spr", key
, value
)
217 dict.__setitem
__(self
, key
, value
)
219 def __call__(self
, ridx
):
222 def dump(self
, printout
=True):
224 keys
= list(self
.keys())
227 sprname
= spr_dict
.get(k
, None)
231 sprname
= sprname
.SPR
232 res
.append((sprname
, self
[k
].value
))
234 for sprname
, value
in res
:
235 print(" ", sprname
, hex(value
))
240 def __init__(self
, pc_init
=0):
241 self
.CIA
= SelectableInt(pc_init
, 64)
242 self
.NIA
= self
.CIA
+ SelectableInt(4, 64) # only true for v3.0B!
244 def update_nia(self
, is_svp64
):
245 increment
= 8 if is_svp64
else 4
246 self
.NIA
= self
.CIA
+ SelectableInt(increment
, 64)
248 def update(self
, namespace
, is_svp64
):
249 """updates the program counter (PC) by 4 if v3.0B mode or 8 if SVP64
251 self
.CIA
= namespace
['NIA'].narrow(64)
252 self
.update_nia(is_svp64
)
253 namespace
['CIA'] = self
.CIA
254 namespace
['NIA'] = self
.NIA
259 def __init__(self
, init
=0):
260 self
.spr
= SelectableInt(init
, 24)
261 # SVP64 RM fields: see https://libre-soc.org/openpower/sv/svp64/
262 self
.mmode
= FieldSelectableInt(self
.spr
, [0])
263 self
.mask
= FieldSelectableInt(self
.spr
, tuple(range(1, 4)))
264 self
.elwidth
= FieldSelectableInt(self
.spr
, tuple(range(4, 6)))
265 self
.ewsrc
= FieldSelectableInt(self
.spr
, tuple(range(6, 8)))
266 self
.subvl
= FieldSelectableInt(self
.spr
, tuple(range(8, 10)))
267 self
.extra
= FieldSelectableInt(self
.spr
, tuple(range(10, 19)))
268 self
.mode
= FieldSelectableInt(self
.spr
, tuple(range(19, 24)))
269 # these cover the same extra field, split into parts as EXTRA2
270 self
.extra2
= list(range(4))
271 self
.extra2
[0] = FieldSelectableInt(self
.spr
, tuple(range(10, 12)))
272 self
.extra2
[1] = FieldSelectableInt(self
.spr
, tuple(range(12, 14)))
273 self
.extra2
[2] = FieldSelectableInt(self
.spr
, tuple(range(14, 16)))
274 self
.extra2
[3] = FieldSelectableInt(self
.spr
, tuple(range(16, 18)))
275 self
.smask
= FieldSelectableInt(self
.spr
, tuple(range(16, 19)))
276 # and here as well, but EXTRA3
277 self
.extra3
= list(range(3))
278 self
.extra3
[0] = FieldSelectableInt(self
.spr
, tuple(range(10, 13)))
279 self
.extra3
[1] = FieldSelectableInt(self
.spr
, tuple(range(13, 16)))
280 self
.extra3
[2] = FieldSelectableInt(self
.spr
, tuple(range(16, 19)))
283 SVP64RM_MMODE_SIZE
= len(SVP64RMFields().mmode
.br
)
284 SVP64RM_MASK_SIZE
= len(SVP64RMFields().mask
.br
)
285 SVP64RM_ELWIDTH_SIZE
= len(SVP64RMFields().elwidth
.br
)
286 SVP64RM_EWSRC_SIZE
= len(SVP64RMFields().ewsrc
.br
)
287 SVP64RM_SUBVL_SIZE
= len(SVP64RMFields().subvl
.br
)
288 SVP64RM_EXTRA2_SPEC_SIZE
= len(SVP64RMFields().extra2
[0].br
)
289 SVP64RM_EXTRA3_SPEC_SIZE
= len(SVP64RMFields().extra3
[0].br
)
290 SVP64RM_SMASK_SIZE
= len(SVP64RMFields().smask
.br
)
291 SVP64RM_MODE_SIZE
= len(SVP64RMFields().mode
.br
)
294 # SVP64 Prefix fields: see https://libre-soc.org/openpower/sv/svp64/
295 class SVP64PrefixFields
:
297 self
.insn
= SelectableInt(0, 32)
298 # 6 bit major opcode EXT001, 2 bits "identifying" (7, 9), 24 SV ReMap
299 self
.major
= FieldSelectableInt(self
.insn
, tuple(range(0, 6)))
300 self
.pid
= FieldSelectableInt(self
.insn
, (7, 9)) # must be 0b11
301 rmfields
= [6, 8] + list(range(10, 32)) # SVP64 24-bit RM (ReMap)
302 self
.rm
= FieldSelectableInt(self
.insn
, rmfields
)
305 SV64P_MAJOR_SIZE
= len(SVP64PrefixFields().major
.br
)
306 SV64P_PID_SIZE
= len(SVP64PrefixFields().pid
.br
)
307 SV64P_RM_SIZE
= len(SVP64PrefixFields().rm
.br
)
311 # See PowerISA Version 3.0 B Book 1
312 # Section 2.3.1 Condition Register pages 30 - 31
314 LT
= FL
= 0 # negative, less than, floating-point less than
315 GT
= FG
= 1 # positive, greater than, floating-point greater than
316 EQ
= FE
= 2 # equal, floating-point equal
317 SO
= FU
= 3 # summary overflow, floating-point unordered
319 def __init__(self
, init
=0):
320 # rev_cr = int('{:016b}'.format(initial_cr)[::-1], 2)
321 # self.cr = FieldSelectableInt(self._cr, list(range(32, 64)))
322 self
.cr
= SelectableInt(init
, 64) # underlying reg
323 # field-selectable versions of Condition Register TODO check bitranges?
326 bits
= tuple(range(i
*4+32, (i
+1)*4+32))
327 _cr
= FieldSelectableInt(self
.cr
, bits
)
330 # decode SVP64 predicate integer to reg number and invert
333 def get_predint(gpr
, mask
):
336 log("get_predint", mask
, SVP64PredInt
.ALWAYS
.value
)
337 if mask
== SVP64PredInt
.ALWAYS
.value
:
338 return 0xffff_ffff_ffff_ffff # 64 bits of 1
339 if mask
== SVP64PredInt
.R3_UNARY
.value
:
340 return 1 << (gpr(3).value
& 0b111111)
341 if mask
== SVP64PredInt
.R3
.value
:
343 if mask
== SVP64PredInt
.R3_N
.value
:
345 if mask
== SVP64PredInt
.R10
.value
:
347 if mask
== SVP64PredInt
.R10_N
.value
:
348 return ~
gpr(10).value
349 if mask
== SVP64PredInt
.R30
.value
:
351 if mask
== SVP64PredInt
.R30_N
.value
:
352 return ~
gpr(30).value
354 # decode SVP64 predicate CR to reg number and invert status
357 def _get_predcr(mask
):
358 if mask
== SVP64PredCR
.LT
.value
:
360 if mask
== SVP64PredCR
.GE
.value
:
362 if mask
== SVP64PredCR
.GT
.value
:
364 if mask
== SVP64PredCR
.LE
.value
:
366 if mask
== SVP64PredCR
.EQ
.value
:
368 if mask
== SVP64PredCR
.NE
.value
:
370 if mask
== SVP64PredCR
.SO
.value
:
372 if mask
== SVP64PredCR
.NS
.value
:
375 # read individual CR fields (0..VL-1), extract the required bit
376 # and construct the mask
379 def get_predcr(crl
, mask
, vl
):
380 idx
, noninv
= _get_predcr(mask
)
383 cr
= crl
[i
+SVP64CROffs
.CRPred
]
384 if cr
[idx
].value
== noninv
:
389 # TODO, really should just be using PowerDecoder2
390 def get_pdecode_idx_in(dec2
, name
):
392 in1_sel
= yield op
.in1_sel
393 in2_sel
= yield op
.in2_sel
394 in3_sel
= yield op
.in3_sel
395 # get the IN1/2/3 from the decoder (includes SVP64 remap and isvec)
396 in1
= yield dec2
.e
.read_reg1
.data
397 in2
= yield dec2
.e
.read_reg2
.data
398 in3
= yield dec2
.e
.read_reg3
.data
399 in1_isvec
= yield dec2
.in1_isvec
400 in2_isvec
= yield dec2
.in2_isvec
401 in3_isvec
= yield dec2
.in3_isvec
402 log("get_pdecode_idx_in in1", name
, in1_sel
, In1Sel
.RA
.value
,
404 log("get_pdecode_idx_in in2", name
, in2_sel
, In2Sel
.RB
.value
,
406 log("get_pdecode_idx_in in3", name
, in3_sel
, In3Sel
.RS
.value
,
408 log("get_pdecode_idx_in FRS in3", name
, in3_sel
, In3Sel
.FRS
.value
,
410 log("get_pdecode_idx_in FRB in2", name
, in2_sel
, In2Sel
.FRB
.value
,
412 log("get_pdecode_idx_in FRC in3", name
, in3_sel
, In3Sel
.FRC
.value
,
414 # identify which regnames map to in1/2/3
416 if (in1_sel
== In1Sel
.RA
.value
or
417 (in1_sel
== In1Sel
.RA_OR_ZERO
.value
and in1
!= 0)):
418 return in1
, in1_isvec
419 if in1_sel
== In1Sel
.RA_OR_ZERO
.value
:
420 return in1
, in1_isvec
422 if in2_sel
== In2Sel
.RB
.value
:
423 return in2
, in2_isvec
424 if in3_sel
== In3Sel
.RB
.value
:
425 return in3
, in3_isvec
426 # XXX TODO, RC doesn't exist yet!
428 assert False, "RC does not exist yet"
430 if in1_sel
== In1Sel
.RS
.value
:
431 return in1
, in1_isvec
432 if in2_sel
== In2Sel
.RS
.value
:
433 return in2
, in2_isvec
434 if in3_sel
== In3Sel
.RS
.value
:
435 return in3
, in3_isvec
437 if in1_sel
== In1Sel
.FRA
.value
:
438 return in1
, in1_isvec
440 if in2_sel
== In2Sel
.FRB
.value
:
441 return in2
, in2_isvec
443 if in3_sel
== In3Sel
.FRC
.value
:
444 return in3
, in3_isvec
446 if in1_sel
== In1Sel
.FRS
.value
:
447 return in1
, in1_isvec
448 if in3_sel
== In3Sel
.FRS
.value
:
449 return in3
, in3_isvec
453 # TODO, really should just be using PowerDecoder2
454 def get_pdecode_cr_in(dec2
, name
):
456 in_sel
= yield op
.cr_in
457 in_bitfield
= yield dec2
.dec_cr_in
.cr_bitfield
.data
458 sv_cr_in
= yield op
.sv_cr_in
459 spec
= yield dec2
.crin_svdec
.spec
460 sv_override
= yield dec2
.dec_cr_in
.sv_override
461 # get the IN1/2/3 from the decoder (includes SVP64 remap and isvec)
462 in1
= yield dec2
.e
.read_cr1
.data
463 cr_isvec
= yield dec2
.cr_in_isvec
464 log("get_pdecode_cr_in", in_sel
, CROutSel
.CR0
.value
, in1
, cr_isvec
)
465 log(" sv_cr_in", sv_cr_in
)
466 log(" cr_bf", in_bitfield
)
468 log(" override", sv_override
)
469 # identify which regnames map to in / o2
471 if in_sel
== CRInSel
.BI
.value
:
473 log("get_pdecode_cr_in not found", name
)
477 # TODO, really should just be using PowerDecoder2
478 def get_pdecode_cr_out(dec2
, name
):
480 out_sel
= yield op
.cr_out
481 out_bitfield
= yield dec2
.dec_cr_out
.cr_bitfield
.data
482 sv_cr_out
= yield op
.sv_cr_out
483 spec
= yield dec2
.crout_svdec
.spec
484 sv_override
= yield dec2
.dec_cr_out
.sv_override
485 # get the IN1/2/3 from the decoder (includes SVP64 remap and isvec)
486 out
= yield dec2
.e
.write_cr
.data
487 o_isvec
= yield dec2
.o_isvec
488 log("get_pdecode_cr_out", out_sel
, CROutSel
.CR0
.value
, out
, o_isvec
)
489 log(" sv_cr_out", sv_cr_out
)
490 log(" cr_bf", out_bitfield
)
492 log(" override", sv_override
)
493 # identify which regnames map to out / o2
495 if out_sel
== CROutSel
.CR0
.value
:
497 log("get_pdecode_cr_out not found", name
)
501 # TODO, really should just be using PowerDecoder2
502 def get_pdecode_idx_out(dec2
, name
):
504 out_sel
= yield op
.out_sel
505 # get the IN1/2/3 from the decoder (includes SVP64 remap and isvec)
506 out
= yield dec2
.e
.write_reg
.data
507 o_isvec
= yield dec2
.o_isvec
508 # identify which regnames map to out / o2
510 log("get_pdecode_idx_out", out_sel
, OutSel
.RA
.value
, out
, o_isvec
)
511 if out_sel
== OutSel
.RA
.value
:
514 log("get_pdecode_idx_out", out_sel
, OutSel
.RT
.value
,
515 OutSel
.RT_OR_ZERO
.value
, out
, o_isvec
,
517 if out_sel
== OutSel
.RT
.value
:
519 elif name
== 'RT_OR_ZERO':
520 log("get_pdecode_idx_out", out_sel
, OutSel
.RT
.value
,
521 OutSel
.RT_OR_ZERO
.value
, out
, o_isvec
,
523 if out_sel
== OutSel
.RT_OR_ZERO
.value
:
526 log("get_pdecode_idx_out", out_sel
, OutSel
.FRA
.value
, out
, o_isvec
)
527 if out_sel
== OutSel
.FRA
.value
:
530 log("get_pdecode_idx_out", out_sel
, OutSel
.FRT
.value
,
531 OutSel
.FRT
.value
, out
, o_isvec
)
532 if out_sel
== OutSel
.FRT
.value
:
534 log("get_pdecode_idx_out not found", name
, out_sel
, out
, o_isvec
)
538 # TODO, really should just be using PowerDecoder2
539 def get_pdecode_idx_out2(dec2
, name
):
540 # check first if register is activated for write
542 out_sel
= yield op
.out_sel
543 out
= yield dec2
.e
.write_ea
.data
544 o_isvec
= yield dec2
.o2_isvec
545 out_ok
= yield dec2
.e
.write_ea
.ok
546 log("get_pdecode_idx_out2", name
, out_sel
, out
, out_ok
, o_isvec
)
551 if hasattr(op
, "upd"):
552 # update mode LD/ST uses read-reg A also as an output
554 log("get_pdecode_idx_out2", upd
, LDSTMode
.update
.value
,
555 out_sel
, OutSel
.RA
.value
,
557 if upd
== LDSTMode
.update
.value
:
560 int_op
= yield dec2
.dec
.op
.internal_op
561 fft_en
= yield dec2
.use_svp64_fft
562 # if int_op == MicrOp.OP_FP_MADD.value and fft_en:
564 log("get_pdecode_idx_out2", out_sel
, OutSel
.FRS
.value
,
570 class ISACaller(ISACallerHelper
, ISAFPHelpers
):
571 # decoder2 - an instance of power_decoder2
572 # regfile - a list of initial values for the registers
573 # initial_{etc} - initial values for SPRs, Condition Register, Mem, MSR
574 # respect_pc - tracks the program counter. requires initial_insns
575 def __init__(self
, decoder2
, regfile
, initial_sprs
=None, initial_cr
=0,
576 initial_mem
=None, initial_msr
=0,
587 self
.bigendian
= bigendian
589 self
.is_svp64_mode
= False
590 self
.respect_pc
= respect_pc
591 if initial_sprs
is None:
593 if initial_mem
is None:
595 if fpregfile
is None:
597 if initial_insns
is None:
599 assert self
.respect_pc
== False, "instructions required to honor pc"
601 log("ISACaller insns", respect_pc
, initial_insns
, disassembly
)
602 log("ISACaller initial_msr", initial_msr
)
604 # "fake program counter" mode (for unit testing)
608 if isinstance(initial_mem
, tuple):
609 self
.fake_pc
= initial_mem
[0]
610 disasm_start
= self
.fake_pc
612 disasm_start
= initial_pc
614 # disassembly: we need this for now (not given from the decoder)
615 self
.disassembly
= {}
617 for i
, code
in enumerate(disassembly
):
618 self
.disassembly
[i
*4 + disasm_start
] = code
620 # set up registers, instruction memory, data memory, PC, SPRs, MSR, CR
621 self
.svp64rm
= SVP64RM()
622 if initial_svstate
is None:
624 if isinstance(initial_svstate
, int):
625 initial_svstate
= SVP64State(initial_svstate
)
626 # SVSTATE, MSR and PC
627 self
.svstate
= initial_svstate
628 self
.msr
= SelectableInt(initial_msr
, 64) # underlying reg
630 # GPR FPR SPR registers
631 initial_sprs
= deepcopy(initial_sprs
) # so as not to get modified
632 self
.gpr
= GPR(decoder2
, self
, self
.svstate
, regfile
)
633 self
.fpr
= GPR(decoder2
, self
, self
.svstate
, fpregfile
)
634 self
.spr
= SPR(decoder2
, initial_sprs
) # initialise SPRs before MMU
636 # set up 4 dummy SVSHAPEs if they aren't already set up
638 sname
= 'SVSHAPE%d' % i
639 if sname
not in self
.spr
:
640 self
.spr
[sname
] = SVSHAPE(0)
642 # make sure it's an SVSHAPE
643 val
= self
.spr
[sname
].value
644 self
.spr
[sname
] = SVSHAPE(val
)
645 self
.last_op_svshape
= False
648 self
.mem
= Mem(row_bytes
=8, initial_mem
=initial_mem
)
649 self
.imem
= Mem(row_bytes
=4, initial_mem
=initial_insns
)
650 # MMU mode, redirect underlying Mem through RADIX
652 self
.mem
= RADIX(self
.mem
, self
)
654 self
.imem
= RADIX(self
.imem
, self
)
657 # FPR (same as GPR except for FP nums)
658 # 4.2.2 p124 FPSCR (definitely "separate" - not in SPR)
659 # note that mffs, mcrfs, mtfsf "manage" this FPSCR
660 # 2.3.1 CR (and sub-fields CR0..CR6 - CR0 SO comes from XER.SO)
661 # note that mfocrf, mfcr, mtcr, mtocrf, mcrxrx "manage" CRs
663 # 2.3.2 LR (actually SPR #8) -- Done
664 # 2.3.3 CTR (actually SPR #9) -- Done
665 # 2.3.4 TAR (actually SPR #815)
666 # 3.2.2 p45 XER (actually SPR #1) -- Done
667 # 3.2.3 p46 p232 VRSAVE (actually SPR #256)
669 # create CR then allow portions of it to be "selectable" (below)
670 self
.cr_fields
= CRFields(initial_cr
)
671 self
.cr
= self
.cr_fields
.cr
673 # "undefined", just set to variable-bit-width int (use exts "max")
674 # self.undefined = SelectableInt(0, 256) # TODO, not hard-code 256!
677 self
.namespace
.update(self
.spr
)
678 self
.namespace
.update({'GPR': self
.gpr
,
682 'memassign': self
.memassign
,
685 'SVSTATE': self
.svstate
,
686 'SVSHAPE0': self
.spr
['SVSHAPE0'],
687 'SVSHAPE1': self
.spr
['SVSHAPE1'],
688 'SVSHAPE2': self
.spr
['SVSHAPE2'],
689 'SVSHAPE3': self
.spr
['SVSHAPE3'],
692 'undefined': undefined
,
693 'mode_is_64bit': True,
694 'SO': XER_bits
['SO'],
695 'XLEN': 64 # elwidth overrides, later
698 # update pc to requested start point
699 self
.set_pc(initial_pc
)
701 # field-selectable versions of Condition Register
702 self
.crl
= self
.cr_fields
.crl
704 self
.namespace
["CR%d" % i
] = self
.crl
[i
]
706 self
.decoder
= decoder2
.dec
709 super().__init
__(XLEN
=self
.namespace
["XLEN"])
713 return self
.namespace
["XLEN"]
715 def call_trap(self
, trap_addr
, trap_bit
):
716 """calls TRAP and sets up NIA to the new execution location.
717 next instruction will begin at trap_addr.
719 self
.TRAP(trap_addr
, trap_bit
)
720 self
.namespace
['NIA'] = self
.trap_nia
721 self
.pc
.update(self
.namespace
, self
.is_svp64_mode
)
723 def TRAP(self
, trap_addr
=0x700, trap_bit
=PIb
.TRAP
):
724 """TRAP> saves PC, MSR (and TODO SVSTATE), and updates MSR
726 TRAP function is callable from inside the pseudocode itself,
727 hence the default arguments. when calling from inside ISACaller
728 it is best to use call_trap()
730 log("TRAP:", hex(trap_addr
), hex(self
.namespace
['MSR'].value
))
731 # store CIA(+4?) in SRR0, set NIA to 0x700
732 # store MSR in SRR1, set MSR to um errr something, have to check spec
733 # store SVSTATE (if enabled) in SVSRR0
734 self
.spr
['SRR0'].value
= self
.pc
.CIA
.value
735 self
.spr
['SRR1'].value
= self
.namespace
['MSR'].value
736 if self
.is_svp64_mode
:
737 self
.spr
['SVSRR0'] = self
.namespace
['SVSTATE'].value
738 self
.trap_nia
= SelectableInt(trap_addr
, 64)
739 self
.spr
['SRR1'][trap_bit
] = 1 # change *copy* of MSR in SRR1
741 # set exception bits. TODO: this should, based on the address
742 # in figure 66 p1065 V3.0B and the table figure 65 p1063 set these
743 # bits appropriately. however it turns out that *for now* in all
744 # cases (all trap_addrs) the exact same thing is needed.
745 self
.msr
[MSRb
.IR
] = 0
746 self
.msr
[MSRb
.DR
] = 0
747 self
.msr
[MSRb
.FE0
] = 0
748 self
.msr
[MSRb
.FE1
] = 0
749 self
.msr
[MSRb
.EE
] = 0
750 self
.msr
[MSRb
.RI
] = 0
751 self
.msr
[MSRb
.SF
] = 1
752 self
.msr
[MSRb
.TM
] = 0
753 self
.msr
[MSRb
.VEC
] = 0
754 self
.msr
[MSRb
.VSX
] = 0
755 self
.msr
[MSRb
.PR
] = 0
756 self
.msr
[MSRb
.FP
] = 0
757 self
.msr
[MSRb
.PMM
] = 0
758 self
.msr
[MSRb
.TEs
] = 0
759 self
.msr
[MSRb
.TEe
] = 0
760 self
.msr
[MSRb
.UND
] = 0
761 self
.msr
[MSRb
.LE
] = 1
763 def memassign(self
, ea
, sz
, val
):
764 self
.mem
.memassign(ea
, sz
, val
)
766 def prep_namespace(self
, insn_name
, formname
, op_fields
):
767 # TODO: get field names from form in decoder*1* (not decoder2)
768 # decoder2 is hand-created, and decoder1.sigform is auto-generated
770 # then "yield" fields only from op_fields rather than hard-coded
772 fields
= self
.decoder
.sigforms
[formname
]
773 log("prep_namespace", formname
, op_fields
)
774 for name
in op_fields
:
775 # CR immediates. deal with separately. needs modifying
777 if self
.is_svp64_mode
and name
in ['BI']: # TODO, more CRs
778 # BI is a 5-bit, must reconstruct the value
779 regnum
, is_vec
= yield from get_pdecode_cr_in(self
.dec2
, name
)
780 sig
= getattr(fields
, name
)
782 # low 2 LSBs (CR field selector) remain same, CR num extended
783 assert regnum
<= 7, "sigh, TODO, 128 CR fields"
784 val
= (val
& 0b11) |
(regnum
<< 2)
787 sig
= getattr(fields
, name
.upper())
789 sig
= getattr(fields
, name
)
791 # these are all opcode fields involved in index-selection of CR,
792 # and need to do "standard" arithmetic. CR[BA+32] for example
793 # would, if using SelectableInt, only be 5-bit.
794 if name
in ['BF', 'BFA', 'BC', 'BA', 'BB', 'BT', 'BI']:
795 self
.namespace
[name
] = val
797 self
.namespace
[name
] = SelectableInt(val
, sig
.width
)
799 self
.namespace
['XER'] = self
.spr
['XER']
800 self
.namespace
['CA'] = self
.spr
['XER'][XER_bits
['CA']].value
801 self
.namespace
['CA32'] = self
.spr
['XER'][XER_bits
['CA32']].value
803 # add some SVSTATE convenience variables
805 srcstep
= self
.svstate
.srcstep
806 self
.namespace
['VL'] = vl
807 self
.namespace
['srcstep'] = srcstep
809 # sv.bc* need some extra fields
810 if self
.is_svp64_mode
and insn_name
.startswith("sv.bc"):
811 # blegh grab bits manually
812 mode
= yield self
.dec2
.rm_dec
.rm_in
.mode
813 bc_vlset
= (mode
& SVP64MODE
.BC_VLSET
) != 0
814 bc_vli
= (mode
& SVP64MODE
.BC_VLI
) != 0
815 bc_snz
= (mode
& SVP64MODE
.BC_SNZ
) != 0
816 bc_vsb
= yield self
.dec2
.rm_dec
.bc_vsb
817 bc_lru
= yield self
.dec2
.rm_dec
.bc_lru
818 bc_gate
= yield self
.dec2
.rm_dec
.bc_gate
819 sz
= yield self
.dec2
.rm_dec
.pred_sz
820 self
.namespace
['ALL'] = SelectableInt(bc_gate
, 1)
821 self
.namespace
['VSb'] = SelectableInt(bc_vsb
, 1)
822 self
.namespace
['LRu'] = SelectableInt(bc_lru
, 1)
823 self
.namespace
['VLSET'] = SelectableInt(bc_vlset
, 1)
824 self
.namespace
['VLI'] = SelectableInt(bc_vli
, 1)
825 self
.namespace
['sz'] = SelectableInt(sz
, 1)
826 self
.namespace
['SNZ'] = SelectableInt(bc_snz
, 1)
828 def handle_carry_(self
, inputs
, outputs
, already_done
):
829 inv_a
= yield self
.dec2
.e
.do
.invert_in
831 inputs
[0] = ~inputs
[0]
833 imm_ok
= yield self
.dec2
.e
.do
.imm_data
.ok
835 imm
= yield self
.dec2
.e
.do
.imm_data
.data
836 inputs
.append(SelectableInt(imm
, 64))
837 assert len(outputs
) >= 1
838 log("outputs", repr(outputs
))
839 if isinstance(outputs
, list) or isinstance(outputs
, tuple):
845 log("gt input", x
, output
)
846 gt
= (gtu(x
, output
))
849 cy
= 1 if any(gts
) else 0
851 if not (1 & already_done
):
852 self
.spr
['XER'][XER_bits
['CA']] = cy
854 log("inputs", already_done
, inputs
)
856 # ARGH... different for OP_ADD... *sigh*...
857 op
= yield self
.dec2
.e
.do
.insn_type
858 if op
== MicrOp
.OP_ADD
.value
:
859 res32
= (output
.value
& (1 << 32)) != 0
860 a32
= (inputs
[0].value
& (1 << 32)) != 0
862 b32
= (inputs
[1].value
& (1 << 32)) != 0
865 cy32
= res32 ^ a32 ^ b32
866 log("CA32 ADD", cy32
)
870 log("input", x
, output
)
871 log(" x[32:64]", x
, x
[32:64])
872 log(" o[32:64]", output
, output
[32:64])
873 gt
= (gtu(x
[32:64], output
[32:64])) == SelectableInt(1, 1)
875 cy32
= 1 if any(gts
) else 0
876 log("CA32", cy32
, gts
)
877 if not (2 & already_done
):
878 self
.spr
['XER'][XER_bits
['CA32']] = cy32
880 def handle_overflow(self
, inputs
, outputs
, div_overflow
):
881 if hasattr(self
.dec2
.e
.do
, "invert_in"):
882 inv_a
= yield self
.dec2
.e
.do
.invert_in
884 inputs
[0] = ~inputs
[0]
886 imm_ok
= yield self
.dec2
.e
.do
.imm_data
.ok
888 imm
= yield self
.dec2
.e
.do
.imm_data
.data
889 inputs
.append(SelectableInt(imm
, 64))
890 assert len(outputs
) >= 1
891 log("handle_overflow", inputs
, outputs
, div_overflow
)
892 if len(inputs
) < 2 and div_overflow
is None:
895 # div overflow is different: it's returned by the pseudo-code
896 # because it's more complex than can be done by analysing the output
897 if div_overflow
is not None:
898 ov
, ov32
= div_overflow
, div_overflow
899 # arithmetic overflow can be done by analysing the input and output
900 elif len(inputs
) >= 2:
904 input_sgn
= [exts(x
.value
, x
.bits
) < 0 for x
in inputs
]
905 output_sgn
= exts(output
.value
, output
.bits
) < 0
906 ov
= 1 if input_sgn
[0] == input_sgn
[1] and \
907 output_sgn
!= input_sgn
[0] else 0
910 input32_sgn
= [exts(x
.value
, 32) < 0 for x
in inputs
]
911 output32_sgn
= exts(output
.value
, 32) < 0
912 ov32
= 1 if input32_sgn
[0] == input32_sgn
[1] and \
913 output32_sgn
!= input32_sgn
[0] else 0
915 self
.spr
['XER'][XER_bits
['OV']] = ov
916 self
.spr
['XER'][XER_bits
['OV32']] = ov32
917 so
= self
.spr
['XER'][XER_bits
['SO']]
919 self
.spr
['XER'][XER_bits
['SO']] = so
921 def handle_comparison(self
, outputs
, cr_idx
=0):
923 assert isinstance(out
, SelectableInt
), \
924 "out zero not a SelectableInt %s" % repr(outputs
)
925 log("handle_comparison", out
.bits
, hex(out
.value
))
926 # TODO - XXX *processor* in 32-bit mode
927 # https://bugs.libre-soc.org/show_bug.cgi?id=424
929 # o32 = exts(out.value, 32)
930 # print ("handle_comparison exts 32 bit", hex(o32))
931 out
= exts(out
.value
, out
.bits
)
932 log("handle_comparison exts", hex(out
))
933 zero
= SelectableInt(out
== 0, 1)
934 positive
= SelectableInt(out
> 0, 1)
935 negative
= SelectableInt(out
< 0, 1)
936 SO
= self
.spr
['XER'][XER_bits
['SO']]
937 log("handle_comparison SO", SO
)
938 cr_field
= selectconcat(negative
, positive
, zero
, SO
)
939 log("handle_comparison cr_field", self
.cr
, cr_idx
, cr_field
)
940 self
.crl
[cr_idx
].eq(cr_field
)
942 def set_pc(self
, pc_val
):
943 self
.namespace
['NIA'] = SelectableInt(pc_val
, 64)
944 self
.pc
.update(self
.namespace
, self
.is_svp64_mode
)
946 def get_next_insn(self
):
950 pc
= self
.pc
.CIA
.value
953 ins
= self
.imem
.ld(pc
, 4, False, True, instr_fetch
=True)
955 raise KeyError("no instruction at 0x%x" % pc
)
959 """set up one instruction
961 pc
, insn
= self
.get_next_insn()
962 yield from self
.setup_next_insn(pc
, insn
)
964 def setup_next_insn(self
, pc
, ins
):
965 """set up next instruction
968 log("setup: 0x%x 0x%x %s" % (pc
, ins
& 0xffffffff, bin(ins
)))
969 log("CIA NIA", self
.respect_pc
, self
.pc
.CIA
.value
, self
.pc
.NIA
.value
)
971 yield self
.dec2
.sv_rm
.eq(0)
972 yield self
.dec2
.dec
.raw_opcode_in
.eq(ins
& 0xffffffff)
973 yield self
.dec2
.dec
.bigendian
.eq(self
.bigendian
)
974 yield self
.dec2
.state
.msr
.eq(self
.msr
.value
)
975 yield self
.dec2
.state
.pc
.eq(pc
)
976 if self
.svstate
is not None:
977 yield self
.dec2
.state
.svstate
.eq(self
.svstate
.value
)
979 # SVP64. first, check if the opcode is EXT001, and SVP64 id bits set
981 opcode
= yield self
.dec2
.dec
.opcode_in
982 pfx
= SVP64PrefixFields() # TODO should probably use SVP64PrefixDecoder
983 pfx
.insn
.value
= opcode
984 major
= pfx
.major
.asint(msb0
=True) # MSB0 inversion
985 log("prefix test: opcode:", major
, bin(major
),
986 pfx
.insn
[7] == 0b1, pfx
.insn
[9] == 0b1)
987 self
.is_svp64_mode
= ((major
== 0b000001) and
988 pfx
.insn
[7].value
== 0b1 and
989 pfx
.insn
[9].value
== 0b1)
990 self
.pc
.update_nia(self
.is_svp64_mode
)
992 yield self
.dec2
.is_svp64_mode
.eq(self
.is_svp64_mode
)
993 self
.namespace
['NIA'] = self
.pc
.NIA
994 self
.namespace
['SVSTATE'] = self
.svstate
995 if not self
.is_svp64_mode
:
998 # in SVP64 mode. decode/print out svp64 prefix, get v3.0B instruction
999 log("svp64.rm", bin(pfx
.rm
.asint(msb0
=True)))
1000 log(" svstate.vl", self
.svstate
.vl
)
1001 log(" svstate.mvl", self
.svstate
.maxvl
)
1002 sv_rm
= pfx
.rm
.asint(msb0
=True)
1003 ins
= self
.imem
.ld(pc
+4, 4, False, True, instr_fetch
=True)
1004 log(" svsetup: 0x%x 0x%x %s" % (pc
+4, ins
& 0xffffffff, bin(ins
)))
1005 yield self
.dec2
.dec
.raw_opcode_in
.eq(ins
& 0xffffffff) # v3.0B suffix
1006 yield self
.dec2
.sv_rm
.eq(sv_rm
) # svp64 prefix
1009 def execute_one(self
):
1010 """execute one instruction
1012 # get the disassembly code for this instruction
1013 if self
.is_svp64_mode
:
1014 if not self
.disassembly
:
1015 code
= yield from self
.get_assembly_name()
1017 code
= self
.disassembly
[self
._pc
+4]
1018 log(" svp64 sim-execute", hex(self
._pc
), code
)
1020 if not self
.disassembly
:
1021 code
= yield from self
.get_assembly_name()
1023 code
= self
.disassembly
[self
._pc
]
1024 log("sim-execute", hex(self
._pc
), code
)
1025 opname
= code
.split(' ')[0]
1027 yield from self
.call(opname
) # execute the instruction
1028 except MemException
as e
: # check for memory errors
1029 if e
.args
[0] == 'unaligned': # alignment error
1030 # run a Trap but set DAR first
1031 print("memory unaligned exception, DAR", e
.dar
)
1032 self
.spr
['DAR'] = SelectableInt(e
.dar
, 64)
1033 self
.call_trap(0x600, PIb
.PRIV
) # 0x600, privileged
1035 elif e
.args
[0] == 'invalid': # invalid
1036 # run a Trap but set DAR first
1037 log("RADIX MMU memory invalid error, mode %s" % e
.mode
)
1038 if e
.mode
== 'EXECUTE':
1039 # XXX TODO: must set a few bits in SRR1,
1040 # see microwatt loadstore1.vhdl
1041 # if m_in.segerr = '0' then
1042 # v.srr1(47 - 33) := m_in.invalid;
1043 # v.srr1(47 - 35) := m_in.perm_error; -- noexec fault
1044 # v.srr1(47 - 44) := m_in.badtree;
1045 # v.srr1(47 - 45) := m_in.rc_error;
1046 # v.intr_vec := 16#400#;
1048 # v.intr_vec := 16#480#;
1049 self
.call_trap(0x400, PIb
.PRIV
) # 0x400, privileged
1051 self
.call_trap(0x300, PIb
.PRIV
) # 0x300, privileged
1053 # not supported yet:
1054 raise e
# ... re-raise
1056 # don't use this except in special circumstances
1057 if not self
.respect_pc
:
1060 log("execute one, CIA NIA", hex(self
.pc
.CIA
.value
),
1061 hex(self
.pc
.NIA
.value
))
1063 def get_assembly_name(self
):
1064 # TODO, asmregs is from the spec, e.g. add RT,RA,RB
1065 # see http://bugs.libre-riscv.org/show_bug.cgi?id=282
1066 dec_insn
= yield self
.dec2
.e
.do
.insn
1067 insn_1_11
= yield self
.dec2
.e
.do
.insn
[1:11]
1068 asmcode
= yield self
.dec2
.dec
.op
.asmcode
1069 int_op
= yield self
.dec2
.dec
.op
.internal_op
1070 log("get assembly name asmcode", asmcode
, int_op
,
1071 hex(dec_insn
), bin(insn_1_11
))
1072 asmop
= insns
.get(asmcode
, None)
1074 # sigh reconstruct the assembly instruction name
1075 if hasattr(self
.dec2
.e
.do
, "oe"):
1076 ov_en
= yield self
.dec2
.e
.do
.oe
.oe
1077 ov_ok
= yield self
.dec2
.e
.do
.oe
.ok
1081 if hasattr(self
.dec2
.e
.do
, "rc"):
1082 rc_en
= yield self
.dec2
.e
.do
.rc
.rc
1083 rc_ok
= yield self
.dec2
.e
.do
.rc
.ok
1087 # grrrr have to special-case MUL op (see DecodeOE)
1088 log("ov %d en %d rc %d en %d op %d" %
1089 (ov_ok
, ov_en
, rc_ok
, rc_en
, int_op
))
1090 if int_op
in [MicrOp
.OP_MUL_H64
.value
, MicrOp
.OP_MUL_H32
.value
]:
1095 if not asmop
.endswith("."): # don't add "." to "andis."
1098 if hasattr(self
.dec2
.e
.do
, "lk"):
1099 lk
= yield self
.dec2
.e
.do
.lk
1102 log("int_op", int_op
)
1103 if int_op
in [MicrOp
.OP_B
.value
, MicrOp
.OP_BC
.value
]:
1104 AA
= yield self
.dec2
.dec
.fields
.FormI
.AA
[0:-1]
1108 spr_msb
= yield from self
.get_spr_msb()
1109 if int_op
== MicrOp
.OP_MFCR
.value
:
1114 # XXX TODO: for whatever weird reason this doesn't work
1115 # https://bugs.libre-soc.org/show_bug.cgi?id=390
1116 if int_op
== MicrOp
.OP_MTCRF
.value
:
1123 def get_remap_indices(self
):
1124 """WARNING, this function stores remap_idxs and remap_loopends
1125 in the class for later use. this to avoid problems with yield
1127 # go through all iterators in lock-step, advance to next remap_idx
1128 srcstep
, dststep
= self
.get_src_dststeps()
1129 # get four SVSHAPEs. here we are hard-coding
1130 SVSHAPE0
= self
.spr
['SVSHAPE0']
1131 SVSHAPE1
= self
.spr
['SVSHAPE1']
1132 SVSHAPE2
= self
.spr
['SVSHAPE2']
1133 SVSHAPE3
= self
.spr
['SVSHAPE3']
1134 # set up the iterators
1135 remaps
= [(SVSHAPE0
, SVSHAPE0
.get_iterator()),
1136 (SVSHAPE1
, SVSHAPE1
.get_iterator()),
1137 (SVSHAPE2
, SVSHAPE2
.get_iterator()),
1138 (SVSHAPE3
, SVSHAPE3
.get_iterator()),
1141 self
.remap_loopends
= [0] * 4
1142 self
.remap_idxs
= [0, 1, 2, 3]
1144 for i
, (shape
, remap
) in enumerate(remaps
):
1145 # zero is "disabled"
1146 if shape
.value
== 0x0:
1147 self
.remap_idxs
[i
] = 0
1148 # pick src or dststep depending on reg num (0-2=in, 3-4=out)
1149 step
= dststep
if (i
in [3, 4]) else srcstep
1150 # this is terrible. O(N^2) looking for the match. but hey.
1151 for idx
, (remap_idx
, loopends
) in enumerate(remap
):
1154 self
.remap_idxs
[i
] = remap_idx
1155 self
.remap_loopends
[i
] = loopends
1156 dbg
.append((i
, step
, remap_idx
, loopends
))
1157 for (i
, step
, remap_idx
, loopends
) in dbg
:
1158 log("SVSHAPE %d idx, end" % i
, step
, remap_idx
, bin(loopends
))
1161 def get_spr_msb(self
):
1162 dec_insn
= yield self
.dec2
.e
.do
.insn
1163 return dec_insn
& (1 << 20) != 0 # sigh - XFF.spr[-1]?
1165 def call(self
, name
):
1166 """call(opcode) - the primary execution point for instructions
1168 self
.last_st_addr
= None # reset the last known store address
1169 self
.last_ld_addr
= None # etc.
1171 ins_name
= name
.strip() # remove spaces if not already done so
1173 log("halted - not executing", ins_name
)
1176 # TODO, asmregs is from the spec, e.g. add RT,RA,RB
1177 # see http://bugs.libre-riscv.org/show_bug.cgi?id=282
1178 asmop
= yield from self
.get_assembly_name()
1179 log("call", ins_name
, asmop
)
1182 int_op
= yield self
.dec2
.dec
.op
.internal_op
1183 spr_msb
= yield from self
.get_spr_msb()
1185 instr_is_privileged
= False
1186 if int_op
in [MicrOp
.OP_ATTN
.value
,
1187 MicrOp
.OP_MFMSR
.value
,
1188 MicrOp
.OP_MTMSR
.value
,
1189 MicrOp
.OP_MTMSRD
.value
,
1191 MicrOp
.OP_RFID
.value
]:
1192 instr_is_privileged
= True
1193 if int_op
in [MicrOp
.OP_MFSPR
.value
,
1194 MicrOp
.OP_MTSPR
.value
] and spr_msb
:
1195 instr_is_privileged
= True
1197 log("is priv", instr_is_privileged
, hex(self
.msr
.value
),
1199 # check MSR priv bit and whether op is privileged: if so, throw trap
1200 if instr_is_privileged
and self
.msr
[MSRb
.PR
] == 1:
1201 self
.call_trap(0x700, PIb
.PRIV
)
1204 # check halted condition
1205 if ins_name
== 'attn':
1209 # check illegal instruction
1211 if ins_name
not in ['mtcrf', 'mtocrf']:
1212 illegal
= ins_name
!= asmop
1214 # sigh deal with setvl not being supported by binutils (.long)
1215 if asmop
.startswith('setvl'):
1219 # and svstep not being supported by binutils (.long)
1220 if asmop
.startswith('svstep'):
1224 # and svremap not being supported by binutils (.long)
1225 if asmop
.startswith('svremap'):
1227 ins_name
= 'svremap'
1229 # and svshape not being supported by binutils (.long)
1230 if asmop
.startswith('svshape'):
1232 ins_name
= 'svshape'
1235 if asmop
== 'fsins':
1238 if asmop
== 'fcoss':
1242 # sigh also deal with ffmadds not being supported by binutils (.long)
1243 if asmop
== 'ffmadds':
1245 ins_name
= 'ffmadds'
1247 # and fdmadds not being supported by binutils (.long)
1248 if asmop
== 'fdmadds':
1250 ins_name
= 'fdmadds'
1252 # and ffadds not being supported by binutils (.long)
1253 if asmop
== 'ffadds':
1257 if asmop
== 'ternlogi' \
1258 or re
.fullmatch(r
'grevw?i?\.?', asmop
or ''):
1262 # branch-conditional redirects to sv.bc
1263 if asmop
.startswith('bc') and self
.is_svp64_mode
:
1264 ins_name
= 'sv.%s' % ins_name
1266 log(" post-processed name", ins_name
, asmop
)
1268 # illegal instructions call TRAP at 0x700
1270 print("illegal", ins_name
, asmop
)
1271 self
.call_trap(0x700, PIb
.ILLEG
)
1272 print("name %s != %s - calling ILLEGAL trap, PC: %x" %
1273 (ins_name
, asmop
, self
.pc
.CIA
.value
))
1276 # this is for setvl "Vertical" mode: if set true,
1277 # srcstep/dststep is explicitly advanced. mode says which SVSTATE to
1278 # test for Rc=1 end condition. 3 bits of all 3 loops are put into CR0
1279 self
.allow_next_step_inc
= False
1280 self
.svstate_next_mode
= 0
1282 # nop has to be supported, we could let the actual op calculate
1283 # but PowerDecoder has a pattern for nop
1284 if ins_name
is 'nop':
1285 self
.update_pc_next()
1288 # look up instruction in ISA.instrs, prepare namespace
1289 info
= self
.instrs
[ins_name
]
1290 yield from self
.prep_namespace(ins_name
, info
.form
, info
.op_fields
)
1292 # preserve order of register names
1293 input_names
= create_args(list(info
.read_regs
) +
1294 list(info
.uninit_regs
))
1295 log("input names", input_names
)
1297 # get SVP64 entry for the current instruction
1298 sv_rm
= self
.svp64rm
.instrs
.get(ins_name
)
1299 if sv_rm
is not None:
1300 dest_cr
, src_cr
, src_byname
, dest_byname
= decode_extra(sv_rm
)
1302 dest_cr
, src_cr
, src_byname
, dest_byname
= False, False, {}, {}
1303 log("sv rm", sv_rm
, dest_cr
, src_cr
, src_byname
, dest_byname
)
1305 # see if srcstep/dststep need skipping over masked-out predicate bits
1306 if (self
.is_svp64_mode
or ins_name
== 'setvl' or
1307 ins_name
in ['svremap', 'svstate']):
1308 yield from self
.svstate_pre_inc()
1309 if self
.is_svp64_mode
:
1310 pre
= yield from self
.update_new_svstate_steps()
1312 self
.svp64_reset_loop()
1314 self
.update_pc_next()
1316 srcstep
, dststep
= self
.get_src_dststeps()
1317 pred_dst_zero
= self
.pred_dst_zero
1318 pred_src_zero
= self
.pred_src_zero
1319 vl
= self
.svstate
.vl
1321 # VL=0 in SVP64 mode means "do nothing: skip instruction"
1322 if self
.is_svp64_mode
and vl
== 0:
1323 self
.pc
.update(self
.namespace
, self
.is_svp64_mode
)
1324 log("SVP64: VL=0, end of call", self
.namespace
['CIA'],
1325 self
.namespace
['NIA'])
1328 # for when SVREMAP is active, using pre-arranged schedule.
1329 # note: modifying PowerDecoder2 needs to "settle"
1330 remap_en
= self
.svstate
.SVme
1331 persist
= self
.svstate
.RMpst
1332 active
= (persist
or self
.last_op_svshape
) and remap_en
!= 0
1333 if self
.is_svp64_mode
:
1334 yield self
.dec2
.remap_active
.eq(remap_en
if active
else 0)
1336 if persist
or self
.last_op_svshape
:
1337 remaps
= self
.get_remap_indices()
1338 if self
.is_svp64_mode
and (persist
or self
.last_op_svshape
):
1339 # just some convenient debug info
1341 sname
= 'SVSHAPE%d' % i
1342 shape
= self
.spr
[sname
]
1343 log(sname
, bin(shape
.value
))
1344 log(" lims", shape
.lims
)
1345 log(" mode", shape
.mode
)
1346 log(" skip", shape
.skip
)
1348 # set up the list of steps to remap
1349 mi0
= self
.svstate
.mi0
1350 mi1
= self
.svstate
.mi1
1351 mi2
= self
.svstate
.mi2
1352 mo0
= self
.svstate
.mo0
1353 mo1
= self
.svstate
.mo1
1354 steps
= [(self
.dec2
.in1_step
, mi0
), # RA
1355 (self
.dec2
.in2_step
, mi1
), # RB
1356 (self
.dec2
.in3_step
, mi2
), # RC
1357 (self
.dec2
.o_step
, mo0
), # RT
1358 (self
.dec2
.o2_step
, mo1
), # EA
1360 remap_idxs
= self
.remap_idxs
1362 # now cross-index the required SHAPE for each of 3-in 2-out regs
1363 rnames
= ['RA', 'RB', 'RC', 'RT', 'EA']
1364 for i
, (dstep
, shape_idx
) in enumerate(steps
):
1365 (shape
, remap
) = remaps
[shape_idx
]
1366 remap_idx
= remap_idxs
[shape_idx
]
1367 # zero is "disabled"
1368 if shape
.value
== 0x0:
1370 # now set the actual requested step to the current index
1371 yield dstep
.eq(remap_idx
)
1373 # debug printout info
1374 rremaps
.append((shape
.mode
, i
, rnames
[i
], shape_idx
,
1377 log("shape remap", x
)
1378 # after that, settle down (combinatorial) to let Vector reg numbers
1379 # work themselves out
1381 if self
.is_svp64_mode
:
1382 remap_active
= yield self
.dec2
.remap_active
1384 remap_active
= False
1385 log("remap active", bin(remap_active
))
1387 # main input registers (RT, RA ...)
1389 for name
in input_names
:
1390 # using PowerDecoder2, first, find the decoder index.
1391 # (mapping name RA RB RC RS to in1, in2, in3)
1392 regnum
, is_vec
= yield from get_pdecode_idx_in(self
.dec2
, name
)
1394 # doing this is not part of svp64, it's because output
1395 # registers, to be modified, need to be in the namespace.
1396 regnum
, is_vec
= yield from get_pdecode_idx_out(self
.dec2
, name
)
1398 regnum
, is_vec
= yield from get_pdecode_idx_out2(self
.dec2
,
1401 # in case getting the register number is needed, _RA, _RB
1402 regname
= "_" + name
1403 self
.namespace
[regname
] = regnum
1404 if not self
.is_svp64_mode
or not pred_src_zero
:
1405 log('reading reg %s %s' % (name
, str(regnum
)), is_vec
)
1407 reg_val
= SelectableInt(self
.fpr(regnum
))
1408 elif name
is not None:
1409 reg_val
= SelectableInt(self
.gpr(regnum
))
1411 log('zero input reg %s %s' % (name
, str(regnum
)), is_vec
)
1413 inputs
.append(reg_val
)
1414 # arrrrgh, awful hack, to get _RT into namespace
1415 if ins_name
in ['setvl', 'svstep']:
1417 RT
= yield self
.dec2
.dec
.RT
1418 self
.namespace
[regname
] = SelectableInt(RT
, 5)
1420 self
.namespace
["RT"] = SelectableInt(0, 5)
1421 regnum
, is_vec
= yield from get_pdecode_idx_out(self
.dec2
, "RT")
1422 log('hack input reg %s %s' % (name
, str(regnum
)), is_vec
)
1424 # in SVP64 mode for LD/ST work out immediate
1425 # XXX TODO: replace_ds for DS-Form rather than D-Form.
1426 # use info.form to detect
1427 replace_d
= False # update / replace constant in pseudocode
1428 if self
.is_svp64_mode
:
1429 ldstmode
= yield self
.dec2
.rm_dec
.ldstmode
1430 # shift mode reads SVD (or SVDS - TODO)
1431 # *BUT*... because this is "overloading" of LD operations,
1432 # it gets *STORED* into D (or DS, TODO)
1433 if ldstmode
== SVP64LDSTmode
.SHIFT
.value
:
1434 imm
= yield self
.dec2
.dec
.fields
.FormSVD
.SVD
[0:11]
1435 imm
= exts(imm
, 11) # sign-extend to integer
1436 log("shift SVD", imm
)
1439 if info
.form
== 'DS':
1440 # DS-Form, multiply by 4 then knock 2 bits off after
1441 imm
= yield self
.dec2
.dec
.fields
.FormDS
.DS
[0:14] * 4
1443 imm
= yield self
.dec2
.dec
.fields
.FormD
.D
[0:16]
1444 imm
= exts(imm
, 16) # sign-extend to integer
1445 # get the right step. LD is from srcstep, ST is dststep
1446 op
= yield self
.dec2
.e
.do
.insn_type
1448 if op
== MicrOp
.OP_LOAD
.value
:
1450 offsmul
= yield self
.dec2
.in1_step
1451 log("D-field REMAP src", imm
, offsmul
)
1454 log("D-field src", imm
, offsmul
)
1455 elif op
== MicrOp
.OP_STORE
.value
:
1456 # XXX NOTE! no bit-reversed STORE! this should not ever be used
1458 log("D-field dst", imm
, offsmul
)
1459 # bit-reverse mode, rev already done through get_src_dst_steps()
1460 if ldstmode
== SVP64LDSTmode
.SHIFT
.value
:
1461 # manually look up RC, sigh
1462 RC
= yield self
.dec2
.dec
.RC
[0:5]
1464 log("LD-SHIFT:", "VL", vl
,
1465 "RC", RC
.value
, "imm", imm
,
1466 "offs", bin(offsmul
),
1468 imm
= SelectableInt((imm
* offsmul
) << RC
.value
, 32)
1469 # Unit-Strided LD/ST adds offset*width to immediate
1470 elif ldstmode
== SVP64LDSTmode
.UNITSTRIDE
.value
:
1471 ldst_len
= yield self
.dec2
.e
.do
.data_len
1472 imm
= SelectableInt(imm
+ offsmul
* ldst_len
, 32)
1474 # Element-strided multiplies the immediate by element step
1475 elif ldstmode
== SVP64LDSTmode
.ELSTRIDE
.value
:
1476 imm
= SelectableInt(imm
* offsmul
, 32)
1479 ldst_ra_vec
= yield self
.dec2
.rm_dec
.ldst_ra_vec
1480 ldst_imz_in
= yield self
.dec2
.rm_dec
.ldst_imz_in
1481 log("LDSTmode", SVP64LDSTmode(ldstmode
),
1482 offsmul
, imm
, ldst_ra_vec
, ldst_imz_in
)
1483 # new replacement D... errr.. DS
1485 if info
.form
== 'DS':
1486 # TODO: assert 2 LSBs are zero?
1487 log("DS-Form, TODO, assert 2 LSBs zero?", bin(imm
.value
))
1488 imm
.value
= imm
.value
>> 2
1489 self
.namespace
['DS'] = imm
1491 self
.namespace
['D'] = imm
1493 # "special" registers
1494 for special
in info
.special_regs
:
1495 if special
in special_sprs
:
1496 inputs
.append(self
.spr
[special
])
1498 inputs
.append(self
.namespace
[special
])
1500 # clear trap (trap) NIA
1501 self
.trap_nia
= None
1503 # check if this was an sv.bc* and create an indicator that
1504 # this is the last check to be made as a loop. combined with
1505 # the ALL/ANY mode we can early-exit
1506 if self
.is_svp64_mode
and ins_name
.startswith("sv.bc"):
1507 no_in_vec
= yield self
.dec2
.no_in_vec
# BI is scalar
1508 end_loop
= no_in_vec
or srcstep
== vl
-1 or dststep
== vl
-1
1509 self
.namespace
['end_loop'] = SelectableInt(end_loop
, 1)
1511 # execute actual instruction here (finally)
1512 log("inputs", inputs
)
1513 results
= info
.func(self
, *inputs
)
1514 log("results", results
)
1516 # "inject" decorator takes namespace from function locals: we need to
1517 # overwrite NIA being overwritten (sigh)
1518 if self
.trap_nia
is not None:
1519 self
.namespace
['NIA'] = self
.trap_nia
1521 log("after func", self
.namespace
['CIA'], self
.namespace
['NIA'])
1523 # check if op was a LD/ST so that debugging can check the
1525 if int_op
in [MicrOp
.OP_STORE
.value
,
1527 self
.last_st_addr
= self
.mem
.last_st_addr
1528 if int_op
in [MicrOp
.OP_LOAD
.value
,
1530 self
.last_ld_addr
= self
.mem
.last_ld_addr
1531 log("op", int_op
, MicrOp
.OP_STORE
.value
, MicrOp
.OP_LOAD
.value
,
1532 self
.last_st_addr
, self
.last_ld_addr
)
1534 # detect if CA/CA32 already in outputs (sra*, basically)
1537 output_names
= create_args(info
.write_regs
)
1538 for name
in output_names
:
1544 log("carry already done?", bin(already_done
))
1545 if hasattr(self
.dec2
.e
.do
, "output_carry"):
1546 carry_en
= yield self
.dec2
.e
.do
.output_carry
1550 yield from self
.handle_carry_(inputs
, results
, already_done
)
1552 if not self
.is_svp64_mode
: # yeah just no. not in parallel processing
1553 # detect if overflow was in return result
1556 for name
, output
in zip(output_names
, results
):
1557 if name
== 'overflow':
1560 if hasattr(self
.dec2
.e
.do
, "oe"):
1561 ov_en
= yield self
.dec2
.e
.do
.oe
.oe
1562 ov_ok
= yield self
.dec2
.e
.do
.oe
.ok
1566 log("internal overflow", overflow
, ov_en
, ov_ok
)
1568 yield from self
.handle_overflow(inputs
, results
, overflow
)
1570 # only do SVP64 dest predicated Rc=1 if dest-pred is not enabled
1572 if not self
.is_svp64_mode
or not pred_dst_zero
:
1573 if hasattr(self
.dec2
.e
.do
, "rc"):
1574 rc_en
= yield self
.dec2
.e
.do
.rc
.rc
1575 if rc_en
and ins_name
not in ['svstep']:
1576 regnum
, is_vec
= yield from get_pdecode_cr_out(self
.dec2
, "CR0")
1577 self
.handle_comparison(results
, regnum
)
1579 # any modified return results?
1581 for name
, output
in zip(output_names
, results
):
1582 if name
== 'overflow': # ignore, done already (above)
1584 if isinstance(output
, int):
1585 output
= SelectableInt(output
, 256)
1586 if name
in ['CA', 'CA32']:
1588 log("writing %s to XER" % name
, output
)
1589 self
.spr
['XER'][XER_bits
[name
]] = output
.value
1591 log("NOT writing %s to XER" % name
, output
)
1592 elif name
in info
.special_regs
:
1593 log('writing special %s' % name
, output
, special_sprs
)
1594 if name
in special_sprs
:
1595 self
.spr
[name
] = output
1597 self
.namespace
[name
].eq(output
)
1599 log('msr written', hex(self
.msr
.value
))
1601 regnum
, is_vec
= yield from get_pdecode_idx_out(self
.dec2
,
1604 regnum
, is_vec
= yield from get_pdecode_idx_out2(
1607 # temporary hack for not having 2nd output
1608 regnum
= yield getattr(self
.decoder
, name
)
1610 if self
.is_svp64_mode
and pred_dst_zero
:
1611 log('zeroing reg %d %s' % (regnum
, str(output
)),
1613 output
= SelectableInt(0, 256)
1619 log('writing %s %s %s' % (ftype
, regnum
, str(output
)),
1621 if output
.bits
> 64:
1622 output
= SelectableInt(output
.value
, 64)
1624 self
.fpr
[regnum
] = output
1626 self
.gpr
[regnum
] = output
1628 # check if it is the SVSTATE.src/dest step that needs incrementing
1629 # this is our Sub-Program-Counter loop from 0 to VL-1
1633 if self
.allow_next_step_inc
:
1634 log("SVSTATE_NEXT: inc requested, mode",
1635 self
.svstate_next_mode
, self
.allow_next_step_inc
)
1636 yield from self
.svstate_pre_inc()
1637 pre
= yield from self
.update_new_svstate_steps()
1639 # reset at end of loop including exit Vertical Mode
1640 log("SVSTATE_NEXT: end of loop, reset")
1641 self
.svp64_reset_loop()
1642 self
.svstate
.vfirst
= 0
1645 results
= [SelectableInt(0, 64)]
1646 self
.handle_comparison(results
) # CR0
1648 if self
.allow_next_step_inc
== 2:
1649 log("SVSTATE_NEXT: read")
1650 nia_update
= (yield from self
.svstate_post_inc(ins_name
))
1652 log("SVSTATE_NEXT: post-inc")
1653 # use actual src/dst-step here to check end, do NOT
1654 # use bit-reversed version
1655 srcstep
, dststep
= self
.new_srcstep
, self
.new_dststep
1656 remaps
= self
.get_remap_indices()
1657 remap_idxs
= self
.remap_idxs
1658 vl
= self
.svstate
.vl
1659 end_src
= srcstep
== vl
-1
1660 end_dst
= dststep
== vl
-1
1661 if self
.allow_next_step_inc
!= 2:
1663 self
.svstate
.srcstep
+= SelectableInt(1, 7)
1665 self
.svstate
.dststep
+= SelectableInt(1, 7)
1666 self
.namespace
['SVSTATE'] = self
.svstate
.spr
1667 # set CR0 (if Rc=1) based on end
1669 srcstep
= self
.svstate
.srcstep
1670 dststep
= self
.svstate
.srcstep
1671 endtest
= 1 if (end_src
or end_dst
) else 0
1672 #results = [SelectableInt(endtest, 64)]
1673 # self.handle_comparison(results) # CR0
1675 # see if svstep was requested, if so, which SVSTATE
1677 if self
.svstate_next_mode
> 0:
1678 shape_idx
= self
.svstate_next_mode
.value
-1
1679 endings
= self
.remap_loopends
[shape_idx
]
1680 cr_field
= SelectableInt((~endings
) << 1 | endtest
, 4)
1681 print("svstep Rc=1, CR0", cr_field
)
1682 self
.crl
[0].eq(cr_field
) # CR0
1683 if end_src
or end_dst
:
1684 # reset at end of loop including exit Vertical Mode
1685 log("SVSTATE_NEXT: after increments, reset")
1686 self
.svp64_reset_loop()
1687 self
.svstate
.vfirst
= 0
1689 elif self
.is_svp64_mode
:
1690 nia_update
= (yield from self
.svstate_post_inc(ins_name
))
1692 # XXX only in non-SVP64 mode!
1693 # record state of whether the current operation was an svshape,
1694 # to be able to know if it should apply in the next instruction.
1695 # also (if going to use this instruction) should disable ability
1696 # to interrupt in between. sigh.
1697 self
.last_op_svshape
= asmop
== 'svremap'
1700 self
.update_pc_next()
1702 def SVSTATE_NEXT(self
, mode
, submode
):
1703 """explicitly moves srcstep/dststep on to next element, for
1704 "Vertical-First" mode. this function is called from
1705 setvl pseudo-code, as a pseudo-op "svstep"
1707 WARNING: this function uses information that was created EARLIER
1708 due to it being in the middle of a yield, but this function is
1709 *NOT* called from yield (it's called from compiled pseudocode).
1711 self
.allow_next_step_inc
= submode
.value
+ 1
1712 log("SVSTATE_NEXT mode", mode
, submode
, self
.allow_next_step_inc
)
1713 self
.svstate_next_mode
= mode
1714 if self
.svstate_next_mode
> 0:
1715 shape_idx
= self
.svstate_next_mode
.value
-1
1716 return SelectableInt(self
.remap_idxs
[shape_idx
], 7)
1717 return SelectableInt(0, 7)
1719 def svstate_pre_inc(self
):
1720 """check if srcstep/dststep need to skip over masked-out predicate bits
1722 # get SVSTATE VL (oh and print out some debug stuff)
1723 vl
= self
.svstate
.vl
1724 srcstep
= self
.svstate
.srcstep
1725 dststep
= self
.svstate
.dststep
1726 sv_a_nz
= yield self
.dec2
.sv_a_nz
1727 fft_mode
= yield self
.dec2
.use_svp64_fft
1728 in1
= yield self
.dec2
.e
.read_reg1
.data
1729 log("SVP64: VL, srcstep, dststep, sv_a_nz, in1 fft, svp64",
1730 vl
, srcstep
, dststep
, sv_a_nz
, in1
, fft_mode
,
1733 # get predicate mask (all 64 bits)
1734 srcmask
= dstmask
= 0xffff_ffff_ffff_ffff
1736 pmode
= yield self
.dec2
.rm_dec
.predmode
1737 reverse_gear
= yield self
.dec2
.rm_dec
.reverse_gear
1738 sv_ptype
= yield self
.dec2
.dec
.op
.SV_Ptype
1739 srcpred
= yield self
.dec2
.rm_dec
.srcpred
1740 dstpred
= yield self
.dec2
.rm_dec
.dstpred
1741 pred_src_zero
= yield self
.dec2
.rm_dec
.pred_sz
1742 pred_dst_zero
= yield self
.dec2
.rm_dec
.pred_dz
1743 if pmode
== SVP64PredMode
.INT
.value
:
1744 srcmask
= dstmask
= get_predint(self
.gpr
, dstpred
)
1745 if sv_ptype
== SVPtype
.P2
.value
:
1746 srcmask
= get_predint(self
.gpr
, srcpred
)
1747 elif pmode
== SVP64PredMode
.CR
.value
:
1748 srcmask
= dstmask
= get_predcr(self
.crl
, dstpred
, vl
)
1749 if sv_ptype
== SVPtype
.P2
.value
:
1750 srcmask
= get_predcr(self
.crl
, srcpred
, vl
)
1751 log(" pmode", pmode
)
1752 log(" reverse", reverse_gear
)
1753 log(" ptype", sv_ptype
)
1754 log(" srcpred", bin(srcpred
))
1755 log(" dstpred", bin(dstpred
))
1756 log(" srcmask", bin(srcmask
))
1757 log(" dstmask", bin(dstmask
))
1758 log(" pred_sz", bin(pred_src_zero
))
1759 log(" pred_dz", bin(pred_dst_zero
))
1761 # okaaay, so here we simply advance srcstep (TODO dststep)
1762 # until the predicate mask has a "1" bit... or we run out of VL
1763 # let srcstep==VL be the indicator to move to next instruction
1764 if not pred_src_zero
:
1765 while (((1 << srcstep
) & srcmask
) == 0) and (srcstep
!= vl
):
1766 log(" skip", bin(1 << srcstep
))
1769 if not pred_dst_zero
:
1770 while (((1 << dststep
) & dstmask
) == 0) and (dststep
!= vl
):
1771 log(" skip", bin(1 << dststep
))
1774 # now work out if the relevant mask bits require zeroing
1776 pred_dst_zero
= ((1 << dststep
) & dstmask
) == 0
1778 pred_src_zero
= ((1 << srcstep
) & srcmask
) == 0
1780 # store new srcstep / dststep
1781 self
.new_srcstep
, self
.new_dststep
= srcstep
, dststep
1782 self
.pred_dst_zero
, self
.pred_src_zero
= pred_dst_zero
, pred_src_zero
1783 log(" new srcstep", srcstep
)
1784 log(" new dststep", dststep
)
1786 def get_src_dststeps(self
):
1787 """gets srcstep and dststep
1789 return self
.new_srcstep
, self
.new_dststep
1791 def update_new_svstate_steps(self
):
1792 # note, do not get the bit-reversed srcstep here!
1793 srcstep
, dststep
= self
.new_srcstep
, self
.new_dststep
1795 # update SVSTATE with new srcstep
1796 self
.svstate
.srcstep
= srcstep
1797 self
.svstate
.dststep
= dststep
1798 self
.namespace
['SVSTATE'] = self
.svstate
1799 yield self
.dec2
.state
.svstate
.eq(self
.svstate
.value
)
1800 yield Settle() # let decoder update
1801 srcstep
= self
.svstate
.srcstep
1802 dststep
= self
.svstate
.dststep
1803 vl
= self
.svstate
.vl
1804 log(" srcstep", srcstep
)
1805 log(" dststep", dststep
)
1808 # check if end reached (we let srcstep overrun, above)
1809 # nothing needs doing (TODO zeroing): just do next instruction
1810 return srcstep
== vl
or dststep
== vl
1812 def svstate_post_inc(self
, insn_name
, vf
=0):
1813 # check if SV "Vertical First" mode is enabled
1814 vfirst
= self
.svstate
.vfirst
1815 log(" SV Vertical First", vf
, vfirst
)
1816 if not vf
and vfirst
== 1:
1820 # check if it is the SVSTATE.src/dest step that needs incrementing
1821 # this is our Sub-Program-Counter loop from 0 to VL-1
1822 # XXX twin predication TODO
1823 vl
= self
.svstate
.vl
1824 mvl
= self
.svstate
.maxvl
1825 srcstep
= self
.svstate
.srcstep
1826 dststep
= self
.svstate
.dststep
1827 rm_mode
= yield self
.dec2
.rm_dec
.mode
1828 reverse_gear
= yield self
.dec2
.rm_dec
.reverse_gear
1829 sv_ptype
= yield self
.dec2
.dec
.op
.SV_Ptype
1830 out_vec
= not (yield self
.dec2
.no_out_vec
)
1831 in_vec
= not (yield self
.dec2
.no_in_vec
)
1832 log(" svstate.vl", vl
)
1833 log(" svstate.mvl", mvl
)
1834 log(" svstate.srcstep", srcstep
)
1835 log(" svstate.dststep", dststep
)
1836 log(" mode", rm_mode
)
1837 log(" reverse", reverse_gear
)
1838 log(" out_vec", out_vec
)
1839 log(" in_vec", in_vec
)
1840 log(" sv_ptype", sv_ptype
, sv_ptype
== SVPtype
.P2
.value
)
1841 # check if srcstep needs incrementing by one, stop PC advancing
1842 # svp64 loop can end early if the dest is scalar for single-pred
1843 # but for 2-pred both src/dest have to be checked.
1844 # XXX this might not be true! it may just be LD/ST
1845 if sv_ptype
== SVPtype
.P2
.value
:
1846 svp64_is_vector
= (out_vec
or in_vec
)
1848 svp64_is_vector
= out_vec
1849 # check if this was an sv.bc* and if so did it succeed
1850 if self
.is_svp64_mode
and insn_name
.startswith("sv.bc"):
1851 end_loop
= self
.namespace
['end_loop']
1852 log("branch %s end_loop" % insn_name
, end_loop
)
1854 self
.svp64_reset_loop()
1855 self
.update_pc_next()
1857 if svp64_is_vector
and srcstep
!= vl
-1 and dststep
!= vl
-1:
1858 self
.svstate
.srcstep
+= SelectableInt(1, 7)
1859 self
.svstate
.dststep
+= SelectableInt(1, 7)
1860 self
.namespace
['SVSTATE'] = self
.svstate
1861 # not an SVP64 branch, so fix PC (NIA==CIA) for next loop
1862 # (by default, NIA is CIA+4 if v3.0B or CIA+8 if SVP64)
1863 # this way we keep repeating the same instruction (with new steps)
1864 self
.pc
.NIA
.value
= self
.pc
.CIA
.value
1865 self
.namespace
['NIA'] = self
.pc
.NIA
1866 log("end of sub-pc call", self
.namespace
['CIA'],
1867 self
.namespace
['NIA'])
1868 return False # DO NOT allow PC update whilst Sub-PC loop running
1870 # reset loop to zero and update NIA
1871 self
.svp64_reset_loop()
1876 def update_pc_next(self
):
1877 # UPDATE program counter
1878 self
.pc
.update(self
.namespace
, self
.is_svp64_mode
)
1879 self
.svstate
.spr
= self
.namespace
['SVSTATE']
1880 log("end of call", self
.namespace
['CIA'],
1881 self
.namespace
['NIA'],
1882 self
.namespace
['SVSTATE'])
1884 def svp64_reset_loop(self
):
1885 self
.svstate
.srcstep
= 0
1886 self
.svstate
.dststep
= 0
1887 log(" svstate.srcstep loop end (PC to update)")
1888 self
.namespace
['SVSTATE'] = self
.svstate
1890 def update_nia(self
):
1891 self
.pc
.update_nia(self
.is_svp64_mode
)
1892 self
.namespace
['NIA'] = self
.pc
.NIA
1896 """Decorator factory.
1898 this decorator will "inject" variables into the function's namespace,
1899 from the *dictionary* in self.namespace. it therefore becomes possible
1900 to make it look like a whole stack of variables which would otherwise
1901 need "self." inserted in front of them (*and* for those variables to be
1902 added to the instance) "appear" in the function.
1904 "self.namespace['SI']" for example becomes accessible as just "SI" but
1905 *only* inside the function, when decorated.
1907 def variable_injector(func
):
1909 def decorator(*args
, **kwargs
):
1911 func_globals
= func
.__globals
__ # Python 2.6+
1912 except AttributeError:
1913 func_globals
= func
.func_globals
# Earlier versions.
1915 context
= args
[0].namespace
# variables to be injected
1916 saved_values
= func_globals
.copy() # Shallow copy of dict.
1917 log("globals before", context
.keys())
1918 func_globals
.update(context
)
1919 result
= func(*args
, **kwargs
)
1920 log("globals after", func_globals
['CIA'], func_globals
['NIA'])
1921 log("args[0]", args
[0].namespace
['CIA'],
1922 args
[0].namespace
['NIA'],
1923 args
[0].namespace
['SVSTATE'])
1924 if 'end_loop' in func_globals
:
1925 log("args[0] end_loop", func_globals
['end_loop'])
1926 args
[0].namespace
= func_globals
1927 #exec (func.__code__, func_globals)
1930 # func_globals = saved_values # Undo changes.
1936 return variable_injector