* Copyright (c) 2025 Huawei Technologies Co., Ltd.
* This program is free software, you can redistribute it and/or modify it under the terms and conditions of
* CANN Open Software License Agreement Version 2.0 (the "License").
* Please refer to the License for details. You may not use this file except in compliance with the License.
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED,
* INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE.
* See LICENSE in the root of the software repository for the full text of the License.
*/
* \file ParseInput.cpp
* \brief
*/
#include "cost_model/simulation/tools/ParseInput.h"
#include <vector>
#include "nlohmann/json.hpp"
#include "cost_model/simulation/tools/visualizer.h"
#include "cost_model/simulation/base/ModelTop.h"
#include "passes/pass_utils/pass_utils.h"
#include "tilefwk/error_code.h"
#include "tilefwk/pypto_fwk_log.h"
using namespace std;
namespace CostModel {
using Json = nlohmann::json;
void ParseInput::ParseJson(std::shared_ptr<CostModel::SimSys> sim, const std::string& jsonPath)
{
std::ifstream input(jsonPath);
if (!input.is_open()) {
SIMULATION_LOGE(CostModel::ExternalErrorScene::FILE_OPEN_FAILED,
"Error: fail to open file: %s", jsonPath.c_str());
return;
}
Json j;
input >> j;
sim->enableExpectValue = false;
const auto& functions = j.at("functions");
bool foundStartFunc = false;
for (const auto& function : functions) {
std::unordered_map<int, int> tensorMagicIdMap;
tensorMagicIdMap.clear();
FunctionPtr func = std::make_shared<Function>();
func->functionHash = std::stoull(function.at("hash").get<std::string>());
func->magic = function.at("magic");
func->funcName = function.at("magicname");
if (!foundStartFunc) {
size_t pos = func->funcName.find(sim->config.startFunctionLabel);
if (pos != std::string::npos) {
foundStartFunc = true;
sim->startFuncName = func->funcName;
sim->startFuncHash = func->functionHash;
}
}
bool isCube = false;
const auto& operations = function.at("operations");
for (const auto& op : operations) {
if (op.at("opcode") == "NOP") {
continue;
}
TileOpPtr tileOp = std::make_shared<TileOp>();
tileOp->funcPtr = func;
const auto& iOperand = op.at("ioperands");
for (const auto& in : iOperand) {
int magic = in.at("magic");
auto it = tensorMagicIdMap.find(magic);
if (it != tensorMagicIdMap.end()) {
func->tiles[it->second]->consumers.emplace_back(tileOp);
tileOp->iOperand.emplace_back(func->tiles[it->second]);
continue;
}
tensorMagicIdMap[magic] = int(func->tiles.size());
TilePtr tensor = std::make_shared<Tile>(in.dump());
tensor->funcPtr = func;
tensor->consumers.emplace_back(tileOp);
func->tiles.emplace_back(tensor);
tileOp->iOperand.emplace_back(tensor);
if (tensor->nodeType == NodeType::INCAST) {
func->incastMagic.emplace_back(magic);
}
func->tileMap[tensor->magic] = tensor;
}
const auto& output = op.at("ooperands");
for (const auto& out : output) {
int magic = out["magic"];
auto it = tensorMagicIdMap.find(magic);
if (it != tensorMagicIdMap.end()) {
func->tiles[it->second]->producer = tileOp;
func->tiles[it->second]->producers.emplace_back(tileOp);
tileOp->oOperand.emplace_back(func->tiles[it->second]);
continue;
}
tensorMagicIdMap[magic] = int(func->tiles.size());
TilePtr tensor = std::make_shared<Tile>(out.dump());
tensor->funcPtr = func;
tensor->producer = tileOp;
tensor->producers.emplace_back(tileOp);
func->tiles.emplace_back(tensor);
tileOp->oOperand.emplace_back(tensor);
if (tensor->nodeType == NodeType::OUTCAST) {
func->outcastMagic.emplace_back(magic);
}
func->tileMap[tensor->magic] = tensor;
}
tileOp->opcode = op.at("opcode");
tileOp->magic = op.at("opmagic");
tileOp->bufType = OperandType::BUF_UB;
if (tileOp->IsCall()) {
tileOp->calleeHash = std::stoull(op.at("calleehash").get<std::string>());
}
tileOp->GetPipeType();
if (tileOp->pipeType == CorePipeType::PIPE_CUBE) {
isCube = true;
}
func->tileOps.emplace_back(tileOp);
}
if (isCube) {
func->machineType = MachineType::AIC;
sim->stats->totalFunctionCube++;
} else {
func->machineType = MachineType::AIV;
sim->stats->totalFunctionVec++;
}
if (sim->drawGraph) {
ModelVisualizer visualizer;
visualizer.DrawFunction(func, sim->graphsOutdir);
}
sim->stats->totalFunctionNum++;
sim->stats->totalFunctionTileOps += func->tileOps.size();
sim->functionCache.Insert(func);
}
}
bool ParseInput::FilterOpcode(std::string& opcode)
{
if (opcode == "NOP") {
return true;
}
auto allocQuery = opcode.find("ALLOC");
if (allocQuery != std::string::npos) {
return true;
}
auto phaseQuery = opcode.find("PHASE");
if (phaseQuery != std::string::npos) {
return true;
}
auto syncQuery = opcode.find("SYNC");
if (syncQuery != std::string::npos) {
return true;
}
auto barQuery = opcode.find("BAR");
if (barQuery != std::string::npos) {
return true;
}
return false;
}
void ParseInput::BuildTile(npu::tile_fwk::Function &func, std::shared_ptr<npu::tile_fwk::LogicalTensor> logicalTensor, TilePtr tile)
{
tile->magic = logicalTensor->magic;
for (auto& s : logicalTensor->shape) {
tile->shape.emplace_back(s);
}
for (auto& o : logicalTensor->offset) {
tile->offset.emplace_back(o);
}
tile->bufferType = npu::tile_fwk::MemoryTypeToString(logicalTensor->GetMemoryTypeOriginal());
tile->bufType = CostModel::BufferNameToType(tile->bufferType);
tile->GetPipeType();
tile->symbol = logicalTensor->tensor->symbol;
tile->dataTypeStr = npu::tile_fwk::DataType2String(logicalTensor->tensor->datatype);
tile->dataType = CostModel::ToDataType(tile->dataTypeStr);
std::string type = npu::tile_fwk::NodeType2String(FunctionUtils::GetNodeType(*logicalTensor, func));
tile->nodeType = CostModel::ToNodeType(type);
tile->rawMagic = logicalTensor->tensor->rawmagic;
for (auto& value : logicalTensor->tensor->rawshape) {
tile->rawShape.emplace_back(value);
}
}
void ParseInput::BuildFunctionInvoke(FunctionPtr root, std::shared_ptr<CostModel::SimSys> sim)
{
auto cache = sim->functionCache.cache;
int esgId = 0;
for (auto& op : root->tileOps) {
if (op->IsCall()) {
auto& callee = cache[op->calleeHash];
const auto& incast1 = op->iOperand;
const auto& incast2 = callee->incastMagic;
for (size_t i = 0; i < incast1.size(); i++) {
auto& t1 = incast1[i];
auto& t2 = incast2[i];
callee->invoke[esgId].binds[t2] = t1;
}
const auto& outcast1 = op->oOperand;
const auto& outcast2 = callee->outcastMagic;
for (size_t i = 0; i < outcast1.size(); i++) {
auto& t1 = outcast1[i];
auto& t2 = outcast2[i];
callee->invoke[esgId].binds[t2] = t1;
}
esgId++;
}
}
}
void ParseInput::GetTileAllocSeq(const std::vector<Operation*>& operationList, FunctionPtr func)
{
if (operationList.empty()) {
return;
}
func->tileAllocSequence.clear();
func->tileAllocSequence.resize(static_cast<int>(CorePipeType::TOTAL_CORE_PIPE_TYPE));
for (const auto& op : operationList) {
std::string opcode = op->GetOpcodeStr();
if (FilterOpcode(opcode) || op->IsCall()) {
continue;
}
auto& tileOp = func->tileOpMap[op->opmagic];
bool srcTileHasProducesor = false;
bool allDstTileMemKnown = true;
for (auto& in : tileOp->iOperand) {
if (!in->exeInfo.visited) {
in->exeInfo.visited = true;
func->tileAllocSequence[static_cast<int>(in->pipeType)].emplace_back(in->magic);
}
if (!in->producers.empty()) {
srcTileHasProducesor = true;
}
}
for (auto& out : tileOp->oOperand) {
if (!out->exeInfo.visited) {
out->exeInfo.visited = true;
func->tileAllocSequence[static_cast<int>(out->pipeType)].emplace_back(out->magic);
}
if (out->bufType == BUF_UNKNOWN || out->bufType == BUF_DDR) {
allDstTileMemKnown = false;
}
}
if ((tileOp->iOperand.size() == 0 || !srcTileHasProducesor) &&
(tileOp->oOperand.size() == 0 || !allDstTileMemKnown)) {
func->tileAllocSequence[static_cast<int>(tileOp->pipeType)].emplace_back(tileOp->magic);
}
}
bool fullCover = true;
for (auto& tile : func->tiles) {
if (!tile->exeInfo.visited) {
fullCover = false;
break;
}
}
func->hasSchedule = fullCover;
}
void ParseInput::BuildFunction(
std::shared_ptr<CostModel::SimSys> sim, npu::tile_fwk::Function* parentFunc, FunctionPtr func)
{
std::unordered_map<int, int> tileMagicIdMap;
tileMagicIdMap.clear();
bool isCube = false;
func->parentFunction = parentFunc;
func->functionHash = parentFunc->GetFunctionHash().GetHash();
func->magic = parentFunc->GetFuncMagic();
func->funcName = parentFunc->GetMagicName();
func->InitPipeExecTime();
for (const auto& incast : parentFunc->inCasts_) {
func->incastMagic.emplace_back(incast->magic);
}
for (const auto& outcast : parentFunc->outCasts_) {
func->outcastMagic.emplace_back(outcast->magic);
}
bool hasCall = false;
const auto& opAfterOOOPass = parentFunc->OperationsAfterOOO();
uint64_t seq = 0;
for (auto& op : opAfterOOOPass) {
std::string opcode = op.GetOpcodeStr();
if (FilterOpcode(opcode)) {
continue;
}
func->opSequenceAfterOOO_[op.GetOpMagic()] = seq++;
func->opMagicSequence.emplace_back(op.GetOpMagic());
}
const auto& operations = parentFunc->Operations();
for (auto& op : operations) {
std::string opcode = op.GetOpcodeStr();
if (FilterOpcode(opcode)) {
continue;
}
TileOpPtr tileOp = std::make_shared<TileOp>();
tileOp->funcPtr = func;
tileOp->operation = &op;
if (op.HasAttr(OpAttributeKey::scalar)) {
tileOp->scalarVld = true;
tileOp->scalarVal = op.GetElementAttribute(OpAttributeKey::scalar);
}
for (auto& input : op.GetIOperands()) {
int magic = input->magic;
auto it = tileMagicIdMap.find(magic);
if (it != tileMagicIdMap.end()) {
func->tiles[it->second]->consumers.emplace_back(tileOp);
tileOp->iOperand.emplace_back(func->tiles[it->second]);
continue;
}
tileMagicIdMap[magic] = func->tiles.size();
TilePtr tile = std::make_shared<Tile>();
BuildTile(*parentFunc, input, tile);
tile->funcPtr = func;
tile->consumers.emplace_back(tileOp);
func->tiles.emplace_back(tile);
tileOp->iOperand.emplace_back(tile);
func->tileMap[tile->magic] = tile;
}
for (const auto& out : op.GetOOperands()) {
int magic = out->magic;
auto it = tileMagicIdMap.find(magic);
if (it != tileMagicIdMap.end()) {
func->tiles[it->second]->producer = tileOp;
func->tiles[it->second]->producers.emplace_back(tileOp);
tileOp->oOperand.emplace_back(func->tiles[it->second]);
continue;
}
tileMagicIdMap[magic] = int(func->tiles.size());
TilePtr tile = std::make_shared<Tile>();
BuildTile(*parentFunc, out, tile);
tile->funcPtr = func;
tile->producer = tileOp;
tile->producers.emplace_back(tileOp);
func->tiles.emplace_back(tile);
tileOp->oOperand.emplace_back(tile);
func->tileMap[tile->magic] = tile;
}
tileOp->opcode = op.GetOpcodeStr();
tileOp->magic = op.GetOpMagic();
tileOp->subgraphId = op.GetSubgraphID();
tileOp->semanticLabel = op.GetSemanticLabelStr();
tileOp->bufType = OperandType::BUF_UB;
if (tileOp->IsCall()) {
hasCall = true;
tileOp->calleeHash = op.GetCalleeHash().GetHash();
}
tileOp->GetPipeType();
tileOp->IsSpecial();
if (tileOp->pipeType == CorePipeType::PIPE_CUBE) {
isCube = true;
}
func->tileOps.emplace_back(tileOp);
func->tileOpMap[tileOp->magic] = tileOp;
}
ASSERT(CostModel::ForwardSimErrorScene::BUILD_FUNCTION_ERROR,
hasCall || func->opSequenceAfterOOO_.size() == 0 || (func->tileOps.size() == func->opSequenceAfterOOO_.size()))
<< "[SIMULATION]: "
<< "hasCall=" << hasCall << " func->opSequenceAfterOOO_.size=" << func->opSequenceAfterOOO_.size()
<< " func->tileOps.size=" << func->tileOps.size();
if (sim->config.useOOOPassSeq) {
GetTileAllocSeq(parentFunc->Operations().DuplicatedOpList(), func);
}
if (isCube) {
func->machineType = MachineType::AIC;
} else {
func->machineType = MachineType::AIV;
}
CheckFunction(parentFunc, func);
}
void ParseInput::CheckTileOp(FunctionPtr func)
{
SIMULATION_LOGW("\n[Simulation Check Function]: %s", func->funcName.c_str());
for (const auto& op : func->tileOps) {
if (op->IsCall()) {
continue;
}
if (op->iOperand.size() == 0) {
SIMULATION_LOGW("TileOp has no input: %s", func->funcName.c_str());
if (op->operation != nullptr) {
SIMULATION_LOGW("Frontend Operation: %s", op->operation->Dump().c_str());
}
SIMULATION_LOGW("Simulation Op: %s", op->Dump(true).c_str());
}
if (op->oOperand.size() == 0) {
SIMULATION_LOGW("Function: %s Op: %s has no input", func->funcName.c_str(), op->Dump(true).c_str());
}
}
}
void ParseInput::CheckTile(FunctionPtr func)
{
for (auto& tile : func->tiles) {
if (tile->producers.size() == 0) {
if (std::find(func->incastMagic.begin(), func->incastMagic.end(), tile->magic) == func->incastMagic.end()) {
SIMULATION_LOGW("Tile has no producer, but not incast: %s", tile->Dump().c_str());
func->incastMagic.emplace_back(tile->magic);
}
}
if (tile->consumers.size() == 0) {
if (std::find(func->outcastMagic.begin(), func->outcastMagic.end(), tile->magic) ==
func->outcastMagic.end()) {
SIMULATION_LOGW("Tile has no consumer, but not outcast: %s", tile->Dump().c_str());
func->outcastMagic.emplace_back(tile->magic);
}
}
}
}
void ParseInput::CheckInOutCast(FunctionPtr func)
{
auto inIdx = func->incastMagic.begin();
while (inIdx != func->incastMagic.end()) {
if (func->tileMap.find((*inIdx)) == func->tileMap.end()) {
SIMULATION_LOGW("Incast not found in tileMap: %d", (*inIdx));
inIdx = func->incastMagic.erase(inIdx);
continue;
}
auto& incast = func->tileMap[(*inIdx)];
incast->nodeType = NodeType::INCAST;
if (incast->producers.size() != 0) {
SIMULATION_LOGW("Incast has producer %s", incast->Dump().c_str());
}
if (incast->consumers.size() == 0) {
SIMULATION_LOGW("Incast has no consumer %s", incast->Dump().c_str());
}
inIdx++;
}
auto outIdx = func->outcastMagic.begin();
while (outIdx != func->outcastMagic.end()) {
if (func->tileMap.find((*outIdx)) == func->tileMap.end()) {
SIMULATION_LOGW("Outcast not found in tileMap %d", (*outIdx));
outIdx = func->outcastMagic.erase(outIdx);
continue;
}
auto& outcast = func->tileMap[(*outIdx)];
outcast->nodeType = NodeType::OUTCAST;
if (outcast->producers.size() == 0) {
SIMULATION_LOGW("Outcast has no producer %s", outcast->Dump().c_str());
}
if (outcast->consumers.size() != 0) {
SIMULATION_LOGW("Outcast has no consumer %s", outcast->Dump().c_str());
}
outIdx++;
}
}
void ParseInput::CheckFunction(npu::tile_fwk::Function* parentFunc, FunctionPtr func)
{
(void)parentFunc;
CheckTileOp(func);
CheckTile(func);
CheckInOutCast(func);
}
void ParseInput::ParseFunction(
std::shared_ptr<CostModel::SimSys> sim, std::vector<npu::tile_fwk::Function*>& inputFuncs, bool topoFromRootFunc)
{
if (topoFromRootFunc) {
sim->enableExpectValue = true;
ASSERT(CostModel::ForwardSimErrorScene::BUILD_FUNCTION_ERROR, inputFuncs.size() == 1)
<< "[SIMULATION]: inputFuncs.size is not equals to 1."
<< "inputFuncs.size=" << inputFuncs.size();
for (const auto& rootFunction : inputFuncs) {
FunctionPtr func = std::make_shared<Function>();
func->functionHash = rootFunction->GetFunctionHash().GetHash();
func->magic = rootFunction->GetFuncMagic();
func->funcName = rootFunction->GetMagicName();
sim->startFuncName = func->funcName;
sim->startFuncHash = func->functionHash;
const auto& operations = rootFunction->Operations();
for (auto& topo : rootFunction->topoInfo_.GetTopology()) {
TopoInfoEntry entry;
entry.eSgId = topo.esgId;
entry.readyState = topo.readyState;
entry.outGraph = topo.outGraph;
entry.calleeHash = operations[topo.esgId].GetCalleeHash().GetHash();
func->inputTopo.push_back(entry);
}
BuildFunction(sim, rootFunction, func);
if (sim->drawGraph) {
ModelVisualizer visualizer;
visualizer.DrawFunction(func, sim->graphsOutdir);
}
func->topoFromRootFunc = true;
sim->functionCache.Insert(func);
for (auto& leafFunc : rootFunction->programs_) {
FunctionPtr lFunc = std::make_shared<Function>();
BuildFunction(sim, leafFunc.second, lFunc);
lFunc->pSgId = leafFunc.first;
lFunc->parentFunction = leafFunc.second;
if (lFunc->machineType == MachineType::AIC) {
sim->stats->totalFunctionCube++;
} else {
sim->stats->totalFunctionVec++;
}
sim->stats->totalFunctionNum++;
sim->stats->totalFunctionTileOps += lFunc->tileOps.size();
sim->functionCache.Insert(lFunc);
func->tileMap.insert(lFunc->tileMap.begin(), lFunc->tileMap.end());
if (sim->drawGraph) {
ModelVisualizer visualizer;
visualizer.DrawFunction(lFunc, sim->graphsOutdir);
}
}
BuildFunctionInvoke(func, sim);
}
return;
}
sim->enableExpectValue = false;
bool foundStartFunc = false;
for (const auto& function : inputFuncs) {
FunctionPtr func = std::make_shared<Function>();
BuildFunction(sim, function, func);
func->parentFunction = function;
if (!foundStartFunc) {
size_t pos = func->funcName.find(sim->config.startFunctionLabel);
if (pos != std::string::npos) {
foundStartFunc = true;
sim->startFuncName = func->funcName;
sim->startFuncHash = func->functionHash;
}
}
if (sim->drawGraph) {
ModelVisualizer visualizer;
visualizer.DrawFunction(func, sim->graphsOutdir);
}
sim->stats->totalFunctionNum++;
sim->stats->totalFunctionTileOps += func->tileOps.size();
sim->functionCache.Insert(func);
BuildFunctionInvoke(func, sim);
}
}
void ParseInput::ParseSingleFunction(std::shared_ptr<CostModel::SimSys> sim, npu::tile_fwk::Function* func)
{
FunctionPtr lFunc = std::make_shared<Function>();
BuildFunction(sim, func, lFunc);
sim->functionCache.Insert(lFunc);
sim->singleFuncHash = lFunc->functionHash;
if (sim->drawGraph) {
ModelVisualizer visualizer;
visualizer.DrawFunction(lFunc, sim->graphsOutdir);
}
}
void ParseInput::ParseJsonConfig(const std::string& path, std::vector<std::string>& cfg) const
{
std::ifstream file(path);
if (!file.is_open()) {
SIMULATION_LOGE(CostModel::ExternalErrorScene::FILE_OPEN_FAILED,
"Error: fail to open file: %s", path.c_str());
return;
}
Json j;
file >> j;
for (auto it = j.begin(); it != j.end(); ++it) {
std::string c = it.key() + "=" + it.value().dump();
cfg.emplace_back(c);
}
file.close();
}
void ParseInput::ParseConfig(const std::string& path, std::vector<std::string>& cfg) const
{
std::ifstream file(path);
if (!file.is_open()) {
SIMULATION_LOGE(CostModel::ExternalErrorScene::FILE_OPEN_FAILED,
"Error: fail to open file: %s", path.c_str());
return;
}
std::string line;
while (std::getline(file, line)) {
size_t pos = line.find('=');
if (pos != std::string::npos) {
cfg.emplace_back(line);
} else {
SIMULATION_LOGE(CostModel::ExternalErrorScene::FILE_CONTENT_ERROR,
"Parse Config File Error: %s", line.c_str());
}
}
file.close();
}
void ParseInput::ParseCalendarJson(std::shared_ptr<CostModel::SimSys> sim, const std::string& jsonPath) const
{
std::ifstream jsonInput(jsonPath);
if (!jsonInput.is_open()) {
SIMULATION_LOGE(CostModel::ExternalErrorScene::FILE_OPEN_FAILED,
"Error: fail to open file: %s", jsonPath.c_str());
return;
}
Json calendarJson;
jsonInput >> calendarJson;
int counterNum = calendarJson["numSupportedCounters"].get<int>();
sim->calendarCounter.resize(counterNum, 0);
std::vector<std::pair<int, int>> waitVector;
int taskId;
for (const auto& core : calendarJson["cores"]) {
for (const auto& task : core["tasks"]) {
if (task.contains("functionHash")) {
sim->taskWaitMap[task["taskId"].get<int>()] = waitVector;
sim->corePacketMap[core["coreId"].get<int>()].push_back(
{task["taskId"].get<int>(), std::stoull(task["functionHash"].get<std::string>())});
taskId = task["taskId"].get<int>();
if (sim->config.calendarMode == static_cast<uint64_t>(CalendarMode::GLOBAL_COUNTER)) {
ASSERT(CostModel::ForwardSimErrorScene::CALENDAR_ERROR, waitVector.size() == 1)
<< "[SIMULATION]: task has two wait in calendar global counter."
<< "waitVector.size=" << waitVector.size();
sim->taskFirstSetMap[taskId] = waitVector[0].second + 1;
}
waitVector.clear();
} else {
if (task["operation"].get<std::string>() == "wait") {
waitVector.push_back({task["counterId"].get<int>(), task["expectedValue"].get<int>()});
} else if (task["operation"].get<std::string>() == "set") {
sim->taskSetMap[taskId] = task["counterId"].get<int>();
sim->taskSetExpectMap[taskId] = task["expectedValue"];
} else if (task["operation"].get<std::string>() == "setWait") {
sim->taskWaitBeforeSetMap[taskId].push_back(
{task["counterId"].get<int>(), task["expectedValue"].get<int>()});
}
}
}
}
}
void ParseInput::ParseFixedLatencyTask(std::shared_ptr<CostModel::SimSys> sim, std::string const& path)
{
std::ifstream jsonInput(path);
if (!jsonInput.is_open()) {
SIMULATION_LOGE(CostModel::ExternalErrorScene::FILE_OPEN_FAILED,
"Error: fail to open file: %s", path.c_str());
return;
}
Json fixedLatencyTask;
jsonInput >> fixedLatencyTask;
uint64_t virtualRootHash = 0;
uint64_t virtualLeafHash = 1;
std::unordered_map<std::string, uint64_t> leafVirturalHashMap;
std::unordered_map<std::string, MachineType> leafMachineTypeMap;
FunctionPtr func = std::make_shared<Function>();
func->functionHash = virtualRootHash;
func->magic = virtualRootHash;
func->funcName = "virtual_root_function";
sim->startFuncName = func->funcName;
sim->startFuncHash = func->functionHash;
uint64_t cycleConvert = sim->config.fixedLatencyTimeConvert;
for (const auto& item : fixedLatencyTask) {
TopoInfoEntry entry;
entry.eSgId = item["taskId"].get<uint64_t>();
entry.readyState = item["remainingPredecessors"];
entry.readyState *= -1;
entry.outGraph = item["successors"].get<setType>();
std::string funcName = item["funcName"].get<std::string>();
if (leafVirturalHashMap.find(funcName) == leafVirturalHashMap.end()) {
leafVirturalHashMap[funcName] = virtualLeafHash++;
}
entry.calleeHash = leafVirturalHashMap[funcName];
double exeTime = item["execTime"].get<double>();
entry.fixedLatency = true;
entry.fixedLatencyVal = static_cast<uint64_t>(std::trunc(exeTime * cycleConvert));
std::string machineType = item["coreType"];
entry.mType = ToMachineType(machineType);
leafMachineTypeMap[funcName] = entry.mType;
func->inputTopo.push_back(entry);
}
func->topoFromRootFunc = true;
sim->functionCache.Insert(func);
for (auto& [funcName, funcHash] : leafVirturalHashMap) {
FunctionPtr leafFunc = std::make_shared<Function>();
leafFunc->functionHash = funcHash;
leafFunc->machineType = leafMachineTypeMap[funcName];
leafFunc->funcName = funcName;
sim->functionCache.Insert(leafFunc);
}
}
void ParseInput::ParseTopoJson(std::string path, std::deque<TaskMap>& taskMapQueue)
{
std::ifstream jsonInput(path);
if (!jsonInput.is_open()) {
SIMULATION_LOGE(CostModel::ExternalErrorScene::FILE_OPEN_FAILED,
"Error: fail to open file: %s", path.c_str());
return;
}
Json topoJson;
jsonInput >> topoJson;
std::map<uint64_t, TaskMap> groupTaskMap;
for (const auto& item : topoJson) {
auto subtask = std::make_shared<Task>();
subtask->seqNo = item.value("seqNo", 0);
subtask->taskId = item.value("taskId", 0);
subtask->leafIndex = item.value("leafIndex", 0);
subtask->opmagic = item.value("opmagic", 0);
subtask->psgId = item.value("psgId", -1);
subtask->rootIndex = item.value("rootIndex", 0);
subtask->uniqueKey = item.value("uniqueKey", subtask->taskId);
subtask->functionHash = item["funcHash"].get<uint64_t>();
subtask->machineType = ToMachineType(item["coreType"]);
subtask->successors = item["successors"].get<std::vector<uint64_t>>();
groupTaskMap[subtask->seqNo][subtask->taskId] = subtask;
}
for (auto& taskMap : groupTaskMap) {
for (auto& task : taskMap.second) {
for (auto& successor : task.second->successors) {
taskMap.second.at(successor)->predecessors.push_back(task.first);
}
}
for (auto& task : taskMap.second) {
task.second->remainingPredecessors = task.second->predecessors.size();
}
}
for (auto& entry : groupTaskMap) {
taskMapQueue.push_back(entry.second);
}
}
void ParseInput::ParseReplayInfoJson(
const std::string& path, std::unordered_map<uint64_t, std::deque<ReplayTaskEntry>>& replayTasksInfoMap)
{
std::ifstream file(path);
if (!file.is_open()) {
SIMULATION_LOGE(CostModel::ExternalErrorScene::FILE_OPEN_FAILED,
"Error: fail to open file: %s", path.c_str());
return;
}
Json j;
file >> j;
for (const auto& item : j) {
uint64_t blockIdx = item["blockIdx"];
std::string coreTypeStr = item["coreType"];
MachineType coreType = ToMachineType(coreTypeStr);
if (!IsCoreMachine(coreType)) {
continue;
}
uint64_t machineId = GetProcessID(coreType, blockIdx);
const auto& tasks = item["tasks"];
replayTasksInfoMap[machineId] = std::deque<ReplayTaskEntry>();
auto& machineTaskQ = replayTasksInfoMap[machineId];
for (const auto& task : tasks) {
uint64_t seqNo = task["seqNo"];
uint64_t taskId = task["taskId"];
uint64_t beginCycle = task["execStart"];
uint64_t endCycle = task["execEnd"];
machineTaskQ.push_back(ReplayTaskEntry(seqNo, taskId, beginCycle, endCycle));
}
}
}
}