library ieee; use ieee.std_logic_1164.all; use ieee.numeric_std.all; use work.math_pkg.all; use work.rtps_package.all; use work.user_config.all; use work.rtps_config_package.all; -- TODO: Check if sample_cnt is always maintained (also with MAX_SAMPLES_PER_INSTANCE = LENGTH_UNLIMITED) entity dds_reader is generic ( ID : ID_TYPE := 0; TIME_BASED_FILTER_QOS : DURATION_TYPE := ENDPOINT_TIME_BASED_FILTER_QOS(ID); DEADLINE_QOS : DURATION_TYPE := ENDPOINT_DEADLINE_QOS(ID); MAX_INSTANCES : std_logic_vector(CDR_LONG_WIDTH-1 downto 0) := ENDPOINT_MAX_INSTANCES(ID); MAX_SAMPLES_PER_INSTANCE : std_logic_vector(CDR_LONG_WIDTH-1 downto 0) := ENDPOINT_MAX_SAMPLES_PER_INSTANCE(ID); MAX_SAMPLES : std_logic_vector(CDR_LONG_WIDTH-1 downto 0) := ENDPOINT_MAX_SAMPLES(ID); HISTORY_QOS : std_logic_vector(CDR_ENUMERATION_WIDTH-1 downto 0) := ENDPOINT_HISTORY_QOS(ID); RELIABILITY_QOS : std_logic_vector(CDR_ENUMERATION_WIDTH-1 downto 0) := ENDPOINT_RELIABILITY_QOS(ID); PRESENTATION_QOS : std_logic_vector(CDR_ENUMERATION_WIDTH-1 downto 0) := ENDPOINT_PRESENTATION_QOS(ID); DESTINATION_ORDER_QOS : std_logic_vector(CDR_ENUMERATION_WIDTH-1 downto 0) := ENDPOINT_DESTINATION_ORDER_QOS(ID); COHERENT_ACCESS : boolean := ENDPOINT_COHERENT_ACCESS(ID); ORDERED_ACCESS : boolean := ENDPOINT_ORDERED_ACCESS(ID); WITH_KEY : boolean := ENDPOINT_WITH_KEY(ID); PAYLOAD_FRAME_SIZE : natural; MAX_REMOTE_ENDPOINTS : natural := 50 ); port ( -- SYSTEM clk : in std_logic; reset : in std_logic; time : in TIME_TYPE; -- FROM RTPS ENDPOINT start_rtps : in std_logic; opcode_rtps : in HISTORY_CACHE_OPCODE_TYPE; ack_rtps : out std_logic; done_rtps : out std_logic; ret_rtps : out HISTORY_CACHE_RESPONSE_TYPE; data_in_rtps : in std_logic_vector(WORD_WIDTH-1 downto 0); valid_in_rtps : in std_logic; ready_in_rtps : out std_logic; last_word_in_rtps : in std_logic; -- TO/FROM KEY_HOLDER start_kh : out std_logic; opcode_kh : out KEY_HOLDER_OPCODE_TYPE; ack_kh : in std_logic; data_in_kh : in std_logic_vector(WORD_WIDTH-1 downto 0); valid_in_kh : in std_logic; ready_in_kh : out std_logic; last_word_in_kh : in std_logic; data_out_kh : out std_logic_vector(WORD_WIDTH-1 downto 0); valid_out_kh : out std_logic; ready_out_kh : in std_logic; last_word_out_kh : out std_logic; abort_kh : out std_logic; -- TO USER ENTITY start_dds : in std_logic; ack_dds : out std_logic; opcode_dds : in DDS_READER_OPCODE_TYPE; instance_state_dds : in std_logic_vector(INSTANCE_STATE_KIND_WIDTH-1 downto 0); view_state_dds : in std_logic_vector(VIEW_STATE_KIND_WIDTH-1 downto 0); sample_state_dds : in std_logic_vector(SAMPLE_STATE_KIND_WIDTH-1 downto 0); instance_handle_dds : in INSTANCE_HANDLE_TYPE; max_samples_dds : in std_logic_vector(MAX_SAMPLES_WIDTH-1 downto 0); get_data_dds : in std_logic; done_dds : out std_logic; return_code_dds : out std_logic_vector(RETURN_CODE_WIDTH-1 downto 0); ready_out_dds : in std_logic; valid_out_dds : out std_logic; data_out_dds : out std_logic_vector(WORD_WIDTH-1 downto 0); last_word_out_dds : out std_logic; -- Sample Info si_sample_state : out std_logic_vector(SAMPLE_STATE_KIND_WIDTH-1 downto 0); si_view_state : out std_logic_vector(VIEW_STATE_KIND_WIDTH-1 downto 0); si_instance_state : out std_logic_vector(INSTANCE_STATE_KIND_WIDTH-1 downto 0); si_source_timestamp : out TIME_TYPE; si_instance_handle : out INSTANCE_HANDLE_TYPE; si_publication_handle : out PUBLICATION_HANDLE_TYPE; si_disposed_generation_count : out std_logic_vector(DISPOSED_GENERATION_COUNT_WIDTH-1 downto 0); si_no_writers_generation_count : out std_logic_vector(NO_WRITERS_GENERATION_COUNT_WIDTH-1 downto 0); si_sample_rank : out std_logic_vector(SAMPLE_RANK_WIDTH-1 downto 0); si_generation_rank : out std_logic_vector(GENERATION_RANK_WIDTH-1 downto 0); si_absolute_generation_rank : out std_logic_vector(ABSOLUTE_GENERATION_COUNT_WIDTH-1 downto 0); si_valid_data : out std_logic; si_valid : out std_logic; si_ack : in std_logic; eoc : out std_logic; -- Communication Status status : out std_logic_vector(STATUS_KIND_WIDTH-1 downto 0) ); end entity; architecture arch of dds_reader is --*****CONSTANT DECLARATION***** -- NOTE: Because we need to first determine the Instance before making the ACCEPT/REJECT/DROP decision -- we need to latch the cache change first, calculate the Key Hash if necessary, fetch the associated -- Instance, and then decide on it. This in effect means that we always need an extra slot in sample and -- payload memory that is only used as a latch. -- *SAMPLE MEMORY* -- 4-Byte Word Size of a Sample Info Entry in Memory function gen_sample_frame_size(WITH_KEY : boolean) return natural is variable ret : natural := 0; begin if (WITH_KEY) then return 11; else return 10; end if; end function; constant SAMPLE_FRAME_SIZE : natural := gen_sample_frame_size(WITH_KEY); -- Sample Info Memory Size in 4-Byte Words constant SAMPLE_MEMORY_SIZE : natural := to_integer(unsigned(MAX_SAMPLES)+1) * SAMPLE_FRAME_SIZE; -- Sample Info Memory Address Width constant SAMPLE_MEMORY_ADDR_WIDTH : natural := log2c(SAMPLE_MEMORY_SIZE); -- Highest Sample Info Memory Address constant SAMPLE_MEMORY_MAX_ADDRESS : unsigned(SAMPLE_MEMORY_ADDR_WIDTH-1 downto 0) := to_unsigned(SAMPLE_MEMORY_SIZE-1, SAMPLE_MEMORY_ADDR_WIDTH); -- Highest Sample Info Frame Address constant MAX_SAMPLE_ADDRESS : unsigned(SAMPLE_MEMORY_ADDR_WIDTH-1 downto 0) := SAMPLE_MEMORY_MAX_ADDRESS - SAMPLE_FRAME_SIZE + 1; -- Address pointing to the beginning of the first Sample Data Frame constant FIRST_SAMPLE_ADDRESS : unsigned(SAMPLE_MEMORY_ADDR_WIDTH-1 downto 0) := (others => '0'); -- *PAYLOAD MEMORY* -- Payload Memory Size in 4-Byte Words constant PAYLOAD_MEMORY_SIZE : natural := to_integer(unsigned(MAX_SAMPLES)+1) * PAYLOAD_FRAME_SIZE; -- Payload Memory Address Width constant PAYLOAD_MEMORY_ADDR_WIDTH : natural := log2c(PAYLOAD_MEMORY_SIZE); -- Highest Payload Memory Address constant PAYLOAD_MEMORY_MAX_ADDRESS : unsigned(PAYLOAD_MEMORY_ADDR_WIDTH-1 downto 0) := to_unsigned(PAYLOAD_MEMORY_SIZE-1, PAYLOAD_MEMORY_ADDR_WIDTH); -- Highest Payload Frame Address constant MAX_PAYLOAD_ADDRESS : unsigned(PAYLOAD_MEMORY_ADDR_WIDTH-1 downto 0) := PAYLOAD_MEMORY_MAX_ADDRESS - PAYLOAD_FRAME_SIZE + 1; -- Address pointing to the beginning of the first Payload Data Frame constant FIRST_PAYLOAD_ADDRESS : unsigned(PAYLOAD_MEMORY_ADDR_WIDTH-1 downto 0) := (others => '0'); -- *INSTANCE MEMORY* -- 4-Byte Word Size of a Instance Entry in Memory function gen_inst_frame_size(time_based_filter : DURATION_TYPE) return natural is variable ret : natural := 0; begin if (time_based_filter = DURATION_ZERO) then return 9 + round_div(MAX_REMOTE_ENDPOINTS, WORD_WIDTH); else return 11 + round_div(MAX_REMOTE_ENDPOINTS, WORD_WIDTH); end if; end function; constant INSTANCE_FRAME_SIZE : natural := gen_inst_frame_size(TIME_BASED_FILTER_QOS); -- Instance Memory Size in 4-Byte Words constant INSTANCE_MEMORY_SIZE : natural := to_integer(unsigned(MAX_INSTANCES)) * INSTANCE_FRAME_SIZE; -- Instance Memory Address Width constant INSTANCE_MEMORY_ADDR_WIDTH : natural := log2c(INSTANCE_MEMORY_SIZE); -- Highest Instance Memory Address constant INSTANCE_MEMORY_MAX_ADDRESS: unsigned(INSTANCE_MEMORY_ADDR_WIDTH-1 downto 0) := to_unsigned(INSTANCE_MEMORY_SIZE-1, INSTANCE_MEMORY_ADDR_WIDTH); -- Highest Instance Frame Address constant MAX_INSTANCE_ADDRESS : unsigned(INSTANCE_MEMORY_ADDR_WIDTH-1 downto 0) := INSTANCE_MEMORY_MAX_ADDRESS - INSTANCE_FRAME_SIZE + 1; -- Address pointing to the beginning of the first Instance Data Frame constant FIRST_INSTANCE_ADDRESS : unsigned(INSTANCE_MEMORY_ADDR_WIDTH-1 downto 0) := (others => '0'); -- *SAMPLE MEMORY FRAME FIELD OFFSETS* -- 4-Byte Word Offsets to Beginning of Respective Fields in the Endpoint Memory Frame constant SMF_STATUS_INFO_OFFSET : natural := 0; constant SMF_TIMESTAMP_OFFSET : natural := 1; constant SMF_LIFESPAN_DEADLINE_OFFSET : natural := 3; constant SMF_PAYLOAD_ADDR_OFFSET : natural := 5; constant SMF_INSTANCE_ADDR_OFFSET : natural := 6; function gen_smf_disposed_gen_cnt_offset(WITH_KEY : boolean) return natural is variable ret : natural := 0; begin ret := (SMF_INSTANCE_ADDR_OFFSET + 1) when WITH_KEY else SMF_INSTANCE_ADDR_OFFSET; return ret; end function; constant SMF_DISPOSED_GEN_CNT_OFFSET : natural := gen_smf_disposed_gen_cnt_offset(WITH_KEY); constant SMF_NO_WRITERS_GEN_CNT_OFFSET : natural := SMF_DISPOSED_GEN_CNT_OFFSET + 1; constant SMF_PREV_ADDR_OFFSET : natural := SMF_NO_WRITERS_GEN_CNT_OFFSET + 1; constant SMF_NEXT_ADDR_OFFSET : natural := SMF_PREV_ADDR_OFFSET + 1; -- *PAYLOAD MEMORY FRAME FIELD OFFSETS* -- 4-Byte Word Offsets to Beginning of Respective Fields in the Endpoint Memory Frame constant PMF_NEXT_ADDR_OFFSET : natural := 0; constant PMF_PAYLOAD_OFFSET : natural := 1; -- *INSTANCE MEMORY FRAME FIELD OFFSETS* -- 4-Byte Word Offsets to Beginning of Respective Fields in the Endpoint Memory Frame constant IMF_NEXT_ADDR_OFFSET : natural := 0; constant IMF_KEY_HASH_OFFSET : natural := 1; constant IMF_STATUS_INFO_OFFSET : natural := 5; constant IMF_SAMPLE_CNT_OFFSET : natural := 6; constant IMF_DISPOSED_GEN_CNT_OFFSET : natural := 7; constant IMF_NO_WRITERS_GEN_CNT_OFFSET : natural := 8; constant IMF_IGNORE_DEADLINE_OFFSET : natural := 9; function gen_imf_writer_bitmap_offset(time_based_filter : DURATION_TYPE) return natural is variable ret : natural := 0; begin ret := IMF_IGNORE_DEADLINE_OFFSET+2 when (time_based_filter /= DURATION_ZERO) else IMF_IGNORE_DEADLINE_OFFSET; return ret; end function; constant IMF_WRITER_BITMAP_OFFSET : natural := gen_imf_writer_bitmap_offset(TIME_BASED_FILTER_QOS); -- *INSTANCE MEMORY FRAME FIELD FLAGS* -- Flags mapping to the respective Endpoint Memory Frame Fields 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'); --*****TYPE DECLARATION***** -- FSM states. Explained below in detail type STAGE_TYPE is (IDLE, RETURN_DDS, RETURN_RTPS, ADD_SAMPLE_INFO, ADD_PAYLOAD_ADDRESS, ADD_PAYLOAD, NEXT_PAYLOAD_SLOT, ALIGN_PAYLOAD, GET_KEY_HASH, INITIATE_INSTANCE_SEARCH, FILTER_STAGE, UPDATE_INSTANCE, FINALIZE_PAYLOAD, PRE_SAMPLE_FINALIZE, FIND_POS, FIX_POINTERS, FINALIZE_SAMPLE, GENERATE_SAMPLE, GET_OLDEST_SAMPLE_INSTANCE, FIND_OLDEST_INST_SAMPLE, REMOVE_SAMPLE, POST_SAMPLE_REMOVE, SKIP_AND_RETURN, REMOVE_WRITER, REMOVE_STALE_INSTANCE, GET_NEXT_SAMPLE, PRE_CALCULATE, FINALIZE_SAMPLE_INFO, GET_PAYLOAD, FIND_NEXT_INSTANCE, CHECK_INSTANCE, CHECK_LIFESPAN, PROCESS_PENDING_SAMPLE_GENERATION, GET_SAMPLE_REJECTED_STATUS, GET_REQUESTED_DEADLINE_MISSED_STATUS, CHECK_DEADLINE, RESET_SAMPLE_MEMORY, RESET_PAYLOAD_MEMORY); -- Instance Memory FSM states. Explained below in detail type INST_STAGE_TYPE is (IDLE, SEARCH_INSTANCE_HASH, SEARCH_INSTANCE_ADDR, GET_NEXT_INSTANCE, GET_INSTANCE_DATA, FIND_POS, INSERT_INSTANCE, UPDATE_INSTANCE, REMOVE_INSTANCE, UNMARK_INSTANCES, RESET_MEMORY); -- *Instance Memory Opcodes* -- OPCODE DESCRIPTION -- SEARCH_INSTANCE_HASH Search Instance based on Key Hash pointed by "key_hash". -- Set "inst_addr_base" to Base Address of found Instance, of INSTANCE_MEMORY_MAX_ADDRESS if nothing found. -- "inst_data" contains Instance Data according to "inst_mem_fields". -- SEARCH_INSTANCE_ADDR Search Instance based on Instance Pointer pointed by "inst_addr_update". -- Set "inst_addr_base" to "inst_addr_update" -- "inst_data" contains Instance Data according to "inst_mem_fields". -- INSERT_INSTANCE Insert Instance to memory. The Instance is inserted in Key Hash Numerical Order. -- UPDATE_INSTANCE Update Instance Data pointed by "inst_addr_base" according to "inst_mem_fields" -- GET_FIRST_INSTANCE Get Instance Data of first Instance (Instance with smallest Key Hash Numerical Order) according to "inst_mem_fields". -- Set "inst_addr_base" to Address of Instance or INSTANCE_MEMORY_MAX_ADDRESS if no Instance in Memory. -- GET_NEXT_INSTANCE Get Instance Data of next Instance (from the Instance pointed by "inst_addr_base") according to "inst_mem_fields". -- Set "inst_addr_base" to Address of Instance or INSTANCE_MEMORY_MAX_ADDRESS if no other Instance in Memory. -- REMOVE_INSTANCE Remove Instance pointed by "inst_addr_base". -- GET_INSTANCE Get Data of Instance pointed by "inst_addr_update" according to "inst_mem_fields". -- Already fetched Data of the Participant is not modified. -- UNMARK_INSTANCES Reset the MARK_FLAG of all Instances in Memory. type INSTANCE_OPCODE_TYPE is (NOP, SEARCH_INSTANCE_HASH, SEARCH_INSTANCE_ADDR, INSERT_INSTANCE, UPDATE_INSTANCE, GET_FIRST_INSTANCE, GET_NEXT_INSTANCE, REMOVE_INSTANCE, GET_INSTANCE, UNMARK_INSTANCES); type WRITER_BITMAP_ARRAY_TYPE is array (0 to round_div(MAX_REMOTE_ENDPOINTS, WORD_WIDTH)-1) of std_logic_vector(0 to WORD_WIDTH-1); constant ZERO_WRITER_BITMAP_ARRAY : WRITER_BITMAP_ARRAY_TYPE := (others => (others => '0')); constant WRITER_BITMAP_WIDTH : natural := WRITER_BITMAP_ARRAY_TYPE'length*WORD_WIDTH; -- Record of Instance Data type INSTANCE_DATA_TYPE is record key_hash : KEY_HASH_TYPE; status_info : std_logic_vector(WORD_WIDTH-1 downto 0); sample_cnt : unsigned(WORD_WIDTH-1 downto 0); disposed_gen_cnt : unsigned(WORD_WIDTH-1 downto 0); no_writers_gen_cnt : unsigned(WORD_WIDTH-1 downto 0); ignore_deadline : TIME_TYPE; writer_bitmap : WRITER_BITMAP_ARRAY_TYPE; end record; -- Zero initialized Endpoint Data constant ZERO_INSTANCE_DATA : INSTANCE_DATA_TYPE := ( key_hash => (others => (others => '0')), status_info => (others => '0'), sample_cnt => (others => '0'), disposed_gen_cnt => (others => '0'), no_writers_gen_cnt => (others => '0'), ignore_deadline => TIME_INVALID, writer_bitmap => ZERO_WRITER_BITMAP_ARRAY ); -- Instance Data Latch used as temporal cache by Instance Memory FSM type INST_LATCH_DATA_TYPE is record key_hash : KEY_HASH_TYPE; status_info : std_logic_vector(CDR_LONG_WIDTH-1 downto 0); sample_cnt : unsigned(CDR_LONG_WIDTH-1 downto 0); gen_cnt : unsigned(CDR_LONG_WIDTH-1 downto 0); deadline : TIME_TYPE; writer_bitmap : WRITER_BITMAP_ARRAY_TYPE; field_flags : std_logic_vector(0 to IMF_FLAG_WIDTH-1); addr : unsigned(INSTANCE_MEMORY_ADDR_WIDTH-1 downto 0); end record; -- Zero initialized Instance Data Latch constant ZERO_INST_LATCH_DATA : INST_LATCH_DATA_TYPE := ( key_hash => (others => (others => '0')), status_info => (others => '0'), sample_cnt => (others => '0'), gen_cnt => (others => '0'), deadline => TIME_INVALID, writer_bitmap => ZERO_WRITER_BITMAP_ARRAY, field_flags => (others => '0'), addr => (others => '0') ); --*****SIGNAL DECLARATION -- *SAMPLE MEMORY CONNECTION SIGNALS* 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'; -- *PAYLOAD MEMORY CONNECTION SIGNALS* 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'; -- *INSTANCE MEMORY CONNECTION SIGNALS* signal inst_addr : unsigned(INSTANCE_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'; -- *MAIN PROCESS* -- FSM state signal stage, stage_next : STAGE_TYPE := IDLE; -- General Purpose Counter signal cnt, cnt_next : natural range 0 to 18 := 0; -- Counter used to read/write Payload Fames signal cnt2, cnt2_next : natural range 0 to PAYLOAD_FRAME_SIZE := 0; -- Counter used to read/write Payload Fames signal cnt3, cnt3_next : natural range 0 to PAYLOAD_FRAME_SIZE := 0; -- Head of Empty Sample List signal empty_sample_list_head, empty_sample_list_head_next : unsigned(SAMPLE_MEMORY_ADDR_WIDTH-1 downto 0) := (others => '0'); -- Tail of Empty Sample List signal empty_sample_list_tail, empty_sample_list_tail_next : unsigned(SAMPLE_MEMORY_ADDR_WIDTH-1 downto 0) := (others => '0'); -- Head of Empty Payload List signal empty_payload_list_head, empty_payload_list_head_next : unsigned(PAYLOAD_MEMORY_ADDR_WIDTH-1 downto 0) := (others => '0'); -- Oldest Sample (Head of Occupied Sample List) signal oldest_sample, oldest_sample_next : unsigned(SAMPLE_MEMORY_ADDR_WIDTH-1 downto 0) := (others => '0'); -- Newest Sample (Tail of Occupied Sample List) signal newest_sample, newest_sample_next : unsigned(SAMPLE_MEMORY_ADDR_WIDTH-1 downto 0) := (others => '0'); -- Highest Timestamp of all READ Samples signal last_read_ts, last_read_ts_next : TIME_TYPE := TIME_INVALID; -- Denotes if the oldest Sample should be removed signal remove_oldest_sample, remove_oldest_sample_next : std_logic := '0'; -- Denotes if the oldest sample of the Instance with 'key_hash' should be removed signal remove_oldest_inst_sample, remove_oldest_inst_sample_next : std_logic := '0'; -- Remote Writer ID signal writer_id, writer_id_next : natural range 0 to MAX_REMOTE_ENDPOINTS-1 := 0; -- Key Hash Latch signal key_hash, key_hash_next : KEY_HASH_TYPE := HANDLE_NIL; -- RTPS Return Code Latch signal rtps_return_code_latch, rtps_return_code_latch_next : HISTORY_CACHE_RESPONSE_TYPE := ERROR; -- DDS Return Code Latch signal dds_return_code_latch, dds_return_code_latch_next : std_logic_vector(RETURN_CODE_WIDTH-1 downto 0) := RETCODE_ERROR; -- Source Timestamp Latch signal ts_latch, ts_latch_next : TIME_TYPE := TIME_INVALID; -- Lifespan Latch signal lifespan, lifespan_next : TIME_TYPE := TIME_INVALID; -- Sample Status Info Latch signal sample_status_info, sample_status_info_next : std_logic_vector(CDR_LONG_WIDTH-1 downto 0) := (others => '0'); -- General Purpose Payload Pointer signal payload_addr_latch_1, payload_addr_latch_1_next : unsigned(PAYLOAD_MEMORY_ADDR_WIDTH-1 downto 0) := (others => '0'); -- General Purpose Payload Pointer signal payload_addr_latch_2, payload_addr_latch_2_next : unsigned(PAYLOAD_MEMORY_ADDR_WIDTH-1 downto 0) := (others => '0'); -- General Purpose Sample Pointer signal sample_addr_latch_1, sample_addr_latch_1_next : unsigned(SAMPLE_MEMORY_ADDR_WIDTH-1 downto 0) := (others => '0'); -- General Purpose Sample Pointer signal sample_addr_latch_2, sample_addr_latch_2_next : unsigned(SAMPLE_MEMORY_ADDR_WIDTH-1 downto 0) := (others => '0'); -- General Purpose Sample Pointer signal sample_addr_latch_3, sample_addr_latch_3_next : unsigned(SAMPLE_MEMORY_ADDR_WIDTH-1 downto 0) := (others => '0'); -- General Purpose Sample Pointer signal sample_addr_latch_4, sample_addr_latch_4_next : unsigned(SAMPLE_MEMORY_ADDR_WIDTH-1 downto 0) := (others => '0'); -- General Purpose Sample Pointer signal sample_addr_latch_5, sample_addr_latch_5_next : unsigned(SAMPLE_MEMORY_ADDR_WIDTH-1 downto 0) := (others => '0'); -- General Purpose Instance Pointer signal inst_addr_latch_1, inst_addr_latch_1_next : unsigned(INSTANCE_MEMORY_ADDR_WIDTH-1 downto 0) := (others => '0'); -- General Purpose Instance Pointer signal inst_addr_latch_2, inst_addr_latch_2_next : unsigned(INSTANCE_MEMORY_ADDR_WIDTH-1 downto 0) := (others => '0'); -- General Purpose Long Latch signal long_latch, long_latch_next : std_logic_vector(CDR_LONG_WIDTH-1 downto 0) := (others => '0'); -- Signal used to pass Writer Bitmaps to Instance Memory Process signal writer_bitmap : WRITER_BITMAP_ARRAY_TYPE := ZERO_WRITER_BITMAP_ARRAY; -- Signal used to pass Sample Status Infos to Instance Memory Process signal status_info_update : std_logic_vector(CDR_LONG_WIDTH-1 downto 0) := (others => '0'); -- Signal used to pass Generation Counters to the Instance Memory Process signal gen_cnt : unsigned(CDR_LONG_WIDTH-1 downto 0) := (others => '0'); -- Signal used to pass TIMEs to the Instance Memory Process signal deadline : TIME_TYPE := TIME_INVALID; -- Signal containing the relevant Instance Memory Frame Fields of the Instance Memory Operation signal inst_mem_fields : std_logic_vector(0 to IMF_FLAG_WIDTH-1) := (others => '0'); -- Signal used to pass Instance Pointers to the Instance Memory Process signal inst_addr_update : unsigned(INSTANCE_MEMORY_ADDR_WIDTH-1 downto 0) := (others => '0'); -- Signal used to pass Sample Counts to the Instance Memory Process signal sample_cnt : unsigned(CDR_LONG_WIDTH-1 downto 0) := (others => '0'); -- Signals start of Instance Memory Operation signal inst_op_start : std_logic := '0'; -- Opcode of Instance Memory Operation (Valid only when inst_op_start is high) signal inst_opcode : INSTANCE_OPCODE_TYPE := NOP; -- Signals the end of an Instance Memory Operation signal inst_op_done : std_logic := '0'; -- Time of next Sample Lifespan Check signal lifespan_time, lifespan_time_next : TIME_TYPE := TIME_ZERO; -- Signifies if a Lifespan Check is in progress signal is_lifespan_check, is_lifespan_check_next : std_logic := '0'; -- Sample State Latch signal sample_state, sample_state_next : std_logic_vector(SAMPLE_STATE_KIND_WIDTH-1 downto 0) := (others => '0'); -- View State Latch signal view_state, view_state_next : std_logic_vector(VIEW_STATE_KIND_WIDTH-1 downto 0) := (others => '0'); -- Instance State Latch signal instance_state, instance_state_next : std_logic_vector(INSTANCE_STATE_KIND_WIDTH-1 downto 0) := (others => '0'); -- Instance Handle Latch signal instance_handle, instance_handle_next : INSTANCE_HANDLE_TYPE := HANDLE_NIL; -- Max Samples Latch signal max_samples_latch, max_samples_latch_next : unsigned(MAX_SAMPLES_WIDTH-1 downto 0) := (others => '0'); -- Denotes the current length of the Collection signal collection_cnt, collection_cnt_next : unsigned(MAX_SAMPLES_WIDTH-1 downto 0) := (others => '0'); -- Denotes the current pre-calculated length of the Collection signal collection_cnt_max, collection_cnt_max_next : unsigned(MAX_SAMPLES_WIDTH-1 downto 0) := (others => '0'); -- Denotes the Generation Rank (For a collection of length collection_cnt_max) signal collection_generation_rank, collection_generation_rank_next : unsigned(GENERATION_RANK_WIDTH-1 downto 0) := (others => '0'); -- Number of NOT_ALIVE->ALIVE Transitions during reception of selected Sample signal cur_generation_rank, cur_generation_rank_next : unsigned(GENERATION_RANK_WIDTH-1 downto 0) := (others => '0'); -- Denotes if a TAKE operation is in progress signal is_take, is_take_next : std_logic := '0'; -- NOTE: We use this signal to prevent the costly Instance Marking in the case that we only need to ouptput samples of one Instance. -- Denotes if the READ/TAKE operation applies to a single Instance signal single_instance, single_instance_next : std_logic := '0'; -- Denotes if the marks on Instances should be reset signal unmark_instances_flag, unmark_instances_flag_next : std_logic := '0'; -- Denotes if the READ/TAKE operation does not apply to a specific Instance signal dynamic_next_instance, dynamic_next_instance_next : std_logic := '0'; -- Signal containing the number of currently stale Instances signal stale_inst_cnt, stale_inst_cnt_next : natural range 0 to to_integer(unsigned(MAX_INSTANCES))-1 := 0; -- Test signal used for testbench synchronisation signal idle_sig : std_logic := '0'; -- Signal denoting if the PRE_CALCULATE stage was run for the current instance signal pre_calculated, pre_calculated_next : std_logic := '0'; -- Disposed Generation Count Latch signal dis_gen_cnt_latch, dis_gen_cnt_latch_next : unsigned(WORD_WIDTH-1 downto 0) := (others => '0'); -- No Writers Generation Count Latch signal no_w_gen_cnt_latch, no_w_gen_cnt_latch_next : unsigned(WORD_WIDTH-1 downto 0) := (others => '0'); -- Denotes if a newer sample of the same Instance exists signal newer_inst_sample, newer_inst_sample_next : std_logic := '0'; -- Denotes if a new Instance is added signal new_inst, new_inst_next : std_logic := '0'; -- Triggers Sample Generation signal trigger_sample_gen, trigger_sample_gen_next : std_logic := '0'; -- Waits for Sample Removal (MAX_SAMPLES Limit lift) to trigger Sample Generation signal wait_for_sample_removal, wait_for_sample_removal_next : std_logic := '0'; -- *COMMUNICATION STATUS* signal status_sig, status_sig_next : std_logic_vector(STATUS_KIND_WIDTH-1 downto 0) := (others => '0'); -- SAMPLE REJECT STATUS signal sample_rej_cnt, sample_rej_cnt_next : unsigned(SAMPLE_REJECTED_STATUS_COUNT_WIDTH-1 downto 0) := (others => '0'); signal sample_rej_cnt_change, sample_rej_cnt_change_next : unsigned(SAMPLE_REJECTED_STATUS_COUNT_WIDTH-1 downto 0) := (others => '0'); signal sample_rej_last_reason, sample_rej_last_reason_next : std_logic_vector(CDR_ENUMERATION_WIDTH-1 downto 0) := (others =>'0'); signal sample_rej_last_inst, sample_rej_last_inst_next : INSTANCE_HANDLE_TYPE := (others => (others => '0')); -- REQUESTED DEADLINE MISSED STATUS -- Time of next Deadline Miss Check signal deadline_time, deadline_time_next : TIME_TYPE := TIME_ZERO; signal deadline_miss_cnt, deadline_miss_cnt_next : unsigned(REQUESTED_DEADLINE_MISSED_STATUS_COUNT_WIDTH-1 downto 0) := (others => '0'); signal deadline_miss_cnt_change, deadline_miss_cnt_change_next : unsigned(REQUESTED_DEADLINE_MISSED_STATUS_COUNT_WIDTH-1 downto 0) := (others => '0'); signal deadline_miss_last_inst, deadline_miss_last_inst_next : INSTANCE_HANDLE_TYPE := (others => (others => '0')); -- *SAMPLE INFO* signal si_sample_state_sig, si_sample_state_sig_next : std_logic_vector(SAMPLE_STATE_KIND_WIDTH-1 downto 0) := (others => '0'); signal si_view_state_sig, si_view_state_sig_next : std_logic_vector(VIEW_STATE_KIND_WIDTH-1 downto 0) := (others => '0'); signal si_instance_state_sig, si_instance_state_sig_next : std_logic_vector(INSTANCE_STATE_KIND_WIDTH-1 downto 0) := (others => '0'); signal si_source_timestamp_sig, si_source_timestamp_sig_next : TIME_TYPE := TIME_INVALID; signal si_instance_handle_sig, si_instance_handle_sig_next : INSTANCE_HANDLE_TYPE := HANDLE_NIL; signal si_publication_handle_sig, si_publication_handle_sig_next : PUBLICATION_HANDLE_TYPE := (others => (others => '0')); signal si_disposed_generation_count_sig, si_disposed_generation_count_sig_next : std_logic_vector(DISPOSED_GENERATION_COUNT_WIDTH-1 downto 0) := (others => '0'); signal si_no_writers_generation_count_sig, si_no_writers_generation_count_sig_next : std_logic_vector(NO_WRITERS_GENERATION_COUNT_WIDTH-1 downto 0) := (others => '0'); signal si_sample_rank_sig, si_sample_rank_sig_next : unsigned(SAMPLE_RANK_WIDTH-1 downto 0) := (others => '0'); signal si_generation_rank_sig, si_generation_rank_sig_next : unsigned(GENERATION_RANK_WIDTH-1 downto 0) := (others => '0'); signal si_absolute_generation_rank_sig, si_absolute_generation_rank_sig_next : unsigned(ABSOLUTE_GENERATION_COUNT_WIDTH-1 downto 0) := (others => '0'); signal si_valid_data_sig, si_valid_data_sig_next : std_logic := '0'; signal si_valid_sig, si_valid_sig_next : std_logic := '0'; signal eoc_sig, eoc_sig_next : std_logic := '0'; -- *INSTANCE MEMORY PROCESS* -- Instance Memory FSM state signal inst_stage, inst_stage_next : INST_STAGE_TYPE := IDLE; -- Pointer to current relevant Instance Memory Frame Address signal inst_addr_base, inst_addr_base_next : unsigned(INSTANCE_MEMORY_ADDR_WIDTH-1 downto 0) := (others => '0'); -- Pointer to next Instance Memory Frame Address signal inst_next_addr_base, inst_next_addr_base_next : unsigned(INSTANCE_MEMORY_ADDR_WIDTH-1 downto 0) := (others => '0'); -- Pointer to previous Instacne Memory Address signal inst_prev_addr_base, inst_prev_addr_base_next : unsigned(INSTANCE_MEMORY_ADDR_WIDTH-1 downto 0) := (others => '0'); -- Head of Empty Instance List signal inst_empty_head, inst_empty_head_next : unsigned(INSTANCE_MEMORY_ADDR_WIDTH-1 downto 0) := (others => '0'); -- Head of Occupied Instance List signal inst_occupied_head, inst_occupied_head_next : unsigned(INSTANCE_MEMORY_ADDR_WIDTH-1 downto 0) := (others => '0'); -- Latch for Instance Data from main process signal inst_latch_data, inst_latch_data_next : INST_LATCH_DATA_TYPE := ZERO_INST_LATCH_DATA; -- NOTE: The next signal is driven by the inst_ctrl_prc. In case WITH_KEY is FALSE, no inst_ctrl_prc is generated and the inst_data is -- set by the main process directly by drivng the next2 signal. The sync_prc is responsible for latching the corrct next signal. -- Latch for Instance Data from memory signal inst_data, inst_data_next, inst_data_next2 : INSTANCE_DATA_TYPE := ZERO_INSTANCE_DATA; -- General Purpose Counter signal inst_cnt, inst_cnt_next : natural range 0 to 21 := 0; -- Counter used to read/write the Writer Bitmap signal inst_cnt2, inst_cnt2_next : natural range 0 to WRITER_BITMAP_ARRAY_TYPE'length := 0; -- General Purpose Long Latch signal inst_long_latch, inst_long_latch_next : std_logic_vector(CDR_LONG_WIDTH-1 downto 0) := (others => '0'); -- Instance Memory Flag Array denoting which inst_data Fields are up-to-date with the respective fields of the Instance (Pointed by inst_addr_base) signal current_imf, current_imf_next : std_logic_vector(0 to IMF_FLAG_WIDTH-1) := (others => '0'); --*****ALIAS DECLARATION***** alias prev_sample : unsigned(SAMPLE_MEMORY_ADDR_WIDTH-1 downto 0) is sample_addr_latch_1; alias prev_sample_next : unsigned(SAMPLE_MEMORY_ADDR_WIDTH-1 downto 0) is sample_addr_latch_1_next; alias sel_sample : unsigned(SAMPLE_MEMORY_ADDR_WIDTH-1 downto 0) is sample_addr_latch_1; alias sel_sample_next : unsigned(SAMPLE_MEMORY_ADDR_WIDTH-1 downto 0) is sample_addr_latch_1_next; alias next_sample : unsigned(SAMPLE_MEMORY_ADDR_WIDTH-1 downto 0) is sample_addr_latch_2; alias next_sample_next : unsigned(SAMPLE_MEMORY_ADDR_WIDTH-1 downto 0) is sample_addr_latch_2_next; alias cur_sample : unsigned(SAMPLE_MEMORY_ADDR_WIDTH-1 downto 0) is sample_addr_latch_3; alias cur_sample_next : unsigned(SAMPLE_MEMORY_ADDR_WIDTH-1 downto 0) is sample_addr_latch_3_next; alias sample_p1 : unsigned(SAMPLE_MEMORY_ADDR_WIDTH-1 downto 0) is sample_addr_latch_4; alias sample_p1_next : unsigned(SAMPLE_MEMORY_ADDR_WIDTH-1 downto 0) is sample_addr_latch_4_next; alias sample_p2 : unsigned(SAMPLE_MEMORY_ADDR_WIDTH-1 downto 0) is sample_addr_latch_5; alias sample_p2_next : unsigned(SAMPLE_MEMORY_ADDR_WIDTH-1 downto 0) is sample_addr_latch_5_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_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; alias next_inst_next : unsigned(INSTANCE_MEMORY_ADDR_WIDTH-1 downto 0) is inst_addr_latch_2_next; alias first_payload : unsigned(PAYLOAD_MEMORY_ADDR_WIDTH-1 downto 0) is payload_addr_latch_2; alias first_payload_next : unsigned(PAYLOAD_MEMORY_ADDR_WIDTH-1 downto 0) is payload_addr_latch_2_next; alias has_data : std_logic is sample_status_info(SSI_DATA_FLAG); alias has_key_hash : std_logic is sample_status_info(SSI_KEY_HASH_FLAG); -- *FUNCTION DECLARATION* function from_writer_bitmap_array (input : WRITER_BITMAP_ARRAY_TYPE) return std_logic_vector is variable ret : std_logic_vector(0 to WRITER_BITMAP_WIDTH-1) := (others => '0'); begin for i in 0 to input'length-1 loop ret(i*WORD_WIDTH to ((i+1)*WORD_WIDTH)-1) := input(i); end loop; return ret; end function; function to_writer_bitmap_array (input : std_logic_vector(0 to WRITER_BITMAP_WIDTH-1)) return WRITER_BITMAP_ARRAY_TYPE is variable ret : WRITER_BITMAP_ARRAY_TYPE := ZERO_WRITER_BITMAP_ARRAY; begin for i in 0 to ret'length-1 loop ret(i) := input(i*WORD_WIDTH to ((i+1)*WORD_WIDTH)-1); end loop; return ret; end function; -- This function caps the range of a natural. -- This is needed, because during simulation some values may be outside the range due to delta time delays. function cap_range(input : in integer; max : in natural) return natural is begin if (input > max and SIMULATION_FLAG) then return max; elsif (input < 0 and SIMULATION_FLAG) then return 0; else return input; end if; end function; begin --*****COMPONENT INSTANTIATION***** 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, MAX_BURST_LENGTH => SAMPLE_FRAME_SIZE ) port map ( 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_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, MAX_BURST_LENGTH => PAYLOAD_FRAME_SIZE ) port map ( clk => clk, reset => reset or payload_abort_read, addr => std_logic_vector(payload_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 ); gen_instance_mem_ctrl_inst : if WITH_KEY generate 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, MAX_BURST_LENGTH => INSTANCE_FRAME_SIZE ) port map ( clk => clk, reset => reset or inst_abort_read, addr => std_logic_vector(inst_addr), read => inst_read, ready_in => inst_ready_in, valid_in => inst_valid_in, data_in => inst_write_data, ready_out => inst_ready_out, valid_out => inst_valid_out, data_out => inst_read_data ); end generate; si_sample_state <= si_sample_state_sig; si_view_state <= si_view_state_sig; si_instance_state <= si_instance_state_sig; si_source_timestamp <= si_source_timestamp_sig; si_instance_handle <= si_instance_handle_sig; si_publication_handle <= si_publication_handle_sig; si_disposed_generation_count <= si_disposed_generation_count_sig; si_no_writers_generation_count <= si_no_writers_generation_count_sig; si_sample_rank <= std_logic_vector(si_sample_rank_sig); si_generation_rank <= std_logic_vector(si_generation_rank_sig); si_absolute_generation_rank <= std_logic_vector(si_absolute_generation_rank_sig); si_valid_data <= si_valid_data_sig; si_valid <= si_valid_sig; eoc <= eoc_sig; status <= status_sig; -- *Main State Machine* -- STATE DESCRIPTION -- IDLE Idle State. Initiates Deadline Miss Checks, Lifespan Expiry Checks, RTPS Operation handling, and DDS Operation handling, in that priority order. -- RETURN_DDS Return latched DDS Return Code -- RETURN_RTPS Return latched RTPS Return Code -- ADD_SAMPLE_INFO Latch and store Cache Change (pre-payload) -- ADD_PAYLOAD_ADDRESS Store payload pointer. -- ADD_PAYLOAD Push payload to memory and key hash generator (as needed) -- NEXT_PAYLOAD_SLOT Get pointer to next empty payload slot -- ALIGN_PAYLOAD Store the offset of the actual payload in the last address of the last payload slot. -- GET_KEY_HASH Fetch the calculated key hash from the Key Hash Generator -- INITIATE_INSTANCE_SEARCH Initiate Instance Search Memory Operation. This state is used to start the Search operation as soon as the required data is available -- FILTER_STAGE This state decides if the RTPS Cache Change is accepted, dropped, or rejected. It also decides what sample (if any) has to be removed. -- UPDATE_INSTANCE Update the Data of the Instance of the received sample (Cache Change) -- FINALIZE_PAYLOAD Finalize the payload addition (Update pointers) -- PRE_SAMPLE_FINALIZE Store Sample Info based on Instance Data -- FIND_POS Find Sample List position based on DESTINATION_ORDER_QOS -- FIX_POINTERS Update the List Pointers of the inserted Sample neighbours (First Step of Sample Addition Finalization) -- FINALIZE_SAMPLE Update inserted sample and list pointers. (Second Step of Sample Addition Finalization) -- GENERATE_SAMPLE Generate a NOT_ALIVE_NO_WRITERS Sample -- GET_OLDEST_SAMPLE_INSTANCE Fetch the Instance Data of the oldest sample -- FIND_OLDEST_INST_SAMPLE Find the oldest sample of a specific Instance -- REMOVE_SAMPLE Remove sample and linked payload -- POST_SAMPLE_REMOVE Update Instance Data of removed sample. If Instance Memory is full, and Instance is now eligible for removal, it is removed. -- SKIP_AND_RETURN Skip DDS Input and return latched Return Code -- REMOVE_WRITER Unmark specified Writer Bitmap Position from all stored Instances. (Also updates Instance Data if necessary) -- REMOVE_STALE_INSTANCE Find and remove the first eligible Instance in the memory -- GET_NEXT_SAMPLE Find the next sample in the requested collection -- PRE_CALCULATE Calculate ranks for the selected sample in the requested collection. -- FINALIZE_SAMPLE_INFO Finalize the Sample Info Data, and present them. -- GET_PAYLOAD Push linked Payload to output -- FIND_NEXT_INSTANCE Find next Instance that passes requested masks -- CHECK_INSTANCE Check if selected Instance passes requested masks -- CHECK_LIFESPAN Check and remove samples with expired Lifespans -- PROCESS_PENDING_SAMPLE_GENERATION Iterate through the Instances and Generate Samples where required -- GET_SAMPLE_REJECTED_STATUS Return Sample Rejected Status -- GET_REQUESTED_DEADLINE_MISSED_STATUS Return Requested Deadline Missed Status -- CHECK_DEADLINE Check and Mark Instances with missed Deadlines -- RESET_SAMPLE_MEMORY Reset Sample Memory to Empty State -- RESET_PAYLOAD_MEMORY Reset Payload Memory to Empty State parse_a_prc : process (all) variable tmp_dw : DOUBLE_WORD_ARRAY := (others => (others => '0')); variable tmp_bitmap : std_logic_vector(0 to WRITER_BITMAP_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 Registered stage_next <= stage; newest_sample_next <= newest_sample; empty_payload_list_head_next <= empty_payload_list_head; empty_sample_list_head_next <= empty_sample_list_head; empty_sample_list_tail_next <= empty_sample_list_tail; payload_addr_latch_1_next <= payload_addr_latch_1; payload_addr_latch_2_next <= payload_addr_latch_2; ts_latch_next <= ts_latch; long_latch_next <= long_latch; sample_addr_latch_1_next <= sample_addr_latch_1; sample_addr_latch_2_next <= sample_addr_latch_2; sample_addr_latch_3_next <= sample_addr_latch_3; sample_addr_latch_4_next <= sample_addr_latch_4; sample_addr_latch_5_next <= sample_addr_latch_5; writer_id_next <= writer_id; key_hash_next <= key_hash; sample_status_info_next <= sample_status_info; remove_oldest_sample_next <= remove_oldest_sample; remove_oldest_inst_sample_next <= remove_oldest_inst_sample; si_sample_state_sig_next <= si_sample_state; si_view_state_sig_next <= si_view_state_sig; si_instance_state_sig_next <= si_instance_state_sig; si_source_timestamp_sig_next <= si_source_timestamp_sig; si_instance_handle_sig_next <= si_instance_handle_sig; si_publication_handle_sig_next <= si_publication_handle_sig; si_disposed_generation_count_sig_next <= si_disposed_generation_count_sig; si_no_writers_generation_count_sig_next <= si_no_writers_generation_count_sig; si_sample_rank_sig_next <= si_sample_rank_sig; si_generation_rank_sig_next <= si_generation_rank_sig; si_absolute_generation_rank_sig_next <= si_absolute_generation_rank_sig; si_valid_data_sig_next <= si_valid_data_sig; si_valid_sig_next <= si_valid_sig; eoc_sig_next <= eoc_sig; sample_state_next <= sample_state; view_state_next <= view_state; instance_state_next <= instance_state; instance_handle_next <= instance_handle; max_samples_latch_next <= max_samples_latch; inst_addr_latch_1_next <= inst_addr_latch_1; inst_addr_latch_2_next <= inst_addr_latch_2; collection_cnt_next <= collection_cnt; collection_cnt_max_next <= collection_cnt_max; collection_generation_rank_next <= collection_generation_rank; cur_generation_rank_next <= cur_generation_rank; is_take_next <= is_take; single_instance_next <= single_instance; unmark_instances_flag_next <= unmark_instances_flag; dynamic_next_instance_next <= dynamic_next_instance; last_read_ts_next <= last_read_ts; sample_rej_cnt_next <= sample_rej_cnt; sample_rej_cnt_change_next <= sample_rej_cnt_change; sample_rej_last_reason_next <= sample_rej_last_reason; sample_rej_last_inst_next <= sample_rej_last_inst; deadline_time_next <= deadline_time; deadline_miss_cnt_next <= deadline_miss_cnt; deadline_miss_cnt_change_next <= deadline_miss_cnt_change; deadline_miss_last_inst_next <= deadline_miss_last_inst; lifespan_time_next <= lifespan_time; is_lifespan_check_next <= is_lifespan_check; status_sig_next <= status_sig; cnt_next <= cnt; cnt2_next <= cnt2; cnt3_next <= cnt3; lifespan_next <= lifespan; stale_inst_cnt_next <= stale_inst_cnt; inst_data_next2 <= inst_data; oldest_sample_next <= oldest_sample; rtps_return_code_latch_next <= rtps_return_code_latch; dds_return_code_latch_next <= dds_return_code_latch; pre_calculated_next <= pre_calculated; dis_gen_cnt_latch_next <= dis_gen_cnt_latch; no_w_gen_cnt_latch_next <= no_w_gen_cnt_latch; newer_inst_sample_next <= newer_inst_sample; new_inst_next <= new_inst; trigger_sample_gen_next <= trigger_sample_gen; wait_for_sample_removal_next <= wait_for_sample_removal; -- DEFAULT Unregistered inst_opcode <= NOP; opcode_kh <= NOP; ret_rtps <= ERROR; return_code_dds <= RETCODE_UNSUPPORTED; ack_dds <= '0'; done_dds <= '0'; ack_rtps <= '0'; done_rtps <= '0'; inst_op_start <= '0'; sample_read <= '0'; sample_ready_out <= '0'; sample_valid_in <= '0'; sample_abort_read <= '0'; payload_read <= '0'; payload_ready_out <= '0'; payload_valid_in <= '0'; payload_abort_read <= '0'; ready_in_rtps <= '0'; start_kh <= '0'; abort_kh <= '0'; ready_in_kh <= '0'; valid_out_kh <= '0'; last_word_out_kh <= '0'; valid_out_dds <= '0'; last_word_out_dds <= '0'; idle_sig <= '0'; data_out_dds <= (others => '0'); data_out_kh <= (others => '0'); writer_bitmap <= ZERO_WRITER_BITMAP_ARRAY; inst_addr_update <= (others => '0'); sample_addr <= (others => '0'); sample_write_data <= (others => '0'); payload_addr <= (others => '0'); payload_write_data <= (others => '0'); case (stage) is when IDLE => idle_sig <= '1'; -- Reset new_inst_next <= '0'; newer_inst_sample_next <= '0'; remove_oldest_inst_sample_next <= '0'; remove_oldest_sample_next <= '0'; is_take_next <= '0'; key_hash_next <= HANDLE_NIL; -- DEADLINE QoS if (DEADLINE_QOS /= DURATION_INFINITE and deadline_time <= time) then -- Reset Timeout deadline_time_next <= deadline_time + DEADLINE_QOS; -- Synthesis Guard if (WITH_KEY) then stage_next <= CHECK_DEADLINE; cnt_next <= 0; else if (inst_data.status_info(ISI_LIVELINESS_FLAG) = '1') then -- Reset Liveliness Flag inst_data_next2.status_info(ISI_LIVELINESS_FLAG) <= '0'; else -- Update Requested Deadline Missed Status status_sig_next <= status_sig or REQUESTED_DEADLINE_MISSED_STATUS; deadline_miss_cnt_next <= deadline_miss_cnt + 1; deadline_miss_cnt_change_next <= deadline_miss_cnt_change + 1; end if; end if; -- LIFESPAN QoS elsif (lifespan_time <= time) then -- Reset Timeout lifespan_time_next <= TIME_INFINITE; -- Samples Available if (oldest_sample /= SAMPLE_MEMORY_MAX_ADDRESS) then cur_sample_next <= oldest_sample; stage_next <= CHECK_LIFESPAN; cnt_next <= 0; end if; -- Sample Generation elsif (trigger_sample_gen = '1') then -- Synthesis Guard if (WITH_KEY) then stage_next <= PROCESS_PENDING_SAMPLE_GENERATION; cnt_next <= 0; else -- RESOURCE_LIMITS_QOS (MAX_SAMPLES) if (empty_sample_list_head = empty_sample_list_tail) then if (HISTORY_QOS = KEEP_ALL_HISTORY_QOS and RELIABILITY_QOS = RELIABLE_RELIABILITY_QOS) then wait_for_sample_removal_next <= '1'; -- Reset trigger_sample_gen_next <= '0'; -- DONE stage_next <= IDLE; else -- Reset trigger_sample_gen_next <= '0'; -- Update Instance inst_data_next2.status_info(ISI_GENERATE_SAMPLE_FLAG) <= '0'; inst_data_next2.sample_cnt <= inst_data.sample_cnt + 1; -- Accept Change (Remove Oldest Sample) remove_oldest_sample_next <= '1'; cur_sample_next <= empty_sample_list_head; cur_inst_next <= inst_addr_base; stage_next <= GENERATE_SAMPLE; cnt_next <= 0; end if; else -- Reset trigger_sample_gen_next <= '0'; -- Update Instance inst_data_next2.status_info(ISI_GENERATE_SAMPLE_FLAG) <= '0'; inst_data_next2.sample_cnt <= inst_data.sample_cnt + 1; cur_sample_next <= empty_sample_list_head; cur_inst_next <= inst_addr_base; stage_next <= GENERATE_SAMPLE; cnt_next <= 0; end if; end if; -- RTPS Operation elsif (start_rtps = '1') then case (opcode_rtps) is when ADD_CACHE_CHANGE => -- NOTE: We have to explicitly check the Payload Memory, as it may be "unaligned" with our Sample Memory -- (Sample Memory has available Slot, but Payload Memory not) -- Payload Memory Full if (empty_payload_list_head = PAYLOAD_MEMORY_MAX_ADDRESS) then if (HISTORY_QOS = KEEP_ALL_HISTORY_QOS and RELIABILITY_QOS = RELIABLE_RELIABILITY_QOS) then ack_rtps <= '1'; -- Reject Change stage_next <= SKIP_AND_RETURN; cnt_next <= 0; rtps_return_code_latch_next <= REJECTED; -- Update Sample Reject Status status_sig_next <= status_sig or SAMPLE_REJECTED_STATUS; 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_PAYOAD_MEMORY_LIMIT; sample_rej_last_inst_next <= HANDLE_NIL; else assert (oldest_sample /= SAMPLE_MEMORY_MAX_ADDRESS) severity FAILURE; -- Do not ACK Operation ack_dds <= '0'; remove_oldest_sample_next <= '1'; if (WITH_KEY) then stage_next <= GET_OLDEST_SAMPLE_INSTANCE; cnt_next <= 0; else cur_sample_next <= oldest_sample; stage_next <= REMOVE_SAMPLE; cnt_next <= 0; end if; end if; else ack_rtps <= '1'; stage_next <= ADD_SAMPLE_INFO; cur_sample_next <= empty_sample_list_head; cnt_next <= 0; end if; when REMOVE_WRITER => ack_rtps <= '1'; -- Synthesis Guard if (WITH_KEY) then -- Latch Writer Pos writer_id_next <= to_integer(unsigned(data_in_rtps)); stage_next <= REMOVE_WRITER; cnt_next <= 2; else -- Convert Writer Bitmap to SLV tmp_bitmap := from_writer_bitmap_array(inst_data.writer_bitmap); -- Remove Writer tmp_bitmap(to_integer(unsigned(data_in_rtps))) := '0'; -- Convert Back inst_data_next2.writer_bitmap <= to_writer_bitmap_array(tmp_bitmap); -- NOT_ALIVE_NO_WRITERS Transition if (tmp_bitmap = (tmp_bitmap'reverse_range => '0') and inst_data.status_info(ISI_NOT_ALIVE_DISPOSED_FLAG) = '0') then trigger_sample_gen_next <= '1'; inst_data_next2.status_info(ISI_GENERATE_SAMPLE_FLAG) <= '1'; inst_data_next2.status_info(ISI_NOT_ALIVE_NO_WRITERS_FLAG) <= '1'; end if; stage_next <= RETURN_RTPS; rtps_return_code_latch_next <= OK; end if; when others => null; end case; -- Unmark Instances elsif (WITH_KEY and unmark_instances_flag = '1') then -- Memory Operation Guard if (inst_op_done = '1') then inst_op_start <= '1'; inst_opcode <= UNMARK_INSTANCES; unmark_instances_flag_next <= '0'; end if; -- DDS Operation elsif (start_dds = '1') then -- Latch Input Signals sample_state_next <= sample_state_dds; view_state_next <= view_state_dds; instance_state_next <= instance_state_dds; max_samples_latch_next <= unsigned(max_samples_dds); -- Reset sel_sample_next <= SAMPLE_MEMORY_MAX_ADDRESS; sample_p1_next <= SAMPLE_MEMORY_MAX_ADDRESS; sample_p2_next <= SAMPLE_MEMORY_MAX_ADDRESS; pre_calculated_next <= '0'; single_instance_next <= '0' when WITH_KEY else '1'; dynamic_next_instance_next <= '0'; collection_cnt_next <= (others => '0'); collection_cnt_max_next <= (others => '0'); si_sample_state_sig_next <= (others => '0'); si_view_state_sig_next <= (others => '0'); si_instance_state_sig_next <= (others => '0'); si_source_timestamp_sig_next <= TIME_ZERO; si_instance_handle_sig_next <= HANDLE_NIL; si_publication_handle_sig_next <= (others => (others => '0')); si_sample_rank_sig_next <= (others => '0'); si_generation_rank_sig_next <= (others => '0'); si_valid_data_sig_next <= '0'; si_valid_sig_next <= '0'; eoc_sig_next <= '0'; si_absolute_generation_rank_sig_next <= (others => '0'); si_disposed_generation_count_sig_next <= (others => '0'); si_no_writers_generation_count_sig_next <= (others => '0'); case (opcode_dds) is when READ => ack_dds <= '1'; -- No Samples Available if (oldest_sample = SAMPLE_MEMORY_MAX_ADDRESS) then stage_next <= RETURN_DDS; dds_return_code_latch_next <= RETCODE_NO_DATA; else cur_sample_next <= oldest_sample; cur_inst_next <= INSTANCE_MEMORY_MAX_ADDRESS; stage_next <= GET_NEXT_SAMPLE; cnt_next <= 0; if (unsigned(max_samples_dds) = 1) then single_instance_next <= '1'; end if; end if; when TAKE => ack_dds <= '1'; -- No Samples Available if (oldest_sample = SAMPLE_MEMORY_MAX_ADDRESS) then stage_next <= RETURN_DDS; dds_return_code_latch_next <= RETCODE_NO_DATA; else is_take_next <= '1'; cur_sample_next <= oldest_sample; cur_inst_next <= INSTANCE_MEMORY_MAX_ADDRESS; stage_next <= GET_NEXT_SAMPLE; cnt_next <= 0; if (unsigned(max_samples_dds) = 1) then single_instance_next <= '1'; end if; end if; when READ_NEXT_SAMPLE => ack_dds <= '1'; -- No Samples Available if (oldest_sample = SAMPLE_MEMORY_MAX_ADDRESS) then stage_next <= RETURN_DDS; dds_return_code_latch_next <= RETCODE_NO_DATA; else single_instance_next <= '1'; cur_sample_next <= oldest_sample; cur_inst_next <= INSTANCE_MEMORY_MAX_ADDRESS; sample_state_next <= NOT_READ_SAMPLE_STATE; view_state_next <= ANY_VIEW_STATE; instance_state_next <= ANY_INSTANCE_STATE; max_samples_latch_next <= to_unsigned(1, max_samples_latch'length); stage_next <= GET_NEXT_SAMPLE; cnt_next <= 0; end if; when TAKE_NEXT_SAMPLE => ack_dds <= '1'; -- No Samples Available if (oldest_sample = SAMPLE_MEMORY_MAX_ADDRESS) then stage_next <= RETURN_DDS; dds_return_code_latch_next <= RETCODE_NO_DATA; else is_take_next <= '1'; single_instance_next <= '1'; cur_sample_next <= oldest_sample; cur_inst_next <= INSTANCE_MEMORY_MAX_ADDRESS; sample_state_next <= NOT_READ_SAMPLE_STATE; view_state_next <= ANY_VIEW_STATE; instance_state_next <= ANY_INSTANCE_STATE; max_samples_latch_next <= to_unsigned(1, max_samples_latch'length); stage_next <= GET_NEXT_SAMPLE; cnt_next <= 0; end if; when READ_INSTANCE => ack_dds <= '1'; -- Synthesis Guard if (WITH_KEY) then -- No Samples Available if (oldest_sample = SAMPLE_MEMORY_MAX_ADDRESS) then stage_next <= RETURN_DDS; dds_return_code_latch_next <= RETCODE_NO_DATA; else single_instance_next <= '1'; cur_sample_next <= oldest_sample; key_hash_next <= instance_handle_dds; stage_next <= CHECK_INSTANCE; cnt_next <= 0; end if; else stage_next <= RETURN_DDS; dds_return_code_latch_next <= RETCODE_ILLEGAL_OPERATION; end if; when TAKE_INSTANCE => ack_dds <= '1'; -- Synthesis Guard if (WITH_KEY) then -- No Samples Available if (oldest_sample = SAMPLE_MEMORY_MAX_ADDRESS) then stage_next <= RETURN_DDS; dds_return_code_latch_next <= RETCODE_NO_DATA; else is_take_next <= '1'; single_instance_next <= '1'; cur_sample_next <= oldest_sample; key_hash_next <= instance_handle_dds; stage_next <= CHECK_INSTANCE; cnt_next <= 0; end if; else stage_next <= RETURN_DDS; dds_return_code_latch_next <= RETCODE_ILLEGAL_OPERATION; end if; when READ_NEXT_INSTANCE => ack_dds <= '1'; -- Synthesis Guard if (WITH_KEY) then -- No Samples Available if (oldest_sample = SAMPLE_MEMORY_MAX_ADDRESS) then stage_next <= RETURN_DDS; dds_return_code_latch_next <= RETCODE_NO_DATA; else single_instance_next <= '1'; dynamic_next_instance_next <= '1'; cur_sample_next <= oldest_sample; key_hash_next <= instance_handle_dds; stage_next <= FIND_NEXT_INSTANCE; cnt_next <= 0; end if; else stage_next <= RETURN_DDS; dds_return_code_latch_next <= RETCODE_ILLEGAL_OPERATION; end if; when TAKE_NEXT_INSTANCE => ack_dds <= '1'; -- Synthesis Guard if (WITH_KEY) then -- No Samples Available if (oldest_sample = SAMPLE_MEMORY_MAX_ADDRESS) then stage_next <= RETURN_DDS; dds_return_code_latch_next <= RETCODE_NO_DATA; else is_take_next <= '1'; single_instance_next <= '1'; dynamic_next_instance_next <= '1'; cur_sample_next <= oldest_sample; key_hash_next <= instance_handle_dds; stage_next <= FIND_NEXT_INSTANCE; cnt_next <= 0; end if; else stage_next <= RETURN_DDS; dds_return_code_latch_next <= RETCODE_ILLEGAL_OPERATION; end if; when GET_SAMPLE_REJECTED_STATUS => ack_dds <= '1'; stage_next <= GET_SAMPLE_REJECTED_STATUS; cnt_next <= 0; when GET_REQUESTED_DEADLINE_MISSED_STATUS => ack_dds <= '1'; stage_next <= GET_REQUESTED_DEADLINE_MISSED_STATUS; cnt_next <= 0; when others => ack_dds <= '1'; stage_next <= RETURN_DDS; dds_return_code_latch_next <= RETCODE_UNSUPPORTED; end case; end if; when RETURN_DDS => done_dds <= '1'; return_code_dds <= dds_return_code_latch; -- DONE stage_next <= IDLE; when RETURN_RTPS => done_rtps <= '1'; ret_rtps <= rtps_return_code_latch; -- DONE stage_next <= IDLE; when ADD_SAMPLE_INFO => -- Precondition: cur_sample set case (cnt) is -- SET Status Info when 0 => -- Input Guard if (valid_in_rtps = '1') then -- NOTE: The PAYLOAD_FLAG and KEY_HASH_FLAG are set by the RTPS Reader -- NOTE: The ALIGNED_FLAG is set by default. if actual Payload is not aligned, need to reset. sample_valid_in <= '1'; sample_addr <= cur_sample + SMF_STATUS_INFO_OFFSET; sample_write_data <= data_in_rtps; sample_write_data(SSI_KEY_HASH_FLAG) <= '0'; -- Key Hash Flag is not stored sample_write_data(SSI_READ_FLAG) <= '0'; sample_write_data(SSI_ALIGNED_FLAG) <= data_in_rtps(SSI_DATA_FLAG); -- Latch Status Info sample_status_info_next <= data_in_rtps; sample_status_info_next(SSI_READ_FLAG) <= '0'; sample_status_info_next(SSI_ALIGNED_FLAG) <= data_in_rtps(SSI_DATA_FLAG); -- Memory Flow Control Guard if (sample_ready_in = '1') then ready_in_rtps <= '1'; cnt_next <= cnt + 1; end if; end if; -- SET Timestamp 1/2 when 1 => -- Input Guard if (valid_in_rtps = '1') then sample_valid_in <= '1'; sample_addr <= cur_sample + SMF_TIMESTAMP_OFFSET; sample_write_data <= data_in_rtps; -- Latch Timestamp ts_latch_next(0) <= unsigned(data_in_rtps); -- Memory Flow Control Guard if (sample_ready_in = '1') then ready_in_rtps <= '1'; cnt_next <= cnt + 1; end if; end if; -- SET Timestamp 2/2 when 2 => -- Input Guard if (valid_in_rtps = '1') then sample_valid_in <= '1'; sample_addr <= cur_sample + SMF_TIMESTAMP_OFFSET + 1; sample_write_data <= data_in_rtps; -- Latch Timestamp ts_latch_next(1) <= unsigned(data_in_rtps); -- 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 /= TIME_INVALID and tmp_dw < last_read_ts)) then -- Drop Sample rtps_return_code_latch_next <= OK; stage_next <= SKIP_AND_RETURN; cnt_next <= 0; end if; end if; end if; end if; -- SET Lifespan Deadline 1/2 when 3 => -- Input Guard if (valid_in_rtps = '1') then sample_valid_in <= '1'; sample_addr <= cur_sample + SMF_LIFESPAN_DEADLINE_OFFSET; sample_write_data <= data_in_rtps; -- Latch Lifespan lifespan_next(0) <= unsigned(data_in_rtps); -- Memory Flow Control Guard if (sample_ready_in = '1') then ready_in_rtps <= '1'; cnt_next <= cnt + 1; end if; end if; -- SET Lifespan Deadline 2/2 when 4 => -- Input Guard if (valid_in_rtps = '1') then sample_valid_in <= '1'; sample_addr <= cur_sample + SMF_LIFESPAN_DEADLINE_OFFSET + 1; sample_write_data <= data_in_rtps; -- Latch Lifespan lifespan_next(1) <= unsigned(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; end if; -- Key Hash 1/4 when 5 => -- Input Guard if (valid_in_rtps = '1') then ready_in_rtps <= '1'; -- Latch Input, but do not pass to Memory key_hash_next(0) <= data_in_rtps; cnt_next <= cnt + 1; end if; -- Key Hash 2/4 when 6 => -- Input Guard if (valid_in_rtps = '1') then ready_in_rtps <= '1'; -- Latch Input, but do not pass to Memory key_hash_next(1) <= data_in_rtps; cnt_next <= cnt + 1; end if; -- Key Hash 3/4 when 7 => -- Input Guard if (valid_in_rtps = '1') then ready_in_rtps <= '1'; -- Latch Input, but do not pass to Memory key_hash_next(2) <= data_in_rtps; cnt_next <= cnt + 1; end if; -- Key Hash 4/4 when 8 => -- Input Guard if (valid_in_rtps = '1') then ready_in_rtps <= '1'; -- Latch Input, but do not pass to Memory key_hash_next(3) <= data_in_rtps; cnt_next <= cnt + 1; end if; -- Writer Endpoint Position when 9 => -- Input Guard if (valid_in_rtps = '1') then ready_in_rtps <= '1'; -- Latch Input, but do not pass to Memory writer_id_next <= cap_range(to_integer(unsigned(data_in_rtps)), MAX_REMOTE_ENDPOINTS-1); cnt_next <= cnt + 1; end if; -- SET Payload Address when 10 => assert (empty_payload_list_head /= PAYLOAD_MEMORY_MAX_ADDRESS) severity FAILURE; sample_valid_in <= '1'; sample_addr <= cur_sample + SMF_PAYLOAD_ADDR_OFFSET; if (has_data = '1') then -- Store Payload Address sample_write_data <= std_logic_vector(resize(empty_payload_list_head, WORD_WIDTH)); cur_payload_next <= empty_payload_list_head; else -- Mark Sample with no Payload sample_write_data <= std_logic_vector(resize(PAYLOAD_MEMORY_MAX_ADDRESS, WORD_WIDTH)); end if; -- Memory Flow Control Guard if (sample_ready_in = '1') then -- If Key Hash is available, start the Instance Search first if (WITH_KEY and has_key_hash = '1') then stage_next <= INITIATE_INSTANCE_SEARCH; -- Key Hash Needs to be Calculated elsif (WITH_KEY and has_key_hash = '0') then cnt_next <= cnt + 1; elsif (has_data = '1') then assert (not WITH_KEY) severity FAILURE; stage_next <= ADD_PAYLOAD; cnt_next <= 0; cnt2_next <= 1; else -- has_data = '0' assert (not WITH_KEY) severity FAILURE; stage_next <= FILTER_STAGE; end if; end if; -- Initiate KH Operation when 11 => -- Synthesis Guard if (WITH_KEY) then start_kh <= '1'; -- Payload is Serialized Key if (has_data = '0') then opcode_kh <= PUSH_SERIALIZED_KEY; else opcode_kh <= PUSH_DATA; end if; if (ack_kh = '1') then -- Payload is Serialized Key if (has_data = '0') then stage_next <= ADD_PAYLOAD; cnt_next <= 1; else stage_next <= ADD_PAYLOAD; cnt_next <= 0; cnt2_next <= 1; end if; end if; end if; when others => null; end case; when ADD_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: -- has_data has_key_hash -- 1 1 The payload is written to memory [Entered from INITIATE_INSTANCE_SEARCH] -- 1 0 The payload is written to memory and the KHG at the same time (KHG controls the flow) [Entered from ADD_PAYLOAD_ADDRESS] -- 0 0 There is no payload to write, but the input contains the key for the KHG [Entered from ADD_PAYLOAD_ADDRESS] 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 -- Key Hash needs to be calculated if (WITH_KEY and has_key_hash = '0') then cnt_next <= cnt + 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 <= ALIGN_PAYLOAD; cnt_next <= 0; end if; else -- End of Payload Slot if (cnt2 = PAYLOAD_FRAME_SIZE-1) then stage_next <= NEXT_PAYLOAD_SLOT; cnt_next <= 0; else -- Next Word cnt2_next <= cnt2 + 1; end if; end if; end if; end if; end if; -- Push to KHG when 1 => -- Synthesis Guard if (WITH_KEY) then -- Input Guard if (valid_in_rtps = '1') then valid_out_kh <= '1'; data_out_kh <= data_in_rtps; -- Output Guard if (ready_out_kh = '1') then ready_in_rtps <= '1'; if (has_data = '1') then -- End of Payload if (last_word_in_rtps = '1') then last_word_out_kh <= '1'; -- End of Payload Slot if (cnt2 = PAYLOAD_FRAME_SIZE-1) then -- Fetch the Key Hash stage_next <= GET_KEY_HASH; cnt_next <= 0; cnt2_next <= 0; else stage_next <= ALIGN_PAYLOAD; cnt_next <= 0; end if; else -- End of Payload Slot if (cnt2 = PAYLOAD_FRAME_SIZE-1) then stage_next <= NEXT_PAYLOAD_SLOT; cnt_next <= 0; else -- Next Word cnt_next <= 0; cnt2_next <= cnt2 + 1; end if; end if; else -- End of Payload if (last_word_in_rtps = '1') then last_word_out_kh <= '1'; -- Fetch the Key Hash stage_next <= GET_KEY_HASH; cnt_next <= 0; cnt2_next <= 0; else -- Next Word cnt_next <= 1; -- Same Sub-state end if; end if; end if; end if; end if; when others => null; end case; when NEXT_PAYLOAD_SLOT => -- Precondition: cur_payload set case (cnt) is -- GET Next Pointer when 0 => 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 => payload_ready_out <= '1'; -- Memory Control Flow Guard if (payload_valid_out = '1') then -- No Empty Payload Slots available if (resize(unsigned(payload_read_data),PAYLOAD_MEMORY_ADDR_WIDTH) = PAYLOAD_MEMORY_MAX_ADDRESS) then -- Reject Change rtps_return_code_latch_next <= REJECTED; stage_next <= SKIP_AND_RETURN; cnt_next <= 0; -- Abort Key Hash Generation abort_kh <= '1'; -- Update Sample Reject Status status_sig_next <= status_sig or SAMPLE_REJECTED_STATUS; 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_PAYOAD_MEMORY_LIMIT; sample_rej_last_inst_next <= key_hash; else -- Latch next Payload Slot and Continue cur_payload_next <= resize(unsigned(payload_read_data),PAYLOAD_MEMORY_ADDR_WIDTH); stage_next <= ADD_PAYLOAD; cnt_next <= 0; cnt2_next <= 1; end if; end if; when others => null; end case; when ALIGN_PAYLOAD => case (cnt) is -- Mark Payload as unaligned when 0 => sample_valid_in <= '1'; sample_addr <= cur_sample + SMF_STATUS_INFO_OFFSET; sample_write_data <= sample_status_info; sample_write_data(SSI_ALIGNED_FLAG) <= '0'; -- Memory Control Flow Guard if (sample_ready_in = '1') then cnt_next <= cnt + 1; end if; -- Store Payload End Offset when 1 => payload_valid_in <= '1'; payload_addr <= cur_payload + PAYLOAD_FRAME_SIZE-1; payload_write_data <= std_logic_vector(to_unsigned(cnt2, WORD_WIDTH)); -- Memory Control Flow Guard if (payload_ready_in = '1') then if (WITH_KEY and has_key_hash = '0') then stage_next <= GET_KEY_HASH; cnt_next <= 0; cnt2_next <= 0; else stage_next <= FILTER_STAGE; end if; end if; when others => null; end case; when GET_KEY_HASH => -- Synthesis Guard if (WITH_KEY) then case (cnt) is -- Initiate READ Operation when 0 => start_kh <= '1'; opcode_kh <= READ_KEY_HASH; if (ack_kh = '1') then cnt_next <= cnt + 1; end if; -- READ Key Hash when 1 => ready_in_kh <= '1'; if (valid_in_kh = '1') then cnt2_next <= cnt2 + 1; -- Latch Key Hash key_hash_next(cnt2) <= data_in_kh; -- Exit Condition if (last_word_in_kh = '1') then -- DONE stage_next <= INITIATE_INSTANCE_SEARCH; end if; end if; when others => null; end case; end if; when INITIATE_INSTANCE_SEARCH => -- Synthesis Guard if (WITH_KEY) then -- Memory Operation Guard if (inst_op_done = '1') then inst_op_start <= '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' and WITH_KEY and has_key_hash = '1') then stage_next <= ADD_PAYLOAD; cnt_next <= 0; cnt2_next <= 1; else stage_next <= FILTER_STAGE; end if; end if; end if; when FILTER_STAGE => -- Precondition: cur_sample set, inst_data set (IMF_STATUS_FLAG, IMF_IGNORE_DEADLINE_FLAG, IMF_SAMPLE_CNT_FLAG, IMF_DISPOSED_CNT_FLAG, IMF_NO_WRITERS_CNT_FLAG) -- Wait for Instance Search to finish if (not WITH_KEY or inst_op_done = '1') then assert check_mask(current_imf, IMF_STATUS_FLAG or IMF_IGNORE_DEADLINE_FLAG or IMF_SAMPLE_CNT_FLAG or IMF_DISPOSED_CNT_FLAG or IMF_NO_WRITERS_CNT_FLAG) severity FAILURE; -- Instance Found if (not WITH_KEY or inst_addr_base /= INSTANCE_MEMORY_MAX_ADDRESS) then -- Latch Instance Pointer cur_inst_next <= inst_addr_base; -- Latch Instance Generation Counters dis_gen_cnt_latch_next <= inst_data.disposed_gen_cnt; no_w_gen_cnt_latch_next <= inst_data.no_writers_gen_cnt; -- TIME_BASED_FILTER QOS if (TIME_BASED_FILTER_QOS /= DURATION_ZERO and time < inst_data.ignore_deadline) then -- Drop Change done_rtps <= '1'; ret_rtps <= OK; stage_next <= IDLE; -- Pending Sample Generation -- NOTE: If there is a Pending Sample Generation and we reach this stage, the limiting factor is still here and the Sample will be rejected. -- In order to have a valid sample rejected status it makes sense to let the sample be rejected "naturally". --elsif (inst_data.status_info(ISI_GENERATE_SAMPLE_FLAG) = '1') then -- -- Reject Change -- done_rtps <= '1'; -- ret_rtps <= REJECTED; -- stage_next <= IDLE; -- -- Update Sample Reject Status -- status_sig_next <= status_sig or SAMPLE_REJECTED_STATUS; -- 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_PENDING_SAMPLE_GENERATION; -- sample_rej_last_inst_next <= key_hash; -- RESOURCE_LIMITS_QOS (MAX_SAMPLES_PER_INSTANCE) elsif (WITH_KEY and MAX_SAMPLES_PER_INSTANCE /= LENGTH_UNLIMITED and inst_data.sample_cnt = unsigned(MAX_SAMPLES_PER_INSTANCE)) then if (HISTORY_QOS = KEEP_ALL_HISTORY_QOS and RELIABILITY_QOS = RELIABLE_RELIABILITY_QOS) then -- Reject Change done_rtps <= '1'; ret_rtps <= REJECTED; stage_next <= IDLE; -- Update Sample Reject Status status_sig_next <= status_sig or SAMPLE_REJECTED_STATUS; 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'; done_rtps <= '1'; ret_rtps <= OK; if (DESTINATION_ORDER_QOS = BY_SOURCE_TIMESTAMP_DESTINATION_ORDER_QOS and newest_sample /= SAMPLE_MEMORY_MAX_ADDRESS) then stage_next <= FIND_POS; next_sample_next <= SAMPLE_MEMORY_MAX_ADDRESS; prev_sample_next <= newest_sample; cur_sample_next <= newest_sample; cnt_next <= 0; else stage_next <= UPDATE_INSTANCE; end if; 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 done_rtps <= '1'; ret_rtps <= REJECTED; stage_next <= IDLE; -- Update Sample Reject Status status_sig_next <= status_sig or SAMPLE_REJECTED_STATUS; 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'; done_rtps <= '1'; ret_rtps <= OK; if (DESTINATION_ORDER_QOS = BY_SOURCE_TIMESTAMP_DESTINATION_ORDER_QOS and newest_sample /= SAMPLE_MEMORY_MAX_ADDRESS) then stage_next <= FIND_POS; next_sample_next <= SAMPLE_MEMORY_MAX_ADDRESS; prev_sample_next <= newest_sample; cur_sample_next <= newest_sample; cnt_next <= 0; else stage_next <= UPDATE_INSTANCE; end if; end if; else -- Accept Change done_rtps <= '1'; ret_rtps <= OK; if (DESTINATION_ORDER_QOS = BY_SOURCE_TIMESTAMP_DESTINATION_ORDER_QOS and newest_sample /= SAMPLE_MEMORY_MAX_ADDRESS) then stage_next <= FIND_POS; next_sample_next <= SAMPLE_MEMORY_MAX_ADDRESS; prev_sample_next <= newest_sample; cur_sample_next <= newest_sample; cnt_next <= 0; else stage_next <= UPDATE_INSTANCE; end if; end if; else -- (only WITH_KEY) new_inst_next <= '1'; -- Latch Instance Pointer cur_inst_next <= inst_empty_head; -- Ignore UNREGISTER/FILTERED Samples on Unknown Instances if (sample_status_info(SSI_UNREGISTERED_FLAG) = '1' or sample_status_info(SSI_FILTERED_FLAG) = '1') then -- Drop Change done_rtps <= '1'; ret_rtps <= OK; -- DONE stage_next <= IDLE; -- RESOURCE_LIMITS_QOS (MAX_SAMPLES) elsif (empty_sample_list_head = empty_sample_list_tail) then if (HISTORY_QOS = KEEP_ALL_HISTORY_QOS and RELIABILITY_QOS = RELIABLE_RELIABILITY_QOS) then -- Reject Change done_rtps <= '1'; ret_rtps <= REJECTED; stage_next <= IDLE; -- Update Sample Reject Status status_sig_next <= status_sig or SAMPLE_REJECTED_STATUS; 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 -- RESOURCE_LIMITS_QOS (MAX_INSTANCES) (Instance Memory Full) if (inst_empty_head = INSTANCE_MEMORY_MAX_ADDRESS) then -- No Stale Instances available if (stale_inst_cnt = 0) then -- Reject Change done_rtps <= '1'; ret_rtps <= REJECTED; -- DONE stage_next <= IDLE; -- Update Sample Reject Status status_sig_next <= status_sig or SAMPLE_REJECTED_STATUS; 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; else -- Accept Change (Remove Oldest Sample) remove_oldest_sample_next <= '1'; done_rtps <= '1'; ret_rtps <= OK; -- Remove Stale Instance and Insert Instance inst_op_start <= '1'; inst_opcode <= GET_FIRST_INSTANCE; inst_mem_fields <= IMF_SAMPLE_CNT_FLAG or IMF_WRITER_BITMAP_FLAG; stage_next <= REMOVE_STALE_INSTANCE; cnt_next <= 0; end if; else -- Accept Change (Remove Oldest Sample) remove_oldest_sample_next <= '1'; done_rtps <= '1'; ret_rtps <= OK; -- Insert New Instance inst_op_start <= '1'; inst_opcode <= INSERT_INSTANCE; status_info_update <= (ISI_LIVELINESS_FLAG => '1', ISI_NOT_ALIVE_DISPOSED_FLAG => sample_status_info(SSI_DISPOSED_FLAG), others => '0'); sample_cnt <= to_unsigned(1, WORD_WIDTH); deadline <= (time + TIME_BASED_FILTER_QOS) when (TIME_BASED_FILTER_QOS /= DURATION_ZERO) else TIME_INVALID; tmp_bitmap := (others => '0'); tmp_bitmap(writer_id) := '1'; writer_bitmap <= to_writer_bitmap_array(tmp_bitmap); if (DESTINATION_ORDER_QOS = BY_SOURCE_TIMESTAMP_DESTINATION_ORDER_QOS and newest_sample /= SAMPLE_MEMORY_MAX_ADDRESS) then stage_next <= FIND_POS; next_sample_next <= SAMPLE_MEMORY_MAX_ADDRESS; prev_sample_next <= newest_sample; cur_sample_next <= newest_sample; cnt_next <= 0; else if (has_data = '1') then stage_next <= FINALIZE_PAYLOAD; cnt_next <= 0; else stage_next <= PRE_SAMPLE_FINALIZE; cnt_next <= 0; end if; end if; end if; end if; else -- RESOURCE_LIMITS_QOS (MAX_INSTANCES) (Instance Memory Full) if (inst_empty_head = INSTANCE_MEMORY_MAX_ADDRESS) then -- No Stale Instances available if (stale_inst_cnt = 0) then -- Reject Change done_rtps <= '1'; ret_rtps <= REJECTED; -- DONE stage_next <= IDLE; -- Update Sample Reject Status status_sig_next <= status_sig or SAMPLE_REJECTED_STATUS; 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; else done_rtps <= '1'; ret_rtps <= OK; -- Remove Stale Instance and Insert Instance inst_op_start <= '1'; inst_opcode <= GET_FIRST_INSTANCE; inst_mem_fields <= IMF_SAMPLE_CNT_FLAG or IMF_WRITER_BITMAP_FLAG; stage_next <= REMOVE_STALE_INSTANCE; cnt_next <= 0; end if; else -- Accept Change done_rtps <= '1'; ret_rtps <= OK; -- Insert New Instance inst_op_start <= '1'; inst_opcode <= INSERT_INSTANCE; status_info_update <= (ISI_LIVELINESS_FLAG => '1', ISI_NOT_ALIVE_DISPOSED_FLAG => sample_status_info(SSI_DISPOSED_FLAG), others => '0'); sample_cnt <= to_unsigned(1, WORD_WIDTH); deadline <= (time + TIME_BASED_FILTER_QOS) when (TIME_BASED_FILTER_QOS /= DURATION_ZERO) else TIME_INVALID; tmp_bitmap := (others => '0'); tmp_bitmap(writer_id) := '1'; writer_bitmap <= to_writer_bitmap_array(tmp_bitmap); if (DESTINATION_ORDER_QOS = BY_SOURCE_TIMESTAMP_DESTINATION_ORDER_QOS and newest_sample /= SAMPLE_MEMORY_MAX_ADDRESS) then stage_next <= FIND_POS; next_sample_next <= SAMPLE_MEMORY_MAX_ADDRESS; prev_sample_next <= newest_sample; cur_sample_next <= newest_sample; cnt_next <= 0; else if (has_data = '1') then stage_next <= FINALIZE_PAYLOAD; cnt_next <= 0; else stage_next <= PRE_SAMPLE_FINALIZE; cnt_next <= 0; end if; end if; end if; end if; end if; end if; when FIND_POS => -- Synthesis Guard if (DESTINATION_ORDER_QOS = BY_SOURCE_TIMESTAMP_DESTINATION_ORDER_QOS) then -- Precondition: cur_sample set case (cnt) is -- GET Timestamp 1/2 when 0 => sample_valid_in <= '1'; sample_addr <= cur_sample + SMF_TIMESTAMP_OFFSET; sample_read <= '1'; -- Memory Flow Control Guard if (sample_ready_in = '1') then cnt_next <= cnt + 1; end if; -- 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; -- GET Instance Pointer when 3 => sample_valid_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; -- READ Timestamp 1/2 when 4 => 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 5 => 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)); -- Found position (After current slot) if (ts_latch >= tmp_dw) then sample_abort_read <= '1'; prev_sample_next <= cur_sample; cur_sample_next <= empty_sample_list_head; if (new_inst = '1') then if (has_data = '1') then stage_next <= FINALIZE_PAYLOAD; cnt_next <= 0; else stage_next <= PRE_SAMPLE_FINALIZE; cnt_next <= 0; end if; else stage_next <= UPDATE_INSTANCE; end if; else cnt_next <= cnt + 1; end if; end if; -- READ Previous Sample Pointer when 6 => sample_ready_out <= '1'; -- Memory Flow Control Guard if (sample_valid_out = '1') then prev_sample_next <= resize(unsigned(sample_read_data),SAMPLE_MEMORY_ADDR_WIDTH); cnt_next <= cnt + 1; end if; -- READ Instance Poiner when 7 => sample_ready_out <= '1'; -- Memory Flow Control Guard if (sample_valid_out = '1') then -- Sample has Same Instance if (resize(unsigned(sample_read_data),INSTANCE_MEMORY_ADDR_WIDTH) = cur_inst) then -- Newer Sample of same Instance found newer_inst_sample_next <= '1'; -- NOT_ALIVE Sample if (sample_status_info(SSI_DISPOSED_FLAG) = '1' or sample_status_info(SSI_UNREGISTERED_FLAG) = '1') then -- NOTE: We drop Dispose and Unregister Samples if a newer Sample of the same Instance exists, because else -- the Instance State and Generation Counters would have to be recalculated (by crawling through all the Instance Samples) -- Drop Sample stage_next <= IDLE; else cnt_next <= cnt + 1; end if; else -- No previous Slot (Oldest Sample) if (prev_sample = PAYLOAD_MEMORY_MAX_ADDRESS) then assert (cur_sample = oldest_sample) severity FAILURE; -- NOTE: Sample is added to HEAD of List next_sample_next <= cur_sample; cur_sample_next <= empty_sample_list_head; if (new_inst = '1') then if (has_data = '1') then stage_next <= FINALIZE_PAYLOAD; cnt_next <= 0; else stage_next <= PRE_SAMPLE_FINALIZE; cnt_next <= 0; end if; else stage_next <= UPDATE_INSTANCE; end if; else -- Continue Search cur_sample_next <= prev_sample; next_sample_next <= cur_sample; cnt_next <= 0; end if; end if; end if; -- GET Disposed Generation Count when 8 => sample_valid_in <= '1'; sample_addr <= cur_sample + SMF_DISPOSED_GEN_CNT_OFFSET; sample_read <= '1'; -- Memory Flow Control Guard if (sample_ready_in = '1') then cnt_next <= cnt + 1; end if; -- GET No Writers Generation Count when 9 => sample_valid_in <= '1'; sample_addr <= cur_sample + SMF_NO_WRITERS_GEN_CNT_OFFSET; sample_read <= '1'; -- Memory Flow Control Guard if (sample_ready_in = '1') then cnt_next <= cnt + 1; end if; -- READ Disposed Generation Count when 10 => sample_ready_out <= '1'; -- Memory Flow Control Guard if (sample_valid_out = '1') then -- Latch Generation Counter dis_gen_cnt_latch_next <= unsigned(sample_read_data); cnt_next <= cnt + 1; end if; -- READ No Writers Generation Count when 11 => sample_ready_out <= '1'; -- Memory Flow Control Guard if (sample_valid_out = '1') then -- Latch Generation Counter no_w_gen_cnt_latch_next <= unsigned(sample_read_data); -- Continue Search cur_sample_next <= prev_sample; next_sample_next <= cur_sample; cnt_next <= 0; end if; when others => null; end case; end if; when UPDATE_INSTANCE => -- Precondition inst_data set (IMF_STATUS_FLAG, IMF_WRITER_BITMAP_FLAG, IMF_DISPOSED_CNT_FLAG, IMF_NO_WRITERS_CNT_FLAG, IMF_SAMPLE_CNT_FLAG, IMF_IGNORE_DEADLINE_FLAG) -- Mark if Sample is stored in memory tmp_bool := TRUE; -- Memory Operation Guard if (not WITH_KEY or inst_op_done = '1') then assert check_mask(current_imf, IMF_STATUS_FLAG or IMF_WRITER_BITMAP_FLAG or IMF_DISPOSED_CNT_FLAG or IMF_NO_WRITERS_CNT_FLAG or IMF_SAMPLE_CNT_FLAG or IMF_IGNORE_DEADLINE_FLAG) severity FAILURE; -- DEFAULT STATUS INFO (LIVELINESS) if (WITH_KEY) then tmp_update := IMF_STATUS_FLAG; status_info_update <= inst_data.status_info; status_info_update(ISI_LIVELINESS_FLAG) <= '1'; else inst_data_next2.status_info(ISI_LIVELINESS_FLAG) <= '1'; end if; -- *WRITER BITMAP* -- Convert Writer Bitmap to SLV tmp_bitmap := from_writer_bitmap_array(inst_data.writer_bitmap); -- ALIVE/FILTERED/DISPOSE Operation if (sample_status_info(SSI_UNREGISTERED_FLAG) /= '1') then -- Write if Writer New for Instance if (tmp_bitmap(writer_id) /= '1') then -- Insert Writer tmp_bitmap(writer_id) := '1'; -- Convert Back -- Synthesis Guard if (WITH_KEY) then writer_bitmap <= to_writer_bitmap_array(tmp_bitmap); tmp_update := tmp_update or IMF_WRITER_BITMAP_FLAG; else inst_data_next2.writer_bitmap <= to_writer_bitmap_array(tmp_bitmap); end if; end if; else -- Write if Writer New for Instance if (tmp_bitmap(writer_id) /= '0') then -- Insert Writer tmp_bitmap(writer_id) := '0'; -- Convert Back -- Synthesis Guard if (WITH_KEY) then writer_bitmap <= to_writer_bitmap_array(tmp_bitmap); tmp_update := tmp_update or IMF_WRITER_BITMAP_FLAG; else inst_data_next2.writer_bitmap <= to_writer_bitmap_array(tmp_bitmap); end if; end if; end if; -- *GENERATION COUNTERS / VIEW STATE* -- Only Update Instance State if Sample if newest if (newer_inst_sample = '0') then -- NOT_ALIVE_DISPOSED -> ALIVE Transition if (sample_status_info(SSI_DISPOSED_FLAG) = '0' and sample_status_info(SSI_UNREGISTERED_FLAG) = '0' and inst_data.status_info(ISI_NOT_ALIVE_DISPOSED_FLAG) = '1') then -- Synthesis Guard if (WITH_KEY) then tmp_update := tmp_update or IMF_DISPOSED_CNT_FLAG; gen_cnt <= inst_data.disposed_gen_cnt + 1; status_info_update(ISI_VIEW_FLAG) <= '0'; else inst_data_next2.disposed_gen_cnt <= inst_data.disposed_gen_cnt + 1; inst_data_next2.status_info(ISI_VIEW_FLAG) <= '0'; end if; -- NOT_ALIVE_NO_WRITERS -> ALIVE Transition OR NOT_ALIVE_NO_WRITERS -> NOT_ALIVE_DISPOSED Transition elsif (sample_status_info(SSI_UNREGISTERED_FLAG) = '0' and inst_data.status_info(ISI_NOT_ALIVE_NO_WRITERS_FLAG) = '1') then -- Synthesis Guard if (WITH_KEY) then tmp_update := tmp_update or IMF_NO_WRITERS_CNT_FLAG; gen_cnt <= inst_data.no_writers_gen_cnt + 1; status_info_update(ISI_VIEW_FLAG) <= '0'; else inst_data_next2.no_writers_gen_cnt <= inst_data.no_writers_gen_cnt + 1; inst_data_next2.status_info(ISI_VIEW_FLAG) <= '0'; end if; end if; end if; -- *STATUS INFO* -- * -> NOT_ALIVE_DISPOSED Transition if (sample_status_info(SSI_DISPOSED_FLAG) = '1') then -- NOT_ALIVE_DISPOSED -> NOT_ALIVE_DISPOSED if (inst_data.status_info(ISI_NOT_ALIVE_DISPOSED_FLAG) = '1') then tmp_bool := FALSE; -- Only Update Instance State if Sample if newest elsif (newer_inst_sample = '0') then -- Synthesis Guard if (WITH_KEY) then status_info_update(ISI_NOT_ALIVE_DISPOSED_FLAG) <= '1'; status_info_update(ISI_NOT_ALIVE_NO_WRITERS_FLAG) <= '0'; else inst_data_next2.status_info(ISI_NOT_ALIVE_DISPOSED_FLAG) <= '1'; inst_data_next2.status_info(ISI_NOT_ALIVE_NO_WRITERS_FLAG) <= '0'; end if; end if; -- * -> NOT_ALIVE_NO_WRITERS Transition elsif (sample_status_info(SSI_UNREGISTERED_FLAG) = '1' and tmp_bitmap = (tmp_bitmap'reverse_range => '0')) then -- NOT_ALIVE -> NOT_ALIVE_NO_WRITERS if (inst_data.status_info(ISI_NOT_ALIVE_DISPOSED_FLAG) = '1' or inst_data.status_info(ISI_NOT_ALIVE_NO_WRITERS_FLAG) = '1') then tmp_bool := FALSE; -- Only Update Instance State if Sample if newest elsif (newer_inst_sample = '0') then -- Synthesis Guard if (WITH_KEY) then status_info_update(ISI_NOT_ALIVE_DISPOSED_FLAG) <= '0'; status_info_update(ISI_NOT_ALIVE_NO_WRITERS_FLAG) <= '1'; else inst_data_next2.status_info(ISI_NOT_ALIVE_DISPOSED_FLAG) <= '0'; inst_data_next2.status_info(ISI_NOT_ALIVE_NO_WRITERS_FLAG) <= '1'; end if; end if; -- * -> ALIVE Transition elsif (sample_status_info(SSI_UNREGISTERED_FLAG) = '0' and sample_status_info(SSI_DISPOSED_FLAG) = '0') then -- ALIVE -> ALIVE if (inst_data.status_info(ISI_NOT_ALIVE_NO_WRITERS_FLAG) /= '1' and inst_data.status_info(ISI_NOT_ALIVE_DISPOSED_FLAG) /= '1') then -- Filtered Sample if (sample_status_info(SSI_FILTERED_FLAG) = '1') then tmp_bool := FALSE; else assert (has_data = '1') severity FAILURE; end if; -- Only Update Instance State if Sample if newest elsif (newer_inst_sample = '0') then -- Synthesis Guard if (WITH_KEY) then status_info_update(ISI_NOT_ALIVE_DISPOSED_FLAG) <= '0'; status_info_update(ISI_NOT_ALIVE_NO_WRITERS_FLAG) <= '0'; else inst_data_next2.status_info(ISI_NOT_ALIVE_DISPOSED_FLAG) <= '0'; inst_data_next2.status_info(ISI_NOT_ALIVE_NO_WRITERS_FLAG) <= '0'; end if; end if; else tmp_bool := FALSE; end if; -- *INSTANCE SAMPLE COUNT* if (tmp_bool) then -- Synthesis Guard if (WITH_KEY) then tmp_update := tmp_update or IMF_SAMPLE_CNT_FLAG; sample_cnt <= inst_data.sample_cnt + 1; else inst_data_next2.sample_cnt <= inst_data.sample_cnt + 1; end if; end if; -- *IGNORE DEADLINE* if (TIME_BASED_FILTER_QOS /= DURATION_ZERO) then -- Synthesis Guard if (WITH_KEY) then tmp_update := tmp_update or IMF_IGNORE_DEADLINE_FLAG; deadline <= time + TIME_BASED_FILTER_QOS; else inst_data_next2.ignore_deadline <= time + TIME_BASED_FILTER_QOS; end if; end if; -- *STALE INSTANCE COUNT* if (tmp_bool) then -- Synthesis Guard if (WITH_KEY) then -- Instance was Stale if (inst_data.sample_cnt = 0 and inst_data.writer_bitmap = ZERO_WRITER_BITMAP_ARRAY) then assert (stale_inst_cnt /= 0) severity FAILURE; -- NOTE: The UPDATE_INSTANCE state is only taken if a new Sample is added to an existing Instance. -- Since Instances with Samples are not stale, we have to unmark the Instance. stale_inst_cnt_next <= stale_inst_cnt - 1; end if; end if; else -- Synthesis Guard if (WITH_KEY) then -- Stale Instance Transition if (inst_data.sample_cnt = 0 and inst_data.writer_bitmap /= ZERO_WRITER_BITMAP_ARRAY and tmp_bitmap = (tmp_bitmap'reverse_range => '0')) then stale_inst_cnt_next <= stale_inst_cnt + 1; end if; end if; end if; -- Synthesis Guard if (WITH_KEY) then -- UPDATE Instance inst_op_start <= '1'; inst_opcode <= UPDATE_INSTANCE; inst_mem_fields <= tmp_update; end if; if (not tmp_bool) then -- DONE (Drop Sample) stage_next <= IDLE; elsif (has_data = '1') then stage_next <= FINALIZE_PAYLOAD; cnt_next <= 0; else stage_next <= PRE_SAMPLE_FINALIZE; cnt_next <= 0; end if; end if; when FINALIZE_PAYLOAD => -- Precondition: cur_payload set case (cnt) is -- GET Next Pointer when 0 => 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 <= std_logic_vector(resize(PAYLOAD_MEMORY_MAX_ADDRESS,WORD_WIDTH)); -- 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 <= resize(unsigned(payload_read_data),PAYLOAD_MEMORY_ADDR_WIDTH); stage_next <= PRE_SAMPLE_FINALIZE; cnt_next <= 0; end if; when others => null; end case; when PRE_SAMPLE_FINALIZE => -- Precondition: cur_sample set, inst_data set (IMF_DISPOSED_CNT_FLAG, IMF_NO_WRITERS_CNT_FLAG) -- Wait for instance Update to Complete if (not WITH_KEY or inst_op_done = '1') then assert check_mask(current_imf, IMF_DISPOSED_CNT_FLAG or IMF_NO_WRITERS_CNT_FLAG) severity FAILURE; case (cnt) is -- SET Disposed Generation Counter when 0 => sample_valid_in <= '1'; sample_addr <= cur_sample + SMF_DISPOSED_GEN_CNT_OFFSET; if (newer_inst_sample = '1') then sample_write_data <= std_logic_vector(dis_gen_cnt_latch); else sample_write_data <= std_logic_vector(inst_data.disposed_gen_cnt); end if; -- Memory Flow Control Guard if (sample_ready_in = '1') then cnt_next <= cnt + 1; end if; -- SET No Writer Generation Counter when 1 => sample_valid_in <= '1'; sample_addr <= cur_sample + SMF_NO_WRITERS_GEN_CNT_OFFSET; if (newer_inst_sample = '1') then sample_write_data <= std_logic_vector(no_w_gen_cnt_latch); else sample_write_data <= std_logic_vector(inst_data.no_writers_gen_cnt); end if; -- Memory Flow Control Guard if (sample_ready_in = '1') then -- First Sample if (newest_sample = SAMPLE_MEMORY_MAX_ADDRESS) then stage_next <= FINALIZE_SAMPLE; next_sample_next <= SAMPLE_MEMORY_MAX_ADDRESS; prev_sample_next <= SAMPLE_MEMORY_MAX_ADDRESS; cnt_next <= 0; elsif (DESTINATION_ORDER_QOS = BY_SOURCE_TIMESTAMP_DESTINATION_ORDER_QOS) then stage_next <= FIX_POINTERS; if (prev_sample = SAMPLE_MEMORY_MAX_ADDRESS) then cnt_next <= 1; -- Skip to Previous Pointer Fix else cnt_next <= 0; end if; else stage_next <= FIX_POINTERS; next_sample_next <= SAMPLE_MEMORY_MAX_ADDRESS; prev_sample_next <= newest_sample; cnt_next <= 0; end if; end if; when others => null; end case; end if; when FIX_POINTERS => -- Precondition: prev_sample set, next_sample set case (cnt) is -- Next Pointer (Previous Sample) when 0 => -- Fix Next Pointer sample_valid_in <= '1'; sample_addr <= prev_sample + SMF_NEXT_ADDR_OFFSET; sample_write_data <= std_logic_vector(resize(empty_sample_list_head,WORD_WIDTH)); -- 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 1 => -- Fix Previous Pointer sample_valid_in <= '1'; sample_addr <= next_sample + SMF_PREV_ADDR_OFFSET; sample_write_data <= std_logic_vector(resize(empty_sample_list_head,WORD_WIDTH)); -- 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, cur_sample set case (cnt) is -- GET Next (Empty) Sample when 0 => 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 -- Synthesis Guard if (WITH_KEY) then cnt_next <= cnt + 1; else cnt_next <= cnt + 2; end if; end if; -- SET Instance Pointer when 1 => -- Synthesis Guard if (WITH_KEY) then -- Write Instance Pointer sample_valid_in <= '1'; sample_addr <= cur_sample + SMF_INSTANCE_ADDR_OFFSET; sample_write_data <= std_logic_vector(resize(cur_inst,WORD_WIDTH)); -- Memory Flow Control Guard if (sample_ready_in = '1') then cnt_next <= cnt + 1; end if; end if; -- SET Previous Pointer when 2 => -- Write Previous Pointer sample_valid_in <= '1'; sample_addr <= cur_sample + SMF_PREV_ADDR_OFFSET; sample_write_data <= std_logic_vector(resize(prev_sample,WORD_WIDTH)); -- Memory Flow Control Guard if (sample_ready_in = '1') then cnt_next <= cnt + 1; end if; -- SET Next Pointer when 3 => -- Write Next Pointer sample_valid_in <= '1'; sample_addr <= cur_sample + SMF_NEXT_ADDR_OFFSET; sample_write_data <= std_logic_vector(resize(next_sample,WORD_WIDTH)); -- Memory Flow Control Guard if (sample_ready_in = '1') then cnt_next <= cnt + 1; end if; -- READ Next (Empty) Sample when 4 => sample_ready_out <= '1'; -- Memory Flow Control Guard if (sample_valid_out = '1') then -- Fix new Empty List Head empty_sample_list_head_next <= resize(unsigned(sample_read_data),SAMPLE_MEMORY_ADDR_WIDTH); -- 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; -- If current Sample as no predecessor, it is the oldest if (prev_sample = SAMPLE_MEMORY_MAX_ADDRESS) then oldest_sample_next <= cur_sample; end if; -- Signal Data Available status_sig_next <= status_sig or DATA_AVAILABLE_STATUS; -- Update Lifespan Check Time if (lifespan /= TIME_INVALID and lifespan < lifespan_time) then lifespan_time_next <= lifespan; end if; if (WITH_KEY and remove_oldest_inst_sample = '1') then assert (oldest_sample /= SAMPLE_MEMORY_MAX_ADDRESS) severity FAILURE; cur_sample_next <= oldest_sample; stage_next <= FIND_OLDEST_INST_SAMPLE; cnt_next <= 0; elsif (remove_oldest_sample = '1') then assert (oldest_sample /= SAMPLE_MEMORY_MAX_ADDRESS) severity FAILURE; -- Synthesis Guard if (WITH_KEY) then stage_next <= GET_OLDEST_SAMPLE_INSTANCE; cnt_next <= 0; else cur_sample_next <= oldest_sample; stage_next <= REMOVE_SAMPLE; cnt_next <= 0; end if; else -- DONE stage_next <= IDLE; end if; end if; when others => null; end case; when GENERATE_SAMPLE => -- Precondition: cur_sample set, cur_inst set, inst_data set (IMF_DISPOSED_CNT_FLAG, IMF_NO_WRITERS_CNT_FLAG) -- Wait for Instane Data if (not WITH_KEY or inst_op_done = '1') then assert check_mask(current_imf, IMF_DISPOSED_CNT_FLAG or IMF_NO_WRITERS_CNT_FLAG) severity FAILURE; case (cnt) is -- GET Next Sample (Empty List) when 0 => 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; -- SET Sample Status Info when 1 => sample_valid_in <= '1'; sample_addr <= cur_sample + SMF_STATUS_INFO_OFFSET; sample_write_data <= (SSI_UNREGISTERED_FLAG => '1', others => '0'); -- Memory Flow Control Guard if (sample_ready_in = '1') then cnt_next <= cnt + 1; end if; -- SET Timestamp 1/2 when 2 => sample_valid_in <= '1'; sample_addr <= cur_sample + SMF_TIMESTAMP_OFFSET; sample_write_data <= std_logic_vector(time(0)); -- Memory Flow Control Guard if (sample_ready_in = '1') then cnt_next <= cnt + 1; end if; -- SET Timestamp 2/2 when 3 => sample_valid_in <= '1'; sample_addr <= cur_sample + SMF_TIMESTAMP_OFFSET + 1; sample_write_data <= std_logic_vector(time(1)); -- Memory Flow Control Guard if (sample_ready_in = '1') then cnt_next <= cnt + 1; end if; -- SET Lifespan 1/2 when 4 => sample_valid_in <= '1'; sample_addr <= cur_sample + SMF_LIFESPAN_DEADLINE_OFFSET; sample_write_data <= std_logic_vector(TIME_INVALID(0)); -- Memory Flow Control Guard if (sample_ready_in = '1') then cnt_next <= cnt + 1; end if; -- SET Lifespan 2/2 when 5 => sample_valid_in <= '1'; sample_addr <= cur_sample + SMF_LIFESPAN_DEADLINE_OFFSET + 1; sample_write_data <= std_logic_vector(TIME_INVALID(1)); -- Memory Flow Control Guard if (sample_ready_in = '1') then cnt_next <= cnt + 1; end if; -- SET Payload Pointer when 6 => sample_valid_in <= '1'; sample_addr <= cur_sample + SMF_PAYLOAD_ADDR_OFFSET; sample_write_data <= std_logic_vector(resize(PAYLOAD_MEMORY_MAX_ADDRESS,WORD_WIDTH)); -- Memory Flow Control Guard if (sample_ready_in = '1') then cnt_next <= cnt + 1; end if; -- SET Instance Pointer when 7 => sample_valid_in <= '1'; sample_addr <= cur_sample + SMF_INSTANCE_ADDR_OFFSET; sample_write_data <= std_logic_vector(resize(cur_inst,WORD_WIDTH)); -- Memory Flow Control Guard if (sample_ready_in = '1') then cnt_next <= cnt + 1; end if; -- SET Disposed Generation Count when 8 => sample_valid_in <= '1'; sample_addr <= cur_sample + SMF_DISPOSED_GEN_CNT_OFFSET; sample_write_data <= std_logic_vector(inst_data.disposed_gen_cnt); -- Memory Flow Control Guard if (sample_ready_in = '1') then cnt_next <= cnt + 1; end if; -- SET No Writers Generation Count when 9 => sample_valid_in <= '1'; sample_addr <= cur_sample + SMF_NO_WRITERS_GEN_CNT_OFFSET; sample_write_data <= std_logic_vector(inst_data.no_writers_gen_cnt); -- Memory Flow Control Guard if (sample_ready_in = '1') then cnt_next <= cnt + 1; end if; -- SET Previous Sample Pointer when 10 => sample_valid_in <= '1'; sample_addr <= cur_sample + SMF_PREV_ADDR_OFFSET; sample_write_data <= std_logic_vector(resize(newest_sample,WORD_WIDTH)); -- Memory Flow Control Guard if (sample_ready_in = '1') then cnt_next <= cnt + 1; end if; -- SET Next Sample Pointer when 11 => sample_valid_in <= '1'; sample_addr <= cur_sample + SMF_NEXT_ADDR_OFFSET; sample_write_data <= std_logic_vector(resize(SAMPLE_MEMORY_MAX_ADDRESS,WORD_WIDTH)); -- Memory Flow Control Guard if (sample_ready_in = '1') then assert (newest_sample /= SAMPLE_MEMORY_MAX_ADDRESS) severity FAILURE; cnt_next <= cnt + 1; end if; -- SET Next Sample Pointer (Previous Sample) when 12 => sample_valid_in <= '1'; sample_addr <= newest_sample + SMF_NEXT_ADDR_OFFSET; sample_write_data <= std_logic_vector(resize(empty_sample_list_head,WORD_WIDTH)); -- Memory Flow Control Guard if (sample_ready_in = '1') then cnt_next <= cnt + 1; end if; -- READ Next Address (Empty List) when 13 => sample_ready_out <= '1'; -- Memory Flow Control Guard if (sample_valid_out = '1') then -- Update Sample List Pointer newest_sample_next <= cur_sample; empty_sample_list_head_next <= resize(unsigned(sample_read_data), SAMPLE_MEMORY_ADDR_WIDTH); -- Signal Data Available status_sig_next <= status_sig or DATA_AVAILABLE_STATUS; if (WITH_KEY and remove_oldest_inst_sample = '1') then assert (oldest_sample /= SAMPLE_MEMORY_MAX_ADDRESS) severity FAILURE; cur_sample_next <= oldest_sample; stage_next <= FIND_OLDEST_INST_SAMPLE; cnt_next <= 0; elsif (remove_oldest_sample = '1') then assert (oldest_sample /= SAMPLE_MEMORY_MAX_ADDRESS) severity FAILURE; -- Synthesis Guard if (WITH_KEY) then stage_next <= GET_OLDEST_SAMPLE_INSTANCE; cnt_next <= 0; else cur_sample_next <= oldest_sample; stage_next <= REMOVE_SAMPLE; cnt_next <= 0; end if; elsif (trigger_sample_gen = '1') then -- Continue stage_next <= PROCESS_PENDING_SAMPLE_GENERATION; cnt_next <= 1; else -- DONE stage_next <= IDLE; end if; end if; when others => null; end case; end if; when GET_OLDEST_SAMPLE_INSTANCE => -- Synthesis Guard if (WITH_KEY) then 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'; -- Memory Flow Control Guard if (sample_valid_out = '1') then cur_inst_next <= resize(unsigned(sample_read_data),INSTANCE_MEMORY_ADDR_WIDTH); cur_sample_next <= oldest_sample; stage_next <= REMOVE_SAMPLE; cnt_next <= 0; end if; end if; when others => null; end case; end if; when FIND_OLDEST_INST_SAMPLE => -- Precondition: cur_sample set -- Synthesis Guard if (WITH_KEY) then case (cnt) is -- GET Instance Pointer when 0 => sample_valid_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; -- GET Next Sample when 1 => 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; -- READ Instance Pointer when 2 => sample_ready_out <= '1'; -- Memory Flow Control Guard if (sample_valid_out = '1') then -- Oldest Instance Sample Found if (resize(unsigned(sample_read_data),INSTANCE_MEMORY_ADDR_WIDTH) = cur_inst) then sample_abort_read <= '1'; stage_next <= REMOVE_SAMPLE; cnt_next <= 0; else cnt_next <= cnt + 1; end if; end if; -- READ Next Sample when 3 => sample_ready_out <= '1'; -- Memory Flow Control Guard if (sample_valid_out = '1') then cur_sample_next <= resize(unsigned(sample_read_data),SAMPLE_MEMORY_ADDR_WIDTH); cnt_next <= 0; end if; when others => null; end case; end if; when REMOVE_SAMPLE => -- Precondition: cur_sample set, cur_inst set case (cnt) is -- GET Instance Data when 0 => if (not WITH_KEY or (cur_inst = inst_addr_base and check_mask(current_imf, IMF_SAMPLE_CNT_FLAG or IMF_WRITER_BITMAP_FLAG))) then cnt_next <= cnt + 1; else -- Memory Operation Guard if (inst_op_done = '1') then inst_op_start <= '1'; inst_opcode <= GET_INSTANCE; inst_mem_fields <= IMF_SAMPLE_CNT_FLAG or IMF_WRITER_BITMAP_FLAG or IMF_STATUS_FLAG; inst_addr_update <= cur_inst; cnt_next <= cnt + 1; end if; end if; -- GET Previous Sample when 1 => 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; -- GET Next Sample when 2 => 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; -- GET Payload Pointer when 3 => 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 4 => sample_ready_out <= '1'; -- Memory Flow Control Guard if (sample_valid_out = '1') then prev_sample_next <= resize(unsigned(sample_read_data),SAMPLE_MEMORY_ADDR_WIDTH); cnt_next <= cnt + 1; end if; -- READ Next Sample when 5 => sample_ready_out <= '1'; -- Memory Flow Control Guard if (sample_valid_out = '1') then next_sample_next <= resize(unsigned(sample_read_data),SAMPLE_MEMORY_ADDR_WIDTH); -- 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; cnt_next <= cnt + 2; --Skip Next Step else cnt_next <= cnt + 1; end if; end if; -- SET Next Pointer (Empty List Tail) when 6 => -- Add Current Sample after Empty List Tail sample_valid_in <= '1'; sample_addr <= empty_sample_list_tail + SMF_NEXT_ADDR_OFFSET; sample_write_data <= std_logic_vector(resize(cur_sample,WORD_WIDTH)); -- Memory Flow Control Guard if (sample_ready_in = '1') then cnt_next <= cnt + 1; end if; -- SET Next Pointer (Current Sample) when 7 => -- Make Current Sample Empty List Tail sample_valid_in <= '1'; sample_addr <= cur_sample + SMF_NEXT_ADDR_OFFSET; sample_write_data <= std_logic_vector(resize(SAMPLE_MEMORY_MAX_ADDRESS,WORD_WIDTH)); -- 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 = SAMPLE_MEMORY_MAX_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 = SAMPLE_MEMORY_MAX_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; -- NOTE: Sample Memory Empty (newest_sample also set to MAX_ADDR) -- Fix Oldest Pointer oldest_sample_next <= SAMPLE_MEMORY_MAX_ADDRESS; 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; -- SET Previous Address (Next Sample) when 8 => -- Remove link to cur_sample sample_valid_in <= '1'; sample_addr <= next_sample + SMF_PREV_ADDR_OFFSET; sample_write_data <= std_logic_vector(resize(prev_sample,WORD_WIDTH)); -- Memory Flow Control Guard if (sample_ready_in = '1') then -- Current Sample is oldest sample (List Head) if (prev_sample = SAMPLE_MEMORY_MAX_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 <= next_sample; cnt_next <= cnt + 2; -- Skip next step else cnt_next <= cnt + 1; end if; end if; -- SET Next Address (Previous Sample) when 9 => -- Remove link to cur_sample sample_valid_in <= '1'; sample_addr <= prev_sample + SMF_NEXT_ADDR_OFFSET; sample_write_data <= std_logic_vector(resize(next_sample,WORD_WIDTH)); -- Memory Flow Control Guard if (sample_ready_in = '1') then cnt_next <= cnt + 1; end if; -- READ Payload Pointer when 10 => sample_ready_out <= '1'; -- Memory Flow Control Guard if (sample_valid_out = '1') then cur_payload_next <= resize(unsigned(sample_read_data),PAYLOAD_MEMORY_ADDR_WIDTH); -- Sample has no Data if (resize(unsigned(sample_read_data),PAYLOAD_MEMORY_ADDR_WIDTH) = PAYLOAD_MEMORY_MAX_ADDRESS) then stage_next <= POST_SAMPLE_REMOVE; -- Payload Memory Full elsif (empty_payload_list_head = PAYLOAD_MEMORY_MAX_ADDRESS) then -- Fix Empty List Head empty_payload_list_head_next <= resize(unsigned(sample_read_data),PAYLOAD_MEMORY_ADDR_WIDTH); stage_next <= POST_SAMPLE_REMOVE; else -- Latch First Payload Slot for later use first_payload_next <= resize(unsigned(sample_read_data),PAYLOAD_MEMORY_ADDR_WIDTH); cnt_next <= cnt + 1; end if; end if; -- GET Next Payload when 11 => 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 12 => payload_ready_out <= '1'; -- Memory Flow Control Guard if (payload_valid_out = '1') then -- Found Empty List Tail if (resize(unsigned(payload_read_data),PAYLOAD_MEMORY_ADDR_WIDTH) = PAYLOAD_MEMORY_MAX_ADDRESS) then cnt_next <= cnt + 1; else cur_payload_next <= resize(unsigned(payload_read_data),PAYLOAD_MEMORY_ADDR_WIDTH); cnt_next <= cnt - 1; end if; end if; -- SET Next Payload Pointer (Last Payload of Current Sample) when 13 => payload_valid_in <= '1'; payload_addr <= cur_payload + PMF_NEXT_ADDR_OFFSET; payload_write_data <= std_logic_vector(resize(empty_payload_list_head,WORD_WIDTH)); -- Fix Empty List Head empty_payload_list_head_next <= first_payload; -- Memory Flow Control Guard if (payload_ready_in = '1') then stage_next <= POST_SAMPLE_REMOVE; end if; when others => null; end case; when POST_SAMPLE_REMOVE => -- Precondition: inst_data set (IMF_SAMPLE_CNT_FLAG, IMF_WRITER_BITMAP_FLAG, IMF_STATUS_FLAG) -- Memory Operation Guard if (not WITH_KEY or inst_op_done = '1') then assert check_mask(current_imf, IMF_SAMPLE_CNT_FLAG or IMF_WRITER_BITMAP_FLAG or IMF_STATUS_FLAG) severity FAILURE; -- Synthesis Guard if (WITH_KEY) then -- Stale Instance Update if (inst_data.sample_cnt = 1 and inst_data.writer_bitmap = ZERO_WRITER_BITMAP_ARRAY) then stale_inst_cnt_next <= stale_inst_cnt + 1; end if; inst_op_start <= '1'; inst_opcode <= UPDATE_INSTANCE; inst_mem_fields <= IMF_SAMPLE_CNT_FLAG; sample_cnt <= inst_data.sample_cnt - 1; else inst_data_next2.sample_cnt <= inst_data.sample_cnt - 1; end if; if (wait_for_sample_removal = '1' or inst_data.status_info(ISI_GENERATE_SAMPLE_FLAG) = '1') then trigger_sample_gen_next <= '1'; -- Reset wait_for_sample_removal_next <= '0'; end if; -- Reset remove_oldest_inst_sample_next <= '0'; remove_oldest_sample_next <= '0'; if (is_take = '1') then -- cur_inst has no more samples in collection if (si_sample_rank_sig = 0) then -- Skipped Sample available if (sample_p2 /= SAMPLE_MEMORY_MAX_ADDRESS) then cur_sample_next <= sample_p2; else cur_sample_next <= sample_p1; end if; cur_inst_next <= INSTANCE_MEMORY_MAX_ADDRESS; sample_p2_next <= SAMPLE_MEMORY_MAX_ADDRESS; pre_calculated_next <= '0'; else cur_sample_next <= sample_p1; end if; sample_p1_next <= SAMPLE_MEMORY_MAX_ADDRESS; sel_sample_next <= SAMPLE_MEMORY_MAX_ADDRESS; -- Continue Processing 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 -- DONE stage_next <= IDLE; else -- Continue Search cur_sample_next <= next_sample; stage_next <= CHECK_LIFESPAN; cnt_next <= 0; end if; elsif (trigger_sample_gen = '1') then -- Continue stage_next <= PROCESS_PENDING_SAMPLE_GENERATION; cnt_next <= 1; else -- DONE stage_next <= IDLE; end if; end if; when SKIP_AND_RETURN => case (cnt) is -- SKIP READ when 0 => ready_in_rtps <= '1'; -- Wait until last word from input if (last_word_in_rtps = '1') then cnt_next <= cnt + 1; end if; -- Return Code when 1 => done_rtps <= '1'; ret_rtps <= rtps_return_code_latch; -- DONE stage_next <= IDLE; when others => null; end case; when REMOVE_WRITER => -- Precondition: inst_data set (IMF_WRITER_BITMAP_FLAG, IMF_STATUS_FLAG, IMF_SAMPLE_CNT_FLAG) -- Synthesis Guard if (WITH_KEY) then -- Memory Operation Guard if (inst_op_done = '1') then case (cnt) is when 0 => assert check_mask(current_imf, IMF_WRITER_BITMAP_FLAG or IMF_STATUS_FLAG or IMF_SAMPLE_CNT_FLAG) severity FAILURE; -- No More Instances if (inst_addr_base = INSTANCE_MEMORY_MAX_ADDRESS) then -- DONE done_rtps <= '1'; ret_rtps <= OK; stage_next <= IDLE; else -- Convert Writer Bitmap to SLV tmp_bitmap := from_writer_bitmap_array(inst_data.writer_bitmap); -- Remove Writer tmp_bitmap(writer_id) := '0'; -- NOTE: writer_bitmap is not latched, since the memory process is latching it at the -- same clock cycle. -- Convert Back writer_bitmap <= to_writer_bitmap_array(tmp_bitmap); -- NOT_ALIVE_NO_WRITERS Transition if (tmp_bitmap = (tmp_bitmap'reverse_range => '0') and inst_data.status_info(ISI_NOT_ALIVE_DISPOSED_FLAG) = '0') then trigger_sample_gen_next <= '1'; status_info_update <= inst_data.status_info; status_info_update(ISI_NOT_ALIVE_NO_WRITERS_FLAG) <= '1'; status_info_update(ISI_GENERATE_SAMPLE_FLAG) <= '1'; 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; inst_mem_fields <= IMF_WRITER_BITMAP_FLAG; end if; -- Update Stale Instance Count if (tmp_bitmap = (tmp_bitmap'reverse_range => '0') and inst_data.sample_cnt = 0) then stale_inst_cnt_next <= stale_inst_cnt + 1; end if; -- Continue cnt_next <= 1; end if; when 1 => inst_op_start <= '1'; inst_opcode <= GET_NEXT_INSTANCE; inst_mem_fields <= IMF_STATUS_FLAG or IMF_SAMPLE_CNT_FLAG or IMF_WRITER_BITMAP_FLAG; stage_next <= REMOVE_WRITER; cnt_next <= 0; when 2 => inst_op_start <= '1'; inst_opcode <= GET_FIRST_INSTANCE; inst_mem_fields <= IMF_STATUS_FLAG or IMF_SAMPLE_CNT_FLAG or IMF_WRITER_BITMAP_FLAG; stage_next <= REMOVE_WRITER; cnt_next <= 0; when others => null; end case; end if; end if; when REMOVE_STALE_INSTANCE => -- Precondition: inst_data set (IMF_SAMPLE_CNT_FLAG, IMF_WRITER_BITMAP_FLAG) -- Synthesis Guard if (WITH_KEY) then -- Wait for Instance Data if (inst_op_done = '1') then case (cnt) is -- Find and Remove First Stale Instance when 0 => assert check_mask(current_imf, IMF_SAMPLE_CNT_FLAG or IMF_WRITER_BITMAP_FLAG) severity FAILURE; -- Iterated through all Instances if (inst_addr_base = INSTANCE_MEMORY_MAX_ADDRESS) then -- NOTE: We should enter this state only if there is at least one stale Instance to be removed, so we should never enter this branch. assert FALSE severity FAILURE; stage_next <= IDLE; else -- Found Stale Instance (No Samples and No Active Writers) if (inst_data.sample_cnt = 0 and inst_data.writer_bitmap = ZERO_WRITER_BITMAP_ARRAY) then -- Remove Stale Instance inst_op_start <= '1'; inst_opcode <= REMOVE_INSTANCE; -- Update Stale Instance Count stale_inst_cnt_next <= stale_inst_cnt - 1; cnt_next <= cnt + 1; else -- Continue Search 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; -- Insert New Instance when 1 => inst_op_start <= '1'; inst_opcode <= INSERT_INSTANCE; status_info_update <= (ISI_LIVELINESS_FLAG => '1', ISI_NOT_ALIVE_DISPOSED_FLAG => sample_status_info(SSI_DISPOSED_FLAG), others => '0'); sample_cnt <= to_unsigned(1, WORD_WIDTH); deadline <= (time + TIME_BASED_FILTER_QOS) when (TIME_BASED_FILTER_QOS /= DURATION_ZERO) else TIME_INVALID; tmp_bitmap := (others => '0'); tmp_bitmap(writer_id) := '1'; writer_bitmap <= to_writer_bitmap_array(tmp_bitmap); -- Latch Instance Pointer cur_inst_next <= inst_empty_head; if (DESTINATION_ORDER_QOS = BY_SOURCE_TIMESTAMP_DESTINATION_ORDER_QOS and newest_sample /= SAMPLE_MEMORY_MAX_ADDRESS) then stage_next <= FIND_POS; next_sample_next <= SAMPLE_MEMORY_MAX_ADDRESS; prev_sample_next <= newest_sample; cur_sample_next <= newest_sample; cnt_next <= 0; else if (has_data = '1') then stage_next <= FINALIZE_PAYLOAD; cnt_next <= 0; else stage_next <= PRE_SAMPLE_FINALIZE; cnt_next <= 0; end if; end if; when others => null; end case; end if; end if; when GET_NEXT_SAMPLE => -- Precondition: cur_sample set, cur_inst set, si_sample_rank_sig set case (cnt) is -- GET Next Sample when 0 => 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 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 -- Synthesis Guard if (WITH_KEY) then cnt_next <= cnt + 1; else cnt_next <= cnt + 2; -- Skip Next Step end if; end if; -- GET Instance Pointer when 2 => -- Synthesis Guard if (WITH_KEY) then 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; end if; -- READ Next Sample when 3 => sample_ready_out <= '1'; -- Memory Control Flow Guard if (sample_valid_out = '1') then next_sample_next <= resize(unsigned(sample_read_data),SAMPLE_MEMORY_ADDR_WIDTH); cnt_next <= cnt + 1; end if; -- READ Status Info when 4 => sample_ready_out <= '1'; -- Memory Control Flow Guard if (sample_valid_out = '1') then tmp_bool := TRUE; -- Check Sample State case (sample_state) is when READ_SAMPLE_STATE => if (sample_read_data(SSI_READ_FLAG) /= '1') then tmp_bool := FALSE; end if; when NOT_READ_SAMPLE_STATE => if (sample_read_data(SSI_READ_FLAG) /= '0') then tmp_bool := FALSE; end if; when ANY_SAMPLE_STATE => null; -- Uknown Sample State when others => tmp_bool := FALSE; end case; -- Latch Sample Status Info sample_status_info_next <= sample_read_data; if (sample_read_data(SSI_READ_FLAG) = '1') then si_sample_state_sig_next <= READ_SAMPLE_STATE; else si_sample_state_sig_next <= NOT_READ_SAMPLE_STATE; end if; -- Sample Passes Checks if (tmp_bool) then if (WITH_KEY) then cnt_next <= cnt + 1; else -- First Instance Sample -- NOTE: If sample rank is bigger than zero, we have already accepted the instance. if (si_sample_rank_sig = 0) then cnt_next <= cnt + 3; --Skip to Check Instance State else -- Select Sample collection_cnt_next <= collection_cnt + 1; sel_sample_next <= cur_sample; -- Latch Next Sample (For resume purposes) sample_p1_next <= next_sample; si_sample_rank_sig_next <= si_sample_rank_sig - 1; cnt_next <= cnt + 4; --Skip all Instance Related States end if; end if; else -- Sample not in collection, Skip Sample cnt_next <= 18; sample_abort_read <= '1'; end if; end if; -- READ Instance Pointer when 5 => -- Synthesis Guard if (WITH_KEY) then 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 /= resize(unsigned(sample_read_data),INSTANCE_MEMORY_ADDR_WIDTH)) then -- Consecutive Instance Sample Order if (not ORDERED_ACCESS or PRESENTATION_QOS = INSTANCE_PRESENTATION_QOS or single_instance = '1') then -- Skip Sample cnt_next <= 18; sample_abort_read <= '1'; -- Latch first skipped Sample if (sample_p2 = SAMPLE_MEMORY_MAX_ADDRESS) then sample_p2_next <= cur_sample; end if; else -- Get Instance Data next_inst_next <= resize(unsigned(sample_read_data),INSTANCE_MEMORY_ADDR_WIDTH); cnt_next <= cnt + 1; end if; else -- Select Sample collection_cnt_next <= collection_cnt + 1; sel_sample_next <= cur_sample; -- Latch Next Sample (For resume purposes) sample_p1_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_next <= si_sample_rank_sig - 1; end if; -- Skip Instance Operation cnt_next <= cnt + 3; end if; else -- Get Instance Data next_inst_next <= resize(unsigned(sample_read_data),INSTANCE_MEMORY_ADDR_WIDTH); cnt_next <= cnt + 1; end if; end if; end if; -- Get Instance Data when 6 => -- Synthesis Guard if (WITH_KEY) then -- Memory Operation Guard if (inst_op_done = '1') then inst_op_start <= '1'; inst_opcode <= GET_INSTANCE; inst_mem_fields <= IMF_STATUS_FLAG; inst_addr_update <= next_inst; cnt_next <= cnt + 1; end if; end if; -- Check Instance Data when 7 => -- Wait for Instance Data if (not WITH_KEY or inst_op_done = '1') then assert check_mask(current_imf, IMF_STATUS_FLAG) severity FAILURE; assert (next_inst = inst_addr_base) severity FAILURE; -- DEFAULT tmp_bool := TRUE; -- Check Instance State case (instance_state) is when ALIVE_INSTANCE_STATE => if (inst_data.status_info(ISI_NOT_ALIVE_DISPOSED_FLAG) = '1' or inst_data.status_info(ISI_NOT_ALIVE_NO_WRITERS_FLAG) = '1') then tmp_bool := FALSE; end if; when NOT_ALIVE_DISPOSED_INSTANCE_STATE => if (inst_data.status_info(ISI_NOT_ALIVE_DISPOSED_FLAG) = '0') then tmp_bool := FALSE; end if; when NOT_ALIVE_NO_WRITERS_INSTANCE_STATE => if (inst_data.status_info(ISI_NOT_ALIVE_NO_WRITERS_FLAG) = '0') then tmp_bool := FALSE; end if; when NOT_ALIVE_INSTANCE_STATE => if (inst_data.status_info(ISI_NOT_ALIVE_DISPOSED_FLAG) = '0' and inst_data.status_info(ISI_NOT_ALIVE_NO_WRITERS_FLAG) = '0') then tmp_bool := FALSE; end if; when ANY_INSTANCE_STATE => null; when others => tmp_bool := FALSE; end case; -- Check View State case (view_state) is when NEW_VIEW_STATE => if (inst_data.status_info(ISI_VIEW_FLAG) = '1') then tmp_bool := FALSE; end if; when NOT_NEW_VIEW_STATE => if (inst_data.status_info(ISI_VIEW_FLAG) = '0') then tmp_bool := FALSE; end if; when ANY_VIEW_STATE => null; when others => tmp_bool := FALSE; end case; -- Check Instance Mark if (inst_data.status_info(ISI_MARK_FLAG) = '1') then -- Skip Marked Instance tmp_bool := FALSE; end if; -- Instance Passes Checks if (tmp_bool) then -- Select Sample collection_cnt_next <= collection_cnt + 1; collection_cnt_max_next <= collection_cnt + 1; si_sample_rank_sig_next <= (others => '0'); cur_inst_next <= next_inst; sel_sample_next <= cur_sample; -- Latch Next Sample (For resume purposes) sample_p1_next <= next_sample; cnt_next <= cnt + 1; -- Reset pre_calculated_next <= '0'; else if (WITH_KEY) then -- Skip Sample cnt_next <= 18; sample_abort_read <= '1'; else -- Instance does not pass Checks done_dds <= '1'; return_code_dds <= RETCODE_NO_DATA; stage_next <= IDLE; end if; end if; end if; -- GET Timestamp 1/2 when 8 => sample_valid_in <= '1'; sample_addr <= cur_sample + SMF_TIMESTAMP_OFFSET; sample_read <= '1'; -- Memory Control Flow Guard if (sample_ready_in = '1') then cnt_next <= cnt + 1; end if; -- GET Timestamp 2/2 when 9 => sample_valid_in <= '1'; sample_addr <= cur_sample + SMF_TIMESTAMP_OFFSET + 1; sample_read <= '1'; -- Memory Control Flow Guard if (sample_ready_in = '1') then cnt_next <= cnt + 1; end if; -- GET Payload Pointer when 10 => 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 11 => 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 12 => 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 Timestamp 1/2 when 13 => sample_ready_out <= '1'; -- Memory Control Flow Guard if (sample_valid_out = '1') then si_source_timestamp_sig_next(0) <= unsigned(sample_read_data); cnt_next <= cnt + 1; end if; -- READ Timestamp 2/2 when 14 => sample_ready_out <= '1'; -- Memory Control Flow Guard if (sample_valid_out = '1') then si_source_timestamp_sig_next(1) <= unsigned(sample_read_data); cnt_next <= cnt + 1; end if; -- READ Payload Pointer when 15 => sample_ready_out <= '1'; -- Memory Control Flow Guard if (sample_valid_out = '1') then -- Latch Payload Address cur_payload_next <= resize(unsigned(sample_read_data),PAYLOAD_MEMORY_ADDR_WIDTH); cnt_next <= cnt + 1; end if; -- READ Disposed Generation Count when 16 => 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 17 => 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 <= unsigned(si_disposed_generation_count_sig) + unsigned(sample_read_data); if (pre_calculated = '0') then -- Reset collection_generation_rank_next <= unsigned(si_disposed_generation_count_sig) + unsigned(sample_read_data); end if; cnt_next <= cnt + 1; end if; -- Exit State when 18 => -- Exit Condition (Sample Selected) if (sel_sample /= SAMPLE_MEMORY_MAX_ADDRESS) then -- Sample not marked as Read if (sample_status_info(SSI_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(SSI_READ_FLAG) <= '1'; -- Memory Control Flow Guard if (sample_ready_in = '1') then -- Pre-Calculation already done for selected Instance (Or not necessary) if (pre_calculated = '1' or collection_cnt_max = max_samples_latch or next_sample = SAMPLE_MEMORY_MAX_ADDRESS) then stage_next <= FINALIZE_SAMPLE_INFO; cnt_next <= 0; else -- Calculate Instance Sample Ranks cur_sample_next <= next_sample; stage_next <= PRE_CALCULATE; cnt_next <= 0; end if; end if; else -- Pre-Calculation already done for selected Instance (Or not necessary) if (pre_calculated = '1' or collection_cnt_max = max_samples_latch or next_sample = SAMPLE_MEMORY_MAX_ADDRESS) then stage_next <= FINALIZE_SAMPLE_INFO; cnt_next <= 0; else -- Calculate Instance Sample Ranks cur_sample_next <= next_sample; stage_next <= PRE_CALCULATE; cnt_next <= 0; end if; end if; -- First Sample Selected if (collection_cnt = 1) then done_dds <= '1'; return_code_dds <= RETCODE_OK; end if; else -- End of Samples if (next_sample = SAMPLE_MEMORY_MAX_ADDRESS) then -- Collection Empty if (collection_cnt = 0) then -- READ_NEXT_INSTANCE/TAKE_NEXT_INSTANCE Operation if (WITH_KEY and dynamic_next_instance = '1') then -- NOTE: We selected a compatible instance, but the instance has no compatible samples. -- Find next compatible instance. stage_next <= FIND_NEXT_INSTANCE; cnt_next <= 1; else done_dds <= '1'; return_code_dds <= RETCODE_NO_DATA; stage_next <= IDLE; end if; else -- Mark End of Collection eoc_sig_next <= '1'; stage_next <= IDLE; -- Consecutive Instance Sample Order of multiple Instances if ((not ORDERED_ACCESS or PRESENTATION_QOS = INSTANCE_PRESENTATION_QOS) and single_instance = '0') then -- Unmark Instances unmark_instances_flag_next <= '1'; end if; end if; else -- Continue Searching cur_sample_next <= next_sample; cnt_next <= 0; end if; end if; when others => null; end case; when PRE_CALCULATE => -- Precondition: cur_sample set, cur_inst set case (cnt) is -- GET Next Sample when 0 => 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 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 -- Synthesis Guard if (WITH_KEY) then cnt_next <= cnt + 1; else cnt_next <= cnt + 2; --Skip Next Step end if; end if; -- GET Instance Pointer when 2 => -- Synthesis Guard if (WITH_KEY) then 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; 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 <= resize(unsigned(sample_read_data),SAMPLE_MEMORY_ADDR_WIDTH); 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 tmp_bool := TRUE; -- Check Sample State case (sample_state) is when READ_SAMPLE_STATE => if (sample_read_data(SSI_READ_FLAG) /= '1') then tmp_bool := FALSE; end if; when NOT_READ_SAMPLE_STATE => if (sample_read_data(SSI_READ_FLAG) /= '0') then tmp_bool := FALSE; end if; when ANY_SAMPLE_STATE => null; -- Uknown Sample State when others => tmp_bool := FALSE; end case; -- Sample Passes Checks if (tmp_bool) then -- Synthesis Guard if (WITH_KEY) then cnt_next <= cnt + 1; else -- 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 + 2; --Skip Next Step end if; else -- Skip Sample cnt_next <= 12; sample_abort_read <= '1'; end if; end if; -- READ Instance Pointer when 7 => -- Synthesis Guard if (WITH_KEY) then sample_ready_out <= '1'; -- Memory Control Flow Guard if (sample_valid_out = '1') then -- Same Instance if (resize(unsigned(sample_read_data),INSTANCE_MEMORY_ADDR_WIDTH) = 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 -- 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; end if; -- READ Disposed Generation Count when 8 => sample_ready_out <= '1'; -- Memory Control Flow Guard if (sample_valid_out = '1') then -- Calculate highest collection generation rank collection_generation_rank_next <= unsigned(sample_read_data); cnt_next <= cnt + 1; end if; -- READ No Writers Generation Count when 9 => sample_ready_out <= '1'; -- Memory Control Flow Guard if (sample_valid_out = '1') then -- Calculate highest collection generation rank collection_generation_rank_next <= collection_generation_rank + unsigned(sample_read_data); -- Skip Instance Check cnt_next <= cnt + 3; end if; -- Get Instance Data when 10 => -- Synthesis Guard if (WITH_KEY) then -- Memory Operation Guard if (inst_op_done = '1') then inst_op_start <= '1'; inst_opcode <= GET_INSTANCE; inst_mem_fields <= IMF_STATUS_FLAG; inst_addr_update <= next_inst; cnt_next <= cnt + 1; end if; end if; -- Check Instance Data when 11 => -- Synthesis Guard if (WITH_KEY) then -- Wait for Instance Data if (inst_op_done = '1') then assert check_mask(current_imf, IMF_STATUS_FLAG) severity FAILURE; assert (next_inst = inst_addr_base) severity FAILURE; -- DEFAULT tmp_bool := TRUE; -- Check Instance State case (instance_state) is when ALIVE_INSTANCE_STATE => if (inst_data.status_info(ISI_NOT_ALIVE_DISPOSED_FLAG) = '1' or inst_data.status_info(ISI_NOT_ALIVE_NO_WRITERS_FLAG) = '1') then tmp_bool := FALSE; end if; when NOT_ALIVE_DISPOSED_INSTANCE_STATE => if (inst_data.status_info(ISI_NOT_ALIVE_DISPOSED_FLAG) = '0') then tmp_bool := FALSE; end if; when NOT_ALIVE_NO_WRITERS_INSTANCE_STATE => if (inst_data.status_info(ISI_NOT_ALIVE_NO_WRITERS_FLAG) = '0') then tmp_bool := FALSE; end if; when NOT_ALIVE_INSTANCE_STATE => if (inst_data.status_info(ISI_NOT_ALIVE_DISPOSED_FLAG) = '0' and inst_data.status_info(ISI_NOT_ALIVE_NO_WRITERS_FLAG) = '0') then tmp_bool := FALSE; end if; when ANY_INSTANCE_STATE => null; when others => tmp_bool := FALSE; end case; -- Check View State case (view_state) is when NEW_VIEW_STATE => if (inst_data.status_info(ISI_VIEW_FLAG) = '1') then tmp_bool := FALSE; end if; when NOT_NEW_VIEW_STATE => if (inst_data.status_info(ISI_VIEW_FLAG) = '0') then tmp_bool := FALSE; end if; when ANY_VIEW_STATE => null; when others => tmp_bool := FALSE; end case; -- Check Instance Mark if (inst_data.status_info(ISI_MARK_FLAG) = '1') then -- Skip Marked Instance tmp_bool := FALSE; end if; -- Instance passes Checks if (tmp_bool) then -- Count Sample collection_cnt_max_next <= collection_cnt_max + 1; end if; cnt_next <= cnt + 1; end if; end if; -- 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_latch) then stage_next <= FINALIZE_SAMPLE_INFO; cnt_next <= 0; pre_calculated_next <= '1'; else -- Continue with next Sample cur_sample_next <= next_sample; cnt_next <= 0; end if; when others => null; end case; when FINALIZE_SAMPLE_INFO => -- Precondition: cur_inst set case (cnt) is -- Finalize Sample Info Data when 0 => -- Wait for Instance Data if (not WITH_KEY or inst_op_done = '1') then -- Instance Data valid if (not WITH_KEY or (inst_addr_base = cur_inst and check_mask(current_imf,IMF_STATUS_FLAG or IMF_KEY_HASH_FLAG or IMF_DISPOSED_CNT_FLAG or IMF_NO_WRITERS_CNT_FLAG))) then -- Sample Info View State if (inst_data.status_info(ISI_VIEW_FLAG) = '0') then si_view_state_sig_next <= NEW_VIEW_STATE; else si_view_state_sig_next <= NOT_NEW_VIEW_STATE; end if; -- Sample Info Instance State if (inst_data.status_info(ISI_NOT_ALIVE_DISPOSED_FLAG) = '1') then si_instance_state_sig_next <= NOT_ALIVE_DISPOSED_INSTANCE_STATE; elsif (inst_data.status_info(ISI_NOT_ALIVE_NO_WRITERS_FLAG) = '1') then si_instance_state_sig_next <= NOT_ALIVE_NO_WRITERS_INSTANCE_STATE; else si_instance_state_sig_next <= ALIVE_INSTANCE_STATE; end if; -- Sample Info Instance Handle si_instance_handle_sig_next <= inst_data.key_hash; -- Sample Info Generation Rank si_generation_rank_sig_next <= collection_generation_rank - cur_generation_rank; -- Sample Info Absolut Generation Rank -- XXX: Possible Worst Case Path (2 32-bit Operations in same clock) si_absolute_generation_rank_sig_next <= (inst_data.disposed_gen_cnt + inst_data.no_writers_gen_cnt) - cur_generation_rank; -- Sample Info Valid Data if (cur_payload /= PAYLOAD_MEMORY_MAX_ADDRESS) then si_valid_data_sig_next <= '1'; else si_valid_data_sig_next <= '0'; end if; si_valid_sig_next <= '1'; cnt_next <= 1; else -- Get Instance Data inst_op_start <= '1'; inst_opcode <= GET_INSTANCE; inst_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; -- Present Data when 1 => -- Synthesis Guard if (DESTINATION_ORDER_QOS = BY_SOURCE_TIMESTAMP_DESTINATION_ORDER_QOS) then -- Update Last Read Timestamp if (si_source_timestamp_sig > last_read_ts) then last_read_ts_next <= si_source_timestamp_sig; end if; end if; -- Reset Data Available Status status_sig_next <= status_sig and (not DATA_AVAILABLE_STATUS); -- Wait on User if (si_ack = '1') then -- Sample Data Request if (get_data_dds = '1') then stage_next <= GET_PAYLOAD; cnt_next <= 0; else cnt_next <= 2; -- Invalidate Data si_valid_sig_next <= '0'; end if; end if; -- Post-Present Data when 2 => -- Memory Operation Guard if (not WITH_KEY or inst_op_done = '1') then assert check_mask(current_imf, IMF_STATUS_FLAG) severity FAILURE; -- NOTE: If we have a presentation of consecutive same instance samples of multiple instances, we have to -- mark the instances we have already handled, in order to prevent the GET_NEXT_SAMPLE state to -- re-process them. -- Last Sample of Instance in Collection if (si_sample_rank_sig = 0) then -- Synthesis Guard if (WITH_KEY) then inst_op_start <= '1'; inst_opcode <= UPDATE_INSTANCE; inst_mem_fields <= IMF_STATUS_FLAG; status_info_update <= inst_data.status_info; -- Consecutive Instance Sample Order of multiple Instances if ((not ORDERED_ACCESS or PRESENTATION_QOS = INSTANCE_PRESENTATION_QOS) and single_instance = '0') then -- Mark Instance status_info_update(ISI_MARK_FLAG) <= '1'; end if; -- Instance is NOT_VIEWED and sample is from last generation of Instance if (inst_data.status_info(ISI_VIEW_FLAG) = '0' and si_absolute_generation_rank_sig = 0) then -- Mark Instance as VIEWED status_info_update(ISI_VIEW_FLAG) <= '1'; end if; else -- Instance is NOT_VIEWED and sample is from last generation of Instance if (inst_data.status_info(ISI_VIEW_FLAG) = '0' and si_absolute_generation_rank_sig = 0) then -- Mark Instance as VIEWED inst_data_next2.status_info(ISI_VIEW_FLAG) <= '1'; end if; end if; end if; -- End of Collection if (collection_cnt = max_samples_latch or (sample_p1 = SAMPLE_MEMORY_MAX_ADDRESS and sample_p2 = SAMPLE_MEMORY_MAX_ADDRESS) or (si_sample_rank_sig = 0 and single_instance = '1')) then -- Mark End of Collection eoc_sig_next <= '1'; -- Consecutive Instance Sample Order of multiple Instances if ((not ORDERED_ACCESS or PRESENTATION_QOS = INSTANCE_PRESENTATION_QOS) and single_instance = '0') then -- Unmark Instances unmark_instances_flag_next <= '1'; end if; if (is_take = '1') then cur_sample_next <= sel_sample; stage_next <= REMOVE_SAMPLE; cnt_next <= 0; is_take_next <= '0'; -- Return to IDLE from REMOVE else -- DONE stage_next <= IDLE; end if; else if (is_take = '1') then -- Remove Sample cur_sample_next <= sel_sample; stage_next <= REMOVE_SAMPLE; cnt_next <= 0; else -- cur_inst has no more samples in collection if (si_sample_rank_sig = 0) then -- Skipped Sample available if (sample_p2 /= SAMPLE_MEMORY_MAX_ADDRESS) then cur_sample_next <= sample_p2; else cur_sample_next <= sample_p1; end if; cur_inst_next <= INSTANCE_MEMORY_MAX_ADDRESS; sample_p2_next <= SAMPLE_MEMORY_MAX_ADDRESS; pre_calculated_next <= '0'; else cur_sample_next <= sample_p1; end if; sample_p1_next <= SAMPLE_MEMORY_MAX_ADDRESS; sel_sample_next <= SAMPLE_MEMORY_MAX_ADDRESS; -- Continue Processing stage_next <= GET_NEXT_SAMPLE; cnt_next <= 0; end if; end if; end if; when others => null; end case; when GET_PAYLOAD => -- Precondition: cur_payload set, sample_status_info set -- NOTE: We are using the Burst Capability of the Memory Controller as a FIFO which we -- fill and the output is directly reading. cnt is switching the memory reading states, -- cnt2 signals the offset of the payload read, and cnt3 signals how many Bytes have been -- requested but not yet claimed (i.e. how many Bytes are in the FIFO). -- DEFAULT tmp_bool := FALSE; case (cnt) is -- GET Next Pointer when 0 => -- NOTE: We have to make sure that no pending Reads are in the Memory Controler Buffer, -- else the Next Payload Pointer cannot be read. -- No Pending Reads if (cnt3 = 0) then 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; end if; -- READ Next Pointer when 1 => payload_ready_out <= '1'; -- Memory Flow Control Guard if (payload_valid_out = '1') then next_payload_next <= resize(unsigned(payload_read_data),PAYLOAD_MEMORY_ADDR_WIDTH); cnt2_next <= 1; -- Last Payload Slot is unaligned if (resize(unsigned(payload_read_data),PAYLOAD_MEMORY_ADDR_WIDTH) = PAYLOAD_MEMORY_MAX_ADDRESS and sample_status_info(SSI_ALIGNED_FLAG) = '0') then cnt_next <= cnt + 1; else cnt_next <= cnt + 3; long_latch_next <= std_logic_vector(to_unsigned(PAYLOAD_FRAME_SIZE-1,CDR_LONG_WIDTH)); end if; end if; -- GET Payload Offset when 2 => payload_valid_in <= '1'; payload_addr <= cur_payload + PAYLOAD_FRAME_SIZE-1; payload_read <= '1'; -- Memory Flow Control Guard if (payload_ready_in = '1') then cnt_next <= cnt + 1; end if; -- READ Payload Offset when 3 => payload_ready_out <= '1'; -- Memory Flow Control Guard if (payload_valid_out = '1') then long_latch_next <= payload_read_data; cnt_next <= cnt + 1; end if; -- GET PAYLOAD when 4 => 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 = unsigned(long_latch)) then -- End of Payload if (next_payload = PAYLOAD_MEMORY_MAX_ADDRESS) then -- DONE (Wait for Output to finidh reading) cnt_next <= cnt + 1; else -- Next Payload Slot cur_payload_next <= next_payload; cnt_next <= 0; end if; else cnt2_next <= cnt2 + 1; end if; 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'; data_out_dds <= payload_read_data; -- End of Payload if (cnt3 = 1 and cnt = 5) 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 tmp_bool variable to signal 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; -- Exit Condition if (cnt3 = 1 and cnt = 5) then -- Exit stage_next <= FINALIZE_SAMPLE_INFO; cnt_next <= 2; -- Invalidate Data si_valid_sig_next <= '0'; end if; end if; end if; end if; end if; when FIND_NEXT_INSTANCE => -- Synthesis Guard if (WITH_KEY) then -- 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_mem_fields <= IMF_STATUS_FLAG or IMF_KEY_HASH_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_mem_fields <= IMF_STATUS_FLAG or IMF_KEY_HASH_FLAG; cnt_next <= 2; when 2 => assert check_mask(current_imf, IMF_STATUS_FLAG) severity FAILURE; -- Instance Found if (inst_addr_base /= INSTANCE_MEMORY_MAX_ADDRESS) then -- DEFAULT tmp_bool := TRUE; -- Check Instance Handle (Key Hash) -- XXX: Posible Worst Case Path (128-bit Comparison) if (to_unsigned(inst_data.key_hash) <= to_unsigned(key_hash)) then tmp_bool := FALSE; end if; -- Check Instance State case (instance_state) is when ALIVE_INSTANCE_STATE => if (inst_data.status_info(ISI_NOT_ALIVE_DISPOSED_FLAG) = '1' or inst_data.status_info(ISI_NOT_ALIVE_NO_WRITERS_FLAG) = '1') then tmp_bool := FALSE; end if; when NOT_ALIVE_DISPOSED_INSTANCE_STATE => if (inst_data.status_info(ISI_NOT_ALIVE_DISPOSED_FLAG) = '0') then tmp_bool := FALSE; end if; when NOT_ALIVE_NO_WRITERS_INSTANCE_STATE => if (inst_data.status_info(ISI_NOT_ALIVE_NO_WRITERS_FLAG) = '0') then tmp_bool := FALSE; end if; when NOT_ALIVE_INSTANCE_STATE => if (inst_data.status_info(ISI_NOT_ALIVE_DISPOSED_FLAG) = '0' and inst_data.status_info(ISI_NOT_ALIVE_NO_WRITERS_FLAG) = '0') then tmp_bool := FALSE; end if; when ANY_INSTANCE_STATE => null; when others => tmp_bool := FALSE; end case; -- Check View State case (view_state) is when NEW_VIEW_STATE => if (inst_data.status_info(ISI_VIEW_FLAG) = '1') then tmp_bool := FALSE; end if; when NOT_NEW_VIEW_STATE => if (inst_data.status_info(ISI_VIEW_FLAG) = '0') then tmp_bool := FALSE; end if; when ANY_VIEW_STATE => null; when others => tmp_bool := FALSE; end case; -- Instance Passes Checks if (tmp_bool) then cur_inst_next <= inst_addr_base; stage_next <= GET_NEXT_SAMPLE; cnt_next <= 0; -- Reset sel_sample_next <= SAMPLE_MEMORY_MAX_ADDRESS; sample_p1_next <= SAMPLE_MEMORY_MAX_ADDRESS; sample_p2_next <= SAMPLE_MEMORY_MAX_ADDRESS; 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_mem_fields <= IMF_STATUS_FLAG or IMF_KEY_HASH_FLAG; end if; else -- DONE done_dds <= '1'; return_code_dds <= RETCODE_NO_DATA; stage_next <= IDLE; end if; when others => null; end case; end if; end if; when CHECK_INSTANCE => -- Synthesis Guard if (WITH_KEY) then -- 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 <= SEARCH_INSTANCE_HASH; inst_mem_fields <= IMF_STATUS_FLAG; cnt_next <= cnt + 1; when 1 => assert check_mask(current_imf, IMF_STATUS_FLAG) severity FAILURE; -- Instance Found if (inst_addr_base /= INSTANCE_MEMORY_MAX_ADDRESS) then -- DEFAULT tmp_bool := TRUE; -- Check Instance State case (instance_state) is when ALIVE_INSTANCE_STATE => if (inst_data.status_info(ISI_NOT_ALIVE_DISPOSED_FLAG) = '1' or inst_data.status_info(ISI_NOT_ALIVE_NO_WRITERS_FLAG) = '1') then tmp_bool := FALSE; end if; when NOT_ALIVE_DISPOSED_INSTANCE_STATE => if (inst_data.status_info(ISI_NOT_ALIVE_DISPOSED_FLAG) = '0') then tmp_bool := FALSE; end if; when NOT_ALIVE_NO_WRITERS_INSTANCE_STATE => if (inst_data.status_info(ISI_NOT_ALIVE_NO_WRITERS_FLAG) = '0') then tmp_bool := FALSE; end if; when NOT_ALIVE_INSTANCE_STATE => if (inst_data.status_info(ISI_NOT_ALIVE_DISPOSED_FLAG) = '0' and inst_data.status_info(ISI_NOT_ALIVE_NO_WRITERS_FLAG) = '0') then tmp_bool := FALSE; end if; when ANY_INSTANCE_STATE => null; when others => tmp_bool := FALSE; end case; -- Check View State case (view_state) is when NEW_VIEW_STATE => if (inst_data.status_info(ISI_VIEW_FLAG) = '1') then tmp_bool := FALSE; end if; when NOT_NEW_VIEW_STATE => if (inst_data.status_info(ISI_VIEW_FLAG) = '0') then tmp_bool := FALSE; end if; when ANY_VIEW_STATE => null; when others => tmp_bool := FALSE; end case; -- Instance Passes Checks if (tmp_bool) then -- Get Instance Samples cur_inst_next <= inst_addr_base; stage_next <= GET_NEXT_SAMPLE; cnt_next <= 0; else -- DONE done_dds <= '1'; return_code_dds <= RETCODE_NO_DATA; stage_next <= IDLE; end if; else -- Given Instance does not exist -- DONE done_dds <= '1'; return_code_dds <= RETCODE_BAD_PARAMETER; stage_next <= IDLE; end if; when others => null; end case; end if; end if; when CHECK_LIFESPAN => -- Precondition: cur_sample set, case (cnt) is -- GET Next Sample when 0 => 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_valid_in <= '1'; sample_addr <= cur_sample + SMF_LIFESPAN_DEADLINE_OFFSET; sample_read <= '1'; -- Memory Control Flow Guard if (sample_ready_in = '1') then cnt_next <= cnt + 1; end if; -- GET Lifespan 2/2 when 2 => sample_valid_in <= '1'; sample_addr <= cur_sample + SMF_LIFESPAN_DEADLINE_OFFSET + 1; sample_read <= '1'; -- Memory Control Flow Guard if (sample_ready_in = '1') then if (WITH_KEY) then cnt_next <= cnt + 1; else cnt_next <= cnt + 2; --Skip Next Step end if; end if; -- GET Instance Pointer when 3 => -- Synthesis Guard if (WITH_KEY) then 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; end if; -- READ Next Sample when 4 => sample_ready_out <= '1'; -- Memory Control Flow Guard if (sample_valid_out = '1') then next_sample_next <= resize(unsigned(sample_read_data),SAMPLE_MEMORY_ADDR_WIDTH); cnt_next <= cnt + 1; end if; -- READ Lifespan 1/2 when 5 => 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 6 => 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 if (WITH_KEY) then cnt_next <= cnt + 1; else -- Remove Sample stage_next <= REMOVE_SAMPLE; cnt_next <= 0; end if; else sample_abort_read <= '1'; -- Update Check Time if (tmp_dw /= TIME_INVALID and tmp_dw < lifespan_time) then lifespan_time_next <= tmp_dw; end if; -- 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; -- READ Instance Pointer when 7 => -- Synthesis Guard if (WITH_KEY) then -- Memory Operation Guard if (inst_op_done = '1') then sample_ready_out <= '1'; -- Memory Control Flow Guard if (sample_valid_out = '1') then -- Fetch Instance Data inst_op_start <= '1'; inst_opcode <= GET_INSTANCE; inst_mem_fields <= IMF_STATUS_FLAG or IMF_SAMPLE_CNT_FLAG or IMF_WRITER_BITMAP_FLAG; inst_addr_update <= resize(unsigned(sample_read_data),INSTANCE_MEMORY_ADDR_WIDTH); -- Remove Sample stage_next <= REMOVE_SAMPLE; cnt_next <= 0; end if; end if; end if; when others => null; end case; when PROCESS_PENDING_SAMPLE_GENERATION => -- Synthesis Guard if (WITH_KEY) then -- Wait for Instance Data if (inst_op_done = '1') then case (cnt) is when 0 => inst_op_start <= '1'; inst_opcode <= GET_FIRST_INSTANCE; inst_mem_fields <= IMF_STATUS_FLAG; cnt_next <= cnt + 2; when 1 => -- Continue inst_op_start <= '1'; inst_opcode <= GET_NEXT_INSTANCE; inst_mem_fields <= IMF_STATUS_FLAG; cnt_next <= cnt + 1; when 2 => assert check_mask(current_imf, IMF_STATUS_FLAG) severity FAILURE; -- Instance Found if (inst_addr_base /= INSTANCE_MEMORY_MAX_ADDRESS) then -- Sample needs to be Generated if (inst_data.status_info(ISI_GENERATE_SAMPLE_FLAG) = '1') then -- GET Required Instance Data inst_op_start <= '1'; inst_opcode <= GET_INSTANCE; inst_mem_fields <= IMF_STATUS_FLAG or IMF_SAMPLE_CNT_FLAG or IMF_DISPOSED_CNT_FLAG or IMF_NO_WRITERS_CNT_FLAG; inst_addr_update <= inst_addr_base; cnt_next <= cnt + 1; else -- Continue inst_op_start <= '1'; inst_opcode <= GET_NEXT_INSTANCE; inst_mem_fields <= IMF_STATUS_FLAG; end if; else -- Reset trigger_sample_gen_next <= '0'; -- DONE stage_next <= IDLE; end if; when 3 => assert check_mask(current_imf, IMF_STATUS_FLAG or IMF_SAMPLE_CNT_FLAG) severity FAILURE; -- RESOURCE_LIMITS_QOS (MAX_SAMPLES_PER_INSTANCE) if (WITH_KEY and MAX_SAMPLES_PER_INSTANCE /= LENGTH_UNLIMITED and inst_data.sample_cnt = unsigned(MAX_SAMPLES_PER_INSTANCE)) then if (HISTORY_QOS = KEEP_ALL_HISTORY_QOS and RELIABILITY_QOS = RELIABLE_RELIABILITY_QOS) then -- Continue inst_op_start <= '1'; inst_opcode <= GET_NEXT_INSTANCE; inst_mem_fields <= IMF_STATUS_FLAG; cnt_next <= 2; else -- Accept Change (Remove Oldest Instance Sample) remove_oldest_inst_sample_next <= '1'; -- Update Instance inst_op_start <= '1'; inst_opcode <= UPDATE_INSTANCE; inst_mem_fields <= IMF_STATUS_FLAG or IMF_SAMPLE_CNT_FLAG; sample_cnt <= inst_data.sample_cnt + 1; status_info_update <= inst_data.status_info; status_info_update(ISI_GENERATE_SAMPLE_FLAG) <= '0'; cur_sample_next <= empty_sample_list_head; cur_inst_next <= inst_addr_base; stage_next <= GENERATE_SAMPLE; cnt_next <= 0; 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 wait_for_sample_removal_next <= '1'; -- Reset trigger_sample_gen_next <= '0'; -- DONE stage_next <= IDLE; else -- Accept Change (Remove Oldest Sample) remove_oldest_sample_next <= '1'; -- Update Instance inst_op_start <= '1'; inst_opcode <= UPDATE_INSTANCE; inst_mem_fields <= IMF_STATUS_FLAG or IMF_SAMPLE_CNT_FLAG; sample_cnt <= inst_data.sample_cnt + 1; status_info_update <= inst_data.status_info; status_info_update(ISI_GENERATE_SAMPLE_FLAG) <= '0'; cur_sample_next <= empty_sample_list_head; cur_inst_next <= inst_addr_base; stage_next <= GENERATE_SAMPLE; cnt_next <= 0; end if; else -- Update Instance inst_op_start <= '1'; inst_opcode <= UPDATE_INSTANCE; inst_mem_fields <= IMF_STATUS_FLAG or IMF_SAMPLE_CNT_FLAG; sample_cnt <= inst_data.sample_cnt + 1; status_info_update <= inst_data.status_info; status_info_update(ISI_GENERATE_SAMPLE_FLAG) <= '0'; cur_sample_next <= empty_sample_list_head; cur_inst_next <= inst_addr_base; stage_next <= GENERATE_SAMPLE; cnt_next <= 0; end if; when others => null; end case; end if; end if; when GET_SAMPLE_REJECTED_STATUS => case (cnt) is -- Return Code when 0 => done_dds <= '1'; return_code_dds <= RETCODE_OK; cnt_next <= cnt + 1; -- Total Count when 1 => data_out_dds <= std_logic_vector(sample_rej_cnt); valid_out_dds <= '1'; if (ready_out_dds = '1') then cnt_next <= cnt + 1; end if; -- Total Count Change when 2 => data_out_dds <= std_logic_vector(sample_rej_cnt_change); valid_out_dds <= '1'; if (ready_out_dds = '1') then -- Reset sample_rej_cnt_change_next <= (others => '0'); cnt_next <= cnt + 1; end if; -- Last Reason when 3 => data_out_dds <= sample_rej_last_reason; valid_out_dds <= '1'; if (ready_out_dds = '1') then -- Reset sample_rej_last_reason_next <= NOT_REJECTED; cnt_next <= cnt + 1; end if; -- Last Instance Handle 1/4 when 4 => data_out_dds <= sample_rej_last_inst(0); valid_out_dds <= '1'; if (ready_out_dds = '1') then cnt_next <= cnt + 1; end if; -- Last Instance Handle 2/4 when 5 => data_out_dds <= sample_rej_last_inst(1); valid_out_dds <= '1'; if (ready_out_dds = '1') then cnt_next <= cnt + 1; end if; -- Last Instance Handle 3/4 when 6 => data_out_dds <= sample_rej_last_inst(2); valid_out_dds <= '1'; if (ready_out_dds = '1') then cnt_next <= cnt + 1; end if; -- Last Instance Handle 4/4 when 7 => data_out_dds <= sample_rej_last_inst(3); valid_out_dds <= '1'; last_word_out_dds <= '1'; if (ready_out_dds = '1') then -- Reset sample_rej_last_inst_next <= HANDLE_NIL; status_sig_next <= status_sig and (not SAMPLE_REJECTED_STATUS); -- DONE stage_next <= IDLE; end if; when others => null; end case; when GET_REQUESTED_DEADLINE_MISSED_STATUS => case (cnt) is -- Return Code when 0 => done_dds <= '1'; return_code_dds <= RETCODE_OK; cnt_next <= cnt + 1; -- Total Count when 1 => data_out_dds <= std_logic_vector(deadline_miss_cnt); valid_out_dds <= '1'; if (ready_out_dds = '1') then cnt_next <= cnt + 1; end if; -- Total Count Change when 2 => data_out_dds <= std_logic_vector(deadline_miss_cnt_change); valid_out_dds <= '1'; if (ready_out_dds = '1') then -- Reset deadline_miss_cnt_change_next <= (others => '0'); cnt_next <= cnt + 1; end if; -- Last Instance Handle 1/4 when 3 => data_out_dds <= deadline_miss_last_inst(0); valid_out_dds <= '1'; if (ready_out_dds = '1') then cnt_next <= cnt + 1; end if; -- Last Instance Handle 2/4 when 4 => data_out_dds <= deadline_miss_last_inst(1); valid_out_dds <= '1'; if (ready_out_dds = '1') then cnt_next <= cnt + 1; end if; -- Last Instance Handle 3/4 when 5 => data_out_dds <= deadline_miss_last_inst(2); valid_out_dds <= '1'; if (ready_out_dds = '1') then cnt_next <= cnt + 1; end if; -- Last Instance Handle 4/4 when 6 => data_out_dds <= deadline_miss_last_inst(3); valid_out_dds <= '1'; last_word_out_dds <= '1'; if (ready_out_dds = '1') then -- Reset deadline_miss_last_inst_next <= HANDLE_NIL; status_sig_next <= status_sig and (not REQUESTED_DEADLINE_MISSED_STATUS); -- DONE stage_next <= IDLE; end if; when others => null; end case; when CHECK_DEADLINE => -- Synthesis Guard if (WITH_KEY) then -- Memory Operation Guard if (inst_op_done = '1') then case (cnt) is -- Get First Instance when 0 => inst_op_start <= '1'; inst_opcode <= GET_FIRST_INSTANCE; inst_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_mem_fields <= IMF_KEY_HASH_FLAG or IMF_STATUS_FLAG; cnt_next <= 2; -- Check Instance when 2 => assert check_mask(current_imf, IMF_STATUS_FLAG or IMF_KEY_HASH_FLAG) severity FAILURE; -- Reached End of Instances if (inst_addr_base = INSTANCE_MEMORY_MAX_ADDRESS) then -- DONE stage_next <= IDLE; else -- Instance received Sample if (inst_data.status_info(ISI_LIVELINESS_FLAG) = '1') then -- Reset Liveliness Flag inst_op_start <= '1'; inst_opcode <= UPDATE_INSTANCE; inst_mem_fields <= IMF_STATUS_FLAG; status_info_update <= inst_data.status_info; status_info_update(ISI_LIVELINESS_FLAG) <= '0'; cnt_next <= 1; else -- Update Requested Deadline Missed Status status_sig_next <= status_sig or REQUESTED_DEADLINE_MISSED_STATUS; deadline_miss_cnt_next <= deadline_miss_cnt + 1; deadline_miss_cnt_change_next <= deadline_miss_cnt_change + 1; deadline_miss_last_inst_next <= inst_data.key_hash; cnt_next <= 1; end if; end if; when others => null; end case; end if; end if; when RESET_SAMPLE_MEMORY => case (cnt) is -- Initialize when 0 => prev_sample_next <= SAMPLE_MEMORY_MAX_ADDRESS; cur_sample_next <= (others => '0'); cnt_next <= cnt + 1; -- Set Previous Pointer when 1 => sample_valid_in <= '1'; sample_addr <= cur_sample + SMF_PREV_ADDR_OFFSET; sample_write_data <= std_logic_vector(resize(prev_sample,WORD_WIDTH)); -- Memory Flow Control Guard if (sample_ready_in = '1') then cnt_next <= cnt + 1; end if; -- Set Next Pointer when 2 => sample_valid_in <= '1'; sample_addr <= cur_sample + SMF_NEXT_ADDR_OFFSET; if (cur_sample = MAX_SAMPLE_ADDRESS) then sample_write_data <= std_logic_vector(resize(SAMPLE_MEMORY_MAX_ADDRESS,WORD_WIDTH)); else sample_write_data <= std_logic_vector(resize(cur_sample + SAMPLE_FRAME_SIZE,WORD_WIDTH)); end if; -- Memory Flow Control Guard if (sample_ready_in = '1') then if (cur_sample = MAX_SAMPLE_ADDRESS) then -- DONE stage_next <= RESET_PAYLOAD_MEMORY; cnt_next <= 0; empty_sample_list_head_next <= FIRST_SAMPLE_ADDRESS; empty_sample_list_tail_next <= MAX_SAMPLE_ADDRESS; else -- Continue cur_sample_next <= cur_sample + SAMPLE_FRAME_SIZE; prev_sample_next <= cur_sample; cnt_next <= 1; end if; end if; when others => null; end case; when RESET_PAYLOAD_MEMORY => case (cnt) is -- Initialize when 0 => cur_payload_next <= (others => '0'); cnt_next <= cnt + 1; -- Set Next Pointer when 1 => payload_valid_in <= '1'; payload_addr <= cur_payload + PMF_NEXT_ADDR_OFFSET; if (cur_payload = MAX_PAYLOAD_ADDRESS) then payload_write_data <= std_logic_vector(resize(PAYLOAD_MEMORY_MAX_ADDRESS,WORD_WIDTH)); else payload_write_data <= std_logic_vector(resize(cur_payload + PAYLOAD_FRAME_SIZE,WORD_WIDTH)); end if; -- Memory Flow Control Guard if (payload_ready_in = '1') then if (cur_payload = MAX_PAYLOAD_ADDRESS) then -- DONE stage_next <= IDLE; empty_payload_list_head_next <= FIRST_PAYLOAD_ADDRESS; else cur_payload_next <= cur_payload + PAYLOAD_FRAME_SIZE; end if; end if; when others => null; end case; when others => null; end case; end process; gen_inst_ctrl_prc : if WITH_KEY generate -- *Instance Memory Process* -- STATE DESCRIPTION -- IDLE Idle State. Done Signal is pulled high and Memory FSM accepts new memory operations -- SEARCH_INSTANCE_HASH See Memory OPCODE Description -- SEARCH_INSTANCE_ADDR See Memory OPCODE Description -- GET_NEXT_INSTANCE See Memory OPCODE Description -- GET_INSTANCE_DATA Latch specified Instance Data for use by main process -- FIND_POS Find List position of Instance to be added -- INSERT_INSTANCE See Memory OPCODE Description -- UPDATE_INSTANCE See Memory OPCODE Description -- REMOVE_INSTANCE See Memory OPCODE Description -- UNMARK_INTANCES See Memory OPCODE Description -- RESET_MEMORY Reset Endpoint Memory to Empty State inst_ctrl_prc : process(all) begin -- DEFAULT Registered inst_stage_next <= inst_stage; inst_addr_base_next <= inst_addr_base; 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_data_next <= inst_data; inst_long_latch_next <= inst_long_latch; current_imf_next <= current_imf; -- DEFAULT Unregistered inst_abort_read <= '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 (inst_stage) is when IDLE => inst_op_done <= '1'; if (inst_op_start = '1') then -- Latch Signals needed for Mermory Operation (Use _next signals, because some signals are set in same clk) inst_latch_data_next <= ( key_hash => key_hash_next, status_info => status_info_update, sample_cnt => sample_cnt, gen_cnt => gen_cnt, deadline => deadline, writer_bitmap => writer_bitmap, field_flags => inst_mem_fields, addr => inst_addr_update ); case(inst_opcode) is when SEARCH_INSTANCE_HASH => -- Reset Data current_imf_next <= inst_mem_fields; inst_data_next <= ZERO_INSTANCE_DATA; -- No Instances available if (inst_occupied_head = INSTANCE_MEMORY_MAX_ADDRESS) then inst_addr_base_next <= INSTANCE_MEMORY_MAX_ADDRESS; else inst_prev_addr_base_next <= INSTANCE_MEMORY_MAX_ADDRESS; inst_addr_base_next <= inst_occupied_head; inst_stage_next <= SEARCH_INSTANCE_HASH; inst_cnt_next <= 0; end if; when SEARCH_INSTANCE_ADDR => -- Reset Data current_imf_next <= inst_mem_fields; inst_data_next <= ZERO_INSTANCE_DATA; -- No Instances avialable if (inst_occupied_head = INSTANCE_MEMORY_MAX_ADDRESS) then inst_addr_base_next <= INSTANCE_MEMORY_MAX_ADDRESS; else inst_prev_addr_base_next <= INSTANCE_MEMORY_MAX_ADDRESS; inst_addr_base_next <= inst_occupied_head; inst_stage_next <= SEARCH_INSTANCE_ADDR; inst_cnt_next <= 0; end if; when INSERT_INSTANCE => -- NOTE: Since this process has no way to communicate a failed insert to the main process, it has to be made sure -- by the main process that the operation can succeed (Memory is available) assert (inst_empty_head /= INSTANCE_MEMORY_MAX_ADDRESS) report "Instance Insertion while memory Full" severity FAILURE; -- Reset Data current_imf_next <= (others => '1'); inst_data_next <= ZERO_INSTANCE_DATA; -- First Instance if (inst_occupied_head = INSTANCE_MEMORY_MAX_ADDRESS) then inst_prev_addr_base_next <= INSTANCE_MEMORY_MAX_ADDRESS; inst_next_addr_base_next <= INSTANCE_MEMORY_MAX_ADDRESS; inst_addr_base_next <= inst_empty_head; inst_stage_next <= INSERT_INSTANCE; inst_cnt_next <= 1; -- Skip first Step inst_occupied_head_next <= inst_empty_head; else inst_prev_addr_base_next <= INSTANCE_MEMORY_MAX_ADDRESS; inst_addr_base_next <= inst_occupied_head; inst_stage_next <= FIND_POS; inst_cnt_next <= 0; end if; when UPDATE_INSTANCE => current_imf_next <= current_imf or inst_mem_fields; inst_stage_next <= UPDATE_INSTANCE; if check_mask(inst_mem_fields,IMF_STATUS_FLAG) then inst_cnt_next <= 0; elsif check_mask(inst_mem_fields,IMF_SAMPLE_CNT_FLAG) then inst_cnt_next <= 1; elsif check_mask(inst_mem_fields,IMF_DISPOSED_CNT_FLAG) then inst_cnt_next <= 2; elsif check_mask(inst_mem_fields,IMF_NO_WRITERS_CNT_FLAG) then inst_cnt_next <= 3; elsif (TIME_BASED_FILTER_QOS /= DURATION_ZERO and check_mask(inst_mem_fields,IMF_IGNORE_DEADLINE_FLAG)) then inst_cnt_next <= 4; elsif check_mask(inst_mem_fields,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 => -- Reset current_imf_next <= inst_mem_fields; inst_data_next <= ZERO_INSTANCE_DATA; -- No Instances available if (inst_occupied_head = INSTANCE_MEMORY_MAX_ADDRESS) then inst_addr_base_next <= INSTANCE_MEMORY_MAX_ADDRESS; else inst_prev_addr_base_next <= INSTANCE_MEMORY_MAX_ADDRESS; inst_addr_base_next <= inst_occupied_head; inst_stage_next <= GET_NEXT_INSTANCE; inst_cnt_next <= 0; end if; when GET_NEXT_INSTANCE => -- Reset current_imf_next <= inst_mem_fields; inst_data_next <= ZERO_INSTANCE_DATA; -- No Instances available if (inst_next_addr_base = INSTANCE_MEMORY_MAX_ADDRESS) then inst_addr_base_next <= INSTANCE_MEMORY_MAX_ADDRESS; else inst_prev_addr_base_next <= inst_addr_base; inst_addr_base_next <= inst_next_addr_base; inst_stage_next <= GET_NEXT_INSTANCE; inst_cnt_next <= 0; end if; when REMOVE_INSTANCE => -- Reset current_imf_next <= (others => '0'); inst_data_next <= ZERO_INSTANCE_DATA; inst_stage_next <= REMOVE_INSTANCE; inst_cnt_next <= 0; when GET_INSTANCE => inst_addr_base_next <= inst_addr_update; if (inst_addr_base /= inst_addr_update) then -- Reset current_imf_next <= inst_mem_fields; inst_data_next <= ZERO_INSTANCE_DATA; else current_imf_next <= current_imf or inst_mem_fields; end if; -- Get Instance Data inst_stage_next <= GET_INSTANCE_DATA; if check_mask(inst_mem_fields,IMF_KEY_HASH_FLAG) then inst_cnt_next <= 0; elsif check_mask(inst_mem_fields,IMF_STATUS_FLAG) then inst_cnt_next <= 4; elsif check_mask(inst_mem_fields,IMF_SAMPLE_CNT_FLAG) then inst_cnt_next <= 5; elsif check_mask(inst_mem_fields,IMF_DISPOSED_CNT_FLAG) then inst_cnt_next <= 6; elsif check_mask(inst_mem_fields,IMF_NO_WRITERS_CNT_FLAG) then inst_cnt_next <= 7; elsif (TIME_BASED_FILTER_QOS /= DURATION_ZERO and check_mask(inst_mem_fields,IMF_IGNORE_DEADLINE_FLAG)) then inst_cnt_next <= 8; elsif check_mask(inst_mem_fields,IMF_WRITER_BITMAP_FLAG) then inst_cnt_next <= 10; inst_cnt2_next <= 0; else -- DONE inst_stage_next <= IDLE; end if; when UNMARK_INSTANCES => -- Empty Memory Guard if (inst_occupied_head /= INSTANCE_MEMORY_MAX_ADDRESS) then -- Reset inst_data_next <= ZERO_INSTANCE_DATA; current_imf_next <= (others => '0'); inst_addr_base_next <= inst_occupied_head; inst_stage_next <= UNMARK_INSTANCES; inst_cnt_next <= 0; end if; when others => null; end case; end if; when SEARCH_INSTANCE_HASH => case (inst_cnt) is -- GET Next Instance when 0 => 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_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 => 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 3 => 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 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 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 <= resize(unsigned(inst_read_data),INSTANCE_MEMORY_ADDR_WIDTH); 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 inst_abort_read <= '1'; -- 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; end if; else inst_cnt_next <= inst_cnt + 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 -- No Match if (inst_read_data /= inst_latch_data.key_hash(1)) then inst_abort_read <= '1'; -- 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; end if; else inst_cnt_next <= inst_cnt + 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 -- No Match if (inst_read_data /= inst_latch_data.key_hash(2)) then inst_abort_read <= '1'; -- 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; 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; end if; else -- Get Instance Data inst_stage_next <= GET_INSTANCE_DATA; if check_mask(inst_latch_data.field_flags,IMF_KEY_HASH_FLAG) then inst_cnt_next <= 0; elsif check_mask(inst_latch_data.field_flags,IMF_STATUS_FLAG) then inst_cnt_next <= 4; elsif check_mask(inst_latch_data.field_flags,IMF_SAMPLE_CNT_FLAG) then inst_cnt_next <= 5; elsif check_mask(inst_latch_data.field_flags,IMF_DISPOSED_CNT_FLAG) then inst_cnt_next <= 6; elsif check_mask(inst_latch_data.field_flags,IMF_NO_WRITERS_CNT_FLAG) then inst_cnt_next <= 7; elsif (TIME_BASED_FILTER_QOS /= DURATION_ZERO and check_mask(inst_latch_data.field_flags,IMF_IGNORE_DEADLINE_FLAG)) then inst_cnt_next <= 8; elsif check_mask(inst_latch_data.field_flags,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 => case (inst_cnt) is -- GET Next Instance when 0 => 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_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 <= resize(unsigned(inst_read_data),INSTANCE_MEMORY_ADDR_WIDTH); -- Match if (resize(unsigned(inst_read_data),INSTANCE_MEMORY_ADDR_WIDTH) = inst_latch_data.addr) then -- Get Instance Data inst_stage_next <= GET_INSTANCE_DATA; if check_mask(inst_latch_data.field_flags,IMF_KEY_HASH_FLAG) then inst_cnt_next <= 0; elsif check_mask(inst_latch_data.field_flags,IMF_STATUS_FLAG) then inst_cnt_next <= 4; elsif check_mask(inst_latch_data.field_flags,IMF_SAMPLE_CNT_FLAG) then inst_cnt_next <= 5; elsif check_mask(inst_latch_data.field_flags,IMF_DISPOSED_CNT_FLAG) then inst_cnt_next <= 6; elsif check_mask(inst_latch_data.field_flags,IMF_NO_WRITERS_CNT_FLAG) then inst_cnt_next <= 7; elsif (TIME_BASED_FILTER_QOS /= DURATION_ZERO and check_mask(inst_latch_data.field_flags,IMF_IGNORE_DEADLINE_FLAG)) then inst_cnt_next <= 8; elsif check_mask(inst_latch_data.field_flags,IMF_WRITER_BITMAP_FLAG) then inst_cnt_next <= 10; inst_cnt2_next <= 0; else -- DONE inst_stage_next <= IDLE; end if; -- No Match else -- Reached List Tail, No Match if (resize(unsigned(inst_read_data),INSTANCE_MEMORY_ADDR_WIDTH) = 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; when GET_NEXT_INSTANCE => case (inst_cnt) is -- GET next Instance when 0 => 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_ready_out <= '1'; -- Memory Flow Control Guard if (inst_valid_out = '1') then inst_next_addr_base_next <= resize(unsigned(inst_read_data),INSTANCE_MEMORY_ADDR_WIDTH); -- Get Instance Data inst_stage_next <= GET_INSTANCE_DATA; if check_mask(inst_latch_data.field_flags,IMF_KEY_HASH_FLAG) then inst_cnt_next <= 0; elsif check_mask(inst_latch_data.field_flags,IMF_STATUS_FLAG) then inst_cnt_next <= 4; elsif check_mask(inst_latch_data.field_flags,IMF_SAMPLE_CNT_FLAG) then inst_cnt_next <= 5; elsif check_mask(inst_latch_data.field_flags,IMF_DISPOSED_CNT_FLAG) then inst_cnt_next <= 6; elsif check_mask(inst_latch_data.field_flags,IMF_NO_WRITERS_CNT_FLAG) then inst_cnt_next <= 7; elsif (TIME_BASED_FILTER_QOS /= DURATION_ZERO and check_mask(inst_latch_data.field_flags,IMF_IGNORE_DEADLINE_FLAG)) then inst_cnt_next <= 8; elsif check_mask(inst_latch_data.field_flags,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 => case (inst_cnt) is -- GET Key Hash 1/4 when 0 => 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_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_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_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_flags,IMF_STATUS_FLAG) then inst_cnt_next <= 4; elsif check_mask(inst_latch_data.field_flags,IMF_SAMPLE_CNT_FLAG) then inst_cnt_next <= 5; elsif check_mask(inst_latch_data.field_flags,IMF_DISPOSED_CNT_FLAG) then inst_cnt_next <= 6; elsif check_mask(inst_latch_data.field_flags,IMF_NO_WRITERS_CNT_FLAG) then inst_cnt_next <= 7; elsif (TIME_BASED_FILTER_QOS /= DURATION_ZERO and check_mask(inst_latch_data.field_flags,IMF_IGNORE_DEADLINE_FLAG)) then inst_cnt_next <= 8; elsif check_mask(inst_latch_data.field_flags,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_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_flags,IMF_SAMPLE_CNT_FLAG) then inst_cnt_next <= 5; elsif check_mask(inst_latch_data.field_flags,IMF_DISPOSED_CNT_FLAG) then inst_cnt_next <= 6; elsif check_mask(inst_latch_data.field_flags,IMF_NO_WRITERS_CNT_FLAG) then inst_cnt_next <= 7; elsif (TIME_BASED_FILTER_QOS /= DURATION_ZERO and check_mask(inst_latch_data.field_flags,IMF_IGNORE_DEADLINE_FLAG)) then inst_cnt_next <= 8; elsif check_mask(inst_latch_data.field_flags,IMF_WRITER_BITMAP_FLAG) then inst_cnt_next <= 10; inst_cnt2_next <= 0; else if check_mask(inst_latch_data.field_flags,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_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_flags,IMF_DISPOSED_CNT_FLAG) then inst_cnt_next <= 6; elsif check_mask(inst_latch_data.field_flags,IMF_NO_WRITERS_CNT_FLAG) then inst_cnt_next <= 7; elsif (TIME_BASED_FILTER_QOS /= DURATION_ZERO and check_mask(inst_latch_data.field_flags,IMF_IGNORE_DEADLINE_FLAG)) then inst_cnt_next <= 8; elsif check_mask(inst_latch_data.field_flags,IMF_WRITER_BITMAP_FLAG) then inst_cnt_next <= 10; inst_cnt2_next <= 0; else if check_mask(inst_latch_data.field_flags,IMF_KEY_HASH_FLAG) then inst_cnt_next <= 11; elsif check_mask(inst_latch_data.field_flags,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_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_flags,IMF_NO_WRITERS_CNT_FLAG) then inst_cnt_next <= 7; elsif (TIME_BASED_FILTER_QOS /= DURATION_ZERO and check_mask(inst_latch_data.field_flags,IMF_IGNORE_DEADLINE_FLAG)) then inst_cnt_next <= 8; elsif check_mask(inst_latch_data.field_flags,IMF_WRITER_BITMAP_FLAG) then inst_cnt_next <= 10; inst_cnt2_next <= 0; else if check_mask(inst_latch_data.field_flags,IMF_KEY_HASH_FLAG) then inst_cnt_next <= 11; elsif check_mask(inst_latch_data.field_flags,IMF_STATUS_FLAG) then inst_cnt_next <= 15; elsif check_mask(inst_latch_data.field_flags,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_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_flags,IMF_IGNORE_DEADLINE_FLAG)) then inst_cnt_next <= 8; elsif check_mask(inst_latch_data.field_flags,IMF_WRITER_BITMAP_FLAG) then inst_cnt_next <= 10; inst_cnt2_next <= 0; else if check_mask(inst_latch_data.field_flags,IMF_KEY_HASH_FLAG) then inst_cnt_next <= 11; elsif check_mask(inst_latch_data.field_flags,IMF_STATUS_FLAG) then inst_cnt_next <= 15; elsif check_mask(inst_latch_data.field_flags,IMF_SAMPLE_CNT_FLAG) then inst_cnt_next <= 16; elsif check_mask(inst_latch_data.field_flags,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 => -- 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_flags,IMF_WRITER_BITMAP_FLAG) then inst_cnt_next <= 10; inst_cnt2_next <= 0; else if check_mask(inst_latch_data.field_flags,IMF_KEY_HASH_FLAG) then inst_cnt_next <= 11; elsif check_mask(inst_latch_data.field_flags,IMF_STATUS_FLAG) then inst_cnt_next <= 15; elsif check_mask(inst_latch_data.field_flags,IMF_SAMPLE_CNT_FLAG) then inst_cnt_next <= 16; elsif check_mask(inst_latch_data.field_flags,IMF_DISPOSED_CNT_FLAG) then inst_cnt_next <= 17; elsif check_mask(inst_latch_data.field_flags,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 = WRITER_BITMAP_ARRAY_TYPE'length-1) then if check_mask(inst_latch_data.field_flags,IMF_KEY_HASH_FLAG) then inst_cnt_next <= 11; elsif check_mask(inst_latch_data.field_flags,IMF_STATUS_FLAG) then inst_cnt_next <= 15; elsif check_mask(inst_latch_data.field_flags,IMF_SAMPLE_CNT_FLAG) then inst_cnt_next <= 16; elsif check_mask(inst_latch_data.field_flags,IMF_DISPOSED_CNT_FLAG) then inst_cnt_next <= 17; elsif check_mask(inst_latch_data.field_flags,IMF_NO_WRITERS_CNT_FLAG) then inst_cnt_next <= 18; elsif (TIME_BASED_FILTER_QOS /= DURATION_ZERO and check_mask(inst_latch_data.field_flags,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_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_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_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_data_next.key_hash(3) <= inst_read_data; if check_mask(inst_latch_data.field_flags,IMF_STATUS_FLAG) then inst_cnt_next <= 15; elsif check_mask(inst_latch_data.field_flags,IMF_SAMPLE_CNT_FLAG) then inst_cnt_next <= 16; elsif check_mask(inst_latch_data.field_flags,IMF_DISPOSED_CNT_FLAG) then inst_cnt_next <= 17; elsif check_mask(inst_latch_data.field_flags,IMF_NO_WRITERS_CNT_FLAG) then inst_cnt_next <= 18; elsif (TIME_BASED_FILTER_QOS /= DURATION_ZERO and check_mask(inst_latch_data.field_flags,IMF_IGNORE_DEADLINE_FLAG)) then inst_cnt_next <= 19; elsif check_mask(inst_latch_data.field_flags,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_data_next.status_info <= inst_read_data; if check_mask(inst_latch_data.field_flags,IMF_SAMPLE_CNT_FLAG) then inst_cnt_next <= 16; elsif check_mask(inst_latch_data.field_flags,IMF_DISPOSED_CNT_FLAG) then inst_cnt_next <= 17; elsif check_mask(inst_latch_data.field_flags,IMF_NO_WRITERS_CNT_FLAG) then inst_cnt_next <= 18; elsif (TIME_BASED_FILTER_QOS /= DURATION_ZERO and check_mask(inst_latch_data.field_flags,IMF_IGNORE_DEADLINE_FLAG)) then inst_cnt_next <= 19; elsif check_mask(inst_latch_data.field_flags,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_data_next.sample_cnt <= unsigned(inst_read_data); if check_mask(inst_latch_data.field_flags,IMF_DISPOSED_CNT_FLAG) then inst_cnt_next <= 17; elsif check_mask(inst_latch_data.field_flags,IMF_NO_WRITERS_CNT_FLAG) then inst_cnt_next <= 18; elsif (TIME_BASED_FILTER_QOS /= DURATION_ZERO and check_mask(inst_latch_data.field_flags,IMF_IGNORE_DEADLINE_FLAG)) then inst_cnt_next <= 19; elsif check_mask(inst_latch_data.field_flags,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_data_next.disposed_gen_cnt <= unsigned(inst_read_data); if check_mask(inst_latch_data.field_flags,IMF_NO_WRITERS_CNT_FLAG) then inst_cnt_next <= 18; elsif (TIME_BASED_FILTER_QOS /= DURATION_ZERO and check_mask(inst_latch_data.field_flags,IMF_IGNORE_DEADLINE_FLAG)) then inst_cnt_next <= 19; elsif check_mask(inst_latch_data.field_flags,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_data_next.no_writers_gen_cnt <= unsigned(inst_read_data); if (TIME_BASED_FILTER_QOS /= DURATION_ZERO and check_mask(inst_latch_data.field_flags,IMF_IGNORE_DEADLINE_FLAG)) then inst_cnt_next <= 19; elsif check_mask(inst_latch_data.field_flags,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_data_next.ignore_deadline(0) <= unsigned(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_data_next.ignore_deadline(1) <= unsigned(inst_read_data); if check_mask(inst_latch_data.field_flags,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_data_next.writer_bitmap(inst_cnt2) <= inst_read_data; -- Exit Condition if (inst_cnt2 = WRITER_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 FIND_POS => -- NOTE: Instances are inserted in KEY_HASH numerical order. case (inst_cnt) is -- GET Next Instance when 0 => 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_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 => 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 3 => 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 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 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 <= resize(unsigned(inst_read_data),INSTANCE_MEMORY_ADDR_WIDTH); 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 inst_cnt_next <= inst_cnt + 1; -- Found Position (Before Current Instance) if (inst_latch_data.key_hash(0) < inst_read_data) then inst_next_addr_base_next <= inst_addr_base; inst_abort_read <= '1'; -- Occupied List Head if (inst_prev_addr_base = INSTANCE_MEMORY_MAX_ADDRESS) then assert (inst_addr_base = inst_occupied_head) severity FAILURE; inst_occupied_head_next <= inst_empty_head; inst_addr_base_next <= inst_empty_head; inst_stage_next <= INSERT_INSTANCE; inst_cnt_next <= 1; -- Skip First Step else inst_addr_base_next <= inst_empty_head; inst_stage_next <= INSERT_INSTANCE; inst_cnt_next <= 0; end if; -- BIGGER-THAN elsif (inst_latch_data.key_hash(0) /= inst_read_data) then inst_abort_read <= '1'; -- End of Instances if (inst_next_addr_base = INSTANCE_MEMORY_MAX_ADDRESS) then inst_next_addr_base_next <= INSTANCE_MEMORY_MAX_ADDRESS; inst_prev_addr_base_next <= inst_addr_base; inst_addr_base_next <= inst_empty_head; inst_stage_next <= INSERT_INSTANCE; inst_cnt_next <= 0; else -- Continue inst_prev_addr_base_next <= inst_addr_base; inst_addr_base_next <= inst_next_addr_base; inst_cnt_next <= 0; end if; 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 inst_cnt_next <= inst_cnt + 1; -- Found Position (Before Current Instance) if (inst_latch_data.key_hash(1) < inst_read_data) then inst_next_addr_base_next <= inst_addr_base; inst_abort_read <= '1'; -- Occupied List Head if (inst_prev_addr_base = INSTANCE_MEMORY_MAX_ADDRESS) then assert (inst_addr_base = inst_occupied_head) severity FAILURE; inst_occupied_head_next <= inst_empty_head; inst_addr_base_next <= inst_empty_head; inst_stage_next <= INSERT_INSTANCE; inst_cnt_next <= 1; -- Skip First Step else inst_addr_base_next <= inst_empty_head; inst_stage_next <= INSERT_INSTANCE; inst_cnt_next <= 0; end if; -- BIGGER-THAN elsif (inst_latch_data.key_hash(1) /= inst_read_data) then inst_abort_read <= '1'; -- End of Instances if (inst_next_addr_base = INSTANCE_MEMORY_MAX_ADDRESS) then inst_next_addr_base_next <= INSTANCE_MEMORY_MAX_ADDRESS; inst_prev_addr_base_next <= inst_addr_base; inst_addr_base_next <= inst_empty_head; inst_stage_next <= INSERT_INSTANCE; inst_cnt_next <= 0; else -- Continue inst_prev_addr_base_next <= inst_addr_base; inst_addr_base_next <= inst_next_addr_base; inst_cnt_next <= 0; end if; 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 inst_cnt_next <= inst_cnt + 1; -- Found Position (Before Current Instance) if (inst_latch_data.key_hash(2) < inst_read_data) then inst_next_addr_base_next <= inst_addr_base; inst_abort_read <= '1'; -- Occupied List Head if (inst_prev_addr_base = INSTANCE_MEMORY_MAX_ADDRESS) then assert (inst_addr_base = inst_occupied_head) severity FAILURE; inst_occupied_head_next <= inst_empty_head; inst_addr_base_next <= inst_empty_head; inst_stage_next <= INSERT_INSTANCE; inst_cnt_next <= 1; -- Skip First Step else inst_addr_base_next <= inst_empty_head; inst_stage_next <= INSERT_INSTANCE; inst_cnt_next <= 0; end if; -- BIGGER-THAN elsif (inst_latch_data.key_hash(2) /= inst_read_data) then inst_abort_read <= '1'; -- End of Instances if (inst_next_addr_base = INSTANCE_MEMORY_MAX_ADDRESS) then inst_next_addr_base_next <= INSTANCE_MEMORY_MAX_ADDRESS; inst_prev_addr_base_next <= inst_addr_base; inst_addr_base_next <= inst_empty_head; inst_stage_next <= INSERT_INSTANCE; inst_cnt_next <= 0; else -- Continue inst_prev_addr_base_next <= inst_addr_base; inst_addr_base_next <= inst_next_addr_base; inst_cnt_next <= 0; end if; end if; end if; -- Key Hash 4/4 when 9 => inst_ready_out <= '1'; -- Memory Flow Control Guard if (inst_valid_out = '1') then inst_cnt_next <= inst_cnt + 1; -- Found Position (Before Current Instance) 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) severity FAILURE; inst_occupied_head_next <= inst_empty_head; inst_addr_base_next <= inst_empty_head; inst_stage_next <= INSERT_INSTANCE; inst_cnt_next <= 1; -- Skip First Step else inst_addr_base_next <= inst_empty_head; inst_stage_next <= INSERT_INSTANCE; inst_cnt_next <= 0; end if; else assert (inst_latch_data.key_hash(3) /= inst_read_data) report "Duplicate Instance Detected" severity FAILURE; -- End of Instances if (inst_next_addr_base = INSTANCE_MEMORY_MAX_ADDRESS) then inst_next_addr_base_next <= INSTANCE_MEMORY_MAX_ADDRESS; inst_prev_addr_base_next <= inst_addr_base; inst_addr_base_next <= inst_empty_head; inst_stage_next <= INSERT_INSTANCE; inst_cnt_next <= 0; else -- Continue inst_prev_addr_base_next <= inst_addr_base; inst_addr_base_next <= inst_next_addr_base; inst_cnt_next <= 0; end if; end if; end if; when others => null; end case; when INSERT_INSTANCE => -- Precondition: inst_addr_base set, inst_prev_addr_base set (Only if first Step executed), inst_next_addr_base set case (inst_cnt) is -- SET Next Pointer (Previous Instance) when 0 => inst_valid_in <= '1'; inst_addr <= inst_prev_addr_base + IMF_NEXT_ADDR_OFFSET; inst_write_data <= std_logic_vector(resize(inst_addr_base,WORD_WIDTH)); -- Memory Flow Control Guard if (inst_ready_in = '1') then inst_cnt_next <= inst_cnt + 1; end if; -- GET Next Pointer when 1 => 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; -- SET Next Pointer (New Instance) when 2 => inst_valid_in <= '1'; inst_addr <= inst_addr_base + IMF_NEXT_ADDR_OFFSET; inst_write_data <= std_logic_vector(resize(inst_next_addr_base,WORD_WIDTH)); -- Memory Flow Control Guard if (inst_ready_in = '1') then inst_cnt_next <= inst_cnt + 1; end if; -- READ Next Pointer when 3 => inst_ready_out <= '1'; -- Memory Flow Control Guard if (inst_valid_out = '1') then -- Fix Empty List Head inst_empty_head_next <= resize(unsigned(inst_read_data),INSTANCE_MEMORY_ADDR_WIDTH); inst_cnt_next <= inst_cnt + 1; end if; -- Key Hash 1/4 when 4 => inst_valid_in <= '1'; inst_addr <= inst_addr_base + IMF_KEY_HASH_OFFSET; inst_write_data <= inst_latch_data.key_hash(0); inst_data_next.key_hash(0) <= inst_latch_data.key_hash(0); -- Memory Flow Control Guard if (inst_ready_in = '1') then inst_cnt_next <= inst_cnt + 1; end if; -- Key Hash 2/4 when 5 => inst_valid_in <= '1'; inst_addr <= inst_addr_base + IMF_KEY_HASH_OFFSET + 1; inst_write_data <= inst_latch_data.key_hash(1); inst_data_next.key_hash(1) <= inst_latch_data.key_hash(1); -- Memory Flow Control Guard if (inst_ready_in = '1') then inst_cnt_next <= inst_cnt + 1; end if; -- Key Hash 3/4 when 6 => inst_valid_in <= '1'; inst_addr <= inst_addr_base + IMF_KEY_HASH_OFFSET + 2; inst_write_data <= inst_latch_data.key_hash(2); inst_data_next.key_hash(2) <= inst_latch_data.key_hash(2); -- Memory Flow Control Guard if (inst_ready_in = '1') then inst_cnt_next <= inst_cnt + 1; end if; -- Key Hash 4/4 when 7 => inst_valid_in <= '1'; inst_addr <= inst_addr_base + IMF_KEY_HASH_OFFSET + 3; inst_write_data <= inst_latch_data.key_hash(3); inst_data_next.key_hash(3) <= inst_latch_data.key_hash(3); -- Memory Flow Control Guard if (inst_ready_in = '1') then inst_cnt_next <= inst_cnt + 1; end if; -- Status Info when 8 => 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; -- Memory Flow Control Guard if (inst_ready_in = '1') then inst_cnt_next <= inst_cnt + 1; end if; -- Sample Count when 9 => inst_valid_in <= '1'; inst_addr <= inst_addr_base + IMF_SAMPLE_CNT_OFFSET; inst_write_data <= std_logic_vector(inst_latch_data.sample_cnt); inst_data_next.sample_cnt <= inst_latch_data.sample_cnt; -- Memory Flow Control Guard if (inst_ready_in = '1') then inst_cnt_next <= inst_cnt + 1; end if; -- Disposed Generation Count when 10 => inst_valid_in <= '1'; inst_addr <= inst_addr_base + IMF_DISPOSED_GEN_CNT_OFFSET; inst_write_data <= (others => '0'); inst_data_next.disposed_gen_cnt <= (others => '0'); -- Memory Flow Control Guard if (inst_ready_in = '1') then inst_cnt_next <= inst_cnt + 1; end if; -- No Writers Generation Count when 11 => inst_valid_in <= '1'; inst_addr <= inst_addr_base + IMF_NO_WRITERS_GEN_CNT_OFFSET; inst_write_data <= (others => '0'); inst_data_next.no_writers_gen_cnt <= (others => '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 12 => -- Synthesis Guard if (TIME_BASED_FILTER_QOS /= DURATION_ZERO) then inst_valid_in <= '1'; inst_addr <= inst_addr_base + IMF_IGNORE_DEADLINE_OFFSET; inst_write_data <= std_logic_vector(inst_latch_data.deadline(0)); inst_data_next.ignore_deadline(0) <= inst_latch_data.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 13 => -- 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_write_data <= std_logic_vector(inst_latch_data.deadline(1)); inst_data_next.ignore_deadline(1) <= 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 14 => -- 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 = WRITER_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 UPDATE_INSTANCE => case (inst_cnt) is -- Status Info when 0 => 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; -- Memory Flow Control Guard if (inst_ready_in = '1') then if check_mask(inst_latch_data.field_flags,IMF_SAMPLE_CNT_FLAG) then inst_cnt_next <= 1; elsif check_mask(inst_latch_data.field_flags,IMF_DISPOSED_CNT_FLAG) then inst_cnt_next <= 2; elsif check_mask(inst_latch_data.field_flags,IMF_NO_WRITERS_CNT_FLAG) then inst_cnt_next <= 3; elsif (TIME_BASED_FILTER_QOS /= DURATION_ZERO and check_mask(inst_latch_data.field_flags,IMF_IGNORE_DEADLINE_FLAG)) then inst_cnt_next <= 4; elsif check_mask(inst_latch_data.field_flags,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_valid_in <= '1'; inst_addr <= inst_addr_base + IMF_SAMPLE_CNT_OFFSET; inst_write_data <= std_logic_vector(inst_latch_data.sample_cnt); inst_data_next.sample_cnt <= inst_latch_data.sample_cnt; -- Memory Flow Control Guard if (inst_ready_in = '1') then if check_mask(inst_latch_data.field_flags,IMF_DISPOSED_CNT_FLAG) then inst_cnt_next <= 2; elsif check_mask(inst_latch_data.field_flags,IMF_NO_WRITERS_CNT_FLAG) then inst_cnt_next <= 3; elsif (TIME_BASED_FILTER_QOS /= DURATION_ZERO and check_mask(inst_latch_data.field_flags,IMF_IGNORE_DEADLINE_FLAG)) then inst_cnt_next <= 4; elsif check_mask(inst_latch_data.field_flags,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_valid_in <= '1'; inst_addr <= inst_addr_base + IMF_DISPOSED_GEN_CNT_OFFSET; inst_write_data <= std_logic_vector(inst_latch_data.gen_cnt); inst_data_next.disposed_gen_cnt <= inst_latch_data.gen_cnt; -- Memory Flow Control Guard if (inst_ready_in = '1') then if check_mask(inst_latch_data.field_flags,IMF_NO_WRITERS_CNT_FLAG) then inst_cnt_next <= 3; elsif (TIME_BASED_FILTER_QOS /= DURATION_ZERO and check_mask(inst_latch_data.field_flags,IMF_IGNORE_DEADLINE_FLAG)) then inst_cnt_next <= 4; elsif check_mask(inst_latch_data.field_flags,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_valid_in <= '1'; inst_addr <= inst_addr_base + IMF_NO_WRITERS_GEN_CNT_OFFSET; inst_write_data <= std_logic_vector(inst_latch_data.gen_cnt); inst_data_next.no_writers_gen_cnt <= inst_latch_data.gen_cnt; -- Memory Flow Control Guard if (inst_ready_in = '1') then if (TIME_BASED_FILTER_QOS /= DURATION_ZERO and check_mask(inst_latch_data.field_flags,IMF_IGNORE_DEADLINE_FLAG)) then inst_cnt_next <= 4; elsif check_mask(inst_latch_data.field_flags,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_valid_in <= '1'; inst_addr <= inst_addr_base + IMF_IGNORE_DEADLINE_OFFSET; inst_write_data <= std_logic_vector(inst_latch_data.deadline(0)); inst_data_next.ignore_deadline(0) <= inst_latch_data.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_valid_in <= '1'; inst_addr <= inst_addr_base + IMF_IGNORE_DEADLINE_OFFSET + 1; inst_write_data <= std_logic_vector(inst_latch_data.deadline(1)); inst_data_next.ignore_deadline(1) <= inst_latch_data.deadline(1); -- Memory Flow Control Guard if (inst_ready_in = '1') then if check_mask(inst_latch_data.field_flags,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 = WRITER_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 REMOVE_INSTANCE => -- Precondition: inst_addr_base set, inst_prev_addr_base set case (inst_cnt) is -- GET Next Instance when 0 => 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_ready_out <= '1'; -- Memory Flow Control Guard if (inst_valid_out = '1') then inst_next_addr_base_next <= resize(unsigned(inst_read_data),INSTANCE_MEMORY_ADDR_WIDTH); -- Removed Instance is List Head if (inst_prev_addr_base = INSTANCE_MEMORY_MAX_ADDRESS) then assert (inst_addr_base = inst_occupied_head) severity FAILURE; -- Fix Occupied Head inst_occupied_head_next <= resize(unsigned(inst_read_data),INSTANCE_MEMORY_ADDR_WIDTH); inst_cnt_next <= inst_cnt + 2; -- Skip Next Step else inst_cnt_next <= inst_cnt + 1; end if; end if; -- SET Next Pointer (Previous Instance) when 2 => -- 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 <= std_logic_vector(resize(inst_next_addr_base,WORD_WIDTH)); -- Memory Flow Control Guard if (inst_ready_in = '1') then inst_cnt_next <= inst_cnt + 1; end if; -- SET 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 <= std_logic_vector(resize(inst_empty_head,WORD_WIDTH)); -- Memory Flow Control Guard if (inst_ready_in = '1') then -- Fix Empty List Head inst_empty_head_next <= inst_addr_base; -- Reset inst_addr_base_next <= INSTANCE_MEMORY_MAX_ADDRESS; -- DONE inst_stage_next <= IDLE; end if; when others => null; end case; when UNMARK_INSTANCES => -- Precondition: inst_addr_base set case (inst_cnt) is -- GET Next Instance when 0 => 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_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 inst_cnt_next <= inst_cnt + 1; end if; -- READ Next Instance when 2 => inst_ready_out <= '1'; -- Memory Flow Control Guard if (inst_valid_out = '1') then inst_next_addr_base_next <= resize(unsigned(inst_read_data),INSTANCE_MEMORY_ADDR_WIDTH); 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(ISI_MARK_FLAG) = '1') then -- Latch Status Info (With MARK removed) inst_long_latch_next <= inst_read_data; inst_long_latch_next(ISI_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_next <= 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_next <= inst_next_addr_base; inst_cnt_next <= 0; end if; end if; when others => null; end case; when RESET_MEMORY => case (inst_cnt) is -- Initialize when 0 => inst_addr_base_next <= FIRST_INSTANCE_ADDRESS; inst_cnt_next <= inst_cnt + 1; -- Set Next Pointer when 1 => inst_valid_in <= '1'; inst_addr <= inst_addr_base + IMF_NEXT_ADDR_OFFSET; if (inst_addr_base = MAX_INSTANCE_ADDRESS) then inst_write_data <= std_logic_vector(resize(INSTANCE_MEMORY_MAX_ADDRESS,WORD_WIDTH)); else inst_write_data <= std_logic_vector(resize(inst_addr_base + INSTANCE_FRAME_SIZE,WORD_WIDTH)); end if; -- Memory Flow Control Guard if (inst_ready_in = '1') then if (inst_addr_base = MAX_INSTANCE_ADDRESS) then -- DONE inst_stage_next <= IDLE; inst_empty_head_next <= FIRST_INSTANCE_ADDRESS; else inst_addr_base_next <= inst_addr_base + INSTANCE_FRAME_SIZE; end if; end if; when others => null; end case; when others => null; end case; end process; end generate; sync_prc : process(clk) begin if rising_edge(clk) then if (reset = '1') then stage <= RESET_SAMPLE_MEMORY; inst_stage <= RESET_MEMORY; newest_sample <= SAMPLE_MEMORY_MAX_ADDRESS; oldest_sample <= SAMPLE_MEMORY_MAX_ADDRESS; empty_sample_list_head <= SAMPLE_MEMORY_MAX_ADDRESS; empty_sample_list_tail <= SAMPLE_MEMORY_MAX_ADDRESS; empty_payload_list_head <= PAYLOAD_MEMORY_MAX_ADDRESS; inst_addr_base <= INSTANCE_MEMORY_MAX_ADDRESS; inst_occupied_head <= INSTANCE_MEMORY_MAX_ADDRESS; inst_next_addr_base <= INSTANCE_MEMORY_MAX_ADDRESS; inst_prev_addr_base <= INSTANCE_MEMORY_MAX_ADDRESS; inst_empty_head <= INSTANCE_MEMORY_MAX_ADDRESS; key_hash <= HANDLE_NIL; si_instance_handle_sig <= HANDLE_NIL; si_publication_handle_sig <= (others => (others => '0')); instance_handle <= HANDLE_NIL; sample_rej_last_inst <= HANDLE_NIL; ts_latch <= TIME_INVALID; lifespan_time <= TIME_INFINITE; lifespan <= TIME_INVALID; si_source_timestamp_sig <= TIME_INVALID; last_read_ts <= TIME_ZERO; deadline_time <= time + DEADLINE_QOS; si_sample_state_sig <= ANY_SAMPLE_STATE; sample_state <= ANY_SAMPLE_STATE; si_view_state_sig <= ANY_VIEW_STATE; view_state <= ANY_VIEW_STATE; si_instance_state_sig <= ANY_INSTANCE_STATE; instance_state <= ANY_INSTANCE_STATE; inst_data <= ZERO_INSTANCE_DATA; inst_latch_data <= ZERO_INST_LATCH_DATA; sample_rej_last_reason <= NOT_REJECTED; rtps_return_code_latch <= ERROR; dds_return_code_latch <= RETCODE_ERROR; writer_id <= 0; cnt <= 0; cnt2 <= 0; cnt3 <= 0; inst_cnt <= 0; inst_cnt2 <= 0; stale_inst_cnt <= 0; is_lifespan_check <= '0'; remove_oldest_sample <= '0'; remove_oldest_inst_sample <= '0'; si_valid_data_sig <= '0'; si_valid_sig <= '0'; eoc_sig <= '0'; is_take <= '0'; single_instance <= '0'; unmark_instances_flag <= '0'; dynamic_next_instance <= '0'; pre_calculated <= '0'; newer_inst_sample <= '0'; new_inst <= '0'; trigger_sample_gen <= '0'; wait_for_sample_removal <= '0'; dis_gen_cnt_latch <= (others => '0'); no_w_gen_cnt_latch <= (others => '0'); current_imf <= (others => '0'); sample_addr_latch_1 <= (others => '0'); sample_addr_latch_2 <= (others => '0'); sample_addr_latch_3 <= (others => '0'); sample_addr_latch_4 <= (others => '0'); sample_addr_latch_5 <= (others => '0'); payload_addr_latch_1 <= (others => '0'); payload_addr_latch_2 <= (others => '0'); inst_addr_latch_1 <= (others => '0'); inst_addr_latch_2 <= (others => '0'); long_latch <= (others => '0'); sample_status_info <= (others => '0'); si_disposed_generation_count_sig <= (others => '0'); si_no_writers_generation_count_sig <= (others => '0'); si_sample_rank_sig <= (others => '0'); si_generation_rank_sig <= (others => '0'); si_absolute_generation_rank_sig <= (others => '0'); max_samples_latch <= (others => '0'); collection_cnt <= (others => '0'); collection_cnt_max <= (others => '0'); collection_generation_rank <= (others => '0'); cur_generation_rank <= (others => '0'); sample_rej_cnt <= (others => '0'); sample_rej_cnt_change <= (others => '0'); deadline_miss_cnt <= (others => '0'); deadline_miss_cnt_change <= (others => '0'); deadline_miss_last_inst <= HANDLE_NIL; status_sig <= (others => '0'); inst_long_latch <= (others => '0'); else stage <= stage_next; inst_stage <= inst_stage_next; newest_sample <= newest_sample_next; oldest_sample <= oldest_sample_next; empty_sample_list_head <= empty_sample_list_head_next; empty_sample_list_tail <= empty_sample_list_tail_next; empty_payload_list_head <= empty_payload_list_head_next; inst_addr_base <= inst_addr_base_next; inst_occupied_head <= inst_occupied_head_next; inst_next_addr_base <= inst_next_addr_base_next; inst_prev_addr_base <= inst_prev_addr_base_next; inst_empty_head <= inst_empty_head_next; key_hash <= key_hash_next; si_instance_handle_sig <= si_instance_handle_sig_next; si_publication_handle_sig <= si_publication_handle_sig_next; instance_handle <= instance_handle_next; sample_rej_last_inst <= sample_rej_last_inst_next; ts_latch <= ts_latch_next; lifespan_time <= lifespan_time_next; lifespan <= lifespan_next; si_source_timestamp_sig <= si_source_timestamp_sig_next; last_read_ts <= last_read_ts_next; deadline_time <= deadline_time_next; si_sample_state_sig <= si_sample_state_sig_next; sample_state <= sample_state_next; si_view_state_sig <= si_view_state_sig_next; view_state <= view_state_next; si_instance_state_sig <= si_instance_state_sig_next; instance_state <= instance_state_next; inst_data <= inst_data_next when WITH_KEY else inst_data_next2; inst_latch_data <= inst_latch_data_next; sample_rej_last_reason <= sample_rej_last_reason_next; rtps_return_code_latch <= rtps_return_code_latch_next; dds_return_code_latch <= dds_return_code_latch_next; writer_id <= writer_id_next; cnt <= cnt_next; cnt2 <= cnt2_next; cnt3 <= cnt3_next; inst_cnt <= inst_cnt_next; inst_cnt2 <= inst_cnt2_next; stale_inst_cnt <= stale_inst_cnt_next; is_lifespan_check <= is_lifespan_check_next; remove_oldest_sample <= remove_oldest_sample_next; remove_oldest_inst_sample <= remove_oldest_inst_sample_next; si_valid_data_sig <= si_valid_data_sig_next; si_valid_sig <= si_valid_sig_next; eoc_sig <= eoc_sig_next; is_take <= is_take_next; single_instance <= single_instance_next; unmark_instances_flag <= unmark_instances_flag_next; dynamic_next_instance <= dynamic_next_instance_next; pre_calculated <= pre_calculated_next; newer_inst_sample <= newer_inst_sample_next; new_inst <= new_inst_next; trigger_sample_gen <= trigger_sample_gen_next; wait_for_sample_removal <= wait_for_sample_removal_next; dis_gen_cnt_latch <= dis_gen_cnt_latch_next; no_w_gen_cnt_latch <= no_w_gen_cnt_latch_next; current_imf <= current_imf_next when WITH_KEY else (others => '1'); sample_addr_latch_1 <= sample_addr_latch_1_next; sample_addr_latch_2 <= sample_addr_latch_2_next; sample_addr_latch_3 <= sample_addr_latch_3_next; sample_addr_latch_4 <= sample_addr_latch_4_next; sample_addr_latch_5 <= sample_addr_latch_5_next; payload_addr_latch_1 <= payload_addr_latch_1_next; payload_addr_latch_2 <= payload_addr_latch_2_next; inst_addr_latch_1 <= inst_addr_latch_1_next; inst_addr_latch_2 <= inst_addr_latch_2_next; long_latch <= long_latch_next; sample_status_info <= sample_status_info_next; si_disposed_generation_count_sig <= si_disposed_generation_count_sig_next; si_no_writers_generation_count_sig <= si_no_writers_generation_count_sig_next; si_sample_rank_sig <= si_sample_rank_sig_next; si_generation_rank_sig <= si_generation_rank_sig_next; si_absolute_generation_rank_sig <= si_absolute_generation_rank_sig_next; max_samples_latch <= max_samples_latch_next; collection_cnt <= collection_cnt_next; collection_cnt_max <= collection_cnt_max_next; collection_generation_rank <= collection_generation_rank_next; cur_generation_rank <= cur_generation_rank_next; sample_rej_cnt <= sample_rej_cnt_next; sample_rej_cnt_change <= sample_rej_cnt_change_next; deadline_miss_cnt <= deadline_miss_cnt_next; deadline_miss_cnt_change <= deadline_miss_cnt_change_next; deadline_miss_last_inst <= deadline_miss_last_inst_next; status_sig <= status_sig_next; inst_long_latch <= inst_long_latch_next; end if; end if; end process; end architecture;