source: XOpenSparcT1/trunk/T1-CPU/exu/sparc_exu_rml.v @ 6

Revision 6, 36.1 KB checked in by pntsvt00, 13 years ago (diff)

versione iniziale opensparc

Line 
1// ========== Copyright Header Begin ==========================================
2//
3// OpenSPARC T1 Processor File: sparc_exu_rml.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_rml
24//      Description: Register management logic.  Contains CWP, CANSAVE, CANRESTORE
25//              and other window management registers.  Generates RF related traps
26//              and switches the global registers to alternate globals.  All the registers
27//              are written in the W stage (there is no bypassing so they must
28//              swap out) and will either get a new value generated by a window management
29//              Instruction or by a WRPS instruction.  The following traps can be generated:
30//                      Fill: restore with canrestore == 0
31//                      clean_window: save with cleanwin-canrestore == 0
32//                      spill: flushw with cansave != nwindows -2 or
33//                              save with cansave == 0
34//              It is assumed that the contents of the new window will get squashed
35//              on a clean_window or fill trap so the save or restore gets executed
36//              normally.  Spill traps or WRCWPs mean that all 16 windowed registers
37//              must be saved and restored (a 4 cycle operation).
38*/
39module sparc_exu_rml (/*AUTOARG*/
40   // Outputs
41   exu_tlu_spill_wtype, exu_tlu_spill_other, exu_tlu_cwp_retry, 
42   exu_tlu_cwp3_w, exu_tlu_cwp2_w, exu_tlu_cwp1_w, exu_tlu_cwp0_w, 
43   so, exu_tlu_cwp_cmplt, exu_tlu_cwp_cmplt_tid, rml_ecl_cwp_d, 
44   rml_ecl_cansave_d, rml_ecl_canrestore_d, rml_ecl_otherwin_d, 
45   rml_ecl_wstate_d, rml_ecl_cleanwin_d, rml_ecl_fill_e, 
46   rml_ecl_clean_window_e, rml_ecl_other_e, rml_ecl_wtype_e, 
47   exu_ifu_spill_e, rml_ecl_gl_e, rml_irf_old_lo_cwp_e, 
48   rml_irf_new_lo_cwp_e, rml_irf_old_e_cwp_e, rml_irf_new_e_cwp_e, 
49   rml_irf_swap_even_e, rml_irf_swap_odd_e, rml_irf_swap_local_e, 
50   rml_irf_kill_restore_w, rml_irf_cwpswap_tid_e, rml_ecl_swap_done, 
51   rml_ecl_rmlop_done_e, exu_ifu_oddwin_s, exu_tlu_spill, 
52   exu_tlu_spill_tid, rml_ecl_kill_m, rml_irf_old_agp, 
53   rml_irf_new_agp, rml_irf_swap_global, rml_irf_global_tid, 
54   // Inputs
55   tlu_exu_cwp_retry_m, rst_tri_en, rclk, se, si, grst_l, arst_l, 
56   ifu_exu_tid_s2, ifu_exu_save_d, ifu_exu_restore_d, 
57   ifu_exu_saved_e, ifu_exu_restored_e, ifu_exu_flushw_e, 
58   ecl_rml_thr_m, ecl_rml_thr_w, ecl_rml_cwp_wen_e, 
59   ecl_rml_cansave_wen_w, ecl_rml_canrestore_wen_w, 
60   ecl_rml_otherwin_wen_w, ecl_rml_wstate_wen_w, 
61   ecl_rml_cleanwin_wen_w, ecl_rml_xor_data_e, ecl_rml_kill_e, 
62   ecl_rml_kill_w, ecl_rml_early_flush_w, exu_tlu_wsr_data_w, 
63   tlu_exu_agp, tlu_exu_agp_swap, tlu_exu_agp_tid, tlu_exu_cwp_m, 
64   tlu_exu_cwpccr_update_m, ecl_rml_inst_vld_w,current_cwp
65   ) ;
66   input rclk;
67   input se;
68   input si;
69   input grst_l;
70   input arst_l;
71   input [1:0] ifu_exu_tid_s2;
72   input       ifu_exu_save_d;
73   input       ifu_exu_restore_d;
74   input       ifu_exu_saved_e;
75   input       ifu_exu_restored_e;
76   input       ifu_exu_flushw_e;
77   input [3:0] ecl_rml_thr_m;
78   input [3:0] ecl_rml_thr_w;
79   input       ecl_rml_cwp_wen_e;
80   input       ecl_rml_cansave_wen_w;
81   input       ecl_rml_canrestore_wen_w;
82   input       ecl_rml_otherwin_wen_w;
83   input       ecl_rml_wstate_wen_w;
84   input       ecl_rml_cleanwin_wen_w;
85   input [2:0] ecl_rml_xor_data_e;
86   input       ecl_rml_kill_e;// needed for oddwin updates
87   input       ecl_rml_kill_w;
88   input       ecl_rml_early_flush_w;
89   input [5:0] exu_tlu_wsr_data_w; // for wstate
90   input [1:0]   tlu_exu_agp;   // alternate global pointer
91   input         tlu_exu_agp_swap;// switch globals
92   input [1:0]   tlu_exu_agp_tid;// thread that agp refers to
93   input [2:0] tlu_exu_cwp_m;   // for switching cwp on return from trap
94   input       tlu_exu_cwpccr_update_m;
95   input       ecl_rml_inst_vld_w;
96   /*AUTOINPUT*/
97   // Beginning of automatic inputs (from unused autoinst inputs)
98   input                rst_tri_en;             // To cwp of sparc_exu_rml_cwp.v
99   input                tlu_exu_cwp_retry_m;    // To cwp of sparc_exu_rml_cwp.v
100   // End of automatics
101
102   /*AUTOOUTPUT*/
103   // Beginning of automatic outputs (from unused autoinst outputs)
104   output [2:0]         exu_tlu_cwp0_w;         // From cwp of sparc_exu_rml_cwp.v
105   output [2:0]         exu_tlu_cwp1_w;         // From cwp of sparc_exu_rml_cwp.v
106   output [2:0]         exu_tlu_cwp2_w;         // From cwp of sparc_exu_rml_cwp.v
107   output [2:0]         exu_tlu_cwp3_w;         // From cwp of sparc_exu_rml_cwp.v
108   output               exu_tlu_cwp_retry;      // From cwp of sparc_exu_rml_cwp.v
109   output               exu_tlu_spill_other;    // From cwp of sparc_exu_rml_cwp.v
110   output [2:0]         exu_tlu_spill_wtype;    // From cwp of sparc_exu_rml_cwp.v
111   // End of automatics
112   output               so;
113   output      exu_tlu_cwp_cmplt;
114   output [1:0] exu_tlu_cwp_cmplt_tid;
115   output [2:0]  rml_ecl_cwp_d;
116   output [2:0]  rml_ecl_cansave_d;
117   output [2:0]  rml_ecl_canrestore_d;
118   output [2:0]  rml_ecl_otherwin_d;
119   output [5:0]  rml_ecl_wstate_d;
120   output [2:0]  rml_ecl_cleanwin_d;
121   output        rml_ecl_fill_e;
122   output        rml_ecl_clean_window_e;
123   output        rml_ecl_other_e;
124   output [2:0] rml_ecl_wtype_e;
125   output       exu_ifu_spill_e;
126   output [1:0] rml_ecl_gl_e;
127
128   output [2:0]  rml_irf_old_lo_cwp_e;  // current window pointer for locals and odds
129   output [2:0]  rml_irf_new_lo_cwp_e;  // current window pointer for locals and odd
130   output [1:0]  rml_irf_old_e_cwp_e;  // current window pointer for evens
131   output [1:0]  rml_irf_new_e_cwp_e;  // current window pointer for evens
132   output        rml_irf_swap_even_e;
133   output        rml_irf_swap_odd_e;
134   output        rml_irf_swap_local_e;
135   output        rml_irf_kill_restore_w;
136   output [1:0]  rml_irf_cwpswap_tid_e;
137
138   output [3:0] rml_ecl_swap_done;
139   output       rml_ecl_rmlop_done_e;   
140   output [3:0] exu_ifu_oddwin_s;
141   output       exu_tlu_spill;
142   output [1:0] exu_tlu_spill_tid;
143   output       rml_ecl_kill_m;
144   
145   output [1:0]  rml_irf_old_agp; // alternate global pointer
146   output [1:0]  rml_irf_new_agp; // alternate global pointer
147   output        rml_irf_swap_global;
148   output [1:0]  rml_irf_global_tid;
149   output reg [11:0] current_cwp;
150   
151   wire          clk;
152   wire [1:0]    tid_d;
153   wire [3:0]    thr_d;
154   wire [1:0]    tid_e;
155   wire          rml_reset_l;
156   wire          reset;
157   wire          save_e;
158   wire          save_m;
159   wire          restore_e;
160   wire          swap_e;
161   wire          agp_wen;
162   wire [1:0]    agp_thr0;
163   wire [1:0]    agp_thr1;
164   wire [1:0]    agp_thr2;
165   wire [1:0]    agp_thr3;
166   wire [1:0]    agp_thr0_next;
167   wire [1:0]    agp_thr1_next;
168   wire [1:0]    agp_thr2_next;
169   wire [1:0]    agp_thr3_next;
170   wire          agp_wen_thr0_w;
171   wire          agp_wen_thr1_w;
172   wire          agp_wen_thr2_w;
173   wire          agp_wen_thr3_w;
174   wire [1:0]    new_agp;   
175   wire [1:0]    agp_tid;
176   wire [3:0]    agp_thr;
177   wire        full_swap_e;
178   wire   did_restore_m;
179   wire   did_restore_w;
180   wire   kill_restore_m;
181   wire   kill_restore_w;
182
183   wire [2:0]  rml_ecl_cwp_e;
184   wire [2:0]  rml_ecl_cansave_e;
185   wire [2:0]  rml_ecl_canrestore_e;
186   wire [2:0]  rml_ecl_otherwin_e;
187   wire [2:0]  rml_ecl_cleanwin_e;
188
189   wire [2:0]  rml_next_cwp_e;       
190   wire [2:0]  rml_next_cansave_e;// e-stage of rml generated new data
191   wire [2:0]  rml_next_canrestore_e;
192   wire [2:0]  rml_next_otherwin_e;
193   wire [2:0]  rml_next_cleanwin_e;
194   
195   wire [2:0]  next_cwp_e;     
196   wire [2:0]  next_cansave_e;  // e-stage of new data
197   wire [2:0]  next_canrestore_e;
198   wire [2:0]  next_otherwin_e;
199   wire [2:0]  next_cleanwin_e;
200   wire [2:0]  next_cwp_m;      // m-stage of new data
201   wire [2:0]  next_cansave_m;
202   wire [2:0]  next_canrestore_m;
203   wire [2:0]  next_otherwin_m;
204   wire [2:0]  next_cleanwin_m;
205   wire [2:0]  next_cansave_w;// w-stage of new data
206   wire [2:0]  next_canrestore_w;
207   wire [2:0]  next_otherwin_w;
208   wire [2:0]  next_cleanwin_w;
209   wire [2:0]  next_cwp_noreset_w;
210   wire [2:0]  next_cwp_w;
211
212   wire   rml_cwp_wen_e;        // wen for cwp from rml
213   wire   rml_cwp_wen_m;        // wen for cwp from rml
214   wire [2:0] spill_cwp_e;      // next cwp if there is a spill trap
215   wire       spill_cwp_carry0; // carry bit from spill cwp computations
216   wire       spill_cwp_carry1;
217   wire       next_cwp_sel_inc; // select line to next_cwp mux
218
219   wire        rml_cansave_wen_w;// rml generated wen
220   wire        rml_canrestore_wen_w;
221   wire        rml_otherwin_wen_w;
222   wire        rml_cleanwin_wen_w;
223
224   wire        cansave_wen_w;// wen to registers
225   wire        canrestore_wen_w;
226   wire        otherwin_wen_w;
227   wire        cleanwin_wen_w;
228   wire        cwp_wen_nokill_w;
229   wire        cwp_wen_w;
230   wire        wstate_wen_w;
231
232   wire        cwp_wen_m;       // rml generated wen w/o kills
233   wire        cansave_wen_m;
234   wire        canrestore_wen_m;
235   wire        otherwin_wen_m;
236   wire        cleanwin_wen_m;
237   wire        cansave_wen_valid_m;     // rml generated wen w/ kills
238   wire        canrestore_wen_valid_m;
239   wire        otherwin_wen_valid_m;
240   wire        cleanwin_wen_valid_m;
241
242   wire          cwp_wen_e;       // rml generated wen_e
243   wire        cansave_wen_e;
244   wire        canrestore_wen_e;
245   wire        otherwin_wen_e;
246   wire        cleanwin_wen_e;
247
248   wire        cansave_inc_e;
249   wire        canrestore_inc_e;
250
251   wire        spill_trap_save;
252   wire        spill_trap_flush;
253   wire        spill_m;
254   wire [2:0]  cleanwin_xor_canrestore;
255
256   wire        otherwin_is0_e;
257   wire        cansave_is0_e;
258   wire        canrestore_is0_e;
259
260   wire        swap_locals_ins;
261   wire        swap_outs;
262   wire [2:0]  old_cwp_e;
263   wire [2:0]  new_cwp_e;
264
265   wire [2:0]   rml_ecl_wtype_d;
266   wire [2:0]   rml_ecl_wtype_e;
267   wire         rml_ecl_other_d;
268   wire         rml_ecl_other_e;
269   wire        exu_tlu_spill_e;
270   wire         rml_ecl_kill_e;
271   wire         rml_kill_w;
272   wire         vld_w;
273   wire         win_trap_e;
274   wire         win_trap_m;
275   wire         win_trap_w;
276
277   assign       clk = rclk;
278   // Reset flop
279    dffrl_async rstff(.din (grst_l),
280                        .q   (rml_reset_l),
281                        .clk (clk),
282                        .rst_l (arst_l), .se(se), .si(), .so());
283   assign       reset = ~rml_reset_l;
284 
285   dff_s #(2) tid_s2d(.din(ifu_exu_tid_s2[1:0]), .clk(clk), .q(tid_d[1:0]), .se(se), .si(), .so());
286   dff_s #(2) tid_d2e(.din(tid_d[1:0]), .clk(clk), .q(tid_e[1:0]), .se(se), .si(), .so());
287   assign       thr_d[3] = tid_d[1] & tid_d[0];
288   assign       thr_d[2] = tid_d[1] & ~tid_d[0];
289   assign       thr_d[1] = ~tid_d[1] & tid_d[0];
290   assign       thr_d[0] = ~tid_d[1] & ~tid_d[0];
291   
292   dff_s save_d2e(.din(ifu_exu_save_d), .clk(clk), .q(save_e), .se(se), .si(), .so());
293   dff_s save_e2m(.din(save_e), .clk(clk), .q(save_m), .se(se), .si(), .so());
294   dff_s restore_d2e(.din(ifu_exu_restore_d), .clk(clk), .q(restore_e), .se(se), .si(), .so());
295
296   // don't check flush_pipe in w if caused by rml trap.  Things with a higher priority
297   // than a window trap have been accumulated into ecl_rml_kill_w
298   assign       vld_w = ecl_rml_inst_vld_w & (~ecl_rml_early_flush_w | win_trap_w);
299   assign     rml_kill_w = ecl_rml_kill_w | ~vld_w;
300
301   assign     win_trap_e = rml_ecl_fill_e | exu_tlu_spill_e | rml_ecl_clean_window_e;
302   dff_s win_trap_e2m(.din(win_trap_e), .clk(clk), .q(win_trap_m), .se(se), .si(), .so());
303   dff_s win_trap_m2w(.din(win_trap_m), .clk(clk), .q(win_trap_w), .se(se), .si(), .so());
304   
305   assign canrestore_is0_e = (~rml_ecl_canrestore_e[0] & ~rml_ecl_canrestore_e[1] 
306                              & ~rml_ecl_canrestore_e[2]);
307   assign cansave_is0_e = (~rml_ecl_cansave_e[0] & ~rml_ecl_cansave_e[1] & 
308                           ~rml_ecl_cansave_e[2]);
309   assign otherwin_is0_e = ~rml_ecl_other_e;
310
311   ///////////////////////////////////////
312   // Signals that operations are done
313   // restore/return is not signalled here
314   // because it depends on the write to the
315   // irf (computed in ecl_wb)
316   ////////////////////////////////////////
317   assign rml_ecl_rmlop_done_e = (ifu_exu_saved_e | ifu_exu_restored_e |
318                                  (ifu_exu_flushw_e & ~spill_trap_flush));
319   
320   //////////////////////////
321   // Trap generation
322   //////////////////////////
323   // Fill trap generated on restore and canrestore == 0
324   assign rml_ecl_fill_e = restore_e & canrestore_is0_e; 
325   
326   // Spill trap on save with cansave == 0
327   assign spill_trap_save = save_e & cansave_is0_e;
328   assign exu_ifu_spill_e = spill_trap_save;
329   // Spill trap on wflush with cansave != (NWINDOWS - 2 = 6)
330   assign spill_trap_flush = (ifu_exu_flushw_e & ~(rml_ecl_cansave_e[2] &
331                                                 rml_ecl_cansave_e[1] & 
332                                                 ~rml_ecl_cansave_e[0]));
333   assign exu_tlu_spill_e = (spill_trap_save | spill_trap_flush);
334   dff_s spill_e2m(.din(exu_tlu_spill_e), .clk(clk), .q(spill_m), .se(se), .si(), .so());
335
336   // Clean window trap on save w/ cleanwin - canrestore == 0
337   // or cleanwin == canrestore
338   // (not signalled on spill traps because spill is higher priority)
339   assign cleanwin_xor_canrestore = rml_ecl_cleanwin_e ^ rml_ecl_canrestore_e;
340   assign rml_ecl_clean_window_e = ~(cleanwin_xor_canrestore[2] |
341                                cleanwin_xor_canrestore[1] |
342                                cleanwin_xor_canrestore[0]) & save_e & ~exu_tlu_spill_e;
343
344   // Kill signal for w1 wen bit (all others don't care)
345   assign rml_ecl_kill_e = rml_ecl_fill_e | exu_tlu_spill_e;
346   dff_s rml_kill_e2m(.din(rml_ecl_kill_e), .clk(clk), .q(rml_ecl_kill_m),
347                    .se(se), .si(), .so());
348   
349
350   // WTYPE generation
351   assign rml_ecl_other_d = (rml_ecl_otherwin_d[0] | rml_ecl_otherwin_d[1] 
352                            | rml_ecl_otherwin_d[2]);
353   dff_s other_d2e(.din(rml_ecl_other_d), .clk(clk), .q(rml_ecl_other_e), .se(se),
354                 .si(), .so());
355   mux2ds #(3) wtype_mux(.dout(rml_ecl_wtype_d[2:0]),
356                          .in0(rml_ecl_wstate_d[2:0]),
357                          .in1(rml_ecl_wstate_d[5:3]),
358                          .sel0(~rml_ecl_other_d),
359                          .sel1(rml_ecl_other_d));
360   dff_s #(3) wtype_d2e(.din(rml_ecl_wtype_d[2:0]), .clk(clk), .q(rml_ecl_wtype_e[2:0]),
361                    .se(se), .si(), .so());
362
363
364   ////////////////////////////
365   // Interface with IRF
366   ////////////////////////////
367   assign rml_irf_old_lo_cwp_e[2:0] = old_cwp_e[2:0];
368   assign rml_irf_new_lo_cwp_e[2:0] = new_cwp_e[2:0];
369   assign rml_irf_old_e_cwp_e[1:0] = (old_cwp_e[0])? old_cwp_e[2:1] + 2'b01: old_cwp_e[2:1];
370   assign rml_irf_new_e_cwp_e[1:0] = (new_cwp_e[0])? new_cwp_e[2:1] + 2'b01: new_cwp_e[2:1];
371   
372   assign rml_irf_swap_local_e = (swap_e | swap_locals_ins);
373   assign rml_irf_swap_odd_e = ((save_e | ecl_rml_cwp_wen_e | spill_trap_flush | swap_locals_ins) & old_cwp_e[0]) | 
374                                 ((restore_e | swap_outs) & ~old_cwp_e[0]);
375   assign rml_irf_swap_even_e = ((save_e | ecl_rml_cwp_wen_e | spill_trap_flush | swap_locals_ins) & ~old_cwp_e[0]) |
376                                  ((restore_e | swap_outs) & old_cwp_e[0]);
377
378   assign swap_e = save_e | restore_e | ecl_rml_cwp_wen_e | spill_trap_flush;
379   dff_s dff_did_restore_e2m(.din(swap_e), .clk(clk),
380                       .q(did_restore_m), .se(se),
381                       .si(), .so());
382   dff_s dff_did_restore_m2w(.din(did_restore_m), .clk(clk),
383                       .q(did_restore_w), .se(se),
384                       .si(), .so());
385   // kill restore on all saves (except those that spill) and any swaps that
386   // get kill signals
387   assign kill_restore_m = (~spill_m & save_m);
388   dff_s dff_kill_restore_m2w(.din(kill_restore_m), .clk(clk), .q(kill_restore_w),
389                            .se(se), .si(), .so());
390   assign rml_irf_kill_restore_w = kill_restore_w | (did_restore_w & rml_kill_w);
391
392
393   ///////////////////////////////
394   // CWP logic
395   ///////////////////////////////
396   // Logic to compute next_cwp on spill trap.
397   //  CWP = CWP + CANSAVE + 2
398   assign spill_cwp_e[0] = rml_ecl_cwp_e[0] ^ rml_ecl_cansave_e[0];
399   assign spill_cwp_carry0 = rml_ecl_cwp_e[0] & rml_ecl_cansave_e[0];
400   assign spill_cwp_e[1] = rml_ecl_cwp_e[1] ^ rml_ecl_cansave_e[1] ^ ~spill_cwp_carry0;
401   assign spill_cwp_carry1 = (rml_ecl_cwp_e[1] | rml_ecl_cansave_e[1] |
402                              spill_cwp_carry0) & ~(rml_ecl_cwp_e[1] &
403                                                    rml_ecl_cansave_e[1] &
404                                                    spill_cwp_carry0);
405   assign spill_cwp_e[2] = rml_ecl_cwp_e[2] ^ rml_ecl_cansave_e[2] ^ spill_cwp_carry1;
406
407   assign rml_cwp_wen_e = (save_e | restore_e) & ~exu_tlu_spill_e;
408   assign cwp_wen_e = (rml_cwp_wen_e | ecl_rml_cwp_wen_e) & ~ecl_rml_kill_e;
409   sparc_exu_rml_inc3 cwp_inc(.dout(rml_next_cwp_e[2:0]), .din(rml_ecl_cwp_e[2:0]),
410                                  .inc(save_e));
411
412   assign     next_cwp_sel_inc = ~(ecl_rml_cwp_wen_e | exu_tlu_spill_e);
413   mux3ds #(3) next_cwp_mux(.dout(next_cwp_e[2:0]), 
414                          .in0(rml_next_cwp_e[2:0]),
415                          .in1(ecl_rml_xor_data_e[2:0]),
416                          .in2(spill_cwp_e[2:0]),
417                          .sel0(next_cwp_sel_inc),
418                          .sel1(ecl_rml_cwp_wen_e),
419                          .sel2(exu_tlu_spill_e));
420
421   dff_s cwp_wen_e2m(.din(cwp_wen_e), .clk(clk), .q(rml_cwp_wen_m),
422                       .se(se), .si(), .so());
423   dff_s #(3) next_cwp_e2m(.din(next_cwp_e[2:0]), .clk(clk), .q(next_cwp_m[2:0]),
424                           .se(se), .si(), .so());
425   assign     cwp_wen_m = rml_cwp_wen_m;
426   dff_s #(3) next_cwp_m2w(.din(next_cwp_m[2:0]), .clk(clk), .q(next_cwp_noreset_w[2:0]),
427                         .se(se), .si(), .so());
428   dff_s cwp_wen_m2w(.din(cwp_wen_m), .clk(clk), .q(cwp_wen_nokill_w),
429                       .se(se), .si(), .so());
430   assign cwp_wen_w = cwp_wen_nokill_w & ~rml_kill_w;
431   assign next_cwp_w[2:0] = next_cwp_noreset_w[2:0];
432
433   assign full_swap_e = (exu_tlu_spill_e | ecl_rml_cwp_wen_e);
434
435
436   // oddwin signal for ifu needs bypass from w.  It is done in M and staged for timing.
437   // This is possible because the thread is switched out so there is only one bypass condition.
438   // Only save/return will switch in fast enough for a bypass so this is the only write condition
439   // we need to check
440   wire [3:0] oddwin_m;
441   wire [3:0] oddwin_w;
442   assign     oddwin_m[3] = (cwp_wen_m & ecl_rml_thr_m[3])? next_cwp_m[0]: oddwin_w[3];
443   assign     oddwin_m[2] = (cwp_wen_m & ecl_rml_thr_m[2])? next_cwp_m[0]: oddwin_w[2];
444   assign     oddwin_m[1] = (cwp_wen_m & ecl_rml_thr_m[1])? next_cwp_m[0]: oddwin_w[1];
445   assign     oddwin_m[0] = (cwp_wen_m & ecl_rml_thr_m[0])? next_cwp_m[0]: oddwin_w[0];
446   dff_s #(4) oddwin_dff(.din(oddwin_m[3:0]), .clk(clk), .q(exu_ifu_oddwin_s[3:0]),
447                       .se(se), .si(), .so());
448
449   integer i;
450   wire [11:0] next_cwp;
451   always @(posedge clk)
452      begin
453         current_cwp[2:0]<=(cwp_wen_m & ecl_rml_thr_m[0])? next_cwp_m: next_cwp[2:0];
454         current_cwp[5:3]<=(cwp_wen_m & ecl_rml_thr_m[1])? next_cwp_m: next_cwp[5:3];
455         current_cwp[8:6]<=(cwp_wen_m & ecl_rml_thr_m[2])? next_cwp_m: next_cwp[8:6];
456         current_cwp[11:9]<=(cwp_wen_m & ecl_rml_thr_m[3])? next_cwp_m: next_cwp[11:9];
457      end
458     
459   sparc_exu_rml_cwp cwp(
460                         .swap_outs     (swap_outs),
461                         .swap_locals_ins(swap_locals_ins),
462                         .rml_ecl_cwp_e (rml_ecl_cwp_e[2:0]),
463                         .old_cwp_e     (old_cwp_e[2:0]),
464                         .new_cwp_e     (new_cwp_e[2:0]),
465                         .oddwin_w     (oddwin_w[3:0]),
466                         .next_cwp     (next_cwp),
467                         /*AUTOINST*/
468                         // Outputs
469                         .rml_ecl_cwp_d (rml_ecl_cwp_d[2:0]),
470                         .exu_tlu_cwp0_w(exu_tlu_cwp0_w[2:0]),
471                         .exu_tlu_cwp1_w(exu_tlu_cwp1_w[2:0]),
472                         .exu_tlu_cwp2_w(exu_tlu_cwp2_w[2:0]),
473                         .exu_tlu_cwp3_w(exu_tlu_cwp3_w[2:0]),
474                         .rml_irf_cwpswap_tid_e(rml_irf_cwpswap_tid_e[1:0]),
475                         .exu_tlu_spill (exu_tlu_spill),
476                         .exu_tlu_spill_wtype(exu_tlu_spill_wtype[2:0]),
477                         .exu_tlu_spill_other(exu_tlu_spill_other),
478                         .exu_tlu_spill_tid(exu_tlu_spill_tid[1:0]),
479                         .rml_ecl_swap_done(rml_ecl_swap_done[3:0]),
480                         .exu_tlu_cwp_cmplt(exu_tlu_cwp_cmplt),
481                         .exu_tlu_cwp_cmplt_tid(exu_tlu_cwp_cmplt_tid[1:0]),
482                         .exu_tlu_cwp_retry(exu_tlu_cwp_retry),
483                         // Inputs
484                         .clk           (clk),
485                         .se            (se),
486                         .reset         (reset),
487                         .rst_tri_en    (rst_tri_en),
488                         .rml_ecl_wtype_e(rml_ecl_wtype_e[2:0]),
489                         .rml_ecl_other_e(rml_ecl_other_e),
490                         .exu_tlu_spill_e(exu_tlu_spill_e),
491                         .tlu_exu_cwpccr_update_m(tlu_exu_cwpccr_update_m),
492                         .tlu_exu_cwp_retry_m(tlu_exu_cwp_retry_m),
493                         .tlu_exu_cwp_m (tlu_exu_cwp_m[2:0]),
494                         .thr_d         (thr_d[3:0]),
495                         .ecl_rml_thr_m (ecl_rml_thr_m[3:0]),
496                         .ecl_rml_thr_w (ecl_rml_thr_w[3:0]),
497                         .tid_e         (tid_e[1:0]),
498                         .next_cwp_w    (next_cwp_w[2:0]),
499                         .next_cwp_e    (next_cwp_e[2:0]),
500                         .cwp_wen_w     (cwp_wen_w),
501                         .save_e        (save_e),
502                         .restore_e     (restore_e),
503                         .ifu_exu_flushw_e(ifu_exu_flushw_e),
504                         .ecl_rml_cwp_wen_e(ecl_rml_cwp_wen_e),
505                         .full_swap_e   (full_swap_e),
506                         .rml_kill_w    (rml_kill_w));
507
508   ///////////////////////////////
509   // Cansave logic
510   ///////////////////////////////
511   assign cansave_wen_e = ((save_e & ~cansave_is0_e & ~rml_ecl_clean_window_e) |
512                           ifu_exu_saved_e |
513                           (restore_e & ~canrestore_is0_e) |
514                           (ifu_exu_restored_e & otherwin_is0_e));
515   sparc_exu_rml_inc3 cansave_inc(.dout(rml_next_cansave_e[2:0]), .din(rml_ecl_cansave_e[2:0]),
516                                  .inc(cansave_inc_e));
517   assign cansave_inc_e = restore_e | ifu_exu_saved_e;
518
519   mux2ds #(3) next_cansave_mux(.dout(next_cansave_e[2:0]),
520                              .in0(ecl_rml_xor_data_e[2:0]),
521                              .in1(rml_next_cansave_e[2:0]),
522                              .sel0(~cansave_wen_e),
523                              .sel1(cansave_wen_e));
524   dff_s cansave_wen_e2m(.din(cansave_wen_e), .clk(clk), .q(cansave_wen_m),
525                       .se(se), .si(), .so());
526   dff_s #(3) next_cansave_e2m(.din(next_cansave_e[2:0]), .clk(clk), .q(next_cansave_m[2:0]),
527                           .se(se), .si(), .so());
528   assign cansave_wen_valid_m = cansave_wen_m;
529   dff_s cansave_wen_m2w(.din(cansave_wen_valid_m), .clk(clk), .q(rml_cansave_wen_w),
530                       .se(se), .si(), .so());
531   dff_s #(3) next_cansave_m2w(.din(next_cansave_m[2:0]), .clk(clk), .q(next_cansave_w[2:0]),
532                           .se(se), .si(), .so());
533   assign cansave_wen_w = (rml_cansave_wen_w | ecl_rml_cansave_wen_w) & ~rml_kill_w;
534
535   ///////////////////////////////
536   // Canrestore logic
537   ///////////////////////////////
538   assign canrestore_wen_e = ((save_e & ~cansave_is0_e & ~rml_ecl_clean_window_e) |
539                              ifu_exu_restored_e |
540                              (restore_e & ~canrestore_is0_e) |
541                              (ifu_exu_saved_e & otherwin_is0_e));
542   sparc_exu_rml_inc3 canrestore_inc(.dout(rml_next_canrestore_e[2:0]),
543                                     .din(rml_ecl_canrestore_e[2:0]),
544                                     .inc(canrestore_inc_e));
545   assign canrestore_inc_e = ifu_exu_restored_e | save_e;
546   
547   mux2ds #(3) next_canrestore_mux(.dout(next_canrestore_e[2:0]),
548                                    .in0(ecl_rml_xor_data_e[2:0]),
549                                    .in1(rml_next_canrestore_e[2:0]),
550                                    .sel0(~canrestore_wen_e),
551                                    .sel1(canrestore_wen_e));
552   dff_s canrestore_wen_e2m(.din(canrestore_wen_e), .clk(clk), .q(canrestore_wen_m),
553                       .se(se), .si(), .so());
554   dff_s #(3) next_canrestore_e2m(.din(next_canrestore_e[2:0]), .clk(clk), .q(next_canrestore_m[2:0]),
555                           .se(se), .si(), .so());
556   assign canrestore_wen_valid_m = canrestore_wen_m;
557   dff_s canrestore_wen_m2w(.din(canrestore_wen_valid_m), .clk(clk), .q(rml_canrestore_wen_w),
558                       .se(se), .si(), .so());
559   dff_s #(3) next_canrestore_m2w(.din(next_canrestore_m[2:0]), .clk(clk), .q(next_canrestore_w[2:0]),
560                           .se(se), .si(), .so());
561   assign canrestore_wen_w = (rml_canrestore_wen_w | ecl_rml_canrestore_wen_w) & ~rml_kill_w;
562
563   ///////////////////////////////
564   // Otherwin logic
565   ///////////////////////////////
566   // Decrements on saved or restored if otherwin != 0
567   assign otherwin_wen_e = ((ifu_exu_saved_e | ifu_exu_restored_e) 
568                            & ~otherwin_is0_e);
569   assign rml_next_otherwin_e[2] = ((rml_ecl_otherwin_e[2] & rml_ecl_otherwin_e[1]) |
570                                (rml_ecl_otherwin_e[2] & rml_ecl_otherwin_e[0]));
571   assign rml_next_otherwin_e[1] = rml_ecl_otherwin_e[1] ^ ~rml_ecl_otherwin_e[0];
572   assign rml_next_otherwin_e[0] = ~rml_ecl_otherwin_e[0];
573
574   mux2ds #(3) next_otherwin_mux(.dout(next_otherwin_e[2:0]),
575                               .in0(ecl_rml_xor_data_e[2:0]),
576                               .in1(rml_next_otherwin_e[2:0]),
577                               .sel0(~otherwin_wen_e),
578                               .sel1(otherwin_wen_e));
579   dff_s otherwin_wen_e2m(.din(otherwin_wen_e), .clk(clk), .q(otherwin_wen_m),
580                       .se(se), .si(), .so());
581   dff_s #(3) next_otherwin_e2m(.din(next_otherwin_e[2:0]), .clk(clk), .q(next_otherwin_m[2:0]),
582                           .se(se), .si(), .so());
583   assign otherwin_wen_valid_m = otherwin_wen_m;
584   dff_s otherwin_wen_m2w(.din(otherwin_wen_valid_m), .clk(clk), .q(rml_otherwin_wen_w),
585                       .se(se), .si(), .so());
586   dff_s #(3) next_otherwin_m2w(.din(next_otherwin_m[2:0]), .clk(clk), .q(next_otherwin_w[2:0]),
587                           .se(se), .si(), .so());
588   assign otherwin_wen_w = (rml_otherwin_wen_w | ecl_rml_otherwin_wen_w) & ~rml_kill_w;
589
590   ///////////////////////////////
591   // Cleanwin logic
592   ///////////////////////////////
593   // increments on restored if cleanwin != 7
594   assign cleanwin_wen_e = (ifu_exu_restored_e &
595                            ~(rml_ecl_cleanwin_e[2] & rml_ecl_cleanwin_e[1] 
596                              & rml_ecl_cleanwin_e[0]));
597   assign rml_next_cleanwin_e[2] = ((~rml_ecl_cleanwin_e[2] & rml_ecl_cleanwin_e[1] 
598                                 & rml_ecl_cleanwin_e[0]) | rml_ecl_cleanwin_e[2]);
599   assign rml_next_cleanwin_e[1] = rml_ecl_cleanwin_e[1] ^ rml_ecl_cleanwin_e[0];
600   assign rml_next_cleanwin_e[0] = ~rml_ecl_cleanwin_e[0];
601   
602   mux2ds #(3) next_cleanwin_mux(.dout(next_cleanwin_e[2:0]),
603                                  .in0(ecl_rml_xor_data_e[2:0]),
604                                  .in1(rml_next_cleanwin_e[2:0]),
605                                  .sel0(~cleanwin_wen_e),
606                                  .sel1(cleanwin_wen_e));
607   dff_s cleanwin_wen_e2m(.din(cleanwin_wen_e), .clk(clk), .q(cleanwin_wen_m),
608                       .se(se), .si(), .so());
609   dff_s #(3) next_cleanwin_e2m(.din(next_cleanwin_e[2:0]), .clk(clk), .q(next_cleanwin_m[2:0]),
610                           .se(se), .si(), .so());
611   assign cleanwin_wen_valid_m = cleanwin_wen_m;
612   dff_s cleanwin_wen_m2w(.din(cleanwin_wen_valid_m), .clk(clk), .q(rml_cleanwin_wen_w),
613                       .se(se), .si(), .so());
614   dff_s #(3) next_cleanwin_m2w(.din(next_cleanwin_m[2:0]), .clk(clk), .q(next_cleanwin_w[2:0]),
615                           .se(se), .si(), .so());
616   assign cleanwin_wen_w = (rml_cleanwin_wen_w | ecl_rml_cleanwin_wen_w) & ~rml_kill_w;
617
618   ///////////////////////////////
619   // WSTATE logic
620   ///////////////////////////////
621   assign wstate_wen_w = ecl_rml_wstate_wen_w & ~rml_kill_w;
622
623   ///////////////////////////////
624   // Storage of other WMRs
625   ///////////////////////////////
626   sparc_exu_reg  cansave_reg(.clk(clk), .se(se),
627                                .data_out(rml_ecl_cansave_d[2:0]), .thr_out(thr_d[3:0]), 
628                                .thr_w(ecl_rml_thr_w[3:0]),
629                              .wen_w(cansave_wen_w), .data_in_w(next_cansave_w[2:0]));
630   dff_s #(3) cansave_d2e(.din(rml_ecl_cansave_d[2:0]), .clk(clk), .q(rml_ecl_cansave_e[2:0]), .se(se),
631                  .si(), .so());
632   sparc_exu_reg  canrestore_reg(.clk(clk), .se(se),
633                                   .data_out(rml_ecl_canrestore_d[2:0]), .thr_out(thr_d[3:0]),
634                                   .thr_w(ecl_rml_thr_w[3:0]),
635                                   .wen_w(canrestore_wen_w),
636                                   .data_in_w(next_canrestore_w[2:0]));
637   dff_s #(3) canrestore_d2e(.din(rml_ecl_canrestore_d[2:0]), .clk(clk), .q(rml_ecl_canrestore_e[2:0]),
638                         .se(se), .si(), .so());
639   sparc_exu_reg  otherwin_reg(.clk(clk), .se(se),
640                                 .data_out(rml_ecl_otherwin_d[2:0]), .thr_out(thr_d[3:0]),
641                                 .thr_w(ecl_rml_thr_w[3:0]),
642                                 .wen_w(otherwin_wen_w), .data_in_w(next_otherwin_w[2:0]));
643   dff_s #(3) otherwin_d2e(.din(rml_ecl_otherwin_d[2:0]), .clk(clk), .q(rml_ecl_otherwin_e[2:0]),
644                       .se(se), .si(), .so());
645   sparc_exu_reg  cleanwin_reg(.clk(clk), .se(se),
646                                 .data_out(rml_ecl_cleanwin_d[2:0]), .thr_out(thr_d[3:0]),
647                                 .thr_w(ecl_rml_thr_w[3:0]),
648                                 .wen_w(cleanwin_wen_w), .data_in_w(next_cleanwin_w[2:0]));
649   dff_s #(3) cleanwin_d2e(.din(rml_ecl_cleanwin_d[2:0]), .clk(clk), .q(rml_ecl_cleanwin_e[2:0]),
650                       .se(se), .si(), .so());
651   sparc_exu_reg hi_wstate_reg(.clk(clk), .se(se),
652                               .data_out(rml_ecl_wstate_d[5:3]), .thr_out(thr_d[3:0]),
653                               .thr_w(ecl_rml_thr_w[3:0]),
654                               .wen_w(wstate_wen_w), 
655                               .data_in_w(exu_tlu_wsr_data_w[5:3]));
656   sparc_exu_reg lo_wstate_reg(.clk(clk), .se(se),
657                               .data_out(rml_ecl_wstate_d[2:0]), .thr_out(thr_d[3:0]),
658                               .thr_w(ecl_rml_thr_w[3:0]),
659                               .wen_w(wstate_wen_w), 
660                               .data_in_w(exu_tlu_wsr_data_w[2:0]));
661
662
663   /////////////////////////////////
664   // Alternate Globals control
665   //----------------------------
666   /////////////////////////////////
667   assign rml_irf_new_agp[1:0] = tlu_exu_agp[1:0];
668   assign agp_tid[1:0] = tlu_exu_agp_tid[1:0];
669
670`ifdef FPGA_SYN_1THREAD
671   assign rml_irf_old_agp[1:0] = agp_thr0[1:0];
672   assign        agp_wen_thr0_w = (agp_thr[0] & agp_wen) | reset;   
673   // mux between new and current value
674   mux2ds #(2) agp_next0_mux(.dout(agp_thr0_next[1:0]),
675                               .in0(agp_thr0[1:0]),
676                               .in1(new_agp[1:0]),
677                               .sel0(~agp_wen_thr0_w),
678                               .sel1(agp_wen_thr0_w));
679   dff_s #(2) dff_agp_thr0(.din(agp_thr0_next[1:0]), .clk(clk), .q(agp_thr0[1:0]),
680                       .se(se), .si(), .so());
681   // generation of controls
682   assign        agp_wen = tlu_exu_agp_swap;
683   assign        rml_irf_swap_global = agp_wen;
684   assign        rml_irf_global_tid[1:0] = agp_tid[1:0];
685
686   // decode tids
687   assign        agp_thr[0] = ~agp_tid[1] & ~agp_tid[0];
688      // Decode agp input
689   assign new_agp[1:0] = rml_irf_new_agp[1:0] | {2{reset}};
690
691   // send current global level to ecl for error logging
692   assign rml_ecl_gl_e[1:0] = agp_thr0[1:0];
693   
694`else
695           
696   //  Output selection for current agp
697   mux4ds #(2) mux_agp_out1(.dout(rml_irf_old_agp[1:0]), 
698                            .sel0(agp_thr[0]),
699                            .sel1(agp_thr[1]),
700                            .sel2(agp_thr[2]),
701                            .sel3(agp_thr[3]),
702                            .in0(agp_thr0[1:0]),
703                            .in1(agp_thr1[1:0]),
704                            .in2(agp_thr2[1:0]),
705                            .in3(agp_thr3[1:0]));
706
707   //////////////////////////////////////
708   //  Storage of agp
709   //////////////////////////////////////
710   
711   // enable input for each thread
712   assign        agp_wen_thr0_w = (agp_thr[0] & agp_wen) | reset;
713   assign        agp_wen_thr1_w = (agp_thr[1] & agp_wen) | reset;
714   assign        agp_wen_thr2_w = (agp_thr[2] & agp_wen) | reset;
715   assign        agp_wen_thr3_w = (agp_thr[3] & agp_wen) | reset;
716
717   // mux between new and current value
718   mux2ds #(2) agp_next0_mux(.dout(agp_thr0_next[1:0]),
719                               .in0(agp_thr0[1:0]),
720                               .in1(new_agp[1:0]),
721                               .sel0(~agp_wen_thr0_w),
722                               .sel1(agp_wen_thr0_w));
723   mux2ds #(2) agp_next1_mux(.dout(agp_thr1_next[1:0]),
724                               .in0(agp_thr1[1:0]),
725                               .in1(new_agp[1:0]),
726                               .sel0(~agp_wen_thr1_w),
727                               .sel1(agp_wen_thr1_w));
728   mux2ds #(2) agp_next2_mux(.dout(agp_thr2_next[1:0]),
729                               .in0(agp_thr2[1:0]),
730                               .in1(new_agp[1:0]),
731                               .sel0(~agp_wen_thr2_w),
732                               .sel1(agp_wen_thr2_w));
733   mux2ds #(2) agp_next3_mux(.dout(agp_thr3_next[1:0]),
734                               .in0(agp_thr3[1:0]),
735                               .in1(new_agp[1:0]),
736                               .sel0(~agp_wen_thr3_w),
737                               .sel1(agp_wen_thr3_w));
738
739   // store new value
740   dff_s #(2) dff_agp_thr0(.din(agp_thr0_next[1:0]), .clk(clk), .q(agp_thr0[1:0]),
741                       .se(se), .si(), .so());
742   dff_s #(2) dff_agp_thr1(.din(agp_thr1_next[1:0]), .clk(clk), .q(agp_thr1[1:0]),
743                       .se(se), .si(), .so());
744   dff_s #(2) dff_agp_thr2(.din(agp_thr2_next[1:0]), .clk(clk), .q(agp_thr2[1:0]),
745                       .se(se), .si(), .so());
746   dff_s #(2) dff_agp_thr3(.din(agp_thr3_next[1:0]), .clk(clk), .q(agp_thr3[1:0]),
747                       .se(se), .si(), .so());
748   
749   // generation of controls
750   assign        agp_wen = tlu_exu_agp_swap;
751   assign        rml_irf_swap_global = agp_wen;
752   assign        rml_irf_global_tid[1:0] = agp_tid[1:0];
753
754   // decode tids
755   assign        agp_thr[0] = ~agp_tid[1] & ~agp_tid[0];
756   assign        agp_thr[1] = ~agp_tid[1] & agp_tid[0];
757   assign        agp_thr[2] = agp_tid[1] & ~agp_tid[0];
758   assign        agp_thr[3] = agp_tid[1] & agp_tid[0];
759   
760   // Decode agp input
761   assign new_agp[1:0] = rml_irf_new_agp[1:0] | {2{reset}};
762
763   // send current global level to ecl for error logging
764   assign rml_ecl_gl_e[1:0] = ((tid_e[1:0] == 2'b00)? agp_thr0[1:0]:
765                               (tid_e[1:0] == 2'b01)? agp_thr1[1:0]:
766                               (tid_e[1:0] == 2'b10)? agp_thr2[1:0]:
767                                                              agp_thr3[1:0]);
768`endif // !`ifdef FPGA_SYN_1THREAD
769   
770endmodule // sparc_exu_rml
Note: See TracBrowser for help on using the repository browser.