Introduce addr_to_wb() and wb_to_addr() helpers
authorBenjamin Herrenschmidt <benh@kernel.crashing.org>
Mon, 27 Sep 2021 11:53:52 +0000 (21:53 +1000)
committerBenjamin Herrenschmidt <benh@kernel.crashing.org>
Mon, 27 Sep 2021 12:04:35 +0000 (22:04 +1000)
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 <benh@kernel.crashing.org>
dcache.vhdl
icache.vhdl
wishbone_types.vhdl

index 489ccb5f9376e7ea14e1c05a0504bb9bd54e954c..b4098f920e10136f608362487d28e235b5b486ba 100644 (file)
@@ -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
index ecd0c84ec716c8aaec2c943ed81798964fc94901..e7ac5289cef0efc250a828d9d01edb6dcf974fb2 100644 (file)
@@ -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;
index 8cb3e9b010889fd5e1456d8c6c253bcd47ade9bd..aea75e88ca604d98103ff6dc7116e5263ed70d47 100644 (file)
@@ -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;