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
)
32 from openpower
.consts
import PIb
, MSRb
# big-endian (PowerISA versions)
33 from openpower
.consts
import (SVP64MODE
,
36 from openpower
.decoder
.power_svp64
import SVP64RM
, decode_extra
38 from openpower
.decoder
.isa
.radixmmu
import RADIX
39 from openpower
.decoder
.isa
.mem
import Mem
, swap_order
, MemException
40 from openpower
.decoder
.isa
.svshape
import SVSHAPE
41 from openpower
.decoder
.isa
.svstate
import SVP64State
44 from openpower
.util
import log
46 from collections
import namedtuple
50 instruction_info
= namedtuple('instruction_info',
51 'func read_regs uninit_regs write_regs ' +
52 'special_regs op_fields form asmregs')
63 # TODO (lkcl): adjust other registers that should be in a particular order
64 # probably CA, CA32, and CR
89 "overflow": 7, # should definitely be last
92 fregs
= ['FRA', 'FRB', 'FRC', 'FRS', 'FRT']
95 def create_args(reglist
, extra
=None):
96 retval
= list(OrderedSet(reglist
))
97 retval
.sort(key
=lambda reg
: REG_SORT_ORDER
.get(reg
, 0))
99 return [extra
] + retval
105 def __init__(self
, decoder
, isacaller
, svstate
, regfile
):
108 self
.isacaller
= isacaller
109 self
.svstate
= svstate
110 for i
in range(len(regfile
)):
111 self
[i
] = SelectableInt(regfile
[i
], 64)
113 def __call__(self
, ridx
):
114 if isinstance(ridx
, SelectableInt
):
118 def set_form(self
, form
):
121 def __setitem__(self
, rnum
, value
):
122 # rnum = rnum.value # only SelectableInt allowed
123 log("GPR setitem", rnum
, value
)
124 if isinstance(rnum
, SelectableInt
):
126 dict.__setitem
__(self
, rnum
, value
)
128 def getz(self
, rnum
):
129 # rnum = rnum.value # only SelectableInt allowed
130 log("GPR getzero?", rnum
)
132 return SelectableInt(0, 64)
135 def _get_regnum(self
, attr
):
136 getform
= self
.sd
.sigforms
[self
.form
]
137 rnum
= getattr(getform
, attr
)
140 def ___getitem__(self
, attr
):
141 """ XXX currently not used
143 rnum
= self
._get
_regnum
(attr
)
144 log("GPR getitem", attr
, rnum
)
145 return self
.regfile
[rnum
]
147 def dump(self
, printout
=True):
149 for i
in range(len(self
)):
150 res
.append(self
[i
].value
)
152 for i
in range(0, len(res
), 8):
155 s
.append("%08x" % res
[i
+j
])
157 print("reg", "%2d" % i
, s
)
162 def __init__(self
, dec2
, initial_sprs
={}):
165 for key
, v
in initial_sprs
.items():
166 if isinstance(key
, SelectableInt
):
168 key
= special_sprs
.get(key
, key
)
169 if isinstance(key
, int):
172 info
= spr_byname
[key
]
173 if not isinstance(v
, SelectableInt
):
174 v
= SelectableInt(v
, info
.length
)
177 def __getitem__(self
, key
):
179 log("dict", self
.items())
180 # if key in special_sprs get the special spr, otherwise return key
181 if isinstance(key
, SelectableInt
):
183 if isinstance(key
, int):
184 key
= spr_dict
[key
].SPR
185 key
= special_sprs
.get(key
, key
)
186 if key
== 'HSRR0': # HACK!
188 if key
== 'HSRR1': # HACK!
191 res
= dict.__getitem
__(self
, key
)
193 if isinstance(key
, int):
196 info
= spr_byname
[key
]
197 dict.__setitem
__(self
, key
, SelectableInt(0, info
.length
))
198 res
= dict.__getitem
__(self
, key
)
199 log("spr returning", key
, res
)
202 def __setitem__(self
, key
, value
):
203 if isinstance(key
, SelectableInt
):
205 if isinstance(key
, int):
206 key
= spr_dict
[key
].SPR
208 key
= special_sprs
.get(key
, key
)
209 if key
== 'HSRR0': # HACK!
210 self
.__setitem
__('SRR0', value
)
211 if key
== 'HSRR1': # HACK!
212 self
.__setitem
__('SRR1', value
)
213 log("setting spr", key
, value
)
214 dict.__setitem
__(self
, key
, value
)
216 def __call__(self
, ridx
):
219 def dump(self
, printout
=True):
221 keys
= list(self
.keys())
224 sprname
= spr_dict
.get(k
, None)
228 sprname
= sprname
.SPR
229 res
.append((sprname
, self
[k
].value
))
231 for sprname
, value
in res
:
232 print(" ", sprname
, hex(value
))
237 def __init__(self
, pc_init
=0):
238 self
.CIA
= SelectableInt(pc_init
, 64)
239 self
.NIA
= self
.CIA
+ SelectableInt(4, 64) # only true for v3.0B!
241 def update_nia(self
, is_svp64
):
242 increment
= 8 if is_svp64
else 4
243 self
.NIA
= self
.CIA
+ SelectableInt(increment
, 64)
245 def update(self
, namespace
, is_svp64
):
246 """updates the program counter (PC) by 4 if v3.0B mode or 8 if SVP64
248 self
.CIA
= namespace
['NIA'].narrow(64)
249 self
.update_nia(is_svp64
)
250 namespace
['CIA'] = self
.CIA
251 namespace
['NIA'] = self
.NIA
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
,
484 if out_sel
== OutSel
.RT
.value
:
486 elif name
== 'RT_OR_ZERO':
487 log ("get_pdecode_idx_out", out_sel
, OutSel
.RT
.value
,
488 OutSel
.RT_OR_ZERO
.value
, out
, o_isvec
,
490 if out_sel
== OutSel
.RT_OR_ZERO
.value
:
493 log ("get_pdecode_idx_out", out_sel
, OutSel
.FRA
.value
, out
, o_isvec
)
494 if out_sel
== OutSel
.FRA
.value
:
497 log ("get_pdecode_idx_out", out_sel
, OutSel
.FRT
.value
,
498 OutSel
.FRT
.value
, out
, o_isvec
)
499 if out_sel
== OutSel
.FRT
.value
:
501 log ("get_pdecode_idx_out not found", name
, out_sel
, out
, o_isvec
)
505 # TODO, really should just be using PowerDecoder2
506 def get_pdecode_idx_out2(dec2
, name
):
507 # check first if register is activated for write
509 out_sel
= yield op
.out_sel
510 out
= yield dec2
.e
.write_ea
.data
511 o_isvec
= yield dec2
.o2_isvec
512 out_ok
= yield dec2
.e
.write_ea
.ok
513 log ("get_pdecode_idx_out2", name
, out_sel
, out
, out_ok
, o_isvec
)
518 if hasattr(op
, "upd"):
519 # update mode LD/ST uses read-reg A also as an output
521 log ("get_pdecode_idx_out2", upd
, LDSTMode
.update
.value
,
522 out_sel
, OutSel
.RA
.value
,
524 if upd
== LDSTMode
.update
.value
:
527 int_op
= yield dec2
.dec
.op
.internal_op
528 fft_en
= yield dec2
.use_svp64_fft
529 #if int_op == MicrOp.OP_FP_MADD.value and fft_en:
531 log ("get_pdecode_idx_out2", out_sel
, OutSel
.FRS
.value
,
538 # decoder2 - an instance of power_decoder2
539 # regfile - a list of initial values for the registers
540 # initial_{etc} - initial values for SPRs, Condition Register, Mem, MSR
541 # respect_pc - tracks the program counter. requires initial_insns
542 def __init__(self
, decoder2
, regfile
, initial_sprs
=None, initial_cr
=0,
543 initial_mem
=None, initial_msr
=0,
554 self
.bigendian
= bigendian
556 self
.is_svp64_mode
= False
557 self
.respect_pc
= respect_pc
558 if initial_sprs
is None:
560 if initial_mem
is None:
562 if fpregfile
is None:
564 if initial_insns
is None:
566 assert self
.respect_pc
== False, "instructions required to honor pc"
568 log("ISACaller insns", respect_pc
, initial_insns
, disassembly
)
569 log("ISACaller initial_msr", initial_msr
)
571 # "fake program counter" mode (for unit testing)
575 if isinstance(initial_mem
, tuple):
576 self
.fake_pc
= initial_mem
[0]
577 disasm_start
= self
.fake_pc
579 disasm_start
= initial_pc
581 # disassembly: we need this for now (not given from the decoder)
582 self
.disassembly
= {}
584 for i
, code
in enumerate(disassembly
):
585 self
.disassembly
[i
*4 + disasm_start
] = code
587 # set up registers, instruction memory, data memory, PC, SPRs, MSR, CR
588 self
.svp64rm
= SVP64RM()
589 if initial_svstate
is None:
591 if isinstance(initial_svstate
, int):
592 initial_svstate
= SVP64State(initial_svstate
)
593 # SVSTATE, MSR and PC
594 self
.svstate
= initial_svstate
595 self
.msr
= SelectableInt(initial_msr
, 64) # underlying reg
597 # GPR FPR SPR registers
598 self
.gpr
= GPR(decoder2
, self
, self
.svstate
, regfile
)
599 self
.fpr
= GPR(decoder2
, self
, self
.svstate
, fpregfile
)
600 self
.spr
= SPR(decoder2
, initial_sprs
) # initialise SPRs before MMU
602 # set up 4 dummy SVSHAPEs if they aren't already set up
604 sname
= 'SVSHAPE%d' % i
605 if sname
not in self
.spr
:
606 self
.spr
[sname
] = SVSHAPE(0)
608 # make sure it's an SVSHAPE
609 val
= self
.spr
[sname
].value
610 self
.spr
[sname
] = SVSHAPE(val
)
611 self
.last_op_svshape
= False
614 self
.mem
= Mem(row_bytes
=8, initial_mem
=initial_mem
)
615 self
.imem
= Mem(row_bytes
=4, initial_mem
=initial_insns
)
616 # MMU mode, redirect underlying Mem through RADIX
618 self
.mem
= RADIX(self
.mem
, self
)
620 self
.imem
= RADIX(self
.imem
, self
)
623 # FPR (same as GPR except for FP nums)
624 # 4.2.2 p124 FPSCR (definitely "separate" - not in SPR)
625 # note that mffs, mcrfs, mtfsf "manage" this FPSCR
626 # 2.3.1 CR (and sub-fields CR0..CR6 - CR0 SO comes from XER.SO)
627 # note that mfocrf, mfcr, mtcr, mtocrf, mcrxrx "manage" CRs
629 # 2.3.2 LR (actually SPR #8) -- Done
630 # 2.3.3 CTR (actually SPR #9) -- Done
631 # 2.3.4 TAR (actually SPR #815)
632 # 3.2.2 p45 XER (actually SPR #1) -- Done
633 # 3.2.3 p46 p232 VRSAVE (actually SPR #256)
635 # create CR then allow portions of it to be "selectable" (below)
636 self
.cr_fields
= CRFields(initial_cr
)
637 self
.cr
= self
.cr_fields
.cr
639 # "undefined", just set to variable-bit-width int (use exts "max")
640 #self.undefined = SelectableInt(0, 256) # TODO, not hard-code 256!
643 self
.namespace
.update(self
.spr
)
644 self
.namespace
.update({'GPR': self
.gpr
,
648 'memassign': self
.memassign
,
651 'SVSTATE': self
.svstate
,
652 'SVSHAPE0': self
.spr
['SVSHAPE0'],
653 'SVSHAPE1': self
.spr
['SVSHAPE1'],
654 'SVSHAPE2': self
.spr
['SVSHAPE2'],
655 'SVSHAPE3': self
.spr
['SVSHAPE3'],
658 'undefined': undefined
,
659 'mode_is_64bit': True,
663 # update pc to requested start point
664 self
.set_pc(initial_pc
)
666 # field-selectable versions of Condition Register
667 self
.crl
= self
.cr_fields
.crl
669 self
.namespace
["CR%d" % i
] = self
.crl
[i
]
671 self
.decoder
= decoder2
.dec
674 def call_trap(self
, trap_addr
, trap_bit
):
675 """calls TRAP and sets up NIA to the new execution location.
676 next instruction will begin at trap_addr.
678 self
.TRAP(trap_addr
, trap_bit
)
679 self
.namespace
['NIA'] = self
.trap_nia
680 self
.pc
.update(self
.namespace
, self
.is_svp64_mode
)
682 def TRAP(self
, trap_addr
=0x700, trap_bit
=PIb
.TRAP
):
683 """TRAP> saves PC, MSR (and TODO SVSTATE), and updates MSR
685 TRAP function is callable from inside the pseudocode itself,
686 hence the default arguments. when calling from inside ISACaller
687 it is best to use call_trap()
689 log("TRAP:", hex(trap_addr
), hex(self
.namespace
['MSR'].value
))
690 # store CIA(+4?) in SRR0, set NIA to 0x700
691 # store MSR in SRR1, set MSR to um errr something, have to check spec
692 # store SVSTATE (if enabled) in SVSRR0
693 self
.spr
['SRR0'].value
= self
.pc
.CIA
.value
694 self
.spr
['SRR1'].value
= self
.namespace
['MSR'].value
695 if self
.is_svp64_mode
:
696 self
.spr
['SVSRR0'] = self
.namespace
['SVSTATE'].value
697 self
.trap_nia
= SelectableInt(trap_addr
, 64)
698 self
.spr
['SRR1'][trap_bit
] = 1 # change *copy* of MSR in SRR1
700 # set exception bits. TODO: this should, based on the address
701 # in figure 66 p1065 V3.0B and the table figure 65 p1063 set these
702 # bits appropriately. however it turns out that *for now* in all
703 # cases (all trap_addrs) the exact same thing is needed.
704 self
.msr
[MSRb
.IR
] = 0
705 self
.msr
[MSRb
.DR
] = 0
706 self
.msr
[MSRb
.FE0
] = 0
707 self
.msr
[MSRb
.FE1
] = 0
708 self
.msr
[MSRb
.EE
] = 0
709 self
.msr
[MSRb
.RI
] = 0
710 self
.msr
[MSRb
.SF
] = 1
711 self
.msr
[MSRb
.TM
] = 0
712 self
.msr
[MSRb
.VEC
] = 0
713 self
.msr
[MSRb
.VSX
] = 0
714 self
.msr
[MSRb
.PR
] = 0
715 self
.msr
[MSRb
.FP
] = 0
716 self
.msr
[MSRb
.PMM
] = 0
717 self
.msr
[MSRb
.TEs
] = 0
718 self
.msr
[MSRb
.TEe
] = 0
719 self
.msr
[MSRb
.UND
] = 0
720 self
.msr
[MSRb
.LE
] = 1
722 def memassign(self
, ea
, sz
, val
):
723 self
.mem
.memassign(ea
, sz
, val
)
725 def prep_namespace(self
, insn_name
, formname
, op_fields
):
726 # TODO: get field names from form in decoder*1* (not decoder2)
727 # decoder2 is hand-created, and decoder1.sigform is auto-generated
729 # then "yield" fields only from op_fields rather than hard-coded
731 fields
= self
.decoder
.sigforms
[formname
]
732 log("prep_namespace", formname
, op_fields
)
733 for name
in op_fields
:
735 sig
= getattr(fields
, name
.upper())
737 sig
= getattr(fields
, name
)
739 # these are all opcode fields involved in index-selection of CR,
740 # and need to do "standard" arithmetic. CR[BA+32] for example
741 # would, if using SelectableInt, only be 5-bit.
742 if name
in ['BF', 'BFA', 'BC', 'BA', 'BB', 'BT', 'BI']:
743 self
.namespace
[name
] = val
745 self
.namespace
[name
] = SelectableInt(val
, sig
.width
)
747 self
.namespace
['XER'] = self
.spr
['XER']
748 self
.namespace
['CA'] = self
.spr
['XER'][XER_bits
['CA']].value
749 self
.namespace
['CA32'] = self
.spr
['XER'][XER_bits
['CA32']].value
751 # add some SVSTATE convenience variables
753 srcstep
= self
.svstate
.srcstep
754 self
.namespace
['VL'] = vl
755 self
.namespace
['srcstep'] = srcstep
757 # sv.bc* need some extra fields
758 if self
.is_svp64_mode
and insn_name
.startswith("sv.bc"):
759 # blegh grab bits manually
760 mode
= yield self
.dec2
.rm_dec
.rm_in
.mode
761 bc_vlset
= (mode
& SVP64MODE
.BC_VLSET
) != 0
762 bc_vli
= (mode
& SVP64MODE
.BC_VLI
) != 0
763 bc_snz
= (mode
& SVP64MODE
.BC_SNZ
) != 0
764 bc_vsb
= yield self
.dec2
.rm_dec
.bc_vsb
765 bc_lru
= yield self
.dec2
.rm_dec
.bc_lru
766 sz
= yield self
.dec2
.rm_dec
.pred_sz
767 self
.namespace
['VSb'] = SelectableInt(bc_vsb
, 1)
768 self
.namespace
['LRu'] = SelectableInt(bc_lru
, 1)
769 self
.namespace
['VLSET'] = SelectableInt(bc_vlset
, 1)
770 self
.namespace
['VLI'] = SelectableInt(bc_vli
, 1)
771 self
.namespace
['sz'] = SelectableInt(sz
, 1)
772 self
.namespace
['SNZ'] = SelectableInt(bc_snz
, 1)
774 def handle_carry_(self
, inputs
, outputs
, already_done
):
775 inv_a
= yield self
.dec2
.e
.do
.invert_in
777 inputs
[0] = ~inputs
[0]
779 imm_ok
= yield self
.dec2
.e
.do
.imm_data
.ok
781 imm
= yield self
.dec2
.e
.do
.imm_data
.data
782 inputs
.append(SelectableInt(imm
, 64))
783 assert len(outputs
) >= 1
784 log("outputs", repr(outputs
))
785 if isinstance(outputs
, list) or isinstance(outputs
, tuple):
791 log("gt input", x
, output
)
792 gt
= (gtu(x
, output
))
795 cy
= 1 if any(gts
) else 0
797 if not (1 & already_done
):
798 self
.spr
['XER'][XER_bits
['CA']] = cy
800 log("inputs", already_done
, inputs
)
802 # ARGH... different for OP_ADD... *sigh*...
803 op
= yield self
.dec2
.e
.do
.insn_type
804 if op
== MicrOp
.OP_ADD
.value
:
805 res32
= (output
.value
& (1 << 32)) != 0
806 a32
= (inputs
[0].value
& (1 << 32)) != 0
808 b32
= (inputs
[1].value
& (1 << 32)) != 0
811 cy32
= res32 ^ a32 ^ b32
812 log("CA32 ADD", cy32
)
816 log("input", x
, output
)
817 log(" x[32:64]", x
, x
[32:64])
818 log(" o[32:64]", output
, output
[32:64])
819 gt
= (gtu(x
[32:64], output
[32:64])) == SelectableInt(1, 1)
821 cy32
= 1 if any(gts
) else 0
822 log("CA32", cy32
, gts
)
823 if not (2 & already_done
):
824 self
.spr
['XER'][XER_bits
['CA32']] = cy32
826 def handle_overflow(self
, inputs
, outputs
, div_overflow
):
827 if hasattr(self
.dec2
.e
.do
, "invert_in"):
828 inv_a
= yield self
.dec2
.e
.do
.invert_in
830 inputs
[0] = ~inputs
[0]
832 imm_ok
= yield self
.dec2
.e
.do
.imm_data
.ok
834 imm
= yield self
.dec2
.e
.do
.imm_data
.data
835 inputs
.append(SelectableInt(imm
, 64))
836 assert len(outputs
) >= 1
837 log("handle_overflow", inputs
, outputs
, div_overflow
)
838 if len(inputs
) < 2 and div_overflow
is None:
841 # div overflow is different: it's returned by the pseudo-code
842 # because it's more complex than can be done by analysing the output
843 if div_overflow
is not None:
844 ov
, ov32
= div_overflow
, div_overflow
845 # arithmetic overflow can be done by analysing the input and output
846 elif len(inputs
) >= 2:
850 input_sgn
= [exts(x
.value
, x
.bits
) < 0 for x
in inputs
]
851 output_sgn
= exts(output
.value
, output
.bits
) < 0
852 ov
= 1 if input_sgn
[0] == input_sgn
[1] and \
853 output_sgn
!= input_sgn
[0] else 0
856 input32_sgn
= [exts(x
.value
, 32) < 0 for x
in inputs
]
857 output32_sgn
= exts(output
.value
, 32) < 0
858 ov32
= 1 if input32_sgn
[0] == input32_sgn
[1] and \
859 output32_sgn
!= input32_sgn
[0] else 0
861 self
.spr
['XER'][XER_bits
['OV']] = ov
862 self
.spr
['XER'][XER_bits
['OV32']] = ov32
863 so
= self
.spr
['XER'][XER_bits
['SO']]
865 self
.spr
['XER'][XER_bits
['SO']] = so
867 def handle_comparison(self
, outputs
, cr_idx
=0):
869 assert isinstance(out
, SelectableInt
), \
870 "out zero not a SelectableInt %s" % repr(outputs
)
871 log("handle_comparison", out
.bits
, hex(out
.value
))
872 # TODO - XXX *processor* in 32-bit mode
873 # https://bugs.libre-soc.org/show_bug.cgi?id=424
875 # o32 = exts(out.value, 32)
876 # print ("handle_comparison exts 32 bit", hex(o32))
877 out
= exts(out
.value
, out
.bits
)
878 log("handle_comparison exts", hex(out
))
879 zero
= SelectableInt(out
== 0, 1)
880 positive
= SelectableInt(out
> 0, 1)
881 negative
= SelectableInt(out
< 0, 1)
882 SO
= self
.spr
['XER'][XER_bits
['SO']]
883 log("handle_comparison SO", SO
)
884 cr_field
= selectconcat(negative
, positive
, zero
, SO
)
885 log("handle_comparison cr_field", self
.cr
, cr_idx
, cr_field
)
886 self
.crl
[cr_idx
].eq(cr_field
)
888 def set_pc(self
, pc_val
):
889 self
.namespace
['NIA'] = SelectableInt(pc_val
, 64)
890 self
.pc
.update(self
.namespace
, self
.is_svp64_mode
)
892 def get_next_insn(self
):
896 pc
= self
.pc
.CIA
.value
899 ins
= self
.imem
.ld(pc
, 4, False, True, instr_fetch
=True)
901 raise KeyError("no instruction at 0x%x" % pc
)
905 """set up one instruction
907 pc
, insn
= self
.get_next_insn()
908 yield from self
.setup_next_insn(pc
, insn
)
910 def setup_next_insn(self
, pc
, ins
):
911 """set up next instruction
914 log("setup: 0x%x 0x%x %s" % (pc
, ins
& 0xffffffff, bin(ins
)))
915 log("CIA NIA", self
.respect_pc
, self
.pc
.CIA
.value
, self
.pc
.NIA
.value
)
917 yield self
.dec2
.sv_rm
.eq(0)
918 yield self
.dec2
.dec
.raw_opcode_in
.eq(ins
& 0xffffffff)
919 yield self
.dec2
.dec
.bigendian
.eq(self
.bigendian
)
920 yield self
.dec2
.state
.msr
.eq(self
.msr
.value
)
921 yield self
.dec2
.state
.pc
.eq(pc
)
922 if self
.svstate
is not None:
923 yield self
.dec2
.state
.svstate
.eq(self
.svstate
.value
)
925 # SVP64. first, check if the opcode is EXT001, and SVP64 id bits set
927 opcode
= yield self
.dec2
.dec
.opcode_in
928 pfx
= SVP64PrefixFields() # TODO should probably use SVP64PrefixDecoder
929 pfx
.insn
.value
= opcode
930 major
= pfx
.major
.asint(msb0
=True) # MSB0 inversion
931 log ("prefix test: opcode:", major
, bin(major
),
932 pfx
.insn
[7] == 0b1, pfx
.insn
[9] == 0b1)
933 self
.is_svp64_mode
= ((major
== 0b000001) and
934 pfx
.insn
[7].value
== 0b1 and
935 pfx
.insn
[9].value
== 0b1)
936 self
.pc
.update_nia(self
.is_svp64_mode
)
937 yield self
.dec2
.is_svp64_mode
.eq(self
.is_svp64_mode
) # set SVP64 decode
938 self
.namespace
['NIA'] = self
.pc
.NIA
939 self
.namespace
['SVSTATE'] = self
.svstate
940 if not self
.is_svp64_mode
:
943 # in SVP64 mode. decode/print out svp64 prefix, get v3.0B instruction
944 log ("svp64.rm", bin(pfx
.rm
.asint(msb0
=True)))
945 log (" svstate.vl", self
.svstate
.vl
)
946 log (" svstate.mvl", self
.svstate
.maxvl
)
947 sv_rm
= pfx
.rm
.asint(msb0
=True)
948 ins
= self
.imem
.ld(pc
+4, 4, False, True, instr_fetch
=True)
949 log(" svsetup: 0x%x 0x%x %s" % (pc
+4, ins
& 0xffffffff, bin(ins
)))
950 yield self
.dec2
.dec
.raw_opcode_in
.eq(ins
& 0xffffffff) # v3.0B suffix
951 yield self
.dec2
.sv_rm
.eq(sv_rm
) # svp64 prefix
954 def execute_one(self
):
955 """execute one instruction
957 # get the disassembly code for this instruction
958 if self
.is_svp64_mode
:
959 if not self
.disassembly
:
960 code
= yield from self
.get_assembly_name()
962 code
= self
.disassembly
[self
._pc
+4]
963 log(" svp64 sim-execute", hex(self
._pc
), code
)
965 if not self
.disassembly
:
966 code
= yield from self
.get_assembly_name()
968 code
= self
.disassembly
[self
._pc
]
969 log("sim-execute", hex(self
._pc
), code
)
970 opname
= code
.split(' ')[0]
972 yield from self
.call(opname
) # execute the instruction
973 except MemException
as e
: # check for memory errors
974 if e
.args
[0] != 'unaligned': # only doing aligned at the mo
975 raise e
# ... re-raise
976 # run a Trap but set DAR first
977 print ("memory unaligned exception, DAR", e
.dar
)
978 self
.spr
['DAR'] = SelectableInt(e
.dar
, 64)
979 self
.call_trap(0x600, PIb
.PRIV
) # 0x600, privileged
982 # don't use this except in special circumstances
983 if not self
.respect_pc
:
986 log("execute one, CIA NIA", self
.pc
.CIA
.value
, self
.pc
.NIA
.value
)
988 def get_assembly_name(self
):
989 # TODO, asmregs is from the spec, e.g. add RT,RA,RB
990 # see http://bugs.libre-riscv.org/show_bug.cgi?id=282
991 dec_insn
= yield self
.dec2
.e
.do
.insn
992 insn_1_11
= yield self
.dec2
.e
.do
.insn
[1:11]
993 asmcode
= yield self
.dec2
.dec
.op
.asmcode
994 int_op
= yield self
.dec2
.dec
.op
.internal_op
995 log("get assembly name asmcode", asmcode
, int_op
,
996 hex(dec_insn
), bin(insn_1_11
))
997 asmop
= insns
.get(asmcode
, None)
999 # sigh reconstruct the assembly instruction name
1000 if hasattr(self
.dec2
.e
.do
, "oe"):
1001 ov_en
= yield self
.dec2
.e
.do
.oe
.oe
1002 ov_ok
= yield self
.dec2
.e
.do
.oe
.ok
1006 if hasattr(self
.dec2
.e
.do
, "rc"):
1007 rc_en
= yield self
.dec2
.e
.do
.rc
.rc
1008 rc_ok
= yield self
.dec2
.e
.do
.rc
.ok
1012 # grrrr have to special-case MUL op (see DecodeOE)
1013 log("ov %d en %d rc %d en %d op %d" %
1014 (ov_ok
, ov_en
, rc_ok
, rc_en
, int_op
))
1015 if int_op
in [MicrOp
.OP_MUL_H64
.value
, MicrOp
.OP_MUL_H32
.value
]:
1020 if not asmop
.endswith("."): # don't add "." to "andis."
1023 if hasattr(self
.dec2
.e
.do
, "lk"):
1024 lk
= yield self
.dec2
.e
.do
.lk
1027 log("int_op", int_op
)
1028 if int_op
in [MicrOp
.OP_B
.value
, MicrOp
.OP_BC
.value
]:
1029 AA
= yield self
.dec2
.dec
.fields
.FormI
.AA
[0:-1]
1033 spr_msb
= yield from self
.get_spr_msb()
1034 if int_op
== MicrOp
.OP_MFCR
.value
:
1039 # XXX TODO: for whatever weird reason this doesn't work
1040 # https://bugs.libre-soc.org/show_bug.cgi?id=390
1041 if int_op
== MicrOp
.OP_MTCRF
.value
:
1048 def get_remap_indices(self
):
1049 """WARNING, this function stores remap_idxs and remap_loopends
1050 in the class for later use. this to avoid problems with yield
1052 # go through all iterators in lock-step, advance to next remap_idx
1053 srcstep
, dststep
= self
.get_src_dststeps()
1054 # get four SVSHAPEs. here we are hard-coding
1055 SVSHAPE0
= self
.spr
['SVSHAPE0']
1056 SVSHAPE1
= self
.spr
['SVSHAPE1']
1057 SVSHAPE2
= self
.spr
['SVSHAPE2']
1058 SVSHAPE3
= self
.spr
['SVSHAPE3']
1059 # set up the iterators
1060 remaps
= [(SVSHAPE0
, SVSHAPE0
.get_iterator()),
1061 (SVSHAPE1
, SVSHAPE1
.get_iterator()),
1062 (SVSHAPE2
, SVSHAPE2
.get_iterator()),
1063 (SVSHAPE3
, SVSHAPE3
.get_iterator()),
1066 self
.remap_loopends
= [0] * 4
1067 self
.remap_idxs
= [0, 1, 2, 3]
1069 for i
, (shape
, remap
) in enumerate(remaps
):
1070 # zero is "disabled"
1071 if shape
.value
== 0x0:
1072 self
.remap_idxs
[i
] = 0
1073 # pick src or dststep depending on reg num (0-2=in, 3-4=out)
1074 step
= dststep
if (i
in [3, 4]) else srcstep
1075 # this is terrible. O(N^2) looking for the match. but hey.
1076 for idx
, (remap_idx
, loopends
) in enumerate(remap
):
1079 self
.remap_idxs
[i
] = remap_idx
1080 self
.remap_loopends
[i
] = loopends
1081 dbg
.append((i
, step
, remap_idx
, loopends
))
1082 for (i
, step
, remap_idx
, loopends
) in dbg
:
1083 log ("SVSHAPE %d idx, end" % i
, step
, remap_idx
, bin(loopends
))
1086 def get_spr_msb(self
):
1087 dec_insn
= yield self
.dec2
.e
.do
.insn
1088 return dec_insn
& (1 << 20) != 0 # sigh - XFF.spr[-1]?
1090 def call(self
, name
):
1091 """call(opcode) - the primary execution point for instructions
1093 self
.last_st_addr
= None # reset the last known store address
1094 self
.last_ld_addr
= None # etc.
1096 ins_name
= name
.strip() # remove spaces if not already done so
1098 log("halted - not executing", ins_name
)
1101 # TODO, asmregs is from the spec, e.g. add RT,RA,RB
1102 # see http://bugs.libre-riscv.org/show_bug.cgi?id=282
1103 asmop
= yield from self
.get_assembly_name()
1104 log("call", ins_name
, asmop
)
1107 int_op
= yield self
.dec2
.dec
.op
.internal_op
1108 spr_msb
= yield from self
.get_spr_msb()
1110 instr_is_privileged
= False
1111 if int_op
in [MicrOp
.OP_ATTN
.value
,
1112 MicrOp
.OP_MFMSR
.value
,
1113 MicrOp
.OP_MTMSR
.value
,
1114 MicrOp
.OP_MTMSRD
.value
,
1116 MicrOp
.OP_RFID
.value
]:
1117 instr_is_privileged
= True
1118 if int_op
in [MicrOp
.OP_MFSPR
.value
,
1119 MicrOp
.OP_MTSPR
.value
] and spr_msb
:
1120 instr_is_privileged
= True
1122 log("is priv", instr_is_privileged
, hex(self
.msr
.value
),
1124 # check MSR priv bit and whether op is privileged: if so, throw trap
1125 if instr_is_privileged
and self
.msr
[MSRb
.PR
] == 1:
1126 self
.call_trap(0x700, PIb
.PRIV
)
1129 # check halted condition
1130 if ins_name
== 'attn':
1134 # check illegal instruction
1136 if ins_name
not in ['mtcrf', 'mtocrf']:
1137 illegal
= ins_name
!= asmop
1139 # sigh deal with setvl not being supported by binutils (.long)
1140 if asmop
.startswith('setvl'):
1144 # and svstep not being supported by binutils (.long)
1145 if asmop
.startswith('svstep'):
1149 # and svremap not being supported by binutils (.long)
1150 if asmop
.startswith('svremap'):
1152 ins_name
= 'svremap'
1154 # and svshape not being supported by binutils (.long)
1155 if asmop
.startswith('svshape'):
1157 ins_name
= 'svshape'
1160 if asmop
== 'fsins':
1163 if asmop
== 'fcoss':
1167 # sigh also deal with ffmadds not being supported by binutils (.long)
1168 if asmop
== 'ffmadds':
1170 ins_name
= 'ffmadds'
1172 # and fdmadds not being supported by binutils (.long)
1173 if asmop
== 'fdmadds':
1175 ins_name
= 'fdmadds'
1177 # and ffadds not being supported by binutils (.long)
1178 if asmop
== 'ffadds':
1182 # branch-conditional redirects to sv.bc
1183 if asmop
.startswith('bc') and self
.is_svp64_mode
:
1184 ins_name
= 'sv.%s' % ins_name
1186 log(" post-processed name", ins_name
, asmop
)
1188 # illegal instructions call TRAP at 0x700
1190 print("illegal", ins_name
, asmop
)
1191 self
.call_trap(0x700, PIb
.ILLEG
)
1192 print("name %s != %s - calling ILLEGAL trap, PC: %x" %
1193 (ins_name
, asmop
, self
.pc
.CIA
.value
))
1196 # this is for setvl "Vertical" mode: if set true,
1197 # srcstep/dststep is explicitly advanced. mode says which SVSTATE to
1198 # test for Rc=1 end condition. 3 bits of all 3 loops are put into CR0
1199 self
.allow_next_step_inc
= False
1200 self
.svstate_next_mode
= 0
1202 # nop has to be supported, we could let the actual op calculate
1203 # but PowerDecoder has a pattern for nop
1204 if ins_name
is 'nop':
1205 self
.update_pc_next()
1208 # look up instruction in ISA.instrs, prepare namespace
1209 info
= self
.instrs
[ins_name
]
1210 yield from self
.prep_namespace(ins_name
, info
.form
, info
.op_fields
)
1212 # preserve order of register names
1213 input_names
= create_args(list(info
.read_regs
) +
1214 list(info
.uninit_regs
))
1215 log("input names", input_names
)
1217 # get SVP64 entry for the current instruction
1218 sv_rm
= self
.svp64rm
.instrs
.get(ins_name
)
1219 if sv_rm
is not None:
1220 dest_cr
, src_cr
, src_byname
, dest_byname
= decode_extra(sv_rm
)
1222 dest_cr
, src_cr
, src_byname
, dest_byname
= False, False, {}, {}
1223 log ("sv rm", sv_rm
, dest_cr
, src_cr
, src_byname
, dest_byname
)
1225 # see if srcstep/dststep need skipping over masked-out predicate bits
1226 if (self
.is_svp64_mode
or ins_name
== 'setvl' or
1227 ins_name
.startswith("sv")):
1228 yield from self
.svstate_pre_inc()
1229 if self
.is_svp64_mode
:
1230 pre
= yield from self
.update_new_svstate_steps()
1232 self
.svp64_reset_loop()
1234 self
.update_pc_next()
1236 srcstep
, dststep
= self
.get_src_dststeps()
1237 pred_dst_zero
= self
.pred_dst_zero
1238 pred_src_zero
= self
.pred_src_zero
1239 vl
= self
.svstate
.vl
1241 # VL=0 in SVP64 mode means "do nothing: skip instruction"
1242 if self
.is_svp64_mode
and vl
== 0:
1243 self
.pc
.update(self
.namespace
, self
.is_svp64_mode
)
1244 log("SVP64: VL=0, end of call", self
.namespace
['CIA'],
1245 self
.namespace
['NIA'])
1248 # for when SVREMAP is active, using pre-arranged schedule.
1249 # note: modifying PowerDecoder2 needs to "settle"
1250 remap_en
= self
.svstate
.SVme
1251 persist
= self
.svstate
.RMpst
1252 active
= (persist
or self
.last_op_svshape
) and remap_en
!= 0
1253 yield self
.dec2
.remap_active
.eq(remap_en
if active
else 0)
1255 if persist
or self
.last_op_svshape
:
1256 remaps
= self
.get_remap_indices()
1257 if self
.is_svp64_mode
and (persist
or self
.last_op_svshape
):
1258 # just some convenient debug info
1260 sname
= 'SVSHAPE%d' % i
1261 shape
= self
.spr
[sname
]
1262 log (sname
, bin(shape
.value
))
1263 log (" lims", shape
.lims
)
1264 log (" mode", shape
.mode
)
1265 log (" skip", shape
.skip
)
1267 # set up the list of steps to remap
1268 mi0
= self
.svstate
.mi0
1269 mi1
= self
.svstate
.mi1
1270 mi2
= self
.svstate
.mi2
1271 mo0
= self
.svstate
.mo0
1272 mo1
= self
.svstate
.mo1
1273 steps
= [(self
.dec2
.in1_step
, mi0
), # RA
1274 (self
.dec2
.in2_step
, mi1
), # RB
1275 (self
.dec2
.in3_step
, mi2
), # RC
1276 (self
.dec2
.o_step
, mo0
), # RT
1277 (self
.dec2
.o2_step
, mo1
), # EA
1279 remap_idxs
= self
.remap_idxs
1281 # now cross-index the required SHAPE for each of 3-in 2-out regs
1282 rnames
= ['RA', 'RB', 'RC', 'RT', 'EA']
1283 for i
, (dstep
, shape_idx
) in enumerate(steps
):
1284 (shape
, remap
) = remaps
[shape_idx
]
1285 remap_idx
= remap_idxs
[shape_idx
]
1286 # zero is "disabled"
1287 if shape
.value
== 0x0:
1289 # now set the actual requested step to the current index
1290 yield dstep
.eq(remap_idx
)
1292 # debug printout info
1293 rremaps
.append((shape
.mode
, i
, rnames
[i
], shape_idx
,
1296 log ("shape remap", x
)
1297 # after that, settle down (combinatorial) to let Vector reg numbers
1298 # work themselves out
1300 remap_active
= yield self
.dec2
.remap_active
1301 log ("remap active", bin(remap_active
))
1303 # main input registers (RT, RA ...)
1305 for name
in input_names
:
1306 # using PowerDecoder2, first, find the decoder index.
1307 # (mapping name RA RB RC RS to in1, in2, in3)
1308 regnum
, is_vec
= yield from get_pdecode_idx_in(self
.dec2
, name
)
1310 # doing this is not part of svp64, it's because output
1311 # registers, to be modified, need to be in the namespace.
1312 regnum
, is_vec
= yield from get_pdecode_idx_out(self
.dec2
, name
)
1314 regnum
, is_vec
= yield from get_pdecode_idx_out2(self
.dec2
,
1317 # in case getting the register number is needed, _RA, _RB
1318 regname
= "_" + name
1319 self
.namespace
[regname
] = regnum
1320 if not self
.is_svp64_mode
or not pred_src_zero
:
1321 log('reading reg %s %s' % (name
, str(regnum
)), is_vec
)
1323 reg_val
= self
.fpr(regnum
)
1324 elif name
is not None:
1325 reg_val
= self
.gpr(regnum
)
1327 log('zero input reg %s %s' % (name
, str(regnum
)), is_vec
)
1329 inputs
.append(reg_val
)
1330 # arrrrgh, awful hack, to get _RT into namespace
1331 if ins_name
in ['setvl', 'svstep']:
1333 RT
= yield self
.dec2
.dec
.RT
1334 self
.namespace
[regname
] = SelectableInt(RT
, 5)
1336 self
.namespace
["RT"] = SelectableInt(0, 5)
1337 regnum
, is_vec
= yield from get_pdecode_idx_out(self
.dec2
, "RT")
1338 log('hack input reg %s %s' % (name
, str(regnum
)), is_vec
)
1340 # in SVP64 mode for LD/ST work out immediate
1341 # XXX TODO: replace_ds for DS-Form rather than D-Form.
1342 # use info.form to detect
1343 replace_d
= False # update / replace constant in pseudocode
1344 if self
.is_svp64_mode
:
1345 ldstmode
= yield self
.dec2
.rm_dec
.ldstmode
1346 # shift mode reads SVD (or SVDS - TODO)
1347 # *BUT*... because this is "overloading" of LD operations,
1348 # it gets *STORED* into D (or DS, TODO)
1349 if ldstmode
== SVP64LDSTmode
.SHIFT
.value
:
1350 imm
= yield self
.dec2
.dec
.fields
.FormSVD
.SVD
[0:11]
1351 imm
= exts(imm
, 11) # sign-extend to integer
1352 log ("shift SVD", imm
)
1355 if info
.form
== 'DS':
1356 # DS-Form, multiply by 4 then knock 2 bits off after
1357 imm
= yield self
.dec2
.dec
.fields
.FormDS
.DS
[0:14] * 4
1359 imm
= yield self
.dec2
.dec
.fields
.FormD
.D
[0:16]
1360 imm
= exts(imm
, 16) # sign-extend to integer
1361 # get the right step. LD is from srcstep, ST is dststep
1362 op
= yield self
.dec2
.e
.do
.insn_type
1364 if op
== MicrOp
.OP_LOAD
.value
:
1366 offsmul
= yield self
.dec2
.in1_step
1367 log("D-field REMAP src", imm
, offsmul
)
1370 log("D-field src", imm
, offsmul
)
1371 elif op
== MicrOp
.OP_STORE
.value
:
1372 # XXX NOTE! no bit-reversed STORE! this should not ever be used
1374 log("D-field dst", imm
, offsmul
)
1375 # bit-reverse mode, rev already done through get_src_dst_steps()
1376 if ldstmode
== SVP64LDSTmode
.SHIFT
.value
:
1377 # manually look up RC, sigh
1378 RC
= yield self
.dec2
.dec
.RC
[0:5]
1380 log ("LD-SHIFT:", "VL", vl
,
1381 "RC", RC
.value
, "imm", imm
,
1382 "offs", bin(offsmul
),
1384 imm
= SelectableInt((imm
* offsmul
) << RC
.value
, 32)
1385 # Unit-Strided LD/ST adds offset*width to immediate
1386 elif ldstmode
== SVP64LDSTmode
.UNITSTRIDE
.value
:
1387 ldst_len
= yield self
.dec2
.e
.do
.data_len
1388 imm
= SelectableInt(imm
+ offsmul
* ldst_len
, 32)
1390 # Element-strided multiplies the immediate by element step
1391 elif ldstmode
== SVP64LDSTmode
.ELSTRIDE
.value
:
1392 imm
= SelectableInt(imm
* offsmul
, 32)
1395 ldst_ra_vec
= yield self
.dec2
.rm_dec
.ldst_ra_vec
1396 ldst_imz_in
= yield self
.dec2
.rm_dec
.ldst_imz_in
1397 log("LDSTmode", SVP64LDSTmode(ldstmode
),
1398 offsmul
, imm
, ldst_ra_vec
, ldst_imz_in
)
1399 # new replacement D... errr.. DS
1401 if info
.form
== 'DS':
1402 # TODO: assert 2 LSBs are zero?
1403 log("DS-Form, TODO, assert 2 LSBs zero?", bin(imm
.value
))
1404 imm
.value
= imm
.value
>> 2
1405 self
.namespace
['DS'] = imm
1407 self
.namespace
['D'] = imm
1409 # "special" registers
1410 for special
in info
.special_regs
:
1411 if special
in special_sprs
:
1412 inputs
.append(self
.spr
[special
])
1414 inputs
.append(self
.namespace
[special
])
1416 # clear trap (trap) NIA
1417 self
.trap_nia
= None
1419 # execute actual instruction here (finally)
1420 log("inputs", inputs
)
1421 results
= info
.func(self
, *inputs
)
1422 log("results", results
)
1424 # "inject" decorator takes namespace from function locals: we need to
1425 # overwrite NIA being overwritten (sigh)
1426 if self
.trap_nia
is not None:
1427 self
.namespace
['NIA'] = self
.trap_nia
1429 log("after func", self
.namespace
['CIA'], self
.namespace
['NIA'])
1431 # check if op was a LD/ST so that debugging can check the
1433 if int_op
in [MicrOp
.OP_STORE
.value
,
1435 self
.last_st_addr
= self
.mem
.last_st_addr
1436 if int_op
in [MicrOp
.OP_LOAD
.value
,
1438 self
.last_ld_addr
= self
.mem
.last_ld_addr
1439 log ("op", int_op
, MicrOp
.OP_STORE
.value
, MicrOp
.OP_LOAD
.value
,
1440 self
.last_st_addr
, self
.last_ld_addr
)
1442 # detect if CA/CA32 already in outputs (sra*, basically)
1445 output_names
= create_args(info
.write_regs
)
1446 for name
in output_names
:
1452 log("carry already done?", bin(already_done
))
1453 if hasattr(self
.dec2
.e
.do
, "output_carry"):
1454 carry_en
= yield self
.dec2
.e
.do
.output_carry
1458 yield from self
.handle_carry_(inputs
, results
, already_done
)
1460 if not self
.is_svp64_mode
: # yeah just no. not in parallel processing
1461 # detect if overflow was in return result
1464 for name
, output
in zip(output_names
, results
):
1465 if name
== 'overflow':
1468 if hasattr(self
.dec2
.e
.do
, "oe"):
1469 ov_en
= yield self
.dec2
.e
.do
.oe
.oe
1470 ov_ok
= yield self
.dec2
.e
.do
.oe
.ok
1474 log("internal overflow", overflow
, ov_en
, ov_ok
)
1476 yield from self
.handle_overflow(inputs
, results
, overflow
)
1478 # only do SVP64 dest predicated Rc=1 if dest-pred is not enabled
1480 if not self
.is_svp64_mode
or not pred_dst_zero
:
1481 if hasattr(self
.dec2
.e
.do
, "rc"):
1482 rc_en
= yield self
.dec2
.e
.do
.rc
.rc
1483 if rc_en
and ins_name
not in ['svstep']:
1484 regnum
, is_vec
= yield from get_pdecode_cr_out(self
.dec2
, "CR0")
1485 self
.handle_comparison(results
, regnum
)
1487 # any modified return results?
1489 for name
, output
in zip(output_names
, results
):
1490 if name
== 'overflow': # ignore, done already (above)
1492 if isinstance(output
, int):
1493 output
= SelectableInt(output
, 256)
1494 if name
in ['CA', 'CA32']:
1496 log("writing %s to XER" % name
, output
)
1497 self
.spr
['XER'][XER_bits
[name
]] = output
.value
1499 log("NOT writing %s to XER" % name
, output
)
1500 elif name
in info
.special_regs
:
1501 log('writing special %s' % name
, output
, special_sprs
)
1502 if name
in special_sprs
:
1503 self
.spr
[name
] = output
1505 self
.namespace
[name
].eq(output
)
1507 log('msr written', hex(self
.msr
.value
))
1509 regnum
, is_vec
= yield from get_pdecode_idx_out(self
.dec2
,
1512 regnum
, is_vec
= yield from get_pdecode_idx_out2(
1515 # temporary hack for not having 2nd output
1516 regnum
= yield getattr(self
.decoder
, name
)
1518 if self
.is_svp64_mode
and pred_dst_zero
:
1519 log('zeroing reg %d %s' % (regnum
, str(output
)),
1521 output
= SelectableInt(0, 256)
1527 log('writing %s %s %s' % (ftype
, regnum
, str(output
)),
1529 if output
.bits
> 64:
1530 output
= SelectableInt(output
.value
, 64)
1532 self
.fpr
[regnum
] = output
1534 self
.gpr
[regnum
] = output
1536 # check if it is the SVSTATE.src/dest step that needs incrementing
1537 # this is our Sub-Program-Counter loop from 0 to VL-1
1540 if self
.allow_next_step_inc
:
1541 log("SVSTATE_NEXT: inc requested, mode",
1542 self
.svstate_next_mode
, self
.allow_next_step_inc
)
1543 yield from self
.svstate_pre_inc()
1544 pre
= yield from self
.update_new_svstate_steps()
1546 # reset at end of loop including exit Vertical Mode
1547 log ("SVSTATE_NEXT: end of loop, reset")
1548 self
.svp64_reset_loop()
1549 self
.svstate
.vfirst
= 0
1552 results
= [SelectableInt(0, 64)]
1553 self
.handle_comparison(results
) # CR0
1555 if self
.allow_next_step_inc
== 2:
1556 log ("SVSTATE_NEXT: read")
1557 yield from self
.svstate_post_inc()
1559 log ("SVSTATE_NEXT: post-inc")
1560 # use actual src/dst-step here to check end, do NOT
1561 # use bit-reversed version
1562 srcstep
, dststep
= self
.new_srcstep
, self
.new_dststep
1563 remaps
= self
.get_remap_indices()
1564 remap_idxs
= self
.remap_idxs
1565 vl
= self
.svstate
.vl
1566 end_src
= srcstep
== vl
-1
1567 end_dst
= dststep
== vl
-1
1568 if self
.allow_next_step_inc
!= 2:
1570 self
.svstate
.srcstep
+= SelectableInt(1, 7)
1572 self
.svstate
.dststep
+= SelectableInt(1, 7)
1573 self
.namespace
['SVSTATE'] = self
.svstate
.spr
1574 # set CR0 (if Rc=1) based on end
1576 srcstep
= self
.svstate
.srcstep
1577 dststep
= self
.svstate
.srcstep
1578 endtest
= 1 if (end_src
or end_dst
) else 0
1579 #results = [SelectableInt(endtest, 64)]
1580 #self.handle_comparison(results) # CR0
1582 # see if svstep was requested, if so, which SVSTATE
1584 if self
.svstate_next_mode
> 0:
1585 shape_idx
= self
.svstate_next_mode
.value
-1
1586 endings
= self
.remap_loopends
[shape_idx
]
1587 cr_field
= SelectableInt((~endings
)<<1 | endtest
, 4)
1588 print ("svstep Rc=1, CR0", cr_field
)
1589 self
.crl
[0].eq(cr_field
) # CR0
1590 if end_src
or end_dst
:
1591 # reset at end of loop including exit Vertical Mode
1592 log ("SVSTATE_NEXT: after increments, reset")
1593 self
.svp64_reset_loop()
1594 self
.svstate
.vfirst
= 0
1596 elif self
.is_svp64_mode
:
1597 yield from self
.svstate_post_inc()
1599 # XXX only in non-SVP64 mode!
1600 # record state of whether the current operation was an svshape,
1601 # to be able to know if it should apply in the next instruction.
1602 # also (if going to use this instruction) should disable ability
1603 # to interrupt in between. sigh.
1604 self
.last_op_svshape
= asmop
== 'svremap'
1606 self
.update_pc_next()
1608 def SVSTATE_NEXT(self
, mode
, submode
):
1609 """explicitly moves srcstep/dststep on to next element, for
1610 "Vertical-First" mode. this function is called from
1611 setvl pseudo-code, as a pseudo-op "svstep"
1613 WARNING: this function uses information that was created EARLIER
1614 due to it being in the middle of a yield, but this function is
1615 *NOT* called from yield (it's called from compiled pseudocode).
1617 self
.allow_next_step_inc
= submode
.value
+ 1
1618 log("SVSTATE_NEXT mode", mode
, submode
, self
.allow_next_step_inc
)
1619 self
.svstate_next_mode
= mode
1620 if self
.svstate_next_mode
> 0:
1621 shape_idx
= self
.svstate_next_mode
.value
-1
1622 return SelectableInt(self
.remap_idxs
[shape_idx
], 7)
1623 return SelectableInt(0, 7)
1625 def svstate_pre_inc(self
):
1626 """check if srcstep/dststep need to skip over masked-out predicate bits
1628 # get SVSTATE VL (oh and print out some debug stuff)
1629 vl
= self
.svstate
.vl
1630 srcstep
= self
.svstate
.srcstep
1631 dststep
= self
.svstate
.dststep
1632 sv_a_nz
= yield self
.dec2
.sv_a_nz
1633 fft_mode
= yield self
.dec2
.use_svp64_fft
1634 in1
= yield self
.dec2
.e
.read_reg1
.data
1635 log ("SVP64: VL, srcstep, dststep, sv_a_nz, in1 fft, svp64",
1636 vl
, srcstep
, dststep
, sv_a_nz
, in1
, fft_mode
,
1639 # get predicate mask
1640 srcmask
= dstmask
= 0xffff_ffff_ffff_ffff
1642 pmode
= yield self
.dec2
.rm_dec
.predmode
1643 reverse_gear
= yield self
.dec2
.rm_dec
.reverse_gear
1644 sv_ptype
= yield self
.dec2
.dec
.op
.SV_Ptype
1645 srcpred
= yield self
.dec2
.rm_dec
.srcpred
1646 dstpred
= yield self
.dec2
.rm_dec
.dstpred
1647 pred_src_zero
= yield self
.dec2
.rm_dec
.pred_sz
1648 pred_dst_zero
= yield self
.dec2
.rm_dec
.pred_dz
1649 if pmode
== SVP64PredMode
.INT
.value
:
1650 srcmask
= dstmask
= get_predint(self
.gpr
, dstpred
)
1651 if sv_ptype
== SVPtype
.P2
.value
:
1652 srcmask
= get_predint(self
.gpr
, srcpred
)
1653 elif pmode
== SVP64PredMode
.CR
.value
:
1654 srcmask
= dstmask
= get_predcr(self
.crl
, dstpred
, vl
)
1655 if sv_ptype
== SVPtype
.P2
.value
:
1656 srcmask
= get_predcr(self
.crl
, srcpred
, vl
)
1657 log (" pmode", pmode
)
1658 log (" reverse", reverse_gear
)
1659 log (" ptype", sv_ptype
)
1660 log (" srcpred", bin(srcpred
))
1661 log (" dstpred", bin(dstpred
))
1662 log (" srcmask", bin(srcmask
))
1663 log (" dstmask", bin(dstmask
))
1664 log (" pred_sz", bin(pred_src_zero
))
1665 log (" pred_dz", bin(pred_dst_zero
))
1667 # okaaay, so here we simply advance srcstep (TODO dststep)
1668 # until the predicate mask has a "1" bit... or we run out of VL
1669 # let srcstep==VL be the indicator to move to next instruction
1670 if not pred_src_zero
:
1671 while (((1<<srcstep
) & srcmask
) == 0) and (srcstep
!= vl
):
1672 log (" skip", bin(1<<srcstep
))
1675 if not pred_dst_zero
:
1676 while (((1<<dststep
) & dstmask
) == 0) and (dststep
!= vl
):
1677 log (" skip", bin(1<<dststep
))
1680 # now work out if the relevant mask bits require zeroing
1682 pred_dst_zero
= ((1<<dststep
) & dstmask
) == 0
1684 pred_src_zero
= ((1<<srcstep
) & srcmask
) == 0
1686 # store new srcstep / dststep
1687 self
.new_srcstep
, self
.new_dststep
= srcstep
, dststep
1688 self
.pred_dst_zero
, self
.pred_src_zero
= pred_dst_zero
, pred_src_zero
1689 log (" new srcstep", srcstep
)
1690 log (" new dststep", dststep
)
1692 def get_src_dststeps(self
):
1693 """gets srcstep and dststep
1695 return self
.new_srcstep
, self
.new_dststep
1697 def update_new_svstate_steps(self
):
1698 # note, do not get the bit-reversed srcstep here!
1699 srcstep
, dststep
= self
.new_srcstep
, self
.new_dststep
1701 # update SVSTATE with new srcstep
1702 self
.svstate
.srcstep
= srcstep
1703 self
.svstate
.dststep
= dststep
1704 self
.namespace
['SVSTATE'] = self
.svstate
1705 yield self
.dec2
.state
.svstate
.eq(self
.svstate
.value
)
1706 yield Settle() # let decoder update
1707 srcstep
= self
.svstate
.srcstep
1708 dststep
= self
.svstate
.dststep
1709 vl
= self
.svstate
.vl
1710 log (" srcstep", srcstep
)
1711 log (" dststep", dststep
)
1714 # check if end reached (we let srcstep overrun, above)
1715 # nothing needs doing (TODO zeroing): just do next instruction
1716 return srcstep
== vl
or dststep
== vl
1718 def svstate_post_inc(self
, vf
=0):
1719 # check if SV "Vertical First" mode is enabled
1720 vfirst
= self
.svstate
.vfirst
1721 log (" SV Vertical First", vf
, vfirst
)
1722 if not vf
and vfirst
== 1:
1726 # check if it is the SVSTATE.src/dest step that needs incrementing
1727 # this is our Sub-Program-Counter loop from 0 to VL-1
1728 # XXX twin predication TODO
1729 vl
= self
.svstate
.vl
1730 mvl
= self
.svstate
.maxvl
1731 srcstep
= self
.svstate
.srcstep
1732 dststep
= self
.svstate
.dststep
1733 rm_mode
= yield self
.dec2
.rm_dec
.mode
1734 reverse_gear
= yield self
.dec2
.rm_dec
.reverse_gear
1735 sv_ptype
= yield self
.dec2
.dec
.op
.SV_Ptype
1736 out_vec
= not (yield self
.dec2
.no_out_vec
)
1737 in_vec
= not (yield self
.dec2
.no_in_vec
)
1738 log (" svstate.vl", vl
)
1739 log (" svstate.mvl", mvl
)
1740 log (" svstate.srcstep", srcstep
)
1741 log (" svstate.dststep", dststep
)
1742 log (" mode", rm_mode
)
1743 log (" reverse", reverse_gear
)
1744 log (" out_vec", out_vec
)
1745 log (" in_vec", in_vec
)
1746 log (" sv_ptype", sv_ptype
, sv_ptype
== SVPtype
.P2
.value
)
1747 # check if srcstep needs incrementing by one, stop PC advancing
1748 # svp64 loop can end early if the dest is scalar for single-pred
1749 # but for 2-pred both src/dest have to be checked.
1750 # XXX this might not be true! it may just be LD/ST
1751 if sv_ptype
== SVPtype
.P2
.value
:
1752 svp64_is_vector
= (out_vec
or in_vec
)
1754 svp64_is_vector
= out_vec
1755 if svp64_is_vector
and srcstep
!= vl
-1 and dststep
!= vl
-1:
1756 self
.svstate
.srcstep
+= SelectableInt(1, 7)
1757 self
.svstate
.dststep
+= SelectableInt(1, 7)
1758 self
.pc
.NIA
.value
= self
.pc
.CIA
.value
1759 self
.namespace
['NIA'] = self
.pc
.NIA
1760 self
.namespace
['SVSTATE'] = self
.svstate
1761 log("end of sub-pc call", self
.namespace
['CIA'],
1762 self
.namespace
['NIA'])
1763 return False # DO NOT allow PC update whilst Sub-PC loop running
1765 # reset loop to zero and update NIA
1766 self
.svp64_reset_loop()
1771 def update_pc_next(self
):
1772 # UPDATE program counter
1773 self
.pc
.update(self
.namespace
, self
.is_svp64_mode
)
1774 self
.svstate
.spr
= self
.namespace
['SVSTATE']
1775 log("end of call", self
.namespace
['CIA'],
1776 self
.namespace
['NIA'],
1777 self
.namespace
['SVSTATE'])
1779 def svp64_reset_loop(self
):
1780 self
.svstate
.srcstep
= 0
1781 self
.svstate
.dststep
= 0
1782 log (" svstate.srcstep loop end (PC to update)")
1783 self
.namespace
['SVSTATE'] = self
.svstate
1785 def update_nia(self
):
1786 self
.pc
.update_nia(self
.is_svp64_mode
)
1787 self
.namespace
['NIA'] = self
.pc
.NIA
1790 """Decorator factory.
1792 this decorator will "inject" variables into the function's namespace,
1793 from the *dictionary* in self.namespace. it therefore becomes possible
1794 to make it look like a whole stack of variables which would otherwise
1795 need "self." inserted in front of them (*and* for those variables to be
1796 added to the instance) "appear" in the function.
1798 "self.namespace['SI']" for example becomes accessible as just "SI" but
1799 *only* inside the function, when decorated.
1801 def variable_injector(func
):
1803 def decorator(*args
, **kwargs
):
1805 func_globals
= func
.__globals
__ # Python 2.6+
1806 except AttributeError:
1807 func_globals
= func
.func_globals
# Earlier versions.
1809 context
= args
[0].namespace
# variables to be injected
1810 saved_values
= func_globals
.copy() # Shallow copy of dict.
1811 log("globals before", context
.keys())
1812 func_globals
.update(context
)
1813 result
= func(*args
, **kwargs
)
1814 log("globals after", func_globals
['CIA'], func_globals
['NIA'])
1815 log("args[0]", args
[0].namespace
['CIA'],
1816 args
[0].namespace
['NIA'],
1817 args
[0].namespace
['SVSTATE'])
1818 args
[0].namespace
= func_globals
1819 #exec (func.__code__, func_globals)
1822 # func_globals = saved_values # Undo changes.
1828 return variable_injector