Skip to content

Commit 8f0efe7

Browse files
committed
Create wrapper for PULP cluster
1 parent a5f3758 commit 8f0efe7

2 files changed

Lines changed: 241 additions & 0 deletions

File tree

Bender.yml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,9 @@ sources:
3636
# Level 3
3737
- src/snitch_icache.sv
3838
- src/snitch_read_only_cache.sv
39+
- target: pulp
40+
files:
41+
- src/pulp_icache_wrap.sv
3942
- target: test
4043
files:
4144
- test/snitch_icache_l0_tb.sv

src/pulp_icache_wrap.sv

Lines changed: 238 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,238 @@
1+
// Copyright 2024 ETH Zurich and University of Bologna.
2+
// Solderpad Hardware License, Version 0.51, see LICENSE for details.
3+
// SPDX-License-Identifier: SHL-0.51
4+
5+
// Michael Rogenmoser <michaero@iis.ee.ethz.ch>
6+
7+
`include "common_cells/registers.svh"
8+
9+
/// Porting from hier-icache:
10+
/// Unsupported: different line width, banks in L1, L0 not fully associative
11+
/// [SH_FETCH_DATA_WIDTH == Cache line width]
12+
/// [SH_NB_BANKS == 1]
13+
/// [PRI_NB_WAYS == L0_LINE_COUNT] -> here fully associative
14+
/// [SH_CACHE_LINE == PRI_CACHE_LINE]
15+
/// NumFetchPorts = NB_CORES
16+
/// L0_LINE_COUNT = PRI_CACHE_SIZE/(bytes per line)
17+
/// LINE_WIDTH = X_CACHE_LINE * DATA_WIDTH -> Use >= 32*NB_CORES for optimal performance
18+
/// LINE_COUNT = SH_CACHE_SIZE/(bytes per line)
19+
/// SET_COUNT = SH_NB_WAYS
20+
/// FetchAddrWidth = FETCH_ADDR_WIDTH
21+
/// FetchDataWidth = PRI_FETCH_DATA_WIDTH
22+
/// AxiAddrWidth = AXI_ADDR
23+
/// AxiDataWidth = AXI_DATA
24+
module pulp_icache_wrap #(
25+
/// Number of request (fetch) ports
26+
parameter int NumFetchPorts = -1,
27+
/// L0 Cache Line Count
28+
parameter int L0_LINE_COUNT = -1,
29+
/// Cache Line Width
30+
/// For optimal performance, use >= 32*NumFetchPorts to allow execution of 32-bit instructions
31+
/// for each core before requiring another L0-L1 fetch.
32+
parameter int LINE_WIDTH = -1,
33+
/// The number of cache lines per set. Power of two; >= 2.
34+
parameter int LINE_COUNT = -1,
35+
/// The set associativity of the cache. Power of two; >= 1.
36+
parameter int SET_COUNT = 1,
37+
/// Fetch interface address width. Same as FILL_AW; >= 1.
38+
parameter int FetchAddrWidth = -1,
39+
/// Fetch interface data width. Power of two; >= 8.
40+
parameter int FetchDataWidth = -1,
41+
/// Fill interface address width. Same as FETCH_AW; >= 1.
42+
parameter int AxiAddrWidth = -1,
43+
/// Fill interface data width. Power of two; >= 8.
44+
parameter int AxiDataWidth = -1,
45+
/// Configuration input types for memory cuts used in implementation.
46+
parameter type sram_cfg_data_t = logic,
47+
parameter type sram_cfg_tag_t = logic,
48+
49+
parameter type axi_req_t = logic,
50+
parameter type axi_rsp_t = logic
51+
) (
52+
input logic clk_i,
53+
input logic rst_ni,
54+
55+
// Processor interface
56+
input logic [NumFetchPorts-1:0] fetch_req_i,
57+
input logic [NumFetchPorts-1:0][FetchAddrWidth-1:0] fetch_addr_i,
58+
output logic [NumFetchPorts-1:0] fetch_gnt_o,
59+
output logic [NumFetchPorts-1:0] fetch_rvalid_o,
60+
output logic [NumFetchPorts-1:0][FetchDataWidth-1:0] fetch_rdata_o,
61+
output logic [NumFetchPorts-1:0] fetch_rerror_o,
62+
63+
input logic enable_prefetching_i,
64+
output snitch_icache_pkg::icache_events_t [NumFetchPorts-1:0] icache_events_o,
65+
input logic [NumFetchPorts-1:0] flush_valid_i,
66+
output logic [NumFetchPorts-1:0] flush_ready_o,
67+
68+
// SRAM configs
69+
input sram_cfg_data_t sram_cfg_data_i,
70+
input sram_cfg_tag_t sram_cfg_tag_i,
71+
72+
// AXI interface
73+
output axi_req_t axi_req_o,
74+
input axi_rsp_t axi_rsp_i
75+
);
76+
localparam int unsigned AdapterType = 1;
77+
78+
logic [NumFetchPorts-1:0] fetch_valid, fetch_ready, fetch_rerror;
79+
logic [NumFetchPorts-1:0][FetchAddrWidth-1:0] fetch_addr;
80+
logic [NumFetchPorts-1:0][FetchDataWidth-1:0] fetch_rdata;
81+
82+
for (genvar i = 0; i < NumFetchPorts; i++) begin : gen_adapter
83+
if (AdapterType == 0) begin : gen_response_cut
84+
85+
// Reuquires the core to keep data applied steady while req is high, may not be guaranteed...
86+
spill_register #(
87+
.T (logic [FetchDataWidth-1+1:0]),
88+
.Bypass(1'b0)
89+
) i_spill_reg (
90+
.clk_i,
91+
.rst_ni,
92+
.valid_i ( fetch_ready [i] ),
93+
.ready_o ( /* Unconnected as always ready */ ),
94+
.data_i ( {fetch_rdata [i], fetch_rerror [i]} ),
95+
.valid_o ( fetch_rvalid_o[i] ),
96+
.ready_i ( '1 ),
97+
.data_o ( {fetch_rdata_o[i], fetch_rerror_o[i]} )
98+
);
99+
100+
assign fetch_addr[i] = fetch_addr_i[i];
101+
assign fetch_valid[i] = fetch_req_i[i];
102+
assign fetch_gnt_o[i] = fetch_ready[i];
103+
104+
end else if (AdapterType == 1) begin : gen_request_cut
105+
106+
logic gnt;
107+
108+
assign fetch_gnt_o[i] = gnt & fetch_req_i[i];
109+
110+
spill_register #(
111+
.T (logic [FetchAddrWidth-1:0]),
112+
.Bypass(1'b0)
113+
) i_spill_reg (
114+
.clk_i,
115+
.rst_ni,
116+
.valid_i ( fetch_req_i [i] ),
117+
.ready_o ( gnt ),
118+
.data_i ( fetch_addr_i[i] ),
119+
.valid_o ( fetch_valid [i] ),
120+
.ready_i ( fetch_ready [i] ),
121+
.data_o ( fetch_addr [i] )
122+
);
123+
124+
assign fetch_rdata_o [i] = fetch_rdata [i];
125+
assign fetch_rerror_o[i] = fetch_rerror[i];
126+
assign fetch_rvalid_o[i] = fetch_ready [i] & fetch_valid[i];
127+
128+
end else begin : gen_flexible_cut
129+
// This can still be improved, there is still an extra stall cycle sometimes AFAIK...
130+
131+
logic stalled_d, stalled_q;
132+
133+
logic spill_valid, spill_ready;
134+
logic [FetchAddrWidth-1:0] spill_addr;
135+
136+
spill_register #(
137+
.T (logic [FetchAddrWidth-1:0]),
138+
.Bypass(1'b0)
139+
) i_req_spill_reg (
140+
.clk_i,
141+
.rst_ni,
142+
.valid_i ( fetch_req_i [i] ),
143+
.ready_o ( fetch_gnt_o [i] ),
144+
.data_i ( fetch_addr_i[i] ),
145+
.valid_o ( spill_valid ),
146+
.ready_i ( spill_ready ),
147+
.data_o ( spill_addr )
148+
);
149+
150+
always_comb begin
151+
// Keep steady state
152+
stalled_d = stalled_q;
153+
154+
// If already stalled
155+
if (stalled_q) begin
156+
// only revert back to unstalled state with sufficient gap
157+
if (!spill_valid && !fetch_req_i[i])
158+
stalled_d = 1'b0;
159+
end else begin
160+
if (fetch_req_i[i] && !fetch_ready[i])
161+
stalled_d = 1'b1;
162+
end
163+
end
164+
`FF(stalled_q, stalled_d, '0)
165+
166+
assign fetch_valid[i] = stalled_q ? spill_valid : fetch_req_i[i];
167+
assign fetch_addr [i] = stalled_q ? spill_addr : fetch_addr_i[i];
168+
169+
logic spill_rvalid;
170+
logic spill_rerror;
171+
logic [FetchDataWidth-1:0] spill_rdata;
172+
173+
spill_register #(
174+
.T (logic [FetchDataWidth-1+1:0]),
175+
.Bypass(1'b0)
176+
) i_rsp_spill_reg (
177+
.clk_i,
178+
.rst_ni,
179+
.valid_i ( fetch_ready [i] ),
180+
.ready_o ( /* Unconnected as always ready */ ),
181+
.data_i ( {fetch_rdata[i], fetch_rerror[i]} ),
182+
.valid_o ( spill_rvalid ),
183+
.ready_i ( '1 ),
184+
.data_o ( {spill_rdata , spill_rerror } )
185+
);
186+
187+
assign fetch_rvalid_o[i] = stalled_q ? fetch_ready[i] : spill_rvalid;
188+
assign fetch_rdata_o [i] = stalled_q ? fetch_rdata [i] : spill_rdata;
189+
assign fetch_rerror_o[i] = stalled_q ? fetch_rerror[i] : spill_rerror;
190+
191+
end
192+
end
193+
194+
snitch_icache #(
195+
.NR_FETCH_PORTS ( NumFetchPorts ),
196+
.L0_LINE_COUNT ( L0_LINE_COUNT ),
197+
.LINE_WIDTH ( LINE_WIDTH ),
198+
.LINE_COUNT ( LINE_COUNT ),
199+
.SET_COUNT ( SET_COUNT ),
200+
.FETCH_AW ( FetchAddrWidth ),
201+
.FETCH_DW ( FetchDataWidth ),
202+
.FILL_AW ( AxiAddrWidth ),
203+
.FILL_DW ( AxiDataWidth ),
204+
.FETCH_PRIORITY ( 1 ),
205+
.L1_TAG_SCM ( 1 ),
206+
.SERIAL_LOOKUP ( 1 ),
207+
.NUM_AXI_OUTSTANDING( 4 ),
208+
.EARLY_LATCH ( 0 ),
209+
.ISO_CROSSING ( 0 ),
210+
.sram_cfg_data_t ( sram_cfg_data_t ),
211+
.sram_cfg_tag_t ( sram_cfg_tag_t ),
212+
.axi_req_t ( axi_req_t ),
213+
.axi_rsp_t ( axi_rsp_t )
214+
) i_snitch_icache (
215+
.clk_i,
216+
.clk_d2_i ( clk_i ),
217+
.rst_ni,
218+
219+
.enable_prefetching_i,
220+
.icache_events_o,
221+
.flush_valid_i,
222+
.flush_ready_o,
223+
224+
.inst_addr_i ( fetch_addr ),
225+
.inst_data_o ( fetch_rdata ),
226+
.inst_cacheable_i ( {NumFetchPorts{1'b1}} ),
227+
.inst_valid_i ( fetch_valid ),
228+
.inst_ready_o ( fetch_ready ),
229+
.inst_error_o ( fetch_rerror ),
230+
231+
.sram_cfg_data_i,
232+
.sram_cfg_tag_i,
233+
234+
.axi_req_o,
235+
.axi_rsp_i
236+
);
237+
238+
endmodule

0 commit comments

Comments
 (0)