PowerDown Manager and Bankwise PowerDown

This commit is contained in:
Janik Schlemminger
2014-04-02 16:10:10 +02:00
parent e930002e5c
commit 9b49ca2d64
27 changed files with 757 additions and 102 deletions

View File

@@ -39,19 +39,19 @@ public:
tlm_utils::simple_initiator_socket<ControllerWrapper, BUSWIDTH, tlm::tlm_base_protocol_types> iSocket;
tlm_utils::simple_target_socket<ControllerWrapper, BUSWIDTH, tlm::tlm_base_protocol_types> tSocket;
ControllerWrapper(sc_module_name name, TlmRecorder& recorder):
frontendPEQ(this, &ControllerWrapper::frontendPEQCallback), dramPEQ(
this, &ControllerWrapper::dramPEQCallback), controllerPEQ(this,
&ControllerWrapper::controllerPEQCallback), recorder(recorder), debugManager(DebugManager::getInstance())
ControllerWrapper(sc_module_name name, TlmRecorder& recorder) :
frontendPEQ(this, &ControllerWrapper::frontendPEQCallback), dramPEQ(this,
&ControllerWrapper::dramPEQCallback), controllerPEQ(this,
&ControllerWrapper::controllerPEQCallback), recorder(recorder), debugManager(
DebugManager::getInstance())
{
controller = new Controller(*this, recorder);
scheduler = new FR_FCFS(controller->getBankStates());
inputBufferDelay = controller->config.Timings.clk;
scheduler = new Fifo(controller->getBankStates());
inputBufferDelay = controller->config.Timings.clk;
iSocket.register_nb_transport_bw(this, &ControllerWrapper::nb_transport_bw);
tSocket.register_nb_transport_fw(this, &ControllerWrapper::nb_transport_fw);
for(Bank bank:controller->getBankStates().getBanks())
bankIsFreeForRequest[bank] = true;
payloadsInSystem = std::vector<int>(controller->config.numberOfBanks);
}
~ControllerWrapper()
@@ -60,35 +60,53 @@ public:
delete scheduler;
}
virtual void send(const ScheduledCommand& command,tlm_generic_payload& payload) override
virtual void send(const ScheduledCommand& command, tlm_generic_payload& payload) override
{
assert(command.getStart() >= sc_time_stamp());
switch (command.getCommand())
{
case Command::Read:
dramPEQ.notify(payload,BEGIN_RD, command.getStart() - sc_time_stamp());
dramPEQ.notify(payload,END_RD, command.getEnd() - sc_time_stamp());
dramPEQ.notify(payload, BEGIN_RD, command.getStart() - sc_time_stamp());
dramPEQ.notify(payload, END_RD, command.getEnd() - sc_time_stamp());
break;
case Command::Write:
dramPEQ.notify(payload,BEGIN_WR, command.getStart() - sc_time_stamp());
dramPEQ.notify(payload,END_WR, command.getEnd() - sc_time_stamp());
dramPEQ.notify(payload, BEGIN_WR, command.getStart() - sc_time_stamp());
dramPEQ.notify(payload, END_WR, command.getEnd() - sc_time_stamp());
break;
case Command::AutoRefresh:
dramPEQ.notify(payload,BEGIN_AUTO_REFRESH, command.getStart() - sc_time_stamp());
dramPEQ.notify(payload,END_AUTO_REFRESH, command.getEnd() - sc_time_stamp());
dramPEQ.notify(payload, BEGIN_AUTO_REFRESH, command.getStart() - sc_time_stamp());
dramPEQ.notify(payload, END_AUTO_REFRESH, command.getEnd() - sc_time_stamp());
break;
case Command::Activate:
dramPEQ.notify(payload,BEGIN_ACT, command.getStart() - sc_time_stamp());
dramPEQ.notify(payload,END_ACT, command.getEnd() - sc_time_stamp());
dramPEQ.notify(payload, BEGIN_ACT, command.getStart() - sc_time_stamp());
dramPEQ.notify(payload, END_ACT, command.getEnd() - sc_time_stamp());
break;
case Command::Precharge:
dramPEQ.notify(payload,BEGIN_PRE, command.getStart() - sc_time_stamp());
dramPEQ.notify(payload,END_PRE, command.getEnd() - sc_time_stamp());
dramPEQ.notify(payload, BEGIN_PRE, command.getStart() - sc_time_stamp());
dramPEQ.notify(payload, END_PRE, command.getEnd() - sc_time_stamp());
break;
case Command::PrechargeAll:
dramPEQ.notify(payload,BEGIN_PRE_ALL, command.getStart() - sc_time_stamp());
dramPEQ.notify(payload,END_PRE_ALL, command.getEnd() - sc_time_stamp());
dramPEQ.notify(payload, BEGIN_PRE_ALL, command.getStart() - sc_time_stamp());
dramPEQ.notify(payload, END_PRE_ALL, command.getEnd() - sc_time_stamp());
break;
case Command::PDNA:
dramPEQ.notify(payload, BEGIN_PDNA, command.getStart() - sc_time_stamp());
break;
case Command::PDNP:
dramPEQ.notify(payload, BEGIN_PDNP, command.getStart() - sc_time_stamp());
break;
case Command::SREF:
dramPEQ.notify(payload, BEGIN_SREF, command.getStart() - sc_time_stamp());
break;
case Command::PDNAX:
dramPEQ.notify(payload, END_PDNA, command.getStart() - sc_time_stamp());
break;
case Command::PDNPX:
dramPEQ.notify(payload, END_PDNP, command.getStart() - sc_time_stamp());
break;
case Command::SREFX:
dramPEQ.notify(payload, END_SREF, command.getStart() - sc_time_stamp());
break;
default:
SC_REPORT_FATAL(0, "unsupported command in controller wrapper");
@@ -102,12 +120,12 @@ public:
assert(time >= sc_time_stamp());
sc_time delay = time - sc_time_stamp();
controllerPEQ.notify(payload, REFRESH_TRIGGER, delay);
}
}
private:
Controller* controller;
Scheduler* scheduler;
map<Bank, bool> bankIsFreeForRequest;
std::vector<int> payloadsInSystem;
tlm_utils::peq_with_cb_and_phase<ControllerWrapper> frontendPEQ;
tlm_utils::peq_with_cb_and_phase<ControllerWrapper> dramPEQ;
@@ -121,31 +139,43 @@ private:
{
printDebugMessage("Transaction enters system");
Bank bank = DramExtension::getExtension(payload).getBank();
payloadsInSystem.at(bank.ID()) = payloadsInSystem.at(bank.ID()) + 1;
scheduler->schedule(&payload);
scheduleNextPayload(bank);
}
void scheduleNextPayload(Bank bank)
void payloadLeavesSystem(tlm_generic_payload& payload)
{
printDebugMessage("In trigger for bank " + to_string(bank.ID()));
if(controller->isBusy(sc_time_stamp(), bank))
return;
Bank bank = DramExtension::getExtension(payload).getBank();
payloadsInSystem.at(bank.ID()) = payloadsInSystem.at(bank.ID()) - 1;
int numberOfPayloadsOnBank = payloadsInSystem.at(bank.ID());
else if(scheduler->hasTransactionForBank(bank))
sc_assert(numberOfPayloadsOnBank >= 0);
if (numberOfPayloadsOnBank == 0)
{
tlm_generic_payload* nextTransaction = scheduler->getTransactionForBank(bank);
if(controller->schedule(sc_time_stamp(), *nextTransaction))
{
printDebugMessage("Next payload was scheduled by core");
scheduler->popTransactionForBank(bank);
}
controller->powerDownManager->sleep(bank, sc_time_stamp());
}
}
void payloadLeavesSystem(tlm_generic_payload& payload)
void scheduleNextPayload(Bank bank)
{
if (scheduler->hasTransactionForBank(bank))
{
printDebugMessage("Try to schedule next payload on bank " + to_string(bank.ID()));
if (controller->isBusy(sc_time_stamp(), bank))
return;
tlm_generic_payload* nextTransaction = scheduler->getTransactionForBank(bank);
if (controller->scheduleRequest(sc_time_stamp(), *nextTransaction))
{
scheduler->popTransactionForBank(bank);
printDebugMessage(
"Next payload was scheduled by core for bank " + to_string(bank.ID()));
}
printDebugMessage("End try to schedule next payload on bank " + to_string(bank.ID()));
}
}
tlm_sync_enum nb_transport_bw(tlm_generic_payload& payload, tlm_phase& phase, sc_time& bwDelay)
@@ -157,7 +187,7 @@ private:
tlm_sync_enum nb_transport_fw(tlm_generic_payload& payload, tlm_phase& phase, sc_time& fwDelay)
{
DramExtension::getExtension(payload);
recorder.recordPhase(payload,phase,sc_time_stamp());
recorder.recordPhase(payload, phase, sc_time_stamp());
if (phase == BEGIN_REQ)
{
@@ -191,20 +221,40 @@ private:
void dramPEQCallback(tlm_generic_payload& payload, const tlm_phase& phase)
{
recorder.recordPhase(payload, phase, sc_time_stamp());
recorder.recordPhase(payload, phase, sc_time_stamp());
if (phase == BEGIN_RD || phase == BEGIN_WR)
{
scheduleNextPayload(DramExtension::getExtension(payload).getBank());
sendToDram(payload, phase, SC_ZERO_TIME);
}
else if(phase == BEGIN_AUTO_REFRESH || phase == BEGIN_ACT
|| phase == BEGIN_PRE || phase == BEGIN_PRE_ALL)
else if (phase == BEGIN_AUTO_REFRESH || phase == BEGIN_ACT || phase == BEGIN_PRE
|| phase == BEGIN_PRE_ALL || phase == BEGIN_PDNA || phase == BEGIN_PDNP || phase == BEGIN_SREF)
{
sendToDram(payload, phase, SC_ZERO_TIME);
}
else if(phase == END_AUTO_REFRESH)
else if (phase == END_PDNA || phase == END_PDNP)
{
sendToDram(payload, phase, SC_ZERO_TIME);
scheduleNextPayload(DramExtension::getExtension(payload).getBank());
}
else if( phase == END_SREF)
{
sendToDram(payload, phase, SC_ZERO_TIME);
controller->refreshManager->reInitialize(payload, sc_time_stamp());
scheduleNextPayload(DramExtension::getExtension(payload).getBank());
}
else if (phase == END_AUTO_REFRESH)
{
if (controller->powerDownManager->isActive(
DramExtension::getExtension(payload).getBank()))
{
controller->powerDownManager->sleep(DramExtension::getExtension(payload).getBank(),
sc_time_stamp());
}
scheduleNextPayload(DramExtension::getExtension(payload).getBank());
}
else if (phase == END_RD || phase == END_WR)
@@ -220,7 +270,9 @@ private:
{
ostringstream oss;
oss << phase;
string str = string("dramPEQCallback queue in controller wrapper was triggered with unknown phase ") + oss.str();
string str = string(
"dramPEQCallback queue in controller wrapper was triggered with unknown phase ")
+ oss.str();
SC_REPORT_FATAL(0, str.c_str());
}
}
@@ -255,9 +307,16 @@ private:
void printDebugMessage(string message, Importance importance = Importance::Info)
{
debugManager.printDebugMessage(message,Sender::DramWrapper,importance);
debugManager.printDebugMessage(message, Sender::DramWrapper, importance);
}
void stop()
{
for(Bank bank : controller->state.bankStates.getBanks())
{
controller->powerDownManager->wakeUp(bank, sc_time_stamp());
}
}
};
#endif /* CONTROLLERWRAPPER_H_ */