rtps-fpga/src/dds_endpoint.vhd

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;