/* * Copyright (C) 2020-2021 Intel Corporation * * SPDX-License-Identifier: MIT * */ #include "ocloc_arg_helper.h" #include "shared/source/helpers/file_io.h" #include "shared/source/helpers/hw_info.h" #include "shared/source/helpers/string.h" #include "hw_cmds.h" #include #include #include void Source::toVectorOfStrings(std::vector &lines, bool replaceTabs) { std::string line; const char *file = reinterpret_cast(data); while (*file != '\0') { if (replaceTabs && *file == '\t') { line += ' '; } else if (*file == '\n') { lines.push_back(line); line = ""; } else { line += *file; } file++; } } Output::Output(const std::string &name, const void *data, const size_t &size) : name(name), size(size) { this->data = new uint8_t[size]; memcpy_s(reinterpret_cast(this->data), this->size, data, size); }; OclocArgHelper::OclocArgHelper(const uint32_t numSources, const uint8_t **dataSources, const uint64_t *lenSources, const char **nameSources, const uint32_t numInputHeaders, const uint8_t **dataInputHeaders, const uint64_t *lenInputHeaders, const char **nameInputHeaders, uint32_t *numOutputs, uint8_t ***dataOutputs, uint64_t **lenOutputs, char ***nameOutputs) : numOutputs(numOutputs), nameOutputs(nameOutputs), dataOutputs(dataOutputs), lenOutputs(lenOutputs), hasOutput(numOutputs != nullptr), deviceProductTable({ #define NAMEDDEVICE(devId, product, ignored_gtType, ignored_devName) {devId, NEO::hardwarePrefix[NEO::product::hwInfo.platform.eProductFamily]}, #define DEVICE(devId, product, ignored_gtType) {devId, NEO::hardwarePrefix[NEO::product::hwInfo.platform.eProductFamily]}, #include "devices.inl" #undef DEVICE #undef NAMEDDEVICE {0u, std::string("")}}), deviceMap({ #define DEVICE_CONFIG_REVISION(product, productConfig, revision_id) {product, &NEO::productConfig::hwInfo, NEO::productConfig::setupHardwareInfo, revision_id}, #define DEVICE_CONFIG(product, productConfig) {product, &NEO::productConfig::hwInfo, NEO::productConfig::setupHardwareInfo, NEO::productConfig::hwInfo.platform.usRevId}, #include "product_config.inl" #undef DEVICE_CONFIG #undef DEVICE_CONFIG_REVISION {PRODUCT_CONFIG::UNKNOWN_ISA, {}, 0x0}}) { for (uint32_t i = 0; i < numSources; ++i) { inputs.push_back(Source(dataSources[i], static_cast(lenSources[i]), nameSources[i])); } for (uint32_t i = 0; i < numInputHeaders; ++i) { headers.push_back(Source(dataInputHeaders[i], static_cast(lenInputHeaders[i]), nameInputHeaders[i])); } for (unsigned int i = 0; i < IGFX_MAX_CORE; ++i) { if (NEO::familyName[i] == nullptr) continue; std::string gen = NEO::familyName[i]; std::transform(gen.begin(), gen.end(), gen.begin(), ::tolower); genIGFXMap.insert({gen, i}); } } OclocArgHelper::OclocArgHelper() : OclocArgHelper(0, nullptr, nullptr, nullptr, 0, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr) {} OclocArgHelper::~OclocArgHelper() { if (outputEnabled()) { saveOutput(oclocStdoutLogName, messagePrinter.getLog()); moveOutputs(); } } bool OclocArgHelper::fileExists(const std::string &filename) const { return sourceFileExists(filename) || ::fileExists(filename); } void OclocArgHelper::moveOutputs() { *numOutputs = static_cast(outputs.size()); *nameOutputs = new char *[outputs.size()]; *dataOutputs = new uint8_t *[outputs.size()]; *lenOutputs = new uint64_t[outputs.size()]; for (size_t i = 0; i < outputs.size(); ++i) { size_t size = outputs[i]->name.length() + 1; (*nameOutputs)[i] = new char[size]; strncpy_s((*nameOutputs)[i], size, outputs[i]->name.c_str(), outputs[i]->name.length() + 1); (*dataOutputs)[i] = outputs[i]->data; (*lenOutputs)[i] = outputs[i]->size; } } Source *OclocArgHelper::findSourceFile(const std::string &filename) { for (auto &source : inputs) { if (filename == source.name) { return &source; } } return nullptr; } bool OclocArgHelper::sourceFileExists(const std::string &filename) const { for (auto &input : inputs) { if (filename == input.name) { return true; } } return false; } std::vector OclocArgHelper::headersToVectorOfStrings() { std::vector lines; for (auto &header : headers) { header.toVectorOfStrings(lines, true); } return lines; } void OclocArgHelper::readFileToVectorOfStrings(const std::string &filename, std::vector &lines) { if (Source *s = findSourceFile(filename)) { s->toVectorOfStrings(lines); } else { ::readFileToVectorOfStrings(lines, filename); } } std::vector OclocArgHelper::readBinaryFile(const std::string &filename) { if (Source *s = findSourceFile(filename)) { return s->toBinaryVector(); } else { return ::readBinaryFile(filename); } } std::unique_ptr OclocArgHelper::loadDataFromFile(const std::string &filename, size_t &retSize) { if (Source *s = findSourceFile(filename)) { auto size = s->length; std::unique_ptr ret(new char[size]()); memcpy_s(ret.get(), size, s->data, s->length); retSize = s->length; return ret; } else { return ::loadDataFromFile(filename.c_str(), retSize); } } void OclocArgHelper::setDeviceInfoForFatbinaryTarget(const DeviceMapping &device) { deviceForFatbinary.hwInfo = device.hwInfo; deviceForFatbinary.setupHardwareInfo = device.setupHardwareInfo; deviceForFatbinary.revId = device.revId; } void OclocArgHelper::setHwInfoForFatbinaryTarget(NEO::HardwareInfo &hwInfo) { hwInfo = *deviceForFatbinary.hwInfo; deviceForFatbinary.setupHardwareInfo(&hwInfo, true); hwInfo.platform.usRevId = deviceForFatbinary.revId; } bool OclocArgHelper::getHwInfoForProductConfig(uint32_t config, NEO::HardwareInfo &hwInfo) { bool retVal = false; if (config == UNKNOWN_ISA) { return retVal; } for (auto &deviceConfig : deviceMap) { if (deviceConfig.config == config) { hwInfo = *deviceConfig.hwInfo; deviceConfig.setupHardwareInfo(&hwInfo, true); hwInfo.platform.usRevId = deviceConfig.revId; retVal = true; return retVal; } } return retVal; } void OclocArgHelper::getProductConfigsForGfxCoreFamily(GFXCORE_FAMILY core, std::vector &out) { for (auto &deviceConfig : deviceMap) { if (deviceConfig.config == PRODUCT_CONFIG::UNKNOWN_ISA) continue; if (deviceConfig.hwInfo->platform.eRenderCoreFamily == core) { out.push_back(deviceConfig); } } } void OclocArgHelper::saveOutput(const std::string &filename, const void *pData, const size_t &dataSize) { if (outputEnabled()) { addOutput(filename, pData, dataSize); } else { writeDataToFile(filename.c_str(), pData, dataSize); } } void OclocArgHelper::saveOutput(const std::string &filename, const std::ostream &stream) { std::stringstream ss; ss << stream.rdbuf(); if (outputEnabled()) { addOutput(filename, ss.str().c_str(), ss.str().length()); } else { std::ofstream file(filename); file << ss.str(); } } std::string OclocArgHelper::returnProductNameForDevice(unsigned short deviceId) { std::string res = ""; for (int i = 0; deviceProductTable[i].deviceId != 0; i++) { if (deviceProductTable[i].deviceId == deviceId) { res = deviceProductTable[i].product; } } return res; } std::vector OclocArgHelper::getAllSupportedDeviceConfigs() { std::vector allConfigs; for (auto &deviceConfig : deviceMap) { if (deviceConfig.config != PRODUCT_CONFIG::UNKNOWN_ISA) { allConfigs.push_back(deviceConfig); } } std::sort(allConfigs.begin(), allConfigs.end(), compareConfigs); return allConfigs; } const std::string OclocArgHelper::parseProductConfigFromValue(PRODUCT_CONFIG config) { auto configValue = static_cast(config); std::stringstream stringConfig; uint32_t major = (configValue & 0xff0000) >> 16; uint32_t minor = (configValue & 0x00ff00) >> 8; uint32_t revision = configValue & 0x0000ff; stringConfig << major << "." << minor << "." << revision; return stringConfig.str(); } std::vector OclocArgHelper::getAllSupportedProductConfigs() { std::vector allConfigs; for (auto &deviceConfig : deviceMap) { if (deviceConfig.config != PRODUCT_CONFIG::UNKNOWN_ISA) { allConfigs.push_back(deviceConfig.config); } } std::sort(allConfigs.begin(), allConfigs.end()); return allConfigs; } int OclocArgHelper::parseProductConfigFromString(const std::string &device, size_t begin, size_t end) { if (begin == end) { return CONFIG_STATUS::MISMATCHED_VALUE; } if (end == std::string::npos) { if (!std::all_of(device.begin() + begin, device.end(), (::isdigit))) { return CONFIG_STATUS::MISMATCHED_VALUE; } return std::stoi(device.substr(begin, device.size() - begin)); } else { if (!std::all_of(device.begin() + begin, device.begin() + end, (::isdigit))) { return CONFIG_STATUS::MISMATCHED_VALUE; } return std::stoi(device.substr(begin, end - begin)); } } std::vector OclocArgHelper::getMajorMinorRevision(const std::string &device) { std::vector numeration; auto major_pos = device.find("."); auto major = parseProductConfigFromString(device, 0, major_pos); if (major == CONFIG_STATUS::MISMATCHED_VALUE) { return {}; } numeration.push_back(major); if (major_pos == std::string::npos) { return numeration; } auto minor_pos = device.find(".", ++major_pos); auto minor = parseProductConfigFromString(device, major_pos, minor_pos); if (minor == CONFIG_STATUS::MISMATCHED_VALUE) { return {}; } numeration.push_back(minor); if (minor_pos == std::string::npos) { return numeration; } auto revision = parseProductConfigFromString(device, minor_pos + 1, device.size()); if (revision == CONFIG_STATUS::MISMATCHED_VALUE) { return {}; } numeration.push_back(revision); return numeration; } uint32_t OclocArgHelper::getProductConfig(std::vector &numeration) { uint32_t config = 0x0; config = numeration.at(0) << 16; if (numeration.size() > 1) { config |= (numeration.at(1) << 8); } if (numeration.size() > 2) { config |= numeration.at(2); } return config; } uint32_t OclocArgHelper::getMaskForConfig(std::vector &numeration) { uint32_t mask = 0xffffff; if (numeration.size() == 1) { mask = 0xff0000; } else if (numeration.size() == 2) { mask = 0xffff00; } return mask; } bool OclocArgHelper::isGen(const std::string &device) { std::string buf(device); std::transform(buf.begin(), buf.end(), buf.begin(), ::tolower); auto it = genIGFXMap.find(buf); return it == genIGFXMap.end() ? false : true; } unsigned int OclocArgHelper::returnIGFXforGen(const std::string &device) { std::string buf(device); std::transform(buf.begin(), buf.end(), buf.begin(), ::tolower); auto it = genIGFXMap.find(buf); if (it == genIGFXMap.end()) return 0; return it->second; } PRODUCT_CONFIG OclocArgHelper::findConfigMatch(const std::string &device, bool firstAppearance) { auto numeration = getMajorMinorRevision(device); if (numeration.empty()) { return PRODUCT_CONFIG::UNKNOWN_ISA; } std::vector allMatchedConfigs; std::vector allConfigs = getAllSupportedProductConfigs(); auto configValue = getProductConfig(numeration); uint32_t mask = getMaskForConfig(numeration); if (!firstAppearance) { // find last appearance std::reverse(allConfigs.begin(), allConfigs.end()); } for (auto &productConfig : allConfigs) { uint32_t value = static_cast(productConfig) & mask; if (value == configValue) { return productConfig; } } return PRODUCT_CONFIG::UNKNOWN_ISA; }