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.
This commit is contained in:
Greek 2021-12-08 18:55:17 +01:00 committed by Greek64
parent f13d28d811
commit 1fdf2198ba

View File

@ -438,21 +438,6 @@ architecture arch of rtps_builtin_endpoint is
alias gap_list_end_next : SEQUENCENUMBER_TYPE is sn_latch_3_next; 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.
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 -- Helper function to convert BITMAP_TYPE to std_logic_vector
function to_slv_bitmap (input : BITMAP_TYPE) return std_logic_vector is function to_slv_bitmap (input : BITMAP_TYPE) return std_logic_vector is
@ -773,7 +758,7 @@ begin
stale_check_next <= '1'; stale_check_next <= '1';
stage_next <= PARTICIPANT_STALE_CHECK; stage_next <= PARTICIPANT_STALE_CHECK;
cnt_next <= 1; cnt_next <= 1; -- EXIT CONDITION
-- Reset Timeout -- Reset Timeout
check_time_next <= TIME_INFINITE; check_time_next <= TIME_INFINITE;
@ -1814,92 +1799,120 @@ begin
-- Wait for Stale Search to finish -- Wait for Stale Search to finish
if (mem_op_done = '1') then if (mem_op_done = '1') then
case (cnt) is case (cnt) is
-- GET NEXT PARTICIPANT
when 0 => when 0 =>
mem_op_start <= '1'; mem_op_start <= '1';
mem_opcode <= GET_NEXT_PARTICIPANT; mem_opcode <= GET_NEXT_PARTICIPANT;
mem_field_flags <= PMF_LEASE_DEADLINE_FLAG or PMF_ACKNACK_RES_TIME_FLAG or PMF_HEARTBEAT_RES_TIME_FLAG; mem_field_flags <= PMF_LEASE_DEADLINE_FLAG or PMF_ACKNACK_RES_TIME_FLAG or PMF_HEARTBEAT_RES_TIME_FLAG;
cnt_next <= cnt + 1; cnt_next <= cnt + 1;
-- EXIT CONDITION
when 1 => 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; -- No More Participants
if (mem_addr_base = PARTICIPANT_MEMORY_MAX_ADDRESS) then
-- 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
-- Reset -- Reset
stale_check_next <= '0'; stale_check_next <= '0';
-- DONE -- DONE
stage_next <= IDLE; stage_next <= IDLE;
else
-- Check if STALE
cnt_next <= cnt + 1;
end if; end if;
-- LEASE DEADLINE
when 2 => 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; assert check_mask(current_pmf, PMF_GUIDPREFIX_FLAG) severity FAILURE;
-- Latch GUID Prefix -- Latch GUID Prefix
@ -1912,7 +1925,8 @@ begin
stage_next <= INFORM_ENDPOINTS_PARTICIPANT_UNMATCH; stage_next <= INFORM_ENDPOINTS_PARTICIPANT_UNMATCH;
cnt_next <= 0; cnt_next <= 0;
when 3 => -- POST-ACKNACK-SENT
when 6 =>
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;
@ -1925,11 +1939,12 @@ begin
-- Reset -- Reset
res_time <= TIME_INVALID; res_time <= TIME_INVALID;
end if; 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 -- Continue
cnt_next <= 1; cnt_next <= 3;
when 4 => -- POST-DATA-SENT
when 7 =>
assert check_mask(current_pmf, PMF_EXTRA_FLAGS_FLAG) severity FAILURE; assert check_mask(current_pmf, PMF_EXTRA_FLAGS_FLAG) severity FAILURE;
mem_op_start <= '1'; mem_op_start <= '1';
@ -1945,10 +1960,10 @@ begin
-- Reset -- Reset
res_time <= TIME_INVALID; res_time <= TIME_INVALID;
end if; 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 -- Continue
cnt_next <= 1; cnt_next <= 4;
when others => when others =>
null; null;
end case; end case;
@ -3029,7 +3044,7 @@ begin
-- Currently in Stale Check -- Currently in Stale Check
if (stale_check = '1') then if (stale_check = '1') then
stage_next <= PARTICIPANT_STALE_CHECK; stage_next <= PARTICIPANT_STALE_CHECK;
cnt_next <= 0; cnt_next <= 0; -- GET NEXT PARTICIPANT
else else
-- DONE -- DONE
stage_next <= SKIP_PACKET; stage_next <= SKIP_PACKET;
@ -3236,7 +3251,7 @@ begin
-- Continue -- Continue
stage_next <= PARTICIPANT_STALE_CHECK; stage_next <= PARTICIPANT_STALE_CHECK;
cnt_next <= 3; cnt_next <= 6; -- POST-ACKNACK-SENT
when others => when others =>
null; null;
end case; end case;
@ -3387,7 +3402,7 @@ begin
-- Currently in Stale Check -- Currently in Stale Check
elsif (stale_check = '1') then elsif (stale_check = '1') then
stage_next <= PARTICIPANT_STALE_CHECK; stage_next <= PARTICIPANT_STALE_CHECK;
cnt_next <= 4; cnt_next <= 7; -- POST-DATA-SENT
else else
-- DONE -- DONE
stage_next <= IDLE; stage_next <= IDLE;
@ -3426,7 +3441,7 @@ begin
-- Currently in Stale Check -- Currently in Stale Check
elsif (stale_check = '1') then elsif (stale_check = '1') then
stage_next <= PARTICIPANT_STALE_CHECK; stage_next <= PARTICIPANT_STALE_CHECK;
cnt_next <= 4; cnt_next <= 7; -- POST-DATA-SENT
else else
-- DONE -- DONE
stage_next <= IDLE; stage_next <= IDLE;
@ -3613,7 +3628,7 @@ begin
-- Currently in Stale Check -- Currently in Stale Check
elsif (stale_check = '1') then elsif (stale_check = '1') then
stage_next <= PARTICIPANT_STALE_CHECK; stage_next <= PARTICIPANT_STALE_CHECK;
cnt_next <= 4; cnt_next <= 7; -- POST-DATA-SENT
else else
-- DONE -- DONE
stage_next <= IDLE; stage_next <= IDLE;