1*** Variables ***
2# RISC-V registers
3${a1}                         0xb
4${starting_pc}                0x2000
5${next_instruction}           0x2004
6${mtvec}                      0x1010
7${illegal_instruction}        0x2
8${load_misaligned}            0x4
9${store_misaligned}           0x6
10${register_0}                 0x0
11${illegal_opcode}             0x00008000
12${illegal_csr}                0xf120d073
13${nonexisting_csr}            0xfff0d073
14
15
16*** Keywords ***
17Create Machine
18    [Arguments]    ${bitness}    ${init_pc}
19    Execute Command           using sysbus
20    Execute Command           mach create "risc-v"
21
22    Execute Command           machine LoadPlatformDescriptionFromString "clint: IRQControllers.CoreLevelInterruptor @ sysbus 0x44000000 { frequency: 66000000 }"
23    Execute Command           machine LoadPlatformDescriptionFromString "cpu: CPU.RiscV${bitness} @ sysbus { timeProvider: clint; cpuType: \\"rv${bitness}gc\\" }"
24    Execute Command           machine LoadPlatformDescriptionFromString "mem: Memory.MappedMemory @ sysbus 0x1000 { size: 0x40000 }"
25
26    IF    ${init_pc}
27       Execute Command           cpu PC ${starting_pc}
28    END
29
30Create Machine 32
31    Create Machine    bitness=32  init_pc=True
32
33Create Machine 64
34    Create Machine    bitness=64  init_pc=True
35
36Write Opcode To
37    [Arguments]                         ${adress}   ${opcode}
38    Execute Command                     sysbus WriteDoubleWord ${adress} ${opcode}
39
40Load Program With Invalid Instruction
41    [Arguments]                         ${address}
42    ${addi_opcode}                      Set Variable  0x00050593  #addi        x11 x10 0
43    ${vector_opcode}                    Set Variable  0x00000057  #vadd.vv     v0, v0, v0, v0.t
44    ${fvf_vector_opcode}                Set Variable  0x00005057  #vfadd.vf    v0, v0, ft0, v0.t
45    ${start_pc}=                        Convert To Integer  ${address}
46
47    # Depending on the fact if vector extension is enabled or not, the program will cause
48    # invalid instruction exception at ${vector_opcode} or ${fvf_vector_opcode}.
49    Write Opcode To  ${start_pc}     ${addi_opcode}            #addi x11 x10 0
50    Write Opcode To  ${start_pc+4}   ${addi_opcode}            #addi x11 x10 0
51    Write Opcode To  ${start_pc+8}   ${vector_opcode}          #vadd.vv v0, v0, v0, v0.t
52    Write Opcode To  ${start_pc+12}  ${addi_opcode}            #addi x11 x10 0
53    Write Opcode To  ${start_pc+16}  ${addi_opcode}            #addi x11 x10 0
54    Write Opcode To  ${start_pc+20}  ${addi_opcode}            #addi x11 x10 0
55    Write Opcode To  ${start_pc+24}  ${fvf_vector_opcode}      #vfadd.vf v0, v0, ft0, v0.t
56    Write Opcode To  ${start_pc+28}  ${addi_opcode}            #addi x11 x10 0
57    Write Opcode To  ${start_pc+32}  ${vector_opcode}          #vadd.vv v0, v0, v0, v0.t
58    Write Opcode To  ${start_pc+36}  ${addi_opcode}            #addi x11 x10 0
59
60Set ResetVector And Verify PC
61    [Arguments]    ${reset_vector}    ${should_set_pc}
62    IF    ${should_set_pc}
63        ${expected_pc}=  Set Variable     ${reset_vector}
64    ELSE
65        ${expected_pc}=  Execute Command  cpu PC
66    END
67    Execute Command                cpu ResetVector ${reset_vector}
68    Verify PC                      ${expected_pc}
69
70Should Properly Handle ResetVector
71    # Setting ResetVector before setting PC directly, with LoadELF etc. should propagate to PC.
72    Set ResetVector And Verify PC   0x1234    should_set_pc=True
73    Set ResetVector And Verify PC   0x1238    should_set_pc=True
74
75    # Setting PC other than as an effect of ResetVector should stop the propagation.
76    ${new_reset_vector_value}=  Set Variable  0x123C
77    Execute Command                 cpu PC 0x5678
78    Set ResetVector And Verify PC   ${new_reset_vector_value}    should_set_pc=False
79
80    # Reset should set PC to ResetVector and restore PC propagation on ResetVector.
81    Execute Command                 cpu Reset
82    Verify PC                       ${new_reset_vector_value}
83    Set ResetVector And Verify PC   0x1240    should_set_pc=True
84
85Should Properly Handle ResetVector At Init And After Reset
86    Verify PC                       0x1000  # Default ResetVector
87    Should Properly Handle ResetVector
88
89    ${new_reset_vector_value}=  Set Variable    0x2468
90    Execute Command                 cpu ResetVector ${new_reset_vector_value}
91    Execute Command                 cpu Reset
92    Verify PC                       ${new_reset_vector_value}
93    Should Properly Handle ResetVector
94
95Verify PC
96    [Arguments]    ${expected_pc}
97    ${pc}=  Execute Command        cpu PC
98    Should Be Equal As Integers    ${pc}    ${expected_pc}
99
100*** Test Cases ***
101Should Handle LB
102    Create Machine 32
103
104    Execute Command                 cpu SetRegister ${a1} 0x00000000
105
106    # lb a0, 0x00000005(a1)
107    Execute Command                 sysbus WriteDoubleWord ${starting_pc} 0x00558503
108
109    Execute Command                 cpu Step
110
111    ${pc}=                          Execute Command     cpu PC
112    Should Be Equal As Numbers      ${pc}   ${next_instruction}
113
114Should Handle LH
115    Create Machine 32
116
117    Execute Command                 cpu SetRegister ${a1} 0x00000001
118
119    # lh a0, 0x00000005(a1)
120    Execute Command                 sysbus WriteDoubleWord ${starting_pc} 0x00559503
121
122    Execute Command                 cpu Step
123
124    ${pc}=                          Execute Command     cpu PC
125    Should Be Equal As Numbers      ${pc}   ${next_instruction}
126
127Should Fail LH
128    Create Machine 32
129
130    Execute Command                 cpu SetRegister ${a1} 0x00000000
131
132    # lh a0, 0x00000005(a1)
133    Execute Command                 sysbus WriteDoubleWord ${starting_pc} 0x00559503
134
135    Execute Command                 cpu Step
136
137    ${pc}=                          Execute Command     cpu PC
138    Should Be Equal As Numbers      ${pc}   ${mtvec}
139
140    ${mcause}=                      Execute Command     cpu MCAUSE
141    Should Be Equal As Numbers      ${mcause}   ${load_misaligned}
142
143Should Handle LW
144    Create Machine 32
145
146    Execute Command                 cpu SetRegister ${a1} 0x00000003
147
148    # lw a0, 0x00000005(a1)
149    Execute Command                 sysbus WriteDoubleWord ${starting_pc} 0x0055a503
150
151    Execute Command                 cpu Step
152
153    ${pc}=                          Execute Command     cpu PC
154    Should Be Equal As Numbers      ${pc}   ${next_instruction}
155
156Should Fail LW
157    Create Machine 32
158
159    Execute Command                 cpu SetRegister ${a1} 0x00000000
160
161    # lw a0, 0x00000005(a1)
162    Execute Command                 sysbus WriteDoubleWord ${starting_pc} 0x0055a503
163
164    Execute Command                 cpu Step
165
166    ${pc}=                          Execute Command     cpu PC
167    Should Be Equal As Numbers      ${pc}   ${mtvec}
168
169    ${mcause}=                      Execute Command     cpu MCAUSE
170    Should Be Equal As Numbers      ${mcause}   ${load_misaligned}
171
172Should Handle LD
173    Create Machine 64
174
175    Execute Command                 cpu SetRegister ${a1} 0x00000003
176
177    # ld a0, 0x00000005(a1)
178    Execute Command                 sysbus WriteDoubleWord ${starting_pc} 0x0055b503
179
180    Execute Command                 cpu Step
181
182    ${pc}=                          Execute Command     cpu PC
183    Should Be Equal As Numbers      ${pc}   ${next_instruction}
184
185Should Fail LD
186    Create Machine 64
187
188    Execute Command                 cpu SetRegister ${a1} 0x00000000
189
190    # ld a0, 0x00000005(a1)
191    Execute Command                 sysbus WriteDoubleWord ${starting_pc} 0x0055b503
192
193    Execute Command                 cpu Step
194
195    ${pc}=                          Execute Command     cpu PC
196    Should Be Equal As Numbers      ${pc}   ${mtvec}
197
198    ${mcause}=                      Execute Command     cpu MCAUSE
199    Should Be Equal As Numbers      ${mcause}   ${load_misaligned}
200
201Should Handle SB
202    Create Machine 32
203
204    Execute Command                 cpu SetRegister ${a1} 0x00000000
205
206    # sb a0, 0x00000005(a1)
207    Execute Command                 sysbus WriteDoubleWord ${starting_pc} 0x00a582a3
208
209    Execute Command                 cpu Step
210
211    ${pc}=                          Execute Command     cpu PC
212    Should Be Equal As Numbers      ${pc}   ${next_instruction}
213
214Should Handle SH
215    Create Machine 32
216
217    Execute Command                 cpu SetRegister ${a1} 0x00000001
218
219    # sh a0, 0x00000005(a1)
220    Execute Command                 sysbus WriteDoubleWord ${starting_pc} 0x00a592a3
221
222    Execute Command                 cpu Step
223
224    ${pc}=                          Execute Command     cpu PC
225    Should Be Equal As Numbers      ${pc}   ${next_instruction}
226
227Should Fail SH
228    Create Machine 32
229
230    Execute Command                 cpu SetRegister ${a1} 0x00000000
231
232    # sh a0, 0x00000005(a1)
233    Execute Command                 sysbus WriteDoubleWord ${starting_pc} 0x00a592a3
234
235    Execute Command                 cpu Step
236
237    ${pc}=                          Execute Command     cpu PC
238    Should Be Equal As Numbers      ${pc}   ${mtvec}
239
240    ${mcause}=                      Execute Command     cpu MCAUSE
241    Should Be Equal As Numbers      ${mcause}   ${store_misaligned}
242
243Should Handle SW
244    Create Machine 32
245
246    Execute Command                 cpu SetRegister ${a1} 0x00000003
247
248    # sw a0, 0x00000005(a1)
249    Execute Command                 sysbus WriteDoubleWord ${starting_pc} 0x00a5a2a3
250
251    Execute Command                 cpu Step
252
253    ${pc}=                          Execute Command     cpu PC
254    Should Be Equal As Numbers      ${pc}   ${next_instruction}
255
256Should Fail SW
257    Create Machine 32
258
259    Execute Command                 cpu SetRegister ${a1} 0x00000000
260
261    # sw a0, 0x00000005(a1)
262    Execute Command                 sysbus WriteDoubleWord ${starting_pc} 0x00a5a2a3
263
264    Execute Command                 cpu Step
265
266    ${pc}=                          Execute Command     cpu PC
267    Should Be Equal As Numbers      ${pc}   ${mtvec}
268
269    ${mcause}=                      Execute Command     cpu MCAUSE
270    Should Be Equal As Numbers      ${mcause}   ${store_misaligned}
271
272Should Handle SD
273    Create Machine 64
274
275    Execute Command                 cpu SetRegister ${a1} 0x00000003
276
277    # sd a0, 0x00000005(a1)
278    Execute Command                 sysbus WriteDoubleWord ${starting_pc} 0x00a5b2a3
279
280    Execute Command                 cpu Step
281
282    ${pc}=                          Execute Command     cpu PC
283    Should Be Equal As Numbers      ${pc}   ${next_instruction}
284
285Should Fail SD
286    Create Machine 64
287
288    Execute Command                 cpu SetRegister ${a1} 0x00000001
289
290    # sd a0, 0x00000005(a1)
291    Execute Command                 sysbus WriteDoubleWord ${starting_pc} 0x00a5b2a3
292
293    Execute Command                 cpu Step
294
295    ${pc}=                          Execute Command     cpu PC
296    Should Be Equal As Numbers      ${pc}   ${mtvec}
297
298    ${mcause}=                      Execute Command     cpu MCAUSE
299    Should Be Equal As Numbers      ${mcause}   ${store_misaligned}
300
301Should Fail On Setting X0 register
302    Create Machine 32
303
304    ${msg}=     		    Run Keyword And Expect Error        *   Execute Command       cpu SetRegister ${register_0} 0x00000001
305    Should Contain      	    ${msg}      register is read-only
306
307    Register Should Be Equal        0  0x0
308
309Should Set MEPC on Illegal Instruction
310    Create Machine 32
311
312    # j .
313    Execute Command                 sysbus WriteDoubleWord 0x1010 0x0000006f
314
315    # j 0x4000
316    Execute Command                 sysbus WriteDoubleWord ${starting_pc} 0x0000206f
317    # nop
318    Execute Command                 sysbus WriteDoubleWord 0x4000 0x00000013
319    # ILLEGAL INSTRUCTION
320    Execute Command                 sysbus WriteDoubleWord 0x4004 ${illegal_opcode}
321
322    Execute Command                 cpu Step 3
323
324    PC Should Be Equal              0x1010
325
326    ${mcause}=                      Execute Command     cpu MCAUSE
327    Should Be Equal As Numbers      ${mcause}  ${illegal_instruction}
328    ${mtval}=                       Execute Command     cpu MTVAL
329    Should Be Equal As Numbers      ${mtval}   ${illegal_opcode}
330    ${mepc}=                        Execute Command     cpu MEPC
331    Should Be Equal As Numbers      ${mepc}    0x4004
332
333Should Set MEPC on Illegal CSR access
334    Create Machine 32
335    Execute Command   cpu CSRValidation Full
336
337    # j .
338    Execute Command                 sysbus WriteDoubleWord 0x1010 0x0000006f
339
340    # j 0x4000
341    Execute Command                 sysbus WriteDoubleWord ${starting_pc} 0x0000206f
342    # nop
343    Execute Command                 sysbus WriteDoubleWord 0x4000 0x00000013
344    # csrwi marchid, 1 - this is an illegal CSR operation as `marchid` is read-only
345    Execute Command                 sysbus WriteDoubleWord 0x4004 ${illegal_csr}
346
347    Execute Command                 cpu Step 3
348
349    PC Should Be Equal              0x1010
350
351    ${mcause}=                      Execute Command     cpu MCAUSE
352    Should Be Equal As Numbers      ${mcause}  ${illegal_instruction}
353    ${mtval}=                       Execute Command     cpu MTVAL
354    Should Be Equal As Numbers      ${mtval}   ${illegal_csr}
355    ${mepc}=                        Execute Command     cpu MEPC
356    Should Be Equal As Numbers      ${mepc}    0x4004
357
358Should Set MEPC on Non-Existing CSR access
359    Create Machine 32
360
361    # j .
362    Execute Command                 sysbus WriteDoubleWord 0x1010 0x0000006f
363
364    # j 0x4000
365    Execute Command                 sysbus WriteDoubleWord ${starting_pc} 0x0000206f
366    # nop
367    Execute Command                 sysbus WriteDoubleWord 0x4000 0x00000013
368    # csrwi marchid, 1 - this is an illegal CSR operation as `marchid` is read-only
369    Execute Command                 sysbus WriteDoubleWord 0x4004 ${nonexisting_csr}
370
371    Execute Command                 cpu Step 3
372
373    PC Should Be Equal              0x1010
374
375    ${mcause}=                      Execute Command     cpu MCAUSE
376    Should Be Equal As Numbers      ${mcause}  ${illegal_instruction}
377    ${mtval}=                       Execute Command     cpu MTVAL
378    Should Be Equal As Numbers      ${mtval}   ${nonexisting_csr}
379    ${mepc}=                        Execute Command     cpu MEPC
380    Should Be Equal As Numbers      ${mepc}    0x4004
381
382Should Allow SRET In Machine Mode
383    Create Machine 32
384
385    Execute Command                 cpu SEPC 0x1234
386
387    # j 0x4000
388    Execute Command                 sysbus WriteDoubleWord ${starting_pc} 0x0000206f
389    # nop
390    Execute Command                 sysbus WriteDoubleWord 0x4000 0x00000013
391    # sret
392    Execute Command                 sysbus WriteDoubleWord 0x4004 0x10200073
393
394    Execute Command                 cpu Step 3
395
396    PC Should Be Equal              0x1234
397
398Should Exit Translation Block After Invalid Instruction And Report Single Error
399    Create Machine 32
400    Load Program With Invalid Instruction               ${starting_pc}
401    Create Log Tester               3
402
403    ${start_pc}=                    Convert To Integer  ${starting_pc}
404    ${illegal_opcode_1_pc}          Set Variable        ${start_pc+8}
405    ${illegal_opcode_1_pc_hex}=     Convert To Hex      ${illegal_opcode_1_pc}
406
407    ${illegal_opcode_2_pc}          Set Variable        ${start_pc+24}
408    ${illegal_opcode_2_pc_hex}=     Convert To Hex      ${illegal_opcode_2_pc}
409
410    ${illegal_opcode_3_pc}          Set Variable        ${start_pc+32}
411    ${illegal_opcode_3_pc_hex}=     Convert To Hex      ${illegal_opcode_3_pc}
412
413    # It doesn't use single stepping on purpose, as it would cause translation blocks of size 1.
414    Execute Command                 cpu PerformanceInMips 1
415    Execute Command                 emulation SetGlobalQuantum "0.000020"
416    Execute Command                 emulation RunFor "0.000010"
417    Wait For Log Entry              PC: 0x${illegal_opcode_1_pc_hex}.* instruction set is not enabled for this CPU!  treatAsRegex=True
418    Should Not Be In Log            PC: 0x${illegal_opcode_2_pc_hex}.* instruction set is not enabled for this CPU!  0  treatAsRegex=True
419    Should Not Be In Log            PC: 0x${illegal_opcode_3_pc_hex}.* instruction set is not enabled for this CPU!  0  treatAsRegex=True
420
421Should Properly Handle ResetVector After Creation And After Reset 32
422    Create Machine                  bitness=32  init_pc=False
423    Should Properly Handle ResetVector At Init And After Reset
424
425Should Properly Handle ResetVector After Creation And After Reset 64
426    Create Machine                  bitness=64  init_pc=False
427    Should Properly Handle ResetVector At Init And After Reset
428