fpga: sim: chdr_stream_endpoint_tb improvements

- Adds test coverage for stream command and status packets
- Cleans up report output during simulation
- Stops clocks at the end of simulation, so chdr_stream_endpoint_tb can
  be run directly instead of just chdr_stream_endpoint_all_tb


Original-commit: 97cb396297828f57bba455a275966c58f1abce6e
This commit is contained in:
Wade Fife
2020-08-31 08:16:43 -05:00
parent 15d9d740ef
commit d6849765ec
2 changed files with 150 additions and 36 deletions
@@ -14,13 +14,7 @@ module chdr_stream_endpoint_all_tb#(
/* no IO */
);
chdr_stream_endpoint_tb #(.TEST_NAME("64B"),.CHDR_W(64)) CHDR64 ();
chdr_stream_endpoint_tb #(.TEST_NAME("512B"),.CHDR_W(512)) CHDR512 ();
// Wait for all done
bit clk,rst;
sim_clock_gen #(100.0) clk_gen (clk, rst);
always_ff@(posedge clk)
if (CHDR64.test.done && CHDR512.test.done) $finish(1);
chdr_stream_endpoint_tb #(.TEST_NAME("64B"), .CHDR_W(64)) CHDR64 ();
chdr_stream_endpoint_tb #(.TEST_NAME("512B"), .CHDR_W(512)) CHDR512 ();
endmodule
@@ -9,7 +9,7 @@
`default_nettype none
module chdr_stream_endpoint_tb#(
parameter TEST_NAME = "chdr_stream_endpoint_tb",
parameter TEST_NAME = "",
parameter CHDR_W = 64
)(
/* no IO */
@@ -19,7 +19,6 @@ module chdr_stream_endpoint_tb#(
// ----------------------------------------
// Include macros and time declarations for use with PkgTestExec
`define TEST_EXEC_OBJ test
`include "test_exec.svh"
import PkgTestExec::*;
@@ -29,8 +28,10 @@ module chdr_stream_endpoint_tb#(
// Clocks and resets
bit rfnoc_chdr_clk, rfnoc_chdr_rst;
bit rfnoc_ctrl_clk, rfnoc_ctrl_rst;
sim_clock_gen #(6.0) rfnoc_chdr_clk_gen (rfnoc_chdr_clk, rfnoc_chdr_rst); // 166.6 MHz
sim_clock_gen #(20.0) rfnoc_ctrl_clk_gen (rfnoc_ctrl_clk, rfnoc_ctrl_rst); // 50 MHz
sim_clock_gen #(.PERIOD(6.0), .AUTOSTART(0))
rfnoc_chdr_clk_gen (rfnoc_chdr_clk, rfnoc_chdr_rst); // 166.6 MHz
sim_clock_gen #(.PERIOD(20.0), .AUTOSTART(0))
rfnoc_ctrl_clk_gen (rfnoc_ctrl_clk, rfnoc_ctrl_rst); // 50 MHz
// Parameters
localparam bit VERBOSE = 0;
@@ -48,6 +49,9 @@ module chdr_stream_endpoint_tb#(
localparam [9:0] PORT_A = 10'd1;
localparam [9:0] PORT_B = 10'd2;
// Create a formatted string with the test name for reporting output
string test_name = TEST_NAME == "" ? "" : {TEST_NAME, ": "};
typedef ChdrData #(CHDR_W)::chdr_word_t chdr_word_t;
// ----------------------------------------
@@ -275,11 +279,109 @@ module chdr_stream_endpoint_tb#(
// ----------------------------------------
// Test Utilities
// ----------------------------------------
TestExec test = new();
integer cached_mgmt_seqnum = 0;
integer cached_ctrl_seqnum = 0;
integer cached_data_seqnum = 0;
// Test stream command packets and their stream status response packets
task automatic send_recv_stream_packets(
input [15:0] dst_epid
);
ChdrPacket #(CHDR_W) tx_chdr, rx_chdr, exp_chdr;
chdr_header_t chdr_hdr;
chdr_str_command_t str_cmd;
chdr_str_status_t str_sts;
chdr_seq_num_t seq_num, resp_seq_num;
int xfer_count_bytes;
int xfer_count_pkts;
chdr_strc_opcode_t op[] = {
STRC_INIT, // Test once with zero init values
STRC_PING,
STRC_RESYNC,
STRC_INIT // Test again with non-zero init values
};
seq_num = 0;
resp_seq_num = 0;
xfer_count_bytes = 0;
xfer_count_pkts = 0;
// Iterate over stream commands to test
foreach (op[i]) begin
chdr_hdr = '{
dst_epid : dst_epid,
seq_num : seq_num,
default : 0
};
str_cmd = '{
src_epid : EPID_TB,
op_code : op[i],
num_bytes : { $urandom(), $urandom() }, // 64-bit
num_pkts : { $urandom(), $urandom() }, // 40-bit
default : 0
};
// On the first STRC_INIT, test the init values of 0, which we use to get
// the buffer sizes. We should only get one status update in response.
if (i == 0) begin
assert (op[i] == STRC_INIT) else $fatal(1, "Expecting STRC_INIT op");
str_cmd.num_bytes = 0;
str_cmd.num_pkts = 0;
end
// Send the stream command packet
tx_chdr = new();
tx_chdr.write_stream_cmd(chdr_hdr, str_cmd);
if (VERBOSE) begin $write("Tx"); tx_chdr.print(); end
tb_chdr_bfm.put_chdr(tx_chdr);
// Get the stream status packet response
tb_chdr_bfm.get_chdr(rx_chdr);
if (VERBOSE) begin $write("Rx"); rx_chdr.print(); end
// Build up the expected response
if (op[i] == STRC_INIT) begin
// STRC_INIT resets the counters in the stream endpoint
resp_seq_num = 0;
xfer_count_pkts = 0;
xfer_count_bytes = 0;
end
chdr_hdr.dst_epid = EPID_TB; // Response should come back to TB endpoint
chdr_hdr.seq_num = resp_seq_num;
str_sts = '{
src_epid : dst_epid,
status : STRS_OKAY,
capacity_bytes : 2**(MTU+1) * (CHDR_W/8) - 1,
capacity_pkts : 'hFFFFFF,
xfer_count_pkts : xfer_count_pkts,
xfer_count_bytes : xfer_count_bytes,
default : 0
};
$write(""); str_sts.status_info = 0; // Work around Vivado bug :(
if (op[i] == STRC_RESYNC) begin
// The STRC_RESYNC op should update the xfer_count_bytes in the SEP, so
// we should expect the values we sent to be echoed in the response.
str_sts.xfer_count_pkts = str_cmd.num_pkts;
str_sts.xfer_count_bytes = str_cmd.num_bytes;
end
exp_chdr = new();
exp_chdr.write_stream_status(chdr_hdr, str_sts);
if (VERBOSE) begin $write("ExpRx"); exp_chdr.print(); end
// Validate contents of the response
`ASSERT_ERROR(exp_chdr.equal(rx_chdr),
"Received CHDR stream status packet was incorrect");
// Update counters. Note that xfer_count_bytes counts whole CHDR words
// because that's the width of the internal buffers.
xfer_count_bytes += $ceil(tx_chdr.header.length / (CHDR_W/8.0)) * (CHDR_W/8);
xfer_count_pkts += 1;
resp_seq_num += 1;
seq_num += 1;
end
endtask : send_recv_stream_packets
task automatic send_recv_mgmt_packet(
input chdr_header_t tx_mgmt_hdr,
input chdr_mgmt_t tx_mgmt_pl,
@@ -390,7 +492,7 @@ module chdr_stream_endpoint_tb#(
};
tx_chdr.write_ctrl(chdr_hdr, ctrl_hdr, ctrl_op, ctrl_data, ctrl_ts);
test.start_timeout(ctrl_timeout, 2us, "Waiting for management transaction");
test.start_timeout(ctrl_timeout, 2us, "Waiting for control transaction");
if (VERBOSE) begin $write("Tx"); tx_chdr.print(); end
tb_chdr_bfm.put_chdr(tx_chdr.copy());
tb_chdr_bfm.get_chdr(rx_chdr);
@@ -410,7 +512,6 @@ module chdr_stream_endpoint_tb#(
if (VERBOSE) begin $write("ExpRx"); exp_chdr.print(); end
// Validate contents
exp_chdr.disable_comparing_beyond_length = 1;
`ASSERT_ERROR(exp_chdr.equal(rx_chdr),
"Received CHDR control packet was incorrect");
end
@@ -528,7 +629,7 @@ module chdr_stream_endpoint_tb#(
// ----------------------------------------
// Test Process
// ----------------------------------------
initial begin
initial begin : tb_main
// Shared Variables
// ----------------------------------------
@@ -551,7 +652,7 @@ module chdr_stream_endpoint_tb#(
// Initialize
// ----------------------------------------
test.start_tb({TEST_NAME,"chdr_stream_endpoint_tb"});
test.start_tb({test_name, "chdr_stream_endpoint_tb"});
// Start the BFMs
a0_data_bfm.run();
@@ -563,12 +664,16 @@ module chdr_stream_endpoint_tb#(
tb_chdr_bfm.set_master_stall_prob(0);
tb_chdr_bfm.set_slave_stall_prob(0);
// Start the clocks
rfnoc_chdr_clk_gen.start();
rfnoc_ctrl_clk_gen.start();
// Reset
// ----------------------------------------
rfnoc_ctrl_clk_gen.reset();
rfnoc_chdr_clk_gen.reset();
test.start_test({TEST_NAME,"Wait for reset"});
test.start_test({test_name, "Wait for reset"});
test.start_timeout(timeout, 1us, "Waiting for reset");
while (rfnoc_ctrl_rst) @(posedge rfnoc_ctrl_clk);
while (rfnoc_chdr_rst) @(posedge rfnoc_chdr_clk);
@@ -578,7 +683,7 @@ module chdr_stream_endpoint_tb#(
// Discover Topology
// ----------------------------------------
test.start_test({TEST_NAME,"Discover Topology"});
test.start_test({test_name, "Discover Topology"});
begin
automatic chdr_header_t tx_mgmt_hdr, rx_mgmt_hdr;
automatic chdr_mgmt_t tx_mgmt_pl, rx_mgmt_pl;
@@ -670,7 +775,7 @@ module chdr_stream_endpoint_tb#(
// Configure Routes to Stream Endpoints A and B
// ----------------------------------------
test.start_test({TEST_NAME,"Configure Routes"});
test.start_test({test_name, "Configure Routes"});
begin
automatic chdr_header_t tx_mgmt_hdr, rx_mgmt_hdr;
automatic chdr_mgmt_t tx_mgmt_pl, rx_mgmt_pl;
@@ -707,7 +812,7 @@ module chdr_stream_endpoint_tb#(
// Configure Stream Endpoints
// ----------------------------------------
test.start_test({TEST_NAME,"Configure Stream Endpoints"});
test.start_test({test_name, "Configure Stream Endpoints"});
begin
automatic chdr_header_t tx_mgmt_hdr, rx_mgmt_hdr;
automatic chdr_mgmt_t tx_mgmt_pl, rx_mgmt_pl;
@@ -756,9 +861,20 @@ module chdr_stream_endpoint_tb#(
end
test.end_test();
// Test Stream Commands and Responses
// ----------------------------------------
test.start_test({test_name, "Test Stream Commands"}, 1ms);
begin
automatic logic [15:0] epids[2] = {EPID_A, EPID_B};
foreach (epids[i]) begin
send_recv_stream_packets(epids[i]);
end
end
test.end_test();
// Setup a stream between Endpoint A and B
// ----------------------------------------
test.start_test({TEST_NAME,"Setup bidirectional stream between endpoints A and B"});
test.start_test({test_name, "Setup bidirectional stream between endpoints A and B"});
begin
automatic chdr_header_t tx_mgmt_hdr, rx_mgmt_hdr;
automatic chdr_mgmt_t tx_mgmt_pl, rx_mgmt_pl;
@@ -865,7 +981,7 @@ module chdr_stream_endpoint_tb#(
cached_ctrl_seqnum = 0;
for (int cfg = 0; cfg < 2; cfg++) begin
$sformat(tc_label, "Control Xact to A (%s)", (cfg?"Slow":"Fast"));
test.start_test({TEST_NAME,tc_label});
test.start_test({test_name, tc_label});
begin
tb_chdr_bfm.set_master_stall_prob(cfg?SLOW_STALL_PROB:FAST_STALL_PROB);
tb_chdr_bfm.set_slave_stall_prob(cfg?SLOW_STALL_PROB:FAST_STALL_PROB);
@@ -880,7 +996,7 @@ module chdr_stream_endpoint_tb#(
cached_ctrl_seqnum = 0;
for (int cfg = 0; cfg < 2; cfg++) begin
$sformat(tc_label, "Control Xact to B (%s)", (cfg?"Slow":"Fast"));
test.start_test({TEST_NAME,tc_label});
test.start_test({test_name, tc_label});
begin
tb_chdr_bfm.set_master_stall_prob(cfg?SLOW_STALL_PROB:FAST_STALL_PROB);
tb_chdr_bfm.set_slave_stall_prob(cfg?SLOW_STALL_PROB:FAST_STALL_PROB);
@@ -898,7 +1014,7 @@ module chdr_stream_endpoint_tb#(
automatic logic slv_cfg = cfg[1];
$sformat(tc_label, "Stream Data from A to B (%s Mst, %s Slv)",
(mst_cfg?"Slow":"Fast"), (slv_cfg?"Slow":"Fast"));
test.start_test({TEST_NAME,tc_label});
test.start_test({test_name, tc_label});
begin
set_unidir_stall_prob(EPID_A, EPID_B,
mst_cfg?SLOW_STALL_PROB:FAST_STALL_PROB,
@@ -917,7 +1033,7 @@ module chdr_stream_endpoint_tb#(
automatic logic slv_cfg = cfg[1];
$sformat(tc_label, "Stream Data from B to A (%s Mst, %s Slv)",
(mst_cfg?"Slow":"Fast"), (slv_cfg?"Slow":"Fast"));
test.start_test({TEST_NAME,tc_label});
test.start_test({test_name, tc_label});
begin
set_unidir_stall_prob(EPID_B, EPID_A,
mst_cfg?SLOW_STALL_PROB:FAST_STALL_PROB,
@@ -935,7 +1051,7 @@ module chdr_stream_endpoint_tb#(
automatic logic slv_cfg = cfg[1];
$sformat(tc_label, "Stream Data between A <=> B simultaneously (%s Mst, %s Slv)",
(mst_cfg?"Slow":"Fast"), (slv_cfg?"Slow":"Fast"));
test.start_test({TEST_NAME,tc_label});
test.start_test({test_name, tc_label});
begin
set_bidir_stall_prob(
mst_cfg?SLOW_STALL_PROB:FAST_STALL_PROB,
@@ -956,7 +1072,7 @@ module chdr_stream_endpoint_tb#(
automatic logic slv_cfg = cfg[1];
$sformat(tc_label, "Stream Data and Control between A <=> B (%s Mst, %s Slv)",
(mst_cfg?"Slow":"Fast"), (slv_cfg?"Slow":"Fast"));
test.start_test({TEST_NAME,tc_label});
test.start_test({test_name, tc_label});
begin
tb_chdr_bfm.set_master_stall_prob(mst_cfg?SLOW_STALL_PROB:FAST_STALL_PROB);
tb_chdr_bfm.set_slave_stall_prob(slv_cfg?SLOW_STALL_PROB:FAST_STALL_PROB);
@@ -982,7 +1098,7 @@ module chdr_stream_endpoint_tb#(
// Check zero sequence errors after streaming
// ----------------------------------------
test.start_test({TEST_NAME,"Check zero sequence errors after streaming"});
test.start_test({test_name, "Check zero sequence errors after streaming"});
begin
automatic logic [15:0] epids[2] = {EPID_A, EPID_B};
foreach (epids[i]) begin
@@ -1000,7 +1116,7 @@ module chdr_stream_endpoint_tb#(
// can cause the count to be greater than just the number data packets
// that are sent, so the comparisons are to > instead of ==
// ----------------------------------------
test.start_test({TEST_NAME,"Force sequence error"});
test.start_test({test_name, "Force sequence error"});
begin
// First sequence error
send_recv_data_packets(EPID_A, EPID_B, 1, cached_data_seqnum++, 1);
@@ -1028,7 +1144,7 @@ module chdr_stream_endpoint_tb#(
// Force routing error
// ----------------------------------------
test.start_test({TEST_NAME,"Force routing error"});
test.start_test({test_name, "Force routing error"});
begin
logic [31:0] old_route_err_count;
// First sequence error
@@ -1058,7 +1174,7 @@ module chdr_stream_endpoint_tb#(
// Setup a stream between Endpoint A and B
// ----------------------------------------
test.start_test({TEST_NAME,"Reconfigure flow control (reset state)"});
test.start_test({test_name, "Reconfigure flow control (reset state)"});
begin
automatic chdr_header_t tx_mgmt_hdr, rx_mgmt_hdr;
automatic chdr_mgmt_t tx_mgmt_pl, rx_mgmt_pl;
@@ -1122,7 +1238,7 @@ module chdr_stream_endpoint_tb#(
// Check zero errors after reinit
// ----------------------------------------
test.start_test({TEST_NAME,"Check zero errors after reinit"});
test.start_test({test_name, "Check zero errors after reinit"});
begin
automatic logic [15:0] epids[2] = {EPID_A, EPID_B};
foreach (epids[i]) begin
@@ -1136,7 +1252,7 @@ module chdr_stream_endpoint_tb#(
// Stream data between A <=> B simultaneously
// ----------------------------------------
test.start_test({TEST_NAME,"Stream Data between A <=> B with a lossy link"});
test.start_test({test_name, "Stream Data between A <=> B with a lossy link"});
begin
cached_data_seqnum = 0;
set_bidir_stall_prob(FAST_STALL_PROB, SLOW_STALL_PROB);
@@ -1154,9 +1270,13 @@ module chdr_stream_endpoint_tb#(
// Finish Up
// ----------------------------------------
// Stop the clocks
rfnoc_chdr_clk_gen.kill();
rfnoc_ctrl_clk_gen.kill();
// Display final statistics and results
test.end_tb(.finish(0));
end
end : tb_main
endmodule
`default_nettype wire
`default_nettype wire