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