From 5cfa65e836138179ca84d369a9711460411aa88e Mon Sep 17 00:00:00 2001 From: Benjamin Herrenschmidt Date: Mon, 27 Sep 2021 21:53:52 +1000 Subject: [PATCH] Introduce addr_to_wb() and wb_to_addr() helpers These convert addresses to/from wishbone addresses, and use them in parts of the caches, in order to make the code a bit more readable. Along the way, rename some functions in the caches to make it a bit clearer what they operate on and fix a bug in the icache STOP_RELOAD state where the wb address wasn't properly converted. Signed-off-by: Benjamin Herrenschmidt --- dcache.vhdl | 13 ++++++------- icache.vhdl | 30 ++++++++++++++---------------- wishbone_types.vhdl | 20 ++++++++++++++++++++ 3 files changed, 40 insertions(+), 23 deletions(-) diff --git a/dcache.vhdl b/dcache.vhdl index 489ccb5..b4098f9 100644 --- a/dcache.vhdl +++ b/dcache.vhdl @@ -452,7 +452,7 @@ architecture rtl of dcache is end; -- Returns whether this is the last row of a line - function is_last_row_addr(addr: wishbone_addr_type; last: row_in_line_t) return boolean is + function is_last_row_wb_addr(addr: wishbone_addr_type; last: row_in_line_t) return boolean is begin return unsigned(addr(LINE_OFF_BITS - ROW_OFF_BITS - 1 downto 0)) = last; end; @@ -464,7 +464,7 @@ architecture rtl of dcache is end; -- Return the address of the next row in the current cache line - function next_row_addr(addr: wishbone_addr_type) return std_ulogic_vector is + function next_row_wb_addr(addr: wishbone_addr_type) return std_ulogic_vector is variable row_idx : std_ulogic_vector(ROW_LINEBITS-1 downto 0); variable result : wishbone_addr_type; begin @@ -804,8 +804,7 @@ begin variable addr : real_addr_t; begin if rising_edge(clk) then - addr := (others => '0'); - addr(snoop_in.adr'left + ROW_OFF_BITS downto ROW_OFF_BITS) := snoop_in.adr; + addr := addr_to_real(wb_to_addr(snoop_in.adr)); snoop_tag_set <= cache_tags(get_index(addr)); snoop_wrtag <= get_tag(addr); snoop_index <= get_index(addr); @@ -1381,7 +1380,7 @@ begin -- Main state machine case r1.state is when IDLE => - r1.wb.adr <= req.real_addr(r1.wb.adr'left + ROW_OFF_BITS downto ROW_OFF_BITS); + r1.wb.adr <= addr_to_wb(req.real_addr); r1.wb.sel <= req.byte_sel; r1.wb.dat <= req.data; r1.dcbz <= req.dcbz; @@ -1469,12 +1468,12 @@ begin -- If we are still sending requests, was one accepted ? if wishbone_in.stall = '0' and r1.wb.stb = '1' then -- That was the last word ? We are done sending. Clear stb. - if is_last_row_addr(r1.wb.adr, r1.end_row_ix) then + if is_last_row_wb_addr(r1.wb.adr, r1.end_row_ix) then r1.wb.stb <= '0'; end if; -- Calculate the next row address - r1.wb.adr <= next_row_addr(r1.wb.adr); + r1.wb.adr <= next_row_wb_addr(r1.wb.adr); end if; -- Incoming acks processing diff --git a/icache.vhdl b/icache.vhdl index ecd0c84..e7ac528 100644 --- a/icache.vhdl +++ b/icache.vhdl @@ -235,7 +235,7 @@ architecture rtl of icache is end; -- Return the cache row index (data memory) for an address - function get_row(addr: std_ulogic_vector) return row_t is + function get_row(addr: std_ulogic_vector(63 downto 0)) return row_t is begin return to_integer(unsigned(addr(SET_SIZE_BITS - 1 downto ROW_OFF_BITS))); end; @@ -249,9 +249,9 @@ architecture rtl of icache is end; -- Returns whether this is the last row of a line - function is_last_row_addr(addr: wishbone_addr_type; last: row_in_line_t) return boolean is + function is_last_row_wb_addr(wb_addr: wishbone_addr_type; last: row_in_line_t) return boolean is begin - return unsigned(addr(LINE_OFF_BITS - ROW_OFF_BITS - 1 downto 0)) = last; + return unsigned(wb_addr(LINE_OFF_BITS - ROW_OFF_BITS - 1 downto 0)) = last; end; -- Returns whether this is the last row of a line @@ -261,15 +261,15 @@ architecture rtl of icache is end; -- Return the address of the next row in the current cache line - function next_row_addr(addr: wishbone_addr_type) + function next_row_wb_addr(wb_addr: wishbone_addr_type) return std_ulogic_vector is variable row_idx : std_ulogic_vector(ROW_LINEBITS-1 downto 0); variable result : wishbone_addr_type; begin -- Is there no simpler way in VHDL to generate that 3 bits adder ? - row_idx := addr(ROW_LINEBITS - 1 downto 0); + row_idx := wb_addr(ROW_LINEBITS - 1 downto 0); row_idx := std_ulogic_vector(unsigned(row_idx) + 1); - result := addr; + result := wb_addr; result(ROW_LINEBITS - 1 downto 0) := row_idx; return result; end; @@ -299,10 +299,9 @@ architecture rtl of icache is end; -- Get the tag value from the address - function get_tag(addr: std_ulogic_vector(REAL_ADDR_BITS - 1 downto 0); - endian: std_ulogic) return cache_tag_t is + function get_tag(addr: real_addr_t; endian: std_ulogic) return cache_tag_t is begin - return endian & addr(REAL_ADDR_BITS - 1 downto SET_SIZE_BITS); + return endian & addr(addr'left downto SET_SIZE_BITS); end; -- Read a tag from a tag memory row @@ -523,7 +522,7 @@ begin -- used for cache miss processing if needed -- req_laddr <= (63 downto REAL_ADDR_BITS => '0') & - real_addr(REAL_ADDR_BITS - 1 downto ROW_OFF_BITS)& + real_addr(REAL_ADDR_BITS - 1 downto ROW_OFF_BITS) & (ROW_OFF_BITS-1 downto 0 => '0'); -- Test if pending request is a hit on any way @@ -655,8 +654,7 @@ begin -- Detect snooped writes and decode address into index and tag -- Since we never write, any write should be snooped snoop_valid <= wb_snoop_in.cyc and wb_snoop_in.stb and wb_snoop_in.we; - snoop_addr := (others => '0'); - snoop_addr(wb_snoop_in.adr'left + ROW_OFF_BITS downto ROW_OFF_BITS) := wb_snoop_in.adr; + 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)); snoop_tag := get_tag(snoop_addr, '0'); @@ -715,7 +713,7 @@ begin -- Prep for first wishbone read. We calculate the address of -- the start of the cache line and start the WB cycle. -- - r.wb.adr <= req_laddr(r.wb.adr'left + ROW_OFF_BITS downto ROW_OFF_BITS); + r.wb.adr <= addr_to_wb(req_laddr); r.wb.cyc <= '1'; r.wb.stb <= '1'; @@ -747,12 +745,12 @@ begin if wishbone_in.stall = '0' and r.wb.stb = '1' then -- That was the last word ? We are done sending. Clear stb. -- - if is_last_row_addr(r.wb.adr, r.end_row_ix) then + if is_last_row_wb_addr(r.wb.adr, r.end_row_ix) then r.wb.stb <= '0'; end if; -- Calculate the next row address - r.wb.adr <= next_row_addr(r.wb.adr); + r.wb.adr <= next_row_wb_addr(r.wb.adr); end if; -- Abort reload if we get an invalidation @@ -783,7 +781,7 @@ begin when STOP_RELOAD => -- Wait for all outstanding requests to be satisfied, then -- go to IDLE state. - if get_row_of_line(r.store_row) = get_row_of_line(get_row(r.wb.adr)) then + if get_row_of_line(r.store_row) = get_row_of_line(get_row(wb_to_addr(r.wb.adr))) then r.wb.cyc <= '0'; r.state <= IDLE; end if; diff --git a/wishbone_types.vhdl b/wishbone_types.vhdl index 8cb3e9b..aea75e8 100644 --- a/wishbone_types.vhdl +++ b/wishbone_types.vhdl @@ -15,6 +15,9 @@ package wishbone_types is subtype wishbone_data_type is std_ulogic_vector(wishbone_data_bits-1 downto 0); subtype wishbone_sel_type is std_ulogic_vector(wishbone_sel_bits-1 downto 0); + function addr_to_wb(addr: std_ulogic_vector) return wishbone_addr_type; + function wb_to_addr(wb_addr: wishbone_addr_type) return std_ulogic_vector; + type wishbone_master_out is record adr : wishbone_addr_type; dat : wishbone_data_type; @@ -38,6 +41,7 @@ package wishbone_types is -- -- IO Bus to a device, 30-bit address, 32-bits data -- + type wb_io_master_out is record adr : std_ulogic_vector(29 downto 0); dat : std_ulogic_vector(31 downto 0); @@ -56,3 +60,19 @@ package wishbone_types is end record; constant wb_io_slave_out_init : wb_io_slave_out := (ack => '0', stall => '0', others => (others => '0')); end package wishbone_types; + +package body wishbone_types is + function addr_to_wb(addr: std_ulogic_vector) return wishbone_addr_type is + begin + assert addr'length >= (wishbone_addr_type'length + wishbone_log2_width); + assert addr'right = 0; + return addr(wishbone_addr_type'left + wishbone_log2_width downto wishbone_log2_width); + end; + function wb_to_addr(wb_addr: wishbone_addr_type) return std_ulogic_vector is + variable ret : std_ulogic_vector(63 downto 0); + begin + ret := (others => '0'); + ret(wishbone_addr_type'left + wishbone_log2_width downto wishbone_log2_width) := wb_addr; + return ret; + end; +end wishbone_types; -- 2.30.2