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)
773 # use these to detect if the branch took place
774 self
.namespace
['ctr_ok'] = SelectableInt(0, 1)
775 self
.namespace
['cond_ok'] = SelectableInt(0, 1)
777 def handle_carry_(self
, inputs
, outputs
, already_done
):
778 inv_a
= yield self
.dec2
.e
.do
.invert_in
780 inputs
[0] = ~inputs
[0]
782 imm_ok
= yield self
.dec2
.e
.do
.imm_data
.ok
784 imm
= yield self
.dec2
.e
.do
.imm_data
.data
785 inputs
.append(SelectableInt(imm
, 64))
786 assert len(outputs
) >= 1
787 log("outputs", repr(outputs
))
788 if isinstance(outputs
, list) or isinstance(outputs
, tuple):
794 log("gt input", x
, output
)
795 gt
= (gtu(x
, output
))
798 cy
= 1 if any(gts
) else 0
800 if not (1 & already_done
):
801 self
.spr
['XER'][XER_bits
['CA']] = cy
803 log("inputs", already_done
, inputs
)
805 # ARGH... different for OP_ADD... *sigh*...
806 op
= yield self
.dec2
.e
.do
.insn_type
807 if op
== MicrOp
.OP_ADD
.value
:
808 res32
= (output
.value
& (1 << 32)) != 0
809 a32
= (inputs
[0].value
& (1 << 32)) != 0
811 b32
= (inputs
[1].value
& (1 << 32)) != 0
814 cy32
= res32 ^ a32 ^ b32
815 log("CA32 ADD", cy32
)
819 log("input", x
, output
)
820 log(" x[32:64]", x
, x
[32:64])
821 log(" o[32:64]", output
, output
[32:64])
822 gt
= (gtu(x
[32:64], output
[32:64])) == SelectableInt(1, 1)
824 cy32
= 1 if any(gts
) else 0
825 log("CA32", cy32
, gts
)
826 if not (2 & already_done
):
827 self
.spr
['XER'][XER_bits
['CA32']] = cy32
829 def handle_overflow(self
, inputs
, outputs
, div_overflow
):
830 if hasattr(self
.dec2
.e
.do
, "invert_in"):
831 inv_a
= yield self
.dec2
.e
.do
.invert_in
833 inputs
[0] = ~inputs
[0]
835 imm_ok
= yield self
.dec2
.e
.do
.imm_data
.ok
837 imm
= yield self
.dec2
.e
.do
.imm_data
.data
838 inputs
.append(SelectableInt(imm
, 64))
839 assert len(outputs
) >= 1
840 log("handle_overflow", inputs
, outputs
, div_overflow
)
841 if len(inputs
) < 2 and div_overflow
is None:
844 # div overflow is different: it's returned by the pseudo-code
845 # because it's more complex than can be done by analysing the output
846 if div_overflow
is not None:
847 ov
, ov32
= div_overflow
, div_overflow
848 # arithmetic overflow can be done by analysing the input and output
849 elif len(inputs
) >= 2:
853 input_sgn
= [exts(x
.value
, x
.bits
) < 0 for x
in inputs
]
854 output_sgn
= exts(output
.value
, output
.bits
) < 0
855 ov
= 1 if input_sgn
[0] == input_sgn
[1] and \
856 output_sgn
!= input_sgn
[0] else 0
859 input32_sgn
= [exts(x
.value
, 32) < 0 for x
in inputs
]
860 output32_sgn
= exts(output
.value
, 32) < 0
861 ov32
= 1 if input32_sgn
[0] == input32_sgn
[1] and \
862 output32_sgn
!= input32_sgn
[0] else 0
864 self
.spr
['XER'][XER_bits
['OV']] = ov
865 self
.spr
['XER'][XER_bits
['OV32']] = ov32
866 so
= self
.spr
['XER'][XER_bits
['SO']]
868 self
.spr
['XER'][XER_bits
['SO']] = so
870 def handle_comparison(self
, outputs
, cr_idx
=0):
872 assert isinstance(out
, SelectableInt
), \
873 "out zero not a SelectableInt %s" % repr(outputs
)
874 log("handle_comparison", out
.bits
, hex(out
.value
))
875 # TODO - XXX *processor* in 32-bit mode
876 # https://bugs.libre-soc.org/show_bug.cgi?id=424
878 # o32 = exts(out.value, 32)
879 # print ("handle_comparison exts 32 bit", hex(o32))
880 out
= exts(out
.value
, out
.bits
)
881 log("handle_comparison exts", hex(out
))
882 zero
= SelectableInt(out
== 0, 1)
883 positive
= SelectableInt(out
> 0, 1)
884 negative
= SelectableInt(out
< 0, 1)
885 SO
= self
.spr
['XER'][XER_bits
['SO']]
886 log("handle_comparison SO", SO
)
887 cr_field
= selectconcat(negative
, positive
, zero
, SO
)
888 log("handle_comparison cr_field", self
.cr
, cr_idx
, cr_field
)
889 self
.crl
[cr_idx
].eq(cr_field
)
891 def set_pc(self
, pc_val
):
892 self
.namespace
['NIA'] = SelectableInt(pc_val
, 64)
893 self
.pc
.update(self
.namespace
, self
.is_svp64_mode
)
895 def get_next_insn(self
):
899 pc
= self
.pc
.CIA
.value
902 ins
= self
.imem
.ld(pc
, 4, False, True, instr_fetch
=True)
904 raise KeyError("no instruction at 0x%x" % pc
)
908 """set up one instruction
910 pc
, insn
= self
.get_next_insn()
911 yield from self
.setup_next_insn(pc
, insn
)
913 def setup_next_insn(self
, pc
, ins
):
914 """set up next instruction
917 log("setup: 0x%x 0x%x %s" % (pc
, ins
& 0xffffffff, bin(ins
)))
918 log("CIA NIA", self
.respect_pc
, self
.pc
.CIA
.value
, self
.pc
.NIA
.value
)
920 yield self
.dec2
.sv_rm
.eq(0)
921 yield self
.dec2
.dec
.raw_opcode_in
.eq(ins
& 0xffffffff)
922 yield self
.dec2
.dec
.bigendian
.eq(self
.bigendian
)
923 yield self
.dec2
.state
.msr
.eq(self
.msr
.value
)
924 yield self
.dec2
.state
.pc
.eq(pc
)
925 if self
.svstate
is not None:
926 yield self
.dec2
.state
.svstate
.eq(self
.svstate
.value
)
928 # SVP64. first, check if the opcode is EXT001, and SVP64 id bits set
930 opcode
= yield self
.dec2
.dec
.opcode_in
931 pfx
= SVP64PrefixFields() # TODO should probably use SVP64PrefixDecoder
932 pfx
.insn
.value
= opcode
933 major
= pfx
.major
.asint(msb0
=True) # MSB0 inversion
934 log ("prefix test: opcode:", major
, bin(major
),
935 pfx
.insn
[7] == 0b1, pfx
.insn
[9] == 0b1)
936 self
.is_svp64_mode
= ((major
== 0b000001) and
937 pfx
.insn
[7].value
== 0b1 and
938 pfx
.insn
[9].value
== 0b1)
939 self
.pc
.update_nia(self
.is_svp64_mode
)
940 yield self
.dec2
.is_svp64_mode
.eq(self
.is_svp64_mode
) # set SVP64 decode
941 self
.namespace
['NIA'] = self
.pc
.NIA
942 self
.namespace
['SVSTATE'] = self
.svstate
943 if not self
.is_svp64_mode
:
946 # in SVP64 mode. decode/print out svp64 prefix, get v3.0B instruction
947 log ("svp64.rm", bin(pfx
.rm
.asint(msb0
=True)))
948 log (" svstate.vl", self
.svstate
.vl
)
949 log (" svstate.mvl", self
.svstate
.maxvl
)
950 sv_rm
= pfx
.rm
.asint(msb0
=True)
951 ins
= self
.imem
.ld(pc
+4, 4, False, True, instr_fetch
=True)
952 log(" svsetup: 0x%x 0x%x %s" % (pc
+4, ins
& 0xffffffff, bin(ins
)))
953 yield self
.dec2
.dec
.raw_opcode_in
.eq(ins
& 0xffffffff) # v3.0B suffix
954 yield self
.dec2
.sv_rm
.eq(sv_rm
) # svp64 prefix
957 def execute_one(self
):
958 """execute one instruction
960 # get the disassembly code for this instruction
961 if self
.is_svp64_mode
:
962 if not self
.disassembly
:
963 code
= yield from self
.get_assembly_name()
965 code
= self
.disassembly
[self
._pc
+4]
966 log(" svp64 sim-execute", hex(self
._pc
), code
)
968 if not self
.disassembly
:
969 code
= yield from self
.get_assembly_name()
971 code
= self
.disassembly
[self
._pc
]
972 log("sim-execute", hex(self
._pc
), code
)
973 opname
= code
.split(' ')[0]
975 yield from self
.call(opname
) # execute the instruction
976 except MemException
as e
: # check for memory errors
977 if e
.args
[0] != 'unaligned': # only doing aligned at the mo
978 raise e
# ... re-raise
979 # run a Trap but set DAR first
980 print ("memory unaligned exception, DAR", e
.dar
)
981 self
.spr
['DAR'] = SelectableInt(e
.dar
, 64)
982 self
.call_trap(0x600, PIb
.PRIV
) # 0x600, privileged
985 # don't use this except in special circumstances
986 if not self
.respect_pc
:
989 log("execute one, CIA NIA", self
.pc
.CIA
.value
, self
.pc
.NIA
.value
)
991 def get_assembly_name(self
):
992 # TODO, asmregs is from the spec, e.g. add RT,RA,RB
993 # see http://bugs.libre-riscv.org/show_bug.cgi?id=282
994 dec_insn
= yield self
.dec2
.e
.do
.insn
995 insn_1_11
= yield self
.dec2
.e
.do
.insn
[1:11]
996 asmcode
= yield self
.dec2
.dec
.op
.asmcode
997 int_op
= yield self
.dec2
.dec
.op
.internal_op
998 log("get assembly name asmcode", asmcode
, int_op
,
999 hex(dec_insn
), bin(insn_1_11
))
1000 asmop
= insns
.get(asmcode
, None)
1002 # sigh reconstruct the assembly instruction name
1003 if hasattr(self
.dec2
.e
.do
, "oe"):
1004 ov_en
= yield self
.dec2
.e
.do
.oe
.oe
1005 ov_ok
= yield self
.dec2
.e
.do
.oe
.ok
1009 if hasattr(self
.dec2
.e
.do
, "rc"):
1010 rc_en
= yield self
.dec2
.e
.do
.rc
.rc
1011 rc_ok
= yield self
.dec2
.e
.do
.rc
.ok
1015 # grrrr have to special-case MUL op (see DecodeOE)
1016 log("ov %d en %d rc %d en %d op %d" %
1017 (ov_ok
, ov_en
, rc_ok
, rc_en
, int_op
))
1018 if int_op
in [MicrOp
.OP_MUL_H64
.value
, MicrOp
.OP_MUL_H32
.value
]:
1023 if not asmop
.endswith("."): # don't add "." to "andis."
1026 if hasattr(self
.dec2
.e
.do
, "lk"):
1027 lk
= yield self
.dec2
.e
.do
.lk
1030 log("int_op", int_op
)
1031 if int_op
in [MicrOp
.OP_B
.value
, MicrOp
.OP_BC
.value
]:
1032 AA
= yield self
.dec2
.dec
.fields
.FormI
.AA
[0:-1]
1036 spr_msb
= yield from self
.get_spr_msb()
1037 if int_op
== MicrOp
.OP_MFCR
.value
:
1042 # XXX TODO: for whatever weird reason this doesn't work
1043 # https://bugs.libre-soc.org/show_bug.cgi?id=390
1044 if int_op
== MicrOp
.OP_MTCRF
.value
:
1051 def get_remap_indices(self
):
1052 """WARNING, this function stores remap_idxs and remap_loopends
1053 in the class for later use. this to avoid problems with yield
1055 # go through all iterators in lock-step, advance to next remap_idx
1056 srcstep
, dststep
= self
.get_src_dststeps()
1057 # get four SVSHAPEs. here we are hard-coding
1058 SVSHAPE0
= self
.spr
['SVSHAPE0']
1059 SVSHAPE1
= self
.spr
['SVSHAPE1']
1060 SVSHAPE2
= self
.spr
['SVSHAPE2']
1061 SVSHAPE3
= self
.spr
['SVSHAPE3']
1062 # set up the iterators
1063 remaps
= [(SVSHAPE0
, SVSHAPE0
.get_iterator()),
1064 (SVSHAPE1
, SVSHAPE1
.get_iterator()),
1065 (SVSHAPE2
, SVSHAPE2
.get_iterator()),
1066 (SVSHAPE3
, SVSHAPE3
.get_iterator()),
1069 self
.remap_loopends
= [0] * 4
1070 self
.remap_idxs
= [0, 1, 2, 3]
1072 for i
, (shape
, remap
) in enumerate(remaps
):
1073 # zero is "disabled"
1074 if shape
.value
== 0x0:
1075 self
.remap_idxs
[i
] = 0
1076 # pick src or dststep depending on reg num (0-2=in, 3-4=out)
1077 step
= dststep
if (i
in [3, 4]) else srcstep
1078 # this is terrible. O(N^2) looking for the match. but hey.
1079 for idx
, (remap_idx
, loopends
) in enumerate(remap
):
1082 self
.remap_idxs
[i
] = remap_idx
1083 self
.remap_loopends
[i
] = loopends
1084 dbg
.append((i
, step
, remap_idx
, loopends
))
1085 for (i
, step
, remap_idx
, loopends
) in dbg
:
1086 log ("SVSHAPE %d idx, end" % i
, step
, remap_idx
, bin(loopends
))
1089 def get_spr_msb(self
):
1090 dec_insn
= yield self
.dec2
.e
.do
.insn
1091 return dec_insn
& (1 << 20) != 0 # sigh - XFF.spr[-1]?
1093 def call(self
, name
):
1094 """call(opcode) - the primary execution point for instructions
1096 self
.last_st_addr
= None # reset the last known store address
1097 self
.last_ld_addr
= None # etc.
1099 ins_name
= name
.strip() # remove spaces if not already done so
1101 log("halted - not executing", ins_name
)
1104 # TODO, asmregs is from the spec, e.g. add RT,RA,RB
1105 # see http://bugs.libre-riscv.org/show_bug.cgi?id=282
1106 asmop
= yield from self
.get_assembly_name()
1107 log("call", ins_name
, asmop
)
1110 int_op
= yield self
.dec2
.dec
.op
.internal_op
1111 spr_msb
= yield from self
.get_spr_msb()
1113 instr_is_privileged
= False
1114 if int_op
in [MicrOp
.OP_ATTN
.value
,
1115 MicrOp
.OP_MFMSR
.value
,
1116 MicrOp
.OP_MTMSR
.value
,
1117 MicrOp
.OP_MTMSRD
.value
,
1119 MicrOp
.OP_RFID
.value
]:
1120 instr_is_privileged
= True
1121 if int_op
in [MicrOp
.OP_MFSPR
.value
,
1122 MicrOp
.OP_MTSPR
.value
] and spr_msb
:
1123 instr_is_privileged
= True
1125 log("is priv", instr_is_privileged
, hex(self
.msr
.value
),
1127 # check MSR priv bit and whether op is privileged: if so, throw trap
1128 if instr_is_privileged
and self
.msr
[MSRb
.PR
] == 1:
1129 self
.call_trap(0x700, PIb
.PRIV
)
1132 # check halted condition
1133 if ins_name
== 'attn':
1137 # check illegal instruction
1139 if ins_name
not in ['mtcrf', 'mtocrf']:
1140 illegal
= ins_name
!= asmop
1142 # sigh deal with setvl not being supported by binutils (.long)
1143 if asmop
.startswith('setvl'):
1147 # and svstep not being supported by binutils (.long)
1148 if asmop
.startswith('svstep'):
1152 # and svremap not being supported by binutils (.long)
1153 if asmop
.startswith('svremap'):
1155 ins_name
= 'svremap'
1157 # and svshape not being supported by binutils (.long)
1158 if asmop
.startswith('svshape'):
1160 ins_name
= 'svshape'
1163 if asmop
== 'fsins':
1166 if asmop
== 'fcoss':
1170 # sigh also deal with ffmadds not being supported by binutils (.long)
1171 if asmop
== 'ffmadds':
1173 ins_name
= 'ffmadds'
1175 # and fdmadds not being supported by binutils (.long)
1176 if asmop
== 'fdmadds':
1178 ins_name
= 'fdmadds'
1180 # and ffadds not being supported by binutils (.long)
1181 if asmop
== 'ffadds':
1185 # branch-conditional redirects to sv.bc
1186 if asmop
.startswith('bc') and self
.is_svp64_mode
:
1187 ins_name
= 'sv.%s' % ins_name
1189 log(" post-processed name", ins_name
, asmop
)
1191 # illegal instructions call TRAP at 0x700
1193 print("illegal", ins_name
, asmop
)
1194 self
.call_trap(0x700, PIb
.ILLEG
)
1195 print("name %s != %s - calling ILLEGAL trap, PC: %x" %
1196 (ins_name
, asmop
, self
.pc
.CIA
.value
))
1199 # this is for setvl "Vertical" mode: if set true,
1200 # srcstep/dststep is explicitly advanced. mode says which SVSTATE to
1201 # test for Rc=1 end condition. 3 bits of all 3 loops are put into CR0
1202 self
.allow_next_step_inc
= False
1203 self
.svstate_next_mode
= 0
1205 # nop has to be supported, we could let the actual op calculate
1206 # but PowerDecoder has a pattern for nop
1207 if ins_name
is 'nop':
1208 self
.update_pc_next()
1211 # look up instruction in ISA.instrs, prepare namespace
1212 info
= self
.instrs
[ins_name
]
1213 yield from self
.prep_namespace(ins_name
, info
.form
, info
.op_fields
)
1215 # preserve order of register names
1216 input_names
= create_args(list(info
.read_regs
) +
1217 list(info
.uninit_regs
))
1218 log("input names", input_names
)
1220 # get SVP64 entry for the current instruction
1221 sv_rm
= self
.svp64rm
.instrs
.get(ins_name
)
1222 if sv_rm
is not None:
1223 dest_cr
, src_cr
, src_byname
, dest_byname
= decode_extra(sv_rm
)
1225 dest_cr
, src_cr
, src_byname
, dest_byname
= False, False, {}, {}
1226 log ("sv rm", sv_rm
, dest_cr
, src_cr
, src_byname
, dest_byname
)
1228 # see if srcstep/dststep need skipping over masked-out predicate bits
1229 if (self
.is_svp64_mode
or ins_name
== 'setvl' or
1230 ins_name
in ['svremap', 'svstate']):
1231 yield from self
.svstate_pre_inc()
1232 if self
.is_svp64_mode
:
1233 pre
= yield from self
.update_new_svstate_steps()
1235 self
.svp64_reset_loop()
1237 self
.update_pc_next()
1239 srcstep
, dststep
= self
.get_src_dststeps()
1240 pred_dst_zero
= self
.pred_dst_zero
1241 pred_src_zero
= self
.pred_src_zero
1242 vl
= self
.svstate
.vl
1244 # VL=0 in SVP64 mode means "do nothing: skip instruction"
1245 if self
.is_svp64_mode
and vl
== 0:
1246 self
.pc
.update(self
.namespace
, self
.is_svp64_mode
)
1247 log("SVP64: VL=0, end of call", self
.namespace
['CIA'],
1248 self
.namespace
['NIA'])
1251 # for when SVREMAP is active, using pre-arranged schedule.
1252 # note: modifying PowerDecoder2 needs to "settle"
1253 remap_en
= self
.svstate
.SVme
1254 persist
= self
.svstate
.RMpst
1255 active
= (persist
or self
.last_op_svshape
) and remap_en
!= 0
1256 yield self
.dec2
.remap_active
.eq(remap_en
if active
else 0)
1258 if persist
or self
.last_op_svshape
:
1259 remaps
= self
.get_remap_indices()
1260 if self
.is_svp64_mode
and (persist
or self
.last_op_svshape
):
1261 # just some convenient debug info
1263 sname
= 'SVSHAPE%d' % i
1264 shape
= self
.spr
[sname
]
1265 log (sname
, bin(shape
.value
))
1266 log (" lims", shape
.lims
)
1267 log (" mode", shape
.mode
)
1268 log (" skip", shape
.skip
)
1270 # set up the list of steps to remap
1271 mi0
= self
.svstate
.mi0
1272 mi1
= self
.svstate
.mi1
1273 mi2
= self
.svstate
.mi2
1274 mo0
= self
.svstate
.mo0
1275 mo1
= self
.svstate
.mo1
1276 steps
= [(self
.dec2
.in1_step
, mi0
), # RA
1277 (self
.dec2
.in2_step
, mi1
), # RB
1278 (self
.dec2
.in3_step
, mi2
), # RC
1279 (self
.dec2
.o_step
, mo0
), # RT
1280 (self
.dec2
.o2_step
, mo1
), # EA
1282 remap_idxs
= self
.remap_idxs
1284 # now cross-index the required SHAPE for each of 3-in 2-out regs
1285 rnames
= ['RA', 'RB', 'RC', 'RT', 'EA']
1286 for i
, (dstep
, shape_idx
) in enumerate(steps
):
1287 (shape
, remap
) = remaps
[shape_idx
]
1288 remap_idx
= remap_idxs
[shape_idx
]
1289 # zero is "disabled"
1290 if shape
.value
== 0x0:
1292 # now set the actual requested step to the current index
1293 yield dstep
.eq(remap_idx
)
1295 # debug printout info
1296 rremaps
.append((shape
.mode
, i
, rnames
[i
], shape_idx
,
1299 log ("shape remap", x
)
1300 # after that, settle down (combinatorial) to let Vector reg numbers
1301 # work themselves out
1303 remap_active
= yield self
.dec2
.remap_active
1304 log ("remap active", bin(remap_active
))
1306 # main input registers (RT, RA ...)
1308 for name
in input_names
:
1309 # using PowerDecoder2, first, find the decoder index.
1310 # (mapping name RA RB RC RS to in1, in2, in3)
1311 regnum
, is_vec
= yield from get_pdecode_idx_in(self
.dec2
, name
)
1313 # doing this is not part of svp64, it's because output
1314 # registers, to be modified, need to be in the namespace.
1315 regnum
, is_vec
= yield from get_pdecode_idx_out(self
.dec2
, name
)
1317 regnum
, is_vec
= yield from get_pdecode_idx_out2(self
.dec2
,
1320 # in case getting the register number is needed, _RA, _RB
1321 regname
= "_" + name
1322 self
.namespace
[regname
] = regnum
1323 if not self
.is_svp64_mode
or not pred_src_zero
:
1324 log('reading reg %s %s' % (name
, str(regnum
)), is_vec
)
1326 reg_val
= self
.fpr(regnum
)
1327 elif name
is not None:
1328 reg_val
= self
.gpr(regnum
)
1330 log('zero input reg %s %s' % (name
, str(regnum
)), is_vec
)
1332 inputs
.append(reg_val
)
1333 # arrrrgh, awful hack, to get _RT into namespace
1334 if ins_name
in ['setvl', 'svstep']:
1336 RT
= yield self
.dec2
.dec
.RT
1337 self
.namespace
[regname
] = SelectableInt(RT
, 5)
1339 self
.namespace
["RT"] = SelectableInt(0, 5)
1340 regnum
, is_vec
= yield from get_pdecode_idx_out(self
.dec2
, "RT")
1341 log('hack input reg %s %s' % (name
, str(regnum
)), is_vec
)
1343 # in SVP64 mode for LD/ST work out immediate
1344 # XXX TODO: replace_ds for DS-Form rather than D-Form.
1345 # use info.form to detect
1346 replace_d
= False # update / replace constant in pseudocode
1347 if self
.is_svp64_mode
:
1348 ldstmode
= yield self
.dec2
.rm_dec
.ldstmode
1349 # shift mode reads SVD (or SVDS - TODO)
1350 # *BUT*... because this is "overloading" of LD operations,
1351 # it gets *STORED* into D (or DS, TODO)
1352 if ldstmode
== SVP64LDSTmode
.SHIFT
.value
:
1353 imm
= yield self
.dec2
.dec
.fields
.FormSVD
.SVD
[0:11]
1354 imm
= exts(imm
, 11) # sign-extend to integer
1355 log ("shift SVD", imm
)
1358 if info
.form
== 'DS':
1359 # DS-Form, multiply by 4 then knock 2 bits off after
1360 imm
= yield self
.dec2
.dec
.fields
.FormDS
.DS
[0:14] * 4
1362 imm
= yield self
.dec2
.dec
.fields
.FormD
.D
[0:16]
1363 imm
= exts(imm
, 16) # sign-extend to integer
1364 # get the right step. LD is from srcstep, ST is dststep
1365 op
= yield self
.dec2
.e
.do
.insn_type
1367 if op
== MicrOp
.OP_LOAD
.value
:
1369 offsmul
= yield self
.dec2
.in1_step
1370 log("D-field REMAP src", imm
, offsmul
)
1373 log("D-field src", imm
, offsmul
)
1374 elif op
== MicrOp
.OP_STORE
.value
:
1375 # XXX NOTE! no bit-reversed STORE! this should not ever be used
1377 log("D-field dst", imm
, offsmul
)
1378 # bit-reverse mode, rev already done through get_src_dst_steps()
1379 if ldstmode
== SVP64LDSTmode
.SHIFT
.value
:
1380 # manually look up RC, sigh
1381 RC
= yield self
.dec2
.dec
.RC
[0:5]
1383 log ("LD-SHIFT:", "VL", vl
,
1384 "RC", RC
.value
, "imm", imm
,
1385 "offs", bin(offsmul
),
1387 imm
= SelectableInt((imm
* offsmul
) << RC
.value
, 32)
1388 # Unit-Strided LD/ST adds offset*width to immediate
1389 elif ldstmode
== SVP64LDSTmode
.UNITSTRIDE
.value
:
1390 ldst_len
= yield self
.dec2
.e
.do
.data_len
1391 imm
= SelectableInt(imm
+ offsmul
* ldst_len
, 32)
1393 # Element-strided multiplies the immediate by element step
1394 elif ldstmode
== SVP64LDSTmode
.ELSTRIDE
.value
:
1395 imm
= SelectableInt(imm
* offsmul
, 32)
1398 ldst_ra_vec
= yield self
.dec2
.rm_dec
.ldst_ra_vec
1399 ldst_imz_in
= yield self
.dec2
.rm_dec
.ldst_imz_in
1400 log("LDSTmode", SVP64LDSTmode(ldstmode
),
1401 offsmul
, imm
, ldst_ra_vec
, ldst_imz_in
)
1402 # new replacement D... errr.. DS
1404 if info
.form
== 'DS':
1405 # TODO: assert 2 LSBs are zero?
1406 log("DS-Form, TODO, assert 2 LSBs zero?", bin(imm
.value
))
1407 imm
.value
= imm
.value
>> 2
1408 self
.namespace
['DS'] = imm
1410 self
.namespace
['D'] = imm
1412 # "special" registers
1413 for special
in info
.special_regs
:
1414 if special
in special_sprs
:
1415 inputs
.append(self
.spr
[special
])
1417 inputs
.append(self
.namespace
[special
])
1419 # clear trap (trap) NIA
1420 self
.trap_nia
= None
1422 # execute actual instruction here (finally)
1423 log("inputs", inputs
)
1424 results
= info
.func(self
, *inputs
)
1425 log("results", results
)
1427 # "inject" decorator takes namespace from function locals: we need to
1428 # overwrite NIA being overwritten (sigh)
1429 if self
.trap_nia
is not None:
1430 self
.namespace
['NIA'] = self
.trap_nia
1432 log("after func", self
.namespace
['CIA'], self
.namespace
['NIA'])
1434 # check if op was a LD/ST so that debugging can check the
1436 if int_op
in [MicrOp
.OP_STORE
.value
,
1438 self
.last_st_addr
= self
.mem
.last_st_addr
1439 if int_op
in [MicrOp
.OP_LOAD
.value
,
1441 self
.last_ld_addr
= self
.mem
.last_ld_addr
1442 log ("op", int_op
, MicrOp
.OP_STORE
.value
, MicrOp
.OP_LOAD
.value
,
1443 self
.last_st_addr
, self
.last_ld_addr
)
1445 # detect if CA/CA32 already in outputs (sra*, basically)
1448 output_names
= create_args(info
.write_regs
)
1449 for name
in output_names
:
1455 log("carry already done?", bin(already_done
))
1456 if hasattr(self
.dec2
.e
.do
, "output_carry"):
1457 carry_en
= yield self
.dec2
.e
.do
.output_carry
1461 yield from self
.handle_carry_(inputs
, results
, already_done
)
1463 if not self
.is_svp64_mode
: # yeah just no. not in parallel processing
1464 # detect if overflow was in return result
1467 for name
, output
in zip(output_names
, results
):
1468 if name
== 'overflow':
1471 if hasattr(self
.dec2
.e
.do
, "oe"):
1472 ov_en
= yield self
.dec2
.e
.do
.oe
.oe
1473 ov_ok
= yield self
.dec2
.e
.do
.oe
.ok
1477 log("internal overflow", overflow
, ov_en
, ov_ok
)
1479 yield from self
.handle_overflow(inputs
, results
, overflow
)
1481 # only do SVP64 dest predicated Rc=1 if dest-pred is not enabled
1483 if not self
.is_svp64_mode
or not pred_dst_zero
:
1484 if hasattr(self
.dec2
.e
.do
, "rc"):
1485 rc_en
= yield self
.dec2
.e
.do
.rc
.rc
1486 if rc_en
and ins_name
not in ['svstep']:
1487 regnum
, is_vec
= yield from get_pdecode_cr_out(self
.dec2
, "CR0")
1488 self
.handle_comparison(results
, regnum
)
1490 # any modified return results?
1492 for name
, output
in zip(output_names
, results
):
1493 if name
== 'overflow': # ignore, done already (above)
1495 if isinstance(output
, int):
1496 output
= SelectableInt(output
, 256)
1497 if name
in ['CA', 'CA32']:
1499 log("writing %s to XER" % name
, output
)
1500 self
.spr
['XER'][XER_bits
[name
]] = output
.value
1502 log("NOT writing %s to XER" % name
, output
)
1503 elif name
in info
.special_regs
:
1504 log('writing special %s' % name
, output
, special_sprs
)
1505 if name
in special_sprs
:
1506 self
.spr
[name
] = output
1508 self
.namespace
[name
].eq(output
)
1510 log('msr written', hex(self
.msr
.value
))
1512 regnum
, is_vec
= yield from get_pdecode_idx_out(self
.dec2
,
1515 regnum
, is_vec
= yield from get_pdecode_idx_out2(
1518 # temporary hack for not having 2nd output
1519 regnum
= yield getattr(self
.decoder
, name
)
1521 if self
.is_svp64_mode
and pred_dst_zero
:
1522 log('zeroing reg %d %s' % (regnum
, str(output
)),
1524 output
= SelectableInt(0, 256)
1530 log('writing %s %s %s' % (ftype
, regnum
, str(output
)),
1532 if output
.bits
> 64:
1533 output
= SelectableInt(output
.value
, 64)
1535 self
.fpr
[regnum
] = output
1537 self
.gpr
[regnum
] = output
1539 # check if it is the SVSTATE.src/dest step that needs incrementing
1540 # this is our Sub-Program-Counter loop from 0 to VL-1
1543 if self
.allow_next_step_inc
:
1544 log("SVSTATE_NEXT: inc requested, mode",
1545 self
.svstate_next_mode
, self
.allow_next_step_inc
)
1546 yield from self
.svstate_pre_inc()
1547 pre
= yield from self
.update_new_svstate_steps()
1549 # reset at end of loop including exit Vertical Mode
1550 log ("SVSTATE_NEXT: end of loop, reset")
1551 self
.svp64_reset_loop()
1552 self
.svstate
.vfirst
= 0
1555 results
= [SelectableInt(0, 64)]
1556 self
.handle_comparison(results
) # CR0
1558 if self
.allow_next_step_inc
== 2:
1559 log ("SVSTATE_NEXT: read")
1560 yield from self
.svstate_post_inc()
1562 log ("SVSTATE_NEXT: post-inc")
1563 # use actual src/dst-step here to check end, do NOT
1564 # use bit-reversed version
1565 srcstep
, dststep
= self
.new_srcstep
, self
.new_dststep
1566 remaps
= self
.get_remap_indices()
1567 remap_idxs
= self
.remap_idxs
1568 vl
= self
.svstate
.vl
1569 end_src
= srcstep
== vl
-1
1570 end_dst
= dststep
== vl
-1
1571 if self
.allow_next_step_inc
!= 2:
1573 self
.svstate
.srcstep
+= SelectableInt(1, 7)
1575 self
.svstate
.dststep
+= SelectableInt(1, 7)
1576 self
.namespace
['SVSTATE'] = self
.svstate
.spr
1577 # set CR0 (if Rc=1) based on end
1579 srcstep
= self
.svstate
.srcstep
1580 dststep
= self
.svstate
.srcstep
1581 endtest
= 1 if (end_src
or end_dst
) else 0
1582 #results = [SelectableInt(endtest, 64)]
1583 #self.handle_comparison(results) # CR0
1585 # see if svstep was requested, if so, which SVSTATE
1587 if self
.svstate_next_mode
> 0:
1588 shape_idx
= self
.svstate_next_mode
.value
-1
1589 endings
= self
.remap_loopends
[shape_idx
]
1590 cr_field
= SelectableInt((~endings
)<<1 | endtest
, 4)
1591 print ("svstep Rc=1, CR0", cr_field
)
1592 self
.crl
[0].eq(cr_field
) # CR0
1593 if end_src
or end_dst
:
1594 # reset at end of loop including exit Vertical Mode
1595 log ("SVSTATE_NEXT: after increments, reset")
1596 self
.svp64_reset_loop()
1597 self
.svstate
.vfirst
= 0
1599 elif self
.is_svp64_mode
:
1600 yield from self
.svstate_post_inc()
1602 # XXX only in non-SVP64 mode!
1603 # record state of whether the current operation was an svshape,
1604 # to be able to know if it should apply in the next instruction.
1605 # also (if going to use this instruction) should disable ability
1606 # to interrupt in between. sigh.
1607 self
.last_op_svshape
= asmop
== 'svremap'
1609 self
.update_pc_next()
1611 def SVSTATE_NEXT(self
, mode
, submode
):
1612 """explicitly moves srcstep/dststep on to next element, for
1613 "Vertical-First" mode. this function is called from
1614 setvl pseudo-code, as a pseudo-op "svstep"
1616 WARNING: this function uses information that was created EARLIER
1617 due to it being in the middle of a yield, but this function is
1618 *NOT* called from yield (it's called from compiled pseudocode).
1620 self
.allow_next_step_inc
= submode
.value
+ 1
1621 log("SVSTATE_NEXT mode", mode
, submode
, self
.allow_next_step_inc
)
1622 self
.svstate_next_mode
= mode
1623 if self
.svstate_next_mode
> 0:
1624 shape_idx
= self
.svstate_next_mode
.value
-1
1625 return SelectableInt(self
.remap_idxs
[shape_idx
], 7)
1626 return SelectableInt(0, 7)
1628 def svstate_pre_inc(self
):
1629 """check if srcstep/dststep need to skip over masked-out predicate bits
1631 # get SVSTATE VL (oh and print out some debug stuff)
1632 vl
= self
.svstate
.vl
1633 srcstep
= self
.svstate
.srcstep
1634 dststep
= self
.svstate
.dststep
1635 sv_a_nz
= yield self
.dec2
.sv_a_nz
1636 fft_mode
= yield self
.dec2
.use_svp64_fft
1637 in1
= yield self
.dec2
.e
.read_reg1
.data
1638 log ("SVP64: VL, srcstep, dststep, sv_a_nz, in1 fft, svp64",
1639 vl
, srcstep
, dststep
, sv_a_nz
, in1
, fft_mode
,
1642 # get predicate mask
1643 srcmask
= dstmask
= 0xffff_ffff_ffff_ffff
1645 pmode
= yield self
.dec2
.rm_dec
.predmode
1646 reverse_gear
= yield self
.dec2
.rm_dec
.reverse_gear
1647 sv_ptype
= yield self
.dec2
.dec
.op
.SV_Ptype
1648 srcpred
= yield self
.dec2
.rm_dec
.srcpred
1649 dstpred
= yield self
.dec2
.rm_dec
.dstpred
1650 pred_src_zero
= yield self
.dec2
.rm_dec
.pred_sz
1651 pred_dst_zero
= yield self
.dec2
.rm_dec
.pred_dz
1652 if pmode
== SVP64PredMode
.INT
.value
:
1653 srcmask
= dstmask
= get_predint(self
.gpr
, dstpred
)
1654 if sv_ptype
== SVPtype
.P2
.value
:
1655 srcmask
= get_predint(self
.gpr
, srcpred
)
1656 elif pmode
== SVP64PredMode
.CR
.value
:
1657 srcmask
= dstmask
= get_predcr(self
.crl
, dstpred
, vl
)
1658 if sv_ptype
== SVPtype
.P2
.value
:
1659 srcmask
= get_predcr(self
.crl
, srcpred
, vl
)
1660 log (" pmode", pmode
)
1661 log (" reverse", reverse_gear
)
1662 log (" ptype", sv_ptype
)
1663 log (" srcpred", bin(srcpred
))
1664 log (" dstpred", bin(dstpred
))
1665 log (" srcmask", bin(srcmask
))
1666 log (" dstmask", bin(dstmask
))
1667 log (" pred_sz", bin(pred_src_zero
))
1668 log (" pred_dz", bin(pred_dst_zero
))
1670 # okaaay, so here we simply advance srcstep (TODO dststep)
1671 # until the predicate mask has a "1" bit... or we run out of VL
1672 # let srcstep==VL be the indicator to move to next instruction
1673 if not pred_src_zero
:
1674 while (((1<<srcstep
) & srcmask
) == 0) and (srcstep
!= vl
):
1675 log (" skip", bin(1<<srcstep
))
1678 if not pred_dst_zero
:
1679 while (((1<<dststep
) & dstmask
) == 0) and (dststep
!= vl
):
1680 log (" skip", bin(1<<dststep
))
1683 # now work out if the relevant mask bits require zeroing
1685 pred_dst_zero
= ((1<<dststep
) & dstmask
) == 0
1687 pred_src_zero
= ((1<<srcstep
) & srcmask
) == 0
1689 # store new srcstep / dststep
1690 self
.new_srcstep
, self
.new_dststep
= srcstep
, dststep
1691 self
.pred_dst_zero
, self
.pred_src_zero
= pred_dst_zero
, pred_src_zero
1692 log (" new srcstep", srcstep
)
1693 log (" new dststep", dststep
)
1695 def get_src_dststeps(self
):
1696 """gets srcstep and dststep
1698 return self
.new_srcstep
, self
.new_dststep
1700 def update_new_svstate_steps(self
):
1701 # note, do not get the bit-reversed srcstep here!
1702 srcstep
, dststep
= self
.new_srcstep
, self
.new_dststep
1704 # update SVSTATE with new srcstep
1705 self
.svstate
.srcstep
= srcstep
1706 self
.svstate
.dststep
= dststep
1707 self
.namespace
['SVSTATE'] = self
.svstate
1708 yield self
.dec2
.state
.svstate
.eq(self
.svstate
.value
)
1709 yield Settle() # let decoder update
1710 srcstep
= self
.svstate
.srcstep
1711 dststep
= self
.svstate
.dststep
1712 vl
= self
.svstate
.vl
1713 log (" srcstep", srcstep
)
1714 log (" dststep", dststep
)
1717 # check if end reached (we let srcstep overrun, above)
1718 # nothing needs doing (TODO zeroing): just do next instruction
1719 return srcstep
== vl
or dststep
== vl
1721 def svstate_post_inc(self
, vf
=0):
1722 # check if SV "Vertical First" mode is enabled
1723 vfirst
= self
.svstate
.vfirst
1724 log (" SV Vertical First", vf
, vfirst
)
1725 if not vf
and vfirst
== 1:
1729 # check if it is the SVSTATE.src/dest step that needs incrementing
1730 # this is our Sub-Program-Counter loop from 0 to VL-1
1731 # XXX twin predication TODO
1732 vl
= self
.svstate
.vl
1733 mvl
= self
.svstate
.maxvl
1734 srcstep
= self
.svstate
.srcstep
1735 dststep
= self
.svstate
.dststep
1736 rm_mode
= yield self
.dec2
.rm_dec
.mode
1737 reverse_gear
= yield self
.dec2
.rm_dec
.reverse_gear
1738 sv_ptype
= yield self
.dec2
.dec
.op
.SV_Ptype
1739 out_vec
= not (yield self
.dec2
.no_out_vec
)
1740 in_vec
= not (yield self
.dec2
.no_in_vec
)
1741 log (" svstate.vl", vl
)
1742 log (" svstate.mvl", mvl
)
1743 log (" svstate.srcstep", srcstep
)
1744 log (" svstate.dststep", dststep
)
1745 log (" mode", rm_mode
)
1746 log (" reverse", reverse_gear
)
1747 log (" out_vec", out_vec
)
1748 log (" in_vec", in_vec
)
1749 log (" sv_ptype", sv_ptype
, sv_ptype
== SVPtype
.P2
.value
)
1750 # check if srcstep needs incrementing by one, stop PC advancing
1751 # svp64 loop can end early if the dest is scalar for single-pred
1752 # but for 2-pred both src/dest have to be checked.
1753 # XXX this might not be true! it may just be LD/ST
1754 if sv_ptype
== SVPtype
.P2
.value
:
1755 svp64_is_vector
= (out_vec
or in_vec
)
1757 svp64_is_vector
= out_vec
1758 if svp64_is_vector
and srcstep
!= vl
-1 and dststep
!= vl
-1:
1759 self
.svstate
.srcstep
+= SelectableInt(1, 7)
1760 self
.svstate
.dststep
+= SelectableInt(1, 7)
1761 self
.pc
.NIA
.value
= self
.pc
.CIA
.value
1762 self
.namespace
['NIA'] = self
.pc
.NIA
1763 self
.namespace
['SVSTATE'] = self
.svstate
1764 log("end of sub-pc call", self
.namespace
['CIA'],
1765 self
.namespace
['NIA'])
1766 return False # DO NOT allow PC update whilst Sub-PC loop running
1768 # reset loop to zero and update NIA
1769 self
.svp64_reset_loop()
1774 def update_pc_next(self
):
1775 # UPDATE program counter
1776 self
.pc
.update(self
.namespace
, self
.is_svp64_mode
)
1777 self
.svstate
.spr
= self
.namespace
['SVSTATE']
1778 log("end of call", self
.namespace
['CIA'],
1779 self
.namespace
['NIA'],
1780 self
.namespace
['SVSTATE'])
1782 def svp64_reset_loop(self
):
1783 self
.svstate
.srcstep
= 0
1784 self
.svstate
.dststep
= 0
1785 log (" svstate.srcstep loop end (PC to update)")
1786 self
.namespace
['SVSTATE'] = self
.svstate
1788 def update_nia(self
):
1789 self
.pc
.update_nia(self
.is_svp64_mode
)
1790 self
.namespace
['NIA'] = self
.pc
.NIA
1793 """Decorator factory.
1795 this decorator will "inject" variables into the function's namespace,
1796 from the *dictionary* in self.namespace. it therefore becomes possible
1797 to make it look like a whole stack of variables which would otherwise
1798 need "self." inserted in front of them (*and* for those variables to be
1799 added to the instance) "appear" in the function.
1801 "self.namespace['SI']" for example becomes accessible as just "SI" but
1802 *only* inside the function, when decorated.
1804 def variable_injector(func
):
1806 def decorator(*args
, **kwargs
):
1808 func_globals
= func
.__globals
__ # Python 2.6+
1809 except AttributeError:
1810 func_globals
= func
.func_globals
# Earlier versions.
1812 context
= args
[0].namespace
# variables to be injected
1813 saved_values
= func_globals
.copy() # Shallow copy of dict.
1814 log("globals before", context
.keys())
1815 func_globals
.update(context
)
1816 result
= func(*args
, **kwargs
)
1817 log("globals after", func_globals
['CIA'], func_globals
['NIA'])
1818 log("args[0]", args
[0].namespace
['CIA'],
1819 args
[0].namespace
['NIA'],
1820 args
[0].namespace
['SVSTATE'])
1821 args
[0].namespace
= func_globals
1822 #exec (func.__code__, func_globals)
1825 # func_globals = saved_values # Undo changes.
1831 return variable_injector