1*** Variables ***
2${MEMORY_START}                     0x80000000
3${PLATFORM}                         SEPARATOR=\n
4...                                 dram: Memory.MappedMemory @ sysbus ${MEMORY_START} {
5...                                 ${SPACE*4}size: 0x80000000
6...                                 }
7...                                 mmio: Memory.ArrayMemory @ sysbus 0x100000000 {
8...                                 ${SPACE*4}size: 0x10000
9...                                 }
10...
11...                                 cpu: CPU.RiscV64 @ sysbus {
12...                                 ${SPACE*4}cpuType: "rv64gc_zicsr_zifencei";
13...                                 ${SPACE*4}hartId: 1;
14...                                 ${SPACE*4}privilegedArchitecture: PrivilegedArchitecture.Priv1_10;
15...                                 ${SPACE*4}timeProvider: empty;
16...                                 ${SPACE*4}CyclesPerInstruction: 8;
17...                                 ${SPACE*4}allowUnalignedAccesses: true
18...                                 }
19${PAGE_SPANNING_ADDRESS}            0x0000000080000fff  # Assuming page size is 4 KiB
20${MMIO_ADDRESS}                     0x0000000100001000
21${MEMORY_VALUE}                     0xffffffff80000000
22${INCREMENT_BY_X}                   0xfffffffffffff800
23${INCREMENT_BY_Y}                   0xffffffff80000000
24${EXPECTED_SUM_X_W}                 0x000000007ffff800
25${EXPECTED_SUM_Y_W}                 0x00000000fffff800
26${EXPECTED_SUM_X_D}                 0xffffffff7ffff800
27${EXPECTED_SUM_Y_D}                 0xffffffff7ffff000
28
29# Registers used
30${a0}                               10
31${a1}                               11
32${a2}                               12
33
34*** Keywords ***
35Create Machine
36    Execute Command                 mach create
37    Execute Command                 machine LoadPlatformDescriptionFromString """${PLATFORM}"""
38    Execute Command                 cpu ExecutionMode SingleStep
39    Execute Command                 cpu PC 0x80000000
40
41Amoadd.w Should Increment Memory Location ${variable_address}
42    Create Machine
43
44    # Place value in memory.
45    Execute Command                 sysbus WriteDoubleWord ${variable_address} ${MEMORY_VALUE}
46
47    # The assembly instructions to execute in this test.
48    ${ASSEMBLY_AMOADD_W}=           catenate  SEPARATOR=
49    ...                             amoadd.w a2, a1, (a0);
50    ...                             amoadd.w a2, a1, (a0);
51
52    # Place machine code at PC.
53    Execute Command                 cpu AssembleBlock 0x80000000 "${ASSEMBLY_AMOADD_W}"
54
55    Execute Command                 cpu SetRegister ${a0} ${variable_address}
56    Execute Command                 cpu SetRegister ${a1} ${INCREMENT_BY_X}
57
58    # Perform amoadd to atomically increment memory location
59    Execute Command                 cpu Step
60
61    # After amoadd, rd register should have the original memory value (before the add)...
62    Register Should Be Equal        ${a2}  ${MEMORY_VALUE}  cpuName=cpu
63    # and a1 should remain unchanged
64    Register Should Be Equal        ${a1}  ${INCREMENT_BY_X}  cpuName=cpu
65
66    # Now value in memory should have been incremented.
67    ${res}=                         Execute Command  sysbus ReadDoubleWord ${variable_address}
68    Should Be Equal As Integers     ${res}  ${EXPECTED_SUM_X_W}  "first amoadd: Memory location should now contain ${EXPECTED_SUM_X_W}"
69
70    # Now, instead, increment by y.
71    Execute Command                 cpu SetRegister ${a1} ${INCREMENT_BY_Y}
72
73    # Perform amoadd again
74    Execute Command                 cpu Step
75
76    # After second amoadd, rd register should have the sum from the previous amoadd
77    Register Should Be Equal        ${a2}  ${EXPECTED_SUM_X_W}  cpuName=cpu
78
79    # Now value in memory should have been incremented.
80    ${res}=                         Execute Command  sysbus ReadDoubleWord ${variable_address}
81    Should Be Equal As Integers     ${res}  ${EXPECTED_SUM_Y_W}  "second amoadd: Memory location should now contain ${EXPECTED_SUM_Y_W}"
82
83Amoadd.d Should Increment Memory Location ${variable_address}
84    Create Machine
85
86    # Place value in memory.
87    Execute Command                 sysbus WriteQuadWord ${variable_address} ${MEMORY_VALUE}
88
89    # The assembly instructions to execute in this test.
90    ${ASSEMBLY_AMOADD_D}=           catenate  SEPARATOR=
91    ...                             amoadd.d a2, a1, (a0);
92    ...                             amoadd.d a2, a1, (a0);
93
94    # Place machine code at PC.
95    Execute Command                 cpu AssembleBlock 0x80000000 "${ASSEMBLY_AMOADD_D}"
96
97    Execute Command                 cpu SetRegister ${a0} ${variable_address}
98    Execute Command                 cpu SetRegister ${a1} ${INCREMENT_BY_X}
99
100    # Perform amoadd to atomically increment memory location
101    Execute Command                 cpu Step
102
103    # After amoadd, rd register should have the original memory value (before the add)...
104    Register Should Be Equal        ${a2}  ${MEMORY_VALUE}  cpuName=cpu
105    # and a1 should remain unchanged
106    Register Should Be Equal        ${a1}  ${INCREMENT_BY_X}  cpuName=cpu
107
108    # Now value in memory should have been incremented.
109    ${res}=                         Execute Command  sysbus ReadQuadWord ${variable_address}
110    Should Be Equal As Integers     ${res}  ${EXPECTED_SUM_X_D}  "first amoadd: Memory location should now contain ${EXPECTED_SUM_X_D}"
111
112    # Load INCREMENT_BY_X into a1 again
113    Execute Command                 cpu SetRegister ${a1} ${INCREMENT_BY_X}
114
115    # Perform amoadd again
116    Execute Command                 cpu Step
117
118    # After second amoadd, rd register should have the sum from the previous amoadd
119    Register Should Be Equal        ${a2}  ${EXPECTED_SUM_X_D}  cpuName=cpu
120
121    # Now value in memory should have been incremented.
122    ${res}=                         Execute Command  sysbus ReadQuadWord ${variable_address}
123    Should Be Equal As Integers     ${res}  ${EXPECTED_SUM_Y_D}  "second amoadd: Memory location should now contain ${EXPECTED_SUM_Y_D}"
124
125*** Test Cases ***
126Amoadd.w Should Increment Single-Page Memory Location
127    Amoadd.w Should Increment Memory Location 0x80000100
128
129Amoadd.d Should Increment Single-Page Memory Location
130    Amoadd.d Should Increment Memory Location 0x80000100
131
132Amoadd.w Should Increment Page-Spanning Memory Location
133    Amoadd.w Should Increment Memory Location ${PAGE_SPANNING_ADDRESS}
134
135Amoadd.d Should Increment Page-Spanning Memory Location
136    Amoadd.d Should Increment Memory Location ${PAGE_SPANNING_ADDRESS}
137
138Amoadd.d Should Increment MMIO Memory Location
139    Amoadd.d Should Increment Memory Location ${MMIO_ADDRESS}
140
141Amoadd.w Should Increment MMIO Memory Location
142    Amoadd.w Should Increment Memory Location ${MMIO_ADDRESS}
143