From 2e1850c19bde59f599e746c19187bc68cafa8c5c Mon Sep 17 00:00:00 2001 From: Jens Ahrensfeld Date: Mon, 30 Mar 2009 22:26:15 +0000 Subject: [PATCH] - redesigned - added invalidate_all and invalidate_at control Committed on the Free edition of March Hare Software CVSNT Server. Upgrade to CVS Suite for more features and support: http://march-hare.com/cvsnt/ git-svn-id: http://moon:8086/svn/vhdl/trunk@420 cc03376c-175c-47c8-b038-4cd826a8556b --- lib/CPUs/MIPS/src/core/dcache.vhd | 246 ++++++++++++++++++------------ lib/CPUs/MIPS/src/core/icache.vhd | 189 ++++++++++++++++------- 2 files changed, 287 insertions(+), 148 deletions(-) diff --git a/lib/CPUs/MIPS/src/core/dcache.vhd b/lib/CPUs/MIPS/src/core/dcache.vhd index 5ae96d7..ef8c5db 100644 --- a/lib/CPUs/MIPS/src/core/dcache.vhd +++ b/lib/CPUs/MIPS/src/core/dcache.vhd @@ -81,10 +81,10 @@ END COMPONENT; constant cache_index_width : natural := lg2(cache_size) - word_index_width; constant tag_width : natural := 32 - word_index_width - cache_index_width - 2; constant tag_parity_width : natural := 3; - constant tram_data_width : natural := 1 + tag_parity_width + tag_width; - constant tram_addr_width : natural := cache_index_width; + constant tag_ram_data_width : natural := 1 + tag_parity_width + tag_width; + constant tag_ram_addr_width : natural := cache_index_width; - subtype tram_data_t is unsigned (tram_data_width-1 downto 0); + subtype tag_ram_data_t is unsigned (tag_ram_data_width-1 downto 0); type dcache_entry_t is record valid : std_logic; @@ -96,7 +96,7 @@ END COMPONENT; alias cpu_cache_index is cpu_addr(cache_index_width+word_index_width+1 downto word_index_width+2); alias cpu_tag is cpu_addr(tag_width+cache_index_width+word_index_width+1 downto cache_index_width+word_index_width+2); - function to_dcache_entry(x : tram_data_t) return dcache_entry_t is + function to_dcache_entry(x : tag_ram_data_t) return dcache_entry_t is variable result : dcache_entry_t; begin result.valid := x(0); @@ -106,66 +106,77 @@ END COMPONENT; return result; end to_dcache_entry; - function to_tram_data(x : dcache_entry_t) return tram_data_t is - variable result : tram_data_t; + function to_tag_ram_data(x : dcache_entry_t) return tag_ram_data_t is + variable result : tag_ram_data_t; begin result(0) := x.valid; result(3 downto 1) := x.tv_p; result(tag_width+3 downto 4) := x.tag; return result; - end to_tram_data; + end to_tag_ram_data; - type cache_state_t is (init, ready, flush, mem_request, mem_access, mem_data, rd_cache); + type cache_state_t is (init, ready, invalidate, flush, mem_request, mem_access, mem_data, rd_cache); signal s, sn : cache_state_t; + signal cache_req : std_logic; + signal cache_ack : std_logic; signal cache_busy : std_logic; signal cache_hit : std_logic; signal tag_match : std_logic; + signal cache_hit_inv : std_logic; + signal tag_match_inv : std_logic; signal word_index_reg : unsigned(word_index_width-1 downto 0); signal addr_windex_reg : unsigned(word_index_width-1 downto 0); signal cache_index_reg : unsigned(cache_index_width-1 downto 0); - signal tag_index_reg : unsigned(tag_width-1 downto 0); + signal cache_index_inv : unsigned(cache_index_width-1 downto 0); + signal tag_reg : unsigned(tag_width-1 downto 0); + signal tag_inv : unsigned(tag_width-1 downto 0); + signal tag_reg_inv : unsigned(tag_width-1 downto 0); signal cache_entry_in : dcache_entry_t; signal cache_entry_out : dcache_entry_t; - signal cpu_dram_addr : unsigned(lg2(cache_size)-1 downto 0); - signal cpu_dram_dout : word_t; - signal cpu_dram_din : word_t; + signal cache_entry_out_inv : dcache_entry_t; + signal cpu_data_ram_addr : unsigned(lg2(cache_size)-1 downto 0); + signal cpu_data_ram_dout : word_t; signal cpu_data_reg : word_t; signal cpu_be_reg : unsigned(3 downto 0); signal cpu_we_reg : std_logic; - signal ctrl_dram_en : std_logic; - signal ctrl_dram_addr : unsigned(lg2(cache_size)-1 downto 0); - signal ctrl_dram_din : word_t; - signal ctrl_dram_we : unsigned(3 downto 0); - signal cpu_dram_we : unsigned(3 downto 0); - signal cpu_dram_en : std_logic; - signal cpu_en2 : std_logic; + signal ctrl_data_ram_addr : unsigned(lg2(cache_size)-1 downto 0); + signal ctrl_data_ram_we : unsigned(3 downto 0); + signal cpu_data_ram_we : unsigned(3 downto 0); signal cpu_we2 : std_logic; - signal tram_addr_rd : unsigned(cache_index_width-1 downto 0); - signal tram_dout : tram_data_t; - signal tram_addr_wr : unsigned(cache_index_width-1 downto 0); - signal tram_din : tram_data_t; - signal tram_we : std_logic; + signal tag_ram_addr_rd : unsigned(cache_index_width-1 downto 0); + signal tag_ram_dout : tag_ram_data_t; + signal tag_ram_dout_inv : tag_ram_data_t; + signal tag_ram_addr_wr : unsigned(cache_index_width-1 downto 0); + signal tag_ram_din : tag_ram_data_t; + signal tag_ram_we : std_logic; signal fill_count : natural range 0 to 2**word_index_width-1; signal fill_count_en : std_logic; signal fill_count_rdy : std_logic; signal flush_count : natural range 0 to 2**cache_index_width-1; + signal flush_count_rst : std_logic; signal flush_count_en : std_logic; signal flush_count_rdy : std_logic; signal request_count : natural range 0 to 2**word_index_width-1; signal request_count_en : std_logic; signal request_count_rdy : std_logic; - signal cpu_reg_en : std_logic; signal was_miss : std_logic; + signal invalidate_all : std_logic; + signal invalidate_ack : std_logic; + signal invalidate_en : std_logic; + signal invalidate_req : std_logic; signal cpu_hit_we : std_logic; signal instant_raw : std_logic; begin + cache_index_inv <= ctrl.inv_addr(cache_index_width+word_index_width+1 downto word_index_width+2); + tag_inv <= ctrl.inv_addr(tag_width+cache_index_width+word_index_width+1 downto cache_index_width+word_index_width+2); + cpu_hit_we <= cpu_we2 and cache_hit; cpu_index_register: @@ -176,10 +187,10 @@ cpu_index_register: if ACK_I = '1' then word_index_reg <= word_index_reg + 1; end if; - elsif cpu_reg_en = '1' and en = '1' and instant_raw = '0' then + elsif cache_busy = '0' then word_index_reg <= cpu_word_index; cache_index_reg <= cpu_cache_index; - tag_index_reg <= cpu_tag; + tag_reg <= cpu_tag; end if; end if; end process; @@ -192,36 +203,30 @@ addr_windex_register: if SRDY_I = '1' then addr_windex_reg <= addr_windex_reg + 1; end if; - elsif cpu_reg_en = '1' and en = '1' and instant_raw = '0' then + elsif cache_busy = '0' then addr_windex_reg <= cpu_word_index; end if; end if; end process; -cpu_data_register: +cpu_request_register: process(CLK_I) begin if rising_edge(CLK_I) then if RST_I = '1' then cpu_we_reg <= '0'; - elsif cpu_reg_en = '1' and en = '1' then - cpu_data_reg <= cpu_din; - cpu_be_reg <= cpu_be; - cpu_we_reg <= cpu_we; - end if; - end if; - end process; - -cpu_was_wr_register: - process(CLK_I) - begin - if rising_edge(CLK_I) then - cpu_en2 <= '0'; - cpu_we2 <= '0'; - if cpu_en = '1' and en = '1' then - cpu_we2 <= cpu_we; - cpu_en2 <= '1'; - cpu_dram_din <= cpu_din; + cache_req <= '0'; + elsif cpu_en = '1' and en = '1' then + if cache_busy = '0' then + cpu_we2 <= cpu_we; + cache_req <= '1'; + cpu_data_reg <= cpu_din; + cpu_be_reg <= cpu_be; + cpu_we_reg <= cpu_we; + end if; + elsif cache_ack = '1' then + cache_req <= '0'; + cpu_we2 <= '0'; end if; end if; end process; @@ -237,23 +242,26 @@ instant_raw_logic: end if; end process; -inst_tag_ram : dpram_1w1r +inst_tag_ram : dpram_2w2r GENERIC MAP ( - addr_width => tram_addr_width, - data_width => tram_data_width + addr_width => tag_ram_addr_width, + data_width => tag_ram_data_width ) PORT MAP ( - clka => CLK_I, - clkb => CLK_I, + clk_a => CLK_I, + clk_b => CLK_I, en_a => '1', en_b => '1', - we_a => tram_we, - addr_a => tram_addr_wr, - addr_b => tram_addr_rd, - din_a => tram_din, - dout_b => tram_dout + we_a => tag_ram_we, + we_b => '0', + addr_a => tag_ram_addr_wr, + addr_b => tag_ram_addr_rd, + din_a => tag_ram_din, + din_b => tag_ram_din, + dout_a => tag_ram_dout_inv, + dout_b => tag_ram_dout ); gen_data_ram: @@ -272,17 +280,34 @@ gen_data_ram: clk_b => CLK_I, en_a => '1', en_b => '1', - we_a => cpu_dram_we(i), - we_b => ctrl_dram_we(i), - addr_a => ctrl_dram_addr, - addr_b => cpu_dram_addr, + we_a => cpu_data_ram_we(i), + we_b => ctrl_data_ram_we(i), + addr_a => ctrl_data_ram_addr, + addr_b => cpu_data_ram_addr, din_a => cpu_data_reg(8*(i+1)-1 downto 8*i), din_b => DAT_I(8*(i+1)-1 downto 8*i), dout_a => open, - dout_b => cpu_dram_dout(8*(i+1)-1 downto 8*i) + dout_b => cpu_data_ram_dout(8*(i+1)-1 downto 8*i) ); end generate; + + +cache_invalidate_request: + process(CLK_I) + begin + if rising_edge(CLK_I) then + if RST_I = '1' or ctrl.inv_all = '1' or ctrl.inv_at = '1' then + invalidate_req <= '1'; + invalidate_all <= ctrl.inv_all or RST_I; + tag_reg_inv <= tag_inv; + elsif invalidate_ack = '1' then + invalidate_req <= '0'; + invalidate_all <= '0'; + end if; + end if; + end process; + cache_state_next: process(CLK_I) begin @@ -295,64 +320,89 @@ cache_state_next: end if; end process; - cpu_busy <= cache_busy or instant_raw; - cpu_dout <= cpu_dram_dout; + cpu_busy <= cache_busy; + cpu_dout <= cpu_data_ram_dout; - tag_match <= '1' when tag_index_reg = cache_entry_out.tag else '0'; + tag_match <= '1' when tag_reg = cache_entry_out.tag else '0'; cache_hit <= tag_match and cache_entry_out.valid; - tram_din <= to_tram_data(cache_entry_in); - tram_addr_wr <= to_unsigned(flush_count, cache_index_width) when flush_count_en = '1' else cache_index_reg; - tram_addr_rd <= cpu_cache_index when was_miss = '0' else cache_index_reg; - cache_entry_out <= to_dcache_entry(tram_dout); + tag_match_inv <= '1' when tag_reg_inv = cache_entry_out_inv.tag else '0'; + cache_hit_inv <= tag_match_inv and cache_entry_out_inv.valid; + tag_ram_din <= to_tag_ram_data(cache_entry_in); + tag_ram_addr_wr <= to_unsigned(flush_count, cache_index_width) when invalidate_en = '1' else cache_index_reg; + tag_ram_addr_rd <= cpu_cache_index when (was_miss = '0' and instant_raw = '0') else cache_index_reg; + + cache_entry_out <= to_dcache_entry(tag_ram_dout); + cache_entry_out_inv <= to_dcache_entry(tag_ram_dout_inv); - cpu_dram_addr <= (cpu_cache_index & cpu_word_index) when (was_miss = '0' and instant_raw = '0' and fill_count_en = '0') else (cache_index_reg & word_index_reg); - ADDR_O <= tag_index_reg & cache_index_reg & addr_windex_reg & "00"; - ctrl_dram_addr <= cache_index_reg & word_index_reg; - ctrl_dram_we <= (others => fill_count_en and ACK_I); - cpu_dram_we <= cpu_be_reg when (cpu_hit_we = '1') else (others => '0'); + cpu_data_ram_addr <= (cpu_cache_index & cpu_word_index) when (was_miss = '0' and instant_raw = '0' and fill_count_en = '0') else (cache_index_reg & word_index_reg); + ADDR_O <= tag_reg & cache_index_reg & addr_windex_reg & "00"; + ctrl_data_ram_addr <= cache_index_reg & word_index_reg; + ctrl_data_ram_we <= (others => fill_count_en and ACK_I); + cpu_data_ram_we <= cpu_be_reg when (cpu_hit_we = '1') else (others => '0'); cache_state: - process(s, instant_raw, cache_hit, flush_count_rdy, fill_count_rdy, request_count_rdy, tag_index_reg, cpu_en, SRDY_I, cpu_en2, cpu_we_reg) + process(s, cache_req, instant_raw, cache_hit, cache_hit_inv, flush_count_rdy, fill_count_rdy, request_count_rdy, tag_reg, SRDY_I, cpu_we_reg, invalidate_req, invalidate_all) begin - cpu_reg_en <= '0'; - cache_busy <= '1'; - tram_we <= '0'; + cache_busy <= cache_req; + cache_ack <= '0'; + tag_ram_we <= '0'; flush_count_en <= '0'; + flush_count_rst <= '0'; + invalidate_en <= '0'; request_count_en <= '0'; fill_count_en <= '0'; CYC_O <= '0'; STB_O <= '0'; was_miss <= '0'; + invalidate_ack <= '0'; + cache_entry_in.tv_p <= (others => '0'); - cache_entry_in.tag <= tag_index_reg; + cache_entry_in.tag <= tag_reg; cache_entry_in.valid <= '0'; sn <= s; case s is when init => - sn <= flush; + sn <= ready; when ready => - cache_busy <= '0'; - cpu_reg_en <= '1'; - if cpu_en2 = '1' then - if cache_hit = '0' and cpu_we_reg = '0' then - sn <= mem_request; - cpu_reg_en <= '0'; - cache_busy <= '1'; - CYC_O <= '1'; + if invalidate_req = '1' then + sn <= invalidate; + invalidate_en <= '1'; + else + if cache_req = '1' then + if cache_hit = '0' and cpu_we_reg = '0' then + sn <= mem_request; + cache_busy <= '1'; + CYC_O <= '1'; + else + cache_busy <= instant_raw; + cache_ack <= not instant_raw; + end if; end if; end if; + when invalidate => + sn <= rd_cache; + invalidate_en <= '1'; + invalidate_ack <= '1'; + if invalidate_all = '1' then + sn <= flush; + flush_count_rst <= '1'; + elsif cache_hit_inv = '1' then + tag_ram_we <= '1'; + cache_entry_in.valid <= '0'; + cache_entry_in.tag <= (others => '0'); + sn <= rd_cache; + end if; + when flush => flush_count_en <= '1'; - tram_we <= '1'; + invalidate_en <= '1'; + tag_ram_we <= '1'; cache_entry_in.valid <= '0'; cache_entry_in.tag <= (others => '0'); if flush_count_rdy = '1' then - tram_we <= '0'; - sn <= ready; - if cpu_en = '1' then - cpu_reg_en <= '1'; - end if; + tag_ram_we <= '0'; + sn <= rd_cache; end if; when mem_request => CYC_O <= '1'; @@ -372,7 +422,7 @@ cache_state: CYC_O <= '1'; fill_count_en <= '1'; if fill_count_rdy = '1' then - tram_we <= '1'; + tag_ram_we <= '1'; cache_entry_in.valid <= '1'; sn <= rd_cache; end if; @@ -390,10 +440,12 @@ flush_counter: process(CLK_I) begin if rising_edge(CLK_I) then - if flush_count_en = '0' then + if ctrl.inv_at = '1' then + flush_count <= to_integer(cache_index_inv); + elsif flush_count_rst = '1' then flush_count_rdy <= '0'; flush_count <= 2**cache_index_width-1; - else + elsif flush_count_en = '1' then if flush_count /= 0 then flush_count <= flush_count - 1; else diff --git a/lib/CPUs/MIPS/src/core/icache.vhd b/lib/CPUs/MIPS/src/core/icache.vhd index 76005ad..9cb04ce 100644 --- a/lib/CPUs/MIPS/src/core/icache.vhd +++ b/lib/CPUs/MIPS/src/core/icache.vhd @@ -51,6 +51,29 @@ COMPONENT dpram_1w1r ); END COMPONENT; +COMPONENT dpram_2w2r is + GENERIC + ( + addr_width : integer := 3; + data_width : integer := 8 + ); + PORT + ( + clk_a : in STD_LOGIC; + clk_b : in STD_LOGIC; + en_a : in STD_LOGIC; + en_b : in STD_LOGIC; + we_a : in STD_LOGIC; + we_b : in STD_LOGIC; + addr_a : in unsigned (addr_width-1 downto 0); + addr_b : in unsigned (addr_width-1 downto 0); + din_a : in unsigned (data_width-1 downto 0); + din_b : in unsigned (data_width-1 downto 0); + dout_a : out unsigned (data_width-1 downto 0); + dout_b : out unsigned (data_width-1 downto 0) + ); +END COMPONENT; + constant word_index_width : natural := lg2(line_size); constant cache_index_width : natural := lg2(cache_size) - word_index_width; constant tag_width : natural := 32 - word_index_width - cache_index_width - 2; @@ -69,7 +92,7 @@ END COMPONENT; alias cpu_word_index is cpu_addr(word_index_width+1 downto 2); alias cpu_cache_index is cpu_addr(cache_index_width+word_index_width+1 downto word_index_width+2); alias cpu_tag is cpu_addr(tag_width+cache_index_width+word_index_width+1 downto cache_index_width+word_index_width+2); - + function to_icache_entry(x : tag_ram_data_t) return icache_entry_t is variable result : icache_entry_t; begin @@ -90,47 +113,63 @@ END COMPONENT; return result; end to_tag_ram_data; - type cache_state_t is (init, ready, flush, mem_request, mem_access, mem_data, rd_cache); + type cache_state_t is (init, ready, invalidate, flush, mem_request, mem_access, mem_data, rd_cache, upd_cache); signal s, sn : cache_state_t; + signal cache_req : std_logic; + signal cache_ack : std_logic; signal cache_busy : std_logic; signal cache_miss : std_logic; signal tag_match : std_logic; + signal cache_miss_inv : std_logic; + signal tag_match_inv : std_logic; signal word_index_reg : unsigned(word_index_width-1 downto 0); signal addr_windex_reg : unsigned(word_index_width-1 downto 0); signal cache_index_reg : unsigned(cache_index_width-1 downto 0); - signal tag_index_reg : unsigned(tag_width-1 downto 0); + signal cache_index_inv : unsigned(cache_index_width-1 downto 0); + signal tag_reg : unsigned(tag_width-1 downto 0); + signal tag_inv : unsigned(tag_width-1 downto 0); + signal tag_reg_inv : unsigned(tag_width-1 downto 0); signal cache_entry_in : icache_entry_t; signal cache_entry_out : icache_entry_t; + signal cache_entry_out_inv : icache_entry_t; signal data_ram_addr_rd : unsigned(lg2(cache_size)-1 downto 0); signal data_ram_data_rd : word_t; signal data_ram_addr_wr : unsigned(lg2(cache_size)-1 downto 0); signal data_ram_data_wr : word_t; signal data_ram_we : std_logic; - signal data_ram_re : std_logic; signal tag_ram_addr_rd : unsigned(cache_index_width-1 downto 0); signal tag_ram_data_rd : tag_ram_data_t; + signal tag_ram_data_rd_inv : tag_ram_data_t; signal tag_ram_addr_wr : unsigned(cache_index_width-1 downto 0); signal tag_ram_data_wr : tag_ram_data_t; - signal tag_ram_re : std_logic; signal tag_ram_we : std_logic; signal fill_count : natural range 0 to 2**word_index_width-1; signal fill_count_en : std_logic; signal fill_count_rdy : std_logic; signal flush_count : natural range 0 to 2**cache_index_width-1; + signal flush_count_rst : std_logic; signal flush_count_en : std_logic; signal flush_count_rdy : std_logic; signal request_count : natural range 0 to 2**word_index_width-1; signal request_count_en : std_logic; signal request_count_rdy : std_logic; - signal cpu_reg_en : std_logic; + signal ram_read_en : std_logic; signal was_miss : std_logic; - + signal invalidate_all : std_logic; + signal invalidate_ack : std_logic; + signal invalidate_en : std_logic; + signal invalidate_req : std_logic; + begin + ram_read_en <= cpu_en or was_miss; + cache_index_inv <= ctrl.inv_addr(cache_index_width+word_index_width+1 downto word_index_width+2); + tag_inv <= ctrl.inv_addr(tag_width+cache_index_width+word_index_width+1 downto cache_index_width+word_index_width+2); + cpu_index_reg: process(CLK_I) @@ -138,15 +177,15 @@ cpu_index_reg: if rising_edge(CLK_I) then if RST_I = '1' then cache_index_reg <= (others => '0'); - tag_index_reg <= (others => '0'); + tag_reg <= (others => '0'); elsif fill_count_en = '1' then if ACK_I = '1' then word_index_reg <= word_index_reg + 1; end if; - elsif cpu_reg_en = '1' then + elsif cache_busy = '0' then word_index_reg <= cpu_word_index; cache_index_reg <= cpu_cache_index; - tag_index_reg <= cpu_tag; + tag_reg <= cpu_tag; end if; end if; end process; @@ -159,13 +198,44 @@ addr_windex_register: if SRDY_I = '1' then addr_windex_reg <= addr_windex_reg + 1; end if; - elsif cpu_reg_en = '1' then + elsif cache_busy = '0' then addr_windex_reg <= cpu_word_index; end if; end if; end process; -inst_tag_ram : dpram_1w1r +cpu_request_register: + process(CLK_I) + begin + if rising_edge(CLK_I) then + if RST_I = '1' then + cache_req <= '0'; + elsif cpu_en = '1' then + if cache_busy = '0' then + cache_req <= en; + end if; + elsif cache_ack = '1' then + cache_req <= '0'; + end if; + end if; + end process; + +cache_invalidate_request: + process(CLK_I) + begin + if rising_edge(CLK_I) then + if RST_I = '1' or ctrl.inv_all = '1' or ctrl.inv_at = '1' then + invalidate_req <= '1'; + invalidate_all <= ctrl.inv_all or RST_I; + tag_reg_inv <= tag_inv; + elsif invalidate_ack = '1' then + invalidate_req <= '0'; + invalidate_all <= '0'; + end if; + end if; + end process; + +inst_tag_ram : dpram_2w2r GENERIC MAP ( addr_width => tag_ram_addr_width, @@ -173,14 +243,17 @@ inst_tag_ram : dpram_1w1r ) PORT MAP ( - clka => CLK_I, - clkb => CLK_I, + clk_a => CLK_I, + clk_b => CLK_I, en_a => '1', - en_b => tag_ram_re, + en_b => ram_read_en, we_a => tag_ram_we, + we_b => '0', addr_a => tag_ram_addr_wr, addr_b => tag_ram_addr_rd, din_a => tag_ram_data_wr, + din_b => tag_ram_data_wr, + dout_a => tag_ram_data_rd_inv, dout_b => tag_ram_data_rd ); @@ -195,7 +268,7 @@ inst_data_ram : dpram_1w1r clka => CLK_I, clkb => CLK_I, en_a => '1', - en_b => data_ram_re, + en_b => ram_read_en, we_a => data_ram_we, addr_a => data_ram_addr_wr, addr_b => data_ram_addr_rd, @@ -203,7 +276,6 @@ inst_data_ram : dpram_1w1r dout_b => data_ram_data_rd ); - cache_state_next: process(CLK_I) begin @@ -216,70 +288,86 @@ cache_state_next: end if; end process; + ADDR_O <= tag_reg & cache_index_reg & addr_windex_reg & "00"; cpu_busy <= cache_busy; cpu_dout <= data_ram_data_rd; - tag_match <= '1' when tag_index_reg = cache_entry_out.tag else '0'; - cache_miss <= not (tag_match and cache_entry_out.valid); - tag_ram_data_wr <= to_tag_ram_data(cache_entry_in); - tag_ram_addr_wr <= to_unsigned(flush_count, cache_index_width) when flush_count_en = '1' else cache_index_reg; - tag_ram_addr_rd <= cpu_cache_index when was_miss = '0' else cache_index_reg; cache_entry_out <= to_icache_entry(tag_ram_data_rd); + tag_match <= '1' when tag_reg = cache_entry_out.tag else '0'; + cache_miss <= not (tag_match and cache_entry_out.valid); + + cache_entry_out_inv <= to_icache_entry(tag_ram_data_rd_inv); + tag_match_inv <= '1' when tag_reg_inv = cache_entry_out_inv.tag else '0'; + cache_miss_inv <= not (tag_match_inv and cache_entry_out_inv.valid); + + tag_ram_data_wr <= to_tag_ram_data(cache_entry_in); + tag_ram_addr_wr <= to_unsigned(flush_count, cache_index_width) when invalidate_en = '1' else cache_index_reg; + tag_ram_addr_rd <= cpu_cache_index when was_miss = '0' else cache_index_reg; data_ram_addr_rd <= (cpu_cache_index & cpu_word_index) when was_miss = '0' else (cache_index_reg & word_index_reg); - ADDR_O <= tag_index_reg & cache_index_reg & addr_windex_reg & "00"; data_ram_addr_wr <= cache_index_reg & word_index_reg; data_ram_data_wr <= DAT_I; data_ram_we <= fill_count_en and ACK_I; cache_state: - process(s, cache_miss, flush_count_rdy, fill_count_rdy, request_count_rdy, tag_index_reg, cpu_en, SRDY_I, en) + process(s, cache_req, cache_miss, cache_miss_inv, flush_count_rdy, fill_count_rdy, request_count_rdy, tag_reg, SRDY_I, invalidate_req, invalidate_all) begin - cpu_reg_en <= '0'; - cache_busy <= '1'; + cache_busy <= cache_req; + cache_ack <= '0'; tag_ram_we <= '0'; flush_count_en <= '0'; + flush_count_rst <= '0'; + invalidate_en <= '0'; request_count_en <= '0'; fill_count_en <= '0'; CYC_O <= '0'; STB_O <= '0'; - data_ram_re <= '0'; - tag_ram_re <= '0'; was_miss <= '0'; + invalidate_ack <= '0'; + cache_entry_in.tv_p <= (others => '0'); - cache_entry_in.tag <= tag_index_reg; + cache_entry_in.tag <= tag_reg; cache_entry_in.valid <= '0'; sn <= s; case s is when init => - sn <= flush; + sn <= ready; when ready => - if en = '1' then - cache_busy <= '0'; + if invalidate_req = '1' then + sn <= invalidate; + invalidate_en <= '1'; + elsif cache_req = '1' then if cache_miss = '1' then sn <= mem_request; - cpu_reg_en <= '0'; - cache_busy <= '1'; CYC_O <= '1'; - elsif cpu_en = '1' then - cpu_reg_en <= '1'; - data_ram_re <= '1'; - tag_ram_re <= '1'; + else + cache_busy <= '0'; + cache_ack <= '1'; end if; end if; + when invalidate => + sn <= rd_cache; + invalidate_en <= '1'; + invalidate_ack <= '1'; + if invalidate_all = '1' then + sn <= flush; + flush_count_rst <= '1'; + elsif cache_miss_inv = '0' then + tag_ram_we <= '1'; + cache_entry_in.valid <= '0'; + cache_entry_in.tag <= (others => '0'); + sn <= rd_cache; + end if; + when flush => flush_count_en <= '1'; + invalidate_en <= '1'; tag_ram_we <= '1'; cache_entry_in.valid <= '0'; cache_entry_in.tag <= (others => '0'); if flush_count_rdy = '1' then tag_ram_we <= '0'; - sn <= ready; - if cpu_en = '1' then - cpu_reg_en <= '1'; - data_ram_re <= '1'; - tag_ram_re <= '1'; - end if; + sn <= rd_cache; end if; when mem_request => CYC_O <= '1'; @@ -304,11 +392,8 @@ cache_state: sn <= rd_cache; end if; when rd_cache => - tag_ram_re <= '1'; - data_ram_re <= '1'; - was_miss <= '1'; - sn <= ready; - + was_miss <= '1'; + sn <= ready; when others => sn <= ready; end case; @@ -319,10 +404,12 @@ flush_counter: process(CLK_I) begin if rising_edge(CLK_I) then - if flush_count_en = '0' then + if ctrl.inv_at = '1' then + flush_count <= to_integer(cache_index_inv); + elsif flush_count_rst = '1' then flush_count_rdy <= '0'; flush_count <= 2**cache_index_width-1; - else + elsif flush_count_en = '1' then if flush_count /= 0 then flush_count <= flush_count - 1; else