* 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
This commit is contained in:
Greek 2020-11-21 21:05:57 +01:00
parent e624ba4bac
commit 16bd4558de
6 changed files with 373 additions and 165 deletions

View File

@ -151,6 +151,8 @@ GAP PAYLOAD
+-------------------------------------------------------------+
| [GapList.Bitmap] x 0-8 |
+-------------------------------------------------------------+
| UNUSED |
+-------------------------------------------------------------+
ENDPOINT_ID
===========

View File

@ -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

View File

@ -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;

View File

@ -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'));

View File

@ -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.

View File

@ -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;