From d1d95c4ec7305c73f89e4f13b116578f917d1e9c Mon Sep 17 00:00:00 2001 From: Greek Date: Mon, 1 Feb 2021 23:48:58 +0100 Subject: [PATCH] Redo Memory Interface of DDS Endpoint Propagation of RTPS changes --- src/dds_endpoint.vhd | 4251 +++++++++++++++++++++++++++--------------- 1 file changed, 2707 insertions(+), 1544 deletions(-) diff --git a/src/dds_endpoint.vhd b/src/dds_endpoint.vhd index 9500f5e..9181d5a 100644 --- a/src/dds_endpoint.vhd +++ b/src/dds_endpoint.vhd @@ -2,6 +2,8 @@ library ieee; use ieee.std_logic_1164.all; use ieee.numeric_std.all; +-- TODO: Check if sample_cnt is always maintained (also with MAX_SAMPLES_PER_INSTANCE = LENGTH_UNLIMITED) + entity history_cache is generic ( TIME_BASED_FILTER_QOS : DURATION_TYPE := DEFAULT_TIME_BASED_FILTER_QOS; @@ -96,14 +98,15 @@ architecture arch of history_cache is -- 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'); + -- *INSTANCE MEMORY FRAME FIELD FLAGS* + constant IMF_FLAG_WIDTH : natural := 7; + constant IMF_KEY_HASH_FLAG : std_logic_vector(0 to IMF_FLAG_WIDTH-1) := (0 => 1, others => '0'); + constant IMF_STATUS_FLAG : std_logic_vector(0 to IMF_FLAG_WIDTH-1) := (1 => 1, others => '0'); + constant IMF_SAMPLE_CNT_FLAG : std_logic_vector(0 to IMF_FLAG_WIDTH-1) := (2 => 1, others => '0'); + constant IMF_DISPOSED_CNT_FLAG : std_logic_vector(0 to IMF_FLAG_WIDTH-1) := (3 => 1, others => '0'); + constant IMF_NO_WRITERS_CNT_FLAG : std_logic_vector(0 to IMF_FLAG_WIDTH-1) := (4 => 1, others => '0'); + constant IMF_IGNORE_DEADLINE_FLAG : std_logic_vector(0 to IMF_FLAG_WIDTH-1) := (5 => 1, others => '0'); + constant IMF_WRITER_BITMAP_FLAG : std_logic_vector(0 to IMF_FLAG_WIDTH-1) := (6 => 1, others => '0'); -- *SAMPLE MEMORY FRAME FORMAT* constant SMF_STATUS_INFO_OFFSET : natural := 0; @@ -113,8 +116,8 @@ architecture arch of history_cache is 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; + constant SMF_PREV_ADDR_OFFSET : natural := 9; + constant SMF_NEXT_ADDR_OFFSET : natural := 10; -- *PAYLOAD MEMORY FRAME FORMAT* constant PMF_NEXT_ADDR_OFFSET : natural := 0; constant PMF_PAYLOAD_OFFSET : natural := 1; @@ -123,9 +126,9 @@ architecture arch of history_cache is 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_DISPOSED_GEN_CNT_OFFSET : natural := 7; + constant IMF_NO_WRITERS_GEN_CNT_OFFSET : natural := 8; + constant IMF_IGNORE_DEADLINE_OFFSET : natural := 9; 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***** @@ -133,10 +136,6 @@ architecture arch of history_cache is type STAGE_TYPE is (IDLE, TODO); type INST_STAGE_TYPE is (IDLE, TODO); type INSTANCE_OPCODE_TYPE is (NOP, TODO); - -- VAR_1 (STATUS_INFO, SAMPLE_COUNT, DISPOSED_GENERATION_COUNT, NO_WRITERS_GENERATION_COUNT, IGNORE_DEADLINE, WRITER_BITMAP) - -- VAR_2 (KEY_HASH, STATUS_INFO, SAMPLE_COUNT, DISPOSED_GENERATION_COUNT, NO_WRITERS_GENERATION_COUNT) - -- VAR_3 (KEY_HASH, STATUS_INFO) - type INSTANCE_DATA_VARIANT_TYPE is (VAR_1, VAR_2, VAR_3); type INSTANCE_DATA_TYPE is record key_hash : KEY_HASH_TYPE; status_info : std_logic_vector(WORD_WIDTH-1 downto 0); @@ -156,40 +155,48 @@ architecture arch of history_cache is writer_bitmap => (others => (others => '0')) ); type INST_LATCH_DATA_TYPE is record - variant : INSTANCE_DATA_VARIANT_TYPE; key_hash : KEY_HASH_TYPE; status_info : std_logic_vector(CDR_LONG_WIDTH-1 downto 0); sample_cnt : std_logic_vector(CDR_LONG_WIDTH-1 downto 0); 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); + field_flags : std_logic_vector(0 to IMF_FLAG_WIDTH-1); addr : unsigned(INSTANCE_MEMORY_ADDR_WIDTH-1 downto 0); end record; constant ZERO_INST_LATCH_DATA : INST_LATCH_DATA_TYPE := ( - variant => VAR_1, key_hash => (others => (others => '0')), status_info => (others => '0'), sample_cnt => (others => '0'), gen_cnt => (others => '0'), deadline => TIME_INVALID, writer_bitmap => (others => (others => '0')), - update_flags => (others => '0'), + field_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_addr : unsigned(SAMPLE_MEMORY_ADDR_WIDTH-1 downto 0) := (others => '0'); + signal sample_read : std_logic := '0'; signal sample_read_data, sample_write_data : std_logic_vector(WORD_WIDTH-1 downto 0) := (others => '0'); + signal sample_ready_in, sample_valid_in : std_logic := '0'; + signal sample_ready_out, sample_valid_out : std_logic := '0'; + signal sample_abort_read : std_logic := '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_addr : unsigned(PAYLOAD_MEMORY_ADDR_WIDTH-1 downto 0) := (others => '0'); + signal payload_read : std_logic := '0'; signal payload_read_data, payload_write_data : std_logic_vector(WORD_WIDTH-1 downto 0) := (others => '0'); + signal payload_ready_in, payload_valid_in : std_logic := '0'; + signal payload_ready_out, payload_valid_out : std_logic := '0'; + signal payload_abort_read : std_logic := '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_addr : unsigned(PAYLOAD_MEMORY_ADDR_WIDTH-1 downto 0) := (others => '0'); + signal inst_read : std_logic := '0'; signal inst_read_data, inst_write_data : std_logic_vector(WORD_WIDTH-1 downto 0) := (others => '0'); + signal inst_ready_in, inst_valid_in : std_logic := '0'; + signal inst_ready_out, inst_valid_out : std_logic := '0'; + signal inst_abort_read : std_logic := '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'); @@ -207,6 +214,7 @@ architecture arch of history_cache is 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 sample_addr_latch_4, sample_addr_latch_4_next : unsigned(SAMPLE_MEMORY_ADDR_WIDTH-1 downto 0) := (others => '0'); signal ts_latch, ts_latch_next : TIME_TYPE := TIME_INVALID; signal last_read_ts, last_read_ts_next : TIME_TYPE := TIME_INVALID; signal long_latch, long_latch_next : std_logic_vector(CDR_LONG_WIDTH-1 downto 0) := (others => '0'); @@ -224,6 +232,8 @@ architecture arch of history_cache is 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 cnt2, cnt2_next : natural range 0 to PAYLOAD_FRAME_SIZE := 0; + signal cnt3, cnt3_next : natural range 0 to PAYLOAD_FRAME_SIZE := 0; signal inst_op_start : std_logic := '0'; signal inst_op_done : std_logic := '0'; @@ -235,13 +245,11 @@ architecture arch of history_cache is 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_mem_fields : std_logic_vector(0 to IMF_FLAG_WIDTH-1) := (others => '0'); signal inst_cnt, inst_cnt_next : natural range TODO := 0; + signal inst_cnt2, inst_cnt2_next : natural 0 to ENDPOINT_BITMAP_ARRAY_TYPE'length := 0; signal inst_mem_full, inst_mem_full_next : std_logic := '0'; - signal inst_delete_lock, inst_delete_lock_next : std_logic := '0'; - signal inst_atomic_lock : std_logic := '0'; - signal inst_long_latch_1, inst_long_latch_1_next : std_logic_vector(CDR_LONG_WIDTH-1 downto 0) := (others => '0'); - signal inst_long_latch_2, inst_long_latch_2_next : std_logic_vector(CDR_LONG_WIDTH-1 downto 0) := (others => '0'); + signal inst_long_latch, inst_long_latch_next : std_logic_vector(CDR_LONG_WIDTH-1 downto 0) := (others => '0'); signal si_sample_state_sig, si_sample_state_sig_next : std_logic_vector(SAMPLE_STATE_KIND_WIDTH-1 downto 0) := (others => '0'); signal si_view_state_sig, si_view_state_sig_next : std_logic_vector(VIEW_STATE_KIND_WIDTH-1 downto 0) := (others => '0'); @@ -299,10 +307,12 @@ architecture arch of history_cache is 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 second_sample : unsigned(SAMPLE_MEMORY_ADDR_WIDTH-1 downto 0) is sample_addr_latch_4; + alias second_sample_next: unsigned(SAMPLE_MEMORY_ADDR_WIDTH-1 downto 0) is sample_addr_latch_4_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 next_payload : unsigned(PAYLOAD_MEMORY_ADDR_WIDTH-1 downto 0) is payload_addr_latch_2; + alias next_payload_next : unsigned(PAYLOAD_MEMORY_ADDR_WIDTH-1 downto 0) is payload_addr_latch_2_next; alias cur_inst : unsigned(INSTANCE_MEMORY_ADDR_WIDTH-1 downto 0) is inst_addr_latch_1; alias cur_inst_next : unsigned(INSTANCE_MEMORY_ADDR_WIDTH-1 downto 0) is inst_addr_latch_1_next; alias next_inst : unsigned(INSTANCE_MEMORY_ADDR_WIDTH-1 downto 0) is inst_addr_latch_2; @@ -322,51 +332,67 @@ architecture arch of history_cache is begin - sample_ram_inst : entity work.single_port_ram(arch) + sample_mem_ctrl_inst : entity work.mem_ctrl(arch) generic map ( - ADDR_WIDTH => SAMPLE_MEMORY_ADDR_WIDTH, - DATA_WIDTH => WORD_WIDTH, - MEMORY_DEPTH => SAMPLE_MEMORY_SIZE + ADDR_WIDTH => SAMPLE_MEMORY_ADDR_WIDTH, + DATA_WIDTH => WORD_WIDTH, + MEMORY_DEPTH => SAMPLE_MEMORY_SIZE, + MAX_BURST_LENGTH => SAMPLE_FRAME_SIZE ) port map ( - clk => clk, - addr => sample_addr, - wen => sample_wen, - ren => sample_ren, - wr_data => sample_write_data, - rd_data => sample_read_data + clk => clk, + reset => reset or sample_abort_read, + addr => std_logic_vector(sample_addr), + read => sample_read, + ready_in => sample_ready_in, + valid_in => sample_valid_in, + data_in => sample_write_data, + ready_out => sample_ready_out, + valid_out => sample_valid_out, + data_out => sample_read_data ); - payload_ram_inst : entity work.single_port_ram(arch) + payload_mem_ctrl_inst : entity work.mem_ctrl(arch) generic map ( - ADDR_WIDTH => PAYLOAD_MEMORY_ADDR_WIDTH, - DATA_WIDTH => WORD_WIDTH, - MEMORY_DEPTH => PAYLOAD_MEMORY_SIZE + ADDR_WIDTH => PAYLOAD_MEMORY_ADDR_WIDTH, + DATA_WIDTH => WORD_WIDTH, + MEMORY_DEPTH => PAYLOAD_MEMORY_SIZE, + MAX_BURST_LENGTH => PAYLOAD_FRAME_SIZE ) port map ( - clk => clk, - addr => payload_addr, - wen => payload_wen, - ren => payload_ren, - wr_data => payload_write_data, - rd_data => payload_read_data + clk => clk, + reset => reset or sample_abort_read, + addr => std_logic_vector(sample_addr), + read => payload_read, + ready_in => payload_ready_in, + valid_in => payload_valid_in, + data_in => payload_write_data, + ready_out => payload_ready_out, + valid_out => payload_valid_out, + data_out => payload_read_data ); - - instance_ram_inst : entity work.single_port_ram(arch) + + instance_mem_ctrl_inst : entity work.mem_ctrl(arch) generic map ( - ADDR_WIDTH => INSTANCE_MEMORY_ADDR_WIDTH, - DATA_WIDTH => WORD_WIDTH, - MEMORY_DEPTH => INSTANCE_MEMORY_SIZE + ADDR_WIDTH => INSTANCE_MEMORY_ADDR_WIDTH, + DATA_WIDTH => WORD_WIDTH, + MEMORY_DEPTH => INSTANCE_MEMORY_SIZE, + MAX_BURST_LENGTH => INSTANCE_FRAME_SIZE ) port map ( - clk => clk, - addr => inst_addr, - wen => inst_wen, - ren => inst_ren, - wr_data => inst_write_data, - rd_data => inst_read_data + clk => clk, + reset => reset or sample_abort_read, + addr => std_logic_vector(sample_addr), + read => instance_read, + ready_in => instance_ready_in, + valid_in => instance_valid_in, + data_in => instance_write_data, + ready_out => instance_ready_out, + valid_out => instance_valid_out, + data_out => instance_read_data ); - + + key_hash_generator_inst : entity work.key_hash_generator(arch) port ( clk => clk, @@ -384,20 +410,24 @@ begin parse_a_prc : process (all) variable tmp_dw : DOUBLE_WORD_ARRAY := (others => (others => '0')); variable tmp_bitmap : std_logic_vector(0 to ENDPOINT_BITMAP_WIDTH-1) := (others => '0'); - variable tmp_update : std_logic_vector(0 to UPDATE_INSTANCE_FLAG_WIDTH-1) := (others => '0'); + variable tmp_update : std_logic_vector(0 to IMF_FLAG_WIDTH-1) := (others => '0'); variable tmp_bool : boolean := FALSE; begin -- Default stage_next <= stage; res_rtps <= UNDEFINED; - sample_addr_next <= sample_addr; + sample_addr <= (others => '0'); sample_write_data <= (others => '0'); - sample_ren <= '0'; - sample_wen <= '0'; - payload_addr_next <= payload_addr; + sample_read <= '0'; + sample_ready_out <= '0'; + sample_valid_in <= '0'; + sample_abort_read <= '0'; + payload_addr <= (others => '0'); payload_write_data <= (others => '0'); - payload_ren <= '0'; - payload_wen <= '0'; + payload_read <= '0'; + payload_ready_out <= '0'; + payload_valid_in <= '0'; + payload_abort_read <= '0'; ready_in_rtps <= '0'; newest_sample_next <= newest_sample; empty_payload_list_head_next <= empty_payload_list_head; @@ -409,6 +439,8 @@ begin long_latch_next <= long_latch; sample_addr_latch_1_next <= sample_addr_latch_1; sample_addr_latch_2_next <= sample_addr_latch_2; + sample_addr_latch_3_next <= sample_addr_latch_3; + sample_addr_latch_4_next <= sample_addr_latch_4; payload_mem_full_next <= payload_mem_full; sample_mem_full_next <= sample_mem_full; writer_pos_next <= writer_pos; @@ -473,6 +505,7 @@ begin abort_khg <= '0'; return_code_dds <= RETCODE_UNSUPPORTED; status_sig_next <= status_sig; + cnt2_next <= cnt2; case (stage) is when IDLE => @@ -501,7 +534,6 @@ begin -- Samples Available if (oldest_sample /= SAMPLE_MEMORY_MAX_ADDRESS) then cur_sample <= oldest_sample; - sample_addr_next <= oldest_sample + SMF_NEXT_ADDR_OFFSET; stage_next <= CHECK_LIFESPAN; cnt_next <= 0; end if; @@ -514,7 +546,6 @@ begin res_rtps <= ACK; stage_next <= ADD_SAMPLE_INFO; cur_sample_next <= empty_sample_list_head; - sample_addr_next <= empty_sample_list_head; cnt_next <= 0; end if; when REMOVE_WRITER => @@ -524,7 +555,7 @@ begin writer_pos_next <= to_integer(unsigned(data_in_rtps)); inst_op_start <= '1'; inst_opcode <= GET_FIRST_INSTANCE; - inst_data_variant <= VAR_1; + inst_mem_fields <= IMF_STATUS_FLAG or IMF_WRITER_BITMAP_FLAG; stage_next <= REMOVE_WRITER; res_rtps <= ACK; end if; @@ -534,8 +565,8 @@ begin elsif (unmark_instances = '1') then -- Memory Operation Guard if (inst_op_done = '1') then - inst_op_start <= '1'; - inst_opcode <= UNMARK_INTANCES; + inst_op_start <= '1'; + inst_opcode <= UNMARK_INTANCES; unmark_instances_next <= '0'; end if; elsif (start_dds = '1') then @@ -569,7 +600,6 @@ begin when READ => ack_dds <= '1'; cur_sample_next <= oldest_sample; - sample_addr_next <= oldest_sample + SMF_STATUS_INFO_OFFSET; cur_inst_next <= INSTANCE_MEMORY_MAX_ADDRESS; stage_next <= GET_NEXT_SAMPLE; cnt_next <= 0; @@ -577,7 +607,6 @@ begin is_take_next <= '1'; ack_dds <= '1'; cur_sample_next <= oldest_sample; - sample_addr_next <= oldest_sample + SMF_STATUS_INFO_OFFSET; cur_inst_next <= INSTANCE_MEMORY_MAX_ADDRESS; stage_next <= GET_NEXT_SAMPLE; cnt_next <= 0; @@ -585,7 +614,6 @@ begin ack_dds <= '1'; single_sample_next <= '1'; cur_sample_next <= oldest_sample; - sample_addr_next <= oldest_sample + SMF_STATUS_INFO_OFFSET; cur_inst_next <= INSTANCE_MEMORY_MAX_ADDRESS; sample_state_next <= NOT_READ_SAMPLE_STATE; view_state_next <= ANY_VIEW_STATE; @@ -598,7 +626,6 @@ begin is_take_next <= '1'; single_sample_next <= '1'; cur_sample_next <= oldest_sample; - sample_addr_next <= oldest_sample + SMF_STATUS_INFO_OFFSET; cur_inst_next <= INSTANCE_MEMORY_MAX_ADDRESS; sample_state_next <= NOT_READ_SAMPLE_STATE; view_state_next <= ANY_VIEW_STATE; @@ -610,7 +637,6 @@ begin ack_dds <= '1'; single_instance_next <= '1'; cur_sample_next <= oldest_sample; - sample_addr_next <= oldest_sample + SMF_STATUS_INFO_OFFSET; key_hash_next <= instance_handle_in; stage_next <= CHECK_INSTANCE; cnt_next <= 0; @@ -619,7 +645,6 @@ begin is_take_next <= '1'; single_instance_next <= '1'; cur_sample_next <= oldest_sample; - sample_addr_next <= oldest_sample + SMF_STATUS_INFO_OFFSET; key_hash_next <= instance_handle_in; stage_next <= CHECK_INSTANCE; cnt_next <= 0; @@ -628,7 +653,6 @@ begin single_instance_next <= '1'; dynamic_next_instance_next <= '1'; cur_sample_next <= oldest_sample; - sample_addr_next <= oldest_sample + SMF_STATUS_INFO_OFFSET; key_hash_next <= instance_handle_in; stage_next <= FIND_NEXT_INSTANCE; cnt_next <= 0; @@ -638,7 +662,6 @@ begin single_instance_next <= '1'; dynamic_next_instance_next <= '1'; cur_sample_next <= oldest_sample; - sample_addr_next <= oldest_sample + SMF_STATUS_INFO_OFFSET; key_hash_next <= instance_handle_in; stage_next <= FIND_NEXT_INSTANCE; cnt_next <= 0; @@ -662,119 +685,145 @@ begin -- DONE stage_next <= IDLE; when ADD_SAMPLE_INFO => - -- Precondition: sample_addr (empty_sample_list_head) - - ready_in_rtps <= '1'; + -- Precondition: cur_sample set -- Input Guard if (valid_in_rtps = '1') then - cnt_next <= cnt + 1; - sample_addr_next <= sample_addr + 1; - - -- Write Through - sample_wen <= '1'; - sample_write_data <= data_in_rtps; - case (cnt) is -- Status Info when 0 => + sample_valid_in <= '1'; + sample_addr <= cur_sample + SMF_STATUS_INFO_OFFSET; + sample_write_data <= data_in_rtps; -- Initialize local status bits sample_write_data(READ_FLAG) <= '0'; -- Latch Status Info sample_status_info_next <= data_in_rtps; sample_status_info_next(READ_FLAG) <= '0'; - -- Latch Timestamp for ordering + -- Memory Flow Control Guard + if (sample_ready_in = '1') then + ready_in_rtps <= '1'; + cnt_next <= cnt + 1; + end if; -- Timestamp 1/2 when 1 => + sample_valid_in <= '1'; + sample_addr <= cur_sample + SMF_TIMESTAMP_OFFSET; + sample_write_data <= data_in_rtps; + -- Latch Timestamp ts_latch_next(0) <= data_in_rtps; + -- Memory Flow Control Guard + if (sample_ready_in = '1') then + ready_in_rtps <= '1'; + cnt_next <= cnt + 1; + end if; -- Timestamp 2/2 when 2 => + sample_valid_in <= '1'; + sample_addr <= cur_sample + SMF_TIMESTAMP_OFFSET + 1; + sample_write_data <= data_in_rtps; + -- Latch Timestamp ts_latch_next(1) <= data_in_rtps; - - -- Synthesis Guard - if (DESTINATION_ORDER_QOS = BY_SOURCE_TIMESTAMP_DESTINATION_ORDER_QOS) then - -- Check Timestamp - tmp_dw := (0 => ts_latch(0), 1 => unsigned(data_in_rtps)); - - -- NOTE: Equal timestamps are still acceptable, as they are inserted after the - -- highest last read sample. - - -- Timestamp is smaller than highest last read (Or is Invalid) - if (tmp_dw /= TIME_INVALID or tmp_dw < last_read_ts) then - -- Drop Sample - stage_next <= SKIP_ADD_DROP; + -- Memory Flow Control Guard + if (sample_ready_in = '1') then + ready_in_rtps <= '1'; + cnt_next <= cnt + 1; + -- Synthesis Guard + if (DESTINATION_ORDER_QOS = BY_SOURCE_TIMESTAMP_DESTINATION_ORDER_QOS) then + -- Check Timestamp + tmp_dw := (0 => ts_latch(0), 1 => unsigned(data_in_rtps)); + + -- NOTE: Equal timestamps are still acceptable, as they are inserted after the + -- last read sample. + + -- Timestamp is smaller than highest last read (Or is Invalid) + if (tmp_dw /= TIME_INVALID or tmp_dw < last_read_ts) then + -- Drop Sample + stage_next <= SKIP_ADD_DROP; + end if; end if; end if; - + -- Lifespane Deadline 1/2 + when 3 => + sample_valid_in <= '1'; + sample_addr <= cur_sample + SMF_LIFESPAN_DEADLINE_OFFSET; + sample_write_data <= data_in_rtps; + -- Memory Flow Control Guard + if (sample_ready_in = '1') then + ready_in_rtps <= '1'; + cnt_next <= cnt + 1; + end if; -- Lifespan Deadline 2/2 when 4 => - -- Skip Key Hash, if not available - if (has_key_hash = '0') then - cnt_next <= 9; + sample_valid_in <= '1'; + sample_addr <= cur_sample + SMF_LIFESPAN_DEADLINE_OFFSET + 1; + sample_write_data <= data_in_rtps; + -- Memory Flow Control Guard + if (sample_ready_in = '1') then + ready_in_rtps <= '1'; + -- Skip Key Hash, if not available + if (has_key_hash = '0') then + cnt_next <= 9; + else + cnt_next <= cnt + 1; + end if; end if; - -- Latch Key Hash -- Key Hash 1/4 when 5 => -- Latch Input, but do not pass to Memory - sample_wen <= '0'; - sample_addr_next <= sample_addr; -- Keep Addr (Payload Addr) key_hash_next(0) <= data_in_rtps; + cnt_next <= cnt + 1; -- Key Hash 2/4 when 6 => -- Latch Input, but do not pass to Memory - sample_wen <= '0'; - sample_addr_next <= sample_addr; -- Keep Addr (Payload Addr) key_hash_next(1) <= data_in_rtps; + cnt_next <= cnt + 1; -- Key Hash 3/4 when 7 => -- Latch Input, but do not pass to Memory - sample_wen <= '0'; - sample_addr_next <= sample_addr; -- Keep Addr (Payload Addr) key_hash_next(2) <= data_in_rtps; + cnt_next <= cnt + 1; -- Key Hash 4/4 when 8 => -- Latch Input, but do not pass to Memory - sample_wen <= '0'; - sample_addr_next <= sample_addr; -- Keep Addr (Payload Addr) - key_hash_next(3) <= data_in_rtps; + key_hash_next(3) <= data_in_rtps; + cnt_next <= cnt + 1; -- Writer Endpoint Position when 9 => -- Latch Input, but do not pass to Memory writer_pos_next <= to_integer(unsigned(data_in_rtps)); - sample_wen <= '0'; - sample_addr_next <= sample_addr; -- Keep Addr (Payload Addr) stage_next <= ADD_PAYLOAD_ADDRESS; when others => null; end case; end if; when ADD_PAYLOAD_ADDRESS => - -- Precondition: sample_addr (Payload Address) - - sample_addr_next <= cur_sample + SMF_INSTANCE_ADDR_OFFSET; - + -- Precondition: cur_sample set + + sample_valid_in <= '1'; + sample_addr <= cur_sample + SMF_PAYLOAD_ADDR_OFFSET; if (has_data = '1') then -- Store Payload Address - sample_wen <= '1'; sample_write_data <= empty_payload_list_head; - payload_addr_next <= empty_payload_list_head + PMF_PAYLOAD_OFFSET; cur_payload_next <= empty_payload_list_head; else -- Mark Sample with no Payload - sample_wen <= '1'; sample_write_data <= PAYLOAD_MEMORY_MAX_ADDRESS; end if; - -- If Key Hash is available, start the Instance Search first - if (has_key_hash = '1') then - stage_next <= INITIATE_INSTANCE_SEARCH; - else - stage_next <= ADD_PAYLOAD; - cnt_next <= 0; + -- Memory Flow Control Guard + if (sample_ready_in = '1') then + -- 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; end if; when ADD_PAYLOAD => - -- Precondition (if has_data = '1'): cur_payload set (Current Slot), payload_addr (Beginning of Payload Data of cur_payload) + -- Precondition (if has_data = '1'): cur_payload set (Current Slot) -- 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: @@ -783,93 +832,142 @@ begin -- 1 0 The payload is written to memory and the KHG at the same time (KHG controls the flow) -- 0 0 There is no payload to write, but the input contains the key for the KHG - if (has_key_hash = '0') then - ready_in_rtps <= khg_ready_in; - else - ready_in_rtps <= '1'; - end if; - - -- Flow Control Guard - if ((valid_in_rtps = '1' and has_key_hash = '1') or (valid_in_rtps = '1' and has_key_hash = '0' and khg_ready_in = '1')) then - cnt_next <= cnt + 1; - payload_addr_next <= payload_addr + 1; - - -- Payload Write - if (has_data = '1') then - payload_write_data <= data_in_rtps; - payload_wen <= '1'; - end if; - - -- Key Hash Generator Write - if (has_key_hash = '0') then - khg_data_in <= data_in_rtps; - khg_valid_in <= '1'; - end if; - - -- End of Payload - if (last_word_in_rtps = '1') then - khg_last_word_in <= '1'; - - -- Payload Slot not full - if (has_data = '1' and cnt /= PAYLOAD_FRAME_SIZE-2) then - -- Zero Rest of Payload Slot - stage_next <= ZERO_PAYLOAD; - else - if (has_key_hash = '0') then - -- Fetch the Key Hash - stage_next <= GET_KEY_HASH; - cnt_next <= 0; - else - stage_next <= FILTER_STAGE; + case (cnt) is + -- Push to memory + when 0 => + -- Input Guard + if (valid_in_rtps = '1') then + payload_valid_in <= '1'; + payload_addr <= cur_payload + cnt2; + payload_write_data <= data_in_rtps; + -- Memory Control Flow Guard + if (payload_ready_in = '1') then + cnt2_next <= cnt2 + 1; + + -- Key Hash needs to be calculated + if (has_key_hash = '0') then + cnt_next <= 1; + else + ready_in_rtps <= '1'; + -- End of Payload + if (last_word_in_rtps = '1') then + -- End of Payload Slot + if (cnt2 = PAYLOAD_FRAME_SIZE-1) then + stage_next <= FILTER_STAGE; + else + stage_next <= ZERO_PAYLOAD; + end if; + else + -- End of Payload Slot + if (cnt2 = PAYLOAD_FRAME_SIZE-1) then + stage_next <= NEXT_PAYLOAD_SLOT; + else + -- Next Word + cnt_next <= 0; + end if; + end if; + end if; end if; end if; - -- End of Payload Slot - elsif (has_data = '1' and cnt = PAYLOAD_FRAME_SIZE-2) then - stage_next <= NEXT_PAYLOAD_SLOT; - payload_addr_next <= cur_payload + PMF_NEXT_ADDR_OFFSET; - cnt_next <= 0; - end if; - end if; + -- Push to KHG + when 1 => + assert (valid_in_rtps = '1') severity FAILURE; + + khg_valid_in <= '1'; + khg_data_in <= data_in_rtps; + + -- Output Guard + if (khg_ready_in = '1') then + ready_in_rtps <= '1'; + if (has_data = '1') then + -- End of Payload + if (last_word_in_rtps = '1') then + -- End of Payload Slot + if (cnt2 = PAYLOAD_FRAME_SIZE) then + -- Fetch the Key Hash + stage_next <= GET_KEY_HASH; + cnt_next <= 0; + else + stage_next <= ZERO_PAYLOAD; + end if; + else + -- End of Payload Slot + if (cnt2 = PAYLOAD_FRAME_SIZE) then + stage_next <= NEXT_PAYLOAD_SLOT; + cnt_next <= 0; + else + -- Next Word + cnt_next <= 0; + end if; + end if; + else + -- End of Payload + if (last_word_in_rtps = '1') then + -- Fetch the Key Hash + stage_next <= GET_KEY_HASH; + cnt_next <= 0; + else + -- Next Word + cnt_next <= 1; + end if; + end if; + end if; + when others => + null; + end case; when NEXT_PAYLOAD_SLOT => - -- Precondition: payload_addr (Next Pointer of cur_payload) - - cnt_next <= cnt + 1; + -- Precondition: cur_payload set case (cnt) is - -- Preload + -- GET Next Pointer when 0 => - payload_ren <= '1'; + payload_valid_in <= '1'; + payload_addr <= cur_payload + PMF_NEXT_ADDR_OFFSET; + payload_read <= '1'; + + -- Memory Control Flow Guard + if (payload_ready_in = '1') then + cnt_next <= cnt + 1; + end if; + -- READ Next Pointer when 1 => - -- No Empty Payload Slots available - if (payload_read_data = PAYLOAD_MEMORY_MAX_ADDRESS) then - -- Reject Change - stage_next <= SKIP_ADD_REJECT; - -- Abort Key Hash Generation - abort_khg <= '1'; - else - -- Latch next Payload Slot and Continue - cur_payload_next <= payload_read_data; - payload_addr_next <= payload_read_data + PMF_PAYLOAD_OFFSET; - stage_next <= ADD_PAYLOAD; + payload_ready_out <= '1'; + + -- Memory Control Flow Guard + if (payload_valid_out = '1') then + -- No Empty Payload Slots available + if (payload_read_data = PAYLOAD_MEMORY_MAX_ADDRESS) then + -- Reject Change + stage_next <= SKIP_ADD_REJECT; + -- Abort Key Hash Generation + abort_khg <= '1'; + else + -- Latch next Payload Slot and Continue + cur_payload_next <= payload_read_data; + stage_next <= ADD_PAYLOAD; + cnt_next <= 0; + cnt2_next <= 1; + end if; end if; when others => null; end case; when ZERO_PAYLOAD => - cnt_next <= cnt + 1; - payload_addr_next <= payload_addr + 1; - -- Zero Payload + payload_valid_in <= '1'; + payload_addr <= cur_payload + cnt2; payload_write_data <= (others => '0'); - payload_wen <= '1'; - -- Exit Condition - if (cnt = PAYLOAD_FRAME_SIZE-2) then - if (has_key_hash = '0') then - stage_next <= GET_KEY_HASH; - cnt_next <= 0; - else - stage_next <= FILTER_STAGE; + -- Memory Control Flow Guard + if (payload_ready_in = '1') then + -- Exit Condition + if (cnt2 = PAYLOAD_FRAME_SIZE-1) then + if (has_key_hash = '0') then + stage_next <= GET_KEY_HASH; + cnt_next <= 0; + else + stage_next <= FILTER_STAGE; + end if; end if; end if; when GET_KEY_HASH => @@ -880,7 +978,7 @@ begin cnt_next <= cnt + 1; -- Latch Key Hash - key_hash_next(cnt) <= khg_data_out; + key_hash_next(cnt) <= khg_data_out; -- Exit Condition if (khg_last_word_out = '1') then @@ -891,9 +989,9 @@ begin when INITIATE_INSTANCE_SEARCH => -- Memory Operation Guard if (inst_op_done = '1') then - inst_opcode <= SEARCH_INSTANCE_HASH; inst_op_start <= '1'; - inst_data_variant <= VAR_1; + inst_opcode <= SEARCH_INSTANCE_HASH; + inst_mem_fields <= IMF_STATUS_FLAG or IMF_SAMPLE_CNT_FLAG or IMF_DISPOSED_CNT_FLAG or IMF_NO_WRITERS_CNT_FLAG or IMF_IGNORE_DEADLINE_FLAG or IMF_WRITER_BITMAP_FLAG; -- Payload not yet stored if (has_data = '1') then @@ -904,141 +1002,144 @@ begin end if; end if; when FILTER_STAGE => - -- Precondition: sample_addr (Instance Address of New Sample) + -- Precondition: cur_sample set -- Wait for Instance Search to finish if (inst_op_done = '1') then - sample_addr_next <= cur_sample + SMF_DISPOSED_GEN_CNT_OFFSET; - cur_inst_next <= inst_addr_base; + sample_valid_in <= '1'; + sample_addr <= cur_sample + SMF_INSTANCE_ADDR_OFFSET; + cur_inst_next <= inst_addr_base; -- Instance Found if (inst_addr_base /= INSTANCE_MEMORY_MAX_ADDRESS) then -- Store Instance Address sample_write_data <= inst_addr_base; - sample_wen <= '1'; - -- TIME_BASED_FILTER QOS - if (TIME_BASED_FILTER_QOS /= DURATION_ZERO and time <= inst_data.ignore_deadline) then - -- Drop Change - res_rtps <= ACCEPTED; - stage_next <= IDLE; - -- RESOURCE_LIMITS_QOS (MAX_SAMPLES_PER_INSTANCE) - elsif (MAX_SAMPLES_PER_INSTANCE /= LENGTH_UNLIMITED and inst_data.sample_cnt = MAX_SAMPLES_PER_INSTANCE) then - if (HISTORY_QOS = KEEP_LAST_HISTORY_QOS and RELIABILITY_QOS = RELIABLE_RELIABILITY_QOS) then - -- Reject Change - res_rtps <= REJECTED; + -- Memory Flow Control Guard + if (sample_ready_in = '1') then + -- TIME_BASED_FILTER QOS + if (TIME_BASED_FILTER_QOS /= DURATION_ZERO and time <= inst_data.ignore_deadline) then + -- Drop Change + res_rtps <= ACCEPTED; stage_next <= IDLE; - -- Update Sample Reject Status - status_sig_next(SAMPLE_REJECTED_STATUS) <= '1'; - sample_rej_cnt_next <= sample_rej_cnt + 1; - sample_rej_cnt_change_next <= sample_rej_cnt_change + 1; - sample_rej_last_reason_next <= REJECTED_BY_SAMPLES_PER_INSTANCE_LIMIT; - sample_rej_last_inst_next <= key_hash; + -- RESOURCE_LIMITS_QOS (MAX_SAMPLES_PER_INSTANCE) + elsif (MAX_SAMPLES_PER_INSTANCE /= LENGTH_UNLIMITED and inst_data.sample_cnt = MAX_SAMPLES_PER_INSTANCE) then + if (HISTORY_QOS = KEEP_LAST_HISTORY_QOS and RELIABILITY_QOS = RELIABLE_RELIABILITY_QOS) then + -- Reject Change + res_rtps <= REJECTED; + stage_next <= IDLE; + -- Update Sample Reject Status + status_sig_next(SAMPLE_REJECTED_STATUS) <= '1'; + sample_rej_cnt_next <= sample_rej_cnt + 1; + sample_rej_cnt_change_next <= sample_rej_cnt_change + 1; + sample_rej_last_reason_next <= REJECTED_BY_SAMPLES_PER_INSTANCE_LIMIT; + sample_rej_last_inst_next <= key_hash; + else + -- Accept Change (Remove Oldest Instance Sample) + remove_oldest_inst_sample_next <= '1'; + res_rtps <= ACCEPTED; + stage_next <= UPDATE_INSTANCE; + end if; + -- RESOURCE_LIMITS_QOS (MAX_SAMPLES) + elsif (empty_sample_list_head = empty_sample_list_tail) then + if (HISTORY_QOS = KEEP_ALL_HISTORY_QOS and RELIABILITY_QOS = RELIABLE_RELIABILITY_QOS) then + -- Reject Change + res_rtps <= REJECTED; + stage_next <= IDLE; + -- Update Sample Reject Status + status_sig_next(SAMPLE_REJECTED_STATUS) <= '1'; + sample_rej_cnt_next <= sample_rej_cnt + 1; + sample_rej_cnt_change_next <= sample_rej_cnt_change + 1; + sample_rej_last_reason_next <= REJECTED_BY_SAMPLES_LIMIT; + sample_rej_last_inst_next <= key_hash; + else + -- Accept Change (Remove Oldest Sample) + remove_oldest_sample_next <= '1'; + res_rtps <= ACCEPTED; + stage_next <= UPDATE_INSTANCE; + end if; else - -- Accept Change (Remove Oldest Instance Sample) - remove_oldest_inst_sample_next <= '1'; + -- Accept Change res_rtps <= ACCEPTED; stage_next <= UPDATE_INSTANCE; end if; - -- RESOURCE_LIMITS_QOS (MAX_SAMPLES) - elsif (empty_sample_list_head = empty_sample_list_tail) then - if (HISTORY_QOS = KEEP_ALL_HISTORY_QOS and RELIABILITY_QOS = RELIABLE_RELIABILITY_QOS) then - -- Reject Change - res_rtps <= REJECTED; - stage_next <= IDLE; - -- Update Sample Reject Status - status_sig_next(SAMPLE_REJECTED_STATUS) <= '1'; - sample_rej_cnt_next <= sample_rej_cnt + 1; - sample_rej_cnt_change_next <= sample_rej_cnt_change + 1; - sample_rej_last_reason_next <= REJECTED_BY_SAMPLES_LIMIT; - sample_rej_last_inst_next <= key_hash; - else - -- Accept Change (Remove Oldest Sample) - remove_oldest_sample_next <= '1'; - res_rtps <= ACCEPTED; - stage_next <= UPDATE_INSTANCE; - end if; - else - -- Accept Change - res_rtps <= ACCEPTED; - stage_next <= UPDATE_INSTANCE; end if; else -- Store Instance Address sample_write_data <= inst_empty_head; - sample_wen <= '1'; - -- RESOURCE_LIMITS_QOS (MAX_INSTANCES) (Instance Memory Full) - if (inst_empty_head = INSTANCE_MEMORY_MAX_ADDRESS) then - -- Reject Change - res_rtps <= REJECTED; - stage_next <= IDLE; - -- Update Sample Reject Status - status_sig_next(SAMPLE_REJECTED_STATUS) <= '1'; - sample_rej_cnt_next <= sample_rej_cnt + 1; - sample_rej_cnt_change_next <= sample_rej_cnt_change + 1; - sample_rej_last_reason_next <= REJECTED_BY_INSTANCES_LIMIT; - sample_rej_last_inst_next <= key_hash; - -- RESOURCE_LIMITS_QOS (MAX_SAMPLES) - elsif (empty_sample_list_head = empty_sample_list_tail) then - if (HISTORY_QOS = KEEP_ALL_HISTORY_QOS and RELIABILITY_QOS = RELIABLE_RELIABILITY_QOS) then - -- Reject Change + -- Memory Flow Control Guard + if (sample_ready_in = '1') then + -- RESOURCE_LIMITS_QOS (MAX_INSTANCES) (Instance Memory Full) + if (inst_empty_head = INSTANCE_MEMORY_MAX_ADDRESS) then + -- Reject Change res_rtps <= REJECTED; stage_next <= IDLE; -- Update Sample Reject Status status_sig_next(SAMPLE_REJECTED_STATUS) <= '1'; sample_rej_cnt_next <= sample_rej_cnt + 1; sample_rej_cnt_change_next <= sample_rej_cnt_change + 1; - sample_rej_last_reason_next <= REJECTED_BY_SAMPLES_LIMIT; + sample_rej_last_reason_next <= REJECTED_BY_INSTANCES_LIMIT; sample_rej_last_inst_next <= key_hash; + -- RESOURCE_LIMITS_QOS (MAX_SAMPLES) + elsif (empty_sample_list_head = empty_sample_list_tail) then + if (HISTORY_QOS = KEEP_ALL_HISTORY_QOS and RELIABILITY_QOS = RELIABLE_RELIABILITY_QOS) then + -- Reject Change + res_rtps <= REJECTED; + stage_next <= IDLE; + -- Update Sample Reject Status + status_sig_next(SAMPLE_REJECTED_STATUS) <= '1'; + sample_rej_cnt_next <= sample_rej_cnt + 1; + sample_rej_cnt_change_next <= sample_rej_cnt_change + 1; + sample_rej_last_reason_next <= REJECTED_BY_SAMPLES_LIMIT; + sample_rej_last_inst_next <= key_hash; + else + -- Accept Change (Remove Oldest Sample) + remove_oldest_sample_next <= '1'; + res_rtps <= ACCEPTED; + + -- Only Insert Sample/Instance if Instance is ALIVE + if (sample_status_info(DISPOSED_FLAG) /= '1' and sample_status_info(UNREGISTERED_FLAG) /= '1' and sample_status_info(FILTERED_FLAG) /= '1') then + -- Insert New Instance + inst_op_start <= '1'; + inst_opcode <= INSERT_INSTANCE; + + added_new_instance_next <= '1'; + + if (has_data = '1') then + 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 (Remove Oldest Sample) - remove_oldest_sample_next <= '1'; - res_rtps <= ACCEPTED; + -- Accept Change + res_rtps <= ACCEPTED; -- Only Insert Sample/Instance if Instance is ALIVE if (sample_status_info(DISPOSED_FLAG) /= '1' and sample_status_info(UNREGISTERED_FLAG) /= '1' and sample_status_info(FILTERED_FLAG) /= '1') then -- Insert New Instance - inst_opcode <= INSERT_INSTANCE; inst_op_start <= '1'; - - added_new_instance_next <= '1'; + inst_opcode <= INSERT_INSTANCE; if (has_data = '1') then - payload_addr_next <= cur_payload; - stage_next <= FINALIZE_PAYLOAD; - cnt_next <= 0; + stage_next <= FINALIZE_PAYLOAD; + cnt_next <= 0; else - stage_next <= PRE_SAMPLE_FINALIZE; - cnt_next <= 0; + stage_next <= PRE_SAMPLE_FINALIZE; + cnt_next <= 0; end if; else -- Drop Change stage_next <= IDLE; end if; end if; - else - -- Accept Change - res_rtps <= ACCEPTED; - - -- Only Insert Sample/Instance if Instance is ALIVE - if (sample_status_info(DISPOSED_FLAG) /= '1' and sample_status_info(UNREGISTERED_FLAG) /= '1' and sample_status_info(FILTERED_FLAG) /= '1') then - -- Insert New Instance - inst_opcode <= INSERT_INSTANCE; - inst_op_start <= '1'; - - if (has_data = '1') then - payload_addr_next <= cur_payload; - stage_next <= FINALIZE_PAYLOAD; - cnt_next <= 0; - else - stage_next <= PRE_SAMPLE_FINALIZE; - cnt_next <= 0; - end if; - else - -- Drop Change - stage_next <= IDLE; - end if; end if; end if; end if; @@ -1053,7 +1154,7 @@ begin -- 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; + tmp_update <= tmp_update or IMF_STATUS_FLAG; status_info_update <= inst_data.status; status_info_update(NOT_ALIVE_DISPOSED_FLAG) <= '1'; status_info_update(NOT_ALIVE_NO_WRITERS_FLAG) <= '0'; @@ -1066,7 +1167,7 @@ begin tmp_bitmap(writer_pos) := '0'; -- Convert Back writer_bitmap <= from_endpoint_bitmap(tmp_bitmap); - tmp_update := tmp_update or WRITER_BITMAP_FLAG; + tmp_update := tmp_update or IMF_WRITER_BITMAP_FLAG; -- Instance UNREGISTERED elsif (sample_status_info(UNREGISTERED_FLAG) = '1') then -- WRITER BITMAP @@ -1076,12 +1177,12 @@ begin tmp_bitmap(writer_pos) := '0'; -- Convert Back writer_bitmap <= from_endpoint_bitmap(tmp_bitmap); - tmp_update := tmp_update or WRITER_BITMAP_FLAG; + tmp_update := tmp_update or IMF_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; + tmp_update <= tmp_update or IMF_STATUS_FLAG; status_info_update <= inst_data.status; status_info_update(NOT_ALIVE_DISPOSED_FLAG) <= '0'; status_info_update(NOT_ALIVE_NO_WRITERS_FLAG) <= '1'; @@ -1090,7 +1191,7 @@ begin -- Instance ALIVE/FILTERED else -- STATUS INFO - tmp_update <= tmp_update or STATUS_FLAG; + tmp_update <= tmp_update or IMF_STATUS_FLAG; status_info_update <= inst_data.status; status_info_update(NOT_ALIVE_DISPOSED_FLAG) <= '0'; status_info_update(NOT_ALIVE_NO_WRITERS_FLAG) <= '0'; @@ -1100,11 +1201,11 @@ begin -- 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; + tmp_update := tmp_update or IMF_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; + tmp_update := tmp_update or IMF_NO_WRITERS_CNT_FLAG; gen_cnt <= inst_data.no_writers_gen_cnt + 1; end if; @@ -1117,27 +1218,26 @@ begin tmp_bitmap(writer_pos) := '0'; -- Convert Back writer_bitmap <= from_endpoint_bitmap(tmp_bitmap); - tmp_update := tmp_update or WRITER_BITMAP_FLAG; + tmp_update := tmp_update or IMF_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; + tmp_update := tmp_update or IMF_SAMPLE_CNT_FLAG; end if; -- IGNORE DEADLINE if (TIME_BASED_FILTER_QOS /= DURATION_ZERO) then - tmp_update := tmp_update or IGNORE_DEADLINE_FLAG; + tmp_update := tmp_update or IMF_IGNORE_DEADLINE_FLAG; deadline <= time + TIME_BASED_FILTER_QOS; end if; - inst_opcode <= UPDATE_INSTANCE; - inst_op_start <= '1'; - update_inst_flags <= tmp_update; + inst_op_start <= '1'; + inst_opcode <= UPDATE_INSTANCE; + inst_mem_fields <= tmp_update; if (has_data = '1') then - payload_addr_next <= cur_payload; stage_next <= FINALIZE_PAYLOAD; cnt_next <= 0; else @@ -1146,37 +1246,53 @@ begin end if; end if; when FINALIZE_PAYLOAD => - -- Precondition: payload_addr (Beginning of Last Added Payload Slot) - - cnt_next <= cnt + 1; + -- Precondition: cur_payload set case (cnt) is - -- Preload + -- GET Next Pointer when 0 => - payload_ren <= '1'; - when 1 => - -- Fix New Empty List Head - empty_payload_list_head_next <= payload_read_data; + payload_valid_in <= '1'; + payload_addr <= cur_payload + PMF_NEXT_ADDR_OFFSET; + payload_read <= '1'; + -- Memory Control Flow Guard + if (payload_ready_in = '1') then + cnt_next <= cnt + 1; + end if; + -- Next Pointer + when 1 => + payload_valid_in <= '1'; + payload_addr <= cur_payload + PMF_NEXT_ADDR_OFFSET; -- Make current Slot the Tail payload_write_data <= PAYLOAD_MEMORY_MAX_ADDRESS; - payload_wen <= '1'; - stage_next <= PRE_SAMPLE_FINALIZE; - cnt_next <= 0; + -- Memory Control Flow Guard + if (payload_ready_in = '1') then + cnt_next <= cnt + 1; + end if; + -- READ Next Pointer + when 2 => + payload_ready_out <= '1'; + + -- Memory Control Flow Guard + if (payload_valid_out = '1') then + -- Fix New Empty List Head + empty_payload_list_head_next <= payload_read_data; + + stage_next <= PRE_SAMPLE_FINALIZE; + cnt_next <= 0; + end if; when others => null; end case; when PRE_SAMPLE_FINALIZE => - -- Precondition: sample_addr (Disposed generation Counter of New Sample) - - cnt_next <= cnt + 1; + -- Precondition: cur_sample set case (cnt) is -- Disposed Generation Counter when 0 => - sample_addr_next <= cur_sample + SMF_NO_WRITERS_GEN_CNT_OFFSET; - sample_wen <= '1'; + sample_valid_in <= '1'; + sample_addr <= cur_sample + SMF_DISPOSED_GEN_CNT_OFFSET; -- 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 @@ -1184,9 +1300,15 @@ begin else sample_write_data <= gen_cnt; end if; + + -- Memory Flow Control Guard + if (sample_ready_in = '1') then + cnt_next <= cnt + 1; + end if; -- No Writer Generation Counter when 1 => - sample_wen <= '1'; + sample_valid_in <= '1'; + sample_addr <= cur_sample + SMF_NO_WRITERS_GEN_CNT_OFFSET; -- 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 @@ -1194,11 +1316,15 @@ begin else sample_write_data <= gen_cnt; end if; + + -- Memory Flow Control Guard + if (sample_ready_in = '1') then + cnt_next <= cnt + 1; + end if; when 2 => -- First Sample if (newest_sample = SAMPLE_MEMORY_MAX_ADDRESS) then stage_next <= FINALIZE_SAMPLE; - sample_addr_next <= empty_sample_list_head + SMF_PREV_ADDR_OFFSET; cur_sample_next <= empty_sample_list_head; next_sample_next <= SAMPLE_MEMORY_MAX_ADDRESS; prev_sample_next <= SAMPLE_MEMORY_MAX_ADDRESS; @@ -1206,13 +1332,11 @@ begin elsif (DESTINATION_ORDER_QOS = BY_RECEPTION_TIMESTAMP_DESTINATION_ORDER_QOS) then stage_next <= FIX_POINTERS; prev_sample_next <= newest_sample; - sample_addr_next <= newest_sample + SMF_NEXT_ADDR_OFFSET; cur_sample_next <= newest_sample; cnt_next <= 0; else stage_next <= FIND_POS; prev_sample_next <= newest_sample; - sample_addr_next <= newest_sample + SMF_TIMESTAMP_OFFSET; cur_sample_next <= newest_sample; cnt_next <= 0; end if; @@ -1222,208 +1346,300 @@ begin when FIND_POS => -- Synthesis Guard if (DESTINATION_ORDER_QOS /= BY_RECEPTION_TIMESTAMP_DESTINATION_ORDER_QOS) then - -- Precondition: prev_sample set, sample_addr (Timestamp 1/2 Addr of prev_sample) + -- Precondition: cur_sample set cnt_next <= cnt + 1; case (cnt) is - -- Preload + -- GET Timestamp 1/2 when 0 => - sample_addr_next <= sample_addr + 1; -- Timestamp 2/2 - sample_ren <= '1'; - -- Timestamp 1/2 - when 1 => - sample_addr_next <= cur_sample + SMF_PREV_ADDR_OFFSET; - sample_ren <= '1'; - long_latch_next <= sample_read_data; - -- Timestamp 2/2 - when 2 => - sample_ren <= '1'; + sample_valid_in <= '1'; + sample_addr <= cur_sample + SMF_TIMESTAMP_OFFSET; + sample_read <= '1'; - tmp_dw := (0 => unsigned(long_latch), 1 => unsigned(sample_read_data)); - - sample_addr_next <= cur_sample + SMF_NEXT_ADDR_OFFSET; - - -- Found position (After current slot) - if (ts_latch >= tmp_dw) then - stage_next <= FIX_POINTERS; - cnt_next <= 0; + -- Memory Flow Control Guard + if (sample_ready_in = '1') then + cnt_next <= cnt + 1; end if; - -- Previous Pointer (Previous Sample) + -- GET Timestamp 2/2 + when 1 => + sample_valid_in <= '1'; + sample_addr <= cur_sample + SMF_TIMESTAMP_OFFSET + 1; + sample_read <= '1'; + + -- Memory Flow Control Guard + if (sample_ready_in = '1') then + cnt_next <= cnt + 1; + end if; + -- GET Previous Sample + when 2 => + sample_valid_in <= '1'; + sample_addr <= cur_sample + SMF_PREV_ADDR_OFFSET; + sample_read <= '1'; + + -- Memory Flow Control Guard + if (sample_ready_in = '1') then + cnt_next <= cnt + 1; + end if; + -- READ Timestamp 1/2 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; + sample_ready_out <= '1'; + + -- Memory Flow Control Guard + if (sample_valid_out = '1') then + long_latch_next <= sample_read_data; + cnt_next <= cnt + 1; + end if; + -- READ Timestamp 2/2 + when 4 => + sample_ready_out <= '1'; + + -- Memory Flow Control Guard + if (sample_valid_out = '1') then + tmp_dw := (0 => unsigned(long_latch), 1 => unsigned(sample_read_data)); - -- NOTE: Sample is added to HEAD of List - - prev_sample_next <= SAMPLE_MEMORY_MAX_ADDRESS; - next_sample_next <= cur_sample; - stage_next <= FIX_POINTERS; - cnt_next <= 2; -- Skip to Previous Pointer Fix - else - -- Continue Search - prev_sample_next <= sample_read_data; - sample_addr_next <= sample_read_data + SMF_TIMESTAMP_OFFSET; - cnt_next <= 0; + -- Found position (After current slot) + if (ts_latch >= tmp_dw) then + prev_sample_next <= cur_sample; + stage_next <= FIX_POINTERS; + cnt_next <= 0; + sample_abort_read <= '1'; + end if; + end if; + -- READ Previous Sample + when 5 => + sample_ready_out <= '1'; + + if (sample_valid_out = '1') then + -- No previous Slot (Oldest Sample) + if (sample_read_data = PAYLOAD_MEMORY_MAX_ADDRESS) then + assert (prev_sample = oldest_sample) report "Previous Sample is MAX_ADDR, but sample is not OLDEST (HEAD)" severity FAILURE; + + -- NOTE: Sample is added to HEAD of List + + prev_sample_next <= SAMPLE_MEMORY_MAX_ADDRESS; + next_sample_next <= cur_sample; + stage_next <= FIX_POINTERS; + cnt_next <= 1; -- Skip to Previous Pointer Fix + else + -- Continue Search + cur_sample_next <= sample_read_data; + next_sample_next <= cur_sample; + cnt_next <= 0; + end if; end if; end case; end if; when FIX_POINTERS => - -- Precondition: sample_addr (Next Addr of prev_sample) - - cnt_next <= cnt + 1; + -- Precondition: prev_sample set, next_sample set case (cnt) is - -- Preload - when 0 => - sample_ren <= '1'; -- Next Pointer (Previous Sample) - when 1 => - + when 0 => -- Fix Next Pointer - sample_write_data <= empty_sample_list_head; - sample_wen <= '1'; + sample_valid_in <= '1'; + sample_addr <= prev_sample + SMF_NEXT_ADDR_OFFSET; + sample_write_data <= empty_sample_list_head; - -- No next Slot (Newest Sample) - if (sample_read_data = SAMPLE_MEMORY_MAX_ADDRESS) then - assert (prev_sample = newest_sample) report "Next Sample is MAX_ADDRESS, but sample is not NEWEST (TAIL)" severity FAILURE; - - next_sample_next <= SAMPLE_MEMORY_MAX_ADDRESS; - stage_next <= FINALIZE_SAMPLE; - sample_addr_next <= empty_sample_list_head + SMF_PREV_ADDR_OFFSET; - cur_sample_next <= empty_sample_list_head; - cnt_next <= 0; - else - -- Latch Next Sample - next_sample_next <= sample_read_data; - - sample_addr_next <= sample_read_data + SMF_PREV_ADDR_OFFSET; -- Prev Addr of Next Sample + -- Memory Flow Control Guard + if (sample_ready_in = '1') then + -- No next Slot (Newest Sample) + if (next_sample = SAMPLE_MEMORY_MAX_ADDRESS) then + assert (prev_sample = newest_sample) report "Next Sample is MAX_ADDRESS, but sample is not NEWEST (TAIL)" severity FAILURE; + + stage_next <= FINALIZE_SAMPLE; + cur_sample_next <= empty_sample_list_head; + cnt_next <= 0; + else + cnt_next <= 1; + end if; end if; -- Previous Pointer (Next Sample) - when 2 => + when 1 => -- Fix Previous Pointer + sample_valid_in <= '1'; + sample_addr <= next_sample + SMF_PREV_ADDR_OFFSET; sample_write_data <= empty_sample_list_head; - sample_wen <= '1'; - stage_next <= FINALIZE_SAMPLE; - sample_addr_next <= empty_sample_list_head + SMF_PREV_ADDR_OFFSET; - cur_sample_next <= empty_sample_list_head; - cnt_next <= 0; + -- Memory Flow Control Guard + if (sample_ready_in = '1') then + stage_next <= FINALIZE_SAMPLE; + cur_sample_next <= empty_sample_list_head; + cnt_next <= 0; + end if; when others => null; end case; when FINALIZE_SAMPLE => - -- Precondition: prev_sample set, next_sample set, sample_addr (Prev Addr of new sample) - - cnt_next <= cnt + 1; + -- Precondition: prev_sample set, next_sample set, cur_sample case (cnt) is - -- Previous Sample Address + -- GET Next (Empty) Sample when 0 => - sample_addr_next <= cur_sample + SMF_NEXT_ADDR_OFFSET; - - -- Write Prev Addr - sample_write_data <= prev_sample; - sample_wen <= '1'; - -- Preload + sample_valid_in <= '1'; + sample_addr <= cur_sample + SMF_NEXT_ADDR_OFFSET; + sample_read <= '1'; + -- Memory Flow Control Guard + if (sample_ready_in = '1') then + cnt_next <= cnt + 1; + end if; + -- Previous Pointer when 1 => - sample_ren <= '1'; - -- Next Sample Address + -- Write Previous Pointer + sample_valid_in <= '1'; + sample_addr <= cur_sample + SMF_PREV_ADDR_OFFSET; + sample_write_data <= prev_sample; + + -- Memory Flow Control Guard + if (sample_ready_in = '1') then + cnt_next <= cnt + 1; + end if; + -- Next Pointer when 2 => - empty_sample_list_head_next <= sample_read_data; + -- Write Next Pointer + sample_valid_in <= '1'; + sample_addr <= cur_sample + SMF_NEXT_ADDR_OFFSET; + sample_write_data <= next_sample; - -- 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; + -- Memory Flow Control Guard + if (sample_ready_in = '1') then + cnt_next <= cnt + 1; end if; - -- Signal Data Available - status_sig_next(DATA_AVAILABLE_STATUS) <= '1'; + -- READ Next (Empty) Sample + when 3 => + sample_ready_out <= '1'; - -- NOTE: added_new_instance and remove_oldest_sample are NOT mutual exclusive, but Instance Removal takes precedence. - - -- New Instance was added, and Instance Memory is Full - if (added_new_instance = '1' and inst_empty_head = INSTANCE_MEMORY_MAX_ADDRESS) then - -- Memory Operation Guard - if (inst_op_done = '1') then - inst_op_start <= '1'; - inst_opcode <= GET_FIRST_INSTANCE; - inst_data_variant <= VAR_1; - - -- NOTE: Instances are only removed in two occasions: - -- * A new instance is added, and the instance memory gets full - -- * A Sample is removed, making an instance eligible for deletion, while the - -- instance memory is full. - -- The combination of both cases allows to search and remove instances only when needed. - - stage_next <= REMOVE_STALE_INSTANCE; - else - cnt_next <= cnt; -- Keep State + -- Memory Flow Control Guard + if (sample_valid_out = '1') then + + -- Fix new Empty List Head + empty_sample_list_head_next <= sample_read_data; + + -- If newest Sample is now previous, select current sample as new newest + if (newest_sample = prev_sample) then + newest_sample_next <= cur_sample; + end if; + + -- Signal Data Available + status_sig_next(DATA_AVAILABLE_STATUS) <= '1'; + + -- NOTE: added_new_instance and remove_oldest_sample are NOT mutual exclusive, but Instance Removal takes precedence. + + -- New Instance was added, and Instance Memory is Full + if (added_new_instance = '1' and inst_empty_head = INSTANCE_MEMORY_MAX_ADDRESS) then + -- Memory Operation Guard + if (inst_op_done = '1') then + inst_op_start <= '1'; + inst_opcode <= GET_FIRST_INSTANCE; + inst_mem_fields <= IMF_SAMPLE_CNT_FLAG or IMF_WRITER_BITMAP_FLAG; + + -- NOTE: Instances are only removed in two occasions: + -- * A new instance is added, and the instance memory gets full + -- * A Sample is removed, making an instance eligible for deletion, while the + -- instance memory is full. + -- The combination of both cases allows to search and remove instances only when needed. + + stage_next <= REMOVE_STALE_INSTANCE; + else + cnt_next <= cnt; -- Keep State + end if; + elsif (remove_oldest_inst_sample = '1') then + cur_sample <= oldest_sample; + 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; - elsif (remove_oldest_inst_sample = '1') then - cur_sample <= oldest_sample; - sample_addr_next <= oldest_sample + SMF_INSTANCE_ADDR_OFFSET; - stage_next <= FIND_OLDEST_INST_SAMPLE; - elsif (remove_oldest_sample = '1') then - stage_next <= GET_OLDEST_SAMPLE_INSTANCE; - else - -- DONE - stage_next <= IDLE; end if; end case; when GET_OLDEST_SAMPLE_INSTANCE => - -- Memory Operation Guard - if (inst_op_done = '1') then - cnt_next <= cnt + 1; - - case (cnt) is - -- Preload - when 0 => - sample_ren <= '1'; - when 1 => - -- NOTE: We have to initiate an instance "search" despite having direct access to the instance - -- in order to set up the 'previous' instance pointer required by the removal procedure - -- (Since we do not store previous pointers in the memory frame format) - inst_op_start <= '1'; - inst_opcode <= SEARCH_INSTANCE_ADDR; - inst_data_variant <= VAR_1; - inst_addr_update <= sample_read_data; + + case (cnt) is + -- GET Instance Pointer (Oldest Sample) + when 0 => + sample_valid_in <= '1'; + sample_addr <= oldest_sample + SMF_INSTANCE_ADDR_OFFSET; + sample_read <= '1'; + + -- Memory Flow Control Guard + if (sample_ready_in = '1') then + cnt_next <= cnt + 1; + end if; + -- READ Instance Pointer (Oldest Sample) + when 1 => + -- Memory Operation Guard + if (inst_op_done = '1') then + sample_ready_out <= '1'; - 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; + -- Memory Flow Control Guard + if (sample_valid_out = '1') then + -- NOTE: We have to initiate an instance "search" despite having direct access to the instance + -- in order to set up the 'previous' instance pointer required by the removal procedure + -- (Since we do not store previous pointers in the memory frame format) + inst_op_start <= '1'; + inst_opcode <= SEARCH_INSTANCE_ADDR; + inst_mem_fields <= IMF_SAMPLE_CNT_FLAG or IMF_WRITER_BITMAP_FLAG; + inst_addr_update <= sample_read_data; + + cur_sample_next <= oldest_sample; + stage_next <= REMOVE_SAMPLE; + end if; + end if; + when others => + null; + end case; when FIND_OLDEST_INST_SAMPLE => - -- Precondition: cur_sample set, sample_addr (Instance Address of cur_sample) + -- Precondition: cur_sample set cnt_next <= cnt + 1; case (cnt) is - -- Preload + -- GET Instance Pointer when 0 => - sample_ren <= '1'; - sample_addr_next <= cur_sample + SMF_NEXT_ADDR_OFFSET; - -- Instance Address - when 1 => - sample_ren <= '1'; - -- Oldest Instance Sample Found - if (sample_read_data = cur_inst) then - stage_next <= REMOVE_SAMPLE; - sample_addr_next <= cur_sample + SMF_PREV_ADDR_OFFSET; + sample_ready_in <= '1'; + sample_addr <= cur_sample + SMF_INSTANCE_ADDR_OFFSET; + sample_read <= '1'; + + -- Memory Flow Control Guard + if (sample_ready_in = '1') then + cnt_next <= cnt + 1; end if; - -- Next Address + -- GET Next Sample + when 1 => + sample_ready_in <= '1'; + sample_addr <= cur_sample + SMF_NEXT_ADDR_OFFSET; + sample_read <= '1'; + + -- Memory Flow Control Guard + if (sample_ready_in = '1') then + cnt_next <= cnt + 1; + end if; + -- READ Instance Pointer + when 1 => + sample_ready_out <= '1'; + + -- Memory Flow Control Guard + if (sample_valid_out = '1') then + -- Oldest Instance Sample Found + if (sample_read_data = cur_inst) then + stage_next <= REMOVE_SAMPLE; + sample_abort_read <= '1'; + else + cnt_next <= cnt + 1; + end if; + end if; + -- READ Next Sample when 2 => - cur_sample_next <= sample_read_data; - sample_addr_next <= sample_read_data + SMF_INSTANCE_ADDR_OFFSET; - cnt_next <= 0; + sample_ready_out <= '1'; + + -- Memory Flow Control Guard + if (sample_valid_out = '1') then + cur_sample_next <= sample_read_data; + cnt_next <= 0; + end if; when others => null; end case; @@ -1432,138 +1648,194 @@ begin -- Wait for Instance Search to finish if (inst_op_done = '1') then - cnt_next <= cnt + 1; case (cnt) is - -- Preload + -- GET Previous Sample when 0 => - sample_ren <= '1'; - sample_addr_next <= cur_sample + 1; -- Next Addr - -- Previous Pointer (Current Sample) - when 1 => - sample_ren <= '1'; - prev_sample_next <= sample_read_data; - -- Next Pointer (Current Sample) - when 2 => - next_sample_next <= sample_read_data; + sample_valid_in <= '1'; + sample_addr <= cur_sample + SMF_PREV_ADDR_OFFSET; + sample_read <= '1'; - -- 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; + -- Memory Flow Control Guard + if (sample_ready_in = '1') then + cnt_next <= cnt + 1; end if; - -- Previous Address (Next Sample) - when 3 => - -- Remove link to cur_sample - sample_write_data <= prev_sample; - sample_wen <= '1'; + -- GET Next Sample + when 1 => + sample_valid_in <= '1'; + sample_addr <= cur_sample + SMF_NEXT_ADDR_OFFSET; + sample_read <= '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; + -- Memory Flow Control Guard + if (sample_ready_in = '1') then + cnt_next <= cnt + 1; + end if; + -- GET Payload Pointer + when 2 => + sample_valid_in <= '1'; + sample_addr <= cur_sample + SMF_PAYLOAD_ADDR_OFFSET; + sample_read <= '1'; + + -- Memory Flow Control Guard + if (sample_ready_in = '1') then + cnt_next <= cnt + 1; + end if; + -- READ Previous Sample + when 3 => + sample_ready_out <= '1'; + -- Memory Flow Control Guard + if (sample_valid_out = '1') then + prev_sample_next <= sample_read_data; + cnt_next <= cnt + 1; + end if; + -- READ Next Sample + when 4 => + sample_ready_out <= '1'; + -- Memory Flow Control Guard + if (sample_valid_out = '1') then + next_sample_next <= sample_read_data; -- 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; + cnt_next <= cnt + 2; --Skip Next Step else - -- Skip to Empty List Handling - cnt_next <= 5; - sample_addr_next <= empty_sample_list_tail + SMF_NEXT_ADDR_OFFSET; + cnt_next <= cnt + 1; + end if; + end if; + -- Next Pointer (Empty List Tail) + when 5 => + -- Add Current Sample after Empty List Tail + sample_valid_in <= '1'; + sample_addr <= empty_sample_list_tail + SMF_NEXT_ADDR_OFFSET; + sample_write_data <= cur_sample; + + -- Memory Flow Control Guard + if (sample_ready_in = '1') then + cnt_next <= cnt + 1; + end if; + -- Next Pointer (Current Sample) + when 6 => + -- Make Current Sample Empty List Tail + sample_valid_in <= '1'; + sample_addr <= cur_sample + SMF_NEXT_ADDR_OFFSET; + sample_write_data <= INSTANCE_MEMORY_MAX_ADDRESS; + + -- Memory Flow Control Guard + if (sample_ready_in = '1') then + -- Fix Empty List Pointers + empty_sample_list_tail_next <= cur_sample; + + -- Current Sample is Newest (Occupied List Tail) + if (next_sample = 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) + + cnt_next <= cnt + 3; -- Skip next 2 steps + else + cnt_next <= cnt + 2; -- Skip next step + end if; + else + cnt_next <= cnt + 1; + end if; + end if; + -- Previous Address (Next Sample) + when 7 => + -- Remove link to cur_sample + sample_valid_in <= '1'; + sample_addr <= next_sample + SMF_PREV_ADDR_OFFSET; + sample_write_data <= prev_sample; + + -- Memory Flow Control Guard + if (sample_ready_in = '1') then + -- 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; + + cnt_next <= cnt + 2; -- Skip next step + else + cnt_next <= cnt + 1; 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 + -- Remove link to cur_sample + sample_valid_in <= '1'; + sample_addr <= prev_sample + SMF_NEXT_ADDR_OFFSET; + sample_write_data <= next_sample; + + -- Memory Flow Control Guard + if (sample_ready_in = '1') then + cnt_next <= cnt + 1; + end if; + -- READ Payload Pointer 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'; - + sample_ready_out <= '1'; + + -- Memory Flow Control Guard + if (sample_valid_out = '1') then + 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 + empty_payload_list_head_next <= sample_read_data; + + stage_next <= POST_SAMPLE_REMOVE; + else + empty_payload_list_head_next <= sample_read_data; + cnt_next <= cnt + 1; + end if; + end if; + -- GET Next Payload + when 10 => + payload_valid_in <= '1'; + payload_addr <= cur_payload + PMF_NEXT_ADDR_OFFSET; + payload_read <= '1'; + + -- Memory Flow Control Guard + if (payload_ready_in = '1') then + cnt_next <= cnt + 1; + end if; + -- READ Next Payload + when 11 => + payload_ready_out <= '1'; + + -- Memory Flow Control Guard + if (payload_valid_out = '1') then + -- Found Empty List Tail + if (payload_read_data = MAX_PAYLOAD_ADDRESS) then + cnt_next <= cnt + 1; + else + cur_payload_next <= payload_read_data; + cnt_next <= cnt - 1; + end if; + end if; + -- Next Payload Pointer (Last Payload of Current Sample) + when 12 => + payload_valid_in <= '1'; + payload_addr <= cur_payload + PMF_NEXT_ADDR_OFFSET; + payload_write_data <= empty_payload_list_head; + + -- Memory Flow Control Guard + if (payload_ready_in = '1') then stage_next <= POST_SAMPLE_REMOVE; - else - payload_addr_next <= payload_read_data + PMF_NEXT_ADDR_OFFSET; - cnt_next <= 8; end if; when others => null; @@ -1573,24 +1845,25 @@ begin -- Memory Operation Guard if (inst_op_done = '1') then -- No Instance Change on remove_oldest_inst_sample - if (remove_oldest_inst_sample = '0') then + if (remove_oldest_inst_sample /= '1') then tmp_bitmap := to_endpoint_bitmap(inst_data.writer_bitmap); -- Instance obsolete and Instance Memory Full if (inst_data.sample_cnt = 1 and tmp_bitmap = (tmp_bitmap'range => '0') and inst_empty_head = INSTANCE_MEMORY_MAX_ADDRESS) then inst_op_start <= '1'; inst_opcode <= REMOVE_INSTANCE; else - inst_op_start <= '1'; - inst_opcode <= UPDATE_INSTANCE; - update_inst_flags <= SAMPLE_CNT_FLAG; - sample_cnt <= inst_data.sample_cnt - 1; + inst_op_start <= '1'; + inst_opcode <= UPDATE_INSTANCE; + inst_mem_fields <= IMF_SAMPLE_CNT_FLAG; + sample_cnt <= inst_data.sample_cnt - 1; end if; end if; if (is_take = '1') then -- Continue Processing - stage_next <= GET_NEXT_SAMPLE; - cnt_next <= 0; + cur_sample_next <= second_sample; + stage_next <= GET_NEXT_SAMPLE; + cnt_next <= 0; elsif (is_lifespan_check = '1') then -- Reached End of Samples if (next_sample = SAMPLE_MEMORY_MAX_ADDRESS) then @@ -1599,7 +1872,6 @@ begin else -- Continue Search cur_sample_next <= next_sample; - sample_addr_next <= next_sample + SMF_NEXT_ADDR_OFFSET; stage_next <= CHECK_LIFESPAN; cnt_next <= 0; end if; @@ -1672,13 +1944,13 @@ begin status_info_update(NOT_ALIVE_DISPOSED_FLAG) <= '0'; status_info_update(NOT_ALIVE_NO_WRITERS_FLAG) <= '1'; status_info_update(LIVELINESS_FLAG) <= '1'; - inst_op_start <= '1'; - inst_opcode <= UPDATE_INSTANCE; - update_inst_flags <= STATUS_FLAG or WRITER_BITMAP_FLAG; + inst_op_start <= '1'; + inst_opcode <= UPDATE_INSTANCE; + inst_mem_fields <= IMF_STATUS_FLAG or IMF_WRITER_BITMAP_FLAG; else - inst_op_start <= '1'; - inst_opcode <= UPDATE_INSTANCE; - update_inst_flags <= WRITER_BITMAP_FLAG; + inst_op_start <= '1'; + inst_opcode <= UPDATE_INSTANCE; + inst_mem_fields <= IMF_WRITER_BITMAP_FLAG; end if; stage_next <= GET_NEXT_INSTANCE; @@ -1687,10 +1959,10 @@ begin when GET_NEXT_INSTANCE => -- Wait for Operation to Complete if (inst_op_done = '1') then - inst_op_start <= '1'; - inst_opcode <= GET_NEXT_INSTANCE; - inst_data_variant <= VAR_1; - stage_next <= REMOVE_WRITER; + inst_op_start <= '1'; + inst_opcode <= GET_NEXT_INSTANCE; + inst_mem_fields <= IMF_STATUS_FLAG or IMF_WRITER_BITMAP_FLAG; + stage_next <= REMOVE_WRITER; end if; when REMOVE_STALE_INSTANCE => -- Wait for Instance Data @@ -1699,7 +1971,6 @@ begin if (inst_addr_base = INSTANCE_MEMORY_MAX_ADDRESS) then if (remove_oldest_inst_sample = '1') then cur_sample <= oldest_sample; - sample_addr_next <= oldest_sample + SMF_INSTANCE_ADDR_OFFSET; stage_next <= FIND_OLDEST_INST_SAMPLE; else -- DONE @@ -1717,7 +1988,6 @@ begin if (remove_oldest_inst_sample = '1') then cur_sample <= oldest_sample; - sample_addr_next <= oldest_sample + SMF_INSTANCE_ADDR_OFFSET; stage_next <= FIND_OLDEST_INST_SAMPLE; else -- DONE @@ -1725,113 +1995,155 @@ begin end if; else -- Continue Search - inst_op_start <= '1'; - inst_opcode <= GET_NEXT_INSTANCE; - inst_data_variant <= VAR_1; + inst_op_start <= '1'; + inst_opcode <= GET_NEXT_INSTANCE; + inst_mem_fields <= IMF_SAMPLE_CNT_FLAG or IMF_WRITER_BITMAP_FLAG; end if; end if; end if; when GET_NEXT_SAMPLE => - -- Precondition: cur_sample set, sample_addr (Status Info of cur_sample), cur_inst set, si_sample_rank_sig set - - cnt_next <= cnt + 1; + -- Precondition: cur_sample set, cur_inst set, si_sample_rank_sig set case (cnt) is - -- Preload + -- GET Next Sample when 0 => - sample_addr_next <= cur_sample + SMF_INSTANCE_ADDR_OFFSET; - sample_ren <= '1'; - -- Status Info - when 1 => - sample_addr_next <= cur_sample + SMF_TIMESTAMP_OFFSET; - sample_ren <= '1'; + sample_valid_in <= '1'; + sample_addr <= cur_sample + SMF_NEXT_ADDR_OFFSET; + sample_read <= '1'; - -- Latch Sample Status Info - sample_status_info_next <= sample_read_data; - - -- Check Sample State - case (sample_state) is - when READ_SAMPLE_STATE => - if (sample_read_data(READ_FLAG) /= '1') then - -- Sample not in collection, Skip Sample - sample_addr_next <= cur_sample + SMF_NEXT_ADDR_OFFSET; - cnt_next <= 13; - end if; - when NOT_READ_SAMPLE_STATE => - if (sample_read_data(READ_FLAG) /= '0') then - -- Sample not in collection, Skip Sample - sample_addr_next <= cur_sample + SMF_NEXT_ADDR_OFFSET; - cnt_next <= 13; - end if; - when ANY_SAMPLE_STATE => - null; - -- Uknown Sample State - when others => - -- Sample not in collection, Skip Sample - sample_addr_next <= cur_sample + SMF_NEXT_ADDR_OFFSET; - cnt_next <= 13; - end case; - - if (sample_read_data(READ_FLAG) = '1') then - si_sample_state_sig_next <= READ_SAMPLE_STATE; - else - si_sample_state_sig_next <= NOT_READ_SAMPLE_STATE; + -- Memory Control Flow Guard + if (sample_ready_in = '1') then + cnt_next <= cnt + 1; end if; - -- Instance Pointer + -- GET Status Info + when 1 => + sample_valid_in <= '1'; + sample_addr <= cur_sample + SMF_STATUS_INFO_OFFSET; + sample_read <= '1'; + + -- Memory Control Flow Guard + if (sample_ready_in = '1') then + cnt_next <= cnt + 1; + end if; + -- GET Instance Pointer when 2 => - -- Instance pre-selected - if (cur_inst /= INSTANCE_MEMORY_MAX_ADDRESS) then - -- Sample has different Instance - if (cur_inst /= sample_read_data) then - -- Consecutive Instance Sample Order - if (not ORDERED_ACCESS or PRESENTATION_QOS = INSTANCE_PRESENTATION_QOS) then - -- Skip Sample - sample_addr_next <= cur_sample + SMF_NEXT_ADDR_OFFSET; - cnt_next <= 13; + sample_valid_in <= '1'; + sample_addr <= cur_sample + SMF_INSTANCE_ADDR_OFFSET; + sample_read <= '1'; + + -- Memory Control Flow Guard + if (sample_ready_in = '1') then + cnt_next <= cnt + 1; + end if; + -- READ Next Sample + sample_ready_out <= '1'; + + -- Memory Control Flow Guard + if (sample_valid_out = '1') then + next_sample_next <= sample_read_data; + cnt_next <= cnt + 1; + end if; + -- READ Status Info + when 3 => + sample_ready_out <= '1'; + + -- Memory Control Flow Guard + if (sample_valid_out = '1') then + -- DEFAULT + cnt_next <= cnt + 1; + + -- Latch Sample Status Info + sample_status_info_next <= sample_read_data; + + -- Check Sample State + case (sample_state) is + when READ_SAMPLE_STATE => + if (sample_read_data(READ_FLAG) /= '1') then + -- Sample not in collection, Skip Sample + cnt_next <= 17; + sample_abort_read <= '1'; + end if; + when NOT_READ_SAMPLE_STATE => + if (sample_read_data(READ_FLAG) /= '0') then + -- Sample not in collection, Skip Sample + cnt_next <= 17; + sample_abort_read <= '1'; + end if; + when ANY_SAMPLE_STATE => + null; + -- Uknown Sample State + when others => + -- Sample not in collection, Skip Sample + cnt_next <= 17; + sample_abort_read <= '1'; + end case; + + if (sample_read_data(READ_FLAG) = '1') then + si_sample_state_sig_next <= READ_SAMPLE_STATE; + else + si_sample_state_sig_next <= NOT_READ_SAMPLE_STATE; + end if; + end if; + -- READ Instance Pointer + when 4 => + sample_ready_out <= '1'; + + -- Memory Control Flow Guard + if (sample_valid_out = '1') then + -- Instance pre-selected + if (cur_inst /= INSTANCE_MEMORY_MAX_ADDRESS) then + -- Sample has different Instance + if (cur_inst /= sample_read_data) then + -- Consecutive Instance Sample Order + if (not ORDERED_ACCESS or PRESENTATION_QOS = INSTANCE_PRESENTATION_QOS) then + -- Skip Sample + cnt_next <= 17; + sample_abort_read <= '1'; + else + -- Get Instance Data + next_inst_next <= sample_read_data; + cnt_next <= cnt + 1; + end if; else - -- Get Instance Data - next_inst_next <= sample_read_data; + -- Select Sample + collection_cnt_next <= collection_cnt + 1; + first_sample_next <= cur_sample; + -- Latch Next Sample (For resume purposes) + second_sample_next <= next_sample; + + -- First Instance Sample + -- NOTE: This state only enters with a sample rank of 0 and cur_inst set, when the + -- first sample of the instance has not yet been selected + if (si_sample_rank_sig = 0) then + -- Reset + collection_cnt_max_next <= collection_cnt + 1; + else + si_sample_rank_sig <= si_sample_rank_sig - 1; + end if; + + -- Skip Instance Operation + cnt_next <= cnt + 3; end if; else - -- Select Sample - collection_cnt_next <= collection_cnt + 1; - first_sample_next <= cur_sample; - - -- First Instance Sample - -- NOTE: This state only enters with a sample rank of 0 and cur_inst set, when the - -- first sample of the instance has not yet been selected - if (si_sample_rank_sig = 0) then - -- Reset - collection_cnt_max_next <= collection_cnt + 1; - else - si_sample_rank_sig <= si_sample_rank_sig - 1; - end if; - - sample_addr_next <= sample_addr + 1; -- Timestamp 2/2 - sample_ren <= '1'; - cnt_next <= 5; -- Skip Instance Operation + -- Get Instance Data + next_inst_next <= sample_read_data; + cnt_next <= cnt + 1; end if; - else - -- Get Instance Data - next_inst_next <= sample_read_data; end if; - -- Get Instance - when 3 => + -- Get Instance Data + when 5 => -- Memory Operation Guard if (inst_op_done = '1') then inst_op_start <= '1'; inst_opcode <= GET_INSTANCE; - inst_data_variant <= VAR_2; + inst_mem_fields <= IMF_KEY_HASH_FLAG or IMF_STATUS_FLAG or IMF_DISPOSED_CNT_FLAG or IMF_NO_WRITERS_CNT_FLAG; inst_addr_update <= next_inst; - else - cnt_next <= cnt; -- Keep sub-state + cnt_next <= cnt + 1; end if; -- Check Instance Data - when 4 => + when 6 => -- Wait for Instance Data if (inst_op_done = '1') then - sample_addr_next <= sample_addr + 1; -- Timestamp 2/2 - sample_ren <= '1'; -- DEFAULT tmp_bool := TRUE; @@ -1889,60 +2201,136 @@ begin si_sample_rank_sig <= (others => '0'); cur_inst_next <= next_inst; first_sample_next <= cur_sample; + -- Latch Next Sample (For resume purposes) + second_sample_next <= next_sample; + cnt_next <= cnt + 1; else -- Skip Sample - sample_addr_next <= cur_sample + SMF_NEXT_ADDR_OFFSET; - cnt_next <= 13; + cnt_next <= 17; + sample_abort_read <= '1'; end if; - else - cnt_next <= cnt; -- Keep sub-state end if; - -- Timestamp 1/2 - when 5 => - sample_addr_next <= cur_sample + SMF_PAYLOAD_ADDR_OFFSET; - sample_ren <= '1'; + -- GET Timestamp 1/2 + when 7 => + sample_valid_in <= '1'; + sample_addr <= cur_sample + SMF_TIMESTAMP_OFFSET; + sample_read <= '1'; - si_source_timestamp_sig_next(0) <= sample_read_data; - -- Timestamp 2/2 - when 6 => - sample_addr_next <= cur_sample + SMF_DISPOSED_GEN_CNT_OFFSET; - sample_ren <= '1'; + -- Memory Control Flow Guard + if (sample_ready_in = '1') then + cnt_next <= cnt + 1; + end if; + -- GET Timestamp 2/2 + when 8 => + sample_valid_in <= '1'; + sample_addr <= cur_sample + SMF_TIMESTAMP_OFFSET + 1; + sample_read <= '1'; - si_source_timestamp_sig_next(1) <= sample_read_data; - -- Payload Pointer + -- Memory Control Flow Guard + if (sample_ready_in = '1') then + cnt_next <= cnt + 1; + end if; + -- GET Payload Pointer + when 9 => + sample_valid_in <= '1'; + sample_addr <= cur_sample + SMF_PAYLOAD_ADDR_OFFSET; + sample_read <= '1'; + + -- Memory Control Flow Guard + if (sample_ready_in = '1') then + cnt_next <= cnt + 1; + end if; + -- GET Disposed Generation Count when 10 => - sample_addr_next <= cur_sample + SMF_NO_WRITERS_GEN_CNT_OFFSET; - sample_ren <= '1'; + sample_valid_in <= '1'; + sample_addr <= cur_sample + SMF_DISPOSED_GEN_CNT_OFFSET; + sample_read <= '1'; - -- Latch Payload Address - cur_payload_next <= sample_read_data; - -- Disposed Generation Count + -- Memory Control Flow Guard + if (sample_ready_in = '1') then + cnt_next <= cnt + 1; + end if; + -- GET No Writers Generation Count when 11 => - sample_addr_next <= cur_sample + SMF_NEXT_ADDR_OFFSET; - sample_ren <= '1'; + sample_valid_in <= '1'; + sample_addr <= cur_sample + SMF_STATUS_INFO_OFFSET; + sample_read <= '1'; - si_disposed_generation_count_sig_next <= sample_read_data; - -- No Writers Generation Count + -- Memory Control Flow Guard + if (sample_ready_in = '1') then + cnt_next <= cnt + 1; + end if; + -- READ Timestamp 1/2 when 12 => - sample_ren <= '1'; + sample_ready_out <= '1'; - si_no_writers_generation_count_sig_next <= sample_read_data; - cur_generation_rank_next <= si_disposed_generation_count_sig + sample_read_data; - -- Calculate highest collection generation rank - collection_generation_rank_next <= si_disposed_generation_count_sig + sample_read_data; - - cnt_next <= 14; -- Skip Preload - -- Preload + -- Memory Control Flow Guard + if (sample_valid_out = '1') then + si_source_timestamp_sig_next(0) <= sample_read_data; + cnt_next <= cnt + 1; + end if; + -- READ Timestamp 2/2 when 13 => - sample_ren <= '1'; - -- Next Pointer + sample_ready_out <= '1'; + + -- Memory Control Flow Guard + if (sample_valid_out = '1') then + si_source_timestamp_sig_next(1) <= sample_read_data; + cnt_next <= cnt + 1; + end if; + -- READ Payload Pointer when 14 => + sample_ready_out <= '1'; + + -- Memory Control Flow Guard + if (sample_valid_out = '1') then + -- Latch Payload Address + cur_payload_next <= sample_read_data; + cnt_next <= cnt + 1; + end if; + -- READ Disposed Generation Count + when 15 => + sample_ready_out <= '1'; + + -- Memory Control Flow Guard + if (sample_valid_out = '1') then + si_disposed_generation_count_sig_next <= sample_read_data; + cnt_next <= cnt + 1; + end if; + -- READ No Writers Generation Count + when 16 => + sample_ready_out <= '1'; + + -- Memory Control Flow Guard + if (sample_valid_out = '1') then + si_no_writers_generation_count_sig_next <= sample_read_data; + cur_generation_rank_next <= si_disposed_generation_count_sig + sample_read_data; + -- Calculate highest collection generation rank + collection_generation_rank_next <= si_disposed_generation_count_sig + sample_read_data; + cnt_next <= cnt + 1; + end if; + -- Exit State + when 17 => -- Reached End of Samples - if (sample_read_data = SAMPLE_MEMORY_MAX_ADDRESS) then + if (next_sample = SAMPLE_MEMORY_MAX_ADDRESS) then -- Exit Condition (Sample Selected) if (first_sample = cur_sample) then - stage_next <= FINALIZE_SAMPLE_INFO; - cnt_next <= 0; + -- Sample not marked as Read + if (sample_status_info(READ_FLAG) /= '1') then + -- Mark Sample as Read + sample_valid_in <= '1'; + sample_addr <= cur_sample + SMF_STATUS_INFO_OFFSET; + sample_write_data <= sample_status_info; + sample_write_data(READ_FLAG) <= '1'; + -- Memory Control Flow Guard + if (sample_ready_in = '1') then + stage_next <= FINALIZE_SAMPLE_INFO; + cnt_next <= 0; + end if; + else + stage_next <= FINALIZE_SAMPLE_INFO; + cnt_next <= 0; + end if; else -- Collection Empty if (collection_cnt = 0) then @@ -1964,22 +2352,38 @@ begin end if; end if; else - -- Next Sample - cur_sample_next <= sample_read_data; - sample_addr_next <= sample_read_data + SMF_STATUS_INFO_OFFSET; + cur_sample_next <= next_sample; cnt_next <= 0; -- Exit Condition (Sample Selected) if (first_sample = cur_sample) then - -- Pre-Calculation already done for selected Instance - if (si_sample_rank_sig /= 0) then - stage_next <= FINALIZE_SAMPLE_INFO; - cnt_next <= 0; + -- Sample not marked as Read + if (sample_status_info(READ_FLAG) /= '1') then + -- Mark Sample as Read + sample_valid_in <= '1'; + sample_addr <= cur_sample + SMF_STATUS_INFO_OFFSET; + sample_write_data <= sample_status_info; + sample_write_data(READ_FLAG) <= '1'; + -- Memory Control Flow Guard + if (sample_ready_in = '1') then + -- Pre-Calculation already done for selected Instance (Or not necessary) + if (si_sample_rank_sig /= 0 or collection_cnt_max = max_samples) then + stage_next <= FINALIZE_SAMPLE_INFO; + cnt_next <= 0; + else + -- Calculate Instance Sample Ranks + stage_next <= PRE_CALCULATE; + end if; + end if; else - -- Latch Next Sample (For resume purposes) - next_sample_next <= sample_read_data; - -- Calculate Instance Sample Ranks - stage_next <= PRE_CALCULATE; + -- Pre-Calculation already done for selected Instance (Or not necessary) + if (si_sample_rank_sig /= 0 or collection_cnt_max = max_samples) then + stage_next <= FINALIZE_SAMPLE_INFO; + cnt_next <= 0; + else + -- Calculate Instance Sample Ranks + stage_next <= PRE_CALCULATE; + end if; end if; end if; end if; @@ -1987,98 +2391,161 @@ begin null; end case; when PRE_CALCULATE => - -- Precondition: cur_sample set, sample_addr_next (Status Info of cur_sample) + -- Precondition: cur_sample set, cur_inst set cnt_next <= cnt + 1; case (cnt) is - -- Preload + -- GET Next Sample when 0 => - sample_addr_next <= cur_sample + SMF_INSTANCE_ADDR_OFFSET; - sample_ren <= '1'; + sample_valid_in <= '1'; + sample_addr <= cur_sample + SMF_NEXT_ADDR_OFFSET; + sample_read <= '1'; - -- Exit Condition (Reached Collection Limit) - if (collection_cnt_max = max_samples) then - stage_next <= FINALIZE_SAMPLE_INFO; - cnt_next <= 0; + -- Memory Control Flow Guard + if (sample_ready_in = '1') then + cnt_next <= cnt + 1; end if; - -- Status Info + -- GET Status Info when 1 => - sample_addr_next <= cur_sample + SMF_DISPOSED_GEN_CNT_OFFSET; - sample_ren <= '1'; + sample_valid_in <= '1'; + sample_addr <= cur_sample + SMF_STATUS_INFO_OFFSET; + sample_read <= '1'; - -- Check Sample State - case (sample_state) is - when READ_SAMPLE_STATE => - if (sample_read_data(READ_FLAG) /= '1') then - -- Skip Sample - sample_addr_next <= cur_sample + SMF_NEXT_ADDR_OFFSET; - cnt_next <= 7; - end if; - when NOT_READ_SAMPLE_STATE => - if (sample_read_data(READ_FLAG) /= '0') then - -- Skip Sample - sample_addr_next <= cur_sample + SMF_NEXT_ADDR_OFFSET; - cnt_next <= 7; - end if; - when ANY_SAMPLE_STATE => - null; - -- Uknown Sample State - when others => - -- Skip Sample - sample_addr_next <= cur_sample + SMF_NEXT_ADDR_OFFSET; - cnt_next <= 7; - end case; - -- Instance Pointer + -- Memory Control Flow Guard + if (sample_ready_in = '1') then + cnt_next <= cnt + 1; + end if; + -- GET Instance Pointer when 2 => - sample_addr_next <= cur_sample + SMF_NO_WRITERS_GEN_CNT_OFFSET; - sample_ren <= '1'; + sample_valid_in <= '1'; + sample_addr <= cur_sample + SMF_INSTANCE_ADDR_OFFSET; + sample_read <= '1'; - -- Same Instance - if (sample_read_data = cur_inst) then - -- Count Sample (No need to check Instance) - collection_cnt_max_next <= collection_cnt_max + 1; - si_sample_rank_sig_next <= si_sample_rank_sig + 1; - else - -- Consecutive Instance Sample Order - if (not ORDERED_ACCESS or PRESENTATION_QOS = INSTANCE_PRESENTATION_QOS or single_instance = '1') then - -- Skip Sample - sample_addr_next <= cur_sample + SMF_NEXT_ADDR_OFFSET; - cnt_next <= 7; + -- Memory Control Flow Guard + if (sample_ready_in = '1') then + cnt_next <= cnt + 1; + end if; + -- GET Disposed Generation Count + when 3 => + sample_valid_in <= '1'; + sample_addr <= cur_sample + SMF_DISPOSED_GEN_CNT_OFFSET; + sample_read <= '1'; + + -- Memory Control Flow Guard + if (sample_ready_in = '1') then + cnt_next <= cnt + 1; + end if; + -- GET No Writers Generation Count + when 4 => + sample_valid_in <= '1'; + sample_addr <= cur_sample + SMF_NO_WRITERS_GEN_CNT_OFFSET; + sample_read <= '1'; + + -- Memory Control Flow Guard + if (sample_ready_in = '1') then + cnt_next <= cnt + 1; + end if; + -- READ Next Sample + when 5 => + sample_ready_out <= '1'; + + -- Memory Control Flow Guard + if (sample_valid_out = '1') then + next_sample_next <= sample_read_data; + cnt_next <= cnt + 1; + end if; + -- READ Status Info + when 6 => + sample_ready_out <= '1'; + + -- Memory Control Flow Guard + if (sample_valid_out = '1') then + -- DEFAULT + cnt_next <= cnt + 1; + + -- Check Sample State + case (sample_state) is + when READ_SAMPLE_STATE => + if (sample_read_data(READ_FLAG) /= '1') then + -- Skip Sample + cnt_next <= 12; + sample_abort_read <= '1'; + end if; + when NOT_READ_SAMPLE_STATE => + if (sample_read_data(READ_FLAG) /= '0') then + -- Skip Sample + cnt_next <= 12; + sample_abort_read <= '1'; + end if; + when ANY_SAMPLE_STATE => + null; + -- Uknown Sample State + when others => + -- Skip Sample + cnt_next <= 12; + sample_abort_read <= '1'; + end case; + end if; + -- READ Instance Pointer + when 7 => + sample_ready_out <= '1'; + + -- Memory Control Flow Guard + if (sample_valid_out = '1') then + -- Same Instance + if (sample_read_data = cur_inst) then + -- Count Sample (No need to check Instance) + collection_cnt_max_next <= collection_cnt_max + 1; + si_sample_rank_sig_next <= si_sample_rank_sig + 1; + + cnt_next <= cnt + 1; else - -- Check New Instance - next_inst_next <= sample_read_data; - cnt_next <= 5; + -- Consecutive Instance Sample Order + if (not ORDERED_ACCESS or PRESENTATION_QOS = INSTANCE_PRESENTATION_QOS or single_instance = '1') then + -- Skip Sample + cnt_next <= 12; + sample_abort_read <= '1'; + else + -- Check New Instance + cnt_next <= cnt + 3; + sample_abort_read <= '1'; + end if; end if; end if; - -- Disposed Generation Count - when 3 => - sample_addr_next <= cur_sample + SMF_NEXT_ADDR_OFFSET; - sample_ren <= '1'; + -- READ Disposed Generation Count + when 8 => + sample_ready_out <= '1'; - -- Calculate highest collection generation rank - collection_generation_rank_next <= sample_read_data; - -- No Writers Generation Count - when 4 => - sample_ren <= '1'; + -- Memory Control Flow Guard + if (sample_valid_out = '1') then + -- Calculate highest collection generation rank + collection_generation_rank_next <= sample_read_data; + cnt_next <= cnt + 1; + end if; + -- READ No Writers Generation Count + when 9 => + sample_ready_out <= '1'; - -- Calculate highest collection generation rank - collection_generation_rank_next <= collection_generation_rank + sample_read_data; - - cnt_next <= 8; - -- Initiate Get Memory Operation - when 5 => + -- Memory Control Flow Guard + if (sample_valid_out = '1') then + -- Calculate highest collection generation rank + collection_generation_rank_next <= collection_generation_rank + sample_read_data; + -- Skip Instance Check + cnt_next <= cnt + 3; + end if; + -- Get Instance Data + when 10 => -- Memory Operation Guard if (inst_op_done = '1') then inst_op_start <= '1'; inst_opcode <= GET_INSTANCE_DATA_2; - inst_data_variant <= VAR_2; + inst_mem_fields <= IMF_STATUS_FLAG; inst_addr_update <= next_inst; - else - cnt_next <= cnt; -- Keep State + cnt_next <= cnt + 1; end if; - -- State Check - when 6 => + -- Check Instance Data + when 11 => -- Wait for Instance Data if (inst_op_done = '1') then -- DEFAULT @@ -2135,26 +2602,18 @@ begin -- Count Sample collection_cnt_max_next <= collection_cnt_max + 1; end if; - -- Done - sample_addr_next <= cur_sample + SMF_NEXT_ADDR_OFFSET; - cnt_next <= 7; - else - cnt_next <= cnt; -- Keep sub-state + cnt_next <= cnt + 1; end if; - -- Preload - when 7 => - sample_ren <= '1'; - -- Next Pointer - when 8 => - -- Exit Condition (Reached End of Samples) - if (sample_read_data = SAMPLE_MEMORY_MAX_ADDRESS) then + -- Exit State + when 12 => + -- Exit Condition (Reached End of Samples or Collection Fully Precalculated) + if (next_sample = SAMPLE_MEMORY_MAX_ADDRESS or collection_cnt_max = max_samples) then stage_next <= FINALIZE_SAMPLE_INFO; cnt_next <= 0; else -- Continue with next Sample - cur_sample_next <= sample_read_data; - sample_addr_next <= sample_read_data + SMF_STATUS_INFO_OFFSET; - cnt_next <= 0; + cur_sample_next <= next_sample; + cnt_next <= 0; end if; when others => null; @@ -2162,11 +2621,11 @@ begin when FINALIZE_SAMPLE_INFO => -- Precondition: cur_inst set + -- TODO: Explicitly get the required instance data. + case (cnt) is -- Finalize Sample Info Data when 0 => - sample_addr_next <= first_sample + SMF_STATUS_INFO_OFFSET; - -- Wait for Instance Data if (inst_op_done = '1') then -- Instance Data valid @@ -2210,7 +2669,7 @@ begin -- Get Instance Data inst_op_start <= '1'; inst_opcode <= GET_INSTANCE; - inst_data_variant <= VAR_2; + inst_mem_fields <= IMF_KEY_HASH_FLAG or IMF_STATUS_FLAG or IMF_DISPOSED_CNT_FLAG or IMF_NO_WRITERS_CNT_FLAG; inst_addr_update <= cur_inst; end if; end if; @@ -2230,19 +2689,10 @@ begin -- Reset Data Available Status status_sig_next(DATA_AVAILABLE_STATUS) <= '0'; - -- Sample not marked as Read - if (sample_status_info(READ_FLAG) /= '1') then - -- Mark Sample as Read - sample_write_data <= sample_status_info; - sample_write_data(READ_FLAG) <= '1'; - sample_wen <= '1'; - end if; - -- Sample Data Request if (get_data = '1') then stage_next <= GET_PAYLOAD; cnt_next <= 0; - payload_addr_next <= cur_payload; else cnt_next <= 2; end if; @@ -2257,7 +2707,7 @@ begin if (si_sample_rank_sig = 1) then inst_op_start <= '1'; inst_opcode <= UPDATE_INSTANCE; - update_inst_flags <= STATUS_FLAG; + inst_mem_fields <= IMF_STATUS_FLAG; status_info_update <= inst_data.status_info; -- Consecutive Instance Sample Order of multiple Instances @@ -2288,15 +2738,11 @@ begin if (is_take = '1') then stage_next <= REMOVE_SAMPLE; cur_sample_next <= first_sample; - sample_addr_next <= first_sample + SMF_PREV_ADDR_OFFSET; else -- DONE stage_next <= IDLE; end if; else - cur_sample <= next_sample; - cnt_next <= 0; - -- Reached End of Samples if (next_sample = SAMPLE_MEMORY_MAX_ADDRESS) then -- DONE @@ -2322,10 +2768,11 @@ begin -- Remove Sample stage_next <= REMOVE_SAMPLE; cur_sample_next <= first_sample; - sample_addr_next <= first_sample + SMF_PREV_ADDR_OFFSET; else -- Continue Processing + cur_sample <= second_sample; stage_next <= GET_NEXT_SAMPLE; + cnt_next <= 0; end if; end if; end if; @@ -2333,72 +2780,107 @@ begin null; end case; when GET_PAYLOAD => - -- Precondition: payload_addr (Beginning of cur_payload) + -- Precondition: cur_payload set + + -- DEFAULT + tmp_bool := FALSE; case (cnt) is - -- Preload + -- GET Next Pointer when 0 => - payload_addr_next <= payload_addr + 1; - payload_ren <= '1'; - cnt_next <= cnt + 1; - -- Next Pointer - when 1 => - payload_addr_next <= payload_addr + 1; - payload_ren <= '1'; - cnt_next <= cnt + 1; + payload_valid_in <= '1'; + payload_addr <= cur_payload + PMF_NEXT_ADDR_OFFSET; + payload_read <= '1'; - next_payload_next <= payload_read_data; - -- Payload - when others => - if (ready_out_dds = '1') then - payload_addr_next <= payload_addr + 1; - payload_ren <= '1'; - cnt_next <= cnt + 1; - - valid_out_dds <= '1'; - if (has_latched = '0') then - data_out_dds <= payload_read_data; - else - -- Previously Latched - data_out_dds <= long_latch; - end if; - - -- Reset - has_lacthed_next <= '0'; - - -- End of Payload Frame - if (cnt = PAYLOAD_FRAME_SIZE) then - -- Last Payload Frame + -- Memory Flow Control Guard + if (payload_ready_in = '1') then + cnt_next <= cnt + 1; + end if; + -- READ Next Pointer + when 1 => + payload_ready_out <= '1'; + + -- Memory Flow Control Guard + if (payload_valid_out = '1') then + next_payload_next <= payload_read_data; + cnt_next <= cnt + 1; + cnt2 <= 1; + end if; + -- GET PAYLOAD + when 3 => + payload_valid_in <= '1'; + payload_addr <= cur_payload + cnt2; + payload_read <= '1'; + + -- Memory Flow Control Guard + if (payload_ready_in = '1') then + cnt3_next <= cnt3 + 1; + tmp_bool := TRUE; + -- End of Payload Slot + if (cnt2 = PAYLOAD_FRAME_SIZE-1) then + -- End of Payload if (next_payload = PAYLOAD_MEMORY_MAX_ADDRESS) then - last_word_out_dds <= '1'; - - stage_next <= FINALIZE_SAMPLE_INFO; - cnt_next <= 2; + -- DONE (Wait for Output to finidh reading) + cnt_next <= cnt + 1; else - -- Continue with next payload Slot - payload_addr_next <= next_payload; + -- Next Payload Slot + cur_payload_next <= next_payload; cnt_next <= 0; end if; + else + cnt2_next <= cnt2 + 1; end if; - else - long_latch_next <= payload_read_data; - has_lacthed_next <= '1'; end if; - + when others => + null; end case; + + -- Data available for Output + if (cnt3 /= 0) then + -- Memory Flow Control Guard + if (payload_valid_out = '1') then + valid_out_dds <= '1'; + + -- End of Payload + if (cnt3 = 1 and cnt = 4) then + last_word_out_dds <= '1'; + end if; + + -- DDS Read + if (ready_out_dds = '1') then + payload_ready_out <= '1'; + -- NOTE: We are using the temp Bool variable to denote if there is an increment + -- on the same clock cycle. + -- Increment in same clock cycle + if (tmp_bool) then + cnt3_next <= cnt3; -- Override increment + else + cnt3_next <= cnt3 - 1; + end if; + end if; + end if; + -- Finished Reading + elsif (cnt = 4) then + assert (cnt3 = 0) severity FAILURE; + -- DONE + stage_next <= FINALIZE_SAMPLE_INFO; + cnt_next <= 2; + end if; when FIND_NEXT_INSTANCE => -- Wait for Instance Data if (inst_op_done = '1') then case (cnt) is when 0 => + -- NOTE: The Generation Counters are not used directly in this state, but will be needed by the FINALIZE_SAMPLE_INFO state. inst_op_start <= '1'; inst_opcode <= GET_FIRST_INSTANCE; - inst_data_variant <= VAR_2; + inst_mem_fields <= IMF_KEY_HASH_FLAG or IMF_STATUS_FLAG or IMF_DISPOSED_CNT_FLAG or IMF_NO_WRITERS_CNT_FLAG; cnt_next <= 2; when 1 => + -- NOTE: The Generation Counters are not used directly in this state, but will be needed by the FINALIZE_SAMPLE_INFO state. inst_op_start <= '1'; inst_opcode <= GET_NEXT_INSTANCE; - inst_data_variant <= VAR_2; + inst_mem_fields <= IMF_KEY_HASH_FLAG or IMF_STATUS_FLAG or IMF_DISPOSED_CNT_FLAG or IMF_NO_WRITERS_CNT_FLAG; cnt_next <= 2; when 2 => -- Instance Found @@ -2457,9 +2939,10 @@ begin cur_inst <= inst_addr_base; stage_next <= GET_NEXT_SAMPLE; else + -- NOTE: The Generation Counters are not used directly in this state, but will be needed by the FINALIZE_SAMPLE_INFO state. inst_op_start <= '1'; inst_opcode <= GET_NEXT_INSTANCE; - inst_data_variant <= VAR_2; + inst_mem_fields <= IMF_KEY_HASH_FLAG or IMF_STATUS_FLAG or IMF_DISPOSED_CNT_FLAG or IMF_NO_WRITERS_CNT_FLAG; end if; else -- DONE @@ -2476,9 +2959,10 @@ begin if (inst_op_done = '1') then case (cnt) is when 0 => + -- NOTE: The Generation Counters are not used directly in this state, but will be needed by the FINALIZE_SAMPLE_INFO state. inst_op_start <= '1'; inst_opcode <= SEARCH_INSTANCE_HASH; - inst_data_variant <= VAR_2; + inst_mem_fields <= IMF_KEY_HASH_FLAG or IMF_STATUS_FLAG or IMF_DISPOSED_CNT_FLAG or IMF_NO_WRITERS_CNT_FLAG; cnt_next <= 1; when 1 => -- Instance Found @@ -2549,45 +3033,80 @@ begin end case; end if; when CHECK_LIFESPAN => - -- Precondition: cur_sample set, sample_addr (Next Pointer of cur_sample) + -- Precondition: cur_sample set, case (cnt) is - -- Preload + -- GET Next Sample when 0 => - sample_addr_next <= cur_sample + SMF_LIFESPAN_DEADLINE_OFFSET; - sample_ren <= '1'; - -- Next Pointer + sample_valid_in <= '1'; + sample_addr <= cur_sample + SMF_NEXT_ADDR_OFFSET; + sample_read <= '1'; + + -- Memory Control Flow Guard + if (sample_ready_in = '1') then + cnt_next <= cnt + 1; + end if; + -- GET Lifespan 1/2 when 1 => - sample_addr_next <= sample_addr + 1; -- Lifespan 2/2 - sample_ren <= '1'; + sample_valid_in <= '1'; + sample_addr <= cur_sample + SMF_LIFESPAN_DEADLINE_OFFSET; + sample_read <= '1'; - -- Latch Next Sample - next_sample_next <= sample_read_data; - -- Lifespan 1/2 + -- Memory Control Flow Guard + if (sample_ready_in = '1') then + cnt_next <= cnt + 1; + end if; + -- GET Lifespan 2/2 when 2 => - sample_ren <= '1'; + sample_valid_in <= '1'; + sample_addr <= cur_sample + SMF_LIFESPAN_DEADLINE_OFFSET + 1; + sample_read <= '1'; - long_latch_next <= sample_read_data; - -- Lifespan 2/2 + -- Memory Control Flow Guard + if (sample_ready_in = '1') then + cnt_next <= cnt + 1; + end if; + -- READ Next Sample when 3 => - tmp_dw := (0 => unsigned(long_latch), 1 => unsigned(sample_read_data)); + sample_ready_out <= '1'; - -- Sample Lifespan Expired - if (tmp_dw /= TIME_INVALID and time >= tmp_dw) then - -- Remove Sample - sample_addr_next <= cur_sample + SMF_PREV_ADDR_OFFSET; - stage_next <= REMOVE_SAMPLE; - cnt_next <= 0; - else - -- Reached End of Samples - if (next_sample = SAMPLE_MEMORY_MAX_ADDRESS) then - -- DONE - stage_next <= IDLE; - else - -- Continue Search - cur_sample_next <= next_sample; - sample_addr_next <= next_sample + SMF_NEXT_ADDR_OFFSET; + -- Memory Control Flow Guard + if (sample_valid_out = '1') then + next_sample_next <= sample_read_data; + cnt_next <= cnt + 1; + end if; + -- READ Lifespan 1/2 + when 4 => + sample_ready_out <= '1'; + + -- Memory Control Flow Guard + if (sample_valid_out = '1') then + long_latch_next <= sample_read_data; + cnt_next <= cnt + 1; + end if; + -- READ Lifespan 2/2 + when 3 => + sample_ready_out <= '1'; + + -- Memory Control Flow Guard + if (sample_valid_out = '1') then + tmp_dw := (0 => unsigned(long_latch), 1 => unsigned(sample_read_data)); + + -- Sample Lifespan Expired + if (tmp_dw /= TIME_INVALID and time >= tmp_dw) then + -- Remove Sample + stage_next <= REMOVE_SAMPLE; cnt_next <= 0; + else + -- Reached End of Samples + if (next_sample = SAMPLE_MEMORY_MAX_ADDRESS) then + -- DONE + stage_next <= IDLE; + else + -- Continue Search + cur_sample_next <= next_sample; + cnt_next <= 0; + end if; end if; end if; when others => @@ -2686,13 +3205,13 @@ begin when 0 => inst_op_start <= '1'; inst_opcode <= GET_FIRST_INSTANCE; - inst_data_variant <= VAR_3; + inst_mem_fields <= IMF_KEY_HASH_FLAG or IMF_STATUS_FLAG; cnt_next <= 2; -- Get Next Instance when 1 => inst_op_start <= '1'; inst_opcode <= GET_NEXT_INSTANCE; - inst_data_variant <= VAR_3; + inst_mem_fields <= IMF_KEY_HASH_FLAG or IMF_STATUS_FLAG; cnt_next <= 2; -- Check Instance when 2 => @@ -2706,7 +3225,7 @@ begin -- Reset Liveliness Flag inst_op_start <= '1'; inst_opcode <= UPDATE_INSTANCE; - update_inst_flags <= STATUS_FLAG; + inst_mem_fields <= IMF_STATUS_FLAG; status_info_update <= inst_data.status_info; status_info_update(LIVELINESS_FLAG) <= '0'; cnt_next <= 1; @@ -2734,20 +3253,23 @@ 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_cnt2_next <= inst_cnt2; inst_mem_full_next <= inst_mem_full; inst_data_next <= inst_data; + inst_long_latch_next <= inst_long_latch; -- DEFAULT Unregistered - inst_write_data <= (others => '0'); - inst_op_done <= '0'; - inst_ren <= '0'; - inst_wen <= '0'; + inst_ready_out <= '0'; + inst_valid_in <= '0'; + inst_read <= '0'; + inst_op_done <= '0'; + inst_addr <= (others => '0'); + inst_write_data <= (others => '0'); case (mem_stage) is @@ -2757,14 +3279,13 @@ begin if (inst_op_start = '1') then -- Latch Signals needed for Mermory Operation (Use _next signals, because some signals are set in same clk) inst_latch_data_next <= ( - variant => inst_data_variant, key_hash => key_hash_next, status_info => status_info_update, sample_cnt => sample_cnt, gen_cnt => gen_cnt, deadline => deadline, writer_bitmap => writer_bitmap, - update_flags => update_inst_flags, + field_flags => inst_mem_fields, addr => inst_addr_update ); @@ -2779,7 +3300,6 @@ begin 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; @@ -2793,7 +3313,6 @@ begin 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; @@ -2802,36 +3321,28 @@ begin -- 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; + inst_stage_next <= UPDATE_INSTANCE; + inst_addr_base_next <= inst_addr_update; + if check_mask(inst_mem_fields.field_flag,IMF_STATUS_FLAG) then + inst_cnt_next <= 0; + elsif check_mask(inst_mem_fields.field_flag,IMF_SAMPLE_CNT_FLAG) then + inst_cnt_next <= 1; + elsif check_mask(inst_mem_fields.field_flag,IMF_DISPOSED_CNT_FLAG) then + inst_cnt_next <= 2; + elsif check_mask(inst_mem_fields.field_flag,IMF_NO_WRITERS_CNT_FLAG) then + inst_cnt_next <= 3; + elsif (TIME_BASED_FILTER_QOS /= DURATION_ZERO and check_mask(inst_mem_fields.field_flag,IMF_IGNORE_DEADLINE_FLAG)) then + inst_cnt_next <= 4; + elsif check_mask(inst_mem_fields.field_flag,IMF_WRITER_BITMAP_FLAG) then + inst_cnt_next <= 6; + inst_cnt2_next <= 0; + else + -- DONE + inst_stage_next <= IDLE; end if; when GET_FIRST_INSTANCE => -- No Instances avialable @@ -2840,20 +3351,27 @@ begin else inst_prev_addr_base_next <= INSTANCE_MEMORY_MAX_ADDRESS; inst_addr_base_next <= inst_occupied_head; - case (inst_data_variant) is - when VAR_1 => - inst_addr_next <= inst_occupied_head + IMF_STATUS_INFO_OFFSET; - inst_stage_next <= GET_INSTANCE_DATA_1; - inst_cnt_next <= 0; - when VAR_2 => - inst_addr_next <= inst_occupied_head + IMF_KEY_HASH_OFFSET; - inst_stage_next <= GET_INSTANCE_DATA_2; - inst_cnt_next <= 0; - when VAR_3 => - inst_addr_next <= inst_occupied_head + IMF_KEY_HASH_OFFSET; - inst_stage_next <= GET_INSTANCE_DATA_3; - inst_cnt_next <= 0; - end case; + -- Get Instance Data + inst_stage_next <= GET_INSTANCE_DATA; + if check_mask(inst_mem_fields.field_flag,IMF_KEY_HASH_FLAG) then + inst_cnt_next <= 0; + elsif check_mask(inst_mem_fields.field_flag,IMF_STATUS_FLAG) then + inst_cnt_next <= 4; + elsif check_mask(inst_mem_fields.field_flag,IMF_SAMPLE_CNT_FLAG) then + inst_cnt_next <= 5; + elsif check_mask(inst_mem_fields.field_flag,IMF_DISPOSED_CNT_FLAG) then + inst_cnt_next <= 6; + elsif check_mask(inst_mem_fields.field_flag,IMF_NO_WRITERS_CNT_FLAG) then + inst_cnt_next <= 7; + elsif (TIME_BASED_FILTER_QOS /= DURATION_ZERO and check_mask(inst_mem_fields.field_flag,IMF_IGNORE_DEADLINE_FLAG)) then + inst_cnt_next <= 8; + elsif check_mask(inst_mem_fields.field_flag,IMF_WRITER_BITMAP_FLAG) then + inst_cnt_next <= 10; + inst_cnt2_next <= 0; + else + -- DONE + inst_stage_next <= IDLE; + end if; end if; when GET_NEXT_INSTANCE => -- No Instances avialable @@ -2862,736 +3380,1381 @@ begin else inst_prev_addr_base_next <= inst_addr_base; inst_addr_base_next <= inst_next_addr_base; - inst_addr_next <= inst_next_addr_base; inst_stage_next <= GET_NEXT_INSTANCE; inst_cnt_next <= 0; end if; when REMOVE_INSTANCE => - assert (inst_occupied_head = INSTANCE_MEMORY_MAX_ADDRESS) report "Request Removal on empty memory" severity FAILURE; - - inst_prev_addr_base_next <= INSTANCE_MEMORY_MAX_ADDRESS; - inst_addr_base_next <= inst_occupied_head; - inst_addr_next <= inst_occupied_head; - inst_stage_next <= REMOVE_INSTANCE; - inst_cnt_next <= 0; + inst_stage_next <= REMOVE_INSTANCE; + inst_cnt_next <= 0; when GET_INSTANCE => - inst_addr_base_next <= inst_addr_update; - case (inst_data_variant) is - when VAR_1 => - inst_addr_next <= inst_addr_update + IMF_STATUS_INFO_OFFSET; - inst_stage_next <= GET_INSTANCE_DATA_1; - inst_cnt_next <= 0; - when VAR_2 => - inst_addr_next <= inst_addr_update + IMF_KEY_HASH_OFFSET; - inst_stage_next <= GET_INSTANCE_DATA_2; - inst_cnt_next <= 0; - when VAR_3 => - inst_addr_next <= inst_addr_update + IMF_KEY_HASH_OFFSET; - inst_stage_next <= GET_INSTANCE_DATA_3; - inst_cnt_next <= 0; - end case; + inst_addr_base_next <= inst_addr_update; + -- Get Instance Data + inst_stage_next <= GET_INSTANCE_DATA; + if check_mask(inst_mem_fields.field_flag,IMF_KEY_HASH_FLAG) then + inst_cnt_next <= 0; + elsif check_mask(inst_mem_fields.field_flag,IMF_STATUS_FLAG) then + inst_cnt_next <= 4; + elsif check_mask(inst_mem_fields.field_flag,IMF_SAMPLE_CNT_FLAG) then + inst_cnt_next <= 5; + elsif check_mask(inst_mem_fields.field_flag,IMF_DISPOSED_CNT_FLAG) then + inst_cnt_next <= 6; + elsif check_mask(inst_mem_fields.field_flag,IMF_NO_WRITERS_CNT_FLAG) then + inst_cnt_next <= 7; + elsif (TIME_BASED_FILTER_QOS /= DURATION_ZERO and check_mask(inst_mem_fields.field_flag,IMF_IGNORE_DEADLINE_FLAG)) then + inst_cnt_next <= 8; + elsif check_mask(inst_mem_fields.field_flag,IMF_WRITER_BITMAP_FLAG) then + inst_cnt_next <= 10; + inst_cnt2_next <= 0; + else + -- DONE + inst_stage_next <= IDLE; + end if; when UNMARK_INTANCES => -- Empty Memory Guard if (inst_occupied_head /= INSTANCE_MEMORY_MAX_ADDRESS) then - inst_addr_base_next <= inst_occupied_head; - inst_addr_next <= inst_occupied_head + IMF_NEXT_ADDR_OFFSET; - inst_stage_next <= UNMARK_INTANCES; - inst_cnt_next <= 0; + inst_addr_base_next <= inst_occupied_head; + inst_stage_next <= UNMARK_INTANCES; + inst_cnt_next <= 0; end if; when others => null; end case; end if; when SEARCH_INSTANCE_HASH => - inst_ren <= '1'; - inst_cnt_next <= inst_cnt + 1; - inst_addr_next <= inst_addr + 1; case (inst_cnt) is - -- Preload + -- GET Next Instance when 0 => - null; - -- Next Instance + inst_valid_in <= '1'; + inst_addr <= inst_addr_base + IMF_NEXT_ADDR_OFFSET; + inst_read <= '1'; + + -- Memory Flow Control Guard + if (inst_ready_in = '1') then + inst_cnt_next <= inst_cnt + 1; + end if; + -- GET Key Hash 1/4 when 1 => - inst_next_addr_base_next <= inst_read_data; - -- Key Hash 1/4 + inst_valid_in <= '1'; + inst_addr <= inst_addr_base + IMF_KEY_HASH_OFFSET; + inst_read <= '1'; + + -- Memory Flow Control Guard + if (inst_ready_in = '1') then + inst_cnt_next <= inst_cnt + 1; + end if; + -- GET Key Hash 2/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; + inst_valid_in <= '1'; + inst_addr <= inst_addr_base + IMF_KEY_HASH_OFFSET + 1; + inst_read <= '1'; + + -- Memory Flow Control Guard + if (inst_ready_in = '1') then + inst_cnt_next <= inst_cnt + 1; end if; - -- Key Hash 2/4 + -- GET Key Hash 3/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; + inst_valid_in <= '1'; + inst_addr <= inst_addr_base + IMF_KEY_HASH_OFFSET + 2; + inst_read <= '1'; + + -- Memory Flow Control Guard + if (inst_ready_in = '1') then + inst_cnt_next <= inst_cnt + 1; end if; - -- Key Hash 3/4 + -- GET Key Hash 4/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; + inst_valid_in <= '1'; + inst_addr <= inst_addr_base + IMF_KEY_HASH_OFFSET + 3; + inst_read <= '1'; + + -- Memory Flow Control Guard + if (inst_ready_in = '1') then + inst_cnt_next <= inst_cnt + 1; + end if; + -- READ Next Instance + when 5 => + inst_ready_out <= '1'; + + -- Memory Flow Control Guard + if (inst_valid_out = '1') then + inst_next_addr_base_next <= inst_read_data; + inst_cnt_next <= inst_cnt + 1; + end if; + -- READ Key Hash 1/4 + when 6 => + inst_ready_out <= '1'; + + -- Memory Flow Control Guard + if (inst_valid_out = '1') then + -- No Match + if (inst_read_data /= inst_latch_data.key_hash(0)) then + -- Reached List Tail, No Match + if (inst_next_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_cnt_next <= 0; + inst_abort_read <= '1'; + end if; 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; + inst_cnt_next <= inst_cnt + 1; 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; + -- READ Key Hash 2/4 + when 7 => + inst_ready_out <= '1'; + + -- Memory Flow Control Guard + if (inst_valid_out = '1') then + -- No Match + if (inst_read_data /= inst_latch_data.key_hash(1)) then + -- Reached List Tail, No Match + if (inst_next_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_cnt_next <= 0; + inst_abort_read <= '1'; + end if; 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; + inst_cnt_next <= inst_cnt + 1; end if; - -- Match - else - -- Fetch Instance Data - case (inst_data_variant) is - when VAR_1 => - inst_stage_next <= GET_INSTANCE_DATA_1; - inst_cnt_next <= 1; -- No preload needed - when VAR_2 => - inst_addr_next <= inst_addr_base + IMF_KEY_HASH_OFFSET; - inst_stage_next <= GET_INSTANCE_DATA_2; + end if; + -- READ Key Hash 3/4 + when 8 => + inst_ready_out <= '1'; + + -- Memory Flow Control Guard + if (inst_valid_out = '1') then + -- No Match + if (inst_read_data /= inst_latch_data.key_hash(2)) then + -- Reached List Tail, No Match + if (inst_next_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_cnt_next <= 0; + inst_abort_read <= '1'; + end if; + else + inst_cnt_next <= inst_cnt + 1; + end if; + end if; + -- READ Key Hash 4/4 + when 9 => + inst_ready_out <= '1'; + + -- Memory Flow Control Guard + if (inst_valid_out = '1') then + -- No Match + if (inst_read_data /= inst_latch_data.key_hash(3)) then + -- Reached List Tail, No Match + if (inst_next_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_cnt_next <= 0; + inst_abort_read <= '1'; + end if; + else + -- Get Instance Data + inst_stage_next <= GET_INSTANCE_DATA; + if check_mask(inst_latch_data.field_flag,IMF_KEY_HASH_FLAG) then inst_cnt_next <= 0; - when VAR_3 => - inst_addr_next <= inst_addr_base + IMF_KEY_HASH_OFFSET; - inst_stage_next <= GET_INSTANCE_DATA_3; - inst_cnt_next <= 0; - end case; + elsif check_mask(inst_latch_data.field_flag,IMF_STATUS_FLAG) then + inst_cnt_next <= 4; + elsif check_mask(inst_latch_data.field_flag,IMF_SAMPLE_CNT_FLAG) then + inst_cnt_next <= 5; + elsif check_mask(inst_latch_data.field_flag,IMF_DISPOSED_CNT_FLAG) then + inst_cnt_next <= 6; + elsif check_mask(inst_latch_data.field_flag,IMF_NO_WRITERS_CNT_FLAG) then + inst_cnt_next <= 7; + elsif (TIME_BASED_FILTER_QOS /= DURATION_ZERO and check_mask(inst_latch_data.field_flag,IMF_IGNORE_DEADLINE_FLAG)) then + inst_cnt_next <= 8; + elsif check_mask(inst_latch_data.field_flag,IMF_WRITER_BITMAP_FLAG) then + inst_cnt_next <= 10; + inst_cnt2_next <= 0; + else + -- DONE + inst_stage_next <= IDLE; + end if; + end if; end if; when others => null; end case; when SEARCH_INSTANCE_ADDR => - inst_cnt_next <= inst_cnt + 1; - inst_addr_next <= inst_addr + 1; case (inst_cnt) is - -- Preload + -- GET Next Instance when 0 => - inst_ren <= '1'; - -- Next Instance + inst_valid_in <= '1'; + inst_addr <= inst_addr_base + IMF_NEXT_ADDR_OFFSET; + inst_read <= '1'; + + -- Memory Flow Control Guard + if (inst_ready_in = '1') then + inst_cnt_next <= inst_cnt + 1; + end if; + -- READ Next Instance when 1 => - inst_prev_addr_base_next <= inst_addr_base; - inst_addr_base_next <= inst_read_data; - - -- Match - if (inst_read_data = inst_latch_data.addr) then - -- Fetch Instance Data - case (inst_data_variant) is - when VAR_1 => - inst_addr_next <= inst_read_data + IMF_STATUS_INFO_OFFSET; - inst_stage_next <= GET_INSTANCE_DATA_1; + inst_ready_out <= '1'; + + -- Memory Flow Control Guard + if (inst_valid_out = '1') then + inst_prev_addr_base_next <= inst_addr_base; + inst_addr_base_next <= inst_read_data; + + -- Match + if (inst_read_data = inst_latch_data.addr) then + -- Get Instance Data + inst_stage_next <= GET_INSTANCE_DATA; + if check_mask(inst_latch_data.field_flag,IMF_KEY_HASH_FLAG) then inst_cnt_next <= 0; - when VAR_2 => - inst_addr_next <= inst_read_data + IMF_KEY_HASH_OFFSET; - inst_stage_next <= GET_INSTANCE_DATA_2; - -- TODO: Skip Preload? - inst_cnt_next <= 0; - when VAR_3 => - inst_addr_next <= inst_read_data + IMF_KEY_HASH_OFFSET; - inst_stage_next <= GET_INSTANCE_DATA_3; - -- TODO: Skip Preload? - inst_cnt_next <= 0; - end case; - -- No Match - else - -- Reached List Tail, No Match - if (inst_read_data = INSTANCE_MEMORY_MAX_ADDRESS) then - inst_addr_base_next <= INSTANCE_MEMORY_MAX_ADDRESS; --No match - -- DONE - inst_stage_next <= IDLE; + elsif check_mask(inst_latch_data.field_flag,IMF_STATUS_FLAG) then + inst_cnt_next <= 4; + elsif check_mask(inst_latch_data.field_flag,IMF_SAMPLE_CNT_FLAG) then + inst_cnt_next <= 5; + elsif check_mask(inst_latch_data.field_flag,IMF_DISPOSED_CNT_FLAG) then + inst_cnt_next <= 6; + elsif check_mask(inst_latch_data.field_flag,IMF_NO_WRITERS_CNT_FLAG) then + inst_cnt_next <= 7; + elsif (TIME_BASED_FILTER_QOS /= DURATION_ZERO and check_mask(inst_latch_data.field_flag,IMF_IGNORE_DEADLINE_FLAG)) then + inst_cnt_next <= 8; + elsif check_mask(inst_latch_data.field_flag,IMF_WRITER_BITMAP_FLAG) then + inst_cnt_next <= 10; + inst_cnt2_next <= 0; + else + -- DONE + inst_stage_next <= IDLE; + end if; + -- No Match else - -- Continue Search - inst_addr_next <= inst_read_data; - inst_cnt_next <= 0; + -- Reached List Tail, No Match + if (inst_read_data = INSTANCE_MEMORY_MAX_ADDRESS) then + inst_addr_base_next <= INSTANCE_MEMORY_MAX_ADDRESS; --No match + -- DONE + inst_stage_next <= IDLE; + else + -- Continue Search + inst_cnt_next <= 0; + end if; end if; end if; when others => null; - end case; + end case; when GET_NEXT_INSTANCE => case (inst_cnt) is - -- Preload + -- GET next Instance when 0 => - inst_wen <= '1'; - -- Next Instance + inst_valid_in <= '1'; + inst_addr <= inst_addr_base + IMF_NEXT_ADDR_OFFSET; + inst_read <= '1'; + + -- Memory Flow Control Guard + if (inst_ready_in = '1') then + inst_cnt_next <= inst_cnt + 1; + end if; + -- READ Next Instance when 1 => - -- Latch Next Instance - inst_next_addr_base_next <= inst_read_data; + inst_ready_out <= '1'; - - -- Fetch Instance Data - case (inst_data_variant) is - when VAR_1 => - inst_addr_next <= inst_addr_base + IMF_STATUS_INFO_OFFSET; - inst_stage_next <= GET_INSTANCE_DATA_1; + -- Memory Flow Control Guard + if (inst_valid_out = '1') then + inst_next_addr_base_next <= inst_read_data; + -- Get Instance Data + inst_stage_next <= GET_INSTANCE_DATA; + if check_mask(inst_latch_data.field_flag,IMF_KEY_HASH_FLAG) then inst_cnt_next <= 0; - when VAR_2 => - inst_addr_next <= inst_addr_base + IMF_KEY_HASH_OFFSET; - inst_stage_next <= GET_INSTANCE_DATA_2; - -- TODO: Skip Preload? - inst_cnt_next <= 0; - when VAR_3 => - inst_addr_next <= inst_addr_base + IMF_KEY_HASH_OFFSET; - inst_stage_next <= GET_INSTANCE_DATA_3; - -- TODO: Skip Preload? - inst_cnt_next <= 0; - end case; - end case; - when GET_INSTANCE_DATA_3 => - -- Precondition: inst_addr (Status Info) - - inst_ren <= '1'; - inst_cnt_next <= inst_cnt + 1; - inst_addr_next <= inst_addr + 1; - - case (inst_cnt) is - -- Memory Preload - when 0 => - null; - -- Key Hash 1/4 - when 1 => - inst_data_next.key_hash(0) <= inst_read_data; - -- Key Hash 2/4 - when 2 => - inst_data_next.key_hash(1) <= inst_read_data; - -- Key Hash 3/4 - when 3 => - inst_data_next.key_hash(2) <= inst_read_data; - -- Key Hash 4/4 - when 4 => - inst_data_next.key_hash(3) <= inst_read_data; - -- Status Info - when 5 => - inst_data_next.status_info <= inst_read_data; - - -- DONE - inst_stage_next <= IDLE; + elsif check_mask(inst_latch_data.field_flag,IMF_STATUS_FLAG) then + inst_cnt_next <= 4; + elsif check_mask(inst_latch_data.field_flag,IMF_SAMPLE_CNT_FLAG) then + inst_cnt_next <= 5; + elsif check_mask(inst_latch_data.field_flag,IMF_DISPOSED_CNT_FLAG) then + inst_cnt_next <= 6; + elsif check_mask(inst_latch_data.field_flag,IMF_NO_WRITERS_CNT_FLAG) then + inst_cnt_next <= 7; + elsif (TIME_BASED_FILTER_QOS /= DURATION_ZERO and check_mask(inst_latch_data.field_flag,IMF_IGNORE_DEADLINE_FLAG)) then + inst_cnt_next <= 8; + elsif check_mask(inst_latch_data.field_flag,IMF_WRITER_BITMAP_FLAG) then + inst_cnt_next <= 10; + inst_cnt2_next <= 0; + else + -- DONE + inst_stage_next <= IDLE; + end if; + end if; when others => null; end case; - when GET_INSTANCE_DATA_2 => - -- Precondition: inst_addr (Status Info) - - inst_ren <= '1'; - inst_cnt_next <= inst_cnt + 1; - inst_addr_next <= inst_addr + 1; - + when GET_INSTANCE_DATA => case (inst_cnt) is - -- Memory Preload + -- GET Key Hash 1/4 when 0 => - null; - -- Key Hash 1/4 + inst_valid_in <= '1'; + inst_addr <= inst_addr_base + IMF_KEY_HASH_OFFSET; + inst_read <= '1'; + + -- Memory Flow Control Guard + if (inst_ready_in = '1') then + inst_cnt_next <= inst_cnt + 1; + end if; + -- GET Key Hash 2/4 when 1 => - inst_data_next.key_hash(0) <= inst_read_data; - -- Key Hash 2/4 + inst_valid_in <= '1'; + inst_addr <= inst_addr_base + IMF_KEY_HASH_OFFSET + 1; + inst_read <= '1'; + + -- Memory Flow Control Guard + if (inst_ready_in = '1') then + inst_cnt_next <= inst_cnt + 1; + end if; + -- GET Key Hash 3/4 when 2 => - inst_data_next.key_hash(1) <= inst_read_data; - -- Key Hash 3/4 + inst_valid_in <= '1'; + inst_addr <= inst_addr_base + IMF_KEY_HASH_OFFSET + 2; + inst_read <= '1'; + + -- Memory Flow Control Guard + if (inst_ready_in = '1') then + inst_cnt_next <= inst_cnt + 1; + end if; + -- GET Key Hash 4/4 when 3 => - inst_data_next.key_hash(2) <= inst_read_data; - -- Key Hash 4/4 + inst_valid_in <= '1'; + inst_addr <= inst_addr_base + IMF_KEY_HASH_OFFSET + 3; + inst_read <= '1'; + + -- Memory Flow Control Guard + if (inst_ready_in = '1') then + if check_mask(inst_latch_data.field_flag,IMF_STATUS_FLAG) then + inst_cnt_next <= 4; + elsif check_mask(inst_latch_data.field_flag,IMF_SAMPLE_CNT_FLAG) then + inst_cnt_next <= 5; + elsif check_mask(inst_latch_data.field_flag,IMF_DISPOSED_CNT_FLAG) then + inst_cnt_next <= 6; + elsif check_mask(inst_latch_data.field_flag,IMF_NO_WRITERS_CNT_FLAG) then + inst_cnt_next <= 7; + elsif (TIME_BASED_FILTER_QOS /= DURATION_ZERO and check_mask(inst_latch_data.field_flag,IMF_IGNORE_DEADLINE_FLAG)) then + inst_cnt_next <= 8; + elsif check_mask(inst_latch_data.field_flag,IMF_WRITER_BITMAP_FLAG) then + inst_cnt_next <= 10; + inst_cnt2_next <= 0; + else + inst_cnt_next <= 11; + end if; + end if; + -- GET Status Info when 4 => - inst_data_next.key_hash(3) <= inst_read_data; - -- Status Info + inst_valid_in <= '1'; + inst_addr <= inst_addr_base + IMF_STATUS_INFO_OFFSET; + inst_read <= '1'; + + -- Memory Flow Control Guard + if (inst_ready_in = '1') then + if check_mask(inst_latch_data.field_flag,IMF_SAMPLE_CNT_FLAG) then + inst_cnt_next <= 5; + elsif check_mask(inst_latch_data.field_flag,IMF_DISPOSED_CNT_FLAG) then + inst_cnt_next <= 6; + elsif check_mask(inst_latch_data.field_flag,IMF_NO_WRITERS_CNT_FLAG) then + inst_cnt_next <= 7; + elsif (TIME_BASED_FILTER_QOS /= DURATION_ZERO and check_mask(inst_latch_data.field_flag,IMF_IGNORE_DEADLINE_FLAG)) then + inst_cnt_next <= 8; + elsif check_mask(inst_latch_data.field_flag,IMF_WRITER_BITMAP_FLAG) then + inst_cnt_next <= 10; + inst_cnt2_next <= 0; + else + if check_mask(inst_latch_data.field_flag,IMF_KEY_HASH_FLAG) then + inst_cnt_next <= 11; + else + inst_cnt_next <= 15; + end if; + end if; + end if; + -- GET Sample Count when 5 => - inst_data_next.status_info <= inst_read_data; - -- Sample Count + inst_valid_in <= '1'; + inst_addr <= inst_addr_base + IMF_SAMPLE_CNT_OFFSET; + inst_read <= '1'; + + -- Memory Flow Control Guard + if (inst_ready_in = '1') then + if check_mask(inst_latch_data.field_flag,IMF_DISPOSED_CNT_FLAG) then + inst_cnt_next <= 6; + elsif check_mask(inst_latch_data.field_flag,IMF_NO_WRITERS_CNT_FLAG) then + inst_cnt_next <= 7; + elsif (TIME_BASED_FILTER_QOS /= DURATION_ZERO and check_mask(inst_latch_data.field_flag,IMF_IGNORE_DEADLINE_FLAG)) then + inst_cnt_next <= 8; + elsif check_mask(inst_latch_data.field_flag,IMF_WRITER_BITMAP_FLAG) then + inst_cnt_next <= 10; + inst_cnt2_next <= 0; + else + if check_mask(inst_latch_data.field_flag,IMF_KEY_HASH_FLAG) then + inst_cnt_next <= 11; + elsif check_mask(inst_latch_data.field_flag,IMF_STATUS_FLAG) then + inst_cnt_next <= 15; + else + inst_cnt_next <= 16; + end if; + end if; + end if; + -- GET Disposed Generation Count when 6 => - inst_data_next.sample_cnt <= inst_read_data; - -- Disposed Generation Count + inst_valid_in <= '1'; + inst_addr <= inst_addr_base + IMF_DISPOSED_GEN_CNT_OFFSET; + inst_read <= '1'; + + -- Memory Flow Control Guard + if (inst_ready_in = '1') then + if check_mask(inst_latch_data.field_flag,IMF_NO_WRITERS_CNT_FLAG) then + inst_cnt_next <= 7; + elsif (TIME_BASED_FILTER_QOS /= DURATION_ZERO and check_mask(inst_latch_data.field_flag,IMF_IGNORE_DEADLINE_FLAG)) then + inst_cnt_next <= 8; + elsif check_mask(inst_latch_data.field_flag,IMF_WRITER_BITMAP_FLAG) then + inst_cnt_next <= 10; + inst_cnt2_next <= 0; + else + if check_mask(inst_latch_data.field_flag,IMF_KEY_HASH_FLAG) then + inst_cnt_next <= 11; + elsif check_mask(inst_latch_data.field_flag,IMF_STATUS_FLAG) then + inst_cnt_next <= 15; + elsif check_mask(inst_latch_data.field_flag,IMF_SAMPLE_CNT_FLAG) then + inst_cnt_next <= 16; + else + inst_cnt_next <= 17; + end if; + end if; + end if; + -- GET No Writers Generation Count when 7 => - inst_data_next.disposed_gen_cnt <= inst_read_data; - -- No Writers Generation Count + inst_valid_in <= '1'; + inst_addr <= inst_addr_base + IMF_NO_WRITERS_GEN_CNT_OFFSET; + inst_read <= '1'; + + -- Memory Flow Control Guard + if (inst_ready_in = '1') then + if (TIME_BASED_FILTER_QOS /= DURATION_ZERO and check_mask(inst_latch_data.field_flag,IMF_IGNORE_DEADLINE_FLAG)) then + inst_cnt_next <= 8; + elsif check_mask(inst_latch_data.field_flag,IMF_WRITER_BITMAP_FLAG) then + inst_cnt_next <= 10; + inst_cnt2_next <= 0; + else + if check_mask(inst_latch_data.field_flag,IMF_KEY_HASH_FLAG) then + inst_cnt_next <= 11; + elsif check_mask(inst_latch_data.field_flag,IMF_STATUS_FLAG) then + inst_cnt_next <= 15; + elsif check_mask(inst_latch_data.field_flag,IMF_SAMPLE_CNT_FLAG) then + inst_cnt_next <= 16; + elsif check_mask(inst_latch_data.field_flag,IMF_DISPOSED_CNT_FLAG) then + inst_cnt_next <= 17; + else + inst_cnt_next <= 18; + end if; + end if; + end if; + -- GET Ignore Deadline 1/2 when 8 => - inst_data_next.no_writers_gen_cnt <= inst_read_data; - - -- DONE - inst_stage_next <= IDLE; - when others => - null; + -- Synthesis Guard + if (TIME_BASED_FILTER_QOS /= DURATION_ZERO) then + inst_valid_in <= '1'; + inst_addr <= inst_addr_base + IMF_IGNORE_DEADLINE_OFFSET; + inst_read <= '1'; + + -- Memory Flow Control Guard + if (inst_ready_in = '1') then + inst_cnt_next <= inst_cnt + 1; + end if; + end if; + -- GET Ignore Deadline 2/2 + when 9 => + -- Synthesis Guard + if (TIME_BASED_FILTER_QOS /= DURATION_ZERO) then + inst_valid_in <= '1'; + inst_addr <= inst_addr_base + IMF_IGNORE_DEADLINE_OFFSET + 1; + inst_read <= '1'; + + -- Memory Flow Control Guard + if (inst_ready_in = '1') then + if check_mask(inst_latch_data.field_flag,IMF_WRITER_BITMAP_FLAG) then + inst_cnt_next <= 10; + inst_cnt2_next <= 0; + else + if check_mask(inst_latch_data.field_flag,IMF_KEY_HASH_FLAG) then + inst_cnt_next <= 11; + elsif check_mask(inst_latch_data.field_flag,IMF_STATUS_FLAG) then + inst_cnt_next <= 15; + elsif check_mask(inst_latch_data.field_flag,IMF_SAMPLE_CNT_FLAG) then + inst_cnt_next <= 16; + elsif check_mask(inst_latch_data.field_flag,IMF_DISPOSED_CNT_FLAG) then + inst_cnt_next <= 17; + elsif check_mask(inst_latch_data.field_flag,IMF_NO_WRITERS_CNT_FLAG) then + inst_cnt_next <= 18; + else + inst_cnt_next <= 19; + end if; + end if; + end if; + end if; + -- GET Writer Bitmap + when 10 => + -- XXX: Possible Worst case Path (2 Additions in same clock) + inst_valid_in <= '1'; + inst_addr <= inst_addr_base + IMF_IGNORE_DEADLINE_OFFSET + inst_cnt2; + inst_read <= '1'; + + -- Memory Flow Control Guard + if (inst_ready_in = '1') then + -- Exit Condition + if (inst_cnt2 = ENDPOINT_BITMAP_ARRAY_TYPE'length-1) then + if check_mask(inst_latch_data.field_flag,IMF_KEY_HASH_FLAG) then + inst_cnt_next <= 11; + elsif check_mask(inst_latch_data.field_flag,IMF_STATUS_FLAG) then + inst_cnt_next <= 15; + elsif check_mask(inst_latch_data.field_flag,IMF_SAMPLE_CNT_FLAG) then + inst_cnt_next <= 16; + elsif check_mask(inst_latch_data.field_flag,IMF_DISPOSED_CNT_FLAG) then + inst_cnt_next <= 17; + elsif check_mask(inst_latch_data.field_flag,IMF_NO_WRITERS_CNT_FLAG) then + inst_cnt_next <= 18; + elsif (TIME_BASED_FILTER_QOS /= DURATION_ZERO and check_mask(inst_latch_data.field_flag,IMF_IGNORE_DEADLINE_FLAG)) then + inst_cnt_next <= 19; + else + inst_cnt_next <= 21; + inst_cnt2_next <= 0; + end if; + else + inst_cnt2_next <= inst_cnt2 + 1; + end if; + end if; + -- READ Key Hash 1/4 + when 11 => + inst_ready_out <= '1'; + + -- Memory Flow Control Guard + if (inst_valid_out = '1') then + inst_latch_data_next.key_hash(0) <= inst_read_data; + inst_cnt_next <= inst_cnt + 1; + end if; + -- READ Key Hash 2/4 + when 12 => + inst_ready_out <= '1'; + + -- Memory Flow Control Guard + if (inst_valid_out = '1') then + inst_latch_data_next.key_hash(1) <= inst_read_data; + inst_cnt_next <= inst_cnt + 1; + end if; + -- READ Key Hash 3/4 + when 13 => + inst_ready_out <= '1'; + + -- Memory Flow Control Guard + if (inst_valid_out = '1') then + inst_latch_data_next.key_hash(2) <= inst_read_data; + inst_cnt_next <= inst_cnt + 1; + end if; + -- READ Key Hash 4/4 + when 14 => + inst_ready_out <= '1'; + + -- Memory Flow Control Guard + if (inst_valid_out = '1') then + inst_latch_data_next.key_hash(3) <= inst_read_data; + + if check_mask(inst_latch_data.field_flag,IMF_STATUS_FLAG) then + inst_cnt_next <= 15; + elsif check_mask(inst_latch_data.field_flag,IMF_SAMPLE_CNT_FLAG) then + inst_cnt_next <= 16; + elsif check_mask(inst_latch_data.field_flag,IMF_DISPOSED_CNT_FLAG) then + inst_cnt_next <= 17; + elsif check_mask(inst_latch_data.field_flag,IMF_NO_WRITERS_CNT_FLAG) then + inst_cnt_next <= 18; + elsif (TIME_BASED_FILTER_QOS /= DURATION_ZERO and check_mask(inst_latch_data.field_flag,IMF_IGNORE_DEADLINE_FLAG)) then + inst_cnt_next <= 19; + elsif check_mask(inst_latch_data.field_flag,IMF_WRITER_BITMAP_FLAG) then + inst_cnt_next <= 21; + inst_cnt2_next <= 0; + else + -- DONE + inst_stage_next <= IDLE; + end if; + end if; + -- READ Status Info + when 15 => + inst_ready_out <= '1'; + + -- Memory Flow Control Guard + if (inst_valid_out = '1') then + inst_latch_data_next.status_info <= inst_read_data; + + if check_mask(inst_latch_data.field_flag,IMF_SAMPLE_CNT_FLAG) then + inst_cnt_next <= 16; + elsif check_mask(inst_latch_data.field_flag,IMF_DISPOSED_CNT_FLAG) then + inst_cnt_next <= 17; + elsif check_mask(inst_latch_data.field_flag,IMF_NO_WRITERS_CNT_FLAG) then + inst_cnt_next <= 18; + elsif (TIME_BASED_FILTER_QOS /= DURATION_ZERO and check_mask(inst_latch_data.field_flag,IMF_IGNORE_DEADLINE_FLAG)) then + inst_cnt_next <= 19; + elsif check_mask(inst_latch_data.field_flag,IMF_WRITER_BITMAP_FLAG) then + inst_cnt_next <= 21; + inst_cnt2_next <= 0; + else + -- DONE + inst_stage_next <= IDLE; + end if; + end if; + -- READ Sample Count + when 16 => + inst_ready_out <= '1'; + + -- Memory Flow Control Guard + if (inst_valid_out = '1') then + inst_latch_data_next.sample_cnt <= inst_read_data; + + if check_mask(inst_latch_data.field_flag,IMF_DISPOSED_CNT_FLAG) then + inst_cnt_next <= 17; + elsif check_mask(inst_latch_data.field_flag,IMF_NO_WRITERS_CNT_FLAG) then + inst_cnt_next <= 18; + elsif (TIME_BASED_FILTER_QOS /= DURATION_ZERO and check_mask(inst_latch_data.field_flag,IMF_IGNORE_DEADLINE_FLAG)) then + inst_cnt_next <= 19; + elsif check_mask(inst_latch_data.field_flag,IMF_WRITER_BITMAP_FLAG) then + inst_cnt_next <= 21; + inst_cnt2_next <= 0; + else + -- DONE + inst_stage_next <= IDLE; + end if; + end if; + -- READ Disposed Generation Count + when 17 => + inst_ready_out <= '1'; + + -- Memory Flow Control Guard + if (inst_valid_out = '1') then + inst_latch_data_next.disposed_gen_cnt <= inst_read_data; + + if check_mask(inst_latch_data.field_flag,IMF_NO_WRITERS_CNT_FLAG) then + inst_cnt_next <= 18; + elsif (TIME_BASED_FILTER_QOS /= DURATION_ZERO and check_mask(inst_latch_data.field_flag,IMF_IGNORE_DEADLINE_FLAG)) then + inst_cnt_next <= 19; + elsif check_mask(inst_latch_data.field_flag,IMF_WRITER_BITMAP_FLAG) then + inst_cnt_next <= 21; + inst_cnt2_next <= 0; + else + -- DONE + inst_stage_next <= IDLE; + end if; + end if; + -- READ No Writers Generation Count + when 18 => + inst_ready_out <= '1'; + + -- Memory Flow Control Guard + if (inst_valid_out = '1') then + inst_latch_data_next.no_writers_gen_cnt <= inst_read_data; + + if (TIME_BASED_FILTER_QOS /= DURATION_ZERO and check_mask(inst_latch_data.field_flag,IMF_IGNORE_DEADLINE_FLAG)) then + inst_cnt_next <= 19; + elsif check_mask(inst_latch_data.field_flag,IMF_WRITER_BITMAP_FLAG) then + inst_cnt_next <= 21; + inst_cnt2_next <= 0; + else + -- DONE + inst_stage_next <= IDLE; + end if; + end if; + -- READ Ignore Deadline 1/2 + when 19 => + inst_ready_out <= '1'; + + -- Memory Flow Control Guard + if (inst_valid_out = '1') then + inst_latch_data_next.ignore_deadline(0) <= inst_read_data; + + inst_cnt_next <= inst_cnt + 1; + end if; + -- READ Ignore Deadline 2/2 + when 20 => + inst_ready_out <= '1'; + + -- Memory Flow Control Guard + if (inst_valid_out = '1') then + inst_latch_data_next.ignore_deadline(1) <= inst_read_data; + + if check_mask(inst_latch_data.field_flag,IMF_WRITER_BITMAP_FLAG) then + inst_cnt_next <= 21; + inst_cnt2_next <= 0; + else + -- DONE + inst_stage_next <= IDLE; + end if; + end if; + -- READ Writer Bitamp + when 21 => + inst_ready_out <= '1'; + + -- Memory Flow Control Guard + if (inst_valid_out = '1') then + inst_latch_data_next.writer_bitmap(inst_cnt2) <= inst_read_data; + -- Exit Condition + if (inst_cnt2 = ENDPOINT_BITMAP_ARRAY_TYPE'length-1) then + -- DONE + inst_stage_next <= IDLE; + else + inst_cnt2_next <= inst_cnt2 + 1; + end if; + end if; end case; - when GET_INSTANCE_DATA_1 => - -- Precondition: inst_addr (Status Info) - - inst_ren <= '1'; - inst_cnt_next <= inst_cnt + 1; - inst_addr_next <= inst_addr + 1; - - case (inst_cnt) is - -- Memory Preload - when 0 => - null; - -- Status Info - when 1 => - inst_data_next.status_info <= inst_read_data; - -- Sample Count - when 2 => - inst_data_next.sample_cnt <= inst_read_data; - -- Disposed Generation Count - when 3 => - inst_data_next.disposed_gen_cnt <= inst_read_data; - -- No Writers Generation Count - when 4 => - inst_data_next.no_writers_gen_cnt <= inst_read_data; - -- Ignore Deadline 1/2 - when 5 => - inst_data_next.ignore_deadline(0) <= unsigned(inst_read_data); - -- Ignore Deadline 2/2 - when 5 => - inst_data_next.ignore_deadline(1) <= unsigned(inst_read_data); - -- DONE - inst_stage_next <= GET_WRITER_BITMAP; - inst_cnt_next <= 0; - when others => - null; - end case; - when GET_WRITER_BITMAP => - inst_cnt_next <= inst_cnt + 1; - - inst_latch_data_next.writer_bitmap(inst_cnt) <= inst_read_data; - - if (inst_cnt = writer_bitmap'length-1) then - -- DONE - inst_stage_next <= IDLE; - end if; when FIND_POS => - inst_cnt_next <= inst_cnt + 1; - inst_addr_next <= inst_addr + 1; - inst_ren <= '1'; - -- NOTE: Instances are inserted in KEY_HASH numerical order. + -- TODO: Handle inst_next_addr_base = MAX_ADDR + case (inst_cnt) is - - -- Preload + -- GET Next Instance when 0 => - null; - -- Next Instance + inst_valid_in <= '1'; + inst_addr <= inst_addr_base + IMF_NEXT_ADDR_OFFSET; + inst_read <= '1'; + + -- Memory Flow Control Guard + if (inst_ready_in = '1') then + inst_cnt_next <= inst_cnt + 1; + end if; + -- GET Key Hash 1/4 when 1 => - inst_next_addr_base_next <= inst_read_data; - -- Key Hash 1/4 + inst_valid_in <= '1'; + inst_addr <= inst_addr_base + IMF_KEY_HASH_OFFSET; + inst_read <= '1'; + + -- Memory Flow Control Guard + if (inst_ready_in = '1') then + inst_cnt_next <= inst_cnt + 1; + end if; + -- GET Key Hash 2/4 when 2 => - -- Found Position - if (inst_latch_data.key_hash(0) < inst_read_data) then - inst_next_addr_base_next <= inst_addr_base; - -- Occupied List Head - if (inst_prev_addr_base = INSTANCE_MEMORY_MAX_ADDRESS) then - assert (inst_addr_base = inst_occupied_head) - inst_occupied_head_next <= inst_empty_head; - - inst_addr_base_next <= inst_empty_head; - inst_addr_next <= inst_empty_head + IMF_NEXT_ADDR_OFFSET; - inst_stage_next <= INSERT_INSTANCE; - cnt_next <= 1; -- Skip First Step - else - inst_addr_base_next <= inst_prev_addr_base; - inst_addr_next <= inst_prev_addr_base + IMF_NEXT_ADDR_OFFSET; - inst_stage_next <= INSERT_INSTANCE; - cnt_next <= 0; - end if; - -- BIGGER-THAN - elsif (inst_latch_data.key_hash(0) /= inst_read_data) then - -- Continue - inst_prev_addr_base_next <= inst_addr_base; - inst_addr_next <= inst_next_addr_base; - inst_addr_base_next <= inst_next_addr_base; - cnt_next <= 0; + inst_valid_in <= '1'; + inst_addr <= inst_addr_base + IMF_KEY_HASH_OFFSET + 1; + inst_read <= '1'; + + -- Memory Flow Control Guard + if (inst_ready_in = '1') then + inst_cnt_next <= inst_cnt + 1; end if; - -- Key Hash 2/4 + -- GET Key Hash 3/4 when 3 => - -- Found Position - if (inst_latch_data.key_hash(1) < inst_read_data) then - inst_next_addr_base_next <= inst_addr_base; - -- Occupied List Head - if (inst_prev_addr_base = INSTANCE_MEMORY_MAX_ADDRESS) then - assert (inst_addr_base = inst_occupied_head) - inst_occupied_head_next <= inst_empty_head; - - inst_addr_base_next <= inst_empty_head; - inst_addr_next <= inst_empty_head + IMF_NEXT_ADDR_OFFSET; - inst_stage_next <= INSERT_INSTANCE; - cnt_next <= 1; -- Skip First Step - else - inst_addr_base_next <= inst_prev_addr_base; - inst_addr_next <= inst_prev_addr_base + IMF_NEXT_ADDR_OFFSET; - inst_stage_next <= INSERT_INSTANCE; - cnt_next <= 0; - end if; - -- BIGGER-THAN - elsif (inst_latch_data.key_hash(1) /= inst_read_data) then - -- Continue - inst_prev_addr_base_next <= inst_addr_base; - inst_addr_next <= inst_next_addr_base; - inst_addr_base_next <= inst_next_addr_base; - cnt_next <= 0; + inst_valid_in <= '1'; + inst_addr <= inst_addr_base + IMF_KEY_HASH_OFFSET + 2; + inst_read <= '1'; + + -- Memory Flow Control Guard + if (inst_ready_in = '1') then + inst_cnt_next <= inst_cnt + 1; end if; - -- Key Hash 3/4 + -- GET Key Hash 4/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; + inst_valid_in <= '1'; + inst_addr <= inst_addr_base + IMF_KEY_HASH_OFFSET + 3; + inst_read <= '1'; + + -- Memory Flow Control Guard + if (inst_ready_in = '1') then + inst_cnt_next <= inst_cnt + 1; + end if; + -- READ Next Instance + when 5 => + inst_ready_out <= '1'; + + -- Memory Flow Control Guard + if (inst_valid_out = '1') then + inst_next_addr_base_next <= inst_read_data; + inst_cnt_next <= inst_cnt + 1; + end if; + -- READ Key Hash 1/4 + when 6 => + inst_ready_out <= '1'; + + -- Memory Flow Control Guard + if (inst_valid_out = '1') then + -- Found Position (Before Current Instance) + 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_stage_next <= INSERT_INSTANCE; + cnt_next <= 1; -- Skip First Step + else + inst_addr_base_next <= inst_prev_addr_base; + inst_stage_next <= INSERT_INSTANCE; + cnt_next <= 0; + end if; + -- BIGGER-THAN + elsif (inst_latch_data.key_hash(0) /= inst_read_data) then + -- Continue + inst_prev_addr_base_next <= inst_addr_base; + inst_addr_base_next <= inst_next_addr_base; + cnt_next <= 0; + inst_abort_read <= '1'; + end if; + end if; + -- READ Key Hash 2/4 + when 7 => + inst_ready_out <= '1'; + + -- Memory Flow Control Guard + if (inst_valid_out = '1') then + -- Found Position (Before Current Instance) + if (inst_latch_data.key_hash(1) < inst_read_data) then + inst_next_addr_base_next <= inst_addr_base; + -- Occupied List Head + if (inst_prev_addr_base = INSTANCE_MEMORY_MAX_ADDRESS) then + assert (inst_addr_base = inst_occupied_head) + inst_occupied_head_next <= inst_empty_head; + + inst_addr_base_next <= inst_empty_head; + inst_stage_next <= INSERT_INSTANCE; + cnt_next <= 1; -- Skip First Step + else + inst_addr_base_next <= inst_prev_addr_base; + 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_base_next <= inst_next_addr_base; + cnt_next <= 0; + inst_abort_read <= '1'; + end if; + end if; + -- READ Key Hash 3/4 + when 8 => + inst_ready_out <= '1'; + + -- Memory Flow Control Guard + if (inst_valid_out = '1') then + -- Found Position (Before Current Instance) + 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_stage_next <= INSERT_INSTANCE; + cnt_next <= 1; -- Skip First Step + else + inst_addr_base_next <= inst_prev_addr_base; + inst_stage_next <= INSERT_INSTANCE; + cnt_next <= 0; + end if; + -- BIGGER-THAN + elsif (inst_latch_data.key_hash(2) /= inst_read_data) then + -- Continue + inst_prev_addr_base_next <= inst_addr_base; + inst_addr_base_next <= inst_next_addr_base; + cnt_next <= 0; + inst_abort_read <= '1'; end if; - -- BIGGER-THAN - elsif (inst_latch_data.key_hash(2) /= inst_read_data) then - -- Continue - inst_prev_addr_base_next <= inst_addr_base; - inst_addr_next <= inst_next_addr_base; - inst_addr_base_next <= inst_next_addr_base; - cnt_next <= 0; end if; -- Key Hash 4/4 when 5 => - -- Found Position - if (inst_latch_data.key_hash(3) < inst_read_data) then - inst_next_addr_base_next <= inst_addr_base; - -- Occupied List Head - if (inst_prev_addr_base = INSTANCE_MEMORY_MAX_ADDRESS) then - assert (inst_addr_base = inst_occupied_head) - inst_occupied_head_next <= inst_empty_head; - - inst_addr_base_next <= inst_empty_head; - inst_addr_next <= inst_empty_head + IMF_NEXT_ADDR_OFFSET; - inst_stage_next <= INSERT_INSTANCE; - cnt_next <= 1; -- Skip First Step + inst_ready_out <= '1'; + + -- Memory Flow Control Guard + if (inst_valid_out = '1') then + -- 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_stage_next <= INSERT_INSTANCE; + cnt_next <= 1; -- Skip First Step + else + inst_addr_base_next <= inst_prev_addr_base; + inst_stage_next <= INSERT_INSTANCE; + cnt_next <= 0; + end if; 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; + 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_base_next <= inst_next_addr_base; + 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; + -- Precondition: inst_addr_base set, inst_prev_addr_base set case (inst_cnt) is - -- Next Pointer (Previous Instance) + -- GET Next Pointer 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_valid_in <= '1'; + inst_addr <= inst_addr_base + IMF_NEXT_ADDR_OFFSET; + inst_read <= '1'; - inst_write_data <= inst_next_addr_base; - inst_wen <= '1'; + -- Memory Flow Control Guard + if (inst_ready_in = '1') then + -- Insert to Occupied List Head + if (inst_prev_addr_base = INSTANCE_MEMORY_MAX_ADDRESS) then + inst_cnt_next <= inst_cnt + 2; + else + inst_cnt_next <= inst_cnt + 1; + end if; + end if; + -- Next Pointer (Previous Instance) + when 1 => + inst_valid_in <= '1'; + inst_addr <= inst_prev_addr_base + IMF_NEXT_ADDR_OFFSET; + inst_write_data <= inst_addr_base; + + -- Memory Flow Control Guard + if (inst_ready_in = '1') then + inst_cnt_next <= inst_cnt + 1; + end if; + -- READ Next Pointer + when 2 => + inst_ready_out <= '1'; + + -- Memory Flow Control Guard + if (inst_valid_out = '1') then + -- Fix Empty List Head + inst_empty_head_next <= inst_read_data; + + -- TODO + end if; -- Key Hash 1/4 when 3 => + inst_valid_in <= '1'; + inst_addr <= inst_addr_base + IMF_KEY_HASH_OFFSET; inst_write_data <= inst_latch_data.key_hash(0); - inst_wen <= '1'; + + -- Memory Flow Control Guard + if (inst_ready_in = '1') then + inst_cnt_next <= inst_cnt + 1; + end if; -- Key Hash 2/4 when 4 => + inst_valid_in <= '1'; + inst_addr <= inst_addr_base + IMF_KEY_HASH_OFFSET + 1; inst_write_data <= inst_latch_data.key_hash(1); - inst_wen <= '1'; + + -- Memory Flow Control Guard + if (inst_ready_in = '1') then + inst_cnt_next <= inst_cnt + 1; + end if; -- Key Hash 3/4 when 5 => + inst_valid_in <= '1'; + inst_addr <= inst_addr_base + IMF_KEY_HASH_OFFSET + 2; inst_write_data <= inst_latch_data.key_hash(2); - inst_wen <= '1'; + + -- Memory Flow Control Guard + if (inst_ready_in = '1') then + inst_cnt_next <= inst_cnt + 1; + end if; -- Key Hash 4/4 when 6 => + inst_valid_in <= '1'; + inst_addr <= inst_addr_base + IMF_KEY_HASH_OFFSET + 3; inst_write_data <= inst_latch_data.key_hash(3); - inst_wen <= '1'; + + -- Memory Flow Control Guard + if (inst_ready_in = '1') then + inst_cnt_next <= inst_cnt + 1; + end if; -- Status Info when 7 => + inst_valid_in <= '1'; + inst_addr <= inst_addr_base + IMF_STATUS_INFO_OFFSET; inst_write_data <= inst_latch_data.status_info; - inst_wen <= '1'; + + -- Memory Flow Control Guard + if (inst_ready_in = '1') then + inst_cnt_next <= inst_cnt + 1; + end if; -- Sample Count when 8 => + inst_valid_in <= '1'; + inst_addr <= inst_addr_base + IMF_SAMPLE_CNT_OFFSET; inst_write_data <= std_logic_vector(to_unsigned(1, WORD_WIDTH)); - inst_wen <= '1'; + + -- Memory Flow Control Guard + if (inst_ready_in = '1') then + inst_cnt_next <= inst_cnt + 1; + end if; -- Disposed Generation Count when 9 => + inst_valid_in <= '1'; + inst_addr <= inst_addr_base + IMF_SAMPLE_CNT_OFFSET; inst_write_data <= (others => '0'); - inst_wen <= '1'; + + -- Memory Flow Control Guard + if (inst_ready_in = '1') then + inst_cnt_next <= inst_cnt + 1; + end if; -- No Writers Generation Count when 10 => + inst_valid_in <= '1'; + inst_addr <= inst_addr_base + IMF_SAMPLE_CNT_OFFSET; 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; + -- Memory Flow Control Guard + if (inst_ready_in = '1') then + if (TIME_BASED_FILTER_QOS /= DURATION_ZERO) then + inst_cnt_next <= inst_cnt + 1; + else + inst_cnt_next <= inst_cnt + 3; + inst_cnt2_next <= 0; + end if; end if; + -- Ignore Deadline 1/2 when 11 => + -- Synthesis Guard if (TIME_BASED_FILTER_QOS /= DURATION_ZERO) then + inst_valid_in <= '1'; + inst_addr <= inst_addr_base + IMF_SAMPLE_CNT_OFFSET; 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; + -- Memory Flow Control Guard + if (inst_ready_in = '1') then + inst_cnt_next <= inst_cnt + 1; + end if; + end if; + -- Ignore Deadline 2/2 + when 12 => + -- Synthesis Guard + if (TIME_BASED_FILTER_QOS /= DURATION_ZERO) then + inst_valid_in <= '1'; + inst_addr <= inst_addr_base + IMF_SAMPLE_CNT_OFFSET; + inst_write_data <= inst_latch_data.deadline(1); + + -- Memory Flow Control Guard + if (inst_ready_in = '1') then + inst_cnt_next <= inst_cnt + 1; + inst_cnt2_next <= 0; + end if; + end if; + -- Writer Bitmap + when 13 => + -- XXX: Possible Worst case Path (2 Additions in same clock) + inst_valid_in <= '1'; + inst_addr <= inst_addr_base + IMF_WRITER_BITMAP_OFFSET + inst_cnt2; + inst_write_data <= inst_latch_data.writer_bitmap(inst_cnt2); + + -- Memory Flow Control Guard + if (inst_ready_in = '1') then + -- Exit Condition + if (inst_cnt2 = ENDPOINT_BITMAP_ARRAY_TYPE'length-1) then + -- DONE + inst_stage_next <= IDLE; + else + inst_cnt2_next <= inst_cnt2 + 1; + end if; end if; when others => null; end case; - when SET_WRITER_BITMAP => - inst_wen <= '1'; - inst_addr_next <= inst_addr + 1; - inst_cnt_next <= inst_cnt + 1; - - inst_write_data <= inst_latch_data.writer_bitmap(inst_cnt); - - -- Exit Condition - if (inst_cnt = inst_latch_data.writer_bitmap'length-1) then - -- DONE - inst_stage_next <= IDLE; - end if; when UPDATE_INSTANCE => - inst_cnt_next <= inst_cnt + 1; - case (inst_cnt) is -- Status Info when 0 => - inst_wen <= '1'; - inst_write_data <= inst_latch_data.status_info; + inst_valid_in <= '1'; + inst_addr <= inst_addr_base + IMF_STATUS_INFO_OFFSET; + inst_write_data <= inst_latch_data.status_info; inst_data_next.status_info <= inst_latch_data.status_info; - - if ((inst_latch_data.update_flags and SAMPLE_CNT_FLAG) = SAMPLE_CNT_FLAG) then - inst_addr_next <= inst_addr_base + IMF_SAMPLE_CNT_OFFSET; - inst_cnt_next <= 1; - elsif ((inst_latch_data.update_flags and DISPOSED_CNT_FLAG) = DISPOSED_CNT_FLAG) then - inst_addr_next <= inst_addr_base + IMF_DISPOSED_GEN_CNT_OFFSET; - inst_cnt_next <= 2; - elsif ((inst_latch_data.update_flags and NO_WRITERS_CNT_FLAG) = NO_WRITERS_CNT_FLAG) then - inst_addr_next <= inst_addr_base + IMF_NO_WRITERS_GEN_CNT_OFFSET; - inst_cnt_next <= 3; - elsif (TIME_BASED_FILTER_QOS /= DURATION_ZERO and (inst_latch_data.update_flags and IGNORE_DEADLINE_FLAG) = IGNORE_DEADLINE_FLAG) then - inst_addr_next <= inst_addr_base + IMF_IGNORE_DEADLINE_OFFSET; - inst_cnt_next <= 4; - elsif ((inst_latch_data.update_flags and WRITER_BITMAP_FLAG) = WRITER_BITMAP_FLAG) then - inst_addr_next <= inst_addr_base + IMF_WRITER_BITMAP_OFFSET; - inst_stage_next <= SET_WRITER_BITMAP; - inst_cnt_next <= 0; - else - -- DONE - inst_stage_next <= IDLE; + -- Memory Flow Control Guard + if (inst_ready_in = '1') then + if check_mask(inst_latch_data.field_flag,IMF_SAMPLE_CNT_FLAG) then + inst_cnt_next <= 1; + elsif check_mask(inst_latch_data.field_flag,IMF_DISPOSED_CNT_FLAG) then + inst_cnt_next <= 2; + elsif check_mask(inst_latch_data.field_flag,IMF_NO_WRITERS_CNT_FLAG) then + inst_cnt_next <= 3; + elsif (TIME_BASED_FILTER_QOS /= DURATION_ZERO and check_mask(inst_latch_data.field_flag,IMF_IGNORE_DEADLINE_FLAG)) then + inst_cnt_next <= 4; + elsif check_mask(inst_latch_data.field_flag,IMF_WRITER_BITMAP_FLAG) then + inst_cnt_next <= 6; + inst_cnt2_next <= 0; + else + -- DONE + inst_stage_next <= IDLE; + end if; end if; -- Sample Count when 1 => - inst_wen <= '1'; - inst_write_data <= inst_latch_data.sample_cnt; + inst_valid_in <= '1'; + inst_addr <= inst_addr_base + IMF_STATUS_INFO_OFFSET; + inst_write_data <= inst_latch_data.sample_cnt; inst_data_next.sample_cnt <= inst_latch_data.sample_cnt; - - if ((inst_latch_data.update_flags and DISPOSED_CNT_FLAG) = DISPOSED_CNT_FLAG) then - inst_addr_next <= inst_addr_base + IMF_DISPOSED_GEN_CNT_OFFSET; - inst_cnt_next <= 2; - elsif ((inst_latch_data.update_flags and NO_WRITERS_CNT_FLAG) = NO_WRITERS_CNT_FLAG) then - inst_addr_next <= inst_addr_base + IMF_NO_WRITERS_GEN_CNT_OFFSET; - inst_cnt_next <= 3; - elsif (TIME_BASED_FILTER_QOS /= DURATION_ZERO and (inst_latch_data.update_flags and IGNORE_DEADLINE_FLAG) = IGNORE_DEADLINE_FLAG) then - inst_addr_next <= inst_addr_base + IMF_IGNORE_DEADLINE_OFFSET; - inst_cnt_next <= 4; - elsif ((inst_latch_data.update_flags and WRITER_BITMAP_FLAG) = WRITER_BITMAP_FLAG) then - inst_addr_next <= inst_addr_base + IMF_WRITER_BITMAP_OFFSET; - inst_stage_next <= SET_WRITER_BITMAP; - inst_cnt_next <= 0; - else - -- DONE - inst_stage_next <= IDLE; + -- Memory Flow Control Guard + if (inst_ready_in = '1') then + if check_mask(inst_latch_data.field_flag,IMF_DISPOSED_CNT_FLAG) then + inst_cnt_next <= 2; + elsif check_mask(inst_latch_data.field_flag,IMF_NO_WRITERS_CNT_FLAG) then + inst_cnt_next <= 3; + elsif (TIME_BASED_FILTER_QOS /= DURATION_ZERO and check_mask(inst_latch_data.field_flag,IMF_IGNORE_DEADLINE_FLAG)) then + inst_cnt_next <= 4; + elsif check_mask(inst_latch_data.field_flag,IMF_WRITER_BITMAP_FLAG) then + inst_cnt_next <= 6; + inst_cnt2_next <= 0; + else + -- DONE + inst_stage_next <= IDLE; + end if; end if; -- Disposed Generation Count when 2 => - inst_wen <= '1'; - inst_write_data <= inst_latch_data.gen_cnt; + inst_valid_in <= '1'; + inst_addr <= inst_addr_base + IMF_DISPOSED_GEN_CNT_OFFSET; + inst_write_data <= inst_latch_data.gen_cnt; inst_data_next.disposed_gen_cnt <= inst_latch_data.gen_cnt; - - -- NOTE: Both Generation Counters cannot be updated on the same update procedure - if (TIME_BASED_FILTER_QOS /= DURATION_ZERO and (inst_latch_data.update_flags and IGNORE_DEADLINE_FLAG) = IGNORE_DEADLINE_FLAG) then - inst_addr_next <= inst_addr_base + IMF_IGNORE_DEADLINE_OFFSET; - inst_cnt_next <= 4; - elsif ((inst_latch_data.update_flags and WRITER_BITMAP_FLAG) = WRITER_BITMAP_FLAG) then - inst_addr_next <= inst_addr_base + IMF_WRITER_BITMAP_OFFSET; - inst_stage_next <= SET_WRITER_BITMAP; - inst_cnt_next <= 0; - else - -- DONE - inst_stage_next <= IDLE; + -- Memory Flow Control Guard + if (inst_ready_in = '1') then + if check_mask(inst_latch_data.field_flag,IMF_NO_WRITERS_CNT_FLAG) then + inst_cnt_next <= 3; + elsif (TIME_BASED_FILTER_QOS /= DURATION_ZERO and check_mask(inst_latch_data.field_flag,IMF_IGNORE_DEADLINE_FLAG)) then + inst_cnt_next <= 4; + elsif check_mask(inst_latch_data.field_flag,IMF_WRITER_BITMAP_FLAG) then + inst_cnt_next <= 6; + inst_cnt2_next <= 0; + else + -- DONE + inst_stage_next <= IDLE; + end if; end if; -- No Writers Generation Count when 3 => - inst_wen <= '1'; - inst_write_data <= inst_latch_data.gen_cnt; + inst_valid_in <= '1'; + inst_addr <= inst_addr_base + IMF_NO_WRITERS_GEN_CNT_OFFSET; + inst_write_data <= inst_latch_data.gen_cnt; inst_data_next.no_writers_gen_cnt <= inst_latch_data.gen_cnt; - - if (TIME_BASED_FILTER_QOS /= DURATION_ZERO and (inst_latch_data.update_flags and IGNORE_DEADLINE_FLAG) = IGNORE_DEADLINE_FLAG) then - inst_addr_next <= inst_addr_base + IMF_IGNORE_DEADLINE_OFFSET; - inst_cnt_next <= 4; - elsif ((inst_latch_data.update_flags and WRITER_BITMAP_FLAG) = WRITER_BITMAP_FLAG) then - inst_addr_next <= inst_addr_base + IMF_WRITER_BITMAP_OFFSET; - inst_stage_next <= SET_WRITER_BITMAP; - inst_cnt_next <= 0; - else - -- DONE - inst_stage_next <= IDLE; + -- Memory Flow Control Guard + if (inst_ready_in = '1') then + if (TIME_BASED_FILTER_QOS /= DURATION_ZERO and check_mask(inst_latch_data.field_flag,IMF_IGNORE_DEADLINE_FLAG)) then + inst_cnt_next <= 4; + elsif check_mask(inst_latch_data.field_flag,IMF_WRITER_BITMAP_FLAG) then + inst_cnt_next <= 6; + inst_cnt2_next <= 0; + else + -- DONE + inst_stage_next <= IDLE; + end if; end if; -- Ignore Deadline 1/2 when 4 => if (TIME_BASED_FILTER_QOS /= DURATION_ZERO) then - inst_wen <= '1'; - inst_write_data <= std_logic_vector(inst_latch_data.ignore_deadline(0)); + inst_valid_in <= '1'; + inst_addr <= inst_addr_base + IMF_IGNORE_DEADLINE_OFFSET; + inst_write_data <= std_logic_vector(inst_latch_data.ignore_deadline(0)); inst_data_next.deadline <= inst_latch_data.ignore_deadline(0); + -- Memory Flow Control Guard + if (inst_ready_in = '1') then + inst_cnt_next <= inst_cnt + 1; + end if; end if; -- Ignore Deadline 2/2 when 5 => if (TIME_BASED_FILTER_QOS /= DURATION_ZERO) then - inst_wen <= '1'; - inst_write_data <= std_logic_vector(inst_latch_data.ignore_deadline(1)); - inst_data_next.deadline <= inst_latch_data.ignore_deadline(1); - - if ((inst_latch_data.update_flags and WRITER_BITMAP_FLAG) = WRITER_BITMAP_FLAG) then - inst_addr_next <= inst_addr_base + IMF_WRITER_BITMAP_OFFSET; - inst_stage_next <= SET_WRITER_BITMAP; - inst_cnt_next <= 0; - else + inst_valid_in <= '1'; + inst_addr <= inst_addr_base + IMF_IGNORE_DEADLINE_OFFSET + 1; + inst_write_data <= std_logic_vector(inst_latch_data.ignore_deadline(0)); + inst_data_next.deadline <= inst_latch_data.ignore_deadline(0); + -- Memory Flow Control Guard + if (inst_ready_in = '1') then + if check_mask(inst_latch_data.field_flag,IMF_WRITER_BITMAP_FLAG) then + inst_cnt_next <= 6; + inst_cnt2_next <= 0; + else + -- DONE + inst_stage_next <= IDLE; + end if; + end if; + end if; + -- Writer Bitmap + when 6 => + -- XXX: Possible Worst case Path (2 Additions in same clock) + inst_valid_in <= '1'; + inst_addr <= inst_addr_base + IMF_WRITER_BITMAP_OFFSET + inst_cnt2; + inst_write_data <= inst_latch_data.writer_bitmap(inst_cnt2); + inst_data_next.writer_bitmap <= inst_latch_data.writer_bitmap; + -- Memory Flow Control Guard + if (inst_ready_in = '1') then + -- Exit Condition + if (inst_cnt2 = ENDPOINT_BITMAP_ARRAY_TYPE'length-1) then -- DONE - inst_stage_next <= IDLE; + inst_stage_next <= IDLE; + else + inst_cnt2_next <= inst_cnt2 + 1; end if; end if; when others => null; end case; when REMOVE_INSTANCE => - inst_cnt_next <= inst_cnt + 1; + -- Precondition: inst_addr_base set, inst_prev_addr_base set case (inst_cnt) is - -- Preload + -- GET Next Instance when 0 => - inst_ren <= '1'; - inst_addr_next <= inst_prev_addr_base + IMF_NEXT_ADDR_OFFSET; - -- Next Pointer (Previous Occupied Instance) + inst_valid_in <= '1'; + inst_addr <= inst_addr_base + IMF_NEXT_ADDR_OFFSET; + inst_read <= '1'; + + -- Memory Flow Control Guard + if (inst_ready_in = '1') then + inst_cnt_next <= inst_cnt + 1; + end if; + -- READ Next Instance when 1 => - -- Fix Pointer - inst_write_data <= inst_read_data; - inst_wen <= '1'; + inst_ready_out <= '1'; - inst_addr_next <= inst_addr_base + IMF_NEXT_ADDR_OFFSET; - -- Next Pointer (Current Instance) + -- Memory Flow Control Guard + if (inst_valid_out = '1') then + inst_next_addr_base_next <= inst_read_data; + inst_cnt_next <= inst_cnt + 1; + end if; + -- Next Pointer (Previous 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; + -- Point Previous instance to Next Instance (Remove current Instance from inbetween) + inst_valid_in <= '1'; + inst_addr <= inst_prev_addr_base + IMF_NEXT_ADDR_OFFSET; + inst_write_data <= inst_next_addr_base; - -- Reset - inst_data_next <= ZERO_INSTANCE_DATA; - inst_addr_base_next <= INSTANCE_MEMORY_MAX_ADDRESS; + -- Memory Flow Control Guard + if (inst_ready_in = '1') then + inst_cnt_next <= inst_cnt + 1; + end if; + -- Next Pointer (Current/Removed Instance) + when 3 => + -- Point Current Instance to Empty List Head (Make Removed Instance Head of the Empty List) + inst_valid_in <= '1'; + inst_addr <= inst_addr_base + IMF_NEXT_ADDR_OFFSET; + inst_write_data <= inst_empty_head; - -- DONE - inst_stage_next <= IDLE; + -- Memory Flow Control Guard + if (inst_ready_in = '1') then + -- Fix Empty List Head + inst_empty_head_next <= inst_addr_base; + + -- Reset + inst_data_next <= ZERO_INSTANCE_DATA; + inst_addr_base_next <= INSTANCE_MEMORY_MAX_ADDRESS; + + -- DONE + inst_stage_next <= IDLE; + end if; when others => null; end case; when UNMARK_INTANCES => - -- Precondition: - - inst_cnt_next <= inst_cnt + 1; + -- Precondition: inst_addr_base set case (inst_cnt) is - -- Preload + -- GET Next Instance when 0 => - inst_addr_next <= inst_addr_base + IMF_STATUS_INFO_OFFSET; - inst_ren <= '1'; - -- Next Pointer + inst_valid_in <= '1'; + inst_addr <= inst_addr_base + IMF_NEXT_ADDR_OFFSET; + inst_read <= '1'; + + -- Memory Flow Control Guard + if (inst_ready_in = '1') then + inst_cnt_next <= inst_cnt + 1; + end if; + -- GET Status Info when 1 => - inst_ren <= '1'; + inst_valid_in <= '1'; + inst_addr <= inst_addr_base + IMF_STATUS_INFO_OFFSET; + inst_read <= '1'; - next_inst_next <= inst_read_data; - -- Instance Status Info + -- Memory Flow Control Guard + if (inst_ready_in = '1') then + inst_cnt_next <= inst_cnt + 1; + end if; + -- READ Next Instance when 2 => - inst_write_data <= inst_read_data; - inst_write_data(MARK_FLAG) <= '0'; - inst_wen <= '1'; + inst_ready_out <= '1'; - -- Reached End of Instances - if (next_inst = INSTANCE_MEMORY_MAX_ADDRESS) then - -- DONE - inst_stage_next <= IDLE; - else - inst_addr_base_next <= next_inst; - inst_addr_next <= next_inst + IMF_NEXT_ADDR_OFFSET; - inst_cnt_next <= 0; + -- Memory Flow Control Guard + if (inst_valid_out = '1') then + inst_next_addr_base_next <= inst_read_data; + inst_cnt_next <= inst_cnt + 1; + end if; + -- READ Status Info + when 3 => + inst_ready_out <= '1'; + + -- Memory Flow Control Guard + if (inst_valid_out = '1') then + -- MARK Flag Set + if (inst_read_data(MARK_FLAG) = '1') then + -- Latch Status Info (With MARK removed) + inst_long_latch_next <= inst_read_data; + inst_long_latch_next(MARK_FLAG) <= '0'; + inst_cnt_next <= inst_cnt + 1; + else + -- End of Instances + if (inst_next_addr_base = INSTANCE_MEMORY_MAX_ADDRESS) then + -- DONE + inst_stage_next <= IDLE; + else + -- Continue + inst_addr_base <= inst_next_addr_base; + inst_cnt_next <= 0; + end if; + end if; + end if; + -- Status Info + when 4 => + inst_valid_in <= '1'; + inst_addr <= inst_addr_base + IMF_STATUS_INFO_OFFSET; + inst_write_data <= inst_long_latch; + + -- Memory Flow Control Guard + if (inst_ready_in = '1') then + -- End of Instances + if (inst_next_addr_base = INSTANCE_MEMORY_MAX_ADDRESS) then + -- DONE + inst_stage_next <= IDLE; + else + -- Continue + inst_addr_base <= inst_next_addr_base; + inst_cnt_next <= 0; + end if; end if; when others => null;