From 965e7fbb4aca0cfd3417a72268bdaef4b0fd531c Mon Sep 17 00:00:00 2001 From: Greek Date: Wed, 8 Dec 2021 20:58:33 +0100 Subject: [PATCH] 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. --- src/dds_reader.vhd | 191 ++++++++++++++++++++++++++++----------------- 1 file changed, 119 insertions(+), 72 deletions(-) diff --git a/src/dds_reader.vhd b/src/dds_reader.vhd index 65c556b..9ac72de 100644 --- a/src/dds_reader.vhd +++ b/src/dds_reader.vhd @@ -1183,7 +1183,7 @@ begin cur_sample_next <= oldest_sample; key_hash_next <= instance_handle_dds; stage_next <= FIND_NEXT_INSTANCE; - cnt_next <= 0; + cnt_next <= 0; -- GET FIRST INSTANCE end if; else stage_next <= RETURN_DDS; @@ -1204,7 +1204,7 @@ begin cur_sample_next <= oldest_sample; key_hash_next <= instance_handle_dds; stage_next <= FIND_NEXT_INSTANCE; - cnt_next <= 0; + cnt_next <= 0; -- GET FIRST INSTANCE end if; else stage_next <= RETURN_DDS; @@ -3726,7 +3726,7 @@ begin -- NOTE: We selected a compatible instance, but the instance has no compatible samples. -- Find next compatible instance. stage_next <= FIND_NEXT_INSTANCE; - cnt_next <= 1; + cnt_next <= 1; -- GET NEXT INSTANCE else done_dds <= '1'; return_code_dds <= RETCODE_NO_DATA; @@ -4308,92 +4308,139 @@ begin -- Wait for Instance Data if (inst_op_done = '1') then case (cnt) is + -- GET FIRST INSTANCE when 0 => -- 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_FIRST_INSTANCE; inst_mem_fields <= IMF_STATUS_FLAG or IMF_KEY_HASH_FLAG; cnt_next <= 2; + -- GET NEXT INSTANCE when 1 => -- 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; cnt_next <= 2; + -- EXIT CONDITION when 2 => - assert check_mask(current_imf, IMF_STATUS_FLAG) severity FAILURE; - - -- 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 + -- No More Instances + if (inst_addr_base = INSTANCE_MEMORY_MAX_ADDRESS) then -- DONE done_dds <= '1'; return_code_dds <= RETCODE_NO_DATA; 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; when others => null;