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

use work.mem_pkg.all;
use work.cache_pkg.all;
use work.single_clock_rw_ram_pkg.all;

entity data_st_1w is
	generic (
		SETS_LD  : natural := SETS_LD
	);
	port (
		clk       : in std_logic;

		we        : in std_logic;
		rd        : in std_logic;
		index     : in c_index_type;
		byteena   : in mem_byteena_type;

		data_in   : in mem_data_type;
		data_out  : out mem_data_type
	);
end entity;

architecture impl of data_st_1w is
	-- (word) address consists of |index bits|
	constant CACHE_DATA_ADDRESS_BITS : integer := c_index_type'length;
	-- data consists of |valid bit|tag bits|actual data bits|
	--constant CACHE_DATA_BITS : integer := 1 + c_tag_type'length + mem_data_type'length;
	-- actually data consists of only |actual data bits|, because the rest is auxiliary mgmt information
	constant CACHE_DATA_BITS : integer := mem_data_type'length;

	-- range types
	subtype cache_address_range_type is natural range CACHE_DATA_ADDRESS_BITS - 1 downto 0;
	subtype cache_data_range_type is natural range CACHE_DATA_BITS - 1 downto 0;

	-- aux types
	subtype byte_type is std_logic_vector(BYTE_WIDTH - 1 downto 0);

	-- auxiliary signals
	signal write_address : std_logic_vector(cache_address_range_type);
	signal read_address : std_logic_vector(cache_address_range_type);
begin
	-- structural
	single_clock_rw_ram_inst : entity work.single_clock_rw_ram
	generic map (
		ADDR_WIDTH => CACHE_DATA_ADDRESS_BITS,
		DATA_WIDTH => CACHE_DATA_BITS
	)
	port map (
		clk           => clk,
		data_in       => data_in,
		write_address => write_address,
		read_address  => read_address,
		we            => we,
		data_out      => data_out,
		byteena       => byteena
	);

	-- concurrent
	--data_out <= data_out_b0 & data_out_b1 & data_out_b2 & data_out_b3;
	read_address <= index;
	write_address <= index;

	-- sequential
	/*async : process(all)
		variable masked_byte : byte_type := (others => '0');
	begin
		for i in byteena'range loop
			if byteena(i) = '0' then
				masked_byte := data_out((i + 1) * BYTE_WIDTH - 1 downto i * BYTE_WIDTH);
			else
				masked_byte := data_in((i + 1) * BYTE_WIDTH - 1 downto i * BYTE_WIDTH);
			end if;
			ram_data_in((i + 1) * BYTE_WIDTH - 1 downto i * BYTE_WIDTH) <= masked_byte;
		end loop;
	end process;*/
end architecture;
