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