* Liveliness Assertion * Participant Announcement * Colapse all Header sending into single stage, remove RTPS header from pre-generated data
1019 lines
56 KiB
VHDL
1019 lines
56 KiB
VHDL
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)
|
|
|
|
package rtps_package is
|
|
|
|
--*****USER CONFIG*****
|
|
-- Unicast IPv4 Address used by all RTPS Entities [Default 192.168.0.80]
|
|
constant IPv4_UNICAST_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 := "";
|
|
|
|
-----------------------------------------------------------------------------------------------------
|
|
-- *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) of std_logic_vector(31 downto 0);
|
|
type ENDPOINT_STRING_SLV_TYPE is array (0 to MAX_ENDPOINTS-1) of STRING_SLV_WORD_TYPE;
|
|
subtype QOS_TYPE is array (0 to MAX_ENDPOINTS-1) of std_logic_vector(31 downto 0);
|
|
subtype 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,32));
|
|
constant ALLOW_TYPE_COERCION : std_logic_vector(15 downto 0) := std_logic_vector(to_unsigned(1,32));
|
|
-- *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);
|
|
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 DEFAULT_PARTICIPANT_LEASE_DURATION : DOUBLE_WORD_ARRAY := (to_unsigned(100,32),to_unsigned(0,32);
|
|
constant PARTICIPANT_LEASE_DURATION : DOUBLE_WORD_ARRAY := DEFAULT_PARTICIPANT_LEASE_DURATION;
|
|
|
|
-- NOTE: The buffer will not only store participants, but also endpoint data
|
|
-- Used to determine the size of the built-inendpoint buffer
|
|
constant MAX_REMOTE_PARTICIPANTS : natural := 50;
|
|
|
|
--*****DDSI-RTPS 2.3*****
|
|
|
|
-- Default Multicast Ipv4 Address (239.255.0.1)
|
|
constant DEFAULT_IPv4_MULTICAST_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
|
|
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";
|
|
constant SID_GAP : std_logic_vector(SUBMESSAGE_ID_WIDTH-1 downto 0) := x"08";
|
|
constant SID_INFO_TS : std_logic_vector(SUBMESSAGE_ID_WIDTH-1 downto 0) := x"09";
|
|
constant SID_INFO_SRC : std_logic_vector(SUBMESSAGE_ID_WIDTH-1 downto 0) := x"0c";
|
|
constant SID_INFO_REPLY_IP4 : std_logic_vector(SUBMESSAGE_ID_WIDTH-1 downto 0) := x"0d";
|
|
constant SID_INFO_DST : std_logic_vector(SUBMESSAGE_ID_WIDTH-1 downto 0) := x"0e";
|
|
constant SID_INFO_REPLY : std_logic_vector(SUBMESSAGE_ID_WIDTH-1 downto 0) := x"0f";
|
|
constant SID_NACK_FRAG : std_logic_vector(SUBMESSAGE_ID_WIDTH-1 downto 0) := x"12";
|
|
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
|
|
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";
|
|
constant PID_TYPE_NAME : std_logic_vector(PARAMETER_ID_WIDTH-1 downto 0) := x"0007";
|
|
constant PID_USER_DATA : std_logic_vector(PARAMETER_ID_WIDTH-1 downto 0) := x"002c";
|
|
constant PID_GROUP_DATA : std_logic_vector(PARAMETER_ID_WIDTH-1 downto 0) := x"002d";
|
|
constant PID_TOPIC_DATA : std_logic_vector(PARAMETER_ID_WIDTH-1 downto 0) := x"002e";
|
|
constant PID_DURABILITY : std_logic_vector(PARAMETER_ID_WIDTH-1 downto 0) := x"001d";
|
|
constant PID_DURABILITY_SERVICE : std_logic_vector(PARAMETER_ID_WIDTH-1 downto 0) := x"001e";
|
|
constant PID_DEADLINE : std_logic_vector(PARAMETER_ID_WIDTH-1 downto 0) := x"0023";
|
|
constant PID_LATENCY_BUDGET : std_logic_vector(PARAMETER_ID_WIDTH-1 downto 0) := x"0027";
|
|
constant PID_LIVELINESS : std_logic_vector(PARAMETER_ID_WIDTH-1 downto 0) := x"001b";
|
|
constant PID_RELIABILITY : std_logic_vector(PARAMETER_ID_WIDTH-1 downto 0) := x"001a";
|
|
constant PID_LIFESPAN : std_logic_vector(PARAMETER_ID_WIDTH-1 downto 0) := x"002b";
|
|
constant PID_DESTINATION_ORDER : std_logic_vector(PARAMETER_ID_WIDTH-1 downto 0) := x"0025";
|
|
constant PID_HISTORY : std_logic_vector(PARAMETER_ID_WIDTH-1 downto 0) := x"0040";
|
|
constant PID_RESOURCE_LIMITS : std_logic_vector(PARAMETER_ID_WIDTH-1 downto 0) := x"0041";
|
|
constant PID_OWNERSHIP : std_logic_vector(PARAMETER_ID_WIDTH-1 downto 0) := x"001f";
|
|
constant PID_OWNERSHIP_STRENGTH : std_logic_vector(PARAMETER_ID_WIDTH-1 downto 0) := x"001e";
|
|
constant PID_PRESENTATION : std_logic_vector(PARAMETER_ID_WIDTH-1 downto 0) := x"0021";
|
|
constant PID_PARTITION : std_logic_vector(PARAMETER_ID_WIDTH-1 downto 0) := x"0029";
|
|
constant PID_TIME_BASED_FILTER : std_logic_vector(PARAMETER_ID_WIDTH-1 downto 0) := x"0004";
|
|
constant PID_TRANSPORT_PRIORITY : std_logic_vector(PARAMETER_ID_WIDTH-1 downto 0) := x"0049";
|
|
constant PID_DOMAIN_ID : std_logic_vector(PARAMETER_ID_WIDTH-1 downto 0) := x"000f";
|
|
constant PID_DOMAIN_TAG : std_logic_vector(PARAMETER_ID_WIDTH-1 downto 0) := x"4014";
|
|
constant PID_PROTOCOL_VERSION : std_logic_vector(PARAMETER_ID_WIDTH-1 downto 0) := x"0015";
|
|
constant PID_VENDORID : std_logic_vector(PARAMETER_ID_WIDTH-1 downto 0) := x"0016";
|
|
constant PID_UNICAST_LOCATOR : std_logic_vector(PARAMETER_ID_WIDTH-1 downto 0) := x"002f";
|
|
constant PID_MULTICAST_LOCATOR : std_logic_vector(PARAMETER_ID_WIDTH-1 downto 0) := x"0030";
|
|
constant PID_DEFAULT_UNICAST_LOCATOR : std_logic_vector(PARAMETER_ID_WIDTH-1 downto 0) := x"0031";
|
|
constant PID_DEFAULT_MULTICAST_LOCATOR : std_logic_vector(PARAMETER_ID_WIDTH-1 downto 0) := x"0048";
|
|
constant PID_METATRAFFIC_UNICAST_LOCATOR : std_logic_vector(PARAMETER_ID_WIDTH-1 downto 0) := x"0032";
|
|
constant PID_METATRAFFIC_MULTICAST_LOCATOR : std_logic_vector(PARAMETER_ID_WIDTH-1 downto 0) := x"0033";
|
|
constant PID_EXPECTS_INLINE_QOS : std_logic_vector(PARAMETER_ID_WIDTH-1 downto 0) := x"0043";
|
|
constant PID_PARTICIPANT_MANUAL_LIVELINESS_COUNT : std_logic_vector(PARAMETER_ID_WIDTH-1 downto 0) := x"0034";
|
|
constant PID_PARTICIPANT_LEASE_DURATION : std_logic_vector(PARAMETER_ID_WIDTH-1 downto 0) := x"0002";
|
|
constant PID_CONTENT_FILTER_PROPERTY : std_logic_vector(PARAMETER_ID_WIDTH-1 downto 0) := x"0035";
|
|
constant PID_PARTICIPANT_GUID : std_logic_vector(PARAMETER_ID_WIDTH-1 downto 0) := x"0050";
|
|
constant PID_GROUP_GUID : std_logic_vector(PARAMETER_ID_WIDTH-1 downto 0) := x"0052";
|
|
constant PID_BUILTIN_ENDPOINT_SET : std_logic_vector(PARAMETER_ID_WIDTH-1 downto 0) := x"0058";
|
|
constant PID_BUILTIN_ENDPOINT_QOS : std_logic_vector(PARAMETER_ID_WIDTH-1 downto 0) := x"0077";
|
|
constant PID_PROPERTY_LIST : std_logic_vector(PARAMETER_ID_WIDTH-1 downto 0) := x"0059";
|
|
constant PID_TYPE_MAX_SIZE_SERIALIZED : std_logic_vector(PARAMETER_ID_WIDTH-1 downto 0) := x"0060";
|
|
constant PID_ENTITY_NAME : std_logic_vector(PARAMETER_ID_WIDTH-1 downto 0) := x"0062";
|
|
constant PID_ENDPOINT_GUID : std_logic_vector(PARAMETER_ID_WIDTH-1 downto 0) := x"005a";
|
|
-- INLINE-QOS ONLY
|
|
constant PID_CONTENT_FILTER_INFO : std_logic_vector(PARAMETER_ID_WIDTH-1 downto 0) := x"0055";
|
|
constant PID_COHERENT_SET : std_logic_vector(PARAMETER_ID_WIDTH-1 downto 0) := x"0056";
|
|
constant PID_DIRECTED_WRITE : std_logic_vector(PARAMETER_ID_WIDTH-1 downto 0) := x"0057";
|
|
constant PID_ORIGINAL_WRITER_INFO : std_logic_vector(PARAMETER_ID_WIDTH-1 downto 0) := x"0061";
|
|
constant PID_GROUP_COHERENT_SET : std_logic_vector(PARAMETER_ID_WIDTH-1 downto 0) := x"0063";
|
|
constant PID_GROUP_SEQ_NUM : std_logic_vector(PARAMETER_ID_WIDTH-1 downto 0) := x"0064";
|
|
constant PID_WRITER_GROUP_INFO : std_logic_vector(PARAMETER_ID_WIDTH-1 downto 0) := x"0065";
|
|
constant PID_SECURE_WRITER_GROUP_INFO : std_logic_vector(PARAMETER_ID_WIDTH-1 downto 0) := x"0066";
|
|
constant PID_KEY_HASH : std_logic_vector(PARAMETER_ID_WIDTH-1 downto 0) := x"0070";
|
|
constant PID_STATUS_INFO : std_logic_vector(PARAMETER_ID_WIDTH-1 downto 0) := x"0071";
|
|
-- XTYPES 1.3
|
|
constant PID_EXTENDED : std_logic_vector(PARAMETER_ID_WIDTH-1 downto 0) := x"7F01";
|
|
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) := to_unsigned(USER_DOMAIN_ID, DOMAIN_ID'length);
|
|
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);
|
|
|
|
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
|
|
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");
|
|
constant ENTITYID_SEDP_BUILTIN_TOPICS_DETECTOR : std_logic_vector(ENTITYID_WIDTH-1 downto 0) := (x"000002c7");
|
|
constant ENTITYID_SEDP_BUILTIN_PUBLICATIONS_ANNOUNCER : std_logic_vector(ENTITYID_WIDTH-1 downto 0) := (x"000003c2");
|
|
constant ENTITYID_SEDP_BUILTIN_PUBLICATIONS_DETECTOR : std_logic_vector(ENTITYID_WIDTH-1 downto 0) := (x"000003c7");
|
|
constant ENTITYID_SEDP_BUILTIN_SUBSCRIPTIONS_ANNOUNCER : std_logic_vector(ENTITYID_WIDTH-1 downto 0) := (x"000004c2");
|
|
constant ENTITYID_SEDP_BUILTIN_SUBSCRIPTIONS_DETECTOR : std_logic_vector(ENTITYID_WIDTH-1 downto 0) := (x"000004c7");
|
|
constant ENTITYID_SPDP_BUILTIN_PARTICIPANT_ANNOUNCER : std_logic_vector(ENTITYID_WIDTH-1 downto 0) := (x"000100c2");
|
|
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");
|
|
|
|
constant LOCATOR_KIND_WIDTH : natural := 32;
|
|
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
|
|
constant DISC_BUILTIN_ENDPOINT_PARTICIPANT_ANNOUNCER : natural := 0;
|
|
constant DISC_BUILTIN_ENDPOINT_PARTICIPANT_DETECTOR : natural := 1;
|
|
constant DISC_BUILTIN_ENDPOINT_PUBLICATIONS_ANNOUNCER : natural := 2;
|
|
constant DISC_BUILTIN_ENDPOINT_PUBLICATIONS_DETECTOR : natural := 3;
|
|
constant DISC_BUILTIN_ENDPOINT_SUBSCRIPTIONS_ANNOUNCER : natural := 4;
|
|
constant DISC_BUILTIN_ENDPOINT_SUBSCRIPTIONS_DETECTOR : natural := 5;
|
|
constant BUILTIN_ENDPOINT_PARTICIPANT_MESSAGE_DATA_WRITER : natural := 10;
|
|
constant BUILTIN_ENDPOINT_PARTICIPANT_MESSAGE_DATA_READER : natural := 11;
|
|
constant DISC_BUILTIN_ENDPOINT_TOPICS_ANNOUNCER : natural := 28;
|
|
constant DISC_BUILTIN_ENDPOINT_TOPICS_DETECTOR : natural := 29;
|
|
|
|
-- 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
|
|
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 := 19;
|
|
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 := min(MAX_ENDPOINTS*PARTICIPANT_FRAME_SIZE, 2**32);
|
|
--****************
|
|
|
|
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(31 downto 0);
|
|
|
|
type WORD_ARRAY_TYPE is array (range <>) of std_logic_vector(31 downto 0);
|
|
type OUTPUT_DATA_TYPE is record
|
|
data : WORD_ARRAY_TYPE;
|
|
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
|
|
|
|
-- 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;
|
|
function ">" (L,R: DOUBLE_WORD_ARRAY) return boolean;
|
|
function "<" (L,R: DOUBLE_WORD_ARRAY) return boolean;
|
|
function ">=" (L,R: DOUBLE_WORD_ARRAY) return boolean;
|
|
function "<=" (L,R: DOUBLE_WORD_ARRAY) return boolean;
|
|
function "=" (L,R: DOUBLE_WORD_ARRAY) return boolean;
|
|
function "/=" (L,R: DOUBLE_WORD_ARRAY) return boolean;
|
|
function "+" (L,R: DOUBLE_WORD_ARRAY) return DOUBLE_WORD_ARRAY;
|
|
function "+" (L: DOUBLE_WORD_ARRAY, R: natural) return DOUBLE_WORD_ARRAY;
|
|
function "+" (L: natural, R: DOUBLE_WORD_ARRAY) return DOUBLE_WORD_ARRAY;
|
|
function "-" (L,R: DOUBLE_WORD_ARRAY) return DOUBLE_WORD_ARRAY;
|
|
function "-" (L: DOUBLE_WORD_ARRAY, R: natural) return DOUBLE_WORD_ARRAY;
|
|
function "-" (L: natural, R: DOUBLE_WORD_ARRAY) return DOUBLE_WORD_ARRAY;
|
|
|
|
end package;
|
|
|
|
package body rtps_package is
|
|
|
|
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'length(1))-1 downto GUIDPREFIX_WIDTH-(i*ret'length(1))-ret'length(1));
|
|
end loop;
|
|
return ret;
|
|
end function;
|
|
|
|
constant GUIDPREFIX : GUIDPREFIX_TYPE := gen_guidprefix;
|
|
|
|
function convert_string (str : string) 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)), 8)) & std_logic_vector(to_unsigned(character'POS(str(i+1)), 8)) & std_logic_vector(to_unsigned(character'POS(str(i+2)), 8)) & std_logic_vector(to_unsigned(character'POS(str(i+3)), 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
|
|
ret : natural := 0;
|
|
begin
|
|
ret := 0;
|
|
for i in 0 to str'length loop
|
|
for j in 0 to str'length(1)-1 loop
|
|
-- Count Bytes
|
|
ret := ret + 1;
|
|
-- Exit on first NULL byte (NULL Byte included in count)
|
|
if (str(i)(str'length(1)-j*8-1 downto str'length(1)-j*8-8) = (8 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
|
|
-- Limit DATA to MAX UDPv4 Payload Size - RTPS Header (65487 Bytes)
|
|
variable ret : OUTPUT_DATA_TYPE(data(0 to 16371)) := (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;
|
|
ind2 := 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'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);
|
|
-- 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 tmp-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 tmp-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) := ENDPOINT_DEADLINE(i)(0);
|
|
len := len + 1;
|
|
ret.data(ind+len) := 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) := ENDPOINT_LEASE_DURATION(i)(0);
|
|
len := len + 1;
|
|
ret.data(ind+len) := 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) := ENDPOINT_MAX_BLOCKING_TIME(i)(0);
|
|
len := len + 1;
|
|
ret.data(ind+len) := 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
|
|
-- Limit DATA to MAX UDPv4 Payload Size - RTPS Header (65487 Bytes)
|
|
variable ret : OUTPUT_DATA_TYPE(data(0 to 16371)) := (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;
|
|
ind2 := 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 tmp-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 tmp-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) := ENDPOINT_DEADLINE(i)(0);
|
|
len := len + 1;
|
|
ret.data(ind+len) := 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) := ENDPOINT_LEASE_DURATION(i)(0);
|
|
len := len + 1;
|
|
ret.data(ind+len) := 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) := ENDPOINT_MAX_BLOCKING_TIME(i)(0);
|
|
len := len + 1;
|
|
ret.data(ind+len) := 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) := ENDPOINT_LIFESPAN(i)(0);
|
|
len := len + 1;
|
|
ret.data(ind+len) := 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 ENDPOINT_DATA : OUTPUT_DATA_TYPE := gen_writer_endpoint_data;
|
|
|
|
function gen_participant_data return OUTPUT_DATA_TYPE is
|
|
-- Limit DATA to MAX UDPv4 Payload Size - RTPS Header (65487 Bytes)
|
|
variable ret : OUTPUT_DATA_TYPE(data(0 to 16371)) := (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;
|
|
ind2 := 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'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_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 tmp-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) := (31 downto 16 => PROTOCOLVERSION_2_4, others => '0');
|
|
-- VENDORID
|
|
len := len + 1;
|
|
ret.data(ind+len) := PID_VENDORID & std_logic_vector(to_unsigned(4, 16));
|
|
len := len + 1;
|
|
ret.data(ind+len) := (31 downto 16 => VENDORID, others => '0');
|
|
-- 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) := (16 downto 0 => META_IPv4_UNICAST_PORT, 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) := (others => '0');
|
|
len := len + 1;
|
|
ret.data(ind+len) := DEFAULT_IPv4_MULTICAST_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) := (16 downto 0 => META_IPv4_MULTICAST_PORT, 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) := (others => '0');
|
|
len := len + 1;
|
|
ret.data(ind+len) := DEFAULT_IPv4_MULTICAST_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) := (16 downto 0 => USER_IPv4_UNICAST_PORT, 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) := (others => '0');
|
|
len := len + 1;
|
|
ret.data(ind+len) := DEFAULT_IPv4_MULTICAST_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) := (16 downto 0 => USER_IPv4_MULTICAST_PORT, 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) := (others => '0');
|
|
len := len + 1;
|
|
ret.data(ind+len) := DEFAULT_IPv4_MULTICAST_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) := PARTICIPANT_LEASE_DURATION(0);
|
|
len := len + 1;
|
|
ret.data(ind+len) := 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);
|
|
ret1) := seq(31 downto 0);
|
|
return ret;
|
|
end function;
|
|
|
|
function ">" (L,R: DOUBLE_WORD_ARRAY) return boolean is
|
|
begin
|
|
return convert_from_double_word(L) > convert_from_double_word(R);
|
|
end function;
|
|
|
|
function "<" (L,R: DOUBLE_WORD_ARRAY) return boolean is
|
|
begin
|
|
return convert_from_double_word(L) < convert_from_double_word(R);
|
|
end function;
|
|
|
|
function ">=" (L,R: DOUBLE_WORD_ARRAY) return boolean is
|
|
begin
|
|
return convert_from_double_word(L) >= convert_from_double_word(R);
|
|
end function;
|
|
|
|
function "<=" (L,R: DOUBLE_WORD_ARRAY) return boolean is
|
|
begin
|
|
return convert_from_double_word(L) <= convert_from_double_word(R);
|
|
end function;
|
|
|
|
function "=" (L,R: DOUBLE_WORD_ARRAY) return boolean;
|
|
begin
|
|
return convert_from_double_word(L) = convert_from_double_word(R);
|
|
end function;
|
|
|
|
function "/=" (L,R: DOUBLE_WORD_ARRAY) return boolean is
|
|
begin
|
|
return convert_from_double_word(L) /= convert_from_double_word(R);
|
|
end function;
|
|
|
|
function "+" (L,R: DOUBLE_WORD_ARRAY) return DOUBLE_WORD_ARRAY is
|
|
begin
|
|
return convert_to_double_word(convert_from_double_word(L) + convert_from_double_word(R));
|
|
end function;
|
|
|
|
function "+" (L: DOUBLE_WORD_ARRAY, R: natural) return DOUBLE_WORD_ARRAY is
|
|
begin
|
|
return convert_to_double_word(convert_from_double_word(L) + R);
|
|
end function;
|
|
|
|
function "+" (L: natural, R: DOUBLE_WORD_ARRAY) return DOUBLE_WORD_ARRAY is
|
|
begin
|
|
return convert_to_double_word(L + convert_from_double_word(R));
|
|
end function;
|
|
|
|
function "-" (L,R: DOUBLE_WORD_ARRAY) return DOUBLE_WORD_ARRAY is
|
|
begin
|
|
return convert_to_double_word(convert_from_double_word(L) - convert_from_double_word(R));
|
|
end function;
|
|
|
|
function "-" (L: DOUBLE_WORD_ARRAY, R: natural) return DOUBLE_WORD_ARRAY is
|
|
begin
|
|
return convert_to_double_word(convert_from_double_word(L) - R);
|
|
end function;
|
|
|
|
function "-" (L: natural, R: DOUBLE_WORD_ARRAY) return DOUBLE_WORD_ARRAY is
|
|
begin
|
|
return convert_to_double_word(L - convert_from_double_word(R));
|
|
end function;
|
|
|
|
end package body;
|