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

Make dict_t type generic #835

Merged
merged 4 commits into from
May 31, 2022
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
10 changes: 5 additions & 5 deletions docs/conf.py
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@
version = ""
release = ""

language = None
language = "en"

exclude_patterns = ["release_notes/*.*"]

Expand Down Expand Up @@ -92,8 +92,8 @@
# -- ExtLinks -------------------------------------------------------------

extlinks = {
"vunit_example": ("https://github.com/VUnit/vunit/tree/master/examples/%s/", ""),
"vunit_file": ("https://github.com/VUnit/vunit/tree/master/%s/", ""),
"vunit_commit": ("https://github.com/vunit/vunit/tree/%s/", "@"),
"vunit_issue": ("https://github.com/VUnit/vunit/issues/%s/", "#"),
"vunit_example": ("https://github.com/VUnit/vunit/tree/master/examples/%s/", "%s"),
"vunit_file": ("https://github.com/VUnit/vunit/tree/master/%s/", "%s"),
"vunit_commit": ("https://github.com/vunit/vunit/tree/%s/", "@%s"),
"vunit_issue": ("https://github.com/VUnit/vunit/issues/%s/", "#%s"),
}
107 changes: 107 additions & 0 deletions examples/vhdl/data_types/tb_dict_transactions.vhd
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
-- 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-2022, Lars Asplund lars.anders.asplund@gmail.com

library vunit_lib;
context vunit_lib.vunit_context;
context vunit_lib.data_types_context;

library ieee;
use ieee.std_logic_1164.all;

library osvvm;
use osvvm.RandomPkg.all;

entity tb_dict_transactions is
generic (
runner_cfg : string);
end entity;

architecture a of tb_dict_transactions is
-- Dicts are references to data. These references can be declared as global constants to make
-- the dict accessible to any process. We're not saying that different processes communicating
-- through a global variable / shared dict is always a good thing to do, but it's possible.
constant global : dict_t := new_dict;

-- Queues can also be shared as global constants. This will enable another and safer mode of
-- sharing dicts as we will see later on
constant transaction_queue : queue_t := new_queue;

signal clk : std_logic := '0';
begin
test_runner : process
begin
test_runner_setup(runner, runner_cfg);

-- Here we're using the global dict as a way to figure out when the test is finished
-- and can be terminated. This works because the pending transactions value is set
-- to 10 before the first rising edge of clk. Global dicts can easily lead to
-- data races if one is not careful. There are better ways to signal completion but this
-- is an example of dicts so that's why we're using it.
wait until rising_edge(clk) and get(global, "pending transactions") = 0;

test_runner_cleanup(runner);
end process;

transaction_producer : process
variable transaction : dict_t;
variable rnd : RandomPType;
begin
-- There is one overloaded set procedure for each type. You can also use the type specific alias,
-- in this case set_integer. Type specific aliases also exist for the get functions, get_integer for example.
set(global, "pending transactions", rnd.RandInt(10, 100));

generate_random_read_and_write_transactions: for i in 1 to get(global, "pending transactions") loop
-- Dicts can contain a mix of data types. In this case the dict represents a bus initiator
-- read or write transaction. All transactions have an integer address and write transactions
-- also have a std_ulogic_vector data word.
transaction := new_dict;
set(transaction, "address", rnd.RandInt(0, 2 ** 20 - 1));
if rnd.RandBool then
set(transaction, "data", rnd.RandSlv(32));
end if;

-- Dicts can be used with other complex data types, for example pushed into a queue. push_ref
-- will set the transaction to null_dict which means that the ownership of the data is handed
-- over to the consumer. By having only one owner of the dict at any time we avoid the data race
-- risk associated with shared data like the global dict
push_ref(transaction_queue, transaction);
end loop;
wait;
end process;

transaction_consumer : process
variable transaction : dict_t;
variable address : natural;
begin
wait until rising_edge(clk) and not is_empty(transaction_queue);

transaction := pop_ref(transaction_queue);

-- dicts are type safe. If one tries to read the address as a std_ulogic_vector the result is an error:
--
-- "Stored value for address is of type integer but get function for std_ulogic_vector was called.
--
-- It's also possible to be explicit by using get_integer
address := get(transaction, "address");

if has_key(transaction, "data") then
info("Writing 0x" & to_hstring(get_std_ulogic_vector(transaction, "data")) & " to address " & to_string(address));

-- Handle write transaction

else
info("Reading from address " & to_string(address));

-- Handle read transaction

end if;

set(global, "pending transactions", get(global, "pending transactions") - 1);
deallocate(transaction); -- Garbage collection
end process;

clk <= not clk after 1 ns;
end architecture;
17 changes: 17 additions & 0 deletions vunit/vhdl/com/src/com_types.vhd
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ use work.logger_pkg.all;
use work.queue_pkg.all;
use work.queue_2008p_pkg.all;
use work.queue_pool_pkg.all;
use work.dict_pkg.all;

package com_types_pkg is

Expand Down Expand Up @@ -394,6 +395,11 @@ package com_types_pkg is
alias push_integer_array_t_ref is push_ref[msg_t, integer_array_t];
alias pop_integer_array_t_ref is pop_ref[msg_t return integer_array_t];

procedure push_ref(constant msg : msg_t; value : inout dict_t);
impure function pop_ref(msg : msg_t) return dict_t;
alias push_dict_t_ref is push_ref[msg_t, dict_t];
alias pop_dict_t_ref is pop_ref[msg_t return dict_t];

end package;

package body com_types_pkg is
Expand Down Expand Up @@ -854,4 +860,15 @@ package body com_types_pkg is
return pop_ref(msg.data);
end;

procedure push_ref(constant msg : msg_t; value : inout dict_t) is
begin
push_ref(msg.data, value);
end;

impure function pop_ref(msg : msg_t) return dict_t is
begin
return pop_ref(msg.data);
end;


end package body com_types_pkg;
9 changes: 9 additions & 0 deletions vunit/vhdl/com/test/tb_com_msg_building.vhd
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ context vunit_lib.com_context;
use vunit_lib.queue_pkg.all;
use vunit_lib.integer_vector_ptr_pkg.all;
use vunit_lib.integer_array_pkg.all;
use vunit_lib.dict_pkg.all;

library ieee;
use ieee.std_logic_1164.all;
Expand Down Expand Up @@ -39,6 +40,7 @@ begin
variable boolv : boolean_vector(0 to 1);
variable integer_vector_ptr, integer_vector_ptr_copy : integer_vector_ptr_t;
variable integer_array, integer_array_copy : integer_array_t;
variable dict : dict_t;

constant my_msg_type : msg_type_t := new_msg_type("my msg type");
begin
Expand Down Expand Up @@ -268,6 +270,13 @@ begin
push_integer_array_t_ref(msg, integer_array);
check(integer_array = null_integer_array);
check(pop_integer_array_t_ref(msg) = integer_array_copy);
elsif run("Test push and pop of dict_t") then
msg := new_msg;
dict := new_dict;
set_integer(dict, "key", 17);
push_dict_t_ref(msg, dict);
check(dict = null_dict);
check_equal(get_integer(pop_dict_t_ref(msg), "key"), 17);
elsif run("Test push and pop of msg_t") then
msg := new_msg;
msg2 := new_msg;
Expand Down
27 changes: 27 additions & 0 deletions vunit/vhdl/data_types/src/data_types_private_pkg.vhd
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
-- 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-2022, Lars Asplund lars.anders.asplund@gmail.com

use work.string_ops.all;

package data_types_private_pkg is
type data_type_t is (
vhdl_character, vhdl_integer, vunit_byte, vhdl_string, vhdl_boolean, vhdl_real, vhdl_bit, ieee_std_ulogic,
vhdl_severity_level, vhdl_file_open_status, vhdl_file_open_kind, vhdl_bit_vector, ieee_std_ulogic_vector,
ieee_complex, ieee_complex_polar, ieee_numeric_bit_unsigned, ieee_numeric_bit_signed,
ieee_numeric_std_unsigned, ieee_numeric_std_signed, vhdl_time, vunit_integer_vector_ptr_t,
vunit_string_ptr_t, vunit_queue_t, vunit_integer_array_t, vhdl_boolean_vector, vhdl_integer_vector,
vhdl_real_vector, vhdl_time_vector, ieee_ufixed, ieee_sfixed, ieee_float, vunit_dict_t
);

impure function to_string(data_type : data_type_t) return string;
end package;

package body data_types_private_pkg is
impure function to_string(data_type : data_type_t) return string is
begin
return split(data_type_t'image(data_type), "_", 1)(1).all;
end;
end package body;
Loading