blob: 479a612b4ec2f469fb54293e0245f95be1d9e8d0 [file] [log] [blame]
Love Kumard899e022024-01-19 11:06:41 +05301# SPDX-License-Identifier: GPL-2.0
2# (C) Copyright 2023, Advanced Micro Devices, Inc.
3
4import pytest
5import random
6import string
7import test_net
8
9"""
10Note: This test relies on boardenv_* containing configuration values to define
11RPU applications information for AMD's ZynqMP SoC which contains, application
12names, processors, address where it is built, expected output and the tftp load
13addresses. This test will be automatically skipped without this.
14
15It also relies on dhcp or setup_static net test to support tftp to load
16application on DDR. All the environment parameters are stored sequentially.
17The length of all parameters values should be same. For example, if 2 app_names
18are defined in a list as a value of parameter 'app_name' then the other
19parameters value also should have a list with 2 items.
20It will run RPU cases for all the applications defined in boardenv_*
21configuration file.
22
23Example:
24env__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
36def 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
68def ret_code(u_boot_console):
69 return u_boot_console.run_command('echo $?')
70
71# Initialize tcm
72def tcminit(u_boot_console, rpu_mode):
73 output = u_boot_console.run_command('zynqmp tcminit %s' % rpu_mode)
74 assert 'Initializing TCM overwrites TCM content' in output
75 return ret_code(u_boot_console)
76
77# Load application in DDR
78def 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
88def 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# Load apps on RPU cores
93def rpu_apps_load(u_boot_console, rpu_mode):
94 apps, procs, cpu_nums, addrs, outputs, tftp_addrs = get_rpu_apps_env(
95 u_boot_console)
96 test_net.test_net_dhcp(u_boot_console)
97 if not test_net.net_set_up:
98 test_net.test_net_setup_static(u_boot_console)
99
100 try:
101 assert tcminit(u_boot_console, rpu_mode).endswith('0')
102
103 for i in range(len(apps)):
104 if rpu_mode == 'lockstep' and procs[i] != 'rpu0':
105 continue
106
107 load_app_ddr(u_boot_console, tftp_addrs[i], apps[i])
108 rel_addr = int(addrs[i] + 0x3C)
109
110 # Release cpu at app load address
111 cpu_num = cpu_nums[i]
112 cmd = 'cpu %d release %x %s' % (cpu_num, rel_addr, rpu_mode)
113 output = u_boot_console.run_command(cmd)
114 exp_op = f'Using TCM jump trampoline for address {hex(rel_addr)}'
115 assert exp_op in output
116 assert f'R5 {rpu_mode} mode' in output
117 u_boot_console.wait_for(outputs[i])
118 assert ret_code(u_boot_console).endswith('0')
119 finally:
120 disable_cpus(u_boot_console, cpu_nums)
121
122@pytest.mark.buildconfigspec('cmd_zynqmp')
123def test_zynqmp_rpu_app_load_split(u_boot_console):
124 rpu_apps_load(u_boot_console, 'split')
125
126@pytest.mark.buildconfigspec('cmd_zynqmp')
127def test_zynqmp_rpu_app_load_lockstep(u_boot_console):
128 rpu_apps_load(u_boot_console, 'lockstep')
129
130@pytest.mark.buildconfigspec('cmd_zynqmp')
131def test_zynqmp_rpu_app_load_negative(u_boot_console):
132 apps, procs, cpu_nums, addrs, outputs, tftp_addrs = get_rpu_apps_env(
133 u_boot_console)
134
135 # Invalid commands
136 u_boot_console.run_command('zynqmp tcminit mode')
137 assert ret_code(u_boot_console).endswith('1')
138
139 rand_str = ''.join(random.choices(string.ascii_lowercase, k=4))
140 u_boot_console.run_command('zynqmp tcminit %s' % rand_str)
141 assert ret_code(u_boot_console).endswith('1')
142
143 rand_num = random.randint(2, 100)
144 u_boot_console.run_command('zynqmp tcminit %d' % rand_num)
145 assert ret_code(u_boot_console).endswith('1')
146
147 test_net.test_net_dhcp(u_boot_console)
148 if not test_net.net_set_up:
149 test_net.test_net_setup_static(u_boot_console)
150
151 try:
152 rpu_mode = 'split'
153 assert tcminit(u_boot_console, rpu_mode).endswith('0')
154
155 for i in range(len(apps)):
156 load_app_ddr(u_boot_console, tftp_addrs[i], apps[i])
157
158 # Run in split mode at different load address
159 rel_addr = int(addrs[i]) + random.randint(200, 1000)
160 cpu_num = cpu_nums[i]
161 cmd = 'cpu %d release %x %s' % (cpu_num, rel_addr, rpu_mode)
162 output = u_boot_console.run_command(cmd)
163 exp_op = f'Using TCM jump trampoline for address {hex(rel_addr)}'
164 assert exp_op in output
165 assert f'R5 {rpu_mode} mode' in output
166 assert not outputs[i] in output
167
168 # Invalid rpu mode
169 rand_str = ''.join(random.choices(string.ascii_lowercase, k=4))
170 cmd = 'cpu %d release %x %s' % (cpu_num, rel_addr, rand_str)
171 output = u_boot_console.run_command(cmd)
172 assert exp_op in output
173 assert f'Unsupported mode' in output
174 assert not ret_code(u_boot_console).endswith('0')
175
176 # Switch to lockstep mode, without disabling CPUs
177 rpu_mode = 'lockstep'
178 u_boot_console.run_command('zynqmp tcminit %s' % rpu_mode)
179 assert not ret_code(u_boot_console).endswith('0')
180
181 # Disable cpus
182 disable_cpus(u_boot_console, cpu_nums)
183
184 # Switch to lockstep mode, after disabling CPUs
185 output = u_boot_console.run_command('zynqmp tcminit %s' % rpu_mode)
186 assert 'Initializing TCM overwrites TCM content' in output
187 assert ret_code(u_boot_console).endswith('0')
188
189 # Run lockstep mode for RPU1
190 for i in range(len(apps)):
191 if procs[i] == 'rpu0':
192 continue
193
194 load_app_ddr(u_boot_console, tftp_addrs[i], apps[i])
195 rel_addr = int(addrs[i] + 0x3C)
196 cpu_num = cpu_nums[i]
197 cmd = 'cpu %d release %x %s' % (cpu_num, rel_addr, rpu_mode)
198 output = u_boot_console.run_command(cmd)
199 exp_op = f'Using TCM jump trampoline for address {hex(rel_addr)}'
200 assert exp_op in output
201 assert f'R5 {rpu_mode} mode' in output
202 assert u_boot_console.p.expect([outputs[i]])
203 finally:
204 disable_cpus(u_boot_console, cpu_nums)
205 # This forces the console object to be shutdown, so any subsequent test
206 # will reset the board back into U-Boot.
207 u_boot_console.drain_console()
208 u_boot_console.cleanup_spawn()