1 """Power ISA Decoder second stage
3 based on Anton Blanchard microwatt decode2.vhdl
6 from nmigen
import Module
, Elaboratable
, Signal
, Mux
, Const
, Cat
, Repl
, Record
7 from nmigen
.cli
import rtlil
9 from nmutil
.iocontrol
import RecordObject
10 from nmutil
.extend
import exts
12 from soc
.decoder
.power_decoder
import create_pdecode
13 from soc
.decoder
.power_enums
import (InternalOp
, CryIn
, Function
,
14 LdstLen
, In1Sel
, In2Sel
, In3Sel
,
18 class DecodeA(Elaboratable
):
19 """DecodeA from instruction
21 decodes register RA, whether immediate-zero, implicit and
25 def __init__(self
, dec
):
27 self
.sel_in
= Signal(In1Sel
, reset_less
=True)
28 self
.insn_in
= Signal(32, reset_less
=True)
29 self
.reg_out
= Data(5, name
="reg_a")
30 self
.immz_out
= Signal(reset_less
=True)
31 self
.spr_out
= Data(10, "spr_a")
33 def elaborate(self
, platform
):
37 # select Register A field
38 ra
= Signal(5, reset_less
=True)
39 comb
+= ra
.eq(self
.dec
.RA
)
40 with m
.If((self
.sel_in
== In1Sel
.RA
) |
41 ((self
.sel_in
== In1Sel
.RA_OR_ZERO
) &
42 (ra
!= Const(0, 5)))):
43 comb
+= self
.reg_out
.data
.eq(ra
)
44 comb
+= self
.reg_out
.ok
.eq(1)
46 # zero immediate requested
47 with m
.If((self
.sel_in
== In1Sel
.RA_OR_ZERO
) &
48 (self
.reg_out
.data
== Const(0, 5))):
49 comb
+= self
.immz_out
.eq(1)
51 # decode SPR1 based on instruction type
53 # BC or BCREG: potential implicit register (CTR)
54 with m
.If((op
.internal_op
== InternalOp
.OP_BC
) |
55 (op
.internal_op
== InternalOp
.OP_BCREG
)):
56 with m
.If(~self
.dec
.BO
[2]): # 3.0B p38 BO2=0, use CTR reg
57 comb
+= self
.spr_out
.data
.eq(SPR
.CTR
) # constant: CTR
58 comb
+= self
.spr_out
.ok
.eq(1)
59 # MFSPR or MTSPR: move-from / move-to SPRs
60 with m
.If((op
.internal_op
== InternalOp
.OP_MFSPR
) |
61 (op
.internal_op
== InternalOp
.OP_MTSPR
)):
62 comb
+= self
.spr_out
.data
.eq(self
.dec
.SPR
) # SPR field, XFX
63 comb
+= self
.spr_out
.ok
.eq(1)
70 def __init__(self
, width
, name
):
71 name_ok
= "%s_ok" % name
72 layout
= ((name
, width
), (name_ok
, 1))
73 Record
.__init
__(self
, layout
)
74 self
.data
= getattr(self
, name
) # convenience
75 self
.ok
= getattr(self
, name_ok
) # convenience
76 self
.data
.reset_less
= True # grrr
77 self
.reset_less
= True # grrr
80 return [self
.data
, self
.ok
]
83 class DecodeB(Elaboratable
):
84 """DecodeB from instruction
86 decodes register RB, different forms of immediate (signed, unsigned),
90 def __init__(self
, dec
):
92 self
.sel_in
= Signal(In2Sel
, reset_less
=True)
93 self
.insn_in
= Signal(32, reset_less
=True)
94 self
.reg_out
= Data(5, "reg_b")
95 self
.imm_out
= Data(64, "imm_b")
96 self
.spr_out
= Data(10, "spr_b")
98 def elaborate(self
, platform
):
102 # select Register B field
103 with m
.Switch(self
.sel_in
):
104 with m
.Case(In2Sel
.RB
):
105 comb
+= self
.reg_out
.data
.eq(self
.dec
.RB
)
106 comb
+= self
.reg_out
.ok
.eq(1)
107 with m
.Case(In2Sel
.CONST_UI
):
108 comb
+= self
.imm_out
.data
.eq(self
.dec
.UI
)
109 comb
+= self
.imm_out
.ok
.eq(1)
110 with m
.Case(In2Sel
.CONST_SI
): # TODO: sign-extend here?
111 comb
+= self
.imm_out
.data
.eq(
112 exts(self
.dec
.SI
, 16, 64))
113 comb
+= self
.imm_out
.ok
.eq(1)
114 with m
.Case(In2Sel
.CONST_UI_HI
):
115 comb
+= self
.imm_out
.data
.eq(self
.dec
.UI
<<16)
116 comb
+= self
.imm_out
.ok
.eq(1)
117 with m
.Case(In2Sel
.CONST_SI_HI
): # TODO: sign-extend here?
118 comb
+= self
.imm_out
.data
.eq(self
.dec
.SI
<<16)
119 comb
+= self
.imm_out
.data
.eq(
120 exts(self
.dec
.SI
<< 16, 32, 64))
121 comb
+= self
.imm_out
.ok
.eq(1)
122 with m
.Case(In2Sel
.CONST_LI
):
123 comb
+= self
.imm_out
.data
.eq(self
.dec
.LI
<<2)
124 comb
+= self
.imm_out
.ok
.eq(1)
125 with m
.Case(In2Sel
.CONST_BD
):
126 comb
+= self
.imm_out
.data
.eq(self
.dec
.BD
<<2)
127 comb
+= self
.imm_out
.ok
.eq(1)
128 with m
.Case(In2Sel
.CONST_DS
):
129 comb
+= self
.imm_out
.data
.eq(self
.dec
.DS
<<2)
130 comb
+= self
.imm_out
.ok
.eq(1)
131 with m
.Case(In2Sel
.CONST_M1
):
132 comb
+= self
.imm_out
.data
.eq(~
Const(0, 64)) # all 1s
133 comb
+= self
.imm_out
.ok
.eq(1)
134 with m
.Case(In2Sel
.CONST_SH
):
135 comb
+= self
.imm_out
.data
.eq(self
.dec
.sh
)
136 comb
+= self
.imm_out
.ok
.eq(1)
137 with m
.Case(In2Sel
.CONST_SH32
):
138 comb
+= self
.imm_out
.data
.eq(self
.dec
.SH32
)
139 comb
+= self
.imm_out
.ok
.eq(1)
141 # decode SPR2 based on instruction type
143 # BCREG implicitly uses CTR or LR for 2nd reg
144 with m
.If(op
.internal_op
== InternalOp
.OP_BCREG
):
145 with m
.If(self
.dec
.FormXL
.XO
[9]): # 3.0B p38 top bit of XO
146 comb
+= self
.spr_out
.data
.eq(SPR
.CTR
)
148 comb
+= self
.spr_out
.data
.eq(SPR
.LR
)
149 comb
+= self
.spr_out
.ok
.eq(1)
154 class DecodeC(Elaboratable
):
155 """DecodeC from instruction
160 def __init__(self
, dec
):
162 self
.sel_in
= Signal(In3Sel
, reset_less
=True)
163 self
.insn_in
= Signal(32, reset_less
=True)
164 self
.reg_out
= Data(5, "reg_c")
166 def elaborate(self
, platform
):
170 # select Register C field
171 with m
.If(self
.sel_in
== In3Sel
.RS
):
172 comb
+= self
.reg_out
.data
.eq(self
.dec
.RS
)
173 comb
+= self
.reg_out
.ok
.eq(1)
178 class DecodeOut(Elaboratable
):
179 """DecodeOut from instruction
181 decodes output register RA, RT or SPR
184 def __init__(self
, dec
):
186 self
.sel_in
= Signal(OutSel
, reset_less
=True)
187 self
.insn_in
= Signal(32, reset_less
=True)
188 self
.reg_out
= Data(5, "reg_o")
189 self
.spr_out
= Data(10, "spr_o")
191 def elaborate(self
, platform
):
195 # select Register out field
196 with m
.Switch(self
.sel_in
):
197 with m
.Case(OutSel
.RT
):
198 comb
+= self
.reg_out
.data
.eq(self
.dec
.RT
)
199 comb
+= self
.reg_out
.ok
.eq(1)
200 with m
.Case(OutSel
.RA
):
201 comb
+= self
.reg_out
.data
.eq(self
.dec
.RA
)
202 comb
+= self
.reg_out
.ok
.eq(1)
203 with m
.Case(OutSel
.SPR
):
204 comb
+= self
.spr_out
.data
.eq(self
.dec
.SPR
) # from XFX
205 comb
+= self
.spr_out
.ok
.eq(1)
210 class DecodeRC(Elaboratable
):
211 """DecodeRc from instruction
213 decodes Record bit Rc
215 def __init__(self
, dec
):
217 self
.sel_in
= Signal(RC
, reset_less
=True)
218 self
.insn_in
= Signal(32, reset_less
=True)
219 self
.rc_out
= Data(1, "rc")
221 def elaborate(self
, platform
):
225 # select Record bit out field
226 with m
.Switch(self
.sel_in
):
228 comb
+= self
.rc_out
.data
.eq(self
.dec
.Rc
)
229 comb
+= self
.rc_out
.ok
.eq(1)
231 comb
+= self
.rc_out
.data
.eq(1)
232 comb
+= self
.rc_out
.ok
.eq(1)
233 with m
.Case(RC
.NONE
):
234 comb
+= self
.rc_out
.data
.eq(0)
235 comb
+= self
.rc_out
.ok
.eq(1)
240 class DecodeOE(Elaboratable
):
241 """DecodeOE from instruction
243 decodes OE field: uses RC decode detection which might not be good
245 -- For now, use "rc" in the decode table to decide whether oe exists.
246 -- This is not entirely correct architecturally: For mulhd and
247 -- mulhdu, the OE field is reserved. It remains to be seen what an
248 -- actual POWER9 does if we set it on those instructions, for now we
249 -- test that further down when assigning to the multiplier oe input.
251 def __init__(self
, dec
):
253 self
.sel_in
= Signal(RC
, reset_less
=True)
254 self
.insn_in
= Signal(32, reset_less
=True)
255 self
.oe_out
= Data(1, "oe")
257 def elaborate(self
, platform
):
261 # select OE bit out field
262 with m
.Switch(self
.sel_in
):
264 comb
+= self
.oe_out
.data
.eq(self
.dec
.OE
)
265 comb
+= self
.oe_out
.ok
.eq(1)
272 self
.ca
= Signal(reset_less
=True)
273 self
.ca32
= Signal(reset_less
=True)
274 self
.ov
= Signal(reset_less
=True)
275 self
.ov32
= Signal(reset_less
=True)
276 self
.so
= Signal(reset_less
=True)
279 return [self
.ca
, self
.ca32
, self
.ov
, self
.ov32
, self
.so
, ]
282 class Decode2ToExecute1Type(RecordObject
):
284 def __init__(self
, name
=None):
286 RecordObject
.__init
__(self
, name
=name
)
288 self
.valid
= Signal(reset_less
=True)
289 self
.insn_type
= Signal(InternalOp
, reset_less
=True)
290 self
.fn_unit
= Signal(Function
, reset_less
=True)
291 self
.nia
= Signal(64, reset_less
=True)
292 self
.write_reg
= Data(5, name
="rego")
293 self
.read_reg1
= Data(5, name
="reg1")
294 self
.read_reg2
= Data(5, name
="reg2")
295 self
.read_reg3
= Data(5, name
="reg3")
296 self
.imm_data
= Data(64, name
="imm")
297 self
.write_spr
= Data(10, name
="spro")
298 self
.read_spr1
= Data(10, name
="spr1")
299 self
.read_spr2
= Data(10, name
="spr2")
300 #self.read_data1 = Signal(64, reset_less=True)
301 #self.read_data2 = Signal(64, reset_less=True)
302 #self.read_data3 = Signal(64, reset_less=True)
303 #self.cr = Signal(32, reset_less=True) # NO: this is from the CR SPR
304 #self.xerc = XerBits() # NO: this is from the XER SPR
305 self
.lk
= Signal(reset_less
=True)
306 self
.rc
= Data(1, "rc")
307 self
.oe
= Data(1, "oe")
308 self
.invert_a
= Signal(reset_less
=True)
309 self
.invert_out
= Signal(reset_less
=True)
310 self
.input_carry
= Signal(CryIn
, reset_less
=True)
311 self
.output_carry
= Signal(reset_less
=True)
312 self
.input_cr
= Signal(reset_less
=True)
313 self
.output_cr
= Signal(reset_less
=True)
314 self
.is_32bit
= Signal(reset_less
=True)
315 self
.is_signed
= Signal(reset_less
=True)
316 self
.insn
= Signal(32, reset_less
=True)
317 self
.data_len
= Signal(4, reset_less
=True) # bytes
318 self
.byte_reverse
= Signal(reset_less
=True)
319 self
.sign_extend
= Signal(reset_less
=True)# do we need this?
320 self
.update
= Signal(reset_less
=True) # LD/ST is "update" variant
323 class PowerDecode2(Elaboratable
):
325 def __init__(self
, dec
):
328 self
.e
= Decode2ToExecute1Type()
331 return self
.dec
.ports() + self
.e
.ports()
333 def elaborate(self
, platform
):
337 # set up submodule decoders
338 m
.submodules
.dec
= self
.dec
339 m
.submodules
.dec_a
= dec_a
= DecodeA(self
.dec
)
340 m
.submodules
.dec_b
= dec_b
= DecodeB(self
.dec
)
341 m
.submodules
.dec_c
= dec_c
= DecodeC(self
.dec
)
342 m
.submodules
.dec_o
= dec_o
= DecodeOut(self
.dec
)
343 m
.submodules
.dec_rc
= dec_rc
= DecodeRC(self
.dec
)
344 m
.submodules
.dec_oe
= dec_oe
= DecodeOE(self
.dec
)
346 # copy instruction through...
347 for i
in [self
.e
.insn
, dec_a
.insn_in
, dec_b
.insn_in
,
348 dec_c
.insn_in
, dec_o
.insn_in
, dec_rc
.insn_in
,
350 comb
+= i
.eq(self
.dec
.opcode_in
)
352 # ...and subdecoders' input fields
353 comb
+= dec_a
.sel_in
.eq(self
.dec
.op
.in1_sel
)
354 comb
+= dec_b
.sel_in
.eq(self
.dec
.op
.in2_sel
)
355 comb
+= dec_c
.sel_in
.eq(self
.dec
.op
.in3_sel
)
356 comb
+= dec_o
.sel_in
.eq(self
.dec
.op
.out_sel
)
357 comb
+= dec_rc
.sel_in
.eq(self
.dec
.op
.rc_sel
)
358 comb
+= dec_oe
.sel_in
.eq(self
.dec
.op
.rc_sel
) # XXX should be OE sel
360 # decode LD/ST length
361 with m
.Switch(self
.dec
.op
.ldst_len
):
362 with m
.Case(LdstLen
.is1B
):
363 comb
+= self
.e
.data_len
.eq(1)
364 with m
.Case(LdstLen
.is2B
):
365 comb
+= self
.e
.data_len
.eq(2)
366 with m
.Case(LdstLen
.is4B
):
367 comb
+= self
.e
.data_len
.eq(4)
368 with m
.Case(LdstLen
.is8B
):
369 comb
+= self
.e
.data_len
.eq(8)
371 comb
+= self
.e
.nia
.eq(0) # XXX TODO
372 comb
+= self
.e
.valid
.eq(0) # XXX TODO
373 fu
= self
.dec
.op
.function_unit
374 itype
= Mux(fu
== Function
.NONE
,
375 InternalOp
.OP_ILLEGAL
,
376 self
.dec
.op
.internal_op
)
377 comb
+= self
.e
.insn_type
.eq(itype
)
378 comb
+= self
.e
.fn_unit
.eq(fu
)
380 # registers a, b, c and out
381 comb
+= self
.e
.read_reg1
.eq(dec_a
.reg_out
)
382 comb
+= self
.e
.read_reg2
.eq(dec_b
.reg_out
)
383 comb
+= self
.e
.read_reg3
.eq(dec_c
.reg_out
)
384 comb
+= self
.e
.write_reg
.eq(dec_o
.reg_out
)
385 comb
+= self
.e
.imm_data
.eq(dec_b
.imm_out
)
388 comb
+= self
.e
.rc
.eq(dec_rc
.rc_out
)
389 comb
+= self
.e
.oe
.eq(dec_oe
.oe_out
)
392 comb
+= self
.e
.read_spr1
.eq(dec_a
.spr_out
)
393 comb
+= self
.e
.read_spr2
.eq(dec_b
.spr_out
)
394 comb
+= self
.e
.write_spr
.eq(dec_o
.spr_out
)
396 # decoded/selected instruction flags
397 comb
+= self
.e
.invert_a
.eq(self
.dec
.op
.inv_a
)
398 comb
+= self
.e
.invert_out
.eq(self
.dec
.op
.inv_out
)
399 comb
+= self
.e
.input_carry
.eq(self
.dec
.op
.cry_in
) # carry comes in
400 comb
+= self
.e
.output_carry
.eq(self
.dec
.op
.cry_out
) # carry goes out
401 comb
+= self
.e
.is_32bit
.eq(self
.dec
.op
.is_32b
)
402 comb
+= self
.e
.is_signed
.eq(self
.dec
.op
.sgn
)
403 with m
.If(self
.dec
.op
.lk
):
404 comb
+= self
.e
.lk
.eq(self
.dec
.LK
) # XXX TODO: accessor
406 comb
+= self
.e
.byte_reverse
.eq(self
.dec
.op
.br
)
407 comb
+= self
.e
.sign_extend
.eq(self
.dec
.op
.sgn_ext
)
408 comb
+= self
.e
.update
.eq(self
.dec
.op
.upd
) # LD/ST "update" mode
410 comb
+= self
.e
.input_cr
.eq(self
.dec
.op
.cr_in
) # condition reg comes in
411 comb
+= self
.e
.output_cr
.eq(self
.dec
.op
.cr_out
) # condition reg goes in
417 if __name__
== '__main__':
418 pdecode
= create_pdecode()
419 dec2
= PowerDecode2(pdecode
)
420 vl
= rtlil
.convert(dec2
, ports
=dec2
.ports() + pdecode
.ports())
421 with
open("dec2.il", "w") as f
: