diff --git a/src/rtps_reader.vhd b/src/rtps_reader.vhd index fab130d..9b8285c 100644 --- a/src/rtps_reader.vhd +++ b/src/rtps_reader.vhd @@ -6,12 +6,7 @@ use work.rtps_package.all; use work.user_config.all; use work.rtps_config_package.all; --- TODO: Use TIME_INVALID instead of zero. (Backport to builtin_endpoint) [Pay atention to (0) bit of ACKNACK and HEARTBEAT Deadlines, if compatible] --- TODO: Check for special values of time/duration? --- TODO: Remove last_word flag from metattraffic operations --- TODO: Replace all ('range => 0) checks with defined constants, where possible -- TODO: Adding LIFESPAN Duration in the stored Endpoint Metatraffic Data would allow us to not expect in-line QoS (Which could be a significant overhead) --- TODO: Is mem_addr_base needed? Isn't it a direct mirror of addr_mem_base? mem_addr_base is only used in the same clock cycle as mem_op_done is pulled high. entity rtps_reader is @@ -31,12 +26,13 @@ entity rtps_reader is -- FROM RTPS_HANDLER (USER TRAFFIC) empty_user : in std_logic; rd_user : out std_logic; - last_word_in_user : in std_logic; data_in_user : in std_logic_vector(WORD_WIDTH-1 downto 0); + last_word_in_user : in std_logic; -- FROM RTPS_BUILTIN_ENDPOINT (META TRAFFIC) empty_meta : in std_logic; - data_in_meta : in std_logic_vector(WORD_WIDTH-1 downto 0); rd_meta : out std_logic; + data_in_meta : in std_logic_vector(WORD_WIDTH-1 downto 0); + last_word_in_meta : in std_logic; -- RTPS OUTPUT wr_rtps : out std_logic; full_rtps : in std_logic; @@ -95,10 +91,10 @@ architecture arch of rtps_reader is type STAGE_TYPE is (IDLE, LATCH_GUIDPREFIX, LATCH_ENTITYID, INITIATE_ENDPOINT_SEARCH, LATCH_ENDPOINT_DATA, METATRAFFIC_OPERATION, LATCH_SRC_ADDR, LATCH_EXTRA_DATA, LATCH_HEARTBEAT, PROCESS_HEARTBEAT, LATCH_GAP, PROCESS_GAP, FIND_NEXT_VALID_IN_BITMAP, PROCESS_INLINE_QOS, LATCH_LIFESPAN, LATCH_KEY_HASH, LATCH_STATUS_INFO, INITIATE_ADD_CACHE_CHANGE_REQUEST, ADD_CACHE_CHANGE, PUSH_PAYLOAD, FINALIZE_ADD_CACHE_CHANGE_REQUEST, - ENDPOINT_STALE_CHECK, SEND_HEADER, SEND_ACKNACK, SKIP_PARAMETER, SKIP_PACKET); + ENDPOINT_STALE_CHECK, SEND_HEADER, SEND_ACKNACK, SKIP_PARAMETER, SKIP_PACKET, SKIP_META_OPERATION); -- Memory FSM states. Explained below in detail type MEM_STAGE_TYPE is (IDLE, SEARCH_ENDPOINT, GET_ENDPOINT_DATA, INSERT_ENDPOINT, UPDATE_ENDPOINT, REMOVE_ENDPOINT, FIND_EMPTY_SLOT, - RESET_MAX_POINTER, GET_NEXT_ENDPOINT); + RESET_MAX_POINTER, GET_NEXT_ENDPOINT, RESET_MEMORY); -- *Memory FSM Opcodes* -- OPCODE DESCRIPTION -- SEARCH_ENDPOINT Find Endpoint with specified GUID in memory @@ -320,10 +316,10 @@ begin read => mem_read, ready_in => mem_ready_in, valid_in => mem_valid_in, - data_in_user => mem_write_data, + data_in => mem_write_data, ready_out => mem_ready_out, valid_out => mem_valid_out, - data_out_rtps => mem_read_data + data_out => mem_read_data ); -- Big Endian Representation @@ -357,6 +353,7 @@ begin -- SEND_ACKNACK Send ACKNACK Submessage -- SKIP_PARAMETER Skip rest of Parameter -- SKIP_PACKET Skip rest of Packet + -- SKIP_META_OPERATION Skip Metatraffic Operation parse_prc : process(all) variable tmp_dw : DOUBLE_WORD_ARRAY := (others => (others => '0')); -- NOTE: We convert the bitamp to a slv to make operations easier (The tool should handle both cases equally) @@ -364,14 +361,14 @@ begin variable rd_guard : std_logic := '0'; variable tmp_flags : std_logic_vector(0 to EMF_FLAG_WIDTH-1) := (others => '0'); begin - -- DEFAULT Registerd + -- DEFAULT Registered stage_next <= stage; meta_opcode_next <= meta_opcode; cnt_next <= cnt; + cnt2_next <= cnt2; guid_next <= guid; addr_next <= addr; portn_next <= portn; - expects_inline_qos_next <= expects_inline_qos; is_meta_next <= is_meta; opcode_next <= opcode; flags_next <= flags; @@ -399,9 +396,8 @@ begin rd_user <= '0'; mem_op_start <= '0'; start_dds <= '0'; - ready_out_dds <= '0'; valid_out_dds <= '0'; - last_word_out_dds <= '0'; + last_word_out_dds <= '0'; rd_guard := '0'; mem_field_flags <= (others => '0'); data_out_dds <= (others => '0'); @@ -446,8 +442,22 @@ begin -- Latch Endpoint Metatraffic Opcode meta_opcode_next <= data_in_meta; - stage_next <= LATCH_GUIDPREFIX; - cnt_next <= 0; + case (data_in_meta) is + when OPCODE_ENDPOINT_MATCH => + stage_next <= LATCH_GUIDPREFIX; + cnt_next <= 0; + when OPCODE_ENDPOINT_UNMATCH => + stage_next <= LATCH_GUIDPREFIX; + cnt_next <= 0; + when OPCODE_PARTICIPANT_UNMATCH => + stage_next <= LATCH_GUIDPREFIX; + cnt_next <= 0; + when OPCODE_LIVELINESS_UPDATE => + stage_next <= LATCH_GUIDPREFIX; + cnt_next <= 0; + when others => + stage_next <= SKIP_META_OPERATION; + end case; -- Input FIFO Guard elsif (empty_user = '0') then rd_guard := '1'; @@ -499,6 +509,7 @@ begin end if; if (is_meta = '1' and (meta_opcode = OPCODE_PARTICIPANT_UNMATCH or meta_opcode = OPCODE_LIVELINESS_UPDATE)) then + assert (last_word_in_meta = '1') report "last_word_in_meta not set" severity FAILURE; -- DONE Parsing stage_next <= INITIATE_ENDPOINT_SEARCH; else @@ -510,6 +521,7 @@ begin -- Input FIFO Guard if ((is_meta = '1' and empty_meta = '0') or (is_meta = '0' and empty_user = '0')) then if (is_meta = '1') then + assert (meta_opcode /= OPCODE_ENDPOINT_UNMATCH or (meta_opcode = OPCODE_ENDPOINT_UNMATCH and last_word_in_meta = '1')) "last_word_in_meta not set" severity FAILURE; rd_meta <= '1'; guid_next(3) <= data_in_meta; -- Memory Operation Guard @@ -555,7 +567,6 @@ begin stage_next <= METATRAFFIC_OPERATION; cnt_next <= 0; when others => - assert FALSE report "Uknown metatraffic endpoint frame opcode." severity FAILURE; null; end case; else @@ -569,7 +580,7 @@ begin cnt_next <= 0; when SID_HEARTBEAT => stage_next <= LATCH_HEARTBEAT; - mem_field_flags <= EMF_NEXT_SEQ_NR_FLAG; + mem_field_flags <= EMF_NEXT_SEQ_NR_FLAG or EMF_RES_TIME_FLAG; cnt_next <= 0; when SID_GAP => stage_next <= LATCH_GAP; @@ -594,6 +605,8 @@ begin addr_next <= data_in_meta; -- UDP Port when 1 => + assert (last_word_in_meta = '1') report "last_word_in_meta not set" severity FAILURE; + portn_next <= data_in_meta(WORD_WIDTH-1 downto WORD_WIDTH-UDP_PORT_WIDTH-1); stage_next <= METATRAFFIC_OPERATION; @@ -724,7 +737,6 @@ begin null; end case; when others => - assert FALSE report "Uknown metatraffic endpoint frame opcode." severity FAILURE; null; end case; end if; @@ -823,7 +835,7 @@ begin end if; -- No scheduled Heartbeat Response - if (mem_endpoint_data.res_time = 0) then + if (mem_endpoint_data.res_time = TIME_INVALID) then -- If current Sequence Number obsolete (removed from source history cache) if (first_seq_nr > mem_endpoint_data.next_seq_nr and first_seq_nr <= last_seq_nr) then -- Store new expected Sequence Number and set Response Dealy @@ -894,18 +906,18 @@ begin -- GapList.Base 2/2 when 3 => gap_list_base_next(1) <= unsigned(data_in_user); - -- ReaderSNState.NumBits + -- GapList.NumBits when 4 => gap_list_end_next <= gap_list_base + to_integer(unsigned(data_in_user)); bitmap_cnt_next <= unsigned(round_slv(data_in_user(log2c(MAX_BITMAP_WIDTH)-1 downto 0),bitmap_cnt'length)); cnt2_next <= 0; - -- ReaderSNState.Bitmap + -- GapList.Bitmap when 5 => -- Read Bitmap if (cnt2 < bitmap_cnt) then cnt2_next <= cnt2 + 1; - bitmap_latch_next(cnt2) <= data_in_swapped; + bitmap_latch_next(cnt2) <= data_in_user; -- Keep Sub-State cnt_next <= cnt; @@ -1120,12 +1132,17 @@ begin stage_next <= SKIP_PARAMETER; end if; when INITIATE_ADD_CACHE_CHANGE_REQUEST => - start_dds <= '1'; - opcode_dds <= ADD_CACHE_CHANGE; - -- Wait until History Cache acknowledges request - if (res_dds = ACK) then - stage_next <= ADD_CACHE_CHANGE; - cnt_next <= 0; + -- SANITY CHECK: Skip if no Hash Key and no payload + if (WITH_KEY and key_hash_rcvd = '0' and data_flag = '0' and key_flag = '0') then + stage_next <= SKIP_PACKET; + else + start_dds <= '1'; + opcode_dds <= ADD_CACHE_CHANGE; + -- Wait until History Cache acknowledges request + if (res_dds = ACK) then + stage_next <= ADD_CACHE_CHANGE; + cnt_next <= 0; + end if; end if; when ADD_CACHE_CHANGE => case (cnt) is @@ -1218,8 +1235,10 @@ begin -- Output Guard if (ready_out_dds = '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 + -- the serialized Key. -- Payload exists - if (data_flag = '1' or (WITH_KEY and key_flag = '1')) then + if (data_flag = '1' or (WITH_KEY and key_hash_rcvd = '0')) then stage_next <= PUSH_PAYLOAD; else -- DONE @@ -1331,7 +1350,7 @@ begin end if; else -- Update Check Time - if (mem_endpoint_data.res_time /= TIME_INVALID and mem_endpoint_data.lease_deadline /= TIME_INVALID and mem_endpoint_data.res_time < mem_endpoint_data.lease_deadline) then + if (RELIABILTY_QOS = RELIABLE_RELIABILITY_QOS and mem_endpoint_data.res_time /= TIME_INVALID and mem_endpoint_data.lease_deadline /= TIME_INVALID and mem_endpoint_data.res_time < mem_endpoint_data.lease_deadline) then if (mem_endpoint_data.res_time < check_time) then check_time_next <= mem_endpoint_data.res_time; end if; @@ -1369,7 +1388,7 @@ begin mem_field_flags <= RES_TIME_FLAG; -- Send ACKNACK - -- Increment Heartbeat/Acknack Counter + -- Increment Acknack Counter count_next <= count + 1; stage_next <= SEND_HEADER; return_stage_next <= SEND_ACKNACK; @@ -1510,6 +1529,14 @@ begin -- Skip-Read rd_guard := '1'; end if; + when SKIP_META_OPERATION => + -- Skip-Read + rd_meta <= '1'; + + -- Exit Condition + if (last_word_in_meta = '1') then + stage_next <= IDLE; + end if; when others => null; end case; @@ -1556,6 +1583,7 @@ begin -- 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. -- GET_NEXT_ENDPOINT See Memory OPCODE Description + -- RESET_MEMORY Reset Endpoint Memory to Empty State mem_ctrl_prc : process(all) begin -- DEFAULT Registered @@ -1669,8 +1697,7 @@ begin end if; when SEARCH_ENDPOINT => case (mem_cnt) is - -- *READ ADDRESS* - -- Entity ID + -- GET Entity ID when 0 => mem_addr <= mem_addr_base + EMF_ENTITYID_OFFSET; mem_read <= '1'; @@ -1679,7 +1706,7 @@ begin if (mem_ready_in = '1') then mem_cnt_next <= mem_cnt + 1; end if; - -- GUID Prefix 1/3 + -- GET GUID Prefix 1/3 when 1 => mem_addr <= mem_addr_base + EMF_GUIDPREFIX_OFFSET; mem_read <= '1'; @@ -1688,7 +1715,7 @@ begin if (mem_ready_in = '1') then mem_cnt_next <= mem_cnt + 1; end if; - -- GUID Prefix 2/3 + -- GET GUID Prefix 2/3 when 2 => mem_addr <= mem_addr_base + EMF_GUIDPREFIX_OFFSET + 1; mem_read <= '1'; @@ -1697,7 +1724,7 @@ begin if (mem_ready_in = '1') then mem_cnt_next <= mem_cnt + 1; end if; - -- GUID Prefix 3/3 + -- GET GUID Prefix 3/3 when 3 => mem_addr <= mem_addr_base + EMF_GUIDPREFIX_OFFSET + 2; mem_read <= '1'; @@ -1706,8 +1733,7 @@ begin if (mem_ready_in = '1') then mem_cnt_next <= mem_cnt + 1; end if; - -- *READ DATA* - -- Entity ID + -- READ Entity ID when 4 => mem_ready_out <= '1'; -- Memory Flow Control Guard @@ -1730,7 +1756,7 @@ begin mem_cnt_next <= mem_cnt + 1; end if; end if; - -- GUID Prefix 1/3 + -- READ GUID Prefix 1/3 when 5 => mem_ready_out <= '1'; -- Memory Flow Control Guard @@ -1753,7 +1779,7 @@ begin mem_cnt_next <= mem_cnt + 1; end if; end if; - -- GUID Prefix 2/3 + -- READ GUID Prefix 2/3 when 6 => mem_ready_out <= '1'; -- Memory Flow Control Guard @@ -1776,7 +1802,7 @@ begin mem_cnt_next <= mem_cnt + 1; end if; end if; - -- GUID Prefix 3/3 + -- READ GUID Prefix 3/3 when 7 => mem_ready_out <= '1'; -- Memory Flow Control Guard @@ -1827,8 +1853,7 @@ begin when GET_ENDPOINT_DATA => case (mem_cnt) is - -- *READ ADDR* - -- Entity ID + -- GET Entity ID when 0 => mem_valid_in <= '1'; mem_addr <= mem_addr_base + EMF_ENTITYID_OFFSET; @@ -1851,7 +1876,7 @@ begin mem_cnt_next <= 12; end if; end if; - -- GUID Prefix 1/3 + -- GET GUID Prefix 1/3 when 1 => mem_valid_in <= '1'; mem_addr <= mem_addr_base + EMF_GUIDPREFIX_OFFSET; @@ -1860,7 +1885,7 @@ begin if (mem_ready_in = '1') then mem_cnt_next <= mem_cnt + 1; end if; - -- GUID Prefix 2/3 + -- GET GUID Prefix 2/3 when 2 => mem_valid_in <= '1'; mem_addr <= mem_addr_base + EMF_GUIDPREFIX_OFFSET + 1; @@ -1869,7 +1894,7 @@ begin if (mem_ready_in = '1') then mem_cnt_next <= mem_cnt + 1; end if; - -- GUID Prefix 3/3 + -- GET GUID Prefix 3/3 when 3 => mem_valid_in <= '1'; mem_addr <= mem_addr_base + EMF_GUIDPREFIX_OFFSET + 2; @@ -1894,7 +1919,7 @@ begin end if; end if; end if; - -- IPv4 Address + -- GET IPv4 Address when 4 => -- Synthesis Guard if (RELIABILTY_QOS = RELIABLE_RELIABILITY_QOS) then @@ -1922,7 +1947,7 @@ begin end if; end if; end if; - -- UDP Port/ Flags + -- GET UDP Port/ Flags when 5 => -- Synthesis Guard if (RELIABILTY_QOS = RELIABLE_RELIABILITY_QOS) then @@ -1950,7 +1975,7 @@ begin end if; end if; end if; - -- Next Sequence Number 1/2 + -- GET Next Sequence Number 1/2 when 6 => mem_valid_in <= '1'; mem_addr <= mem_addr_base + EMF_NEXT_SEQ_NR_OFFSET; @@ -1959,7 +1984,7 @@ begin if (mem_ready_in = '1') then mem_cnt_next <= mem_cnt + 1; end if; - -- Next Sequence Number 2/2 + -- GET Next Sequence Number 2/2 when 7 => mem_valid_in <= '1'; mem_addr <= mem_addr_base + EMF_NEXT_SEQ_NR_OFFSET + 1; @@ -1984,7 +2009,7 @@ begin end if; end if; end if; - -- Lease Deadline 1/2 + -- GET Lease Deadline 1/2 when 8 => mem_valid_in <= '1'; mem_addr <= mem_addr_base + EMF_LEASE_DEADLINE_OFFSET; @@ -1993,7 +2018,7 @@ begin if (mem_ready_in = '1') then mem_cnt_next <= mem_cnt + 1; end if; - -- Lease Deadline 2/2 + -- GET Lease Deadline 2/2 when 9 => mem_valid_in <= '1'; mem_addr <= mem_addr_base + EMF_LEASE_DEADLINE_OFFSET + 1; @@ -2018,7 +2043,7 @@ begin end if; end if; end if; - -- Response Time 1/2 + -- GET Response Time 1/2 when 10 => -- Synthesis Guard if (RELIABILTY_QOS = RELIABLE_RELIABILITY_QOS) then @@ -2030,7 +2055,7 @@ begin mem_cnt_next <= mem_cnt + 1; end if; end if; - -- Response Time 2/2 + -- GET Response Time 2/2 when 11 => -- Synthesis Guard if (RELIABILTY_QOS = RELIABLE_RELIABILITY_QOS) then @@ -2056,8 +2081,7 @@ begin end if; end if; end if; - -- *READ DATA* - -- Entity ID + -- READ Entity ID when 12 => mem_ready_out <= '1'; -- Memory Flow Control Guard @@ -2081,7 +2105,7 @@ begin mem_stage_next <= IDLE; end if; end if; - -- GUID Prefix 1/3 + -- READ GUID Prefix 1/3 when 13 => mem_ready_out <= '1'; -- Memory Flow Control Guard @@ -2090,7 +2114,7 @@ begin mem_cnt_next <= mem_cnt + 1; end if; - -- GUID Prefix 2/3 + -- READ GUID Prefix 2/3 when 14 => mem_ready_out <= '1'; -- Memory Flow Control Guard @@ -2099,7 +2123,7 @@ begin mem_cnt_next <= mem_cnt + 1; end if; - -- GUID Prefix 3/3 + -- READ GUID Prefix 3/3 when 15 => mem_ready_out <= '1'; -- Memory Flow Control Guard @@ -2121,7 +2145,7 @@ begin mem_stage_next <= IDLE; end if; end if; - -- IPv4 Address + -- READ IPv4 Address when 16 => -- Synthesis Guard if (RELIABILTY_QOS = RELIABLE_RELIABILITY_QOS) then @@ -2144,7 +2168,7 @@ begin end if; end if; end if; - -- UDP Port + -- READ UDP Port when 17 => -- Synthesis Guard if (RELIABILTY_QOS = RELIABLE_RELIABILITY_QOS) then @@ -2165,7 +2189,7 @@ begin end if; end if; end if; - -- Next Sequence Number 1/2 + -- READ Next Sequence Number 1/2 when 18 => mem_ready_out <= '1'; -- Memory Flow Control Guard @@ -2174,7 +2198,7 @@ begin mem_cnt_next <= mem_cnt + 1; end if; - -- Next Sequence Number 2/2 + -- READ Next Sequence Number 2/2 when 19 => mem_ready_out <= '1'; -- Memory Flow Control Guard @@ -2190,7 +2214,7 @@ begin mem_stage_next <= IDLE; end if; end if; - -- Lease Deadline 1/2 + -- READ Lease Deadline 1/2 when 20 => mem_ready_out <= '1'; -- Memory Flow Control Guard @@ -2199,7 +2223,7 @@ begin mem_cnt_next <= mem_cnt + 1; end if; - -- Lease Deadline 2/2 + -- READ Lease Deadline 2/2 when 21 => mem_ready_out <= '1'; -- Memory Flow Control Guard @@ -2213,7 +2237,7 @@ begin mem_stage_next <= IDLE; end if; end if; - -- Response Time 1/2 + -- READ Response Time 1/2 when 22 => -- Synthesis Guard if (RELIABILTY_QOS = RELIABLE_RELIABILITY_QOS) then @@ -2225,7 +2249,7 @@ begin mem_cnt_next <= mem_cnt + 1; end if; end if; - -- Response Time 2/2 + -- READ Response Time 2/2 when 23 => -- Synthesis Guard if (RELIABILTY_QOS = RELIABLE_RELIABILITY_QOS) then @@ -2415,7 +2439,8 @@ begin mem_write_data <= std_logic_vector(mem_endpoint_latch_data.next_seq_nr(0)); -- Memory Flow Control Guard if (mem_ready_in = '1') - mem_cnt_next <= mem_cnt + 1; + mem_cnt_next <= mem_cnt + 1; + end if; -- Next Sequence Number 2/2 when 3 => mem_valid_in <= '1'; @@ -2561,8 +2586,7 @@ begin end case; when RESET_MAX_POINTER => case (mem_cnt) is - -- *READ ADDRESS* - -- Entity ID + -- GET Entity ID when 0 => mem_addr <= mem_addr_base + EMF_ENTITYID_OFFSET; mem_read <= '1'; @@ -2572,8 +2596,7 @@ begin if (mem_ready_in = '1') then mem_cnt_next <= 1; end if; - -- *READ DATA* - -- Entity ID + -- READ Entity ID when 1 => mem_ready_out <= '1'; @@ -2618,8 +2641,7 @@ begin end case; when GET_NEXT_ENDPOINT => case (mem_cnt) is - -- *READ ADDRESS* - -- Entity ID + -- GET Entity ID when 0 => mem_valid_in <= '1'; mem_read <= '1'; @@ -2629,8 +2651,7 @@ begin if (mem_ready_in = '1') then mem_cnt_next <= 1; end if; - -- *READ DATA* - -- Entity ID + -- READ Entity ID when 1 => mem_ready_out <= '1'; @@ -2677,6 +2698,32 @@ begin when others => null; end case; + when RESET_MEMORY => + case (mem_cnt) is + -- Initiate Reset + when 0 => + mem_addr_base_next <= FIRST_ENDPOINT_ADDRESS; + mem_cnt_next <= mem_cnt + 1; + -- Reset Memory + when 1 => + mem_valid_in <= '1'; + mem_addr <= mem_addr_base + EMF_ENTITYID_OFFSET; + mem_write_data <= ENTITYID_UNKNOWN; + + -- Memory Flow Control Guard + if (mem_ready_in = '1') then + -- End of Memory + if (mem_addr_base = MAX_ENDPOINT_ADDRESS) then + -- DONE + mem_stage_next <= IDLE; + else + -- Next Endpoint Frame + mem_addr_base_next <= mem_addr_base + ENDPOINT_FRAME_SIZE; + end if; + end if; + when others => + null; + end case; when others => null; end case;