library ieee; use ieee.std_logic_1164.all; use ieee.numeric_std.all; entity history_cache is generic ( TIME_BASED_FILTER_QOS : DURATION_TYPE := DEFAULT_TIME_BASED_FILTER_QOS; MAX_INSTANCES : natural := DEFAULT_MAX_INSTANCES; MAX_SAMPLES_PER_INSTANCE : natural := DEFAULT_MAX_SAMPLES_PER_INSTANCE; HISTORY_QOS : std_logic_vector(CDR_ENUMERATION_WIDTH-1 downto 0) := DEFAULT_HISTORY_QOS; RELIABILITY_QOS : std_logic_vector(CDR_ENUMERATION_WIDTH-1 downto 0) := DEFAULT_RELIABILTY_QOS; PRESENTATION_QOS : std_logic_vector(CDR_ENUMERATION_WIDTH-1 downto 0) := DEFAULT_PRESENTATION_QOS; DESTINATION_ORDER_QOS : std_logic_vector(CDR_ENUMERATION_WIDTH-1 downto 0) := DEFAULT_DESTINATION_ORDER_QOS; COHERENT_ACCESS : boolean := DEFAULT_COHERENT_ACCESS; ORDERED_ACCESS : boolean := DEFAULT_ORDERED_ACCESS; ); port ( clk : in std_logic; reset : in std_logic; start_rtps : in std_logic; opcode_rtps : in HISTORY_CACHE_OPCODE_TYPE; res_rtps : out HISTORY_CACHE_RESPOSNE_TYPE; data_in_rtps : in std_logic_vector(WORD_WIDTH-1 downto 0); valid_in_rtps : in std_logic; ready_in_rtps : out std_logic; last_word_in_rtps : in std_logic; -- start_dds : in std_logic; ack_dds : out std_logic; opcode_dds : in HISTORY_CACHE_OPCODE_TYPE; instance_state_in : in std_logic_vector(INSTANCE_STATE_KIND_WIDTH-1 downto 0); view_state_in : in std_logic_vector(VIEW_STATE_KIND_WIDTH-1 downto 0); sample_state_in : in std_logic_vector(SAMPLE_STATE_KIND_WIDTH-1 downto 0); instance_handle_in : in INSTANCE_HANDLE_TYPE; max_samples_in : in std_logic_vector(MAX_SAMPLES_WIDTH-1 downto 0); next_sample : in std_logic; get_data : in std_logic; done_dds : out std_logic; return_code_dds : out std_logic_vector(RETURN_CODE_WIDTH-1 downto 0); -- Sample Info si_sample_state : out std_logic_vector(SAMPLE_STATE_KIND_WIDTH-1 downto 0); si_view_state : out std_logic_vector(VIEW_STATE_KIND_WIDTH-1 downto 0); si_instance_state : out std_logic_vector(INSTANCE_STATE_KIND_WIDTH-1 downto 0); si_source_timestamp : out TIME_TYPE; si_instance_handle : out INSTANCE_HANDLE_TYPE; si_publication_handle : out PUBLICATION_HANDLE_TYPE; si_disposed_generation_count : out std_logic_vector(DISPOSED_GENERATION_COUNT_WIDTH-1 downto 0); si_no_writers_generation_count : out std_logic_vector(NO_WRITERS_GENERATION_COUNT_WIDTH-1 downto 0); si_sample_rank : out std_logic_vector(SAMPLE_RANK_WIDTH-1 downto 0); si_generation_rank : out std_logic_vector(GENERATION_RANK_WIDTH-1 downto 0); si_absolute_generation_count : out std_logic_vector(ABSOLUTE_GENERATION_COUNT_WIDTH-1 downto 0); si_valid_data : out std_logic; si_valid : out std_logic; ready_out_dds : in std_logic; valid_out_dds : out std_logic; data_out_dds : out std_logic_vector(WORD_WIDTH-1 downto 0); last_word_out_dds : out std_logic; status : out std_logic_vector(STATUS_KIND_WIDTH-1 downto 0); ); end entity; architecture arch of history_cache is --*****CONSTANT DECLARATION***** -- Sample Info Memory Size in 4-Byte Words constant SAMPLE_MEMORY_SIZE : natural := TODO; -- Sample Info Memory Address Width constant SAMPLE_MEMORY_ADDR_WIDTH : natural := log2c(SAMPLE_MEMORY_SIZE); -- Highest Sample Info Memory Address constant SAMPLE_MEMORY_MAX_ADDRESS : unsigned(SAMPLE_MEMORY_ADDR_WIDTH-1 downto 0) := to_unsigned(SAMPLE_MEMORY_SIZE-1, SAMPLE_MEMORY_ADDR_WIDTH); -- Highest Sample Info Frame Address constant MAX_SAMPLE_ADDRESS : unsigned(SAMPLE_MEMORY_ADDR_WIDTH-1 downto 0) := SAMPLE_MEMORY_MAX_ADDRESS - SAMPLE_INFO_FRAME_SIZE + 1; -- Payload Memory Size in 4-Byte Words constant PAYLOAD_MEMORY_SIZE : natural := TODO; -- Payload Memory Address Width constant PAYLOAD_MEMORY_ADDR_WIDTH : natural := log2c(PAYLOAD_MEMORY_SIZE); -- Highest Payload Memory Address constant PAYLOAD_MEMORY_MAX_ADDRESS : unsigned(PAYLOAD_MEMORY_ADDR_WIDTH-1 downto 0) := to_unsigned(PAYLOAD_MEMORY_SIZE-1, PAYLOAD_MEMORY_ADDR_WIDTH); -- Highest Payload Frame Address constant MAX_PAYLOAD_ADDRESS : unsigned(PAYLOAD_MEMORY_ADDR_WIDTH-1 downto 0) := PAYLOAD_MEMORY_MAX_ADDRESS - PAYLOAD_FRAME_SIZE + 1; -- Instance Memory Size in 4-Byte Words constant INSTANCE_MEMORY_SIZE : natural := TODO; -- Instance Memory Address Width constant INSTANCE_MEMORY_ADDR_WIDTH : natural := log2c(INSTANCE_MEMORY_SIZE); -- Highest Instance Memory Address constant INSTANCE_MEMORY_MAX_ADDRESS: unsigned(INSTANCE_MEMORY_ADDR_WIDTH-1 downto 0) := to_unsigned(INSTANCE_MEMORY_SIZE-1, INSTANCE_MEMORY_ADDR_WIDTH); -- Highest Instance Frame Address constant MAX_INSTANCE_ADDRESS : unsigned(INSTANCE_MEMORY_ADDR_WIDTH-1 downto 0) := INSTANCE_MEMORY_MAX_ADDRESS - INSTANCE_FRAME_SIZE + 1; -- Address pointing to the beginning of the first Instance Data Frame constant FIRST_INSTANCE_ADDRESS : unsigned(INSTANCE_MEMORY_ADDR_WIDTH-1 downto 0) := (others => '0'); -- *UPDATE INSTANCE FLAG POSITIONS* constant UPDATE_INSTANCE_FLAG_WIDTH : natural := 6; constant STATUS_FLAG : std_logic_vector(0 to UPDATE_INSTANCE_FLAG_WIDTH-1) := (0 => 1, others => '0'); constant SAMPLE_CNT_FLAG : std_logic_vector(0 to UPDATE_INSTANCE_FLAG_WIDTH-1) := (1 => 1, others => '0'); constant DISPOSED_CNT_FLAG : std_logic_vector(0 to UPDATE_INSTANCE_FLAG_WIDTH-1) := (2 => 1, others => '0'); constant NO_WRITERS_CNT_FLAG : std_logic_vector(0 to UPDATE_INSTANCE_FLAG_WIDTH-1) := (3 => 1, others => '0'); constant IGNORE_DEADLINE_FLAG : std_logic_vector(0 to UPDATE_INSTANCE_FLAG_WIDTH-1) := (4 => 1, others => '0'); constant WRITER_BITMAP_FLAG : std_logic_vector(0 to UPDATE_INSTANCE_FLAG_WIDTH-1) := (5 => 1, others => '0'); -- *SAMPLE MEMORY FRAME FORMAT* constant SMF_STATUS_INFO_OFFSET : natural := 0; constant SMF_TIMESTAMP_OFFSET : natural := 1; constant SMF_LIFESPAN_DEADLINE_OFFSET : natural := 3; constant SMF_PAYLOAD_ADDR_OFFSET : natural := 5; constant SMF_INSTANCE_ADDR_OFFSET : natural := 6; constant SMF_DISPOSED_GEN_CNT_OFFSET : natural := 7; constant SMF_NO_WRITERS_GEN_CNT_OFFSET : natural := 8; constant SMF_PREV_ADDR_OFFSET : natural := SMF_NO_WRITERS_GEN_CNT_OFFSET+1; constant SMF_NEXT_ADDR_OFFSET : natural := SMF_PREV_ADDR_OFFSET+1; -- *PAYLOAD MEMORY FRAME FORMAT* constant PMF_NEXT_ADDR_OFFSET : natural := 0; constant PMF_PAYLOAD_OFFSET : natural := 1; -- *INSTANCE MEMORY FRAME OFFSET* constant IMF_NEXT_ADDR_OFFSET : natural := 0; constant IMF_KEY_HASH_OFFSET : natural := 1; constant IMF_STATUS_INFO_OFFSET : natural := 5; constant IMF_SAMPLE_CNT_OFFSET : natural := 6; constant IMF_DISPOSED_GEN_CNT_OFFSET : natural := IMF_SAMPLE_CNT_OFFSET+1 when (MAX_SAMPLES_PER_INSTANCE /= LENGTH_UNLIMITED) else IMF_STATUS_INFO_OFFSET+1; constant IMF_NO_WRITERS_GEN_CNT_OFFSET : natural := IMF_DISPOSED_GEN_CNT_OFFSET+1; constant IMF_IGNORE_DEADLINE_OFFSET : natural := IMF_NO_WRITERS_GEN_CNT_OFFSET+1; constant IMF_WRITER_BITMAP_OFFSET : natural := IMF_IGNORE_DEADLINE_OFFSET+2 when (TIME_BASED_FILTER_QOS /= DURATION_ZERO) else IMF_NO_WRITERS_GEN_CNT_OFFSET+1; --*****TYPE DECLARATION***** -- FSM states. Explained below in detail type STAGE_TYPE is (IDLE, TODO); type INST_STAGE_TYPE is (IDLE, TODO); type INSTANCE_OPCODE_TYPE is (NOP, TODO); type INSTANCE_DATA_TYPE is record key_hash : KEY_HASH_TYPE; status_info : std_logic_vector(WORD_WIDTH-1 downto 0); sample_cnt : unsigned(WORD_WIDTH-1 downto 0); disposed_gen_cnt : unsigned(WORD_WIDTH-1 downto 0); no_writers_gen_cnt : unsigned(WORD_WIDTH-1 downto 0); ignore_deadline : TIME_TYPE; writer_bitmap : ENDPOINT_BITMAP_ARRAY_TYPE; end record; constant ZERO_INSTANCE_DATA : INSTANCE_DATA_TYPE := ( key_hash => (others => (others => '0')), status_info => (others => '0'), sample_cnt => (others => '0'), disposed_gen_cnt => (others => '0'), no_writers_gen_cnt => (others => '0'), ignore_deadline => TIME_INVALID, writer_bitmap => (others => (others => '0')) ); type INST_LATCH_DATA_TYPE is record variant : std_logic; 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); gen_cnt : std_logic_vector(CDR_LONG_WIDTH-1 downto 0); deadline : TIME_TYPE; writer_bitmap : std_logic_vector(0 to ENDPOINT_BITMAP_WIDTH-1); update_flags : std_logic_vector(0 to UPDATE_INSTANCE_FLAG_WIDTH-1); addr : unsigned(INSTANCE_MEMORY_ADDR_WIDTH-1 downto 0); end record; constant ZERO_INST_LATCH_DATA : INST_LATCH_DATA_TYPE := ( variant => '1', key_hash => (others => (others => '0')), status_info => (others => '0'), sample_cnt => (others => '0'), gen_cnt => (others => '0'), deadline => TIME_INVALID, writer_bitmap => (others => (others => '0')), update_flags => (others => '0'), addr => (others => '0') ); --*****SIGNAL DECLARATION signal sample_addr, sample_addr_next : unsigned(SAMPLE_MEMORY_ADDR_WIDTH-1 downto 0) := (others => '0'); signal sample_wen, sample_ren : std_logic := '0'; signal sample_read_data, sample_write_data : std_logic_vector(WORD_WIDTH-1 downto 0) := (others => '0'); signal payload_addr, payload_addr_next : unsigned(PAYLOAD_MEMORY_ADDR_WIDTH-1 downto 0) := (others => '0'); signal payload_wen, payload_ren : std_logic := '0'; signal payload_read_data, payload_write_data : std_logic_vector(WORD_WIDTH-1 downto 0) := (others => '0'); signal inst_addr, inst_addr_next : unsigned(PAYLOAD_MEMORY_ADDR_WIDTH-1 downto 0) := (others => '0'); signal inst_wen, inst_ren : std_logic := '0'; signal inst_read_data, inst_write_data : std_logic_vector(WORD_WIDTH-1 downto 0) := (others => '0'); signal khg_valid_in, khg_ready_in, khg_last_word_in, khg_valid_out, khg_ready_out, khg_last_word_out : std_logic := '0'; signal khg_data_in, khg_data_out : std_logic_vector(WORD_WIDTH-1 downto 0) := (others => '0'); signal stage, stage_next : STAGE_TYPE := IDLE; signal cnt, cnt_next : natural range TODO := 0; signal empty_sample_list_head, empty_sample_list_head_next : unsigned(SAMPLE_MEMORY_ADDR_WIDTH-1 downto 0) := (others => '0'); signal empty_sample_list_tail, empty_sample_list_tail_next : unsigned(SAMPLE_MEMORY_ADDR_WIDTH-1 downto 0) := (others => '0'); signal empty_payload_list_head, empty_payload_list_head_next : unsigned(PAYLOAD_MEMORY_ADDR_WIDTH-1 downto 0) := (others => '0'); signal oldest_sample, oldest_sample_next : unsigned(SAMPLE_MEMORY_ADDR_WIDTH-1 downto 0) := (others => '0'); signal newest_sample, newest_sample_next : unsigned(SAMPLE_MEMORY_ADDR_WIDTH-1 downto 0) := (others => '0'); signal first_unread_sample, first_unread_sample_next : unsigned(SAMPLE_MEMORY_ADDR_WIDTH-1 downto 0) := (others => '0'); signal payload_addr_latch_1, payload_addr_latch_1_next : unsigned(PAYLOAD_MEMORY_ADDR_WIDTH-1 downto 0) := (others => '0'); signal payload_addr_latch_2, payload_addr_latch_2_next : unsigned(PAYLOAD_MEMORY_ADDR_WIDTH-1 downto 0) := (others => '0'); signal sample_addr_latch_1, sample_addr_latch_1_next : unsigned(SAMPLE_MEMORY_ADDR_WIDTH-1 downto 0) := (others => '0'); signal sample_addr_latch_2, sample_addr_latch_2_next : unsigned(SAMPLE_MEMORY_ADDR_WIDTH-1 downto 0) := (others => '0'); signal sample_addr_latch_3, sample_addr_latch_3_next : unsigned(SAMPLE_MEMORY_ADDR_WIDTH-1 downto 0) := (others => '0'); signal ts_latch, ts_latch_next : TIME_TYPE := TIME_INVALID; signal last_read_ts, last_read_ts_next : TIME_TYPE := TIME_INVALID; signal long_latch, long_latch_next : std_logic_vector(CDR_LONG_WIDTH-1 downto 0) := (others => '0'); signal payload_mem_full, payload_mem_full_next : std_logic := '0'; signal sample_mem_full, sample_mem_full_next : std_logic := '0'; signal writer_pos, writer_pos_next : natural range TODO := 0; signal writer_bitmap : ENDPOINT_BITMAP_ARRAY_TYPE; signal status_info_update : std_logic_vector(CDR_LONG_WIDTH-1 downto 0) := (others => '0'); signal key_hash, key_hash_next : KEY_HASH_TYPE := (others => (others => '0')); signal remove_oldest_sample, remove_oldest_sample_next : std_logic := '0'; signal remove_oldest_inst_sample, remove_oldest_inst_sample_next : std_logic := '0'; signal added_new_instance, added_new_instance_next : std_logic := '0'; signal sample_status_info, sample_status_info_next : std_logic_vector(CDR_LONG_WIDTH-1 downto 0) := (others => '0'); signal gen_cnt : unsigned(CDR_LONG_WIDTH-1 downto 0) := (others => '0'); signal deadline : TIME_TYPE := TIME_INVALID; signal inst_addr_update : unsigned(INSTANCE_MEMORY_ADDR_WIDTH-1 downto 0) := (others => '0'); signal sample_cnt : unsigned(CDR_LONG_WIDTH-1 downto 0) := (others => '0'); signal inst_op_start : std_logic := '0'; signal inst_op_done : std_logic := '0'; signal inst_opcode : INSTANCE_OPCODE_TYPE := NOP; signal inst_stage, inst_stage_next : INST_STAGE_TYPE := IDLE; signal inst_addr_base, inst_addr_base_next : unsigned(INSTANCE_MEMORY_ADDR_WIDTH-1 downto 0) := (others => '0'); signal inst_next_addr_base, inst_next_addr_base_next : unsigned(INSTANCE_MEMORY_ADDR_WIDTH-1 downto 0) := (others => '0'); signal inst_prev_addr_base, inst_prev_addr_base_next : unsigned(INSTANCE_MEMORY_ADDR_WIDTH-1 downto 0) := (others => '0'); signal inst_empty_head, inst_empty_head_next : unsigned(INSTANCE_MEMORY_ADDR_WIDTH-1 downto 0) := (others => '0'); signal inst_occupied_head, inst_occupied_head_next : unsigned(INSTANCE_MEMORY_ADDR_WIDTH-1 downto 0) := (others => '0'); signal inst_latch_data, inst_latch_data_next : INST_LATCH_DATA_TYPE := ZERO_INST_LATCH_DATA; signal update_inst_flags : std_logic_vector(0 to UPDATE_INSTANCE_FLAG_WIDTH-1) := (others => '0'); signal inst_cnt, inst_cnt_next : natural range TODO := 0; signal inst_mem_full, inst_mem_full_next : std_logic := '0'; signal inst_delete_lock, inst_delete_lock_next : std_logic := '0'; signal inst_atomic_lock : std_logic := '0'; signal inst_long_latch_1, inst_long_latch_1_next : std_logic_vector(CDR_LONG_WIDTH-1 downto 0) := (others => '0'); signal inst_long_latch_2, inst_long_latch_2_next : std_logic_vector(CDR_LONG_WIDTH-1 downto 0) := (others => '0'); signal si_sample_state_sig, si_sample_state_sig_next : std_logic_vector(SAMPLE_STATE_KIND_WIDTH-1 downto 0) := (others => '0'); signal si_view_state_sig, si_view_state_sig_next : std_logic_vector(VIEW_STATE_KIND_WIDTH-1 downto 0) := (others => '0'); signal si_instance_state_sig, si_instance_state_sig_next : std_logic_vector(INSTANCE_STATE_KIND_WIDTH-1 downto 0) := (others => '0'); signal si_source_timestamp_sig, si_source_timestamp_sig_next : TIME_TYPE := TIME_INVALID; signal si_instance_handle_sig, si_instance_handle_sig_next : INSTANCE_HANDLE_TYPE := (others => (others => '0')); signal si_publication_handle_sig, si_publication_handle_sig_next : PUBLICATION_HANDLE_TYPE := (others => (others => '0')); signal si_disposed_generation_count_sig, si_disposed_generation_count_sig_next : unsigned(DISPOSED_GENERATION_COUNT_WIDTH-1 downto 0) := (others => '0'); signal si_no_writers_generation_count_sig, si_no_writers_generation_count_sig_next : unsigned(NO_WRITERS_GENERATION_COUNT_WIDTH-1 downto 0) := (others => '0'); signal si_sample_rank_sig, si_sample_rank_sig_next : unsigned(SAMPLE_RANK_WIDTH-1 downto 0) := (others => '0'); signal si_generation_rank_sig, si_generation_rank_sig_next : unsigned(GENERATION_RANK_WIDTH-1 downto 0) := (others => '0'); signal si_absolute_generation_count_sig, si_absolute_generation_count_sig_next : unsigned(ABSOLUTE_GENERATION_COUNT_WIDTH-1 downto 0) := (others => '0'); signal si_valid_data_sig, si_valid_data_sig_next : std_logic := '0'; signal si_valid_sig, si_valid_sig_next : std_logic := '0'; signal sample_state, sample_state_next : std_logic_vector(SAMPLE_STATE_KIND_WIDTH-1 downto 0) := (others => '0'); signal view_state, view_state_next : std_logic_vector(VIEW_STATE_KIND_WIDTH-1 downto 0) := (others => '0'); signal instance_state, instance_state_next : std_logic_vector(INSTANCE_STATE_KIND_WIDTH-1 downto 0) := (others => '0'); signal instance_handle, instance_handle_next : INSTANCE_HANDLE_TYPE := (others => '0'); signal max_samples, max_samples_next : unsigned(MAX_SAMPLES_WIDTH-1 downto 0) := (others => '0'); signal inst_addr_latch, inst_addr_latch_next : unsigned(INSTANCE_MEMORY_ADDR_WIDTH-1 downto 0) := (others => '0'); signal collection_cnt, collection_cnt_next : unsigned(MAX_SAMPLES_WIDTH-1 downto 0) := (others => '0'); signal collection_cnt_max, collection_cnt_max_next : unsigned(MAX_SAMPLES_WIDTH-1 downto 0) := (others => '0'); signal collection_generation_rank, collection_generation_rank_next : unsigned(GENERATION_RANK_WIDTH-1 downto 0) := (others => '0'); signal cur_generation_rank, cur_generation_rank_next : unsigned(GENERATION_RANK_WIDTH-1 downto 0) := (others => '0'); signal is_take, is_take_next : std_logic := '0'; signal has_latched, has_lacthed_next : std_logic := '0'; signal single_instance, single_instance_next : std_logic := '0'; -- NOTE: We use this signal to prevent the costly Instance Marking in the case that we only need to ouptput next sample. -- I.e. make READ_NEXT/TAKE_NEXT the fastest commands. 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 abort_khg : std_logic := '0'; signal status_sig, status_sig_next : std_logic_vector(STATUS_KIND_WIDTH-1 downto 0) := (others => '0'); signal sample_rej_cnt, sample_rej_cnt_next : unsigned(SAMPLE_REJECTED_STATUS_COUNT_WIDTH-1 downto 0) := (others => '0'); 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')); --*****ALIAS DECLARATION***** alias prev_sample : unsigned(SAMPLE_MEMORY_ADDR_WIDTH-1 downto 0) is sample_addr_latch_1; alias prev_sample_next : unsigned(SAMPLE_MEMORY_ADDR_WIDTH-1 downto 0) is sample_addr_latch_1_next; alias first_sample : unsigned(SAMPLE_MEMORY_ADDR_WIDTH-1 downto 0) is sample_addr_latch_1; alias first_sample_next : unsigned(SAMPLE_MEMORY_ADDR_WIDTH-1 downto 0) is sample_addr_latch_1_next; alias next_sample : unsigned(SAMPLE_MEMORY_ADDR_WIDTH-1 downto 0) is sample_addr_latch_2; alias next_sample_next : unsigned(SAMPLE_MEMORY_ADDR_WIDTH-1 downto 0) is sample_addr_latch_2_next; alias cur_sample : unsigned(SAMPLE_MEMORY_ADDR_WIDTH-1 downto 0) is sample_addr_latch_3; alias cur_sample_next : unsigned(SAMPLE_MEMORY_ADDR_WIDTH-1 downto 0) is sample_addr_latch_3_next; alias cur_payload : unsigned(PAYLOAD_MEMORY_ADDR_WIDTH-1 downto 0) is payload_addr_latch_1; alias cur_payload_next : unsigned(PAYLOAD_MEMORY_ADDR_WIDTH-1 downto 0) is payload_addr_latch_1_next; alias next_payload : unsigned(PAYLOAD_MEMORY_ADDR_WIDTH-1 downto 0) is payload_addr_latch_1; alias next_payload_next : unsigned(PAYLOAD_MEMORY_ADDR_WIDTH-1 downto 0) is payload_addr_latch_1_next; alias cur_inst : unsigned(INSTANCE_MEMORY_ADDR_WIDTH-1 downto 0) is inst_addr_latch_1; alias cur_inst_next : unsigned(INSTANCE_MEMORY_ADDR_WIDTH-1 downto 0) is inst_addr_latch_1_next; alias next_inst : unsigned(INSTANCE_MEMORY_ADDR_WIDTH-1 downto 0) is inst_addr_latch_2; alias next_inst_next : unsigned(INSTANCE_MEMORY_ADDR_WIDTH-1 downto 0) is inst_addr_latch_2_next; alias has_data : std_logic is sample_status_info(PAYLOAD_FLAG); alias has_key_hash : std_logic is sample_status_info(KEY_HASH_FLAG); -- *FUNCTION DECLARATION* function to_unsigned(input : KEY_HASH_TYPE) return unsigned is variable ret : unsigned((KEY_HASH_WIDTH*WORD_WIDTH)-1 downto 0) := (others => '0'); begin for i in 0 to KEY_HASH_WIDTH-1 loop ret(((KEY_HASH_WIDTH-i)*WORD_WIDTH)-1 downto (KEY_HASH_WIDTH-1-i)*WORD_WIDTH) := input(i); end loop; return ret; end function; begin sample_ram_inst : entity work.single_port_ram(arch) generic map ( ADDR_WIDTH => SAMPLE_MEMORY_ADDR_WIDTH, DATA_WIDTH => WORD_WIDTH, MEMORY_DEPTH => SAMPLE_MEMORY_SIZE ) port map ( clk => clk, addr => sample_addr, wen => sample_wen, ren => sample_ren, wr_data => sample_write_data, rd_data => sample_read_data ); payload_ram_inst : entity work.single_port_ram(arch) generic map ( ADDR_WIDTH => PAYLOAD_MEMORY_ADDR_WIDTH, DATA_WIDTH => WORD_WIDTH, MEMORY_DEPTH => PAYLOAD_MEMORY_SIZE ) port map ( clk => clk, addr => payload_addr, wen => payload_wen, ren => payload_ren, wr_data => payload_write_data, rd_data => payload_read_data ); instance_ram_inst : entity work.single_port_ram(arch) generic map ( ADDR_WIDTH => INSTANCE_MEMORY_ADDR_WIDTH, DATA_WIDTH => WORD_WIDTH, MEMORY_DEPTH => INSTANCE_MEMORY_SIZE ) port map ( clk => clk, addr => inst_addr, wen => inst_wen, ren => inst_ren, wr_data => inst_write_data, rd_data => inst_read_data ); key_hash_generator_inst : entity work.key_hash_generator(arch) port ( clk => clk, reset => reset or abort_khg, data_in => khg_data_in, valid_in => khg_valid_in, ready_in => khg_ready_in, last_word_in => khg_last_word_in, data_out => khg_data_out, valid_out => khg_valid_out, ready_out => khg_ready_out, last_word_out => khg_last_word_out ); parse_a_prc : process (all) variable tmp_dw : DOUBLE_WORD_ARRAY := (others => (others => '0')); variable tmp_bitmap : std_logic_vector(0 to ENDPOINT_BITMAP_WIDTH-1) := (others => '0'); variable tmp_update : std_logic_vector(0 to UPDATE_INSTANCE_FLAG_WIDTH-1) := (others => '0'); variable tmp_bool : boolean := FALSE; begin -- Default stage_next <= stage; res_rtps <= UNDEFINED; sample_addr_next <= sample_addr; sample_write_data <= (others => '0'); sample_ren <= '0'; sample_wen <= '0'; payload_addr_next <= payload_addr; payload_write_data <= (others => '0'); payload_ren <= '0'; payload_wen <= '0'; ready_in_rtps <= '0'; newest_sample_next <= newest_sample; empty_payload_list_head_next <= empty_payload_list_head; empty_sample_list_head_next <= empty_sample_list_head; empty_sample_list_tail_next <= empty_sample_list_tail; payload_addr_latch_1_next <= payload_addr_latch_1; payload_addr_latch_2_next <= payload_addr_latch_2; ts_latch_next <= ts_latch; long_latch_next <= long_latch; sample_addr_latch_1_next <= sample_addr_latch_1; sample_addr_latch_2_next <= sample_addr_latch_2; payload_mem_full_next <= payload_mem_full; sample_mem_full_next <= sample_mem_full; writer_pos_next <= writer_pos; inst_opcode <= NOP; key_hash_next <= key_hash; sample_status_info_next <= sample_status_info; inst_op_start <= '0'; khg_last_word_in <= '0'; khg_data_in <= (others => '0'); khg_valid_in <= '0'; khg_ready_out <= '0'; writer_bitmap <= (others => '0'); inst_addr_update <= (others => '0'); remove_oldest_sample_next <= remove_oldest_sample; remove_oldest_inst_sample_next <= remove_oldest_inst_sample; added_new_instance_next <= added_new_instance; si_sample_state_sig_next <= si_sample_state; si_view_state_sig_next <= si_view_state_sig; si_instance_state_sig_next <= si_instance_state_sig; si_source_timestamp_sig_next <= si_source_timestamp_sig; si_instance_handle_sig_next <= si_instance_handle_sig; si_publication_handle_sig_next <= si_publication_handle_sig; si_disposed_generation_count_sig_next <= si_disposed_generation_count_sig; si_no_writers_generation_count_sig_next <= si_no_writers_generation_count_sig; si_sample_rank_sig_next <= si_sample_rank_sig; si_generation_rank_sig_next <= si_generation_rank_sig; si_absolute_generation_count_sig_next <= si_absolute_generation_count_sig; si_valid_data_sig_next <= si_valid_data_sig; si_valid_sig_next <= si_valid_sig_next; sample_state_next <= sample_state; view_state_next <= view_state; instance_state_next <= instance_state; instance_handle_next <= instance_handle; max_samples_next <= max_samples; inst_addr_latch_1_next <= inst_addr_latch_1; inst_addr_latch_2_next <= inst_addr_latch_2; collection_cnt_next <= collection_cnt; collection_cnt_max_next <= collection_cnt_max; collection_generation_rank_next <= collection_generation_rank; cur_generation_rank_next <= cur_generation_rank; is_take_next <= is_take; has_lacthed_next <= has_latched; single_instance_next <= single_instance; single_sample_next <= single_sample; unmark_instances_next <= unmark_instances; is_first_instance_sample_next <= is_first_instance_sample; dynamic_next_instance_next <= dynamic_next_instance; last_read_ts_next <= last_read_ts; sample_rej_cnt_next <= sample_rej_cnt; 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; ack_dds <= '0'; inst_data_variant <= '0'; done_dds <= '0'; abort_khg <= '0'; return_code_dds <= RETCODE_UNSUPPORTED; status_sig_next <= status_sig; case (stage) is when IDLE => -- DEFAULT ready_in_rtps <= '1'; -- Reset remove_oldest_inst_sample_next <= '0'; remove_oldest_sample_next <= '0'; added_new_instance_next <= '0'; is_take_next <= '0'; if (start_rtps = '1') then case (opcode_rtps) is when ADD_CHANGE => -- This Operation does not accept input at this time ready_in_rtps <= '0'; res_rtps <= ACK; stage_next <= ADD_SAMPLE_INFO; cur_sample_next <= empty_sample_list_head; sample_addr_next <= empty_sample_list_head; cnt_next <= 0; end if; when REMOVE_WRITER => -- Input and Memory Gurad if (valid_in_rtps = '1' and inst_op_done = '1') then -- Latch Writer Pos writer_pos_next <= to_integer(unsigned(data_in_rtps)); inst_op_start <= '1'; inst_opcode <= GET_FIRST_INSTANCE; inst_data_variant <= '0'; stage_next <= REMOVE_WRITER; res_rtps <= ACK; end if; when others => null; end case; elsif (unmark_instances = '1') then -- Memory Operation Guard if (inst_op_done = '1') then inst_op_start <= '1'; inst_opcode <= UNMARK_INTANCES; unmark_instances_next <= '0'; end if; elsif (start_dds = '1') then -- Latch Input Signals sample_state_next <= sample_state_in; view_state_next <= view_state_in; instance_state_next <= instance_state; max_samples_next <= unsigned(max_samples_in); -- Reset single_instance_next <= '0'; single_instance_next <= '0'; collection_cnt_next <= 0; collection_cnt_max_next <= 0; is_first_instance_sample_next <= '1'; si_sample_state_sig_next <= (others => '0'); si_view_state_sig_next <= (others => '0'); si_instance_state_sig_next <= (others => '0'); si_source_timestamp_sig_next <= TIME_ZERO; si_instance_handle_sig_next <= (others => (others => '0')); si_publication_handle_sig_next <= (others => (others => '0')); si_sample_rank_sig_next <= (others => '0'); si_generation_rank_sig_next <= (others => '0'); si_valid_data_sig_next <= '0'; si_valid_sig_next <= '0'; si_absolute_generation_count_sig_next <= (others => '0'); si_disposed_generation_count_sig_next <= (others => '0'); si_no_writers_generation_count_sig_next <= (others => '0'); case (opcode_dds) is when READ => ack_dds <= '1'; cur_sample_next <= oldest_sample; sample_addr_next <= oldest_sample + SMF_STATUS_INFO_OFFSET; cur_inst_next <= INSTANCE_MEMORY_MAX_ADDRESS; stage_next <= GET_NEXT_SAMPLE; cnt_next <= 0; when TAKE => is_take_next <= '1'; ack_dds <= '1'; cur_sample_next <= oldest_sample; sample_addr_next <= oldest_sample + SMF_STATUS_INFO_OFFSET; cur_inst_next <= INSTANCE_MEMORY_MAX_ADDRESS; stage_next <= GET_NEXT_SAMPLE; cnt_next <= 0; when READ_NEXT_SAMPLE => ack_dds <= '1'; single_sample_next <= '1'; cur_sample_next <= oldest_sample; sample_addr_next <= oldest_sample + SMF_STATUS_INFO_OFFSET; cur_inst_next <= INSTANCE_MEMORY_MAX_ADDRESS; sample_state_next <= NOT_READ_SAMPLE_STATE; view_state_next <= ANY_VIEW_STATE; instance_state_next <= ALIVE_INSTANCE_STATE; max_samples_next <= to_unsigned(1, max_samples'length); stage_next <= GET_NEXT_SAMPLE; cnt_next <= 0; when TAKE_NEXT_SAMPLE => ack_dds <= '1'; is_take_next <= '1'; single_sample_next <= '1'; cur_sample_next <= oldest_sample; sample_addr_next <= oldest_sample + SMF_STATUS_INFO_OFFSET; cur_inst_next <= INSTANCE_MEMORY_MAX_ADDRESS; sample_state_next <= NOT_READ_SAMPLE_STATE; view_state_next <= ANY_VIEW_STATE; instance_state_next <= ALIVE_INSTANCE_STATE; max_samples_next <= to_unsigned(1, max_samples'length); stage_next <= GET_NEXT_SAMPLE; cnt_next <= 0; when READ_INSTANCE => ack_dds <= '1'; single_instance_next <= '1'; cur_sample_next <= oldest_sample; sample_addr_next <= oldest_sample + SMF_STATUS_INFO_OFFSET; key_hash_next <= instance_handle_in; stage_next <= CHECK_INSTANCE; cnt_next <= 0; when TAKE_INSTANCE => ack_dds <= '1'; is_take_next <= '1'; single_instance_next <= '1'; cur_sample_next <= oldest_sample; sample_addr_next <= oldest_sample + SMF_STATUS_INFO_OFFSET; key_hash_next <= instance_handle_in; stage_next <= CHECK_INSTANCE; cnt_next <= 0; when READ_NEXT_INSTANCE => ack_dds <= '1'; single_instance_next <= '1'; dynamic_next_instance_next <= '1'; cur_sample_next <= oldest_sample; sample_addr_next <= oldest_sample + SMF_STATUS_INFO_OFFSET; key_hash_next <= instance_handle_in; stage_next <= FIND_NEXT_INSTANCE; cnt_next <= 0; when TAKE_NEXT_INSTANCE => ack_dds <= '1'; is_take_next <= '1'; single_instance_next <= '1'; dynamic_next_instance_next <= '1'; cur_sample_next <= oldest_sample; sample_addr_next <= oldest_sample + SMF_STATUS_INFO_OFFSET; key_hash_next <= instance_handle_in; stage_next <= FIND_NEXT_INSTANCE; cnt_next <= 0; when GET_SAMPLE_REJECTED_STATUS => ack_dds <= '1'; stage_next <= GET_SAMPLE_REJECTED_STATUS; when others => ack_dds <= '1'; stage_next <= UNKNOWN_OPERATION; end case; end if; when UNKNOWN_OPERATION => done_dds <= '1'; return_code_dds <= RETCODE_UNSUPPORTED; -- DONE stage_next <= IDLE; when ADD_SAMPLE_INFO => -- Precondition: sample_addr (empty_sample_list_head) ready_in_rtps <= '1'; -- Input Guard if (valid_in_rtps = '1') then cnt_next <= cnt + 1; sample_addr_next <= sample_addr + 1; -- Write Through sample_wen <= '1'; sample_write_data <= data_in_rtps; case (cnt) is -- Status Info when 0 => -- Initialize local status bits sample_write_data(READ_FLAG) <= '0'; -- Latch Status Info sample_status_info_next <= data_in_rtps; sample_status_info_next(READ_FLAG) <= '0'; -- Latch Timestamp for ordering -- Timestamp 1/2 when 1 => ts_latch_next(0) <= data_in_rtps; -- Timestamp 2/2 when 2 => ts_latch_next(1) <= data_in_rtps; -- Synthesis Guard if (DESTINATION_ORDER_QOS = BY_SOURCE_TIMESTAMP_DESTINATION_ORDER_QOS) then -- Check Timestamp tmp_dw := (0 => ts_latch(0), 1 => unsigned(data_in_rtps)); -- NOTE: Equal timestamps are still acceptable, as they are inserted after the -- highest last read sample. -- Timestamp is smaller than highest last read (Or is Invalid) if (tmp_dw /= TIME_INVALID or tmp_dw < last_read_ts) then -- Drop Sample stage_next <= SKIP_ADD_DROP; end if; end if; -- Lifespan Deadline 2/2 when 4 => -- Skip Key Hash, if not available if (has_key_hash = '0') then cnt_next <= 9; end if; -- Latch Key Hash -- Key Hash 1/4 when 5 => -- Latch Input, but do not pass to Memory sample_wen <= '0'; sample_addr_next <= sample_addr; -- Keep Addr (Payload Addr) key_hash_next(0) <= data_in_rtps; -- Key Hash 2/4 when 6 => -- Latch Input, but do not pass to Memory sample_wen <= '0'; sample_addr_next <= sample_addr; -- Keep Addr (Payload Addr) key_hash_next(1) <= data_in_rtps; -- Key Hash 3/4 when 7 => -- Latch Input, but do not pass to Memory sample_wen <= '0'; sample_addr_next <= sample_addr; -- Keep Addr (Payload Addr) key_hash_next(2) <= data_in_rtps; -- Key Hash 4/4 when 8 => -- Latch Input, but do not pass to Memory sample_wen <= '0'; sample_addr_next <= sample_addr; -- Keep Addr (Payload Addr) key_hash_next(3) <= data_in_rtps; -- Writer Endpoint Position when 9 => -- Latch Input, but do not pass to Memory writer_pos_next <= to_integer(unsigned(data_in_rtps)); sample_wen <= '0'; sample_addr_next <= sample_addr; -- Keep Addr (Payload Addr) stage_next <= ADD_PAYLOAD_ADDRESS; when others => null; end case; end if; when ADD_PAYLOAD_ADDRESS => -- Precondition: sample_addr (Payload Address) sample_addr_next <= cur_sample + SMF_INSTANCE_ADDR_OFFSET; if (has_data = '1') then -- Store Payload Address sample_wen <= '1'; sample_write_data <= empty_payload_list_head; payload_addr_next <= empty_payload_list_head + PMF_PAYLOAD_OFFSET; cur_payload_next <= empty_payload_list_head; else -- Mark Sample with no Payload sample_wen <= '1'; sample_write_data <= PAYLOAD_MEMORY_MAX_ADDRESS; end if; -- If Key Hash is available, start the Instance Search first if (has_key_hash = '1') then stage_next <= INITIATE_INSTANCE_SEARCH; else stage_next <= ADD_PAYLOAD; cnt_next <= 0; end if; when ADD_PAYLOAD => -- Precondition (if has_data = '1'): cur_payload set (Current Slot), payload_addr (Beginning of Payload Data of cur_payload) -- NOTE: This state is responsible for reading the payload and writing it through to the local payload memory -- and key hash generator (KHG). This state is taken on following cases: -- has_data has_key_hash -- 1 1 The payload is written to memory -- 1 0 The payload is written to memory and the KHG at the same time (KHG controls the flow) -- 0 0 There is no payload to write, but the input contains the key for the KHG if (has_key_hash = '0') then ready_in_rtps <= khg_ready_in; else ready_in_rtps <= '1'; end if; -- Flow Control Guard if ((valid_in_rtps = '1' and has_key_hash = '1') or (valid_in_rtps = '1' and has_key_hash = '0' and khg_ready_in = '1')) then cnt_next <= cnt + 1; payload_addr_next <= payload_addr + 1; -- Payload Write if (has_data = '1') then payload_write_data <= data_in_rtps; payload_wen <= '1'; end if; -- Key Hash Generator Write if (has_key_hash = '0') then khg_data_in <= data_in_rtps; khg_valid_in <= '1'; end if; -- End of Payload if (last_word_in_rtps = '1') then khg_last_word_in <= '1'; -- Payload Slot not full if (has_data = '1' and cnt /= PAYLOAD_FRAME_SIZE-2) then -- Zero Rest of Payload Slot stage_next <= ZERO_PAYLOAD; else if (has_key_hash = '0') then -- Fetch the Key Hash stage_next <= GET_KEY_HASH; cnt_next <= 0; else stage_next <= FILTER_STAGE; end if; end if; -- End of Payload Slot elsif (has_data = '1' and cnt = PAYLOAD_FRAME_SIZE-2) then stage_next <= NEXT_PAYLOAD_SLOT; payload_addr_next <= cur_payload + PMF_NEXT_ADDR_OFFSET; cnt_next <= 0; end if; end if; when NEXT_PAYLOAD_SLOT => -- Precondition: payload_addr (Next Pointer of cur_payload) cnt_next <= cnt + 1; case (cnt) is -- Preload when 0 => payload_ren <= '1'; when 1 => -- No Empty Payload Slots available if (payload_read_data = PAYLOAD_MEMORY_MAX_ADDRESS) then -- Reject Change stage_next <= SKIP_ADD_REJECT; -- Abort Key Hash Generation abort_khg <= '1'; else -- Latch next Payload Slot and Continue cur_payload_next <= payload_read_data; payload_addr_next <= payload_read_data + PMF_PAYLOAD_OFFSET; stage_next <= ADD_PAYLOAD; end if; when others => null; end case; when ZERO_PAYLOAD => cnt_next <= cnt + 1; payload_addr_next <= payload_addr + 1; -- Zero Payload payload_write_data <= (others => '0'); payload_wen <= '1'; -- Exit Condition if (cnt = PAYLOAD_FRAME_SIZE-2) then if (has_key_hash = '0') then stage_next <= GET_KEY_HASH; cnt_next <= 0; else stage_next <= FILTER_STAGE; end if; end if; when GET_KEY_HASH => khg_ready_out <= '1'; if (khg_valid_out = '1') then cnt_next <= cnt + 1; -- Latch Key Hash key_hash_next(cnt) <= khg_data_out; -- Exit Condition if (khg_last_word_out = '1') then -- DONE stage_next <= INITIATE_INSTANCE_SEARCH; end if; end if; when INITIATE_INSTANCE_SEARCH => -- Memory Operation Guard if (inst_op_done = '1') then inst_opcode <= SEARCH_INSTANCE_HASH; inst_op_start <= '1'; inst_data_variant <= '0'; -- Payload not yet stored if (has_data = '1') then stage_next <= ADD_PAYLOAD; cnt_next <= 0; else stage_next <= FILTER_STAGE; end if; end if; when FILTER_STAGE => -- Precondition: sample_addr (Instance Address of New Sample) -- Wait for Instance Search to finish if (inst_op_done = '1') then sample_addr_next <= cur_sample + SMF_DISPOSED_GEN_CNT_OFFSET; cur_inst_next <= inst_addr_base; -- Instance Found if (inst_addr_base /= INSTANCE_MEMORY_MAX_ADDRESS) then -- Store Instance Address sample_write_data <= inst_addr_base; sample_wen <= '1'; -- TIME_BASED_FILTER QOS if (TIME_BASED_FILTER_QOS /= DURATION_ZERO and time <= inst_data.ignore_deadline) then -- Drop Change res_rtps <= ACCEPTED; stage_next <= IDLE; -- RESOURCE_LIMITS_QOS (MAX_SAMPLES_PER_INSTANCE) elsif (MAX_SAMPLES_PER_INSTANCE /= LENGTH_UNLIMITED and inst_data.sample_cnt = MAX_SAMPLES_PER_INSTANCE) then if (HISTORY_QOS = KEEP_LAST_HISTORY_QOS and RELIABILITY_QOS = RELIABLE_RELIABILITY_QOS) then -- Reject Change res_rtps <= REJECTED; stage_next <= IDLE; -- Update Sample Reject Status status_sig_next(SAMPLE_REJECTED_STATUS) <= '1'; sample_rej_cnt_next <= sample_rej_cnt + 1; sample_rej_cnt_change_next <= sample_rej_cnt_change + 1; sample_rej_last_reason_next <= REJECTED_BY_SAMPLES_PER_INSTANCE_LIMIT; sample_rej_last_inst_next <= key_hash; else -- Accept Change (Remove Oldest Instance Sample) remove_oldest_inst_sample_next <= '1'; res_rtps <= ACCEPTED; stage_next <= UPDATE_INSTANCE; end if; -- RESOURCE_LIMITS_QOS (MAX_SAMPLES) elsif (empty_sample_list_head = empty_sample_list_tail) then if (HISTORY_QOS = KEEP_ALL_HISTORY_QOS and RELIABILITY_QOS = RELIABLE_RELIABILITY_QOS) then -- Reject Change res_rtps <= REJECTED; stage_next <= IDLE; -- Update Sample Reject Status status_sig_next(SAMPLE_REJECTED_STATUS) <= '1'; sample_rej_cnt_next <= sample_rej_cnt + 1; sample_rej_cnt_change_next <= sample_rej_cnt_change + 1; sample_rej_last_reason_next <= REJECTED_BY_SAMPLES_LIMIT; sample_rej_last_inst_next <= key_hash; else -- Accept Change (Remove Oldest Sample) remove_oldest_sample_next <= '1'; res_rtps <= ACCEPTED; stage_next <= UPDATE_INSTANCE; end if; else -- Accept Change res_rtps <= ACCEPTED; stage_next <= UPDATE_INSTANCE; end if; else -- Store Instance Address sample_write_data <= inst_empty_head; sample_wen <= '1'; -- RESOURCE_LIMITS_QOS (MAX_INSTANCES) (Instance Memory Full) if (inst_empty_head = INSTANCE_MEMORY_MAX_ADDRESS) then -- Reject Change res_rtps <= REJECTED; stage_next <= IDLE; -- Update Sample Reject Status status_sig_next(SAMPLE_REJECTED_STATUS) <= '1'; sample_rej_cnt_next <= sample_rej_cnt + 1; sample_rej_cnt_change_next <= sample_rej_cnt_change + 1; sample_rej_last_reason_next <= REJECTED_BY_INSTANCES_LIMIT; sample_rej_last_inst_next <= key_hash; -- RESOURCE_LIMITS_QOS (MAX_SAMPLES) elsif (empty_sample_list_head = empty_sample_list_tail) then if (HISTORY_QOS = KEEP_ALL_HISTORY_QOS and RELIABILITY_QOS = RELIABLE_RELIABILITY_QOS) then -- Reject Change res_rtps <= REJECTED; stage_next <= IDLE; -- Update Sample Reject Status status_sig_next(SAMPLE_REJECTED_STATUS) <= '1'; sample_rej_cnt_next <= sample_rej_cnt + 1; sample_rej_cnt_change_next <= sample_rej_cnt_change + 1; sample_rej_last_reason_next <= REJECTED_BY_SAMPLES_LIMIT; sample_rej_last_inst_next <= key_hash; else -- Accept Change (Remove Oldest Sample) remove_oldest_sample_next <= '1'; res_rtps <= ACCEPTED; -- Only Insert Sample/Instance if Instance is ALIVE if (sample_status_info(DISPOSED_FLAG) /= '1' and sample_status_info(UNREGISTERED_FLAG) /= '1' and sample_status_info(FILTERED_FLAG) /= '1') then -- Insert New Instance inst_opcode <= INSERT_INSTANCE; inst_op_start <= '1'; added_new_instance_next <= '1'; if (has_data = '1') then payload_addr_next <= cur_payload; stage_next <= FINALIZE_PAYLOAD; cnt_next <= 0; else stage_next <= PRE_SAMPLE_FINALIZE; cnt_next <= 0; end if; else -- Drop Change stage_next <= IDLE; end if; end if; else -- Accept Change res_rtps <= ACCEPTED; -- Only Insert Sample/Instance if Instance is ALIVE if (sample_status_info(DISPOSED_FLAG) /= '1' and sample_status_info(UNREGISTERED_FLAG) /= '1' and sample_status_info(FILTERED_FLAG) /= '1') then -- Insert New Instance inst_opcode <= INSERT_INSTANCE; inst_op_start <= '1'; if (has_data = '1') then payload_addr_next <= cur_payload; stage_next <= FINALIZE_PAYLOAD; cnt_next <= 0; else stage_next <= PRE_SAMPLE_FINALIZE; cnt_next <= 0; end if; else -- Drop Change stage_next <= IDLE; end if; end if; end if; end if; when UPDATE_INSTANCE => -- Memory Operation Guard if (inst_op_done = '1') then -- DEFAULT tmp_update := (others => '0'); -- Instance DISPOSED if (sample_status_info(DISPOSED_FLAG) = '1') then -- ALIVE -> NOT_ALIVE_DISPOSED Transition if (inst_data.status_info(NOT_ALIVE_DISPOSED_FLAG) /= '1' and inst_data.status_info(NOT_ALIVE_NO_WRITERS_FLAG) /= '1') then -- STATUS INFO tmp_update <= tmp_update or STATUS_FLAG; status_info_update <= inst_data.status; status_info_update(NOT_ALIVE_DISPOSED_FLAG) <= '1'; status_info_update(NOT_ALIVE_NO_WRITERS_FLAG) <= '0'; status_info_update(LIVELINESS_FLAG) <= '1'; end if; -- WRITER BITMAP -- Convert Writer Bitmap to SLV tmp_bitmap := to_endpoint_bitmap(inst_data.writer_bitmap); -- Remove Writer tmp_bitmap(writer_pos) := '0'; -- Convert Back writer_bitmap <= from_endpoint_bitmap(tmp_bitmap); tmp_update := tmp_update or WRITER_BITMAP_FLAG; -- Instance UNREGISTERED elsif (sample_status_info(UNREGISTERED_FLAG) = '1') then -- WRITER BITMAP -- Convert Writer Bitmap to SLV tmp_bitmap := to_endpoint_bitmap(inst_data.writer_bitmap); -- Remove Writer tmp_bitmap(writer_pos) := '0'; -- Convert Back writer_bitmap <= from_endpoint_bitmap(tmp_bitmap); tmp_update := tmp_update or WRITER_BITMAP_FLAG; -- ALIVE -> NOT_ALIVE_NO_WRITERS Transition if (inst_data.status_info(NOT_ALIVE_DISPOSED_FLAG) /= '1' and inst_data.status_info(NOT_ALIVE_NO_WRITERS_FLAG) /= '1' and tmp_bitmap = (tmp_bitmap => '0')) then -- STATUS INFO tmp_update <= tmp_update or STATUS_FLAG; status_info_update <= inst_data.status; status_info_update(NOT_ALIVE_DISPOSED_FLAG) <= '0'; status_info_update(NOT_ALIVE_NO_WRITERS_FLAG) <= '1'; status_info_update(LIVELINESS_FLAG) <= '1'; end if; -- Instance ALIVE/FILTERED else -- STATUS INFO tmp_update <= tmp_update or STATUS_FLAG; status_info_update <= inst_data.status; status_info_update(NOT_ALIVE_DISPOSED_FLAG) <= '0'; status_info_update(NOT_ALIVE_NO_WRITERS_FLAG) <= '0'; status_info_update(LIVELINESS_FLAG) <= '1'; -- GENERATION COUNTERS -- NOT_ALIVE_DISPOSED -> ALIVE Transition if (inst_data.status_info(NOT_ALIVE_DISPOSED_FLAG) = '1') then tmp_update := tmp_update or DISPOSED_CNT_FLAG; gen_cnt <= inst_data.disposed_gen_cnt + 1; -- NOT_ALIVE_NO_WRITERS -> ALIVE Transition elsif (inst_data.status_info(NOT_ALIVE_NO_WRITERS_FLAG) = '1') then tmp_update := tmp_update or NO_WRITERS_CNT_FLAG; gen_cnt <= inst_data.no_writers_gen_cnt + 1; end if; -- WRITER BITMAP -- Convert Writer Bitmap to SLV tmp_bitmap := to_endpoint_bitmap(inst_data.writer_bitmap); -- Write if Writer New for Instance if (tmp_bitmap(writer_pos) /= '1') then -- Remove Writer tmp_bitmap(writer_pos) := '0'; -- Convert Back writer_bitmap <= from_endpoint_bitmap(tmp_bitmap); tmp_update := tmp_update or WRITER_BITMAP_FLAG; end if; end if; -- INSTANCE SAMPLE COUNT -- NOTE: Ignored when remove_oldest_inst_sample, since it will be decremented again. (Stays same) if (remove_oldest_inst_sample = '0') then tmp_update := tmp_update or SAMPLE_CNT_FLAG; end if; -- IGNORE DEADLINE if (TIME_BASED_FILTER_QOS /= DURATION_ZERO) then tmp_update := tmp_update or IGNORE_DEADLINE_FLAG; deadline <= time + TIME_BASED_FILTER_QOS; end if; inst_opcode <= UPDATE_INSTANCE; inst_op_start <= '1'; update_inst_flags <= tmp_update; if (has_data = '1') then payload_addr_next <= cur_payload; stage_next <= FINALIZE_PAYLOAD; cnt_next <= 0; else stage_next <= PRE_SAMPLE_FINALIZE; cnt_next <= 0; end if; end if; when FINALIZE_PAYLOAD => -- Precondition: payload_addr (Beginning of Last Added Payload Slot) cnt_next <= cnt + 1; case (cnt) is -- Preload when 0 => payload_ren <= '1'; when 1 => -- Fix New Empty List Head empty_payload_list_head_next <= payload_read_data; -- Make current Slot the Tail payload_write_data <= PAYLOAD_MEMORY_MAX_ADDRESS; payload_wen <= '1'; stage_next <= PRE_SAMPLE_FINALIZE; cnt_next <= 0; when others => null; end case; when PRE_SAMPLE_FINALIZE => -- Precondition: sample_addr (Disposed generation Counter of New Sample) cnt_next <= cnt + 1; case (cnt) is -- Disposed Generation Counter when 0 => sample_addr_next <= cur_sample + SMF_NO_WRITERS_GEN_CNT_OFFSET; sample_wen <= '1'; -- NOT_ALIVE_DISPOSED -> ALIVE Transition if (inst_data.status_info(NOT_ALIVE_DISPOSED_FLAG) = '1' and sample_status_info(NOT_ALIVE_DISPOSED_FLAG) = '0' and sample_status_info(NOT_ALIVE_NO_WRITERS_FLAG) = '0') then sample_write_data <= gen_cnt + 1; else sample_write_data <= gen_cnt; end if; -- No Writer Generation Counter when 1 => sample_wen <= '1'; -- NOT_ALIVE_NO_WRITERS -> ALIVE Transition if (inst_data.status_info(NOT_ALIVE_NO_WRITERS_FLAG) = '1' and sample_status_info(NOT_ALIVE_DISPOSED_FLAG) = '0' and sample_status_info(NOT_ALIVE_NO_WRITERS_FLAG) = '0') then sample_write_data <= gen_cnt + 1; else sample_write_data <= gen_cnt; end if; when 2 => -- First Sample if (newest_sample = SAMPLE_MEMORY_MAX_ADDRESS) then stage_next <= FINALIZE_SAMPLE; sample_addr_next <= empty_sample_list_head + SMF_PREV_ADDR_OFFSET; cur_sample_next <= empty_sample_list_head; next_sample_next <= SAMPLE_MEMORY_MAX_ADDRESS; prev_sample_next <= SAMPLE_MEMORY_MAX_ADDRESS; cnt_next <= 0; elsif (DESTINATION_ORDER_QOS = BY_RECEPTION_TIMESTAMP_DESTINATION_ORDER_QOS) then stage_next <= FIX_POINTERS; prev_sample_next <= newest_sample; sample_addr_next <= newest_sample + SMF_NEXT_ADDR_OFFSET; cur_sample_next <= newest_sample; cnt_next <= 0; else stage_next <= FIND_POS; prev_sample_next <= newest_sample; sample_addr_next <= newest_sample + SMF_TIMESTAMP_OFFSET; cur_sample_next <= newest_sample; cnt_next <= 0; end if; when others => null; end case; when FIND_POS => -- Synthesis Guard if (DESTINATION_ORDER_QOS /= BY_RECEPTION_TIMESTAMP_DESTINATION_ORDER_QOS) then -- Precondition: prev_sample set, sample_addr (Timestamp 1/2 Addr of prev_sample) cnt_next <= cnt + 1; case (cnt) is -- Preload when 0 => sample_addr_next <= sample_addr + 1; -- Timestamp 2/2 sample_ren <= '1'; -- Timestamp 1/2 when 1 => sample_addr_next <= cur_sample + SMF_PREV_ADDR_OFFSET; sample_ren <= '1'; long_latch_next <= sample_read_data; -- Timestamp 2/2 when 2 => sample_ren <= '1'; tmp_dw := (0 => unsigned(long_latch), 1 => unsigned(sample_read_data)); sample_addr_next <= cur_sample + SMF_NEXT_ADDR_OFFSET; -- Found position (After current slot) if (ts_latch >= tmp_dw) then stage_next <= FIX_POINTERS; cnt_next <= 0; end if; -- Previous Pointer (Previous Sample) when 3 => -- No previous Slot (Oldest Sample) if (sample_read_data = PAYLOAD_MEMORY_MAX_ADDRESS) then assert (prev_sample = oldest_sample) report "Previous Sample is MAX_ADDR, but sample is not OLDEST (HEAD)" severity FAILURE; -- NOTE: Sample is added to HEAD of List prev_sample_next <= SAMPLE_MEMORY_MAX_ADDRESS; next_sample_next <= cur_sample; stage_next <= FIX_POINTERS; cnt_next <= 2; -- Skip to Previous Pointer Fix else -- Continue Search prev_sample_next <= sample_read_data; sample_addr_next <= sample_read_data + SMF_TIMESTAMP_OFFSET; cnt_next <= 0; end if; end case; end if; when FIX_POINTERS => -- Precondition: sample_addr (Next Addr of prev_sample) cnt_next <= cnt + 1; case (cnt) is -- Preload when 0 => sample_ren <= '1'; -- Next Pointer (Previous Sample) when 1 => -- Fix Next Pointer sample_write_data <= empty_sample_list_head; sample_wen <= '1'; -- No next Slot (Newest Sample) if (sample_read_data = SAMPLE_MEMORY_MAX_ADDRESS) then assert (prev_sample = newest_sample) report "Next Sample is MAX_ADDRESS, but sample is not NEWEST (TAIL)" severity FAILURE; next_sample_next <= SAMPLE_MEMORY_MAX_ADDRESS; stage_next <= FINALIZE_SAMPLE; sample_addr_next <= empty_sample_list_head + SMF_PREV_ADDR_OFFSET; cur_sample_next <= empty_sample_list_head; cnt_next <= 0; else -- Latch Next Sample next_sample_next <= sample_read_data; sample_addr_next <= sample_read_data + SMF_PREV_ADDR_OFFSET; -- Prev Addr of Next Sample end if; -- Previous Pointer (Next Sample) when 2 => -- Fix Previous Pointer sample_write_data <= empty_sample_list_head; sample_wen <= '1'; stage_next <= FINALIZE_SAMPLE; sample_addr_next <= empty_sample_list_head + SMF_PREV_ADDR_OFFSET; cur_sample_next <= empty_sample_list_head; cnt_next <= 0; when others => null; end case; when FINALIZE_SAMPLE => -- Precondition: prev_sample set, next_sample set, sample_addr (Prev Addr of new sample) cnt_next <= cnt + 1; case (cnt) is -- Previous Sample Address when 0 => sample_addr_next <= cur_sample + SMF_NEXT_ADDR_OFFSET; -- Write Prev Addr sample_write_data <= prev_sample; sample_wen <= '1'; -- Preload when 1 => sample_ren <= '1'; -- Next Sample Address when 2 => empty_sample_list_head_next <= sample_read_data; -- Write Next Addr sample_write_data <= next_sample; sample_wen <= '1'; -- If newest Sample is now previous, select current sample as new newest if (newest_sample = prev_sample) then newest_sample_next <= empty_sample_list_head; end if; -- Signal Data Available status_sig_next(DATA_AVAILABLE_STATUS) <= '1'; -- NOTE: added_new_instance and remove_oldest_sample are NOT mutual exclusive, but Instance Removal takes precedence. -- New Instance was added, and Instance Memory is Full if (added_new_instance = '1' and inst_empty_head = INSTANCE_MEMORY_MAX_ADDRESS) then -- Memory Operation Guard if (inst_op_done = '1') then inst_op_start <= '1'; inst_opcode <= GET_FIRST_INSTANCE; inst_data_variant <= '0'; -- NOTE: Instances are only removed in two occasions: -- * A new instance is added, and the instance memory gets full -- * A Sample is removed, making an instance eligible for deletion, while the -- instance memory is full. -- The combination of both cases allows to search and remove instances only when needed. stage_next <= REMOVE_STALE_INSTANCE; else cnt_next <= cnt; -- Keep State end if; elsif (remove_oldest_inst_sample = '1') then cur_sample <= oldest_sample; sample_addr_next <= oldest_sample + SMF_INSTANCE_ADDR_OFFSET; stage_next <= FIND_OLDEST_INST_SAMPLE; elsif (remove_oldest_sample = '1') then stage_next <= GET_OLDEST_SAMPLE_INSTANCE; else -- DONE stage_next <= IDLE; end if; end case; when GET_OLDEST_SAMPLE_INSTANCE => -- Memory Operation Guard if (inst_op_done = '1') then cnt_next <= cnt + 1; case (cnt) is -- Preload when 0 => sample_ren <= '1'; when 1 => -- NOTE: We have to initiate an instance "search" despite having direct access to the instance -- in order to set up the 'previous' instance pointer required by the removal procedure -- (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_addr_update <= sample_read_data; cur_sample_next <= oldest_sample; sample_addr_next <= oldest_sample + SMF_PREV_ADDR_OFFSET; stage_next <= REMOVE_SAMPLE; when others => null; end case; end if; when FIND_OLDEST_INST_SAMPLE => -- Precondition: cur_sample set, sample_addr (Instance Address of cur_sample) cnt_next <= cnt + 1; case (cnt) is -- Preload when 0 => sample_ren <= '1'; sample_addr_next <= cur_sample + SMF_NEXT_ADDR_OFFSET; -- Instance Address when 1 => sample_ren <= '1'; -- Oldest Instance Sample Found if (sample_read_data = cur_inst) then stage_next <= REMOVE_SAMPLE; sample_addr_next <= cur_sample + SMF_PREV_ADDR_OFFSET; end if; -- Next Address when 2 => cur_sample_next <= sample_read_data; sample_addr_next <= sample_read_data + SMF_INSTANCE_ADDR_OFFSET; cnt_next <= 0; when others => null; end case; when REMOVE_SAMPLE => -- Precondition: cur_sample set, sample_addr (Previous Pointer of cur_sample) -- Wait for Instance Search to finish if (inst_op_done = '1') then cnt_next <= cnt + 1; case (cnt) is -- Preload when 0 => sample_ren <= '1'; sample_addr_next <= cur_sample + 1; -- Next Addr -- Previous Pointer (Current Sample) when 1 => sample_ren <= '1'; prev_sample_next <= sample_read_data; -- Next Pointer (Current Sample) when 2 => next_sample_next <= sample_read_data; -- Make Current Sample Empty List Tail sample_write_data <= INSTANCE_MEMORY_MAX_ADDRESS; sample_wen <= '1'; -- Current Sample is Newest (Occupied List Tail) if (sample_read_data = MAX_SAMPLE_ADDRESS) then assert (cur_sample = newest_sample) report "Next Sample is MAX_ADDR, but cur_sample /= newest_sample" severity FAILURE; -- Fix Newest Pointer newest_sample_next <= prev_sample; -- Current Sample is Oldest (List Head) if (prev_sample = MAX_SAMPLE_ADDRESS) then assert (cur_sample = oldest_sample) report "Previous Sample is MAX_ADDR, but cur_sample /= oldest_sample" severity FAILURE; assert (newest_sample = oldest_sample) report "Previous and Next Sample is MAX_ADDR, but cur_sample /= newest_sample /= oldest_sample" severity FAILURE; -- Fix Oldest Pointer oldest_sample_next <= MAX_SAMPLE_ADDRESS; -- NOTE: Sample Memory Empty (newest_sample also set to MAX_ADDR) -- Sample Memory Full if (empty_sample_list_head = SAMPLE_MEMORY_MAX_ADDRESS) then empty_sample_list_head_next <= cur_sample; empty_sample_list_tail_next <= cur_sample; -- Skip to Payload Handling cnt_next <= 6; sample_addr_next <= cur_sample + SMF_PAYLOAD_ADDR_OFFSET; else -- Skip to Empty List Handling cnt_next <= 5; sample_addr_next <= empty_sample_list_tail + SMF_NEXT_ADDR_OFFSET; end if; else -- Skip to Previous Handling sample_addr_next <= prev_sample + SMF_NEXT_ADDR_OFFSET; cnt_next <= 4; end if; else sample_addr_next <= sample_read_data + SMF_PREV_ADDR_OFFSET; end if; -- Previous Address (Next Sample) when 3 => -- Remove link to cur_sample sample_write_data <= prev_sample; sample_wen <= '1'; -- Current Sample is oldest sample (List Head) if (prev_sample = MAX_SAMPLE_ADDRESS) then assert (cur_sample = oldest_sample) report "Previous Sample is MAX_ADDR, but cur_sample /= oldest_sample" severity FAILURE; -- Fix Oldest Pointer oldest_sample_next <= MAX_SAMPLE_ADDRESS; -- Sample Memory Full if (empty_sample_list_head = SAMPLE_MEMORY_MAX_ADDRESS) then empty_sample_list_head_next <= cur_sample; empty_sample_list_tail_next <= cur_sample; -- Skip to Payload Handling cnt_next <= 6; sample_addr_next <= cur_sample + SMF_PAYLOAD_ADDR_OFFSET; else -- Skip to Empty List Handling cnt_next <= 5; sample_addr_next <= empty_sample_list_tail + SMF_NEXT_ADDR_OFFSET; end if; end if; -- Next Address (Previous Sample) when 4 => -- Remove link to cur_sample sample_write_data <= next_sample; sample_wen <= '1'; sample_addr_next <= cur_sample + SMF_PAYLOAD_ADDR_OFFSET; -- Next Address (Empty Tail) when 5 => sample_write_data <= cur_sample; sample_wen <= '1'; -- Fix Empty List Pointers empty_sample_list_tail_next <= cur_sample; sample_addr_next <= cur_sample + SMF_PAYLOAD_ADDR_OFFSET; -- Preload when 6 => sample_ren <= '1'; -- Payload Address when 7 => cur_payload_next <= sample_read_data; -- Sample has no Data if (sample_read_data = MAX_PAYLOAD_ADDRESS) then stage_next <= POST_SAMPLE_REMOVE; -- Payload Memory Full elsif (empty_payload_list_head = MAX_PAYLOAD_ADDRESS) then -- NOTE: Make the head of the Payload, the head of the Empty List empty_payload_list_head_next <= sample_read_data; stage_next <= POST_SAMPLE_REMOVE; else payload_addr_next <= cur_payload + PMF_NEXT_ADDR_OFFSET; end if; -- Preload when 8 => payload_ren <= '1'; -- Next Payload Addr when 9 => -- Found Empty List Tail if (payload_read_data = MAX_PAYLOAD_ADDRESS) then empty_payload_list_head_next <= cur_payload; payload_write_data <= empty_payload_list_head; payload_wen <= '1'; stage_next <= POST_SAMPLE_REMOVE; else payload_addr_next <= payload_read_data + PMF_NEXT_ADDR_OFFSET; cnt_next <= 8; end if; when others => null; end case; end if; when POST_SAMPLE_REMOVE => -- Memory Operation Guard if (inst_op_done = '1') then -- No Instance Change on remove_oldest_inst_sample if (remove_oldest_inst_sample = '0') then tmp_bitmap := to_endpoint_bitmap(inst_data.writer_bitmap); -- Instance obsolete and Instance Memory Full if (inst_data.sample_cnt = 1 and tmp_bitmap = (tmp_bitmap'range => '0') and inst_empty_head = INSTANCE_MEMORY_MAX_ADDRESS) then inst_op_start <= '1'; inst_opcode <= REMOVE_INSTANCE; else inst_op_start <= '1'; inst_opcode <= UPDATE_INSTANCE; update_inst_flags <= SAMPLE_CNT_FLAG; sample_cnt <= inst_data.sample_cnt - 1; end if; end if; if (is_take = '1') then -- Continue Processing stage_next <= GET_NEXT_SAMPLE; cnt_next <= 0; else -- DONE stage_next <= IDLE; end if; end if; when SKIP_ADD_REJECT => case (cnt) is -- SKIP READ when 0 => ready_in_rtps <= '1'; -- Wait until last word from input if (last_word_in_rtps = '1') then cnt_next <= 1; end if; -- REJECT SAMPLE when 1 => res_rtps <= REJECTED; stage_next <= IDLE; -- TODO: Add a new Reject Status? (E.g. REJECTED_BY_PAYLOAD_LIMIT?, or UNSPECIFIED REJECT?) -- Update Sample Reject Status status_sig_next(SAMPLE_REJECTED_STATUS) <= '1'; sample_rej_cnt_next <= sample_rej_cnt + 1; sample_rej_cnt_change_next <= sample_rej_cnt_change + 1; sample_rej_last_reason_next <= REJECTED_BY_SAMPLES_LIMIT; sample_rej_last_inst_next <= key_hash; when others => null; end case; when SKIP_ADD_DROP => case (cnt) is -- SKIP READ when 0 => ready_in_rtps <= '1'; -- Wait until last word from input if (last_word_in_rtps = '1') then cnt_next <= 1; end if; -- DROP SAMPLE when 1 => res_rtps <= ACCEPTED; stage_next <= IDLE; when others => null; end case; when REMOVE_WRITER => -- Memory Operation Guard if (inst_op_done = '1') then -- No More Instances if (inst_addr_base = INSTANCE_MEMORY_MAX_ADDRESS) then -- DONE stage_next <= IDLE; else -- Convert Writer Bitmap to SLV tmp_bitmap := to_endpoint_bitmap(inst_data.writer_bitmap); -- Remove Writer tmp_bitmap(writer_pos) := '0'; -- NOTE: writer_bitmap is not latched, since the memory process is latching it at the -- same clock cycle. -- Convert Back writer_bitmap <= from_endpoint_bitmap(tmp_bitmap); -- No More Writers for Instance if (tmp_bitmap = (tmp_bitmap'range => '0')) then status_info_update <= inst_data.status; status_info_update(NOT_ALIVE_DISPOSED_FLAG) <= '0'; status_info_update(NOT_ALIVE_NO_WRITERS_FLAG) <= '1'; status_info_update(LIVELINESS_FLAG) <= '1'; inst_op_start <= '1'; inst_opcode <= UPDATE_INSTANCE; update_inst_flags <= STATUS_FLAG or WRITER_BITMAP_FLAG; else inst_op_start <= '1'; inst_opcode <= UPDATE_INSTANCE; update_inst_flags <= WRITER_BITMAP_FLAG; end if; stage_next <= GET_NEXT_INSTANCE; end if; end if; when GET_NEXT_INSTANCE => -- Wait for Operation to Complete if (inst_op_done = '1') then inst_op_start <= '1'; inst_opcode <= GET_NEXT_INSTANCE; inst_data_variant <= '0'; stage_next <= REMOVE_WRITER; end if; when REMOVE_STALE_INSTANCE => -- Wait for Instance Data if (inst_op_done = '1') then -- Iterated through all Instances if (inst_addr_base = INSTANCE_MEMORY_MAX_ADDRESS) then if (remove_oldest_inst_sample = '1') then cur_sample <= oldest_sample; sample_addr_next <= oldest_sample + SMF_INSTANCE_ADDR_OFFSET; stage_next <= FIND_OLDEST_INST_SAMPLE; else -- DONE stage_next <= IDLE; end if; else -- Convert Writer Bitmap to SLV tmp_bitmap := to_endpoint_bitmap(inst_data.writer_bitmap); -- Found Stale Instance (No Samples and No Active Writers) if (inst_data.sample_cnt = 0 and tmp_bitmap = (tmp_bitmap'range => '0')) then -- Remove Stale Instance inst_op_start <= '1'; inst_opcode <= REMOVE_INSTANCE; if (remove_oldest_inst_sample = '1') then cur_sample <= oldest_sample; sample_addr_next <= oldest_sample + SMF_INSTANCE_ADDR_OFFSET; stage_next <= FIND_OLDEST_INST_SAMPLE; else -- DONE stage_next <= IDLE; end if; else -- Continue Search inst_op_start <= '1'; inst_opcode <= GET_NEXT_INSTANCE; inst_data_variant <= '0'; end if; end if; end if; when GET_NEXT_SAMPLE => -- Precondition: cur_sample set, sample_addr (Status Info of cur_sample), cur_inst set, si_sample_rank_sig set cnt_next <= cnt + 1; case (cnt) is -- Preload when 0 => sample_addr_next <= cur_sample + SMF_INSTANCE_ADDR_OFFSET; sample_ren <= '1'; -- Status Info when 1 => sample_addr_next <= cur_sample + SMF_TIMESTAMP_OFFSET; sample_ren <= '1'; -- Latch Sample Status Info sample_status_info_next <= sample_read_data; -- Check Sample State case (sample_state) is when READ_SAMPLE_STATE => if (sample_read_data(READ_FLAG) /= '1') then -- Sample not in collection, Skip Sample sample_addr_next <= cur_sample + SMF_NEXT_ADDR_OFFSET; cnt_next <= 13; end if; when NOT_READ_SAMPLE_STATE => if (sample_read_data(READ_FLAG) /= '0') then -- Sample not in collection, Skip Sample sample_addr_next <= cur_sample + SMF_NEXT_ADDR_OFFSET; cnt_next <= 13; end if; when ANY_SAMPLE_STATE => null; -- Uknown Sample State when others => -- Sample not in collection, Skip Sample sample_addr_next <= cur_sample + SMF_NEXT_ADDR_OFFSET; cnt_next <= 13; end case; if (sample_read_data(READ_FLAG) = '1') then si_sample_state_sig_next <= READ_SAMPLE_STATE; else si_sample_state_sig_next <= NOT_READ_SAMPLE_STATE; end if; -- Instance Pointer when 2 => -- Instance pre-selected if (cur_inst /= INSTANCE_MEMORY_MAX_ADDRESS) then -- Sample has different Instance if (cur_inst /= sample_read_data) then -- Consecutive Instance Sample Order if (not ORDERED_ACCESS or PRESENTATION_QOS = INSTANCE_PRESENTATION_QOS) then -- Skip Sample sample_addr_next <= cur_sample + SMF_NEXT_ADDR_OFFSET; cnt_next <= 13; else -- Get Instance Data next_inst_next <= sample_read_data; end if; else -- Select Sample collection_cnt_next <= collection_cnt + 1; first_sample_next <= cur_sample; -- First Instance Sample -- NOTE: This state only enters with a sample rank of 0 and cur_inst set, when the -- first sample of the instance has not yet been selected if (si_sample_rank_sig = 0) then -- Reset collection_cnt_max_next <= collection_cnt + 1; else si_sample_rank_sig <= si_sample_rank_sig - 1; end if; sample_addr_next <= sample_addr + 1; -- Timestamp 2/2 sample_ren <= '1'; cnt_next <= 5; -- Skip Instance Operation end if; else -- Get Instance Data next_inst_next <= sample_read_data; end if; -- Get Instance when 3 => -- Memory Operation Guard if (inst_op_done = '1') then inst_op_start <= '1'; inst_opcode <= GET_INSTANCE; inst_data_variant <= '1'; inst_addr_update <= next_inst; else cnt_next <= cnt; -- Keep sub-state end if; -- Check Instance Data when 4 => -- Wait for Instance Data if (inst_op_done = '1') then sample_addr_next <= sample_addr + 1; -- Timestamp 2/2 sample_ren <= '1'; -- DEFAULT tmp_bool := TRUE; -- Check Instance State case (instance_state) is when ALIVE_INSTANCE_STATE => if (inst_data.status_info(NOT_ALIVE_DISPOSED_FLAG) = '1' or inst_data.status_info(NOT_ALIVE_NO_WRITERS_FLAG) = '1') then tmp_bool := FALSE; end if; when NOT_ALIVE_DISPOSED_INSTANCE_STATE => if (inst_data.status_info(NOT_ALIVE_DISPOSED_FLAG) = '0') then tmp_bool := FALSE; end if; when NOT_ALIVE_NO_WRITERS_INSTANCE_STATE => if (inst_data.status_info(NOT_ALIVE_NO_WRITERS_FLAG) = '0') then tmp_bool := FALSE; end if; when NOT_ALIVE_INSTANCE_STATE => if (inst_data.status_info(NOT_ALIVE_DISPOSED_FLAG) = '0' and inst_data.status_info(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(VIEW_FLAG) = '0') then tmp_bool := FALSE; end if; when NOT_NEW_VIEW_STATE => if (inst_data.status_info(VIEW_FLAG) = '1') then tmp_bool := FALSE; end if; when ANY_VIEW_STATE => null; when others => tmp_bool := FALSE; end case; -- Check Instance Mark if (inst_data.status_info(MARK_FLAG) = '1') then -- Skip Marked Instance tmp_bool := FALSE; end if; -- Instance Passes Checks if (tmp_bool) then -- Select Sample collection_cnt_next <= collection_cnt + 1; collection_cnt_max_next <= collection_cnt + 1; si_sample_rank_sig <= (others => '0'); cur_inst_next <= next_inst; first_sample_next <= cur_sample; else -- Skip Sample sample_addr_next <= cur_sample + SMF_NEXT_ADDR_OFFSET; cnt_next <= 13; end if; else cnt_next <= cnt; -- Keep sub-state end if; -- Timestamp 1/2 when 5 => sample_addr_next <= cur_sample + SMF_PAYLOAD_ADDR_OFFSET; sample_ren <= '1'; si_source_timestamp_sig_next(0) <= sample_read_data; -- Timestamp 2/2 when 6 => sample_addr_next <= cur_sample + SMF_DISPOSED_GEN_CNT_OFFSET; sample_ren <= '1'; si_source_timestamp_sig_next(1) <= sample_read_data; -- Payload Pointer when 10 => sample_addr_next <= cur_sample + SMF_NO_WRITERS_GEN_CNT_OFFSET; sample_ren <= '1'; -- Latch Payload Address cur_payload_next <= sample_read_data; -- Disposed Generation Count when 11 => sample_addr_next <= cur_sample + SMF_NEXT_ADDR_OFFSET; sample_ren <= '1'; si_disposed_generation_count_sig_next <= sample_read_data; -- No Writers Generation Count when 12 => sample_ren <= '1'; si_no_writers_generation_count_sig_next <= sample_read_data; cur_generation_rank_next <= si_disposed_generation_count_sig + sample_read_data; -- Calculate highest collection generation rank collection_generation_rank_next <= si_disposed_generation_count_sig + sample_read_data; cnt_next <= 14; -- Skip Preload -- Preload when 13 => sample_ren <= '1'; -- Next Pointer when 14 => -- Reached End of Samples if (sample_read_data = SAMPLE_MEMORY_MAX_ADDRESS) then -- Exit Condition (Sample Selected) if (first_sample = cur_sample) then stage_next <= FINALIZE_SAMPLE_INFO; cnt_next <= 0; else -- Collection Empty if (collection_cnt = 0) then -- READ_NEXT_INSTANCE/TAKE_NEXT_INSTANCE Operation if (dynamic_next_instance = '1') then -- 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; else done_dds <= '1'; return_code_dds <= RETCODE_NO_DATA; stage_next <= IDLE; end if; else done_dds <= '1'; return_code_dds <= RETCODE_OK; stage_next <= IDLE; end if; end if; else -- Next Sample cur_sample_next <= sample_read_data; sample_addr_next <= sample_read_data + SMF_STATUS_INFO_OFFSET; cnt_next <= 0; -- Exit Condition (Sample Selected) if (first_sample = cur_sample) then -- Pre-Calculation already done for selected Instance if (si_sample_rank_sig /= 0) then stage_next <= FINALIZE_SAMPLE_INFO; cnt_next <= 0; else -- Latch Next Sample (For resume purposes) next_sample_next <= sample_read_data; -- Calculate Instance Sample Ranks stage_next <= PRE_CALCULATE; end if; end if; end if; when others => null; end case; when PRE_CALCULATE => -- Precondition: cur_sample set, sample_addr_next (Status Info of cur_sample) cnt_next <= cnt + 1; case (cnt) is -- Preload when 0 => sample_addr_next <= cur_sample + SMF_INSTANCE_ADDR_OFFSET; sample_ren <= '1'; -- Exit Condition (Reached Collection Limit) if (collection_cnt_max = max_samples) then stage_next <= FINALIZE_SAMPLE_INFO; cnt_next <= 0; end if; -- Status Info when 1 => sample_addr_next <= cur_sample + SMF_DISPOSED_GEN_CNT_OFFSET; sample_ren <= '1'; -- Check Sample State case (sample_state) is when READ_SAMPLE_STATE => if (sample_read_data(READ_FLAG) /= '1') then -- Skip Sample sample_addr_next <= cur_sample + SMF_NEXT_ADDR_OFFSET; cnt_next <= 7; end if; when NOT_READ_SAMPLE_STATE => if (sample_read_data(READ_FLAG) /= '0') then -- Skip Sample sample_addr_next <= cur_sample + SMF_NEXT_ADDR_OFFSET; cnt_next <= 7; end if; when ANY_SAMPLE_STATE => null; -- Uknown Sample State when others => -- Skip Sample sample_addr_next <= cur_sample + SMF_NEXT_ADDR_OFFSET; cnt_next <= 7; end case; -- Instance Pointer when 2 => sample_addr_next <= cur_sample + SMF_NO_WRITERS_GEN_CNT_OFFSET; sample_ren <= '1'; -- Same Instance if (sample_read_data = cur_inst) then -- Count Sample (No need to check Instance) collection_cnt_max_next <= collection_cnt_max + 1; si_sample_rank_sig_next <= si_sample_rank_sig + 1; else -- Consecutive Instance Sample Order if (not ORDERED_ACCESS or PRESENTATION_QOS = INSTANCE_PRESENTATION_QOS or single_instance = '1') then -- Skip Sample sample_addr_next <= cur_sample + SMF_NEXT_ADDR_OFFSET; cnt_next <= 7; else -- Check New Instance next_inst_next <= sample_read_data; cnt_next <= 5; end if; end if; -- Disposed Generation Count when 3 => sample_addr_next <= cur_sample + SMF_NEXT_ADDR_OFFSET; sample_ren <= '1'; -- Calculate highest collection generation rank collection_generation_rank_next <= sample_read_data; -- No Writers Generation Count when 4 => sample_ren <= '1'; -- Calculate highest collection generation rank collection_generation_rank_next <= collection_generation_rank + sample_read_data; cnt_next <= 8; -- Initiate Get Memory Operation when 5 => -- Memory Operation Guard if (inst_op_done = '1') then inst_op_start <= '1'; inst_opcode <= GET_INSTANCE_DATA_2; inst_data_variant <= '1'; inst_addr_update <= next_inst; else cnt_next <= cnt; -- Keep State end if; -- State Check when 6 => -- Wait for Instance Data if (inst_op_done = '1') then -- DEFAULT tmp_bool := TRUE; -- Check Instance State case (instance_state) is when ALIVE_INSTANCE_STATE => if (inst_data.status_info(NOT_ALIVE_DISPOSED_FLAG) = '1' or inst_data.status_info(NOT_ALIVE_NO_WRITERS_FLAG) = '1') then tmp_bool := FALSE; end if; when NOT_ALIVE_DISPOSED_INSTANCE_STATE => if (inst_data.status_info(NOT_ALIVE_DISPOSED_FLAG) = '0') then tmp_bool := FALSE; end if; when NOT_ALIVE_NO_WRITERS_INSTANCE_STATE => if (inst_data.status_info(NOT_ALIVE_NO_WRITERS_FLAG) = '0') then tmp_bool := FALSE; end if; when NOT_ALIVE_INSTANCE_STATE => if (inst_data.status_info(NOT_ALIVE_DISPOSED_FLAG) = '0' and inst_data.status_info(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(VIEW_FLAG) = '0') then tmp_bool := FALSE; end if; when NOT_NEW_VIEW_STATE => if (inst_data.status_info(VIEW_FLAG) = '1') then tmp_bool := FALSE; end if; when ANY_VIEW_STATE => null; when others => tmp_bool := FALSE; end case; -- Check Instance Mark if (inst_data.status_info(MARK_FLAG) = '1') then -- Skip Marked Instance tmp_bool := FALSE; end if; -- Instance passes Checks if (tmp_bool) then -- Count Sample collection_cnt_max_next <= collection_cnt_max + 1; end if; -- Done sample_addr_next <= cur_sample + SMF_NEXT_ADDR_OFFSET; cnt_next <= 7; else cnt_next <= cnt; -- Keep sub-state end if; -- Preload when 7 => sample_ren <= '1'; -- Next Pointer when 8 => -- Exit Condition (Reached End of Samples) if (sample_read_data = SAMPLE_MEMORY_MAX_ADDRESS) then stage_next <= FINALIZE_SAMPLE_INFO; cnt_next <= 0; else -- Continue with next Sample cur_sample_next <= sample_read_data; sample_addr_next <= sample_read_data + SMF_STATUS_INFO_OFFSET; cnt_next <= 0; end if; when others => null; end case; when FINALIZE_SAMPLE_INFO => -- Precondition: cur_inst set case (cnt) is -- Finalize Sample Info Data when 0 => sample_addr_next <= first_sample + SMF_STATUS_INFO_OFFSET; -- Wait for Instance Data if (inst_op_done = '1') then -- Instance Data valid if (inst_addr_base = cur_inst) then -- Sample Info View State if (inst_data.status_info(VIEW_FLAG) = '1') then si_view_state_sig_next <= NEW_VIEW_STATE; else si_view_state_sig_next <= NOT_NEW_VIEW_STATE; end if; -- Sample Info Instance State if (inst_data.status_info(NOT_ALIVE_DISPOSED_FLAG) = '1') then si_instance_state_sig_next <= NOT_ALIVE_DISPOSED_INSTANCE_STATE; elsif (inst_data.status_info(NOT_ALIVE_NO_WRITERS_FLAG) = '1') then si_instance_state_sig_next <= NOT_ALIVE_NO_WRITERS_INSTANCE_STATE; else si_instance_state_sig_next <= ALIVE_INSTANCE_STATE; end if; -- Sample Info Instance Handle si_instance_handle_sig_next <= inst_data.key_hash; -- Sample Info Generation Rank si_generation_rank_sig_next <= collection_generation_rank - cur_generation_rank; -- Sample Info Absolut Generation Rank -- XXX: Possible Worst Case Path (2 32-bit Operations in same clock) si_generation_rank_sig_next <= (inst_data.disposed_gen_cnt + inst_data.no_writers_gen_cnt) - cur_generation_rank; -- Sample Info Valid Data if (cur_payload /= PAYLOAD_MEMORY_MAX_ADDRESS) then si_valid_data_sig_next <= '1'; else si_valid_data_sig_next <= '0'; end if; si_valid_sig_next <= '1'; cnt_next <= 1; else -- Get Instance Data inst_op_start <= '1'; inst_opcode <= GET_INSTANCE; inst_data_variant <= '1'; inst_addr_update <= cur_inst; end if; end if; -- Present Data when 1 => -- Invalidate Data si_valid_sig_next <= '0'; -- Synthesis Guard if (DESTINATION_ORDER_QOS = BY_SOURCE_TIMESTAMP_DESTINATION_ORDER_QOS) then -- Update Last Read Timestamp if (si_source_timestamp_sig > last_read_ts) then last_read_ts_next <= si_source_timestamp_sig; end if; end if; -- Reset Data Available Status status_sig_next(DATA_AVAILABLE_STATUS) <= '0'; -- Sample not marked as Read if (sample_status_info(READ_FLAG) /= '1') then -- Mark Sample as Read sample_write_data <= sample_status_info; sample_write_data(READ_FLAG) <= '1'; sample_wen <= '1'; end if; -- Sample Data Request if (get_data = '1') then stage_next <= GET_PAYLOAD; cnt_next <= 0; payload_addr_next <= cur_payload; else cnt_next <= 2; end if; -- Post-Present Data when 2 => -- Memory Operation Guard if (inst_op_done = '1') then -- NOTE: If we have a presentation of consecutive same instance samples of multiple instances, we have to -- mark the instances we have already handled, in order to prevent the GET_NEXT_SAMPLE state to -- re-process them. -- Last Sample of Instance in Collection if (si_sample_rank_sig = 1) then inst_op_start <= '1'; inst_opcode <= UPDATE_INSTANCE; update_inst_flags <= STATUS_FLAG; status_info_update <= inst_data.status_info; -- Consecutive Instance Sample Order of multiple Instances if ((not ORDERED_ACCESS or PRESENTATION_QOS = INSTANCE_PRESENTATION_QOS) and single_instance = '0' and single_sample = '0') then -- Completed Collection if (collection_cnt = max_samples) then -- Unmark Instances unmark_instances_next <= '1'; else -- Mark Instance status_info_update(MARK_FLAG) <= '1'; end if; end if; -- Instance is NOT_VIEWED and sample is from last generation of Instance if (inst_data.status_info(VIEW_FLAG) = '0' and si_absolute_generation_count_sig = 0) then -- Mark Instance as VIEWED status_info_update(VIEW_FLAG) <= '1'; end if; end if; -- Collection Completed if (collection_cnt = max_samples) then done_dds <= '1'; return_code_dds <= RETCODE_OK; is_take_next <= '0'; -- Return to IDLE from REMOVE if (is_take = '1') then stage_next <= REMOVE_SAMPLE; cur_sample_next <= first_sample; sample_addr_next <= first_sample + SMF_PREV_ADDR_OFFSET; else -- DONE stage_next <= IDLE; end if; else cur_sample <= next_sample; cnt_next <= 0; -- Reached End of Samples if (next_sample = SAMPLE_MEMORY_MAX_ADDRESS) then -- DONE done_dds <= '1'; return_code_dds <= RETCODE_OK; is_take_next <= '0'; -- Return to IDLE from REMOVE end if; -- cur_inst has no more samples in collection if (si_sample_rank_sig = 0) then -- Present only single Instance if (single_instance = '1') then -- DONE done_dds <= '1'; return_code_dds <= RETCODE_OK; is_take_next <= '0'; -- Return to IDLE from REMOVE else cur_inst_next <= INSTANCE_MEMORY_MAX_ADDRESS; end if; end if; if (is_take = '1') then -- Remove Sample stage_next <= REMOVE_SAMPLE; cur_sample_next <= first_sample; sample_addr_next <= first_sample + SMF_PREV_ADDR_OFFSET; else -- Continue Processing stage_next <= GET_NEXT_SAMPLE; end if; end if; end if; when others => null; end case; when GET_PAYLOAD => -- Precondition: payload_addr (Beginning of cur_payload) case (cnt) is -- Preload when 0 => payload_addr_next <= payload_addr + 1; payload_ren <= '1'; cnt_next <= cnt + 1; -- Next Pointer when 1 => payload_addr_next <= payload_addr + 1; payload_ren <= '1'; cnt_next <= cnt + 1; next_payload_next <= payload_read_data; -- Payload when others => if (ready_out_dds = '1') then payload_addr_next <= payload_addr + 1; payload_ren <= '1'; cnt_next <= cnt + 1; valid_out_dds <= '1'; if (has_latched = '0') then data_out_dds <= payload_read_data; else -- Previously Latched data_out_dds <= long_latch; end if; -- Reset has_lacthed_next <= '0'; -- End of Payload Frame if (cnt = PAYLOAD_FRAME_SIZE) then -- Last Payload Frame if (next_payload = PAYLOAD_MEMORY_MAX_ADDRESS) then last_word_out_dds <= '1'; stage_next <= FINALIZE_SAMPLE_INFO; cnt_next <= 2; else -- Continue with next payload Slot payload_addr_next <= next_payload; cnt_next <= 0; end if; end if; else long_latch_next <= payload_read_data; has_lacthed_next <= '1'; end if; end case; when FIND_NEXT_INSTANCE => -- Wait for Instance Data if (inst_op_done = '1') then case (cnt) is when 0 => inst_op_start <= '1'; inst_opcode <= GET_FIRST_INSTANCE; inst_data_variant <= '1'; cnt_next <= 2; when 1 => inst_op_start <= '1'; inst_opcode <= GET_NEXT_INSTANCE; inst_data_variant <= '1'; cnt_next <= 2; when 2 => -- Instance Found if (inst_addr_base /= SAMPLE_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(NOT_ALIVE_DISPOSED_FLAG) = '1' or inst_data.status_info(NOT_ALIVE_NO_WRITERS_FLAG) = '1') then tmp_bool := FALSE; end if; when NOT_ALIVE_DISPOSED_INSTANCE_STATE => if (inst_data.status_info(NOT_ALIVE_DISPOSED_FLAG) = '0') then tmp_bool := FALSE; end if; when NOT_ALIVE_NO_WRITERS_INSTANCE_STATE => if (inst_data.status_info(NOT_ALIVE_NO_WRITERS_FLAG) = '0') then tmp_bool := FALSE; end if; when NOT_ALIVE_INSTANCE_STATE => if (inst_data.status_info(NOT_ALIVE_DISPOSED_FLAG) = '0' and inst_data.status_info(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(VIEW_FLAG) = '0') then tmp_bool := FALSE; end if; when NOT_NEW_VIEW_STATE => if (inst_data.status_info(VIEW_FLAG) = '1') 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 <= inst_addr_base; stage_next <= GET_NEXT_SAMPLE; else inst_op_start <= '1'; inst_opcode <= GET_NEXT_INSTANCE; inst_data_variant <= '1'; end if; else -- DONE done_dds <= '1'; return_code_dds <= RETCODE_NO_DATA; stage_next <= IDLE; end if; when others => null; end case; end if; when CHECK_INSTANCE => -- Wait for Instance Data if (inst_op_done = '1') then case (cnt) is when 0 => inst_op_start <= '1'; inst_opcode <= SEARCH_INSTANCE_HASH; inst_data_variant <= '1'; cnt_next <= 1; when 1 => -- Instance Found if (inst_addr_base /= SAMPLE_MEMORY_MAX_ADDRESS) then -- DEFAULT tmp_bool := TRUE; -- Check Instance State case (instance_state) is when ALIVE_INSTANCE_STATE => if (inst_data.status_info(NOT_ALIVE_DISPOSED_FLAG) = '1' or inst_data.status_info(NOT_ALIVE_NO_WRITERS_FLAG) = '1') then tmp_bool := FALSE; end if; when NOT_ALIVE_DISPOSED_INSTANCE_STATE => if (inst_data.status_info(NOT_ALIVE_DISPOSED_FLAG) = '0') then tmp_bool := FALSE; end if; when NOT_ALIVE_NO_WRITERS_INSTANCE_STATE => if (inst_data.status_info(NOT_ALIVE_NO_WRITERS_FLAG) = '0') then tmp_bool := FALSE; end if; when NOT_ALIVE_INSTANCE_STATE => if (inst_data.status_info(NOT_ALIVE_DISPOSED_FLAG) = '0' and inst_data.status_info(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(VIEW_FLAG) = '0') then tmp_bool := FALSE; end if; when NOT_NEW_VIEW_STATE => if (inst_data.status_info(VIEW_FLAG) = '1') 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 -- Get Instance Samples cur_inst <= inst_addr_base; stage_next <= GET_NEXT_SAMPLE; else -- DONE done_dds <= '1'; return_code_dds <= RETCODE_NO_DATA; stage_next <= IDLE; end if; else -- Given Instance does not exist -- DONE done_dds <= '1'; return_code_dds <= RETCODE_BAD_PARAMETER; stage_next <= IDLE; end if; when others => null; end case; end if; when GET_SAMPLE_REJECTED_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 <= sample_rej_cnt; -- Total Count Change when 1 => data_out_dds <= sample_rej_cnt_change; -- Reset sample_rej_cnt_change_next <= (others => '0'); -- Last Reason when 2 => data_out_dds <= sample_rej_last_reason; -- Reset sample_rej_last_reason <= NOT_REJECTED; -- Last Instance Handle 1/4 when 3 => data_out_dds <= sample_rej_last_inst(0); -- Last Instance Handle 2/4 when 4 => data_out_dds <= sample_rej_last_inst(1); -- Last Instance Handle 3/4 when 5 => data_out_dds <= sample_rej_last_inst(2); -- Last Instance Handle 4/4 when 6 => data_out_dds <= sample_rej_last_inst(3); last_word_out_dds <= '1'; -- Return Code when 7 => done_dds <= '1'; return_code_dds <= RETCODE_OK; -- Reset status_sig_next(SAMPLE_REJECTED_STATUS) <= '0'; -- DONE stage_next <= IDLE; when others => null; end case; end if; when others => null; end case; end process; inst_ctrl_prc : process(all) begin -- DEFAULT Registered inst_stage_next <= inst_stage; inst_addr_base_next <= inst_addr_base; inst_addr_next <= inst_addr; inst_empty_head_next <= inst_empty_head; inst_occupied_head_next <= inst_occupied_head; inst_latch_data_next <= inst_latch_data; inst_next_addr_base_next <= inst_next_addr_base; inst_prev_addr_base_next <= inst_prev_addr_base; inst_cnt_next <= inst_cnt; inst_mem_full_next <= inst_mem_full; inst_data_next <= inst_data; -- DEFAULT Unregistered inst_write_data <= (others => '0'); inst_op_done <= '0'; inst_ren <= '0'; inst_wen <= '0'; case (mem_stage) is when IDLE => inst_op_done <= '1'; if (inst_op_start = '1') then -- Latch Signals needed for Mermory Operation (Use _next signals, because some signals are set in same clk) inst_latch_data_next <= ( variant => inst_data_variant, key_hash => key_hash_next, status_info => status_info_update, sample_cnt => sample_cnt, gen_cnt => gen_cnt, deadline => deadline, writer_bitmap => writer_bitmap, update_flags => update_inst_flags, addr => inst_addr_update ); case(inst_opcode) is when SEARCH_INSTANCE_HASH => -- Reset Data inst_data_next <= ZERO_INSTANCE_DATA; -- No Instances avialable if (inst_occupied_head = INSTANCE_MEMORY_MAX_ADDRESS) then inst_addr_base_next <= INSTANCE_MEMORY_MAX_ADDRESS; else inst_prev_addr_base <= INSTANCE_MEMORY_MAX_ADDRESS; inst_addr_base_next <= inst_occupied_head; inst_addr_next <= inst_occupied_head; inst_stage_next <= SEARCH_INSTANCE_HASH; inst_cnt_next <= 0; end if; when SEARCH_INSTANCE_ADDR => -- Reset Data inst_data_next <= ZERO_INSTANCE_DATA; -- No Instances avialable if (inst_occupied_head = INSTANCE_MEMORY_MAX_ADDRESS) then inst_addr_base_next <= INSTANCE_MEMORY_MAX_ADDRESS; else inst_prev_addr_base <= INSTANCE_MEMORY_MAX_ADDRESS; inst_addr_base_next <= inst_occupied_head; inst_addr_next <= inst_occupied_head; inst_stage_next <= SEARCH_INSTANCE_ADDR; inst_cnt_next <= 0; end if; when INSERT_INSTANCE => -- NOTE: Since this process has no way to communicate a failed insert to the main process, it has to be made sure -- by the main process that the operation can succeed (Memory is available) assert (inst_empty_head /= INSTANCE_MEMORY_MAX_ADDRESS) report "Instance Insertion while memory Full" severity FAILURE; inst_addr_next <= inst_occupied_head; inst_addr_base_next <= inst_occupied_head; inst_stage_next <= FIND_POS; inst_cnt_next <= 0; when UPDATE_INSTANCE => inst_addr_base_next <= inst_addr_update; if ((update_inst_flags and STATUS_FLAG) = STATUS_FLAG) then inst_stage_next <= UPDATE_INSTANCE; inst_addr_next <= inst_addr_update + IMF_STATUS_INFO_OFFSET; inst_cnt_next <= 0; elsif ((update_inst_flags and SAMPLE_CNT_FLAG) = SAMPLE_CNT_FLAG) then inst_stage_next <= UPDATE_INSTANCE; inst_addr_next <= inst_addr_update + IMF_SAMPLE_CNT_OFFSET; inst_cnt_next <= 3; elsif ((update_inst_flags and DISPOSED_CNT_FLAG) = DISPOSED_CNT_FLAG) then inst_stage_next <= UPDATE_INSTANCE; inst_addr_next <= inst_addr_update + IMF_DISPOSED_GEN_CNT_OFFSET; inst_cnt_next <= 6; elsif ((update_inst_flags and NO_WRITERS_CNT_FLAG) = NO_WRITERS_CNT_FLAG) then inst_stage_next <= UPDATE_INSTANCE; inst_addr_next <= inst_addr_update + IMF_NO_WRITERS_GEN_CNT_OFFSET; inst_cnt_next <= 7; elsif (TIME_BASED_FILTER_QOS /= DURATION_ZERO and (update_inst_flags and IGNORE_DEADLINE_FLAG) = IGNORE_DEADLINE_FLAG) then inst_stage_next <= UPDATE_INSTANCE; inst_addr_next <= inst_addr_update + IMF_IGNORE_DEADLINE_OFFSET; inst_cnt_next <= 8; elsif ((update_inst_flags and WRITER_BITMAP_FLAG) = WRITER_BITMAP_FLAG) then inst_stage_next <= SET_WRITER_BITMAP; inst_addr_next <= inst_addr_update + IMF_WRITER_BITMAP_OFFSET; inst_cnt_next <= 0; end if; when GET_FIRST_INSTANCE => -- No Instances avialable if (inst_occupied_head = INSTANCE_MEMORY_MAX_ADDRESS) then inst_addr_base_next <= INSTANCE_MEMORY_MAX_ADDRESS; 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; end if; when GET_NEXT_INSTANCE => -- No Instances avialable if (inst_next_addr_base = INSTANCE_MEMORY_MAX_ADDRESS) then inst_addr_base_next <= INSTANCE_MEMORY_MAX_ADDRESS; else inst_prev_addr_base_next <= inst_addr_base; inst_addr_base_next <= inst_next_addr_base; inst_addr_next <= inst_next_addr_base; inst_stage_next <= GET_NEXT_INSTANCE; inst_cnt_next <= 0; end if; when REMOVE_INSTANCE => assert (inst_occupied_head = INSTANCE_MEMORY_MAX_ADDRESS) report "Request Removal on empty memory" severity FAILURE; inst_prev_addr_base_next <= INSTANCE_MEMORY_MAX_ADDRESS; inst_addr_base_next <= inst_occupied_head; inst_addr_next <= inst_occupied_head; inst_stage_next <= REMOVE_INSTANCE; 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; when UNMARK_INTANCES => -- Empty Memory Guard if (inst_occupied_head /= INSTANCE_MEMORY_MAX_ADDRESS) then inst_addr_base_next <= inst_occupied_head; inst_addr_next <= inst_occupied_head + IMF_NEXT_ADDR_OFFSET; inst_stage_next <= UNMARK_INTANCES; inst_cnt_next <= 0; end if; when others => null; end case; end if; when SEARCH_INSTANCE_HASH => inst_ren <= '1'; inst_cnt_next <= inst_cnt + 1; inst_addr_next <= inst_addr + 1; case (inst_cnt) is -- Preload when 0 => null; -- Next Instance when 1 => inst_next_addr_base_next <= inst_read_data; -- Key Hash 1/4 when 2 => -- No Match if (inst_read_data /= inst_latch_data.key_hash(0)) then -- Reached List Tail, No Match if (inst_addr_base = INSTANCE_MEMORY_MAX_ADDRESS) then inst_addr_base_next <= INSTANCE_MEMORY_MAX_ADDRESS; --No match -- DONE inst_stage_next <= IDLE; else -- Continue Search inst_prev_addr_base_next <= inst_addr_base; inst_addr_base_next <= inst_next_addr_base; inst_addr_next <= inst_next_addr_base; inst_cnt_next <= 0; end if; end if; -- Key Hash 2/4 when 3 => -- No Match if (inst_read_data /= inst_latch_data.key_hash(1)) then -- Reached List Tail, No Match if (inst_addr_base = INSTANCE_MEMORY_MAX_ADDRESS) then inst_addr_base_next <= INSTANCE_MEMORY_MAX_ADDRESS; --No match -- DONE inst_stage_next <= IDLE; else -- Continue Search inst_prev_addr_base_next <= inst_addr_base; inst_addr_base_next <= inst_next_addr_base; inst_addr_next <= inst_next_addr_base; inst_cnt_next <= 0; end if; end if; -- Key Hash 3/4 when 4 => -- No Match if (inst_read_data /= inst_latch_data.key_hash(2)) then -- Reached List Tail, No Match if (inst_addr_base = INSTANCE_MEMORY_MAX_ADDRESS) then inst_addr_base_next <= INSTANCE_MEMORY_MAX_ADDRESS; --No match -- DONE inst_stage_next <= IDLE; else -- Continue Search inst_prev_addr_base_next <= inst_addr_base; inst_addr_base_next <= inst_next_addr_base; inst_addr_next <= inst_next_addr_base; inst_cnt_next <= 0; end if; end if; -- Key Hash 4/4 when 5 => -- No Match if (inst_read_data /= inst_latch_data.key_hash(3)) then -- Reached List Tail, No Match if (inst_addr_base = INSTANCE_MEMORY_MAX_ADDRESS) then inst_addr_base_next <= INSTANCE_MEMORY_MAX_ADDRESS; --No match -- DONE inst_stage_next <= IDLE; else -- Continue Search inst_prev_addr_base_next <= inst_addr_base; inst_addr_base_next <= inst_next_addr_base; inst_addr_next <= inst_next_addr_base; inst_cnt_next <= 0; end if; -- 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; end if; when others => null; end case; when SEARCH_INSTANCE_ADDR => inst_cnt_next <= inst_cnt + 1; inst_addr_next <= inst_addr + 1; case (inst_cnt) is -- Preload when 0 => inst_ren <= '1'; -- Next Instance when 1 => inst_prev_addr_base_next <= inst_addr_base; inst_addr_base_next <= inst_read_data; -- 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; -- No Match else -- Reached List Tail, No Match if (inst_read_data = INSTANCE_MEMORY_MAX_ADDRESS) then inst_addr_base_next <= INSTANCE_MEMORY_MAX_ADDRESS; --No match -- DONE inst_stage_next <= IDLE; else -- Continue Search inst_addr_next <= inst_read_data; inst_cnt_next <= 0; end if; end if; when others => null; end case; when GET_NEXT_INSTANCE => case (inst_cnt) is -- Preload when 0 => inst_wen <= '1'; -- Next Instance when 1 => -- Latch Next Instance inst_next_addr_base_next <= inst_read_data; -- 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; end case; when GET_INSTANCE_DATA_2 => -- 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; -- Sample Count when 6 => inst_data_next.sample_cnt <= inst_read_data; -- Disposed Generation Count when 7 => inst_data_next.disposed_gen_cnt <= inst_read_data; -- No Writers Generation Count when 8 => inst_data_next.no_writers_gen_cnt <= inst_read_data; -- DONE inst_stage_next <= IDLE; when others => null; end case; when GET_INSTANCE_DATA_1 => -- 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; -- Status Info when 1 => inst_data_next.status_info <= inst_read_data; -- Sample Count when 2 => inst_data_next.sample_cnt <= inst_read_data; -- Disposed Generation Count when 3 => inst_data_next.disposed_gen_cnt <= inst_read_data; -- No Writers Generation Count when 4 => inst_data_next.no_writers_gen_cnt <= inst_read_data; -- Ignore Deadline 1/2 when 5 => inst_data_next.ignore_deadline(0) <= unsigned(inst_read_data); -- Ignore Deadline 2/2 when 5 => inst_data_next.ignore_deadline(1) <= unsigned(inst_read_data); -- DONE inst_stage_next <= GET_WRITER_BITMAP; inst_cnt_next <= 0; when others => null; end case; when GET_WRITER_BITMAP => inst_cnt_next <= inst_cnt + 1; inst_latch_data_next.writer_bitmap(inst_cnt) <= inst_read_data; if (inst_cnt = writer_bitmap'length-1) then -- DONE inst_stage_next <= IDLE; end if; when FIND_POS => inst_cnt_next <= inst_cnt + 1; inst_addr_next <= inst_addr + 1; inst_ren <= '1'; -- NOTE: Instances are inserted in KEY_HASH numerical order. case (inst_cnt) is -- Preload when 0 => null; -- Next Instance when 1 => inst_next_addr_base_next <= inst_read_data; -- Key Hash 1/4 when 2 => -- Found Position if (inst_latch_data.key_hash(0) < inst_read_data) then inst_next_addr_base_next <= inst_addr_base; -- Occupied List Head if (inst_prev_addr_base = INSTANCE_MEMORY_MAX_ADDRESS) then assert (inst_addr_base = inst_occupied_head) inst_occupied_head_next <= inst_empty_head; inst_addr_base_next <= inst_empty_head; inst_addr_next <= inst_empty_head + IMF_NEXT_ADDR_OFFSET; inst_stage_next <= INSERT_INSTANCE; cnt_next <= 1; -- Skip First Step else inst_addr_base_next <= inst_prev_addr_base; inst_addr_next <= inst_prev_addr_base + IMF_NEXT_ADDR_OFFSET; inst_stage_next <= INSERT_INSTANCE; cnt_next <= 0; end if; -- BIGGER-THAN elsif (inst_latch_data.key_hash(0) /= inst_read_data) then -- Continue inst_prev_addr_base_next <= inst_addr_base; inst_addr_next <= inst_next_addr_base; inst_addr_base_next <= inst_next_addr_base; cnt_next <= 0; end if; -- Key Hash 2/4 when 3 => -- Found Position if (inst_latch_data.key_hash(1) < inst_read_data) then inst_next_addr_base_next <= inst_addr_base; -- Occupied List Head if (inst_prev_addr_base = INSTANCE_MEMORY_MAX_ADDRESS) then assert (inst_addr_base = inst_occupied_head) inst_occupied_head_next <= inst_empty_head; inst_addr_base_next <= inst_empty_head; inst_addr_next <= inst_empty_head + IMF_NEXT_ADDR_OFFSET; inst_stage_next <= INSERT_INSTANCE; cnt_next <= 1; -- Skip First Step else inst_addr_base_next <= inst_prev_addr_base; inst_addr_next <= inst_prev_addr_base + IMF_NEXT_ADDR_OFFSET; inst_stage_next <= INSERT_INSTANCE; cnt_next <= 0; end if; -- BIGGER-THAN elsif (inst_latch_data.key_hash(1) /= inst_read_data) then -- Continue inst_prev_addr_base_next <= inst_addr_base; inst_addr_next <= inst_next_addr_base; inst_addr_base_next <= inst_next_addr_base; cnt_next <= 0; end if; -- Key Hash 3/4 when 4 => -- Found Position if (inst_latch_data.key_hash(2) < inst_read_data) then inst_next_addr_base_next <= inst_addr_base; -- Occupied List Head if (inst_prev_addr_base = INSTANCE_MEMORY_MAX_ADDRESS) then assert (inst_addr_base = inst_occupied_head) inst_occupied_head_next <= inst_empty_head; inst_addr_base_next <= inst_empty_head; inst_addr_next <= inst_empty_head + IMF_NEXT_ADDR_OFFSET; inst_stage_next <= INSERT_INSTANCE; cnt_next <= 1; -- Skip First Step else inst_addr_base_next <= inst_prev_addr_base; inst_addr_next <= inst_prev_addr_base + IMF_NEXT_ADDR_OFFSET; inst_stage_next <= INSERT_INSTANCE; cnt_next <= 0; end if; -- BIGGER-THAN elsif (inst_latch_data.key_hash(2) /= inst_read_data) then -- Continue inst_prev_addr_base_next <= inst_addr_base; inst_addr_next <= inst_next_addr_base; inst_addr_base_next <= inst_next_addr_base; cnt_next <= 0; end if; -- Key Hash 4/4 when 5 => -- Found Position if (inst_latch_data.key_hash(3) < inst_read_data) then inst_next_addr_base_next <= inst_addr_base; -- Occupied List Head if (inst_prev_addr_base = INSTANCE_MEMORY_MAX_ADDRESS) then assert (inst_addr_base = inst_occupied_head) inst_occupied_head_next <= inst_empty_head; inst_addr_base_next <= inst_empty_head; inst_addr_next <= inst_empty_head + IMF_NEXT_ADDR_OFFSET; inst_stage_next <= INSERT_INSTANCE; cnt_next <= 1; -- Skip First Step else inst_addr_base_next <= inst_prev_addr_base; inst_addr_next <= inst_prev_addr_base + IMF_NEXT_ADDR_OFFSET; inst_stage_next <= INSERT_INSTANCE; cnt_next <= 0; end if; else assert (inst_latch_data.key_hash(3) /= inst_read_data) report "Doublicate Instance Detected" severity FAILURE; -- Continue inst_prev_addr_base_next <= inst_addr_base; inst_addr_next <= inst_next_addr_base; inst_addr_base_next <= inst_next_addr_base; cnt_next <= 0; end if; when others => null; end case; when INSERT_INSTANCE => inst_addr_next <= inst_addr + 1; inst_cnt_next <= inst_cnt + 1; case (inst_cnt) is -- Next Pointer (Previous Instance) when 0 => inst_write_data <= inst_empty_head; inst_wen <= '1'; inst_addr_next <= inst_empty_head; inst_addr_base_next <= inst_empty_head; -- Preload when 1 => inst_ren <= '1'; inst_addr_next <= inst_addr; -- Keep Addr -- Next Pointer (New Instance) when 2 => -- Fix Empty List Head inst_empty_head_next <= inst_read_data; inst_write_data <= inst_next_addr_base; inst_wen <= '1'; -- Key Hash 1/4 when 3 => inst_write_data <= inst_latch_data.key_hash(0); inst_wen <= '1'; -- Key Hash 2/4 when 4 => inst_write_data <= inst_latch_data.key_hash(1); inst_wen <= '1'; -- Key Hash 3/4 when 5 => inst_write_data <= inst_latch_data.key_hash(2); inst_wen <= '1'; -- Key Hash 4/4 when 6 => inst_write_data <= inst_latch_data.key_hash(3); inst_wen <= '1'; -- Status Info when 7 => inst_write_data <= inst_latch_data.status_info; inst_wen <= '1'; -- Sample Count when 8 => inst_write_data <= std_logic_vector(to_unsigned(1, WORD_WIDTH)); inst_wen <= '1'; -- Disposed Generation Count when 9 => inst_write_data <= (others => '0'); inst_wen <= '1'; -- No Writers Generation Count when 10 => inst_write_data <= (others => '0'); inst_wen <= '1'; if (TIME_BASED_FILTER_QOS /= DURATION_ZERO) then inst_cnt <= 11; else inst_stage_next <= SET_WRITER_BITMAP; inst_cnt_next <= 0; end if; -- Ignore Deadline 1/2 when 11 => if (TIME_BASED_FILTER_QOS /= DURATION_ZERO) then inst_write_data <= inst_latch_data.deadline(0); inst_wen <= '1'; end if; -- Ignore Deadline 1/2 when 12 => if (TIME_BASED_FILTER_QOS /= DURATION_ZERO) then inst_write_data <= inst_latch_data.deadline(1); inst_wen <= '1'; inst_stage_next <= SET_WRITER_BITMAP; inst_cnt_next <= 0; end if; when others => null; end case; when SET_WRITER_BITMAP => inst_wen <= '1'; inst_addr_next <= inst_addr + 1; inst_cnt_next <= inst_cnt + 1; inst_write_data <= inst_latch_data.writer_bitmap(inst_cnt); -- Exit Condition if (inst_cnt = inst_latch_data.writer_bitmap'length-1) then -- DONE inst_stage_next <= IDLE; end if; when UPDATE_INSTANCE => inst_cnt_next <= inst_cnt + 1; case (inst_cnt) is -- Status Info when 0 => inst_wen <= '1'; inst_write_data <= inst_latch_data.status_info; inst_data_next.status_info <= inst_latch_data.status_info; if ((inst_latch_data.update_flags and SAMPLE_CNT_FLAG) = SAMPLE_CNT_FLAG) then inst_addr_next <= inst_addr_base + IMF_SAMPLE_CNT_OFFSET; inst_cnt_next <= 1; elsif ((inst_latch_data.update_flags and DISPOSED_CNT_FLAG) = DISPOSED_CNT_FLAG) then inst_addr_next <= inst_addr_base + IMF_DISPOSED_GEN_CNT_OFFSET; inst_cnt_next <= 2; elsif ((inst_latch_data.update_flags and NO_WRITERS_CNT_FLAG) = NO_WRITERS_CNT_FLAG) then inst_addr_next <= inst_addr_base + IMF_NO_WRITERS_GEN_CNT_OFFSET; inst_cnt_next <= 3; elsif (TIME_BASED_FILTER_QOS /= DURATION_ZERO and (inst_latch_data.update_flags and IGNORE_DEADLINE_FLAG) = IGNORE_DEADLINE_FLAG) then inst_addr_next <= inst_addr_base + IMF_IGNORE_DEADLINE_OFFSET; inst_cnt_next <= 4; elsif ((inst_latch_data.update_flags and WRITER_BITMAP_FLAG) = WRITER_BITMAP_FLAG) then inst_addr_next <= inst_addr_base + IMF_WRITER_BITMAP_OFFSET; inst_stage_next <= SET_WRITER_BITMAP; inst_cnt_next <= 0; else -- DONE inst_stage_next <= IDLE; end if; -- Sample Count when 1 => inst_wen <= '1'; inst_write_data <= inst_latch_data.sample_cnt; inst_data_next.sample_cnt <= inst_latch_data.sample_cnt; if ((inst_latch_data.update_flags and DISPOSED_CNT_FLAG) = DISPOSED_CNT_FLAG) then inst_addr_next <= inst_addr_base + IMF_DISPOSED_GEN_CNT_OFFSET; inst_cnt_next <= 2; elsif ((inst_latch_data.update_flags and NO_WRITERS_CNT_FLAG) = NO_WRITERS_CNT_FLAG) then inst_addr_next <= inst_addr_base + IMF_NO_WRITERS_GEN_CNT_OFFSET; inst_cnt_next <= 3; elsif (TIME_BASED_FILTER_QOS /= DURATION_ZERO and (inst_latch_data.update_flags and IGNORE_DEADLINE_FLAG) = IGNORE_DEADLINE_FLAG) then inst_addr_next <= inst_addr_base + IMF_IGNORE_DEADLINE_OFFSET; inst_cnt_next <= 4; elsif ((inst_latch_data.update_flags and WRITER_BITMAP_FLAG) = WRITER_BITMAP_FLAG) then inst_addr_next <= inst_addr_base + IMF_WRITER_BITMAP_OFFSET; inst_stage_next <= SET_WRITER_BITMAP; inst_cnt_next <= 0; else -- DONE inst_stage_next <= IDLE; end if; -- Disposed Generation Count when 2 => inst_wen <= '1'; inst_write_data <= inst_latch_data.gen_cnt; inst_data_next.disposed_gen_cnt <= inst_latch_data.gen_cnt; -- NOTE: Both Generation Counters cannot be updated on the same update procedure if (TIME_BASED_FILTER_QOS /= DURATION_ZERO and (inst_latch_data.update_flags and IGNORE_DEADLINE_FLAG) = IGNORE_DEADLINE_FLAG) then inst_addr_next <= inst_addr_base + IMF_IGNORE_DEADLINE_OFFSET; inst_cnt_next <= 4; elsif ((inst_latch_data.update_flags and WRITER_BITMAP_FLAG) = WRITER_BITMAP_FLAG) then inst_addr_next <= inst_addr_base + IMF_WRITER_BITMAP_OFFSET; inst_stage_next <= SET_WRITER_BITMAP; inst_cnt_next <= 0; else -- DONE inst_stage_next <= IDLE; end if; -- No Writers Generation Count when 3 => inst_wen <= '1'; inst_write_data <= inst_latch_data.gen_cnt; inst_data_next.no_writers_gen_cnt <= inst_latch_data.gen_cnt; if (TIME_BASED_FILTER_QOS /= DURATION_ZERO and (inst_latch_data.update_flags and IGNORE_DEADLINE_FLAG) = IGNORE_DEADLINE_FLAG) then inst_addr_next <= inst_addr_base + IMF_IGNORE_DEADLINE_OFFSET; inst_cnt_next <= 4; elsif ((inst_latch_data.update_flags and WRITER_BITMAP_FLAG) = WRITER_BITMAP_FLAG) then inst_addr_next <= inst_addr_base + IMF_WRITER_BITMAP_OFFSET; inst_stage_next <= SET_WRITER_BITMAP; inst_cnt_next <= 0; else -- DONE inst_stage_next <= IDLE; end if; -- Ignore Deadline 1/2 when 4 => if (TIME_BASED_FILTER_QOS /= DURATION_ZERO) then inst_wen <= '1'; inst_write_data <= std_logic_vector(inst_latch_data.ignore_deadline(0)); inst_data_next.deadline <= inst_latch_data.ignore_deadline(0); end if; -- Ignore Deadline 2/2 when 5 => if (TIME_BASED_FILTER_QOS /= DURATION_ZERO) then inst_wen <= '1'; inst_write_data <= std_logic_vector(inst_latch_data.ignore_deadline(1)); inst_data_next.deadline <= inst_latch_data.ignore_deadline(1); if ((inst_latch_data.update_flags and WRITER_BITMAP_FLAG) = WRITER_BITMAP_FLAG) then inst_addr_next <= inst_addr_base + IMF_WRITER_BITMAP_OFFSET; inst_stage_next <= SET_WRITER_BITMAP; inst_cnt_next <= 0; else -- DONE inst_stage_next <= IDLE; end if; end if; when others => null; end case; when REMOVE_INSTANCE => inst_cnt_next <= inst_cnt + 1; case (inst_cnt) is -- Preload when 0 => inst_ren <= '1'; inst_addr_next <= inst_prev_addr_base + IMF_NEXT_ADDR_OFFSET; -- Next Pointer (Previous Occupied Instance) when 1 => -- Fix Pointer inst_write_data <= inst_read_data; inst_wen <= '1'; inst_addr_next <= inst_addr_base + IMF_NEXT_ADDR_OFFSET; -- Next Pointer (Current Instance) when 2 => -- Fix Pointer inst_write_data <= inst_empty_head; inst_wen <= '1'; -- Fix Empty List Head inst_empty_head_next <= inst_addr_base; -- Reset inst_data_next <= ZERO_INSTANCE_DATA; inst_addr_base_next <= INSTANCE_MEMORY_MAX_ADDRESS; -- DONE inst_stage_next <= IDLE; when others => null; end case; when UNMARK_INTANCES => -- Precondition: inst_cnt_next <= inst_cnt + 1; case (inst_cnt) is -- Preload when 0 => inst_addr_next <= inst_addr_base + IMF_STATUS_INFO_OFFSET; inst_ren <= '1'; -- Next Pointer when 1 => inst_ren <= '1'; next_inst_next <= inst_read_data; -- Instance Status Info when 2 => inst_write_data <= inst_read_data; inst_write_data(MARK_FLAG) <= '0'; inst_wen <= '1'; -- Reached End of Instances if (next_inst = INSTANCE_MEMORY_MAX_ADDRESS) then -- DONE inst_stage_next <= IDLE; else inst_addr_base_next <= next_inst; inst_addr_next <= next_inst + IMF_NEXT_ADDR_OFFSET; inst_cnt_next <= 0; end if; when others => null; end case; when others => null; end case; end process; end architecture;