From 33ddf8a96d8eeec25ad73b0390ae72e703d80def Mon Sep 17 00:00:00 2001 From: Emanuel Schmid Date: Tue, 18 May 2021 09:49:01 +0200 Subject: [PATCH 1/6] Fix message content --- vunit/vhdl/verification_components/test/tb_axi_stream.vhd | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vunit/vhdl/verification_components/test/tb_axi_stream.vhd b/vunit/vhdl/verification_components/test/tb_axi_stream.vhd index eb506afea..38417ed90 100644 --- a/vunit/vhdl/verification_components/test/tb_axi_stream.vhd +++ b/vunit/vhdl/verification_components/test/tb_axi_stream.vhd @@ -431,7 +431,7 @@ begin tid => std_logic_vector(to_unsigned(42, id'length)), tdest => std_logic_vector(to_unsigned(i+1, dest'length)), tuser => std_logic_vector(to_unsigned(i*2, user'length)), - msg => "check blocking", + msg => "check non-blocking", blocking => false); end loop; From 0ab538408e8764a2d3da74c3765f9116a1611b48 Mon Sep 17 00:00:00 2001 From: Emanuel Schmid Date: Tue, 18 May 2021 09:49:29 +0200 Subject: [PATCH 2/6] Minor change to help readability --- vunit/vhdl/verification_components/test/tb_axi_stream.vhd | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vunit/vhdl/verification_components/test/tb_axi_stream.vhd b/vunit/vhdl/verification_components/test/tb_axi_stream.vhd index 38417ed90..6e9749a7d 100644 --- a/vunit/vhdl/verification_components/test/tb_axi_stream.vhd +++ b/vunit/vhdl/verification_components/test/tb_axi_stream.vhd @@ -353,7 +353,7 @@ begin user := x"45"; end if; push_axi_stream(net, master_axi_stream, x"12", tlast => '1', tkeep => "1", tstrb => "1", tid => id, tdest => dest, tuser => user); - check_axi_stream(net, slave_axi_stream, x"12", '1', msg => "reduced checking axi stream"); + check_axi_stream(net, slave_axi_stream, x"12", tlast => '1', msg => "reduced checking axi stream"); elsif run("test failing check") then if id'length > 0 then From 9fa8af039b3251a1d8cbee22fdb065f50438ccbc Mon Sep 17 00:00:00 2001 From: Emanuel Schmid Date: Tue, 18 May 2021 09:49:52 +0200 Subject: [PATCH 3/6] Add test to check non-blocking reduced check - currently fails. --- .../test/tb_axi_stream.vhd | 36 +++++++++++++++++++ 1 file changed, 36 insertions(+) diff --git a/vunit/vhdl/verification_components/test/tb_axi_stream.vhd b/vunit/vhdl/verification_components/test/tb_axi_stream.vhd index 6e9749a7d..8586f28fd 100644 --- a/vunit/vhdl/verification_components/test/tb_axi_stream.vhd +++ b/vunit/vhdl/verification_components/test/tb_axi_stream.vhd @@ -440,6 +440,42 @@ begin wait_until_idle(net, as_sync(slave_axi_stream)); check_equal(now, timestamp + (12+1)*10 ns, " transaction time incorrect"); + elsif run("test back-to-back passing reduced check") then + wait until rising_edge(aclk); + timestamp := now; + + last := '0'; + for i in 3 to 14 loop + if i = 14 then + last := '1'; + end if; + push_axi_stream(net, master_axi_stream, + tdata => std_logic_vector(to_unsigned(i, 8)), + tlast => last, + tkeep => "1", + tstrb => "1", + tid => std_logic_vector(to_unsigned(42, id'length)), + tdest => std_logic_vector(to_unsigned(i+1, dest'length)), + tuser => std_logic_vector(to_unsigned(i*2, user'length))); + end loop; + + last := '0'; + for i in 3 to 14 loop + if i = 14 then + last := '1'; + end if; + check_axi_stream(net, slave_axi_stream, + expected => std_logic_vector(to_unsigned(i, 8)), + tlast => last, + msg => "check non-blocking", + blocking => false); + end loop; + + check_equal(now, timestamp, result(" setting up transaction stalled")); + + wait_until_idle(net, as_sync(slave_axi_stream)); + check_equal(now, timestamp + (12+1)*10 ns, " transaction time incorrect"); + elsif run("test back-to-back failing check") then wait until rising_edge(aclk); timestamp := now; From 7a06bc8774b2894b98b679ccdd3057186725a15e Mon Sep 17 00:00:00 2001 From: Emanuel Schmid Date: Tue, 18 May 2021 09:52:58 +0200 Subject: [PATCH 4/6] Fix non-blocking partial check --- .../src/axi_stream_pkg.vhd | 32 ++++--------------- .../src/axi_stream_slave.vhd | 30 +++++++++-------- 2 files changed, 22 insertions(+), 40 deletions(-) diff --git a/vunit/vhdl/verification_components/src/axi_stream_pkg.vhd b/vunit/vhdl/verification_components/src/axi_stream_pkg.vhd index dfd8d30e2..0f4184277 100644 --- a/vunit/vhdl/verification_components/src/axi_stream_pkg.vhd +++ b/vunit/vhdl/verification_components/src/axi_stream_pkg.vhd @@ -730,12 +730,6 @@ package body axi_stream_pkg is variable got_tdest : std_logic_vector(dest_length(axi_stream)-1 downto 0); variable got_tuser : std_logic_vector(user_length(axi_stream)-1 downto 0); variable check_msg : msg_t := new_msg(check_axi_stream_msg); - variable normalized_data : std_logic_vector(data_length(axi_stream)-1 downto 0) := (others => '0'); - variable normalized_keep : std_logic_vector(data_length(axi_stream)/8-1 downto 0) := (others => '0'); - variable normalized_strb : std_logic_vector(data_length(axi_stream)/8-1 downto 0) := (others => '0'); - variable normalized_id : std_logic_vector(id_length(axi_stream)-1 downto 0) := (others => '0'); - variable normalized_dest : std_logic_vector(dest_length(axi_stream)-1 downto 0) := (others => '0'); - variable normalized_user : std_logic_vector(user_length(axi_stream)-1 downto 0) := (others => '0'); begin if blocking then pop_axi_stream(net, axi_stream, got_tdata, got_tlast, got_tkeep, got_tstrb, got_tid, got_tdest, got_tuser); @@ -758,27 +752,13 @@ package body axi_stream_pkg is end if; else push_string(check_msg, msg); - if normalized_data'length > 0 then - normalized_data(expected'length-1 downto 0) := expected; - push_std_ulogic_vector(check_msg, normalized_data); - normalized_keep(tkeep'length-1 downto 0) := tkeep; - push_std_ulogic_vector(check_msg, normalized_keep); - normalized_strb(tstrb'length-1 downto 0) := tstrb; - push_std_ulogic_vector(check_msg, normalized_strb); - end if; + push_std_ulogic_vector(check_msg, expected); + push_std_ulogic_vector(check_msg, tkeep); + push_std_ulogic_vector(check_msg, tstrb); push_std_ulogic(check_msg, tlast); - if normalized_id'length > 0 then - normalized_id(tid'length-1 downto 0) := tid; - push_std_ulogic_vector(check_msg, normalized_id); - end if; - if normalized_dest'length > 0 then - normalized_dest(tdest'length-1 downto 0) := tdest; - push_std_ulogic_vector(check_msg, normalized_dest); - end if; - if normalized_user'length > 0 then - normalized_user(tuser'length-1 downto 0) := tuser; - push_std_ulogic_vector(check_msg, normalized_user); - end if; + push_std_ulogic_vector(check_msg, tid); + push_std_ulogic_vector(check_msg, tdest); + push_std_ulogic_vector(check_msg, tuser); send(net, axi_stream.p_actor, check_msg); end if; end procedure; diff --git a/vunit/vhdl/verification_components/src/axi_stream_slave.vhd b/vunit/vhdl/verification_components/src/axi_stream_slave.vhd index 0889c172b..4be0e74a9 100644 --- a/vunit/vhdl/verification_components/src/axi_stream_slave.vhd +++ b/vunit/vhdl/verification_components/src/axi_stream_slave.vhd @@ -69,6 +69,14 @@ begin end process; bus_process : process + + procedure check_field(got, exp : std_logic_vector; msg : string) is + begin + if got'length /= 0 and exp'length /= 0 then + check_equal(got, exp, msg); + end if; + end procedure; + variable reply_msg, msg : msg_t; variable msg_type : msg_type_t; variable report_msg : string_ptr_t; @@ -117,27 +125,21 @@ begin reply_msg := new_axi_stream_transaction_msg(axi_stream_transaction); reply(net, msg, reply_msg); + elsif msg_type = check_axi_stream_msg then tready <= '1'; wait until (tvalid and tready) = '1' and rising_edge(aclk); tready <= '0'; report_msg := new_string_ptr(pop_string(msg)); - if tdata'length > 0 then - check_equal(tdata, pop_std_ulogic_vector(msg), "TDATA mismatch, " & to_string(report_msg)); - check_equal(tkeep, pop_std_ulogic_vector(msg), "TKEEP mismatch, " & to_string(report_msg)); - check_equal(tstrb, pop_std_ulogic_vector(msg), "TSTRB mismatch, " & to_string(report_msg)); - end if; + check_field(tdata, pop_std_ulogic_vector(msg), "TDATA mismatch, " & to_string(report_msg)); + check_field(tkeep, pop_std_ulogic_vector(msg), "TKEEP mismatch, " & to_string(report_msg)); + check_field(tstrb, pop_std_ulogic_vector(msg), "TSTRB mismatch, " & to_string(report_msg)); check_equal(tlast, pop_std_ulogic(msg), "TLAST mismatch, " & to_string(report_msg)); - if tid'length > 0 then - check_equal(tid, pop_std_ulogic_vector(msg), "TID mismatch, " & to_string(report_msg)); - end if; - if tdest'length > 0 then - check_equal(tdest, pop_std_ulogic_vector(msg), "TDEST mismatch, " & to_string(report_msg)); - end if; - if tuser'length > 0 then - check_equal(tuser, pop_std_ulogic_vector(msg), "TUSER mismatch, " & to_string(report_msg)); - end if; + check_field(tid, pop_std_ulogic_vector(msg), "TID mismatch, " & to_string(report_msg)); + check_field(tdest, pop_std_ulogic_vector(msg), "TDEST mismatch, " & to_string(report_msg)); + check_field(tuser, pop_std_ulogic_vector(msg), "TUSER mismatch, " & to_string(report_msg)); + else unexpected_msg_type(msg_type); end if; From 86be266d06b51a35b5afbe5af8a9320fa802e855 Mon Sep 17 00:00:00 2001 From: Emanuel Schmid Date: Tue, 18 May 2021 09:55:13 +0200 Subject: [PATCH 5/6] Add test for stall_config on non-blocking check --- vunit/vhdl/verification_components/run.py | 6 +++++- .../test/tb_axi_stream.vhd | 21 ++++++++++++++++++- 2 files changed, 25 insertions(+), 2 deletions(-) diff --git a/vunit/vhdl/verification_components/run.py b/vunit/vhdl/verification_components/run.py index 20a39fe56..f3abeb20c 100644 --- a/vunit/vhdl/verification_components/run.py +++ b/vunit/vhdl/verification_components/run.py @@ -173,8 +173,12 @@ def gen_avalon_master_tests(obj, *args): name="stall_master", generics=dict(g_stall_percentage_master=30) ) -TB_AXI_STREAM.test("test random stall on slave").add_config( +TB_AXI_STREAM.test("test random pop stall on slave").add_config( name="stall_slave", generics=dict(g_stall_percentage_slave=30) ) +TB_AXI_STREAM.test("test random check stall on slave").add_config( + name="stall_slave", generics=dict(g_stall_percentage_slave=40) +) + UI.main() diff --git a/vunit/vhdl/verification_components/test/tb_axi_stream.vhd b/vunit/vhdl/verification_components/test/tb_axi_stream.vhd index 8586f28fd..aa8eaa336 100644 --- a/vunit/vhdl/verification_components/test/tb_axi_stream.vhd +++ b/vunit/vhdl/verification_components/test/tb_axi_stream.vhd @@ -526,7 +526,7 @@ begin check_equal(now, timestamp + 20 ns, " transaction time incorrect"); - elsif run("test random stall on master") or run("test random stall on slave") then + elsif run("test random stall on master") or run("test random pop stall on slave") then wait until rising_edge(aclk); for i in 0 to 100 loop pop_stream(net, slave_stream, reference); @@ -557,6 +557,25 @@ begin check_equal(axis_stall_stats.valid.events, 0, "Checking that there are zero tvalid stall events"); end if; + elsif run("test random check stall on slave") then + wait until rising_edge(aclk); + for i in 0 to 100 loop + check_axi_stream(net, slave_axi_stream, std_logic_vector(to_unsigned(i + 1, data'length)), blocking => false); + end loop; + for i in 0 to 100 loop + push_stream(net, master_stream, std_logic_vector(to_unsigned(i + 1, data'length)), true); + end loop; + + wait_until_idle(net, master_sync); -- wait until all transfers are done before checking them + wait_until_idle(net, slave_sync); + + info("There have been " & to_string(axis_stall_stats.valid.events) & " tvalid stall events"); + info("Min stall length was " & to_string(axis_stall_stats.valid.min)); + info("Max stall length was " & to_string(axis_stall_stats.valid.max)); + check((axis_stall_stats.ready.events < (g_stall_percentage_slave+10)) and (axis_stall_stats.ready.events > (g_stall_percentage_slave-10)), "Checking that the tready stall probability lies within reasonable boundaries"); + check((axis_stall_stats.ready.min >= min_stall_cycles) and (axis_stall_stats.ready.max <= max_stall_cycles), "Checking that the minimal and maximal stall lenghts are in expected boundaries"); + check_equal(axis_stall_stats.valid.events, 0, "Checking that there are zero tvalid stall events"); + end if; test_runner_cleanup(runner); end process; From 2d0c4864e7fb4f89c24fa02aa692919a6da385f3 Mon Sep 17 00:00:00 2001 From: Emanuel Schmid Date: Tue, 18 May 2021 09:56:08 +0200 Subject: [PATCH 6/6] Implement stalling for non-blocking check by removing code duplication. --- .../src/axi_stream_slave.vhd | 51 +++++++++---------- 1 file changed, 24 insertions(+), 27 deletions(-) diff --git a/vunit/vhdl/verification_components/src/axi_stream_slave.vhd b/vunit/vhdl/verification_components/src/axi_stream_slave.vhd index 4be0e74a9..1a14ce98c 100644 --- a/vunit/vhdl/verification_components/src/axi_stream_slave.vhd +++ b/vunit/vhdl/verification_components/src/axi_stream_slave.vhd @@ -104,7 +104,7 @@ begin wait until rising_edge(aclk); elsif msg_type = notify_request_msg then -- Ignore this message, but expect it - elsif msg_type = stream_pop_msg or msg_type = pop_axi_stream_msg then + elsif msg_type = stream_pop_msg or msg_type = pop_axi_stream_msg or msg_type = check_axi_stream_msg then -- stall according to probability configuration probability_stall_axi_stream(aclk, slave, rnd); @@ -113,32 +113,29 @@ begin wait until (tvalid and tready) = '1' and rising_edge(aclk); tready <= '0'; - axi_stream_transaction := ( - tdata => tdata, - tlast => tlast = '1', - tkeep => tkeep, - tstrb => tstrb, - tid => tid, - tdest => tdest, - tuser => tuser - ); - - reply_msg := new_axi_stream_transaction_msg(axi_stream_transaction); - reply(net, msg, reply_msg); - - elsif msg_type = check_axi_stream_msg then - tready <= '1'; - wait until (tvalid and tready) = '1' and rising_edge(aclk); - tready <= '0'; - - report_msg := new_string_ptr(pop_string(msg)); - check_field(tdata, pop_std_ulogic_vector(msg), "TDATA mismatch, " & to_string(report_msg)); - check_field(tkeep, pop_std_ulogic_vector(msg), "TKEEP mismatch, " & to_string(report_msg)); - check_field(tstrb, pop_std_ulogic_vector(msg), "TSTRB mismatch, " & to_string(report_msg)); - check_equal(tlast, pop_std_ulogic(msg), "TLAST mismatch, " & to_string(report_msg)); - check_field(tid, pop_std_ulogic_vector(msg), "TID mismatch, " & to_string(report_msg)); - check_field(tdest, pop_std_ulogic_vector(msg), "TDEST mismatch, " & to_string(report_msg)); - check_field(tuser, pop_std_ulogic_vector(msg), "TUSER mismatch, " & to_string(report_msg)); + if msg_type = stream_pop_msg or msg_type = pop_axi_stream_msg then + axi_stream_transaction := ( + tdata => tdata, + tlast => tlast = '1', + tkeep => tkeep, + tstrb => tstrb, + tid => tid, + tdest => tdest, + tuser => tuser + ); + + reply_msg := new_axi_stream_transaction_msg(axi_stream_transaction); + reply(net, msg, reply_msg); + elsif msg_type = check_axi_stream_msg then + report_msg := new_string_ptr(pop_string(msg)); + check_field(tdata, pop_std_ulogic_vector(msg), "TDATA mismatch, " & to_string(report_msg)); + check_field(tkeep, pop_std_ulogic_vector(msg), "TKEEP mismatch, " & to_string(report_msg)); + check_field(tstrb, pop_std_ulogic_vector(msg), "TSTRB mismatch, " & to_string(report_msg)); + check_equal(tlast, pop_std_ulogic(msg), "TLAST mismatch, " & to_string(report_msg)); + check_field(tid, pop_std_ulogic_vector(msg), "TID mismatch, " & to_string(report_msg)); + check_field(tdest, pop_std_ulogic_vector(msg), "TDEST mismatch, " & to_string(report_msg)); + check_field(tuser, pop_std_ulogic_vector(msg), "TUSER mismatch, " & to_string(report_msg)); + end if; else unexpected_msg_type(msg_type);