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