From 1fdf2198ba05719a93d7e5837efd373436c21462 Mon Sep 17 00:00:00 2001 From: Greek Date: Wed, 8 Dec 2021 18:55:17 +0100 Subject: [PATCH] TIMING CLOSURE: Further Sub-Split PARTICIPANT_STALE_CHECK in rtps_builtin_endpoint The PARTICIPANT_STALE_CHECK stage of the rtps_builtin_endpoint was doing 4 consecutive 64-bit comparisons in the same clock cycle. The stage was further sub-split to make one 64-bit comparison per clock cycle. --- src/rtps_builtin_endpoint.vhd | 221 ++++++++++++++++++---------------- 1 file changed, 118 insertions(+), 103 deletions(-) diff --git a/src/rtps_builtin_endpoint.vhd b/src/rtps_builtin_endpoint.vhd index 8a239e1..d2c8dde 100644 --- a/src/rtps_builtin_endpoint.vhd +++ b/src/rtps_builtin_endpoint.vhd @@ -438,21 +438,6 @@ architecture arch of rtps_builtin_endpoint is alias gap_list_end_next : SEQUENCENUMBER_TYPE is sn_latch_3_next; --*****FUNCTION DECLARATION***** - -- Return minimum of t1,t2,t3 or TIME_INVALID if t1,t2,t3 < t. - function min_time(t1, t2, t3, t : TIME_TYPE) return TIME_TYPE is - variable ret : TIME_TYPE := TIME_INVALID; - begin - if (not (t1 <= t)) then - ret := t1; - end if; - if (not (t2 <= t) and t2 < ret) then - ret := t2; - end if; - if (not (t3 <= t) and t3 < ret) then - ret := t3; - end if; - return ret; - end function; -- Helper function to convert BITMAP_TYPE to std_logic_vector function to_slv_bitmap (input : BITMAP_TYPE) return std_logic_vector is @@ -773,7 +758,7 @@ begin stale_check_next <= '1'; stage_next <= PARTICIPANT_STALE_CHECK; - cnt_next <= 1; + cnt_next <= 1; -- EXIT CONDITION -- Reset Timeout check_time_next <= TIME_INFINITE; @@ -1814,92 +1799,120 @@ begin -- Wait for Stale Search to finish if (mem_op_done = '1') then case (cnt) is + -- GET NEXT PARTICIPANT when 0 => mem_op_start <= '1'; mem_opcode <= GET_NEXT_PARTICIPANT; mem_field_flags <= PMF_LEASE_DEADLINE_FLAG or PMF_ACKNACK_RES_TIME_FLAG or PMF_HEARTBEAT_RES_TIME_FLAG; cnt_next <= cnt + 1; + -- EXIT CONDITION when 1 => - assert check_mask(current_pmf, PMF_LEASE_DEADLINE_FLAG or PMF_HEARTBEAT_RES_TIME_FLAG or PMF_ACKNACK_RES_TIME_FLAG) severity FAILURE; - - -- Found Stale Entry - if (mem_addr_base /= PARTICIPANT_MEMORY_MAX_ADDRESS) then - - -- Lease Expiration - if (participant_data.lease_deadline /= TIME_INVALID and participant_data.lease_deadline <= time) then - mem_op_start <= '1'; - mem_opcode <= GET_PARTICIPANT; - mem_field_flags <= PMF_GUIDPREFIX_FLAG; - mem_addr_update <= mem_addr_base; - cnt_next <= cnt + 1; - -- HEARTBEAT Response Time - elsif (participant_data.heartbeat_res_time /= TIME_INVALID and participant_data.heartbeat_res_time <= time) then - -- Suppression Delay - if (participant_data.heartbeat_res_time(1)(0) = '1') then - mem_op_start <= '1'; - mem_opcode <= UPDATE_PARTICIPANT; - mem_field_flags <= PMF_HEARTBEAT_RES_TIME_FLAG; - res_time <= TIME_INVALID; - -- Response Delay - else - mem_op_start <= '1'; - mem_opcode <= GET_PARTICIPANT; - mem_field_flags <= PMF_META_IPV4_ADDR_FLAG or PMF_UDP_PORT_FLAG or PMF_PUB_SEQ_NR_FLAG or PMF_SUB_SEQ_NR_FLAG or PMF_MES_SEQ_NR_FLAG; - mem_addr_update <= mem_addr_base; - - -- Send ACKNACK - stage_next <= SEND_HEADER; - return_stage_next <= SEND_ACKNACK; - cnt_next <= 0; - -- Increment Heartbeat/Acknack Counter - count_next <= count + 1; - end if; - - -- Update Check Time - if (participant_data.lease_deadline /= TIME_INVALID and participant_data.lease_deadline < check_time) then - check_time_next <= participant_data.lease_deadline; - end if; - -- ACKNACK Response Time - elsif (participant_data.acknack_res_time /= TIME_INVALID and participant_data.acknack_res_time <= time) then - -- Suppression Delay - if (participant_data.acknack_res_time(1)(0) = '1') then - mem_op_start <= '1'; - mem_opcode <= UPDATE_PARTICIPANT; - mem_field_flags <= PMF_ACKNACK_RES_TIME_FLAG; - res_time <= TIME_INVALID; - -- Response Delay - else - mem_op_start <= '1'; - mem_opcode <= GET_PARTICIPANT; - mem_field_flags <= PMF_META_IPV4_ADDR_FLAG or PMF_UDP_PORT_FLAG or PMF_EXTRA_FLAGS_FLAG; - mem_addr_update <= mem_addr_base; - - -- Send Requested Data - stage_next <= SEND_HEADER; - return_stage_next <= SEND_PUB_DATA; - cnt_next <= 0; - end if; - else - -- Continue Search - mem_op_start <= '1'; - mem_opcode <= GET_NEXT_PARTICIPANT; - mem_field_flags <= PMF_LEASE_DEADLINE_FLAG or PMF_ACKNACK_RES_TIME_FLAG or PMF_HEARTBEAT_RES_TIME_FLAG; - end if; - - -- NOTE: If the Lease Time expired, but one of the response times is less the check_time, the check_time will be updated - -- Update Check Time - -- XXX: Possible Worst Case Path (4 consecutive 64-bit comparisons in same clock) - tmp_dw := min_time(participant_data.lease_deadline, participant_data.heartbeat_res_time, participant_data.acknack_res_time, time); - if (tmp_dw < check_time) then - check_time_next <= tmp_dw; - end if; - else + -- No More Participants + if (mem_addr_base = PARTICIPANT_MEMORY_MAX_ADDRESS) then -- Reset stale_check_next <= '0'; -- DONE stage_next <= IDLE; + else + -- Check if STALE + cnt_next <= cnt + 1; end if; + -- LEASE DEADLINE when 2 => + assert check_mask(current_pmf, PMF_LEASE_DEADLINE_FLAG) severity FAILURE; + assert (mem_addr_base /= PARTICIPANT_MEMORY_MAX_ADDRESS) severity FAILURE; + + -- Lease Expiration + if (participant_data.lease_deadline /= TIME_INVALID and participant_data.lease_deadline <= time) then + mem_op_start <= '1'; + mem_opcode <= GET_PARTICIPANT; + mem_field_flags <= PMF_GUIDPREFIX_FLAG; + mem_addr_update <= mem_addr_base; + cnt_next <= 5; -- HELPER STAGE + else + -- Check Next Field + cnt_next <= cnt + 1; + + -- Update Check Time + if (participant_data.lease_deadline /= TIME_INVALID and participant_data.lease_deadline < check_time) then + check_time_next <= participant_data.lease_deadline; + end if; + end if; + -- HEARTBEAT RESPONSE TIME + when 3 => + assert check_mask(current_pmf, PMF_HEARTBEAT_RES_TIME_FLAG) severity FAILURE; + assert (mem_addr_base /= PARTICIPANT_MEMORY_MAX_ADDRESS) severity FAILURE; + + -- HEARTBEAT Response Time Passed + if (participant_data.heartbeat_res_time /= TIME_INVALID and participant_data.heartbeat_res_time <= time) then + -- Suppression Delay + if (participant_data.heartbeat_res_time(1)(0) = '1') then + mem_op_start <= '1'; + mem_opcode <= UPDATE_PARTICIPANT; + mem_field_flags <= PMF_HEARTBEAT_RES_TIME_FLAG; + res_time <= TIME_INVALID; + -- Response Delay + else + mem_op_start <= '1'; + mem_opcode <= GET_PARTICIPANT; + mem_field_flags <= PMF_META_IPV4_ADDR_FLAG or PMF_UDP_PORT_FLAG or PMF_PUB_SEQ_NR_FLAG or PMF_SUB_SEQ_NR_FLAG or PMF_MES_SEQ_NR_FLAG; + mem_addr_update <= mem_addr_base; + + -- Send ACKNACK + stage_next <= SEND_HEADER; + return_stage_next <= SEND_ACKNACK; + cnt_next <= 0; + -- Increment Heartbeat/Acknack Counter + count_next <= count + 1; + end if; + else + -- Check Next Field + cnt_next <= cnt + 1; + + -- Update Check Time + if (participant_data.heartbeat_res_time /= TIME_INVALID and participant_data.heartbeat_res_time < check_time) then + check_time_next <= participant_data.heartbeat_res_time; + end if; + end if; + -- ACKNACK RESPONSE TIME + when 4 => + assert check_mask(current_pmf, PMF_ACKNACK_RES_TIME_FLAG) severity FAILURE; + assert (mem_addr_base /= PARTICIPANT_MEMORY_MAX_ADDRESS) severity FAILURE; + + -- ACKNACK Response Time Passed + if (participant_data.acknack_res_time /= TIME_INVALID and participant_data.acknack_res_time <= time) then + -- Suppression Delay + if (participant_data.acknack_res_time(1)(0) = '1') then + mem_op_start <= '1'; + mem_opcode <= UPDATE_PARTICIPANT; + mem_field_flags <= PMF_ACKNACK_RES_TIME_FLAG; + res_time <= TIME_INVALID; + -- Response Delay + else + mem_op_start <= '1'; + mem_opcode <= GET_PARTICIPANT; + mem_field_flags <= PMF_META_IPV4_ADDR_FLAG or PMF_UDP_PORT_FLAG or PMF_EXTRA_FLAGS_FLAG; + mem_addr_update <= mem_addr_base; + + -- Send Requested Data + stage_next <= SEND_HEADER; + return_stage_next <= SEND_PUB_DATA; + cnt_next <= 0; + end if; + else + -- Continue Search + mem_op_start <= '1'; + mem_opcode <= GET_NEXT_PARTICIPANT; + mem_field_flags <= PMF_LEASE_DEADLINE_FLAG or PMF_ACKNACK_RES_TIME_FLAG or PMF_HEARTBEAT_RES_TIME_FLAG; + cnt_next <= 1; + + -- Update Check Time + if (participant_data.acknack_res_time /= TIME_INVALID and participant_data.acknack_res_time < check_time) then + check_time_next <= participant_data.acknack_res_time; + end if; + end if; + -- HELPER STAGE (Lacthes Participant GUID for removal) + when 5 => assert check_mask(current_pmf, PMF_GUIDPREFIX_FLAG) severity FAILURE; -- Latch GUID Prefix @@ -1912,7 +1925,8 @@ begin stage_next <= INFORM_ENDPOINTS_PARTICIPANT_UNMATCH; cnt_next <= 0; - when 3 => + -- POST-ACKNACK-SENT + when 6 => mem_op_start <= '1'; mem_opcode <= UPDATE_PARTICIPANT; mem_field_flags <= PMF_HEARTBEAT_RES_TIME_FLAG; @@ -1925,11 +1939,12 @@ begin -- Reset res_time <= TIME_INVALID; end if; - -- NOTE: We go back to the Comparison Sub-state to check for further deadlines. - -- The check_time is updated in that sub-state. + + -- NOTE: The HEARTBEAT Time is re-checked in order to update the check_time -- Continue - cnt_next <= 1; - when 4 => + cnt_next <= 3; + -- POST-DATA-SENT + when 7 => assert check_mask(current_pmf, PMF_EXTRA_FLAGS_FLAG) severity FAILURE; mem_op_start <= '1'; @@ -1945,10 +1960,10 @@ begin -- Reset res_time <= TIME_INVALID; end if; - -- NOTE: We go back to the Comparison Sub-state to check for further deadlines. - -- The check_time is updated in that sub-state. + + -- NOTE: The ACKNACK Time is re-checked in order to update the check_time -- Continue - cnt_next <= 1; + cnt_next <= 4; when others => null; end case; @@ -3029,7 +3044,7 @@ begin -- Currently in Stale Check if (stale_check = '1') then stage_next <= PARTICIPANT_STALE_CHECK; - cnt_next <= 0; + cnt_next <= 0; -- GET NEXT PARTICIPANT else -- DONE stage_next <= SKIP_PACKET; @@ -3236,7 +3251,7 @@ begin -- Continue stage_next <= PARTICIPANT_STALE_CHECK; - cnt_next <= 3; + cnt_next <= 6; -- POST-ACKNACK-SENT when others => null; end case; @@ -3387,7 +3402,7 @@ begin -- Currently in Stale Check elsif (stale_check = '1') then stage_next <= PARTICIPANT_STALE_CHECK; - cnt_next <= 4; + cnt_next <= 7; -- POST-DATA-SENT else -- DONE stage_next <= IDLE; @@ -3426,7 +3441,7 @@ begin -- Currently in Stale Check elsif (stale_check = '1') then stage_next <= PARTICIPANT_STALE_CHECK; - cnt_next <= 4; + cnt_next <= 7; -- POST-DATA-SENT else -- DONE stage_next <= IDLE; @@ -3613,7 +3628,7 @@ begin -- Currently in Stale Check elsif (stale_check = '1') then stage_next <= PARTICIPANT_STALE_CHECK; - cnt_next <= 4; + cnt_next <= 7; -- POST-DATA-SENT else -- DONE stage_next <= IDLE;