Fix DESTINATION_ORDER_QOS in dds_endpoint

The rtps_endpoint only sends the source timestamp (TIME_INVALID if no
source timestamp provided). If ordering BY_RECEPTION, the sample is added
to the list tail. If ordering BY_SOURCE the samples are ordered
according to the source timestamp, but droped if the source timestamp is
earlier than a sample that has been read by the user or INVALID (Ensures
determenistic behavior).
This commit is contained in:
Greek 2021-01-26 18:57:09 +01:00
parent 164bd508c1
commit 728a6964d3

View File

@ -2,9 +2,6 @@ library ieee;
use ieee.std_logic_1164.all; use ieee.std_logic_1164.all;
use ieee.numeric_std.all; use ieee.numeric_std.all;
-- TODO: Cancel KHG operation on incomplete payload parsing
-- TODO: Make sure rest of Payload slot is zero initialized
entity history_cache is entity history_cache is
generic ( generic (
TIME_BASED_FILTER_QOS : DURATION_TYPE := DEFAULT_TIME_BASED_FILTER_QOS; TIME_BASED_FILTER_QOS : DURATION_TYPE := DEFAULT_TIME_BASED_FILTER_QOS;
@ -13,6 +10,7 @@ entity history_cache is
HISTORY_QOS : std_logic_vector(CDR_ENUMERATION_WIDTH-1 downto 0) := DEFAULT_HISTORY_QOS; HISTORY_QOS : std_logic_vector(CDR_ENUMERATION_WIDTH-1 downto 0) := DEFAULT_HISTORY_QOS;
RELIABILITY_QOS : std_logic_vector(CDR_ENUMERATION_WIDTH-1 downto 0) := DEFAULT_RELIABILTY_QOS; RELIABILITY_QOS : std_logic_vector(CDR_ENUMERATION_WIDTH-1 downto 0) := DEFAULT_RELIABILTY_QOS;
PRESENTATION_QOS : std_logic_vector(CDR_ENUMERATION_WIDTH-1 downto 0) := DEFAULT_PRESENTATION_QOS; PRESENTATION_QOS : std_logic_vector(CDR_ENUMERATION_WIDTH-1 downto 0) := DEFAULT_PRESENTATION_QOS;
DESTINATION_ORDER_QOS : std_logic_vector(CDR_ENUMERATION_WIDTH-1 downto 0) := DEFAULT_DESTINATION_ORDER_QOS;
COHERENT_ACCESS : boolean := DEFAULT_COHERENT_ACCESS; COHERENT_ACCESS : boolean := DEFAULT_COHERENT_ACCESS;
ORDERED_ACCESS : boolean := DEFAULT_ORDERED_ACCESS; ORDERED_ACCESS : boolean := DEFAULT_ORDERED_ACCESS;
); );
@ -206,6 +204,7 @@ architecture arch of history_cache is
signal sample_addr_latch_2, sample_addr_latch_2_next : unsigned(SAMPLE_MEMORY_ADDR_WIDTH-1 downto 0) := (others => '0'); signal sample_addr_latch_2, sample_addr_latch_2_next : unsigned(SAMPLE_MEMORY_ADDR_WIDTH-1 downto 0) := (others => '0');
signal sample_addr_latch_3, sample_addr_latch_3_next : unsigned(SAMPLE_MEMORY_ADDR_WIDTH-1 downto 0) := (others => '0'); signal sample_addr_latch_3, sample_addr_latch_3_next : unsigned(SAMPLE_MEMORY_ADDR_WIDTH-1 downto 0) := (others => '0');
signal ts_latch, ts_latch_next : TIME_TYPE := TIME_INVALID; signal ts_latch, ts_latch_next : TIME_TYPE := TIME_INVALID;
signal last_read_ts, last_read_ts_next : TIME_TYPE := TIME_INVALID;
signal long_latch, long_latch_next : std_logic_vector(CDR_LONG_WIDTH-1 downto 0) := (others => '0'); signal long_latch, long_latch_next : std_logic_vector(CDR_LONG_WIDTH-1 downto 0) := (others => '0');
signal payload_mem_full, payload_mem_full_next : std_logic := '0'; signal payload_mem_full, payload_mem_full_next : std_logic := '0';
signal sample_mem_full, sample_mem_full_next : std_logic := '0'; signal sample_mem_full, sample_mem_full_next : std_logic := '0';
@ -440,6 +439,7 @@ begin
unmark_instances_next <= unmark_instances; unmark_instances_next <= unmark_instances;
is_first_instance_sample_next <= is_first_instance_sample; is_first_instance_sample_next <= is_first_instance_sample;
dynamic_next_instance_next <= dynamic_next_instance; dynamic_next_instance_next <= dynamic_next_instance;
last_read_ts_next <= last_read_ts;
ack_dds <= '0'; ack_dds <= '0';
inst_data_variant <= '0'; inst_data_variant <= '0';
done_dds <= '0'; done_dds <= '0';
@ -634,6 +634,22 @@ begin
-- Timestamp 2/2 -- Timestamp 2/2
when 2 => when 2 =>
ts_latch_next(1) <= data_in_rtps; ts_latch_next(1) <= data_in_rtps;
-- Synthesis Guard
if (DESTINATION_ORDER_QOS = BY_SOURCE_TIMESTAMP_DESTINATION_ORDER_QOS) then
-- Check Timestamp
tmp_dw := (0 => ts_latch(0), 1 => unsigned(data_in_rtps));
-- NOTE: Equal timestamps are still acceptable, as they are inserted after the
-- highest last read sample.
-- Timestamp is smaller than highest last read (Or is Invalid)
if (tmp_dw /= TIME_INVALID or tmp_dw < last_read_ts) then
-- Drop Sample
stage_next <= SKIP_ADD_DROP;
end if;
end if;
-- Lifespan Deadline 2/2 -- Lifespan Deadline 2/2
when 4 => when 4 =>
-- Skip Key Hash, if not available -- Skip Key Hash, if not available
@ -665,6 +681,7 @@ begin
sample_wen <= '0'; sample_wen <= '0';
sample_addr_next <= sample_addr; -- Keep Addr (Payload Addr) sample_addr_next <= sample_addr; -- Keep Addr (Payload Addr)
key_hash_next(3) <= data_in_rtps; key_hash_next(3) <= data_in_rtps;
-- Writer Endpoint Position
when 9 => when 9 =>
-- Latch Input, but do not pass to Memory -- Latch Input, but do not pass to Memory
writer_pos_next <= to_integer(unsigned(data_in_rtps)); writer_pos_next <= to_integer(unsigned(data_in_rtps));
@ -678,7 +695,7 @@ begin
when ADD_PAYLOAD_ADDRESS => when ADD_PAYLOAD_ADDRESS =>
-- Precondition: sample_addr (Payload Address) -- Precondition: sample_addr (Payload Address)
sample_addr_next <= sample_addr + 1; -- Instance Address sample_addr_next <= cur_sample + SMF_INSTANCE_ADDR_OFFSET;
if (has_data = '1') then if (has_data = '1') then
-- Store Payload Address -- Store Payload Address
@ -762,7 +779,7 @@ begin
-- No Empty Payload Slots available -- No Empty Payload Slots available
if (payload_read_data = PAYLOAD_MEMORY_MAX_ADDRESS) then if (payload_read_data = PAYLOAD_MEMORY_MAX_ADDRESS) then
-- Reject Change -- Reject Change
stage_next <= SKIP_ADD; stage_next <= SKIP_ADD_REJECT;
else else
-- Latch next Payload Slot and Continue -- Latch next Payload Slot and Continue
cur_payload_next <= payload_read_data; cur_payload_next <= payload_read_data;
@ -808,7 +825,7 @@ begin
-- Wait for Instance Search to finish -- Wait for Instance Search to finish
if (inst_op_done = '1') then if (inst_op_done = '1') then
sample_addr_next <= sample_addr + 1; -- Disposed Gen Counter sample_addr_next <= cur_sample + SMF_DISPOSED_GEN_CNT_OFFSET;
-- Instance Found -- Instance Found
if (inst_addr_base /= INSTANCE_MEMORY_MAX_ADDRESS) then if (inst_addr_base /= INSTANCE_MEMORY_MAX_ADDRESS) then
@ -819,25 +836,25 @@ begin
-- TIME_BASED_FILTER QOS -- TIME_BASED_FILTER QOS
if (TIME_BASED_FILTER_QOS /= DURATION_ZERO and time <= inst_data.ignore_deadline) then if (TIME_BASED_FILTER_QOS /= DURATION_ZERO and time <= inst_data.ignore_deadline) then
-- Drop Change -- Drop Change
res_rtps <= ACCEPTED; res_rtps <= ACCEPTED;
stage_next <= IDLE; stage_next <= IDLE;
-- RESOURCE_LIMITS_QOS (MAX_SAMPLES_PER_INSTANCE) -- RESOURCE_LIMITS_QOS (MAX_SAMPLES_PER_INSTANCE)
elsif (MAX_SAMPLES_PER_INSTANCE /= LENGTH_UNLIMITED and inst_data.sample_cnt = MAX_SAMPLES_PER_INSTANCE) then elsif (MAX_SAMPLES_PER_INSTANCE /= LENGTH_UNLIMITED and inst_data.sample_cnt = MAX_SAMPLES_PER_INSTANCE) then
if (HISTORY_QOS = KEEP_LAST_HISTORY_QOS and RELIABILITY_QOS = RELIABLE_RELIABILITY_QOS) then if (HISTORY_QOS = KEEP_LAST_HISTORY_QOS and RELIABILITY_QOS = RELIABLE_RELIABILITY_QOS) then
-- Reject Change -- Reject Change
res_rtps <= REJECTED; res_rtps <= REJECTED;
stage_next <= IDLE; stage_next <= IDLE;
else else
-- Accept Change (Remove Oldest Instance Sample) -- Accept Change (Remove Oldest Instance Sample)
remove_oldest_inst_sample_next <= '1'; remove_oldest_inst_sample_next <= '1';
res_rtps <= ACCEPTED; res_rtps <= ACCEPTED;
stage_next <= UPDATE_INSTANCE; stage_next <= UPDATE_INSTANCE;
end if; end if;
-- RESOURCE_LIMITS_QOS (MAX_SAMPLES) -- RESOURCE_LIMITS_QOS (MAX_SAMPLES)
elsif (empty_sample_list_head = empty_sample_list_tail) then elsif (empty_sample_list_head = empty_sample_list_tail) then
if (HISTORY_QOS = KEEP_ALL_HISTORY_QOS and RELIABILITY_QOS = RELIABLE_RELIABILITY_QOS) then if (HISTORY_QOS = KEEP_ALL_HISTORY_QOS and RELIABILITY_QOS = RELIABLE_RELIABILITY_QOS) then
-- Reject Change -- Reject Change
res_rtps <= REJECTED; res_rtps <= REJECTED;
stage_next <= IDLE; stage_next <= IDLE;
else else
-- Accept Change (Remove Oldest Sample) -- Accept Change (Remove Oldest Sample)
@ -1050,7 +1067,7 @@ begin
case (cnt) is case (cnt) is
-- Disposed Generation Counter -- Disposed Generation Counter
when 0 => when 0 =>
sample_addr_next <= sample_addr + 1; sample_addr_next <= cur_sample + SMF_NO_WRITERS_GEN_CNT_OFFSET;
sample_wen <= '1'; sample_wen <= '1';
-- NOT_ALIVE_DISPOSED -> ALIVE Transition -- NOT_ALIVE_DISPOSED -> ALIVE Transition
@ -1074,60 +1091,76 @@ begin
if (newest_sample = SAMPLE_MEMORY_MAX_ADDRESS) then if (newest_sample = SAMPLE_MEMORY_MAX_ADDRESS) then
stage_next <= FINALIZE_SAMPLE; stage_next <= FINALIZE_SAMPLE;
sample_addr_next <= empty_sample_list_head + SMF_PREV_ADDR_OFFSET; sample_addr_next <= empty_sample_list_head + SMF_PREV_ADDR_OFFSET;
cur_sample_next <= empty_sample_list_head;
next_sample_next <= SAMPLE_MEMORY_MAX_ADDRESS; next_sample_next <= SAMPLE_MEMORY_MAX_ADDRESS;
prev_sample_next <= SAMPLE_MEMORY_MAX_ADDRESS; prev_sample_next <= SAMPLE_MEMORY_MAX_ADDRESS;
cnt_next <= 0; cnt_next <= 0;
elsif (DESTINATION_ORDER_QOS = BY_RECEPTION_TIMESTAMP_DESTINATION_ORDER_QOS) then
stage_next <= FIX_POINTERS;
prev_sample_next <= newest_sample;
sample_addr_next <= newest_sample + SMF_NEXT_ADDR_OFFSET;
cur_sample_next <= newest_sample;
cnt_next <= 0;
else else
stage_next <= FIND_POS; stage_next <= FIND_POS;
prev_sample_next <= newest_sample; prev_sample_next <= newest_sample;
sample_addr_next <= newest_sample + SMF_TIMESTAMP_OFFSET; sample_addr_next <= newest_sample + SMF_TIMESTAMP_OFFSET;
cur_sample_next <= newest_sample;
cnt_next <= 0; cnt_next <= 0;
end if; end if;
when others => when others =>
null; null;
end case; end case;
when FIND_POS => when FIND_POS =>
-- Precondition: prev_sample set, sample_addr (Timestamp 1/2 Addr of prev_sample) -- Synthesis Guard
if (DESTINATION_ORDER_QOS /= BY_RECEPTION_TIMESTAMP_DESTINATION_ORDER_QOS) then
cnt_next <= cnt + 1; -- Precondition: prev_sample set, sample_addr (Timestamp 1/2 Addr of prev_sample)
case (cnt) is cnt_next <= cnt + 1;
-- Preload
when 0 => case (cnt) is
sample_addr_next <= sample_addr + 1; -- Preload
sample_ren <= '1'; when 0 =>
-- Timestamp 1/2 sample_addr_next <= sample_addr + 1; -- Timestamp 2/2
when 1 => sample_ren <= '1';
sample_addr_next <= sample_addr + SMF_PREV_ADDR_OFFSET-(SMF_TIMESTAMP_OFFSET+1); -- Prev Addr -- Timestamp 1/2
sample_ren <= '1'; when 1 =>
long_latch_next <= sample_read_data; sample_addr_next <= cur_sample + SMF_PREV_ADDR_OFFSET;
-- Timestamp 2/2 sample_ren <= '1';
when 2 => long_latch_next <= sample_read_data;
sample_ren <= '1'; -- Timestamp 2/2
when 2 =>
tmp_dw := (0 => unsigned(long_latch), 1 => unsigned(sample_read_data)); sample_ren <= '1';
sample_addr_next <= sample_addr + SMF_NEXT_ADDR_OFFSET-SMF_PREV_ADDR_OFFSET; -- Next Addr
-- Found position (After current slot)
if (ts_latch >= tmp_dw) then
stage_next <= FIX_POINTERS;
cnt_next <= 0;
end if;
-- Previous Address
when 3 =>
-- No previous Slot (Oldest Sample)
if (sample_read_data = PAYLOAD_MEMORY_MAX_ADDRESS) then
assert (prev_sample = oldest_sample) report "Previous Sample is MAX_ADDR, but sample is not OLDEST (HEAD)" severity FAILURE;
stage_next <= FIX_POINTERS; tmp_dw := (0 => unsigned(long_latch), 1 => unsigned(sample_read_data));
cnt_next <= 0;
else sample_addr_next <= cur_sample + SMF_NEXT_ADDR_OFFSET;
prev_sample_next <= sample_read_data;
sample_addr_next <= sample_read_data + SMF_TIMESTAMP_OFFSET; -- Found position (After current slot)
cnt_next <= 0; if (ts_latch >= tmp_dw) then
end if; stage_next <= FIX_POINTERS;
end case; cnt_next <= 0;
end if;
-- Previous Pointer (Previous Sample)
when 3 =>
-- No previous Slot (Oldest Sample)
if (sample_read_data = PAYLOAD_MEMORY_MAX_ADDRESS) then
assert (prev_sample = oldest_sample) report "Previous Sample is MAX_ADDR, but sample is not OLDEST (HEAD)" severity FAILURE;
-- NOTE: Sample is added to HEAD of List
prev_sample_next <= SAMPLE_MEMORY_MAX_ADDRESS;
next_sample_next <= cur_sample;
stage_next <= FIX_POINTERS;
cnt_next <= 2; -- Skip to Previous Pointer Fix
else
-- Continue Search
prev_sample_next <= sample_read_data;
sample_addr_next <= sample_read_data + SMF_TIMESTAMP_OFFSET;
cnt_next <= 0;
end if;
end case;
end if;
when FIX_POINTERS => when FIX_POINTERS =>
-- Precondition: sample_addr (Next Addr of prev_sample) -- Precondition: sample_addr (Next Addr of prev_sample)
@ -1137,6 +1170,7 @@ begin
-- Preload -- Preload
when 0 => when 0 =>
sample_ren <= '1'; sample_ren <= '1';
-- Next Pointer (Previous Sample)
when 1 => when 1 =>
-- Fix Next Pointer -- Fix Next Pointer
@ -1149,7 +1183,8 @@ begin
next_sample_next <= SAMPLE_MEMORY_MAX_ADDRESS; next_sample_next <= SAMPLE_MEMORY_MAX_ADDRESS;
stage_next <= FINALIZE_SAMPLE; stage_next <= FINALIZE_SAMPLE;
sample_addr_next <= empty_sample_list_head + SMF_PREV_ADDR_OFFSET; -- Prev Addr of New Sample sample_addr_next <= empty_sample_list_head + SMF_PREV_ADDR_OFFSET;
cur_sample_next <= empty_sample_list_head;
cnt_next <= 0; cnt_next <= 0;
else else
-- Latch Next Sample -- Latch Next Sample
@ -1157,13 +1192,15 @@ begin
sample_addr_next <= sample_read_data + SMF_PREV_ADDR_OFFSET; -- Prev Addr of Next Sample sample_addr_next <= sample_read_data + SMF_PREV_ADDR_OFFSET; -- Prev Addr of Next Sample
end if; end if;
-- Previous Pointer (Next Sample)
when 2 => when 2 =>
-- Fix Previous Pointer -- Fix Previous Pointer
sample_write_data <= empty_sample_list_head; sample_write_data <= empty_sample_list_head;
sample_wen <= '1'; sample_wen <= '1';
stage_next <= FINALIZE_SAMPLE; stage_next <= FINALIZE_SAMPLE;
sample_addr_next <= empty_sample_list_head + SMF_PREV_ADDR_OFFSET; -- Prev Addr of New Sample sample_addr_next <= empty_sample_list_head + SMF_PREV_ADDR_OFFSET;
cur_sample_next <= empty_sample_list_head;
cnt_next <= 0; cnt_next <= 0;
when others => when others =>
null; null;
@ -1176,7 +1213,7 @@ begin
case (cnt) is case (cnt) is
-- Previous Sample Address -- Previous Sample Address
when 0 => when 0 =>
sample_addr_next <= sample_addr + 1; -- Next Sample sample_addr_next <= cur_sample + SMF_NEXT_ADDR_OFFSET;
-- Write Prev Addr -- Write Prev Addr
sample_write_data <= prev_sample; sample_write_data <= prev_sample;
@ -1439,7 +1476,7 @@ begin
stage_next <= IDLE; stage_next <= IDLE;
end if; end if;
end if; end if;
when SKIP_ADD => when SKIP_ADD_REJECT =>
case (cnt) is case (cnt) is
-- SKIP READ -- SKIP READ
when 0 => when 0 =>
@ -1455,6 +1492,22 @@ begin
when others => when others =>
null; null;
end case; end case;
when SKIP_ADD_DROP =>
case (cnt) is
-- SKIP READ
when 0 =>
ready_in_rtps <= '1';
-- Wait until last word from input
if (last_word_in_rtps = '1') then
cnt_next <= 1;
end if;
-- DROP SAMPLE
when 1 =>
res_rtps <= ACCEPTED;
stage_next <= IDLE;
when others =>
null;
end case;
when REMOVE_WRITER => when REMOVE_WRITER =>
-- Memory Operation Guard -- Memory Operation Guard
if (inst_op_done = '1') then if (inst_op_done = '1') then
@ -2015,6 +2068,14 @@ begin
-- Invalidate Data -- Invalidate Data
si_valid_sig_next <= '0'; si_valid_sig_next <= '0';
-- Synthesis Guard
if (DESTINATION_ORDER_QOS = BY_SOURCE_TIMESTAMP_DESTINATION_ORDER_QOS) then
-- Update Last Read Timestamp
if (si_source_timestamp_sig > last_read_ts) then
last_read_ts_next <= si_source_timestamp_sig;
end if;
end if;
-- Sample not marked as Read -- Sample not marked as Read
if (sample_status_info(READ_FLAG) /= '1') then if (sample_status_info(READ_FLAG) /= '1') then
-- Mark Sample as Read -- Mark Sample as Read