TIMING CLOSURE: Further Sub-Split FIND_NEXT_INSTANCE in dds_reader

The FIND_NEXT_INSTANCE stage of the dds_reader was doing a 128-bit
comparison (Key Hash) in 1 clock cycle.
The comparison was split among 4 clock cycles.
This commit is contained in:
Greek 2021-12-08 20:58:33 +01:00 committed by Greek64
parent 4841d0a6bb
commit 965e7fbb4a

View File

@ -1183,7 +1183,7 @@ begin
cur_sample_next <= oldest_sample; cur_sample_next <= oldest_sample;
key_hash_next <= instance_handle_dds; key_hash_next <= instance_handle_dds;
stage_next <= FIND_NEXT_INSTANCE; stage_next <= FIND_NEXT_INSTANCE;
cnt_next <= 0; cnt_next <= 0; -- GET FIRST INSTANCE
end if; end if;
else else
stage_next <= RETURN_DDS; stage_next <= RETURN_DDS;
@ -1204,7 +1204,7 @@ begin
cur_sample_next <= oldest_sample; cur_sample_next <= oldest_sample;
key_hash_next <= instance_handle_dds; key_hash_next <= instance_handle_dds;
stage_next <= FIND_NEXT_INSTANCE; stage_next <= FIND_NEXT_INSTANCE;
cnt_next <= 0; cnt_next <= 0; -- GET FIRST INSTANCE
end if; end if;
else else
stage_next <= RETURN_DDS; stage_next <= RETURN_DDS;
@ -3726,7 +3726,7 @@ begin
-- NOTE: We selected a compatible instance, but the instance has no compatible samples. -- NOTE: We selected a compatible instance, but the instance has no compatible samples.
-- Find next compatible instance. -- Find next compatible instance.
stage_next <= FIND_NEXT_INSTANCE; stage_next <= FIND_NEXT_INSTANCE;
cnt_next <= 1; cnt_next <= 1; -- GET NEXT INSTANCE
else else
done_dds <= '1'; done_dds <= '1';
return_code_dds <= RETCODE_NO_DATA; return_code_dds <= RETCODE_NO_DATA;
@ -4308,92 +4308,139 @@ begin
-- Wait for Instance Data -- Wait for Instance Data
if (inst_op_done = '1') then if (inst_op_done = '1') then
case (cnt) is case (cnt) is
-- GET FIRST INSTANCE
when 0 => when 0 =>
-- NOTE: The Generation Counters are not used directly in this state, but will be needed by the FINALIZE_SAMPLE_INFO state. -- NOTE: The Generation Counters are not used directly in this state, but will be needed by the FINALIZE_SAMPLE_INFO state.
inst_op_start <= '1'; inst_op_start <= '1';
inst_opcode <= GET_FIRST_INSTANCE; inst_opcode <= GET_FIRST_INSTANCE;
inst_mem_fields <= IMF_STATUS_FLAG or IMF_KEY_HASH_FLAG; inst_mem_fields <= IMF_STATUS_FLAG or IMF_KEY_HASH_FLAG;
cnt_next <= 2; cnt_next <= 2;
-- GET NEXT INSTANCE
when 1 => when 1 =>
-- NOTE: The Generation Counters are not used directly in this state, but will be needed by the FINALIZE_SAMPLE_INFO state. -- NOTE: The Generation Counters are not used directly in this state, but will be needed by the FINALIZE_SAMPLE_INFO state.
inst_op_start <= '1'; inst_op_start <= '1';
inst_opcode <= GET_NEXT_INSTANCE; inst_opcode <= GET_NEXT_INSTANCE;
inst_mem_fields <= IMF_STATUS_FLAG or IMF_KEY_HASH_FLAG; inst_mem_fields <= IMF_STATUS_FLAG or IMF_KEY_HASH_FLAG;
cnt_next <= 2; cnt_next <= 2;
-- EXIT CONDITION
when 2 => when 2 =>
assert check_mask(current_imf, IMF_STATUS_FLAG) severity FAILURE; -- No More Instances
if (inst_addr_base = INSTANCE_MEMORY_MAX_ADDRESS) then
-- Instance Found
if (inst_addr_base /= INSTANCE_MEMORY_MAX_ADDRESS) then
-- DEFAULT
tmp_bool := TRUE;
-- Check Instance Handle (Key Hash)
-- XXX: Posible Worst Case Path (128-bit Comparison)
if (to_unsigned(inst_data.key_hash) <= to_unsigned(key_hash)) then
tmp_bool := FALSE;
end if;
-- Check Instance State
case (instance_state) is
when ALIVE_INSTANCE_STATE =>
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(ISI_NOT_ALIVE_DISPOSED_FLAG) = '0') then
tmp_bool := FALSE;
end if;
when NOT_ALIVE_NO_WRITERS_INSTANCE_STATE =>
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(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 =>
null;
when others =>
tmp_bool := FALSE;
end case;
-- Check View State
case (view_state) is
when NEW_VIEW_STATE =>
if (inst_data.status_info(ISI_VIEW_FLAG) = '1') then
tmp_bool := FALSE;
end if;
when NOT_NEW_VIEW_STATE =>
if (inst_data.status_info(ISI_VIEW_FLAG) = '0') then
tmp_bool := FALSE;
end if;
when ANY_VIEW_STATE =>
null;
when others =>
tmp_bool := FALSE;
end case;
-- Instance Passes Checks
if (tmp_bool) then
cur_inst_next <= inst_addr_base;
stage_next <= GET_NEXT_SAMPLE;
cnt_next <= 0;
-- Reset
sel_sample_next <= SAMPLE_MEMORY_MAX_ADDRESS;
sample_p1_next <= SAMPLE_MEMORY_MAX_ADDRESS;
sample_p2_next <= SAMPLE_MEMORY_MAX_ADDRESS;
else
-- NOTE: The Generation Counters are not used directly in this state, but will be needed by the FINALIZE_SAMPLE_INFO state.
inst_op_start <= '1';
inst_opcode <= GET_NEXT_INSTANCE;
inst_mem_fields <= IMF_STATUS_FLAG or IMF_KEY_HASH_FLAG;
end if;
else
-- DONE -- DONE
done_dds <= '1'; done_dds <= '1';
return_code_dds <= RETCODE_NO_DATA; return_code_dds <= RETCODE_NO_DATA;
stage_next <= IDLE; stage_next <= IDLE;
else
-- Check Instance
cnt_next <= cnt + 1;
end if;
-- KEY HASH 1/4
when 3 =>
assert (inst_addr_base /= INSTANCE_MEMORY_MAX_ADDRESS) severity FAILURE;
assert check_mask(current_imf, IMF_KEY_HASH_FLAG) severity FAILURE;
if (unsigned(inst_data.key_hash(0)) > unsigned(key_hash(0))) then
cnt_next <= 7; -- INSTANCE STATUS CHECK
elsif (unsigned(inst_data.key_hash(0)) = unsigned(key_hash(0))) then
-- Continue Check
cnt_next <= cnt + 1;
else -- LESS THAN
cnt_next <= 1; -- GET NEXT INSTANCE
end if;
-- KEY HASH 2/4
when 4 =>
assert (inst_addr_base /= INSTANCE_MEMORY_MAX_ADDRESS) severity FAILURE;
assert check_mask(current_imf, IMF_KEY_HASH_FLAG) severity FAILURE;
if (unsigned(inst_data.key_hash(1)) > unsigned(key_hash(1))) then
cnt_next <= 7; -- INSTANCE STATUS CHECK
elsif (unsigned(inst_data.key_hash(1)) = unsigned(key_hash(1))) then
-- Continue Check
cnt_next <= cnt + 1;
else -- LESS THAN
cnt_next <= 1; -- GET NEXT INSTANCE
end if;
-- KEY HASH 3/4
when 5 =>
assert (inst_addr_base /= INSTANCE_MEMORY_MAX_ADDRESS) severity FAILURE;
assert check_mask(current_imf, IMF_KEY_HASH_FLAG) severity FAILURE;
if (unsigned(inst_data.key_hash(2)) > unsigned(key_hash(2))) then
cnt_next <= 7; -- INSTANCE STATUS CHECK
elsif (unsigned(inst_data.key_hash(2)) = unsigned(key_hash(2))) then
-- Continue Check
cnt_next <= cnt + 1;
else -- LESS THAN
cnt_next <= 1; -- GET NEXT INSTANCE
end if;
-- KEY HASH 4/4
when 6 =>
assert check_mask(current_imf, IMF_KEY_HASH_FLAG) severity FAILURE;
if (unsigned(inst_data.key_hash(3)) > unsigned(key_hash(3))) then
cnt_next <= 7; -- INSTANCE STATUS CHECK
else -- LESS THAN EQUAL
cnt_next <= 1; -- GET NEXT INSTANCE
end if;
-- INSTANCE STATUS CHECK
when 7 =>
assert (inst_addr_base /= INSTANCE_MEMORY_MAX_ADDRESS) severity FAILURE;
assert check_mask(current_imf, IMF_STATUS_FLAG) severity FAILURE;
-- DEFAULT
tmp_bool := TRUE;
-- Check Instance State
case (instance_state) is
when ALIVE_INSTANCE_STATE =>
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(ISI_NOT_ALIVE_DISPOSED_FLAG) = '0') then
tmp_bool := FALSE;
end if;
when NOT_ALIVE_NO_WRITERS_INSTANCE_STATE =>
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(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 =>
null;
when others =>
tmp_bool := FALSE;
end case;
-- Check View State
case (view_state) is
when NEW_VIEW_STATE =>
if (inst_data.status_info(ISI_VIEW_FLAG) = '1') then
tmp_bool := FALSE;
end if;
when NOT_NEW_VIEW_STATE =>
if (inst_data.status_info(ISI_VIEW_FLAG) = '0') then
tmp_bool := FALSE;
end if;
when ANY_VIEW_STATE =>
null;
when others =>
tmp_bool := FALSE;
end case;
-- Instance Passes Checks
if (tmp_bool) then
cur_inst_next <= inst_addr_base;
stage_next <= GET_NEXT_SAMPLE;
cnt_next <= 0;
-- Reset
sel_sample_next <= SAMPLE_MEMORY_MAX_ADDRESS;
sample_p1_next <= SAMPLE_MEMORY_MAX_ADDRESS;
sample_p2_next <= SAMPLE_MEMORY_MAX_ADDRESS;
else
cnt_next <= 1; -- GET NEXT INSTANCE
end if; end if;
when others => when others =>
null; null;