1 # SPDX-License-Identifier: LGPLv3+
2 # Copyright (C) 2020, 2021 Luke Kenneth Casson Leighton <lkcl@lkcl.net>
3 # Copyright (C) 2020 Michael Nolan
4 # Funded by NLnet http://nlnet.nl
5 """core of the python-based POWER9 simulator
7 this is part of a cycle-accurate POWER9 simulator. its primary purpose is
8 not speed, it is for both learning and educational purposes, as well as
9 a method of verifying the HDL.
13 * https://bugs.libre-soc.org/show_bug.cgi?id=424
16 from nmigen
.back
.pysim
import Settle
17 from functools
import wraps
19 from openpower
.decoder
.orderedset
import OrderedSet
20 from openpower
.decoder
.selectable_int
import (FieldSelectableInt
, SelectableInt
,
22 from openpower
.decoder
.power_enums
import (spr_dict
, spr_byname
, XER_bits
,
23 insns
, MicrOp
, In1Sel
, In2Sel
, In3Sel
,
24 OutSel
, CROutSel
, LDSTMode
,
25 SVP64RMMode
, SVP64PredMode
,
26 SVP64PredInt
, SVP64PredCR
,
29 from openpower
.decoder
.power_enums
import SVPtype
31 from openpower
.decoder
.helpers
import (exts
, gtu
, ltu
, undefined
, bitrev
)
32 from openpower
.consts
import PIb
, MSRb
# big-endian (PowerISA versions)
33 from openpower
.consts
import SVP64CROffs
34 from openpower
.decoder
.power_svp64
import SVP64RM
, decode_extra
36 from openpower
.decoder
.isa
.radixmmu
import RADIX
37 from openpower
.decoder
.isa
.mem
import Mem
, swap_order
, MemException
38 from openpower
.decoder
.isa
.svshape
import SVSHAPE
39 from openpower
.decoder
.isa
.svstate
import SVP64State
42 from openpower
.util
import log
44 from collections
import namedtuple
48 instruction_info
= namedtuple('instruction_info',
49 'func read_regs uninit_regs write_regs ' +
50 'special_regs op_fields form asmregs')
61 # TODO (lkcl): adjust other registers that should be in a particular order
62 # probably CA, CA32, and CR
87 "overflow": 7, # should definitely be last
90 fregs
= ['FRA', 'FRB', 'FRC', 'FRS', 'FRT']
93 def create_args(reglist
, extra
=None):
94 retval
= list(OrderedSet(reglist
))
95 retval
.sort(key
=lambda reg
: REG_SORT_ORDER
.get(reg
, 0))
97 return [extra
] + retval
103 def __init__(self
, decoder
, isacaller
, svstate
, regfile
):
106 self
.isacaller
= isacaller
107 self
.svstate
= svstate
108 for i
in range(len(regfile
)):
109 self
[i
] = SelectableInt(regfile
[i
], 64)
111 def __call__(self
, ridx
):
112 if isinstance(ridx
, SelectableInt
):
116 def set_form(self
, form
):
119 def __setitem__(self
, rnum
, value
):
120 # rnum = rnum.value # only SelectableInt allowed
121 log("GPR setitem", rnum
, value
)
122 if isinstance(rnum
, SelectableInt
):
124 dict.__setitem
__(self
, rnum
, value
)
126 def getz(self
, rnum
):
127 # rnum = rnum.value # only SelectableInt allowed
128 log("GPR getzero?", rnum
)
130 return SelectableInt(0, 64)
133 def _get_regnum(self
, attr
):
134 getform
= self
.sd
.sigforms
[self
.form
]
135 rnum
= getattr(getform
, attr
)
138 def ___getitem__(self
, attr
):
139 """ XXX currently not used
141 rnum
= self
._get
_regnum
(attr
)
142 log("GPR getitem", attr
, rnum
)
143 return self
.regfile
[rnum
]
145 def dump(self
, printout
=True):
147 for i
in range(len(self
)):
148 res
.append(self
[i
].value
)
150 for i
in range(0, len(res
), 8):
153 s
.append("%08x" % res
[i
+j
])
155 print("reg", "%2d" % i
, s
)
160 def __init__(self
, dec2
, initial_sprs
={}):
163 for key
, v
in initial_sprs
.items():
164 if isinstance(key
, SelectableInt
):
166 key
= special_sprs
.get(key
, key
)
167 if isinstance(key
, int):
170 info
= spr_byname
[key
]
171 if not isinstance(v
, SelectableInt
):
172 v
= SelectableInt(v
, info
.length
)
175 def __getitem__(self
, key
):
177 log("dict", self
.items())
178 # if key in special_sprs get the special spr, otherwise return key
179 if isinstance(key
, SelectableInt
):
181 if isinstance(key
, int):
182 key
= spr_dict
[key
].SPR
183 key
= special_sprs
.get(key
, key
)
184 if key
== 'HSRR0': # HACK!
186 if key
== 'HSRR1': # HACK!
189 res
= dict.__getitem
__(self
, key
)
191 if isinstance(key
, int):
194 info
= spr_byname
[key
]
195 dict.__setitem
__(self
, key
, SelectableInt(0, info
.length
))
196 res
= dict.__getitem
__(self
, key
)
197 log("spr returning", key
, res
)
200 def __setitem__(self
, key
, value
):
201 if isinstance(key
, SelectableInt
):
203 if isinstance(key
, int):
204 key
= spr_dict
[key
].SPR
206 key
= special_sprs
.get(key
, key
)
207 if key
== 'HSRR0': # HACK!
208 self
.__setitem
__('SRR0', value
)
209 if key
== 'HSRR1': # HACK!
210 self
.__setitem
__('SRR1', value
)
211 log("setting spr", key
, value
)
212 dict.__setitem
__(self
, key
, value
)
214 def __call__(self
, ridx
):
217 def dump(self
, printout
=True):
219 keys
= list(self
.keys())
222 sprname
= spr_dict
.get(k
, None)
226 sprname
= sprname
.SPR
227 res
.append((sprname
, self
[k
].value
))
229 for sprname
, value
in res
:
230 print(" ", sprname
, hex(value
))
235 def __init__(self
, pc_init
=0):
236 self
.CIA
= SelectableInt(pc_init
, 64)
237 self
.NIA
= self
.CIA
+ SelectableInt(4, 64) # only true for v3.0B!
239 def update_nia(self
, is_svp64
):
240 increment
= 8 if is_svp64
else 4
241 self
.NIA
= self
.CIA
+ SelectableInt(increment
, 64)
243 def update(self
, namespace
, is_svp64
):
244 """updates the program counter (PC) by 4 if v3.0B mode or 8 if SVP64
246 self
.CIA
= namespace
['NIA'].narrow(64)
247 self
.update_nia(is_svp64
)
248 namespace
['CIA'] = self
.CIA
249 namespace
['NIA'] = self
.NIA
254 def __init__(self
, init
=0):
255 self
.spr
= SelectableInt(init
, 24)
256 # SVP64 RM fields: see https://libre-soc.org/openpower/sv/svp64/
257 self
.mmode
= FieldSelectableInt(self
.spr
, [0])
258 self
.mask
= FieldSelectableInt(self
.spr
, tuple(range(1,4)))
259 self
.elwidth
= FieldSelectableInt(self
.spr
, tuple(range(4,6)))
260 self
.ewsrc
= FieldSelectableInt(self
.spr
, tuple(range(6,8)))
261 self
.subvl
= FieldSelectableInt(self
.spr
, tuple(range(8,10)))
262 self
.extra
= FieldSelectableInt(self
.spr
, tuple(range(10,19)))
263 self
.mode
= FieldSelectableInt(self
.spr
, tuple(range(19,24)))
264 # these cover the same extra field, split into parts as EXTRA2
265 self
.extra2
= list(range(4))
266 self
.extra2
[0] = FieldSelectableInt(self
.spr
, tuple(range(10,12)))
267 self
.extra2
[1] = FieldSelectableInt(self
.spr
, tuple(range(12,14)))
268 self
.extra2
[2] = FieldSelectableInt(self
.spr
, tuple(range(14,16)))
269 self
.extra2
[3] = FieldSelectableInt(self
.spr
, tuple(range(16,18)))
270 self
.smask
= FieldSelectableInt(self
.spr
, tuple(range(16,19)))
271 # and here as well, but EXTRA3
272 self
.extra3
= list(range(3))
273 self
.extra3
[0] = FieldSelectableInt(self
.spr
, tuple(range(10,13)))
274 self
.extra3
[1] = FieldSelectableInt(self
.spr
, tuple(range(13,16)))
275 self
.extra3
[2] = FieldSelectableInt(self
.spr
, tuple(range(16,19)))
278 SVP64RM_MMODE_SIZE
= len(SVP64RMFields().mmode
.br
)
279 SVP64RM_MASK_SIZE
= len(SVP64RMFields().mask
.br
)
280 SVP64RM_ELWIDTH_SIZE
= len(SVP64RMFields().elwidth
.br
)
281 SVP64RM_EWSRC_SIZE
= len(SVP64RMFields().ewsrc
.br
)
282 SVP64RM_SUBVL_SIZE
= len(SVP64RMFields().subvl
.br
)
283 SVP64RM_EXTRA2_SPEC_SIZE
= len(SVP64RMFields().extra2
[0].br
)
284 SVP64RM_EXTRA3_SPEC_SIZE
= len(SVP64RMFields().extra3
[0].br
)
285 SVP64RM_SMASK_SIZE
= len(SVP64RMFields().smask
.br
)
286 SVP64RM_MODE_SIZE
= len(SVP64RMFields().mode
.br
)
289 # SVP64 Prefix fields: see https://libre-soc.org/openpower/sv/svp64/
290 class SVP64PrefixFields
:
292 self
.insn
= SelectableInt(0, 32)
293 # 6 bit major opcode EXT001, 2 bits "identifying" (7, 9), 24 SV ReMap
294 self
.major
= FieldSelectableInt(self
.insn
, tuple(range(0,6)))
295 self
.pid
= FieldSelectableInt(self
.insn
, (7, 9)) # must be 0b11
296 rmfields
= [6, 8] + list(range(10,32)) # SVP64 24-bit RM (ReMap)
297 self
.rm
= FieldSelectableInt(self
.insn
, rmfields
)
300 SV64P_MAJOR_SIZE
= len(SVP64PrefixFields().major
.br
)
301 SV64P_PID_SIZE
= len(SVP64PrefixFields().pid
.br
)
302 SV64P_RM_SIZE
= len(SVP64PrefixFields().rm
.br
)
306 # See PowerISA Version 3.0 B Book 1
307 # Section 2.3.1 Condition Register pages 30 - 31
309 LT
= FL
= 0 # negative, less than, floating-point less than
310 GT
= FG
= 1 # positive, greater than, floating-point greater than
311 EQ
= FE
= 2 # equal, floating-point equal
312 SO
= FU
= 3 # summary overflow, floating-point unordered
314 def __init__(self
, init
=0):
315 # rev_cr = int('{:016b}'.format(initial_cr)[::-1], 2)
316 # self.cr = FieldSelectableInt(self._cr, list(range(32, 64)))
317 self
.cr
= SelectableInt(init
, 64) # underlying reg
318 # field-selectable versions of Condition Register TODO check bitranges?
321 bits
= tuple(range(i
*4+32, (i
+1)*4+32))
322 _cr
= FieldSelectableInt(self
.cr
, bits
)
325 # decode SVP64 predicate integer to reg number and invert
326 def get_predint(gpr
, mask
):
329 log ("get_predint", mask
, SVP64PredInt
.ALWAYS
.value
)
330 if mask
== SVP64PredInt
.ALWAYS
.value
:
331 return 0xffff_ffff_ffff_ffff
332 if mask
== SVP64PredInt
.R3_UNARY
.value
:
333 return 1 << (gpr(3).value
& 0b111111)
334 if mask
== SVP64PredInt
.R3
.value
:
336 if mask
== SVP64PredInt
.R3_N
.value
:
338 if mask
== SVP64PredInt
.R10
.value
:
340 if mask
== SVP64PredInt
.R10_N
.value
:
341 return ~
gpr(10).value
342 if mask
== SVP64PredInt
.R30
.value
:
344 if mask
== SVP64PredInt
.R30_N
.value
:
345 return ~
gpr(30).value
347 # decode SVP64 predicate CR to reg number and invert status
348 def _get_predcr(mask
):
349 if mask
== SVP64PredCR
.LT
.value
:
351 if mask
== SVP64PredCR
.GE
.value
:
353 if mask
== SVP64PredCR
.GT
.value
:
355 if mask
== SVP64PredCR
.LE
.value
:
357 if mask
== SVP64PredCR
.EQ
.value
:
359 if mask
== SVP64PredCR
.NE
.value
:
361 if mask
== SVP64PredCR
.SO
.value
:
363 if mask
== SVP64PredCR
.NS
.value
:
366 # read individual CR fields (0..VL-1), extract the required bit
367 # and construct the mask
368 def get_predcr(crl
, mask
, vl
):
369 idx
, noninv
= _get_predcr(mask
)
372 cr
= crl
[i
+SVP64CROffs
.CRPred
]
373 if cr
[idx
].value
== noninv
:
378 # TODO, really should just be using PowerDecoder2
379 def get_pdecode_idx_in(dec2
, name
):
381 in1_sel
= yield op
.in1_sel
382 in2_sel
= yield op
.in2_sel
383 in3_sel
= yield op
.in3_sel
384 # get the IN1/2/3 from the decoder (includes SVP64 remap and isvec)
385 in1
= yield dec2
.e
.read_reg1
.data
386 in2
= yield dec2
.e
.read_reg2
.data
387 in3
= yield dec2
.e
.read_reg3
.data
388 in1_isvec
= yield dec2
.in1_isvec
389 in2_isvec
= yield dec2
.in2_isvec
390 in3_isvec
= yield dec2
.in3_isvec
391 log ("get_pdecode_idx_in in1", name
, in1_sel
, In1Sel
.RA
.value
,
393 log ("get_pdecode_idx_in in2", name
, in2_sel
, In2Sel
.RB
.value
,
395 log ("get_pdecode_idx_in in3", name
, in3_sel
, In3Sel
.RS
.value
,
397 log ("get_pdecode_idx_in FRS in3", name
, in3_sel
, In3Sel
.FRS
.value
,
399 log ("get_pdecode_idx_in FRB in2", name
, in2_sel
, In2Sel
.FRB
.value
,
401 log ("get_pdecode_idx_in FRC in3", name
, in3_sel
, In3Sel
.FRC
.value
,
403 # identify which regnames map to in1/2/3
405 if (in1_sel
== In1Sel
.RA
.value
or
406 (in1_sel
== In1Sel
.RA_OR_ZERO
.value
and in1
!= 0)):
407 return in1
, in1_isvec
408 if in1_sel
== In1Sel
.RA_OR_ZERO
.value
:
409 return in1
, in1_isvec
411 if in2_sel
== In2Sel
.RB
.value
:
412 return in2
, in2_isvec
413 if in3_sel
== In3Sel
.RB
.value
:
414 return in3
, in3_isvec
415 # XXX TODO, RC doesn't exist yet!
417 assert False, "RC does not exist yet"
419 if in1_sel
== In1Sel
.RS
.value
:
420 return in1
, in1_isvec
421 if in2_sel
== In2Sel
.RS
.value
:
422 return in2
, in2_isvec
423 if in3_sel
== In3Sel
.RS
.value
:
424 return in3
, in3_isvec
426 if in1_sel
== In1Sel
.FRA
.value
:
427 return in1
, in1_isvec
429 if in2_sel
== In2Sel
.FRB
.value
:
430 return in2
, in2_isvec
432 if in3_sel
== In3Sel
.FRC
.value
:
433 return in3
, in3_isvec
435 if in1_sel
== In1Sel
.FRS
.value
:
436 return in1
, in1_isvec
437 if in3_sel
== In3Sel
.FRS
.value
:
438 return in3
, in3_isvec
442 # TODO, really should just be using PowerDecoder2
443 def get_pdecode_cr_out(dec2
, name
):
445 out_sel
= yield op
.cr_out
446 out_bitfield
= yield dec2
.dec_cr_out
.cr_bitfield
.data
447 sv_cr_out
= yield op
.sv_cr_out
448 spec
= yield dec2
.crout_svdec
.spec
449 sv_override
= yield dec2
.dec_cr_out
.sv_override
450 # get the IN1/2/3 from the decoder (includes SVP64 remap and isvec)
451 out
= yield dec2
.e
.write_cr
.data
452 o_isvec
= yield dec2
.o_isvec
453 log ("get_pdecode_cr_out", out_sel
, CROutSel
.CR0
.value
, out
, o_isvec
)
454 log (" sv_cr_out", sv_cr_out
)
455 log (" cr_bf", out_bitfield
)
457 log (" override", sv_override
)
458 # identify which regnames map to out / o2
460 if out_sel
== CROutSel
.CR0
.value
:
462 log ("get_pdecode_cr_out not found", name
)
466 # TODO, really should just be using PowerDecoder2
467 def get_pdecode_idx_out(dec2
, name
):
469 out_sel
= yield op
.out_sel
470 # get the IN1/2/3 from the decoder (includes SVP64 remap and isvec)
471 out
= yield dec2
.e
.write_reg
.data
472 o_isvec
= yield dec2
.o_isvec
473 # identify which regnames map to out / o2
475 log ("get_pdecode_idx_out", out_sel
, OutSel
.RA
.value
, out
, o_isvec
)
476 if out_sel
== OutSel
.RA
.value
:
479 log ("get_pdecode_idx_out", out_sel
, OutSel
.RT
.value
,
480 OutSel
.RT_OR_ZERO
.value
, out
, o_isvec
,
482 if out_sel
== OutSel
.RT
.value
:
484 elif name
== 'RT_OR_ZERO':
485 log ("get_pdecode_idx_out", out_sel
, OutSel
.RT
.value
,
486 OutSel
.RT_OR_ZERO
.value
, out
, o_isvec
,
488 if out_sel
== OutSel
.RT_OR_ZERO
.value
:
491 log ("get_pdecode_idx_out", out_sel
, OutSel
.FRA
.value
, out
, o_isvec
)
492 if out_sel
== OutSel
.FRA
.value
:
495 log ("get_pdecode_idx_out", out_sel
, OutSel
.FRT
.value
,
496 OutSel
.FRT
.value
, out
, o_isvec
)
497 if out_sel
== OutSel
.FRT
.value
:
499 log ("get_pdecode_idx_out not found", name
, out_sel
, out
, o_isvec
)
503 # TODO, really should just be using PowerDecoder2
504 def get_pdecode_idx_out2(dec2
, name
):
505 # check first if register is activated for write
507 out_sel
= yield op
.out_sel
508 out
= yield dec2
.e
.write_ea
.data
509 o_isvec
= yield dec2
.o2_isvec
510 out_ok
= yield dec2
.e
.write_ea
.ok
511 log ("get_pdecode_idx_out2", name
, out_sel
, out
, out_ok
, o_isvec
)
516 if hasattr(op
, "upd"):
517 # update mode LD/ST uses read-reg A also as an output
519 log ("get_pdecode_idx_out2", upd
, LDSTMode
.update
.value
,
520 out_sel
, OutSel
.RA
.value
,
522 if upd
== LDSTMode
.update
.value
:
525 int_op
= yield dec2
.dec
.op
.internal_op
526 fft_en
= yield dec2
.use_svp64_fft
527 #if int_op == MicrOp.OP_FP_MADD.value and fft_en:
529 log ("get_pdecode_idx_out2", out_sel
, OutSel
.FRS
.value
,
536 # decoder2 - an instance of power_decoder2
537 # regfile - a list of initial values for the registers
538 # initial_{etc} - initial values for SPRs, Condition Register, Mem, MSR
539 # respect_pc - tracks the program counter. requires initial_insns
540 def __init__(self
, decoder2
, regfile
, initial_sprs
=None, initial_cr
=0,
541 initial_mem
=None, initial_msr
=0,
552 self
.bigendian
= bigendian
554 self
.is_svp64_mode
= False
555 self
.respect_pc
= respect_pc
556 if initial_sprs
is None:
558 if initial_mem
is None:
560 if fpregfile
is None:
562 if initial_insns
is None:
564 assert self
.respect_pc
== False, "instructions required to honor pc"
566 log("ISACaller insns", respect_pc
, initial_insns
, disassembly
)
567 log("ISACaller initial_msr", initial_msr
)
569 # "fake program counter" mode (for unit testing)
573 if isinstance(initial_mem
, tuple):
574 self
.fake_pc
= initial_mem
[0]
575 disasm_start
= self
.fake_pc
577 disasm_start
= initial_pc
579 # disassembly: we need this for now (not given from the decoder)
580 self
.disassembly
= {}
582 for i
, code
in enumerate(disassembly
):
583 self
.disassembly
[i
*4 + disasm_start
] = code
585 # set up registers, instruction memory, data memory, PC, SPRs, MSR, CR
586 self
.svp64rm
= SVP64RM()
587 if initial_svstate
is None:
589 if isinstance(initial_svstate
, int):
590 initial_svstate
= SVP64State(initial_svstate
)
591 # SVSTATE, MSR and PC
592 self
.svstate
= initial_svstate
593 self
.msr
= SelectableInt(initial_msr
, 64) # underlying reg
595 # GPR FPR SPR registers
596 self
.gpr
= GPR(decoder2
, self
, self
.svstate
, regfile
)
597 self
.fpr
= GPR(decoder2
, self
, self
.svstate
, fpregfile
)
598 self
.spr
= SPR(decoder2
, initial_sprs
) # initialise SPRs before MMU
600 # set up 4 dummy SVSHAPEs if they aren't already set up
602 sname
= 'SVSHAPE%d' % i
603 if sname
not in self
.spr
:
604 self
.spr
[sname
] = SVSHAPE(0)
606 # make sure it's an SVSHAPE
607 val
= self
.spr
[sname
].value
608 self
.spr
[sname
] = SVSHAPE(val
)
609 self
.last_op_svshape
= False
612 self
.mem
= Mem(row_bytes
=8, initial_mem
=initial_mem
)
613 self
.imem
= Mem(row_bytes
=4, initial_mem
=initial_insns
)
614 # MMU mode, redirect underlying Mem through RADIX
616 self
.mem
= RADIX(self
.mem
, self
)
618 self
.imem
= RADIX(self
.imem
, self
)
621 # FPR (same as GPR except for FP nums)
622 # 4.2.2 p124 FPSCR (definitely "separate" - not in SPR)
623 # note that mffs, mcrfs, mtfsf "manage" this FPSCR
624 # 2.3.1 CR (and sub-fields CR0..CR6 - CR0 SO comes from XER.SO)
625 # note that mfocrf, mfcr, mtcr, mtocrf, mcrxrx "manage" CRs
627 # 2.3.2 LR (actually SPR #8) -- Done
628 # 2.3.3 CTR (actually SPR #9) -- Done
629 # 2.3.4 TAR (actually SPR #815)
630 # 3.2.2 p45 XER (actually SPR #1) -- Done
631 # 3.2.3 p46 p232 VRSAVE (actually SPR #256)
633 # create CR then allow portions of it to be "selectable" (below)
634 self
.cr_fields
= CRFields(initial_cr
)
635 self
.cr
= self
.cr_fields
.cr
637 # "undefined", just set to variable-bit-width int (use exts "max")
638 #self.undefined = SelectableInt(0, 256) # TODO, not hard-code 256!
641 self
.namespace
.update(self
.spr
)
642 self
.namespace
.update({'GPR': self
.gpr
,
646 'memassign': self
.memassign
,
649 'SVSTATE': self
.svstate
,
650 'SVSHAPE0': self
.spr
['SVSHAPE0'],
651 'SVSHAPE1': self
.spr
['SVSHAPE1'],
652 'SVSHAPE2': self
.spr
['SVSHAPE2'],
653 'SVSHAPE3': self
.spr
['SVSHAPE3'],
656 'undefined': undefined
,
657 'mode_is_64bit': True,
661 # update pc to requested start point
662 self
.set_pc(initial_pc
)
664 # field-selectable versions of Condition Register
665 self
.crl
= self
.cr_fields
.crl
667 self
.namespace
["CR%d" % i
] = self
.crl
[i
]
669 self
.decoder
= decoder2
.dec
672 def call_trap(self
, trap_addr
, trap_bit
):
673 """calls TRAP and sets up NIA to the new execution location.
674 next instruction will begin at trap_addr.
676 self
.TRAP(trap_addr
, trap_bit
)
677 self
.namespace
['NIA'] = self
.trap_nia
678 self
.pc
.update(self
.namespace
, self
.is_svp64_mode
)
680 def TRAP(self
, trap_addr
=0x700, trap_bit
=PIb
.TRAP
):
681 """TRAP> saves PC, MSR (and TODO SVSTATE), and updates MSR
683 TRAP function is callable from inside the pseudocode itself,
684 hence the default arguments. when calling from inside ISACaller
685 it is best to use call_trap()
687 log("TRAP:", hex(trap_addr
), hex(self
.namespace
['MSR'].value
))
688 # store CIA(+4?) in SRR0, set NIA to 0x700
689 # store MSR in SRR1, set MSR to um errr something, have to check spec
690 # store SVSTATE (if enabled) in SVSRR0
691 self
.spr
['SRR0'].value
= self
.pc
.CIA
.value
692 self
.spr
['SRR1'].value
= self
.namespace
['MSR'].value
693 if self
.is_svp64_mode
:
694 self
.spr
['SVSRR0'] = self
.namespace
['SVSTATE'].value
695 self
.trap_nia
= SelectableInt(trap_addr
, 64)
696 self
.spr
['SRR1'][trap_bit
] = 1 # change *copy* of MSR in SRR1
698 # set exception bits. TODO: this should, based on the address
699 # in figure 66 p1065 V3.0B and the table figure 65 p1063 set these
700 # bits appropriately. however it turns out that *for now* in all
701 # cases (all trap_addrs) the exact same thing is needed.
702 self
.msr
[MSRb
.IR
] = 0
703 self
.msr
[MSRb
.DR
] = 0
704 self
.msr
[MSRb
.FE0
] = 0
705 self
.msr
[MSRb
.FE1
] = 0
706 self
.msr
[MSRb
.EE
] = 0
707 self
.msr
[MSRb
.RI
] = 0
708 self
.msr
[MSRb
.SF
] = 1
709 self
.msr
[MSRb
.TM
] = 0
710 self
.msr
[MSRb
.VEC
] = 0
711 self
.msr
[MSRb
.VSX
] = 0
712 self
.msr
[MSRb
.PR
] = 0
713 self
.msr
[MSRb
.FP
] = 0
714 self
.msr
[MSRb
.PMM
] = 0
715 self
.msr
[MSRb
.TEs
] = 0
716 self
.msr
[MSRb
.TEe
] = 0
717 self
.msr
[MSRb
.UND
] = 0
718 self
.msr
[MSRb
.LE
] = 1
720 def memassign(self
, ea
, sz
, val
):
721 self
.mem
.memassign(ea
, sz
, val
)
723 def prep_namespace(self
, formname
, op_fields
):
724 # TODO: get field names from form in decoder*1* (not decoder2)
725 # decoder2 is hand-created, and decoder1.sigform is auto-generated
727 # then "yield" fields only from op_fields rather than hard-coded
729 fields
= self
.decoder
.sigforms
[formname
]
730 log("prep_namespace", formname
, op_fields
)
731 for name
in op_fields
:
733 sig
= getattr(fields
, name
.upper())
735 sig
= getattr(fields
, name
)
737 # these are all opcode fields involved in index-selection of CR,
738 # and need to do "standard" arithmetic. CR[BA+32] for example
739 # would, if using SelectableInt, only be 5-bit.
740 if name
in ['BF', 'BFA', 'BC', 'BA', 'BB', 'BT', 'BI']:
741 self
.namespace
[name
] = val
743 self
.namespace
[name
] = SelectableInt(val
, sig
.width
)
745 self
.namespace
['XER'] = self
.spr
['XER']
746 self
.namespace
['CA'] = self
.spr
['XER'][XER_bits
['CA']].value
747 self
.namespace
['CA32'] = self
.spr
['XER'][XER_bits
['CA32']].value
749 # add some SVSTATE convenience variables
751 srcstep
= self
.svstate
.srcstep
752 self
.namespace
['VL'] = vl
753 self
.namespace
['srcstep'] = srcstep
755 def handle_carry_(self
, inputs
, outputs
, already_done
):
756 inv_a
= yield self
.dec2
.e
.do
.invert_in
758 inputs
[0] = ~inputs
[0]
760 imm_ok
= yield self
.dec2
.e
.do
.imm_data
.ok
762 imm
= yield self
.dec2
.e
.do
.imm_data
.data
763 inputs
.append(SelectableInt(imm
, 64))
764 assert len(outputs
) >= 1
765 log("outputs", repr(outputs
))
766 if isinstance(outputs
, list) or isinstance(outputs
, tuple):
772 log("gt input", x
, output
)
773 gt
= (gtu(x
, output
))
776 cy
= 1 if any(gts
) else 0
778 if not (1 & already_done
):
779 self
.spr
['XER'][XER_bits
['CA']] = cy
781 log("inputs", already_done
, inputs
)
783 # ARGH... different for OP_ADD... *sigh*...
784 op
= yield self
.dec2
.e
.do
.insn_type
785 if op
== MicrOp
.OP_ADD
.value
:
786 res32
= (output
.value
& (1 << 32)) != 0
787 a32
= (inputs
[0].value
& (1 << 32)) != 0
789 b32
= (inputs
[1].value
& (1 << 32)) != 0
792 cy32
= res32 ^ a32 ^ b32
793 log("CA32 ADD", cy32
)
797 log("input", x
, output
)
798 log(" x[32:64]", x
, x
[32:64])
799 log(" o[32:64]", output
, output
[32:64])
800 gt
= (gtu(x
[32:64], output
[32:64])) == SelectableInt(1, 1)
802 cy32
= 1 if any(gts
) else 0
803 log("CA32", cy32
, gts
)
804 if not (2 & already_done
):
805 self
.spr
['XER'][XER_bits
['CA32']] = cy32
807 def handle_overflow(self
, inputs
, outputs
, div_overflow
):
808 if hasattr(self
.dec2
.e
.do
, "invert_in"):
809 inv_a
= yield self
.dec2
.e
.do
.invert_in
811 inputs
[0] = ~inputs
[0]
813 imm_ok
= yield self
.dec2
.e
.do
.imm_data
.ok
815 imm
= yield self
.dec2
.e
.do
.imm_data
.data
816 inputs
.append(SelectableInt(imm
, 64))
817 assert len(outputs
) >= 1
818 log("handle_overflow", inputs
, outputs
, div_overflow
)
819 if len(inputs
) < 2 and div_overflow
is None:
822 # div overflow is different: it's returned by the pseudo-code
823 # because it's more complex than can be done by analysing the output
824 if div_overflow
is not None:
825 ov
, ov32
= div_overflow
, div_overflow
826 # arithmetic overflow can be done by analysing the input and output
827 elif len(inputs
) >= 2:
831 input_sgn
= [exts(x
.value
, x
.bits
) < 0 for x
in inputs
]
832 output_sgn
= exts(output
.value
, output
.bits
) < 0
833 ov
= 1 if input_sgn
[0] == input_sgn
[1] and \
834 output_sgn
!= input_sgn
[0] else 0
837 input32_sgn
= [exts(x
.value
, 32) < 0 for x
in inputs
]
838 output32_sgn
= exts(output
.value
, 32) < 0
839 ov32
= 1 if input32_sgn
[0] == input32_sgn
[1] and \
840 output32_sgn
!= input32_sgn
[0] else 0
842 self
.spr
['XER'][XER_bits
['OV']] = ov
843 self
.spr
['XER'][XER_bits
['OV32']] = ov32
844 so
= self
.spr
['XER'][XER_bits
['SO']]
846 self
.spr
['XER'][XER_bits
['SO']] = so
848 def handle_comparison(self
, outputs
, cr_idx
=0):
850 assert isinstance(out
, SelectableInt
), \
851 "out zero not a SelectableInt %s" % repr(outputs
)
852 log("handle_comparison", out
.bits
, hex(out
.value
))
853 # TODO - XXX *processor* in 32-bit mode
854 # https://bugs.libre-soc.org/show_bug.cgi?id=424
856 # o32 = exts(out.value, 32)
857 # print ("handle_comparison exts 32 bit", hex(o32))
858 out
= exts(out
.value
, out
.bits
)
859 log("handle_comparison exts", hex(out
))
860 zero
= SelectableInt(out
== 0, 1)
861 positive
= SelectableInt(out
> 0, 1)
862 negative
= SelectableInt(out
< 0, 1)
863 SO
= self
.spr
['XER'][XER_bits
['SO']]
864 log("handle_comparison SO", SO
)
865 cr_field
= selectconcat(negative
, positive
, zero
, SO
)
866 log("handle_comparison cr_field", self
.cr
, cr_idx
, cr_field
)
867 self
.crl
[cr_idx
].eq(cr_field
)
869 def set_pc(self
, pc_val
):
870 self
.namespace
['NIA'] = SelectableInt(pc_val
, 64)
871 self
.pc
.update(self
.namespace
, self
.is_svp64_mode
)
873 def get_next_insn(self
):
877 pc
= self
.pc
.CIA
.value
880 ins
= self
.imem
.ld(pc
, 4, False, True, instr_fetch
=True)
882 raise KeyError("no instruction at 0x%x" % pc
)
886 """set up one instruction
888 pc
, insn
= self
.get_next_insn()
889 yield from self
.setup_next_insn(pc
, insn
)
891 def setup_next_insn(self
, pc
, ins
):
892 """set up next instruction
895 log("setup: 0x%x 0x%x %s" % (pc
, ins
& 0xffffffff, bin(ins
)))
896 log("CIA NIA", self
.respect_pc
, self
.pc
.CIA
.value
, self
.pc
.NIA
.value
)
898 yield self
.dec2
.sv_rm
.eq(0)
899 yield self
.dec2
.dec
.raw_opcode_in
.eq(ins
& 0xffffffff)
900 yield self
.dec2
.dec
.bigendian
.eq(self
.bigendian
)
901 yield self
.dec2
.state
.msr
.eq(self
.msr
.value
)
902 yield self
.dec2
.state
.pc
.eq(pc
)
903 if self
.svstate
is not None:
904 yield self
.dec2
.state
.svstate
.eq(self
.svstate
.value
)
906 # SVP64. first, check if the opcode is EXT001, and SVP64 id bits set
908 opcode
= yield self
.dec2
.dec
.opcode_in
909 pfx
= SVP64PrefixFields() # TODO should probably use SVP64PrefixDecoder
910 pfx
.insn
.value
= opcode
911 major
= pfx
.major
.asint(msb0
=True) # MSB0 inversion
912 log ("prefix test: opcode:", major
, bin(major
),
913 pfx
.insn
[7] == 0b1, pfx
.insn
[9] == 0b1)
914 self
.is_svp64_mode
= ((major
== 0b000001) and
915 pfx
.insn
[7].value
== 0b1 and
916 pfx
.insn
[9].value
== 0b1)
917 self
.pc
.update_nia(self
.is_svp64_mode
)
918 yield self
.dec2
.is_svp64_mode
.eq(self
.is_svp64_mode
) # set SVP64 decode
919 self
.namespace
['NIA'] = self
.pc
.NIA
920 self
.namespace
['SVSTATE'] = self
.svstate
921 if not self
.is_svp64_mode
:
924 # in SVP64 mode. decode/print out svp64 prefix, get v3.0B instruction
925 log ("svp64.rm", bin(pfx
.rm
.asint(msb0
=True)))
926 log (" svstate.vl", self
.svstate
.vl
)
927 log (" svstate.mvl", self
.svstate
.maxvl
)
928 sv_rm
= pfx
.rm
.asint(msb0
=True)
929 ins
= self
.imem
.ld(pc
+4, 4, False, True, instr_fetch
=True)
930 log(" svsetup: 0x%x 0x%x %s" % (pc
+4, ins
& 0xffffffff, bin(ins
)))
931 yield self
.dec2
.dec
.raw_opcode_in
.eq(ins
& 0xffffffff) # v3.0B suffix
932 yield self
.dec2
.sv_rm
.eq(sv_rm
) # svp64 prefix
934 # store this for use in get_src_dststeps()
935 self
.ldstmode
= yield self
.dec2
.rm_dec
.ldstmode
937 def execute_one(self
):
938 """execute one instruction
940 # get the disassembly code for this instruction
941 if self
.is_svp64_mode
:
942 if not self
.disassembly
:
943 code
= yield from self
.get_assembly_name()
945 code
= self
.disassembly
[self
._pc
+4]
946 log(" svp64 sim-execute", hex(self
._pc
), code
)
948 if not self
.disassembly
:
949 code
= yield from self
.get_assembly_name()
951 code
= self
.disassembly
[self
._pc
]
952 log("sim-execute", hex(self
._pc
), code
)
953 opname
= code
.split(' ')[0]
955 yield from self
.call(opname
) # execute the instruction
956 except MemException
as e
: # check for memory errors
957 if e
.args
[0] != 'unaligned': # only doing aligned at the mo
958 raise e
# ... re-raise
959 # run a Trap but set DAR first
960 print ("memory unaligned exception, DAR", e
.dar
)
961 self
.spr
['DAR'] = SelectableInt(e
.dar
, 64)
962 self
.call_trap(0x600, PIb
.PRIV
) # 0x600, privileged
965 # don't use this except in special circumstances
966 if not self
.respect_pc
:
969 log("execute one, CIA NIA", self
.pc
.CIA
.value
, self
.pc
.NIA
.value
)
971 def get_assembly_name(self
):
972 # TODO, asmregs is from the spec, e.g. add RT,RA,RB
973 # see http://bugs.libre-riscv.org/show_bug.cgi?id=282
974 dec_insn
= yield self
.dec2
.e
.do
.insn
975 insn_1_11
= yield self
.dec2
.e
.do
.insn
[1:11]
976 asmcode
= yield self
.dec2
.dec
.op
.asmcode
977 int_op
= yield self
.dec2
.dec
.op
.internal_op
978 log("get assembly name asmcode", asmcode
, int_op
,
979 hex(dec_insn
), bin(insn_1_11
))
980 asmop
= insns
.get(asmcode
, None)
982 # sigh reconstruct the assembly instruction name
983 if hasattr(self
.dec2
.e
.do
, "oe"):
984 ov_en
= yield self
.dec2
.e
.do
.oe
.oe
985 ov_ok
= yield self
.dec2
.e
.do
.oe
.ok
989 if hasattr(self
.dec2
.e
.do
, "rc"):
990 rc_en
= yield self
.dec2
.e
.do
.rc
.rc
991 rc_ok
= yield self
.dec2
.e
.do
.rc
.ok
995 # grrrr have to special-case MUL op (see DecodeOE)
996 log("ov %d en %d rc %d en %d op %d" %
997 (ov_ok
, ov_en
, rc_ok
, rc_en
, int_op
))
998 if int_op
in [MicrOp
.OP_MUL_H64
.value
, MicrOp
.OP_MUL_H32
.value
]:
1003 if not asmop
.endswith("."): # don't add "." to "andis."
1006 if hasattr(self
.dec2
.e
.do
, "lk"):
1007 lk
= yield self
.dec2
.e
.do
.lk
1010 log("int_op", int_op
)
1011 if int_op
in [MicrOp
.OP_B
.value
, MicrOp
.OP_BC
.value
]:
1012 AA
= yield self
.dec2
.dec
.fields
.FormI
.AA
[0:-1]
1016 spr_msb
= yield from self
.get_spr_msb()
1017 if int_op
== MicrOp
.OP_MFCR
.value
:
1022 # XXX TODO: for whatever weird reason this doesn't work
1023 # https://bugs.libre-soc.org/show_bug.cgi?id=390
1024 if int_op
== MicrOp
.OP_MTCRF
.value
:
1031 def get_remap_indices(self
):
1032 """WARNING, this function stores remap_idxs and remap_loopends
1033 in the class for later use. this to avoid problems with yield
1035 # go through all iterators in lock-step, advance to next remap_idx
1036 srcstep
, dststep
= self
.get_src_dststeps()
1037 # get four SVSHAPEs. here we are hard-coding
1038 SVSHAPE0
= self
.spr
['SVSHAPE0']
1039 SVSHAPE1
= self
.spr
['SVSHAPE1']
1040 SVSHAPE2
= self
.spr
['SVSHAPE2']
1041 SVSHAPE3
= self
.spr
['SVSHAPE3']
1042 # set up the iterators
1043 remaps
= [(SVSHAPE0
, SVSHAPE0
.get_iterator()),
1044 (SVSHAPE1
, SVSHAPE1
.get_iterator()),
1045 (SVSHAPE2
, SVSHAPE2
.get_iterator()),
1046 (SVSHAPE3
, SVSHAPE3
.get_iterator()),
1049 self
.remap_loopends
= [0] * 4
1050 self
.remap_idxs
= [0, 1, 2, 3]
1052 for i
, (shape
, remap
) in enumerate(remaps
):
1053 # zero is "disabled"
1054 if shape
.value
== 0x0:
1055 self
.remap_idxs
[i
] = 0
1056 # pick src or dststep depending on reg num (0-2=in, 3-4=out)
1057 step
= dststep
if (i
in [3, 4]) else srcstep
1058 # this is terrible. O(N^2) looking for the match. but hey.
1059 for idx
, (remap_idx
, loopends
) in enumerate(remap
):
1062 self
.remap_idxs
[i
] = remap_idx
1063 self
.remap_loopends
[i
] = loopends
1064 dbg
.append((i
, step
, remap_idx
, loopends
))
1065 for (i
, step
, remap_idx
, loopends
) in dbg
:
1066 log ("SVSHAPE %d idx, end" % i
, step
, remap_idx
, bin(loopends
))
1069 def get_spr_msb(self
):
1070 dec_insn
= yield self
.dec2
.e
.do
.insn
1071 return dec_insn
& (1 << 20) != 0 # sigh - XFF.spr[-1]?
1073 def call(self
, name
):
1074 """call(opcode) - the primary execution point for instructions
1076 self
.last_st_addr
= None # reset the last known store address
1077 self
.last_ld_addr
= None # etc.
1079 ins_name
= name
.strip() # remove spaces if not already done so
1081 log("halted - not executing", ins_name
)
1084 # TODO, asmregs is from the spec, e.g. add RT,RA,RB
1085 # see http://bugs.libre-riscv.org/show_bug.cgi?id=282
1086 asmop
= yield from self
.get_assembly_name()
1087 log("call", ins_name
, asmop
)
1090 int_op
= yield self
.dec2
.dec
.op
.internal_op
1091 spr_msb
= yield from self
.get_spr_msb()
1093 instr_is_privileged
= False
1094 if int_op
in [MicrOp
.OP_ATTN
.value
,
1095 MicrOp
.OP_MFMSR
.value
,
1096 MicrOp
.OP_MTMSR
.value
,
1097 MicrOp
.OP_MTMSRD
.value
,
1099 MicrOp
.OP_RFID
.value
]:
1100 instr_is_privileged
= True
1101 if int_op
in [MicrOp
.OP_MFSPR
.value
,
1102 MicrOp
.OP_MTSPR
.value
] and spr_msb
:
1103 instr_is_privileged
= True
1105 log("is priv", instr_is_privileged
, hex(self
.msr
.value
),
1107 # check MSR priv bit and whether op is privileged: if so, throw trap
1108 if instr_is_privileged
and self
.msr
[MSRb
.PR
] == 1:
1109 self
.call_trap(0x700, PIb
.PRIV
)
1112 # check halted condition
1113 if ins_name
== 'attn':
1117 # check illegal instruction
1119 if ins_name
not in ['mtcrf', 'mtocrf']:
1120 illegal
= ins_name
!= asmop
1122 # sigh deal with setvl not being supported by binutils (.long)
1123 if asmop
.startswith('setvl'):
1127 # and svstep not being supported by binutils (.long)
1128 if asmop
.startswith('svstep'):
1132 # and svremap not being supported by binutils (.long)
1133 if asmop
.startswith('svremap'):
1135 ins_name
= 'svremap'
1137 # and svshape not being supported by binutils (.long)
1138 if asmop
.startswith('svshape'):
1140 ins_name
= 'svshape'
1143 if asmop
== 'fsins':
1146 if asmop
== 'fcoss':
1150 # sigh also deal with ffmadds not being supported by binutils (.long)
1151 if asmop
== 'ffmadds':
1153 ins_name
= 'ffmadds'
1155 # and fdmadds not being supported by binutils (.long)
1156 if asmop
== 'fdmadds':
1158 ins_name
= 'fdmadds'
1160 # and ffadds not being supported by binutils (.long)
1161 if asmop
== 'ffadds':
1166 print("illegal", ins_name
, asmop
)
1167 self
.call_trap(0x700, PIb
.ILLEG
)
1168 print("name %s != %s - calling ILLEGAL trap, PC: %x" %
1169 (ins_name
, asmop
, self
.pc
.CIA
.value
))
1172 # this is for setvl "Vertical" mode: if set true,
1173 # srcstep/dststep is explicitly advanced. mode says which SVSTATE to
1174 # test for Rc=1 end condition. 3 bits of all 3 loops are put into CR0
1175 self
.allow_next_step_inc
= False
1176 self
.svstate_next_mode
= 0
1178 # nop has to be supported, we could let the actual op calculate
1179 # but PowerDecoder has a pattern for nop
1180 if ins_name
is 'nop':
1181 self
.update_pc_next()
1184 info
= self
.instrs
[ins_name
]
1185 yield from self
.prep_namespace(info
.form
, info
.op_fields
)
1187 # preserve order of register names
1188 input_names
= create_args(list(info
.read_regs
) +
1189 list(info
.uninit_regs
))
1190 log("input names", input_names
)
1192 # get SVP64 entry for the current instruction
1193 sv_rm
= self
.svp64rm
.instrs
.get(ins_name
)
1194 if sv_rm
is not None:
1195 dest_cr
, src_cr
, src_byname
, dest_byname
= decode_extra(sv_rm
)
1197 dest_cr
, src_cr
, src_byname
, dest_byname
= False, False, {}, {}
1198 log ("sv rm", sv_rm
, dest_cr
, src_cr
, src_byname
, dest_byname
)
1200 # see if srcstep/dststep need skipping over masked-out predicate bits
1201 if (self
.is_svp64_mode
or ins_name
== 'setvl' or
1202 ins_name
.startswith("sv")):
1203 yield from self
.svstate_pre_inc()
1204 if self
.is_svp64_mode
:
1205 pre
= yield from self
.update_new_svstate_steps()
1207 self
.svp64_reset_loop()
1209 self
.update_pc_next()
1211 srcstep
, dststep
= self
.get_src_dststeps()
1212 pred_dst_zero
= self
.pred_dst_zero
1213 pred_src_zero
= self
.pred_src_zero
1214 vl
= self
.svstate
.vl
1216 # VL=0 in SVP64 mode means "do nothing: skip instruction"
1217 if self
.is_svp64_mode
and vl
== 0:
1218 self
.pc
.update(self
.namespace
, self
.is_svp64_mode
)
1219 log("SVP64: VL=0, end of call", self
.namespace
['CIA'],
1220 self
.namespace
['NIA'])
1223 # for when SVREMAP is active, using pre-arranged schedule.
1224 # note: modifying PowerDecoder2 needs to "settle"
1225 remap_en
= self
.svstate
.SVme
1226 persist
= self
.svstate
.RMpst
1227 active
= (persist
or self
.last_op_svshape
) and remap_en
!= 0
1228 yield self
.dec2
.remap_active
.eq(remap_en
if active
else 0)
1230 if persist
or self
.last_op_svshape
:
1231 remaps
= self
.get_remap_indices()
1232 if self
.is_svp64_mode
and (persist
or self
.last_op_svshape
):
1233 # just some convenient debug info
1235 sname
= 'SVSHAPE%d' % i
1236 shape
= self
.spr
[sname
]
1237 log (sname
, bin(shape
.value
))
1238 log (" lims", shape
.lims
)
1239 log (" mode", shape
.mode
)
1240 log (" skip", shape
.skip
)
1242 # set up the list of steps to remap
1243 mi0
= self
.svstate
.mi0
1244 mi1
= self
.svstate
.mi1
1245 mi2
= self
.svstate
.mi2
1246 mo0
= self
.svstate
.mo0
1247 mo1
= self
.svstate
.mo1
1248 steps
= [(self
.dec2
.in1_step
, mi0
), # RA
1249 (self
.dec2
.in2_step
, mi1
), # RB
1250 (self
.dec2
.in3_step
, mi2
), # RC
1251 (self
.dec2
.o_step
, mo0
), # RT
1252 (self
.dec2
.o2_step
, mo1
), # EA
1254 remap_idxs
= self
.remap_idxs
1256 # now cross-index the required SHAPE for each of 3-in 2-out regs
1257 rnames
= ['RA', 'RB', 'RC', 'RT', 'EA']
1258 for i
, (dstep
, shape_idx
) in enumerate(steps
):
1259 (shape
, remap
) = remaps
[shape_idx
]
1260 remap_idx
= remap_idxs
[shape_idx
]
1261 # zero is "disabled"
1262 if shape
.value
== 0x0:
1264 # now set the actual requested step to the current index
1265 yield dstep
.eq(remap_idx
)
1267 # debug printout info
1268 rremaps
.append((shape
.mode
, i
, rnames
[i
], shape_idx
,
1271 log ("shape remap", x
)
1272 # after that, settle down (combinatorial) to let Vector reg numbers
1273 # work themselves out
1275 remap_active
= yield self
.dec2
.remap_active
1276 log ("remap active", bin(remap_active
))
1278 # main input registers (RT, RA ...)
1280 for name
in input_names
:
1281 # using PowerDecoder2, first, find the decoder index.
1282 # (mapping name RA RB RC RS to in1, in2, in3)
1283 regnum
, is_vec
= yield from get_pdecode_idx_in(self
.dec2
, name
)
1285 # doing this is not part of svp64, it's because output
1286 # registers, to be modified, need to be in the namespace.
1287 regnum
, is_vec
= yield from get_pdecode_idx_out(self
.dec2
, name
)
1289 regnum
, is_vec
= yield from get_pdecode_idx_out2(self
.dec2
,
1292 # in case getting the register number is needed, _RA, _RB
1293 regname
= "_" + name
1294 self
.namespace
[regname
] = regnum
1295 if not self
.is_svp64_mode
or not pred_src_zero
:
1296 log('reading reg %s %s' % (name
, str(regnum
)), is_vec
)
1298 reg_val
= self
.fpr(regnum
)
1299 elif name
is not None:
1300 reg_val
= self
.gpr(regnum
)
1302 log('zero input reg %s %s' % (name
, str(regnum
)), is_vec
)
1304 inputs
.append(reg_val
)
1305 # arrrrgh, awful hack, to get _RT into namespace
1306 if ins_name
in ['setvl', 'svstep']:
1308 RT
= yield self
.dec2
.dec
.RT
1309 self
.namespace
[regname
] = SelectableInt(RT
, 5)
1311 self
.namespace
["RT"] = SelectableInt(0, 5)
1312 regnum
, is_vec
= yield from get_pdecode_idx_out(self
.dec2
, "RT")
1313 log('hack input reg %s %s' % (name
, str(regnum
)), is_vec
)
1315 # in SVP64 mode for LD/ST work out immediate
1316 # XXX TODO: replace_ds for DS-Form rather than D-Form.
1317 # use info.form to detect
1318 replace_d
= False # update / replace constant in pseudocode
1319 if self
.is_svp64_mode
:
1320 ldstmode
= yield self
.dec2
.rm_dec
.ldstmode
1321 # bitreverse mode reads SVD (or SVDS - TODO)
1322 # *BUT*... because this is "overloading" of LD operations,
1323 # it gets *STORED* into D (or DS, TODO)
1324 if ldstmode
== SVP64LDSTmode
.BITREVERSE
.value
:
1325 imm
= yield self
.dec2
.dec
.fields
.FormSVD
.SVD
[0:11]
1326 imm
= exts(imm
, 11) # sign-extend to integer
1327 log ("bitrev SVD", imm
)
1330 if info
.form
== 'DS':
1331 # DS-Form, multiply by 4 then knock 2 bits off after
1332 imm
= yield self
.dec2
.dec
.fields
.FormDS
.DS
[0:14] * 4
1334 imm
= yield self
.dec2
.dec
.fields
.FormD
.D
[0:16]
1335 imm
= exts(imm
, 16) # sign-extend to integer
1336 # get the right step. LD is from srcstep, ST is dststep
1337 op
= yield self
.dec2
.e
.do
.insn_type
1339 if op
== MicrOp
.OP_LOAD
.value
:
1341 offsmul
= yield self
.dec2
.in1_step
1342 log("D-field REMAP src", imm
, offsmul
)
1345 log("D-field src", imm
, offsmul
)
1346 elif op
== MicrOp
.OP_STORE
.value
:
1347 # XXX NOTE! no bit-reversed STORE! this should not ever be used
1349 log("D-field dst", imm
, offsmul
)
1350 # bit-reverse mode, rev already done through get_src_dst_steps()
1351 if ldstmode
== SVP64LDSTmode
.BITREVERSE
.value
:
1352 # manually look up RC, sigh
1353 RC
= yield self
.dec2
.dec
.RC
[0:5]
1355 log ("LD-BITREVERSE:", "VL", vl
,
1356 "RC", RC
.value
, "imm", imm
,
1357 "offs", bin(offsmul
),
1359 imm
= SelectableInt((imm
* offsmul
) << RC
.value
, 32)
1360 # Unit-Strided LD/ST adds offset*width to immediate
1361 elif ldstmode
== SVP64LDSTmode
.UNITSTRIDE
.value
:
1362 ldst_len
= yield self
.dec2
.e
.do
.data_len
1363 imm
= SelectableInt(imm
+ offsmul
* ldst_len
, 32)
1365 # Element-strided multiplies the immediate by element step
1366 elif ldstmode
== SVP64LDSTmode
.ELSTRIDE
.value
:
1367 imm
= SelectableInt(imm
* offsmul
, 32)
1370 ldst_ra_vec
= yield self
.dec2
.rm_dec
.ldst_ra_vec
1371 ldst_imz_in
= yield self
.dec2
.rm_dec
.ldst_imz_in
1372 log("LDSTmode", SVP64LDSTmode(ldstmode
),
1373 offsmul
, imm
, ldst_ra_vec
, ldst_imz_in
)
1374 # new replacement D... errr.. DS
1376 if info
.form
== 'DS':
1377 # TODO: assert 2 LSBs are zero?
1378 log("DS-Form, TODO, assert 2 LSBs zero?", bin(imm
.value
))
1379 imm
.value
= imm
.value
>> 2
1380 self
.namespace
['DS'] = imm
1382 self
.namespace
['D'] = imm
1384 # "special" registers
1385 for special
in info
.special_regs
:
1386 if special
in special_sprs
:
1387 inputs
.append(self
.spr
[special
])
1389 inputs
.append(self
.namespace
[special
])
1391 # clear trap (trap) NIA
1392 self
.trap_nia
= None
1394 # execute actual instruction here (finally)
1395 log("inputs", inputs
)
1396 results
= info
.func(self
, *inputs
)
1397 log("results", results
)
1399 # "inject" decorator takes namespace from function locals: we need to
1400 # overwrite NIA being overwritten (sigh)
1401 if self
.trap_nia
is not None:
1402 self
.namespace
['NIA'] = self
.trap_nia
1404 log("after func", self
.namespace
['CIA'], self
.namespace
['NIA'])
1406 # check if op was a LD/ST so that debugging can check the
1408 if int_op
in [MicrOp
.OP_STORE
.value
,
1410 self
.last_st_addr
= self
.mem
.last_st_addr
1411 if int_op
in [MicrOp
.OP_LOAD
.value
,
1413 self
.last_ld_addr
= self
.mem
.last_ld_addr
1414 log ("op", int_op
, MicrOp
.OP_STORE
.value
, MicrOp
.OP_LOAD
.value
,
1415 self
.last_st_addr
, self
.last_ld_addr
)
1417 # detect if CA/CA32 already in outputs (sra*, basically)
1420 output_names
= create_args(info
.write_regs
)
1421 for name
in output_names
:
1427 log("carry already done?", bin(already_done
))
1428 if hasattr(self
.dec2
.e
.do
, "output_carry"):
1429 carry_en
= yield self
.dec2
.e
.do
.output_carry
1433 yield from self
.handle_carry_(inputs
, results
, already_done
)
1435 if not self
.is_svp64_mode
: # yeah just no. not in parallel processing
1436 # detect if overflow was in return result
1439 for name
, output
in zip(output_names
, results
):
1440 if name
== 'overflow':
1443 if hasattr(self
.dec2
.e
.do
, "oe"):
1444 ov_en
= yield self
.dec2
.e
.do
.oe
.oe
1445 ov_ok
= yield self
.dec2
.e
.do
.oe
.ok
1449 log("internal overflow", overflow
, ov_en
, ov_ok
)
1451 yield from self
.handle_overflow(inputs
, results
, overflow
)
1453 # only do SVP64 dest predicated Rc=1 if dest-pred is not enabled
1455 if not self
.is_svp64_mode
or not pred_dst_zero
:
1456 if hasattr(self
.dec2
.e
.do
, "rc"):
1457 rc_en
= yield self
.dec2
.e
.do
.rc
.rc
1458 if rc_en
and ins_name
not in ['svstep']:
1459 regnum
, is_vec
= yield from get_pdecode_cr_out(self
.dec2
, "CR0")
1460 self
.handle_comparison(results
, regnum
)
1462 # any modified return results?
1464 for name
, output
in zip(output_names
, results
):
1465 if name
== 'overflow': # ignore, done already (above)
1467 if isinstance(output
, int):
1468 output
= SelectableInt(output
, 256)
1469 if name
in ['CA', 'CA32']:
1471 log("writing %s to XER" % name
, output
)
1472 self
.spr
['XER'][XER_bits
[name
]] = output
.value
1474 log("NOT writing %s to XER" % name
, output
)
1475 elif name
in info
.special_regs
:
1476 log('writing special %s' % name
, output
, special_sprs
)
1477 if name
in special_sprs
:
1478 self
.spr
[name
] = output
1480 self
.namespace
[name
].eq(output
)
1482 log('msr written', hex(self
.msr
.value
))
1484 regnum
, is_vec
= yield from get_pdecode_idx_out(self
.dec2
,
1487 regnum
, is_vec
= yield from get_pdecode_idx_out2(
1490 # temporary hack for not having 2nd output
1491 regnum
= yield getattr(self
.decoder
, name
)
1493 if self
.is_svp64_mode
and pred_dst_zero
:
1494 log('zeroing reg %d %s' % (regnum
, str(output
)),
1496 output
= SelectableInt(0, 256)
1502 log('writing %s %s %s' % (ftype
, regnum
, str(output
)),
1504 if output
.bits
> 64:
1505 output
= SelectableInt(output
.value
, 64)
1507 self
.fpr
[regnum
] = output
1509 self
.gpr
[regnum
] = output
1511 # check if it is the SVSTATE.src/dest step that needs incrementing
1512 # this is our Sub-Program-Counter loop from 0 to VL-1
1515 if self
.allow_next_step_inc
:
1516 log("SVSTATE_NEXT: inc requested, mode",
1517 self
.svstate_next_mode
, self
.allow_next_step_inc
)
1518 yield from self
.svstate_pre_inc()
1519 pre
= yield from self
.update_new_svstate_steps()
1521 # reset at end of loop including exit Vertical Mode
1522 log ("SVSTATE_NEXT: end of loop, reset")
1523 self
.svp64_reset_loop()
1524 self
.svstate
.vfirst
= 0
1527 results
= [SelectableInt(0, 64)]
1528 self
.handle_comparison(results
) # CR0
1530 if self
.allow_next_step_inc
== 2:
1531 log ("SVSTATE_NEXT: read")
1532 yield from self
.svstate_post_inc()
1534 log ("SVSTATE_NEXT: post-inc")
1535 # use actual src/dst-step here to check end, do NOT
1536 # use bit-reversed version
1537 srcstep
, dststep
= self
.new_srcstep
, self
.new_dststep
1538 remaps
= self
.get_remap_indices()
1539 remap_idxs
= self
.remap_idxs
1540 vl
= self
.svstate
.vl
1541 end_src
= srcstep
== vl
-1
1542 end_dst
= dststep
== vl
-1
1543 if self
.allow_next_step_inc
!= 2:
1545 self
.svstate
.srcstep
+= SelectableInt(1, 7)
1547 self
.svstate
.dststep
+= SelectableInt(1, 7)
1548 self
.namespace
['SVSTATE'] = self
.svstate
.spr
1549 # set CR0 (if Rc=1) based on end
1551 srcstep
= self
.svstate
.srcstep
1552 dststep
= self
.svstate
.srcstep
1553 endtest
= 1 if (end_src
or end_dst
) else 0
1554 #results = [SelectableInt(endtest, 64)]
1555 #self.handle_comparison(results) # CR0
1557 # see if svstep was requested, if so, which SVSTATE
1559 if self
.svstate_next_mode
> 0:
1560 shape_idx
= self
.svstate_next_mode
.value
-1
1561 endings
= self
.remap_loopends
[shape_idx
]
1562 cr_field
= SelectableInt((~endings
)<<1 | endtest
, 4)
1563 print ("svstep Rc=1, CR0", cr_field
)
1564 self
.crl
[0].eq(cr_field
) # CR0
1565 if end_src
or end_dst
:
1566 # reset at end of loop including exit Vertical Mode
1567 log ("SVSTATE_NEXT: after increments, reset")
1568 self
.svp64_reset_loop()
1569 self
.svstate
.vfirst
= 0
1571 elif self
.is_svp64_mode
:
1572 yield from self
.svstate_post_inc()
1574 # XXX only in non-SVP64 mode!
1575 # record state of whether the current operation was an svshape,
1576 # to be able to know if it should apply in the next instruction.
1577 # also (if going to use this instruction) should disable ability
1578 # to interrupt in between. sigh.
1579 self
.last_op_svshape
= asmop
== 'svremap'
1581 self
.update_pc_next()
1583 def SVSTATE_NEXT(self
, mode
, submode
):
1584 """explicitly moves srcstep/dststep on to next element, for
1585 "Vertical-First" mode. this function is called from
1586 setvl pseudo-code, as a pseudo-op "svstep"
1588 WARNING: this function uses information that was created EARLIER
1589 due to it being in the middle of a yield, but this function is
1590 *NOT* called from yield (it's called from compiled pseudocode).
1592 self
.allow_next_step_inc
= submode
.value
+ 1
1593 log("SVSTATE_NEXT mode", mode
, submode
, self
.allow_next_step_inc
)
1594 self
.svstate_next_mode
= mode
1595 if self
.svstate_next_mode
> 0:
1596 shape_idx
= self
.svstate_next_mode
.value
-1
1597 return SelectableInt(self
.remap_idxs
[shape_idx
], 7)
1598 return SelectableInt(0, 7)
1600 def svstate_pre_inc(self
):
1601 """check if srcstep/dststep need to skip over masked-out predicate bits
1603 # get SVSTATE VL (oh and print out some debug stuff)
1604 vl
= self
.svstate
.vl
1605 srcstep
= self
.svstate
.srcstep
1606 dststep
= self
.svstate
.dststep
1607 sv_a_nz
= yield self
.dec2
.sv_a_nz
1608 fft_mode
= yield self
.dec2
.use_svp64_fft
1609 in1
= yield self
.dec2
.e
.read_reg1
.data
1610 log ("SVP64: VL, srcstep, dststep, sv_a_nz, in1 fft, svp64",
1611 vl
, srcstep
, dststep
, sv_a_nz
, in1
, fft_mode
,
1614 # get predicate mask
1615 srcmask
= dstmask
= 0xffff_ffff_ffff_ffff
1617 pmode
= yield self
.dec2
.rm_dec
.predmode
1618 reverse_gear
= yield self
.dec2
.rm_dec
.reverse_gear
1619 sv_ptype
= yield self
.dec2
.dec
.op
.SV_Ptype
1620 srcpred
= yield self
.dec2
.rm_dec
.srcpred
1621 dstpred
= yield self
.dec2
.rm_dec
.dstpred
1622 pred_src_zero
= yield self
.dec2
.rm_dec
.pred_sz
1623 pred_dst_zero
= yield self
.dec2
.rm_dec
.pred_dz
1624 if pmode
== SVP64PredMode
.INT
.value
:
1625 srcmask
= dstmask
= get_predint(self
.gpr
, dstpred
)
1626 if sv_ptype
== SVPtype
.P2
.value
:
1627 srcmask
= get_predint(self
.gpr
, srcpred
)
1628 elif pmode
== SVP64PredMode
.CR
.value
:
1629 srcmask
= dstmask
= get_predcr(self
.crl
, dstpred
, vl
)
1630 if sv_ptype
== SVPtype
.P2
.value
:
1631 srcmask
= get_predcr(self
.crl
, srcpred
, vl
)
1632 log (" pmode", pmode
)
1633 log (" reverse", reverse_gear
)
1634 log (" ptype", sv_ptype
)
1635 log (" srcpred", bin(srcpred
))
1636 log (" dstpred", bin(dstpred
))
1637 log (" srcmask", bin(srcmask
))
1638 log (" dstmask", bin(dstmask
))
1639 log (" pred_sz", bin(pred_src_zero
))
1640 log (" pred_dz", bin(pred_dst_zero
))
1642 # okaaay, so here we simply advance srcstep (TODO dststep)
1643 # until the predicate mask has a "1" bit... or we run out of VL
1644 # let srcstep==VL be the indicator to move to next instruction
1645 if not pred_src_zero
:
1646 while (((1<<srcstep
) & srcmask
) == 0) and (srcstep
!= vl
):
1647 log (" skip", bin(1<<srcstep
))
1650 if not pred_dst_zero
:
1651 while (((1<<dststep
) & dstmask
) == 0) and (dststep
!= vl
):
1652 log (" skip", bin(1<<dststep
))
1655 # now work out if the relevant mask bits require zeroing
1657 pred_dst_zero
= ((1<<dststep
) & dstmask
) == 0
1659 pred_src_zero
= ((1<<srcstep
) & srcmask
) == 0
1661 # store new srcstep / dststep
1662 self
.new_srcstep
, self
.new_dststep
= srcstep
, dststep
1663 self
.pred_dst_zero
, self
.pred_src_zero
= pred_dst_zero
, pred_src_zero
1664 log (" new srcstep", srcstep
)
1665 log (" new dststep", dststep
)
1667 def get_src_dststeps(self
):
1668 """gets srcstep and dststep but performs bit-reversal on srcstep if
1669 required. use this ONLY to perform calculations, do NOT update
1670 SVSTATE with the bit-reversed value of srcstep
1672 ARGH, had to store self.ldstmode and VL due to yield issues
1674 srcstep
, dststep
= self
.new_srcstep
, self
.new_dststep
1675 if self
.is_svp64_mode
:
1676 if self
.ldstmode
== SVP64LDSTmode
.BITREVERSE
.value
:
1677 vl
= self
.svstate
.vl
1678 log ("SRCSTEP-BITREVERSE:", "VL", vl
, "srcstep", srcstep
,
1679 "rev", bin(bitrev(srcstep
, vl
)))
1680 srcstep
= bitrev(srcstep
, vl
)
1682 return (srcstep
, dststep
)
1684 def update_new_svstate_steps(self
):
1685 # note, do not get the bit-reversed srcstep here!
1686 srcstep
, dststep
= self
.new_srcstep
, self
.new_dststep
1688 # update SVSTATE with new srcstep
1689 self
.svstate
.srcstep
= srcstep
1690 self
.svstate
.dststep
= dststep
1691 self
.namespace
['SVSTATE'] = self
.svstate
1692 yield self
.dec2
.state
.svstate
.eq(self
.svstate
.value
)
1693 yield Settle() # let decoder update
1694 srcstep
= self
.svstate
.srcstep
1695 dststep
= self
.svstate
.dststep
1696 vl
= self
.svstate
.vl
1697 log (" srcstep", srcstep
)
1698 log (" dststep", dststep
)
1701 # check if end reached (we let srcstep overrun, above)
1702 # nothing needs doing (TODO zeroing): just do next instruction
1703 return srcstep
== vl
or dststep
== vl
1705 def svstate_post_inc(self
, vf
=0):
1706 # check if SV "Vertical First" mode is enabled
1707 vfirst
= self
.svstate
.vfirst
1708 log (" SV Vertical First", vf
, vfirst
)
1709 if not vf
and vfirst
== 1:
1713 # check if it is the SVSTATE.src/dest step that needs incrementing
1714 # this is our Sub-Program-Counter loop from 0 to VL-1
1715 # XXX twin predication TODO
1716 vl
= self
.svstate
.vl
1717 mvl
= self
.svstate
.maxvl
1718 srcstep
= self
.svstate
.srcstep
1719 dststep
= self
.svstate
.dststep
1720 rm_mode
= yield self
.dec2
.rm_dec
.mode
1721 reverse_gear
= yield self
.dec2
.rm_dec
.reverse_gear
1722 sv_ptype
= yield self
.dec2
.dec
.op
.SV_Ptype
1723 out_vec
= not (yield self
.dec2
.no_out_vec
)
1724 in_vec
= not (yield self
.dec2
.no_in_vec
)
1725 log (" svstate.vl", vl
)
1726 log (" svstate.mvl", mvl
)
1727 log (" svstate.srcstep", srcstep
)
1728 log (" svstate.dststep", dststep
)
1729 log (" mode", rm_mode
)
1730 log (" reverse", reverse_gear
)
1731 log (" out_vec", out_vec
)
1732 log (" in_vec", in_vec
)
1733 log (" sv_ptype", sv_ptype
, sv_ptype
== SVPtype
.P2
.value
)
1734 # check if srcstep needs incrementing by one, stop PC advancing
1735 # svp64 loop can end early if the dest is scalar for single-pred
1736 # but for 2-pred both src/dest have to be checked.
1737 # XXX this might not be true! it may just be LD/ST
1738 if sv_ptype
== SVPtype
.P2
.value
:
1739 svp64_is_vector
= (out_vec
or in_vec
)
1741 svp64_is_vector
= out_vec
1742 if svp64_is_vector
and srcstep
!= vl
-1 and dststep
!= vl
-1:
1743 self
.svstate
.srcstep
+= SelectableInt(1, 7)
1744 self
.svstate
.dststep
+= SelectableInt(1, 7)
1745 self
.pc
.NIA
.value
= self
.pc
.CIA
.value
1746 self
.namespace
['NIA'] = self
.pc
.NIA
1747 self
.namespace
['SVSTATE'] = self
.svstate
1748 log("end of sub-pc call", self
.namespace
['CIA'],
1749 self
.namespace
['NIA'])
1750 return False # DO NOT allow PC update whilst Sub-PC loop running
1752 # reset loop to zero and update NIA
1753 self
.svp64_reset_loop()
1758 def update_pc_next(self
):
1759 # UPDATE program counter
1760 self
.pc
.update(self
.namespace
, self
.is_svp64_mode
)
1761 self
.svstate
.spr
= self
.namespace
['SVSTATE']
1762 log("end of call", self
.namespace
['CIA'],
1763 self
.namespace
['NIA'],
1764 self
.namespace
['SVSTATE'])
1766 def svp64_reset_loop(self
):
1767 self
.svstate
.srcstep
= 0
1768 self
.svstate
.dststep
= 0
1769 log (" svstate.srcstep loop end (PC to update)")
1770 self
.namespace
['SVSTATE'] = self
.svstate
1772 def update_nia(self
):
1773 self
.pc
.update_nia(self
.is_svp64_mode
)
1774 self
.namespace
['NIA'] = self
.pc
.NIA
1777 """Decorator factory.
1779 this decorator will "inject" variables into the function's namespace,
1780 from the *dictionary* in self.namespace. it therefore becomes possible
1781 to make it look like a whole stack of variables which would otherwise
1782 need "self." inserted in front of them (*and* for those variables to be
1783 added to the instance) "appear" in the function.
1785 "self.namespace['SI']" for example becomes accessible as just "SI" but
1786 *only* inside the function, when decorated.
1788 def variable_injector(func
):
1790 def decorator(*args
, **kwargs
):
1792 func_globals
= func
.__globals
__ # Python 2.6+
1793 except AttributeError:
1794 func_globals
= func
.func_globals
# Earlier versions.
1796 context
= args
[0].namespace
# variables to be injected
1797 saved_values
= func_globals
.copy() # Shallow copy of dict.
1798 log("globals before", context
.keys())
1799 func_globals
.update(context
)
1800 result
= func(*args
, **kwargs
)
1801 log("globals after", func_globals
['CIA'], func_globals
['NIA'])
1802 log("args[0]", args
[0].namespace
['CIA'],
1803 args
[0].namespace
['NIA'],
1804 args
[0].namespace
['SVSTATE'])
1805 args
[0].namespace
= func_globals
1806 #exec (func.__code__, func_globals)
1809 # func_globals = saved_values # Undo changes.
1815 return variable_injector