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 nmigen
.back
.pysim
import Settle
17 from functools
import wraps
19 from openpower
.decoder
.orderedset
import OrderedSet
20 from openpower
.decoder
.selectable_int
import (FieldSelectableInt
, SelectableInt
,
22 from openpower
.decoder
.power_enums
import (spr_dict
, spr_byname
, XER_bits
,
23 insns
, MicrOp
, In1Sel
, In2Sel
, In3Sel
,
24 OutSel
, CROutSel
, LDSTMode
,
25 SVP64RMMode
, SVP64PredMode
,
26 SVP64PredInt
, SVP64PredCR
,
29 from openpower
.decoder
.power_enums
import SVPtype
31 from openpower
.decoder
.helpers
import (exts
, gtu
, ltu
, undefined
, bitrev
)
32 from openpower
.consts
import PIb
, MSRb
# big-endian (PowerISA versions)
33 from openpower
.consts
import SVP64CROffs
34 from openpower
.decoder
.power_svp64
import SVP64RM
, decode_extra
36 from openpower
.decoder
.isa
.radixmmu
import RADIX
37 from openpower
.decoder
.isa
.mem
import Mem
, swap_order
, MemException
38 from openpower
.decoder
.isa
.svshape
import SVSHAPE
40 from openpower
.util
import log
42 from collections
import namedtuple
46 instruction_info
= namedtuple('instruction_info',
47 'func read_regs uninit_regs write_regs ' +
48 'special_regs op_fields form asmregs')
59 # TODO (lkcl): adjust other registers that should be in a particular order
60 # probably CA, CA32, and CR
85 "overflow": 7, # should definitely be last
88 fregs
= ['FRA', 'FRB', 'FRC', 'FRS', 'FRT']
91 def create_args(reglist
, extra
=None):
92 retval
= list(OrderedSet(reglist
))
93 retval
.sort(key
=lambda reg
: REG_SORT_ORDER
.get(reg
, 0))
95 return [extra
] + retval
101 def __init__(self
, decoder
, isacaller
, svstate
, regfile
):
104 self
.isacaller
= isacaller
105 self
.svstate
= svstate
106 for i
in range(len(regfile
)):
107 self
[i
] = SelectableInt(regfile
[i
], 64)
109 def __call__(self
, ridx
):
110 if isinstance(ridx
, SelectableInt
):
114 def set_form(self
, form
):
117 def __setitem__(self
, rnum
, value
):
118 # rnum = rnum.value # only SelectableInt allowed
119 log("GPR setitem", rnum
, value
)
120 if isinstance(rnum
, SelectableInt
):
122 dict.__setitem
__(self
, rnum
, value
)
124 def getz(self
, rnum
):
125 # rnum = rnum.value # only SelectableInt allowed
126 log("GPR getzero?", rnum
)
128 return SelectableInt(0, 64)
131 def _get_regnum(self
, attr
):
132 getform
= self
.sd
.sigforms
[self
.form
]
133 rnum
= getattr(getform
, attr
)
136 def ___getitem__(self
, attr
):
137 """ XXX currently not used
139 rnum
= self
._get
_regnum
(attr
)
140 log("GPR getitem", attr
, rnum
)
141 return self
.regfile
[rnum
]
143 def dump(self
, printout
=True):
145 for i
in range(len(self
)):
146 res
.append(self
[i
].value
)
148 for i
in range(0, len(res
), 8):
151 s
.append("%08x" % res
[i
+j
])
153 print("reg", "%2d" % i
, s
)
158 def __init__(self
, dec2
, initial_sprs
={}):
161 for key
, v
in initial_sprs
.items():
162 if isinstance(key
, SelectableInt
):
164 key
= special_sprs
.get(key
, key
)
165 if isinstance(key
, int):
168 info
= spr_byname
[key
]
169 if not isinstance(v
, SelectableInt
):
170 v
= SelectableInt(v
, info
.length
)
173 def __getitem__(self
, key
):
175 log("dict", self
.items())
176 # if key in special_sprs get the special spr, otherwise return key
177 if isinstance(key
, SelectableInt
):
179 if isinstance(key
, int):
180 key
= spr_dict
[key
].SPR
181 key
= special_sprs
.get(key
, key
)
182 if key
== 'HSRR0': # HACK!
184 if key
== 'HSRR1': # HACK!
187 res
= dict.__getitem
__(self
, key
)
189 if isinstance(key
, int):
192 info
= spr_byname
[key
]
193 dict.__setitem
__(self
, key
, SelectableInt(0, info
.length
))
194 res
= dict.__getitem
__(self
, key
)
195 log("spr returning", key
, res
)
198 def __setitem__(self
, key
, value
):
199 if isinstance(key
, SelectableInt
):
201 if isinstance(key
, int):
202 key
= spr_dict
[key
].SPR
204 key
= special_sprs
.get(key
, key
)
205 if key
== 'HSRR0': # HACK!
206 self
.__setitem
__('SRR0', value
)
207 if key
== 'HSRR1': # HACK!
208 self
.__setitem
__('SRR1', value
)
209 log("setting spr", key
, value
)
210 dict.__setitem
__(self
, key
, value
)
212 def __call__(self
, ridx
):
215 def dump(self
, printout
=True):
217 keys
= list(self
.keys())
220 sprname
= spr_dict
.get(k
, None)
224 sprname
= sprname
.SPR
225 res
.append((sprname
, self
[k
].value
))
227 for sprname
, value
in res
:
228 print(" ", sprname
, hex(value
))
233 def __init__(self
, pc_init
=0):
234 self
.CIA
= SelectableInt(pc_init
, 64)
235 self
.NIA
= self
.CIA
+ SelectableInt(4, 64) # only true for v3.0B!
237 def update_nia(self
, is_svp64
):
238 increment
= 8 if is_svp64
else 4
239 self
.NIA
= self
.CIA
+ SelectableInt(increment
, 64)
241 def update(self
, namespace
, is_svp64
):
242 """updates the program counter (PC) by 4 if v3.0B mode or 8 if SVP64
244 self
.CIA
= namespace
['NIA'].narrow(64)
245 self
.update_nia(is_svp64
)
246 namespace
['CIA'] = self
.CIA
247 namespace
['NIA'] = self
.NIA
250 # Simple-V: see https://libre-soc.org/openpower/sv
252 def __init__(self
, init
=0):
253 self
.spr
= SelectableInt(init
, 32)
254 # fields of SVSTATE, see https://libre-soc.org/openpower/sv/sprs/
255 self
.maxvl
= FieldSelectableInt(self
.spr
, tuple(range(0,7)))
256 self
.vl
= FieldSelectableInt(self
.spr
, tuple(range(7,14)))
257 self
.srcstep
= FieldSelectableInt(self
.spr
, tuple(range(14,21)))
258 self
.dststep
= FieldSelectableInt(self
.spr
, tuple(range(21,28)))
259 self
.subvl
= FieldSelectableInt(self
.spr
, tuple(range(28,30)))
260 self
.svstep
= FieldSelectableInt(self
.spr
, tuple(range(30,32)))
265 def __init__(self
, init
=0):
266 self
.spr
= SelectableInt(init
, 24)
267 # SVP64 RM fields: see https://libre-soc.org/openpower/sv/svp64/
268 self
.mmode
= FieldSelectableInt(self
.spr
, [0])
269 self
.mask
= FieldSelectableInt(self
.spr
, tuple(range(1,4)))
270 self
.elwidth
= FieldSelectableInt(self
.spr
, tuple(range(4,6)))
271 self
.ewsrc
= FieldSelectableInt(self
.spr
, tuple(range(6,8)))
272 self
.subvl
= FieldSelectableInt(self
.spr
, tuple(range(8,10)))
273 self
.extra
= FieldSelectableInt(self
.spr
, tuple(range(10,19)))
274 self
.mode
= FieldSelectableInt(self
.spr
, tuple(range(19,24)))
275 # these cover the same extra field, split into parts as EXTRA2
276 self
.extra2
= list(range(4))
277 self
.extra2
[0] = FieldSelectableInt(self
.spr
, tuple(range(10,12)))
278 self
.extra2
[1] = FieldSelectableInt(self
.spr
, tuple(range(12,14)))
279 self
.extra2
[2] = FieldSelectableInt(self
.spr
, tuple(range(14,16)))
280 self
.extra2
[3] = FieldSelectableInt(self
.spr
, tuple(range(16,18)))
281 self
.smask
= FieldSelectableInt(self
.spr
, tuple(range(16,19)))
282 # and here as well, but EXTRA3
283 self
.extra3
= list(range(3))
284 self
.extra3
[0] = FieldSelectableInt(self
.spr
, tuple(range(10,13)))
285 self
.extra3
[1] = FieldSelectableInt(self
.spr
, tuple(range(13,16)))
286 self
.extra3
[2] = FieldSelectableInt(self
.spr
, tuple(range(16,19)))
289 SVP64RM_MMODE_SIZE
= len(SVP64RMFields().mmode
.br
)
290 SVP64RM_MASK_SIZE
= len(SVP64RMFields().mask
.br
)
291 SVP64RM_ELWIDTH_SIZE
= len(SVP64RMFields().elwidth
.br
)
292 SVP64RM_EWSRC_SIZE
= len(SVP64RMFields().ewsrc
.br
)
293 SVP64RM_SUBVL_SIZE
= len(SVP64RMFields().subvl
.br
)
294 SVP64RM_EXTRA2_SPEC_SIZE
= len(SVP64RMFields().extra2
[0].br
)
295 SVP64RM_EXTRA3_SPEC_SIZE
= len(SVP64RMFields().extra3
[0].br
)
296 SVP64RM_SMASK_SIZE
= len(SVP64RMFields().smask
.br
)
297 SVP64RM_MODE_SIZE
= len(SVP64RMFields().mode
.br
)
300 # SVP64 Prefix fields: see https://libre-soc.org/openpower/sv/svp64/
301 class SVP64PrefixFields
:
303 self
.insn
= SelectableInt(0, 32)
304 # 6 bit major opcode EXT001, 2 bits "identifying" (7, 9), 24 SV ReMap
305 self
.major
= FieldSelectableInt(self
.insn
, tuple(range(0,6)))
306 self
.pid
= FieldSelectableInt(self
.insn
, (7, 9)) # must be 0b11
307 rmfields
= [6, 8] + list(range(10,32)) # SVP64 24-bit RM (ReMap)
308 self
.rm
= FieldSelectableInt(self
.insn
, rmfields
)
311 SV64P_MAJOR_SIZE
= len(SVP64PrefixFields().major
.br
)
312 SV64P_PID_SIZE
= len(SVP64PrefixFields().pid
.br
)
313 SV64P_RM_SIZE
= len(SVP64PrefixFields().rm
.br
)
317 # See PowerISA Version 3.0 B Book 1
318 # Section 2.3.1 Condition Register pages 30 - 31
320 LT
= FL
= 0 # negative, less than, floating-point less than
321 GT
= FG
= 1 # positive, greater than, floating-point greater than
322 EQ
= FE
= 2 # equal, floating-point equal
323 SO
= FU
= 3 # summary overflow, floating-point unordered
325 def __init__(self
, init
=0):
326 # rev_cr = int('{:016b}'.format(initial_cr)[::-1], 2)
327 # self.cr = FieldSelectableInt(self._cr, list(range(32, 64)))
328 self
.cr
= SelectableInt(init
, 64) # underlying reg
329 # field-selectable versions of Condition Register TODO check bitranges?
332 bits
= tuple(range(i
*4+32, (i
+1)*4+32))
333 _cr
= FieldSelectableInt(self
.cr
, bits
)
336 # decode SVP64 predicate integer to reg number and invert
337 def get_predint(gpr
, mask
):
340 log ("get_predint", mask
, SVP64PredInt
.ALWAYS
.value
)
341 if mask
== SVP64PredInt
.ALWAYS
.value
:
342 return 0xffff_ffff_ffff_ffff
343 if mask
== SVP64PredInt
.R3_UNARY
.value
:
344 return 1 << (gpr(3).value
& 0b111111)
345 if mask
== SVP64PredInt
.R3
.value
:
347 if mask
== SVP64PredInt
.R3_N
.value
:
349 if mask
== SVP64PredInt
.R10
.value
:
351 if mask
== SVP64PredInt
.R10_N
.value
:
352 return ~
gpr(10).value
353 if mask
== SVP64PredInt
.R30
.value
:
355 if mask
== SVP64PredInt
.R30_N
.value
:
356 return ~
gpr(30).value
358 # decode SVP64 predicate CR to reg number and invert status
359 def _get_predcr(mask
):
360 if mask
== SVP64PredCR
.LT
.value
:
362 if mask
== SVP64PredCR
.GE
.value
:
364 if mask
== SVP64PredCR
.GT
.value
:
366 if mask
== SVP64PredCR
.LE
.value
:
368 if mask
== SVP64PredCR
.EQ
.value
:
370 if mask
== SVP64PredCR
.NE
.value
:
372 if mask
== SVP64PredCR
.SO
.value
:
374 if mask
== SVP64PredCR
.NS
.value
:
377 # read individual CR fields (0..VL-1), extract the required bit
378 # 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_out(dec2
, name
):
456 out_sel
= yield op
.cr_out
457 out_bitfield
= yield dec2
.dec_cr_out
.cr_bitfield
.data
458 sv_cr_out
= yield op
.sv_cr_out
459 spec
= yield dec2
.crout_svdec
.spec
460 sv_override
= yield dec2
.dec_cr_out
.sv_override
461 # get the IN1/2/3 from the decoder (includes SVP64 remap and isvec)
462 out
= yield dec2
.e
.write_cr
.data
463 o_isvec
= yield dec2
.o_isvec
464 log ("get_pdecode_cr_out", out_sel
, CROutSel
.CR0
.value
, out
, o_isvec
)
465 log (" sv_cr_out", sv_cr_out
)
466 log (" cr_bf", out_bitfield
)
468 log (" override", sv_override
)
469 # identify which regnames map to out / o2
471 if out_sel
== CROutSel
.CR0
.value
:
473 log ("get_pdecode_cr_out not found", name
)
477 # TODO, really should just be using PowerDecoder2
478 def get_pdecode_idx_out(dec2
, name
):
480 out_sel
= yield op
.out_sel
481 # get the IN1/2/3 from the decoder (includes SVP64 remap and isvec)
482 out
= yield dec2
.e
.write_reg
.data
483 o_isvec
= yield dec2
.o_isvec
484 # identify which regnames map to out / o2
486 log ("get_pdecode_idx_out", out_sel
, OutSel
.RA
.value
, out
, o_isvec
)
487 if out_sel
== OutSel
.RA
.value
:
490 log ("get_pdecode_idx_out", out_sel
, OutSel
.RT
.value
,
491 OutSel
.RT_OR_ZERO
.value
, out
, o_isvec
,
493 if out_sel
== OutSel
.RT
.value
:
496 log ("get_pdecode_idx_out", out_sel
, OutSel
.FRA
.value
, out
, o_isvec
)
497 if out_sel
== OutSel
.FRA
.value
:
500 log ("get_pdecode_idx_out", out_sel
, OutSel
.FRT
.value
,
501 OutSel
.FRT
.value
, out
, o_isvec
)
502 if out_sel
== OutSel
.FRT
.value
:
504 log ("get_pdecode_idx_out not found", name
, out_sel
, out
, o_isvec
)
508 # TODO, really should just be using PowerDecoder2
509 def get_pdecode_idx_out2(dec2
, name
):
510 # check first if register is activated for write
512 out_sel
= yield op
.out_sel
513 out
= yield dec2
.e
.write_ea
.data
514 o_isvec
= yield dec2
.o2_isvec
515 out_ok
= yield dec2
.e
.write_ea
.ok
516 log ("get_pdecode_idx_out2", name
, out_sel
, out
, out_ok
, o_isvec
)
521 if hasattr(op
, "upd"):
522 # update mode LD/ST uses read-reg A also as an output
524 log ("get_pdecode_idx_out2", upd
, LDSTMode
.update
.value
,
525 out_sel
, OutSel
.RA
.value
,
527 if upd
== LDSTMode
.update
.value
:
530 int_op
= yield dec2
.dec
.op
.internal_op
531 fft_en
= yield dec2
.use_svp64_fft
532 #if int_op == MicrOp.OP_FP_MADD.value and fft_en:
534 log ("get_pdecode_idx_out2", out_sel
, OutSel
.FRS
.value
,
541 # decoder2 - an instance of power_decoder2
542 # regfile - a list of initial values for the registers
543 # initial_{etc} - initial values for SPRs, Condition Register, Mem, MSR
544 # respect_pc - tracks the program counter. requires initial_insns
545 def __init__(self
, decoder2
, regfile
, initial_sprs
=None, initial_cr
=0,
546 initial_mem
=None, initial_msr
=0,
557 self
.bigendian
= bigendian
559 self
.is_svp64_mode
= False
560 self
.respect_pc
= respect_pc
561 if initial_sprs
is None:
563 if initial_mem
is None:
565 if fpregfile
is None:
567 if initial_insns
is None:
569 assert self
.respect_pc
== False, "instructions required to honor pc"
571 log("ISACaller insns", respect_pc
, initial_insns
, disassembly
)
572 log("ISACaller initial_msr", initial_msr
)
574 # "fake program counter" mode (for unit testing)
578 if isinstance(initial_mem
, tuple):
579 self
.fake_pc
= initial_mem
[0]
580 disasm_start
= self
.fake_pc
582 disasm_start
= initial_pc
584 # disassembly: we need this for now (not given from the decoder)
585 self
.disassembly
= {}
587 for i
, code
in enumerate(disassembly
):
588 self
.disassembly
[i
*4 + disasm_start
] = code
590 # set up registers, instruction memory, data memory, PC, SPRs, MSR, CR
591 self
.svp64rm
= SVP64RM()
592 if initial_svstate
is None:
594 if isinstance(initial_svstate
, int):
595 initial_svstate
= SVP64State(initial_svstate
)
596 # SVSTATE, MSR and PC
597 self
.svstate
= initial_svstate
598 self
.msr
= SelectableInt(initial_msr
, 64) # underlying reg
600 # GPR FPR SPR registers
601 self
.gpr
= GPR(decoder2
, self
, self
.svstate
, regfile
)
602 self
.fpr
= GPR(decoder2
, self
, self
.svstate
, fpregfile
)
603 self
.spr
= SPR(decoder2
, initial_sprs
) # initialise SPRs before MMU
605 # set up 4 dummy SVSHAPEs if they aren't already set up
607 sname
= 'SVSHAPE%d' % i
608 if sname
not in self
.spr
:
609 self
.spr
[sname
] = SVSHAPE(0)
611 # make sure it's an SVSHAPE
612 val
= self
.spr
[sname
].value
613 self
.spr
[sname
] = SVSHAPE(val
)
614 self
.last_op_svshape
= False
617 self
.mem
= Mem(row_bytes
=8, initial_mem
=initial_mem
)
618 self
.imem
= Mem(row_bytes
=4, initial_mem
=initial_insns
)
619 # MMU mode, redirect underlying Mem through RADIX
621 self
.mem
= RADIX(self
.mem
, self
)
623 self
.imem
= RADIX(self
.imem
, self
)
626 # FPR (same as GPR except for FP nums)
627 # 4.2.2 p124 FPSCR (definitely "separate" - not in SPR)
628 # note that mffs, mcrfs, mtfsf "manage" this FPSCR
629 # 2.3.1 CR (and sub-fields CR0..CR6 - CR0 SO comes from XER.SO)
630 # note that mfocrf, mfcr, mtcr, mtocrf, mcrxrx "manage" CRs
632 # 2.3.2 LR (actually SPR #8) -- Done
633 # 2.3.3 CTR (actually SPR #9) -- Done
634 # 2.3.4 TAR (actually SPR #815)
635 # 3.2.2 p45 XER (actually SPR #1) -- Done
636 # 3.2.3 p46 p232 VRSAVE (actually SPR #256)
638 # create CR then allow portions of it to be "selectable" (below)
639 self
.cr_fields
= CRFields(initial_cr
)
640 self
.cr
= self
.cr_fields
.cr
642 # "undefined", just set to variable-bit-width int (use exts "max")
643 #self.undefined = SelectableInt(0, 256) # TODO, not hard-code 256!
646 self
.namespace
.update(self
.spr
)
647 self
.namespace
.update({'GPR': self
.gpr
,
651 'memassign': self
.memassign
,
654 'SVSTATE': self
.svstate
.spr
,
655 'SVSHAPE0': self
.spr
['SVSHAPE0'],
656 'SVSHAPE1': self
.spr
['SVSHAPE1'],
657 'SVSHAPE2': self
.spr
['SVSHAPE2'],
658 'SVSHAPE3': self
.spr
['SVSHAPE3'],
661 'undefined': undefined
,
662 'mode_is_64bit': True,
666 # update pc to requested start point
667 self
.set_pc(initial_pc
)
669 # field-selectable versions of Condition Register
670 self
.crl
= self
.cr_fields
.crl
672 self
.namespace
["CR%d" % i
] = self
.crl
[i
]
674 self
.decoder
= decoder2
.dec
677 def call_trap(self
, trap_addr
, trap_bit
):
678 """calls TRAP and sets up NIA to the new execution location.
679 next instruction will begin at trap_addr.
681 self
.TRAP(trap_addr
, trap_bit
)
682 self
.namespace
['NIA'] = self
.trap_nia
683 self
.pc
.update(self
.namespace
, self
.is_svp64_mode
)
685 def TRAP(self
, trap_addr
=0x700, trap_bit
=PIb
.TRAP
):
686 """TRAP> saves PC, MSR (and TODO SVSTATE), and updates MSR
688 TRAP function is callable from inside the pseudocode itself,
689 hence the default arguments. when calling from inside ISACaller
690 it is best to use call_trap()
692 log("TRAP:", hex(trap_addr
), hex(self
.namespace
['MSR'].value
))
693 # store CIA(+4?) in SRR0, set NIA to 0x700
694 # store MSR in SRR1, set MSR to um errr something, have to check spec
695 # store SVSTATE (if enabled) in SVSRR0
696 self
.spr
['SRR0'].value
= self
.pc
.CIA
.value
697 self
.spr
['SRR1'].value
= self
.namespace
['MSR'].value
698 if self
.is_svp64_mode
:
699 self
.spr
['SVSRR0'] = self
.namespace
['SVSTATE'].value
700 self
.trap_nia
= SelectableInt(trap_addr
, 64)
701 self
.spr
['SRR1'][trap_bit
] = 1 # change *copy* of MSR in SRR1
703 # set exception bits. TODO: this should, based on the address
704 # in figure 66 p1065 V3.0B and the table figure 65 p1063 set these
705 # bits appropriately. however it turns out that *for now* in all
706 # cases (all trap_addrs) the exact same thing is needed.
707 self
.msr
[MSRb
.IR
] = 0
708 self
.msr
[MSRb
.DR
] = 0
709 self
.msr
[MSRb
.FE0
] = 0
710 self
.msr
[MSRb
.FE1
] = 0
711 self
.msr
[MSRb
.EE
] = 0
712 self
.msr
[MSRb
.RI
] = 0
713 self
.msr
[MSRb
.SF
] = 1
714 self
.msr
[MSRb
.TM
] = 0
715 self
.msr
[MSRb
.VEC
] = 0
716 self
.msr
[MSRb
.VSX
] = 0
717 self
.msr
[MSRb
.PR
] = 0
718 self
.msr
[MSRb
.FP
] = 0
719 self
.msr
[MSRb
.PMM
] = 0
720 self
.msr
[MSRb
.TEs
] = 0
721 self
.msr
[MSRb
.TEe
] = 0
722 self
.msr
[MSRb
.UND
] = 0
723 self
.msr
[MSRb
.LE
] = 1
725 def memassign(self
, ea
, sz
, val
):
726 self
.mem
.memassign(ea
, sz
, val
)
728 def prep_namespace(self
, formname
, op_fields
):
729 # TODO: get field names from form in decoder*1* (not decoder2)
730 # decoder2 is hand-created, and decoder1.sigform is auto-generated
732 # then "yield" fields only from op_fields rather than hard-coded
734 fields
= self
.decoder
.sigforms
[formname
]
735 for name
in op_fields
:
737 sig
= getattr(fields
, name
.upper())
739 sig
= getattr(fields
, name
)
741 # these are all opcode fields involved in index-selection of CR,
742 # and need to do "standard" arithmetic. CR[BA+32] for example
743 # would, if using SelectableInt, only be 5-bit.
744 if name
in ['BF', 'BFA', 'BC', 'BA', 'BB', 'BT', 'BI']:
745 self
.namespace
[name
] = val
747 self
.namespace
[name
] = SelectableInt(val
, sig
.width
)
749 self
.namespace
['XER'] = self
.spr
['XER']
750 self
.namespace
['CA'] = self
.spr
['XER'][XER_bits
['CA']].value
751 self
.namespace
['CA32'] = self
.spr
['XER'][XER_bits
['CA32']].value
753 # add some SVSTATE convenience variables
754 vl
= self
.svstate
.vl
.asint(msb0
=True)
755 srcstep
= self
.svstate
.srcstep
.asint(msb0
=True)
756 self
.namespace
['VL'] = vl
757 self
.namespace
['srcstep'] = srcstep
759 def handle_carry_(self
, inputs
, outputs
, already_done
):
760 inv_a
= yield self
.dec2
.e
.do
.invert_in
762 inputs
[0] = ~inputs
[0]
764 imm_ok
= yield self
.dec2
.e
.do
.imm_data
.ok
766 imm
= yield self
.dec2
.e
.do
.imm_data
.data
767 inputs
.append(SelectableInt(imm
, 64))
768 assert len(outputs
) >= 1
769 log("outputs", repr(outputs
))
770 if isinstance(outputs
, list) or isinstance(outputs
, tuple):
776 log("gt input", x
, output
)
777 gt
= (gtu(x
, output
))
780 cy
= 1 if any(gts
) else 0
782 if not (1 & already_done
):
783 self
.spr
['XER'][XER_bits
['CA']] = cy
785 log("inputs", already_done
, inputs
)
787 # ARGH... different for OP_ADD... *sigh*...
788 op
= yield self
.dec2
.e
.do
.insn_type
789 if op
== MicrOp
.OP_ADD
.value
:
790 res32
= (output
.value
& (1 << 32)) != 0
791 a32
= (inputs
[0].value
& (1 << 32)) != 0
793 b32
= (inputs
[1].value
& (1 << 32)) != 0
796 cy32
= res32 ^ a32 ^ b32
797 log("CA32 ADD", cy32
)
801 log("input", x
, output
)
802 log(" x[32:64]", x
, x
[32:64])
803 log(" o[32:64]", output
, output
[32:64])
804 gt
= (gtu(x
[32:64], output
[32:64])) == SelectableInt(1, 1)
806 cy32
= 1 if any(gts
) else 0
807 log("CA32", cy32
, gts
)
808 if not (2 & already_done
):
809 self
.spr
['XER'][XER_bits
['CA32']] = cy32
811 def handle_overflow(self
, inputs
, outputs
, div_overflow
):
812 if hasattr(self
.dec2
.e
.do
, "invert_in"):
813 inv_a
= yield self
.dec2
.e
.do
.invert_in
815 inputs
[0] = ~inputs
[0]
817 imm_ok
= yield self
.dec2
.e
.do
.imm_data
.ok
819 imm
= yield self
.dec2
.e
.do
.imm_data
.data
820 inputs
.append(SelectableInt(imm
, 64))
821 assert len(outputs
) >= 1
822 log("handle_overflow", inputs
, outputs
, div_overflow
)
823 if len(inputs
) < 2 and div_overflow
is None:
826 # div overflow is different: it's returned by the pseudo-code
827 # because it's more complex than can be done by analysing the output
828 if div_overflow
is not None:
829 ov
, ov32
= div_overflow
, div_overflow
830 # arithmetic overflow can be done by analysing the input and output
831 elif len(inputs
) >= 2:
835 input_sgn
= [exts(x
.value
, x
.bits
) < 0 for x
in inputs
]
836 output_sgn
= exts(output
.value
, output
.bits
) < 0
837 ov
= 1 if input_sgn
[0] == input_sgn
[1] and \
838 output_sgn
!= input_sgn
[0] else 0
841 input32_sgn
= [exts(x
.value
, 32) < 0 for x
in inputs
]
842 output32_sgn
= exts(output
.value
, 32) < 0
843 ov32
= 1 if input32_sgn
[0] == input32_sgn
[1] and \
844 output32_sgn
!= input32_sgn
[0] else 0
846 self
.spr
['XER'][XER_bits
['OV']] = ov
847 self
.spr
['XER'][XER_bits
['OV32']] = ov32
848 so
= self
.spr
['XER'][XER_bits
['SO']]
850 self
.spr
['XER'][XER_bits
['SO']] = so
852 def handle_comparison(self
, outputs
, cr_idx
=0):
854 assert isinstance(out
, SelectableInt
), \
855 "out zero not a SelectableInt %s" % repr(outputs
)
856 log("handle_comparison", out
.bits
, hex(out
.value
))
857 # TODO - XXX *processor* in 32-bit mode
858 # https://bugs.libre-soc.org/show_bug.cgi?id=424
860 # o32 = exts(out.value, 32)
861 # print ("handle_comparison exts 32 bit", hex(o32))
862 out
= exts(out
.value
, out
.bits
)
863 log("handle_comparison exts", hex(out
))
864 zero
= SelectableInt(out
== 0, 1)
865 positive
= SelectableInt(out
> 0, 1)
866 negative
= SelectableInt(out
< 0, 1)
867 SO
= self
.spr
['XER'][XER_bits
['SO']]
868 log("handle_comparison SO", SO
)
869 cr_field
= selectconcat(negative
, positive
, zero
, SO
)
870 self
.crl
[cr_idx
].eq(cr_field
)
872 def set_pc(self
, pc_val
):
873 self
.namespace
['NIA'] = SelectableInt(pc_val
, 64)
874 self
.pc
.update(self
.namespace
, self
.is_svp64_mode
)
876 def get_next_insn(self
):
880 pc
= self
.pc
.CIA
.value
883 ins
= self
.imem
.ld(pc
, 4, False, True, instr_fetch
=True)
885 raise KeyError("no instruction at 0x%x" % pc
)
889 """set up one instruction
891 pc
, insn
= self
.get_next_insn()
892 yield from self
.setup_next_insn(pc
, insn
)
894 def setup_next_insn(self
, pc
, ins
):
895 """set up next instruction
898 log("setup: 0x%x 0x%x %s" % (pc
, ins
& 0xffffffff, bin(ins
)))
899 log("CIA NIA", self
.respect_pc
, self
.pc
.CIA
.value
, self
.pc
.NIA
.value
)
901 yield self
.dec2
.sv_rm
.eq(0)
902 yield self
.dec2
.dec
.raw_opcode_in
.eq(ins
& 0xffffffff)
903 yield self
.dec2
.dec
.bigendian
.eq(self
.bigendian
)
904 yield self
.dec2
.state
.msr
.eq(self
.msr
.value
)
905 yield self
.dec2
.state
.pc
.eq(pc
)
906 if self
.svstate
is not None:
907 yield self
.dec2
.state
.svstate
.eq(self
.svstate
.spr
.value
)
909 # SVP64. first, check if the opcode is EXT001, and SVP64 id bits set
911 opcode
= yield self
.dec2
.dec
.opcode_in
912 pfx
= SVP64PrefixFields() # TODO should probably use SVP64PrefixDecoder
913 pfx
.insn
.value
= opcode
914 major
= pfx
.major
.asint(msb0
=True) # MSB0 inversion
915 log ("prefix test: opcode:", major
, bin(major
),
916 pfx
.insn
[7] == 0b1, pfx
.insn
[9] == 0b1)
917 self
.is_svp64_mode
= ((major
== 0b000001) and
918 pfx
.insn
[7].value
== 0b1 and
919 pfx
.insn
[9].value
== 0b1)
920 self
.pc
.update_nia(self
.is_svp64_mode
)
921 yield self
.dec2
.is_svp64_mode
.eq(self
.is_svp64_mode
) # set SVP64 decode
922 self
.namespace
['NIA'] = self
.pc
.NIA
923 self
.namespace
['SVSTATE'] = self
.svstate
.spr
924 if not self
.is_svp64_mode
:
927 # in SVP64 mode. decode/print out svp64 prefix, get v3.0B instruction
928 log ("svp64.rm", bin(pfx
.rm
.asint(msb0
=True)))
929 log (" svstate.vl", self
.svstate
.vl
.asint(msb0
=True))
930 log (" svstate.mvl", self
.svstate
.maxvl
.asint(msb0
=True))
931 sv_rm
= pfx
.rm
.asint(msb0
=True)
932 ins
= self
.imem
.ld(pc
+4, 4, False, True, instr_fetch
=True)
933 log(" svsetup: 0x%x 0x%x %s" % (pc
+4, ins
& 0xffffffff, bin(ins
)))
934 yield self
.dec2
.dec
.raw_opcode_in
.eq(ins
& 0xffffffff) # v3.0B suffix
935 yield self
.dec2
.sv_rm
.eq(sv_rm
) # svp64 prefix
938 def execute_one(self
):
939 """execute one instruction
941 # get the disassembly code for this instruction
942 if self
.is_svp64_mode
:
943 if not self
.disassembly
:
944 code
= yield from self
.get_assembly_name()
946 code
= self
.disassembly
[self
._pc
+4]
947 log(" svp64 sim-execute", hex(self
._pc
), code
)
949 if not self
.disassembly
:
950 code
= yield from self
.get_assembly_name()
952 code
= self
.disassembly
[self
._pc
]
953 log("sim-execute", hex(self
._pc
), code
)
954 opname
= code
.split(' ')[0]
956 yield from self
.call(opname
) # execute the instruction
957 except MemException
as e
: # check for memory errors
958 if e
.args
[0] != 'unaligned': # only doing aligned at the mo
959 raise e
# ... re-raise
960 # run a Trap but set DAR first
961 print ("memory unaligned exception, DAR", e
.dar
)
962 self
.spr
['DAR'] = SelectableInt(e
.dar
, 64)
963 self
.call_trap(0x600, PIb
.PRIV
) # 0x600, privileged
966 # don't use this except in special circumstances
967 if not self
.respect_pc
:
970 log("execute one, CIA NIA", self
.pc
.CIA
.value
, self
.pc
.NIA
.value
)
972 def get_assembly_name(self
):
973 # TODO, asmregs is from the spec, e.g. add RT,RA,RB
974 # see http://bugs.libre-riscv.org/show_bug.cgi?id=282
975 dec_insn
= yield self
.dec2
.e
.do
.insn
976 insn_1_11
= yield self
.dec2
.e
.do
.insn
[1:11]
977 asmcode
= yield self
.dec2
.dec
.op
.asmcode
978 int_op
= yield self
.dec2
.dec
.op
.internal_op
979 log("get assembly name asmcode", asmcode
, int_op
,
980 hex(dec_insn
), bin(insn_1_11
))
981 asmop
= insns
.get(asmcode
, None)
983 # sigh reconstruct the assembly instruction name
984 if hasattr(self
.dec2
.e
.do
, "oe"):
985 ov_en
= yield self
.dec2
.e
.do
.oe
.oe
986 ov_ok
= yield self
.dec2
.e
.do
.oe
.ok
990 if hasattr(self
.dec2
.e
.do
, "rc"):
991 rc_en
= yield self
.dec2
.e
.do
.rc
.rc
992 rc_ok
= yield self
.dec2
.e
.do
.rc
.ok
996 # grrrr have to special-case MUL op (see DecodeOE)
997 log("ov %d en %d rc %d en %d op %d" %
998 (ov_ok
, ov_en
, rc_ok
, rc_en
, int_op
))
999 if int_op
in [MicrOp
.OP_MUL_H64
.value
, MicrOp
.OP_MUL_H32
.value
]:
1004 if not asmop
.endswith("."): # don't add "." to "andis."
1007 if hasattr(self
.dec2
.e
.do
, "lk"):
1008 lk
= yield self
.dec2
.e
.do
.lk
1011 log("int_op", int_op
)
1012 if int_op
in [MicrOp
.OP_B
.value
, MicrOp
.OP_BC
.value
]:
1013 AA
= yield self
.dec2
.dec
.fields
.FormI
.AA
[0:-1]
1017 spr_msb
= yield from self
.get_spr_msb()
1018 if int_op
== MicrOp
.OP_MFCR
.value
:
1023 # XXX TODO: for whatever weird reason this doesn't work
1024 # https://bugs.libre-soc.org/show_bug.cgi?id=390
1025 if int_op
== MicrOp
.OP_MTCRF
.value
:
1032 def get_spr_msb(self
):
1033 dec_insn
= yield self
.dec2
.e
.do
.insn
1034 return dec_insn
& (1 << 20) != 0 # sigh - XFF.spr[-1]?
1036 def call(self
, name
):
1037 """call(opcode) - the primary execution point for instructions
1039 self
.last_st_addr
= None # reset the last known store address
1040 self
.last_ld_addr
= None # etc.
1042 name
= name
.strip() # remove spaces if not already done so
1044 log("halted - not executing", name
)
1047 # TODO, asmregs is from the spec, e.g. add RT,RA,RB
1048 # see http://bugs.libre-riscv.org/show_bug.cgi?id=282
1049 asmop
= yield from self
.get_assembly_name()
1050 log("call", name
, asmop
)
1053 int_op
= yield self
.dec2
.dec
.op
.internal_op
1054 spr_msb
= yield from self
.get_spr_msb()
1056 instr_is_privileged
= False
1057 if int_op
in [MicrOp
.OP_ATTN
.value
,
1058 MicrOp
.OP_MFMSR
.value
,
1059 MicrOp
.OP_MTMSR
.value
,
1060 MicrOp
.OP_MTMSRD
.value
,
1062 MicrOp
.OP_RFID
.value
]:
1063 instr_is_privileged
= True
1064 if int_op
in [MicrOp
.OP_MFSPR
.value
,
1065 MicrOp
.OP_MTSPR
.value
] and spr_msb
:
1066 instr_is_privileged
= True
1068 log("is priv", instr_is_privileged
, hex(self
.msr
.value
),
1070 # check MSR priv bit and whether op is privileged: if so, throw trap
1071 if instr_is_privileged
and self
.msr
[MSRb
.PR
] == 1:
1072 self
.call_trap(0x700, PIb
.PRIV
)
1075 # check halted condition
1080 # check illegal instruction
1082 if name
not in ['mtcrf', 'mtocrf']:
1083 illegal
= name
!= asmop
1085 # sigh deal with setvl not being supported by binutils (.long)
1086 if asmop
.startswith('setvl'):
1090 # and svremap not being supported by binutils (.long)
1091 if asmop
.startswith('svremap'):
1095 # sigh also deal with ffmadds not being supported by binutils (.long)
1096 if asmop
== 'ffmadds':
1100 # and ffadds not being supported by binutils (.long)
1101 if asmop
== 'ffadds':
1106 print("illegal", name
, asmop
)
1107 self
.call_trap(0x700, PIb
.ILLEG
)
1108 print("name %s != %s - calling ILLEGAL trap, PC: %x" %
1109 (name
, asmop
, self
.pc
.CIA
.value
))
1112 # this is for setvl "Vertical" mode: if set true,
1113 # srcstep/dststep is explicitly advanced
1114 self
.allow_next_step_inc
= False
1116 # nop has to be supported, we could let the actual op calculate
1117 # but PowerDecoder has a pattern for nop
1119 self
.update_pc_next()
1122 info
= self
.instrs
[name
]
1123 yield from self
.prep_namespace(info
.form
, info
.op_fields
)
1125 # preserve order of register names
1126 input_names
= create_args(list(info
.read_regs
) +
1127 list(info
.uninit_regs
))
1130 # get SVP64 entry for the current instruction
1131 sv_rm
= self
.svp64rm
.instrs
.get(name
)
1132 if sv_rm
is not None:
1133 dest_cr
, src_cr
, src_byname
, dest_byname
= decode_extra(sv_rm
)
1135 dest_cr
, src_cr
, src_byname
, dest_byname
= False, False, {}, {}
1136 log ("sv rm", sv_rm
, dest_cr
, src_cr
, src_byname
, dest_byname
)
1138 # see if srcstep/dststep need skipping over masked-out predicate bits
1139 if self
.is_svp64_mode
:
1140 yield from self
.svstate_pre_inc()
1141 pre
= yield from self
.update_new_svstate_steps()
1143 self
.svp64_reset_loop()
1145 self
.update_pc_next()
1147 srcstep
, dststep
= self
.new_srcstep
, self
.new_dststep
1148 pred_dst_zero
= self
.pred_dst_zero
1149 pred_src_zero
= self
.pred_src_zero
1150 vl
= self
.svstate
.vl
.asint(msb0
=True)
1152 # VL=0 in SVP64 mode means "do nothing: skip instruction"
1153 if self
.is_svp64_mode
and vl
== 0:
1154 self
.pc
.update(self
.namespace
, self
.is_svp64_mode
)
1155 log("SVP64: VL=0, end of call", self
.namespace
['CIA'],
1156 self
.namespace
['NIA'])
1159 # for when SVSHAPE is active, a very bad hack here (to be replaced)
1160 # using pre-arranged schedule. all of this is awful but it is a
1161 # start. next job will be to put the proper activation in place
1162 yield self
.dec2
.remap_active
.eq(1 if self
.last_op_svshape
else 0)
1164 if self
.is_svp64_mode
and self
.last_op_svshape
:
1165 # get four SVSHAPEs. here we are hard-coding
1166 # SVSHAPE0 to FRT, SVSHAPE1 to FRA, SVSHAPE2 to FRC and
1167 # SVSHAPE3 to FRB, assuming "fmadd FRT, FRA, FRC, FRB."
1168 SVSHAPE0
= self
.spr
['SVSHAPE0']
1169 SVSHAPE1
= self
.spr
['SVSHAPE1']
1170 SVSHAPE2
= self
.spr
['SVSHAPE2']
1171 SVSHAPE3
= self
.spr
['SVSHAPE3']
1173 sname
= 'SVSHAPE%d' % i
1174 shape
= self
.spr
[sname
]
1175 print (sname
, bin(shape
.value
))
1176 print (" lims", shape
.lims
)
1177 print (" mode", shape
.mode
)
1178 print (" skip", shape
.skip
)
1180 remaps
= [(SVSHAPE0
, SVSHAPE0
.get_iterator()),
1181 (SVSHAPE1
, SVSHAPE1
.get_iterator()),
1182 (SVSHAPE2
, SVSHAPE2
.get_iterator()),
1183 (SVSHAPE3
, SVSHAPE3
.get_iterator()),
1186 for i
, (shape
, remap
) in enumerate(remaps
):
1187 # zero is "disabled"
1188 if shape
.value
== 0x0:
1190 # XXX hardcoded! pick dststep for out (i==0) else srcstep
1191 if shape
.mode
== 0b00: # multiply mode
1192 step
= dststep
if (i
== 0) else srcstep
1193 if shape
.mode
== 0b01: # FFT butterfly mode
1194 step
= srcstep
# XXX HACK - for now only use srcstep
1195 # this is terrible. O(N^2) looking for the match. but hey.
1196 for idx
, remap_idx
in enumerate(remap
):
1200 if shape
.mode
== 0b00:
1202 yield self
.dec2
.o_step
.eq(remap_idx
) # RT
1203 yield self
.dec2
.o2_step
.eq(remap_idx
) # EA
1205 yield self
.dec2
.in1_step
.eq(remap_idx
) # RA
1207 yield self
.dec2
.in3_step
.eq(remap_idx
) # RB
1209 yield self
.dec2
.in2_step
.eq(remap_idx
) # RC
1210 # FFT butterfly mode
1211 if shape
.mode
== 0b01:
1213 yield self
.dec2
.o_step
.eq(remap_idx
) # RT
1214 yield self
.dec2
.in2_step
.eq(remap_idx
) # RB
1216 yield self
.dec2
.in1_step
.eq(remap_idx
) # RA
1217 yield self
.dec2
.o2_step
.eq(remap_idx
) # EA (FRS)
1219 yield self
.dec2
.in3_step
.eq(remap_idx
) # RC
1222 rremaps
.append((shape
.mode
, i
, idx
, remap_idx
)) # debug printing
1224 print ("shape remap", x
)
1225 # after that, settle down (combinatorial) to let Vector reg numbers
1226 # work themselves out
1228 remap_active
= yield self
.dec2
.remap_active
1229 print ("remap active", remap_active
)
1231 # main input registers (RT, RA ...)
1233 for name
in input_names
:
1234 # using PowerDecoder2, first, find the decoder index.
1235 # (mapping name RA RB RC RS to in1, in2, in3)
1236 regnum
, is_vec
= yield from get_pdecode_idx_in(self
.dec2
, name
)
1238 # doing this is not part of svp64, it's because output
1239 # registers, to be modified, need to be in the namespace.
1240 regnum
, is_vec
= yield from get_pdecode_idx_out(self
.dec2
, name
)
1242 regnum
, is_vec
= yield from get_pdecode_idx_out2(self
.dec2
,
1245 # in case getting the register number is needed, _RA, _RB
1246 regname
= "_" + name
1247 self
.namespace
[regname
] = regnum
1248 if not self
.is_svp64_mode
or not pred_src_zero
:
1249 log('reading reg %s %s' % (name
, str(regnum
)), is_vec
)
1251 reg_val
= self
.fpr(regnum
)
1252 elif name
is not None:
1253 reg_val
= self
.gpr(regnum
)
1255 log('zero input reg %s %s' % (name
, str(regnum
)), is_vec
)
1257 inputs
.append(reg_val
)
1258 # arrrrgh, awful hack, to get _RT into namespace
1259 if asmop
== 'setvl':
1261 RT
= yield self
.dec2
.dec
.RT
1262 self
.namespace
[regname
] = SelectableInt(RT
, 5)
1264 # in SVP64 mode for LD/ST work out immediate
1265 # XXX TODO: replace_ds for DS-Form rather than D-Form.
1266 # use info.form to detect
1267 replace_d
= False # update / replace constant in pseudocode
1268 if self
.is_svp64_mode
:
1269 ldstmode
= yield self
.dec2
.rm_dec
.ldstmode
1270 # bitreverse mode reads SVD (or SVDS - TODO)
1271 # *BUT*... because this is "overloading" of LD operations,
1272 # it gets *STORED* into D (or DS, TODO)
1273 if ldstmode
== SVP64LDSTmode
.BITREVERSE
.value
:
1274 imm
= yield self
.dec2
.dec
.fields
.FormSVD
.SVD
[0:11]
1275 imm
= exts(imm
, 11) # sign-extend to integer
1276 print ("bitrev SVD", imm
)
1279 imm
= yield self
.dec2
.dec
.fields
.FormD
.D
[0:16]
1280 imm
= exts(imm
, 16) # sign-extend to integer
1281 # get the right step. LD is from srcstep, ST is dststep
1282 op
= yield self
.dec2
.e
.do
.insn_type
1284 if op
== MicrOp
.OP_LOAD
.value
:
1286 log("D-field src", imm
, offsmul
)
1287 elif op
== MicrOp
.OP_STORE
.value
:
1289 log("D-field dst", imm
, offsmul
)
1291 if ldstmode
== SVP64LDSTmode
.BITREVERSE
.value
:
1292 # manually look up RC, sigh
1293 RC
= yield self
.dec2
.dec
.RC
[0:5]
1295 log ("RC", RC
.value
, "imm", imm
, "offs", bin(offsmul
),
1296 "rev", bin(bitrev(offsmul
, vl
)))
1297 imm
= SelectableInt((imm
* bitrev(offsmul
, vl
)) << RC
.value
, 32)
1298 # Unit-Strided LD/ST adds offset*width to immediate
1299 elif ldstmode
== SVP64LDSTmode
.UNITSTRIDE
.value
:
1300 ldst_len
= yield self
.dec2
.e
.do
.data_len
1301 imm
= SelectableInt(imm
+ offsmul
* ldst_len
, 32)
1303 # Element-strided multiplies the immediate by element step
1304 elif ldstmode
== SVP64LDSTmode
.ELSTRIDE
.value
:
1305 imm
= SelectableInt(imm
* offsmul
, 32)
1307 ldst_ra_vec
= yield self
.dec2
.rm_dec
.ldst_ra_vec
1308 ldst_imz_in
= yield self
.dec2
.rm_dec
.ldst_imz_in
1309 log("LDSTmode", ldstmode
, SVP64LDSTmode
.BITREVERSE
.value
,
1310 offsmul
, imm
, ldst_ra_vec
, ldst_imz_in
)
1313 self
.namespace
['D'] = imm
1315 # "special" registers
1316 for special
in info
.special_regs
:
1317 if special
in special_sprs
:
1318 inputs
.append(self
.spr
[special
])
1320 inputs
.append(self
.namespace
[special
])
1322 # clear trap (trap) NIA
1323 self
.trap_nia
= None
1325 # execute actual instruction here (finally)
1326 log("inputs", inputs
)
1327 results
= info
.func(self
, *inputs
)
1328 log("results", results
)
1330 # "inject" decorator takes namespace from function locals: we need to
1331 # overwrite NIA being overwritten (sigh)
1332 if self
.trap_nia
is not None:
1333 self
.namespace
['NIA'] = self
.trap_nia
1335 log("after func", self
.namespace
['CIA'], self
.namespace
['NIA'])
1337 # check if op was a LD/ST so that debugging can check the
1339 if int_op
in [MicrOp
.OP_STORE
.value
,
1341 self
.last_st_addr
= self
.mem
.last_st_addr
1342 if int_op
in [MicrOp
.OP_LOAD
.value
,
1344 self
.last_ld_addr
= self
.mem
.last_ld_addr
1345 log ("op", int_op
, MicrOp
.OP_STORE
.value
, MicrOp
.OP_LOAD
.value
,
1346 self
.last_st_addr
, self
.last_ld_addr
)
1348 # detect if CA/CA32 already in outputs (sra*, basically)
1351 output_names
= create_args(info
.write_regs
)
1352 for name
in output_names
:
1358 log("carry already done?", bin(already_done
))
1359 if hasattr(self
.dec2
.e
.do
, "output_carry"):
1360 carry_en
= yield self
.dec2
.e
.do
.output_carry
1364 yield from self
.handle_carry_(inputs
, results
, already_done
)
1366 if not self
.is_svp64_mode
: # yeah just no. not in parallel processing
1367 # detect if overflow was in return result
1370 for name
, output
in zip(output_names
, results
):
1371 if name
== 'overflow':
1374 if hasattr(self
.dec2
.e
.do
, "oe"):
1375 ov_en
= yield self
.dec2
.e
.do
.oe
.oe
1376 ov_ok
= yield self
.dec2
.e
.do
.oe
.ok
1380 log("internal overflow", overflow
, ov_en
, ov_ok
)
1382 yield from self
.handle_overflow(inputs
, results
, overflow
)
1384 # only do SVP64 dest predicated Rc=1 if dest-pred is not enabled
1386 if not self
.is_svp64_mode
or not pred_dst_zero
:
1387 if hasattr(self
.dec2
.e
.do
, "rc"):
1388 rc_en
= yield self
.dec2
.e
.do
.rc
.rc
1390 regnum
, is_vec
= yield from get_pdecode_cr_out(self
.dec2
, "CR0")
1391 self
.handle_comparison(results
, regnum
)
1393 # any modified return results?
1395 for name
, output
in zip(output_names
, results
):
1396 if name
== 'overflow': # ignore, done already (above)
1398 if isinstance(output
, int):
1399 output
= SelectableInt(output
, 256)
1400 if name
in ['CA', 'CA32']:
1402 log("writing %s to XER" % name
, output
)
1403 self
.spr
['XER'][XER_bits
[name
]] = output
.value
1405 log("NOT writing %s to XER" % name
, output
)
1406 elif name
in info
.special_regs
:
1407 log('writing special %s' % name
, output
, special_sprs
)
1408 if name
in special_sprs
:
1409 self
.spr
[name
] = output
1411 self
.namespace
[name
].eq(output
)
1413 log('msr written', hex(self
.msr
.value
))
1415 regnum
, is_vec
= yield from get_pdecode_idx_out(self
.dec2
,
1418 regnum
, is_vec
= yield from get_pdecode_idx_out2(
1421 # temporary hack for not having 2nd output
1422 regnum
= yield getattr(self
.decoder
, name
)
1424 if self
.is_svp64_mode
and pred_dst_zero
:
1425 log('zeroing reg %d %s' % (regnum
, str(output
)),
1427 output
= SelectableInt(0, 256)
1433 log('writing %s %s %s' % (regnum
, ftype
, str(output
)),
1435 if output
.bits
> 64:
1436 output
= SelectableInt(output
.value
, 64)
1438 self
.fpr
[regnum
] = output
1440 self
.gpr
[regnum
] = output
1442 # check if it is the SVSTATE.src/dest step that needs incrementing
1443 # this is our Sub-Program-Counter loop from 0 to VL-1
1446 if self
.allow_next_step_inc
:
1447 log("SVSTATE_NEXT: inc requested")
1448 yield from self
.svstate_pre_inc()
1449 pre
= yield from self
.update_new_svstate_steps()
1451 # reset at end of loop including exit Vertical Mode
1452 log ("SVSTATE_NEXT: end of loop, reset")
1453 self
.svp64_reset_loop()
1454 self
.msr
[MSRb
.SVF
] = 0
1457 results
= [SelectableInt(0, 64)]
1458 self
.handle_comparison(results
) # CR0
1460 log ("SVSTATE_NEXT: post-inc")
1461 srcstep
, dststep
= self
.new_srcstep
, self
.new_dststep
1462 vl
= self
.svstate
.vl
.asint(msb0
=True)
1463 end_src
= srcstep
== vl
-1
1464 end_dst
= dststep
== vl
-1
1466 self
.svstate
.srcstep
+= SelectableInt(1, 7)
1468 self
.svstate
.dststep
+= SelectableInt(1, 7)
1469 self
.namespace
['SVSTATE'] = self
.svstate
.spr
1470 # set CR0 (if Rc=1) based on end
1472 srcstep
= self
.svstate
.srcstep
.asint(msb0
=True)
1473 dststep
= self
.svstate
.srcstep
.asint(msb0
=True)
1474 endtest
= 0 if (end_src
or end_dst
) else 1
1475 results
= [SelectableInt(endtest
, 64)]
1476 self
.handle_comparison(results
) # CR0
1477 if end_src
or end_dst
:
1478 # reset at end of loop including exit Vertical Mode
1479 log ("SVSTATE_NEXT: after increments, reset")
1480 self
.svp64_reset_loop()
1481 self
.msr
[MSRb
.SVF
] = 0
1483 elif self
.is_svp64_mode
:
1484 yield from self
.svstate_post_inc()
1486 # XXX only in non-SVP64 mode!
1487 # record state of whether the current operation was an svshape,
1488 # to be able to know if it should apply in the next instruction.
1489 # also (if going to use this instruction) should disable ability
1490 # to interrupt in between. sigh.
1491 self
.last_op_svshape
= asmop
== 'svremap'
1493 self
.update_pc_next()
1495 def SVSTATE_NEXT(self
):
1496 """explicitly moves srcstep/dststep on to next element, for
1497 "Vertical-First" mode. this function is called from
1498 setvl pseudo-code, as a pseudo-op "svstep"
1501 self
.allow_next_step_inc
= True
1503 def svstate_pre_inc(self
):
1504 """check if srcstep/dststep need to skip over masked-out predicate bits
1506 # get SVSTATE VL (oh and print out some debug stuff)
1507 vl
= self
.svstate
.vl
.asint(msb0
=True)
1508 srcstep
= self
.svstate
.srcstep
.asint(msb0
=True)
1509 dststep
= self
.svstate
.dststep
.asint(msb0
=True)
1510 sv_a_nz
= yield self
.dec2
.sv_a_nz
1511 fft_mode
= yield self
.dec2
.use_svp64_fft
1512 in1
= yield self
.dec2
.e
.read_reg1
.data
1513 log ("SVP64: VL, srcstep, dststep, sv_a_nz, in1 fft",
1514 vl
, srcstep
, dststep
, sv_a_nz
, in1
, fft_mode
)
1516 # get predicate mask
1517 srcmask
= dstmask
= 0xffff_ffff_ffff_ffff
1519 pmode
= yield self
.dec2
.rm_dec
.predmode
1520 reverse_gear
= yield self
.dec2
.rm_dec
.reverse_gear
1521 sv_ptype
= yield self
.dec2
.dec
.op
.SV_Ptype
1522 srcpred
= yield self
.dec2
.rm_dec
.srcpred
1523 dstpred
= yield self
.dec2
.rm_dec
.dstpred
1524 pred_src_zero
= yield self
.dec2
.rm_dec
.pred_sz
1525 pred_dst_zero
= yield self
.dec2
.rm_dec
.pred_dz
1526 if pmode
== SVP64PredMode
.INT
.value
:
1527 srcmask
= dstmask
= get_predint(self
.gpr
, dstpred
)
1528 if sv_ptype
== SVPtype
.P2
.value
:
1529 srcmask
= get_predint(self
.gpr
, srcpred
)
1530 elif pmode
== SVP64PredMode
.CR
.value
:
1531 srcmask
= dstmask
= get_predcr(self
.crl
, dstpred
, vl
)
1532 if sv_ptype
== SVPtype
.P2
.value
:
1533 srcmask
= get_predcr(self
.crl
, srcpred
, vl
)
1534 log (" pmode", pmode
)
1535 log (" reverse", reverse_gear
)
1536 log (" ptype", sv_ptype
)
1537 log (" srcpred", bin(srcpred
))
1538 log (" dstpred", bin(dstpred
))
1539 log (" srcmask", bin(srcmask
))
1540 log (" dstmask", bin(dstmask
))
1541 log (" pred_sz", bin(pred_src_zero
))
1542 log (" pred_dz", bin(pred_dst_zero
))
1544 # okaaay, so here we simply advance srcstep (TODO dststep)
1545 # until the predicate mask has a "1" bit... or we run out of VL
1546 # let srcstep==VL be the indicator to move to next instruction
1547 if not pred_src_zero
:
1548 while (((1<<srcstep
) & srcmask
) == 0) and (srcstep
!= vl
):
1549 log (" skip", bin(1<<srcstep
))
1552 if not pred_dst_zero
:
1553 while (((1<<dststep
) & dstmask
) == 0) and (dststep
!= vl
):
1554 log (" skip", bin(1<<dststep
))
1557 # now work out if the relevant mask bits require zeroing
1559 pred_dst_zero
= ((1<<dststep
) & dstmask
) == 0
1561 pred_src_zero
= ((1<<srcstep
) & srcmask
) == 0
1563 # store new srcstep / dststep
1564 self
.new_srcstep
, self
.new_dststep
= srcstep
, dststep
1565 self
.pred_dst_zero
, self
.pred_src_zero
= pred_dst_zero
, pred_src_zero
1566 log (" new srcstep", srcstep
)
1567 log (" new dststep", dststep
)
1569 def update_new_svstate_steps(self
):
1570 srcstep
, dststep
= self
.new_srcstep
, self
.new_dststep
1572 # update SVSTATE with new srcstep
1573 self
.svstate
.srcstep
[0:7] = srcstep
1574 self
.svstate
.dststep
[0:7] = dststep
1575 self
.namespace
['SVSTATE'] = self
.svstate
.spr
1576 yield self
.dec2
.state
.svstate
.eq(self
.svstate
.spr
.value
)
1577 yield Settle() # let decoder update
1578 srcstep
= self
.svstate
.srcstep
.asint(msb0
=True)
1579 dststep
= self
.svstate
.dststep
.asint(msb0
=True)
1580 vl
= self
.svstate
.vl
.asint(msb0
=True)
1581 log (" srcstep", srcstep
)
1582 log (" dststep", dststep
)
1584 # check if end reached (we let srcstep overrun, above)
1585 # nothing needs doing (TODO zeroing): just do next instruction
1586 return srcstep
== vl
or dststep
== vl
1588 def svstate_post_inc(self
, vf
=0):
1589 # check if SV "Vertical First" mode is enabled
1590 log (" SV Vertical First", vf
, self
.msr
[MSRb
.SVF
].value
)
1591 if not vf
and self
.msr
[MSRb
.SVF
].value
== 1:
1595 # check if it is the SVSTATE.src/dest step that needs incrementing
1596 # this is our Sub-Program-Counter loop from 0 to VL-1
1597 # XXX twin predication TODO
1598 vl
= self
.svstate
.vl
.asint(msb0
=True)
1599 mvl
= self
.svstate
.maxvl
.asint(msb0
=True)
1600 srcstep
= self
.svstate
.srcstep
.asint(msb0
=True)
1601 dststep
= self
.svstate
.dststep
.asint(msb0
=True)
1602 rm_mode
= yield self
.dec2
.rm_dec
.mode
1603 reverse_gear
= yield self
.dec2
.rm_dec
.reverse_gear
1604 sv_ptype
= yield self
.dec2
.dec
.op
.SV_Ptype
1605 out_vec
= not (yield self
.dec2
.no_out_vec
)
1606 in_vec
= not (yield self
.dec2
.no_in_vec
)
1607 log (" svstate.vl", vl
)
1608 log (" svstate.mvl", mvl
)
1609 log (" svstate.srcstep", srcstep
)
1610 log (" svstate.dststep", dststep
)
1611 log (" mode", rm_mode
)
1612 log (" reverse", reverse_gear
)
1613 log (" out_vec", out_vec
)
1614 log (" in_vec", in_vec
)
1615 log (" sv_ptype", sv_ptype
, sv_ptype
== SVPtype
.P2
.value
)
1616 # check if srcstep needs incrementing by one, stop PC advancing
1617 # svp64 loop can end early if the dest is scalar for single-pred
1618 # but for 2-pred both src/dest have to be checked.
1619 # XXX this might not be true! it may just be LD/ST
1620 if sv_ptype
== SVPtype
.P2
.value
:
1621 svp64_is_vector
= (out_vec
or in_vec
)
1623 svp64_is_vector
= out_vec
1624 if svp64_is_vector
and srcstep
!= vl
-1 and dststep
!= vl
-1:
1625 self
.svstate
.srcstep
+= SelectableInt(1, 7)
1626 self
.svstate
.dststep
+= SelectableInt(1, 7)
1627 self
.pc
.NIA
.value
= self
.pc
.CIA
.value
1628 self
.namespace
['NIA'] = self
.pc
.NIA
1629 self
.namespace
['SVSTATE'] = self
.svstate
.spr
1630 log("end of sub-pc call", self
.namespace
['CIA'],
1631 self
.namespace
['NIA'])
1632 return False # DO NOT allow PC update whilst Sub-PC loop running
1634 # reset loop to zero and update NIA
1635 self
.svp64_reset_loop()
1640 def update_pc_next(self
):
1641 # UPDATE program counter
1642 self
.pc
.update(self
.namespace
, self
.is_svp64_mode
)
1643 self
.svstate
.spr
= self
.namespace
['SVSTATE']
1644 log("end of call", self
.namespace
['CIA'],
1645 self
.namespace
['NIA'],
1646 self
.namespace
['SVSTATE'])
1648 def svp64_reset_loop(self
):
1649 self
.svstate
.srcstep
[0:7] = 0
1650 self
.svstate
.dststep
[0:7] = 0
1651 log (" svstate.srcstep loop end (PC to update)")
1652 self
.namespace
['SVSTATE'] = self
.svstate
.spr
1654 def update_nia(self
):
1655 self
.pc
.update_nia(self
.is_svp64_mode
)
1656 self
.namespace
['NIA'] = self
.pc
.NIA
1659 """Decorator factory.
1661 this decorator will "inject" variables into the function's namespace,
1662 from the *dictionary* in self.namespace. it therefore becomes possible
1663 to make it look like a whole stack of variables which would otherwise
1664 need "self." inserted in front of them (*and* for those variables to be
1665 added to the instance) "appear" in the function.
1667 "self.namespace['SI']" for example becomes accessible as just "SI" but
1668 *only* inside the function, when decorated.
1670 def variable_injector(func
):
1672 def decorator(*args
, **kwargs
):
1674 func_globals
= func
.__globals
__ # Python 2.6+
1675 except AttributeError:
1676 func_globals
= func
.func_globals
# Earlier versions.
1678 context
= args
[0].namespace
# variables to be injected
1679 saved_values
= func_globals
.copy() # Shallow copy of dict.
1680 func_globals
.update(context
)
1681 result
= func(*args
, **kwargs
)
1682 log("globals after", func_globals
['CIA'], func_globals
['NIA'])
1683 log("args[0]", args
[0].namespace
['CIA'],
1684 args
[0].namespace
['NIA'],
1685 args
[0].namespace
['SVSTATE'])
1686 args
[0].namespace
= func_globals
1687 #exec (func.__code__, func_globals)
1690 # func_globals = saved_values # Undo changes.
1696 return variable_injector