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.
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/
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
19 from soc
.decoder
.power_fields
import DecodeFields
20 from soc
.decoder
.power_fieldsn
import SignalBitRange
22 from soc
.consts
import MSR
, PI
, TT
, field
, field_slice
25 def msr_copy(msr_o
, msr_i
, zero_me
=True):
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).
39 for stt
, end
in [(0,16), (22, 27), (31, 64)]:
40 l
.append(msr_o
[stt
:end
].eq(msr_i
[stt
:end
]))
44 def msr_check_pr(m
, msr
):
45 """msr_check_pr: checks "problem state"
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
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()
60 def trap(self
, m
, trap_addr
, return_addr
):
61 """trap. sets new PC, stores MSR and old PC in SRR1 and SRR0
66 nia_o
, srr0_o
, srr1_o
= self
.o
.nia
, self
.o
.srr0
, self
.o
.srr1
69 comb
+= nia_o
.data
.eq(trap_addr
)
70 comb
+= nia_o
.ok
.eq(1)
72 # addr to begin from on return
73 comb
+= srr0_o
.data
.eq(return_addr
)
74 comb
+= srr0_o
.ok
.eq(1)
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)
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
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)
114 return TrapInputData(self
.pspec
)
117 return TrapOutputData(self
.pspec
)
119 def elaborate(self
, platform
):
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
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])
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)
140 a
= Signal(64, reset_less
=True)
141 b
= Signal(64, reset_less
=True)
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])
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)
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
)
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
))
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())
178 # TODO: some #defines for the bits n stuff.
179 with m
.Switch(op
.insn_type
):
182 # TDI/TWI/TD/TW. v3.0B p90-91
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
.EINT
):
199 # do nothing unusual? see 3.0B Book III 6.5.7 p1073
201 with m
.If(traptype
& TT
.DEC
):
202 # do nothing unusual?
204 with m
.If(traptype
& TT
.ILLEG
):
205 comb
+= srr1_o
.data
[PI
.ILLEG
].eq(1)
206 comb
+= srr1_o
.ok
.eq(1)
208 # when SRR1 is written to, update MSR bits
209 self
.msr_exception(m
, trapaddr
)
212 # MTMSR/D. v3.0B p TODO - move to MSR
214 with m
.Case(MicrOp
.OP_MTMSRD
, MicrOp
.OP_MTMSR
):
215 L
= self
.fields
.FormX
.L
[0:-1] # X-Form field L
216 # start with copy of msr
217 comb
+= msr_o
.eq(msr_i
)
220 comb
+= msr_o
.data
[MSR
.RI
].eq(a_i
[MSR
.RI
])
221 comb
+= msr_o
.data
[MSR
.EE
].eq(a_i
[MSR
.EE
])
223 # Architecture says to leave out bits 3 (HV), 51 (ME)
224 # and 63 (LE) (IBM bit numbering)
225 with m
.If(op
.insn_type
== MicrOp
.OP_MTMSRD
):
226 # not MSB0 notation here!
227 for stt
, end
in [(1,12), (13, 60), (61, 64)]:
228 comb
+= msr_o
.data
[stt
:end
].eq(a_i
[stt
:end
])
229 # put *back* bits 29-31 (MSB0 notation)
230 bits
= field_slice(29, 31)
231 with m
.If((msr_i
[bits
] == Const(0b010, 3)) &
232 (a_i
[bits
] == Const(0b000, 3))):
233 comb
+= msr_o
.data
[bits
].eq(msr_i
[bits
])
236 # mtmsr - 32-bit, only room for bottom 32 LSB flags
237 for stt
, end
in [(1,12), (13, 32)]:
238 comb
+= msr_o
.data
[stt
:end
].eq(a_i
[stt
:end
])
239 msr_check_pr(m
, msr_o
.data
)
241 # Per https://bugs.libre-soc.org/show_bug.cgi?id=325#c123,
242 # this actually *is* in the microwatt code now.
244 # hypervisor stuff. here: bits 3 (HV) and 51 (ME) were
245 # copied over by msr_copy but if HV was not set we need
246 # the *original* (msr_i) bits
247 with m
.If(~msr_i
[MSR
.HV
]):
248 comb
+= msr_o
.data
[MSR
.HV
].eq(msr_i
[MSR
.HV
])
249 comb
+= msr_o
.data
[MSR
.ME
].eq(msr_i
[MSR
.ME
])
251 comb
+= msr_o
.ok
.eq(1)
254 # MFMSR. v3.0B p TODO - move from MSR
256 with m
.Case(MicrOp
.OP_MFMSR
):
257 # some of the bits need zeroing? apparently not
258 comb
+= o
.data
.eq(msr_i
)
264 with m
.Case(MicrOp
.OP_RFID
):
266 # return addr was in srr0
267 comb
+= nia_o
.data
.eq(br_ext(srr0_i
[2:]))
268 comb
+= nia_o
.ok
.eq(1)
270 # MSR was in srr1: copy it over, however *caveats below*
271 comb
+= msr_copy(msr_o
.data
, srr1_i
, zero_me
=False) # don't zero
273 with m
.If(~self
.i
.ctx
.op
.insn
[9]): # XXX BAD HACK! (hrfid)
274 with m
.If(field(msr_i
, 3)): # HV
275 comb
+= field(msr_o
, 51).eq(field(srr1_i
, 51)) # ME
277 comb
+= field(msr_o
, 51).eq(field(msr_i
, 51)) # ME
279 # check problem state
280 msr_check_pr(m
, msr_o
.data
)
282 # don't understand but it's in the spec. again: bits 32-34
283 # are copied from srr1_i and need *restoring* to msr_i
285 bits
= field_slice(29, 31) # bits 29, 30, 31 (Power notation)
286 with m
.If((msr_i
[bits
] == Const(0b010, 3)) &
287 (srr1_i
[bits
] == Const(0b000, 3))):
288 comb
+= msr_o
.data
[bits
].eq(msr_i
[bits
])
290 comb
+= msr_o
.ok
.eq(1)
295 with m
.Case(MicrOp
.OP_SC
):
296 # scv is not covered here. currently an illegal instruction.
297 # raising "illegal" is the decoder's job, not ours, here.
299 # According to V3.0B, Book II, section 3.3.1, the System Call
300 # instruction allows you to trap directly into the hypervisor
301 # if the opcode's LEV sub-field is equal to 1.
302 # however we are following *microwatt* - which has
303 # not implemented hypervisor.
305 # jump to the trap address, return at cia+4
306 self
.trap(m
, 0xc00, cia_i
+4)
307 self
.msr_exception(m
, 0xc00)
310 #with m.Case(MicrOp.OP_ADDPCIS):
313 comb
+= self
.o
.ctx
.eq(self
.i
.ctx
)