New hardware-equivalent backpressure implementation.
This commit is contained in:
@@ -65,7 +65,6 @@ Controller::Controller(sc_module_name name) :
|
||||
{
|
||||
SC_METHOD(controllerMethod);
|
||||
sensitive << beginReqEvent << endRespEvent << controllerEvent << dataResponseEvent;
|
||||
dont_initialize();
|
||||
|
||||
Configuration &config = Configuration::getInstance();
|
||||
memSpec = config.memSpec;
|
||||
@@ -162,8 +161,6 @@ Controller::Controller(sc_module_name name) :
|
||||
{
|
||||
PowerDownManagerIF *manager = new PowerDownManagerStaggered(Rank(rankID), checker);
|
||||
powerDownManagers.push_back(manager);
|
||||
manager->triggerEntry(TriggerSource::Controller);
|
||||
controllerEvent.notify(manager->start());
|
||||
}
|
||||
}
|
||||
else
|
||||
@@ -182,7 +179,6 @@ Controller::Controller(sc_module_name name) :
|
||||
RefreshManagerIF *manager = new RefreshManagerRankwise
|
||||
(bankMachinesOnRank[rankID], powerDownManagers[rankID], Rank(rankID), checker);
|
||||
refreshManagers.push_back(manager);
|
||||
controllerEvent.notify(manager->start());
|
||||
}
|
||||
}
|
||||
else if (config.refreshPolicy == "Bankwise")
|
||||
@@ -193,7 +189,6 @@ Controller::Controller(sc_module_name name) :
|
||||
RefreshManagerIF *manager = new RefreshManagerBankwise
|
||||
(bankMachinesOnRank[rankID], powerDownManagers[rankID], Rank(rankID), checker);
|
||||
refreshManagers.push_back(manager);
|
||||
controllerEvent.notify(manager->start());
|
||||
}
|
||||
}
|
||||
else
|
||||
@@ -220,38 +215,20 @@ Controller::~Controller()
|
||||
|
||||
void Controller::controllerMethod()
|
||||
{
|
||||
// (1) Release payload if arbiter has accepted the result
|
||||
if (sc_time_stamp() == timeToRelease && payloadToRelease != nullptr)
|
||||
releasePayload();
|
||||
// (1) Release payload if arbiter has accepted the result (finish END_RESP)
|
||||
if (payloadToRelease != nullptr && timeToRelease <= sc_time_stamp())
|
||||
finishEndResp();
|
||||
|
||||
// (2) Send next result to arbiter
|
||||
// (2) Send next result to arbiter (start BEGIN_RESP)
|
||||
if (payloadToRelease == nullptr)
|
||||
{
|
||||
payloadToRelease = respQueue->nextPayload();
|
||||
startBeginResp();
|
||||
|
||||
if (payloadToRelease != nullptr)
|
||||
sendToFrontend(payloadToRelease, BEGIN_RESP);
|
||||
else
|
||||
{
|
||||
sc_time triggerTime = respQueue->getTriggerTime();
|
||||
if (triggerTime != sc_max_time())
|
||||
dataResponseEvent.notify(triggerTime - sc_time_stamp());
|
||||
}
|
||||
}
|
||||
|
||||
// (3) Accept new request from arbiter and start appropriate BM if necessary
|
||||
if (sc_time_stamp() >= timeToAcquire && payloadToAcquire != nullptr)
|
||||
// (3) Insert new request from arbiter into scheduler and restart appropriate BM (finish BEGIN_REQ)
|
||||
if (payloadToAcquire != nullptr && timeToAcquire <= sc_time_stamp())
|
||||
{
|
||||
if (scheduler->hasBufferSpace(payloadToAcquire))
|
||||
{
|
||||
Bank bank = DramExtension::getBank(payloadToAcquire);
|
||||
acquirePayload();
|
||||
|
||||
if (bankMachines[bank.ID()]->isIdle())
|
||||
bankMachines[bank.ID()]->start();
|
||||
}
|
||||
else
|
||||
PRINTDEBUGMESSAGE(name(), "Total number of payloads exceeded, backpressure!");
|
||||
unsigned bankID = DramExtension::getBank(payloadToAcquire).ID();
|
||||
finishBeginReq();
|
||||
bankMachines[bankID]->start();
|
||||
}
|
||||
|
||||
// (4) Start refresh and power-down managers to issue requests for the current time
|
||||
@@ -334,7 +311,11 @@ void Controller::controllerMethod()
|
||||
readyCmdBlocked = true;
|
||||
}
|
||||
|
||||
// (6) Restart bank machines, refresh managers and power-down managers to issue new requests for the future
|
||||
// (6) Accept request from arbiter if scheduler is not full, otherwise backpressure (start END_REQ)
|
||||
if (payloadToAcquire != nullptr && timeToAcquire == sc_max_time())
|
||||
startEndReq();
|
||||
|
||||
// (7) Restart bank machines, refresh managers and power-down managers to issue new requests for the future
|
||||
// TODO: check if all calls are necessary
|
||||
sc_time timeForNextTrigger = sc_max_time();
|
||||
for (auto it : bankMachines)
|
||||
@@ -343,8 +324,6 @@ void Controller::controllerMethod()
|
||||
if (!(localTime == sc_time_stamp() && readyCmdBlocked))
|
||||
timeForNextTrigger = std::min(timeForNextTrigger, localTime);
|
||||
}
|
||||
if (payloadToAcquire != nullptr && sc_time_stamp() >= timeToAcquire && scheduler->hasBufferSpace(payloadToAcquire))
|
||||
acquirePayload();
|
||||
for (auto it : refreshManagers)
|
||||
timeForNextTrigger = std::min(timeForNextTrigger, it->start());
|
||||
for (auto it : powerDownManagers)
|
||||
@@ -394,7 +373,55 @@ unsigned int Controller::transport_dbg(tlm_generic_payload &)
|
||||
return 0;
|
||||
}
|
||||
|
||||
void Controller::releasePayload()
|
||||
void Controller::finishBeginReq()
|
||||
{
|
||||
uint64_t id __attribute__((unused)) = DramExtension::getPayloadID(payloadToAcquire);
|
||||
PRINTDEBUGMESSAGE(name(), "Payload " + std::to_string(id) + " entered system.");
|
||||
|
||||
if (totalNumberOfPayloads == 0)
|
||||
idleTimeCollector.end();
|
||||
totalNumberOfPayloads++;
|
||||
|
||||
Rank rank = DramExtension::getRank(payloadToAcquire);
|
||||
if (ranksNumberOfPayloads[rank.ID()] == 0)
|
||||
{
|
||||
refreshManagers[rank.ID()]->notifyActive();
|
||||
powerDownManagers[rank.ID()]->triggerExit(TriggerSource::Controller);
|
||||
}
|
||||
ranksNumberOfPayloads[rank.ID()]++;
|
||||
|
||||
scheduler->storeRequest(payloadToAcquire);
|
||||
payloadToAcquire->acquire();
|
||||
timeToAcquire = sc_max_time();
|
||||
}
|
||||
|
||||
void Controller::startEndReq()
|
||||
{
|
||||
if (scheduler->hasBufferSpace())
|
||||
{
|
||||
payloadToAcquire->set_response_status(TLM_OK_RESPONSE);
|
||||
sendToFrontend(payloadToAcquire, END_REQ);
|
||||
payloadToAcquire = nullptr;
|
||||
}
|
||||
else
|
||||
PRINTDEBUGMESSAGE(name(), "Total number of payloads exceeded, backpressure!");
|
||||
}
|
||||
|
||||
void Controller::startBeginResp()
|
||||
{
|
||||
payloadToRelease = respQueue->nextPayload();
|
||||
|
||||
if (payloadToRelease != nullptr)
|
||||
sendToFrontend(payloadToRelease, BEGIN_RESP);
|
||||
else
|
||||
{
|
||||
sc_time triggerTime = respQueue->getTriggerTime();
|
||||
if (triggerTime != sc_max_time())
|
||||
dataResponseEvent.notify(triggerTime - sc_time_stamp());
|
||||
}
|
||||
}
|
||||
|
||||
void Controller::finishEndResp()
|
||||
{
|
||||
uint64_t id __attribute__((unused)) = DramExtension::getPayloadID(payloadToRelease);
|
||||
PRINTDEBUGMESSAGE(name(), "Payload " + std::to_string(id) + " left system.");
|
||||
@@ -409,32 +436,6 @@ void Controller::releasePayload()
|
||||
idleTimeCollector.start();
|
||||
}
|
||||
|
||||
void Controller::acquirePayload()
|
||||
{
|
||||
uint64_t id __attribute__((unused)) = DramExtension::getPayloadID(payloadToAcquire);
|
||||
PRINTDEBUGMESSAGE(name(), "Payload " + std::to_string(id) + " entered system.");
|
||||
|
||||
Rank rank = DramExtension::getRank(payloadToAcquire);
|
||||
|
||||
if (totalNumberOfPayloads == 0)
|
||||
idleTimeCollector.end();
|
||||
totalNumberOfPayloads++;
|
||||
|
||||
if(ranksNumberOfPayloads[rank.ID()] == 0)
|
||||
{
|
||||
refreshManagers[rank.ID()]->notifyActive();
|
||||
powerDownManagers[rank.ID()]->triggerExit(TriggerSource::Controller);
|
||||
}
|
||||
ranksNumberOfPayloads[rank.ID()]++;
|
||||
|
||||
scheduler->storeRequest(payloadToAcquire);
|
||||
payloadToAcquire->acquire();
|
||||
payloadToAcquire->set_response_status(TLM_OK_RESPONSE);
|
||||
sendToFrontend(payloadToAcquire, END_REQ);
|
||||
payloadToAcquire = nullptr;
|
||||
timeToAcquire = sc_max_time();
|
||||
}
|
||||
|
||||
void Controller::sendToFrontend(tlm_generic_payload *payload, tlm_phase phase)
|
||||
{
|
||||
sc_time delay = SC_ZERO_TIME;
|
||||
|
||||
@@ -94,8 +94,10 @@ private:
|
||||
tlm_generic_payload *payloadToRelease = nullptr;
|
||||
sc_time timeToRelease = sc_max_time();
|
||||
|
||||
void releasePayload();
|
||||
void acquirePayload();
|
||||
void finishBeginReq();
|
||||
void startEndReq();
|
||||
void startBeginResp();
|
||||
void finishEndResp();
|
||||
|
||||
void controllerMethod();
|
||||
sc_event beginReqEvent, endRespEvent, controllerEvent, dataResponseEvent;
|
||||
|
||||
@@ -62,7 +62,7 @@ private:
|
||||
sc_time timeToSchedule;
|
||||
Command nextCommand;
|
||||
|
||||
bool triggered = false;
|
||||
bool triggered = true;
|
||||
bool enterSelfRefresh = false;
|
||||
bool controllerIdle = true;
|
||||
unsigned activatedBanks = 0;
|
||||
|
||||
@@ -41,9 +41,9 @@ SchedulerFifo::SchedulerFifo()
|
||||
requestBufferSize = Configuration::getInstance().requestBufferSize;
|
||||
}
|
||||
|
||||
bool SchedulerFifo::hasBufferSpace(tlm_generic_payload *payload)
|
||||
bool SchedulerFifo::hasBufferSpace()
|
||||
{
|
||||
if (buffer[DramExtension::getBank(payload).ID()].size() < requestBufferSize)
|
||||
if (buffer[lastBankID].size() < requestBufferSize)
|
||||
return true;
|
||||
else
|
||||
return false;
|
||||
@@ -51,7 +51,8 @@ bool SchedulerFifo::hasBufferSpace(tlm_generic_payload *payload)
|
||||
|
||||
void SchedulerFifo::storeRequest(tlm_generic_payload *payload)
|
||||
{
|
||||
buffer[DramExtension::getBank(payload).ID()].push_back(payload);
|
||||
lastBankID = DramExtension::getBank(payload).ID();
|
||||
buffer[lastBankID].push_back(payload);
|
||||
}
|
||||
|
||||
void SchedulerFifo::removeRequest(tlm_generic_payload *payload)
|
||||
|
||||
@@ -48,7 +48,7 @@ class SchedulerFifo : public SchedulerIF
|
||||
{
|
||||
public:
|
||||
SchedulerFifo();
|
||||
virtual bool hasBufferSpace(tlm_generic_payload *) override;
|
||||
virtual bool hasBufferSpace() override;
|
||||
virtual void storeRequest(tlm_generic_payload *) override;
|
||||
virtual void removeRequest(tlm_generic_payload *) override;
|
||||
virtual tlm_generic_payload *getNextRequest(BankMachine *) override;
|
||||
@@ -57,6 +57,7 @@ public:
|
||||
private:
|
||||
std::vector<std::deque<tlm_generic_payload *>> buffer;
|
||||
unsigned requestBufferSize;
|
||||
unsigned lastBankID;
|
||||
};
|
||||
|
||||
#endif // SCHEDULERFIFO_H
|
||||
|
||||
@@ -43,9 +43,9 @@ SchedulerFrFcfs::SchedulerFrFcfs()
|
||||
requestBufferSize = Configuration::getInstance().requestBufferSize;
|
||||
}
|
||||
|
||||
bool SchedulerFrFcfs::hasBufferSpace(tlm_generic_payload *payload)
|
||||
bool SchedulerFrFcfs::hasBufferSpace()
|
||||
{
|
||||
if (buffer[DramExtension::getBank(payload).ID()].size() < requestBufferSize)
|
||||
if (buffer[lastBankID].size() < requestBufferSize)
|
||||
return true;
|
||||
else
|
||||
return false;
|
||||
@@ -53,7 +53,8 @@ bool SchedulerFrFcfs::hasBufferSpace(tlm_generic_payload *payload)
|
||||
|
||||
void SchedulerFrFcfs::storeRequest(tlm_generic_payload *payload)
|
||||
{
|
||||
buffer[DramExtension::getBank(payload).ID()].push_back(payload);
|
||||
lastBankID = DramExtension::getBank(payload).ID();
|
||||
buffer[lastBankID].push_back(payload);
|
||||
}
|
||||
|
||||
void SchedulerFrFcfs::removeRequest(tlm_generic_payload *payload)
|
||||
|
||||
@@ -48,7 +48,7 @@ class SchedulerFrFcfs : public SchedulerIF
|
||||
{
|
||||
public:
|
||||
SchedulerFrFcfs();
|
||||
virtual bool hasBufferSpace(tlm_generic_payload *) override;
|
||||
virtual bool hasBufferSpace() override;
|
||||
virtual void storeRequest(tlm_generic_payload *) override;
|
||||
virtual void removeRequest(tlm_generic_payload *) override;
|
||||
virtual tlm_generic_payload *getNextRequest(BankMachine *) override;
|
||||
@@ -57,6 +57,7 @@ public:
|
||||
private:
|
||||
std::vector<std::list<tlm_generic_payload *>> buffer;
|
||||
unsigned requestBufferSize;
|
||||
unsigned lastBankID;
|
||||
};
|
||||
|
||||
#endif // SCHEDULERFRFCFS_H
|
||||
|
||||
@@ -41,9 +41,9 @@ SchedulerFrFcfsGrp::SchedulerFrFcfsGrp()
|
||||
requestBufferSize = Configuration::getInstance().requestBufferSize;
|
||||
}
|
||||
|
||||
bool SchedulerFrFcfsGrp::hasBufferSpace(tlm_generic_payload *payload)
|
||||
bool SchedulerFrFcfsGrp::hasBufferSpace()
|
||||
{
|
||||
if (buffer[DramExtension::getBank(payload).ID()].size() < requestBufferSize)
|
||||
if (buffer[lastBankID].size() < requestBufferSize)
|
||||
return true;
|
||||
else
|
||||
return false;
|
||||
@@ -51,7 +51,8 @@ bool SchedulerFrFcfsGrp::hasBufferSpace(tlm_generic_payload *payload)
|
||||
|
||||
void SchedulerFrFcfsGrp::storeRequest(tlm_generic_payload *payload)
|
||||
{
|
||||
buffer[DramExtension::getBank(payload).ID()].push_back(payload);
|
||||
lastBankID = DramExtension::getBank(payload).ID();
|
||||
buffer[lastBankID].push_back(payload);
|
||||
}
|
||||
|
||||
void SchedulerFrFcfsGrp::removeRequest(tlm_generic_payload *payload)
|
||||
|
||||
@@ -49,7 +49,7 @@ class SchedulerFrFcfsGrp : public SchedulerIF
|
||||
{
|
||||
public:
|
||||
SchedulerFrFcfsGrp();
|
||||
virtual bool hasBufferSpace(tlm_generic_payload *) override;
|
||||
virtual bool hasBufferSpace() override;
|
||||
virtual void storeRequest(tlm_generic_payload *) override;
|
||||
virtual void removeRequest(tlm_generic_payload *) override;
|
||||
virtual tlm_generic_payload *getNextRequest(BankMachine *) override;
|
||||
@@ -59,6 +59,7 @@ private:
|
||||
std::vector<std::list<tlm_generic_payload *>> buffer;
|
||||
unsigned requestBufferSize;
|
||||
tlm_command lastCommand = TLM_READ_COMMAND;
|
||||
unsigned lastBankID;
|
||||
};
|
||||
|
||||
#endif // SCHEDULERFRFCFSGRP_H
|
||||
|
||||
@@ -49,7 +49,7 @@ class SchedulerIF
|
||||
{
|
||||
public:
|
||||
virtual ~SchedulerIF() {}
|
||||
virtual bool hasBufferSpace(tlm_generic_payload *) = 0;
|
||||
virtual bool hasBufferSpace() = 0;
|
||||
virtual void storeRequest(tlm_generic_payload *) = 0;
|
||||
virtual void removeRequest(tlm_generic_payload *) = 0;
|
||||
virtual tlm_generic_payload *getNextRequest(BankMachine *) = 0;
|
||||
|
||||
Reference in New Issue
Block a user