From 9acd98b32ea143af4a0ea14e1af9983d7585c0c4 Mon Sep 17 00:00:00 2001 From: Greek Date: Mon, 2 Nov 2020 14:39:27 +0100 Subject: [PATCH] * Update .gitignore * Split rtps_package --- .gitignore | 1 + src/rtps_builtin_endpoint.vhd | 232 +++---- src/rtps_config_package.vhd | 759 +++++++++++++++++++++++ src/rtps_handler.vhd | 60 +- src/rtps_package.vhd | 1098 +++++++-------------------------- src/test.vhd | 11 +- src/test_package.vhd | 3 + src/user_config.vhd | 123 ++++ syn/DE10-Nano/top.qsf | 41 +- syn/Zedboard/rtps-fpga.xpr | 25 +- 10 files changed, 1292 insertions(+), 1061 deletions(-) create mode 100644 src/rtps_config_package.vhd create mode 100644 src/user_config.vhd diff --git a/.gitignore b/.gitignore index e781e52..cb1f2c6 100644 --- a/.gitignore +++ b/.gitignore @@ -17,6 +17,7 @@ #***QUARTUS*** #Project File !*.qpf +!*.qsf #Settings File !*.qsf #QSYS File diff --git a/src/rtps_builtin_endpoint.vhd b/src/rtps_builtin_endpoint.vhd index f61723a..4e251ec 100644 --- a/src/rtps_builtin_endpoint.vhd +++ b/src/rtps_builtin_endpoint.vhd @@ -4,6 +4,8 @@ use ieee.numeric_std.all; use work.math_pkg.all; use work.rtps_package.all; +use work.user_config.all; +use work.rtps_config_package.all; -- TODO: Skip Packet while we are waiting for memory operation to complete -- TODO: add_res is still valid after removal. So we could continue searching the next orphan endpoint from that address on @@ -14,17 +16,17 @@ entity rtps_builtin_endpoint is reset : in std_logic; -- Synchronous Reset empty : in std_logic; -- Input FIFO empty flag rd : out std_logic; -- Input FIFO read signal - data_in : in std_logic_vector(31 downto 0); -- Input FIFO data signal + data_in : in std_logic_vector(WORD_WIDTH-1 downto 0); -- Input FIFO data signal last_word_in : in std_logic; - time : in DOUBLE_WORD_ARRAY; - endpoint_output : out USER_ENDPOINT_OUTPUT; - endpoint_full : in std_logic_vector(0 to MAX_ENDPOINTS-1); - endpoint_wr : out std_logic_vector(0 to MAX_ENDPOINTS-1); - rtps_output : out std_logic_vector(31 downto 0); + time : in TIME_TYPE; + endpoint_output : out std_logic_vector(WORD_WIDTH-1 downto 0); + endpoint_full : in std_logic_vector(0 to NUM_ENDPOINTS-1); + endpoint_wr : out std_logic_vector(0 to NUM_ENDPOINTS-1); + rtps_output : out std_logic_vector(WORD_WIDTH-1 downto 0); rtps_wr : out std_logic; rtps_full : in std_logic; last_word_out : out std_logic; - alive : in std_logic_vector(0 to MAX_ENDPOINTS-1) + alive : in std_logic_vector(0 to NUM_ENDPOINTS-1) ); end entity; @@ -101,22 +103,22 @@ architecture arch of rtps_builtin_endpoint is -- * MESSAGE Participant Message Data type MESSAGE_TYPE_TYPE is (NONE, PDP, EDP, MESSAGE); -- String Content - type STRING_CONTENT_TYPE is (TOPIC_NAME, TYPE_NAME, DOMAIN_TAG); + type STRING_CONTENT_TYPE is (TOPIC_NAME_TYPE, TYPE_NAME_TYPE, DOMAIN_TAG_TYPE); -- Record of all Participant Data stored in memory type PARTICIPANT_DATA_TYPE is record - meta_addr : std_logic_vector(31 downto 0); - def_addr : std_logic_vector(31 downto 0); - meta_port : std_logic_vector(15 downto 0); - def_port : std_logic_vector(15 downto 0); + meta_addr : std_logic_vector(IPv4_ADDRESS_WIDTH-1 downto 0); + def_addr : std_logic_vector(IPv4_ADDRESS_WIDTH-1 downto 0); + meta_port : std_logic_vector(UDP_PORT_WIDTH-1 downto 0); + def_port : std_logic_vector(UDP_PORT_WIDTH-1 downto 0); extra_flags : std_logic_vector(EXTRA_FLAGS_WIDTH-1 downto 0); - lease_duration : DOUBLE_WORD_ARRAY; - lease_deadline : DOUBLE_WORD_ARRAY; - heartbeat_res_time : DOUBLE_WORD_ARRAY; - acknack_res_time : DOUBLE_WORD_ARRAY; - spdp_seq_nr : DOUBLE_WORD_ARRAY; - pub_seq_nr : DOUBLE_WORD_ARRAY; - sub_seq_nr : DOUBLE_WORD_ARRAY; - mes_seq_nr : DOUBLE_WORD_ARRAY; + lease_duration : DURATION_TYPE; + lease_deadline : TIME_TYPE; + heartbeat_res_time : TIME_TYPE; + acknack_res_time : TIME_TYPE; + spdp_seq_nr : SEQUENCE_NR_TYPE; + pub_seq_nr : SEQUENCE_NR_TYPE; + sub_seq_nr : SEQUENCE_NR_TYPE; + mes_seq_nr : SEQUENCE_NR_TYPE; end record; --*****CONSTANT DECLARATION***** @@ -153,13 +155,13 @@ architecture arch of rtps_builtin_endpoint is -- Signifies if the Reader Endpoint expects in-line QoS constant EXPECTS_INLINE_QOS_FLAG : natural := 0; -- Highest Sequence Number of Publisher Data - constant PUB_SEQUENCE_NR : DOUBLE_WORD_ARRAY := convert_to_double_word(to_unsigned(NUM_WRITERS, 64)); + constant PUB_SEQUENCE_NR : SEQUENCE_NR_TYPE := convert_to_double_word(to_unsigned(NUM_WRITERS, 64)); -- Highest Sequence Number of Subscriber Data - constant SUB_SEQUENCE_NR : DOUBLE_WORD_ARRAY := convert_to_double_word(to_unsigned(NUM_READERS, 64)); + constant SUB_SEQUENCE_NR : SEQUENCE_NR_TYPE := convert_to_double_word(to_unsigned(NUM_READERS, 64)); -- Constant for Sequence Number 1 - constant SEQUENCE_NR_START : DOUBLE_WORD_ARRAY := convert_to_double_word(to_unsigned(1, 64)); + constant SEQUENCE_NR_START : SEQUENCE_NR_TYPE := convert_to_double_word(to_unsigned(1, 64)); -- Heartbeat/Liveliness Assertion Period - constant HEARTBEAT_PERIOD : DOUBLE_WORD_ARRAY := work.rtps_package.min(MIN_ENDPOINT_LEASE_DURATION, PARTICIPANT_HEARTBEAT_PERIOD) - DURATION_DELTA; + constant HEARTBEAT_PERIOD : DURATION_TYPE := work.rtps_package.min(MIN_ENDPOINT_LEASE_DURATION, PARTICIPANT_HEARTBEAT_PERIOD) - DURATION_DELTA; -- Constant for zero Participant Data constant ZERO_PARTICIPANT_DATA : PARTICIPANT_DATA_TYPE := ( meta_addr => (others => '0'), @@ -190,39 +192,39 @@ architecture arch of rtps_builtin_endpoint is -- Signal used to reset the word counter signal reset_read_cnt : std_logic; -- Word (4-Byte) counter (Counts words read from input fifo) - signal read_cnt : unsigned(13 downto 0) := (others => '0'); + signal read_cnt : unsigned(SUBMESSAGE_LENGTH_WIDTH-3 downto 0) := (others => '0'); -- RTPS Submessage ID Latch signal opcode, opcode_next : std_logic_vector(SUBMESSAGE_ID_WIDTH-1 downto 0) := (others => '0'); -- RTPS Submessage Flags Latch - signal flags, flags_next : std_logic_vector(7 downto 0) := (others => '0'); + signal flags, flags_next : std_logic_vector(SUBMESSAGE_FLAGS_WIDTH-1 downto 0) := (others => '0'); -- UDPv4 Source Port Latch - signal src_port, src_port_next : std_logic_vector(15 downto 0) := (others => '0'); + signal src_port, src_port_next : std_logic_vector(UDP_PORT_WIDTH-1 downto 0) := (others => '0'); -- IPv4 Source Address Latch - signal src_addr, src_addr_next : std_logic_vector(31 downto 0) := (others => '0'); + signal src_addr, src_addr_next : std_logic_vector(IPv4_ADDRESS_WIDTH-1 downto 0) := (others => '0'); -- Source Entity ID Latch - signal src_entityid, src_entityid_next : std_logic_vector(31 downto 0) := (others => '0'); + signal src_entityid, src_entityid_next : std_logic_vector(ENTITYID_WIDTH-1 downto 0) := (others => '0'); -- Destination Entity ID Latch - signal dest_entityid, dest_entityid_next : std_logic_vector(31 downto 0) := (others => '0'); + signal dest_entityid, dest_entityid_next : std_logic_vector(ENTITYID_WIDTH-1 downto 0) := (others => '0'); -- Source GUID Latch signal guid, guid_next : GUID_TYPE := (others => (others => '0')); -- RTPS DATA Submessage Sequence Number Latch - signal seq_nr, seq_nr_next : DOUBLE_WORD_ARRAY := (others => (others => '0')); + signal seq_nr, seq_nr_next : SEQUENCE_NR_TYPE := (others => (others => '0')); -- Word aligned End of Parameter - signal parameter_end, parameter_end_next : unsigned(15 downto 0) := (others => '0'); + signal parameter_end, parameter_end_next : unsigned(PARAMETER_LENGTH_WIDTH-1 downto 0) := (others => '0'); -- RTPS DATA Submessage Content Type signal message_type, message_type_next : MESSAGE_TYPE_TYPE := NONE; -- Data in represented in Big Endian - signal data_in_swapped : std_logic_vector(31 downto 0) := (others => '0'); + signal data_in_swapped : std_logic_vector(WORD_WIDTH-1 downto 0) := (others => '0'); -- Byte Length of string - signal string_length, string_length_next : unsigned(31 downto 0) := (others => '0'); + signal string_length, string_length_next : unsigned(WORD_WIDTH-1 downto 0) := (others => '0'); -- Counter of compared string words (4-Byte) - signal compare_length, compare_length_next : unsigned(29 downto 0) := (others => '0'); + signal compare_length, compare_length_next : unsigned(WORD_WIDTH-3 downto 0) := (others => '0'); -- Bitmask of local Endpoint Matches - signal endpoint_mask, endpoint_mask_next : std_logic_vector(0 to MAX_ENDPOINTS-1) := (others => '0'); + signal endpoint_mask, endpoint_mask_next : std_logic_vector(0 to NUM_ENDPOINTS-1) := (others => '0'); -- Bitmask of new local Endpoint Matches - signal endpoint_match, endpoint_match_next : std_logic_vector(0 to MAX_ENDPOINTS-1) := (others => '0'); + signal endpoint_match, endpoint_match_next : std_logic_vector(0 to NUM_ENDPOINTS-1) := (others => '0'); -- Bitmask of local Endpoint unmatches - signal endpoint_unmatch, endpoint_unmatch_next : std_logic_vector(0 to MAX_ENDPOINTS-1) := (others => '0'); + signal endpoint_unmatch, endpoint_unmatch_next : std_logic_vector(0 to NUM_ENDPOINTS-1) := (others => '0'); -- Bitmask of local Endpoint Matches stored in Memory signal endpoint_mask_array, endpoint_mask_array_next : ENDPOINT_BITMASK_ARRAY_TYPE := (others => (others => '0')); -- Signifies if the source of the Participant Data is compatible with our Participant @@ -230,7 +232,7 @@ architecture arch of rtps_builtin_endpoint is -- Signifies if the Packet is comming from a Subscriber Endpoint signal is_subscriber, is_subscriber_next : std_logic := '0'; -- Signal storing times for memory operations (Participant Lease Deadline, HEARTBEAT/ACKNACK Response/Suppression Time) - signal deadline, deadline_next : DOUBLE_WORD_ARRAY := (others => (others => '0')); + signal deadline, deadline_next : TIME_TYPE := (others => (others => '0')); -- Signifies that the read Locator is a Metatraffic Locator signal is_meta_addr, is_meta_addr_next : std_logic := '0'; -- General Purpose counter @@ -261,25 +263,25 @@ architecture arch of rtps_builtin_endpoint is -- Lowest Endpoint Memory Address (Points to first Word of last occupied Endpoint Frame) signal max_endpoint_addr, max_endpoint_addr_next : unsigned(BUILTIN_BUFFER_ADDR_WIDTH-1 downto 0) := (others => '0'); -- Memory Data Read and Write Signals - signal mem_read_data, mem_write_data : std_logic_vector(31 downto 0) := (others => '0'); + signal mem_read_data, mem_write_data : std_logic_vector(WORD_WIDTH-1 downto 0) := (others => '0'); -- Memory Read and Write Enable Signals signal mem_rd, mem_wr : std_logic := '0'; -- General Purpose Counter (Memory FSM) signal mem_cnt, mem_cnt_next : natural range 0 to max(22, ENDPOINT_BITMASK_SIZE-1) := 0; -- Contains the Sequence Number stored in the Buffer of the current relevant Message Type (Participant/Publisher/Subscriber/Message Data) - signal mem_seq_nr, mem_seq_nr_next : DOUBLE_WORD_ARRAY := (others => (others => '0')); + signal mem_seq_nr, mem_seq_nr_next : SEQUENCE_NR_TYPE := (others => (others => '0')); -- Signifies the next expected Sequence Number of the current relevant Message Type (Participant/Publisher/Subscriber/Message Data) - signal next_seq_nr, next_seq_nr_next : DOUBLE_WORD_ARRAY := (others => (others => '0')); + signal next_seq_nr, next_seq_nr_next : SEQUENCE_NR_TYPE := (others => (others => '0')); -- Latch used to store the first Sequence Number in ACKNACK/HEARTBEAT/GAP Messages - signal first_seq_nr, first_seq_nr_next : DOUBLE_WORD_ARRAY := (others => (others => '0')); + signal first_seq_nr, first_seq_nr_next : SEQUENCE_NR_TYPE := (others => (others => '0')); -- Latch used to store the last Sequence Number in HEARTBEAT/GAP Messages - signal last_seq_nr, last_seq_nr_next : DOUBLE_WORD_ARRAY := (others => (others => '0')); + signal last_seq_nr, last_seq_nr_next : SEQUENCE_NR_TYPE := (others => (others => '0')); -- Signifies if we currently do a Orphan Endpoint Search (Endpoint whose parent Participant was removed) signal is_orphan_search, is_orphan_search_next : std_logic := '0'; -- Intermediate write enable signal. signal wr_sig : std_logic := '0'; -- Intermediate Output Signal - signal output_sig : std_logic_vector(31 downto 0) := (others => '0'); + signal output_sig : std_logic_vector(WORD_WIDTH-1 downto 0) := (others => '0'); -- Signifies if we currently are resetting the MAX Participant/Endpoint Pointer signal reset_max_pointer, reset_max_pointer_next : std_logic := '0'; -- Signifies if we currently are doing a Participant Stale Entry Check (Used to start Stale Checks between packet handling) @@ -297,40 +299,40 @@ architecture arch of rtps_builtin_endpoint is -- Signifies when "mem_seq_nr" and "next_seq_nr" signals are valid signal seq_prc_done, seq_prc_done_next : std_logic := '0'; -- Signal containing the HEARTBEAT/ACKNACK count of all built-in Endpoints - signal count, count_next : unsigned(31 downto 0) := (others => '0'); + signal count, count_next : unsigned(COUNT_WIDTH-1 downto 0) := (others => '0'); -- Toggle set when at least one Endpoint has asserted the "alive" signal, until reset signal endpoint_alive : std_logic := '0'; -- Resets the "endpoint_alive" signal signal reset_endpoint_alive : std_logic := '0'; -- NOTE: The "auto_live_seq_nr" is always higher than "man_live_seq_nr" -- Contains the highest Sequence Number for automatic liveliness updates - signal auto_live_seq_nr, auto_live_seq_nr_next : DOUBLE_WORD_ARRAY := (others => (others => '0')); + signal auto_live_seq_nr, auto_live_seq_nr_next : SEQUENCE_NR_TYPE := (others => (others => '0')); -- Contains the highest Sequence Number for manual by participant liveliness updates - signal man_live_seq_nr, man_live_seq_nr_next : DOUBLE_WORD_ARRAY := (others => (others => '0')); + signal man_live_seq_nr, man_live_seq_nr_next : SEQUENCE_NR_TYPE := (others => (others => '0')); -- Points to the first Sequence Number after "man_live_seq_nr" (Signifies the start of the GAP between "man_live_seq_nr" and "auto_live_seq_nr") - signal live_gap_start, live_gap_start_next : DOUBLE_WORD_ARRAY := (others => (others => '0')); + signal live_gap_start, live_gap_start_next : SEQUENCE_NR_TYPE := (others => (others => '0')); -- Points to the first Sequence Number before "auto_live_seq_nr" (Signifies the end of the GAP between "man_live_seq_nr" and "auto_live_seq_nr") - signal live_gap_end, live_gap_end_next : DOUBLE_WORD_ARRAY := (others => (others => '0')); + signal live_gap_end, live_gap_end_next : SEQUENCE_NR_TYPE := (others => (others => '0')); -- Participant Announcement Timeout Time - signal announcement_time, announcement_time_next : DOUBLE_WORD_ARRAY := (others => (others => '0')); + signal announcement_time, announcement_time_next : TIME_TYPE := (others => (others => '0')); -- Heartbeat/Liveliness Assertion Timeout Time - signal heartbeat_time, heartbeat_time_next : DOUBLE_WORD_ARRAY := (others => (others => '0')); + signal heartbeat_time, heartbeat_time_next : TIME_TYPE := (others => (others => '0')); -- Signifies if we are currently in a Liveliness Assertion signal is_live_assert, is_live_assert_next : std_logic := '0'; -- Signifies the content of the string read from input - signal string_content, string_content_next : STRING_CONTENT_TYPE := TOPIC_NAME; + signal string_content, string_content_next : STRING_CONTENT_TYPE := TOPIC_NAME_TYPE; -- Signifies that the expects_inline_qos Flag was explicitly set via a Parameter ID signal expects_inline_qos_set, expects_inline_qos_set_next : std_logic := '0'; -- Endpoint Locator IPv4 Address Latch - signal def_addr, def_addr_next : std_logic_vector(31 downto 0) := (others => '0'); + signal def_addr, def_addr_next : std_logic_vector(IPv4_ADDRESS_WIDTH-1 downto 0) := (others => '0'); -- Metatraffic Locator IPv4 Address Latch - signal meta_addr, meta_addr_next : std_logic_vector(31 downto 0) := (others => '0'); + signal meta_addr, meta_addr_next : std_logic_vector(IPv4_ADDRESS_WIDTH-1 downto 0) := (others => '0'); -- Endpoint UDPv4 Port Latch - signal def_port, def_port_next : std_logic_vector(15 downto 0) := (others => '0'); + signal def_port, def_port_next : std_logic_vector(UDP_PORT_WIDTH-1 downto 0) := (others => '0'); -- Metatraffic UDPv4 Port Latch - signal meta_port, meta_port_next : std_logic_vector(15 downto 0) := (others => '0'); + signal meta_port, meta_port_next : std_logic_vector(UDP_PORT_WIDTH-1 downto 0) := (others => '0'); -- Participant Lease Duration Latch - signal lease_duration, lease_duration_next : DOUBLE_WORD_ARRAY := (others => (others => '0')); + signal lease_duration, lease_duration_next : DURATION_TYPE := (others => (others => '0')); -- Extra Flags Latch signal extra_flags, extra_flags_next : std_logic_vector(EXTRA_FLAGS_WIDTH-1 downto 0) := (others => '0'); @@ -490,10 +492,8 @@ begin output_prc : process(all) begin -- Data Signal - for i in 0 to MAX_ENDPOINTS-1 loop - endpoint_output(i) <= output_sig; - end loop; - rtps_output <= output_sig; + endpoint_output <= output_sig; + rtps_output <= output_sig; --Write Enable Signal endpoint_wr <= (others => '0'); @@ -577,7 +577,7 @@ begin -- SKIP_PARAMETER Skip rest of Parameter -- SKIP_PACKET Skip rest of Packet parse_prc: process(all) - variable tmp_endpoint_mask : std_logic_vector(0 to MAX_ENDPOINTS-1) := (others => '0'); + variable tmp_endpoint_mask : std_logic_vector(0 to NUM_ENDPOINTS-1) := (others => '0'); begin --DEFAULT Registered stage_next <= stage; @@ -1113,7 +1113,7 @@ begin when PARTICIPANT_MESSAGE_DATA_KIND_AUTOMATIC_LIVELINESS_UPDATE => -- Unmark all readers without automatic liveliness QoS for i in 0 to NUM_READERS-1 loop - if (AUTOMATIC_LIVELINESS_QOS /= ENDPOINT_LIVELINESS(i)) then + if (AUTOMATIC_LIVELINESS_QOS /= ENDPOINT_LIVELINESS_QOS(i)) then endpoint_mask_next(i) <= '0'; end if; end loop; @@ -1123,7 +1123,7 @@ begin when PARTICIPANT_MESSAGE_DATA_KIND_MANUAL_LIVELINESS_UPDATE => -- Unmark all readers without manual by participant liveliness QoS for i in 0 to NUM_READERS-1 loop - if (MANUAL_BY_PARTICIPANT_LIVELINESS_QOS /= ENDPOINT_LIVELINESS(i)) then + if (MANUAL_BY_PARTICIPANT_LIVELINESS_QOS /= ENDPOINT_LIVELINESS_QOS(i)) then endpoint_mask_next(i) <= '0'; end if; end loop; @@ -1533,7 +1533,7 @@ begin mem_op_start <= '1'; -- Mark UNMATCHES endpoint_match_next <= (others => '0'); - endpoint_unmatch_next <= convert_from_bitmask_array(endpoint_mask_array, MAX_ENDPOINTS); + endpoint_unmatch_next <= convert_from_bitmask_array(endpoint_mask_array, NUM_ENDPOINTS); -- Propagate Unmatches to local Endpoints stage_next <= INFORM_ENDPOINTS_UNMATCH; cnt_next <= 0; @@ -1550,7 +1550,7 @@ begin -- Reset Word Counter reset_read_cnt <= '1'; -- Latch Parameter End (In order to skip parameters) - parameter_end_next <= unsigned(endian_swap(endian_flag,parameter_length)); + parameter_end_next <= unsigned(big_endian_swap(endian_flag,parameter_length)); -- DEFAULT STAGE stage_next <= SKIP_PARAMETER; @@ -1578,7 +1578,7 @@ begin if(qos_flag = '0' and message_type = PDP) then stage_next <= LATCH_STRING_LENGTH; -- Mark String contents (Needed for string comparison) - string_content_next <= DOMAIN_TAG; + string_content_next <= DOMAIN_TAG_TYPE; end if; when PID_PROTOCOL_VERSION => -- Ignore in-line QoS @@ -1643,7 +1643,7 @@ begin if(qos_flag = '0' and message_type = EDP) then stage_next <= LATCH_STRING_LENGTH; -- Mark String contents (Needed for string comparison) - string_content_next <= TOPIC_NAME; + string_content_next <= TOPIC_NAME_TYPE; end if; when PID_TYPE_NAME => -- Ignore in-line QoS @@ -1651,7 +1651,7 @@ begin if(qos_flag = '0' and message_type = EDP) then stage_next <= LATCH_STRING_LENGTH; -- Mark String contents (Needed for string comparison) - string_content_next <= TYPE_NAME; + string_content_next <= TYPE_NAME_TYPE; end if; when PID_DURABILITY => -- Ignore in-line QoS @@ -1866,20 +1866,20 @@ begin -- Unmark matches on string comparison missmatch case (string_content) is - when TOPIC_NAME => - for i in 0 to MAX_ENDPOINTS-1 loop + when TOPIC_NAME_TYPE => + for i in 0 to NUM_ENDPOINTS-1 loop if (data_in /= ENDPOINT_TOPIC(i)(cnt)) then endpoint_mask_next(i) <= '0'; end if; end loop; - when TYPE_NAME => - for i in 0 to MAX_ENDPOINTS-1 loop + when TYPE_NAME_TYPE => + for i in 0 to NUM_ENDPOINTS-1 loop if (data_in /= ENDPOINT_TYPE(i)(cnt)) then endpoint_mask_next(i) <= '0'; end if; end loop; - when DOMAIN_TAG => - if (data_in /= work.rtps_package.DOMAIN_TAG(cnt)) then + when DOMAIN_TAG_TYPE => + if (data_in /= DOMAIN_TAG(cnt)) then participant_match_next <= '0'; end if; when others => @@ -1964,10 +1964,13 @@ begin -- Locator Port when 1 => -- Latch Source Port - if (is_meta_addr = '0') then - def_port_next <= data_in_swapped(def_port'length-1 downto 0); - else - meta_port_next <= data_in_swapped(meta_port'length-1 downto 0); + -- SANITY CHECK: Check if UDP Port valid + if (data_in_swapped(UDP_PORT_INVALID'range) /= UDP_PORT_INVALID) then + if (is_meta_addr = '0') then + def_port_next <= data_in_swapped(def_port'length-1 downto 0); + else + meta_port_next <= data_in_swapped(meta_port'length-1 downto 0); + end if; end if; -- Locator Address 1/4 when 2 => @@ -1981,10 +1984,13 @@ begin -- Locator Address 4/4 (IPv4) when 5 => -- Latch Src Addr - if (is_meta_addr = '0') then - def_addr_next <= data_in_swapped; - else - meta_addr_next <= data_in_swapped; + -- SANITY CHECK: Check if IPv4 Address valid + if (data_in_swapped /= IPv4_ADDRESS_INVALID) then + if (is_meta_addr = '0') then + def_addr_next <= data_in_swapped; + else + meta_addr_next <= data_in_swapped; + end if; end if; -- DONE stage_next <= SKIP_PARAMETER; @@ -2058,15 +2064,15 @@ begin -- Check QoS Compatibility (Unmark match on incompatibility) -- COMPATIBLE (DDS v1.4): offered >= requested, with VOLATILE < TRANSIENT_LOCAL < TRANSIENT < PERSISTENT - for i in 0 to MAX_ENDPOINTS-1 loop + for i in 0 to NUM_ENDPOINTS-1 loop -- data-in is Subscriber-Requested if (is_subscriber = '1') then - if (unsigned(data_in_swapped) > unsigned(ENDPOINT_DURABILITY(i))) then + if (unsigned(data_in_swapped) > unsigned(ENDPOINT_DURABILITY_QOS(i))) then endpoint_mask_next(i) <= '0'; end if; -- data-in is Publisher-Offered else - if (unsigned(data_in_swapped) < unsigned(ENDPOINT_DURABILITY(i))) then + if (unsigned(data_in_swapped) < unsigned(ENDPOINT_DURABILITY_QOS(i))) then endpoint_mask_next(i) <= '0'; end if; end if; @@ -2084,15 +2090,15 @@ begin when 0 => -- Check QoS Compatibility (Unmark match on incompatibility) -- COMPATIBLE (DDS v1.4): offered <= requested - for i in 0 to MAX_ENDPOINTS-1 loop + for i in 0 to NUM_ENDPOINTS-1 loop -- data-in is Subscriber-Requested if (is_subscriber = '1') then - if (unsigned(data_in_swapped) < ENDPOINT_DEADLINE(i)(0)) then + if (unsigned(data_in_swapped) < ENDPOINT_DEADLINE_QOS(i)(0)) then endpoint_mask_next(i) <= '0'; end if; -- data-in is Publisher-Offered else - if (unsigned(data_in_swapped) > ENDPOINT_DEADLINE(i)(0)) then + if (unsigned(data_in_swapped) > ENDPOINT_DEADLINE_QOS(i)(0)) then endpoint_mask_next(i) <= '0'; end if; end if; @@ -2100,15 +2106,15 @@ begin when 1 => -- Check QoS Compatibility (Unmark match on incompatibility) -- COMPATIBLE (DDS v1.4): offered <= requested - for i in 0 to MAX_ENDPOINTS-1 loop + for i in 0 to NUM_ENDPOINTS-1 loop -- data-in is Subscriber-Requested if (is_subscriber = '1') then - if (unsigned(data_in_swapped) < ENDPOINT_DEADLINE(i)(1)) then + if (unsigned(data_in_swapped) < ENDPOINT_DEADLINE_QOS(i)(1)) then endpoint_mask_next(i) <= '0'; end if; -- data-in is Publisher-Offered else - if (unsigned(data_in_swapped) > ENDPOINT_DEADLINE(i)(1)) then + if (unsigned(data_in_swapped) > ENDPOINT_DEADLINE_QOS(i)(1)) then endpoint_mask_next(i) <= '0'; end if; end if; @@ -2126,15 +2132,15 @@ begin -- Check QoS Compatibility (Unmark match on incompatibility) -- COMPATIBLE (DDS v1.4): offered >= requested, with AUTOMATIC < MANUAL_BY_PARTICIPANT < MANUAL_BY_TOPIC - for i in 0 to MAX_ENDPOINTS-1 loop + for i in 0 to NUM_ENDPOINTS-1 loop -- data-in is Subscriber-Requested if (is_subscriber = '1') then - if (unsigned(data_in_swapped) > unsigned(ENDPOINT_LIVELINESS(i))) then + if (unsigned(data_in_swapped) > unsigned(ENDPOINT_LIVELINESS_QOS(i))) then endpoint_mask_next(i) <= '0'; end if; -- data-in is Publisher-Offered else - if (unsigned(data_in_swapped) < unsigned(ENDPOINT_LIVELINESS(i))) then + if (unsigned(data_in_swapped) < unsigned(ENDPOINT_LIVELINESS_QOS(i))) then endpoint_mask_next(i) <= '0'; end if; end if; @@ -2153,7 +2159,7 @@ begin when 0 => -- Check QoS Compatibility (Unmark match on incompatibility) -- COMPATIBLE (DDS v1.4): offered <= requested - for i in 0 to MAX_ENDPOINTS-1 loop + for i in 0 to NUM_ENDPOINTS-1 loop -- data-in is Subscriber-Requested if (is_subscriber = '1') then if (unsigned(data_in_swapped) > ENDPOINT_LEASE_DURATION(i)(0)) then @@ -2169,7 +2175,7 @@ begin when 1 => -- Check QoS Compatibility (Unmark match on incompatibility) -- COMPATIBLE (DDS v1.4): offered <= requested - for i in 0 to MAX_ENDPOINTS-1 loop + for i in 0 to NUM_ENDPOINTS-1 loop -- data-in is Subscriber-Requested if (is_subscriber = '1') then if (unsigned(data_in_swapped) > ENDPOINT_LEASE_DURATION(i)(1)) then @@ -2195,15 +2201,15 @@ begin -- Check QoS Compatibility (Unmark match on incompatibility) -- COMPATIBLE (DDS v1.4): offered >= requested, with BEST_EFFORT < RELIABLE - for i in 0 to MAX_ENDPOINTS-1 loop + for i in 0 to NUM_ENDPOINTS-1 loop -- data-in is Subscriber-Requested if (is_subscriber = '1') then - if (unsigned(data_in_swapped) > unsigned(ENDPOINT_RELIABILITY(i))) then + if (unsigned(data_in_swapped) > unsigned(ENDPOINT_RELIABILITY_QOS(i))) then endpoint_mask_next(i) <= '0'; end if; -- data-in is Publisher-Offered else - if (unsigned(data_in_swapped) < unsigned(ENDPOINT_RELIABILITY(i))) then + if (unsigned(data_in_swapped) < unsigned(ENDPOINT_RELIABILITY_QOS(i))) then endpoint_mask_next(i) <= '0'; end if; end if; @@ -2220,15 +2226,15 @@ begin -- Check QoS Compatibility (Unmark match on incompatibility) -- COMPATIBLE (DDS v1.4): offered >= requested, with BY_RECEPTION_TIMESTAMP < BY_SOURCE_TIMESTAMP - for i in 0 to MAX_ENDPOINTS-1 loop + for i in 0 to NUM_ENDPOINTS-1 loop -- data-in is Subscriber-Requested if (is_subscriber = '1') then - if (unsigned(data_in_swapped) > unsigned(ENDPOINT_DESTINATION_ORDER(i))) then + if (unsigned(data_in_swapped) > unsigned(ENDPOINT_DESTINATION_ORDER_QOS(i))) then endpoint_mask_next(i) <= '0'; end if; -- data-in is Publisher-Offered else - if (unsigned(data_in_swapped) < unsigned(ENDPOINT_DESTINATION_ORDER(i))) then + if (unsigned(data_in_swapped) < unsigned(ENDPOINT_DESTINATION_ORDER_QOS(i))) then endpoint_mask_next(i) <= '0'; end if; end if; @@ -2260,29 +2266,29 @@ begin when 0 => -- Check QoS Compatibility (Unmark match on incompatibility) -- COMPATIBLE (DDS v1.4): offered >= requested, with INSTANCE < TOPIC < GROUP - for i in 0 to MAX_ENDPOINTS-1 loop + for i in 0 to NUM_ENDPOINTS-1 loop -- data-in is Subscriber-Requested if (is_subscriber = '1') then - if (unsigned(data_in_swapped) > unsigned(ENDPOINT_PRESENTATION(i))) then + if (unsigned(data_in_swapped) > unsigned(ENDPOINT_PRESENTATION_QOS(i))) then endpoint_mask_next(i) <= '0'; end if; -- data-in is Publisher-Offered else - if (unsigned(data_in_swapped) < unsigned(ENDPOINT_PRESENTATION(i))) then + if (unsigned(data_in_swapped) < unsigned(ENDPOINT_PRESENTATION_QOS(i))) then endpoint_mask_next(i) <= '0'; end if; end if; end loop; when 1 => -- Check QoS Compatibility (Unmark match on incompatibility) - for i in 0 to MAX_ENDPOINTS-1 loop + for i in 0 to NUM_ENDPOINTS-1 loop -- data-in is Subscriber-Requested -- COMPATIBLE (DDS v1.4): requested=FALSE or requested=offered=TRUE if (is_subscriber = '1') then - if (data_in(23) = '1' and ENDPOINT_COHERENT_ACCESS(i) = '0') then + if (data_in(23) = '1' and ENDPOINT_COHERENT_ACCESS(i) = FALSE) then endpoint_mask_next(i) <= '0'; end if; - if (data_in(15) = '1' and ENDPOINT_ORDERED_ACCESS(i) = '0') then + if (data_in(15) = '1' and ENDPOINT_ORDERED_ACCESS(i) = FALSE) then endpoint_mask_next(i) <= '0'; end if; end if; @@ -2405,7 +2411,7 @@ begin -- At least one local Endpoint match if (endpoint_mask /= (endpoint_mask'range => '0')) then -- Mark Endpoint match changes - tmp_endpoint_mask := convert_from_bitmask_array(endpoint_mask_array, MAX_ENDPOINTS); + tmp_endpoint_mask := convert_from_bitmask_array(endpoint_mask_array, NUM_ENDPOINTS); tmp_endpoint_mask := tmp_endpoint_mask xor endpoint_mask; -- Mark UNMATCHES endpoint_unmatch_next <= tmp_endpoint_mask xor endpoint_mask; @@ -2424,7 +2430,7 @@ begin mem_op_start <= '1'; -- Mark UNMATCHES endpoint_match_next <= (others => '0'); - endpoint_unmatch_next <= convert_from_bitmask_array(endpoint_mask_array, MAX_ENDPOINTS); + endpoint_unmatch_next <= convert_from_bitmask_array(endpoint_mask_array, NUM_ENDPOINTS); -- Propagate Unmatches to local Endpoints stage_next <= INFORM_ENDPOINTS_UNMATCH; cnt_next <= 0; @@ -4020,7 +4026,7 @@ begin stage <= IDLE; return_stage <= IDLE; message_type <= NONE; - string_content <= DOMAIN_TAG; + string_content <= DOMAIN_TAG_TYPE; mem_stage <= IDLE; opcode <= (others => '0'); flags <= (others => '0'); diff --git a/src/rtps_config_package.vhd b/src/rtps_config_package.vhd new file mode 100644 index 0000000..6772fe7 --- /dev/null +++ b/src/rtps_config_package.vhd @@ -0,0 +1,759 @@ +library ieee; +use ieee.std_logic_1164.all; +use ieee.numeric_std.all; + +use work.math_pkg.all; +use work.rtps_package.all; +use work.user_config.all; + +-- TODO: Convert ALL integers to natural, and remove all conversions (Arithmetics between natural and unsigned are directly supported) + +package rtps_config_package is + + constant VENDORID : std_logic_vector(VENDORID_WIDTH-1 downto 0) := VENDORID_UNKNOWN; + constant GUIDPREFIX : GUIDPREFIX_TYPE; -- Deferred to Package Body + type ENTITYID_TYPE is array (0 to NUM_ENDPOINTS-1) of std_logic_vector(ENTITYID_WIDTH-1 downto 0); + constant ENTITYID : ENTITYID_TYPE; -- Deferred to Package Body + constant DOMAIN_ID : std_logic_vector(DOMAIN_ID_WIDTH-1 downto 0) := std_logic_vector(to_unsigned(USER_DOMAIN_ID, DOMAIN_ID_WIDTH)); + + -- Smallest Writer Endpoint Lease Duration + constant MIN_ENDPOINT_LEASE_DURATION : DURATION_TYPE; -- Deferred to package Body + + -- (see DDSI-RTPS 2.3 Section 9.6.1) + -- PB + DG * domain_id + d0 + constant META_IPv4_MULTICAST_PORT: std_logic_vector(UDP_PORT_WIDTH-1 downto 0) := std_logic_vector(to_unsigned(PORT_CONFIG_PB + PORT_CONFIG_D0 + PORT_CONFIG_DG*USER_DOMAIN_ID, UDP_PORT_WIDTH)); + -- (see DDSI-RTPS 2.3 Section 9.6.1) + -- PB + DG * domainId + d1 + PG * participant_id + -- participant_id=0 + constant META_IPv4_UNICAST_PORT : std_logic_vector(UDP_PORT_WIDTH-1 downto 0) := std_logic_vector(to_unsigned(PORT_CONFIG_PB + PORT_CONFIG_D1 + PORT_CONFIG_DG*USER_DOMAIN_ID, UDP_PORT_WIDTH)); + -- (see DDSI-RTPS 2.3 Section 9.6.1) + -- PB + DG * domainId + d2 + constant USER_IPv4_MULTICAST_PORT: std_logic_vector(UDP_PORT_WIDTH-1 downto 0) := std_logic_vector(to_unsigned(PORT_CONFIG_PB + PORT_CONFIG_D2 + PORT_CONFIG_DG*USER_DOMAIN_ID, UDP_PORT_WIDTH)); + -- (see DDSI-RTPS 2.3 Section 9.6.1) + -- PB + DG * domainId + d3 + PG * participant_id + -- participant_id=0 + constant USER_IPv4_UNICAST_PORT : std_logic_vector(UDP_PORT_WIDTH-1 downto 0) := std_logic_vector(to_unsigned(PORT_CONFIG_PB + PORT_CONFIG_D3 + PORT_CONFIG_DG*USER_DOMAIN_ID, UDP_PORT_WIDTH)); + + -- 4-Byte Word Size of a Participant Entry in Memory + constant PARTICIPANT_FRAME_SIZE : natural := 23; + -- 4-Byte Word Size of Endpoint Bitmask in Memory + constant ENDPOINT_BITMASK_SIZE : natural := round_div(NUM_ENDPOINTS, 32); + type ENDPOINT_BITMASK_ARRAY_TYPE is array (0 to ENDPOINT_BITMASK_SIZE-1) of std_logic_vector(0 to WORD_WIDTH-1); + -- 4-Byte Word Size of a Endpoint Entry in Memory + constant ENDPOINT_FRAME_SIZE : natural := 4 + ENDPOINT_BITMASK_SIZE; + -- Built-in Endpoint Memory Buffer 4-Byte Word Size + constant BUILTIN_BUFFER_SIZE : natural := MAX_REMOTE_PARTICIPANTS*PARTICIPANT_FRAME_SIZE; + + -- ENDPOINT FRAME OPCODES + constant ENDPOINT_MATCH_OPCODE_WIDTH: natural := 32; + constant OPCODE_MATCH : std_logic_vector(ENDPOINT_MATCH_OPCODE_WIDTH-1 downto 0) := x"55000000"; + constant OPCODE_UNMATCH : std_logic_vector(ENDPOINT_MATCH_OPCODE_WIDTH-1 downto 0) := x"55000001"; + constant OPCODE_LIVELINESS_UPDATE : std_logic_vector(ENDPOINT_MATCH_OPCODE_WIDTH-1 downto 0) := x"55000002"; + + + -- Marks the Reader Endpoint in the Endpoint Array + constant ENDPOINT_READERS : std_logic_vector(0 to NUM_ENDPOINTS-1) := (0 to NUM_READERS-1 => '1', others => '0'); + + type WORD_ARRAY_TYPE is array (natural range <>) of std_logic_vector(WORD_WIDTH-1 downto 0); + type OUTPUT_DATA_TYPE is record + -- Limit DATA to MAX UDPv4 Payload Size - RTPS Header (65487 Bytes) + data : WORD_ARRAY_TYPE(0 to 16371); + length : natural; + end record; + constant READER_ENDPOINT_DATA : OUTPUT_DATA_TYPE; --Deferred to package body + constant WRITER_ENDPOINT_DATA : OUTPUT_DATA_TYPE; --Deferred to package body + constant PARTICIPANT_DATA : OUTPUT_DATA_TYPE; --Deferred to package body + + type STRING_WORD_ARRAY_TYPE is array (0 to (256/(WORD_WIDTH/8))-1) of std_logic_vector(WORD_WIDTH-1 downto 0); + type ENDPOINT_STRING_TYPE is array (0 to NUM_ENDPOINTS-1) of STRING_WORD_ARRAY_TYPE; + constant ENDPOINT_TOPIC : ENDPOINT_STRING_TYPE; --Deferred to package body + constant ENDPOINT_TYPE : ENDPOINT_STRING_TYPE; --Deferred to package body + constant DOMAIN_TAG : STRING_WORD_ARRAY_TYPE; -- Deferred to package body + + -- Swap "data" to Big Endian representation. + function big_endian_swap(is_little_endian : std_logic; data : std_logic_vector) return std_logic_vector; + function big_endian_swap(is_little_endian : std_logic; data : unsigned) return unsigned; + +end package; + +package body rtps_config_package is + + procedure assertions is + begin + assert (NUM_ENDPOINTS = (NUM_READERS+NUM_WRITERS)) severity failure; + + assert (ENDPOINT_WITH_KEY'length = NUM_ENDPOINTS) report "Endpoint arrays have to be NUM_ENDPOINTS long" severity failure; + assert (ENDPOINT_TOPIC_STRING'length = NUM_ENDPOINTS) report "Endpoint arrays have to be NUM_ENDPOINTS long" severity failure; + assert (ENDPOINT_TYPE_STRING'length = NUM_ENDPOINTS) report "Endpoint arrays have to be NUM_ENDPOINTS long" severity failure; + assert (ENDPOINT_HEARTBEAT_PERIOD'length = NUM_ENDPOINTS) report "Endpoint arrays have to be NUM_ENDPOINTS long" severity failure; + assert (ENDPOINT_HEARTBEAT_RESPONSE_DELAY'length = NUM_ENDPOINTS) report "Endpoint arrays have to be NUM_ENDPOINTS long" severity failure; + assert (ENDPOINT_HEARTBEAT_SUPPRESSION_DELAY'length = NUM_ENDPOINTS) report "Endpoint arrays have to be NUM_ENDPOINTS long" severity failure; + assert (ENDPOINT_ACKNACK_RESPONSE_DELAY'length = NUM_ENDPOINTS) report "Endpoint arrays have to be NUM_ENDPOINTS long" severity failure; + assert (ENDPOINT_ACKNACK_SUPPRESSION_DELAY'length = NUM_ENDPOINTS) report "Endpoint arrays have to be NUM_ENDPOINTS long" severity failure; + assert (ENDPOINT_DURABILITY_QOS'length = NUM_ENDPOINTS) report "Endpoint arrays have to be NUM_ENDPOINTS long" severity failure; + assert (ENDPOINT_DURABILITY_SERVICE_CLEANUP_DELAY'length = NUM_ENDPOINTS) report "Endpoint arrays have to be NUM_ENDPOINTS long" severity failure; + assert (ENDPOINT_DURABILITY_SERVICE_HISTORY'length = NUM_ENDPOINTS) report "Endpoint arrays have to be NUM_ENDPOINTS long" severity failure; + assert (ENDPOINT_DURABILITY_SERVICE_HISTORY_DEPTH'length = NUM_ENDPOINTS) report "Endpoint arrays have to be NUM_ENDPOINTS long" severity failure; + assert (ENDPOINT_DURABILITY_SERVICE_MAX_SAMPLES'length = NUM_ENDPOINTS) report "Endpoint arrays have to be NUM_ENDPOINTS long" severity failure; + assert (ENDPOINT_DURABILITY_SERVICE_MAX_INSTANCES'length = NUM_ENDPOINTS) report "Endpoint arrays have to be NUM_ENDPOINTS long" severity failure; + assert (ENDPOINT_DURABILITY_SERVICE_MAX_SAMPLES_PER_INSTANCE'length = NUM_ENDPOINTS) report "Endpoint arrays have to be NUM_ENDPOINTS long" severity failure; + assert (ENDPOINT_PRESENTATION_QOS'length = NUM_ENDPOINTS) report "Endpoint arrays have to be NUM_ENDPOINTS long" severity failure; + assert (ENDPOINT_COHERENT_ACCESS'length = NUM_ENDPOINTS) report "Endpoint arrays have to be NUM_ENDPOINTS long" severity failure; + assert (ENDPOINT_ORDERED_ACCESS'length = NUM_ENDPOINTS) report "Endpoint arrays have to be NUM_ENDPOINTS long" severity failure; + assert (ENDPOINT_DEADLINE_QOS'length = NUM_ENDPOINTS) report "Endpoint arrays have to be NUM_ENDPOINTS long" severity failure; + assert (ENDPOINT_LATENCY_BUDGET_QOS'length = NUM_ENDPOINTS) report "Endpoint arrays have to be NUM_ENDPOINTS long" severity failure; + assert (ENDPOINT_OWNERSHIP_QOS'length = NUM_ENDPOINTS) report "Endpoint arrays have to be NUM_ENDPOINTS long" severity failure; + assert (ENDPOINT_OWNERSHIP_STRENGTH_QOS'length = NUM_ENDPOINTS) report "Endpoint arrays have to be NUM_ENDPOINTS long" severity failure; + assert (ENDPOINT_LIVELINESS_QOS'length = NUM_ENDPOINTS) report "Endpoint arrays have to be NUM_ENDPOINTS long" severity failure; + assert (ENDPOINT_LEASE_DURATION'length = NUM_ENDPOINTS) report "Endpoint arrays have to be NUM_ENDPOINTS long" severity failure; + assert (ENDPOINT_TIME_BASED_FILTER_QOS'length = NUM_ENDPOINTS) report "Endpoint arrays have to be NUM_ENDPOINTS long" severity failure; + assert (ENDPOINT_RELIABILITY_QOS'length = NUM_ENDPOINTS) report "Endpoint arrays have to be NUM_ENDPOINTS long" severity failure; + assert (ENDPOINT_MAX_BLOCKING_TIME'length = NUM_ENDPOINTS) report "Endpoint arrays have to be NUM_ENDPOINTS long" severity failure; + assert (ENDPOINT_TRANSPORT_PRIORITY_QOS'length = NUM_ENDPOINTS) report "Endpoint arrays have to be NUM_ENDPOINTS long" severity failure; + assert (ENDPOINT_LIFESPAN_QOS'length = NUM_ENDPOINTS) report "Endpoint arrays have to be NUM_ENDPOINTS long" severity failure; + assert (ENDPOINT_DESTINATION_ORDER_QOS'length = NUM_ENDPOINTS) report "Endpoint arrays have to be NUM_ENDPOINTS long" severity failure; + assert (ENDPOINT_HISTORY_QOS'length = NUM_ENDPOINTS) report "Endpoint arrays have to be NUM_ENDPOINTS long" severity failure; + assert (ENDPOINT_HISTORY_DEPTH'length = NUM_ENDPOINTS) report "Endpoint arrays have to be NUM_ENDPOINTS long" severity failure; + assert (ENDPOINT_MAX_SAMPLES'length = NUM_ENDPOINTS) report "Endpoint arrays have to be NUM_ENDPOINTS long" severity failure; + assert (ENDPOINT_MAX_INSTANCES'length = NUM_ENDPOINTS) report "Endpoint arrays have to be NUM_ENDPOINTS long" severity failure; + assert (ENDPOINT_MAX_SAMPLES_PER_INSTANCE'length = NUM_ENDPOINTS) report "Endpoint arrays have to be NUM_ENDPOINTS long" severity failure; + assert (ENDPOINT_AUTODISPOSE_UNREGISTERED_INSTANCES'length = NUM_ENDPOINTS) report "Endpoint arrays have to be NUM_ENDPOINTS long" severity failure; + assert (ENDPOINT_AUTOPURGE_NOWRITER_SAMPLES_DELAY'length = NUM_ENDPOINTS) report "Endpoint arrays have to be NUM_ENDPOINTS long" severity failure; + assert (ENDPOINT_AUTOPURGE_DISPOSED_SAMPLES_DELAY'length = NUM_ENDPOINTS) report "Endpoint arrays have to be NUM_ENDPOINTS long" severity failure; + + assert (PARTICIPANT_ANNOUNCEMENT_PERIOD+DURATION_DELTA <= PARTICIPANT_LEASE_DURATION) report "Participant Announcement Period has to be less than the Participant Lease Duration" severity failure; + + for i in 0 to NUM_ENDPOINTS-1 loop + assert (unsigned(ENDPOINT_DURABILITY_QOS(i)) < unsigned(TRANSIENT_DURABILITY_QOS)) report "TRANSIENT and PERSISTENT Durability QoS not supported" severity failure; + assert (ENDPOINT_PRESENTATION_QOS(i) /= GROUP_PRESENTATION_QOS) report "GROUP Presentation QoS not supported" severity failure; + assert (ENDPOINT_DEADLINE_QOS(i) >= ENDPOINT_TIME_BASED_FILTER_QOS(i)) report "DEADLINE Qos cannot be less than TIME_BASED_FILTER QoS" severity failure; + assert (ENDPOINT_OWNERSHIP_QOS(i) = SHARED_OWNERSHIP_QOS) report "Only SHARED Ownership QoS supported" severity failure; + assert (unsigned(ENDPOINT_MAX_SAMPLES(i)) >= unsigned(ENDPOINT_MAX_SAMPLES_PER_INSTANCE(i))) report "MAX_SAMPLES cannot be less than MAX_SAMPLES_PER_INSTANCE in Resource Limits QoS" severity failure; + end loop; + end procedure; + + function booelan_to_std_logic(input : boolean) return std_logic is + variable ret : std_logic := '0'; + begin + ret := '0'; + if (input = TRUE) then + ret := '1'; + end if; + return ret; + end function; + + function gen_entyid return ENTITYID_TYPE is + variable ret : ENTITYID_TYPE; + begin + ret := (others => (others => '0')); + for i in 0 to ret'length-1 loop + -- (see DDSI-RTPS 2.3 Section 9.3.1.2) + -- Entity Kind Mapping + ret(i)(7 downto 6) := USER_DEFINED_ENTITY; + if (i <= NUM_READERS-1) then + if (ENDPOINT_WITH_KEY(i)) then + ret(i)(5 downto 0) := READER_WITH_KEY; + else + ret(i)(5 downto 0) := READER_NO_KEY; + end if; + else + if (ENDPOINT_WITH_KEY(i)) then + ret(i)(5 downto 0) := WRITER_WITH_KEY; + else + ret(i)(5 downto 0) := WRITER_NO_KEY; + end if; + end if; + -- ID Mapping + ret(i)(ENTITYID_WIDTH-1 downto 8) := std_logic_vector(to_unsigned(i,ENTITYID_WIDTH-8)); + end loop; + return ret; + end function; + + constant ENTITYID : ENTITYID_TYPE := gen_entyid; + + function gen_guidprefix return GUIDPREFIX_TYPE is + variable tmp : std_logic_vector(GUIDPREFIX_WIDTH-1 downto 0) := (others => '0'); + variable ret : GUIDPREFIX_TYPE := (others => (others => '0')); + begin + tmp := (others => '0'); + ret := (others => (others => '0')); + -- First two bytes have to be Vendor ID (see DDSI-RTPS 2.3 Section 9.3.1.5) + tmp(GUIDPREFIX_WIDTH-1 downto GUIDPREFIX_WIDTH-VENDORID_WIDTH) := VENDORID; + -- Next we insert the MAC address for uniqueness + tmp(GUIDPREFIX_WIDTH-VENDORID_WIDTH-1 downto GUIDPREFIX_WIDTH-VENDORID_WIDTH-48) := MAC_ADDRESS; + -- Next we insert the Domain ID + tmp(DOMAIN_ID_WIDTH-1 downto 0) := DOMAIN_ID; + + -- Convert to return type + for i in 0 to ret'length-1 loop + ret(i) := tmp(GUIDPREFIX_WIDTH-(i*ret(i)'length)-1 downto GUIDPREFIX_WIDTH-(i*ret(i)'length)-ret(i)'length); + end loop; + return ret; + end function; + + constant GUIDPREFIX : GUIDPREFIX_TYPE := gen_guidprefix; + + function find_min_lease_duration return DURATION_TYPE is + variable ret : DURATION_TYPE := (others => (others => '0')); + begin + ret := DURATION_INFINITE; + -- Sanity Check + if (NUM_WRITERS = 0) then + return ret; + end if; + + -- Iterate through writers + for i in NUM_READERS to NUM_ENDPOINTS-1 loop + -- Do not consider "MANUAL_BY_TOPIC" Liveliness + if (ENDPOINT_LIVELINESS_QOS(i) /= MANUAL_BY_TOPIC_LIVELINESS_QOS) then + -- Find Minimum Lease Duration + if (ENDPOINT_LEASE_DURATION(i) < ret) then + ret := ENDPOINT_LEASE_DURATION(i); + end if; + end if; + end loop; + return ret; + end function; + + constant MIN_ENDPOINT_LEASE_DURATION : DURATION_TYPE := find_min_lease_duration; + + function convert_string (str : string(1 to 256)) return STRING_WORD_ARRAY_TYPE is + variable ret : STRING_WORD_ARRAY_TYPE := (others => (others => '0')); + begin + ret := (others => (others => '0')); + for i in 0 to ret'length-1 loop + ret(i) := std_logic_vector(to_unsigned(character'POS(str((i*4)+1)), 8)) & std_logic_vector(to_unsigned(character'POS(str((i*4)+2)), 8)) & std_logic_vector(to_unsigned(character'POS(str((i*4)+3)), 8)) & std_logic_vector(to_unsigned(character'POS(str((i*4)+4)), 8)); + end loop; + return ret; + end function; + + function convert_endpoint_string (string_array : USER_STRING_ARRAY_TYPE) return ENDPOINT_STRING_TYPE is + variable ret : ENDPOINT_STRING_TYPE := (others => (others => (others => '0'))); + begin + ret := (others => (others => (others => '0'))); + for i in 0 to ret'length-1 loop + ret(i) := convert_string(string_array(i)); + end loop; + return ret; + end function; + + constant ENDPOINT_TOPIC : ENDPOINT_STRING_TYPE := convert_endpoint_string(ENDPOINT_TOPIC_STRING); + constant ENDPOINT_TYPE : ENDPOINT_STRING_TYPE := convert_endpoint_string(ENDPOINT_TYPE_STRING); + constant DOMAIN_TAG : STRING_WORD_ARRAY_TYPE := convert_string(USER_DOMAIN_TAG); + + function string_len (str : STRING_WORD_ARRAY_TYPE) return natural is + variable ret : natural := 0; + begin + ret := 0; + for i in 0 to str'length-1 loop + for j in 0 to (str(i)'length/8)-1 loop + -- Count Bytes + ret := ret + 1; + -- Exit on first NULL byte (NULL Byte included in count) + if (str(i)(str(i)'length-j*8-1 downto str(i)'length-j*8-8) = (7 downto 0 => '0')) then + exit; + end if; + end loop; + end loop; + return ret; + end function; + + function gen_reader_endpoint_data return OUTPUT_DATA_TYPE is + variable ret : OUTPUT_DATA_TYPE := (data => (others => (others => '0')), length => 0); + variable ind : natural := 0; + variable len : natural := 0; + variable tmp : natural := 0; + begin + ret.data := (others => (others => '0')); + ret.length := 0; + -- Sanity Check + if (NUM_READERS = 0) then + return ret; + end if; + len := 0; + ind := 0; + + -- RTPS Submessages + -- One DATA Submessage for each Reader + for i in 0 to NUM_READERS-1 loop + -- RTPS Submessage Header + ret.data(ind) := SID_DATA & "00000100" & x"0000"; + -- DATA Header (extraFlags, octetsToInlineQoS) + len := len + 1; + ret.data(ind+len) := x"0000" & std_logic_vector(to_unsigned(16, 16)); + -- DATA Header (Reader Entity ID) + len := len + 1; + ret.data(ind+len) := ENTITYID_SEDP_BUILTIN_SUBSCRIPTIONS_DETECTOR; + -- DATA Header (Writer Entity ID) + len := len + 1; + ret.data(ind+len) := ENTITYID_SEDP_BUILTIN_SUBSCRIPTIONS_ANNOUNCER; + -- DATA Header (Sequence Number) + len := len + 1; + ret.data(ind+len) := (others => '0'); + -- DATA Header (Sequence Number) + len := len + 1; + ret.data(ind+len) := std_logic_vector(to_unsigned(i+1, ret.data(0)'length)); + -- Serialized Payload Header + len := len + 1; + ret.data(ind+len) := PL_CDR_BE & x"0000"; + -- Serialized Payload BEGIN + -- GUID + len := len + 1; + ret.data(ind+len):= PID_ENDPOINT_GUID & std_logic_vector(to_unsigned(16, 16)); + len := len + 1; + ret.data(ind+len) := GUIDPREFIX(0); + len := len + 1; + ret.data(ind+len) := GUIDPREFIX(1); + len := len + 1; + ret.data(ind+len) := GUIDPREFIX(2); + len := len + 1; + ret.data(ind+len) := ENTITYID(i); + -- EXPECTS INLINE QOS (Only relevant for Reader endpoints) + len := len + 1; + ret.data(ind+len) := PID_EXPECTS_INLINE_QOS & std_logic_vector(to_unsigned(4, 16)); + len := len + 1; + ret.data(ind+len) := (24 => '1', others => '0'); + -- TOPIC NAME + tmp := string_len(ENDPOINT_TOPIC(i)); + len := len + 1; + ret.data(ind+len) := PID_TOPIC_NAME & std_logic_vector(to_unsigned((round_div(tmp,4)+1)*4, 16)); + len := len + 1; + ret.data(ind+len) := std_logic_vector(to_unsigned(tmp, 32)); + for j in 0 to round_div(tmp,4)-1 loop + len := len + 1; + ret.data(ind+len) := ENDPOINT_TOPIC(i)(j); + end loop; + -- TYPE NAME + tmp := string_len(ENDPOINT_TYPE(i)); + len := len + 1; + ret.data(ind+len) := PID_TYPE_NAME & std_logic_vector(to_unsigned((round_div(tmp,4)+1)*4, 16)); + len := len + 1; + ret.data(ind+len) := std_logic_vector(to_unsigned(tmp, 32)); + for j in 0 to round_div(tmp,4)-1 loop + len := len + 1; + ret.data(ind+len) := ENDPOINT_TYPE(i)(j); + end loop; + -- DURABILITY + if (ENDPOINT_DURABILITY_QOS(i) /= DEFAULT_DURABILITY_QOS) then + len := len + 1; + ret.data(ind+len) := PID_DURABILITY & std_logic_vector(to_unsigned(4, 16)); + len := len + 1; + ret.data(ind+len) := ENDPOINT_DURABILITY_QOS(i); + end if; + -- DEADLINE + if (ENDPOINT_DEADLINE_QOS(i) /= DEFAULT_DEADLINE_QOS) then + len := len + 1; + ret.data(ind+len) := PID_DEADLINE & std_logic_vector(to_unsigned(8, 16)); + len := len + 1; + ret.data(ind+len) := std_logic_vector(ENDPOINT_DEADLINE_QOS(i)(0)); + len := len + 1; + ret.data(ind+len) := std_logic_vector(ENDPOINT_DEADLINE_QOS(i)(1)); + end if; + -- LIVELINESS + if (ENDPOINT_LIVELINESS_QOS(i) /= DEFAULT_LIVELINESS_QOS or ENDPOINT_LEASE_DURATION(i) /= DEFAULT_LEASE_DURATION) then + len := len + 1; + ret.data(ind+len) := PID_LIVELINESS & std_logic_vector(to_unsigned(12, 16)); + len := len + 1; + ret.data(ind+len) := ENDPOINT_LIVELINESS_QOS(i); + len := len + 1; + ret.data(ind+len) := std_logic_vector(ENDPOINT_LEASE_DURATION(i)(0)); + len := len + 1; + ret.data(ind+len) := std_logic_vector(ENDPOINT_LEASE_DURATION(i)(1)); + end if; + -- RELIABILITY + if (ENDPOINT_RELIABILITY_QOS(i) /= DEFAULT_RELIABILTY_QOS or ENDPOINT_MAX_BLOCKING_TIME(i) /= DEFAULT_MAX_BLOCKING_TIME) then + len := len + 1; + ret.data(ind+len) := PID_RELIABILITY & std_logic_vector(to_unsigned(12, 16)); + len := len + 1; + ret.data(ind+len) := ENDPOINT_RELIABILITY_QOS(i); + len := len + 1; + ret.data(ind+len) := std_logic_vector(ENDPOINT_MAX_BLOCKING_TIME(i)(0)); + len := len + 1; + ret.data(ind+len) := std_logic_vector(ENDPOINT_MAX_BLOCKING_TIME(i)(1)); + end if; + -- DESTINATION ORDER + if (ENDPOINT_DESTINATION_ORDER_QOS(i) /= DEFAULT_DESTINATION_ORDER_QOS) then + len := len + 1; + ret.data(ind+len) := PID_DESTINATION_ORDER & std_logic_vector(to_unsigned(4, 16)); + len := len + 1; + ret.data(ind+len) := ENDPOINT_DESTINATION_ORDER_QOS(i); + end if; + -- PRESENTATION + if (ENDPOINT_PRESENTATION_QOS(i) /= DEFAULT_PRESENTATION_QOS or ENDPOINT_COHERENT_ACCESS(i) /= DEFAULT_COHERENT_ACCESS or ENDPOINT_ORDERED_ACCESS(i) /= DEFAULT_ORDERED_ACCESS) then + len := len + 1; + ret.data(ind+len) := PID_PRESENTATION & std_logic_vector(to_unsigned(8, 16)); + len := len + 1; + ret.data(ind+len) := ENDPOINT_PRESENTATION_QOS(i); + len := len + 1; + ret.data(ind+len) := (24 => booelan_to_std_logic(ENDPOINT_COHERENT_ACCESS(i)), 16 => booelan_to_std_logic(ENDPOINT_ORDERED_ACCESS(i)), others => '0'); + end if; + -- SENTINEL + len := len + 1; + ret.data(ind+len) := PID_SENTINEL & std_logic_vector(to_unsigned(0, 16)); + -- Fix Submessage Length + ret.data(ind)(15 downto 0) := std_logic_vector(to_unsigned(len*4, 16)); + -- Reset Pointers + ind := ind + len + 1; + len := 0; + end loop; + -- Store Total Length + ret.length := ind; + return ret; + end function; + + constant READER_ENDPOINT_DATA : OUTPUT_DATA_TYPE := gen_reader_endpoint_data; + + function gen_writer_endpoint_data return OUTPUT_DATA_TYPE is + variable ret : OUTPUT_DATA_TYPE := (data => (others => (others => '0')), length => 0); + variable ind : natural := 0; + variable len : natural := 0; + variable tmp : natural := 0; + begin + ret.data := (others => (others => '0')); + ret.length := 0; + -- Sanity Check + if (NUM_WRITERS = 0) then + return ret; + end if; + len := 0; + ind := 0; + + -- RTPS Submessages + -- One DATA Submessage for each Writer Endpoint + for i in NUM_READERS to NUM_ENDPOINTS-1 loop + -- RTPS Submessage Header + ret.data(ind) := SID_DATA & "00000100" & x"0000"; + -- DATA Header (extraFlags, octetsToInlineQoS) + len := len + 1; + ret.data(ind+len) := x"0000" & std_logic_vector(to_unsigned(16, 16)); + -- DATA Header (Reader Entity ID) + len := len + 1; + ret.data(ind+len) := ENTITYID_SEDP_BUILTIN_PUBLICATIONS_DETECTOR; + -- DATA Header (Writer Entity ID) + len := len + 1; + ret.data(ind+len) := ENTITYID_SEDP_BUILTIN_PUBLICATIONS_ANNOUNCER; + -- DATA Header (Sequence Number) + len := len + 1; + ret.data(ind+len) := (others => '0'); + -- DATA Header (Sequence Number) + len := len + 1; + ret.data(ind+len) := std_logic_vector(to_unsigned(i-NUM_READERS+1, ret.data'length(1))); + -- Serialized Payload Header + len := len + 1; + ret.data(ind+len) := PL_CDR_BE & x"0000"; + -- Serialized Payload BEGIN + -- GUID + len := len + 1; + ret.data(ind+len):= PID_ENDPOINT_GUID & std_logic_vector(to_unsigned(16, 16)); + len := len + 1; + ret.data(ind+len) := GUIDPREFIX(0); + len := len + 1; + ret.data(ind+len) := GUIDPREFIX(1); + len := len + 1; + ret.data(ind+len) := GUIDPREFIX(2); + len := len + 1; + ret.data(ind+len) := ENTITYID(i); + -- TOPIC NAME + tmp := string_len(ENDPOINT_TOPIC(i)); + len := len + 1; + ret.data(ind+len) := PID_TOPIC_NAME & std_logic_vector(to_unsigned((round_div(tmp,4)+1)*4, 16)); + len := len + 1; + ret.data(ind+len) := std_logic_vector(to_unsigned(tmp, 32)); + for j in 0 to round_div(tmp,4)-1 loop + len := len + 1; + ret.data(ind+len) := ENDPOINT_TOPIC(i)(j); + end loop; + -- TYPE NAME + tmp := string_len(ENDPOINT_TYPE(i)); + len := len + 1; + ret.data(ind+len) := PID_TYPE_NAME & std_logic_vector(to_unsigned((round_div(tmp,4)+1)*4, 16)); + len := len + 1; + ret.data(ind+len) := std_logic_vector(to_unsigned(tmp, 32)); + for j in 0 to round_div(tmp,4)-1 loop + len := len + 1; + ret.data(ind+len) := ENDPOINT_TYPE(i)(j); + end loop; + -- DURABILITY + if (ENDPOINT_DURABILITY_QOS(i) /= DEFAULT_DURABILITY_QOS) then + len := len + 1; + ret.data(ind+len) := PID_DURABILITY & std_logic_vector(to_unsigned(4, 16)); + len := len + 1; + ret.data(ind+len) := ENDPOINT_DURABILITY_QOS(i); + end if; + -- DEADLINE + if (ENDPOINT_DEADLINE_QOS(i) /= DEFAULT_DEADLINE_QOS) then + len := len + 1; + ret.data(ind+len) := PID_DEADLINE & std_logic_vector(to_unsigned(8, 16)); + len := len + 1; + ret.data(ind+len) := std_logic_vector(ENDPOINT_DEADLINE_QOS(i)(0)); + len := len + 1; + ret.data(ind+len) := std_logic_vector(ENDPOINT_DEADLINE_QOS(i)(1)); + end if; + -- LIVELINESS + if (ENDPOINT_LIVELINESS_QOS(i) /= DEFAULT_LIVELINESS_QOS or ENDPOINT_LEASE_DURATION(i) /= DEFAULT_LEASE_DURATION) then + len := len + 1; + ret.data(ind+len) := PID_LIVELINESS & std_logic_vector(to_unsigned(12, 16)); + len := len + 1; + ret.data(ind+len) := ENDPOINT_LIVELINESS_QOS(i); + len := len + 1; + ret.data(ind+len) := std_logic_vector(ENDPOINT_LEASE_DURATION(i)(0)); + len := len + 1; + ret.data(ind+len) := std_logic_vector(ENDPOINT_LEASE_DURATION(i)(1)); + end if; + -- RELIABILITY + if (ENDPOINT_RELIABILITY_QOS(i) /= DEFAULT_RELIABILTY_QOS or ENDPOINT_MAX_BLOCKING_TIME(i) /= DEFAULT_MAX_BLOCKING_TIME) then + len := len + 1; + ret.data(ind+len) := PID_RELIABILITY & std_logic_vector(to_unsigned(12, 16)); + len := len + 1; + ret.data(ind+len) := ENDPOINT_RELIABILITY_QOS(i); + len := len + 1; + ret.data(ind+len) := std_logic_vector(ENDPOINT_MAX_BLOCKING_TIME(i)(0)); + len := len + 1; + ret.data(ind+len) := std_logic_vector(ENDPOINT_MAX_BLOCKING_TIME(i)(1)); + end if; + -- LIFESPAN + if (ENDPOINT_LIFESPAN_QOS(i) /= DEFAULT_LIFESPAN_QOS) then + len := len + 1; + ret.data(ind+len) := PID_LIFESPAN & std_logic_vector(to_unsigned(8, 16)); + len := len + 1; + ret.data(ind+len) := std_logic_vector(ENDPOINT_LIFESPAN_QOS(i)(0)); + len := len + 1; + ret.data(ind+len) := std_logic_vector(ENDPOINT_LIFESPAN_QOS(i)(1)); + end if; + -- DESTINATION ORDER + if (ENDPOINT_DESTINATION_ORDER_QOS(i) /= DEFAULT_DESTINATION_ORDER_QOS) then + len := len + 1; + ret.data(ind+len) := PID_DESTINATION_ORDER & std_logic_vector(to_unsigned(4, 16)); + len := len + 1; + ret.data(ind+len) := ENDPOINT_DESTINATION_ORDER_QOS(i); + end if; + -- PRESENTATION + if (ENDPOINT_PRESENTATION_QOS(i) /= DEFAULT_PRESENTATION_QOS or ENDPOINT_COHERENT_ACCESS(i) /= DEFAULT_COHERENT_ACCESS or ENDPOINT_ORDERED_ACCESS(i) /= DEFAULT_ORDERED_ACCESS) then + len := len + 1; + ret.data(ind+len) := PID_PRESENTATION & std_logic_vector(to_unsigned(8, 16)); + len := len + 1; + ret.data(ind+len) := ENDPOINT_PRESENTATION_QOS(i); + len := len + 1; + ret.data(ind+len) := (24 => booelan_to_std_logic(ENDPOINT_COHERENT_ACCESS(i)), 16 => booelan_to_std_logic(ENDPOINT_ORDERED_ACCESS(i)), others => '0'); + end if; + -- SENTINEL + len := len + 1; + ret.data(ind+len) := PID_SENTINEL & std_logic_vector(to_unsigned(0, 16)); + -- Fix Submessage Length + ret.data(ind)(15 downto 0) := std_logic_vector(to_unsigned(len*4, 16)); + -- Reset Pointers + ind := ind + len + 1; + len := 0; + end loop; + -- Store Total Length + ret.length := ind; + return ret; + end function; + + constant WRITER_ENDPOINT_DATA : OUTPUT_DATA_TYPE := gen_writer_endpoint_data; + + function gen_participant_data return OUTPUT_DATA_TYPE is + variable ret : OUTPUT_DATA_TYPE := (data => (others => (others => '0')), length => 0); + variable ind : natural := 0; + variable len : natural := 0; + variable tmp : natural := 0; + begin + ret.data := (others => (others => '0')); + ret.length := 0; + len := 0; + ind := 0; + + -- RTPS DATA SUBMESSAGE + -- RTPS Submessage Header + ret.data(ind) := SID_DATA & "00000100" & x"0000"; + -- DATA Header (extraFlags, octetsToInlineQoS) + len := len + 1; + ret.data(ind+len) := x"0000" & std_logic_vector(to_unsigned(16, 16)); + -- DATA Header (Reader Entity ID) + len := len + 1; + ret.data(ind+len) := ENTITYID_SPDP_BUILTIN_PARTICIPANT_DETECTOR; + -- DATA Header (Writer Entity ID) + len := len + 1; + ret.data(ind+len) := ENTITYID_SPDP_BUILTIN_PARTICIPANT_ANNOUNCER; + -- DATA Header (Sequence Number) + len := len + 1; + ret.data(ind+len) := (others => '0'); + -- DATA Header (Sequence Number) + len := len + 1; + ret.data(ind+len) := std_logic_vector(to_unsigned(1, ret.data(ind+len)'length)); + -- Serialized Payload Header + len := len + 1; + ret.data(ind+len) := PL_CDR_BE & x"0000"; + -- Serialized Payload BEGIN + -- GUID + len := len + 1; + ret.data(ind+len):= PID_PARTICIPANT_GUID & std_logic_vector(to_unsigned(16, 16)); + len := len + 1; + ret.data(ind+len) := GUIDPREFIX(0); + len := len + 1; + ret.data(ind+len) := GUIDPREFIX(1); + len := len + 1; + ret.data(ind+len) := GUIDPREFIX(2); + len := len + 1; + ret.data(ind+len) := ENTITYID_PARTICIPANT; + -- DOMAIN ID + len := len + 1; + ret.data(ind+len):= PID_DOMAIN_ID & std_logic_vector(to_unsigned(4, 16)); + len := len + 1; + ret.data(ind+len):= DOMAIN_ID; + -- DOMAIN TAG + -- TODO: Check if Guard works + if (USER_DOMAIN_TAG /= "") then + tmp := string_len(DOMAIN_TAG); + len := len + 1; + ret.data(ind+len) := PID_DOMAIN_TAG & std_logic_vector(to_unsigned((round_div(tmp,4)+1)*4, 16)); + len := len + 1; + ret.data(ind+len) := std_logic_vector(to_unsigned(tmp, 32)); + for j in 0 to round_div(tmp,4)-1 loop + len := len + 1; + ret.data(ind+len) := DOMAIN_TAG(j); + end loop; + end if; + -- PROTOCOL VERSION + len := len + 1; + ret.data(ind+len) := PID_PROTOCOL_VERSION & std_logic_vector(to_unsigned(4, 16)); + len := len + 1; + ret.data(ind+len) := (others => '0'); + ret.data(ind+len)(31 downto 16) := PROTOCOLVERSION_2_4; + -- VENDORID + len := len + 1; + ret.data(ind+len) := PID_VENDORID & std_logic_vector(to_unsigned(4, 16)); + len := len + 1; + ret.data(ind+len) := (others => '0'); + ret.data(ind+len)(31 downto 16) := VENDORID; + -- TODO: Expects inline QoS of Participant + -- METATRAFFIC UNICAST LOCATOR + len := len + 1; + ret.data(ind+len) := PID_METATRAFFIC_UNICAST_LOCATOR & std_logic_vector(to_unsigned(24, 16)); + len := len + 1; + ret.data(ind+len) := LOCATOR_KIND_UDPv4; + len := len + 1; + ret.data(ind+len) := (others => '0'); + ret.data(ind+len)(15 downto 0) := META_IPv4_UNICAST_PORT; + len := len + 1; + ret.data(ind+len) := (others => '0'); + len := len + 1; + ret.data(ind+len) := (others => '0'); + len := len + 1; + ret.data(ind+len) := (others => '0'); + len := len + 1; + ret.data(ind+len) := DEFAULT_IPv4_META_ADDRESS; + -- METATRAFFIC MULTICAST LOCATOR + len := len + 1; + ret.data(ind+len) := PID_METATRAFFIC_MULTICAST_LOCATOR & std_logic_vector(to_unsigned(24, 16)); + len := len + 1; + ret.data(ind+len) := LOCATOR_KIND_UDPv4; + len := len + 1; + ret.data(ind+len) := (others => '0'); + ret.data(ind+len)(15 downto 0) := META_IPv4_MULTICAST_PORT; + len := len + 1; + ret.data(ind+len) := (others => '0'); + len := len + 1; + ret.data(ind+len) := (others => '0'); + len := len + 1; + ret.data(ind+len) := (others => '0'); + len := len + 1; + ret.data(ind+len) := DEFAULT_IPv4_META_ADDRESS; + -- DEFAULT UNICAST LOCATOR + len := len + 1; + ret.data(ind+len) := PID_DEFAULT_UNICAST_LOCATOR & std_logic_vector(to_unsigned(24, 16)); + len := len + 1; + ret.data(ind+len) := LOCATOR_KIND_UDPv4; + len := len + 1; + ret.data(ind+len) := (others => '0'); + ret.data(ind+len)(15 downto 0) := USER_IPv4_UNICAST_PORT; + len := len + 1; + ret.data(ind+len) := (others => '0'); + len := len + 1; + ret.data(ind+len) := (others => '0'); + len := len + 1; + ret.data(ind+len) := (others => '0'); + len := len + 1; + ret.data(ind+len) := DEFAULT_IPv4_META_ADDRESS; + -- DEFAULT MULTICAST LOCATOR + len := len + 1; + ret.data(ind+len) := PID_METATRAFFIC_MULTICAST_LOCATOR & std_logic_vector(to_unsigned(24, 16)); + len := len + 1; + ret.data(ind+len) := LOCATOR_KIND_UDPv4; + len := len + 1; + ret.data(ind+len) := (others => '0'); + ret.data(ind+len)(15 downto 0) := USER_IPv4_MULTICAST_PORT; + len := len + 1; + ret.data(ind+len) := (others => '0'); + len := len + 1; + ret.data(ind+len) := (others => '0'); + len := len + 1; + ret.data(ind+len) := (others => '0'); + len := len + 1; + ret.data(ind+len) := DEFAULT_IPv4_META_ADDRESS; + -- LEASE DURATION + if (PARTICIPANT_LEASE_DURATION /= DEFAULT_PARTICIPANT_LEASE_DURATION) then + len := len + 1; + ret.data(ind+len) := PID_PARTICIPANT_LEASE_DURATION & std_logic_vector(to_unsigned(8, 16)); + len := len + 1; + ret.data(ind+len) := std_logic_vector(PARTICIPANT_LEASE_DURATION(0)); + len := len + 1; + ret.data(ind+len) := std_logic_vector(PARTICIPANT_LEASE_DURATION(1)); + end if; + -- AVAILABLE ENDPOINTS + len := len + 1; + ret.data(ind+len) := PID_BUILTIN_ENDPOINT_SET & std_logic_vector(to_unsigned(4, 16)); + len := len + 1; + ret.data(ind+len) := (DISC_BUILTIN_ENDPOINT_PARTICIPANT_ANNOUNCER => '1', DISC_BUILTIN_ENDPOINT_PARTICIPANT_DETECTOR => '1', BUILTIN_ENDPOINT_PARTICIPANT_MESSAGE_DATA_WRITER => '1', BUILTIN_ENDPOINT_PARTICIPANT_MESSAGE_DATA_READER => '1', others => '0'); + if (NUM_READERS > 0) then + ret.data(ind+len)(DISC_BUILTIN_ENDPOINT_PUBLICATIONS_DETECTOR) := '1'; + ret.data(ind+len)(DISC_BUILTIN_ENDPOINT_SUBSCRIPTIONS_ANNOUNCER):= '1'; + end if; + if (NUM_WRITERS > 0) then + ret.data(ind+len)(DISC_BUILTIN_ENDPOINT_PUBLICATIONS_ANNOUNCER) := '1'; + ret.data(ind+len)(DISC_BUILTIN_ENDPOINT_SUBSCRIPTIONS_DETECTOR) := '1'; + end if; + -- MANUAL LIVELINESS COUNT + len := len + 1; + ret.data(ind+len) := PID_PARTICIPANT_MANUAL_LIVELINESS_COUNT & std_logic_vector(to_unsigned(4, 16)); + len := len + 1; + ret.data(ind+len) := (others => '0'); + -- SENTINEL + len := len + 1; + ret.data(ind+len) := PID_SENTINEL & std_logic_vector(to_unsigned(0, 16)); + + -- Store Length + ret.length := ind + len + 1; + return ret; + end function; + + constant PARTICIPANT_DATA : OUTPUT_DATA_TYPE := gen_participant_data; + + -- Returns the 'data' argument either as is, or with reversed Byte order, depending on the + -- 'is_little_endian' argument. + function big_endian_swap(is_little_endian : std_logic; data : std_logic_vector) return std_logic_vector is + variable ret : std_logic_vector(data'range); + begin + -- Assert that Data Signal is Byte aligned + assert (data'length mod 8 = 0) severity failure; + -- Little Endian + if (is_little_endian = '1') then + -- Reverse byte Order + for i in 0 to (data'length/8)-1 loop + ret(i*8+8-1 downto i*8) := data(((data'length/8)-1-i)*8+8-1 downto ((data'length/8)-1-i)*8); + end loop; + -- Big Endian + else + ret := data; + end if; + return ret; + end function; + + -- Returns the 'data' argument either as is, or with reversed Byte order, depending on the + -- 'is_little_endian' argument. + function big_endian_swap(is_little_endian : std_logic; data : unsigned) return unsigned is + begin + return unsigned(big_endian_swap(is_little_endian, std_logic_vector(data))); + end function; + +end package body; diff --git a/src/rtps_handler.vhd b/src/rtps_handler.vhd index c4a4fde..87f55e9 100644 --- a/src/rtps_handler.vhd +++ b/src/rtps_handler.vhd @@ -4,6 +4,8 @@ use ieee.numeric_std.all; use work.math_pkg.all; use work.rtps_package.all; +use work.user_config.all; +use work.rtps_config_package.all; -- Checksum has to be checked before -- TODO: Change "endian-swap" to "big-endian" throughout @@ -14,13 +16,13 @@ entity rtps_handler is reset : in std_logic; -- Synchronous Reset empty : in std_logic; -- Input FIFO empty flag rd : out std_logic; -- Input FIFO read signal - data_in : in std_logic_vector(31 downto 0); -- Input FIFO data signal - builtin_output : out std_logic_vector(31 downto 0); -- Output FIFO (Built-In Endpoint) data signal + data_in : in std_logic_vector(WORD_WIDTH-1 downto 0); -- Input FIFO data signal + builtin_output : out std_logic_vector(WORD_WIDTH-1 downto 0); -- Output FIFO (Built-In Endpoint) data signal builtin_full : in std_logic; -- Output FIFO (Built-In Endpoint) full signal builtin_wr : out std_logic; -- Output FIFO (Built-In Endpoint) write signal - user_output : out std_logic_vector(31 downto 0); -- Output FIFO (User Endpoints) data signal - user_full : in std_logic_vector(0 to MAX_ENDPOINTS-1); -- Output FIFO (User Endpoints) full signal - user_wr : out std_logic_vector(0 to MAX_ENDPOINTS-1); -- Output FIFO (User Endpoints) write signal + user_output : out std_logic_vector(WORD_WIDTH-1 downto 0); -- Output FIFO (User Endpoints) data signal + user_full : in std_logic_vector(0 to NUM_ENDPOINTS-1); -- Output FIFO (User Endpoints) full signal + user_wr : out std_logic_vector(0 to NUM_ENDPOINTS-1); -- Output FIFO (User Endpoints) write signal last_word_out : out std_logic -- Output FIFO Last Word signal ); end entity; @@ -75,29 +77,29 @@ architecture arch of rtps_handler is -- Signal used to reset the word counter signal reset_read_cnt : std_logic; -- 4-Byte Word counter (Counts words read from input FIFO) - signal read_cnt : unsigned(13 downto 0) := (others => '0'); + signal read_cnt : unsigned(UDP_HEADER_LENGTH_WIDTH-3 downto 0) := (others => '0'); -- Total packet length (4-Byte Words) - signal packet_length, packet_length_next : unsigned(13 downto 0) := (others => '0'); + signal packet_length, packet_length_next : unsigned(UDP_HEADER_LENGTH_WIDTH-3 downto 0) := (others => '0'); -- End of Submessage from the beginning of the UDP Packet in Bytes - signal sub_end, sub_end_next : unsigned(15 downto 0) := (others => '0'); + signal sub_end, sub_end_next : unsigned(SUBMESSAGE_LENGTH_WIDTH-1 downto 0) := (others => '0'); -- End of DATA Submessage Sub-Header (Beginning of inlineQoS/Payload) from the beginning of the UDP Packet in Bytes - signal data_header_end, data_header_end_next : unsigned(15 downto 0) := (others => '0'); + signal data_header_end, data_header_end_next : unsigned(SUBMESSAGE_LENGTH_WIDTH-1 downto 0) := (others => '0'); -- Input Signal Latch. Used to read 4-Byte aligned from input (see align_prc) - signal align_sig, align_sig_next : std_logic_vector(23 downto 0) := (others => '0'); + signal align_sig, align_sig_next : std_logic_vector((3*BYTE_WIDTH)-1 downto 0) := (others => '0'); -- 4-Byte Aligned Input (see align_prc) - signal data_in_aligned : std_logic_vector(31 downto 0); + signal data_in_aligned : std_logic_vector(WORD_WIDTH-1 downto 0); -- 4-Byte Alignement offset (see align_prc) signal align_offset, align_offset_next : std_logic_vector(1 downto 0) := (others => '0'); -- 4-Byte Alignement offset latch signal offset_latch, offset_latch_next : std_logic_vector(1 downto 0) := (others => '0'); -- IPv4 Source Address latch - signal src_addr, src_addr_next : std_logic_vector(31 downto 0) := (others => '0'); + signal src_addr, src_addr_next : std_logic_vector(IPv4_ADDRESS_WIDTH-1 downto 0) := (others => '0'); -- UDP Source Port latch - signal src_port, src_port_next : std_logic_vector(15 downto 0) := (others => '0'); + signal src_port, src_port_next : std_logic_vector(UDP_PORT_WIDTH-1 downto 0) := (others => '0'); -- Denotes if processed Message is Metatraffic signal is_metatraffic, is_metatraffic_next : std_logic := '0'; -- RTPS Submessage Flag latch - signal flags, flags_next : std_logic_vector(7 downto 0) := (others => '0'); + signal flags, flags_next : std_logic_vector(SUBMESSAGE_FLAGS_WIDTH-1 downto 0) := (others => '0'); -- Reader Entity ID latch signal reader_entityid, reader_entityid_next : std_logic_vector(ENTITYID_WIDTH-1 downto 0) := (others => '0'); -- Writer Entity ID latch @@ -105,18 +107,18 @@ architecture arch of rtps_handler is -- Source GUID Prefix latch signal src_guidprefix, src_guidprefix_next : GUIDPREFIX_TYPE := (others => (others => '0')); -- Vector denoting the Destination User Endpoints of the Message - signal user_endpoint, user_endpoint_next : std_logic_vector(0 to MAX_ENDPOINTS-1) := (others => '0'); + signal user_endpoint, user_endpoint_next : std_logic_vector(0 to NUM_ENDPOINTS-1) := (others => '0'); -- Denotes if the Message is destined for the Built-in Endpoints signal builtin_endpoint, builtin_endpoint_next : std_logic := '0'; -- numLocator latch -- NOTE: Since Submessages are limited to 2^16 Bytes, we can limit this also to 16 bits - signal numlocators, numlocators_next : unsigned(15 downto 0) := (others => '0'); + signal numlocators, numlocators_next : unsigned(SUBMESSAGE_LENGTH_WIDTH-1 downto 0) := (others => '0'); -- Denotes if a suitable Locator has been found signal locator_match, locator_match_next : std_logic := '0'; -- Denotes if the Source of the Message is a Reader Endpoint signal src_is_reader, src_is_reader_next : std_logic := '0'; -- Intermediate Output Data Signal - signal output_sig : std_logic_vector(31 downto 0) := (others => '0'); + signal output_sig : std_logic_vector(WORD_WIDTH-1 downto 0) := (others => '0'); -- Intermediate Write Enable Signal signal wr_sig : std_logic := '0'; -- Submessage ID latch (Used as OPCODE by Endpoints) @@ -127,13 +129,13 @@ architecture arch of rtps_handler is -- TODO: Recheck range signal cnt, cnt_next : natural range 0 to 8 := 0; -- Input in Big Endian representation - signal data_in_swapped : std_logic_vector(31 downto 0) := (others => '0'); + signal data_in_swapped : std_logic_vector(WORD_WIDTH-1 downto 0) := (others => '0'); -- Sequence Number latch - signal seq_nr, seq_nr_next : DOUBLE_WORD_ARRAY := (others => (others => '0')); + signal seq_nr, seq_nr_next : SEQUENCE_NR_TYPE := (others => (others => '0')); -- Indicates the Destination IP Address signal ip_addr_type, ip_addr_type_next : IPv4_ADDRESS_TYPE := INVALID; -- Alias "substitution" - signal rtps_sub_length, rtps_sub_data_length : unsigned(15 downto 0) := (others => '0'); + signal rtps_sub_length, rtps_sub_data_length : unsigned(SUBMESSAGE_LENGTH_WIDTH-1 downto 0) := (others => '0'); --*****ALIAS DEFINATION***** -- UDP HEADER @@ -148,7 +150,7 @@ architecture arch of rtps_handler is alias rtps_sub_id : std_logic_vector(7 downto 0) is data_in(31 downto 24); alias rtps_sub_flags : std_logic_vector(7 downto 0) is data_in(23 downto 16); -- Apparently illegal alias expression - --alias rtps_sub_length : unsigned(15 downto 0) is unsigned(endian_swap(rtps_sub_flags(0), data_in(15 downto 0))); + --alias rtps_sub_length : unsigned(15 downto 0) is unsigned(big_endian_swap(rtps_sub_flags(0), data_in(15 downto 0))); -- RTPS SUBMESSAGE FLAGS alias rtps_sub_endianness : std_logic is flags(0); alias rtps_sub_multicast : std_logic is flags(1); @@ -158,7 +160,7 @@ architecture arch of rtps_handler is alias rtps_sub_key : std_logic is flags(3); -- RTPS DATA SUBMESSAGE HEADER -- Apparently illegal alias expression - --alias rtps_sub_data_length : unsigned(15 downto 0) is unsigned(endian_swap(rtps_sub_endianness, data_in(15 downto 0))); + --alias rtps_sub_data_length : unsigned(15 downto 0) is unsigned(big_endian_swap(rtps_sub_endianness, data_in(15 downto 0))); --*****FUNCTION DECLARATION***** @@ -177,10 +179,10 @@ architecture arch of rtps_handler is begin -- ALIAS SUBSTITUTION - rtps_sub_length <= unsigned(endian_swap(rtps_sub_flags(0), data_in(15 downto 0))); + rtps_sub_length <= unsigned(big_endian_swap(rtps_sub_flags(0), data_in(15 downto 0))); -- NOTE: While "rtps_sub_length" has to use the flag directly form the "data_in" signal to determine Endianness, here the -- "flags" signal is already valid (and thus also its aliases) - rtps_sub_data_length <= unsigned(endian_swap(rtps_sub_endianness, data_in(15 downto 0))); + rtps_sub_data_length <= unsigned(big_endian_swap(rtps_sub_endianness, data_in(15 downto 0))); rd <= rd_sig; @@ -265,7 +267,7 @@ begin -- SKIP_SUB Skip rest of Submessage -- SKIP_PACKET Skip rest of UDP Packet parse_prc: process(all) - variable tmp : std_logic_vector(0 to MAX_ENDPOINTS-1) := (others => '0'); + variable tmp : std_logic_vector(0 to NUM_ENDPOINTS-1) := (others => '0'); variable dest : std_logic_vector(ENTITYID_WIDTH-1 downto 0) := (others => '0'); begin --DEFAULT Registered @@ -717,7 +719,7 @@ begin -- We only store UDPv4 Locators if (locator_match = '1') then -- We only store valid Locators - if (data_in_swapped = (data_in_swapped'reverse_range => '0')) then + if (data_in_swapped(UDP_PORT_INVALID'range) = UDP_PORT_INVALID) then locator_match_next <= '0'; else src_port_next <= data_in_swapped(src_port_next'length-1 downto 0); @@ -735,7 +737,7 @@ begin -- Locator Address 4/4 (IPv4 Address) when 5 => -- We only store valid UDPv4 Locators - if (locator_match = '1' and data_in_swapped /= (data_in_swapped'reverse_range => '0')) then + if (locator_match = '1' and data_in_swapped /= IPv4_ADDRESS_INVALID) then src_addr_next <= data_in_swapped; -- Extract only first matching Locator and ignore the rest stage_next <= SKIP_SUB; @@ -758,7 +760,7 @@ begin -- IPv4 Address when 0 => -- Store only valid Locators - if (data_in_swapped = (data_in_swapped'reverse_range => '0')) then + if (data_in_swapped = IPv4_ADDRESS_INVALID) then locator_match_next <= '0'; else locator_match_next <= '1'; @@ -767,7 +769,7 @@ begin -- UDPv4 Port when 1 => -- Store only valid Locators - if (locator_match = '1' and data_in_swapped /= (data_in_swapped'reverse_range => '0')) then + if (locator_match = '1' and data_in_swapped(UDP_PORT_INVALID'range) /= UDP_PORT_INVALID) then src_port_next <= data_in_swapped(src_port_next'length-1 downto 0); stage_next <= SKIP_SUB; -- Parse Multicast if available diff --git a/src/rtps_package.vhd b/src/rtps_package.vhd index bd2aa9e..17d362a 100644 --- a/src/rtps_package.vhd +++ b/src/rtps_package.vhd @@ -1,169 +1,77 @@ library ieee; use ieee.std_logic_1164.all; use ieee.numeric_std.all; - -use work.math_pkg.all; - --- TODO: Convert ALL integers to natural, and remove all conversions (Arithmetics between natural and unsigned are directly supported) +use ieee.math_real.CEIL; package rtps_package is - --*****USER CONFIG***** - -- Unicast IPv4 Address used by all RTPS Entities [Default 192.168.0.80] - constant DEFAULT_IPv4_ADDRESS : std_logic_vector(31 downto 0) := x"C0A80080"; - -- Number of RTPS Writer Endpoints - constant NUM_WRITERS : natural := 0; - -- Number of RTPS Reader Endpoints - constant NUM_READERS : natural := 1; - ----------------------------------------------------------------------------------------------------- - -- *DO NOT MODIFY BEGIN* - constant MAX_ENDPOINTS : natural := NUM_READERS+NUM_WRITERS; - -- *DO NOT MODIFY END* - ----------------------------------------------------------------------------------------------------- - -- PB Value of Default Port Generation (see DDSI-RTPS 2.3 Section 9.6.1) - constant PORT_CONFIG_PB : natural := 7400; - -- DG Value of Default Port Generation (see DDSI-RTPS 2.3 Section 9.6.1) - constant PORT_CONFIG_DG : natural := 250; - -- PG Value of Default Port Generation (see DDSI-RTPS 2.3 Section 9.6.1) - constant PORT_CONFIG_PG : natural := 2; - -- D0 Value of Default Port Generation (see DDSI-RTPS 2.3 Section 9.6.1) - constant PORT_CONFIG_D0 : natural := 0; - -- D1 Value of Default Port Generation (see DDSI-RTPS 2.3 Section 9.6.1) - constant PORT_CONFIG_D1 : natural := 10; - -- D2 Value of Default Port Generation (see DDSI-RTPS 2.3 Section 9.6.1) - constant PORT_CONFIG_D2 : natural := 1; - -- D3 Value of Default Port Generation (see DDSI-RTPS 2.3 Section 9.6.1) - constant PORT_CONFIG_D3 : natural := 11; - -- MAC Address of underlying network stack (Used to generate GUIDs) - constant MAC_ADDRESS : std_logic_vector(47 downto 0) := x"97917E0BA8CF"; - -- Domain ID - constant USER_DOMAIN_ID : natural := 1; - -- Domain TAG - constant USER_DOMAIN_TAG : string(1 to 256) := (others => NUL); --"" - - ----------------------------------------------------------------------------------------------------- - -- *DO NOT MODIFY BEGIN* - type ENDPOINT_WITH_KEY_TYPE is array (0 to MAX_ENDPOINTS-1) of boolean; - type ENDPOINT_STRING_TYPE is array (0 to MAX_ENDPOINTS-1) of string(1 to 256); - type STRING_SLV_WORD_TYPE is array (0 to ((256*8)/32)-1) of std_logic_vector(31 downto 0); - type ENDPOINT_STRING_SLV_TYPE is array (0 to MAX_ENDPOINTS-1) of STRING_SLV_WORD_TYPE; - type QOS_TYPE is array (0 to MAX_ENDPOINTS-1) of std_logic_vector(31 downto 0); - type QOS_SLV_TYPE is array (0 to MAX_ENDPOINTS-1) of std_logic_vector(31 downto 0); - type DOUBLE_WORD_ARRAY is array (0 to 1) of unsigned(31 downto 0); - type ENDPOINT_DURATION_TYPE is array (0 to MAX_ENDPOINTS-1) of DOUBLE_WORD_ARRAY; - - constant DURATION_INFINITE : DOUBLE_WORD_ARRAY := (x"7fffffff", x"ffffffff"); - - -- DURABILITY KIND - constant VOLATILE_DURABILITY_QOS : std_logic_vector(31 downto 0) := std_logic_vector(to_unsigned(0,32)); - constant TRANSIENT_LOCAL_DURABILITY_QOS : std_logic_vector(31 downto 0) := std_logic_vector(to_unsigned(1,32)); - constant TRANSIENT_DURABILITY_QOS : std_logic_vector(31 downto 0) := std_logic_vector(to_unsigned(2,32)); - constant PERSISTENT_DURABILITY_QOS : std_logic_vector(31 downto 0) := std_logic_vector(to_unsigned(3,32)); - -- LIVELINESS KIND - constant AUTOMATIC_LIVELINESS_QOS : std_logic_vector(31 downto 0) := std_logic_vector(to_unsigned(0,32)); - constant MANUAL_BY_PARTICIPANT_LIVELINESS_QOS : std_logic_vector(31 downto 0) := std_logic_vector(to_unsigned(1,32)); - constant MANUAL_BY_TOPIC_LIVELINESS_QOS : std_logic_vector(31 downto 0) := std_logic_vector(to_unsigned(2,32)); - -- RELIABILITY KIND - constant BEST_EFFORT_RELIABILITY_QOS : std_logic_vector(31 downto 0) := std_logic_vector(to_unsigned(1,32)); - constant RELIABLE_RELIABILITY_QOS : std_logic_vector(31 downto 0) := std_logic_vector(to_unsigned(2,32)); - -- OWNERSHIP KIND - constant SHARED_OWNERSHIP_QOS : std_logic_vector(31 downto 0) := std_logic_vector(to_unsigned(0,32)); - constant EXCLUSIVE_OWNERSHIP_QOS : std_logic_vector(31 downto 0) := std_logic_vector(to_unsigned(1,32)); - -- DESTINATION ORDER KIND - constant BY_RECEPTION_TIMESTAMP_DESTINATIONORDER_QOS : std_logic_vector(31 downto 0) := std_logic_vector(to_unsigned(0,32)); - constant BY_SOURCE_TIMESTAMP_DESTINATIONORDER_QOS : std_logic_vector(31 downto 0) := std_logic_vector(to_unsigned(1,32)); - -- PRESENTATION KIND - constant INSTANCE_PRESENTATION_QOS : std_logic_vector(31 downto 0) := std_logic_vector(to_unsigned(0,32)); - constant TOPIC_PRESENTATION_QOS : std_logic_vector(31 downto 0) := std_logic_vector(to_unsigned(1,32)); - constant GROUP_PRESENTATION_QOS : std_logic_vector(31 downto 0) := std_logic_vector(to_unsigned(2,32)); - -- HISTORY KIND - constant KEEP_LAST_HISTORY_QOS : std_logic_vector(31 downto 0) := std_logic_vector(to_unsigned(0,32)); - constant KEEP_ALL_HISTORY_QOS : std_logic_vector(31 downto 0) := std_logic_vector(to_unsigned(1,32)); - -- TYPE CONSISTENCY KIND - constant DISALLOW_TYPE_COERCION : std_logic_vector(15 downto 0) := std_logic_vector(to_unsigned(0,16)); - constant ALLOW_TYPE_COERCION : std_logic_vector(15 downto 0) := std_logic_vector(to_unsigned(1,16)); - -- *DO NOT MODIFY END* - ----------------------------------------------------------------------------------------------------- - - --***RTPS ENDPOINTS*** - -- Array denoting if Endpoints use Keyed Topics - constant ENDPOINT_WITH_KEY : ENDPOINT_WITH_KEY_TYPE := (0 => FALSE); - -- Array mapping Topic Strings to Endpoints - -- NOTE: All strings have to be padded to 256 characters - constant ENDPOINT_TOPIC_STRING : ENDPOINT_STRING_TYPE := (0 => "Placeholder" & (12 to 256 => NUL)); - constant ENDPOINT_TOPIC : ENDPOINT_STRING_SLV_TYPE; -- Deferred to Package Body - constant ENDPOINT_TYPE_STRING : ENDPOINT_STRING_TYPE := (0 => "Placeholder" & (12 to 256 => NUL)); - constant ENDPOINT_TYPE : ENDPOINT_STRING_SLV_TYPE; -- Deferred to Package Body - constant ENDPOINT_DURABILITY : QOS_TYPE := (0 => VOLATILE_DURABILITY_QOS); - -- TODO: Make sure GROUP is not selected - constant ENDPOINT_PRESENTATION : QOS_TYPE := (0 => INSTANCE_PRESENTATION_QOS); - constant ENDPOINT_COHERENT_ACCESS : std_logic_vector(0 to MAX_ENDPOINTS-1) := (others => '0'); - constant ENDPOINT_ORDERED_ACCESS : std_logic_vector(0 to MAX_ENDPOINTS-1) := (others => '0'); - constant ENDPOINT_DEADLINE : ENDPOINT_DURATION_TYPE := (0 => DURATION_INFINITE); --TODO: Assert - constant ENDPOINT_LIVELINESS : QOS_TYPE := (0 => AUTOMATIC_LIVELINESS_QOS); - constant ENDPOINT_LEASE_DURATION : ENDPOINT_DURATION_TYPE := (0 => DURATION_INFINITE); --TODO: Assert - -- Only relevant for Readers - constant ENDPOINT_TIME_BASED_FILTER : ENDPOINT_DURATION_TYPE := (0 => (to_unsigned(0,32),to_unsigned(0,32))); --TODO: Assert - constant ENDPOINT_RELIABILITY : QOS_TYPE := (0 => RELIABLE_RELIABILITY_QOS); - constant ENDPOINT_MAX_BLOCKING_TIME : ENDPOINT_DURATION_TYPE := (0 => (to_unsigned(0,32),to_unsigned(429496730,32))); --ca 100ms - -- Only relevant for Writers - constant ENDPOINT_LIFESPAN : ENDPOINT_DURATION_TYPE := (0 => DURATION_INFINITE); - constant ENDPOINT_DESTINATION_ORDER : QOS_TYPE := (0 => BY_RECEPTION_TIMESTAMP_DESTINATIONORDER_QOS); - constant ENDPOINT_HISTORY : QOS_TYPE := (0 => KEEP_LAST_HISTORY_QOS); - constant ENDPOINT_DEPTH : QOS_SLV_TYPE := (0 => std_logic_vector(to_unsigned(1,32))); --TODO: Assert - constant ENDPOINT_MAX_SAMPLES : QOS_SLV_TYPE := (0 => std_logic_vector(to_unsigned(0,32))); --TODO: Assert - constant ENDPOINT_MAX_INSTANCES : QOS_SLV_TYPE := (0 => std_logic_vector(to_unsigned(0,32))); --TODO: Assert - constant ENDPOINT_MAX_SAMP_PER_INST : QOS_SLV_TYPE := (0 => std_logic_vector(to_unsigned(0,32))); --TODO: Assert - - constant ENDPOINT_HEARTBEAT_PERIOD : ENDPOINT_DURATION_TYPE := (0 => (to_unsigned(3,32),to_unsigned(0,32))); -- 3s - constant ENDPOINT_HEARTBEAT_RESPONSE_DELAY : ENDPOINT_DURATION_TYPE := (0 => (to_unsigned(0,32),to_unsigned(2147483648,32))); -- 500 ms - constant ENDPOINT_HEARTBEAT_SUPPRESSION_DELAY : ENDPOINT_DURATION_TYPE := (0 => (to_unsigned(0,32),to_unsigned(0,32))); - constant ENDPOINT_ACKNACK_RESPONSE_DELAY : ENDPOINT_DURATION_TYPE := (0 => (to_unsigned(0,32),to_unsigned(858993459,32))); -- 200 ms - constant ENDPOINT_ACKNACK_SUPPRESSION_DELAY : ENDPOINT_DURATION_TYPE := (0 => (to_unsigned(0,32),to_unsigned(0,32))); - - constant PARTICIPANT_HEARTBEAT_PERIOD : DOUBLE_WORD_ARRAY := (to_unsigned(3,32),to_unsigned(0,32)); -- 3s - constant PARTICIPANT_HEARTBEAT_RESPONSE_DELAY : DOUBLE_WORD_ARRAY := (to_unsigned(0,32),to_unsigned(2147483648,32)); -- 500 ms - constant PARTICIPANT_HEARTBEAT_SUPPRESSION_DELAY : DOUBLE_WORD_ARRAY := (to_unsigned(0,32),to_unsigned(0,32)); - constant PARTICIPANT_ACKNACK_RESPONSE_DELAY : DOUBLE_WORD_ARRAY := (to_unsigned(0,32),to_unsigned(858993459,32)); -- 200 ms - constant PARTICIPANT_ACKNACK_SUPPRESSION_DELAY : DOUBLE_WORD_ARRAY := (to_unsigned(0,32),to_unsigned(0,32)); - - constant DURATION_DELTA : DOUBLE_WORD_ARRAY := (to_unsigned(0,32),to_unsigned(429496730,32)); --100 ms - - constant DEFAULT_PARTICIPANT_LEASE_DURATION : DOUBLE_WORD_ARRAY := (to_unsigned(100,32),to_unsigned(0,32)); -- 100s - constant PARTICIPANT_ANNOUNCEMENT_PERIOD : DOUBLE_WORD_ARRAY := (to_unsigned(30,32),to_unsigned(0,32)); -- 30s - constant PARTICIPANT_LEASE_DURATION : DOUBLE_WORD_ARRAY := DEFAULT_PARTICIPANT_LEASE_DURATION; - constant MIN_ENDPOINT_LEASE_DURATION : DOUBLE_WORD_ARRAY; -- Deferred to package Body - - - -- NOTE: The buffer will not only store participants, but also endpoint data - -- Used to determine the size of the builtin endpoint buffer - constant MAX_REMOTE_PARTICIPANTS : natural := 50; - --*****DDSI-RTPS 2.3***** - - -- Default Multicast Ipv4 Address (239.255.0.1) - constant DEFAULT_IPv4_META_ADDRESS : std_logic_vector(31 downto 0) := x"EFFF0001"; - - constant GUIDPREFIX_WIDTH : natural := 96; - constant PROTOCOLVERSION_WIDTH : natural := 16; - constant VENDORID_WIDTH : natural := 16; - constant SUBMESSAGE_ID_WIDTH : natural := 8; - constant DOMAIN_ID_WIDTH : natural := 32; - constant UDP_PORT_WIDTH : natural := 16; - constant ENTITYID_WIDTH : natural := 32; - constant PROTOCOL_WIDTH : natural := 32; - constant PARAMETER_ID_WIDTH : natural := 16; - constant PAYLOAD_REPRESENTATION_ID : natural := 16; - constant PAYLOAD_REPRESENTATION_OPTIONS : natural := 16; - constant SEQUENCE_NR_WIDTH : natural := 64; - constant PARTICIPANT_MESSAGE_KIND_WIDTH : natural := 32; - -- 'RTPS' in Ascii code - constant PROTOCOL_RTPS : std_logic_vector(PROTOCOL_WIDTH-1 downto 0) := x"52545053"; - constant PROTOCOLVERSION_2_4 : std_logic_vector(PROTOCOLVERSION_WIDTH-1 downto 0) := x"0204"; - constant VENDORID_UNKNOWN : std_logic_vector(VENDORID_WIDTH-1 downto 0) := (others => '0'); - constant VENDORID : std_logic_vector(VENDORID_WIDTH-1 downto 0) := VENDORID_UNKNOWN; - -- Submessage IDs + -- *WIDTHS* + constant WORD_WIDTH : natural := 32; + constant BYTE_WIDTH : natural := 8; + constant UDP_PORT_WIDTH : natural := 16; + constant IPv4_ADDRESS_WIDTH : natural := 32; + constant UDP_HEADER_LENGTH_WIDTH : natural := 16; + -- CDR ENCODING WIDTHS + constant CDR_CHAR_WIDTH : natural := 8; + constant CDR_OCTET_WIDTH : natural := 8; + constant CDR_BOOLEAN_WIDTH : natural := 8; + constant CDR_SHORT_WIDTH : natural := 16; + constant CDR_ENUMERATION_SHORT_WIDTH : natural := 16; + constant CDR_LONG_WIDTH : natural := 32; + constant CDR_FLOAT_WIDTH : natural := 32; + constant CDR_ENUMERATION_WIDTH : natural := 32; + constant CDR_LONG_LONG_WIDTH : natural := 64; + constant CDR_DOUBLE_WIDTH : natural := 64; + constant CDR_LONG_DOUBLE_WIDTH : natural := 64; + -- RTPS + -- NOTE: Widths not defined with a CDR Width are defined as byte arrays (Same Endian representation) + constant GUIDPREFIX_WIDTH : natural := 96; + constant ENTITYID_WIDTH : natural := 32; + constant GUID_WIDTH : natural := GUIDPREFIX_WIDTH + ENTITYID_WIDTH; + constant PROTOCOL_WIDTH : natural := 32; + constant PROTOCOLVERSION_WIDTH : natural := 16; + constant VENDORID_WIDTH : natural := 16; + constant SUBMESSAGE_ID_WIDTH : natural := CDR_OCTET_WIDTH; + constant SUBMESSAGE_FLAGS_WIDTH : natural := CDR_OCTET_WIDTH; + constant SUBMESSAGE_LENGTH_WIDTH : natural := CDR_SHORT_WIDTH; + constant DOMAIN_ID_WIDTH : natural := CDR_LONG_WIDTH; + constant PARAMETER_ID_WIDTH : natural := CDR_SHORT_WIDTH; + constant PARAMETER_LENGTH_WIDTH : natural := CDR_SHORT_WIDTH; + constant PAYLOAD_REPRESENTATION_ID_WIDTH : natural := 16; + constant PAYLOAD_REPRESENTATION_OPTIONS_WIDTH : natural := 16; + constant PARTICIPANT_MESSAGE_KIND_WIDTH : natural := 32; + constant LOCATOR_KIND_WIDTH : natural := CDR_LONG_WIDTH; + constant COUNT_WIDTH : natural := CDR_LONG_WIDTH; + constant SUBMESSAGE_DATA_EXTRA_FLAGS_WIDTH : natural := 16; + + -- *TYPES DEFINITION* + -- Generic Types + type STRING_WORD_ARRAY_TYPE is array (0 to ((256*BYTE_WIDTH)/WORD_WIDTH)-1) of std_logic_vector(WORD_WIDTH-1 downto 0); -- Strings are constrained to 256 Characters + type DOUBLE_WORD_ARRAY is array (0 to 1) of unsigned(WORD_WIDTH-1 downto 0); + -- RTPS + -- TODO: Define unconstrained WORD_ARRAY and define constrained subtypes + subtype SEQUENCE_NR_TYPE is DOUBLE_WORD_ARRAY; + subtype DURATION_TYPE is DOUBLE_WORD_ARRAY; + subtype TIME_TYPE is DOUBLE_WORD_ARRAY; + type GUIDPREFIX_TYPE is array (0 to (GUIDPREFIX_WIDTH/WORD_WIDTH)-1) of std_logic_vector(WORD_WIDTH-1 downto 0); + type GUID_TYPE is array (0 to (GUID_WIDTH/WORD_WIDTH)-1) of std_logic_vector(WORD_WIDTH-1 downto 0); + + -- Helper Function + function gen_duration(s,ns : integer) return DURATION_TYPE; + + -- *PREDEFINED VALUES* + constant DEFAULT_IPv4_META_ADDRESS : std_logic_vector(IPv4_ADDRESS_WIDTH-1 downto 0) := x"EFFF0001"; -- Default Multicast Ipv4 Address (239.255.0.1) + constant DURATION_INFINITE : DURATION_TYPE := (x"7fffffff", x"ffffffff"); + constant PROTOCOL_RTPS : std_logic_vector(PROTOCOL_WIDTH-1 downto 0) := x"52545053"; -- 'RTPS' in Ascii code + constant PROTOCOLVERSION_2_4 : std_logic_vector(PROTOCOLVERSION_WIDTH-1 downto 0) := x"0204"; + constant VENDORID_UNKNOWN : std_logic_vector(VENDORID_WIDTH-1 downto 0) := (others => '0'); + constant GUIDPREFIX_UNKNOWN : GUIDPREFIX_TYPE := (others => (others => '0')); + constant UDP_PORT_INVALID : std_logic_vector(UDP_PORT_WIDTH-1 downto 0) := (others => '0'); + constant IPv4_ADDRESS_INVALID : std_logic_vector(IPv4_ADDRESS_WIDTH-1 downto 0) := (others => '0'); + + -- *SUBMESSAGE IDs* constant SID_PAD : std_logic_vector(SUBMESSAGE_ID_WIDTH-1 downto 0) := x"01"; constant SID_ACKNACK : std_logic_vector(SUBMESSAGE_ID_WIDTH-1 downto 0) := x"06"; constant SID_HEARTBEAT : std_logic_vector(SUBMESSAGE_ID_WIDTH-1 downto 0) := x"07"; @@ -177,7 +85,19 @@ package rtps_package is constant SID_HEARTBEAT_FRAG : std_logic_vector(SUBMESSAGE_ID_WIDTH-1 downto 0) := x"13"; constant SID_DATA : std_logic_vector(SUBMESSAGE_ID_WIDTH-1 downto 0) := x"15"; constant SID_DATA_FRAG : std_logic_vector(SUBMESSAGE_ID_WIDTH-1 downto 0) := x"16"; - -- Parameter IDs + + -- *SUBMESSAGE FLAG POSITIONS* + constant SUBMESSAGE_ENDIAN_FLAG_POS : natural := 0; + constant SUBMESSAGE_FINAL_FLAG_POS : natural := 1; + constant SUBMESSAGE_INLINE_QOS_FLAG_POS : natural := 1; + constant SUBMESSAGE_DATA_FLAG_POS : natural := 2; + constant SUBMESSAGE_KEY_FLAG_POS : natural := 3; + constant SUBMESSAGE_NON_STANDARD_PAYLOAD_FLAG_POS : natural := 4; + constant SUBMESSAGE_LIVELINESS_FLAG_POS : natural := 2; + constant SUBMESSAGE_MULTICAST_FLAG_POS : natural := 1; + constant SUBMESSAGE_INVALIDATE_FLAG_POS : natural := 1; + + -- *PARAMETER IDs* constant PID_PAD : std_logic_vector(PARAMETER_ID_WIDTH-1 downto 0) := x"0000"; constant PID_SENTINEL : std_logic_vector(PARAMETER_ID_WIDTH-1 downto 0) := x"0001"; constant PID_TOPIC_NAME : std_logic_vector(PARAMETER_ID_WIDTH-1 downto 0) := x"0005"; @@ -239,72 +159,20 @@ package rtps_package is constant PID_LIST_END : std_logic_vector(PARAMETER_ID_WIDTH-1 downto 0) := x"7F02"; constant PID_IGNORE : std_logic_vector(PARAMETER_ID_WIDTH-1 downto 0) := x"3F03"; - - -- PAYLOAD REPRESENTATION IDENTIFIERS - constant CDR_BE : std_logic_vector(PAYLOAD_REPRESENTATION_ID-1 downto 0) := x"0000"; - constant CDR_LE : std_logic_vector(PAYLOAD_REPRESENTATION_ID-1 downto 0) := x"0001"; - constant PL_CDR_BE : std_logic_vector(PAYLOAD_REPRESENTATION_ID-1 downto 0) := x"0002"; - constant PL_CDR_LE : std_logic_vector(PAYLOAD_REPRESENTATION_ID-1 downto 0) := x"0003"; - constant XML : std_logic_vector(PAYLOAD_REPRESENTATION_ID-1 downto 0) := x"0004"; - constant CDR2_BE : std_logic_vector(PAYLOAD_REPRESENTATION_ID-1 downto 0) := x"0010"; - constant CDR2_LE : std_logic_vector(PAYLOAD_REPRESENTATION_ID-1 downto 0) := x"0011"; - constant PL_CDR2_BE : std_logic_vector(PAYLOAD_REPRESENTATION_ID-1 downto 0) := x"0012"; - constant PL_CDR2_LE : std_logic_vector(PAYLOAD_REPRESENTATION_ID-1 downto 0) := x"0013"; - constant D_CDR_BE : std_logic_vector(PAYLOAD_REPRESENTATION_ID-1 downto 0) := x"0014"; - constant D_CDR_LE : std_logic_vector(PAYLOAD_REPRESENTATION_ID-1 downto 0) := x"0015"; - - - - - - constant DOMAIN_ID : std_logic_vector(DOMAIN_ID_WIDTH-1 downto 0) := std_logic_vector(to_unsigned(USER_DOMAIN_ID, DOMAIN_ID_WIDTH)); - constant DOMAIN_TAG : STRING_SLV_WORD_TYPE; -- Deferred to package body - - -- Since this implementation runs on the same network stack and the RTPS Endpoints (Readers & Writers) - -- can be differentiated based on their Entity ID, it makes no sense to have multiple IP Addresses - -- (and hence multiple Participants). - -- We generate just a single participant for every Domain, and later match the Endpoints to their respective - -- Domain (and thus also to their respective RTPS Participant). - - -- (see DDSI-RTPS 2.3 Section 9.6.1) - -- PB + DG * domain_id + d0 - constant META_IPv4_MULTICAST_PORT: std_logic_vector(UDP_PORT_WIDTH-1 downto 0) := std_logic_vector(to_unsigned(PORT_CONFIG_PB + PORT_CONFIG_D0 + PORT_CONFIG_DG*USER_DOMAIN_ID, UDP_PORT_WIDTH)); - -- (see DDSI-RTPS 2.3 Section 9.6.1) - -- PB + DG * domainId + d1 + PG * participant_id - -- participant_id=0 - constant META_IPv4_UNICAST_PORT : std_logic_vector(UDP_PORT_WIDTH-1 downto 0) := std_logic_vector(to_unsigned(PORT_CONFIG_PB + PORT_CONFIG_D1 + PORT_CONFIG_DG*USER_DOMAIN_ID, UDP_PORT_WIDTH)); - -- (see DDSI-RTPS 2.3 Section 9.6.1) - -- PB + DG * domainId + d2 - constant USER_IPv4_MULTICAST_PORT: std_logic_vector(UDP_PORT_WIDTH-1 downto 0) := std_logic_vector(to_unsigned(PORT_CONFIG_PB + PORT_CONFIG_D2 + PORT_CONFIG_DG*USER_DOMAIN_ID, UDP_PORT_WIDTH)); - -- (see DDSI-RTPS 2.3 Section 9.6.1) - -- PB + DG * domainId + d3 + PG * participant_id - -- participant_id=0 - constant USER_IPv4_UNICAST_PORT : std_logic_vector(UDP_PORT_WIDTH-1 downto 0) := std_logic_vector(to_unsigned(PORT_CONFIG_PB + PORT_CONFIG_D3 + PORT_CONFIG_DG*USER_DOMAIN_ID, UDP_PORT_WIDTH)); - - type GUIDPREFIX_TYPE is array (0 to GUIDPREFIX_WIDTH/32-1) of std_logic_vector(31 downto 0); - type GUID_TYPE is array (0 to (GUIDPREFIX_WIDTH+ENTITYID_WIDTH)/32-1) of std_logic_vector(31 downto 0); + -- *PAYLOAD REPRESENTATION IDENTIFIERS* + constant CDR_BE : std_logic_vector(PAYLOAD_REPRESENTATION_ID_WIDTH-1 downto 0) := x"0000"; + constant CDR_LE : std_logic_vector(PAYLOAD_REPRESENTATION_ID_WIDTH-1 downto 0) := x"0001"; + constant PL_CDR_BE : std_logic_vector(PAYLOAD_REPRESENTATION_ID_WIDTH-1 downto 0) := x"0002"; + constant PL_CDR_LE : std_logic_vector(PAYLOAD_REPRESENTATION_ID_WIDTH-1 downto 0) := x"0003"; + constant XML : std_logic_vector(PAYLOAD_REPRESENTATION_ID_WIDTH-1 downto 0) := x"0004"; + constant CDR2_BE : std_logic_vector(PAYLOAD_REPRESENTATION_ID_WIDTH-1 downto 0) := x"0010"; + constant CDR2_LE : std_logic_vector(PAYLOAD_REPRESENTATION_ID_WIDTH-1 downto 0) := x"0011"; + constant PL_CDR2_BE : std_logic_vector(PAYLOAD_REPRESENTATION_ID_WIDTH-1 downto 0) := x"0012"; + constant PL_CDR2_LE : std_logic_vector(PAYLOAD_REPRESENTATION_ID_WIDTH-1 downto 0) := x"0013"; + constant D_CDR_BE : std_logic_vector(PAYLOAD_REPRESENTATION_ID_WIDTH-1 downto 0) := x"0014"; + constant D_CDR_LE : std_logic_vector(PAYLOAD_REPRESENTATION_ID_WIDTH-1 downto 0) := x"0015"; - constant GUIDPREFIX : GUIDPREFIX_TYPE; -- Deferred to Package Body - constant GUIDPREFIX_UNKNOWN : GUIDPREFIX_TYPE := (others => (others => '0')); - - subtype ENTITY_KIND_H is std_logic_vector(1 downto 0); - subtype ENTITY_KIND_L is std_logic_vector(5 downto 0); - --FOLLOWING MAP TO ENTITY_KIND_H - constant USER_DEFINED_ENTITY : ENTITY_KIND_H := "00"; - constant BUILT_IN_ENTITY : ENTITY_KIND_H := "11"; - constant VENDOR_SPECIFIC_ENTITY : ENTITY_KIND_H := "01"; - --FOLLOWING MAP TO ENTITY_KIND_L - constant WRITER_WITH_KEY : ENTITY_KIND_L := "000010"; - constant WRITER_NO_KEY : ENTITY_KIND_L := "000011"; - constant READER_NO_KEY : ENTITY_KIND_L := "000100"; - constant READER_WITH_KEY : ENTITY_KIND_L := "000111"; - constant WRITER_GROUP : ENTITY_KIND_L := "001000"; - constant READER_GROUP : ENTITY_KIND_L := "001001"; - - -- DDSI-RTPS 2.3 states that Entity IDs have to be unique within each Participant. - -- For simplicity and ease of mapping we make the Entity IDs unique across all Participant and Domains on this node. - type ENTITYID_TYPE is array (0 to MAX_ENDPOINTS-1) of std_logic_vector(ENTITYID_WIDTH-1 downto 0); - constant ENTITYID : ENTITYID_TYPE; -- Deferred to Package Body + -- *ENTITY ID* constant ENTITYID_UNKNOWN : std_logic_vector(ENTITYID_WIDTH-1 downto 0) := (others => '0'); constant ENTITYID_PARTICIPANT : std_logic_vector(ENTITYID_WIDTH-1 downto 0) := (x"000001c1"); constant ENTITYID_SEDP_BUILTIN_TOPICS_ANNOUNCER : std_logic_vector(ENTITYID_WIDTH-1 downto 0) := (x"000002c2"); @@ -317,14 +185,105 @@ package rtps_package is constant ENTITYID_SPDP_BUILTIN_PARTICIPANT_DETECTOR : std_logic_vector(ENTITYID_WIDTH-1 downto 0) := (x"000100c7"); constant ENTITYID_P2P_BUILTIN_PARTICIPANT_MESSAGE_WRITER: std_logic_vector(ENTITYID_WIDTH-1 downto 0) := (x"000200c2"); constant ENTITYID_P2P_BUILTIN_PARTICIPANT_MESSAGE_READER: std_logic_vector(ENTITYID_WIDTH-1 downto 0) := (x"000200c7"); + -- *ENTITY KIND* (Last Byte of Entity ID) + subtype ENTITY_KIND_H_RANGE is natural range 1 downto 0; + subtype ENTITY_KIND_L_RANGE is natural range 7 downto 2; + --FOLLOWING MAP TO ENTITY_KIND_H + constant USER_DEFINED_ENTITY : std_logic_vector(ENTITY_KIND_H_RANGE) := "00"; + constant BUILT_IN_ENTITY : std_logic_vector(ENTITY_KIND_H_RANGE) := "11"; + constant VENDOR_SPECIFIC_ENTITY : std_logic_vector(ENTITY_KIND_H_RANGE) := "01"; + --FOLLOWING MAP TO ENTITY_KIND_L + constant WRITER_WITH_KEY : std_logic_vector(ENTITY_KIND_L_RANGE) := "000010"; + constant WRITER_NO_KEY : std_logic_vector(ENTITY_KIND_L_RANGE) := "000011"; + constant READER_NO_KEY : std_logic_vector(ENTITY_KIND_L_RANGE) := "000100"; + constant READER_WITH_KEY : std_logic_vector(ENTITY_KIND_L_RANGE) := "000111"; + constant WRITER_GROUP : std_logic_vector(ENTITY_KIND_L_RANGE) := "001000"; + constant READER_GROUP : std_logic_vector(ENTITY_KIND_L_RANGE) := "001001"; - constant LOCATOR_KIND_WIDTH : natural := 32; + -- *LOCATOR KIND* constant LOCATOR_KIND_INVALID : std_logic_vector := std_logic_vector(to_signed(-1,LOCATOR_KIND_WIDTH)); constant LOCATOR_KIND_RESERVERD : std_logic_vector := std_logic_vector(to_signed(0,LOCATOR_KIND_WIDTH)); constant LOCATOR_KIND_UDPv4 : std_logic_vector := std_logic_vector(to_signed(1,LOCATOR_KIND_WIDTH)); constant LOCATOR_KIND_UDPv6 : std_logic_vector := std_logic_vector(to_signed(2,LOCATOR_KIND_WIDTH)); - -- BUILTIN ENDPOINT SET POSITIONS + -- *DDS QoS* + -- DURABILITY + constant VOLATILE_DURABILITY_QOS : std_logic_vector(CDR_ENUMERATION_WIDTH-1 downto 0) := std_logic_vector(to_unsigned(0,CDR_ENUMERATION_WIDTH)); + constant TRANSIENT_LOCAL_DURABILITY_QOS : std_logic_vector(CDR_ENUMERATION_WIDTH-1 downto 0) := std_logic_vector(to_unsigned(1,CDR_ENUMERATION_WIDTH)); + constant TRANSIENT_DURABILITY_QOS : std_logic_vector(CDR_ENUMERATION_WIDTH-1 downto 0) := std_logic_vector(to_unsigned(2,CDR_ENUMERATION_WIDTH)); + constant PERSISTENT_DURABILITY_QOS : std_logic_vector(CDR_ENUMERATION_WIDTH-1 downto 0) := std_logic_vector(to_unsigned(3,CDR_ENUMERATION_WIDTH)); + constant DEFAULT_DURABILITY_QOS : std_logic_vector(CDR_ENUMERATION_WIDTH-1 downto 0) := VOLATILE_DURABILITY_QOS; + -- PRESENTATION + constant INSTANCE_PRESENTATION_QOS : std_logic_vector(CDR_ENUMERATION_WIDTH-1 downto 0) := std_logic_vector(to_unsigned(0,CDR_ENUMERATION_WIDTH)); + constant TOPIC_PRESENTATION_QOS : std_logic_vector(CDR_ENUMERATION_WIDTH-1 downto 0) := std_logic_vector(to_unsigned(1,CDR_ENUMERATION_WIDTH)); + constant GROUP_PRESENTATION_QOS : std_logic_vector(CDR_ENUMERATION_WIDTH-1 downto 0) := std_logic_vector(to_unsigned(2,CDR_ENUMERATION_WIDTH)); + constant DEFAULT_PRESENTATION_QOS : std_logic_vector(CDR_ENUMERATION_WIDTH-1 downto 0) := INSTANCE_PRESENTATION_QOS; + -- COHERENT ACCESS (PRESENTATION) + constant DEFAULT_COHERENT_ACCESS : boolean := FALSE; + -- ORDERED ACCESS (PRESENTATION) + constant DEFAULT_ORDERED_ACCESS : boolean := FALSE; + -- DEADLINE + constant DEFAULT_DEADLINE_QOS : DURATION_TYPE := DURATION_INFINITE; + -- LATENCY BUDGET + constant DEFAULT_LATENCY_BUDGET_QOS : DURATION_TYPE := (others => (others => '0')); + -- OWNERSHIP + constant SHARED_OWNERSHIP_QOS : std_logic_vector(CDR_ENUMERATION_WIDTH-1 downto 0) := std_logic_vector(to_unsigned(0,CDR_ENUMERATION_WIDTH)); + constant EXCLUSIVE_OWNERSHIP_QOS : std_logic_vector(CDR_ENUMERATION_WIDTH-1 downto 0) := std_logic_vector(to_unsigned(1,CDR_ENUMERATION_WIDTH)); + constant DEFAULT_OWNERSHIP_QOS : std_logic_vector(CDR_ENUMERATION_WIDTH-1 downto 0) := SHARED_OWNERSHIP_QOS; + -- OWNERSHIP STRENGTH + constant DEFAULT_OWNERSHIP_STRENGTH_QOS : std_logic_vector(CDR_LONG_WIDTH-1 downto 0) := (others => '0'); + -- LIVELINESS + constant AUTOMATIC_LIVELINESS_QOS : std_logic_vector(CDR_ENUMERATION_WIDTH-1 downto 0) := std_logic_vector(to_unsigned(0,CDR_ENUMERATION_WIDTH)); + constant MANUAL_BY_PARTICIPANT_LIVELINESS_QOS : std_logic_vector(CDR_ENUMERATION_WIDTH-1 downto 0) := std_logic_vector(to_unsigned(1,CDR_ENUMERATION_WIDTH)); + constant MANUAL_BY_TOPIC_LIVELINESS_QOS : std_logic_vector(CDR_ENUMERATION_WIDTH-1 downto 0) := std_logic_vector(to_unsigned(2,CDR_ENUMERATION_WIDTH)); + constant DEFAULT_LIVELINESS_QOS : std_logic_vector(CDR_ENUMERATION_WIDTH-1 downto 0) := AUTOMATIC_LIVELINESS_QOS; + -- LEASE DURATION (LIVELINESS) + constant DEFAULT_LEASE_DURATION : DURATION_TYPE := DURATION_INFINITE; + -- TIME_BASED_FILTER + constant DEFAULT_TIME_BASED_FILTER_QOS : DURATION_TYPE := (others => (others => '0')); + -- RELIABILITY + constant BEST_EFFORT_RELIABILITY_QOS : std_logic_vector(CDR_ENUMERATION_WIDTH-1 downto 0) := std_logic_vector(to_unsigned(1,CDR_ENUMERATION_WIDTH)); + constant RELIABLE_RELIABILITY_QOS : std_logic_vector(CDR_ENUMERATION_WIDTH-1 downto 0) := std_logic_vector(to_unsigned(2,CDR_ENUMERATION_WIDTH)); + constant DEFAULT_RELIABILTY_QOS : std_logic_vector(CDR_ENUMERATION_WIDTH-1 downto 0) := RELIABLE_RELIABILITY_QOS; + -- MAX BLOCKING TIME (RELIABILITY) + constant DEFAULT_MAX_BLOCKING_TIME : DURATION_TYPE := gen_duration(0,100 * (10**6)); -- 100 ms + -- TRANSPORT_PRIORITY + constant DEFAULT_TRANSPORT_PRIORITY_QOS : std_logic_vector(CDR_LONG_WIDTH-1 downto 0) := (others => '0'); + -- LIFESPAN + constant DEFAULT_LIFESPAN_QOS : DURATION_TYPE := DURATION_INFINITE; + -- DESTINATION ORDER + constant BY_RECEPTION_TIMESTAMP_DESTINATION_ORDER_QOS : std_logic_vector(CDR_ENUMERATION_WIDTH-1 downto 0) := std_logic_vector(to_unsigned(0,CDR_ENUMERATION_WIDTH)); + constant BY_SOURCE_TIMESTAMP_DESTINATION_ORDER_QOS : std_logic_vector(CDR_ENUMERATION_WIDTH-1 downto 0) := std_logic_vector(to_unsigned(1,CDR_ENUMERATION_WIDTH)); + constant DEFAULT_DESTINATION_ORDER_QOS : std_logic_vector(CDR_ENUMERATION_WIDTH-1 downto 0) := BY_RECEPTION_TIMESTAMP_DESTINATION_ORDER_QOS; + -- HISTORY + constant KEEP_LAST_HISTORY_QOS : std_logic_vector(CDR_ENUMERATION_WIDTH-1 downto 0) := std_logic_vector(to_unsigned(0,CDR_ENUMERATION_WIDTH)); + constant KEEP_ALL_HISTORY_QOS : std_logic_vector(CDR_ENUMERATION_WIDTH-1 downto 0) := std_logic_vector(to_unsigned(1,CDR_ENUMERATION_WIDTH)); + constant DEFAULT_HISTORY_QOS : std_logic_vector(CDR_ENUMERATION_WIDTH-1 downto 0) := KEEP_LAST_HISTORY_QOS; + -- DEPTH (HISTORY) + constant DEFAULT_HISTORY_DEPTH : std_logic_vector(CDR_LONG_WIDTH-1 downto 0) := std_logic_vector(to_unsigned(1,CDR_LONG_WIDTH)); + -- RESOURCE_LIMITS + constant DEFAULT_MAX_SAMPLES : std_logic_vector(CDR_LONG_WIDTH-1 downto 0) := std_logic_vector(to_signed(-1,CDR_LONG_WIDTH)); -- LENGTH_UNLIMITED + constant DEFAULT_MAX_INSTANCES : std_logic_vector(CDR_LONG_WIDTH-1 downto 0) := std_logic_vector(to_signed(-1,CDR_LONG_WIDTH)); -- LENGTH_UNLIMITED + constant DEFAULT_MAX_SAMPLES_PER_INSTANCE : std_logic_vector(CDR_LONG_WIDTH-1 downto 0) := std_logic_vector(to_signed(-1,CDR_LONG_WIDTH)); -- LENGTH_UNLIMITED + -- WRITER_DATA_LIFECYCLE + constant DEFAULT_AUTODISPOSE_UNREGISTERED_INSTANCES : boolean := TRUE; + -- READER_DATA_LIFECYCLE + constant DEFAULT_AUTOPURGE_NOWRITER_SAMPLES_DELAY : DURATION_TYPE := DURATION_INFINITE; + constant DEFAULT_AUTOPURGE_DISPOSED_SAMPLES_DELAY : DURATION_TYPE := DURATION_INFINITE; + -- TYPE_CONSISTENCY (DDS XTYPES 1.3) + constant DISALLOW_TYPE_COERCION : std_logic_vector(CDR_ENUMERATION_SHORT_WIDTH-1 downto 0) := std_logic_vector(to_unsigned(0,CDR_ENUMERATION_SHORT_WIDTH)); + constant ALLOW_TYPE_COERCION : std_logic_vector(CDR_ENUMERATION_SHORT_WIDTH-1 downto 0) := std_logic_vector(to_unsigned(1,CDR_ENUMERATION_SHORT_WIDTH)); + -- DURABILITY SERVICE (DURABILITY) + constant DEFAULT_DURABILITY_SERVICE_CLEANUP_DELAY : DURATION_TYPE := (others => (others => '0')); + constant DEFAULT_DURABILITY_SERVICE_HISTORY : std_logic_vector(CDR_ENUMERATION_WIDTH-1 downto 0) := KEEP_LAST_HISTORY_QOS; + constant DEFAULT_DURABILITY_SERVICE_HISTORY_DEPTH : std_logic_vector(CDR_LONG_WIDTH-1 downto 0) := std_logic_vector(to_unsigned(1,CDR_LONG_WIDTH)); + constant DEFAULT_DURABILITY_SERVICE_MAX_SAMPLES : std_logic_vector(CDR_LONG_WIDTH-1 downto 0) := std_logic_vector(to_signed(-1,CDR_LONG_WIDTH)); -- LENGTH_UNLIMITED + constant DEFAULT_DURABILITY_SERVICE_MAX_INSTANCES : std_logic_vector(CDR_LONG_WIDTH-1 downto 0) := std_logic_vector(to_signed(-1,CDR_LONG_WIDTH)); -- LENGTH_UNLIMITED + constant DEFAULT_DURABILITY_SERVICE_MAX_SAMPLES_PER_INSTANCE: std_logic_vector(CDR_LONG_WIDTH-1 downto 0) := std_logic_vector(to_signed(-1,CDR_LONG_WIDTH)); -- LENGTH_UNLIMITED + + constant DEFAULT_PARTICIPANT_LEASE_DURATION : DURATION_TYPE := gen_duration(100, 0); -- 100 s + + -- *BUILTIN ENDPOINT SET POSITIONS* constant DISC_BUILTIN_ENDPOINT_PARTICIPANT_ANNOUNCER : natural := 0; constant DISC_BUILTIN_ENDPOINT_PARTICIPANT_DETECTOR : natural := 1; constant DISC_BUILTIN_ENDPOINT_PUBLICATIONS_ANNOUNCER : natural := 2; @@ -336,50 +295,25 @@ package rtps_package is constant DISC_BUILTIN_ENDPOINT_TOPICS_ANNOUNCER : natural := 28; constant DISC_BUILTIN_ENDPOINT_TOPICS_DETECTOR : natural := 29; - -- BUILTIN ENDPOINT QOS BITMASK + -- *BUILTIN ENDPOINT QOS BITMASK* -- XXX: We use some of the unused bits of the 32-bit bitmask when stored in the buffer for internal purposes. (see "builtin_endpoint" Entity) constant BEST_EFFORT_PARTICIPANT_MESSAGE_DATA_READER : natural := 0; - -- PARTICIPANT MESSAGE KIND + -- *PARTICIPANT MESSAGE KIND* constant PARTICIPANT_MESSAGE_DATA_KIND_UNKNOWN : std_logic_vector(PARTICIPANT_MESSAGE_KIND_WIDTH-1 downto 0) := (others => '0'); constant PARTICIPANT_MESSAGE_DATA_KIND_AUTOMATIC_LIVELINESS_UPDATE : std_logic_vector(PARTICIPANT_MESSAGE_KIND_WIDTH-1 downto 0) := x"00000001"; constant PARTICIPANT_MESSAGE_DATA_KIND_MANUAL_LIVELINESS_UPDATE : std_logic_vector(PARTICIPANT_MESSAGE_KIND_WIDTH-1 downto 0) := x"00000002"; - --*****CUSTOM***** - constant PARTICIPANT_FRAME_SIZE : natural := 23; - constant ENDPOINT_BITMASK_SIZE : natural := round_div(MAX_ENDPOINTS, 32); - constant ENDPOINT_FRAME_SIZE : natural := 4 + ENDPOINT_BITMASK_SIZE; - -- Limit Buffer to 32 bit Addresses - constant BUILTIN_BUFFER_SIZE : natural := work.math_pkg.min(MAX_ENDPOINTS*PARTICIPANT_FRAME_SIZE, natural'high); - --**************** + --*CUSTOM TYPES* + type USER_BOOLEAN_ARRAY_TYPE is array (natural range <>) of boolean; + type USER_STRING_ARRAY_TYPE is array (natural range <>) of string(1 to 256); + type USER_DURATION_ARRAY_TYPE is array (natural range <>) of DURATION_TYPE; + type USER_ENUMERATION_ARRAY_TYPE is array (natural range <>) of std_logic_vector(CDR_ENUMERATION_WIDTH-1 downto 0); + type USER_LONG_ARRAY_TYPE is array (natural range <>) of std_logic_vector(CDR_LONG_WIDTH-1 downto 0); - constant ENDPOINT_MATCH_OPCODE_WIDTH: natural := 32; - - constant OPCODE_MATCH : std_logic_vector(ENDPOINT_MATCH_OPCODE_WIDTH-1 downto 0) := x"55000000"; - constant OPCODE_UNMATCH : std_logic_vector(ENDPOINT_MATCH_OPCODE_WIDTH-1 downto 0) := x"55000001"; - constant OPCODE_LIVELINESS_UPDATE : std_logic_vector(ENDPOINT_MATCH_OPCODE_WIDTH-1 downto 0) := x"55000002"; - - type USER_ENDPOINT_OUTPUT is array (0 to MAX_ENDPOINTS-1) of std_logic_vector(31 downto 0); - type ENDPOINT_BITMASK_ARRAY_TYPE is array (0 to ENDPOINT_BITMASK_SIZE-1) of std_logic_vector(0 to 31); - - type WORD_ARRAY_TYPE is array (natural range <>) of std_logic_vector(31 downto 0); - type OUTPUT_DATA_TYPE is record - -- Limit DATA to MAX UDPv4 Payload Size - RTPS Header (65487 Bytes) - data : WORD_ARRAY_TYPE(0 to 16371); - length : natural; - end record; - - -- TODO: Use this everywhere - -- Marks the Reader Endpoint in the Endpoint Array - constant ENDPOINT_READERS : std_logic_vector(0 to MAX_ENDPOINTS-1) := (0 to NUM_READERS-1 => '1', others => '0'); - - constant READER_ENDPOINT_DATA : OUTPUT_DATA_TYPE; --Deferred to package body - constant WRITER_ENDPOINT_DATA : OUTPUT_DATA_TYPE; --Deferred to package body - constant PARTICIPANT_DATA : OUTPUT_DATA_TYPE; --Deferred to package body - - -- OVERLOAD FUNCTIONS - function convert_from_double_word (seq: DOUBLE_WORD_ARRAY) return unsigned; - function convert_to_double_word (seq: unsigned(63 downto 0)) return DOUBLE_WORD_ARRAY; + -- *OVERLOAD FUNCTIONS* + function convert_from_double_word (input: DOUBLE_WORD_ARRAY) return unsigned; + function convert_to_double_word (input: unsigned(63 downto 0)) return DOUBLE_WORD_ARRAY; function ">" (L,R: DOUBLE_WORD_ARRAY) return boolean; function ">" (L: DOUBLE_WORD_ARRAY; R: natural) return boolean; function ">" (L: natural; R: DOUBLE_WORD_ARRAY) return boolean; @@ -406,618 +340,23 @@ package rtps_package is function "-" (L: natural; R: DOUBLE_WORD_ARRAY) return DOUBLE_WORD_ARRAY; function min(L, R : DOUBLE_WORD_ARRAY) return DOUBLE_WORD_ARRAY; function max(L, R : DOUBLE_WORD_ARRAY) return DOUBLE_WORD_ARRAY; - - function endian_swap(endianness : std_logic; data : std_logic_vector) return std_logic_vector; - function endian_swap(endianness : std_logic; data : unsigned) return unsigned; - - end package; package body rtps_package is - function gen_entyid return ENTITYID_TYPE is - variable ret : ENTITYID_TYPE; + function convert_from_double_word (input: DOUBLE_WORD_ARRAY) return unsigned is + variable ret : unsigned(63 downto 0) := (others => '0'); begin - ret := (others => (others => '0')); - for i in 0 to ret'length-1 loop - -- (see DDSI-RTPS 2.3 Section 9.3.1.2) - -- Entity Kind Mapping - ret(i)(7 downto 6) := USER_DEFINED_ENTITY; - if (i <= NUM_READERS-1) then - if (ENDPOINT_WITH_KEY(i)) then - ret(i)(5 downto 0) := READER_WITH_KEY; - else - ret(i)(5 downto 0) := READER_NO_KEY; - end if; - else - if (ENDPOINT_WITH_KEY(i)) then - ret(i)(5 downto 0) := WRITER_WITH_KEY; - else - ret(i)(5 downto 0) := WRITER_NO_KEY; - end if; - end if; - -- ID Mapping - ret(i)(ENTITYID_WIDTH-1 downto 8) := std_logic_vector(to_unsigned(i,ENTITYID_WIDTH-8)); - end loop; + ret(63 downto 32) := input(0); + ret(31 downto 0) := input(1); return ret; end function; - constant ENTITYID : ENTITYID_TYPE := gen_entyid; - - - function gen_guidprefix return GUIDPREFIX_TYPE is - variable tmp : std_logic_vector(GUIDPREFIX_WIDTH-1 downto 0) := (others => '0'); - variable ret : GUIDPREFIX_TYPE := (others => (others => '0')); - begin - tmp := (others => '0'); - ret := (others => (others => '0')); - -- First two bytes have to be Vendor ID (see DDSI-RTPS 2.3 Section 9.3.1.5) - tmp(GUIDPREFIX_WIDTH-1 downto GUIDPREFIX_WIDTH-VENDORID_WIDTH) := VENDORID; - -- Next we insert the MAC address for uniqueness - tmp(GUIDPREFIX_WIDTH-VENDORID_WIDTH-1 downto GUIDPREFIX_WIDTH-VENDORID_WIDTH-48) := MAC_ADDRESS; - -- Next we insert the Domain ID - tmp(DOMAIN_ID_WIDTH-1 downto 0) := DOMAIN_ID; - - -- Convert to return type - for i in 0 to ret'length-1 loop - ret(i) := tmp(GUIDPREFIX_WIDTH-(i*ret(i)'length)-1 downto GUIDPREFIX_WIDTH-(i*ret(i)'length)-ret(i)'length); - end loop; - return ret; - end function; - - constant GUIDPREFIX : GUIDPREFIX_TYPE := gen_guidprefix; - - function find_min_lease_duration return DOUBLE_WORD_ARRAY is + function convert_to_double_word (input: unsigned(63 downto 0)) return DOUBLE_WORD_ARRAY is variable ret : DOUBLE_WORD_ARRAY := (others => (others => '0')); begin - ret := DURATION_INFINITE; - -- Sanity Check - if (NUM_WRITERS = 0) then - return ret; - end if; - - -- Iterate through writers - for i in NUM_READERS to MAX_ENDPOINTS-1 loop - -- Do not consider "MANUAL_BY_TOPIC" Liveliness - if (ENDPOINT_LIVELINESS(i) /= MANUAL_BY_TOPIC_LIVELINESS_QOS) then - -- Find Minimum Lease Duration - if (ENDPOINT_LEASE_DURATION(i) < ret) then - ret := ENDPOINT_LEASE_DURATION(i); - end if; - end if; - end loop; - return ret; - end function; - - constant MIN_ENDPOINT_LEASE_DURATION : DOUBLE_WORD_ARRAY := find_min_lease_duration; - - -- TODO: Use unconstraint string as input - function convert_string (str : string(1 to 256)) return STRING_SLV_WORD_TYPE is - variable ret : STRING_SLV_WORD_TYPE := (others => (others => '0')); - begin - ret := (others => (others => '0')); - for i in 0 to ret'length-1 loop - ret(i) := std_logic_vector(to_unsigned(character'POS(str((i*4)+1)), 8)) & std_logic_vector(to_unsigned(character'POS(str((i*4)+2)), 8)) & std_logic_vector(to_unsigned(character'POS(str((i*4)+3)), 8)) & std_logic_vector(to_unsigned(character'POS(str((i*4)+4)), 8)); - end loop; - return ret; - end function; - - function convert_endpoint_string (string_array : ENDPOINT_STRING_TYPE) return ENDPOINT_STRING_SLV_TYPE is - variable ret : ENDPOINT_STRING_SLV_TYPE := (others => (others => (others => '0'))); - begin - ret := (others => (others => (others => '0'))); - for i in 0 to ret'length-1 loop - ret(i) := convert_string(string_array(i)); - end loop; - return ret; - end function; - - constant ENDPOINT_TOPIC : ENDPOINT_STRING_SLV_TYPE := convert_endpoint_string(ENDPOINT_TOPIC_STRING); - constant ENDPOINT_TYPE : ENDPOINT_STRING_SLV_TYPE := convert_endpoint_string(ENDPOINT_TYPE_STRING); - constant DOMAIN_TAG : STRING_SLV_WORD_TYPE := convert_string(USER_DOMAIN_TAG); - - function string_len (str : STRING_SLV_WORD_TYPE) return natural is - variable ret : natural := 0; - begin - ret := 0; - for i in 0 to str'length-1 loop - for j in 0 to (str(i)'length/8)-1 loop - -- Count Bytes - ret := ret + 1; - -- Exit on first NULL byte (NULL Byte included in count) - if (str(i)(str(i)'length-j*8-1 downto str(i)'length-j*8-8) = (7 downto 0 => '0')) then - exit; - end if; - end loop; - end loop; - return ret; - end function; - - function gen_reader_endpoint_data return OUTPUT_DATA_TYPE is - variable ret : OUTPUT_DATA_TYPE := (data => (others => (others => '0')), length => 0); - variable ind : natural := 0; - variable len : natural := 0; - variable tmp : natural := 0; - begin - ret.data := (others => (others => '0')); - ret.length := 0; - -- Sanity Check - if (NUM_READERS = 0) then - return ret; - end if; - len := 0; - ind := 0; - - -- RTPS Submessages - -- One DATA Submessage for each Reader - for i in 0 to NUM_READERS-1 loop - -- RTPS Submessage Header - ret.data(ind) := SID_DATA & "00000100" & x"0000"; - -- DATA Header (extraFlags, octetsToInlineQoS) - len := len + 1; - ret.data(ind+len) := x"0000" & std_logic_vector(to_unsigned(16, 16)); - -- DATA Header (Reader Entity ID) - len := len + 1; - ret.data(ind+len) := ENTITYID_SEDP_BUILTIN_SUBSCRIPTIONS_DETECTOR; - -- DATA Header (Writer Entity ID) - len := len + 1; - ret.data(ind+len) := ENTITYID_SEDP_BUILTIN_SUBSCRIPTIONS_ANNOUNCER; - -- DATA Header (Sequence Number) - len := len + 1; - ret.data(ind+len) := (others => '0'); - -- DATA Header (Sequence Number) - len := len + 1; - ret.data(ind+len) := std_logic_vector(to_unsigned(i+1, ret.data(0)'length)); - -- Serialized Payload Header - len := len + 1; - ret.data(ind+len) := PL_CDR_BE & x"0000"; - -- Serialized Payload BEGIN - -- GUID - len := len + 1; - ret.data(ind+len):= PID_ENDPOINT_GUID & std_logic_vector(to_unsigned(16, 16)); - len := len + 1; - ret.data(ind+len) := GUIDPREFIX(0); - len := len + 1; - ret.data(ind+len) := GUIDPREFIX(1); - len := len + 1; - ret.data(ind+len) := GUIDPREFIX(2); - len := len + 1; - ret.data(ind+len) := ENTITYID(i); - -- EXPECTS INLINE QOS (Only relevant for Reader endpoints) - len := len + 1; - ret.data(ind+len) := PID_EXPECTS_INLINE_QOS & std_logic_vector(to_unsigned(4, 16)); - len := len + 1; - ret.data(ind+len) := (24 => '1', others => '0'); - -- TOPIC NAME - tmp := string_len(ENDPOINT_TOPIC(i)); - len := len + 1; - ret.data(ind+len) := PID_TOPIC_NAME & std_logic_vector(to_unsigned((round_div(tmp,4)+1)*4, 16)); - len := len + 1; - ret.data(ind+len) := std_logic_vector(to_unsigned(tmp, 32)); - for j in 0 to round_div(tmp,4)-1 loop - len := len + 1; - ret.data(ind+len) := ENDPOINT_TOPIC(i)(j); - end loop; - -- TYPE NAME - tmp := string_len(ENDPOINT_TYPE(i)); - len := len + 1; - ret.data(ind+len) := PID_TYPE_NAME & std_logic_vector(to_unsigned((round_div(tmp,4)+1)*4, 16)); - len := len + 1; - ret.data(ind+len) := std_logic_vector(to_unsigned(tmp, 32)); - for j in 0 to round_div(tmp,4)-1 loop - len := len + 1; - ret.data(ind+len) := ENDPOINT_TYPE(i)(j); - end loop; - -- DURABILITY - if (ENDPOINT_DURABILITY(i) /= VOLATILE_DURABILITY_QOS) then - len := len + 1; - ret.data(ind+len) := PID_DURABILITY & std_logic_vector(to_unsigned(4, 16)); - len := len + 1; - ret.data(ind+len) := ENDPOINT_DURABILITY(i); - end if; - -- DEADLINE - if (ENDPOINT_DEADLINE(i) /= DURATION_INFINITE) then - len := len + 1; - ret.data(ind+len) := PID_DEADLINE & std_logic_vector(to_unsigned(8, 16)); - len := len + 1; - ret.data(ind+len) := std_logic_vector(ENDPOINT_DEADLINE(i)(0)); - len := len + 1; - ret.data(ind+len) := std_logic_vector(ENDPOINT_DEADLINE(i)(1)); - end if; - -- LIVELINESS - if (ENDPOINT_LIVELINESS(i) /= AUTOMATIC_LIVELINESS_QOS or ENDPOINT_LEASE_DURATION(i) /= DURATION_INFINITE) then - len := len + 1; - ret.data(ind+len) := PID_LIVELINESS & std_logic_vector(to_unsigned(12, 16)); - len := len + 1; - ret.data(ind+len) := ENDPOINT_LIVELINESS(i); - len := len + 1; - ret.data(ind+len) := std_logic_vector(ENDPOINT_LEASE_DURATION(i)(0)); - len := len + 1; - ret.data(ind+len) := std_logic_vector(ENDPOINT_LEASE_DURATION(i)(1)); - end if; - -- RELIABILITY - -- TODO: Check also max_blocking_time for change (Currently ignored) - if (ENDPOINT_RELIABILITY(i) /= RELIABLE_RELIABILITY_QOS) then - len := len + 1; - ret.data(ind+len) := PID_RELIABILITY & std_logic_vector(to_unsigned(12, 16)); - len := len + 1; - ret.data(ind+len) := ENDPOINT_RELIABILITY(i); - len := len + 1; - ret.data(ind+len) := std_logic_vector(ENDPOINT_MAX_BLOCKING_TIME(i)(0)); - len := len + 1; - ret.data(ind+len) := std_logic_vector(ENDPOINT_MAX_BLOCKING_TIME(i)(1)); - end if; - -- DESTINATION ORDER - if (ENDPOINT_DESTINATION_ORDER(i) /= BY_RECEPTION_TIMESTAMP_DESTINATIONORDER_QOS) then - len := len + 1; - ret.data(ind+len) := PID_DESTINATION_ORDER & std_logic_vector(to_unsigned(4, 16)); - len := len + 1; - ret.data(ind+len) := ENDPOINT_DESTINATION_ORDER(i); - end if; - -- PRESENTATION - if (ENDPOINT_PRESENTATION(i) /= INSTANCE_PRESENTATION_QOS) then - len := len + 1; - ret.data(ind+len) := PID_PRESENTATION & std_logic_vector(to_unsigned(8, 16)); - len := len + 1; - ret.data(ind+len) := ENDPOINT_PRESENTATION(i); - len := len + 1; - ret.data(ind+len) := (24 => ENDPOINT_COHERENT_ACCESS(i), 16 => ENDPOINT_ORDERED_ACCESS(i), others => '0'); - end if; - -- SENTINEL - len := len + 1; - ret.data(ind+len) := PID_SENTINEL & std_logic_vector(to_unsigned(0, 16)); - -- Fix Submessage Length - ret.data(ind)(15 downto 0) := std_logic_vector(to_unsigned(len*4, 16)); - -- Reset Pointers - ind := ind + len + 1; - len := 0; - end loop; - -- Store Total Length - ret.length := ind; - return ret; - end function; - - constant READER_ENDPOINT_DATA : OUTPUT_DATA_TYPE := gen_reader_endpoint_data; - - function gen_writer_endpoint_data return OUTPUT_DATA_TYPE is - variable ret : OUTPUT_DATA_TYPE := (data => (others => (others => '0')), length => 0); - variable ind : natural := 0; - variable len : natural := 0; - variable tmp : natural := 0; - begin - ret.data := (others => (others => '0')); - ret.length := 0; - -- Sanity Check - if (NUM_WRITERS = 0) then - return ret; - end if; - len := 0; - ind := 0; - - -- RTPS Submessages - -- One DATA Submessage for each Writer Endpoint - for i in NUM_READERS to MAX_ENDPOINTS-1 loop - -- RTPS Submessage Header - ret.data(ind) := SID_DATA & "00000100" & x"0000"; - -- DATA Header (extraFlags, octetsToInlineQoS) - len := len + 1; - ret.data(ind+len) := x"0000" & std_logic_vector(to_unsigned(16, 16)); - -- DATA Header (Reader Entity ID) - len := len + 1; - ret.data(ind+len) := ENTITYID_SEDP_BUILTIN_PUBLICATIONS_DETECTOR; - -- DATA Header (Writer Entity ID) - len := len + 1; - ret.data(ind+len) := ENTITYID_SEDP_BUILTIN_PUBLICATIONS_ANNOUNCER; - -- DATA Header (Sequence Number) - len := len + 1; - ret.data(ind+len) := (others => '0'); - -- DATA Header (Sequence Number) - len := len + 1; - ret.data(ind+len) := std_logic_vector(to_unsigned(i-NUM_READERS+1, ret.data'length(1))); - -- Serialized Payload Header - len := len + 1; - ret.data(ind+len) := PL_CDR_BE & x"0000"; - -- Serialized Payload BEGIN - -- GUID - len := len + 1; - ret.data(ind+len):= PID_ENDPOINT_GUID & std_logic_vector(to_unsigned(16, 16)); - len := len + 1; - ret.data(ind+len) := GUIDPREFIX(0); - len := len + 1; - ret.data(ind+len) := GUIDPREFIX(1); - len := len + 1; - ret.data(ind+len) := GUIDPREFIX(2); - len := len + 1; - ret.data(ind+len) := ENTITYID(i); - -- TOPIC NAME - tmp := string_len(ENDPOINT_TOPIC(i)); - len := len + 1; - ret.data(ind+len) := PID_TOPIC_NAME & std_logic_vector(to_unsigned((round_div(tmp,4)+1)*4, 16)); - len := len + 1; - ret.data(ind+len) := std_logic_vector(to_unsigned(tmp, 32)); - for j in 0 to round_div(tmp,4)-1 loop - len := len + 1; - ret.data(ind+len) := ENDPOINT_TOPIC(i)(j); - end loop; - -- TYPE NAME - tmp := string_len(ENDPOINT_TYPE(i)); - len := len + 1; - ret.data(ind+len) := PID_TYPE_NAME & std_logic_vector(to_unsigned((round_div(tmp,4)+1)*4, 16)); - len := len + 1; - ret.data(ind+len) := std_logic_vector(to_unsigned(tmp, 32)); - for j in 0 to round_div(tmp,4)-1 loop - len := len + 1; - ret.data(ind+len) := ENDPOINT_TYPE(i)(j); - end loop; - -- DURABILITY - if (ENDPOINT_DURABILITY(i) /= VOLATILE_DURABILITY_QOS) then - len := len + 1; - ret.data(ind+len) := PID_DURABILITY & std_logic_vector(to_unsigned(4, 16)); - len := len + 1; - ret.data(ind+len) := ENDPOINT_DURABILITY(i); - end if; - -- DEADLINE - if (ENDPOINT_DEADLINE(i) /= DURATION_INFINITE) then - len := len + 1; - ret.data(ind+len) := PID_DEADLINE & std_logic_vector(to_unsigned(8, 16)); - len := len + 1; - ret.data(ind+len) := std_logic_vector(ENDPOINT_DEADLINE(i)(0)); - len := len + 1; - ret.data(ind+len) := std_logic_vector(ENDPOINT_DEADLINE(i)(1)); - end if; - -- LIVELINESS - if (ENDPOINT_LIVELINESS(i) /= AUTOMATIC_LIVELINESS_QOS or ENDPOINT_LEASE_DURATION(i) /= DURATION_INFINITE) then - len := len + 1; - ret.data(ind+len) := PID_LIVELINESS & std_logic_vector(to_unsigned(12, 16)); - len := len + 1; - ret.data(ind+len) := ENDPOINT_LIVELINESS(i); - len := len + 1; - ret.data(ind+len) := std_logic_vector(ENDPOINT_LEASE_DURATION(i)(0)); - len := len + 1; - ret.data(ind+len) := std_logic_vector(ENDPOINT_LEASE_DURATION(i)(1)); - end if; - -- RELIABILITY - -- TODO: Check also max_blocking_time for change (Currently ignored) - if (ENDPOINT_RELIABILITY(i) /= RELIABLE_RELIABILITY_QOS) then - len := len + 1; - ret.data(ind+len) := PID_RELIABILITY & std_logic_vector(to_unsigned(12, 16)); - len := len + 1; - ret.data(ind+len) := ENDPOINT_RELIABILITY(i); - len := len + 1; - ret.data(ind+len) := std_logic_vector(ENDPOINT_MAX_BLOCKING_TIME(i)(0)); - len := len + 1; - ret.data(ind+len) := std_logic_vector(ENDPOINT_MAX_BLOCKING_TIME(i)(1)); - end if; - -- LIFESPAN - if (ENDPOINT_LIFESPAN(i) /= DURATION_INFINITE) then - len := len + 1; - ret.data(ind+len) := PID_LIFESPAN & std_logic_vector(to_unsigned(8, 16)); - len := len + 1; - ret.data(ind+len) := std_logic_vector(ENDPOINT_LIFESPAN(i)(0)); - len := len + 1; - ret.data(ind+len) := std_logic_vector(ENDPOINT_LIFESPAN(i)(1)); - end if; - -- DESTINATION ORDER - if (ENDPOINT_DESTINATION_ORDER(i) /= BY_RECEPTION_TIMESTAMP_DESTINATIONORDER_QOS) then - len := len + 1; - ret.data(ind+len) := PID_DESTINATION_ORDER & std_logic_vector(to_unsigned(4, 16)); - len := len + 1; - ret.data(ind+len) := ENDPOINT_DESTINATION_ORDER(i); - end if; - -- PRESENTATION - if (ENDPOINT_PRESENTATION(i) /= INSTANCE_PRESENTATION_QOS) then - len := len + 1; - ret.data(ind+len) := PID_PRESENTATION & std_logic_vector(to_unsigned(8, 16)); - len := len + 1; - ret.data(ind+len) := ENDPOINT_PRESENTATION(i); - len := len + 1; - ret.data(ind+len) := (24 => ENDPOINT_COHERENT_ACCESS(i), 16 => ENDPOINT_ORDERED_ACCESS(i), others => '0'); - end if; - -- SENTINEL - len := len + 1; - ret.data(ind+len) := PID_SENTINEL & std_logic_vector(to_unsigned(0, 16)); - -- Fix Submessage Length - ret.data(ind)(15 downto 0) := std_logic_vector(to_unsigned(len*4, 16)); - -- Reset Pointers - ind := ind + len + 1; - len := 0; - end loop; - -- Store Total Length - ret.length := ind; - return ret; - end function; - - constant WRITER_ENDPOINT_DATA : OUTPUT_DATA_TYPE := gen_writer_endpoint_data; - - function gen_participant_data return OUTPUT_DATA_TYPE is - variable ret : OUTPUT_DATA_TYPE := (data => (others => (others => '0')), length => 0); - variable ind : natural := 0; - variable len : natural := 0; - variable tmp : natural := 0; - begin - ret.data := (others => (others => '0')); - ret.length := 0; - len := 0; - ind := 0; - - -- RTPS DATA SUBMESSAGE - -- RTPS Submessage Header - ret.data(ind) := SID_DATA & "00000100" & x"0000"; - -- DATA Header (extraFlags, octetsToInlineQoS) - len := len + 1; - ret.data(ind+len) := x"0000" & std_logic_vector(to_unsigned(16, 16)); - -- DATA Header (Reader Entity ID) - len := len + 1; - ret.data(ind+len) := ENTITYID_SPDP_BUILTIN_PARTICIPANT_DETECTOR; - -- DATA Header (Writer Entity ID) - len := len + 1; - ret.data(ind+len) := ENTITYID_SPDP_BUILTIN_PARTICIPANT_ANNOUNCER; - -- DATA Header (Sequence Number) - len := len + 1; - ret.data(ind+len) := (others => '0'); - -- DATA Header (Sequence Number) - len := len + 1; - ret.data(ind+len) := std_logic_vector(to_unsigned(1, ret.data(ind+len)'length)); - -- Serialized Payload Header - len := len + 1; - ret.data(ind+len) := PL_CDR_BE & x"0000"; - -- Serialized Payload BEGIN - -- GUID - len := len + 1; - ret.data(ind+len):= PID_PARTICIPANT_GUID & std_logic_vector(to_unsigned(16, 16)); - len := len + 1; - ret.data(ind+len) := GUIDPREFIX(0); - len := len + 1; - ret.data(ind+len) := GUIDPREFIX(1); - len := len + 1; - ret.data(ind+len) := GUIDPREFIX(2); - len := len + 1; - ret.data(ind+len) := ENTITYID_PARTICIPANT; - -- DOMAIN ID - len := len + 1; - ret.data(ind+len):= PID_DOMAIN_ID & std_logic_vector(to_unsigned(4, 16)); - len := len + 1; - ret.data(ind+len):= DOMAIN_ID; - -- DOMAIN TAG - if (USER_DOMAIN_TAG /= "") then - tmp := string_len(DOMAIN_TAG); - len := len + 1; - ret.data(ind+len) := PID_DOMAIN_TAG & std_logic_vector(to_unsigned((round_div(tmp,4)+1)*4, 16)); - len := len + 1; - ret.data(ind+len) := std_logic_vector(to_unsigned(tmp, 32)); - for j in 0 to round_div(tmp,4)-1 loop - len := len + 1; - ret.data(ind+len) := DOMAIN_TAG(j); - end loop; - end if; - -- PROTOCOL VERSION - len := len + 1; - ret.data(ind+len) := PID_PROTOCOL_VERSION & std_logic_vector(to_unsigned(4, 16)); - len := len + 1; - ret.data(ind+len) := (others => '0'); - ret.data(ind+len)(31 downto 16) := PROTOCOLVERSION_2_4; - -- VENDORID - len := len + 1; - ret.data(ind+len) := PID_VENDORID & std_logic_vector(to_unsigned(4, 16)); - len := len + 1; - ret.data(ind+len) := (others => '0'); - ret.data(ind+len)(31 downto 16) := VENDORID; - -- TODO: Expects inline QoS of Participant - -- METATRAFFIC UNICAST LOCATOR - len := len + 1; - ret.data(ind+len) := PID_METATRAFFIC_UNICAST_LOCATOR & std_logic_vector(to_unsigned(24, 16)); - len := len + 1; - ret.data(ind+len) := LOCATOR_KIND_UDPv4; - len := len + 1; - ret.data(ind+len) := (others => '0'); - ret.data(ind+len)(15 downto 0) := META_IPv4_UNICAST_PORT; - len := len + 1; - ret.data(ind+len) := (others => '0'); - len := len + 1; - ret.data(ind+len) := (others => '0'); - len := len + 1; - ret.data(ind+len) := (others => '0'); - len := len + 1; - ret.data(ind+len) := DEFAULT_IPv4_META_ADDRESS; - -- METATRAFFIC MULTICAST LOCATOR - len := len + 1; - ret.data(ind+len) := PID_METATRAFFIC_MULTICAST_LOCATOR & std_logic_vector(to_unsigned(24, 16)); - len := len + 1; - ret.data(ind+len) := LOCATOR_KIND_UDPv4; - len := len + 1; - ret.data(ind+len) := (others => '0'); - ret.data(ind+len)(15 downto 0) := META_IPv4_MULTICAST_PORT; - len := len + 1; - ret.data(ind+len) := (others => '0'); - len := len + 1; - ret.data(ind+len) := (others => '0'); - len := len + 1; - ret.data(ind+len) := (others => '0'); - len := len + 1; - ret.data(ind+len) := DEFAULT_IPv4_META_ADDRESS; - -- DEFAULT UNICAST LOCATOR - len := len + 1; - ret.data(ind+len) := PID_DEFAULT_UNICAST_LOCATOR & std_logic_vector(to_unsigned(24, 16)); - len := len + 1; - ret.data(ind+len) := LOCATOR_KIND_UDPv4; - len := len + 1; - ret.data(ind+len) := (others => '0'); - ret.data(ind+len)(15 downto 0) := USER_IPv4_UNICAST_PORT; - len := len + 1; - ret.data(ind+len) := (others => '0'); - len := len + 1; - ret.data(ind+len) := (others => '0'); - len := len + 1; - ret.data(ind+len) := (others => '0'); - len := len + 1; - ret.data(ind+len) := DEFAULT_IPv4_META_ADDRESS; - -- DEFAULT MULTICAST LOCATOR - len := len + 1; - ret.data(ind+len) := PID_METATRAFFIC_MULTICAST_LOCATOR & std_logic_vector(to_unsigned(24, 16)); - len := len + 1; - ret.data(ind+len) := LOCATOR_KIND_UDPv4; - len := len + 1; - ret.data(ind+len) := (others => '0'); - ret.data(ind+len)(15 downto 0) := USER_IPv4_MULTICAST_PORT; - len := len + 1; - ret.data(ind+len) := (others => '0'); - len := len + 1; - ret.data(ind+len) := (others => '0'); - len := len + 1; - ret.data(ind+len) := (others => '0'); - len := len + 1; - ret.data(ind+len) := DEFAULT_IPv4_META_ADDRESS; - -- LEASE DURATION - if (PARTICIPANT_LEASE_DURATION /= DEFAULT_PARTICIPANT_LEASE_DURATION) then - len := len + 1; - ret.data(ind+len) := PID_PARTICIPANT_LEASE_DURATION & std_logic_vector(to_unsigned(8, 16)); - len := len + 1; - ret.data(ind+len) := std_logic_vector(PARTICIPANT_LEASE_DURATION(0)); - len := len + 1; - ret.data(ind+len) := std_logic_vector(PARTICIPANT_LEASE_DURATION(1)); - end if; - -- AVAILABLE ENDPOINTS - len := len + 1; - ret.data(ind+len) := PID_BUILTIN_ENDPOINT_SET & std_logic_vector(to_unsigned(4, 16)); - len := len + 1; - ret.data(ind+len) := (DISC_BUILTIN_ENDPOINT_PARTICIPANT_ANNOUNCER => '1', DISC_BUILTIN_ENDPOINT_PARTICIPANT_DETECTOR => '1', BUILTIN_ENDPOINT_PARTICIPANT_MESSAGE_DATA_WRITER => '1', BUILTIN_ENDPOINT_PARTICIPANT_MESSAGE_DATA_READER => '1', others => '0'); - if (NUM_READERS > 0) then - ret.data(ind+len)(DISC_BUILTIN_ENDPOINT_PUBLICATIONS_DETECTOR) := '1'; - ret.data(ind+len)(DISC_BUILTIN_ENDPOINT_SUBSCRIPTIONS_ANNOUNCER):= '1'; - end if; - if (NUM_WRITERS > 0) then - ret.data(ind+len)(DISC_BUILTIN_ENDPOINT_PUBLICATIONS_ANNOUNCER) := '1'; - ret.data(ind+len)(DISC_BUILTIN_ENDPOINT_SUBSCRIPTIONS_DETECTOR) := '1'; - end if; - -- MANUAL LIVELINESS COUNT - len := len + 1; - ret.data(ind+len) := PID_PARTICIPANT_MANUAL_LIVELINESS_COUNT & std_logic_vector(to_unsigned(4, 16)); - len := len + 1; - ret.data(ind+len) := (others => '0'); - -- SENTINEL - len := len + 1; - ret.data(ind+len) := PID_SENTINEL & std_logic_vector(to_unsigned(0, 16)); - - -- Store Length - ret.length := ind + len + 1; - return ret; - end function; - - constant PARTICIPANT_DATA : OUTPUT_DATA_TYPE := gen_participant_data; - - function convert_from_double_word (seq: DOUBLE_WORD_ARRAY) return unsigned is - variable ret : unsigned(SEQUENCE_NR_WIDTH-1 downto 0) := (others => '0'); - begin - ret(63 downto 32) := seq(0); - ret(31 downto 0) := seq(1); - return ret; - end function; - - function convert_to_double_word (seq: unsigned(63 downto 0)) return DOUBLE_WORD_ARRAY is - variable ret : DOUBLE_WORD_ARRAY := (others => (others => '0')); - begin - ret(0) := seq(63 downto 32); - ret(1) := seq(31 downto 0); + ret(0) := input(63 downto 32); + ret(1) := input(31 downto 0); return ret; end function; @@ -1163,31 +502,16 @@ package body rtps_package is return ret; end function; - -- Returns the 'data' argument either as is, or with reversed Byte order, depending on the - -- 'endianness' argument. - function endian_swap(endianness : std_logic; data : std_logic_vector) return std_logic_vector is - variable ret : std_logic_vector(data'range); + function gen_duration(s,ns : integer) return DURATION_TYPE is + variable ret : DURATION_TYPE := (others => (others => '0')); + -- "unit" is the value of "ret(1)" equal to 1 nanosecond + -- (1 / 2^-32) * 10^-9 + constant unit : real := 4.294967296; begin - -- Assert that Data Signal is Byte aligned - assert (data'length mod 8 = 0) severity failure; - -- Little Endian - if (endianness = '1') then - -- Reverse byte Order - for i in 0 to (data'length/8)-1 loop - ret(i*8+8-1 downto i*8) := data(((data'length/8)-1-i)*8+8-1 downto ((data'length/8)-1-i)*8); - end loop; - -- Big Endian - else - ret := data; - end if; + assert (ns < 10**9) report "ns argument has to be less than a second" severity failure; + ret(0) := to_unsigned(s, 32); + ret(1) := to_unsigned(natural(CEIL(real(ns)*unit)),32); return ret; end function; - -- Returns the 'data' argument either as is, or with reversed Byte order, depending on the - -- 'endianness' argument. - function endian_swap(endianness : std_logic; data : unsigned) return unsigned is - begin - return unsigned(endian_swap(endianness, std_logic_vector(data))); - end function; - end package body; diff --git a/src/test.vhd b/src/test.vhd index 66239da..f750525 100644 --- a/src/test.vhd +++ b/src/test.vhd @@ -14,12 +14,14 @@ entity test is clk : in std_logic; -- Input Clock reset : in std_logic; -- Synchronous Reset input : in std_logic_vector(31 downto 0); - cnt : out natural range 0 to MAX_ENDPOINTS + cnt : out natural range 0 to NUM_ENDPOINTS ); end entity; architecture arch of test is - + + signal test_var : natural := 0; + -- Compares argument 'ref' with every element of 'ar', and returns the index of the last match. -- If no match is found, array length is returned. function match_id_endpoint (ref : std_logic_vector(ENTITYID_WIDTH-1 downto 0); ar : ENTITYID_TYPE) return natural is @@ -38,7 +40,10 @@ begin process(all) begin - cnt <= match_id_endpoint(input, ENTITYID); + cnt <= 0; + if (test_var < to_unsigned(input)) then + cnt <= match_id_endpoint(input, ENTITYID); + end if; end process; diff --git a/src/test_package.vhd b/src/test_package.vhd index 8e239ce..4cedf01 100644 --- a/src/test_package.vhd +++ b/src/test_package.vhd @@ -3,6 +3,7 @@ use ieee.std_logic_1164.all; use ieee.numeric_std.all; package test_package is + --generic( generic_var : natural := 1 ); -- Number of Domains constant NUM_DOMAIN : integer := 1; @@ -23,6 +24,8 @@ package test_package is type DOMAIN_ID_TYPE is array (NUM_DOMAIN-1 downto 0) of std_logic_vector(DOMAIN_ID_WIDTH-1 downto 0); + type TEST_ARRAY is array (natural range <>) of string(1 to 256); + function gen_domain_ids (user_id : USER_DOMAIN_ID_TYPE) return DOMAIN_ID_TYPE; diff --git a/src/user_config.vhd b/src/user_config.vhd new file mode 100644 index 0000000..af761cf --- /dev/null +++ b/src/user_config.vhd @@ -0,0 +1,123 @@ +library ieee; +use ieee.std_logic_1164.all; +use ieee.numeric_std.all; + +use work.rtps_package.all; + +package user_config is + + --*****USER CONFIG***** + + -- NOTE: All strings have to be padded to 256 characters + + -- Unicast IPv4 Address used by all RTPS Entities [Default 192.168.0.80] + constant DEFAULT_IPv4_ADDRESS : std_logic_vector(IPv4_ADDRESS_WIDTH-1 downto 0) := x"C0A80080"; + -- Number of RTPS Writer Endpoints + constant NUM_WRITERS : natural := 0; + -- Number of RTPS Reader Endpoints + constant NUM_READERS : natural := 1; + -- Number of RTPS Endpoints (Do not modify) + constant NUM_ENDPOINTS : natural := NUM_READERS+NUM_WRITERS; + -- PB Value of Default Port Generation (see DDSI-RTPS 2.3 Section 9.6.1) + constant PORT_CONFIG_PB : natural := 7400; + -- DG Value of Default Port Generation (see DDSI-RTPS 2.3 Section 9.6.1) + constant PORT_CONFIG_DG : natural := 250; + -- PG Value of Default Port Generation (see DDSI-RTPS 2.3 Section 9.6.1) + constant PORT_CONFIG_PG : natural := 2; + -- D0 Value of Default Port Generation (see DDSI-RTPS 2.3 Section 9.6.1) + constant PORT_CONFIG_D0 : natural := 0; + -- D1 Value of Default Port Generation (see DDSI-RTPS 2.3 Section 9.6.1) + constant PORT_CONFIG_D1 : natural := 10; + -- D2 Value of Default Port Generation (see DDSI-RTPS 2.3 Section 9.6.1) + constant PORT_CONFIG_D2 : natural := 1; + -- D3 Value of Default Port Generation (see DDSI-RTPS 2.3 Section 9.6.1) + constant PORT_CONFIG_D3 : natural := 11; + -- MAC Address of underlying network stack (Used to generate GUIDs) + constant MAC_ADDRESS : std_logic_vector(47 downto 0) := x"97917E0BA8CF"; + -- Domain ID + constant USER_DOMAIN_ID : natural := 1; + -- Domain TAG + constant USER_DOMAIN_TAG : string(1 to 256) := (others => NUL); --"" + + --***RTPS ENDPOINTS*** + -- Array denoting if Endpoints use Keyed Topics + constant ENDPOINT_WITH_KEY : USER_BOOLEAN_ARRAY_TYPE(0 to NUM_ENDPOINTS-1) := (others => FALSE); + -- Array mapping Topic Names to Endpoints + constant ENDPOINT_TOPIC_STRING : USER_STRING_ARRAY_TYPE(0 to NUM_ENDPOINTS-1) := (0 => "Placeholder" & (12 to 256 => NUL)); + -- Array mapping Type Names to Endpoints + constant ENDPOINT_TYPE_STRING : USER_STRING_ARRAY_TYPE(0 to NUM_ENDPOINTS-1) := (0 => "Placeholder" & (12 to 256 => NUL)); + -- *TIMING CHARACTERISTICS* + -- Timing Characteristics for Participant + constant PARTICIPANT_ANNOUNCEMENT_PERIOD : DURATION_TYPE := gen_duration(30,0); -- 30 s + constant PARTICIPANT_LEASE_DURATION : DURATION_TYPE := DEFAULT_PARTICIPANT_LEASE_DURATION; + -- Denotes how much faster then the deadline/period we schedule in order to account for transport delay. + constant DURATION_DELTA : DURATION_TYPE := gen_duration(0, 100*(10**6)); -- 100 ms + -- Timing Characteristics for built-in Endpoints + constant PARTICIPANT_HEARTBEAT_PERIOD : DURATION_TYPE := gen_duration(1,0); -- 1 s + constant PARTICIPANT_HEARTBEAT_RESPONSE_DELAY : DURATION_TYPE := gen_duration(0,500*(10**6)); -- 500 ms + constant PARTICIPANT_HEARTBEAT_SUPPRESSION_DELAY : DURATION_TYPE := gen_duration(0,0); + constant PARTICIPANT_ACKNACK_RESPONSE_DELAY : DURATION_TYPE := gen_duration(3,200*(10**6)); -- 200 ms + constant PARTICIPANT_ACKNACK_SUPPRESSION_DELAY : DURATION_TYPE := gen_duration(0,0); + -- Array mapping Timing Characteristics to Endpoints + constant ENDPOINT_HEARTBEAT_PERIOD : USER_DURATION_ARRAY_TYPE(0 to NUM_ENDPOINTS-1) := (others => gen_duration(1,0)); -- 1 s + constant ENDPOINT_HEARTBEAT_RESPONSE_DELAY : USER_DURATION_ARRAY_TYPE(0 to NUM_ENDPOINTS-1) := (others => gen_duration(0,500*(10**6))); -- 500 ms + constant ENDPOINT_HEARTBEAT_SUPPRESSION_DELAY : USER_DURATION_ARRAY_TYPE(0 to NUM_ENDPOINTS-1) := (others => gen_duration(0,0)); + constant ENDPOINT_ACKNACK_RESPONSE_DELAY : USER_DURATION_ARRAY_TYPE(0 to NUM_ENDPOINTS-1) := (others => gen_duration(3,200*(10**6))); -- 200 ms + constant ENDPOINT_ACKNACK_SUPPRESSION_DELAY : USER_DURATION_ARRAY_TYPE(0 to NUM_ENDPOINTS-1) := (others => gen_duration(0,0)); + + + --***ENDPOINT DDS QOS*** + -- Array mapping DURABILITY QoS to Endpoints + constant ENDPOINT_DURABILITY_QOS : USER_ENUMERATION_ARRAY_TYPE(0 to NUM_ENDPOINTS-1) := (others => DEFAULT_DURABILITY_QOS); + constant ENDPOINT_DURABILITY_SERVICE_CLEANUP_DELAY : USER_DURATION_ARRAY_TYPE(0 to NUM_ENDPOINTS-1) := (others => DEFAULT_DURABILITY_SERVICE_CLEANUP_DELAY); + constant ENDPOINT_DURABILITY_SERVICE_HISTORY : USER_LONG_ARRAY_TYPE(0 to NUM_ENDPOINTS-1) := (others => DEFAULT_DURABILITY_SERVICE_HISTORY); + constant ENDPOINT_DURABILITY_SERVICE_HISTORY_DEPTH : USER_LONG_ARRAY_TYPE(0 to NUM_ENDPOINTS-1) := (others => DEFAULT_DURABILITY_SERVICE_HISTORY_DEPTH); + constant ENDPOINT_DURABILITY_SERVICE_MAX_SAMPLES : USER_LONG_ARRAY_TYPE(0 to NUM_ENDPOINTS-1) := (others => DEFAULT_DURABILITY_SERVICE_MAX_SAMPLES); + constant ENDPOINT_DURABILITY_SERVICE_MAX_INSTANCES : USER_LONG_ARRAY_TYPE(0 to NUM_ENDPOINTS-1) := (others => DEFAULT_DURABILITY_SERVICE_MAX_INSTANCES); + constant ENDPOINT_DURABILITY_SERVICE_MAX_SAMPLES_PER_INSTANCE : USER_LONG_ARRAY_TYPE(0 to NUM_ENDPOINTS-1) := (others => DEFAULT_DURABILITY_SERVICE_MAX_SAMPLES_PER_INSTANCE); + -- Array mapping PRESENTATION QoS to Endpoints + constant ENDPOINT_PRESENTATION_QOS : USER_ENUMERATION_ARRAY_TYPE(0 to NUM_ENDPOINTS-1) := (others => DEFAULT_PRESENTATION_QOS); + constant ENDPOINT_COHERENT_ACCESS : USER_BOOLEAN_ARRAY_TYPE(0 to NUM_ENDPOINTS-1) := (others => DEFAULT_COHERENT_ACCESS); + constant ENDPOINT_ORDERED_ACCESS : USER_BOOLEAN_ARRAY_TYPE(0 to NUM_ENDPOINTS-1) := (others => DEFAULT_ORDERED_ACCESS); + -- Array mapping DEADLINE QoS to Endpoints + constant ENDPOINT_DEADLINE_QOS : USER_DURATION_ARRAY_TYPE(0 to NUM_ENDPOINTS-1) := (others => DEFAULT_DEADLINE_QOS); + -- Array mapping LATENCY_BUDGET QoS to Endpoints + constant ENDPOINT_LATENCY_BUDGET_QOS : USER_DURATION_ARRAY_TYPE(0 to NUM_ENDPOINTS-1) := (others => DEFAULT_LATENCY_BUDGET_QOS); + -- Array mapping OWNERSHIP QoS to Endpoints + constant ENDPOINT_OWNERSHIP_QOS : USER_ENUMERATION_ARRAY_TYPE(0 to NUM_ENDPOINTS-1) := (others => DEFAULT_OWNERSHIP_QOS); + -- Array mapping OWNERSHIP_STRENGTH QoS to Endpoints (Only relevant to Writers) + constant ENDPOINT_OWNERSHIP_STRENGTH_QOS : USER_LONG_ARRAY_TYPE(0 to NUM_ENDPOINTS-1) := (others => DEFAULT_OWNERSHIP_STRENGTH_QOS); + -- Array mapping LIVELINESS QoS to Endpoints + constant ENDPOINT_LIVELINESS_QOS : USER_ENUMERATION_ARRAY_TYPE(0 to NUM_ENDPOINTS-1) := (others => DEFAULT_LIVELINESS_QOS); + constant ENDPOINT_LEASE_DURATION : USER_DURATION_ARRAY_TYPE(0 to NUM_ENDPOINTS-1) := (others => DEFAULT_LEASE_DURATION); + -- Array mapping TIME_BASED_FILTER QoS to Endpoints (Only relevant to Readers) + constant ENDPOINT_TIME_BASED_FILTER_QOS : USER_DURATION_ARRAY_TYPE(0 to NUM_ENDPOINTS-1) := (others => DEFAULT_TIME_BASED_FILTER_QOS); + -- XXX: PARTITION QoS Ignored + -- Array mapping RELIABILITY QoS to Endpoints + constant ENDPOINT_RELIABILITY_QOS : USER_ENUMERATION_ARRAY_TYPE(0 to NUM_ENDPOINTS-1) := (others => DEFAULT_RELIABILTY_QOS); + -- (Only relevant to Writers) + constant ENDPOINT_MAX_BLOCKING_TIME : USER_DURATION_ARRAY_TYPE(0 to NUM_ENDPOINTS-1) := (others => DEFAULT_MAX_BLOCKING_TIME); + -- Array mapping TRANSPORT_PRIORITY QoS to Endpoints (Only relevant to Writers) + constant ENDPOINT_TRANSPORT_PRIORITY_QOS : USER_LONG_ARRAY_TYPE(0 to NUM_ENDPOINTS-1) := (others => DEFAULT_TRANSPORT_PRIORITY_QOS); + -- Array mapping LIFESPAN QoS to Endpoints (Only relevant to Writers) + constant ENDPOINT_LIFESPAN_QOS : USER_DURATION_ARRAY_TYPE(0 to NUM_ENDPOINTS-1) := (others => DEFAULT_LIFESPAN_QOS); + -- Array mapping DESTINATION_ORDER QoS to Endpoints + constant ENDPOINT_DESTINATION_ORDER_QOS : USER_ENUMERATION_ARRAY_TYPE(0 to NUM_ENDPOINTS-1) := (others => DEFAULT_DESTINATION_ORDER_QOS); + -- Array mapping HISTORY QoS to Endpoints + constant ENDPOINT_HISTORY_QOS : USER_ENUMERATION_ARRAY_TYPE(0 to NUM_ENDPOINTS-1) := (others => DEFAULT_HISTORY_QOS); + constant ENDPOINT_HISTORY_DEPTH : USER_LONG_ARRAY_TYPE(0 to NUM_ENDPOINTS-1) := (others => DEFAULT_HISTORY_DEPTH); + -- Array mapping RESOURCE_LIMITS QoS to Endpoints + constant ENDPOINT_MAX_SAMPLES : USER_LONG_ARRAY_TYPE(0 to NUM_ENDPOINTS-1) := (others => DEFAULT_MAX_SAMPLES); + constant ENDPOINT_MAX_INSTANCES : USER_LONG_ARRAY_TYPE(0 to NUM_ENDPOINTS-1) := (others => DEFAULT_MAX_INSTANCES); + constant ENDPOINT_MAX_SAMPLES_PER_INSTANCE : USER_LONG_ARRAY_TYPE(0 to NUM_ENDPOINTS-1) := (others => DEFAULT_MAX_SAMPLES_PER_INSTANCE); + -- XXX: ENTITY_FACTORY QoS Ignored + -- Array mapping WRITER_DATA_LIFECYCLE QoS to Endpoints (Only relevant to Writers) + constant ENDPOINT_AUTODISPOSE_UNREGISTERED_INSTANCES : USER_BOOLEAN_ARRAY_TYPE(0 to NUM_ENDPOINTS-1) := (others => DEFAULT_AUTODISPOSE_UNREGISTERED_INSTANCES); + -- Array mapping Reader_DATA_LIFECYCLE QoS to Endpoints (Only relevant to Readers) + constant ENDPOINT_AUTOPURGE_NOWRITER_SAMPLES_DELAY : USER_DURATION_ARRAY_TYPE(0 to NUM_ENDPOINTS-1) := (others => DEFAULT_AUTOPURGE_NOWRITER_SAMPLES_DELAY); + constant ENDPOINT_AUTOPURGE_DISPOSED_SAMPLES_DELAY : USER_DURATION_ARRAY_TYPE(0 to NUM_ENDPOINTS-1) := (others => DEFAULT_AUTOPURGE_DISPOSED_SAMPLES_DELAY); + + -- NOTE: The buffer will not only store participants, but also endpoint data + -- Used to determine the size of the builtin endpoint buffer + constant MAX_REMOTE_PARTICIPANTS : natural := 50; +end package; \ No newline at end of file diff --git a/syn/DE10-Nano/top.qsf b/syn/DE10-Nano/top.qsf index 17cebf9..b923cad 100644 --- a/syn/DE10-Nano/top.qsf +++ b/syn/DE10-Nano/top.qsf @@ -1,8 +1,8 @@ # -------------------------------------------------------------------------- # # -# Copyright (C) 2018 Intel Corporation. All rights reserved. +# Copyright (C) 2020 Intel Corporation. All rights reserved. # Your use of Intel Corporation's design tools, logic functions -# and other software and tools, and its AMPP partner logic +# and other software and tools, and any partner logic # functions, and any output files from any of the foregoing # (including device programming or simulation files), and any # associated documentation or information are expressly subject @@ -12,13 +12,14 @@ # agreement, including, without limitation, that your use is for # the sole purpose of programming logic devices manufactured by # Intel and sold by Intel or its authorized distributors. Please -# refer to the applicable agreement for further details. +# refer to the applicable agreement for further details, at +# https://fpgasoftware.intel.com/eula. # # -------------------------------------------------------------------------- # # # Quartus Prime -# Version 18.1.0 Build 625 09/12/2018 SJ Lite Edition -# Date created = 12:05:11 May 29, 2020 +# Version 20.1.0 Build 711 06/05/2020 SJ Lite Edition +# Date created = 13:33:09 November 02, 2020 # # -------------------------------------------------------------------------- # # @@ -37,24 +38,22 @@ set_global_assignment -name FAMILY "Cyclone V" -set_global_assignment -name DEVICE 5CSEBA6U23I7 -set_global_assignment -name TOP_LEVEL_ENTITY test -set_global_assignment -name ORIGINAL_QUARTUS_VERSION 18.1.0 -set_global_assignment -name PROJECT_CREATION_TIME_DATE "12:05:11 MAY 29, 2020" -set_global_assignment -name LAST_QUARTUS_VERSION "18.1.0 Lite Edition" -set_global_assignment -name PROJECT_OUTPUT_DIRECTORY output_files -set_global_assignment -name MIN_CORE_JUNCTION_TEMP "-40" -set_global_assignment -name MAX_CORE_JUNCTION_TEMP 100 -set_global_assignment -name ERROR_CHECK_FREQUENCY_DIVISOR 256 +set_global_assignment -name DEVICE 5CGXFC7C7F23C8 +set_global_assignment -name TOP_LEVEL_ENTITY rtps_builtin_endpoint +set_global_assignment -name ORIGINAL_QUARTUS_VERSION 20.1.0 +set_global_assignment -name PROJECT_CREATION_TIME_DATE "13:33:09 NOVEMBER 02, 2020" +set_global_assignment -name LAST_QUARTUS_VERSION "20.1.0 Lite Edition" +set_global_assignment -name VHDL_FILE ../../src/user_config.vhd -hdl_version VHDL_2008 +set_global_assignment -name VHDL_FILE ../../src/single_port_ram.vhd -hdl_version VHDL_2008 +set_global_assignment -name VHDL_FILE ../../src/rtps_package.vhd -hdl_version VHDL_2008 +set_global_assignment -name VHDL_FILE ../../src/rtps_handler.vhd -hdl_version VHDL_2008 +set_global_assignment -name VHDL_FILE ../../src/rtps_config_package.vhd -hdl_version VHDL_2008 +set_global_assignment -name VHDL_FILE ../../src/rtps_builtin_endpoint.vhd -hdl_version VHDL_2008 +set_global_assignment -name VHDL_FILE ../../src/math_pkg.vhd -hdl_version VHDL_2008 +set_global_assignment -name MIN_CORE_JUNCTION_TEMP 0 +set_global_assignment -name MAX_CORE_JUNCTION_TEMP 85 set_global_assignment -name POWER_PRESET_COOLING_SOLUTION "23 MM HEAT SINK WITH 200 LFPM AIRFLOW" set_global_assignment -name POWER_BOARD_THERMAL_MODEL "NONE (CONSERVATIVE)" -set_global_assignment -name VHDL_FILE ../../src/rtps_handler.vhd -hdl_version VHDL_2008 -set_global_assignment -name VHDL_FILE ../../src/single_port_ram.vhd -hdl_version VHDL_2008 -set_global_assignment -name VHDL_FILE ../../src/rtps_builtin_endpoint.vhd -hdl_version VHDL_2008 -set_global_assignment -name VHDL_FILE ../../src/rtps_package.vhd -hdl_version VHDL_2008 -set_global_assignment -name VHDL_FILE ../../src/test_package.vhd -hdl_version VHDL_2008 -set_global_assignment -name VHDL_FILE ../../src/test.vhd -hdl_version VHDL_2008 -set_global_assignment -name VHDL_FILE ../../src/math_pkg.vhd -hdl_version VHDL_2008 set_global_assignment -name PARTITION_NETLIST_TYPE SOURCE -section_id Top set_global_assignment -name PARTITION_FITTER_PRESERVATION_LEVEL PLACEMENT_AND_ROUTING -section_id Top set_global_assignment -name PARTITION_COLOR 16764057 -section_id Top diff --git a/syn/Zedboard/rtps-fpga.xpr b/syn/Zedboard/rtps-fpga.xpr index fcb009f..f34dee3 100644 --- a/syn/Zedboard/rtps-fpga.xpr +++ b/syn/Zedboard/rtps-fpga.xpr @@ -73,16 +73,28 @@ + + + + + + + + + + + + + @@ -98,6 +110,7 @@ +