d0b80550190bc8b12b8f338654019a47516d542e
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
):
112 def set_form(self
, form
):
115 def getz(self
, rnum
):
116 # rnum = rnum.value # only SelectableInt allowed
117 log("GPR getzero?", rnum
)
119 return SelectableInt(0, 64)
122 def _get_regnum(self
, attr
):
123 getform
= self
.sd
.sigforms
[self
.form
]
124 rnum
= getattr(getform
, attr
)
127 def ___getitem__(self
, attr
):
128 """ XXX currently not used
130 rnum
= self
._get
_regnum
(attr
)
131 log("GPR getitem", attr
, rnum
)
132 return self
.regfile
[rnum
]
134 def dump(self
, printout
=True):
136 for i
in range(len(self
)):
137 res
.append(self
[i
].value
)
139 for i
in range(0, len(res
), 8):
142 s
.append("%08x" % res
[i
+j
])
144 print("reg", "%2d" % i
, s
)
149 def __init__(self
, dec2
, initial_sprs
={}):
152 for key
, v
in initial_sprs
.items():
153 if isinstance(key
, SelectableInt
):
155 key
= special_sprs
.get(key
, key
)
156 if isinstance(key
, int):
159 info
= spr_byname
[key
]
160 if not isinstance(v
, SelectableInt
):
161 v
= SelectableInt(v
, info
.length
)
164 def __getitem__(self
, key
):
166 log("dict", self
.items())
167 # if key in special_sprs get the special spr, otherwise return key
168 if isinstance(key
, SelectableInt
):
170 if isinstance(key
, int):
171 key
= spr_dict
[key
].SPR
172 key
= special_sprs
.get(key
, key
)
173 if key
== 'HSRR0': # HACK!
175 if key
== 'HSRR1': # HACK!
178 res
= dict.__getitem
__(self
, key
)
180 if isinstance(key
, int):
183 info
= spr_byname
[key
]
184 dict.__setitem
__(self
, key
, SelectableInt(0, info
.length
))
185 res
= dict.__getitem
__(self
, key
)
186 log("spr returning", key
, res
)
189 def __setitem__(self
, key
, value
):
190 if isinstance(key
, SelectableInt
):
192 if isinstance(key
, int):
193 key
= spr_dict
[key
].SPR
195 key
= special_sprs
.get(key
, key
)
196 if key
== 'HSRR0': # HACK!
197 self
.__setitem
__('SRR0', value
)
198 if key
== 'HSRR1': # HACK!
199 self
.__setitem
__('SRR1', value
)
200 log("setting spr", key
, value
)
201 dict.__setitem
__(self
, key
, value
)
203 def __call__(self
, ridx
):
206 def dump(self
, printout
=True):
208 keys
= list(self
.keys())
211 sprname
= spr_dict
.get(k
, None)
215 sprname
= sprname
.SPR
216 res
.append((sprname
, self
[k
].value
))
218 for sprname
, value
in res
:
219 print(" ", sprname
, hex(value
))
224 def __init__(self
, pc_init
=0):
225 self
.CIA
= SelectableInt(pc_init
, 64)
226 self
.NIA
= self
.CIA
+ SelectableInt(4, 64) # only true for v3.0B!
228 def update_nia(self
, is_svp64
):
229 increment
= 8 if is_svp64
else 4
230 self
.NIA
= self
.CIA
+ SelectableInt(increment
, 64)
232 def update(self
, namespace
, is_svp64
):
233 """updates the program counter (PC) by 4 if v3.0B mode or 8 if SVP64
235 self
.CIA
= namespace
['NIA'].narrow(64)
236 self
.update_nia(is_svp64
)
237 namespace
['CIA'] = self
.CIA
238 namespace
['NIA'] = self
.NIA
241 # Simple-V: see https://libre-soc.org/openpower/sv
243 def __init__(self
, init
=0):
244 self
.spr
= SelectableInt(init
, 32)
245 # fields of SVSTATE, see https://libre-soc.org/openpower/sv/sprs/
246 self
.maxvl
= FieldSelectableInt(self
.spr
, tuple(range(0,7)))
247 self
.vl
= FieldSelectableInt(self
.spr
, tuple(range(7,14)))
248 self
.srcstep
= FieldSelectableInt(self
.spr
, tuple(range(14,21)))
249 self
.dststep
= FieldSelectableInt(self
.spr
, tuple(range(21,28)))
250 self
.subvl
= FieldSelectableInt(self
.spr
, tuple(range(28,30)))
251 self
.svstep
= FieldSelectableInt(self
.spr
, tuple(range(30,32)))
256 def __init__(self
, init
=0):
257 self
.spr
= SelectableInt(init
, 24)
258 # SVP64 RM fields: see https://libre-soc.org/openpower/sv/svp64/
259 self
.mmode
= FieldSelectableInt(self
.spr
, [0])
260 self
.mask
= FieldSelectableInt(self
.spr
, tuple(range(1,4)))
261 self
.elwidth
= FieldSelectableInt(self
.spr
, tuple(range(4,6)))
262 self
.ewsrc
= FieldSelectableInt(self
.spr
, tuple(range(6,8)))
263 self
.subvl
= FieldSelectableInt(self
.spr
, tuple(range(8,10)))
264 self
.extra
= FieldSelectableInt(self
.spr
, tuple(range(10,19)))
265 self
.mode
= FieldSelectableInt(self
.spr
, tuple(range(19,24)))
266 # these cover the same extra field, split into parts as EXTRA2
267 self
.extra2
= list(range(4))
268 self
.extra2
[0] = FieldSelectableInt(self
.spr
, tuple(range(10,12)))
269 self
.extra2
[1] = FieldSelectableInt(self
.spr
, tuple(range(12,14)))
270 self
.extra2
[2] = FieldSelectableInt(self
.spr
, tuple(range(14,16)))
271 self
.extra2
[3] = FieldSelectableInt(self
.spr
, tuple(range(16,18)))
272 self
.smask
= FieldSelectableInt(self
.spr
, tuple(range(16,19)))
273 # and here as well, but EXTRA3
274 self
.extra3
= list(range(3))
275 self
.extra3
[0] = FieldSelectableInt(self
.spr
, tuple(range(10,13)))
276 self
.extra3
[1] = FieldSelectableInt(self
.spr
, tuple(range(13,16)))
277 self
.extra3
[2] = FieldSelectableInt(self
.spr
, tuple(range(16,19)))
280 SVP64RM_MMODE_SIZE
= len(SVP64RMFields().mmode
.br
)
281 SVP64RM_MASK_SIZE
= len(SVP64RMFields().mask
.br
)
282 SVP64RM_ELWIDTH_SIZE
= len(SVP64RMFields().elwidth
.br
)
283 SVP64RM_EWSRC_SIZE
= len(SVP64RMFields().ewsrc
.br
)
284 SVP64RM_SUBVL_SIZE
= len(SVP64RMFields().subvl
.br
)
285 SVP64RM_EXTRA2_SPEC_SIZE
= len(SVP64RMFields().extra2
[0].br
)
286 SVP64RM_EXTRA3_SPEC_SIZE
= len(SVP64RMFields().extra3
[0].br
)
287 SVP64RM_SMASK_SIZE
= len(SVP64RMFields().smask
.br
)
288 SVP64RM_MODE_SIZE
= len(SVP64RMFields().mode
.br
)
291 # SVP64 Prefix fields: see https://libre-soc.org/openpower/sv/svp64/
292 class SVP64PrefixFields
:
294 self
.insn
= SelectableInt(0, 32)
295 # 6 bit major opcode EXT001, 2 bits "identifying" (7, 9), 24 SV ReMap
296 self
.major
= FieldSelectableInt(self
.insn
, tuple(range(0,6)))
297 self
.pid
= FieldSelectableInt(self
.insn
, (7, 9)) # must be 0b11
298 rmfields
= [6, 8] + list(range(10,32)) # SVP64 24-bit RM (ReMap)
299 self
.rm
= FieldSelectableInt(self
.insn
, rmfields
)
302 SV64P_MAJOR_SIZE
= len(SVP64PrefixFields().major
.br
)
303 SV64P_PID_SIZE
= len(SVP64PrefixFields().pid
.br
)
304 SV64P_RM_SIZE
= len(SVP64PrefixFields().rm
.br
)
308 # See PowerISA Version 3.0 B Book 1
309 # Section 2.3.1 Condition Register pages 30 - 31
311 LT
= FL
= 0 # negative, less than, floating-point less than
312 GT
= FG
= 1 # positive, greater than, floating-point greater than
313 EQ
= FE
= 2 # equal, floating-point equal
314 SO
= FU
= 3 # summary overflow, floating-point unordered
316 def __init__(self
, init
=0):
317 # rev_cr = int('{:016b}'.format(initial_cr)[::-1], 2)
318 # self.cr = FieldSelectableInt(self._cr, list(range(32, 64)))
319 self
.cr
= SelectableInt(init
, 64) # underlying reg
320 # field-selectable versions of Condition Register TODO check bitranges?
323 bits
= tuple(range(i
*4+32, (i
+1)*4+32))
324 _cr
= FieldSelectableInt(self
.cr
, bits
)
327 # decode SVP64 predicate integer to reg number and invert
328 def get_predint(gpr
, mask
):
331 log ("get_predint", mask
, SVP64PredInt
.ALWAYS
.value
)
332 if mask
== SVP64PredInt
.ALWAYS
.value
:
333 return 0xffff_ffff_ffff_ffff
334 if mask
== SVP64PredInt
.R3_UNARY
.value
:
335 return 1 << (gpr(3).value
& 0b111111)
336 if mask
== SVP64PredInt
.R3
.value
:
338 if mask
== SVP64PredInt
.R3_N
.value
:
340 if mask
== SVP64PredInt
.R10
.value
:
342 if mask
== SVP64PredInt
.R10_N
.value
:
343 return ~
gpr(10).value
344 if mask
== SVP64PredInt
.R30
.value
:
346 if mask
== SVP64PredInt
.R30_N
.value
:
347 return ~
gpr(30).value
349 # decode SVP64 predicate CR to reg number and invert status
350 def _get_predcr(mask
):
351 if mask
== SVP64PredCR
.LT
.value
:
353 if mask
== SVP64PredCR
.GE
.value
:
355 if mask
== SVP64PredCR
.GT
.value
:
357 if mask
== SVP64PredCR
.LE
.value
:
359 if mask
== SVP64PredCR
.EQ
.value
:
361 if mask
== SVP64PredCR
.NE
.value
:
363 if mask
== SVP64PredCR
.SO
.value
:
365 if mask
== SVP64PredCR
.NS
.value
:
368 # read individual CR fields (0..VL-1), extract the required bit
369 # and construct the mask
370 def get_predcr(crl
, mask
, vl
):
371 idx
, noninv
= _get_predcr(mask
)
374 cr
= crl
[i
+SVP64CROffs
.CRPred
]
375 if cr
[idx
].value
== noninv
:
380 # TODO, really should just be using PowerDecoder2
381 def get_pdecode_idx_in(dec2
, name
):
383 in1_sel
= yield op
.in1_sel
384 in2_sel
= yield op
.in2_sel
385 in3_sel
= yield op
.in3_sel
386 # get the IN1/2/3 from the decoder (includes SVP64 remap and isvec)
387 in1
= yield dec2
.e
.read_reg1
.data
388 in2
= yield dec2
.e
.read_reg2
.data
389 in3
= yield dec2
.e
.read_reg3
.data
390 in1_isvec
= yield dec2
.in1_isvec
391 in2_isvec
= yield dec2
.in2_isvec
392 in3_isvec
= yield dec2
.in3_isvec
393 log ("get_pdecode_idx_in in1", name
, in1_sel
, In1Sel
.RA
.value
,
395 log ("get_pdecode_idx_in in2", name
, in2_sel
, In2Sel
.RB
.value
,
397 log ("get_pdecode_idx_in in3", name
, in3_sel
, In3Sel
.RS
.value
,
399 log ("get_pdecode_idx_in FRS in3", name
, in3_sel
, In3Sel
.FRS
.value
,
401 log ("get_pdecode_idx_in FRB in2", name
, in2_sel
, In2Sel
.FRB
.value
,
403 log ("get_pdecode_idx_in FRC in3", name
, in3_sel
, In3Sel
.FRC
.value
,
405 # identify which regnames map to in1/2/3
407 if (in1_sel
== In1Sel
.RA
.value
or
408 (in1_sel
== In1Sel
.RA_OR_ZERO
.value
and in1
!= 0)):
409 return in1
, in1_isvec
410 if in1_sel
== In1Sel
.RA_OR_ZERO
.value
:
411 return in1
, in1_isvec
413 if in2_sel
== In2Sel
.RB
.value
:
414 return in2
, in2_isvec
415 if in3_sel
== In3Sel
.RB
.value
:
416 return in3
, in3_isvec
417 # XXX TODO, RC doesn't exist yet!
419 assert False, "RC does not exist yet"
421 if in1_sel
== In1Sel
.RS
.value
:
422 return in1
, in1_isvec
423 if in2_sel
== In2Sel
.RS
.value
:
424 return in2
, in2_isvec
425 if in3_sel
== In3Sel
.RS
.value
:
426 return in3
, in3_isvec
428 if in1_sel
== In1Sel
.FRA
.value
:
429 return in1
, in1_isvec
431 if in2_sel
== In2Sel
.FRB
.value
:
432 return in2
, in2_isvec
434 if in3_sel
== In3Sel
.FRC
.value
:
435 return in3
, in3_isvec
437 if in1_sel
== In1Sel
.FRS
.value
:
438 return in1
, in1_isvec
439 if in3_sel
== In3Sel
.FRS
.value
:
440 return in3
, in3_isvec
444 # TODO, really should just be using PowerDecoder2
445 def get_pdecode_cr_out(dec2
, name
):
447 out_sel
= yield op
.cr_out
448 out_bitfield
= yield dec2
.dec_cr_out
.cr_bitfield
.data
449 sv_cr_out
= yield op
.sv_cr_out
450 spec
= yield dec2
.crout_svdec
.spec
451 sv_override
= yield dec2
.dec_cr_out
.sv_override
452 # get the IN1/2/3 from the decoder (includes SVP64 remap and isvec)
453 out
= yield dec2
.e
.write_cr
.data
454 o_isvec
= yield dec2
.o_isvec
455 log ("get_pdecode_cr_out", out_sel
, CROutSel
.CR0
.value
, out
, o_isvec
)
456 log (" sv_cr_out", sv_cr_out
)
457 log (" cr_bf", out_bitfield
)
459 log (" override", sv_override
)
460 # identify which regnames map to out / o2
462 if out_sel
== CROutSel
.CR0
.value
:
464 log ("get_pdecode_cr_out not found", name
)
468 # TODO, really should just be using PowerDecoder2
469 def get_pdecode_idx_out(dec2
, name
):
471 out_sel
= yield op
.out_sel
472 # get the IN1/2/3 from the decoder (includes SVP64 remap and isvec)
473 out
= yield dec2
.e
.write_reg
.data
474 o_isvec
= yield dec2
.o_isvec
475 # identify which regnames map to out / o2
477 log ("get_pdecode_idx_out", out_sel
, OutSel
.RA
.value
, out
, o_isvec
)
478 if out_sel
== OutSel
.RA
.value
:
481 log ("get_pdecode_idx_out", out_sel
, OutSel
.RT
.value
,
482 OutSel
.RT_OR_ZERO
.value
, out
, o_isvec
)
483 if out_sel
== OutSel
.RT
.value
:
486 log ("get_pdecode_idx_out", out_sel
, OutSel
.FRA
.value
, out
, o_isvec
)
487 if out_sel
== OutSel
.FRA
.value
:
490 log ("get_pdecode_idx_out", out_sel
, OutSel
.FRT
.value
,
491 OutSel
.FRT
.value
, out
, o_isvec
)
492 if out_sel
== OutSel
.FRT
.value
:
494 log ("get_pdecode_idx_out not found", name
, out_sel
, out
, o_isvec
)
498 # TODO, really should just be using PowerDecoder2
499 def get_pdecode_idx_out2(dec2
, name
):
500 # check first if register is activated for write
502 out_sel
= yield op
.out_sel
503 out
= yield dec2
.e
.write_ea
.data
504 o_isvec
= yield dec2
.o2_isvec
505 out_ok
= yield dec2
.e
.write_ea
.ok
506 log ("get_pdecode_idx_out2", name
, out_sel
, out
, out_ok
, o_isvec
)
511 if hasattr(op
, "upd"):
512 # update mode LD/ST uses read-reg A also as an output
514 log ("get_pdecode_idx_out2", upd
, LDSTMode
.update
.value
,
515 out_sel
, OutSel
.RA
.value
,
517 if upd
== LDSTMode
.update
.value
:
520 int_op
= yield dec2
.dec
.op
.internal_op
521 fft_en
= yield dec2
.use_svp64_fft
522 if int_op
== MicrOp
.OP_FP_MADD
.value
and fft_en
:
523 log ("get_pdecode_idx_out2", out_sel
, OutSel
.FRS
.value
,
530 # decoder2 - an instance of power_decoder2
531 # regfile - a list of initial values for the registers
532 # initial_{etc} - initial values for SPRs, Condition Register, Mem, MSR
533 # respect_pc - tracks the program counter. requires initial_insns
534 def __init__(self
, decoder2
, regfile
, initial_sprs
=None, initial_cr
=0,
535 initial_mem
=None, initial_msr
=0,
546 self
.bigendian
= bigendian
548 self
.is_svp64_mode
= False
549 self
.respect_pc
= respect_pc
550 if initial_sprs
is None:
552 if initial_mem
is None:
554 if fpregfile
is None:
556 if initial_insns
is None:
558 assert self
.respect_pc
== False, "instructions required to honor pc"
560 log("ISACaller insns", respect_pc
, initial_insns
, disassembly
)
561 log("ISACaller initial_msr", initial_msr
)
563 # "fake program counter" mode (for unit testing)
567 if isinstance(initial_mem
, tuple):
568 self
.fake_pc
= initial_mem
[0]
569 disasm_start
= self
.fake_pc
571 disasm_start
= initial_pc
573 # disassembly: we need this for now (not given from the decoder)
574 self
.disassembly
= {}
576 for i
, code
in enumerate(disassembly
):
577 self
.disassembly
[i
*4 + disasm_start
] = code
579 # set up registers, instruction memory, data memory, PC, SPRs, MSR, CR
580 self
.svp64rm
= SVP64RM()
581 if initial_svstate
is None:
583 if isinstance(initial_svstate
, int):
584 initial_svstate
= SVP64State(initial_svstate
)
585 # SVSTATE, MSR and PC
586 self
.svstate
= initial_svstate
587 self
.msr
= SelectableInt(initial_msr
, 64) # underlying reg
589 # GPR FPR SPR registers
590 self
.gpr
= GPR(decoder2
, self
, self
.svstate
, regfile
)
591 self
.fpr
= GPR(decoder2
, self
, self
.svstate
, fpregfile
)
592 self
.spr
= SPR(decoder2
, initial_sprs
) # initialise SPRs before MMU
594 # set up 4 dummy SVSHAPEs if they aren't already set up
596 sname
= 'SVSHAPE%d' % i
597 if sname
not in self
.spr
:
598 self
.spr
[sname
] = SVSHAPE(0)
600 # make sure it's an SVSHAPE
601 val
= self
.spr
[sname
].value
602 self
.spr
[sname
] = SVSHAPE(val
)
603 self
.last_op_svshape
= False
606 self
.mem
= Mem(row_bytes
=8, initial_mem
=initial_mem
)
607 self
.imem
= Mem(row_bytes
=4, initial_mem
=initial_insns
)
608 # MMU mode, redirect underlying Mem through RADIX
610 self
.mem
= RADIX(self
.mem
, self
)
612 self
.imem
= RADIX(self
.imem
, self
)
615 # FPR (same as GPR except for FP nums)
616 # 4.2.2 p124 FPSCR (definitely "separate" - not in SPR)
617 # note that mffs, mcrfs, mtfsf "manage" this FPSCR
618 # 2.3.1 CR (and sub-fields CR0..CR6 - CR0 SO comes from XER.SO)
619 # note that mfocrf, mfcr, mtcr, mtocrf, mcrxrx "manage" CRs
621 # 2.3.2 LR (actually SPR #8) -- Done
622 # 2.3.3 CTR (actually SPR #9) -- Done
623 # 2.3.4 TAR (actually SPR #815)
624 # 3.2.2 p45 XER (actually SPR #1) -- Done
625 # 3.2.3 p46 p232 VRSAVE (actually SPR #256)
627 # create CR then allow portions of it to be "selectable" (below)
628 self
.cr_fields
= CRFields(initial_cr
)
629 self
.cr
= self
.cr_fields
.cr
631 # "undefined", just set to variable-bit-width int (use exts "max")
632 #self.undefined = SelectableInt(0, 256) # TODO, not hard-code 256!
635 self
.namespace
.update(self
.spr
)
636 self
.namespace
.update({'GPR': self
.gpr
,
640 'memassign': self
.memassign
,
643 'SVSTATE': self
.svstate
.spr
,
644 'SVSHAPE0': self
.spr
['SVSHAPE0'],
645 'SVSHAPE1': self
.spr
['SVSHAPE1'],
646 'SVSHAPE2': self
.spr
['SVSHAPE2'],
647 'SVSHAPE3': self
.spr
['SVSHAPE3'],
650 'undefined': undefined
,
651 'mode_is_64bit': True,
655 # update pc to requested start point
656 self
.set_pc(initial_pc
)
658 # field-selectable versions of Condition Register
659 self
.crl
= self
.cr_fields
.crl
661 self
.namespace
["CR%d" % i
] = self
.crl
[i
]
663 self
.decoder
= decoder2
.dec
666 def call_trap(self
, trap_addr
, trap_bit
):
667 """calls TRAP and sets up NIA to the new execution location.
668 next instruction will begin at trap_addr.
670 self
.TRAP(trap_addr
, trap_bit
)
671 self
.namespace
['NIA'] = self
.trap_nia
672 self
.pc
.update(self
.namespace
, self
.is_svp64_mode
)
674 def TRAP(self
, trap_addr
=0x700, trap_bit
=PIb
.TRAP
):
675 """TRAP> saves PC, MSR (and TODO SVSTATE), and updates MSR
677 TRAP function is callable from inside the pseudocode itself,
678 hence the default arguments. when calling from inside ISACaller
679 it is best to use call_trap()
681 log("TRAP:", hex(trap_addr
), hex(self
.namespace
['MSR'].value
))
682 # store CIA(+4?) in SRR0, set NIA to 0x700
683 # store MSR in SRR1, set MSR to um errr something, have to check spec
684 # store SVSTATE (if enabled) in SVSRR0
685 self
.spr
['SRR0'].value
= self
.pc
.CIA
.value
686 self
.spr
['SRR1'].value
= self
.namespace
['MSR'].value
687 if self
.is_svp64_mode
:
688 self
.spr
['SVSRR0'] = self
.namespace
['SVSTATE'].value
689 self
.trap_nia
= SelectableInt(trap_addr
, 64)
690 self
.spr
['SRR1'][trap_bit
] = 1 # change *copy* of MSR in SRR1
692 # set exception bits. TODO: this should, based on the address
693 # in figure 66 p1065 V3.0B and the table figure 65 p1063 set these
694 # bits appropriately. however it turns out that *for now* in all
695 # cases (all trap_addrs) the exact same thing is needed.
696 self
.msr
[MSRb
.IR
] = 0
697 self
.msr
[MSRb
.DR
] = 0
698 self
.msr
[MSRb
.FE0
] = 0
699 self
.msr
[MSRb
.FE1
] = 0
700 self
.msr
[MSRb
.EE
] = 0
701 self
.msr
[MSRb
.RI
] = 0
702 self
.msr
[MSRb
.SF
] = 1
703 self
.msr
[MSRb
.TM
] = 0
704 self
.msr
[MSRb
.VEC
] = 0
705 self
.msr
[MSRb
.VSX
] = 0
706 self
.msr
[MSRb
.PR
] = 0
707 self
.msr
[MSRb
.FP
] = 0
708 self
.msr
[MSRb
.PMM
] = 0
709 self
.msr
[MSRb
.TEs
] = 0
710 self
.msr
[MSRb
.TEe
] = 0
711 self
.msr
[MSRb
.UND
] = 0
712 self
.msr
[MSRb
.LE
] = 1
714 def memassign(self
, ea
, sz
, val
):
715 self
.mem
.memassign(ea
, sz
, val
)
717 def prep_namespace(self
, formname
, op_fields
):
718 # TODO: get field names from form in decoder*1* (not decoder2)
719 # decoder2 is hand-created, and decoder1.sigform is auto-generated
721 # then "yield" fields only from op_fields rather than hard-coded
723 fields
= self
.decoder
.sigforms
[formname
]
724 for name
in op_fields
:
726 sig
= getattr(fields
, name
.upper())
728 sig
= getattr(fields
, name
)
730 # these are all opcode fields involved in index-selection of CR,
731 # and need to do "standard" arithmetic. CR[BA+32] for example
732 # would, if using SelectableInt, only be 5-bit.
733 if name
in ['BF', 'BFA', 'BC', 'BA', 'BB', 'BT', 'BI']:
734 self
.namespace
[name
] = val
736 self
.namespace
[name
] = SelectableInt(val
, sig
.width
)
738 self
.namespace
['XER'] = self
.spr
['XER']
739 self
.namespace
['CA'] = self
.spr
['XER'][XER_bits
['CA']].value
740 self
.namespace
['CA32'] = self
.spr
['XER'][XER_bits
['CA32']].value
742 # add some SVSTATE convenience variables
743 vl
= self
.svstate
.vl
.asint(msb0
=True)
744 srcstep
= self
.svstate
.srcstep
.asint(msb0
=True)
745 self
.namespace
['VL'] = vl
746 self
.namespace
['srcstep'] = srcstep
748 def handle_carry_(self
, inputs
, outputs
, already_done
):
749 inv_a
= yield self
.dec2
.e
.do
.invert_in
751 inputs
[0] = ~inputs
[0]
753 imm_ok
= yield self
.dec2
.e
.do
.imm_data
.ok
755 imm
= yield self
.dec2
.e
.do
.imm_data
.data
756 inputs
.append(SelectableInt(imm
, 64))
757 assert len(outputs
) >= 1
758 log("outputs", repr(outputs
))
759 if isinstance(outputs
, list) or isinstance(outputs
, tuple):
765 log("gt input", x
, output
)
766 gt
= (gtu(x
, output
))
769 cy
= 1 if any(gts
) else 0
771 if not (1 & already_done
):
772 self
.spr
['XER'][XER_bits
['CA']] = cy
774 log("inputs", already_done
, inputs
)
776 # ARGH... different for OP_ADD... *sigh*...
777 op
= yield self
.dec2
.e
.do
.insn_type
778 if op
== MicrOp
.OP_ADD
.value
:
779 res32
= (output
.value
& (1 << 32)) != 0
780 a32
= (inputs
[0].value
& (1 << 32)) != 0
782 b32
= (inputs
[1].value
& (1 << 32)) != 0
785 cy32
= res32 ^ a32 ^ b32
786 log("CA32 ADD", cy32
)
790 log("input", x
, output
)
791 log(" x[32:64]", x
, x
[32:64])
792 log(" o[32:64]", output
, output
[32:64])
793 gt
= (gtu(x
[32:64], output
[32:64])) == SelectableInt(1, 1)
795 cy32
= 1 if any(gts
) else 0
796 log("CA32", cy32
, gts
)
797 if not (2 & already_done
):
798 self
.spr
['XER'][XER_bits
['CA32']] = cy32
800 def handle_overflow(self
, inputs
, outputs
, div_overflow
):
801 if hasattr(self
.dec2
.e
.do
, "invert_in"):
802 inv_a
= yield self
.dec2
.e
.do
.invert_in
804 inputs
[0] = ~inputs
[0]
806 imm_ok
= yield self
.dec2
.e
.do
.imm_data
.ok
808 imm
= yield self
.dec2
.e
.do
.imm_data
.data
809 inputs
.append(SelectableInt(imm
, 64))
810 assert len(outputs
) >= 1
811 log("handle_overflow", inputs
, outputs
, div_overflow
)
812 if len(inputs
) < 2 and div_overflow
is None:
815 # div overflow is different: it's returned by the pseudo-code
816 # because it's more complex than can be done by analysing the output
817 if div_overflow
is not None:
818 ov
, ov32
= div_overflow
, div_overflow
819 # arithmetic overflow can be done by analysing the input and output
820 elif len(inputs
) >= 2:
824 input_sgn
= [exts(x
.value
, x
.bits
) < 0 for x
in inputs
]
825 output_sgn
= exts(output
.value
, output
.bits
) < 0
826 ov
= 1 if input_sgn
[0] == input_sgn
[1] and \
827 output_sgn
!= input_sgn
[0] else 0
830 input32_sgn
= [exts(x
.value
, 32) < 0 for x
in inputs
]
831 output32_sgn
= exts(output
.value
, 32) < 0
832 ov32
= 1 if input32_sgn
[0] == input32_sgn
[1] and \
833 output32_sgn
!= input32_sgn
[0] else 0
835 self
.spr
['XER'][XER_bits
['OV']] = ov
836 self
.spr
['XER'][XER_bits
['OV32']] = ov32
837 so
= self
.spr
['XER'][XER_bits
['SO']]
839 self
.spr
['XER'][XER_bits
['SO']] = so
841 def handle_comparison(self
, outputs
, cr_idx
=0):
843 assert isinstance(out
, SelectableInt
), \
844 "out zero not a SelectableInt %s" % repr(outputs
)
845 log("handle_comparison", out
.bits
, hex(out
.value
))
846 # TODO - XXX *processor* in 32-bit mode
847 # https://bugs.libre-soc.org/show_bug.cgi?id=424
849 # o32 = exts(out.value, 32)
850 # print ("handle_comparison exts 32 bit", hex(o32))
851 out
= exts(out
.value
, out
.bits
)
852 log("handle_comparison exts", hex(out
))
853 zero
= SelectableInt(out
== 0, 1)
854 positive
= SelectableInt(out
> 0, 1)
855 negative
= SelectableInt(out
< 0, 1)
856 SO
= self
.spr
['XER'][XER_bits
['SO']]
857 log("handle_comparison SO", SO
)
858 cr_field
= selectconcat(negative
, positive
, zero
, SO
)
859 self
.crl
[cr_idx
].eq(cr_field
)
861 def set_pc(self
, pc_val
):
862 self
.namespace
['NIA'] = SelectableInt(pc_val
, 64)
863 self
.pc
.update(self
.namespace
, self
.is_svp64_mode
)
865 def get_next_insn(self
):
869 pc
= self
.pc
.CIA
.value
872 ins
= self
.imem
.ld(pc
, 4, False, True, instr_fetch
=True)
874 raise KeyError("no instruction at 0x%x" % pc
)
878 """set up one instruction
880 pc
, insn
= self
.get_next_insn()
881 yield from self
.setup_next_insn(pc
, insn
)
883 def setup_next_insn(self
, pc
, ins
):
884 """set up next instruction
887 log("setup: 0x%x 0x%x %s" % (pc
, ins
& 0xffffffff, bin(ins
)))
888 log("CIA NIA", self
.respect_pc
, self
.pc
.CIA
.value
, self
.pc
.NIA
.value
)
890 yield self
.dec2
.sv_rm
.eq(0)
891 yield self
.dec2
.dec
.raw_opcode_in
.eq(ins
& 0xffffffff)
892 yield self
.dec2
.dec
.bigendian
.eq(self
.bigendian
)
893 yield self
.dec2
.state
.msr
.eq(self
.msr
.value
)
894 yield self
.dec2
.state
.pc
.eq(pc
)
895 if self
.svstate
is not None:
896 yield self
.dec2
.state
.svstate
.eq(self
.svstate
.spr
.value
)
898 # SVP64. first, check if the opcode is EXT001, and SVP64 id bits set
900 opcode
= yield self
.dec2
.dec
.opcode_in
901 pfx
= SVP64PrefixFields() # TODO should probably use SVP64PrefixDecoder
902 pfx
.insn
.value
= opcode
903 major
= pfx
.major
.asint(msb0
=True) # MSB0 inversion
904 log ("prefix test: opcode:", major
, bin(major
),
905 pfx
.insn
[7] == 0b1, pfx
.insn
[9] == 0b1)
906 self
.is_svp64_mode
= ((major
== 0b000001) and
907 pfx
.insn
[7].value
== 0b1 and
908 pfx
.insn
[9].value
== 0b1)
909 self
.pc
.update_nia(self
.is_svp64_mode
)
910 yield self
.dec2
.is_svp64_mode
.eq(self
.is_svp64_mode
) # set SVP64 decode
911 self
.namespace
['NIA'] = self
.pc
.NIA
912 self
.namespace
['SVSTATE'] = self
.svstate
.spr
913 if not self
.is_svp64_mode
:
916 # in SVP64 mode. decode/print out svp64 prefix, get v3.0B instruction
917 log ("svp64.rm", bin(pfx
.rm
.asint(msb0
=True)))
918 log (" svstate.vl", self
.svstate
.vl
.asint(msb0
=True))
919 log (" svstate.mvl", self
.svstate
.maxvl
.asint(msb0
=True))
920 sv_rm
= pfx
.rm
.asint(msb0
=True)
921 ins
= self
.imem
.ld(pc
+4, 4, False, True, instr_fetch
=True)
922 log(" svsetup: 0x%x 0x%x %s" % (pc
+4, ins
& 0xffffffff, bin(ins
)))
923 yield self
.dec2
.dec
.raw_opcode_in
.eq(ins
& 0xffffffff) # v3.0B suffix
924 yield self
.dec2
.sv_rm
.eq(sv_rm
) # svp64 prefix
927 def execute_one(self
):
928 """execute one instruction
930 # get the disassembly code for this instruction
931 if self
.is_svp64_mode
:
932 if not self
.disassembly
:
933 code
= yield from self
.get_assembly_name()
935 code
= self
.disassembly
[self
._pc
+4]
936 log(" svp64 sim-execute", hex(self
._pc
), code
)
938 if not self
.disassembly
:
939 code
= yield from self
.get_assembly_name()
941 code
= self
.disassembly
[self
._pc
]
942 log("sim-execute", hex(self
._pc
), code
)
943 opname
= code
.split(' ')[0]
945 yield from self
.call(opname
) # execute the instruction
946 except MemException
as e
: # check for memory errors
947 if e
.args
[0] != 'unaligned': # only doing aligned at the mo
948 raise e
# ... re-raise
949 # run a Trap but set DAR first
950 print ("memory unaligned exception, DAR", e
.dar
)
951 self
.spr
['DAR'] = SelectableInt(e
.dar
, 64)
952 self
.call_trap(0x600, PIb
.PRIV
) # 0x600, privileged
955 # don't use this except in special circumstances
956 if not self
.respect_pc
:
959 log("execute one, CIA NIA", self
.pc
.CIA
.value
, self
.pc
.NIA
.value
)
961 def get_assembly_name(self
):
962 # TODO, asmregs is from the spec, e.g. add RT,RA,RB
963 # see http://bugs.libre-riscv.org/show_bug.cgi?id=282
964 dec_insn
= yield self
.dec2
.e
.do
.insn
965 insn_1_11
= yield self
.dec2
.e
.do
.insn
[1:11]
966 asmcode
= yield self
.dec2
.dec
.op
.asmcode
967 int_op
= yield self
.dec2
.dec
.op
.internal_op
968 log("get assembly name asmcode", asmcode
, int_op
,
969 hex(dec_insn
), bin(insn_1_11
))
970 asmop
= insns
.get(asmcode
, None)
972 # sigh reconstruct the assembly instruction name
973 if hasattr(self
.dec2
.e
.do
, "oe"):
974 ov_en
= yield self
.dec2
.e
.do
.oe
.oe
975 ov_ok
= yield self
.dec2
.e
.do
.oe
.ok
979 if hasattr(self
.dec2
.e
.do
, "rc"):
980 rc_en
= yield self
.dec2
.e
.do
.rc
.rc
981 rc_ok
= yield self
.dec2
.e
.do
.rc
.ok
985 # grrrr have to special-case MUL op (see DecodeOE)
986 log("ov %d en %d rc %d en %d op %d" %
987 (ov_ok
, ov_en
, rc_ok
, rc_en
, int_op
))
988 if int_op
in [MicrOp
.OP_MUL_H64
.value
, MicrOp
.OP_MUL_H32
.value
]:
993 if not asmop
.endswith("."): # don't add "." to "andis."
996 if hasattr(self
.dec2
.e
.do
, "lk"):
997 lk
= yield self
.dec2
.e
.do
.lk
1000 log("int_op", int_op
)
1001 if int_op
in [MicrOp
.OP_B
.value
, MicrOp
.OP_BC
.value
]:
1002 AA
= yield self
.dec2
.dec
.fields
.FormI
.AA
[0:-1]
1006 spr_msb
= yield from self
.get_spr_msb()
1007 if int_op
== MicrOp
.OP_MFCR
.value
:
1012 # XXX TODO: for whatever weird reason this doesn't work
1013 # https://bugs.libre-soc.org/show_bug.cgi?id=390
1014 if int_op
== MicrOp
.OP_MTCRF
.value
:
1021 def get_spr_msb(self
):
1022 dec_insn
= yield self
.dec2
.e
.do
.insn
1023 return dec_insn
& (1 << 20) != 0 # sigh - XFF.spr[-1]?
1025 def call(self
, name
):
1026 """call(opcode) - the primary execution point for instructions
1028 self
.last_st_addr
= None # reset the last known store address
1029 self
.last_ld_addr
= None # etc.
1031 name
= name
.strip() # remove spaces if not already done so
1033 log("halted - not executing", name
)
1036 # TODO, asmregs is from the spec, e.g. add RT,RA,RB
1037 # see http://bugs.libre-riscv.org/show_bug.cgi?id=282
1038 asmop
= yield from self
.get_assembly_name()
1039 log("call", name
, asmop
)
1042 int_op
= yield self
.dec2
.dec
.op
.internal_op
1043 spr_msb
= yield from self
.get_spr_msb()
1045 instr_is_privileged
= False
1046 if int_op
in [MicrOp
.OP_ATTN
.value
,
1047 MicrOp
.OP_MFMSR
.value
,
1048 MicrOp
.OP_MTMSR
.value
,
1049 MicrOp
.OP_MTMSRD
.value
,
1051 MicrOp
.OP_RFID
.value
]:
1052 instr_is_privileged
= True
1053 if int_op
in [MicrOp
.OP_MFSPR
.value
,
1054 MicrOp
.OP_MTSPR
.value
] and spr_msb
:
1055 instr_is_privileged
= True
1057 log("is priv", instr_is_privileged
, hex(self
.msr
.value
),
1059 # check MSR priv bit and whether op is privileged: if so, throw trap
1060 if instr_is_privileged
and self
.msr
[MSRb
.PR
] == 1:
1061 self
.call_trap(0x700, PIb
.PRIV
)
1064 # check halted condition
1069 # check illegal instruction
1071 if name
not in ['mtcrf', 'mtocrf']:
1072 illegal
= name
!= asmop
1074 # sigh deal with setvl not being supported by binutils (.long)
1075 if asmop
.startswith('setvl'):
1079 # and svremap not being supported by binutils (.long)
1080 if asmop
.startswith('svremap'):
1084 # sigh also deal with ffmadds not being supported by binutils (.long)
1085 if asmop
== 'ffmadds':
1090 print("illegal", name
, asmop
)
1091 self
.call_trap(0x700, PIb
.ILLEG
)
1092 print("name %s != %s - calling ILLEGAL trap, PC: %x" %
1093 (name
, asmop
, self
.pc
.CIA
.value
))
1096 # nop has to be supported, we could let the actual op calculate
1097 # but PowerDecoder has a pattern for nop
1099 self
.update_pc_next()
1102 info
= self
.instrs
[name
]
1103 yield from self
.prep_namespace(info
.form
, info
.op_fields
)
1105 # preserve order of register names
1106 input_names
= create_args(list(info
.read_regs
) +
1107 list(info
.uninit_regs
))
1110 # get SVP64 entry for the current instruction
1111 sv_rm
= self
.svp64rm
.instrs
.get(name
)
1112 if sv_rm
is not None:
1113 dest_cr
, src_cr
, src_byname
, dest_byname
= decode_extra(sv_rm
)
1115 dest_cr
, src_cr
, src_byname
, dest_byname
= False, False, {}, {}
1116 log ("sv rm", sv_rm
, dest_cr
, src_cr
, src_byname
, dest_byname
)
1118 # get SVSTATE VL (oh and print out some debug stuff)
1119 if self
.is_svp64_mode
:
1120 vl
= self
.svstate
.vl
.asint(msb0
=True)
1121 srcstep
= self
.svstate
.srcstep
.asint(msb0
=True)
1122 dststep
= self
.svstate
.dststep
.asint(msb0
=True)
1123 sv_a_nz
= yield self
.dec2
.sv_a_nz
1124 fft_mode
= yield self
.dec2
.use_svp64_fft
1125 in1
= yield self
.dec2
.e
.read_reg1
.data
1126 log ("SVP64: VL, srcstep, dststep, sv_a_nz, in1 fft",
1127 vl
, srcstep
, dststep
, sv_a_nz
, in1
, fft_mode
)
1129 # get predicate mask
1130 srcmask
= dstmask
= 0xffff_ffff_ffff_ffff
1131 if self
.is_svp64_mode
:
1132 pmode
= yield self
.dec2
.rm_dec
.predmode
1133 reverse_gear
= yield self
.dec2
.rm_dec
.reverse_gear
1134 sv_ptype
= yield self
.dec2
.dec
.op
.SV_Ptype
1135 srcpred
= yield self
.dec2
.rm_dec
.srcpred
1136 dstpred
= yield self
.dec2
.rm_dec
.dstpred
1137 pred_src_zero
= yield self
.dec2
.rm_dec
.pred_sz
1138 pred_dst_zero
= yield self
.dec2
.rm_dec
.pred_dz
1139 if pmode
== SVP64PredMode
.INT
.value
:
1140 srcmask
= dstmask
= get_predint(self
.gpr
, dstpred
)
1141 if sv_ptype
== SVPtype
.P2
.value
:
1142 srcmask
= get_predint(self
.gpr
, srcpred
)
1143 elif pmode
== SVP64PredMode
.CR
.value
:
1144 srcmask
= dstmask
= get_predcr(self
.crl
, dstpred
, vl
)
1145 if sv_ptype
== SVPtype
.P2
.value
:
1146 srcmask
= get_predcr(self
.crl
, srcpred
, vl
)
1147 log (" pmode", pmode
)
1148 log (" reverse", reverse_gear
)
1149 log (" ptype", sv_ptype
)
1150 log (" srcpred", bin(srcpred
))
1151 log (" dstpred", bin(dstpred
))
1152 log (" srcmask", bin(srcmask
))
1153 log (" dstmask", bin(dstmask
))
1154 log (" pred_sz", bin(pred_src_zero
))
1155 log (" pred_dz", bin(pred_dst_zero
))
1157 # okaaay, so here we simply advance srcstep (TODO dststep)
1158 # until the predicate mask has a "1" bit... or we run out of VL
1159 # let srcstep==VL be the indicator to move to next instruction
1160 if not pred_src_zero
:
1161 while (((1<<srcstep
) & srcmask
) == 0) and (srcstep
!= vl
):
1162 log (" skip", bin(1<<srcstep
))
1165 if not pred_dst_zero
:
1166 while (((1<<dststep
) & dstmask
) == 0) and (dststep
!= vl
):
1167 log (" skip", bin(1<<dststep
))
1170 # now work out if the relevant mask bits require zeroing
1172 pred_dst_zero
= ((1<<dststep
) & dstmask
) == 0
1174 pred_src_zero
= ((1<<srcstep
) & srcmask
) == 0
1176 # update SVSTATE with new srcstep
1177 self
.svstate
.srcstep
[0:7] = srcstep
1178 self
.svstate
.dststep
[0:7] = dststep
1179 self
.namespace
['SVSTATE'] = self
.svstate
.spr
1180 yield self
.dec2
.state
.svstate
.eq(self
.svstate
.spr
.value
)
1181 yield Settle() # let decoder update
1182 srcstep
= self
.svstate
.srcstep
.asint(msb0
=True)
1183 dststep
= self
.svstate
.dststep
.asint(msb0
=True)
1184 log (" srcstep", srcstep
)
1185 log (" dststep", dststep
)
1187 # check if end reached (we let srcstep overrun, above)
1188 # nothing needs doing (TODO zeroing): just do next instruction
1189 if srcstep
== vl
or dststep
== vl
:
1190 self
.svp64_reset_loop()
1191 self
.update_pc_next()
1194 # VL=0 in SVP64 mode means "do nothing: skip instruction"
1195 if self
.is_svp64_mode
and vl
== 0:
1196 self
.pc
.update(self
.namespace
, self
.is_svp64_mode
)
1197 log("SVP64: VL=0, end of call", self
.namespace
['CIA'],
1198 self
.namespace
['NIA'])
1201 # for when SVSHAPE is active, a very bad hack here (to be replaced)
1202 # using pre-arranged schedule. all of this is awful but it is a
1203 # start. next job will be to put the proper activation in place
1204 yield self
.dec2
.remap_active
.eq(1 if self
.last_op_svshape
else 0)
1205 if self
.is_svp64_mode
and self
.last_op_svshape
:
1206 # get four SVSHAPEs. here we are hard-coding
1207 # SVSHAPE0 to FRT, SVSHAPE1 to FRA, SVSHAPE2 to FRC and
1208 # SVSHAPE3 to FRB, assuming "fmadd FRT, FRA, FRC, FRB."
1209 SVSHAPE0
= self
.spr
['SVSHAPE0']
1210 SVSHAPE1
= self
.spr
['SVSHAPE1']
1211 SVSHAPE2
= self
.spr
['SVSHAPE2']
1212 SVSHAPE3
= self
.spr
['SVSHAPE3']
1214 sname
= 'SVSHAPE%d' % i
1215 shape
= self
.spr
[sname
]
1216 print (sname
, bin(shape
.value
))
1217 print (" lims", shape
.lims
)
1218 print (" mode", shape
.mode
)
1219 print (" skip", shape
.skip
)
1221 remaps
= [(SVSHAPE0
, SVSHAPE0
.get_iterator()),
1222 (SVSHAPE1
, SVSHAPE1
.get_iterator()),
1223 (SVSHAPE2
, SVSHAPE2
.get_iterator()),
1224 (SVSHAPE3
, SVSHAPE3
.get_iterator()),
1227 for i
, (shape
, remap
) in enumerate(remaps
):
1228 # zero is "disabled"
1229 if shape
.value
== 0x0:
1231 # XXX hardcoded! pick dststep for out (i==0) else srcstep
1232 if shape
.mode
== 0b00: # multiply mode
1233 step
= dststep
if (i
== 0) else srcstep
1234 if shape
.mode
== 0b01: # FFT butterfly mode
1235 step
= srcstep
# XXX HACK - for now only use srcstep
1236 # this is terrible. O(N^2) looking for the match. but hey.
1237 for idx
, remap_idx
in enumerate(remap
):
1241 if shape
.mode
== 0b00:
1243 yield self
.dec2
.o_step
.eq(remap_idx
) # RT
1244 yield self
.dec2
.o2_step
.eq(remap_idx
) # EA
1246 yield self
.dec2
.in1_step
.eq(remap_idx
) # RA
1248 yield self
.dec2
.in3_step
.eq(remap_idx
) # RB
1250 yield self
.dec2
.in2_step
.eq(remap_idx
) # RC
1251 # FFT butterfly mode
1252 if shape
.mode
== 0b01:
1254 yield self
.dec2
.o_step
.eq(remap_idx
) # RT
1255 yield self
.dec2
.in1_step
.eq(remap_idx
) # RA
1257 yield self
.dec2
.in2_step
.eq(remap_idx
) # RB
1258 yield self
.dec2
.o2_step
.eq(remap_idx
) # EA (FRS)
1260 yield self
.dec2
.in3_step
.eq(remap_idx
) # RC
1263 rremaps
.append((shape
.mode
, i
, idx
, remap_idx
)) # debug printing
1265 print ("shape remap", x
)
1266 # after that, settle down (combinatorial) to let Vector reg numbers
1267 # work themselves out
1269 remap_active
= yield self
.dec2
.remap_active
1270 print ("remap active", remap_active
)
1272 # main input registers (RT, RA ...)
1274 for name
in input_names
:
1275 # using PowerDecoder2, first, find the decoder index.
1276 # (mapping name RA RB RC RS to in1, in2, in3)
1277 regnum
, is_vec
= yield from get_pdecode_idx_in(self
.dec2
, name
)
1279 # doing this is not part of svp64, it's because output
1280 # registers, to be modified, need to be in the namespace.
1281 regnum
, is_vec
= yield from get_pdecode_idx_out(self
.dec2
, name
)
1283 regnum
, is_vec
= yield from get_pdecode_idx_out2(self
.dec2
,
1286 # in case getting the register number is needed, _RA, _RB
1287 regname
= "_" + name
1288 self
.namespace
[regname
] = regnum
1289 if not self
.is_svp64_mode
or not pred_src_zero
:
1290 log('reading reg %s %s' % (name
, str(regnum
)), is_vec
)
1292 reg_val
= self
.fpr(regnum
)
1294 reg_val
= self
.gpr(regnum
)
1296 log('zero input reg %s %s' % (name
, str(regnum
)), is_vec
)
1298 inputs
.append(reg_val
)
1300 # in SVP64 mode for LD/ST work out immediate
1301 # XXX TODO: replace_ds for DS-Form rather than D-Form.
1302 # use info.form to detect
1303 replace_d
= False # update / replace constant in pseudocode
1304 if self
.is_svp64_mode
:
1305 ldstmode
= yield self
.dec2
.rm_dec
.ldstmode
1306 # bitreverse mode reads SVD (or SVDS - TODO)
1307 # *BUT*... because this is "overloading" of LD operations,
1308 # it gets *STORED* into D (or DS, TODO)
1309 if ldstmode
== SVP64LDSTmode
.BITREVERSE
.value
:
1310 imm
= yield self
.dec2
.dec
.fields
.FormSVD
.SVD
[0:11]
1311 imm
= exts(imm
, 11) # sign-extend to integer
1312 print ("bitrev SVD", imm
)
1315 imm
= yield self
.dec2
.dec
.fields
.FormD
.D
[0:16]
1316 imm
= exts(imm
, 16) # sign-extend to integer
1317 # get the right step. LD is from srcstep, ST is dststep
1318 op
= yield self
.dec2
.e
.do
.insn_type
1320 if op
== MicrOp
.OP_LOAD
.value
:
1322 log("D-field src", imm
, offsmul
)
1323 elif op
== MicrOp
.OP_STORE
.value
:
1325 log("D-field dst", imm
, offsmul
)
1327 if ldstmode
== SVP64LDSTmode
.BITREVERSE
.value
:
1328 # manually look up RC, sigh
1329 RC
= yield self
.dec2
.dec
.RC
[0:5]
1331 log ("RC", RC
.value
, "imm", imm
, "offs", bin(offsmul
),
1332 "rev", bin(bitrev(offsmul
, vl
)))
1333 imm
= SelectableInt((imm
* bitrev(offsmul
, vl
)) << RC
.value
, 32)
1334 # Unit-Strided LD/ST adds offset*width to immediate
1335 elif ldstmode
== SVP64LDSTmode
.UNITSTRIDE
.value
:
1336 ldst_len
= yield self
.dec2
.e
.do
.data_len
1337 imm
= SelectableInt(imm
+ offsmul
* ldst_len
, 32)
1339 # Element-strided multiplies the immediate by element step
1340 elif ldstmode
== SVP64LDSTmode
.ELSTRIDE
.value
:
1341 imm
= SelectableInt(imm
* offsmul
, 32)
1343 ldst_ra_vec
= yield self
.dec2
.rm_dec
.ldst_ra_vec
1344 ldst_imz_in
= yield self
.dec2
.rm_dec
.ldst_imz_in
1345 log("LDSTmode", ldstmode
, SVP64LDSTmode
.BITREVERSE
.value
,
1346 offsmul
, imm
, ldst_ra_vec
, ldst_imz_in
)
1349 self
.namespace
['D'] = imm
1351 # "special" registers
1352 for special
in info
.special_regs
:
1353 if special
in special_sprs
:
1354 inputs
.append(self
.spr
[special
])
1356 inputs
.append(self
.namespace
[special
])
1358 # clear trap (trap) NIA
1359 self
.trap_nia
= None
1361 # execute actual instruction here (finally)
1362 log("inputs", inputs
)
1363 results
= info
.func(self
, *inputs
)
1364 log("results", results
)
1366 # "inject" decorator takes namespace from function locals: we need to
1367 # overwrite NIA being overwritten (sigh)
1368 if self
.trap_nia
is not None:
1369 self
.namespace
['NIA'] = self
.trap_nia
1371 log("after func", self
.namespace
['CIA'], self
.namespace
['NIA'])
1373 # check if op was a LD/ST so that debugging can check the
1375 if int_op
in [MicrOp
.OP_STORE
.value
,
1377 self
.last_st_addr
= self
.mem
.last_st_addr
1378 if int_op
in [MicrOp
.OP_LOAD
.value
,
1380 self
.last_ld_addr
= self
.mem
.last_ld_addr
1381 log ("op", int_op
, MicrOp
.OP_STORE
.value
, MicrOp
.OP_LOAD
.value
,
1382 self
.last_st_addr
, self
.last_ld_addr
)
1384 # detect if CA/CA32 already in outputs (sra*, basically)
1387 output_names
= create_args(info
.write_regs
)
1388 for name
in output_names
:
1394 log("carry already done?", bin(already_done
))
1395 if hasattr(self
.dec2
.e
.do
, "output_carry"):
1396 carry_en
= yield self
.dec2
.e
.do
.output_carry
1400 yield from self
.handle_carry_(inputs
, results
, already_done
)
1402 if not self
.is_svp64_mode
: # yeah just no. not in parallel processing
1403 # detect if overflow was in return result
1406 for name
, output
in zip(output_names
, results
):
1407 if name
== 'overflow':
1410 if hasattr(self
.dec2
.e
.do
, "oe"):
1411 ov_en
= yield self
.dec2
.e
.do
.oe
.oe
1412 ov_ok
= yield self
.dec2
.e
.do
.oe
.ok
1416 log("internal overflow", overflow
, ov_en
, ov_ok
)
1418 yield from self
.handle_overflow(inputs
, results
, overflow
)
1420 # only do SVP64 dest predicated Rc=1 if dest-pred is not enabled
1422 if not self
.is_svp64_mode
or not pred_dst_zero
:
1423 if hasattr(self
.dec2
.e
.do
, "rc"):
1424 rc_en
= yield self
.dec2
.e
.do
.rc
.rc
1426 regnum
, is_vec
= yield from get_pdecode_cr_out(self
.dec2
, "CR0")
1427 self
.handle_comparison(results
, regnum
)
1429 # any modified return results?
1431 for name
, output
in zip(output_names
, results
):
1432 if name
== 'overflow': # ignore, done already (above)
1434 if isinstance(output
, int):
1435 output
= SelectableInt(output
, 256)
1436 if name
in ['CA', 'CA32']:
1438 log("writing %s to XER" % name
, output
)
1439 self
.spr
['XER'][XER_bits
[name
]] = output
.value
1441 log("NOT writing %s to XER" % name
, output
)
1442 elif name
in info
.special_regs
:
1443 log('writing special %s' % name
, output
, special_sprs
)
1444 if name
in special_sprs
:
1445 self
.spr
[name
] = output
1447 self
.namespace
[name
].eq(output
)
1449 log('msr written', hex(self
.msr
.value
))
1451 regnum
, is_vec
= yield from get_pdecode_idx_out(self
.dec2
,
1454 regnum
, is_vec
= yield from get_pdecode_idx_out2(
1457 # temporary hack for not having 2nd output
1458 regnum
= yield getattr(self
.decoder
, name
)
1460 if self
.is_svp64_mode
and pred_dst_zero
:
1461 log('zeroing reg %d %s' % (regnum
, str(output
)),
1463 output
= SelectableInt(0, 256)
1469 log('writing %s %s %s' % (regnum
, ftype
, str(output
)),
1471 if output
.bits
> 64:
1472 output
= SelectableInt(output
.value
, 64)
1474 self
.fpr
[regnum
] = output
1476 self
.gpr
[regnum
] = output
1478 # check if it is the SVSTATE.src/dest step that needs incrementing
1479 # this is our Sub-Program-Counter loop from 0 to VL-1
1480 if self
.is_svp64_mode
:
1481 # XXX twin predication TODO
1482 vl
= self
.svstate
.vl
.asint(msb0
=True)
1483 mvl
= self
.svstate
.maxvl
.asint(msb0
=True)
1484 srcstep
= self
.svstate
.srcstep
.asint(msb0
=True)
1485 dststep
= self
.svstate
.dststep
.asint(msb0
=True)
1486 rm_mode
= yield self
.dec2
.rm_dec
.mode
1487 reverse_gear
= yield self
.dec2
.rm_dec
.reverse_gear
1488 sv_ptype
= yield self
.dec2
.dec
.op
.SV_Ptype
1489 out_vec
= not (yield self
.dec2
.no_out_vec
)
1490 in_vec
= not (yield self
.dec2
.no_in_vec
)
1491 log (" svstate.vl", vl
)
1492 log (" svstate.mvl", mvl
)
1493 log (" svstate.srcstep", srcstep
)
1494 log (" svstate.dststep", dststep
)
1495 log (" mode", rm_mode
)
1496 log (" reverse", reverse_gear
)
1497 log (" out_vec", out_vec
)
1498 log (" in_vec", in_vec
)
1499 log (" sv_ptype", sv_ptype
, sv_ptype
== SVPtype
.P2
.value
)
1500 # check if srcstep needs incrementing by one, stop PC advancing
1501 # svp64 loop can end early if the dest is scalar for single-pred
1502 # but for 2-pred both src/dest have to be checked.
1503 # XXX this might not be true! it may just be LD/ST
1504 if sv_ptype
== SVPtype
.P2
.value
:
1505 svp64_is_vector
= (out_vec
or in_vec
)
1507 svp64_is_vector
= out_vec
1508 if svp64_is_vector
and srcstep
!= vl
-1 and dststep
!= vl
-1:
1509 self
.svstate
.srcstep
+= SelectableInt(1, 7)
1510 self
.svstate
.dststep
+= SelectableInt(1, 7)
1511 self
.pc
.NIA
.value
= self
.pc
.CIA
.value
1512 self
.namespace
['NIA'] = self
.pc
.NIA
1513 self
.namespace
['SVSTATE'] = self
.svstate
.spr
1514 log("end of sub-pc call", self
.namespace
['CIA'],
1515 self
.namespace
['NIA'])
1516 return # DO NOT allow PC to update whilst Sub-PC loop running
1517 # reset loop to zero
1518 self
.svp64_reset_loop()
1520 # XXX only in non-SVP64 mode!
1521 # record state of whether the current operation was an svshape,
1522 # to be able to know if it should apply in the next instruction.
1523 # also (if going to use this instruction) should disable ability
1524 # to interrupt in between. sigh.
1525 self
.last_op_svshape
= asmop
== 'svremap'
1527 self
.update_pc_next()
1529 def update_pc_next(self
):
1530 # UPDATE program counter
1531 self
.pc
.update(self
.namespace
, self
.is_svp64_mode
)
1532 self
.svstate
.spr
= self
.namespace
['SVSTATE']
1533 log("end of call", self
.namespace
['CIA'],
1534 self
.namespace
['NIA'],
1535 self
.namespace
['SVSTATE'])
1537 def svp64_reset_loop(self
):
1538 self
.svstate
.srcstep
[0:7] = 0
1539 self
.svstate
.dststep
[0:7] = 0
1540 log (" svstate.srcstep loop end (PC to update)")
1541 self
.pc
.update_nia(self
.is_svp64_mode
)
1542 self
.namespace
['NIA'] = self
.pc
.NIA
1543 self
.namespace
['SVSTATE'] = self
.svstate
.spr
1547 """Decorator factory.
1549 this decorator will "inject" variables into the function's namespace,
1550 from the *dictionary* in self.namespace. it therefore becomes possible
1551 to make it look like a whole stack of variables which would otherwise
1552 need "self." inserted in front of them (*and* for those variables to be
1553 added to the instance) "appear" in the function.
1555 "self.namespace['SI']" for example becomes accessible as just "SI" but
1556 *only* inside the function, when decorated.
1558 def variable_injector(func
):
1560 def decorator(*args
, **kwargs
):
1562 func_globals
= func
.__globals
__ # Python 2.6+
1563 except AttributeError:
1564 func_globals
= func
.func_globals
# Earlier versions.
1566 context
= args
[0].namespace
# variables to be injected
1567 saved_values
= func_globals
.copy() # Shallow copy of dict.
1568 func_globals
.update(context
)
1569 result
= func(*args
, **kwargs
)
1570 log("globals after", func_globals
['CIA'], func_globals
['NIA'])
1571 log("args[0]", args
[0].namespace
['CIA'],
1572 args
[0].namespace
['NIA'],
1573 args
[0].namespace
['SVSTATE'])
1574 args
[0].namespace
= func_globals
1575 #exec (func.__code__, func_globals)
1578 # func_globals = saved_values # Undo changes.
1584 return variable_injector