add first peripheral set
[shakti-peripherals.git] / src / uncore / axi4 / AXI4_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_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_Types :: *;
39
40 // ================================================================
41 // The interface for the fabric module
42
43 interface AXI4_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_Slave_IFC #(wd_addr, wd_data, wd_user)) v_from_masters;
53
54 // To slaves
55 interface Vector #(num_slaves, AXI4_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_Fabric #(function Tuple2 #(Bool, Bit #(TLog #(num_slaves)))
65 fn_addr_to_slave_num (Bit #(wd_addr) addr))
66 (AXI4_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
75 // Transactors facing masters
76 Vector #(num_masters, AXI4_Slave_Xactor_IFC #(wd_addr, wd_data, wd_user))
77 xactors_from_masters <- replicateM (mkAXI4_Slave_Xactor);
78
79 // Transactors facing slaves
80 Vector #(num_slaves, AXI4_Master_Xactor_IFC #(wd_addr, wd_data, wd_user))
81 xactors_to_slaves <- replicateM (mkAXI4_Master_Xactor);
82
83 // FIFOs to keep track of which master originated a transaction, in
84 // order to route corresponding responses back to that master.
85 // Legal masters are 0..(num_masters-1)
86 // The value of 'num_masters' is used for decode errors (no such slave)
87
88 Vector #(num_masters, FIFOF #(Bit #(log_ns_plus_1))) v_f_wr_sjs <- replicateM (mkFIFOF);
89 Vector #(num_masters, FIFOF #(Bit #(wd_user))) v_f_wr_err_user <- replicateM (mkFIFOF);
90 Vector #(num_slaves, FIFOF #(Bit #(log_nm_plus_1))) v_f_wr_mis <- replicateM (mkFIFOF);
91
92 Vector #(num_masters, FIFOF #(Bit #(log_ns_plus_1))) v_f_rd_sjs <- replicateM (mkFIFOF);
93 Vector #(num_masters, FIFOF #(Bit #(wd_user))) v_f_rd_err_user <- replicateM (mkFIFOF);
94 Vector #(num_slaves, FIFOF #(Bit #(log_nm_plus_1))) v_f_rd_mis <- replicateM (mkFIFOF);
95
96 // ----------------------------------------------------------------
97 // BEHAVIOR
98
99 function Bool wr_move_from_mi_to_sj (Integer mi, Integer sj);
100 let addr = xactors_from_masters [mi].o_wr_addr.first.awaddr;
101 match { .legal, .slave_num } = fn_addr_to_slave_num (addr);
102 return (legal && (slave_num == fromInteger (sj)));
103 endfunction
104
105 function Bool wr_illegal_sj (Integer mi);
106 let addr = xactors_from_masters [mi].o_wr_addr.first.awaddr;
107 match { .legal, ._ } = fn_addr_to_slave_num (addr);
108 return (! legal);
109 endfunction
110
111 function Bool rd_move_from_mi_to_sj (Integer mi, Integer sj);
112 let addr = xactors_from_masters [mi].o_rd_addr.first.araddr;
113 match { .legal, .slave_num } = fn_addr_to_slave_num (addr);
114 return (legal && (slave_num == fromInteger (sj)));
115 endfunction
116
117 function Bool rd_illegal_sj (Integer mi);
118 let addr = xactors_from_masters [mi].o_rd_addr.first.araddr;
119 match { .legal, ._ } = fn_addr_to_slave_num (addr);
120 return (! legal);
121 endfunction
122
123 // ----------------
124 // Wr requests from masters to slaves
125
126 // Legal destination slaves
127 for (Integer mi = 0; mi < valueOf (num_masters); mi = mi + 1)
128 for (Integer sj = 0; sj < valueOf (num_slaves); sj = sj + 1)
129
130 rule rl_wr_xaction_master_to_slave (wr_move_from_mi_to_sj (mi, sj));
131 AXI4_Wr_Addr #(wd_addr, wd_user) a <- pop_o (xactors_from_masters [mi].o_wr_addr);
132 AXI4_Wr_Data #(wd_data) d <- pop_o (xactors_from_masters [mi].o_wr_data);
133
134 xactors_to_slaves [sj].i_wr_addr.enq (a);
135 xactors_to_slaves [sj].i_wr_data.enq (d);
136
137 v_f_wr_mis [sj].enq (fromInteger (mi));
138 v_f_wr_sjs [mi].enq (fromInteger (sj));
139
140 `ifdef verbose
141 $display ($time,"\tAXI4_Fabric: wr master [%0d] -> slave [%0d]", mi, sj);
142 $display ($time,"\t ", fshow (a));
143 $display ($time,"\t ", fshow (d));
144 `endif
145 endrule
146
147 for (Integer mi = 0; mi < valueOf (num_masters); mi = mi + 1)
148 for (Integer sj = 0; sj < valueOf (num_slaves); sj = sj + 1)
149
150 rule rl_wr_xaction_master_to_slave_data ((v_f_wr_mis [sj].first == fromInteger (mi))
151 && (v_f_wr_sjs [mi].first == fromInteger (sj)));
152 AXI4_Wr_Data #(wd_data) d <- pop_o (xactors_from_masters [mi].o_wr_data);
153 xactors_to_slaves [sj].i_wr_data.enq(d);
154 `ifdef verbose $display ($time,"\tAXI4_Fabric: Write Data -> slave[%0d] \n",sj,$time,"\t", fshow (d)); `endif
155 endrule
156
157
158 // Non-existent destination slaves
159 for (Integer mi = 0; mi < valueOf (num_masters); mi = mi + 1)
160 rule rl_wr_xaction_no_such_slave (wr_illegal_sj (mi));
161 AXI4_Wr_Addr #(wd_addr, wd_user) a <- pop_o (xactors_from_masters [mi].o_wr_addr);
162 AXI4_Wr_Data #(wd_data) d <- pop_o (xactors_from_masters [mi].o_wr_data);
163
164 v_f_wr_sjs [mi].enq (fromInteger (valueOf (num_slaves)));
165 v_f_wr_err_user [mi].enq (a.awuser);
166 `ifdef verbose
167 $display ($time,"\tAXI4_Fabric: wr master [%0d] -> illegal addr", mi);
168 $display ($time,"\t ", fshow (a));
169 `endif
170 endrule
171
172 // ----------------
173 // Rd requests from masters to slaves
174
175 // Legal destination slaves
176 for (Integer mi = 0; mi < valueOf (num_masters); mi = mi + 1)
177 for (Integer sj = 0; sj < valueOf (num_slaves); sj = sj + 1)
178
179 rule rl_rd_xaction_master_to_slave (rd_move_from_mi_to_sj (mi, sj));
180 AXI4_Rd_Addr #(wd_addr, wd_user) a <- pop_o (xactors_from_masters [mi].o_rd_addr);
181
182 xactors_to_slaves [sj].i_rd_addr.enq (a);
183
184 v_f_rd_mis [sj].enq (fromInteger (mi));
185 v_f_rd_sjs [mi].enq (fromInteger (sj));
186
187 `ifdef verbose
188 $display ($time,"\tAXI4_Fabric: rd master [%0d] -> slave [%0d]", mi, sj);
189 $display ($time,"\t ", fshow (a));
190 `endif
191 endrule
192
193 // Non-existent destination slaves
194 for (Integer mi = 0; mi < valueOf (num_masters); mi = mi + 1)
195 rule rl_rd_xaction_no_such_slave (rd_illegal_sj (mi));
196 AXI4_Rd_Addr #(wd_addr, wd_user) a <- pop_o (xactors_from_masters [mi].o_rd_addr);
197
198 v_f_rd_sjs [mi].enq (fromInteger (valueOf (num_slaves)));
199 v_f_rd_err_user [mi].enq (a.aruser);
200
201 `ifdef verbose
202 $display ($time,"\tAXI4_Fabric: rd master [%0d] -> illegal addr", mi);
203 $display ($time,"\t ", fshow (a));
204 `endif
205 endrule
206
207 // ----------------
208 // Wr responses from slaves to masters
209
210 for (Integer mi = 0; mi < valueOf (num_masters); mi = mi + 1)
211 for (Integer sj = 0; sj < valueOf (num_slaves); sj = sj + 1)
212
213 rule rl_wr_resp_slave_to_master ( (v_f_wr_mis [sj].first == fromInteger (mi))
214 && (v_f_wr_sjs [mi].first == fromInteger (sj)));
215 v_f_wr_mis [sj].deq;
216 v_f_wr_sjs [mi].deq;
217 AXI4_Wr_Resp #(wd_user) b <- pop_o (xactors_to_slaves [sj].o_wr_resp);
218
219 xactors_from_masters [mi].i_wr_resp.enq (b);
220
221 `ifdef verbose
222 $display ($time,"\tAXI4_Fabric: wr master [%0d] <- slave [%0d]", mi, sj);
223 $display ($time,"\t ", fshow (b));
224 `endif
225 endrule
226
227 // ----------------
228 // Wr error responses to masters
229 // v_f_wr_sjs [mi].first has value num_slaves (illegal value)
230 // v_f_wr_err_user [mi].first contains the request's 'user' data
231
232 for (Integer mi = 0; mi < valueOf (num_masters); mi = mi + 1)
233
234 rule rl_wr_resp_err_to_master (v_f_wr_sjs [mi].first == fromInteger (valueOf (num_slaves)));
235 v_f_wr_sjs [mi].deq;
236 v_f_wr_err_user [mi].deq;
237
238 //let b = AXI4_Wr_Resp {bresp: AXI4_DECERR, buser: v_f_wr_err_user [mi].first};
239 let b = AXI4_Wr_Resp {bresp: AXI4_DECERR, buser: v_f_wr_err_user [mi].first, bid:fromInteger(mi)};
240
241 xactors_from_masters [mi].i_wr_resp.enq (b);
242
243 `ifdef verbose
244 $display ($time,"\tAXI4_Fabric: wr master [%0d] <- error", mi);
245 $display ($time,"\t ", fshow (b));
246 `endif
247 endrule
248
249 // ----------------
250 // Rd responses from slaves to masters
251
252 for (Integer mi = 0; mi < valueOf (num_masters); mi = mi + 1)
253 for (Integer sj = 0; sj < valueOf (num_slaves); sj = sj + 1)
254
255 rule rl_rd_resp_slave_to_master ( (v_f_rd_mis [sj].first == fromInteger (mi))
256 && (v_f_rd_sjs [mi].first == fromInteger (sj)));
257 AXI4_Rd_Data #(wd_data, wd_user) r <- pop_o (xactors_to_slaves [sj].o_rd_data);
258
259 xactors_from_masters [mi].i_rd_data.enq (r);
260 if(r.rlast)begin
261 v_f_rd_mis [sj].deq;
262 v_f_rd_sjs [mi].deq;
263 end
264
265 `ifdef verbose
266 $display ($time,"\tAXI4_Fabric: rd master [%0d] <- slave [%0d]", mi, sj);
267 $display ($time,"\t ", fshow (r));
268 `endif
269 endrule
270
271 // ----------------
272 // Rd error responses to masters
273 // v_f_rd_sjs [mi].first has value num_slaves (illegal value)
274 // v_f_rd_err_user [mi].first contains the request's 'user' data
275
276 for (Integer mi = 0; mi < valueOf (num_masters); mi = mi + 1)
277
278 rule rl_rd_resp_err_to_master (v_f_rd_sjs [mi].first == fromInteger (valueOf (num_slaves)));
279 v_f_rd_sjs [mi].deq;
280 v_f_rd_err_user [mi].deq;
281
282 Bit #(wd_data) data = 0;
283 let r = AXI4_Rd_Data {rresp: AXI4_DECERR, ruser: v_f_rd_err_user [mi].first, rdata: data, rlast:True,rid:fromInteger(mi)};
284
285 xactors_from_masters [mi].i_rd_data.enq (r);
286
287 `ifdef verbose
288 $display ($time,"\tAXI4_Fabric: rd master [%0d] <- error", mi);
289 $display ($time,"\t ", fshow (r));
290 `endif
291 endrule
292
293 // ----------------------------------------------------------------
294 // INTERFACE
295
296 function AXI4_Slave_IFC #(wd_addr, wd_data, wd_user) f1 (Integer j) = xactors_from_masters [j].axi_side;
297 function AXI4_Master_IFC #(wd_addr, wd_data, wd_user) f2 (Integer j) = xactors_to_slaves [j].axi_side;
298
299 method Action reset;
300 for (Integer mi = 0; mi < valueOf (num_masters); mi = mi + 1) begin
301 xactors_from_masters [mi].reset;
302
303 v_f_wr_sjs [mi].clear;
304 v_f_wr_err_user [mi].clear;
305
306 v_f_rd_sjs [mi].clear;
307 v_f_rd_err_user [mi].clear;
308 end
309
310 for (Integer sj = 0; sj < valueOf (num_slaves); sj = sj + 1) begin
311 xactors_to_slaves [sj].reset;
312 v_f_wr_mis [sj].clear;
313 v_f_rd_mis [sj].clear;
314 end
315 endmethod
316
317 interface v_from_masters = genWith (f1);
318 interface v_to_slaves = genWith (f2);
319 endmodule
320
321 // ================================================================
322
323 endpackage: AXI4_Fabric