From a792cb7d8aad27138e2591e998298c2ba379d8f3 Mon Sep 17 00:00:00 2001 From: Greek Date: Fri, 13 Nov 2020 11:52:38 +0100 Subject: [PATCH] * Added testbench package * First rtps_handler Testbench NOTE: Not tested/compiled. --- src/Tests/Level 0/rtps_handler-test1.vhd | 834 ++++++++++ src/rtps_test_package.vhd | 1771 ++++++++++++++++++++++ 2 files changed, 2605 insertions(+) create mode 100644 src/Tests/Level 0/rtps_handler-test1.vhd create mode 100644 src/rtps_test_package.vhd diff --git a/src/Tests/Level 0/rtps_handler-test1.vhd b/src/Tests/Level 0/rtps_handler-test1.vhd new file mode 100644 index 0000000..c4c62d3 --- /dev/null +++ b/src/Tests/Level 0/rtps_handler-test1.vhd @@ -0,0 +1,834 @@ +library ieee; +use ieee.std_logic_1164.all; +use ieee.numeric_std.all; + + +entity rtps_handler-test1 is +end entity; + +architecture testbench of rtps_handler-test1 is + + -- *COMPONENT DECLARATION* + component rtps_handler is + port ( + clk : in std_logic; -- Input Clock + 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(WORD_WIDTH-1 downto 0); -- Input FIFO data signal + data_out : out std_logic_vector(WORD_WIDTH-1 downto 0); -- Output 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_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 component; + + -- *FUNCTION DECLARATION* + + -- *SIGNAL DECLARATION* + signal clk, reset, in_empty, rd_sig, builtin_full, builtin_wr, user_full, user_wr, last_word_out, packet_done : std_logic := '0'; + signal data_in, data_out : std_logic_vector(WORD_WIDTH-1 downto 0) := (others => '0'); + signal stimulus, reference : TEST_PACKET_TYPE := ( + data => (others => (others => '0')), + length => 0 + ); + +begin + + -- Unit Under Test + uut : rtps_handler + port map ( + clk => clk, + reset => reset, + empty => in_empty, + rd => rd_sig, + data_in => data_in, + data_out => data_out, + builtin_full => builtin_full, + builtin_wr => builtin_wr + user_full => user_full, + user_wr => user_wr + last_word_out => last_word_out + ); + + stimulus_prc : process + variable ep : ENDPOINT_DATA_TYPE := DEFAULT_ENDPOINT_DATA; + constant rand_data : TEST_PACKET_TYPE := (length => 2, data => (0 => rand_slv(WORD_WIDTH), 1 => rand_slv(WORD_WIDTH))); + variable rtps_header : RTPS_HEADER_TYPE := DEFAULT_RTPS_HEADER; + variable acknack : RTPS_ACKNACK_SUBMESSAGE_TYPE := DEFAULT_RTPS_ACKNACK_SUBMESSAGE; + variable data : RTPS_DATA_SUBMESSAGE_TYPE := DEFAULT_RTPS_DATA_SUBMESSAGE; + variable gap : RTPS_GAP_SUBMESSAGE_TYPE := DEFAULT_RTPS_GAP_SUBMESSAGE; + variable heartbeat : RTPS_HEARTBEAT_SUBMESSAGE_TYPE := DEFAULT_RTPS_HEARTBEAT_SUBMESSAGE; + variable info_ts : RTPS_INFO_TIMESTAMP_SUBMESSAGE_TYPE := DEFAULT_RTPS_INFO_TIMESTAMP_SUBMESSAGE; + variable pad : RTPS_PAD_SUBMESSAGE_TYPE := DEFAULT_RTPS_PAD_SUBMESSAGE; + variable info_dest : RTPS_INFO_DESTINATION_SUBMESSAGE_TYPE := DEFAULT_RTPS_INFO_DESTINATION_SUBMESSAGE; + variable info_src : RTPS_INFO_SOURCE_SUBMESSAGE_TYPE := DEFAULT_RTPS_INFO_SOURCE_SUBMESSAGE; + variable info_reply : RTPS_INFO_REPLY_SUBMESSAGE_TYPE := DEFAULT_RTPS_INFO_REPLY_SUBMESSAGE; + variable info_reply4 : RTPS_INFO_REPLY_IP4_SUBMESSAGE_TYPE := DEFAULT_RTPS_INFO_REPLY_IP4_SUBMESSAGE; + variable udp_header_meta, udp_header_user : UDP_HEADER_TYPE := DEFAULT_UDP_HEADER; + begin + ep.entityId := rand_slv(ep.entityId'length); + acknack.readerId := ep.entityId; + data.writerId := ep.entityId; + gap.writerId := ep.entityId; + heartbeat.writerId := ep.entityId; + + data.flags(SUBMESSAGE_DATA_FLAG_POS) := '1'; + data.data := rand_data; + + rtps_header.guidPrefix := ep.participant.guidPrefix; + udp_header_meta.dest := DEST_LOC.meta.locator(0); + udp_header_user.dest := DEST_LOC.user.locator(0); + udp_header_meta.src := ep.participant.defaultUnicastLocatorList.locator(0); + udp_header_user.src := ep.participant.defaultUnicastLocatorList.locator(0); + info_dest.guidPrefix := GUIDPREFIX; + info_ts.flags(SUBMESSAGE_INVALIDATE_FLAG_POS) := '0'; + info_ts.timestamp := (unsigned(rand_slv(WORD_WIDTH)),unsigned(rand_slv(WORD_WIDTH))); + pad.submessageLength := int(28,16); + info_reply.unicastLocatorList.numLocators := int(2,32); + info_reply.unicastLocatorList.locator(0) := ( + kind => LOCATOR_KIND_UDPv4, + port_(UDP_PORT_WIDTH-1 downto 0) => rand_slv(UDP_PORT_WIDTH), + addr(IPv4_ADDRESS_WIDTH-1 downto 0) => rand_slv(IPv4_ADDRESS_WIDTH) + ); + info_reply.unicastLocatorList.locator(1) := ( + kind => LOCATOR_KIND_UDPv4, + port_(UDP_PORT_WIDTH-1 downto 0) => (others => '0'), -- Invalid Port + addr(IPv4_ADDRESS_WIDTH-1 downto 0) => rand_slv(IPv4_ADDRESS_WIDTH) + ); + info_reply.multicastLocatorList.numLocators := int(2,32); + info_reply.multicastLocatorList.locator(0) := ( + kind => LOCATOR_KIND_UDPv4, + port_(UDP_PORT_WIDTH-1 downto 0) => rand_slv(UDP_PORT_WIDTH), + addr(IPv4_ADDRESS_WIDTH-1 downto 0) => rand_slv(IPv4_ADDRESS_WIDTH) + ); + info_reply.multicastLocatorList.locator(1) := ( + kind => LOCATOR_KIND_UDPv4, + port_(UDP_PORT_WIDTH-1 downto 0) => rand_slv(UDP_PORT_WIDTH), + addr(IPv4_ADDRESS_WIDTH-1 downto 0) => (others => '0') -- Invalid Addr + ); + info_reply4.unicastLocator := ( + kind => LOCATOR_KIND_UDPv4, + port_(UDP_PORT_WIDTH-1 downto 0) => rand_slv(UDP_PORT_WIDTH), + addr(IPv4_ADDRESS_WIDTH-1 downto 0) => rand_slv(IPv4_ADDRESS_WIDTH) + ); + info_reply4.multicastLocator := ( + kind => LOCATOR_KIND_UDPv4, + port_(UDP_PORT_WIDTH-1 downto 0) => rand_slv(UDP_PORT_WIDTH), + addr(IPv4_ADDRESS_WIDTH-1 downto 0) => rand_slv(IPv4_ADDRESS_WIDTH) + ); + + report "Initiating Test" severity note; + reset <= '1'; + wait until rising_edge(clk); + + + -- *RTPS HEADER* + report "Sending invalid RTPS Header [Packet Size to small]" severity note; + gen_udp_header(udp_header_meta, stimulus); + gen_rtps_header(rtps_header, stimulus); + stimulus.length := length-1; + fix_udp_packet(stimulus); + wait until (packet_done = '1'); + stimulus.length := 0; + reference.length := 0; + + report "Sending invalid RTPS Header [Protocol Missmatch]" severity note; + gen_udp_header(udp_header_meta, stimulus); + rtps_header.protocol := rand_slv(PROTOCOL_WIDTH); + gen_rtps_header(rtps_header, stimulus); + rtps_header.protocol := DEFAULT_RTPS_HEADER.protocol; + gen_data(data, stimulus); + fix_udp_packet(stimulus); + wait until (packet_done = '1'); + stimulus.length := 0; + reference.length := 0; + + report "Sending invalid RTPS Header [Protocol Major Version Missmatch]" severity note; + gen_udp_header(udp_header_meta, stimulus); + rtps_header.version := PROTOCOLVERSION_1_0; + gen_rtps_header(rtps_header, stimulus); + rtps_header.version := DEFAULT_RTPS_HEADER.version; + gen_data(data, stimulus); + fix_udp_packet(stimulus); + wait until (packet_done = '1'); + stimulus.length := 0; + reference.length := 0; + + + -- *DATA SUBMESSAGE* + report "Sending valid DATA [Empty Submessage]" severity note; + gen_udp_header(udp_header_meta, stimulus); + gen_rtps_header(rtps_header, stimulus); + data.flags(SUBMESSAGE_DATA_FLAG_POS) := '0'; + data.data.length := 0; + gen_data(data, stimulus); + data.flags(SUBMESSAGE_DATA_FLAG_POS) := '1'; + data.data := rand_data; + fix_udp_packet(stimulus); + wait until (packet_done = '1'); + stimulus.length := 0; + reference.length := 0; + + report "Sending valid DATA [Meta Traffic, Both Endianness]" severity note; + gen_udp_header(udp_header_meta, stimulus); + gen_rtps_header(rtps_header, stimulus); + gen_data(data, stimulus); + gen_data_out(data, udp_header_meta.src, TRUE, TIME_INVALID, rtps_header.guidPrefix, reference); + data.littleEndian := '1'; + gen_data(data, stimulus); + gen_data_out(data, udp_header_meta.src, TRUE, TIME_INVALID, rtps_header.guidPrefix, reference); + data.littleEndian := '0'; + fix_udp_packet(stimulus); + wait until (packet_done = '1'); + stimulus.length := 0; + reference.length := 0; + + report "Sending valid DATA [User Traffic]" severity note; + gen_udp_header(udp_header_user, stimulus); + gen_rtps_header(rtps_header, stimulus); + gen_data(data, stimulus); + gen_data_out(data, udp_header_user.src, FALSE, TIME_INVALID, rtps_header.guidPrefix, reference); + fix_udp_packet(stimulus); + wait until (packet_done = '1'); + stimulus.length := 0; + reference.length := 0; + + report "Sending valid DATA [Extra Header Bytes]" severity note; + gen_udp_header(udp_header_meta, stimulus); + gen_rtps_header(rtps_header, stimulus); + data.octetsToInlineQos := int(23,16); + gen_data(data, stimulus); + data.octetsToInlineQos := DEFAULT_RTPS_DATA_SUBMESSAGE.octetsToInlineQos; + gen_data_out(data, udp_header_meta.src, TRUE, TIME_INVALID, rtps_header.guidPrefix, reference); + fix_udp_packet(stimulus); + wait until (packet_done = '1'); + stimulus.length := 0; + reference.length := 0; + + report "Sending invalid DATA [DATA and KEY Flag set]" severity note; + gen_udp_header(udp_header_meta, stimulus); + gen_rtps_header(rtps_header, stimulus); + data.flags(SUBMESSAGE_KEY_FLAG_POS) := '1'; + gen_data(data, stimulus); + data.flags(SUBMESSAGE_KEY_FLAG_POS) := '0'; + gen_data_out(data, udp_header_meta.src, TRUE, TIME_INVALID, rtps_header.guidPrefix, reference); + fix_udp_packet(stimulus); + wait until (packet_done = '1'); + stimulus.length := 0; + reference.length := 0; + + report "Sending invalid DATA [Packet Size too small]" severity note; + gen_udp_header(udp_header_meta, stimulus); + gen_rtps_header(rtps_header, stimulus); + gen_data(data, stimulus); + stimulus.length := length-1; + fix_udp_packet(stimulus); + wait until (packet_done = '1'); + stimulus.length := 0; + reference.length := 0; + + report "Sending invalid DATA [Submessage Length too small]" severity note; + gen_udp_header(udp_header_meta, stimulus); + gen_rtps_header(rtps_header, stimulus); + data.submessageLength := int(16,16); + gen_data(data, stimulus); + data.submessageLength := DEFAULT_RTPS_DATA_SUBMESSAGE.submessageLength; + gen_data(data, stimulus); + fix_udp_packet(stimulus); + wait until (packet_done = '1'); + stimulus.length := 0; + reference.length := 0; + + report "Sending invalid DATA [Invalid writerSN]" severity note; + gen_udp_header(udp_header_meta, stimulus); + gen_rtps_header(rtps_header, stimulus); + data.sequenceNumber := (others => (others => '0')); + gen_data(data, stimulus); + data.sequenceNumber := DEFAULT_RTPS_DATA_SUBMESSAGE.sequenceNumber; + gen_data(data, stimulus); + fix_udp_packet(stimulus); + wait until (packet_done = '1'); + stimulus.length := 0; + reference.length := 0; + + + -- *ACKNACK SUBMESSAGE* + report "Sending valid ACKNACK [Meta Traffic, Both Endianness]" severity note; + gen_udp_header(udp_header_meta, stimulus); + gen_rtps_header(rtps_header, stimulus); + gen_acknack(acknack, stimulus); + gen_acknack_out(acknack, udp_header_meta.src, TRUE, rtps_header.guidPrefix, reference); + acknack.littleEndian := '1'; + gen_acknack(acknack, stimulus); + gen_acknack_out(acknack, udp_header_meta.src, TRUE, rtps_header.guidPrefix, reference); + acknack.littleEndian := '0'; + fix_udp_packet(stimulus); + wait until (packet_done = '1'); + stimulus.length := 0; + reference.length := 0; + + report "Sending valid ACKNACK [User Traffic]" severity note; + gen_udp_header(udp_header_user, stimulus); + gen_rtps_header(rtps_header, stimulus); + gen_acknack(acknack, stimulus); + gen_acknack_out(acknack, udp_header_user.src, FALSE, rtps_header.guidPrefix, reference); + fix_udp_packet(stimulus); + wait until (packet_done = '1'); + stimulus.length := 0; + reference.length := 0; + + report "Sending invalid ACKNACK [Packet Size too small]" severity note; + gen_udp_header(udp_header_meta, stimulus); + gen_rtps_header(rtps_header, stimulus); + gen_acknack(acknack, stimulus); + stimulus.length := length-1; + fix_udp_packet(stimulus); + wait until (packet_done = '1'); + stimulus.length := 0; + reference.length := 0; + + report "Sending invalid ACKNACK [Submessage Length too small]" severity note; + gen_udp_header(udp_header_meta, stimulus); + gen_rtps_header(rtps_header, stimulus); + acknack.submessageLength := int(20,16); + gen_acknack(acknack, stimulus); + acknack.submessageLength := DEFAULT_RTPS_ACKNACK_SUBMESSAGE.submessageLength; + gen_data(data, stimulus); + fix_udp_packet(stimulus); + wait until (packet_done = '1'); + stimulus.length := 0; + reference.length := 0; + + report "Sending invalid ACKNACK [ReaderSNState invalid (Base invalid)]" severity note; + gen_udp_header(udp_header_meta, stimulus); + gen_rtps_header(rtps_header, stimulus); + acknack.readerSNState.base := (others => (others => '0')); + gen_acknack(acknack, stimulus); + acknack.readerSNState := DEFAULT_RTPS_ACKNACK_SUBMESSAGE.readerSNState; + gen_data(data, stimulus); + fix_udp_packet(stimulus); + wait until (packet_done = '1'); + stimulus.length := 0; + reference.length := 0; + + report "Sending invalid ACKNACK [ReaderSNState invalid (NumBits invalid)]" severity note; + gen_udp_header(udp_header_meta, stimulus); + gen_rtps_header(rtps_header, stimulus); + acknack.readerSNState.numBits := int(257, 32); + gen_acknack(acknack, stimulus); + acknack.readerSNState := DEFAULT_RTPS_ACKNACK_SUBMESSAGE.readerSNState; + gen_data(data, stimulus); + fix_udp_packet(stimulus); + wait until (packet_done = '1'); + stimulus.length := 0; + reference.length := 0; + + -- *GAP SUBMESSAGE* + report "Sending valid GAP [Meta Traffic, Both Endianness]" severity note; + gen_udp_header(udp_header_meta, stimulus); + gen_rtps_header(rtps_header, stimulus); + gen_gap(gap, stimulus); + gen_gap_out(gap, udp_header_meta.src, TRUE, rtps_header.guidPrefix, reference); + gap.littleEndian := '1'; + gen_gap(gap, stimulus); + gen_gap_out(gap, udp_header_meta.src, TRUE, rtps_header.guidPrefix, reference); + gap.littleEndian := '0'; + fix_udp_packet(stimulus); + wait until (packet_done = '1'); + stimulus.length := 0; + reference.length := 0; + + report "Sending valid GAP [User Traffic]" severity note; + gen_udp_header(udp_header_user, stimulus); + gen_rtps_header(rtps_header, stimulus); + gen_gap(gap, stimulus); + gen_gap_out(gap, udp_header_user.src, FALSE, rtps_header.guidPrefix, reference); + fix_udp_packet(stimulus); + wait until (packet_done = '1'); + stimulus.length := 0; + reference.length := 0; + + report "Sending invalid GAP [Packet Size too small]" severity note; + gen_udp_header(udp_header_meta, stimulus); + gen_rtps_header(rtps_header, stimulus); + gen_gap(gap, stimulus); + stimulus.length := length-1; + fix_udp_packet(stimulus); + wait until (packet_done = '1'); + stimulus.length := 0; + reference.length := 0; + + report "Sending invalid GAP [Submessage Length too small]" severity note; + gen_udp_header(udp_header_meta, stimulus); + gen_rtps_header(rtps_header, stimulus); + gap.submessageLength := int(24,16); + gen_gap(gap, stimulus); + gap.submessageLength := DEFAULT_RTPS_GAP_SUBMESSAGE.submessageLength; + gen_data(data, stimulus); + fix_udp_packet(stimulus); + wait until (packet_done = '1'); + stimulus.length := 0; + reference.length := 0; + + report "Sending invalid GAP [GapStart invalid]" severity note; + gen_udp_header(udp_header_meta, stimulus); + gen_rtps_header(rtps_header, stimulus); + gap.gapStart := (others => (others => '0')); + gen_gap(gap, stimulus); + gap.gapStart := DEFAULT_RTPS_GAP_SUBMESSAGE.gapStart; + gen_data(data, stimulus); + fix_udp_packet(stimulus); + wait until (packet_done = '1'); + stimulus.length := 0; + reference.length := 0; + + report "Sending invalid GAP [GapList invalid (Base invalid)]" severity note; + gen_udp_header(udp_header_meta, stimulus); + gen_rtps_header(rtps_header, stimulus); + gap.gapList.base := (others => (others => '0')); + gen_gap(gap, stimulus); + gap.gapList := DEFAULT_RTPS_GAP_SUBMESSAGE.gapList; + gen_data(data, stimulus); + fix_udp_packet(stimulus); + wait until (packet_done = '1'); + stimulus.length := 0; + reference.length := 0; + + report "Sending invalid GAP [GapList invalid (NumBits invalid)]" severity note; + gen_udp_header(udp_header_meta, stimulus); + gen_rtps_header(rtps_header, stimulus); + gap.gapList.numBits := int(257,32); + gen_gap(gap, stimulus); + gap.gapList := DEFAULT_RTPS_GAP_SUBMESSAGE.gapList; + gen_data(data, stimulus); + fix_udp_packet(stimulus); + wait until (packet_done = '1'); + stimulus.length := 0; + reference.length := 0; + + + -- *HEARTBEAT SUBMESSAGE* + report "Sending valid HEARTBEAT [Meta Traffic, Both Endianness]" severity note; + gen_udp_header(udp_header_meta, stimulus); + gen_rtps_header(rtps_header, stimulus); + gen_heartbeat(heartbeat, stimulus); + gen_heartbeat_out(heartbeat, udp_header_meta.src, TRUE, rtps_header.guidPrefix, reference); + heartbeat.littleEndian := '1'; + gen_heartbeat(heartbeat, stimulus); + gen_heartbeat_out(heartbeat, udp_header_meta.src, TRUE, rtps_header.guidPrefix, reference); + heartbeat.littleEndian := '0'; + fix_udp_packet(stimulus); + wait until (packet_done = '1'); + stimulus.length := 0; + reference.length := 0; + + report "Sending valid HEARTBEAT [User Traffic]" severity note; + gen_udp_header(udp_header_user, stimulus); + gen_rtps_header(rtps_header, stimulus); + gen_heartbeat(heartbeat, stimulus); + gen_heartbeat_out(heartbeat, udp_header_user.src, FALSE, rtps_header.guidPrefix, reference); + fix_udp_packet(stimulus); + wait until (packet_done = '1'); + stimulus.length := 0; + reference.length := 0; + + report "Sending invalid HEARTBEAT [Packet Size too small]" severity note; + gen_udp_header(udp_header_meta, stimulus); + gen_rtps_header(rtps_header, stimulus); + gen_heartbeat(heartbeat, stimulus); + stimulus.length := length-1; + fix_udp_packet(stimulus); + wait until (packet_done = '1'); + stimulus.length := 0; + reference.length := 0; + + report "Sending invalid HEARTBEAT [Submessage Length too small]" severity note; + gen_udp_header(udp_header_meta, stimulus); + gen_rtps_header(rtps_header, stimulus); + heartbeat.submessageLength := int(24,16); + gen_heartbeat(heartbeat, stimulus); + heartbeat.submessageLength := (others => '1'); + gen_data(data, stimulus); + fix_udp_packet(stimulus); + wait until (packet_done = '1'); + stimulus.length := 0; + reference.length := 0; + + report "Sending invalid HEARTBEAT [FirstSN invalid]" severity note; + gen_udp_header(udp_header_meta, stimulus); + gen_rtps_header(rtps_header, stimulus); + heartbeat.firstSN := (others => (others => '0')); + gen_heartbeat(heartbeat, stimulus); + heartbeat.firstSN := DEFAULT_RTPS_HEARTBEAT_SUBMESSAGE.firstSN; + gen_data(data, stimulus); + fix_udp_packet(stimulus); + wait until (packet_done = '1'); + stimulus.length := 0; + reference.length := 0; + + report "Sending invalid HEARTBEAT [LastSN invalid]" severity note; + gen_udp_header(udp_header_meta, stimulus); + gen_rtps_header(rtps_header, stimulus); + heartbeat.lastSN := (others => (others => '1')); + gen_heartbeat(heartbeat, stimulus); + heartbeat.lastSN := DEFAULT_RTPS_HEARTBEAT_SUBMESSAGE.lastSN; + gen_data(data, stimulus); + fix_udp_packet(stimulus); + wait until (packet_done = '1'); + stimulus.length := 0; + reference.length := 0; + + + -- *INFO_SOURCE SUBMESSAGE* + report "Testing INFO_SOURCE interpretation" severity note; + gen_udp_header(udp_header_meta, stimulus); + gen_rtps_header(rtps_header, stimulus); + -- Send valid DATA + gen_data(data, stimulus); + gen_data_out(data, udp_header_meta.src, TRUE, TIME_INVALID, rtps_header.guidPrefix, reference); + -- Send INFO_SOURCE (Change Source GUID Prefix) + info_src.guidPrefix(0) := rand_slv(WORD_WIDTH); + gen_info_src(info_src, stimulus); + -- Send valid DATA + gen_data(data, stimulus); + gen_data_out(data, udp_header_meta.src, TRUE, TIME_INVALID, info_dest.guidPrefix, reference); + -- Send INFO_SOURCE (Change GUID Prefix, Little Endian) + info_src.littleEndian := '1'; + info_src.guidPrefix := ep.participant.guidPrefix; + gen_info_src(info_src, stimulus); + info_src.littleEndian := '0'; + -- Send valid DATA + gen_data(data, stimulus); + gen_data_out(data, udp_header_meta.src, TRUE, TIME_INVALID, ep.participant.guidPrefix, reference); + -- Send INFO_SOURCE [Protocol Major Version Missmatch] + info_src.version := PROTOCOLVERSION_1_0; + gen_info_src(info_src, stimulus); + info_src.version := PROTOCOLVERSION_2_4; + -- Send valid DATA + gen_data(data, stimulus); + fix_udp_packet(stimulus); + wait until (packet_done = '1'); + stimulus.length := 0; + reference.length := 0; + + report "Sending invalid INFO_SOURCE [Submessage Length too small]" severity note; + gen_udp_header(udp_header_meta, stimulus); + gen_rtps_header(rtps_header, stimulus); + info_src.submessageLength := int(16,16); + gen_info_src(info_src, stimulus); + info_src.submessageLength := DEFAULT_RTPS_INFO_SOURCE_SUBMESSAGE.submessageLength; + gen_data(data, stimulus); + fix_udp_packet(stimulus); + wait until (packet_done = '1'); + stimulus.length := 0; + reference.length := 0; + + + -- *INFO_DESTINATION SUBMESSAGE* + report "Testing INFO_DESTINATION interpretation" severity note; + gen_udp_header(udp_header_meta, stimulus); + gen_rtps_header(rtps_header, stimulus); + -- Send valid DATA + gen_data(data, stimulus); + gen_data_out(data, udp_header_meta.src, TRUE, TIME_INVALID, rtps_header.guidPrefix, reference); + -- Send INFO_DESTINATION [Correct GUID Prefix] + gen_info_dest(info_dest, stimulus); + -- Send valid DATA + gen_data(data, stimulus); + gen_data_out(data, udp_header_meta.src, TRUE, TIME_INVALID, info_dest.guidPrefix, reference); + -- Send INFO_DESTINATION [Correct GUID Prefix, Little Endian] + info_dest.littleEndian := '1'; + gen_info_dest(info_dest, stimulus); + info_dest.littleEndian := '0'; + -- Send valid DATA + gen_data(data, stimulus); + gen_data_out(data, udp_header_meta.src, TRUE, TIME_INVALID, info_dest.guidPrefix, reference); + -- Send INFO_DESTINATION [Incorrect GUID Prefix] + info_dest.guidPrefix := rtps_header.guidPrefix; + gen_info_src(info_dest, stimulus); + info_dest.guidPrefix := GUIDPREFIX; + -- Send valid DATA + gen_data(data, stimulus); + fix_udp_packet(stimulus); + wait until (packet_done = '1'); + stimulus.length := 0; + reference.length := 0; + + report "Sending invalid INFO_DESTINATION [Submessage Length too small]" severity note; + gen_udp_header(udp_header_meta, stimulus); + gen_rtps_header(rtps_header, stimulus); + info_dest.submessageLength := int(8,16); + gen_info_dest(info_dest, stimulus); + info_dest.submessageLength := DEFAULT_RTPS_INFO_DESTINATION_SUBMESSAGE.submessageLength; + gen_data(data, stimulus); + fix_udp_packet(stimulus); + wait until (packet_done = '1'); + stimulus.length := 0; + reference.length := 0; + + + -- *INFO_REPLY SUBMESSAGE* + report "Testing INFO_REPLY interpretation" severity note; + gen_udp_header(udp_header_meta, stimulus); + gen_rtps_header(rtps_header, stimulus); + -- Send valid DATA + gen_data(data, stimulus); + gen_data_out(data, udp_header_meta.src, TRUE, TIME_INVALID, rtps_header.guidPrefix, reference); + -- Send INFO_REPLY [Empty Locator Lists] + info_reply.unicastLocatorList.numLocators := int(0,32); + gen_info_reply(info_reply, stimulus); + info_reply.unicastLocatorList.numLocators := int(2,32); + -- Send valid DATA + gen_data(data, stimulus); + gen_data_out(data, udp_header_meta.src, TRUE, TIME_INVALID, info_dest.guidPrefix, reference); + -- Send INFO_REPLY [1 valid Unicast, 1 invalid Unicast] + gen_info_reply(info_reply, stimulus); + -- Send valid DATA + gen_data(data, stimulus); + gen_data_out(data, info_reply.unicastLocatorList.locator(0), TRUE, TIME_INVALID, info_dest.guidPrefix, reference); + -- Send INFO_REPLY [0 Unicast, 1 invalid Multicast, 1 valid Multicast, Little Endian] + info_reply.unicastLocatorList.numLocators := int(0,32); + info_reply.flags(SUBMESSAGE_MULTICAST_FLAG_POS) := '1'; + gen_info_reply(info_reply, stimulus); + info_reply.flags(SUBMESSAGE_MULTICAST_FLAG_POS) := '0'; + info_reply.unicastLocatorList.numLocators := int(2,32); + -- Send valid DATA + gen_data(data, stimulus); + gen_data_out(data, info_reply.multicastLocatorList.locator(0), TRUE, TIME_INVALID, info_dest.guidPrefix, reference); + wait until (packet_done = '1'); + stimulus.length := 0; + reference.length := 0; + + report "Sending invalid INFO_REPLY [Submessage Length too small]" severity note; + gen_udp_header(udp_header_meta, stimulus); + gen_rtps_header(rtps_header, stimulus); + info_reply.submessageLength := int(48,16); + gen_info_reply(info_reply, stimulus); + info_reply.submessageLength := DEFAULT_RTPS_INFO_REPLY_SUBMESSAGE.submessageLength; + gen_data(data, stimulus); + fix_udp_packet(stimulus); + wait until (packet_done = '1'); + stimulus.length := 0; + reference.length := 0; + + + -- *INFO_REPLY_IP4 SUBMESSAGE* + report "Testing INFO_REPLY_IP4 interpretation" severity note; + gen_udp_header(udp_header_meta, stimulus); + gen_rtps_header(rtps_header, stimulus); + -- Send valid DATA + gen_data(data, stimulus); + gen_data_out(data, udp_header_meta.src, TRUE, TIME_INVALID, rtps_header.guidPrefix, reference); + -- Send INFO_REPLY_IP4 [Valid Unicast] + gen_info_reply(info_reply, stimulus); + -- Send valid DATA + gen_data(data, stimulus); + gen_data_out(data, info_reply4.unicastLocator, TRUE, TIME_INVALID, info_dest.guidPrefix, reference); + -- Send INFO_REPLY_IP4 [Invalid Unicast, Valid Multicast, Little Endian] + info_reply4.littleEndian := '1'; + info_reply4.flags(SUBMESSAGE_MULTICAST_FLAG_POS) := '1'; + info_reply4.unicastLocator.addr := (others => '0'); + gen_info_reply(info_reply, stimulus); + info_reply4.littleEndian := '0'; + -- Send valid DATA + gen_data(data, stimulus); + gen_data_out(data, info_reply4.multicastLocator, TRUE, TIME_INVALID, info_dest.guidPrefix, reference); + -- Send INFO_REPLY_IP4 [Invalid Unicast, Invalid Multicast] + gen_data_out(data, info_reply4.multicastLocator, TRUE, TIME_INVALID, info_dest.guidPrefix, reference); -- Generate Reference while locator still valid + info_reply4.multicastLocator.port_ := (others => '0'); + gen_info_reply(info_reply, stimulus); + info_reply4.unicastLocator.addr := rand_slv(IPv4_ADDRESS_WIDTH); + info_reply4.multicastLocator.port_ := rand_slv(UDP_PORT_WIDTH); + info_reply4.flags(SUBMESSAGE_MULTICAST_FLAG_POS) := '0'; + -- Send valid DATA + gen_data(data, stimulus); + fix_udp_packet(stimulus); + wait until (packet_done = '1'); + stimulus.length := 0; + reference.length := 0; + + report "Sending invalid INFO_REPLY_IP4 [Submessage Length too small]" severity note; + gen_udp_header(udp_header_meta, stimulus); + gen_rtps_header(rtps_header, stimulus); + info_reply4.submessageLength := int(4,16); + gen_info_reply_ip4(info_reply4, stimulus); + info_reply4.submessageLength := DEFAULT_RTPS_INFO_REPLY_IP4_SUBMESSAGE.submessageLength; + gen_data(data, stimulus); + fix_udp_packet(stimulus); + wait until (packet_done = '1'); + stimulus.length := 0; + reference.length := 0; + + -- *INFO TS* + report "Testing INFO_TIMESTAMP interpretation" severity note; + gen_udp_header(udp_header_meta, stimulus); + gen_rtps_header(rtps_header, stimulus); + -- Send valid DATA + gen_data(data, stimulus); + gen_data_out(data, udp_header_meta.src, TRUE, TIME_INVALID, info_dest.guidPrefix, reference); + -- Send INFO_TIMESTAMP [Change Timestamp] + gen_info_ts(info_ts, stimulus); + -- Send valid Data + gen_data(data, stimulus); + gen_data_out(data, udp_header_meta.src, TRUE, info_ts.timestamp, info_dest.guidPrefix, reference); + -- Send INFO_TIMESTAMP [Change Timestamp, Little Endian] + info_ts.timestamp(0) := unsigned(rand_slv(WORD_WIDTH)); + info_ts.littleEndian := '1'; + gen_info_ts(info_ts, stimulus); + info_ts.littleEndian := '0'; + -- Send valid DATA + gen_data(data, stimulus); + gen_data_out(data, udp_header_meta.src, TRUE, info_ts.timestamp, info_dest.guidPrefix, reference); + -- Send INFO_TIMESTAMP [Invalidate Timestamp] + info_ts.timestamp(0) := unsigned(rand_slv(WORD_WIDTH)); + info_ts.flags(SUBMESSAGE_INVALIDATE_FLAG_POS) := '1'; + gen_info_ts(info_ts, stimulus); + info_ts.flags(SUBMESSAGE_INVALIDATE_FLAG_POS) := '0'; + -- Send valid DATA + gen_data(data, stimulus); + gen_data_out(data, udp_header_meta.src, TRUE, TIME_INVALID, info_dest.guidPrefix, reference); + fix_udp_packet(stimulus); + wait until (packet_done = '1'); + stimulus.length := 0; + reference.length := 0; + + report "Sending invalid INFO_TMESTAMP [Submessage Length too small]" severity note; + gen_udp_header(udp_header_meta, stimulus); + gen_rtps_header(rtps_header, stimulus); + info_ts.submessageLength := int(4,16); + gen_info_ts(info_ts, stimulus); + info_ts.submessageLength := DEFAULT_RTPS_INFO_REPLY_IP4_SUBMESSAGE.submessageLength; + gen_data(data, stimulus); + fix_udp_packet(stimulus); + wait until (packet_done = '1'); + stimulus.length := 0; + reference.length := 0; + + + -- *PAD* + report "Testing PAD interpretation" severity note; + gen_udp_header(udp_header_meta, stimulus); + gen_rtps_header(rtps_header, stimulus); + -- Send valid DATA + gen_data(data, stimulus); + gen_data_out(data, udp_header_meta.src, TRUE, TIME_INVALID, info_dest.guidPrefix, reference); + -- Send PAD + gen_pad(pad, stimulus); + -- Send valid DATA + gen_data(data, stimulus); + gen_data_out(data, udp_header_meta.src, TRUE, TIME_INVALID, info_dest.guidPrefix, reference); + fix_udp_packet(stimulus); + wait until (packet_done = '1'); + stimulus.length := 0; + reference.length := 0; + + + -- *UNKNOWN* + report "Testing unknown Submessage handling" severity note; + gen_udp_header(udp_header_meta, stimulus); + gen_rtps_header(rtps_header, stimulus); + -- Send valid DATA + gen_data(data, stimulus); + gen_data_out(data, udp_header_meta.src, TRUE, TIME_INVALID, info_dest.guidPrefix, reference); + -- Send valid DATA_FRAG Submessage (DATA_FRAG ignored) + gen_data_frag(DEFAULT_RTPS_DATA_FRAG_SUBMESSAGE, stimulus); + -- Send valid DATA + gen_data(data, stimulus); + gen_data_out(data, udp_header_meta.src, TRUE, TIME_INVALID, info_dest.guidPrefix, reference); + -- Send valid HEARTBEAT_FRAG Submessage (HEARTBEAT_FRAG ignored) + gen_heartbeat_frag(DEFAULT_RTPS_HEARTBEAT_FRAG_SUBMESSAGE, stimulus); + -- Send valid DATA + gen_data(data, stimulus); + gen_data_out(data, udp_header_meta.src, TRUE, TIME_INVALID, info_dest.guidPrefix, reference); + -- Send valid NACK_FRAG Submesage (NACK_FRAG ignored) + gen_nack_frag(DEFAULT_RTPS_NACK_FRAG_SUBMESSAGE, stimulus); + -- Send valid DATA + gen_data(data, stimulus); + gen_data_out(data, udp_header_meta.src, TRUE, TIME_INVALID, info_dest.guidPrefix, reference); + -- Send UNKNOWN Submessage (ignored) + pad.submessageID := (others => '1'); + gen_pad(pad, stimulus); + pad.submessageID := DEFAULT_RTPS_PAD_SUBMESSAGE.submessageID; + -- Send valid DATA + gen_data(data, stimulus); + gen_data_out(data, udp_header_meta.src, TRUE, TIME_INVALID, info_dest.guidPrefix, reference); + fix_udp_packet(stimulus); + wait until (packet_done = '1'); + stimulus.length := 0; + reference.length := 0; + + end process; + + clock_prc : process + begin + clk <= '0'; + wait for 25 ns; + clk <= '1'; + wait for 25 ns; + end process; + + fifo_ctl_prc : process + begin + in_empty <= '0'; + builtin_full <= '0'; + user_full <= '0'; + wait until rising_edge(clk); + in_empty <= '1'; + builtin_full <= '0'; + user_full <= '0'; + wait until rising_edge(clk); + in_empty <= '0'; + builtin_full <= '1'; + user_full <= '0'; + wait until rising_edge(clk); + in_empty <= '0'; + builtin_full <= '0'; + user_full <= '1'; + wait until rising_edge(clk); + end process; + + assert (not (in_empty = '1' and rd_sig = '1')) report "Input FIFO read signal high while empty signal high" severity failure; + assert (not (builtin_full = '1' and builtin_wr = '1')) report "Builtin FIFO write signal high while full signal high" severity failure; + assert (not (user_full = '1' and user_wr = '1')) report "Builtin FIFO write signal high while full signal high" severity failure; + + input_prc : process(all) + signal cnt : natural := 0; + begin + if rising_edge(clk) then + if (reset = '1') then + data_in <= (others => '0'); + cnt <= 0; + packet_done <= '0'; + else + if (cnt = stimulus.length) then + cnt <= 0; + packet_done <= '1'; + elsif (rd_sig = '1') then + data_in <= stimulus.data(cnt); + cnt <= cnt + 1; + packet_done <= '0'; + end if; + end if; + end if; + end process; + + output_prc : process(all) + signal cnt : natural := 0; + begin + if rising_edge(clk) then + if (reset = '1') then + cnt <= 0; + else + assert (cnt <= reference.length) report "Received too many words in output" severity failure; + if ((builtin_wr = '1' or user_wr = '1') and rd_sig = '0') then + assert (data_out = reference.data(cnt)) report "Received unexpected output. Received: " & str(data_out) & ", Expected: " & str(reference.data(cnt)) severity failure; + cnt <= cnt + 1; + end if; + end if; + end if; + end process; + +end architecture; \ No newline at end of file diff --git a/src/rtps_test_package.vhd b/src/rtps_test_package.vhd new file mode 100644 index 0000000..f19fb27 --- /dev/null +++ b/src/rtps_test_package.vhd @@ -0,0 +1,1771 @@ +library ieee; +use ieee.std_logic_1164.all; +use ieee.numeric_std.all; +use ieee.math_real.UNIFORM; +use ieee.math_real.ROUND; + +package rtps_test_package is + + -- converts std_logic into a character + function chr(sl: std_logic) return character; + -- converts std_logic_vector into a string (binary base) + function str(slv: std_logic_vector) return string; + -- converts std_logic into a string + function str(sl: std_logic) return string; + impure function rand_int(min_val, max_val : integer) return integer; + impure function rand_slv(len : integer) return std_logic_vector; + function gen_rand_addr return LOCATOR_TYPE; + function int(n : integer, width : natural) return std_logic_vector; + + constant DEFAULT_GUIDPREFIX := (0 => rand_slv(WORD_WIDTH), 1 => rand_slv(WORD_WIDTH), 2 => rand_slv(WORD_WIDTH)); + constant DEFAULT_ENTITYID := rand_slv(ENTITYID_WIDTH); + + type TEST_PACKET_TYPE is record + -- Limit Packet Size to 2^16 (IPv4 size limit) + data : WORD_ARRAY_TYPE(0 to (2**16)/4); + length : natural; + end record; + + type LOCATOR_TYPE is record + kind : std_logic_vector(LOCATOR_KIND_WIDTH-1 downto 0); + port_ : std_logic_vector(31 downto 0); + addr : std_logic_vector(127 downto 0); + end record; + + constant EMPTY_LOCATOR : LOCATOR_TYPE := ( + kind => LOCATOR_KIND_INVALID, + port_ => (others => '0'), + addr => (others => '0') + ); + + -- Limit Number of Locators to maximum number that fits in a maximum length RTPS Submessage + type LOCATOR_TYPE_ARRAY is array (0 to ((2**16)/4)/6) of LOCATOR_TYPE; + + type LOCATOR_LIST_TYPE is record + numLocators : std_logic_vector(CDR_LONG_WIDTH-1 downto 0); + locator : LOCATOR_TYPE_ARRAY; + end record; + + constant EMPTY_LOCATOR_LIST : LOCATOR_LIST_TYPE := ( + numLocators => (others => '0'), + locator => (others => EMPTY_LOCATOR) + ); + + type SEQUENCENUMBER_SET_TYPE is record + base : SEQUENCENUMBER_TYPE; + numBits : std_logic_vector(CDR_LONG_WIDTH-1 downto 0); + bitmap : std_logic_vector(0 to 255); + end record; + + constant DEFAULT_SEQUENCENUMBER_SET : SEQUENCENUMBER_SET_TYPE := ( + base => FIRST_SEQUENCENUMBER, + numBits => (others => '0'), + bitmap => (others => '0') + ); + + type FRAGMENTNUMBER_SET_TYPE is record + base : std_logic_vector(CDR_LONG_WIDTH-1 downto 0); + numBits : std_logic_vector(CDR_LONG_WIDTH-1 downto 0); + bitmap : std_logic_vector(0 to 255); + end record; + + constant DEFAULT_FRAGMENTNUMBER_SET : FRAGMENTNUMBER_SET_TYPE := ( + base => int(1,CDR_LONG_WIDTH), + numBits => (others => '0'), + bitmap => (others => '0') + ); + + -- Valid Destination Locators + type DEST_LOCATOR_LIST_TYPE is record + meta : LOCATOR_LIST_TYPE; + user : LOCATOR_LIST_TYPE; + end record; + + constant DEST_LOC : DEST_LOCATOR_LIST_TYPE := ( + meta => ( + numLocators => int(4,CDR_LONG_WIDTH), + locator => ( + 0 => ( + kind => LOCATOR_KIND_UDPv4, + port_(UDP_PORT_WIDTH-1 downto 0) => META_IPv4_MULTICAST_PORT, + addr(IPv4_ADDRESS_WIDTH-1 downto 0) => DEFAULT_META_ADDR + ), + 1 => ( + kind => LOCATOR_KIND_UDPv4, + port_(UDP_PORT_WIDTH-1 downto 0) => META_IPv4_UNICAST_PORT, + addr(IPv4_ADDRESS_WIDTH-1 downto 0) => DEFAULT_META_ADDR + ), + 2 => ( + kind => LOCATOR_KIND_UDPv4, + port_(UDP_PORT_WIDTH-1 downto 0) => META_IPv4_MULTICAST_PORT, + addr(IPv4_ADDRESS_WIDTH-1 downto 0) => DEFAULT_ADDR + ), + 3 => ( + kind => LOCATOR_KIND_UDPv4, + port_(UDP_PORT_WIDTH-1 downto 0) => META_IPv4_UNICAST_PORT, + addr(IPv4_ADDRESS_WIDTH-1 downto 0) => DEFAULT_ADDR + ) + ), + user => ( + numLocators => int(2,CDR_LONG_WIDTH), + locator => ( + 0 => ( + kind => LOCATOR_KIND_UDPv4, + port_(UDP_PORT_WIDTH-1 downto 0) => USER_IPv4_MULTICAST_PORT, + addr(IPv4_ADDRESS_WIDTH-1 downto 0) => DEFAULT_ADDR + ), + 1 => ( + kind => LOCATOR_KIND_UDPv4, + port_(UDP_PORT_WIDTH-1 downto 0) => USER_IPv4_UNICAST_PORT, + addr(IPv4_ADDRESS_WIDTH-1 downto 0) => DEFAULT_ADDR + ) + ) + ); + + -- *UDP HEADER* + type UDP_HEADER_TYPE is record + src : LOCATOR_TYPE; + dest : LOCATOR_TYPE; + is_meta : boolean; + end type; + + constant DEFAULT_UDP_HEADER : UDP_HEADER_TYPE := ( + src => EMPTY_LOCATOR, + dest => EMPTY_LOCATOR, + is_meta => FALSE + ); + + procedure gen_udp_header(ref : in UDP_HEADER_TYPE; output : inout TEST_PACKET_TYPE); + procedure fix_udp_packet(output : inout TEST_PACKET_TYPE); + + -- *RTPS HEADER* + type RTPS_HEADER_TYPE is record + protocol : std_logic_vector(PROTOCOL_WIDTH-1 downto 0); + version : std_logic_vector(PROTOCOLVERSION_WIDTH-1 downto 0); + vendorId : std_logic_vector(VENDORID_WIDTH-1 downto 0); + guidPrefix : GUIDPREFIX_TYPE; + end record; + + constant DEFAULT_RTPS_HEADER : RTPS_HEADER_TYPE := ( + protocol => PROTOCOL_RTPS, + version => PROTOCOLVERSION_2_4, + vendorId => VENDORID_UNKNOWN, + guidPrefix => DEFAULT_GUIDPREFIX + ); + + procedure gen_rtps_header( ref : in RTPS_HEADER_TYPE; output : inout TEST_PACKET_TYPE); + + -- *GENERIC RTPS SUBMESSAGE HEADER* + type RTPS_SUBMESSAGE_HEADER_TYPE is record + submessageID : std_logic_vector(SUBMESSAGE_ID_WIDTH-1 downto 0); + flags : std_logic_vector(SUBMESSAGE_FLAGS_WIDTH-1 downto 0); + submessageLength: std_logic_vector(SUBMESSAGE_LENGTH_WIDTH-1 downto 0); + end record; + + procedure gen_rtps_subheader( ref : in RTPS_SUBMESSAGE_HEADER_TYPE; output : inout TEST_PACKET_TYPE); + + -- *ACKNACK* + type RTPS_ACKNACK_SUBMESSAGE_TYPE is record + submessageID : std_logic_vector(SUBMESSAGE_ID_WIDTH-1 downto 0); + flags : std_logic_vector(SUBMESSAGE_FLAGS_WIDTH-1 downto 0); + submessageLength : std_logic_vector(SUBMESSAGE_LENGTH_WIDTH-1 downto 0); + readerId : std_logic_vector(ENTITYID_WIDTH-1 downto 0); + writerId : std_logic_vector(ENTITYID_WIDTH-1 downto 0); + readerSNState : SEQUENCENUMBER_SET_TYPE; + count : std_logic_vector(COUNT_WIDTH-1 downto 0); + end record; + + constant DEFAULT_RTPS_ACKNACK_SUBMESSAGE : RTPS_ACKNACK_SUBMESSAGE_TYPE := ( + submessageID => SID_ACKNACK, + flags => (SUBMESSAGE_ENDIAN_FLAG_POS => '0', SUBMESSAGE_FINAL_FLAG_POS => '1', others => '0'), + submessageLength => (others => '1'), + readerId => DEFAULT_ENTITYID, + writerId => ENTITYID_UNKNOWN, + readerSNState => DEFAULT_SEQUENCENUMBER_SET, + count => int(1,COUNT_WIDTH) + ); + + procedure gen_acknack( ref : in RTPS_ACKNACK_SUBMESSAGE_TYPE; output : inout TEST_PACKET_TYPE); + procedure gen_acknack_out(ref : in RTPS_ACKNACK_SUBMESSAGE_TYPE; loc : in LOCATOR_TYPE; is_meta : in boolean; src_guid : in GUIDPREFIX_TYPE; output : inout TEST_PACKET_TYPE); + + -- *NACK FRAG* + type RTPS_NACK_FRAG_SUBMESSAGE_TYPE is record + submessageID : std_logic_vector(SUBMESSAGE_ID_WIDTH-1 downto 0); + flags : std_logic_vector(SUBMESSAGE_FLAGS_WIDTH-1 downto 0); + submessageLength : std_logic_vector(SUBMESSAGE_LENGTH_WIDTH-1 downto 0); + readerId : std_logic_vector(ENTITYID_WIDTH-1 downto 0); + writerId : std_logic_vector(ENTITYID_WIDTH-1 downto 0); + writerSN : SEQUENCENUMBER_TYPE; + fragmentNumberState : FRAGMENTNUMBER_SET_TYPE; + count : std_logic_vector(COUNT_WIDTH-1 downto 0); + end record; + + constant DEFAULT_RTPS_NACK_FRAG_SUBMESSAGE : RTPS_NACK_FRAG_SUBMESSAGE_TYPE := ( + submessageID => SID_NACK_FRAG, + flags => (SUBMESSAGE_ENDIAN_FLAG_POS => '0', others => '0'), + submessageLength => (others => '1'), + readerId => DEFAULT_ENTITYID, + writerId => ENTITYID_UNKNOWN, + writerSN => FIRST_SEQUENCENUMBER, + fragmentNumberState => DEFAULT_FRAGMENTNUMBER_SET, + count => int(1,COUNT_WIDTH) + ); + + procedure gen_nack_frag( ref : in RTPS_NACK_FRAG_SUBMESSAGE_TYPE; output : inout TEST_PACKET_TYPE); + + -- *DATA* + type RTPS_DATA_SUBMESSAGE_TYPE is record + submessageID : std_logic_vector(SUBMESSAGE_ID_WIDTH-1 downto 0); + flags : std_logic_vector(SUBMESSAGE_FLAGS_WIDTH-1 downto 0); + submessageLength : std_logic_vector(SUBMESSAGE_LENGTH_WIDTH-1 downto 0); + extraFlags : std_logic_vector(SUBMESSAGE_DATA_EXTRA_FLAGS_WIDTH-1 downto 0); + octetsToInlineQos : std_logic_vector(SUBMESSAGE_LENGTH_WIDTH-1 downto 0); + readerId : std_logic_vector(ENTITYID_WIDTH-1 downto 0); + writerId : std_logic_vector(ENTITYID_WIDTH-1 downto 0); + sequenceNumber : SEQUENCENUMBER_TYPE; + data : TEST_PACKET_TYPE; + end record; + + constant DEFAULT_RTPS_DATA_SUBMESSAGE : RTPS_DATA_SUBMESSAGE_TYPE := ( + submessageID => SID_DATA, + flags => (SUBMESSAGE_ENDIAN_FLAG_POS => '0', SUBMESSAGE_INLINE_QOS_FLAG_POS => '0', SUBMESSAGE_DATA_FLAG_POS => '0', SUBMESSAGE_KEY_FLAG_POS => '0', SUBMESSAGE_NON_STANDARD_PAYLOAD_FLAG_POS => '0', others => '0'), + submessageLength => (others => '1'), + extraFlags => (others => '0'), + octetsToInlineQos => int(16, SUBMESSAGE_LENGTH_WIDTH), + readerId => ENTITYID_UNKNOWN, + writerId => DEFAULT_ENTITYID, + sequenceNumber => FIRST_SEQUENCENUMBER, + data => (length => 0, data => (others => (others => '0'))) + ); + + procedure gen_data( ref : in RTPS_DATA_SUBMESSAGE_TYPE; output : inout TEST_PACKET_TYPE); + procedure gen_data_out(ref : in RTPS_DATA_SUBMESSAGE_TYPE; loc : in LOCATOR_TYPE; ts : in TIME_TYPE; is_meta : in boolean; src_guid : in GUIDPREFIX_TYPE; output : inout TEST_PACKET_TYPE); + + -- *DATA FRAG* + type RTPS_DATA_FRAG_SUBMESSAGE_TYPE is record + submessageID : std_logic_vector(SUBMESSAGE_ID_WIDTH-1 downto 0); + flags : std_logic_vector(SUBMESSAGE_FLAGS_WIDTH-1 downto 0); + submessageLength : std_logic_vector(SUBMESSAGE_LENGTH_WIDTH-1 downto 0); + extraFlags : std_logic_vector(SUBMESSAGE_DATA_EXTRA_FLAGS_WIDTH-1 downto 0); + octetsToInlineQos : std_logic_vector(SUBMESSAGE_LENGTH_WIDTH-1 downto 0); + readerId : std_logic_vector(ENTITYID_WIDTH-1 downto 0); + writerId : std_logic_vector(ENTITYID_WIDTH-1 downto 0); + sequenceNumber : SEQUENCENUMBER_TYPE; + fragmentNumber : std_logic_vector(CDR_LONG_WIDTH-1 downto 0); + fragmentsInSubmessage : std_logic_vector(CDR_SHORT_WIDTH-1 downto 0); + fragmentSize : std_logic_vector(CDR_SHORT_WIDTH-1 downto 0); + sampleSize : std_logic_vector(CDR_LONG_WIDTH-1 downto 0); + data : TEST_PACKET_TYPE; + end record; + + constant DEFAULT_RTPS_DATA_FRAG_SUBMESSAGE : RTPS_DATA_FRAG_SUBMESSAGE_TYPE := ( + submessageID => SID_DATA_FRAG, + flags => (SUBMESSAGE_ENDIAN_FLAG_POS => '0', SUBMESSAGE_INLINE_QOS_FLAG_POS => '0', (SUBMESSAGE_KEY_FLAG_POS-1) => '0', (SUBMESSAGE_NON_STANDARD_PAYLOAD_FLAG_POS-1) => '0', others => '0'), + submessageLength => (others => '1'), + extraFlags => (others => '0'), + octetsToInlineQos => int(28, SUBMESSAGE_LENGTH_WIDTH), + readerId => ENTITYID_UNKNOWN, + writerId => DEFAULT_ENTITYID, + sequenceNumber => FIRST_SEQUENCENUMBER, + fragmentNumber => int(1,CDR_SHORT_WIDTH), + fragmentsInSubmessage => int(1,CDR_SHORT_WIDTH), + fragmentSize => (others => '0'), + sampleSize => (others => '0'), + data => (length => 0, data => (others => (others => '0'))) + ); + + procedure gen_data_frag( ref : in RTPS_DATA_FRAG_SUBMESSAGE_TYPE; output : inout TEST_PACKET_TYPE); + + -- *GAP* + type RTPS_GAP_SUBMESSAGE_TYPE is record + submessageID : std_logic_vector(SUBMESSAGE_ID_WIDTH-1 downto 0); + flags : std_logic_vector(SUBMESSAGE_FLAGS_WIDTH-1 downto 0); + submessageLength : std_logic_vector(SUBMESSAGE_LENGTH_WIDTH-1 downto 0); + readerId : std_logic_vector(ENTITYID_WIDTH-1 downto 0); + writerId : std_logic_vector(ENTITYID_WIDTH-1 downto 0); + gapStart : SEQUENCENUMBER_TYPE; + gapList : SEQUENCENUMBER_SET_TYPE; + end record; + + constant DEFAULT_RTPS_GAP_SUBMESSAGE : RTPS_GAP_SUBMESSAGE_TYPE := ( + submessageID => SID_GAP, + flags => (SUBMESSAGE_ENDIAN_FLAG_POS => '0', others => '0'), + submessageLength => (others => '1'), + readerId => ENTITYID_UNKNOWN, + writerId => ENTITYID_UNKNOWN, + gapStart => FIRST_SEQUENCENUMBER, + gapList => DEFAULT_SEQUENCENUMBER_SET + ); + + procedure gen_gap( ref : in RTPS_GAP_SUBMESSAGE_TYPE; output : inout TEST_PACKET_TYPE); + procedure gen_gap_out(ref : in RTPS_GAP_SUBMESSAGE_TYPE; loc : in LOCATOR_TYPE; is_meta : in boolean; src_guid : in GUIDPREFIX_TYPE; output : inout TEST_PACKET_TYPE); + + -- *HEARTBEAT* + type RTPS_HEARTBEAT_SUBMESSAGE_TYPE is record + submessageID : std_logic_vector(SUBMESSAGE_ID_WIDTH-1 downto 0); + flags : std_logic_vector(SUBMESSAGE_FLAGS_WIDTH-1 downto 0); + submessageLength : std_logic_vector(SUBMESSAGE_LENGTH_WIDTH-1 downto 0); + readerId : std_logic_vector(ENTITYID_WIDTH-1 downto 0); + writerId : std_logic_vector(ENTITYID_WIDTH-1 downto 0); + firstSN : SEQUENCENUMBER_TYPE; + lastSN : SEQUENCENUMBER_TYPE; + count : std_logic_vector(COUNT_WIDTH-1 downto 0); + end record; + + constant DEFAULT_RTPS_HEARTBEAT_SUBMESSAGE : RTPS_HEARTBEAT_SUBMESSAGE_TYPE := ( + submessageID => SID_HEARTBEAT, + flags => (SUBMESSAGE_ENDIAN_FLAG_POS => '0', SUBMESSAGE_FINAL_FLAG_POS => '1', SUBMESSAGE_LIVELINESS_FLAG_POS => '0', others => '0'), + submessageLength => (others => '1'), + readerId => ENTITYID_UNKNOWN, + writerId => DEFAULT_ENTITYID, + firstSN => FIRST_SEQUENCENUMBER, + lastSN => (others => (others => '0')), + count => int(1, COUNT_WIDTH), + ); + + procedure gen_heartbeat( ref : in RTPS_HEARTBEAT_SUBMESSAGE_TYPE; output : inout TEST_PACKET_TYPE); + procedure gen_heartbeat_out(ref : in RTPS_HEARTBEAT_SUBMESSAGE_TYPE; loc : in LOCATOR_TYPE; is_meta : in boolean; src_guid : in GUIDPREFIX_TYPE; output : inout TEST_PACKET_TYPE); + + -- *HEARTBEAT FRAG* + type RTPS_HEARTBEAT_FRAG_SUBMESSAGE_TYPE is record + submessageID : std_logic_vector(SUBMESSAGE_ID_WIDTH-1 downto 0); + flags : std_logic_vector(SUBMESSAGE_FLAGS_WIDTH-1 downto 0); + submessageLength : std_logic_vector(SUBMESSAGE_LENGTH_WIDTH-1 downto 0); + readerId : std_logic_vector(ENTITYID_WIDTH-1 downto 0); + writerId : std_logic_vector(ENTITYID_WIDTH-1 downto 0); + writerSN : SEQUENCENUMBER_TYPE; + lastFragmentNum : std_logic_vector(CDR_LONG_WIDTH-1 downto 0); + count : std_logic_vector(COUNT_WIDTH-1 downto 0); + end record; + + constant DEFAULT_RTPS_HEARTBEAT_FRAG_SUBMESSAGE : RTPS_HEARTBEAT__FRAG_SUBMESSAGE_TYPE := ( + submessageID => SID_HEARTBEAT_FRAG, + flags => (SUBMESSAGE_ENDIAN_FLAG_POS => '0', others => '0'), + submessageLength => (others => '1'), + readerId => ENTITYID_UNKNOWN, + writerId => DEFAULT_ENTITYID, + writerSN => FIRST_SEQUENCENUMBER, + lastFragmentNum => int(1,CDR_LONG_WIDTH), + count => int(1, COUNT_WIDTH) + ); + + procedure gen_heartbeat_frag( ref : in RTPS_HEARTBEAT_FRAG_SUBMESSAGE_TYPE; output : inout TEST_PACKET_TYPE); + + -- *INFO DESTINATION* + type RTPS_INFO_DESTINATION_SUBMESSAGE_TYPE is record + submessageID : std_logic_vector(SUBMESSAGE_ID_WIDTH-1 downto 0); + flags : std_logic_vector(SUBMESSAGE_FLAGS_WIDTH-1 downto 0); + submessageLength : std_logic_vector(SUBMESSAGE_LENGTH_WIDTH-1 downto 0); + guidPrefix : GUIDPREFIX_TYPE; + end record; + + constant DEFAULT_RTPS_INFO_DESTINATION_SUBMESSAGE : RTPS_INFO_DESTINATION_SUBMESSAGE_TYPE := ( + submessageID => SID_INFO_DST, + flags => (SUBMESSAGE_ENDIAN_FLAG_POS => '0', others => '0'), + submessageLength => (others => '1'), + guidPrefix => DEFAULT_GUIDPREFIX + ); + + procedure gen_info_dest( ref : in RTPS_INFO_DESTINATION_SUBMESSAGE_TYPE; output : inout TEST_PACKET_TYPE); + + -- *INFO REPLY* + type RTPS_INFO_REPLY_SUBMESSAGE_TYPE is record + submessageID : std_logic_vector(SUBMESSAGE_ID_WIDTH-1 downto 0); + flags : std_logic_vector(SUBMESSAGE_FLAGS_WIDTH-1 downto 0); + submessageLength : std_logic_vector(SUBMESSAGE_LENGTH_WIDTH-1 downto 0); + unicastLocatorList : LOCATOR_LIST_TYPE; + multicastLocatorList: LOCATOR_LIST_TYPE; + end record; + + constant DEFAULT_RTPS_INFO_REPLY_SUBMESSAGE : RTPS_INFO_REPLY_SUBMESSAGE_TYPE := ( + submessageID => SID_INFO_REPLY, + flags => (SUBMESSAGE_ENDIAN_FLAG_POS => '0', SUBMESSAGE_MULTICAST_FLAG_POS => '0', others => '0'), + submessageLength => (others => '1') + unicastLocatorList => EMPTY_LOCATOR_LIST, + multicastLocatorList=> EMPTY_LOCATOR_LIST + ); + + procedure gen_info_reply( ref : in RTPS_INFO_REPLY_SUBMESSAGE_TYPE; output : inout TEST_PACKET_TYPE); + + -- *INFO SOURCE* + type RTPS_INFO_SOURCE_SUBMESSAGE_TYPE is record + submessageID : std_logic_vector(SUBMESSAGE_ID_WIDTH-1 downto 0); + flags : std_logic_vector(SUBMESSAGE_FLAGS_WIDTH-1 downto 0); + submessageLength: std_logic_vector(SUBMESSAGE_LENGTH_WIDTH-1 downto 0); + unused : std_logic_vector(31 downto 0); + version : std_logic_vector(PROTOCOLVERSION_WIDTH-1 downto 0); + vendorId : std_logic_vector(VENDORID_WIDTH-1 downto 0); + guidPrefix : GUIDPREFIX_TYPE; + end record; + + constant DEFAULT_RTPS_INFO_SOURCE_SUBMESSAGE : RTPS_INFO_SOURCE_SUBMESSAGE_TYPE := ( + submessageID => SID_INFO_SRC, + flags => (SUBMESSAGE_ENDIAN_FLAG_POS => '0', others => '0'), + submessageLength=> (others => '1'), + unused => (others => '0'), + version => PROTOCOLVERSION_2_4, + vendorId => VENDORID_UNKNOWN, + guidPrefix => DEFAULT_GUIDPREFIX + ); + + procedure gen_info_src( ref : in RTPS_INFO_SOURCE_SUBMESSAGE_TYPE; output : inout TEST_PACKET_TYPE); + + -- *INFO TIMESTAMP* + type RTPS_INFO_TIMESTAMP_SUBMESSAGE_TYPE is record + submessageID : std_logic_vector(SUBMESSAGE_ID_WIDTH-1 downto 0); + flags : std_logic_vector(SUBMESSAGE_FLAGS_WIDTH-1 downto 0); + submessageLength: std_logic_vector(SUBMESSAGE_LENGTH_WIDTH-1 downto 0); + timestamp : TIME_TYPE; + end record; + + constant DEFAULT_RTPS_INFO_TIMESTAMP_SUBMESSAGE : RTPS_INFO_TIMESTAMP_SUBMESSAGE_TYPE := ( + submessageID => SID_INFO_TS + flags => (SUBMESSAGE_ENDIAN_FLAG_POS => '0', SUBMESSAGE_INVALIDATE_FLAG_POS => '1', others => '0'), + submessageLength=> (others => '1'), + timestamp => (others => (others => '0')); + ); + + procedure gen_info_ts( ref : in RTPS_INFO_TIMESTAMP_SUBMESSAGE_TYPE; output : inout TEST_PACKET_TYPE); + + -- *PAD* + subtype RTPS_PAD_SUBMESSAGE_TYPE is RTPS_SUBMESSAGE_HEADER_TYPE; + + constant DEFAULT_RTPS_PAD_SUBMESSAGE : RTPS_PAD_SUBMESSAGE_TYPE := ( + submessageID => SID_PAD, + flags => (others => '0'), + submessageLength=> (others => '0') + ); + + procedure gen_pad( ref : in RTPS_PAD_SUBMESSAGE_TYPE; output : inout TEST_PACKET_TYPE); + + -- *INFO REPLY IPv4* + type RTPS_INFO_REPLY_IP4_SUBMESSAGE_TYPE is record + submessageID : std_logic_vector(SUBMESSAGE_ID_WIDTH-1 downto 0); + flags : std_logic_vector(SUBMESSAGE_FLAGS_WIDTH-1 downto 0); + submessageLength : std_logic_vector(SUBMESSAGE_LENGTH_WIDTH-1 downto 0); + unicastLocator : LOCATOR_TYPE; + multicastLocator : LOCATOR_TYPE; + end record; + + constant DEFAULT_RTPS_INFO_REPLY_IP4_SUBMESSAGE : RTPS_INFO_REPLY_IP4_SUBMESSAGE_TYPE := ( + submessageID => SID_INFO_REPLY_IP4, + flags => (SUBMESSAGE_ENDIAN_FLAG_POS => '0', SUBMESSAGE_MULTICAST_FLAG_POS => '0', others => '0'), + submessageLength => (others => '1'), + unicastLocator => EMPTY_LOCATOR, + multicastLocator => EMPTY_LOCATOR + ); + + procedure gen_info_reply_ip4( ref : in RTPS_INFO_REPLY_IP4_SUBMESSAGE_TYPE; output : inout TEST_PACKET_TYPE); + + type PARTICIPANT_DATA_TYPE is record + littleEndian : std_logic; + domainId : std_logic_vector(DOMAIN_ID_WIDTH-1 downto 0); + domainTag : STRING_WORD_ARRAY_TYPE; + protocolVersion : std_logic_vector(PROTOCOLVERSION_WIDTH-1 downto 0); + vendorId : std_logic_vector(VENDORID_WIDTH-1 downto 0); + guidPrefix : GUIDPREFIX_TYPE; + entityId : std_logic_vector(ENTITYID_WIDTH-1 downto 0); + expectsInlineQoS : std_logic_vector(CDR_BOOLEAN_WIDTH-1 downto 0); + metatrafficUnicastLocatorList : LOCATOR_LIST_TYPE; + metatrafficMulticastLocatorList : LOCATOR_LIST_TYPE; + defaultUnicastLocatorList : LOCATOR_LIST_TYPE; + defaultMulticastLocatorList : LOCATOR_LIST_TYPE; + leaseDuration : DURATION_TYPE; + manualLivelinessCount : std_logic_vector(CDR_LONG_WIDTH-1 downto 0); + builtinEndpointQoS : std_logic_vector(CDR_LONG_WIDTH-1 downto 0); + availableBuiltinEndpoints : std_logic_vector(CDR_LONG_WIDTH-1 downto 0); + end record; + + constant DEFAULT_PARTICIPANT_DATA : PARTICIPANT_DATA_TYPE := ( + littleEndian => '0', + domainId => (others => '0'), + domainTag => (others => (others => '0')), + protocolVersion => PROTOCOLVERSION_2_4, + vendorId => VENDORID_UNKNOWN, + guidPrefix => GUIDPREFIX_UNKNOWN, + expectsInlineQoS => (others => '0'), + metatrafficUnicastLocatorList => EMPTY_LOCATOR_LIST, + metatrafficMulticastLocatorList => EMPTY_LOCATOR_LIST, + defaultUnicastLocatorList => (numLocators => int(1,CDR_LONG_WIDTH), + locator(0) => gen_rand_addr), + defaultMulticastLocatorList => EMPTY_LOCATOR_LIST, + leaseDuration => DEFAULT_PARTICIPANT_LEASE_DURATION, + manualLivelinessCount => (others => '0'), + builtinEndpointQoS => (others => '0'), + availableBuiltinEndpoints => (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'); + ); + + procedure gen_participant_announcement( ref : in PARTICIPANT_DATA_TYPE; output : inout TEST_PACKET_TYPE); + + type ENDPOINT_DATA_TYPE is record + littleEndian : std_logic; + participant : PARTICIPANT_DATA_TYPE; + entityId : std_logic_vector(ENTITYID_WIDTH-1 downto 0); + topic_name : STRING_WORD_ARRAY_TYPE; + type_name : STRING_WORD_ARRAY_TYPE; + durability : std_logic_vector(CDR_ENUMERATION_WIDTH-1 downto 0); + durability_service_cleanup_delay : std_logic_vector(CDR_LONG_WIDTH-1 downto 0); + durability_service_history : std_logic_vector(CDR_ENUMERATION_WIDTH-1 downto 0); + durability_service_history_depth : std_logic_vector(CDR_LONG_WIDTH-1 downto 0); + durability_service_max_samples : std_logic_vector(CDR_LONG_WIDTH-1 downto 0); + durability_service_max_instances : std_logic_vector(CDR_LONG_WIDTH-1 downto 0); + durability_service_max_samples_per_instances : std_logic_vector(CDR_LONG_WIDTH-1 downto 0); + presentation : std_logic_vector(CDR_ENUMERATION_WIDTH-1 downto 0); + coherent_access : std_logic_vector(CDR_BOOLEAN_WIDTH-1 downto 0); + ordered_access : std_logic_vector(CDR_BOOLEAN_WIDTH-1 downto 0); + deadline : DURATION_TYPE; + latency_budget : DURATION_TYPE; + ownership : std_logic_vector(CDR_ENUMERATION_WIDTH-1 downto 0); + ownership_strength : std_logic_vector() + liveliness : std_logic_vector(CDR_ENUMERATION_WIDTH-1 downto 0); + leaseDuration : DURATION_TYPE; + time_based_filter : DURATION_TYPE; + reliability : std_logic_vector(CDR_ENUMERATION_WIDTH-1 downto 0); + max_blocking_time : std_logic_vector(CDR_LONG_WIDTH-1 downto 0); + transport_priority : std_logic_vector(CDR_LONG_WIDTH-1 downto 0); + lifespan : DURATION_TYPE; + destination_order : std_logic_vector(CDR_ENUMERATION_WIDTH-1 downto 0); + -- Represent Data as Strings (Ease of Use) + user_data : STRING_WORD_ARRAY_TYPE; + topic_data : STRING_WORD_ARRAY_TYPE; + group_data : STRING_WORD_ARRAY_TYPE; + expectsInlineQoS : std_logic_vector(CDR_BOOLEAN_WIDTH-1 downto 0); + unicastLocatorList : LOCATOR_LIST_TYPE; + multicastLocatorList : LOCATOR_LIST_TYPE; + max_size_serialized : std_logic_vector(CDR_LONG_WIDTH-1 downto 0); + end record; + + constant DEFAULT_ENDPOINT_DATA : ENDPOINT_DATA_TYPE := ( + littleEndian => '0', + participant => DEFAULT_PARTICIPANT_DATA, + entityId => DEFAULT_ENTITYID, + topic_name => EMPTY_STRING, + type_name => EMPTY_STRING, + durability => DEFAULT_DURABILITY_QOS, + durability_service_cleanup_delay => DEFAULT_DURABILITY_SERVICE_CLEANUP_DELAY, + durability_service_history => DEFAULT_DURABILITY_SERVICE_HISTORY, + durability_service_history_depth => DEFAULT_DURABILITY_SERVICE_HISTORY_DEPTH, + durability_service_max_samples => DEFAULT_DURABILITY_SERVICE_MAX_SAMPLES, + durability_service_max_instances => DEFAULT_DURABILITY_SERVICE_MAX_INSTANCES, + durability_service_max_samples_per_instances => DEFAULT_DURABILITY_SERVICE_MAX_SAMPLES_PER_INSTANCE, + presentation => DEFAULT_PRESENTATION_QOS, + coherent_access => (0 => boolean_to_std_logic(DEFAULT_COHERENT_ACCESS), others => '0'), + ordered_access => (0 => boolean_to_std_logic(DEFAULT_ORDERED_ACCESS), others => '0'), + deadline => DEFAULT_DEADLINE_QOS, + latency_budget => DEFAULT_LATENCY_BUDGET_QOS, + ownership => DEFAULT_OWNERSHIP_QOS, + ownership_strength => DEFAULT_OWNERSHIP_STRENGTH_QOS, + liveliness => DEFAULT_LIVELINESS_QOS, + leaseDuration => DEFAULT_LEASE_DURATION, + time_based_filter => DEFAULT_TIME_BASED_FILTER_QOS, + reliability => DEFAULT_RELIABILTY_QOS, + max_blocking_time => DEFAULT_MAX_BLOCKING_TIME, + transport_priority => DEFAULT_TRANSPORT_PRIORITY_QOS, + lifespan => DEFAULT_LIFESPAN_QOS, + destination_order => DEFAULT_DESTINATION_ORDER_QOS, + user_data => EMPTY_STRING, + topic_data => EMPTY_STRING, + group_data => EMPTY_STRING, + expectsInlineQoS => (others => '0'), + unicastLocatorList => EMPTY_LOCATOR_LIST, + multicastLocatorList => EMPTY_LOCATOR_LIST, + max_size_serialized => (others => '0') + ); + + procedure gen_endpoint_data( ref : in ENDPOINT_DATA_TYPE; output : inout TEST_PACKET_TYPE); + +end package; + +package body rtps_test_package is + + procedure store_byte(in_off : in natural range 0 to 3; input : in std_logic_vector(WORD_WIDTH-1 downto 0); out_off : in natural range 0 to 3; output : inout TEST_PACKET_TYPE) is + begin + output.data(length)((BYTE_WIDTH*out_off)+BYTE_WIDTH-1 downto (BYTE_WIDTH*out_off)) := input(BYTE_WIDTH*in_off)+BYTE_WIDTH-1 downto (BYTE_WIDTH*in_off) + end procedure; + + procedure gen_udp_header(ref : in UDP_HEADER_TYPE; output : inout TEST_PACKET_TYPE) is + begin + -- Source Port & Destination Port + output.data(length) := ref.src.port_(UDP_PORT_WIDTH-1 downto 0) & ref.dest.port_(UDP_PORT_WIDTH-1 downto 0); + output.length := output.length + 1; + -- Length & Checksum + output.data(length) := (others => '0'); + output.length := output.length + 1; + end procedure; + + procedure fix_udp_packet(output : inout TEST_PACKET_TYPE) is + begin + assert (output.length < 2**UDP_PORT_WIDTH) report "Exceeded maximum UDP Packet Size" severity error; + output.data(31 downto 16) := int(output.length*4, UDP_HEADER_LENGTH_WIDTH); + -- TODO: Calculate Checksum + end procedure; + + procedure gen_rtps_header( ref : in RTPS_HEADER_TYPE; output : inout TEST_PACKET_TYPE) is + begin + -- Protocol + output.data(length) := ref.protocol; + output.length := output.length + 1; + -- Protocol Version & Vendor ID + output.data(length) := ref.version & ref.vendorId; + output.length := output.length + 1; + -- GUID Prefix + output.data(length) := ref.guidPrefix(0); + output.length := output.length + 1; + output.data(length) := ref.guidPrefix(1); + output.length := output.length + 1; + output.data(length) := ref.guidPrefix(2); + output.length := output.length + 1; + end procedure; + + procedure gen_rtps_subheader( ref : in RTPS_SUBMESSAGE_HEADER_TYPE; output : inout TEST_PACKET_TYPE) is + begin + -- Submessage ID & Submessage Flags & Submessage Length + output.data(length) := ref.submessageID & ref.flags & endian_swap(ref.flags(SUBMESSAGE_ENDIAN_FLAG_POS), ref.submessageLength); + output.length := output.length + 1; + end procedure; + + procedure gen_acknack( ref : in RTPS_ACKNACK_SUBMESSAGE_TYPE; output : inout TEST_PACKET_TYPE) is + variable start : natural := 0; + begin + start := output.length; + -- Submessage ID & Submessage Flags & Submessage Length + output.data(length) := ref.submessageID & ref.flags & endian_swap(ref.flags(SUBMESSAGE_ENDIAN_FLAG_POS), ref.submessageLength); + output.length := output.length + 1; + -- Reader ID + output.data(length) := ref.readerId; + output.length := output.length + 1; + -- Writer ID + output.data(length) := ref.writerId; + output.length := output.length + 1; + -- Reader State (Base) + output.data(length) := endian_swap(ref.flags(SUBMESSAGE_ENDIAN_FLAG_POS), std_logic_vector(ref.readerSNState.base(0))); + output.length := output.length + 1; + output.data(length) := endian_swap(ref.flags(SUBMESSAGE_ENDIAN_FLAG_POS), std_logic_vector(ref.readerSNState.base(1))); + output.length := output.length + 1; + -- Reader State (NumBits) + assert (unsigned(ref.readerSNState.numBits) > 256) report "ACKNACK: readerSNState.numbits is higher than 256." severity warning; + output.data(length) := endian_swap(ref.flags(SUBMESSAGE_ENDIAN_FLAG_POS), ref.readerSNState.numBits); + output.length := output.length + 1; + -- Reader State (Bitmap) + for i in 0 to round_div(to_integer(unsigned(ref.readerSNState.numBits)),32)-1 loop + if (i < MAX_BITMAP_WIDTH/WORD_WIDTH) then + output.data(length) := endian_swap(ref.flags(SUBMESSAGE_ENDIAN_FLAG_POS), ref.readerSNState.bitmap(i*32 to i*32+31)); + output.length := output.length + 1; + end if; + end loop; + -- Count + output.data(length) := endian_swap(ref.flags(SUBMESSAGE_ENDIAN_FLAG_POS), ref.count); + output.length := output.length + 1; + -- Fix Submessage Length + if (ref.submessageLength = (ref.submessageLength'range => '1')) then + output.data(start)(SUBMESSAGE_LENGTH_WIDTH-1 downto 0) := endian_swap(ref.flags(SUBMESSAGE_ENDIAN_FLAG_POS), int(output.length-start-1,SUBMESSAGE_LENGTH_WIDTH)); + -- Fix Packet Length + else + output.length := start + to_integer(ref.submessageLength); + end if; + end procedure; + + procedure gen_acknack_out(ref : in RTPS_ACKNACK_SUBMESSAGE_TYPE; loc : in LOCATOR_TYPE; is_meta : in boolean; src_guid : in GUIDPREFIX_TYPE; output : inout TEST_PACKET_TYPE) is + begin + -- Opcode & Flags & Source Port + output.data(length) := ref.submessageID & ref.flags & loc.port_(UDP_PORT_WIDTH-1 downto 0); + output.length := output.length + 1; + -- Source Address + output.data(length) := ref.loc.addr(IPv4_ADDRESS_WIDTH-1 downto 0); + output.length := output.length + 1; + -- Source Entity ID + output.data(length) := ref.readerId; + output.length := output.length + 1; + -- Source GUID Prefix + output.data(length) := src_guid(0); + output.length := output.length + 1; + output.data(length) := src_guid(1); + output.length := output.length + 1; + output.data(length) := src_guid(2); + output.length := output.length + 1; + -- Destination Enity ID + if (is_meta) then + output.data(length) := ref.writerId; + output.length := output.length + 1; + end if; + -- ACKNACK PAYLOAD + -- Reader State (Base) + output.data(length) := ref.readerSNState.base(0); + output.length := output.length + 1; + output.data(length) := ref.readerSNState.base(1); + output.length := output.length + 1; + -- Reader State (NumBits) + output.data(length) := ref.readerSNState.numBits; + output.length := output.length + 1; + -- Reader State (Bitmap) + for i in 0 to round_div(to_integer(unsigned(ref.readerSNState.numBits)),32)-1 loop + output.data(length) := ref.readerSNState.bitmap(i*32 to i*32+31); + output.length := output.length + 1; + end loop; + -- Count + output.data(length) := ref.count; + output.length := output.length + 1; + end procedure; + + procedure gen_nack_frag( ref : in RTPS_NACK_FRAG_SUBMESSAGE_TYPE; output : inout TEST_PACKET_TYPE) is + variable start : natural := 0; + begin + start := output.length; + -- Submessage ID & Submessage Flags & Submessage Length + output.data(length) := ref.submessageID & ref.flags & endian_swap(ref.flags(SUBMESSAGE_ENDIAN_FLAG_POS), ref.submessageLength); + output.length := output.length + 1; + -- Reader ID + output.data(length) := ref.readerId; + output.length := output.length + 1; + -- Writer ID + output.data(length) := ref.writerId; + output.length := output.length + 1; + -- Writer Sequence Number + output.data(length) := endian_swap(ref.flags(SUBMESSAGE_ENDIAN_FLAG_POS), std_logic_vector(ref.writerSN(0))); + output.length := output.length + 1; + output.data(length) := endian_swap(ref.flags(SUBMESSAGE_ENDIAN_FLAG_POS), std_logic_vector(ref.writerSN(1))); + output.length := output.length + 1; + -- FragmentNumber State (Base) + output.data(length) := endian_swap(ref.flags(SUBMESSAGE_ENDIAN_FLAG_POS), ref.fragmentNumberState.base); + output.length := output.length + 1; + -- Reader State (NumBits) + assert (unsigned(ref.fragmentNumberState.numBits) > 256) report "ACKNACK: fragmentNumberState.numbits is higher than 256." severity warning; + output.data(length) := endian_swap(ref.flags(SUBMESSAGE_ENDIAN_FLAG_POS), ref.fragmentNumberState.numBits); + output.length := output.length + 1; + -- Reader State (Bitmap) + for i in 0 to round_div(to_integer(unsigned(ref.fragmentNumberState.numBits)),32)-1 loop + if (i < MAX_BITMAP_WIDTH/WORD_WIDTH) then + output.data(length) := endian_swap(ref.flags(SUBMESSAGE_ENDIAN_FLAG_POS), ref.fragmentNumberState.bitmap(i*32 to i*32+31)); + output.length := output.length + 1; + end if; + end loop; + -- Count + output.data(length) := endian_swap(ref.flags(SUBMESSAGE_ENDIAN_FLAG_POS), ref.count); + output.length := output.length + 1; + -- Fix Submessage Length + if (ref.submessageLength = (ref.submessageLength'range => '1')) then + output.data(start)(SUBMESSAGE_LENGTH_WIDTH-1 downto 0) := endian_swap(ref.flags(SUBMESSAGE_ENDIAN_FLAG_POS), int(output.length-start-1,SUBMESSAGE_LENGTH_WIDTH)); + -- Fix Packet Length + else + output.length := start + to_integer(ref.submessageLength); + end if; + end procedure; + + procedure gen_data( ref : in RTPS_DATA_SUBMESSAGE_TYPE; output : inout TEST_PACKET_TYPE) is + variable start : natural := 0; + variable tmp : natural := 0; + variable tmp2 : natural := 0; + begin + start := output.length; + -- Submessage ID & Submessage Flags & Submessage Length + output.data(length) := ref.submessageID & ref.flags & endian_swap(ref.flags(SUBMESSAGE_ENDIAN_FLAG_POS), ref.submessageLength); + output.length := output.length + 1; + -- Extra Flags & octetsToInlineQos + output.data(length) := ref.extraFlags & endian_swap(ref.flags(SUBMESSAGE_ENDIAN_FLAG_POS), ref.octetsToInlineQos); + output.length := output.length + 1; + -- Reader ID + output.data(length) := ref.readerId; + output.length := output.length + 1; + -- Writer ID + output.data(length) := ref.writerId; + output.length := output.length + 1; + -- Sequence Number + output.data(length) := endian_swap(ref.flags(SUBMESSAGE_ENDIAN_FLAG_POS), std_logic_vector(ref.sequenceNumber(0))); + output.length := output.length + 1; + output.data(length) := endian_swap(ref.flags(SUBMESSAGE_ENDIAN_FLAG_POS), std_logic_vector(ref.sequenceNumber(1))); + output.length := output.length + 1; + -- EXTRA HEADER + tmp := to_integer(unsigned(ref.octetsToInlineQos)) - 16; + if (tmp > 0) then + for i in 0 to tmp-1 loop + store_byte(i mod 4, output, i mod 4, rand_slv(WORD_WIDTH)); + if (i mod 4 = 3) then + output.length := output.length + 1; + output.data(length) := (others => '0'); + end if; + end loop; + end if; + -- DATA + if (ref.data.length > 0) then + assert ((ref.flags(SUBMESSAGE_DATA_FLAG_POS) or ref.flags(SUBMESSAGE_INLINE_QOS_FLAG_POS) or ref.flags(SUBMESSAGE_KEY_FLAG_POS)) = '1') report "DATA: Writing serialized payload with no flags." severity warning; + for i in 0 to (ref.data.length*4)-1 loop + store_byte((i+tmp) mod 4, output, i mod 4, ref.data.data(i/4)); + if ((i+tmp) mod 4 = 3) then + output.length := output.length + 1; + output.data(length) := (others => '0'); + end if; + end loop; + end if; + -- Fix Alignement + if ((tmp + ref.data.length*4) mod 4 /= 0) then + output.length := output.length + 1; + end if; + -- Fix Submessage Length + if (ref.submessageLength = (ref.submessageLength'range => '1')) then + output.data(start)(SUBMESSAGE_LENGTH_WIDTH-1 downto 0) := endian_swap(ref.flags(SUBMESSAGE_ENDIAN_FLAG_POS), int(output.length-start-1,SUBMESSAGE_LENGTH_WIDTH)); + -- Fix Packet Length + else + output.length := start + to_integer(ref.submessageLength); + end if; + end procedure; + + procedure gen_data_out(ref : in RTPS_DATA_SUBMESSAGE_TYPE; loc : in LOCATOR_TYPE; ts : in TIME_TYPE; is_meta : in boolean; src_guid : in GUIDPREFIX_TYPE; output : inout TEST_PACKET_TYPE) is + begin + -- Opcode & Flags & Source Port + output.data(length) := ref.submessageID & ref.flags & loc.port_(UDP_PORT_WIDTH-1 downto 0); + output.length := output.length + 1; + -- Source Address + output.data(length) := ref.loc.addr(IPv4_ADDRESS_WIDTH-1 downto 0); + output.length := output.length + 1; + -- Source Entity ID + output.data(length) := ref.writerId; + output.length := output.length + 1; + -- Source GUID Prefix + output.data(length) := src_guid(0); + output.length := output.length + 1; + output.data(length) := src_guid(1); + output.length := output.length + 1; + output.data(length) := src_guid(2); + output.length := output.length + 1; + -- Destination Enity ID + if (is_meta) then + output.data(length) := ref.readerId; + output.length := output.length + 1; + end if; + -- Sequence Number + output.data(length) := std_logic_vector(ref.sequenceNumber(0)); + output.length := output.length + 1; + output.data(length) := std_logic_vector(ref.sequenceNumber(1)); + output.length := output.length + 1; + -- Timestamp + if (not is_meta) then + output.data(length) := std_logic_vector(ts(0)); + output.length := output.length + 1; + output.data(length) := std_logic_vector(ts(1)); + output.length := output.length + 1; + end if; + -- DATA PAYLOAD + if (ref.data.length > 0) then + for i in 0 to ref.data.length-1 loop + output.data(length) := ref.data.data(i); + output.length := output.length + 1; + end loop; + end if; + end procedure; + + procedure gen_data_frag( ref : in RTPS_DATA_FRAG_SUBMESSAGE_TYPE; output : inout TEST_PACKET_TYPE) is + variable start : natural := 0; + variable tmp : natural := 0; + varibale off : natural := 0; + begin + start := output.length; + -- Submessage ID & Submessage Flags & Submessage Length + output.data(length) := ref.submessageID & ref.flags & endian_swap(ref.flags(SUBMESSAGE_ENDIAN_FLAG_POS), ref.submessageLength); + output.length := output.length + 1; + -- Extra Flags & octetsToInlineQos + output.data(length) := ref.extraFlags & endian_swap(ref.flags(SUBMESSAGE_ENDIAN_FLAG_POS), ref.octetsToInlineQos); + output.length := output.length + 1; + -- Reader ID + output.data(length) := ref.readerId; + output.length := output.length + 1; + -- Writer ID + output.data(length) := ref.writerId; + output.length := output.length + 1; + -- Sequence Number + output.data(length) := endian_swap(ref.flags(SUBMESSAGE_ENDIAN_FLAG_POS), std_logic_vector(ref.sequenceNumber(0))); + output.length := output.length + 1; + output.data(length) := endian_swap(ref.flags(SUBMESSAGE_ENDIAN_FLAG_POS), std_logic_vector(ref.sequenceNumber(1))); + output.length := output.length + 1; + -- Fragment Number + output.data(length) := endian_swap(ref.flags(SUBMESSAGE_ENDIAN_FLAG_POS), ref.fragmentNumber); + output.length := output.length + 1; + -- FragmentsinSubmessage & FragmentSize + output.data(length) := endian_swap(ref.flags(SUBMESSAGE_ENDIAN_FLAG_POS), ref.fragmentsInSubmessage) & endian_swap(ref.flags(SUBMESSAGE_ENDIAN_FLAG_POS), ref.fragmentSize); + output.length := output.length + 1; + -- EXTRA HEADER + tmp := to_integer(unsigned(ref.octetsToInlineQos)) - 16; + if (tmp > 0) then + for i in 0 to tmp-1 loop + store_byte(i mod 4, output, i mod 4, rand_slv(WORD_WIDTH)); + if (i mod 4 = 3) then + output.length := output.length + 1; + output.data(length) := (others => '0'); + end if; + end loop; + end if; + -- DATA + if (ref.data.length > 0) then + assert ((ref.flags(SUBMESSAGE_INLINE_QOS_FLAG_POS) or ref.flags(SUBMESSAGE_KEY_FLAG_POS-1)) = '1') report "DATA_FRAG: Writing serialized payload with no flags." severity warning; + for i in 0 to (ref.data.length*4)-1 loop + store_byte((i+tmp) mod 4, output, i mod 4, ref.data.data(i/4)); + if ((i+tmp) mod 4 = 3) then + output.length := output.length + 1; + output.data(length) := (others => '0'); + end if; + end loop; + end if; + -- Fix Alignement + if ((tmp + ref.data.length*4) mod 4 /= 0) then + output.length := output.length + 1; + end if; + -- Fix Submessage Length + if (ref.submessageLength = (ref.submessageLength'range => '1')) then + output.data(start)(SUBMESSAGE_LENGTH_WIDTH-1 downto 0) := endian_swap(ref.flags(SUBMESSAGE_ENDIAN_FLAG_POS), int(output.length-start-1,SUBMESSAGE_LENGTH_WIDTH)); + -- Fix Packet Length + else + output.length := start + to_integer(ref.submessageLength); + end if; + end procedure; + + procedure gen_gap( ref : in RTPS_GAP_SUBMESSAGE_TYPE; output : inout TEST_PACKET_TYPE) is + variable start : natural := 0; + begin + start := output.length; + -- Submessage ID & Submessage Flags & Submessage Length + output.data(length) := ref.submessageID & ref.flags & endian_swap(ref.flags(SUBMESSAGE_ENDIAN_FLAG_POS), ref.submessageLength); + output.length := output.length + 1; + -- Reader ID + output.data(length) := ref.readerId; + output.length := output.length + 1; + -- Writer ID + output.data(length) := ref.writerId; + output.length := output.length + 1; + -- Gap Start + output.data(length) := endian_swap(ref.flags(SUBMESSAGE_ENDIAN_FLAG_POS), std_logic_vector(ref.gapStart(0))); + output.length := output.length + 1; + output.data(length) := endian_swap(ref.flags(SUBMESSAGE_ENDIAN_FLAG_POS), std_logic_vector(ref.gapStart(1))); + output.length := output.length + 1; + -- Gap List (Base) + output.data(length) := endian_swap(ref.flags(SUBMESSAGE_ENDIAN_FLAG_POS), std_logic_vector(ref.gapList.base(0))); + output.length := output.length + 1; + output.data(length) := endian_swap(ref.flags(SUBMESSAGE_ENDIAN_FLAG_POS), std_logic_vector(ref.gapList.base(1))); + output.length := output.length + 1; + -- Gap List (NumBits) + assert (unsigned(ref.gapList.numBits) > 256) report "GAP: gapList.numbits is higher than 256." severity warning; + output.data(length) := endian_swap(ref.flags(SUBMESSAGE_ENDIAN_FLAG_POS), ref.gapList.numBits); + output.length := output.length + 1; + -- Gap List (Bitmap) + for i in 0 to round_div(to_integer(unsigned(ref.gapList.numBits)),32)-1 loop + if (i < MAX_BITMAP_WIDTH/WORD_WIDTH) then + output.data(length) := endian_swap(ref.flags(SUBMESSAGE_ENDIAN_FLAG_POS), ref.gapList.bitmap(i*32 to i*32+31)); + output.length := output.length + 1; + end if; + end loop; + -- Fix Submessage Length + if (ref.submessageLength = (ref.submessageLength'range => '1')) then + output.data(start)(SUBMESSAGE_LENGTH_WIDTH-1 downto 0) := endian_swap(ref.flags(SUBMESSAGE_ENDIAN_FLAG_POS), int(output.length-start-1,SUBMESSAGE_LENGTH_WIDTH)); + -- Fix Packet Length + else + output.length := start + to_integer(ref.submessageLength); + end if; + end procedure; + + procedure gen_gap_out(ref : in RTPS_GAP_SUBMESSAGE_TYPE; loc : in LOCATOR_TYPE; is_meta : in boolean; src_guid : in GUIDPREFIX_TYPE; output : inout TEST_PACKET_TYPE) is + begin + -- Opcode & Flags & Source Port + output.data(length) := ref.submessageID & ref.flags & loc.port_(UDP_PORT_WIDTH-1 downto 0); + output.length := output.length + 1; + -- Source Address + output.data(length) := ref.loc.addr(IPv4_ADDRESS_WIDTH-1 downto 0); + output.length := output.length + 1; + -- Source Entity ID + output.data(length) := ref.writerId; + output.length := output.length + 1; + -- Source GUID Prefix + output.data(length) := src_guid(0); + output.length := output.length + 1; + output.data(length) := src_guid(1); + output.length := output.length + 1; + output.data(length) := src_guid(2); + output.length := output.length + 1; + -- Destination Enity ID + if (is_meta) then + output.data(length) := ref.readerId; + output.length := output.length + 1; + end if; + -- GAP PAYLOAD + -- Gap Start + output.data(length) := ref.gapStart(0); + output.length := output.length + 1; + output.data(length) := ref.gapStart(1); + output.length := output.length + 1; + -- Gap List (Base) + output.data(length) := ref.gapList.base(0); + output.length := output.length + 1; + output.data(length) := ref.gapList.base(1); + output.length := output.length + 1; + -- Gap List (NumBits) + output.data(length) := ref.gapList.numBits; + output.length := output.length + 1; + -- Gap List (Bitmap) + for i in 0 to round_div(to_integer(unsigned(ref.gapList.numBits)),32)-1 loop + output.data(length) := ref.gapList.bitmap(i*32 to i*32+31); + output.length := output.length + 1; + end loop; + end procedure; + + procedure gen_heartbeat( ref : in RTPS_HEARTBEAT_SUBMESSAGE_TYPE; output : inout TEST_PACKET_TYPE) is + variable start : natural := 0; + begin + start := output.length; + -- Submessage ID & Submessage Flags & Submessage Length + output.data(length) := ref.submessageID & ref.flags & endian_swap(ref.flags(SUBMESSAGE_ENDIAN_FLAG_POS), ref.submessageLength); + output.length := output.length + 1; + -- Reader ID + output.data(length) := ref.readerId; + output.length := output.length + 1; + -- Writer ID + output.data(length) := ref.writerId; + output.length := output.length + 1; + -- First Sequence Number + output.data(length) := endian_swap(ref.flags(SUBMESSAGE_ENDIAN_FLAG_POS), std_logic_vector(ref.firstSN(0))); + output.length := output.length + 1; + output.data(length) := endian_swap(ref.flags(SUBMESSAGE_ENDIAN_FLAG_POS), std_logic_vector(ref.firstSN(1))); + output.length := output.length + 1; + -- Last Sequence Number + output.data(length) := endian_swap(ref.flags(SUBMESSAGE_ENDIAN_FLAG_POS), std_logic_vector(ref.lastSN(0))); + output.length := output.length + 1; + output.data(length) := endian_swap(ref.flags(SUBMESSAGE_ENDIAN_FLAG_POS), std_logic_vector(ref.lastSN(1))); + output.length := output.length + 1; + -- Count + output.data(length) := endian_swap(ref.flags(SUBMESSAGE_ENDIAN_FLAG_POS), ref.count); + output.length := output.length + 1; + -- Fix Submessage Length + if (ref.submessageLength = (ref.submessageLength'range => '1')) then + output.data(start)(SUBMESSAGE_LENGTH_WIDTH-1 downto 0) := endian_swap(ref.flags(SUBMESSAGE_ENDIAN_FLAG_POS), int(output.length-start-1,SUBMESSAGE_LENGTH_WIDTH)); + -- Fix Packet Length + else + output.length := start + to_integer(ref.submessageLength); + end if; + end procedure; + + procedure gen_heartbeat_out(ref : in RTPS_HEARTBEAT_SUBMESSAGE_TYPE; loc : in LOCATOR_TYPE; is_meta : in boolean; src_guid : in GUIDPREFIX_TYPE; output : inout TEST_PACKET_TYPE) is + begin + -- Opcode & Flags & Source Port + output.data(length) := ref.submessageID & ref.flags & loc.port_(UDP_PORT_WIDTH-1 downto 0); + output.length := output.length + 1; + -- Source Address + output.data(length) := ref.loc.addr(IPv4_ADDRESS_WIDTH-1 downto 0); + output.length := output.length + 1; + -- Source Entity ID + output.data(length) := ref.writerId; + output.length := output.length + 1; + -- Source GUID Prefix + output.data(length) := src_guid(0); + output.length := output.length + 1; + output.data(length) := src_guid(1); + output.length := output.length + 1; + output.data(length) := src_guid(2); + output.length := output.length + 1; + -- Destination Enity ID + if (is_meta) then + output.data(length) := ref.readerId; + output.length := output.length + 1; + end if; + -- HEARTBEAT PAYLOAD-- First Sequence Number + output.data(length) := ref.firstSN(0); + output.length := output.length + 1; + output.data(length) := ref.firstSN(1); + output.length := output.length + 1; + -- Last Sequence Number + output.data(length) := ref.lastSN(0); + output.length := output.length + 1; + output.data(length) := ref.lastSN(1); + output.length := output.length + 1; + -- Count + output.data(length) := ref.count; + output.length := output.length + 1; + end procedure; + + procedure gen_heartbeat_frag( ref : in RTPS_HEARTBEAT_FRAG_SUBMESSAGE_TYPE; output : inout TEST_PACKET_TYPE) is + variable start : natural := 0; + begin + start := output.length; + -- Submessage ID & Submessage Flags & Submessage Length + output.data(length) := ref.submessageID & ref.flags & endian_swap(ref.flags(SUBMESSAGE_ENDIAN_FLAG_POS), ref.submessageLength); + output.length := output.length + 1; + -- Reader ID + output.data(length) := ref.readerId; + output.length := output.length + 1; + -- Writer ID + output.data(length) := ref.writerId; + output.length := output.length + 1; + -- Sequence Number + output.data(length) := endian_swap(ref.flags(SUBMESSAGE_ENDIAN_FLAG_POS), std_logic_vector(ref.writerSN(0))); + output.length := output.length + 1; + output.data(length) := endian_swap(ref.flags(SUBMESSAGE_ENDIAN_FLAG_POS), std_logic_vector(ref.writerSN(1))); + output.length := output.length + 1; + -- Last Fargment Number + output.data(length) := endian_swap(ref.flags(SUBMESSAGE_ENDIAN_FLAG_POS), ref.lastFragmentNum); + output.length := output.length + 1; + -- Count + output.data(length) := ref.count; + output.length := output.length + 1; + -- Fix Submessage Length + if (ref.submessageLength = (ref.submessageLength'range => '1')) then + output.data(start)(SUBMESSAGE_LENGTH_WIDTH-1 downto 0) := endian_swap(ref.flags(SUBMESSAGE_ENDIAN_FLAG_POS), int(output.length-start-1,SUBMESSAGE_LENGTH_WIDTH)); + -- Fix Packet Length + else + output.length := start + to_integer(ref.submessageLength); + end if; + end procedure; + + procedure gen_info_dest( ref : in RTPS_INFO_DESTINATION_SUBMESSAGE_TYPE; output : inout TEST_PACKET_TYPE) is + variable start : natural := 0; + begin + start := output.length; + -- Submessage ID & Submessage Flags & Submessage Length + output.data(length) := ref.submessageID & ref.flags & endian_swap(ref.flags(SUBMESSAGE_ENDIAN_FLAG_POS), ref.submessageLength); + output.length := output.length + 1; + -- GUID Prefix + output.data(length) := ref.guidPrefix(0); + output.length := output.length + 1; + output.data(length) := ref.guidPrefix(1); + output.length := output.length + 1; + output.data(length) := ref.guidPrefix(2); + output.length := output.length + 1; + -- Fix Submessage Length + if (ref.submessageLength = (ref.submessageLength'range => '1')) then + output.data(start)(SUBMESSAGE_LENGTH_WIDTH-1 downto 0) := endian_swap(ref.flags(SUBMESSAGE_ENDIAN_FLAG_POS), int(output.length-start-1,SUBMESSAGE_LENGTH_WIDTH)); + -- Fix Packet Length + else + output.length := start + to_integer(ref.submessageLength); + end if; + end procedure; + + procedure gen_info_reply( ref : in RTPS_INFO_REPLY_SUBMESSAGE_TYPE; output : inout TEST_PACKET_TYPE) is + variable start : natural := 0; + begin + start := output.length; + -- Submessage ID & Submessage Flags & Submessage Length + output.data(length) := ref.submessageID & ref.flags & endian_swap(ref.flags(SUBMESSAGE_ENDIAN_FLAG_POS), ref.submessageLength); + output.length := output.length + 1; + -- Unicast Locator (NumLocators) + output.data(length) := endian_swap(ref.flags(SUBMESSAGE_ENDIAN_FLAG_POS), ref.unicastLocatorList.numLocators); + output.length := output.length + 1; + for i in 0 to to_integer(unsigned(ref.unicastLocatorList.numLocators))-1 loop + -- Unicast Locator (Kind) + output.data(length) := endian_swap(ref.flags(SUBMESSAGE_ENDIAN_FLAG_POS), ref.unicastLocatorList.locator(i).kind); + output.length := output.length + 1; + -- Unicast Locator (Port) + output.data(length) := endian_swap(ref.flags(SUBMESSAGE_ENDIAN_FLAG_POS), ref.unicastLocatorList.locator(i).port_); + output.length := output.length + 1; + -- Unicast Locator (Address) + output.data(length) := ref.unicastLocatorList.locator(i).addr(127 downto 96); + output.length := output.length + 1; + output.data(length) := ref.unicastLocatorList.locator(i).addr(95 downto 64); + output.length := output.length + 1; + output.data(length) := ref.unicastLocatorList.locator(i).addr(63 downto 32); + output.length := output.length + 1; + output.data(length) := ref.unicastLocatorList.locator(i).addr(31 downto 0); + output.length := output.length + 1; + end loop; + if (ref.flags(SUBMESSAGE_MULTICAST_FLAG_POS) = '1') then + -- Unicast Locator (NumLocators) + output.data(length) := endian_swap(ref.flags(SUBMESSAGE_ENDIAN_FLAG_POS), ref.multicastLocatorList.numLocators); + output.length := output.length + 1; + for i in 0 to to_integer(unsigned(ref.multicastLocatorList.numLocators))-1 loop + -- Unicast Locator (Kind) + output.data(length) := endian_swap(ref.flags(SUBMESSAGE_ENDIAN_FLAG_POS), ref.multicastLocatorList.locator(i).kind); + output.length := output.length + 1; + -- Unicast Locator (Port) + output.data(length) := endian_swap(ref.flags(SUBMESSAGE_ENDIAN_FLAG_POS), ref.multicastLocatorList.locator(i).port_); + output.length := output.length + 1; + -- Unicast Locator (Address) + output.data(length) := ref.multicastLocatorList.locator(i).addr(127 downto 96); + output.length := output.length + 1; + output.data(length) := ref.multicastLocatorList.locator(i).addr(95 downto 64); + output.length := output.length + 1; + output.data(length) := ref.multicastLocatorList.locator(i).addr(63 downto 32); + output.length := output.length + 1; + output.data(length) := ref.multicastLocatorList.locator(i).addr(31 downto 0); + output.length := output.length + 1; + end loop; + end if; + -- Fix Submessage Length + if (ref.submessageLength = (ref.submessageLength'range => '1')) then + output.data(start)(SUBMESSAGE_LENGTH_WIDTH-1 downto 0) := endian_swap(ref.flags(SUBMESSAGE_ENDIAN_FLAG_POS), int(output.length-start-1,SUBMESSAGE_LENGTH_WIDTH)); + -- Fix Packet Length + else + output.length := start + to_integer(ref.submessageLength); + end if; + end procedure; + + procedure gen_info_src( ref : in RTPS_INFO_SOURCE_SUBMESSAGE_TYPE; output : inout TEST_PACKET_TYPE) is + variable start : natural := 0; + begin + start := output.length; + -- Submessage ID & Submessage Flags & Submessage Length + output.data(length) := ref.submessageID & ref.flags & endian_swap(ref.flags(SUBMESSAGE_ENDIAN_FLAG_POS), ref.submessageLength); + output.length := output.length + 1; + -- UNUSED + output.data(length) := endian_swap(ref.flags(SUBMESSAGE_ENDIAN_FLAG_POS), ref.unused); + output.length := output.length + 1; + -- Protocol Version & Vendor ID + output.data(length) := ref.version & ref.vendorId; + output.length := output.length + 1; + -- GUID Prefix + output.data(length) := ref.guidPrefix(0); + output.length := output.length + 1; + output.data(length) := ref.guidPrefix(1); + output.length := output.length + 1; + output.data(length) := ref.guidPrefix(2); + output.length := output.length + 1; + -- Fix Submessage Length + if (ref.submessageLength = (ref.submessageLength'range => '1')) then + output.data(start)(SUBMESSAGE_LENGTH_WIDTH-1 downto 0) := endian_swap(ref.flags(SUBMESSAGE_ENDIAN_FLAG_POS), int(output.length-start-1,SUBMESSAGE_LENGTH_WIDTH)); + -- Fix Packet Length + else + output.length := start + to_integer(ref.submessageLength); + end if; + end procedure; + + procedure gen_info_ts( ref : in RTPS_INFO_TIMESTAMP_SUBMESSAGE_TYPE; output : inout TEST_PACKET_TYPE) is + variable start : natural := 0; + begin + start := output.length; + -- Submessage ID & Submessage Flags & Submessage Length + output.data(length) := ref.submessageID & ref.flags & endian_swap(ref.flags(SUBMESSAGE_ENDIAN_FLAG_POS), ref.submessageLength); + output.length := output.length + 1; + -- Timestamp + if (ref.flags(SUBMESSAGE_INVALIDATE_FLAG_POS) = '0') then + output.data(length) := endian_swap(ref.flags(SUBMESSAGE_ENDIAN_FLAG_POS), std_logic_vector(ref.timestamp(0))); + output.length := output.length + 1; + output.data(length) := endian_swap(ref.flags(SUBMESSAGE_ENDIAN_FLAG_POS), std_logic_vector(ref.timestamp(1))); + output.length := output.length + 1; + end if; + -- Fix Submessage Length + if (ref.submessageLength = (ref.submessageLength'range => '1')) then + output.data(start)(SUBMESSAGE_LENGTH_WIDTH-1 downto 0) := endian_swap(ref.flags(SUBMESSAGE_ENDIAN_FLAG_POS), int(output.length-start-1,SUBMESSAGE_LENGTH_WIDTH)); + -- Fix Packet Length + else + output.length := start + to_integer(ref.submessageLength); + end if; + end procedure; + + procedure gen_pad( ref : in RTPS_PAD_SUBMESSAGE_TYPE; output : inout TEST_PACKET_TYPE) is + begin + -- Submessage Header + gen_rtps_subheader(ref, output); + -- Padding + for i in 0 to to_integer(unsigned(ref.submessageLength))-1 loop + output.data(length) := (others => '0') + output.length := output.length + 1; + end loop; + end procedure; + + procedure gen_info_reply_ip4( ref : in RTPS_INFO_REPLY_IP4_SUBMESSAGE_TYPE; output : inout TEST_PACKET_TYPE) is + variable start : natural := 0; + begin + start := output.length; + -- Submessage ID & Submessage Flags & Submessage Length + output.data(length) := ref.submessageID & ref.flags & endian_swap(ref.flags(SUBMESSAGE_ENDIAN_FLAG_POS), ref.submessageLength); + output.length := output.length + 1; + -- Unicast Locator (Address) + output.data(length) := endian_swap(ref.flags(SUBMESSAGE_ENDIAN_FLAG_POS), ref.unicastLocator.addr(IPv4_ADDRESS_WIDTH-1 downto 0)); + output.length := output.length + 1; + -- Unicast Locator (Port) + output.data(length) := endian_swap(ref.flags(SUBMESSAGE_ENDIAN_FLAG_POS), ref.unicastLocator.port_(UDP_PORT_WIDTH-1 downto 0)); + output.length := output.length + 1; + if (ref.flags(SUBMESSAGE_MULTICAST_FLAG_POS) = '1') then + -- Multicast Locator (Address) + output.data(length) := endian_swap(ref.flags(SUBMESSAGE_ENDIAN_FLAG_POS), ref.multicastLocator.addr(IPv4_ADDRESS_WIDTH-1 downto 0)); + output.length := output.length + 1; + -- Multicast Locator (Port) + output.data(length) := endian_swap(ref.flags(SUBMESSAGE_ENDIAN_FLAG_POS), ref.multicastLocator.port_(UDP_PORT_WIDTH-1 downto 0)); + output.length := output.length + 1; + end if; + -- Fix Submessage Length + if (ref.submessageLength = (ref.submessageLength'range => '1')) then + output.data(start)(SUBMESSAGE_LENGTH_WIDTH-1 downto 0) := endian_swap(ref.flags(SUBMESSAGE_ENDIAN_FLAG_POS), int(output.length-start-1,SUBMESSAGE_LENGTH_WIDTH)); + -- Fix Packet Length + else + output.length := start + to_integer(ref.submessageLength); + end if; + end procedure; + + procedure gen_participant_announcement( ref : in PARTICIPANT_DATA_TYPE; output : inout TEST_PACKET_TYPE) is + variable tmp : natural := 0; + begin + -- Representation Identifier & Representation Options + output.data(length) := (PL_CDR_BE when ref.littleEndian = '0' else PL_CDR_LE) & x"0000"; + output.length := output.length + 1; + -- GUID + output.data(length) := PID_PARTICIPANT_GUID & endian_swap(ref.littleEndian, int(16, PARAMETER_LENGTH_WIDTH)); + output.length := output.length + 1; + output.data(length) := ref.guidPrefix(0); + output.length := output.length + 1; + output.data(length) := ref.guidPrefix(1); + output.length := output.length + 1; + output.data(length) := ref.guidPrefix(2); + output.length := output.length + 1; + output.data(length) := ref.entityId; + output.length := output.length + 1; + -- DOMAIN ID + output.data(length) := PID_DOMAIN_ID & endian_swap(ref.littleEndian, int(4, PARAMETER_LENGTH_WIDTH)); + output.length := output.length + 1; + output.data(length) := endian_swap(ref.littleEndian, ref.domainId); + output.length := output.length + 1; + -- DOMAIN TAG + if (ref.domainTag /= EMPTY_STRING) then + tmp := string_len(ref.domainTag); + output.data(length) := PID_DOMAIN_TAG & endian_swap(ref.littleEndian, int((round_div(tmp,4)+1)*4, PARAMETER_LENGTH_WIDTH)); + output.length := output.length + 1; + output.data(length) := endian_swap(ref.littleEndian, int(tmp, CDR_LONG_WIDTH);); + output.length := output.length + 1; + for i in 0 to round_div(tmp,4)-1 loop + output.data(length) := ref.domainTag(i); + output.length := output.length + 1; + end loop; + end if; + -- PROTOCOL VERSION + output.data(length) := PID_PROTOCOL_VERSION & endian_swap(ref.littleEndian, int(4, PARAMETER_LENGTH_WIDTH)); + output.length := output.length + 1; + output.data(length) := (others => '0'); + output.data(length)(31 downto 16) := ref.protocolVersion; + output.length := output.length + 1; + -- VENDORID + output.data(length) := PID_VENDORID & endian_swap(ref.littleEndian, int(4,PARAMETER_LENGTH_WIDTH)); + output.length := output.length + 1; + output.data(length) := (others => '0'); + output.data(length)(31 downto 16) := ref.vendorId; + output.length := output.length + 1; + -- EXPECTS IN-LINE QOS + if (ref.expectsInlineQoS(0) /= '0') then + output.data(length) := PID_EXPECTS_INLINE_QOS & endian_swap(ref.littleEndian, int(4,PARAMETER_LENGTH_WIDTH)); + output.length := output.length + 1; + output.data(length) := (others => '0'); + output.data(length)(31 downto 24) := ref.expectsInlineQoS; -- 1 Byte, No endian swap + output.length := output.length + 1; + end if; + -- METATRAFFIC UNICAST LOCATOR + if (ref.metatrafficUnicastLocatorList.numLocators /= ref.metatrafficUnicastLocatorList.numLocators'range => '0') then + tmp := to_integer(unsigned(ref.metatrafficUnicastLocatorList.numLocators)); + output.data(length) := PID_METATRAFFIC_UNICAST_LOCATOR & endian_swap(ref.littleEndian, int(((tmp*6)+1)*4,PARAMETER_LENGTH_WIDTH)); + output.length := output.length + 1; + output.data(length) := endian_swap(ref.littleEndian, ref.metatrafficUnicastLocatorList.numLocators); + output.length := output.length + 1; + for i in 0 to tmp-1 loop + output.data(length) := endian_swap(ref.littleEndian, ref.metatrafficUnicastLocatorList.locator(i).kind); + output.length := output.length + 1; + output.data(length) := endian_swap(ref.littleEndian, ref.metatrafficUnicastLocatorList.locator(i).port_); + output.length := output.length + 1; + output.data(length) := ref.metatrafficUnicastLocatorList.locator(i).addr(127 downto 96); + output.length := output.length + 1; + output.data(length) := ref.metatrafficUnicastLocatorList.locator(i).addr(95 downto 64); + output.length := output.length + 1; + output.data(length) := ref.metatrafficUnicastLocatorList.locator(i).addr(63 downto 32); + output.length := output.length + 1; + output.data(length) := ref.metatrafficUnicastLocatorList.locator(i).addr(31 downto 0); + output.length := output.length + 1; + end loop; + end if; + -- METATRAFFIC MULTICAST LOCATOR + if (ref.metatrafficMulticastLocatorList.numLocators /= ref.metatrafficMulticastLocatorList.numLocators'range => '0') then + tmp := to_integer(unsigned(ref.metatrafficMulticastLocatorList.numLocators)); + output.data(length) := PID_METATRAFFIC_MULTICAST_LOCATOR & endian_swap(ref.littleEndian, int(((tmp*6)+1)*4,PARAMETER_LENGTH_WIDTH)); + output.length := output.length + 1; + output.data(length) := endian_swap(ref.littleEndian, ref.metatrafficMulticastLocatorList.numLocators); + output.length := output.length + 1; + for i in 0 to tmp-1 loop + output.data(length) := endian_swap(ref.littleEndian, ref.metatrafficMulticastLocatorList.locator(i).kind); + output.length := output.length + 1; + output.data(length) := endian_swap(ref.littleEndian, ref.metatrafficMulticastLocatorList.locator(i).port_); + output.length := output.length + 1; + output.data(length) := ref.metatrafficMulticastLocatorList.locator(i).addr(127 downto 96); + output.length := output.length + 1; + output.data(length) := ref.metatrafficMulticastLocatorList.locator(i).addr(95 downto 64); + output.length := output.length + 1; + output.data(length) := ref.metatrafficMulticastLocatorList.locator(i).addr(63 downto 32); + output.length := output.length + 1; + output.data(length) := ref.metatrafficMulticastLocatorList.locator(i).addr(31 downto 0); + output.length := output.length + 1; + end loop; + end if; + -- DEFAULT UNICAST LOCATOR + assert (unsigned(ref.defaultUnicastLocatorList.numLocators) > 0) report "PARTICIPANT_DATA: Participant needs to have at least one Default Unicast Locator." severity error; + if (ref.defaultUnicastLocatorList.numLocators /= ref.defaultUnicastLocatorList.numLocators'range => '0') then + tmp := to_integer(unsigned(ref.defaultUnicastLocatorList.numLocators)); + output.data(length) := PID_METATRAFFIC_MULTICAST_LOCATOR & endian_swap(ref.littleEndian, int(((tmp*6)+1)*4,PARAMETER_LENGTH_WIDTH)); + output.length := output.length + 1; + output.data(length) := endian_swap(ref.littleEndian, ref.defaultUnicastLocatorList.numLocators); + output.length := output.length + 1; + for i in 0 to tmp-1 loop + output.data(length) := endian_swap(ref.littleEndian, ref.defaultUnicastLocatorList.locator(i).kind); + output.length := output.length + 1; + output.data(length) := endian_swap(ref.littleEndian, ref.defaultUnicastLocatorList.locator(i).port_); + output.length := output.length + 1; + output.data(length) := ref.defaultUnicastLocatorList.locator(i).addr(127 downto 96); + output.length := output.length + 1; + output.data(length) := ref.defaultUnicastLocatorList.locator(i).addr(95 downto 64); + output.length := output.length + 1; + output.data(length) := ref.defaultUnicastLocatorList.locator(i).addr(63 downto 32); + output.length := output.length + 1; + output.data(length) := ref.defaultUnicastLocatorList.locator(i).addr(31 downto 0); + output.length := output.length + 1; + end loop; + end if; + -- DEFAULT MULTICAST LOCATOR + if (ref.defaultMulticastLocatorList.numLocators /= ref.defaultMulticastLocatorList.numLocators'range => '0') then + tmp := to_integer(unsigned(ref.defaultMulticastLocatorList.numLocators)); + output.data(length) := PID_METATRAFFIC_MULTICAST_LOCATOR & endian_swap(ref.littleEndian, int(((tmp*6)+1)*4,PARAMETER_LENGTH_WIDTH)); + output.length := output.length + 1; + output.data(length) := endian_swap(ref.littleEndian, ref.defaultMulticastLocatorList.numLocators); + output.length := output.length + 1; + for i in 0 to tmp-1 loop + output.data(length) := endian_swap(ref.littleEndian, ref.defaultMulticastLocatorList.locator(i).kind); + output.length := output.length + 1; + output.data(length) := endian_swap(ref.littleEndian, ref.defaultMulticastLocatorList.locator(i).port_); + output.length := output.length + 1; + output.data(length) := ref.defaultMulticastLocatorList.locator(i).addr(127 downto 96); + output.length := output.length + 1; + output.data(length) := ref.defaultMulticastLocatorList.locator(i).addr(95 downto 64); + output.length := output.length + 1; + output.data(length) := ref.defaultMulticastLocatorList.locator(i).addr(63 downto 32); + output.length := output.length + 1; + output.data(length) := ref.defaultMulticastLocatorList.locator(i).addr(31 downto 0); + output.length := output.length + 1; + end loop; + end if; + -- LEASE DURATION + if (ref.leaseDuration /= DEFAULT_PARTICIPANT_LEASE_DURATION) then + output.data(length) := PID_PARTICIPANT_LEASE_DURATION & endian_swap(ref.littleEndian, int(8,PARAMETER_LENGTH_WIDTH)); + output.length := output.length + 1; + output.data(length) := endian_swap(ref.littleEndian, std_logic_vector(ref.leaseDuration(0))); + output.length := output.length + 1; + output.data(length) := endian_swap(ref.littleEndian, std_logic_vector(ref.leaseDuration(1))); + output.length := output.length + 1; + end if; + -- AVAILABLE ENDPOINTS + output.data(length) := PID_BUILTIN_ENDPOINT_SET & endian_swap(ref.littleEndian, int(4,PARAMETER_LENGTH_WIDTH)); + output.length := output.length + 1; + output.data(length) := endian_swap(ref.littleEndian, ref.availableBuiltinEndpoints); + output.length := output.length + 1; + -- MANUAL LIVELINESS COUNT + output.data(length) := PID_PARTICIPANT_MANUAL_LIVELINESS_COUNT & endian_swap(ref.littleEndian, int(4,PARAMETER_LENGTH_WIDTH)); + output.length := output.length + 1; + output.data(length) := endian_swap(ref.littleEndian, ref.manualLivelinessCount); + output.length := output.length + 1; + end procedure; + + procedure gen_endpoint_data( ref : in ENDPOINT_DATA_TYPE; output : inout TEST_PACKET_TYPE) is + variable tmp : natural := 0; + begin + -- GUID + output.data(length) := PID_ENDPOINT_GUID & endian_swap(ref.littleEndian, int(16,PARAMETER_LENGTH_WIDTH)); + output.length := output.length + 1; + output.data(length) := ref.guidPrefix(0); + output.length := output.length + 1; + output.data(length) := ref.guidPrefix(1); + output.length := output.length + 1; + output.data(length) := ref.guidPrefix(2); + output.length := output.length + 1; + output.data(length) := ref.entityId; + output.length := output.length + 1; + -- EXPECTS IN-LINE QOS + if (ref.expectsInlineQoS(0) /= '0') then + output.data(length) := PID_EXPECTS_INLINE_QOS & endian_swap(ref.littleEndian, int(4,PARAMETER_LENGTH_WIDTH)); + output.length := output.length + 1; + output.data(length) := (others => '0'); + output.data(length)(31 downto 24) := ref.expectsInlineQoS; -- 1 Byte, No endian swap + output.length := output.length + 1; + end if; + -- TOPIC NAME + tmp := string_len(ref.topic_name); + output.data(length) := PID_TOPIC_NAME & endian_swap(ref.littleEndian, int((round_div(tmp,4)+1)*4,PARAMETER_LENGTH_WIDTH)); + output.length := output.length + 1; + output.data(length) := endian_swap(ref.littleEndian, int(tmp, CDR_LONG_WIDTH)); + output.length := output.length + 1; + for i in 0 to round_div(tmp,4)-1 loop + output.data(length) := ref.topic_name(i); + output.length := output.length + 1; + end loop; + -- TYPE NAME + tmp := string_len(ref.type_name); + output.data(length) := PID_TOPIC_NAME & endian_swap(ref.littleEndian, int((round_div(tmp,4)+1)*4,PARAMETER_LENGTH_WIDTH)); + output.length := output.length + 1; + output.data(length) := endian_swap(ref.littleEndian, int(tmp,CDR_LONG_WIDTH)); + output.length := output.length + 1; + for i in 0 to round_div(tmp,4)-1 loop + output.data(length) := ref.type_name(i); + output.length := output.length + 1; + end loop; + -- DURABILITY + if (ref.durability /= DEFAULT_DURABILITY_QOS) then + output.data(length) := PID_DURABILITY & endian_swap(ref.littleEndian, int(4,PARAMETER_LENGTH_WIDTH)); + output.length := output.length + 1; + output.data(length) := endian_swap(ref.littleEndian, ref.durability); + output.length := output.length + 1; + end if; + -- DURABILITY SERVICE + if (ref.durability_service_cleanup_delay /= DEFAULT_DURABILITY_SERVICE_CLEANUP_DELAY or ref.durability_service_history /= DEFAULT_DURABILITY_SERVICE_HISTORY or + ref.durability_service_history_depth /= DEFAULT_DURABILITY_SERVICE_HISTORY_DEPTH or ref.durability_service_max_samples /= DEFAULT_DURABILITY_SERVICE_MAX_SAMPLES or + ref.durability_service_max_instances /= DEFAULT_DURABILITY_SERVICE_MAX_INSTANCES or ref.durability_service_max_samples_per_instances /= DEFAULT_DURABILITY_SERVICE_MAX_SAMPLES_PER_INSTANCE) then + + output.data(length) := PID_DURABILITY_SERVICE & endian_swap(ref.littleEndian, int(28,PARAMETER_LENGTH_WIDTH)); + output.length := output.length + 1; + output.data(length) := endian_swap(ref.littleEndian, std_logic_vector(ref.durability_service_cleanup_delay(0))); + output.length := output.length + 1; + output.data(length) := endian_swap(ref.littleEndian, std_logic_vector(ref.durability_service_cleanup_delay(1))); + output.length := output.length + 1; + output.data(length) := endian_swap(ref.littleEndian, ref.durability_service_history); + output.length := output.length + 1; + output.data(length) := endian_swap(ref.littleEndian, ref.durability_service_history_depth); + output.length := output.length + 1; + output.data(length) := endian_swap(ref.littleEndian, ref.durability_service_max_samples); + output.length := output.length + 1; + output.data(length) := endian_swap(ref.littleEndian, ref.durability_service_max_instances); + output.length := output.length + 1; + output.data(length) := endian_swap(ref.littleEndian, ref.durability_service_max_samples_per_instances); + output.length := output.length + 1; + end if; + -- PRESENTATION + if (ref.presentation /= DEFAULT_PRESENTATION_QOS or ref.coherent_access(0) /= boolean_to_std_logic(DEFAULT_COHERENT_ACCESS) or ref.ordered_access(0) /= boolean_to_std_logic(DEFAULT_ORDERED_ACCESS)) then + output.data(length) := PID_PRESENTATION & endian_swap(ref.littleEndian, int(8,PARAMETER_LENGTH_WIDTH)); + output.length := output.length + 1; + output.data(length) := endian_swap(ref.littleEndian, ref.presentation); + output.length := output.length + 1; + output.data(length) := endian_swap(ref.littleEndian, ref.coherent_access) & endian_swap(ref.littleEndian, ref.ordered_access); + output.length := output.length + 1; + end if; + -- DEADLINE + if (ref.deadline /= DEFAULT_DEADLINE_QOS) then + output.data(length) := PID_DEADLINE & endian_swap(ref.littleEndian, int(8,PARAMETER_LENGTH_WIDTH)); + output.length := output.length + 1; + output.data(length) := endian_swap(ref.littleEndian, std_logic_vector(ref.deadline(0))); + output.length := output.length + 1; + output.data(length) := endian_swap(ref.littleEndian, std_logic_vector(ref.deadline(1))); + output.length := output.length + 1; + end if; + -- LATENCY BUDGET + if (ref.latency_budget /= DEFAULT_LATENCY_BUDGET_QOS) then + output.data(length) := PID_LATENCY_BUDGET & endian_swap(ref.littleEndian, int(8,PARAMETER_LENGTH_WIDTH)); + output.length := output.length + 1; + output.data(length) := endian_swap(ref.littleEndian, std_logic_vector(ref.deadline(0))); + output.length := output.length + 1; + output.data(length) := endian_swap(ref.littleEndian, std_logic_vector(ref.deadline(1))); + output.length := output.length + 1; + end if; + -- OWNERSHIP + if (ref.ownership /= DEFAULT_OWNERSHIP_QOS) then + output.data(length) := PID_OWNERSHIP & endian_swap(ref.littleEndian, int(4,PARAMETER_LENGTH_WIDTH)); + output.length := output.length + 1; + output.data(length) := endian_swap(ref.littleEndian, ref.ownership); + output.length := output.length + 1; + end if; + -- OWNERSHIP STRENGTH + if (ref.ownership /= DEFAULT_OWNERSHIP_STRENGTH_QOS) then + output.data(length) := PID_OWNERSHIP_STRENGTH & endian_swap(ref.littleEndian, int(4,PARAMETER_LENGTH_WIDTH)); + output.length := output.length + 1; + output.data(length) := endian_swap(ref.littleEndian, ref.ownership_strength); + output.length := output.length + 1; + end if; + -- LIVELINESS + if (ref.liveliness /= DEFAULT_LIVELINESS_QOS or ref.leaseDuration /= DEFAULT_LEASE_DURATION) then + output.data(length) := PID_LIVELINESS & endian_swap(ref.littleEndian, int(12,PARAMETER_LENGTH_WIDTH)); + output.length := output.length + 1; + output.data(length) := endian_swap(ref.littleEndian, ref.liveliness); + output.length := output.length + 1; + output.data(length) := endian_swap(ref.littleEndian, std_logic_vector(ref.leaseDuration(0))); + output.length := output.length + 1; + output.data(length) := endian_swap(ref.littleEndian, std_logic_vector(ref.leaseDuration(1))); + output.length := output.length + 1; + end if; + -- TIME BASED FILTER + if (ref.time_based_filter /= DEFAULT_TIME_BASED_FILTER_QOS) then + output.data(length) := PID_TIME_BASED_FILTER & endian_swap(ref.littleEndian, int(8,PARAMETER_LENGTH_WIDTH)); + output.length := output.length + 1; + output.data(length) := endian_swap(ref.littleEndian, std_logic_vector(ref.time_based_filter(0))); + output.length := output.length + 1; + output.data(length) := endian_swap(ref.littleEndian, std_logic_vector(ref.time_based_filter(1))); + output.length := output.length + 1; + end if; + -- RELIABILITY + if (ref.reliability /= DEFAULT_RELIABILTY_QOS or ref.max_blocking_time /= DEFAULT_MAX_BLOCKING_TIME) then + output.data(length) := PID_RELIABILITY & endian_swap(ref.littleEndian, int(12,PARAMETER_LENGTH_WIDTH)); + output.length := output.length + 1; + output.data(length) := endian_swap(ref.littleEndian, ref.reliability); + output.length := output.length + 1; + output.data(length) := endian_swap(ref.littleEndian, std_logic_vector(ref.max_blocking_time(0))); + output.length := output.length + 1; + output.data(length) := endian_swap(ref.littleEndian, std_logic_vector(ref.max_blocking_time(1))); + output.length := output.length + 1; + end if; + -- TRANSPORT PRIORITY + if (ref.transport_priority /= DEFAULT_TRANSPORT_PRIORITY_QOS) then + output.data(length) := PID_TRANSPORT_PRIORITY & endian_swap(ref.littleEndian, int(4,PARAMETER_LENGTH_WIDTH)); + output.length := output.length + 1; + output.data(length) := endian_swap(ref.littleEndian, ref.transport_priority); + output.length := output.length + 1; + end if; + -- LIFESPAN + if (ref.lifespan /= DEFAULT_LIFESPAN_QOS) then + output.data(length) := PID_LIFESPAN & endian_swap(ref.littleEndian, int(8,PARAMETER_LENGTH_WIDTH)); + output.length := output.length + 1; + output.data(length) := endian_swap(ref.littleEndian, std_logic_vector(ref.lifespan(0))); + output.length := output.length + 1; + output.data(length) := endian_swap(ref.littleEndian, std_logic_vector(ref.lifespan(1))); + output.length := output.length + 1; + end if; + -- DESTINATION ORDER + if (ref.destination_order /= DEFAULT_DESTINATION_ORDER_QOS) then + output.data(length) := PID_DESTINATION_ORDER & endian_swap(ref.littleEndian, int(4,PARAMETER_LENGTH_WIDTH)); + output.length := output.length + 1; + output.data(length) := endian_swap(ref.littleEndian, ref.destination_order); + output.length := output.length + 1; + end if; + -- UNICAST LOCATORS + if (unsigned(ref.unicastLocatorList.numLocators) > 0) then + tmp := to_integer(unsigned(ref.unicastLocatorList.numLocators)); + for i in 0 to tmp-1 loop + output.data(length) := PID_UNICAST_LOCATOR & endian_swap(ref.littleEndian, int(24,PARAMETER_LENGTH_WIDTH)); + output.length := output.length + 1; + output.data(length) := endian_swap(ref.littleEndian, ref.unicastLocatorList.locator(i).kind); + output.length := output.length + 1; + output.data(length) := endian_swap(ref.littleEndian, ref.unicastLocatorList.locator(i).port_); + output.length := output.length + 1; + output.data(length) := ref.unicastLocatorList.locator(i).addr(127 downto 96); + output.length := output.length + 1; + output.data(length) := ref.unicastLocatorList.locator(i).addr(95 downto 64); + output.length := output.length + 1; + output.data(length) := ref.unicastLocatorList.locator(i).addr(63 downto 32); + output.length := output.length + 1; + output.data(length) := ref.unicastLocatorList.locator(i).addr(31 downto 0); + output.length := output.length + 1; + end loop; + end if; + -- MULTICAST LOCATORS + if (unsigned(ref.multicastLocatorList.numLocators) > 0) then + tmp := to_integer(unsigned(ref.multicastLocatorList.numLocators)); + for i in 0 to tmp-1 loop + output.data(length) := PID_MULTICAST_LOCATOR & endian_swap(ref.littleEndian, int(24,PARAMETER_LENGTH_WIDTH)); + output.length := output.length + 1; + output.data(length) := endian_swap(ref.littleEndian, ref.multicastLocatorList.locator(i).kind); + output.length := output.length + 1; + output.data(length) := endian_swap(ref.littleEndian, ref.multicastLocatorList.locator(i).port_); + output.length := output.length + 1; + output.data(length) := ref.multicastLocatorList.locator(i).addr(127 downto 96); + output.length := output.length + 1; + output.data(length) := ref.multicastLocatorList.locator(i).addr(95 downto 64); + output.length := output.length + 1; + output.data(length) := ref.multicastLocatorList.locator(i).addr(63 downto 32); + output.length := output.length + 1; + output.data(length) := ref.multicastLocatorList.locator(i).addr(31 downto 0); + output.length := output.length + 1; + end loop; + end if; + -- USER DATA + tmp := string_len(ref.user_data); + if (tmp > 1) then + output.data(length) := PID_USER_DATA & endian_swap(ref.littleEndian, int((round_div(tmp,4)+1)*4,PARAMETER_LENGTH_WIDTH)); + output.length := output.length + 1; + output.data(length) := endian_swap(ref.littleEndian, int(tmp, 32)); + output.length := output.length + 1; + for i in 0 to round_div(tmp,4)-1 loop + output.data(length) := ref.user_data(i); + output.length := output.length + 1; + end loop; + end if; + -- TOPIC DATA + tmp := string_len(ref.topic_data); + if (tmp > 1) then + output.data(length) := PID_TOPIC_DATA & endian_swap(ref.littleEndian, int((round_div(tmp,4)+1)*4,PARAMETER_LENGTH_WIDTH)); + output.length := output.length + 1; + output.data(length) := endian_swap(ref.littleEndian, int(tmp,32)); + output.length := output.length + 1; + for i in 0 to round_div(tmp,4)-1 loop + output.data(length) := ref.topic_data(i); + output.length := output.length + 1; + end loop; + end if; + -- GROUP DATA + tmp := string_len(ref.group_data); + if (tmp > 1) then + output.data(length) := PID_GROUP_DATA & endian_swap(ref.littleEndian, int((round_div(tmp,4)+1)*4,PARAMETER_LENGTH_WIDTH)); + output.length := output.length + 1; + output.data(length) := endian_swap(ref.littleEndian, int(tmp,32)); + output.length := output.length + 1; + for i in 0 to round_div(tmp,4)-1 loop + output.data(length) := ref.group_data(i); + output.length := output.length + 1; + end loop; + end if; + -- MAX SIZE SERIALIZED + if (unsigned(ref.max_size_serialized) /= 0) then + output.data(length) := PID_DATA_MAX_SIZE_SERIALIZED & endian_swap(ref.littleEndian, int(4,PARAMETER_LENGTH_WIDTH)); + output.length := output.length + 1; + output.data(length) := endian_swap(ref.littleEndian, ref.max_size_serialized); + output.length := output.length + 1; + end if; + end procedure; + + -- converts std_logic into a character + function chr(sl: std_logic) return character is + variable c: character; + begin + case sl is + when 'U' => c:= 'U'; + when 'X' => c:= 'X'; + when '0' => c:= '0'; + when '1' => c:= '1'; + when 'Z' => c:= 'Z'; + when 'W' => c:= 'W'; + when 'L' => c:= 'L'; + when 'H' => c:= 'H'; + when '-' => c:= '-'; + end case; + return c; + end function; + + -- converts std_logic_vector into a string (binary base) + -- (this also takes care of the fact that the range of + -- a string is natural while a std_logic_vector may + -- have an integer range) + function str(slv: std_logic_vector) return string is + variable ret : string (1 to slv'length); + begin + for i in slv'range loop + ret(i+1) := chr(slv(i)); + end loop; + return ret; + end function; + + function str(sl: std_logic) return string is + variable ret : string (1 to 1); + begin + ret(1) := chr(sl); + return ret; + end function; + + impure function rand_int(min_val, max_val : integer) return integer is + variable r : real; + begin + UNIFORM(999, 999, r); + return integer(ROUND(r * real(max_val - min_val + 1) + real(min_val) - 0.5)); + end function; + + impure function rand_slv(len : integer) return std_logic_vector is + variable r : real; + variable slv : std_logic_vector(len - 1 downto 0); + begin + for i in slv'range loop + uniform(999, 999, r); + slv(i) := '1' when r > 0.5 else '0'; + end loop; + return slv; + end function; + + function gen_rand_addr return LOCATOR_TYPE is + variable ret : LOCATOR_TYPE := EMPTY_LOCATOR; + begin + ret.kind => LOCATOR_KIND_UDPv4; + ret.port_(UDP_PORT_WIDTH-1 downto 0) => rand_slv(UDP_PORT_WIDTH); + ret.addr(IPv4_ADDRESS_WIDTH-1 downto 0)=> rand_slv(IPv4_ADDRESS_WIDTH); + end function; + + function int(n : integer, width : natural) return std_logic_vector is + begin + return std_logic_vector(to_signed(n, width)); + end function; + +end package body; \ No newline at end of file