-- altera vhdl_input_version vhdl_2008
-- XXX: QSYS Fix (https://www.intel.com/content/www/us/en/support/programmable/articles/000079458.html)

library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;

use work.math_pkg.all;
use work.rtps_package.all;
use work.user_config.all;
use work.rtps_config_package.all;
use work.Type1_package.all;

entity dds_reader_syn is
    port (
        -- SYSTEM
        clk     : in std_logic;
        reset   : in std_logic;
        -- FROM RTPS ENDPOINT
        input   : in std_logic_vector(13 downto 0);
        output  : out std_logic_vector(24 downto 0)
    );
end entity;

architecture arch of dds_reader_syn is

    constant NUM_READERS : natural := 1;

begin
    
    if_gen : if (NUM_READERS > 0) generate
        signal time : TIME_TYPE;
        signal start_rtps, ack_rtps, done_rtps, valid_in_rtps, ready_in_rtps, last_word_in_rtps, start_dds, ack_dds, get_data_dds, done_dds, valid_out_dds, ready_out_dds, last_word_out_dds, sample_info_valid, sample_info_ack, eoc : std_logic_vector(0 to NUM_READERS-1);
        signal opcode_rtps : HISTORY_CACHE_OPCODE_ARRAY_TYPE(0 to NUM_READERS-1);
        signal ret_rtps : HISTORY_CACHE_RESPONSE_ARRAY_TYPE(0 to NUM_READERS-1);
        signal data_in_rtps, data_out_dds : WORD_ARRAY_TYPE(0 to NUM_READERS-1);
        signal opcode_dds : DDS_READER_OPCODE_ARRAY_TYPE(0 to NUM_READERS-1);
        signal instance_state_dds : INSTANCE_STATE_ARRAY_TYPE(0 to NUM_READERS-1);
        signal view_state_dds : VIEW_STATE_ARRAY_TYPE(0 to NUM_READERS-1);
        signal sample_state_dds : SAMPLE_STATE_ARRAY_TYPE(0 to NUM_READERS-1);
        signal instance_handle_dds : INSTANCE_HANDLE_ARRAY_TYPE(0 to NUM_READERS-1);
        signal max_samples_dds : MAX_SAMPLES_ARRAY_TYPE(0 to NUM_READERS-1);
        signal return_code_dds : RETURN_CODE_ARRAY_TYPE(0 to NUM_READERS-1);
        signal sample_info : SAMPLE_INFO_ARRAY_TYPE(0 to NUM_READERS-1);
        signal status : STATUS_KIND_ARRAY_TYPE(0 to NUM_READERS-1);
    begin
        
        -- This process is here to reduce the port count (allowing the entity to be synthesized as top level), but still prevent the tool from optimizing any logic away.
        dummy_reducer : process (all)
            variable tmp : std_logic_vector(127 downto 0);
        begin
            if rising_edge(clk) then
                time    <= to_double_word(to_unsigned(time)(62 downto 0) & input(0));
                for i in 0 to NUM_READERS-1 loop
                    start_rtps(i)           <= input(1);
                    opcode_rtps(i)          <= HISTORY_CACHE_OPCODE_TYPE'VAL(to_integer(unsigned(input)));
                    data_in_rtps(i)         <= data_in_rtps(i)(data_in_rtps(i)'length-2 downto 0) & input(2);
                    valid_in_rtps(i)        <= input(3);
                    last_word_in_rtps(i)    <= input(4);
                    start_dds(i)            <= input(5);
                    opcode_dds(i)           <= DDS_READER_OPCODE_TYPE'VAL(to_integer(unsigned(input)));
                    instance_state_dds(i)   <= instance_state_dds(i)(instance_state_dds(i)'length-2 downto 0) & input(6);
                    view_state_dds(i)       <= view_state_dds(i)(view_state_dds(i)'length-2 downto 0) & input(7);
                    sample_state_dds(i)     <= sample_state_dds(i)(sample_state_dds(i)'length-2 downto 0) & input(8);
                    tmp := std_logic_vector(to_unsigned(instance_handle_dds(i))(126 downto 0) & input(9));
                    instance_handle_dds(i)  <= to_key_hash(tmp);
                    max_samples_dds(i)      <= max_samples_dds(i)(max_samples_dds(i)'length-2 downto 0) & input(10);
                    get_data_dds(i)         <= input(11);
                    ready_out_dds(i)        <= input(12);
                    sample_info_ack(i)      <= input(13);
                end loop;
            end if;
            for i in 0 to NUM_READERS-1 loop
                output(0)   <= ack_rtps(i);
                output(1)   <= done_rtps(i);
                output(2)   <= to_unsigned(HISTORY_CACHE_RESPONSE_TYPE'POS(ret_rtps(i)),1)(0);
                output(3)   <= ready_in_rtps(i);
                output(4)   <= ack_dds(i);
                output(5)   <= done_dds(i);
                output(6)   <= return_code_dds(i)(to_integer(unsigned(input)));
                output(7)   <= valid_out_dds(i);
                output(8)   <= data_out_dds(i)(to_integer(unsigned(input)));
                output(9)   <= last_word_out_dds(i);
                output(10)  <= sample_info(i).sample_state(to_integer(unsigned(input)));
                output(11)  <= sample_info(i).view_state(to_integer(unsigned(input)));
                output(12)  <= sample_info(i).instance_state(to_integer(unsigned(input)));
                output(13)  <= to_unsigned(sample_info(i).source_timestamp)(to_integer(unsigned(input)));
                output(14)  <= to_unsigned(sample_info(i).instance_handle)(to_integer(unsigned(input)));
                output(15)  <= to_unsigned(sample_info(i).publication_handle)(to_integer(unsigned(input)));
                output(16)  <= sample_info(i).disposed_generation_count(to_integer(unsigned(input)));
                output(17)  <= sample_info(i).no_writers_generation_count(to_integer(unsigned(input)));
                output(18)  <= sample_info(i).sample_rank(to_integer(unsigned(input)));
                output(19)  <= sample_info(i).generation_rank(to_integer(unsigned(input)));
                output(20)  <= sample_info(i).absolute_generation_rank(to_integer(unsigned(input)));
                output(21)  <= sample_info(i).valid_data;
                output(22)  <= sample_info_valid(i);
                output(23)  <= eoc(i);
                output(24)  <= status(i)(to_integer(unsigned(input)));
            end loop;
        end process;
        
        syn_inst : entity work.dds_reader(arch)
            generic map (
                NUM_READERS             => NUM_READERS,
                CONFIG_ARRAY            => to_QUARTUS_CONFIG_ARRAY_TYPE(ENDPOINT_CONFIG(0 to NUM_READERS-1)),
                MAX_REMOTE_ENDPOINTS    => 50
            )
            port map (
                clk                             => clk,
                reset                           => reset,
                time                            => time,
                start_rtps                      => start_rtps,
                opcode_rtps                     => opcode_rtps,
                ack_rtps                        => ack_rtps,
                done_rtps                       => done_rtps,
                ret_rtps                        => ret_rtps,
                data_in_rtps                    => data_in_rtps,
                valid_in_rtps                   => valid_in_rtps,
                ready_in_rtps                   => ready_in_rtps,
                last_word_in_rtps               => last_word_in_rtps,
                start_dds                       => start_dds,
                ack_dds                         => ack_dds,
                opcode_dds                      => opcode_dds,
                instance_state_dds              => instance_state_dds,
                view_state_dds                  => view_state_dds,
                sample_state_dds                => sample_state_dds,
                instance_handle_dds             => instance_handle_dds,
                max_samples_dds                 => max_samples_dds,
                get_data_dds                    => get_data_dds,
                done_dds                        => done_dds,
                return_code_dds                 => return_code_dds,
                ready_out_dds                   => ready_out_dds,
                valid_out_dds                   => valid_out_dds,
                data_out_dds                    => data_out_dds,
                last_word_out_dds               => last_word_out_dds,
                sample_info                     => sample_info,
                sample_info_valid               => sample_info_valid,
                sample_info_ack                 => sample_info_ack,
                eoc                             => eoc,
                status                          => status
            );
    end generate;
    
end architecture;
