LIBRARY IEEE;
USE IEEE.std_logic_1164.ALL;
LIBRARY WORK;
USE WORK.mem_pack.ALL;
LIBRARY STD;
USE STD.textio.ALL;
ENTITY ram IS
GENERIC ( no_of_address_bits : POSITIVE := 20;
no_of_data_bits : POSITIVE := 32;
no_of_pages : POSITIVE := 2 ;
max_bits : POSITIVE := 15;
-- the maximum of address bits that are used not masked
file_name : STRING (1 TO 4) := "PAGE"
);
PORT ( address : IN std_logic_vector(no_of_address_bits-1 DOWNTO 0):=(others=>'Z');
r_wbar : IN std_logic := '1';
cs : IN std_logic := '0';
data : INOUT std_logic_vector(no_of_data_bits-1 DOWNTO 0):=(OTHERS=>'Z');
dump : IN BOOLEAN := FALSE
);
CONSTANT max : POSITIVE := (2**max_bits)-1;
TYPE n_way IS ARRAY (1 TO no_of_pages) OF NATURAL;
SUBTYPE mem_word IS std_logic_vector(no_of_data_bits-1 DOWNTO 0);
SUBTYPE mem_coded IS string(round(no_of_data_bits,7) DOWNTO 1);
CONSTANT all_zeros : mem_coded := (others=>'0');
TYPE page_type IS ARRAY (1 TO no_of_pages, 0 TO max ) OF mem_coded;
SUBTYPE lru_type IS natural_vector (1 TO no_of_pages);
TYPE dirty_table IS ARRAY (1 TO no_of_pages) OF BIT;
END ram;
ARCHITECTURE n_way_paging_6 OF ram IS
BEGIN
PROCESS (address, r_wbar, cs, dump)
VARIABLE lru_table : lru_type := (others => 0);
VARIABLE page_table : n_way := (others => NATURAL'HIGH);
VARIABLE page_no : NATURAL;
VARIABLE chosen_page : POSITIVE;
VARIABLE page : page_type:=(others=>(others=>all_zeros));
VARIABLE data_v : mem_word;
VARIABLE dirty_bits : dirty_table; -- these values should be '0' at the begining
VARIABLE valid : BIT_VECTOR(1 TO no_of_pages);
VARIABLE found : BOOLEAN;
VARIABLE replace_found : BOOLEAN;
FILE f : TEXT;
VARIABLE l : LINE;
VARIABLE status : FILE_OPEN_STATUS := NAME_ERROR;
BEGIN
IF dump THEN
FOR i IN page_table'RANGE LOOP
IF (dirty_bits(i)='1' AND valid(i)='1') THEN
FILE_OPEN(f, file_name & int2str(page_table(i)) & ".RAM", WRITE_MODE);
FOR h IN 0 TO max LOOP
write(l,page(i, h),RIGHT);
writeline(f, l);
END LOOP;
FILE_CLOSE(F);
END IF;
END LOOP;
ELSIF (cs='1') THEN
page_no := std_logic2int(address( no_of_address_bits-1 DOWNTO max_bits));
FOR i IN lru_table'RANGE LOOP
lru_table(i) := lru_table(i) + 1;
END LOOP;
found := FALSE;
FOR i IN page_table'RANGE LOOP
IF (page_no = page_table(i) AND
valid(i) = '1') THEN
chosen_page := i;
found := TRUE;
EXIT;
END IF;
END LOOP;
IF found = FALSE THEN -- page fault
replace_found := FALSE;
FOR i IN page_table'RANGE LOOP
IF valid(i) = '0' THEN
chosen_page := i;
replace_found := TRUE;
EXIT;
END IF;
END LOOP;
IF replace_found=FALSE THEN
chosen_page := max_of(lru_table);
END IF;
-- WRITE THE FILE BACK
IF (dirty_bits(chosen_page)='1' AND valid(chosen_page)='1') THEN
FILE_OPEN(f, file_name & int2str(page_table(chosen_page)) & ".RAM", WRITE_MODE);
FOR h IN 0 TO max LOOP
write(l,page(chosen_page, h),RIGHT);
writeline(f, l);
END LOOP;
FILE_CLOSE(F);
ELSE
valid(chosen_page):='1';
END IF;
FILE_OPEN(status,f, file_name & int2str(page_no) & ".RAM", READ_MODE);
-- READ THE NEW PAGE
IF (status = OPEN_OK) THEN
FOR h IN 0 TO max LOOP
readline(f, l);
read(l, page(chosen_page, h));
DEALLOCATE(l);
END LOOP;
FILE_CLOSE(F);
END IF;
dirty_bits(chosen_page):='0';
page_table(chosen_page):=page_no;
END IF;
IF (r_wbar='1') THEN
decode(page(chosen_page, std_logic2int(address(max_bits-1 DOWNTO 0))), data_v);
data <= data_v;
ELSIF (r_wbar='0') THEN
data_v := data;
encode(data_v, page(chosen_page, std_logic2int(address(max_bits-1 DOWNTO 0))));
dirty_bits(chosen_page):='1';
END IF;
lru_table(chosen_page) := 0;
ELSIF cs='0' THEN
data <= (others => 'Z');
END IF;
END PROCESS;
END n_way_paging_6;
|