Add a simple direct mapped icache
Signed-off-by: Anton Blanchard <anton@linux.ibm.com>pull/49/head
							parent
							
								
									6cbf456388
								
							
						
					
					
						commit
						89849a6856
					
				@ -0,0 +1,173 @@
 | 
			
		||||
library ieee;
 | 
			
		||||
use ieee.std_logic_1164.all;
 | 
			
		||||
use ieee.numeric_std.all;
 | 
			
		||||
 | 
			
		||||
library work;
 | 
			
		||||
use work.common.all;
 | 
			
		||||
use work.wishbone_types.all;
 | 
			
		||||
 | 
			
		||||
-- 64 bit direct mapped icache. All instructions are 4B aligned.
 | 
			
		||||
 | 
			
		||||
entity icache is
 | 
			
		||||
    generic (
 | 
			
		||||
        -- Line size in 64bit doublewords
 | 
			
		||||
        LINE_SIZE_DW : natural := 8;
 | 
			
		||||
        -- Number of lines
 | 
			
		||||
        NUM_LINES : natural := 32
 | 
			
		||||
        );
 | 
			
		||||
    port (
 | 
			
		||||
        clk          : in std_ulogic;
 | 
			
		||||
        rst          : in std_ulogic;
 | 
			
		||||
 | 
			
		||||
        i_in         : in Fetch2ToIcacheType;
 | 
			
		||||
        i_out        : out IcacheToFetch2Type;
 | 
			
		||||
 | 
			
		||||
        wishbone_out : out wishbone_master_out;
 | 
			
		||||
        wishbone_in  : in wishbone_slave_out
 | 
			
		||||
        );
 | 
			
		||||
end entity icache;
 | 
			
		||||
 | 
			
		||||
architecture rtl of icache is
 | 
			
		||||
    function log2(i : natural) return integer is
 | 
			
		||||
        variable tmp : integer := i;
 | 
			
		||||
        variable ret : integer := 0;
 | 
			
		||||
    begin
 | 
			
		||||
        while tmp > 1 loop
 | 
			
		||||
            ret  := ret + 1;
 | 
			
		||||
            tmp := tmp / 2;
 | 
			
		||||
        end loop;
 | 
			
		||||
        return ret;
 | 
			
		||||
    end function;
 | 
			
		||||
 | 
			
		||||
    function ispow2(i : integer) return boolean is
 | 
			
		||||
    begin
 | 
			
		||||
        if to_integer(to_unsigned(i, 32) and to_unsigned(i - 1, 32)) = 0 then
 | 
			
		||||
            return true;
 | 
			
		||||
        else
 | 
			
		||||
            return false;
 | 
			
		||||
        end if;
 | 
			
		||||
    end function;
 | 
			
		||||
 | 
			
		||||
    constant LINE_SIZE : natural := LINE_SIZE_DW*8;
 | 
			
		||||
    constant OFFSET_BITS : natural := log2(LINE_SIZE);
 | 
			
		||||
    constant INDEX_BITS : natural := log2(NUM_LINES);
 | 
			
		||||
    constant TAG_BITS : natural := 64 - OFFSET_BITS - INDEX_BITS;
 | 
			
		||||
 | 
			
		||||
    subtype cacheline_type is std_logic_vector((LINE_SIZE*8)-1 downto 0);
 | 
			
		||||
    type cacheline_array is array(0 to NUM_LINES-1) of cacheline_type;
 | 
			
		||||
 | 
			
		||||
    subtype cacheline_tag_type is std_logic_vector(TAG_BITS-1 downto 0);
 | 
			
		||||
    type cacheline_tag_array is array(0 to NUM_LINES-1) of cacheline_tag_type;
 | 
			
		||||
 | 
			
		||||
    signal cachelines : cacheline_array := (others => (others => '0'));
 | 
			
		||||
    signal tags       : cacheline_tag_array := (others => (others => '0'));
 | 
			
		||||
    signal tags_valid : std_ulogic_vector(NUM_LINES-1 downto 0) := (others => '0');
 | 
			
		||||
 | 
			
		||||
    attribute ram_style : string;
 | 
			
		||||
    attribute ram_style of cachelines : signal is "block";
 | 
			
		||||
 | 
			
		||||
    attribute ram_decomp : string;
 | 
			
		||||
    attribute ram_decomp of cachelines : signal is "power";
 | 
			
		||||
 | 
			
		||||
    type state_type is (IDLE, WAIT_ACK);
 | 
			
		||||
 | 
			
		||||
    type reg_internal_type is record
 | 
			
		||||
        state : state_type;
 | 
			
		||||
        w     : wishbone_master_out;
 | 
			
		||||
        store_index     : integer range 0 to (NUM_LINES-1);
 | 
			
		||||
        store_word  : integer range 0 to (LINE_SIZE-1);
 | 
			
		||||
    end record;
 | 
			
		||||
 | 
			
		||||
    signal r : reg_internal_type;
 | 
			
		||||
 | 
			
		||||
    signal read_index : integer range 0 to NUM_LINES-1;
 | 
			
		||||
    signal read_tag   : std_ulogic_vector(63-OFFSET_BITS-INDEX_BITS downto 0);
 | 
			
		||||
    signal read_miss  : boolean;
 | 
			
		||||
 | 
			
		||||
    function get_index(addr: std_ulogic_vector(63 downto 0)) return integer is
 | 
			
		||||
    begin
 | 
			
		||||
        return to_integer(unsigned(addr((OFFSET_BITS+INDEX_BITS-1) downto OFFSET_BITS)));
 | 
			
		||||
    end;
 | 
			
		||||
 | 
			
		||||
    function get_word(addr: std_ulogic_vector(63 downto 0); data: cacheline_type) return std_ulogic_vector is
 | 
			
		||||
        variable word : integer;
 | 
			
		||||
    begin
 | 
			
		||||
        word := to_integer(unsigned(addr(OFFSET_BITS-1 downto 2)));
 | 
			
		||||
        return data((word+1)*32-1 downto word*32);
 | 
			
		||||
    end;
 | 
			
		||||
 | 
			
		||||
    function get_tag(addr: std_ulogic_vector(63 downto 0)) return std_ulogic_vector is
 | 
			
		||||
    begin
 | 
			
		||||
        return addr(63 downto OFFSET_BITS+INDEX_BITS);
 | 
			
		||||
    end;
 | 
			
		||||
begin
 | 
			
		||||
    assert ispow2(LINE_SIZE) report "LINE_SIZE not power of 2" severity FAILURE;
 | 
			
		||||
    assert ispow2(NUM_LINES) report "NUM_LINES not power of 2" severity FAILURE;
 | 
			
		||||
 | 
			
		||||
    icache_read : process(all)
 | 
			
		||||
    begin
 | 
			
		||||
        read_index <= get_index(i_in.addr);
 | 
			
		||||
        read_tag <= get_tag(i_in.addr);
 | 
			
		||||
        read_miss <= false;
 | 
			
		||||
 | 
			
		||||
        i_out.ack <= '0';
 | 
			
		||||
        i_out.insn <= get_word(i_in.addr, cachelines(read_index));
 | 
			
		||||
 | 
			
		||||
        if i_in.req = '1' then
 | 
			
		||||
            if (tags_valid(read_index) = '1') and (tags(read_index) = read_tag) then
 | 
			
		||||
                -- report hit asynchronously
 | 
			
		||||
                i_out.ack <= '1';
 | 
			
		||||
            else
 | 
			
		||||
                read_miss <= true;
 | 
			
		||||
            end if;
 | 
			
		||||
        end if;
 | 
			
		||||
    end process;
 | 
			
		||||
 | 
			
		||||
    wishbone_out <= r.w;
 | 
			
		||||
 | 
			
		||||
    icache_write : process(clk)
 | 
			
		||||
    begin
 | 
			
		||||
        if rising_edge(clk) then
 | 
			
		||||
            if rst = '1' then
 | 
			
		||||
                tags_valid <= (others => '0');
 | 
			
		||||
                r.state <= IDLE;
 | 
			
		||||
                r.w.cyc <= '0';
 | 
			
		||||
                r.w.stb <= '0';
 | 
			
		||||
            end if;
 | 
			
		||||
 | 
			
		||||
            r.w.dat <= (others => '0');
 | 
			
		||||
            r.w.sel <= "11111111";
 | 
			
		||||
            r.w.we  <= '0';
 | 
			
		||||
 | 
			
		||||
            case r.state is
 | 
			
		||||
                when IDLE =>
 | 
			
		||||
                    if read_miss = true then
 | 
			
		||||
                        r.state <= WAIT_ACK;
 | 
			
		||||
                        r.store_word <= 0;
 | 
			
		||||
                        r.store_index <= read_index;
 | 
			
		||||
 | 
			
		||||
                        tags(read_index) <= read_tag;
 | 
			
		||||
                        tags_valid(read_index) <= '0';
 | 
			
		||||
 | 
			
		||||
                        r.w.adr <= i_in.addr(63 downto OFFSET_BITS) & (OFFSET_BITS-1 downto 0 => '0');
 | 
			
		||||
                        r.w.cyc <= '1';
 | 
			
		||||
                        r.w.stb <= '1';
 | 
			
		||||
                    end if;
 | 
			
		||||
                when WAIT_ACK =>
 | 
			
		||||
                    if wishbone_in.ack = '1' then
 | 
			
		||||
                        cachelines(r.store_index)((r.store_word+1)*64-1 downto ((r.store_word)*64)) <= wishbone_in.dat;
 | 
			
		||||
                        r.store_word <= r.store_word + 1;
 | 
			
		||||
 | 
			
		||||
                        if r.store_word = (LINE_SIZE_DW-1) then
 | 
			
		||||
                            r.state <= IDLE;
 | 
			
		||||
                            tags_valid(r.store_index) <= '1';
 | 
			
		||||
                            r.w.cyc <= '0';
 | 
			
		||||
                            r.w.stb <= '0';
 | 
			
		||||
                        else
 | 
			
		||||
                            r.w.adr(OFFSET_BITS-1 downto 3) <= std_ulogic_vector(to_unsigned(r.store_word+1, OFFSET_BITS-3));
 | 
			
		||||
                        end if;
 | 
			
		||||
                    end if;
 | 
			
		||||
            end case;
 | 
			
		||||
        end if;
 | 
			
		||||
    end process;
 | 
			
		||||
end;
 | 
			
		||||
					Loading…
					
					
				
		Reference in New Issue