Merge remote-tracking branch 'origin/master' into simple_initiator

This commit is contained in:
Éder F. Zulian
2016-07-06 10:16:30 +02:00
18 changed files with 758 additions and 714 deletions

View File

@@ -109,11 +109,36 @@ class DramConfig(object):
self.tXSRDLL = self.clk * memspec.getIntValue("XSDLL")
self.tAL = self.clk * memspec.getIntValue("AL")
self.tRFC = self.clk * memspec.getIntValue("RFC")
elif (self. memoryType == "DDR3"):
self.nActivateWindow = 4
self.tRP = self.clk * memspec.getIntValue("RP");
self.tRAS = self.clk * memspec.getIntValue("RAS");
self.tRC = self.clk * memspec.getIntValue("RC");
self.tRTP = self.clk * memspec.getIntValue("RTP");
self.tRRD_S = self.clk * memspec.getIntValue("RRD");
self.tRRD_L = self.clk * memspec.getIntValue("RRD");
self.tCCD_S = self.clk * memspec.getIntValue("CCD");
self.tCCD_L = self.clk * memspec.getIntValue("CCD");
self.tRCD = self.clk * memspec.getIntValue("RCD");
self.tNAW = self.clk * memspec.getIntValue("FAW");
self.tRL = self.clk * memspec.getIntValue("RL");
self.tWL = self.clk * memspec.getIntValue("WL");
self.tWR = self.clk * memspec.getIntValue("WR");
self.tWTR_S = self.clk * memspec.getIntValue("WTR");
self.tWTR_L = self.clk * memspec.getIntValue("WTR");
self.tCKESR = self.clk * memspec.getIntValue("CKESR");
self.tCKE = self.clk * memspec.getIntValue("CKE");
self.tXP = self.clk * memspec.getIntValue("XP");
self.tXPDLL = self.clk * memspec.getIntValue("XPDLL");
self.tXSR = self.clk * memspec.getIntValue("XS");
self.tXSRDLL = self.clk * memspec.getIntValue("XSDLL");
self.tAL = self.clk * memspec.getIntValue("AL");
self.tRFC = self.clk * memspec.getIntValue("RFC");
else:
raise Exception("MemoryType not supported yet. Insert a coin into the coin machine and try again")
# TODO ADD DDR3
def clkAlign(self, value):
return math.ceil(1.0*value/self.clk)*self.clk

View File

@@ -0,0 +1 @@
../../../src/common/third_party/DRAMPower/memspecs/SAMSUNG_K4B1G1646E_1Gb_DDR3-1600_16bit.xml

View File

@@ -99,12 +99,14 @@ SOURCES += \
src/controller/core/configuration/ConfigurationLoader.cpp \
src/controller/core/powerdown/NoPowerDown.cpp \
src/controller/Command.cpp \
src/controller/Controller.cpp \
src/controller/ControllerState.cpp \
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 \
src/simulation/TracePlayer.cpp \
src/simulation/StlPlayer.cpp
HEADERS += \
src/common/third_party/tinyxml2/tinyxml2.h \

View File

@@ -30,11 +30,497 @@
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* Authors:
* Janik Schlemminger
* 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()
@@ -102,8 +101,8 @@ public:
virtual void send(const ScheduledCommand& command, tlm_generic_payload& payload) override;
virtual void send(Trigger trigger, sc_time time, tlm_generic_payload& payload) override;
tlm_utils::simple_initiator_socket<Controller, BUSWIDTH, tlm::tlm_base_protocol_types> iSocket;
tlm_utils::simple_target_socket<Controller, BUSWIDTH, tlm::tlm_base_protocol_types> tSocket;
tlm_utils::simple_initiator_socket<Controller> iSocket;
tlm_utils::simple_target_socket<Controller> tSocket;
unsigned int getTotalNumberOfPayloadsInSystem();
private:
@@ -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

@@ -78,29 +78,31 @@ ControllerCore::ControllerCore(sc_module_name /*name*/, IController& wrapperConn
if (config.BankwiseLogic)
{
refreshManager = new RefreshManagerBankwise("refManagerBw", *this);
powerDownManager = new PowerDownManagerBankwise("pdnManagerBw", *this);
refreshManager = new RefreshManagerBankwise("refManagerBw", *this);
}
else
{
refreshManager = new RefreshManager("refManager", *this);
refreshManager = new RefreshManager("refManager", *this);
}
if(config.PowerDownMode == EPowerDownMode::Staggered)
{
powerDownManager = new PowerDownManager("pdnManager", *this);
}
else if(config.PowerDownMode == EPowerDownMode::TimeoutPDN || config.PowerDownMode == EPowerDownMode::TimeoutSREF)
{
powerDownManager = new PowerDownManagerTimeout("pdnManagerTout", *this);
}
else if(config.PowerDownMode == EPowerDownMode::NoPowerDown)
{
powerDownManager = new NoPowerDown();
}
if(config.PowerDownMode == EPowerDownMode::Staggered)
{
if (config.BankwiseLogic)
powerDownManager = new PowerDownManagerBankwise("pdnManagerBw", *this);
else
{
SC_REPORT_FATAL(0, "Unsupported powerdown mode in constructor of controller core");
}
powerDownManager = new PowerDownManager("pdnManager", *this);
}
else if(config.PowerDownMode == EPowerDownMode::TimeoutPDN || config.PowerDownMode == EPowerDownMode::TimeoutSREF)
{
powerDownManager = new PowerDownManagerTimeout("pdnManagerTout", *this);
}
else if(config.PowerDownMode == EPowerDownMode::NoPowerDown)
{
powerDownManager = new NoPowerDown();
}
else
{
SC_REPORT_FATAL(0, "Unsupported powerdown mode in constructor of controller core");
}
}

View File

@@ -57,17 +57,16 @@ void RefreshChecker::delayToSatisfyConstraints(ScheduledCommand& command) const
}
else if (lastCommandOnBank.getCommand() == Command::WriteA)
{
command.establishMinDistanceFromStart(lastCommandOnBank.getStart(),
config.memSpec.tWL + getWriteAccessTime() + config.memSpec.tWR + config.memSpec.tRP);
command.establishMinDistanceFromStart(lastCommandOnBank.getStart(), config.memSpec.tWL + getWriteAccessTime() + config.memSpec.tWR + config.memSpec.tRP);
}
else if (lastCommandOnBank.getCommand() == Command::PDNPX || lastCommandOnBank.getCommand() == Command::PDNAX)
{
command.establishMinDistanceFromStart(lastCommandOnBank.getStart(), config.memSpec.tXP);
}
else if (lastCommandOnBank.getCommand() == Command::SREFX)
{
command.establishMinDistanceFromStart(lastCommandOnBank.getStart(), config.memSpec.tXSR);
}
{
command.establishMinDistanceFromStart(lastCommandOnBank.getStart(), config.memSpec.tXSR);
}
else if (lastCommandOnBank.getCommand() == Command::AutoRefresh)
{
}

View File

@@ -54,11 +54,10 @@
using namespace std;
using namespace tlm;
template<unsigned int BUSWIDTH = 128>
struct Arbiter: public sc_module {
public:
tlm_utils::multi_passthrough_initiator_socket<Arbiter, BUSWIDTH> iSocket;
tlm_utils::multi_passthrough_target_socket<Arbiter, BUSWIDTH> tSocket;
tlm_utils::multi_passthrough_initiator_socket<Arbiter> iSocket;
tlm_utils::multi_passthrough_target_socket<Arbiter> tSocket;
SC_CTOR(Arbiter) : payloadEventQueue(this, &Arbiter::peqCallback) {
// The arbiter communicates with one or more memory unity through one or more sockets (one or more memory channels).

View File

@@ -61,11 +61,13 @@ using namespace std;
using namespace tlm;
using namespace Data;
template<unsigned int BUSWIDTH = 128>
struct Dram : sc_module
{
// FIXME: remove this define and use the value from config
const static unsigned int BUSWIDTH = 128;
// TLM Related:
tlm_utils::simple_target_socket<Dram, BUSWIDTH, tlm::tlm_base_protocol_types> tSocket;
tlm_utils::simple_target_socket<Dram> tSocket;
// Power Model related
bool powerAnalysis = Configuration::getInstance().PowerAnalysis;
@@ -86,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")
{
@@ -582,7 +584,7 @@ struct Dram : sc_module
{
tlmRecorder = rec;
}
void setDramController(Controller<> *contr)
void setDramController(Controller *contr)
{
dramController = contr;
}

View File

@@ -45,12 +45,11 @@
using namespace std;
using namespace tlm;
template<unsigned int BUSWIDTH = 128>
struct ReorderBuffer: public sc_module
{
public:
tlm_utils::simple_initiator_socket<ReorderBuffer,BUSWIDTH, tlm::tlm_base_protocol_types> iSocket;
tlm_utils::simple_target_socket<ReorderBuffer, BUSWIDTH, tlm::tlm_base_protocol_types> tSocket;
tlm_utils::simple_initiator_socket<ReorderBuffer> iSocket;
tlm_utils::simple_target_socket<ReorderBuffer> tSocket;
SC_CTOR(ReorderBuffer) :
payloadEventQueue(this, &ReorderBuffer::peqCallback), responseIsPendingInInitator(false)

View File

@@ -117,20 +117,20 @@ void Simulation::instantiateModules(const string &traceName, const string &pathT
#if 0
for (size_t i = 0; i < Configuration::getInstance().NumberOfTracePlayers; i++) {
std::string playerStr = "tracePlayer" + std::to_string(i);
TracePlayer<> *player;
TracePlayer *player;
// When data should be stored during the simulation the StlDataPlayer is needed.
// Else: no data should be stored, for instance to get a faster simulation
// or if you simply dont care about the data the normal StlPlayer is used.
if(Configuration::getInstance().ErrorStoreMode == ErrorStorageMode::NoStorage)
{
StlPlayer<> *newPlayer = new StlPlayer<>(playerStr.c_str(), pathToResources + string("traces/") + devices[i].trace, devices[i].clkMhz, this);
StlPlayer *newPlayer = new StlPlayer(playerStr.c_str(), pathToResources + string("traces/") + devices[i].trace, devices[i].clkMhz, this);
player = newPlayer;
newPlayer->getTraceLength(pathToResources + string("traces/") + devices[i].trace);
totalTransactions += newPlayer->getNumberOfLines(pathToResources + string("traces/") + devices[i].trace);
}
else
{
StlDataPlayer<> *newPlayer = new StlDataPlayer<>(playerStr.c_str(), pathToResources + string("traces/") + devices[i].trace, devices[i].clkMhz, this);
StlDataPlayer *newPlayer = new StlDataPlayer(playerStr.c_str(), pathToResources + string("traces/") + devices[i].trace, devices[i].clkMhz, this);
player = newPlayer;
newPlayer->getTraceLength(pathToResources + string("traces/") + devices[i].trace);
totalTransactions += newPlayer->getNumberOfLines(pathToResources + string("traces/") + devices[i].trace);
@@ -145,18 +145,18 @@ void Simulation::instantiateModules(const string &traceName, const string &pathT
// Create and properly initialize TLM recorders. They need to be ready before creating some modules.
setupTlmRecorders(traceName, pathToResources, devices);
arbiter = new Arbiter<128>("arbiter");
arbiter = new Arbiter("arbiter");
arbiter->setTlmRecorders(tlmRecorders);
init = new ExampleInitiator<>("init");
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);
Dram<> *dram = new Dram<>(str.c_str());
Dram *dram = new Dram(str.c_str());
dram->setTlmRecorder(tlmRecorders[i]);
dram->setDramController(controllers[i]);
drams.push_back(dram);

View File

@@ -97,16 +97,16 @@ private:
// A vector of pointers to all trace player (devices which acquire the bus
// and initiate transactions targeting the memory)
std::vector<TracePlayer<>*> players;
std::vector<TracePlayer*> players;
// All transactions pass through the same arbiter
ExampleInitiator<> *init;
Arbiter<> *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;
ReorderBuffer *reorder;
// DRAM units
std::vector<Dram<>*> drams;
std::vector<Dram*> drams;
// Transaction Recorders (one per channel). They generate the output databases.
std::vector<TlmRecorder*> tlmRecorders;
@@ -118,7 +118,7 @@ private:
void setupTlmRecorders(const string &traceName, const string &pathToResources, const std::vector<Device> &devices);
void instantiateModules(const string &traceName, const string &pathToResources, const std::vector<Device> &devices);
void bindSockets();
void setupDebugManager(const string& traceName);
void setupDebugManager(const string &traceName);
};
#endif /* SIMULATIONMANAGER_H_ */

View File

@@ -45,8 +45,7 @@
using namespace std;
using namespace tlm;
template<unsigned int BUSWIDTH = 128>
struct StlDataPlayer: public TracePlayer<BUSWIDTH>
struct StlDataPlayer: public TracePlayer
{
public:
StlDataPlayer(sc_module_name /*name*/, string pathToTrace, unsigned int clkMhz, TracePlayerListener* listener);
@@ -199,10 +198,9 @@ private:
};
template<unsigned int BUSWIDTH>
StlDataPlayer<BUSWIDTH>::StlDataPlayer(sc_module_name /*name*/, string pathToTrace, unsigned int clkMhz,
StlDataPlayer::StlDataPlayer(sc_module_name /*name*/, string pathToTrace, unsigned int clkMhz,
TracePlayerListener* listener) :
TracePlayer<BUSWIDTH>(listener),file(pathToTrace)
TracePlayer(listener),file(pathToTrace)
{
if (!file.is_open())
SC_REPORT_FATAL(0, (string("Could not open trace ") + pathToTrace).c_str());

View File

@@ -0,0 +1,55 @@
/*
* 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:
* Janik Schlemminger
* Robert Gernhardt
* Matthias Jung
*/
#include "StlPlayer.h"
StlPlayer::StlPlayer(sc_module_name /*name*/, string pathToTrace, unsigned int clkMhz,
TracePlayerListener* listener) :
TracePlayer(listener),file(pathToTrace)
{
if (!file.is_open())
SC_REPORT_FATAL(0, (string("Could not open trace ") + pathToTrace).c_str());
if(clkMhz == 0)
clk = Configuration::getInstance().memSpec.clk;
else
clk = FrequencyToClk(clkMhz);
this->burstlength = Configuration::getInstance().memSpec.BurstLength;
this->bytesPerColumn = xmlAddressDecoder::getInstance().amount["bytes"];
}

View File

@@ -45,8 +45,7 @@
using namespace std;
using namespace tlm;
template<unsigned int BUSWIDTH = 128>
struct StlPlayer: public TracePlayer<BUSWIDTH>
struct StlPlayer: public TracePlayer
{
public:
StlPlayer(sc_module_name /*name*/, string pathToTrace, unsigned int clkMhz, TracePlayerListener *listener);
@@ -185,23 +184,4 @@ private:
sc_time clk;
};
template<unsigned int BUSWIDTH>
StlPlayer<BUSWIDTH>::StlPlayer(sc_module_name /*name*/, string pathToTrace, unsigned int clkMhz,
TracePlayerListener* listener) :
TracePlayer<BUSWIDTH>(listener),file(pathToTrace)
{
if (!file.is_open())
SC_REPORT_FATAL(0, (string("Could not open trace ") + pathToTrace).c_str());
if(clkMhz == 0)
clk = Configuration::getInstance().memSpec.clk;
else
clk = FrequencyToClk(clkMhz);
this->burstlength = Configuration::getInstance().memSpec.BurstLength;
this->bytesPerColumn = xmlAddressDecoder::getInstance().amount["bytes"];
}
#endif // STLPLAYER_H

View File

@@ -44,12 +44,19 @@
using namespace std;
using namespace tlm;
template<unsigned int BUSWIDTH = 128>
struct TraceGenerator: public TracePlayer<BUSWIDTH>
struct TraceGenerator: public TracePlayer
{
public:
TraceGenerator(sc_module_name /*name*/, unsigned int clkMhz,
TracePlayerListener* listener);
TracePlayerListener* listener) : TracePlayer(listener), transCounter(0)
{
if(clkMhz == 0)
clk = Configuration::getInstance().memSpec.clk;
else
clk = FrequencyToClk(clkMhz);
this->burstlenght = Configuration::getInstance().memSpec.BurstLength;
}
virtual void nextPayload() override
{
@@ -67,32 +74,18 @@ public:
payload->set_dmi_allowed(false);
payload->set_byte_enable_length(0);
payload->set_streaming_width(this->burstlenght);
this->setDataPointer(payload, dataElement);
this->setDataPointer(payload, dataElement, 16);
payload->set_command(TLM_READ_COMMAND);
transCounter++;
this->payloadEventQueue.notify(*payload, BEGIN_REQ, SC_ZERO_TIME);
}
private:
unsigned int burstlenght;
sc_time clk;
unsigned int transCounter;
};
template<unsigned int BUSWIDTH>
TraceGenerator<BUSWIDTH>::TraceGenerator(sc_module_name /*name*/, unsigned int clkMhz,
TracePlayerListener* listener) :
TracePlayer<BUSWIDTH>(listener), transCounter(0)
{
if(clkMhz == 0)
clk = Configuration::getInstance().memSpec.clk;
else
clk = FrequencyToClk(clkMhz);
this->burstlenght = Configuration::getInstance().memSpec.BurstLength;
}
#endif

View File

@@ -0,0 +1,108 @@
/*
* 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 "TracePlayer.h"
TracePlayer::TracePlayer(TracePlayerListener* listener) :
payloadEventQueue(this, &TracePlayer::peqCallback), transactionsSent(0), listener(listener)
{
iSocket.register_nb_transport_bw(this, &TracePlayer::nb_transport_bw);
}
gp *TracePlayer::allocatePayload()
{
return memoryManager.allocate();
}
void TracePlayer::terminate()
{
cout << sc_time_stamp() << " " << this->name() << " terminated " << std::endl;
listener->tracePlayerTerminates();
}
void TracePlayer::printDebugMessage(std::string message)
{
DebugManager::getInstance().printDebugMessage(this->name(), message);
}
//TODO: this doesn't depend on the tracePlayer, move it somewhere
void TracePlayer::setDataPointer(gp* payload, unsigned char * dataElement, unsigned int size)
{
//check if payload takes ownership
payload->set_data_length(size);
payload->set_data_ptr(dataElement);
for(unsigned i = 0; i < size; i++)
dataElement[i] = 0;
}
tlm_sync_enum TracePlayer::nb_transport_bw(tlm_generic_payload &payload, tlm_phase &phase, sc_time &bwDelay)
{
payloadEventQueue.notify(payload, phase, bwDelay);
return TLM_ACCEPTED;
}
void TracePlayer::peqCallback(tlm_generic_payload &payload, const tlm_phase &phase)
{
if (phase == BEGIN_REQ)
{
payload.acquire();
GenerationExtension* genExtension = new GenerationExtension(sc_time_stamp());
payload.set_auto_extension(genExtension);
sendToTarget(payload, phase, SC_ZERO_TIME);
transactionsSent++;
DebugManager::getInstance().printDebugMessage(name(), "Performing request #" + std::to_string(transactionsSent));
}
else if (phase == END_REQ)
{
nextPayload();
}
else if (phase == BEGIN_RESP)
{
sendToTarget(payload, END_RESP, SC_ZERO_TIME);
payload.release();
if(Configuration::getInstance().SimulationProgressBar)
listener->transactionFinished();
}
else if (phase == END_RESP)
{
}
else
{
SC_REPORT_FATAL(0, "TracePlayer PEQ was triggered with unknown phase");
}
}

View File

@@ -55,12 +55,11 @@
using namespace std;
using namespace tlm;
template<unsigned int BUSWIDTH = 128>
struct TracePlayer: public sc_module
{
public:
tlm_utils::simple_initiator_socket<TracePlayer, BUSWIDTH, tlm::tlm_base_protocol_types> iSocket;
TracePlayer(TracePlayerListener* listener);
tlm_utils::simple_initiator_socket<TracePlayer> iSocket;
TracePlayer(TracePlayerListener *listener);
virtual void nextPayload() = 0;
protected:
@@ -73,112 +72,15 @@ protected:
private:
tlm_sync_enum nb_transport_bw(tlm_generic_payload& payload, tlm_phase& phase, sc_time& bwDelay);
void peqCallback(tlm_generic_payload& payload, const tlm_phase& phase);
void sendToTarget(tlm_generic_payload& payload, const tlm_phase& phase, const sc_time& delay);
void sendToTarget(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);
}
MemoryManager memoryManager;
unsigned int transactionsSent;
TracePlayerListener* listener;
};
template<unsigned int BUSWIDTH>
TracePlayer<BUSWIDTH>::TracePlayer(TracePlayerListener* listener) :
payloadEventQueue(this, &TracePlayer<BUSWIDTH>::peqCallback), transactionsSent(0), listener(listener)
{
iSocket.register_nb_transport_bw(this, &TracePlayer<BUSWIDTH>::nb_transport_bw);
}
template<unsigned int BUSWIDTH>
gp *TracePlayer<BUSWIDTH>::allocatePayload()
{
return memoryManager.allocate();
}
template<unsigned int BUSWIDTH>
void TracePlayer<BUSWIDTH>::terminate()
{
cout << sc_time_stamp() << " " << this->name() << " terminated " << std::endl;
listener->tracePlayerTerminates();
}
template<unsigned int BUSWIDTH>
void TracePlayer<BUSWIDTH>::printDebugMessage(std::string message)
{
DebugManager::getInstance().printDebugMessage(this->name(), message);
}
template<unsigned int BUSWIDTH>
//TODO: this doesn't depend on the tracePlayer, move it somewhere
void TracePlayer<BUSWIDTH>::setDataPointer(gp* payload, unsigned char * dataElement, unsigned int size)
{
//check if payload takes ownership
payload->set_data_length(size);
payload->set_data_ptr(dataElement);
for(unsigned i = 0; i < size; i++)
dataElement[i] = 0;
}
template<unsigned int BUSWIDTH>
tlm_sync_enum TracePlayer<BUSWIDTH>::nb_transport_bw(tlm_generic_payload &payload, tlm_phase &phase, sc_time &bwDelay)
{
payloadEventQueue.notify(payload, phase, bwDelay);
return TLM_ACCEPTED;
}
template<unsigned int BUSWIDTH>
void TracePlayer<BUSWIDTH>::peqCallback(tlm_generic_payload &payload, const tlm_phase &phase)
{
if (phase == BEGIN_REQ)
{
payload.acquire();
GenerationExtension* genExtension = new GenerationExtension(sc_time_stamp());
payload.set_auto_extension(genExtension);
sendToTarget(payload, phase, SC_ZERO_TIME);
transactionsSent++;
DebugManager::getInstance().printDebugMessage(name(), "Performing request #" + std::to_string(transactionsSent));
}
else if (phase == END_REQ)
{
nextPayload();
}
else if (phase == BEGIN_RESP)
{
//TODO: cleanup:
// unsigned char * dataElement = payload.get_data_ptr();
//
// if(payload.get_command() == TLM_READ_COMMAND)
// {
// cout << "0x";
// for(int i=0; i < 16*2; i++)
// {
// cout << hex << int(dataElement[i]);
// }
// cout << endl;
// }
sendToTarget(payload, END_RESP, SC_ZERO_TIME);
payload.release();
if(Configuration::getInstance().SimulationProgressBar)
listener->transactionFinished();
}
else if (phase == END_RESP)
{
}
else
{
SC_REPORT_FATAL(0, "TracePlayer PEQ was triggered with unknown phase");
}
}
template<unsigned int BUSWIDTH>
void TracePlayer<BUSWIDTH>::sendToTarget(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);
}
#endif /* TRACEPLAYER_H_ */