Files
simulation_core/tests/unit-tests/riscv-lr-sc-instructions.robot

288 lines
14 KiB
Plaintext

*** Variables ***
${UART} sysbus.mmuart1
${URI} @https://dl.antmicro.com/projects/renode
${PLATFORM} @platforms/cpus/polarfire-soc.repl
${SHARED_VARIABLE_ADDRESS} 0x81000000
${VARIABLE_ADDRESS_CPU1} 0x81000000
${VARIABLE_ADDRESS_CPU2} 0x81000100
${LOOP_ITERATIONS} 100
${CORE_1_PC} 0x80000000
${CORE_2_PC} 0x80000100
${VARIABLE_VALUE} 0x5
${NEW_VARIABLE_VALUE} 0xbeeeeeef
# Registers used
${x0} 0
${a0} 10
${a1} 11
${a2} 12
${a3} 13
${a4} 14
# Repeatedly increments the value in (a0) until enough loop iterations have run.
${ASSEMBLY_LRSC_LOOP} SEPARATOR=
... repeat: lr.d a4, (a0);
... add a4, a4, a2;
... sc.d a4, a4, (a0);
... bnez a4, repeat;
... addi a1, a1, -1;
... bnez a1, repeat;
... j 0;
*** Keywords ***
Create Machine
Execute Command mach create
Execute Command machine LoadPlatformDescription ${PLATFORM}
Execute Command sysbus.u54_1 ExecutionMode SingleStep
Execute Command sysbus.u54_2 ExecutionMode SingleStep
Execute Command sysbus.u54_1 PC ${CORE_1_PC}
Execute Command sysbus.u54_2 PC ${CORE_2_PC}
Execute Command sysbus.u54_3 IsHalted true
Execute Command sysbus.u54_4 IsHalted true
Execute Command sysbus.e51 IsHalted true
Assemble Instruction
[Arguments] ${cpu} ${mnemonic} ${operands}= ${address}=0
${len}= Execute Command sysbus.${cpu} AssembleBlock ${address} "${mnemonic} ${operands}"
Create Reservations
# Just write 5 to memory, we'll use this to check for successful and failed writes
Execute Command sysbus WriteDoubleWord ${VARIABLE_ADDRESS_CPU1} ${VARIABLE_VALUE}
Execute Command sysbus WriteDoubleWord ${VARIABLE_ADDRESS_CPU2} ${VARIABLE_VALUE}
# Make a0 hold the memory address
# li a0, ${VARIABLE_ADDRESS_CPU1} (two instructions)
Assemble Instruction u54_1 li a0, ${VARIABLE_ADDRESS_CPU1} 0x80000000
Execute Command sysbus.u54_1 Step 2
Register Should Be Equal ${a0} ${VARIABLE_ADDRESS_CPU1} cpuName=u54_1
# li a0, ${VARIABLE_ADDRESS_CPU2} (three instructions)
Assemble Instruction u54_2 li a0, ${VARIABLE_ADDRESS_CPU2} 0x80000100
Execute Command sysbus.u54_2 Step 3
Register Should Be Equal ${a0} ${VARIABLE_ADDRESS_CPU2} cpuName=u54_2
# Create reservation on first core
Assemble Instruction u54_1 lr.d a1, (a0) 0x80000006
Execute Command sysbus.u54_1 Step
Register Should Be Equal ${a1} ${VARIABLE_VALUE} cpuName=u54_1
# Create reservation on second core
Assemble Instruction u54_2 lr.d a1, (a0) 0x8000010A
Execute Command sysbus.u54_2 Step
Register Should Be Equal ${a1} ${VARIABLE_VALUE} cpuName=u54_2
Contended Memory Value Should Increment To Correct Sum
[Arguments]
... ${assembly_loop_core_1}
... ${assembly_loop_core_2}
Create Machine
Execute Command sysbus.u54_1 ExecutionMode Continuous
Execute Command sysbus.u54_2 ExecutionMode Continuous
Execute Command logLevel 0
# Repeatedly increment a memory location from two cores
${shared_memory_counter}= Set Variable 0x80000600
${counter_start_value}= Set Variable 0
${increments_per_core}= Set Variable 10000000
${increment_step_size}= Set Variable 1
# Initialize shared memory counter.
Execute Command sysbus WriteQuadWord ${shared_memory_counter} ${counter_start_value}
# Set up registers for first core.
Execute Command u54_1 SetRegister ${a0} ${shared_memory_counter}
Execute Command u54_1 SetRegister ${a1} ${increments_per_core}
Execute Command u54_1 SetRegister ${a2} ${increment_step_size}
Execute Command u54_1 SetRegister ${a3} 0x1234
# Set up registers for second core.
Execute Command u54_2 SetRegister ${a0} ${shared_memory_counter}
Execute Command u54_2 SetRegister ${a1} ${increments_per_core}
Execute Command u54_2 SetRegister ${a2} ${increment_step_size}
Execute Command u54_2 SetRegister ${a3} 0x1234
# Place machine code at PC for both cores.
${assembly_size_1}= Execute Command u54_1 AssembleBlock ${CORE_1_PC} "${assembly_loop_core_1}"
${assembly_size_2}= Execute Command u54_2 AssembleBlock ${CORE_2_PC} "${assembly_loop_core_2}"
# Calculate end addresses.
# The -2 is for the 'j 0' and needs to be put at the start due to weird robot/python string conversion
${core_1_end_pc}= Evaluate -2 + ${CORE_1_PC} + ${assembly_size_1}
${core_2_end_pc}= Evaluate -2 + ${CORE_2_PC} + ${assembly_size_2}
# For detecting when loops are finished.
Create Log Tester 0
# Print when exiting loop.
Execute Command u54_1 AddHook ${core_1_end_pc} "self.InfoLog('u54_1 finished'); self.IsHalted = True"
Execute Command u54_2 AddHook ${core_2_end_pc} "self.InfoLog('u54_2 finished'); self.IsHalted = True"
# Wait for the loops to finish...
Wait For Log Entry u54_1 finished timeout=10 keep=true
Wait For Log Entry u54_2 finished timeout=10 keep=true
# In the end, the shared memory counter should've been incremented 2*increments_per_core times.
${counter_final_value}= Execute Command sysbus ReadQuadWord ${shared_memory_counter}
Should Be Equal As Integers ${counter_final_value} ${2 * ${increments_per_core}} "Counter should now have been incremented to ${2 * ${increments_per_core}} but it contains ${counter_final_value}"
*** Test Cases ***
Should Handle Multiple Writes To Same Reservation
Create Machine
Create Reservations
# Try to update memory address with number 6
# This will check if simple LR/SC behaves correctly
Assemble Instruction u54_1 li a2, 0x6 0x8000000A
Execute Command sysbus.u54_1 Step
Register Should Be Equal ${a2} 0x6 cpuName=u54_1
# Check for successful SC
Assemble Instruction u54_1 sc.d a3, a2, (a0) 0x8000000C
Execute Command sysbus.u54_1 Step
Register Should Be Equal ${a3} 0x0 cpuName=u54_1
${res}= Execute Command sysbus ReadDoubleWord ${VARIABLE_ADDRESS_CPU1}
Should Be Equal As Integers ${res} 6
# Try to SC on something that isn't reserved - this should fail (returns 1)
Assemble Instruction u54_1 sc.d a3, zero, (a0) 0x80000010
Execute Command sysbus.u54_1 Step
# Check if SC failed (correct behavior)
Register Should Be Equal ${a3} 0x1 cpuName=u54_1
${res}= Execute Command sysbus ReadDoubleWord ${VARIABLE_ADDRESS_CPU1}
Should Be Equal As Integers ${res} 0x00000006
Should Work On Multiple Cores
Create Machine
Create Reservations
# Having reservations on two cores, we try to store on both of them
Assemble Instruction u54_1 li a2, 0x6 0x8000000A
Execute Command sysbus.u54_1 Step
Register Should Be Equal ${a2} 0x6 cpuName=u54_1
Assemble Instruction u54_2 li a2, 0x7 0x8000010E
Execute Command sysbus.u54_2 Step
Register Should Be Equal ${a2} 0x7 cpuName=u54_2
# Check for successful store on second core
Assemble Instruction u54_2 sc.d a3, a2, (a0) 0x80000110
Execute Command sysbus.u54_2 Step
Register Should Be Equal ${a3} 0x0 cpuName=u54_2
# Check for successful store on first core
Assemble Instruction u54_1 sc.d a3, a2, (a0) 0x8000000C
Execute Command sysbus.u54_1 Step
Register Should Be Equal ${a3} 0x0 cpuName=u54_1
Should Drop Other Core Reservation On SC
Create Machine
Create Reservations
# Check if SC on other core's LR will drop the reservation
Assemble Instruction u54_1 li a2, 0x6 0x8000000A
Execute Command sysbus.u54_1 Step
Register Should Be Equal ${a2} 0x6 cpuName=u54_1
# Get the address of second core's reservation to first core's a0
Assemble Instruction u54_1 li a0, ${VARIABLE_ADDRESS_CPU2} 0x8000000C
Execute Command sysbus.u54_1 Step 3
Register Should Be Equal ${a0} ${VARIABLE_ADDRESS_CPU2} cpuName=u54_1
# Try to store on second core's reservation
Assemble Instruction u54_1 sc.d a3, a2, (a0) 0x80000016
Execute Command sysbus.u54_1 Step
Register Should Be Equal ${a3} 0x1 cpuName=u54_1
# Try to store on second core's reservation by second core
Assemble Instruction u54_2 sc.d a3, a2, (a0) 0x80000110
Execute Command sysbus.u54_2 Step
Register Should Be Equal ${a3} 0x0 cpuName=u54_2
Should Handle Looping LR/SC Pairs To Same Reservation
Create Machine
${start_value}= Set Variable 0
Execute Command sysbus WriteDoubleWord ${VARIABLE_ADDRESS_CPU1} ${start_value}
# Repeatedly increment a memory location on one core
# The assembly instructions to execute in this test.
# It repeatedly increments the value in (a0) until enough loop iterations have run.
${ASSEMBLY_LRSC_LOOP}= catenate SEPARATOR=
... repeat: lr.w a4, (a0);
... addi a4, a4, 1;
... sc.w a4, a4, (a0);
... bnez a4, repeat;
... addi a1, a1, -1;
... bnez a1, repeat;
... j 0;
# Set up registers
Execute Command u54_1 SetRegister ${a0} ${VARIABLE_ADDRESS_CPU1}
Execute Command u54_1 SetRegister ${a1} ${LOOP_ITERATIONS}
# Place machine code at PC.
Execute Command sysbus.u54_1 AssembleBlock 0x80000000 "${ASSEMBLY_LRSC_LOOP}"
FOR ${i} IN RANGE ${start_value} ${LOOP_ITERATIONS}
${next_i}= Set Variable ${${i} + 1}
# Execute lr.w, which should give the memory counter value
Execute Command sysbus.u54_1 Step
Register Should Be Equal ${a4} ${i} cpuName=u54_1
# Execute addi, which should increment the counter value
Execute Command sysbus.u54_1 Step
Register Should Be Equal ${a4} ${next_i} cpuName=u54_1
# Execute sc.w, which should succeed in storing the incremented value to memory
Execute Command sysbus.u54_1 Step
Register Should Be Equal ${a4} 0 cpuName=u54_1
${res}= Execute Command sysbus ReadDoubleWord ${VARIABLE_ADDRESS_CPU1}
Should Be Equal As Integers ${res} ${next_i} "Memory location should now contain ${next_i} but it contains ${res}"
# bnez shouldn't need to jump to repeat, just step over it.
Execute Command sysbus.u54_1 Step
# Check for successful decrement of loop counter
Execute Command sysbus.u54_1 Step
Register Should Be Equal ${a1} ${${LOOP_ITERATIONS} - ${next_i}} cpuName=u54_1
# jump back to start of next loop (if not at final iteration)
Execute Command sysbus.u54_1 Step
END
# In the end, it should've been incremented LOOP_ITERATIONS times.
Register Should Be Equal ${a1} 0 cpuName=u54_1
${res}= Execute Command sysbus ReadDoubleWord ${VARIABLE_ADDRESS_CPU1}
Should Be Equal As Integers ${res} ${LOOP_ITERATIONS} "Memory location should now have been incremented to ${LOOP_ITERATIONS} but it contains ${res}"
Two LR/SC Loops Should Increment To Correct Sum
Contended Memory Value Should Increment To Correct Sum
... assembly_loop_core_1=${ASSEMBLY_LRSC_LOOP}
... assembly_loop_core_2=${ASSEMBLY_LRSC_LOOP}
LR/SC And Amoadd Loops Should Increment To Correct Sum
${ASSEMBLY_AMOADD_LOOP}= catenate SEPARATOR=
... repeat: amoadd.d x0, a2, (a0);
... addi a1, a1, -1;
... bnez a1, repeat;
... j 0;
Contended Memory Value Should Increment To Correct Sum
... assembly_loop_core_1=${ASSEMBLY_AMOADD_LOOP}
... assembly_loop_core_2=${ASSEMBLY_LRSC_LOOP}