Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Bugfix/axi stream slave nonblocking check #720

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 5 additions & 1 deletion vunit/vhdl/verification_components/run.py
Original file line number Diff line number Diff line change
Expand Up @@ -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()
32 changes: 6 additions & 26 deletions vunit/vhdl/verification_components/src/axi_stream_pkg.vhd
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand All @@ -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;
Expand Down
65 changes: 32 additions & 33 deletions vunit/vhdl/verification_components/src/axi_stream_slave.vhd
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -96,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);
Expand All @@ -105,39 +113,30 @@ 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));
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_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));
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);
end if;
Expand Down
61 changes: 58 additions & 3 deletions vunit/vhdl/verification_components/test/tb_axi_stream.vhd
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -431,7 +431,43 @@ 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;

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 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;

Expand Down Expand Up @@ -490,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);
Expand Down Expand Up @@ -521,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;
Expand Down