store KAIVB SPR 850 in TRAP Pipeline
[soc.git] / src / soc / fu / trap / main_stage.py
1 """Trap Pipeline
2
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.
6
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/
10 """
11
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
19
20 from openpower.decoder.power_fields import DecodeFields
21 from openpower.decoder.power_fieldsn import SignalBitRange
22
23 from openpower.consts import MSR, PI, TT, field, field_slice
24
25
26 def msr_copy(msr_o, msr_i, zero_me=True):
27 """msr_copy (also used to copy relevant bits into SRR1)
28
29 ISA says this:
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).
37 """
38 l = []
39 if zero_me:
40 l.append(msr_o.eq(0))
41 for stt, end in [(0,16), (22, 27), (31, 64)]:
42 l.append(msr_o[stt:end].eq(msr_i[stt:end]))
43 return l
44
45
46 def msr_check_pr(m, d_in, msr):
47 """msr_check_pr: checks "problem state"
48 """
49 comb = m.d.comb
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
54
55
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
63 def trap(self, m, trap_addr, return_addr):
64 """trap. sets new PC, stores MSR and old PC in SRR1 and SRR0
65 """
66 comb = m.d.comb
67 op = self.i.ctx.op
68 msr_i = op.msr
69 svstate_i = op.svstate
70
71 exc = LDSTException("trapexc")
72 comb += exc.eq(op.ldst_exc)
73 srr1_i = exc.srr1 # new SRR1 bits come from exception
74 nia_o = self.o.nia
75 svsrr0_o, srr0_o, srr1_o = self.o.svsrr0, self.o.srr0, self.o.srr1
76
77 # trap address
78 comb += nia_o.data.eq(trap_addr)
79 comb += nia_o.ok.eq(1)
80
81 # addr to begin from on return
82 comb += srr0_o.data.eq(return_addr)
83 comb += srr0_o.ok.eq(1)
84
85 # take a copy of the current MSR into SRR1, but first copy old SRR1
86 # this preserves the bits of SRR1 that are not supposed to change:
87 # MSR.IR,DR,PMM,RI,LE (0-5) and MR,FP,ME,FE0 (11-14)
88 # i would suggest reading v3.0C p1063 Book III section 7.2.1 for
89 # advice but it's so obscure and indirect, that it's just easier
90 # to copy microwatt behaviour. see writeback.vhdl
91 # IMPORTANT: PowerDecoder2 needed to actually read SRR1 for
92 # it to have the contents *of* SRR1 to copy over!
93 comb += msr_copy(srr1_o.data, msr_i, False) # old MSR
94 comb += srr1_o.data[16:22].eq(srr1_i[0:6]) # IR,DR,PMM,RI,LE
95 comb += srr1_o.data[27:31].eq(srr1_i[11:15]) # MR,FP,ME,FE0
96 comb += srr1_o.ok.eq(1)
97
98 # take a copy of the current SVSTATE into SVSRR0
99 comb += svsrr0_o.data.eq(svstate_i) # old SVSTATE
100 comb += svsrr0_o.ok.eq(1)
101
102 def msr_exception(self, m, trap_addr, msr_hv=None):
103 """msr_exception - sets bits in MSR specific to an exception.
104 the full list of what needs to be done is given in V3.0B
105 Book III Section 6.5 p1063 however it turns out that for the
106 majority of cases (microwatt showing the way, here), all these
107 bits are all set by all (implemented) interrupt types. this
108 may change in the future, hence the (unused) trap_addr argument
109 """
110 comb = m.d.comb
111 op = self.i.ctx.op
112 msr_i, msr_o = op.msr, self.o.msr
113 comb += msr_o.data.eq(msr_i) # copy msr, first, then modify
114 comb += msr_o.data[MSR.SF].eq(1)
115 comb += msr_o.data[MSR.EE].eq(0)
116 comb += msr_o.data[MSR.PR].eq(0)
117 comb += msr_o.data[MSR.IR].eq(0)
118 comb += msr_o.data[MSR.DR].eq(0)
119 comb += msr_o.data[MSR.RI].eq(0)
120 comb += msr_o.data[MSR.LE].eq(1)
121 comb += msr_o.data[MSR.FE0].eq(0)
122 comb += msr_o.data[MSR.FE1].eq(0)
123 comb += msr_o.data[MSR.VSX].eq(0)
124 comb += msr_o.data[MSR.TM].eq(0)
125 comb += msr_o.data[MSR.VEC].eq(0)
126 comb += msr_o.data[MSR.FP].eq(0)
127 comb += msr_o.data[MSR.PMM].eq(0)
128 comb += msr_o.data[MSR.TEs].eq(0) # this is only 2 bits
129 comb += msr_o.data[MSR.TEe].eq(0) # so just zero them both
130 comb += msr_o.data[MSR.UND].eq(0)
131 if msr_hv is not None:
132 comb += msr_o.data[MSR.HV].eq(msr_hv)
133 comb += msr_o.ok.eq(1)
134
135 def ispec(self):
136 return TrapInputData(self.pspec)
137
138 def ospec(self):
139 return TrapOutputData(self.pspec)
140
141 def elaborate(self, platform):
142 m = Module()
143 comb, sync = m.d.comb, m.d.sync
144 op = self.i.ctx.op
145
146 # convenience variables
147 a_i, b_i = self.i.a, self.i.b
148 cia_i, msr_i, svstate_i = op.cia, op.msr, op.svstate
149 srr0_i, srr1_i, svsrr0_i = self.i.srr0, self.i.srr1, self.i.svsrr0
150 o = self.o.o
151 msr_o, nia_o, svstate_o = self.o.msr, self.o.nia, self.o.svstate
152 srr0_o, srr1_o, svsrr0_o = self.o.srr0, self.o.srr1, self.o.svsrr0
153 traptype, trapaddr = op.traptype, op.trapaddr
154
155 # take copy of D-Form TO field
156 i_fields = self.fields.FormD
157 to = Signal(i_fields.TO[0:-1].shape())
158 comb += to.eq(i_fields.TO[0:-1])
159
160 # signed/unsigned temporaries for RA and RB
161 a_s = Signal(signed(64), reset_less=True)
162 b_s = Signal(signed(64), reset_less=True)
163
164 a = Signal(64, reset_less=True)
165 b = Signal(64, reset_less=True)
166
167 # set up A and B comparison (truncate/sign-extend if 32 bit)
168 with m.If(op.is_32bit):
169 comb += a_s.eq(exts(a_i, 32, 64))
170 comb += b_s.eq(exts(b_i, 32, 64))
171 comb += a.eq(a_i[0:32])
172 comb += b.eq(b_i[0:32])
173 with m.Else():
174 comb += a_s.eq(a_i)
175 comb += b_s.eq(b_i)
176 comb += a.eq(a_i)
177 comb += b.eq(b_i)
178
179 # establish comparison bits
180 lt_s = Signal(reset_less=True)
181 gt_s = Signal(reset_less=True)
182 lt_u = Signal(reset_less=True)
183 gt_u = Signal(reset_less=True)
184 equal = Signal(reset_less=True)
185
186 comb += lt_s.eq(a_s < b_s)
187 comb += gt_s.eq(a_s > b_s)
188 comb += lt_u.eq(a < b)
189 comb += gt_u.eq(a > b)
190 comb += equal.eq(a == b)
191
192 # They're in reverse bit order because POWER.
193 # Check V3.0B Book 1, Appendix C.6 for chart
194 trap_bits = Signal(5, reset_less=True)
195 comb += trap_bits.eq(Cat(gt_u, lt_u, equal, gt_s, lt_s))
196
197 # establish if the trap should go ahead (any tests requested in TO)
198 # or if traptype is set already
199 should_trap = Signal(reset_less=True)
200 comb += should_trap.eq((trap_bits & to).any() | traptype.any())
201
202 # TODO: some #defines for the bits n stuff.
203 with m.Switch(op.insn_type):
204
205 ##############
206 # KAIVB https://bugs.libre-soc.org/show_bug.cgi?id=859
207
208 with m.Case(MicrOp.OP_MTSPR):
209 sync += self.kaivb.eq(a_i)
210
211 with m.Case(MicrOp.OP_MFSPR):
212 comb += o.data.eq(self.kaivb)
213 comb += o.ok.eq(1)
214
215 ###############
216 # TDI/TWI/TD/TW. v3.0B p90-91
217
218 with m.Case(MicrOp.OP_TRAP):
219 # trap instructions (tw, twi, td, tdi)
220 with m.If(should_trap):
221 # generate trap-type program interrupt
222 self.trap(m, trapaddr<<4, cia_i)
223 with m.If(traptype == 0):
224 # say trap occurred (see 3.0B Book III 6.5.9 p1074-6)
225 comb += srr1_o.data[PI.TRAP].eq(1)
226 with m.If(traptype & TT.PRIV):
227 comb += srr1_o.data[PI.PRIV].eq(1)
228 with m.If(traptype & TT.FP):
229 comb += srr1_o.data[PI.FP].eq(1)
230 with m.If(traptype & TT.ADDR):
231 comb += srr1_o.data[PI.ADR].eq(1)
232 with m.If((traptype & TT.MEMEXC).bool() &
233 (trapaddr == 0x400)):
234 # Instruction Storage Interrupt (ISI - 0x400)
235 # v3.0C Book III Chap 7.5.5 p1085
236 # decode exception bits, store in SRR1
237 exc = LDSTException("trapexc")
238 comb += exc.eq(op.ldst_exc)
239 comb += srr1_o.data[PI.INVALID].eq(exc.invalid)
240 comb += srr1_o.data[PI.PERMERR].eq(exc.perm_error)
241 comb += srr1_o.data[PI.ILLEG].eq(exc.badtree)
242 comb += srr1_o.data[PI.PRIV].eq(exc.rc_error)
243 with m.If(traptype & TT.EINT):
244 # do nothing unusual? see 3.0B Book III 6.5.7 p1073
245 pass
246 with m.If(traptype & TT.DEC):
247 # do nothing unusual?
248 pass
249 with m.If(traptype & TT.ILLEG):
250 comb += srr1_o.data[PI.ILLEG].eq(1)
251 comb += srr1_o.ok.eq(1)
252
253 # when SRR1 is written to, update MSR bits
254 self.msr_exception(m, trapaddr)
255
256 # and store SVSTATE in SVSRR0
257 comb += svsrr0_o.data.eq(svstate_i)
258 comb += svsrr0_o.ok.eq(1)
259
260 ###################
261 # MTMSR/D. v3.0B p TODO - move to MSR
262
263 with m.Case(MicrOp.OP_MTMSRD, MicrOp.OP_MTMSR):
264 # L => bit 16 in LSB0, bit 15 in MSB0 order
265 L = self.fields.FormX.L1[0:1] # X-Form field L1
266 # start with copy of msr
267 comb += msr_o.eq(msr_i)
268 with m.If(L):
269 # just update RI..EE
270 comb += msr_o.data[MSR.RI].eq(a_i[MSR.RI])
271 comb += msr_o.data[MSR.EE].eq(a_i[MSR.EE])
272 with m.Else():
273 # Architecture says to leave out bits 3 (HV), 51 (ME)
274 # and 63 (LE) (IBM bit numbering)
275 with m.If(op.insn_type == MicrOp.OP_MTMSRD):
276 # not MSB0 notation here!
277 for stt, end in [(1,12), (13, 60), (61, 64)]:
278 comb += msr_o.data[stt:end].eq(a_i[stt:end])
279 # put *back* bits 29-31 (MSB0 notation)
280 bits = field_slice(29, 31)
281 with m.If((msr_i[bits] == Const(0b010, 3)) &
282 (a_i[bits] == Const(0b000, 3))):
283 comb += msr_o.data[bits].eq(msr_i[bits])
284
285 with m.Else():
286 # mtmsr - 32-bit, only room for bottom 32 LSB flags
287 for stt, end in [(1,12), (13, 32)]:
288 comb += msr_o.data[stt:end].eq(a_i[stt:end])
289 # check problem state: if set, not permitted to set EE,IR,DR
290 msr_check_pr(m, a_i, msr_o.data)
291
292 # Per https://bugs.libre-soc.org/show_bug.cgi?id=325#c123,
293 # this actually *is* in the microwatt code now.
294 #
295 # hypervisor stuff. here: bits 3 (HV) and 51 (ME) were
296 # copied over by msr_copy but if HV was not set we need
297 # the *original* (msr_i) bits
298 # XXX taking this out to see what happens when running
299 # linux-5.7 microwatt buildroot. microwatt does not
300 # implement HV, so this is unlikely to work. 0x900
301 # linux kernel exception handling tends to support this
302 # with m.If(~msr_i[MSR.HV]):
303 # comb += msr_o.data[MSR.HV].eq(msr_i[MSR.HV])
304 # comb += msr_o.data[MSR.ME].eq(msr_i[MSR.ME])
305
306 comb += msr_o.ok.eq(1)
307
308 ###################
309 # MFMSR. v3.0B p TODO - move from MSR
310
311 with m.Case(MicrOp.OP_MFMSR):
312 # some of the bits need zeroing? apparently not
313 comb += o.data.eq(msr_i)
314 comb += o.ok.eq(1)
315
316 ###################
317 # RFID. v3.0B p955
318
319 with m.Case(MicrOp.OP_RFID):
320
321 # return addr was in srr0
322 comb += nia_o.data.eq(br_ext(srr0_i[2:]))
323 comb += nia_o.ok.eq(1)
324
325 # svstate was in svsrr0
326 comb += svstate_o.data.eq(svstate_i)
327 comb += svstate_o.ok.eq(1)
328
329 # MSR was in srr1: copy it over, however *caveats below*
330 comb += msr_copy(msr_o.data, srr1_i, zero_me=False) # don't zero
331
332 if False: # XXX no - not doing hypervisor yet
333 with m.If(~self.i.ctx.op.insn[9]): # XXX BAD HACK! (hrfid)
334 with m.If(field(msr_i, 3)): # HV
335 comb += field(msr_o, 51).eq(field(srr1_i, 51)) # ME
336 with m.Else():
337 comb += field(msr_o, 51).eq(field(msr_i, 51)) # ME
338 else:
339 # same as microwatt: treat MSR.ME rfid same as hrfid
340 comb += field(msr_o, 51).eq(field(srr1_i, 51)) # ME
341
342 # check problem state: if set, not permitted to set EE,IR,DR
343 msr_check_pr(m, srr1_i, msr_o.data)
344
345 # don't understand but it's in the spec. again: bits 32-34
346 # are copied from srr1_i and need *restoring* to msr_i
347
348 bits = field_slice(29, 31) # bits 29, 30, 31 (Power notation)
349 with m.If((msr_i[bits] == Const(0b010, 3)) &
350 (srr1_i[bits] == Const(0b000, 3))):
351 comb += msr_o.data[bits].eq(msr_i[bits])
352
353 comb += msr_o.ok.eq(1)
354
355 #################
356 # SC. v3.0B p952
357
358 with m.Case(MicrOp.OP_SC):
359 # scv is not covered here. currently an illegal instruction.
360 # raising "illegal" is the decoder's job, not ours, here.
361
362 # According to V3.0B, Book II, section 3.3.1, the System Call
363 # instruction allows you to trap directly into the hypervisor
364 # if the opcode's LEV sub-field is equal to 1.
365 # however we are following *microwatt* - which has
366 # not implemented hypervisor.
367
368 # jump to the trap address, return at cia+4
369 self.trap(m, 0xc00, cia_i+4)
370 self.msr_exception(m, 0xc00)
371
372 # TODO (later)
373 #with m.Case(MicrOp.OP_ADDPCIS):
374 # pass
375
376 comb += self.o.ctx.eq(self.i.ctx)
377
378 return m