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 : // $Id$
18 : //
19 : //
20 : // Owner:
21 : // Function: lsu interface with interface queue
22 : // Comments:
23 : //
24 : //********************************************************************************
25 :
26 : module el2_lsu_bus_buffer
27 : import el2_pkg::*;
28 : #(
29 : `include "el2_param.vh"
30 : )(
31 115884880 : input logic clk, // Clock only while core active. Through one clock header. For flops with second clock header built in. Connected to ACTIVE_L2CLK.
32 2 : input logic clk_override, // Override non-functional clock gating
33 299 : input logic rst_l, // reset, active low
34 : // Excluding scan_mode from coverage as its usage is determined by the integrator of the VeeR core.
35 : /*pragma coverage off*/
36 : input logic scan_mode, // scan mode
37 : /*pragma coverage on*/
38 0 : input logic dec_tlu_external_ldfwd_disable, // disable load to load forwarding for externals
39 9 : input logic dec_tlu_wb_coalescing_disable, // disable write buffer coalescing
40 283 : input logic dec_tlu_sideeffect_posted_disable, // Don't block the sideeffect load store to the bus
41 0 : input logic dec_tlu_force_halt,
42 :
43 : // various clocks needed for the bus reads and writes
44 2319254 : input logic lsu_bus_obuf_c1_clken,
45 1219435 : input logic lsu_busm_clken,
46 115884880 : input logic lsu_c2_r_clk,
47 115884880 : input logic lsu_bus_ibuf_c1_clk,
48 0 : input logic lsu_bus_obuf_c1_clk,
49 115884880 : input logic lsu_bus_buf_c1_clk,
50 115884880 : input logic lsu_free_c2_clk,
51 0 : input logic lsu_busm_clk,
52 :
53 :
54 3803483 : input logic dec_lsu_valid_raw_d, // Raw valid for address computation
55 3807141 : input el2_lsu_pkt_t lsu_pkt_m, // lsu packet flowing down the pipe
56 3807139 : input el2_lsu_pkt_t lsu_pkt_r, // lsu packet flowing down the pipe
57 :
58 1876037 : input logic [31:0] lsu_addr_m, // lsu address flowing down the pipe
59 1876261 : input logic [31:0] end_addr_m, // lsu address flowing down the pipe
60 1866834 : input logic [31:0] lsu_addr_r, // lsu address flowing down the pipe
61 1867058 : input logic [31:0] end_addr_r, // lsu address flowing down the pipe
62 350196 : input logic [31:0] store_data_r, // store data flowing down the pipe
63 :
64 410815 : input logic no_word_merge_r, // r store doesn't need to wait in ibuf since it will not coalesce
65 391125 : input logic no_dword_merge_r, // r store doesn't need to wait in ibuf since it will not coalesce
66 1877441 : input logic lsu_busreq_m, // bus request is in m
67 1868284 : output logic lsu_busreq_r, // bus request is in r
68 9314 : input logic ld_full_hit_m, // load can get all its byte from a write buffer entry
69 1277508 : input logic flush_m_up, // flush
70 252372 : input logic flush_r, // flush
71 2572720 : input logic lsu_commit_r, // lsu instruction in r commits
72 20721 : input logic is_sideeffects_r, // lsu attribute is side_effects
73 26182 : input logic ldst_dual_d, // load/store is unaligned at 32 bit boundary
74 26182 : input logic ldst_dual_m, // load/store is unaligned at 32 bit boundary
75 26182 : input logic ldst_dual_r, // load/store is unaligned at 32 bit boundary
76 :
77 1988166 : input logic [7:0] ldst_byteen_ext_m, // HI and LO signals
78 :
79 778481 : output logic lsu_bus_buffer_pend_any, // bus buffer has a pending bus entry
80 259452 : output logic lsu_bus_buffer_full_any, // bus buffer is full
81 1295586 : output logic lsu_bus_buffer_empty_any, // bus buffer is empty
82 :
83 24356 : output logic [3:0] ld_byte_hit_buf_lo, ld_byte_hit_buf_hi, // Byte enables for forwarding data
84 19720 : output logic [31:0] ld_fwddata_buf_lo, ld_fwddata_buf_hi, // load forwarding data
85 :
86 2 : output logic lsu_imprecise_error_load_any, // imprecise load bus error
87 2 : output logic lsu_imprecise_error_store_any, // imprecise store bus error
88 788355 : output logic [31:0] lsu_imprecise_error_addr_any, // address of the imprecise error
89 :
90 : // Non-blocking loads
91 1109559 : output logic lsu_nonblock_load_valid_m, // there is an external load -> put in the cam
92 1651331 : output logic [pt.LSU_NUM_NBLOAD_WIDTH-1:0] lsu_nonblock_load_tag_m, // the tag of the external non block load
93 0 : output logic lsu_nonblock_load_inv_r, // invalidate signal for the cam entry for non block loads
94 1651329 : output logic [pt.LSU_NUM_NBLOAD_WIDTH-1:0] lsu_nonblock_load_inv_tag_r, // tag of the enrty which needs to be invalidated
95 1129044 : output logic lsu_nonblock_load_data_valid, // the non block is valid - sending information back to the cam
96 2 : output logic lsu_nonblock_load_data_error, // non block load has an error
97 435592 : output logic [pt.LSU_NUM_NBLOAD_WIDTH-1:0] lsu_nonblock_load_data_tag, // the tag of the non block load sending the data/error
98 332494 : output logic [31:0] lsu_nonblock_load_data, // Data of the non block load
99 :
100 : // PMU events
101 1860410 : output logic lsu_pmu_bus_trxn,
102 25958 : output logic lsu_pmu_bus_misaligned,
103 4 : output logic lsu_pmu_bus_error,
104 47098 : output logic lsu_pmu_bus_busy,
105 :
106 : // AXI Write Channels
107 820482 : output logic lsu_axi_awvalid,
108 1365255 : input logic lsu_axi_awready,
109 607034 : output logic [pt.LSU_BUS_TAG-1:0] lsu_axi_awid,
110 614263 : output logic [31:0] lsu_axi_awaddr,
111 224636 : output logic [3:0] lsu_axi_awregion,
112 : /* exclude signals that are tied to constant value in this file */
113 : /*pragma coverage off*/
114 : output logic [7:0] lsu_axi_awlen,
115 : /*pragma coverage on*/
116 3043 : output logic [2:0] lsu_axi_awsize,
117 : /* exclude signals that are tied to constant value in this file */
118 : /*pragma coverage off*/
119 : output logic [1:0] lsu_axi_awburst,
120 : output logic lsu_axi_awlock,
121 : /*pragma coverage on*/
122 1957 : output logic [3:0] lsu_axi_awcache,
123 : /* exclude signals that are tied to constant value in this file */
124 : /*pragma coverage off*/
125 : output logic [2:0] lsu_axi_awprot,
126 : output logic [3:0] lsu_axi_awqos,
127 : /*pragma coverage on*/
128 :
129 820482 : output logic lsu_axi_wvalid,
130 1365255 : input logic lsu_axi_wready,
131 217764 : output logic [63:0] lsu_axi_wdata,
132 430439 : output logic [7:0] lsu_axi_wstrb,
133 298 : output logic lsu_axi_wlast,
134 :
135 828182 : input logic lsu_axi_bvalid,
136 : /* exclude signals that are tied to constant value in this file */
137 : /*pragma coverage off*/
138 : output logic lsu_axi_bready,
139 : /*pragma coverage on*/
140 2 : input logic [1:0] lsu_axi_bresp,
141 332383 : input logic [pt.LSU_BUS_TAG-1:0] lsu_axi_bid,
142 :
143 : // AXI Read Channels
144 1103398 : output logic lsu_axi_arvalid,
145 1381994 : input logic lsu_axi_arready,
146 607034 : output logic [pt.LSU_BUS_TAG-1:0] lsu_axi_arid,
147 614263 : output logic [31:0] lsu_axi_araddr,
148 224636 : output logic [3:0] lsu_axi_arregion,
149 : /* exclude signals that are tied to constant value in this file */
150 : /*pragma coverage off*/
151 : output logic [7:0] lsu_axi_arlen,
152 : /*pragma coverage on*/
153 3043 : output logic [2:0] lsu_axi_arsize,
154 : /* exclude signals that are tied to constant value in this file */
155 : /*pragma coverage off*/
156 : output logic [1:0] lsu_axi_arburst,
157 : output logic lsu_axi_arlock,
158 : /*pragma coverage on*/
159 1957 : output logic [3:0] lsu_axi_arcache,
160 : /* exclude signals that are tied to constant value in this file */
161 : /*pragma coverage off*/
162 : output logic [2:0] lsu_axi_arprot,
163 : output logic [3:0] lsu_axi_arqos,
164 : /*pragma coverage on*/
165 :
166 1135692 : input logic lsu_axi_rvalid,
167 : /* exclude signals that are tied to constant value in this file */
168 : /*pragma coverage off*/
169 : output logic lsu_axi_rready,
170 : /*pragma coverage on*/
171 258175 : input logic [pt.LSU_BUS_TAG-1:0] lsu_axi_rid,
172 97123 : input logic [63:0] lsu_axi_rdata,
173 2 : input logic [1:0] lsu_axi_rresp,
174 :
175 327 : input logic lsu_bus_clk_en,
176 329 : input logic lsu_bus_clk_en_q
177 :
178 : );
179 :
180 : // For Ld: IDLE -> START_WAIT -> CMD -> RESP -> DONE_PARTIAL(?) -> DONE_WAIT(?) -> DONE -> IDLE
181 : // For St: IDLE -> START_WAIT -> CMD -> RESP(?) -> IDLE
182 : typedef enum logic [2:0] {IDLE=3'b000, START_WAIT=3'b001, CMD=3'b010, RESP=3'b011, DONE_PARTIAL=3'b100, DONE_WAIT=3'b101, DONE=3'b110} state_t;
183 :
184 : localparam DEPTH = pt.LSU_NUM_NBLOAD;
185 : localparam DEPTH_LOG2 = pt.LSU_NUM_NBLOAD_WIDTH;
186 : localparam TIMER = 8; // This can be only power of 2
187 : localparam TIMER_MAX = TIMER - 1; // Maximum value of timer
188 : localparam TIMER_LOG2 = (TIMER < 2) ? 1 : $clog2(TIMER);
189 :
190 1988166 : logic [3:0] ldst_byteen_hi_m, ldst_byteen_lo_m;
191 25760 : logic [DEPTH-1:0] ld_addr_hitvec_lo, ld_addr_hitvec_hi;
192 10858 : logic [3:0][DEPTH-1:0] ld_byte_hitvec_lo, ld_byte_hitvec_hi;
193 10722 : logic [3:0][DEPTH-1:0] ld_byte_hitvecfn_lo, ld_byte_hitvecfn_hi;
194 :
195 13826 : logic ld_addr_ibuf_hit_lo, ld_addr_ibuf_hit_hi;
196 5618 : logic [3:0] ld_byte_ibuf_hit_lo, ld_byte_ibuf_hit_hi;
197 :
198 1701165 : logic [3:0] ldst_byteen_r;
199 1982454 : logic [3:0] ldst_byteen_hi_r, ldst_byteen_lo_r;
200 315776 : logic [31:0] store_data_hi_r, store_data_lo_r;
201 40463 : logic is_aligned_r; // Aligned load/store
202 13202 : logic ldst_samedw_r;
203 :
204 1109413 : logic lsu_nonblock_load_valid_r;
205 415108 : logic [31:0] lsu_nonblock_load_data_hi, lsu_nonblock_load_data_lo, lsu_nonblock_data_unalgn;
206 270869 : logic [1:0] lsu_nonblock_addr_offset;
207 127544 : logic [1:0] lsu_nonblock_sz;
208 341304 : logic lsu_nonblock_unsign;
209 1129046 : logic lsu_nonblock_load_data_ready;
210 :
211 634503 : logic [DEPTH-1:0] CmdPtr0Dec, CmdPtr1Dec;
212 176354 : logic [DEPTH-1:0] RspPtrDec;
213 230604 : logic [DEPTH_LOG2-1:0] CmdPtr0, CmdPtr1;
214 334718 : logic [DEPTH_LOG2-1:0] RspPtr;
215 1651331 : logic [DEPTH_LOG2-1:0] WrPtr0_m, WrPtr0_r;
216 1601698 : logic [DEPTH_LOG2-1:0] WrPtr1_m, WrPtr1_r;
217 1002113 : logic found_wrptr0, found_wrptr1, found_cmdptr0, found_cmdptr1;
218 2164541 : logic [3:0] buf_numvld_any, buf_numvld_wrcmd_any, buf_numvld_cmd_any, buf_numvld_pend_any;
219 339704 : logic any_done_wait_state;
220 11123 : logic bus_sideeffect_pend;
221 27 : logic bus_coalescing_disable;
222 :
223 386934 : logic bus_addr_match_pending;
224 1862514 : logic bus_cmd_sent, bus_cmd_ready;
225 827750 : logic bus_wcmd_sent, bus_wdata_sent;
226 1300907 : logic bus_rsp_read, bus_rsp_write;
227 344053 : logic [pt.LSU_BUS_TAG-1:0] bus_rsp_read_tag, bus_rsp_write_tag;
228 4 : logic bus_rsp_read_error, bus_rsp_write_error;
229 97123 : logic [63:0] bus_rsp_rdata;
230 :
231 : // Bus buffer signals
232 1628048 : state_t [DEPTH-1:0] buf_state;
233 101402 : logic [DEPTH-1:0][1:0] buf_sz;
234 496321 : logic [DEPTH-1:0][31:0] buf_addr;
235 282733 : logic [DEPTH-1:0][3:0] buf_byteen;
236 525 : logic [DEPTH-1:0] buf_sideeffect;
237 323386 : logic [DEPTH-1:0] buf_write;
238 302444 : logic [DEPTH-1:0] buf_unsign;
239 13054 : logic [DEPTH-1:0] buf_dual;
240 7905 : logic [DEPTH-1:0] buf_samedw;
241 89577 : logic [DEPTH-1:0] buf_nomerge;
242 7049 : logic [DEPTH-1:0] buf_dualhi;
243 410361 : logic [DEPTH-1:0][DEPTH_LOG2-1:0] buf_dualtag;
244 176354 : logic [DEPTH-1:0] buf_ldfwd;
245 161460 : logic [DEPTH-1:0][DEPTH_LOG2-1:0] buf_ldfwdtag;
246 4 : logic [DEPTH-1:0] buf_error;
247 420217 : logic [DEPTH-1:0][31:0] buf_data;
248 1486523 : logic [DEPTH-1:0][DEPTH-1:0] buf_age, buf_age_younger;
249 298546 : logic [DEPTH-1:0][DEPTH-1:0] buf_rspage, buf_rsp_pickage;
250 :
251 1630880 : state_t [DEPTH-1:0] buf_nxtstate;
252 859960 : logic [DEPTH-1:0] buf_rst;
253 2731535 : logic [DEPTH-1:0] buf_state_en;
254 1477950 : logic [DEPTH-1:0] buf_cmd_state_bus_en;
255 1476294 : logic [DEPTH-1:0] buf_resp_state_bus_en;
256 2097000 : logic [DEPTH-1:0] buf_state_bus_en;
257 31862 : logic [DEPTH-1:0] buf_dual_in;
258 16590 : logic [DEPTH-1:0] buf_samedw_in;
259 515549 : logic [DEPTH-1:0] buf_nomerge_in;
260 20721 : logic [DEPTH-1:0] buf_sideeffect_in;
261 664062 : logic [DEPTH-1:0] buf_unsign_in;
262 1690108 : logic [DEPTH-1:0][1:0] buf_sz_in;
263 1545697 : logic [DEPTH-1:0] buf_write_in;
264 1478153 : logic [DEPTH-1:0] buf_wr_en;
265 15768 : logic [DEPTH-1:0] buf_dualhi_in;
266 2072443 : logic [DEPTH-1:0][DEPTH_LOG2-1:0] buf_dualtag_in;
267 1012468 : logic [DEPTH-1:0] buf_ldfwd_en;
268 1477977 : logic [DEPTH-1:0] buf_ldfwd_in;
269 293700 : logic [DEPTH-1:0][DEPTH_LOG2-1:0] buf_ldfwdtag_in;
270 2158432 : logic [DEPTH-1:0][3:0] buf_byteen_in;
271 2095648 : logic [DEPTH-1:0][31:0] buf_addr_in;
272 933207 : logic [DEPTH-1:0][31:0] buf_data_in;
273 4 : logic [DEPTH-1:0] buf_error_en;
274 2336313 : logic [DEPTH-1:0] buf_data_en;
275 80962 : logic [DEPTH-1:0][DEPTH-1:0] buf_age_in;
276 80962 : logic [DEPTH-1:0][DEPTH-1:0] buf_ageQ;
277 307306 : logic [DEPTH-1:0][DEPTH-1:0] buf_rspage_set;
278 307304 : logic [DEPTH-1:0][DEPTH-1:0] buf_rspage_in;
279 307304 : logic [DEPTH-1:0][DEPTH-1:0] buf_rspageQ;
280 :
281 : // Input buffer signals
282 761992 : logic ibuf_valid;
283 8415 : logic ibuf_dual;
284 5367 : logic ibuf_samedw;
285 170 : logic ibuf_nomerge;
286 143939 : logic [DEPTH_LOG2-1:0] ibuf_tag;
287 144158 : logic [DEPTH_LOG2-1:0] ibuf_dualtag;
288 173 : logic ibuf_sideeffect;
289 2 : logic ibuf_unsign;
290 341 : logic ibuf_write;
291 45123 : logic [1:0] ibuf_sz;
292 68535 : logic [3:0] ibuf_byteen;
293 170989 : logic [31:0] ibuf_addr;
294 130645 : logic [31:0] ibuf_data;
295 2882218 : logic [TIMER_LOG2-1:0] ibuf_timer;
296 :
297 1158251 : logic ibuf_byp;
298 767087 : logic ibuf_wr_en;
299 761978 : logic ibuf_rst;
300 234586 : logic ibuf_force_drain;
301 762414 : logic ibuf_drain_vld;
302 571968 : logic [DEPTH-1:0] ibuf_drainvec_vld;
303 1671181 : logic [DEPTH_LOG2-1:0] ibuf_tag_in;
304 1651329 : logic [DEPTH_LOG2-1:0] ibuf_dualtag_in;
305 1542540 : logic [1:0] ibuf_sz_in;
306 1866834 : logic [31:0] ibuf_addr_in;
307 1958877 : logic [3:0] ibuf_byteen_in;
308 315976 : logic [31:0] ibuf_data_in;
309 2882256 : logic [TIMER_LOG2-1:0] ibuf_timer_in;
310 68541 : logic [3:0] ibuf_byteen_out;
311 130645 : logic [31:0] ibuf_data_out;
312 30992 : logic ibuf_merge_en, ibuf_merge_in;
313 :
314 : // Output buffer signals
315 1788340 : logic obuf_valid;
316 370166 : logic obuf_write;
317 339701 : logic obuf_nosend;
318 1134312 : logic obuf_rdrsp_pend;
319 1659 : logic obuf_sideeffect;
320 860789 : logic [31:0] obuf_addr;
321 217764 : logic [63:0] obuf_data;
322 132317 : logic [1:0] obuf_sz;
323 843494 : logic [7:0] obuf_byteen;
324 5916 : logic obuf_merge;
325 0 : logic obuf_cmd_done, obuf_data_done;
326 607034 : logic [pt.LSU_BUS_TAG-1:0] obuf_tag0;
327 525370 : logic [pt.LSU_BUS_TAG-1:0] obuf_tag1;
328 240167 : logic [pt.LSU_BUS_TAG-1:0] obuf_rdrsp_tag;
329 :
330 1040997 : logic ibuf_buf_byp;
331 55926 : logic obuf_force_wr_en;
332 310812 : logic obuf_wr_wait;
333 1806860 : logic obuf_wr_en, obuf_wr_enQ;
334 1788338 : logic obuf_rst;
335 412936 : logic obuf_write_in;
336 993834 : logic obuf_nosend_in;
337 327 : logic obuf_rdrsp_pend_en;
338 1134312 : logic obuf_rdrsp_pend_in;
339 1729 : logic obuf_sideeffect_in;
340 32954 : logic obuf_aligned_in;
341 899304 : logic [31:0] obuf_addr_in;
342 350814 : logic [63:0] obuf_data_in;
343 150766 : logic [1:0] obuf_sz_in;
344 881677 : logic [7:0] obuf_byteen_in;
345 11414 : logic obuf_merge_in;
346 0 : logic obuf_cmd_done_in, obuf_data_done_in;
347 610776 : logic [pt.LSU_BUS_TAG-1:0] obuf_tag0_in;
348 1007283 : logic [pt.LSU_BUS_TAG-1:0] obuf_tag1_in;
349 240167 : logic [pt.LSU_BUS_TAG-1:0] obuf_rdrsp_tag_in;
350 :
351 11414 : logic obuf_merge_en;
352 1139151 : logic [TIMER_LOG2-1:0] obuf_wr_timer, obuf_wr_timer_in;
353 897141 : logic [7:0] obuf_byteen0_in, obuf_byteen1_in;
354 350814 : logic [63:0] obuf_data0_in, obuf_data1_in;
355 :
356 1365297 : logic lsu_axi_awvalid_q, lsu_axi_awready_q;
357 1365297 : logic lsu_axi_wvalid_q, lsu_axi_wready_q;
358 1381991 : logic lsu_axi_arvalid_q, lsu_axi_arready_q;
359 828149 : logic lsu_axi_bvalid_q, lsu_axi_bready_q;
360 1135743 : logic lsu_axi_rvalid_q, lsu_axi_rready_q;
361 344055 : logic [pt.LSU_BUS_TAG-1:0] lsu_axi_bid_q, lsu_axi_rid_q;
362 4 : logic [1:0] lsu_axi_bresp_q, lsu_axi_rresp_q;
363 0 : logic [pt.LSU_BUS_TAG-1:0] lsu_imprecise_error_store_tag;
364 96835 : logic [63:0] lsu_axi_rdata_q;
365 :
366 : //------------------------------------------------------------------------------
367 : // Load forwarding logic start
368 : //------------------------------------------------------------------------------
369 :
370 : // Function to do 8 to 3 bit encoding
371 362793921 : function automatic logic [2:0] f_Enc8to3;
372 : input logic [7:0] Dec_value;
373 :
374 : logic [2:0] Enc_value;
375 362793921 : Enc_value[0] = Dec_value[1] | Dec_value[3] | Dec_value[5] | Dec_value[7];
376 362793921 : Enc_value[1] = Dec_value[2] | Dec_value[3] | Dec_value[6] | Dec_value[7];
377 362793921 : Enc_value[2] = Dec_value[4] | Dec_value[5] | Dec_value[6] | Dec_value[7];
378 :
379 362793921 : return Enc_value[2:0];
380 : endfunction // f_Enc8to3
381 :
382 : // Buffer hit logic for bus load forwarding
383 : assign ldst_byteen_hi_m[3:0] = ldst_byteen_ext_m[7:4];
384 : assign ldst_byteen_lo_m[3:0] = ldst_byteen_ext_m[3:0];
385 : for (genvar i=0; i<DEPTH; i++) begin
386 : assign ld_addr_hitvec_lo[i] = (lsu_addr_m[31:2] == buf_addr[i][31:2]) & buf_write[i] & (buf_state[i] != IDLE) & lsu_busreq_m;
387 : assign ld_addr_hitvec_hi[i] = (end_addr_m[31:2] == buf_addr[i][31:2]) & buf_write[i] & (buf_state[i] != IDLE) & lsu_busreq_m;
388 : end
389 :
390 : for (genvar j=0; j<4; j++) begin
391 : assign ld_byte_hit_buf_lo[j] = |(ld_byte_hitvecfn_lo[j]) | ld_byte_ibuf_hit_lo[j];
392 : assign ld_byte_hit_buf_hi[j] = |(ld_byte_hitvecfn_hi[j]) | ld_byte_ibuf_hit_hi[j];
393 : for (genvar i=0; i<DEPTH; i++) begin
394 : assign ld_byte_hitvec_lo[j][i] = ld_addr_hitvec_lo[i] & buf_byteen[i][j] & ldst_byteen_lo_m[j];
395 : assign ld_byte_hitvec_hi[j][i] = ld_addr_hitvec_hi[i] & buf_byteen[i][j] & ldst_byteen_hi_m[j];
396 :
397 : assign ld_byte_hitvecfn_lo[j][i] = ld_byte_hitvec_lo[j][i] & ~(|(ld_byte_hitvec_lo[j] & buf_age_younger[i])) & ~ld_byte_ibuf_hit_lo[j]; // Kill the byte enable if younger entry exists or byte exists in ibuf
398 : assign ld_byte_hitvecfn_hi[j][i] = ld_byte_hitvec_hi[j][i] & ~(|(ld_byte_hitvec_hi[j] & buf_age_younger[i])) & ~ld_byte_ibuf_hit_hi[j]; // Kill the byte enable if younger entry exists or byte exists in ibuf
399 : end
400 : end
401 :
402 : // Hit in the ibuf
403 : assign ld_addr_ibuf_hit_lo = (lsu_addr_m[31:2] == ibuf_addr[31:2]) & ibuf_write & ibuf_valid & lsu_busreq_m;
404 : assign ld_addr_ibuf_hit_hi = (end_addr_m[31:2] == ibuf_addr[31:2]) & ibuf_write & ibuf_valid & lsu_busreq_m;
405 :
406 : for (genvar i=0; i<4; i++) begin
407 : assign ld_byte_ibuf_hit_lo[i] = ld_addr_ibuf_hit_lo & ibuf_byteen[i] & ldst_byteen_lo_m[i];
408 : assign ld_byte_ibuf_hit_hi[i] = ld_addr_ibuf_hit_hi & ibuf_byteen[i] & ldst_byteen_hi_m[i];
409 : end
410 :
411 298 : always_comb begin
412 298 : ld_fwddata_buf_lo[31:0] = {{8{ld_byte_ibuf_hit_lo[3]}},{8{ld_byte_ibuf_hit_lo[2]}},{8{ld_byte_ibuf_hit_lo[1]}},{8{ld_byte_ibuf_hit_lo[0]}}} & ibuf_data[31:0];
413 298 : ld_fwddata_buf_hi[31:0] = {{8{ld_byte_ibuf_hit_hi[3]}},{8{ld_byte_ibuf_hit_hi[2]}},{8{ld_byte_ibuf_hit_hi[1]}},{8{ld_byte_ibuf_hit_hi[0]}}} & ibuf_data[31:0];
414 1192 : for (int i=0; i<DEPTH; i++) begin
415 1192 : ld_fwddata_buf_lo[7:0] |= {8{ld_byte_hitvecfn_lo[0][i]}} & buf_data[i][7:0];
416 1192 : ld_fwddata_buf_lo[15:8] |= {8{ld_byte_hitvecfn_lo[1][i]}} & buf_data[i][15:8];
417 1192 : ld_fwddata_buf_lo[23:16] |= {8{ld_byte_hitvecfn_lo[2][i]}} & buf_data[i][23:16];
418 1192 : ld_fwddata_buf_lo[31:24] |= {8{ld_byte_hitvecfn_lo[3][i]}} & buf_data[i][31:24];
419 :
420 1192 : ld_fwddata_buf_hi[7:0] |= {8{ld_byte_hitvecfn_hi[0][i]}} & buf_data[i][7:0];
421 1192 : ld_fwddata_buf_hi[15:8] |= {8{ld_byte_hitvecfn_hi[1][i]}} & buf_data[i][15:8];
422 1192 : ld_fwddata_buf_hi[23:16] |= {8{ld_byte_hitvecfn_hi[2][i]}} & buf_data[i][23:16];
423 1192 : ld_fwddata_buf_hi[31:24] |= {8{ld_byte_hitvecfn_hi[3][i]}} & buf_data[i][31:24];
424 : end
425 : end
426 :
427 : //------------------------------------------------------------------------------
428 : // Load forwarding logic end
429 : //------------------------------------------------------------------------------
430 :
431 : assign bus_coalescing_disable = dec_tlu_wb_coalescing_disable | pt.BUILD_AHB_LITE;
432 :
433 : // Get the hi/lo byte enable
434 : assign ldst_byteen_r[3:0] = ({4{lsu_pkt_r.by}} & 4'b0001) |
435 : ({4{lsu_pkt_r.half}} & 4'b0011) |
436 : ({4{lsu_pkt_r.word}} & 4'b1111);
437 :
438 : assign {ldst_byteen_hi_r[3:0], ldst_byteen_lo_r[3:0]} = {4'b0,ldst_byteen_r[3:0]} << lsu_addr_r[1:0];
439 : assign {store_data_hi_r[31:0], store_data_lo_r[31:0]} = {32'b0,store_data_r[31:0]} << 8*lsu_addr_r[1:0];
440 : assign ldst_samedw_r = (lsu_addr_r[3] == end_addr_r[3]);
441 : assign is_aligned_r = (lsu_pkt_r.word & (lsu_addr_r[1:0] == 2'b0)) |
442 : (lsu_pkt_r.half & (lsu_addr_r[0] == 1'b0)) |
443 : lsu_pkt_r.by;
444 :
445 : //------------------------------------------------------------------------------
446 : // Input buffer logic starts here
447 : //------------------------------------------------------------------------------
448 :
449 : assign ibuf_byp = lsu_busreq_r & (lsu_pkt_r.load | no_word_merge_r) & ~ibuf_valid;
450 : assign ibuf_wr_en = lsu_busreq_r & lsu_commit_r & ~ibuf_byp;
451 : assign ibuf_rst = (ibuf_drain_vld & ~ibuf_wr_en) | dec_tlu_force_halt;
452 : assign ibuf_force_drain = lsu_busreq_m & ~lsu_busreq_r & ibuf_valid & (lsu_pkt_m.load | (ibuf_addr[31:2] != lsu_addr_m[31:2])); // Move the ibuf to buf if there is a non-colaescable ld/st in m but nothing in r
453 : assign ibuf_drain_vld = ibuf_valid & (((ibuf_wr_en | (ibuf_timer == TIMER_MAX)) & ~(ibuf_merge_en & ibuf_merge_in)) | ibuf_byp | ibuf_force_drain | ibuf_sideeffect | ~ibuf_write | bus_coalescing_disable);
454 : assign ibuf_tag_in[DEPTH_LOG2-1:0] = (ibuf_merge_en & ibuf_merge_in) ? ibuf_tag[DEPTH_LOG2-1:0] : (ldst_dual_r ? WrPtr1_r : WrPtr0_r);
455 : assign ibuf_dualtag_in[DEPTH_LOG2-1:0] = WrPtr0_r;
456 : assign ibuf_sz_in[1:0] = {lsu_pkt_r.word, lsu_pkt_r.half};
457 : assign ibuf_addr_in[31:0] = ldst_dual_r ? end_addr_r[31:0] : lsu_addr_r[31:0];
458 : assign ibuf_byteen_in[3:0] = (ibuf_merge_en & ibuf_merge_in) ? (ibuf_byteen[3:0] | ldst_byteen_lo_r[3:0]) : (ldst_dual_r ? ldst_byteen_hi_r[3:0] : ldst_byteen_lo_r[3:0]);
459 : for (genvar i=0; i<4; i++) begin
460 : assign ibuf_data_in[(8*i)+7:(8*i)] = (ibuf_merge_en & ibuf_merge_in) ? (ldst_byteen_lo_r[i] ? store_data_lo_r[(8*i)+7:(8*i)] : ibuf_data[(8*i)+7:(8*i)]) :
461 : (ldst_dual_r ? store_data_hi_r[(8*i)+7:(8*i)] : store_data_lo_r[(8*i)+7:(8*i)]);
462 : end
463 : assign ibuf_timer_in = ibuf_wr_en ? '0 : (ibuf_timer < TIMER_MAX) ? (ibuf_timer + 1'b1) : ibuf_timer;
464 :
465 :
466 : assign ibuf_merge_en = lsu_busreq_r & lsu_commit_r & lsu_pkt_r.store & ibuf_valid & ibuf_write & (lsu_addr_r[31:2] == ibuf_addr[31:2]) & ~is_sideeffects_r & ~bus_coalescing_disable;
467 : assign ibuf_merge_in = ~ldst_dual_r; // If it's a unaligned store, merge needs to happen on the way out of ibuf
468 :
469 : // ibuf signals going to bus buffer after merging
470 : for (genvar i=0; i<4; i++) begin
471 : assign ibuf_byteen_out[i] = (ibuf_merge_en & ~ibuf_merge_in) ? (ibuf_byteen[i] | ldst_byteen_lo_r[i]) : ibuf_byteen[i];
472 : assign ibuf_data_out[(8*i)+7:(8*i)] = (ibuf_merge_en & ~ibuf_merge_in) ? (ldst_byteen_lo_r[i] ? store_data_lo_r[(8*i)+7:(8*i)] : ibuf_data[(8*i)+7:(8*i)]) :
473 : ibuf_data[(8*i)+7:(8*i)];
474 : end
475 :
476 : rvdffsc #(.WIDTH(1)) ibuf_valid_ff (.din(1'b1), .dout(ibuf_valid), .en(ibuf_wr_en), .clear(ibuf_rst), .clk(lsu_free_c2_clk), .*);
477 : rvdffs #(.WIDTH(DEPTH_LOG2)) ibuf_tagff (.din(ibuf_tag_in), .dout(ibuf_tag), .en(ibuf_wr_en), .clk(lsu_bus_ibuf_c1_clk), .*);
478 : rvdffs #(.WIDTH(DEPTH_LOG2)) ibuf_dualtagff (.din(ibuf_dualtag_in), .dout(ibuf_dualtag), .en(ibuf_wr_en), .clk(lsu_bus_ibuf_c1_clk), .*);
479 : rvdffs #(.WIDTH(1)) ibuf_dualff (.din(ldst_dual_r), .dout(ibuf_dual), .en(ibuf_wr_en), .clk(lsu_bus_ibuf_c1_clk), .*);
480 : rvdffs #(.WIDTH(1)) ibuf_samedwff (.din(ldst_samedw_r), .dout(ibuf_samedw), .en(ibuf_wr_en), .clk(lsu_bus_ibuf_c1_clk), .*);
481 : rvdffs #(.WIDTH(1)) ibuf_nomergeff (.din(no_dword_merge_r), .dout(ibuf_nomerge), .en(ibuf_wr_en), .clk(lsu_bus_ibuf_c1_clk), .*);
482 : rvdffs #(.WIDTH(1)) ibuf_sideeffectff (.din(is_sideeffects_r), .dout(ibuf_sideeffect), .en(ibuf_wr_en), .clk(lsu_bus_ibuf_c1_clk), .*);
483 : rvdffs #(.WIDTH(1)) ibuf_unsignff (.din(lsu_pkt_r.unsign), .dout(ibuf_unsign), .en(ibuf_wr_en), .clk(lsu_bus_ibuf_c1_clk), .*);
484 : rvdffs #(.WIDTH(1)) ibuf_writeff (.din(lsu_pkt_r.store), .dout(ibuf_write), .en(ibuf_wr_en), .clk(lsu_bus_ibuf_c1_clk), .*);
485 : rvdffs #(.WIDTH(2)) ibuf_szff (.din(ibuf_sz_in[1:0]), .dout(ibuf_sz), .en(ibuf_wr_en), .clk(lsu_bus_ibuf_c1_clk), .*);
486 : rvdffe #(.WIDTH(32)) ibuf_addrff (.din(ibuf_addr_in[31:0]), .dout(ibuf_addr), .en(ibuf_wr_en), .*);
487 : rvdffs #(.WIDTH(4)) ibuf_byteenff (.din(ibuf_byteen_in[3:0]), .dout(ibuf_byteen), .en(ibuf_wr_en), .clk(lsu_bus_ibuf_c1_clk), .*);
488 : rvdffe #(.WIDTH(32)) ibuf_dataff (.din(ibuf_data_in[31:0]), .dout(ibuf_data), .en(ibuf_wr_en), .*);
489 : rvdff #(.WIDTH(TIMER_LOG2)) ibuf_timerff (.din(ibuf_timer_in), .dout(ibuf_timer), .clk(lsu_free_c2_clk), .*);
490 :
491 :
492 : //------------------------------------------------------------------------------
493 : // Input buffer logic ends here
494 : //------------------------------------------------------------------------------
495 :
496 :
497 : //------------------------------------------------------------------------------
498 : // Output buffer logic starts here
499 : //------------------------------------------------------------------------------
500 :
501 : assign obuf_wr_wait = (buf_numvld_wrcmd_any[3:0] == 4'b1) & (buf_numvld_cmd_any[3:0] == 4'b1) & (obuf_wr_timer != TIMER_MAX) &
502 : ~bus_coalescing_disable & ~buf_nomerge[CmdPtr0] & ~buf_sideeffect[CmdPtr0] & ~obuf_force_wr_en;
503 : assign obuf_wr_timer_in = obuf_wr_en ? 3'b0: (((buf_numvld_cmd_any > 4'b0) & (obuf_wr_timer < TIMER_MAX)) ? (obuf_wr_timer + 1'b1) : obuf_wr_timer);
504 : assign obuf_force_wr_en = lsu_busreq_m & ~lsu_busreq_r & ~ibuf_valid & (buf_numvld_cmd_any[3:0] == 4'b1) & (lsu_addr_m[31:2] != buf_addr[CmdPtr0][31:2]); // Entry in m can't merge with entry going to obuf and there is no entry in between
505 : assign ibuf_buf_byp = ibuf_byp & (buf_numvld_pend_any[3:0] == 4'b0) & (~lsu_pkt_r.store | no_dword_merge_r);
506 :
507 : assign obuf_wr_en = ((ibuf_buf_byp & lsu_commit_r & ~(is_sideeffects_r & bus_sideeffect_pend)) |
508 : ((buf_state[CmdPtr0] == CMD) & found_cmdptr0 & ~buf_cmd_state_bus_en[CmdPtr0] & ~(buf_sideeffect[CmdPtr0] & bus_sideeffect_pend) &
509 : (~(buf_dual[CmdPtr0] & buf_samedw[CmdPtr0] & ~buf_write[CmdPtr0]) | found_cmdptr1 | buf_nomerge[CmdPtr0] | obuf_force_wr_en))) &
510 : (bus_cmd_ready | ~obuf_valid | obuf_nosend) & ~obuf_wr_wait & ~bus_addr_match_pending & lsu_bus_clk_en;
511 :
512 : assign obuf_rst = ((bus_cmd_sent | (obuf_valid & obuf_nosend)) & ~obuf_wr_en & lsu_bus_clk_en) | dec_tlu_force_halt;
513 :
514 : assign obuf_write_in = ibuf_buf_byp ? lsu_pkt_r.store : buf_write[CmdPtr0];
515 : assign obuf_sideeffect_in = ibuf_buf_byp ? is_sideeffects_r : buf_sideeffect[CmdPtr0];
516 : assign obuf_addr_in[31:0] = ibuf_buf_byp ? lsu_addr_r[31:0] : buf_addr[CmdPtr0];
517 : assign obuf_sz_in[1:0] = ibuf_buf_byp ? {lsu_pkt_r.word, lsu_pkt_r.half} : buf_sz[CmdPtr0];
518 : assign obuf_merge_in = obuf_merge_en;
519 : assign obuf_tag0_in[pt.LSU_BUS_TAG-1:0] = ibuf_buf_byp ? (pt.LSU_BUS_TAG)'(WrPtr0_r) : (pt.LSU_BUS_TAG)'(CmdPtr0);
520 : assign obuf_tag1_in[pt.LSU_BUS_TAG-1:0] = ibuf_buf_byp ? (pt.LSU_BUS_TAG)'(WrPtr1_r) : (pt.LSU_BUS_TAG)'(CmdPtr1);
521 :
522 : assign obuf_cmd_done_in = ~(obuf_wr_en | obuf_rst) & (obuf_cmd_done | bus_wcmd_sent);
523 : assign obuf_data_done_in = ~(obuf_wr_en | obuf_rst) & (obuf_data_done | bus_wdata_sent);
524 :
525 : assign obuf_aligned_in = ibuf_buf_byp ? is_aligned_r : ((obuf_sz_in[1:0] == 2'b0) |
526 : (obuf_sz_in[0] & ~obuf_addr_in[0]) |
527 : (obuf_sz_in[1] & ~(|obuf_addr_in[1:0])));
528 :
529 : assign obuf_rdrsp_pend_in = ((~(obuf_wr_en & ~obuf_nosend_in) & obuf_rdrsp_pend & ~(bus_rsp_read & (bus_rsp_read_tag == obuf_rdrsp_tag))) | (bus_cmd_sent & ~obuf_write)) & ~dec_tlu_force_halt;
530 : assign obuf_rdrsp_pend_en = lsu_bus_clk_en | dec_tlu_force_halt;
531 : assign obuf_rdrsp_tag_in[pt.LSU_BUS_TAG-1:0] = (bus_cmd_sent & ~obuf_write) ? obuf_tag0[pt.LSU_BUS_TAG-1:0] : obuf_rdrsp_tag[pt.LSU_BUS_TAG-1:0];
532 : // No ld to ld fwd for aligned
533 : assign obuf_nosend_in = (obuf_addr_in[31:3] == obuf_addr[31:3]) & obuf_aligned_in & ~obuf_sideeffect & ~obuf_write & ~obuf_write_in & ~dec_tlu_external_ldfwd_disable &
534 : ((obuf_valid & ~obuf_nosend) | (obuf_rdrsp_pend & ~(bus_rsp_read & (bus_rsp_read_tag == obuf_rdrsp_tag))));
535 :
536 : assign obuf_byteen0_in[7:0] = ibuf_buf_byp ? (lsu_addr_r[2] ? {ldst_byteen_lo_r[3:0],4'b0} : {4'b0,ldst_byteen_lo_r[3:0]}) :
537 : (buf_addr[CmdPtr0][2] ? {buf_byteen[CmdPtr0],4'b0} : {4'b0,buf_byteen[CmdPtr0]});
538 : assign obuf_byteen1_in[7:0] = ibuf_buf_byp ? (end_addr_r[2] ? {ldst_byteen_hi_r[3:0],4'b0} : {4'b0,ldst_byteen_hi_r[3:0]}) :
539 : (buf_addr[CmdPtr1][2] ? {buf_byteen[CmdPtr1],4'b0} : {4'b0,buf_byteen[CmdPtr1]});
540 : assign obuf_data0_in[63:0] = ibuf_buf_byp ? (lsu_addr_r[2] ? {store_data_lo_r[31:0],32'b0} : {32'b0,store_data_lo_r[31:0]}) :
541 : (buf_addr[CmdPtr0][2] ? {buf_data[CmdPtr0],32'b0} : {32'b0,buf_data[CmdPtr0]});
542 : assign obuf_data1_in[63:0] = ibuf_buf_byp ? (end_addr_r[2] ? {store_data_hi_r[31:0],32'b0} :{32'b0,store_data_hi_r[31:0]}) :
543 : (buf_addr[CmdPtr1][2] ? {buf_data[CmdPtr1],32'b0} : {32'b0,buf_data[CmdPtr1]});
544 :
545 : for (genvar i=0 ;i<8; i++) begin
546 : assign obuf_byteen_in[i] = obuf_byteen0_in[i] | (obuf_merge_en & obuf_byteen1_in[i]);
547 : assign obuf_data_in[(8*i)+7:(8*i)] = (obuf_merge_en & obuf_byteen1_in[i]) ? obuf_data1_in[(8*i)+7:(8*i)] : obuf_data0_in[(8*i)+7:(8*i)];
548 : end
549 :
550 : // No store obuf merging for AXI since all stores are sent non-posted. Can't track the second id right now
551 : assign obuf_merge_en = ((CmdPtr0 != CmdPtr1) & found_cmdptr0 & found_cmdptr1 & (buf_state[CmdPtr0] == CMD) & (buf_state[CmdPtr1] == CMD) &
552 : ~buf_cmd_state_bus_en[CmdPtr0] & ~buf_sideeffect[CmdPtr0] &
553 : (~buf_write[CmdPtr0] & buf_dual[CmdPtr0] & ~buf_dualhi[CmdPtr0] & buf_samedw[CmdPtr0])) | // CmdPtr0/CmdPtr1 are for same load which is within a DW
554 : (ibuf_buf_byp & ldst_samedw_r & ldst_dual_r);
555 :
556 :
557 : rvdff_fpga #(.WIDTH(1)) obuf_wren_ff (.din(obuf_wr_en), .dout(obuf_wr_enQ), .clk(lsu_busm_clk), .clken(lsu_busm_clken), .rawclk(clk), .*);
558 : rvdffsc #(.WIDTH(1)) obuf_valid_ff (.din(1'b1), .dout(obuf_valid), .en(obuf_wr_en), .clear(obuf_rst), .clk(lsu_free_c2_clk), .*);
559 : rvdffs #(.WIDTH(1)) obuf_nosend_ff (.din(obuf_nosend_in), .dout(obuf_nosend), .en(obuf_wr_en), .clk(lsu_free_c2_clk), .*);
560 : rvdffs #(.WIDTH(1)) obuf_rdrsp_pend_ff(.din(obuf_rdrsp_pend_in), .dout(obuf_rdrsp_pend), .en(obuf_rdrsp_pend_en), .clk(lsu_free_c2_clk), .*);
561 : rvdff_fpga #(.WIDTH(1)) obuf_cmd_done_ff (.din(obuf_cmd_done_in), .dout(obuf_cmd_done), .clk(lsu_busm_clk), .clken(lsu_busm_clken), .rawclk(clk), .*);
562 : rvdff_fpga #(.WIDTH(1)) obuf_data_done_ff (.din(obuf_data_done_in), .dout(obuf_data_done), .clk(lsu_busm_clk), .clken(lsu_busm_clken), .rawclk(clk), .*);
563 : rvdff_fpga #(.WIDTH(pt.LSU_BUS_TAG)) obuf_rdrsp_tagff (.din(obuf_rdrsp_tag_in), .dout(obuf_rdrsp_tag), .clk(lsu_busm_clk), .clken(lsu_busm_clken), .rawclk(clk), .*);
564 : rvdffs_fpga #(.WIDTH(pt.LSU_BUS_TAG)) obuf_tag0ff (.din(obuf_tag0_in), .dout(obuf_tag0), .en(obuf_wr_en), .clk(lsu_bus_obuf_c1_clk), .clken(lsu_bus_obuf_c1_clken), .rawclk(clk), .*);
565 : rvdffs_fpga #(.WIDTH(pt.LSU_BUS_TAG)) obuf_tag1ff (.din(obuf_tag1_in), .dout(obuf_tag1), .en(obuf_wr_en), .clk(lsu_bus_obuf_c1_clk), .clken(lsu_bus_obuf_c1_clken), .rawclk(clk), .*);
566 : rvdffs_fpga #(.WIDTH(1)) obuf_mergeff (.din(obuf_merge_in), .dout(obuf_merge), .en(obuf_wr_en), .clk(lsu_bus_obuf_c1_clk), .clken(lsu_bus_obuf_c1_clken), .rawclk(clk), .*);
567 : rvdffs_fpga #(.WIDTH(1)) obuf_writeff (.din(obuf_write_in), .dout(obuf_write), .en(obuf_wr_en), .clk(lsu_bus_obuf_c1_clk), .clken(lsu_bus_obuf_c1_clken), .rawclk(clk), .*);
568 : rvdffs_fpga #(.WIDTH(1)) obuf_sideeffectff (.din(obuf_sideeffect_in), .dout(obuf_sideeffect), .en(obuf_wr_en), .clk(lsu_bus_obuf_c1_clk), .clken(lsu_bus_obuf_c1_clken), .rawclk(clk), .*);
569 : rvdffs_fpga #(.WIDTH(2)) obuf_szff (.din(obuf_sz_in[1:0]), .dout(obuf_sz), .en(obuf_wr_en), .clk(lsu_bus_obuf_c1_clk), .clken(lsu_bus_obuf_c1_clken), .rawclk(clk), .*);
570 : rvdffs_fpga #(.WIDTH(8)) obuf_byteenff (.din(obuf_byteen_in[7:0]), .dout(obuf_byteen), .en(obuf_wr_en), .clk(lsu_bus_obuf_c1_clk), .clken(lsu_bus_obuf_c1_clken), .rawclk(clk), .*);
571 : rvdffe #(.WIDTH(32)) obuf_addrff (.din(obuf_addr_in[31:0]), .dout(obuf_addr), .en(obuf_wr_en), .*);
572 : rvdffe #(.WIDTH(64)) obuf_dataff (.din(obuf_data_in[63:0]), .dout(obuf_data), .en(obuf_wr_en), .*);
573 : rvdff_fpga #(.WIDTH(TIMER_LOG2)) obuf_timerff (.din(obuf_wr_timer_in), .dout(obuf_wr_timer), .clk(lsu_busm_clk), .clken(lsu_busm_clken), .rawclk(clk), .*);
574 :
575 :
576 : //------------------------------------------------------------------------------
577 : // Output buffer logic ends here
578 : //------------------------------------------------------------------------------
579 :
580 : // Find the entry to allocate and entry to send
581 42436767 : always_comb begin
582 42436767 : WrPtr0_m[DEPTH_LOG2-1:0] = '0;
583 42436767 : WrPtr1_m[DEPTH_LOG2-1:0] = '0;
584 42436767 : found_wrptr0 = '0;
585 42436767 : found_wrptr1 = '0;
586 :
587 : // Find first write pointer
588 169747068 : for (int i=0; i<DEPTH; i++) begin
589 119478368 : if (~found_wrptr0) begin
590 50268700 : WrPtr0_m[DEPTH_LOG2-1:0] = DEPTH_LOG2'(i);
591 50268700 : found_wrptr0 = (buf_state[i] == IDLE) & ~((ibuf_valid & (ibuf_tag == i)) |
592 50268700 : (lsu_busreq_r & ((WrPtr0_r == i) | (ldst_dual_r & (WrPtr1_r == i)))));
593 : end
594 : end
595 :
596 : // Find second write pointer
597 169747068 : for (int i=0; i<DEPTH; i++) begin
598 118277131 : if (~found_wrptr1) begin
599 51469937 : WrPtr1_m[DEPTH_LOG2-1:0] = DEPTH_LOG2'(i);
600 51469937 : found_wrptr1 = (buf_state[i] == IDLE) & ~((ibuf_valid & (ibuf_tag == i)) |
601 51469937 : (lsu_busreq_m & (WrPtr0_m == i)) |
602 51469937 : (lsu_busreq_r & ((WrPtr0_r == i) | (ldst_dual_r & (WrPtr1_r == i)))));
603 : end
604 : end
605 : end
606 :
607 : // Get the command ptr
608 : for (genvar i=0; i<DEPTH; i++) begin
609 : // These should be one-hot
610 : assign CmdPtr0Dec[i] = ~(|buf_age[i]) & (buf_state[i] == CMD) & ~buf_cmd_state_bus_en[i];
611 : assign CmdPtr1Dec[i] = ~(|(buf_age[i] & ~CmdPtr0Dec)) & ~CmdPtr0Dec[i] & (buf_state[i] == CMD) & ~buf_cmd_state_bus_en[i];
612 : assign RspPtrDec[i] = ~(|buf_rsp_pickage[i]) & (buf_state[i] == DONE_WAIT);
613 : end
614 :
615 : assign found_cmdptr0 = |CmdPtr0Dec;
616 : assign found_cmdptr1 = |CmdPtr1Dec;
617 : assign CmdPtr0 = f_Enc8to3(8'(CmdPtr0Dec[DEPTH-1:0]));
618 : assign CmdPtr1 = f_Enc8to3(8'(CmdPtr1Dec[DEPTH-1:0]));
619 : assign RspPtr = f_Enc8to3(8'(RspPtrDec[DEPTH-1:0]));
620 :
621 : // Age vector
622 : for (genvar i=0; i<DEPTH; i++) begin: GenAgeVec
623 : for (genvar j=0; j<DEPTH; j++) begin
624 : assign buf_age_in[i][j] = (((buf_state[i] == IDLE) & buf_state_en[i]) &
625 : (((buf_state[j] == START_WAIT) | ((buf_state[j] == CMD) & ~buf_cmd_state_bus_en[j])) | // Set age bit for older entries
626 : (ibuf_drain_vld & lsu_busreq_r & (ibuf_byp | ldst_dual_r) & (i == WrPtr0_r) & (j == ibuf_tag)) | // Set case for dual lo
627 : (ibuf_byp & lsu_busreq_r & ldst_dual_r & (i == WrPtr1_r) & (j == WrPtr0_r)))) | // ibuf bypass case
628 : buf_age[i][j];
629 :
630 :
631 : assign buf_age[i][j] = buf_ageQ[i][j] & ~((buf_state[j] == CMD) & buf_cmd_state_bus_en[j]) & ~dec_tlu_force_halt; // Reset case
632 :
633 : assign buf_age_younger[i][j] = (i == j) ? 1'b0: (~buf_age[i][j] & (buf_state[j] != IDLE)); // Younger entries
634 : end
635 : end
636 :
637 : // Age vector for responses
638 : for (genvar i=0; i<DEPTH; i++) begin: GenRspAgeVec
639 : for (genvar j=0; j<DEPTH; j++) begin
640 : assign buf_rspage_set[i][j] = ((buf_state[i] == IDLE) & buf_state_en[i]) &
641 : (~((buf_state[j] == IDLE) | (buf_state[j] == DONE)) | // Set age bit for older entries
642 : (ibuf_drain_vld & lsu_busreq_r & (ibuf_byp | ldst_dual_r) & (DEPTH_LOG2'(i) == WrPtr0_r) & (DEPTH_LOG2'(j) == ibuf_tag)) | // Set case for dual lo
643 : (ibuf_byp & lsu_busreq_r & ldst_dual_r & (DEPTH_LOG2'(i) == WrPtr1_r) & (DEPTH_LOG2'(j) == WrPtr0_r)));
644 : assign buf_rspage_in[i][j] = buf_rspage_set[i][j] | buf_rspage[i][j];
645 : assign buf_rspage[i][j] = buf_rspageQ[i][j] & ~((buf_state[j] == DONE) | (buf_state[j] == IDLE)) & ~dec_tlu_force_halt; // Reset case
646 : assign buf_rsp_pickage[i][j] = buf_rspageQ[i][j] & (buf_state[j] == DONE_WAIT);
647 : end
648 : end
649 :
650 : //------------------------------------------------------------------------------
651 : // Buffer logic
652 : //------------------------------------------------------------------------------
653 640823124 : for (genvar i=0; i<DEPTH; i++) begin : genblock
654 :
655 : assign ibuf_drainvec_vld[i] = (ibuf_drain_vld & (i == ibuf_tag));
656 : assign buf_byteen_in[i] = ibuf_drainvec_vld[i] ? ibuf_byteen_out[3:0] : ((ibuf_byp & ldst_dual_r & (i == WrPtr1_r)) ? ldst_byteen_hi_r[3:0] : ldst_byteen_lo_r[3:0]);
657 : assign buf_addr_in[i] = ibuf_drainvec_vld[i] ? ibuf_addr[31:0] : ((ibuf_byp & ldst_dual_r & (i == WrPtr1_r)) ? end_addr_r[31:0] : lsu_addr_r[31:0]);
658 : assign buf_dual_in[i] = ibuf_drainvec_vld[i] ? ibuf_dual : ldst_dual_r;
659 : assign buf_samedw_in[i] = ibuf_drainvec_vld[i] ? ibuf_samedw : ldst_samedw_r;
660 : assign buf_nomerge_in[i] = ibuf_drainvec_vld[i] ? (ibuf_nomerge | ibuf_force_drain) : no_dword_merge_r;
661 : assign buf_dualhi_in[i] = ibuf_drainvec_vld[i] ? ibuf_dual : (ibuf_byp & ldst_dual_r & (i == WrPtr1_r)); // If it's dual, ibuf will always have the high
662 : assign buf_dualtag_in[i] = ibuf_drainvec_vld[i] ? ibuf_dualtag : ((ibuf_byp & ldst_dual_r & (i == WrPtr1_r)) ? WrPtr0_r : WrPtr1_r);
663 : assign buf_sideeffect_in[i] = ibuf_drainvec_vld[i] ? ibuf_sideeffect : is_sideeffects_r;
664 : assign buf_unsign_in[i] = ibuf_drainvec_vld[i] ? ibuf_unsign : lsu_pkt_r.unsign;
665 : assign buf_sz_in[i] = ibuf_drainvec_vld[i] ? ibuf_sz : {lsu_pkt_r.word, lsu_pkt_r.half};
666 : assign buf_write_in[i] = ibuf_drainvec_vld[i] ? ibuf_write : lsu_pkt_r.store;
667 :
668 : // Buffer entry state machine
669 640823124 : always_comb begin
670 640823124 : buf_nxtstate[i] = IDLE;
671 640823124 : buf_state_en[i] = '0;
672 640823124 : buf_resp_state_bus_en[i] = '0;
673 640823124 : buf_state_bus_en[i] = '0;
674 640823124 : buf_wr_en[i] = '0;
675 640823124 : buf_data_in[i] = '0;
676 640823124 : buf_data_en[i] = '0;
677 640823124 : buf_error_en[i] = '0;
678 640823124 : buf_rst[i] = dec_tlu_force_halt;
679 640823124 : buf_ldfwd_en[i] = dec_tlu_force_halt;
680 640823124 : buf_ldfwd_in[i] = '0;
681 640823124 : buf_ldfwdtag_in[i] = '0;
682 :
683 640823124 : case (buf_state[i])
684 612645415 : IDLE: begin
685 612645415 : buf_nxtstate[i] = lsu_bus_clk_en ? CMD : START_WAIT;
686 612645415 : buf_state_en[i] = (lsu_busreq_r & lsu_commit_r & (((ibuf_byp | ldst_dual_r) & ~ibuf_merge_en & (i == WrPtr0_r)) | (ibuf_byp & ldst_dual_r & (i == WrPtr1_r)))) |
687 612645415 : (ibuf_drain_vld & (i == ibuf_tag));
688 612645415 : buf_wr_en[i] = buf_state_en[i];
689 612645415 : buf_data_en[i] = buf_state_en[i];
690 612645415 : buf_data_in[i] = (ibuf_drain_vld & (i == ibuf_tag)) ? ibuf_data_out[31:0] : store_data_lo_r[31:0];
691 612645415 : buf_cmd_state_bus_en[i] = '0;
692 : end
693 58 : START_WAIT: begin
694 58 : buf_nxtstate[i] = dec_tlu_force_halt ? IDLE : CMD;
695 58 : buf_state_en[i] = lsu_bus_clk_en | dec_tlu_force_halt;
696 58 : buf_cmd_state_bus_en[i] = '0;
697 : end
698 11193906 : CMD: begin
699 11193906 : buf_nxtstate[i] = dec_tlu_force_halt ? IDLE : (obuf_nosend & bus_rsp_read & (bus_rsp_read_tag == obuf_rdrsp_tag)) ? DONE_WAIT : RESP;
700 11193906 : buf_cmd_state_bus_en[i] = ((obuf_tag0 == i) | (obuf_merge & (obuf_tag1 == i))) & obuf_valid & obuf_wr_enQ; // Just use the recently written obuf_valid
701 11193906 : buf_state_bus_en[i] = buf_cmd_state_bus_en[i];
702 11193906 : buf_state_en[i] = (buf_state_bus_en[i] & lsu_bus_clk_en) | dec_tlu_force_halt;
703 11193906 : buf_ldfwd_in[i] = 1'b1;
704 11193906 : buf_ldfwd_en[i] = buf_state_en[i] & ~buf_write[i] & obuf_nosend & ~dec_tlu_force_halt;
705 11193906 : buf_ldfwdtag_in[i] = DEPTH_LOG2'(obuf_rdrsp_tag[pt.LSU_BUS_TAG-2:0]);
706 11193906 : buf_data_en[i] = buf_state_bus_en[i] & lsu_bus_clk_en & obuf_nosend & bus_rsp_read;
707 11193906 : buf_error_en[i] = buf_state_bus_en[i] & lsu_bus_clk_en & obuf_nosend & bus_rsp_read_error;
708 11193906 : buf_data_in[i] = buf_error_en[i] ? bus_rsp_rdata[31:0] : (buf_addr[i][2] ? bus_rsp_rdata[63:32] : bus_rsp_rdata[31:0]);
709 : end
710 12717711 : RESP: begin
711 12717711 : buf_nxtstate[i] = (dec_tlu_force_halt | (buf_write[i] & ~bus_rsp_write_error)) ? IDLE : // Side-effect writes will be non-posted
712 12717711 : (buf_dual[i] & ~buf_samedw[i] & ~buf_write[i] & (buf_state[buf_dualtag[i]] != DONE_PARTIAL)) ? DONE_PARTIAL : // Goto DONE_PARTIAL if this is the first return of dual
713 12717711 : (buf_ldfwd[i] | any_done_wait_state |
714 12717711 : (buf_dual[i] & ~buf_samedw[i] & ~buf_write[i] & buf_ldfwd[buf_dualtag[i]] &
715 12717711 : (buf_state[buf_dualtag[i]] == DONE_PARTIAL) & any_done_wait_state)) ? DONE_WAIT : DONE;
716 12717711 : buf_resp_state_bus_en[i] = (bus_rsp_write & (bus_rsp_write_tag == (pt.LSU_BUS_TAG)'(i))) |
717 12717711 : (bus_rsp_read & ((bus_rsp_read_tag == (pt.LSU_BUS_TAG)'(i)) |
718 12717711 : (buf_ldfwd[i] & (bus_rsp_read_tag == (pt.LSU_BUS_TAG)'(buf_ldfwdtag[i]))) |
719 12717711 : (buf_dual[i] & buf_dualhi[i] & ~buf_write[i] & buf_samedw[i] & (bus_rsp_read_tag == (pt.LSU_BUS_TAG)'(buf_dualtag[i])))));
720 12717711 : buf_state_bus_en[i] = buf_resp_state_bus_en[i];
721 12717711 : buf_state_en[i] = (buf_state_bus_en[i] & lsu_bus_clk_en) | dec_tlu_force_halt;
722 12717711 : buf_data_en[i] = buf_state_bus_en[i] & bus_rsp_read & lsu_bus_clk_en;
723 : // Need to capture the error for stores as well for AXI
724 12717711 : buf_error_en[i] = buf_state_bus_en[i] & lsu_bus_clk_en & ((bus_rsp_read_error & (bus_rsp_read_tag == (pt.LSU_BUS_TAG)'(i))) |
725 12717711 : (bus_rsp_read_error & buf_ldfwd[i] & (bus_rsp_read_tag == (pt.LSU_BUS_TAG)'(buf_ldfwdtag[i]))) |
726 12717711 : (bus_rsp_write_error & (bus_rsp_write_tag == (pt.LSU_BUS_TAG)'(i))));
727 12717711 : buf_data_in[i][31:0] = (buf_state_en[i] & ~buf_error_en[i]) ? (buf_addr[i][2] ? bus_rsp_rdata[63:32] : bus_rsp_rdata[31:0]) : bus_rsp_rdata[31:0];
728 12717711 : buf_cmd_state_bus_en[i] = '0;
729 : end
730 33264 : DONE_PARTIAL: begin // Other part of dual load hasn't returned
731 33264 : buf_nxtstate[i] = dec_tlu_force_halt ? IDLE : (buf_ldfwd[i] | buf_ldfwd[buf_dualtag[i]] | any_done_wait_state) ? DONE_WAIT : DONE;
732 33264 : buf_state_bus_en[i] = bus_rsp_read & ((bus_rsp_read_tag == (pt.LSU_BUS_TAG)'(buf_dualtag[i])) |
733 33264 : (buf_ldfwd[buf_dualtag[i]] & (bus_rsp_read_tag == (pt.LSU_BUS_TAG)'(buf_ldfwdtag[buf_dualtag[i]]))));
734 33264 : buf_state_en[i] = (buf_state_bus_en[i] & lsu_bus_clk_en) | dec_tlu_force_halt;
735 33264 : buf_cmd_state_bus_en[i] = '0;
736 : end
737 849310 : DONE_WAIT: begin // START_WAIT state if there are multiple outstanding nb returns
738 849310 : buf_nxtstate[i] = dec_tlu_force_halt ? IDLE : DONE;
739 849310 : buf_state_en[i] = ((RspPtr == DEPTH_LOG2'(i)) | (buf_dual[i] & (buf_dualtag[i] == RspPtr))) | dec_tlu_force_halt;
740 849310 : buf_cmd_state_bus_en[i] = '0;
741 : end
742 3383460 : DONE: begin
743 3383460 : buf_nxtstate[i] = IDLE;
744 3383460 : buf_rst[i] = 1'b1;
745 3383460 : buf_state_en[i] = 1'b1;
746 3383460 : buf_ldfwd_in[i] = 1'b0;
747 3383460 : buf_ldfwd_en[i] = buf_state_en[i];
748 3383460 : buf_cmd_state_bus_en[i] = '0;
749 : end
750 : /* buf_state is an enum and the existing members are handled above */
751 : /*pragma coverage off*/
752 : default : begin
753 : buf_nxtstate[i] = IDLE;
754 : buf_state_en[i] = '0;
755 : buf_resp_state_bus_en[i] = '0;
756 : buf_state_bus_en[i] = '0;
757 : buf_wr_en[i] = '0;
758 : buf_data_in[i] = '0;
759 : buf_data_en[i] = '0;
760 : buf_error_en[i] = '0;
761 : buf_rst[i] = '0;
762 : buf_cmd_state_bus_en[i] = '0;
763 : end
764 : /*pragma coverage on*/
765 : endcase
766 : end
767 :
768 : rvdffs #(.WIDTH($bits(state_t))) buf_state_ff (.din(buf_nxtstate[i]), .dout({buf_state[i]}), .en(buf_state_en[i]), .clk(lsu_bus_buf_c1_clk), .*);
769 : rvdff #(.WIDTH(DEPTH)) buf_ageff (.din(buf_age_in[i]), .dout(buf_ageQ[i]), .clk(lsu_bus_buf_c1_clk), .*);
770 : rvdff #(.WIDTH(DEPTH)) buf_rspageff (.din(buf_rspage_in[i]), .dout(buf_rspageQ[i]), .clk(lsu_bus_buf_c1_clk), .*);
771 : rvdffs #(.WIDTH(DEPTH_LOG2)) buf_dualtagff (.din(buf_dualtag_in[i]), .dout(buf_dualtag[i]), .en(buf_wr_en[i]), .clk(lsu_bus_buf_c1_clk), .*);
772 : rvdffs #(.WIDTH(1)) buf_dualff (.din(buf_dual_in[i]), .dout(buf_dual[i]), .en(buf_wr_en[i]), .clk(lsu_bus_buf_c1_clk), .*);
773 : rvdffs #(.WIDTH(1)) buf_samedwff (.din(buf_samedw_in[i]), .dout(buf_samedw[i]), .en(buf_wr_en[i]), .clk(lsu_bus_buf_c1_clk), .*);
774 : rvdffs #(.WIDTH(1)) buf_nomergeff (.din(buf_nomerge_in[i]), .dout(buf_nomerge[i]), .en(buf_wr_en[i]), .clk(lsu_bus_buf_c1_clk), .*);
775 : rvdffs #(.WIDTH(1)) buf_dualhiff (.din(buf_dualhi_in[i]), .dout(buf_dualhi[i]), .en(buf_wr_en[i]), .clk(lsu_bus_buf_c1_clk), .*);
776 : rvdffs #(.WIDTH(1)) buf_ldfwdff (.din(buf_ldfwd_in[i]), .dout(buf_ldfwd[i]), .en(buf_ldfwd_en[i]), .clk(lsu_bus_buf_c1_clk), .*);
777 : rvdffs #(.WIDTH(DEPTH_LOG2)) buf_ldfwdtagff (.din(buf_ldfwdtag_in[i]), .dout(buf_ldfwdtag[i]), .en(buf_ldfwd_en[i]), .clk(lsu_bus_buf_c1_clk), .*);
778 : rvdffs #(.WIDTH(1)) buf_sideeffectff (.din(buf_sideeffect_in[i]), .dout(buf_sideeffect[i]), .en(buf_wr_en[i]), .clk(lsu_bus_buf_c1_clk), .*);
779 : rvdffs #(.WIDTH(1)) buf_unsignff (.din(buf_unsign_in[i]), .dout(buf_unsign[i]), .en(buf_wr_en[i]), .clk(lsu_bus_buf_c1_clk), .*);
780 : rvdffs #(.WIDTH(1)) buf_writeff (.din(buf_write_in[i]), .dout(buf_write[i]), .en(buf_wr_en[i]), .clk(lsu_bus_buf_c1_clk), .*);
781 : rvdffs #(.WIDTH(2)) buf_szff (.din(buf_sz_in[i]), .dout(buf_sz[i]), .en(buf_wr_en[i]), .clk(lsu_bus_buf_c1_clk), .*);
782 : rvdffe #(.WIDTH(32)) buf_addrff (.din(buf_addr_in[i][31:0]), .dout(buf_addr[i]), .en(buf_wr_en[i]), .*);
783 : rvdffs #(.WIDTH(4)) buf_byteenff (.din(buf_byteen_in[i][3:0]), .dout(buf_byteen[i]), .en(buf_wr_en[i]), .clk(lsu_bus_buf_c1_clk), .*);
784 : rvdffe #(.WIDTH(32)) buf_dataff (.din(buf_data_in[i][31:0]), .dout(buf_data[i]), .en(buf_data_en[i]), .*);
785 : rvdffsc #(.WIDTH(1)) buf_errorff (.din(1'b1), .dout(buf_error[i]), .en(buf_error_en[i]), .clear(buf_rst[i]), .clk(lsu_bus_buf_c1_clk), .*);
786 :
787 : end
788 :
789 : // buffer full logic
790 298 : always_comb begin
791 298 : buf_numvld_any[3:0] = 4'(({1'b0,lsu_busreq_m} << ldst_dual_m) +
792 298 : ({1'b0,lsu_busreq_r} << ldst_dual_r) +
793 298 : ibuf_valid);
794 298 : buf_numvld_wrcmd_any[3:0] = 4'b0;
795 298 : buf_numvld_cmd_any[3:0] = 4'b0;
796 298 : buf_numvld_pend_any[3:0] = 4'b0;
797 298 : any_done_wait_state = 1'b0;
798 1192 : for (int i=0; i<DEPTH; i++) begin
799 1192 : buf_numvld_any[3:0] += {3'b0, (buf_state[i] != IDLE)};
800 1192 : buf_numvld_wrcmd_any[3:0] += {3'b0, (buf_write[i] & (buf_state[i] == CMD) & ~buf_cmd_state_bus_en[i])};
801 1192 : buf_numvld_cmd_any[3:0] += {3'b0, ((buf_state[i] == CMD) & ~buf_cmd_state_bus_en[i])};
802 1192 : buf_numvld_pend_any[3:0] += {3'b0, ((buf_state[i] == START_WAIT) | ((buf_state[i] == CMD) & ~buf_cmd_state_bus_en[i]))};
803 1192 : any_done_wait_state |= (buf_state[i] == DONE_WAIT);
804 : end
805 : end
806 :
807 : assign lsu_bus_buffer_pend_any = (buf_numvld_pend_any != 0);
808 : assign lsu_bus_buffer_full_any = (ldst_dual_d & dec_lsu_valid_raw_d) ? (buf_numvld_any[3:0] >= (DEPTH-1)) : (buf_numvld_any[3:0] == DEPTH);
809 : assign lsu_bus_buffer_empty_any = ~(|buf_state[DEPTH-1:0]) & ~ibuf_valid & ~obuf_valid;
810 :
811 :
812 : // Non blocking ports
813 : assign lsu_nonblock_load_valid_m = lsu_busreq_m & lsu_pkt_m.valid & lsu_pkt_m.load & ~flush_m_up & ~ld_full_hit_m;
814 : assign lsu_nonblock_load_tag_m[DEPTH_LOG2-1:0] = WrPtr0_m[DEPTH_LOG2-1:0];
815 : assign lsu_nonblock_load_inv_r = lsu_nonblock_load_valid_r & ~lsu_commit_r;
816 : assign lsu_nonblock_load_inv_tag_r[DEPTH_LOG2-1:0] = WrPtr0_r[DEPTH_LOG2-1:0]; // r tag needs to be accurate even if there is no invalidate
817 :
818 298 : always_comb begin
819 298 : lsu_nonblock_load_data_ready = '0;
820 298 : lsu_nonblock_load_data_error = '0;
821 298 : lsu_nonblock_load_data_tag[DEPTH_LOG2-1:0] = '0;
822 298 : lsu_nonblock_load_data_lo[31:0] = '0;
823 298 : lsu_nonblock_load_data_hi[31:0] = '0;
824 1192 : for (int i=0; i<DEPTH; i++) begin
825 : // Use buf_rst[i] instead of buf_state_en[i] for timing
826 1192 : lsu_nonblock_load_data_ready |= (buf_state[i] == DONE) & ~buf_write[i];
827 1192 : lsu_nonblock_load_data_error |= (buf_state[i] == DONE) & buf_error[i] & ~buf_write[i];
828 1192 : lsu_nonblock_load_data_tag[DEPTH_LOG2-1:0] |= DEPTH_LOG2'(i) & {DEPTH_LOG2{((buf_state[i] == DONE) & ~buf_write[i] & (~buf_dual[i] | ~buf_dualhi[i]))}};
829 1192 : lsu_nonblock_load_data_lo[31:0] |= buf_data[i][31:0] & {32{((buf_state[i] == DONE) & ~buf_write[i] & (~buf_dual[i] | ~buf_dualhi[i]))}};
830 1192 : lsu_nonblock_load_data_hi[31:0] |= buf_data[i][31:0] & {32{((buf_state[i] == DONE) & ~buf_write[i] & (buf_dual[i] & buf_dualhi[i]))}};
831 : end
832 : end
833 :
834 : assign lsu_nonblock_addr_offset[1:0] = buf_addr[lsu_nonblock_load_data_tag][1:0];
835 : assign lsu_nonblock_sz[1:0] = buf_sz[lsu_nonblock_load_data_tag][1:0];
836 : assign lsu_nonblock_unsign = buf_unsign[lsu_nonblock_load_data_tag];
837 : assign lsu_nonblock_data_unalgn[31:0] = 32'({lsu_nonblock_load_data_hi[31:0], lsu_nonblock_load_data_lo[31:0]} >> 8*lsu_nonblock_addr_offset[1:0]);
838 :
839 : assign lsu_nonblock_load_data_valid = lsu_nonblock_load_data_ready & ~lsu_nonblock_load_data_error;
840 : assign lsu_nonblock_load_data[31:0] = ({32{ lsu_nonblock_unsign & (lsu_nonblock_sz[1:0] == 2'b00)}} & {24'b0,lsu_nonblock_data_unalgn[7:0]}) |
841 : ({32{ lsu_nonblock_unsign & (lsu_nonblock_sz[1:0] == 2'b01)}} & {16'b0,lsu_nonblock_data_unalgn[15:0]}) |
842 : ({32{~lsu_nonblock_unsign & (lsu_nonblock_sz[1:0] == 2'b00)}} & {{24{lsu_nonblock_data_unalgn[7]}}, lsu_nonblock_data_unalgn[7:0]}) |
843 : ({32{~lsu_nonblock_unsign & (lsu_nonblock_sz[1:0] == 2'b01)}} & {{16{lsu_nonblock_data_unalgn[15]}},lsu_nonblock_data_unalgn[15:0]}) |
844 : ({32{(lsu_nonblock_sz[1:0] == 2'b10)}} & lsu_nonblock_data_unalgn[31:0]);
845 :
846 : // Determine if there is a pending return to sideeffect load/store
847 298 : always_comb begin
848 298 : bus_sideeffect_pend = obuf_valid & obuf_sideeffect & dec_tlu_sideeffect_posted_disable;
849 1192 : for (int i=0; i<DEPTH; i++) begin
850 1192 : bus_sideeffect_pend |= ((buf_state[i] == RESP) & buf_sideeffect[i] & dec_tlu_sideeffect_posted_disable);
851 : end
852 : end
853 :
854 : // We have no ordering rules for AXI. Need to check outstanding trxns to same address for AXI
855 298 : always_comb begin
856 298 : bus_addr_match_pending = '0;
857 1192 : for (int i=0; i<DEPTH; i++) begin
858 1192 : bus_addr_match_pending |= (obuf_valid & (obuf_addr[31:3] == buf_addr[i][31:3]) & (buf_state[i] == RESP) & ~((obuf_tag0 == (pt.LSU_BUS_TAG)'(i)) | (obuf_merge & (obuf_tag1 == (pt.LSU_BUS_TAG)'(i)))));
859 : end
860 : end
861 :
862 : // Generic bus signals
863 : assign bus_cmd_ready = obuf_write ? ((obuf_cmd_done | obuf_data_done) ? (obuf_cmd_done ? lsu_axi_wready : lsu_axi_awready) : (lsu_axi_awready & lsu_axi_wready)) : lsu_axi_arready;
864 : assign bus_wcmd_sent = lsu_axi_awvalid & lsu_axi_awready;
865 : assign bus_wdata_sent = lsu_axi_wvalid & lsu_axi_wready;
866 : assign bus_cmd_sent = ((obuf_cmd_done | bus_wcmd_sent) & (obuf_data_done | bus_wdata_sent)) | (lsu_axi_arvalid & lsu_axi_arready);
867 :
868 : assign bus_rsp_read = lsu_axi_rvalid & lsu_axi_rready;
869 : assign bus_rsp_write = lsu_axi_bvalid & lsu_axi_bready;
870 : assign bus_rsp_read_tag[pt.LSU_BUS_TAG-1:0] = lsu_axi_rid[pt.LSU_BUS_TAG-1:0];
871 : assign bus_rsp_write_tag[pt.LSU_BUS_TAG-1:0] = lsu_axi_bid[pt.LSU_BUS_TAG-1:0];
872 : assign bus_rsp_write_error = bus_rsp_write & (lsu_axi_bresp[1:0] != 2'b0);
873 : assign bus_rsp_read_error = bus_rsp_read & (lsu_axi_rresp[1:0] != 2'b0);
874 : assign bus_rsp_rdata[63:0] = lsu_axi_rdata[63:0];
875 :
876 : // AXI command signals
877 : assign lsu_axi_awvalid = obuf_valid & obuf_write & ~obuf_cmd_done & ~bus_addr_match_pending;
878 : assign lsu_axi_awid[pt.LSU_BUS_TAG-1:0] = (pt.LSU_BUS_TAG)'(obuf_tag0);
879 : assign lsu_axi_awaddr[31:0] = obuf_sideeffect ? obuf_addr[31:0] : {obuf_addr[31:3],3'b0};
880 : assign lsu_axi_awsize[2:0] = obuf_sideeffect ? {1'b0, obuf_sz[1:0]} : 3'b011;
881 : assign lsu_axi_awprot[2:0] = 3'b001;
882 : assign lsu_axi_awcache[3:0] = obuf_sideeffect ? 4'b0 : 4'b1111;
883 : assign lsu_axi_awregion[3:0] = obuf_addr[31:28];
884 : assign lsu_axi_awlen[7:0] = '0;
885 : assign lsu_axi_awburst[1:0] = 2'b01;
886 : assign lsu_axi_awqos[3:0] = '0;
887 : assign lsu_axi_awlock = '0;
888 :
889 : assign lsu_axi_wvalid = obuf_valid & obuf_write & ~obuf_data_done & ~bus_addr_match_pending;
890 : assign lsu_axi_wstrb[7:0] = obuf_byteen[7:0] & {8{obuf_write}};
891 : assign lsu_axi_wdata[63:0] = obuf_data[63:0];
892 : assign lsu_axi_wlast = '1;
893 :
894 : assign lsu_axi_arvalid = obuf_valid & ~obuf_write & ~obuf_nosend & ~bus_addr_match_pending;
895 : assign lsu_axi_arid[pt.LSU_BUS_TAG-1:0] = (pt.LSU_BUS_TAG)'(obuf_tag0);
896 : assign lsu_axi_araddr[31:0] = obuf_sideeffect ? obuf_addr[31:0] : {obuf_addr[31:3],3'b0};
897 : assign lsu_axi_arsize[2:0] = obuf_sideeffect ? {1'b0, obuf_sz[1:0]} : 3'b011;
898 : assign lsu_axi_arprot[2:0] = 3'b001;
899 : assign lsu_axi_arcache[3:0] = obuf_sideeffect ? 4'b0 : 4'b1111;
900 : assign lsu_axi_arregion[3:0] = obuf_addr[31:28];
901 : assign lsu_axi_arlen[7:0] = '0;
902 : assign lsu_axi_arburst[1:0] = 2'b01;
903 : assign lsu_axi_arqos[3:0] = '0;
904 : assign lsu_axi_arlock = '0;
905 :
906 : assign lsu_axi_bready = 1;
907 : assign lsu_axi_rready = 1;
908 :
909 298 : always_comb begin
910 298 : lsu_imprecise_error_store_any = '0;
911 298 : lsu_imprecise_error_store_tag = '0;
912 1192 : for (int i=0; i<DEPTH; i++) begin
913 1192 : lsu_imprecise_error_store_any |= lsu_bus_clk_en_q & (buf_state[i] == DONE) & buf_error[i] & buf_write[i];
914 1192 : lsu_imprecise_error_store_tag |= DEPTH_LOG2'(i) & {DEPTH_LOG2{((buf_state[i] == DONE) & buf_error[i] & buf_write[i])}};
915 : end
916 : end
917 : assign lsu_imprecise_error_load_any = lsu_nonblock_load_data_error & ~lsu_imprecise_error_store_any; // This is to make sure we send only one imprecise error for load/store
918 : assign lsu_imprecise_error_addr_any[31:0] = lsu_imprecise_error_store_any ? buf_addr[lsu_imprecise_error_store_tag[DEPTH_LOG2-1:0]] : buf_addr[lsu_nonblock_load_data_tag[DEPTH_LOG2-1:0]];
919 :
920 : // PMU signals
921 : assign lsu_pmu_bus_trxn = (lsu_axi_awvalid & lsu_axi_awready) | (lsu_axi_wvalid & lsu_axi_wready) | (lsu_axi_arvalid & lsu_axi_arready);
922 : assign lsu_pmu_bus_misaligned = lsu_busreq_r & ldst_dual_r & lsu_commit_r;
923 : assign lsu_pmu_bus_error = lsu_imprecise_error_load_any | lsu_imprecise_error_store_any;
924 : assign lsu_pmu_bus_busy = (lsu_axi_awvalid & ~lsu_axi_awready) | (lsu_axi_wvalid & ~lsu_axi_wready) | (lsu_axi_arvalid & ~lsu_axi_arready);
925 :
926 : rvdff_fpga #(.WIDTH(1)) lsu_axi_awvalid_ff (.din(lsu_axi_awvalid), .dout(lsu_axi_awvalid_q), .clk(lsu_busm_clk), .clken(lsu_busm_clken), .rawclk(clk), .*);
927 : rvdff_fpga #(.WIDTH(1)) lsu_axi_awready_ff (.din(lsu_axi_awready), .dout(lsu_axi_awready_q), .clk(lsu_busm_clk), .clken(lsu_busm_clken), .rawclk(clk), .*);
928 : rvdff_fpga #(.WIDTH(1)) lsu_axi_wvalid_ff (.din(lsu_axi_wvalid), .dout(lsu_axi_wvalid_q), .clk(lsu_busm_clk), .clken(lsu_busm_clken), .rawclk(clk), .*);
929 : rvdff_fpga #(.WIDTH(1)) lsu_axi_wready_ff (.din(lsu_axi_wready), .dout(lsu_axi_wready_q), .clk(lsu_busm_clk), .clken(lsu_busm_clken), .rawclk(clk), .*);
930 : rvdff_fpga #(.WIDTH(1)) lsu_axi_arvalid_ff (.din(lsu_axi_arvalid), .dout(lsu_axi_arvalid_q), .clk(lsu_busm_clk), .clken(lsu_busm_clken), .rawclk(clk), .*);
931 : rvdff_fpga #(.WIDTH(1)) lsu_axi_arready_ff (.din(lsu_axi_arready), .dout(lsu_axi_arready_q), .clk(lsu_busm_clk), .clken(lsu_busm_clken), .rawclk(clk), .*);
932 :
933 : rvdff_fpga #(.WIDTH(1)) lsu_axi_bvalid_ff (.din(lsu_axi_bvalid), .dout(lsu_axi_bvalid_q), .clk(lsu_busm_clk), .clken(lsu_busm_clken), .rawclk(clk), .*);
934 : rvdff_fpga #(.WIDTH(1)) lsu_axi_bready_ff (.din(lsu_axi_bready), .dout(lsu_axi_bready_q), .clk(lsu_busm_clk), .clken(lsu_busm_clken), .rawclk(clk), .*);
935 : rvdff_fpga #(.WIDTH(2)) lsu_axi_bresp_ff (.din(lsu_axi_bresp[1:0]), .dout(lsu_axi_bresp_q[1:0]), .clk(lsu_busm_clk), .clken(lsu_busm_clken), .rawclk(clk), .*);
936 : rvdff_fpga #(.WIDTH(pt.LSU_BUS_TAG)) lsu_axi_bid_ff (.din(lsu_axi_bid[pt.LSU_BUS_TAG-1:0]),.dout(lsu_axi_bid_q[pt.LSU_BUS_TAG-1:0]),.clk(lsu_busm_clk), .clken(lsu_busm_clken), .rawclk(clk), .*);
937 : rvdffe #(.WIDTH(64)) lsu_axi_rdata_ff (.din(lsu_axi_rdata[63:0]), .dout(lsu_axi_rdata_q[63:0]), .en((lsu_axi_rvalid | clk_override) & lsu_bus_clk_en), .*);
938 :
939 : rvdff_fpga #(.WIDTH(1)) lsu_axi_rvalid_ff (.din(lsu_axi_rvalid), .dout(lsu_axi_rvalid_q), .clk(lsu_busm_clk), .clken(lsu_busm_clken), .rawclk(clk), .*);
940 : rvdff_fpga #(.WIDTH(1)) lsu_axi_rready_ff (.din(lsu_axi_rready), .dout(lsu_axi_rready_q), .clk(lsu_busm_clk), .clken(lsu_busm_clken), .rawclk(clk), .*);
941 : rvdff_fpga #(.WIDTH(2)) lsu_axi_rresp_ff (.din(lsu_axi_rresp[1:0]), .dout(lsu_axi_rresp_q[1:0]), .clk(lsu_busm_clk), .clken(lsu_busm_clken), .rawclk(clk), .*);
942 : rvdff_fpga #(.WIDTH(pt.LSU_BUS_TAG)) lsu_axi_rid_ff (.din(lsu_axi_rid[pt.LSU_BUS_TAG-1:0]),.dout(lsu_axi_rid_q[pt.LSU_BUS_TAG-1:0]),.clk(lsu_busm_clk), .clken(lsu_busm_clken), .rawclk(clk), .*);
943 :
944 : rvdff #(.WIDTH(DEPTH_LOG2)) lsu_WrPtr0_rff (.din(WrPtr0_m), .dout(WrPtr0_r), .clk(lsu_c2_r_clk), .*);
945 : rvdff #(.WIDTH(DEPTH_LOG2)) lsu_WrPtr1_rff (.din(WrPtr1_m), .dout(WrPtr1_r), .clk(lsu_c2_r_clk), .*);
946 :
947 : rvdff #(.WIDTH(1)) lsu_busreq_rff (.din(lsu_busreq_m & ~flush_r & ~ld_full_hit_m), .dout(lsu_busreq_r), .clk(lsu_c2_r_clk), .*);
948 : rvdff #(.WIDTH(1)) lsu_nonblock_load_valid_rff (.din(lsu_nonblock_load_valid_m), .dout(lsu_nonblock_load_valid_r), .clk(lsu_c2_r_clk), .*);
949 :
950 : `ifdef RV_ASSERT_ON
951 :
952 : for (genvar i=0; i<4; i++) begin: GenByte
953 : assert_ld_byte_hitvecfn_lo_onehot: assert #0 ($onehot0(ld_byte_hitvecfn_lo[i][DEPTH-1:0]));
954 : assert_ld_byte_hitvecfn_hi_onehot: assert #0 ($onehot0(ld_byte_hitvecfn_hi[i][DEPTH-1:0]));
955 : end
956 :
957 : for (genvar i=0; i<DEPTH; i++) begin: GenAssertAge
958 : assert_bufempty_agevec: assert #0 (~(lsu_bus_buffer_empty_any & |(buf_age[i])));
959 : end
960 :
961 : assert_CmdPtr0Dec_onehot: assert #0 ($onehot0(CmdPtr0Dec[DEPTH-1:0] & ~{DEPTH{dec_tlu_force_halt}}));
962 : assert_CmdPtr1Dec_onehot: assert #0 ($onehot0(CmdPtr1Dec[DEPTH-1:0] & ~{DEPTH{dec_tlu_force_halt}}));
963 :
964 : `endif
965 :
966 : endmodule // el2_lsu_bus_buffer
|