diff --git a/common.vhdl b/common.vhdl index b1a2c8e..425bb79 100644 --- a/common.vhdl +++ b/common.vhdl @@ -626,6 +626,7 @@ package common is store_done : std_ulogic; error : std_ulogic; cache_paradox : std_ulogic; + reserve_nc : std_ulogic; end record; type DcacheEventType is record diff --git a/dcache.vhdl b/dcache.vhdl index 1a1087c..5eb659d 100644 --- a/dcache.vhdl +++ b/dcache.vhdl @@ -353,6 +353,7 @@ architecture rtl of dcache is mmu_done : std_ulogic; mmu_error : std_ulogic; cache_paradox : std_ulogic; + reserve_nc : std_ulogic; -- Signal to complete a failed stcx. stcx_fail : std_ulogic; @@ -1125,7 +1126,7 @@ begin else req_op_flush <= '1'; end if; - elsif nc = '1' and is_hit = '1' then + elsif nc = '1' and (is_hit = '1' or r0.req.reserve = '1') then req_op_bad <= '1'; elsif r0.req.load = '0' then req_op_store <= '1'; -- includes dcbz @@ -1167,6 +1168,7 @@ begin d_out.store_done <= not r1.stcx_fail; d_out.error <= r1.ls_error; d_out.cache_paradox <= r1.cache_paradox; + d_out.reserve_nc <= r1.reserve_nc; -- Outputs to MMU m_out.done <= r1.mmu_done; @@ -1354,16 +1356,16 @@ begin r1.hit_load_valid <= req_op_load_hit; r1.cache_hit <= req_op_load_hit or (req_op_store and req_is_hit); -- causes PLRU update + r1.cache_paradox <= access_ok and req_nc and req_is_hit; + r1.reserve_nc <= access_ok and r0.req.reserve and req_nc; if req_op_bad = '1' then report "Signalling ld/st error valid_ra=" & std_ulogic'image(valid_ra) & " rc_ok=" & std_ulogic'image(rc_ok) & " perm_ok=" & std_ulogic'image(perm_ok); r1.ls_error <= not r0.mmu_req; r1.mmu_error <= r0.mmu_req; - r1.cache_paradox <= access_ok; else r1.ls_error <= '0'; r1.mmu_error <= '0'; - r1.cache_paradox <= '0'; end if; -- Record TLB hit information for updating TLB PLRU diff --git a/loadstore1.vhdl b/loadstore1.vhdl index 69d053d..5e69352 100644 --- a/loadstore1.vhdl +++ b/loadstore1.vhdl @@ -738,7 +738,8 @@ begin end if; interrupt := (r2.req.valid and r2.req.align_intr) or - (d_in.error and d_in.cache_paradox) or m_in.err; + (d_in.error and (d_in.cache_paradox or d_in.reserve_nc)) or + m_in.err; if interrupt = '1' then v.req.valid := '0'; v.busy := '0'; @@ -905,6 +906,7 @@ begin -- signal an interrupt straight away exception := '1'; dsisr(63 - 38) := not r2.req.load; + dsisr(63 - 37) := d_in.reserve_nc; -- XXX there is no architected bit for this -- (probably should be a machine check in fact) dsisr(63 - 35) := d_in.cache_paradox;