Add DebugSession helper methods

Signed-off-by: Mateusz Hoppe <mateusz.hoppe@intel.com>
This commit is contained in:
Mateusz Hoppe
2021-07-28 17:30:15 +00:00
committed by Compute-Runtime-Automation
parent 65f02858ea
commit 89144e494d
3 changed files with 325 additions and 0 deletions

View File

@@ -13,6 +13,49 @@
namespace L0 {
ze_device_thread_t DebugSession::convertToPhysical(ze_device_thread_t thread, uint32_t &deviceIndex) {
auto hwInfo = connectedDevice->getHwInfo();
auto deviceBitfield = connectedDevice->getNEODevice()->getDeviceBitfield();
if (connectedDevice->getNEODevice()->isSubDevice()) {
deviceIndex = Math::log2(static_cast<uint32_t>(deviceBitfield.to_ulong()));
} else if (thread.slice != UINT32_MAX) {
deviceIndex = thread.slice / hwInfo.gtSystemInfo.SliceCount;
thread.slice = thread.slice % hwInfo.gtSystemInfo.SliceCount;
}
return thread;
}
EuThread::ThreadId DebugSession::convertToThreadId(ze_device_thread_t thread) {
auto hwInfo = connectedDevice->getHwInfo();
auto deviceBitfield = connectedDevice->getNEODevice()->getDeviceBitfield();
UNRECOVERABLE_IF(!DebugSession::isSingleThread(thread));
uint32_t deviceIndex = 0;
if (connectedDevice->getNEODevice()->isSubDevice()) {
deviceIndex = Math::log2(static_cast<uint32_t>(deviceBitfield.to_ulong()));
} else {
deviceIndex = thread.slice / hwInfo.gtSystemInfo.SliceCount;
thread.slice = thread.slice % hwInfo.gtSystemInfo.SliceCount;
}
EuThread::ThreadId threadId(deviceIndex, thread.slice, thread.subslice, thread.eu, thread.thread);
return threadId;
}
ze_device_thread_t DebugSession::convertToApi(EuThread::ThreadId threadId) {
auto hwInfo = connectedDevice->getHwInfo();
ze_device_thread_t thread = {static_cast<uint32_t>(threadId.slice), static_cast<uint32_t>(threadId.subslice), static_cast<uint32_t>(threadId.eu), static_cast<uint32_t>(threadId.thread)};
if (!connectedDevice->getNEODevice()->isSubDevice()) {
thread.slice = thread.slice + static_cast<uint32_t>(threadId.tileIndex * hwInfo.gtSystemInfo.SliceCount);
}
return thread;
}
RootDebugSession::RootDebugSession(const zet_debug_config_t &config, Device *device) : DebugSession(config, device) {
if (connectedDevice) {

View File

@@ -43,6 +43,35 @@ struct DebugSession : _zet_debug_session_handle_t {
Device *getConnectedDevice() { return connectedDevice; }
static bool isThreadAll(ze_device_thread_t thread) {
return thread.slice == UINT32_MAX && thread.subslice == UINT32_MAX && thread.eu == UINT32_MAX && thread.thread == UINT32_MAX;
}
static bool isSingleThread(ze_device_thread_t thread) {
return thread.slice != UINT32_MAX && thread.subslice != UINT32_MAX && thread.eu != UINT32_MAX && thread.thread != UINT32_MAX;
}
static bool areThreadsEqual(ze_device_thread_t thread, ze_device_thread_t thread2) {
return thread.slice == thread2.slice && thread.subslice == thread2.subslice && thread.eu == thread2.eu && thread.thread == thread2.thread;
}
static bool checkSingleThreadWithinDeviceThread(ze_device_thread_t checkedThread, ze_device_thread_t thread) {
if (DebugSession::isThreadAll(thread)) {
return true;
}
bool threadMatch = (thread.thread == checkedThread.thread) || thread.thread == UINT32_MAX;
bool euMatch = (thread.eu == checkedThread.eu) || thread.eu == UINT32_MAX;
bool subsliceMatch = (thread.subslice == checkedThread.subslice) || thread.subslice == UINT32_MAX;
bool sliceMatch = (thread.slice == checkedThread.slice) || thread.slice == UINT32_MAX;
return threadMatch && euMatch && subsliceMatch && sliceMatch;
}
virtual ze_device_thread_t convertToPhysical(ze_device_thread_t thread, uint32_t &deviceIndex);
virtual EuThread::ThreadId convertToThreadId(ze_device_thread_t thread);
virtual ze_device_thread_t convertToApi(EuThread::ThreadId threadId);
protected:
DebugSession(const zet_debug_config_t &config, Device *device) : connectedDevice(device){};
virtual void startAsyncThread() = 0;

View File

@@ -7,10 +7,12 @@
#include "shared/test/common/helpers/default_hw_info.h"
#include "shared/test/common/mocks/mock_device.h"
#include "shared/test/common/mocks/ult_device_factory.h"
#include "test.h"
#include "level_zero/core/source/device/device_imp.h"
#include "level_zero/core/test/unit_tests/fixtures/device_fixture.h"
#include "level_zero/core/test/unit_tests/mock.h"
#include "level_zero/core/test/unit_tests/mocks/mock_device.h"
#include "level_zero/tools/test/unit_tests/sources/debug/mock_debug_session.h"
@@ -18,6 +20,142 @@
namespace L0 {
namespace ult {
TEST(DebugSession, givenThreadWhenIsThreadAllCalledThenTrueReturnedOnlyForAllValuesEqualMax) {
ze_device_thread_t thread = {UINT32_MAX, UINT32_MAX, UINT32_MAX, UINT32_MAX};
EXPECT_TRUE(DebugSession::isThreadAll(thread));
thread = {0, UINT32_MAX, UINT32_MAX, UINT32_MAX};
EXPECT_FALSE(DebugSession::isThreadAll(thread));
thread = {UINT32_MAX, 0, UINT32_MAX, UINT32_MAX};
EXPECT_FALSE(DebugSession::isThreadAll(thread));
thread = {UINT32_MAX, UINT32_MAX, 0, UINT32_MAX};
EXPECT_FALSE(DebugSession::isThreadAll(thread));
thread = {UINT32_MAX, UINT32_MAX, UINT32_MAX, 0};
EXPECT_FALSE(DebugSession::isThreadAll(thread));
}
TEST(DebugSession, givenThreadWhenIsSingleThreadCalledThenTrueReturnedOnlyForNonMaxValues) {
ze_device_thread_t thread = {UINT32_MAX, UINT32_MAX, UINT32_MAX, UINT32_MAX};
EXPECT_FALSE(DebugSession::isSingleThread(thread));
thread = {0, UINT32_MAX, UINT32_MAX, UINT32_MAX};
EXPECT_FALSE(DebugSession::isSingleThread(thread));
thread = {UINT32_MAX, 0, UINT32_MAX, UINT32_MAX};
EXPECT_FALSE(DebugSession::isSingleThread(thread));
thread = {UINT32_MAX, UINT32_MAX, 0, UINT32_MAX};
EXPECT_FALSE(DebugSession::isSingleThread(thread));
thread = {UINT32_MAX, UINT32_MAX, UINT32_MAX, 0};
EXPECT_FALSE(DebugSession::isSingleThread(thread));
thread = {UINT32_MAX, UINT32_MAX, 0, 0};
EXPECT_FALSE(DebugSession::isSingleThread(thread));
thread = {UINT32_MAX, 0, 0, 0};
EXPECT_FALSE(DebugSession::isSingleThread(thread));
thread = {UINT32_MAX, 0, UINT32_MAX, 0};
EXPECT_FALSE(DebugSession::isSingleThread(thread));
thread = {0, UINT32_MAX, 0, UINT32_MAX};
EXPECT_FALSE(DebugSession::isSingleThread(thread));
thread = {UINT32_MAX, 0, 0, UINT32_MAX};
EXPECT_FALSE(DebugSession::isSingleThread(thread));
thread = {0, UINT32_MAX, UINT32_MAX, 0};
EXPECT_FALSE(DebugSession::isSingleThread(thread));
thread = {0, 0, UINT32_MAX, 0};
EXPECT_FALSE(DebugSession::isSingleThread(thread));
thread = {0, 0, 0, UINT32_MAX};
EXPECT_FALSE(DebugSession::isSingleThread(thread));
thread = {1, 2, 3, 0};
EXPECT_TRUE(DebugSession::isSingleThread(thread));
}
TEST(DebugSession, givenThreadsWhenAreThreadsEqualCalledThenTrueReturnedForEqualThreads) {
ze_device_thread_t thread = {UINT32_MAX, UINT32_MAX, UINT32_MAX, UINT32_MAX};
ze_device_thread_t thread2 = {UINT32_MAX, UINT32_MAX, UINT32_MAX, UINT32_MAX};
EXPECT_TRUE(DebugSession::areThreadsEqual(thread, thread2));
thread = {0, UINT32_MAX, UINT32_MAX, UINT32_MAX};
EXPECT_FALSE(DebugSession::areThreadsEqual(thread, thread2));
thread2 = {UINT32_MAX, 0, UINT32_MAX, UINT32_MAX};
EXPECT_FALSE(DebugSession::areThreadsEqual(thread, thread2));
thread = {1, 0, 0, 0};
thread2 = {1, 0, 0, UINT32_MAX};
EXPECT_FALSE(DebugSession::areThreadsEqual(thread, thread2));
thread2 = {1, 0, 1, 0};
EXPECT_FALSE(DebugSession::areThreadsEqual(thread, thread2));
thread2 = {1, 1, 0, 0};
EXPECT_FALSE(DebugSession::areThreadsEqual(thread, thread2));
thread2 = {0, 0, 0, 0};
EXPECT_FALSE(DebugSession::areThreadsEqual(thread, thread2));
{
ze_device_thread_t thread = {1, 1, 1, 1};
ze_device_thread_t thread2 = {1, 1, 1, 1};
EXPECT_TRUE(DebugSession::areThreadsEqual(thread, thread2));
}
}
TEST(DebugSession, givenThreadWhenCheckSingleThreadWithinDeviceThreadCalledThenTrueReturnedForMatchingThread) {
ze_device_thread_t thread = {0, 1, 2, 3};
ze_device_thread_t thread2 = {UINT32_MAX, UINT32_MAX, UINT32_MAX, UINT32_MAX};
EXPECT_TRUE(DebugSession::checkSingleThreadWithinDeviceThread(thread, thread2));
thread = {0, 1, 2, 3};
thread2 = {0, UINT32_MAX, UINT32_MAX, UINT32_MAX};
EXPECT_TRUE(DebugSession::checkSingleThreadWithinDeviceThread(thread, thread2));
thread = {0, 1, 2, 3};
thread2 = {0, 1, 2, 3};
EXPECT_TRUE(DebugSession::checkSingleThreadWithinDeviceThread(thread, thread2));
thread = {0, 1, 2, 3};
thread2 = {0, UINT32_MAX, UINT32_MAX, 4};
EXPECT_FALSE(DebugSession::checkSingleThreadWithinDeviceThread(thread, thread2));
thread = {0, 1, 2, 3};
thread2 = {0, 1, 2, 4};
EXPECT_FALSE(DebugSession::checkSingleThreadWithinDeviceThread(thread, thread2));
thread = {0, 1, 2, 3};
thread2 = {1, 1, 2, 3};
EXPECT_FALSE(DebugSession::checkSingleThreadWithinDeviceThread(thread, thread2));
thread = {0, 1, 2, 3};
thread2 = {0, 2, 2, 3};
EXPECT_FALSE(DebugSession::checkSingleThreadWithinDeviceThread(thread, thread2));
thread = {0, 1, 3, 3};
thread2 = {0, 1, 2, 3};
EXPECT_FALSE(DebugSession::checkSingleThreadWithinDeviceThread(thread, thread2));
thread = {0, 1, 3, 3};
thread2 = {UINT32_MAX, 0, 2, 3};
EXPECT_FALSE(DebugSession::checkSingleThreadWithinDeviceThread(thread, thread2));
}
TEST(RootDebugSession, givenSingleThreadWhenGettingSingleThreadsThenCorrectThreadIsReturned) {
zet_debug_config_t config = {};
config.pid = 0x1234;
@@ -165,5 +303,120 @@ TEST(RootDebugSession, givenBindfulSystemRoutineWhenQueryingIsBindlessThenFalseR
EXPECT_FALSE(debugSession->isBindlessSystemRoutine());
}
TEST(RootDebugSession, givenApiThreadAndSingleTileWhenConvertingThenCorrectValuesReturned) {
auto hwInfo = *NEO::defaultHwInfo.get();
NEO::Device *neoDevice(NEO::MockDevice::createWithNewExecutionEnvironment<NEO::MockDevice>(&hwInfo, 0));
Mock<L0::DeviceImp> deviceImp(neoDevice, neoDevice->getExecutionEnvironment());
auto debugSession = std::make_unique<DebugSessionMock>(zet_debug_config_t{0x1234}, &deviceImp);
ze_device_thread_t thread = {hwInfo.gtSystemInfo.SliceCount - 1, hwInfo.gtSystemInfo.SubSliceCount - 1, 0, 0};
uint32_t deviceIndex = 0;
auto convertedThread = debugSession->convertToPhysical(thread, deviceIndex);
EXPECT_EQ(0u, deviceIndex);
EXPECT_EQ(convertedThread.slice, thread.slice);
EXPECT_EQ(convertedThread.subslice, thread.subslice);
EXPECT_EQ(convertedThread.eu, thread.eu);
EXPECT_EQ(convertedThread.thread, thread.thread);
thread.slice = UINT32_MAX;
convertedThread = debugSession->convertToPhysical(thread, deviceIndex);
EXPECT_EQ(0u, deviceIndex);
EXPECT_EQ(convertedThread.slice, thread.slice);
}
using DebugSessionMultiTile = Test<MultipleDevicesWithCustomHwInfo>;
TEST_F(DebugSessionMultiTile, givenApiThreadAndMultipleTilesWhenConvertingToPhysicalThenCorrectValueReturned) {
L0::Device *device = driverHandle->devices[0];
auto debugSession = std::make_unique<DebugSessionMock>(zet_debug_config_t{0x1234}, device);
ze_device_thread_t thread = {sliceCount * 2 - 1, 0, 0, 0};
uint32_t deviceIndex = 0;
auto convertedThread = debugSession->convertToPhysical(thread, deviceIndex);
EXPECT_EQ(1u, deviceIndex);
EXPECT_EQ(sliceCount - 1, convertedThread.slice);
EXPECT_EQ(thread.subslice, convertedThread.subslice);
EXPECT_EQ(thread.eu, convertedThread.eu);
EXPECT_EQ(thread.thread, convertedThread.thread);
thread = {sliceCount - 1, 0, 0, 0};
convertedThread = debugSession->convertToPhysical(thread, deviceIndex);
EXPECT_EQ(0u, deviceIndex);
EXPECT_EQ(sliceCount - 1, convertedThread.slice);
EXPECT_EQ(thread.subslice, convertedThread.subslice);
EXPECT_EQ(thread.eu, convertedThread.eu);
EXPECT_EQ(thread.thread, convertedThread.thread);
thread.slice = UINT32_MAX;
convertedThread = debugSession->convertToPhysical(thread, deviceIndex);
EXPECT_EQ(0u, deviceIndex);
EXPECT_EQ(convertedThread.slice, thread.slice);
L0::DeviceImp *deviceImp = static_cast<DeviceImp *>(device);
debugSession = std::make_unique<DebugSessionMock>(zet_debug_config_t{0x1234}, deviceImp->subDevices[1]);
thread = {sliceCount - 1, 0, 0, 0};
deviceIndex = 10;
convertedThread = debugSession->convertToPhysical(thread, deviceIndex);
EXPECT_EQ(1u, deviceIndex);
EXPECT_EQ(sliceCount - 1, convertedThread.slice);
EXPECT_EQ(thread.subslice, convertedThread.subslice);
EXPECT_EQ(thread.eu, convertedThread.eu);
EXPECT_EQ(thread.thread, convertedThread.thread);
}
TEST_F(DebugSessionMultiTile, WhenConvertingToThreadIdAndBackThenCorrectThreadIdsAreReturned) {
L0::Device *device = driverHandle->devices[0];
auto debugSession = std::make_unique<DebugSessionMock>(zet_debug_config_t{0x1234}, device);
ze_device_thread_t thread = {sliceCount * 2 - 1, 0, 0, 0};
auto threadID = debugSession->convertToThreadId(thread);
EXPECT_EQ(1u, threadID.tileIndex);
EXPECT_EQ(sliceCount - 1, threadID.slice);
EXPECT_EQ(thread.subslice, threadID.subslice);
EXPECT_EQ(thread.eu, threadID.eu);
EXPECT_EQ(thread.thread, threadID.thread);
auto apiThread = debugSession->convertToApi(threadID);
EXPECT_EQ(thread.slice, apiThread.slice);
EXPECT_EQ(thread.subslice, apiThread.subslice);
EXPECT_EQ(thread.eu, apiThread.eu);
EXPECT_EQ(thread.thread, apiThread.thread);
L0::DeviceImp *deviceImp = static_cast<DeviceImp *>(device);
debugSession = std::make_unique<DebugSessionMock>(zet_debug_config_t{0x1234}, deviceImp->subDevices[1]);
thread = {sliceCount - 1, 0, 0, 0};
threadID = debugSession->convertToThreadId(thread);
EXPECT_EQ(1u, threadID.tileIndex);
EXPECT_EQ(sliceCount - 1, threadID.slice);
EXPECT_EQ(thread.subslice, threadID.subslice);
EXPECT_EQ(thread.eu, threadID.eu);
EXPECT_EQ(thread.thread, threadID.thread);
apiThread = debugSession->convertToApi(threadID);
EXPECT_EQ(thread.slice, apiThread.slice);
EXPECT_EQ(thread.subslice, apiThread.subslice);
EXPECT_EQ(thread.eu, apiThread.eu);
EXPECT_EQ(thread.thread, apiThread.thread);
}
} // namespace ult
} // namespace L0