From 80cffb819778702ec3ab0811c9c497a4ececcaa8 Mon Sep 17 00:00:00 2001 From: Greek Date: Mon, 8 Feb 2021 12:31:36 +0100 Subject: [PATCH] Fix unaligned payload handling in DDS Reader Since the payload can only be padded until the next 4-byte aligned address, we needed a way to read out only the actual payload in case the payload was not aligned in the last payload slot (did not go until the end of the payload slot). This is now handled by an additional bit flag in the Sample Status Info which denotes if the payload is aligned. In the case the payload is unaligned, the last address of the last payload slot contains the offset of the actual payload end. This commit also adds MEMORY RESET states for the Sample, payload, and instance Memory. --- src/REF.txt | 29 ++- src/TODO.txt | 17 +- src/dds_reader.vhd | 365 +++++++++++++++++++++++++----------- src/rtps_config_package.vhd | 25 +-- src/rtps_reader.vhd | 7 +- 5 files changed, 303 insertions(+), 140 deletions(-) diff --git a/src/REF.txt b/src/REF.txt index cd5799f..09e112a 100644 --- a/src/REF.txt +++ b/src/REF.txt @@ -348,9 +348,9 @@ WRITER 03| | +-------------------------------------------------------------+ 04| IPv4_ADDRESS | - +-----------------------------+-------------------------+-+-+-+ -05| UDP_PORT | UNUSED |B|H|Q| - +-----------------------------+-------------------------+-+-+-+ + +-----------------------------+-------------------------------+ +05| UDP_PORT | READER_FLAGS | + +-----------------------------+-------------------------------+ 06| | + LEASE_DEADLINE + [Reliable Only] 07| | @@ -370,6 +370,16 @@ WRITER 14| REQ_BITMAP | [Reliable Only] +-------------------------------------------------------------+ +READER_FLAGS +------------ +16..............8...............0 ++-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ ++-------------------------+-+-+-+ +| UNUSED |B|H|Q| ++-------------------------+-+-+-+ +Q...Reader expects in-line QoS +H...Reader expects Historical Data +B...Reader has RELIABILITY BEST_EFFORT HISTORY CACHE ============= @@ -434,12 +444,13 @@ STATUS INFO ----------- 31............24..............16..............8...............0 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ -+-+-+-+-------------------------------------------------+-+-+-+ -|R|P|K| UNUSED |F|U|D| -+-+-+-+-------------------------------------------------+-+-+-+ ++-+-+-+-+-----------------------------------------------+-+-+-+ +|R|P|A|K| UNUSED |F|U|D| ++-+-+-+-+-----------------------------------------------+-+-+-+ R...Sample has been Read P...Sample has associated Payload +A...Associated Payload is aligned (Payload does extend until end of last Palyload Slot) K...Key Hash available F...FilteredFlag @@ -458,8 +469,10 @@ PAYLOAD MEMORY **| | +-------------------------------------------------------------+ -HISTORY CACHE INPUT -=================== +DDS ENTITY INPUT +================ +READER +------ 31............24..............16..............8...............0 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +-------------------------------------------------------------+ diff --git a/src/TODO.txt b/src/TODO.txt index 509e62a..b990c2a 100644 --- a/src/TODO.txt +++ b/src/TODO.txt @@ -72,6 +72,8 @@ * The Lease Duration is also updated if the Cache Change is not accepted by the DDS/HC. This in effect "skews" the "correctness" of the Writer Liveliness Protocol until the reader has no pending request from the Writer. * If an Instance is DISPOSED, but later has no active writers, the Instance STAYS in the NOT_ALIVE_DISPOSED state. * Is a Writer that is Disposing a Instance also Unregistering that instance? (Currently only Unregistering removes the remote Writer) + - No +* Since Lifespan is a duration, there is an inherent difference in the expiration time between writer and reader. This in addition to the fact that the reader may use the Reception time for the expiration time calculation could lead to an actual expiration duration almost double in length (If sent right before expiring locally in the writer). * Fast-RTPS doen not follow DDSI-RTPS Specification - Open Github Issue @@ -191,10 +193,16 @@ DESIGN DECISIONS sizes are adjusted according to that), or may be variable, in which case the payload is stored in a linked list of predefined sized memory frames. The first word of a payload contains the address of the next linked memory frame. If this is the last frame (or if the payload is static and there - are no linked frames), the address is MAX_ADDRESS. The last bit of this address is the "occupied" - bit. This bit signifies if the memory frame is used or free, and is used for the insert operation - to find a new empty slot. This in effect means that all frame sizes have to be a multiple of 2 - (all frame addresses have to be aligned to 2). + are no linked frames), the address is MAX_ADDRESS. + +* !REJECTED! The last bit of this address is the "occupied" bit. This bit signifies if the memory + frame is used or free, and is used for the insert operation to find a new empty slot. This in + effect means that all frame sizes have to be a multiple of 2 (all frame addresses have to be + aligned to 2). + +* If the last payload slot of a variable sized payload is not aligned with the actual end of the + Payload slot, we mark this via a bit in the sample info memory, and store the last address of the + actual payload in the last address of the payload slot. * !REJECTED! The History Cache (HC) is the interface between RTPS and DDS. The History Cache contains the Sample Info and Payload memories. The HC has two input "sides", one is connected to the DDS @@ -224,6 +232,7 @@ DESIGN DECISIONS sense to implement dual port RAMs for the History Cache. + PROTOCOL UNCOMPLIANCE ===================== * Partition QoS diff --git a/src/dds_reader.vhd b/src/dds_reader.vhd index 3b3c684..bfa969f 100644 --- a/src/dds_reader.vhd +++ b/src/dds_reader.vhd @@ -78,7 +78,7 @@ architecture arch of dds_reader is -- Highest Sample Info Memory Address constant SAMPLE_MEMORY_MAX_ADDRESS : unsigned(SAMPLE_MEMORY_ADDR_WIDTH-1 downto 0) := to_unsigned(SAMPLE_MEMORY_SIZE-1, SAMPLE_MEMORY_ADDR_WIDTH); -- Highest Sample Info Frame Address - constant MAX_SAMPLE_ADDRESS : unsigned(SAMPLE_MEMORY_ADDR_WIDTH-1 downto 0) := SAMPLE_MEMORY_MAX_ADDRESS - SAMPLE_INFO_FRAME_SIZE + 1; + constant MAX_SAMPLE_ADDRESS : unsigned(SAMPLE_MEMORY_ADDR_WIDTH-1 downto 0) := SAMPLE_MEMORY_MAX_ADDRESS - SAMPLE_FRAME_SIZE + 1; -- *PAYLOAD MEMORY* -- Payload Memory Size in 4-Byte Words @@ -143,7 +143,7 @@ architecture arch of dds_reader is --*****TYPE DECLARATION***** -- FSM states. Explained below in detail - type STAGE_TYPE is (IDLE, UNKNOWN_OPERATION, ADD_SAMPLE_INFO, ADD_PAYLOAD_ADDRESS, ADD_PAYLOAD, NEXT_PAYLOAD_SLOT, ZERO_PAYLOAD, GET_KEY_HASH, INITIATE_INSTANCE_SEARCH, + type STAGE_TYPE is (IDLE, UNKNOWN_OPERATION, ADD_SAMPLE_INFO, ADD_PAYLOAD_ADDRESS, ADD_PAYLOAD, NEXT_PAYLOAD_SLOT, ALIGN_PAYLOAD, GET_KEY_HASH, INITIATE_INSTANCE_SEARCH, FILTER_STAGE, UPDATE_INSTANCE, FINALIZE_PAYLOAD, PRE_SAMPLE_FINALIZE, FIND_POS, FIX_POINTERS, FINALIZE_SAMPLE, GET_OLDEST_SAMPLE_INSTANCE, FIND_OLDEST_INST_SAMPLE, REMOVE_SAMPLE, POST_SAMPLE_REMOVE, SKIP_ADD_REJECT, SKIP_ADD_DROP, REMOVE_WRITER, REMOVE_STALE_INSTANCE, GET_NEXT_SAMPLE, PRE_CALCULATE, FINALIZE_SAMPLE_INFO, GET_PAYLOAD, FIND_NEXT_INSTANCE, CHECK_INSTANCE, CHECK_LIFESPAN, GET_SAMPLE_REJECTED_STATUS, GET_REQUESTED_DEADLINE_MISSED_STATUS, CHECK_DEADLINE); @@ -411,13 +411,13 @@ architecture arch of dds_reader is alias cur_payload : unsigned(PAYLOAD_MEMORY_ADDR_WIDTH-1 downto 0) is payload_addr_latch_1; alias cur_payload_next : unsigned(PAYLOAD_MEMORY_ADDR_WIDTH-1 downto 0) is payload_addr_latch_1_next; alias next_payload : unsigned(PAYLOAD_MEMORY_ADDR_WIDTH-1 downto 0) is payload_addr_latch_2; - alias next_payload_next : unsigned(PAYLOAD_MEMORY_ADDR_WIDTH-1 downto 0) is payload_addr_latch_2_next; + alias next_payload_next : unsigned(PAYLOAD_MEMORY_ADDR_WIDTH-1 downto 0) is payload_addr_latch_2_next; alias cur_inst : unsigned(INSTANCE_MEMORY_ADDR_WIDTH-1 downto 0) is inst_addr_latch_1; alias cur_inst_next : unsigned(INSTANCE_MEMORY_ADDR_WIDTH-1 downto 0) is inst_addr_latch_1_next; alias next_inst : unsigned(INSTANCE_MEMORY_ADDR_WIDTH-1 downto 0) is inst_addr_latch_2; alias next_inst_next : unsigned(INSTANCE_MEMORY_ADDR_WIDTH-1 downto 0) is inst_addr_latch_2_next; - alias has_data : std_logic is sample_status_info(PAYLOAD_FLAG); - alias has_key_hash : std_logic is sample_status_info(KEY_HASH_FLAG); + alias has_data : std_logic is sample_status_info(SSI_PAYLOAD_FLAG); + alias has_key_hash : std_logic is sample_status_info(SSI_KEY_HASH_FLAG); -- *FUNCTION DECLARATION* function to_unsigned(input : KEY_HASH_TYPE) return unsigned is @@ -532,7 +532,7 @@ begin -- ADD_PAYLOAD_ADDRESS Store payload pointer. -- ADD_PAYLOAD Push payload to memory and key hash generator (as needed) -- NEXT_PAYLOAD_SLOT Get pointer to next empty payload slot - -- ZERO_PAYLOAD Fill rest of payload slot with zeroes + -- ALIGN_PAYLOAD Store the offset of the actual payload in the last address of the last payload slot. -- GET_KEY_HASH Fetch the calculated key hash from the Key Hash Generator -- INITIATE_INSTANCE_SEARCH Initiate Instance Search Memory Operation. This state is used to start the Search operation as soon as the required data is available -- FILTER_STAGE This state decides if the RTPS Cache Change is accepted, dropped, or rejected. It also decides what sample (if any) has to be removed. @@ -678,9 +678,9 @@ begin stage_next <= CHECK_DEADLINE; cnt_next <= 0; else - if (inst_data.status_info(LIVELINESS_FLAG) = '1') then + if (inst_data.status_info(ISI_LIVELINESS_FLAG) = '1') then -- Reset Liveliness Flag - inst_data_next.status_info(LIVELINESS_FLAG) <= '0'; + inst_data_next.status_info(ISI_LIVELINESS_FLAG) <= '0'; else -- Update Requested Deadline Missed Status status_sig_next(REQUESTED_DEADLINE_MISSED_STATUS) <= '1'; @@ -729,8 +729,8 @@ begin inst_data_next.writer_bitmap <= from_endpoint_bitmap(tmp_bitmap); -- NOT_ALIVE_NO_WRITERS Transition - if (tmp_bitmap = (tmp_bitmap'range => '0') and inst_data.status_info(NOT_ALIVE_DISPOSED_FLAG) = '0') then - inst_data_next.status_info(NOT_ALIVE_NO_WRITERS_FLAG) <= '1'; + if (tmp_bitmap = (tmp_bitmap'range => '0') and inst_data.status_info(ISI_NOT_ALIVE_DISPOSED_FLAG) = '0') then + inst_data_next.status_info(ISI_NOT_ALIVE_NO_WRITERS_FLAG) <= '1'; end if; end if; when others => @@ -892,14 +892,16 @@ begin case (cnt) is -- Status Info when 0 => + -- NOTE: The PAYLOAD_FLAG, ALIGNED_FLAG, and KEY_HASH_FLAG are set by the RTPS Reader + -- NOTE: The ALIGNED_FLAG is set by default. if actual Payload is not aligned, need to reset. sample_valid_in <= '1'; sample_addr <= cur_sample + SMF_STATUS_INFO_OFFSET; sample_write_data <= data_in_rtps; -- Initialize local status bits - sample_write_data(READ_FLAG) <= '0'; + sample_write_data(SSI_READ_FLAG) <= '0'; -- Latch Status Info - sample_status_info_next <= data_in_rtps; - sample_status_info_next(READ_FLAG) <= '0'; + sample_status_info_next <= data_in_rtps; + sample_status_info_next(SSI_READ_FLAG) <= '0'; -- Memory Flow Control Guard if (sample_ready_in = '1') then ready_in_rtps <= '1'; @@ -1050,20 +1052,18 @@ begin payload_write_data <= data_in_rtps; -- Memory Control Flow Guard if (payload_ready_in = '1') then - cnt2_next <= cnt2 + 1; - -- Key Hash needs to be calculated if (WITH_KEY and has_key_hash = '0') then - cnt_next <= 1; + cnt_next <= cnt + 1; else ready_in_rtps <= '1'; -- End of Payload if (last_word_in_rtps = '1') then -- End of Payload Slot if (cnt2 = PAYLOAD_FRAME_SIZE-1) then - stage_next <= FILTER_STAGE; + stage_next <= FILTER_STAGE; else - stage_next <= ZERO_PAYLOAD; + stage_next <= ALIGN_PAYLOAD; end if; else -- End of Payload Slot @@ -1072,7 +1072,7 @@ begin cnt_next <= 0; else -- Next Word - cnt_next <= 0; + cnt2_next <= cnt2 + 1; end if; end if; end if; @@ -1099,7 +1099,7 @@ begin stage_next <= GET_KEY_HASH; cnt_next <= 0; else - stage_next <= ZERO_PAYLOAD; + stage_next <= ALIGN_PAYLOAD; end if; else -- End of Payload Slot @@ -1109,6 +1109,7 @@ begin else -- Next Word cnt_next <= 0; + cnt2_next <= cnt2 + 1; end if; end if; else @@ -1119,7 +1120,7 @@ begin cnt_next <= 0; else -- Next Word - cnt_next <= 1; + cnt_next <= 1; -- Same Sub-state end if; end if; end if; @@ -1164,24 +1165,37 @@ begin when others => null; end case; - when ZERO_PAYLOAD => - -- Zero Payload - payload_valid_in <= '1'; - payload_addr <= cur_payload + cnt2; - payload_write_data <= (others => '0'); - - -- Memory Control Flow Guard - if (payload_ready_in = '1') then - -- Exit Condition - if (cnt2 = PAYLOAD_FRAME_SIZE-1) then - if (WITH_KEY and has_key_hash = '0') then - stage_next <= GET_KEY_HASH; - cnt_next <= 0; - else - stage_next <= FILTER_STAGE; + when ALIGN_PAYLOAD => + case (cnt) is + -- Mark Payload as unaligned + when 0 => + sample_valid_in <= '1'; + sample_addr <= cur_sample + SMF_STATUS_INFO_OFFSET; + sample_write_data <= sample_status_info; + sample_write_data(SSI_ALIGNED_FLAG) <= '0'; + + -- Memory Control Flow Guard + if (sample_ready_in = '1') then + cnt_next <= cnt + 1; end if; - end if; - end if; + -- Store Payload End Offset + when 1 => + payload_valid_in <= '1'; + payload_addr <= cur_payload + PAYLOAD_FRAME_SIZE-1; + payload_write_data <= to_unsigned(cnt2, WORD_WIDTH); + + -- Memory Control Flow Guard + if (payload_ready_in = '1') then + if (WITH_KEY and has_key_hash = '0') then + stage_next <= GET_KEY_HASH; + cnt_next <= 0; + else + stage_next <= FILTER_STAGE; + end if; + end if; + when others => + null; + end case; when GET_KEY_HASH => -- Synthesis Guard if (WITH_KEY) then @@ -1316,7 +1330,7 @@ begin res_rtps <= ACCEPTED; -- Only Insert Sample/Instance if Instance is ALIVE - if (sample_status_info(DISPOSED_FLAG) /= '1' and sample_status_info(UNREGISTERED_FLAG) /= '1' and sample_status_info(FILTERED_FLAG) /= '1') then + if (sample_status_info(SSI_DISPOSED_FLAG) /= '1' and sample_status_info(SSI_UNREGISTERED_FLAG) /= '1' and sample_status_info(SSI_FILTERED_FLAG) /= '1') then -- Insert New Instance inst_op_start <= '1'; inst_opcode <= INSERT_INSTANCE; @@ -1340,7 +1354,7 @@ begin res_rtps <= ACCEPTED; -- Only Insert Sample/Instance if Instance is ALIVE - if (sample_status_info(DISPOSED_FLAG) /= '1' and sample_status_info(UNREGISTERED_FLAG) /= '1' and sample_status_info(FILTERED_FLAG) /= '1') then + if (sample_status_info(SSI_DISPOSED_FLAG) /= '1' and sample_status_info(SSI_UNREGISTERED_FLAG) /= '1' and sample_status_info(SSI_FILTERED_FLAG) /= '1') then -- Insert New Instance inst_op_start <= '1'; inst_opcode <= INSERT_INSTANCE; @@ -1367,23 +1381,23 @@ begin tmp_update := (others => '0'); -- Instance DISPOSED - if (sample_status_info(DISPOSED_FLAG) = '1') then + if (sample_status_info(SSI_DISPOSED_FLAG) = '1') then -- ALIVE -> NOT_ALIVE_DISPOSED Transition - if (inst_data.status_info(NOT_ALIVE_DISPOSED_FLAG) /= '1' and inst_data.status_info(NOT_ALIVE_NO_WRITERS_FLAG) /= '1') then + if (inst_data.status_info(ISI_NOT_ALIVE_DISPOSED_FLAG) /= '1' and inst_data.status_info(ISI_NOT_ALIVE_NO_WRITERS_FLAG) /= '1') then -- STATUS INFO -- Synthesis Guard if (WITH_KEY) then tmp_update <= tmp_update or IMF_STATUS_FLAG; status_info_update <= inst_data.status_info; - status_info_update(NOT_ALIVE_DISPOSED_FLAG) <= '1'; - status_info_update(LIVELINESS_FLAG) <= '1'; + status_info_update(ISI_NOT_ALIVE_DISPOSED_FLAG) <= '1'; + status_info_update(ISI_LIVELINESS_FLAG) <= '1'; else - inst_data_next.status_info(NOT_ALIVE_DISPOSED_FLAG) <= '1'; - inst_data_next.status_info(LIVELINESS_FLAG) <= '1'; + inst_data_next.status_info(ISI_NOT_ALIVE_DISPOSED_FLAG) <= '1'; + inst_data_next.status_info(ISI_LIVELINESS_FLAG) <= '1'; end if; end if; -- Instance UNREGISTERED - elsif (sample_status_info(UNREGISTERED_FLAG) = '1') then + elsif (sample_status_info(SSI_UNREGISTERED_FLAG) = '1') then -- WRITER BITMAP -- Convert Writer Bitmap to SLV tmp_bitmap := to_endpoint_bitmap(inst_data.writer_bitmap); @@ -1400,17 +1414,17 @@ begin end if; -- ALIVE -> NOT_ALIVE_NO_WRITERS Transition - if (inst_data.status_info(NOT_ALIVE_DISPOSED_FLAG) /= '1' and inst_data.status_info(NOT_ALIVE_NO_WRITERS_FLAG) /= '1' and tmp_bitmap = (tmp_bitmap => '0')) then + if (inst_data.status_info(ISI_NOT_ALIVE_DISPOSED_FLAG) /= '1' and inst_data.status_info(ISI_NOT_ALIVE_NO_WRITERS_FLAG) /= '1' and tmp_bitmap = (tmp_bitmap => '0')) then -- STATUS INFO -- Synthesis Guard if (WITH_KEY) then tmp_update <= tmp_update or IMF_STATUS_FLAG; status_info_update <= inst_data.status_info; - status_info_update(NOT_ALIVE_NO_WRITERS_FLAG) <= '1'; - status_info_update(LIVELINESS_FLAG) <= '1'; + status_info_update(ISI_NOT_ALIVE_NO_WRITERS_FLAG) <= '1'; + status_info_update(ISI_LIVELINESS_FLAG) <= '1'; else - inst_data_next.status_info(NOT_ALIVE_NO_WRITERS_FLAG) <= '1'; - inst_data_next.status_info(LIVELINESS_FLAG) <= '1'; + inst_data_next.status_info(ISI_NOT_ALIVE_NO_WRITERS_FLAG) <= '1'; + inst_data_next.status_info(ISI_LIVELINESS_FLAG) <= '1'; end if; end if; -- Instance ALIVE/FILTERED @@ -1420,19 +1434,19 @@ begin if (WITH_KEY) then tmp_update <= tmp_update or IMF_STATUS_FLAG; status_info_update <= inst_data.status_info; - status_info_update(NOT_ALIVE_DISPOSED_FLAG) <= '0'; - status_info_update(NOT_ALIVE_NO_WRITERS_FLAG) <= '0'; - status_info_update(LIVELINESS_FLAG) <= '1'; + status_info_update(ISI_NOT_ALIVE_DISPOSED_FLAG) <= '0'; + status_info_update(ISI_NOT_ALIVE_NO_WRITERS_FLAG) <= '0'; + status_info_update(ISI_LIVELINESS_FLAG) <= '1'; else - inst_data_next.status_info(NOT_ALIVE_DISPOSED_FLAG) <= '0'; - inst_data_next.status_info(NOT_ALIVE_NO_WRITERS_FLAG) <= '0'; - inst_data_next.status_info(LIVELINESS_FLAG) <= '1'; + inst_data_next.status_info(ISI_NOT_ALIVE_DISPOSED_FLAG) <= '0'; + inst_data_next.status_info(ISI_NOT_ALIVE_NO_WRITERS_FLAG) <= '0'; + inst_data_next.status_info(ISI_LIVELINESS_FLAG) <= '1'; end if; -- GENERATION COUNTERS -- NOT_ALIVE_DISPOSED -> ALIVE Transition - if (inst_data.status_info(NOT_ALIVE_DISPOSED_FLAG) = '1') then + if (inst_data.status_info(ISI_NOT_ALIVE_DISPOSED_FLAG) = '1') then -- Synthesis Guard if (WITH_KEY) then tmp_update := tmp_update or IMF_DISPOSED_CNT_FLAG; @@ -1441,7 +1455,7 @@ begin inst_data_next.disposed_gen_cnt <= inst_data.disposed_gen_cnt + 1; end if; -- NOT_ALIVE_NO_WRITERS -> ALIVE Transition - elsif (inst_data.status_info(NOT_ALIVE_NO_WRITERS_FLAG) = '1') then + elsif (inst_data.status_info(ISI_NOT_ALIVE_NO_WRITERS_FLAG) = '1') then -- Synthesis Guard if (WITH_KEY) then tmp_update := tmp_update or IMF_NO_WRITERS_CNT_FLAG; @@ -2218,9 +2232,9 @@ begin writer_bitmap <= from_endpoint_bitmap(tmp_bitmap); -- NOT_ALIVE_NO_WRITERS Transition - if (tmp_bitmap = (tmp_bitmap'range => '0') and inst_data.status_info(NOT_ALIVE_DISPOSED_FLAG) = '0') then + if (tmp_bitmap = (tmp_bitmap'range => '0') and inst_data.status_info(ISI_NOT_ALIVE_DISPOSED_FLAG) = '0') then status_info_update <= inst_data.status_info; - status_info_update(NOT_ALIVE_NO_WRITERS_FLAG) <= '1'; + status_info_update(ISI_NOT_ALIVE_NO_WRITERS_FLAG) <= '1'; inst_op_start <= '1'; inst_opcode <= UPDATE_INSTANCE; inst_mem_fields <= IMF_STATUS_FLAG or IMF_WRITER_BITMAP_FLAG; @@ -2347,13 +2361,13 @@ begin -- Check Sample State case (sample_state) is when READ_SAMPLE_STATE => - if (sample_read_data(READ_FLAG) /= '1') then + if (sample_read_data(SSI_READ_FLAG) /= '1') then -- Sample not in collection, Skip Sample cnt_next <= 17; sample_abort_read <= '1'; end if; when NOT_READ_SAMPLE_STATE => - if (sample_read_data(READ_FLAG) /= '0') then + if (sample_read_data(SSI_READ_FLAG) /= '0') then -- Sample not in collection, Skip Sample cnt_next <= 17; sample_abort_read <= '1'; @@ -2367,7 +2381,7 @@ begin sample_abort_read <= '1'; end case; - if (sample_read_data(READ_FLAG) = '1') then + if (sample_read_data(SSI_READ_FLAG) = '1') then si_sample_state_sig_next <= READ_SAMPLE_STATE; else si_sample_state_sig_next <= NOT_READ_SAMPLE_STATE; @@ -2447,19 +2461,19 @@ begin -- Check Instance State case (instance_state) is when ALIVE_INSTANCE_STATE => - if (inst_data.status_info(NOT_ALIVE_DISPOSED_FLAG) = '1' or inst_data.status_info(NOT_ALIVE_NO_WRITERS_FLAG) = '1') then + if (inst_data.status_info(ISI_NOT_ALIVE_DISPOSED_FLAG) = '1' or inst_data.status_info(ISI_NOT_ALIVE_NO_WRITERS_FLAG) = '1') then tmp_bool := FALSE; end if; when NOT_ALIVE_DISPOSED_INSTANCE_STATE => - if (inst_data.status_info(NOT_ALIVE_DISPOSED_FLAG) = '0') then + if (inst_data.status_info(ISI_NOT_ALIVE_DISPOSED_FLAG) = '0') then tmp_bool := FALSE; end if; when NOT_ALIVE_NO_WRITERS_INSTANCE_STATE => - if (inst_data.status_info(NOT_ALIVE_NO_WRITERS_FLAG) = '0') then + if (inst_data.status_info(ISI_NOT_ALIVE_NO_WRITERS_FLAG) = '0') then tmp_bool := FALSE; end if; when NOT_ALIVE_INSTANCE_STATE => - if (inst_data.status_info(NOT_ALIVE_DISPOSED_FLAG) = '0' and inst_data.status_info(NOT_ALIVE_NO_WRITERS_FLAG) = '0') then + if (inst_data.status_info(ISI_NOT_ALIVE_DISPOSED_FLAG) = '0' and inst_data.status_info(ISI_NOT_ALIVE_NO_WRITERS_FLAG) = '0') then tmp_bool := FALSE; end if; when ANY_INSTANCE_STATE => @@ -2471,11 +2485,11 @@ begin -- Check View State case (view_state) is when NEW_VIEW_STATE => - if (inst_data.status_info(VIEW_FLAG) = '0') then + if (inst_data.status_info(ISI_VIEW_FLAG) = '0') then tmp_bool := FALSE; end if; when NOT_NEW_VIEW_STATE => - if (inst_data.status_info(VIEW_FLAG) = '1') then + if (inst_data.status_info(ISI_VIEW_FLAG) = '1') then tmp_bool := FALSE; end if; when ANY_VIEW_STATE => @@ -2485,7 +2499,7 @@ begin end case; -- Check Instance Mark - if (inst_data.status_info(MARK_FLAG) = '1') then + if (inst_data.status_info(ISI_MARK_FLAG) = '1') then -- Skip Marked Instance tmp_bool := FALSE; end if; @@ -2613,12 +2627,12 @@ begin -- Exit Condition (Sample Selected) if (first_sample = cur_sample) then -- Sample not marked as Read - if (sample_status_info(READ_FLAG) /= '1') then + if (sample_status_info(SSI_READ_FLAG) /= '1') then -- Mark Sample as Read sample_valid_in <= '1'; sample_addr <= cur_sample + SMF_STATUS_INFO_OFFSET; sample_write_data <= sample_status_info; - sample_write_data(READ_FLAG) <= '1'; + sample_write_data(SSI_READ_FLAG) <= '1'; -- Memory Control Flow Guard if (sample_ready_in = '1') then stage_next <= FINALIZE_SAMPLE_INFO; @@ -2655,12 +2669,12 @@ begin -- Exit Condition (Sample Selected) if (first_sample = cur_sample) then -- Sample not marked as Read - if (sample_status_info(READ_FLAG) /= '1') then + if (sample_status_info(SSI_READ_FLAG) /= '1') then -- Mark Sample as Read sample_valid_in <= '1'; sample_addr <= cur_sample + SMF_STATUS_INFO_OFFSET; sample_write_data <= sample_status_info; - sample_write_data(READ_FLAG) <= '1'; + sample_write_data(SSI_READ_FLAG) <= '1'; -- Memory Control Flow Guard if (sample_ready_in = '1') then -- Pre-Calculation already done for selected Instance (Or not necessary) @@ -2764,13 +2778,13 @@ begin -- Check Sample State case (sample_state) is when READ_SAMPLE_STATE => - if (sample_read_data(READ_FLAG) /= '1') then + if (sample_read_data(SSI_READ_FLAG) /= '1') then -- Skip Sample cnt_next <= 12; sample_abort_read <= '1'; end if; when NOT_READ_SAMPLE_STATE => - if (sample_read_data(READ_FLAG) /= '0') then + if (sample_read_data(SSI_READ_FLAG) /= '0') then -- Skip Sample cnt_next <= 12; sample_abort_read <= '1'; @@ -2856,19 +2870,19 @@ begin -- Check Instance State case (instance_state) is when ALIVE_INSTANCE_STATE => - if (inst_data.status_info(NOT_ALIVE_DISPOSED_FLAG) = '1' or inst_data.status_info(NOT_ALIVE_NO_WRITERS_FLAG) = '1') then + if (inst_data.status_info(ISI_NOT_ALIVE_DISPOSED_FLAG) = '1' or inst_data.status_info(ISI_NOT_ALIVE_NO_WRITERS_FLAG) = '1') then tmp_bool := FALSE; end if; when NOT_ALIVE_DISPOSED_INSTANCE_STATE => - if (inst_data.status_info(NOT_ALIVE_DISPOSED_FLAG) = '0') then + if (inst_data.status_info(ISI_NOT_ALIVE_DISPOSED_FLAG) = '0') then tmp_bool := FALSE; end if; when NOT_ALIVE_NO_WRITERS_INSTANCE_STATE => - if (inst_data.status_info(NOT_ALIVE_NO_WRITERS_FLAG) = '0') then + if (inst_data.status_info(ISI_NOT_ALIVE_NO_WRITERS_FLAG) = '0') then tmp_bool := FALSE; end if; when NOT_ALIVE_INSTANCE_STATE => - if (inst_data.status_info(NOT_ALIVE_DISPOSED_FLAG) = '0' and inst_data.status_info(NOT_ALIVE_NO_WRITERS_FLAG) = '0') then + if (inst_data.status_info(ISI_NOT_ALIVE_DISPOSED_FLAG) = '0' and inst_data.status_info(ISI_NOT_ALIVE_NO_WRITERS_FLAG) = '0') then tmp_bool := FALSE; end if; when ANY_INSTANCE_STATE => @@ -2880,11 +2894,11 @@ begin -- Check View State case (view_state) is when NEW_VIEW_STATE => - if (inst_data.status_info(VIEW_FLAG) = '0') then + if (inst_data.status_info(ISI_VIEW_FLAG) = '0') then tmp_bool := FALSE; end if; when NOT_NEW_VIEW_STATE => - if (inst_data.status_info(VIEW_FLAG) = '1') then + if (inst_data.status_info(ISI_VIEW_FLAG) = '1') then tmp_bool := FALSE; end if; when ANY_VIEW_STATE => @@ -2894,7 +2908,7 @@ begin end case; -- Check Instance Mark - if (inst_data.status_info(MARK_FLAG) = '1') then + if (inst_data.status_info(ISI_MARK_FLAG) = '1') then -- Skip Marked Instance tmp_bool := FALSE; end if; @@ -2934,16 +2948,16 @@ begin -- Instance Data valid if (not WITH_KEY or inst_addr_base = cur_inst) then -- Sample Info View State - if (inst_data.status_info(VIEW_FLAG) = '1') then + if (inst_data.status_info(ISI_VIEW_FLAG) = '1') then si_view_state_sig_next <= NEW_VIEW_STATE; else si_view_state_sig_next <= NOT_NEW_VIEW_STATE; end if; -- Sample Info Instance State - if (inst_data.status_info(NOT_ALIVE_DISPOSED_FLAG) = '1') then + if (inst_data.status_info(ISI_NOT_ALIVE_DISPOSED_FLAG) = '1') then si_instance_state_sig_next <= NOT_ALIVE_DISPOSED_INSTANCE_STATE; - elsif (inst_data.status_info(NOT_ALIVE_NO_WRITERS_FLAG) = '1') then + elsif (inst_data.status_info(ISI_NOT_ALIVE_NO_WRITERS_FLAG) = '1') then si_instance_state_sig_next <= NOT_ALIVE_NO_WRITERS_INSTANCE_STATE; else si_instance_state_sig_next <= ALIVE_INSTANCE_STATE; @@ -3023,20 +3037,20 @@ begin unmark_instances_next <= '1'; else -- Mark Instance - status_info_update(MARK_FLAG) <= '1'; + status_info_update(ISI_MARK_FLAG) <= '1'; end if; end if; -- Instance is NOT_VIEWED and sample is from last generation of Instance - if (inst_data.status_info(VIEW_FLAG) = '0' and si_absolute_generation_count_sig = 0) then + if (inst_data.status_info(ISI_VIEW_FLAG) = '0' and si_absolute_generation_count_sig = 0) then -- Mark Instance as VIEWED - status_info_update(VIEW_FLAG) <= '1'; + status_info_update(ISI_VIEW_FLAG) <= '1'; end if; else -- Instance is NOT_VIEWED and sample is from last generation of Instance - if (inst_data.status_info(VIEW_FLAG) = '0' and si_absolute_generation_count_sig = 0) then + if (inst_data.status_info(ISI_VIEW_FLAG) = '0' and si_absolute_generation_count_sig = 0) then -- Mark Instance as VIEWED - inst_data_next.status_info(VIEW_FLAG) <= '1'; + inst_data_next.status_info(ISI_VIEW_FLAG) <= '1'; end if; end if; end if; @@ -3092,7 +3106,7 @@ begin null; end case; when GET_PAYLOAD => - -- Precondition: cur_payload set + -- Precondition: cur_payload set, sample_status_info set -- DEFAULT tmp_bool := FALSE; @@ -3115,11 +3129,37 @@ begin -- Memory Flow Control Guard if (payload_valid_out = '1') then next_payload_next <= payload_read_data; - cnt_next <= cnt + 1; cnt2 <= 1; + + -- Last Payload Slot is unaligned + if (payload_read_data = PAYLOAD_MEMORY_MAX_ADDRESS and sample_status_info(SSI_ALIGNED_FLAG) = '0') then + cnt_next <= cnt + 1 + else + cnt_next <= cnt + 3; + long_latch_next <= PAYLOAD_FRAME_SIZE-1; + end if; + end if; + -- GET Payload Offset + when 2 => + payload_valid_in <= '1'; + payload_addr <= cur_payload + PAYLOAD_FRAME_SIZE-1; + payload_read <= '1'; + + -- Memory Flow Control Guard + if (payload_ready_in = '1') then + cnt_next <= cnt + 1; + end if; + -- READ Payload Offset + when 3 => + payload_ready_out <= '1'; + + -- Memory Flow Control Guard + if (payload_valid_out = '1') then + long_latch_next <= payload_read_data; + cnt_next <= cnt + 1; end if; -- GET PAYLOAD - when 3 => + when 4 => payload_valid_in <= '1'; payload_addr <= cur_payload + cnt2; payload_read <= '1'; @@ -3129,7 +3169,7 @@ begin cnt3_next <= cnt3 + 1; tmp_bool := TRUE; -- End of Payload Slot - if (cnt2 = PAYLOAD_FRAME_SIZE-1) then + if (cnt2 = unsigned(long_latch)) then -- End of Payload if (next_payload = PAYLOAD_MEMORY_MAX_ADDRESS) then -- DONE (Wait for Output to finidh reading) @@ -3211,19 +3251,19 @@ begin -- Check Instance State case (instance_state) is when ALIVE_INSTANCE_STATE => - if (inst_data.status_info(NOT_ALIVE_DISPOSED_FLAG) = '1' or inst_data.status_info(NOT_ALIVE_NO_WRITERS_FLAG) = '1') then + if (inst_data.status_info(ISI_NOT_ALIVE_DISPOSED_FLAG) = '1' or inst_data.status_info(ISI_NOT_ALIVE_NO_WRITERS_FLAG) = '1') then tmp_bool := FALSE; end if; when NOT_ALIVE_DISPOSED_INSTANCE_STATE => - if (inst_data.status_info(NOT_ALIVE_DISPOSED_FLAG) = '0') then + if (inst_data.status_info(ISI_NOT_ALIVE_DISPOSED_FLAG) = '0') then tmp_bool := FALSE; end if; when NOT_ALIVE_NO_WRITERS_INSTANCE_STATE => - if (inst_data.status_info(NOT_ALIVE_NO_WRITERS_FLAG) = '0') then + if (inst_data.status_info(ISI_NOT_ALIVE_NO_WRITERS_FLAG) = '0') then tmp_bool := FALSE; end if; when NOT_ALIVE_INSTANCE_STATE => - if (inst_data.status_info(NOT_ALIVE_DISPOSED_FLAG) = '0' and inst_data.status_info(NOT_ALIVE_NO_WRITERS_FLAG) = '0') then + if (inst_data.status_info(ISI_NOT_ALIVE_DISPOSED_FLAG) = '0' and inst_data.status_info(ISI_NOT_ALIVE_NO_WRITERS_FLAG) = '0') then tmp_bool := FALSE; end if; when ANY_INSTANCE_STATE => @@ -3235,11 +3275,11 @@ begin -- Check View State case (view_state) is when NEW_VIEW_STATE => - if (inst_data.status_info(VIEW_FLAG) = '0') then + if (inst_data.status_info(ISI_VIEW_FLAG) = '0') then tmp_bool := FALSE; end if; when NOT_NEW_VIEW_STATE => - if (inst_data.status_info(VIEW_FLAG) = '1') then + if (inst_data.status_info(ISI_VIEW_FLAG) = '1') then tmp_bool := FALSE; end if; when ANY_VIEW_STATE => @@ -3290,19 +3330,19 @@ begin -- Check Instance State case (instance_state) is when ALIVE_INSTANCE_STATE => - if (inst_data.status_info(NOT_ALIVE_DISPOSED_FLAG) = '1' or inst_data.status_info(NOT_ALIVE_NO_WRITERS_FLAG) = '1') then + if (inst_data.status_info(ISI_NOT_ALIVE_DISPOSED_FLAG) = '1' or inst_data.status_info(ISI_NOT_ALIVE_NO_WRITERS_FLAG) = '1') then tmp_bool := FALSE; end if; when NOT_ALIVE_DISPOSED_INSTANCE_STATE => - if (inst_data.status_info(NOT_ALIVE_DISPOSED_FLAG) = '0') then + if (inst_data.status_info(ISI_NOT_ALIVE_DISPOSED_FLAG) = '0') then tmp_bool := FALSE; end if; when NOT_ALIVE_NO_WRITERS_INSTANCE_STATE => - if (inst_data.status_info(NOT_ALIVE_NO_WRITERS_FLAG) = '0') then + if (inst_data.status_info(ISI_NOT_ALIVE_NO_WRITERS_FLAG) = '0') then tmp_bool := FALSE; end if; when NOT_ALIVE_INSTANCE_STATE => - if (inst_data.status_info(NOT_ALIVE_DISPOSED_FLAG) = '0' and inst_data.status_info(NOT_ALIVE_NO_WRITERS_FLAG) = '0') then + if (inst_data.status_info(ISI_NOT_ALIVE_DISPOSED_FLAG) = '0' and inst_data.status_info(ISI_NOT_ALIVE_NO_WRITERS_FLAG) = '0') then tmp_bool := FALSE; end if; when ANY_INSTANCE_STATE => @@ -3314,11 +3354,11 @@ begin -- Check View State case (view_state) is when NEW_VIEW_STATE => - if (inst_data.status_info(VIEW_FLAG) = '0') then + if (inst_data.status_info(ISI_VIEW_FLAG) = '0') then tmp_bool := FALSE; end if; when NOT_NEW_VIEW_STATE => - if (inst_data.status_info(VIEW_FLAG) = '1') then + if (inst_data.status_info(ISI_VIEW_FLAG) = '1') then tmp_bool := FALSE; end if; when ANY_VIEW_STATE => @@ -3547,13 +3587,13 @@ begin stage_next <= IDLE; else -- Instance received Sample - if (inst_data.status_info(LIVELINESS_FLAG) = '1') then + if (inst_data.status_info(ISI_LIVELINESS_FLAG) = '1') then -- Reset Liveliness Flag inst_op_start <= '1'; inst_opcode <= UPDATE_INSTANCE; inst_mem_fields <= IMF_STATUS_FLAG; status_info_update <= inst_data.status_info; - status_info_update(LIVELINESS_FLAG) <= '0'; + status_info_update(ISI_LIVELINESS_FLAG) <= '0'; cnt_next <= 1; else -- Update Requested Deadline Missed Status @@ -3569,6 +3609,77 @@ begin end case; end if; end if; + when RESET_SAMPLE_MEMORY => + case (cnt) is + -- Initialize + when 0 => + prev_sample_next <= SAMPLE_MEMORY_MAX_ADDRESS; + cur_sample_next <= (others => '0'); + cnt_next <= cnt + 1; + -- Set Previous Pointer + when 1 => + sample_valid_in <= '1'; + sample_addr <= cur_sample + SMF_PREV_ADDR_OFFSET; + sample_write_data <= prev_sample; + + -- Memory Flow Control Guard + if (sample_ready_in = '1') then + cnt_next <= cnt + 1; + end if; + -- Set Next Pointer + when 2 => + sample_valid_in <= '1'; + sample_addr <= cur_sample + SMF_NEXT_ADDR_OFFSET; + if (cur_sample = MAX_SAMPLE_ADDRESS) then + sample_write_data <= SAMPLE_MEMORY_MAX_ADDRESS; + else + sample_write_data <= cur_sample + SAMPLE_FRAME_SIZE; + end if; + + -- Memory Flow Control Guard + if (sample_ready_in = '1') then + if (cur_sample = MAX_SAMPLE_ADDRESS) then + -- DONE + stage_next <= RESET_PAYLOAD_MEMORY; + cnt_next <= 0; + else + -- Continue + cur_sample_next <= cur_sample + SAMPLE_FRAME_SIZE; + prev_sample_next <= cur_sample; + cnt_next <= 1; + end if; + end if; + when others => + null; + end case; + when RESET_PAYLOAD_MEMORY => + case (inst_cnt) is + -- Initialize + when 0 => + cur_payload_next <= (others => '0'); + cnt_next <= cnt + 1; + -- Set Next Pointer + when 1 => + payload_valid_in <= '1'; + payload_addr <= cur_payload + PMF_NEXT_ADDR_OFFSET; + if (cur_payload = MAX_PAYLOAD_ADDRESS) then + payload_write_data <= PAYLOAD_MEMORY_MAX_ADDRESS; + else + payload_write_data <= cur_payload + PAYLOAD_FRAME_SIZE; + end if; + + -- Memory Flow Control Guard + if (payload_ready_in = '1') then + if (cur_payload = MAX_PAYLOAD_ADDRESS) then + -- DONE + stage_next <= IDLE; + else + cur_payload_next <= cur_payload + PAYLOAD_FRAME_SIZE; + end if; + end if; + when others => + null; + end case; when others => null; end case; @@ -5059,10 +5170,10 @@ begin -- Memory Flow Control Guard if (inst_valid_out = '1') then -- MARK Flag Set - if (inst_read_data(MARK_FLAG) = '1') then + if (inst_read_data(ISI_MARK_FLAG) = '1') then -- Latch Status Info (With MARK removed) inst_long_latch_next <= inst_read_data; - inst_long_latch_next(MARK_FLAG) <= '0'; + inst_long_latch_next(ISI_MARK_FLAG) <= '0'; inst_cnt_next <= inst_cnt + 1; else -- End of Instances @@ -5097,6 +5208,34 @@ begin when others => null; end case; + when RESET_MEMORY => + case (inst_cnt) is + -- Initialize + when 0 => + inst_addr_base_next <= FIRST_INSTANCE_ADDRESS; + inst_cnt_next <= inst_cnt + 1; + -- Set Next Pointer + when 1 => + inst_valid_in <= '1'; + inst_addr <= inst_addr_base + IMF_NEXT_ADDR_OFFSET; + if (inst_addr_base = MAX_INSTANCE_ADDRESS) then + inst_write_data <= INSTANCE_MEMORY_MAX_ADDRESS; + else + inst_write_data <= inst_addr_base + INSTANCE_FRAME_SIZE; + end if; + + -- Memory Flow Control Guard + if (inst_ready_in = '1') then + if (inst_addr_base = MAX_INSTANCE_ADDRESS) then + -- DONE + inst_stage_next <= IDLE; + else + inst_addr_base_next <= inst_addr_base + INSTANCE_FRAME_SIZE; + end if; + end if; + when others => + null; + end case; when others => null; end case; diff --git a/src/rtps_config_package.vhd b/src/rtps_config_package.vhd index 920e8af..7d3399d 100644 --- a/src/rtps_config_package.vhd +++ b/src/rtps_config_package.vhd @@ -53,22 +53,23 @@ package rtps_config_package is type KEY_GENERATOR_OPCODE_TYPE is (NOP, WRITE_PAYLOAD, READ_KEY, READ_SIZE); type HISTORY_CACHE_RESPONSE_TYPE is (UNDEFINED, ACK, ACCEPTED, REJECTED, INVALID); - -- TODO: Prefix the Flags with something that differntiates between them -- Sample Status Info Flags - constant DISPOSED_FLAG : natural := STATUS_INFO_DISPOSED_FLAG; - constant UNREGISTERED_FLAG : natural := STATUS_INFO_UNREGISTERED_FLAG; - constant FILTERED_FLAG : natural := STATUS_INFO_FILTERED_FLAG; - constant KEY_HASH_FLAG : natural := 29; - constant PAYLOAD_FLAG : natural := 30; - constant READ_FLAG : natural := 31; + constant SSI_DISPOSED_FLAG : natural := STATUS_INFO_DISPOSED_FLAG; + constant SSI_UNREGISTERED_FLAG : natural := STATUS_INFO_UNREGISTERED_FLAG; + constant SSI_FILTERED_FLAG : natural := STATUS_INFO_FILTERED_FLAG; + constant SSI_KEY_HASH_FLAG : natural := 28; + constant SSI_ALIGNED_FLAG : natural := 29; + constant SSI_PAYLOAD_FLAG : natural := 30; + constant SSI_READ_FLAG : natural := 31; -- Instance Status Info Flags - constant NOT_ALIVE_DISPOSED_FLAG : natural := 0; - constant NOT_ALIVE_NO_WRITERS_FLAG : natural := 1; - constant LIVELINESS_FLAG : natural := 2; - constant VIEW_FLAG : natural := 3; - constant MARK_FLAG : natural := 4; + constant ISI_NOT_ALIVE_DISPOSED_FLAG : natural := 0; + constant ISI_NOT_ALIVE_NO_WRITERS_FLAG : natural := 1; + constant ISI_LIVELINESS_FLAG : natural := 2; + constant ISI_VIEW_FLAG : natural := 3; + constant ISI_MARK_FLAG : natural := 4; + -- TODO: Prefix the Flags with something that differntiates between them -- Remote Endpoint Flags constant EXPECTS_INLINE_QOS_FLAG : natural := 0; constant SEND_HISTORICAL_DATA_FLAG : natural := 1; diff --git a/src/rtps_reader.vhd b/src/rtps_reader.vhd index 9b8285c..dd49710 100644 --- a/src/rtps_reader.vhd +++ b/src/rtps_reader.vhd @@ -1149,9 +1149,10 @@ begin -- Status Info when 0 => valid_out_dds <= '1'; - data_out_dds <= status_info; - data_out_dds(KEY_HASH_FLAG) <= key_hash_rcvd; - data_out_dds(PAYLOAD_FLAG) <= data_flag; + data_out_dds <= status_info; + data_out_dds(SSI_KEY_HASH_FLAG) <= key_hash_rcvd; + data_out_dds(SSI_PAYLOAD_FLAG) <= data_flag; + data_out_dds(SSI_ALIGNED_FLAG) <= data_flag; -- Output Guard if (ready_out_dds = '1') then cnt_next <= cnt + 1;