仿真平台内核初版 -tlib库 包含<sparc arm riscv powerPC>
This commit is contained in:
477
tests/unit-tests/riscv-unit-tests.robot
Normal file
477
tests/unit-tests/riscv-unit-tests.robot
Normal file
@@ -0,0 +1,477 @@
|
||||
*** Variables ***
|
||||
# RISC-V registers
|
||||
${a1} 0xb
|
||||
${starting_pc} 0x2000
|
||||
${next_instruction} 0x2004
|
||||
${mtvec} 0x1010
|
||||
${illegal_instruction} 0x2
|
||||
${load_misaligned} 0x4
|
||||
${store_misaligned} 0x6
|
||||
${register_0} 0x0
|
||||
${illegal_opcode} 0x00008000
|
||||
${illegal_csr} 0xf120d073
|
||||
${nonexisting_csr} 0xfff0d073
|
||||
${divide_by_zero_flag} ${{ 1 << 3 }}
|
||||
|
||||
*** Keywords ***
|
||||
Create Machine
|
||||
[Arguments] ${bitness} ${init_pc}
|
||||
Execute Command using sysbus
|
||||
Execute Command mach create "risc-v"
|
||||
|
||||
Execute Command machine LoadPlatformDescriptionFromString "clint: IRQControllers.CoreLevelInterruptor @ sysbus 0x44000000 { frequency: 66000000 }"
|
||||
Execute Command machine LoadPlatformDescriptionFromString "cpu: CPU.RiscV${bitness} @ sysbus { timeProvider: clint; cpuType: \\"rv${bitness}gc_Zfh\\" }"
|
||||
Execute Command machine LoadPlatformDescriptionFromString "mem: Memory.MappedMemory @ sysbus 0x1000 { size: 0x40000 }"
|
||||
|
||||
IF ${init_pc}
|
||||
Execute Command cpu PC ${starting_pc}
|
||||
END
|
||||
|
||||
Create Machine 32
|
||||
Create Machine bitness=32 init_pc=True
|
||||
|
||||
Create Machine 64
|
||||
Create Machine bitness=64 init_pc=True
|
||||
|
||||
Write Opcode To
|
||||
[Arguments] ${adress} ${opcode}
|
||||
Execute Command sysbus WriteDoubleWord ${adress} ${opcode}
|
||||
|
||||
Load Program With Invalid Instruction
|
||||
[Arguments] ${address}
|
||||
${addi_opcode} Set Variable 0x00050593 #addi x11 x10 0
|
||||
${vector_opcode} Set Variable 0x00000057 #vadd.vv v0, v0, v0, v0.t
|
||||
${fvf_vector_opcode} Set Variable 0x00005057 #vfadd.vf v0, v0, ft0, v0.t
|
||||
${start_pc}= Convert To Integer ${address}
|
||||
|
||||
# Depending on the fact if vector extension is enabled or not, the program will cause
|
||||
# invalid instruction exception at ${vector_opcode} or ${fvf_vector_opcode}.
|
||||
Write Opcode To ${start_pc} ${addi_opcode} #addi x11 x10 0
|
||||
Write Opcode To ${start_pc+4} ${addi_opcode} #addi x11 x10 0
|
||||
Write Opcode To ${start_pc+8} ${vector_opcode} #vadd.vv v0, v0, v0, v0.t
|
||||
Write Opcode To ${start_pc+12} ${addi_opcode} #addi x11 x10 0
|
||||
Write Opcode To ${start_pc+16} ${addi_opcode} #addi x11 x10 0
|
||||
Write Opcode To ${start_pc+20} ${addi_opcode} #addi x11 x10 0
|
||||
Write Opcode To ${start_pc+24} ${fvf_vector_opcode} #vfadd.vf v0, v0, ft0, v0.t
|
||||
Write Opcode To ${start_pc+28} ${addi_opcode} #addi x11 x10 0
|
||||
Write Opcode To ${start_pc+32} ${vector_opcode} #vadd.vv v0, v0, v0, v0.t
|
||||
Write Opcode To ${start_pc+36} ${addi_opcode} #addi x11 x10 0
|
||||
|
||||
Set ResetVector And Verify PC
|
||||
[Arguments] ${reset_vector} ${should_set_pc}
|
||||
IF ${should_set_pc}
|
||||
${expected_pc}= Set Variable ${reset_vector}
|
||||
ELSE
|
||||
${expected_pc}= Execute Command cpu PC
|
||||
END
|
||||
Execute Command cpu ResetVector ${reset_vector}
|
||||
Verify PC ${expected_pc}
|
||||
|
||||
Should Properly Handle ResetVector
|
||||
# Setting ResetVector before setting PC directly, with LoadELF etc. should propagate to PC.
|
||||
Set ResetVector And Verify PC 0x1234 should_set_pc=True
|
||||
Set ResetVector And Verify PC 0x1238 should_set_pc=True
|
||||
|
||||
# Setting PC other than as an effect of ResetVector should stop the propagation.
|
||||
${new_reset_vector_value}= Set Variable 0x123C
|
||||
Execute Command cpu PC 0x5678
|
||||
Set ResetVector And Verify PC ${new_reset_vector_value} should_set_pc=False
|
||||
|
||||
# Reset should set PC to ResetVector and restore PC propagation on ResetVector.
|
||||
Execute Command cpu Reset
|
||||
Verify PC ${new_reset_vector_value}
|
||||
Set ResetVector And Verify PC 0x1240 should_set_pc=True
|
||||
|
||||
Should Properly Handle ResetVector At Init And After Reset
|
||||
Verify PC 0x1000 # Default ResetVector
|
||||
Should Properly Handle ResetVector
|
||||
|
||||
${new_reset_vector_value}= Set Variable 0x2468
|
||||
Execute Command cpu ResetVector ${new_reset_vector_value}
|
||||
Execute Command cpu Reset
|
||||
Verify PC ${new_reset_vector_value}
|
||||
Should Properly Handle ResetVector
|
||||
|
||||
Verify PC
|
||||
[Arguments] ${expected_pc}
|
||||
${pc}= Execute Command cpu PC
|
||||
Should Be Equal As Integers ${pc} ${expected_pc}
|
||||
|
||||
*** Test Cases ***
|
||||
Should Handle LB
|
||||
Create Machine 32
|
||||
|
||||
Execute Command cpu SetRegister ${a1} 0x00000000
|
||||
|
||||
# lb a0, 0x00000005(a1)
|
||||
Execute Command sysbus WriteDoubleWord ${starting_pc} 0x00558503
|
||||
|
||||
Execute Command cpu Step
|
||||
|
||||
${pc}= Execute Command cpu PC
|
||||
Should Be Equal As Numbers ${pc} ${next_instruction}
|
||||
|
||||
Should Handle LH
|
||||
Create Machine 32
|
||||
|
||||
Execute Command cpu SetRegister ${a1} 0x00000001
|
||||
|
||||
# lh a0, 0x00000005(a1)
|
||||
Execute Command sysbus WriteDoubleWord ${starting_pc} 0x00559503
|
||||
|
||||
Execute Command cpu Step
|
||||
|
||||
${pc}= Execute Command cpu PC
|
||||
Should Be Equal As Numbers ${pc} ${next_instruction}
|
||||
|
||||
Should Fail LH
|
||||
Create Machine 32
|
||||
|
||||
Execute Command cpu SetRegister ${a1} 0x00000000
|
||||
|
||||
# lh a0, 0x00000005(a1)
|
||||
Execute Command sysbus WriteDoubleWord ${starting_pc} 0x00559503
|
||||
|
||||
Execute Command cpu Step
|
||||
|
||||
${pc}= Execute Command cpu PC
|
||||
Should Be Equal As Numbers ${pc} ${mtvec}
|
||||
|
||||
${mcause}= Execute Command cpu MCAUSE
|
||||
Should Be Equal As Numbers ${mcause} ${load_misaligned}
|
||||
|
||||
Should Handle LW
|
||||
Create Machine 32
|
||||
|
||||
Execute Command cpu SetRegister ${a1} 0x00000003
|
||||
|
||||
# lw a0, 0x00000005(a1)
|
||||
Execute Command sysbus WriteDoubleWord ${starting_pc} 0x0055a503
|
||||
|
||||
Execute Command cpu Step
|
||||
|
||||
${pc}= Execute Command cpu PC
|
||||
Should Be Equal As Numbers ${pc} ${next_instruction}
|
||||
|
||||
Should Fail LW
|
||||
Create Machine 32
|
||||
|
||||
Execute Command cpu SetRegister ${a1} 0x00000000
|
||||
|
||||
# lw a0, 0x00000005(a1)
|
||||
Execute Command sysbus WriteDoubleWord ${starting_pc} 0x0055a503
|
||||
|
||||
Execute Command cpu Step
|
||||
|
||||
${pc}= Execute Command cpu PC
|
||||
Should Be Equal As Numbers ${pc} ${mtvec}
|
||||
|
||||
${mcause}= Execute Command cpu MCAUSE
|
||||
Should Be Equal As Numbers ${mcause} ${load_misaligned}
|
||||
|
||||
Should Handle LD
|
||||
Create Machine 64
|
||||
|
||||
Execute Command cpu SetRegister ${a1} 0x00000003
|
||||
|
||||
# ld a0, 0x00000005(a1)
|
||||
Execute Command sysbus WriteDoubleWord ${starting_pc} 0x0055b503
|
||||
|
||||
Execute Command cpu Step
|
||||
|
||||
${pc}= Execute Command cpu PC
|
||||
Should Be Equal As Numbers ${pc} ${next_instruction}
|
||||
|
||||
Should Fail LD
|
||||
Create Machine 64
|
||||
|
||||
Execute Command cpu SetRegister ${a1} 0x00000000
|
||||
|
||||
# ld a0, 0x00000005(a1)
|
||||
Execute Command sysbus WriteDoubleWord ${starting_pc} 0x0055b503
|
||||
|
||||
Execute Command cpu Step
|
||||
|
||||
${pc}= Execute Command cpu PC
|
||||
Should Be Equal As Numbers ${pc} ${mtvec}
|
||||
|
||||
${mcause}= Execute Command cpu MCAUSE
|
||||
Should Be Equal As Numbers ${mcause} ${load_misaligned}
|
||||
|
||||
Should Handle SB
|
||||
Create Machine 32
|
||||
|
||||
Execute Command cpu SetRegister ${a1} 0x00000000
|
||||
|
||||
# sb a0, 0x00000005(a1)
|
||||
Execute Command sysbus WriteDoubleWord ${starting_pc} 0x00a582a3
|
||||
|
||||
Execute Command cpu Step
|
||||
|
||||
${pc}= Execute Command cpu PC
|
||||
Should Be Equal As Numbers ${pc} ${next_instruction}
|
||||
|
||||
Should Handle SH
|
||||
Create Machine 32
|
||||
|
||||
Execute Command cpu SetRegister ${a1} 0x00000001
|
||||
|
||||
# sh a0, 0x00000005(a1)
|
||||
Execute Command sysbus WriteDoubleWord ${starting_pc} 0x00a592a3
|
||||
|
||||
Execute Command cpu Step
|
||||
|
||||
${pc}= Execute Command cpu PC
|
||||
Should Be Equal As Numbers ${pc} ${next_instruction}
|
||||
|
||||
Should Fail SH
|
||||
Create Machine 32
|
||||
|
||||
Execute Command cpu SetRegister ${a1} 0x00000000
|
||||
|
||||
# sh a0, 0x00000005(a1)
|
||||
Execute Command sysbus WriteDoubleWord ${starting_pc} 0x00a592a3
|
||||
|
||||
Execute Command cpu Step
|
||||
|
||||
${pc}= Execute Command cpu PC
|
||||
Should Be Equal As Numbers ${pc} ${mtvec}
|
||||
|
||||
${mcause}= Execute Command cpu MCAUSE
|
||||
Should Be Equal As Numbers ${mcause} ${store_misaligned}
|
||||
|
||||
Should Handle SW
|
||||
Create Machine 32
|
||||
|
||||
Execute Command cpu SetRegister ${a1} 0x00000003
|
||||
|
||||
# sw a0, 0x00000005(a1)
|
||||
Execute Command sysbus WriteDoubleWord ${starting_pc} 0x00a5a2a3
|
||||
|
||||
Execute Command cpu Step
|
||||
|
||||
${pc}= Execute Command cpu PC
|
||||
Should Be Equal As Numbers ${pc} ${next_instruction}
|
||||
|
||||
Should Fail SW
|
||||
Create Machine 32
|
||||
|
||||
Execute Command cpu SetRegister ${a1} 0x00000000
|
||||
|
||||
# sw a0, 0x00000005(a1)
|
||||
Execute Command sysbus WriteDoubleWord ${starting_pc} 0x00a5a2a3
|
||||
|
||||
Execute Command cpu Step
|
||||
|
||||
${pc}= Execute Command cpu PC
|
||||
Should Be Equal As Numbers ${pc} ${mtvec}
|
||||
|
||||
${mcause}= Execute Command cpu MCAUSE
|
||||
Should Be Equal As Numbers ${mcause} ${store_misaligned}
|
||||
|
||||
Should Handle SD
|
||||
Create Machine 64
|
||||
|
||||
Execute Command cpu SetRegister ${a1} 0x00000003
|
||||
|
||||
# sd a0, 0x00000005(a1)
|
||||
Execute Command sysbus WriteDoubleWord ${starting_pc} 0x00a5b2a3
|
||||
|
||||
Execute Command cpu Step
|
||||
|
||||
${pc}= Execute Command cpu PC
|
||||
Should Be Equal As Numbers ${pc} ${next_instruction}
|
||||
|
||||
Should Fail SD
|
||||
Create Machine 64
|
||||
|
||||
Execute Command cpu SetRegister ${a1} 0x00000001
|
||||
|
||||
# sd a0, 0x00000005(a1)
|
||||
Execute Command sysbus WriteDoubleWord ${starting_pc} 0x00a5b2a3
|
||||
|
||||
Execute Command cpu Step
|
||||
|
||||
${pc}= Execute Command cpu PC
|
||||
Should Be Equal As Numbers ${pc} ${mtvec}
|
||||
|
||||
${mcause}= Execute Command cpu MCAUSE
|
||||
Should Be Equal As Numbers ${mcause} ${store_misaligned}
|
||||
|
||||
Should Fail On Setting X0 register
|
||||
Create Machine 32
|
||||
|
||||
${msg}= Run Keyword And Expect Error * Execute Command cpu SetRegister ${register_0} 0x00000001
|
||||
Should Contain ${msg} register is read-only
|
||||
|
||||
Register Should Be Equal 0 0x0
|
||||
|
||||
Should Set MEPC on Illegal Instruction
|
||||
Create Machine 32
|
||||
|
||||
# j .
|
||||
Execute Command sysbus WriteDoubleWord 0x1010 0x0000006f
|
||||
|
||||
# j 0x4000
|
||||
Execute Command sysbus WriteDoubleWord ${starting_pc} 0x0000206f
|
||||
# nop
|
||||
Execute Command sysbus WriteDoubleWord 0x4000 0x00000013
|
||||
# ILLEGAL INSTRUCTION
|
||||
Execute Command sysbus WriteDoubleWord 0x4004 ${illegal_opcode}
|
||||
|
||||
Execute Command cpu Step 3
|
||||
|
||||
PC Should Be Equal 0x1010
|
||||
|
||||
${mcause}= Execute Command cpu MCAUSE
|
||||
Should Be Equal As Numbers ${mcause} ${illegal_instruction}
|
||||
${mtval}= Execute Command cpu MTVAL
|
||||
Should Be Equal As Numbers ${mtval} ${illegal_opcode}
|
||||
${mepc}= Execute Command cpu MEPC
|
||||
Should Be Equal As Numbers ${mepc} 0x4004
|
||||
|
||||
Should Set MEPC on Illegal CSR access
|
||||
Create Machine 32
|
||||
Execute Command cpu CSRValidation Full
|
||||
|
||||
# j .
|
||||
Execute Command sysbus WriteDoubleWord 0x1010 0x0000006f
|
||||
|
||||
# j 0x4000
|
||||
Execute Command sysbus WriteDoubleWord ${starting_pc} 0x0000206f
|
||||
# nop
|
||||
Execute Command sysbus WriteDoubleWord 0x4000 0x00000013
|
||||
# csrwi marchid, 1 - this is an illegal CSR operation as `marchid` is read-only
|
||||
Execute Command sysbus WriteDoubleWord 0x4004 ${illegal_csr}
|
||||
|
||||
Execute Command cpu Step 3
|
||||
|
||||
PC Should Be Equal 0x1010
|
||||
|
||||
${mcause}= Execute Command cpu MCAUSE
|
||||
Should Be Equal As Numbers ${mcause} ${illegal_instruction}
|
||||
${mtval}= Execute Command cpu MTVAL
|
||||
Should Be Equal As Numbers ${mtval} ${illegal_csr}
|
||||
${mepc}= Execute Command cpu MEPC
|
||||
Should Be Equal As Numbers ${mepc} 0x4004
|
||||
|
||||
Should Set MEPC on Non-Existing CSR access
|
||||
Create Machine 32
|
||||
|
||||
# j .
|
||||
Execute Command sysbus WriteDoubleWord 0x1010 0x0000006f
|
||||
|
||||
# j 0x4000
|
||||
Execute Command sysbus WriteDoubleWord ${starting_pc} 0x0000206f
|
||||
# nop
|
||||
Execute Command sysbus WriteDoubleWord 0x4000 0x00000013
|
||||
# csrwi marchid, 1 - this is an illegal CSR operation as `marchid` is read-only
|
||||
Execute Command sysbus WriteDoubleWord 0x4004 ${nonexisting_csr}
|
||||
|
||||
Execute Command cpu Step 3
|
||||
|
||||
PC Should Be Equal 0x1010
|
||||
|
||||
${mcause}= Execute Command cpu MCAUSE
|
||||
Should Be Equal As Numbers ${mcause} ${illegal_instruction}
|
||||
${mtval}= Execute Command cpu MTVAL
|
||||
Should Be Equal As Numbers ${mtval} ${nonexisting_csr}
|
||||
${mepc}= Execute Command cpu MEPC
|
||||
Should Be Equal As Numbers ${mepc} 0x4004
|
||||
|
||||
Should Allow SRET In Machine Mode
|
||||
Create Machine 32
|
||||
|
||||
Execute Command cpu SEPC 0x1234
|
||||
|
||||
# j 0x4000
|
||||
Execute Command sysbus WriteDoubleWord ${starting_pc} 0x0000206f
|
||||
# nop
|
||||
Execute Command sysbus WriteDoubleWord 0x4000 0x00000013
|
||||
# sret
|
||||
Execute Command sysbus WriteDoubleWord 0x4004 0x10200073
|
||||
|
||||
Execute Command cpu Step 3
|
||||
|
||||
PC Should Be Equal 0x1234
|
||||
|
||||
Should Exit Translation Block After Invalid Instruction And Report Single Error
|
||||
Create Machine 32
|
||||
Load Program With Invalid Instruction ${starting_pc}
|
||||
Create Log Tester 3
|
||||
|
||||
${start_pc}= Convert To Integer ${starting_pc}
|
||||
${illegal_opcode_1_pc} Set Variable ${start_pc+8}
|
||||
${illegal_opcode_1_pc_hex}= Convert To Hex ${illegal_opcode_1_pc}
|
||||
|
||||
${illegal_opcode_2_pc} Set Variable ${start_pc+24}
|
||||
${illegal_opcode_2_pc_hex}= Convert To Hex ${illegal_opcode_2_pc}
|
||||
|
||||
${illegal_opcode_3_pc} Set Variable ${start_pc+32}
|
||||
${illegal_opcode_3_pc_hex}= Convert To Hex ${illegal_opcode_3_pc}
|
||||
|
||||
# It doesn't use single stepping on purpose, as it would cause translation blocks of size 1.
|
||||
Execute Command cpu PerformanceInMips 1
|
||||
Execute Command emulation SetGlobalQuantum "0.000020"
|
||||
Execute Command emulation RunFor "0.000010"
|
||||
Wait For Log Entry PC: 0x${illegal_opcode_1_pc_hex}.* instruction set is not enabled for this CPU! treatAsRegex=True
|
||||
Should Not Be In Log PC: 0x${illegal_opcode_2_pc_hex}.* instruction set is not enabled for this CPU! 0 treatAsRegex=True
|
||||
Should Not Be In Log PC: 0x${illegal_opcode_3_pc_hex}.* instruction set is not enabled for this CPU! 0 treatAsRegex=True
|
||||
|
||||
Should Properly Handle ResetVector After Creation And After Reset 32
|
||||
Create Machine bitness=32 init_pc=False
|
||||
Should Properly Handle ResetVector At Init And After Reset
|
||||
|
||||
Should Properly Handle ResetVector After Creation And After Reset 64
|
||||
Create Machine bitness=64 init_pc=False
|
||||
Should Properly Handle ResetVector At Init And After Reset
|
||||
|
||||
Should Set Flag On Single Precision Floating Point Division By Zero
|
||||
[Tags] floating-point
|
||||
${float32_zero}= Set Variable 0xffffffff00000000
|
||||
${float32_one}= Set Variable 0xffffffff3F800000
|
||||
${float32_infinity}= Set Variable 0xffffffff7f800000
|
||||
|
||||
Create Machine 64
|
||||
|
||||
Execute Command cpu SetRegister "F0" ${float32_zero}
|
||||
Execute Command cpu SetRegister "F1" ${float32_one}
|
||||
Execute Command cpu SetRegister "F2" 0x0 # register where result will be stored
|
||||
# Expected result: 1/0 = Infinity and Divide by Zero flag set.
|
||||
Execute Command cpu AssembleBlock ${starting_pc} "fdiv.s f2, f1, f0"
|
||||
|
||||
Register Should Be Equal F2 0x0
|
||||
${fflags}= Execute Command cpu GetRegister "FFLAGS"
|
||||
Should Be True (${fflags} & ${divide_by_zero_flag}) == 0
|
||||
|
||||
Execute Command cpu Step
|
||||
PC Should Be Equal ${{ ${starting_pc} + 4 }}
|
||||
|
||||
Register Should Be Equal F2 ${float32_infinity}
|
||||
${fflags}= Execute Command cpu GetRegister "FFLAGS"
|
||||
Should Be True (${fflags} & ${divide_by_zero_flag}) != 0
|
||||
|
||||
Should Set Flag On Half Precision Floating Point Division By Zero
|
||||
[Tags] floating-point
|
||||
${float16_zero}= Set Variable 0xffffffffffff0000
|
||||
${float16_one}= Set Variable 0xffffffffffff3c00
|
||||
${float16_infinity}= Set Variable 0xffffffffffff7c00
|
||||
|
||||
Create Machine 64
|
||||
|
||||
Execute Command cpu SetRegister "F0" ${float16_zero}
|
||||
Execute Command cpu SetRegister "F1" ${float16_one}
|
||||
Execute Command cpu SetRegister "F2" 0x0 # register where result will be stored
|
||||
# Expected result: 1/0 = Infinity and Divide by Zero flag set.
|
||||
Execute Command cpu AssembleBlock ${starting_pc} "fdiv.h f2, f1, f0"
|
||||
|
||||
Register Should Be Equal F2 0x0
|
||||
${fflags}= Execute Command cpu GetRegister "FFLAGS"
|
||||
Should Be True (${fflags} & ${divide_by_zero_flag}) == 0
|
||||
|
||||
Execute Command cpu Step
|
||||
PC Should Be Equal ${{ ${starting_pc} + 4 }}
|
||||
|
||||
Register Should Be Equal F2 ${float16_infinity}
|
||||
${fflags}= Execute Command cpu GetRegister "FFLAGS"
|
||||
Should Be True (${fflags} & ${divide_by_zero_flag}) != 0
|
||||
Reference in New Issue
Block a user