1 """Power ISA Decoder second stage
3 based on Anton Blanchard microwatt decode2.vhdl
5 Note: OP_TRAP is used for exceptions and interrupts (micro-code style) by
6 over-riding the internal opcode when an exception is needed.
9 from nmigen
import Module
, Elaboratable
, Signal
, Mux
, Const
, Cat
, Repl
, Record
10 from nmigen
.cli
import rtlil
11 from nmutil
.util
import sel
13 from nmutil
.picker
import PriorityPicker
14 from nmutil
.iocontrol
import RecordObject
15 from nmutil
.extend
import exts
17 from openpower
.exceptions
import LDSTException
19 from openpower
.decoder
.power_svp64_prefix
import SVP64PrefixDecoder
20 from openpower
.decoder
.power_svp64_extra
import SVP64CRExtra
, SVP64RegExtra
21 from openpower
.decoder
.power_svp64_rm
import (SVP64RMModeDecode
,
22 sv_input_record_layout
,
24 from openpower
.sv
.svp64
import SVP64Rec
26 from openpower
.decoder
.power_regspec_map
import regspec_decode_read
27 from openpower
.decoder
.power_decoder
import create_pdecode
28 from openpower
.decoder
.power_enums
import (MicrOp
, CryIn
, Function
,
30 LdstLen
, In1Sel
, In2Sel
, In3Sel
,
31 OutSel
, SPRfull
, SPRreduced
,
33 SVEXTRA
, SVEtype
, SVPtype
)
34 from openpower
.decoder
.decode2execute1
import (Decode2ToExecute1Type
, Data
,
37 from openpower
.consts
import (MSR
, SPEC
, EXTRA2
, EXTRA3
, SVP64P
, field
,
38 SPEC_SIZE
, SPECb
, SPEC_AUG_SIZE
, SVP64CROffs
,
39 FastRegsEnum
, XERRegsEnum
, TT
)
41 from openpower
.state
import CoreState
42 from openpower
.util
import (spr_to_fast
, log
)
45 def decode_spr_num(spr
):
46 return Cat(spr
[5:10], spr
[0:5])
49 def instr_is_priv(m
, op
, insn
):
50 """determines if the instruction is privileged or not
53 is_priv_insn
= Signal(reset_less
=True)
55 with m
.Case(MicrOp
.OP_ATTN
, MicrOp
.OP_MFMSR
, MicrOp
.OP_MTMSRD
,
56 MicrOp
.OP_MTMSR
, MicrOp
.OP_RFID
):
57 comb
+= is_priv_insn
.eq(1)
58 with m
.Case(MicrOp
.OP_TLBIE
) : comb
+= is_priv_insn
.eq(1)
59 with m
.Case(MicrOp
.OP_MFSPR
, MicrOp
.OP_MTSPR
):
60 with m
.If(insn
[20]): # field XFX.spr[-1] i think
61 comb
+= is_priv_insn
.eq(1)
65 class SPRMap(Elaboratable
):
66 """SPRMap: maps POWER9 SPR numbers to internal enum values, fast and slow
69 def __init__(self
, regreduce_en
):
70 self
.regreduce_en
= regreduce_en
76 self
.spr_i
= Signal(10, reset_less
=True)
77 self
.spr_o
= Data(SPR
, name
="spr_o")
78 self
.fast_o
= Data(3, name
="fast_o")
80 def elaborate(self
, platform
):
86 with m
.Switch(self
.spr_i
):
87 for i
, x
in enumerate(SPR
):
89 m
.d
.comb
+= self
.spr_o
.data
.eq(i
)
90 m
.d
.comb
+= self
.spr_o
.ok
.eq(1)
91 for x
, v
in spr_to_fast
.items():
93 m
.d
.comb
+= self
.fast_o
.data
.eq(v
)
94 m
.d
.comb
+= self
.fast_o
.ok
.eq(1)
98 class DecodeA(Elaboratable
):
99 """DecodeA from instruction
101 decodes register RA, implicit and explicit CSRs
104 def __init__(self
, dec
, regreduce_en
):
105 self
.regreduce_en
= regreduce_en
106 if self
.regreduce_en
:
111 self
.sel_in
= Signal(In1Sel
, reset_less
=True)
112 self
.insn_in
= Signal(32, reset_less
=True)
113 self
.reg_out
= Data(5, name
="reg_a")
114 self
.spr_out
= Data(SPR
, "spr_a")
115 self
.fast_out
= Data(3, "fast_a")
116 self
.sv_nz
= Signal(1)
118 def elaborate(self
, platform
):
123 m
.submodules
.sprmap
= sprmap
= SPRMap(self
.regreduce_en
)
125 # select Register A field, if *full 7 bits* are zero (2 more from SVP64)
126 ra
= Signal(5, reset_less
=True)
127 comb
+= ra
.eq(self
.dec
.RA
)
128 with m
.If((self
.sel_in
== In1Sel
.RA
) |
129 ((self
.sel_in
== In1Sel
.RA_OR_ZERO
) &
130 ((ra
!= Const(0, 5)) |
(self
.sv_nz
!= Const(0, 1))))):
131 comb
+= reg
.data
.eq(ra
)
134 # some Logic/ALU ops have RS as the 3rd arg, but no "RA".
135 # moved it to 1st position (in1_sel)... because
136 rs
= Signal(5, reset_less
=True)
137 comb
+= rs
.eq(self
.dec
.RS
)
138 with m
.If(self
.sel_in
== In1Sel
.RS
):
139 comb
+= reg
.data
.eq(rs
)
142 # select Register FRA field,
143 fra
= Signal(5, reset_less
=True)
144 comb
+= fra
.eq(self
.dec
.FRA
)
145 with m
.If(self
.sel_in
== In1Sel
.FRA
):
146 comb
+= reg
.data
.eq(fra
)
149 # select Register FRS field,
150 frs
= Signal(5, reset_less
=True)
151 comb
+= frs
.eq(self
.dec
.FRS
)
152 with m
.If(self
.sel_in
== In1Sel
.FRS
):
153 comb
+= reg
.data
.eq(frs
)
156 # decode Fast-SPR based on instruction type
157 with m
.Switch(op
.internal_op
):
159 # BC or BCREG: implicit register (CTR) NOTE: same in DecodeOut
160 with m
.Case(MicrOp
.OP_BC
):
161 with m
.If(~self
.dec
.BO
[2]): # 3.0B p38 BO2=0, use CTR reg
163 comb
+= self
.fast_out
.data
.eq(FastRegsEnum
.CTR
)
164 comb
+= self
.fast_out
.ok
.eq(1)
165 with m
.Case(MicrOp
.OP_BCREG
):
166 xo9
= self
.dec
.FormXL
.XO
[9] # 3.0B p38 top bit of XO
167 xo5
= self
.dec
.FormXL
.XO
[5] # 3.0B p38
168 with m
.If(xo9
& ~xo5
):
170 comb
+= self
.fast_out
.data
.eq(FastRegsEnum
.CTR
)
171 comb
+= self
.fast_out
.ok
.eq(1)
173 # MFSPR move from SPRs
174 with m
.Case(MicrOp
.OP_MFSPR
):
175 spr
= Signal(10, reset_less
=True)
176 comb
+= spr
.eq(decode_spr_num(self
.dec
.SPR
)) # from XFX
177 comb
+= sprmap
.spr_i
.eq(spr
)
178 comb
+= self
.spr_out
.eq(sprmap
.spr_o
)
179 comb
+= self
.fast_out
.eq(sprmap
.fast_o
)
184 class DecodeAImm(Elaboratable
):
185 """DecodeA immediate from instruction
187 decodes register RA, whether immediate-zero, implicit and
188 explicit CSRs. SVP64 mode requires 2 extra bits
191 def __init__(self
, dec
):
193 self
.sel_in
= Signal(In1Sel
, reset_less
=True)
194 self
.immz_out
= Signal(reset_less
=True)
195 self
.sv_nz
= Signal(1) # EXTRA bits from SVP64
197 def elaborate(self
, platform
):
201 # zero immediate requested
202 ra
= Signal(5, reset_less
=True)
203 comb
+= ra
.eq(self
.dec
.RA
)
204 with m
.If((self
.sel_in
== In1Sel
.RA_OR_ZERO
) &
205 (ra
== Const(0, 5)) &
206 (self
.sv_nz
== Const(0, 1))):
207 comb
+= self
.immz_out
.eq(1)
212 class DecodeB(Elaboratable
):
213 """DecodeB from instruction
215 decodes register RB, different forms of immediate (signed, unsigned),
216 and implicit SPRs. register B is basically "lane 2" into the CompUnits.
217 by industry-standard convention, "lane 2" is where fully-decoded
218 immediates are muxed in.
221 def __init__(self
, dec
):
223 self
.sel_in
= Signal(In2Sel
, reset_less
=True)
224 self
.insn_in
= Signal(32, reset_less
=True)
225 self
.reg_out
= Data(7, "reg_b")
226 self
.reg_isvec
= Signal(1, name
="reg_b_isvec") # TODO: in reg_out
227 self
.fast_out
= Data(3, "fast_b")
229 def elaborate(self
, platform
):
235 # select Register B field
236 with m
.Switch(self
.sel_in
):
237 with m
.Case(In2Sel
.FRB
):
238 comb
+= reg
.data
.eq(self
.dec
.FRB
)
240 with m
.Case(In2Sel
.RB
):
241 comb
+= reg
.data
.eq(self
.dec
.RB
)
243 with m
.Case(In2Sel
.RS
):
244 # for M-Form shiftrot
245 comb
+= reg
.data
.eq(self
.dec
.RS
)
248 # decode SPR2 based on instruction type
249 # BCREG implicitly uses LR or TAR for 2nd reg
250 # CTR however is already in fast_spr1 *not* 2.
251 with m
.If(op
.internal_op
== MicrOp
.OP_BCREG
):
252 xo9
= self
.dec
.FormXL
.XO
[9] # 3.0B p38 top bit of XO
253 xo5
= self
.dec
.FormXL
.XO
[5] # 3.0B p38
255 comb
+= self
.fast_out
.data
.eq(FastRegsEnum
.LR
)
256 comb
+= self
.fast_out
.ok
.eq(1)
258 comb
+= self
.fast_out
.data
.eq(FastRegsEnum
.TAR
)
259 comb
+= self
.fast_out
.ok
.eq(1)
264 class DecodeBImm(Elaboratable
):
265 """DecodeB immediate from instruction
267 def __init__(self
, dec
):
269 self
.sel_in
= Signal(In2Sel
, reset_less
=True)
270 self
.imm_out
= Data(64, "imm_b")
272 def elaborate(self
, platform
):
276 # select Register B Immediate
277 with m
.Switch(self
.sel_in
):
278 with m
.Case(In2Sel
.CONST_UI
): # unsigned
279 comb
+= self
.imm_out
.data
.eq(self
.dec
.UI
)
280 comb
+= self
.imm_out
.ok
.eq(1)
281 with m
.Case(In2Sel
.CONST_SI
): # sign-extended 16-bit
282 si
= Signal(16, reset_less
=True)
283 comb
+= si
.eq(self
.dec
.SI
)
284 comb
+= self
.imm_out
.data
.eq(exts(si
, 16, 64))
285 comb
+= self
.imm_out
.ok
.eq(1)
286 with m
.Case(In2Sel
.CONST_SI_HI
): # sign-extended 16+16=32 bit
287 si_hi
= Signal(32, reset_less
=True)
288 comb
+= si_hi
.eq(self
.dec
.SI
<< 16)
289 comb
+= self
.imm_out
.data
.eq(exts(si_hi
, 32, 64))
290 comb
+= self
.imm_out
.ok
.eq(1)
291 with m
.Case(In2Sel
.CONST_UI_HI
): # unsigned
292 ui
= Signal(16, reset_less
=True)
293 comb
+= ui
.eq(self
.dec
.UI
)
294 comb
+= self
.imm_out
.data
.eq(ui
<< 16)
295 comb
+= self
.imm_out
.ok
.eq(1)
296 with m
.Case(In2Sel
.CONST_LI
): # sign-extend 24+2=26 bit
297 li
= Signal(26, reset_less
=True)
298 comb
+= li
.eq(self
.dec
.LI
<< 2)
299 comb
+= self
.imm_out
.data
.eq(exts(li
, 26, 64))
300 comb
+= self
.imm_out
.ok
.eq(1)
301 with m
.Case(In2Sel
.CONST_BD
): # sign-extend (14+2)=16 bit
302 bd
= Signal(16, reset_less
=True)
303 comb
+= bd
.eq(self
.dec
.BD
<< 2)
304 comb
+= self
.imm_out
.data
.eq(exts(bd
, 16, 64))
305 comb
+= self
.imm_out
.ok
.eq(1)
306 with m
.Case(In2Sel
.CONST_DS
): # sign-extended (14+2=16) bit
307 ds
= Signal(16, reset_less
=True)
308 comb
+= ds
.eq(self
.dec
.DS
<< 2)
309 comb
+= self
.imm_out
.data
.eq(exts(ds
, 16, 64))
310 comb
+= self
.imm_out
.ok
.eq(1)
311 with m
.Case(In2Sel
.CONST_M1
): # signed (-1)
312 comb
+= self
.imm_out
.data
.eq(~
Const(0, 64)) # all 1s
313 comb
+= self
.imm_out
.ok
.eq(1)
314 with m
.Case(In2Sel
.CONST_SH
): # unsigned - for shift
315 comb
+= self
.imm_out
.data
.eq(self
.dec
.sh
)
316 comb
+= self
.imm_out
.ok
.eq(1)
317 with m
.Case(In2Sel
.CONST_SH32
): # unsigned - for shift
318 comb
+= self
.imm_out
.data
.eq(self
.dec
.SH32
)
319 comb
+= self
.imm_out
.ok
.eq(1)
324 class DecodeC(Elaboratable
):
325 """DecodeC from instruction
327 decodes register RC. this is "lane 3" into some CompUnits (not many)
330 def __init__(self
, dec
):
332 self
.sel_in
= Signal(In3Sel
, reset_less
=True)
333 self
.insn_in
= Signal(32, reset_less
=True)
334 self
.reg_out
= Data(5, "reg_c")
336 def elaborate(self
, platform
):
342 # select Register C field
343 with m
.Switch(self
.sel_in
):
344 with m
.Case(In3Sel
.RB
):
345 # for M-Form shiftrot
346 comb
+= reg
.data
.eq(self
.dec
.RB
)
348 with m
.Case(In3Sel
.FRS
):
349 comb
+= reg
.data
.eq(self
.dec
.FRS
)
351 with m
.Case(In3Sel
.FRC
):
352 comb
+= reg
.data
.eq(self
.dec
.FRC
)
354 with m
.Case(In3Sel
.RS
):
355 comb
+= reg
.data
.eq(self
.dec
.RS
)
361 class DecodeOut(Elaboratable
):
362 """DecodeOut from instruction
364 decodes output register RA, RT or SPR
367 def __init__(self
, dec
, regreduce_en
):
368 self
.regreduce_en
= regreduce_en
369 if self
.regreduce_en
:
374 self
.sel_in
= Signal(OutSel
, reset_less
=True)
375 self
.insn_in
= Signal(32, reset_less
=True)
376 self
.reg_out
= Data(5, "reg_o")
377 self
.spr_out
= Data(SPR
, "spr_o")
378 self
.fast_out
= Data(3, "fast_o")
380 def elaborate(self
, platform
):
383 m
.submodules
.sprmap
= sprmap
= SPRMap(self
.regreduce_en
)
387 # select Register out field
388 with m
.Switch(self
.sel_in
):
389 with m
.Case(OutSel
.FRT
):
390 comb
+= reg
.data
.eq(self
.dec
.FRT
)
392 with m
.Case(OutSel
.RT
):
393 comb
+= reg
.data
.eq(self
.dec
.RT
)
395 with m
.Case(OutSel
.RA
):
396 comb
+= reg
.data
.eq(self
.dec
.RA
)
398 with m
.Case(OutSel
.SPR
):
399 spr
= Signal(10, reset_less
=True)
400 comb
+= spr
.eq(decode_spr_num(self
.dec
.SPR
)) # from XFX
401 # MFSPR move to SPRs - needs mapping
402 with m
.If(op
.internal_op
== MicrOp
.OP_MTSPR
):
403 comb
+= sprmap
.spr_i
.eq(spr
)
404 comb
+= self
.spr_out
.eq(sprmap
.spr_o
)
405 comb
+= self
.fast_out
.eq(sprmap
.fast_o
)
408 with m
.Switch(op
.internal_op
):
410 # BC or BCREG: implicit register (CTR) NOTE: same in DecodeA
411 with m
.Case(MicrOp
.OP_BC
, MicrOp
.OP_BCREG
):
412 with m
.If(~self
.dec
.BO
[2]): # 3.0B p38 BO2=0, use CTR reg
414 comb
+= self
.fast_out
.data
.eq(FastRegsEnum
.CTR
)
415 comb
+= self
.fast_out
.ok
.eq(1)
417 # RFID 1st spr (fast)
418 with m
.Case(MicrOp
.OP_RFID
):
419 comb
+= self
.fast_out
.data
.eq(FastRegsEnum
.SRR0
) # SRR0
420 comb
+= self
.fast_out
.ok
.eq(1)
425 class DecodeOut2(Elaboratable
):
426 """DecodeOut2 from instruction
428 decodes output registers (2nd one). note that RA is *implicit* below,
429 which now causes problems with SVP64
431 TODO: SVP64 is a little more complex, here. svp64 allows extending
432 by one more destination by having one more EXTRA field. RA-as-src
433 is not the same as RA-as-dest. limited in that it's the same first
434 5 bits (from the v3.0B opcode), but still kinda cool. mostly used
435 for operations that have src-as-dest: mostly this is LD/ST-with-update
436 but there are others.
439 def __init__(self
, dec
):
441 self
.sel_in
= Signal(OutSel
, reset_less
=True)
442 self
.lk
= Signal(reset_less
=True)
443 self
.insn_in
= Signal(32, reset_less
=True)
444 self
.reg_out
= Data(5, "reg_o2")
445 self
.fast_out
= Data(3, "fast_o2")
446 self
.fast_out3
= Data(3, "fast_o3")
448 def elaborate(self
, platform
):
452 #m.submodules.svdec = svdec = SVP64RegExtra()
454 # get the 5-bit reg data before svp64-munging it into 7-bit plus isvec
455 #reg = Signal(5, reset_less=True)
457 if hasattr(self
.dec
.op
, "upd"):
458 # update mode LD/ST uses read-reg A also as an output
459 with m
.If(self
.dec
.op
.upd
== LDSTMode
.update
):
460 comb
+= self
.reg_out
.data
.eq(self
.dec
.RA
)
461 comb
+= self
.reg_out
.ok
.eq(1)
463 # B, BC or BCREG: potential implicit register (LR) output
464 # these give bl, bcl, bclrl, etc.
465 with m
.Switch(op
.internal_op
):
467 # BC* implicit register (LR)
468 with m
.Case(MicrOp
.OP_BC
, MicrOp
.OP_B
, MicrOp
.OP_BCREG
):
469 with m
.If(self
.lk
): # "link" mode
470 comb
+= self
.fast_out
.data
.eq(FastRegsEnum
.LR
) # LR
471 comb
+= self
.fast_out
.ok
.eq(1)
473 # RFID 2nd and 3rd spr (fast)
474 with m
.Case(MicrOp
.OP_RFID
):
475 comb
+= self
.fast_out
.data
.eq(FastRegsEnum
.SRR1
) # SRR1
476 comb
+= self
.fast_out
.ok
.eq(1)
477 comb
+= self
.fast_out3
.data
.eq(FastRegsEnum
.SVSRR0
) # SVSRR0
478 comb
+= self
.fast_out3
.ok
.eq(1)
483 class DecodeRC(Elaboratable
):
484 """DecodeRc from instruction
486 decodes Record bit Rc
489 def __init__(self
, dec
):
491 self
.sel_in
= Signal(RC
, reset_less
=True)
492 self
.insn_in
= Signal(32, reset_less
=True)
493 self
.rc_out
= Data(1, "rc")
495 def elaborate(self
, platform
):
499 # select Record bit out field
500 with m
.Switch(self
.sel_in
):
502 comb
+= self
.rc_out
.data
.eq(self
.dec
.Rc
)
503 comb
+= self
.rc_out
.ok
.eq(1)
505 comb
+= self
.rc_out
.data
.eq(1)
506 comb
+= self
.rc_out
.ok
.eq(1)
507 with m
.Case(RC
.NONE
):
508 comb
+= self
.rc_out
.data
.eq(0)
509 comb
+= self
.rc_out
.ok
.eq(1)
514 class DecodeOE(Elaboratable
):
515 """DecodeOE from instruction
517 decodes OE field: uses RC decode detection which might not be good
519 -- For now, use "rc" in the decode table to decide whether oe exists.
520 -- This is not entirely correct architecturally: For mulhd and
521 -- mulhdu, the OE field is reserved. It remains to be seen what an
522 -- actual POWER9 does if we set it on those instructions, for now we
523 -- test that further down when assigning to the multiplier oe input.
526 def __init__(self
, dec
):
528 self
.sel_in
= Signal(RC
, reset_less
=True)
529 self
.insn_in
= Signal(32, reset_less
=True)
530 self
.oe_out
= Data(1, "oe")
532 def elaborate(self
, platform
):
537 with m
.Switch(op
.internal_op
):
539 # mulhw, mulhwu, mulhd, mulhdu - these *ignore* OE
541 # XXX ARGH! ignoring OE causes incompatibility with microwatt
542 # http://lists.libre-soc.org/pipermail/libre-soc-dev/2020-August/000302.html
543 with m
.Case(MicrOp
.OP_MUL_H64
, MicrOp
.OP_MUL_H32
,
544 MicrOp
.OP_EXTS
, MicrOp
.OP_CNTZ
,
545 MicrOp
.OP_SHL
, MicrOp
.OP_SHR
, MicrOp
.OP_RLC
,
546 MicrOp
.OP_LOAD
, MicrOp
.OP_STORE
,
547 MicrOp
.OP_RLCL
, MicrOp
.OP_RLCR
,
551 # all other ops decode OE field
553 # select OE bit out field
554 with m
.Switch(self
.sel_in
):
556 comb
+= self
.oe_out
.data
.eq(self
.dec
.OE
)
557 comb
+= self
.oe_out
.ok
.eq(1)
562 class DecodeCRIn(Elaboratable
):
563 """Decodes input CR from instruction
565 CR indices - insn fields - (not the data *in* the CR) require only 3
566 bits because they refer to CR0-CR7
569 def __init__(self
, dec
):
571 self
.sel_in
= Signal(CRInSel
, reset_less
=True)
572 self
.insn_in
= Signal(32, reset_less
=True)
573 self
.cr_bitfield
= Data(3, "cr_bitfield")
574 self
.cr_bitfield_b
= Data(3, "cr_bitfield_b")
575 self
.cr_bitfield_o
= Data(3, "cr_bitfield_o")
576 self
.whole_reg
= Data(8, "cr_fxm")
577 self
.sv_override
= Signal(2, reset_less
=True) # do not do EXTRA spec
579 def elaborate(self
, platform
):
583 m
.submodules
.ppick
= ppick
= PriorityPicker(8, reverse_i
=True,
586 # zero-initialisation
587 comb
+= self
.cr_bitfield
.ok
.eq(0)
588 comb
+= self
.cr_bitfield_b
.ok
.eq(0)
589 comb
+= self
.cr_bitfield_o
.ok
.eq(0)
590 comb
+= self
.whole_reg
.ok
.eq(0)
591 comb
+= self
.sv_override
.eq(0)
593 # select the relevant CR bitfields
594 with m
.Switch(self
.sel_in
):
595 with m
.Case(CRInSel
.NONE
):
596 pass # No bitfield activated
597 with m
.Case(CRInSel
.CR0
):
598 comb
+= self
.cr_bitfield
.data
.eq(0) # CR0 (MSB0 numbering)
599 comb
+= self
.cr_bitfield
.ok
.eq(1)
600 comb
+= self
.sv_override
.eq(1)
601 with m
.Case(CRInSel
.CR1
):
602 comb
+= self
.cr_bitfield
.data
.eq(1) # CR1 (MSB0 numbering)
603 comb
+= self
.cr_bitfield
.ok
.eq(1)
604 comb
+= self
.sv_override
.eq(2)
605 with m
.Case(CRInSel
.BI
):
606 comb
+= self
.cr_bitfield
.data
.eq(self
.dec
.BI
[2:5])
607 comb
+= self
.cr_bitfield
.ok
.eq(1)
608 with m
.Case(CRInSel
.BFA
):
609 comb
+= self
.cr_bitfield
.data
.eq(self
.dec
.FormX
.BFA
)
610 comb
+= self
.cr_bitfield
.ok
.eq(1)
611 with m
.Case(CRInSel
.BA_BB
):
612 comb
+= self
.cr_bitfield
.data
.eq(self
.dec
.BA
[2:5])
613 comb
+= self
.cr_bitfield
.ok
.eq(1)
614 comb
+= self
.cr_bitfield_b
.data
.eq(self
.dec
.BB
[2:5])
615 comb
+= self
.cr_bitfield_b
.ok
.eq(1)
616 comb
+= self
.cr_bitfield_o
.data
.eq(self
.dec
.BT
[2:5])
617 comb
+= self
.cr_bitfield_o
.ok
.eq(1)
618 with m
.Case(CRInSel
.BC
):
619 comb
+= self
.cr_bitfield
.data
.eq(self
.dec
.BC
[2:5])
620 comb
+= self
.cr_bitfield
.ok
.eq(1)
621 with m
.Case(CRInSel
.WHOLE_REG
):
622 comb
+= self
.whole_reg
.ok
.eq(1)
623 move_one
= Signal(reset_less
=True)
624 comb
+= move_one
.eq(self
.insn_in
[20]) # MSB0 bit 11
625 with m
.If((op
.internal_op
== MicrOp
.OP_MFCR
) & move_one
):
626 # must one-hot the FXM field
627 comb
+= ppick
.i
.eq(self
.dec
.FXM
)
628 comb
+= self
.whole_reg
.data
.eq(ppick
.o
)
630 # otherwise use all of it
631 comb
+= self
.whole_reg
.data
.eq(0xff)
636 class DecodeCROut(Elaboratable
):
637 """Decodes input CR from instruction
639 CR indices - insn fields - (not the data *in* the CR) require only 3
640 bits because they refer to CR0-CR7
643 def __init__(self
, dec
):
645 self
.rc_in
= Signal(reset_less
=True)
646 self
.sel_in
= Signal(CROutSel
, reset_less
=True)
647 self
.insn_in
= Signal(32, reset_less
=True)
648 self
.cr_bitfield
= Data(3, "cr_bitfield")
649 self
.whole_reg
= Data(8, "cr_fxm")
650 self
.sv_override
= Signal(2, reset_less
=True) # do not do EXTRA spec
652 def elaborate(self
, platform
):
656 m
.submodules
.ppick
= ppick
= PriorityPicker(8, reverse_i
=True,
659 comb
+= self
.cr_bitfield
.ok
.eq(0)
660 comb
+= self
.whole_reg
.ok
.eq(0)
661 comb
+= self
.sv_override
.eq(0)
663 # please note these MUST match (setting of cr_bitfield.ok) exactly
664 # with write_cr0 below in PowerDecoder2. the reason it's separated
665 # is to avoid having duplicate copies of DecodeCROut in multiple
666 # PowerDecoderSubsets. register decoding should be a one-off in
667 # PowerDecoder2. see https://bugs.libre-soc.org/show_bug.cgi?id=606
669 with m
.Switch(self
.sel_in
):
670 with m
.Case(CROutSel
.NONE
):
671 pass # No bitfield activated
672 with m
.Case(CROutSel
.CR0
):
673 comb
+= self
.cr_bitfield
.data
.eq(0) # CR0 (MSB0 numbering)
674 comb
+= self
.cr_bitfield
.ok
.eq(self
.rc_in
) # only when RC=1
675 comb
+= self
.sv_override
.eq(1)
676 with m
.Case(CROutSel
.CR1
):
677 comb
+= self
.cr_bitfield
.data
.eq(1) # CR1 (MSB0 numbering)
678 comb
+= self
.cr_bitfield
.ok
.eq(self
.rc_in
) # only when RC=1
679 comb
+= self
.sv_override
.eq(2)
680 with m
.Case(CROutSel
.BF
):
681 comb
+= self
.cr_bitfield
.data
.eq(self
.dec
.FormX
.BF
)
682 comb
+= self
.cr_bitfield
.ok
.eq(1)
683 with m
.Case(CROutSel
.BT
):
684 comb
+= self
.cr_bitfield
.data
.eq(self
.dec
.FormXL
.BT
[2:5])
685 comb
+= self
.cr_bitfield
.ok
.eq(1)
686 with m
.Case(CROutSel
.WHOLE_REG
):
687 comb
+= self
.whole_reg
.ok
.eq(1)
688 move_one
= Signal(reset_less
=True)
689 comb
+= move_one
.eq(self
.insn_in
[20])
690 with m
.If((op
.internal_op
== MicrOp
.OP_MTCRF
)):
692 # must one-hot the FXM field
693 comb
+= ppick
.i
.eq(self
.dec
.FXM
)
694 with m
.If(ppick
.en_o
):
695 comb
+= self
.whole_reg
.data
.eq(ppick
.o
)
697 comb
+= self
.whole_reg
.data
.eq(0b00000001) # CR7
699 comb
+= self
.whole_reg
.data
.eq(self
.dec
.FXM
)
701 # otherwise use all of it
702 comb
+= self
.whole_reg
.data
.eq(0xff)
706 # dictionary of Input Record field names that, if they exist,
707 # will need a corresponding CSV Decoder file column (actually, PowerOp)
708 # to be decoded (this includes the single bit names)
709 record_names
= {'insn_type': 'internal_op',
710 'fn_unit': 'function_unit',
711 'SV_Ptype': 'SV_Ptype',
715 'imm_data': 'in2_sel',
716 'invert_in': 'inv_a',
717 'invert_out': 'inv_out',
720 'output_carry': 'cry_out',
721 'input_carry': 'cry_in',
722 'is_32bit': 'is_32b',
725 'data_len': 'ldst_len',
726 'byte_reverse': 'br',
727 'sign_extend': 'sgn_ext',
732 class PowerDecodeSubset(Elaboratable
):
733 """PowerDecodeSubset: dynamic subset decoder
735 only fields actually requested are copied over. hence, "subset" (duh).
737 def __init__(self
, dec
, opkls
=None, fn_name
=None, final
=False, state
=None,
738 svp64_en
=True, regreduce_en
=False):
740 self
.svp64_en
= svp64_en
741 self
.regreduce_en
= regreduce_en
743 self
.sv_rm
= SVP64Rec(name
="dec_svp64") # SVP64 RM field
744 self
.rm_dec
= SVP64RMModeDecode("svp64_rm_dec")
745 # set these to the predicate mask bits needed for the ALU
746 self
.pred_sm
= Signal() # TODO expand to SIMD mask width
747 self
.pred_dm
= Signal() # TODO expand to SIMD mask width
748 self
.sv_a_nz
= Signal(1)
751 self
.fn_name
= fn_name
753 opkls
= Decode2ToOperand
754 self
.do
= opkls(fn_name
)
755 col_subset
= self
.get_col_subset(self
.do
)
757 # only needed for "main" PowerDecode2
759 self
.e
= Decode2ToExecute1Type(name
=self
.fn_name
, do
=self
.do
,
760 regreduce_en
=regreduce_en
)
762 # create decoder if one not already given
764 dec
= create_pdecode(name
=fn_name
, col_subset
=col_subset
,
765 row_subset
=self
.rowsubsetfn
)
768 # state information needed by the Decoder
770 state
= CoreState("dec2")
773 def get_col_subset(self
, do
):
774 subset
= { 'cr_in', 'cr_out', 'rc_sel'} # needed, non-optional
775 for k
, v
in record_names
.items():
778 log ("get_col_subset", self
.fn_name
, do
.fields
, subset
)
781 def rowsubsetfn(self
, opcode
, row
):
782 """select per-Function-Unit subset of opcodes to be processed
784 normally this just looks at the "unit" column. MMU is different
785 in that it processes specific SPR set/get operations that the SPR
788 return (row
['unit'] == self
.fn_name
or
789 # sigh a dreadful hack: MTSPR and MFSPR need to be processed
790 # by the MMU pipeline so we direct those opcodes to MMU **AND**
791 # SPR pipelines, then selectively weed out the SPRs that should
792 # or should not not go to each pipeline, further down.
793 # really this should be done by modifying the CSV syntax
794 # to support multiple tasks (unit column multiple entries)
795 # see https://bugs.libre-soc.org/show_bug.cgi?id=310
796 (self
.fn_name
== 'MMU' and row
['unit'] == 'SPR' and
797 row
['internal op'] in ['OP_MTSPR', 'OP_MFSPR'])
801 ports
= self
.dec
.ports() + self
.e
.ports()
803 ports
+= self
.sv_rm
.ports()
806 def needs_field(self
, field
, op_field
):
811 return hasattr(do
, field
) and self
.op_get(op_field
) is not None
813 def do_get(self
, field
, final
=False):
814 if final
or self
.final
:
818 return getattr(do
, field
, None)
820 def do_copy(self
, field
, val
, final
=False):
821 df
= self
.do_get(field
, final
)
822 if df
is not None and val
is not None:
826 def op_get(self
, op_field
):
827 return getattr(self
.dec
.op
, op_field
, None)
829 def elaborate(self
, platform
):
830 if self
.regreduce_en
:
837 op
, do
= self
.dec
.op
, self
.do
838 msr
, cia
, svstate
= state
.msr
, state
.pc
, state
.svstate
839 # fill in for a normal instruction (not an exception)
840 # copy over if non-exception, non-privileged etc. is detected
842 if self
.fn_name
is None:
845 name
= self
.fn_name
+ "tmp"
846 self
.e_tmp
= Decode2ToExecute1Type(name
=name
, opkls
=self
.opkls
,
847 regreduce_en
=self
.regreduce_en
)
849 # set up submodule decoders
850 m
.submodules
.dec
= self
.dec
851 m
.submodules
.dec_rc
= self
.dec_rc
= dec_rc
= DecodeRC(self
.dec
)
852 m
.submodules
.dec_oe
= dec_oe
= DecodeOE(self
.dec
)
855 # and SVP64 RM mode decoder
856 m
.submodules
.sv_rm_dec
= rm_dec
= self
.rm_dec
858 # copy instruction through...
859 for i
in [do
.insn
, dec_rc
.insn_in
, dec_oe
.insn_in
, ]:
860 comb
+= i
.eq(self
.dec
.opcode_in
)
862 # ...and subdecoders' input fields
863 comb
+= dec_rc
.sel_in
.eq(op
.rc_sel
)
864 comb
+= dec_oe
.sel_in
.eq(op
.rc_sel
) # XXX should be OE sel
867 comb
+= self
.do_copy("msr", msr
)
868 comb
+= self
.do_copy("cia", cia
)
869 comb
+= self
.do_copy("svstate", svstate
)
871 # set up instruction type
872 # no op: defaults to OP_ILLEGAL
873 internal_op
= self
.op_get("internal_op")
874 comb
+= self
.do_copy("insn_type", internal_op
)
876 # function unit for decoded instruction: requires minor redirect
878 fn
= self
.op_get("function_unit")
879 spr
= Signal(10, reset_less
=True)
880 comb
+= spr
.eq(decode_spr_num(self
.dec
.SPR
)) # from XFX
882 # Microwatt doesn't implement the partition table
883 # instead has PRTBL register (SPR) to point to process table
885 is_mmu_spr
= Signal()
886 comb
+= is_spr_mv
.eq((internal_op
== MicrOp
.OP_MTSPR
) |
887 (internal_op
== MicrOp
.OP_MFSPR
))
888 comb
+= is_mmu_spr
.eq((spr
== SPR
.DSISR
.value
) |
889 (spr
== SPR
.DAR
.value
) |
890 (spr
== SPR
.PRTBL
.value
) |
891 (spr
== SPR
.PIDR
.value
))
892 # MMU must receive MMU SPRs
893 with m
.If(is_spr_mv
& (fn
== Function
.SPR
) & is_mmu_spr
):
894 comb
+= self
.do_copy("fn_unit", Function
.NONE
)
895 comb
+= self
.do_copy("insn_type", MicrOp
.OP_ILLEGAL
)
896 # SPR pipe must *not* receive MMU SPRs
897 with m
.Elif(is_spr_mv
& (fn
== Function
.MMU
) & ~is_mmu_spr
):
898 comb
+= self
.do_copy("fn_unit", Function
.NONE
)
899 comb
+= self
.do_copy("insn_type", MicrOp
.OP_ILLEGAL
)
902 comb
+= self
.do_copy("fn_unit", fn
)
905 if self
.needs_field("zero_a", "in1_sel"):
906 m
.submodules
.dec_ai
= dec_ai
= DecodeAImm(self
.dec
)
907 comb
+= dec_ai
.sv_nz
.eq(self
.sv_a_nz
)
908 comb
+= dec_ai
.sel_in
.eq(op
.in1_sel
)
909 comb
+= self
.do_copy("zero_a", dec_ai
.immz_out
) # RA==0 detected
910 if self
.needs_field("imm_data", "in2_sel"):
911 m
.submodules
.dec_bi
= dec_bi
= DecodeBImm(self
.dec
)
912 comb
+= dec_bi
.sel_in
.eq(op
.in2_sel
)
913 comb
+= self
.do_copy("imm_data", dec_bi
.imm_out
) # imm in RB
916 comb
+= self
.do_copy("rc", dec_rc
.rc_out
)
917 comb
+= self
.do_copy("oe", dec_oe
.oe_out
)
919 # CR in/out - note: these MUST match with what happens in
921 rc_out
= self
.dec_rc
.rc_out
.data
922 with m
.Switch(op
.cr_out
):
923 with m
.Case(CROutSel
.CR0
, CROutSel
.CR1
):
924 comb
+= self
.do_copy("write_cr0", rc_out
) # only when RC=1
925 with m
.Case(CROutSel
.BF
, CROutSel
.BT
):
926 comb
+= self
.do_copy("write_cr0", 1)
928 comb
+= self
.do_copy("input_cr", self
.op_get("cr_in")) # CR in
929 comb
+= self
.do_copy("output_cr", self
.op_get("cr_out")) # CR out
932 # connect up SVP64 RM Mode decoding
933 fn
= self
.op_get("function_unit")
934 comb
+= rm_dec
.fn_in
.eq(fn
) # decode needs to know if LD/ST type
935 comb
+= rm_dec
.ptype_in
.eq(op
.SV_Ptype
) # Single/Twin predicated
936 comb
+= rm_dec
.rc_in
.eq(rc_out
) # Rc=1
937 comb
+= rm_dec
.rm_in
.eq(self
.sv_rm
) # SVP64 RM mode
938 if self
.needs_field("imm_data", "in2_sel"):
939 bzero
= dec_bi
.imm_out
.ok
& ~dec_bi
.imm_out
.data
.bool()
940 comb
+= rm_dec
.ldst_imz_in
.eq(bzero
) # B immediate is zero
942 # decoded/selected instruction flags
943 comb
+= self
.do_copy("data_len", self
.op_get("ldst_len"))
944 comb
+= self
.do_copy("invert_in", self
.op_get("inv_a"))
945 comb
+= self
.do_copy("invert_out", self
.op_get("inv_out"))
946 comb
+= self
.do_copy("input_carry", self
.op_get("cry_in"))
947 comb
+= self
.do_copy("output_carry", self
.op_get("cry_out"))
948 comb
+= self
.do_copy("is_32bit", self
.op_get("is_32b"))
949 comb
+= self
.do_copy("is_signed", self
.op_get("sgn"))
950 lk
= self
.op_get("lk")
953 comb
+= self
.do_copy("lk", self
.dec
.LK
) # XXX TODO: accessor
955 comb
+= self
.do_copy("byte_reverse", self
.op_get("br"))
956 comb
+= self
.do_copy("sign_extend", self
.op_get("sgn_ext"))
957 comb
+= self
.do_copy("ldst_mode", self
.op_get("upd")) # LD/ST mode
959 # copy over SVP64 input record fields (if they exist)
961 # TODO, really do we have to do these explicitly?? sigh
962 #for (field, _) in sv_input_record_layout:
963 # comb += self.do_copy(field, self.rm_dec.op_get(field))
964 comb
+= self
.do_copy("sv_saturate", self
.rm_dec
.saturate
)
965 comb
+= self
.do_copy("sv_Ptype", self
.rm_dec
.ptype_in
)
966 comb
+= self
.do_copy("sv_ldstmode", self
.rm_dec
.ldstmode
)
967 # these get set up based on incoming mask bits. TODO:
968 # pass in multiple bits (later, when SIMD backends are enabled)
969 with m
.If(self
.rm_dec
.pred_sz
):
970 comb
+= self
.do_copy("sv_pred_sz", ~self
.pred_sm
)
971 with m
.If(self
.rm_dec
.pred_dz
):
972 comb
+= self
.do_copy("sv_pred_dz", ~self
.pred_dm
)
977 class PowerDecode2(PowerDecodeSubset
):
978 """PowerDecode2: the main instruction decoder.
980 whilst PowerDecode is responsible for decoding the actual opcode, this
981 module encapsulates further specialist, sparse information and
982 expansion of fields that is inconvenient to have in the CSV files.
983 for example: the encoding of the immediates, which are detected
984 and expanded out to their full value from an annotated (enum)
987 implicit register usage is also set up, here. for example: OP_BC
988 requires implicitly reading CTR, OP_RFID requires implicitly writing
991 in addition, PowerDecoder2 is responsible for detecting whether
992 instructions are illegal (or privileged) or not, and instead of
993 just leaving at that, *replacing* the instruction to execute with
994 a suitable alternative (trap).
996 LDSTExceptions are done the cycle _after_ they're detected (after
997 they come out of LDSTCompUnit). basically despite the instruction
998 being decoded, the results of the decode are completely ignored
999 and "exception.happened" used to set the "actual" instruction to
1000 "OP_TRAP". the LDSTException data structure gets filled in,
1001 in the CompTrapOpSubset and that's what it fills in SRR.
1003 to make this work, TestIssuer must notice "exception.happened"
1004 after the (failed) LD/ST and copies the LDSTException info from
1005 the output, into here (PowerDecoder2). without incrementing PC.
1008 def __init__(self
, dec
, opkls
=None, fn_name
=None, final
=False,
1009 state
=None, svp64_en
=True, regreduce_en
=False):
1010 super().__init
__(dec
, opkls
, fn_name
, final
, state
, svp64_en
,
1012 self
.ldst_exc
= LDSTException("dec2_exc")
1015 self
.cr_out_isvec
= Signal(1, name
="cr_out_isvec")
1016 self
.cr_in_isvec
= Signal(1, name
="cr_in_isvec")
1017 self
.cr_in_b_isvec
= Signal(1, name
="cr_in_b_isvec")
1018 self
.cr_in_o_isvec
= Signal(1, name
="cr_in_o_isvec")
1019 self
.in1_isvec
= Signal(1, name
="reg_a_isvec")
1020 self
.in2_isvec
= Signal(1, name
="reg_b_isvec")
1021 self
.in3_isvec
= Signal(1, name
="reg_c_isvec")
1022 self
.o_isvec
= Signal(1, name
="reg_o_isvec")
1023 self
.o2_isvec
= Signal(1, name
="reg_o2_isvec")
1024 self
.no_in_vec
= Signal(1, name
="no_in_vec") # no inputs vector
1025 self
.no_out_vec
= Signal(1, name
="no_out_vec") # no outputs vector
1026 self
.loop_continue
= Signal(1, name
="loop_continue")
1028 self
.no_in_vec
= Const(1, 1)
1029 self
.no_out_vec
= Const(1, 1)
1030 self
.loop_continue
= Const(0, 1)
1032 def get_col_subset(self
, opkls
):
1033 subset
= super().get_col_subset(opkls
)
1034 subset
.add("asmcode")
1035 subset
.add("in1_sel")
1036 subset
.add("in2_sel")
1037 subset
.add("in3_sel")
1038 subset
.add("out_sel")
1040 subset
.add("sv_in1")
1041 subset
.add("sv_in2")
1042 subset
.add("sv_in3")
1043 subset
.add("sv_out")
1044 subset
.add("sv_out2")
1045 subset
.add("sv_cr_in")
1046 subset
.add("sv_cr_out")
1047 subset
.add("SV_Etype")
1048 subset
.add("SV_Ptype")
1049 # from SVP64RMModeDecode
1050 for (field
, _
) in sv_input_record_layout
:
1053 subset
.add("internal_op")
1057 def elaborate(self
, platform
):
1058 m
= super().elaborate(platform
)
1061 e_out
, op
, do_out
= self
.e
, self
.dec
.op
, self
.e
.do
1062 dec_spr
, msr
, cia
, ext_irq
= state
.dec
, state
.msr
, state
.pc
, state
.eint
1063 rc_out
= self
.dec_rc
.rc_out
.data
1067 # fill in for a normal instruction (not an exception)
1068 # copy over if non-exception, non-privileged etc. is detected
1070 # set up submodule decoders
1071 m
.submodules
.dec_a
= dec_a
= DecodeA(self
.dec
, self
.regreduce_en
)
1072 m
.submodules
.dec_b
= dec_b
= DecodeB(self
.dec
)
1073 m
.submodules
.dec_c
= dec_c
= DecodeC(self
.dec
)
1074 m
.submodules
.dec_o
= dec_o
= DecodeOut(self
.dec
, self
.regreduce_en
)
1075 m
.submodules
.dec_o2
= dec_o2
= DecodeOut2(self
.dec
)
1076 m
.submodules
.dec_cr_in
= self
.dec_cr_in
= DecodeCRIn(self
.dec
)
1077 m
.submodules
.dec_cr_out
= self
.dec_cr_out
= DecodeCROut(self
.dec
)
1078 comb
+= dec_a
.sv_nz
.eq(self
.sv_a_nz
)
1081 # and SVP64 Extra decoders
1082 m
.submodules
.crout_svdec
= crout_svdec
= SVP64CRExtra()
1083 m
.submodules
.crin_svdec
= crin_svdec
= SVP64CRExtra()
1084 m
.submodules
.crin_svdec_b
= crin_svdec_b
= SVP64CRExtra()
1085 m
.submodules
.crin_svdec_o
= crin_svdec_o
= SVP64CRExtra()
1086 m
.submodules
.in1_svdec
= in1_svdec
= SVP64RegExtra()
1087 m
.submodules
.in2_svdec
= in2_svdec
= SVP64RegExtra()
1088 m
.submodules
.in3_svdec
= in3_svdec
= SVP64RegExtra()
1089 m
.submodules
.o_svdec
= o_svdec
= SVP64RegExtra()
1090 m
.submodules
.o2_svdec
= o2_svdec
= SVP64RegExtra()
1092 # debug access to crout_svdec (used in get_pdecode_cr_out)
1093 self
.crout_svdec
= crout_svdec
1095 # get the 5-bit reg data before svp64-munging it into 7-bit plus isvec
1096 reg
= Signal(5, reset_less
=True)
1098 # copy instruction through...
1099 for i
in [do
.insn
, dec_a
.insn_in
, dec_b
.insn_in
,
1100 self
.dec_cr_in
.insn_in
, self
.dec_cr_out
.insn_in
,
1101 dec_c
.insn_in
, dec_o
.insn_in
, dec_o2
.insn_in
]:
1102 comb
+= i
.eq(self
.dec
.opcode_in
)
1105 comb
+= self
.dec_cr_in
.sel_in
.eq(op
.cr_in
)
1106 comb
+= self
.dec_cr_out
.sel_in
.eq(op
.cr_out
)
1107 comb
+= self
.dec_cr_out
.rc_in
.eq(rc_out
)
1110 comb
+= self
.do_copy("read_cr_whole", self
.dec_cr_in
.whole_reg
)
1111 comb
+= self
.do_copy("write_cr_whole", self
.dec_cr_out
.whole_reg
)
1113 # ...and subdecoders' input fields
1114 comb
+= dec_a
.sel_in
.eq(op
.in1_sel
)
1115 comb
+= dec_b
.sel_in
.eq(op
.in2_sel
)
1116 comb
+= dec_c
.sel_in
.eq(op
.in3_sel
)
1117 comb
+= dec_o
.sel_in
.eq(op
.out_sel
)
1118 comb
+= dec_o2
.sel_in
.eq(op
.out_sel
)
1119 if hasattr(do
, "lk"):
1120 comb
+= dec_o2
.lk
.eq(do
.lk
)
1123 # now do the SVP64 munging. op.SV_Etype and op.sv_in1 comes from
1124 # PowerDecoder which in turn comes from LDST-RM*.csv and RM-*.csv
1125 # which in turn were auto-generated by sv_analysis.py
1126 extra
= self
.sv_rm
.extra
# SVP64 extra bits 10:18
1130 comb
+= crout_svdec
.idx
.eq(op
.sv_cr_out
) # SVP64 CR out
1131 comb
+= self
.cr_out_isvec
.eq(crout_svdec
.isvec
)
1134 # CR in - selection slightly different due to shared CR field sigh
1135 cr_a_idx
= Signal(SVEXTRA
)
1136 cr_b_idx
= Signal(SVEXTRA
)
1138 # these change slightly, when decoding BA/BB. really should have
1139 # their own separate CSV column: sv_cr_in1 and sv_cr_in2, but hey
1140 comb
+= cr_a_idx
.eq(op
.sv_cr_in
)
1141 comb
+= cr_b_idx
.eq(SVEXTRA
.NONE
)
1142 with m
.If(op
.sv_cr_in
== SVEXTRA
.Idx_1_2
.value
):
1143 comb
+= cr_a_idx
.eq(SVEXTRA
.Idx1
)
1144 comb
+= cr_b_idx
.eq(SVEXTRA
.Idx2
)
1146 comb
+= self
.cr_in_isvec
.eq(crin_svdec
.isvec
)
1147 comb
+= self
.cr_in_b_isvec
.eq(crin_svdec_b
.isvec
)
1148 comb
+= self
.cr_in_o_isvec
.eq(crin_svdec_o
.isvec
)
1150 # indices are slightly different, BA/BB mess sorted above
1151 comb
+= crin_svdec
.idx
.eq(cr_a_idx
) # SVP64 CR in A
1152 comb
+= crin_svdec_b
.idx
.eq(cr_b_idx
) # SVP64 CR in B
1153 comb
+= crin_svdec_o
.idx
.eq(op
.sv_cr_out
) # SVP64 CR out
1155 # get SVSTATE srcstep (TODO: elwidth etc.) needed below
1156 vl
= Signal
.like(self
.state
.svstate
.vl
)
1157 srcstep
= Signal
.like(self
.state
.svstate
.srcstep
)
1158 dststep
= Signal
.like(self
.state
.svstate
.dststep
)
1159 comb
+= vl
.eq(self
.state
.svstate
.vl
)
1160 comb
+= srcstep
.eq(self
.state
.svstate
.srcstep
)
1161 comb
+= dststep
.eq(self
.state
.svstate
.dststep
)
1163 # registers a, b, c and out and out2 (LD/ST EA)
1164 for to_reg
, fromreg
, svdec
, out
in (
1165 (e
.read_reg1
, dec_a
.reg_out
, in1_svdec
, False),
1166 (e
.read_reg2
, dec_b
.reg_out
, in2_svdec
, False),
1167 (e
.read_reg3
, dec_c
.reg_out
, in3_svdec
, False),
1168 (e
.write_reg
, dec_o
.reg_out
, o_svdec
, True),
1169 (e
.write_ea
, dec_o2
.reg_out
, o2_svdec
, True)):
1170 comb
+= svdec
.extra
.eq(extra
) # EXTRA field of SVP64 RM
1171 comb
+= svdec
.etype
.eq(op
.SV_Etype
) # EXTRA2/3 for this insn
1172 comb
+= svdec
.reg_in
.eq(fromreg
.data
) # 3-bit (CR0/BC/BFA)
1173 comb
+= to_reg
.ok
.eq(fromreg
.ok
)
1174 # detect if Vectorised: add srcstep/dststep if yes.
1175 # to_reg is 7-bits, outs get dststep added, ins get srcstep
1176 with m
.If(svdec
.isvec
):
1177 step
= dststep
if out
else srcstep
1178 # reverse gear goes the opposite way
1179 with m
.If(self
.rm_dec
.reverse_gear
):
1180 comb
+= to_reg
.data
.eq(svdec
.reg_out
+(vl
-1-step
))
1182 comb
+= to_reg
.data
.eq(step
+svdec
.reg_out
)
1184 comb
+= to_reg
.data
.eq(svdec
.reg_out
)
1186 comb
+= in1_svdec
.idx
.eq(op
.sv_in1
) # SVP64 reg #1 (in1_sel)
1187 comb
+= in2_svdec
.idx
.eq(op
.sv_in2
) # SVP64 reg #2 (in2_sel)
1188 comb
+= in3_svdec
.idx
.eq(op
.sv_in3
) # SVP64 reg #3 (in3_sel)
1189 comb
+= o_svdec
.idx
.eq(op
.sv_out
) # SVP64 output (out_sel)
1190 comb
+= o2_svdec
.idx
.eq(op
.sv_out2
) # SVP64 output (implicit)
1191 # XXX TODO - work out where this should come from. the problem is
1192 # that LD-with-update is implied (computed from "is instruction in
1193 # "update mode" rather than specified cleanly as its own CSV column
1195 # output reg-is-vectorised (and when no in/out is vectorised)
1196 comb
+= self
.in1_isvec
.eq(in1_svdec
.isvec
)
1197 comb
+= self
.in2_isvec
.eq(in2_svdec
.isvec
)
1198 comb
+= self
.in3_isvec
.eq(in3_svdec
.isvec
)
1199 comb
+= self
.o_isvec
.eq(o_svdec
.isvec
)
1200 comb
+= self
.o2_isvec
.eq(o2_svdec
.isvec
)
1201 # TODO add SPRs here. must be True when *all* are scalar
1202 l
= map(lambda svdec
: svdec
.isvec
, [in1_svdec
, in2_svdec
, in3_svdec
,
1203 crin_svdec
, crin_svdec_b
, crin_svdec_o
])
1204 comb
+= self
.no_in_vec
.eq(~
Cat(*l
).bool()) # all input scalar
1205 l
= map(lambda svdec
: svdec
.isvec
, [o2_svdec
, o_svdec
, crout_svdec
])
1206 # in mapreduce mode, scalar out is *allowed*
1207 with m
.If(self
.rm_dec
.mode
== SVP64RMMode
.MAPREDUCE
.value
):
1208 comb
+= self
.no_out_vec
.eq(0)
1210 comb
+= self
.no_out_vec
.eq(~
Cat(*l
).bool()) # all output scalar
1211 # now create a general-purpose "test" as to whether looping
1212 # should continue. this doesn't include predication bit-tests
1213 loop
= self
.loop_continue
1214 with m
.Switch(op
.SV_Ptype
):
1215 with m
.Case(SVPtype
.P2
.value
):
1217 # TODO: *and cache-inhibited LD/ST!*
1218 comb
+= loop
.eq(~
(self
.no_in_vec | self
.no_out_vec
))
1219 with m
.Case(SVPtype
.P1
.value
):
1220 # single-predication, test relies on dest only
1221 comb
+= loop
.eq(~self
.no_out_vec
)
1223 # not an SV operation, no looping
1226 # condition registers (CR)
1227 for to_reg
, cr
, name
, svdec
, out
in (
1228 (e
.read_cr1
, self
.dec_cr_in
, "cr_bitfield", crin_svdec
, 0),
1229 (e
.read_cr2
, self
.dec_cr_in
, "cr_bitfield_b", crin_svdec_b
, 0),
1230 (e
.read_cr3
, self
.dec_cr_in
, "cr_bitfield_o", crin_svdec_o
, 0),
1231 (e
.write_cr
, self
.dec_cr_out
, "cr_bitfield", crout_svdec
, 1)):
1232 fromreg
= getattr(cr
, name
)
1233 comb
+= svdec
.extra
.eq(extra
) # EXTRA field of SVP64 RM
1234 comb
+= svdec
.etype
.eq(op
.SV_Etype
) # EXTRA2/3 for this insn
1235 comb
+= svdec
.cr_in
.eq(fromreg
.data
) # 3-bit (CR0/BC/BFA)
1236 with m
.If(svdec
.isvec
):
1237 # check if this is CR0 or CR1: treated differently
1238 # (does not "listen" to EXTRA2/3 spec for a start)
1239 # also: the CRs start from completely different locations
1240 step
= dststep
if out
else srcstep
1241 with m
.If(cr
.sv_override
== 1): # CR0
1242 offs
= SVP64CROffs
.CR0
1243 comb
+= to_reg
.data
.eq(step
+offs
)
1244 with m
.Elif(cr
.sv_override
== 2): # CR1
1245 offs
= SVP64CROffs
.CR1
1246 comb
+= to_reg
.data
.eq(step
+1)
1248 comb
+= to_reg
.data
.eq(step
+svdec
.cr_out
) # 7-bit out
1250 comb
+= to_reg
.data
.eq(svdec
.cr_out
) # 7-bit output
1251 comb
+= to_reg
.ok
.eq(fromreg
.ok
)
1253 # sigh must determine if RA is nonzero (7 bit)
1254 comb
+= self
.sv_a_nz
.eq(e
.read_reg1
.data
!= Const(0, 7))
1256 # connect up to/from read/write GPRs
1257 for to_reg
, fromreg
in ((e
.read_reg1
, dec_a
.reg_out
),
1258 (e
.read_reg2
, dec_b
.reg_out
),
1259 (e
.read_reg3
, dec_c
.reg_out
),
1260 (e
.write_reg
, dec_o
.reg_out
),
1261 (e
.write_ea
, dec_o2
.reg_out
)):
1262 comb
+= to_reg
.data
.eq(fromreg
.data
)
1263 comb
+= to_reg
.ok
.eq(fromreg
.ok
)
1265 # connect up to/from read/write CRs
1266 for to_reg
, cr
, name
in (
1267 (e
.read_cr1
, self
.dec_cr_in
, "cr_bitfield", ),
1268 (e
.read_cr2
, self
.dec_cr_in
, "cr_bitfield_b", ),
1269 (e
.read_cr3
, self
.dec_cr_in
, "cr_bitfield_o", ),
1270 (e
.write_cr
, self
.dec_cr_out
, "cr_bitfield", )):
1271 fromreg
= getattr(cr
, name
)
1272 comb
+= to_reg
.data
.eq(fromreg
.data
)
1273 comb
+= to_reg
.ok
.eq(fromreg
.ok
)
1276 comb
+= self
.rm_dec
.ldst_ra_vec
.eq(self
.in1_isvec
) # RA is vector
1279 comb
+= e
.read_spr1
.eq(dec_a
.spr_out
)
1280 comb
+= e
.write_spr
.eq(dec_o
.spr_out
)
1282 # Fast regs out including SRR0/1/SVSRR0
1283 comb
+= e
.read_fast1
.eq(dec_a
.fast_out
)
1284 comb
+= e
.read_fast2
.eq(dec_b
.fast_out
)
1285 comb
+= e
.write_fast1
.eq(dec_o
.fast_out
) # SRR0 (OP_RFID)
1286 comb
+= e
.write_fast2
.eq(dec_o2
.fast_out
) # SRR1 (ditto)
1287 comb
+= e
.write_fast3
.eq(dec_o2
.fast_out3
) # SVSRR0 (ditto)
1289 # sigh this is exactly the sort of thing for which the
1290 # decoder is designed to not need. MTSPR, MFSPR and others need
1291 # access to the XER bits. however setting e.oe is not appropriate
1292 with m
.If(op
.internal_op
== MicrOp
.OP_MFSPR
):
1293 comb
+= e
.xer_in
.eq(0b111) # SO, CA, OV
1294 with m
.If(op
.internal_op
== MicrOp
.OP_CMP
):
1295 comb
+= e
.xer_in
.eq(1<<XERRegsEnum
.SO
) # SO
1296 with m
.If(op
.internal_op
== MicrOp
.OP_MTSPR
):
1297 comb
+= e
.xer_out
.eq(1)
1299 # set the trapaddr to 0x700 for a td/tw/tdi/twi operation
1300 with m
.If(op
.internal_op
== MicrOp
.OP_TRAP
):
1301 # *DO NOT* call self.trap here. that would reset absolutely
1302 # everything including destroying read of RA and RB.
1303 comb
+= self
.do_copy("trapaddr", 0x70) # strip first nibble
1305 ####################
1306 # ok so the instruction's been decoded, blah blah, however
1307 # now we need to determine if it's actually going to go ahead...
1308 # *or* if in fact it's a privileged operation, whether there's
1309 # an external interrupt, etc. etc. this is a simple priority
1310 # if-elif-elif sequence. decrement takes highest priority,
1311 # EINT next highest, privileged operation third.
1313 # check if instruction is privileged
1314 is_priv_insn
= instr_is_priv(m
, op
.internal_op
, e
.do
.insn
)
1316 # different IRQ conditions
1317 ext_irq_ok
= Signal()
1318 dec_irq_ok
= Signal()
1321 ldst_exc
= self
.ldst_exc
1323 comb
+= ext_irq_ok
.eq(ext_irq
& msr
[MSR
.EE
]) # v3.0B p944 (MSR.EE)
1324 comb
+= dec_irq_ok
.eq(dec_spr
[63] & msr
[MSR
.EE
]) # 6.5.11 p1076
1325 comb
+= priv_ok
.eq(is_priv_insn
& msr
[MSR
.PR
])
1326 comb
+= illeg_ok
.eq(op
.internal_op
== MicrOp
.OP_ILLEGAL
)
1328 # LD/ST exceptions. TestIssuer copies the exception info at us
1329 # after a failed LD/ST.
1330 with m
.If(ldst_exc
.happened
):
1331 with m
.If(ldst_exc
.alignment
):
1332 self
.trap(m
, TT
.PRIV
, 0x600)
1333 with m
.Elif(ldst_exc
.instr_fault
):
1334 with m
.If(ldst_exc
.segment_fault
):
1335 self
.trap(m
, TT
.PRIV
, 0x480)
1337 # pass exception info to trap to create SRR1
1338 self
.trap(m
, TT
.MEMEXC
, 0x400, ldst_exc
)
1340 with m
.If(ldst_exc
.segment_fault
):
1341 self
.trap(m
, TT
.PRIV
, 0x380)
1343 self
.trap(m
, TT
.PRIV
, 0x300)
1345 # decrement counter (v3.0B p1099): TODO 32-bit version (MSR.LPCR)
1346 with m
.Elif(dec_irq_ok
):
1347 self
.trap(m
, TT
.DEC
, 0x900) # v3.0B 6.5 p1065
1349 # external interrupt? only if MSR.EE set
1350 with m
.Elif(ext_irq_ok
):
1351 self
.trap(m
, TT
.EINT
, 0x500)
1353 # privileged instruction trap
1354 with m
.Elif(priv_ok
):
1355 self
.trap(m
, TT
.PRIV
, 0x700)
1357 # illegal instruction must redirect to trap. this is done by
1358 # *overwriting* the decoded instruction and starting again.
1359 # (note: the same goes for interrupts and for privileged operations,
1360 # just with different trapaddr and traptype)
1361 with m
.Elif(illeg_ok
):
1362 # illegal instruction trap
1363 self
.trap(m
, TT
.ILLEG
, 0x700)
1365 # no exception, just copy things to the output
1369 ####################
1370 # follow-up after trap/irq to set up SRR0/1
1372 # trap: (note e.insn_type so this includes OP_ILLEGAL) set up fast regs
1373 # Note: OP_SC could actually be modified to just be a trap
1374 with m
.If((do_out
.insn_type
== MicrOp
.OP_TRAP
) |
1375 (do_out
.insn_type
== MicrOp
.OP_SC
)):
1376 # TRAP write fast1 = SRR0
1377 comb
+= e_out
.write_fast1
.data
.eq(FastRegsEnum
.SRR0
) # SRR0
1378 comb
+= e_out
.write_fast1
.ok
.eq(1)
1379 # TRAP write fast2 = SRR1
1380 comb
+= e_out
.write_fast2
.data
.eq(FastRegsEnum
.SRR1
) # SRR1
1381 comb
+= e_out
.write_fast2
.ok
.eq(1)
1382 # TRAP write fast2 = SRR1
1383 comb
+= e_out
.write_fast3
.data
.eq(FastRegsEnum
.SVSRR0
) # SVSRR0
1384 comb
+= e_out
.write_fast3
.ok
.eq(1)
1386 # RFID: needs to read SRR0/1
1387 with m
.If(do_out
.insn_type
== MicrOp
.OP_RFID
):
1388 # TRAP read fast1 = SRR0
1389 comb
+= e_out
.read_fast1
.data
.eq(FastRegsEnum
.SRR0
) # SRR0
1390 comb
+= e_out
.read_fast1
.ok
.eq(1)
1391 # TRAP read fast2 = SRR1
1392 comb
+= e_out
.read_fast2
.data
.eq(FastRegsEnum
.SRR1
) # SRR1
1393 comb
+= e_out
.read_fast2
.ok
.eq(1)
1394 # TRAP read fast2 = SVSRR0
1395 comb
+= e_out
.read_fast3
.data
.eq(FastRegsEnum
.SVSRR0
) # SVSRR0
1396 comb
+= e_out
.read_fast3
.ok
.eq(1)
1398 # annoying simulator bug
1399 if hasattr(e_out
, "asmcode") and hasattr(self
.dec
.op
, "asmcode"):
1400 comb
+= e_out
.asmcode
.eq(self
.dec
.op
.asmcode
)
1404 def trap(self
, m
, traptype
, trapaddr
, ldst_exc
=None):
1405 """trap: this basically "rewrites" the decoded instruction as a trap
1408 op
, e
= self
.dec
.op
, self
.e
1409 comb
+= e
.eq(0) # reset eeeeeverything
1412 comb
+= self
.do_copy("insn", self
.dec
.opcode_in
, True)
1413 comb
+= self
.do_copy("insn_type", MicrOp
.OP_TRAP
, True)
1414 comb
+= self
.do_copy("fn_unit", Function
.TRAP
, True)
1415 comb
+= self
.do_copy("trapaddr", trapaddr
>> 4, True) # bottom 4 bits
1416 comb
+= self
.do_copy("traptype", traptype
, True) # request type
1417 comb
+= self
.do_copy("ldst_exc", ldst_exc
, True) # request type
1418 comb
+= self
.do_copy("msr", self
.state
.msr
, True) # copy of MSR "state"
1419 comb
+= self
.do_copy("cia", self
.state
.pc
, True) # copy of PC "state"
1420 comb
+= self
.do_copy("svstate", self
.state
.svstate
, True) # SVSTATE
1424 def get_rdflags(e
, cu
):
1426 for idx
in range(cu
.n_src
):
1427 regfile
, regname
, _
= cu
.get_in_spec(idx
)
1428 rdflag
, read
= regspec_decode_read(e
, regfile
, regname
)
1434 if __name__
== '__main__':
1435 pdecode
= create_pdecode()
1436 dec2
= PowerDecode2(pdecode
)
1437 vl
= rtlil
.convert(dec2
, ports
=dec2
.ports() + pdecode
.ports())
1438 with
open("dec2.il", "w") as f
: