Skip to content

Commit

Permalink
Add response latency to axi slaves
Browse files Browse the repository at this point in the history
  • Loading branch information
kraigher committed Apr 25, 2018
1 parent e67ac7c commit d4c0b6a
Show file tree
Hide file tree
Showing 8 changed files with 359 additions and 42 deletions.
102 changes: 88 additions & 14 deletions vunit/vhdl/verification_components/src/axi_pkg.vhd
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ package axi_pkg is
constant axi_burst_type_wrap : axi_burst_type_t := "10";

subtype axi4_len_t is std_logic_vector(7 downto 0);
constant max_axi4_burst_length : natural := 2**axi4_len_t'length;
subtype axi4_size_t is std_logic_vector(2 downto 0);

subtype probability_t is real range 0.0 to 1.0;
Expand All @@ -37,6 +38,8 @@ package axi_pkg is
p_initial_address_stall_probability : probability_t;
p_initial_data_stall_probability : probability_t;
p_initial_write_response_stall_probability : probability_t;
p_initial_min_response_latency : delay_length;
p_initial_max_response_latency : delay_length;
p_actor : actor_t;
p_memory : memory_t;
p_logger : logger_t;
Expand All @@ -50,28 +53,61 @@ package axi_pkg is
address_stall_probability : probability_t := 0.0;
data_stall_probability : probability_t := 0.0;
write_response_stall_probability : probability_t := 0.0;
min_response_latency : delay_length := 0 ns;
max_response_latency : delay_length := 0 ns;
logger : logger_t := axi_slave_logger) return axi_slave_t;

-- Set the maximum number address channel tokens that can be queued
procedure set_address_fifo_depth(signal net : inout network_t; axi_slave : axi_slave_t; depth : positive);
procedure set_address_fifo_depth(signal net : inout network_t;
axi_slave : axi_slave_t;
depth : positive);

-- Set the maximum number write responses that can be queued
procedure set_write_response_fifo_depth(signal net : inout network_t; axi_slave : axi_slave_t; depth : positive);
procedure set_write_response_fifo_depth(signal net : inout network_t;
axi_slave : axi_slave_t;
depth : positive);

-- Set the address channel stall probability
procedure set_address_stall_probability(signal net : inout network_t; axi_slave : axi_slave_t;
procedure set_address_stall_probability(signal net : inout network_t;
axi_slave : axi_slave_t;
probability : probability_t);

-- Set the data channel stall probability
procedure set_data_stall_probability(signal net : inout network_t; axi_slave : axi_slave_t;
procedure set_data_stall_probability(signal net : inout network_t;
axi_slave : axi_slave_t;
probability : probability_t);

-- Set the write response stall probability
procedure set_write_response_stall_probability(signal net : inout network_t; axi_slave : axi_slave_t;
procedure set_write_response_stall_probability(signal net : inout network_t;
axi_slave : axi_slave_t;
probability : probability_t);

procedure enable_4kbyte_boundary_check(signal net : inout network_t; axi_slave : axi_slave_t);
procedure disable_4kbyte_boundary_check(signal net : inout network_t; axi_slave : axi_slave_t);
-- Set the response latency
--
-- For a write slave this is the time between the last write data
-- and providing the write reponse. All write data is written to the
-- memory model right before providing write response.
-- Data address and expected value is still checked as soons as it arrives to
-- the axi slave and is not delayed until the write response time.
--
-- For a read slave this is the time between the read burst arrival and the
-- first provided read data
--
-- The response latency is randomly choosen in the uniform interval:
-- [min_latency, max_latency]
procedure set_response_latency(signal net : inout network_t;
axi_slave : axi_slave_t;
min_latency, max_latency : delay_length);

-- Short hand for set_response_latency when min and max are the same
procedure set_response_latency(signal net : inout network_t;
axi_slave : axi_slave_t;
latency : delay_length);

procedure enable_4kbyte_boundary_check(signal net : inout network_t;
axi_slave : axi_slave_t);
procedure disable_4kbyte_boundary_check(signal net : inout network_t;
axi_slave : axi_slave_t);

-- Check that bursts are well behaved, that is that data channel traffic is
-- as compact as possible
Expand All @@ -87,11 +123,15 @@ package axi_pkg is
-- 2. uses max arsize supported by data width
procedure enable_well_behaved_check(signal net : inout network_t; axi_slave : axi_slave_t);



-- Private constants
constant axi_slave_set_address_fifo_depth_msg : msg_type_t := new_msg_type("axi slave set address channel fifo depth");
constant axi_slave_set_write_response_fifo_depth_msg : msg_type_t := new_msg_type("set write response fifo depth");
constant axi_slave_set_address_stall_probability_msg : msg_type_t := new_msg_type("axi slave set address channel stall probability");
constant axi_slave_set_data_stall_probability_msg : msg_type_t := new_msg_type("axi slave set data stall probability");
constant axi_slave_set_write_response_stall_probability_msg : msg_type_t := new_msg_type("axi slave set write response stall probability");
constant axi_slave_set_response_latency_msg : msg_type_t := new_msg_type("axi slave response latency probability");
constant axi_slave_configure_4kbyte_boundary_check_msg : msg_type_t := new_msg_type("axi slave configure 4kbyte boundary check");
constant axi_slave_enable_well_behaved_check_msg : msg_type_t := new_msg_type("axi slave enable well behaved check");

Expand All @@ -105,6 +145,8 @@ package body axi_pkg is
address_stall_probability : probability_t := 0.0;
data_stall_probability : probability_t := 0.0;
write_response_stall_probability : probability_t := 0.0;
min_response_latency : delay_length := 0 ns;
max_response_latency : delay_length := 0 ns;
logger : logger_t := axi_slave_logger) return axi_slave_t is
begin
return (p_actor => new_actor,
Expand All @@ -114,11 +156,15 @@ package body axi_pkg is
p_initial_address_stall_probability => address_stall_probability,
p_initial_data_stall_probability => data_stall_probability,
p_initial_write_response_stall_probability => write_response_stall_probability,
p_initial_min_response_latency => min_response_latency,
p_initial_max_response_latency => max_response_latency,
p_memory => to_vc_interface(memory, logger),
p_logger => logger);
end;

procedure set_address_fifo_depth(signal net : inout network_t; axi_slave : axi_slave_t; depth : positive) is
procedure set_address_fifo_depth(signal net : inout network_t;
axi_slave : axi_slave_t;
depth : positive) is
variable request_msg : msg_t;
variable ack : boolean;
begin
Expand All @@ -128,7 +174,9 @@ package body axi_pkg is
assert ack report "Failed on set_address_fifo_depth command";
end;

procedure set_write_response_fifo_depth(signal net : inout network_t; axi_slave : axi_slave_t; depth : positive) is
procedure set_write_response_fifo_depth(signal net : inout network_t;
axi_slave : axi_slave_t;
depth : positive) is
variable request_msg : msg_t;
variable ack : boolean;
begin
Expand All @@ -138,7 +186,8 @@ package body axi_pkg is
assert ack report "Failed on set_write_response_fifo_depth command";
end;

procedure set_address_stall_probability(signal net : inout network_t; axi_slave : axi_slave_t;
procedure set_address_stall_probability(signal net : inout network_t;
axi_slave : axi_slave_t;
probability : probability_t) is
variable request_msg : msg_t;
variable ack : boolean;
Expand All @@ -149,7 +198,8 @@ package body axi_pkg is
assert ack report "Failed on set_address_stall_probability command";
end;

procedure set_data_stall_probability(signal net : inout network_t; axi_slave : axi_slave_t;
procedure set_data_stall_probability(signal net : inout network_t;
axi_slave : axi_slave_t;
probability : probability_t) is
variable request_msg : msg_t;
variable ack : boolean;
Expand Down Expand Up @@ -183,17 +233,41 @@ package body axi_pkg is
assert ack report "Failed on configure_4kbyte_boundary_check command";
end;

procedure enable_4kbyte_boundary_check(signal net : inout network_t; axi_slave : axi_slave_t) is
procedure set_response_latency(signal net : inout network_t;
axi_slave : axi_slave_t;
min_latency, max_latency : delay_length) is
variable request_msg : msg_t;
variable ack : boolean;
begin
request_msg := new_msg(axi_slave_set_response_latency_msg);
push_time(request_msg, min_latency);
push_time(request_msg, max_latency);
request(net, axi_slave.p_actor, request_msg, ack);
assert ack report "Failed on set_response_latency command";
end;

-- Short hand for set_response_latency when min and max are the same
procedure set_response_latency(signal net : inout network_t;
axi_slave : axi_slave_t;
latency : delay_length) is
begin
set_response_latency(net, axi_slave, latency, latency);
end;

procedure enable_4kbyte_boundary_check(signal net : inout network_t;
axi_slave : axi_slave_t) is
begin
configure_4kbyte_boundary_check(net, axi_slave, true);
end;

procedure disable_4kbyte_boundary_check(signal net : inout network_t; axi_slave : axi_slave_t) is
procedure disable_4kbyte_boundary_check(signal net : inout network_t;
axi_slave : axi_slave_t) is
begin
configure_4kbyte_boundary_check(net, axi_slave, false);
end;

procedure enable_well_behaved_check(signal net : inout network_t; axi_slave : axi_slave_t) is
procedure enable_well_behaved_check(signal net : inout network_t;
axi_slave : axi_slave_t) is
variable request_msg : msg_t;
variable ack : boolean;
begin
Expand Down
58 changes: 55 additions & 3 deletions vunit/vhdl/verification_components/src/axi_private_pkg.vhd
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,8 @@ package axi_private_pkg is
procedure set_address_stall_probability(probability : probability_t);
procedure set_data_stall_probability(probability : probability_t);
procedure set_write_response_stall_probability(probability : probability_t);
procedure set_min_response_latency(latency : delay_length);
procedure set_max_response_latency(latency : delay_length);
procedure set_check_4kbyte_boundary(value : boolean);
procedure enable_well_behaved_check;
impure function should_check_well_behaved return boolean;
Expand Down Expand Up @@ -80,6 +82,9 @@ package axi_private_pkg is

procedure finish_burst(burst : axi_burst_t);

procedure push_random_response_time;
impure function pop_response_time return time;

procedure fail(msg : string);
procedure check_4kbyte_boundary(burst : axi_burst_t);
impure function data_size return integer;
Expand All @@ -101,7 +106,6 @@ package body axi_private_pkg is

procedure push_axi_burst(queue : queue_t; burst : axi_burst_t);
impure function pop_axi_burst(queue : queue_t) return axi_burst_t;
constant qlen_per_burst : natural := 4*5+1;

type axi_slave_private_t is protected body
variable p_axi_slave : axi_slave_t;
Expand All @@ -111,13 +115,18 @@ package body axi_private_pkg is
variable p_id_indexes : integer_vector_ptr_t;
variable p_burst_queue_max_length : natural;
variable p_burst_queue : queue_t;
variable p_burst_queue_length : natural;
variable p_resp_queue_max_length : natural;
variable p_resp_queue : queue_t;
variable p_resp_queue_length : natural;
variable p_check_4kbyte_boundary : boolean;
variable p_rnd : RandomPType;
variable p_addr_stall_prob : probability_t;
variable p_data_stall_prob : probability_t;
variable p_wresp_stall_prob : probability_t;
variable p_min_response_latency : delay_length;
variable p_max_response_latency : delay_length;
variable p_response_time_queue : queue_t;
variable p_check_well_behaved : boolean;

procedure init(axi_slave : axi_slave_t;
Expand All @@ -132,13 +141,18 @@ package body axi_private_pkg is
p_id_indexes := new_integer_vector_ptr(length => max_id+1, value => 0);
p_burst_queue_max_length := axi_slave.p_initial_address_fifo_depth;
p_burst_queue := new_queue;
p_burst_queue_length := 0;
p_resp_queue_max_length := axi_slave.p_initial_write_response_fifo_depth;
p_resp_queue := new_queue;
p_resp_queue_length := 0;
p_check_4kbyte_boundary := axi_slave.p_initial_check_4kbyte_boundary;
p_check_well_behaved := false;
set_address_stall_probability(axi_slave.p_initial_address_stall_probability);
set_data_stall_probability(axi_slave.p_initial_data_stall_probability);
set_write_response_stall_probability(axi_slave.p_initial_write_response_stall_probability);
p_response_time_queue := new_queue;
set_min_response_latency(axi_slave.p_initial_min_response_latency);
set_max_response_latency(axi_slave.p_initial_max_response_latency);
end;

impure function get_actor return actor_t is
Expand Down Expand Up @@ -181,6 +195,16 @@ package body axi_private_pkg is
p_wresp_stall_prob := probability;
end;

procedure set_min_response_latency(latency : delay_length) is
begin
p_min_response_latency := latency;
end;

procedure set_max_response_latency(latency : delay_length) is
begin
p_max_response_latency := latency;
end;

procedure set_check_4kbyte_boundary(value : boolean) is
begin
p_check_4kbyte_boundary := value;
Expand Down Expand Up @@ -291,6 +315,7 @@ package body axi_private_pkg is
procedure push_burst(burst : axi_burst_t) is
begin
push_axi_burst(p_burst_queue, burst);
p_burst_queue_length := p_burst_queue_length + 1;
end;

impure function pop_burst return axi_burst_t is
Expand All @@ -306,6 +331,7 @@ package body axi_private_pkg is
"Start providing data for read burst " & describe_burst(burst));
end case;
end if;
p_burst_queue_length := p_burst_queue_length - 1;
return burst;
end;

Expand All @@ -321,12 +347,13 @@ package body axi_private_pkg is

impure function burst_queue_length return natural is
begin
return length(p_burst_queue)/qlen_per_burst;
return p_burst_queue_length;
end;

procedure push_resp(burst : axi_burst_t) is
begin
push_axi_burst(p_resp_queue, burst);
p_resp_queue_length := p_resp_queue_length + 1;
end;

impure function pop_resp return axi_burst_t is
Expand All @@ -336,6 +363,7 @@ package body axi_private_pkg is
debug(p_axi_slave.p_logger,
"Providing write response for burst " & describe_burst(resp_burst));
end if;
p_resp_queue_length := p_resp_queue_length - 1;
return resp_burst;
end;

Expand All @@ -353,6 +381,25 @@ package body axi_private_pkg is
end if;
end;

impure function random_response_latency return delay_length is
begin
if p_min_response_latency = p_max_response_latency then
return p_min_response_latency;
else
return p_rnd.RandTime(p_min_response_latency, p_max_response_latency);
end if;
end;

procedure push_random_response_time is
begin
push_time(p_response_time_queue, now + random_response_latency);
end;

impure function pop_response_time return time is
begin
return pop_time(p_response_time_queue);
end;

impure function resp_queue_full return boolean is
begin
return resp_queue_length = p_resp_queue_max_length;
Expand All @@ -365,7 +412,7 @@ package body axi_private_pkg is

impure function resp_queue_length return natural is
begin
return length(p_resp_queue)/qlen_per_burst;
return p_resp_queue_length;
end;

procedure fail(msg : string) is
Expand Down Expand Up @@ -455,6 +502,11 @@ package body axi_private_pkg is
self.set_write_response_stall_probability(pop_real(request_msg));
acknowledge(net, request_msg, true);

elsif msg_type = axi_slave_set_response_latency_msg then
self.set_min_response_latency(pop_time(request_msg));
self.set_max_response_latency(pop_time(request_msg));
acknowledge(net, request_msg, true);

elsif msg_type = axi_slave_configure_4kbyte_boundary_check_msg then
self.set_check_4kbyte_boundary(pop_boolean(request_msg));
acknowledge(net, request_msg, true);
Expand Down
Loading

0 comments on commit d4c0b6a

Please sign in to comment.