1*** Variables ***
2${CPU_COUNT}                        4
3${INIT_PERIPHBASE_ADDRESS}          0xAE000000
4${INIT_PERIPHBASE}                  0x57000
5${NEW_PERIPHBASE_ADDRESS}           0x80000000
6${NEW_PERIPHBASE}                   0x40000
7${REPL_PATH}                        platforms/cpus/cortex-r8_smp.repl
8${SIGNALS_UNIT}                     signalsUnit
9
10${GIC_MODEL}                        Antmicro.Renode.Peripherals.IRQControllers.ARM_GenericInterruptController
11${PRIVATE_TIMER_MODEL}              Antmicro.Renode.Peripherals.Timers.ARM_PrivateTimer
12${SCU_MODEL}                        Antmicro.Renode.Peripherals.Miscellaneous.ArmSnoopControlUnit
13
14*** Keywords ***
15Create Cortex-R8 Machine
16    [Arguments]                     ${scu_registration}
17
18    Execute Command                 mach create
19    Execute Command                 machine LoadPlatformDescriptionFromString "using \\"${REPL_PATH}\\"; scu: @ ${scu_registration}"
20
21Should Modify Peripheral Registration
22    Verify Command Output As Integer  0x0  cpu0 GetSystemRegisterValue "CBAR"
23
24    Execute Command                 emulation RunFor '0.0001'
25    FOR  ${i}  IN RANGE  ${CPU_COUNT}
26        # SCU address is based on PERIPHBASE with zero offset.
27        Verify Command Output As Integer
28        ...                             ${INIT_PERIPHBASE_ADDRESS}  cpu${i} GetSystemRegisterValue "CBAR"
29    END
30
31    Execute Command                 ${SIGNALS_UNIT} SetSignalFromAddress "PERIPHBASE" ${NEW_PERIPHBASE_ADDRESS}
32
33    # Nothing changes before exiting from reset.
34    Verify Peripherals Registered At  ${INIT_PERIPHBASE_ADDRESS}
35    Verify Command Output As Integer
36    ...                             ${INIT_PERIPHBASE_ADDRESS}  cpu1 GetSystemRegisterValue "CBAR"
37
38    # Let's make sure the behavior is preserved across serialization.
39    ${f}=                           Allocate Temporary File
40    Execute Command                 Save @${f}
41    Execute Command                 Clear
42    Execute Command                 Load @${f}
43    Execute Command                 mach set 0
44
45    FOR  ${i}  IN RANGE  ${CPU_COUNT}
46        Execute Command                 cpu${i} Reset
47    END
48    Execute Command                 emulation RunFor '0.0001'
49
50    FOR  ${i}  IN RANGE  ${CPU_COUNT}
51        Verify Command Output As Integer  ${NEW_PERIPHBASE_ADDRESS}  cpu${i} GetSystemRegisterValue "CBAR"
52    END
53
54    Verify Peripherals Registered At  ${NEW_PERIPHBASE_ADDRESS}
55
56Verify Command Output As Integer
57    [Arguments]                     ${expected}  ${command}
58
59    ${output}=                      Execute Command  ${command}
60    Should Be Equal As Integers     ${expected}  ${output}  base=16
61
62Verify Command Output
63    [Arguments]                     ${expected}  ${command}
64
65    ${output}=                      Execute Command  ${command}
66    Should Be Equal                 ${expected}  ${output}  strip_spaces=True
67
68Verify PERIPHBASE Init Value
69    Verify Command Output As Integer  ${INIT_PERIPHBASE_ADDRESS}  ${SIGNALS_UNIT} GetAddress "PERIPHBASE"
70
71Verify Peripherals Registered At
72    [Arguments]                     ${address}
73
74    FOR  ${i}  IN RANGE  ${CPU_COUNT}
75        Verify Command Output
76        ...                             ${SCU_MODEL}  sysbus WhatPeripheralIsAt ${address} cpu${i}
77        Verify Command Output
78        ...                             ${GIC_MODEL}  sysbus WhatPeripheralIsAt ${${address} + 0x100} cpu${i}  # CPU interface
79        Verify Command Output
80        ...                             ${GIC_MODEL}  sysbus WhatPeripheralIsAt ${${address} + 0x1000} cpu${i}  # distributor
81        Verify Command Output
82        ...                             ${PRIVATE_TIMER_MODEL}  sysbus WhatPeripheralIsAt ${${address} + 0x600} cpu${i}
83    END
84
85Verify PCs
86    [Arguments]                     ${cpu0_pc_expected}  ${cpu1_pc_expected}
87
88    Verify Command Output As Integer  ${cpu0_pc_expected}  cpu0 PC
89    Verify Command Output As Integer  ${cpu1_pc_expected}  cpu1 PC
90
91*** Test Cases ***
92Create Machine With SCU Registered
93    Create Cortex-R8 Machine        scu_registration=sysbus ${INIT_PERIPHBASE_ADDRESS}
94    Provides                        created-cr8-machine
95
96Should Gracefully Handle Invalid Signal
97    Requires                        created-cr8-machine
98
99    # All available signals should be printed with both names when the given signal can't be found.
100    # Let's just check if two example signals are included: INITRAM and PERIPHBASE.
101    Run Keyword And Expect Error    *No such signal: ''\nAvailable signals are:*INITRAM (InitializeInstructionTCM)*
102    ...                             Execute Command  ${SIGNALS_UNIT} GetSignal ""
103    Run Keyword And Expect Error    *No such signal: 'INVALID'\nAvailable signals are:*PERIPHBASE (PeripheralsBase)*
104    ...                             Execute Command  ${SIGNALS_UNIT} GetSignal "INVALID"
105
106Should Handle Addresses
107    Requires                        created-cr8-machine
108
109    Verify PERIPHBASE Init Value
110
111    Execute Command                   ${SIGNALS_UNIT} SetSignalFromAddress "PERIPHBASE" ${NEW_PERIPHBASE_ADDRESS}
112    Verify Command Output As Integer  ${NEW_PERIPHBASE_ADDRESS}  ${SIGNALS_UNIT} GetAddress "PERIPHBASE"
113
114    # When set from address, the signal is set to a value based on address' top bits.
115    Verify Command Output As Integer  ${NEW_PERIPHBASE}  ${SIGNALS_UNIT} GetSignal "PERIPHBASE"
116
117    Create Log Tester                 0
118
119    # DBGROMADDR is a 20-bit signal, let's first set it to a non-zero value.
120    ${exp_value}=    Set Variable     0x12345
121    ${address}=      Set Variable     ${exp_value}000
122    ${signal}=       Set Variable     DebugROMAddress
123    Execute Command                   ${SIGNALS_UNIT} SetSignalFromAddress ${signal} ${address}
124
125    # Setting signals from addresses with bits over 32 set is invalid for Cortex-R8 even though only top 20 bits are set.
126    ${address_64b}=    Set Variable   0xFEDCB00000000000
127    Run Keyword And Expect Error      *${SIGNALS_UNIT}: ${signal}: 20-bit signal in a 32-bit unit shouldn't be set from ${address_64b} address*
128    ...  Execute Command              ${SIGNALS_UNIT} SetSignalFromAddress ${signal} ${address_64b}
129
130    # Valid address/value should be preserved.
131    Verify Command Output As Integer  ${address}    ${SIGNALS_UNIT} GetAddress ${signal}
132    Verify Command Output As Integer  ${exp_value}      ${SIGNALS_UNIT} GetSignal ${signal}
133
134    # PFILTERSTART is a 12-bit signal so setting it from an address with any of bits 0-19 set should fail.
135    ${address}=    Set Variable       0x12340000
136    ${signal}=     Set Variable       PeripheralFilterStart
137    Run Keyword And Expect Error      *${SIGNALS_UNIT}: ${signal}: 12-bit signal in a 32-bit unit shouldn't be set from ${address} address*
138    ...  Execute Command              ${SIGNALS_UNIT} SetSignalFromAddress ${signal} ${address}
139
140    # Make sure it stayed zero.
141    Verify Command Output As Integer  0x0    ${SIGNALS_UNIT} GetAddress ${signal}
142    Verify Command Output As Integer  0x0    ${SIGNALS_UNIT} GetSignal ${signal}
143
144Should Modify Peripheral Registration With SCU Registered
145    Requires                        created-cr8-machine
146
147    Verify Command Output As Integer  ${INIT_PERIPHBASE}  ${SIGNALS_UNIT} GetSignal "PERIPHBASE"
148    Verify Peripherals Registered At  ${INIT_PERIPHBASE_ADDRESS}
149
150    Should Modify Peripheral Registration
151
152Should Modify Peripheral Registration With SCU Unregistered
153    Create Cortex-R8 Machine        scu_registration=sysbus
154
155    # SCU initially unregistered, PERIPHBASE not automatically set as when SCU registered at a specific address.
156    Verify Command Output As Integer  0x0  ${SIGNALS_UNIT} GetSignal "PERIPHBASE"
157
158    # There should be no peripheral at INIT_PERIPHBASE where SCU is registered by default.
159    ${peripherals}=                 Execute Command  peripherals
160    Should Not Contain              ${peripherals}  ${INIT_PERIPHBASE_ADDRESS}
161
162    # Now let's set PERIPHBASE which will register SCU there on CPU out of reset and test modifying registrations.
163    Execute Command                 ${SIGNALS_UNIT} SetSignalFromAddress "PERIPHBASE" ${INIT_PERIPHBASE_ADDRESS}
164    Should Modify Peripheral Registration
165
166    ${peripherals}=                 Execute Command  peripherals
167
168Should Set PC For Cores With INITRAM And VINITHI High
169    Requires                        created-cr8-machine
170
171    Execute Command                 cpu0 ExecutionMode SingleStep
172    Execute Command                 cpu1 ExecutionMode SingleStep
173
174    # Both signals will be high only for cpu0.
175    Execute Command                 ${SIGNALS_UNIT} SetSignalStateForCPU "INITRAM" true cpu0
176    Execute Command                 ${SIGNALS_UNIT} SetSignalStateForCPU "INITRAM" true cpu1
177    Execute Command                 ${SIGNALS_UNIT} SetSignalStateForCPU "VINITHI" true cpu0
178    Execute Command                 ${SIGNALS_UNIT} SetSignalStateForCPU "VINITHI" false cpu1
179
180    Verify PCs                      0x0  0x0
181
182    Start Emulation
183    Verify PCs                      0xFFFF0000  0x0
184
185    Execute Command                 cpu0 PC 0x12345678
186    Execute Command                 cpu1 PC 0x90ABCDE0
187
188    # PCs are set immediately because machine is started right after Reset if it was started before.
189    Execute Command                 machine Reset
190    Verify PCs                      0xFFFF0000  0x0
191
192    # Now both signals will be high only for cpu1.
193    # Setting signals shouldn't influence PCs before starting-after-reset.
194    Execute Command                 ${SIGNALS_UNIT} SetSignalStateForCPU "VINITHI" false cpu0
195    Execute Command                 ${SIGNALS_UNIT} SetSignalStateForCPU "VINITHI" true cpu1
196    Verify PCs                      0xFFFF0000  0x0
197
198    Execute Command                 cpu0 Reset
199    Execute Command                 cpu1 Reset
200    Verify PCs                      0x0  0x0
201
202    Execute Command                 cpu0 Start
203    Execute Command                 cpu1 Start
204    Verify PCs                      0x0  0xFFFF0000
205
206Verify PERIPHBASE Init Value With CPU-specific SCU Registrations
207    Execute Command                 mach create
208
209    ${PLATFORM}=                    Catenate  SEPARATOR=\n
210    ...                             signalsUnit: Miscellaneous.CortexR8SignalsUnit @ sysbus
211    ...                             ${SPACE*4}snoopControlUnit: scu
212    ...
213    ...                             cpu0: CPU.ARMv7R @ sysbus
214    ...                             ${SPACE*4}cpuType: "cortex-r8"
215    ...                             ${SPACE*4}cpuId: 0
216    ...                             ${SPACE*4}signalsUnit: signalsUnit
217    ...
218    ...                             cpu1: CPU.ARMv7R @ sysbus
219    ...                             ${SPACE*4}cpuType: "cortex-r8"
220    ...                             ${SPACE*4}cpuId: 1
221    ...                             ${SPACE*4}signalsUnit: signalsUnit
222    ...
223    ...                             scu: Miscellaneous.ArmSnoopControlUnit @ {
224    ...                             ${SPACE*4}sysbus new Bus.BusPointRegistration { address: 0xae000000; cpu: cpu0 };
225    ...                             ${SPACE*4}sysbus new Bus.BusPointRegistration { address: 0xae000000; cpu: cpu1 }
226    ...                             }
227    Execute Command                 machine LoadPlatformDescriptionFromString """${PLATFORM}"""
228
229    Verify PERIPHBASE Init Value
230
231Registration Of Unsupported CPU Should Not Be Allowed From The Monitor
232    Requires                        created-cr8-machine
233
234    ${CR5_CPU}=                     Catenate  SEPARATOR=\n
235    ...                             cr5: CPU.ARMv7R @ sysbus
236    ...                             ${SPACE*4}cpuType: "cortex-r5"
237    ...                             ${SPACE*4}cpuId: 5
238
239    Execute Command                 machine LoadPlatformDescriptionFromString """${CR5_CPU}"""
240
241    ${MESSAGE}=                     Catenate  SEPARATOR=${SPACE}
242    ...    *Tried to register unsupported CPU model to CortexR8SignalsUnit: cortex-r5;
243    ...    supported CPUs are: cortex-r8*
244
245    Run Keyword And Expect Error    ${MESSAGE}
246    ...    Execute Command          ${SIGNALS_UNIT} RegisterCPU cr5
247
248Registration Of Unsupported CPU Should Not Be Allowed From Platform Description
249    Execute Command                 mach create
250
251    ${CR8_CPU}=                     Catenate  SEPARATOR=\n
252    ...                             ${SIGNALS_UNIT}: Miscellaneous.CortexR5SignalsUnit @ sysbus
253    ...
254    ...                             cpu: CPU.ARMv7R @ sysbus
255    ...                             ${SPACE*4}cpuType: "cortex-r8"
256    ...                             ${SPACE*4}signalsUnit: ${SIGNALS_UNIT}
257
258    ${MESSAGE}=                     Catenate  SEPARATOR=${SPACE}
259    ...    *Tried to register unsupported CPU model to CortexR5SignalsUnit: cortex-r8;
260    ...    supported CPUs are: cortex-r5, cortex-r5f*
261
262    Run Keyword And Expect Error    ${MESSAGE}
263    ...    Execute Command          machine LoadPlatformDescriptionFromString """${CR8_CPU}"""
264
265Create Machine With Cortex-R5 And Cortex-R5F
266    Execute Command                 mach create
267
268    ${PLATFORM}=                    Catenate  SEPARATOR=\n
269    ...                             ${SIGNALS_UNIT}: Miscellaneous.CortexR5SignalsUnit @ sysbus
270    ...
271    ...                             cpu0: CPU.ARMv7R @ sysbus
272    ...                             ${SPACE*4}cpuType: "cortex-r5f"
273    ...                             ${SPACE*4}cpuId: 0
274    ...                             ${SPACE*4}signalsUnit: ${SIGNALS_UNIT}
275    ...
276    ...                             cpu1: CPU.ARMv7R @ sysbus
277    ...                             ${SPACE*4}cpuType: "cortex-r5"
278    ...                             ${SPACE*4}cpuId: 1
279    ...                             ${SPACE*4}signalsUnit: ${SIGNALS_UNIT}
280
281    Execute Command                 machine LoadPlatformDescriptionFromString """${PLATFORM}"""
282
283    Provides                        created-cr5-machine
284
285Set Cortex-R5 Peripheral Interface Region Registers With Signals
286    Requires                        created-cr5-machine
287
288    # So that there's no CPU abort after starting emulation which is also why SingleStep is used.
289    Execute Command                 machine LoadPlatformDescriptionFromString "mem: Memory.MappedMemory @ sysbus 0x0 { size: 0x10000 }"
290
291    # Base can be up to 20 bits.
292    Execute Command                 ${SIGNALS_UNIT} SetSignalFromAddress "PPHBASE" 0x12345000
293    Execute Command                 ${SIGNALS_UNIT} SetSignalFromAddress "PPXBASE" 0x60007000
294    Execute Command                 ${SIGNALS_UNIT} SetSignalFromAddress "PPVBASE" 0x00089000
295
296    # Size can be up to 5 bits.
297    Execute Command                 ${SIGNALS_UNIT} SetSignal "PPHSIZE" 0x1F
298    Execute Command                 ${SIGNALS_UNIT} SetSignal "PPXSIZE" 0x10
299    Execute Command                 ${SIGNALS_UNIT} SetSignal "PPVSIZE" 0x0F
300
301    FOR  ${i}  IN RANGE  2
302        # Init is a per-cpu signal, there's no init signal for Virtual AXI Interface Region Register (PPVR).
303        Execute Command                 ${SIGNALS_UNIT} SetSignalStateForCPU "INITPPH" false cpu${i}
304        Execute Command                 ${SIGNALS_UNIT} SetSignalStateForCPU "INITPPX" true cpu${i}
305
306        # Configuration signals take effect on CPU out of reset.
307        Verify Command Output As Integer  0x0  cpu${i} GetSystemRegisterValue "PPHR"
308        Verify Command Output As Integer  0x0  cpu${i} GetSystemRegisterValue "PPXR"
309        Verify Command Output As Integer  0x0  cpu${i} GetSystemRegisterValue "PPVR"
310
311        # Continuous code execution would quickly reach 0x10000 and cause CPU abort.
312        Execute Command    cpu${i} ExecutionMode SingleStep
313    END
314
315    Start Emulation
316
317    FOR  ${i}  IN RANGE  2
318        Verify Command Output As Integer  ${{ hex(0x12345000 | (0x1F << 2) | 0) }}  cpu${i} GetSystemRegisterValue "PPHR"
319        Verify Command Output As Integer  ${{ hex(0x60007000 | (0x10 << 2) | 1) }}  cpu${i} GetSystemRegisterValue "PPXR"
320        Verify Command Output As Integer  ${{ hex(0x00089000 | (0x0F << 2) | 0) }}  cpu${i} GetSystemRegisterValue "PPVR"
321    END
322