Line data Source code
1 : // SPDX-License-Identifier: Apache-2.0
2 : // Copyright 2020 Western Digital Corporation or its affiliates.
3 : //
4 : // Licensed under the Apache License, Version 2.0 (the "License");
5 : // you may not use this file except in compliance with the License.
6 : // You may obtain a copy of the License at
7 : //
8 : // http://www.apache.org/licenses/LICENSE-2.0
9 : //
10 : // Unless required by applicable law or agreed to in writing, software
11 : // distributed under the License is distributed on an "AS IS" BASIS,
12 : // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 : // See the License for the specific language governing permissions and
14 : // limitations under the License.
15 :
16 : //********************************************************************************
17 : // el2_ifu_ifc_ctl.sv
18 : // Function: Fetch pipe control
19 : //
20 : // Comments:
21 : //********************************************************************************
22 :
23 : module el2_ifu_ifc_ctl
24 : import el2_pkg::*;
25 : #(
26 : `include "el2_param.vh"
27 : )
28 : (
29 69840565 : input logic clk, // Clock only while core active. Through one clock header. For flops with second clock header built in. Connected to ACTIVE_L2CLK.
30 69840565 : input logic free_l2clk, // Clock always. Through one clock header. For flops with second header built in.
31 :
32 338 : input logic rst_l, // reset enable, from core pin
33 : // Excluding scan_mode from coverage as its usage is determined by the integrator of the VeeR core.
34 : /*verilator coverage_off*/
35 : input logic scan_mode, // scan
36 : /*verilator coverage_on*/
37 :
38 6782653 : input logic ic_hit_f, // Icache hit
39 5908764 : input logic ifu_ic_mb_empty, // Miss buffer empty
40 :
41 5986539 : input logic ifu_fb_consume1, // Aligner consumed 1 fetch buffer
42 1761739 : input logic ifu_fb_consume2, // Aligner consumed 2 fetch buffers
43 :
44 232 : input logic dec_tlu_flush_noredir_wb, // Don't fetch on flush
45 673974 : input logic exu_flush_final, // FLush
46 227566 : input logic [31:1] exu_flush_path_final, // Flush path
47 :
48 3170544 : input logic ifu_bp_hit_taken_f, // btb hit, select the target path
49 518479 : input logic [31:1] ifu_bp_btb_target_f, // predicted target PC
50 :
51 16 : input logic ic_dma_active, // IC DMA active, stop fetching
52 2632580 : input logic ic_write_stall, // IC is writing, stop fetching
53 26 : input logic dma_iccm_stall_any, // force a stall in the fetch pipe for DMA ICCM access
54 :
55 0 : input logic [31:0] dec_tlu_mrac_ff , // side_effect and cacheable for each region
56 :
57 443 : output logic [31:1] ifc_fetch_addr_f, // fetch addr F
58 443 : output logic [31:1] ifc_fetch_addr_bf, // fetch addr BF
59 :
60 3714536 : output logic ifc_fetch_req_f, // fetch request valid F
61 :
62 614908 : output logic ifu_pmu_fetch_stall, // pmu event measuring fetch stall
63 :
64 375 : output logic ifc_fetch_uncacheable_bf, // The fetch request is uncacheable space. BF stage
65 3714574 : output logic ifc_fetch_req_bf, // Fetch request. Comes with the address. BF stage
66 568 : output logic ifc_fetch_req_bf_raw, // Fetch request without some qualifications. Used for clock-gating. BF stage
67 84 : output logic ifc_iccm_access_bf, // This request is to the ICCM. Do not generate misses to the bus.
68 2 : output logic ifc_region_acc_fault_bf, // Access fault. in ICCM region but offset is outside defined ICCM.
69 :
70 640547 : output logic ifc_dma_access_ok // fetch is not accessing the ICCM, DMA can proceed
71 :
72 :
73 : );
74 :
75 443 : logic [31:1] fetch_addr_bf;
76 445 : logic [31:1] fetch_addr_next;
77 445816 : logic [3:0] fb_write_f, fb_write_ns;
78 :
79 1083954 : logic fb_full_f_ns, fb_full_f;
80 605 : logic fb_right, fb_right2, fb_left, wfm, idle;
81 5885178 : logic sel_last_addr_bf, sel_next_addr_bf;
82 8567842 : logic miss_f, miss_a;
83 26 : logic flush_fb, dma_iccm_stall_any_f;
84 790 : logic mb_empty_mod, goto_idle, leave_idle;
85 3661454 : logic fetch_bf_en;
86 626520 : logic line_wrap;
87 472249 : logic fetch_addr_next_1;
88 :
89 : // FSM assignment
90 : typedef enum logic [1:0] { IDLE = 2'b00 ,
91 : FETCH = 2'b01 ,
92 : STALL = 2'b10 ,
93 : WFM = 2'b11 } state_t ;
94 560 : state_t state ;
95 560 : state_t next_state ;
96 :
97 42 : logic dma_stall;
98 : assign dma_stall = ic_dma_active | dma_iccm_stall_any_f;
99 :
100 :
101 :
102 : // Fetch address mux
103 : // - flush
104 : // - Miss *or* flush during WFM (icache miss buffer is blocking)
105 : // - Sequential
106 :
107 : if(pt.BTB_ENABLE==1) begin : genblock1
108 : logic sel_btb_addr_bf;
109 :
110 : assign sel_last_addr_bf = ~exu_flush_final & (~ifc_fetch_req_f | ~ic_hit_f);
111 : assign sel_btb_addr_bf = ~exu_flush_final & ifc_fetch_req_f & ifu_bp_hit_taken_f & ic_hit_f;
112 : assign sel_next_addr_bf = ~exu_flush_final & ifc_fetch_req_f & ~ifu_bp_hit_taken_f & ic_hit_f;
113 :
114 :
115 : assign fetch_addr_bf[31:1] = ( ({31{exu_flush_final}} & exu_flush_path_final[31:1]) | // FLUSH path
116 : ({31{sel_last_addr_bf}} & ifc_fetch_addr_f[31:1]) | // MISS path
117 : ({31{sel_btb_addr_bf}} & {ifu_bp_btb_target_f[31:1]})| // BTB target
118 : ({31{sel_next_addr_bf}} & {fetch_addr_next[31:1]})); // SEQ path
119 :
120 :
121 : end // if (pt.BTB_ENABLE=1)
122 : else begin
123 : assign sel_last_addr_bf = ~exu_flush_final & (~ifc_fetch_req_f | ~ic_hit_f);
124 : assign sel_next_addr_bf = ~exu_flush_final & ifc_fetch_req_f & ic_hit_f;
125 :
126 :
127 : assign fetch_addr_bf[31:1] = ( ({31{exu_flush_final}} & exu_flush_path_final[31:1]) | // FLUSH path
128 : ({31{sel_last_addr_bf}} & ifc_fetch_addr_f[31:1]) | // MISS path
129 : ({31{sel_next_addr_bf}} & {fetch_addr_next[31:1]})); // SEQ path
130 :
131 : end
132 : assign fetch_addr_next[31:1] = {({ifc_fetch_addr_f[31:2]} + 30'b1), fetch_addr_next_1 };
133 : assign line_wrap = (fetch_addr_next[pt.ICACHE_TAG_INDEX_LO] ^ ifc_fetch_addr_f[pt.ICACHE_TAG_INDEX_LO]);
134 :
135 : assign fetch_addr_next_1 = line_wrap ? 1'b0 : ifc_fetch_addr_f[1];
136 :
137 : assign ifc_fetch_req_bf_raw = ~idle;
138 : assign ifc_fetch_req_bf = ifc_fetch_req_bf_raw &
139 :
140 : ~(fb_full_f_ns & ~(ifu_fb_consume2 | ifu_fb_consume1)) &
141 : ~dma_stall &
142 : ~ic_write_stall &
143 : ~dec_tlu_flush_noredir_wb;
144 :
145 :
146 : assign fetch_bf_en = exu_flush_final | ifc_fetch_req_f;
147 :
148 : assign miss_f = ifc_fetch_req_f & ~ic_hit_f & ~exu_flush_final;
149 :
150 : assign mb_empty_mod = (ifu_ic_mb_empty | exu_flush_final) & ~dma_stall & ~miss_f & ~miss_a;
151 :
152 : // Halt flushes and takes us to IDLE
153 : assign goto_idle = exu_flush_final & dec_tlu_flush_noredir_wb;
154 : // If we're in IDLE, and we get a flush, goto FETCH
155 : assign leave_idle = exu_flush_final & ~dec_tlu_flush_noredir_wb & idle;
156 :
157 : //.i 7
158 : //.o 2
159 : //.ilb state[1] state[0] reset_delayed miss_f mb_empty_mod goto_idle leave_idle
160 : //.ob next_state[1] next_state[0]
161 : //.type fr
162 : //
163 : //# fetch 01, stall 10, wfm 11, idle 00
164 : //-- 1---- 01
165 : //-- 0--1- 00
166 : //00 0--00 00
167 : //00 0--01 01
168 : //
169 : //01 01-0- 11
170 : //01 00-0- 01
171 : //
172 : //11 0-10- 01
173 : //11 0-00- 11
174 :
175 : assign next_state[1] = (~state[1] & state[0] & miss_f & ~goto_idle) |
176 : (state[1] & ~mb_empty_mod & ~goto_idle);
177 :
178 : assign next_state[0] = (~goto_idle & leave_idle) | (state[0] & ~goto_idle);
179 :
180 : assign flush_fb = exu_flush_final;
181 :
182 : // model fb write logic to mass balance the fetch buffers
183 : assign fb_right = ( ifu_fb_consume1 & ~ifu_fb_consume2 & (~ifc_fetch_req_f | miss_f)) | // Consumed and no new fetch
184 : (ifu_fb_consume2 & ifc_fetch_req_f); // Consumed 2 and new fetch
185 :
186 :
187 : assign fb_right2 = (ifu_fb_consume2 & (~ifc_fetch_req_f | miss_f)); // Consumed 2 and no new fetch
188 :
189 : assign fb_left = ifc_fetch_req_f & ~(ifu_fb_consume1 | ifu_fb_consume2) & ~miss_f;
190 :
191 : // CBH
192 : assign fb_write_ns[3:0] = ( ({4{(flush_fb)}} & 4'b0001) |
193 : ({4{~flush_fb & fb_right }} & {1'b0, fb_write_f[3:1]}) |
194 : ({4{~flush_fb & fb_right2}} & {2'b0, fb_write_f[3:2]}) |
195 : ({4{~flush_fb & fb_left }} & {fb_write_f[2:0], 1'b0}) |
196 : ({4{~flush_fb & ~fb_right & ~fb_right2 & ~fb_left}} & fb_write_f[3:0]));
197 :
198 :
199 : assign fb_full_f_ns = fb_write_ns[3];
200 :
201 : assign idle = state == IDLE ;
202 : assign wfm = state == WFM ;
203 :
204 : rvdffie #(10) fbwrite_ff (.*, .clk(free_l2clk),
205 : .din( {dma_iccm_stall_any, miss_f, ifc_fetch_req_bf, next_state[1:0], fb_full_f_ns, fb_write_ns[3:0]}),
206 : .dout({dma_iccm_stall_any_f, miss_a, ifc_fetch_req_f, state[1:0], fb_full_f, fb_write_f[3:0]}));
207 :
208 : assign ifu_pmu_fetch_stall = wfm |
209 : (ifc_fetch_req_bf_raw &
210 : ( (fb_full_f & ~(ifu_fb_consume2 | ifu_fb_consume1 | exu_flush_final)) |
211 : dma_stall));
212 :
213 :
214 :
215 : assign ifc_fetch_addr_bf[31:1] = fetch_addr_bf[31:1];
216 :
217 : rvdffpcie #(31) faddrf1_ff (.*, .en(fetch_bf_en), .din(fetch_addr_bf[31:1]), .dout(ifc_fetch_addr_f[31:1]));
218 :
219 :
220 : if (pt.ICCM_ENABLE) begin : genblock2
221 : logic iccm_acc_in_region_bf;
222 : logic iccm_acc_in_range_bf;
223 : rvrangecheck #( .CCM_SADR (pt.ICCM_SADR),
224 : .CCM_SIZE (pt.ICCM_SIZE) ) iccm_rangecheck (
225 : .addr ({ifc_fetch_addr_bf[31:1],1'b0}) ,
226 : .in_range (iccm_acc_in_range_bf) ,
227 : .in_region(iccm_acc_in_region_bf)
228 : );
229 :
230 : assign ifc_iccm_access_bf = iccm_acc_in_range_bf ;
231 :
232 : assign ifc_dma_access_ok = ( (~ifc_iccm_access_bf |
233 : (fb_full_f & ~(ifu_fb_consume2 | ifu_fb_consume1)) |
234 : (wfm & ~ifc_fetch_req_bf) |
235 : idle ) & ~exu_flush_final) |
236 : dma_iccm_stall_any_f;
237 :
238 : assign ifc_region_acc_fault_bf = ~iccm_acc_in_range_bf & iccm_acc_in_region_bf ;
239 : end
240 : else begin
241 : assign ifc_iccm_access_bf = 1'b0 ;
242 : assign ifc_dma_access_ok = 1'b0 ;
243 : assign ifc_region_acc_fault_bf = 1'b0 ;
244 : end
245 :
246 : assign ifc_fetch_uncacheable_bf = ~dec_tlu_mrac_ff[{ifc_fetch_addr_bf[31:28] , 1'b0 }] ; // bit 0 of each region description is the cacheable bit
247 :
248 : endmodule // el2_ifu_ifc_ctl
249 :
|