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