Skip to content

Commit ad5735c

Browse files
Add EuThread class
- add thread map to RootDebugSession Signed-off-by: Mateusz Hoppe <[email protected]>
1 parent e87056f commit ad5735c

File tree

8 files changed

+455
-1
lines changed

8 files changed

+455
-1
lines changed

level_zero/tools/source/debug/CMakeLists.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,10 @@
55
#
66

77
set(L0_SRCS_TOOLS_DEBUG
8+
${CMAKE_CURRENT_SOURCE_DIR}/debug_session.cpp
89
${CMAKE_CURRENT_SOURCE_DIR}/debug_session.h
910
${CMAKE_CURRENT_SOURCE_DIR}/debug_handlers.h
11+
${CMAKE_CURRENT_SOURCE_DIR}/eu_thread.h
1012
${CMAKE_CURRENT_SOURCE_DIR}${BRANCH_DIR_SUFFIX}/debug_handlers.cpp
1113
)
1214

Lines changed: 99 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,99 @@
1+
/*
2+
* Copyright (C) 2021 Intel Corporation
3+
*
4+
* SPDX-License-Identifier: MIT
5+
*
6+
*/
7+
8+
#include "level_zero/tools/source/debug/debug_session.h"
9+
10+
#include "shared/source/helpers/hw_info.h"
11+
12+
#include "level_zero/core/source/device/device_imp.h"
13+
14+
namespace L0 {
15+
16+
RootDebugSession::RootDebugSession(const zet_debug_config_t &config, Device *device) : DebugSession(config, device) {
17+
18+
if (connectedDevice) {
19+
auto hwInfo = connectedDevice->getHwInfo();
20+
const uint32_t numSubslicesPerSlice = hwInfo.gtSystemInfo.MaxSubSlicesSupported / hwInfo.gtSystemInfo.MaxSlicesSupported;
21+
const uint32_t numEuPerSubslice = hwInfo.gtSystemInfo.MaxEuPerSubSlice;
22+
const uint32_t numThreadsPerEu = (hwInfo.gtSystemInfo.ThreadCount / hwInfo.gtSystemInfo.EUCount);
23+
uint32_t subDeviceCount = 1;
24+
25+
for (uint32_t tileIndex = 0; tileIndex < subDeviceCount; tileIndex++) {
26+
for (uint32_t sliceID = 0; sliceID < hwInfo.gtSystemInfo.MaxSlicesSupported; sliceID++) {
27+
for (uint32_t subsliceID = 0; subsliceID < numSubslicesPerSlice; subsliceID++) {
28+
for (uint32_t euID = 0; euID < numEuPerSubslice; euID++) {
29+
30+
for (uint32_t threadID = 0; threadID < numThreadsPerEu; threadID++) {
31+
32+
EuThread::ThreadId thread = {tileIndex, sliceID, subsliceID, euID, threadID};
33+
34+
allThreads[uint64_t(thread)] = std::make_unique<EuThread>(thread);
35+
}
36+
}
37+
}
38+
}
39+
}
40+
}
41+
}
42+
43+
std::vector<ze_device_thread_t> RootDebugSession::getSingleThreads(ze_device_thread_t physicalThread, const NEO::HardwareInfo &hwInfo) {
44+
const uint32_t numSubslicesPerSlice = hwInfo.gtSystemInfo.MaxSubSlicesSupported / hwInfo.gtSystemInfo.MaxSlicesSupported;
45+
const uint32_t numEuPerSubslice = hwInfo.gtSystemInfo.MaxEuPerSubSlice;
46+
const uint32_t numThreadsPerEu = (hwInfo.gtSystemInfo.ThreadCount / hwInfo.gtSystemInfo.EUCount);
47+
48+
UNRECOVERABLE_IF(numThreadsPerEu > 8);
49+
50+
std::vector<ze_device_thread_t> threads;
51+
52+
const uint32_t slice = physicalThread.slice;
53+
const uint32_t subslice = physicalThread.subslice;
54+
const uint32_t eu = physicalThread.eu;
55+
const uint32_t thread = physicalThread.thread;
56+
57+
for (uint32_t sliceID = 0; sliceID < hwInfo.gtSystemInfo.MaxSlicesSupported; sliceID++) {
58+
if (slice != UINT32_MAX) {
59+
sliceID = slice;
60+
}
61+
62+
for (uint32_t subsliceID = 0; subsliceID < numSubslicesPerSlice; subsliceID++) {
63+
if (subslice != UINT32_MAX) {
64+
subsliceID = subslice;
65+
}
66+
67+
for (uint32_t euID = 0; euID < numEuPerSubslice; euID++) {
68+
if (eu != UINT32_MAX) {
69+
euID = eu;
70+
}
71+
72+
for (uint32_t threadID = 0; threadID < numThreadsPerEu; threadID++) {
73+
if (thread != UINT32_MAX) {
74+
threadID = thread;
75+
}
76+
threads.push_back({sliceID, subsliceID, euID, threadID});
77+
78+
if (thread != UINT32_MAX) {
79+
break;
80+
}
81+
}
82+
83+
if (eu != UINT32_MAX) {
84+
break;
85+
}
86+
}
87+
if (subslice != UINT32_MAX) {
88+
break;
89+
}
90+
}
91+
if (slice != UINT32_MAX) {
92+
break;
93+
}
94+
}
95+
96+
return threads;
97+
}
98+
99+
} // namespace L0

level_zero/tools/source/debug/debug_session.h

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,12 @@
77

88
#pragma once
99
#include "level_zero/core/source/debugger/debugger_l0.h"
10+
#include "level_zero/tools/source/debug/eu_thread.h"
11+
#include <level_zero/ze_api.h>
1012
#include <level_zero/zet_api.h>
1113

14+
#include <memory>
15+
1216
struct _zet_debug_session_handle_t {};
1317

1418
namespace L0 {
@@ -51,10 +55,14 @@ struct RootDebugSession : DebugSession {
5155
RootDebugSession() = delete;
5256

5357
protected:
54-
RootDebugSession(const zet_debug_config_t &config, Device *device) : DebugSession(config, device){};
58+
RootDebugSession(const zet_debug_config_t &config, Device *device);
5559

5660
virtual bool readModuleDebugArea() = 0;
61+
std::vector<ze_device_thread_t> getSingleThreads(ze_device_thread_t physicalThread, const NEO::HardwareInfo &hwInfo);
62+
5763
DebugAreaHeader debugArea;
64+
65+
std::map<uint64_t, std::unique_ptr<EuThread>> allThreads;
5866
};
5967

6068
} // namespace L0
Lines changed: 108 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,108 @@
1+
/*
2+
* Copyright (C) 2021 Intel Corporation
3+
*
4+
* SPDX-License-Identifier: MIT
5+
*
6+
*/
7+
8+
#pragma once
9+
10+
#include "shared/source/debug_settings/debug_settings_manager.h"
11+
12+
#include <level_zero/ze_api.h>
13+
14+
#include <limits>
15+
#include <sstream>
16+
#include <string>
17+
namespace L0 {
18+
19+
class EuThread {
20+
public:
21+
enum class State {
22+
Running,
23+
Stopped,
24+
Unavailable
25+
};
26+
27+
struct ThreadId {
28+
union {
29+
struct {
30+
uint64_t thread : 4;
31+
uint64_t eu : 5;
32+
uint64_t subslice : 10;
33+
uint64_t slice : 10;
34+
uint64_t tileIndex : 2;
35+
uint64_t reserved : 33;
36+
};
37+
uint64_t packed;
38+
};
39+
40+
ThreadId(uint32_t tile, uint32_t slice, uint32_t subslice, uint32_t eu, uint32_t thread) {
41+
this->packed = 0;
42+
this->tileIndex = tile;
43+
this->slice = slice;
44+
this->subslice = subslice;
45+
this->eu = eu;
46+
this->thread = thread;
47+
}
48+
49+
ThreadId(uint32_t tile, ze_device_thread_t thread) {
50+
this->packed = 0;
51+
this->tileIndex = tile;
52+
this->slice = thread.slice;
53+
this->subslice = thread.subslice;
54+
this->eu = thread.eu;
55+
this->thread = thread.thread;
56+
}
57+
58+
operator uint64_t() const {
59+
return packed;
60+
}
61+
};
62+
63+
virtual ~EuThread() = default;
64+
65+
EuThread(ThreadId threadId) : threadId(threadId) {}
66+
67+
bool stopThread() {
68+
if (state == State::Stopped) {
69+
return false;
70+
}
71+
state = State::Stopped;
72+
return true;
73+
}
74+
75+
bool resumeThread() {
76+
if (state != State::Stopped) {
77+
return false;
78+
}
79+
state = State::Running;
80+
return true;
81+
}
82+
83+
bool isStopped() {
84+
return state == State::Stopped;
85+
}
86+
87+
bool isRunning() {
88+
return state != State::Stopped;
89+
}
90+
91+
std::string toString() {
92+
std::stringstream threadString;
93+
threadString << "device index = " << threadId.tileIndex << " slice = " << threadId.slice << " subslice = " << threadId.subslice << " eu = " << threadId.eu
94+
<< " thread = " << threadId.thread;
95+
return threadString.str();
96+
}
97+
98+
ThreadId getThreadId() {
99+
return threadId;
100+
}
101+
102+
protected:
103+
ThreadId threadId;
104+
State state = State::Unavailable;
105+
};
106+
107+
static_assert(sizeof(EuThread::ThreadId) == sizeof(uint64_t));
108+
} // namespace L0

level_zero/tools/test/unit_tests/sources/debug/CMakeLists.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@
66

77
target_sources(${TARGET_NAME} PRIVATE
88
${CMAKE_CURRENT_SOURCE_DIR}/CMakeLists.txt
9+
${CMAKE_CURRENT_SOURCE_DIR}/debug_session_tests.cpp
10+
${CMAKE_CURRENT_SOURCE_DIR}/eu_thread_tests.cpp
911
${CMAKE_CURRENT_SOURCE_DIR}/mock_debug_session.h
1012
${CMAKE_CURRENT_SOURCE_DIR}${BRANCH_DIR_SUFFIX}/test_debug_api.cpp
1113
)
Lines changed: 141 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,141 @@
1+
/*
2+
* Copyright (C) 2021 Intel Corporation
3+
*
4+
* SPDX-License-Identifier: MIT
5+
*
6+
*/
7+
8+
#include "shared/test/common/helpers/default_hw_info.h"
9+
#include "shared/test/common/mocks/mock_device.h"
10+
11+
#include "test.h"
12+
13+
#include "level_zero/core/source/device/device_imp.h"
14+
#include "level_zero/core/test/unit_tests/mock.h"
15+
#include "level_zero/core/test/unit_tests/mocks/mock_device.h"
16+
#include "level_zero/tools/test/unit_tests/sources/debug/mock_debug_session.h"
17+
18+
namespace L0 {
19+
namespace ult {
20+
21+
TEST(RootDebugSession, givenSingleThreadWhenGettingSingleThreadsThenCorrectThreadIsReturned) {
22+
zet_debug_config_t config = {};
23+
config.pid = 0x1234;
24+
25+
auto hwInfo = *NEO::defaultHwInfo.get();
26+
NEO::Device *neoDevice(NEO::MockDevice::createWithNewExecutionEnvironment<NEO::MockDevice>(&hwInfo, 0));
27+
Mock<L0::DeviceImp> deviceImp(neoDevice, neoDevice->getExecutionEnvironment());
28+
auto debugSession = std::make_unique<DebugSessionMock>(config, &deviceImp);
29+
30+
auto subslice = hwInfo.gtSystemInfo.MaxSubSlicesSupported / hwInfo.gtSystemInfo.MaxSlicesSupported - 1;
31+
ze_device_thread_t physicalThread = {0, subslice, 2, 3};
32+
33+
auto threads = debugSession->getSingleThreads(physicalThread, hwInfo);
34+
35+
EXPECT_EQ(1u, threads.size());
36+
EXPECT_EQ(0u, threads[0].slice);
37+
EXPECT_EQ(subslice, threads[0].subslice);
38+
EXPECT_EQ(2u, threads[0].eu);
39+
EXPECT_EQ(3u, threads[0].thread);
40+
}
41+
42+
TEST(RootDebugSession, givenAllThreadsWhenGettingSingleThreadsThenCorrectThreadsAreReturned) {
43+
zet_debug_config_t config = {};
44+
config.pid = 0x1234;
45+
46+
auto hwInfo = *NEO::defaultHwInfo.get();
47+
NEO::Device *neoDevice(NEO::MockDevice::createWithNewExecutionEnvironment<NEO::MockDevice>(&hwInfo, 0));
48+
Mock<L0::DeviceImp> deviceImp(neoDevice, neoDevice->getExecutionEnvironment());
49+
auto debugSession = std::make_unique<DebugSessionMock>(config, &deviceImp);
50+
51+
auto subslice = hwInfo.gtSystemInfo.MaxSubSlicesSupported / hwInfo.gtSystemInfo.MaxSlicesSupported - 1;
52+
ze_device_thread_t physicalThread = {0, subslice, 2, UINT32_MAX};
53+
const uint32_t numThreadsPerEu = (hwInfo.gtSystemInfo.ThreadCount / hwInfo.gtSystemInfo.EUCount);
54+
55+
auto threads = debugSession->getSingleThreads(physicalThread, hwInfo);
56+
57+
EXPECT_EQ(numThreadsPerEu, threads.size());
58+
59+
for (uint32_t i = 0; i < numThreadsPerEu; i++) {
60+
EXPECT_EQ(0u, threads[i].slice);
61+
EXPECT_EQ(subslice, threads[i].subslice);
62+
EXPECT_EQ(2u, threads[i].eu);
63+
EXPECT_EQ(i, threads[i].thread);
64+
}
65+
}
66+
67+
TEST(RootDebugSession, givenAllEUsWhenGettingSingleThreadsThenCorrectThreadsAreReturned) {
68+
zet_debug_config_t config = {};
69+
config.pid = 0x1234;
70+
71+
auto hwInfo = *NEO::defaultHwInfo.get();
72+
NEO::Device *neoDevice(NEO::MockDevice::createWithNewExecutionEnvironment<NEO::MockDevice>(&hwInfo, 0));
73+
Mock<L0::DeviceImp> deviceImp(neoDevice, neoDevice->getExecutionEnvironment());
74+
auto debugSession = std::make_unique<DebugSessionMock>(config, &deviceImp);
75+
76+
auto subslice = hwInfo.gtSystemInfo.MaxSubSlicesSupported / hwInfo.gtSystemInfo.MaxSlicesSupported - 1;
77+
ze_device_thread_t physicalThread = {0, subslice, UINT32_MAX, 0};
78+
const uint32_t numEuPerSubslice = hwInfo.gtSystemInfo.MaxEuPerSubSlice;
79+
80+
auto threads = debugSession->getSingleThreads(physicalThread, hwInfo);
81+
82+
EXPECT_EQ(numEuPerSubslice, threads.size());
83+
84+
for (uint32_t i = 0; i < numEuPerSubslice; i++) {
85+
EXPECT_EQ(0u, threads[i].slice);
86+
EXPECT_EQ(subslice, threads[i].subslice);
87+
EXPECT_EQ(i, threads[i].eu);
88+
EXPECT_EQ(0u, threads[i].thread);
89+
}
90+
}
91+
92+
TEST(RootDebugSession, givenAllSubslicesWhenGettingSingleThreadsThenCorrectThreadsAreReturned) {
93+
zet_debug_config_t config = {};
94+
config.pid = 0x1234;
95+
96+
auto hwInfo = *NEO::defaultHwInfo.get();
97+
NEO::Device *neoDevice(NEO::MockDevice::createWithNewExecutionEnvironment<NEO::MockDevice>(&hwInfo, 0));
98+
Mock<L0::DeviceImp> deviceImp(neoDevice, neoDevice->getExecutionEnvironment());
99+
auto debugSession = std::make_unique<DebugSessionMock>(config, &deviceImp);
100+
101+
ze_device_thread_t physicalThread = {0, UINT32_MAX, 0, 0};
102+
const uint32_t numSubslicesPerSlice = hwInfo.gtSystemInfo.MaxSubSlicesSupported / hwInfo.gtSystemInfo.MaxSlicesSupported;
103+
104+
auto threads = debugSession->getSingleThreads(physicalThread, hwInfo);
105+
106+
EXPECT_EQ(numSubslicesPerSlice, threads.size());
107+
108+
for (uint32_t i = 0; i < numSubslicesPerSlice; i++) {
109+
EXPECT_EQ(0u, threads[i].slice);
110+
EXPECT_EQ(i, threads[i].subslice);
111+
EXPECT_EQ(0u, threads[i].eu);
112+
EXPECT_EQ(0u, threads[i].thread);
113+
}
114+
}
115+
116+
TEST(RootDebugSession, givenAllSlicesWhenGettingSingleThreadsThenCorrectThreadsAreReturned) {
117+
zet_debug_config_t config = {};
118+
config.pid = 0x1234;
119+
120+
auto hwInfo = *NEO::defaultHwInfo.get();
121+
NEO::Device *neoDevice(NEO::MockDevice::createWithNewExecutionEnvironment<NEO::MockDevice>(&hwInfo, 0));
122+
Mock<L0::DeviceImp> deviceImp(neoDevice, neoDevice->getExecutionEnvironment());
123+
auto debugSession = std::make_unique<DebugSessionMock>(config, &deviceImp);
124+
125+
ze_device_thread_t physicalThread = {UINT32_MAX, 0, 0, 0};
126+
const uint32_t numSlices = hwInfo.gtSystemInfo.MaxSlicesSupported;
127+
128+
auto threads = debugSession->getSingleThreads(physicalThread, hwInfo);
129+
130+
EXPECT_EQ(numSlices, threads.size());
131+
132+
for (uint32_t i = 0; i < numSlices; i++) {
133+
EXPECT_EQ(i, threads[i].slice);
134+
EXPECT_EQ(0u, threads[i].subslice);
135+
EXPECT_EQ(0u, threads[i].eu);
136+
EXPECT_EQ(0u, threads[i].thread);
137+
}
138+
}
139+
140+
} // namespace ult
141+
} // namespace L0

0 commit comments

Comments
 (0)