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

add possibility to configure random stalls for axi_stream #557

Merged
merged 25 commits into from
Feb 10, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
60ffc73
Added possibility to configure random stalls
Oct 4, 2019
c8af779
Added lines for linter
Oct 7, 2019
a7179f3
Removed whitespaces and added check for zero stall activity where not…
Oct 7, 2019
1804abc
replaced configuration functions by constants configured by generic
Nov 18, 2019
c460bf1
uncommented disabled checks
Nov 18, 2019
5e3f7e3
fixed ordering of the signals in if statement and used VHDL 2008
Nov 18, 2019
3efca1a
Fixed order of generics to be backwards compatible
Nov 19, 2019
0856b53
Change of stall generics to provide [0-100]% stall
Nov 19, 2019
c25636e
replaces stat signals with records
Nov 19, 2019
46564a0
only include RandomPType with use instead of all
Nov 19, 2019
5aadfa8
made random variable privat to process
Dec 9, 2019
4f14cea
moved procedures that are private to a private package
Dec 9, 2019
0e20ec8
give meaningful name to generics to avoid comment
Dec 9, 2019
5e0794e
fixed return value for p_actor in new_axi_stream_slave
Jan 14, 2020
c3e6cf2
added procedure drive_invalid_output
Jan 14, 2020
a6b69ec
replaced for loop with direct call to test case
Jan 14, 2020
78acd19
introduced new_stall_config function
Jan 14, 2020
a811f38
unified random stall test cases for axi_stream
Jan 14, 2020
83d91cc
removed explicit numbers in test case
Jan 14, 2020
065e58d
replaced if statement for min/max evaluation by min/max functions
Jan 14, 2020
07ab061
reformated using black
Jan 14, 2020
ae0db7c
fixed typo
Feb 7, 2020
4005b05
fixed formating issues
Feb 7, 2020
3489cee
Fixed year of license text in axi_stream_private_pkg.vhd
Feb 10, 2020
3d0e47c
uppercased test bench variable
Feb 10, 2020
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
7 changes: 7 additions & 0 deletions vunit/vhdl/verification_components/run.py
Original file line number Diff line number Diff line change
Expand Up @@ -132,5 +132,12 @@ def gen_avalon_master_tests(obj, *args):
name="max_waits=%d" % max_waits, generics=dict(max_waits=max_waits)
)

TB_AXI_STREAM.test("test random stall on master").add_config(
name="stall_master", generics=dict(g_stall_percentage_master=30)
)

TB_AXI_STREAM.test("test random stall on slave").add_config(
name="stall_slave", generics=dict(g_stall_percentage_slave=30)
)

ui.main()
141 changes: 82 additions & 59 deletions vunit/vhdl/verification_components/src/axi_stream_master.vhd
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,13 @@ context work.vunit_context;
context work.com_context;
use work.stream_master_pkg.all;
use work.axi_stream_pkg.all;
use work.axi_stream_private_pkg.all;
use work.queue_pkg.all;
use work.sync_pkg.all;

library osvvm;
use osvvm.RandomPkg.RandomPType;

entity axi_stream_master is
generic (
master : axi_stream_master_t;
Expand Down Expand Up @@ -42,6 +46,22 @@ architecture a of axi_stream_master is
constant message_queue : queue_t := new_queue;
signal notify_bus_process_done : std_logic := '0';

procedure drive_invalid_output(signal l_tdata : out std_logic_vector(data_length(master)-1 downto 0);
signal l_tkeep : out std_logic_vector(data_length(master)/8-1 downto 0);
signal l_tstrb : out std_logic_vector(data_length(master)/8-1 downto 0);
signal l_tid : out std_logic_vector(id_length(master)-1 downto 0);
signal l_tdest : out std_logic_vector(dest_length(master)-1 downto 0);
signal l_tuser : out std_logic_vector(user_length(master)-1 downto 0))
is
begin
l_tdata <= (others => drive_invalid_val);
l_tkeep <= (others => drive_invalid_val);
l_tstrb <= (others => drive_invalid_val);
l_tid <= (others => drive_invalid_val);
l_tdest <= (others => drive_invalid_val);
l_tuser <= (others => drive_invalid_val_user);
end procedure;

begin

main : process
Expand Down Expand Up @@ -69,68 +89,71 @@ begin
bus_process : process
variable msg : msg_t;
variable msg_type : msg_type_t;
variable rnd : RandomPType;
begin
if drive_invalid then
tdata <= (others => drive_invalid_val);
tkeep <= (others => drive_invalid_val);
tstrb <= (others => drive_invalid_val);
tid <= (others => drive_invalid_val);
tdest <= (others => drive_invalid_val);
tuser <= (others => drive_invalid_val_user);
end if;

-- Wait for messages to arrive on the queue, posted by the process above
wait until rising_edge(aclk) and (not is_empty(message_queue) or areset_n = '0');

if (areset_n = '0') then
tvalid <= '0';
else
while not is_empty(message_queue) loop
msg := pop(message_queue);
msg_type := message_type(msg);

if msg_type = wait_for_time_msg then
handle_sync_message(net, msg_type, msg);
-- Re-align with the clock when a wait for time message was handled, because this breaks edge alignment.
wait until rising_edge(aclk);
elsif msg_type = notify_request_msg then
-- Ignore this message, but expect it
elsif msg_type = stream_push_msg or msg_type = push_axi_stream_msg then
tvalid <= '1';
tdata <= pop_std_ulogic_vector(msg);
if msg_type = push_axi_stream_msg then
tlast <= pop_std_ulogic(msg);
tkeep <= pop_std_ulogic_vector(msg);
tstrb <= pop_std_ulogic_vector(msg);
tid <= pop_std_ulogic_vector(msg);
tdest <= pop_std_ulogic_vector(msg);
tuser <= pop_std_ulogic_vector(msg);
else
if pop_boolean(msg) then
tlast <= '1';
rnd.InitSeed(rnd'instance_name);
loop
if drive_invalid then
drive_invalid_output(tdata, tkeep, tstrb, tid, tdest, tuser);
end if;

-- Wait for messages to arrive on the queue, posted by the process above
wait until rising_edge(aclk) and (not is_empty(message_queue) or areset_n = '0');

if (areset_n = '0') then
tvalid <= '0';
else
while not is_empty(message_queue) loop
msg := pop(message_queue);
msg_type := message_type(msg);

if msg_type = wait_for_time_msg then
handle_sync_message(net, msg_type, msg);
-- Re-align with the clock when a wait for time message was handled, because this breaks edge alignment.
wait until rising_edge(aclk);
elsif msg_type = notify_request_msg then
-- Ignore this message, but expect it
elsif msg_type = stream_push_msg or msg_type = push_axi_stream_msg then
drive_invalid_output(tdata, tkeep, tstrb, tid, tdest, tuser);
-- stall according to probability configuration
probability_stall_axi_stream(aclk, master, rnd);

tvalid <= '1';
tdata <= pop_std_ulogic_vector(msg);
if msg_type = push_axi_stream_msg then
tlast <= pop_std_ulogic(msg);
tkeep <= pop_std_ulogic_vector(msg);
tstrb <= pop_std_ulogic_vector(msg);
tid <= pop_std_ulogic_vector(msg);
tdest <= pop_std_ulogic_vector(msg);
tuser <= pop_std_ulogic_vector(msg);
else
tlast <= '0';
if pop_boolean(msg) then
tlast <= '1';
else
tlast <= '0';
end if;
tkeep <= (others => '1');
tstrb <= (others => '1');
tid <= (others => '0');
tdest <= (others => '0');
tuser <= (others => '0');
end if;
tkeep <= (others => '1');
tstrb <= (others => '1');
tid <= (others => '0');
tdest <= (others => '0');
tuser <= (others => '0');
wait until ((tvalid and tready) = '1' or areset_n = '0') and rising_edge(aclk);
tvalid <= '0';
tlast <= '0';
else
unexpected_msg_type(msg_type);
end if;
wait until ((tvalid and tready) = '1' or areset_n = '0') and rising_edge(aclk);
tvalid <= '0';
tlast <= '0';
else
unexpected_msg_type(msg_type);
end if;

delete(msg);
end loop;

notify_bus_process_done <= '1';
wait until notify_bus_process_done = '1';
notify_bus_process_done <= '0';
end if;

delete(msg);
end loop;

notify_bus_process_done <= '1';
wait until notify_bus_process_done = '1';
notify_bus_process_done <= '0';
end if;
end loop;
end process;

axi_stream_monitor_generate : if master.p_monitor /= null_axi_stream_monitor generate
Expand Down Expand Up @@ -171,4 +194,4 @@ begin
);
end generate axi_stream_protocol_checker_generate;

end architecture;
end architecture;
41 changes: 40 additions & 1 deletion vunit/vhdl/verification_components/src/axi_stream_pkg.vhd
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,18 @@ context work.data_types_context;

package axi_stream_pkg is

type stall_config_t is record
stall_probability : real range 0.0 to 1.0;
min_stall_cycles : natural;
max_stall_cycles : natural;
end record;

constant null_stall_config : stall_config_t := (
stall_probability => 0.0,
min_stall_cycles => 0,
max_stall_cycles => 0
);

type axi_stream_component_type_t is (null_component, default_component, custom_component);

type axi_stream_protocol_checker_t is record
Expand Down Expand Up @@ -99,6 +111,7 @@ package axi_stream_pkg is
p_id_length : natural;
p_dest_length : natural;
p_user_length : natural;
p_stall_config : stall_config_t;
p_logger : logger_t;
p_monitor : axi_stream_monitor_t;
p_protocol_checker : axi_stream_protocol_checker_t;
Expand All @@ -110,6 +123,7 @@ package axi_stream_pkg is
p_id_length : natural;
p_dest_length : natural;
p_user_length : natural;
p_stall_config : stall_config_t;
p_logger : logger_t;
p_monitor : axi_stream_monitor_t;
p_protocol_checker : axi_stream_protocol_checker_t;
Expand All @@ -123,6 +137,7 @@ package axi_stream_pkg is
id_length : natural := 0;
dest_length : natural := 0;
user_length : natural := 0;
stall_config : stall_config_t := null_stall_config;
logger : logger_t := axi_stream_logger;
actor : actor_t := null_actor;
monitor : axi_stream_monitor_t := null_axi_stream_monitor;
Expand All @@ -134,6 +149,7 @@ package axi_stream_pkg is
id_length : natural := 0;
dest_length : natural := 0;
user_length : natural := 0;
stall_config : stall_config_t := null_stall_config;
logger : logger_t := axi_stream_logger;
actor : actor_t := null_actor;
monitor : axi_stream_monitor_t := null_axi_stream_monitor;
Expand Down Expand Up @@ -285,6 +301,12 @@ package axi_stream_pkg is
variable msg : inout msg_t;
variable axi_transaction : out axi_stream_transaction_t);

function new_stall_config(
stall_probability : real range 0.0 to 1.0;
min_stall_cycles : natural;
max_stall_cycles : natural
) return stall_config_t;

end package;

package body axi_stream_pkg is
Expand Down Expand Up @@ -343,6 +365,7 @@ package body axi_stream_pkg is
id_length : natural := 0;
dest_length : natural := 0;
user_length : natural := 0;
stall_config : stall_config_t := null_stall_config;
logger : logger_t := axi_stream_logger;
actor : actor_t := null_actor;
monitor : axi_stream_monitor_t := null_axi_stream_monitor;
Expand All @@ -361,6 +384,7 @@ package body axi_stream_pkg is
p_id_length => id_length,
p_dest_length => dest_length,
p_user_length => user_length,
p_stall_config => stall_config,
p_logger => logger,
p_monitor => p_monitor,
p_protocol_checker => p_protocol_checker);
Expand All @@ -371,6 +395,7 @@ package body axi_stream_pkg is
id_length : natural := 0;
dest_length : natural := 0;
user_length : natural := 0;
stall_config : stall_config_t := null_stall_config;
logger : logger_t := axi_stream_logger;
actor : actor_t := null_actor;
monitor : axi_stream_monitor_t := null_axi_stream_monitor;
Expand All @@ -384,11 +409,12 @@ package body axi_stream_pkg is
p_actor := actor when actor /= null_actor else new_actor;
p_protocol_checker := get_valid_protocol_checker(data_length, id_length, dest_length, user_length, logger, actor, protocol_checker, "slave");

return (p_actor => new_actor,
return (p_actor => p_actor,
p_data_length => data_length,
p_id_length => id_length,
eine marked this conversation as resolved.
Show resolved Hide resolved
p_dest_length => dest_length,
p_user_length => user_length,
p_stall_config => stall_config,
p_logger => logger,
p_monitor => p_monitor,
p_protocol_checker => p_protocol_checker);
Expand Down Expand Up @@ -780,4 +806,17 @@ package body axi_stream_pkg is
end if;
end;

function new_stall_config(
stall_probability : real range 0.0 to 1.0;
min_stall_cycles : natural;
max_stall_cycles : natural) return stall_config_t is
variable stall_config : stall_config_t;
begin
stall_config := (
stall_probability => stall_probability,
min_stall_cycles => min_stall_cycles,
max_stall_cycles => max_stall_cycles);
return stall_config;
end;

end package body;
68 changes: 68 additions & 0 deletions vunit/vhdl/verification_components/src/axi_stream_private_pkg.vhd
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
-- This Source Code Form is subject to the terms of the Mozilla Public
-- License, v. 2.0. If a copy of the MPL was not distributed with this file,
-- You can obtain one at http://mozilla.org/MPL/2.0/.
--
-- Copyright (c) 2014-2020, Lars Asplund lars.anders.asplund@gmail.com

library ieee;
use ieee.std_logic_1164.all;

library osvvm;
use osvvm.RandomPkg.RandomPType;

use work.axi_stream_pkg.all;

package axi_stream_private_pkg is
procedure probability_stall_axi_stream(
signal aclk : in std_logic;
axi_stream : in axi_stream_slave_t;
rnd : inout RandomPType
);

procedure probability_stall_axi_stream(
signal aclk : in std_logic;
axi_stream : in axi_stream_master_t;
rnd : inout RandomPType
);

procedure probability_stall_axi_stream(
signal aclk : in std_logic;
stall_config : in stall_config_t;
rnd : inout RandomPType
);

end package;

package body axi_stream_private_pkg is

procedure probability_stall_axi_stream(
signal aclk : in std_logic;
axi_stream : in axi_stream_master_t;
rnd : inout RandomPType) is
begin
probability_stall_axi_stream(aclk, axi_stream.p_stall_config, rnd);
end procedure;

procedure probability_stall_axi_stream(
signal aclk : in std_logic;
axi_stream : in axi_stream_slave_t;
rnd : inout RandomPType) is
begin
probability_stall_axi_stream(aclk, axi_stream.p_stall_config, rnd);
end procedure;

procedure probability_stall_axi_stream(
signal aclk : in std_logic;
stall_config : in stall_config_t;
rnd : inout RandomPType) is
variable num_stall_cycles : natural := 0;
begin
if rnd.Uniform(0.0, 1.0) < stall_config.stall_probability then
num_stall_cycles := rnd.FavorSmall(stall_config.min_stall_cycles, stall_config.max_stall_cycles);
end if;
for stall in 0 to num_stall_cycles-1 loop
wait until rising_edge(aclk);
end loop;
end procedure;

end package body;
Loading