Add software tags

Related-To: NEO-344

Signed-off-by: Konstanty Misiak <konstanty.misiak@intel.com>
This commit is contained in:
Konstanty Misiak
2021-01-26 11:22:10 +00:00
committed by Compute-Runtime-Automation
parent d1f95a0ff8
commit 88a1593913
17 changed files with 922 additions and 4 deletions

View File

@@ -36,6 +36,8 @@ DECLARE_DEBUG_VARIABLE(bool, AUBDumpAllocsOnEnqueueSVMMemcpyOnly, false, "Force
DECLARE_DEBUG_VARIABLE(bool, AUBDumpForceAllToLocalMemory, false, "Force placing every allocation in local memory address space")
/*DEBUG FLAGS*/
DECLARE_DEBUG_VARIABLE(bool, EnableSWTags, false, "Enable software tagging in batch buffer")
DECLARE_DEBUG_VARIABLE(bool, DumpSWTagsBXML, false, "Dump software tags BXML into a file")
DECLARE_DEBUG_VARIABLE(bool, DisableTimestampPacketOptimizations, false, "Allocate new allocation per node + dont reuse old nodes")
DECLARE_DEBUG_VARIABLE(bool, DisableCachingForStatefulBufferAccess, false, "Disable caching for stateful buffer access")
DECLARE_DEBUG_VARIABLE(bool, EnableDebugBreak, true, "Enable DEBUG_BREAKs")

View File

@@ -19,6 +19,7 @@
#include "shared/source/os_interface/os_interface.h"
#include "shared/source/os_interface/os_time.h"
#include "shared/source/source_level_debugger/source_level_debugger.h"
#include "shared/source/utilities/software_tags_manager.h"
namespace NEO {
@@ -34,6 +35,7 @@ Device::Device(ExecutionEnvironment *executionEnvironment)
Device::~Device() {
DEBUG_BREAK_IF(nullptr == executionEnvironment->memoryManager.get());
if (performanceCounters) {
performanceCounters->shutdown();
}
@@ -99,6 +101,10 @@ bool Device::createDeviceImpl() {
}
}
if (DebugManager.flags.EnableSWTags.get() && !getRootDeviceEnvironment().tagsManager->isInitialized()) {
getRootDeviceEnvironment().tagsManager->initialize(*this);
}
return true;
}

View File

@@ -15,6 +15,7 @@
#include "shared/source/helpers/bindless_heaps_helper.h"
#include "shared/source/helpers/hw_helper.h"
#include "shared/source/memory_manager/memory_manager.h"
#include "shared/source/utilities/software_tags_manager.h"
namespace NEO {
extern CommandStreamReceiver *createCommandStream(ExecutionEnvironment &executionEnvironment,
@@ -24,6 +25,10 @@ extern CommandStreamReceiver *createCommandStream(ExecutionEnvironment &executio
RootDevice::RootDevice(ExecutionEnvironment *executionEnvironment, uint32_t rootDeviceIndex) : Device(executionEnvironment), rootDeviceIndex(rootDeviceIndex) {}
RootDevice::~RootDevice() {
if (getRootDeviceEnvironment().tagsManager) {
getRootDeviceEnvironment().tagsManager->shutdown();
}
for (auto subdevice : subdevices) {
if (subdevice) {
delete subdevice;
@@ -94,6 +99,7 @@ bool RootDevice::createDeviceImpl() {
if (ApiSpecificConfig::getBindlessConfiguration()) {
this->executionEnvironment->rootDeviceEnvironments[getRootDeviceIndex()]->createBindlessHeapsHelper(getMemoryManager(), getNumAvailableDevices() > 1, rootDeviceIndex);
}
return true;
}

View File

@@ -19,11 +19,16 @@
#include "shared/source/memory_manager/memory_manager.h"
#include "shared/source/memory_manager/memory_operations_handler.h"
#include "shared/source/os_interface/os_interface.h"
#include "shared/source/utilities/software_tags_manager.h"
namespace NEO {
RootDeviceEnvironment::RootDeviceEnvironment(ExecutionEnvironment &executionEnvironment) : executionEnvironment(executionEnvironment) {
hwInfo = std::make_unique<HardwareInfo>();
if (DebugManager.flags.EnableSWTags.get()) {
tagsManager = std::make_unique<SWTagsManager>();
}
}
RootDeviceEnvironment::~RootDeviceEnvironment() = default;

View File

@@ -28,6 +28,7 @@ class HwDeviceId;
class MemoryManager;
class MemoryOperationsHandler;
class OSInterface;
class SWTagsManager;
struct HardwareInfo;
constexpr uint32_t allSubDevicesActive = std::numeric_limits<uint32_t>::max();
@@ -67,6 +68,7 @@ struct RootDeviceEnvironment {
std::unique_ptr<CompilerInterface> compilerInterface;
std::unique_ptr<BuiltIns> builtins;
std::unique_ptr<Debugger> debugger;
std::unique_ptr<SWTagsManager> tagsManager;
ExecutionEnvironment &executionEnvironment;
uint32_t deviceAffinityMask = allSubDevicesActive;

View File

@@ -1,5 +1,5 @@
#
# Copyright (C) 2019-2020 Intel Corporation
# Copyright (C) 2019-2021 Intel Corporation
#
# SPDX-License-Identifier: MIT
#
@@ -28,6 +28,10 @@ set(NEO_CORE_UTILITIES
${CMAKE_CURRENT_SOURCE_DIR}/perf_profiler.h
${CMAKE_CURRENT_SOURCE_DIR}/range.h
${CMAKE_CURRENT_SOURCE_DIR}/reference_tracked_object.h
${CMAKE_CURRENT_SOURCE_DIR}/software_tags.cpp
${CMAKE_CURRENT_SOURCE_DIR}/software_tags.h
${CMAKE_CURRENT_SOURCE_DIR}/software_tags_manager.cpp
${CMAKE_CURRENT_SOURCE_DIR}/software_tags_manager.h
${CMAKE_CURRENT_SOURCE_DIR}/spinlock.h
${CMAKE_CURRENT_SOURCE_DIR}/stackvec.h
${CMAKE_CURRENT_SOURCE_DIR}/tag_allocator.h

View File

@@ -0,0 +1,153 @@
/*
* Copyright (C) 2021 Intel Corporation
*
* SPDX-License-Identifier: MIT
*
*/
#include "shared/source/utilities/software_tags.h"
#include "shared/source/debug_settings/debug_settings_manager.h"
#include "shared/source/helpers/file_io.h"
namespace NEO {
namespace SWTags {
void BXMLHeapInfo::bxml(std::ostream &os) {
os << "<Structure Name=\"SWTAG_BXML_HEAP_INFO\" Source=\"Driver\" Project=\"All\">\n";
os << " <Description>BXML heap info. This will always be at offset 0.</Description>\n";
os << " <DWord Name=\"0\">\n";
os << " <BitField HighBit=\"31\" LowBit=\"0\" Name=\"MagicNumber\" Format=\"U32\">\n";
os << " <Description>This is the target of the MI_STORE_DATA_IMM that specifies where the heap exists. This value will always be 0xDEB06D0C.</Description>\n";
os << " <ValidValue Value=\"DEB06D0Ch\" IsDefault=\"true\" Name=\"SWTAG_MAGIC_NUMBER\" />\n";
os << " </BitField>\n";
os << " </DWord>\n";
os << " <DWord Name=\"1\">\n";
os << " <BitField HighBit=\"31\" LowBit=\"0\" Name=\"HeapSize\" Format=\"U32\">\n";
os << " <Description>Specifies the size in DWORDs of the BXML buffer allocated by the UMD driver.</Description>\n";
os << " </BitField>\n";
os << " </DWord>\n";
os << " <DWord Name=\"2\">\n";
os << " <BitField HighBit=\"31\" LowBit=\"0\" Name=\"Component\" Format=\"U32\">\n";
os << " <Description>Specifies the component type.</Description>\n";
os << " </BitField>\n";
os << " </DWord>\n";
os << "</Structure>\n";
}
void SWTagHeapInfo::bxml(std::ostream &os) {
os << "<Structure Name=\"SWTAG_HEAP_INFO\" Source=\"Driver\" Project=\"All\">\n";
os << " <Description>Software tag heap info. This will always be at offset 0.</Description>\n";
os << " <DWord Name=\"0\">\n";
os << " <BitField HighBit=\"31\" LowBit=\"0\" Name=\"MagicNumber\" Format=\"U32\">\n";
os << " <Description>This is the target of the MI_STORE_DATA_IMM that specifies where the heap exists. This value will always be 0xDEB06DD1.</Description>\n";
os << " <ValidValue Value=\"DEB06DD1h\" IsDefault=\"true\" Name=\"SWTAG_MAGIC_NUMBER\"/>\n";
os << " </BitField>\n";
os << " </DWord>\n";
os << " <DWord Name=\"1\">\n";
os << " <BitField HighBit=\"31\" LowBit=\"0\" Name=\"HeapSize\" Format=\"U32\">\n";
os << " <Description>Specifies the size in DWORDs of the tag heap allocated by the UMD driver. Maximum value is 1MB.</Description>\n";
os << " </BitField>\n";
os << " </DWord>\n";
os << " <DWord Name=\"2\">\n";
os << " <BitField HighBit=\"31\" LowBit=\"0\" Name=\"Component\" Format=\"U32\">\n";
os << " <Description>Specifies the component type.</Description>\n";
os << " </BitField>\n";
os << " </DWord>\n";
os << "</Structure>\n";
}
uint32_t BaseTag::getMarkerNoopID(OpCode opcode) {
MarkerNoopID id;
id.OpCode = static_cast<uint32_t>(opcode);
id.Reserved = 0;
return id.value;
}
uint32_t BaseTag::getOffsetNoopID(uint32_t offset) {
OffsetNoopID id;
id.Offset = offset / sizeof(uint32_t);
id.SubTag = 0;
id.MagicBit = 1;
id.Reserved = 0;
return id.value;
}
void BaseTag::bxml(std::ostream &os, OpCode opcode, size_t size, const char *name) {
os << " <DWord Name=\"0\">\n";
os << " <BitField Name=\"DriverDebug\" HighBit=\"31\" LowBit=\"31\" Format=\"OpCode\">\n";
os << " <Description>Specifies this is a SW driver debug tag.</Description>\n";
os << " <ValidValue Value=\"1\" IsDefault=\"true\" Name=\"DRIVER_DEBUG\" />\n";
os << " </BitField>\n";
os << " <BitField Name=\"Component\" HighBit=\"30\" LowBit=\"24\" Format=\"OpCode\">\n";
os << " <Description>Specifies the component type.</Description>\n";
os << " <ValidValue Value=\"1h\" IsDefault=\"true\" Name=\"COMMON\" />\n";
os << " </BitField>\n";
os << " <BitField Name=\"OpCode\" HighBit=\"23\" LowBit=\"0\" Format=\"OpCode\">\n";
os << " <Description>Specifies the opcode.</Description>\n";
os << " <ValidValue Value=\"" << static_cast<uint32_t>(opcode) << "\" IsDefault=\"true\" Name=\"" << name << "\" />\n";
os << " </BitField>\n";
os << " </DWord>\n";
os << " <DWord Name=\"1\">\n";
os << " <BitField Name=\"DWORDCount\" HighBit=\"31\" LowBit=\"0\" Format=\"=n\">\n";
os << " <Description>Specifies the tag size in DWORDs (TotalSize - 2)</Description>\n";
os << " <ValidValue Value=\"" << static_cast<uint32_t>(size / sizeof(uint32_t) - 2) << "\" IsDefault=\"true\" Name=\"DWORD_COUNT_n\" />\n";
os << " </BitField>\n";
os << " </DWord>\n";
}
void KernelNameTag::bxml(std::ostream &os) {
os << "<Instruction Name=\"KernelName\" Source=\"Driver\" Project=\"All\" LengthBias=\"2\">\n";
os << " <Description>Name of the kernel.</Description>\n";
BaseTag::bxml(os, OpCode::KernelName, sizeof(KernelNameTag), "KERNEL_NAME");
unsigned int stringDWORDSize = KENEL_NAME_STR_LENGTH / sizeof(uint32_t);
os << " <Dword Name=\"2.." << 2 + stringDWORDSize << "\">\n";
os << " <BitField Name=\"KernelName\" HighBit=\"" << 32 * stringDWORDSize - 1 << "\" LowBit=\"0\" Format=\"string\">\n";
os << " <Description>Name of the kernel.</Description>\n";
os << " </BitField>\n";
os << " </Dword>\n";
os << "</Instruction>\n";
}
void PipeControlReasonTag::bxml(std::ostream &os) {
os << "<Instruction Name=\"PipeControlReason\" Source=\"Driver\" Project=\"All\" LengthBias=\"2\">\n";
os << " <Description>Reason for why the PIPE_CONTROL was inserted.</Description>\n";
BaseTag::bxml(os, OpCode::PipeControlReason, sizeof(PipeControlReasonTag), "PIPE_CONTROL_REASON");
unsigned int stringDWORDSize = REASON_STR_LENGTH / sizeof(uint32_t);
os << " <Dword Name=\"2.." << 2 + stringDWORDSize << "\">\n";
os << " <BitField Name=\"PipeControlReason\" HighBit=\"" << 32 * stringDWORDSize - 1 << "\" LowBit=\"0\" Format=\"string\">\n";
os << " <Description>Reason of the PIPE_CONTROL.</Description>\n";
os << " </BitField>\n";
os << " </Dword>\n";
os << "</Instruction>\n";
}
SWTagBXML::SWTagBXML() {
std::ostringstream ss;
ss << "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n";
ss << "<BSpec>\n";
BXMLHeapInfo::bxml(ss);
SWTagHeapInfo::bxml(ss);
KernelNameTag::bxml(ss);
PipeControlReasonTag::bxml(ss);
ss << "</BSpec>";
str = ss.str();
if (DebugManager.flags.DumpSWTagsBXML.get()) {
writeDataToFile("swtagsbxml_dump.xml", str.c_str(), str.size());
}
}
} // namespace SWTags
} // namespace NEO

View File

@@ -0,0 +1,120 @@
/*
* Copyright (C) 2021 Intel Corporation
*
* SPDX-License-Identifier: MIT
*
*/
#pragma once
#include "shared/source/helpers/string.h"
#include <sstream>
#include <string>
namespace NEO {
namespace SWTags {
enum class OpCode : uint32_t {
Unknown,
KernelName,
PipeControlReason
};
enum class Component : uint32_t {
COMMON = 1
};
struct BXMLHeapInfo {
const uint32_t magicNumber = 0xDEB06D0C;
const uint32_t heapSize;
const uint32_t component = static_cast<uint32_t>(Component::COMMON);
BXMLHeapInfo(size_t size) : heapSize(static_cast<uint32_t>(size)) {}
static void bxml(std::ostream &os);
};
struct SWTagHeapInfo {
const uint32_t magicNumber = 0xDEB06DD1;
const uint32_t heapSize;
const uint32_t component = static_cast<uint32_t>(Component::COMMON);
SWTagHeapInfo(size_t size) : heapSize(static_cast<uint32_t>(size)) {}
static void bxml(std::ostream &os);
};
struct BaseTag {
public:
BaseTag(OpCode code, size_t size) : opcode(static_cast<uint32_t>(code)),
reserved(0),
component(static_cast<uint32_t>(Component::COMMON)),
driverDebug(1),
DWORDCount(static_cast<uint32_t>(size / sizeof(uint32_t) - 2)) {}
OpCode getOpCode() const { return static_cast<OpCode>(opcode); }
static uint32_t getMarkerNoopID(OpCode opcode);
static uint32_t getOffsetNoopID(uint32_t offset);
static void bxml(std::ostream &os, OpCode opcode, size_t size, const char *name);
protected:
union MarkerNoopID {
struct {
uint32_t OpCode : 20;
uint32_t Reserved : 12;
};
uint32_t value;
};
union OffsetNoopID {
struct {
uint32_t Offset : 20;
uint32_t SubTag : 1;
uint32_t MagicBit : 1;
uint32_t Reserved : 10;
};
uint32_t value;
};
const uint32_t opcode : 20;
const uint32_t reserved : 4;
const uint32_t component : 7;
const uint32_t driverDebug : 1; // always 0x1
const uint32_t DWORDCount;
};
struct KernelNameTag : public BaseTag {
public:
KernelNameTag(const char *name)
: BaseTag(OpCode::KernelName, sizeof(KernelNameTag)) {
strcpy_s(kernelName, KENEL_NAME_STR_LENGTH, name);
}
static void bxml(std::ostream &os);
private:
static constexpr unsigned int KENEL_NAME_STR_LENGTH = sizeof(uint32_t) * 16; // Dword aligned
char kernelName[KENEL_NAME_STR_LENGTH] = {};
};
struct PipeControlReasonTag : public BaseTag {
public:
PipeControlReasonTag(const char *reason)
: BaseTag(OpCode::PipeControlReason, sizeof(PipeControlReasonTag)) {
strcpy_s(reasonString, REASON_STR_LENGTH, reason);
}
static void bxml(std::ostream &os);
private:
static constexpr unsigned int REASON_STR_LENGTH = sizeof(uint32_t) * 32; // Dword aligned
char reasonString[REASON_STR_LENGTH] = {};
};
struct SWTagBXML {
SWTagBXML();
std::string str;
};
} // namespace SWTags
} // namespace NEO

View File

@@ -0,0 +1,56 @@
/*
* Copyright (C) 2021 Intel Corporation
*
* SPDX-License-Identifier: MIT
*
*/
#include "shared/source/utilities/software_tags_manager.h"
namespace NEO {
void SWTagsManager::initialize(Device &device) {
UNRECOVERABLE_IF(initialized);
memoryManager = device.getMemoryManager();
allocateBXMLHeap(device);
allocateSWTagHeap(device);
initialized = true;
}
void SWTagsManager::shutdown() {
UNRECOVERABLE_IF(!initialized);
memoryManager->freeGraphicsMemory(bxmlHeap);
memoryManager->freeGraphicsMemory(tagHeap);
initialized = false;
}
void SWTagsManager::allocateBXMLHeap(Device &device) {
SWTags::SWTagBXML tagBXML;
size_t heapSizeInBytes = sizeof(SWTags::BXMLHeapInfo) + tagBXML.str.size() + 1;
const AllocationProperties properties{
device.getRootDeviceIndex(),
heapSizeInBytes,
GraphicsAllocation::AllocationType::LINEAR_STREAM,
device.getDeviceBitfield()};
bxmlHeap = memoryManager->allocateGraphicsMemoryWithProperties(properties);
SWTags::BXMLHeapInfo bxmlHeapInfo(heapSizeInBytes / sizeof(uint32_t));
MemoryTransferHelper::transferMemoryToAllocation(false, device, bxmlHeap, 0, &bxmlHeapInfo, sizeof(bxmlHeapInfo));
MemoryTransferHelper::transferMemoryToAllocation(false, device, bxmlHeap, sizeof(bxmlHeapInfo), tagBXML.str.c_str(), heapSizeInBytes - sizeof(bxmlHeapInfo));
}
void SWTagsManager::allocateSWTagHeap(Device &device) {
const AllocationProperties properties{
device.getRootDeviceIndex(),
MAX_TAG_HEAP_SIZE,
GraphicsAllocation::AllocationType::LINEAR_STREAM,
device.getDeviceBitfield()};
tagHeap = memoryManager->allocateGraphicsMemoryWithProperties(properties);
SWTags::SWTagHeapInfo tagHeapInfo(MAX_TAG_HEAP_SIZE / sizeof(uint32_t));
MemoryTransferHelper::transferMemoryToAllocation(false, device, tagHeap, 0, &tagHeapInfo, sizeof(tagHeapInfo));
currentHeapOffset += sizeof(tagHeapInfo);
}
} // namespace NEO

View File

@@ -0,0 +1,122 @@
/*
* Copyright (C) 2021 Intel Corporation
*
* SPDX-License-Identifier: MIT
*
*/
#pragma once
#include "shared/source/debug_settings/debug_settings_manager.h"
#include "shared/source/memory_manager/memory_manager.h"
#include "shared/source/utilities/software_tags.h"
namespace NEO {
class Device;
class GraphicsAllocation;
class LinearStream;
class SWTagsManager {
public:
SWTagsManager() = default;
void initialize(Device &device);
void shutdown();
bool isInitialized() const { return initialized; }
GraphicsAllocation *getBXMLHeapAllocation() { return bxmlHeap; }
GraphicsAllocation *getSWTagHeapAllocation() { return tagHeap; }
template <typename GfxFamily>
void insertBXMLHeapAddress(LinearStream &cmdStream);
template <typename GfxFamily>
void insertSWTagHeapAddress(LinearStream &cmdStream);
template <typename GfxFamily, typename Tag, typename... Params>
void insertTag(LinearStream &cmdStream, Device &device, Params... params);
template <typename GfxFamily>
static size_t estimateSpaceForSWTags();
static const unsigned int MAX_TAG_COUNT = 20;
static const unsigned int MAX_TAG_HEAP_SIZE = 1024;
private:
void allocateBXMLHeap(Device &device);
void allocateSWTagHeap(Device &device);
MemoryManager *memoryManager;
GraphicsAllocation *tagHeap = nullptr;
GraphicsAllocation *bxmlHeap = nullptr;
unsigned int currentHeapOffset = 0;
unsigned int currentTagCount = 0;
bool initialized = false;
};
template <typename GfxFamily>
void SWTagsManager::insertBXMLHeapAddress(LinearStream &cmdStream) {
using MI_STORE_DATA_IMM = typename GfxFamily::MI_STORE_DATA_IMM;
auto ptr = reinterpret_cast<SWTags::BXMLHeapInfo *>(memoryManager->lockResource(bxmlHeap));
MI_STORE_DATA_IMM storeDataImm = GfxFamily::cmdInitStoreDataImm;
storeDataImm.setAddress(bxmlHeap->getGpuAddress());
storeDataImm.setDwordLength(MI_STORE_DATA_IMM::DWORD_LENGTH::DWORD_LENGTH_STORE_DWORD);
storeDataImm.setDataDword0(ptr->magicNumber);
memoryManager->unlockResource(bxmlHeap);
auto sdiSpace = cmdStream.getSpaceForCmd<MI_STORE_DATA_IMM>();
*sdiSpace = storeDataImm;
}
template <typename GfxFamily>
void SWTagsManager::insertSWTagHeapAddress(LinearStream &cmdStream) {
using MI_STORE_DATA_IMM = typename GfxFamily::MI_STORE_DATA_IMM;
auto ptr = reinterpret_cast<SWTags::BXMLHeapInfo *>(memoryManager->lockResource(tagHeap));
MI_STORE_DATA_IMM storeDataImm = GfxFamily::cmdInitStoreDataImm;
storeDataImm.setAddress(tagHeap->getGpuAddress());
storeDataImm.setDwordLength(MI_STORE_DATA_IMM::DWORD_LENGTH::DWORD_LENGTH_STORE_DWORD);
storeDataImm.setDataDword0(ptr->magicNumber);
memoryManager->unlockResource(tagHeap);
auto sdiSpace = cmdStream.getSpaceForCmd<MI_STORE_DATA_IMM>();
*sdiSpace = storeDataImm;
}
template <typename GfxFamily, typename Tag, typename... Params>
void SWTagsManager::insertTag(LinearStream &cmdStream, Device &device, Params... params) {
using MI_NOOP = typename GfxFamily::MI_NOOP;
unsigned int tagSize = sizeof(Tag);
if (currentTagCount >= MAX_TAG_COUNT || currentHeapOffset + tagSize > MAX_TAG_HEAP_SIZE) {
return;
}
++currentTagCount;
Tag tag(std::forward<Params>(params)...);
MemoryTransferHelper::transferMemoryToAllocation(false, device, tagHeap, currentHeapOffset, &tag, tagSize);
MI_NOOP marker = GfxFamily::cmdInitNoop;
marker.setIdentificationNumber(tag.getMarkerNoopID(tag.getOpCode()));
marker.setIdentificationNumberRegisterWriteEnable(true);
MI_NOOP offset = GfxFamily::cmdInitNoop;
offset.setIdentificationNumber(tag.getOffsetNoopID(currentHeapOffset));
currentHeapOffset += tagSize;
MI_NOOP *pNoop = cmdStream.getSpaceForCmd<MI_NOOP>();
*pNoop = marker;
pNoop = cmdStream.getSpaceForCmd<MI_NOOP>();
*pNoop = offset;
}
template <typename GfxFamily>
size_t SWTagsManager::estimateSpaceForSWTags() {
using MI_STORE_DATA_IMM = typename GfxFamily::MI_STORE_DATA_IMM;
using MI_NOOP = typename GfxFamily::MI_NOOP;
return 2 * sizeof(MI_STORE_DATA_IMM) + 2 * MAX_TAG_COUNT * sizeof(MI_NOOP);
}
} // namespace NEO

View File

@@ -18,6 +18,7 @@ target_sources(${TARGET_NAME} PRIVATE
${CMAKE_CURRENT_SOURCE_DIR}/numeric_tests.cpp
${CMAKE_CURRENT_SOURCE_DIR}/perf_profiler_tests.cpp
${CMAKE_CURRENT_SOURCE_DIR}/reference_tracked_object_tests.cpp
${CMAKE_CURRENT_SOURCE_DIR}/software_tags_manager_tests.cpp
${CMAKE_CURRENT_SOURCE_DIR}/spinlock_tests.cpp
${CMAKE_CURRENT_SOURCE_DIR}/timer_util_tests.cpp
${CMAKE_CURRENT_SOURCE_DIR}/vec_tests.cpp

View File

@@ -0,0 +1,256 @@
/*
* Copyright (C) 2021 Intel Corporation
*
* SPDX-License-Identifier: MIT
*
*/
#include "shared/source/helpers/file_io.h"
#include "shared/source/utilities/software_tags_manager.h"
#include "shared/test/common/fixtures/device_fixture.h"
#include "shared/test/common/helpers/debug_manager_state_restore.h"
#include "test.h"
using namespace NEO;
using namespace SWTags;
constexpr static uint32_t testOpCode = 42;
struct TestTag : public BaseTag {
TestTag() : BaseTag(static_cast<OpCode>(testOpCode), sizeof(TestTag)) {}
char testString[5] = "Test";
bool testBool = true;
uint16_t testWord = 42;
uint32_t testDword = 42;
};
struct VeryLargeTag : public BaseTag {
VeryLargeTag() : BaseTag(static_cast<OpCode>(testOpCode), sizeof(VeryLargeTag)) {}
char largeBuffer[1025] = {};
};
struct SoftwareTagsManagerTests : public DeviceFixture, public ::testing::Test {
void SetUp() override {
DebugManager.flags.EnableSWTags.set(true);
DeviceFixture::SetUp();
tagsManager = pDevice->getRootDeviceEnvironment().tagsManager.get();
ASSERT_TRUE(tagsManager->isInitialized());
ASSERT_NE(nullptr, tagsManager->getBXMLHeapAllocation());
ASSERT_NE(nullptr, tagsManager->getSWTagHeapAllocation());
}
void TearDown() override {
DeviceFixture::TearDown();
}
template <typename GfxFamily>
void initializeTestCmdStream() {
const AllocationProperties properties{
pDevice->getRootDeviceIndex(),
SWTagsManager::estimateSpaceForSWTags<GfxFamily>(),
GraphicsAllocation::AllocationType::LINEAR_STREAM,
pDevice->getDeviceBitfield()};
GraphicsAllocation *allocation = pDevice->getMemoryManager()->allocateGraphicsMemoryWithProperties(properties);
testCmdStream = std::make_unique<LinearStream>(allocation);
}
void freeTestCmdStream() {
pDevice->getMemoryManager()->freeGraphicsMemory(testCmdStream->getGraphicsAllocation());
}
SWTagsManager *tagsManager;
std::unique_ptr<LinearStream> testCmdStream;
DebugManagerStateRestore dbgRestorer;
};
TEST_F(SoftwareTagsManagerTests, whenSWTagsMangerIsInitializedThenHeapAllocationsAreCorrect) {
auto memoryMgr = pDevice->getMemoryManager();
SWTagBXML bxml;
BXMLHeapInfo bxmlInfo((sizeof(BXMLHeapInfo) + bxml.str.size() + 1) / sizeof(uint32_t));
SWTagHeapInfo tagInfo(SWTagsManager::MAX_TAG_HEAP_SIZE / sizeof(uint32_t));
auto bxmlHeap = tagsManager->getBXMLHeapAllocation();
auto tagHeap = tagsManager->getSWTagHeapAllocation();
auto ptr = memoryMgr->lockResource(bxmlHeap);
auto pBxmlInfo = reinterpret_cast<BXMLHeapInfo *>(ptr);
EXPECT_EQ(bxmlInfo.component, pBxmlInfo->component);
EXPECT_EQ(bxmlInfo.heapSize, pBxmlInfo->heapSize);
EXPECT_EQ(bxmlInfo.magicNumber, pBxmlInfo->magicNumber);
EXPECT_EQ(0, memcmp(bxml.str.c_str(), ptrOffset(ptr, sizeof(BXMLHeapInfo)), bxml.str.size()));
memoryMgr->unlockResource(bxmlHeap);
ptr = memoryMgr->lockResource(tagHeap);
auto pTagInfo = reinterpret_cast<SWTagHeapInfo *>(ptr);
EXPECT_EQ(tagInfo.component, pTagInfo->component);
EXPECT_EQ(tagInfo.heapSize, pTagInfo->heapSize);
EXPECT_EQ(tagInfo.magicNumber, pTagInfo->magicNumber);
memoryMgr->unlockResource(tagHeap);
}
HWTEST_F(SoftwareTagsManagerTests, whenHeapsAddressesAreInsertedThenCmdStreamHasCorrectContents) {
using MI_STORE_DATA_IMM = typename FamilyType::MI_STORE_DATA_IMM;
initializeTestCmdStream<FamilyType>();
tagsManager->insertBXMLHeapAddress<FamilyType>(*testCmdStream.get());
tagsManager->insertSWTagHeapAddress<FamilyType>(*testCmdStream.get());
EXPECT_EQ(testCmdStream->getUsed(), 2 * sizeof(MI_STORE_DATA_IMM));
void *bufferBase = testCmdStream->getCpuBase();
auto sdi1 = reinterpret_cast<MI_STORE_DATA_IMM *>(bufferBase);
auto sdi2 = reinterpret_cast<MI_STORE_DATA_IMM *>(ptrOffset(bufferBase, sizeof(MI_STORE_DATA_IMM)));
auto bxmlHeap = tagsManager->getBXMLHeapAllocation();
auto tagHeap = tagsManager->getSWTagHeapAllocation();
EXPECT_EQ(sdi1->getAddress(), bxmlHeap->getGpuAddress());
EXPECT_EQ(sdi2->getAddress(), tagHeap->getGpuAddress());
freeTestCmdStream();
}
HWTEST_F(SoftwareTagsManagerTests, whenTestTagIsInsertedThenItIsSuccessful) {
using MI_NOOP = typename FamilyType::MI_NOOP;
initializeTestCmdStream<FamilyType>();
tagsManager->insertTag<FamilyType, TestTag>(*testCmdStream.get(), *pDevice);
EXPECT_EQ(testCmdStream->getUsed(), 2 * sizeof(MI_NOOP));
void *bufferBase = testCmdStream->getCpuBase();
auto marker_noop = reinterpret_cast<MI_NOOP *>(bufferBase);
auto offset_noop = reinterpret_cast<MI_NOOP *>(ptrOffset(bufferBase, sizeof(MI_NOOP)));
EXPECT_EQ(BaseTag::getMarkerNoopID(static_cast<OpCode>(testOpCode)), marker_noop->getIdentificationNumber());
EXPECT_EQ(true, marker_noop->getIdentificationNumberRegisterWriteEnable());
uint32_t firstTagOffset = sizeof(SWTagHeapInfo); // SWTagHeapInfo is always on offset 0, first tag is inserted immediately after.
EXPECT_EQ(BaseTag::getOffsetNoopID(firstTagOffset), offset_noop->getIdentificationNumber());
EXPECT_EQ(false, offset_noop->getIdentificationNumberRegisterWriteEnable());
auto memoryMgr = pDevice->getMemoryManager();
auto tagHeap = tagsManager->getSWTagHeapAllocation();
TestTag tag;
auto ptr = memoryMgr->lockResource(tagHeap);
auto pTag = reinterpret_cast<TestTag *>(ptrOffset(ptr, firstTagOffset));
EXPECT_EQ(0, strcmp(tag.testString, pTag->testString));
EXPECT_EQ(tag.testBool, pTag->testBool);
EXPECT_EQ(tag.testWord, pTag->testWord);
EXPECT_EQ(tag.testDword, pTag->testDword);
memoryMgr->unlockResource(tagHeap);
freeTestCmdStream();
}
HWTEST_F(SoftwareTagsManagerTests, whenVeryLargeTagIsInsertedThenItIsNotSuccessful) {
initializeTestCmdStream<FamilyType>();
tagsManager->insertTag<FamilyType, VeryLargeTag>(*testCmdStream.get(), *pDevice);
EXPECT_EQ(0u, testCmdStream->getUsed());
freeTestCmdStream();
}
HWTEST_F(SoftwareTagsManagerTests, givenSoftwareManagerWithMaxTagsReachedWhenTagIsInsertedThenItIsNotSuccessful) {
using MI_NOOP = typename FamilyType::MI_NOOP;
initializeTestCmdStream<FamilyType>();
EXPECT_TRUE(tagsManager->MAX_TAG_HEAP_SIZE > (tagsManager->MAX_TAG_COUNT + 1) * sizeof(TestTag));
for (unsigned int i = 0; i <= tagsManager->MAX_TAG_COUNT; ++i) {
tagsManager->insertTag<FamilyType, TestTag>(*testCmdStream.get(), *pDevice);
}
EXPECT_EQ(testCmdStream->getUsed(), tagsManager->MAX_TAG_COUNT * 2 * sizeof(MI_NOOP));
tagsManager->insertTag<FamilyType, TestTag>(*testCmdStream.get(), *pDevice);
EXPECT_EQ(testCmdStream->getUsed(), tagsManager->MAX_TAG_COUNT * 2 * sizeof(MI_NOOP));
freeTestCmdStream();
}
TEST(SoftwareTagsManagerMultiDeviceTests, givenEnableSWTagsAndCreateMultipleSubDevicesWhenDeviceCreatedThenSWTagsManagerIsInitializedOnlyOnce) {
DebugManagerStateRestore dbgRestorer;
DebugManager.flags.EnableSWTags.set(true);
DebugManager.flags.CreateMultipleSubDevices.set(2);
VariableBackup<bool> mockDeviceFlagBackup(&MockDevice::createSingleDevice, false);
// This test checks if UNRECOVERABLE_IF(...) was not called
MockDevice *device = nullptr;
EXPECT_NO_THROW(device = MockDevice::createWithNewExecutionEnvironment<MockDevice>(defaultHwInfo.get()));
EXPECT_NE(device, nullptr);
delete device;
}
struct SoftwareTagsParametrizedTests : public ::testing::TestWithParam<SWTags::OpCode> {
void SetUp() override {
tagMap.emplace(OpCode::KernelName, std::make_unique<KernelNameTag>(""));
tagMap.emplace(OpCode::PipeControlReason, std::make_unique<PipeControlReasonTag>(""));
}
std::map<OpCode, std::unique_ptr<BaseTag>> tagMap;
};
INSTANTIATE_TEST_CASE_P(
SoftwareTags,
SoftwareTagsParametrizedTests,
testing::Values(
OpCode::KernelName,
OpCode::PipeControlReason));
TEST_P(SoftwareTagsParametrizedTests, whenGetOpCodeIsCalledThenCorrectValueIsReturned) {
auto opcode = GetParam();
auto tag = tagMap.at(opcode).get();
EXPECT_EQ(opcode, tag->getOpCode());
}
TEST(SoftwareTagsTests, whenGetMarkerNoopIDCalledThenCorectValueIsReturned) {
uint32_t id = SWTags::BaseTag::getMarkerNoopID(static_cast<OpCode>(testOpCode));
EXPECT_EQ(testOpCode, id);
}
TEST(SoftwareTagsTests, whenGetOffsetNoopIDCalledThenCorrectValueIsReturned) {
uint32_t address1 = 0;
uint32_t address2 = 1234;
uint32_t id1 = BaseTag::getOffsetNoopID(address1);
uint32_t id2 = BaseTag::getOffsetNoopID(address2);
EXPECT_EQ(static_cast<uint32_t>(1 << 21) | address1 / sizeof(uint32_t), id1);
EXPECT_EQ(static_cast<uint32_t>(1 << 21) | address2 / sizeof(uint32_t), id2);
}
TEST(SoftwareTagsBXMLTests, givenDumpSWTagsBXMLWhenConstructingBXMLThenAFileIsDumped) {
DebugManagerStateRestore dbgRestorer;
DebugManager.flags.DumpSWTagsBXML.set(true);
const char *filename = "swtagsbxml_dump.xml";
SWTagBXML bxml;
size_t retSize;
auto data = loadDataFromFile(filename, retSize);
EXPECT_EQ(retSize, bxml.str.size());
EXPECT_EQ(0, strcmp(data.get(), bxml.str.c_str()));
writeDataToFile(filename, "", 1);
}