* 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 TraceLogger.cpp
* \brief
*/
#include "cost_model/simulation/statistics/TraceLogger.h"
#include <algorithm>
#include <iostream>
#include <fstream>
#include <map>
#include "cost_model/simulation/base/ModelTop.h"
using namespace std;
namespace CostModel {
Json Event::ToJson()
{
Json root;
root["name"] = name;
if (!catagory.empty()) {
root["cat"] = catagory;
}
root["ph"] = phase;
if (!bp.empty()) {
root["bp"] = bp;
}
if (id > 0) {
root["id"] = id;
}
root["ts"] = timestamp;
root["pid"] = pid;
root["tid"] = tid;
if (!hint.empty()) {
Json args;
args["event-hint"] = hint;
args["color"] = this->GetColor();
root["args"] = std::move(args);
}
return root;
}
Json Event::ToFlowStartJson(int flowId) const
{
Json root;
root["cat"] = "machine-view-last-dep";
root["id"] = flowId;
root["name"] = "machine-view-last-dep";
root["ph"] = "s";
root["pid"] = pid;
root["tid"] = tid;
root["ts"] = timestamp - 1;
return root;
}
Json Event::ToFlowEndJson(int flowId) const
{
Json root;
root["bp"] = "e";
root["cat"] = "machine-view-last-dep";
root["id"] = flowId;
root["name"] = "machine-view-last-dep";
root["ph"] = "f";
root["pid"] = pid;
root["tid"] = tid;
root["ts"] = timestamp;
return root;
}
std::string Event::GetColor()
{
size_t pos1 = name.find('(');
if (pos1 == std::string::npos) {
return "";
}
size_t pos2 = name.find(')');
if (pos2 == std::string::npos) {
return "";
}
return name.substr(pos1 + 1, pos2 - pos1 - 1);
}
int Event::ExtraHintInfo(std::string& key)
{
size_t pos = hint.find(key);
pos += key.length();
std::string numStr = hint.substr(pos);
size_t spacePos = numStr.find(' ');
numStr = numStr.substr(0, spacePos);
std::stringstream ss(numStr);
int value;
ss >> value;
return value;
}
Json CounterEvent::ToJson() const
{
Json jSize;
jSize["size"] = size;
Json root;
root["args"] = jSize;
root["name"] = catagory;
root["pid"] = pid;
root["tid"] = tid;
root["ph"] = "C";
root["ts"] = timestamp;
return root;
}
Json Thread::ToJson() const
{
Json root;
Json args;
args["name"] = name;
root["args"] = std::move(args);
root["cat"] = "__metadata";
root["name"] = "thread_name";
root["ph"] = "M";
root["pid"] = pid;
root["tid"] = tid;
return root;
}
Json Process::ToJson() const
{
Json root;
Json args;
args["name"] = name;
root["args"] = std::move(args);
root["cat"] = "__metadata";
root["name"] = "process_name";
root["ph"] = "M";
root["pid"] = pid;
return root;
}
Json Process::ToSortIndexJson(int sortIndex) const
{
Json root;
Json args;
args["sort_index"] = sortIndex;
root["args"] = std::move(args);
root["cat"] = "__metadata";
root["name"] = "process_sort_index";
root["ph"] = "M";
root["pid"] = pid;
return root;
}
void Duration::OutputContextSwitchTrace(
std::ofstream& os, std::map<Pid, Process>& mProcesses, std::map<PTid, Thread>& mThreads,
const uint64_t sysClockTicks)
{
string processInfo = to_string(start.tid);
std::string subgraphName = "SUBGRAPH";
auto it = mThreads.find(PTid{start.pid, start.tid});
if (it != mThreads.end()) {
subgraphName = it->second.name;
}
std::ostringstream cpuId;
int formatOffset = 3;
cpuId << setfill('0') << setw(formatOffset) << mProcesses[start.tid].coreIdx;
string cpuIdx = cpuId.str();
string cpuInfo = "( 0) [" + cpuIdx + "] ....";
string cpuMgrTile = "cpumgr-idle-" + to_string(start.pid);
string cpuSwitchTitle = subgraphName + "-" + to_string(start.tid);
string cpuWakeupInfo =
": sched_wakeup: comm=" + subgraphName + " pid=" + processInfo + " prio=20 target_cpu=" + cpuIdx;
string cpuSwitchInfo1 =
": sched_switch: prev_comm=cpumgr-idle-0 prev_pid=0 prev_prio=-2 prev_state=R+ ==> next_comm=" + subgraphName +
" next_pid=" + processInfo + " next_prio=5";
string cpuSwitchInfo2 = ": sched_switch: prev_comm=" + subgraphName + " prev_pid=" + processInfo +
" prev_prio=5 prev_state= ==> next_comm=cpumgr-idle-0 next_pid=0 next_prio=-2";
string cpuIdleInfo = ": cpu_idle: state=0 cpu_id=" + cpuIdx;
std::ostringstream cyc1;
int precision = 6;
cyc1 << std::fixed << std::setprecision(precision) << (double(start.timestamp) / sysClockTicks);
string sCycle = cyc1.str();
std::ostringstream cyc2;
cyc2 << std::fixed << std::setprecision(precision) << (double(end.timestamp) / sysClockTicks);
string eCycle = cyc2.str();
os << setw(width) << left << cpuMgrTile << setw(width) << right << cpuInfo << setw(width2) << right << sCycle;
os << cpuWakeupInfo << std::endl;
os << setw(width) << left << cpuSwitchTitle << setw(width) << right << cpuInfo << setw(width2) << right << sCycle;
os << cpuSwitchInfo1 << std::endl;
os << setw(width) << left << cpuMgrTile << setw(width) << right << cpuInfo << setw(width2) << right << eCycle;
os << cpuSwitchInfo2 << std::endl;
os << setw(width) << left << cpuMgrTile << setw(width) << right << cpuInfo << setw(width2) << right << eCycle;
os << cpuIdleInfo << std::endl;
}
void Duration::OutputBeginEndTrace(
std::ofstream& os, std::map<Pid, Process>& mProcesses, std::map<PTid, Thread>& mThreads,
const uint64_t sysClockTicks)
{
string processInfo = to_string(start.pid);
std::ostringstream cpuId;
int formatOffset = 3;
cpuId << setfill('0') << setw(formatOffset) << mProcesses[start.pid].coreIdx;
string cpuIdx = cpuId.str();
string cpuInfo = "(" + processInfo + ") [" + cpuIdx + "] ....";
string pipeName = "";
auto it = mThreads.find(PTid{start.pid, start.tid});
if (it != mThreads.end()) {
pipeName = it->second.name;
}
string title = pipeName + "-" + to_string(start.tid);
string beginInfo = ": tracing_mark_write: B|" + processInfo + "|" + start.name + " " + start.hint;
string endInfo = ": tracing_mark_write: E|" + processInfo + "|";
std::ostringstream cyc1;
int precision = 6;
cyc1 << std::fixed << std::setprecision(precision) << (double(start.timestamp) / sysClockTicks);
string sCycle = cyc1.str();
std::ostringstream cyc2;
cyc2 << std::fixed << std::setprecision(precision) << (double(end.timestamp) / sysClockTicks);
string eCycle = cyc2.str();
os << setw(width) << left << title << setw(width) << right << cpuInfo << setw(width2) << right << sCycle;
os << beginInfo << std::endl;
os << setw(width) << left << title << setw(width) << right << cpuInfo << setw(width2) << right << eCycle;
os << endInfo << std::endl;
}
Json Duration::ToJson()
{
Json root;
if (!start.catagory.empty()) {
root["cat"] = start.catagory;
}
root["ph"] = "X";
root["id"] = start.id;
root["name"] = start.name;
root["pid"] = start.pid;
root["tid"] = start.tid;
root["ts"] = start.timestamp;
root["dur"] = end.timestamp - start.timestamp;
if (!start.hint.empty()) {
Json args;
args["event-hint"] = start.hint;
args["color"] = start.GetColor();
root["args"] = std::move(args);
}
return root;
}
void TraceLogger::SetProcessName(std::string name, CostModel::Pid pid, size_t coreIdx)
{
mProcesses[pid] = Process{
.name = name,
.pid = pid,
.coreIdx = coreIdx,
};
mMachineTileOpMap[pid] = std::map<int, int>();
}
void TraceLogger::SetThreadName(std::string name, CostModel::Pid pid, CostModel::Tid tid)
{
mThreads[PTid{pid, tid}] = Thread{
.name = name,
.pid = pid,
.tid = tid,
};
}
Event TraceLogger::AddEventBegin(
std::string name, CostModel::Pid pid, CostModel::Tid tid, CostModel::TimeStamp timestamp, std::string hint)
{
mEventIdPtr++;
auto beginEvent = Event{
.name = name,
.id = mEventIdPtr,
.catagory = "event",
.phase = "B",
.bp = "",
.timestamp = timestamp,
.pid = pid,
.tid = tid,
.hint = hint,
};
mEvents.push_back(beginEvent);
m_eventStacks[PTid{pid, tid}].push(beginEvent);
return beginEvent;
}
Event TraceLogger::AddEventEnd(CostModel::Pid pid, CostModel::Tid tid, CostModel::TimeStamp timestamp)
{
auto beginEvent = m_eventStacks[PTid{pid, tid}].top();
m_eventStacks[PTid{pid, tid}].pop();
auto endEvent = Event{
.name = beginEvent.name,
.id = beginEvent.id,
.catagory = "event",
.phase = "E",
.bp = "",
.timestamp = timestamp,
.pid = pid,
.tid = tid,
.hint = beginEvent.hint,
};
mEvents.push_back(endEvent);
mDurations.emplace(beginEvent.id, Duration{beginEvent, endEvent});
auto machineType = GetMachineType(tid);
if (pid == topMachineViewPid && IsCoreMachine(machineType)) {
std::string taskKey = "TaskId:";
auto pos = beginEvent.hint.find(taskKey);
if (pos != std::string::npos) {
int taskId = beginEvent.ExtraHintInfo(taskKey);
mTaskIDToDurationIndex[taskId] = beginEvent.id;
}
mMachineTileOpMap[pid].clear();
}
return endEvent;
}
void TraceLogger::AddDuration(const LogData& data)
{
mEventIdPtr++;
auto beginEvent = Event{
.name = data.name,
.id = mEventIdPtr,
.catagory = "event",
.phase = "B",
.bp = "",
.timestamp = data.sTime,
.pid = data.pid,
.tid = data.tid,
.hint = data.hint,
};
auto endEvent = Event{
.name = data.name,
.id = mEventIdPtr,
.catagory = "event",
.phase = "E",
.bp = "",
.timestamp = data.eTime,
.pid = data.pid,
.tid = data.tid,
.hint = beginEvent.hint,
};
mEvents.push_back(beginEvent);
mEvents.push_back(endEvent);
mDurations.emplace(beginEvent.id, Duration{beginEvent, endEvent});
if (data.isLogTileOp) {
std::istringstream iss(data.name);
int magic;
iss >> magic;
mMachineTileOpMap[data.pid][magic] = mEventIdPtr;
}
}
void TraceLogger::AddFlow(uint64_t srcTask, uint64_t dstTask)
{
EventId srcId;
EventId dstId;
srcId.eid = mTaskIDToDurationIndex[srcTask];
dstId.eid = mTaskIDToDurationIndex[dstTask];
AddFlow("flow", srcId, dstId);
}
void TraceLogger::AddTileOpFlow(Pid pid, uint64_t srcMagic, uint64_t dstMagic)
{
if (mMachineTileOpMap.find(pid) == mMachineTileOpMap.end()) {
return;
}
if (mMachineTileOpMap[pid].find(srcMagic) == mMachineTileOpMap[pid].end() ||
mMachineTileOpMap[pid].find(dstMagic) == mMachineTileOpMap[pid].end()) {
return;
}
EventId srcId;
EventId dstId;
srcId.eid = mMachineTileOpMap[pid][srcMagic];
dstId.eid = mMachineTileOpMap[pid][dstMagic];
AddFlow("flow", srcId, dstId);
}
void TraceLogger::AddFlow(std::string name, CostModel::EventId from, CostModel::EventId to)
{
mFlows.push_back(Flow{name, from, to});
}
void TraceLogger::AddCounterEvent(CostModel::Pid pid, CostModel::Tid tid, CostModel::CounterType type)
{
mCounterEventIdPtr++;
auto sizeCount = CounterEvent{
.id = mCounterEventIdPtr,
.catagory = "count",
.phase = "C",
.type = type,
.size = 0,
.timestamp = TimeStamp(sim->GetCycles()),
.pid = pid,
.tid = tid,
};
mCounters.emplace_back(sizeCount);
mCounts[PTid{pid, tid}].emplace_back(sizeCount);
}
void TraceLogger::EraseLogInfo(uint64_t startCycle)
{
auto new_events_end = mEvents.begin();
for (auto it = mEvents.begin(); it != mEvents.end(); ++it) {
if (it->timestamp <= startCycle) {
if (it != new_events_end) {
*new_events_end = std::move(*it);
}
++new_events_end;
}
}
mEvents.erase(new_events_end, mEvents.end());
for (auto it = mDurations.begin(); it != mDurations.end();) {
if (it->second.start.timestamp > startCycle) {
it = mDurations.erase(it);
} else {
++it;
}
}
auto new_counters_end = mCounters.begin();
for (auto it = mCounters.begin(); it != mCounters.end(); ++it) {
if (it->timestamp <= startCycle) {
if (it != new_counters_end) {
*new_counters_end = std::move(*it);
}
++new_counters_end;
}
}
mCounters.erase(new_counters_end, mCounters.end());
for (auto& counts : mCounts) {
auto new_counts_end = counts.second.begin();
for (auto it = counts.second.begin(); it != counts.second.end(); ++it) {
if (it->timestamp <= startCycle) {
if (it != new_counts_end) {
*new_counts_end = std::move(*it);
}
++new_counts_end;
}
}
counts.second.erase(new_counts_end, counts.second.end());
}
mTaskIDToDurationIndex.clear();
}
void TraceLogger::GetTotalMachineQueueSize(CostModel::TimeStamp interval)
{
std::map<int, std::map<int, int>> machinesQueueIntervalCount;
std::map<int, std::map<int, int>> machinesQueueTotalCount;
std::map<int, std::map<int, int>> machinesQueuePushpopCount;
TimeStamp lastTime = 0;
for (auto& counter : mCounters) {
if (!sim->IsQueue(counter.tid)) {
continue;
}
int machineType = GetMachineType(counter.pid);
int qId = counter.tid;
std::string queueName = mThreads[PTid{counter.pid, counter.tid}].name;
auto& intervalCount = machinesQueueIntervalCount[machineType][qId];
auto& totalCount = machinesQueueTotalCount[machineType][qId];
auto& pushpopCount = machinesQueuePushpopCount[machineType][qId];
if (counter.type == CounterType::QUEUE_PUSH) {
intervalCount++;
totalCount++;
} else {
intervalCount--;
totalCount--;
}
pushpopCount++;
if ((counter.timestamp / interval) != (lastTime / interval)) {
mCounterEventIdPtr++;
auto sizeCount = CounterEvent{
.id = mCounterEventIdPtr,
.catagory = "count",
.phase = "C",
.type = CounterType::COUNT_SIZE,
.size = totalCount,
.timestamp = counter.timestamp,
.pid = counter.pid,
.tid = counter.tid,
};
mCounterEventIdPtr++;
auto pushpopNum = CounterEvent{
.id = mCounterEventIdPtr,
.catagory = "count",
.phase = "C",
.type = CounterType::COUNT_SIZE,
.size = pushpopCount,
.timestamp = counter.timestamp,
.pid = counter.pid,
.tid = counter.tid,
};
if (machineType == int(CostModel::MachineType::DEVICE)) {
totalDeviceMachineQueueSize.emplace_back(sizeCount);
totalDeviceMachinePushpopNum.emplace_back(pushpopNum);
} else if (machineType == int(CostModel::MachineType::CPU)) {
totalAicpuMachineQueueSize.emplace_back(sizeCount);
totalAicpuMachinePushpopNum.emplace_back(pushpopNum);
} else if (IsCoreMachine(machineType)) {
totalCoreMachineQueueSize.emplace_back(sizeCount);
totalCoreMachinePushpopNum.emplace_back(pushpopNum);
} else if (machineType == int(CostModel::MachineType::PIPE)) {
totalPipeMachineQueueSize.emplace_back(sizeCount);
totalPipeMachinePushpopNum.emplace_back(pushpopNum);
}
intervalCount = 0;
pushpopCount = 0;
}
lastTime = counter.timestamp;
}
}
void TraceLogger::GetFunctionCacheSize(
TimeStamp interval, const std::pair<const PTid, std::vector<CounterEvent>>& threadCounter)
{
int totalCount = 0;
int hitCount = 0;
int missCount = 0;
TimeStamp lastTime = 0;
Pid pid = threadCounter.first.pid;
Tid tid = threadCounter.first.tid;
for (auto& counter : threadCounter.second) {
if ((counter.timestamp / interval) != (lastTime / interval)) {
auto totalNum = CounterEvent{
.id = ++mCounterEventIdPtr,
.catagory = "count",
.phase = "C",
.type = CounterType::COUNT_SIZE,
.size = totalCount,
.timestamp = lastTime,
.pid = pid,
.tid = tid,
};
auto hitNum = CounterEvent{
.id = ++mCounterEventIdPtr,
.catagory = "count",
.phase = "C",
.type = CounterType::COUNT_SIZE,
.size = hitCount,
.timestamp = lastTime,
.pid = pid,
.tid = tid,
};
auto missNum = CounterEvent{
.id = ++mCounterEventIdPtr,
.catagory = "count",
.phase = "C",
.type = CounterType::COUNT_SIZE,
.size = missCount,
.timestamp = lastTime,
.pid = pid,
.tid = tid,
};
functionCacheTotal.emplace_back(totalNum);
functionCacheHit.emplace_back(hitNum);
functionCacheMiss.emplace_back(missNum);
totalCount = 0;
hitCount = 0;
missCount = 0;
}
if (counter.type == CounterType::CACHE_HIT) {
hitCount++;
totalCount++;
} else if (counter.type == CounterType::CACHE_MISS) {
missCount++;
totalCount++;
} else {
}
lastTime = counter.timestamp;
}
}
void TraceLogger::GetTotalFunctionCacheSize(TimeStamp interval)
{
std::vector<CounterEvent> totalCounterVec;
for (auto& threadCounter : mCounts) {
if (threadCounter.first.tid == sim->pidToMachineMp[threadCounter.first.pid]->functionCacheTid) {
std::copy(threadCounter.second.begin(), threadCounter.second.end(), std::back_inserter(totalCounterVec));
}
}
sort(totalCounterVec.begin(), totalCounterVec.end(), [&](CounterEvent a, CounterEvent b) {
return a.timestamp < b.timestamp;
});
Pid pid = sim->machines[0]->machineId;
Tid tid = sim->machines[0]->functionCacheTid;
GetFunctionCacheSize(interval, {{pid, tid}, totalCounterVec});
}
void TraceLogger::GetCounters()
{
const uint32_t intervalLen = 100;
TimeStamp interval = TimeStamp(intervalLen);
for (auto& threadCounter : mCounts) {
if (threadCounter.first.tid == sim->pidToMachineMp[threadCounter.first.pid]->functionCacheTid) {
GetFunctionCacheSize(intervalLen, threadCounter);
continue;
}
if (!sim->IsQueue(threadCounter.first.tid)) {
continue;
}
int totalCount = 0;
TimeStamp lastTime = 0;
for (auto& count : threadCounter.second) {
if (count.type == CounterType::QUEUE_PUSH) {
totalCount++;
} else {
totalCount--;
}
if ((count.timestamp / interval) != (lastTime / interval)) {
mCounterEventIdPtr++;
auto sizeCount = CounterEvent{
.id = mCounterEventIdPtr,
.catagory = "count",
.phase = "C",
.type = CounterType::COUNT_SIZE,
.size = totalCount,
.timestamp = count.timestamp,
.pid = threadCounter.first.pid,
.tid = threadCounter.first.tid,
};
eachMachineQueueSize[threadCounter.first].emplace_back(sizeCount);
}
lastTime = count.timestamp;
}
}
GetTotalFunctionCacheSize(intervalLen);
GetTotalMachineQueueSize(intervalLen);
}
void TraceLogger::GetDeviceReadyQ()
{
if (processDeviceReadyQueue) {
return;
}
std::map<uint64_t, int> readyQueueCounts;
int qSize = 0;
size_t devicePid;
std::set<uint64_t> readyQueueTidSet;
sim->GetDeviceReadyQueueInfo(devicePid, readyQueueTidSet);
for (auto& countEvent : mCounts) {
if (countEvent.first.pid != devicePid) {
continue;
}
if (readyQueueTidSet.find(countEvent.first.tid) == readyQueueTidSet.end()) {
continue;
}
readyQueueCounts.clear();
qSize = 0;
for (auto& event : countEvent.second) {
if (event.type == CounterType::QUEUE_PUSH) {
qSize++;
readyQueueCounts[event.timestamp] = qSize;
} else {
qSize--;
readyQueueCounts[event.timestamp] = qSize;
}
}
for (auto& it : readyQueueCounts) {
auto sizeCount = CounterEvent{
.id = mQSizeIdPtr++,
.catagory = mThreads[countEvent.first].name,
.phase = "C",
.type = CounterType::QUEUE_PUSH,
.size = it.second,
.timestamp = TimeStamp(it.first),
.pid = countEvent.first.pid,
.tid = countEvent.first.tid,
};
totalDeviceMachineQueueSize.emplace_back(sizeCount);
}
}
processDeviceReadyQueue = true;
}
void TraceLogger::OutEachMachineQueueSize(std::ofstream& os, const uint64_t sysClockTicks)
{
std::string title = "queueCounter-0";
for (auto& machineQCounter : eachMachineQueueSize) {
auto& ptid = machineQCounter.first;
std::string queueName = mProcesses[ptid.pid].name + mThreads[ptid].name;
std::string cpuInfo = "( 0) [000] ....";
for (auto& count : machineQCounter.second) {
std::ostringstream cyc1;
cyc1 << std::fixed << std::setprecision(precision) << (double(count.timestamp) / sysClockTicks);
std::string cycle = cyc1.str();
std::string workInfo =
": clock_set_rate: " + queueName + " state=" + std::to_string(count.size) + " cpu_id=0";
os << std::setw(width) << std::left << title << std::setw(width) << std::right << cpuInfo;
os << std::setw(width2) << std::right << cycle << workInfo << std::endl;
}
}
}
void TraceLogger::OutCounters(
std::ofstream& os, std::vector<CounterEvent>& counterQ, std::string prefix, std::string suffix,
const uint64_t sysClockTicks)
{
std::string title = "queueCounter-0";
for (auto& counter : counterQ) {
auto ptid = PTid{counter.pid, counter.tid};
if (ptid.pid != sim->machines[0]->machineId) {
std::string queueName = prefix + mThreads[ptid].name + suffix;
std::string cpuInfo = "(" + to_string(ptid.pid) + ") [" + to_string(ptid.pid % 10000) + "] ....";
std::ostringstream cyc1;
cyc1 << std::fixed << std::setprecision(precision) << (double(counter.timestamp) / sysClockTicks);
std::string cycle = cyc1.str();
std::string workInfo =
": tracing_mark_write: C|" + to_string(ptid.pid) + "|" + queueName + '|' + std::to_string(counter.size);
os << std::setw(width) << std::left << title << std::setw(width) << std::right << cpuInfo;
os << std::setw(width2) << std::right << cycle << workInfo << std::endl;
} else {
std::string queueName = prefix + mThreads[ptid].name + suffix;
std::string cpuInfo = "( 0) [000] ....";
std::ostringstream cyc1;
cyc1 << std::fixed << std::setprecision(precision) << (double(counter.timestamp) / sysClockTicks);
std::string cycle = cyc1.str();
std::string workInfo =
": clock_set_rate: " + queueName + " state=" + std::to_string(counter.size) + " cpu_id=0";
os << std::setw(width) << std::left << title << std::setw(width) << std::right << cpuInfo;
os << std::setw(width2) << std::right << cycle << workInfo << std::endl;
}
}
}
Json TraceLogger::QSizeToJson(std::vector<CounterEvent>& counterQ)
{
Json root = Json::array();
for (auto& count : counterQ) {
root.emplace_back(count.ToJson());
}
return root;
}
Json TraceLogger::ToJson()
{
Json root;
auto traceEvents = Json::array();
int processSortIndex = 0;
for (auto&& [pid, process] : mProcesses) {
auto machineType = GetMachineType(pid);
if (machineType >= int(MachineType::PIPE)) {
continue;
};
traceEvents.emplace_back(process.ToJson());
traceEvents.emplace_back(process.ToSortIndexJson(processSortIndex++));
}
for (auto&& [ptid, thread] : mThreads) {
if (ptid.tid > coreTid && ptid.tid < reversedTidNum) {
continue;
}
traceEvents.emplace_back(thread.ToJson());
}
for (auto& duration : mDurations) {
traceEvents.emplace_back(duration.second.ToJson());
}
int flowIndex = 0;
for (auto& flow : mFlows) {
auto& fStart = mDurations[flow.from.eid].end;
auto& fEnd = mDurations[flow.to.eid].start;
traceEvents.emplace_back(fStart.ToFlowStartJson(flowIndex));
traceEvents.emplace_back(fEnd.ToFlowEndJson(flowIndex));
flowIndex++;
}
GetDeviceReadyQ();
auto readyQJson = QSizeToJson(totalDeviceMachineQueueSize);
traceEvents.insert(traceEvents.end(), readyQJson.begin(), readyQJson.end());
root["traceEvents"] = std::move(traceEvents);
return root;
}
void TraceLogger::ToTrace(std::ofstream& os)
{
for (auto& duration : mDurations) {
if (duration.second.start.pid == topMachineViewPid) {
duration.second.OutputContextSwitchTrace(os, mProcesses, mThreads, config.sysClockTicks);
} else {
duration.second.OutputBeginEndTrace(os, mProcesses, mThreads, config.sysClockTicks);
}
}
}
void TraceLogger::LogTaskInfo(Event& start, Event& end)
{
int coreId = mProcesses[start.pid].coreIdx;
std::string taskKey = "TaskId:";
int taskId = start.ExtraHintInfo(taskKey);
std::string subgraphKey = "pSgId:";
int pSgId = start.ExtraHintInfo(subgraphKey);
uint64_t sTime = start.timestamp;
uint64_t eTime = end.timestamp;
Json taskJson;
taskJson["taskId"] = taskId;
taskJson["execStart"] = sTime;
taskJson["execEnd"] = eTime;
taskJson["subGraphId"] = pSgId;
taskJson["completeSeq"] = sim->taskCompleteSeq[taskId];
mCoreInfoLogs[coreId].taskLogs.push_back(taskJson);
}
void TraceLogger::LogPipeInfo(Event& start, Event& end)
{
std::string name = "";
if (sim->IsWorkPipe(start.pid, start.tid, name)) {
int coreId = mProcesses[start.pid].coreIdx;
uint64_t sTime = start.timestamp;
uint64_t eTime = end.timestamp;
Json pipeJson;
pipeJson["tileOp"] = start.name;
pipeJson["execStart"] = sTime;
pipeJson["execEnd"] = eTime;
mCoreInfoLogs[coreId].pipeLogs[name].emplace_back(pipeJson);
}
}
void TraceLogger::LogCoreInfo(Duration& duration)
{
auto& start = duration.start;
auto& end = duration.end;
size_t initPos = start.name.find("Init");
if (initPos != std::string::npos) {
return;
}
if (start.tid == 1) {
LogTaskInfo(start, end);
} else {
LogPipeInfo(start, end);
}
}
void TraceLogger::ToFilterTrace(std::ofstream& os, std::map<int, std::pair<std::string, std::vector<Json>>>& coreTasks)
{
for (auto it : mProcesses) {
auto machineType = GetMachineType(it.first);
if (IsCoreMachine(machineType)) {
coreTasks[it.second.coreIdx] = {MachineName(static_cast<MachineType>(machineType)), {}};
mCoreInfoLogs[it.second.coreIdx] =
CoreInfoLog(it.second.coreIdx, MachineName(static_cast<MachineType>(machineType)));
}
}
for (auto& duration : mDurations) {
auto machineType = GetMachineType(duration.second.start.pid);
if (IsCoreMachine(machineType)) {
LogCoreInfo(duration.second);
}
if (duration.second.start.tid != 1 || !IsCoreMachine(machineType)) {
continue;
}
auto& start = duration.second.start;
auto& end = duration.second.end;
size_t initPos = start.name.find("Init");
if (initPos != std::string::npos) {
continue;
}
int coreId = mProcesses[start.pid].coreIdx;
std::string seqKey = "SeqNo:";
int seqNo = start.ExtraHintInfo(seqKey);
std::string taskKey = "TaskId:";
int taskId = start.ExtraHintInfo(taskKey);
std::string subgraphKey = "pSgId:";
int pSgId = start.ExtraHintInfo(subgraphKey);
uint64_t sTime = start.timestamp;
uint64_t eTime = end.timestamp;
Json taskJson;
taskJson["seqNo"] = seqNo;
taskJson["taskId"] = taskId;
taskJson["execStart"] = sTime;
taskJson["execEnd"] = eTime;
taskJson["subGraphId"] = pSgId;
taskJson["completeSeq"] = sim->taskCompleteSeq[taskId];
coreTasks[coreId].second.push_back(taskJson);
}
Json printJson;
for (auto& it : coreTasks) {
Json coreJson;
coreJson["blockIdx"] = it.first;
coreJson["coreType"] = it.second.first;
coreJson["tasks"] = it.second.second;
printJson.push_back(coreJson);
}
os << printJson.dump(1) << std::endl;
}
void TraceLogger::ToPipeTrace(std::ofstream& os)
{
Json res;
for (auto& coreInfo : mCoreInfoLogs) {
Json coreJson;
coreJson["blockIdx"] = coreInfo.second.idx;
coreJson["coreType"] = coreInfo.second.type;
for (auto& pipe : coreInfo.second.pipeLogs) {
coreJson["pipeLogs"][pipe.first] = pipe.second;
}
res.push_back(coreJson);
}
os << res.dump(1) << std::endl;
}
void TraceLogger::ToCalendarGlobalJson(
std::ofstream& osCalendar, std::map<int, std::pair<std::string, std::vector<Json>>> coreTasks)
{
int numSupportedCounters = 1;
int counterId = 0;
Json calendarJson;
calendarJson["numSupportedCounters"] = numSupportedCounters;
calendarJson["cores"] = Json::array();
for (auto& it : coreTasks) {
Json core;
core["coreId"] = it.first;
if (it.second.first.find("HUB") != std::string::npos) {
continue;
}
core["tasks"] = Json::array();
for (const auto& taskJson : it.second.second) {
int taskId = taskJson["taskId"];
Json waitOp;
waitOp["counterId"] = counterId;
waitOp["operation"] = "wait";
waitOp["expectedValue"] = sim->taskToCounter[taskId][0];
core["tasks"].push_back(waitOp);
Json taskExec;
taskExec["functionHash"] = std::to_string(sim->taskToHash[taskId]);
taskExec["taskId"] = taskId;
core["tasks"].push_back(taskExec);
Json setWaitOp;
setWaitOp["counterId"] = counterId;
setWaitOp["operation"] = "setWait";
setWaitOp["expectedValue"] = sim->taskToCounter[taskId][1];
core["tasks"].push_back(setWaitOp);
Json setOp;
setOp["counterId"] = counterId;
setOp["operation"] = "set";
setOp["expectedValue"] = sim->taskToCounter[taskId][1] + 1;
core["tasks"].push_back(setOp);
}
calendarJson["cores"].push_back(core);
}
osCalendar << calendarJson.dump(1) << std::endl;
}
}