-- SET_SIZE_BITS is the log base 2 of the set size
constant SET_SIZE_BITS : natural := LINE_OFF_BITS + INDEX_BITS;
-- TAG_BITS is the number of bits of the tag part of the address
- constant TAG_BITS : natural := REAL_ADDR_BITS - SET_SIZE_BITS;
+ -- the +1 is to allow the endianness to be stored in the tag
+ constant TAG_BITS : natural := REAL_ADDR_BITS - SET_SIZE_BITS + 1;
-- WAY_BITS is the number of bits to select a way
constant WAY_BITS : natural := log2(NUM_WAYS);
hit_nia : std_ulogic_vector(63 downto 0);
hit_smark : std_ulogic;
hit_valid : std_ulogic;
+ big_endian: std_ulogic;
-- Cache miss state (reload state machine)
state : state_t;
end;
-- Get the tag value from the address
- function get_tag(addr: std_ulogic_vector(REAL_ADDR_BITS - 1 downto 0)) return cache_tag_t is
+ function get_tag(addr: std_ulogic_vector(REAL_ADDR_BITS - 1 downto 0);
+ endian: std_ulogic) return cache_tag_t is
begin
- return addr(REAL_ADDR_BITS - 1 downto SET_SIZE_BITS);
+ return endian & addr(REAL_ADDR_BITS - 1 downto SET_SIZE_BITS);
end;
-- Read a tag from a tag memory row
report "geometry bits don't add up" severity FAILURE;
assert (LINE_OFF_BITS = ROW_OFF_BITS + ROW_LINEBITS)
report "geometry bits don't add up" severity FAILURE;
- assert (REAL_ADDR_BITS = TAG_BITS + INDEX_BITS + LINE_OFF_BITS)
+ assert (REAL_ADDR_BITS + 1 = TAG_BITS + INDEX_BITS + LINE_OFF_BITS)
report "geometry bits don't add up" severity FAILURE;
- assert (REAL_ADDR_BITS = TAG_BITS + ROW_BITS + ROW_OFF_BITS)
+ assert (REAL_ADDR_BITS + 1 = TAG_BITS + ROW_BITS + ROW_OFF_BITS)
report "geometry bits don't add up" severity FAILURE;
sim_debug: if SIM generate
signal wr_addr : std_ulogic_vector(ROW_BITS-1 downto 0);
signal dout : cache_row_t;
signal wr_sel : std_ulogic_vector(ROW_SIZE-1 downto 0);
+ signal wr_dat : std_ulogic_vector(wishbone_in.dat'left downto 0);
begin
way: entity work.cache_ram
generic map (
rd_data => dout,
wr_sel => wr_sel,
wr_addr => wr_addr,
- wr_data => wishbone_in.dat
+ wr_data => wr_dat
);
process(all)
+ variable j: integer;
begin
+ -- byte-swap read data if big endian
+ if r.store_tag(TAG_BITS - 1) = '0' then
+ wr_dat <= wishbone_in.dat;
+ else
+ for ii in 0 to (wishbone_in.dat'length / 8) - 1 loop
+ j := ((ii / 4) * 4) + (3 - (ii mod 4));
+ wr_dat(ii * 8 + 7 downto ii * 8) <= wishbone_in.dat(j * 8 + 7 downto j * 8);
+ end loop;
+ end if;
do_read <= not (stall_in or use_previous);
do_write <= '0';
if wishbone_in.ack = '1' and replace_way = i then
cache_out(i) <= dout;
rd_addr <= std_ulogic_vector(to_unsigned(req_row, ROW_BITS));
wr_addr <= std_ulogic_vector(to_unsigned(r.store_row, ROW_BITS));
- for i in 0 to ROW_SIZE-1 loop
- wr_sel(i) <= do_write;
+ for ii in 0 to ROW_SIZE-1 loop
+ wr_sel(ii) <= do_write;
end loop;
end process;
end generate;
-- last cycle, and we don't want the first 32-bit chunk, then we can
-- keep the data we read last cycle and just use that.
if unsigned(i_in.nia(INSN_BITS+2-1 downto 2)) /= 0 then
- use_previous <= i_in.sequential and r.hit_valid;
+ use_previous <= i_in.req and i_in.sequential and r.hit_valid;
else
use_previous <= '0';
end if;
-- 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);
+ 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
i_out.nia <= r.hit_nia;
i_out.stop_mark <= r.hit_smark;
i_out.fetch_failed <= r.fetch_failed;
+ i_out.big_endian <= r.big_endian;
+ i_out.next_predicted <= i_in.predicted;
-- Stall fetch1 if we have a miss on cache or TLB or a protection fault
stall_out <= not (is_hit and access_ok);
-- Send stop marks and NIA down regardless of validity
r.hit_smark <= i_in.stop_mark;
r.hit_nia <= i_in.nia;
+ r.big_endian <= i_in.big_endian;
end if;
end if;
end process;