Line data Source code
1 : //********************************************************************************
2 : // SPDX-License-Identifier: Apache-2.0
3 : // Copyright 2020 Western Digital Corporation or its affiliates.
4 : //
5 : // Licensed under the Apache License, Version 2.0 (the "License");
6 : // you may not use this file except in compliance with the License.
7 : // You may obtain a copy of the License at
8 : //
9 : // http://www.apache.org/licenses/LICENSE-2.0
10 : //
11 : // Unless required by applicable law or agreed to in writing, software
12 : // distributed under the License is distributed on an "AS IS" BASIS,
13 : // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 : // See the License for the specific language governing permissions and
15 : // limitations under the License.
16 : //********************************************************************************
17 :
18 : //********************************************************************************
19 : // Function: Programmable Interrupt Controller
20 : // Comments:
21 : //********************************************************************************
22 :
23 : module el2_pic_ctrl
24 : import el2_pkg::*;
25 : #(
26 : `include "el2_param.vh"
27 : )
28 : (
29 :
30 67357489 : input logic clk, // Core clock
31 67357489 : input logic free_clk, // free clock
32 505 : input logic rst_l, // Reset for all flops
33 4 : input logic clk_override, // Clock over-ride for gating
34 302 : input logic io_clk_override, // PIC IO Clock over-ride for gating
35 269 : input logic [pt.PIC_TOTAL_INT_PLUS1-1:0] extintsrc_req, // Interrupt requests
36 1694287 : input logic [31:0] picm_rdaddr, // Address of the register
37 1710005 : input logic [31:0] picm_wraddr, // Address of the register
38 712136 : input logic [31:0] picm_wr_data, // Data to be written to the register
39 42900 : input logic picm_wren, // Write enable to the register
40 9602 : input logic picm_rden, // Read enable for the register
41 10 : input logic picm_mken, // Read the Mask for the register
42 1216 : input logic [3:0] meicurpl, // Current Priority Level
43 57 : input logic [3:0] meipt, // Current Priority Threshold
44 :
45 1133 : output logic mexintpend, // External Inerrupt request to the core
46 834 : output logic [7:0] claimid, // Claim Id of the requested interrupt
47 716 : output logic [3:0] pl, // Priority level of the requested interrupt
48 4770 : output logic [31:0] picm_rd_data, // Read data of the register
49 159 : output logic mhwakeup, // Wake-up interrupt request
50 : // Excluding scan_mode from coverage as its usage is determined by the integrator of the VeeR core.
51 : /*pragma coverage off*/
52 : input logic scan_mode // scan mode
53 : /*pragma coverage on*/
54 :
55 : );
56 :
57 : localparam NUM_LEVELS = $clog2(pt.PIC_TOTAL_INT_PLUS1);
58 : localparam INTPRIORITY_BASE_ADDR = pt.PIC_BASE_ADDR ;
59 : localparam INTPEND_BASE_ADDR = pt.PIC_BASE_ADDR + 32'h00001000 ;
60 : localparam INTENABLE_BASE_ADDR = pt.PIC_BASE_ADDR + 32'h00002000 ;
61 : localparam EXT_INTR_PIC_CONFIG = pt.PIC_BASE_ADDR + 32'h00003000 ;
62 : localparam EXT_INTR_GW_CONFIG = pt.PIC_BASE_ADDR + 32'h00004000 ;
63 : localparam EXT_INTR_GW_CLEAR = pt.PIC_BASE_ADDR + 32'h00005000 ;
64 :
65 :
66 : localparam INTPEND_SIZE = (pt.PIC_TOTAL_INT_PLUS1 <= 32) ? 32 :
67 : (pt.PIC_TOTAL_INT_PLUS1 <= 64) ? 64 :
68 : (pt.PIC_TOTAL_INT_PLUS1 <= 128) ? 128 :
69 : (pt.PIC_TOTAL_INT_PLUS1 <= 256) ? 256 :
70 : (pt.PIC_TOTAL_INT_PLUS1 <= 512) ? 512 : 1024 ;
71 :
72 : localparam INT_GRPS = INTPEND_SIZE / 32 ;
73 : localparam INTPRIORITY_BITS = 4 ;
74 : localparam ID_BITS = 8 ;
75 : localparam int GW_CONFIG[pt.PIC_TOTAL_INT_PLUS1-1:0] = '{default:0} ;
76 :
77 : localparam INT_ENABLE_GRPS = (pt.PIC_TOTAL_INT_PLUS1 - 1) / 4 ;
78 :
79 474 : logic [pt.PIC_TOTAL_INT_PLUS1-1:0] intenable_clk_enable ;
80 : //logic [INT_ENABLE_GRPS:0] intenable_clk_enable_grp ;
81 0 : logic [INT_ENABLE_GRPS:0] gw_clk ;
82 :
83 1580 : logic addr_intpend_base_match;
84 :
85 634 : logic raddr_config_pic_match ;
86 4234 : logic raddr_intenable_base_match;
87 1965591 : logic raddr_intpriority_base_match;
88 11881 : logic raddr_config_gw_base_match ;
89 :
90 638 : logic waddr_config_pic_match ;
91 1965822 : logic waddr_intpriority_base_match;
92 4618 : logic waddr_intenable_base_match;
93 12260 : logic waddr_config_gw_base_match ;
94 1514 : logic addr_clear_gw_base_match ;
95 :
96 1133 : logic mexintpend_in;
97 159 : logic mhwakeup_in ;
98 200 : logic intpend_reg_read ;
99 :
100 4770 : logic [31:0] picm_rd_data_in, intpend_rd_out;
101 1464 : logic intenable_rd_out ;
102 1560 : logic [INTPRIORITY_BITS-1:0] intpriority_rd_out;
103 1572 : logic [1:0] gw_config_rd_out;
104 :
105 106 : logic [pt.PIC_TOTAL_INT_PLUS1-1:0] [INTPRIORITY_BITS-1:0] intpriority_reg;
106 127 : logic [pt.PIC_TOTAL_INT_PLUS1-1:0] [INTPRIORITY_BITS-1:0] intpriority_reg_inv;
107 302 : logic [pt.PIC_TOTAL_INT_PLUS1-1:0] intpriority_reg_we;
108 100 : logic [pt.PIC_TOTAL_INT_PLUS1-1:0] intpriority_reg_re;
109 236 : logic [pt.PIC_TOTAL_INT_PLUS1-1:0] [1:0] gw_config_reg;
110 :
111 85 : logic [pt.PIC_TOTAL_INT_PLUS1-1:0] intenable_reg;
112 502 : logic [pt.PIC_TOTAL_INT_PLUS1-1:0] intenable_reg_we;
113 100 : logic [pt.PIC_TOTAL_INT_PLUS1-1:0] intenable_reg_re;
114 502 : logic [pt.PIC_TOTAL_INT_PLUS1-1:0] gw_config_reg_we;
115 100 : logic [pt.PIC_TOTAL_INT_PLUS1-1:0] gw_config_reg_re;
116 106 : logic [pt.PIC_TOTAL_INT_PLUS1-1:0] gw_clear_reg_we;
117 :
118 279 : logic [INTPEND_SIZE-1:0] intpend_reg_extended;
119 :
120 106 : logic [pt.PIC_TOTAL_INT_PLUS1-1:0] [INTPRIORITY_BITS-1:0] intpend_w_prior_en;
121 304 : logic [pt.PIC_TOTAL_INT_PLUS1-1:0] [ID_BITS-1:0] intpend_id;
122 325 : logic [INTPRIORITY_BITS-1:0] maxint;
123 713 : logic [INTPRIORITY_BITS-1:0] selected_int_priority;
124 132 : logic [INT_GRPS-1:0] [31:0] intpend_rd_part_out ;
125 :
126 21 : logic config_reg;
127 21 : logic intpriord;
128 104 : logic config_reg_we ;
129 100 : logic config_reg_re ;
130 556657 : logic config_reg_in ;
131 3102 : logic intpriority_reg_read ;
132 3100 : logic intenable_reg_read ;
133 3100 : logic gw_config_reg_read ;
134 42902 : logic picm_wren_ff , picm_rden_ff ;
135 1694254 : logic [31:0] picm_raddr_ff;
136 1710004 : logic [31:0] picm_waddr_ff;
137 712123 : logic [31:0] picm_wr_data_ff;
138 19247 : logic [3:0] mask;
139 10 : logic picm_mken_ff;
140 834 : logic [ID_BITS-1:0] claimid_in ;
141 713 : logic [INTPRIORITY_BITS-1:0] pl_in ;
142 734 : logic [INTPRIORITY_BITS-1:0] pl_in_q ;
143 :
144 : //logic [pt.PIC_TOTAL_INT_PLUS1-1:0] extintsrc_req_sync;
145 279 : logic [pt.PIC_TOTAL_INT_PLUS1-1:0] extintsrc_req_gw;
146 0 : logic picm_bypass_ff;
147 :
148 : // clkens
149 9616 : logic pic_raddr_c1_clken;
150 0 : logic pic_waddr_c1_clken;
151 42904 : logic pic_data_c1_clken;
152 12408 : logic pic_pri_c1_clken;
153 18606 : logic pic_int_c1_clken;
154 18606 : logic gw_config_c1_clken;
155 :
156 : // clocks
157 67238537 : logic pic_raddr_c1_clk;
158 67271829 : logic pic_data_c1_clk;
159 67241337 : logic pic_pri_c1_clk;
160 67247537 : logic pic_int_c1_clk;
161 67247537 : logic gw_config_c1_clk;
162 :
163 : // ---- Clock gating section ------
164 : // c1 clock enables
165 : assign pic_raddr_c1_clken = picm_mken | picm_rden | clk_override;
166 : assign pic_data_c1_clken = picm_wren | clk_override;
167 : assign pic_pri_c1_clken = (waddr_intpriority_base_match & picm_wren_ff) | (raddr_intpriority_base_match & picm_rden_ff) | clk_override;
168 : assign pic_int_c1_clken = (waddr_intenable_base_match & picm_wren_ff) | (raddr_intenable_base_match & picm_rden_ff) | clk_override;
169 : assign gw_config_c1_clken = (waddr_config_gw_base_match & picm_wren_ff) | (raddr_config_gw_base_match & picm_rden_ff) | clk_override;
170 :
171 : // C1 - 1 clock pulse for data
172 : rvoclkhdr pic_addr_c1_cgc ( .en(pic_raddr_c1_clken), .l1clk(pic_raddr_c1_clk), .* );
173 : rvoclkhdr pic_data_c1_cgc ( .en(pic_data_c1_clken), .l1clk(pic_data_c1_clk), .* );
174 : rvoclkhdr pic_pri_c1_cgc ( .en(pic_pri_c1_clken), .l1clk(pic_pri_c1_clk), .* );
175 : rvoclkhdr pic_int_c1_cgc ( .en(pic_int_c1_clken), .l1clk(pic_int_c1_clk), .* );
176 : rvoclkhdr gw_config_c1_cgc ( .en(gw_config_c1_clken), .l1clk(gw_config_c1_clk), .* );
177 :
178 : // ------ end clock gating section ------------------------
179 :
180 : assign raddr_intenable_base_match = (picm_raddr_ff[31:NUM_LEVELS+2] == INTENABLE_BASE_ADDR[31:NUM_LEVELS+2]) ;
181 : assign raddr_intpriority_base_match = (picm_raddr_ff[31:NUM_LEVELS+2] == INTPRIORITY_BASE_ADDR[31:NUM_LEVELS+2]) ;
182 : assign raddr_config_gw_base_match = (picm_raddr_ff[31:NUM_LEVELS+2] == EXT_INTR_GW_CONFIG[31:NUM_LEVELS+2]) ;
183 : assign raddr_config_pic_match = (picm_raddr_ff[31:0] == EXT_INTR_PIC_CONFIG[31:0]) ;
184 :
185 : assign addr_intpend_base_match = (picm_raddr_ff[31:6] == INTPEND_BASE_ADDR[31:6]) ;
186 :
187 : assign waddr_config_pic_match = (picm_waddr_ff[31:0] == EXT_INTR_PIC_CONFIG[31:0]) ;
188 : assign addr_clear_gw_base_match = (picm_waddr_ff[31:NUM_LEVELS+2] == EXT_INTR_GW_CLEAR[31:NUM_LEVELS+2]) ;
189 : assign waddr_intpriority_base_match = (picm_waddr_ff[31:NUM_LEVELS+2] == INTPRIORITY_BASE_ADDR[31:NUM_LEVELS+2]) ;
190 : assign waddr_intenable_base_match = (picm_waddr_ff[31:NUM_LEVELS+2] == INTENABLE_BASE_ADDR[31:NUM_LEVELS+2]) ;
191 : assign waddr_config_gw_base_match = (picm_waddr_ff[31:NUM_LEVELS+2] == EXT_INTR_GW_CONFIG[31:NUM_LEVELS+2]) ;
192 :
193 : assign picm_bypass_ff = picm_rden_ff & picm_wren_ff & ( picm_raddr_ff[31:0] == picm_waddr_ff[31:0] ); // pic writes and reads to same address together
194 :
195 :
196 : rvdff #(32) picm_radd_flop (.*, .din (picm_rdaddr), .dout(picm_raddr_ff), .clk(pic_raddr_c1_clk));
197 : rvdff #(32) picm_wadd_flop (.*, .din (picm_wraddr), .dout(picm_waddr_ff), .clk(pic_data_c1_clk));
198 : rvdff #(1) picm_wre_flop (.*, .din (picm_wren), .dout(picm_wren_ff), .clk(free_clk));
199 : rvdff #(1) picm_rde_flop (.*, .din (picm_rden), .dout(picm_rden_ff), .clk(free_clk));
200 : rvdff #(1) picm_mke_flop (.*, .din (picm_mken), .dout(picm_mken_ff), .clk(free_clk));
201 : rvdff #(32) picm_dat_flop (.*, .din (picm_wr_data[31:0]), .dout(picm_wr_data_ff[31:0]), .clk(pic_data_c1_clk));
202 :
203 : //rvsyncss #(pt.PIC_TOTAL_INT_PLUS1-1) sync_inst
204 : //(
205 : // .clk (free_clk),
206 : // .dout(extintsrc_req_sync[pt.PIC_TOTAL_INT_PLUS1-1:1]),
207 : // .din (extintsrc_req[pt.PIC_TOTAL_INT_PLUS1-1:1]),
208 : // .*) ;
209 : //
210 : //assign extintsrc_req_sync[0] = extintsrc_req[0];
211 : /*
212 : genvar p ;
213 : for (p=0; p<=INT_ENABLE_GRPS ; p++) begin : IO_CLK_GRP
214 : if (p==INT_ENABLE_GRPS) begin : LAST_GRP
215 : assign intenable_clk_enable_grp[p] = |intenable_clk_enable[pt.PIC_TOTAL_INT_PLUS1-1 : p*4] | io_clk_override;
216 : rvoclkhdr intenable_c1_cgc ( .en(intenable_clk_enable_grp[p]), .l1clk(gw_clk[p]), .* );
217 : end else begin : CLK_GRPS
218 : assign intenable_clk_enable_grp[p] = |intenable_clk_enable[p*4+3 : p*4] | io_clk_override;
219 : rvoclkhdr intenable_c1_cgc ( .en(intenable_clk_enable_grp[p]), .l1clk(gw_clk[p]), .* );
220 : end
221 : end
222 : */
223 :
224 :
225 :
226 : genvar i ;
227 : genvar p ;
228 : for (p=0; p<=INT_ENABLE_GRPS ; p++) begin : IO_CLK_GRP
229 : wire grp_clk, grp_clken;
230 :
231 : assign grp_clken = |intenable_clk_enable[(p==INT_ENABLE_GRPS?pt.PIC_TOTAL_INT_PLUS1-1:p*4+3) : p*4] | io_clk_override;
232 :
233 : `ifndef RV_FPGA_OPTIMIZE
234 : rvclkhdr intenable_c1_cgc( .en(grp_clken), .l1clk(grp_clk), .* );
235 : `else
236 : /*pragma coverage off*/
237 : assign gw_clk[p] = 1'b0 ;
238 : /*pragma coverage on*/
239 : `endif
240 :
241 : for(genvar i= (p==0 ? 1: 0); i< (p==INT_ENABLE_GRPS ? pt.PIC_TOTAL_INT_PLUS1-p*4 :4); i++) begin : GW
242 : el2_configurable_gw gw_inst(
243 : .*,
244 : .gw_clk(grp_clk),
245 : .rawclk(clk),
246 : .clken (grp_clken),
247 : .extintsrc_req(extintsrc_req[i+p*4]) ,
248 : .meigwctrl_polarity(gw_config_reg[i+p*4][0]) ,
249 : .meigwctrl_type(gw_config_reg[i+p*4][1]) ,
250 : .meigwclr(gw_clear_reg_we[i+p*4]) ,
251 : .extintsrc_req_config(extintsrc_req_gw[i+p*4])
252 : );
253 : end
254 : end
255 :
256 :
257 :
258 :
259 :
260 :
261 :
262 :
263 : for (i=0; i<pt.PIC_TOTAL_INT_PLUS1 ; i++) begin : SETREG
264 :
265 : if (i > 0 ) begin : NON_ZERO_INT
266 : assign intpriority_reg_we[i] = waddr_intpriority_base_match & (picm_waddr_ff[NUM_LEVELS+1:2] == i) & picm_wren_ff;
267 : assign intpriority_reg_re[i] = raddr_intpriority_base_match & (picm_raddr_ff[NUM_LEVELS+1:2] == i) & picm_rden_ff;
268 :
269 : assign intenable_reg_we[i] = waddr_intenable_base_match & (picm_waddr_ff[NUM_LEVELS+1:2] == i) & picm_wren_ff;
270 : assign intenable_reg_re[i] = raddr_intenable_base_match & (picm_raddr_ff[NUM_LEVELS+1:2] == i) & picm_rden_ff;
271 :
272 : assign gw_config_reg_we[i] = waddr_config_gw_base_match & (picm_waddr_ff[NUM_LEVELS+1:2] == i) & picm_wren_ff;
273 : assign gw_config_reg_re[i] = raddr_config_gw_base_match & (picm_raddr_ff[NUM_LEVELS+1:2] == i) & picm_rden_ff;
274 :
275 : assign gw_clear_reg_we[i] = addr_clear_gw_base_match & (picm_waddr_ff[NUM_LEVELS+1:2] == i) & picm_wren_ff ;
276 :
277 : rvdffs #(INTPRIORITY_BITS) intpriority_ff (.*, .en( intpriority_reg_we[i]), .din (picm_wr_data_ff[INTPRIORITY_BITS-1:0]), .dout(intpriority_reg[i]), .clk(pic_pri_c1_clk));
278 : rvdffs #(1) intenable_ff (.*, .en( intenable_reg_we[i]), .din (picm_wr_data_ff[0]), .dout(intenable_reg[i]), .clk(pic_int_c1_clk));
279 : rvdffs #(2) gw_config_ff (.*, .en( gw_config_reg_we[i]), .din (picm_wr_data_ff[1:0]), .dout(gw_config_reg[i]), .clk(gw_config_c1_clk));
280 :
281 : assign intenable_clk_enable[i] = gw_config_reg[i][1] | intenable_reg_we[i] | intenable_reg[i] | gw_clear_reg_we[i] ;
282 :
283 : /*
284 : rvsyncss_fpga #(1) sync_inst
285 : (
286 : .gw_clk (gw_clk[i/4]),
287 : .rawclk (clk),
288 : .clken (intenable_clk_enable_grp[i/4]),
289 : .dout (extintsrc_req_sync[i]),
290 : .din (extintsrc_req[i]),
291 : .*) ;
292 :
293 :
294 :
295 :
296 :
297 : el2_configurable_gw config_gw_inst(.*,
298 : .gw_clk(gw_clk[i/4]),
299 : .rawclk(clk),
300 : .clken (intenable_clk_enable_grp[i/4]),
301 : .extintsrc_req_sync(extintsrc_req_sync[i]) ,
302 : .meigwctrl_polarity(gw_config_reg[i][0]) ,
303 : .meigwctrl_type(gw_config_reg[i][1]) ,
304 : .meigwclr(gw_clear_reg_we[i]) ,
305 : .extintsrc_req_config(extintsrc_req_gw[i])
306 : );
307 : */
308 :
309 : end else begin : INT_ZERO
310 : assign intpriority_reg_we[i] = 1'b0 ;
311 : assign intpriority_reg_re[i] = 1'b0 ;
312 : assign intenable_reg_we[i] = 1'b0 ;
313 : assign intenable_reg_re[i] = 1'b0 ;
314 :
315 : assign gw_config_reg_we[i] = 1'b0 ;
316 : assign gw_config_reg_re[i] = 1'b0 ;
317 : assign gw_clear_reg_we[i] = 1'b0 ;
318 :
319 : assign gw_config_reg[i] = '0 ;
320 :
321 : assign intpriority_reg[i] = {INTPRIORITY_BITS{1'b0}} ;
322 : assign intenable_reg[i] = 1'b0 ;
323 : assign extintsrc_req_gw[i] = 1'b0 ;
324 : // assign extintsrc_req_sync[i] = 1'b0 ;
325 : assign intenable_clk_enable[i] = 1'b0;
326 : end
327 :
328 :
329 873824832 : assign intpriority_reg_inv[i] = intpriord ? ~intpriority_reg[i] : intpriority_reg[i] ;
330 :
331 : assign intpend_w_prior_en[i] = {INTPRIORITY_BITS{(extintsrc_req_gw[i] & intenable_reg[i])}} & intpriority_reg_inv[i] ;
332 : assign intpend_id[i] = i ;
333 : end
334 :
335 :
336 : assign pl_in[INTPRIORITY_BITS-1:0] = selected_int_priority[INTPRIORITY_BITS-1:0] ;
337 :
338 : //if (pt.PIC_2CYCLE == 1) begin : genblock
339 : //end
340 : //else begin : genblock
341 : //end
342 :
343 : genvar l, m , j, k;
344 :
345 : if (pt.PIC_2CYCLE == 1) begin : genblock
346 : logic [NUM_LEVELS/2:0] [pt.PIC_TOTAL_INT_PLUS1+2:0] [INTPRIORITY_BITS-1:0] level_intpend_w_prior_en;
347 : logic [NUM_LEVELS/2:0] [pt.PIC_TOTAL_INT_PLUS1+2:0] [ID_BITS-1:0] level_intpend_id;
348 : logic [NUM_LEVELS:NUM_LEVELS/2] [(pt.PIC_TOTAL_INT_PLUS1/2**(NUM_LEVELS/2))+1:0] [INTPRIORITY_BITS-1:0] levelx_intpend_w_prior_en;
349 : logic [NUM_LEVELS:NUM_LEVELS/2] [(pt.PIC_TOTAL_INT_PLUS1/2**(NUM_LEVELS/2))+1:0] [ID_BITS-1:0] levelx_intpend_id;
350 :
351 : assign level_intpend_w_prior_en[0][pt.PIC_TOTAL_INT_PLUS1+2:0] = {4'b0,4'b0,4'b0,intpend_w_prior_en[pt.PIC_TOTAL_INT_PLUS1-1:0]} ;
352 : assign level_intpend_id[0][pt.PIC_TOTAL_INT_PLUS1+2:0] = {8'b0,8'b0,8'b0,intpend_id[pt.PIC_TOTAL_INT_PLUS1-1:0]} ;
353 :
354 : logic [(pt.PIC_TOTAL_INT_PLUS1/2**(NUM_LEVELS/2)):0] [INTPRIORITY_BITS-1:0] l2_intpend_w_prior_en_ff;
355 : logic [(pt.PIC_TOTAL_INT_PLUS1/2**(NUM_LEVELS/2)):0] [ID_BITS-1:0] l2_intpend_id_ff;
356 :
357 : assign levelx_intpend_w_prior_en[NUM_LEVELS/2][(pt.PIC_TOTAL_INT_PLUS1/2**(NUM_LEVELS/2))+1:0] = {{1*INTPRIORITY_BITS{1'b0}},l2_intpend_w_prior_en_ff[(pt.PIC_TOTAL_INT_PLUS1/2**(NUM_LEVELS/2)):0]} ;
358 : assign levelx_intpend_id[NUM_LEVELS/2][(pt.PIC_TOTAL_INT_PLUS1/2**(NUM_LEVELS/2))+1:0] = {{1*ID_BITS{1'b1}},l2_intpend_id_ff[(pt.PIC_TOTAL_INT_PLUS1/2**(NUM_LEVELS/2)):0]} ;
359 : /// Do the prioritization of the interrupts here ////////////
360 : for (l=0; l<NUM_LEVELS/2 ; l++) begin : TOP_LEVEL
361 : for (m=0; m<=(pt.PIC_TOTAL_INT_PLUS1)/(2**(l+1)) ; m++) begin : COMPARE
362 : if ( m == (pt.PIC_TOTAL_INT_PLUS1)/(2**(l+1))) begin
363 : assign level_intpend_w_prior_en[l+1][m+1] = '0 ;
364 : assign level_intpend_id[l+1][m+1] = '0 ;
365 : end
366 : el2_cmp_and_mux #(.ID_BITS(ID_BITS),
367 : .INTPRIORITY_BITS(INTPRIORITY_BITS)) cmp_l1 (
368 : .a_id(level_intpend_id[l][2*m]),
369 : .a_priority(level_intpend_w_prior_en[l][2*m]),
370 : .b_id(level_intpend_id[l][2*m+1]),
371 : .b_priority(level_intpend_w_prior_en[l][2*m+1]),
372 : .out_id(level_intpend_id[l+1][m]),
373 : .out_priority(level_intpend_w_prior_en[l+1][m])) ;
374 :
375 : end
376 : end
377 :
378 : for (i=0; i<=pt.PIC_TOTAL_INT_PLUS1/2**(NUM_LEVELS/2) ; i++) begin : MIDDLE_FLOPS
379 : rvdff #(INTPRIORITY_BITS) level2_intpend_prior_reg (.*, .din (level_intpend_w_prior_en[NUM_LEVELS/2][i]), .dout(l2_intpend_w_prior_en_ff[i]), .clk(free_clk));
380 : rvdff #(ID_BITS) level2_intpend_id_reg (.*, .din (level_intpend_id[NUM_LEVELS/2][i]), .dout(l2_intpend_id_ff[i]), .clk(free_clk));
381 : end
382 :
383 : for (j=NUM_LEVELS/2; j<NUM_LEVELS ; j++) begin : BOT_LEVELS
384 : for (k=0; k<=(pt.PIC_TOTAL_INT_PLUS1)/(2**(j+1)) ; k++) begin : COMPARE
385 : if ( k == (pt.PIC_TOTAL_INT_PLUS1)/(2**(j+1))) begin
386 : assign levelx_intpend_w_prior_en[j+1][k+1] = '0 ;
387 : assign levelx_intpend_id[j+1][k+1] = '0 ;
388 : end
389 : el2_cmp_and_mux #(.ID_BITS(ID_BITS),
390 : .INTPRIORITY_BITS(INTPRIORITY_BITS))
391 : cmp_l1 (
392 : .a_id(levelx_intpend_id[j][2*k]),
393 : .a_priority(levelx_intpend_w_prior_en[j][2*k]),
394 : .b_id(levelx_intpend_id[j][2*k+1]),
395 : .b_priority(levelx_intpend_w_prior_en[j][2*k+1]),
396 : .out_id(levelx_intpend_id[j+1][k]),
397 : .out_priority(levelx_intpend_w_prior_en[j+1][k])) ;
398 : end
399 : end
400 : assign claimid_in[ID_BITS-1:0] = levelx_intpend_id[NUM_LEVELS][0] ; // This is the last level output
401 : assign selected_int_priority[INTPRIORITY_BITS-1:0] = levelx_intpend_w_prior_en[NUM_LEVELS][0] ;
402 : end
403 : else begin : genblock
404 :
405 : logic [NUM_LEVELS:0] [pt.PIC_TOTAL_INT_PLUS1+1:0] [INTPRIORITY_BITS-1:0] level_intpend_w_prior_en;
406 : logic [NUM_LEVELS:0] [pt.PIC_TOTAL_INT_PLUS1+1:0] [ID_BITS-1:0] level_intpend_id;
407 :
408 : assign level_intpend_w_prior_en[0][pt.PIC_TOTAL_INT_PLUS1+1:0] = {{2*INTPRIORITY_BITS{1'b0}},intpend_w_prior_en[pt.PIC_TOTAL_INT_PLUS1-1:0]} ;
409 : assign level_intpend_id[0][pt.PIC_TOTAL_INT_PLUS1+1:0] = {{2*ID_BITS{1'b1}},intpend_id[pt.PIC_TOTAL_INT_PLUS1-1:0]} ;
410 :
411 : /// Do the prioritization of the interrupts here ////////////
412 : // genvar l, m , j, k; already declared outside ifdef
413 : for (l=0; l<NUM_LEVELS ; l++) begin : LEVEL
414 : for (m=0; m<=(pt.PIC_TOTAL_INT_PLUS1)/(2**(l+1)) ; m++) begin : COMPARE
415 : if ( m == (pt.PIC_TOTAL_INT_PLUS1)/(2**(l+1))) begin
416 : assign level_intpend_w_prior_en[l+1][m+1] = '0 ;
417 : assign level_intpend_id[l+1][m+1] = '0 ;
418 : end
419 : el2_cmp_and_mux #(.ID_BITS(ID_BITS),
420 : .INTPRIORITY_BITS(INTPRIORITY_BITS)) cmp_l1 (
421 : .a_id(level_intpend_id[l][2*m]),
422 : .a_priority(level_intpend_w_prior_en[l][2*m]),
423 : .b_id(level_intpend_id[l][2*m+1]),
424 : .b_priority(level_intpend_w_prior_en[l][2*m+1]),
425 : .out_id(level_intpend_id[l+1][m]),
426 : .out_priority(level_intpend_w_prior_en[l+1][m])) ;
427 :
428 : end
429 : end
430 : assign claimid_in[ID_BITS-1:0] = level_intpend_id[NUM_LEVELS][0] ; // This is the last level output
431 : assign selected_int_priority[INTPRIORITY_BITS-1:0] = level_intpend_w_prior_en[NUM_LEVELS][0] ;
432 :
433 : end
434 :
435 :
436 :
437 : ///////////////////////////////////////////////////////////////////////
438 : // Config Reg`
439 : ///////////////////////////////////////////////////////////////////////
440 : assign config_reg_we = waddr_config_pic_match & picm_wren_ff;
441 : assign config_reg_re = raddr_config_pic_match & picm_rden_ff;
442 :
443 : assign config_reg_in = picm_wr_data_ff[0] ; //
444 : rvdffs #(1) config_reg_ff (.*, .clk(free_clk), .en(config_reg_we), .din (config_reg_in), .dout(config_reg));
445 :
446 : assign intpriord = config_reg ;
447 :
448 :
449 :
450 : //////////////////////////////////////////////////////////////////////////
451 : // Send the interrupt to the core if it is above the thresh-hold
452 : //////////////////////////////////////////////////////////////////////////
453 : ///////////////////////////////////////////////////////////
454 : /// ClaimId Reg and Corresponding PL
455 : ///////////////////////////////////////////////////////////
456 : //
457 27307026 : assign pl_in_q[INTPRIORITY_BITS-1:0] = intpriord ? ~pl_in : pl_in ;
458 : rvdff #(ID_BITS) claimid_ff (.*, .din (claimid_in[ID_BITS-1:00]), .dout(claimid[ID_BITS-1:00]), .clk(free_clk));
459 : rvdff #(INTPRIORITY_BITS) pl_ff (.*, .din (pl_in_q[INTPRIORITY_BITS-1:0]), .dout(pl[INTPRIORITY_BITS-1:0]), .clk(free_clk));
460 :
461 1237 : logic [INTPRIORITY_BITS-1:0] meipt_inv , meicurpl_inv ;
462 27307026 : assign meipt_inv[INTPRIORITY_BITS-1:0] = intpriord ? ~meipt[INTPRIORITY_BITS-1:0] : meipt[INTPRIORITY_BITS-1:0] ;
463 27307026 : assign meicurpl_inv[INTPRIORITY_BITS-1:0] = intpriord ? ~meicurpl[INTPRIORITY_BITS-1:0] : meicurpl[INTPRIORITY_BITS-1:0] ;
464 : assign mexintpend_in = (( selected_int_priority[INTPRIORITY_BITS-1:0] > meipt_inv[INTPRIORITY_BITS-1:0]) &
465 : ( selected_int_priority[INTPRIORITY_BITS-1:0] > meicurpl_inv[INTPRIORITY_BITS-1:0]) );
466 : rvdff #(1) mexintpend_ff (.*, .clk(free_clk), .din (mexintpend_in), .dout(mexintpend));
467 :
468 27307026 : assign maxint[INTPRIORITY_BITS-1:0] = intpriord ? 0 : 15 ;
469 : assign mhwakeup_in = ( pl_in_q[INTPRIORITY_BITS-1:0] == maxint) ;
470 : rvdff #(1) wake_up_ff (.*, .clk(free_clk), .din (mhwakeup_in), .dout(mhwakeup));
471 :
472 :
473 :
474 :
475 :
476 : //////////////////////////////////////////////////////////////////////////
477 : // Reads of register.
478 : // 1- intpending
479 : //////////////////////////////////////////////////////////////////////////
480 :
481 : assign intpend_reg_read = addr_intpend_base_match & picm_rden_ff ;
482 : assign intpriority_reg_read = raddr_intpriority_base_match & picm_rden_ff;
483 : assign intenable_reg_read = raddr_intenable_base_match & picm_rden_ff;
484 : assign gw_config_reg_read = raddr_config_gw_base_match & picm_rden_ff;
485 :
486 : assign intpend_reg_extended[INTPEND_SIZE-1:0] = {{INTPEND_SIZE-pt.PIC_TOTAL_INT_PLUS1{1'b0}},extintsrc_req_gw[pt.PIC_TOTAL_INT_PLUS1-1:0]} ;
487 :
488 : for (i=0; i<(INT_GRPS); i++) begin
489 : assign intpend_rd_part_out[i] = (({32{intpend_reg_read & picm_raddr_ff[5:2] == i}}) & intpend_reg_extended[((32*i)+31):(32*i)]) ;
490 : end
491 :
492 304 : always_comb begin : INTPEND_RD
493 304 : intpend_rd_out = '0 ;
494 304 : for (int i=0; i<INT_GRPS; i++) begin
495 304 : intpend_rd_out |= intpend_rd_part_out[i] ;
496 : end
497 : end
498 :
499 27354860 : always_comb begin : INTEN_RD
500 27354860 : intenable_rd_out = '0 ;
501 27354860 : intpriority_rd_out = '0 ;
502 27354860 : gw_config_rd_out = '0 ;
503 875355520 : for (int i=0; i<pt.PIC_TOTAL_INT_PLUS1; i++) begin
504 875346220 : if (intenable_reg_re[i]) begin
505 9300 : intenable_rd_out = intenable_reg[i] ;
506 : end
507 875346220 : if (intpriority_reg_re[i]) begin
508 9300 : intpriority_rd_out = intpriority_reg[i] ;
509 : end
510 875346220 : if (gw_config_reg_re[i]) begin
511 9300 : gw_config_rd_out = gw_config_reg[i] ;
512 : end
513 : end
514 : end
515 :
516 :
517 : assign picm_rd_data_in[31:0] = ({32{intpend_reg_read }} & intpend_rd_out ) |
518 : ({32{intpriority_reg_read }} & {{32-INTPRIORITY_BITS{1'b0}}, intpriority_rd_out } ) |
519 : ({32{intenable_reg_read }} & {31'b0 , intenable_rd_out } ) |
520 : ({32{gw_config_reg_read }} & {30'b0 , gw_config_rd_out } ) |
521 : ({32{config_reg_re }} & {31'b0 , config_reg } ) |
522 : ({32{picm_mken_ff & mask[3]}} & {30'b0 , 2'b11 } ) |
523 : ({32{picm_mken_ff & mask[2]}} & {31'b0 , 1'b1 } ) |
524 : ({32{picm_mken_ff & mask[1]}} & {28'b0 , 4'b1111 } ) |
525 : ({32{picm_mken_ff & mask[0]}} & 32'b0 ) ;
526 :
527 :
528 27354860 : assign picm_rd_data[31:0] = picm_bypass_ff ? picm_wr_data_ff[31:0] : picm_rd_data_in[31:0] ;
529 :
530 1694236 : logic [14:0] address;
531 :
532 : assign address[14:0] = picm_raddr_ff[14:0];
533 :
534 : `include "pic_map_auto.h"
535 :
536 : endmodule
537 :
538 :
539 : module el2_cmp_and_mux #(parameter ID_BITS=8,
540 : INTPRIORITY_BITS = 4)
541 : (
542 8750 : input logic [ID_BITS-1:0] a_id,
543 3816 : input logic [INTPRIORITY_BITS-1:0] a_priority,
544 :
545 7965 : input logic [ID_BITS-1:0] b_id,
546 3952 : input logic [INTPRIORITY_BITS-1:0] b_priority,
547 :
548 12332 : output logic [ID_BITS-1:0] out_id,
549 6272 : output logic [INTPRIORITY_BITS-1:0] out_priority
550 :
551 : );
552 :
553 6207 : logic a_is_lt_b ;
554 :
555 : assign a_is_lt_b = ( a_priority[INTPRIORITY_BITS-1:0] < b_priority[INTPRIORITY_BITS-1:0] ) ;
556 :
557 983016770 : assign out_id[ID_BITS-1:0] = a_is_lt_b ? b_id[ID_BITS-1:0] :
558 : a_id[ID_BITS-1:0] ;
559 983016770 : assign out_priority[INTPRIORITY_BITS-1:0] = a_is_lt_b ? b_priority[INTPRIORITY_BITS-1:0] :
560 : a_priority[INTPRIORITY_BITS-1:0] ;
561 : endmodule // cmp_and_mux
562 :
563 :
564 : module el2_configurable_gw (
565 3397872 : input logic gw_clk,
566 1671817307 : input logic rawclk,
567 39994 : input logic clken,
568 15664 : input logic rst_l,
569 6615 : input logic extintsrc_req ,
570 748 : input logic meigwctrl_polarity ,
571 7064 : input logic meigwctrl_type ,
572 2500 : input logic meigwclr ,
573 :
574 6290 : output logic extintsrc_req_config
575 : );
576 :
577 :
578 6645 : logic gw_int_pending_in, gw_int_pending, extintsrc_req_sync;
579 :
580 : rvsyncss_fpga #(1) sync_inst (
581 : .dout (extintsrc_req_sync),
582 : .din (extintsrc_req),
583 : .*) ;
584 :
585 :
586 : assign gw_int_pending_in = (extintsrc_req_sync ^ meigwctrl_polarity) | (gw_int_pending & ~meigwclr) ;
587 : rvdff_fpga #(1) int_pend_ff (.*, .clk(gw_clk), .rawclk(rawclk), .clken(clken), .din (gw_int_pending_in), .dout(gw_int_pending));
588 :
589 :
590 844158418 : assign extintsrc_req_config = meigwctrl_type ? ((extintsrc_req_sync ^ meigwctrl_polarity) | gw_int_pending) : (extintsrc_req_sync ^ meigwctrl_polarity) ;
591 :
592 : endmodule // configurable_gw
593 :
594 :
595 :
596 :
597 :
598 :
599 :
600 :
601 :
|