diff --git a/vunit/vhdl/com/run.py b/vunit/vhdl/com/run.py index fc204cf66..7a01bcff7 100644 --- a/vunit/vhdl/com/run.py +++ b/vunit/vhdl/com/run.py @@ -13,7 +13,4 @@ prj.add_com() tb_com_lib = prj.add_library("tb_com_lib") tb_com_lib.add_source_files(join(root, 'test', '*.vhd')) -pkg = tb_com_lib.package('custom_types_pkg') -pkg.generate_codecs(codec_package_name='custom_codec_pkg', used_packages=['ieee.std_logic_1164', 'constants_pkg', - 'tb_com_lib.more_constants_pkg']) prj.main() diff --git a/vunit/vhdl/com/src/com.vhd b/vunit/vhdl/com/src/com.vhd index 0ca05ab2a..d8d712eaf 100644 --- a/vunit/vhdl/com/src/com.vhd +++ b/vunit/vhdl/com/src/com.vhd @@ -13,7 +13,6 @@ context work.vunit_context; use work.queue_pkg.all; use work.queue_2008_pkg.all; -use work.queue_pool_pkg.all; use work.integer_vector_ptr_pkg.all; use work.string_ptr_pkg.all; use work.codec_pkg.all; @@ -233,7 +232,6 @@ package body com_pkg is variable status : com_status_t; variable source_actor : actor_t; variable mailbox : mailbox_id_t; - variable message : message_ptr_t; begin delete(reply_msg); @@ -252,7 +250,7 @@ package body com_pkg is wait_on_subscribers(sender, (published, outbound), timeout); messenger.publish(sender, msg, (published, outbound)); notify(net); - recycle(queue_pool, msg.data); + deallocate(msg.data); end; impure function peek_message( @@ -266,8 +264,7 @@ package body com_pkg is return msg; end if; - msg := messenger.get_all_but_payload(actor, position, mailbox_id); - msg.data := decode(messenger.get_payload(actor, position, mailbox_id)); + msg := messenger.get_message(actor, position, mailbox_id); return msg; end; @@ -374,8 +371,7 @@ package body com_pkg is begin started_with_full_mailbox := messenger.is_full(actor, mailbox_id); - msg := messenger.get_all_but_payload(actor, position, mailbox_id); - msg.data := decode(messenger.get_payload(actor, position, mailbox_id)); + msg := messenger.get_message(actor, position, mailbox_id); messenger.delete_envelope(actor, position, mailbox_id); if started_with_full_mailbox then @@ -683,17 +679,4 @@ package body com_pkg is return l.all; end; - ----------------------------------------------------------------------------- - -- Misc - ----------------------------------------------------------------------------- - procedure allow_timeout is - begin - messenger.allow_timeout; - end; - - procedure allow_deprecated is - begin - messenger.allow_deprecated; - end; - end package body com_pkg; diff --git a/vunit/vhdl/com/src/com_api.vhd b/vunit/vhdl/com/src/com_api.vhd index dfc5ba26b..85f4c3f95 100644 --- a/vunit/vhdl/com/src/com_api.vhd +++ b/vunit/vhdl/com/src/com_api.vhd @@ -267,15 +267,4 @@ package com_pkg is -- Return string representation of the messenger state impure function get_messenger_state_string(indent : string := "") return string; - ----------------------------------------------------------------------------- - -- Misc - ----------------------------------------------------------------------------- - - -- Allow deprecated APIs - procedure allow_deprecated; - - -- Allow timeout in deprecated functionality. If not allowed timeouts will - -- cause a runtime error. - procedure allow_timeout; - end package; diff --git a/vunit/vhdl/com/src/com_common.vhd b/vunit/vhdl/com/src/com_common.vhd index 3078f0b89..4fca0e197 100644 --- a/vunit/vhdl/com/src/com_common.vhd +++ b/vunit/vhdl/com/src/com_common.vhd @@ -17,7 +17,7 @@ package com_common_pkg is procedure notify (signal net : inout network_t); - impure function no_error_status (status : com_status_t; old_api : boolean := false) return boolean; + impure function no_error_status (status : com_status_t) return boolean; end package com_common_pkg; package body com_common_pkg is @@ -30,9 +30,9 @@ package body com_common_pkg is end if; end procedure notify; - impure function no_error_status (status : com_status_t; old_api : boolean := false) return boolean is + impure function no_error_status (status : com_status_t) return boolean is begin - return (status = ok) or ((status = timeout) and messenger.timeout_is_allowed and old_api); + return status = ok; end; end package body com_common_pkg; diff --git a/vunit/vhdl/com/src/com_context.vhd b/vunit/vhdl/com/src/com_context.vhd index 6764b0f09..9e6a52be2 100644 --- a/vunit/vhdl/com/src/com_context.vhd +++ b/vunit/vhdl/com/src/com_context.vhd @@ -10,10 +10,7 @@ context com_context is use vunit_lib.com_types_pkg.all; use vunit_lib.codec_pkg.all; use vunit_lib.codec_2008_pkg.all; - use vunit_lib.com_string_pkg.all; use vunit_lib.codec_builder_pkg.all; use vunit_lib.codec_builder_2008_pkg.all; - use vunit_lib.com_debug_codec_builder_pkg.all; - use vunit_lib.com_deprecated_pkg.all; use vunit_lib.com_common_pkg.all; end context; diff --git a/vunit/vhdl/com/src/com_debug_codec_builder.vhd b/vunit/vhdl/com/src/com_debug_codec_builder.vhd deleted file mode 100644 index 8720f8956..000000000 --- a/vunit/vhdl/com/src/com_debug_codec_builder.vhd +++ /dev/null @@ -1,294 +0,0 @@ --- This package contains support functions for debug codec building --- --- 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-2019, Lars Asplund lars.anders.asplund@gmail.com - -library vunit_lib; -context vunit_lib.vunit_context; - -use std.textio.all; - -package com_debug_codec_builder_pkg is - ----------------------------------------------------------------------------- - -- Encoding support - ----------------------------------------------------------------------------- - procedure open_group ( - variable l : inout line); - procedure append_group ( - variable l : inout line; - constant element : in string); - procedure close_group ( - variable l : inout line; - variable code : out string; - variable length : out natural); - function create_group ( - constant num_of_elements : natural range 0 to 10; - constant element1 : string := ""; - constant element2 : string := ""; - constant element3 : string := ""; - constant element4 : string := ""; - constant element5 : string := ""; - constant element6 : string := ""; - constant element7 : string := ""; - constant element8 : string := ""; - constant element9 : string := ""; - constant element10 : string := "") - return string; - function create_array_group ( - constant arr : string; - constant range_left1 : string; - constant range_right1 : string; - constant is_ascending1 : boolean; - constant range_left2 : string := ""; - constant range_right2 : string := ""; - constant is_ascending2 : boolean := true) - return string; - function escape_special_characters ( - constant data : string) - return string; - - ----------------------------------------------------------------------------- - -- Decoding support - ----------------------------------------------------------------------------- - procedure split_group ( - constant grp : in string; - variable elements : inout lines_t; - constant max_num_of_elements : in natural; - variable length : inout natural); - function get_element ( - constant grp : in string; - constant position : in natural) - return string; - function get_first_element ( - constant grp : string) - return string; - procedure deallocate_elements ( - variable elements : inout lines_t); - function unescape_special_characters ( - constant code : string) - return string; -end package com_debug_codec_builder_pkg; - -package body com_debug_codec_builder_pkg is - ----------------------------------------------------------------------------- - -- Encoding support - ----------------------------------------------------------------------------- - procedure open_group ( - variable l : inout line) is - begin - deallocate(l); - write(l, '('); - end procedure open_group; - - procedure append_group ( - variable l : inout line; - constant element : in string) is - begin - write(l, element & ","); - end procedure append_group; - - procedure close_group ( - variable l : inout line; - variable code : out string; - variable length : out natural) is - variable final : line; - variable line_length : integer; - begin - if l.all /= "(" then - line_length := l.all'length; - write(final, l.all(1 to line_length - 1)); - deallocate(l); - else - final := l; - end if; - write(final, ')'); - length := final.all'length; - code(1 to length) := final.all; - deallocate(final); - end procedure close_group; - - function create_group ( - constant num_of_elements : natural range 0 to 10; - constant element1 : string := ""; - constant element2 : string := ""; - constant element3 : string := ""; - constant element4 : string := ""; - constant element5 : string := ""; - constant element6 : string := ""; - constant element7 : string := ""; - constant element8 : string := ""; - constant element9 : string := ""; - constant element10 : string := "") - return string is - begin - if num_of_elements = 4 then - return "(" & element1 & "," & element2 & "," & element3 & "," & element4 & ")"; - elsif num_of_elements = 3 then - return "(" & element1 & "," & element2 & "," & element3 & ")"; - elsif num_of_elements = 5 then - return "(" & element1 & "," & element2 & "," & element3 & "," & element4 & "," & element5 & ")"; - elsif num_of_elements = 2 then - return "(" & element1 & "," & element2 & ")"; - elsif num_of_elements = 7 then - return "(" & element1 & "," & element2 & "," & element3 & "," & element4 & "," & element5 & "," & element6 & "," & element7 & ")"; - elsif num_of_elements = 1 then - return "(" & element1 & ")"; - elsif num_of_elements = 6 then - return "(" & element1 & "," & element2 & "," & element3 & "," & element4 & "," & element5 & "," & element6 & ")"; - elsif num_of_elements = 8 then - return "(" & element1 & "," & element2 & "," & element3 & "," & element4 & "," & element5 & "," & element6 & "," & element7 & "," & element8 & ")"; - elsif num_of_elements = 9 then - return "(" & element1 & "," & element2 & "," & element3 & "," & element4 & "," & element5 & "," & element6 & "," & element7 & "," & element8 & "," & element9 & ")"; - elsif num_of_elements = 10 then - return "(" & element1 & "," & element2 & "," & element3 & "," & element4 & "," & element5 & "," & element6 & "," & element7 & "," & element8 & "," & element9 & "," & element10 & ")"; - else - return "()"; - end if; - end function create_group; - - function create_array_group ( - constant arr : string; - constant range_left1 : string; - constant range_right1 : string; - constant is_ascending1 : boolean; - constant range_left2 : string := ""; - constant range_right2 : string := ""; - constant is_ascending2 : boolean := true) - return string is - variable ret_val : string(1 to 18 + arr'length + range_left1'length + range_right1'length + - range_left2'length + range_right2'length); - variable l : line; - variable length : natural; - begin - open_group(l); - append_group(l, arr); - append_group(l, range_left1); - append_group(l, range_right1); - append_group(l, to_string(is_ascending1)); - if range_left2 /= "" then - append_group(l, range_left2); - append_group(l, range_right2); - append_group(l, to_string(is_ascending2)); - end if; - close_group(l, ret_val, length); - - return ret_val(1 to length); - end; - - function escape_special_characters ( - constant data : string) - return string is - begin - return replace(replace(replace(data, ')', "\rp"), '(', "\lp"), ',', "\comma"); - end function escape_special_characters; - - ----------------------------------------------------------------------------- - -- Decoding support - ----------------------------------------------------------------------------- - procedure split_group ( - constant grp : in string; - variable elements : inout lines_t; - constant max_num_of_elements : in natural; - variable length : inout natural) is - variable element_start : positive; - variable level : natural := 0; - begin - deallocate_elements(elements); - length := 0; - - if (grp = "()") or -- Empty group - (grp(grp'left) /= '(') or -- Not a valid group - (grp(grp'right) /= ')') then -- Not a valid group - return; - end if; - - elements := new line_vector(0 to max_num_of_elements - 1); - element_start := grp'left + 1; - for i in grp'left + 1 to grp'right loop - if length = max_num_of_elements then - return; - elsif grp(i) = '(' then - level := level + 1; - elsif ((grp(i) = ',') or (i = grp'right)) and (level = 0) then - if grp(i) = ',' then - write(elements.all(length), grp(element_start to i - 1)); - else - write(elements.all(length), grp(element_start to i - 1)); - end if; - - length := length + 1; - element_start := i + 1; - elsif grp(i) = ')' then - level := level - 1; - end if; - end loop; - - if level /= 0 then -- Not a valid group - deallocate_elements(elements); - length := 0; - end if; - - end procedure split_group; - - function get_element ( - constant grp : in string; - constant position : in natural) - return string is - variable elements : lines_t; - variable length : natural; - variable ret_val : string(1 to grp'length); - begin - if grp = "" then - return ""; - end if; - - if grp(grp'left) /= '(' then - if position = 0 then - return grp; - else - return ""; - end if; - end if; - - split_group(grp, elements, position + 1, length); - if length < position + 1 then - return ""; - else - length := elements.all(position).all'length; - ret_val(1 to length) := elements.all(position).all; - deallocate_elements(elements); - return ret_val(1 to length); - end if; - end function get_element; - - function get_first_element ( - constant grp : string) - return string is - begin - return get_element(grp, 0); - end function get_first_element; - - procedure deallocate_elements ( - variable elements : inout lines_t) is - begin - if elements = null then - return; - end if; - - for i in elements.all'range loop - deallocate(elements.all(i)); - end loop; - deallocate(elements); - end procedure deallocate_elements; - - function unescape_special_characters ( - constant code : string) - return string is - begin - return replace(replace(replace(code, "\rp", ')'), "\lp", '('), "\comma", ','); - end function unescape_special_characters; - -end package body com_debug_codec_builder_pkg; diff --git a/vunit/vhdl/com/src/com_deprecated.vhd b/vunit/vhdl/com/src/com_deprecated.vhd deleted file mode 100644 index 2829176eb..000000000 --- a/vunit/vhdl/com/src/com_deprecated.vhd +++ /dev/null @@ -1,917 +0,0 @@ --- Com deprecated package provides deprecated functionality and APIs. These --- will eventually be removed --- --- 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-2019, Lars Asplund lars.anders.asplund@gmail.com - -library ieee; -use ieee.std_logic_1164.all; - -use work.codec_pkg.all; -use work.com_support_pkg.all; -use work.com_messenger_pkg.all; -use work.com_types_pkg.all; -use work.com_pkg.all; -use work.com_common_pkg.all; - -use std.textio.all; - -package com_deprecated_pkg is - ----------------------------------------------------------------------------- - -- Handling of actors - ----------------------------------------------------------------------------- - constant null_actor_c : actor_t := null_actor; - impure function create (name : string := ""; inbox_size : positive := positive'high) return actor_t; - procedure destroy (actor : inout actor_t; status : out com_status_t); - impure function inbox_size (actor : actor_t) return natural; - - ----------------------------------------------------------------------------- - -- Message related subprograms - ----------------------------------------------------------------------------- - constant no_message_id_c : message_id_t := no_message_id; - impure function new_message (sender : actor_t := null_actor_c) return message_ptr_t; - impure function compose ( - payload : string := ""; - sender : actor_t := null_actor_c; - request_id : message_id_t := no_message_id_c) - return message_ptr_t; - procedure copy (src : inout message_ptr_t; dst : inout message_ptr_t); - procedure delete (message : inout message_ptr_t); - - ----------------------------------------------------------------------------- - -- Primary send and receive related subprograms - ----------------------------------------------------------------------------- - constant max_timeout_c : time := max_timeout; - procedure send ( - signal net : inout network_t; - constant receiver : in actor_t; - variable message : inout message_ptr_t; - constant timeout : in time := max_timeout_c; - constant keep_message : in boolean := true); - procedure receive ( - signal net : inout network_t; - constant receiver : in actor_t; - variable message : inout message_ptr_t; - constant timeout : in time := max_timeout_c); - procedure reply ( - signal net : inout network_t; - variable request : inout message_ptr_t; - variable message : inout message_ptr_t; - constant timeout : in time := max_timeout_c; - constant keep_message : in boolean := true); - procedure receive_reply ( - signal net : inout network_t; - variable request : inout message_ptr_t; - variable message : inout message_ptr_t; - constant timeout : in time := max_timeout_c); - procedure send ( - signal net : inout network_t; - constant receiver : in actor_t; - variable message : inout message_ptr_t; - variable receipt : out receipt_t; - constant timeout : in time := max_timeout_c; - constant keep_message : in boolean := true); - procedure reply ( - signal net : inout network_t; - constant sender : in actor_t; - constant receiver : in actor_t; - constant request_id : in message_id_t; - constant payload : in string := ""; - variable receipt : out receipt_t; - constant timeout : in time := max_timeout_c); - procedure reply ( - signal net : inout network_t; - constant receiver : in actor_t; - constant request_id : in message_id_t; - constant payload : in string := ""; - variable receipt : out receipt_t; - constant timeout : in time := max_timeout_c); - procedure reply ( - signal net : inout network_t; - constant receiver : in actor_t; - variable message : inout message_ptr_t; - variable receipt : out receipt_t; - constant timeout : in time := max_timeout_c; - constant keep_message : in boolean := false); - procedure receive_reply ( - signal net : inout network_t; - constant receiver : in actor_t; - constant request_id : in message_id_t; - variable message : inout message_ptr_t; - constant timeout : in time := max_timeout_c); - procedure receive_reply ( - signal net : inout network_t; - constant receiver : in actor_t; - constant request_id : in message_id_t; - variable positive_ack : out boolean; - variable status : out com_status_t; - constant timeout : in time := max_timeout_c); - - ----------------------------------------------------------------------------- - -- Secondary send and receive related subprograms - ----------------------------------------------------------------------------- - procedure send ( - signal net : inout network_t; - constant sender : in actor_t; - constant receiver : in actor_t; - constant payload : in string := ""; - variable receipt : out receipt_t; - constant timeout : in time := max_timeout_c); - procedure send ( - signal net : inout network_t; - constant receiver : in actor_t; - constant payload : in string := ""; - variable receipt : out receipt_t; - constant timeout : in time := max_timeout_c); - procedure request ( - signal net : inout network_t; - constant sender : in actor_t; - constant receiver : in actor_t; - constant request_payload : in string := ""; - variable reply_message : inout message_ptr_t; - constant timeout : in time := max_timeout_c); - procedure request ( - signal net : inout network_t; - constant receiver : in actor_t; - variable request_message : inout message_ptr_t; - variable reply_message : inout message_ptr_t; - constant timeout : in time := max_timeout_c; - constant keep_message : in boolean := false); - procedure request ( - signal net : inout network_t; - constant receiver : in actor_t; - variable request_message : inout message_ptr_t; - variable positive_ack : out boolean; - constant timeout : in time := max_timeout_c; - constant keep_message : in boolean := false); - procedure publish ( - signal net : inout network_t; - variable message : inout message_ptr_t; - constant timeout : in time := max_timeout_c; - constant keep_message : in boolean := false); - procedure request ( - signal net : inout network_t; - constant sender : in actor_t; - constant receiver : in actor_t; - constant request_payload : in string := ""; - variable positive_ack : out boolean; - variable status : out com_status_t; - constant timeout : in time := max_timeout_c); - procedure request ( - signal net : inout network_t; - constant receiver : in actor_t; - variable request_message : inout message_ptr_t; - variable positive_ack : out boolean; - variable status : out com_status_t; - constant timeout : in time := max_timeout_c; - constant keep_message : in boolean := false); - procedure publish ( - signal net : inout network_t; - constant sender : in actor_t; - constant payload : in string := ""; - variable status : out com_status_t; - constant timeout : in time := max_timeout_c); - procedure publish ( - signal net : inout network_t; - variable message : inout message_ptr_t; - variable status : out com_status_t; - constant timeout : in time := max_timeout_c; - constant keep_message : in boolean := false); - procedure acknowledge ( - signal net : inout network_t; - constant sender : in actor_t; - constant receiver : in actor_t; - constant request_id : in message_id_t; - constant positive_ack : in boolean := true; - variable receipt : out receipt_t; - constant timeout : in time := max_timeout_c); - procedure acknowledge ( - signal net : inout network_t; - constant receiver : in actor_t; - constant request_id : in message_id_t; - constant positive_ack : in boolean := true; - variable receipt : out receipt_t; - constant timeout : in time := max_timeout_c); - - ----------------------------------------------------------------------------- - -- Low-level subprograms primarily used for handling timeout wihout error - ----------------------------------------------------------------------------- - impure function has_messages (actor : actor_t) return boolean; - impure function get_message (receiver : actor_t; delete_from_inbox : boolean := true) return message_ptr_t; - - procedure wait_for_messages ( - signal net : in network_t; - constant receiver : in actor_t; - variable status : out com_status_t; - constant receive_timeout : in time := max_timeout_c); - - ----------------------------------------------------------------------------- - -- Receive related subprograms - ----------------------------------------------------------------------------- - procedure subscribe ( - constant subscriber : in actor_t; - constant publisher : in actor_t; - variable status : out com_status_t); - procedure unsubscribe ( - constant subscriber : in actor_t; - constant publisher : in actor_t; - variable status : out com_status_t); - impure function num_of_missed_messages (actor : actor_t) return natural; - -end package; - -package body com_deprecated_pkg is - procedure deprecated (msg : string) is - begin - messenger.deprecated(msg); - end; - - ----------------------------------------------------------------------------- - -- Handling of actors - ----------------------------------------------------------------------------- - impure function create (name : string := ""; inbox_size : positive := positive'high) return actor_t is - begin - deprecated("create() instead of new_actor()"); - return new_actor(name, inbox_size); - end; - - procedure destroy (actor : inout actor_t; status : out com_status_t) is - begin - deprecated("destroy() with status output"); - status := ok; - messenger.destroy(actor); - end; - - impure function inbox_size (actor : actor_t) return natural is - begin - deprecated("inbox_size() instead of mailbox_size()"); - return messenger.mailbox_size(actor, inbox); - end; - - ----------------------------------------------------------------------------- - -- Message related subprograms - ----------------------------------------------------------------------------- - impure function new_message (sender : actor_t := null_actor_c) return message_ptr_t is - variable message : message_ptr_t; - begin - deprecated("new_message()"); - message := new message_t; - message.sender := sender; - return message; - end function; - - impure function compose ( - payload : string := ""; - sender : actor_t := null_actor_c; - request_id : message_id_t := no_message_id_c) - return message_ptr_t is - variable message : message_ptr_t; - begin - deprecated("compose()"); - message := new message_t; - message.sender := sender; - message.request_id := request_id; - write(message.payload, payload); - return message; - end function compose; - - procedure copy (src : inout message_ptr_t; dst : inout message_ptr_t) is - begin - deprecated("copy() based on message_ptr_t"); - dst := new message_t; - dst.id := src.id; - dst.status := src.status; - dst.receiver := src.receiver; - dst.sender := src.sender; - dst.request_id := src.request_id; - write(dst.payload, src.payload.all); - end procedure copy; - - procedure delete (message : inout message_ptr_t) is - begin - deprecated("delete() based on message_ptr_t"); - if message /= null then - deallocate(message.payload); - deallocate(message); - end if; - end procedure delete; - - ----------------------------------------------------------------------------- - -- Primary send and receive related subprograms - ----------------------------------------------------------------------------- - procedure send ( - signal net : inout network_t; - constant receiver : in actor_t; - constant mailbox_id : in mailbox_id_t; - variable message : inout message_ptr_t; - constant timeout : in time := max_timeout_c; - constant keep_message : in boolean := true) is - variable receipt : receipt_t; - begin - deprecated("send() based on message_ptr_t"); - check(message /= null, null_message_error); - check(not messenger.unknown_actor(receiver), unknown_receiver_error); - - if messenger.is_full(receiver, mailbox_id) then - wait on net until not messenger.is_full(receiver, mailbox_id) for timeout; - check(not messenger.is_full(receiver, mailbox_id), full_inbox_error); - end if; - - messenger.send(message.sender, receiver, mailbox_id, message.request_id, message.payload.all, receipt); - message.id := receipt.id; - message.receiver := receiver; - notify(net); - - if not keep_message then - delete(message); - end if; - end; - - procedure send ( - signal net : inout network_t; - constant receiver : in actor_t; - variable message : inout message_ptr_t; - constant timeout : in time := max_timeout_c; - constant keep_message : in boolean := true) is - begin - send(net, receiver, inbox, message, timeout, keep_message); - end; - - procedure receive ( - signal net : inout network_t; - constant receiver : in actor_t; - variable message : inout message_ptr_t; - constant timeout : in time := max_timeout_c) is - variable status : com_status_t; - variable started_with_full_inbox : boolean; - begin - deprecated("receive() based on message_ptr_t"); - delete(message); - wait_for_message(net, receiver, status, timeout); - - if not check(no_error_status(status, true), status) then - return; - end if; - - if status = ok then - started_with_full_inbox := messenger.is_full(receiver, inbox); - message := get_message(receiver); - if started_with_full_inbox then - notify(net); - end if; - else - message := new message_t; - message.receiver := receiver; - message.status := status; - end if; - end; - - procedure reply ( - signal net : inout network_t; - variable request : inout message_ptr_t; - variable message : inout message_ptr_t; - constant timeout : in time := max_timeout_c; - constant keep_message : in boolean := true) is - begin - deprecated("reply() based on message_ptr_t"); - check(request.id /= no_message_id_c, reply_missing_request_id_error); - message.request_id := request.id; - message.sender := request.receiver; - - if request.sender /= null_actor_c then - send(net, request.sender, inbox, message, timeout, keep_message); - else - send(net, request.receiver, outbox, message, timeout, keep_message); - end if; - end; - - procedure wait_for_reply_stash_message ( - signal net : inout network_t; - constant receiver : in actor_t; - constant mailbox_id : in mailbox_id_t := inbox; - constant request_id : in message_id_t; - variable status : out com_status_t; - constant timeout : in time := max_timeout_c) is - variable started_with_full_inbox : boolean := false; - begin - check(not messenger.deferred(receiver), deferred_receiver_error); - - status := ok; - if mailbox_id = inbox then - started_with_full_inbox := messenger.is_full(receiver, inbox); - end if; - - if messenger.has_reply_stash_message(receiver, request_id) then - return; - elsif messenger.find_and_stash_reply_message(receiver, request_id, mailbox_id) then - if started_with_full_inbox then - notify(net); - end if; - return; - else - wait on net until messenger.find_and_stash_reply_message(receiver, request_id, mailbox_id) for timeout; - if not messenger.has_reply_stash_message(receiver, request_id) then - status := work.com_types_pkg.timeout; - elsif started_with_full_inbox then - notify(net); - end if; - end if; - end procedure wait_for_reply_stash_message; - - impure function get_reply_stash_message ( - receiver : actor_t; - clear_reply_stash : boolean := true) - return message_ptr_t is - variable message : message_ptr_t; - begin - check(messenger.has_reply_stash_message(receiver), null_message_error); - - message := new message_t; - message.status := ok; - message.id := messenger.get_reply_stash_message_id(receiver); - message.request_id := messenger.get_reply_stash_message_request_id(receiver); - message.sender := messenger.get_reply_stash_message_sender(receiver); - message.receiver := messenger.get_reply_stash_message_receiver(receiver); - write(message.payload, messenger.get_reply_stash_message_payload(receiver)); - if clear_reply_stash then - messenger.clear_reply_stash(receiver); - end if; - - return message; - end function get_reply_stash_message; - - procedure receive_reply ( - signal net : inout network_t; - variable request : inout message_ptr_t; - variable message : inout message_ptr_t; - constant timeout : in time := max_timeout_c) is - variable status : com_status_t; - variable source_actor : actor_t; - variable mailbox : mailbox_id_t; - begin - deprecated("receive_reply() based on message_ptr_t"); - delete(message); - - source_actor := request.sender when request.sender /= null_actor_c else request.receiver; - mailbox := inbox when request.sender /= null_actor_c else outbox; - - wait_for_reply_stash_message(net, source_actor, mailbox, request.id, status, timeout); - check(no_error_status(status, true), status); - if status = ok then - message := get_reply_stash_message(source_actor); - else - message := new message_t; - message.receiver := request.sender; - message.status := status; - end if; - end; - - -- - procedure publish ( - signal net : inout network_t; - constant sender : in actor_t; - variable message : inout message_ptr_t; - constant timeout : in time := max_timeout_c; - constant keep_message : in boolean := true) is - begin - deprecated("publish() based on message_ptr_t"); - check(message /= null, null_message_error); - message.sender := sender; - message.receiver := null_actor_c; - - if messenger.subscriber_inbox_is_full(message.sender, (published, outbound)) then - wait on net until not messenger.subscriber_inbox_is_full(sender, (published, outbound)) for timeout; - check(not messenger.subscriber_inbox_is_full(message.sender, (published, outbound)), full_inbox_error); - end if; - - messenger.publish(message.sender, message.payload.all); - notify(net); - - if not keep_message then - delete(message); - end if; - end; - procedure send ( - signal net : inout network_t; - constant receiver : in actor_t; - variable message : inout message_ptr_t; - variable receipt : out receipt_t; - constant timeout : in time := max_timeout_c; - constant keep_message : in boolean := true) is - begin - deprecated("send() with message and receipt. Use send() without receipt and look at message.id instead"); - check(message /= null, null_message_error); - check(not messenger.unknown_actor(receiver), unknown_receiver_error); - - if messenger.is_full(receiver, inbox) then - wait on net until not messenger.is_full(receiver, inbox) for timeout; - check(not messenger.is_full(receiver, inbox), full_inbox_error); - end if; - - messenger.send(message.sender, receiver, inbox, message.request_id, message.payload.all, receipt); - message.id := receipt.id; - message.receiver := receiver; - notify(net); - - if not keep_message then - delete(message); - end if; - end; - - -- - procedure receive_reply ( - signal net : inout network_t; - constant receiver : in actor_t; - constant receipt : in receipt_t; - variable positive_ack : out boolean; - variable status : out com_status_t; - constant timeout : in time := max_timeout_c) is - variable message : message_ptr_t; - begin - deprecated("receive_reply() with status output. Use without or wait_for_reply() if accepting timeout"); - wait_for_reply_stash_message(net, receiver, inbox, receipt.id, status, timeout); - check(no_error_status(status, true), status); - if status = ok then - message := get_reply_stash_message(receiver); - status := message.status; - positive_ack := decode(message.payload.all); - delete(message); - else - positive_ack := false; - end if; - end; - - -- - procedure receive_reply ( - signal net : inout network_t; - variable request : inout message_ptr_t; - variable positive_ack : out boolean; - variable status : out com_status_t; - constant timeout : in time := max_timeout_c) is - constant receipt : receipt_t := (status => ok, id => request.id); - begin - receive_reply(net, request.sender, receipt, positive_ack, status, timeout); - end; - - procedure receive_reply ( - signal net : inout network_t; - constant receiver : in actor_t; - constant request_id : in message_id_t; - variable message : inout message_ptr_t; - constant timeout : in time := max_timeout_c) is - variable status : com_status_t; - begin - deprecated("receive_reply() with request ID input. Use send receipt or message input instead"); - delete(message); - wait_for_reply_stash_message(net, receiver, inbox, request_id, status, timeout); - if status = ok then - message := get_reply_stash_message(receiver); - else - message := new message_t; - message.status := status; - end if; - end; - - procedure receive_reply ( - signal net : inout network_t; - constant receiver : in actor_t; - constant request_id : in message_id_t; - variable positive_ack : out boolean; - variable status : out com_status_t; - constant timeout : in time := max_timeout_c) is - variable message : message_ptr_t; - begin - deprecated("receive_reply() with request ID input. Use send receipt or message input instead"); - receive_reply(net, receiver, request_id, message, timeout); - if message.status = ok then - positive_ack := decode(message.payload.all); - else - positive_ack := false; - end if; - - status := message.status; - end; - - procedure reply ( - signal net : inout network_t; - constant sender : in actor_t; - constant receiver : in actor_t; - constant request_id : in message_id_t; - constant payload : in string := ""; - variable receipt : out receipt_t; - constant timeout : in time := max_timeout_c) is - variable message : message_ptr_t; - begin - deprecated("reply() with sender (already known by requestor)"); - deprecated("reply() with receipt. A reply being a request for which a reply is expected is not common "); - message := compose(payload, sender, request_id); - reply(net, receiver, message, receipt, timeout); - end; - - procedure reply ( - signal net : inout network_t; - constant receiver : in actor_t; - variable message : inout message_ptr_t; - variable receipt : out receipt_t; - constant timeout : in time := max_timeout_c; - constant keep_message : in boolean := false) is - begin - deprecated("reply() with receipt. A reply being a request for which a reply is expected is not common "); - check(message.request_id /= no_message_id_c, reply_missing_request_id_error); - - send(net, receiver, message, receipt, timeout, keep_message); - end; - - procedure reply ( - signal net : inout network_t; - constant receiver : in actor_t; - constant request_id : in message_id_t; - constant payload : in string := ""; - variable receipt : out receipt_t; - constant timeout : in time := max_timeout_c) is - variable message : message_ptr_t; - begin - deprecated("reply() with receipt. A reply being a request for which a reply is expected is not common "); - message := compose(payload, request_id => request_id); - reply(net, receiver, message, receipt, timeout); - end; - - ----------------------------------------------------------------------------- - -- Secondary send and receive related subprograms - ----------------------------------------------------------------------------- - procedure send ( - signal net : inout network_t; - constant sender : in actor_t; - constant receiver : in actor_t; - constant payload : in string := ""; - variable receipt : out receipt_t; - constant timeout : in time := max_timeout_c) is - variable message : message_ptr_t; - begin - deprecated("send() with string payload"); - message := compose(payload, sender); - send(net, receiver, message, timeout, keep_message => true); - receipt := (status => ok, id => message.id); - delete(message); - end; - procedure send ( - signal net : inout network_t; - constant receiver : in actor_t; - constant payload : in string := ""; - variable receipt : out receipt_t; - constant timeout : in time := max_timeout_c) is - variable message : message_ptr_t; - begin - deprecated("send() with string payload"); - message := compose(payload); - send(net, receiver, message, timeout, keep_message => true); - receipt := (status => ok, id => message.id); - delete(message); - end; - - procedure request ( - signal net : inout network_t; - constant sender : in actor_t; - constant receiver : in actor_t; - constant request_payload : in string := ""; - variable reply_message : inout message_ptr_t; - constant timeout : in time := max_timeout_c) is - variable request_message : message_ptr_t; - begin - deprecated("request() with string payload"); - request_message := compose(request_payload, sender); - request(net, receiver, request_message, reply_message, timeout); - end; - - procedure request ( - signal net : inout network_t; - constant receiver : in actor_t; - variable request_message : inout message_ptr_t; - variable reply_message : inout message_ptr_t; - constant timeout : in time := max_timeout_c; - constant keep_message : in boolean := false) is - variable start : time; - begin - deprecated("request() based on message_ptr_t"); - start := now; - send(net, receiver, request_message, timeout, keep_message => true); - receive_reply(net, request_message, reply_message, timeout - (now - start)); - if not keep_message then - delete(request_message); - end if; - end; - - procedure request ( - signal net : inout network_t; - constant sender : in actor_t; - constant receiver : in actor_t; - constant request_payload : in string := ""; - variable positive_ack : out boolean; - variable status : out com_status_t; - constant timeout : in time := max_timeout_c) is - variable request_message : message_ptr_t; - begin - deprecated("request() with status. use request() without status or send + wait_for_reply for polling requests"); - request_message := compose(request_payload, sender); - request(net, receiver, request_message, positive_ack, status, timeout); - end; - - procedure request ( - signal net : inout network_t; - constant receiver : in actor_t; - variable request_message : inout message_ptr_t; - variable positive_ack : out boolean; - variable status : out com_status_t; - constant timeout : in time := max_timeout_c; - constant keep_message : in boolean := false) is - variable start : time; - begin - deprecated("request() with status. use request() without status or send + wait_for_reply for polling requests"); - start := now; - send(net, receiver, request_message, timeout, keep_message => true); - receive_reply(net, request_message, positive_ack, status, timeout - (now - start)); - if not keep_message then - delete(request_message); - end if; - end; - - -- - procedure receive_reply ( - signal net : inout network_t; - variable request : inout message_ptr_t; - variable positive_ack : out boolean; - constant timeout : in time := max_timeout_c) is - variable message : message_ptr_t; - begin - receive_reply(net, request, message, timeout); - positive_ack := decode(message.payload.all); - delete(message); - end; - - procedure request ( - signal net : inout network_t; - constant receiver : in actor_t; - variable request_message : inout message_ptr_t; - variable positive_ack : out boolean; - constant timeout : in time := max_timeout_c; - constant keep_message : in boolean := false) is - variable start : time; - begin - deprecated("request() based on message_ptr_t"); - start := now; - send(net, receiver, request_message, timeout, keep_message => true); - receive_reply(net, request_message, positive_ack, timeout - (now - start)); - if not keep_message then - delete(request_message); - end if; - end; - - procedure publish ( - signal net : inout network_t; - variable message : inout message_ptr_t; - constant timeout : in time := max_timeout_c; - constant keep_message : in boolean := false) is - begin - publish(net, message.sender, message, timeout, keep_message); - end; - - procedure acknowledge ( - signal net : inout network_t; - constant sender : in actor_t; - constant receiver : in actor_t; - constant request_id : in message_id_t; - constant positive_ack : in boolean := true; - variable receipt : out receipt_t; - constant timeout : in time := max_timeout_c) is - variable message : message_ptr_t; - begin - deprecated("acknowledge() with sender (already known by requestor)"); - deprecated("acknowledge() with receipt. An acknowledge being a request for which a reply is expected is not common "); - message := compose(encode(positive_ack), sender, request_id); - send(net, receiver, message, receipt, timeout); - end; - - procedure acknowledge ( - signal net : inout network_t; - constant receiver : in actor_t; - constant request_id : in message_id_t; - constant positive_ack : in boolean := true; - variable receipt : out receipt_t; - constant timeout : in time := max_timeout_c) is - begin - deprecated("acknowledge() with receipt. An acknowledge being a request for which a reply is expected is not common "); - acknowledge(net, null_actor_c, receiver, request_id, positive_ack, receipt, timeout); - end; - - - ----------------------------------------------------------------------------- - -- Low-level subprograms primarily used for handling timeout wihout error - ----------------------------------------------------------------------------- - impure function has_messages (actor : actor_t) return boolean is - begin - deprecated("has_messages() with old naming. Use has_message() instead"); - return has_message(actor); - end function has_messages; - - impure function get_message (receiver : actor_t; delete_from_inbox : boolean := true) return message_ptr_t is - variable message : message_ptr_t; - begin - deprecated("get_message() based on message_ptr_t"); - check(messenger.has_messages(receiver), null_message_error); - - message := new message_t; - message.status := ok; - message.id := messenger.get_id(receiver); - message.request_id := messenger.get_request_id(receiver); - message.sender := messenger.get_sender(receiver); - message.receiver := receiver; - write(message.payload, messenger.get_payload(receiver)); - if delete_from_inbox then - messenger.delete_envelope(receiver); - end if; - - return message; - end function get_message; - - procedure wait_for_messages ( - signal net : in network_t; - constant receiver : in actor_t; - variable status : out com_status_t; - constant receive_timeout : in time := max_timeout_c) is - begin - deprecated("wait_for_messages() with old naming. Use wait_for_message() instead"); - wait_for_message(net, receiver, status, receive_timeout); - end procedure wait_for_messages; - - - procedure publish ( - signal net : inout network_t; - constant sender : in actor_t; - constant payload : in string := ""; - variable status : out com_status_t; - constant timeout : in time := max_timeout_c) is - variable message : message_ptr_t; - begin - deprecated("publish() with status output"); - status := ok; - message := compose(payload, sender); - publish(net, message, status, timeout); - end; - - procedure publish ( - signal net : inout network_t; - variable message : inout message_ptr_t; - variable status : out com_status_t; - constant timeout : in time := max_timeout_c; - constant keep_message : in boolean := false) is - begin - deprecated("publish() with status output"); - check(message /= null, null_message_error); - - status := ok; - if messenger.subscriber_inbox_is_full(message.sender, (published, outbound)) then - wait on net until not messenger.subscriber_inbox_is_full(message.sender, (published, outbound)) for timeout; - check(not messenger.subscriber_inbox_is_full(message.sender, (published, outbound)), full_inbox_error); - end if; - - messenger.publish(message.sender, message.payload.all); - notify(net); - - if not keep_message then - delete(message); - end if; - end; - - ----------------------------------------------------------------------------- - -- Receive related subprograms - ----------------------------------------------------------------------------- - procedure subscribe ( - constant subscriber : in actor_t; - constant publisher : in actor_t; - variable status : out com_status_t) is - begin - deprecated("subscribe() with status output"); - status := ok; - messenger.subscribe(subscriber, publisher); - end procedure subscribe; - - procedure unsubscribe ( - constant subscriber : in actor_t; - constant publisher : in actor_t; - variable status : out com_status_t) is - begin - deprecated("subscribe() with status output"); - status := ok; - messenger.unsubscribe(subscriber, publisher); - end procedure unsubscribe; - - impure function num_of_missed_messages (actor : actor_t) return natural is - begin - deprecated("num_of_missed_messages(). Missed messages not allowed."); - return 0; - end num_of_missed_messages; - -end package body com_deprecated_pkg; diff --git a/vunit/vhdl/com/src/com_messenger.vhd b/vunit/vhdl/com/src/com_messenger.vhd index 90cf58333..af9e3a84a 100644 --- a/vunit/vhdl/com/src/com_messenger.vhd +++ b/vunit/vhdl/com/src/com_messenger.vhd @@ -10,7 +10,6 @@ use work.com_types_pkg.all; use work.com_support_pkg.all; use work.queue_pkg.all; -use work.queue_pool_pkg.all; use work.string_ptr_pkg.all; use work.codec_pkg.all; use work.logger_pkg.all; @@ -56,18 +55,10 @@ package com_messenger_pkg is ----------------------------------------------------------------------------- -- Send related subprograms ----------------------------------------------------------------------------- - procedure send ( - constant sender : in actor_t; - constant receiver : in actor_t; - constant mailbox_id : in mailbox_id_t; - constant request_id : in message_id_t; - constant payload : in string; - variable receipt : out receipt_t); procedure send ( constant receiver : in actor_t; constant mailbox_id : in mailbox_id_t; variable msg : inout msg_t); - procedure publish (sender : actor_t; payload : string); procedure publish ( constant sender : in actor_t; variable msg : inout msg_t; @@ -82,27 +73,7 @@ package com_messenger_pkg is ----------------------------------------------------------------------------- impure function has_messages (actor : actor_t) return boolean; impure function has_messages (actor_vec : actor_vec_t) return boolean; - impure function get_payload ( - actor : actor_t; - position : natural := 0; - mailbox_id : mailbox_id_t := inbox) return string; - impure function get_sender ( - actor : actor_t; - position : natural := 0; - mailbox_id : mailbox_id_t := inbox) return actor_t; - impure function get_receiver ( - actor : actor_t; - position : natural := 0; - mailbox_id : mailbox_id_t := inbox) return actor_t; - impure function get_id ( - actor : actor_t; - position : natural := 0; - mailbox_id : mailbox_id_t := inbox) return message_id_t; - impure function get_request_id ( - actor : actor_t; - position : natural := 0; - mailbox_id : mailbox_id_t := inbox) return message_id_t; - impure function get_all_but_payload ( + impure function get_message ( actor : actor_t; position : natural := 0; mailbox_id : mailbox_id_t := inbox) return msg_t; @@ -112,26 +83,11 @@ package com_messenger_pkg is position : natural := 0; mailbox_id : mailbox_id_t := inbox); - impure function has_reply_stash_message ( - actor : actor_t; - request_id : message_id_t := no_message_id) - return boolean; -- - impure function get_reply_stash_message_payload (actor : actor_t) return string; - impure function get_reply_stash_message_sender (actor : actor_t) return actor_t; - impure function get_reply_stash_message_receiver (actor : actor_t) return actor_t; - impure function get_reply_stash_message_id (actor : actor_t) return message_id_t; - impure function get_reply_stash_message_request_id (actor : actor_t) return message_id_t; impure function find_reply_message ( actor : actor_t; request_id : message_id_t; mailbox_id : mailbox_id_t := inbox) return integer; - impure function find_and_stash_reply_message ( - actor : actor_t; - request_id : message_id_t; - mailbox_id : mailbox_id_t := inbox) - return boolean; - procedure clear_reply_stash (actor : actor_t); procedure subscribe ( subscriber : actor_t; @@ -149,14 +105,6 @@ package com_messenger_pkg is impure function get_subscriptions(subscriber : actor_t) return subscription_vec_t; impure function get_subscribers(publisher : actor_t) return subscription_vec_t; - --------------------------------------------------------------------------- - -- Misc - --------------------------------------------------------------------------- - procedure allow_timeout; - impure function timeout_is_allowed return boolean; - procedure allow_deprecated; - procedure deprecated (msg : string); - end protected; end package com_messenger_pkg; @@ -165,7 +113,7 @@ package body com_messenger_pkg is type envelope_ptr_t is access envelope_t; type envelope_t is record - message : message_t; + message : msg_t; next_envelope : envelope_ptr_t; end record envelope_t; type envelope_ptr_array is array (positive range <>) of envelope_ptr_t; @@ -201,7 +149,6 @@ package body com_messenger_pkg is deferred_creation : boolean; inbox : mailbox_ptr_t; outbox : mailbox_ptr_t; - reply_stash : envelope_ptr_t; subscribers : subscribers_t; end record actor_item_t; @@ -216,15 +163,10 @@ package body com_messenger_pkg is deferred_creation => false, inbox => create(0), outbox => create(0), - reply_stash => null, subscribers => (null, null, null)); -- variable envelope_recycle_bin : envelope_ptr_array(1 to 1000); variable n_recycled_envelopes : natural := 0; - variable null_message : message_t := (no_message_id, null_msg_type, ok, null_actor, - null_actor, no_message_id, null); variable next_message_id : message_id_t := no_message_id + 1; - variable timeout_allowed : boolean := false; - variable deprecated_allowed : boolean := false; ----------------------------------------------------------------------------- -- Handling of actors @@ -233,7 +175,7 @@ package body com_messenger_pkg is begin if n_recycled_envelopes > 0 then n_recycled_envelopes := n_recycled_envelopes - 1; - envelope_recycle_bin(n_recycled_envelopes + 1).message := null_message; + envelope_recycle_bin(n_recycled_envelopes + 1).message := null_msg; envelope_recycle_bin(n_recycled_envelopes + 1).next_envelope := null; return envelope_recycle_bin(n_recycled_envelopes + 1); else @@ -292,7 +234,7 @@ package body com_messenger_pkg is end loop; deallocate(old_actors); actors(actors'length - 1) := ((id => actors'length - 1), new string'(name), - deferred_creation, create(inbox_size), create(outbox_size), null, (null, null, null)); + deferred_creation, create(inbox_size), create(outbox_size), (null, null, null)); return actors(actors'length - 1).actor; end function; @@ -387,7 +329,7 @@ package body com_messenger_pkg is while actors(actor.id).inbox.first_envelope /= null loop envelope := actors(actor.id).inbox.first_envelope; actors(actor.id).inbox.first_envelope := envelope.next_envelope; - deallocate(envelope.message.payload); + delete(envelope.message); deallocate_envelope(envelope); end loop; @@ -561,51 +503,6 @@ package body com_messenger_pkg is ----------------------------------------------------------------------------- -- Send related subprograms ----------------------------------------------------------------------------- - procedure send ( - constant sender : in actor_t; - constant receiver : in actor_t; - constant mailbox_id : in mailbox_id_t; - constant request_id : in message_id_t; - constant payload : in string; - variable receipt : out receipt_t) is - variable envelope : envelope_ptr_t; - variable mailbox : mailbox_ptr_t; - begin - check(not is_full(receiver, mailbox_id), full_inbox_error); - - receipt.status := ok; - receipt.id := next_message_id; - envelope := new_envelope; - envelope.message.sender := sender; - envelope.message.receiver := receiver; - envelope.message.id := next_message_id; - envelope.message.request_id := request_id; - write(envelope.message.payload, payload); - next_message_id := next_message_id + 1; - - mailbox := actors(receiver.id).inbox when mailbox_id = inbox else actors(receiver.id).outbox; - mailbox.num_of_messages := mailbox.num_of_messages + 1; - if mailbox.last_envelope /= null then - mailbox.last_envelope.next_envelope := envelope; - else - mailbox.first_envelope := envelope; - end if; - mailbox.last_envelope := envelope; - end; - - procedure publish (sender : actor_t; payload : string) is - variable receipt : receipt_t; - variable subscriber_item : subscriber_item_ptr_t; - begin - check(not unknown_actor(sender), unknown_publisher_error); - - subscriber_item := actors(sender.id).subscribers(published); - while subscriber_item /= null loop - send(sender, subscriber_item.actor, inbox, no_message_id, payload, receipt); - subscriber_item := subscriber_item.next_item; - end loop; - end; - impure function to_string(msg : msg_t) return string is function id_to_string(id : message_id_t) return string is begin @@ -646,28 +543,22 @@ package body com_messenger_pkg is mailbox_id : mailbox_id_t; copy_msg : boolean) is variable envelope : envelope_ptr_t; - variable data : msg_data_t := msg.data; + variable message : msg_t; variable mailbox : mailbox_ptr_t; begin if copy_msg then - data := new_queue(queue_pool); - for i in 0 to length(msg.data) - 1 loop - unsafe_push(data, get(msg.data.data, 1+i)); - end loop; + message := copy(msg); + else + message := msg; end if; if is_visible(com_logger, trace) then trace(com_logger, "[" & to_string(msg) & "] => " & name(receiver) & " " & mailbox_id_t'image(mailbox_id)); end if; - envelope := new_envelope; - envelope.message.id := msg.id; - envelope.message.msg_type := msg.msg_type; - envelope.message.sender := msg.sender; - envelope.message.receiver := msg.receiver; - envelope.message.request_id := msg.request_id; - write(envelope.message.payload, encode(data)); + envelope := new_envelope; + envelope.message := message; mailbox := actors(receiver.id).inbox when mailbox_id = inbox else actors(receiver.id).outbox; mailbox.num_of_messages := mailbox.num_of_messages + 1; @@ -783,82 +674,7 @@ package body com_messenger_pkg is end loop; end; - impure function get_payload ( - actor : actor_t; - position : natural := 0; - mailbox_id : mailbox_id_t := inbox) return string is - variable envelope, previous_envelope : envelope_ptr_t; - variable mailbox : mailbox_ptr_t; - begin - get_envelope(actor, position, mailbox_id, mailbox, envelope, previous_envelope); - if envelope /= null then - return envelope.message.payload.all; - else - return ""; - end if; - end; - - impure function get_sender ( - actor : actor_t; - position : natural := 0; - mailbox_id : mailbox_id_t := inbox) return actor_t is - variable envelope, previous_envelope : envelope_ptr_t; - variable mailbox : mailbox_ptr_t; - begin - get_envelope(actor, position, mailbox_id, mailbox, envelope, previous_envelope); - if envelope /= null then - return envelope.message.sender; - else - return null_actor; - end if; - end; - - impure function get_receiver ( - actor : actor_t; - position : natural := 0; - mailbox_id : mailbox_id_t := inbox) return actor_t is - variable envelope, previous_envelope : envelope_ptr_t; - variable mailbox : mailbox_ptr_t; - begin - get_envelope(actor, position, mailbox_id, mailbox, envelope, previous_envelope); - if envelope /= null then - return envelope.message.receiver; - else - return null_actor; - end if; - end; - - impure function get_id ( - actor : actor_t; - position : natural := 0; - mailbox_id : mailbox_id_t := inbox) return message_id_t is - variable envelope, previous_envelope : envelope_ptr_t; - variable mailbox : mailbox_ptr_t; - begin - get_envelope(actor, position, mailbox_id, mailbox, envelope, previous_envelope); - if envelope /= null then - return envelope.message.id; - else - return no_message_id; - end if; - end; - - impure function get_request_id ( - actor : actor_t; - position : natural := 0; - mailbox_id : mailbox_id_t := inbox) return message_id_t is - variable envelope, previous_envelope : envelope_ptr_t; - variable mailbox : mailbox_ptr_t; - begin - get_envelope(actor, position, mailbox_id, mailbox, envelope, previous_envelope); - if envelope /= null then - return envelope.message.request_id; - else - return no_message_id; - end if; - end; - - impure function get_all_but_payload ( + impure function get_message ( actor : actor_t; position : natural := 0; mailbox_id : mailbox_id_t := inbox) return msg_t is @@ -868,13 +684,7 @@ package body com_messenger_pkg is begin get_envelope(actor, position, mailbox_id, mailbox, envelope, previous_envelope); if envelope /= null then - msg.id := envelope.message.id; - msg.msg_type := envelope.message.msg_type; - msg.status := envelope.message.status; - msg.sender := envelope.message.sender; - msg.receiver := envelope.message.receiver; - msg.request_id := envelope.message.request_id; - msg.data := null_queue; + msg := envelope.message; else msg := null_msg; end if; @@ -888,22 +698,15 @@ package body com_messenger_pkg is mailbox_id : mailbox_id_t := inbox) is variable envelope, previous_envelope : envelope_ptr_t; variable mailbox : mailbox_ptr_t; - variable msg : msg_t; begin get_envelope(actor, position, mailbox_id, mailbox, envelope, previous_envelope); if envelope /= null then if is_visible(com_logger, trace) then - msg.id := envelope.message.id; - msg.msg_type := envelope.message.msg_type; - msg.sender := envelope.message.sender; - msg.receiver := envelope.message.receiver; - msg.request_id := envelope.message.request_id; - trace(com_logger, name(actor) & " " & mailbox_id_t'image(mailbox_id) & " => [" & to_string(msg) & "]"); + trace(com_logger, name(actor) & " " & mailbox_id_t'image(mailbox_id) & + " => [" & to_string(envelope.message) & "]"); end if; - deallocate(envelope.message.payload); - if previous_envelope /= null then previous_envelope.next_envelope := envelope.next_envelope; else @@ -919,70 +722,6 @@ package body com_messenger_pkg is end if; end; - impure function has_reply_stash_message ( - actor : actor_t; - request_id : message_id_t := no_message_id) - return boolean is - begin - if request_id = no_message_id then - return actors(actor.id).reply_stash /= null; - elsif actors(actor.id).reply_stash /= null then - return actors(actor.id).reply_stash.message.request_id = request_id; - else - return false; - end if; - end function has_reply_stash_message; - - impure function get_reply_stash_message_payload (actor : actor_t) return string is - variable envelope : envelope_ptr_t := actors(actor.id).reply_stash; - begin - if envelope /= null then - return envelope.message.payload.all; - else - return ""; - end if; - end; - - impure function get_reply_stash_message_sender (actor : actor_t) return actor_t is - variable envelope : envelope_ptr_t := actors(actor.id).reply_stash; - begin - if envelope /= null then - return envelope.message.sender; - else - return null_actor; - end if; - end; - - impure function get_reply_stash_message_receiver (actor : actor_t) return actor_t is - variable envelope : envelope_ptr_t := actors(actor.id).reply_stash; - begin - if envelope /= null then - return envelope.message.receiver; - else - return null_actor; - end if; - end; - - impure function get_reply_stash_message_id (actor : actor_t) return message_id_t is - variable envelope : envelope_ptr_t := actors(actor.id).reply_stash; - begin - if envelope /= null then - return envelope.message.id; - else - return no_message_id; - end if; - end; - - impure function get_reply_stash_message_request_id (actor : actor_t) return message_id_t is - variable envelope : envelope_ptr_t := actors(actor.id).reply_stash; - begin - if envelope /= null then - return envelope.message.request_id; - else - return no_message_id; - end if; - end; - procedure find_reply_message ( actor : actor_t; request_id : message_id_t; @@ -1026,45 +765,6 @@ package body com_messenger_pkg is end if; end; - impure function find_and_stash_reply_message ( - actor : actor_t; - request_id : message_id_t; - mailbox_id : mailbox_id_t := inbox) - return boolean is - variable envelope : envelope_ptr_t; - variable previous_envelope : envelope_ptr_t := null; - variable mailbox : mailbox_ptr_t; - variable position : natural; - begin - find_reply_message(actor, request_id, mailbox_id, mailbox, envelope, previous_envelope, position); - - if envelope /= null then - actors(actor.id).reply_stash := envelope; - - if previous_envelope /= null then - previous_envelope.next_envelope := envelope.next_envelope; - else - mailbox.first_envelope := envelope.next_envelope; - end if; - - if mailbox.first_envelope = null then - mailbox.last_envelope := null; - end if; - - mailbox.num_of_messages := mailbox.num_of_messages - 1; - - return true; - end if; - - return false; - end function find_and_stash_reply_message; - - procedure clear_reply_stash (actor : actor_t) is - begin - deallocate(actors(actor.id).reply_stash.message.payload); - deallocate(actors(actor.id).reply_stash); - end procedure clear_reply_stash; - procedure subscribe ( subscriber : actor_t; publisher : actor_t; @@ -1184,29 +884,6 @@ package body com_messenger_pkg is return subscriptions; end; - - ----------------------------------------------------------------------------- - -- Misc - ----------------------------------------------------------------------------- - procedure allow_timeout is - begin - timeout_allowed := true; - end procedure allow_timeout; - - impure function timeout_is_allowed return boolean is - begin - return timeout_allowed; - end function timeout_is_allowed; - - procedure allow_deprecated is - begin - deprecated_allowed := true; - end procedure allow_deprecated; - - procedure deprecated (msg : string) is - begin - check(deprecated_allowed, deprecated_interface_error, msg); - end; end protected body; end package body com_messenger_pkg; diff --git a/vunit/vhdl/com/src/com_string.vhd b/vunit/vhdl/com/src/com_string.vhd deleted file mode 100644 index 9c53821c7..000000000 --- a/vunit/vhdl/com/src/com_string.vhd +++ /dev/null @@ -1,307 +0,0 @@ --- The com string package provides to_string functions for data types supported --- by the com codec package that don't have a standard to_string function defined. --- These functions are also used as the encode function when the debug codecs --- are used. In some cases the standard to_string function isn't used by the --- debug encoder. For example, arrays like std_ulogic_vector are encoded along with --- their ranges such that this property is unchanged by the transfer. In these --- cases there is a to_detailed_string available in this package. --- --- 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-2019, Lars Asplund lars.anders.asplund@gmail.com -library ieee; -use ieee.std_logic_1164.all; -use ieee.math_complex.all; -use ieee.numeric_bit.all; -use ieee.numeric_std.all; -use ieee.fixed_pkg.all; -use ieee.float_pkg.all; - -use std.textio.all; - -use work.com_debug_codec_builder_pkg.all; -use work.queue_pkg.all; -use work.integer_vector_ptr_pkg.all; -use work.string_ptr_pkg.all; - -package com_string_pkg is - function to_detailed_string ( - constant data : real) - return string; - function to_detailed_string ( - constant data : string) - return string; - alias to_string is to_detailed_string[string return string]; - function to_detailed_string ( - constant data : boolean_vector) - return string; - alias to_string is to_detailed_string[boolean_vector return string]; - function to_detailed_string ( - constant data : bit_vector) - return string; - function to_detailed_string ( - constant data : integer_vector) - return string; - alias to_string is to_detailed_string[integer_vector return string]; - function to_detailed_string ( - constant data : real_vector) - return string; - alias to_string is to_detailed_string[real_vector return string]; - function to_detailed_string ( - constant data : time_vector) - return string; - alias to_string is to_detailed_string[time_vector return string]; - function to_detailed_string ( - constant data : std_ulogic_vector) - return string; - function to_string ( - constant data : complex) - return string; - function to_string ( - constant data : complex_polar) - return string; - function to_string ( - constant data : integer_vector_ptr_t) - return string; - function to_string ( - constant data : queue_t) - return string; - function to_detailed_string ( - constant data : ieee.numeric_bit.unsigned) - return string; - function to_detailed_string ( - constant data : ieee.numeric_bit.signed) - return string; - function to_detailed_string ( - constant data : ieee.numeric_std.unsigned) - return string; - function to_detailed_string ( - constant data : ieee.numeric_std.signed) - return string; - function to_detailed_string ( - constant data : ufixed) - return string; - function to_detailed_string ( - constant data : sfixed) - return string; - function to_detailed_string ( - constant data : float) - return string; -end package com_string_pkg; - -package body com_string_pkg is - function to_detailed_string ( - constant data : real) - return string is - constant f64 : float64 := (others => '0'); - begin - return to_string(to_float(data, f64)); - end; - - function to_detailed_string ( - constant data : string) - return string is - begin - -- Modelsim sets data'right to 0 which is out of the positive index range used by - -- strings. This becomes a problem in the decoder which tries to maintain range - if (data'left = 1) and (data'right = 0) then - return create_array_group("", "2", "1", true); - else - return create_array_group(escape_special_characters(data), to_string(data'left), to_string(data'right), data'ascending); - end if; - end; - - function to_detailed_string ( - constant data : boolean_vector) - return string is - variable element : string(1 to 2 + data'length * 6); - variable l : line; - variable length : natural; - begin - open_group(l); - for i in data'range loop - append_group(l, to_string(data(i))); - end loop; - close_group(l, element, length); - - return create_array_group(element(1 to length), to_string(data'left), to_string(data'right), data'ascending); - end; - - function to_detailed_string ( - constant data : bit_vector) - return string is - begin - if (data'left = 0) and (data'right = -1) then - return create_array_group(to_string(data), "1", "0", true); - else - return create_array_group(to_string(data), to_string(data'left), to_string(data'right), data'ascending); - end if; - end; - - function to_detailed_string ( - constant data : integer_vector) - return string is - variable element : string(1 to 2 + data'length * 12); - variable l : line; - variable length : natural; - begin - open_group(l); - for i in data'range loop - append_group(l, to_string(data(i))); - end loop; - close_group(l, element, length); - - return create_array_group(element(1 to length), to_string(data'left), to_string(data'right), data'ascending); - end; - - function to_detailed_string ( - constant data : real_vector) - return string is - variable element : string(1 to 2 + data'length * 67); - variable l : line; - variable length : natural; - begin - open_group(l); - for i in data'range loop - append_group(l, to_detailed_string(data(i))); - end loop; - close_group(l, element, length); - - return create_array_group(element(1 to length), to_string(data'left), to_string(data'right), data'ascending); - end; - - function to_detailed_string ( - constant data : time_vector) - return string is - variable element : string(1 to 2 + data'length * 67); - variable l : line; - variable length : natural; - begin - open_group(l); - for i in data'range loop - append_group(l, to_string(data(i))); - end loop; - close_group(l, element, length); - - return create_array_group(element(1 to length), to_string(data'left), to_string(data'right), data'ascending); - end; - - function to_detailed_string ( - constant data : std_ulogic_vector) - return string is - begin - if (data'left = 0) and (data'right = -1) then - return create_array_group(to_string(data), "1", "0", true); - else - return create_array_group(to_string(data), to_string(data'left), to_string(data'right), data'ascending); - end if; - end; - - function to_string ( - constant data : complex) - return string is - begin - return create_group(2, to_detailed_string(data.re), to_detailed_string(data.im)); - end; - - function to_string ( - constant data : complex_polar) - return string is - begin - return create_group(2, to_detailed_string(data.mag), to_detailed_string(data.arg)); - end; - - function to_string ( - constant data : integer_vector_ptr_t) - return string is - begin - return create_group(1, to_string(data.ref)); - end; - - function to_string ( - constant data : queue_t) - return string is - begin - return create_group(2, to_string(data.p_meta), to_string(to_integer(data.data))); - end; - - function to_detailed_string ( - constant data : ieee.numeric_bit.unsigned) - return string is - begin - if (data'left = 0) and (data'right = -1) then - return create_array_group(to_string(data), "1", "0", true); - else - return create_array_group(to_string(data), to_string(data'left), to_string(data'right), data'ascending); - end if; - end; - - function to_detailed_string ( - constant data : ieee.numeric_bit.signed) - return string is - begin - if (data'left = 0) and (data'right = -1) then - return create_array_group(to_string(data), "1", "0", true); - else - return create_array_group(to_string(data), to_string(data'left), to_string(data'right), data'ascending); - end if; - end; - - function to_detailed_string ( - constant data : ieee.numeric_std.unsigned) - return string is - begin - if (data'left = 0) and (data'right = -1) then - return create_array_group(to_string(data), "1", "0", true); - else - return create_array_group(to_string(data), to_string(data'left), to_string(data'right), data'ascending); - end if; - end; - - function to_detailed_string ( - constant data : ieee.numeric_std.signed) - return string is - begin - if (data'left = 0) and (data'right = -1) then - return create_array_group(to_string(data), "1", "0", true); - else - return create_array_group(to_string(data), to_string(data'left), to_string(data'right), data'ascending); - end if; - end; - - function to_detailed_string ( - constant data : ufixed) - return string is - variable unsigned_data : ieee.numeric_std.unsigned(data'length - 1 downto 0); - begin - for i in unsigned_data'range loop - unsigned_data(i) := data(i + data'low); - end loop; - return create_array_group(to_string(unsigned_data), to_string(data'left), to_string(data'right), false); - end; - - function to_detailed_string ( - constant data : sfixed) - return string is - variable unsigned_data : ieee.numeric_std.unsigned(data'length - 1 downto 0); - begin - for i in unsigned_data'range loop - unsigned_data(i) := data(i + data'low); - end loop; - return create_array_group(to_string(unsigned_data), to_string(data'left), to_string(data'right), false); - end; - - function to_detailed_string ( - constant data : float) - return string is - variable unsigned_data : ieee.numeric_std.unsigned(data'length - 1 downto 0); - begin - for i in unsigned_data'range loop - unsigned_data(i) := data(i + data'low); - end loop; - return create_array_group(to_string(unsigned_data), to_string(data'left), to_string(data'right), false); - end; - -end package body com_string_pkg; diff --git a/vunit/vhdl/com/src/com_types.vhd b/vunit/vhdl/com/src/com_types.vhd index 42946fa6c..18af09447 100644 --- a/vunit/vhdl/com/src/com_types.vhd +++ b/vunit/vhdl/com/src/com_types.vhd @@ -22,7 +22,6 @@ use work.string_ptr_pkg.all; use work.logger_pkg.all; use work.queue_pkg.all; use work.queue_2008_pkg.all; -use work.queue_pool_pkg.all; package com_types_pkg is @@ -80,18 +79,6 @@ package com_types_pkg is subtype message_id_t is natural; constant no_message_id : message_id_t := 0; - -- Deprecated message type - type message_t is record - id : message_id_t; - msg_type : msg_type_t; - status : com_status_t; - sender : actor_t; - receiver : actor_t; - request_id : message_id_t; - payload : line; - end record message_t; - type message_ptr_t is access message_t; - -- Message type. All fields of the record are private and should not be -- referenced directly by the user. subtype msg_data_t is queue_t; @@ -134,12 +121,6 @@ package com_types_pkg is type subscription_vec_t is array (natural range <>) of subscription_t; type subscription_vec_ptr_t is access subscription_vec_t; - -- Deprecated - type receipt_t is record - status : com_status_t; - id : message_id_t; - end record receipt_t; - -- An event type representing the network over which actors communicate. An event in -- the network notifies connected actors which can determine the cause of the -- event by consulting the com messenger (com_messenger.vhd). Actors can be @@ -177,7 +158,6 @@ package com_types_pkg is end record messenger_state_t; constant com_logger : logger_t := get_logger("vunit_lib:com"); - constant queue_pool : queue_pool_t := new_queue_pool; ----------------------------------------------------------------------------- -- Handling of message types @@ -389,10 +369,10 @@ package com_types_pkg is alias push_msg_t is push[msg_t, msg_t]; alias pop_msg_t is pop[msg_t return msg_t]; - procedure push_ref(constant msg : msg_t; value : inout integer_array_t); - impure function pop_ref(msg : msg_t) return integer_array_t; - 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(msg : msg_t; value : inout integer_array_t); + impure function pop(msg : msg_t) return integer_array_t; + alias push_integer_array_t_ref is push[msg_t, integer_array_t]; + alias pop_integer_array_t_ref is pop[msg_t return integer_array_t]; end package; @@ -468,25 +448,21 @@ package body com_types_pkg is variable msg : msg_t; begin msg.sender := sender; - msg.data := new_queue(queue_pool); + msg.data := new_queue; msg.msg_type := msg_type; return msg; end; procedure delete(msg : inout msg_t) is begin - recycle(queue_pool, msg.data); + deallocate(msg.data); msg := null_msg; end procedure delete; impure function copy(msg : msg_t) return msg_t is variable result : msg_t := msg; begin - result.data := new_queue(queue_pool); - for i in 0 to length(msg.data) - 1 loop - unsafe_push(result.data, get(msg.data.data, 1 + i)); - end loop; - + result.data := copy(msg.data); return result; end; @@ -510,8 +486,7 @@ package body com_types_pkg is if msg.data = null_queue then return true; end if; - - return length(msg.data) = 0; + return is_empty(msg.data); end; procedure push(queue : queue_t; variable value : inout msg_t) is @@ -844,14 +819,14 @@ package body com_types_pkg is return pop(msg.data); end; - procedure push_ref(constant msg : msg_t; value : inout integer_array_t) is + procedure push(msg : msg_t; value : inout integer_array_t) is begin - push_ref(msg.data, value); + push(msg.data, value); end; - impure function pop_ref(msg : msg_t) return integer_array_t is + impure function pop(msg : msg_t) return integer_array_t is begin - return pop_ref(msg.data); + return pop(msg.data); end; end package body com_types_pkg; diff --git a/vunit/vhdl/com/test/constants.vhd b/vunit/vhdl/com/test/constants.vhd deleted file mode 100644 index f812700db..000000000 --- a/vunit/vhdl/com/test/constants.vhd +++ /dev/null @@ -1,11 +0,0 @@ --- Test suite for com codec package --- --- 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-2019, Lars Asplund lars.anders.asplund@gmail.com - -package constants_pkg is - constant byte_msb : natural := 7; -end package constants_pkg; diff --git a/vunit/vhdl/com/test/custom_types.vhd b/vunit/vhdl/com/test/custom_types.vhd deleted file mode 100644 index a00c0a415..000000000 --- a/vunit/vhdl/com/test/custom_types.vhd +++ /dev/null @@ -1,112 +0,0 @@ --- Test suite for com codec package --- --- 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-2019, Lars Asplund lars.anders.asplund@gmail.com - -library vunit_lib; -context vunit_lib.vunit_context; -context vunit_lib.com_context; - -library ieee; -use ieee.std_logic_1164.all; -use ieee.math_complex.all; -use ieee.numeric_bit.all; -use ieee.numeric_std.all; -use ieee.fixed_pkg.all; -use ieee.float_pkg.all; - -use std.textio.all; - -use work.constants_pkg.all; -use work.more_constants_pkg.all; - -package custom_types_pkg is - type enum1_t is (red, green, blue); - -- Commented type should be ignored, if not this will cause a compile error --- type enum1_t is (foo,bar); - - type record1_t is record - a : natural; - b, c, d : integer; - end record record1_t; - type record2_msg_type_t is (command); - type record2_t is record - msg_type : record2_msg_type_t; - a : natural; - b, c, d : integer; - e : std_logic; - end record record2_t; - type record3_t is record - char : character; - end record record3_t; - type record4_t is record - my_integer : integer; - my_real : real; - my_time : time; - my_boolean : boolean; - my_bit : bit; - my_std_ulogic : std_ulogic; - my_severity_level : severity_level; - my_file_open_status : file_open_status; - my_file_open_kind : file_open_kind; - my_integer2 : integer; - end record record4_t; - type record5_t is record - my_character : character; - my_string : string(1 to 3); - my_boolean_vector : boolean_vector(1 to 3); - my_bit_vector : bit_vector(1 to 3); - my_integer_vector : integer_vector(1 to 3); - my_real_vector : real_vector(1 to 3); - my_time_vector : time_vector(1 to 3); - my_std_ulogic_vector : std_ulogic_vector(1 to 3); - my_complex : complex; - my_character2 : character; - end record record5_t; - type record6_t is record - my_complex_polar : complex_polar; - my_bit_unsigned : ieee.numeric_bit.unsigned(1 to 3); - my_bit_signed : ieee.numeric_bit.signed(1 to 3); - my_std_unsigned : ieee.numeric_std.unsigned(1 to 3); - my_std_signed : ieee.numeric_std.signed(1 to 3); - my_ufixed : ufixed(2 downto -2); - my_sfixed : sfixed(2 downto -2); - my_float : float64; - my_complex_polar2 : complex_polar; - end record record6_t; - type record7_t is record - r4 : record4_t; - r5 : record5_t; - r6 : record6_t; - end record record7_t; - type record8_msg_type_t is (read, write); - type record8_t is record - msg_type : record8_msg_type_t; - addr : natural; - data : natural; - end record record8_t; type int_2d_t is array (integer range <>, integer range <>) of integer; - type record9_msg_type_t is (foo, bar); - type record9_t is record - msg_type : record9_msg_type_t; - slv : std_logic_vector(byte_msb downto byte_lsb); - str : string(1 to 3); - int_2d : int_2d_t(1 to 2, 4 downto -1); - end record record9_t; - - type array1_t is array (-2 to 2) of natural; - type array2_t is array (2 downto -2) of natural; - type array3_t is array (-2 to 2, -1 to 1) of natural; - type array4_t is array (positive range <>) of natural; - type array5_t is array (integer range <>, integer range <>) of natural; - type fruit_t is (apple, banana, melon, kiwi, orange, papaya); - type array6_t is array (fruit_t range <>) of natural; --- type--array7_t is array (integer range <>, fruit_t range <>) of natural; - type array8_t is array (2 * (3 - 4) to 2, -1 to -1 + 2) of natural; - type array9_t is array (array1_t'range) of natural; - type array10_t is array (array1_t'range, -1 to 1) of natural; - - -end package custom_types_pkg; diff --git a/vunit/vhdl/com/test/more_constants.vhd b/vunit/vhdl/com/test/more_constants.vhd deleted file mode 100644 index 6948acf59..000000000 --- a/vunit/vhdl/com/test/more_constants.vhd +++ /dev/null @@ -1,11 +0,0 @@ --- Test suite for com codec package --- --- 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-2019, Lars Asplund lars.anders.asplund@gmail.com - -package more_constants_pkg is - constant byte_lsb : natural := 0; -end package more_constants_pkg; diff --git a/vunit/vhdl/com/test/tb_com.vhd b/vunit/vhdl/com/test/tb_com.vhd index cc2951def..da5d9d169 100644 --- a/vunit/vhdl/com/test/tb_com.vhd +++ b/vunit/vhdl/com/test/tb_com.vhd @@ -44,7 +44,6 @@ begin variable request_msg, request_msg2, request_msg3, reply_msg : msg_t; variable peeked_msg1, peeked_msg2 : msg_t; variable msg_vec_ptr : msg_vec_ptr_t; - variable deprecated_message : message_ptr_t; variable subscription_vec_ptr : subscription_vec_ptr_t; variable actor_state : actor_state_t; variable mailbox_state : mailbox_state_t; @@ -1248,12 +1247,6 @@ begin unmock(com_logger); - -- Deprecated APIs - elsif run("Test that use of deprecated API leads to an error") then - mock(com_logger); - deprecated_message := compose("hello world"); - check_only_log(com_logger, "DEPRECATED INTERFACE ERROR. compose()", failure); - unmock(com_logger); end if; end loop; diff --git a/vunit/vhdl/com/test/tb_com_codec.vhd b/vunit/vhdl/com/test/tb_com_codec.vhd deleted file mode 100644 index 6bb247d09..000000000 --- a/vunit/vhdl/com/test/tb_com_codec.vhd +++ /dev/null @@ -1,245 +0,0 @@ --- Test suite for com codec package --- --- 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-2019, Lars Asplund lars.anders.asplund@gmail.com - --- vunit: run_all_in_same_sim - -library vunit_lib; -context vunit_lib.vunit_context; -context vunit_lib.com_context; - -library tb_com_lib; -use tb_com_lib.custom_codec_pkg.all; -use tb_com_lib.custom_types_pkg.all; - -library ieee; -use ieee.std_logic_1164.all; -use ieee.float_pkg.all; - -use std.textio.all; - -entity tb_com_codec is - generic ( - runner_cfg : string); -end entity tb_com_codec; - -architecture test_fixture of tb_com_codec is -begin - test_runner : process - constant f64 : float64 := (others => '0'); - constant special_chars : string(1 to 3) := "),("; - constant comma : character := ','; - constant lp : character := '('; - constant rp : character := ')'; - variable null_array4_t : array4_t(10 to 8); - variable null_array5_t : array5_t(1 to 0, 1 to 0); - variable null_array5_2_t : array5_t(0 to 1, 1 to 0); - variable null_array5_3_t : array5_t(1 to 0, 0 to 1); - variable null_array6_t : array6_t(apple downto banana); --- variable null_array7_t : array7_t(1 to 2, apple downto banana); - variable t1 : time; - variable my_record4 : record4_t; - variable my_record5 : record5_t; - variable my_record6 : record6_t; - variable my_record7 : record7_t; - variable e1, e2, e3 : line; - - variable a1 : array1_t; - variable a2 : array2_t; - variable a3 : array3_t; - variable a4 : array4_t(1 to 5); - variable a4_null : array4_t(1 to 0); - variable a5_null : array5_t(1 to 0, 1 to 0); - variable a5_null2 : array5_t(0 to 1, 1 to 0); - variable a5_null3 : array5_t(1 to 0, 0 to 1); - variable a5 : array5_t(1 to 5, 1 to 3); - variable a6_null : array6_t(apple downto orange); - variable a6 : array6_t(apple to orange); --- variable a7_null : array7_t(1 to 2, apple downto banana); --- variable a7 : array7_t(1 to 5, apple to melon); - variable a8 : array8_t; - variable a9 : array9_t; - variable a10 : array10_t; - - variable enum1 : enum1_t; - - variable rec1 : record1_t; - variable rec2 : record2_t; - variable rec3 : record3_t; - variable rec9 : record9_t; - - -- Temp variables to make test case pass Riviera-PRO 2016.10 - variable range_left, range_right : integer; - - variable msg, msg2 : msg_t; - - begin - test_runner_setup(runner, runner_cfg); - - while test_suite loop - if run("Test that custom enumeration type can be encoded and decoded") then - enum1 := decode(encode(red)); - check_relation(enum1 = red); - enum1 := decode(encode(green)); - check_relation(enum1 = green); - enum1 := decode(encode(blue)); - check_relation(enum1 = blue); - elsif run("Test that custom enumeration type can be pushed and popped") then - msg := new_msg; - push_enum1_t(msg, red); - check_relation(pop_enum1_t(msg) = red, result("for pop_enum1")); - elsif run("Test that custom record type can be encoded and decoded") then - rec1 := decode(encode_record1_t((character'pos(lp), -1, -2, -3))); - check_relation(rec1 = (character'pos(lp), -1, -2, -3)); - - rec2 := decode(encode_record2_t((command, 1, -1, -2, -3, '1'))); - check_relation(rec2 = (command, 1, -1, -2, -3, '1')); - rec2 := decode(command(1, -1, -2, -3, '1')); - check_relation(rec2 = (command, 1, -1, -2, -3, '1')); - - rec3 := decode(encode_record3_t((char => comma))); - check_relation(rec3 = (char => comma)); - rec3 := decode(encode_record3_t((char => lp))); - check_relation(rec3 = (char => lp)); - rec3 := decode(encode_record3_t((char => rp))); - check_relation(rec3 = (char => rp)); - elsif run("Test that custom record type can be pushed and popped") then - msg := new_msg; - rec1 := (character'pos(lp), -1, -2, -3); - push_record1_t(msg, rec1); - check_relation(pop_record1_t(msg) = rec1, result("for pop_record1_t")); - elsif run("Test that custom array can be encoded and decoded") then - a1 := decode(encode_array1_t((0, 1, 2, 3, 4))); - check_relation(a1 = (0, 1, 2, 3, 4)); - check_relation(a1'left = -2); - check_relation(a1'right = 2); - - a2 := decode(encode_array2_t((0, 1, 2, 3, 4))); - check_relation(a2 = (0, 1, 2, 3, 4)); - check_relation(a2'left = 2); - check_relation(a2'right = -2); - - a3 := decode(encode_array3_t(((0, 1, 2), (3, 4, 5), (6, 7, 8), (9, 10, 11), (12, 13, 14)))); - check_relation(a3 = ((0, 1, 2), (3, 4, 5), (6, 7, 8), (9, 10, 11), (12, 13, 14))); - check_relation(a3'left(1) = -2); - check_relation(a3'right(1) = 2); - check_relation(a3'left(2) = -1); - check_relation(a3'right(2) = 1); - - a4_null := decode(encode(null_array4_t)); - check_relation(a4_null = null_array4_t); - a4 := decode(encode_array4_t((0, 1, 2, 3, 4))); - check_relation(a4 = (0, 1, 2, 3, 4)); - - a5_null := decode(encode(null_array5_t)); - check_relation(a5_null = null_array5_t); - a5_null2 := decode(encode(null_array5_2_t)); - check_relation(a5_null2 = null_array5_2_t); - a5_null3 := decode(encode(null_array5_3_t)); - check_relation(a5_null3 = null_array5_3_t); - a5 := decode(encode_array5_t(((0, 1, 2), (3, 4, 5), (6, 7, 8), (9, 10, 11), (12, 13, 14)))); - check_relation(a5 = ((0, 1, 2), (3, 4, 5), (6, 7, 8), (9, 10, 11), (12, 13, 14))); - - a6_null := decode(encode(null_array6_t)); - check_relation(a6_null = null_array6_t); - a6 := decode(encode_array6_t((0, 1, 2, 3, 4))); - check_relation(a6 = (0, 1, 2, 3, 4)); - - -- This test has been removed since it fails under Active-HDL. @TODO - -- Investigate futher if this can be reintroduced or separated into its - -- own test that is selectively executed in the acceptance tests - -- depending on simulator. - --a7_null := decode(encode(null_array7_t)); - --check_relation(a7_null = null_array7_t); - --a7 := decode(encode_array7_t(((0, 1, 2), (3, 4, 5), (6, 7, 8), (9, 10, 11), (12, 13, 14)))); - --check_relation(a7 = ((0, 1, 2), (3, 4, 5), (6, 7, 8), (9, 10, 11), (12, 13, 14))); - - a8 := decode(encode_array8_t(((0, 1, 2), (3, 4, 5), (6, 7, 8), (9, 10, 11), (12, 13, 14)))); - check_relation(a8 = ((0, 1, 2), (3, 4, 5), (6, 7, 8), (9, 10, 11), (12, 13, 14))); - check_relation(a8'left(1) = -2); - check_relation(a8'right(1) = 2); - check_relation(a8'left(2) = -1); - check_relation(a8'right(2) = 1); - - a9 := decode(encode_array9_t((0, 1, 2, 3, 4))); - check_relation(a9 = (0, 1, 2, 3, 4)); - check_relation(a9'left = -2); - check_relation(a9'right = 2); - - a10 := decode(encode_array10_t(((0, 1, 2), (3, 4, 5), (6, 7, 8), (9, 10, 11), (12, 13, 14)))); - check_relation(a10 = ((0, 1, 2), (3, 4, 5), (6, 7, 8), (9, 10, 11), (12, 13, 14))); - check_relation(a10'left(1) = -2); - check_relation(a10'right(1) = 2); - check_relation(a10'left(2) = -1); - check_relation(a10'right(2) = 1); - elsif run("Test that custom array can be pushed and popped") then - msg := new_msg; - a1 := (0, 1, 2, 3, 4); - push_array1_t(msg, a1); - check_relation(pop_array1_t(msg) = a1, result("for pop_array1_t")); - - a3 := ((0, 1, 2), (3, 4, 5), (6, 7, 8), (9, 10, 11), (12, 13, 14)); - push_array3_t(msg, a3); - check_relation(pop_array3_t(msg) = a3, result("for pop_array3_t")); - - a4 := (0, 1, 2, 3, 4); - push_array4_t(msg, a4); - check_relation(pop_array4_t(msg) = a4, result("for pop_array4_t")); - - a5 := ((0, 1, 2), (3, 4, 5), (6, 7, 8), (9, 10, 11), (12, 13, 14)); - push_array5_t(msg, a5); - check_relation(pop_array5_t(msg) = a5, result("for pop_array5_t")); - - elsif run("Test that all provided codecs can be used within a composite") then - my_record4 := (17, 42.21, -365 ns, true, '0', 'U', error, open_ok, read_mode, 21); - check_relation(my_record4 = decode(encode(my_record4))); - - my_record5 := ('f', "abc", (true, false, false), ('1', '0', '0'), (17, 21, 42), (-3.14, 2.71, 1000.1000), - (-13 ns, 14 ps, 3 ms), "1UX", (1.12, -0.25), 'g'); - check_relation(my_record5 = decode(encode(my_record5))); - - my_record6 := ((112.3, 0.48), "100", "011", "1XU", "LHW", "1U0X1", "01LZ1", to_float(234.56, f64), - (12.3, -0.48)); - check_relation(my_record6 = record6_t'(decode(encode(my_record6)))); - - my_record7 := (my_record4, my_record5, my_record6); - check_relation(my_record7 = record7_t'(decode(encode(my_record7)))); - elsif run("Test that the values of different enumeration types used for msg_type record elements get different encodings") then - write(e1, encode(record2_msg_type_t'(command))); - write(e2, encode(record8_msg_type_t'(read))); - write(e3, encode(record8_msg_type_t'(write))); - check_relation(e1.all /= e2.all); - check_relation(e1.all /= e3.all); - check_relation(e2.all /= e3.all); - deallocate(e1); - deallocate(e2); - deallocate(e3); - elsif run("Test that records with different msg_type enumeration types can classified with a single get_msg_type function") then - write(e1, encode(record2_msg_type_t'(command))); - write(e2, encode(record8_msg_type_t'(read))); - write(e3, encode(record8_msg_type_t'(write))); - check(get_record2_msg_type_t(e1.all) = command); - check(get_record8_msg_type_t(e2.all) = read); - check(get_record8_msg_type_t(e3.all) = write); - check(get_msg_type(e1.all) = command); - check(get_msg_type(e2.all) = read); - check(get_msg_type(e3.all) = write); - deallocate(e1); - deallocate(e2); - deallocate(e3); - elsif run("Test that records containing arrays can be encoded and decoded") then - rec9 := decode(encode(record9_t'(foo, x"a5", "foo", ((1, 2, 3, 4, 5, 6), (4, 3, 2, 1, 0, -1))))); - check_relation(rec9 = (foo, x"a5", "foo", ((1, 2, 3, 4, 5, 6), (4, 3, 2, 1, 0, -1)))); - end if; - end loop; - - test_runner_cleanup(runner); - wait; - end process; - - test_runner_watchdog(runner, 100 ms); -end test_fixture; diff --git a/vunit/vhdl/com/test/tb_com_deprecated.vhd b/vunit/vhdl/com/test/tb_com_deprecated.vhd deleted file mode 100644 index 1dc516333..000000000 --- a/vunit/vhdl/com/test/tb_com_deprecated.vhd +++ /dev/null @@ -1,454 +0,0 @@ --- Test suite for deprecated parts of the com package --- --- 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-2019, Lars Asplund lars.anders.asplund@gmail.com - -library vunit_lib; -context vunit_lib.vunit_context; -context vunit_lib.com_context; - -library ieee; -use ieee.std_logic_1164.all; - -use std.textio.all; - -entity tb_com_deprecated is - generic ( - runner_cfg : string); -end entity tb_com_deprecated; - -architecture test_fixture of tb_com_deprecated is - signal hello_world_received, start_receiver, start_server, - start_server2, start_server3, start_server5, - start_subscribers : boolean := false; - signal start_limited_inbox, start_limited_inbox_subscriber, - limited_inbox_actor_done : boolean := false; - signal hello_subscriber_received : std_logic_vector(1 to 2) := "ZZ"; - - constant com_logger : logger_t := get_logger("vunit_lib:com"); -begin - test_runner : process - variable actor_to_destroy, actor_to_keep, actor, actor2, self, - receiver, server, deferred_actor, publisher, subscriber : actor_t; - variable status : com_status_t; - variable receipt, receipt2 : receipt_t; - variable n_actors : natural; - variable message : message_ptr_t; - variable reply_message : message_ptr_t; - variable request_message : message_ptr_t; - variable t_start, t_stop : time; - variable ack : boolean; - begin - test_runner_setup(runner, runner_cfg); - allow_timeout; - allow_deprecated; - - while test_suite loop - reset_messenger; - self := create("test runner"); - if run("Test that a created actor can be destroyed") then - actor_to_destroy := create("actor to destroy"); - actor_to_keep := create("actor to keep"); - n_actors := num_of_actors; - destroy(actor_to_destroy, status); - check(num_of_actors = n_actors - 1, "Expected one less actor"); - check(status = ok, "Expected destroy status to be ok"); - check(actor_to_destroy = null_actor_c, "Destroyed actor should be nullified"); - check(find("actor to destroy", false) = null_actor_c, "A destroyed actor should not be found"); - check(find("actor to keep", false) /= null_actor_c, - "Actors other than the one destroyed must not be affected"); - elsif run("Test that a non-existing actor cannot be destroyed") then - actor := null_actor_c; - mock(com_logger); - destroy(actor, status); - check_only_log(com_logger, "UNKNOWN ACTOR ERROR.", failure); - unmock(com_logger); - elsif run("Test that a created actor get the correct inbox size") then - actor := new_actor("actor with max inbox"); - check(inbox_size(actor) = positive'high, "Expected maximum sized inbox"); - actor2 := new_actor("actor with bounded inbox", 23); - check(inbox_size(actor2) = 23, "Expected inbox size = 23"); - check(inbox_size(null_actor_c) = 0, "Expected no inbox on null actor"); - check(inbox_size(find("actor to be created")) = 1, - "Expected inbox size on actor with deferred creation to be one"); - check(inbox_size(new_actor("actor to be created", 42)) = 42, - "Expected inbox size on actor with deferred creation to change to given value when created"); - elsif run("Test that a message can be deleted") then - message := compose("hello"); - delete(message); - check(message = null, "Message not deleted"); - elsif run("Test that an actor can send a message to another actor") then - start_receiver <= true; - wait for 1 ns; - receiver := find("receiver"); - message := compose("hello world", self); - send(net, receiver, message); - check(message.sender = self); - check(message.receiver = receiver); - wait until hello_world_received for 1 ns; - check(hello_world_received, "Expected ""hello world"" to be received at the server"); - elsif run("Test that an actor can send a message in response to another message from an a priori unknown actor") then - start_server <= true; - wait for 1 ns; - server := find("server"); - message := compose("request", self); - send(net, server, message, receipt); - check(receipt.status = ok, "Expected send to succeed"); - receive(net, self, message); - if check(message.status = ok, "Expected no receive problems") then - check(message.payload.all = "request acknowledge", "Expected ""request acknowledge"""); - end if; - delete(message); - elsif run("Test that an actor can send a message to itself") then - send(net, self, "hello", receipt); - receive(net, self, message); - check(message.status = ok, "Expected no receive problems"); - check_equal(message.payload.all, "hello"); - elsif run("Test that an actor can poll for incoming messages") then - receive(net, self, message, 0 ns); - check(message.payload = null, "Expected no message payload"); - check(message.status = timeout, "Expected timeout"); - send(net, self, self, "hello again", receipt); - check(receipt.status = ok, "Expected send to succeed"); - receive(net, self, message, 0 ns); - if check(message.status = ok, "Expected no problems with receive") then - check(message.payload.all = "hello again", "Expected ""hello again"""); - check(message.sender = self, "Expected message from myself"); - end if; - delete(message); - elsif run("Test that an actor can send to an actor with deferred creation") then - deferred_actor := find("deferred actor"); - send(net, deferred_actor, "hello actor to be created", receipt); - check(receipt.status = ok, "Expected send to succeed"); - deferred_actor := create("deferred actor"); - receive(net, deferred_actor, message); - if check(message.status = ok, "Expected no problems with receive") then - check(message.payload.all = "hello actor to be created", "Expected ""hello actor to be created"""); - end if; - delete(message); - elsif run("Test that empty messages can be sent") then - send(net, self, "", receipt); - check(receipt.status = ok, "Expected send to succeed"); - receive(net, self, message); - if check(message.status = ok, "Expected no problems with receive") then - check(message.payload.all = "", "Expected an empty message"); - end if; - delete(message); - elsif run("Test that each sent message gets an increasing message number") then - send(net, self, "", receipt); - check(receipt.id = 1, "Expected first receipt id to be 1"); - send(net, self, "", receipt); - check(receipt.id = 2, "Expected second receipt id to be 2"); - receive(net, self, message); - check(message.id = 1, "Expected first message id to be 1"); - receive(net, self, message); - check(message.id = 2, "Expected second message id to be 2"); - elsif run("Test that a limited-inbox receiver can receive as expected without blocking") then - start_limited_inbox <= true; - actor := find("limited inbox"); - t_start := now; - send(net, self, actor, "First message", receipt); - t_stop := now; - check_equal(t_stop - t_start, 0 ns, "Expected no blocking on first message"); - t_start := now; - send(net, self, actor, "Second message", receipt, 0 ns); - t_stop := now; - check_equal(t_stop - t_start, 0 ns, "Expected no blocking on second message"); - t_start := now; - send(net, actor, "Third message", receipt, 11 ns); - t_stop := now; - check_equal(t_stop - t_start, 10 ns, "Expected a 10 ns blocking period on third message"); - elsif run("Test that sending to a limited-inbox receiver times out as expected") then - start_limited_inbox <= true; - actor := find("limited inbox"); - send(net, actor, "First message", receipt); - send(net, actor, "Second message", receipt, 0 ns); - mock(com_logger); - send(net, actor, "Third message", receipt, 9 ns); - check_log(com_logger, "FULL INBOX ERROR.", failure); - check_only_log(com_logger, "FULL INBOX ERROR.", failure); - unmock(com_logger); - - elsif run("Test that an actor can publish messages to multiple subscribers") then - publisher := create("publisher"); - start_subscribers <= true; - wait for 1 ns; - publish(net, publisher, "hello subscriber", status); - check(status = ok, "Expected publish to succeed"); - wait until hello_subscriber_received = "11" for 1 ns; - check(hello_subscriber_received = "11", "Expected ""hello subscribers"" to be received at the subscribers"); - - elsif run("Test that a subscriber can unsubscribe") then - subscribe(self, self, status); - check(status = ok, "Expected subscription to be ok"); - publish(net, self, "hello subscriber", status); - check(status = ok, "Expected publish to succeed"); - receive(net, self, message, 0 ns); - check(message.status = ok, "Expected no problems with receive"); - check(message.payload.all = "hello subscriber", "Expected a ""hello subscriber"" message"); - unsubscribe(self, self, status); - publish(net, self, "hello subscriber", status); - check(status = ok, "Expected publish to succeed"); - receive(net, self, message, 0 ns); - check(message.status = timeout, "Expected no message"); - elsif run("Test that a destroyed subscriber is not addressed by the publisher") then - subscriber := create("subscriber"); - subscribe(subscriber, self, status); - check(status = ok, "Expected subscription to be ok"); - publish(net, self, "hello subscriber", status); - check(status = ok, "Expected publish to succeed"); - receive(net, subscriber, message, 0 ns); - if check(message.status = ok, "Expected no problems with receive") then - check(message.payload.all = "hello subscriber", "Expected a ""hello subscriber"" message"); - end if; - destroy(subscriber, status); - check(status = ok, "Expected destroy status to be ok"); - publish(net, self, "hello subscriber", status); - check(status = ok, "Expected publish to succeed. Got " & com_status_t'image(status) & "."); - elsif run("Test that an actor can only subscribe once to the same publisher") then - subscribe(self, self, status); - check(status = ok, "Expected subscription to be ok"); - mock(com_logger); - subscribe(self, self, status); - check_only_log(com_logger, "ALREADY A SUBSCRIBER ERROR.", failure); - unmock(com_logger); - - elsif run("Test that a client can wait for an out-of-order request reply") then - start_server2 <= true; - server := find("server2"); - send(net, self, server, "request1", receipt); - send(net, self, server, "request2", receipt2); - - receive_reply(net, self, receipt2.id, reply_message); - check(reply_message.payload.all = "reply2", "Expected ""reply2"""); - check(reply_message.request_id = receipt2.id, "Expected request_id = " & integer'image(receipt2.id) & - " but got " & integer'image(reply_message.request_id)); - receive_reply(net, self, receipt.id, reply_message); - check(reply_message.payload.all = "reply1", "Expected ""reply1"""); - check(reply_message.request_id = receipt.id, "Expected request_id = " & integer'image(receipt.id) & - " but got " & integer'image(reply_message.request_id)); - delete(reply_message); - elsif run("Test that a synchronous request can be made") then - start_server3 <= true; - server := find("server3"); - - request(net, self, server, "request1", reply_message); - check(reply_message.payload.all = "reply1", "Expected ""reply1"""); - delete(reply_message); - - request(net, self, server, "request2", ack, status); - check(status = ok, "Expected request to succeed"); - check(ack, "Expected positive acknowledgement"); - - request(net, self, server, "request3", ack, status); - check(status = ok, "Expected request to succeed"); - check(not ack, "Expected negative acknowledgement"); - - t_start := now; - request(net, self, server, "request4", reply_message, 3 ns); - check(reply_message.status = timeout, "Expected timeout"); - check(now - t_start = 3 ns, "Expected timeout after 3 ns"); - delete(reply_message); - - send(net, self, server, "A message", receipt); - send(net, self, server, "This will sit in the inbox for 3 ns", receipt); - t_start := now; - request(net, self, server, - "The send part will block for 3 ns, the receive part should timout after 2 to get a total of 5 ns", - reply_message, 5 ns); - check(reply_message.status = timeout, "Expected timeout"); - check(now - t_start = 5 ns, "Expected timeout after 5 ns"); - delete(reply_message); - elsif run("Test that an anonymous request can be made") then - start_server5 <= true; - server := find("server5"); - - request_message := compose("request"); - send(net, server, request_message); - wait for 10 ns; - receive_reply(net, request_message, reply_message); - check_equal(reply_message.payload.all, "reply"); - - request_message := compose("request2"); - send(net, server, request_message); - receive_reply(net, request_message, reply_message); - check_equal(reply_message.payload.all, "reply2"); - - request_message := compose("request3"); - request(net, server, request_message, reply_message); - check_equal(reply_message.payload.all, "reply3"); - end if; - end loop; - - test_runner_cleanup(runner); - wait; - end process; - - test_runner_watchdog(runner, 100 ms); - - receiver : process is - variable self : actor_t; - variable message : message_ptr_t; - variable status : com_status_t; - begin - wait until start_receiver; - self := create("receiver"); - wait_for_messages(net, self, status); - message := get_message(self); - if check(message.payload.all = "hello world", "Expected ""hello world""") then - hello_world_received <= true; - end if; - delete(message); - wait; - end process receiver; - - server : process is - variable self : actor_t; - variable message : message_ptr_t; - variable receipt : receipt_t; - begin - wait until start_server; - self := create("server"); - receive(net, self, message); - if check(message.payload.all = "request", "Expected ""request""") then - send(net, message.sender, "request acknowledge", receipt); - check(receipt.status = ok, "Expected send to succeed"); - end if; - delete(message); - wait; - end process server; - - subscribers : for i in 1 to 2 generate - process is - variable self, publisher : actor_t; - variable message : message_ptr_t; - variable status : com_status_t; - begin - wait until start_subscribers; - self := create("subscriber " & integer'image(i)); - publisher := find("publisher"); - subscribe(self, publisher, status); - receive(net, self, message); - if check(message.payload.all = "hello subscriber", "Expected ""hello subscriber""") then - hello_subscriber_received(i) <= '1'; - hello_subscriber_received(3 - i) <= 'Z'; - end if; - delete(message); - wait; - end process; - end generate subscribers; - - server2 : process is - variable self : actor_t; - variable request_message1, request_message2 : message_ptr_t; - variable receipt : receipt_t; - begin - wait until start_server2; - self := create("server2"); - receive(net, self, request_message1); - check(request_message1.payload.all = "request1", "Expected ""request1"""); - receive(net, self, request_message2); - check(request_message2.payload.all = "request2", "Expected ""request2"""); - - reply(net, request_message2.sender, request_message2.id, "reply2", receipt); - check(receipt.status = ok, "Expected reply to succeed"); - reply(net, request_message1.sender, request_message1.id, "reply1", receipt); - check(receipt.status = ok, "Expected reply to succeed"); - - delete(request_message1); - delete(request_message2); - wait; - end process server2; - - server3 : process is - variable self : actor_t; - variable request_message : message_ptr_t; - variable receipt : receipt_t; - begin - wait until start_server3; - self := create("server3", 1); - - receive(net, self, request_message); - check(request_message.payload.all = "request1", "Expected ""request1"""); - reply(net, request_message.sender, request_message.id, "reply1", receipt); - check(receipt.status = ok, "Expected reply to succeed"); - delete(request_message); - - receive(net, self, request_message); - check(request_message.payload.all = "request2", "Expected ""request2"""); - acknowledge(net, request_message.sender, request_message.id, true, receipt); - check(receipt.status = ok, "Expected acknowledge to succeed"); - delete(request_message); - - receive(net, self, request_message); - acknowledge(net, request_message.sender, request_message.id, false, receipt); - delete(request_message); - - receive(net, self, request_message); - delete(request_message); - - receive(net, self, request_message); - wait for 3 ns; - receive(net, self, request_message); - delete(request_message); - wait; - end process server3; - - server5 : process is - variable self : actor_t; - variable request_message : message_ptr_t; - variable reply_message : message_ptr_t; - begin - wait until start_server5; - self := create("server5"); - - receive(net, self, request_message); - check_equal(request_message.payload.all, "request"); - reply_message := compose("reply"); - reply(net, request_message, reply_message); - - receive(net, self, request_message); - check_equal(request_message.payload.all, "request2"); - reply_message := compose("reply2"); - wait for 10 ns; - reply(net, request_message, reply_message); - - receive(net, self, request_message); - check_equal(request_message.payload.all, "request3"); - reply_message := compose("reply3"); - reply(net, request_message, reply_message); - - wait; - end process server5; - - limited_inbox_actor : process is - variable self : actor_t; - variable msg : msg_t; - begin - wait until start_limited_inbox; - self := create("limited inbox", 2); - wait for 10 ns; - receive(net, self, msg); - receive(net, self, msg); - receive(net, self, msg); - limited_inbox_actor_done <= true; - wait; - end process limited_inbox_actor; - - limited_inbox_subscriber : process is - variable self : actor_t; - variable message : message_ptr_t; - begin - wait until start_limited_inbox_subscriber; - self := create("limited inbox subscriber", 1); - subscribe(self, find("test runner")); - wait for 10 ns; - receive(net, self, message); - wait; - end process limited_inbox_subscriber; - - -end test_fixture; diff --git a/vunit/vhdl/data_types/src/codec.vhd b/vunit/vhdl/data_types/src/codec.vhd index 798942570..c3fcbcde5 100644 --- a/vunit/vhdl/data_types/src/codec.vhd +++ b/vunit/vhdl/data_types/src/codec.vhd @@ -451,9 +451,10 @@ package body codec_pkg is function get_range ( constant code : string) return range_t is - constant range_left : integer := decode(code(1 to 4)); - constant range_right : integer := decode(code(5 to 8)); - constant is_ascending : boolean := decode(code(9 to 9)); + constant left : positive := code'left; + constant range_left : integer := decode(code(left to left + 3)); + constant range_right : integer := decode(code(left + 4 to left + 7)); + constant is_ascending : boolean := decode(code(left + 8 to left + 8)); constant ret_val_ascending : range_t(range_left to range_right) := (others => '0'); constant ret_val_descending : range_t(range_left downto range_right) := (others => '0'); begin diff --git a/vunit/vhdl/data_types/src/data_types_context.vhd b/vunit/vhdl/data_types/src/data_types_context.vhd index b31fa7602..519bf975c 100644 --- a/vunit/vhdl/data_types/src/data_types_context.vhd +++ b/vunit/vhdl/data_types/src/data_types_context.vhd @@ -7,12 +7,9 @@ context data_types_context is library vunit_lib; use vunit_lib.integer_vector_ptr_pkg.all; - use vunit_lib.integer_vector_ptr_pool_pkg.all; use vunit_lib.integer_array_pkg.all; use vunit_lib.string_ptr_pkg.all; use vunit_lib.queue_pkg.all; - use vunit_lib.queue_pool_pkg.all; use vunit_lib.string_ptr_pkg.all; - use vunit_lib.string_ptr_pool_pkg.all; use vunit_lib.dict_pkg.all; end context; diff --git a/vunit/vhdl/data_types/src/dict_pkg.vhd b/vunit/vhdl/data_types/src/dict_pkg.vhd index 394cdc746..08eceea77 100644 --- a/vunit/vhdl/data_types/src/dict_pkg.vhd +++ b/vunit/vhdl/data_types/src/dict_pkg.vhd @@ -5,9 +5,7 @@ -- Copyright (c) 2014-2019, Lars Asplund lars.anders.asplund@gmail.com use work.string_ptr_pkg.all; -use work.string_ptr_pool_pkg.all; use work.integer_vector_ptr_pkg.all; -use work.integer_vector_ptr_pool_pkg.all; package dict_pkg is type dict_t is record @@ -51,8 +49,6 @@ package dict_pkg is end package; package body dict_pkg is - constant int_pool : integer_vector_ptr_pool_t := new_integer_vector_ptr_pool; - constant str_pool : string_ptr_pool_t := new_string_ptr_pool; constant meta_num_keys : natural := 0; constant meta_length : natural := meta_num_keys+1; constant new_bucket_size : natural := 1; @@ -63,17 +59,17 @@ package body dict_pkg is variable tmp : integer_vector_ptr_t; constant num_buckets : natural := 1; begin - dict := (p_meta => new_integer_vector_ptr(int_pool, meta_length), - p_bucket_lengths => new_integer_vector_ptr(int_pool, num_buckets), - p_bucket_keys => new_integer_vector_ptr(int_pool, num_buckets), - p_bucket_values => new_integer_vector_ptr(int_pool, num_buckets)); + dict := (p_meta => new_integer_vector_ptr(meta_length), + p_bucket_lengths => new_integer_vector_ptr(num_buckets), + p_bucket_keys => new_integer_vector_ptr(num_buckets), + p_bucket_values => new_integer_vector_ptr(num_buckets)); set(dict.p_meta, meta_num_keys, 0); for i in 0 to length(dict.p_bucket_lengths)-1 loop -- Zero items in bucket set(dict.p_bucket_lengths, i, 0); - tmp := new_integer_vector_ptr(int_pool, new_bucket_size); + tmp := new_integer_vector_ptr(new_bucket_size); set(dict.p_bucket_keys, i, to_integer(tmp)); - tmp := new_integer_vector_ptr(int_pool, new_bucket_size); + tmp := new_integer_vector_ptr(new_bucket_size); set(dict.p_bucket_values, i, to_integer(tmp)); end loop; return dict; @@ -100,16 +96,20 @@ package body dict_pkg is for idx in 0 to bucket_length-1 loop key := to_string_ptr(get(bucket_keys, idx)); value := to_string_ptr(get(bucket_values, idx)); - recycle(str_pool, key); - recycle(str_pool, value); + deallocate(key); + deallocate(value); end loop; - recycle(int_pool, bucket_values); - recycle(int_pool, bucket_keys); + deallocate(bucket_values); + deallocate(bucket_keys); end loop; - recycle(int_pool, dict.p_meta); - recycle(int_pool, dict.p_bucket_lengths); - recycle(int_pool, dict.p_bucket_values); - recycle(int_pool, dict.p_bucket_keys); + deallocate(dict.p_meta); + deallocate(dict.p_bucket_lengths); + deallocate(dict.p_bucket_values); + deallocate(dict.p_bucket_keys); + dict.p_meta := null_ptr; + dict.p_bucket_lengths := null_ptr; + dict.p_bucket_values := null_ptr; + dict.p_bucket_keys := null_ptr; end; -- DJB2 hash @@ -157,8 +157,8 @@ package body dict_pkg is if deallocate_item then key := to_string_ptr(get(bucket_keys, i)); value := to_string_ptr(get(bucket_values, i)); - recycle(str_pool, key); - recycle(str_pool, value); + deallocate(key); + deallocate(value); end if; set(bucket_keys, i, get(bucket_keys, bucket_length-1)); set(bucket_values, i, get(bucket_values, bucket_length-1)); @@ -241,8 +241,8 @@ package body dict_pkg is -- Create new buckets for i in old_num_buckets to num_buckets-1 loop - set(dict.p_bucket_keys, i, to_integer(new_integer_vector_ptr(int_pool, new_bucket_size))); - set(dict.p_bucket_values, i, to_integer(new_integer_vector_ptr(int_pool, new_bucket_size))); + set(dict.p_bucket_keys, i, to_integer(new_integer_vector_ptr(new_bucket_size))); + set(dict.p_bucket_values, i, to_integer(new_integer_vector_ptr(new_bucket_size))); set(dict.p_bucket_lengths, i, 0); end loop; @@ -260,7 +260,7 @@ package body dict_pkg is -- Reuse existing value storage reallocate(old_value_ptr, value); else - insert_new(dict, key_hash, new_string_ptr(str_pool, key), new_string_ptr(str_pool, value)); + insert_new(dict, key_hash, new_string_ptr(key), new_string_ptr(value)); end if; end; diff --git a/vunit/vhdl/data_types/src/integer_array_pkg-body.vhd b/vunit/vhdl/data_types/src/integer_array_pkg-body.vhd index c4f5ca6ec..5bb2594a6 100644 --- a/vunit/vhdl/data_types/src/integer_array_pkg-body.vhd +++ b/vunit/vhdl/data_types/src/integer_array_pkg-body.vhd @@ -6,6 +6,9 @@ use std.textio.all; +use work.codec_pkg.all; +use work.codec_builder_pkg.all; + package body integer_array_pkg is type binary_file_t is file of character; @@ -453,4 +456,45 @@ package body integer_array_pkg is file_close(fread); return arr; end; + + function encode ( + data : integer_array_t + ) return string is begin + return encode(data.length) & + encode(data.width) & + encode(data.height) & + encode(data.depth) & + encode(data.bit_width) & + encode(data.is_signed) & + encode(data.lower_limit) & + encode(data.upper_limit) & + encode(data.data); + end; + + procedure decode ( + code : string; + index : inout positive; + result : out integer_array_t + ) is begin + decode(code, index, result.length); + decode(code, index, result.width); + decode(code, index, result.height); + decode(code, index, result.depth); + decode(code, index, result.bit_width); + decode(code, index, result.is_signed); + decode(code, index, result.lower_limit); + decode(code, index, result.upper_limit); + decode(code, index, result.data); + end; + + function decode ( + code : string + ) return integer_array_t is + variable ret_val : integer_array_t; + variable index : positive := code'left; + begin + decode(code, index, ret_val); + return ret_val; + end; + end package body; diff --git a/vunit/vhdl/data_types/src/integer_array_pkg.vhd b/vunit/vhdl/data_types/src/integer_array_pkg.vhd index cc20a3bf0..b5e6e558f 100644 --- a/vunit/vhdl/data_types/src/integer_array_pkg.vhd +++ b/vunit/vhdl/data_types/src/integer_array_pkg.vhd @@ -178,4 +178,19 @@ package integer_array_pkg is arr : integer_array_t; file_name : string ); + + function encode ( + data : integer_array_t + ) return string; + + procedure decode ( + code : string; + index : inout positive; + result : out integer_array_t + ); + + function decode ( + code : string + ) return integer_array_t; + end package; diff --git a/vunit/vhdl/data_types/src/integer_vector_ptr_pkg-body-200x.vhd b/vunit/vhdl/data_types/src/integer_vector_ptr_pkg-body-200x.vhd index d81be6175..129054f4a 100644 --- a/vunit/vhdl/data_types/src/integer_vector_ptr_pkg-body-200x.vhd +++ b/vunit/vhdl/data_types/src/integer_vector_ptr_pkg-body-200x.vhd @@ -5,145 +5,215 @@ -- Copyright (c) 2014-2019, Lars Asplund lars.anders.asplund@gmail.com package body integer_vector_ptr_pkg is + type integer_vector_ptr_storage_t is protected - impure function new_integer_vector_ptr ( + + impure function new_ptr ( length : natural := 0; value : val_t := 0 ) return natural; + procedure check_valid ( + ref : index_t + ); + procedure deallocate ( - ref : natural + ref : index_t + ); + + procedure reallocate_storage ( + length : positive + ); + + procedure reallocate_stack ( + length : positive ); impure function length ( - ref : natural - ) return integer; + ref : index_t + ) return natural; procedure set ( - ref : natural; + ref : index_t; index : natural; value : val_t ); impure function get ( - ref : natural; + ref : index_t; index : natural ) return val_t; procedure reallocate ( - ref : natural; + ref : index_t; length : natural; value : val_t := 0 ); procedure resize ( - ref : natural; + ref : index_t; length : natural; drop : natural := 0; - value : val_t := 0 + value : val_t := 0; + rotate : natural := 0 ); end protected; type integer_vector_ptr_storage_t is protected body - variable current_index : integer := 0; - variable ptrs : vava_t := null; - impure function new_integer_vector_ptr ( + -- Pointer storage + variable storage : vava_t := new vav_t'(0 to 2**16 - 1 => null); + variable storage_index : natural := 0; + + -- Stack of unused storage indices + variable stack : integer_vector_access_t := new integer_vector_t'(0 to 2**16 - 1 => -1); + variable stack_index : natural := 0; + + impure function new_ptr ( length : natural := 0; value : val_t := 0 ) return natural is - variable old_ptrs : vava_t; - variable retval : ptr_t := (ref => current_index); + variable ref : index_t; begin - if ptrs = null then - ptrs := new vav_t'(0 => null); - elsif ptrs'length <= current_index then - -- Reallocate ptr pointers to larger ptr - -- Use more size to trade size for speed - old_ptrs := ptrs; - ptrs := new vav_t'(0 to ptrs'length + 2**16 => null); - for i in old_ptrs'range loop - ptrs(i) := old_ptrs(i); - end loop; - deallocate(old_ptrs); + if stack_index > 0 then + stack_index := stack_index - 1; + ref := stack(stack_index); + else + if storage_index >= storage'length then + reallocate_storage(storage'length + 2**16); + end if; + ref := storage_index; + storage_index := storage_index + 1; end if; - ptrs(current_index) := new integer_vector_t'(0 to length-1 => value); - current_index := current_index + 1; - return retval.ref; + storage(ref) := new vec_t'(0 to length - 1 => value); + return ref; + end; + + procedure check_valid ( + ref : index_t + ) is begin + assert 0 <= ref and ref < storage_index report "invalid pointer"; + assert storage(ref) /= null report "unallocated pointer"; end; procedure deallocate ( - ref : natural + ref : index_t ) is begin - deallocate(ptrs(ref)); - ptrs(ref) := null; + if ref >= 0 then + check_valid(ref); + if stack_index >= stack'length then + reallocate_stack(stack'length + 2**16); + end if; + stack(stack_index) := ref; + stack_index := stack_index + 1; + deallocate(storage(ref)); + storage(ref) := null; + end if; + end; + + procedure reallocate_storage ( + length : positive + ) is + variable old_storage : vava_t; + begin + old_storage := storage; + storage := new vav_t'(0 to length - 1 => null); + for i in old_storage'range loop + storage(i) := old_storage(i); + end loop; + deallocate(old_storage); + end; + + procedure reallocate_stack ( + length : positive + ) is + variable old_stack : integer_vector_access_t; + begin + old_stack := stack; + stack := new integer_vector_t'(0 to length - 1 => -1); + for i in old_stack'range loop + stack(i) := old_stack(i); + end loop; + deallocate(old_stack); end; impure function length ( - ref : natural - ) return integer is begin - return ptrs(ref)'length; + ref : index_t + ) return natural is begin + check_valid(ref); + return storage(ref)'length; end; procedure set ( - ref : natural; + ref : index_t; index : natural; value : val_t ) is begin - ptrs(ref)(index) := value; + check_valid(ref); + storage(ref)(index) := value; end; impure function get ( - ref : natural; + ref : index_t; index : natural ) return val_t is begin - return ptrs(ref)(index); + check_valid(ref); + return storage(ref)(index); end; procedure reallocate ( - ref : natural; + ref : index_t; length : natural; value : val_t := 0 ) is begin - deallocate(ptrs(ref)); - ptrs(ref) := new integer_vector_t'(0 to length - 1 => value); + check_valid(ref); + deallocate(storage(ref)); + storage(ref) := new vec_t'(0 to length - 1 => value); end; procedure resize ( - ref : natural; + ref : index_t; length : natural; drop : natural := 0; - value : val_t := 0 + value : val_t := 0; + rotate : natural := 0 ) is - variable old_ptr, new_ptr : integer_vector_access_t; - variable min_len : natural := length; + variable old_ptr : va_t; + variable new_ptr : va_t := new vec_t'(0 to length - 1 => value); + variable min_length : natural; + variable index : natural; begin - new_ptr := new integer_vector_t'(0 to length - 1 => value); - old_ptr := ptrs(ref); - if min_len > old_ptr'length - drop then - min_len := old_ptr'length - drop; + check_valid(ref); + assert drop = 0 or rotate = 0 report "can't combine drop and rotate"; + old_ptr := storage(ref); + min_length := old_ptr'length - drop; + if length < min_length then + min_length := length; end if; - for i in 0 to min_len-1 loop - new_ptr(i) := old_ptr(drop + i); + for i in 0 to min_length - 1 loop + index := (drop + rotate + i) mod old_ptr'length; + new_ptr(i) := old_ptr(index); end loop; - ptrs(ref) := new_ptr; + storage(ref) := new_ptr; deallocate(old_ptr); end; end protected body; - shared variable integer_vector_ptr_storage : integer_vector_ptr_storage_t; + shared variable ptr_storage : integer_vector_ptr_storage_t; function to_integer ( value : ptr_t - ) return integer is begin + ) return index_t is begin return value.ref; end; impure function to_integer_vector_ptr ( - value : val_t + value : index_t ) return ptr_t is begin - -- @TODO maybe assert that the ref is valid + if value >= 0 then + ptr_storage.check_valid(value); + end if; return (ref => value); end; @@ -151,19 +221,19 @@ package body integer_vector_ptr_pkg is length : natural := 0; value : val_t := 0 ) return ptr_t is begin - return (ref => integer_vector_ptr_storage.new_integer_vector_ptr(length, value)); + return (ref => ptr_storage.new_ptr(length, value)); end; procedure deallocate ( ptr : ptr_t ) is begin - integer_vector_ptr_storage.deallocate(ptr.ref); + ptr_storage.deallocate(ptr.ref); end; impure function length ( ptr : ptr_t - ) return integer is begin - return integer_vector_ptr_storage.length(ptr.ref); + ) return natural is begin + return ptr_storage.length(ptr.ref); end; procedure set ( @@ -171,14 +241,14 @@ package body integer_vector_ptr_pkg is index : natural; value : val_t ) is begin - integer_vector_ptr_storage.set(ptr.ref, index, value); + ptr_storage.set(ptr.ref, index, value); end; impure function get ( ptr : ptr_t; index : natural ) return val_t is begin - return integer_vector_ptr_storage.get(ptr.ref, index); + return ptr_storage.get(ptr.ref, index); end; procedure reallocate ( @@ -186,16 +256,17 @@ package body integer_vector_ptr_pkg is length : natural; value : val_t := 0 ) is begin - integer_vector_ptr_storage.reallocate(ptr.ref, length, value); + ptr_storage.reallocate(ptr.ref, length, value); end; procedure resize ( ptr : ptr_t; length : natural; drop : natural := 0; - value : val_t := 0 + value : val_t := 0; + rotate : natural := 0 ) is begin - integer_vector_ptr_storage.resize(ptr.ref, length, drop, value); + ptr_storage.resize(ptr.ref, length, drop, value, rotate); end; function encode ( @@ -223,3 +294,4 @@ package body integer_vector_ptr_pkg is end; end package body; + diff --git a/vunit/vhdl/data_types/src/integer_vector_ptr_pkg-body-93.vhd b/vunit/vhdl/data_types/src/integer_vector_ptr_pkg-body-93.vhd index 4ff7ac8bc..230fd7dc9 100644 --- a/vunit/vhdl/data_types/src/integer_vector_ptr_pkg-body-93.vhd +++ b/vunit/vhdl/data_types/src/integer_vector_ptr_pkg-body-93.vhd @@ -5,43 +5,88 @@ -- Copyright (c) 2014-2019, Lars Asplund lars.anders.asplund@gmail.com package body integer_vector_ptr_pkg is - shared variable current_index : integer := 0; - shared variable ptrs : vava_t := null; + + -- Pointer storage + shared variable storage : vava_t := new vav_t'(0 to 2**16 - 1 => null); + shared variable storage_index : natural := 0; + + -- Stack of unused storage indices + shared variable stack : integer_vector_access_t := new integer_vector_t'(0 to 2**16 - 1 => -1); + shared variable stack_index : natural := 0; + + procedure reallocate_storage ( + length : positive + ) is + variable old_storage : vava_t; + begin + old_storage := storage; + storage := new vav_t'(0 to length - 1 => null); + for i in old_storage'range loop + storage(i) := old_storage(i); + end loop; + deallocate(old_storage); + end; + + procedure reallocate_stack ( + length : positive + ) is + variable old_stack : integer_vector_access_t; + begin + old_stack := stack; + stack := new integer_vector_t'(0 to length - 1 => -1); + for i in old_stack'range loop + stack(i) := old_stack(i); + end loop; + deallocate(old_stack); + end; impure function new_integer_vector_ptr ( length : natural := 0; value : val_t := 0 ) return ptr_t is - variable old_ptrs : vava_t; + variable ref : index_t; begin - if ptrs = null then - ptrs := new vav_t'(0 => null); - elsif ptrs'length <= current_index then - -- Reallocate ptr pointers to larger ptr - -- Use more size to trade size for speed - old_ptrs := ptrs; - ptrs := new vav_t'(0 to ptrs'length + 2**16 => null); - for i in old_ptrs'range loop - ptrs(i) := old_ptrs(i); - end loop; - deallocate(old_ptrs); + if stack_index > 0 then + stack_index := stack_index - 1; + ref := stack(stack_index); + else + if storage_index >= storage'length then + reallocate_storage(storage'length + 2**16); + end if; + ref := storage_index; + storage_index := storage_index + 1; end if; - ptrs(current_index) := new integer_vector_t'(0 to length-1 => value); - current_index := current_index + 1; - return (ref => current_index-1); + storage(ref) := new vec_t'(0 to length - 1 => value); + return (ref => ref); + end; + + procedure check_valid ( + ref : index_t + ) is begin + assert 0 <= ref and ref < storage_index report "invalid pointer"; + assert storage(ref) /= null report "unallocated pointer"; end; procedure deallocate ( ptr : ptr_t ) is begin - deallocate(ptrs(ptr.ref)); - ptrs(ptr.ref) := null; + if ptr.ref > 0 then + check_valid(ptr.ref); + if stack_index >= stack'length then + reallocate_stack(stack'length + 2**16); + end if; + stack(stack_index) := ptr.ref; + stack_index := stack_index + 1; + deallocate(storage(ptr.ref)); + storage(ptr.ref) := null; + end if; end; impure function length ( ptr : ptr_t - ) return integer is begin - return ptrs(ptr.ref)'length; + ) return natural is begin + check_valid(ptr.ref); + return storage(ptr.ref)'length; end; procedure set ( @@ -49,14 +94,16 @@ package body integer_vector_ptr_pkg is index : natural; value : val_t ) is begin - ptrs(ptr.ref)(index) := value; + check_valid(ptr.ref); + storage(ptr.ref)(index) := value; end; impure function get ( ptr : ptr_t; index : natural ) return val_t is begin - return ptrs(ptr.ref)(index); + check_valid(ptr.ref); + return storage(ptr.ref)(index); end; procedure reallocate ( @@ -64,41 +111,50 @@ package body integer_vector_ptr_pkg is length : natural; value : val_t := 0 ) is begin - deallocate(ptrs(ptr.ref)); - ptrs(ptr.ref) := new integer_vector_t'(0 to length - 1 => value); + check_valid(ptr.ref); + deallocate(storage(ptr.ref)); + storage(ptr.ref) := new vec_t'(0 to length - 1 => value); end; procedure resize ( ptr : ptr_t; length : natural; drop : natural := 0; - value : val_t := 0 + value : val_t := 0; + rotate : natural := 0 ) is - variable old_ptr, new_ptr : integer_vector_access_t; - variable min_len : natural := length; + variable old_ptr : va_t; + variable new_ptr : va_t := new vec_t'(0 to length - 1 => value); + variable min_length : natural; + variable index : natural; begin - new_ptr := new integer_vector_t'(0 to length - 1 => value); - old_ptr := ptrs(ptr.ref); - if min_len > old_ptr'length - drop then - min_len := old_ptr'length - drop; + check_valid(ptr.ref); + assert drop = 0 or rotate = 0 report "can't combine drop and rotate"; + old_ptr := storage(ptr.ref); + min_length := old_ptr'length - drop; + if length < min_length then + min_length := length; end if; - for i in 0 to min_len-1 loop - new_ptr(i) := old_ptr(drop + i); + for i in 0 to min_length - 1 loop + index := (drop + rotate + i) mod old_ptr'length; + new_ptr(i) := old_ptr(index); end loop; - ptrs(ptr.ref) := new_ptr; + storage(ptr.ref) := new_ptr; deallocate(old_ptr); end; function to_integer ( value : ptr_t - ) return integer is begin + ) return index_t is begin return value.ref; end; impure function to_integer_vector_ptr ( - value : val_t + value : index_t ) return ptr_t is begin - -- @TODO maybe assert that the ref is valid + if value >= 0 then + check_valid(value); + end if; return (ref => value); end; @@ -127,3 +183,4 @@ package body integer_vector_ptr_pkg is end; end package body; + diff --git a/vunit/vhdl/data_types/src/integer_vector_ptr_pkg.vhd b/vunit/vhdl/data_types/src/integer_vector_ptr_pkg.vhd index b61337c19..0ee01a104 100644 --- a/vunit/vhdl/data_types/src/integer_vector_ptr_pkg.vhd +++ b/vunit/vhdl/data_types/src/integer_vector_ptr_pkg.vhd @@ -3,7 +3,6 @@ -- You can obtain one at http://mozilla.org/MPL/2.0/. -- -- Copyright (c) 2014-2019, Lars Asplund lars.anders.asplund@gmail.com - -- -- The purpose of this package is to provide an integer vector access type (pointer) -- that can itself be used in arrays and returned from functions unlike a @@ -17,24 +16,29 @@ use work.codec_pkg.all; use work.codec_builder_pkg.all; package integer_vector_ptr_pkg is + subtype index_t is integer range -1 to integer'high; + type integer_vector_ptr_t is record ref : index_t; end record; - constant null_ptr : integer_vector_ptr_t := (ref => -1); - alias ptr_t is integer_vector_ptr_t; - alias val_t is integer; - alias vec_t is integer_vector_t; - alias vav_t is integer_vector_access_vector_t; - alias vava_t is integer_vector_access_vector_access_t; + constant null_integer_vector_ptr : integer_vector_ptr_t := (ref => -1); + alias null_ptr is null_integer_vector_ptr; + + alias ptr_t is integer_vector_ptr_t; + alias val_t is integer; + alias vec_t is integer_vector_t; + alias va_t is integer_vector_access_t; + alias vav_t is integer_vector_access_vector_t; + alias vava_t is integer_vector_access_vector_access_t; function to_integer ( value : ptr_t - ) return integer; + ) return index_t; impure function to_integer_vector_ptr ( - value : val_t + value : index_t ) return ptr_t; impure function new_integer_vector_ptr ( @@ -48,7 +52,7 @@ package integer_vector_ptr_pkg is impure function length ( ptr : ptr_t - ) return integer; + ) return natural; procedure set ( ptr : ptr_t; @@ -71,7 +75,8 @@ package integer_vector_ptr_pkg is ptr : ptr_t; length : natural; drop : natural := 0; - value : val_t := 0 + value : val_t := 0; + rotate : natural := 0 ); function encode ( @@ -94,3 +99,4 @@ package integer_vector_ptr_pkg is constant integer_vector_ptr_t_code_length : positive := integer_code_length; end package; + diff --git a/vunit/vhdl/data_types/src/queue_pkg-2008.vhd b/vunit/vhdl/data_types/src/queue_pkg-2008.vhd index c6ebfdde4..89ed51a69 100644 --- a/vunit/vhdl/data_types/src/queue_pkg-2008.vhd +++ b/vunit/vhdl/data_types/src/queue_pkg-2008.vhd @@ -10,9 +10,9 @@ use ieee.float_pkg.all; use work.queue_pkg.all; use work.codec_2008_pkg.all; -use work.codec_builder_2008_pkg.all; package queue_2008_pkg is + procedure push ( queue : queue_t; value : boolean_vector @@ -96,111 +96,129 @@ package queue_2008_pkg is alias push_float is push[queue_t, float]; alias pop_float is pop[queue_t return float]; + end package; package body queue_2008_pkg is + procedure push ( queue : queue_t; value : boolean_vector ) is begin - push_type(queue, vhdl_boolean_vector); - push_variable_string(queue, encode(value)); + push_item(queue, encode(vhdl_boolean_vector) & encode(value)); end; impure function pop ( queue : queue_t - ) return boolean_vector is begin - check_type(queue, vhdl_boolean_vector); - return decode(pop_variable_string(queue)); + ) return boolean_vector is + constant str : string := pop_item(queue); + constant typ : queue_item_type_t := decode(str(1)); + begin + check_type(typ, vhdl_boolean_vector); + return decode(str(2 to str'right)); end; procedure push ( queue : queue_t; value : integer_vector ) is begin - push_type(queue, vhdl_integer_vector); - push_variable_string(queue, encode(value)); + push_item(queue, encode(vhdl_integer_vector) & encode(value)); end; impure function pop ( queue : queue_t - ) return integer_vector is begin - check_type(queue, vhdl_integer_vector); - return decode(pop_variable_string(queue)); + ) return integer_vector is + constant str : string := pop_item(queue); + constant typ : queue_item_type_t := decode(str(1)); + begin + check_type(typ, vhdl_integer_vector); + return decode(str(2 to str'right)); end; procedure push ( queue : queue_t; value : real_vector ) is begin - push_type(queue, vhdl_real_vector); - push_variable_string(queue, encode(value)); + push_item(queue, encode(vhdl_real_vector) & encode(value)); end; impure function pop ( queue : queue_t - ) return real_vector is begin - check_type(queue, vhdl_real_vector); - return decode(pop_variable_string(queue)); + ) return real_vector is + constant str : string := pop_item(queue); + constant typ : queue_item_type_t := decode(str(1)); + begin + check_type(typ, vhdl_real_vector); + return decode(str(2 to str'right)); end; procedure push ( queue : queue_t; value : time_vector ) is begin - push_type(queue, vhdl_time_vector); - push_variable_string(queue, encode(value)); + push_item(queue, encode(vhdl_time_vector) & encode(value)); end; impure function pop ( queue : queue_t - ) return time_vector is begin - check_type(queue, vhdl_time_vector); - return decode(pop_variable_string(queue)); + ) return time_vector is + constant str : string := pop_item(queue); + constant typ : queue_item_type_t := decode(str(1)); + begin + check_type(typ, vhdl_time_vector); + return decode(str(2 to str'right)); end; procedure push ( queue : queue_t; value : ufixed ) is begin - push_type(queue, ieee_ufixed); - push_variable_string(queue, encode(value)); + push_item(queue, encode(ieee_ufixed) & encode(value)); end; impure function pop ( queue : queue_t - ) return ufixed is begin - check_type(queue, ieee_ufixed); - return decode(pop_variable_string(queue)); + ) return ufixed is + constant str : string := pop_item(queue); + constant typ : queue_item_type_t := decode(str(1)); + begin + check_type(typ, ieee_ufixed); + return decode(str(2 to str'right)); end; procedure push ( queue : queue_t; value : sfixed ) is begin - push_type(queue, ieee_sfixed); - push_variable_string(queue, encode(value)); + push_item(queue, encode(ieee_sfixed) & encode(value)); end; impure function pop ( queue : queue_t - ) return sfixed is begin - check_type(queue, ieee_sfixed); - return decode(pop_variable_string(queue)); + ) return sfixed is + constant str : string := pop_item(queue); + constant typ : queue_item_type_t := decode(str(1)); + begin + check_type(typ, ieee_sfixed); + return decode(str(2 to str'right)); end; procedure push ( queue : queue_t; value : float ) is begin - push_type(queue, ieee_float); - push_variable_string(queue, encode(value)); + push_item(queue, encode(ieee_float) & encode(value)); end; impure function pop ( queue : queue_t - ) return float is begin - check_type(queue, ieee_float); - return decode(pop_variable_string(queue)); + ) return float is + constant str : string := pop_item(queue); + constant typ : queue_item_type_t := decode(str(1)); + begin + check_type(typ, ieee_float); + return decode(str(2 to str'right)); end; + end package body; + diff --git a/vunit/vhdl/data_types/src/queue_pkg-body.vhd b/vunit/vhdl/data_types/src/queue_pkg-body.vhd index d78907d75..508a6891b 100644 --- a/vunit/vhdl/data_types/src/queue_pkg-body.vhd +++ b/vunit/vhdl/data_types/src/queue_pkg-body.vhd @@ -4,62 +4,173 @@ -- -- Copyright (c) 2014-2019, Lars Asplund lars.anders.asplund@gmail.com -library ieee; -use ieee.math_real.all; -use ieee.math_complex.all; use work.codec_pkg.all; -use work.codec_builder_pkg.all; package body queue_pkg is + constant tail_idx : natural := 0; constant head_idx : natural := 1; - constant num_meta : natural := head_idx + 1; - constant queue_t_code_length : positive := integer_vector_ptr_t_code_length + string_ptr_t_code_length; + constant wrap_idx : natural := 2; + constant num_meta : natural := wrap_idx + 1; impure function new_queue - return queue_t is begin - return (p_meta => new_integer_vector_ptr(num_meta), - data => new_string_ptr); + return queue_t is + begin + return (p_meta => new_integer_vector_ptr(length => num_meta), + data => new_integer_vector_ptr(length => 256, value => -1)); end; impure function length ( queue : queue_t ) return natural is - constant head : integer := get(queue.p_meta, head_idx); - constant tail : integer := get(queue.p_meta, tail_idx); + variable head : natural; + variable tail : natural; + variable wrap : natural; begin - return tail - head; + assert queue /= null_queue report "Null queue has no length"; + head := get(queue.p_meta, head_idx); + tail := get(queue.p_meta, tail_idx); + wrap := get(queue.p_meta, wrap_idx); + if wrap = 0 then + return head - tail; + else + return length(queue.data) - (head - tail); + end if; end; impure function is_empty ( queue : queue_t ) return boolean is begin + assert queue /= null_queue report "Null queue has no length"; return length(queue) = 0; end; + impure function is_full ( + queue : queue_t + ) return boolean is begin + assert queue /= null_queue report "Null queue has no length"; + return length(queue) = length(queue.data); + end; + procedure flush ( queue : queue_t - ) is begin + ) is + variable ref : integer; + begin assert queue /= null_queue report "Flush null queue"; set(queue.p_meta, head_idx, 0); set(queue.p_meta, tail_idx, 0); + set(queue.p_meta, wrap_idx, 0); + for i in 0 to length(queue.data) - 1 loop + ref := get(queue.data, i); + if ref >= 0 then + deallocate(to_string_ptr(ref)); + set(queue.data, i, -1); + end if; + end loop; + end; + + procedure unsafe_push ( + queue : queue_t; + value : string_ptr_t + ) is + variable head : natural; + variable tail : natural; + variable wrap : natural; + variable size : positive; + begin + assert queue /= null_queue report "Push to null queue"; + head := get(queue.p_meta, head_idx); + tail := get(queue.p_meta, tail_idx); + wrap := get(queue.p_meta, wrap_idx); + size := length(queue.data); + if is_full(queue) then + resize(queue.data, 2 * size, rotate => tail); + tail := 0; + head := size; + wrap := 0; + size := 2 * size; + set(queue.p_meta, tail_idx, tail); + set(queue.p_meta, wrap_idx, wrap); + end if; + set(queue.data, head, to_integer(value)); + head := head + 1; + if head >= size then + head := head mod size; + if wrap = 0 then + wrap := 1; + else + wrap := 0; + end if; + set(queue.p_meta, wrap_idx, wrap); + end if; + set(queue.p_meta, head_idx, head); + end; + + impure function unsafe_pop ( + queue : queue_t + ) return string_ptr_t is + variable size : positive; + variable tail : natural; + variable wrap : natural; + variable data : string_ptr_t; + begin + assert queue /= null_queue report "Pop from null queue"; + assert length(queue) > 0 report "Pop from empty queue"; + size := length(queue.data); + tail := get(queue.p_meta, tail_idx); + wrap := get(queue.p_meta, wrap_idx); + data := to_string_ptr(get(queue.data, tail)); + set(queue.data, tail, -1); + tail := tail + 1; + if tail >= size then + tail := tail mod size; + if wrap = 0 then + wrap := 1; + else + wrap := 0; + end if; + set(queue.p_meta, wrap_idx, wrap); + end if; + set(queue.p_meta, tail_idx, tail); + return data; end; impure function copy ( queue : queue_t ) return queue_t is constant result : queue_t := new_queue; + variable tail : natural; + variable size : positive; + variable idx : natural; + variable ptr : string_ptr_t; begin + assert queue /= null_queue report "Copy null queue"; + tail := get(queue.p_meta, tail_idx); + size := length(queue.data); for i in 0 to length(queue) - 1 loop - unsafe_push(result, get(queue.data, 1 + i)); + idx := (tail + i) mod size; + ptr := to_string_ptr(get(queue.data, idx)); + unsafe_push(result, new_string_ptr(to_string(ptr))); end loop; return result; end; + procedure deallocate ( + queue : inout queue_t + ) is begin + if queue /= null_queue then + flush(queue); + deallocate(queue.p_meta); + deallocate(queue.data); + queue := null_queue; + end if; + end; + function encode ( data : queue_t ) return string is begin - return encode(data.p_meta) & encode(to_integer(data.data)); + return encode(data.p_meta) & encode(data.data); end; procedure decode ( @@ -81,524 +192,461 @@ package body queue_pkg is return ret_val; end; - procedure unsafe_push ( - queue : queue_t; - value : character - ) is - variable tail : integer; - variable head : integer; - begin - assert queue /= null_queue report "Push to null queue"; - tail := get(queue.p_meta, tail_idx); - head := get(queue.p_meta, head_idx); - if length(queue.data) < tail + 1 then - -- Allocate more new data, double data to avoid - -- to much copying. - -- Also normalize the queue by dropping unnused data before head - resize(queue.data, 2 * length(queue) + 1, drop => head); - tail := tail - head; - head := 0; - set(queue.p_meta, head_idx, head); - end if; - set(queue.data, 1 + tail, value); - set(queue.p_meta, tail_idx, tail + 1); - end; - - impure function unsafe_pop ( - queue : queue_t + function encode ( + item_type : queue_item_type_t ) return character is - variable head : integer; - variable data : character; begin - assert queue /= null_queue report "Pop from null queue"; - assert length(queue) > 0 report "Pop from empty queue"; - head := get(queue.p_meta, head_idx); - data := get(queue.data, 1 + head); - set(queue.p_meta, head_idx, head + 1); - return data; + return character'val(queue_item_type_t'pos(item_type)); end; - procedure push_type ( - queue : queue_t; - element_type : queue_element_type_t - ) is begin - unsafe_push(queue, character'val(queue_element_type_t'pos(element_type))); - end; - - impure function pop_type ( - queue : queue_t - ) return queue_element_type_t is begin - return queue_element_type_t'val(character'pos(unsafe_pop(queue))); + function decode ( + char : character + ) return queue_item_type_t is + begin + return queue_item_type_t'val(character'pos(char)); end; procedure check_type ( - queue : queue_t; - element_type : queue_element_type_t + got : queue_item_type_t; + expected : queue_item_type_t ) is - constant popped_type : queue_element_type_t := pop_type(queue); begin - if popped_type /= element_type then - report "Got queue element of type " & queue_element_type_t'image(popped_type) & - ", expected " & queue_element_type_t'image(element_type) & "." severity error; + if got /= expected then + report "Got queue item of type " & queue_item_type_t'image(got) & + ", expected " & queue_item_type_t'image(expected) & "." severity error; end if; end; - procedure push ( - queue : queue_t; - value : character - ) is begin - push_type(queue, vhdl_character); - unsafe_push(queue, value); - end; - - impure function pop ( - queue : queue_t - ) return character is begin - check_type(queue, vhdl_character); - return unsafe_pop(queue); - end; - - procedure push_fix_string ( + procedure push_item ( queue : queue_t; value : string - ) is begin - for i in value'range loop - unsafe_push(queue, value(i)); - end loop; + ) is + begin + unsafe_push(queue, new_string_ptr(value)); end; - impure function pop_fix_string ( - queue : queue_t; - length : natural + impure function pop_item ( + queue : queue_t ) return string is - variable result : string(1 to length); + constant ptr : string_ptr_t := unsafe_pop(queue); + constant str : string := to_string(ptr); begin - for i in result'range loop - result(i) := unsafe_pop(queue); - end loop; - - return result; + deallocate(ptr); + return str; end; - procedure unsafe_push ( + procedure push ( queue : queue_t; - value : integer + value : character ) is begin - push_fix_string(queue, encode(value)); + push_item(queue, encode(vhdl_character) & encode(value)); end; - impure function unsafe_pop ( + impure function pop ( queue : queue_t - ) return integer is begin - return decode(pop_fix_string(queue, integer_code_length)); + ) return character is + constant str : string := pop_item(queue); + constant typ : queue_item_type_t := decode(str(1)); + begin + check_type(typ, vhdl_character); + return decode(str(2 to str'right)); end; procedure push ( queue : queue_t; value : integer ) is begin - push_type(queue, vhdl_integer); - push_fix_string(queue, encode(value)); + push_item(queue, encode(vhdl_integer) & encode(value)); end; impure function pop ( queue : queue_t - ) return integer is begin - check_type(queue, vhdl_integer); - return decode(pop_fix_string(queue, integer_code_length)); + ) return integer is + constant str : string := pop_item(queue); + constant typ : queue_item_type_t := decode(str(1)); + begin + check_type(typ, vhdl_integer); + return decode(str(2 to str'right)); end; procedure push_byte ( queue : queue_t; value : natural range 0 to 255 ) is begin - push_type(queue, vunit_byte); - unsafe_push(queue, character'val(value)); + push_item(queue, encode(vunit_byte) & encode(character'val(value))); end; impure function pop_byte ( queue : queue_t - ) return integer is begin - check_type(queue, vunit_byte); - return character'pos(unsafe_pop(queue)); - end; - - procedure push_variable_string ( - queue : queue_t; - value : string - ) is begin - unsafe_push(queue, value'length); - push_fix_string(queue, value); - end; - - impure function pop_variable_string ( - queue : queue_t - ) return string is - constant length : integer := unsafe_pop(queue); + ) return integer is + constant str : string := pop_item(queue); + constant typ : queue_item_type_t := decode(str(1)); begin - return pop_fix_string(queue, length); + check_type(typ, vunit_byte); + return character'pos(decode(str(2 to str'right))); end; procedure push ( queue : queue_t; value : boolean ) is begin - push_type(queue, vhdl_boolean); - push_fix_string(queue, encode(value)); + push_item(queue, encode(vhdl_boolean) & encode(value)); end; impure function pop ( queue : queue_t - ) return boolean is begin - check_type(queue, vhdl_boolean); - return decode(pop_fix_string(queue, boolean_code_length)); - end; - - procedure unsafe_push ( - queue : queue_t; - value : boolean - ) is begin - push_fix_string(queue, encode(value)); - end; - - impure function unsafe_pop ( - queue : queue_t - ) return boolean is begin - return decode(pop_fix_string(queue, boolean_code_length)); + ) return boolean is + constant str : string := pop_item(queue); + constant typ : queue_item_type_t := decode(str(1)); + begin + check_type(typ, vhdl_boolean); + return decode(str(2 to str'right)); end; procedure push ( queue : queue_t; value : real ) is begin - push_type(queue, vhdl_real); - push_fix_string(queue, encode(value)); + push_item(queue, encode(vhdl_real) & encode(value)); end; impure function pop ( queue : queue_t - ) return real is begin - check_type(queue, vhdl_real); - return decode(pop_fix_string(queue, real_code_length)); + ) return real is + constant str : string := pop_item(queue); + constant typ : queue_item_type_t := decode(str(1)); + begin + check_type(typ, vhdl_real); + return decode(str(2 to str'right)); end; procedure push ( queue : queue_t; value : bit ) is begin - push_type(queue, vhdl_bit); - push_fix_string(queue, encode(value)); + push_item(queue, encode(vhdl_bit) & encode(value)); end; impure function pop ( queue : queue_t - ) return bit is begin - check_type(queue, vhdl_bit); - return decode(pop_fix_string(queue, bit_code_length)); + ) return bit is + constant str : string := pop_item(queue); + constant typ : queue_item_type_t := decode(str(1)); + begin + check_type(typ, vhdl_bit); + return decode(str(2 to str'right)); end; procedure push ( queue : queue_t; value : std_ulogic ) is begin - push_type(queue, ieee_std_ulogic); - push_fix_string(queue, encode(value)); + push_item(queue, encode(ieee_std_ulogic) & encode(value)); end; impure function pop ( queue : queue_t - ) return std_ulogic is begin - check_type(queue, ieee_std_ulogic); - return decode(pop_fix_string(queue, std_ulogic_code_length)); + ) return std_ulogic is + constant str : string := pop_item(queue); + constant typ : queue_item_type_t := decode(str(1)); + begin + check_type(typ, ieee_std_ulogic); + return decode(str(2 to str'right)); end; procedure push ( queue : queue_t; value : severity_level ) is begin - push_type(queue, vhdl_severity_level); - push_fix_string(queue, encode(value)); + push_item(queue, encode(vhdl_severity_level) & encode(value)); end; impure function pop ( queue : queue_t - ) return severity_level is begin - check_type(queue, vhdl_severity_level); - return decode(pop_fix_string(queue, severity_level_code_length)); + ) return severity_level is + constant str : string := pop_item(queue); + constant typ : queue_item_type_t := decode(str(1)); + begin + check_type(typ, vhdl_severity_level); + return decode(str(2 to str'right)); end; procedure push ( queue : queue_t; value : file_open_status ) is begin - push_type(queue, vhdl_file_open_status); - push_fix_string(queue, encode(value)); + push_item(queue, encode(vhdl_file_open_status) & encode(value)); end; impure function pop ( queue : queue_t - ) return file_open_status is begin - check_type(queue, vhdl_file_open_status); - return decode(pop_fix_string(queue, file_open_status_code_length)); + ) return file_open_status is + constant str : string := pop_item(queue); + constant typ : queue_item_type_t := decode(str(1)); + begin + check_type(typ, vhdl_file_open_status); + return decode(str(2 to str'right)); end; procedure push ( queue : queue_t; value : file_open_kind ) is begin - push_type(queue, vhdl_file_open_kind); - push_fix_string(queue, encode(value)); + push_item(queue, encode(vhdl_file_open_kind) & encode(value)); end; impure function pop ( queue : queue_t - ) return file_open_kind is begin - check_type(queue, vhdl_file_open_kind); - return decode(pop_fix_string(queue, file_open_kind_code_length)); + ) return file_open_kind is + constant str : string := pop_item(queue); + constant typ : queue_item_type_t := decode(str(1)); + begin + check_type(typ, vhdl_file_open_kind); + return decode(str(2 to str'right)); end; procedure push ( queue : queue_t; value : bit_vector ) is begin - push_type(queue, vhdl_bit_vector); - push_variable_string(queue, encode(value)); + push_item(queue, encode(vhdl_bit_vector) & encode(value)); end; impure function pop ( queue : queue_t - ) return bit_vector is begin - check_type(queue, vhdl_bit_vector); - return decode(pop_variable_string(queue)); + ) return bit_vector is + constant str : string := pop_item(queue); + constant typ : queue_item_type_t := decode(str(1)); + begin + check_type(typ, vhdl_bit_vector); + return decode(str(2 to str'right)); end; procedure push ( queue : queue_t; value : std_ulogic_vector ) is begin - push_type(queue, vhdl_std_ulogic_vector); - push_variable_string(queue, encode(value)); + push_item(queue, encode(ieee_std_ulogic_vector) & encode(value)); end; impure function pop ( queue : queue_t - ) return std_ulogic_vector is begin - check_type(queue, vhdl_std_ulogic_vector); - return decode(pop_variable_string(queue)); + ) return std_ulogic_vector is + constant str : string := pop_item(queue); + constant typ : queue_item_type_t := decode(str(1)); + begin + check_type(typ, ieee_std_ulogic_vector); + report str; + return decode(str(2 to str'right)); end; procedure push ( queue : queue_t; value : complex ) is begin - push_type(queue, ieee_complex); - push_fix_string(queue, encode(value)); + push_item(queue, encode(ieee_complex) & encode(value)); end; impure function pop ( queue : queue_t - ) return complex is begin - check_type(queue, ieee_complex); - return decode(pop_fix_string(queue, complex_code_length)); + ) return complex is + constant str : string := pop_item(queue); + constant typ : queue_item_type_t := decode(str(1)); + begin + check_type(typ, ieee_complex); + return decode(str(2 to str'right)); end; procedure push ( queue : queue_t; value : complex_polar ) is begin - push_type(queue, ieee_complex_polar); - push_fix_string(queue, encode(value)); + push_item(queue, encode(ieee_complex_polar) & encode(value)); end; impure function pop ( queue : queue_t - ) return complex_polar is begin - check_type(queue, ieee_complex_polar); - return decode(pop_fix_string(queue, complex_polar_code_length)); + ) return complex_polar is + constant str : string := pop_item(queue); + constant typ : queue_item_type_t := decode(str(1)); + begin + check_type(typ, ieee_complex_polar); + return decode(str(2 to str'right)); end; procedure push ( queue : queue_t; value : ieee.numeric_bit.unsigned ) is begin - push_type(queue, ieee_numeric_bit_unsigned); - push_variable_string(queue, encode(value)); + push_item(queue, encode(ieee_numeric_bit_unsigned) & encode(value)); end; impure function pop ( queue : queue_t - ) return ieee.numeric_bit.unsigned is begin - check_type(queue, ieee_numeric_bit_unsigned); - return decode(pop_variable_string(queue)); + ) return ieee.numeric_bit.unsigned is + constant str : string := pop_item(queue); + constant typ : queue_item_type_t := decode(str(1)); + begin + check_type(typ, ieee_numeric_bit_unsigned); + return decode(str(2 to str'right)); end; procedure push ( queue : queue_t; value : ieee.numeric_bit.signed ) is begin - push_type(queue, ieee_numeric_bit_signed); - push_variable_string(queue, encode(value)); + push_item(queue, encode(ieee_numeric_bit_signed) & encode(value)); end; impure function pop ( queue : queue_t - ) return ieee.numeric_bit.signed is begin - check_type(queue, ieee_numeric_bit_signed); - return decode(pop_variable_string(queue)); + ) return ieee.numeric_bit.signed is + constant str : string := pop_item(queue); + constant typ : queue_item_type_t := decode(str(1)); + begin + check_type(typ, ieee_numeric_bit_signed); + return decode(str(2 to str'right)); end; procedure push ( queue : queue_t; value : ieee.numeric_std.unsigned ) is begin - push_type(queue, ieee_numeric_std_unsigned); - push_variable_string(queue, encode(value)); + push_item(queue, encode(ieee_numeric_std_unsigned) & encode(value)); end; impure function pop ( queue : queue_t - ) return ieee.numeric_std.unsigned is begin - check_type(queue, ieee_numeric_std_unsigned); - return decode(pop_variable_string(queue)); + ) return ieee.numeric_std.unsigned is + constant str : string := pop_item(queue); + constant typ : queue_item_type_t := decode(str(1)); + begin + check_type(typ, ieee_numeric_std_unsigned); + return decode(str(2 to str'right)); end; procedure push ( queue : queue_t; value : ieee.numeric_std.signed ) is begin - push_type(queue, ieee_numeric_std_signed); - push_variable_string(queue, encode(value)); + push_item(queue, encode(ieee_numeric_std_signed) & encode(value)); end; impure function pop ( queue : queue_t - ) return ieee.numeric_std.signed is begin - check_type(queue, ieee_numeric_std_signed); - return decode(pop_variable_string(queue)); + ) return ieee.numeric_std.signed is + constant str : string := pop_item(queue); + constant typ : queue_item_type_t := decode(str(1)); + begin + check_type(typ, ieee_numeric_std_signed); + return decode(str(2 to str'right)); end; procedure push ( queue : queue_t; value : string ) is begin - push_type(queue, vhdl_string); - push_variable_string(queue, encode(value)); + push_item(queue, encode(vhdl_string) & encode(value)); end; impure function pop ( queue : queue_t - ) return string is begin - check_type(queue, vhdl_string); - return decode(pop_variable_string(queue)); + ) return string is + constant str : string := pop_item(queue); + constant typ : queue_item_type_t := decode(str(1)); + begin + check_type(typ, vhdl_string); + return decode(str(2 to str'right)); end; procedure push ( queue : queue_t; value : time ) is begin - push_type(queue, vhdl_time); - push_fix_string(queue, encode(value)); + push_item(queue, encode(vhdl_time) & encode(value)); end; impure function pop ( queue : queue_t - ) return time is begin - check_type(queue, vhdl_time); - return decode(pop_fix_string(queue, time_code_length)); + ) return time is + constant str : string := pop_item(queue); + constant typ : queue_item_type_t := decode(str(1)); + begin + check_type(typ, vhdl_time); + return decode(str(2 to str'right)); end; procedure push ( queue : queue_t; variable value : inout integer_vector_ptr_t ) is begin - push_type(queue, vunit_integer_vector_ptr_t); - push_fix_string(queue, encode(value)); - value := null_ptr; + push_item(queue, encode(vunit_integer_vector_ptr) & encode(value)); + value := null_integer_vector_ptr; end; impure function pop ( queue : queue_t - ) return integer_vector_ptr_t is begin - check_type(queue, vunit_integer_vector_ptr_t); - return decode(pop_fix_string(queue, integer_vector_ptr_t_code_length)); - end; - - procedure unsafe_push ( - queue : queue_t; - value : integer_vector_ptr_t - ) is begin - push_fix_string(queue, encode(value)); - end; - - impure function unsafe_pop ( - queue : queue_t - ) return integer_vector_ptr_t is begin - return decode(pop_fix_string(queue, integer_vector_ptr_t_code_length)); + ) return integer_vector_ptr_t is + constant str : string := pop_item(queue); + constant typ : queue_item_type_t := decode(str(1)); + begin + check_type(typ, vunit_integer_vector_ptr); + return decode(str(2 to str'right)); end; procedure push ( queue : queue_t; variable value : inout string_ptr_t ) is begin - push_type(queue, vunit_string_ptr_t); - push_fix_string(queue, encode(value)); + push_item(queue, encode(vunit_string_ptr) & encode(value)); value := null_string_ptr; end; impure function pop ( queue : queue_t - ) return string_ptr_t is begin - check_type(queue, vunit_string_ptr_t); - return decode(pop_fix_string(queue, string_ptr_t_code_length)); + ) return string_ptr_t is + constant str : string := pop_item(queue); + constant typ : queue_item_type_t := decode(str(1)); + begin + check_type(typ, vunit_string_ptr); + return decode(str(2 to str'right)); end; procedure push ( queue : queue_t; variable value : inout queue_t ) is begin - push_type(queue, vunit_queue_t); - push_fix_string(queue, encode(value)); + push_item(queue, encode(vunit_queue) & encode(value)); value := null_queue; end; impure function pop ( queue : queue_t - ) return queue_t is begin - check_type(queue, vunit_queue_t); - return decode(pop_fix_string(queue, queue_t_code_length)); + ) return queue_t is + constant str : string := pop_item(queue); + constant typ : queue_item_type_t := decode(str(1)); + begin + check_type(typ, vunit_queue); + return decode(str(2 to str'right)); end; - procedure push_ref ( + procedure push ( constant queue : queue_t; value : inout integer_array_t ) is begin - push_type(queue, vunit_integer_array_t); - unsafe_push(queue, value.length); - unsafe_push(queue, value.width); - unsafe_push(queue, value.height); - unsafe_push(queue, value.depth); - unsafe_push(queue, value.bit_width); - unsafe_push(queue, value.is_signed); - unsafe_push(queue, value.lower_limit); - unsafe_push(queue, value.upper_limit); - unsafe_push(queue, value.data); + push_item(queue, encode(vunit_integer_array) & encode(value)); value := null_integer_array; end; - impure function pop_ref ( + impure function pop ( queue : queue_t - ) return integer_array_t is begin - check_type(queue, vunit_integer_array_t); - return ( - length => unsafe_pop(queue), - width => unsafe_pop(queue), - height => unsafe_pop(queue), - depth => unsafe_pop(queue), - bit_width => unsafe_pop(queue), - is_signed => unsafe_pop(queue), - lower_limit => unsafe_pop(queue), - upper_limit => unsafe_pop(queue), - data => unsafe_pop(queue) - ); + ) return integer_array_t is + constant str : string := pop_item(queue); + constant typ : queue_item_type_t := decode(str(1)); + begin + check_type(typ, vunit_integer_array); + return decode(str(2 to str'right)); end; + end package body; + diff --git a/vunit/vhdl/data_types/src/queue_pkg.vhd b/vunit/vhdl/data_types/src/queue_pkg.vhd index 132d8ea23..0e4465a8e 100644 --- a/vunit/vhdl/data_types/src/queue_pkg.vhd +++ b/vunit/vhdl/data_types/src/queue_pkg.vhd @@ -14,17 +14,53 @@ use work.string_ptr_pkg.all; use work.integer_array_pkg.all; package queue_pkg is + + type queue_item_type_t is ( + vhdl_boolean, + vhdl_boolean_vector, + vhdl_bit, + vhdl_bit_vector, + vhdl_character, + vhdl_string, + vhdl_integer, + vhdl_integer_vector, + vhdl_real, + vhdl_real_vector, + vhdl_time, + vhdl_time_vector, + vhdl_severity_level, + vhdl_file_open_status, + vhdl_file_open_kind, + ieee_complex, + ieee_complex_polar, + ieee_std_ulogic, + ieee_std_ulogic_vector, + ieee_numeric_bit_unsigned, + ieee_numeric_bit_signed, + ieee_numeric_std_unsigned, + ieee_numeric_std_signed, + ieee_ufixed, + ieee_sfixed, + ieee_float, + vunit_byte, + vunit_integer_vector_ptr, + vunit_string_ptr, + vunit_integer_array, + vunit_queue + ); + type queue_t is record p_meta : integer_vector_ptr_t; - data : string_ptr_t; + data : integer_vector_ptr_t; end record; + type queue_vec_t is array(integer range <>) of queue_t; - constant null_queue : queue_t := (p_meta => null_ptr, data => null_string_ptr); + + constant null_queue : queue_t := (p_meta => null_ptr, data => null_ptr); impure function new_queue - return queue_t; + return queue_t; - -- Returns the length of the queue in bytes impure function length ( queue : queue_t ) return natural; @@ -41,6 +77,32 @@ package queue_pkg is queue : queue_t ) return queue_t; + procedure deallocate ( + queue : inout queue_t + ); + + function encode ( + item_type : queue_item_type_t + ) return character; + + function decode ( + char : character + ) return queue_item_type_t; + + procedure push_item ( + queue : queue_t; + value : string + ); + + impure function pop_item ( + queue : queue_t + ) return string; + + procedure check_type ( + got : queue_item_type_t; + expected : queue_item_type_t + ); + procedure push ( queue : queue_t; value : integer @@ -314,27 +376,17 @@ package queue_pkg is alias push_queue_ref is push[queue_t, queue_t]; alias pop_queue_ref is pop[queue_t return queue_t]; - procedure push_ref ( + procedure push ( constant queue : queue_t; value : inout integer_array_t ); - impure function pop_ref ( + impure function pop ( queue : queue_t ) return integer_array_t; - alias push_integer_array_t_ref is push_ref[queue_t, integer_array_t]; - alias pop_integer_array_t_ref is pop_ref[queue_t return integer_array_t]; - - -- Private - type queue_element_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, vhdl_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 - ); + alias push_integer_array_t_ref is push[queue_t, integer_array_t]; + alias pop_integer_array_t_ref is pop[queue_t return integer_array_t]; function encode ( data : queue_t @@ -353,41 +405,5 @@ package queue_pkg is alias encode_queue_t is encode[queue_t return string]; alias decode_queue_t is decode[string return queue_t]; - procedure push_type ( - queue : queue_t; - element_type : queue_element_type_t - ); - - procedure check_type ( - queue : queue_t; - element_type : queue_element_type_t - ); - - procedure unsafe_push ( - queue : queue_t; - value : character - ); - - impure function unsafe_pop ( - queue : queue_t - ) return character; - - procedure push_variable_string ( - queue : queue_t; - value : string - ); - - impure function pop_variable_string ( - queue : queue_t - ) return string; - - procedure push_fix_string ( - queue : queue_t; - value : string - ); - - impure function pop_fix_string ( - queue : queue_t; - length : natural - ) return string; end package; + diff --git a/vunit/vhdl/data_types/src/queue_pool_pkg.vhd b/vunit/vhdl/data_types/src/queue_pool_pkg.vhd index abc5f24da..68d322145 100644 --- a/vunit/vhdl/data_types/src/queue_pool_pkg.vhd +++ b/vunit/vhdl/data_types/src/queue_pool_pkg.vhd @@ -7,15 +7,18 @@ use work.integer_vector_ptr_pool_pkg.all; use work.string_ptr_pool_pkg.all; use work.queue_pkg.all; +use work.integer_vector_ptr_pkg.all; package queue_pool_pkg is + type queue_pool_t is record index_pool : integer_vector_ptr_pool_t; - data_pool : string_ptr_pool_t; + data_pool : integer_vector_ptr_pool_t; end record; + constant null_queue_pool : queue_pool_t := ( index_pool => null_integer_vector_ptr_pool, - data_pool => null_string_ptr_pool); + data_pool => null_integer_vector_ptr_pool); impure function new_queue_pool return queue_pool_t; @@ -28,14 +31,16 @@ package queue_pool_pkg is pool : queue_pool_t; variable queue : inout queue_t ); + end package; package body queue_pool_pkg is + impure function new_queue_pool return queue_pool_t is begin return ( index_pool => new_integer_vector_ptr_pool, - data_pool => new_string_ptr_pool + data_pool => new_integer_vector_ptr_pool ); end; @@ -45,10 +50,12 @@ package body queue_pool_pkg is variable queue : queue_t; begin queue := ( - p_meta => new_integer_vector_ptr(pool.index_pool, 2), - data => new_string_ptr(pool.data_pool, 0) + p_meta => new_integer_vector_ptr(pool.index_pool, 3), + data => new_integer_vector_ptr(pool.data_pool, 256) ); - flush(queue); + for i in 0 to length(queue.data) - 1 loop + set(queue.data, i, -1); + end loop; return queue; end; @@ -56,7 +63,10 @@ package body queue_pool_pkg is pool : queue_pool_t; variable queue : inout queue_t ) is begin + flush(queue); recycle(pool.index_pool, queue.p_meta); recycle(pool.data_pool, queue.data); end; + end package body; + diff --git a/vunit/vhdl/data_types/src/string_ptr_pkg-body-200x.vhd b/vunit/vhdl/data_types/src/string_ptr_pkg-body-200x.vhd index 83406a721..5f7e6490f 100644 --- a/vunit/vhdl/data_types/src/string_ptr_pkg-body-200x.vhd +++ b/vunit/vhdl/data_types/src/string_ptr_pkg-body-200x.vhd @@ -4,242 +4,319 @@ -- -- Copyright (c) 2014-2019, Lars Asplund lars.anders.asplund@gmail.com +use work.integer_vector_pkg.all; + package body string_ptr_pkg is + type string_ptr_storage_t is protected - impure function new_string_ptr ( + + impure function new_ptr ( length : natural := 0 ) return natural; + impure function new_ptr ( + value : vec_t + ) return natural; + + procedure check_valid ( + ref : index_t + ); + procedure deallocate ( - ref : natural + ref : index_t + ); + + procedure reallocate_storage ( + length : positive + ); + + procedure reallocate_stack ( + length : positive ); impure function length ( - ref : natural - ) return integer; + ref : index_t + ) return natural; procedure set ( - ref : natural; - index : natural; + ref : index_t; + index : positive; value : val_t ); impure function get ( - ref : natural; - index : natural + ref : index_t; + index : positive ) return val_t; procedure reallocate ( - ref : natural; + ref : index_t; length : natural ); procedure reallocate ( - ref : natural; - value : string + ref : index_t; + value : vec_t ); procedure resize ( - ref : natural; + ref : index_t; length : natural; - drop : natural := 0 + drop : natural := 0; + rotate : natural := 0 ); impure function to_string ( - ref : natural + ref : index_t ) return string; + end protected; type string_ptr_storage_t is protected body - variable current_index : integer := 0; - variable ptrs : vava_t := null; - impure function new_string_ptr ( + -- Pointer storage + variable storage : vava_t := new vav_t'(0 to 2**16 - 1 => null); + variable storage_index : natural := 0; + + -- Stack of unused storage indices + variable stack : integer_vector_access_t := new integer_vector_t'(0 to 2**16 - 1 => -1); + variable stack_index : natural := 0; + + impure function new_ptr ( length : natural := 0 ) return natural is - variable old_ptrs : string_access_vector_access_t; + constant value : vec_t(1 to length) := (others => val_t'low); begin - if ptrs = null then - ptrs := new vav_t'(0 => null); - elsif ptrs'length <= current_index then - -- Reallocate ptr pointers to larger ptr - -- Use more size to trade size for speed - old_ptrs := ptrs; - ptrs := new vav_t'(0 to ptrs'length + 2**16 => null); - for i in old_ptrs'range loop - ptrs(i) := old_ptrs(i); - end loop; - deallocate(old_ptrs); + return new_ptr(value); + end; + + impure function new_ptr ( + value : vec_t + ) return natural is + variable ref : index_t; + begin + if stack_index > 0 then + stack_index := stack_index - 1; + ref := stack(stack_index); + else + if storage_index >= storage'length then + reallocate_storage(storage'length + 2**16); + end if; + ref := storage_index; + storage_index := storage_index + 1; end if; - ptrs(current_index) := new string'(1 to length => val_t'low); - current_index := current_index + 1; - return current_index-1; + storage(ref) := new vec_t'(value); + return ref; + end; + + procedure check_valid ( + ref : index_t + ) is begin + assert 0 <= ref and ref < storage_index report "invalid pointer"; + assert storage(ref) /= null report "unallocated pointer"; end; procedure deallocate ( - ref : natural + ref : index_t ) is begin - deallocate(ptrs(ref)); - ptrs(ref) := null; + if ref >= 0 then + check_valid(ref); + if stack_index >= stack'length then + reallocate_stack(stack'length + 2**16); + end if; + stack(stack_index) := ref; + stack_index := stack_index + 1; + deallocate(storage(ref)); + storage(ref) := null; + end if; + end; + + procedure reallocate_storage ( + length : positive + ) is + variable old_storage : vava_t; + begin + old_storage := storage; + storage := new vav_t'(0 to length - 1 => null); + for i in old_storage'range loop + storage(i) := old_storage(i); + end loop; + deallocate(old_storage); + end; + + procedure reallocate_stack ( + length : positive + ) is + variable old_stack : integer_vector_access_t; + begin + old_stack := stack; + stack := new integer_vector_t'(0 to length - 1 => -1); + for i in old_stack'range loop + stack(i) := old_stack(i); + end loop; + deallocate(old_stack); end; impure function length ( - ref : natural - ) return integer is begin - return ptrs(ref)'length; + ref : index_t + ) return natural is begin + check_valid(ref); + return storage(ref)'length; end; procedure set ( - ref : natural; - index : natural; + ref : index_t; + index : positive; value : val_t ) is begin - ptrs(ref)(index) := value; + check_valid(ref); + storage(ref)(index) := value; end; impure function get ( - ref : natural; - index : natural + ref : index_t; + index : positive ) return val_t is begin - return ptrs(ref)(index); + check_valid(ref); + return storage(ref)(index); end; procedure reallocate ( - ref : natural; + ref : index_t; length : natural ) is - variable old_ptr, new_ptr : string_access_t; + variable value : vec_t(1 to length) := (others => val_t'low); begin - deallocate(ptrs(ref)); - ptrs(ref) := new string'(1 to length => val_t'low); + reallocate(ref, value); end; procedure reallocate ( - ref : natural; - value : string - ) is - variable old_ptr, new_ptr : string_access_t; - variable n_value : string(1 to value'length) := value; - begin - deallocate(ptrs(ref)); - ptrs(ref) := new string'(n_value); + ref : index_t; + value : vec_t + ) is begin + check_valid(ref); + deallocate(storage(ref)); + storage(ref) := new vec_t'(value); end; procedure resize ( - ref : natural; + ref : index_t; length : natural; - drop : natural := 0 + drop : natural := 0; + rotate : natural := 0 ) is - variable old_ptr, new_ptr : string_access_t; - variable min_length : natural := length; + variable old_ptr : va_t; + variable new_ptr : va_t := new vec_t'(1 to length => val_t'low); + variable min_length : natural; + variable index : natural; begin - new_ptr := new string'(1 to length => val_t'low); - old_ptr := ptrs(ref); - if min_length > old_ptr'length - drop then - min_length := old_ptr'length - drop; + check_valid(ref); + assert drop = 0 or rotate = 0 report "can't combine drop and rotate"; + old_ptr := storage(ref); + min_length := old_ptr'length - drop; + if length < min_length then + min_length := length; end if; - for i in 1 to min_length loop - new_ptr(i) := old_ptr(drop + i); + for i in 0 to min_length - 1 loop + index := (drop + rotate + i) mod old_ptr'length; + new_ptr(i + 1) := old_ptr(index + 1); end loop; - ptrs(ref) := new_ptr; + storage(ref) := new_ptr; deallocate(old_ptr); end; impure function to_string ( - ref : natural + ref : index_t ) return string is begin - return ptrs(ref).all; + check_valid(ref); + return storage(ref).all; end; end protected body; - shared variable string_ptr_storage : string_ptr_storage_t; + shared variable ptr_storage : string_ptr_storage_t; function to_integer ( value : ptr_t - ) return integer is begin + ) return index_t is begin return value.ref; end; impure function to_string_ptr ( - value : integer + value : index_t ) return ptr_t is begin - -- @TODO maybe assert that the ref is valid + if value >= 0 then + ptr_storage.check_valid(value); + end if; return (ref => value); end; impure function new_string_ptr ( length : natural := 0 ) return ptr_t is begin - return (ref => string_ptr_storage.new_string_ptr(length)); + return (ref => ptr_storage.new_ptr(length)); end; impure function new_string_ptr ( - value : string - ) return ptr_t is - variable result : ptr_t := new_string_ptr(value'length); - variable n_value : string(1 to value'length) := value; - begin - for i in 1 to n_value'length loop - set(result, i, n_value(i)); - end loop; - return result; + value : vec_t + ) return ptr_t is begin + return (ref => ptr_storage.new_ptr(value)); end; procedure deallocate ( ptr : ptr_t - ) is - begin - string_ptr_storage.deallocate(ptr.ref); + ) is begin + ptr_storage.deallocate(ptr.ref); end; impure function length ( ptr : ptr_t - ) return integer is begin - return string_ptr_storage.length(ptr.ref); + ) return natural is begin + return ptr_storage.length(ptr.ref); end; procedure set ( ptr : ptr_t; - index : natural; + index : positive; value : val_t ) is begin - string_ptr_storage.set(ptr.ref, index, value); + ptr_storage.set(ptr.ref, index, value); end; impure function get ( - ptr : ptr_t; - index : natural + ptr : ptr_t; + index : positive ) return val_t is begin - return string_ptr_storage.get(ptr.ref, index); + return ptr_storage.get(ptr.ref, index); end; procedure reallocate ( - ptr : ptr_t; + ptr : ptr_t; length : natural ) is begin - string_ptr_storage.reallocate(ptr.ref, length); + ptr_storage.reallocate(ptr.ref, length); end; procedure reallocate ( ptr : ptr_t; - value : string + value : vec_t ) is begin - string_ptr_storage.reallocate(ptr.ref, value); + ptr_storage.reallocate(ptr.ref, value); end; procedure resize ( ptr : ptr_t; length : natural; - drop : natural := 0 + drop : natural := 0; + rotate : natural := 0 ) is begin - string_ptr_storage.resize(ptr.ref, length, drop); + ptr_storage.resize(ptr.ref, length, drop, rotate); end; impure function to_string ( ptr : ptr_t ) return string is begin - return string_ptr_storage.to_string(ptr.ref); + return ptr_storage.to_string(ptr.ref); end; function encode ( @@ -252,18 +329,19 @@ package body string_ptr_pkg is code : string ) return ptr_t is variable ret_val : ptr_t; - variable index : positive := code'left; + variable index : positive := code'left; begin decode(code, index, ret_val); return ret_val; end; procedure decode ( - constant code : string; - variable index : inout positive; + constant code : string; + variable index : inout positive; variable result : out ptr_t ) is begin decode(code, index, result.ref); end; end package body; + diff --git a/vunit/vhdl/data_types/src/string_ptr_pkg-body-93.vhd b/vunit/vhdl/data_types/src/string_ptr_pkg-body-93.vhd index 7f0684109..5cc077b83 100644 --- a/vunit/vhdl/data_types/src/string_ptr_pkg-body-93.vhd +++ b/vunit/vhdl/data_types/src/string_ptr_pkg-body-93.vhd @@ -4,133 +4,183 @@ -- -- Copyright (c) 2014-2019, Lars Asplund lars.anders.asplund@gmail.com +use work.integer_vector_pkg.all; + package body string_ptr_pkg is - shared variable current_index : integer := 0; - shared variable ptrs : vava_t := null; + + -- Pointer storage + shared variable storage : vava_t := new vav_t'(0 to 2**16 - 1 => null); + shared variable storage_index : natural := 0; + + -- Stack of unused storage indices + shared variable stack : integer_vector_access_t := new integer_vector_t'(0 to 2**16 - 1 => -1); + shared variable stack_index : natural := 0; + + procedure reallocate_storage ( + length : positive + ) is + variable old_storage : vava_t; + begin + old_storage := storage; + storage := new vav_t'(0 to length - 1 => null); + for i in old_storage'range loop + storage(i) := old_storage(i); + end loop; + deallocate(old_storage); + end; + + procedure reallocate_stack ( + length : positive + ) is + variable old_stack : integer_vector_access_t; + begin + old_stack := stack; + stack := new integer_vector_t'(0 to length - 1 => -1); + for i in old_stack'range loop + stack(i) := old_stack(i); + end loop; + deallocate(old_stack); + end; impure function new_string_ptr ( length : natural := 0 ) return ptr_t is - variable old_ptrs : vava_t; - variable retval : ptr_t := (ref => current_index); + constant value : vec_t(1 to length) := (others => val_t'low); begin - if ptrs = null then - ptrs := new vav_t'(0 => null); - elsif ptrs'length <= current_index then - -- Reallocate ptr pointers to larger ptr - -- Use more size to trade size for speed - old_ptrs := ptrs; - ptrs := new vav_t'(0 to ptrs'length + 2**16 => null); - for i in old_ptrs'range loop - ptrs(i) := old_ptrs(i); - end loop; - deallocate(old_ptrs); + return new_string_ptr(value); + end; + + impure function new_string_ptr ( + value : vec_t + ) return ptr_t is + variable ref : index_t; + begin + if stack_index > 0 then + stack_index := stack_index - 1; + ref := stack(stack_index); + else + if storage_index >= storage'length then + reallocate_storage(storage'length + 2**16); + end if; + ref := storage_index; + storage_index := storage_index + 1; end if; - ptrs(current_index) := new string'(1 to length => val_t'low); - current_index := current_index + 1; - return retval; + storage(ref) := new vec_t'(value); + return (ref => ref); + end; + + procedure check_valid ( + ref : index_t + ) is begin + assert 0 <= ref and ref < storage_index report "invalid pointer"; + assert storage(ref) /= null report "unallocated pointer"; end; procedure deallocate ( ptr : ptr_t ) is begin - deallocate(ptrs(ptr.ref)); - ptrs(ptr.ref) := null; + if ptr.ref > 0 then + check_valid(ptr.ref); + if stack_index >= stack'length then + reallocate_stack(stack'length + 2**16); + end if; + stack(stack_index) := ptr.ref; + stack_index := stack_index + 1; + deallocate(storage(ptr.ref)); + storage(ptr.ref) := null; + end if; end; impure function length ( ptr : ptr_t - ) return integer is begin - return ptrs(ptr.ref)'length; + ) return natural is begin + check_valid(ptr.ref); + return storage(ptr.ref)'length; end; procedure set ( ptr : ptr_t; - index : natural; + index : positive; value : val_t ) is begin - ptrs(ptr.ref)(index) := value; + check_valid(ptr.ref); + storage(ptr.ref)(index) := value; end; impure function get ( ptr : ptr_t; - index : natural + index : positive ) return val_t is begin - return ptrs(ptr.ref)(index); + check_valid(ptr.ref); + return storage(ptr.ref)(index); end; procedure reallocate ( ptr : ptr_t; length : natural ) is - variable old_ptr, new_ptr : string_access_t; + variable value : vec_t(1 to length) := (others => val_t'low); begin - deallocate(ptrs(ptr.ref)); - ptrs(ptr.ref) := new string'(1 to length => val_t'low); + reallocate(ptr, value); end; procedure reallocate ( ptr : ptr_t; - value : string - ) is - variable old_ptr, new_ptr : string_access_t; - variable n_value : string(1 to value'length) := value; - begin - deallocate(ptrs(ptr.ref)); - ptrs(ptr.ref) := new string'(n_value); + value : vec_t + ) is begin + check_valid(ptr.ref); + deallocate(storage(ptr.ref)); + storage(ptr.ref) := new vec_t'(value); end; procedure resize ( ptr : ptr_t; length : natural; - drop : natural := 0 + drop : natural := 0; + rotate : natural := 0 ) is - variable old_ptr, new_ptr : string_access_t; - variable min_length : natural := length; + variable old_ptr : va_t; + variable new_ptr : va_t := new vec_t'(1 to length => val_t'low); + variable min_length : natural; + variable index : natural; begin - new_ptr := new string'(1 to length => val_t'low); - old_ptr := ptrs(ptr.ref); - if min_length > old_ptr'length - drop then - min_length := old_ptr'length - drop; + check_valid(ptr.ref); + assert drop = 0 or rotate = 0 report "can't combine drop and rotate"; + old_ptr := storage(ptr.ref); + min_length := old_ptr'length - drop; + if length < min_length then + min_length := length; end if; - for i in 1 to min_length loop - new_ptr(i) := old_ptr(drop + i); + for i in 0 to min_length - 1 loop + index := (drop + rotate + i) mod old_ptr'length; + new_ptr(i + 1) := old_ptr(index + 1); end loop; - ptrs(ptr.ref) := new_ptr; + storage(ptr.ref) := new_ptr; deallocate(old_ptr); end; impure function to_string ( ptr : ptr_t ) return string is begin - return ptrs(ptr.ref).all; + check_valid(ptr.ref); + return storage(ptr.ref).all; end; function to_integer ( value : ptr_t - ) return integer is begin + ) return index_t is begin return value.ref; end; impure function to_string_ptr ( - value : integer + value : index_t ) return ptr_t is begin - -- @TODO maybe assert that the ref is valid + if value >= 0 then + check_valid(value); + end if; return (ref => value); end; - impure function new_string_ptr ( - value : string - ) return ptr_t is - variable result : ptr_t := new_string_ptr(value'length); - variable n_value : string(1 to value'length) := value; - begin - for i in 1 to n_value'length loop - set(result, i, n_value(i)); - end loop; - return result; - end; - function encode ( data : ptr_t ) return string is begin @@ -156,3 +206,4 @@ package body string_ptr_pkg is end; end package body; + diff --git a/vunit/vhdl/data_types/src/string_ptr_pkg.vhd b/vunit/vhdl/data_types/src/string_ptr_pkg.vhd index 19d2381a6..054c02be9 100644 --- a/vunit/vhdl/data_types/src/string_ptr_pkg.vhd +++ b/vunit/vhdl/data_types/src/string_ptr_pkg.vhd @@ -16,23 +16,28 @@ use work.codec_pkg.all; use work.codec_builder_pkg.all; package string_ptr_pkg is + subtype index_t is integer range -1 to integer'high; + type string_ptr_t is record ref : index_t; end record; + constant null_string_ptr : string_ptr_t := (ref => -1); - alias ptr_t is string_ptr_t; - alias val_t is character; - alias vav_t is string_access_vector_t; - alias vava_t is string_access_vector_access_t; + alias ptr_t is string_ptr_t; + alias val_t is character; + alias vec_t is string; + alias va_t is string_access_t; + alias vav_t is string_access_vector_t; + alias vava_t is string_access_vector_access_t; function to_integer ( value : ptr_t - ) return integer; + ) return index_t; impure function to_string_ptr ( - value : integer + value : index_t ) return ptr_t; impure function new_string_ptr ( @@ -40,7 +45,7 @@ package string_ptr_pkg is ) return ptr_t; impure function new_string_ptr ( - value : string + value : vec_t ) return ptr_t; procedure deallocate ( @@ -49,17 +54,17 @@ package string_ptr_pkg is impure function length ( ptr : ptr_t - ) return integer; + ) return natural; procedure set ( ptr : ptr_t; - index : natural; + index : positive; value : val_t ); impure function get ( ptr : ptr_t; - index : natural + index : positive ) return val_t; procedure reallocate ( @@ -69,13 +74,14 @@ package string_ptr_pkg is procedure reallocate ( ptr : ptr_t; - value : string + value : vec_t ); procedure resize ( ptr : ptr_t; length : natural; - drop : natural := 0 + drop : natural := 0; + rotate : natural := 0 ); impure function to_string ( @@ -96,9 +102,10 @@ package string_ptr_pkg is variable result : out ptr_t ); - alias encode_ptr_t is encode[ptr_t return string]; - alias decode_ptr_t is decode[string return ptr_t]; + alias encode_string_ptr_t is encode[ptr_t return string]; + alias decode_string_ptr_t is decode[string return ptr_t]; constant string_ptr_t_code_length : positive := integer_code_length; end package; + diff --git a/vunit/vhdl/data_types/test/tb_integer_vector_ptr.vhd b/vunit/vhdl/data_types/test/tb_integer_vector_ptr.vhd index c60c83b3e..acfb7faf2 100644 --- a/vunit/vhdl/data_types/test/tb_integer_vector_ptr.vhd +++ b/vunit/vhdl/data_types/test/tb_integer_vector_ptr.vhd @@ -88,6 +88,30 @@ begin check_equal(get(ptr, i), 4+i); end loop; + elsif run("test_resize_with_rotate") then + ptr := new_integer_vector_ptr(8); + for i in 0 to 7 loop + set(ptr, i, i); + end loop; + resize(ptr, 16, rotate => 6, value => -1); + + for i in 0 to 7 loop + check_equal(get(ptr, i), (6+i) mod 8); + end loop; + for i in 8 to 15 loop + check_equal(get(ptr, i), -1); + end loop; + + ptr := new_integer_vector_ptr(8); + for i in 0 to 7 loop + set(ptr, i, i); + end loop; + resize(ptr, 4, rotate => 6); + + for i in 0 to 3 loop + check_equal(get(ptr, i), (6+i) mod 8); + end loop; + elsif run("test_resize_with_default") then ptr := new_integer_vector_ptr(0); resize(ptr, 2, value => a_random_value); diff --git a/vunit/vhdl/data_types/test/tb_queue.vhd b/vunit/vhdl/data_types/test/tb_queue.vhd index 77448f35c..92db4911e 100644 --- a/vunit/vhdl/data_types/test/tb_queue.vhd +++ b/vunit/vhdl/data_types/test/tb_queue.vhd @@ -57,12 +57,12 @@ begin check_equal(length(queue), 0, "Empty queue length"); push_integer(queue, 11); - check_equal(length(queue), 5, "Length"); + check_equal(length(queue), 1, "Length"); push_integer(queue, 22); - check_equal(length(queue), 10, "Length"); + check_equal(length(queue), 2, "Length"); check_equal(pop_integer(queue), 11, "data"); - check_equal(length(queue), 5, "Length"); + check_equal(length(queue), 1, "Length"); check_equal(pop_integer(queue), 22, "data"); check_equal(length(queue), 0, "Length"); @@ -91,21 +91,21 @@ begin check_equal(length(queue), 0, "Empty queue length"); push_character(queue, '1'); - check_equal(length(queue), 2, "Length"); + check_equal(length(queue), 1, "Length"); push_character(queue, '2'); - check_equal(length(queue), 4, "Length"); + check_equal(length(queue), 2, "Length"); assert pop_character(queue) = '1'; - check_equal(length(queue), 2, "Length"); + check_equal(length(queue), 1, "Length"); assert pop_character(queue) = '2'; check_equal(length(queue), 0, "Length"); elsif run("Test flush queue") then queue := new_queue; push_character(queue, '1'); - check_equal(length(queue), 2, "Length"); + check_equal(length(queue), 1, "Length"); push_character(queue, '2'); - check_equal(length(queue), 4, "Length"); + check_equal(length(queue), 2, "Length"); flush(queue); check_equal(length(queue), 0, "Length"); diff --git a/vunit/vhdl/run/src/runner_pkg.vhd b/vunit/vhdl/run/src/runner_pkg.vhd index fedf7c8a7..9645066b1 100644 --- a/vunit/vhdl/run/src/runner_pkg.vhd +++ b/vunit/vhdl/run/src/runner_pkg.vhd @@ -7,9 +7,7 @@ -- Copyright (c) 2014-2019, Lars Asplund lars.anders.asplund@gmail.com use work.string_ptr_pkg.all; -use work.string_ptr_pool_pkg.all; use work.integer_vector_ptr_pkg.all; -use work.integer_vector_ptr_pool_pkg.all; use work.run_types_pkg.all; use work.logger_pkg.all; use work.string_ops.all; @@ -159,11 +157,8 @@ package body runner_pkg is end if; end; - constant str_pool : string_ptr_pool_t := new_string_ptr_pool; - constant int_pool : integer_vector_ptr_pool_t := new_integer_vector_ptr_pool; - impure function new_runner return runner_t is - variable runner : runner_t := (p_data => new_integer_vector_ptr(int_pool, runner_length)); + variable runner : runner_t := (p_data => new_integer_vector_ptr(runner_length)); begin runner_init(runner); return runner; @@ -196,12 +191,12 @@ package body runner_pkg is set(runner.p_data, test_case_iteration_idx, 0); set(runner.p_data, test_case_exit_after_error_idx, to_integer(false)); set(runner.p_data, test_suite_exit_after_error_idx, to_integer(false)); - set(runner.p_data, runner_cfg_idx, to_integer(new_string_ptr(str_pool, runner_cfg_default))); + set(runner.p_data, runner_cfg_idx, to_integer(new_string_ptr(runner_cfg_default))); set(runner.p_data, disable_simulation_exit_idx, to_integer(false)); set(runner.p_data, entry_locks_idx, to_integer(integer_vector_ptr_t'(new_integer_vector_ptr(n_legal_phases)))); set(runner.p_data, exit_locks_idx, to_integer(integer_vector_ptr_t'(new_integer_vector_ptr(n_legal_phases)))); - set(runner.p_data, timeout_idx, to_integer(new_string_ptr(str_pool, encode(0 ns)))); + set(runner.p_data, timeout_idx, to_integer(new_string_ptr(encode(0 ns)))); end; procedure set_active_python_runner(runner : runner_t; value : boolean) is @@ -287,7 +282,7 @@ package body runner_pkg is test_case_name := to_string_ptr(get(test_case_names, index-1)); if test_case_name = null_string_ptr then - test_case_name := new_string_ptr(str_pool, new_name); + test_case_name := new_string_ptr(new_name); else reallocate(test_case_name, new_name); end if; @@ -369,7 +364,7 @@ package body runner_pkg is run_test_case := to_string_ptr(get(run_test_cases, index-1)); if run_test_case = null_string_ptr then - run_test_case := new_string_ptr(str_pool, new_name); + run_test_case := new_string_ptr(new_name); else reallocate(run_test_case, new_name); end if; @@ -399,7 +394,7 @@ package body runner_pkg is variable running_test_case : string_ptr_t := to_string_ptr(get(runner.p_data, running_test_case_idx)); begin if running_test_case = null_string_ptr then - running_test_case := new_string_ptr(str_pool, new_name); + running_test_case := new_string_ptr(new_name); else reallocate(running_test_case, new_name); end if; @@ -504,7 +499,7 @@ package body runner_pkg is variable runner_cfg : string_ptr_t := to_string_ptr(get(runner.p_data, runner_cfg_idx)); begin if runner_cfg = null_string_ptr then - runner_cfg := new_string_ptr(str_pool, new_value); + runner_cfg := new_string_ptr(new_value); else reallocate(runner_cfg, new_value); end if; @@ -532,7 +527,7 @@ package body runner_pkg is variable timeout_ptr : string_ptr_t := to_string_ptr(get(runner.p_data, timeout_idx)); begin if timeout_ptr = null_string_ptr then - timeout_ptr := new_string_ptr(str_pool, new_value); + timeout_ptr := new_string_ptr(new_value); else reallocate(timeout_ptr, new_value); end if; diff --git a/vunit/vhdl/verification_components/src/axi_statistics_pkg.vhd b/vunit/vhdl/verification_components/src/axi_statistics_pkg.vhd index d39895601..14d1b8119 100644 --- a/vunit/vhdl/verification_components/src/axi_statistics_pkg.vhd +++ b/vunit/vhdl/verification_components/src/axi_statistics_pkg.vhd @@ -5,7 +5,6 @@ -- Copyright (c) 2014-2019, Lars Asplund lars.anders.asplund@gmail.com use work.axi_pkg.all; -use work.integer_vector_ptr_pool_pkg.all; use work.integer_vector_ptr_pkg.all; package axi_statistics_pkg is @@ -41,13 +40,11 @@ end package; package body axi_statistics_pkg is - constant ptr_pool : integer_vector_ptr_pool_t := new_integer_vector_ptr_pool; impure function new_axi_statistics return axi_statistics_t is variable stat : axi_statistics_t; begin - stat := (p_count_by_burst_length => new_integer_vector_ptr(ptr_pool, - min_length => max_axi4_burst_length + 1)); + stat := (p_count_by_burst_length => new_integer_vector_ptr(length => max_axi4_burst_length + 1)); clear(stat); return stat; end; @@ -121,7 +118,7 @@ package body axi_statistics_pkg is procedure deallocate(variable stat : inout axi_statistics_t) is begin if stat /= null_axi_statistics then - recycle(ptr_pool, stat.p_count_by_burst_length); + deallocate(stat.p_count_by_burst_length); stat := null_axi_statistics; end if; end; diff --git a/vunit/vhdl/verification_components/src/axi_write_slave.vhd b/vunit/vhdl/verification_components/src/axi_write_slave.vhd index 94a44f8f3..c7711e4eb 100644 --- a/vunit/vhdl/verification_components/src/axi_write_slave.vhd +++ b/vunit/vhdl/verification_components/src/axi_write_slave.vhd @@ -14,7 +14,6 @@ use work.axi_slave_private_pkg.all; use work.queue_pkg.all; use work.memory_pkg.all; use work.integer_vector_ptr_pkg.all; -use work.integer_vector_ptr_pool_pkg.all; context work.com_context; entity axi_write_slave is @@ -49,7 +48,6 @@ architecture a of axi_write_slave is signal initialized : boolean := false; constant data_vector_length : natural := max_axi4_burst_length * wdata'length; - constant data_pool : integer_vector_ptr_pool_t := new_integer_vector_ptr_pool; type burst_data_t is record length : natural; @@ -76,14 +74,16 @@ architecture a of axi_write_slave is impure function new_burst_data return burst_data_t is begin return (length => 0, - address => new_integer_vector_ptr(data_pool, min_length => data_vector_length), - data => new_integer_vector_ptr(data_pool, min_length => data_vector_length)); + address => new_integer_vector_ptr(length => data_vector_length), + data => new_integer_vector_ptr(length => data_vector_length)); end; - procedure recycle(variable burst_data : inout burst_data_t) is + procedure deallocate(variable burst_data : inout burst_data_t) is begin - recycle(data_pool, burst_data.address); - recycle(data_pool, burst_data.data); + deallocate(burst_data.address); + deallocate(burst_data.data); + burst_data.address := null_ptr; + burst_data.data := null_ptr; end; begin @@ -120,7 +120,7 @@ begin for i in 0 to burst_data.length-1 loop write_byte_unchecked(axi_slave.p_memory, get(burst_data.address, i), get(burst_data.data, i)); end loop; - recycle(burst_data); + deallocate(burst_data); end; variable resp_burst, input_burst, burst : axi_burst_t;