library ieee; use ieee.std_logic_1164.all; use ieee.numeric_std.all; -- TODO: Cancel KHG operation on incomplete payload parsing 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; ); port ( clk : in std_logic; reset : in std_logic; start_a : in std_logic; opcode_a : in HISTORY_CACHE_OPCODE_TYPE; res_a : out HISTORY_CACHE_RESPOSNE_TYPE; data_in_a : in std_logic_vector(WORD_WIDTH-1 downto 0); valid_in_a : in std_logic; ready_in_a : out std_logic; last_word_in_a : in std_logic; start_b : in std_logic; opcode_b : in HISTORY_CACHE_OPCODE_TYPE; res_b : out HISTORY_CACHE_RESPOSNE_TYPE; data_out_b : out std_logic_vector(WORD_WIDTH-1 downto 0); last_word_out_b : in std_logic; instance_state : in INSTANCE_STATE_TYPE; view_state : in VIEW_STATE_TYPE; sample_state : in SAMPLE_STATE; ); 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 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 := ( 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 key_hash : KEY_HASH_TYPE; instance_state : INSTANCE_STATE_TYPE; 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 := ( key_hash => (others => (others => '0')), instance_state => ALIVE, 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 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 instance_state_update : INSTANCE_STATE_TYPE := ALIVE; 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, inst_long_latch_next : std_logic_vector(CDR_LONG_WIDTH-1 downto 0) := (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 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 has_data : std_logic is sample_status_info(PAYLOAD_FLAG); alias has_key_hash : std_logic is sample_status_info(KEY_HASH_FLAG); 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, 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'); begin -- Default stage_next <= stage; res_a <= 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_a <= '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; case (stage) is when IDLE => -- DEFAULT ready_in_a <= '1'; remove_oldest_inst_sample_next <= '0'; remove_oldest_sample_next <= '0'; added_new_instance_next <= '0'; if (start_a = '1') then case (opcode_a) is when ADD_CHANGE => -- This Operation does not accept input at this time ready_in_a <= '0'; res_a <= 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_a = '1' and inst_op_done = '1') then -- Latch Writer Pos writer_pos_next <= to_integer(unsigned(data_in_a)); inst_op_start <= '1'; inst_opcode <= GET_FIRST_INSTANCE; stage_next <= REMOVE_WRITER; res_a <= ACK; end if; when others => null; end case; elsif (start_b = '1') then -- TODO end if; when ADD_SAMPLE_INFO => -- Precondition: sample_addr (empty_sample_list_head) ready_in_a <= '1'; -- Input Guard if (valid_in_a = '1') then cnt_next <= cnt + 1; sample_addr_next <= sample_addr + 1; -- Write Through sample_wen <= '1'; sample_write_data <= data_in_a; 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_a; sample_status_info_next(READ_FLAG) <= '0'; -- Latch Timestamp for ordering -- Timestamp 1/2 when 1 => ts_latch_next(0) <= data_in_a; -- Timestamp 2/2 when 2 => ts_latch_next(1) <= data_in_a; -- 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_a; -- 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_a; -- 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_a; -- 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_a; when 9 => -- Latch Input, but do not pass to Memory writer_pos_next <= to_integer(unsigned(data_in_a)); 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 <= sample_addr + 1; -- Instance Address 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_NEXT_ADDR_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_a <= khg_ready_in; else ready_in_a <= '1'; end if; -- Flow Control Guard if ((valid_in_a = '1' and has_key_hash = '0') or (valid_in_a = '1' and has_key_hash = '0' and khg_ready_in = '1')) then cnt_next <= cnt + 1; payload_addr_next <= payload_addr + PMF_NEXT_ADDR_OFFSET; -- Payload Write if (has_data = '1') then payload_write_data <= data_in_a; payload_wen <= '1'; end if; -- Key Hash Generator Write if (has_key_hash = '0') then khg_data_in <= data_in_a; khg_valid_in <= '1'; end if; -- End of Payload if (last_word_in_a = '1') then if (has_key_hash = '0') then khg_last_word_in <= '1'; stage_next <= GET_KEY_HASH; cnt_next <= 0; else stage_next <= FILTER_STAGE; 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; cnt_next <= 0; end if; end if; when NEXT_PAYLOAD_SLOT => -- Precondition: payload_addr (Beginning of current Slot) 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; else -- Latch next Payload Slot and Continue cur_payload_next <= payload_read_data; payload_addr_next <= payload_read_data + PMF_NEXT_ADDR_OFFSET; stage_next <= ADD_PAYLOAD; end if; when others => null; end case; 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'; -- 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 <= sample_addr + 1; -- Disposed Gen Counter -- 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_a <= 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_a <= REJECTED; stage_next <= IDLE; else -- Accept Change (Remove Oldest Instance Sample) remove_oldest_inst_sample_next <= '1'; res_a <= 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_a <= REJECTED; stage_next <= IDLE; else -- Accept Change (Remove Oldest Sample) remove_oldest_sample_next <= '1'; res_a <= ACCEPTED; stage_next <= UPDATE_INSTANCE; end if; else -- Accept Change res_a <= 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_a <= REJECTED; stage_next <= IDLE; -- 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_a <= REJECTED; stage_next <= IDLE; else -- Accept Change (Remove Oldest Sample) remove_oldest_sample_next <= '1'; res_a <= 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_a <= 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; instance_state_update <= NOT_ALIVE_DISPOSED; 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; instance_state_update <= NOT_ALIVE_NO_WRITERS; end if; -- Instance ALIVE/FILTERED else -- STATUS INFO tmp_update <= tmp_update or STATUS_FLAG; instance_state_update <= ALIVE; -- 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 <= sample_addr + 1; 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_INFO; sample_addr_next <= empty_sample_list_head + SMF_PREV_ADDR_OFFSET; next_sample_next <= SAMPLE_MEMORY_MAX_ADDRESS; prev_sample_next <= SAMPLE_MEMORY_MAX_ADDRESS; cnt_next <= 0; else stage_next <= FIND_POS; prev_sample_next <= newest_sample; sample_addr_next <= newest_sample + SMF_TIMESTAMP_OFFSET; cnt_next <= 0; end if; when others => null; end case; when FIND_POS => -- 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; sample_ren <= '1'; -- Timestamp 1/2 when 1 => sample_addr_next <= sample_addr + SMF_PREV_ADDR_OFFSET-(SMF_TIMESTAMP_OFFSET+1); -- Prev Addr 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 <= sample_addr + SMF_NEXT_ADDR_OFFSET-SMF_PREV_ADDR_OFFSET; -- Next Addr -- Found position (After current slot) if (ts_latch >= tmp_dw) then stage_next <= FIX_POINTERS; cnt_next <= 0; end if; -- Previous Address 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; stage_next <= FIX_POINTERS; cnt_next <= 0; else prev_sample_next <= sample_read_data; sample_addr_next <= sample_read_data + SMF_TIMESTAMP_OFFSET; cnt_next <= 0; end if; end case; when FIX_POINTERS => -- Precondition: sample_addr (Next Addr of prev_sample) cnt_next <= cnt + 1; case (cnt) is -- Preload when 0 => sample_ren <= '1'; 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_INFO; sample_addr_next <= empty_sample_list_head + SMF_PREV_ADDR_OFFSET; -- Prev Addr of New Sample 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; when 2 => -- Fix Previous Pointer sample_write_data <= empty_sample_list_head; sample_wen <= '1'; stage_next <= FINALIZE_SAMPLE_INFO; sample_addr_next <= empty_sample_list_head + SMF_PREV_ADDR_OFFSET; -- Prev Addr of New Sample cnt_next <= 0; when others => null; end case; when FINALIZE_SAMPLE_INFO => -- 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 <= sample_addr + 1; -- Next Sample -- 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; -- 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; stage_next <= REMOVE_STALE_INSTANCE; else cnt_next <= cnt; -- Keep State end if; elsif (remove_oldest_inst_sample = '1') then sample_addr_next <= cur_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 => inst_op_start <= '1'; inst_opcode <= SEARCH_INSTANCE_ADDR; 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; -- Next Addr -- Instance Address when 1 => sample_ren <= '1'; -- Oldest Instance Sample Found if (sample_read_data = inst_addr_base) 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; -- Instance Addr cnt_next <= 0; when others => null; end case; when REMOVE_SAMPLE => -- Precondition: cur_sample set, sample_addr (Previous Address 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 Addr (Current Sample) when 1 => sample_ren <= '1'; prev_sample_next <= sample_read_data; -- Next Addr (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; -- DONE stage_next <= IDLE; else inst_op_start <= '1'; inst_opcode <= UPDATE_INSTANCE; update_inst_flags <= SAMPLE_CNT_FLAG; sample_cnt <= inst_data.sample_cnt - 1; -- DONE stage_next <= IDLE; end if; end if; end if; when SKIP_ADD => case (cnt) is -- SKIP READ when 0 => ready_in_a <= '1'; -- Wait until last word from input if (last_word_in_a = '1') then cnt_next <= 1; end if; -- REJECT SAMPLE when 1 => res_a <= REJECTED; 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 inst_op_start <= '1'; instance_state_update <= NOT_ALIVE_NO_WRITERS; 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 <= NEXT_INSTANCE; 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 -- DONE stage_next <= IDLE; 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; -- DONE stage_next <= IDLE; else -- Continue Search inst_op_start <= '1'; inst_opcode <= GET_NEXT_INSTANCE; end if; end if; 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 <= ( key_hash => key_hash_next, instance_state => instance_state_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; inst_stage_next <= GET_INSTANCE_DATA; inst_cnt_next <= 0; end if; when GET_NEXT_INSTANCE => 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; 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 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 inst_stage_next <= GET_INSTANCE_DATA; inst_cnt_next <= 1; -- No preload needed 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; -- No Match if (inst_read_data /= inst_latch_data.addr) then -- Fetch Instance Data inst_stage_next <= GET_INSTANCE_DATA; inst_addr_next <= inst_read_data + IMF_STATUS_INFO_OFFSET; inst_cnt_next <= 0; -- Match else -- 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_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; inst_addr_next <= inst_addr_base + IMF_STATUS_INFO_OFFSET; inst_cnt_next <= 0; inst_stage_next <= GET_INSTANCE_DATA; end case; when GET_INSTANCE_DATA => -- 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 /= 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 < 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 /= 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_long_latch; case (inst_latch_data.instance_state) is when ALIVE => inst_write_data(NOT_ALIVE_DISPOSED_FLAG) <= '0'; inst_write_data(NOT_ALIVE_NO_WRITERS_FLAG) <= '0'; inst_write_data(LIVELINESS_FLAG) <= '1'; when NOT_ALIVE_DISPOSED => inst_write_data(NOT_ALIVE_DISPOSED_FLAG) <= '1'; inst_write_data(NOT_ALIVE_NO_WRITERS_FLAG) <= '0'; inst_write_data(LIVELINESS_FLAG) <= '1'; when NOT_ALIVE_NO_WRITERS => inst_write_data(NOT_ALIVE_DISPOSED_FLAG) <= '0'; inst_write_data(NOT_ALIVE_NO_WRITERS_FLAG) <= '1'; inst_write_data(LIVELINESS_FLAG) <= '1'; end case; 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; 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; -- 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; 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)); 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)); 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 Instance (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 Instance (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; -- DONE inst_stage_next <= IDLE; when others => null; end case; when others => null; end case; end process; end architecture;