Backport GAP parsing logic to RTPS Builtin Endpoint

The GAP parsing logic was backported from RTPS Reader, so that the RTPS
Builtin Endpoint can parse all kind of GAP without making assumptions.
The Test 4 of the RTPS Builtin Endpoint was extended to test HAERTBEAT and GAP Handling of the RTPS
Builting endpoint, and Test 2 of the RTPS Reader was extended with an
additional Test (GAP with next expected SN not marked in bitmap)
This commit is contained in:
Greek 2021-05-13 13:31:00 +02:00
parent 293d89f083
commit 8cd1c29518
8 changed files with 1565 additions and 162 deletions

View File

@ -12,7 +12,7 @@ use work.rtps_test_package.all;
-- This testbench tests the matching of remote endpoints. This is done by checking the Match/Unmatch Frame sent to the local endpoints. -- This testbench tests the matching of remote endpoints. This is done by checking the Match/Unmatch Frame sent to the local endpoints.
-- The local participant is configured with following endpoints (called "fixed" endpoints): -- The local participant is configured with following endpoints (called "fixed" endpoints):
-- NOTE: All Endpoints are configured with topic "TOPIC_1" and type "TYPE_1", except is explicitly stated otherwise. -- NOTE: All Endpoints are configured with topic "TOPIC_1" and type "TYPE_1", except if explicitly stated otherwise.
-- WRITER 0 -- WRITER 0
-- * DEFAULT -- * DEFAULT
-- WRITER 1 -- WRITER 1

File diff suppressed because it is too large Load Diff

View File

@ -672,6 +672,20 @@ begin
stimulus_user := EMPTY_TEST_PACKET; stimulus_user := EMPTY_TEST_PACKET;
reference := EMPTY_TEST_PACKET; reference := EMPTY_TEST_PACKET;
Log("Endpoint 2 Heartbeat [GAP 21-22, 24]", INFO);
endpoint := e2;
sub := DEFAULT_RTPS_SUBMESSAGE;
sub.submessageID := SID_GAP;
sub.writerId := endpoint.entityid;
sub.readerId := DEFAULT_READER_ENTITYID;
sub.gapStart := gen_sn(21);
sub.gapList := (base => gen_sn(22), numBits => int(3, CDR_LONG_WIDTH), bitmap => (0 => '1', 2 => '1', others => '0'));
gen_rtps_handler_out(sub, get_loc(endpoint), FALSE, src_ts, endpoint.participant.guidPrefix, stimulus_user);
start_user_test;
wait_on_user_sent;
stimulus_user := EMPTY_TEST_PACKET;
reference := EMPTY_TEST_PACKET;
Log("Accept Endpoint 2 sent DATA [SN 23]", INFO); Log("Accept Endpoint 2 sent DATA [SN 23]", INFO);
endpoint := e2; endpoint := e2;
sub := DEFAULT_RTPS_SUBMESSAGE; sub := DEFAULT_RTPS_SUBMESSAGE;

View File

@ -323,27 +323,27 @@ begin
-- *HEARTBEAT HANDLING* -- *HEARTBEAT HANDLING*
Log("Test HEARTBEAT Handling", INFO); Log("Test HEARTBEAT Handling", INFO);
Log("Endpoint 2 Heartbeat [First 11, Last 19]", INFO); Log("Endpoint 2 Heartbeat [First 11, Last 18]", INFO);
endpoint := e2; endpoint := e2;
sub := DEFAULT_RTPS_SUBMESSAGE; sub := DEFAULT_RTPS_SUBMESSAGE;
sub.submessageID := SID_HEARTBEAT; sub.submessageID := SID_HEARTBEAT;
sub.writerId := endpoint.entityid; sub.writerId := endpoint.entityid;
sub.readerId := DEFAULT_READER_ENTITYID; sub.readerId := DEFAULT_READER_ENTITYID;
sub.firstSN := gen_sn(11); sub.firstSN := gen_sn(11);
sub.lastSN := gen_sn(19); sub.lastSN := gen_sn(18);
gen_rtps_handler_out(sub, get_loc(endpoint), FALSE, src_ts, endpoint.participant.guidPrefix, stimulus_user); gen_rtps_handler_out(sub, get_loc(endpoint), FALSE, src_ts, endpoint.participant.guidPrefix, stimulus_user);
start_user_test; start_user_test;
wait_on_user_sent; wait_on_user_sent;
stimulus_user := EMPTY_TEST_PACKET; stimulus_user := EMPTY_TEST_PACKET;
reference := EMPTY_TEST_PACKET; reference := EMPTY_TEST_PACKET;
Log("Ignore Endpoint 2 sent DATA [SN 19]", INFO); Log("Ignore Endpoint 2 sent DATA [SN 18]", INFO);
endpoint := e2; endpoint := e2;
sub := DEFAULT_RTPS_SUBMESSAGE; sub := DEFAULT_RTPS_SUBMESSAGE;
sub.submessageID := SID_DATA; sub.submessageID := SID_DATA;
sub.writerId := endpoint.entityid; sub.writerId := endpoint.entityid;
sub.readerId := DEFAULT_READER_ENTITYID; sub.readerId := DEFAULT_READER_ENTITYID;
sub.writerSN := gen_sn(19); sub.writerSN := gen_sn(18);
sub.flags(SUBMESSAGE_DATA_FLAG_POS) := '1'; sub.flags(SUBMESSAGE_DATA_FLAG_POS) := '1';
sub.data := gen_payload; sub.data := gen_payload;
gen_rtps_handler_out(sub, get_loc(endpoint), FALSE, src_ts, endpoint.participant.guidPrefix, stimulus_user); gen_rtps_handler_out(sub, get_loc(endpoint), FALSE, src_ts, endpoint.participant.guidPrefix, stimulus_user);
@ -653,6 +653,20 @@ begin
stimulus_user := EMPTY_TEST_PACKET; stimulus_user := EMPTY_TEST_PACKET;
reference := EMPTY_TEST_PACKET; reference := EMPTY_TEST_PACKET;
Log("Endpoint 2 Heartbeat [GAP 21-22, 24]", INFO);
endpoint := e2;
sub := DEFAULT_RTPS_SUBMESSAGE;
sub.submessageID := SID_GAP;
sub.writerId := endpoint.entityid;
sub.readerId := DEFAULT_READER_ENTITYID;
sub.gapStart := gen_sn(21);
sub.gapList := (base => gen_sn(22), numBits => int(3, CDR_LONG_WIDTH), bitmap => (0 => '1', 2 => '1', others => '0'));
gen_rtps_handler_out(sub, get_loc(endpoint), FALSE, src_ts, endpoint.participant.guidPrefix, stimulus_user);
start_user_test;
wait_on_user_sent;
stimulus_user := EMPTY_TEST_PACKET;
reference := EMPTY_TEST_PACKET;
Log("Accept Endpoint 2 sent DATA [SN 23]", INFO); Log("Accept Endpoint 2 sent DATA [SN 23]", INFO);
endpoint := e2; endpoint := e2;
sub := DEFAULT_RTPS_SUBMESSAGE; sub := DEFAULT_RTPS_SUBMESSAGE;

View File

@ -653,6 +653,20 @@ begin
stimulus_user := EMPTY_TEST_PACKET; stimulus_user := EMPTY_TEST_PACKET;
reference := EMPTY_TEST_PACKET; reference := EMPTY_TEST_PACKET;
Log("Endpoint 2 Heartbeat [GAP 21-22, 24]", INFO);
endpoint := e2;
sub := DEFAULT_RTPS_SUBMESSAGE;
sub.submessageID := SID_GAP;
sub.writerId := endpoint.entityid;
sub.readerId := DEFAULT_READER_ENTITYID;
sub.gapStart := gen_sn(21);
sub.gapList := (base => gen_sn(22), numBits => int(3, CDR_LONG_WIDTH), bitmap => (0 => '1', 2 => '1', others => '0'));
gen_rtps_handler_out(sub, get_loc(endpoint), FALSE, src_ts, endpoint.participant.guidPrefix, stimulus_user);
start_user_test;
wait_on_user_sent;
stimulus_user := EMPTY_TEST_PACKET;
reference := EMPTY_TEST_PACKET;
Log("Accept Endpoint 2 sent DATA [SN 23]", INFO); Log("Accept Endpoint 2 sent DATA [SN 23]", INFO);
endpoint := e2; endpoint := e2;
sub := DEFAULT_RTPS_SUBMESSAGE; sub := DEFAULT_RTPS_SUBMESSAGE;

View File

@ -668,6 +668,20 @@ begin
stimulus_user := EMPTY_TEST_PACKET; stimulus_user := EMPTY_TEST_PACKET;
reference := EMPTY_TEST_PACKET; reference := EMPTY_TEST_PACKET;
Log("Endpoint 2 Heartbeat [GAP 21-22, 24]", INFO);
endpoint := e2;
sub := DEFAULT_RTPS_SUBMESSAGE;
sub.submessageID := SID_GAP;
sub.writerId := endpoint.entityid;
sub.readerId := DEFAULT_READER_ENTITYID;
sub.gapStart := gen_sn(21);
sub.gapList := (base => gen_sn(22), numBits => int(3, CDR_LONG_WIDTH), bitmap => (0 => '1', 2 => '1', others => '0'));
gen_rtps_handler_out(sub, get_loc(endpoint), FALSE, src_ts, endpoint.participant.guidPrefix, stimulus_user);
start_user_test;
wait_on_user_sent;
stimulus_user := EMPTY_TEST_PACKET;
reference := EMPTY_TEST_PACKET;
Log("Accept Endpoint 2 sent DATA [SN 23]", INFO); Log("Accept Endpoint 2 sent DATA [SN 23]", INFO);
endpoint := e2; endpoint := e2;
sub := DEFAULT_RTPS_SUBMESSAGE; sub := DEFAULT_RTPS_SUBMESSAGE;

View File

@ -668,6 +668,20 @@ begin
stimulus_user := EMPTY_TEST_PACKET; stimulus_user := EMPTY_TEST_PACKET;
reference := EMPTY_TEST_PACKET; reference := EMPTY_TEST_PACKET;
Log("Endpoint 2 Heartbeat [GAP 21-22, 24]", INFO);
endpoint := e2;
sub := DEFAULT_RTPS_SUBMESSAGE;
sub.submessageID := SID_GAP;
sub.writerId := endpoint.entityid;
sub.readerId := DEFAULT_READER_ENTITYID;
sub.gapStart := gen_sn(21);
sub.gapList := (base => gen_sn(22), numBits => int(3, CDR_LONG_WIDTH), bitmap => (0 => '1', 2 => '1', others => '0'));
gen_rtps_handler_out(sub, get_loc(endpoint), FALSE, src_ts, endpoint.participant.guidPrefix, stimulus_user);
start_user_test;
wait_on_user_sent;
stimulus_user := EMPTY_TEST_PACKET;
reference := EMPTY_TEST_PACKET;
Log("Accept Endpoint 2 sent DATA [SN 23]", INFO); Log("Accept Endpoint 2 sent DATA [SN 23]", INFO);
endpoint := e2; endpoint := e2;
sub := DEFAULT_RTPS_SUBMESSAGE; sub := DEFAULT_RTPS_SUBMESSAGE;

View File

@ -124,8 +124,8 @@ architecture arch of rtps_builtin_endpoint is
--*****TYPE DECLARATION***** --*****TYPE DECLARATION*****
-- FSM states. Explained below in detail -- FSM states. Explained below in detail
type STAGE_TYPE is (IDLE, PACKET_HEADER, PACKET_SRC_ADDR, PACKET_SRC_ENTITYID, PACKET_SRC_GUIDPREFIX, PACKET_DEST_ENTITYID, type STAGE_TYPE is (IDLE, PACKET_HEADER, PACKET_SRC_ADDR, PACKET_SRC_ENTITYID, PACKET_SRC_GUIDPREFIX, PACKET_DEST_ENTITYID,
CHECK_SRC_ENTITYID, LATCH_SEQ_NR, PROCESS_DATA, PROCESS_MESSAGE_SEQUENCE_NUMBERS, PROCESS_MESSAGE, PROCESS_GAP, PROCESS_GAP_SEQUENCE_NUMBERS, PROCESS_PL, CHECK_DEFAULT, CHECK_SRC_ENTITYID, LATCH_SEQ_NR, PROCESS_DATA, PROCESS_MESSAGE_SEQUENCE_NUMBERS, PROCESS_MESSAGE, PROCESS_GAP, PROCESS_GAP_SEQUENCE_NUMBERS, FIND_NEXT_VALID_IN_BITMAP,
LATCH_STRING_LENGTH, COMPARE_STRING, RXO_DURABILITY, RXO_DEADLINE, RXO_LIVELINESS, RXO_LEASE_DURATION, LATCH_LEASE_DURATION, PROCESS_PL, CHECK_DEFAULT, LATCH_STRING_LENGTH, COMPARE_STRING, RXO_DURABILITY, RXO_DEADLINE, RXO_LIVELINESS, RXO_LEASE_DURATION, LATCH_LEASE_DURATION,
RXO_RELIABILITY, RXO_DESTINATION_ORDER, RXO_OWNERSHIP, RXO_PRESENTATION, RXO_PARTITION, RXO_LATENCY_BUDGET, CHECK_MAX_SIZE_SERIALIZED, RXO_RELIABILITY, RXO_DESTINATION_ORDER, RXO_OWNERSHIP, RXO_PRESENTATION, RXO_PARTITION, RXO_LATENCY_BUDGET, CHECK_MAX_SIZE_SERIALIZED,
MATCH_DOMAIN_ID, MATCH_PROTOCOL_VERSION, LATCH_LOCATOR, LATCH_EXPECTS_INLINE_QOS, MATCH_GUID, CHECK_REMOTE_BUILTIN_ENDPOINTS, MATCH_DOMAIN_ID, MATCH_PROTOCOL_VERSION, LATCH_LOCATOR, LATCH_EXPECTS_INLINE_QOS, MATCH_GUID, CHECK_REMOTE_BUILTIN_ENDPOINTS,
PARTICIPANT_MATCH_STAGE, INFORM_ENDPOINTS_MATCH, INFORM_ENDPOINTS_UNMATCH, INFORM_ENDPOINTS_PARTICIPANT_UNMATCH, PARTICIPANT_STALE_CHECK, PARTICIPANT_MATCH_STAGE, INFORM_ENDPOINTS_MATCH, INFORM_ENDPOINTS_UNMATCH, INFORM_ENDPOINTS_PARTICIPANT_UNMATCH, PARTICIPANT_STALE_CHECK,
@ -274,11 +274,13 @@ architecture arch of rtps_builtin_endpoint is
-- Counter used to index the Subscriber Data -- Counter used to index the Subscriber Data
signal subscriber_data_cnt, subscriber_data_cnt_next : natural range 0 to work.math_pkg.max(READER_ENDPOINT_DATA.length-1, 0) := 0; signal subscriber_data_cnt, subscriber_data_cnt_next : natural range 0 to work.math_pkg.max(READER_ENDPOINT_DATA.length-1, 0) := 0;
-- Signifies the next expected Sequence Number of the current relevant Message Type (Participant/Publisher/Subscriber/Message Data) -- Signifies the next expected Sequence Number of the current relevant Message Type (Participant/Publisher/Subscriber/Message Data)
signal next_seq_nr, next_seq_nr_next : SEQUENCENUMBER_TYPE := (others => (others => '0')); signal next_seq_nr, next_seq_nr_next : SEQUENCENUMBER_TYPE := SEQUENCENUMBER_UNKNOWN;
-- Latch used to store the first Sequence Number in ACKNACK/HEARTBEAT/GAP Messages -- Generic Sequence Number Latch
signal first_seq_nr, first_seq_nr_next : SEQUENCENUMBER_TYPE := (others => (others => '0')); signal sn_latch_1, sn_latch_1_next : SEQUENCENUMBER_TYPE := SEQUENCENUMBER_UNKNOWN;
-- Latch used to store the last Sequence Number in HEARTBEAT/GAP Messages -- Generic Sequence Number Latch
signal last_seq_nr, last_seq_nr_next : SEQUENCENUMBER_TYPE := (others => (others => '0')); signal sn_latch_2, sn_latch_2_next : SEQUENCENUMBER_TYPE := SEQUENCENUMBER_UNKNOWN;
-- Generic Sequence Number Latch
signal sn_latch_3, sn_latch_3_next : SEQUENCENUMBER_TYPE := SEQUENCENUMBER_UNKNOWN;
-- Intermediate write enable signal. -- Intermediate write enable signal.
signal wr_sig : std_logic := '0'; signal wr_sig : std_logic := '0';
-- Signifies if a Stale Endpoint Check is in progress -- Signifies if a Stale Endpoint Check is in progress
@ -302,6 +304,14 @@ architecture arch of rtps_builtin_endpoint is
signal live_gap_start, live_gap_start_next : SEQUENCENUMBER_TYPE := (others => (others => '0')); signal live_gap_start, live_gap_start_next : SEQUENCENUMBER_TYPE := (others => (others => '0'));
-- Points to the first Sequence Number before "auto_live_seq_nr" (Signifies the end of the GAP between "man_live_seq_nr" and "auto_live_seq_nr") -- Points to the first Sequence Number before "auto_live_seq_nr" (Signifies the end of the GAP between "man_live_seq_nr" and "auto_live_seq_nr")
signal live_gap_end, live_gap_end_next : SEQUENCENUMBER_TYPE := (others => (others => '0')); signal live_gap_end, live_gap_end_next : SEQUENCENUMBER_TYPE := (others => (others => '0'));
-- Denotes the number of valid Bitmap longs (4-Byte words)
signal bitmap_cnt, bitmap_cnt_next : unsigned(log2c(MAX_BITMAP_WIDTH/CDR_LONG_WIDTH)-1 downto 0) := (others => '0');
-- NumberSet Bitmap Latch
signal bitmap_latch, bitmap_latch_next : BITMAP_TYPE := (others => (others => '0'));
-- Counter used to read out Bitmaps
signal cnt2, cnt2_next : natural range 0 to BITMAP_TYPE'length := 0;
-- Signal used to iterate through Bitmaps
signal bitmap_pos, bitmap_pos_next : natural range 0 to MAX_BITMAP_WIDTH-1 := 0;
-- Participant Announcement Timeout Time -- Participant Announcement Timeout Time
signal announcement_time, announcement_time_next : TIME_TYPE := (others => (others => '0')); signal announcement_time, announcement_time_next : TIME_TYPE := (others => (others => '0'));
-- Heartbeat/Liveliness Assertion Timeout Time -- Heartbeat/Liveliness Assertion Timeout Time
@ -398,6 +408,18 @@ architecture arch of rtps_builtin_endpoint is
alias key_flag : std_logic is flags(3); alias key_flag : std_logic is flags(3);
alias final_flag : std_logic is flags(1); alias final_flag : std_logic is flags(1);
alias payload_flag : std_logic is flags(4); alias payload_flag : std_logic is flags(4);
-- HEARTBEAT
alias first_seq_nr : SEQUENCENUMBER_TYPE is sn_latch_1;
alias first_seq_nr_next : SEQUENCENUMBER_TYPE is sn_latch_1_next;
alias last_seq_nr : SEQUENCENUMBER_TYPE is sn_latch_2;
alias last_seq_nr_next : SEQUENCENUMBER_TYPE is sn_latch_2_next;
-- GAP
alias gap_start : SEQUENCENUMBER_TYPE is sn_latch_1;
alias gap_start_next : SEQUENCENUMBER_TYPE is sn_latch_1_next;
alias gap_list_base : SEQUENCENUMBER_TYPE is sn_latch_2;
alias gap_list_base_next : SEQUENCENUMBER_TYPE is sn_latch_2_next;
alias gap_list_end : SEQUENCENUMBER_TYPE is sn_latch_3;
alias gap_list_end_next : SEQUENCENUMBER_TYPE is sn_latch_3_next;
--*****FUNCTION DECLARATION***** --*****FUNCTION DECLARATION*****
-- Return minimum of t1,t2,t3 or TIME_INVALID if t1,t2,t3 < t. -- Return minimum of t1,t2,t3 or TIME_INVALID if t1,t2,t3 < t.
@ -416,6 +438,16 @@ architecture arch of rtps_builtin_endpoint is
return ret; return ret;
end function; end function;
-- Helper function to convert BITMAP_TYPE to std_logic_vector
function to_slv_bitmap (input : BITMAP_TYPE) return std_logic_vector is
variable ret : std_logic_vector(0 to MAX_BITMAP_WIDTH-1) := (others => '0');
begin
for i in 0 to BITMAP_TYPE'length-1 loop
ret(i*WORD_WIDTH to ((i+1)*WORD_WIDTH)-1) := input(i);
end loop;
return ret;
end function;
procedure assert_sn is procedure assert_sn is
begin begin
if (message_type = EDP and is_subscriber = '0') then if (message_type = EDP and is_subscriber = '0') then
@ -519,6 +551,7 @@ begin
-- LIVELINESS_UPDATE Propagate Liveliness Assertion of remote Participant to respective local Reader Endpoints -- LIVELINESS_UPDATE Propagate Liveliness Assertion of remote Participant to respective local Reader Endpoints
-- PROCESS_GAP Parse RTPS GAP Submessage -- PROCESS_GAP Parse RTPS GAP Submessage
-- PROCESS_GAP_SEQUENCE_NUMBERS Process GAP Sequence Numbers. Update stored Sequence Numbers if necessary -- PROCESS_GAP_SEQUENCE_NUMBERS Process GAP Sequence Numbers. Update stored Sequence Numbers if necessary
-- FIND_NEXT_VALID_IN_BITMAP Iterate through Bitmap and find the next valid Sequence Number.
-- PROCESS_HEARTBEAT Parse RTPS HEARTBEAT Submessage -- PROCESS_HEARTBEAT Parse RTPS HEARTBEAT Submessage
-- PROCESS_HEARTBEAT_SEQUENCE_NUMBERS Process HEARTBEAT Sequence Numbers. Update stored Sequence Numbers if necessary. Set HEARTBEAT response timeout accordingly. -- PROCESS_HEARTBEAT_SEQUENCE_NUMBERS Process HEARTBEAT Sequence Numbers. Update stored Sequence Numbers if necessary. Set HEARTBEAT response timeout accordingly.
-- PROCESS_ACKNACK Parse RTPS ACKNACK Submessage -- PROCESS_ACKNACK Parse RTPS ACKNACK Submessage
@ -568,6 +601,8 @@ begin
variable tmp_default_qos_match : DEFAULT_QOS_MATCH_TYPE := READER_DEFAULT_QOS_MATCH; variable tmp_default_qos_match : DEFAULT_QOS_MATCH_TYPE := READER_DEFAULT_QOS_MATCH;
variable tmp_dw : DOUBLE_WORD_ARRAY := (others => (others => '0')); variable tmp_dw : DOUBLE_WORD_ARRAY := (others => (others => '0'));
variable mem_seq_nr : SEQUENCENUMBER_TYPE := SEQUENCENUMBER_UNKNOWN; variable mem_seq_nr : SEQUENCENUMBER_TYPE := SEQUENCENUMBER_UNKNOWN;
-- NOTE: We convert the bitamp to a slv to make operations easier (The tool should handle both cases equally)
variable tmp_bitmap : std_logic_vector(0 to MAX_BITMAP_WIDTH-1) := (others => '0');
begin begin
--DEFAULT Registered --DEFAULT Registered
stage_next <= stage; stage_next <= stage;
@ -595,8 +630,9 @@ begin
cnt_next <= cnt; cnt_next <= cnt;
reader_flags_next <= reader_flags; reader_flags_next <= reader_flags;
stale_check_next <= stale_check; stale_check_next <= stale_check;
first_seq_nr_next <= first_seq_nr; sn_latch_1_next <= sn_latch_1;
last_seq_nr_next <= last_seq_nr; sn_latch_2_next <= sn_latch_2;
sn_latch_3_next <= sn_latch_3;
auto_live_seq_nr_next <= auto_live_seq_nr; auto_live_seq_nr_next <= auto_live_seq_nr;
man_live_seq_nr_next <= man_live_seq_nr; man_live_seq_nr_next <= man_live_seq_nr;
live_gap_start_next <= live_gap_start; live_gap_start_next <= live_gap_start;
@ -615,6 +651,10 @@ begin
long_latch_next <= long_latch; long_latch_next <= long_latch;
rcvd_next <= rcvd; rcvd_next <= rcvd;
check_time_next <= check_time; check_time_next <= check_time;
cnt2_next <= cnt2;
bitmap_cnt_next <= bitmap_cnt;
bitmap_latch_next <= bitmap_latch;
bitmap_pos_next <= bitmap_pos;
-- DEFAULT Unregistered -- DEFAULT Unregistered
rd_sig <= '0'; rd_sig <= '0';
rd_guard := '0'; rd_guard := '0';
@ -1349,18 +1389,37 @@ begin
rd_guard := '1'; rd_guard := '1';
cnt_next <= cnt + 1; cnt_next <= cnt + 1;
-- Latch Sequence Numbers
case (cnt) is case (cnt) is
-- GapStart Sequence Number 1/2
when 0 => when 0 =>
first_seq_nr_next(0) <= unsigned(data_in_swapped); gap_start_next(0) <= unsigned(data_in_swapped);
-- GapStart Sequence Number 2/2
when 1 => when 1 =>
first_seq_nr_next(1) <= unsigned(data_in_swapped); gap_start_next(1) <= unsigned(data_in_swapped);
-- GapList.Base 1/2
when 2 => when 2 =>
last_seq_nr_next(0) <= unsigned(data_in_swapped); gap_list_base_next(0) <= unsigned(data_in_swapped);
-- GapList.Base 2/2
when 3 => when 3 =>
last_seq_nr_next(1) <= unsigned(data_in_swapped); gap_list_base_next(1) <= unsigned(data_in_swapped);
-- NOTE: Rest of GAP Message is ignored -- GapList.NumBits
when 4 =>
gap_list_end_next <= gap_list_base + to_integer(unsigned(data_in_swapped));
bitmap_cnt_next <= unsigned(round_slv(data_in_swapped(log2c(MAX_BITMAP_WIDTH)-1 downto 0),bitmap_cnt'length));
cnt2_next <= 0;
-- GapList.Bitmap
when 5 =>
-- Read Bitmap
if (cnt2 < bitmap_cnt) then
cnt2_next <= cnt2 + 1;
bitmap_latch_next(cnt2) <= data_in_swapped;
-- Keep Sub-State
cnt_next <= cnt;
else
stage_next <= PROCESS_GAP_SEQUENCE_NUMBERS; stage_next <= PROCESS_GAP_SEQUENCE_NUMBERS;
end if;
when others => when others =>
null; null;
end case; end case;
@ -1371,12 +1430,34 @@ begin
-- Wait for Sequence Number to be fetched from buffer -- Wait for Sequence Number to be fetched from buffer
if (mem_op_done = '1') then if (mem_op_done = '1') then
-- DEFAULT
stage_next <= SKIP_PACKET;
-- Sender known -- Sender known
if (mem_addr_base /= PARTICIPANT_MEMORY_MAX_ADDRESS) then if (mem_addr_base /= PARTICIPANT_MEMORY_MAX_ADDRESS) then
-- XXX: This logic relies on the sender marking continuous GAPs with the GAP Start Sequence Number and GAP End Sequence Number Set Base (i.e. the first bit in the bitmask should be 0/not in GAP) -- GAP is relevant
-- GAP only relevant if next expected sequence number in GAP if (gap_start <= mem_seq_nr and mem_seq_nr <= gap_list_end) then
if (first_seq_nr <= mem_seq_nr and last_seq_nr >= mem_seq_nr) then -- Next Expected is in GAP List
-- Store GAP end as last sequence number if (gap_list_base <= mem_seq_nr) then
-- Begin searching next valid SN from the current expected in the bitmap list
bitmap_pos_next <= to_integer(next_seq_nr - gap_list_base);
else
-- Begin searching next valid SN from the beginning of the bitmap list
next_seq_nr_next <= gap_list_base;
bitmap_pos_next <= 0;
end if;
stage_next <= FIND_NEXT_VALID_IN_BITMAP;
end if;
end if;
end if;
when FIND_NEXT_VALID_IN_BITMAP =>
-- Memory Operation Guard
if (mem_op_done = '1') then
tmp_bitmap := to_slv_bitmap(bitmap_latch);
-- First valid sequence number found
if (tmp_bitmap(bitmap_pos) = '0') then
-- Update next sequence number
mem_op_start <= '1'; mem_op_start <= '1';
mem_opcode <= UPDATE_PARTICIPANT; mem_opcode <= UPDATE_PARTICIPANT;
if (message_type = EDP and is_subscriber = '0') then if (message_type = EDP and is_subscriber = '0') then
@ -1386,11 +1467,13 @@ begin
else -- message_type = MESSAGE else -- message_type = MESSAGE
mem_field_flags <= PMF_MES_SEQ_NR_FLAG; mem_field_flags <= PMF_MES_SEQ_NR_FLAG;
end if; end if;
next_seq_nr_next <= last_seq_nr + 1;
end if;
end if;
-- DONE -- DONE
stage_next <= SKIP_PACKET; stage_next <= SKIP_PACKET;
else
-- Continue search
bitmap_pos_next <= bitmap_pos + 1;
next_seq_nr_next <= next_seq_nr + 1;
end if;
end if; end if;
when PROCESS_HEARTBEAT => when PROCESS_HEARTBEAT =>
-- Input FIFO Guard -- Input FIFO Guard
@ -1425,10 +1508,11 @@ begin
-- No scheduled Heartbeat Response -- No scheduled Heartbeat Response
if (participant_data.heartbeat_res_time = TIME_INVALID) then if (participant_data.heartbeat_res_time = TIME_INVALID) then
-- If current Sequence Number obsolete (removed from source history cache) -- If current Sequence Number obsolete (removed from source history cache)
if (first_seq_nr > mem_seq_nr and first_seq_nr <= last_seq_nr) then if (first_seq_nr > mem_seq_nr) then
-- Store new expected Sequence Number and set Response Dealy -- Store new expected Sequence Number and set Response Dealy
mem_op_start <= '1'; mem_op_start <= '1';
mem_opcode <= UPDATE_PARTICIPANT; mem_opcode <= UPDATE_PARTICIPANT;
next_seq_nr_next <= first_seq_nr;
if (message_type = EDP and is_subscriber = '0') then if (message_type = EDP and is_subscriber = '0') then
mem_field_flags <= PMF_PUB_SEQ_NR_FLAG or PMF_HEARTBEAT_RES_TIME_FLAG; mem_field_flags <= PMF_PUB_SEQ_NR_FLAG or PMF_HEARTBEAT_RES_TIME_FLAG;
elsif (message_type = EDP and is_subscriber = '1') then elsif (message_type = EDP and is_subscriber = '1') then
@ -1436,8 +1520,8 @@ begin
else -- message_type = MESSAGE else -- message_type = MESSAGE
mem_field_flags <= PMF_MES_SEQ_NR_FLAG or PMF_HEARTBEAT_RES_TIME_FLAG; mem_field_flags <= PMF_MES_SEQ_NR_FLAG or PMF_HEARTBEAT_RES_TIME_FLAG;
end if; end if;
next_seq_nr_next <= first_seq_nr; -- NOTE: Only response with ACKNACK if SN is available (Or no Final Flag)
if (PARTICIPANT_HEARTBEAT_RESPONSE_DELAY /= DURATION_INFINITE) then if (PARTICIPANT_HEARTBEAT_RESPONSE_DELAY /= DURATION_INFINITE and (first_seq_nr <= last_seq_nr or final_flag = '0')) then
tmp_dw := time + PARTICIPANT_HEARTBEAT_RESPONSE_DELAY; tmp_dw := time + PARTICIPANT_HEARTBEAT_RESPONSE_DELAY;
res_time <= tmp_dw; res_time <= tmp_dw;
-- NOTE: Last Bit denotes if this is Response or Suppression Delay -- NOTE: Last Bit denotes if this is Response or Suppression Delay
@ -1451,11 +1535,12 @@ begin
res_time <= TIME_INVALID; res_time <= TIME_INVALID;
end if; end if;
-- If new Sequence Number is available or Writer expects ACKNACK -- If new Sequence Number is available or Writer expects ACKNACK
elsif (PARTICIPANT_HEARTBEAT_RESPONSE_DELAY /= DURATION_INFINITE and (last_seq_nr >= mem_seq_nr or final_flag = '0')) then elsif (last_seq_nr >= mem_seq_nr or final_flag = '0') then
-- Set Response Delay -- Set Response Delay
mem_op_start <= '1'; mem_op_start <= '1';
mem_opcode <= UPDATE_PARTICIPANT; mem_opcode <= UPDATE_PARTICIPANT;
mem_field_flags <= PMF_HEARTBEAT_RES_TIME_FLAG; mem_field_flags <= PMF_HEARTBEAT_RES_TIME_FLAG;
if (PARTICIPANT_HEARTBEAT_RESPONSE_DELAY /= DURATION_INFINITE) then
tmp_dw := time + PARTICIPANT_HEARTBEAT_RESPONSE_DELAY; tmp_dw := time + PARTICIPANT_HEARTBEAT_RESPONSE_DELAY;
res_time <= tmp_dw; res_time <= tmp_dw;
-- NOTE: Last Bit denotes if this is Response or Suppression Delay -- NOTE: Last Bit denotes if this is Response or Suppression Delay
@ -1465,14 +1550,18 @@ begin
if (tmp_dw < check_time) then if (tmp_dw < check_time) then
check_time_next <= tmp_dw; check_time_next <= tmp_dw;
end if; end if;
else
res_time <= TIME_INVALID;
end if;
end if; end if;
-- Currently in Heartbeat Response Delay -- Currently in Heartbeat Response Delay
elsif (participant_data.heartbeat_res_time(1)(0) = '0') then elsif (participant_data.heartbeat_res_time(1)(0) = '0') then
-- If current Sequence Number obsolete (removed from source history cache) -- If current Sequence Number obsolete (removed from source history cache)
if (first_seq_nr > mem_seq_nr and first_seq_nr <= last_seq_nr) then if (first_seq_nr > mem_seq_nr) then
-- Store new expected Sequence Number -- Store new expected Sequence Number
mem_op_start <= '1'; mem_op_start <= '1';
mem_opcode <= UPDATE_PARTICIPANT; mem_opcode <= UPDATE_PARTICIPANT;
next_seq_nr_next <= first_seq_nr;
if (message_type = EDP and is_subscriber = '0') then if (message_type = EDP and is_subscriber = '0') then
mem_field_flags <= PMF_PUB_SEQ_NR_FLAG; mem_field_flags <= PMF_PUB_SEQ_NR_FLAG;
elsif (message_type = EDP and is_subscriber = '1') then elsif (message_type = EDP and is_subscriber = '1') then
@ -1480,7 +1569,6 @@ begin
else -- message_type = MESSAGE else -- message_type = MESSAGE
mem_field_flags <= PMF_MES_SEQ_NR_FLAG; mem_field_flags <= PMF_MES_SEQ_NR_FLAG;
end if; end if;
next_seq_nr_next <= first_seq_nr;
end if; end if;
end if; end if;
end if; end if;
@ -5635,8 +5723,9 @@ begin
mem_prev_addr_base <= PARTICIPANT_MEMORY_MAX_ADDRESS; mem_prev_addr_base <= PARTICIPANT_MEMORY_MAX_ADDRESS;
seq_nr <= SEQUENCENUMBER_UNKNOWN; seq_nr <= SEQUENCENUMBER_UNKNOWN;
next_seq_nr <= SEQUENCENUMBER_UNKNOWN; next_seq_nr <= SEQUENCENUMBER_UNKNOWN;
first_seq_nr <= SEQUENCENUMBER_UNKNOWN; sn_latch_1 <= SEQUENCENUMBER_UNKNOWN;
last_seq_nr <= SEQUENCENUMBER_UNKNOWN; sn_latch_2 <= SEQUENCENUMBER_UNKNOWN;
sn_latch_3 <= SEQUENCENUMBER_UNKNOWN;
auto_live_seq_nr <= convert_to_double_word(to_unsigned(2, 64)); auto_live_seq_nr <= convert_to_double_word(to_unsigned(2, 64));
man_live_seq_nr <= FIRST_SEQUENCENUMBER; man_live_seq_nr <= FIRST_SEQUENCENUMBER;
live_gap_start <= convert_to_double_word(to_unsigned(2, 64)); live_gap_start <= convert_to_double_word(to_unsigned(2, 64));
@ -5648,6 +5737,8 @@ begin
participant_data <= ZERO_PARTICIPANT_DATA; participant_data <= ZERO_PARTICIPANT_DATA;
participant_latch_data <= ZERO_PARTICIPANT_LATCH_DATA; participant_latch_data <= ZERO_PARTICIPANT_LATCH_DATA;
cnt <= 0; cnt <= 0;
cnt2 <= 0;
bitmap_pos <= 0;
mem_cnt <= 0; mem_cnt <= 0;
participant_data_cnt <= 0; participant_data_cnt <= 0;
publisher_data_cnt <= 0; publisher_data_cnt <= 0;
@ -5669,6 +5760,8 @@ begin
rcvd <= (others => '0'); rcvd <= (others => '0');
reader_flags <= (others => '0'); reader_flags <= (others => '0');
current_pmf <= (others => '0'); current_pmf <= (others => '0');
bitmap_cnt <= (others => '0');
bitmap_latch <= (others => (others => '0'));
else else
stage <= stage_next; stage <= stage_next;
return_stage <= return_stage_next; return_stage <= return_stage_next;
@ -5691,8 +5784,9 @@ begin
mem_prev_addr_base <= mem_prev_addr_base_next; mem_prev_addr_base <= mem_prev_addr_base_next;
seq_nr <= seq_nr_next; seq_nr <= seq_nr_next;
next_seq_nr <= next_seq_nr_next; next_seq_nr <= next_seq_nr_next;
first_seq_nr <= first_seq_nr_next; sn_latch_1 <= sn_latch_1_next;
last_seq_nr <= last_seq_nr_next; sn_latch_2 <= sn_latch_2_next;
sn_latch_3 <= sn_latch_3_next;
auto_live_seq_nr <= auto_live_seq_nr_next; auto_live_seq_nr <= auto_live_seq_nr_next;
man_live_seq_nr <= man_live_seq_nr_next; man_live_seq_nr <= man_live_seq_nr_next;
live_gap_start <= live_gap_start_next; live_gap_start <= live_gap_start_next;
@ -5704,6 +5798,8 @@ begin
participant_data <= participant_data_next; participant_data <= participant_data_next;
participant_latch_data <= participant_latch_data_next; participant_latch_data <= participant_latch_data_next;
cnt <= cnt_next; cnt <= cnt_next;
cnt2 <= cnt2_next;
bitmap_pos <= bitmap_pos_next;
mem_cnt <= mem_cnt_next; mem_cnt <= mem_cnt_next;
participant_data_cnt <= participant_data_cnt_next; participant_data_cnt <= participant_data_cnt_next;
publisher_data_cnt <= publisher_data_cnt_next; publisher_data_cnt <= publisher_data_cnt_next;
@ -5725,6 +5821,8 @@ begin
rcvd <= rcvd_next; rcvd <= rcvd_next;
reader_flags <= reader_flags_next; reader_flags <= reader_flags_next;
current_pmf <= current_pmf_next; current_pmf <= current_pmf_next;
bitmap_cnt <= bitmap_cnt_next;
bitmap_latch <= bitmap_latch_next;
end if; end if;
end if; end if;
end process; end process;