New hardware-equivalent backpressure implementation.

This commit is contained in:
Lukas Steiner
2020-04-01 16:01:07 +02:00
parent f428d57dfa
commit fbbe306ee5
10 changed files with 88 additions and 79 deletions

View File

@@ -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;

View File

@@ -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;

View File

@@ -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;

View File

@@ -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)

View File

@@ -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

View File

@@ -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)

View File

@@ -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

View File

@@ -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)

View File

@@ -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

View File

@@ -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;