1*** Variables ***
2${PLATFORM}                         SEPARATOR=
3...                                 """                                                    ${\n}
4...                                 cpu: CPU.ARMv7A @ sysbus                               ${\n}
5...                                 ${SPACE*4}cpuType: "cortex-a9"                         ${\n}
6...                                                                                        ${\n}
7...                                 pmu: Miscellaneous.ArmPerformanceMonitoringUnit @ {    ${\n}
8...                                 ${SPACE*8}cpu;                                         ${\n}
9...                                 ${SPACE*8}sysbus new Bus.BusRangeRegistration {        ${\n}
10...                                 ${SPACE*8}${SPACE*4}address: ${MMIO_ADDRESS};          ${\n}
11...                                 ${SPACE*8}${SPACE*4}size: 0x1000                       ${\n}
12...                                 ${SPACE*8}}                                            ${\n}
13...                                 ${SPACE*4}}                                            ${\n}
14...                                 ${SPACE*4}peripheralId: ${PERIPHERAL_ID}               ${\n}
15...                                 ${SPACE*4}withProcessorIdMMIORegisters: true           ${\n}
16...                                                                                        ${\n}
17...                                 memory: Memory.MappedMemory @ sysbus 0x0               ${\n}
18...                                 ${SPACE*4}size: 0x20000                                ${\n}
19...                                 """
20
21${BOGUS_EVENT_1}                    0x1
22${BOGUS_EVENT_2}                    0xAB
23${SOFTWARE_INCREMENT_EVENT}         0x00
24${INSTRUCTIONS_EVENT}               0x8
25${CYCLES_EVENT}                     0x11
26
27${CPU_MIDR}                         0x410fc090
28${MMIO_ADDRESS}                     0xF0000000
29${MMIO_SOFTWARE_LOCK_KEY}           0xC5ACCE55
30${PERIPHERAL_ID}                    0xFEDCBA9876543210
31${REG_ID_PFR1_OFFSET}               0xD24
32${REG_MIDR_OFFSET}                  0xD00
33${REG_MPUIR_OFFSET}                 0xD10
34${REG_PMCCNTR_OFFSET}               0x07C
35${REG_PMCNTENSET_OFFSET}            0xC00
36${REG_PMCR_OFFSET}                  0xE04
37${REG_PMLAR_OFFSET}                 0xFB0  # MMIO-only register
38${REG_PMPID0_OFFSET}                0xFE0
39${REG_PMPID2_OFFSET}                0xFE8
40${REG_PMPID4_OFFSET}                0xFD0
41${REG_PMSWINC_OFFSET}               0xCA0
42${REG_PMXEVCNTR0_OFFSET}            0x000
43${REG_PMXEVCNTR30_OFFSET}           0x078
44${REG_PMXEVTYPER0_OFFSET}           0x400
45${REG_PMXEVTYPER30_OFFSET}          0x478
46${REG_TLBTR_OFFSET}                 0xD0C
47
48*** Keywords ***
49Create Machine
50    # Some keywords expect numbers to be printed as hex.
51    Execute Command                 numbersMode Hexadecimal
52
53    Execute Command                 using sysbus
54    Execute Command                 mach create
55    Execute Command                 machine LoadPlatformDescriptionFromString ${PLATFORM}
56
57    # Create infinite loop
58    Execute Command                 sysbus WriteDoubleWord 0x1000 0xE320F000  # nop
59    Execute Command                 sysbus WriteDoubleWord 0x1004 0xEAFFFFFD  # b to 0x1000
60
61    # Set predefined PerformanceInMips, so it's possible to calculate
62    # the number of expected instructions to execute in the given time frame
63    Execute Command                 cpu PerformanceInMips 100
64    Execute Command                 cpu PC 0x1000
65
66Set Register Bits
67    [Arguments]                     ${regName}  ${value}
68    ${enabledCounters}=             Execute Command  cpu.pmu GetRegister ${regName}
69    ${mask}=                        Evaluate  hex(int($enabledCounters, 16) | int($value))
70
71    Execute Command                 cpu.pmu SetRegister ${regName} ${mask}
72
73Clear Register Bits
74    [Arguments]                     ${regName}  ${value}
75    ${enabledCounters}=             Execute Command  cpu.pmu GetRegister ${regName}
76    ${mask}=                        Evaluate  hex(int($enabledCounters, 16) & ~int($value))
77
78    Execute Command                 cpu.pmu SetRegister ${regName} ${mask}
79
80Assert Bit Set
81    [Arguments]                     ${value}  ${bit}
82    ${isSet}=                       Evaluate  (${value} & (1 << ${bit})) > 0
83    Should Be True                  ${isSet}
84
85Assert Bit Unset
86    [Arguments]                     ${value}  ${bit}
87    ${isNotSet}=                    Evaluate  (${value} & (1 << ${bit})) == 0
88    Should Be True                  ${isNotSet}
89
90Enable PMU
91    Set Register Bits               "PMCR"  1
92
93Disable PMU
94    Clear Register Bits             "PMCR"  1
95
96Reset PMU Counters
97    Set Register Bits               "PMCR"  2
98
99Reset PMU Cycle Counter
100    Set Register Bits               "PMCR"  4
101
102Set Cycles Divisor 64
103    [Arguments]                     ${divisor}
104    IF  ${divisor}
105        Set Register Bits               "PMCR"  8
106    ELSE
107        Clear Register Bits             "PMCR"  8
108    END
109
110Switch Privilege Mode
111    [Arguments]                     ${privileged}
112    # use CPSR to switch between PL0/PL1
113    IF  ${privileged}  # PL1 - SVC mode
114        ${cpsr}=                        Execute Command  cpu CPSR
115        ${cpsr}=                        Evaluate  (int(${cpsr}) & ~0x1F ) | 0x13
116        Execute Command                 cpu CPSR ${cpsr}
117    ELSE  # PL0
118        ${cpsr}=                        Execute Command  cpu CPSR
119        ${cpsr}=                        Evaluate  (int(${cpsr}) & ~0x1F ) | 0x10
120        Execute Command                 cpu CPSR ${cpsr}
121    END
122
123Enable PMU Counter
124    [Arguments]                     ${counter}
125    ${value}=                       Evaluate  (1 << int($counter))
126
127    Set Register Bits               "PMCNTENSET"  ${value}
128
129Disable PMU Counter
130    [Arguments]                     ${counter}
131    ${value}=                       Evaluate  (1 << int($counter))
132
133    Execute Command                 cpu.pmu SetRegister "PMCNTENCLR" ${value}
134
135Enable Overflow Interrupt For PMU Counter
136    [Arguments]                     ${counter}
137    ${value}=                       Evaluate  (1 << int($counter))
138
139    Execute Command                 cpu.pmu SetRegister "PMINTENSET" ${value}
140
141Disable Overflow Interrupt For PMU Counter
142    [Arguments]                     ${counter}
143    ${value}=                       Evaluate  (1 << int($counter))
144
145    Execute Command                 cpu.pmu SetRegister "PMINTENCLR"  ${value}
146
147Increment Software PMU Counter
148    [Arguments]                     ${counter}
149    ${value}=                       Evaluate  (1 << int($counter))
150
151    Execute Command                 cpu.pmu SetRegister "PMSWINC" ${value}
152
153Assert PMU Counter Is Equal To
154    [Arguments]                     ${counter}  ${value}
155    ${cnt}=                         Execute Command  cpu.pmu GetCounterValue ${counter}
156
157    Should Be Equal As Integers     ${cnt}  ${value}
158
159Assert Executed Instructions Equal To
160    [Arguments]                     ${value}
161    ${executedInstructions}=        Execute Command  cpu ExecutedInstructions
162
163    Should Be Equal As Integers     ${executedInstructions}  ${value}
164
165Assert PMU Cycle Counter Equal To
166    [Arguments]                     ${value}
167    ${cycles}=                      Execute Command  cpu.pmu GetCycleCounterValue
168
169    Should Be Equal As Integers     ${cycles}  ${value}
170
171Assert PMU IRQ Is Set
172    ${irqState}=                    Execute Command  cpu.pmu IRQ
173    Should Contain                  ${irqState}  GPIO: set
174
175Assert PMU IRQ Is Unset
176    ${irqState}=                    Execute Command  cpu.pmu IRQ
177    Should Contain                  ${irqState}  GPIO: unset
178
179Assert PMU Counter Overflowed
180    [Arguments]                     ${counter}
181    # n-th bit denotes overflow status for the n-th PMU counter
182    ${overflowStatus}=              Execute Command  cpu.pmu GetRegister "PMOVSR"
183    Assert Bit Set                  ${overflowStatus}  ${counter}
184
185Assert PMU Counter Not Overflowed
186    [Arguments]                     ${counter}
187    ${overflowStatus}=              Execute Command  cpu.pmu GetRegister "PMOVSR"
188    Assert Bit Unset                ${overflowStatus}  ${counter}
189
190Assert Command Output Equal To
191    [Arguments]                     ${expectedOutput}  ${command}
192    ${output}=                      Execute Command  ${command}
193    Should Be Equal                 ${output}  ${expectedOutput}  strip_spaces=True
194
195Get ${name} Register Offset
196    ${variableName}=  Set Variable  ${{ "REG_" + "${name}" + "_OFFSET" }}
197    RETURN  ${ ${variableName} }
198
199MMIO-Accessed ${name} Should Be Equal To Value ${expectedValue}
200    ${offset}=                      Get ${name} Register Offset
201    ${output}=                      Execute Command  sysbus ReadDoubleWord ${{ ${MMIO_ADDRESS} + ${offset} }}
202    Should Be Equal As Integers     ${output}  ${expectedValue}
203
204MMIO-Accessed ${name} Should Be Equal To System Register
205    # There are no direct PMXEVCNTR and PMXEVTYPER system registers for all counters but only
206    # two such registers depending on PMSELR so PMU wrapping methods have to be used instead.
207    IF  "${name}".startswith("PMXEVCNTR")
208        ${expectedValue}=           Execute Command  cpu.pmu GetCounterValue ${{ int("${name}".replace("PMXEVCNTR", "")) }}
209    ELSE IF  "${name}".startswith("PMXEVTYPER")
210        ${expectedValue}=           Execute Command  cpu.pmu GetCounterEvent ${{ int("${name}".replace("PMXEVTYPER", "")) }}
211    ELSE
212        ${expectedValue}=           Execute Command  cpu GetSystemRegisterValue "${name}"
213    END
214
215    MMIO-Accessed ${name} Should Be Equal To Value ${expectedValue}
216
217Write ${value} To ${name} Using MMIO
218    ${offset}=                      Get ${name} Register Offset
219    Execute Command                 sysbus WriteDoubleWord ${{ ${MMIO_ADDRESS} + ${offset} }} ${value}
220
221Unlock MMIO Writes
222    Write ${MMIO_SOFTWARE_LOCK_KEY} To PMLAR Using MMIO
223
224*** Test Cases ***
225Should Count Cycles
226    Create Machine
227
228    Enable PMU
229    Enable PMU Counter              31  # Cycle counter
230
231    Execute Command                 emulation RunFor "00:00:01.12"
232
233    # Given a known PerformanceInMIPS, it can be assumed that 112 000 000 instructions have been executed
234    Assert PMU Cycle Counter Equal To  112 000 000
235    Assert Executed Instructions Equal To  112 000 000
236
237Should Count Cycles With Divisor
238    Create Machine
239    Enable PMU Counter              31  # Cycle counter
240    Enable PMU
241    Set Cycles Divisor 64           ${True}
242
243    Execute Command                 emulation RunFor "00:00:00.01"
244    Assert Executed Instructions Equal To  1000000
245    Assert PMU Cycle Counter Equal To  15625
246
247    Set Cycles Divisor 64           ${False}
248
249    Execute Command                 emulation RunFor "00:00:00.01"
250    Assert Executed Instructions Equal To  2000000
251    Assert PMU Cycle Counter Equal To  1015625
252
253Should Program PMU Counter To Count Cycles
254    Create Machine
255
256    Enable PMU
257    Execute Command                 cpu.pmu SetCounterEvent 0 ${CYCLES_EVENT}
258    Enable PMU Counter              0
259
260    Execute Command                 emulation RunFor "00:00:01.12"
261
262    # As above, given PerformanceInMIPS, we know how many instructions to expect
263    # One cycle is equal to one instruction, this is not a mistake
264    Assert Executed Instructions Equal To  112 000 000
265    Assert PMU Counter Is Equal To  0  112 000 000
266
267    # Now, an instruction should be equal to 1.25 cycles
268    Execute Command                 cpu CyclesPerInstruction 1.25
269    Execute Command                 emulation RunFor "00:00:00.01"
270
271    # Executed 1 000 000 instructions, so 1 250 000 cycles
272    Assert Executed Instructions Equal To  113 000 000
273    Assert PMU Counter Is Equal To  0  113 250 000
274
275Should Program PMU Counter To Count Instructions
276    Create Machine
277
278    # Cycles value will be used in dependent tests
279    Enable PMU Counter              31
280    Enable PMU
281    Execute Command                 cpu.pmu SetCounterEvent 0 ${INSTRUCTIONS_EVENT}
282    Enable PMU Counter              0
283
284    Execute Command                 emulation RunFor "00:00:01.12"
285    Assert Executed Instructions Equal To  112 000 000
286    Assert PMU Counter Is Equal To  0  112 000 000
287
288    Provides                        program-counter
289
290Should Reset PMU counters
291    Requires                        program-counter
292
293    Assert PMU Counter Is Equal To  0  112 000 000
294    Reset PMU Counters
295    Assert PMU Counter Is Equal To  0  0
296
297    Assert PMU Cycle Counter Equal To  112 000 000
298    Reset PMU Cycle Counter
299    Assert PMU Cycle Counter Equal To  0
300
301Should Kick Software Increment
302    Create Machine
303
304    # Configure PMU counters, only Counter 0 subscribes to Software Increment event, Counter 1 subscribes to non-implemented event
305    # So only Counter 0 is expected to be incremented
306    Execute Command                 cpu.pmu SetCounterEvent 0 ${SOFTWARE_INCREMENT_EVENT}
307    Execute Command                 cpu.pmu SetCounterEvent 1 ${BOGUS_EVENT_1}
308
309    # Verify the configured events by reading their event ids
310    ${ev1}=                         Execute Command  cpu.pmu GetCounterEvent 1
311    ${ev0}=                         Execute Command  cpu.pmu GetCounterEvent 0
312    Should Be Equal As Integers     ${ev1}  1
313    Should Be Equal As Integers     ${ev0}  0
314
315    Increment Software PMU Counter  0
316    Increment Software PMU Counter  1
317
318    # Counters and PMU are disabled, should not count
319    Assert PMU Counter Is Equal To  0  0
320    Assert PMU Counter Is Equal To  1  0
321
322    Enable PMU Counter              0
323
324    Increment Software PMU Counter  1
325    Increment Software PMU Counter  0
326
327    # Still not counting, PMU is not enabled
328    Assert PMU Counter Is Equal To  0  0
329    Assert PMU Counter Is Equal To  1  0
330    Enable PMU
331
332    Increment Software PMU Counter  0
333    Increment Software PMU Counter  1
334
335    # PMU Counter 1 is not a Software Increment, so it shouldn't increment at all
336    # Counter 0 is incremented only once, after "Enable PMU". Previous increments were invalid, since PMU was disabled
337    Assert PMU Counter Is Equal To  0  1
338    Assert PMU Counter Is Equal To  1  0
339
340Should Respect PMU Counter Pasue And Resume
341    Create Machine
342    Enable PMU
343
344    Execute Command                 cpu.pmu SetCounterEvent 1 ${CYCLES_EVENT}
345    Enable PMU Counter              1
346    Execute Command                 emulation RunFor "00:00:00.01"
347
348    Assert PMU Counter Is Equal To  1  1000000
349    Assert Executed Instructions Equal To  1000000
350
351    # Shouldn't count with disabled PMU
352    Disable PMU
353    Execute Command                 emulation RunFor "00:00:00.01"
354
355    Assert PMU Counter Is Equal To  1  1000000
356    Assert Executed Instructions Equal To  2000000
357
358    Enable PMU
359    Execute Command                 emulation RunFor "00:00:00.01"
360
361    Assert PMU Counter Is Equal To  1  2000000
362    Assert Executed Instructions Equal To  3000000
363
364    # Shouldn't count when the counter is disabled
365    Disable PMU Counter             1
366    Execute Command                 emulation RunFor "00:00:00.01"
367
368    Assert PMU Counter Is Equal To  1  2000000
369    Assert Executed Instructions Equal To  4000000
370
371    Enable PMU Counter              1
372    Execute Command                 emulation RunFor "00:00:00.01"
373
374    Assert PMU Counter Is Equal To  1  3000000
375    Assert Executed Instructions Equal To  5000000
376
377Should Trigger Cycles Overflow
378    Create Machine
379
380    Enable PMU
381
382    ## Counter 2
383    # The performance in MIPS is known, so it's possible to calculate the exact moment the counter should overflow
384    # Configure counter, so after 3 000 000 instructions it should have overflowed and have the value 2 stored
385    # so it's set to "UINT32_MAX - value + 3"
386    Execute Command                 cpu.pmu SetCounterEvent 2 ${CYCLES_EVENT}
387    Execute Command                 cpu.pmu SetCounterValue 2 0xFFD23942
388    Enable Overflow Interrupt For PMU Counter  2
389    Enable PMU Counter              2
390
391    ## Counter 1
392    Execute Command                 cpu.pmu SetCounterEvent 1 ${CYCLES_EVENT}
393    # expected to execute 1 000 000 instructions, so load "UINT32_MAX - value" to counter
394    # it is expected to overflow one instruction after
395    Execute Command                 cpu.pmu SetCounterValue 1 0xFFF0BDBF
396    Enable Overflow Interrupt For PMU Counter  1
397    Enable PMU Counter              1
398
399    # See that it didn't overflow too soon
400    Execute Command                 emulation RunFor "00:00:00.01"
401    Assert Executed Instructions Equal To  1000000
402    # The value is counter's base value "0xFFF0BDBF" + 1 000 000 expected instructions to execute
403    Assert PMU Counter Is Equal To  1  0xFFFFFFFF
404    Assert PMU Counter Not Overflowed  1
405    Assert PMU IRQ Is Unset
406
407    # It will overflow 1 instruction after, we now execute 100 000, so overflow bit has to be set
408    Execute Command                 emulation RunFor "00:00:00.001"
409    Assert PMU Counter Overflowed   1
410    Assert PMU IRQ Is Set
411
412    Provides                        cycles-overflow
413
414Should Resume Execution After Cycles Overflow
415    Requires                        cycles-overflow
416
417    Execute Command                 emulation RunFor "00:00:00.01"
418    Assert Executed Instructions Equal To  2100000
419    # instructions are counted from 0 after overflow, so instead from 1 000 000 + 100 000 subtract 1
420    Assert PMU Counter Is Equal To  1  1099999
421
422    Provides                        resumed-after-overflow
423
424Should Overflow Second Time
425    Requires                        resumed-after-overflow
426    # Clear overflow bit for counter 1
427    Execute Command                 cpu.pmu SetRegister "PMOVSR" 0x2
428
429    Execute Command                 emulation RunFor "00:00:00.009"
430    Assert Executed Instructions Equal To  3000000
431    Assert PMU Counter Is Equal To  2  2
432
433    Assert PMU Counter Overflowed   2
434
435Should Increment Bogus Event From Monitor
436    # The event is unimplemented, and there will be warnings in the logs
437    # but still can be used it in a test scenario
438    Create Machine
439
440    Enable PMU
441    Execute Command                 cpu.pmu SetCounterEvent 1 ${BOGUS_EVENT_2}
442    Enable PMU Counter              1
443
444    Execute Command                 cpu.pmu BroadcastEvent ${BOGUS_EVENT_2} 5
445    Assert PMU Counter Is Equal To  1  5
446
447    # now, let's overflow
448    Enable Overflow Interrupt For PMU Counter  1
449    Execute Command                 cpu.pmu BroadcastEvent ${BOGUS_EVENT_2} 0xFFFFFFFF
450    Assert PMU Counter Is Equal To  1  4
451
452    Assert PMU Counter Overflowed   1
453    Assert PMU IRQ Is Set
454
455Should Count Instructions With PL Masking
456    Create Machine
457
458    Enable PMU Counter              0
459    Execute Command                 cpu.pmu SetCounterEvent 0 ${INSTRUCTIONS_EVENT} ignoreCountAtPL0=false ignoreCountAtPL1=true
460    Enable PMU
461    Enable Overflow Interrupt For PMU Counter  0
462
463    Execute Command                 emulation RunFor "00:00:00.01"
464    Assert Executed Instructions Equal To  1000000
465    # The counter doesn't count at PL1, so should be zero
466    Assert PMU Counter Is Equal To  0  0
467
468    Switch Privilege Mode           ${False}
469    Execute Command                 emulation RunFor "00:00:00.01"
470    Assert Executed Instructions Equal To  2000000
471    # The PMU counter only counted in PL0, so only 1 000 000 instructions
472    Assert PMU Counter Is Equal To  0  1000000
473
474    Execute Command                 cpu.pmu SetCounterEvent 0 ${INSTRUCTIONS_EVENT} ignoreCountAtPL0=true ignoreCountAtPL1=true
475    # Now, counting at PL0 is disabled too, so PMU counter should not progress
476    Execute Command                 emulation RunFor "00:00:00.01"
477    Assert Executed Instructions Equal To  3000000
478    Assert PMU Counter Is Equal To  0  1000000
479
480    # See that the counter doesn't count and doesn't trigger overflow
481    # Configure counter, so after 3 000 000 instructions it should have overflowed and have the value 2 stored
482    # so it's set to "UINT32_MAX - value + 3"
483    # But it shouldn't count anything at PL0
484    Execute Command                 cpu.pmu SetCounterValue 0 0xFFD23942
485    Execute Command                 emulation RunFor "00:00:00.03"
486    Assert Executed Instructions Equal To  6000000
487    # No progress for the couner
488    Assert PMU Counter Is Equal To  0  0xFFD23942
489    Assert PMU Counter Not Overflowed  0
490    Assert PMU IRQ Is Unset
491
492    # Now, switch the mode back to PL1 and enable counting events there
493    Execute Command                 cpu.pmu SetCounterEvent 0 ${INSTRUCTIONS_EVENT} ignoreCountAtPL0=true ignoreCountAtPL1=false
494    Switch Privilege Mode           ${True}
495
496    # The counter hadn't progressed at all, so it's not necessary to set it's value again
497    Execute Command                 emulation RunFor "00:00:00.03"
498    Assert Executed Instructions Equal To  9000000
499    Assert PMU Counter Is Equal To  0  2
500    Assert PMU Counter Overflowed   0
501    Assert PMU IRQ Is Set
502
503Should Allow MMIO Writes Only After Disabling Software Lock
504    Create Machine
505
506    Create Log Tester               0
507    Execute Command                 logLevel -1 pmu
508    Assert Command Output Equal To  True  pmu SoftwareLockEnabled
509
510    # Try writing.
511    Write 0xAB To PMXEVTYPER0 Using MMIO
512    Wait For Log Entry              write ignored
513    Wait For Log Entry              Software Lock can be cleared by writing ${MMIO_SOFTWARE_LOCK_KEY} to the PMLAR register at ${REG_PMLAR_OFFSET}
514    MMIO-Accessed PMXEVTYPER0 Should Be Equal To Value 0
515
516    # Try unlocking with invalid key.
517    ${invalidUnlockKey}=  Set Variable  0xABCD
518    Write ${invalidUnlockKey} To PMLAR Using MMIO
519    Wait For Log Entry              Tried to disable Software Lock with invalid value ${invalidUnlockKey}, should be ${MMIO_SOFTWARE_LOCK_KEY}
520    Assert Command Output Equal To  True  pmu SoftwareLockEnabled
521
522    # Unlock.
523    Unlock MMIO Writes
524    Wait For Log Entry              Software Lock disabled
525    Assert Command Output Equal To  False  pmu SoftwareLockEnabled
526
527    # Write again.
528    Write ${BOGUS_EVENT_1} To PMXEVTYPER0 Using MMIO
529    Should Not Be In Log            write ignored
530    Wait For Log Entry              cpu: Invalid/Unimplemented event ${BOGUS_EVENT_1} selected for PMU counter 0
531    MMIO-Accessed PMXEVTYPER0 Should Be Equal To Value ${BOGUS_EVENT_1}
532
533Should Kick Software Incremented Counters Using MMIO
534    Create Machine
535    Unlock MMIO Writes
536
537    # Enable PMU.
538    Write 0x1 To PMCR Using MMIO
539
540    # Set counters 0 and 30 to software increment event and enable them.
541    Write ${SOFTWARE_INCREMENT_EVENT} To PMXEVTYPER0 Using MMIO
542    Write ${SOFTWARE_INCREMENT_EVENT} To PMXEVTYPER30 Using MMIO
543    Write ${{ (1 << 30) | 1 }} To PMCNTENSET Using MMIO
544
545    # Increment counters using both MMIO and System Registers.
546    Write 1 To PMSWINC Using MMIO
547    Write ${{ 1 << 30 }} To PMSWINC Using MMIO
548    Increment Software PMU Counter  30
549
550    # Make sure the MMIO-accessed count is valid and equal to system registers.
551    MMIO-Accessed PMXEVCNTR0 Should Be Equal To Value 1
552    MMIO-Accessed PMXEVCNTR0 Should Be Equal To System Register
553    MMIO-Accessed PMXEVCNTR30 Should Be Equal To Value 2
554    MMIO-Accessed PMXEVCNTR30 Should Be Equal To System Register
555
556Should Read Peripheral ID Using MMIO
557    Create Machine
558
559    ${peripheralId}=  Execute Command  pmu PeripheralId
560    ${peripheralId}=  Strip String     ${peripheralId}
561
562    # Peripheral ID's bits 20-23 should contain variant from bits 20-23 of MIDR.
563    Should Be Equal As Integers     ${{ ((${peripheralId}^${CPU_MIDR}) >> 20) & 0xF }}  0
564
565    # Each of PMPID0-PMPID7 contains 8 bits from PeripheralId.
566    MMIO-Accessed PMPID0 Should Be Equal To Value ${{ ${peripheralId} & 0xFF }}
567    MMIO-Accessed PMPID2 Should Be Equal To Value ${{ (${peripheralId} >> 16) & 0xFF }}
568    MMIO-Accessed PMPID4 Should Be Equal To Value ${{ (${peripheralId} >> 32) & 0xFF }}
569
570Should Read Processor ID System Registers Using MMIO
571    Create Machine
572
573    MMIO-Accessed ID_PFR1 Should Be Equal To System Register
574    MMIO-Accessed MIDR Should Be Equal To System Register
575    # MIDR is read for MPUIR because Cortex-A9 doesn't have MPU.
576    MMIO-Accessed MPUIR Should Be Equal To Value ${CPU_MIDR}
577    MMIO-Accessed TLBTR Should Be Equal To System Register
578
579Should Read PMU Registers Using MMIO
580    # Let's use a saved state with enabled cycle counter and counter 0 counting instructions.
581    Requires                        program-counter
582
583    # Compare PMU registers used in the case providing `program-counter` state.
584    MMIO-Accessed PMXEVCNTR0 Should Be Equal To System Register
585    MMIO-Accessed PMXEVTYPER0 Should Be Equal To System Register
586    MMIO-Accessed PMCCNTR Should Be Equal To System Register
587    MMIO-Accessed PMCNTENSET Should Be Equal To System Register
588    MMIO-Accessed PMCR Should Be Equal To System Register
589