* 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 BaseQueue.h
* \brief
*/
#pragma once
#ifndef QUEUE_H
#define QUEUE_H
#include <climits>
#include <queue>
#include <iostream>
#include "cost_model/simulation/base/SimObj.h"
#include "cost_model/simulation/statistics/TraceLogger.h"
namespace CostModel {
template <typename T>
class SimQueue : public SimObj {
private:
uint64_t maxQueueSize = 1024;
uint64_t tick = 0;
uint64_t wDelay = 0;
uint64_t rDelay = 0;
std::deque<T> wQueue;
std::deque<T> rQueue;
std::deque<uint64_t> wTimeQueue;
std::deque<uint64_t> rTimeQueue;
uint64_t rWaitLatency = INT_MAX;
uint64_t wWaitLatency = INT_MAX;
uint64_t intervalCycles = 1;
std::shared_ptr<TraceLogger> mLogger = nullptr;
CostModel::Pid pid = 0;
CostModel::Tid tid = 0;
public:
SimQueue() = default;
~SimQueue() override = default;
void Build() override { Reset(); }
void Xfer() override {}
void UpdateIntervalCycles(uint64_t deltaCycles) { intervalCycles = deltaCycles; }
void Step() override
{
if (wTimeQueue.empty() && rTimeQueue.empty()) {
tick = 0;
rWaitLatency = INT_MAX;
wWaitLatency = INT_MAX;
} else {
tick += intervalCycles;
}
while (!wTimeQueue.empty() && tick >= wTimeQueue.front()) {
rQueue.push_back(std::move(wQueue.front()));
rTimeQueue.push_back(tick + rDelay);
wQueue.pop_front();
wTimeQueue.pop_front();
}
if (!wTimeQueue.empty()) {
wWaitLatency = wTimeQueue.front() - tick;
}
if (!rTimeQueue.empty()) {
rWaitLatency = rTimeQueue.front() - tick;
}
}
void Reset() override
{
wQueue.clear();
rQueue.clear();
wTimeQueue.clear();
rTimeQueue.clear();
}
std::shared_ptr<SimSys> GetSim() override { return nullptr; }
SimQueue(const SimQueue&) = delete;
SimQueue& operator=(const SimQueue&) = delete;
uint64_t GetMinWaitCycles()
{
uint64_t res = std::min(rWaitLatency, wWaitLatency);
if (res == 0) {
return 1;
}
return res;
}
void Enqueue(T element, uint64_t extraDelay = 0)
{
wQueue.push_back(std::move(element));
wTimeQueue.push_back(tick + extraDelay + wDelay);
this->LoggerRecordQueueEvent(CounterType::QUEUE_PUSH);
}
bool Dequeue(T& element)
{
if (rQueue.empty()) {
return false;
}
this->LoggerRecordQueueEvent(CounterType::QUEUE_POP);
element = std::move(rQueue.front());
rQueue.pop_front();
rTimeQueue.pop_front();
return true;
}
bool Front(T& element)
{
if (rQueue.empty()) {
return false;
}
element = rQueue.front();
return true;
}
bool PopFront()
{
if (rQueue.empty()) {
return false;
}
rQueue.pop_front();
rTimeQueue.pop_front();
return true;
}
size_t Size() const { return rQueue.size(); }
size_t WriteQueueSize() const { return wQueue.size(); }
bool Empty() const { return (rTimeQueue.empty() || tick < rTimeQueue.front()); }
bool Full() const { return wTimeQueue.size() >= maxQueueSize; }
void SetMaxSize(uint64_t maxSize) { maxQueueSize = maxSize; }
void SetWriteDelay(uint64_t delay) { wDelay = delay; }
void SetReadDelay(uint64_t delay) { rDelay = delay; }
bool IsTerminate() { return (wQueue.empty() && rQueue.empty()); }
void SetCounterInfo(std::shared_ptr<TraceLogger> logger, CostModel::Pid pId, CostModel::Tid tId)
{
mLogger = logger;
pid = pId;
tid = tId;
}
void LoggerRecordQueueEvent(CounterType type)
{
if (mLogger != nullptr) {
mLogger->AddCounterEvent(pid, tid, type);
}
}
int CalendarPopFront()
{
if (rQueue.empty()) {
return false;
}
int number = rQueue.front();
rQueue.pop_front();
rTimeQueue.pop_front();
return number;
}
};
}
#endif