mirror of
https://github.com/u-boot/u-boot.git
synced 2025-04-16 01:44:34 +00:00

This fixture name is quite long and results in lots of verbose code. We know this is U-Boot so the 'u_boot_' part is not necessary. But it is also a bit of a misnomer, since it provides access to all the information available to tests. It is not just the console. It would be too confusing to use con as it would be confused with config and it is probably too short. So shorten it to 'ubman'. Signed-off-by: Simon Glass <sjg@chromium.org> Link: https://lore.kernel.org/u-boot/CAFLszTgPa4aT_J9h9pqeTtLCVn4x2JvLWRcWRD8NaN3uoSAtyA@mail.gmail.com/
222 lines
7.7 KiB
Python
222 lines
7.7 KiB
Python
# SPDX-License-Identifier: GPL-2.0
|
|
# (C) Copyright 2023, Advanced Micro Devices, Inc.
|
|
|
|
import pytest
|
|
import random
|
|
import string
|
|
import test_net
|
|
|
|
"""
|
|
Note: This test relies on boardenv_* containing configuration values to define
|
|
RPU applications information for AMD's ZynqMP SoC which contains, application
|
|
names, processors, address where it is built, expected output and the tftp load
|
|
addresses. This test will be automatically skipped without this.
|
|
|
|
It also relies on dhcp or setup_static net test to support tftp to load
|
|
application on DDR. All the environment parameters are stored sequentially.
|
|
The length of all parameters values should be same. For example, if 2 app_names
|
|
are defined in a list as a value of parameter 'app_name' then the other
|
|
parameters value also should have a list with 2 items.
|
|
It will run RPU cases for all the applications defined in boardenv_*
|
|
configuration file.
|
|
|
|
Example:
|
|
env__zynqmp_rpu_apps = {
|
|
'app_name': ['hello_world_r5_0_ddr.elf', 'hello_world_r5_1_ddr.elf'],
|
|
'proc': ['rpu0', 'rpu1'],
|
|
'cpu_num': [4, 5],
|
|
'addr': [0xA00000, 0xB00000],
|
|
'output': ['Successfully ran Hello World application on DDR from RPU0',
|
|
'Successfully ran Hello World application on DDR from RPU1'],
|
|
'tftp_addr': [0x100000, 0x200000],
|
|
}
|
|
"""
|
|
|
|
# Get rpu apps params from env
|
|
def get_rpu_apps_env(ubman):
|
|
rpu_apps = ubman.config.env.get('env__zynqmp_rpu_apps', False)
|
|
if not rpu_apps:
|
|
pytest.skip('ZynqMP RPU application info not defined!')
|
|
|
|
apps = rpu_apps.get('app_name', None)
|
|
if not apps:
|
|
pytest.skip('No RPU application found!')
|
|
|
|
procs = rpu_apps.get('proc', None)
|
|
if not procs:
|
|
pytest.skip('No RPU application processor provided!')
|
|
|
|
cpu_nums = rpu_apps.get('cpu_num', None)
|
|
if not cpu_nums:
|
|
pytest.skip('No CPU number for respective processor provided!')
|
|
|
|
addrs = rpu_apps.get('addr', None)
|
|
if not addrs:
|
|
pytest.skip('No RPU application build address found!')
|
|
|
|
outputs = rpu_apps.get('output', None)
|
|
if not outputs:
|
|
pytest.skip('Expected output not found!')
|
|
|
|
tftp_addrs = rpu_apps.get('tftp_addr', None)
|
|
if not tftp_addrs:
|
|
pytest.skip('TFTP address to load application not found!')
|
|
|
|
return apps, procs, cpu_nums, addrs, outputs, tftp_addrs
|
|
|
|
# Check return code
|
|
def ret_code(ubman):
|
|
return ubman.run_command('echo $?')
|
|
|
|
# Initialize tcm
|
|
def tcminit(ubman, rpu_mode):
|
|
output = ubman.run_command(f'zynqmp tcminit {rpu_mode}')
|
|
assert 'Initializing TCM overwrites TCM content' in output
|
|
return ret_code(ubman)
|
|
|
|
# Load application in DDR
|
|
def load_app_ddr(ubman, tftp_addr, app):
|
|
output = ubman.run_command('tftpboot %x %s' % (tftp_addr, app))
|
|
assert 'TIMEOUT' not in output
|
|
assert 'Bytes transferred = ' in output
|
|
|
|
# Load elf
|
|
ubman.run_command('bootelf -p %x' % tftp_addr)
|
|
assert ret_code(ubman).endswith('0')
|
|
|
|
# Disable cpus
|
|
def disable_cpus(ubman, cpu_nums):
|
|
for num in cpu_nums:
|
|
ubman.run_command(f'cpu {num} disable')
|
|
|
|
# Get random RPU mode between string and integer
|
|
def get_rpu_mode(rpu_mode):
|
|
if rpu_mode == 0 or rpu_mode == 'lockstep':
|
|
return random.choice(['lockstep', 0])
|
|
elif rpu_mode == 1 or rpu_mode == 'split':
|
|
return random.choice(['split', 1])
|
|
|
|
# Load apps on RPU cores
|
|
def rpu_apps_load(ubman, rpu_mode):
|
|
apps, procs, cpu_nums, addrs, outputs, tftp_addrs = get_rpu_apps_env(
|
|
ubman)
|
|
test_net.test_net_dhcp(ubman)
|
|
if not test_net.net_set_up:
|
|
test_net.test_net_setup_static(ubman)
|
|
|
|
try:
|
|
assert tcminit(ubman, get_rpu_mode(rpu_mode)).endswith('0')
|
|
|
|
for i in range(len(apps)):
|
|
if rpu_mode == 'lockstep' and procs[i] != 'rpu0':
|
|
continue
|
|
|
|
load_app_ddr(ubman, tftp_addrs[i], apps[i])
|
|
rel_addr = hex(int(addrs[i] + 0x3C))
|
|
|
|
# Release cpu at app load address
|
|
cpu_num = cpu_nums[i]
|
|
cmd = f'cpu {cpu_num} release {rel_addr} {rpu_mode}'
|
|
output = ubman.run_command(cmd)
|
|
exp_op = f'Using TCM jump trampoline for address {rel_addr}'
|
|
assert exp_op in output
|
|
assert f'R5 {rpu_mode} mode' in output
|
|
ubman.wait_for(outputs[i])
|
|
assert ret_code(ubman).endswith('0')
|
|
finally:
|
|
disable_cpus(ubman, cpu_nums)
|
|
|
|
@pytest.mark.buildconfigspec('cmd_zynqmp')
|
|
def test_zynqmp_rpu_app_load_split(ubman):
|
|
rpu_apps_load(ubman, 'split')
|
|
|
|
@pytest.mark.buildconfigspec('cmd_zynqmp')
|
|
def test_zynqmp_rpu_app_load_lockstep(ubman):
|
|
rpu_apps_load(ubman, 'lockstep')
|
|
|
|
@pytest.mark.buildconfigspec('cmd_zynqmp')
|
|
def test_zynqmp_rpu_app_load_negative(ubman):
|
|
apps, procs, cpu_nums, addrs, outputs, tftp_addrs = get_rpu_apps_env(
|
|
ubman)
|
|
|
|
# Invalid commands
|
|
rand_str = ''.join(random.choices(string.ascii_lowercase, k=4))
|
|
rand_num = random.randint(2, 100)
|
|
inv_modes = ['mode', rand_str, rand_num, 'splittt', 'locksteppp', '00', 11]
|
|
|
|
for mode in inv_modes:
|
|
ubman.run_command(f'zynqmp tcminit {mode}')
|
|
assert ret_code(ubman).endswith('1')
|
|
|
|
test_net.test_net_dhcp(ubman)
|
|
if not test_net.net_set_up:
|
|
test_net.test_net_setup_static(ubman)
|
|
|
|
try:
|
|
rpu_mode = 'split'
|
|
assert tcminit(ubman, get_rpu_mode(rpu_mode)).endswith('0')
|
|
|
|
inv_modes += [0, 1]
|
|
for i in range(len(apps)):
|
|
load_app_ddr(ubman, tftp_addrs[i], apps[i])
|
|
|
|
# Run in split mode at different load address
|
|
rel_addr = hex(int(addrs[i]) + random.randint(200, 1000))
|
|
cpu_num = cpu_nums[i]
|
|
cmd = f'cpu {cpu_num} release {rel_addr} {rpu_mode}'
|
|
output = ubman.run_command(cmd)
|
|
exp_op = f'Using TCM jump trampoline for address {rel_addr}'
|
|
assert exp_op in output
|
|
assert f'R5 {rpu_mode} mode' in output
|
|
assert not outputs[i] in output
|
|
|
|
# Invalid rpu mode
|
|
for mode in inv_modes:
|
|
cmd = f'cpu {cpu_num} release {rel_addr} {mode}'
|
|
output = ubman.run_command(cmd)
|
|
assert exp_op in output
|
|
assert f'Unsupported mode' in output
|
|
assert not ret_code(ubman).endswith('0')
|
|
|
|
# Switch to lockstep mode, without disabling CPUs
|
|
rpu_mode = 'lockstep'
|
|
output = ubman.run_command(
|
|
f'zynqmp tcminit {get_rpu_mode(rpu_mode)}'
|
|
)
|
|
assert 'ERROR: ' in output
|
|
|
|
# Disable cpus
|
|
disable_cpus(ubman, cpu_nums)
|
|
|
|
# Switch to lockstep mode, after disabling CPUs
|
|
output = ubman.run_command(
|
|
f'zynqmp tcminit {get_rpu_mode(rpu_mode)}'
|
|
)
|
|
assert 'Initializing TCM overwrites TCM content' in output
|
|
assert ret_code(ubman).endswith('0')
|
|
|
|
# Run lockstep mode for RPU1/RPU0
|
|
for i in range(len(apps)):
|
|
load_app_ddr(ubman, tftp_addrs[i], apps[i])
|
|
rel_addr = hex(int(addrs[i] + 0x3C))
|
|
cpu_num = cpu_nums[i]
|
|
cmd = f'cpu {cpu_num} release {rel_addr} {rpu_mode}'
|
|
output = ubman.run_command(cmd)
|
|
exp_op = f'Using TCM jump trampoline for address {rel_addr}'
|
|
assert exp_op in output
|
|
|
|
if procs[i] == 'rpu1':
|
|
assert 'Lockstep mode should run on ZYNQMP_CORE_RPU0' in output
|
|
assert not ret_code(ubman).endswith('0')
|
|
elif procs[i] == 'rpu0':
|
|
assert f'R5 {rpu_mode} mode' in output
|
|
ubman.wait_for(outputs[i])
|
|
assert ret_code(ubman).endswith('0')
|
|
else:
|
|
assert False, 'ERROR: Invalid processor!'
|
|
finally:
|
|
disable_cpus(ubman, cpu_nums)
|
|
# This forces the console object to be shutdown, so any subsequent test
|
|
# will reset the board back into U-Boot.
|
|
ubman.drain_console()
|
|
ubman.cleanup_spawn()
|