1 | // ========== Copyright Header Begin ========================================== |
---|
2 | // |
---|
3 | // OpenSPARC T1 Processor File: sparc_exu_ecl_wb.v |
---|
4 | // Copyright (c) 2006 Sun Microsystems, Inc. All Rights Reserved. |
---|
5 | // DO NOT ALTER OR REMOVE COPYRIGHT NOTICES. |
---|
6 | // |
---|
7 | // The above named program is free software; you can redistribute it and/or |
---|
8 | // modify it under the terms of the GNU General Public |
---|
9 | // License version 2 as published by the Free Software Foundation. |
---|
10 | // |
---|
11 | // The above named program is distributed in the hope that it will be |
---|
12 | // useful, but WITHOUT ANY WARRANTY; without even the implied warranty of |
---|
13 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
---|
14 | // General Public License for more details. |
---|
15 | // |
---|
16 | // You should have received a copy of the GNU General Public |
---|
17 | // License along with this work; if not, write to the Free Software |
---|
18 | // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. |
---|
19 | // |
---|
20 | // ========== Copyright Header End ============================================ |
---|
21 | //////////////////////////////////////////////////////////////////////// |
---|
22 | /* |
---|
23 | // Module Name: sparc_exu_ecl_wb |
---|
24 | // Description: Implements the writeback logic for the exu. |
---|
25 | // This includes the control signals for the w1 and w2 input |
---|
26 | // muxes as well as keeping track of the wen signal for ALU ops. |
---|
27 | */ |
---|
28 | |
---|
29 | module sparc_exu_ecl_wb (/*AUTOARG*/ |
---|
30 | // Outputs |
---|
31 | wb_ccr_wrccr_w, ecl_rml_cwp_wen_e, ecl_rml_cansave_wen_w, |
---|
32 | ecl_rml_canrestore_wen_w, ecl_rml_otherwin_wen_w, |
---|
33 | ecl_rml_wstate_wen_w, ecl_rml_cleanwin_wen_w, ecl_byp_sel_load_m, |
---|
34 | ecl_byp_sel_restore_m, ecl_byp_sel_pipe_m, ecl_byp_restore_m, |
---|
35 | ecl_irf_tid_m, ecl_irf_rd_m, ecl_irf_rd_g, ecl_irf_wen_w2, |
---|
36 | ecl_irf_tid_g, wb_e, bypass_m, ecl_irf_wen_w, ecl_byp_sel_load_g, |
---|
37 | ecl_byp_sel_muldiv_g, ecl_byp_sel_restore_g, wb_divcntl_ack_g, |
---|
38 | wb_ccr_setcc_g, ecl_byp_eclpr_e, exu_ifu_longop_done_g, |
---|
39 | ecl_div_yreg_wen_w, ecl_div_yreg_wen_g, ecl_div_yreg_shift_g, |
---|
40 | ecl_div_yreg_wen_l, wb_eccctl_spec_wen_next, bypass_w, |
---|
41 | wb_byplog_rd_w2, wb_byplog_tid_w2, wb_byplog_wen_w2, |
---|
42 | wb_byplog_rd_g2, wb_byplog_wen_g2, read_yreg_e, |
---|
43 | exu_ffu_wsr_inst_e, |
---|
44 | // Inputs |
---|
45 | clk, se, reset, sehold, ld_rd_g, ld_tid_g, lsu_exu_dfill_vld_g, |
---|
46 | lsu_exu_ldst_miss_g2, rd_m, tid_m, thr_m, tid_w1, ifu_exu_wen_d, |
---|
47 | ifu_exu_kill_e, ecl_exu_kill_m, rml_ecl_kill_m, ifu_tlu_flush_w, |
---|
48 | flush_w1, divcntl_wb_req_g, mdqctl_wb_divrd_g, mdqctl_wb_divthr_g, |
---|
49 | mdqctl_wb_mulrd_g, mdqctl_wb_multhr_g, mdqctl_wb_divsetcc_g, |
---|
50 | mdqctl_wb_mulsetcc_g, ecl_div_sel_div, ifu_tlu_wsr_inst_d, |
---|
51 | ifu_tlu_sraddr_d, rml_ecl_cwp_d, rml_ecl_cansave_d, |
---|
52 | rml_ecl_canrestore_d, rml_ecl_otherwin_d, rml_ecl_wstate_d, |
---|
53 | rml_ecl_cleanwin_d, exu_ifu_cc_d, rml_ecl_swap_done, |
---|
54 | rml_ecl_rmlop_done_e, mdqctl_wb_yreg_wen_g, |
---|
55 | mdqctl_wb_yreg_shift_g, ecl_byp_sel_ecc_m, eccctl_wb_rd_m, |
---|
56 | ifu_exu_inst_vld_e, ifu_exu_inst_vld_w, ifu_exu_return_d, |
---|
57 | restore_e, rml_ecl_fill_e, early_flush_w, ecl_byp_ldxa_g |
---|
58 | ) ; |
---|
59 | input clk; |
---|
60 | input se; |
---|
61 | input reset; |
---|
62 | input sehold; |
---|
63 | input [4:0] ld_rd_g; |
---|
64 | input [1:0] ld_tid_g; |
---|
65 | input lsu_exu_dfill_vld_g; |
---|
66 | input lsu_exu_ldst_miss_g2; |
---|
67 | input [4:0] rd_m; |
---|
68 | input [1:0] tid_m; |
---|
69 | input [3:0] thr_m; |
---|
70 | input [1:0] tid_w1; |
---|
71 | input ifu_exu_wen_d; |
---|
72 | input ifu_exu_kill_e; |
---|
73 | input ecl_exu_kill_m; |
---|
74 | input rml_ecl_kill_m; // kill from spill or fill trap |
---|
75 | input ifu_tlu_flush_w; |
---|
76 | input flush_w1; |
---|
77 | input divcntl_wb_req_g; |
---|
78 | input [4:0] mdqctl_wb_divrd_g; |
---|
79 | input [1:0] mdqctl_wb_divthr_g; |
---|
80 | input [4:0] mdqctl_wb_mulrd_g; |
---|
81 | input [1:0] mdqctl_wb_multhr_g; |
---|
82 | input mdqctl_wb_divsetcc_g; |
---|
83 | input mdqctl_wb_mulsetcc_g; |
---|
84 | input ecl_div_sel_div; |
---|
85 | input ifu_tlu_wsr_inst_d; |
---|
86 | input [6:0] ifu_tlu_sraddr_d; |
---|
87 | input [2:0] rml_ecl_cwp_d; |
---|
88 | input [2:0] rml_ecl_cansave_d; |
---|
89 | input [2:0] rml_ecl_canrestore_d; |
---|
90 | input [2:0] rml_ecl_otherwin_d; |
---|
91 | input [5:0] rml_ecl_wstate_d; |
---|
92 | input [2:0] rml_ecl_cleanwin_d; |
---|
93 | input [7:0] exu_ifu_cc_d; |
---|
94 | input [3:0] rml_ecl_swap_done; |
---|
95 | input rml_ecl_rmlop_done_e; |
---|
96 | input mdqctl_wb_yreg_wen_g; |
---|
97 | input mdqctl_wb_yreg_shift_g; |
---|
98 | input ecl_byp_sel_ecc_m; |
---|
99 | input [4:0] eccctl_wb_rd_m; |
---|
100 | input ifu_exu_inst_vld_e; |
---|
101 | input ifu_exu_inst_vld_w; |
---|
102 | input ifu_exu_return_d; |
---|
103 | input restore_e; |
---|
104 | input rml_ecl_fill_e; |
---|
105 | input early_flush_w; |
---|
106 | input ecl_byp_ldxa_g; |
---|
107 | |
---|
108 | output wb_ccr_wrccr_w; |
---|
109 | output ecl_rml_cwp_wen_e; |
---|
110 | output ecl_rml_cansave_wen_w; |
---|
111 | output ecl_rml_canrestore_wen_w; |
---|
112 | output ecl_rml_otherwin_wen_w; |
---|
113 | output ecl_rml_wstate_wen_w; |
---|
114 | output ecl_rml_cleanwin_wen_w; |
---|
115 | output ecl_byp_sel_load_m; |
---|
116 | output ecl_byp_sel_restore_m; |
---|
117 | output ecl_byp_sel_pipe_m; |
---|
118 | output ecl_byp_restore_m; |
---|
119 | output [1:0] ecl_irf_tid_m; |
---|
120 | output [4:0] ecl_irf_rd_m; |
---|
121 | output [4:0] ecl_irf_rd_g; |
---|
122 | output ecl_irf_wen_w2; |
---|
123 | output [1:0] ecl_irf_tid_g; |
---|
124 | output wb_e; |
---|
125 | output bypass_m; |
---|
126 | output ecl_irf_wen_w; |
---|
127 | output ecl_byp_sel_load_g; |
---|
128 | output ecl_byp_sel_muldiv_g; |
---|
129 | output ecl_byp_sel_restore_g; |
---|
130 | output wb_divcntl_ack_g; |
---|
131 | output wb_ccr_setcc_g; |
---|
132 | output [7:0] ecl_byp_eclpr_e; |
---|
133 | output [3:0] exu_ifu_longop_done_g; |
---|
134 | output [3:0] ecl_div_yreg_wen_w; |
---|
135 | output [3:0] ecl_div_yreg_wen_g; |
---|
136 | output [3:0] ecl_div_yreg_shift_g; |
---|
137 | output [3:0] ecl_div_yreg_wen_l;// w or w2 or shift |
---|
138 | output wb_eccctl_spec_wen_next; |
---|
139 | output bypass_w; |
---|
140 | output [4:0] wb_byplog_rd_w2; |
---|
141 | output [1:0] wb_byplog_tid_w2; |
---|
142 | output wb_byplog_wen_w2; |
---|
143 | output [4:0] wb_byplog_rd_g2; |
---|
144 | output wb_byplog_wen_g2; |
---|
145 | output read_yreg_e; |
---|
146 | output exu_ffu_wsr_inst_e; |
---|
147 | |
---|
148 | wire wb_e; |
---|
149 | wire wb_m; |
---|
150 | wire wb_w; |
---|
151 | wire inst_vld_noflush_wen_m; |
---|
152 | wire inst_vld_noflush_wen_w; |
---|
153 | wire ecl_irf_wen_g; |
---|
154 | wire yreg_wen_w; |
---|
155 | wire yreg_wen_w1; |
---|
156 | wire yreg_wen_w1_vld; |
---|
157 | wire wen_no_inst_vld_m; // load or restore or ce wen |
---|
158 | wire wen_no_inst_vld_w; |
---|
159 | wire wen_w_inst_vld; |
---|
160 | wire valid_e; |
---|
161 | wire valid_m; |
---|
162 | wire valid_w; |
---|
163 | wire ecl_sel_mul_g; |
---|
164 | wire ecl_sel_div_g; |
---|
165 | wire [1:0] muldiv_tid; |
---|
166 | wire setcc_g; // without wen from divcntl |
---|
167 | wire wrsr_e; |
---|
168 | wire wrsr_m; |
---|
169 | wire wrsr_w; |
---|
170 | wire [6:0] sraddr_e; |
---|
171 | wire [6:0] sraddr_m; |
---|
172 | wire [6:0] sraddr_w; |
---|
173 | wire sraddr_ccr_w; |
---|
174 | wire sraddr_y_w; |
---|
175 | wire sraddr_cwp_e; |
---|
176 | wire sraddr_cansave_w; |
---|
177 | wire sraddr_canrestore_w; |
---|
178 | wire sraddr_cleanwin_w; |
---|
179 | wire sraddr_otherwin_w; |
---|
180 | wire sraddr_wstate_w; |
---|
181 | wire sel_cleanwin_d; |
---|
182 | wire sel_otherwin_d; |
---|
183 | wire sel_wstate_d; |
---|
184 | wire sel_canrestore_d; |
---|
185 | wire sel_ccr_d; |
---|
186 | wire sel_cansave_d; |
---|
187 | wire sel_cwp_d; |
---|
188 | wire sel_rdpr_mux1_d; |
---|
189 | wire [2:0] rdpr_mux1_out; |
---|
190 | wire [7:0] rdpr_mux2_out; |
---|
191 | wire [3:0] muldiv_done_g; |
---|
192 | wire [3:0] multhr_dec_g; |
---|
193 | wire [3:0] divthr_dec_g; |
---|
194 | wire [3:0] thrdec_w1; |
---|
195 | wire short_longop_done_e; |
---|
196 | wire short_longop_done_m; |
---|
197 | wire [3:0] short_longop_done; |
---|
198 | wire return_e; |
---|
199 | wire restore_m; |
---|
200 | wire restore_w; |
---|
201 | wire vld_restore_e; |
---|
202 | wire vld_restore_w; |
---|
203 | wire restore_request; |
---|
204 | wire restore_wen; |
---|
205 | wire restore_ready; |
---|
206 | wire restore_ready_next; |
---|
207 | wire restore_picked; |
---|
208 | wire [3:0] restore_done; |
---|
209 | wire [1:0] restore_tid; |
---|
210 | wire [4:0] restore_rd; |
---|
211 | wire [3:0] restore_thr; |
---|
212 | wire [3:0] ecl_longop_done_kill_m; |
---|
213 | wire [3:0] ecl_longop_done_nokill_m; |
---|
214 | wire dfill_vld_g2; |
---|
215 | wire ld_g; |
---|
216 | wire ld_g2; |
---|
217 | wire [1:0] dfill_tid_g2; |
---|
218 | wire [4:0] dfill_rd_g2; |
---|
219 | wire kill_ld_g2; |
---|
220 | wire [1:0] tid_w2; |
---|
221 | wire [4:0] rd_w2; |
---|
222 | |
---|
223 | //////////////////////////////////////////// |
---|
224 | // Pass along result of load for one cycle |
---|
225 | //////////////////////////////////////////// |
---|
226 | assign ld_g = lsu_exu_dfill_vld_g | ecl_byp_ldxa_g; |
---|
227 | dff_s dfill_vld_dff (.din(ld_g), .clk(clk), .q(ld_g2), |
---|
228 | .se(se), .si(), .so()); |
---|
229 | assign kill_ld_g2 = flush_w1 & (dfill_tid_g2[1:0] == tid_w1[1:0]); |
---|
230 | assign dfill_vld_g2 = ld_g2 & ~kill_ld_g2 & ~lsu_exu_ldst_miss_g2; |
---|
231 | dff_s #(2) dfill_tid_dff(.din(ld_tid_g[1:0]), .clk(clk), .q(dfill_tid_g2[1:0]), |
---|
232 | .se(se), .si(), .so()); |
---|
233 | dff_s #(5) dfill_rd_dff(.din(ld_rd_g[4:0]), .clk(clk), .q(dfill_rd_g2[4:0]), |
---|
234 | .se(se), .si(), .so()); |
---|
235 | |
---|
236 | /////////////////////////////////////////// |
---|
237 | // Help with bypassing of long latency ops |
---|
238 | /////////////////////////////////////////// |
---|
239 | assign wb_byplog_rd_w2[4:0] = rd_w2[4:0]; |
---|
240 | assign wb_byplog_wen_w2 = ecl_irf_wen_w2; |
---|
241 | assign wb_byplog_tid_w2[1:0] = tid_w2[1:0]; |
---|
242 | assign wb_byplog_rd_g2[4:0] = dfill_rd_g2[4:0]; |
---|
243 | assign wb_byplog_wen_g2 = ld_g2; |
---|
244 | |
---|
245 | |
---|
246 | //////////////////////////////////////////////////////////////// |
---|
247 | // G selection logic (picks between LOAD and MUL/DIV outputs) |
---|
248 | //////////////////////////////////////////////////////////////// |
---|
249 | // select signals: priority LOAD, RESTORE, MUL, DIV |
---|
250 | assign ecl_byp_sel_load_g = (ld_g2 & (wb_m | wrsr_m | ecl_byp_sel_ecc_m)); |
---|
251 | assign ecl_byp_sel_restore_g = restore_request & ((wb_m | wrsr_m | ecl_byp_sel_ecc_m) ^ ld_g2); |
---|
252 | assign ecl_byp_sel_muldiv_g = ~(ecl_byp_sel_load_g | ecl_byp_sel_restore_g); |
---|
253 | assign ecl_sel_mul_g = ~ecl_div_sel_div & ecl_byp_sel_muldiv_g; |
---|
254 | assign ecl_sel_div_g = ecl_div_sel_div & ecl_byp_sel_muldiv_g; |
---|
255 | assign wb_divcntl_ack_g = ecl_byp_sel_muldiv_g; |
---|
256 | |
---|
257 | assign muldiv_tid[1:0] = (ecl_div_sel_div)? mdqctl_wb_divthr_g[1:0]: mdqctl_wb_multhr_g[1:0]; |
---|
258 | assign muldiv_done_g[3] = ((wb_divcntl_ack_g & divcntl_wb_req_g) & |
---|
259 | muldiv_tid[1] & muldiv_tid[0]); |
---|
260 | assign muldiv_done_g[2] = ((wb_divcntl_ack_g & divcntl_wb_req_g) & |
---|
261 | muldiv_tid[1] & ~muldiv_tid[0]); |
---|
262 | assign muldiv_done_g[1] = ((wb_divcntl_ack_g & divcntl_wb_req_g) & |
---|
263 | ~muldiv_tid[1] & muldiv_tid[0]); |
---|
264 | assign muldiv_done_g[0] = ((wb_divcntl_ack_g & divcntl_wb_req_g) & |
---|
265 | ~muldiv_tid[1] & ~muldiv_tid[0]); |
---|
266 | |
---|
267 | assign ecl_irf_wen_g = (sehold)? ecl_irf_wen_w2: |
---|
268 | (ecl_byp_sel_load_g & dfill_vld_g2 | |
---|
269 | (ecl_byp_sel_restore_g & restore_wen) | |
---|
270 | (ecl_byp_sel_muldiv_g & divcntl_wb_req_g)); |
---|
271 | |
---|
272 | dff_s wen_w2_dff(.din(ecl_irf_wen_g), .clk(clk), .q(ecl_irf_wen_w2), |
---|
273 | .se(se), .si(), .so()); |
---|
274 | mux4ds #(5) rd_g_mux(.dout(ecl_irf_rd_g[4:0]), .in0(dfill_rd_g2[4:0]), |
---|
275 | .in1(mdqctl_wb_divrd_g[4:0]), |
---|
276 | .in2(mdqctl_wb_mulrd_g[4:0]), |
---|
277 | .in3(restore_rd[4:0]), |
---|
278 | .sel0(ecl_byp_sel_load_g), |
---|
279 | .sel1(ecl_sel_div_g), |
---|
280 | .sel2(ecl_sel_mul_g), |
---|
281 | .sel3(ecl_byp_sel_restore_g)); |
---|
282 | mux4ds #(2) thr_g_mux(.dout(ecl_irf_tid_g[1:0]), .in0(dfill_tid_g2[1:0]), |
---|
283 | .in1(mdqctl_wb_divthr_g[1:0]), |
---|
284 | .in2(mdqctl_wb_multhr_g[1:0]), |
---|
285 | .in3(restore_tid[1:0]), |
---|
286 | .sel0(ecl_byp_sel_load_g), |
---|
287 | .sel1(ecl_sel_div_g), |
---|
288 | .sel2(ecl_sel_mul_g), |
---|
289 | .sel3(ecl_byp_sel_restore_g)); |
---|
290 | mux2ds setcc_g_mux(.dout(setcc_g), |
---|
291 | .in0(mdqctl_wb_mulsetcc_g), |
---|
292 | .in1(mdqctl_wb_divsetcc_g), |
---|
293 | .sel0(~ecl_div_sel_div), |
---|
294 | .sel1(ecl_div_sel_div)); |
---|
295 | dff_s #(2) dff_thr_g2w2(.din(ecl_irf_tid_g[1:0]), .clk(clk), .q(tid_w2[1:0]), .se(se), |
---|
296 | .si(), .so()); |
---|
297 | dff_s #(5) dff_rd_g2w2(.din(ecl_irf_rd_g[4:0]), .clk(clk), .q(rd_w2[4:0]), .se(se), |
---|
298 | .si(), .so()); |
---|
299 | // needs wen to setcc |
---|
300 | assign wb_ccr_setcc_g = wb_divcntl_ack_g & divcntl_wb_req_g & setcc_g; |
---|
301 | |
---|
302 | |
---|
303 | /////////////////// |
---|
304 | // W1 port control |
---|
305 | /////////////////// |
---|
306 | // sehold will turn off in pipe writes and put the hold functionality through |
---|
307 | // the non inst_vld part |
---|
308 | // Mux between load and ALU for rd, thr, and wen |
---|
309 | assign ecl_byp_sel_load_m = ~(wb_m | wrsr_m | ecl_byp_sel_ecc_m) & ld_g2; |
---|
310 | assign ecl_byp_sel_pipe_m = (wb_m | wrsr_m) & ~ecl_byp_sel_ecc_m; |
---|
311 | assign ecl_byp_sel_restore_m = ~(wb_m | wrsr_m | ld_g2 | ecl_byp_sel_ecc_m); |
---|
312 | assign wen_no_inst_vld_m = (sehold)? ecl_irf_wen_w: |
---|
313 | ((dfill_vld_g2 & ecl_byp_sel_load_m) | |
---|
314 | (ecl_byp_sel_restore_m & restore_wen)); |
---|
315 | dff_s dff_lsu_wen_m2w(.din(wen_no_inst_vld_m), .clk(clk), .q(wen_no_inst_vld_w), .se(se), .si(), |
---|
316 | .so()); |
---|
317 | // ecc_wen must be kept separate because it needs to check inst_vld but not flush |
---|
318 | assign inst_vld_noflush_wen_m = ecl_byp_sel_ecc_m & ~sehold; |
---|
319 | dff_s ecc_wen_m2w(.din(inst_vld_noflush_wen_m), .clk(clk), .q(inst_vld_noflush_wen_w), .se(se), .si(), .so()); |
---|
320 | |
---|
321 | assign ecl_irf_tid_m[1:0] = ((ecl_byp_sel_load_m)? dfill_tid_g2[1:0]: |
---|
322 | (ecl_byp_sel_restore_m)? restore_tid[1:0]: |
---|
323 | tid_m[1:0]); |
---|
324 | |
---|
325 | mux4ds #(5) rd_mux(.dout(ecl_irf_rd_m[4:0]), |
---|
326 | .in0(rd_m[4:0]), |
---|
327 | .in1(dfill_rd_g2[4:0]), |
---|
328 | .in2(eccctl_wb_rd_m[4:0]), |
---|
329 | .in3(restore_rd[4:0]), |
---|
330 | .sel0(ecl_byp_sel_pipe_m), |
---|
331 | .sel1(ecl_byp_sel_load_m), |
---|
332 | .sel2(ecl_byp_sel_ecc_m), |
---|
333 | .sel3(ecl_byp_sel_restore_m)); |
---|
334 | assign wen_w_inst_vld = valid_w | inst_vld_noflush_wen_w; |
---|
335 | assign ecl_irf_wen_w = ifu_exu_inst_vld_w & wen_w_inst_vld | wen_no_inst_vld_w; |
---|
336 | |
---|
337 | // bypass valid logic and flops |
---|
338 | dff_s dff_wb_d2e(.din(ifu_exu_wen_d), .clk(clk), .q(wb_e), .se(se), |
---|
339 | .si(), .so()); |
---|
340 | dff_s dff_wb_e2m(.din(valid_e), .clk(clk), .q(wb_m), .se(se), |
---|
341 | .si(), .so()); |
---|
342 | dffr_s dff_wb_m2w(.din(valid_m), .clk(clk), .q(wb_w), .se(se), |
---|
343 | .si(), .so(), .rst(reset)); |
---|
344 | assign valid_e = wb_e & ~ifu_exu_kill_e & ~restore_e & ~wrsr_e;// restore doesn't finish on time |
---|
345 | assign bypass_m = wb_m;// bypass doesn't need to check for traps or sehold |
---|
346 | assign valid_m = bypass_m & ~rml_ecl_kill_m & ~sehold;// sehold turns off writes from this path |
---|
347 | assign valid_w = (wb_w & ~early_flush_w & ~ifu_tlu_flush_w);// check inst_vld later |
---|
348 | // don't check flush for bypass |
---|
349 | assign bypass_w = wb_w | inst_vld_noflush_wen_w | wen_no_inst_vld_w; |
---|
350 | |
---|
351 | // speculative wen for ecc injection |
---|
352 | assign wb_eccctl_spec_wen_next = valid_m | dfill_vld_g2 | restore_request | divcntl_wb_req_g; |
---|
353 | |
---|
354 | /////////////////////////////////////////////////////// |
---|
355 | // Priviledged register read and write flops and logic |
---|
356 | /////////////////////////////////////////////////////// |
---|
357 | /* -----\/----- EXCLUDED -----\/----- |
---|
358 | Decoded sraddr |
---|
359 | sraddr[5] = 1-priv, 0-state |
---|
360 | Y - 0 |
---|
361 | CCR - 2 |
---|
362 | CWP - 9 |
---|
363 | CANSAVE - a |
---|
364 | CARESTORE - b |
---|
365 | CLEANWIN - c |
---|
366 | OTHERWIN - d |
---|
367 | WSTATE - e |
---|
368 | GSR - 0x13 |
---|
369 | -----/\----- EXCLUDED -----/\----- */ |
---|
370 | assign ecl_rml_cwp_wen_e = sraddr_cwp_e & wrsr_e; |
---|
371 | assign sraddr_cwp_e = ~sraddr_e[6] & sraddr_e[5] & ~sraddr_e[4] & sraddr_e[3] & ~sraddr_e[2] & |
---|
372 | ~sraddr_e[1] & sraddr_e[0]; |
---|
373 | |
---|
374 | assign sraddr_y_w = ~sraddr_w[6] & ~sraddr_w[5] & ~sraddr_w[4] & ~sraddr_w[3] & ~sraddr_w[2] & |
---|
375 | ~sraddr_w[1] & ~sraddr_w[0]; |
---|
376 | assign sraddr_ccr_w = ~sraddr_w[6] & ~sraddr_w[5] & ~sraddr_w[4] & ~sraddr_w[3] & ~sraddr_w[2] & |
---|
377 | sraddr_w[1] & ~sraddr_w[0]; |
---|
378 | assign sraddr_cansave_w = ~sraddr_w[6] & sraddr_w[5] & ~sraddr_w[4] & sraddr_w[3] & ~sraddr_w[2] & |
---|
379 | sraddr_w[1] & ~sraddr_w[0]; |
---|
380 | assign sraddr_canrestore_w = ~sraddr_w[6] & sraddr_w[5] & ~sraddr_w[4] & sraddr_w[3] & ~sraddr_w[2] & |
---|
381 | sraddr_w[1] & sraddr_w[0]; |
---|
382 | assign sraddr_cleanwin_w = ~sraddr_w[6] & sraddr_w[5] & ~sraddr_w[4] & sraddr_w[3] & sraddr_w[2] & |
---|
383 | ~sraddr_w[1] & ~sraddr_w[0]; |
---|
384 | assign sraddr_otherwin_w = ~sraddr_w[6] & sraddr_w[5] & ~sraddr_w[4] & sraddr_w[3] & sraddr_w[2] & |
---|
385 | ~sraddr_w[1] & sraddr_w[0]; |
---|
386 | assign sraddr_wstate_w = ~sraddr_w[6] & sraddr_w[5] & ~sraddr_w[4] & sraddr_w[3] & sraddr_w[2] & |
---|
387 | sraddr_w[1] & ~sraddr_w[0]; |
---|
388 | |
---|
389 | // yreg writes cycle after w and checks flush in that cycle |
---|
390 | assign yreg_wen_w = sraddr_y_w & wrsr_w & ifu_exu_inst_vld_w; |
---|
391 | assign yreg_wen_w1_vld = yreg_wen_w1 & ~flush_w1; |
---|
392 | |
---|
393 | // controls for all other writes (and flush checks) are in their respective blocks |
---|
394 | assign wb_ccr_wrccr_w = sraddr_ccr_w & wrsr_w; |
---|
395 | assign ecl_rml_cansave_wen_w = sraddr_cansave_w & wrsr_w; |
---|
396 | assign ecl_rml_canrestore_wen_w = sraddr_canrestore_w & wrsr_w; |
---|
397 | assign ecl_rml_cleanwin_wen_w = sraddr_cleanwin_w & wrsr_w; |
---|
398 | assign ecl_rml_otherwin_wen_w = sraddr_otherwin_w & wrsr_w; |
---|
399 | assign ecl_rml_wstate_wen_w = sraddr_wstate_w & wrsr_w; |
---|
400 | |
---|
401 | |
---|
402 | dff_s dff_wrsr_d2e(.din(ifu_tlu_wsr_inst_d), .clk(clk), .q(wrsr_e), .se(se), |
---|
403 | .si(), .so()); |
---|
404 | assign exu_ffu_wsr_inst_e = wrsr_e; |
---|
405 | dff_s dff_wrsr_e2m(.din(wrsr_e), .clk(clk), .q(wrsr_m), .se(se), |
---|
406 | .si(), .so()); |
---|
407 | dff_s dff_wrsr_m2w(.din(wrsr_m), .clk(clk), .q(wrsr_w), .se(se), |
---|
408 | .si(), .so()); |
---|
409 | dff_s #(7) dff_sraddr_d2e(.din(ifu_tlu_sraddr_d[6:0]), .clk(clk), .q(sraddr_e[6:0]), .se(se), |
---|
410 | .si(), .so()); |
---|
411 | dff_s #(7) dff_sraddr_e2m(.din(sraddr_e[6:0]), .clk(clk), .q(sraddr_m[6:0]), .se(se), |
---|
412 | .si(), .so()); |
---|
413 | dff_s #(7) dff_sraddr_m2w(.din(sraddr_m[6:0]), .clk(clk), .q(sraddr_w[6:0]), .se(se), |
---|
414 | .si(), .so()); |
---|
415 | dff_s dff_yreg_wen_w2w1(.din(yreg_wen_w), .clk(clk), .q(yreg_wen_w1), .se(se), .si(), .so()); |
---|
416 | |
---|
417 | // Logic for rdpr/rdsr |
---|
418 | // This mux takes advantage of the fact that these 4 encodings don't overlap |
---|
419 | assign sel_cleanwin_d = ~ifu_tlu_sraddr_d[1] & ~ifu_tlu_sraddr_d[0]; |
---|
420 | assign sel_otherwin_d = ~ifu_tlu_sraddr_d[1] & ifu_tlu_sraddr_d[0]; |
---|
421 | assign sel_cansave_d = ifu_tlu_sraddr_d[1] & ~ifu_tlu_sraddr_d[0]; |
---|
422 | assign sel_canrestore_d = ifu_tlu_sraddr_d[1] & ifu_tlu_sraddr_d[0]; |
---|
423 | mux4ds #(3) rdpr_mux1(.dout(rdpr_mux1_out[2:0]), |
---|
424 | .in0(rml_ecl_canrestore_d[2:0]), |
---|
425 | .in1(rml_ecl_cleanwin_d[2:0]), |
---|
426 | .in2(rml_ecl_cansave_d[2:0]), |
---|
427 | .in3(rml_ecl_otherwin_d[2:0]), |
---|
428 | .sel0(sel_canrestore_d), |
---|
429 | .sel1(sel_cleanwin_d), |
---|
430 | .sel2(sel_cansave_d), |
---|
431 | .sel3(sel_otherwin_d)); |
---|
432 | assign sel_ccr_d = ~ifu_tlu_sraddr_d[3]; |
---|
433 | assign sel_cwp_d = ifu_tlu_sraddr_d[3] & ~ifu_tlu_sraddr_d[2] & ~ifu_tlu_sraddr_d[1] & ifu_tlu_sraddr_d[0]; |
---|
434 | assign sel_wstate_d = ifu_tlu_sraddr_d[3] & ifu_tlu_sraddr_d[2] & ifu_tlu_sraddr_d[1] & ~ifu_tlu_sraddr_d[0]; |
---|
435 | assign sel_rdpr_mux1_d = ~(sel_ccr_d | sel_cwp_d | sel_wstate_d); |
---|
436 | mux4ds #(8) rdpr_mux2(.dout(rdpr_mux2_out[7:0]), |
---|
437 | .in0(exu_ifu_cc_d[7:0]), |
---|
438 | .in1({5'b0, rml_ecl_cwp_d[2:0]}), |
---|
439 | .in2({2'b0, rml_ecl_wstate_d[5:0]}), |
---|
440 | .in3({5'b0, rdpr_mux1_out[2:0]}), |
---|
441 | .sel0(sel_ccr_d), |
---|
442 | .sel1(sel_cwp_d), |
---|
443 | .sel2(sel_wstate_d), |
---|
444 | .sel3(sel_rdpr_mux1_d)); |
---|
445 | |
---|
446 | assign read_yreg_e = ~(sraddr_e[3] | sraddr_e[1]); |
---|
447 | dff_s #(8) rdpr_dff(.din(rdpr_mux2_out[7:0]), .clk(clk), .q(ecl_byp_eclpr_e[7:0]), |
---|
448 | .se(se), .si(), .so()); |
---|
449 | |
---|
450 | |
---|
451 | /////////////////////////////// |
---|
452 | // YREG write enable logic |
---|
453 | /////////////////////////////// |
---|
454 | // decode thr_g for mux select |
---|
455 | assign multhr_dec_g[0] = ~mdqctl_wb_multhr_g[1] & ~mdqctl_wb_multhr_g[0]; |
---|
456 | assign multhr_dec_g[1] = ~mdqctl_wb_multhr_g[1] & mdqctl_wb_multhr_g[0]; |
---|
457 | assign multhr_dec_g[2] = mdqctl_wb_multhr_g[1] & ~mdqctl_wb_multhr_g[0]; |
---|
458 | assign multhr_dec_g[3] = mdqctl_wb_multhr_g[1] & mdqctl_wb_multhr_g[0]; |
---|
459 | |
---|
460 | assign divthr_dec_g[0] = ~mdqctl_wb_divthr_g[1] & ~mdqctl_wb_divthr_g[0]; |
---|
461 | assign divthr_dec_g[1] = ~mdqctl_wb_divthr_g[1] & mdqctl_wb_divthr_g[0]; |
---|
462 | assign divthr_dec_g[2] = mdqctl_wb_divthr_g[1] & ~mdqctl_wb_divthr_g[0]; |
---|
463 | assign divthr_dec_g[3] = mdqctl_wb_divthr_g[1] & mdqctl_wb_divthr_g[0]; |
---|
464 | |
---|
465 | assign thrdec_w1[0] = ~tid_w1[1] & ~tid_w1[0]; |
---|
466 | assign thrdec_w1[1] = ~tid_w1[1] & tid_w1[0]; |
---|
467 | assign thrdec_w1[2] = tid_w1[1] & ~tid_w1[0]; |
---|
468 | assign thrdec_w1[3] = tid_w1[1] & tid_w1[0]; |
---|
469 | |
---|
470 | // enable input for each thread |
---|
471 | |
---|
472 | assign ecl_div_yreg_shift_g[0] = divthr_dec_g[0] & mdqctl_wb_yreg_shift_g; |
---|
473 | assign ecl_div_yreg_wen_w[0] = (thrdec_w1[0] & yreg_wen_w1_vld & |
---|
474 | ~ecl_div_yreg_shift_g[0] & |
---|
475 | ~ecl_div_yreg_wen_g[0]); |
---|
476 | assign ecl_div_yreg_wen_g[0] = (multhr_dec_g[0] & mdqctl_wb_yreg_wen_g & |
---|
477 | ~ecl_div_yreg_shift_g[0]); |
---|
478 | assign ecl_div_yreg_wen_l[0] = ~(ecl_div_yreg_wen_w[0] | ecl_div_yreg_wen_g[0] |
---|
479 | | ecl_div_yreg_shift_g[0]); |
---|
480 | assign ecl_div_yreg_shift_g[1] = divthr_dec_g[1] & mdqctl_wb_yreg_shift_g; |
---|
481 | assign ecl_div_yreg_wen_w[1] = (thrdec_w1[1] & yreg_wen_w1_vld & |
---|
482 | ~ecl_div_yreg_shift_g[1] & |
---|
483 | ~ecl_div_yreg_wen_g[1]); |
---|
484 | assign ecl_div_yreg_wen_g[1] = (multhr_dec_g[1] & mdqctl_wb_yreg_wen_g & |
---|
485 | ~ecl_div_yreg_shift_g[1]); |
---|
486 | assign ecl_div_yreg_wen_l[1] = ~(ecl_div_yreg_wen_w[1] | ecl_div_yreg_wen_g[1] |
---|
487 | | ecl_div_yreg_shift_g[1]); |
---|
488 | assign ecl_div_yreg_shift_g[2] = divthr_dec_g[2] & mdqctl_wb_yreg_shift_g; |
---|
489 | assign ecl_div_yreg_wen_w[2] = (thrdec_w1[2] & yreg_wen_w1_vld & |
---|
490 | ~ecl_div_yreg_shift_g[2] & |
---|
491 | ~ecl_div_yreg_wen_g[2]); |
---|
492 | assign ecl_div_yreg_wen_g[2] = (multhr_dec_g[2] & mdqctl_wb_yreg_wen_g & |
---|
493 | ~ecl_div_yreg_shift_g[2]); |
---|
494 | assign ecl_div_yreg_wen_l[2] = ~(ecl_div_yreg_wen_w[2] | ecl_div_yreg_wen_g[2] |
---|
495 | | ecl_div_yreg_shift_g[2]); |
---|
496 | assign ecl_div_yreg_shift_g[3] = divthr_dec_g[3] & mdqctl_wb_yreg_shift_g; |
---|
497 | assign ecl_div_yreg_wen_w[3] = (thrdec_w1[3] & yreg_wen_w1_vld & |
---|
498 | ~ecl_div_yreg_shift_g[3] & |
---|
499 | ~ecl_div_yreg_wen_g[3]); |
---|
500 | assign ecl_div_yreg_wen_g[3] = (multhr_dec_g[3] & mdqctl_wb_yreg_wen_g & |
---|
501 | ~ecl_div_yreg_shift_g[3]); |
---|
502 | assign ecl_div_yreg_wen_l[3] = ~(ecl_div_yreg_wen_w[3] | ecl_div_yreg_wen_g[3] |
---|
503 | | ecl_div_yreg_shift_g[3]); |
---|
504 | |
---|
505 | ////////////////////////////////////////////////////////// |
---|
506 | // Completion logic for restore |
---|
507 | ////////////////////////////////////////////////////////// |
---|
508 | |
---|
509 | // only worry about restores. Returns are automatically switched back in |
---|
510 | assign ecl_byp_restore_m = restore_m; |
---|
511 | assign vld_restore_e = restore_e & wb_e & ~return_e & ~rml_ecl_fill_e & ifu_exu_inst_vld_e; |
---|
512 | assign vld_restore_w = (restore_w & ~ifu_tlu_flush_w & ~early_flush_w |
---|
513 | & ifu_exu_inst_vld_w & ~reset); |
---|
514 | |
---|
515 | assign restore_request = restore_w | restore_ready; |
---|
516 | assign restore_wen = vld_restore_w | restore_ready; |
---|
517 | assign restore_picked = ecl_byp_sel_restore_m | ecl_byp_sel_restore_g; |
---|
518 | assign restore_done[3:0] = restore_thr[3:0] & {4{restore_picked & restore_request}}; |
---|
519 | // restore request waits for kills in the w stage. they |
---|
520 | // won't start until after the flop |
---|
521 | assign restore_ready_next = (vld_restore_w | restore_ready) & ~restore_picked; |
---|
522 | |
---|
523 | dffe_s #(2) restore_tid_dff(.din(tid_m[1:0]), .clk(clk), .q(restore_tid[1:0]), |
---|
524 | .se(se), .si(), .so(), .en(restore_m)); |
---|
525 | dffe_s #(5) restore_rd_dff(.din(rd_m[4:0]), .clk(clk), .q(restore_rd[4:0]), |
---|
526 | .se(se), .si(), .so(), .en(restore_m)); |
---|
527 | dff_s return_d2e(.din(ifu_exu_return_d), .clk(clk), .q(return_e), |
---|
528 | .se(se), .si(), .so()); |
---|
529 | dff_s restore_e2m(.din(vld_restore_e), .clk(clk), .q(restore_m), |
---|
530 | .se(se), .si(), .so()); |
---|
531 | dff_s restore_m2w(.din(restore_m), .clk(clk), .q(restore_w), |
---|
532 | .se(se), .si(), .so()); |
---|
533 | dff_s restore_ready_dff(.din(restore_ready_next), .q(restore_ready), |
---|
534 | .clk(clk), .se(se), .so(), .si()); |
---|
535 | |
---|
536 | ////////////////////////////////////////////////////////// |
---|
537 | // Completion logic for non integer-pipeline operations |
---|
538 | ////////////////////////////////////////////////////////// |
---|
539 | // short_longops must check inst_vld_e to protect against invalid completion signal |
---|
540 | assign short_longop_done_e = (rml_ecl_rmlop_done_e | (restore_e & ~wb_e & ~return_e)) & |
---|
541 | ifu_exu_inst_vld_e & ~ifu_exu_kill_e; |
---|
542 | dff_s longop_done_e2m (.din(short_longop_done_e), .clk(clk), .q(short_longop_done_m), .se(se), .si(), .so()); |
---|
543 | assign short_longop_done[3:0] = thr_m[3:0] & {4{short_longop_done_m}}; |
---|
544 | |
---|
545 | assign ecl_longop_done_nokill_m[3:0] = (muldiv_done_g[3:0] | restore_done[3:0] | short_longop_done[3:0] | |
---|
546 | rml_ecl_swap_done[3:0]); |
---|
547 | assign ecl_longop_done_kill_m[3:0] = (muldiv_done_g[3:0] | restore_done[3:0] | rml_ecl_swap_done[3:0]); |
---|
548 | assign exu_ifu_longop_done_g[3:0] = (ecl_exu_kill_m)? ecl_longop_done_kill_m[3:0]: ecl_longop_done_nokill_m[3:0]; |
---|
549 | |
---|
550 | |
---|
551 | // decode tid |
---|
552 | assign restore_thr[3] = restore_tid[1] & restore_tid[0]; |
---|
553 | assign restore_thr[2] = restore_tid[1] & ~restore_tid[0]; |
---|
554 | assign restore_thr[1] = ~restore_tid[1] & restore_tid[0]; |
---|
555 | assign restore_thr[0] = ~restore_tid[1] & ~restore_tid[0]; |
---|
556 | |
---|
557 | endmodule // sparc_exu_ecl_wb |
---|