Skip to content

Commit 602e5cf

Browse files
Merge pull request #268 from pulp-platform/xbar_pipeline-tbenz
Add option to enable internal pipelining to `xbar`.
2 parents e0d0f56 + 66e5200 commit 602e5cf

File tree

6 files changed

+260
-126
lines changed

6 files changed

+260
-126
lines changed

CHANGELOG.md

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,12 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.
1111
- Add `axi_channel_compare.sv`: Non-synthesizable module comparing two AXI channels of the same type
1212

1313
### Changed
14-
- `axi_demux`: Replace write FIFO (`w_fifo`) with a write credit counter.
14+
- `axi_demux`: Replace FIFO between AW and W channel by a register plus a counter. This prevents
15+
AWs from being issued to one master port while Ws from another burst are ongoing to another
16+
master port. This is required to prevents deadlocks due to circular waits downstream.
17+
- `axi_xbar`: Add parameter `PipelineStages` to `axi_pkg::xbar_cfg_t`. This adds `axi_multicuts`
18+
in the crossed connections in the xbar between the demuxes and muxes.
19+
- `axi_pkg`: Add documentation to `xbar_cfg_t`.
1520

1621
### Fixed
1722

scripts/run_vsim.sh

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -172,7 +172,7 @@ exec_test() {
172172
for Atop in 0 1; do
173173
for Exclusive in 0 1; do
174174
for UniqueIds in 0 1; do
175-
call_vsim tb_axi_xbar -gTbNumMst=$NumMst -gTbNumSlv=$NumSlv \
175+
call_vsim tb_axi_xbar -gTbNumMasters=$NumMst -gTbNumSlaves=$NumSlv \
176176
-gTbEnAtop=$Atop -gTbEnExcl=$Exclusive \
177177
-gTbUniqueIds=$UniqueIds
178178
done
@@ -202,6 +202,29 @@ exec_test() {
202202
done
203203
done
204204
;;
205+
axi_xbar)
206+
for GEN_ATOP in 0 1; do
207+
for NUM_MST in 1 6; do
208+
for NUM_SLV in 2 9; do
209+
for MST_ID_USE in 3 5; do
210+
MST_ID=5
211+
for DATA_WIDTH in 64 256; do
212+
for PIPE in 0 1; do
213+
call_vsim tb_axi_xbar -t 1ns -voptargs="+acc" \
214+
-gTbNumMasters=$NUM_MST \
215+
-gTbNumSlaves=$NUM_SLV \
216+
-gTbAxiIdWidthMasters=$MST_ID \
217+
-gTbAxiIdUsed=$MST_ID_USE \
218+
-gTbAxiDataWidth=$DATA_WIDTH \
219+
-gTbPipeline=$PIPE \
220+
-gTbEnAtop=$GEN_ATOP
221+
done
222+
done
223+
done
224+
done
225+
done
226+
done
227+
;;
205228
*)
206229
call_vsim tb_$1 -t 1ns -coverage -voptargs="+acc +cover=bcesfx"
207230
;;

src/axi_demux.sv

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -289,10 +289,10 @@ module axi_demux #(
289289
if (!aw_id_cnt_full && (w_open != {IdCounterWidth{1'b1}}) &&
290290
(!(ar_id_cnt_full && slv_aw_chan.atop[axi_pkg::ATOP_R_RESP]) ||
291291
!AtopSupport)) begin
292-
/// There is a valid AW vector make the id lookup and go further, if it passes.
293-
/// Also stall if previous transmitted AWs still have active W's in flight.
294-
/// This prevents deadlocking of the W channel. The counters are there for the
295-
/// Handling of the B responses.
292+
// There is a valid AW vector make the id lookup and go further, if it passes.
293+
// Also stall if previous transmitted AWs still have active W's in flight.
294+
// This prevents deadlocking of the W channel. The counters are there for the
295+
// Handling of the B responses.
296296
if (slv_aw_valid &&
297297
((w_open == '0) || (w_select == slv_aw_select)) &&
298298
(!aw_select_occupied || (slv_aw_select == lookup_aw_select))) begin
@@ -817,7 +817,6 @@ module axi_demux_intf #(
817817
parameter int unsigned MAX_TRANS = 32'd8,
818818
parameter int unsigned AXI_LOOK_BITS = 32'd3,
819819
parameter bit UNIQUE_IDS = 1'b0,
820-
parameter bit FALL_THROUGH = 1'b0,
821820
parameter bit SPILL_AW = 1'b1,
822821
parameter bit SPILL_W = 1'b0,
823822
parameter bit SPILL_B = 1'b0,

src/axi_pkg.sv

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -393,17 +393,44 @@ package axi_pkg;
393393

394394
/// Configuration for `axi_xbar`.
395395
typedef struct packed {
396+
/// Number of slave ports of the crossbar.
397+
/// This many master modules are connected to it.
396398
int unsigned NoSlvPorts;
399+
/// Number of master ports of the crossbar.
400+
/// This many slave modules are connected to it.
397401
int unsigned NoMstPorts;
402+
/// Maximum number of open transactions each master connected to the crossbar can have in
403+
/// flight at the same time.
398404
int unsigned MaxMstTrans;
405+
/// Maximum number of open transactions each slave connected to the crossbar can have in
406+
/// flight at the same time.
399407
int unsigned MaxSlvTrans;
408+
/// Determine if the internal FIFOs of the crossbar are instantiated in fallthrough mode.
409+
/// 0: No fallthrough
410+
/// 1: Fallthrough
400411
bit FallThrough;
412+
/// The Latency mode of the xbar. This determines if the channels on the ports have
413+
/// a spill register instantiated.
414+
/// Example configurations are provided with the enum `xbar_latency_e`.
401415
xbar_latency_e LatencyMode;
416+
/// This is the number of `axi_multicut` stages instantiated in the line cross of the channels.
417+
/// Having multiple stages can potentially add a large number of FFs!
418+
int unsigned PipelineStages;
419+
/// AXI ID width of the salve ports. The ID width of the master ports is determined
420+
/// Automatically. See `axi_mux` for details.
402421
int unsigned AxiIdWidthSlvPorts;
422+
/// The used ID portion to determine if a different salve is used for the same ID.
423+
/// See `axi_demux` for details.
403424
int unsigned AxiIdUsedSlvPorts;
425+
/// Are IDs unique?
404426
bit UniqueIds;
427+
/// AXI4+ATOP address field width.
405428
int unsigned AxiAddrWidth;
429+
/// AXI4+ATOP data field width.
406430
int unsigned AxiDataWidth;
431+
/// The number of address rules defined for routing of the transactions.
432+
/// Each master port can have multiple rules, should have however at least one.
433+
/// If a transaction can not be routed the xbar will answer with an `axi_pkg::RESP_DECERR`.
407434
int unsigned NoAddrRules;
408435
} xbar_cfg_t;
409436

src/axi_xbar.sv

Lines changed: 64 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -13,50 +13,94 @@
1313
// - Andreas Kurth <[email protected]>
1414
// - Florian Zaruba <[email protected]>
1515

16-
// axi_xbar: Fully-connected AXI4+ATOP crossbar with an arbitrary number of slave and master ports.
17-
// See `doc/axi_xbar.md` for the documentation, including the definition of parameters and ports.
16+
/// axi_xbar: Fully-connected AXI4+ATOP crossbar with an arbitrary number of slave and master ports.
17+
/// See `doc/axi_xbar.md` for the documentation, including the definition of parameters and ports.
1818
module axi_xbar
1919
import cf_math_pkg::idx_width;
2020
#(
21+
/// Configuration struct for the crossbar see `axi_pkg` for fields and definitions.
2122
parameter axi_pkg::xbar_cfg_t Cfg = '0,
23+
/// Enable atomic operations support.
2224
parameter bit ATOPs = 1'b1,
25+
/// Connectivity matrix
2326
parameter bit [Cfg.NoSlvPorts-1:0][Cfg.NoMstPorts-1:0] Connectivity = '1,
27+
/// AXI4+ATOP AW channel struct type for the slave ports.
2428
parameter type slv_aw_chan_t = logic,
29+
/// AXI4+ATOP AW channel struct type for the master ports.
2530
parameter type mst_aw_chan_t = logic,
31+
/// AXI4+ATOP W channel struct type for all ports.
2632
parameter type w_chan_t = logic,
33+
/// AXI4+ATOP B channel struct type for the slave ports.
2734
parameter type slv_b_chan_t = logic,
35+
/// AXI4+ATOP B channel struct type for the master ports.
2836
parameter type mst_b_chan_t = logic,
37+
/// AXI4+ATOP AR channel struct type for the slave ports.
2938
parameter type slv_ar_chan_t = logic,
39+
/// AXI4+ATOP AR channel struct type for the master ports.
3040
parameter type mst_ar_chan_t = logic,
41+
/// AXI4+ATOP R channel struct type for the slave ports.
3142
parameter type slv_r_chan_t = logic,
43+
/// AXI4+ATOP R channel struct type for the master ports.
3244
parameter type mst_r_chan_t = logic,
45+
/// AXI4+ATOP request struct type for the slave ports.
3346
parameter type slv_req_t = logic,
47+
/// AXI4+ATOP response struct type for the slave ports.
3448
parameter type slv_resp_t = logic,
49+
/// AXI4+ATOP request struct type for the master ports.
3550
parameter type mst_req_t = logic,
51+
/// AXI4+ATOP response struct type for the master ports
3652
parameter type mst_resp_t = logic,
53+
/// Address rule type for the address decoders from `common_cells:addr_decode`.
54+
/// Example types are provided in `axi_pkg`.
55+
/// Required struct fields:
56+
/// ```
57+
/// typedef struct packed {
58+
/// int unsigned idx;
59+
/// axi_addr_t start_addr;
60+
/// axi_addr_t end_addr;
61+
/// } rule_t;
62+
/// ```
3763
parameter type rule_t = axi_pkg::xbar_rule_64_t
3864
`ifdef VCS
3965
, localparam int unsigned MstPortsIdxWidth =
4066
(Cfg.NoMstPorts == 32'd1) ? 32'd1 : unsigned'($clog2(Cfg.NoMstPorts))
4167
`endif
4268
) (
69+
/// Clock, positive edge triggered.
4370
input logic clk_i,
71+
/// Asynchronous reset, active low.
4472
input logic rst_ni,
73+
/// Testmode enable, active high.
4574
input logic test_i,
75+
/// AXI4+ATOP requests to the slave ports.
4676
input slv_req_t [Cfg.NoSlvPorts-1:0] slv_ports_req_i,
77+
/// AXI4+ATOP responses of the slave ports.
4778
output slv_resp_t [Cfg.NoSlvPorts-1:0] slv_ports_resp_o,
79+
/// AXI4+ATOP requests of the master ports.
4880
output mst_req_t [Cfg.NoMstPorts-1:0] mst_ports_req_o,
81+
/// AXI4+ATOP responses to the master ports.
4982
input mst_resp_t [Cfg.NoMstPorts-1:0] mst_ports_resp_i,
83+
/// Address map array input for the crossbar. This map is global for the whole module.
84+
/// It is used for routing the transactions to the respective master ports.
85+
/// Each master port can have multiple different rules.
5086
input rule_t [Cfg.NoAddrRules-1:0] addr_map_i,
87+
/// Enable default master port.
5188
input logic [Cfg.NoSlvPorts-1:0] en_default_mst_port_i,
5289
`ifdef VCS
90+
/// Enables a default master port for each slave port. When this is enabled unmapped
91+
/// transactions get issued at the master port given by `default_mst_port_i`.
92+
/// When not used, tie to `'0`.
5393
input logic [Cfg.NoSlvPorts-1:0][MstPortsIdxWidth-1:0] default_mst_port_i
5494
`else
95+
/// Enables a default master port for each slave port. When this is enabled unmapped
96+
/// transactions get issued at the master port given by `default_mst_port_i`.
97+
/// When not used, tie to `'0`.
5598
input logic [Cfg.NoSlvPorts-1:0][idx_width(Cfg.NoMstPorts)-1:0] default_mst_port_i
5699
`endif
57100
);
58101

59-
typedef logic [Cfg.AxiAddrWidth-1:0] addr_t;
102+
// Address tpye for inidvidual address signals
103+
typedef logic [Cfg.AxiAddrWidth-1:0] addr_t;
60104
// to account for the decoding error slave
61105
`ifdef VCS
62106
localparam int unsigned MstPortsIdxWidthOne =
@@ -204,8 +248,23 @@ import cf_math_pkg::idx_width;
204248
for (genvar i = 0; i < Cfg.NoSlvPorts; i++) begin : gen_xbar_slv_cross
205249
for (genvar j = 0; j < Cfg.NoMstPorts; j++) begin : gen_xbar_mst_cross
206250
if (Connectivity[i][j]) begin : gen_connection
207-
assign mst_reqs[j][i] = slv_reqs[i][j];
208-
assign slv_resps[i][j] = mst_resps[j][i];
251+
axi_multicut #(
252+
.NoCuts ( Cfg.PipelineStages ),
253+
.aw_chan_t ( slv_aw_chan_t ),
254+
.w_chan_t ( w_chan_t ),
255+
.b_chan_t ( slv_b_chan_t ),
256+
.ar_chan_t ( slv_ar_chan_t ),
257+
.r_chan_t ( slv_r_chan_t ),
258+
.axi_req_t ( slv_req_t ),
259+
.axi_resp_t ( slv_resp_t )
260+
) i_axi_multicut_xbar_pipeline (
261+
.clk_i,
262+
.rst_ni,
263+
.slv_req_i ( slv_reqs[i][j] ),
264+
.slv_resp_o ( slv_resps[i][j] ),
265+
.mst_req_o ( mst_reqs[j][i] ),
266+
.mst_resp_i ( mst_resps[j][i] )
267+
);
209268

210269
end else begin : gen_no_connection
211270
assign mst_reqs[j][i] = '0;

0 commit comments

Comments
 (0)