diff --git a/hdl/hazard3_core.v b/hdl/hazard3_core.v index 2b92b66..48cdf56 100644 --- a/hdl/hazard3_core.v +++ b/hdl/hazard3_core.v @@ -1036,7 +1036,8 @@ always @ (*) begin m_result = bus_rdata_d; end else if (|EXTENSION_A && xm_memop == MEMOP_SC_W) begin // sc.w may fail due to negative response from either local or global monitor. - m_result = {31'h0, mw_local_exclusive_reserved && bus_dph_exokay_d}; + // Note the polarity of the result: 0 for success, 1 for failure. + m_result = {31'h0, !(mw_local_exclusive_reserved && bus_dph_exokay_d)}; end else if (xm_memop != MEMOP_NONE && xm_memop != MEMOP_AMO) begin m_result = m_rdata_pick_sext; end else if (MUL_FAST && m_fast_mul_result_vld) begin diff --git a/test/sim/sw_testcases/lr_sc_bypass.c b/test/sim/sw_testcases/lr_sc_bypass.c index 5123dd7..fd5a12c 100644 --- a/test/sim/sw_testcases/lr_sc_bypass.c +++ b/test/sim/sw_testcases/lr_sc_bypass.c @@ -7,9 +7,9 @@ /*EXPECTED-OUTPUT*************************************************************** lr -> mv: 12345678 -lr -> sc: sc returned 1 +lr -> sc: sc returned 0 scratch[1] = deadbeef -sc -> mv: sc returned 0 +sc -> mv: sc returned 1 scratch[0] = 5678a5a5 *******************************************************************************/ diff --git a/test/sim/sw_testcases/lr_sc_fault.c b/test/sim/sw_testcases/lr_sc_fault.c index e547fbb..5623486 100644 --- a/test/sim/sw_testcases/lr_sc_fault.c +++ b/test/sim/sw_testcases/lr_sc_fault.c @@ -9,13 +9,13 @@ Failed load, suppressed store -> exception, mcause = 5 exception instr: 100627af -sc.w result: 0 +sc.w result: 1 Good load, failed store -> exception, mcause = 7 exception instr: 18a5a52f sc.w result: 123 Repeated failed store -sc.w result: 0 +sc.w result: 1 *******************************************************************************/ @@ -42,7 +42,7 @@ int main() { // suppressing the sc.w. tb_puts("Failed load, suppressed store\n"); sc_result = do_lr_sc(123, bad_addr, bad_addr); - // Failing sc.w must write 0 to the success register. + // Failing sc.w must write 1 to the success register. tb_printf("sc.w result: %u\n", sc_result); // This time the sc.w should fault, after the successful lr.w. @@ -58,7 +58,7 @@ int main() { "sc.w %0, zero, (%1)\n" : "+r" (sc_result) : "r" (bad_addr) ); - // Failing sc.w must write 0 to result register. + // Failing sc.w must write 1 to result register. tb_printf("sc.w result: %u\n", sc_result); return 0; diff --git a/test/sim/sw_testcases/lr_sc_smoke.c b/test/sim/sw_testcases/lr_sc_smoke.c index b194039..b280240 100644 --- a/test/sim/sw_testcases/lr_sc_smoke.c +++ b/test/sim/sw_testcases/lr_sc_smoke.c @@ -17,7 +17,7 @@ OK volatile uint32_t scratch[2]; int main() { - uint32_t load_result, success; + uint32_t load_result, sc_fail; tb_puts("Test 1: lr.w -> nop -> sc.w\n"); scratch[0] = 0x1234; asm volatile ( @@ -26,12 +26,12 @@ int main() { "sc.w %1, %3, (%2)\n" // Note the "&": this marks an "earlyclobber" operand, telling GCC it can't // allocate this output to an input register. (particularly, %0 to %2) - : "=&r" (load_result), "=r" (success) + : "=&r" (load_result), "=r" (sc_fail) : "r" (&scratch[0]), "r" (0x5678) ); tb_assert(load_result == 0x1234, "Bad load result %08x\n", load_result); tb_assert(scratch[0] == 0x5678, "Store didn't write memory\n"); - tb_assert(success == 1, "Should report success\n"); + tb_assert(sc_fail == 0, "Should report success\n"); tb_puts("OK\n"); tb_puts("Test 2: lr.w -> sc.w\n"); @@ -39,23 +39,23 @@ int main() { asm volatile ( "lr.w %0, (%2)\n" "sc.w %1, %3, (%2)\n" - : "=&r" (load_result), "=r" (success) + : "=&r" (load_result), "=r" (sc_fail) : "r" (&scratch[0]), "r" (0xa5a5) ); tb_assert(load_result == 0xabcd, "Bad load result %08x\n", load_result); tb_assert(scratch[0] == 0xa5a5, "Store didn't write memory\n"); - tb_assert(success == 1, "Should report success\n"); + tb_assert(sc_fail == 0, "Should report success\n"); tb_puts("OK\n"); tb_puts("Test 3: sc.w with no preceding lr.w\n"); scratch[0] = 0x1234; asm volatile ( "sc.w %0, %2, (%1)\n" - : "=r" (success) + : "=r" (sc_fail) : "r" (&scratch[0]), "r" (0x5678) ); tb_assert(scratch[0] == 0x1234, "Store shouldn't write memory\n"); - tb_assert(success == 0, "Should report failure\n"); + tb_assert(sc_fail == 1, "Should report failure\n"); tb_puts("OK\n"); // Reservation is only cleared by other harts' stores. @@ -66,12 +66,12 @@ int main() { "lr.w %0, (%2)\n" "sw %3, 4(%2)\n" "sc.w %1, %4, (%2)\n" - : "=&r" (load_result), "=r" (success) + : "=&r" (load_result), "=r" (sc_fail) : "r" (&scratch[0]), "r" (0xabcd), "r" (0x5678) ); tb_assert(scratch[1] == 0xabcd, "Regular store should succeed\n"); tb_assert(scratch[0] == 0x5678, "sc didn't write memory\n"); - tb_assert(success == 1, "Should report success\n"); + tb_assert(sc_fail == 0, "Should report success\n"); tb_puts("OK\n"); return 0;