WIP: addressing code review, restoring proofs, etc.
[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, 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 comb += msr_o.data[MSR.TEs].eq(0) # this is only 2 bits
107 comb += msr_o.data[MSR.TEe].eq(0) # so just zero them both
108 comb += msr_o.data[MSR.UND].eq(0)
109 if msr_hv is not None:
110 comb += msr_o.data[MSR.HV].eq(msr_hv)
111 comb += msr_o.ok.eq(1)
112
113 def ispec(self):
114 return TrapInputData(self.pspec)
115
116 def ospec(self):
117 return TrapOutputData(self.pspec)
118
119 def elaborate(self, platform):
120 m = Module()
121 comb = m.d.comb
122 op = self.i.ctx.op
123
124 # convenience variables
125 a_i, b_i, cia_i, msr_i = self.i.a, self.i.b, op.cia, op.msr
126 srr0_i, srr1_i = self.i.srr0, self.i.srr1
127 o, msr_o, nia_o = self.o.o, self.o.msr, self.o.nia
128 srr0_o, srr1_o = self.o.srr0, self.o.srr1
129 traptype, trapaddr = op.traptype, op.trapaddr
130
131 # take copy of D-Form TO field
132 i_fields = self.fields.FormD
133 to = Signal(i_fields.TO[0:-1].shape())
134 comb += to.eq(i_fields.TO[0:-1])
135
136 # signed/unsigned temporaries for RA and RB
137 a_s = Signal(signed(64), reset_less=True)
138 b_s = Signal(signed(64), reset_less=True)
139
140 a = Signal(64, reset_less=True)
141 b = Signal(64, reset_less=True)
142
143 # set up A and B comparison (truncate/sign-extend if 32 bit)
144 with m.If(op.is_32bit):
145 comb += a_s.eq(exts(a_i, 32, 64))
146 comb += b_s.eq(exts(b_i, 32, 64))
147 comb += a.eq(a_i[0:32])
148 comb += b.eq(b_i[0:32])
149 with m.Else():
150 comb += a_s.eq(a_i)
151 comb += b_s.eq(b_i)
152 comb += a.eq(a_i)
153 comb += b.eq(b_i)
154
155 # establish comparison bits
156 lt_s = Signal(reset_less=True)
157 gt_s = Signal(reset_less=True)
158 lt_u = Signal(reset_less=True)
159 gt_u = Signal(reset_less=True)
160 equal = Signal(reset_less=True)
161
162 comb += lt_s.eq(a_s < b_s)
163 comb += gt_s.eq(a_s > b_s)
164 comb += lt_u.eq(a < b)
165 comb += gt_u.eq(a > b)
166 comb += equal.eq(a == b)
167
168 # They're in reverse bit order because POWER.
169 # Check V3.0B Book 1, Appendix C.6 for chart
170 trap_bits = Signal(5, reset_less=True)
171 comb += trap_bits.eq(Cat(gt_u, lt_u, equal, gt_s, lt_s))
172
173 # establish if the trap should go ahead (any tests requested in TO)
174 # or if traptype is set already
175 should_trap = Signal(reset_less=True)
176 comb += should_trap.eq((trap_bits & to).any() | traptype.any())
177
178 # TODO: some #defines for the bits n stuff.
179 with m.Switch(op.insn_type):
180 #### trap ####
181 with m.Case(MicrOp.OP_TRAP):
182 # trap instructions (tw, twi, td, tdi)
183 with m.If(should_trap):
184 # generate trap-type program interrupt
185 self.trap(m, trapaddr<<4, cia_i)
186 with m.If(traptype == 0):
187 # say trap occurred (see 3.0B Book III 6.5.9 p1074-6)
188 comb += srr1_o.data[PI.TRAP].eq(1)
189 with m.If(traptype & TT.PRIV):
190 comb += srr1_o.data[PI.PRIV].eq(1)
191 with m.If(traptype & TT.FP):
192 comb += srr1_o.data[PI.FP].eq(1)
193 with m.If(traptype & TT.ADDR):
194 comb += srr1_o.data[PI.ADR].eq(1)
195 with m.If(traptype & TT.ILLEG):
196 comb += srr1_o.data[PI.ILLEG].eq(1)
197 comb += srr1_o.ok.eq(1)
198
199 # when SRR1 is written to, update MSR bits
200 self.msr_exception(m, trapaddr)
201
202 # move to MSR
203 with m.Case(MicrOp.OP_MTMSRD, MicrOp.OP_MTMSR):
204 L = self.fields.FormX.L[0:-1] # X-Form field L
205 # start with copy of msr
206 comb += msr_o.eq(msr_i)
207 with m.If(L):
208 # just update RI..EE
209 comb += msr_o.data[MSR.RI].eq(a_i[MSR.RI])
210 comb += msr_o.data[MSR.EE].eq(a_i[MSR.EE])
211 with m.Else():
212 # Architecture says to leave out bits 3 (HV), 51 (ME)
213 # and 63 (LE) (IBM bit numbering)
214 with m.If(op.insn_type == MicrOp.OP_MTMSRD):
215 for stt, end in [(1,12), (13, 60), (61, 64)]:
216 comb += msr_o.data[stt:end].eq(a_i[stt:end])
217 with m.Else():
218 # mtmsr - 32-bit, only room for bottom 32 LSB flags
219 for stt, end in [(1,12), (13, 32)]:
220 comb += msr_o.data[stt:end].eq(a_i[stt:end])
221 msr_check_pr(m, msr_o.data)
222
223 # Per https://bugs.libre-soc.org/show_bug.cgi?id=325#c123,
224 # this actually *is* in the microwatt code now.
225 #
226 # hypervisor stuff. here: bits 3 (HV) and 51 (ME) were
227 # copied over by msr_copy but if HV was not set we need
228 # the *original* (msr_i) bits
229 with m.If(~msr_i[MSR.HV]):
230 comb += msr_o.data[MSR.HV].eq(msr_i[MSR.HV])
231 comb += msr_o.data[MSR.ME].eq(msr_i[MSR.ME])
232
233 comb += msr_o.ok.eq(1)
234
235 # move from MSR
236 with m.Case(MicrOp.OP_MFMSR):
237 # some of the bits need zeroing? apparently not
238 comb += o.data.eq(msr_i)
239 comb += o.ok.eq(1)
240
241 with m.Case(MicrOp.OP_RFID):
242 # XXX f_out.virt_mode <= b_in(MSR.IR) or b_in(MSR.PR);
243 # XXX f_out.priv_mode <= not b_in(MSR.PR);
244
245 # return addr was in srr0
246 comb += nia_o.data.eq(br_ext(srr0_i[2:]))
247 comb += nia_o.ok.eq(1)
248
249 # MSR was in srr1: copy it over, however *caveats below*
250 comb += msr_copy(msr_o.data, srr1_i, zero_me=False) # don't zero
251
252 with m.If(field(msr_i, 3)): # HV
253 comb += field(msr_o, 51).eq(field(srr1_i, 51)) # ME
254 with m.Else():
255 comb += field(msr_o, 51).eq(field(msr_i, 51)) # ME
256
257 # check problem state
258 msr_check_pr(m, msr_o.data)
259
260 # don't understand but it's in the spec. again: bits 32-34
261 # are copied from srr1_i and need *restoring* to msr_i
262
263 bits = field_slice(29, 31) # bits 29, 30, 31 (Power notation)
264 with m.If((msr_i[bits] == Const(0b010, 3)) &
265 (srr1_i[bits] == Const(0b000, 3))):
266 comb += msr_o.data[bits].eq(msr_i[bits])
267
268 comb += msr_o.ok.eq(1)
269
270 # OP_SC
271 with m.Case(MicrOp.OP_SC):
272 # scv is not covered here. currently an illegal instruction.
273 # raising "illegal" is the decoder's job, not ours, here.
274
275 # According to V3.0B, Book II, section 3.3.1, the System Call
276 # instruction allows you to trap directly into the hypervisor
277 # if the opcode's LEV sub-field is equal to 1.
278 # however we are following *microwatt* - which has
279 # not implemented hypervisor.
280
281 # jump to the trap address, return at cia+4
282 self.trap(m, 0xc00, cia_i+4)
283 self.msr_exception(m, 0xc00)
284
285 # TODO (later)
286 #with m.Case(MicrOp.OP_ADDPCIS):
287 # pass
288
289 comb += self.o.ctx.eq(self.i.ctx)
290
291 return m