3 Deals with td/tw/tdi/twi as well as mfmsr/mtmsr, sc and rfid. addpcis TODO.
4 Also used generally for interrupts (as a micro-coding mechanism) by
5 actually modifying the decoded instruction in PowerDecode2.
7 * https://bugs.libre-soc.org/show_bug.cgi?id=325
8 * https://bugs.libre-soc.org/show_bug.cgi?id=344
9 * https://libre-soc.org/openpower/isa/fixedtrap/
12 from nmigen
import (Module
, Signal
, Cat
, Mux
, Const
, signed
)
13 from nmutil
.pipemodbase
import PipeModBase
14 from nmutil
.extend
import exts
15 from soc
.fu
.trap
.pipe_data
import TrapInputData
, TrapOutputData
16 from soc
.fu
.branch
.main_stage
import br_ext
17 from openpower
.decoder
.power_enums
import MicrOp
18 from soc
.experiment
.mem_types
import LDSTException
20 from openpower
.decoder
.power_fields
import DecodeFields
21 from openpower
.decoder
.power_fieldsn
import SignalBitRange
23 from openpower
.consts
import MSR
, PI
, TT
, field
, field_slice
26 def msr_copy(msr_o
, msr_i
, zero_me
=True):
27 """msr_copy (also used to copy relevant bits into SRR1)
30 Defined MSR bits are classified as either full func tion or partial
31 function. Full function MSR bits are saved in SRR1 or HSRR1 when
32 an interrupt other than a System Call Vectored interrupt occurs and
33 restored by rfscv, rfid, or hrfid, while partial function MSR bits
34 are not saved or restored. Full function MSR bits lie in the range
35 0:32, 37:41, and 48:63, and partial function MSR bits lie in the
36 range 33:36 and 42:47. (Note this is IBM bit numbering).
41 for stt
, end
in [(0,16), (22, 27), (31, 64)]:
42 l
.append(msr_o
[stt
:end
].eq(msr_i
[stt
:end
]))
46 def msr_check_pr(m
, d_in
, msr
):
47 """msr_check_pr: checks "problem state"
50 with m
.If(d_in
[MSR
.PR
]):
51 comb
+= msr
[MSR
.EE
].eq(1) # set external interrupt bit
52 comb
+= msr
[MSR
.IR
].eq(1) # set instruction relocation bit
53 comb
+= msr
[MSR
.DR
].eq(1) # set data relocation bit
56 class TrapMainStage(PipeModBase
):
57 def __init__(self
, pspec
):
58 super().__init
__(pspec
, "main")
59 self
.fields
= DecodeFields(SignalBitRange
, [self
.i
.ctx
.op
.insn
])
60 self
.fields
.create_specs()
61 self
.kaivb
= Signal(64) # KAIVB SPR
62 self
.state_reset
= Signal() # raise high to reset KAIVB cache
64 def trap(self
, m
, trap_addr
, return_addr
):
65 """trap. sets new PC, stores MSR and old PC in SRR1 and SRR0
70 svstate_i
= op
.svstate
72 exc
= LDSTException("trapexc")
73 comb
+= exc
.eq(op
.ldst_exc
)
74 srr1_i
= exc
.srr1
# new SRR1 bits come from exception
76 svsrr0_o
, srr0_o
, srr1_o
= self
.o
.svsrr0
, self
.o
.srr0
, self
.o
.srr1
78 # trap address, including KAIVB override
79 comb
+= nia_o
.data
.eq(trap_addr
)
80 comb
+= nia_o
.data
[13:].eq(self
.kaivb
[13:])
81 comb
+= nia_o
.ok
.eq(1)
83 # addr to begin from on return
84 comb
+= srr0_o
.data
.eq(return_addr
)
85 comb
+= srr0_o
.ok
.eq(1)
87 # take a copy of the current MSR into SRR1, but first copy old SRR1
88 # this preserves the bits of SRR1 that are not supposed to change:
89 # MSR.IR,DR,PMM,RI,LE (0-5) and MR,FP,ME,FE0 (11-14)
90 # i would suggest reading v3.0C p1063 Book III section 7.2.1 for
91 # advice but it's so obscure and indirect, that it's just easier
92 # to copy microwatt behaviour. see writeback.vhdl
93 # IMPORTANT: PowerDecoder2 needed to actually read SRR1 for
94 # it to have the contents *of* SRR1 to copy over!
95 comb
+= msr_copy(srr1_o
.data
, msr_i
, False) # old MSR
96 comb
+= srr1_o
.data
[16:22].eq(srr1_i
[0:6]) # IR,DR,PMM,RI,LE
97 comb
+= srr1_o
.data
[27:31].eq(srr1_i
[11:15]) # MR,FP,ME,FE0
98 comb
+= srr1_o
.ok
.eq(1)
100 # take a copy of the current SVSTATE into SVSRR0
101 comb
+= svsrr0_o
.data
.eq(svstate_i
) # old SVSTATE
102 comb
+= svsrr0_o
.ok
.eq(1)
104 def msr_exception(self
, m
, trap_addr
, msr_hv
=None):
105 """msr_exception - sets bits in MSR specific to an exception.
106 the full list of what needs to be done is given in V3.0B
107 Book III Section 6.5 p1063 however it turns out that for the
108 majority of cases (microwatt showing the way, here), all these
109 bits are all set by all (implemented) interrupt types. this
110 may change in the future, hence the (unused) trap_addr argument
114 msr_i
, msr_o
= op
.msr
, self
.o
.msr
115 comb
+= msr_o
.data
.eq(msr_i
) # copy msr, first, then modify
116 comb
+= msr_o
.data
[MSR
.SF
].eq(1)
117 comb
+= msr_o
.data
[MSR
.EE
].eq(0)
118 comb
+= msr_o
.data
[MSR
.PR
].eq(0)
119 comb
+= msr_o
.data
[MSR
.IR
].eq(0)
120 comb
+= msr_o
.data
[MSR
.DR
].eq(0)
121 comb
+= msr_o
.data
[MSR
.RI
].eq(0)
122 comb
+= msr_o
.data
[MSR
.LE
].eq(1)
123 comb
+= msr_o
.data
[MSR
.FE0
].eq(0)
124 comb
+= msr_o
.data
[MSR
.FE1
].eq(0)
125 comb
+= msr_o
.data
[MSR
.VSX
].eq(0)
126 comb
+= msr_o
.data
[MSR
.TM
].eq(0)
127 comb
+= msr_o
.data
[MSR
.VEC
].eq(0)
128 comb
+= msr_o
.data
[MSR
.FP
].eq(0)
129 comb
+= msr_o
.data
[MSR
.PMM
].eq(0)
130 comb
+= msr_o
.data
[MSR
.TEs
].eq(0) # this is only 2 bits
131 comb
+= msr_o
.data
[MSR
.TEe
].eq(0) # so just zero them both
132 comb
+= msr_o
.data
[MSR
.UND
].eq(0)
133 if msr_hv
is not None:
134 comb
+= msr_o
.data
[MSR
.HV
].eq(msr_hv
)
135 comb
+= msr_o
.ok
.eq(1)
138 return TrapInputData(self
.pspec
)
141 return TrapOutputData(self
.pspec
)
143 def elaborate(self
, platform
):
145 comb
, sync
= m
.d
.comb
, m
.d
.sync
148 # convenience variables
149 a_i
, b_i
= self
.i
.a
, self
.i
.b
150 cia_i
, msr_i
, svstate_i
= op
.cia
, op
.msr
, op
.svstate
151 srr0_i
, srr1_i
, svsrr0_i
= self
.i
.srr0
, self
.i
.srr1
, self
.i
.svsrr0
153 msr_o
, nia_o
, svstate_o
= self
.o
.msr
, self
.o
.nia
, self
.o
.svstate
154 srr0_o
, srr1_o
, svsrr0_o
= self
.o
.srr0
, self
.o
.srr1
, self
.o
.svsrr0
155 traptype
, trapaddr
= op
.traptype
, op
.trapaddr
157 # hard reset of KAIVB
158 with m
.If(self
.state_reset
):
159 sync
+= self
.kaivb
.eq(0)
161 # take copy of D-Form TO field
162 i_fields
= self
.fields
.FormD
163 to
= Signal(i_fields
.TO
[0:-1].shape())
164 comb
+= to
.eq(i_fields
.TO
[0:-1])
166 # signed/unsigned temporaries for RA and RB
167 a_s
= Signal(signed(64), reset_less
=True)
168 b_s
= Signal(signed(64), reset_less
=True)
170 a
= Signal(64, reset_less
=True)
171 b
= Signal(64, reset_less
=True)
173 # set up A and B comparison (truncate/sign-extend if 32 bit)
174 with m
.If(op
.is_32bit
):
175 comb
+= a_s
.eq(exts(a_i
, 32, 64))
176 comb
+= b_s
.eq(exts(b_i
, 32, 64))
177 comb
+= a
.eq(a_i
[0:32])
178 comb
+= b
.eq(b_i
[0:32])
185 # establish comparison bits
186 lt_s
= Signal(reset_less
=True)
187 gt_s
= Signal(reset_less
=True)
188 lt_u
= Signal(reset_less
=True)
189 gt_u
= Signal(reset_less
=True)
190 equal
= Signal(reset_less
=True)
192 comb
+= lt_s
.eq(a_s
< b_s
)
193 comb
+= gt_s
.eq(a_s
> b_s
)
194 comb
+= lt_u
.eq(a
< b
)
195 comb
+= gt_u
.eq(a
> b
)
196 comb
+= equal
.eq(a
== b
)
198 # They're in reverse bit order because POWER.
199 # Check V3.0B Book 1, Appendix C.6 for chart
200 trap_bits
= Signal(5, reset_less
=True)
201 comb
+= trap_bits
.eq(Cat(gt_u
, lt_u
, equal
, gt_s
, lt_s
))
203 # establish if the trap should go ahead (any tests requested in TO)
204 # or if traptype is set already
205 should_trap
= Signal(reset_less
=True)
206 comb
+= should_trap
.eq((trap_bits
& to
).any() | traptype
.any())
208 # TODO: some #defines for the bits n stuff.
209 with m
.Switch(op
.insn_type
):
212 # KAIVB https://bugs.libre-soc.org/show_bug.cgi?id=859
214 with m
.Case(MicrOp
.OP_MTSPR
):
215 sync
+= self
.kaivb
.eq(a_i
)
217 with m
.Case(MicrOp
.OP_MFSPR
):
218 comb
+= o
.data
.eq(self
.kaivb
)
222 # TDI/TWI/TD/TW. v3.0B p90-91
224 with m
.Case(MicrOp
.OP_TRAP
):
225 # trap instructions (tw, twi, td, tdi)
226 with m
.If(should_trap
):
227 # generate trap-type program interrupt
228 self
.trap(m
, trapaddr
<<4, cia_i
)
229 with m
.If(traptype
== 0):
230 # say trap occurred (see 3.0B Book III 6.5.9 p1074-6)
231 comb
+= srr1_o
.data
[PI
.TRAP
].eq(1)
232 with m
.If(traptype
& TT
.PRIV
):
233 comb
+= srr1_o
.data
[PI
.PRIV
].eq(1)
234 with m
.If(traptype
& TT
.FP
):
235 comb
+= srr1_o
.data
[PI
.FP
].eq(1)
236 with m
.If(traptype
& TT
.ADDR
):
237 comb
+= srr1_o
.data
[PI
.ADR
].eq(1)
238 with m
.If((traptype
& TT
.MEMEXC
).bool() &
239 (trapaddr
== 0x400)):
240 # Instruction Storage Interrupt (ISI - 0x400)
241 # v3.0C Book III Chap 7.5.5 p1085
242 # decode exception bits, store in SRR1
243 exc
= LDSTException("trapexc")
244 comb
+= exc
.eq(op
.ldst_exc
)
245 comb
+= srr1_o
.data
[PI
.INVALID
].eq(exc
.invalid
)
246 comb
+= srr1_o
.data
[PI
.PERMERR
].eq(exc
.perm_error
)
247 comb
+= srr1_o
.data
[PI
.ILLEG
].eq(exc
.badtree
)
248 comb
+= srr1_o
.data
[PI
.PRIV
].eq(exc
.rc_error
)
249 with m
.If(traptype
& TT
.EINT
):
250 # do nothing unusual? see 3.0B Book III 6.5.7 p1073
252 with m
.If(traptype
& TT
.DEC
):
253 # do nothing unusual?
255 with m
.If(traptype
& TT
.ILLEG
):
256 comb
+= srr1_o
.data
[PI
.ILLEG
].eq(1)
257 comb
+= srr1_o
.ok
.eq(1)
259 # when SRR1 is written to, update MSR bits
260 self
.msr_exception(m
, trapaddr
)
262 # and store SVSTATE in SVSRR0
263 comb
+= svsrr0_o
.data
.eq(svstate_i
)
264 comb
+= svsrr0_o
.ok
.eq(1)
267 # MTMSR/D. v3.0B p TODO - move to MSR
269 with m
.Case(MicrOp
.OP_MTMSRD
, MicrOp
.OP_MTMSR
):
270 # L => bit 16 in LSB0, bit 15 in MSB0 order
271 L
= self
.fields
.FormX
.L1
[0:1] # X-Form field L1
272 # start with copy of msr
273 comb
+= msr_o
.data
.eq(msr_i
)
276 comb
+= msr_o
.data
[MSR
.RI
].eq(a_i
[MSR
.RI
])
277 comb
+= msr_o
.data
[MSR
.EE
].eq(a_i
[MSR
.EE
])
279 # Architecture says to leave out bits 3 (HV), 51 (ME)
280 # and 63 (LE) (IBM bit numbering)
281 with m
.If(op
.insn_type
== MicrOp
.OP_MTMSRD
):
282 # not MSB0 notation here!
283 for stt
, end
in [(1,12), (13, 60), (61, 64)]:
284 comb
+= msr_o
.data
[stt
:end
].eq(a_i
[stt
:end
])
285 # put *back* bits 29-31 (MSB0 notation)
286 bits
= field_slice(29, 31)
287 with m
.If((msr_i
[bits
] == Const(0b010, 3)) &
288 (a_i
[bits
] == Const(0b000, 3))):
289 comb
+= msr_o
.data
[bits
].eq(msr_i
[bits
])
292 # mtmsr - 32-bit, only room for bottom 32 LSB flags
293 for stt
, end
in [(1,12), (13, 32)]:
294 comb
+= msr_o
.data
[stt
:end
].eq(a_i
[stt
:end
])
295 # check problem state: if set, not permitted to set EE,IR,DR
296 msr_check_pr(m
, a_i
, msr_o
.data
)
298 # Per https://bugs.libre-soc.org/show_bug.cgi?id=325#c123,
299 # this actually *is* in the microwatt code now.
301 # hypervisor stuff. here: bits 3 (HV) and 51 (ME) were
302 # copied over by msr_copy but if HV was not set we need
303 # the *original* (msr_i) bits
304 # XXX taking this out to see what happens when running
305 # linux-5.7 microwatt buildroot. microwatt does not
306 # implement HV, so this is unlikely to work. 0x900
307 # linux kernel exception handling tends to support this
308 # with m.If(~msr_i[MSR.HV]):
309 # comb += msr_o.data[MSR.HV].eq(msr_i[MSR.HV])
310 # comb += msr_o.data[MSR.ME].eq(msr_i[MSR.ME])
312 comb
+= msr_o
.ok
.eq(1)
315 # MFMSR. v3.0B p TODO - move from MSR
317 with m
.Case(MicrOp
.OP_MFMSR
):
318 # some of the bits need zeroing? apparently not
319 comb
+= o
.data
.eq(msr_i
)
325 with m
.Case(MicrOp
.OP_RFID
):
327 # return addr was in srr0
328 comb
+= nia_o
.data
.eq(br_ext(srr0_i
[2:]))
329 comb
+= nia_o
.ok
.eq(1)
331 # svstate was in svsrr0
332 comb
+= svstate_o
.data
.eq(svstate_i
)
333 comb
+= svstate_o
.ok
.eq(1)
335 # MSR was in srr1: copy it over, however *caveats below*
336 comb
+= msr_copy(msr_o
.data
, srr1_i
, zero_me
=False) # don't zero
338 if False: # XXX no - not doing hypervisor yet
339 with m
.If(~self
.i
.ctx
.op
.insn
[9]): # XXX BAD HACK! (hrfid)
340 with m
.If(field(msr_i
, 3)): # HV
341 comb
+= field(msr_o
.data
, 51).eq(field(srr1_i
, 51)) # ME
343 comb
+= field(msr_o
.data
, 51).eq(field(msr_i
, 51)) # ME
345 # same as microwatt: treat MSR.ME rfid same as hrfid
346 comb
+= field(msr_o
.data
, 51).eq(field(srr1_i
, 51)) # ME
348 # check problem state: if set, not permitted to set EE,IR,DR
349 msr_check_pr(m
, srr1_i
, msr_o
.data
)
351 # don't understand but it's in the spec. again: bits 32-34
352 # are copied from srr1_i and need *restoring* to msr_i
354 bits
= field_slice(29, 31) # bits 29, 30, 31 (Power notation)
355 with m
.If((msr_i
[bits
] == Const(0b010, 3)) &
356 (srr1_i
[bits
] == Const(0b000, 3))):
357 comb
+= msr_o
.data
[bits
].eq(msr_i
[bits
])
359 comb
+= msr_o
.ok
.eq(1)
364 with m
.Case(MicrOp
.OP_SC
):
365 # scv is not covered here. currently an illegal instruction.
366 # raising "illegal" is the decoder's job, not ours, here.
368 # According to V3.0B, Book II, section 3.3.1, the System Call
369 # instruction allows you to trap directly into the hypervisor
370 # if the opcode's LEV sub-field is equal to 1.
371 # however we are following *microwatt* - which has
372 # not implemented hypervisor.
374 # jump to the trap address, return at cia+4
375 self
.trap(m
, 0xc00, cia_i
+4)
376 self
.msr_exception(m
, 0xc00)
379 #with m.Case(MicrOp.OP_ADDPCIS):
382 comb
+= self
.o
.ctx
.eq(self
.i
.ctx
)