mirror of
https://github.com/antonblanchard/microwatt.git
synced 2026-01-11 23:43:15 +00:00
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 <benh@kernel.crashing.org>
This commit is contained in:
parent
d745995207
commit
5cfa65e836
13
dcache.vhdl
13
dcache.vhdl
@ -452,7 +452,7 @@ architecture rtl of dcache is
|
|||||||
end;
|
end;
|
||||||
|
|
||||||
-- Returns whether this is the last row of a line
|
-- 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
|
begin
|
||||||
return unsigned(addr(LINE_OFF_BITS - ROW_OFF_BITS - 1 downto 0)) = last;
|
return unsigned(addr(LINE_OFF_BITS - ROW_OFF_BITS - 1 downto 0)) = last;
|
||||||
end;
|
end;
|
||||||
@ -464,7 +464,7 @@ architecture rtl of dcache is
|
|||||||
end;
|
end;
|
||||||
|
|
||||||
-- Return the address of the next row in the current cache line
|
-- 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 row_idx : std_ulogic_vector(ROW_LINEBITS-1 downto 0);
|
||||||
variable result : wishbone_addr_type;
|
variable result : wishbone_addr_type;
|
||||||
begin
|
begin
|
||||||
@ -804,8 +804,7 @@ begin
|
|||||||
variable addr : real_addr_t;
|
variable addr : real_addr_t;
|
||||||
begin
|
begin
|
||||||
if rising_edge(clk) then
|
if rising_edge(clk) then
|
||||||
addr := (others => '0');
|
addr := addr_to_real(wb_to_addr(snoop_in.adr));
|
||||||
addr(snoop_in.adr'left + ROW_OFF_BITS downto ROW_OFF_BITS) := snoop_in.adr;
|
|
||||||
snoop_tag_set <= cache_tags(get_index(addr));
|
snoop_tag_set <= cache_tags(get_index(addr));
|
||||||
snoop_wrtag <= get_tag(addr);
|
snoop_wrtag <= get_tag(addr);
|
||||||
snoop_index <= get_index(addr);
|
snoop_index <= get_index(addr);
|
||||||
@ -1381,7 +1380,7 @@ begin
|
|||||||
-- Main state machine
|
-- Main state machine
|
||||||
case r1.state is
|
case r1.state is
|
||||||
when IDLE =>
|
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.sel <= req.byte_sel;
|
||||||
r1.wb.dat <= req.data;
|
r1.wb.dat <= req.data;
|
||||||
r1.dcbz <= req.dcbz;
|
r1.dcbz <= req.dcbz;
|
||||||
@ -1469,12 +1468,12 @@ begin
|
|||||||
-- If we are still sending requests, was one accepted ?
|
-- If we are still sending requests, was one accepted ?
|
||||||
if wishbone_in.stall = '0' and r1.wb.stb = '1' then
|
if wishbone_in.stall = '0' and r1.wb.stb = '1' then
|
||||||
-- That was the last word ? We are done sending. Clear stb.
|
-- 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';
|
r1.wb.stb <= '0';
|
||||||
end if;
|
end if;
|
||||||
|
|
||||||
-- Calculate the next row address
|
-- 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;
|
end if;
|
||||||
|
|
||||||
-- Incoming acks processing
|
-- Incoming acks processing
|
||||||
|
|||||||
30
icache.vhdl
30
icache.vhdl
@ -235,7 +235,7 @@ architecture rtl of icache is
|
|||||||
end;
|
end;
|
||||||
|
|
||||||
-- Return the cache row index (data memory) for an address
|
-- 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
|
begin
|
||||||
return to_integer(unsigned(addr(SET_SIZE_BITS - 1 downto ROW_OFF_BITS)));
|
return to_integer(unsigned(addr(SET_SIZE_BITS - 1 downto ROW_OFF_BITS)));
|
||||||
end;
|
end;
|
||||||
@ -249,9 +249,9 @@ architecture rtl of icache is
|
|||||||
end;
|
end;
|
||||||
|
|
||||||
-- Returns whether this is the last row of a line
|
-- 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
|
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;
|
end;
|
||||||
|
|
||||||
-- Returns whether this is the last row of a line
|
-- Returns whether this is the last row of a line
|
||||||
@ -261,15 +261,15 @@ architecture rtl of icache is
|
|||||||
end;
|
end;
|
||||||
|
|
||||||
-- Return the address of the next row in the current cache line
|
-- 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
|
return std_ulogic_vector is
|
||||||
variable row_idx : std_ulogic_vector(ROW_LINEBITS-1 downto 0);
|
variable row_idx : std_ulogic_vector(ROW_LINEBITS-1 downto 0);
|
||||||
variable result : wishbone_addr_type;
|
variable result : wishbone_addr_type;
|
||||||
begin
|
begin
|
||||||
-- Is there no simpler way in VHDL to generate that 3 bits adder ?
|
-- 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);
|
row_idx := std_ulogic_vector(unsigned(row_idx) + 1);
|
||||||
result := addr;
|
result := wb_addr;
|
||||||
result(ROW_LINEBITS - 1 downto 0) := row_idx;
|
result(ROW_LINEBITS - 1 downto 0) := row_idx;
|
||||||
return result;
|
return result;
|
||||||
end;
|
end;
|
||||||
@ -299,10 +299,9 @@ architecture rtl of icache is
|
|||||||
end;
|
end;
|
||||||
|
|
||||||
-- Get the tag value from the address
|
-- Get the tag value from the address
|
||||||
function get_tag(addr: std_ulogic_vector(REAL_ADDR_BITS - 1 downto 0);
|
function get_tag(addr: real_addr_t; endian: std_ulogic) return cache_tag_t is
|
||||||
endian: std_ulogic) return cache_tag_t is
|
|
||||||
begin
|
begin
|
||||||
return endian & addr(REAL_ADDR_BITS - 1 downto SET_SIZE_BITS);
|
return endian & addr(addr'left downto SET_SIZE_BITS);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
-- Read a tag from a tag memory row
|
-- Read a tag from a tag memory row
|
||||||
@ -523,7 +522,7 @@ begin
|
|||||||
-- used for cache miss processing if needed
|
-- used for cache miss processing if needed
|
||||||
--
|
--
|
||||||
req_laddr <= (63 downto REAL_ADDR_BITS => '0') &
|
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');
|
(ROW_OFF_BITS-1 downto 0 => '0');
|
||||||
|
|
||||||
-- Test if pending request is a hit on any way
|
-- 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
|
-- Detect snooped writes and decode address into index and tag
|
||||||
-- Since we never write, any write should be snooped
|
-- 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_valid <= wb_snoop_in.cyc and wb_snoop_in.stb and wb_snoop_in.we;
|
||||||
snoop_addr := (others => '0');
|
snoop_addr := addr_to_real(wb_to_addr(wb_snoop_in.adr));
|
||||||
snoop_addr(wb_snoop_in.adr'left + ROW_OFF_BITS downto ROW_OFF_BITS) := wb_snoop_in.adr;
|
|
||||||
snoop_index <= get_index(snoop_addr);
|
snoop_index <= get_index(snoop_addr);
|
||||||
snoop_cache_tags := cache_tags(get_index(snoop_addr));
|
snoop_cache_tags := cache_tags(get_index(snoop_addr));
|
||||||
snoop_tag := get_tag(snoop_addr, '0');
|
snoop_tag := get_tag(snoop_addr, '0');
|
||||||
@ -715,7 +713,7 @@ begin
|
|||||||
-- Prep for first wishbone read. We calculate the address of
|
-- Prep for first wishbone read. We calculate the address of
|
||||||
-- the start of the cache line and start the WB cycle.
|
-- 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.cyc <= '1';
|
||||||
r.wb.stb <= '1';
|
r.wb.stb <= '1';
|
||||||
|
|
||||||
@ -747,12 +745,12 @@ begin
|
|||||||
if wishbone_in.stall = '0' and r.wb.stb = '1' then
|
if wishbone_in.stall = '0' and r.wb.stb = '1' then
|
||||||
-- That was the last word ? We are done sending. Clear stb.
|
-- 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';
|
r.wb.stb <= '0';
|
||||||
end if;
|
end if;
|
||||||
|
|
||||||
-- Calculate the next row address
|
-- 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;
|
end if;
|
||||||
|
|
||||||
-- Abort reload if we get an invalidation
|
-- Abort reload if we get an invalidation
|
||||||
@ -783,7 +781,7 @@ begin
|
|||||||
when STOP_RELOAD =>
|
when STOP_RELOAD =>
|
||||||
-- Wait for all outstanding requests to be satisfied, then
|
-- Wait for all outstanding requests to be satisfied, then
|
||||||
-- go to IDLE state.
|
-- 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.wb.cyc <= '0';
|
||||||
r.state <= IDLE;
|
r.state <= IDLE;
|
||||||
end if;
|
end if;
|
||||||
|
|||||||
@ -15,6 +15,9 @@ package wishbone_types is
|
|||||||
subtype wishbone_data_type is std_ulogic_vector(wishbone_data_bits-1 downto 0);
|
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);
|
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
|
type wishbone_master_out is record
|
||||||
adr : wishbone_addr_type;
|
adr : wishbone_addr_type;
|
||||||
dat : wishbone_data_type;
|
dat : wishbone_data_type;
|
||||||
@ -38,6 +41,7 @@ package wishbone_types is
|
|||||||
--
|
--
|
||||||
-- IO Bus to a device, 30-bit address, 32-bits data
|
-- IO Bus to a device, 30-bit address, 32-bits data
|
||||||
--
|
--
|
||||||
|
|
||||||
type wb_io_master_out is record
|
type wb_io_master_out is record
|
||||||
adr : std_ulogic_vector(29 downto 0);
|
adr : std_ulogic_vector(29 downto 0);
|
||||||
dat : std_ulogic_vector(31 downto 0);
|
dat : std_ulogic_vector(31 downto 0);
|
||||||
@ -56,3 +60,19 @@ package wishbone_types is
|
|||||||
end record;
|
end record;
|
||||||
constant wb_io_slave_out_init : wb_io_slave_out := (ack => '0', stall => '0', others => (others => '0'));
|
constant wb_io_slave_out_init : wb_io_slave_out := (ack => '0', stall => '0', others => (others => '0'));
|
||||||
end package wishbone_types;
|
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;
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user