Fix inverted sc return code (argh) and lr/sc tests which also assumed the sc code was inverted

This commit is contained in:
Luke Wren 2022-05-28 15:36:21 +01:00
parent 4090f4eb24
commit 66965ac073
4 changed files with 17 additions and 16 deletions

View File

@ -1036,7 +1036,8 @@ always @ (*) begin
m_result = bus_rdata_d; m_result = bus_rdata_d;
end else if (|EXTENSION_A && xm_memop == MEMOP_SC_W) begin 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. // 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 end else if (xm_memop != MEMOP_NONE && xm_memop != MEMOP_AMO) begin
m_result = m_rdata_pick_sext; m_result = m_rdata_pick_sext;
end else if (MUL_FAST && m_fast_mul_result_vld) begin end else if (MUL_FAST && m_fast_mul_result_vld) begin

View File

@ -7,9 +7,9 @@
/*EXPECTED-OUTPUT*************************************************************** /*EXPECTED-OUTPUT***************************************************************
lr -> mv: 12345678 lr -> mv: 12345678
lr -> sc: sc returned 1 lr -> sc: sc returned 0
scratch[1] = deadbeef scratch[1] = deadbeef
sc -> mv: sc returned 0 sc -> mv: sc returned 1
scratch[0] = 5678a5a5 scratch[0] = 5678a5a5
*******************************************************************************/ *******************************************************************************/

View File

@ -9,13 +9,13 @@
Failed load, suppressed store Failed load, suppressed store
-> exception, mcause = 5 -> exception, mcause = 5
exception instr: 100627af exception instr: 100627af
sc.w result: 0 sc.w result: 1
Good load, failed store Good load, failed store
-> exception, mcause = 7 -> exception, mcause = 7
exception instr: 18a5a52f exception instr: 18a5a52f
sc.w result: 123 sc.w result: 123
Repeated failed store Repeated failed store
sc.w result: 0 sc.w result: 1
*******************************************************************************/ *******************************************************************************/
@ -42,7 +42,7 @@ int main() {
// suppressing the sc.w. // suppressing the sc.w.
tb_puts("Failed load, suppressed store\n"); tb_puts("Failed load, suppressed store\n");
sc_result = do_lr_sc(123, bad_addr, bad_addr); 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); tb_printf("sc.w result: %u\n", sc_result);
// This time the sc.w should fault, after the successful lr.w. // This time the sc.w should fault, after the successful lr.w.
@ -58,7 +58,7 @@ int main() {
"sc.w %0, zero, (%1)\n" "sc.w %0, zero, (%1)\n"
: "+r" (sc_result) : "r" (bad_addr) : "+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); tb_printf("sc.w result: %u\n", sc_result);
return 0; return 0;

View File

@ -17,7 +17,7 @@ OK
volatile uint32_t scratch[2]; volatile uint32_t scratch[2];
int main() { int main() {
uint32_t load_result, success; uint32_t load_result, sc_fail;
tb_puts("Test 1: lr.w -> nop -> sc.w\n"); tb_puts("Test 1: lr.w -> nop -> sc.w\n");
scratch[0] = 0x1234; scratch[0] = 0x1234;
asm volatile ( asm volatile (
@ -26,12 +26,12 @@ int main() {
"sc.w %1, %3, (%2)\n" "sc.w %1, %3, (%2)\n"
// Note the "&": this marks an "earlyclobber" operand, telling GCC it can't // Note the "&": this marks an "earlyclobber" operand, telling GCC it can't
// allocate this output to an input register. (particularly, %0 to %2) // 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) : "r" (&scratch[0]), "r" (0x5678)
); );
tb_assert(load_result == 0x1234, "Bad load result %08x\n", load_result); 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(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("OK\n");
tb_puts("Test 2: lr.w -> sc.w\n"); tb_puts("Test 2: lr.w -> sc.w\n");
@ -39,23 +39,23 @@ int main() {
asm volatile ( asm volatile (
"lr.w %0, (%2)\n" "lr.w %0, (%2)\n"
"sc.w %1, %3, (%2)\n" "sc.w %1, %3, (%2)\n"
: "=&r" (load_result), "=r" (success) : "=&r" (load_result), "=r" (sc_fail)
: "r" (&scratch[0]), "r" (0xa5a5) : "r" (&scratch[0]), "r" (0xa5a5)
); );
tb_assert(load_result == 0xabcd, "Bad load result %08x\n", load_result); 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(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("OK\n");
tb_puts("Test 3: sc.w with no preceding lr.w\n"); tb_puts("Test 3: sc.w with no preceding lr.w\n");
scratch[0] = 0x1234; scratch[0] = 0x1234;
asm volatile ( asm volatile (
"sc.w %0, %2, (%1)\n" "sc.w %0, %2, (%1)\n"
: "=r" (success) : "=r" (sc_fail)
: "r" (&scratch[0]), "r" (0x5678) : "r" (&scratch[0]), "r" (0x5678)
); );
tb_assert(scratch[0] == 0x1234, "Store shouldn't write memory\n"); 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"); tb_puts("OK\n");
// Reservation is only cleared by other harts' stores. // Reservation is only cleared by other harts' stores.
@ -66,12 +66,12 @@ int main() {
"lr.w %0, (%2)\n" "lr.w %0, (%2)\n"
"sw %3, 4(%2)\n" "sw %3, 4(%2)\n"
"sc.w %1, %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) : "r" (&scratch[0]), "r" (0xabcd), "r" (0x5678)
); );
tb_assert(scratch[1] == 0xabcd, "Regular store should succeed\n"); tb_assert(scratch[1] == 0xabcd, "Regular store should succeed\n");
tb_assert(scratch[0] == 0x5678, "sc didn't write memory\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"); tb_puts("OK\n");
return 0; return 0;