comments in trap about exceptions using microcoding
[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 InternalOp
18
19 from soc.decoder.power_fields import DecodeFields
20 from soc.decoder.power_fieldsn import SignalBitRange
21
22 from soc.decoder.power_decoder2 import (TT_FP, TT_PRIV, TT_TRAP, TT_ADDR)
23 from soc.consts import MSR, PI
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 msr_i = self.i.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 ispec(self):
81 return TrapInputData(self.pspec)
82
83 def ospec(self):
84 return TrapOutputData(self.pspec)
85
86 def elaborate(self, platform):
87 m = Module()
88 comb = m.d.comb
89 op = self.i.ctx.op
90
91 # convenience variables
92 a_i, b_i, cia_i, msr_i = self.i.a, self.i.b, self.i.cia, self.i.msr
93 srr0_i, srr1_i = self.i.srr0, self.i.srr1
94 o, msr_o, nia_o = self.o.o, self.o.msr, self.o.nia
95 srr0_o, srr1_o = self.o.srr0, self.o.srr1
96 traptype, trapaddr = op.traptype, op.trapaddr
97
98 # take copy of D-Form TO field
99 i_fields = self.fields.FormD
100 to = Signal(i_fields.TO[0:-1].shape())
101 comb += to.eq(i_fields.TO[0:-1])
102
103 # signed/unsigned temporaries for RA and RB
104 a_s = Signal(signed(64), reset_less=True)
105 b_s = Signal(signed(64), reset_less=True)
106
107 a = Signal(64, reset_less=True)
108 b = Signal(64, reset_less=True)
109
110 # set up A and B comparison (truncate/sign-extend if 32 bit)
111 with m.If(op.is_32bit):
112 comb += a_s.eq(exts(a_i, 32, 64))
113 comb += b_s.eq(exts(b_i, 32, 64))
114 comb += a.eq(a_i[0:32])
115 comb += b.eq(b_i[0:32])
116 with m.Else():
117 comb += a_s.eq(a_i)
118 comb += b_s.eq(b_i)
119 comb += a.eq(a_i)
120 comb += b.eq(b_i)
121
122 # establish comparison bits
123 lt_s = Signal(reset_less=True)
124 gt_s = Signal(reset_less=True)
125 lt_u = Signal(reset_less=True)
126 gt_u = Signal(reset_less=True)
127 equal = Signal(reset_less=True)
128
129 comb += lt_s.eq(a_s < b_s)
130 comb += gt_s.eq(a_s > b_s)
131 comb += lt_u.eq(a < b)
132 comb += gt_u.eq(a > b)
133 comb += equal.eq(a == b)
134
135 # They're in reverse bit order because POWER.
136 # Check V3.0B Book 1, Appendix C.6 for chart
137 trap_bits = Signal(5, reset_less=True)
138 comb += trap_bits.eq(Cat(gt_u, lt_u, equal, gt_s, lt_s))
139
140 # establish if the trap should go ahead (any tests requested in TO)
141 # or if traptype is set already
142 should_trap = Signal(reset_less=True)
143 comb += should_trap.eq((trap_bits & to).any() | traptype.any())
144
145 # TODO: some #defines for the bits n stuff.
146 with m.Switch(op.insn_type):
147 #### trap ####
148 with m.Case(InternalOp.OP_TRAP):
149 # trap instructions (tw, twi, td, tdi)
150 with m.If(should_trap):
151 # generate trap-type program interrupt
152 self.trap(m, trapaddr<<4, cia_i)
153 with m.If(traptype == 0):
154 # say trap occurred (see 3.0B Book III 7.5.9)
155 comb += srr1_o.data[PI.TRAP].eq(1)
156 with m.If(traptype & TT_PRIV):
157 comb += srr1_o.data[PI.PRIV].eq(1)
158 with m.If(traptype & TT_FP):
159 comb += srr1_o.data[PI.FP].eq(1)
160 with m.If(traptype & TT_ADDR):
161 comb += srr1_o.data[PI.ADR].eq(1)
162
163 # move to MSR
164 with m.Case(InternalOp.OP_MTMSRD):
165 L = self.fields.FormX.L[0:-1] # X-Form field L
166 with m.If(L):
167 # just update EE and RI
168 comb += msr_o.data[MSR.EE].eq(a_i[MSR.EE])
169 comb += msr_o.data[MSR.RI].eq(a_i[MSR.RI])
170 with m.Else():
171 # Architecture says to leave out bits 3 (HV), 51 (ME)
172 # and 63 (LE) (IBM bit numbering)
173 for stt, end in [(1,12), (13, 60), (61, 64)]:
174 comb += msr_o.data[stt:end].eq(a_i[stt:end])
175 msr_check_pr(m, msr_o.data)
176 comb += msr_o.ok.eq(1)
177
178 # move from MSR
179 with m.Case(InternalOp.OP_MFMSR):
180 # TODO: some of the bits need zeroing? apparently not
181 comb += o.data.eq(msr_i)
182 comb += o.ok.eq(1)
183
184 with m.Case(InternalOp.OP_RFID):
185 # XXX f_out.virt_mode <= b_in(MSR.IR) or b_in(MSR.PR);
186 # XXX f_out.priv_mode <= not b_in(MSR.PR);
187
188 # return addr was in srr0
189 comb += nia_o.data.eq(br_ext(srr0_i[2:]))
190 comb += nia_o.ok.eq(1)
191 # MSR was in srr1
192 comb += msr_copy(msr_o.data, srr1_i, zero_me=False) # don't zero
193 msr_check_pr(m, msr_o.data)
194 comb += msr_o.ok.eq(1)
195
196 # TODO (later) - add OP_SC
197 #with m.Case(InternalOp.OP_SC):
198 # # TODO: scv must generate illegal instruction. this is
199 # # the decoder's job, not ours, here.
200 #
201 # # jump to the trap address, return at cia+4
202 # self.trap(m, 0xc00, cia_i+4)
203
204 # TODO (later)
205 #with m.Case(InternalOp.OP_ADDPCIS):
206 # pass
207
208 comb += self.o.ctx.eq(self.i.ctx)
209
210 return m