blob: cda8c9203b74a78cc4cc3e41322871e6f793c33f [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
Simon Glassddba5202025-02-09 09:07:14 -070036def get_rpu_apps_env(ubman):
37 rpu_apps = ubman.config.env.get('env__zynqmp_rpu_apps', False)
Love Kumard899e022024-01-19 11:06:41 +053038 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
Simon Glassddba5202025-02-09 09:07:14 -070068def ret_code(ubman):
69 return ubman.run_command('echo $?')
Love Kumard899e022024-01-19 11:06:41 +053070
71# Initialize tcm
Simon Glassddba5202025-02-09 09:07:14 -070072def tcminit(ubman, rpu_mode):
73 output = ubman.run_command(f'zynqmp tcminit {rpu_mode}')
Love Kumard899e022024-01-19 11:06:41 +053074 assert 'Initializing TCM overwrites TCM content' in output
Simon Glassddba5202025-02-09 09:07:14 -070075 return ret_code(ubman)
Love Kumard899e022024-01-19 11:06:41 +053076
77# Load application in DDR
Simon Glassddba5202025-02-09 09:07:14 -070078def load_app_ddr(ubman, tftp_addr, app):
79 output = ubman.run_command('tftpboot %x %s' % (tftp_addr, app))
Love Kumard899e022024-01-19 11:06:41 +053080 assert 'TIMEOUT' not in output
81 assert 'Bytes transferred = ' in output
82
83 # Load elf
Simon Glassddba5202025-02-09 09:07:14 -070084 ubman.run_command('bootelf -p %x' % tftp_addr)
85 assert ret_code(ubman).endswith('0')
Love Kumard899e022024-01-19 11:06:41 +053086
87# Disable cpus
Simon Glassddba5202025-02-09 09:07:14 -070088def disable_cpus(ubman, cpu_nums):
Love Kumard899e022024-01-19 11:06:41 +053089 for num in cpu_nums:
Simon Glassddba5202025-02-09 09:07:14 -070090 ubman.run_command(f'cpu {num} disable')
Love Kumard899e022024-01-19 11:06:41 +053091
Love Kumar0d458242024-11-15 17:32:02 +053092# Get random RPU mode between string and integer
93def 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
Love Kumard899e022024-01-19 11:06:41 +053099# Load apps on RPU cores
Simon Glassddba5202025-02-09 09:07:14 -0700100def rpu_apps_load(ubman, rpu_mode):
Love Kumard899e022024-01-19 11:06:41 +0530101 apps, procs, cpu_nums, addrs, outputs, tftp_addrs = get_rpu_apps_env(
Simon Glassddba5202025-02-09 09:07:14 -0700102 ubman)
103 test_net.test_net_dhcp(ubman)
Love Kumard899e022024-01-19 11:06:41 +0530104 if not test_net.net_set_up:
Simon Glassddba5202025-02-09 09:07:14 -0700105 test_net.test_net_setup_static(ubman)
Love Kumard899e022024-01-19 11:06:41 +0530106
107 try:
Simon Glassddba5202025-02-09 09:07:14 -0700108 assert tcminit(ubman, get_rpu_mode(rpu_mode)).endswith('0')
Love Kumard899e022024-01-19 11:06:41 +0530109
110 for i in range(len(apps)):
111 if rpu_mode == 'lockstep' and procs[i] != 'rpu0':
112 continue
113
Simon Glassddba5202025-02-09 09:07:14 -0700114 load_app_ddr(ubman, tftp_addrs[i], apps[i])
Love Kumar0d458242024-11-15 17:32:02 +0530115 rel_addr = hex(int(addrs[i] + 0x3C))
Love Kumard899e022024-01-19 11:06:41 +0530116
117 # Release cpu at app load address
118 cpu_num = cpu_nums[i]
Love Kumar0d458242024-11-15 17:32:02 +0530119 cmd = f'cpu {cpu_num} release {rel_addr} {rpu_mode}'
Simon Glassddba5202025-02-09 09:07:14 -0700120 output = ubman.run_command(cmd)
Love Kumar0d458242024-11-15 17:32:02 +0530121 exp_op = f'Using TCM jump trampoline for address {rel_addr}'
Love Kumard899e022024-01-19 11:06:41 +0530122 assert exp_op in output
123 assert f'R5 {rpu_mode} mode' in output
Simon Glassddba5202025-02-09 09:07:14 -0700124 ubman.wait_for(outputs[i])
125 assert ret_code(ubman).endswith('0')
Love Kumard899e022024-01-19 11:06:41 +0530126 finally:
Simon Glassddba5202025-02-09 09:07:14 -0700127 disable_cpus(ubman, cpu_nums)
Love Kumard899e022024-01-19 11:06:41 +0530128
129@pytest.mark.buildconfigspec('cmd_zynqmp')
Simon Glassddba5202025-02-09 09:07:14 -0700130def test_zynqmp_rpu_app_load_split(ubman):
131 rpu_apps_load(ubman, 'split')
Love Kumard899e022024-01-19 11:06:41 +0530132
133@pytest.mark.buildconfigspec('cmd_zynqmp')
Simon Glassddba5202025-02-09 09:07:14 -0700134def test_zynqmp_rpu_app_load_lockstep(ubman):
135 rpu_apps_load(ubman, 'lockstep')
Love Kumard899e022024-01-19 11:06:41 +0530136
137@pytest.mark.buildconfigspec('cmd_zynqmp')
Simon Glassddba5202025-02-09 09:07:14 -0700138def test_zynqmp_rpu_app_load_negative(ubman):
Love Kumard899e022024-01-19 11:06:41 +0530139 apps, procs, cpu_nums, addrs, outputs, tftp_addrs = get_rpu_apps_env(
Simon Glassddba5202025-02-09 09:07:14 -0700140 ubman)
Love Kumard899e022024-01-19 11:06:41 +0530141
142 # Invalid commands
Love Kumard899e022024-01-19 11:06:41 +0530143 rand_str = ''.join(random.choices(string.ascii_lowercase, k=4))
Love Kumard899e022024-01-19 11:06:41 +0530144 rand_num = random.randint(2, 100)
Love Kumar0d458242024-11-15 17:32:02 +0530145 inv_modes = ['mode', rand_str, rand_num, 'splittt', 'locksteppp', '00', 11]
146
147 for mode in inv_modes:
Simon Glassddba5202025-02-09 09:07:14 -0700148 ubman.run_command(f'zynqmp tcminit {mode}')
149 assert ret_code(ubman).endswith('1')
Love Kumard899e022024-01-19 11:06:41 +0530150
Simon Glassddba5202025-02-09 09:07:14 -0700151 test_net.test_net_dhcp(ubman)
Love Kumard899e022024-01-19 11:06:41 +0530152 if not test_net.net_set_up:
Simon Glassddba5202025-02-09 09:07:14 -0700153 test_net.test_net_setup_static(ubman)
Love Kumard899e022024-01-19 11:06:41 +0530154
155 try:
156 rpu_mode = 'split'
Simon Glassddba5202025-02-09 09:07:14 -0700157 assert tcminit(ubman, get_rpu_mode(rpu_mode)).endswith('0')
Love Kumard899e022024-01-19 11:06:41 +0530158
Love Kumar0d458242024-11-15 17:32:02 +0530159 inv_modes += [0, 1]
Love Kumard899e022024-01-19 11:06:41 +0530160 for i in range(len(apps)):
Simon Glassddba5202025-02-09 09:07:14 -0700161 load_app_ddr(ubman, tftp_addrs[i], apps[i])
Love Kumard899e022024-01-19 11:06:41 +0530162
163 # Run in split mode at different load address
Love Kumar0d458242024-11-15 17:32:02 +0530164 rel_addr = hex(int(addrs[i]) + random.randint(200, 1000))
Love Kumard899e022024-01-19 11:06:41 +0530165 cpu_num = cpu_nums[i]
Love Kumar0d458242024-11-15 17:32:02 +0530166 cmd = f'cpu {cpu_num} release {rel_addr} {rpu_mode}'
Simon Glassddba5202025-02-09 09:07:14 -0700167 output = ubman.run_command(cmd)
Love Kumar0d458242024-11-15 17:32:02 +0530168 exp_op = f'Using TCM jump trampoline for address {rel_addr}'
Love Kumard899e022024-01-19 11:06:41 +0530169 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
Love Kumar0d458242024-11-15 17:32:02 +0530174 for mode in inv_modes:
175 cmd = f'cpu {cpu_num} release {rel_addr} {mode}'
Simon Glassddba5202025-02-09 09:07:14 -0700176 output = ubman.run_command(cmd)
Love Kumar0d458242024-11-15 17:32:02 +0530177 assert exp_op in output
178 assert f'Unsupported mode' in output
Simon Glassddba5202025-02-09 09:07:14 -0700179 assert not ret_code(ubman).endswith('0')
Love Kumard899e022024-01-19 11:06:41 +0530180
181 # Switch to lockstep mode, without disabling CPUs
182 rpu_mode = 'lockstep'
Simon Glassddba5202025-02-09 09:07:14 -0700183 output = ubman.run_command(
Love Kumar0d458242024-11-15 17:32:02 +0530184 f'zynqmp tcminit {get_rpu_mode(rpu_mode)}'
185 )
186 assert 'ERROR: ' in output
Love Kumard899e022024-01-19 11:06:41 +0530187
188 # Disable cpus
Simon Glassddba5202025-02-09 09:07:14 -0700189 disable_cpus(ubman, cpu_nums)
Love Kumard899e022024-01-19 11:06:41 +0530190
191 # Switch to lockstep mode, after disabling CPUs
Simon Glassddba5202025-02-09 09:07:14 -0700192 output = ubman.run_command(
Love Kumar0d458242024-11-15 17:32:02 +0530193 f'zynqmp tcminit {get_rpu_mode(rpu_mode)}'
194 )
Love Kumard899e022024-01-19 11:06:41 +0530195 assert 'Initializing TCM overwrites TCM content' in output
Simon Glassddba5202025-02-09 09:07:14 -0700196 assert ret_code(ubman).endswith('0')
Love Kumard899e022024-01-19 11:06:41 +0530197
Love Kumar0d458242024-11-15 17:32:02 +0530198 # Run lockstep mode for RPU1/RPU0
Love Kumard899e022024-01-19 11:06:41 +0530199 for i in range(len(apps)):
Simon Glassddba5202025-02-09 09:07:14 -0700200 load_app_ddr(ubman, tftp_addrs[i], apps[i])
Love Kumar0d458242024-11-15 17:32:02 +0530201 rel_addr = hex(int(addrs[i] + 0x3C))
Love Kumard899e022024-01-19 11:06:41 +0530202 cpu_num = cpu_nums[i]
Love Kumar0d458242024-11-15 17:32:02 +0530203 cmd = f'cpu {cpu_num} release {rel_addr} {rpu_mode}'
Simon Glassddba5202025-02-09 09:07:14 -0700204 output = ubman.run_command(cmd)
Love Kumar0d458242024-11-15 17:32:02 +0530205 exp_op = f'Using TCM jump trampoline for address {rel_addr}'
Love Kumard899e022024-01-19 11:06:41 +0530206 assert exp_op in output
Love Kumar0d458242024-11-15 17:32:02 +0530207
208 if procs[i] == 'rpu1':
209 assert 'Lockstep mode should run on ZYNQMP_CORE_RPU0' in output
Simon Glassddba5202025-02-09 09:07:14 -0700210 assert not ret_code(ubman).endswith('0')
Love Kumar0d458242024-11-15 17:32:02 +0530211 elif procs[i] == 'rpu0':
212 assert f'R5 {rpu_mode} mode' in output
Simon Glassddba5202025-02-09 09:07:14 -0700213 ubman.wait_for(outputs[i])
214 assert ret_code(ubman).endswith('0')
Love Kumar0d458242024-11-15 17:32:02 +0530215 else:
216 assert False, 'ERROR: Invalid processor!'
Love Kumard899e022024-01-19 11:06:41 +0530217 finally:
Simon Glassddba5202025-02-09 09:07:14 -0700218 disable_cpus(ubman, cpu_nums)
Love Kumard899e022024-01-19 11:06:41 +0530219 # This forces the console object to be shutdown, so any subsequent test
220 # will reset the board back into U-Boot.
Simon Glassddba5202025-02-09 09:07:14 -0700221 ubman.drain_console()
222 ubman.cleanup_spawn()