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