move all source directories to soc so that "import soc.scoreboard" etc is used
[soc.git] / src / soc / iommu / axi_rab / rab_core.py
1 # // Copyright 2018 ETH Zurich and University of Bologna.
2 # // Copyright and related rights are licensed under the Solderpad Hardware
3 # // License, Version 0.51 (the "License"); you may not use this file except in
4 # // compliance with the License. You may obtain a copy of the License at
5 # // http://solderpad.org/licenses/SHL-0.51. Unless required by applicable law
6 # // or agreed to in writing, software, hardware and materials distributed under
7 # // this License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
8 # // CONDITIONS OF ANY KIND, either express or implied. See the License for the
9 # // specific language governing permissions and limitations under the License.
10
11 # this file has been generated by sv2nmigen
12
13 #
14 # //`include "pulp_soc_defines.sv"
15 #
16 # ////import CfMath::log2;
17 #
18 # //`define MY_ARRAY_SUM(MY_ARRAY,ARRAY_SIZE) ( (ARRAY_SIZE==1) ? MY_ARRAY[0] : (ARRAY_SIZE==2) ? MY_ARRAY[0] + MY_ARRAY[1] : (ARRAY_SIZE==3) ? MY_ARRAY[0] + MY_ARRAY[1] + MY_ARRAY[2] : (ARRAY_SIZE==4) ? MY_ARRAY[0] + MY_ARRAY[1] + MY_ARRAY[2] + MY_ARRAY[3] : 0 )
19 #
20
21 # module rab_core
22 # #(
23 # parameter N_PORTS = 3,
24 # parameter N_L2_SETS = 32,
25 # parameter N_L2_SET_ENTRIES = 32,
26 # parameter AXI_DATA_WIDTH = 64,
27 # parameter AXI_S_ADDR_WIDTH = 32,
28 # parameter AXI_M_ADDR_WIDTH = 40,
29 # parameter AXI_LITE_DATA_WIDTH = 64,
30 # parameter AXI_LITE_ADDR_WIDTH = 32,
31 # parameter AXI_ID_WIDTH = 8,
32 # parameter AXI_USER_WIDTH = 6,
33 # parameter MH_FIFO_DEPTH = 16
34 # )
35 # (
36 # input logic Clk_CI,
37 # input logic Rst_RBI,
38 #
39 # input logic [AXI_LITE_ADDR_WIDTH-1:0] s_axi_awaddr,
40 # input logic s_axi_awvalid,
41 # output logic s_axi_awready,
42 #
43 # input logic [AXI_LITE_DATA_WIDTH-1:0] s_axi_wdata,
44 # input logic [AXI_LITE_DATA_WIDTH/8-1:0] s_axi_wstrb,
45 # input logic s_axi_wvalid,
46 # output logic s_axi_wready,
47 #
48 # input logic [AXI_LITE_ADDR_WIDTH-1:0] s_axi_araddr,
49 # input logic s_axi_arvalid,
50 # output logic s_axi_arready,
51 #
52 # input logic s_axi_rready,
53 # output logic [AXI_LITE_DATA_WIDTH-1:0] s_axi_rdata,
54 # output logic [1:0] s_axi_rresp,
55 # output logic s_axi_rvalid,
56 #
57 # output logic [1:0] s_axi_bresp,
58 # output logic s_axi_bvalid,
59 # input logic s_axi_bready,
60 #
61 # output logic [N_PORTS-1:0] int_miss,
62 # output logic [N_PORTS-1:0] int_prot,
63 # output logic [N_PORTS-1:0] int_multi,
64 # output logic [N_PORTS-1:0] int_prefetch,
65 # output logic int_mhf_full,
66 #
67 # output logic [N_PORTS-1:0] [AXI_S_ADDR_WIDTH-1:0] int_axaddr_o,
68 # output logic [N_PORTS-1:0] [AXI_ID_WIDTH-1:0] int_axid_o,
69 # output logic [N_PORTS-1:0] [7:0] int_axlen_o,
70 # output logic [N_PORTS-1:0] [AXI_USER_WIDTH-1:0] int_axuser_o,
71 #
72 # input logic [N_PORTS-1:0] [AXI_S_ADDR_WIDTH-1:0] port1_addr,
73 # input logic [N_PORTS-1:0] [AXI_ID_WIDTH-1:0] port1_id,
74 # input logic [N_PORTS-1:0] [7:0] port1_len,
75 # input logic [N_PORTS-1:0] [2:0] port1_size,
76 # input logic [N_PORTS-1:0] port1_addr_valid,
77 # input logic [N_PORTS-1:0] port1_type,
78 # input logic [N_PORTS-1:0] [AXI_USER_WIDTH-1:0] port1_user,
79 # input logic [N_PORTS-1:0] port1_sent,
80 # output logic [N_PORTS-1:0] [AXI_M_ADDR_WIDTH-1:0] port1_out_addr,
81 # output logic [N_PORTS-1:0] port1_cache_coherent,
82 # output logic [N_PORTS-1:0] port1_accept,
83 # output logic [N_PORTS-1:0] port1_drop,
84 # output logic [N_PORTS-1:0] port1_miss,
85 #
86 # input logic [N_PORTS-1:0] [AXI_S_ADDR_WIDTH-1:0] port2_addr,
87 # input logic [N_PORTS-1:0] [AXI_ID_WIDTH-1:0] port2_id,
88 # input logic [N_PORTS-1:0] [7:0] port2_len,
89 # input logic [N_PORTS-1:0] [2:0] port2_size,
90 # input logic [N_PORTS-1:0] port2_addr_valid,
91 # input logic [N_PORTS-1:0] port2_type,
92 # input logic [N_PORTS-1:0] [AXI_USER_WIDTH-1:0] port2_user,
93 # input logic [N_PORTS-1:0] port2_sent,
94 # output logic [N_PORTS-1:0] [AXI_M_ADDR_WIDTH-1:0] port2_out_addr,
95 # output logic [N_PORTS-1:0] port2_cache_coherent,
96 # output logic [N_PORTS-1:0] port2_accept,
97 # output logic [N_PORTS-1:0] port2_drop,
98 # output logic [N_PORTS-1:0] port2_miss,
99 #
100 # input logic [N_PORTS-1:0] miss_l2_i,
101 # input logic [N_PORTS-1:0] [AXI_S_ADDR_WIDTH-1:0] miss_l2_addr_i,
102 # input logic [N_PORTS-1:0] [AXI_ID_WIDTH-1:0] miss_l2_id_i,
103 # input logic [N_PORTS-1:0] [AXI_USER_WIDTH-1:0] miss_l2_user_i,
104 #
105 # output logic [N_PORTS-1:0] [AXI_LITE_DATA_WIDTH-1:0] wdata_l2_o,
106 # output logic [N_PORTS-1:0] [AXI_LITE_ADDR_WIDTH-1:0] waddr_l2_o,
107 # output logic [N_PORTS-1:0] wren_l2_o
108 # );
109
110 from nmigen import Signal, Module, Const, Cat, Elaboratable
111
112
113 class rab_core(Elaboratable):
114
115 def __init__(self):
116 self.s_axi_awaddr = Signal(AXI_LITE_ADDR_WIDTH) # input
117 self.s_axi_awvalid = Signal() # input
118 self.s_axi_awready = Signal() # output
119 self.s_axi_wdata = Signal(AXI_LITE_DATA_WIDTH) # input
120 self.s_axi_wstrb = Signal(FIXME) # input
121 self.s_axi_wvalid = Signal() # input
122 self.s_axi_wready = Signal() # output
123 self.s_axi_araddr = Signal(AXI_LITE_ADDR_WIDTH) # input
124 self.s_axi_arvalid = Signal() # input
125 self.s_axi_arready = Signal() # output
126 self.s_axi_rready = Signal() # input
127 self.s_axi_rdata = Signal(AXI_LITE_DATA_WIDTH) # output
128 self.s_axi_rresp = Signal(2) # output
129 self.s_axi_rvalid = Signal() # output
130 self.s_axi_bresp = Signal(2) # output
131 self.s_axi_bvalid = Signal() # output
132 self.s_axi_bready = Signal() # input
133 self.int_miss = Signal(N_PORTS) # output
134 self.int_prot = Signal(N_PORTS) # output
135 self.int_multi = Signal(N_PORTS) # output
136 self.int_prefetch = Signal(N_PORTS) # output
137 self.int_mhf_full = Signal() # output
138 self.int_axaddr_o = Signal() # output
139 self.int_axid_o = Signal() # output
140 self.int_axlen_o = Signal() # output
141 self.int_axuser_o = Signal() # output
142 self.port1_addr = Signal() # input
143 self.port1_id = Signal() # input
144 self.port1_len = Signal() # input
145 self.port1_size = Signal() # input
146 self.port1_addr_valid = Signal(N_PORTS) # input
147 self.port1_type = Signal(N_PORTS) # input
148 self.port1_user = Signal() # input
149 self.port1_sent = Signal(N_PORTS) # input
150 self.port1_out_addr = Signal() # output
151 self.port1_cache_coherent = Signal(N_PORTS) # output
152 self.port1_accept = Signal(N_PORTS) # output
153 self.port1_drop = Signal(N_PORTS) # output
154 self.port1_miss = Signal(N_PORTS) # output
155 self.port2_addr = Signal() # input
156 self.port2_id = Signal() # input
157 self.port2_len = Signal() # input
158 self.port2_size = Signal() # input
159 self.port2_addr_valid = Signal(N_PORTS) # input
160 self.port2_type = Signal(N_PORTS) # input
161 self.port2_user = Signal() # input
162 self.port2_sent = Signal(N_PORTS) # input
163 self.port2_out_addr = Signal() # output
164 self.port2_cache_coherent = Signal(N_PORTS) # output
165 self.port2_accept = Signal(N_PORTS) # output
166 self.port2_drop = Signal(N_PORTS) # output
167 self.port2_miss = Signal(N_PORTS) # output
168 self.miss_l2_i = Signal(N_PORTS) # input
169 self.miss_l2_addr_i = Signal() # input
170 self.miss_l2_id_i = Signal() # input
171 self.miss_l2_user_i = Signal() # input
172 self.wdata_l2_o = Signal() # output
173 self.waddr_l2_o = Signal() # output
174 self.wren_l2_o = Signal(N_PORTS) # output
175
176 def elaborate(self, platform=None):
177 m = Module()
178 return m
179
180
181 """
182
183
184 // ███████╗██╗ ██████╗ ███╗ ██╗ █████╗ ██╗ ███████╗
185 // ██╔════╝██║██╔════╝ ████╗ ██║██╔══██╗██║ ██╔════╝
186 // ███████╗██║██║ ███╗██╔██╗ ██║███████║██║ ███████╗
187 // ╚════██║██║██║ ██║██║╚██╗██║██╔══██║██║ ╚════██║
188 // ███████║██║╚██████╔╝██║ ╚████║██║ ██║███████╗███████║
189 // ╚══════╝╚═╝ ╚═════╝ ╚═╝ ╚═══╝╚═╝ ╚═╝╚══════╝╚══════╝
190 // signals
191
192 localparam integer ENABLE_L2TLB[N_PORTS-1:0] = `EN_L2TLB_ARRAY;
193
194 localparam integer N_SLICES[N_PORTS-1:0] = `N_SLICES_ARRAY;
195 localparam N_SLICES_TOT = `MY_ARRAY_SUM(N_SLICES,N_PORTS);
196 localparam N_SLICES_MAX = `N_SLICES_MAX;
197
198 localparam N_REGS = 4*N_SLICES_TOT + 4;
199 localparam AXI_SIZE_WIDTH = log2(AXI_DATA_WIDTH/8);
200
201 localparam PORT_ID_WIDTH = (N_PORTS < 2) ? 1 : log2(N_PORTS);
202 localparam MISS_META_WIDTH = PORT_ID_WIDTH + AXI_USER_WIDTH + AXI_ID_WIDTH;
203
204 logic [N_PORTS-1:0] [15:0] p1_burst_size;
205 logic [N_PORTS-1:0] [15:0] p2_burst_size;
206
207 logic [N_PORTS-1:0] [AXI_S_ADDR_WIDTH-1:0] p1_align_addr;
208 logic [N_PORTS-1:0] [AXI_S_ADDR_WIDTH-1:0] p2_align_addr;
209
210 logic [N_PORTS-1:0] [AXI_SIZE_WIDTH-1:0] p1_mask;
211 logic [N_PORTS-1:0] [AXI_SIZE_WIDTH-1:0] p2_mask;
212
213 logic [N_PORTS-1:0] [AXI_S_ADDR_WIDTH-1:0] p1_max_addr;
214 logic [N_PORTS-1:0] [AXI_S_ADDR_WIDTH-1:0] p2_max_addr;
215
216 logic [N_PORTS-1:0] p1_prefetch;
217 logic [N_PORTS-1:0] p2_prefetch;
218
219 logic [N_PORTS-1:0] int_rw;
220 logic [N_PORTS-1:0] [AXI_S_ADDR_WIDTH-1:0] int_addr_min;
221 logic [N_PORTS-1:0] [AXI_S_ADDR_WIDTH-1:0] int_addr_max;
222 logic [N_PORTS-1:0] [AXI_ID_WIDTH-1:0] int_id;
223 logic [N_PORTS-1:0] [7:0] int_len;
224 logic [N_PORTS-1:0] [AXI_USER_WIDTH-1:0] int_user;
225
226 logic [N_PORTS-1:0] hit;
227 logic [N_PORTS-1:0] prot;
228 logic [N_PORTS-1:0] prefetch;
229
230 logic [N_PORTS-1:0] no_hit;
231 logic [N_PORTS-1:0] no_prot;
232
233 logic [N_PORTS-1:0] [N_SLICES_MAX-1:0] hit_slices;
234 logic [N_PORTS-1:0] [N_SLICES_MAX-1:0] prot_slices;
235
236 logic [N_PORTS-1:0] [AXI_M_ADDR_WIDTH-1:0] out_addr;
237 logic [N_PORTS-1:0] [AXI_M_ADDR_WIDTH-1:0] out_addr_reg;
238
239 logic [N_PORTS-1:0] cache_coherent;
240 logic [N_PORTS-1:0] cache_coherent_reg;
241
242 logic [N_PORTS-1:0] select;
243 reg [N_PORTS-1:0] curr_priority;
244
245 reg [N_PORTS-1:0] multi_hit;
246
247 logic [N_PORTS-1:0] miss_valid_mhf;
248 logic [N_PORTS-1:0] [AXI_S_ADDR_WIDTH-1:0] miss_addr_mhf;
249 logic [N_PORTS-1:0] [MISS_META_WIDTH-1:0] miss_meta_mhf;
250
251 logic [N_REGS-1:0] [63:0] int_cfg_regs;
252 logic [N_PORTS-1:0] [4*N_SLICES_MAX-1:0] [63:0] int_cfg_regs_slices;
253
254 logic L1AllowMultiHit_S;
255
256 genvar z;
257
258 // █████╗ ███████╗███████╗██╗ ██████╗ ███╗ ██╗███╗ ███╗███████╗███╗ ██╗████████╗███████╗
259 // ██╔══██╗██╔════╝██╔════╝██║██╔════╝ ████╗ ██║████╗ ████║██╔════╝████╗ ██║╚══██╔══╝██╔════╝
260 // ███████║███████╗███████╗██║██║ ███╗██╔██╗ ██║██╔████╔██║█████╗ ██╔██╗ ██║ ██║ ███████╗
261 // ██╔══██║╚════██║╚════██║██║██║ ██║██║╚██╗██║██║╚██╔╝██║██╔══╝ ██║╚██╗██║ ██║ ╚════██║
262 // ██║ ██║███████║███████║██║╚██████╔╝██║ ╚████║██║ ╚═╝ ██║███████╗██║ ╚████║ ██║ ███████║
263 // ╚═╝ ╚═╝╚══════╝╚══════╝╚═╝ ╚═════╝ ╚═╝ ╚═══╝╚═╝ ╚═╝╚══════╝╚═╝ ╚═══╝ ╚═╝ ╚══════╝
264 // assignments
265
266 always_comb
267 begin : PORT_SELECT
268 var integer idx;
269
270 for (idx=0; idx<N_PORTS; idx++) begin
271
272 // select = 1 -> port1 active
273 // select = 0 -> port2 active
274 select[idx] = (curr_priority[idx] & port1_addr_valid[idx]) | ~port2_addr_valid[idx];
275
276 p1_burst_size[idx] = (port1_len[idx] + 1) << port1_size[idx];
277 p2_burst_size[idx] = (port2_len[idx] + 1) << port2_size[idx];
278
279 // align min addr for max addr computation to allow for smart AXI bursts around the 4k boundary
280 if (port1_size[idx] == 3'b001)
281 p1_mask[idx] = 3'b110;
282 else if (port1_size[idx] == 3'b010)
283 p1_mask[idx] = 3'b100;
284 else if (port1_size[idx] == 3'b011)
285 p1_mask[idx] = 3'b000;
286 else
287 p1_mask[idx] = 3'b111;
288
289 p1_align_addr[idx][AXI_S_ADDR_WIDTH-1:AXI_SIZE_WIDTH] = port1_addr[idx][AXI_S_ADDR_WIDTH-1:AXI_SIZE_WIDTH];
290 p1_align_addr[idx][AXI_SIZE_WIDTH-1:0] = port1_addr[idx][AXI_SIZE_WIDTH-1:0] & p1_mask[idx];
291
292 if (port2_size[idx] == 3'b001)
293 p2_mask[idx] = 3'b110;
294 else if (port2_size[idx] == 3'b010)
295 p2_mask[idx] = 3'b100;
296 else if (port2_size[idx] == 3'b011)
297 p2_mask[idx] = 3'b000;
298 else
299 p2_mask[idx] = 3'b111;
300
301 if (port1_user[idx] == {AXI_USER_WIDTH{1'b1}})
302 p1_prefetch[idx] = 1'b1;
303 else
304 p1_prefetch[idx] = 1'b0;
305
306 if (port2_user[idx] == {AXI_USER_WIDTH{1'b1}})
307 p2_prefetch[idx] = 1'b1;
308 else
309 p2_prefetch[idx] = 1'b0;
310
311 p2_align_addr[idx][AXI_S_ADDR_WIDTH-1:AXI_SIZE_WIDTH] = port2_addr[idx][AXI_S_ADDR_WIDTH-1:AXI_SIZE_WIDTH];
312 p2_align_addr[idx][AXI_SIZE_WIDTH-1:0] = port2_addr[idx][AXI_SIZE_WIDTH-1:0] & p2_mask[idx];
313
314 p1_max_addr[idx] = p1_align_addr[idx] + p1_burst_size[idx] - 1;
315 p2_max_addr[idx] = p2_align_addr[idx] + p2_burst_size[idx] - 1;
316
317 int_addr_min[idx] = select[idx] ? port1_addr[idx] : port2_addr[idx];
318 int_addr_max[idx] = select[idx] ? p1_max_addr[idx] : p2_max_addr[idx];
319 int_rw[idx] = select[idx] ? port1_type[idx] : port2_type[idx];
320 int_id[idx] = select[idx] ? port1_id[idx] : port2_id[idx];
321 int_len[idx] = select[idx] ? port1_len[idx] : port2_len[idx];
322 int_user[idx] = select[idx] ? port1_user[idx] : port2_user[idx];
323 prefetch[idx] = select[idx] ? p1_prefetch[idx] : p2_prefetch[idx];
324
325 hit [idx] = | hit_slices [idx];
326 prot[idx] = | prot_slices[idx];
327
328 no_hit [idx] = ~hit [idx];
329 no_prot[idx] = ~prot[idx];
330
331 port1_out_addr[idx] = out_addr_reg[idx];
332 port2_out_addr[idx] = out_addr_reg[idx];
333
334 port1_cache_coherent[idx] = cache_coherent_reg[idx];
335 port2_cache_coherent[idx] = cache_coherent_reg[idx];
336 end
337 end
338
339 always_comb
340 begin
341 var integer idx_port, idx_slice;
342 var integer reg_num;
343 reg_num=0;
344 for ( idx_port = 0; idx_port < N_PORTS; idx_port++ ) begin
345 for ( idx_slice = 0; idx_slice < 4*N_SLICES[idx_port]; idx_slice++ ) begin
346 int_cfg_regs_slices[idx_port][idx_slice] = int_cfg_regs[4+reg_num];
347 reg_num++;
348 end
349 // int_cfg_regs_slices[idx_port][N_SLICES_MAX:N_SLICES[idx_port]] will be dangling
350 // Fix to zero. Synthesis will remove these signals.
351 // int_cfg_regs_slices[idx_port][4*N_SLICES_MAX-1:4*N_SLICES[idx_port]] = 0;
352 end
353 end
354
355 always @(posedge Clk_CI or negedge Rst_RBI)
356 begin : PORT_PRIORITY
357 var integer idx;
358 if (Rst_RBI == 1'b0)
359 curr_priority = 'h0;
360 else begin
361 for (idx=0; idx<N_PORTS; idx++) begin
362 if (port1_accept[idx] || port1_drop[idx])
363 curr_priority[idx] = 1'b1;
364 else if (port2_accept[idx] || port2_drop[idx])
365 curr_priority[idx] = 1'b0;
366 end
367 end
368 end
369
370 // find port that misses
371 logic [PORT_ID_WIDTH-1:0] PortIdx_D; // index of the first missing port
372 var integer idx_miss;
373 always_comb begin : MHF_PORT_SELECT
374 PortIdx_D = 'b0;
375 for (idx_miss = 0; idx_miss < N_PORTS; idx_miss++) begin
376 if (miss_valid_mhf[idx_miss] == 1'b1) begin
377 PortIdx_D = idx_miss;
378 break;
379 end
380 end
381 end // always_comb begin
382
383 // █████╗ ██╗ ██╗██╗ ██████╗ █████╗ ██████╗ ██████╗███████╗ ██████╗
384 // ██╔══██╗╚██╗██╔╝██║ ██╔══██╗██╔══██╗██╔══██╗ ██╔════╝██╔════╝██╔════╝
385 // ███████║ ╚███╔╝ ██║ ██████╔╝███████║██████╔╝ ██║ █████╗ ██║ ███╗
386 // ██╔══██║ ██╔██╗ ██║ ██╔══██╗██╔══██║██╔══██╗ ██║ ██╔══╝ ██║ ██║
387 // ██║ ██║██╔╝ ██╗██║ ██║ ██║██║ ██║██████╔╝ ╚██████╗██║ ╚██████╔╝
388 // ╚═╝ ╚═╝╚═╝ ╚═╝╚═╝ ╚═╝ ╚═╝╚═╝ ╚═╝╚═════╝ ╚═════╝╚═╝ ╚═════╝
389 axi_rab_cfg
390 #(
391 .N_PORTS ( N_PORTS ),
392 .N_REGS ( N_REGS ),
393 .N_L2_SETS ( N_L2_SETS ),
394 .N_L2_SET_ENTRIES( N_L2_SET_ENTRIES ),
395 .ADDR_WIDTH_PHYS ( AXI_M_ADDR_WIDTH ),
396 .ADDR_WIDTH_VIRT ( AXI_S_ADDR_WIDTH ),
397 .N_FLAGS ( 4 ),
398 .AXI_DATA_WIDTH ( AXI_LITE_DATA_WIDTH ),
399 .AXI_ADDR_WIDTH ( AXI_LITE_ADDR_WIDTH ),
400 .MISS_META_WIDTH ( MISS_META_WIDTH ),
401 .MH_FIFO_DEPTH ( MH_FIFO_DEPTH )
402 )
403 u_axi_rab_cfg
404 (
405 .Clk_CI ( Clk_CI ),
406 .Rst_RBI ( Rst_RBI ),
407 .s_axi_awaddr ( s_axi_awaddr ),
408 .s_axi_awvalid ( s_axi_awvalid ),
409 .s_axi_wdata ( s_axi_wdata ),
410 .s_axi_wstrb ( s_axi_wstrb ),
411 .s_axi_wvalid ( s_axi_wvalid ),
412 .s_axi_bready ( s_axi_bready ),
413 .s_axi_araddr ( s_axi_araddr ),
414 .s_axi_arvalid ( s_axi_arvalid ),
415 .s_axi_rready ( s_axi_rready ),
416 .s_axi_arready ( s_axi_arready ),
417 .s_axi_rdata ( s_axi_rdata ),
418 .s_axi_rresp ( s_axi_rresp ),
419 .s_axi_rvalid ( s_axi_rvalid ),
420 .s_axi_wready ( s_axi_wready ),
421 .s_axi_bresp ( s_axi_bresp ),
422 .s_axi_bvalid ( s_axi_bvalid ),
423 .s_axi_awready ( s_axi_awready ),
424 .L1Cfg_DO ( int_cfg_regs ),
425 .L1AllowMultiHit_SO ( L1AllowMultiHit_S ),
426 .MissAddr_DI ( miss_addr_mhf[PortIdx_D] ),
427 .MissMeta_DI ( miss_meta_mhf[PortIdx_D] ),
428 .Miss_SI ( miss_valid_mhf[PortIdx_D] ),
429 .MhFifoFull_SO ( int_mhf_full ),
430 .wdata_l2 ( wdata_l2_o ),
431 .waddr_l2 ( waddr_l2_o ),
432 .wren_l2 ( wren_l2_o )
433 );
434
435 generate for (z = 0; z < N_PORTS; z++) begin : MHF_TLB_SELECT
436 if (ENABLE_L2TLB[z] == 1) begin // L2 TLB is enabled
437 assign miss_valid_mhf[z] = miss_l2_i[z];
438 assign miss_addr_mhf[z] = miss_l2_addr_i[z];
439 assign miss_meta_mhf[z] = {miss_l2_user_i[z], PortIdx_D, miss_l2_id_i[z]};
440 end else begin// L2 TLB is disabled
441 assign miss_valid_mhf[z] = int_miss[z];
442 assign miss_addr_mhf[z] = int_addr_min[z];
443 assign miss_meta_mhf[z] = {int_user[z], PortIdx_D, int_id[z]};
444 end
445 end
446 endgenerate
447
448 // ███████╗██╗ ██╗ ██████╗███████╗ ████████╗ ██████╗ ██████╗
449 // ██╔════╝██║ ██║██╔════╝██╔════╝ ╚══██╔══╝██╔═══██╗██╔══██╗
450 // ███████╗██║ ██║██║ █████╗ ██║ ██║ ██║██████╔╝
451 // ╚════██║██║ ██║██║ ██╔══╝ ██║ ██║ ██║██╔═══╝
452 // ███████║███████╗██║╚██████╗███████╗ ██║ ╚██████╔╝██║
453 // ╚══════╝╚══════╝╚═╝ ╚═════╝╚══════╝ ╚═╝ ╚═════╝ ╚═╝
454 generate for (z = 0; z < N_PORTS; z++) begin : SLICE_TOP_GEN
455 slice_top
456 #(
457 .N_SLICES ( N_SLICES[z] ),
458 .N_REGS ( 4*N_SLICES[z] ),
459 .ADDR_WIDTH_PHYS ( AXI_M_ADDR_WIDTH ),
460 .ADDR_WIDTH_VIRT ( AXI_S_ADDR_WIDTH )
461 )
462 u_slice_top
463 (
464 .int_cfg_regs ( int_cfg_regs_slices[z][4*N_SLICES[z]-1:0] ),
465 .int_rw ( int_rw[z] ),
466 .int_addr_min ( int_addr_min[z] ),
467 .int_addr_max ( int_addr_max[z] ),
468 .multi_hit_allow ( L1AllowMultiHit_S ),
469 .multi_hit ( multi_hit[z] ),
470 .prot ( prot_slices[z][N_SLICES[z]-1:0] ),
471 .hit ( hit_slices [z][N_SLICES[z]-1:0] ),
472 .cache_coherent ( cache_coherent[z] ),
473 .out_addr ( out_addr[z] )
474 );
475 // hit_slices [N_SLICES_MAX-1:N_SLICES_MAX-N_SLICES[z]] will be dangling
476 // prot_slices[N_SLICES_MAX-1:N_SLICES_MAX-N_SLICES[z]] will be dangling
477 // Fix to zero. Synthesis will remove these signals.
478 if ( N_SLICES[z] < N_SLICES_MAX ) begin
479 assign hit_slices [z][N_SLICES_MAX-1:N_SLICES[z]] = 0;
480 assign prot_slices[z][N_SLICES_MAX-1:N_SLICES[z]] = 0;
481 end
482 end // for (z = 0; z < N_PORTS; z++)
483 endgenerate
484
485 // ███████╗███████╗███╗ ███╗
486 // ██╔════╝██╔════╝████╗ ████║
487 // █████╗ ███████╗██╔████╔██║
488 // ██╔══╝ ╚════██║██║╚██╔╝██║
489 // ██║ ███████║██║ ╚═╝ ██║
490 // ╚═╝ ╚══════╝╚═╝ ╚═╝
491 //
492 generate for (z = 0; z < N_PORTS; z++) begin : FSM_GEN
493 fsm
494 #(
495 .AXI_M_ADDR_WIDTH ( AXI_M_ADDR_WIDTH ),
496 .AXI_S_ADDR_WIDTH ( AXI_S_ADDR_WIDTH ),
497 .AXI_ID_WIDTH ( AXI_ID_WIDTH ),
498 .AXI_USER_WIDTH ( AXI_USER_WIDTH )
499 )
500 u_fsm
501 (
502 .Clk_CI ( Clk_CI ),
503 .Rst_RBI ( Rst_RBI ),
504 .port1_addr_valid_i ( port1_addr_valid[z] ),
505 .port2_addr_valid_i ( port2_addr_valid[z] ),
506 .port1_sent_i ( port1_sent[z] ),
507 .port2_sent_i ( port2_sent[z] ),
508 .select_i ( select[z] ),
509 .no_hit_i ( no_hit[z] ),
510 .multi_hit_i ( multi_hit[z] ),
511 .no_prot_i ( no_prot[z] ),
512 .prefetch_i ( prefetch[z] ),
513 .out_addr_i ( out_addr[z] ),
514 .cache_coherent_i ( cache_coherent[z] ),
515 .port1_accept_o ( port1_accept[z] ),
516 .port1_drop_o ( port1_drop[z] ),
517 .port1_miss_o ( port1_miss[z] ),
518 .port2_accept_o ( port2_accept[z] ),
519 .port2_drop_o ( port2_drop[z] ),
520 .port2_miss_o ( port2_miss[z] ),
521 .out_addr_o ( out_addr_reg[z] ),
522 .cache_coherent_o ( cache_coherent_reg[z] ),
523 .miss_o ( int_miss[z] ),
524 .multi_o ( int_multi[z] ),
525 .prot_o ( int_prot[z] ),
526 .prefetch_o ( int_prefetch[z] ),
527 .in_addr_i ( int_addr_min[z] ),
528 .in_id_i ( int_id[z] ),
529 .in_len_i ( int_len[z] ),
530 .in_user_i ( int_user[z] ),
531 .in_addr_o ( int_axaddr_o[z] ),
532 .in_id_o ( int_axid_o[z] ),
533 .in_len_o ( int_axlen_o[z] ),
534 .in_user_o ( int_axuser_o[z] )
535 );
536 end
537 endgenerate
538
539 """