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