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