* rtps_builtin_endpoint in-memory fromat change

- Do not store local endpoint mask of remote endpoints
	- Send MATCH/UNMATCH Frames to all local Endpoinst (Not only previously matched)
This commit is contained in:
Greek 2020-11-28 14:28:35 +01:00
parent c411cab887
commit eac58dd183
5 changed files with 107 additions and 180 deletions

View File

@ -235,10 +235,6 @@ ENDPOINT DATA
+ +
03| |
+-------------------------------------------------------------+
04| |
~ ENDPOINT_BITMASK ~
**| |
+-------------------------------------------------------------+
ENDPOINT MATCH FRAME
====================

View File

@ -117,6 +117,14 @@ DESIGN DECISIONS
Use the lowest bit of the Heartbeat/Acknack Deadline stored in the Participant Data to differentiate
between Delay and Suppression. This reduces the resolution from 0.23 ns to 0.47 ns
* Originally we stored the mask of local matching endpoints in the memory frame of the remote endpoint in order
to be able to send MATCH frames only to new matches, and UNMATCH frames only to previously matched local endpoints.
This decision was reverted, and we just sent MATCH frames to the currently matched local endpoints (non depending on if they are already matched)
and UNMATCH frames to the rest of the local endpoints (non depending on if they were previously matched).
So we basically push the responsibility to the local endpoints, which have to handle this situations accordingly.
Since META traffic is not supposed to be generated as often , this should not produce any significant overhead.
As optimization, on new matched remote endpoints UNMATCH frames can be ignored.
PROTOCOL UNCOMPLIANCE
=====================
* Partition QoS

View File

@ -495,7 +495,9 @@ begin
endpoint.match := UNMATCH;
gen_match_frame(endpoint, reference);
wr_sig := gen_wr(i, FALSE);
-- If Endpoint was previously matched, unmatch
if (or wr_sig = '1') then
wr_sig := (others => '1');
push_reference;
end if;
reference := EMPTY_TEST_PACKET;
@ -507,7 +509,9 @@ begin
endpoint.match := UNMATCH;
gen_match_frame(endpoint, reference);
wr_sig := gen_wr(i, TRUE);
-- If Endpoint was previously matched, unmatch
if (or wr_sig = '1') then
wr_sig := (others => '1');
push_reference;
end if;
reference := EMPTY_TEST_PACKET;
@ -778,9 +782,18 @@ begin
gen_endpoint_data(e1, sub_p.data);
gen_sentinel(sub_p.data);
gen_rtps_handler_out(sub_p, e1, stimulus);
-- UNMATCH
e1.match := UNMATCH;
gen_match_frame(e1, reference);
wr_sig := (0 => '1', 9 => '1', 10 => '1', 15 => '1', others => '0');
wr_sig := not wr_sig;
push_reference;
reference := EMPTY_TEST_PACKET;
-- MATCH
e1.match := MATCH;
gen_match_frame(e1, reference);
wr_sig := not wr_sig;
push_reference;
start_test;
wait_on_complete;
stimulus := EMPTY_TEST_PACKET;
@ -797,8 +810,17 @@ begin
gen_endpoint_data(e2, sub_s.data);
gen_sentinel(sub_s.data);
gen_rtps_handler_out(sub_s, e2, stimulus);
-- UNMATCH
e2.match := UNMATCH;
gen_match_frame(e2, reference);
wr_sig := (NUM_READERS => '1', NUM_READERS+4 => '1', NUM_READERS+5 => '1', NUM_READERS+7 => '1', others => '0');
wr_sig := not wr_sig;
push_reference;
reference := EMPTY_TEST_PACKET;
-- MATCH
e2.match := MATCH;
gen_match_frame(e2, reference);
wr_sig := not wr_sig;
push_reference;
start_test;
wait_on_complete;
@ -813,15 +835,17 @@ begin
gen_endpoint_data(e1, sub_p.data);
gen_sentinel(sub_p.data);
gen_rtps_handler_out(sub_p, e1, stimulus);
-- MATCH
gen_match_frame(e1, reference);
wr_sig := (15 => '1', others => '0');
push_reference;
reference := EMPTY_TEST_PACKET;
-- UNMATCH
e1.match := UNMATCH;
gen_match_frame(e1, reference);
wr_sig := (0 => '1', 9 => '1', 10 => '1', others => '0');
wr_sig := (15 => '1', others => '0');
wr_sig := not wr_sig;
push_reference;
reference := EMPTY_TEST_PACKET;
-- MATCH
e1.match := MATCH;
gen_match_frame(e1, reference);
wr_sig := not wr_sig;
push_reference;
start_test;
wait_on_complete;
@ -837,15 +861,17 @@ begin
gen_endpoint_data(e2, sub_s.data);
gen_sentinel(sub_s.data);
gen_rtps_handler_out(sub_s, e2, stimulus);
-- MATCH
gen_match_frame(e2, reference);
wr_sig := (NUM_READERS+2 => '1', others => '0');
push_reference;
reference := EMPTY_TEST_PACKET;
-- UNMATCH
e2.match := UNMATCH;
gen_match_frame(e2, reference);
wr_sig := (NUM_READERS => '1', NUM_READERS+4 => '1', NUM_READERS+5 => '1', NUM_READERS+7 => '1', others => '0');
wr_sig := (NUM_READERS+2 => '1', others => '0');
wr_sig := not wr_sig;
push_reference;
reference := EMPTY_TEST_PACKET;
-- MATCH
e2.match := MATCH;
gen_match_frame(e2, reference);
wr_sig := not wr_sig;
push_reference;
start_test;
wait_on_complete;

View File

@ -11,7 +11,6 @@ use work.rtps_config_package.all;
-- TODO: Skip Packet while we are waiting for memory operation to complete
-- TODO: add_res is still valid after removal. So we could continue searching the next orphan endpoint from that address on
-- TODO: is it really necessary to process Sequence Numbers in sequence? Could we not just accept any higher Sequence Number?
-- TODO: Remove the Endpoint Bitmask from Memory and just always send MATCH/UNMATCH Frames
entity rtps_builtin_endpoint is
port (
@ -72,8 +71,8 @@ architecture arch of rtps_builtin_endpoint is
SEND_PARTICIPANT_ANNOUNCEMENT, SEND_PUB_DATA, SEND_SUB_DATA, SEND_MES_MAN_LIVE, SEND_MES_GAP, SEND_MES_AUTO_LIVE,
LIVELINESS_UPDATE, SKIP_PARAMETER, SKIP_PACKET);
-- Memory FSM states. Explained below in detail
type MEM_STAGE_TYPE is (IDLE, SEARCH_PARTICIPANT, GET_PARTICIPANT_DATA, SEARCH_ENDPOINT, GET_ENDPOINT_MASK, REMOVE_PARTICIPANT,
REMOVE_ENDPOINT, UPDATE_ENDPOINT, FIND_PARTICIPANT_SLOT, INSERT_PARTICIPANT, FIND_ENDPOINT_SLOT, INSERT_ENDPOINT,
type MEM_STAGE_TYPE is (IDLE, SEARCH_PARTICIPANT, GET_PARTICIPANT_DATA, SEARCH_ENDPOINT, REMOVE_PARTICIPANT,
REMOVE_ENDPOINT, FIND_PARTICIPANT_SLOT, INSERT_PARTICIPANT, FIND_ENDPOINT_SLOT, INSERT_ENDPOINT,
FIND_NEXT_PARTICIPANT, FIND_STALE_PARTICIPANT, UPDATE_PARTICIPANT);
-- Memory FSM Opcodes
-- OPCODE DESCRIPTION
@ -98,7 +97,7 @@ architecture arch of rtps_builtin_endpoint is
-- FIND_NEXT_PARTICIPANT Find next occupied Participant Entry in memory from the Participant Entry pointed by "addr_res".
-- Set "addr_res" signal to Base Address of found Participant Entry or MAX Address if nothing found.
type MEM_OPCODE_TYPE is (NOP, SEARCH_PARTICIPANT, SEARCH_ENDPOINT, INSERT_PARTICIPANT, INSERT_ENDPOINT, UPDATE_PARTICIPANT,
UPDATE_ENDPOINT, REMOVE_PARTICIPANT, REMOVE_ENDPOINT, FIND_STALE_PARTICIPANT, FIND_FIRST_PATICIPANT, FIND_NEXT_PARTICIPANT);
REMOVE_PARTICIPANT, REMOVE_ENDPOINT, FIND_STALE_PARTICIPANT, FIND_FIRST_PATICIPANT, FIND_NEXT_PARTICIPANT);
-- RTPS Data Submessage Content:
-- * PDP Simple Participant Discovery Protocol Data
-- * EDP Simple Endpoint Discovery Protocol Data
@ -246,12 +245,6 @@ architecture arch of rtps_builtin_endpoint is
signal compare_length, compare_length_next : unsigned(WORD_WIDTH-3 downto 0) := (others => '0');
-- Bitmask of local Endpoint Matches
signal endpoint_mask, endpoint_mask_next : std_logic_vector(0 to NUM_ENDPOINTS-1) := (others => '0');
-- Bitmask of new local Endpoint Matches
signal endpoint_match, endpoint_match_next : std_logic_vector(0 to NUM_ENDPOINTS-1) := (others => '0');
-- Bitmask of local Endpoint unmatches
signal endpoint_unmatch, endpoint_unmatch_next : std_logic_vector(0 to NUM_ENDPOINTS-1) := (others => '0');
-- Bitmask of local Endpoint Matches stored in Memory
signal endpoint_mask_array, endpoint_mask_array_next : ENDPOINT_BITMASK_ARRAY_TYPE := (others => (others => '0'));
-- Signifies if the source of the Participant Data is compatible with our Participant
signal participant_match, participant_match_next : std_logic := '0';
-- Signifies if the Packet is comming from a Subscriber Endpoint
@ -292,7 +285,7 @@ architecture arch of rtps_builtin_endpoint is
-- Memory Read and Write Enable Signals
signal mem_rd, mem_wr : std_logic := '0';
-- General Purpose Counter (Memory FSM)
signal mem_cnt, mem_cnt_next : natural range 0 to max(22, ENDPOINT_BITMASK_SIZE-1) := 0;
signal mem_cnt, mem_cnt_next : natural range 0 to 22 := 0;
-- Contains the Sequence Number stored in the Buffer of the current relevant Message Type (Participant/Publisher/Subscriber/Message Data)
signal mem_seq_nr, mem_seq_nr_next : SEQUENCENUMBER_TYPE := (others => (others => '0'));
-- Signifies the next expected Sequence Number of the current relevant Message Type (Participant/Publisher/Subscriber/Message Data)
@ -389,37 +382,6 @@ architecture arch of rtps_builtin_endpoint is
alias payload_flag : std_logic is flags(4);
--*****FUNCTION DECLARATION*****
-- Converts std_logic_vector to ENDPOINT_BITMASK_ARRAY
function convert_to_bitmask_array (bitmask : std_logic_vector) return ENDPOINT_BITMASK_ARRAY_TYPE is
variable ret : ENDPOINT_BITMASK_ARRAY_TYPE := (others => (others => '0'));
begin
ret := (others => (others => '0'));
for i in 0 to ENDPOINT_BITMASK_ARRAY_TYPE'length-1 loop
if (i /= ENDPOINT_BITMASK_ARRAY_TYPE'length-1) then
ret(i) := bitmask(i*32 to i*32+31);
else
ret(i)(0 to (bitmask'length mod 32)-1) := bitmask(i*32 to i*32+(bitmask'length mod 32)-1);
end if;
end loop;
return ret;
end function;
-- Converts ENDPOINT_BITMASK_ARRAY to std_logic_vector
function convert_from_bitmask_array (bitmask : ENDPOINT_BITMASK_ARRAY_TYPE; len : natural) return std_logic_vector is
variable ret : std_logic_vector(0 to len-1) := (others => '0');
begin
ret := (others => '0');
for i in 0 to ENDPOINT_BITMASK_ARRAY_TYPE'length-1 loop
if (i /= ENDPOINT_BITMASK_ARRAY_TYPE'length-1) then
ret(i*32 to i*32+31) := bitmask(i);
else
ret(i*32 to i*32+(len mod 32)-1) := bitmask(i)(0 to (len mod 32)-1);
end if;
end loop;
return ret;
end function;
begin
--*****COMPONENT INSTANTIATION*****
@ -512,11 +474,11 @@ begin
case (stage) is
when INFORM_ENDPOINTS_MATCH =>
if (wr_sig = '1') then
endpoint_wr <= endpoint_match;
endpoint_wr <= endpoint_mask;
end if;
when INFORM_ENDPOINTS_UNMATCH =>
if (wr_sig = '1') then
endpoint_wr <= endpoint_unmatch;
endpoint_wr <= not endpoint_mask;
end if;
when LIVELINESS_UPDATE =>
if (wr_sig = '1') then
@ -610,8 +572,6 @@ begin
string_length_next <= string_length;
compare_length_next <= compare_length;
endpoint_mask_next <= endpoint_mask;
endpoint_match_next <= endpoint_match;
endpoint_unmatch_next <= endpoint_unmatch;
participant_match_next <= participant_match;
is_subscriber_next <= is_subscriber;
lease_duration_next <= lease_duration;
@ -1558,9 +1518,8 @@ begin
mem_op_start <= '1';
-- Latch Orphan Entity ID
guid_next(3) <= mem_guid(3);
-- Mark UNMATCHES
endpoint_match_next <= (others => '0');
endpoint_unmatch_next <= convert_from_bitmask_array(endpoint_mask_array, NUM_ENDPOINTS);
-- Mark All UNMATCHES
endpoint_mask_next <= (others => '0');
-- Propagate Unmatches to local Endpoints
stage_next <= INFORM_ENDPOINTS_UNMATCH;
cnt_next <= 0;
@ -2479,9 +2438,6 @@ begin
-- Add Endpoint in buffer
mem_opcode <= INSERT_ENDPOINT;
mem_op_start <= '1';
-- Mark MATCHES
endpoint_match_next <= endpoint_mask;
endpoint_unmatch_next <= (others => '0');
-- Propagate Matches to local Endpoints
stage_next <= INFORM_ENDPOINTS_MATCH;
cnt_next <= 0;
@ -2494,38 +2450,65 @@ begin
else
-- At least one local Endpoint match
if (endpoint_mask /= (endpoint_mask'range => '0')) then
-- Mark Endpoint match changes
tmp_endpoint_mask := convert_from_bitmask_array(endpoint_mask_array, NUM_ENDPOINTS) xor endpoint_mask;
-- Mark UNMATCHES
endpoint_unmatch_next <= tmp_endpoint_mask and convert_from_bitmask_array(endpoint_mask_array, NUM_ENDPOINTS);
-- Mark NEW MATCHES
-- NOTE: Mark all matches and resent the Endpoint Match Frame also to already Matched Endpoints,
-- in order to propagate possible data updates (e.g. new Locator)
--endpoint_match_next <= tmp_endpoint_mask and endpoint_mask;
endpoint_match_next <= endpoint_mask;
-- Update endpoint in buffer
mem_opcode <= UPDATE_ENDPOINT;
mem_op_start <= '1';
-- Propagate Match Changes to local Endpoints
stage_next <= INFORM_ENDPOINTS_MATCH;
stage_next <= INFORM_ENDPOINTS_UNMATCH;
cnt_next <= 0;
-- No local Endpoint match
else
-- Remove endpoint from buffer
mem_opcode <= REMOVE_ENDPOINT;
mem_op_start <= '1';
-- Mark UNMATCHES
endpoint_match_next <= (others => '0');
endpoint_unmatch_next <= convert_from_bitmask_array(endpoint_mask_array, NUM_ENDPOINTS);
-- Mark All UNMATCHES
endpoint_mask_next <= (others => '0');
-- Propagate Unmatches to local Endpoints
stage_next <= INFORM_ENDPOINTS_UNMATCH;
cnt_next <= 0;
end if;
end if;
end if;
when INFORM_ENDPOINTS_UNMATCH =>
-- Output FIFO Guard
if (((not endpoint_mask) and endpoint_full) = (endpoint_full'range => '0')) then
wr_sig <= '1';
cnt_next <= cnt + 1;
case (cnt) is
-- Match Opcode
when 0 =>
data_out <= OPCODE_UNMATCH;
-- GUID Prefix 1/3
when 1 =>
data_out <= guid(0);
-- GUID Prefix 2/3
when 2 =>
data_out <= guid(1);
-- GUID Prefix 3/3
when 3 =>
data_out <= guid(2);
-- Entity ID
when 4 =>
data_out <= guid(3);
last_word_out <= '1';
-- If we are in the middle of an Orphan Purge Process, return to the search stage
if (is_orphan_search = '1') then
stage_next <= FIND_ORPHAN_ENDPOINT;
else
-- If there are Endpoints to match, inform them
if (endpoint_mask /= (endpoint_mask'range => '0')) then
stage_next <= INFORM_ENDPOINTS_MATCH;
cnt_next <= 0;
else
-- DONE
stage_next <= SKIP_PACKET;
end if;
end if;
when others =>
null;
end case;
end if;
when INFORM_ENDPOINTS_MATCH =>
-- Output FIFO Guard
if ((endpoint_match and endpoint_full) = (endpoint_full'range => '0')) then
if ((endpoint_mask and endpoint_full) = (endpoint_full'range => '0')) then
wr_sig <= '1';
cnt_next <= cnt + 1;
@ -2575,48 +2558,8 @@ begin
data_out(0) <= DEFAULT_EXPECTS_INLINE_QOS;
end if;
-- If there are Endpoints to unmatch, inform them
if (endpoint_unmatch /= (endpoint_unmatch'range => '0')) then
stage_next <= INFORM_ENDPOINTS_UNMATCH;
cnt_next <= 0;
else
-- DONE
stage_next <= SKIP_PACKET;
end if;
when others =>
null;
end case;
end if;
when INFORM_ENDPOINTS_UNMATCH =>
-- Output FIFO Guard
if ((endpoint_unmatch and endpoint_full) = (endpoint_full'range => '0')) then
wr_sig <= '1';
cnt_next <= cnt + 1;
case (cnt) is
-- Match Opcode
when 0 =>
data_out <= OPCODE_UNMATCH;
-- GUID Prefix 1/3
when 1 =>
data_out <= guid(0);
-- GUID Prefix 2/3
when 2 =>
data_out <= guid(1);
-- GUID Prefix 3/3
when 3 =>
data_out <= guid(2);
-- Entity ID
when 4 =>
data_out <= guid(3);
last_word_out <= '1';
-- If we are in the middle of an Orphan Purge Process, return to the search stage
if (is_orphan_search = '1') then
stage_next <= FIND_ORPHAN_ENDPOINT;
else
-- DONE
stage_next <= SKIP_PACKET;
end if;
-- DONE
stage_next <= SKIP_PACKET;
when others =>
null;
end case;
@ -3175,11 +3118,10 @@ begin
last_addr_next <= last_addr;
mem_participant_data_next <= mem_participant_data;
is_heartbeat_res_next <= is_heartbeat_res;
endpoint_mask_array_next <= endpoint_mask_array;
max_participant_addr_next <= max_participant_addr;
max_endpoint_addr_next <= max_endpoint_addr;
reset_max_pointer_next <= reset_max_pointer;
mem_guid_next <= mem_guid;
mem_guid_next <= mem_guid;
-- DEFAULT Unregistered
mem_write_data <= (others => '0');
mem_op_done <= '0';
@ -3241,11 +3183,6 @@ begin
mem_addr_next <= addr_res + 17;
mem_cnt_next <= 14;
end if;
when UPDATE_ENDPOINT =>
mem_addr_next <= addr_res + 4;
endpoint_mask_array_next <= convert_to_bitmask_array(endpoint_mask);
mem_stage_next <= UPDATE_ENDPOINT;
mem_cnt_next <= 0;
when REMOVE_PARTICIPANT =>
mem_addr_next <= addr_res;
mem_stage_next <= REMOVE_PARTICIPANT;
@ -3386,8 +3323,7 @@ begin
-- Match Found
else
addr_res_next <= mem_addr_base;
mem_stage_next <= GET_ENDPOINT_MASK;
mem_cnt_next <= 0;
mem_stage_next <= IDLE;
end if;
when others =>
null;
@ -3467,19 +3403,6 @@ begin
when others =>
null;
end case;
when GET_ENDPOINT_MASK =>
mem_rd <= '1';
mem_cnt_next <= mem_cnt + 1;
mem_addr_next <= mem_addr + 1;
-- Latch Endpoint Bitmask
endpoint_mask_array_next(mem_cnt) <= mem_read_data;
-- Exit Condition
if (mem_cnt = ENDPOINT_BITMASK_SIZE-1) then
-- DONE
mem_stage_next <= IDLE;
end if;
when INSERT_PARTICIPANT =>
mem_wr <= '1';
mem_addr_next <= mem_addr + 1;
@ -3579,11 +3502,8 @@ begin
-- GUIDPrefix 3/3
when 3 =>
mem_write_data <= guid(2);
-- Write Endpoint bitmask via update method
endpoint_mask_array_next <= convert_to_bitmask_array(endpoint_mask);
mem_stage_next <= UPDATE_ENDPOINT;
mem_cnt_next <= 0;
-- DONE
mem_stage_next <= IDLE;
when others =>
null;
end case;
@ -3743,20 +3663,6 @@ begin
when others =>
null;
end case;
when UPDATE_ENDPOINT =>
mem_wr <= '1';
mem_addr_next <= mem_addr + 1;
mem_cnt_next <= mem_cnt + 1;
-- TODO: Use dedicated counter
-- Store new Endpoint Bitmask
mem_write_data <= endpoint_mask_array(mem_cnt);
-- Exit Condition
if (mem_cnt = ENDPOINT_BITMASK_SIZE-1) then
-- DONE
mem_stage_next <= IDLE;
end if;
when REMOVE_PARTICIPANT =>
mem_addr_next <= mem_addr + 1;
mem_cnt_next <= mem_cnt + 1;
@ -4196,8 +4102,6 @@ begin
string_length <= (others => '0');
compare_length <= (others => '0');
endpoint_mask <= (others => '0');
endpoint_match <= (others => '0');
endpoint_unmatch <= (others => '0');
def_addr <= (others => '0');
meta_addr <= (others => '0');
def_port <= (others => '0');
@ -4214,8 +4118,7 @@ begin
max_participant_addr <= FIRST_PARTICIPANT_ADDRESS;
max_endpoint_addr <= FIRST_ENDPOINT_ADDRESS;
guid <= (others => (others => '0'));
mem_guid <= (others => (others => '0'));
endpoint_mask_array <= (others => (others => '0'));
mem_guid <= (others => (others => '0'));
lease_duration <= (others => (others => '0'));
deadline <= (others => (others => '0'));
announcement_time <= (others => (others => '0'));
@ -4262,8 +4165,6 @@ begin
string_length <= string_length_next;
compare_length <= compare_length_next;
endpoint_mask <= endpoint_mask_next;
endpoint_match <= endpoint_match_next;
endpoint_unmatch <= endpoint_unmatch_next;
def_addr <= def_addr_next;
meta_addr <= meta_addr_next;
def_port <= def_port_next;
@ -4280,8 +4181,7 @@ begin
max_participant_addr <= max_participant_addr_next;
max_endpoint_addr <= max_endpoint_addr_next;
guid <= guid_next;
mem_guid <= mem_guid_next;
endpoint_mask_array <= endpoint_mask_array_next;
mem_guid <= mem_guid_next;
lease_duration <= lease_duration_next;
deadline <= deadline_next;
announcement_time <= announcement_time_next;

View File

@ -39,11 +39,8 @@ package rtps_config_package is
-- 4-Byte Word Size of a Participant Entry in Memory
constant PARTICIPANT_FRAME_SIZE : natural := 23;
-- 4-Byte Word Size of Endpoint Bitmask in Memory
constant ENDPOINT_BITMASK_SIZE : natural := round_div(NUM_ENDPOINTS, 32);
type ENDPOINT_BITMASK_ARRAY_TYPE is array (0 to ENDPOINT_BITMASK_SIZE-1) of std_logic_vector(0 to WORD_WIDTH-1);
-- 4-Byte Word Size of a Endpoint Entry in Memory
constant ENDPOINT_FRAME_SIZE : natural := 4 + ENDPOINT_BITMASK_SIZE;
constant ENDPOINT_FRAME_SIZE : natural := 4;
-- Built-in Endpoint Memory Buffer 4-Byte Word Size
constant BUILTIN_BUFFER_SIZE : natural := MAX_REMOTE_PARTICIPANTS*PARTICIPANT_FRAME_SIZE;