]> Git Repo - J-u-boot.git/blob - test/py/tests/test_zynqmp_rpu.py
Merge tag 'u-boot-imx-master-20250127' of https://gitlab.denx.de/u-boot/custodians...
[J-u-boot.git] / test / py / tests / test_zynqmp_rpu.py
1 # SPDX-License-Identifier: GPL-2.0
2 # (C) Copyright 2023, Advanced Micro Devices, Inc.
3
4 import pytest
5 import random
6 import string
7 import test_net
8
9 """
10 Note: This test relies on boardenv_* containing configuration values to define
11 RPU applications information for AMD's ZynqMP SoC which contains, application
12 names, processors, address where it is built, expected output and the tftp load
13 addresses. This test will be automatically skipped without this.
14
15 It also relies on dhcp or setup_static net test to support tftp to load
16 application on DDR. All the environment parameters are stored sequentially.
17 The length of all parameters values should be same. For example, if 2 app_names
18 are defined in a list as a value of parameter 'app_name' then the other
19 parameters value also should have a list with 2 items.
20 It will run RPU cases for all the applications defined in boardenv_*
21 configuration file.
22
23 Example:
24 env__zynqmp_rpu_apps = {
25     'app_name': ['hello_world_r5_0_ddr.elf', 'hello_world_r5_1_ddr.elf'],
26     'proc': ['rpu0', 'rpu1'],
27     'cpu_num': [4, 5],
28     'addr': [0xA00000, 0xB00000],
29     'output': ['Successfully ran Hello World application on DDR from RPU0',
30                'Successfully ran Hello World application on DDR from RPU1'],
31     'tftp_addr': [0x100000, 0x200000],
32 }
33 """
34
35 # Get rpu apps params from env
36 def get_rpu_apps_env(u_boot_console):
37     rpu_apps = u_boot_console.config.env.get('env__zynqmp_rpu_apps', False)
38     if not rpu_apps:
39         pytest.skip('ZynqMP RPU application info not defined!')
40
41     apps = rpu_apps.get('app_name', None)
42     if not apps:
43         pytest.skip('No RPU application found!')
44
45     procs = rpu_apps.get('proc', None)
46     if not procs:
47         pytest.skip('No RPU application processor provided!')
48
49     cpu_nums = rpu_apps.get('cpu_num', None)
50     if not cpu_nums:
51         pytest.skip('No CPU number for respective processor provided!')
52
53     addrs = rpu_apps.get('addr', None)
54     if not addrs:
55         pytest.skip('No RPU application build address found!')
56
57     outputs = rpu_apps.get('output', None)
58     if not outputs:
59         pytest.skip('Expected output not found!')
60
61     tftp_addrs = rpu_apps.get('tftp_addr', None)
62     if not tftp_addrs:
63         pytest.skip('TFTP address to load application not found!')
64
65     return apps, procs, cpu_nums, addrs, outputs, tftp_addrs
66
67 # Check return code
68 def ret_code(u_boot_console):
69     return u_boot_console.run_command('echo $?')
70
71 # Initialize tcm
72 def tcminit(u_boot_console, rpu_mode):
73     output = u_boot_console.run_command(f'zynqmp tcminit {rpu_mode}')
74     assert 'Initializing TCM overwrites TCM content' in output
75     return ret_code(u_boot_console)
76
77 # Load application in DDR
78 def load_app_ddr(u_boot_console, tftp_addr, app):
79     output = u_boot_console.run_command('tftpboot %x %s' % (tftp_addr, app))
80     assert 'TIMEOUT' not in output
81     assert 'Bytes transferred = ' in output
82
83     # Load elf
84     u_boot_console.run_command('bootelf -p %x' % tftp_addr)
85     assert ret_code(u_boot_console).endswith('0')
86
87 # Disable cpus
88 def disable_cpus(u_boot_console, cpu_nums):
89     for num in cpu_nums:
90         u_boot_console.run_command(f'cpu {num} disable')
91
92 # Get random RPU mode between string and integer
93 def get_rpu_mode(rpu_mode):
94     if rpu_mode == 0 or rpu_mode == 'lockstep':
95         return random.choice(['lockstep', 0])
96     elif rpu_mode == 1 or rpu_mode == 'split':
97         return random.choice(['split', 1])
98
99 # Load apps on RPU cores
100 def rpu_apps_load(u_boot_console, rpu_mode):
101     apps, procs, cpu_nums, addrs, outputs, tftp_addrs = get_rpu_apps_env(
102         u_boot_console)
103     test_net.test_net_dhcp(u_boot_console)
104     if not test_net.net_set_up:
105         test_net.test_net_setup_static(u_boot_console)
106
107     try:
108         assert tcminit(u_boot_console, get_rpu_mode(rpu_mode)).endswith('0')
109
110         for i in range(len(apps)):
111             if rpu_mode == 'lockstep' and procs[i] != 'rpu0':
112                 continue
113
114             load_app_ddr(u_boot_console, tftp_addrs[i], apps[i])
115             rel_addr = hex(int(addrs[i] + 0x3C))
116
117             # Release cpu at app load address
118             cpu_num = cpu_nums[i]
119             cmd = f'cpu {cpu_num} release {rel_addr} {rpu_mode}'
120             output = u_boot_console.run_command(cmd)
121             exp_op = f'Using TCM jump trampoline for address {rel_addr}'
122             assert exp_op in output
123             assert f'R5 {rpu_mode} mode' in output
124             u_boot_console.wait_for(outputs[i])
125             assert ret_code(u_boot_console).endswith('0')
126     finally:
127         disable_cpus(u_boot_console, cpu_nums)
128
129 @pytest.mark.buildconfigspec('cmd_zynqmp')
130 def test_zynqmp_rpu_app_load_split(u_boot_console):
131     rpu_apps_load(u_boot_console, 'split')
132
133 @pytest.mark.buildconfigspec('cmd_zynqmp')
134 def test_zynqmp_rpu_app_load_lockstep(u_boot_console):
135     rpu_apps_load(u_boot_console, 'lockstep')
136
137 @pytest.mark.buildconfigspec('cmd_zynqmp')
138 def test_zynqmp_rpu_app_load_negative(u_boot_console):
139     apps, procs, cpu_nums, addrs, outputs, tftp_addrs = get_rpu_apps_env(
140         u_boot_console)
141
142     # Invalid commands
143     rand_str = ''.join(random.choices(string.ascii_lowercase, k=4))
144     rand_num = random.randint(2, 100)
145     inv_modes = ['mode', rand_str, rand_num, 'splittt', 'locksteppp', '00', 11]
146
147     for mode in inv_modes:
148         u_boot_console.run_command(f'zynqmp tcminit {mode}')
149         assert ret_code(u_boot_console).endswith('1')
150
151     test_net.test_net_dhcp(u_boot_console)
152     if not test_net.net_set_up:
153         test_net.test_net_setup_static(u_boot_console)
154
155     try:
156         rpu_mode = 'split'
157         assert tcminit(u_boot_console, get_rpu_mode(rpu_mode)).endswith('0')
158
159         inv_modes += [0, 1]
160         for i in range(len(apps)):
161             load_app_ddr(u_boot_console, tftp_addrs[i], apps[i])
162
163             # Run in split mode at different load address
164             rel_addr = hex(int(addrs[i]) + random.randint(200, 1000))
165             cpu_num = cpu_nums[i]
166             cmd = f'cpu {cpu_num} release {rel_addr} {rpu_mode}'
167             output = u_boot_console.run_command(cmd)
168             exp_op = f'Using TCM jump trampoline for address {rel_addr}'
169             assert exp_op in output
170             assert f'R5 {rpu_mode} mode' in output
171             assert not outputs[i] in output
172
173             # Invalid rpu mode
174             for mode in inv_modes:
175                 cmd = f'cpu {cpu_num} release {rel_addr} {mode}'
176                 output = u_boot_console.run_command(cmd)
177                 assert exp_op in output
178                 assert f'Unsupported mode' in output
179                 assert not ret_code(u_boot_console).endswith('0')
180
181         # Switch to lockstep mode, without disabling CPUs
182         rpu_mode = 'lockstep'
183         output = u_boot_console.run_command(
184             f'zynqmp tcminit {get_rpu_mode(rpu_mode)}'
185         )
186         assert 'ERROR: ' in output
187
188         # Disable cpus
189         disable_cpus(u_boot_console, cpu_nums)
190
191         # Switch to lockstep mode, after disabling CPUs
192         output = u_boot_console.run_command(
193             f'zynqmp tcminit {get_rpu_mode(rpu_mode)}'
194         )
195         assert 'Initializing TCM overwrites TCM content' in output
196         assert ret_code(u_boot_console).endswith('0')
197
198         # Run lockstep mode for RPU1/RPU0
199         for i in range(len(apps)):
200             load_app_ddr(u_boot_console, tftp_addrs[i], apps[i])
201             rel_addr = hex(int(addrs[i] + 0x3C))
202             cpu_num = cpu_nums[i]
203             cmd = f'cpu {cpu_num} release {rel_addr} {rpu_mode}'
204             output = u_boot_console.run_command(cmd)
205             exp_op = f'Using TCM jump trampoline for address {rel_addr}'
206             assert exp_op in output
207
208             if procs[i] == 'rpu1':
209                 assert 'Lockstep mode should run on ZYNQMP_CORE_RPU0' in output
210                 assert not ret_code(u_boot_console).endswith('0')
211             elif procs[i] == 'rpu0':
212                 assert f'R5 {rpu_mode} mode' in output
213                 u_boot_console.wait_for(outputs[i])
214                 assert ret_code(u_boot_console).endswith('0')
215             else:
216                 assert False, 'ERROR: Invalid processor!'
217     finally:
218         disable_cpus(u_boot_console, cpu_nums)
219         # This forces the console object to be shutdown, so any subsequent test
220         # will reset the board back into U-Boot.
221         u_boot_console.drain_console()
222         u_boot_console.cleanup_spawn()
This page took 0.037247 seconds and 4 git commands to generate.