add axi4 lite peripherals
[shakti-peripherals.git] / src / uncore / axi4lite / AXI4_Lite_Fabric.bsv
1 /*
2 Copyright (c) 2013, IIT Madras
3 All rights reserved.
4
5 Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
6
7 * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
8 * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
9 * Neither the name of IIT Madras nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
10
11 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
12 ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
13 */
14 // Copyright (c) 2013-2017 Bluespec, Inc. All Rights Reserved
15
16 package AXI4_Lite_Fabric;
17
18 // ================================================================
19 // This package defines a fabric connecting CPUs, Memories and DMAs
20 // and other IP blocks.
21
22 // ================================================================
23 // Bluespec library imports
24
25 import Vector :: *;
26 import FIFOF :: *;
27 import ConfigReg :: *;
28
29 // ----------------
30 // BSV additional libs
31
32 import Cur_Cycle :: *;
33
34 // ================================================================
35 // Project imports
36
37 import Semi_FIFOF :: *;
38 import AXI4_Lite_Types :: *;
39
40 // ================================================================
41 // The interface for the fabric module
42
43 interface AXI4_Lite_Fabric_IFC #(numeric type num_masters,
44 numeric type num_slaves,
45 numeric type wd_addr,
46 numeric type wd_data,
47 numeric type wd_user);
48 method Action reset;
49 method Action set_verbosity (Bit #(4) verbosity);
50
51 // From masters
52 interface Vector #(num_masters, AXI4_Lite_Slave_IFC #(wd_addr, wd_data, wd_user)) v_from_masters;
53
54 // To slaves
55 interface Vector #(num_slaves, AXI4_Lite_Master_IFC #(wd_addr, wd_data, wd_user)) v_to_slaves;
56 endinterface
57
58 // ================================================================
59 // The Fabric module
60 // The function parameter is an address-decode function, which returns
61 // returns (True, slave-port-num) if address is mapped to slave-port-num
62 // (False, ?) if address is unmapped to any port
63
64 module mkAXI4_Lite_Fabric #(function Tuple2 #(Bool, Bit #(TLog #(num_slaves)))
65 fn_addr_to_slave_num (Bit #(wd_addr) addr))
66 (AXI4_Lite_Fabric_IFC #(num_masters, num_slaves, wd_addr, wd_data, wd_user))
67
68 provisos (Log #(num_masters, log_nm),
69 Log #(num_slaves, log_ns),
70 Log #(TAdd #(num_masters, 1), log_nm_plus_1),
71 Log #(TAdd #(num_slaves, 1), log_ns_plus_1),
72 Add #(_dummy, TLog #(num_slaves), log_ns_plus_1));
73
74 Reg #(Bit #(4)) cfg_verbosity <- mkConfigReg (0);
75
76 // Transactors facing masters
77 Vector #(num_masters, AXI4_Lite_Slave_Xactor_IFC #(wd_addr, wd_data, wd_user))
78 xactors_from_masters <- replicateM (mkAXI4_Lite_Slave_Xactor);
79
80 // Transactors facing slaves
81 Vector #(num_slaves, AXI4_Lite_Master_Xactor_IFC #(wd_addr, wd_data, wd_user))
82 xactors_to_slaves <- replicateM (mkAXI4_Lite_Master_Xactor);
83
84 // FIFOs to keep track of which master originated a transaction, in
85 // order to route corresponding responses back to that master.
86 // Legal masters are 0..(num_masters-1)
87 // The value of 'num_masters' is used for decode errors (no such slave)
88
89 Vector #(num_masters, FIFOF #(Bit #(log_ns_plus_1))) v_f_wr_sjs <- replicateM (mkFIFOF);
90 Vector #(num_masters, FIFOF #(Bit #(wd_user))) v_f_wr_err_user <- replicateM (mkFIFOF);
91 Vector #(num_slaves, FIFOF #(Bit #(log_nm_plus_1))) v_f_wr_mis <- replicateM (mkFIFOF);
92
93 Vector #(num_masters, FIFOF #(Bit #(log_ns_plus_1))) v_f_rd_sjs <- replicateM (mkFIFOF);
94 Vector #(num_masters, FIFOF #(Bit #(wd_user))) v_f_rd_err_user <- replicateM (mkFIFOF);
95 Vector #(num_slaves, FIFOF #(Bit #(log_nm_plus_1))) v_f_rd_mis <- replicateM (mkFIFOF);
96
97 // ----------------------------------------------------------------
98 // BEHAVIOR
99
100 function Bool wr_move_from_mi_to_sj (Integer mi, Integer sj);
101 let addr = xactors_from_masters [mi].o_wr_addr.first.awaddr;
102 match { .legal, .slave_num } = fn_addr_to_slave_num (addr);
103 return (legal && (slave_num == fromInteger (sj)));
104 endfunction
105
106 function Bool wr_illegal_sj (Integer mi);
107 let addr = xactors_from_masters [mi].o_wr_addr.first.awaddr;
108 match { .legal, ._ } = fn_addr_to_slave_num (addr);
109 return (! legal);
110 endfunction
111
112 function Bool rd_move_from_mi_to_sj (Integer mi, Integer sj);
113 let addr = xactors_from_masters [mi].o_rd_addr.first.araddr;
114 match { .legal, .slave_num } = fn_addr_to_slave_num (addr);
115 return (legal && (slave_num == fromInteger (sj)));
116 endfunction
117
118 function Bool rd_illegal_sj (Integer mi);
119 let addr = xactors_from_masters [mi].o_rd_addr.first.araddr;
120 match { .legal, ._ } = fn_addr_to_slave_num (addr);
121 return (! legal);
122 endfunction
123
124 // ----------------
125 // Wr requests from masters to slaves
126
127 // Legal destination slaves
128 for (Integer mi = 0; mi < valueOf (num_masters); mi = mi + 1)
129 for (Integer sj = 0; sj < valueOf (num_slaves); sj = sj + 1)
130
131 rule rl_wr_xaction_master_to_slave (wr_move_from_mi_to_sj (mi, sj));
132 AXI4_Lite_Wr_Addr #(wd_addr, wd_user) a <- pop_o (xactors_from_masters [mi].o_wr_addr);
133 AXI4_Lite_Wr_Data #(wd_data) d <- pop_o (xactors_from_masters [mi].o_wr_data);
134
135 xactors_to_slaves [sj].i_wr_addr.enq (a);
136 xactors_to_slaves [sj].i_wr_data.enq (d);
137
138 v_f_wr_mis [sj].enq (fromInteger (mi));
139 v_f_wr_sjs [mi].enq (fromInteger (sj));
140
141 if (cfg_verbosity > 1) begin
142 $display ("%0d: AXI4_Lite_Fabric: wr master [%0d] -> slave [%0d]", cur_cycle, mi, sj);
143 $display (" ", fshow (a));
144 $display (" ", fshow (d));
145 end
146 endrule
147
148 // Non-existent destination slaves
149 for (Integer mi = 0; mi < valueOf (num_masters); mi = mi + 1)
150 rule rl_wr_xaction_no_such_slave (wr_illegal_sj (mi));
151 AXI4_Lite_Wr_Addr #(wd_addr, wd_user) a <- pop_o (xactors_from_masters [mi].o_wr_addr);
152 AXI4_Lite_Wr_Data #(wd_data) d <- pop_o (xactors_from_masters [mi].o_wr_data);
153
154 v_f_wr_sjs [mi].enq (fromInteger (valueOf (num_slaves)));
155 v_f_wr_err_user [mi].enq (a.awuser);
156
157 if (cfg_verbosity > 1) begin
158 $display ("%0d: AXI4_Lite_Fabric: wr master [%0d] -> illegal addr", cur_cycle, mi);
159 $display (" ", fshow (a));
160 end
161 endrule
162
163 // ----------------
164 // Rd requests from masters to slaves
165
166 // Legal destination slaves
167 for (Integer mi = 0; mi < valueOf (num_masters); mi = mi + 1)
168 for (Integer sj = 0; sj < valueOf (num_slaves); sj = sj + 1)
169
170 rule rl_rd_xaction_master_to_slave (rd_move_from_mi_to_sj (mi, sj));
171 AXI4_Lite_Rd_Addr #(wd_addr, wd_user) a <- pop_o (xactors_from_masters [mi].o_rd_addr);
172
173 xactors_to_slaves [sj].i_rd_addr.enq (a);
174
175 v_f_rd_mis [sj].enq (fromInteger (mi));
176 v_f_rd_sjs [mi].enq (fromInteger (sj));
177
178 if (cfg_verbosity > 1) begin
179 $display ("%0d: AXI4_Lite_Fabric: rd master [%0d] -> slave [%0d]", cur_cycle, mi, sj);
180 $display (" ", fshow (a));
181 end
182 endrule
183
184 // Non-existent destination slaves
185 for (Integer mi = 0; mi < valueOf (num_masters); mi = mi + 1)
186 rule rl_rd_xaction_no_such_slave (rd_illegal_sj (mi));
187 AXI4_Lite_Rd_Addr #(wd_addr, wd_user) a <- pop_o (xactors_from_masters [mi].o_rd_addr);
188
189 v_f_rd_sjs [mi].enq (fromInteger (valueOf (num_slaves)));
190 v_f_rd_err_user [mi].enq (a.aruser);
191
192 if (cfg_verbosity > 1) begin
193 $display ("%0d: AXI4_Lite_Fabric: rd master [%0d] -> illegal addr", cur_cycle, mi);
194 $display (" ", fshow (a));
195 end
196 endrule
197
198 // ----------------
199 // Wr responses from slaves to masters
200
201 for (Integer mi = 0; mi < valueOf (num_masters); mi = mi + 1)
202 for (Integer sj = 0; sj < valueOf (num_slaves); sj = sj + 1)
203
204 rule rl_wr_resp_slave_to_master ( (v_f_wr_mis [sj].first == fromInteger (mi))
205 && (v_f_wr_sjs [mi].first == fromInteger (sj)));
206 v_f_wr_mis [sj].deq;
207 v_f_wr_sjs [mi].deq;
208 AXI4_Lite_Wr_Resp #(wd_user) b <- pop_o (xactors_to_slaves [sj].o_wr_resp);
209
210 xactors_from_masters [mi].i_wr_resp.enq (b);
211
212 if (cfg_verbosity > 1) begin
213 $display ("%0d: AXI4_Lite_Fabric: wr master [%0d] <- slave [%0d]", cur_cycle, mi, sj);
214 $display (" ", fshow (b));
215 end
216 endrule
217
218 // ----------------
219 // Wr error responses to masters
220 // v_f_wr_sjs [mi].first has value num_slaves (illegal value)
221 // v_f_wr_err_user [mi].first contains the request's 'user' data
222
223 for (Integer mi = 0; mi < valueOf (num_masters); mi = mi + 1)
224
225 rule rl_wr_resp_err_to_master (v_f_wr_sjs [mi].first == fromInteger (valueOf (num_slaves)));
226 v_f_wr_sjs [mi].deq;
227 v_f_wr_err_user [mi].deq;
228
229 let b = AXI4_Lite_Wr_Resp {bresp: AXI4_LITE_DECERR, buser: v_f_wr_err_user [mi].first};
230
231 xactors_from_masters [mi].i_wr_resp.enq (b);
232
233 if (cfg_verbosity > 1) begin
234 $display ("%0d: AXI4_Lite_Fabric: wr master [%0d] <- error", cur_cycle, mi);
235 $display (" ", fshow (b));
236 end
237 endrule
238
239 // ----------------
240 // Rd responses from slaves to masters
241
242 for (Integer mi = 0; mi < valueOf (num_masters); mi = mi + 1)
243 for (Integer sj = 0; sj < valueOf (num_slaves); sj = sj + 1)
244
245 rule rl_rd_resp_slave_to_master ( (v_f_rd_mis [sj].first == fromInteger (mi))
246 && (v_f_rd_sjs [mi].first == fromInteger (sj)));
247 v_f_rd_mis [sj].deq;
248 v_f_rd_sjs [mi].deq;
249 AXI4_Lite_Rd_Data #(wd_data, wd_user) r <- pop_o (xactors_to_slaves [sj].o_rd_data);
250
251 xactors_from_masters [mi].i_rd_data.enq (r);
252
253 if (cfg_verbosity > 1) begin
254 $display ("%0d: AXI4_Lite_Fabric: rd master [%0d] <- slave [%0d]", cur_cycle, mi, sj);
255 $display (" ", fshow (r));
256 end
257 endrule
258
259 // ----------------
260 // Rd error responses to masters
261 // v_f_rd_sjs [mi].first has value num_slaves (illegal value)
262 // v_f_rd_err_user [mi].first contains the request's 'user' data
263
264 for (Integer mi = 0; mi < valueOf (num_masters); mi = mi + 1)
265
266 rule rl_rd_resp_err_to_master (v_f_rd_sjs [mi].first == fromInteger (valueOf (num_slaves)));
267 v_f_rd_sjs [mi].deq;
268 v_f_rd_err_user [mi].deq;
269
270 Bit #(wd_data) data = 0;
271 let r = AXI4_Lite_Rd_Data {rresp: AXI4_LITE_DECERR, ruser: v_f_rd_err_user [mi].first, rdata: data};
272
273 xactors_from_masters [mi].i_rd_data.enq (r);
274
275 if (cfg_verbosity > 1) begin
276 $display ("%0d: AXI4_Lite_Fabric: rd master [%0d] <- error", cur_cycle, mi);
277 $display (" ", fshow (r));
278 end
279 endrule
280
281 // ----------------------------------------------------------------
282 // INTERFACE
283
284 function AXI4_Lite_Slave_IFC #(wd_addr, wd_data, wd_user) f1 (Integer j) = xactors_from_masters [j].axi_side;
285 function AXI4_Lite_Master_IFC #(wd_addr, wd_data, wd_user) f2 (Integer j) = xactors_to_slaves [j].axi_side;
286
287 method Action reset;
288 for (Integer mi = 0; mi < valueOf (num_masters); mi = mi + 1) begin
289 xactors_from_masters [mi].reset;
290
291 v_f_wr_sjs [mi].clear;
292 v_f_wr_err_user [mi].clear;
293
294 v_f_rd_sjs [mi].clear;
295 v_f_rd_err_user [mi].clear;
296 end
297
298 for (Integer sj = 0; sj < valueOf (num_slaves); sj = sj + 1) begin
299 xactors_to_slaves [sj].reset;
300 v_f_wr_mis [sj].clear;
301 v_f_rd_mis [sj].clear;
302 end
303 endmethod
304
305 method Action set_verbosity (Bit #(4) verbosity);
306 cfg_verbosity <= verbosity;
307 endmethod
308
309 interface v_from_masters = genWith (f1);
310 interface v_to_slaves = genWith (f2);
311 endmodule
312
313 // ================================================================
314
315 endpackage: AXI4_Lite_Fabric