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: DCCM for LSU pipe
22 : // Comments: Single ported memory
23 : //
24 : //
25 : // DC1 -> DC2 -> DC3 -> DC4 (Commit)
26 : //
27 : // //********************************************************************************
28 :
29 : module el2_lsu_dccm_ctl
30 : import el2_pkg::*;
31 : #(
32 : `include "el2_param.vh"
33 : )
34 : (
35 69840565 : input logic lsu_c2_m_clk, // clocks
36 69840565 : input logic lsu_c2_r_clk, // clocks
37 69840565 : input logic lsu_c1_r_clk, // clocks
38 69840565 : input logic lsu_store_c1_r_clk, // clocks
39 69840565 : input logic lsu_free_c2_clk, // clocks
40 2 : input logic clk_override, // Override non-functional clock gating
41 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.
42 :
43 338 : input logic rst_l, // reset, active low
44 :
45 477821 : input el2_lsu_pkt_t lsu_pkt_r,// lsu packets
46 477824 : input el2_lsu_pkt_t lsu_pkt_m,// lsu packets
47 477872 : input el2_lsu_pkt_t lsu_pkt_d,// lsu packets
48 614422 : input logic addr_in_dccm_d, // address maps to dccm
49 12 : input logic addr_in_pic_d, // address maps to pic
50 12 : input logic addr_in_pic_m, // address maps to pic
51 614422 : input logic addr_in_dccm_m, addr_in_dccm_r, // address in dccm per pipe stage
52 12 : input logic addr_in_pic_r, // address in pic per pipe stage
53 18768 : input logic lsu_raw_fwd_lo_r, lsu_raw_fwd_hi_r,
54 2285226 : input logic lsu_commit_r, // lsu instruction in r commits
55 36584 : input logic ldst_dual_m, ldst_dual_r,// load/store is unaligned at 32 bit boundary per pipe stage
56 :
57 : // lsu address down the pipe
58 593287 : input logic [31:0] lsu_addr_d,
59 470950 : input logic [pt.DCCM_BITS-1:0] lsu_addr_m,
60 593285 : input logic [31:0] lsu_addr_r,
61 :
62 : // lsu address down the pipe - needed to check unaligned
63 677351 : input logic [pt.DCCM_BITS-1:0] end_addr_d,
64 677524 : input logic [pt.DCCM_BITS-1:0] end_addr_m,
65 677522 : input logic [pt.DCCM_BITS-1:0] end_addr_r,
66 :
67 :
68 258448 : input logic stbuf_reqvld_any, // write enable
69 18811 : input logic [pt.LSU_SB_BITS-1:0] stbuf_addr_any, // stbuf address (aligned)
70 :
71 7576 : input logic [pt.DCCM_DATA_WIDTH-1:0] stbuf_data_any, // the read out from stbuf
72 50849 : input logic [pt.DCCM_ECC_WIDTH-1:0] stbuf_ecc_any, // the encoded data with ECC bits
73 5218 : input logic [pt.DCCM_DATA_WIDTH-1:0] stbuf_fwddata_hi_m, // stbuf fowarding to load
74 4892 : input logic [pt.DCCM_DATA_WIDTH-1:0] stbuf_fwddata_lo_m, // stbuf fowarding to load
75 4200 : input logic [pt.DCCM_BYTE_WIDTH-1:0] stbuf_fwdbyteen_hi_m, // stbuf fowarding to load
76 4202 : input logic [pt.DCCM_BYTE_WIDTH-1:0] stbuf_fwdbyteen_lo_m, // stbuf fowarding to load
77 :
78 0 : output logic [pt.DCCM_DATA_WIDTH-1:0] dccm_rdata_hi_r, // data from the dccm
79 0 : output logic [pt.DCCM_DATA_WIDTH-1:0] dccm_rdata_lo_r, // data from the dccm
80 0 : output logic [pt.DCCM_ECC_WIDTH-1:0] dccm_data_ecc_hi_r, // data from the dccm + ecc
81 0 : output logic [pt.DCCM_ECC_WIDTH-1:0] dccm_data_ecc_lo_r,
82 0 : output logic [pt.DCCM_DATA_WIDTH-1:0] lsu_ld_data_r, // right justified, ie load byte will have data at 7:0
83 24696 : output logic [pt.DCCM_DATA_WIDTH-1:0] lsu_ld_data_corr_r, // right justified & ECC corrected, ie load byte will have data at 7:0
84 :
85 4 : input logic lsu_double_ecc_error_r, // lsu has a DED
86 0 : input logic single_ecc_error_hi_r, // sec detected on hi dccm bank
87 4 : input logic single_ecc_error_lo_r, // sec detected on lower dccm bank
88 2 : input logic [pt.DCCM_DATA_WIDTH-1:0] sec_data_hi_r, // corrected dccm data
89 2 : input logic [pt.DCCM_DATA_WIDTH-1:0] sec_data_lo_r, // corrected dccm data
90 2 : input logic [pt.DCCM_DATA_WIDTH-1:0] sec_data_hi_r_ff, // corrected dccm data
91 2 : input logic [pt.DCCM_DATA_WIDTH-1:0] sec_data_lo_r_ff, // corrected dccm data
92 0 : input logic [pt.DCCM_ECC_WIDTH-1:0] sec_data_ecc_hi_r_ff, // the encoded data with ECC bits
93 50849 : input logic [pt.DCCM_ECC_WIDTH-1:0] sec_data_ecc_lo_r_ff, // the encoded data with ECC bits
94 :
95 47176 : output logic [pt.DCCM_DATA_WIDTH-1:0] dccm_rdata_hi_m, // data from the dccm
96 47176 : output logic [pt.DCCM_DATA_WIDTH-1:0] dccm_rdata_lo_m, // data from the dccm
97 154095 : output logic [pt.DCCM_ECC_WIDTH-1:0] dccm_data_ecc_hi_m, // data from the dccm + ecc
98 154095 : output logic [pt.DCCM_ECC_WIDTH-1:0] dccm_data_ecc_lo_m,
99 54456 : output logic [pt.DCCM_DATA_WIDTH-1:0] lsu_ld_data_m, // right justified, ie load byte will have data at 7:0
100 :
101 4 : input logic lsu_double_ecc_error_m, // lsu has a DED
102 47176 : input logic [pt.DCCM_DATA_WIDTH-1:0] sec_data_hi_m, // corrected dccm data
103 47176 : input logic [pt.DCCM_DATA_WIDTH-1:0] sec_data_lo_m, // corrected dccm data
104 :
105 81488 : input logic [31:0] store_data_m, // Store data M-stage
106 0 : input logic dma_dccm_wen, // Perform DMA writes only for word/dword
107 0 : input logic dma_pic_wen, // Perform PIC writes
108 12 : input logic [2:0] dma_mem_tag_m, // DMA Buffer entry number M-stage
109 0 : input logic [31:0] dma_mem_addr, // DMA request address
110 12 : input logic [63:0] dma_mem_wdata, // DMA write data
111 12 : input logic [31:0] dma_dccm_wdata_lo, // Shift the dma data to lower bits to make it consistent to lsu stores
112 0 : input logic [31:0] dma_dccm_wdata_hi, // Shift the dma data to lower bits to make it consistent to lsu stores
113 0 : input logic [pt.DCCM_ECC_WIDTH-1:0] dma_dccm_wdata_ecc_hi, // ECC bits for the DMA wdata
114 50849 : input logic [pt.DCCM_ECC_WIDTH-1:0] dma_dccm_wdata_ecc_lo, // ECC bits for the DMA wdata
115 :
116 1717 : output logic [pt.DCCM_DATA_WIDTH-1:0] store_data_hi_r,
117 92714 : output logic [pt.DCCM_DATA_WIDTH-1:0] store_data_lo_r,
118 1921 : output logic [pt.DCCM_DATA_WIDTH-1:0] store_datafn_hi_r, // data from the dccm
119 92714 : output logic [pt.DCCM_DATA_WIDTH-1:0] store_datafn_lo_r, // data from the dccm
120 56576 : output logic [31:0] store_data_r, // raw store data to be sent to bus
121 4 : output logic ld_single_ecc_error_r,
122 4 : output logic ld_single_ecc_error_r_ff,
123 :
124 0 : output logic [31:0] picm_mask_data_m, // pic data to stbuf
125 262890 : output logic lsu_stbuf_commit_any, // stbuf wins the dccm port or is to pic
126 561000 : output logic lsu_dccm_rden_m, // dccm read
127 561000 : output logic lsu_dccm_rden_r, // dccm read
128 :
129 0 : output logic dccm_dma_rvalid, // dccm serviving the dma load
130 4 : output logic dccm_dma_ecc_error, // DMA load had ecc error
131 12 : output logic [2:0] dccm_dma_rtag, // DMA return tag
132 39564 : output logic [63:0] dccm_dma_rdata, // dccm data to dma request
133 :
134 : // DCCM ports
135 262894 : output logic dccm_wren, // dccm interface -- write
136 561000 : output logic dccm_rden, // dccm interface -- write
137 18811 : output logic [pt.DCCM_BITS-1:0] dccm_wr_addr_lo, // dccm interface -- wr addr for lo bank
138 18811 : output logic [pt.DCCM_BITS-1:0] dccm_wr_addr_hi, // dccm interface -- wr addr for hi bank
139 470956 : output logic [pt.DCCM_BITS-1:0] dccm_rd_addr_lo, // dccm interface -- read address for lo bank
140 677351 : output logic [pt.DCCM_BITS-1:0] dccm_rd_addr_hi, // dccm interface -- read address for hi bank
141 5376 : output logic [pt.DCCM_FDATA_WIDTH-1:0] dccm_wr_data_lo, // dccm write data for lo bank
142 5376 : output logic [pt.DCCM_FDATA_WIDTH-1:0] dccm_wr_data_hi, // dccm write data for hi bank
143 :
144 47176 : input logic [pt.DCCM_FDATA_WIDTH-1:0] dccm_rd_data_lo, // dccm read data back from the dccm
145 47176 : input logic [pt.DCCM_FDATA_WIDTH-1:0] dccm_rd_data_hi, // dccm read data back from the dccm
146 :
147 : // PIC ports
148 8 : output logic picm_wren, // write to pic
149 2 : output logic picm_rden, // read to pick
150 10 : output logic picm_mken, // write to pic need a mask
151 316 : output logic [31:0] picm_rdaddr, // address for pic read access
152 316 : output logic [31:0] picm_wraddr, // address for pic write access
153 92714 : output logic [31:0] picm_wr_data, // write data
154 0 : input logic [31:0] picm_rd_data, // read data
155 :
156 : // Excluding scan_mode from coverage as its usage is determined by the integrator of the VeeR core.
157 : /*verilator coverage_off*/
158 : input logic scan_mode // scan mode
159 : /*verilator coverage_on*/
160 : );
161 :
162 :
163 : localparam DCCM_WIDTH_BITS = $clog2(pt.DCCM_BYTE_WIDTH);
164 :
165 0 : logic lsu_dccm_rden_d, lsu_dccm_wren_d;
166 0 : logic ld_single_ecc_error_lo_r, ld_single_ecc_error_hi_r;
167 0 : logic ld_single_ecc_error_lo_r_ns, ld_single_ecc_error_hi_r_ns;
168 0 : logic ld_single_ecc_error_lo_r_ff, ld_single_ecc_error_hi_r_ff;
169 4 : logic lsu_double_ecc_error_r_ff;
170 0 : logic [pt.DCCM_BITS-1:0] ld_sec_addr_lo_r_ff, ld_sec_addr_hi_r_ff;
171 49136 : logic [pt.DCCM_DATA_WIDTH-1:0] store_data_lo_r_in, store_data_hi_r_in ;
172 0 : logic [63:0] picm_rd_data_m;
173 :
174 25520 : logic dccm_wr_bypass_d_m_hi, dccm_wr_bypass_d_r_hi;
175 25520 : logic dccm_wr_bypass_d_m_lo, dccm_wr_bypass_d_r_lo;
176 0 : logic kill_ecc_corr_lo_r, kill_ecc_corr_hi_r;
177 :
178 : // byte_en flowing down
179 648860 : logic [3:0] store_byteen_m ,store_byteen_r;
180 0 : logic [7:0] store_byteen_ext_m, store_byteen_ext_r;
181 :
182 : if (pt.LOAD_TO_USE_PLUS1 == 1) begin: L2U_Plus1_1
183 : logic [63:0] lsu_rdata_r, lsu_rdata_corr_r;
184 : logic [63:0] dccm_rdata_r, dccm_rdata_corr_r;
185 : logic [63:0] stbuf_fwddata_r;
186 : logic [7:0] stbuf_fwdbyteen_r;
187 : logic [31:0] stbuf_fwddata_lo_r, stbuf_fwddata_hi_r;
188 : logic [3:0] stbuf_fwdbyteen_lo_r, stbuf_fwdbyteen_hi_r;
189 : logic [31:0] lsu_rdata_lo_r, lsu_rdata_hi_r;
190 : logic [63:0] picm_rd_data_r;
191 : logic [63:32] lsu_ld_data_r_nc, lsu_ld_data_corr_r_nc;
192 : logic [2:0] dma_mem_tag_r;
193 : logic stbuf_fwddata_en;
194 :
195 : assign dccm_dma_rvalid = lsu_pkt_r.valid & lsu_pkt_r.load & lsu_pkt_r.dma;
196 : assign dccm_dma_ecc_error = lsu_double_ecc_error_r;
197 : assign dccm_dma_rtag[2:0] = dma_mem_tag_r[2:0];
198 : assign dccm_dma_rdata[63:0] = ldst_dual_r ? lsu_rdata_corr_r[63:0] : {2{lsu_rdata_corr_r[31:0]}};
199 : assign {lsu_ld_data_r_nc[63:32], lsu_ld_data_r[31:0]} = lsu_rdata_r[63:0] >> 8*lsu_addr_r[1:0];
200 : assign {lsu_ld_data_corr_r_nc[63:32], lsu_ld_data_corr_r[31:0]} = lsu_rdata_corr_r[63:0] >> 8*lsu_addr_r[1:0];
201 :
202 : assign picm_rd_data_r[63:32] = picm_rd_data_r[31:0];
203 : assign dccm_rdata_r[63:0] = {dccm_rdata_hi_r[31:0],dccm_rdata_lo_r[31:0]};
204 : assign dccm_rdata_corr_r[63:0] = {sec_data_hi_r[31:0],sec_data_lo_r[31:0]};
205 : assign stbuf_fwddata_r[63:0] = {stbuf_fwddata_hi_r[31:0], stbuf_fwddata_lo_r[31:0]};
206 : assign stbuf_fwdbyteen_r[7:0] = {stbuf_fwdbyteen_hi_r[3:0], stbuf_fwdbyteen_lo_r[3:0]};
207 : assign stbuf_fwddata_en = (|stbuf_fwdbyteen_hi_m[3:0]) | (|stbuf_fwdbyteen_lo_m[3:0]) | clk_override;
208 :
209 : for (genvar i=0; i<8; i++) begin: GenDMAData
210 : assign lsu_rdata_corr_r[(8*i)+7:8*i] = stbuf_fwdbyteen_r[i] ? stbuf_fwddata_r[(8*i)+7:8*i] :
211 : (addr_in_pic_r ? picm_rd_data_r[(8*i)+7:8*i] : ({8{addr_in_dccm_r}} & dccm_rdata_corr_r[(8*i)+7:8*i]));
212 :
213 : assign lsu_rdata_r[(8*i)+7:8*i] = stbuf_fwdbyteen_r[i] ? stbuf_fwddata_r[(8*i)+7:8*i] :
214 : (addr_in_pic_r ? picm_rd_data_r[(8*i)+7:8*i] : ({8{addr_in_dccm_r}} & dccm_rdata_r[(8*i)+7:8*i]));
215 : end
216 : rvdffe #(pt.DCCM_DATA_WIDTH) dccm_rdata_hi_r_ff (.*, .din(dccm_rdata_hi_m[pt.DCCM_DATA_WIDTH-1:0]), .dout(dccm_rdata_hi_r[pt.DCCM_DATA_WIDTH-1:0]), .en((lsu_dccm_rden_m & ldst_dual_m) | clk_override));
217 : rvdffe #(pt.DCCM_DATA_WIDTH) dccm_rdata_lo_r_ff (.*, .din(dccm_rdata_lo_m[pt.DCCM_DATA_WIDTH-1:0]), .dout(dccm_rdata_lo_r[pt.DCCM_DATA_WIDTH-1:0]), .en(lsu_dccm_rden_m | clk_override));
218 : rvdffe #(2*pt.DCCM_ECC_WIDTH) dccm_data_ecc_r_ff (.*, .din({dccm_data_ecc_hi_m[pt.DCCM_ECC_WIDTH-1:0], dccm_data_ecc_lo_m[pt.DCCM_ECC_WIDTH-1:0]}),
219 : .dout({dccm_data_ecc_hi_r[pt.DCCM_ECC_WIDTH-1:0], dccm_data_ecc_lo_r[pt.DCCM_ECC_WIDTH-1:0]}), .en(lsu_dccm_rden_m | clk_override));
220 : rvdff #(8) stbuf_fwdbyteen_ff (.*, .din({stbuf_fwdbyteen_hi_m[3:0], stbuf_fwdbyteen_lo_m[3:0]}), .dout({stbuf_fwdbyteen_hi_r[3:0], stbuf_fwdbyteen_lo_r[3:0]}), .clk(lsu_c2_r_clk));
221 : rvdffe #(64) stbuf_fwddata_ff (.*, .din({stbuf_fwddata_hi_m[31:0], stbuf_fwddata_lo_m[31:0]}), .dout({stbuf_fwddata_hi_r[31:0], stbuf_fwddata_lo_r[31:0]}), .en(stbuf_fwddata_en));
222 : rvdffe #(32) picm_rddata_rff (.*, .din(picm_rd_data_m[31:0]), .dout(picm_rd_data_r[31:0]), .en(addr_in_pic_m | clk_override));
223 : rvdff #(3) dma_mem_tag_rff (.*, .din(dma_mem_tag_m[2:0]), .dout(dma_mem_tag_r[2:0]), .clk(lsu_c1_r_clk));
224 :
225 : end else begin: L2U_Plus1_0
226 :
227 : logic [63:0] lsu_rdata_m, lsu_rdata_corr_m;
228 : logic [63:0] dccm_rdata_m, dccm_rdata_corr_m;
229 : logic [63:0] stbuf_fwddata_m;
230 : logic [7:0] stbuf_fwdbyteen_m;
231 : logic [63:32] lsu_ld_data_m_nc, lsu_ld_data_corr_m_nc;
232 : logic [31:0] lsu_ld_data_corr_m;
233 :
234 : assign dccm_dma_rvalid = lsu_pkt_m.valid & lsu_pkt_m.load & lsu_pkt_m.dma;
235 : assign dccm_dma_ecc_error = lsu_double_ecc_error_m;
236 : assign dccm_dma_rtag[2:0] = dma_mem_tag_m[2:0];
237 : assign dccm_dma_rdata[63:0] = ldst_dual_m ? lsu_rdata_corr_m[63:0] : {2{lsu_rdata_corr_m[31:0]}};
238 : assign {lsu_ld_data_m_nc[63:32], lsu_ld_data_m[31:0]} = 64'(lsu_rdata_m[63:0] >> 8*lsu_addr_m[1:0]);
239 : assign {lsu_ld_data_corr_m_nc[63:32], lsu_ld_data_corr_m[31:0]} = 64'(lsu_rdata_corr_m[63:0] >> 8*lsu_addr_m[1:0]);
240 :
241 : assign dccm_rdata_m[63:0] = {dccm_rdata_hi_m[31:0],dccm_rdata_lo_m[31:0]};
242 : assign dccm_rdata_corr_m[63:0] = {sec_data_hi_m[31:0],sec_data_lo_m[31:0]};
243 : assign stbuf_fwddata_m[63:0] = {stbuf_fwddata_hi_m[31:0], stbuf_fwddata_lo_m[31:0]};
244 : assign stbuf_fwdbyteen_m[7:0] = {stbuf_fwdbyteen_hi_m[3:0], stbuf_fwdbyteen_lo_m[3:0]};
245 :
246 : for (genvar i=0; i<8; i++) begin: GenLoop
247 : assign lsu_rdata_corr_m[(8*i)+7:8*i] = stbuf_fwdbyteen_m[i] ? stbuf_fwddata_m[(8*i)+7:8*i] :
248 : (addr_in_pic_m ? picm_rd_data_m[(8*i)+7:8*i] : ({8{addr_in_dccm_m}} & dccm_rdata_corr_m[(8*i)+7:8*i]));
249 :
250 : assign lsu_rdata_m[(8*i)+7:8*i] = stbuf_fwdbyteen_m[i] ? stbuf_fwddata_m[(8*i)+7:8*i] :
251 : (addr_in_pic_m ? picm_rd_data_m[(8*i)+7:8*i] : ({8{addr_in_dccm_m}} & dccm_rdata_m[(8*i)+7:8*i]));
252 : end
253 :
254 : rvdffe #(32) lsu_ld_data_corr_rff(.*, .din(lsu_ld_data_corr_m[31:0]), .dout(lsu_ld_data_corr_r[31:0]), .en((lsu_pkt_m.valid & lsu_pkt_m.load & (addr_in_pic_m | addr_in_dccm_m)) | clk_override));
255 : end
256 :
257 : assign kill_ecc_corr_lo_r = (((lsu_addr_d[pt.DCCM_BITS-1:2] == lsu_addr_r[pt.DCCM_BITS-1:2]) | (end_addr_d[pt.DCCM_BITS-1:2] == lsu_addr_r[pt.DCCM_BITS-1:2])) & lsu_pkt_d.valid & lsu_pkt_d.store & lsu_pkt_d.dma & addr_in_dccm_d) |
258 : (((lsu_addr_m[pt.DCCM_BITS-1:2] == lsu_addr_r[pt.DCCM_BITS-1:2]) | (end_addr_m[pt.DCCM_BITS-1:2] == lsu_addr_r[pt.DCCM_BITS-1:2])) & lsu_pkt_m.valid & lsu_pkt_m.store & lsu_pkt_m.dma & addr_in_dccm_m);
259 :
260 : assign kill_ecc_corr_hi_r = (((lsu_addr_d[pt.DCCM_BITS-1:2] == end_addr_r[pt.DCCM_BITS-1:2]) | (end_addr_d[pt.DCCM_BITS-1:2] == end_addr_r[pt.DCCM_BITS-1:2])) & lsu_pkt_d.valid & lsu_pkt_d.store & lsu_pkt_d.dma & addr_in_dccm_d) |
261 : (((lsu_addr_m[pt.DCCM_BITS-1:2] == end_addr_r[pt.DCCM_BITS-1:2]) | (end_addr_m[pt.DCCM_BITS-1:2] == end_addr_r[pt.DCCM_BITS-1:2])) & lsu_pkt_m.valid & lsu_pkt_m.store & lsu_pkt_m.dma & addr_in_dccm_m);
262 :
263 : assign ld_single_ecc_error_lo_r = lsu_pkt_r.load & single_ecc_error_lo_r & ~lsu_raw_fwd_lo_r;
264 : assign ld_single_ecc_error_hi_r = lsu_pkt_r.load & single_ecc_error_hi_r & ~lsu_raw_fwd_hi_r;
265 : assign ld_single_ecc_error_r = (ld_single_ecc_error_lo_r | ld_single_ecc_error_hi_r) & ~lsu_double_ecc_error_r;
266 :
267 : assign ld_single_ecc_error_lo_r_ns = ld_single_ecc_error_lo_r & (lsu_commit_r | lsu_pkt_r.dma) & ~kill_ecc_corr_lo_r;
268 : assign ld_single_ecc_error_hi_r_ns = ld_single_ecc_error_hi_r & (lsu_commit_r | lsu_pkt_r.dma) & ~kill_ecc_corr_hi_r;
269 : assign ld_single_ecc_error_r_ff = (ld_single_ecc_error_lo_r_ff | ld_single_ecc_error_hi_r_ff) & ~lsu_double_ecc_error_r_ff;
270 :
271 : assign lsu_stbuf_commit_any = stbuf_reqvld_any &
272 : (~(lsu_dccm_rden_d | lsu_dccm_wren_d | ld_single_ecc_error_r_ff) |
273 : (lsu_dccm_rden_d & ~((stbuf_addr_any[pt.DCCM_WIDTH_BITS+:pt.DCCM_BANK_BITS] == lsu_addr_d[pt.DCCM_WIDTH_BITS+:pt.DCCM_BANK_BITS]) |
274 : (stbuf_addr_any[pt.DCCM_WIDTH_BITS+:pt.DCCM_BANK_BITS] == end_addr_d[pt.DCCM_WIDTH_BITS+:pt.DCCM_BANK_BITS]))));
275 :
276 : // No need to read for aligned word/dword stores since ECC will come by new data completely
277 : assign lsu_dccm_rden_d = lsu_pkt_d.valid & (lsu_pkt_d.load | (lsu_pkt_d.store & (~(lsu_pkt_d.word | lsu_pkt_d.dword) | (lsu_addr_d[1:0] != 2'b0)))) & addr_in_dccm_d;
278 :
279 : // DMA will read/write in decode stage
280 : assign lsu_dccm_wren_d = dma_dccm_wen;
281 :
282 : // DCCM inputs
283 : assign dccm_wren = lsu_dccm_wren_d | lsu_stbuf_commit_any | ld_single_ecc_error_r_ff;
284 : assign dccm_rden = lsu_dccm_rden_d & addr_in_dccm_d;
285 : assign dccm_wr_addr_lo[pt.DCCM_BITS-1:0] = ld_single_ecc_error_r_ff ? (ld_single_ecc_error_lo_r_ff ? ld_sec_addr_lo_r_ff[pt.DCCM_BITS-1:0] : ld_sec_addr_hi_r_ff[pt.DCCM_BITS-1:0]) :
286 : lsu_dccm_wren_d ? lsu_addr_d[pt.DCCM_BITS-1:0] : stbuf_addr_any[pt.DCCM_BITS-1:0];
287 : assign dccm_wr_addr_hi[pt.DCCM_BITS-1:0] = ld_single_ecc_error_r_ff ? (ld_single_ecc_error_hi_r_ff ? ld_sec_addr_hi_r_ff[pt.DCCM_BITS-1:0] : ld_sec_addr_lo_r_ff[pt.DCCM_BITS-1:0]) :
288 : lsu_dccm_wren_d ? end_addr_d[pt.DCCM_BITS-1:0] : stbuf_addr_any[pt.DCCM_BITS-1:0];
289 : assign dccm_rd_addr_lo[pt.DCCM_BITS-1:0] = lsu_addr_d[pt.DCCM_BITS-1:0];
290 : assign dccm_rd_addr_hi[pt.DCCM_BITS-1:0] = end_addr_d[pt.DCCM_BITS-1:0];
291 : assign dccm_wr_data_lo[pt.DCCM_FDATA_WIDTH-1:0] = ld_single_ecc_error_r_ff ? (ld_single_ecc_error_lo_r_ff ? {sec_data_ecc_lo_r_ff[pt.DCCM_ECC_WIDTH-1:0],sec_data_lo_r_ff[pt.DCCM_DATA_WIDTH-1:0]} :
292 : {sec_data_ecc_hi_r_ff[pt.DCCM_ECC_WIDTH-1:0],sec_data_hi_r_ff[pt.DCCM_DATA_WIDTH-1:0]}) :
293 : (dma_dccm_wen ? {dma_dccm_wdata_ecc_lo[pt.DCCM_ECC_WIDTH-1:0],dma_dccm_wdata_lo[pt.DCCM_DATA_WIDTH-1:0]} :
294 : {stbuf_ecc_any[pt.DCCM_ECC_WIDTH-1:0],stbuf_data_any[pt.DCCM_DATA_WIDTH-1:0]});
295 : assign dccm_wr_data_hi[pt.DCCM_FDATA_WIDTH-1:0] = ld_single_ecc_error_r_ff ? (ld_single_ecc_error_hi_r_ff ? {sec_data_ecc_hi_r_ff[pt.DCCM_ECC_WIDTH-1:0],sec_data_hi_r_ff[pt.DCCM_DATA_WIDTH-1:0]} :
296 : {sec_data_ecc_lo_r_ff[pt.DCCM_ECC_WIDTH-1:0],sec_data_lo_r_ff[pt.DCCM_DATA_WIDTH-1:0]}) :
297 : (dma_dccm_wen ? {dma_dccm_wdata_ecc_hi[pt.DCCM_ECC_WIDTH-1:0],dma_dccm_wdata_hi[pt.DCCM_DATA_WIDTH-1:0]} :
298 : {stbuf_ecc_any[pt.DCCM_ECC_WIDTH-1:0],stbuf_data_any[pt.DCCM_DATA_WIDTH-1:0]});
299 :
300 : // DCCM outputs
301 : assign store_byteen_m[3:0] = {4{lsu_pkt_m.store}} &
302 : (({4{lsu_pkt_m.by}} & 4'b0001) |
303 : ({4{lsu_pkt_m.half}} & 4'b0011) |
304 : ({4{lsu_pkt_m.word}} & 4'b1111));
305 :
306 : assign store_byteen_r[3:0] = {4{lsu_pkt_r.store}} &
307 : (({4{lsu_pkt_r.by}} & 4'b0001) |
308 : ({4{lsu_pkt_r.half}} & 4'b0011) |
309 : ({4{lsu_pkt_r.word}} & 4'b1111));
310 :
311 : assign store_byteen_ext_m[7:0] = {4'b0,store_byteen_m[3:0]} << lsu_addr_m[1:0]; // The packet in m
312 : assign store_byteen_ext_r[7:0] = {4'b0,store_byteen_r[3:0]} << lsu_addr_r[1:0];
313 :
314 :
315 :
316 : assign dccm_wr_bypass_d_m_lo = (stbuf_addr_any[pt.DCCM_BITS-1:2] == lsu_addr_m[pt.DCCM_BITS-1:2]) & addr_in_dccm_m;
317 : assign dccm_wr_bypass_d_m_hi = (stbuf_addr_any[pt.DCCM_BITS-1:2] == end_addr_m[pt.DCCM_BITS-1:2]) & addr_in_dccm_m;
318 :
319 : assign dccm_wr_bypass_d_r_lo = (stbuf_addr_any[pt.DCCM_BITS-1:2] == lsu_addr_r[pt.DCCM_BITS-1:2]) & addr_in_dccm_r;
320 : assign dccm_wr_bypass_d_r_hi = (stbuf_addr_any[pt.DCCM_BITS-1:2] == end_addr_r[pt.DCCM_BITS-1:2]) & addr_in_dccm_r;
321 :
322 :
323 : if (pt.LOAD_TO_USE_PLUS1 == 1) begin: L2U1_Plus1_1
324 : logic dccm_wren_Q;
325 : logic [31:0] dccm_wr_data_Q;
326 : logic dccm_wr_bypass_d_m_lo_Q, dccm_wr_bypass_d_m_hi_Q;
327 : logic [31:0] store_data_pre_hi_r, store_data_pre_lo_r;
328 :
329 : assign {store_data_pre_hi_r[31:0], store_data_pre_lo_r[31:0]} = {32'b0,store_data_r[31:0]} << 8*lsu_addr_r[1:0];
330 :
331 : for (genvar i=0; i<4; i++) begin
332 : assign store_data_lo_r[(8*i)+7:(8*i)] = store_byteen_ext_r[i] ? store_data_pre_lo_r[(8*i)+7:(8*i)] : ((dccm_wren_Q & dccm_wr_bypass_d_m_lo_Q) ? dccm_wr_data_Q[(8*i)+7:(8*i)] : sec_data_lo_r[(8*i)+7:(8*i)]);
333 : assign store_data_hi_r[(8*i)+7:(8*i)] = store_byteen_ext_r[i+4] ? store_data_pre_hi_r[(8*i)+7:(8*i)] : ((dccm_wren_Q & dccm_wr_bypass_d_m_hi_Q) ? dccm_wr_data_Q[(8*i)+7:(8*i)] : sec_data_hi_r[(8*i)+7:(8*i)]);
334 :
335 : assign store_datafn_lo_r[(8*i)+7:(8*i)] = store_byteen_ext_r[i] ? store_data_pre_lo_r[(8*i)+7:(8*i)] : ((lsu_stbuf_commit_any & dccm_wr_bypass_d_r_lo) ? stbuf_data_any[(8*i)+7:(8*i)] :
336 : ((dccm_wren_Q & dccm_wr_bypass_d_m_lo_Q) ? dccm_wr_data_Q[(8*i)+7:(8*i)] : sec_data_lo_r[(8*i)+7:(8*i)]));
337 : assign store_datafn_hi_r[(8*i)+7:(8*i)] = store_byteen_ext_r[i+4] ? store_data_pre_hi_r[(8*i)+7:(8*i)] : ((lsu_stbuf_commit_any & dccm_wr_bypass_d_r_hi) ? stbuf_data_any[(8*i)+7:(8*i)] :
338 : ((dccm_wren_Q & dccm_wr_bypass_d_m_hi_Q) ? dccm_wr_data_Q[(8*i)+7:(8*i)] : sec_data_hi_r[(8*i)+7:(8*i)]));
339 : end
340 :
341 : rvdff #(1) dccm_wren_ff (.*, .din(lsu_stbuf_commit_any), .dout(dccm_wren_Q), .clk(lsu_free_c2_clk)); // ECC load errors writing to dccm shouldn't fwd to stores in pipe
342 : rvdffe #(32) dccm_wrdata_ff (.*, .din(stbuf_data_any[31:0]), .dout(dccm_wr_data_Q[31:0]), .en(lsu_stbuf_commit_any | clk_override), .clk(clk));
343 : rvdff #(1) dccm_wrbyp_dm_loff (.*, .din(dccm_wr_bypass_d_m_lo), .dout(dccm_wr_bypass_d_m_lo_Q), .clk(lsu_free_c2_clk));
344 : rvdff #(1) dccm_wrbyp_dm_hiff (.*, .din(dccm_wr_bypass_d_m_hi), .dout(dccm_wr_bypass_d_m_hi_Q), .clk(lsu_free_c2_clk));
345 : rvdff #(32) store_data_rff (.*, .din(store_data_m[31:0]), .dout(store_data_r[31:0]), .clk(lsu_store_c1_r_clk));
346 :
347 : end else begin: L2U1_Plus1_0
348 :
349 : logic [31:0] store_data_hi_m, store_data_lo_m;
350 : logic [63:0] store_data_mask;
351 : assign {store_data_hi_m[31:0] , store_data_lo_m[31:0]} = {32'b0,store_data_m[31:0]} << 8*lsu_addr_m[1:0];
352 :
353 : for (genvar i=0; i<4; i++) begin
354 : assign store_data_hi_r_in[(8*i)+7:(8*i)] = store_byteen_ext_m[i+4] ? store_data_hi_m[(8*i)+7:(8*i)] :
355 : ((lsu_stbuf_commit_any & dccm_wr_bypass_d_m_hi) ? stbuf_data_any[(8*i)+7:(8*i)] : sec_data_hi_m[(8*i)+7:(8*i)]);
356 : assign store_data_lo_r_in[(8*i)+7:(8*i)] = store_byteen_ext_m[i] ? store_data_lo_m[(8*i)+7:(8*i)] :
357 : ((lsu_stbuf_commit_any & dccm_wr_bypass_d_m_lo) ? stbuf_data_any[(8*i)+7:(8*i)] : sec_data_lo_m[(8*i)+7:(8*i)]);
358 :
359 : assign store_datafn_lo_r[(8*i)+7:(8*i)] = (lsu_stbuf_commit_any & dccm_wr_bypass_d_r_lo & ~store_byteen_ext_r[i]) ? stbuf_data_any[(8*i)+7:(8*i)] : store_data_lo_r[(8*i)+7:(8*i)];
360 : assign store_datafn_hi_r[(8*i)+7:(8*i)] = (lsu_stbuf_commit_any & dccm_wr_bypass_d_r_hi & ~store_byteen_ext_r[i+4]) ? stbuf_data_any[(8*i)+7:(8*i)] : store_data_hi_r[(8*i)+7:(8*i)];
361 : end // for (genvar i=0; i<BYTE_WIDTH; i++)
362 :
363 : for (genvar i=0; i<4; i++) begin
364 : assign store_data_mask[(8*i)+7:(8*i)] = {8{store_byteen_r[i]}};
365 : end
366 : assign store_data_r[31:0] = 32'({store_data_hi_r[31:0],store_data_lo_r[31:0]} >> 8*lsu_addr_r[1:0]) & store_data_mask[31:0];
367 :
368 : rvdffe #(pt.DCCM_DATA_WIDTH) store_data_hi_rff (.*, .din(store_data_hi_r_in[pt.DCCM_DATA_WIDTH-1:0]), .dout(store_data_hi_r[pt.DCCM_DATA_WIDTH-1:0]), .en((ldst_dual_m & lsu_pkt_m.valid & lsu_pkt_m.store) | clk_override), .clk(clk));
369 : rvdff #(pt.DCCM_DATA_WIDTH) store_data_lo_rff (.*, .din(store_data_lo_r_in[pt.DCCM_DATA_WIDTH-1:0]), .dout(store_data_lo_r[pt.DCCM_DATA_WIDTH-1:0]), .clk(lsu_store_c1_r_clk));
370 :
371 : end
372 :
373 : assign dccm_rdata_lo_m[pt.DCCM_DATA_WIDTH-1:0] = dccm_rd_data_lo[pt.DCCM_DATA_WIDTH-1:0]; // for ld choose dccm_out
374 : assign dccm_rdata_hi_m[pt.DCCM_DATA_WIDTH-1:0] = dccm_rd_data_hi[pt.DCCM_DATA_WIDTH-1:0]; // for ld this is used for ecc
375 :
376 : assign dccm_data_ecc_lo_m[pt.DCCM_ECC_WIDTH-1:0] = dccm_rd_data_lo[pt.DCCM_FDATA_WIDTH-1:pt.DCCM_DATA_WIDTH];
377 : assign dccm_data_ecc_hi_m[pt.DCCM_ECC_WIDTH-1:0] = dccm_rd_data_hi[pt.DCCM_FDATA_WIDTH-1:pt.DCCM_DATA_WIDTH];
378 :
379 : // PIC signals. PIC ignores the lower 2 bits of address since PIC memory registers are 32-bits
380 : assign picm_wren = (lsu_pkt_r.valid & lsu_pkt_r.store & addr_in_pic_r & lsu_commit_r) | dma_pic_wen;
381 : assign picm_rden = lsu_pkt_d.valid & lsu_pkt_d.load & addr_in_pic_d;
382 : assign picm_mken = lsu_pkt_d.valid & lsu_pkt_d.store & addr_in_pic_d; // Get the mask for stores
383 : assign picm_rdaddr[31:0] = pt.PIC_BASE_ADDR | {{32-pt.PIC_BITS{1'b0}},lsu_addr_d[pt.PIC_BITS-1:0]};
384 :
385 : assign picm_wraddr[31:0] = pt.PIC_BASE_ADDR | {{32-pt.PIC_BITS{1'b0}},(dma_pic_wen ? dma_mem_addr[pt.PIC_BITS-1:0] : lsu_addr_r[pt.PIC_BITS-1:0])};
386 :
387 : assign picm_wr_data[31:0] = dma_pic_wen ? dma_mem_wdata[31:0] : store_datafn_lo_r[31:0];
388 :
389 : assign picm_mask_data_m[31:0] = picm_rd_data_m[31:0];
390 : assign picm_rd_data_m[63:0] = {picm_rd_data[31:0],picm_rd_data[31:0]};
391 :
392 : if (pt.DCCM_ENABLE == 1) begin: Gen_dccm_enable
393 : rvdff #(1) dccm_rden_mff (.*, .din(lsu_dccm_rden_d), .dout(lsu_dccm_rden_m), .clk(lsu_c2_m_clk));
394 : rvdff #(1) dccm_rden_rff (.*, .din(lsu_dccm_rden_m), .dout(lsu_dccm_rden_r), .clk(lsu_c2_r_clk));
395 :
396 : // ECC correction flops since dccm write happens next cycle
397 : // We are writing to dccm in r+1 for ecc correction since fast_int needs to be blocked in decode - 1. We can probably write in r for plus0 configuration since we know ecc error in M.
398 : // In that case these (_ff) flops are needed only in plus1 configuration
399 : rvdff #(1) ld_double_ecc_error_rff (.*, .din(lsu_double_ecc_error_r), .dout(lsu_double_ecc_error_r_ff), .clk(lsu_free_c2_clk));
400 : rvdff #(1) ld_single_ecc_error_hi_rff (.*, .din(ld_single_ecc_error_hi_r_ns), .dout(ld_single_ecc_error_hi_r_ff), .clk(lsu_free_c2_clk));
401 : rvdff #(1) ld_single_ecc_error_lo_rff (.*, .din(ld_single_ecc_error_lo_r_ns), .dout(ld_single_ecc_error_lo_r_ff), .clk(lsu_free_c2_clk));
402 : rvdffe #(pt.DCCM_BITS) ld_sec_addr_hi_rff (.*, .din(end_addr_r[pt.DCCM_BITS-1:0]), .dout(ld_sec_addr_hi_r_ff[pt.DCCM_BITS-1:0]), .en(ld_single_ecc_error_r | clk_override), .clk(clk));
403 : rvdffe #(pt.DCCM_BITS) ld_sec_addr_lo_rff (.*, .din(lsu_addr_r[pt.DCCM_BITS-1:0]), .dout(ld_sec_addr_lo_r_ff[pt.DCCM_BITS-1:0]), .en(ld_single_ecc_error_r | clk_override), .clk(clk));
404 :
405 : end else begin: Gen_dccm_disable
406 : assign lsu_dccm_rden_m = '0;
407 : assign lsu_dccm_rden_r = '0;
408 :
409 : assign lsu_double_ecc_error_r_ff = 1'b0;
410 : assign ld_single_ecc_error_hi_r_ff = 1'b0;
411 : assign ld_single_ecc_error_lo_r_ff = 1'b0;
412 : assign ld_sec_addr_hi_r_ff[pt.DCCM_BITS-1:0] = '0;
413 : assign ld_sec_addr_lo_r_ff[pt.DCCM_BITS-1:0] = '0;
414 : end
415 :
416 : `ifdef RV_ASSERT_ON
417 :
418 : // Load single ECC error correction implies commit/dma
419 : property ld_single_ecc_error_commit;
420 : @(posedge clk) disable iff(~rst_l) (ld_single_ecc_error_r_ff & dccm_wren) |-> ($past(lsu_commit_r | lsu_pkt_r.dma));
421 : endproperty
422 : assert_ld_single_ecc_error_commit: assert property (ld_single_ecc_error_commit) else
423 : $display("No commit or DMA but ECC correction happened");
424 :
425 :
426 : `endif
427 :
428 : endmodule
|