Issue#12 - removal of BUSWIDTH from some modules
Controller.cpp is back, but now it is not empty anymore.
This commit is contained in:
@@ -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 \
|
||||
|
||||
526
DRAMSys/simulator/src/controller/Controller.cpp
Normal file
526
DRAMSys/simulator/src/controller/Controller.cpp
Normal 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;
|
||||
}
|
||||
@@ -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_ */
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user