From 16bd4558debe6ee8801544e19da97e4b90469104 Mon Sep 17 00:00:00 2001 From: Greek Date: Sat, 21 Nov 2020 21:05:57 +0100 Subject: [PATCH] * rtps_handler - Handle case where packet end = submessage end (Avoid extra stage switches) - Fix last_word_out - Fix case where rd and empty are both high (INFO_TS) * Modify Endpoint Frame format of GAP - Add dummy word to avoid complexity * rtps_handler Testbench - Add check for last_word_out --- src/REF.txt | 2 + src/TODO.txt | 1 + src/Tests/Level_0/rtps_handler_test1.vhd | 187 ++++++++-------- src/Tests/Level_0/rtps_handler_test2.vhd | 11 +- src/rtps_handler.vhd | 72 ++++-- src/rtps_test_package.vhd | 265 +++++++++++++++++++---- 6 files changed, 373 insertions(+), 165 deletions(-) diff --git a/src/REF.txt b/src/REF.txt index a2be715..6b11d98 100644 --- a/src/REF.txt +++ b/src/REF.txt @@ -151,6 +151,8 @@ GAP PAYLOAD +-------------------------------------------------------------+ | [GapList.Bitmap] x 0-8 | +-------------------------------------------------------------+ +| UNUSED | ++-------------------------------------------------------------+ ENDPOINT_ID =========== diff --git a/src/TODO.txt b/src/TODO.txt index aed86fd..3c5c65b 100644 --- a/src/TODO.txt +++ b/src/TODO.txt @@ -52,6 +52,7 @@ * Is the empty String a valid Topic and Type Name? * We can determine if a Endpoint is a Reader or Writer via the Entity ID. Is it illegal to get a SEDP with incompatible source (Reader Entity ID from Publications Announcer?) * Can we make an array of records of uncontrained strings? That we we could make an array of variable sized strings... +* Should I also check for Minor_Version >= 4? * Fast-RTPS doen not follow DDSI-RTPS Specification diff --git a/src/Tests/Level_0/rtps_handler_test1.vhd b/src/Tests/Level_0/rtps_handler_test1.vhd index 371b6ef..e6e862c 100644 --- a/src/Tests/Level_0/rtps_handler_test1.vhd +++ b/src/Tests/Level_0/rtps_handler_test1.vhd @@ -106,13 +106,10 @@ architecture testbench of rtps_handler_test1 is -- *SIGNAL DECLARATION* signal clk, reset, in_empty, rd_sig, builtin_full, builtin_wr, last_word_out : std_logic := '0'; - signal user_full, user_wr : std_logic_vector(NUM_ENDPOINTS-1 downto 0) := (others => '0'); + signal user_full, user_wr : std_logic_vector(0 to NUM_ENDPOINTS-1) := (others => '0'); signal data_in, data_out : std_logic_vector(WORD_WIDTH-1 downto 0) := (others => '0'); signal stim_stage, ref_stage : TEST_STAGE_TYPE := IDLE; - shared variable stimulus, reference : TEST_PACKET_TYPE := ( - data => (others => (others => '0')), - length => 0 - ); + shared variable stimulus, reference : TEST_PACKET_TYPE := EMPTY_TEST_PACKET; signal packet_sent, packet_checked : std_logic := '0'; signal cnt_stim, cnt_ref : natural := 0; signal start : std_logic := '0'; @@ -152,11 +149,11 @@ begin variable ts : TIME_TYPE := TIME_INVALID; variable check_cnt : natural := 0; variable RV : RandomPType; - variable RAND_DATA : TEST_PACKET_TYPE; + variable RAND_DATA : TEST_PACKET_TYPE := EMPTY_TEST_PACKET; variable UDP_META : UDP_HEADER_TYPE; variable UDP_USER : UDP_HEADER_TYPE; - -- "Cheat" to use procedure as function + -- Wrapper to use procedure as function impure function gen_rand_loc_2 return LOCATOR_TYPE is variable ret : LOCATOR_TYPE := EMPTY_LOCATOR; begin @@ -184,7 +181,7 @@ begin -- Random Values - RAND_DATA := (length => 2, data => (0 => RV.RandSlv(WORD_WIDTH), 1 => RV.RandSlv(WORD_WIDTH), others => (others => '0'))); + RAND_DATA := (length => 2, data => (0 => RV.RandSlv(WORD_WIDTH), 1 => RV.RandSlv(WORD_WIDTH), others => (others => '0')), last => (others => '0')); UDP_META := (src => gen_rand_loc_2, dest => DEST_LOC.meta.locator(0)); UDP_USER := (src => gen_rand_loc_2, dest => DEST_LOC.user.locator(0)); @@ -218,8 +215,8 @@ begin start_test; wait_on_complete; check_cnt := check_cnt + reference.length; - stimulus.length := 0; - reference.length := 0; + stimulus := EMPTY_TEST_PACKET; + reference := EMPTY_TEST_PACKET; Log("Sending invalid RTPS Header [Protocol Missmatch]", INFO); -- UDP Header @@ -236,8 +233,8 @@ begin start_test; wait_on_complete; check_cnt := check_cnt + reference.length; - stimulus.length := 0; - reference.length := 0; + stimulus := EMPTY_TEST_PACKET; + reference := EMPTY_TEST_PACKET; Log("Sending invalid RTPS Header [Protocol Major Version Missmatch]", INFO); -- UDP Header @@ -254,8 +251,8 @@ begin start_test; wait_on_complete; check_cnt := check_cnt + reference.length; - stimulus.length := 0; - reference.length := 0; + stimulus := EMPTY_TEST_PACKET; + reference := EMPTY_TEST_PACKET; -- Valid RTPS Header from here on rtps_header := DEFAULT_RTPS_HEADER; @@ -276,8 +273,8 @@ begin start_test; wait_on_complete; check_cnt := check_cnt + reference.length; - stimulus.length := 0; - reference.length := 0; + stimulus := EMPTY_TEST_PACKET; + reference := EMPTY_TEST_PACKET; Log("Sending valid DATA [Meta Traffic, Both Endianness]", INFO); -- UDP Header @@ -301,8 +298,8 @@ begin start_test; wait_on_complete; check_cnt := check_cnt + reference.length; - stimulus.length := 0; - reference.length := 0; + stimulus := EMPTY_TEST_PACKET; + reference := EMPTY_TEST_PACKET; Log("Sending valid DATA [User Traffic]", INFO); -- UDP Header @@ -322,8 +319,8 @@ begin start_test; wait_on_complete; check_cnt := check_cnt + reference.length; - stimulus.length := 0; - reference.length := 0; + stimulus := EMPTY_TEST_PACKET; + reference := EMPTY_TEST_PACKET; Log("Sending valid DATA [Extra Header Bytes]", INFO); -- UDP Header @@ -344,8 +341,8 @@ begin start_test; wait_on_complete; check_cnt := check_cnt + reference.length; - stimulus.length := 0; - reference.length := 0; + stimulus := EMPTY_TEST_PACKET; + reference := EMPTY_TEST_PACKET; Log("Sending invalid DATA [DATA and KEY Flag set]", INFO); -- UDP Header @@ -369,8 +366,8 @@ begin start_test; wait_on_complete; check_cnt := check_cnt + reference.length; - stimulus.length := 0; - reference.length := 0; + stimulus := EMPTY_TEST_PACKET; + reference := EMPTY_TEST_PACKET; Log("Sending invalid DATA [Packet Size too small]", INFO); -- UDP Header @@ -390,8 +387,8 @@ begin start_test; wait_on_complete; check_cnt := check_cnt + reference.length; - stimulus.length := 0; - reference.length := 0; + stimulus := EMPTY_TEST_PACKET; + reference := EMPTY_TEST_PACKET; Log("Sending invalid DATA [Submessage Length too small]", INFO); -- UDP Header @@ -414,8 +411,8 @@ begin start_test; wait_on_complete; check_cnt := check_cnt + reference.length; - stimulus.length := 0; - reference.length := 0; + stimulus := EMPTY_TEST_PACKET; + reference := EMPTY_TEST_PACKET; Log("Sending invalid DATA [Invalid writerSN]", INFO); -- UDP Header @@ -438,8 +435,8 @@ begin start_test; wait_on_complete; check_cnt := check_cnt + reference.length; - stimulus.length := 0; - reference.length := 0; + stimulus := EMPTY_TEST_PACKET; + reference := EMPTY_TEST_PACKET; -- *ACKNACK SUBMESSAGE* @@ -463,8 +460,8 @@ begin start_test; wait_on_complete; check_cnt := check_cnt + reference.length; - stimulus.length := 0; - reference.length := 0; + stimulus := EMPTY_TEST_PACKET; + reference := EMPTY_TEST_PACKET; Log("Sending valid ACKNACK [User Traffic]", INFO); -- UDP Header @@ -482,8 +479,8 @@ begin start_test; wait_on_complete; check_cnt := check_cnt + reference.length; - stimulus.length := 0; - reference.length := 0; + stimulus := EMPTY_TEST_PACKET; + reference := EMPTY_TEST_PACKET; Log("Sending invalid ACKNACK [Packet Size too small]", INFO); -- UDP Header @@ -501,8 +498,8 @@ begin start_test; wait_on_complete; check_cnt := check_cnt + reference.length; - stimulus.length := 0; - reference.length := 0; + stimulus := EMPTY_TEST_PACKET; + reference := EMPTY_TEST_PACKET; Log("Sending invalid ACKNACK [Submessage Length too small]", INFO); -- UDP Header @@ -523,8 +520,8 @@ begin start_test; wait_on_complete; check_cnt := check_cnt + reference.length; - stimulus.length := 0; - reference.length := 0; + stimulus := EMPTY_TEST_PACKET; + reference := EMPTY_TEST_PACKET; Log("Sending invalid ACKNACK [ReaderSNState invalid (Base invalid)]", INFO); -- UDP Header @@ -545,8 +542,8 @@ begin start_test; wait_on_complete; check_cnt := check_cnt + reference.length; - stimulus.length := 0; - reference.length := 0; + stimulus := EMPTY_TEST_PACKET; + reference := EMPTY_TEST_PACKET; Log("Sending invalid ACKNACK [ReaderSNState invalid (NumBits invalid)]", INFO); -- UDP Header @@ -567,8 +564,8 @@ begin start_test; wait_on_complete; check_cnt := check_cnt + reference.length; - stimulus.length := 0; - reference.length := 0; + stimulus := EMPTY_TEST_PACKET; + reference := EMPTY_TEST_PACKET; -- *GAP SUBMESSAGE* Log("Sending valid GAP [Meta Traffic, Both Endianness]", INFO); @@ -591,8 +588,8 @@ begin start_test; wait_on_complete; check_cnt := check_cnt + reference.length; - stimulus.length := 0; - reference.length := 0; + stimulus := EMPTY_TEST_PACKET; + reference := EMPTY_TEST_PACKET; Log("Sending valid GAP [User Traffic]", INFO); -- UDP Header @@ -610,8 +607,8 @@ begin start_test; wait_on_complete; check_cnt := check_cnt + reference.length; - stimulus.length := 0; - reference.length := 0; + stimulus := EMPTY_TEST_PACKET; + reference := EMPTY_TEST_PACKET; Log("Sending invalid GAP [Packet Size too small]", INFO); -- UDP Header @@ -629,8 +626,8 @@ begin start_test; wait_on_complete; check_cnt := check_cnt + reference.length; - stimulus.length := 0; - reference.length := 0; + stimulus := EMPTY_TEST_PACKET; + reference := EMPTY_TEST_PACKET; Log("Sending invalid GAP [Submessage Length too small]", INFO); -- UDP Header @@ -651,8 +648,8 @@ begin start_test; wait_on_complete; check_cnt := check_cnt + reference.length; - stimulus.length := 0; - reference.length := 0; + stimulus := EMPTY_TEST_PACKET; + reference := EMPTY_TEST_PACKET; Log("Sending invalid GAP [GapStart invalid]", INFO); -- UDP Header @@ -673,8 +670,8 @@ begin start_test; wait_on_complete; check_cnt := check_cnt + reference.length; - stimulus.length := 0; - reference.length := 0; + stimulus := EMPTY_TEST_PACKET; + reference := EMPTY_TEST_PACKET; Log("Sending invalid GAP [GapList invalid (Base invalid)]", INFO); -- UDP Header @@ -695,8 +692,8 @@ begin start_test; wait_on_complete; check_cnt := check_cnt + reference.length; - stimulus.length := 0; - reference.length := 0; + stimulus := EMPTY_TEST_PACKET; + reference := EMPTY_TEST_PACKET; Log("Sending invalid GAP [GapList invalid (NumBits invalid)]", INFO); -- UDP Header @@ -717,8 +714,8 @@ begin start_test; wait_on_complete; check_cnt := check_cnt + reference.length; - stimulus.length := 0; - reference.length := 0; + stimulus := EMPTY_TEST_PACKET; + reference := EMPTY_TEST_PACKET; -- *HEARTBEAT SUBMESSAGE* @@ -742,8 +739,8 @@ begin start_test; wait_on_complete; check_cnt := check_cnt + reference.length; - stimulus.length := 0; - reference.length := 0; + stimulus := EMPTY_TEST_PACKET; + reference := EMPTY_TEST_PACKET; Log("Sending valid HEARTBEAT [User Traffic]", INFO); -- UDP Header @@ -761,8 +758,8 @@ begin start_test; wait_on_complete; check_cnt := check_cnt + reference.length; - stimulus.length := 0; - reference.length := 0; + stimulus := EMPTY_TEST_PACKET; + reference := EMPTY_TEST_PACKET; Log("Sending invalid HEARTBEAT [Packet Size too small]", INFO); -- UDP Header @@ -780,8 +777,8 @@ begin start_test; wait_on_complete; check_cnt := check_cnt + reference.length; - stimulus.length := 0; - reference.length := 0; + stimulus := EMPTY_TEST_PACKET; + reference := EMPTY_TEST_PACKET; Log("Sending invalid HEARTBEAT [Submessage Length too small]", INFO); -- UDP Header @@ -802,8 +799,8 @@ begin start_test; wait_on_complete; check_cnt := check_cnt + reference.length; - stimulus.length := 0; - reference.length := 0; + stimulus := EMPTY_TEST_PACKET; + reference := EMPTY_TEST_PACKET; Log("Sending invalid HEARTBEAT [FirstSN invalid]", INFO); -- UDP Header @@ -824,8 +821,8 @@ begin start_test; wait_on_complete; check_cnt := check_cnt + reference.length; - stimulus.length := 0; - reference.length := 0; + stimulus := EMPTY_TEST_PACKET; + reference := EMPTY_TEST_PACKET; Log("Sending invalid HEARTBEAT [LastSN invalid]", INFO); -- UDP Header @@ -846,8 +843,8 @@ begin start_test; wait_on_complete; check_cnt := check_cnt + reference.length; - stimulus.length := 0; - reference.length := 0; + stimulus := EMPTY_TEST_PACKET; + reference := EMPTY_TEST_PACKET; Log("Sending invalid HEARTBEAT [LastSN < FirstSN - 1]", INFO); -- UDP Header @@ -869,8 +866,8 @@ begin start_test; wait_on_complete; check_cnt := check_cnt + reference.length; - stimulus.length := 0; - reference.length := 0; + stimulus := EMPTY_TEST_PACKET; + reference := EMPTY_TEST_PACKET; -- *INFO_SOURCE SUBMESSAGE* Log("Testing INFO_SOURCE interpretation", INFO); @@ -912,8 +909,8 @@ begin start_test; wait_on_complete; check_cnt := check_cnt + reference.length; - stimulus.length := 0; - reference.length := 0; + stimulus := EMPTY_TEST_PACKET; + reference := EMPTY_TEST_PACKET; Log("Sending invalid INFO_SOURCE [Submessage Length too small]", INFO); -- UDP Header @@ -933,8 +930,8 @@ begin start_test; wait_on_complete; check_cnt := check_cnt + reference.length; - stimulus.length := 0; - reference.length := 0; + stimulus := EMPTY_TEST_PACKET; + reference := EMPTY_TEST_PACKET; -- *INFO_DESTINATION SUBMESSAGE* @@ -976,8 +973,8 @@ begin start_test; wait_on_complete; check_cnt := check_cnt + reference.length; - stimulus.length := 0; - reference.length := 0; + stimulus := EMPTY_TEST_PACKET; + reference := EMPTY_TEST_PACKET; Log("Sending invalid INFO_DESTINATION [Submessage Length too small]", INFO); -- UDP Header @@ -997,8 +994,8 @@ begin start_test; wait_on_complete; check_cnt := check_cnt + reference.length; - stimulus.length := 0; - reference.length := 0; + stimulus := EMPTY_TEST_PACKET; + reference := EMPTY_TEST_PACKET; -- *INFO_REPLY SUBMESSAGE* @@ -1057,8 +1054,8 @@ begin start_test; wait_on_complete; check_cnt := check_cnt + reference.length; - stimulus.length := 0; - reference.length := 0; + stimulus := EMPTY_TEST_PACKET; + reference := EMPTY_TEST_PACKET; Log("Sending invalid INFO_REPLY [Submessage Length too small]", INFO); -- UDP Header @@ -1081,8 +1078,8 @@ begin start_test; wait_on_complete; check_cnt := check_cnt + reference.length; - stimulus.length := 0; - reference.length := 0; + stimulus := EMPTY_TEST_PACKET; + reference := EMPTY_TEST_PACKET; -- *INFO_REPLY_IP4 SUBMESSAGE* @@ -1129,8 +1126,8 @@ begin start_test; wait_on_complete; check_cnt := check_cnt + reference.length; - stimulus.length := 0; - reference.length := 0; + stimulus := EMPTY_TEST_PACKET; + reference := EMPTY_TEST_PACKET; Log("Sending invalid INFO_REPLY_IP4 [Submessage Length too small]", INFO); -- UDP Header @@ -1150,8 +1147,8 @@ begin start_test; wait_on_complete; check_cnt := check_cnt + reference.length; - stimulus.length := 0; - reference.length := 0; + stimulus := EMPTY_TEST_PACKET; + reference := EMPTY_TEST_PACKET; -- *INFO TS* Log("Testing INFO_TIMESTAMP interpretation", INFO); @@ -1196,8 +1193,8 @@ begin start_test; wait_on_complete; check_cnt := check_cnt + reference.length; - stimulus.length := 0; - reference.length := 0; + stimulus := EMPTY_TEST_PACKET; + reference := EMPTY_TEST_PACKET; Log("Sending invalid INFO_TMESTAMP [Submessage Length too small]", INFO); -- UDP Header @@ -1217,8 +1214,8 @@ begin start_test; wait_on_complete; check_cnt := check_cnt + reference.length; - stimulus.length := 0; - reference.length := 0; + stimulus := EMPTY_TEST_PACKET; + reference := EMPTY_TEST_PACKET; -- *PAD* @@ -1245,8 +1242,8 @@ begin start_test; wait_on_complete; check_cnt := check_cnt + reference.length; - stimulus.length := 0; - reference.length := 0; + stimulus := EMPTY_TEST_PACKET; + reference := EMPTY_TEST_PACKET; -- *UNKNOWN* @@ -1300,8 +1297,8 @@ begin start_test; wait_on_complete; check_cnt := check_cnt + reference.length; - stimulus.length := 0; - reference.length := 0; + stimulus := EMPTY_TEST_PACKET; + reference := EMPTY_TEST_PACKET; AlertIf(GetAffirmCount < check_cnt, "Incomplete test run"); ReportAlerts; @@ -1404,7 +1401,7 @@ begin if (cnt_ref = reference.length) then ref_stage <= IDLE; elsif (builtin_wr = '1' or user_wr /= (0 to NUM_ENDPOINTS-1 => '0')) then - AffirmIfEqual(data_out, reference.data(cnt_ref)); + AffirmIfEqual(last_word_out & data_out, reference.last(cnt_ref) & reference.data(cnt_ref)); cnt_ref <= cnt_ref + 1; end if; end case; diff --git a/src/Tests/Level_0/rtps_handler_test2.vhd b/src/Tests/Level_0/rtps_handler_test2.vhd index a9f7417..a9b3d35 100644 --- a/src/Tests/Level_0/rtps_handler_test2.vhd +++ b/src/Tests/Level_0/rtps_handler_test2.vhd @@ -44,13 +44,10 @@ architecture testbench of rtps_handler_test2 is -- *SIGNAL DECLARATION* signal clk, reset, in_empty, rd_sig, builtin_full, builtin_wr, last_word_out : std_logic := '0'; - signal user_full, user_wr : std_logic_vector(NUM_ENDPOINTS-1 downto 0) := (others => '0'); + signal user_full, user_wr : std_logic_vector(0 to NUM_ENDPOINTS-1) := (others => '0'); signal data_in, data_out : std_logic_vector(WORD_WIDTH-1 downto 0) := (others => '0'); signal stim_stage, ref_stage : TEST_STAGE_TYPE := IDLE; - shared variable stimulus, dummy : TEST_PACKET_TYPE := ( - data => (others => (others => '0')), - length => 0 - ); + shared variable stimulus, dummy : TEST_PACKET_TYPE := EMPTY_TEST_PACKET; signal packet_sent, packet_checked : std_logic := '0'; signal cnt_stim, cnt_ref : natural := 0; signal start : std_logic := '0'; @@ -94,7 +91,7 @@ begin variable tmp_id : std_logic_vector(ENTITYID_WIDTH-1 downto 0); variable is_meta : boolean; - -- "Cheat" to use procedure as function + -- Wrapper to use procedure as function impure function gen_rand_loc_2 return LOCATOR_TYPE is variable ret : LOCATOR_TYPE := EMPTY_LOCATOR; begin @@ -127,7 +124,7 @@ begin -- Default Valid Data Submessage rtps_data := DEFAULT_RTPS_SUBMESSAGE; rtps_data.flags(SUBMESSAGE_DATA_FLAG_POS) := '1'; - rtps_data.data := (length => 2, data => (0 => RV.RandSlv(WORD_WIDTH), 1 => RV.RandSlv(WORD_WIDTH), others => (others => '0'))); + rtps_data.data := (length => 2, data => (0 => RV.RandSlv(WORD_WIDTH), 1 => RV.RandSlv(WORD_WIDTH), others => (others => '0')), last => (others => '0')); diff --git a/src/rtps_handler.vhd b/src/rtps_handler.vhd index 225c705..b8f1341 100644 --- a/src/rtps_handler.vhd +++ b/src/rtps_handler.vhd @@ -575,22 +575,25 @@ begin end case; end if; when PARSE_INFO_TS => - rd_guard := '1'; - cnt_next <= cnt + 1; - - case (cnt) is - -- Timesatmp 1/2 - when 0 => - src_ts_next(0) <= unsigned(data_in_swapped); - -- Timesatmp 2/2 - when 1 => - src_ts_next(1) <= unsigned(data_in_swapped); - - -- DONE - stage_next <= SKIP_SUB; - when others => - null; - end case; + -- Input FIFO Guard + if (empty = '0') then + rd_guard := '1'; + cnt_next <= cnt + 1; + + case (cnt) is + -- Timesatmp 1/2 + when 0 => + src_ts_next(0) <= unsigned(data_in_swapped); + -- Timesatmp 2/2 + when 1 => + src_ts_next(1) <= unsigned(data_in_swapped); + + -- DONE + stage_next <= SKIP_SUB; + when others => + null; + end case; + end if; when PARSE_INFO_REPLY => -- Input FIFO Guard if (empty = '0') then @@ -1135,7 +1138,6 @@ begin -- Keep Sub-State cnt_next <= cnt; - -- Exit Condition end if; -- Count when 4 => @@ -1182,18 +1184,24 @@ begin -- Keep Sub-State cnt_next <= cnt; - -- Exit Condition - else - -- DONE - stage_next <= SKIP_SUB; end if; + -- NOTE: Because we need to pull "last_word_out" high on the last Byte, and doing so in the last Byte of Bitmap was deemed + -- to much overhead (We need a counter in addition to cnt2 to track the next-to-last Byte of the Bitmap), we just + -- define the Frame with an additional dummy word in the end. + -- UNUSED + when 6 => + data_out <= (others => '0'); + wr_sig <= '1'; + last_word_out <= '1'; + + -- DONE + stage_next <= SKIP_SUB; when others => null; end case; when SID_DATA => -- Last Payload Word if (read_cnt = sub_end) then - last_word_out <= '1'; -- Begin parsing of next submessage stage_next <= RTPS_SUB_HEADER; -- Reset alignement @@ -1210,14 +1218,31 @@ begin -- Push Payload data_out <= data_in_aligned; wr_sig <= '1'; + + if (read_cnt_plus = sub_end) then + last_word_out <= '1'; + -- Begin parsing of next submessage + stage_next <= RTPS_SUB_HEADER; + -- Reset alignement + align_offset_next <= (others => '0'); + -- Reset Submessage End + sub_end_next <= (others => '1'); + end if; end if; when others => stage_next <= SKIP_SUB; end case; end if; when SKIP_SUB => + -- End of Packet + if (read_cnt = packet_length) then + -- Continue parsing next Packet + stage_next <= SRC_ADDR_HEADER; + -- Reset Lengths + packet_length_next <= (others => '1'); + sub_end_next <= (others => '1'); -- End of Submessage - if (read_cnt = sub_end) then + elsif (read_cnt = sub_end) then -- Begin parsing of next submessage stage_next <= RTPS_SUB_HEADER; -- Reset Submessage End @@ -1248,7 +1273,6 @@ begin end case; -- OVERREAD GUARD - -- XXX: Read from signal we set -- Read outside of packet Length -- NOTE: If the Packet Length is smaller than expected there will be a read from input FIFO while -- the Packet Length has been reached and will be caught by this clause. diff --git a/src/rtps_test_package.vhd b/src/rtps_test_package.vhd index c9adafc..8efef99 100644 --- a/src/rtps_test_package.vhd +++ b/src/rtps_test_package.vhd @@ -15,12 +15,32 @@ package rtps_test_package is constant DEFAULT_GUIDPREFIX : GUIDPREFIX_TYPE; -- Deferred to Package Body constant DEFAULT_ENTITYID : std_logic_vector(ENTITYID_WIDTH-1 downto 0); -- Deferred to Package Body + type TEST_RAM_TYPE is array (0 to (MAX_REMOTE_PARTICIPANTS*PARTICIPANT_FRAME_SIZE)-1) of std_logic_vector(WORD_WIDTH-1 downto 0); + + type MATCH_TYPE is (MATCH, UNMATCH); + type TEST_PACKET_TYPE is record -- Limit Packet Size to 2^16 (IPv4 size limit) data : WORD_ARRAY_TYPE(0 to (2**16)/4); + last : std_logic_vector(0 to (2**16)/4); length : natural; end record; + constant EMPTY_TEST_PACKET : TEST_PACKET_TYPE; -- Deferred to Package Body + + type TEST_MEMORY_ELEMENT_TYPE is record + addr : natural; + data : std_logic_vector(WORD_WIDTH-1 downto 0); + end record; + + type TEST_MEMORY_TYPE is array (natural range <>) of TEST_MEMORY_ELEMENT_TYPE; + + subtype TEST_PARTICIPANT_MEMORY_FRAME_TYPE is TEST_MEMORY_TYPE(0 to PARTICIPANT_FRAME_SIZE-1); + subtype TEST_ENDPOINT_MEMORY_FRAME_TYPE is TEST_MEMORY_TYPE(0 to ENDPOINT_FRAME_SIZE-1); + + function test_memory_match (A,B : TEST_MEMORY_TYPE) return boolean; + function to_string (input : TEST_MEMORY_TYPE) return string; + constant LOCATOR_PORT_WIDTH : natural := CDR_LONG_WIDTH; constant LOCATOR_ADDR_WIDTH : natural := 4*CDR_LONG_WIDTH; @@ -145,11 +165,15 @@ package rtps_test_package is 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); + match : MATCH_TYPE; + nr : natural; end record; constant DEFAULT_PARTICIPANT_DATA : PARTICIPANT_DATA_TYPE; -- Deferred to Pckage Body - procedure gen_participant_announcement( ref : in PARTICIPANT_DATA_TYPE; output : inout TEST_PACKET_TYPE); + procedure gen_participant_data( ref : in PARTICIPANT_DATA_TYPE; output : inout TEST_PACKET_TYPE); + --function gen_participant_data2 ( ref : PARTICIPANT_DATA_TYPE) return TEST_PACKET_TYPE; + function gen_participant_mem_frame (ref : PARTICIPANT_DATA_TYPE) return TEST_PARTICIPANT_MEMORY_FRAME_TYPE; type ENDPOINT_DATA_TYPE is record littleEndian : std_logic; @@ -220,6 +244,8 @@ package body rtps_test_package is constant DEFAULT_ENTITYID : std_logic_vector(ENTITYID_WIDTH-1 downto 0) := x"b9cbad8d"; + constant EMPTY_TEST_PACKET : TEST_PACKET_TYPE := (length => 0, data => (others => (others => '0')), last => (others => '0')); + constant EMPTY_LOCATOR : LOCATOR_TYPE := ( kind => LOCATOR_KIND_INVALID, portn => (others => '0'), @@ -312,7 +338,7 @@ package body rtps_test_package is octetsToInlineQos => int(16, SUBMESSAGE_LENGTH_WIDTH), writerSN => FIRST_SEQUENCENUMBER, fragmentNumberState => DEFAULT_FRAGMENTNUMBER_SET, - data => (length => 0, data => (others => (others => '0'))), + data => EMPTY_TEST_PACKET, fragmentStartingNumber => int(1,CDR_LONG_WIDTH), fragmentsInSubmessage => int(1,CDR_SHORT_WIDTH), fragmentSize => (others => '0'), @@ -335,8 +361,8 @@ package body rtps_test_package is constant DEFAULT_PARTICIPANT_DATA : PARTICIPANT_DATA_TYPE := ( littleEndian => '0', - domainId => (others => '0'), - domainTag => (others => (others => '0')), + domainId => DOMAIN_ID, + domainTag => DOMAIN_TAG, protocolVersion => PROTOCOLVERSION_2_4, vendorId => VENDORID_UNKNOWN, guidPrefix => GUIDPREFIX_UNKNOWN, @@ -346,10 +372,12 @@ package body rtps_test_package is metatrafficMulticastLocatorList => EMPTY_LOCATOR_LIST, defaultUnicastLocatorList => EMPTY_LOCATOR_LIST, -- NOTE: Has to be initialized defaultMulticastLocatorList => EMPTY_LOCATOR_LIST, - leaseDuration => DEFAULT_PARTICIPANT_LEASE_DURATION, + leaseDuration => 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') + 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'), + match => MATCH, + nr => 0 ); constant DEFAULT_ENDPOINT_DATA : ENDPOINT_DATA_TYPE := ( @@ -504,6 +532,31 @@ package body rtps_test_package is end loop; end procedure; + function is_valid_loc (ref : LOCATOR_TYPE) return boolean is + begin + if (ref.kind /= LOCATOR_KIND_UDPv4) then + return FALSE; + elsif (ref.addr(IPv4_ADDRESS_WIDTH-1 downto 0) = (IPv4_ADDRESS_WIDTH-1 downto 0 => '0')) then + return FALSE; + elsif (ref.portn(UDP_PORT_WIDTH-1 downto 0) = (UDP_PORT_WIDTH-1 downto 0 => '0')) then + return FALSE; + else + return TRUE; + end if; + end function; + + function get_loc (ref : LOCATOR_LIST_TYPE) return LOCATOR_TYPE is + variable ret : LOCATOR_TYPE := EMPTY_LOCATOR; + begin + for i in 0 to to_integer(unsigned(ref.numLocators))-1 loop + if (is_valid_loc(ref.locator(i))) then + ret := ref.locator(i); + end if; + end loop; + + return ret; + end function; + procedure gen_rtps_submessage( ref : in RTPS_SUBMESSAGE_TYPE; output : inout TEST_PACKET_TYPE) is variable start : natural := 0; variable tmp : natural := 0; @@ -788,10 +841,16 @@ package body rtps_test_package is output.length := output.length + 1; -- Gap List write_sequence_ns(ref.gapList, '0', output); + -- UNUSED + output.data(output.length) := (others => '0'); + output.length := output.length + 1; end if; + + -- Mark Last Word + output.last(output.length-1) := '1'; end procedure; - procedure gen_participant_announcement( ref : in PARTICIPANT_DATA_TYPE; output : inout TEST_PACKET_TYPE) is + procedure gen_participant_data( ref : in PARTICIPANT_DATA_TYPE; output : inout TEST_PACKET_TYPE) is variable tmp : natural := 0; begin -- Representation Identifier & Representation Options @@ -849,6 +908,28 @@ package body rtps_test_package is output.data(output.length)(31 downto 24) := ref.expectsInlineQoS; -- 1 Byte, No endian swap output.length := output.length + 1; end if; + -- METATRAFFIC MULTICAST LOCATOR + if (ref.metatrafficMulticastLocatorList.numLocators /= (ref.metatrafficMulticastLocatorList.numLocators'range => '0')) then + tmp := to_integer(unsigned(ref.metatrafficMulticastLocatorList.numLocators)); + output.data(output.length) := PID_METATRAFFIC_MULTICAST_LOCATOR & endian_swap(ref.littleEndian, int(((tmp*6)+1)*4,PARAMETER_LENGTH_WIDTH)); + output.length := output.length + 1; + output.data(output.length) := endian_swap(ref.littleEndian, ref.metatrafficMulticastLocatorList.numLocators); + output.length := output.length + 1; + for i in 0 to tmp-1 loop + output.data(output.length) := endian_swap(ref.littleEndian, ref.metatrafficMulticastLocatorList.locator(i).kind); + output.length := output.length + 1; + output.data(output.length) := endian_swap(ref.littleEndian, ref.metatrafficMulticastLocatorList.locator(i).portn); + output.length := output.length + 1; + output.data(output.length) := ref.metatrafficMulticastLocatorList.locator(i).addr(127 downto 96); + output.length := output.length + 1; + output.data(output.length) := ref.metatrafficMulticastLocatorList.locator(i).addr(95 downto 64); + output.length := output.length + 1; + output.data(output.length) := ref.metatrafficMulticastLocatorList.locator(i).addr(63 downto 32); + output.length := output.length + 1; + output.data(output.length) := ref.metatrafficMulticastLocatorList.locator(i).addr(31 downto 0); + output.length := output.length + 1; + end loop; + end if; -- METATRAFFIC UNICAST LOCATOR if (ref.metatrafficUnicastLocatorList.numLocators /= (ref.metatrafficUnicastLocatorList.numLocators'range => '0')) then tmp := to_integer(unsigned(ref.metatrafficUnicastLocatorList.numLocators)); @@ -871,25 +952,25 @@ package body rtps_test_package is 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)); + -- DEFAULT MULTICAST LOCATOR + if (ref.defaultMulticastLocatorList.numLocators /= (ref.defaultMulticastLocatorList.numLocators'range => '0')) then + tmp := to_integer(unsigned(ref.defaultMulticastLocatorList.numLocators)); output.data(output.length) := PID_METATRAFFIC_MULTICAST_LOCATOR & endian_swap(ref.littleEndian, int(((tmp*6)+1)*4,PARAMETER_LENGTH_WIDTH)); output.length := output.length + 1; - output.data(output.length) := endian_swap(ref.littleEndian, ref.metatrafficMulticastLocatorList.numLocators); + output.data(output.length) := endian_swap(ref.littleEndian, ref.defaultMulticastLocatorList.numLocators); output.length := output.length + 1; for i in 0 to tmp-1 loop - output.data(output.length) := endian_swap(ref.littleEndian, ref.metatrafficMulticastLocatorList.locator(i).kind); + output.data(output.length) := endian_swap(ref.littleEndian, ref.defaultMulticastLocatorList.locator(i).kind); output.length := output.length + 1; - output.data(output.length) := endian_swap(ref.littleEndian, ref.metatrafficMulticastLocatorList.locator(i).portn); + output.data(output.length) := endian_swap(ref.littleEndian, ref.defaultMulticastLocatorList.locator(i).portn); output.length := output.length + 1; - output.data(output.length) := ref.metatrafficMulticastLocatorList.locator(i).addr(127 downto 96); + output.data(output.length) := ref.defaultMulticastLocatorList.locator(i).addr(127 downto 96); output.length := output.length + 1; - output.data(output.length) := ref.metatrafficMulticastLocatorList.locator(i).addr(95 downto 64); + output.data(output.length) := ref.defaultMulticastLocatorList.locator(i).addr(95 downto 64); output.length := output.length + 1; - output.data(output.length) := ref.metatrafficMulticastLocatorList.locator(i).addr(63 downto 32); + output.data(output.length) := ref.defaultMulticastLocatorList.locator(i).addr(63 downto 32); output.length := output.length + 1; - output.data(output.length) := ref.metatrafficMulticastLocatorList.locator(i).addr(31 downto 0); + output.data(output.length) := ref.defaultMulticastLocatorList.locator(i).addr(31 downto 0); output.length := output.length + 1; end loop; end if; @@ -916,28 +997,6 @@ package body rtps_test_package is 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(output.length) := PID_METATRAFFIC_MULTICAST_LOCATOR & endian_swap(ref.littleEndian, int(((tmp*6)+1)*4,PARAMETER_LENGTH_WIDTH)); - output.length := output.length + 1; - output.data(output.length) := endian_swap(ref.littleEndian, ref.defaultMulticastLocatorList.numLocators); - output.length := output.length + 1; - for i in 0 to tmp-1 loop - output.data(output.length) := endian_swap(ref.littleEndian, ref.defaultMulticastLocatorList.locator(i).kind); - output.length := output.length + 1; - output.data(output.length) := endian_swap(ref.littleEndian, ref.defaultMulticastLocatorList.locator(i).portn); - output.length := output.length + 1; - output.data(output.length) := ref.defaultMulticastLocatorList.locator(i).addr(127 downto 96); - output.length := output.length + 1; - output.data(output.length) := ref.defaultMulticastLocatorList.locator(i).addr(95 downto 64); - output.length := output.length + 1; - output.data(output.length) := ref.defaultMulticastLocatorList.locator(i).addr(63 downto 32); - output.length := output.length + 1; - output.data(output.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(output.length) := PID_PARTICIPANT_LEASE_DURATION & endian_swap(ref.littleEndian, int(8,PARAMETER_LENGTH_WIDTH)); @@ -959,6 +1018,115 @@ package body rtps_test_package is output.length := output.length + 1; end procedure; + --function gen_participant_data2 ( ref : PARTICIPANT_DATA_TYPE) return TEST_PACKET_TYPE is + -- variable ret : TEST_PACKET_TYPE := (length => 0, data => (others => (others => '0')), last => (others => '0')); + --begin + -- gen_participant_data(ref, ret); + -- return ret; + --end function; + + function gen_participant_mem_frame (ref : PARTICIPANT_DATA_TYPE) return TEST_PARTICIPANT_MEMORY_FRAME_TYPE is + variable ret : TEST_PARTICIPANT_MEMORY_FRAME_TYPE; + variable start : natural; + variable meta_loc : LOCATOR_TYPE; + variable user_loc : LOCATOR_TYPE; + begin + ret := (others => (addr => 0, data => (others => '0'))); + + -- Calculate Start Address + start := PARTICIPANT_FRAME_SIZE * ref.nr; + + -- Fetch relevant Locators + if (is_valid_loc(get_loc(ref.metatrafficUnicastLocatorList))) then + meta_loc := get_loc(ref.metatrafficUnicastLocatorList); + elsif (is_valid_loc(get_loc(ref.metatrafficMulticastLocatorList))) then + meta_loc := get_loc(ref.metatrafficMulticastLocatorList); + else + meta_loc := DEST_LOC.meta.locator(0); + end if; + if (is_valid_loc(get_loc(ref.defaultUnicastLocatorList))) then + user_loc := get_loc(ref.defaultUnicastLocatorList); + elsif (is_valid_loc(get_loc(ref.defaultMulticastLocatorList))) then + user_loc := get_loc(ref.defaultMulticastLocatorList); + else + user_loc := EMPTY_LOCATOR; + end if; + + for i in 0 to PARTICIPANT_FRAME_SIZE-1 loop + ret(i).addr := start + i; + case (i) is + -- GUID Prefix 1/3 + when 0 => + if (ref.match = MATCH) then + ret(i).data := ref.guidPrefix(0); + else + ret(i).data := (others => '0'); + end if; + -- GUID Prefix 2/3 + when 1 => + if (ref.match = MATCH) then + ret(i).data := ref.guidPrefix(1); + else + ret(i).data := (others => '0'); + end if; + -- GUID Prefix 3/3 + when 2 => + if (ref.match = MATCH) then + ret(i).data := ref.guidPrefix(2); + else + ret(i).data := (others => '0'); + end if; + -- METATRAFFIC IPv4 Address + when 3 => + if (ref.match = MATCH) then + ret(i).data := meta_loc.addr(IPv4_ADDRESS_WIDTH-1 downto 0); + else + ret(i).data := (others => '-'); + end if; + -- DEFAULT IPv4 Address + when 4 => + if (ref.match = MATCH) then + ret(i).data := user_loc.addr(IPv4_ADDRESS_WIDTH-1 downto 0); + else + ret(i).data := (others => '-'); + end if; + -- METATRAFFIC & DEFAULT UDP Port + when 5 => + if (ref.match = MATCH) then + ret(i).data := meta_loc.portn(UDP_PORT_WIDTH-1 downto 0) & user_loc.portn(UDP_PORT_WIDTH-1 downto 0); + else + ret(i).data := (others => '-'); + end if; + -- SPDP Sequence Number 1/2 + when 6 => + -- Ignored + ret(i).data := (others => '-'); + -- SPDP Sequence Number 2/2 + when 8 => + -- Ignored + ret(i).data := (others => '-'); + -- Lease Duration 1/2 + when 9 => + if (ref.match = MATCH) then + ret(i).data := std_logic_vector(ref.leaseDuration(0)); + else + ret(i).data := (others => '-'); + end if; + -- Lease Duration 2/2 + when 10 => + if (ref.match = MATCH) then + ret(i).data := std_logic_vector(ref.leaseDuration(1)); + else + ret(i).data := (others => '-'); + end if; + -- Other Fields Ignored + when others => + ret(i).data := (others => '-'); + end case; + end loop; + return ret; + end function; + procedure gen_endpoint_data( ref : in ENDPOINT_DATA_TYPE; output : inout TEST_PACKET_TYPE) is variable tmp : natural := 0; begin @@ -1210,4 +1378,23 @@ package body rtps_test_package is end if; end procedure; + function test_memory_match (A,B : TEST_MEMORY_TYPE) return boolean is + begin + if (A'length /= B'length) then + return FALSE; + end if; + + for i in 0 to A'length loop + if (A(i).addr /= B(i).addr or (A(i).data ?/= B(i).data) = '1') then + return FALSE; + end if; + end loop; + return TRUE; + end function; + + function to_string (input : TEST_MEMORY_TYPE) return string is + begin + return "length: " & integer'image(input'length) & ", start_addr: " & integer'image(input(0).addr) & "end_addr: " & integer'image(input(input'length-1).addr); + end function; + end package body; \ No newline at end of file