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; GENERATION_COUNTERS : boolean := TRUE; ); 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; ); 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 when GENERATION_COUNTERS else SMF_INSTANCE_ADDR_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 when (GENERATION_COUNTERS) else IMF_SAMPLE_CNT_OFFSET+1 when (MAX_SAMPLES_PER_INSTANCE /= LENGTH_UNLIMITED) else IMF_STATUS_INFO_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 when (GENERATION_COUNTERS) else IMF_SAMPLE_CNT_OFFSET+1 when (MAX_SAMPLES_PER_INSTANCE /= LENGTH_UNLIMITED) else IMF_STATUS_INFO_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; 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); release_lock : std_logic; end record; constant ZERO_INST_LATCH_DATA : INST_LATCH_DATA_TYPE := ( key_hash => (others => (others => '0')), instance_state => ALIVE, gen_cnt => (others => '0'), deadline => TIME_INVALID, writer_bitmap => (others => (others => '0')), update_flags => (others => '0'), release_lock => '0' ); --*****SIGNAL DECLARATION signal sample_addr_a, sample_addr_a_next : unsigned(SAMPLE_MEMORY_ADDR_WIDTH-1 downto 0) := (others => '0'); signal sample_addr_b, sample_addr_b_next : unsigned(SAMPLE_MEMORY_ADDR_WIDTH-1 downto 0) := (others => '0'); signal sample_wen_a, sample_wen_b : std_logic := '0'; signal sample_ren_a, sample_ren_b : std_logic := '0'; signal sample_read_data_a, sample_read_data_b : std_logic_vector(WORD_WIDTH-1 downto 0) := (others => '0'); signal sample_write_data_a, sample_write_data_b : std_logic_vector(WORD_WIDTH-1 downto 0) := (others => '0'); signal payload_addr_a, payload_addr_a_next : unsigned(PAYLOAD_MEMORY_ADDR_WIDTH-1 downto 0) := (others => '0'); signal payload_addr_b, payload_addr_b_next : unsigned(PAYLOAD_MEMORY_ADDR_WIDTH-1 downto 0) := (others => '0'); signal payload_wen_a, payload_wen_b : std_logic := '0'; signal payload_ren_a, payload_ren_b : std_logic := '0'; signal payload_read_data_a, payload_read_data_b : std_logic_vector(WORD_WIDTH-1 downto 0) := (others => '0'); signal payload_write_data_a, payload_write_data_b : std_logic_vector(WORD_WIDTH-1 downto 0) := (others => '0'); signal inst_addr_a, inst_addr_a_next : unsigned(PAYLOAD_MEMORY_ADDR_WIDTH-1 downto 0) := (others => '0'); signal inst_addr_b, inst_addr_b_next : unsigned(PAYLOAD_MEMORY_ADDR_WIDTH-1 downto 0) := (others => '0'); signal inst_wen_a, inst_wen_b : std_logic := '0'; signal inst_ren_a, inst_ren_b : std_logic := '0'; signal inst_read_data_a, inst_read_data_b : std_logic_vector(WORD_WIDTH-1 downto 0) := (others => '0'); signal inst_write_data_a, inst_write_data_b : 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_a, stage_a_next : STAGE_TYPE := IDLE; signal cnt_a, cnt_a_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 empty_payload_list_tail, empty_payload_list_tail_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 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 : INSTANCE_STATE_TYPE := ALIVE; signal key_hash, key_hash_next : KEY_HASH_TYPE := (others => (others => '0')); signal od_instance_sample_removal : std_logic := '0'; signal od_oldest_sample_removal : std_logic := '0'; signal od_sample_removal_done : 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 release_inst_lock : std_logic := '0'; signal inst_op_start_a : std_logic := '0'; signal inst_op_done_a : std_logic := '0'; signal inst_opcode_a : INSTANCE_OPCODE_TYPE := NOP; signal inst_stage_a, inst_stage_a_next : INST_STAGE_TYPE := IDLE; signal inst_addr_base_a, inst_addr_base_a_next : unsigned(INSTANCE_MEMORY_ADDR_WIDTH-1 downto 0) := (others => '0'); signal inst_addr_base_a, inst_addr_base_a_next : unsigned(INSTANCE_MEMORY_ADDR_WIDTH-1 downto 0) := (others => '0'); signal inst_next_addr_base_a, inst_next_addr_base_a_next : unsigned(INSTANCE_MEMORY_ADDR_WIDTH-1 downto 0) := (others => '0'); signal inst_prev_addr_base_a, inst_prev_addr_base_a_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_tail, inst_occupied_tail_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_a : std_logic_vector(0 to UPDATE_INSTANCE_FLAG_WIDTH-1) := (others => '0'); signal inst_cnt_a, inst_cnt_a_next : natural range TODO := 0; signal inst_mem_full, inst_mem_full_next : std_logic := '0'; signal inst_delete_lock_a, inst_delete_lock_a_next : std_logic := '0'; signal inst_atomic_lock_a : std_logic := '0'; signal inst_long_latch_a, inst_long_latch_a_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_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.true_dual_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_a => sample_addr_a, addr_b => sample_addr_b, wen_a => sample_wen_a, wen_b => sample_wen_b, ren_a => sample_ren_a, ren_b => sample_ren_b, wr_data_a => sample_write_data_a, wr_data_b => sample_write_data_b, rd_data_a => sample_read_data_a, rd_data_b => sample_read_data_b ); payload_ram_inst : entity work.true_dual_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_a => payload_addr_a, addr_b => payload_addr_b, wen_a => payload_wen_a, wen_b => payload_wen_b, ren_a => payload_ren_a, ren_b => payload_ren_b, wr_data_a => payload_write_data_a, wr_data_b => payload_write_data_b, rd_data_a => payload_read_data_a, rd_data_b => payload_read_data_b ); instance_ram_inst : entity work.true_dual_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_a => inst_addr_a, addr_b => inst_addr_b, wen_a => inst_wen_a, wen_b => inst_wen_b, ren_a => inst_ren_a, ren_b => inst_ren_b, wr_data_a => inst_write_data_a, wr_data_b => inst_write_data_b, rd_data_a => inst_read_data_a, rd_data_b => inst_read_data_b ); 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_a_next <= stage_a; res_a <= UNDEFINED; sample_addr_a_next <= sample_addr_a; sample_write_data_a <= (others => '0'); sample_ren_a <= '0'; sample_wen_a <= '0'; payload_addr_a_next <= payload_addr_a; payload_write_data_a <= (others => '0'); payload_ren_a <= '0'; payload_wen_a <= '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; 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_a <= NOP; key_hash_next <= key_hash; sample_status_info_next <= sample_status_info; inst_op_start_a <= '0'; khg_last_word_in <= '0'; khg_data_in <= (others => '0'); khg_valid_in <= '0'; khg_ready_out <= '0'; writer_bitmap <= (others => '0'); od_instance_sample_removal <= '0'; od_oldest_sample_removal <= '0'; release_inst_lock <= '0'; -- Reset Payload Memory Fullness Indicator if (payload_mem_full = '1' and empty_payload_list_head /= empty_payload_list_tail) then payload_mem_full_next <= '0'; end if; -- Reset Sample Memory Fullness Indicator if (sample_mem_full = '1' and empty_sample_list_head /= empty_sample_list_tail) then sample_mem_full_next <= '0'; end if; case (stage_a) is when IDLE => -- Release Instance Memory Lock if (inst_delete_lock_a = '1' and inst_op_done_a = '1') then inst_op_start_a <= '1'; inst_opcode_a <= RELEASE_LOCK; end if; if (start_a = '1') then ready_in_a <= '1'; case (opcode_a) is when ADD_CHANGE => -- This Operation does not accept input at this time ready_in_a <= '0'; -- If memory Full if (sample_mem_full = '1' or payload_mem_full = '1') then stage_a_next <= WAIT_FOR_REMOVE; res_a <= ACK; else stage_a_next <= ADD_SAMPLE_INFO; sample_addr_a_next <= empty_sample_list_head; cnt_a_next <= 0; res_a <= ACK; end if; when REMOVE_WRITER => -- Input and Memory Gurad if (valid_in_a = '1' and inst_op_done_a = '1') then -- Latch Writer Pos writer_pos_next <= to_integer(unsigned(data_in_a)); inst_op_start_a <= '1'; inst_opcode_a <= GET_FIRST_INSTANCE; stage_a_next <= REMOVE_WRITER; res_a <= ACK; end if; when others => null; end case; end if; when ADD_SAMPLE_INFO => -- Precondition: sample_addr_a (empty_sample_list_head) ready_in_a <= '1'; -- Input Guard if (valid_in_a = '1') then cnt_a_next <= cnt_a + 1; sample_addr_a_next <= sample_addr_a + 1; -- Write Through sample_wen_a <= '1'; sample_write_data_a <= data_in_a; case (cnt_a) is -- Status Info when 0 => -- Initialize local status bits sample_write_data_a(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; -- Lifespna Deadline 2/2 when 4 => -- Skip Key Hash, if not available if (has_key_hash = '0') then cnt_a_next <= 9; end if; -- Latch Key Hash -- Key Hash 1/4 when 5 => -- Latch Input, but do not pass to Memory sample_wen_a <= '0'; sample_addr_a_next <= sample_addr_a; key_hash_next(0) <= data_in_a; -- Key Hash 2/4 when 6 => -- Latch Input, but do not pass to Memory sample_wen_a <= '0'; sample_addr_a_next <= sample_addr_a; key_hash_next(1) <= data_in_a; -- Key Hash 3/4 when 7 => -- Latch Input, but do not pass to Memory sample_wen_a <= '0'; sample_addr_a_next <= sample_addr_a; key_hash_next(2) <= data_in_a; -- Key Hash 4/4 when 8 => -- Latch Input, but do not pass to Memory sample_wen_a <= '0'; sample_addr_a_next <= sample_addr_a; 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_a <= '0'; sample_addr_a_next <= sample_addr_a; stage_a_next <= ADD_PAYLOAD_ADDRESS; when others => null; end case; end if; when ADD_PAYLOAD_ADDRESS => -- Precondition: sample_addr_a (Payload Address) sample_addr_a_next <= sample_addr_a + 1; -- Instance Address if (has_data = '1') then -- Store Payload Address sample_wen_a <= '1'; sample_write_data_a <= empty_payload_list_head; payload_addr_a_next <= empty_payload_list_head + PMF_NEXT_ADDR_OFFSET; cur_payload_next <= empty_payload_list_head; else -- Mark Sample with no Payload sample_wen_a <= '1'; sample_write_data_a <= PAYLOAD_MEMORY_MAX_ADDRESS; end if; -- If key Hash is avialable, start the Instacne Search first if (has_key_hash = '1') then stage_a_next <= INITIATE_INSTANCE_SEARCH; else stage_a_next <= ADD_PAYLOAD; cnt_a_next <= 0; end if; when ADD_PAYLOAD => -- Precondition (if has_data = '1'): cur_payload set (Current Slot), payload_addr_a (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_a_next <= cnt_a + 1; payload_addr_a_next <= payload_addr_a + PMF_NEXT_ADDR_OFFSET; -- Payload Write if (has_data = '1') then payload_write_data_a <= data_in_a; payload_wen_a <= '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_a_next <= GET_KEY_HASH; cnt_a_next <= 0; else stage_a_next <= FILTER_STAGE; end if; -- End of Payload Slot elsif (has_data = '1' and cnt_a = PAYLOAD_FRAME_SIZE-2) then stage_a_next <= NEXT_PAYLOAD_SLOT; payload_addr_a_next <= cur_payload; cnt_a_next <= 0; end if; end if; when NEXT_PAYLOAD_SLOT => -- Precondition: payload_addr_a (Beginning of current Slot) cnt_a_next <= cnt_a + 1; case (cnt_a) is -- Preload when 0 => payload_ren_a <= '1'; when 1 => -- No Empty Payload Slots available if (payload_read_data_a = PAYLOAD_MEMORY_MAX_ADDRESS) then -- TODO else -- Latch next Payload Slot and Continue cur_payload_next <= payload_read_data_a; payload_addr_a_next <= payload_read_data_a + PMF_NEXT_ADDR_OFFSET; stage_a_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_a_next <= cnt_a + 1; -- Latch Key Hash key_hash_next(cnt_a) <= khg_data_out; -- Exit Condition if (khg_last_word_out = '1') then -- DONE stage_a_next <= INITIATE_INSTANCE_SEARCH; end if; end if; when INITIATE_INSTANCE_SEARCH => -- Memory Operation Guard if (inst_op_done_a = '1') then inst_opcode_a <= SEARCH_INSTANCE; inst_op_start_a <= '1'; -- Payload not yet stored if (has_data = '1') then stage_a_next <= ADD_PAYLOAD; cnt_a_next <= 0; else stage_a_next <= FILTER_STAGE; end if; end if; when FILTER_STAGE => -- Precondition: sample_addr_a (Instance Address of New Sample) -- Wait for Instance Search to finish if (inst_op_done_a = '1') then sample_addr_a_next <= sample_addr_a + 1; -- Disposed Gen Counter (Prev Address if GENERATION_COUNTERS=FALSE) -- Instance Found if (inst_addr_base_a /= INSTANCE_MEMORY_MAX_ADDRESS) then -- Store Instance Address sample_write_data_a <= inst_addr_base_a; sample_wen_a <= '1'; -- TIME_BASED_FILTER QOS if (TIME_BASED_FILTER_QOS /= DURATION_ZERO and time < inst_data.ignore_deadline) then -- Reject Change res_a <= REJECTED; stage_a_next <= IDLE; -- RESOURCE_LIMITS_QOS / HISTORY_QOS elsif (MAX_SAMPLES_PER_INSTANCE /= LENGTH_UNLIMITED and inst_data.sample_cnt = MAX_SAMPLES_PER_INSTANCE) then if (HISTORY_QOS = KEEP_LAST_HISTORY_QOS) then -- Reject Change res_a <= REJECTED; stage_a_next <= IDLE; else od_instance_sample_removal <= '1'; -- Wait until B process completes On-Demand Sample Removal if (od_sample_removal_done = '1') then -- Accept Change res_a <= ACCEPTED; stage_a_next <= UPDATE_INSTANCE; end if; end if; else -- Accept Change res_a <= ACCEPTED; stage_a_next <= UPDATE_INSTANCE; end if; else -- Store Instance Address sample_write_data_a <= inst_empty_head; sample_wen_a <= '1'; -- MAX_INSTANCES Reached (Instance Memory Full) if (inst_mem_full = '1') then -- Reject Change res_a <= REJECTED; stage_a_next <= IDLE; 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_a <= INSERT_INSTANCE; inst_op_start_a <= '1'; release_inst_lock <= '1'; if (has_data = '1') then payload_addr_a_next <= cur_payload; stage_a_next <= FINALIZE_PAYLOAD; cnt_a_next <= 0; else stage_a_next <= SAMPLE_PRE_FINISH; cnt_a_next <= 0 when GENERATION_COUNTERS else 2; end if; else -- Ignore stage_a_next <= IDLE; end if; end if; end if; end if; when UPDATE_INSTANCE => -- Memory Operation Guard if (inst_op_done_a = '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 <= 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 <= NOT_ALIVE_NO_WRITERS; end if; -- Instance ALIVE/FILTERED else -- STATUS INFO tmp_update <= tmp_update or STATUS_FLAG; instance_state <= ALIVE; -- GENERATION COUNTERS if (GENERATION_COUNTERS) then -- 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; 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; -- INSANCE SAMPLE COUNT if (MAX_SAMPLES_PER_INSTANCE /= LENGTH_UNLIMITED) 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_a <= UPDATE_INSTANCE; inst_op_start_a <= '1'; release_inst_lock <= '1'; update_inst_flags_a <= tmp_update; if (has_data = '1') then payload_addr_a_next <= cur_payload; stage_a_next <= FINALIZE_PAYLOAD; cnt_a_next <= 0; else stage_a_next <= SAMPLE_PRE_FINISH; cnt_a_next <= 0 when GENERATION_COUNTERS else 2; end if; end if; when FINALIZE_PAYLOAD => -- Precondition: payload_addr_a (Beginning of Last Added Payload Slot) cnt_a_next <= cnt_a + 1; case (cnt_a) is -- Preload when 0 => payload_ren_a <= '1'; when 1 => -- No Empty Payload Slot available if (payload_read_data_a = PAYLOAD_MEMORY_MAX_ADDRESS) then assert (cur_payload = empty_payload_list_tail) report "Payload List empty, but HEAD /= TAIL" severity FAILURE; -- Signal Sample Memory Full payload_mem_full_next <= '1'; else empty_payload_list_head_next <= payload_read_data_a; end if; -- Make current Slot the Tail payload_write_data_a <= PAYLOAD_MEMORY_MAX_ADDRESS; payload_wen_a <= '1'; stage_a_next <= SAMPLE_PRE_FINISH; cnt_a_next <= 0 when GENERATION_COUNTERS else 2; when others => null; end case; when SAMPLE_PRE_FINISH => -- Precondition: sample_addr_a (Disposed generation Counter of New Sample) cnt_a_next <= cnt_a + 1; case (cnt_a) is -- Disposed Generation Counter when 0 => if (GENERATION_COUNTERS) then sample_addr_a_next <= sample_addr_a + 1; sample_wen_a <= '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_a <= gen_cnt + 1; else sample_write_data_a <= gen_cnt; end if; end if; -- No Writer Generation Counter when 1 => if (GENERATION_COUNTERS) then sample_wen_a <= '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_a <= gen_cnt + 1; else sample_write_data_a <= gen_cnt; end if; end if; when 2 => -- First Sample if (newest_sample = SAMPLE_MEMORY_MAX_ADDRESS) then stage_a_next <= FINALIZE_SAMPLE_INFO; sample_addr_a_next <= empty_sample_list_head + SMF_PREV_ADDR_OFFSET; next_sample_next <= SAMPLE_MEMORY_MAX_ADDRESS; prev_sample_next <= SAMPLE_MEMORY_MAX_ADDRESS; cnt_a_next <= 0; else stage_a_next <= FIND_POS; prev_sample_next <= newest_sample; sample_addr_a_next <= newest_sample + SMF_TIMESTAMP_OFFSET; cnt_a_next <= 0; end if; when others => null; end case; when FIND_POS => -- Precondition: prev_sample set, sample_addr_a (Timestamp 1/2 Addr of prev_sample) cnt_a_next <= cnt_a + 1; case (cnt_a) is -- Preload when 0 => sample_addr_a_next <= sample_addr_a + 1; sample_ren_a <= '1'; -- Timestamp 1/2 when 1 => sample_addr_a_next <= sample_addr_a + SMF_PREV_ADDR_OFFSET-(SMF_TIMESTAMP_OFFSET+1); -- Prev Addr sample_ren_a <= '1'; long_latch_next <= sample_read_data_a; -- Timestamp 2/2 when 2 => sample_ren_a <= '1'; tmp_dw := (0 => unsigned(long_latch), 1 => unsigned(sample_read_data_a)); sample_addr_a_next <= sample_addr_a + SMF_NEXT_ADDR_OFFSET-SMF_PREV_ADDR_OFFSET; -- Next Addr -- Found position (After current slot) if (ts_latch >= tmp_dw) then stage_a_next <= FIX_POINTERS; cnt_a_next <= 0; end if; -- Previous Address when 3 => -- No previous Slot (Oldest Sample) if (sample_read_data_a = 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_a_next <= FIX_POINTERS; cnt_a_next <= 0; else prev_sample_next <= sample_read_data_a; sample_addr_a_next <= sample_read_data_a + SMF_TIMESTAMP_OFFSET; cnt_a_next <= 0; end if; end case; when FIX_POINTERS => -- Precondition: sample_addr_a (Next Addr of prev_sample) cnt_a_next <= cnt_a + 1; case (cnt_a) is -- Preload when 0 => sample_ren_a <= '1'; when 1 => -- Fix Next Pointer sample_write_data_a <= empty_sample_list_head; sample_wen_a <= '1'; -- No next Slot (Newest Sample) if (sample_read_data_a = 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_a_next <= FINALIZE_SAMPLE_INFO; sample_addr_a_next <= empty_sample_list_head + SMF_PREV_ADDR_OFFSET; -- Prev Addr of New Sample cnt_a_next <= 0; else -- Latch Next Sample next_sample_next <= sample_read_data_a; sample_addr_a_next <= sample_read_data_a + SMF_PREV_ADDR_OFFSET; -- Prev Addr of Next Sample end if; when 2 => -- Fix Previous Pointer sample_write_data_a <= empty_sample_list_head; sample_wen_a <= '1'; stage_a_next <= FINALIZE_SAMPLE_INFO; sample_addr_a_next <= empty_sample_list_head + SMF_PREV_ADDR_OFFSET; -- Prev Addr of New Sample cnt_a_next <= 0; when others => null; end case; when FINALIZE_SAMPLE_INFO => -- Precondition: prev_sample set, next_sample set, sample_addr_a (Prev Addr of new sample) cnt_a_next <= cnt_a + 1; case (cnt_a) is -- Previous Address when 0 => sample_addr_a_next <= sample_addr_a + SMF_NEXT_ADDR_OFFSET-SMF_PREV_ADDR_OFFSET; -- Write Prev Addr sample_write_data_a <= prev_sample; sample_ren_a <= '1'; -- Preload when 1 => sample_ren_a <= '1'; -- Next Address when 2 => -- No empty Sample Slot Available if (sample_read_data_a = SAMPLE_MEMORY_MAX_ADDRESS) then -- Signal Smaple Memory Full sample_mem_full_next <= '1'; else empty_sample_list_head_next <= sample_read_data_a; end if; -- Write Next Addr sample_write_data_a <= next_sample; sample_ren_a <= '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; -- DONE stage_a_next <= IDLE; end case; when SKIP_ADD => case (cnt_a) is -- SKIP READ when 0 => ready_in_a <= '1'; -- Wait until last word from input if (last_word_in_a = '1') then cnt_a_next <= 1; end if; -- REJECT SAMPLE when 1 => res_a <= REJECTED; stage_a_next <= IDLE; when others => null; end case; when REMOVE_WRITER => -- Memory Operation Guard if (inst_op_done_a = '1') then -- No More Instances if (inst_addr_base_a = INSTANCE_MEMORY_MAX_ADDRESS) then -- DONE stage_a_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_a <= '1'; instance_state <= NOT_ALIVE_NO_WRITERS; inst_opcode_a <= UPDATE_INSTANCE; update_inst_flags_a <= STATUS_FLAG or WRITER_BITMAP_FLAG; else inst_op_start_a <= '1'; inst_opcode_a <= UPDATE_INSTANCE; update_inst_flags_a <= WRITER_BITMAP_FLAG; end if; stage_a_next <= GET_NEXT_INSTANCE; end if; end if; when GET_NEXT_INSTANCE => -- Wait for Operation to Complete if (inst_op_done_a = '1') then inst_op_start_a <= '1'; inst_opcode_a <= NEXT_INSTANCE; stage_a_next <= REMOVE_WRITER; end if; when WAIT_FOR_REMOVE => -- Stall Input ready_in_a <= '0'; if (HISTORY_QOS = KEEP_ALL_HISTORY_QOS and RELIABILITY_QOS = RELIABLE_RELIABILITY_QOS) then -- Reject Change stage_a_next <= SKIP_ADD; cnt_a_next <= 0; else od_oldest_sample_removal <= '1'; -- NOTE: We are ignoring the od_sample_removal_done signal of process B, because in this -- case we can directly observe the status from the available signals. This cannot -- be done in the MAX_SAMPLES_PER_INSTANCE removal case, since there we have to wait -- until process B explicitly states that it has removed a sample of the offending instance. -- In addition to that, the removal of the oldest sample is no guarantee that the payload -- memory will also get freed (Since the oldest sample may be one without data). -- Here we are keeping the od_oldest_sample_removal signal high (meaning process B will keep -- removing samples) as long as it takes for both memories to get freed. -- Memory Available if (sample_mem_full = '0' and payload_mem_full = '0') then stage_a_next <= ADD_SAMPLE_INFO; sample_addr_a_next <= empty_sample_list_head; cnt_a_next <= 0; end if; end if; when others => null; end case; end process; signal stage_b, stage_b_next : STAGE_TYPE := IDLE; parse_b_prc : process (all) begin -- DEFAULT stage_b_next <= stage_b; case (stage_b) is when IDLE => if (start_b = '1') then case (opcode_b) is when others => null; end case; end if; when others => null; end case; end process; inst_ctrl_prc : process(all) begin -- DEFAULT Registered inst_stage_a_next <= inst_stage_a; inst_addr_base_a_next <= inst_addr_base_a; inst_addr_a_next <= inst_addr_a; inst_empty_head_next <= inst_empty_head; inst_occupied_tail_next <= inst_occupied_tail; inst_latch_data_next <= inst_latch_data; inst_next_addr_base_a_next <= inst_next_addr_base_a; inst_prev_addr_base_a_next <= inst_prev_addr_base_a; inst_cnt_a_next <= inst_cnt_a; inst_mem_full_next <= inst_mem_full; inst_delete_lock_a_next <= inst_delete_lock_a; inst_data_next <= inst_data; -- DEFAULT Unregistered inst_write_data_a <= (others => '0'); inst_op_done_a <= '0'; inst_ren_a <= '0'; inst_wen_a <= '0'; inst_atomic_lock_a <= '0'; case (mem_stage) is when IDLE => inst_op_done_a <= '1'; -- Lock Release if (inst_delete_lock_a = '1' and inst_latch_data.release_lock = '1') then inst_delete_lock_a_next <= '0'; end if; if (inst_op_start_a = '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, gen_cnt => gen_cnt, deadline => deadline, writer_bitmap => writer_bitmap, update_flags => update_inst_flags_a, release_lock => release_inst_lock ); -- Reset Memory Fullness Indicator if (inst_mem_full = '1' and inst_empty_head /= inst_empty_tail) then inst_mem_full_next <= '0'; end if; case(inst_opcode_a) is when SEARCH_INSTANCE => -- Reset Data inst_data_next <= ZERO_INSTANCE_DATA; -- NOTE: This process gets the lock implicitly when the SEARCH_INSTANCE, or GET_FIRST_INSTANCE operation is called, and has to be released explicitly -- by the main process. There are two ways to release the lock: 1) The man process explicitly calles the RELEASE_LOCK operation 2) The main -- process pulls the release_inst_lock signal high during the issuing of the last memory operation (Lock will be release after the opration finishes) -- Process B has lock if (inst_delete_lock_b = '1') then -- Wait until process B releases lock inst_stage_a_next <= WAIT_FOR_LOCK_1; else -- NOTE: The case that both processes aqcuire the lock at the same time is handled by the B process in the next clock cycle. -- Get Lock inst_delete_lock_a_next <= '1'; -- No Instances avialable if (inst_occupied_head = INSTANCE_MEMORY_MAX_ADDRESS) then inst_addr_base_a_next <= INSTANCE_MEMORY_MAX_ADDRESS; else inst_prev_addr_base_a <= INSTANCE_MEMORY_MAX_ADDRESS; inst_addr_base_a_next <= inst_occupied_head; inst_addr_a_next <= inst_occupied_head; inst_stage_a_next <= SEARCH_INSTANCE; inst_cnt_a_next <= 0; end if; 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_mem_full = '0') report "Instance Insertion while memory Full" severity FAILURE; inst_prev_addr_base_a_next <= inst_occupied_tail; inst_addr_base_a_next <= inst_occupied_tail; inst_addr_a_next <= inst_occupied_tail; inst_stage_a_next <= INSERT_PREPARATION; inst_cnt_a_next <= 0; when UPDATE_INSTANCE => inst_addr_base_a_next <= inst_addr_base_a; if ((update_inst_flags_a and STATUS_FLAG) = STATUS_FLAG) then inst_stage_a_next <= UPDATE_INSTANCE; inst_addr_a_next <= inst_addr_base_a + IMF_STATUS_INFO_OFFSET; inst_cnt_a_next <= 0; elsif (MAX_SAMPLES_PER_INSTANCE /= LENGTH_UNLIMITED and (update_inst_flags_a and SAMPLE_CNT_FLAG) = SAMPLE_CNT_FLAG) then inst_stage_a_next <= UPDATE_INSTANCE; inst_addr_a_next <= inst_addr_base_a + IMF_SAMPLE_CNT_OFFSET; inst_cnt_a_next <= 3; elsif (GENERATION_COUNTERS and (update_inst_flags_a and DISPOSED_CNT_FLAG) = DISPOSED_CNT_FLAG) then inst_stage_a_next <= UPDATE_INSTANCE; inst_addr_a_next <= inst_addr_base_a + IMF_DISPOSED_GEN_CNT_OFFSET; inst_cnt_a_next <= 6; elsif (GENERATION_COUNTERS and (update_inst_flags_a and NO_WRITERS_CNT_FLAG) = NO_WRITERS_CNT_FLAG) then inst_stage_a_next <= UPDATE_INSTANCE; inst_addr_a_next <= inst_addr_base_a + IMF_NO_WRITERS_GEN_CNT_OFFSET; inst_cnt_a_next <= 7; elsif (TIME_BASED_FILTER_QOS /= DURATION_ZERO and (update_inst_flags_a and IGNORE_DEADLINE_FLAG) = IGNORE_DEADLINE_FLAG) then inst_stage_a_next <= UPDATE_INSTANCE; inst_addr_a_next <= inst_addr_base_a + IMF_IGNORE_DEADLINE_OFFSET; inst_cnt_a_next <= 8; elsif ((update_inst_flags_a and WRITER_BITMAP_FLAG) = WRITER_BITMAP_FLAG) then inst_stage_a_next <= SET_WRITER_BITMAP; inst_addr_a_next <= inst_addr_base_a + IMF_WRITER_BITMAP_OFFSET; inst_cnt_a_next <= 0; end if; when GET_FIRST_INSTANCE => -- NOTE: This process gets the lock implicitly when the SEARCH_INSTANCE, or GET_FIRST_INSTANCE operation is called, and has to be released explicitly -- by the main process via the RELEASE_LOCK operation. -- Process B has lock if (inst_delete_lock_b = '1') then -- Wait until process B releases lock inst_stage_a_next <= WAIT_FOR_LOCK_2; else -- NOTE: The case that both processes aqcuire the lock at the same time is handled by the B process in the next clock cycle. -- Get Lock inst_delete_lock_a_next <= '1'; -- No Instances avialable if (inst_occupied_head = INSTANCE_MEMORY_MAX_ADDRESS) then inst_addr_base_a_next <= INSTANCE_MEMORY_MAX_ADDRESS; else inst_prev_addr_base_a_next <= INSTANCE_MEMORY_MAX_ADDRESS; inst_addr_base_a_next <= inst_occupied_head; inst_addr_a_next <= inst_occupied_head + 5; inst_stage_a_next <= GET_INSTANCE_DATA; inst_cnt_a_next <= 0; end if; end if; when GET_NEXT_INSTANCE => inst_prev_addr_base_a_next <= inst_addr_base_a; inst_addr_base_a_next <= inst_next_addr_base_a; inst_addr_a_next <= inst_next_addr_base_a; inst_stage_a_next <= GET_NEXT_INSTANCE; inst_cnt_a_next <= 0; when RELEASE_LOCK => inst_delete_lock_a_next <= '0'; when others => null; end case; end if; when WAIT_FOR_LOCK_1 => -- Wait until B process releases lock if (inst_delete_lock_b = '0') then -- Get Lock inst_delete_lock_a_next <= '1'; if (inst_occupied_head /= INSTANCE_MEMORY_MAX_ADDRESS) then inst_addr_base_a_next <= inst_occupied_head; inst_addr_a_next <= inst_occupied_head; inst_stage_a_next <= SEARCH_INSTANCE; inst_cnt_a_next <= 0; else inst_addr_base_a_next <= INSTANCE_MEMORY_MAX_ADDRESS; end if; end if; when WAIT_FOR_LOCK_2 => -- Wait until B process releases lock if (inst_delete_lock_b = '0') then -- Get Lock inst_delete_lock_a_next <= '1'; -- No Instances avialable if (inst_occupied_head = INSTANCE_MEMORY_MAX_ADDRESS) then inst_addr_base_a_next <= INSTANCE_MEMORY_MAX_ADDRESS; else inst_prev_addr_base_a_next <= INSTANCE_MEMORY_MAX_ADDRESS; inst_addr_base_a_next <= inst_occupied_head; inst_addr_a_next <= inst_occupied_head + 5; inst_stage_a_next <= GET_INSTANCE_DATA; inst_cnt_a_next <= 0; end if; end if; when SEARCH_INSTANCE => inst_ren_a <= '1'; inst_cnt_a_next <= inst_cnt_a + 1; inst_addr_a_next <= inst_addr_a + 1; case (inst_cnt_a) is -- Preload when 0 => null; -- Next Instance when 1 => inst_next_addr_base_a_next <= inst_read_data_a; -- Key Hash 1/4 when 2 => -- No Match if (inst_read_data_a /= inst_latch_data.key_hash(0)) then -- Reached List Tail, No Match if (inst_addr_base_a = INSTANCE_MEMORY_MAX_ADDRESS) then inst_addr_base_a_next <= INSTANCE_MEMORY_MAX_ADDRESS; --No match -- DONE inst_stage_a_next <= IDLE; else -- Continue Search inst_prev_addr_base_a_next <= inst_addr_base_a; inst_addr_base_a_next <= inst_next_addr_base_a; inst_addr_a_next <= inst_next_addr_base_a; inst_cnt_a_next <= 0; end if; end if; -- Key Hash 2/4 when 3 => -- No Match if (inst_read_data_a /= inst_latch_data.key_hash(1)) then -- Reached List Tail, No Match if (inst_addr_base_a = INSTANCE_MEMORY_MAX_ADDRESS) then inst_addr_base_a_next <= INSTANCE_MEMORY_MAX_ADDRESS; --No match -- DONE inst_stage_a_next <= IDLE; else -- Continue Search inst_prev_addr_base_a_next <= inst_addr_base_a; inst_addr_base_a_next <= inst_next_addr_base_a; inst_addr_a_next <= inst_next_addr_base_a; inst_cnt_a_next <= 0; end if; end if; -- Key Hash 3/4 when 4 => -- No Match if (inst_read_data_a /= inst_latch_data.key_hash(2)) then -- Reached List Tail, No Match if (inst_addr_base_a = INSTANCE_MEMORY_MAX_ADDRESS) then inst_addr_base_a_next <= INSTANCE_MEMORY_MAX_ADDRESS; --No match -- DONE inst_stage_a_next <= IDLE; else -- Continue Search inst_prev_addr_base_a_next <= inst_addr_base_a; inst_addr_base_a_next <= inst_next_addr_base_a; inst_addr_a_next <= inst_next_addr_base_a; inst_cnt_a_next <= 0; end if; end if; -- Key Hash 4/4 when 5 => -- No Match if (inst_read_data_a /= inst_latch_data.key_hash(3)) then -- Reached List Tail, No Match if (inst_addr_base_a = INSTANCE_MEMORY_MAX_ADDRESS) then inst_addr_base_a_next <= INSTANCE_MEMORY_MAX_ADDRESS; --No match -- DONE inst_stage_a_next <= IDLE; else -- Continue Search inst_prev_addr_base_a_next <= inst_addr_base_a; inst_addr_base_a_next <= inst_next_addr_base_a; inst_addr_a_next <= inst_next_addr_base_a; inst_cnt_a_next <= 0; end if; -- Match else -- Fetch Instance Data inst_stage_a_next <= GET_INSTANCE_DATA; inst_cnt_a_next <= 1; -- No preload needed end if; when others => null; end case; when GET_NEXT_INSTANCE => case (inst_cnt_a) is -- Preload when 0 => inst_wen_a <= '1'; -- Next Instance when 1 => inst_addr_base_a_next <= inst_read_data_a; inst_addr_a_next <= inst_read_data_a + 5; inst_cnt_a_next <= 0; inst_stage_a_next <= GET_INSTANCE_DATA; end case; when GET_INSTANCE_DATA => inst_ren_a <= '1'; inst_cnt_a_next <= inst_cnt_a + 1; inst_addr_a_next <= inst_addr_a + 1; case (inst_cnt_a) is -- Memory Preload when 0 => null; -- Status Info when 1 => inst_data_next.status_info <= inst_read_data_a; -- Sample Count when 2 => inst_data_next.sample_cnt <= inst_read_data_a; -- Disposed Generation Count when 3 => inst_data_next.disposed_gen_cnt <= inst_read_data_a; -- No Writers Generation Count when 4 => inst_data_next.no_writers_gen_cnt <= inst_read_data_a; -- Ignore Deadline 1/2 when 5 => inst_data_next.ignore_deadline(0) <= unsigned(inst_read_data_a); -- Ignore Deadline 2/2 when 5 => inst_data_next.ignore_deadline(1) <= unsigned(inst_read_data_a); -- DONE inst_stage_a_next <= GET_WRITER_BITMAP; inst_cnt_a_next <= 0; when others => null; end case; when GET_WRITER_BITMAP => inst_cnt_a_next <= inst_cnt_a + 1; inst_latch_data_next.writer_bitmap(inst_cnt_a) <= inst_read_data_a; if (inst_cnt_a = writer_bitmap'length-1) then -- DONE inst_stage_a_next <= IDLE; end if; when INSERT_PREPARATION => inst_cnt_a_next <= inst_cnt_a + 1; case (inst_cnt_a) is -- Next Payload Slot (Old Occupied Tail) when 0 => -- Point Old Occupied Tail to New Occupied Tail inst_write_data_a <= inst_empty_head; inst_wen_a <= '1'; inst_occupied_tail_next <= inst_empty_head; inst_addr_a_next <= inst_empty_head; inst_addr_base_a_next <= inst_empty_head; -- Preload when 1 => inst_ren_a <= '1'; -- Next Payload Slot (New Occupied Tail) when 2 => -- Instance Memory Full if (inst_read_data_a = INSTANCE_MEMORY_MAX_ADDRESS) then assert (inst_empty_head = inst_empty_tail) report "Instance empty list empty, but HEAD /= TAIL" severity FAILURE; inst_mem_full_next <= '1'; inst_next_addr_base_a_next <= inst_empty_head; -- Keep same tail else -- Latch new Empty Head inst_next_addr_base_a_next <= inst_read_data_a; end if; inst_stage_a_next <= INSERT_INSTANCE; inst_cnt_a_next <= 0; when others => null; end case; when INSERT_INSTANCE => inst_wen_a <= '1'; inst_addr_a_next <= inst_addr_a + 1; inst_cnt_a_next <= inst_cnt_a + 1; case (inst_cnt_a) is -- Next Instance Address when 0 => -- Mark as Tail inst_write_data_a <= INSTANCE_MEMORY_MAX_ADDRESS; -- Set New Empty List Head inst_empty_head_next <= inst_next_addr_base_a; -- Key Hash 1/4 when 1 => inst_write_data_a <= inst_latch_data.key_hash(0); -- Key Hash 2/4 when 2 => inst_write_data_a <= inst_latch_data.key_hash(1); -- Key Hash 3/4 when 3 => inst_write_data_a <= inst_latch_data.key_hash(2); -- Key Hash 4/4 when 4 => inst_write_data_a <= inst_latch_data.key_hash(3); -- Status Info when 5 => inst_write_data_a <= inst_latch_data.status_info; if (MAX_SAMPLES_PER_INSTANCE /= LENGTH_UNLIMITED) then null; elsif (GENERATION_COUNTERS) then inst_cnt_a <= 7; elsif (TIME_BASED_FILTER_QOS /= DURATION_ZERO) then inst_cnt_a <= 9; else inst_stage_a_next <= SET_WRITER_BITMAP; inst_cnt_a_next <= 0; end if; -- Sample Count when 6 => if (MAX_SAMPLES_PER_INSTANCE /= LENGTH_UNLIMITED) then inst_write_data_a <= std_logic_vector(to_unsigned(1, WORD_WIDTH)); if (GENERATION_COUNTERS) then inst_cnt_a <= 7; elsif (TIME_BASED_FILTER_QOS /= DURATION_ZERO) then inst_cnt_a <= 9; else inst_stage_a_next <= SET_WRITER_BITMAP; inst_cnt_a_next <= 0; end if; end if; -- Disposed Generation Count when 7 => if (GENERATION_COUNTERS) then inst_write_data_a <= (others => '0'); end if; -- No Writers Generation Count when 8 => if (GENERATION_COUNTERS) then inst_write_data_a <= (others => '0'); if (TIME_BASED_FILTER_QOS /= DURATION_ZERO) then inst_cnt_a <= 9; else inst_stage_a_next <= SET_WRITER_BITMAP; inst_cnt_a_next <= 0; end if; end if; -- Ignore Deadline 1/2 when 9 => if (TIME_BASED_FILTER_QOS /= DURATION_ZERO) then inst_write_data_a <= inst_latch_data.deadline(0); end if; -- Ignore Deadline 1/2 when 10 => if (TIME_BASED_FILTER_QOS /= DURATION_ZERO) then inst_write_data_a <= inst_latch_data.deadline(1); inst_stage_a_next <= SET_WRITER_BITMAP; inst_cnt_a_next <= 0; end if; when others => null; end case; when SET_WRITER_BITMAP => inst_wen_a <= '1'; inst_addr_a_next <= inst_addr_a + 1; inst_cnt_a_next <= inst_cnt_a + 1; inst_write_data_a <= inst_latch_data.writer_bitmap(inst_cnt_a); -- Exit Condition if (inst_cnt_a = inst_latch_data.writer_bitmap'length-1) then -- DONE inst_stage_a_next <= IDLE; end if; when UPDATE_INSTANCE => inst_cnt_a_next <= inst_cnt_a + 1; case (inst_cnt_a) is -- *Status Info Begin* -- Preload when 0 => inst_atomic_lock_a <= '1'; inst_ren_a <= '1'; -- Read when 1 => -- Latch Contents inst_atomic_lock_a <= '1'; inst_long_latch_a_next <= inst_read_data_a; -- Write when 2 => inst_atomic_lock_a <= '1'; inst_wen_a <= '1'; inst_write_data_a <= inst_long_latch_a; case (inst_latch_data.instance_state) is when ALIVE => inst_write_data_a(NOT_ALIVE_DISPOSED_FLAG) <= '0'; inst_write_data_a(NOT_ALIVE_NO_WRITERS_FLAG) <= '0'; inst_write_data_a(LIVELINESS_FLAG) <= '1'; when NOT_ALIVE_DISPOSED => inst_write_data_a(NOT_ALIVE_DISPOSED_FLAG) <= '1'; inst_write_data_a(NOT_ALIVE_NO_WRITERS_FLAG) <= '0'; inst_write_data_a(LIVELINESS_FLAG) <= '1'; when NOT_ALIVE_NO_WRITERS => inst_write_data_a(NOT_ALIVE_DISPOSED_FLAG) <= '0'; inst_write_data_a(NOT_ALIVE_NO_WRITERS_FLAG) <= '1'; inst_write_data_a(LIVELINESS_FLAG) <= '1'; end case; if (MAX_SAMPLES_PER_INSTANCE /= LENGTH_UNLIMITED and (inst_latch_data.update_flags and SAMPLE_CNT_FLAG) = SAMPLE_CNT_FLAG) then inst_addr_a_next <= inst_addr_base_a + IMF_SAMPLE_CNT_OFFSET; inst_cnt_a_next <= 3; elsif (GENERATION_COUNTERS and (inst_latch_data.update_flags and DISPOSED_CNT_FLAG) = DISPOSED_CNT_FLAG) then inst_addr_a_next <= inst_addr_base_a + IMF_DISPOSED_GEN_CNT_OFFSET; inst_cnt_a_next <= 6; elsif (GENERATION_COUNTERS and (inst_latch_data.update_flags and NO_WRITERS_CNT_FLAG) = NO_WRITERS_CNT_FLAG) then inst_addr_a_next <= inst_addr_base_a + IMF_NO_WRITERS_GEN_CNT_OFFSET; inst_cnt_a_next <= 7; elsif (TIME_BASED_FILTER_QOS /= DURATION_ZERO and (inst_latch_data.update_flags and IGNORE_DEADLINE_FLAG) = IGNORE_DEADLINE_FLAG) then inst_addr_a_next <= inst_addr_base_a + IMF_IGNORE_DEADLINE_OFFSET; inst_cnt_a_next <= 8; elsif ((inst_latch_data.update_flags and WRITER_BITMAP_FLAG) = WRITER_BITMAP_FLAG) then inst_addr_a_next <= inst_addr_base_a + IMF_WRITER_BITMAP_OFFSET; inst_stage_a_next <= SET_WRITER_BITMAP; inst_cnt_a_next <= 0; else -- DONE inst_stage_a_next <= IDLE; end if; -- *Status Info End* -- *Sample Count Begin* -- Preload when 3 => if (MAX_SAMPLES_PER_INSTANCE /= LENGTH_UNLIMITED) then inst_ren_a <= '1'; inst_atomic_lock_a <= '1'; end if; -- Read when 4 => if (MAX_SAMPLES_PER_INSTANCE /= LENGTH_UNLIMITED) then -- Latch Contents inst_atomic_lock_a <= '1'; inst_long_latch_a_next <= inst_read_data_a; end if; when 5 => if (MAX_SAMPLES_PER_INSTANCE /= LENGTH_UNLIMITED) then -- Increment Sample Count inst_atomic_lock_a <= '1'; inst_wen_a <= '1'; inst_write_data_a <= std_logic_vector(unsigned(inst_long_latch_a) + 1); if (GENERATION_COUNTERS and (inst_latch_data.update_flags and DISPOSED_CNT_FLAG) = DISPOSED_CNT_FLAG) then inst_addr_a_next <= inst_addr_base_a + IMF_DISPOSED_GEN_CNT_OFFSET; inst_cnt_a_next <= 6; elsif (GENERATION_COUNTERS and (inst_latch_data.update_flags and NO_WRITERS_CNT_FLAG) = NO_WRITERS_CNT_FLAG) then inst_addr_a_next <= inst_addr_base_a + IMF_NO_WRITERS_GEN_CNT_OFFSET; inst_cnt_a_next <= 7; elsif (TIME_BASED_FILTER_QOS /= DURATION_ZERO and (inst_latch_data.update_flags and IGNORE_DEADLINE_FLAG) = IGNORE_DEADLINE_FLAG) then inst_addr_a_next <= inst_addr_base_a + IMF_IGNORE_DEADLINE_OFFSET; inst_cnt_a_next <= 8; elsif ((inst_latch_data.update_flags and WRITER_BITMAP_FLAG) = WRITER_BITMAP_FLAG) then inst_addr_a_next <= inst_addr_base_a + IMF_WRITER_BITMAP_OFFSET; inst_stage_a_next <= SET_WRITER_BITMAP; inst_cnt_a_next <= 0; else -- DONE inst_stage_a_next <= IDLE; end if; end if; -- *Sample Count End* -- Disposed Generation Count when 6 => if (GENERATION_COUNTERS) then inst_wen_a <= '1'; inst_write_data_a <= inst_latch_data.gen_cnt; if (GENERATION_COUNTERS and (inst_latch_data.update_flags and NO_WRITERS_CNT_FLAG) = NO_WRITERS_CNT_FLAG) then inst_addr_a_next <= inst_addr_base_a + IMF_NO_WRITERS_GEN_CNT_OFFSET; inst_cnt_a_next <= 7; elsif (TIME_BASED_FILTER_QOS /= DURATION_ZERO and (inst_latch_data.update_flags and IGNORE_DEADLINE_FLAG) = IGNORE_DEADLINE_FLAG) then inst_addr_a_next <= inst_addr_base_a + IMF_IGNORE_DEADLINE_OFFSET; inst_cnt_a_next <= 8; elsif ((inst_latch_data.update_flags and WRITER_BITMAP_FLAG) = WRITER_BITMAP_FLAG) then inst_addr_a_next <= inst_addr_base_a + IMF_WRITER_BITMAP_OFFSET; inst_stage_a_next <= SET_WRITER_BITMAP; inst_cnt_a_next <= 0; else -- DONE inst_stage_a_next <= IDLE; end if; end if; -- No Writers Generation Count when 7 => if (GENERATION_COUNTERS) then inst_wen_a <= '1'; inst_write_data_a <= 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_a_next <= inst_addr_base_a + IMF_IGNORE_DEADLINE_OFFSET; inst_cnt_a_next <= 8; elsif ((inst_latch_data.update_flags and WRITER_BITMAP_FLAG) = WRITER_BITMAP_FLAG) then inst_addr_a_next <= inst_addr_base_a + IMF_WRITER_BITMAP_OFFSET; inst_stage_a_next <= SET_WRITER_BITMAP; inst_cnt_a_next <= 0; else -- DONE inst_stage_a_next <= IDLE; end if; end if; -- Ignore Deadline 1/2 when 8 => if (TIME_BASED_FILTER_QOS /= DURATION_ZERO) then inst_wen_a <= '1'; inst_write_data_a <= std_logic_vector(inst_latch_data.ignore_deadline(0)); end if; -- Ignore Deadline 2/2 when 9 => if (TIME_BASED_FILTER_QOS /= DURATION_ZERO) then inst_wen_a <= '1'; inst_write_data_a <= 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_a_next <= inst_addr_base_a + IMF_WRITER_BITMAP_OFFSET; inst_stage_a_next <= SET_WRITER_BITMAP; inst_cnt_a_next <= 0; else -- DONE inst_stage_a_next <= IDLE; end if; end if; when others => null; end case; when others => null; end case; when others => null; end case; end process; end architecture;