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