2 Copyright (c) 2013, IIT Madras
5 Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
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.
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 ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
14 // Copyright (c) 2013-2017 Bluespec, Inc. All Rights Reserved
18 // ================================================================
19 // This package defines a fabric connecting CPUs, Memories and DMAs
20 // and other IP blocks.
22 // ================================================================
23 // Bluespec library imports
27 import ConfigReg :: *;
30 // BSV additional libs
32 import Cur_Cycle :: *;
34 // ================================================================
37 import Semi_FIFOF :: *;
38 import AXI4_Types :: *;
40 // ================================================================
41 // The interface for the fabric module
43 interface AXI4_Fabric_IFC #(numeric type num_masters,
44 numeric type num_slaves,
47 numeric type wd_user);
49 method Action set_verbosity (Bit #(4) verbosity);
52 interface Vector #(num_masters, AXI4_Slave_IFC #(wd_addr, wd_data, wd_user)) v_from_masters;
55 interface Vector #(num_slaves, AXI4_Master_IFC #(wd_addr, wd_data, wd_user)) v_to_slaves;
58 // ================================================================
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
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))
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));
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);
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);
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)
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);
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);
96 // ----------------------------------------------------------------
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)));
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);
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)));
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);
124 // Wr requests from masters to slaves
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)
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);
134 xactors_to_slaves [sj].i_wr_addr.enq (a);
135 xactors_to_slaves [sj].i_wr_data.enq (d);
137 v_f_wr_mis [sj].enq (fromInteger (mi));
138 v_f_wr_sjs [mi].enq (fromInteger (sj));
141 $display ($time,"\tAXI4_Fabric: wr master [%0d] -> slave [%0d]", mi, sj);
142 $display ($time,"\t ", fshow (a));
143 $display ($time,"\t ", fshow (d));
147 for (Integer mi = 0; mi < valueOf (num_masters); mi = mi + 1)
148 for (Integer sj = 0; sj < valueOf (num_slaves); sj = sj + 1)
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
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);
164 v_f_wr_sjs [mi].enq (fromInteger (valueOf (num_slaves)));
165 v_f_wr_err_user [mi].enq (a.awuser);
167 $display ($time,"\tAXI4_Fabric: wr master [%0d] -> illegal addr", mi);
168 $display ($time,"\t ", fshow (a));
173 // Rd requests from masters to slaves
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)
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);
182 xactors_to_slaves [sj].i_rd_addr.enq (a);
184 v_f_rd_mis [sj].enq (fromInteger (mi));
185 v_f_rd_sjs [mi].enq (fromInteger (sj));
188 $display ($time,"\tAXI4_Fabric: rd master [%0d] -> slave [%0d]", mi, sj);
189 $display ($time,"\t ", fshow (a));
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);
198 v_f_rd_sjs [mi].enq (fromInteger (valueOf (num_slaves)));
199 v_f_rd_err_user [mi].enq (a.aruser);
202 $display ($time,"\tAXI4_Fabric: rd master [%0d] -> illegal addr", mi);
203 $display ($time,"\t ", fshow (a));
208 // Wr responses from slaves to masters
210 for (Integer mi = 0; mi < valueOf (num_masters); mi = mi + 1)
211 for (Integer sj = 0; sj < valueOf (num_slaves); sj = sj + 1)
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)));
217 AXI4_Wr_Resp #(wd_user) b <- pop_o (xactors_to_slaves [sj].o_wr_resp);
219 xactors_from_masters [mi].i_wr_resp.enq (b);
222 $display ($time,"\tAXI4_Fabric: wr master [%0d] <- slave [%0d]", mi, sj);
223 $display ($time,"\t ", fshow (b));
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
232 for (Integer mi = 0; mi < valueOf (num_masters); mi = mi + 1)
234 rule rl_wr_resp_err_to_master (v_f_wr_sjs [mi].first == fromInteger (valueOf (num_slaves)));
236 v_f_wr_err_user [mi].deq;
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)};
241 xactors_from_masters [mi].i_wr_resp.enq (b);
244 $display ($time,"\tAXI4_Fabric: wr master [%0d] <- error", mi);
245 $display ($time,"\t ", fshow (b));
250 // Rd responses from slaves to masters
252 for (Integer mi = 0; mi < valueOf (num_masters); mi = mi + 1)
253 for (Integer sj = 0; sj < valueOf (num_slaves); sj = sj + 1)
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);
259 xactors_from_masters [mi].i_rd_data.enq (r);
266 $display ($time,"\tAXI4_Fabric: rd master [%0d] <- slave [%0d]", mi, sj);
267 $display ($time,"\t ", fshow (r));
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
276 for (Integer mi = 0; mi < valueOf (num_masters); mi = mi + 1)
278 rule rl_rd_resp_err_to_master (v_f_rd_sjs [mi].first == fromInteger (valueOf (num_slaves)));
280 v_f_rd_err_user [mi].deq;
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)};
285 xactors_from_masters [mi].i_rd_data.enq (r);
288 $display ($time,"\tAXI4_Fabric: rd master [%0d] <- error", mi);
289 $display ($time,"\t ", fshow (r));
293 // ----------------------------------------------------------------
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;
300 for (Integer mi = 0; mi < valueOf (num_masters); mi = mi + 1) begin
301 xactors_from_masters [mi].reset;
303 v_f_wr_sjs [mi].clear;
304 v_f_wr_err_user [mi].clear;
306 v_f_rd_sjs [mi].clear;
307 v_f_rd_err_user [mi].clear;
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;
317 interface v_from_masters = genWith (f1);
318 interface v_to_slaves = genWith (f2);
321 // ================================================================
323 endpackage: AXI4_Fabric