Initial commit of OpenSPARC T2 design and verification files.
[OpenSPARC-T2-DV] / verif / env / common / verilog / tlb_sync / tlb_fifo.v
CommitLineData
86530b38
AT
1// ========== Copyright Header Begin ==========================================
2//
3// OpenSPARC T2 Processor File: tlb_fifo.v
4// Copyright (C) 1995-2007 Sun Microsystems, Inc. All Rights Reserved
5// 4150 Network Circle, Santa Clara, California 95054, U.S.A.
6//
7// * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
8//
9// This program is free software; you can redistribute it and/or modify
10// it under the terms of the GNU General Public License as published by
11// the Free Software Foundation; version 2 of the License.
12//
13// This program is distributed in the hope that it will be useful,
14// but WITHOUT ANY WARRANTY; without even the implied warranty of
15// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16// GNU General Public License for more details.
17//
18// You should have received a copy of the GNU General Public License
19// along with this program; if not, write to the Free Software
20// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21//
22// For the avoidance of doubt, and except that if any non-GPL license
23// choice is available it will apply instead, Sun elects to use only
24// the General Public License version 2 (GPLv2) at this time for any
25// software where a choice of GPL license versions is made
26// available with the language indicating that GPLv2 or any later version
27// may be used, or where a choice of which version of the GPL is applied is
28// otherwise unspecified.
29//
30// Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
31// CA 95054 USA or visit www.sun.com if you need additional information or
32// have any questions.
33//
34// ========== Copyright Header End ============================================
35`ifdef CORE_0
36
37module tlb_fifo_c0 (
38
39 // Inputs
40 mytid,
41
42 // Outputs
43 itlb_pipe_d
44);
45
46`include "tlb_sync.vh"
47
48// FIFO_DEPTH is 1 more than IB depth in RTL
49// so that overflow can be detected properly.
50parameter FIFO_DEPTH = 9;
51parameter PTR_WIDTH = 4;
52
53input [2:0] mytid;
54output [(`TLB_FIFO_WIDTH-1):0] itlb_pipe_d;
55`ifndef GATESIM
56
57wire [2:0] mycid;
58wire push1; // 1st signal to qualify push_select
59wire push2; // 2nd signal to qualify push_select
60wire [3:0] push_select; // 1-4 tstamps are pushed
61wire flush_upper;
62wire flush_head;
63wire pop;
64wire itlb_miss;
65wire icache_miss;
66wire fetch_bypass;
67wire exc_valid; // Exception valid
68reg ib_full;
69wire [7:0] ifu_err_vect;
70wire [3:0] ifu_err_select;
71wire [3:0] ifetch_err_vld;
72
73reg [(`TS_WIDTH-1):0] tstamp_curr;
74reg [(`TS_WIDTH-1):0] tstamp_prev;
75
76reg [(`TLB_FIFO_WIDTH-1):0] fifo [0:(FIFO_DEPTH-1)]; // reg array
77reg [(PTR_WIDTH-1):0] pop_ptr;
78reg [(PTR_WIDTH-1):0] push_ptr;
79reg [(`TLB_FIFO_WIDTH-1):0] itlb_pipe_d;
80reg ready;
81
82//----------------------------------------------------------
83// Create wires for reg array so signals can be viewed in Debussy
84`ifdef DEBUG_TLB
85 wire [(`TLB_FIFO_WIDTH-1):0] fifo_0;
86 wire [(`TLB_FIFO_WIDTH-1):0] fifo_1;
87 wire [(`TLB_FIFO_WIDTH-1):0] fifo_2;
88 wire [(`TLB_FIFO_WIDTH-1):0] fifo_3;
89 wire [(`TLB_FIFO_WIDTH-1):0] fifo_4;
90 wire [(`TLB_FIFO_WIDTH-1):0] fifo_5;
91 wire [(`TLB_FIFO_WIDTH-1):0] fifo_6;
92 wire [(`TLB_FIFO_WIDTH-1):0] fifo_7;
93 wire [(`TLB_FIFO_WIDTH-1):0] fifo_8;
94 wire [(`TLB_FIFO_WIDTH-1):0] fifo_9;
95
96 assign fifo_0 = fifo[0];
97 assign fifo_1 = fifo[1];
98 assign fifo_2 = fifo[2];
99 assign fifo_3 = fifo[3];
100 assign fifo_4 = fifo[4];
101 assign fifo_5 = fifo[5];
102 assign fifo_6 = fifo[6];
103 assign fifo_7 = fifo[7];
104 assign fifo_8 = fifo[8];
105 assign fifo_9 = fifo[9];
106`endif
107
108
109//----------------------------------------------------------
110// DUT probes
111
112assign mycid = 0;
113assign push1 = `SPC0.ifu_ftu.ftu_fetch_thr_c[mytid];
114assign push2 = `SPC0.ifu_ftu.ftu_ibu_redirect_bf[mytid];
115assign push_select = `SPC0.ifu_ftu.ftu_instr_valid_c;
116assign flush_upper = `SPC0.pku.pku_flush_upper_buffer[mytid];
117assign flush_head = `SPC0.pku.pku_flush_buffer0[mytid];
118assign pop = `SPC0.pku.pku_pick_p[mytid];
119assign itlb_miss = `PROBES0.itlb_miss[mytid];
120assign icache_miss = `PROBES0.icache_miss[mytid];
121assign fetch_bypass = `PROBES0.fetch_bypass[mytid];
122assign exc_valid = `SPC0.ifu_ftu.ftu_exception_valid_c;
123
124// Error Injection - tlb_sync is pipelining some information that is useful to error injection code.
125`ifdef TLB_FIFO_WIDE
126assign ifu_err_vect = {tb_top.ras.ifu_err.ifu_err_code_c[4:0],tb_top.ras.ifu_err.ifu_err_way[2:0]};
127assign ifu_err_select = tb_top.ras.ifu_err.ifu_err_select[3:0];
128assign ifetch_err_vld = tb_top.ras.ifu_err.ifetch_err_vld[3:0];
129`else
130assign ifu_err_vect = 8'b0;
131assign ifu_err_select = 4'b0;
132assign ifetch_err_vld = 4'b0;
133`endif
134
135//----------------------------------------------------------
136initial begin // {
137 ready = 0;
138 @ (posedge `SPC0.l2clk);
139 // Initialize fifo
140 fifo_clear;
141 itlb_pipe_d = 0;
142 ready = `PARGS.tlb_sync_on;
143end // }
144
145//----------------------------------------------------------
146// push/pop from FIFO
147
148always @ (posedge (`SPC0.l2clk & ready)) begin // {
149
150 // Save tstamp if L1 Icache miss & ITLB hit (for later use if bypass)
151 if (icache_miss & !itlb_miss) begin // {
152 tstamp_prev = `TOP.core_cycle_cnt - 2;
153 end // }
154
155
156 // if POR|WMR, then no TLBread
157 if (`TOP.in_reset_core) begin // {
158 fifo_clear;
159 end // }
160 else begin // {
161
162 itlb_pipe_d <= pop ? fifo[pop_ptr] : itlb_pipe_d; // Get new value or hold state
163
164
165 //------------------------
166 // Pop FIFO - special case
167
168 // This code must be above the Push FIFO code.
169 // to handle the case if (flush_head and push and IB was empty)
170 // Only flush_head if fifo is not empty
171 // Don't need to qualify with flush_upper because the buffer will
172 // be cleared by code below.
173 if (flush_head && (pop_ptr != push_ptr)) begin // {
174 fifo_pop;
175 end // }
176
177 //------------------------
178 // Push FIFO
179
180 // push_select may be asserted at same time as exc_valid.
181 // exc_valid should override.
182
183 // If exc_valid, I must push 2 valid tstamp in IB before making IB full.
184 // this is because the exception instruction will get to W and will
185 // need a ITLB_READ tstamp.
186 // exc_valid will only be asserted if there is room in IB for 4 entries
187 // so it is safe to push 2 entries.
188 // It is required to push 2 because the 1st entry may be DS of annul branch,
189 // then the exception happens on next instruction after DS.
190
191 if (exc_valid && push1 && !push2 && !flush_upper) begin // {
192
193 // It is possible to get back-to-back exceptions.
194 // So, need to check for fifo full before fifo_push.
195 // It is possible to have only 1 entry available after the 1 exception.
196 // if there was a pop at the same time as the exception.
197
198 ib_full = (pop_ptr==0) ? (push_ptr==(FIFO_DEPTH-1)): (push_ptr==(pop_ptr-1));
199 if (!ib_full) begin // {
200 fifo_push(ifu_err_select[0], ifetch_err_vld[0]);
201 end // }
202
203 ib_full = (pop_ptr==0) ? (push_ptr==(FIFO_DEPTH-1)): (push_ptr==(pop_ptr-1));
204 if (!ib_full) begin // {
205 fifo_push(ifu_err_select[1], ifetch_err_vld[1]);
206 end // }
207 end // }
208
209 else begin // {
210
211 if (push_select[0] && push1 && !push2) begin // {
212 fifo_push(ifu_err_select[0], ifetch_err_vld[0]);
213 end // }
214
215 if (push_select[1] && push1 && !push2) begin // {
216 fifo_push(ifu_err_select[1], ifetch_err_vld[1]);
217 end // }
218
219 if (push_select[2] && push1 && !push2) begin // {
220 fifo_push(ifu_err_select[2], ifetch_err_vld[2]);
221 end // }
222
223 if (push_select[3] && push1 && !push2) begin // {
224 fifo_push(ifu_err_select[3], ifetch_err_vld[3]);
225 end // }
226
227 end // }
228
229 //------------------------
230 // Pop FIFO
231
232 // It is possible to push and flush_upper in the same cycle.
233 // If this happens, flush_upper takes priority.
234 // So, flush code must be after push code since same always block.
235
236 // If flush_head and push in same cycle, there will be 1 entry in IB.
237 // Essentially, flush_head is ignored, then an entry is pushed.
238
239
240 case ({flush_upper, flush_head, pop}) // {
241 3'b000: begin
242 // NOP
243 end
244 3'b001: begin
245 fifo_pop;
246 end
247 3'b010: begin
248 // NOP - case handled in code above
249 end
250 3'b011: begin
251 `PR_ERROR ("tlb_sync", `ERROR,
252 "C%0d T%0d Illegal signal combination for IB. flush_upper=%0b flush_head=%0b pick=%0b",
253 mycid,mytid,flush_upper,flush_head,pop);
254 end
255 3'b100: begin
256 // Only flush_upper if fifo is not empty
257 if (pop_ptr != push_ptr) begin // {
258 fifo_pop_upper;
259 end // }
260 end
261 3'b101: begin
262 fifo_clear;
263 end
264 3'b110: begin
265 fifo_clear;
266 end
267 3'b111: begin
268 `PR_ERROR ("tlb_sync", `ERROR,
269 "C%0d T%0d Illegal signal combination for IB. flush_upper=%0b flush_head=%0b pick=%0b",
270 mycid,mytid,flush_upper,flush_head,pop);
271 end
272 endcase // }
273
274 // It is possible to get a pop and exception.
275 // In this case, the pop will happen, then the IB is made full.
276 if (exc_valid && push1 && !push2 && !flush_upper) begin // {
277 fifo_full;
278 end // }
279
280 end // }
281end // always }
282
283//----------------------------------------------------------
284// Empty FIFO and reset push/pop pointers
285task fifo_clear;
286 integer i;
287 begin // {
288 // Initialize fifo
289 pop_ptr = 0;
290 push_ptr = 0;
291
292 for (i=0; i<FIFO_DEPTH; i=i+1) begin // {
293 fifo[i] <= 0;
294 end // }
295
296 end // }
297endtask
298
299//----------------------------------------------------------
300// Empty FIFO and reset push/pop pointers
301task fifo_full;
302 integer i;
303 begin // {
304
305 // Increment push_ptr to full buffere
306 if (pop_ptr == 0) begin // {
307 push_ptr = FIFO_DEPTH-1;
308 end // }
309 else begin // {
310 push_ptr = pop_ptr - 1;
311 end // }
312
313 end // }
314endtask
315
316//----------------------------------------------------------
317// Pop item from FIFO
318task fifo_pop;
319
320 begin // {
321
322 // Make sure the FIFO is not empty before pop
323 if (pop_ptr == push_ptr) begin // {
324 `PR_ERROR ("tlb_sync", `ERROR,
325 "C%0d T%0d IB Underflow. PKU is trying to pick from empty IB.", mycid,mytid);
326 end // }
327
328 // Clear entry in fifo
329 fifo[pop_ptr] <= 0;
330
331 // Increment pop pointer
332 if (pop_ptr==(FIFO_DEPTH-1)) begin // {
333 pop_ptr = 0;
334 end // }
335 else begin // {
336 pop_ptr = pop_ptr + 1;
337 end // }
338
339
340 end // }
341endtask
342
343//----------------------------------------------------------
344// Flush all items from FIFO except head
345task fifo_pop_upper;
346
347 integer i;
348
349 begin // {
350
351 // Make sure the FIFO is not empty
352 if (pop_ptr == push_ptr) begin // {
353 `PR_ERROR ("tlb_sync", `ERROR,
354 "C%0d T%0d IFU is trying to flush upper, but IB is empty.", mycid,mytid);
355 end // }
356
357 // Make push ptr 1 entry above pop ptr
358 if (pop_ptr==(FIFO_DEPTH-1)) begin // {
359 push_ptr = 0;
360 end // }
361 else begin // {
362 push_ptr = pop_ptr + 1;
363 end // }
364
365
366 end // }
367endtask
368
369//----------------------------------------------------------
370// Push item to FIFO
371task fifo_push;
372
373 input err_select;
374 input cache_err_vld;
375 reg [7:0] tmp_err_vect;
376
377 begin // {
378
379 tstamp_curr = `TOP.core_cycle_cnt - 2;
380
381 `ifdef TLB_FIFO_WIDE
382 tmp_err_vect = err_select ? ifu_err_vect : 8'b0;
383 fifo[push_ptr] <= fetch_bypass ? {cache_err_vld,tmp_err_vect,tstamp_prev} : {cache_err_vld,tmp_err_vect,tstamp_curr};
384 `else
385 fifo[push_ptr] <= fetch_bypass ? tstamp_prev : tstamp_curr;
386 `endif
387
388 // Increment push pointer
389 if (push_ptr==(FIFO_DEPTH-1)) begin // {
390 push_ptr = 0;
391 end // }
392 else begin // {
393 push_ptr = push_ptr + 1;
394 end // }
395
396 // Check for Overflow after push
397 if (pop_ptr == push_ptr) begin // {
398 `PR_ERROR ("tlb_sync", `ERROR,
399 "C%0d T%0d IB Overflow. IFU is trying to fetch another instruction, but IB is already full.", mycid,mytid);
400 end // }
401
402 end // }
403endtask
404
405//----------------------------------------------------------
406`endif
407endmodule
408
409`endif
410
411`ifdef CORE_1
412
413module tlb_fifo_c1 (
414
415 // Inputs
416 mytid,
417
418 // Outputs
419 itlb_pipe_d
420);
421
422`include "tlb_sync.vh"
423
424// FIFO_DEPTH is 1 more than IB depth in RTL
425// so that overflow can be detected properly.
426parameter FIFO_DEPTH = 9;
427parameter PTR_WIDTH = 4;
428
429input [2:0] mytid;
430output [(`TLB_FIFO_WIDTH-1):0] itlb_pipe_d;
431`ifndef GATESIM
432
433wire [2:0] mycid;
434wire push1; // 1st signal to qualify push_select
435wire push2; // 2nd signal to qualify push_select
436wire [3:0] push_select; // 1-4 tstamps are pushed
437wire flush_upper;
438wire flush_head;
439wire pop;
440wire itlb_miss;
441wire icache_miss;
442wire fetch_bypass;
443wire exc_valid; // Exception valid
444reg ib_full;
445wire [7:0] ifu_err_vect;
446wire [3:0] ifu_err_select;
447wire [3:0] ifetch_err_vld;
448
449reg [(`TS_WIDTH-1):0] tstamp_curr;
450reg [(`TS_WIDTH-1):0] tstamp_prev;
451
452reg [(`TLB_FIFO_WIDTH-1):0] fifo [0:(FIFO_DEPTH-1)]; // reg array
453reg [(PTR_WIDTH-1):0] pop_ptr;
454reg [(PTR_WIDTH-1):0] push_ptr;
455reg [(`TLB_FIFO_WIDTH-1):0] itlb_pipe_d;
456reg ready;
457
458//----------------------------------------------------------
459// Create wires for reg array so signals can be viewed in Debussy
460`ifdef DEBUG_TLB
461 wire [(`TLB_FIFO_WIDTH-1):0] fifo_0;
462 wire [(`TLB_FIFO_WIDTH-1):0] fifo_1;
463 wire [(`TLB_FIFO_WIDTH-1):0] fifo_2;
464 wire [(`TLB_FIFO_WIDTH-1):0] fifo_3;
465 wire [(`TLB_FIFO_WIDTH-1):0] fifo_4;
466 wire [(`TLB_FIFO_WIDTH-1):0] fifo_5;
467 wire [(`TLB_FIFO_WIDTH-1):0] fifo_6;
468 wire [(`TLB_FIFO_WIDTH-1):0] fifo_7;
469 wire [(`TLB_FIFO_WIDTH-1):0] fifo_8;
470 wire [(`TLB_FIFO_WIDTH-1):0] fifo_9;
471
472 assign fifo_0 = fifo[0];
473 assign fifo_1 = fifo[1];
474 assign fifo_2 = fifo[2];
475 assign fifo_3 = fifo[3];
476 assign fifo_4 = fifo[4];
477 assign fifo_5 = fifo[5];
478 assign fifo_6 = fifo[6];
479 assign fifo_7 = fifo[7];
480 assign fifo_8 = fifo[8];
481 assign fifo_9 = fifo[9];
482`endif
483
484
485//----------------------------------------------------------
486// DUT probes
487
488assign mycid = 1;
489assign push1 = `SPC1.ifu_ftu.ftu_fetch_thr_c[mytid];
490assign push2 = `SPC1.ifu_ftu.ftu_ibu_redirect_bf[mytid];
491assign push_select = `SPC1.ifu_ftu.ftu_instr_valid_c;
492assign flush_upper = `SPC1.pku.pku_flush_upper_buffer[mytid];
493assign flush_head = `SPC1.pku.pku_flush_buffer0[mytid];
494assign pop = `SPC1.pku.pku_pick_p[mytid];
495assign itlb_miss = `PROBES1.itlb_miss[mytid];
496assign icache_miss = `PROBES1.icache_miss[mytid];
497assign fetch_bypass = `PROBES1.fetch_bypass[mytid];
498assign exc_valid = `SPC1.ifu_ftu.ftu_exception_valid_c;
499
500// Error Injection - tlb_sync is pipelining some information that is useful to error injection code.
501`ifdef TLB_FIFO_WIDE
502assign ifu_err_vect = {tb_top.ras.ifu_err.ifu_err_code_c[4:0],tb_top.ras.ifu_err.ifu_err_way[2:0]};
503assign ifu_err_select = tb_top.ras.ifu_err.ifu_err_select[3:0];
504assign ifetch_err_vld = tb_top.ras.ifu_err.ifetch_err_vld[3:0];
505`else
506assign ifu_err_vect = 8'b0;
507assign ifu_err_select = 4'b0;
508assign ifetch_err_vld = 4'b0;
509`endif
510
511//----------------------------------------------------------
512initial begin // {
513 ready = 0;
514 @ (posedge `SPC1.l2clk);
515 // Initialize fifo
516 fifo_clear;
517 itlb_pipe_d = 0;
518 ready = `PARGS.tlb_sync_on;
519end // }
520
521//----------------------------------------------------------
522// push/pop from FIFO
523
524always @ (posedge (`SPC1.l2clk & ready)) begin // {
525
526 // Save tstamp if L1 Icache miss & ITLB hit (for later use if bypass)
527 if (icache_miss & !itlb_miss) begin // {
528 tstamp_prev = `TOP.core_cycle_cnt - 2;
529 end // }
530
531
532 // if POR|WMR, then no TLBread
533 if (`TOP.in_reset_core) begin // {
534 fifo_clear;
535 end // }
536 else begin // {
537
538 itlb_pipe_d <= pop ? fifo[pop_ptr] : itlb_pipe_d; // Get new value or hold state
539
540
541 //------------------------
542 // Pop FIFO - special case
543
544 // This code must be above the Push FIFO code.
545 // to handle the case if (flush_head and push and IB was empty)
546 // Only flush_head if fifo is not empty
547 // Don't need to qualify with flush_upper because the buffer will
548 // be cleared by code below.
549 if (flush_head && (pop_ptr != push_ptr)) begin // {
550 fifo_pop;
551 end // }
552
553 //------------------------
554 // Push FIFO
555
556 // push_select may be asserted at same time as exc_valid.
557 // exc_valid should override.
558
559 // If exc_valid, I must push 2 valid tstamp in IB before making IB full.
560 // this is because the exception instruction will get to W and will
561 // need a ITLB_READ tstamp.
562 // exc_valid will only be asserted if there is room in IB for 4 entries
563 // so it is safe to push 2 entries.
564 // It is required to push 2 because the 1st entry may be DS of annul branch,
565 // then the exception happens on next instruction after DS.
566
567 if (exc_valid && push1 && !push2 && !flush_upper) begin // {
568
569 // It is possible to get back-to-back exceptions.
570 // So, need to check for fifo full before fifo_push.
571 // It is possible to have only 1 entry available after the 1 exception.
572 // if there was a pop at the same time as the exception.
573
574 ib_full = (pop_ptr==0) ? (push_ptr==(FIFO_DEPTH-1)): (push_ptr==(pop_ptr-1));
575 if (!ib_full) begin // {
576 fifo_push(ifu_err_select[0], ifetch_err_vld[0]);
577 end // }
578
579 ib_full = (pop_ptr==0) ? (push_ptr==(FIFO_DEPTH-1)): (push_ptr==(pop_ptr-1));
580 if (!ib_full) begin // {
581 fifo_push(ifu_err_select[1], ifetch_err_vld[1]);
582 end // }
583 end // }
584
585 else begin // {
586
587 if (push_select[0] && push1 && !push2) begin // {
588 fifo_push(ifu_err_select[0], ifetch_err_vld[0]);
589 end // }
590
591 if (push_select[1] && push1 && !push2) begin // {
592 fifo_push(ifu_err_select[1], ifetch_err_vld[1]);
593 end // }
594
595 if (push_select[2] && push1 && !push2) begin // {
596 fifo_push(ifu_err_select[2], ifetch_err_vld[2]);
597 end // }
598
599 if (push_select[3] && push1 && !push2) begin // {
600 fifo_push(ifu_err_select[3], ifetch_err_vld[3]);
601 end // }
602
603 end // }
604
605 //------------------------
606 // Pop FIFO
607
608 // It is possible to push and flush_upper in the same cycle.
609 // If this happens, flush_upper takes priority.
610 // So, flush code must be after push code since same always block.
611
612 // If flush_head and push in same cycle, there will be 1 entry in IB.
613 // Essentially, flush_head is ignored, then an entry is pushed.
614
615
616 case ({flush_upper, flush_head, pop}) // {
617 3'b000: begin
618 // NOP
619 end
620 3'b001: begin
621 fifo_pop;
622 end
623 3'b010: begin
624 // NOP - case handled in code above
625 end
626 3'b011: begin
627 `PR_ERROR ("tlb_sync", `ERROR,
628 "C%0d T%0d Illegal signal combination for IB. flush_upper=%0b flush_head=%0b pick=%0b",
629 mycid,mytid,flush_upper,flush_head,pop);
630 end
631 3'b100: begin
632 // Only flush_upper if fifo is not empty
633 if (pop_ptr != push_ptr) begin // {
634 fifo_pop_upper;
635 end // }
636 end
637 3'b101: begin
638 fifo_clear;
639 end
640 3'b110: begin
641 fifo_clear;
642 end
643 3'b111: begin
644 `PR_ERROR ("tlb_sync", `ERROR,
645 "C%0d T%0d Illegal signal combination for IB. flush_upper=%0b flush_head=%0b pick=%0b",
646 mycid,mytid,flush_upper,flush_head,pop);
647 end
648 endcase // }
649
650 // It is possible to get a pop and exception.
651 // In this case, the pop will happen, then the IB is made full.
652 if (exc_valid && push1 && !push2 && !flush_upper) begin // {
653 fifo_full;
654 end // }
655
656 end // }
657end // always }
658
659//----------------------------------------------------------
660// Empty FIFO and reset push/pop pointers
661task fifo_clear;
662 integer i;
663 begin // {
664 // Initialize fifo
665 pop_ptr = 0;
666 push_ptr = 0;
667
668 for (i=0; i<FIFO_DEPTH; i=i+1) begin // {
669 fifo[i] <= 0;
670 end // }
671
672 end // }
673endtask
674
675//----------------------------------------------------------
676// Empty FIFO and reset push/pop pointers
677task fifo_full;
678 integer i;
679 begin // {
680
681 // Increment push_ptr to full buffere
682 if (pop_ptr == 0) begin // {
683 push_ptr = FIFO_DEPTH-1;
684 end // }
685 else begin // {
686 push_ptr = pop_ptr - 1;
687 end // }
688
689 end // }
690endtask
691
692//----------------------------------------------------------
693// Pop item from FIFO
694task fifo_pop;
695
696 begin // {
697
698 // Make sure the FIFO is not empty before pop
699 if (pop_ptr == push_ptr) begin // {
700 `PR_ERROR ("tlb_sync", `ERROR,
701 "C%0d T%0d IB Underflow. PKU is trying to pick from empty IB.", mycid,mytid);
702 end // }
703
704 // Clear entry in fifo
705 fifo[pop_ptr] <= 0;
706
707 // Increment pop pointer
708 if (pop_ptr==(FIFO_DEPTH-1)) begin // {
709 pop_ptr = 0;
710 end // }
711 else begin // {
712 pop_ptr = pop_ptr + 1;
713 end // }
714
715
716 end // }
717endtask
718
719//----------------------------------------------------------
720// Flush all items from FIFO except head
721task fifo_pop_upper;
722
723 integer i;
724
725 begin // {
726
727 // Make sure the FIFO is not empty
728 if (pop_ptr == push_ptr) begin // {
729 `PR_ERROR ("tlb_sync", `ERROR,
730 "C%0d T%0d IFU is trying to flush upper, but IB is empty.", mycid,mytid);
731 end // }
732
733 // Make push ptr 1 entry above pop ptr
734 if (pop_ptr==(FIFO_DEPTH-1)) begin // {
735 push_ptr = 0;
736 end // }
737 else begin // {
738 push_ptr = pop_ptr + 1;
739 end // }
740
741
742 end // }
743endtask
744
745//----------------------------------------------------------
746// Push item to FIFO
747task fifo_push;
748
749 input err_select;
750 input cache_err_vld;
751 reg [7:0] tmp_err_vect;
752
753 begin // {
754
755 tstamp_curr = `TOP.core_cycle_cnt - 2;
756
757 `ifdef TLB_FIFO_WIDE
758 tmp_err_vect = err_select ? ifu_err_vect : 8'b0;
759 fifo[push_ptr] <= fetch_bypass ? {cache_err_vld,tmp_err_vect,tstamp_prev} : {cache_err_vld,tmp_err_vect,tstamp_curr};
760 `else
761 fifo[push_ptr] <= fetch_bypass ? tstamp_prev : tstamp_curr;
762 `endif
763
764 // Increment push pointer
765 if (push_ptr==(FIFO_DEPTH-1)) begin // {
766 push_ptr = 0;
767 end // }
768 else begin // {
769 push_ptr = push_ptr + 1;
770 end // }
771
772 // Check for Overflow after push
773 if (pop_ptr == push_ptr) begin // {
774 `PR_ERROR ("tlb_sync", `ERROR,
775 "C%0d T%0d IB Overflow. IFU is trying to fetch another instruction, but IB is already full.", mycid,mytid);
776 end // }
777
778 end // }
779endtask
780
781//----------------------------------------------------------
782`endif
783endmodule
784
785`endif
786
787`ifdef CORE_2
788
789module tlb_fifo_c2 (
790
791 // Inputs
792 mytid,
793
794 // Outputs
795 itlb_pipe_d
796);
797
798`include "tlb_sync.vh"
799
800// FIFO_DEPTH is 1 more than IB depth in RTL
801// so that overflow can be detected properly.
802parameter FIFO_DEPTH = 9;
803parameter PTR_WIDTH = 4;
804
805input [2:0] mytid;
806output [(`TLB_FIFO_WIDTH-1):0] itlb_pipe_d;
807`ifndef GATESIM
808
809wire [2:0] mycid;
810wire push1; // 1st signal to qualify push_select
811wire push2; // 2nd signal to qualify push_select
812wire [3:0] push_select; // 1-4 tstamps are pushed
813wire flush_upper;
814wire flush_head;
815wire pop;
816wire itlb_miss;
817wire icache_miss;
818wire fetch_bypass;
819wire exc_valid; // Exception valid
820reg ib_full;
821wire [7:0] ifu_err_vect;
822wire [3:0] ifu_err_select;
823wire [3:0] ifetch_err_vld;
824
825reg [(`TS_WIDTH-1):0] tstamp_curr;
826reg [(`TS_WIDTH-1):0] tstamp_prev;
827
828reg [(`TLB_FIFO_WIDTH-1):0] fifo [0:(FIFO_DEPTH-1)]; // reg array
829reg [(PTR_WIDTH-1):0] pop_ptr;
830reg [(PTR_WIDTH-1):0] push_ptr;
831reg [(`TLB_FIFO_WIDTH-1):0] itlb_pipe_d;
832reg ready;
833
834//----------------------------------------------------------
835// Create wires for reg array so signals can be viewed in Debussy
836`ifdef DEBUG_TLB
837 wire [(`TLB_FIFO_WIDTH-1):0] fifo_0;
838 wire [(`TLB_FIFO_WIDTH-1):0] fifo_1;
839 wire [(`TLB_FIFO_WIDTH-1):0] fifo_2;
840 wire [(`TLB_FIFO_WIDTH-1):0] fifo_3;
841 wire [(`TLB_FIFO_WIDTH-1):0] fifo_4;
842 wire [(`TLB_FIFO_WIDTH-1):0] fifo_5;
843 wire [(`TLB_FIFO_WIDTH-1):0] fifo_6;
844 wire [(`TLB_FIFO_WIDTH-1):0] fifo_7;
845 wire [(`TLB_FIFO_WIDTH-1):0] fifo_8;
846 wire [(`TLB_FIFO_WIDTH-1):0] fifo_9;
847
848 assign fifo_0 = fifo[0];
849 assign fifo_1 = fifo[1];
850 assign fifo_2 = fifo[2];
851 assign fifo_3 = fifo[3];
852 assign fifo_4 = fifo[4];
853 assign fifo_5 = fifo[5];
854 assign fifo_6 = fifo[6];
855 assign fifo_7 = fifo[7];
856 assign fifo_8 = fifo[8];
857 assign fifo_9 = fifo[9];
858`endif
859
860
861//----------------------------------------------------------
862// DUT probes
863
864assign mycid = 2;
865assign push1 = `SPC2.ifu_ftu.ftu_fetch_thr_c[mytid];
866assign push2 = `SPC2.ifu_ftu.ftu_ibu_redirect_bf[mytid];
867assign push_select = `SPC2.ifu_ftu.ftu_instr_valid_c;
868assign flush_upper = `SPC2.pku.pku_flush_upper_buffer[mytid];
869assign flush_head = `SPC2.pku.pku_flush_buffer0[mytid];
870assign pop = `SPC2.pku.pku_pick_p[mytid];
871assign itlb_miss = `PROBES2.itlb_miss[mytid];
872assign icache_miss = `PROBES2.icache_miss[mytid];
873assign fetch_bypass = `PROBES2.fetch_bypass[mytid];
874assign exc_valid = `SPC2.ifu_ftu.ftu_exception_valid_c;
875
876// Error Injection - tlb_sync is pipelining some information that is useful to error injection code.
877`ifdef TLB_FIFO_WIDE
878assign ifu_err_vect = {tb_top.ras.ifu_err.ifu_err_code_c[4:0],tb_top.ras.ifu_err.ifu_err_way[2:0]};
879assign ifu_err_select = tb_top.ras.ifu_err.ifu_err_select[3:0];
880assign ifetch_err_vld = tb_top.ras.ifu_err.ifetch_err_vld[3:0];
881`else
882assign ifu_err_vect = 8'b0;
883assign ifu_err_select = 4'b0;
884assign ifetch_err_vld = 4'b0;
885`endif
886
887//----------------------------------------------------------
888initial begin // {
889 ready = 0;
890 @ (posedge `SPC2.l2clk);
891 // Initialize fifo
892 fifo_clear;
893 itlb_pipe_d = 0;
894 ready = `PARGS.tlb_sync_on;
895end // }
896
897//----------------------------------------------------------
898// push/pop from FIFO
899
900always @ (posedge (`SPC2.l2clk & ready)) begin // {
901
902 // Save tstamp if L1 Icache miss & ITLB hit (for later use if bypass)
903 if (icache_miss & !itlb_miss) begin // {
904 tstamp_prev = `TOP.core_cycle_cnt - 2;
905 end // }
906
907
908 // if POR|WMR, then no TLBread
909 if (`TOP.in_reset_core) begin // {
910 fifo_clear;
911 end // }
912 else begin // {
913
914 itlb_pipe_d <= pop ? fifo[pop_ptr] : itlb_pipe_d; // Get new value or hold state
915
916
917 //------------------------
918 // Pop FIFO - special case
919
920 // This code must be above the Push FIFO code.
921 // to handle the case if (flush_head and push and IB was empty)
922 // Only flush_head if fifo is not empty
923 // Don't need to qualify with flush_upper because the buffer will
924 // be cleared by code below.
925 if (flush_head && (pop_ptr != push_ptr)) begin // {
926 fifo_pop;
927 end // }
928
929 //------------------------
930 // Push FIFO
931
932 // push_select may be asserted at same time as exc_valid.
933 // exc_valid should override.
934
935 // If exc_valid, I must push 2 valid tstamp in IB before making IB full.
936 // this is because the exception instruction will get to W and will
937 // need a ITLB_READ tstamp.
938 // exc_valid will only be asserted if there is room in IB for 4 entries
939 // so it is safe to push 2 entries.
940 // It is required to push 2 because the 1st entry may be DS of annul branch,
941 // then the exception happens on next instruction after DS.
942
943 if (exc_valid && push1 && !push2 && !flush_upper) begin // {
944
945 // It is possible to get back-to-back exceptions.
946 // So, need to check for fifo full before fifo_push.
947 // It is possible to have only 1 entry available after the 1 exception.
948 // if there was a pop at the same time as the exception.
949
950 ib_full = (pop_ptr==0) ? (push_ptr==(FIFO_DEPTH-1)): (push_ptr==(pop_ptr-1));
951 if (!ib_full) begin // {
952 fifo_push(ifu_err_select[0], ifetch_err_vld[0]);
953 end // }
954
955 ib_full = (pop_ptr==0) ? (push_ptr==(FIFO_DEPTH-1)): (push_ptr==(pop_ptr-1));
956 if (!ib_full) begin // {
957 fifo_push(ifu_err_select[1], ifetch_err_vld[1]);
958 end // }
959 end // }
960
961 else begin // {
962
963 if (push_select[0] && push1 && !push2) begin // {
964 fifo_push(ifu_err_select[0], ifetch_err_vld[0]);
965 end // }
966
967 if (push_select[1] && push1 && !push2) begin // {
968 fifo_push(ifu_err_select[1], ifetch_err_vld[1]);
969 end // }
970
971 if (push_select[2] && push1 && !push2) begin // {
972 fifo_push(ifu_err_select[2], ifetch_err_vld[2]);
973 end // }
974
975 if (push_select[3] && push1 && !push2) begin // {
976 fifo_push(ifu_err_select[3], ifetch_err_vld[3]);
977 end // }
978
979 end // }
980
981 //------------------------
982 // Pop FIFO
983
984 // It is possible to push and flush_upper in the same cycle.
985 // If this happens, flush_upper takes priority.
986 // So, flush code must be after push code since same always block.
987
988 // If flush_head and push in same cycle, there will be 1 entry in IB.
989 // Essentially, flush_head is ignored, then an entry is pushed.
990
991
992 case ({flush_upper, flush_head, pop}) // {
993 3'b000: begin
994 // NOP
995 end
996 3'b001: begin
997 fifo_pop;
998 end
999 3'b010: begin
1000 // NOP - case handled in code above
1001 end
1002 3'b011: begin
1003 `PR_ERROR ("tlb_sync", `ERROR,
1004 "C%0d T%0d Illegal signal combination for IB. flush_upper=%0b flush_head=%0b pick=%0b",
1005 mycid,mytid,flush_upper,flush_head,pop);
1006 end
1007 3'b100: begin
1008 // Only flush_upper if fifo is not empty
1009 if (pop_ptr != push_ptr) begin // {
1010 fifo_pop_upper;
1011 end // }
1012 end
1013 3'b101: begin
1014 fifo_clear;
1015 end
1016 3'b110: begin
1017 fifo_clear;
1018 end
1019 3'b111: begin
1020 `PR_ERROR ("tlb_sync", `ERROR,
1021 "C%0d T%0d Illegal signal combination for IB. flush_upper=%0b flush_head=%0b pick=%0b",
1022 mycid,mytid,flush_upper,flush_head,pop);
1023 end
1024 endcase // }
1025
1026 // It is possible to get a pop and exception.
1027 // In this case, the pop will happen, then the IB is made full.
1028 if (exc_valid && push1 && !push2 && !flush_upper) begin // {
1029 fifo_full;
1030 end // }
1031
1032 end // }
1033end // always }
1034
1035//----------------------------------------------------------
1036// Empty FIFO and reset push/pop pointers
1037task fifo_clear;
1038 integer i;
1039 begin // {
1040 // Initialize fifo
1041 pop_ptr = 0;
1042 push_ptr = 0;
1043
1044 for (i=0; i<FIFO_DEPTH; i=i+1) begin // {
1045 fifo[i] <= 0;
1046 end // }
1047
1048 end // }
1049endtask
1050
1051//----------------------------------------------------------
1052// Empty FIFO and reset push/pop pointers
1053task fifo_full;
1054 integer i;
1055 begin // {
1056
1057 // Increment push_ptr to full buffere
1058 if (pop_ptr == 0) begin // {
1059 push_ptr = FIFO_DEPTH-1;
1060 end // }
1061 else begin // {
1062 push_ptr = pop_ptr - 1;
1063 end // }
1064
1065 end // }
1066endtask
1067
1068//----------------------------------------------------------
1069// Pop item from FIFO
1070task fifo_pop;
1071
1072 begin // {
1073
1074 // Make sure the FIFO is not empty before pop
1075 if (pop_ptr == push_ptr) begin // {
1076 `PR_ERROR ("tlb_sync", `ERROR,
1077 "C%0d T%0d IB Underflow. PKU is trying to pick from empty IB.", mycid,mytid);
1078 end // }
1079
1080 // Clear entry in fifo
1081 fifo[pop_ptr] <= 0;
1082
1083 // Increment pop pointer
1084 if (pop_ptr==(FIFO_DEPTH-1)) begin // {
1085 pop_ptr = 0;
1086 end // }
1087 else begin // {
1088 pop_ptr = pop_ptr + 1;
1089 end // }
1090
1091
1092 end // }
1093endtask
1094
1095//----------------------------------------------------------
1096// Flush all items from FIFO except head
1097task fifo_pop_upper;
1098
1099 integer i;
1100
1101 begin // {
1102
1103 // Make sure the FIFO is not empty
1104 if (pop_ptr == push_ptr) begin // {
1105 `PR_ERROR ("tlb_sync", `ERROR,
1106 "C%0d T%0d IFU is trying to flush upper, but IB is empty.", mycid,mytid);
1107 end // }
1108
1109 // Make push ptr 1 entry above pop ptr
1110 if (pop_ptr==(FIFO_DEPTH-1)) begin // {
1111 push_ptr = 0;
1112 end // }
1113 else begin // {
1114 push_ptr = pop_ptr + 1;
1115 end // }
1116
1117
1118 end // }
1119endtask
1120
1121//----------------------------------------------------------
1122// Push item to FIFO
1123task fifo_push;
1124
1125 input err_select;
1126 input cache_err_vld;
1127 reg [7:0] tmp_err_vect;
1128
1129 begin // {
1130
1131 tstamp_curr = `TOP.core_cycle_cnt - 2;
1132
1133 `ifdef TLB_FIFO_WIDE
1134 tmp_err_vect = err_select ? ifu_err_vect : 8'b0;
1135 fifo[push_ptr] <= fetch_bypass ? {cache_err_vld,tmp_err_vect,tstamp_prev} : {cache_err_vld,tmp_err_vect,tstamp_curr};
1136 `else
1137 fifo[push_ptr] <= fetch_bypass ? tstamp_prev : tstamp_curr;
1138 `endif
1139
1140 // Increment push pointer
1141 if (push_ptr==(FIFO_DEPTH-1)) begin // {
1142 push_ptr = 0;
1143 end // }
1144 else begin // {
1145 push_ptr = push_ptr + 1;
1146 end // }
1147
1148 // Check for Overflow after push
1149 if (pop_ptr == push_ptr) begin // {
1150 `PR_ERROR ("tlb_sync", `ERROR,
1151 "C%0d T%0d IB Overflow. IFU is trying to fetch another instruction, but IB is already full.", mycid,mytid);
1152 end // }
1153
1154 end // }
1155endtask
1156
1157//----------------------------------------------------------
1158`endif
1159endmodule
1160
1161`endif
1162
1163`ifdef CORE_3
1164
1165module tlb_fifo_c3 (
1166
1167 // Inputs
1168 mytid,
1169
1170 // Outputs
1171 itlb_pipe_d
1172);
1173
1174`include "tlb_sync.vh"
1175
1176// FIFO_DEPTH is 1 more than IB depth in RTL
1177// so that overflow can be detected properly.
1178parameter FIFO_DEPTH = 9;
1179parameter PTR_WIDTH = 4;
1180
1181input [2:0] mytid;
1182output [(`TLB_FIFO_WIDTH-1):0] itlb_pipe_d;
1183`ifndef GATESIM
1184
1185wire [2:0] mycid;
1186wire push1; // 1st signal to qualify push_select
1187wire push2; // 2nd signal to qualify push_select
1188wire [3:0] push_select; // 1-4 tstamps are pushed
1189wire flush_upper;
1190wire flush_head;
1191wire pop;
1192wire itlb_miss;
1193wire icache_miss;
1194wire fetch_bypass;
1195wire exc_valid; // Exception valid
1196reg ib_full;
1197wire [7:0] ifu_err_vect;
1198wire [3:0] ifu_err_select;
1199wire [3:0] ifetch_err_vld;
1200
1201reg [(`TS_WIDTH-1):0] tstamp_curr;
1202reg [(`TS_WIDTH-1):0] tstamp_prev;
1203
1204reg [(`TLB_FIFO_WIDTH-1):0] fifo [0:(FIFO_DEPTH-1)]; // reg array
1205reg [(PTR_WIDTH-1):0] pop_ptr;
1206reg [(PTR_WIDTH-1):0] push_ptr;
1207reg [(`TLB_FIFO_WIDTH-1):0] itlb_pipe_d;
1208reg ready;
1209
1210//----------------------------------------------------------
1211// Create wires for reg array so signals can be viewed in Debussy
1212`ifdef DEBUG_TLB
1213 wire [(`TLB_FIFO_WIDTH-1):0] fifo_0;
1214 wire [(`TLB_FIFO_WIDTH-1):0] fifo_1;
1215 wire [(`TLB_FIFO_WIDTH-1):0] fifo_2;
1216 wire [(`TLB_FIFO_WIDTH-1):0] fifo_3;
1217 wire [(`TLB_FIFO_WIDTH-1):0] fifo_4;
1218 wire [(`TLB_FIFO_WIDTH-1):0] fifo_5;
1219 wire [(`TLB_FIFO_WIDTH-1):0] fifo_6;
1220 wire [(`TLB_FIFO_WIDTH-1):0] fifo_7;
1221 wire [(`TLB_FIFO_WIDTH-1):0] fifo_8;
1222 wire [(`TLB_FIFO_WIDTH-1):0] fifo_9;
1223
1224 assign fifo_0 = fifo[0];
1225 assign fifo_1 = fifo[1];
1226 assign fifo_2 = fifo[2];
1227 assign fifo_3 = fifo[3];
1228 assign fifo_4 = fifo[4];
1229 assign fifo_5 = fifo[5];
1230 assign fifo_6 = fifo[6];
1231 assign fifo_7 = fifo[7];
1232 assign fifo_8 = fifo[8];
1233 assign fifo_9 = fifo[9];
1234`endif
1235
1236
1237//----------------------------------------------------------
1238// DUT probes
1239
1240assign mycid = 3;
1241assign push1 = `SPC3.ifu_ftu.ftu_fetch_thr_c[mytid];
1242assign push2 = `SPC3.ifu_ftu.ftu_ibu_redirect_bf[mytid];
1243assign push_select = `SPC3.ifu_ftu.ftu_instr_valid_c;
1244assign flush_upper = `SPC3.pku.pku_flush_upper_buffer[mytid];
1245assign flush_head = `SPC3.pku.pku_flush_buffer0[mytid];
1246assign pop = `SPC3.pku.pku_pick_p[mytid];
1247assign itlb_miss = `PROBES3.itlb_miss[mytid];
1248assign icache_miss = `PROBES3.icache_miss[mytid];
1249assign fetch_bypass = `PROBES3.fetch_bypass[mytid];
1250assign exc_valid = `SPC3.ifu_ftu.ftu_exception_valid_c;
1251
1252// Error Injection - tlb_sync is pipelining some information that is useful to error injection code.
1253`ifdef TLB_FIFO_WIDE
1254assign ifu_err_vect = {tb_top.ras.ifu_err.ifu_err_code_c[4:0],tb_top.ras.ifu_err.ifu_err_way[2:0]};
1255assign ifu_err_select = tb_top.ras.ifu_err.ifu_err_select[3:0];
1256assign ifetch_err_vld = tb_top.ras.ifu_err.ifetch_err_vld[3:0];
1257`else
1258assign ifu_err_vect = 8'b0;
1259assign ifu_err_select = 4'b0;
1260assign ifetch_err_vld = 4'b0;
1261`endif
1262
1263//----------------------------------------------------------
1264initial begin // {
1265 ready = 0;
1266 @ (posedge `SPC3.l2clk);
1267 // Initialize fifo
1268 fifo_clear;
1269 itlb_pipe_d = 0;
1270 ready = `PARGS.tlb_sync_on;
1271end // }
1272
1273//----------------------------------------------------------
1274// push/pop from FIFO
1275
1276always @ (posedge (`SPC3.l2clk & ready)) begin // {
1277
1278 // Save tstamp if L1 Icache miss & ITLB hit (for later use if bypass)
1279 if (icache_miss & !itlb_miss) begin // {
1280 tstamp_prev = `TOP.core_cycle_cnt - 2;
1281 end // }
1282
1283
1284 // if POR|WMR, then no TLBread
1285 if (`TOP.in_reset_core) begin // {
1286 fifo_clear;
1287 end // }
1288 else begin // {
1289
1290 itlb_pipe_d <= pop ? fifo[pop_ptr] : itlb_pipe_d; // Get new value or hold state
1291
1292
1293 //------------------------
1294 // Pop FIFO - special case
1295
1296 // This code must be above the Push FIFO code.
1297 // to handle the case if (flush_head and push and IB was empty)
1298 // Only flush_head if fifo is not empty
1299 // Don't need to qualify with flush_upper because the buffer will
1300 // be cleared by code below.
1301 if (flush_head && (pop_ptr != push_ptr)) begin // {
1302 fifo_pop;
1303 end // }
1304
1305 //------------------------
1306 // Push FIFO
1307
1308 // push_select may be asserted at same time as exc_valid.
1309 // exc_valid should override.
1310
1311 // If exc_valid, I must push 2 valid tstamp in IB before making IB full.
1312 // this is because the exception instruction will get to W and will
1313 // need a ITLB_READ tstamp.
1314 // exc_valid will only be asserted if there is room in IB for 4 entries
1315 // so it is safe to push 2 entries.
1316 // It is required to push 2 because the 1st entry may be DS of annul branch,
1317 // then the exception happens on next instruction after DS.
1318
1319 if (exc_valid && push1 && !push2 && !flush_upper) begin // {
1320
1321 // It is possible to get back-to-back exceptions.
1322 // So, need to check for fifo full before fifo_push.
1323 // It is possible to have only 1 entry available after the 1 exception.
1324 // if there was a pop at the same time as the exception.
1325
1326 ib_full = (pop_ptr==0) ? (push_ptr==(FIFO_DEPTH-1)): (push_ptr==(pop_ptr-1));
1327 if (!ib_full) begin // {
1328 fifo_push(ifu_err_select[0], ifetch_err_vld[0]);
1329 end // }
1330
1331 ib_full = (pop_ptr==0) ? (push_ptr==(FIFO_DEPTH-1)): (push_ptr==(pop_ptr-1));
1332 if (!ib_full) begin // {
1333 fifo_push(ifu_err_select[1], ifetch_err_vld[1]);
1334 end // }
1335 end // }
1336
1337 else begin // {
1338
1339 if (push_select[0] && push1 && !push2) begin // {
1340 fifo_push(ifu_err_select[0], ifetch_err_vld[0]);
1341 end // }
1342
1343 if (push_select[1] && push1 && !push2) begin // {
1344 fifo_push(ifu_err_select[1], ifetch_err_vld[1]);
1345 end // }
1346
1347 if (push_select[2] && push1 && !push2) begin // {
1348 fifo_push(ifu_err_select[2], ifetch_err_vld[2]);
1349 end // }
1350
1351 if (push_select[3] && push1 && !push2) begin // {
1352 fifo_push(ifu_err_select[3], ifetch_err_vld[3]);
1353 end // }
1354
1355 end // }
1356
1357 //------------------------
1358 // Pop FIFO
1359
1360 // It is possible to push and flush_upper in the same cycle.
1361 // If this happens, flush_upper takes priority.
1362 // So, flush code must be after push code since same always block.
1363
1364 // If flush_head and push in same cycle, there will be 1 entry in IB.
1365 // Essentially, flush_head is ignored, then an entry is pushed.
1366
1367
1368 case ({flush_upper, flush_head, pop}) // {
1369 3'b000: begin
1370 // NOP
1371 end
1372 3'b001: begin
1373 fifo_pop;
1374 end
1375 3'b010: begin
1376 // NOP - case handled in code above
1377 end
1378 3'b011: begin
1379 `PR_ERROR ("tlb_sync", `ERROR,
1380 "C%0d T%0d Illegal signal combination for IB. flush_upper=%0b flush_head=%0b pick=%0b",
1381 mycid,mytid,flush_upper,flush_head,pop);
1382 end
1383 3'b100: begin
1384 // Only flush_upper if fifo is not empty
1385 if (pop_ptr != push_ptr) begin // {
1386 fifo_pop_upper;
1387 end // }
1388 end
1389 3'b101: begin
1390 fifo_clear;
1391 end
1392 3'b110: begin
1393 fifo_clear;
1394 end
1395 3'b111: begin
1396 `PR_ERROR ("tlb_sync", `ERROR,
1397 "C%0d T%0d Illegal signal combination for IB. flush_upper=%0b flush_head=%0b pick=%0b",
1398 mycid,mytid,flush_upper,flush_head,pop);
1399 end
1400 endcase // }
1401
1402 // It is possible to get a pop and exception.
1403 // In this case, the pop will happen, then the IB is made full.
1404 if (exc_valid && push1 && !push2 && !flush_upper) begin // {
1405 fifo_full;
1406 end // }
1407
1408 end // }
1409end // always }
1410
1411//----------------------------------------------------------
1412// Empty FIFO and reset push/pop pointers
1413task fifo_clear;
1414 integer i;
1415 begin // {
1416 // Initialize fifo
1417 pop_ptr = 0;
1418 push_ptr = 0;
1419
1420 for (i=0; i<FIFO_DEPTH; i=i+1) begin // {
1421 fifo[i] <= 0;
1422 end // }
1423
1424 end // }
1425endtask
1426
1427//----------------------------------------------------------
1428// Empty FIFO and reset push/pop pointers
1429task fifo_full;
1430 integer i;
1431 begin // {
1432
1433 // Increment push_ptr to full buffere
1434 if (pop_ptr == 0) begin // {
1435 push_ptr = FIFO_DEPTH-1;
1436 end // }
1437 else begin // {
1438 push_ptr = pop_ptr - 1;
1439 end // }
1440
1441 end // }
1442endtask
1443
1444//----------------------------------------------------------
1445// Pop item from FIFO
1446task fifo_pop;
1447
1448 begin // {
1449
1450 // Make sure the FIFO is not empty before pop
1451 if (pop_ptr == push_ptr) begin // {
1452 `PR_ERROR ("tlb_sync", `ERROR,
1453 "C%0d T%0d IB Underflow. PKU is trying to pick from empty IB.", mycid,mytid);
1454 end // }
1455
1456 // Clear entry in fifo
1457 fifo[pop_ptr] <= 0;
1458
1459 // Increment pop pointer
1460 if (pop_ptr==(FIFO_DEPTH-1)) begin // {
1461 pop_ptr = 0;
1462 end // }
1463 else begin // {
1464 pop_ptr = pop_ptr + 1;
1465 end // }
1466
1467
1468 end // }
1469endtask
1470
1471//----------------------------------------------------------
1472// Flush all items from FIFO except head
1473task fifo_pop_upper;
1474
1475 integer i;
1476
1477 begin // {
1478
1479 // Make sure the FIFO is not empty
1480 if (pop_ptr == push_ptr) begin // {
1481 `PR_ERROR ("tlb_sync", `ERROR,
1482 "C%0d T%0d IFU is trying to flush upper, but IB is empty.", mycid,mytid);
1483 end // }
1484
1485 // Make push ptr 1 entry above pop ptr
1486 if (pop_ptr==(FIFO_DEPTH-1)) begin // {
1487 push_ptr = 0;
1488 end // }
1489 else begin // {
1490 push_ptr = pop_ptr + 1;
1491 end // }
1492
1493
1494 end // }
1495endtask
1496
1497//----------------------------------------------------------
1498// Push item to FIFO
1499task fifo_push;
1500
1501 input err_select;
1502 input cache_err_vld;
1503 reg [7:0] tmp_err_vect;
1504
1505 begin // {
1506
1507 tstamp_curr = `TOP.core_cycle_cnt - 2;
1508
1509 `ifdef TLB_FIFO_WIDE
1510 tmp_err_vect = err_select ? ifu_err_vect : 8'b0;
1511 fifo[push_ptr] <= fetch_bypass ? {cache_err_vld,tmp_err_vect,tstamp_prev} : {cache_err_vld,tmp_err_vect,tstamp_curr};
1512 `else
1513 fifo[push_ptr] <= fetch_bypass ? tstamp_prev : tstamp_curr;
1514 `endif
1515
1516 // Increment push pointer
1517 if (push_ptr==(FIFO_DEPTH-1)) begin // {
1518 push_ptr = 0;
1519 end // }
1520 else begin // {
1521 push_ptr = push_ptr + 1;
1522 end // }
1523
1524 // Check for Overflow after push
1525 if (pop_ptr == push_ptr) begin // {
1526 `PR_ERROR ("tlb_sync", `ERROR,
1527 "C%0d T%0d IB Overflow. IFU is trying to fetch another instruction, but IB is already full.", mycid,mytid);
1528 end // }
1529
1530 end // }
1531endtask
1532
1533//----------------------------------------------------------
1534`endif
1535endmodule
1536
1537`endif
1538
1539`ifdef CORE_4
1540
1541module tlb_fifo_c4 (
1542
1543 // Inputs
1544 mytid,
1545
1546 // Outputs
1547 itlb_pipe_d
1548);
1549
1550`include "tlb_sync.vh"
1551
1552// FIFO_DEPTH is 1 more than IB depth in RTL
1553// so that overflow can be detected properly.
1554parameter FIFO_DEPTH = 9;
1555parameter PTR_WIDTH = 4;
1556
1557input [2:0] mytid;
1558output [(`TLB_FIFO_WIDTH-1):0] itlb_pipe_d;
1559`ifndef GATESIM
1560
1561wire [2:0] mycid;
1562wire push1; // 1st signal to qualify push_select
1563wire push2; // 2nd signal to qualify push_select
1564wire [3:0] push_select; // 1-4 tstamps are pushed
1565wire flush_upper;
1566wire flush_head;
1567wire pop;
1568wire itlb_miss;
1569wire icache_miss;
1570wire fetch_bypass;
1571wire exc_valid; // Exception valid
1572reg ib_full;
1573wire [7:0] ifu_err_vect;
1574wire [3:0] ifu_err_select;
1575wire [3:0] ifetch_err_vld;
1576
1577reg [(`TS_WIDTH-1):0] tstamp_curr;
1578reg [(`TS_WIDTH-1):0] tstamp_prev;
1579
1580reg [(`TLB_FIFO_WIDTH-1):0] fifo [0:(FIFO_DEPTH-1)]; // reg array
1581reg [(PTR_WIDTH-1):0] pop_ptr;
1582reg [(PTR_WIDTH-1):0] push_ptr;
1583reg [(`TLB_FIFO_WIDTH-1):0] itlb_pipe_d;
1584reg ready;
1585
1586//----------------------------------------------------------
1587// Create wires for reg array so signals can be viewed in Debussy
1588`ifdef DEBUG_TLB
1589 wire [(`TLB_FIFO_WIDTH-1):0] fifo_0;
1590 wire [(`TLB_FIFO_WIDTH-1):0] fifo_1;
1591 wire [(`TLB_FIFO_WIDTH-1):0] fifo_2;
1592 wire [(`TLB_FIFO_WIDTH-1):0] fifo_3;
1593 wire [(`TLB_FIFO_WIDTH-1):0] fifo_4;
1594 wire [(`TLB_FIFO_WIDTH-1):0] fifo_5;
1595 wire [(`TLB_FIFO_WIDTH-1):0] fifo_6;
1596 wire [(`TLB_FIFO_WIDTH-1):0] fifo_7;
1597 wire [(`TLB_FIFO_WIDTH-1):0] fifo_8;
1598 wire [(`TLB_FIFO_WIDTH-1):0] fifo_9;
1599
1600 assign fifo_0 = fifo[0];
1601 assign fifo_1 = fifo[1];
1602 assign fifo_2 = fifo[2];
1603 assign fifo_3 = fifo[3];
1604 assign fifo_4 = fifo[4];
1605 assign fifo_5 = fifo[5];
1606 assign fifo_6 = fifo[6];
1607 assign fifo_7 = fifo[7];
1608 assign fifo_8 = fifo[8];
1609 assign fifo_9 = fifo[9];
1610`endif
1611
1612
1613//----------------------------------------------------------
1614// DUT probes
1615
1616assign mycid = 4;
1617assign push1 = `SPC4.ifu_ftu.ftu_fetch_thr_c[mytid];
1618assign push2 = `SPC4.ifu_ftu.ftu_ibu_redirect_bf[mytid];
1619assign push_select = `SPC4.ifu_ftu.ftu_instr_valid_c;
1620assign flush_upper = `SPC4.pku.pku_flush_upper_buffer[mytid];
1621assign flush_head = `SPC4.pku.pku_flush_buffer0[mytid];
1622assign pop = `SPC4.pku.pku_pick_p[mytid];
1623assign itlb_miss = `PROBES4.itlb_miss[mytid];
1624assign icache_miss = `PROBES4.icache_miss[mytid];
1625assign fetch_bypass = `PROBES4.fetch_bypass[mytid];
1626assign exc_valid = `SPC4.ifu_ftu.ftu_exception_valid_c;
1627
1628// Error Injection - tlb_sync is pipelining some information that is useful to error injection code.
1629`ifdef TLB_FIFO_WIDE
1630assign ifu_err_vect = {tb_top.ras.ifu_err.ifu_err_code_c[4:0],tb_top.ras.ifu_err.ifu_err_way[2:0]};
1631assign ifu_err_select = tb_top.ras.ifu_err.ifu_err_select[3:0];
1632assign ifetch_err_vld = tb_top.ras.ifu_err.ifetch_err_vld[3:0];
1633`else
1634assign ifu_err_vect = 8'b0;
1635assign ifu_err_select = 4'b0;
1636assign ifetch_err_vld = 4'b0;
1637`endif
1638
1639//----------------------------------------------------------
1640initial begin // {
1641 ready = 0;
1642 @ (posedge `SPC4.l2clk);
1643 // Initialize fifo
1644 fifo_clear;
1645 itlb_pipe_d = 0;
1646 ready = `PARGS.tlb_sync_on;
1647end // }
1648
1649//----------------------------------------------------------
1650// push/pop from FIFO
1651
1652always @ (posedge (`SPC4.l2clk & ready)) begin // {
1653
1654 // Save tstamp if L1 Icache miss & ITLB hit (for later use if bypass)
1655 if (icache_miss & !itlb_miss) begin // {
1656 tstamp_prev = `TOP.core_cycle_cnt - 2;
1657 end // }
1658
1659
1660 // if POR|WMR, then no TLBread
1661 if (`TOP.in_reset_core) begin // {
1662 fifo_clear;
1663 end // }
1664 else begin // {
1665
1666 itlb_pipe_d <= pop ? fifo[pop_ptr] : itlb_pipe_d; // Get new value or hold state
1667
1668
1669 //------------------------
1670 // Pop FIFO - special case
1671
1672 // This code must be above the Push FIFO code.
1673 // to handle the case if (flush_head and push and IB was empty)
1674 // Only flush_head if fifo is not empty
1675 // Don't need to qualify with flush_upper because the buffer will
1676 // be cleared by code below.
1677 if (flush_head && (pop_ptr != push_ptr)) begin // {
1678 fifo_pop;
1679 end // }
1680
1681 //------------------------
1682 // Push FIFO
1683
1684 // push_select may be asserted at same time as exc_valid.
1685 // exc_valid should override.
1686
1687 // If exc_valid, I must push 2 valid tstamp in IB before making IB full.
1688 // this is because the exception instruction will get to W and will
1689 // need a ITLB_READ tstamp.
1690 // exc_valid will only be asserted if there is room in IB for 4 entries
1691 // so it is safe to push 2 entries.
1692 // It is required to push 2 because the 1st entry may be DS of annul branch,
1693 // then the exception happens on next instruction after DS.
1694
1695 if (exc_valid && push1 && !push2 && !flush_upper) begin // {
1696
1697 // It is possible to get back-to-back exceptions.
1698 // So, need to check for fifo full before fifo_push.
1699 // It is possible to have only 1 entry available after the 1 exception.
1700 // if there was a pop at the same time as the exception.
1701
1702 ib_full = (pop_ptr==0) ? (push_ptr==(FIFO_DEPTH-1)): (push_ptr==(pop_ptr-1));
1703 if (!ib_full) begin // {
1704 fifo_push(ifu_err_select[0], ifetch_err_vld[0]);
1705 end // }
1706
1707 ib_full = (pop_ptr==0) ? (push_ptr==(FIFO_DEPTH-1)): (push_ptr==(pop_ptr-1));
1708 if (!ib_full) begin // {
1709 fifo_push(ifu_err_select[1], ifetch_err_vld[1]);
1710 end // }
1711 end // }
1712
1713 else begin // {
1714
1715 if (push_select[0] && push1 && !push2) begin // {
1716 fifo_push(ifu_err_select[0], ifetch_err_vld[0]);
1717 end // }
1718
1719 if (push_select[1] && push1 && !push2) begin // {
1720 fifo_push(ifu_err_select[1], ifetch_err_vld[1]);
1721 end // }
1722
1723 if (push_select[2] && push1 && !push2) begin // {
1724 fifo_push(ifu_err_select[2], ifetch_err_vld[2]);
1725 end // }
1726
1727 if (push_select[3] && push1 && !push2) begin // {
1728 fifo_push(ifu_err_select[3], ifetch_err_vld[3]);
1729 end // }
1730
1731 end // }
1732
1733 //------------------------
1734 // Pop FIFO
1735
1736 // It is possible to push and flush_upper in the same cycle.
1737 // If this happens, flush_upper takes priority.
1738 // So, flush code must be after push code since same always block.
1739
1740 // If flush_head and push in same cycle, there will be 1 entry in IB.
1741 // Essentially, flush_head is ignored, then an entry is pushed.
1742
1743
1744 case ({flush_upper, flush_head, pop}) // {
1745 3'b000: begin
1746 // NOP
1747 end
1748 3'b001: begin
1749 fifo_pop;
1750 end
1751 3'b010: begin
1752 // NOP - case handled in code above
1753 end
1754 3'b011: begin
1755 `PR_ERROR ("tlb_sync", `ERROR,
1756 "C%0d T%0d Illegal signal combination for IB. flush_upper=%0b flush_head=%0b pick=%0b",
1757 mycid,mytid,flush_upper,flush_head,pop);
1758 end
1759 3'b100: begin
1760 // Only flush_upper if fifo is not empty
1761 if (pop_ptr != push_ptr) begin // {
1762 fifo_pop_upper;
1763 end // }
1764 end
1765 3'b101: begin
1766 fifo_clear;
1767 end
1768 3'b110: begin
1769 fifo_clear;
1770 end
1771 3'b111: begin
1772 `PR_ERROR ("tlb_sync", `ERROR,
1773 "C%0d T%0d Illegal signal combination for IB. flush_upper=%0b flush_head=%0b pick=%0b",
1774 mycid,mytid,flush_upper,flush_head,pop);
1775 end
1776 endcase // }
1777
1778 // It is possible to get a pop and exception.
1779 // In this case, the pop will happen, then the IB is made full.
1780 if (exc_valid && push1 && !push2 && !flush_upper) begin // {
1781 fifo_full;
1782 end // }
1783
1784 end // }
1785end // always }
1786
1787//----------------------------------------------------------
1788// Empty FIFO and reset push/pop pointers
1789task fifo_clear;
1790 integer i;
1791 begin // {
1792 // Initialize fifo
1793 pop_ptr = 0;
1794 push_ptr = 0;
1795
1796 for (i=0; i<FIFO_DEPTH; i=i+1) begin // {
1797 fifo[i] <= 0;
1798 end // }
1799
1800 end // }
1801endtask
1802
1803//----------------------------------------------------------
1804// Empty FIFO and reset push/pop pointers
1805task fifo_full;
1806 integer i;
1807 begin // {
1808
1809 // Increment push_ptr to full buffere
1810 if (pop_ptr == 0) begin // {
1811 push_ptr = FIFO_DEPTH-1;
1812 end // }
1813 else begin // {
1814 push_ptr = pop_ptr - 1;
1815 end // }
1816
1817 end // }
1818endtask
1819
1820//----------------------------------------------------------
1821// Pop item from FIFO
1822task fifo_pop;
1823
1824 begin // {
1825
1826 // Make sure the FIFO is not empty before pop
1827 if (pop_ptr == push_ptr) begin // {
1828 `PR_ERROR ("tlb_sync", `ERROR,
1829 "C%0d T%0d IB Underflow. PKU is trying to pick from empty IB.", mycid,mytid);
1830 end // }
1831
1832 // Clear entry in fifo
1833 fifo[pop_ptr] <= 0;
1834
1835 // Increment pop pointer
1836 if (pop_ptr==(FIFO_DEPTH-1)) begin // {
1837 pop_ptr = 0;
1838 end // }
1839 else begin // {
1840 pop_ptr = pop_ptr + 1;
1841 end // }
1842
1843
1844 end // }
1845endtask
1846
1847//----------------------------------------------------------
1848// Flush all items from FIFO except head
1849task fifo_pop_upper;
1850
1851 integer i;
1852
1853 begin // {
1854
1855 // Make sure the FIFO is not empty
1856 if (pop_ptr == push_ptr) begin // {
1857 `PR_ERROR ("tlb_sync", `ERROR,
1858 "C%0d T%0d IFU is trying to flush upper, but IB is empty.", mycid,mytid);
1859 end // }
1860
1861 // Make push ptr 1 entry above pop ptr
1862 if (pop_ptr==(FIFO_DEPTH-1)) begin // {
1863 push_ptr = 0;
1864 end // }
1865 else begin // {
1866 push_ptr = pop_ptr + 1;
1867 end // }
1868
1869
1870 end // }
1871endtask
1872
1873//----------------------------------------------------------
1874// Push item to FIFO
1875task fifo_push;
1876
1877 input err_select;
1878 input cache_err_vld;
1879 reg [7:0] tmp_err_vect;
1880
1881 begin // {
1882
1883 tstamp_curr = `TOP.core_cycle_cnt - 2;
1884
1885 `ifdef TLB_FIFO_WIDE
1886 tmp_err_vect = err_select ? ifu_err_vect : 8'b0;
1887 fifo[push_ptr] <= fetch_bypass ? {cache_err_vld,tmp_err_vect,tstamp_prev} : {cache_err_vld,tmp_err_vect,tstamp_curr};
1888 `else
1889 fifo[push_ptr] <= fetch_bypass ? tstamp_prev : tstamp_curr;
1890 `endif
1891
1892 // Increment push pointer
1893 if (push_ptr==(FIFO_DEPTH-1)) begin // {
1894 push_ptr = 0;
1895 end // }
1896 else begin // {
1897 push_ptr = push_ptr + 1;
1898 end // }
1899
1900 // Check for Overflow after push
1901 if (pop_ptr == push_ptr) begin // {
1902 `PR_ERROR ("tlb_sync", `ERROR,
1903 "C%0d T%0d IB Overflow. IFU is trying to fetch another instruction, but IB is already full.", mycid,mytid);
1904 end // }
1905
1906 end // }
1907endtask
1908
1909//----------------------------------------------------------
1910`endif
1911endmodule
1912
1913`endif
1914
1915`ifdef CORE_5
1916
1917module tlb_fifo_c5 (
1918
1919 // Inputs
1920 mytid,
1921
1922 // Outputs
1923 itlb_pipe_d
1924);
1925
1926`include "tlb_sync.vh"
1927
1928// FIFO_DEPTH is 1 more than IB depth in RTL
1929// so that overflow can be detected properly.
1930parameter FIFO_DEPTH = 9;
1931parameter PTR_WIDTH = 4;
1932
1933input [2:0] mytid;
1934output [(`TLB_FIFO_WIDTH-1):0] itlb_pipe_d;
1935`ifndef GATESIM
1936
1937wire [2:0] mycid;
1938wire push1; // 1st signal to qualify push_select
1939wire push2; // 2nd signal to qualify push_select
1940wire [3:0] push_select; // 1-4 tstamps are pushed
1941wire flush_upper;
1942wire flush_head;
1943wire pop;
1944wire itlb_miss;
1945wire icache_miss;
1946wire fetch_bypass;
1947wire exc_valid; // Exception valid
1948reg ib_full;
1949wire [7:0] ifu_err_vect;
1950wire [3:0] ifu_err_select;
1951wire [3:0] ifetch_err_vld;
1952
1953reg [(`TS_WIDTH-1):0] tstamp_curr;
1954reg [(`TS_WIDTH-1):0] tstamp_prev;
1955
1956reg [(`TLB_FIFO_WIDTH-1):0] fifo [0:(FIFO_DEPTH-1)]; // reg array
1957reg [(PTR_WIDTH-1):0] pop_ptr;
1958reg [(PTR_WIDTH-1):0] push_ptr;
1959reg [(`TLB_FIFO_WIDTH-1):0] itlb_pipe_d;
1960reg ready;
1961
1962//----------------------------------------------------------
1963// Create wires for reg array so signals can be viewed in Debussy
1964`ifdef DEBUG_TLB
1965 wire [(`TLB_FIFO_WIDTH-1):0] fifo_0;
1966 wire [(`TLB_FIFO_WIDTH-1):0] fifo_1;
1967 wire [(`TLB_FIFO_WIDTH-1):0] fifo_2;
1968 wire [(`TLB_FIFO_WIDTH-1):0] fifo_3;
1969 wire [(`TLB_FIFO_WIDTH-1):0] fifo_4;
1970 wire [(`TLB_FIFO_WIDTH-1):0] fifo_5;
1971 wire [(`TLB_FIFO_WIDTH-1):0] fifo_6;
1972 wire [(`TLB_FIFO_WIDTH-1):0] fifo_7;
1973 wire [(`TLB_FIFO_WIDTH-1):0] fifo_8;
1974 wire [(`TLB_FIFO_WIDTH-1):0] fifo_9;
1975
1976 assign fifo_0 = fifo[0];
1977 assign fifo_1 = fifo[1];
1978 assign fifo_2 = fifo[2];
1979 assign fifo_3 = fifo[3];
1980 assign fifo_4 = fifo[4];
1981 assign fifo_5 = fifo[5];
1982 assign fifo_6 = fifo[6];
1983 assign fifo_7 = fifo[7];
1984 assign fifo_8 = fifo[8];
1985 assign fifo_9 = fifo[9];
1986`endif
1987
1988
1989//----------------------------------------------------------
1990// DUT probes
1991
1992assign mycid = 5;
1993assign push1 = `SPC5.ifu_ftu.ftu_fetch_thr_c[mytid];
1994assign push2 = `SPC5.ifu_ftu.ftu_ibu_redirect_bf[mytid];
1995assign push_select = `SPC5.ifu_ftu.ftu_instr_valid_c;
1996assign flush_upper = `SPC5.pku.pku_flush_upper_buffer[mytid];
1997assign flush_head = `SPC5.pku.pku_flush_buffer0[mytid];
1998assign pop = `SPC5.pku.pku_pick_p[mytid];
1999assign itlb_miss = `PROBES5.itlb_miss[mytid];
2000assign icache_miss = `PROBES5.icache_miss[mytid];
2001assign fetch_bypass = `PROBES5.fetch_bypass[mytid];
2002assign exc_valid = `SPC5.ifu_ftu.ftu_exception_valid_c;
2003
2004// Error Injection - tlb_sync is pipelining some information that is useful to error injection code.
2005`ifdef TLB_FIFO_WIDE
2006assign ifu_err_vect = {tb_top.ras.ifu_err.ifu_err_code_c[4:0],tb_top.ras.ifu_err.ifu_err_way[2:0]};
2007assign ifu_err_select = tb_top.ras.ifu_err.ifu_err_select[3:0];
2008assign ifetch_err_vld = tb_top.ras.ifu_err.ifetch_err_vld[3:0];
2009`else
2010assign ifu_err_vect = 8'b0;
2011assign ifu_err_select = 4'b0;
2012assign ifetch_err_vld = 4'b0;
2013`endif
2014
2015//----------------------------------------------------------
2016initial begin // {
2017 ready = 0;
2018 @ (posedge `SPC5.l2clk);
2019 // Initialize fifo
2020 fifo_clear;
2021 itlb_pipe_d = 0;
2022 ready = `PARGS.tlb_sync_on;
2023end // }
2024
2025//----------------------------------------------------------
2026// push/pop from FIFO
2027
2028always @ (posedge (`SPC5.l2clk & ready)) begin // {
2029
2030 // Save tstamp if L1 Icache miss & ITLB hit (for later use if bypass)
2031 if (icache_miss & !itlb_miss) begin // {
2032 tstamp_prev = `TOP.core_cycle_cnt - 2;
2033 end // }
2034
2035
2036 // if POR|WMR, then no TLBread
2037 if (`TOP.in_reset_core) begin // {
2038 fifo_clear;
2039 end // }
2040 else begin // {
2041
2042 itlb_pipe_d <= pop ? fifo[pop_ptr] : itlb_pipe_d; // Get new value or hold state
2043
2044
2045 //------------------------
2046 // Pop FIFO - special case
2047
2048 // This code must be above the Push FIFO code.
2049 // to handle the case if (flush_head and push and IB was empty)
2050 // Only flush_head if fifo is not empty
2051 // Don't need to qualify with flush_upper because the buffer will
2052 // be cleared by code below.
2053 if (flush_head && (pop_ptr != push_ptr)) begin // {
2054 fifo_pop;
2055 end // }
2056
2057 //------------------------
2058 // Push FIFO
2059
2060 // push_select may be asserted at same time as exc_valid.
2061 // exc_valid should override.
2062
2063 // If exc_valid, I must push 2 valid tstamp in IB before making IB full.
2064 // this is because the exception instruction will get to W and will
2065 // need a ITLB_READ tstamp.
2066 // exc_valid will only be asserted if there is room in IB for 4 entries
2067 // so it is safe to push 2 entries.
2068 // It is required to push 2 because the 1st entry may be DS of annul branch,
2069 // then the exception happens on next instruction after DS.
2070
2071 if (exc_valid && push1 && !push2 && !flush_upper) begin // {
2072
2073 // It is possible to get back-to-back exceptions.
2074 // So, need to check for fifo full before fifo_push.
2075 // It is possible to have only 1 entry available after the 1 exception.
2076 // if there was a pop at the same time as the exception.
2077
2078 ib_full = (pop_ptr==0) ? (push_ptr==(FIFO_DEPTH-1)): (push_ptr==(pop_ptr-1));
2079 if (!ib_full) begin // {
2080 fifo_push(ifu_err_select[0], ifetch_err_vld[0]);
2081 end // }
2082
2083 ib_full = (pop_ptr==0) ? (push_ptr==(FIFO_DEPTH-1)): (push_ptr==(pop_ptr-1));
2084 if (!ib_full) begin // {
2085 fifo_push(ifu_err_select[1], ifetch_err_vld[1]);
2086 end // }
2087 end // }
2088
2089 else begin // {
2090
2091 if (push_select[0] && push1 && !push2) begin // {
2092 fifo_push(ifu_err_select[0], ifetch_err_vld[0]);
2093 end // }
2094
2095 if (push_select[1] && push1 && !push2) begin // {
2096 fifo_push(ifu_err_select[1], ifetch_err_vld[1]);
2097 end // }
2098
2099 if (push_select[2] && push1 && !push2) begin // {
2100 fifo_push(ifu_err_select[2], ifetch_err_vld[2]);
2101 end // }
2102
2103 if (push_select[3] && push1 && !push2) begin // {
2104 fifo_push(ifu_err_select[3], ifetch_err_vld[3]);
2105 end // }
2106
2107 end // }
2108
2109 //------------------------
2110 // Pop FIFO
2111
2112 // It is possible to push and flush_upper in the same cycle.
2113 // If this happens, flush_upper takes priority.
2114 // So, flush code must be after push code since same always block.
2115
2116 // If flush_head and push in same cycle, there will be 1 entry in IB.
2117 // Essentially, flush_head is ignored, then an entry is pushed.
2118
2119
2120 case ({flush_upper, flush_head, pop}) // {
2121 3'b000: begin
2122 // NOP
2123 end
2124 3'b001: begin
2125 fifo_pop;
2126 end
2127 3'b010: begin
2128 // NOP - case handled in code above
2129 end
2130 3'b011: begin
2131 `PR_ERROR ("tlb_sync", `ERROR,
2132 "C%0d T%0d Illegal signal combination for IB. flush_upper=%0b flush_head=%0b pick=%0b",
2133 mycid,mytid,flush_upper,flush_head,pop);
2134 end
2135 3'b100: begin
2136 // Only flush_upper if fifo is not empty
2137 if (pop_ptr != push_ptr) begin // {
2138 fifo_pop_upper;
2139 end // }
2140 end
2141 3'b101: begin
2142 fifo_clear;
2143 end
2144 3'b110: begin
2145 fifo_clear;
2146 end
2147 3'b111: begin
2148 `PR_ERROR ("tlb_sync", `ERROR,
2149 "C%0d T%0d Illegal signal combination for IB. flush_upper=%0b flush_head=%0b pick=%0b",
2150 mycid,mytid,flush_upper,flush_head,pop);
2151 end
2152 endcase // }
2153
2154 // It is possible to get a pop and exception.
2155 // In this case, the pop will happen, then the IB is made full.
2156 if (exc_valid && push1 && !push2 && !flush_upper) begin // {
2157 fifo_full;
2158 end // }
2159
2160 end // }
2161end // always }
2162
2163//----------------------------------------------------------
2164// Empty FIFO and reset push/pop pointers
2165task fifo_clear;
2166 integer i;
2167 begin // {
2168 // Initialize fifo
2169 pop_ptr = 0;
2170 push_ptr = 0;
2171
2172 for (i=0; i<FIFO_DEPTH; i=i+1) begin // {
2173 fifo[i] <= 0;
2174 end // }
2175
2176 end // }
2177endtask
2178
2179//----------------------------------------------------------
2180// Empty FIFO and reset push/pop pointers
2181task fifo_full;
2182 integer i;
2183 begin // {
2184
2185 // Increment push_ptr to full buffere
2186 if (pop_ptr == 0) begin // {
2187 push_ptr = FIFO_DEPTH-1;
2188 end // }
2189 else begin // {
2190 push_ptr = pop_ptr - 1;
2191 end // }
2192
2193 end // }
2194endtask
2195
2196//----------------------------------------------------------
2197// Pop item from FIFO
2198task fifo_pop;
2199
2200 begin // {
2201
2202 // Make sure the FIFO is not empty before pop
2203 if (pop_ptr == push_ptr) begin // {
2204 `PR_ERROR ("tlb_sync", `ERROR,
2205 "C%0d T%0d IB Underflow. PKU is trying to pick from empty IB.", mycid,mytid);
2206 end // }
2207
2208 // Clear entry in fifo
2209 fifo[pop_ptr] <= 0;
2210
2211 // Increment pop pointer
2212 if (pop_ptr==(FIFO_DEPTH-1)) begin // {
2213 pop_ptr = 0;
2214 end // }
2215 else begin // {
2216 pop_ptr = pop_ptr + 1;
2217 end // }
2218
2219
2220 end // }
2221endtask
2222
2223//----------------------------------------------------------
2224// Flush all items from FIFO except head
2225task fifo_pop_upper;
2226
2227 integer i;
2228
2229 begin // {
2230
2231 // Make sure the FIFO is not empty
2232 if (pop_ptr == push_ptr) begin // {
2233 `PR_ERROR ("tlb_sync", `ERROR,
2234 "C%0d T%0d IFU is trying to flush upper, but IB is empty.", mycid,mytid);
2235 end // }
2236
2237 // Make push ptr 1 entry above pop ptr
2238 if (pop_ptr==(FIFO_DEPTH-1)) begin // {
2239 push_ptr = 0;
2240 end // }
2241 else begin // {
2242 push_ptr = pop_ptr + 1;
2243 end // }
2244
2245
2246 end // }
2247endtask
2248
2249//----------------------------------------------------------
2250// Push item to FIFO
2251task fifo_push;
2252
2253 input err_select;
2254 input cache_err_vld;
2255 reg [7:0] tmp_err_vect;
2256
2257 begin // {
2258
2259 tstamp_curr = `TOP.core_cycle_cnt - 2;
2260
2261 `ifdef TLB_FIFO_WIDE
2262 tmp_err_vect = err_select ? ifu_err_vect : 8'b0;
2263 fifo[push_ptr] <= fetch_bypass ? {cache_err_vld,tmp_err_vect,tstamp_prev} : {cache_err_vld,tmp_err_vect,tstamp_curr};
2264 `else
2265 fifo[push_ptr] <= fetch_bypass ? tstamp_prev : tstamp_curr;
2266 `endif
2267
2268 // Increment push pointer
2269 if (push_ptr==(FIFO_DEPTH-1)) begin // {
2270 push_ptr = 0;
2271 end // }
2272 else begin // {
2273 push_ptr = push_ptr + 1;
2274 end // }
2275
2276 // Check for Overflow after push
2277 if (pop_ptr == push_ptr) begin // {
2278 `PR_ERROR ("tlb_sync", `ERROR,
2279 "C%0d T%0d IB Overflow. IFU is trying to fetch another instruction, but IB is already full.", mycid,mytid);
2280 end // }
2281
2282 end // }
2283endtask
2284
2285//----------------------------------------------------------
2286`endif
2287endmodule
2288
2289`endif
2290
2291`ifdef CORE_6
2292
2293module tlb_fifo_c6 (
2294
2295 // Inputs
2296 mytid,
2297
2298 // Outputs
2299 itlb_pipe_d
2300);
2301
2302`include "tlb_sync.vh"
2303
2304// FIFO_DEPTH is 1 more than IB depth in RTL
2305// so that overflow can be detected properly.
2306parameter FIFO_DEPTH = 9;
2307parameter PTR_WIDTH = 4;
2308
2309input [2:0] mytid;
2310output [(`TLB_FIFO_WIDTH-1):0] itlb_pipe_d;
2311`ifndef GATESIM
2312
2313wire [2:0] mycid;
2314wire push1; // 1st signal to qualify push_select
2315wire push2; // 2nd signal to qualify push_select
2316wire [3:0] push_select; // 1-4 tstamps are pushed
2317wire flush_upper;
2318wire flush_head;
2319wire pop;
2320wire itlb_miss;
2321wire icache_miss;
2322wire fetch_bypass;
2323wire exc_valid; // Exception valid
2324reg ib_full;
2325wire [7:0] ifu_err_vect;
2326wire [3:0] ifu_err_select;
2327wire [3:0] ifetch_err_vld;
2328
2329reg [(`TS_WIDTH-1):0] tstamp_curr;
2330reg [(`TS_WIDTH-1):0] tstamp_prev;
2331
2332reg [(`TLB_FIFO_WIDTH-1):0] fifo [0:(FIFO_DEPTH-1)]; // reg array
2333reg [(PTR_WIDTH-1):0] pop_ptr;
2334reg [(PTR_WIDTH-1):0] push_ptr;
2335reg [(`TLB_FIFO_WIDTH-1):0] itlb_pipe_d;
2336reg ready;
2337
2338//----------------------------------------------------------
2339// Create wires for reg array so signals can be viewed in Debussy
2340`ifdef DEBUG_TLB
2341 wire [(`TLB_FIFO_WIDTH-1):0] fifo_0;
2342 wire [(`TLB_FIFO_WIDTH-1):0] fifo_1;
2343 wire [(`TLB_FIFO_WIDTH-1):0] fifo_2;
2344 wire [(`TLB_FIFO_WIDTH-1):0] fifo_3;
2345 wire [(`TLB_FIFO_WIDTH-1):0] fifo_4;
2346 wire [(`TLB_FIFO_WIDTH-1):0] fifo_5;
2347 wire [(`TLB_FIFO_WIDTH-1):0] fifo_6;
2348 wire [(`TLB_FIFO_WIDTH-1):0] fifo_7;
2349 wire [(`TLB_FIFO_WIDTH-1):0] fifo_8;
2350 wire [(`TLB_FIFO_WIDTH-1):0] fifo_9;
2351
2352 assign fifo_0 = fifo[0];
2353 assign fifo_1 = fifo[1];
2354 assign fifo_2 = fifo[2];
2355 assign fifo_3 = fifo[3];
2356 assign fifo_4 = fifo[4];
2357 assign fifo_5 = fifo[5];
2358 assign fifo_6 = fifo[6];
2359 assign fifo_7 = fifo[7];
2360 assign fifo_8 = fifo[8];
2361 assign fifo_9 = fifo[9];
2362`endif
2363
2364
2365//----------------------------------------------------------
2366// DUT probes
2367
2368assign mycid = 6;
2369assign push1 = `SPC6.ifu_ftu.ftu_fetch_thr_c[mytid];
2370assign push2 = `SPC6.ifu_ftu.ftu_ibu_redirect_bf[mytid];
2371assign push_select = `SPC6.ifu_ftu.ftu_instr_valid_c;
2372assign flush_upper = `SPC6.pku.pku_flush_upper_buffer[mytid];
2373assign flush_head = `SPC6.pku.pku_flush_buffer0[mytid];
2374assign pop = `SPC6.pku.pku_pick_p[mytid];
2375assign itlb_miss = `PROBES6.itlb_miss[mytid];
2376assign icache_miss = `PROBES6.icache_miss[mytid];
2377assign fetch_bypass = `PROBES6.fetch_bypass[mytid];
2378assign exc_valid = `SPC6.ifu_ftu.ftu_exception_valid_c;
2379
2380// Error Injection - tlb_sync is pipelining some information that is useful to error injection code.
2381`ifdef TLB_FIFO_WIDE
2382assign ifu_err_vect = {tb_top.ras.ifu_err.ifu_err_code_c[4:0],tb_top.ras.ifu_err.ifu_err_way[2:0]};
2383assign ifu_err_select = tb_top.ras.ifu_err.ifu_err_select[3:0];
2384assign ifetch_err_vld = tb_top.ras.ifu_err.ifetch_err_vld[3:0];
2385`else
2386assign ifu_err_vect = 8'b0;
2387assign ifu_err_select = 4'b0;
2388assign ifetch_err_vld = 4'b0;
2389`endif
2390
2391//----------------------------------------------------------
2392initial begin // {
2393 ready = 0;
2394 @ (posedge `SPC6.l2clk);
2395 // Initialize fifo
2396 fifo_clear;
2397 itlb_pipe_d = 0;
2398 ready = `PARGS.tlb_sync_on;
2399end // }
2400
2401//----------------------------------------------------------
2402// push/pop from FIFO
2403
2404always @ (posedge (`SPC6.l2clk & ready)) begin // {
2405
2406 // Save tstamp if L1 Icache miss & ITLB hit (for later use if bypass)
2407 if (icache_miss & !itlb_miss) begin // {
2408 tstamp_prev = `TOP.core_cycle_cnt - 2;
2409 end // }
2410
2411
2412 // if POR|WMR, then no TLBread
2413 if (`TOP.in_reset_core) begin // {
2414 fifo_clear;
2415 end // }
2416 else begin // {
2417
2418 itlb_pipe_d <= pop ? fifo[pop_ptr] : itlb_pipe_d; // Get new value or hold state
2419
2420
2421 //------------------------
2422 // Pop FIFO - special case
2423
2424 // This code must be above the Push FIFO code.
2425 // to handle the case if (flush_head and push and IB was empty)
2426 // Only flush_head if fifo is not empty
2427 // Don't need to qualify with flush_upper because the buffer will
2428 // be cleared by code below.
2429 if (flush_head && (pop_ptr != push_ptr)) begin // {
2430 fifo_pop;
2431 end // }
2432
2433 //------------------------
2434 // Push FIFO
2435
2436 // push_select may be asserted at same time as exc_valid.
2437 // exc_valid should override.
2438
2439 // If exc_valid, I must push 2 valid tstamp in IB before making IB full.
2440 // this is because the exception instruction will get to W and will
2441 // need a ITLB_READ tstamp.
2442 // exc_valid will only be asserted if there is room in IB for 4 entries
2443 // so it is safe to push 2 entries.
2444 // It is required to push 2 because the 1st entry may be DS of annul branch,
2445 // then the exception happens on next instruction after DS.
2446
2447 if (exc_valid && push1 && !push2 && !flush_upper) begin // {
2448
2449 // It is possible to get back-to-back exceptions.
2450 // So, need to check for fifo full before fifo_push.
2451 // It is possible to have only 1 entry available after the 1 exception.
2452 // if there was a pop at the same time as the exception.
2453
2454 ib_full = (pop_ptr==0) ? (push_ptr==(FIFO_DEPTH-1)): (push_ptr==(pop_ptr-1));
2455 if (!ib_full) begin // {
2456 fifo_push(ifu_err_select[0], ifetch_err_vld[0]);
2457 end // }
2458
2459 ib_full = (pop_ptr==0) ? (push_ptr==(FIFO_DEPTH-1)): (push_ptr==(pop_ptr-1));
2460 if (!ib_full) begin // {
2461 fifo_push(ifu_err_select[1], ifetch_err_vld[1]);
2462 end // }
2463 end // }
2464
2465 else begin // {
2466
2467 if (push_select[0] && push1 && !push2) begin // {
2468 fifo_push(ifu_err_select[0], ifetch_err_vld[0]);
2469 end // }
2470
2471 if (push_select[1] && push1 && !push2) begin // {
2472 fifo_push(ifu_err_select[1], ifetch_err_vld[1]);
2473 end // }
2474
2475 if (push_select[2] && push1 && !push2) begin // {
2476 fifo_push(ifu_err_select[2], ifetch_err_vld[2]);
2477 end // }
2478
2479 if (push_select[3] && push1 && !push2) begin // {
2480 fifo_push(ifu_err_select[3], ifetch_err_vld[3]);
2481 end // }
2482
2483 end // }
2484
2485 //------------------------
2486 // Pop FIFO
2487
2488 // It is possible to push and flush_upper in the same cycle.
2489 // If this happens, flush_upper takes priority.
2490 // So, flush code must be after push code since same always block.
2491
2492 // If flush_head and push in same cycle, there will be 1 entry in IB.
2493 // Essentially, flush_head is ignored, then an entry is pushed.
2494
2495
2496 case ({flush_upper, flush_head, pop}) // {
2497 3'b000: begin
2498 // NOP
2499 end
2500 3'b001: begin
2501 fifo_pop;
2502 end
2503 3'b010: begin
2504 // NOP - case handled in code above
2505 end
2506 3'b011: begin
2507 `PR_ERROR ("tlb_sync", `ERROR,
2508 "C%0d T%0d Illegal signal combination for IB. flush_upper=%0b flush_head=%0b pick=%0b",
2509 mycid,mytid,flush_upper,flush_head,pop);
2510 end
2511 3'b100: begin
2512 // Only flush_upper if fifo is not empty
2513 if (pop_ptr != push_ptr) begin // {
2514 fifo_pop_upper;
2515 end // }
2516 end
2517 3'b101: begin
2518 fifo_clear;
2519 end
2520 3'b110: begin
2521 fifo_clear;
2522 end
2523 3'b111: begin
2524 `PR_ERROR ("tlb_sync", `ERROR,
2525 "C%0d T%0d Illegal signal combination for IB. flush_upper=%0b flush_head=%0b pick=%0b",
2526 mycid,mytid,flush_upper,flush_head,pop);
2527 end
2528 endcase // }
2529
2530 // It is possible to get a pop and exception.
2531 // In this case, the pop will happen, then the IB is made full.
2532 if (exc_valid && push1 && !push2 && !flush_upper) begin // {
2533 fifo_full;
2534 end // }
2535
2536 end // }
2537end // always }
2538
2539//----------------------------------------------------------
2540// Empty FIFO and reset push/pop pointers
2541task fifo_clear;
2542 integer i;
2543 begin // {
2544 // Initialize fifo
2545 pop_ptr = 0;
2546 push_ptr = 0;
2547
2548 for (i=0; i<FIFO_DEPTH; i=i+1) begin // {
2549 fifo[i] <= 0;
2550 end // }
2551
2552 end // }
2553endtask
2554
2555//----------------------------------------------------------
2556// Empty FIFO and reset push/pop pointers
2557task fifo_full;
2558 integer i;
2559 begin // {
2560
2561 // Increment push_ptr to full buffere
2562 if (pop_ptr == 0) begin // {
2563 push_ptr = FIFO_DEPTH-1;
2564 end // }
2565 else begin // {
2566 push_ptr = pop_ptr - 1;
2567 end // }
2568
2569 end // }
2570endtask
2571
2572//----------------------------------------------------------
2573// Pop item from FIFO
2574task fifo_pop;
2575
2576 begin // {
2577
2578 // Make sure the FIFO is not empty before pop
2579 if (pop_ptr == push_ptr) begin // {
2580 `PR_ERROR ("tlb_sync", `ERROR,
2581 "C%0d T%0d IB Underflow. PKU is trying to pick from empty IB.", mycid,mytid);
2582 end // }
2583
2584 // Clear entry in fifo
2585 fifo[pop_ptr] <= 0;
2586
2587 // Increment pop pointer
2588 if (pop_ptr==(FIFO_DEPTH-1)) begin // {
2589 pop_ptr = 0;
2590 end // }
2591 else begin // {
2592 pop_ptr = pop_ptr + 1;
2593 end // }
2594
2595
2596 end // }
2597endtask
2598
2599//----------------------------------------------------------
2600// Flush all items from FIFO except head
2601task fifo_pop_upper;
2602
2603 integer i;
2604
2605 begin // {
2606
2607 // Make sure the FIFO is not empty
2608 if (pop_ptr == push_ptr) begin // {
2609 `PR_ERROR ("tlb_sync", `ERROR,
2610 "C%0d T%0d IFU is trying to flush upper, but IB is empty.", mycid,mytid);
2611 end // }
2612
2613 // Make push ptr 1 entry above pop ptr
2614 if (pop_ptr==(FIFO_DEPTH-1)) begin // {
2615 push_ptr = 0;
2616 end // }
2617 else begin // {
2618 push_ptr = pop_ptr + 1;
2619 end // }
2620
2621
2622 end // }
2623endtask
2624
2625//----------------------------------------------------------
2626// Push item to FIFO
2627task fifo_push;
2628
2629 input err_select;
2630 input cache_err_vld;
2631 reg [7:0] tmp_err_vect;
2632
2633 begin // {
2634
2635 tstamp_curr = `TOP.core_cycle_cnt - 2;
2636
2637 `ifdef TLB_FIFO_WIDE
2638 tmp_err_vect = err_select ? ifu_err_vect : 8'b0;
2639 fifo[push_ptr] <= fetch_bypass ? {cache_err_vld,tmp_err_vect,tstamp_prev} : {cache_err_vld,tmp_err_vect,tstamp_curr};
2640 `else
2641 fifo[push_ptr] <= fetch_bypass ? tstamp_prev : tstamp_curr;
2642 `endif
2643
2644 // Increment push pointer
2645 if (push_ptr==(FIFO_DEPTH-1)) begin // {
2646 push_ptr = 0;
2647 end // }
2648 else begin // {
2649 push_ptr = push_ptr + 1;
2650 end // }
2651
2652 // Check for Overflow after push
2653 if (pop_ptr == push_ptr) begin // {
2654 `PR_ERROR ("tlb_sync", `ERROR,
2655 "C%0d T%0d IB Overflow. IFU is trying to fetch another instruction, but IB is already full.", mycid,mytid);
2656 end // }
2657
2658 end // }
2659endtask
2660
2661//----------------------------------------------------------
2662`endif
2663endmodule
2664
2665`endif
2666
2667`ifdef CORE_7
2668
2669module tlb_fifo_c7 (
2670
2671 // Inputs
2672 mytid,
2673
2674 // Outputs
2675 itlb_pipe_d
2676);
2677
2678`include "tlb_sync.vh"
2679
2680// FIFO_DEPTH is 1 more than IB depth in RTL
2681// so that overflow can be detected properly.
2682parameter FIFO_DEPTH = 9;
2683parameter PTR_WIDTH = 4;
2684
2685input [2:0] mytid;
2686output [(`TLB_FIFO_WIDTH-1):0] itlb_pipe_d;
2687`ifndef GATESIM
2688
2689wire [2:0] mycid;
2690wire push1; // 1st signal to qualify push_select
2691wire push2; // 2nd signal to qualify push_select
2692wire [3:0] push_select; // 1-4 tstamps are pushed
2693wire flush_upper;
2694wire flush_head;
2695wire pop;
2696wire itlb_miss;
2697wire icache_miss;
2698wire fetch_bypass;
2699wire exc_valid; // Exception valid
2700reg ib_full;
2701wire [7:0] ifu_err_vect;
2702wire [3:0] ifu_err_select;
2703wire [3:0] ifetch_err_vld;
2704
2705reg [(`TS_WIDTH-1):0] tstamp_curr;
2706reg [(`TS_WIDTH-1):0] tstamp_prev;
2707
2708reg [(`TLB_FIFO_WIDTH-1):0] fifo [0:(FIFO_DEPTH-1)]; // reg array
2709reg [(PTR_WIDTH-1):0] pop_ptr;
2710reg [(PTR_WIDTH-1):0] push_ptr;
2711reg [(`TLB_FIFO_WIDTH-1):0] itlb_pipe_d;
2712reg ready;
2713
2714//----------------------------------------------------------
2715// Create wires for reg array so signals can be viewed in Debussy
2716`ifdef DEBUG_TLB
2717 wire [(`TLB_FIFO_WIDTH-1):0] fifo_0;
2718 wire [(`TLB_FIFO_WIDTH-1):0] fifo_1;
2719 wire [(`TLB_FIFO_WIDTH-1):0] fifo_2;
2720 wire [(`TLB_FIFO_WIDTH-1):0] fifo_3;
2721 wire [(`TLB_FIFO_WIDTH-1):0] fifo_4;
2722 wire [(`TLB_FIFO_WIDTH-1):0] fifo_5;
2723 wire [(`TLB_FIFO_WIDTH-1):0] fifo_6;
2724 wire [(`TLB_FIFO_WIDTH-1):0] fifo_7;
2725 wire [(`TLB_FIFO_WIDTH-1):0] fifo_8;
2726 wire [(`TLB_FIFO_WIDTH-1):0] fifo_9;
2727
2728 assign fifo_0 = fifo[0];
2729 assign fifo_1 = fifo[1];
2730 assign fifo_2 = fifo[2];
2731 assign fifo_3 = fifo[3];
2732 assign fifo_4 = fifo[4];
2733 assign fifo_5 = fifo[5];
2734 assign fifo_6 = fifo[6];
2735 assign fifo_7 = fifo[7];
2736 assign fifo_8 = fifo[8];
2737 assign fifo_9 = fifo[9];
2738`endif
2739
2740
2741//----------------------------------------------------------
2742// DUT probes
2743
2744assign mycid = 7;
2745assign push1 = `SPC7.ifu_ftu.ftu_fetch_thr_c[mytid];
2746assign push2 = `SPC7.ifu_ftu.ftu_ibu_redirect_bf[mytid];
2747assign push_select = `SPC7.ifu_ftu.ftu_instr_valid_c;
2748assign flush_upper = `SPC7.pku.pku_flush_upper_buffer[mytid];
2749assign flush_head = `SPC7.pku.pku_flush_buffer0[mytid];
2750assign pop = `SPC7.pku.pku_pick_p[mytid];
2751assign itlb_miss = `PROBES7.itlb_miss[mytid];
2752assign icache_miss = `PROBES7.icache_miss[mytid];
2753assign fetch_bypass = `PROBES7.fetch_bypass[mytid];
2754assign exc_valid = `SPC7.ifu_ftu.ftu_exception_valid_c;
2755
2756// Error Injection - tlb_sync is pipelining some information that is useful to error injection code.
2757`ifdef TLB_FIFO_WIDE
2758assign ifu_err_vect = {tb_top.ras.ifu_err.ifu_err_code_c[4:0],tb_top.ras.ifu_err.ifu_err_way[2:0]};
2759assign ifu_err_select = tb_top.ras.ifu_err.ifu_err_select[3:0];
2760assign ifetch_err_vld = tb_top.ras.ifu_err.ifetch_err_vld[3:0];
2761`else
2762assign ifu_err_vect = 8'b0;
2763assign ifu_err_select = 4'b0;
2764assign ifetch_err_vld = 4'b0;
2765`endif
2766
2767//----------------------------------------------------------
2768initial begin // {
2769 ready = 0;
2770 @ (posedge `SPC7.l2clk);
2771 // Initialize fifo
2772 fifo_clear;
2773 itlb_pipe_d = 0;
2774 ready = `PARGS.tlb_sync_on;
2775end // }
2776
2777//----------------------------------------------------------
2778// push/pop from FIFO
2779
2780always @ (posedge (`SPC7.l2clk & ready)) begin // {
2781
2782 // Save tstamp if L1 Icache miss & ITLB hit (for later use if bypass)
2783 if (icache_miss & !itlb_miss) begin // {
2784 tstamp_prev = `TOP.core_cycle_cnt - 2;
2785 end // }
2786
2787
2788 // if POR|WMR, then no TLBread
2789 if (`TOP.in_reset_core) begin // {
2790 fifo_clear;
2791 end // }
2792 else begin // {
2793
2794 itlb_pipe_d <= pop ? fifo[pop_ptr] : itlb_pipe_d; // Get new value or hold state
2795
2796
2797 //------------------------
2798 // Pop FIFO - special case
2799
2800 // This code must be above the Push FIFO code.
2801 // to handle the case if (flush_head and push and IB was empty)
2802 // Only flush_head if fifo is not empty
2803 // Don't need to qualify with flush_upper because the buffer will
2804 // be cleared by code below.
2805 if (flush_head && (pop_ptr != push_ptr)) begin // {
2806 fifo_pop;
2807 end // }
2808
2809 //------------------------
2810 // Push FIFO
2811
2812 // push_select may be asserted at same time as exc_valid.
2813 // exc_valid should override.
2814
2815 // If exc_valid, I must push 2 valid tstamp in IB before making IB full.
2816 // this is because the exception instruction will get to W and will
2817 // need a ITLB_READ tstamp.
2818 // exc_valid will only be asserted if there is room in IB for 4 entries
2819 // so it is safe to push 2 entries.
2820 // It is required to push 2 because the 1st entry may be DS of annul branch,
2821 // then the exception happens on next instruction after DS.
2822
2823 if (exc_valid && push1 && !push2 && !flush_upper) begin // {
2824
2825 // It is possible to get back-to-back exceptions.
2826 // So, need to check for fifo full before fifo_push.
2827 // It is possible to have only 1 entry available after the 1 exception.
2828 // if there was a pop at the same time as the exception.
2829
2830 ib_full = (pop_ptr==0) ? (push_ptr==(FIFO_DEPTH-1)): (push_ptr==(pop_ptr-1));
2831 if (!ib_full) begin // {
2832 fifo_push(ifu_err_select[0], ifetch_err_vld[0]);
2833 end // }
2834
2835 ib_full = (pop_ptr==0) ? (push_ptr==(FIFO_DEPTH-1)): (push_ptr==(pop_ptr-1));
2836 if (!ib_full) begin // {
2837 fifo_push(ifu_err_select[1], ifetch_err_vld[1]);
2838 end // }
2839 end // }
2840
2841 else begin // {
2842
2843 if (push_select[0] && push1 && !push2) begin // {
2844 fifo_push(ifu_err_select[0], ifetch_err_vld[0]);
2845 end // }
2846
2847 if (push_select[1] && push1 && !push2) begin // {
2848 fifo_push(ifu_err_select[1], ifetch_err_vld[1]);
2849 end // }
2850
2851 if (push_select[2] && push1 && !push2) begin // {
2852 fifo_push(ifu_err_select[2], ifetch_err_vld[2]);
2853 end // }
2854
2855 if (push_select[3] && push1 && !push2) begin // {
2856 fifo_push(ifu_err_select[3], ifetch_err_vld[3]);
2857 end // }
2858
2859 end // }
2860
2861 //------------------------
2862 // Pop FIFO
2863
2864 // It is possible to push and flush_upper in the same cycle.
2865 // If this happens, flush_upper takes priority.
2866 // So, flush code must be after push code since same always block.
2867
2868 // If flush_head and push in same cycle, there will be 1 entry in IB.
2869 // Essentially, flush_head is ignored, then an entry is pushed.
2870
2871
2872 case ({flush_upper, flush_head, pop}) // {
2873 3'b000: begin
2874 // NOP
2875 end
2876 3'b001: begin
2877 fifo_pop;
2878 end
2879 3'b010: begin
2880 // NOP - case handled in code above
2881 end
2882 3'b011: begin
2883 `PR_ERROR ("tlb_sync", `ERROR,
2884 "C%0d T%0d Illegal signal combination for IB. flush_upper=%0b flush_head=%0b pick=%0b",
2885 mycid,mytid,flush_upper,flush_head,pop);
2886 end
2887 3'b100: begin
2888 // Only flush_upper if fifo is not empty
2889 if (pop_ptr != push_ptr) begin // {
2890 fifo_pop_upper;
2891 end // }
2892 end
2893 3'b101: begin
2894 fifo_clear;
2895 end
2896 3'b110: begin
2897 fifo_clear;
2898 end
2899 3'b111: begin
2900 `PR_ERROR ("tlb_sync", `ERROR,
2901 "C%0d T%0d Illegal signal combination for IB. flush_upper=%0b flush_head=%0b pick=%0b",
2902 mycid,mytid,flush_upper,flush_head,pop);
2903 end
2904 endcase // }
2905
2906 // It is possible to get a pop and exception.
2907 // In this case, the pop will happen, then the IB is made full.
2908 if (exc_valid && push1 && !push2 && !flush_upper) begin // {
2909 fifo_full;
2910 end // }
2911
2912 end // }
2913end // always }
2914
2915//----------------------------------------------------------
2916// Empty FIFO and reset push/pop pointers
2917task fifo_clear;
2918 integer i;
2919 begin // {
2920 // Initialize fifo
2921 pop_ptr = 0;
2922 push_ptr = 0;
2923
2924 for (i=0; i<FIFO_DEPTH; i=i+1) begin // {
2925 fifo[i] <= 0;
2926 end // }
2927
2928 end // }
2929endtask
2930
2931//----------------------------------------------------------
2932// Empty FIFO and reset push/pop pointers
2933task fifo_full;
2934 integer i;
2935 begin // {
2936
2937 // Increment push_ptr to full buffere
2938 if (pop_ptr == 0) begin // {
2939 push_ptr = FIFO_DEPTH-1;
2940 end // }
2941 else begin // {
2942 push_ptr = pop_ptr - 1;
2943 end // }
2944
2945 end // }
2946endtask
2947
2948//----------------------------------------------------------
2949// Pop item from FIFO
2950task fifo_pop;
2951
2952 begin // {
2953
2954 // Make sure the FIFO is not empty before pop
2955 if (pop_ptr == push_ptr) begin // {
2956 `PR_ERROR ("tlb_sync", `ERROR,
2957 "C%0d T%0d IB Underflow. PKU is trying to pick from empty IB.", mycid,mytid);
2958 end // }
2959
2960 // Clear entry in fifo
2961 fifo[pop_ptr] <= 0;
2962
2963 // Increment pop pointer
2964 if (pop_ptr==(FIFO_DEPTH-1)) begin // {
2965 pop_ptr = 0;
2966 end // }
2967 else begin // {
2968 pop_ptr = pop_ptr + 1;
2969 end // }
2970
2971
2972 end // }
2973endtask
2974
2975//----------------------------------------------------------
2976// Flush all items from FIFO except head
2977task fifo_pop_upper;
2978
2979 integer i;
2980
2981 begin // {
2982
2983 // Make sure the FIFO is not empty
2984 if (pop_ptr == push_ptr) begin // {
2985 `PR_ERROR ("tlb_sync", `ERROR,
2986 "C%0d T%0d IFU is trying to flush upper, but IB is empty.", mycid,mytid);
2987 end // }
2988
2989 // Make push ptr 1 entry above pop ptr
2990 if (pop_ptr==(FIFO_DEPTH-1)) begin // {
2991 push_ptr = 0;
2992 end // }
2993 else begin // {
2994 push_ptr = pop_ptr + 1;
2995 end // }
2996
2997
2998 end // }
2999endtask
3000
3001//----------------------------------------------------------
3002// Push item to FIFO
3003task fifo_push;
3004
3005 input err_select;
3006 input cache_err_vld;
3007 reg [7:0] tmp_err_vect;
3008
3009 begin // {
3010
3011 tstamp_curr = `TOP.core_cycle_cnt - 2;
3012
3013 `ifdef TLB_FIFO_WIDE
3014 tmp_err_vect = err_select ? ifu_err_vect : 8'b0;
3015 fifo[push_ptr] <= fetch_bypass ? {cache_err_vld,tmp_err_vect,tstamp_prev} : {cache_err_vld,tmp_err_vect,tstamp_curr};
3016 `else
3017 fifo[push_ptr] <= fetch_bypass ? tstamp_prev : tstamp_curr;
3018 `endif
3019
3020 // Increment push pointer
3021 if (push_ptr==(FIFO_DEPTH-1)) begin // {
3022 push_ptr = 0;
3023 end // }
3024 else begin // {
3025 push_ptr = push_ptr + 1;
3026 end // }
3027
3028 // Check for Overflow after push
3029 if (pop_ptr == push_ptr) begin // {
3030 `PR_ERROR ("tlb_sync", `ERROR,
3031 "C%0d T%0d IB Overflow. IFU is trying to fetch another instruction, but IB is already full.", mycid,mytid);
3032 end // }
3033
3034 end // }
3035endtask
3036
3037//----------------------------------------------------------
3038`endif
3039endmodule
3040
3041`endif
3042
3043//----------------------------------------------------------
3044//----------------------------------------------------------