dcache: Cancel reservation on snooped store

This restructures the reservation machinery so that the reservation is
cleared when a snooped store by another agent is done to reservation
address.  The reservation address is now a real address rather than an
effective address.

For store-conditional, it is possible that a snooped store to the
reservation address could come in even after we have asserted cyc and
stb on the wishbone to do the store, and that should cause the store
not to be performed.  To achieve this, store-conditional now uses a
separate state in the r1 state machine, which is set up so that losing
the reservation due to a snooped store cause cyc and stb to be dropped
immediately, and the store-conditional fails.

For load-reserve, the reservation address is set at the end of cycle 1
and the reservation is made valid when the data is available.  For
lqarx, the reservation is made valid when the first doubleword of data
is available.

For the case where a snooped write comes in on cycle 0 of a larx and
hits the same cache line, we detect that the index and way of the
snooped write are the same as the index and way of the larx; it is
done this way because reservation.addr is not set until the real
address is available at the end of cycle 1.  A hit on the same index
and way causes reservation.valid to be set to 0 at the end of cycle 1.

For a write in cycle 1, we compare the latched address in cycle 2 with
the reservation address and clear reservation.valid at the end of
cycle 2 if they match.  In other words we compare the reservation
address with both the address being written this cycle and the address
being written in the previous cycle.

Signed-off-by: Paul Mackerras <paulus@ozlabs.org>
pull/434/head
Paul Mackerras 4 years ago
parent 140b930ad3
commit b181d28df2

@ -606,6 +606,7 @@ package common is
nc : std_ulogic; nc : std_ulogic;
reserve : std_ulogic; reserve : std_ulogic;
atomic_qw : std_ulogic; -- part of a quadword atomic op atomic_qw : std_ulogic; -- part of a quadword atomic op
atomic_first : std_ulogic;
atomic_last : std_ulogic; atomic_last : std_ulogic;
virt_mode : std_ulogic; virt_mode : std_ulogic;
priv_mode : std_ulogic; priv_mode : std_ulogic;

@ -184,7 +184,6 @@ architecture rtl of dcache is
-- Type of operation on a "valid" input -- Type of operation on a "valid" input
type op_t is (OP_NONE, type op_t is (OP_NONE,
OP_BAD, -- NC cache hit, TLB miss, prot/RC failure OP_BAD, -- NC cache hit, TLB miss, prot/RC failure
OP_STCX_FAIL, -- conditional store w/o reservation
OP_LOAD_HIT, -- Cache hit on load OP_LOAD_HIT, -- Cache hit on load
OP_LOAD_MISS, -- Load missing cache OP_LOAD_MISS, -- Load missing cache
OP_LOAD_NC, -- Non-cachable load OP_LOAD_NC, -- Non-cachable load
@ -195,8 +194,8 @@ architecture rtl of dcache is
type state_t is (IDLE, -- Normal load hit processing type state_t is (IDLE, -- Normal load hit processing
RELOAD_WAIT_ACK, -- Cache reload wait ack RELOAD_WAIT_ACK, -- Cache reload wait ack
STORE_WAIT_ACK, -- Store wait ack STORE_WAIT_ACK, -- Store wait ack
NC_LOAD_WAIT_ACK);-- Non-cachable load wait ack NC_LOAD_WAIT_ACK, -- Non-cachable load wait ack

DO_STCX); -- Check for stcx. validity


-- --
-- Dcache operations: -- Dcache operations:
@ -290,6 +289,9 @@ architecture rtl of dcache is
op : op_t; op : op_t;
valid : std_ulogic; valid : std_ulogic;
dcbz : std_ulogic; dcbz : std_ulogic;
reserve : std_ulogic;
first_dw : std_ulogic;
last_dw : std_ulogic;
real_addr : real_addr_t; real_addr : real_addr_t;
data : std_ulogic_vector(63 downto 0); data : std_ulogic_vector(63 downto 0);
byte_sel : std_ulogic_vector(7 downto 0); byte_sel : std_ulogic_vector(7 downto 0);
@ -365,10 +367,12 @@ architecture rtl of dcache is
-- --
type reservation_t is record type reservation_t is record
valid : std_ulogic; valid : std_ulogic;
addr : std_ulogic_vector(63 downto LINE_OFF_BITS); addr : std_ulogic_vector(REAL_ADDR_BITS - 1 downto LINE_OFF_BITS);
end record; end record;


signal reservation : reservation_t; signal reservation : reservation_t;
signal kill_rsrv : std_ulogic;
signal kill_rsrv2 : std_ulogic;


-- Async signals on incoming request -- Async signals on incoming request
signal req_index : index_t; signal req_index : index_t;
@ -382,10 +386,6 @@ architecture rtl of dcache is
signal early_req_row : row_t; signal early_req_row : row_t;
signal early_rd_valid : std_ulogic; signal early_rd_valid : std_ulogic;


signal cancel_store : std_ulogic;
signal set_rsrv : std_ulogic;
signal clear_rsrv : std_ulogic;

signal r0_valid : std_ulogic; signal r0_valid : std_ulogic;
signal r0_stall : std_ulogic; signal r0_stall : std_ulogic;


@ -427,10 +427,13 @@ architecture rtl of dcache is
-- TLB PLRU output interface -- TLB PLRU output interface
signal tlb_plru_victim : std_ulogic_vector(TLB_WAY_BITS-1 downto 0); signal tlb_plru_victim : std_ulogic_vector(TLB_WAY_BITS-1 downto 0);


signal snoop_active : std_ulogic;
signal snoop_tag_set : cache_tags_set_t; signal snoop_tag_set : cache_tags_set_t;
signal snoop_valid : std_ulogic; signal snoop_valid : std_ulogic;
signal snoop_wrtag : cache_tag_t; signal snoop_paddr : real_addr_t;
signal snoop_index : index_t; signal snoop_addr : real_addr_t;
signal snoop_hits : cache_way_valids_t;
signal req_snoop_hit : std_ulogic;


-- --
-- Helper functions to decode incoming requests -- Helper functions to decode incoming requests
@ -861,26 +864,45 @@ begin
end if; end if;
end process; end process;


-- Snoop logic
-- Don't snoop our own cycles
snoop_addr <= addr_to_real(wb_to_addr(snoop_in.adr));
snoop_active <= snoop_in.cyc and snoop_in.stb and snoop_in.we and
not (r1.wb.cyc and not wishbone_in.stall);
kill_rsrv <= '1' when (snoop_active = '1' and reservation.valid = '1' and
snoop_addr(REAL_ADDR_BITS - 1 downto LINE_OFF_BITS) = reservation.addr)
else '0';

-- Cache tag RAM second read port, for snooping -- Cache tag RAM second read port, for snooping
cache_tag_read_2 : process(clk) cache_tag_read_2 : process(clk)
variable addr : real_addr_t;
begin begin
if rising_edge(clk) then if rising_edge(clk) then
-- Don't snoop our own cycles if is_X(snoop_addr) then
snoop_valid <= '0'; snoop_tag_set <= (others => 'X');
if not (r1.wb.cyc = '1' and wishbone_in.stall = '0') then else
if (snoop_in.cyc and snoop_in.stb and snoop_in.we) = '1' then snoop_tag_set <= cache_tags(to_integer(get_index(snoop_addr)));
snoop_valid <= '1';
addr := addr_to_real(wb_to_addr(snoop_in.adr));
assert not is_X(addr);
snoop_tag_set <= cache_tags(to_integer(get_index(addr)));
snoop_wrtag <= get_tag(addr);
snoop_index <= get_index(addr);
end if;
end if; end if;
snoop_paddr <= snoop_addr;
snoop_valid <= snoop_active;
end if; end if;
end process; end process;


-- Compare the previous cycle's snooped store address to the reservation,
-- to catch the case where a write happens on cycle 1 of a cached larx
kill_rsrv2 <= '1' when (snoop_valid = '1' and reservation.valid = '1' and
snoop_paddr(REAL_ADDR_BITS - 1 downto LINE_OFF_BITS) = reservation.addr)
else '0';

snoop_tag_match : process(all)
begin
snoop_hits <= (others => '0');
for i in 0 to NUM_WAYS-1 loop
if snoop_valid = '1' and read_tag(i, snoop_tag_set) = get_tag(snoop_paddr) then
snoop_hits(i) <= '1';
end if;
end loop;
end process;

-- Cache request parsing and hit detection -- Cache request parsing and hit detection
dcache_request : process(all) dcache_request : process(all)
variable req_row : row_t; variable req_row : row_t;
@ -901,6 +923,8 @@ begin
variable rel_match : std_ulogic; variable rel_match : std_ulogic;
variable fwd_matches : std_ulogic_vector(TLB_NUM_WAYS - 1 downto 0); variable fwd_matches : std_ulogic_vector(TLB_NUM_WAYS - 1 downto 0);
variable fwd_match : std_ulogic; variable fwd_match : std_ulogic;
variable snp_matches : std_ulogic_vector(TLB_NUM_WAYS - 1 downto 0);
variable snoop_match : std_ulogic;
begin begin
-- Extract line, row and tag from request -- Extract line, row and tag from request
rindex := get_index(r0.req.addr); rindex := get_index(r0.req.addr);
@ -924,9 +948,11 @@ begin
is_hit := '0'; is_hit := '0';
rel_match := '0'; rel_match := '0';
fwd_match := '0'; fwd_match := '0';
snoop_match := '0';
if r0.req.virt_mode = '1' then if r0.req.virt_mode = '1' then
rel_matches := (others => '0'); rel_matches := (others => '0');
fwd_matches := (others => '0'); fwd_matches := (others => '0');
snp_matches := (others => '0');
for j in tlb_way_t loop for j in tlb_way_t loop
hit_way_set(j) := to_unsigned(0, WAY_BITS); hit_way_set(j) := to_unsigned(0, WAY_BITS);
s_hit := '0'; s_hit := '0';
@ -943,6 +969,9 @@ begin
tlb_valid_way(j) = '1' then tlb_valid_way(j) = '1' then
hit_way_set(j) := to_unsigned(i, WAY_BITS); hit_way_set(j) := to_unsigned(i, WAY_BITS);
s_hit := '1'; s_hit := '1';
if snoop_hits(i) = '1' then
snp_matches(j) := '1';
end if;
end if; end if;
end loop; end loop;
hit_set(j) := s_hit; hit_set(j) := s_hit;
@ -959,6 +988,7 @@ begin
hit_way := hit_way_set(to_integer(tlb_hit_way)); hit_way := hit_way_set(to_integer(tlb_hit_way));
rel_match := rel_matches(to_integer(tlb_hit_way)); rel_match := rel_matches(to_integer(tlb_hit_way));
fwd_match := fwd_matches(to_integer(tlb_hit_way)); fwd_match := fwd_matches(to_integer(tlb_hit_way));
snoop_match := snp_matches(to_integer(tlb_hit_way));
end if; end if;
else else
s_tag := get_tag(r0.req.addr); s_tag := get_tag(r0.req.addr);
@ -970,6 +1000,9 @@ begin
read_tag(i, cache_tag_set) = s_tag then read_tag(i, cache_tag_set) = s_tag then
hit_way := to_unsigned(i, WAY_BITS); hit_way := to_unsigned(i, WAY_BITS);
is_hit := '1'; is_hit := '1';
if snoop_hits(i) = '1' then
snoop_match := '1';
end if;
end if; end if;
end loop; end loop;
if go = '1' and not is_X(r1.reload_tag) and s_tag = r1.reload_tag then if go = '1' and not is_X(r1.reload_tag) and s_tag = r1.reload_tag then
@ -982,6 +1015,13 @@ begin
req_same_tag <= rel_match; req_same_tag <= rel_match;
fwd_same_tag <= fwd_match; fwd_same_tag <= fwd_match;


-- This is 1 if the snooped write from the previous cycle hits the same
-- cache line that is being accessed in this cycle.
req_snoop_hit <= '0';
if go = '1' and snoop_match = '1' and get_index(snoop_paddr) = rindex then
req_snoop_hit <= '1';
end if;

-- Whether to use forwarded data for a load or not -- Whether to use forwarded data for a load or not
use_forward_st <= '0'; use_forward_st <= '0';
use_forward_rl <= '0'; use_forward_rl <= '0';
@ -1060,8 +1100,6 @@ begin
if go = '1' then if go = '1' then
if access_ok = '0' then if access_ok = '0' then
op := OP_BAD; op := OP_BAD;
elsif cancel_store = '1' then
op := OP_STCX_FAIL;
else else
opsel := r0.req.load & nc & is_hit; opsel := r0.req.load & nc & is_hit;
case opsel is case opsel is
@ -1101,45 +1139,6 @@ begin
-- Wire up wishbone request latch out of stage 1 -- Wire up wishbone request latch out of stage 1
wishbone_out <= r1.wb; wishbone_out <= r1.wb;


-- Handle load-with-reservation and store-conditional instructions
reservation_comb: process(all)
begin
cancel_store <= '0';
set_rsrv <= '0';
clear_rsrv <= '0';
if r0_valid = '1' and r0.req.reserve = '1' then
-- XXX generate alignment interrupt if address is not aligned
-- XXX or if r0.req.nc = '1'
if r0.req.load = '1' then
-- load with reservation
set_rsrv <= not r0.req.atomic_qw or r0.req.atomic_last;
else
-- store conditional
clear_rsrv <= not r0.req.atomic_qw or r0.req.atomic_last;
if reservation.valid = '0' or
r0.req.addr(63 downto LINE_OFF_BITS) /= reservation.addr then
cancel_store <= '1';
end if;
end if;
end if;
end process;

reservation_reg: process(clk)
begin
if rising_edge(clk) then
if rst = '1' then
reservation.valid <= '0';
elsif r0_valid = '1' and access_ok = '1' then
if clear_rsrv = '1' then
reservation.valid <= '0';
elsif set_rsrv = '1' then
reservation.valid <= '1';
reservation.addr <= r0.req.addr(63 downto LINE_OFF_BITS);
end if;
end if;
end if;
end process;

-- Return data for loads & completion control logic -- Return data for loads & completion control logic
-- --
writeback_control: process(all) writeback_control: process(all)
@ -1367,12 +1366,6 @@ begin
r1.cache_paradox <= '0'; r1.cache_paradox <= '0';
end if; end if;


if req_op = OP_STCX_FAIL then
r1.stcx_fail <= '1';
else
r1.stcx_fail <= '0';
end if;

-- Record TLB hit information for updating TLB PLRU -- Record TLB hit information for updating TLB PLRU
r1.tlb_hit <= tlb_hit; r1.tlb_hit <= tlb_hit;
r1.tlb_hit_way <= tlb_hit_way; r1.tlb_hit_way <= tlb_hit_way;
@ -1423,6 +1416,8 @@ begin
r1.acks_pending <= to_unsigned(0, 3); r1.acks_pending <= to_unsigned(0, 3);
r1.stalled <= '0'; r1.stalled <= '0';
r1.dec_acks <= '0'; r1.dec_acks <= '0';
reservation.valid <= '0';
reservation.addr <= (others => '0');


-- Not useful normally but helps avoiding tons of sim warnings -- Not useful normally but helps avoiding tons of sim warnings
r1.wb.adr <= (others => '0'); r1.wb.adr <= (others => '0');
@ -1430,27 +1425,40 @@ begin
-- One cycle pulses reset -- One cycle pulses reset
r1.slow_valid <= '0'; r1.slow_valid <= '0';
r1.write_bram <= '0'; r1.write_bram <= '0';
r1.stcx_fail <= '0';


r1.ls_valid <= '0'; r1.ls_valid <= '0';
-- complete tlbies and TLB loads in the third cycle -- complete tlbies and TLB loads in the third cycle
r1.mmu_done <= r0_valid and (r0.tlbie or r0.tlbld); r1.mmu_done <= r0_valid and (r0.tlbie or r0.tlbld);
if req_op = OP_LOAD_HIT or req_op = OP_STCX_FAIL then if req_op = OP_LOAD_HIT then
if r0.mmu_req = '0' then if r0.mmu_req = '0' then
r1.ls_valid <= '1'; r1.ls_valid <= '1';
else else
r1.mmu_done <= '1'; r1.mmu_done <= '1';
end if; end if;
end if; end if;
-- The kill_rsrv2 term covers the case where the reservation
-- address was set at the beginning of this cycle, and a store
-- to that address happened in the previous cycle.
if kill_rsrv = '1' or kill_rsrv2 = '1' then
reservation.valid <= '0';
end if;
if req_go = '1' and access_ok = '1' and r0.req.load = '1' and
r0.req.reserve = '1' and r0.req.atomic_first = '1' then
reservation.addr <= ra(REAL_ADDR_BITS - 1 downto LINE_OFF_BITS);
if req_op = OP_LOAD_HIT then
reservation.valid <= not req_snoop_hit;
end if;
end if;


-- Do invalidations from snooped stores to memory -- Do invalidations from snooped stores to memory
if snoop_valid = '1' then if snoop_valid = '1' then
assert not is_X(snoop_tag_set); assert not is_X(snoop_paddr);
assert not is_X(snoop_wrtag); assert not is_X(snoop_hits);
end if; end if;
for i in 0 to NUM_WAYS-1 loop for i in 0 to NUM_WAYS-1 loop
if snoop_valid = '1' and read_tag(i, snoop_tag_set) = snoop_wrtag then if snoop_hits(i) = '1' then
assert not is_X(snoop_index); cache_valids(to_integer(get_index(snoop_paddr)))(i) <= '0';
cache_valids(to_integer(snoop_index))(i) <= '0';
end if; end if;
end loop; end loop;


@ -1477,6 +1485,9 @@ begin
req.valid := req_go; req.valid := req_go;
req.mmu_req := r0.mmu_req; req.mmu_req := r0.mmu_req;
req.dcbz := r0.req.dcbz; req.dcbz := r0.req.dcbz;
req.reserve := r0.req.reserve;
req.first_dw := r0.req.atomic_first;
req.last_dw := r0.req.atomic_last;
req.real_addr := ra; req.real_addr := ra;
-- Force data to 0 for dcbz -- Force data to 0 for dcbz
if r0.req.dcbz = '1' then if r0.req.dcbz = '1' then
@ -1581,7 +1592,11 @@ begin
r1.state <= NC_LOAD_WAIT_ACK; r1.state <= NC_LOAD_WAIT_ACK;


when OP_STORE_HIT | OP_STORE_MISS => when OP_STORE_HIT | OP_STORE_MISS =>
if req.dcbz = '0' then if req.reserve = '1' then
-- stcx needs to wait until next cycle
-- for the reservation address check
r1.state <= DO_STCX;
elsif req.dcbz = '0' then
r1.state <= STORE_WAIT_ACK; r1.state <= STORE_WAIT_ACK;
r1.full <= '0'; r1.full <= '0';
r1.slow_valid <= '1'; r1.slow_valid <= '1';
@ -1593,6 +1608,9 @@ begin
if req.op = OP_STORE_HIT then if req.op = OP_STORE_HIT then
r1.write_bram <= '1'; r1.write_bram <= '1';
end if; end if;
r1.wb.we <= '1';
r1.wb.cyc <= '1';
r1.wb.stb <= '1';
else else
-- dcbz is handled much like a load miss except -- dcbz is handled much like a load miss except
-- that we are writing to memory instead of reading -- that we are writing to memory instead of reading
@ -1600,19 +1618,18 @@ begin
if req.op = OP_STORE_MISS then if req.op = OP_STORE_MISS then
r1.write_tag <= '1'; r1.write_tag <= '1';
end if; end if;
r1.wb.we <= '1';
r1.wb.cyc <= '1';
r1.wb.stb <= '1';
end if; end if;
r1.wb.we <= '1';
r1.wb.cyc <= '1';
r1.wb.stb <= '1';
if req.op = OP_STORE_MISS then if req.op = OP_STORE_MISS then
ev.store_miss <= '1'; ev.store_miss <= '1';
end if; end if;


-- OP_NONE and OP_BAD do nothing -- OP_NONE and OP_BAD do nothing
-- OP_BAD & OP_STCX_FAIL were handled above already -- OP_BAD was handled above already
when OP_NONE => when OP_NONE =>
when OP_BAD => when OP_BAD =>
when OP_STCX_FAIL =>
end case; end case;


when RELOAD_WAIT_ACK => when RELOAD_WAIT_ACK =>
@ -1652,6 +1669,13 @@ begin
else else
r1.mmu_done <= '1'; r1.mmu_done <= '1';
end if; end if;
-- NB: for lqarx, set the reservation on the first
-- dword so that a snooped store between the two
-- dwords will kill the reservation.
if req.reserve = '1' and req.first_dw = '1' then
reservation.valid <= '1';
reservation.addr <= req.real_addr(REAL_ADDR_BITS - 1 downto LINE_OFF_BITS);
end if;
end if; end if;


-- Check for completion -- Check for completion
@ -1736,6 +1760,48 @@ begin
r1.wb.cyc <= '0'; r1.wb.cyc <= '0';
r1.wb.stb <= '0'; r1.wb.stb <= '0';
end if; end if;

when DO_STCX =>
if reservation.valid = '0' or kill_rsrv = '1' or
r1.req.real_addr(REAL_ADDR_BITS - 1 downto LINE_OFF_BITS) /= reservation.addr then
-- Wrong address, didn't have reservation, or lost reservation
-- Abandon the wishbone cycle if started and fail the stcx.
r1.stcx_fail <= '1';
r1.full <= '0';
r1.ls_valid <= '1';
r1.state <= IDLE;
r1.wb.cyc <= '0';
r1.wb.stb <= '0';
reservation.valid <= '0';
elsif r1.wb.cyc = '0' then
-- Right address and have reservation, so start the
-- wishbone cycle
r1.wb.we <= '1';
r1.wb.cyc <= '1';
r1.wb.stb <= '1';
else
if wishbone_in.stall = '0' then
-- Store has been accepted, so now we can write the
-- cache data RAM
if r1.req.op = OP_STORE_HIT then
r1.write_bram <= '1';
end if;
r1.wb.stb <= '0';
end if;
if wishbone_in.ack = '1' then
r1.state <= IDLE;
r1.wb.cyc <= '0';
r1.wb.stb <= '0';
r1.full <= '0';
r1.slow_valid <= '1';
r1.ls_valid <= '1';
-- For stqcx., kill the reservation on the last dword
if r1.req.last_dw = '1' then
reservation.valid <= '0';
end if;
end if;
end if;

end case; end case;
end if; end if;
end if; end if;

@ -85,6 +85,7 @@ architecture behave of loadstore1 is
xerc : xer_common_t; xerc : xer_common_t;
reserve : std_ulogic; reserve : std_ulogic;
atomic_qw : std_ulogic; atomic_qw : std_ulogic;
atomic_first : std_ulogic;
atomic_last : std_ulogic; atomic_last : std_ulogic;
rc : std_ulogic; rc : std_ulogic;
nc : std_ulogic; -- non-cacheable access nc : std_ulogic; -- non-cacheable access
@ -110,7 +111,7 @@ architecture behave of loadstore1 is
elt_length => x"0", byte_reverse => '0', brev_mask => "000", elt_length => x"0", byte_reverse => '0', brev_mask => "000",
sign_extend => '0', update => '0', sign_extend => '0', update => '0',
xerc => xerc_init, reserve => '0', xerc => xerc_init, reserve => '0',
atomic_qw => '0', atomic_last => '0', atomic_qw => '0', atomic_first => '0', atomic_last => '0',
rc => '0', nc => '0', rc => '0', nc => '0',
virt_mode => '0', priv_mode => '0', load_sp => '0', virt_mode => '0', priv_mode => '0', load_sp => '0',
sprsel => "00", ric => "00", is_slbia => '0', align_intr => '0', sprsel => "00", ric => "00", is_slbia => '0', align_intr => '0',
@ -478,20 +479,20 @@ begin


-- check alignment for larx/stcx -- check alignment for larx/stcx
misaligned := or (addr_mask and addr(2 downto 0)); misaligned := or (addr_mask and addr(2 downto 0));
if l_in.repeat = '1' and l_in.update = '0' and addr(3) /= l_in.second then
misaligned := '1';
end if;
v.align_intr := l_in.reserve and misaligned; v.align_intr := l_in.reserve and misaligned;


v.atomic_first := not misaligned and not l_in.second;
v.atomic_last := not misaligned and (l_in.second or not l_in.repeat);

-- is this a quadword load or store? i.e. lq plq stq pstq lqarx stqcx. -- is this a quadword load or store? i.e. lq plq stq pstq lqarx stqcx.
if l_in.repeat = '1' and l_in.update = '0' then if l_in.repeat = '1' and l_in.update = '0' then
-- is the access aligned? if misaligned = '0' then
if misaligned = '0' and addr(3) = l_in.second then
-- Since the access is aligned we have to do it atomically -- Since the access is aligned we have to do it atomically
v.atomic_qw := '1'; v.atomic_qw := '1';
v.atomic_last := l_in.second;
else else
-- lqarx/stqcx have to be aligned
if l_in.reserve = '1' then
v.align_intr := '1';
end if;
-- We require non-prefixed lq in LE mode to be aligned in order -- We require non-prefixed lq in LE mode to be aligned in order
-- to avoid the case where RA = RT+1 and the second access faults -- to avoid the case where RA = RT+1 and the second access faults
-- after the first has overwritten RA. -- after the first has overwritten RA.
@ -979,6 +980,7 @@ begin
d_out.nc <= stage1_req.nc; d_out.nc <= stage1_req.nc;
d_out.reserve <= stage1_req.reserve; d_out.reserve <= stage1_req.reserve;
d_out.atomic_qw <= stage1_req.atomic_qw; d_out.atomic_qw <= stage1_req.atomic_qw;
d_out.atomic_first <= stage1_req.atomic_first;
d_out.atomic_last <= stage1_req.atomic_last; d_out.atomic_last <= stage1_req.atomic_last;
d_out.addr <= stage1_req.addr; d_out.addr <= stage1_req.addr;
d_out.byte_sel <= stage1_req.byte_sel; d_out.byte_sel <= stage1_req.byte_sel;
@ -991,6 +993,7 @@ begin
d_out.nc <= r2.req.nc; d_out.nc <= r2.req.nc;
d_out.reserve <= r2.req.reserve; d_out.reserve <= r2.req.reserve;
d_out.atomic_qw <= r2.req.atomic_qw; d_out.atomic_qw <= r2.req.atomic_qw;
d_out.atomic_first <= r2.req.atomic_first;
d_out.atomic_last <= r2.req.atomic_last; d_out.atomic_last <= r2.req.atomic_last;
d_out.addr <= r2.req.addr; d_out.addr <= r2.req.addr;
d_out.byte_sel <= r2.req.byte_sel; d_out.byte_sel <= r2.req.byte_sel;

Loading…
Cancel
Save