From 404abefd92be06ff7c30627925cf0901e355f8f2 Mon Sep 17 00:00:00 2001 From: Michael Neuling Date: Thu, 14 Jul 2022 10:31:53 +1000 Subject: [PATCH] Metavalue cleanup for icache.vhdl Signed-off-by: Michael Neuling --- icache.vhdl | 61 +++++++++++++++++++++++++++++++++++++---------------- 1 file changed, 43 insertions(+), 18 deletions(-) diff --git a/icache.vhdl b/icache.vhdl index 394bc5e..9eb08c1 100644 --- a/icache.vhdl +++ b/icache.vhdl @@ -207,7 +207,6 @@ architecture rtl of icache is signal req_is_miss : std_ulogic; signal req_raddr : real_addr_t; - signal tlb_req_index : tlb_index_t; signal real_addr : real_addr_t; signal ra_valid : std_ulogic; signal priv_fault : std_ulogic; @@ -317,14 +316,15 @@ architecture rtl of icache is end; -- Simple hash for direct-mapped TLB index - function hash_ea(addr: std_ulogic_vector(63 downto 0)) return tlb_index_t is + function hash_ea(addr: std_ulogic_vector(63 downto 0)) return std_ulogic_vector is variable hash : std_ulogic_vector(TLB_BITS - 1 downto 0); begin hash := addr(TLB_LG_PGSZ + TLB_BITS - 1 downto TLB_LG_PGSZ) xor addr(TLB_LG_PGSZ + 2 * TLB_BITS - 1 downto TLB_LG_PGSZ + TLB_BITS) xor addr(TLB_LG_PGSZ + 3 * TLB_BITS - 1 downto TLB_LG_PGSZ + 2 * TLB_BITS); - return to_integer(unsigned(hash)); + return hash; end; + begin assert LINE_SIZE mod ROW_SIZE = 0; @@ -435,7 +435,9 @@ begin process(all) begin -- PLRU interface - if get_index(r.hit_nia) = i then + if is_X(r.hit_nia) then + plru_acc_en <= 'X'; + elsif get_index(r.hit_nia) = i then plru_acc_en <= r.hit_valid; else plru_acc_en <= '0'; @@ -450,15 +452,25 @@ begin itlb_lookup : process(all) variable pte : tlb_pte_t; variable ttag : tlb_tag_t; + variable tlb_req_index : std_ulogic_vector(TLB_BITS - 1 downto 0); begin - tlb_req_index <= hash_ea(i_in.nia); - pte := itlb_ptes(tlb_req_index); - ttag := itlb_tags(tlb_req_index); + tlb_req_index := hash_ea(i_in.nia); + if is_X(tlb_req_index) then + pte := (others => 'X'); + ttag := (others => 'X'); + else + pte := itlb_ptes(to_integer(unsigned(tlb_req_index))); + ttag := itlb_tags(to_integer(unsigned(tlb_req_index))); + end if; if i_in.virt_mode = '1' then real_addr <= pte(REAL_ADDR_BITS - 1 downto TLB_LG_PGSZ) & i_in.nia(TLB_LG_PGSZ - 1 downto 0); if ttag = i_in.nia(63 downto TLB_LG_PGSZ + TLB_BITS) then - ra_valid <= itlb_valids(tlb_req_index); + if is_X(tlb_req_index) then + ra_valid <= 'X'; + else + ra_valid <= itlb_valids(to_integer(unsigned(tlb_req_index))); + end if; else ra_valid <= '0'; end if; @@ -476,7 +488,7 @@ begin -- iTLB update itlb_update: process(clk) - variable wr_index : tlb_index_t; + variable wr_index : std_ulogic_vector(TLB_BITS - 1 downto 0); begin if rising_edge(clk) then wr_index := hash_ea(m_in.addr); @@ -486,12 +498,14 @@ begin itlb_valids(i) <= '0'; end loop; elsif m_in.tlbie = '1' then + assert not is_X(wr_index) report "icache index invalid on write" severity FAILURE; -- clear entry regardless of hit or miss - itlb_valids(wr_index) <= '0'; + itlb_valids(to_integer(unsigned(wr_index))) <= '0'; elsif m_in.tlbld = '1' then - itlb_tags(wr_index) <= m_in.addr(63 downto TLB_LG_PGSZ + TLB_BITS); - itlb_ptes(wr_index) <= m_in.pte; - itlb_valids(wr_index) <= '1'; + assert not is_X(wr_index) report "icache index invalid on write" severity FAILURE; + itlb_tags(to_integer(unsigned(wr_index))) <= m_in.addr(63 downto TLB_LG_PGSZ + TLB_BITS); + itlb_ptes(to_integer(unsigned(wr_index))) <= m_in.pte; + itlb_valids(to_integer(unsigned(wr_index))) <= '1'; end if; ev.itlb_miss_resolved <= m_in.tlbld and not rst; end if; @@ -503,9 +517,11 @@ begin variable hit_way : way_t; begin -- Extract line, row and tag from request - req_index <= get_index(i_in.nia); - req_row <= get_row(i_in.nia); - req_tag <= get_tag(real_addr, i_in.big_endian); + if not is_X(i_in.nia) then + req_index <= get_index(i_in.nia); + req_row <= get_row(i_in.nia); + end if; + req_tag <= get_tag(real_addr, i_in.big_endian); -- Calculate address of beginning of cache row, will be -- used for cache miss processing if needed @@ -517,7 +533,11 @@ begin hit_way := 0; is_hit := '0'; for i in way_t loop - if i_in.req = '1' and + if is_X(i_in.nia) then + -- FIXME: This is fragile + -- req_index or req_row could be a metavalue + is_hit := 'X'; + elsif i_in.req = '1' and (cache_valids(req_index)(i) = '1' or (r.state = WAIT_ACK and req_index = r.store_index and @@ -556,7 +576,7 @@ begin -- some of the cache geometry information. -- if r.hit_valid = '1' then - i_out.insn <= read_insn_word(r.hit_nia, cache_out(r.hit_way)); + i_out.insn <= read_insn_word(r.hit_nia, cache_out(r.hit_way)); else i_out.insn <= (others => '0'); end if; @@ -592,6 +612,8 @@ begin r.hit_valid <= req_is_hit; if req_is_hit = '1' then r.hit_way <= req_hit_way; + -- this is a bit fragile but better than propogating bad values + assert not is_X(i_in.nia) report "metavalue in NIA" severity FAILURE; report "cache hit nia:" & to_hstring(i_in.nia) & " IR:" & std_ulogic'image(i_in.virt_mode) & @@ -648,6 +670,9 @@ begin snoop_addr := addr_to_real(wb_to_addr(wb_snoop_in.adr)); snoop_index <= get_index(snoop_addr); snoop_cache_tags := cache_tags(get_index(snoop_addr)); + if snoop_valid = '1' and is_X(snoop_addr) then + report "metavalue in snoop_addr" severity FAILURE; + end if; snoop_tag := get_tag(snoop_addr, '0'); snoop_hits <= (others => '0'); for i in way_t loop