diff --git a/src/dds_endpoint.vhd b/src/dds_endpoint.vhd index 2d73aff..11e1edc 100644 --- a/src/dds_endpoint.vhd +++ b/src/dds_endpoint.vhd @@ -133,6 +133,10 @@ architecture arch of history_cache is type STAGE_TYPE is (IDLE, TODO); type INST_STAGE_TYPE is (IDLE, TODO); type INSTANCE_OPCODE_TYPE is (NOP, TODO); + -- VAR_1 (STATUS_INFO, SAMPLE_COUNT, DISPOSED_GENERATION_COUNT, NO_WRITERS_GENERATION_COUNT, IGNORE_DEADLINE, WRITER_BITMAP) + -- VAR_2 (KEY_HASH, STATUS_INFO, SAMPLE_COUNT, DISPOSED_GENERATION_COUNT, NO_WRITERS_GENERATION_COUNT) + -- VAR_3 (KEY_HASH, STATUS_INFO) + type INSTANCE_DATA_VARIANT_TYPE is (VAR_1, VAR_2, VAR_3); type INSTANCE_DATA_TYPE is record key_hash : KEY_HASH_TYPE; status_info : std_logic_vector(WORD_WIDTH-1 downto 0); @@ -152,7 +156,7 @@ architecture arch of history_cache is writer_bitmap => (others => (others => '0')) ); type INST_LATCH_DATA_TYPE is record - variant : std_logic; + variant : INSTANCE_DATA_VARIANT_TYPE; key_hash : KEY_HASH_TYPE; status_info : std_logic_vector(CDR_LONG_WIDTH-1 downto 0); sample_cnt : std_logic_vector(CDR_LONG_WIDTH-1 downto 0); @@ -163,7 +167,7 @@ architecture arch of history_cache is addr : unsigned(INSTANCE_MEMORY_ADDR_WIDTH-1 downto 0); end record; constant ZERO_INST_LATCH_DATA : INST_LATCH_DATA_TYPE := ( - variant => '1', + variant => VAR_1, key_hash => (others => (others => '0')), status_info => (others => '0'), sample_cnt => (others => '0'), @@ -271,7 +275,7 @@ architecture arch of history_cache is signal single_sample, single_sample_next : std_logic := '0'; signal unmark_instances, unmark_instances_next : std_logic := '0'; signal dynamic_next_instance, dynamic_next_instance_next : std_logic := '0'; - signal inst_data_variant : std_logic := '0'; + signal inst_data_variant : INSTANCE_DATA_VARIANT_TYPE := VAR_1; signal abort_khg : std_logic := '0'; signal status_sig, status_sig_next : std_logic_vector(STATUS_KIND_WIDTH-1 downto 0) := (others => '0'); @@ -279,6 +283,10 @@ architecture arch of history_cache is signal sample_rej_cnt_change, sample_rej_cnt_change_next : unsigned(SAMPLE_REJECTED_STATUS_COUNT_WIDTH-1 downto 0) := (others => '0'); signal sample_rej_last_reason, sample_rej_last_reason_next : std_logic_vector(CDR_ENUMERATION_WIDTH-1 downto 0) := (others =>'0'); signal sample_rej_last_inst, sample_rej_last_inst_next : INSTANCE_HANDLE_TYPE := (others => (others => '0')); + signal deadline_time, deadline_time_next : TIME_TYPE := TIME_ZERO; + signal deadline_miss_cnt, deadline_miss_cnt_next : unsigned(REQUESTED_DEADLINE_MISSED_STATUS_COUNT_WIDTH-1 downto 0) := (others => '0'); + signal deadline_miss_cnt_change, deadline_miss_cnt_change_next : unsigned(REQUESTED_DEADLINE_MISSED_STATUS_COUNT_WIDTH-1 downto 0) := (others => '0'); + signal deadline_miss_last_inst, deadline_miss_last_inst_next : INSTANCE_HANDLE_TYPE := (others => (others => '0')); --*****ALIAS DECLARATION***** alias prev_sample : unsigned(SAMPLE_MEMORY_ADDR_WIDTH-1 downto 0) is sample_addr_latch_1; @@ -451,8 +459,12 @@ begin sample_rej_cnt_change_next <= sample_rej_cnt_change; sample_rej_last_reason_next <= sample_rej_last_reason; sample_rej_last_inst_next <= sample_rej_last_inst; + deadline_time_next <= deadline_time; + deadline_miss_cnt_next <= deadline_miss_cnt; + deadline_miss_cnt_change_next <= deadline_miss_cnt_change; + deadline_miss_last_inst_next <= deadline_miss_last_inst; ack_dds <= '0'; - inst_data_variant <= '0'; + inst_data_variant <= VAR_1; done_dds <= '0'; abort_khg <= '0'; return_code_dds <= RETCODE_UNSUPPORTED; @@ -470,7 +482,14 @@ begin is_take_next <= '0'; - if (start_rtps = '1') then + -- DEADLINE QoS + if (DEADLINE_QOS /= DURATION_INFINITE and deadline_time < time) then + -- Reset Timeout + deadline_time_next <= deadline_time + DEADLINE_QOS; + + stage_next <= CHECK_DEADLINE; + cnt_next <= 0; + elsif (start_rtps = '1') then case (opcode_rtps) is when ADD_CHANGE => -- This Operation does not accept input at this time @@ -489,7 +508,7 @@ begin writer_pos_next <= to_integer(unsigned(data_in_rtps)); inst_op_start <= '1'; inst_opcode <= GET_FIRST_INSTANCE; - inst_data_variant <= '0'; + inst_data_variant <= VAR_1; stage_next <= REMOVE_WRITER; res_rtps <= ACK; end if; @@ -610,6 +629,11 @@ begin when GET_SAMPLE_REJECTED_STATUS => ack_dds <= '1'; stage_next <= GET_SAMPLE_REJECTED_STATUS; + cnt_next <= 0; + when GET_REQUESTED_DEADLINE_MISSED_STATUS => + ack_dds <= '1'; + stage_next <= GET_REQUESTED_DEADLINE_MISSED_STATUS; + cnt_next <= 0; when others => ack_dds <= '1'; stage_next <= UNKNOWN_OPERATION; @@ -853,7 +877,7 @@ begin if (inst_op_done = '1') then inst_opcode <= SEARCH_INSTANCE_HASH; inst_op_start <= '1'; - inst_data_variant <= '0'; + inst_data_variant <= VAR_1; -- Payload not yet stored if (has_data = '1') then @@ -1313,7 +1337,7 @@ begin if (inst_op_done = '1') then inst_op_start <= '1'; inst_opcode <= GET_FIRST_INSTANCE; - inst_data_variant <= '0'; + inst_data_variant <= VAR_1; -- NOTE: Instances are only removed in two occasions: -- * A new instance is added, and the instance memory gets full @@ -1351,7 +1375,7 @@ begin -- (Since we do not store previous pointers in the memory frame format) inst_op_start <= '1'; inst_opcode <= SEARCH_INSTANCE_ADDR; - inst_data_variant <= '0'; + inst_data_variant <= VAR_1; inst_addr_update <= sample_read_data; cur_sample_next <= oldest_sample; @@ -1637,7 +1661,7 @@ begin if (inst_op_done = '1') then inst_op_start <= '1'; inst_opcode <= GET_NEXT_INSTANCE; - inst_data_variant <= '0'; + inst_data_variant <= VAR_1; stage_next <= REMOVE_WRITER; end if; when REMOVE_STALE_INSTANCE => @@ -1675,7 +1699,7 @@ begin -- Continue Search inst_op_start <= '1'; inst_opcode <= GET_NEXT_INSTANCE; - inst_data_variant <= '0'; + inst_data_variant <= VAR_1; end if; end if; end if; @@ -1769,7 +1793,7 @@ begin if (inst_op_done = '1') then inst_op_start <= '1'; inst_opcode <= GET_INSTANCE; - inst_data_variant <= '1'; + inst_data_variant <= VAR_2; inst_addr_update <= next_inst; else cnt_next <= cnt; -- Keep sub-state @@ -2020,7 +2044,7 @@ begin if (inst_op_done = '1') then inst_op_start <= '1'; inst_opcode <= GET_INSTANCE_DATA_2; - inst_data_variant <= '1'; + inst_data_variant <= VAR_2; inst_addr_update <= next_inst; else cnt_next <= cnt; -- Keep State @@ -2158,7 +2182,7 @@ begin -- Get Instance Data inst_op_start <= '1'; inst_opcode <= GET_INSTANCE; - inst_data_variant <= '1'; + inst_data_variant <= VAR_2; inst_addr_update <= cur_inst; end if; end if; @@ -2341,12 +2365,12 @@ begin when 0 => inst_op_start <= '1'; inst_opcode <= GET_FIRST_INSTANCE; - inst_data_variant <= '1'; + inst_data_variant <= VAR_2; cnt_next <= 2; when 1 => inst_op_start <= '1'; inst_opcode <= GET_NEXT_INSTANCE; - inst_data_variant <= '1'; + inst_data_variant <= VAR_2; cnt_next <= 2; when 2 => -- Instance Found @@ -2407,7 +2431,7 @@ begin else inst_op_start <= '1'; inst_opcode <= GET_NEXT_INSTANCE; - inst_data_variant <= '1'; + inst_data_variant <= VAR_2; end if; else -- DONE @@ -2426,7 +2450,7 @@ begin when 0 => inst_op_start <= '1'; inst_opcode <= SEARCH_INSTANCE_HASH; - inst_data_variant <= '1'; + inst_data_variant <= VAR_2; cnt_next <= 1; when 1 => -- Instance Found @@ -2541,6 +2565,91 @@ begin null; end case; end if; + when GET_REQUESTED_DEADLINE_MISSED_STATUS => + if (ready_out_dds = '1') then + cnt_next <= cnt + 1; + valid_out_dds <= '1'; + + case (cnt) is + -- Total Count + when 0 => + data_out_dds <= deadline_miss_cnt; + -- Total Count Change + when 1 => + data_out_dds <= deadline_miss_cnt_change; + -- Reset + deadline_miss_cnt_change_next <= (others => '0'); + -- Last Instance Handle 1/4 + when 2 => + data_out_dds <= deadline_miss_last_inst(0); + -- Last Instance Handle 2/4 + when 3 => + data_out_dds <= deadline_miss_last_inst(1); + -- Last Instance Handle 3/4 + when 4 => + data_out_dds <= deadline_miss_last_inst(2); + -- Last Instance Handle 4/4 + when 5 => + data_out_dds <= deadline_miss_last_inst(3); + last_word_out_dds <= '1'; + -- Return Code + when 6 => + done_dds <= '1'; + return_code_dds <= RETCODE_OK; + -- Reset + status_sig_next(REQUESTED_DEADLINE_MISSED_STATUS) <= '0'; + + -- DONE + stage_next <= IDLE; + when others => + null; + end case; + end if; + when CHECK_DEADLINE => + -- Memory Operation Guard + if (inst_op_done = '1') then + case (cnt) is + -- Get First Instance + when 0 => + inst_op_start <= '1'; + inst_opcode <= GET_FIRST_INSTANCE; + inst_data_variant <= VAR_3; + cnt_next <= 2; + -- Get Next Instance + when 1 => + inst_op_start <= '1'; + inst_opcode <= GET_NEXT_INSTANCE; + inst_data_variant <= VAR_3; + cnt_next <= 2; + -- Check Instance + when 2 => + -- Reached End of Instances + if (inst_addr_base = INSTANCE_MEMORY_MAX_ADDRESS) then + -- DONE + stage_next <= IDLE; + else + -- Instance received Sample + if (inst_data.status_info(LIVELINESS_FLAG) = '1') then + -- Reset Liveliness Flag + inst_op_start <= '1'; + inst_opcode <= UPDATE_INSTANCE; + update_inst_flags <= STATUS_FLAG; + status_info_update <= inst_data.status_info; + status_info_update(LIVELINESS_FLAG) <= '0'; + cnt_next <= 1; + else + -- Update Requested Deadline Missed Status + status_sig_next(REQUESTED_DEADLINE_MISSED_STATUS) <= '1'; + deadline_miss_cnt_next <= deadline_miss_cnt + 1; + deadline_miss_cnt_change_next <= deadline_miss_cnt_change + 1; + deadline_miss_last_inst_next <= inst_data.key_hash; + cnt_next <= 1; + end if; + end if; + when others => + null; + end case; + end if; when others => null; end case; @@ -2658,13 +2767,20 @@ begin else inst_prev_addr_base_next <= INSTANCE_MEMORY_MAX_ADDRESS; inst_addr_base_next <= inst_occupied_head; - inst_addr_next <= inst_occupied_head + IMF_STATUS_INFO_OFFSET; - if (inst_data_variant = '0') then - inst_stage_next <= GET_INSTANCE_DATA_1; - else - inst_stage_next <= GET_INSTANCE_DATA_2; - end if; - inst_cnt_next <= 0; + case (inst_data_variant) is + when VAR_1 => + inst_addr_next <= inst_occupied_head + IMF_STATUS_INFO_OFFSET; + inst_stage_next <= GET_INSTANCE_DATA_1; + inst_cnt_next <= 0; + when VAR_2 => + inst_addr_next <= inst_occupied_head + IMF_KEY_HASH_OFFSET; + inst_stage_next <= GET_INSTANCE_DATA_2; + inst_cnt_next <= 0; + when VAR_3 => + inst_addr_next <= inst_occupied_head + IMF_KEY_HASH_OFFSET; + inst_stage_next <= GET_INSTANCE_DATA_3; + inst_cnt_next <= 0; + end case; end if; when GET_NEXT_INSTANCE => -- No Instances avialable @@ -2687,13 +2803,20 @@ begin inst_cnt_next <= 0; when GET_INSTANCE => inst_addr_base_next <= inst_addr_update; - inst_addr_next <= inst_addr_update + IMF_KEY_HASH_OFFSET; - if (inst_data_variant = '0') then - inst_stage_next <= GET_INSTANCE_DATA_1; - else - inst_stage_next <= GET_INSTANCE_DATA_2; - end if; - inst_cnt_next <= 0; + case (inst_data_variant) is + when VAR_1 => + inst_addr_next <= inst_addr_update + IMF_STATUS_INFO_OFFSET; + inst_stage_next <= GET_INSTANCE_DATA_1; + inst_cnt_next <= 0; + when VAR_2 => + inst_addr_next <= inst_addr_update + IMF_KEY_HASH_OFFSET; + inst_stage_next <= GET_INSTANCE_DATA_2; + inst_cnt_next <= 0; + when VAR_3 => + inst_addr_next <= inst_addr_update + IMF_KEY_HASH_OFFSET; + inst_stage_next <= GET_INSTANCE_DATA_3; + inst_cnt_next <= 0; + end case; when UNMARK_INTANCES => -- Empty Memory Guard if (inst_occupied_head /= INSTANCE_MEMORY_MAX_ADDRESS) then @@ -2788,14 +2911,19 @@ begin -- Match else -- Fetch Instance Data - if (inst_data_variant = '0') then - inst_stage_next <= GET_INSTANCE_DATA_1; - inst_cnt_next <= 1; -- No preload needed - else - inst_addr_next <= inst_addr_base + IMF_KEY_HASH_OFFSET; - inst_stage_next <= GET_INSTANCE_DATA_2; - inst_cnt_next <= 0; - end if; + case (inst_data_variant) is + when VAR_1 => + inst_stage_next <= GET_INSTANCE_DATA_1; + inst_cnt_next <= 1; -- No preload needed + when VAR_2 => + inst_addr_next <= inst_addr_base + IMF_KEY_HASH_OFFSET; + inst_stage_next <= GET_INSTANCE_DATA_2; + inst_cnt_next <= 0; + when VAR_3 => + inst_addr_next <= inst_addr_base + IMF_KEY_HASH_OFFSET; + inst_stage_next <= GET_INSTANCE_DATA_3; + inst_cnt_next <= 0; + end case; end if; when others => null; @@ -2816,16 +2944,22 @@ begin -- Match if (inst_read_data = inst_latch_data.addr) then -- Fetch Instance Data - if (inst_data_variant = '0') then - inst_addr_next <= inst_read_data + IMF_STATUS_INFO_OFFSET; - inst_stage_next <= GET_INSTANCE_DATA_1; - inst_cnt_next <= 0; - else - inst_addr_next <= inst_read_data + IMF_KEY_HASH_OFFSET; - inst_stage_next <= GET_INSTANCE_DATA_2; - -- TODO: Skip Preload? - inst_cnt_next <= 0; - end if; + case (inst_data_variant) is + when VAR_1 => + inst_addr_next <= inst_read_data + IMF_STATUS_INFO_OFFSET; + inst_stage_next <= GET_INSTANCE_DATA_1; + inst_cnt_next <= 0; + when VAR_2 => + inst_addr_next <= inst_read_data + IMF_KEY_HASH_OFFSET; + inst_stage_next <= GET_INSTANCE_DATA_2; + -- TODO: Skip Preload? + inst_cnt_next <= 0; + when VAR_3 => + inst_addr_next <= inst_read_data + IMF_KEY_HASH_OFFSET; + inst_stage_next <= GET_INSTANCE_DATA_3; + -- TODO: Skip Preload? + inst_cnt_next <= 0; + end case; -- No Match else -- Reached List Tail, No Match @@ -2854,16 +2988,54 @@ begin -- Fetch Instance Data - if (inst_data_variant = '0') then - inst_addr_next <= inst_addr_base + IMF_STATUS_INFO_OFFSET; - inst_stage_next <= GET_INSTANCE_DATA_1; - inst_cnt_next <= 0; - else - inst_addr_next <= inst_addr_base + IMF_KEY_HASH_OFFSET; - inst_stage_next <= GET_INSTANCE_DATA_2; - -- TODO: Skip Preload? - inst_cnt_next <= 0; - end if; + case (inst_data_variant) is + when VAR_1 => + inst_addr_next <= inst_addr_base + IMF_STATUS_INFO_OFFSET; + inst_stage_next <= GET_INSTANCE_DATA_1; + inst_cnt_next <= 0; + when VAR_2 => + inst_addr_next <= inst_addr_base + IMF_KEY_HASH_OFFSET; + inst_stage_next <= GET_INSTANCE_DATA_2; + -- TODO: Skip Preload? + inst_cnt_next <= 0; + when VAR_3 => + inst_addr_next <= inst_addr_base + IMF_KEY_HASH_OFFSET; + inst_stage_next <= GET_INSTANCE_DATA_3; + -- TODO: Skip Preload? + inst_cnt_next <= 0; + end case; + end case; + when GET_INSTANCE_DATA_3 => + -- Precondition: inst_addr (Status Info) + + inst_ren <= '1'; + inst_cnt_next <= inst_cnt + 1; + inst_addr_next <= inst_addr + 1; + + case (inst_cnt) is + -- Memory Preload + when 0 => + null; + -- Key Hash 1/4 + when 1 => + inst_data_next.key_hash(0) <= inst_read_data; + -- Key Hash 2/4 + when 2 => + inst_data_next.key_hash(1) <= inst_read_data; + -- Key Hash 3/4 + when 3 => + inst_data_next.key_hash(2) <= inst_read_data; + -- Key Hash 4/4 + when 4 => + inst_data_next.key_hash(3) <= inst_read_data; + -- Status Info + when 5 => + inst_data_next.status_info <= inst_read_data; + + -- DONE + inst_stage_next <= IDLE; + when others => + null; end case; when GET_INSTANCE_DATA_2 => -- Precondition: inst_addr (Status Info)