Various fixes in RTPS Reader/Writer and DDS Reader

Amongst other fixes the interface between RTPS-HC/DDS was changed.
The Liveliness Update metatraffic operation was also made QOS dependant
and put behind synthesis guards.
Instance Removal trigger was modified. While before at least 1 instance
slot needed to be empty at all times (similar to the sample slot), thsi
was changed to only remove instances on demand. This is controlled via
a signal that holds the current number of stale (removalble) instances.
This commit is contained in:
Greek 2021-02-13 17:37:01 +01:00
parent 80cffb8197
commit 2aedc0229d
4 changed files with 905 additions and 614 deletions

File diff suppressed because it is too large Load Diff

View File

@ -51,23 +51,26 @@ package rtps_config_package is
type HISTORY_CACHE_OPCODE_TYPE is (NOP, ADD_CACHE_CHANGE, GET_CACHE_CHANGE, ACK_CACHE_CHANGE, NACK_CACHE_CHANGE); type HISTORY_CACHE_OPCODE_TYPE is (NOP, ADD_CACHE_CHANGE, GET_CACHE_CHANGE, ACK_CACHE_CHANGE, NACK_CACHE_CHANGE);
type KEY_GENERATOR_OPCODE_TYPE is (NOP, WRITE_PAYLOAD, READ_KEY, READ_SIZE); type KEY_GENERATOR_OPCODE_TYPE is (NOP, WRITE_PAYLOAD, READ_KEY, READ_SIZE);
type HISTORY_CACHE_RESPONSE_TYPE is (UNDEFINED, ACK, ACCEPTED, REJECTED, INVALID); type HISTORY_CACHE_RESPONSE_TYPE is (OK, REJECTED, INVALID, ERROR);
-- Sample Status Info Flags -- Sample Status Info Flags
constant SSI_DISPOSED_FLAG : natural := STATUS_INFO_DISPOSED_FLAG; constant SSI_DISPOSED_FLAG : natural := STATUS_INFO_DISPOSED_FLAG;
constant SSI_UNREGISTERED_FLAG : natural := STATUS_INFO_UNREGISTERED_FLAG; constant SSI_UNREGISTERED_FLAG : natural := STATUS_INFO_UNREGISTERED_FLAG;
constant SSI_FILTERED_FLAG : natural := STATUS_INFO_FILTERED_FLAG; constant SSI_FILTERED_FLAG : natural := STATUS_INFO_FILTERED_FLAG;
constant SSI_KEY_HASH_FLAG : natural := 28; constant SSI_KEY_HASH_FLAG : natural := 28; -- Reader Only
constant SSI_ALIGNED_FLAG : natural := 29; constant SSI_ALIGNED_FLAG : natural := 29;
constant SSI_PAYLOAD_FLAG : natural := 30; constant SSI_PAYLOAD_FLAG : natural := 30;
constant SSI_READ_FLAG : natural := 31; constant SSI_READ_FLAG : natural := 31; -- Reader Only
constant SSI_ACK_FLAG : natural := 31; -- Writer Only
-- Instance Status Info Flags -- Instance Status Info Flags
constant ISI_NOT_ALIVE_DISPOSED_FLAG : natural := 0; constant ISI_NOT_ALIVE_DISPOSED_FLAG : natural := 0; -- Reader Only
constant ISI_NOT_ALIVE_NO_WRITERS_FLAG : natural := 1; constant ISI_DISPOSED_FLAG : natural := 0; -- Writer Only
constant ISI_NOT_ALIVE_NO_WRITERS_FLAG : natural := 1; -- Reader Only
constant ISI_UNREGISTERED_FLAG : natural := 1; -- Writer Only
constant ISI_LIVELINESS_FLAG : natural := 2; constant ISI_LIVELINESS_FLAG : natural := 2;
constant ISI_VIEW_FLAG : natural := 3; constant ISI_VIEW_FLAG : natural := 3; -- Reader Only
constant ISI_MARK_FLAG : natural := 4; constant ISI_MARK_FLAG : natural := 4; -- Reader Only
-- TODO: Prefix the Flags with something that differntiates between them -- TODO: Prefix the Flags with something that differntiates between them
-- Remote Endpoint Flags -- Remote Endpoint Flags
@ -123,9 +126,10 @@ package rtps_config_package is
constant ENDPOINT_BITMAP_WIDTH : natural := 1; -- TODO constant ENDPOINT_BITMAP_WIDTH : natural := 1; -- TODO
type ENDPOINT_BITMAP_ARRAY_TYPE is array (0 to round_div(ENDPOINT_BITMAP_WIDTH, WORD_WIDTH)-1) of std_logic_vector(0 to WORD_WIDTH-1); type ENDPOINT_BITMAP_ARRAY_TYPE is array (0 to round_div(ENDPOINT_BITMAP_WIDTH, WORD_WIDTH)-1) of std_logic_vector(0 to WORD_WIDTH-1);
constant ZERO_ENDPOINT_BITMAP_ARRAY : ENDPOINT_BITMAP_ARRAY_TYPE := (others => (others => '0'));
function to_endpoint_bitmap (input : ENDPOINT_BITMAP_ARRAY_TYPE) return std_logic_vector; function from_endpoint_bitmap_array (input : ENDPOINT_BITMAP_ARRAY_TYPE) return std_logic_vector;
function from_endpoint_bitmap (input : std_logic_vector(0 to ENDPOINT_BITMAP_WIDTH-1)) return ENDPOINT_BITMAP_ARRAY_TYPE; function to_endpoint_bitmap_array (input : std_logic_vector(0 to ENDPOINT_BITMAP_WIDTH-1)) return ENDPOINT_BITMAP_ARRAY_TYPE;
-- Swap "data" to Big Endian representation. -- Swap "data" to Big Endian representation.
function endian_swap(swap : std_logic; data : std_logic_vector) return std_logic_vector; function endian_swap(swap : std_logic; data : std_logic_vector) return std_logic_vector;
@ -1193,7 +1197,7 @@ package body rtps_config_package is
return ret; return ret;
end function; end function;
function to_endpoint_bitmap (input : ENDPOINT_BITMAP_ARRAY_TYPE) return std_logic_vector is function from_endpoint_bitmap_array (input : ENDPOINT_BITMAP_ARRAY_TYPE) return std_logic_vector is
variable ret : std_logic_vector(0 to ENDPOINT_BITMAP_WIDTH-1) := (others => '0'); variable ret : std_logic_vector(0 to ENDPOINT_BITMAP_WIDTH-1) := (others => '0');
begin begin
for i in 0 to input'length-1 loop for i in 0 to input'length-1 loop
@ -1202,7 +1206,7 @@ package body rtps_config_package is
return ret; return ret;
end function; end function;
function from_endpoint_bitmap (input : std_logic_vector(0 to ENDPOINT_BITMAP_WIDTH-1)) return ENDPOINT_BITMAP_ARRAY_TYPE is function to_endpoint_bitmap_array (input : std_logic_vector(0 to ENDPOINT_BITMAP_WIDTH-1)) return ENDPOINT_BITMAP_ARRAY_TYPE is
variable ret : ENDPOINT_BITMAP_ARRAY_TYPE := (others => (others => '0')); variable ret : ENDPOINT_BITMAP_ARRAY_TYPE := (others => (others => '0'));
begin begin
for i in 0 to ret'length-1 loop for i in 0 to ret'length-1 loop

View File

@ -12,6 +12,7 @@ use work.rtps_config_package.all;
entity rtps_reader is entity rtps_reader is
generic ( generic (
RELIABILTY_QOS : std_logic_vector(CDR_ENUMERATION_WIDTH-1 downto 0) := DEFAULT_RELIABILTY_QOS; RELIABILTY_QOS : std_logic_vector(CDR_ENUMERATION_WIDTH-1 downto 0) := DEFAULT_RELIABILTY_QOS;
LIVELINESS_QOS : std_logic_vector(CDR_ENUMERATION_WIDTH-1 downto 0) := DEFAULT_LIVELINESS_QOS;
HEARTBEAT_RESPONSE_DELAY : DURATION_TYPE := TODO; HEARTBEAT_RESPONSE_DELAY : DURATION_TYPE := TODO;
HEARTBEAT_SUPPRESSION_DELAY : DURATION_TYPE := TODO; HEARTBEAT_SUPPRESSION_DELAY : DURATION_TYPE := TODO;
LEASE_DURATION : DURATION_TYPE := DEFAULT_LEASE_DURATION; LEASE_DURATION : DURATION_TYPE := DEFAULT_LEASE_DURATION;
@ -38,14 +39,16 @@ entity rtps_reader is
full_rtps : in std_logic; full_rtps : in std_logic;
last_word_out_rtps : out std_logic; last_word_out_rtps : out std_logic;
data_out_rtps : out std_logic_vector(WORD_WIDTH-1 downto 0); data_out_rtps : out std_logic_vector(WORD_WIDTH-1 downto 0);
-- TO DDS READER -- TO HISTORY CACHE
start_dds : out std_logic; start_hc : out std_logic;
opcode_dds : out HISTORY_CACHE_OPCODE_TYPE; opcode_hc : out HISTORY_CACHE_OPCODE_TYPE;
res_dds : in HISTORY_CACHE_RESPOSNE_TYPE; ack_hc : in std_logic;
data_out_dds : out std_logic_vector(WORD_WIDTH-1 downto 0); done_hc : in std_logic;
valid_out_dds : out std_logic; ret_hc : in HISTORY_CACHE_RESPOSNE_TYPE;
ready_out_dds : in std_logic; data_out_hc : out std_logic_vector(WORD_WIDTH-1 downto 0);
last_word_out_dds : out std_logic valid_out_hc : out std_logic;
ready_out_hc : in std_logic;
last_word_out_hc : out std_logic
); );
end entity; end entity;
@ -389,18 +392,18 @@ begin
lifespan_next <= lifespan; lifespan_next <= lifespan;
-- DEFAULT Unregistered -- DEFAULT Unregistered
mem_opcode <= NOP; mem_opcode <= NOP;
opcode_dds <= ADD_CACHE_CHANGE; opcode_hc <= NOP;
lease_deadline <= TIME_INVALID; lease_deadline <= TIME_INVALID;
res_time <= TIME_INVALID; res_time <= TIME_INVALID;
rd_meta <= '0'; rd_meta <= '0';
rd_user <= '0'; rd_user <= '0';
mem_op_start <= '0'; mem_op_start <= '0';
start_dds <= '0'; start_hc <= '0';
valid_out_dds <= '0'; valid_out_hc <= '0';
last_word_out_dds <= '0'; last_word_out_hc <= '0';
rd_guard := '0'; rd_guard := '0';
mem_field_flags <= (others => '0'); mem_field_flags <= (others => '0');
data_out_dds <= (others => '0'); data_out_hc <= (others => '0');
@ -453,8 +456,13 @@ begin
stage_next <= LATCH_GUIDPREFIX; stage_next <= LATCH_GUIDPREFIX;
cnt_next <= 0; cnt_next <= 0;
when OPCODE_LIVELINESS_UPDATE => when OPCODE_LIVELINESS_UPDATE =>
-- Synthesis Guard
if (LIVELINESS_QOS /= MANUAL_BY_TOPIC_LIVELINESS_QOS) then
stage_next <= LATCH_GUIDPREFIX; stage_next <= LATCH_GUIDPREFIX;
cnt_next <= 0; cnt_next <= 0;
else
stage_next <= SKIP_META_OPERATION;
end if;
when others => when others =>
stage_next <= SKIP_META_OPERATION; stage_next <= SKIP_META_OPERATION;
end case; end case;
@ -508,7 +516,7 @@ begin
guid_next(2) <= data_in_user; guid_next(2) <= data_in_user;
end if; end if;
if (is_meta = '1' and (meta_opcode = OPCODE_PARTICIPANT_UNMATCH or meta_opcode = OPCODE_LIVELINESS_UPDATE)) then if (is_meta = '1' and (meta_opcode = OPCODE_PARTICIPANT_UNMATCH or (LIVELINESS_QOS /= MANUAL_BY_TOPIC_LIVELINESS_QOS and meta_opcode = OPCODE_LIVELINESS_UPDATE))) then
assert (last_word_in_meta = '1') report "last_word_in_meta not set" severity FAILURE; assert (last_word_in_meta = '1') report "last_word_in_meta not set" severity FAILURE;
-- DONE Parsing -- DONE Parsing
stage_next <= INITIATE_ENDPOINT_SEARCH; stage_next <= INITIATE_ENDPOINT_SEARCH;
@ -561,11 +569,14 @@ begin
stage_next <= METATRAFFIC_OPERATION; stage_next <= METATRAFFIC_OPERATION;
cnt_next <= 0; cnt_next <= 0;
when OPCODE_LIVELINESS_UPDATE => when OPCODE_LIVELINESS_UPDATE =>
-- Synthesis Guard
if (LIVELINESS_QOS /= MANUAL_BY_TOPIC_LIVELINESS_QOS) then
mem_op_start <= '1'; mem_op_start <= '1';
mem_opcode <= GET_FIRST_ENDPOINT; mem_opcode <= GET_FIRST_ENDPOINT;
mem_field_flags <= (others => '0'); mem_field_flags <= (others => '0');
stage_next <= METATRAFFIC_OPERATION; stage_next <= METATRAFFIC_OPERATION;
cnt_next <= 0; cnt_next <= 0;
end if;
when others => when others =>
null; null;
end case; end case;
@ -657,11 +668,11 @@ begin
stage_next <= IDLE; stage_next <= IDLE;
else else
-- Propagate Removal -- Propagate Removal
start_dds <= '1'; start_hc <= '1';
opcode_dds <= REMOVE_WRITER; opcode_hc <= REMOVE_WRITER;
data_out_dds <= std_logic_vector(to_unsigned(mem_pos, WORD_WIDTH)); data_out_hc <= std_logic_vector(to_unsigned(mem_pos, WORD_WIDTH));
-- Wait for Operation Acknowledgement -- Wait for Operation Acknowledgement
if (res_dds = ACK) then if (ack_hc = '1') then
-- Remove Unmatched Remote Endpoint -- Remove Unmatched Remote Endpoint
mem_op_start <= '1'; mem_op_start <= '1';
mem_opcode <= REMOVE_ENDPOINT; mem_opcode <= REMOVE_ENDPOINT;
@ -680,11 +691,11 @@ begin
-- Participant Match -- Participant Match
if (guid(0) = mem_endpoint_data.guid(0) and guid(1) = mem_endpoint_data.guid(1) and guid(2) = mem_endpoint_data.guid(2)) then if (guid(0) = mem_endpoint_data.guid(0) and guid(1) = mem_endpoint_data.guid(1) and guid(2) = mem_endpoint_data.guid(2)) then
-- Propagate Removal -- Propagate Removal
start_dds <= '1'; start_hc <= '1';
opcode_dds <= REMOVE_WRITER; opcode_hc <= REMOVE_WRITER;
data_out_dds <= std_logic_vector(to_unsigned(mem_pos, WORD_WIDTH)); data_out_hc <= std_logic_vector(to_unsigned(mem_pos, WORD_WIDTH));
-- Wait for Operation Acknowledgement -- Wait for Operation Acknowledgement
if (res_dds = ACK) then if (ack_hc = '1') then
-- Remove Unmatched Remote Endpoint -- Remove Unmatched Remote Endpoint
mem_op_start <= '1'; mem_op_start <= '1';
mem_opcode <= REMOVE_ENDPOINT; mem_opcode <= REMOVE_ENDPOINT;
@ -701,6 +712,8 @@ begin
null; null;
end case; end case;
when OPCODE_LIVELINESS_UPDATE => when OPCODE_LIVELINESS_UPDATE =>
-- Synthesis Guard
if (LIVELINESS_QOS /= MANUAL_BY_TOPIC_LIVELINESS_QOS) then
case (cnt) is case (cnt) is
when 0 => when 0 =>
-- No matches in memory -- No matches in memory
@ -736,6 +749,7 @@ begin
when others => when others =>
null; null;
end case; end case;
end if;
when others => when others =>
null; null;
end case; end case;
@ -1136,10 +1150,10 @@ begin
if (WITH_KEY and key_hash_rcvd = '0' and data_flag = '0' and key_flag = '0') then if (WITH_KEY and key_hash_rcvd = '0' and data_flag = '0' and key_flag = '0') then
stage_next <= SKIP_PACKET; stage_next <= SKIP_PACKET;
else else
start_dds <= '1'; start_hc <= '1';
opcode_dds <= ADD_CACHE_CHANGE; opcode_hc <= ADD_CACHE_CHANGE;
-- Wait until History Cache acknowledges request -- Wait until History Cache acknowledges request
if (res_dds = ACK) then if (ack_hc = '1') then
stage_next <= ADD_CACHE_CHANGE; stage_next <= ADD_CACHE_CHANGE;
cnt_next <= 0; cnt_next <= 0;
end if; end if;
@ -1148,45 +1162,45 @@ begin
case (cnt) is case (cnt) is
-- Status Info -- Status Info
when 0 => when 0 =>
valid_out_dds <= '1'; valid_out_hc <= '1';
data_out_dds <= status_info; data_out_hc <= status_info;
data_out_dds(SSI_KEY_HASH_FLAG) <= key_hash_rcvd; data_out_hc(SSI_KEY_HASH_FLAG) <= key_hash_rcvd;
data_out_dds(SSI_PAYLOAD_FLAG) <= data_flag; data_out_hc(SSI_PAYLOAD_FLAG) <= data_flag;
data_out_dds(SSI_ALIGNED_FLAG) <= data_flag; data_out_hc(SSI_ALIGNED_FLAG) <= data_flag;
-- Output Guard -- Output Guard
if (ready_out_dds = '1') then if (ready_out_hc = '1') then
cnt_next <= cnt + 1; cnt_next <= cnt + 1;
end if; end if;
-- Timestamp 1/2 -- Timestamp 1/2
when 1 => when 1 =>
valid_out_dds <= '1'; valid_out_hc <= '1';
data_out_dds <= ts(0); data_out_hc <= ts(0);
-- Output Guard -- Output Guard
if (ready_out_dds = '1') then if (ready_out_hc = '1') then
cnt_next <= cnt + 1; cnt_next <= cnt + 1;
end if; end if;
-- Timestamp 2/2 -- Timestamp 2/2
when 2 => when 2 =>
valid_out_dds <= '1'; valid_out_hc <= '1';
data_out_dds <= ts(1); data_out_hc <= ts(1);
-- Output Guard -- Output Guard
if (ready_out_dds = '1') then if (ready_out_hc = '1') then
cnt_next <= cnt + 1; cnt_next <= cnt + 1;
end if; end if;
-- Lifespan Deadline 1/2 -- Lifespan Deadline 1/2
when 3 => when 3 =>
valid_out_dds <= '1'; valid_out_hc <= '1';
data_out_dds <= lifespan(0); data_out_hc <= lifespan(0);
-- Output Guard -- Output Guard
if (ready_out_dds = '1') then if (ready_out_hc = '1') then
cnt_next <= cnt + 1; cnt_next <= cnt + 1;
end if; end if;
-- Lifespan Deadline 2/2 -- Lifespan Deadline 2/2
when 4 => when 4 =>
valid_out_dds <= '1'; valid_out_hc <= '1';
data_out_dds <= lifespan(1); data_out_hc <= lifespan(1);
-- Output Guard -- Output Guard
if (ready_out_dds = '1') then if (ready_out_hc = '1') then
-- Skip Key Hash, if not received -- Skip Key Hash, if not received
if (not WITH_KEY or key_hash_rcvd = '0') then if (not WITH_KEY or key_hash_rcvd = '0') then
cnt_next <= cnt + 5; cnt_next <= cnt + 5;
@ -1196,46 +1210,46 @@ begin
end if; end if;
-- Key hash 1/4 -- Key hash 1/4
when 5 => when 5 =>
valid_out_dds <= '1'; valid_out_hc <= '1';
data_out_dds <= key_hash(0); data_out_hc <= key_hash(0);
-- Output Guard -- Output Guard
if (ready_out_dds = '1') then if (ready_out_hc = '1') then
cnt_next <= cnt + 1; cnt_next <= cnt + 1;
end if; end if;
-- Key Hash 2/4 -- Key Hash 2/4
when 6 => when 6 =>
valid_out_dds <= '1'; valid_out_hc <= '1';
data_out_dds <= key_hash(1); data_out_hc <= key_hash(1);
-- Output Guard -- Output Guard
if (ready_out_dds = '1') then if (ready_out_hc = '1') then
cnt_next <= cnt + 1; cnt_next <= cnt + 1;
end if; end if;
-- Key Hash 3/4 -- Key Hash 3/4
when 7 => when 7 =>
valid_out_dds <= '1'; valid_out_hc <= '1';
data_out_dds <= key_hash(2); data_out_hc <= key_hash(2);
-- Output Guard -- Output Guard
if (ready_out_dds = '1') then if (ready_out_hc = '1') then
cnt_next <= cnt + 1; cnt_next <= cnt + 1;
end if; end if;
-- Key hash 4/4 -- Key hash 4/4
when 8 => when 8 =>
valid_out_dds <= '1'; valid_out_hc <= '1';
data_out_dds <= key_hash(3); data_out_hc <= key_hash(3);
-- Output Guard -- Output Guard
if (ready_out_dds = '1') then if (ready_out_hc = '1') then
cnt_next <= cnt + 1; cnt_next <= cnt + 1;
end if; end if;
-- Endpoint Memory Position -- Endpoint Memory Position
when 9 => when 9 =>
-- Wait for Endpoint Search -- Wait for Endpoint Search
if (mem_op_done = '1') then if (mem_op_done = '1') then
valid_out_dds <= '1'; valid_out_hc <= '1';
-- TODO: Assert mem_pos range fits in CDR_LONG -- TODO: Assert mem_pos range fits in CDR_LONG
data_out_dds <= std_logic_vector(to_unsigned(mem_pos, CDR_LONG_WIDTH)); data_out_hc <= std_logic_vector(to_unsigned(mem_pos, CDR_LONG_WIDTH));
-- Output Guard -- Output Guard
if (ready_out_dds = '1') then if (ready_out_hc = '1') then
-- NOTE: We only push the Payload if there is Data, or if the Key Hash was not received and we need to push -- NOTE: We only push the Payload if there is Data, or if the Key Hash was not received and we need to push
-- the serialized Key. -- the serialized Key.
-- Payload exists -- Payload exists
@ -1243,7 +1257,7 @@ begin
stage_next <= PUSH_PAYLOAD; stage_next <= PUSH_PAYLOAD;
else else
-- DONE -- DONE
last_word_out_dds <= '1'; last_word_out_hc <= '1';
stage_next <= FINALIZE_ADD_CACHE_CHANGE_REQUEST; stage_next <= FINALIZE_ADD_CACHE_CHANGE_REQUEST;
end if; end if;
end if; end if;
@ -1254,13 +1268,13 @@ begin
when PUSH_PAYLOAD => when PUSH_PAYLOAD =>
-- Input Guard -- Input Guard
if (empty_user = '0') then if (empty_user = '0') then
valid_out_dds <= '1'; valid_out_hc <= '1';
-- Push Payload to History Cache -- Push Payload to History Cache
data_out_dds <= data_in_user; data_out_hc <= data_in_user;
last_word_out_dds <= last_word_in_user; last_word_out_hc <= last_word_in_user;
-- Output Guard -- Output Guard
if (ready_out_dds = '1') then if (ready_out_hc = '1') then
rd_guard := '1'; rd_guard := '1';
-- Exit Condition -- Exit Condition
@ -1273,7 +1287,7 @@ begin
-- NOTE: Memory is already in done state from previous state (ADD_CACHE_CHANGE) -- NOTE: Memory is already in done state from previous state (ADD_CACHE_CHANGE)
assert (mem_op_done = '1') report "FINALIZE_ADD_CACHE_CHANGE_REQUEST precondition not met. mem_op_done /= '1'" severity FAILURE; assert (mem_op_done = '1') report "FINALIZE_ADD_CACHE_CHANGE_REQUEST precondition not met. mem_op_done /= '1'" severity FAILURE;
-- Wait for History Cache Response -- Wait for History Cache Response
if (res_dds /= UNDEFINED) then if (done_hc = '1') then
-- NOTE: The Lease Duration is also updated if the Cache Change is not accepted. This in effect "skews" the -- NOTE: The Lease Duration is also updated if the Cache Change is not accepted. This in effect "skews" the
-- "correctness" of the Writer Liveliness Protocol until the reader has no pending request from the Writer. -- "correctness" of the Writer Liveliness Protocol until the reader has no pending request from the Writer.
@ -1281,7 +1295,7 @@ begin
-- Update Endpoint -- Update Endpoint
mem_op_start <= '1'; mem_op_start <= '1';
mem_opcode <= UPDATE_ENDPOINT; mem_opcode <= UPDATE_ENDPOINT;
mem_field_flags <= LEASE_DEADLINE_FLAG; mem_field_flags <= EMF_LEASE_DEADLINE_FLAG;
if (LEASE_DURATION /= DURATION_INFINITE) then if (LEASE_DURATION /= DURATION_INFINITE) then
lease_deadline <= time + LEASE_DURATION; lease_deadline <= time + LEASE_DURATION;
@ -1297,9 +1311,9 @@ begin
-- NOTE: In case the operation was unsucessfull (e.g. reached Resource Limits), the Sequence Number is not updated -- NOTE: In case the operation was unsucessfull (e.g. reached Resource Limits), the Sequence Number is not updated
-- and thus not "acknowledged". -- and thus not "acknowledged".
-- Operation was Accepted -- Operation was Accepted
if (res_dds = ACCEPTED) then if (ret_hc = OK) then
-- Update also next sequence number -- Update also next sequence number
mem_field_flags <= NEXT_SEQ_NR_FLAG or LEASE_DEADLINE_FLAG; mem_field_flags <= EMF_NEXT_SEQ_NR_FLAG or EMF_LEASE_DEADLINE_FLAG;
end if; end if;
-- DONE -- DONE

View File

@ -297,21 +297,15 @@ architecture arch of rtps_writer is
alias header_opcode : std_logic_vector(7 downto 0) is data_in_user(31 downto 24); alias header_opcode : std_logic_vector(7 downto 0) is data_in_user(31 downto 24);
alias header_flags : std_logic_vector(7 downto 0) is data_in_user(23 downto 16); alias header_flags : std_logic_vector(7 downto 0) is data_in_user(23 downto 16);
alias header_udp_port : std_logic_vector(15 downto 0) is data_in_user(15 downto 0); alias header_udp_port : std_logic_vector(15 downto 0) is data_in_user(15 downto 0);
-- RTPS PARAMETER LIST HEADER
alias parameter_id : std_logic_vector(15 downto 0) is data_in_user(31 downto 16);
alias parameter_length : std_logic_vector(15 downto 0) is data_in_user(15 downto 0);
alias must_understand : std_logic is parameter_id(14);
-- RTPS DATA PAYLOAD HEADER
alias representation_id : std_logic_vector(15 downto 0) is data_in_user(31 downto 16);
alias representation_options : std_logic_vector(15 downto 0) is data_in_user(15 downto 0);
-- RTPS SUBMESSAGE FLAGS -- RTPS SUBMESSAGE FLAGS
alias endian_flag : std_logic is rtps_flags(0); alias endian_flag : std_logic is rtps_flags(0);
alias qos_flag : std_logic is rtps_flags(1);
alias data_flag : std_logic is rtps_flags(2);
alias key_flag : std_logic is rtps_flags(3);
alias final_flag : std_logic is rtps_flags(1); alias final_flag : std_logic is rtps_flags(1);
alias payload_flag : std_logic is rtps_flags(4);
alias liveliness_flag : std_logic is rtps_flags(2); alias liveliness_flag : std_logic is rtps_flags(2);
-- RTPS OUT DATA SUBMESSAGE FLAGS
alias qos_flag : std_logic is data_out_rtps(17);
alias data_flag : std_logic is data_out_rtps(18);
alias key_flag : std_logic is data_out_rtps(19);
alias payload_flag : std_logic is data_out_rtps(20);
-- ACKNACK -- ACKNACK
alias nack_base : SEQUENCENUMBER_TYPE is sn_latch_1; alias nack_base : SEQUENCENUMBER_TYPE is sn_latch_1;
alias nack_base_next : SEQUENCENUMBER_TYPE is sn_latch_1_next; alias nack_base_next : SEQUENCENUMBER_TYPE is sn_latch_1_next;
@ -362,9 +356,6 @@ begin
data_out => mem_read_data data_out => mem_read_data
); );
-- Propagate Liveliness Assertion
alive <= assert_liveliness when (LIVELINESS_QOS /= MANUAL_BY_TOPIC_LIVELINESS_QOS) else '0';
-- *Main State Machine* -- *Main State Machine*
-- STATE DESCRIPTION -- STATE DESCRIPTION
-- IDLE Idle State. Initiates Stale Endpoint Checks, Metatraffic Packet Processing, and User Packet Processing, in that priority order. -- IDLE Idle State. Initiates Stale Endpoint Checks, Metatraffic Packet Processing, and User Packet Processing, in that priority order.
@ -438,7 +429,7 @@ begin
assert_liveliness_latch_next<= assert_liveliness_latch; assert_liveliness_latch_next<= assert_liveliness_latch;
-- DEFAULT Unregistered -- DEFAULT Unregistered
mem_opcode <= NOP; mem_opcode <= NOP;
opcode_hc <= ADD_CACHE_CHANGE; opcode_hc <= NOP;
lease_deadline <= TIME_INVALID; lease_deadline <= TIME_INVALID;
res_time <= TIME_INVALID; res_time <= TIME_INVALID;
rd_meta <= '0'; rd_meta <= '0';
@ -449,6 +440,7 @@ begin
get_data_hc <= '0'; get_data_hc <= '0';
wr_rtps <= '1'; wr_rtps <= '1';
rd_guard := '0'; rd_guard := '0';
alive <= '0';
mem_field_flags <= (others => '0'); mem_field_flags <= (others => '0');
data_out_dds <= (others => '0'); data_out_dds <= (others => '0');
@ -471,12 +463,28 @@ begin
-- New Cache Change in HC -- New Cache Change in HC
if (data_available = '1') then if (data_available = '1') then
-- Propagate Liveliness
alive <= '1';
new_push_next <= '1'; new_push_next <= '1';
stage_next <= GET_MAX_SN; stage_next <= GET_MAX_SN;
cnt_next <= 0; cnt_next <= 0;
-- Manual Liveliness Assertion
elsif (LIVELINESS_QOS = MANUAL_BY_TOPIC_LIVELINESS_QOS and assert_liveliness_latch = '1') then
-- Propagate Liveliness
alive <= '1';
-- Reset
heartbeat_time_next <= time + HEARTBEAT_PERIOD;
-- Increment Heartbeat Count
count_next <= count + 1;
stage_next <= GET_MIN_SN;
cnt_next <= 0;
-- Heartbeat Timeout -- Heartbeat Timeout
elsif ((RELIABILTY_QOS = RELIABLE_RELIABILITY_QOS and time >= heartbeat_time) or (LIVELINESS_QOS = MANUAL_BY_TOPIC_LIVELINESS_QOS and assert_liveliness_latch = '1')) then elsif (RELIABILTY_QOS = RELIABLE_RELIABILITY_QOS and time >= heartbeat_time) then
-- Reset -- Reset
heartbeat_time_next <= time + HEARTBEAT_PERIOD; heartbeat_time_next <= time + HEARTBEAT_PERIOD;
@ -722,12 +730,6 @@ begin
-- Ignore -- Ignore
stage_next <= IDLE; stage_next <= IDLE;
else else
-- Propagate Removal
start_hc <= '1';
opcode_hc <= REMOVE_WRITER;
data_out_dds <= std_logic_vector(to_unsigned(mem_pos, WORD_WIDTH));
-- Wait for Operation Acknowledgement
if (res_hc = ACK) then
-- Remove Unmatched Remote Endpoint -- Remove Unmatched Remote Endpoint
mem_op_start <= '1'; mem_op_start <= '1';
mem_opcode <= REMOVE_ENDPOINT; mem_opcode <= REMOVE_ENDPOINT;
@ -742,7 +744,6 @@ begin
stage_next <= IDLE; stage_next <= IDLE;
end if; end if;
end if; end if;
end if;
when OPCODE_PARTICIPANT_UNMATCH => when OPCODE_PARTICIPANT_UNMATCH =>
case (cnt) is case (cnt) is
when 0 => when 0 =>
@ -750,6 +751,8 @@ begin
if (mem_addr_base = ENDPOINT_MEMORY_MAX_ADDRESS) then if (mem_addr_base = ENDPOINT_MEMORY_MAX_ADDRESS) then
-- Global ACK SN possibly changed -- Global ACK SN possibly changed
if (RELIABILTY_QOS = RELIABLE_RELIABILITY_QOS and global_ack_seq_nr_base /= SEQUENCENUMBER_UNKNOWN) then if (RELIABILTY_QOS = RELIABLE_RELIABILITY_QOS and global_ack_seq_nr_base /= SEQUENCENUMBER_UNKNOWN) then
-- NOTE: We are triggering an Global ACK SN Update on each Participant Removal. This should not happen as often, and is therefore acceptable.
-- Otherwise we need to check the ack_seq_nr_base in the other substate and mark when equal to current Global ACK SN.
-- Update Global ACK -- Update Global ACK
stage_next <= UPDATE_GLOBAL_ACK; stage_next <= UPDATE_GLOBAL_ACK;
cnt_next <= 0; cnt_next <= 0;
@ -770,6 +773,7 @@ begin
-- Continue Search -- Continue Search
mem_op_start <= '1'; mem_op_start <= '1';
mem_opcode <= GET_NEXT_ENDPOINT; mem_opcode <= GET_NEXT_ENDPOINT;
mem_field_flags <= EMF_GUIDPREFIX_FLAG;
cnt_next <= 0; cnt_next <= 0;
when others => when others =>
null; null;
@ -1333,7 +1337,7 @@ begin
-- Wait until Operation Response -- Wait until Operation Response
if (done_hc = '1') then if (done_hc = '1') then
-- Wait for Operation Response -- Wait for Operation Response
if (ret_hc = ACK) then if (ret_hc = OK) then
get_data_hc <= '1'; get_data_hc <= '1';
if (gap_in_progress = '1') then if (gap_in_progress = '1') then
-- Close GAP and send DATA -- Close GAP and send DATA
@ -1384,7 +1388,7 @@ begin
mem_opcode <= GET_NEXT_ENDPOINT; mem_opcode <= GET_NEXT_ENDPOINT;
mem_field_flags <= EMF_IPV4_ADDR_FLAG or EMF_UDP_PORT_FLAG; mem_field_flags <= EMF_IPV4_ADDR_FLAG or EMF_UDP_PORT_FLAG;
cnt_next <= cnt + 1; cnt_next <= cnt + 1;
-- Initiate Hertbeat Sending -- Initiate Heartbeat Sending
when 2 => when 2 =>
-- End of Endpoint -- End of Endpoint
if (mem_addr_base = ENDPOINT_MEMORY_MAX_ADDRESS) then if (mem_addr_base = ENDPOINT_MEMORY_MAX_ADDRESS) then
@ -1418,49 +1422,17 @@ begin
last_seq_nr_next <= last_seq_nr + 1; last_seq_nr_next <= last_seq_nr + 1;
cnt_next <= cnt + 1; cnt_next <= cnt + 1;
end if; end if;
-- GET SN
when 1 =>
start_hc <= '1';
opcode_hc <= GET_CACHE_CHANGE;
seq_nr_hc <= last_seq_nr;
-- Wait until Operation Acknowledgement
if (ack_hc = '1') then
cnt_next <= cnt + 1;
end if;
-- READ SN
when 2 =>
-- Wait until Operation Response
if (done_hc = '1') then
-- Cache Change Available
if (ret_hc = ACK) then
cnt_next <= cnt + 1;
-- Cache Change Unavailable
else
report "New Cache Change unavailable" severity ERROR;
cnt_next <= 0;
end if;
end if;
-- Get First Reader -- Get First Reader
when 3 => when 1 =>
-- Memory Operation Guard -- Memory Operation Guard
if (mem_op_done = '1') then if (mem_op_done = '1') then
mem_op_start <= '1'; mem_op_start <= '1';
mem_opcode <= GET_FIRST_ENDPOINT; mem_opcode <= GET_FIRST_ENDPOINT;
mem_field_flags <= EMF_IPV4_ADDR_FLAG or EMF_UDP_PORT_FLAG; mem_field_flags <= EMF_IPV4_ADDR_FLAG or EMF_UDP_PORT_FLAG;
cnt_next <= cnt + 2;
end if;
-- Get Next Reader
when 4 =>
-- Memory Operation Guard
if (mem_op_done = '1') then
mem_op_start <= '1';
mem_opcode <= GET_NEXT_ENDPOINT;
mem_field_flags <= EMF_IPV4_ADDR_FLAG or EMF_UDP_PORT_FLAG;
cnt_next <= cnt + 1; cnt_next <= cnt + 1;
end if; end if;
-- Initiate Send -- GET SN
when 5 => when 2 =>
-- Wait for Endpoint Data -- Wait for Endpoint Data
if (mem_op_done = '1') then if (mem_op_done = '1') then
-- End of Endpoints -- End of Endpoints
@ -1484,11 +1456,46 @@ begin
cnt_next <= 0; cnt_next <= 0;
end if; end if;
else else
start_hc <= '1';
opcode_hc <= GET_CACHE_CHANGE;
seq_nr_hc <= last_seq_nr;
-- Wait until Operation Acknowledgement
if (ack_hc = '1') then
cnt_next <= cnt + 1;
end if;
end if;
end if;
-- READ SN
when 3 =>
-- Wait until Operation Response
if (done_hc = '1') then
-- Cache Change Available
if (ret_hc = OK) then
-- Only request Payload if necessary (Contains DATA or Serialized Key)
if (cc_kind = ALIVE or (WITH_KEY and cc_kind /= ALIVE)) then
get_data_hc <= '1';
end if;
stage_next <= SEND_HEADER; stage_next <= SEND_HEADER;
return_stage_next <= SEND_DATA_A; return_stage_next <= SEND_INFO_TS when (DESTINATION_ORDER_QOS = BY_SOURCE_TIMESTAMP_DESTINATION_ORDER_QOS) else SEND_DATA_A;
cnt_next <= 0;
-- Cache Change Unavailable
else
report "New Cache Change unavailable" severity WARNING;
cnt_next <= 0; cnt_next <= 0;
end if; end if;
end if; end if;
-- Get Next Reader
when 4 =>
-- Memory Operation Guard
if (mem_op_done = '1') then
mem_op_start <= '1';
mem_opcode <= GET_NEXT_ENDPOINT;
mem_field_flags <= EMF_IPV4_ADDR_FLAG or EMF_UDP_PORT_FLAG;
-- Loop
cnt_next <= 2;
end if;
when others => when others =>
null; null;
end case; end case;
@ -1548,8 +1555,12 @@ begin
-- Wait until Operation Response -- Wait until Operation Response
if (done_hc = '1') then if (done_hc = '1') then
-- Wait for Operation Response -- Wait for Operation Response
if (ret_hc = ACK) then if (ret_hc = OK) then
-- Only request Payload if necessary (Contains DATA or Serialized Key)
if (cc_kind = ALIVE or (WITH_KEY and cc_kind /= ALIVE)) then
get_data_hc <= '1'; get_data_hc <= '1';
end if;
if (gap_in_progress = '1') then if (gap_in_progress = '1') then
-- Close GAP and send DATA -- Close GAP and send DATA
gap_in_progress_next <= '0'; gap_in_progress_next <= '0';
@ -1658,16 +1669,10 @@ begin
-- DATA RTPS SUBMESSAGE -- DATA RTPS SUBMESSAGE
-- RTPS Submessage Header -- RTPS Submessage Header
when 0 => when 0 =>
-- Operation has no Data data_out_rtps <= SID_DATA & "00000000" & std_logic_vector(to_unsigned(0, SUBMESSAGE_LENGTH_WIDTH));
if (cc_kind /= ALIVE) then data_flag <= '1' when (cc_kind = ALIVE) else '0';
-- Set KEY Flag key_flag <= '1' when (WITH_KEY and cc_kind /= ALIVE) else '0';
data_out_rtps <= SID_DATA & "00001010" & std_logic_vector(to_unsigned(0, SUBMESSAGE_LENGTH_WIDTH)); qos_flag <= '1' when (cc_kind /= ALIVE or WITH_KEY or mem_endpoint_data.flags(EXPECTS_INLINE_QOS_FLAG) = '1') else '0';
wr_sig <= '1';
else
-- Set DATA Flag
data_out_rtps <= SID_DATA & "00000110" & std_logic_vector(to_unsigned(0, SUBMESSAGE_LENGTH_WIDTH));
wr_sig <= '1';
end if;
cnt_next <= cnt + 1; cnt_next <= cnt + 1;
-- extraFlags, octetsToInlineQoS -- extraFlags, octetsToInlineQoS
when 1 => when 1 =>
@ -1693,13 +1698,82 @@ begin
when 5 => when 5 =>
data_out_rtps <= std_logic_vector(next_seq_nr(1)); data_out_rtps <= std_logic_vector(next_seq_nr(1));
wr_sig <= '1'; wr_sig <= '1';
-- Need to send Key Hash
if (WITH_KEY) then
cnt_next <= cnt + 1;
-- Need to send Status Info
elsif (cc_kind /= ALIVE) then
cnt_next <= cnt + 5;
-- Reader expect in-line QoS
elsif(mem_endpoint_data.flags(EXPECTS_INLINE_QOS_FLAG) = '1') then
stage_next <= SEND_INLINE_QOS;
cnt3_next <= 0;
-- Payload Available (DATA or Serialized Key)
elsif (cc_kind = ALIVE or (WITH_KEY and cc_kind /= ALIVE)) then
stage_next <= SEND_DATA_B;
cnt_next <= 0;
else
-- Continue
if (stale_check = '1') then
stage_next <= HANDLE_REQUESTS;
cnt_next <= 0;
req_bitmap_pos_next <= req_bitmap_pos + 1;
next_seq_nr_next <= next_seq_nr + 1;
elsif (new_push = '1') then
stage_next <= HANDLE_NEW;
cnt_next <= 4;
elsif (historical_push = '1') then
stage_next <= HANDLE_HISTORICAL;
cnt_next <= 0;
else
assert FALSE severity FAILURE;
end if;
end if;
-- Key Hash 1/4
when 6 =>
-- Synthesis Guard
if (WITH_KEY) then
data_out_rtps <= std_logic_vector(cc_instance_handle(0));
wr_sig <= '1';
cnt_next <= cnt + 1;
end if;
-- Key Hash 2/4
when 7 =>
-- Synthesis Guard
if (WITH_KEY) then
data_out_rtps <= std_logic_vector(cc_instance_handle(1));
wr_sig <= '1';
cnt_next <= cnt + 1;
end if;
-- Key Hash 3/4
when 8 =>
-- Synthesis Guard
if (WITH_KEY) then
data_out_rtps <= std_logic_vector(cc_instance_handle(2));
wr_sig <= '1';
cnt_next <= cnt + 1;
end if;
-- Key Hash 4/4
when 9 =>
-- Synthesis Guard
if (WITH_KEY) then
data_out_rtps <= std_logic_vector(cc_instance_handle(3));
wr_sig <= '1';
-- Need to send Status Info
if (cc_kind /= ALIVE) then if (cc_kind /= ALIVE) then
cnt_next <= cnt + 1; cnt_next <= cnt + 1;
-- Reader expects in-line QoS
elsif (mem_endpoint_data.flags(EXPECTS_INLINE_QOS_FLAG) = '1') then
stage_next <= SEND_INLINE_QOS;
cnt3_next <= 0;
else else
cnt_next <= cnt + 2; cnt_next <= cnt + 2;
end if; end if;
end if;
-- Status Info -- Status Info
when 6 => when 10 =>
data_out_rtps <= (others => '0'); data_out_rtps <= (others => '0');
wr_sig <= '1'; wr_sig <= '1';
case (cc_kind) is case (cc_kind) is
@ -1712,26 +1786,8 @@ begin
when others => when others =>
null; null;
end case; end case;
cnt_next <= cnt + 1;
-- Key Hash 1/4 -- Reader expects in-line QoS
when 7 =>
data_out_rtps <= std_logic_vector(cc_instance_handle(0));
wr_sig <= '1';
cnt_next <= cnt + 1;
-- Key Hash 2/4
when 8 =>
data_out_rtps <= std_logic_vector(cc_instance_handle(1));
wr_sig <= '1';
cnt_next <= cnt + 1;
-- Key Hash 3/4
when 9 =>
data_out_rtps <= std_logic_vector(cc_instance_handle(2));
wr_sig <= '1';
cnt_next <= cnt + 1;
-- Key Hash 4/4
when 10 =>
data_out_rtps <= std_logic_vector(cc_instance_handle(3));
wr_sig <= '1';
if (mem_endpoint_data.flags(EXPECTS_INLINE_QOS_FLAG) = '1') then if (mem_endpoint_data.flags(EXPECTS_INLINE_QOS_FLAG) = '1') then
stage_next <= SEND_INLINE_QOS; stage_next <= SEND_INLINE_QOS;
cnt3_next <= 0; cnt3_next <= 0;
@ -1742,7 +1798,27 @@ begin
when 11 => when 11 =>
data_out_rtps <= PID_SENTINEL & std_logic_vector(to_unsigned(0, 16)); data_out_rtps <= PID_SENTINEL & std_logic_vector(to_unsigned(0, 16));
wr_sig <= '1'; wr_sig <= '1';
-- Payload Available (DATA or Serialized Key)
if (cc_kind = ALIVE or (WITH_KEY and cc_kind /= ALIVE)) then
stage_next <= SEND_DATA_B; stage_next <= SEND_DATA_B;
else
-- Continue
if (stale_check = '1') then
stage_next <= HANDLE_REQUESTS;
cnt_next <= 0;
req_bitmap_pos_next <= req_bitmap_pos + 1;
next_seq_nr_next <= next_seq_nr + 1;
elsif (new_push = '1') then
stage_next <= HANDLE_NEW;
cnt_next <= 4;
elsif (historical_push = '1') then
stage_next <= HANDLE_HISTORICAL;
cnt_next <= 0;
else
assert FALSE severity FAILURE;
end if;
end if;
when others => when others =>
null; null;
end case; end case;
@ -1756,7 +1832,26 @@ begin
-- Exit Condition -- Exit Condition
if (cnt3 = INLINE_QOS.length-1) then if (cnt3 = INLINE_QOS.length-1) then
-- Payload Available (DATA or Serialized Key)
if (cc_kind = ALIVE or (WITH_KEY and cc_kind /= ALIVE)) then
stage_next <= SEND_DATA_B; stage_next <= SEND_DATA_B;
else
-- Continue
if (stale_check = '1') then
stage_next <= HANDLE_REQUESTS;
cnt_next <= 0;
req_bitmap_pos_next <= req_bitmap_pos + 1;
next_seq_nr_next <= next_seq_nr + 1;
elsif (new_push = '1') then
stage_next <= HANDLE_NEW;
cnt_next <= 4;
elsif (historical_push = '1') then
stage_next <= HANDLE_HISTORICAL;
cnt_next <= 0;
else
assert FALSE severity FAILURE;
end if;
end if;
end if; end if;
end if; end if;
when SEND_DATA_B => when SEND_DATA_B =>
@ -1958,6 +2053,7 @@ begin
-- FIND_EMPTY_SLOT Find first empty_user slot in memory. -- FIND_EMPTY_SLOT Find first empty_user slot in memory.
-- RESET_MAX_POINTER Reset the max_endpoint_addr pointer to last occupied slot in memory. -- RESET_MAX_POINTER Reset the max_endpoint_addr pointer to last occupied slot in memory.
-- GET_NEXT_ENDPOINT See Memory OPCODE Description -- GET_NEXT_ENDPOINT See Memory OPCODE Description
-- RESET_MEMORY Reset Endpoint Memory to Empty State
mem_ctrl_prc : process(all) mem_ctrl_prc : process(all)
begin begin
-- DEFAULT Registered -- DEFAULT Registered