*** 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}