* This file is part of the MindStudio project.
* Copyright (c) 2025 Huawei Technologies Co.,Ltd.
*
* MindStudio is licensed under Mulan PSL v2.
* You can use this software according to the terms and conditions of the Mulan PSL v2.
* You may obtain a copy of Mulan PSL v2 at:
*
* http://license.coscl.org.cn/MulanPSL2
*
* 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 FIT FOR A PARTICULAR PURPOSE.
* See the Mulan PSL v2 for more details.
* ------------------------------------------------------------------------- */
#include "event_container.h"
#include "core/framework/utility/log.h"
namespace Sanitizer {
void EventContainer::Init(uint32_t blockNum, uint32_t deviceNum)
{
deviceNum_ = deviceNum;
maxBlockNum_ = blockNum;
ques_.resize(deviceNum * blockNum * (static_cast<uint32_t>(PipeType::SIZE)));
}
void EventContainer::Push(const SanEvent &e, PipeType pipe, uint32_t blockIdx, uint32_t deviceIdx)
{
if (blockIdx >= maxBlockNum_) {
SAN_ERROR_LOG("Invalid blockIdx %u, serialNo %lu", blockIdx, e.serialNo);
return;
}
if (deviceIdx >= deviceNum_) {
SAN_ERROR_LOG("Invalid deviceIdx %u, serialNo %lu", deviceIdx, e.serialNo);
return;
}
uint32_t pipeIndex = FlattenPipeIdx(static_cast<uint32_t>(pipe), blockIdx, deviceIdx);
if (e.type == EventType::MEM_EVENT && e.eventInfo.memInfo.opType == AccessType::MEMCPY_BLOCKS) {
SanEvent event = e;
event.eventInfo.memInfo.opType = AccessType::READ;
ques_[pipeIndex].push(event);
event.eventInfo.memInfo.opType = AccessType::WRITE;
ques_[pipeIndex].push(event);
return;
}
ques_[pipeIndex].push(e);
}
SanEvent EventContainer::Front() const
{
return ques_[FlattenPipeIdx(pipeIndex_, blockIndex_, deviceIndex_)].front();
}
void EventContainer::Pop()
{
++blockPopCount_;
++devicePopCount_;
ques_[FlattenPipeIdx(pipeIndex_, blockIndex_, deviceIndex_)].pop();
}
bool EventContainer::IsCurQueEmpty() const
{
return ques_[FlattenPipeIdx(pipeIndex_, blockIndex_, deviceIndex_)].empty();
}
bool EventContainer::IsCurBlockEmpty() const
{
uint32_t startIdx = FlattenPipeIdx(0, blockIndex_, deviceIndex_);
uint32_t endIdx = startIdx + static_cast<uint32_t>(PipeType::SIZE);
for (auto i = startIdx; i < endIdx; ++i) {
if (!ques_[i].empty()) {
return false;
}
}
return true;
}
bool EventContainer::IsCurDeviceEmpty() const
{
uint32_t startIdx = FlattenPipeIdx(0, 0, deviceIndex_);
uint32_t endIdx = startIdx + maxBlockNum_ * static_cast<uint32_t>(PipeType::SIZE);
for (uint32_t i = startIdx; i < endIdx; ++i) {
if (!ques_[i].empty()) {
return false;
}
}
return true;
}
bool EventContainer::IsNeedSwitchNextBlock() const
{
if (isBlockStuck_) {
return true;
}
return IsCurBlockEmpty();
}
bool EventContainer::IsNeedSwitchNextDevice() const
{
return isDeviceStuck_ || IsCurDeviceEmpty();
}
bool EventContainer::IsEmpty() const
{
for (const auto &it : ques_) {
if (!it.empty()) {
return false;
}
}
return true;
}
void EventContainer::CheckCurDeviceStuck()
{
if (isDeviceStuck_) {
++stuckDeviceNum_;
} else {
stuckDeviceNum_ = 0;
}
}
bool EventContainer::IsAllDeviceStuck() const
{
return stuckDeviceNum_ == deviceNum_;
}
void EventContainer::PrintStuckSerialNo() const
{
for (size_t i = 0; i < ques_.size(); i++) {
if (ques_[i].empty()) {
continue;
}
SAN_INFO_LOG("Stuck pipe index %lu , serialNo %lu, remaining event count %lu",
i, ques_[i].front().serialNo, ques_[i].size());
}
}
void EventContainer::ForEachFrontEvent(const std::function<void(const SanEvent &)> &func) const {
if (!func) {
return;
}
for (const auto &q : ques_) {
if (!q.empty()) {
func(q.front());
}
}
}
void EventContainer::SwitchToNextDevice()
{
deviceIndex_ = (deviceIndex_ + 1U) % deviceNum_;
blockIndex_ = 0U;
pipeIndex_ = 0U;
blockPopCount_ = 0U;
devicePopCount_ = 0U;
isBlockStuck_ = false;
isDeviceStuck_ = false;
}
void EventContainer::SwitchToNextBlock()
{
blockIndex_ = (blockIndex_ + 1U) % maxBlockNum_;
pipeIndex_ = 0U;
blockPopCount_ = 0U;
isBlockStuck_ = false;
if (blockIndex_ == 0U) {
isDeviceStuck_ = devicePopCount_ == 0U;
if (!isDeviceStuck_) {
stuckDeviceNum_ = 0;
}
devicePopCount_ = 0U;
}
}
void EventContainer::SwitchToNextPipe()
{
pipeIndex_ = (pipeIndex_ + 1U) % static_cast<uint32_t>(PipeType::SIZE);
if (pipeIndex_ == static_cast<uint32_t>(PipeType::PIPE_S)) {
isBlockStuck_ = blockPopCount_ == 0U;
blockPopCount_ = 0U;
}
}
PipeType EventContainer::GetPipeIndex() const
{
return static_cast<PipeType>(pipeIndex_);
}
uint32_t EventContainer::GetQueIndex() const
{
return FlattenPipeIdx(pipeIndex_, blockIndex_, deviceIndex_);
}
uint32_t EventContainer::GetBlockIndex() const
{
return blockIndex_;
}
uint32_t EventContainer::GetCurQueSize() const
{
return ques_[(blockIndex_ * (static_cast<uint32_t>(PipeType::SIZE))) + pipeIndex_].size();
}
uint32_t EventContainer::GetAllQueSize() const
{
uint32_t sum = 0U;
for (const auto &it: ques_) {
sum += it.size();
}
return sum;
}
void EventContainer::SetQueIndex(PipeType pipe)
{
pipeIndex_ = static_cast<uint32_t>(pipe);
}
uint32_t EventContainer::FlattenPipeIdx(uint32_t pipeIdx, uint32_t blockIdx, uint32_t deviceIdx) const
{
return deviceIdx * maxBlockNum_ * static_cast<uint32_t>(PipeType::SIZE) +
blockIdx * static_cast<uint32_t>(PipeType::SIZE) + pipeIdx;
}
}