Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 15 additions & 0 deletions CMake/native.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,11 @@
# as amdxdna_legacy.ko.
option(PACKAGE_LEGACY_DRIVER "Package legacy driver source" OFF)

# The VE2 shim test (test/shim_test) is not part of the normal VE2 runtime
# build. It is opt-in (e.g. built on demand by a dedicated packaging recipe)
# so the default xrt/amdxdna build does not compile or install test artifacts.
option(XDNA_BUILD_SHIM_TEST "Build test/shim_test for the VE2 edge build" OFF)

Comment thread
bisingha-xilinx marked this conversation as resolved.
# By default, build/build.sh downloads binaries to build/amdxdna_bins/
# Absolute path, cannot be used in install command as destination.
set(AMDXDNA_BINS_DIR ${CMAKE_BINARY_DIR}/../amdxdna_bins)
Expand All @@ -19,6 +24,16 @@ if(XDNA_VE2)
include(${CMAKE_CURRENT_SOURCE_DIR}/CMake/xrt_ve2.cmake)
add_subdirectory(src)

# Build the shim tests (test/shim_test) only when explicitly requested. The
# shim_test include dirs reference XRT_SUBMOD_SOURCE_DIR/BINARY_DIR, which are
# only set on the non-VE2 path above; point them at the same xrt submodule the
# VE2 build uses so the test target resolves its headers/generated sources.
if(XDNA_BUILD_SHIM_TEST)
set(XRT_SUBMOD_SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/xrt)
set(XRT_SUBMOD_BINARY_DIR ${CMAKE_CURRENT_BINARY_DIR}/xrt)
add_subdirectory(test)
endif()

else(XDNA_VE2)

# Bring in xrt git submodule before include any local directories
Expand Down
35 changes: 34 additions & 1 deletion src/shim_ve2/xdna_device.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -107,11 +107,42 @@ struct pcie_id
std::ifstream rev_f(base + "/revision");
unsigned int dev_val = 0, rev_val = 0;
if (!(dev_f >> std::hex >> dev_val) || !(rev_f >> std::hex >> rev_val))
throw xrt_core::query::sysfs_error("Failed to read device/revision from " + base);
throw xrt_core::query::sysfs_error("Failed to read device/revision from " + base + "/{device,revision}");
return { static_cast<uint16_t>(dev_val), static_cast<uint8_t>(rev_val) };
}
};

// New query to get the device id
struct pcie_device_id
{
using result_type = query::pcie_device::result_type;

static result_type
get(const xrt_core::device* device, key_type key)
{
return pcie_id::get(device, key).device_id;
}
};

// Query to get the PCIe vendor id from sysfs
struct pcie_vendor
{
using result_type = query::pcie_vendor::result_type;

static result_type
get(const xrt_core::device* device, key_type key)
{
auto [domain, bus, dev, func] = bdf::get(device, key);
std::string bdf_str = boost::str(boost::format("%04x:%02x:%02x.%x") % domain % bus % dev % func);
const std::string base = "/sys/bus/pci/devices/" + bdf_str;
std::ifstream vendor_f(base + "/vendor");
unsigned int vendor_val = 0;
if (!(vendor_f >> std::hex >> vendor_val))
throw xrt_core::query::sysfs_error("Failed to read vendor from " + base + "/vendor");
return static_cast<result_type>(vendor_val);
}
};

struct board_name
{
using result_type = query::board_name::result_type;
Expand Down Expand Up @@ -1064,6 +1095,8 @@ initialize_query_table()
emplace_func0_request<query::xclbin_slots, xclbin_slots>();
emplace_func0_request<query::pcie_bdf, bdf>();
emplace_func0_request<query::pcie_id, pcie_id>();
emplace_func0_request<query::pcie_device, pcie_device_id>();
emplace_func0_request<query::pcie_vendor, pcie_vendor>();
emplace_func0_request<query::rom_vbnv, dev_info>();
emplace_func0_request<query::device_class, dev_info>();
emplace_func0_request<query::total_cols, total_cols>();
Expand Down
5 changes: 5 additions & 0 deletions test/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,9 @@
# Copyright (C) 2024, Advanced Micro Devices, Inc. All rights reserved.

add_subdirectory(shim_test)

# xrt_test exercises the public XRT user API and is only wired up for the
# native (non-VE2) build; the VE2 edge build ships shim_test only.
if(NOT XDNA_VE2)
add_subdirectory(xrt_test)
endif()
33 changes: 33 additions & 0 deletions test/shim_test/dev_info.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -162,6 +162,39 @@ binary_info binary_infos[] = {
.path = "local_shim_test_data/npu3a/resnet50/resnet50.elf",
.flow = PREEMPT_FULL_ELF,
},
// npu_ve2 (aie2ps / VE2): own FULL_ELF binaries for "good" (vadd), "nop" and
// "bad_timeout".
{
.tag = "good",
.device = npu_ve2_device_id,
.revision_id = npu_any_revision_id,
.ip_name2idx = {
{ "DPU:dpu", {0xffffffff} },
},
.path = "local_shim_test_data/npu_ve2/vadd/vadd.elf",
.flow = FULL_ELF,
},
{
.tag = "bad_timeout",
.device = npu_ve2_device_id,
.revision_id = npu_any_revision_id,
.ip_name2idx = {
{ "DPU:dpu", {0xffffffff} },
},
.path = "local_shim_test_data/npu_ve2/bad/bad_timeout.elf",
.extra = { {"exp_status", exp_status_timeout}, {"exp_val", "5"} },
.flow = FULL_ELF,
},
{
.tag = "nop",
.device = npu_ve2_device_id,
.revision_id = npu_any_revision_id,
.ip_name2idx = {
{ "DPU:dpu", {0xffffffff} },
},
.path = "local_shim_test_data/npu_ve2/nop/nop.elf",
.flow = FULL_ELF,
},
{
.tag = "good",
.device = npu4_device_id,
Expand Down
1 change: 1 addition & 0 deletions test/shim_test/dev_info.h
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ const uint16_t npu3_device_id = 0x17f1;
const uint16_t npu3_device_id1 = 0x17f3;
const uint16_t npu3a_device_id = 0x1b0a;
const uint16_t npu3a_device_id1 = 0x1b0c;
const uint16_t npu_ve2_device_id = 0xb052;
const uint16_t npu4_device_id = 0x17f0;
const uint16_t npu_any_revision_id = 0xffff;
const uint16_t npu1_revision_id = 0x0;
Expand Down
106 changes: 78 additions & 28 deletions test/shim_test/shim_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -211,7 +211,8 @@ dev_filter_is_aie4(device::id_type id, device* dev)
if (!is_xdna_dev(dev))
return false;
auto device_id = canonical_device_id(device_query<query::pcie_device>(dev));
return device_id == npu3_device_id || device_id == npu3a_device_id;
return device_id == npu3_device_id || device_id == npu3a_device_id ||
device_id == npu_ve2_device_id;
}

bool
Expand Down Expand Up @@ -274,6 +275,50 @@ dev_filter_is_npu4_and_amdxdna_drv(device::id_type id, device* dev)
return true;
}

// VE2 (aie2ps) is device id npu_ve2. It is grouped under aie4/aie for the tests
// it supports, but several aie/aie4 features are not implemented on VE2. These
// helpers keep VE2 in the broad groups while excluding it from the specific
// tests it cannot pass (and one helper to opt VE2 into a couple of aie2 tests
// it does pass).
bool
is_npu_ve2(device::id_type id, device* dev)
{
if (!is_xdna_dev(dev))
return false;
auto device_id = canonical_device_id(device_query<query::pcie_device>(dev));
return device_id == npu_ve2_device_id;
}

bool
dev_filter_xdna_not_npu_ve2(device::id_type id, device* dev)
{
return dev_filter_xdna(id, dev) && !is_npu_ve2(id, dev);
}

bool
dev_filter_is_aie_not_npu_ve2(device::id_type id, device* dev)
{
return dev_filter_is_aie(id, dev) && !is_npu_ve2(id, dev);
}

bool
dev_filter_is_aie4_not_npu_ve2(device::id_type id, device* dev)
{
return dev_filter_is_aie4(id, dev) && !is_npu_ve2(id, dev);
}

bool
dev_filter_is_aie4_or_npu4_not_npu_ve2(device::id_type id, device* dev)
{
return dev_filter_is_aie4_or_npu4(id, dev) && !is_npu_ve2(id, dev);
}

bool
dev_filter_is_aie2_or_npu_ve2(device::id_type id, device* dev)
{
return dev_filter_is_aie2(id, dev) || is_npu_ve2(id, dev);
}

static void TEST_async_error_io_any(device::id_type id, std::shared_ptr<device>& sdev, arg_type& arg)
{
if (dev_filter_is_npu4(id, sdev.get()))
Expand Down Expand Up @@ -1506,9 +1551,14 @@ std::vector<test_case> test_list {
{XCL_BO_FLAGS_HOST_ONLY, 0, 0x10000, 0x23000, 0x2000}
},
test_case{ "create_and_free_input_output_bo huge pages", {},
TEST_POSITIVE, dev_filter_is_aie, TEST_create_free_bo,
TEST_POSITIVE, dev_filter_is_aie_not_npu_ve2, TEST_create_free_bo,
{XCL_BO_FLAGS_HOST_ONLY, 0, 0x140000000}
},
// VE2 (npu_ve2) has a smaller contiguous CMA pool, so use a 3GB BO instead of 5GB.
test_case{ "create_and_free_input_output_bo huge pages (npu_ve2)", {},
TEST_POSITIVE, is_npu_ve2, TEST_create_free_bo,
{XCL_BO_FLAGS_HOST_ONLY, 0, 0xC0000000}
},
test_case{ "sync_bo for dpu sequence bo", {},
TEST_POSITIVE, dev_filter_xdna, TEST_sync_bo, {XCL_BO_FLAGS_CACHEABLE, 0, 128}
},
Expand All @@ -1522,7 +1572,7 @@ std::vector<test_case> test_list {
TEST_POSITIVE, dev_filter_xdna, TEST_map_bo, {XCL_BO_FLAGS_HOST_ONLY, 0, 361264}
},
test_case{ "map bo for read only", {},
TEST_NEGATIVE, dev_filter_xdna, TEST_map_read_bo, {0x1000}
TEST_NEGATIVE, dev_filter_xdna_not_npu_ve2, TEST_map_read_bo, {0x1000}
},
test_case{ "map exec_buf_bo and test perf", {},
TEST_POSITIVE, dev_filter_xdna, TEST_create_free_bo, {XCL_BO_FLAGS_EXECBUF, 0, 0x1000}
Expand All @@ -1535,7 +1585,7 @@ std::vector<test_case> test_list {
},
// Keep bad run before normal run to test recovery of hw ctx
test_case{ "io test async error", {},
TEST_POSITIVE, dev_filter_is_aie4_or_npu4, TEST_async_error_io_any, {}
TEST_POSITIVE, dev_filter_is_aie4_or_npu4_not_npu_ve2, TEST_async_error_io_any, {}
},
test_case{ "io test real kernel good run", {},
TEST_POSITIVE, dev_filter_xdna, TEST_io, { IO_TEST_NORMAL_RUN, 1 }
Expand All @@ -1550,10 +1600,10 @@ std::vector<test_case> test_list {
TEST_POSITIVE, dev_filter_is_aie, TEST_io_latency, { IO_TEST_NORMAL_RUN, IO_TEST_IOCTL_WAIT, NUM_STRESS_IO }
},
test_case{ "create and free debug bo", {},
TEST_POSITIVE, dev_filter_xdna, TEST_create_free_debug_bo, { 0x1000 }
TEST_POSITIVE, dev_filter_xdna_not_npu_ve2, TEST_create_free_debug_bo, { 0x1000 }
},
test_case{ "create and free large debug bo", {},
TEST_POSITIVE, dev_filter_xdna, TEST_create_free_debug_bo, { 0x100000 }
TEST_POSITIVE, dev_filter_xdna_not_npu_ve2, TEST_create_free_debug_bo, { 0x100000 }
},
test_case{ "create and free uc_log bo", {},
TEST_POSITIVE, dev_filter_is_aie4, TEST_create_free_uc_log_bo, { 0x10000 }
Expand All @@ -1574,7 +1624,7 @@ std::vector<test_case> test_list {
TEST_POSITIVE, dev_filter_is_aie2, TEST_elf_io, { IO_TEST_NORMAL_RUN, 1 }
},
test_case{ "Cmd fencing (user space side)", {},
TEST_POSITIVE, dev_filter_xdna, TEST_cmd_fence_host, {}
TEST_POSITIVE, dev_filter_xdna_not_npu_ve2, TEST_cmd_fence_host, {}
},
test_case{ "io test no op with duplicated BOs", {},
TEST_POSITIVE, dev_filter_xdna, TEST_noop_io_with_dup_bo, {}
Expand All @@ -1583,22 +1633,22 @@ std::vector<test_case> test_list {
TEST_POSITIVE, dev_filter_is_aie, TEST_io_runlist_latency, { IO_TEST_NOOP_RUN, IO_TEST_IOCTL_WAIT, NUM_STRESS_IO }
},
test_case{ "measure no-op kernel throughput chained command", {},
TEST_POSITIVE, dev_filter_is_aie, TEST_io_runlist_throughput, { IO_TEST_NOOP_RUN, IO_TEST_IOCTL_WAIT, NUM_STRESS_IO }
TEST_POSITIVE, dev_filter_is_aie_not_npu_ve2, TEST_io_runlist_throughput, { IO_TEST_NOOP_RUN, IO_TEST_IOCTL_WAIT, NUM_STRESS_IO }
},
test_case{ "measure no-op kernel latency (polling)", {},
TEST_POSITIVE, dev_filter_is_aie, TEST_io_latency, { IO_TEST_NOOP_RUN, IO_TEST_POLL_WAIT, NUM_STRESS_IO }
TEST_POSITIVE, dev_filter_is_aie_not_npu_ve2, TEST_io_latency, { IO_TEST_NOOP_RUN, IO_TEST_POLL_WAIT, NUM_STRESS_IO }
},
test_case{ "measure no-op kernel throughput (polling)", {},
TEST_POSITIVE, dev_filter_is_aie, TEST_io_throughput, { IO_TEST_NOOP_RUN, IO_TEST_POLL_WAIT, NUM_STRESS_IO }
TEST_POSITIVE, dev_filter_is_aie_not_npu_ve2, TEST_io_throughput, { IO_TEST_NOOP_RUN, IO_TEST_POLL_WAIT, NUM_STRESS_IO }
},
test_case{ "measure no-op kernel latency chained command (polling)", {},
TEST_POSITIVE, dev_filter_is_aie, TEST_io_runlist_latency, { IO_TEST_NOOP_RUN, IO_TEST_POLL_WAIT, NUM_STRESS_IO }
TEST_POSITIVE, dev_filter_is_aie_not_npu_ve2, TEST_io_runlist_latency, { IO_TEST_NOOP_RUN, IO_TEST_POLL_WAIT, NUM_STRESS_IO }
},
test_case{ "measure no-op kernel throughput chained command (polling)", {},
TEST_POSITIVE, dev_filter_is_aie, TEST_io_runlist_throughput, { IO_TEST_NOOP_RUN, IO_TEST_POLL_WAIT, NUM_STRESS_IO }
TEST_POSITIVE, dev_filter_is_aie_not_npu_ve2, TEST_io_runlist_throughput, { IO_TEST_NOOP_RUN, IO_TEST_POLL_WAIT, NUM_STRESS_IO }
},
test_case{ "Cmd fencing (driver side)", {},
TEST_POSITIVE, dev_filter_xdna, TEST_cmd_fence_device, {}
TEST_POSITIVE, dev_filter_xdna_not_npu_ve2, TEST_cmd_fence_device, {}
},
test_case{ "sync_bo for input_output 1MiB BO", {},
TEST_POSITIVE, dev_filter_xdna, TEST_sync_bo, {XCL_BO_FLAGS_HOST_ONLY, 0, 0x100000}
Expand All @@ -1619,13 +1669,13 @@ std::vector<test_case> test_list {
TEST_NEGATIVE, dev_filter_is_aie, TEST_create_destroy_max_context, { 1 }
},
test_case{ "Multi context IO test 1", {},
TEST_POSITIVE, dev_filter_is_aie2, TEST_multi_context_io_test, { 0 }
TEST_POSITIVE, dev_filter_is_aie2_or_npu_ve2, TEST_multi_context_io_test, { 0 }
},
test_case{ "Multi context IO test 2", {},
TEST_POSITIVE, dev_filter_is_aie2, TEST_multi_context_io_test, { 1 }
TEST_POSITIVE, dev_filter_is_aie2_or_npu_ve2, TEST_multi_context_io_test, { 1 }
},
test_case{ "Multi context IO test 3", {},
TEST_POSITIVE, dev_filter_is_aie2, TEST_multi_context_io_test, { 2 }
TEST_POSITIVE, dev_filter_is_aie2_or_npu_ve2, TEST_multi_context_io_test, { 2 }
},
test_case{ "Create and destroy devices", {},
TEST_POSITIVE, dev_filter_xdna, TEST_create_destroy_device, {}
Expand All @@ -1640,10 +1690,10 @@ std::vector<test_case> test_list {
TEST_POSITIVE, dev_filter_is_aie2_and_amdxdna_drv, TEST_io_with_ubuf_bo, {}
},
test_case{ "multi-command preempt full ELF io test real kernel good run", {},
TEST_POSITIVE, dev_filter_is_aie4_or_npu4, TEST_preempt_full_elf_io, { IO_TEST_FORCE_PREEMPTION, 8 }
TEST_POSITIVE, dev_filter_is_aie4_or_npu4_not_npu_ve2, TEST_preempt_full_elf_io, { IO_TEST_FORCE_PREEMPTION, 8 }
},
test_case{ "Real kernel delay run for auto-suspend/resume", {},
TEST_POSITIVE, dev_filter_is_aie2, TEST_io_suspend_resume, {}
TEST_POSITIVE, dev_filter_is_aie2_or_npu_ve2, TEST_io_suspend_resume, {}
},
test_case{ "io test timeout run for context health report", {},
TEST_POSITIVE, dev_filter_is_npu4, TEST_io_timeout, {}
Expand All @@ -1652,23 +1702,23 @@ std::vector<test_case> test_list {
TEST_POSITIVE, dev_filter_is_npu4_and_amdxdna_drv, TEST_app_health_query_multi_ctx, {}
},
test_case{ "query hw_contexts (get_info)", {},
TEST_POSITIVE, dev_filter_is_aie, TEST_query_hw_contexts, {}
TEST_POSITIVE, dev_filter_is_aie_not_npu_ve2, TEST_query_hw_contexts, {}
},
test_case{ "hw_context_all (get_array)", {},
TEST_POSITIVE, dev_filter_is_aie, TEST_hw_context_all, {}
TEST_POSITIVE, dev_filter_is_aie_not_npu_ve2, TEST_hw_context_all, {}
},
test_case{ "query telemetry", {},
TEST_POSITIVE, dev_filter_is_aie, TEST_query_telemetry, {}
TEST_POSITIVE, dev_filter_is_aie_not_npu_ve2, TEST_query_telemetry, {}
},
test_case{ "query telemetry header-only buffer fails", {},
TEST_POSITIVE, dev_filter_is_aie, TEST_query_telemetry_short_buf, {}
TEST_POSITIVE, dev_filter_is_aie_not_npu_ve2, TEST_query_telemetry_short_buf, {}
},
//test_case{ "io test no-op kernel good run", {},
// TEST_POSITIVE, dev_filter_is_aie2, TEST_io, { IO_TEST_NOOP_RUN, 1 }
//},
// get async error in multi thread after async error has raised.
test_case{ "get async error in multithread - HAS ASYNC ERROR", {},
TEST_POSITIVE, dev_filter_is_aie4_or_npu4, TEST_async_error_multi, {true}
TEST_POSITIVE, dev_filter_is_aie4_or_npu4_not_npu_ve2, TEST_async_error_multi, {true}
},
test_case{ "gemm and debug BO", {},
TEST_POSITIVE, dev_filter_is_npu4, TEST_io_gemm, {}
Expand Down Expand Up @@ -1733,19 +1783,19 @@ std::vector<test_case> test_list {
TEST_POSITIVE, dev_filter_is_npu4, TEST_dpm_power_modes, {}
},
test_case{ "CERT log: attach/detach", {},
TEST_POSITIVE, dev_filter_is_aie4, TEST_certlog_attach_detach, {}
TEST_POSITIVE, dev_filter_is_aie4_not_npu_ve2, TEST_certlog_attach_detach, {}
},
test_case{ "CERT log: max num_ucs", {},
TEST_POSITIVE, dev_filter_is_aie4, TEST_certlog_multi_uc, {}
TEST_POSITIVE, dev_filter_is_aie4_not_npu_ve2, TEST_certlog_multi_uc, {}
},
test_case{ "CERT log: num_ucs > AIE4_MAX_NUM_CERTS rejected", {},
TEST_POSITIVE, dev_filter_is_aie4, TEST_certlog_num_ucs_overflow, {}
TEST_POSITIVE, dev_filter_is_aie4_not_npu_ve2, TEST_certlog_num_ucs_overflow, {}
},
test_case{ "CERT log: out-of-range uc index rejected", {},
TEST_POSITIVE, dev_filter_is_aie4, TEST_certlog_invalid_uc_index, {}
TEST_POSITIVE, dev_filter_is_aie4_not_npu_ve2, TEST_certlog_invalid_uc_index, {}
},
test_case{ "CERT log: payload overflow rejected", {},
TEST_POSITIVE, dev_filter_is_aie4, TEST_certlog_payload_overflow, {}
TEST_POSITIVE, dev_filter_is_aie4_not_npu_ve2, TEST_certlog_payload_overflow, {}
},
};

Expand Down