Issue#12 - removal of BUSWIDTH from some modules

Controller.cpp is back, but now it is not empty anymore.
This commit is contained in:
Éder F. Zulian
2016-06-29 23:47:35 +02:00
parent d30062db68
commit f00c5ddf95
6 changed files with 536 additions and 516 deletions

View File

@@ -103,7 +103,8 @@ SOURCES += \
src/controller/RowBufferStates.cpp \
src/controller/scheduler/IScheduler.cpp \
src/controller/scheduler/FifoStrict.cpp \
src/error/errormodel.cpp
src/error/errormodel.cpp \
src/controller/Controller.cpp
HEADERS += \
src/common/third_party/tinyxml2/tinyxml2.h \

View File

@@ -0,0 +1,526 @@
/*
* Copyright (c) 2015, University of Kaiserslautern
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* 3. Neither the name of the copyright holder nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER
* OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* Authors:
* Robert Gernhardt
* Matthias Jung
*/
#include "Controller.h"
void Controller::buildScheduler()
{
string selectedScheduler = Configuration::getInstance().Scheduler;
if (selectedScheduler == "FIFO")
{
scheduler = new Fifo(*controllerCore);
}
else if (selectedScheduler == "FIFO_STRICT")
{
scheduler = new FifoStrict(*this, *controllerCore);
}
else if (selectedScheduler == "FR_FCFS")
{
scheduler = new FR_FCFS(*controllerCore);
}
// else if (selectedScheduler == "PAR_BS")
// {
// scheduler = new PAR_BS(*controllerCore, Configuration::getInstance().RefreshAwareScheduling,
// Configuration::getInstance().Capsize);
// }
// else if (selectedScheduler == "Grouper")
// {
// scheduler = new ReadWriteGrouper(*controllerCore);
// }
else
reportFatal(name(), "unsupported scheduler: " + selectedScheduler);
}
void Controller::send(const ScheduledCommand &command, tlm_generic_payload &payload)
{
sc_assert(command.getStart() >= sc_time_stamp());
TimeInterval dataStrobe;
switch (command.getCommand())
{
//TODO: refactor tlm recorder
case Command::Read:
dataStrobe = command.getIntervalOnDataStrobe();
tlmRecorder->updateDataStrobe(dataStrobe.start, dataStrobe.end, payload);
controllerCorePEQ.notify(payload, BEGIN_RD, command.getStart() - sc_time_stamp());
break;
case Command::ReadA:
dataStrobe = command.getIntervalOnDataStrobe();
tlmRecorder->updateDataStrobe(dataStrobe.start, dataStrobe.end, payload);
controllerCorePEQ.notify(payload, BEGIN_RDA, command.getStart() - sc_time_stamp());
break;
case Command::Write:
dataStrobe = command.getIntervalOnDataStrobe();
tlmRecorder->updateDataStrobe(dataStrobe.start, dataStrobe.end, payload);
controllerCorePEQ.notify(payload, BEGIN_WR, command.getStart() - sc_time_stamp());
break;
case Command::WriteA:
dataStrobe = command.getIntervalOnDataStrobe();
tlmRecorder->updateDataStrobe(dataStrobe.start, dataStrobe.end, payload);
controllerCorePEQ.notify(payload, BEGIN_WRA, command.getStart() - sc_time_stamp());
break;
case Command::AutoRefresh:
if(!Configuration::getInstance().BankwiseLogic)
{
if(command.getBank() == Bank(0))
controllerCorePEQ.notify(payload, BEGIN_REFA, command.getStart() - sc_time_stamp());
}
else
controllerCorePEQ.notify(payload, BEGIN_REFB, command.getStart() - sc_time_stamp());
break;
case Command::Activate:
controllerCorePEQ.notify(payload, BEGIN_ACT, command.getStart() - sc_time_stamp());
break;
case Command::Precharge:
controllerCorePEQ.notify(payload, BEGIN_PRE, command.getStart() - sc_time_stamp());
break;
case Command::PrechargeAll:
if(command.getBank() == Bank(0))
controllerCorePEQ.notify(payload, BEGIN_PRE_ALL, command.getStart() - sc_time_stamp());
break;
case Command::PDNA:
if(!Configuration::getInstance().BankwiseLogic)
{
if(command.getBank() == Bank(0))
controllerCorePEQ.notify(payload, BEGIN_PDNA, command.getStart() - sc_time_stamp());
}
else
controllerCorePEQ.notify(payload, BEGIN_PDNAB, command.getStart() - sc_time_stamp());
break;
case Command::PDNAX:
if(!Configuration::getInstance().BankwiseLogic)
{
if(command.getBank() == Bank(0))
controllerCorePEQ.notify(payload, END_PDNA, command.getStart() - sc_time_stamp());
}
else
controllerCorePEQ.notify(payload, END_PDNAB, command.getStart() - sc_time_stamp());
break;
case Command::PDNP:
if(!Configuration::getInstance().BankwiseLogic)
{
if(command.getBank() == Bank(0))
controllerCorePEQ.notify(payload, BEGIN_PDNP, command.getStart() - sc_time_stamp());
}
else
controllerCorePEQ.notify(payload, BEGIN_PDNPB, command.getStart() - sc_time_stamp());
break;
case Command::PDNPX:
if(!Configuration::getInstance().BankwiseLogic)
{
if(command.getBank() == Bank(0))
controllerCorePEQ.notify(payload, END_PDNP, command.getStart() - sc_time_stamp());
}
else
controllerCorePEQ.notify(payload, END_PDNPB, command.getStart() - sc_time_stamp());
break;
case Command::SREF:
if(!Configuration::getInstance().BankwiseLogic)
{
if(command.getBank() == Bank(0))
controllerCorePEQ.notify(payload, BEGIN_SREF, command.getStart() - sc_time_stamp());
}
else
controllerCorePEQ.notify(payload, BEGIN_SREFB, command.getStart() - sc_time_stamp());
break;
case Command::SREFX:
if(!Configuration::getInstance().BankwiseLogic)
{
if(command.getBank() == Bank(0))
controllerCorePEQ.notify(payload, END_SREF, command.getStart() - sc_time_stamp());
}
else
controllerCorePEQ.notify(payload, END_SREFB, command.getStart() - sc_time_stamp());
break;
default:
SC_REPORT_FATAL(0, "unsupported command was sent by controller");
break;
}
}
void Controller::send(Trigger trigger, sc_time time, tlm_generic_payload &payload)
{
sc_assert(time >= sc_time_stamp());
sc_time delay = time - sc_time_stamp();
if (trigger == Trigger::REFTrigger)
{
controllerCorePEQ.notify(payload, REF_TRIGGER, delay);
}
else if (trigger == Trigger::PDNTrigger)
{
controllerCorePEQ.notify(payload, PDN_TRIGGER, delay);
}
else
{
SC_REPORT_FATAL("controller wrapper", "unknown trigger");
}
}
void Controller::controllerCorePEQCallback(tlm_generic_payload &payload, const tlm_phase &phase)
{
if (phase == REF_TRIGGER)
{
controllerCore->triggerRefresh(payload);
}
else if (phase == PDN_TRIGGER)
{
controllerCore->powerDownManager->sleep(DramExtension::getExtension(payload).getBank(),sc_time_stamp());
}
else
{
Bank bank = DramExtension::getBank(payload);
sendToDram(payload, phase, SC_ZERO_TIME);
if (phase == BEGIN_RD || phase == BEGIN_WR)
{
scheduleNextFromScheduler(DramExtension::getBank(payload));
}
else if (phase == BEGIN_REFB)
printDebugMessage("Entering REFB on bank " + to_string(bank.ID()));
else if (phase == BEGIN_REFA)
printDebugMessage("Entering REFA");
else if (containsPhase(phase, { BEGIN_PDNAB, BEGIN_PDNPB, BEGIN_SREFB }))
printDebugMessage("Entering PowerDown " + phaseNameToString(phase) + " on bank " + to_string(bank.ID()));
else if (containsPhase(phase, { END_PDNAB, END_PDNPB, END_SREFB }))
printDebugMessage("Leaving PowerDown " + phaseNameToString(phase) + " on bank " + to_string(bank.ID()));
else if (containsPhase(phase, { BEGIN_PDNA, BEGIN_PDNP, BEGIN_SREF }))
printDebugMessage("Entering PowerDown " + phaseNameToString(phase) + " on all banks");
else if (containsPhase(phase, { END_PDNA, END_PDNP, END_SREF }))
printDebugMessage("Leaving PowerDown " + phaseNameToString(phase) + " on all banks" );
else if (containsPhase(phase, { BEGIN_RD, BEGIN_WR, BEGIN_ACT, BEGIN_PRE, BEGIN_PRE_ALL, BEGIN_RDA, BEGIN_WRA }))
{
}
else
SC_REPORT_FATAL(0, "refreshTriggerPEQCallback queue in controller wrapper was triggered with unsupported phase");
}
}
tlm_sync_enum Controller::nb_transport_fw(tlm_generic_payload &payload, tlm_phase &phase, sc_time &fwDelay)
{
sc_time recTime;
sc_time notDelay;
if (phase == BEGIN_REQ)
{
recTime = fwDelay + sc_time_stamp();
notDelay = clkAlign(sc_time_stamp() + fwDelay) - (sc_time_stamp() + fwDelay) + Configuration::getInstance().memSpec.clk;
printDebugMessage("[fw] Recording " + phaseNameToString(phase) + " at " + recTime.to_string() + " notification in " + notDelay.to_string());
tlmRecorder->recordPhase(payload, phase, recTime);
frontendPEQ.notify(payload, phase, notDelay);
//Bandwidth IDLE
if ((getTotalNumberOfPayloadsInSystem()== 0)&& idleState){
endBandwidthIdleCollector();
}
}
else if (phase == END_RESP)
{
recTime = fwDelay + sc_time_stamp() + Configuration::getInstance().memSpec.clk;
notDelay = clkAlign(sc_time_stamp() + fwDelay) - (sc_time_stamp() + fwDelay);
printDebugMessage("[fw] Recording " + phaseNameToString(phase) + " at " + recTime.to_string() + " notification in " + notDelay.to_string());
// Badnwith IDLE
if (getTotalNumberOfPayloadsInSystem()==1){
startBandwidthIdleCollector();
}
tlmRecorder->recordPhase(payload, phase, recTime);
frontendPEQ.notify(payload, phase, notDelay);
}
return TLM_ACCEPTED;
}
unsigned int Controller::transport_dbg(tlm::tlm_generic_payload& trans)
{
return iSocket->transport_dbg(trans);
}
void Controller::frontendPEQCallback(tlm_generic_payload &payload, const tlm_phase &phase)
{
if (phase == BEGIN_REQ)
{
printDebugMessage(string("Payload in system: ") + to_string(getTotalNumberOfPayloadsInSystem()));
payload.acquire();
payloadEntersSystem(payload);
if (getTotalNumberOfPayloadsInSystem() > controllerCore->config.MaxNrOfTransactions)
{
printDebugMessage("##Backpressure: Max number of transactions in system reached");
backpressure = &payload;
return;
}
payload.set_response_status(tlm::TLM_OK_RESPONSE);
sendToFrontend(payload, END_REQ, SC_ZERO_TIME);
scheduler->schedule(&payload);
scheduleNextFromScheduler(DramExtension::getExtension(payload).getBank());
}
else if (phase == END_RESP)
{
if (backpressure != NULL)
{
printDebugMessage("##Backpressure released");
backpressure->set_response_status(tlm::TLM_OK_RESPONSE);
sendToFrontend(*backpressure, END_REQ, SC_ZERO_TIME);
scheduler->schedule(backpressure);
scheduleNextFromScheduler(DramExtension::getExtension(backpressure).getBank());
backpressure = NULL;
}
payloadLeavesSystem(payload);
payload.release();
}
else
{
SC_REPORT_FATAL(0, "Frontend PEQ event queue in controller wrapper was triggered with unknown phase");
}
}
void Controller::payloadEntersSystem(tlm_generic_payload &payload)
{
Bank bank = DramExtension::getExtension(payload).getBank();
printDebugMessage(
"Payload enters system on bank " + to_string(bank.ID()) + ". Total number of payloads in Controller: "
+ to_string(getTotalNumberOfPayloadsInSystem()));
numberOfPayloadsInSystem[bank]++;
// Set Start Time for Simulation
if (startTimeSet == false){
printDebugMessage("Simulation Timer Start");
startTime = sc_time_stamp()-Configuration::getInstance().memSpec.clk;
startTimeSet = true;
}
}
void Controller::payloadLeavesSystem(tlm_generic_payload &payload)
{
Bank bank = DramExtension::getExtension(payload).getBank();
numberOfPayloadsInSystem[bank]--;
printDebugMessage(
"Payload left system on bank " + to_string(bank.ID()) + ". Total number of payloads in Controller: "
+ to_string(getTotalNumberOfPayloadsInSystem()));
controllerCore->powerDownManager->triggerSleep(bank, sc_time_stamp());
}
unsigned int Controller::getTotalNumberOfPayloadsInSystem()
{
unsigned int sum = 0;
for (Bank bank : controllerCore->getBanks())
{
sum += numberOfPayloadsInSystem[bank];
}
return sum;
}
void Controller::scheduleNextFromScheduler(Bank bank)
{
if(controllerCore->bankIsBusy(bank))
{
return;
}
pair<Command, tlm::tlm_generic_payload*> nextRequest = scheduler->getNextRequest(bank);
if(nextRequest.second != NULL)
{
controllerCore->powerDownManager->wakeUp(DramExtension::getExtension(nextRequest.second).getBank(), sc_time_stamp());
controllerCore->scheduleRequest(nextRequest.first, *nextRequest.second);
printDebugMessage("\t-> Next payload was scheduled by core [" + commandToString(nextRequest.first) + "]");
}
while (!blockedRequests.empty()) {
bank = blockedRequests.front();
blockedRequests.pop();
pair<Command, tlm::tlm_generic_payload*> nextRequest = scheduler->getNextRequest(bank);
if (nextRequest.second != NULL) {
controllerCore->powerDownManager->wakeUp(DramExtension::getExtension(nextRequest.second).getBank(), sc_time_stamp());
controllerCore->scheduleRequest(nextRequest.first, *nextRequest.second);
printDebugMessage("\t-> Next payload was scheduled by core [" + commandToString(nextRequest.first) + "] (unblocked)");
}
}
}
void Controller::sendToFrontend(tlm_generic_payload &payload, const tlm_phase &phase, const sc_time &delay)
{
tlm_phase TPhase = phase;
sc_time TDelay = delay;
tSocket->nb_transport_bw(payload, TPhase, TDelay);
}
tlm_sync_enum Controller::nb_transport_bw(tlm_generic_payload &payload, tlm_phase &phase, sc_time &bwDelay)
{
sc_time recTime = bwDelay + sc_time_stamp();
sc_time notDelay = bwDelay;
printDebugMessage("[bw] Recording " + phaseNameToString(phase) + " at " + recTime.to_string() + " notification in " + notDelay.to_string());
dramPEQ.notify(payload, phase, notDelay);
tlmRecorder->recordPhase(payload, phase, recTime);
return TLM_ACCEPTED;
}
void Controller::dramPEQCallback(tlm_generic_payload &payload, const tlm_phase &phase)
{
Bank bank = DramExtension::getExtension(payload).getBank();
printDebugMessage("Received " + phaseNameToString(phase) + " on bank " + to_string(bank.ID()) + " from DRAM");
if (phase == END_RD || phase == END_WR)
{
sendToFrontend(payload, BEGIN_RESP, SC_ZERO_TIME);
}
else if (phase == END_RDA || phase == END_WRA)
{
sendToFrontend(payload, BEGIN_RESP, SC_ZERO_TIME);
scheduleNextFromScheduler(bank);
}
else if (phase == END_REFA)
{
printDebugMessage("Finished auto refresh on all banks ");
bool sleepy = true;
for(Bank bank : controllerCore->getBanks())
{
if(numberOfPayloadsInSystem[bank] != 0)
{
sleepy = false;
scheduleNextFromScheduler(bank);
}
}
if(sleepy == true)
{
controllerCore->powerDownManager->sleep(0,sc_time_stamp());
}
}
else if(phase == END_REFB)
{
printDebugMessage("Finished auto refresh on bank " + to_string(bank.ID()));
if(numberOfPayloadsInSystem[bank] == 0)
{
controllerCore->powerDownManager->sleep(bank,sc_time_stamp());
}
else
{
scheduleNextFromScheduler(bank);
}
scheduleNextFromScheduler(bank);
}
else if (containsPhase(phase, { END_PRE, END_ACT }))
{
scheduleNextFromScheduler(bank);
}
else if(phase == END_PRE_ALL)
{
// No need to trigger anything for a END_PRE_ALL. It is followed by a AUTO_REFRESH anyway (in our current
// scheduler implementation)
}
else
{
string str = string("dramPEQCallback queue in controller wrapper was triggered with unsupported phase ")
+ phaseNameToString(phase);
SC_REPORT_FATAL(0, str.c_str());
}
}
void Controller::sendToDram(tlm_generic_payload &payload, const tlm_phase &phase, const sc_time &delay)
{
tlm_phase TPhase = phase;
sc_time TDelay = delay;
iSocket->nb_transport_fw(payload, TPhase, TDelay);
}
void Controller::printDebugMessage(string message)
{
debugManager.printDebugMessage(name(), message);
}
bool Controller::containsPhase(tlm_phase phase, std::vector<tlm_phase> phases)
{
for (tlm_phase p : phases)
{
if (p == phase)
return true;
}
return false;
}
void Controller::terminateSimulation()
{
for (Bank bank : controllerCore->getBanks())
{
controllerCore->powerDownManager->wakeUp(bank, clkAlign(sc_time_stamp()));
}
}
void Controller::startBandwidthIdleCollector()
{
printDebugMessage("IDLE Start");
idleStart = sc_time_stamp();
endTime = sc_time_stamp();
idleState = true;
}
void Controller::endBandwidthIdleCollector()
{
printDebugMessage("IDLE End");
idleTime += sc_time_stamp()-idleStart+ Configuration::getInstance().memSpec.clk;
idleState = false;
}
sc_time Controller::getIdleTime()
{
printDebugMessage("IDLE Time: "+idleTime.to_string());
return idleTime;
}
sc_time Controller::getEndTime()
{
printDebugMessage("End Time: "+endTime.to_string());
return endTime;
}
sc_time Controller::getStartTime()
{
printDebugMessage("Start Time: "+startTime.to_string());
return startTime;
}

View File

@@ -72,18 +72,17 @@
using namespace std;
using namespace tlm;
template<unsigned int BUSWIDTH = 128>
struct Controller: public sc_module, public IController
{
public:
Controller(sc_module_name /*name*/, TlmRecorder *rec) :
frontendPEQ(this, &Controller<BUSWIDTH>::frontendPEQCallback), dramPEQ(this, &Controller<BUSWIDTH>::dramPEQCallback), controllerCorePEQ(this, &Controller<BUSWIDTH>::controllerCorePEQCallback), debugManager(DebugManager::getInstance()), tlmRecorder(rec)
frontendPEQ(this, &Controller::frontendPEQCallback), dramPEQ(this, &Controller::dramPEQCallback), controllerCorePEQ(this, &Controller::controllerCorePEQCallback), debugManager(DebugManager::getInstance()), tlmRecorder(rec)
{
controllerCore = new ControllerCore("core", *this, numberOfPayloadsInSystem);
buildScheduler();
iSocket.register_nb_transport_bw(this, &Controller<BUSWIDTH>::nb_transport_bw);
tSocket.register_nb_transport_fw(this, &Controller<BUSWIDTH>::nb_transport_fw);
tSocket.register_transport_dbg(this, &Controller<BUSWIDTH>::transport_dbg);
iSocket.register_nb_transport_bw(this, &Controller::nb_transport_bw);
tSocket.register_nb_transport_fw(this, &Controller::nb_transport_fw);
tSocket.register_transport_dbg(this, &Controller::transport_dbg);
}
~Controller()
@@ -156,511 +155,5 @@ private:
};
// --- IMPLEMENTATION -----
template<unsigned int BUSWIDTH>
void Controller<BUSWIDTH>::buildScheduler()
{
string selectedScheduler = Configuration::getInstance().Scheduler;
if (selectedScheduler == "FIFO")
{
scheduler = new Fifo(*controllerCore);
}
else if (selectedScheduler == "FIFO_STRICT")
{
scheduler = new FifoStrict(*this, *controllerCore);
}
else if (selectedScheduler == "FR_FCFS")
{
scheduler = new FR_FCFS(*controllerCore);
}
// else if (selectedScheduler == "PAR_BS")
// {
// scheduler = new PAR_BS(*controllerCore, Configuration::getInstance().RefreshAwareScheduling,
// Configuration::getInstance().Capsize);
// }
// else if (selectedScheduler == "Grouper")
// {
// scheduler = new ReadWriteGrouper(*controllerCore);
// }
else
reportFatal(name(), "unsupported scheduler: " + selectedScheduler);
}
template<unsigned int BUSWIDTH>
void Controller<BUSWIDTH>::send(const ScheduledCommand &command, tlm_generic_payload &payload)
{
sc_assert(command.getStart() >= sc_time_stamp());
TimeInterval dataStrobe;
switch (command.getCommand())
{
//TODO: refactor tlm recorder
case Command::Read:
dataStrobe = command.getIntervalOnDataStrobe();
tlmRecorder->updateDataStrobe(dataStrobe.start, dataStrobe.end, payload);
controllerCorePEQ.notify(payload, BEGIN_RD, command.getStart() - sc_time_stamp());
break;
case Command::ReadA:
dataStrobe = command.getIntervalOnDataStrobe();
tlmRecorder->updateDataStrobe(dataStrobe.start, dataStrobe.end, payload);
controllerCorePEQ.notify(payload, BEGIN_RDA, command.getStart() - sc_time_stamp());
break;
case Command::Write:
dataStrobe = command.getIntervalOnDataStrobe();
tlmRecorder->updateDataStrobe(dataStrobe.start, dataStrobe.end, payload);
controllerCorePEQ.notify(payload, BEGIN_WR, command.getStart() - sc_time_stamp());
break;
case Command::WriteA:
dataStrobe = command.getIntervalOnDataStrobe();
tlmRecorder->updateDataStrobe(dataStrobe.start, dataStrobe.end, payload);
controllerCorePEQ.notify(payload, BEGIN_WRA, command.getStart() - sc_time_stamp());
break;
case Command::AutoRefresh:
if(!Configuration::getInstance().BankwiseLogic)
{
if(command.getBank() == Bank(0))
controllerCorePEQ.notify(payload, BEGIN_REFA, command.getStart() - sc_time_stamp());
}
else
controllerCorePEQ.notify(payload, BEGIN_REFB, command.getStart() - sc_time_stamp());
break;
case Command::Activate:
controllerCorePEQ.notify(payload, BEGIN_ACT, command.getStart() - sc_time_stamp());
break;
case Command::Precharge:
controllerCorePEQ.notify(payload, BEGIN_PRE, command.getStart() - sc_time_stamp());
break;
case Command::PrechargeAll:
if(command.getBank() == Bank(0))
controllerCorePEQ.notify(payload, BEGIN_PRE_ALL, command.getStart() - sc_time_stamp());
break;
case Command::PDNA:
if(!Configuration::getInstance().BankwiseLogic)
{
if(command.getBank() == Bank(0))
controllerCorePEQ.notify(payload, BEGIN_PDNA, command.getStart() - sc_time_stamp());
}
else
controllerCorePEQ.notify(payload, BEGIN_PDNAB, command.getStart() - sc_time_stamp());
break;
case Command::PDNAX:
if(!Configuration::getInstance().BankwiseLogic)
{
if(command.getBank() == Bank(0))
controllerCorePEQ.notify(payload, END_PDNA, command.getStart() - sc_time_stamp());
}
else
controllerCorePEQ.notify(payload, END_PDNAB, command.getStart() - sc_time_stamp());
break;
case Command::PDNP:
if(!Configuration::getInstance().BankwiseLogic)
{
if(command.getBank() == Bank(0))
controllerCorePEQ.notify(payload, BEGIN_PDNP, command.getStart() - sc_time_stamp());
}
else
controllerCorePEQ.notify(payload, BEGIN_PDNPB, command.getStart() - sc_time_stamp());
break;
case Command::PDNPX:
if(!Configuration::getInstance().BankwiseLogic)
{
if(command.getBank() == Bank(0))
controllerCorePEQ.notify(payload, END_PDNP, command.getStart() - sc_time_stamp());
}
else
controllerCorePEQ.notify(payload, END_PDNPB, command.getStart() - sc_time_stamp());
break;
case Command::SREF:
if(!Configuration::getInstance().BankwiseLogic)
{
if(command.getBank() == Bank(0))
controllerCorePEQ.notify(payload, BEGIN_SREF, command.getStart() - sc_time_stamp());
}
else
controllerCorePEQ.notify(payload, BEGIN_SREFB, command.getStart() - sc_time_stamp());
break;
case Command::SREFX:
if(!Configuration::getInstance().BankwiseLogic)
{
if(command.getBank() == Bank(0))
controllerCorePEQ.notify(payload, END_SREF, command.getStart() - sc_time_stamp());
}
else
controllerCorePEQ.notify(payload, END_SREFB, command.getStart() - sc_time_stamp());
break;
default:
SC_REPORT_FATAL(0, "unsupported command was sent by controller");
break;
}
}
template<unsigned int BUSWIDTH>
void Controller<BUSWIDTH>::send(Trigger trigger, sc_time time, tlm_generic_payload &payload)
{
sc_assert(time >= sc_time_stamp());
sc_time delay = time - sc_time_stamp();
if (trigger == Trigger::REFTrigger)
{
controllerCorePEQ.notify(payload, REF_TRIGGER, delay);
}
else if (trigger == Trigger::PDNTrigger)
{
controllerCorePEQ.notify(payload, PDN_TRIGGER, delay);
}
else
{
SC_REPORT_FATAL("controller wrapper", "unknown trigger");
}
}
template<unsigned int BUSWIDTH>
void Controller<BUSWIDTH>::controllerCorePEQCallback(tlm_generic_payload &payload, const tlm_phase &phase)
{
if (phase == REF_TRIGGER)
{
controllerCore->triggerRefresh(payload);
}
else if (phase == PDN_TRIGGER)
{
controllerCore->powerDownManager->sleep(DramExtension::getExtension(payload).getBank(),sc_time_stamp());
}
else
{
Bank bank = DramExtension::getBank(payload);
sendToDram(payload, phase, SC_ZERO_TIME);
if (phase == BEGIN_RD || phase == BEGIN_WR)
{
scheduleNextFromScheduler(DramExtension::getBank(payload));
}
else if (phase == BEGIN_REFB)
printDebugMessage("Entering REFB on bank " + to_string(bank.ID()));
else if (phase == BEGIN_REFA)
printDebugMessage("Entering REFA");
else if (containsPhase(phase, { BEGIN_PDNAB, BEGIN_PDNPB, BEGIN_SREFB }))
printDebugMessage("Entering PowerDown " + phaseNameToString(phase) + " on bank " + to_string(bank.ID()));
else if (containsPhase(phase, { END_PDNAB, END_PDNPB, END_SREFB }))
printDebugMessage("Leaving PowerDown " + phaseNameToString(phase) + " on bank " + to_string(bank.ID()));
else if (containsPhase(phase, { BEGIN_PDNA, BEGIN_PDNP, BEGIN_SREF }))
printDebugMessage("Entering PowerDown " + phaseNameToString(phase) + " on all banks");
else if (containsPhase(phase, { END_PDNA, END_PDNP, END_SREF }))
printDebugMessage("Leaving PowerDown " + phaseNameToString(phase) + " on all banks" );
else if (containsPhase(phase, { BEGIN_RD, BEGIN_WR, BEGIN_ACT, BEGIN_PRE, BEGIN_PRE_ALL, BEGIN_RDA, BEGIN_WRA }))
{
}
else
SC_REPORT_FATAL(0, "refreshTriggerPEQCallback queue in controller wrapper was triggered with unsupported phase");
}
}
template<unsigned int BUSWIDTH>
tlm_sync_enum Controller<BUSWIDTH>::nb_transport_fw(tlm_generic_payload &payload, tlm_phase &phase, sc_time &fwDelay)
{
sc_time recTime;
sc_time notDelay;
if (phase == BEGIN_REQ)
{
recTime = fwDelay + sc_time_stamp();
notDelay = clkAlign(sc_time_stamp() + fwDelay) - (sc_time_stamp() + fwDelay) + Configuration::getInstance().memSpec.clk;
printDebugMessage("[fw] Recording " + phaseNameToString(phase) + " at " + recTime.to_string() + " notification in " + notDelay.to_string());
tlmRecorder->recordPhase(payload, phase, recTime);
frontendPEQ.notify(payload, phase, notDelay);
//Bandwidth IDLE
if ((getTotalNumberOfPayloadsInSystem()== 0)&& idleState){
endBandwidthIdleCollector();
}
}
else if (phase == END_RESP)
{
recTime = fwDelay + sc_time_stamp() + Configuration::getInstance().memSpec.clk;
notDelay = clkAlign(sc_time_stamp() + fwDelay) - (sc_time_stamp() + fwDelay);
printDebugMessage("[fw] Recording " + phaseNameToString(phase) + " at " + recTime.to_string() + " notification in " + notDelay.to_string());
// Badnwith IDLE
if (getTotalNumberOfPayloadsInSystem()==1){
startBandwidthIdleCollector();
}
tlmRecorder->recordPhase(payload, phase, recTime);
frontendPEQ.notify(payload, phase, notDelay);
}
return TLM_ACCEPTED;
}
template<unsigned int BUSWIDTH>
unsigned int Controller<BUSWIDTH>::transport_dbg(tlm::tlm_generic_payload& trans)
{
return iSocket->transport_dbg(trans);
}
template<unsigned int BUSWIDTH>
void Controller<BUSWIDTH>::frontendPEQCallback(tlm_generic_payload &payload, const tlm_phase &phase)
{
if (phase == BEGIN_REQ)
{
printDebugMessage(string("Payload in system: ") + to_string(getTotalNumberOfPayloadsInSystem()));
payload.acquire();
payloadEntersSystem(payload);
if (getTotalNumberOfPayloadsInSystem() > controllerCore->config.MaxNrOfTransactions)
{
printDebugMessage("##Backpressure: Max number of transactions in system reached");
backpressure = &payload;
return;
}
payload.set_response_status(tlm::TLM_OK_RESPONSE);
sendToFrontend(payload, END_REQ, SC_ZERO_TIME);
scheduler->schedule(&payload);
scheduleNextFromScheduler(DramExtension::getExtension(payload).getBank());
}
else if (phase == END_RESP)
{
if (backpressure != NULL)
{
printDebugMessage("##Backpressure released");
backpressure->set_response_status(tlm::TLM_OK_RESPONSE);
sendToFrontend(*backpressure, END_REQ, SC_ZERO_TIME);
scheduler->schedule(backpressure);
scheduleNextFromScheduler(DramExtension::getExtension(backpressure).getBank());
backpressure = NULL;
}
payloadLeavesSystem(payload);
payload.release();
}
else
{
SC_REPORT_FATAL(0, "Frontend PEQ event queue in controller wrapper was triggered with unknown phase");
}
}
template<unsigned int BUSWIDTH>
void Controller<BUSWIDTH>::payloadEntersSystem(tlm_generic_payload &payload)
{
Bank bank = DramExtension::getExtension(payload).getBank();
printDebugMessage(
"Payload enters system on bank " + to_string(bank.ID()) + ". Total number of payloads in Controller: "
+ to_string(getTotalNumberOfPayloadsInSystem()));
numberOfPayloadsInSystem[bank]++;
// Set Start Time for Simulation
if (startTimeSet == false){
printDebugMessage("Simulation Timer Start");
startTime = sc_time_stamp()-Configuration::getInstance().memSpec.clk;
startTimeSet = true;
}
}
template<unsigned int BUSWIDTH>
void Controller<BUSWIDTH>::payloadLeavesSystem(tlm_generic_payload &payload)
{
Bank bank = DramExtension::getExtension(payload).getBank();
numberOfPayloadsInSystem[bank]--;
printDebugMessage(
"Payload left system on bank " + to_string(bank.ID()) + ". Total number of payloads in Controller: "
+ to_string(getTotalNumberOfPayloadsInSystem()));
controllerCore->powerDownManager->triggerSleep(bank, sc_time_stamp());
}
template<unsigned int BUSWIDTH>
unsigned int Controller<BUSWIDTH>::getTotalNumberOfPayloadsInSystem()
{
unsigned int sum = 0;
for (Bank bank : controllerCore->getBanks())
{
sum += numberOfPayloadsInSystem[bank];
}
return sum;
}
template<unsigned int BUSWIDTH>
void Controller<BUSWIDTH>::scheduleNextFromScheduler(Bank bank)
{
if(controllerCore->bankIsBusy(bank))
{
return;
}
pair<Command, tlm::tlm_generic_payload*> nextRequest = scheduler->getNextRequest(bank);
if(nextRequest.second != NULL)
{
controllerCore->powerDownManager->wakeUp(DramExtension::getExtension(nextRequest.second).getBank(), sc_time_stamp());
controllerCore->scheduleRequest(nextRequest.first, *nextRequest.second);
printDebugMessage("\t-> Next payload was scheduled by core [" + commandToString(nextRequest.first) + "]");
}
while (!blockedRequests.empty()) {
bank = blockedRequests.front();
blockedRequests.pop();
pair<Command, tlm::tlm_generic_payload*> nextRequest = scheduler->getNextRequest(bank);
if (nextRequest.second != NULL) {
controllerCore->powerDownManager->wakeUp(DramExtension::getExtension(nextRequest.second).getBank(), sc_time_stamp());
controllerCore->scheduleRequest(nextRequest.first, *nextRequest.second);
printDebugMessage("\t-> Next payload was scheduled by core [" + commandToString(nextRequest.first) + "] (unblocked)");
}
}
}
template<unsigned int BUSWIDTH>
void Controller<BUSWIDTH>::sendToFrontend(tlm_generic_payload &payload, const tlm_phase &phase, const sc_time &delay)
{
tlm_phase TPhase = phase;
sc_time TDelay = delay;
tSocket->nb_transport_bw(payload, TPhase, TDelay);
}
template<unsigned int BUSWIDTH>
tlm_sync_enum Controller<BUSWIDTH>::nb_transport_bw(tlm_generic_payload &payload, tlm_phase &phase, sc_time &bwDelay)
{
sc_time recTime = bwDelay + sc_time_stamp();
sc_time notDelay = bwDelay;
printDebugMessage("[bw] Recording " + phaseNameToString(phase) + " at " + recTime.to_string() + " notification in " + notDelay.to_string());
dramPEQ.notify(payload, phase, notDelay);
tlmRecorder->recordPhase(payload, phase, recTime);
return TLM_ACCEPTED;
}
template<unsigned int BUSWIDTH>
void Controller<BUSWIDTH>::dramPEQCallback(tlm_generic_payload &payload, const tlm_phase &phase)
{
Bank bank = DramExtension::getExtension(payload).getBank();
printDebugMessage("Received " + phaseNameToString(phase) + " on bank " + to_string(bank.ID()) + " from DRAM");
if (phase == END_RD || phase == END_WR)
{
sendToFrontend(payload, BEGIN_RESP, SC_ZERO_TIME);
}
else if (phase == END_RDA || phase == END_WRA)
{
sendToFrontend(payload, BEGIN_RESP, SC_ZERO_TIME);
scheduleNextFromScheduler(bank);
}
else if (phase == END_REFA)
{
printDebugMessage("Finished auto refresh on all banks ");
bool sleepy = true;
for(Bank bank : controllerCore->getBanks())
{
if(numberOfPayloadsInSystem[bank] != 0)
{
sleepy = false;
scheduleNextFromScheduler(bank);
}
}
if(sleepy == true)
{
controllerCore->powerDownManager->sleep(0,sc_time_stamp());
}
}
else if(phase == END_REFB)
{
printDebugMessage("Finished auto refresh on bank " + to_string(bank.ID()));
if(numberOfPayloadsInSystem[bank] == 0)
{
controllerCore->powerDownManager->sleep(bank,sc_time_stamp());
}
else
{
scheduleNextFromScheduler(bank);
}
scheduleNextFromScheduler(bank);
}
else if (containsPhase(phase, { END_PRE, END_ACT }))
{
scheduleNextFromScheduler(bank);
}
else if(phase == END_PRE_ALL)
{
// No need to trigger anything for a END_PRE_ALL. It is followed by a AUTO_REFRESH anyway (in our current
// scheduler implementation)
}
else
{
string str = string("dramPEQCallback queue in controller wrapper was triggered with unsupported phase ")
+ phaseNameToString(phase);
SC_REPORT_FATAL(0, str.c_str());
}
}
template<unsigned int BUSWIDTH>
void Controller<BUSWIDTH>::sendToDram(tlm_generic_payload &payload, const tlm_phase &phase, const sc_time &delay)
{
tlm_phase TPhase = phase;
sc_time TDelay = delay;
iSocket->nb_transport_fw(payload, TPhase, TDelay);
}
template<unsigned int BUSWIDTH>
void Controller<BUSWIDTH>::printDebugMessage(string message)
{
debugManager.printDebugMessage(name(), message);
}
template<unsigned int BUSWIDTH>
bool Controller<BUSWIDTH>::containsPhase(tlm_phase phase, std::vector<tlm_phase> phases)
{
for (tlm_phase p : phases)
{
if (p == phase)
return true;
}
return false;
}
template<unsigned int BUSWIDTH>
void Controller<BUSWIDTH>::terminateSimulation()
{
for (Bank bank : controllerCore->getBanks())
{
controllerCore->powerDownManager->wakeUp(bank, clkAlign(sc_time_stamp()));
}
}
template<unsigned int BUSWIDTH>
void Controller<BUSWIDTH>::startBandwidthIdleCollector(){
printDebugMessage("IDLE Start");
idleStart = sc_time_stamp();
endTime = sc_time_stamp();
idleState = true;
}
template<unsigned int BUSWIDTH>
void Controller<BUSWIDTH>::endBandwidthIdleCollector(){
printDebugMessage("IDLE End");
idleTime += sc_time_stamp()-idleStart+ Configuration::getInstance().memSpec.clk;
idleState = false;
}
template<unsigned int BUSWIDTH>
sc_time Controller<BUSWIDTH>::getIdleTime(){
printDebugMessage("IDLE Time: "+idleTime.to_string());
return idleTime;
}
template<unsigned int BUSWIDTH>
sc_time Controller<BUSWIDTH>::getEndTime(){
printDebugMessage("End Time: "+endTime.to_string());
return endTime;
}
template<unsigned int BUSWIDTH>
sc_time Controller<BUSWIDTH>::getStartTime(){
printDebugMessage("Start Time: "+startTime.to_string());
return startTime;
}
#endif /* CONTROLLERWRAPPER_H_ */

View File

@@ -88,7 +88,7 @@ struct Dram : sc_module
map< unsigned long int, std::array<unsigned char, BUSWIDTH/2> > memory;
TlmRecorder *tlmRecorder;
Controller<>* dramController;
Controller *dramController;
SC_CTOR(Dram) : tSocket("socket")
{
@@ -583,7 +583,7 @@ struct Dram : sc_module
{
tlmRecorder = rec;
}
void setDramController(Controller<> *contr)
void setDramController(Controller *contr)
{
dramController = contr;
}

View File

@@ -148,7 +148,7 @@ void Simulation::instantiateModules(const string &traceName, const string &pathT
for (size_t i = 0; i < Configuration::getInstance().NumberOfMemChannels; i++) {
std::string str = "controller" + std::to_string(i);
Controller<> *controller = new Controller<>(str.c_str(), tlmRecorders[i]);
Controller *controller = new Controller(str.c_str(), tlmRecorders[i]);
controllers.push_back(controller);
str = "dram" + std::to_string(i);

View File

@@ -100,7 +100,7 @@ private:
// All transactions pass through the same arbiter
Arbiter *arbiter;
// Each DRAM unit has a controller
std::vector<Controller<> *> controllers;
std::vector<Controller *> controllers;
// TODO: Each DRAM has a reorder buffer (check this!)
ReorderBuffer *reorder;
// DRAM units