minor refactoring
This commit is contained in:
@@ -22,6 +22,13 @@ void DebugManager::printDebugMessage(string sender, string message)
|
||||
#endif
|
||||
}
|
||||
|
||||
void DebugManager::openDebugFile(string filename)
|
||||
{
|
||||
if(debugFile)
|
||||
debugFile.close();
|
||||
debugFile.open(filename);
|
||||
}
|
||||
|
||||
void DebugManager::addToWhiteList(string sender)
|
||||
{
|
||||
whiteList.insert(sender);
|
||||
|
||||
@@ -26,12 +26,7 @@ public:
|
||||
bool writeToFile;
|
||||
|
||||
void printDebugMessage(std::string sender, std::string message);
|
||||
void openDebugFile(std::string filename)
|
||||
{
|
||||
if(debugFile)
|
||||
debugFile.close();
|
||||
debugFile.open(filename);
|
||||
}
|
||||
void openDebugFile(std::string filename);
|
||||
|
||||
void addToWhiteList(std::string sender);
|
||||
void addToWhiteList(std::vector<std::string> senders);
|
||||
|
||||
@@ -30,7 +30,6 @@ struct TimeInterval
|
||||
bool intersects(TimeInterval other);
|
||||
};
|
||||
|
||||
|
||||
template<typename Key, typename Val>
|
||||
inline Val getElementFromMap(const std::map<Key, Val>& m, Key key)
|
||||
{
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
#ifndef EXTENDED_PHASE_DRAM
|
||||
#define EXTENDED_PHASE_DRAM
|
||||
// DRAM Control Phases
|
||||
|
||||
// DRAM Control Phases
|
||||
DECLARE_EXTENDED_PHASE(BEGIN_PRE);
|
||||
DECLARE_EXTENDED_PHASE(END_PRE);
|
||||
|
||||
@@ -16,7 +16,6 @@ DECLARE_EXTENDED_PHASE(END_AUTO_REFRESH);
|
||||
|
||||
|
||||
// Phases for Read and Write
|
||||
|
||||
DECLARE_EXTENDED_PHASE(BEGIN_WR);
|
||||
DECLARE_EXTENDED_PHASE(END_WR);
|
||||
|
||||
@@ -30,7 +29,6 @@ DECLARE_EXTENDED_PHASE(BEGIN_RDA);
|
||||
DECLARE_EXTENDED_PHASE(END_RDA);
|
||||
|
||||
// Phases for Power Down
|
||||
|
||||
DECLARE_EXTENDED_PHASE(BEGIN_PDNP);
|
||||
DECLARE_EXTENDED_PHASE(END_PDNP);
|
||||
|
||||
|
||||
@@ -3,97 +3,95 @@
|
||||
|
||||
#include <systemc.h>
|
||||
#include <tlm.h>
|
||||
#include "third_party/tinyxml.h"
|
||||
|
||||
|
||||
using namespace std;
|
||||
|
||||
class xmlConfig
|
||||
{
|
||||
public:
|
||||
public:
|
||||
|
||||
sc_time clk;
|
||||
sc_time tRRD;
|
||||
sc_time tRC;
|
||||
sc_time tRCD;
|
||||
sc_time tBL;
|
||||
sc_time tRL;
|
||||
sc_time tWL;
|
||||
sc_time tWTR;
|
||||
sc_time tRP;
|
||||
sc_time tRAS;
|
||||
sc_time tWR;
|
||||
sc_time tREF;
|
||||
sc_time tRFC;
|
||||
sc_time tXP;
|
||||
sc_time tCKE;
|
||||
sc_time tXSR;
|
||||
sc_time tCKESR;
|
||||
sc_time tREFA;
|
||||
sc_time tREFB;
|
||||
sc_time tPDNTO;
|
||||
sc_time clk;
|
||||
sc_time tRRD;
|
||||
sc_time tRC;
|
||||
sc_time tRCD;
|
||||
sc_time tBL;
|
||||
sc_time tRL;
|
||||
sc_time tWL;
|
||||
sc_time tWTR;
|
||||
sc_time tRP;
|
||||
sc_time tRAS;
|
||||
sc_time tWR;
|
||||
sc_time tREF;
|
||||
sc_time tRFC;
|
||||
sc_time tXP;
|
||||
sc_time tCKE;
|
||||
sc_time tXSR;
|
||||
sc_time tCKESR;
|
||||
sc_time tREFA;
|
||||
sc_time tREFB;
|
||||
sc_time tPDNTO;
|
||||
|
||||
double IDD0;
|
||||
double IDD2N;
|
||||
double IDD3N;
|
||||
double IDD4R;
|
||||
double IDD4W;
|
||||
double IDD5;
|
||||
double IDD6;
|
||||
double IDD5B1;
|
||||
double IDD2P;
|
||||
double IDD3P;
|
||||
double VDD;
|
||||
double IDD0;
|
||||
double IDD2N;
|
||||
double IDD3N;
|
||||
double IDD4R;
|
||||
double IDD4W;
|
||||
double IDD5;
|
||||
double IDD6;
|
||||
double IDD5B1;
|
||||
double IDD2P;
|
||||
double IDD3P;
|
||||
double VDD;
|
||||
|
||||
sc_time ccPreprocessingTime;
|
||||
sc_time ccPreprocessingTime;
|
||||
|
||||
public:
|
||||
xmlConfig()
|
||||
{
|
||||
//clk = sc_time(6.0, SC_NS); // 166MHz
|
||||
clk = sc_time(6, SC_NS); // 166MHz
|
||||
public:
|
||||
xmlConfig()
|
||||
{
|
||||
//clk = sc_time(6.0, SC_NS); // 166MHz
|
||||
clk = sc_time(6, SC_NS); // 166MHz
|
||||
|
||||
// Timings:
|
||||
// WC timings for 200MHz
|
||||
// before thermal:
|
||||
tRRD = 2 * clk; // 2 * clk; // 4 * clk;//1 * clk; //2 * clk;
|
||||
tRCD = 3 * clk; // 2 * clk; // 10 * clk;//3 * clk; //4 * clk;
|
||||
tRL = 3 * clk; // 3 * clk; // 10 * clk;//3 * clk; //3 * clk;
|
||||
tBL = 1 * clk; // 1 * clk; // 1 * clk;//1 * clk; //1 * clk;
|
||||
tWL = 1 * clk; // 1 * clk; // 9 * clk;//1 * clk; //1 * clk;
|
||||
tWTR = 3 * clk; // 3 * clk; // 4 * clk;//3 * clk; //3 * clk;
|
||||
tRP = 3 * clk; // 3 * clk; // 10 * clk;//3 * clk; //4 * clk; // sadri changed from 2 to 3 = 18ns/6ns
|
||||
tRAS = 6 * clk; // 5 * clk; // 18 * clk;//8 * clk; //9 * clk;
|
||||
tWR = 2 * clk; // 2 * clk; // 10 * clk;//2 * clk; //3 * clk;
|
||||
tRFC = 18 * clk; // 22 * clk; // 15 * clk; // 110* clk;//18 * clk; // sadri changed from 15 to 22 = 130ns/6ns
|
||||
tXP = 2 * clk;
|
||||
tCKE = 3 * clk;
|
||||
tXSR = tRFC + 2 * clk;
|
||||
tCKESR = 3 * clk;
|
||||
tPDNTO = 0 * clk;
|
||||
tRC = tRP + tRAS;
|
||||
tREF = sc_time(64, SC_MS);
|
||||
tREFA = tRP + tRFC;
|
||||
tREFB = tRP + tRC; // refresh for one bank
|
||||
// Timings:
|
||||
// WC timings for 200MHz
|
||||
// before thermal:
|
||||
tRRD = 2 * clk; // 2 * clk; // 4 * clk;//1 * clk; //2 * clk;
|
||||
tRCD = 3 * clk; // 2 * clk; // 10 * clk;//3 * clk; //4 * clk;
|
||||
tRL = 3 * clk; // 3 * clk; // 10 * clk;//3 * clk; //3 * clk;
|
||||
tBL = 1 * clk; // 1 * clk; // 1 * clk;//1 * clk; //1 * clk;
|
||||
tWL = 1 * clk; // 1 * clk; // 9 * clk;//1 * clk; //1 * clk;
|
||||
tWTR = 3 * clk; // 3 * clk; // 4 * clk;//3 * clk; //3 * clk;
|
||||
tRP = 3 * clk; // 3 * clk; // 10 * clk;//3 * clk; //4 * clk; // sadri changed from 2 to 3 = 18ns/6ns
|
||||
tRAS = 6 * clk; // 5 * clk; // 18 * clk;//8 * clk; //9 * clk;
|
||||
tWR = 2 * clk; // 2 * clk; // 10 * clk;//2 * clk; //3 * clk;
|
||||
tRFC = 18 * clk; // 22 * clk; // 15 * clk; // 110* clk;//18 * clk; // sadri changed from 15 to 22 = 130ns/6ns
|
||||
tXP = 2 * clk;
|
||||
tCKE = 3 * clk;
|
||||
tXSR = tRFC + 2 * clk;
|
||||
tCKESR = 3 * clk;
|
||||
tPDNTO = 0 * clk;
|
||||
tRC = tRP + tRAS;
|
||||
tREF = sc_time(64, SC_MS);
|
||||
tREFA = tRP + tRFC;
|
||||
tREFB = tRP + tRC; // refresh for one bank
|
||||
|
||||
// Power realted currents and voltages:
|
||||
// 166MHz thermal non minimal timings (200MHz)
|
||||
// 166MHz with minimal timing
|
||||
IDD0 = 37.85 / 1000.0; // 47.3 / 1000.0; //64 / 1000.0;
|
||||
IDD2N = 4.36 / 1000.0; // 4.36 / 1000.0; //4.4 / 1000.0;
|
||||
IDD3N = 5.60 / 1000.0; // 6.07 / 1000.0; //5.9 / 1000.0;
|
||||
IDD4R = 94.64 / 1000.0; // 94.65 / 1000.0; //94 / 1000.0;
|
||||
IDD4W = 88.65 / 1000.0; // 88.66 / 1000.0; //88 / 1000.0;
|
||||
IDD5 = 136.20 / 1000.0; // 162.56 / 1000.0; //163 / 1000.0;
|
||||
IDD5B1 = 37.32 / 1000.0; //
|
||||
IDD2P = 2.4 / 1000.0; //
|
||||
IDD3P = 3.6 / 1000.0; //
|
||||
IDD6 = 3.4 / 1000.0; //
|
||||
// Power realted currents and voltages:
|
||||
// 166MHz thermal non minimal timings (200MHz)
|
||||
// 166MHz with minimal timing
|
||||
IDD0 = 37.85 / 1000.0; // 47.3 / 1000.0; //64 / 1000.0;
|
||||
IDD2N = 4.36 / 1000.0; // 4.36 / 1000.0; //4.4 / 1000.0;
|
||||
IDD3N = 5.60 / 1000.0; // 6.07 / 1000.0; //5.9 / 1000.0;
|
||||
IDD4R = 94.64 / 1000.0; // 94.65 / 1000.0; //94 / 1000.0;
|
||||
IDD4W = 88.65 / 1000.0; // 88.66 / 1000.0; //88 / 1000.0;
|
||||
IDD5 = 136.20 / 1000.0; // 162.56 / 1000.0; //163 / 1000.0;
|
||||
IDD5B1 = 37.32 / 1000.0; //
|
||||
IDD2P = 2.4 / 1000.0; //
|
||||
IDD3P = 3.6 / 1000.0; //
|
||||
IDD6 = 3.4 / 1000.0; //
|
||||
|
||||
VDD = 1.2;
|
||||
VDD = 1.2;
|
||||
|
||||
ccPreprocessingTime = 1 * clk;
|
||||
}
|
||||
ccPreprocessingTime = 1 * clk;
|
||||
}
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
3
dram/src/controller/Controller.cpp
Normal file
3
dram/src/controller/Controller.cpp
Normal file
@@ -0,0 +1,3 @@
|
||||
#include "Controller.h"
|
||||
|
||||
|
||||
@@ -45,175 +45,57 @@ template<unsigned int BUSWIDTH = 128>
|
||||
struct Controller: public sc_module, public IWrapperConnector
|
||||
{
|
||||
public:
|
||||
|
||||
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;
|
||||
|
||||
Controller(sc_module_name /*name*/) :
|
||||
frontendPEQ(this, &Controller::frontendPEQCallback), dramPEQ(this, &Controller::dramPEQCallback), controllerCorePEQ(
|
||||
this, &Controller::controllerCorePEQCallback), debugManager(DebugManager::getInstance())
|
||||
frontendPEQ(this, &Controller<BUSWIDTH>::frontendPEQCallback), dramPEQ(this, &Controller<BUSWIDTH>::dramPEQCallback), controllerCorePEQ(
|
||||
this, &Controller<BUSWIDTH>::controllerCorePEQCallback), debugManager(DebugManager::getInstance())
|
||||
{
|
||||
controllerCore = new ControllerCore(*this, numberOfPayloadsInSystem);
|
||||
buildScheduler();
|
||||
iSocket.register_nb_transport_bw(this, &Controller::nb_transport_bw);
|
||||
tSocket.register_nb_transport_fw(this, &Controller::nb_transport_fw);
|
||||
iSocket.register_nb_transport_bw(this, &Controller<BUSWIDTH>::nb_transport_bw);
|
||||
tSocket.register_nb_transport_fw(this, &Controller<BUSWIDTH>::nb_transport_fw);
|
||||
}
|
||||
|
||||
void buildScheduler()
|
||||
{
|
||||
string selectedScheduler = Configuration::getInstance().Scheduler;
|
||||
|
||||
if (selectedScheduler == "FR_FCFS")
|
||||
{
|
||||
|
||||
scheduler = new FR_FCFS(*controllerCore, Configuration::getInstance().RefreshAwareScheduling,
|
||||
Configuration::getInstance().AdaptiveOpenPagePolicy);
|
||||
}
|
||||
else if (selectedScheduler == "PAR_BS")
|
||||
{
|
||||
scheduler = new PAR_BS(*controllerCore, Configuration::getInstance().RefreshAwareScheduling,
|
||||
Configuration::getInstance().Capsize);
|
||||
}
|
||||
else if (selectedScheduler == "FIFO")
|
||||
scheduler = new Fifo(*controllerCore);
|
||||
else
|
||||
reportFatal(name(), "unsupported scheduler: " + selectedScheduler);
|
||||
}
|
||||
|
||||
~Controller()
|
||||
{
|
||||
delete controllerCore;
|
||||
delete scheduler;
|
||||
}
|
||||
|
||||
void terminateSimulation()
|
||||
{
|
||||
for (Bank bank : controllerCore->getBanks())
|
||||
{
|
||||
controllerCore->powerDownManager->wakeUp(bank, clkAlign(sc_time_stamp()));
|
||||
}
|
||||
}
|
||||
|
||||
// ------- Interaction with controller core ---------
|
||||
virtual void send(const ScheduledCommand& command, tlm_generic_payload& payload) override
|
||||
{
|
||||
sc_assert(command.getStart() >= sc_time_stamp());
|
||||
TimeInterval dataStrobe;
|
||||
void terminateSimulation();
|
||||
// ------- CONTROLLER CORE ---------
|
||||
virtual void send(const ScheduledCommand& command, tlm_generic_payload& payload) override;
|
||||
virtual void send(Trigger trigger, sc_time time, tlm_generic_payload& payload) override;
|
||||
|
||||
switch (command.getCommand())
|
||||
{
|
||||
case Command::Read:
|
||||
dataStrobe = command.getIntervalOnDataStrobe();
|
||||
TlmRecorder::getInstance().updateDataStrobe(dataStrobe.start, dataStrobe.end, payload);
|
||||
controllerCorePEQ.notify(payload, BEGIN_RD, command.getStart() - sc_time_stamp());
|
||||
break;
|
||||
case Command::ReadA:
|
||||
dataStrobe = command.getIntervalOnDataStrobe();
|
||||
TlmRecorder::getInstance().updateDataStrobe(dataStrobe.start, dataStrobe.end, payload);
|
||||
controllerCorePEQ.notify(payload, BEGIN_RDA, command.getStart() - sc_time_stamp());
|
||||
break;
|
||||
case Command::Write:
|
||||
dataStrobe = command.getIntervalOnDataStrobe();
|
||||
TlmRecorder::getInstance().updateDataStrobe(dataStrobe.start, dataStrobe.end, payload);
|
||||
controllerCorePEQ.notify(payload, BEGIN_WR, command.getStart() - sc_time_stamp());
|
||||
break;
|
||||
case Command::WriteA:
|
||||
dataStrobe = command.getIntervalOnDataStrobe();
|
||||
TlmRecorder::getInstance().updateDataStrobe(dataStrobe.start, dataStrobe.end, payload);
|
||||
controllerCorePEQ.notify(payload, BEGIN_WRA, command.getStart() - sc_time_stamp());
|
||||
break;
|
||||
case Command::AutoRefresh:
|
||||
controllerCorePEQ.notify(payload, BEGIN_AUTO_REFRESH, 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:
|
||||
controllerCorePEQ.notify(payload, BEGIN_PRE_ALL, command.getStart() - sc_time_stamp());
|
||||
break;
|
||||
case Command::PDNA:
|
||||
controllerCorePEQ.notify(payload, BEGIN_PDNA, command.getStart() - sc_time_stamp());
|
||||
break;
|
||||
case Command::PDNP:
|
||||
controllerCorePEQ.notify(payload, BEGIN_PDNP, command.getStart() - sc_time_stamp());
|
||||
break;
|
||||
case Command::SREF:
|
||||
controllerCorePEQ.notify(payload, BEGIN_SREF, command.getStart() - sc_time_stamp());
|
||||
break;
|
||||
case Command::PDNAX:
|
||||
controllerCorePEQ.notify(payload, END_PDNA, command.getEnd() - sc_time_stamp());
|
||||
break;
|
||||
case Command::PDNPX:
|
||||
controllerCorePEQ.notify(payload, END_PDNP, command.getEnd() - sc_time_stamp());
|
||||
break;
|
||||
case Command::SREFX:
|
||||
controllerCorePEQ.notify(payload, END_SREF, command.getEnd() - sc_time_stamp());
|
||||
break;
|
||||
|
||||
default:
|
||||
SC_REPORT_FATAL(0, "unsupported command was sent by controller");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
virtual void send(Trigger trigger, sc_time time, tlm_generic_payload& payload) override
|
||||
{
|
||||
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 controllerCorePEQCallback(tlm_generic_payload& payload, const tlm_phase& phase)
|
||||
{
|
||||
if (phase == REF_TRIGGER)
|
||||
{
|
||||
controllerCore->triggerRefresh(payload, sc_time_stamp());
|
||||
}
|
||||
else if (phase == PDN_TRIGGER)
|
||||
{
|
||||
controllerCore->powerDownManager->sleep(DramExtension::getExtension(payload).getBank(),sc_time_stamp());
|
||||
}
|
||||
else
|
||||
{
|
||||
Bank bank = DramExtension::getExtension(payload).getBank();
|
||||
sendToDram(payload, phase, SC_ZERO_TIME);
|
||||
|
||||
if (phase == BEGIN_RD || phase == BEGIN_WR)
|
||||
scheduleNextPayload();
|
||||
else if (phase == BEGIN_AUTO_REFRESH)
|
||||
printDebugMessage("Entering auto refresh on bank " + to_string(bank.ID()));
|
||||
else if (containsPhase(phase, { BEGIN_PDNA, BEGIN_PDNP, BEGIN_SREF }))
|
||||
printDebugMessage("Entering PowerDown " + phaseNameToString(phase) + " on bank " + to_string(bank.ID()));
|
||||
else if (containsPhase(phase, { END_PDNA, END_PDNP, END_SREF }))
|
||||
printDebugMessage("Leaving PowerDown " + phaseNameToString(phase) + " on bank " + to_string(bank.ID()));
|
||||
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_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;
|
||||
|
||||
private:
|
||||
void buildScheduler();
|
||||
void payloadEntersSystem(tlm_generic_payload& payload);
|
||||
void payloadLeavesSystem(tlm_generic_payload& payload);
|
||||
unsigned int getTotalNumberOfPayloadsInSystem();
|
||||
void scheduleNextPayload();
|
||||
|
||||
// --- FRONTEND ------
|
||||
tlm_sync_enum nb_transport_fw(tlm_generic_payload& payload, tlm_phase& phase, sc_time& fwDelay);
|
||||
void frontendPEQCallback(tlm_generic_payload& payload, const tlm_phase& phase);
|
||||
void sendToFrontend(tlm_generic_payload& payload, const tlm_phase& phase, const sc_time& delay);
|
||||
|
||||
// --- DRAM ------
|
||||
tlm_sync_enum nb_transport_bw(tlm_generic_payload& payload, tlm_phase& phase, sc_time& bwDelay);
|
||||
void dramPEQCallback(tlm_generic_payload& payload, const tlm_phase& phase);
|
||||
void sendToDram(tlm_generic_payload& payload, const tlm_phase& phase, const sc_time& delay);
|
||||
|
||||
// ------- CONTROLLER CORE ---------
|
||||
void controllerCorePEQCallback(tlm_generic_payload& payload, const tlm_phase& phase);
|
||||
|
||||
//Helpers
|
||||
void printDebugMessage(string message);
|
||||
bool containsPhase(tlm_phase phase, std::vector<tlm_phase> phases);
|
||||
|
||||
ControllerCore* controllerCore;
|
||||
Scheduler* scheduler;
|
||||
std::map<Bank, int> numberOfPayloadsInSystem;
|
||||
|
||||
tlm::tlm_generic_payload* backpressure = NULL;
|
||||
|
||||
tlm_utils::peq_with_cb_and_phase<Controller> frontendPEQ;
|
||||
@@ -221,188 +103,347 @@ private:
|
||||
tlm_utils::peq_with_cb_and_phase<Controller> controllerCorePEQ;
|
||||
|
||||
DebugManager& debugManager;
|
||||
|
||||
// --- FRONTEND INTERACTION ------
|
||||
tlm_sync_enum nb_transport_fw(tlm_generic_payload& payload, tlm_phase& phase, sc_time& fwDelay)
|
||||
{
|
||||
if (phase == BEGIN_REQ)
|
||||
{
|
||||
TlmRecorder::getInstance().recordPhase(payload, phase, fwDelay + sc_time_stamp());
|
||||
frontendPEQ.notify(payload, phase,
|
||||
clkAlign(sc_time_stamp() + fwDelay) - (sc_time_stamp() + fwDelay) + Configuration::getInstance().Timings.clk);
|
||||
}
|
||||
else if (phase == END_RESP)
|
||||
{
|
||||
TlmRecorder::getInstance().recordPhase(payload, phase,
|
||||
fwDelay + sc_time_stamp() + Configuration::getInstance().Timings.clk);
|
||||
frontendPEQ.notify(payload, phase, clkAlign(sc_time_stamp() + fwDelay) - (sc_time_stamp() + fwDelay));
|
||||
}
|
||||
return TLM_ACCEPTED;
|
||||
}
|
||||
|
||||
void frontendPEQCallback(tlm_generic_payload& payload, const tlm_phase& phase)
|
||||
{
|
||||
if (phase == BEGIN_REQ)
|
||||
{
|
||||
|
||||
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);
|
||||
scheduleNextPayload();
|
||||
}
|
||||
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);
|
||||
scheduleNextPayload();
|
||||
backpressure = NULL;
|
||||
}
|
||||
|
||||
payloadLeavesSystem(payload);
|
||||
payload.release();
|
||||
}
|
||||
else
|
||||
{
|
||||
SC_REPORT_FATAL(0, "Frontend PEQ event queue in controller wrapper was triggered with unknown phase");
|
||||
}
|
||||
}
|
||||
|
||||
void 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]++;
|
||||
}
|
||||
|
||||
void 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 getTotalNumberOfPayloadsInSystem()
|
||||
{
|
||||
unsigned int sum = 0;
|
||||
for (Bank bank : controllerCore->getBanks())
|
||||
{
|
||||
sum += numberOfPayloadsInSystem[bank];
|
||||
}
|
||||
return sum;
|
||||
}
|
||||
|
||||
|
||||
void scheduleNextPayload()
|
||||
{
|
||||
if(scheduler->hasPayloads())
|
||||
{
|
||||
tlm_generic_payload* payload = scheduler->getNextPayload();
|
||||
if(payload != NULL)
|
||||
{
|
||||
controllerCore->powerDownManager->wakeUp(DramExtension::getExtension(payload).getBank(), sc_time_stamp());
|
||||
bool wasScheduledByCore = controllerCore->scheduleRequest(sc_time_stamp(), *payload);
|
||||
if (wasScheduledByCore)
|
||||
{
|
||||
scheduler->removePayload(payload);
|
||||
printDebugMessage("\t-> Next payload was scheduled by core");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void 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);
|
||||
}
|
||||
|
||||
// --- DRAM INTERACTION ------
|
||||
tlm_sync_enum nb_transport_bw(tlm_generic_payload& payload, tlm_phase& phase, sc_time& bwDelay)
|
||||
{
|
||||
dramPEQ.notify(payload, phase, bwDelay);
|
||||
TlmRecorder::getInstance().recordPhase(payload, phase, bwDelay + sc_time_stamp());
|
||||
return TLM_ACCEPTED;
|
||||
}
|
||||
|
||||
void 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 == BEGIN_RD || phase == BEGIN_WR)
|
||||
{
|
||||
scheduleNextPayload();
|
||||
sendToDram(payload, phase, SC_ZERO_TIME);
|
||||
}
|
||||
else 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);
|
||||
scheduleNextPayload();
|
||||
}
|
||||
else if (phase == END_AUTO_REFRESH)
|
||||
{
|
||||
printDebugMessage("Finished auto refresh on bank " + to_string(bank.ID()));
|
||||
if(numberOfPayloadsInSystem[bank] == 0)
|
||||
controllerCore->powerDownManager->sleep(bank,sc_time_stamp());
|
||||
scheduleNextPayload();
|
||||
}
|
||||
else if (containsPhase(phase, { END_PRE, END_PRE_ALL, END_ACT }))
|
||||
{
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
string str = string("dramPEQCallback queue in controller wrapper was triggered with unsupported phase ")
|
||||
+ phaseNameToString(phase);
|
||||
SC_REPORT_FATAL(0, str.c_str());
|
||||
}
|
||||
}
|
||||
|
||||
void 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);
|
||||
}
|
||||
|
||||
//Helpers
|
||||
void printDebugMessage(string message)
|
||||
{
|
||||
debugManager.printDebugMessage(name(), message);
|
||||
}
|
||||
|
||||
bool containsPhase(tlm_phase phase, std::vector<tlm_phase> phases)
|
||||
{
|
||||
for (tlm_phase p : phases)
|
||||
{
|
||||
if (p == phase)
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
// --- IMPLEMENTATION -----
|
||||
|
||||
template<unsigned int BUSWIDTH>
|
||||
void Controller<BUSWIDTH>::buildScheduler()
|
||||
{
|
||||
string selectedScheduler = Configuration::getInstance().Scheduler;
|
||||
|
||||
if (selectedScheduler == "FR_FCFS")
|
||||
{
|
||||
|
||||
scheduler = new FR_FCFS(*controllerCore, Configuration::getInstance().RefreshAwareScheduling,
|
||||
Configuration::getInstance().AdaptiveOpenPagePolicy);
|
||||
}
|
||||
else if (selectedScheduler == "PAR_BS")
|
||||
{
|
||||
scheduler = new PAR_BS(*controllerCore, Configuration::getInstance().RefreshAwareScheduling,
|
||||
Configuration::getInstance().Capsize);
|
||||
}
|
||||
else if (selectedScheduler == "FIFO")
|
||||
scheduler = new Fifo(*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())
|
||||
{
|
||||
case Command::Read:
|
||||
dataStrobe = command.getIntervalOnDataStrobe();
|
||||
TlmRecorder::getInstance().updateDataStrobe(dataStrobe.start, dataStrobe.end, payload);
|
||||
controllerCorePEQ.notify(payload, BEGIN_RD, command.getStart() - sc_time_stamp());
|
||||
break;
|
||||
case Command::ReadA:
|
||||
dataStrobe = command.getIntervalOnDataStrobe();
|
||||
TlmRecorder::getInstance().updateDataStrobe(dataStrobe.start, dataStrobe.end, payload);
|
||||
controllerCorePEQ.notify(payload, BEGIN_RDA, command.getStart() - sc_time_stamp());
|
||||
break;
|
||||
case Command::Write:
|
||||
dataStrobe = command.getIntervalOnDataStrobe();
|
||||
TlmRecorder::getInstance().updateDataStrobe(dataStrobe.start, dataStrobe.end, payload);
|
||||
controllerCorePEQ.notify(payload, BEGIN_WR, command.getStart() - sc_time_stamp());
|
||||
break;
|
||||
case Command::WriteA:
|
||||
dataStrobe = command.getIntervalOnDataStrobe();
|
||||
TlmRecorder::getInstance().updateDataStrobe(dataStrobe.start, dataStrobe.end, payload);
|
||||
controllerCorePEQ.notify(payload, BEGIN_WRA, command.getStart() - sc_time_stamp());
|
||||
break;
|
||||
case Command::AutoRefresh:
|
||||
controllerCorePEQ.notify(payload, BEGIN_AUTO_REFRESH, 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:
|
||||
controllerCorePEQ.notify(payload, BEGIN_PRE_ALL, command.getStart() - sc_time_stamp());
|
||||
break;
|
||||
case Command::PDNA:
|
||||
controllerCorePEQ.notify(payload, BEGIN_PDNA, command.getStart() - sc_time_stamp());
|
||||
break;
|
||||
case Command::PDNP:
|
||||
controllerCorePEQ.notify(payload, BEGIN_PDNP, command.getStart() - sc_time_stamp());
|
||||
break;
|
||||
case Command::SREF:
|
||||
controllerCorePEQ.notify(payload, BEGIN_SREF, command.getStart() - sc_time_stamp());
|
||||
break;
|
||||
case Command::PDNAX:
|
||||
controllerCorePEQ.notify(payload, END_PDNA, command.getEnd() - sc_time_stamp());
|
||||
break;
|
||||
case Command::PDNPX:
|
||||
controllerCorePEQ.notify(payload, END_PDNP, command.getEnd() - sc_time_stamp());
|
||||
break;
|
||||
case Command::SREFX:
|
||||
controllerCorePEQ.notify(payload, END_SREF, command.getEnd() - 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, sc_time_stamp());
|
||||
}
|
||||
else if (phase == PDN_TRIGGER)
|
||||
{
|
||||
controllerCore->powerDownManager->sleep(DramExtension::getExtension(payload).getBank(),sc_time_stamp());
|
||||
}
|
||||
else
|
||||
{
|
||||
Bank bank = DramExtension::getExtension(payload).getBank();
|
||||
sendToDram(payload, phase, SC_ZERO_TIME);
|
||||
|
||||
if (phase == BEGIN_RD || phase == BEGIN_WR)
|
||||
scheduleNextPayload();
|
||||
else if (phase == BEGIN_AUTO_REFRESH)
|
||||
printDebugMessage("Entering auto refresh on bank " + to_string(bank.ID()));
|
||||
else if (containsPhase(phase, { BEGIN_PDNA, BEGIN_PDNP, BEGIN_SREF }))
|
||||
printDebugMessage("Entering PowerDown " + phaseNameToString(phase) + " on bank " + to_string(bank.ID()));
|
||||
else if (containsPhase(phase, { END_PDNA, END_PDNP, END_SREF }))
|
||||
printDebugMessage("Leaving PowerDown " + phaseNameToString(phase) + " on bank " + to_string(bank.ID()));
|
||||
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)
|
||||
{
|
||||
if (phase == BEGIN_REQ)
|
||||
{
|
||||
TlmRecorder::getInstance().recordPhase(payload, phase, fwDelay + sc_time_stamp());
|
||||
frontendPEQ.notify(payload, phase,
|
||||
clkAlign(sc_time_stamp() + fwDelay) - (sc_time_stamp() + fwDelay) + Configuration::getInstance().Timings.clk);
|
||||
}
|
||||
else if (phase == END_RESP)
|
||||
{
|
||||
TlmRecorder::getInstance().recordPhase(payload, phase,
|
||||
fwDelay + sc_time_stamp() + Configuration::getInstance().Timings.clk);
|
||||
frontendPEQ.notify(payload, phase, clkAlign(sc_time_stamp() + fwDelay) - (sc_time_stamp() + fwDelay));
|
||||
}
|
||||
return TLM_ACCEPTED;
|
||||
}
|
||||
|
||||
template<unsigned int BUSWIDTH>
|
||||
void Controller<BUSWIDTH>::frontendPEQCallback(tlm_generic_payload &payload, const tlm_phase &phase)
|
||||
{
|
||||
if (phase == BEGIN_REQ)
|
||||
{
|
||||
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);
|
||||
scheduleNextPayload();
|
||||
}
|
||||
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);
|
||||
scheduleNextPayload();
|
||||
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]++;
|
||||
}
|
||||
|
||||
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>::scheduleNextPayload()
|
||||
{
|
||||
if(scheduler->hasPayloads())
|
||||
{
|
||||
tlm_generic_payload* payload = scheduler->getNextPayload();
|
||||
if(payload != NULL)
|
||||
{
|
||||
controllerCore->powerDownManager->wakeUp(DramExtension::getExtension(payload).getBank(), sc_time_stamp());
|
||||
bool wasScheduledByCore = controllerCore->scheduleRequest(sc_time_stamp(), *payload);
|
||||
if (wasScheduledByCore)
|
||||
{
|
||||
scheduler->removePayload(payload);
|
||||
printDebugMessage("\t-> Next payload was scheduled by core");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
dramPEQ.notify(payload, phase, bwDelay);
|
||||
TlmRecorder::getInstance().recordPhase(payload, phase, bwDelay + sc_time_stamp());
|
||||
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 == BEGIN_RD || phase == BEGIN_WR)
|
||||
{
|
||||
scheduleNextPayload();
|
||||
sendToDram(payload, phase, SC_ZERO_TIME);
|
||||
}
|
||||
else 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);
|
||||
scheduleNextPayload();
|
||||
}
|
||||
else if (phase == END_AUTO_REFRESH)
|
||||
{
|
||||
printDebugMessage("Finished auto refresh on bank " + to_string(bank.ID()));
|
||||
if(numberOfPayloadsInSystem[bank] == 0)
|
||||
controllerCore->powerDownManager->sleep(bank,sc_time_stamp());
|
||||
scheduleNextPayload();
|
||||
}
|
||||
else if (containsPhase(phase, { END_PRE, END_PRE_ALL, END_ACT }))
|
||||
{
|
||||
|
||||
}
|
||||
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()));
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* CONTROLLERWRAPPER_H_ */
|
||||
|
||||
@@ -34,13 +34,12 @@ public:
|
||||
void saveState();
|
||||
void resetState();
|
||||
|
||||
|
||||
const std::vector<Bank>& getBanks();
|
||||
std::vector<Bank> getFreeBanks(sc_time currentTime);
|
||||
const RowBufferState& getRowBufferStates(){return state.rowBufferStates;}
|
||||
|
||||
void send(const CommandSchedule& schedule, tlm::tlm_generic_payload& payload) const;
|
||||
ICommandChecker& getCommandChecker(Command command);
|
||||
static void printDebugMessage(string message);
|
||||
|
||||
Configuration config;
|
||||
ControllerState state;
|
||||
@@ -50,9 +49,10 @@ public:
|
||||
IRefreshManager* refreshManager;
|
||||
std::map<Bank,int>& numberOfPayloads;
|
||||
static std::string senderName;
|
||||
static void printDebugMessage(string message);
|
||||
|
||||
private:
|
||||
void send(const CommandSchedule& schedule, tlm::tlm_generic_payload& payload) const;
|
||||
|
||||
std::map<Command, ICommandChecker*> commandChecker;
|
||||
ControllerState savedState;
|
||||
CommandSequenceGenerator commandSequenceGenerator;
|
||||
|
||||
@@ -80,7 +80,7 @@ sc_time getExecutionTime(Command command, tlm::tlm_generic_payload& payload)
|
||||
}
|
||||
}
|
||||
|
||||
sc_time getMinimalExecutionTime(Command command, tlm::tlm_generic_payload& payload)
|
||||
sc_time getMinExecutionTimeForPowerDownCmd(Command command)
|
||||
{
|
||||
TimingConfiguration& config = Configuration::getInstance().Timings;
|
||||
if (command == Command::PDNA || command == Command::PDNP)
|
||||
@@ -107,7 +107,7 @@ bool isClkAligned(sc_time time, sc_time clk)
|
||||
sc_time getReadAccessTime()
|
||||
{
|
||||
Configuration& config = Configuration::getInstance();
|
||||
return config.BurstLength/config.DataRate*config.Timings.clk;
|
||||
return (config.BurstLength / config.DataRate)*config.Timings.clk;
|
||||
}
|
||||
|
||||
sc_time getWriteAccessTime()
|
||||
@@ -120,7 +120,7 @@ sc_time getWriteAccessTime()
|
||||
}
|
||||
else
|
||||
{
|
||||
return config.Timings.clk * config.BurstLength / config.DataRate;
|
||||
return config.Timings.clk * (config.BurstLength / config.DataRate);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
namespace core
|
||||
{
|
||||
|
||||
sc_time getMinimalExecutionTime(Command command, tlm::tlm_generic_payload& payload);
|
||||
sc_time getMinExecutionTimeForPowerDownCmd(Command command);
|
||||
sc_time getExecutionTime(Command command, tlm::tlm_generic_payload& payload);
|
||||
|
||||
sc_time getReadAccessTime();
|
||||
|
||||
@@ -59,7 +59,7 @@ void PowerDownManager::sleep(Bank bank, sc_time time)
|
||||
}
|
||||
|
||||
Command cmd = IPowerDownManager::getSleepCommand(state);
|
||||
ScheduledCommand pdn(cmd, time, getMinimalExecutionTime(cmd, powerDownPayloads[bank]),
|
||||
ScheduledCommand pdn(cmd, time, getMinExecutionTimeForPowerDownCmd(cmd),
|
||||
DramExtension::getExtension(powerDownPayloads[bank]));
|
||||
|
||||
controller.getCommandChecker(cmd).delayToSatisfyConstraints(pdn);
|
||||
|
||||
@@ -17,26 +17,25 @@ class ControllerCore;
|
||||
class PowerDownManager: public IPowerDownManager
|
||||
{
|
||||
public:
|
||||
PowerDownManager(ControllerCore& controller);
|
||||
virtual ~PowerDownManager();
|
||||
PowerDownManager(ControllerCore& controller);
|
||||
virtual ~PowerDownManager();
|
||||
|
||||
virtual void triggerSleep(Bank bank, sc_time time) override;
|
||||
virtual void sleep(Bank bank, sc_time time) override;
|
||||
virtual void wakeUp(Bank bank, sc_time time) override;
|
||||
virtual void wakeUpForRefresh(Bank bank, sc_time time) override;
|
||||
virtual void triggerSleep(Bank bank, sc_time time) override;
|
||||
virtual void sleep(Bank bank, sc_time time) override;
|
||||
virtual void wakeUp(Bank bank, sc_time time) override;
|
||||
virtual void wakeUpForRefresh(Bank bank, sc_time time) override;
|
||||
virtual bool isInSelfRefresh(Bank bank) override;
|
||||
|
||||
virtual bool isInSelfRefresh(Bank bank) override;
|
||||
private:
|
||||
PowerDownState powerDownState;
|
||||
void sendPowerDownPayloads(ScheduledCommand& cmd);
|
||||
void sendPowerDownPayloads(ScheduledCommand& cmd);
|
||||
bool isInPowerDown();
|
||||
void setPowerDownState(PowerDownState state);
|
||||
bool canSleep();
|
||||
bool isAwakeForRefresh();
|
||||
|
||||
bool isInPowerDown();
|
||||
|
||||
void setPowerDownState(PowerDownState state);
|
||||
bool canSleep();
|
||||
bool isAwakeForRefresh();
|
||||
std::map<Bank, tlm::tlm_generic_payload> powerDownPayloads;
|
||||
ControllerCore& controller;
|
||||
PowerDownState powerDownState;
|
||||
std::map<Bank, tlm::tlm_generic_payload> powerDownPayloads;
|
||||
ControllerCore& controller;
|
||||
};
|
||||
|
||||
} /* namespace core */
|
||||
|
||||
@@ -17,135 +17,135 @@ namespace core {
|
||||
std::string PowerDownManagerBankwise::senderName = "pdn manager";
|
||||
|
||||
PowerDownManagerBankwise::PowerDownManagerBankwise(ControllerCore& controller) :
|
||||
controller(controller)
|
||||
controller(controller)
|
||||
{
|
||||
for (Bank bank : controller.getBanks())
|
||||
{
|
||||
setUpDummy(powerDownPayloads[bank], bank);
|
||||
powerDownStates[bank] = PowerDownState::Awake;
|
||||
}
|
||||
for (Bank bank : controller.getBanks())
|
||||
{
|
||||
setUpDummy(powerDownPayloads[bank], bank);
|
||||
powerDownStates[bank] = PowerDownState::Awake;
|
||||
}
|
||||
}
|
||||
|
||||
void PowerDownManagerBankwise::sleep(Bank bank, sc_time time)
|
||||
{
|
||||
if (!canSleep(bank) || isInPowerDown(bank))
|
||||
return;
|
||||
if (!canSleep(bank) || isInPowerDown(bank))
|
||||
return;
|
||||
|
||||
tlm_generic_payload& payload = powerDownPayloads[bank];
|
||||
tlm_generic_payload& payload = powerDownPayloads[bank];
|
||||
|
||||
PowerDownState state = powerDownStates[bank];
|
||||
if (state == PowerDownState::Awake) //coming from active
|
||||
{
|
||||
state = controller.state.rowBufferStates.rowBufferIsOpen(bank) ? PowerDownState::PDNActive : PowerDownState::PDNPrecharge;
|
||||
}
|
||||
else if (state == PowerDownState::AwakeForRefresh) //coming from refresh interrupting power down
|
||||
{
|
||||
sc_assert(!controller.state.rowBufferStates.rowBufferIsOpen(bank));
|
||||
PowerDownState state = powerDownStates[bank];
|
||||
if (state == PowerDownState::Awake) //coming from active
|
||||
{
|
||||
state = controller.state.rowBufferStates.rowBufferIsOpen(bank) ? PowerDownState::PDNActive : PowerDownState::PDNPrecharge;
|
||||
}
|
||||
else if (state == PowerDownState::AwakeForRefresh) //coming from refresh interrupting power down
|
||||
{
|
||||
sc_assert(!controller.state.rowBufferStates.rowBufferIsOpen(bank));
|
||||
|
||||
if (controller.state.getLastCommand(Command::PDNA, bank).getStart()
|
||||
>= controller.state.getLastCommand(Command::PDNP, bank).getStart())
|
||||
state = PowerDownState::PDNPrecharge;
|
||||
else
|
||||
{
|
||||
state = PowerDownState::PDNSelfRefresh;
|
||||
}
|
||||
}
|
||||
if (controller.state.getLastCommand(Command::PDNA, bank).getStart()
|
||||
>= controller.state.getLastCommand(Command::PDNP, bank).getStart())
|
||||
state = PowerDownState::PDNPrecharge;
|
||||
else
|
||||
{
|
||||
state = PowerDownState::PDNSelfRefresh;
|
||||
}
|
||||
}
|
||||
|
||||
Command cmd = IPowerDownManager::getSleepCommand(state);
|
||||
ScheduledCommand pdn(cmd, time, getMinimalExecutionTime(cmd, payload), DramExtension::getExtension(payload));
|
||||
controller.getCommandChecker(cmd).delayToSatisfyConstraints(pdn);
|
||||
Command cmd = IPowerDownManager::getSleepCommand(state);
|
||||
ScheduledCommand pdn(cmd, time, getMinExecutionTimeForPowerDownCmd(cmd), DramExtension::getExtension(payload));
|
||||
controller.getCommandChecker(cmd).delayToSatisfyConstraints(pdn);
|
||||
|
||||
if (state != PowerDownState::PDNSelfRefresh && controller.refreshManager->hasCollision(pdn))
|
||||
{
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
setState(state, bank);
|
||||
sendPowerDownPayload(pdn);
|
||||
}
|
||||
if (state != PowerDownState::PDNSelfRefresh && controller.refreshManager->hasCollision(pdn))
|
||||
{
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
setState(state, bank);
|
||||
sendPowerDownPayload(pdn);
|
||||
}
|
||||
}
|
||||
|
||||
void PowerDownManagerBankwise::wakeUp(Bank bank, sc_time time)
|
||||
{
|
||||
if (isAwakeForRefresh(bank))
|
||||
{
|
||||
setState(PowerDownState::Awake, bank);
|
||||
}
|
||||
else if (isInPowerDown(bank))
|
||||
{
|
||||
//Request wakes up power down
|
||||
Command cmd = IPowerDownManager::getWakeUpCommand(powerDownStates[bank]);
|
||||
ScheduledCommand pdn(cmd, time, getExecutionTime(cmd, powerDownPayloads[bank]),
|
||||
DramExtension::getExtension(powerDownPayloads[bank]));
|
||||
controller.getCommandChecker(cmd).delayToSatisfyConstraints(pdn);
|
||||
if (isAwakeForRefresh(bank))
|
||||
{
|
||||
setState(PowerDownState::Awake, bank);
|
||||
}
|
||||
else if (isInPowerDown(bank))
|
||||
{
|
||||
//Request wakes up power down
|
||||
Command cmd = IPowerDownManager::getWakeUpCommand(powerDownStates[bank]);
|
||||
ScheduledCommand pdn(cmd, time, getExecutionTime(cmd, powerDownPayloads[bank]),
|
||||
DramExtension::getExtension(powerDownPayloads[bank]));
|
||||
controller.getCommandChecker(cmd).delayToSatisfyConstraints(pdn);
|
||||
|
||||
if (cmd == Command::SREFX)
|
||||
controller.refreshManager->reInitialize(bank, pdn.getEnd());
|
||||
if (cmd == Command::SREFX)
|
||||
controller.refreshManager->reInitialize(bank, pdn.getEnd());
|
||||
|
||||
setState(PowerDownState::Awake, bank);
|
||||
sendPowerDownPayload(pdn);
|
||||
}
|
||||
setState(PowerDownState::Awake, bank);
|
||||
sendPowerDownPayload(pdn);
|
||||
}
|
||||
}
|
||||
|
||||
void PowerDownManagerBankwise::wakeUpForRefresh(Bank bank, sc_time time)
|
||||
{
|
||||
if (isInPowerDown(bank))
|
||||
{
|
||||
Command cmd = IPowerDownManager::getWakeUpCommand(powerDownStates[bank]);
|
||||
ScheduledCommand pdn(cmd, time, getExecutionTime(cmd, powerDownPayloads[bank]),
|
||||
DramExtension::getExtension(powerDownPayloads[bank]));
|
||||
if (isInPowerDown(bank))
|
||||
{
|
||||
Command cmd = IPowerDownManager::getWakeUpCommand(powerDownStates[bank]);
|
||||
ScheduledCommand pdn(cmd, time, getExecutionTime(cmd, powerDownPayloads[bank]),
|
||||
DramExtension::getExtension(powerDownPayloads[bank]));
|
||||
|
||||
setState(PowerDownState::AwakeForRefresh, bank);
|
||||
sendPowerDownPayload(pdn);
|
||||
}
|
||||
setState(PowerDownState::AwakeForRefresh, bank);
|
||||
sendPowerDownPayload(pdn);
|
||||
}
|
||||
}
|
||||
|
||||
bool PowerDownManagerBankwise::isInPowerDown(Bank bank)
|
||||
{
|
||||
return isIn(powerDownStates[bank],
|
||||
{ PowerDownState::PDNActive, PowerDownState::PDNPrecharge, PowerDownState::PDNSelfRefresh });
|
||||
return isIn(powerDownStates[bank],
|
||||
{ PowerDownState::PDNActive, PowerDownState::PDNPrecharge, PowerDownState::PDNSelfRefresh });
|
||||
}
|
||||
|
||||
bool PowerDownManagerBankwise::isInSelfRefresh(Bank bank)
|
||||
{
|
||||
return powerDownStates[bank] == PowerDownState::PDNSelfRefresh;
|
||||
return powerDownStates[bank] == PowerDownState::PDNSelfRefresh;
|
||||
}
|
||||
|
||||
bool PowerDownManagerBankwise::isAwakeForRefresh(Bank bank)
|
||||
{
|
||||
return powerDownStates[bank] == PowerDownState::AwakeForRefresh;
|
||||
return powerDownStates[bank] == PowerDownState::AwakeForRefresh;
|
||||
}
|
||||
|
||||
bool PowerDownManagerBankwise::isAwake(Bank bank)
|
||||
{
|
||||
return powerDownStates[bank] == PowerDownState::Awake;
|
||||
return powerDownStates[bank] == PowerDownState::Awake;
|
||||
}
|
||||
|
||||
void PowerDownManagerBankwise::setState(PowerDownState state, Bank bank)
|
||||
{
|
||||
PowerDownState& bankstate = powerDownStates[bank];
|
||||
bankstate = state;
|
||||
PowerDownState& bankstate = powerDownStates[bank];
|
||||
bankstate = state;
|
||||
|
||||
DebugManager::getInstance().printDebugMessage(PowerDownManagerBankwise::senderName,
|
||||
"Is now in state " + powerDownStateToString(state) + " on Bank " + to_string(bank.ID()));
|
||||
DebugManager::getInstance().printDebugMessage(PowerDownManagerBankwise::senderName,
|
||||
"Is now in state " + powerDownStateToString(state) + " on Bank " + to_string(bank.ID()));
|
||||
}
|
||||
|
||||
void PowerDownManagerBankwise::sendPowerDownPayload(ScheduledCommand& pdn)
|
||||
{
|
||||
controller.state.bus.moveCommandToNextFreeSlot(pdn);
|
||||
controller.state.change(pdn);
|
||||
controller.wrapper.send(pdn, powerDownPayloads[pdn.getBank()]);
|
||||
controller.state.bus.moveCommandToNextFreeSlot(pdn);
|
||||
controller.state.change(pdn);
|
||||
controller.wrapper.send(pdn, powerDownPayloads[pdn.getBank()]);
|
||||
}
|
||||
|
||||
bool PowerDownManagerBankwise::canSleep(Bank bank)
|
||||
{
|
||||
return controller.numberOfPayloads[bank] == 0;
|
||||
return controller.numberOfPayloads[bank] == 0;
|
||||
}
|
||||
|
||||
void PowerDownManagerBankwise::triggerSleep(Bank bank, sc_time time)
|
||||
{
|
||||
sleep(bank, time);
|
||||
sleep(bank, time);
|
||||
}
|
||||
|
||||
}/* namespace core */
|
||||
|
||||
@@ -42,7 +42,7 @@ void PowerDownManagerTimeout::sleep(Bank bank, sc_time time)
|
||||
}
|
||||
|
||||
Command cmd = IPowerDownManager::getSleepCommand(newState);
|
||||
ScheduledCommand pdn(cmd, time, getMinimalExecutionTime(cmd, powerDownPayloads[bank]),
|
||||
ScheduledCommand pdn(cmd, time, getMinExecutionTimeForPowerDownCmd(cmd),
|
||||
DramExtension::getExtension(powerDownPayloads[bank]));
|
||||
|
||||
controller.getCommandChecker(cmd).delayToSatisfyConstraints(pdn);
|
||||
|
||||
@@ -18,28 +18,26 @@ class ControllerCore;
|
||||
class RefreshManager : public IRefreshManager
|
||||
{
|
||||
public:
|
||||
RefreshManager(ControllerCore& controller);
|
||||
virtual ~RefreshManager();
|
||||
RefreshManager(ControllerCore& controller);
|
||||
virtual ~RefreshManager();
|
||||
|
||||
virtual bool hasCollision(const CommandSchedule& schedule) override;
|
||||
virtual bool hasCollision(const ScheduledCommand& command) override;
|
||||
virtual bool hasCollision(const CommandSchedule& schedule) override;
|
||||
virtual bool hasCollision(const ScheduledCommand& command) override;
|
||||
|
||||
|
||||
virtual void scheduleRefresh(tlm::tlm_generic_payload& payload, sc_time time) override;
|
||||
void reInitialize(Bank bank, sc_time time) override;
|
||||
|
||||
virtual bool isInvalidated(tlm::tlm_generic_payload& payload, sc_time time) override;
|
||||
virtual void scheduleRefresh(tlm::tlm_generic_payload& payload, sc_time time) override;
|
||||
void reInitialize(Bank bank, sc_time time) override;
|
||||
virtual bool isInvalidated(tlm::tlm_generic_payload& payload, sc_time time) override;
|
||||
|
||||
private:
|
||||
ControllerCore& controller;
|
||||
RefreshTiming& timing;
|
||||
sc_time nextPlannedRefresh;
|
||||
std::map<Bank, tlm::tlm_generic_payload> refreshPayloads;
|
||||
ControllerCore& controller;
|
||||
RefreshTiming& timing;
|
||||
sc_time nextPlannedRefresh;
|
||||
std::map<Bank, tlm::tlm_generic_payload> refreshPayloads;
|
||||
|
||||
void planNextRefresh();
|
||||
void planNextRefresh();
|
||||
|
||||
void sendToAllBanks(ScheduledCommand& command);
|
||||
void setupTransactions();
|
||||
void sendToAllBanks(ScheduledCommand& command);
|
||||
void setupTransactions();
|
||||
};
|
||||
|
||||
} /* namespace core */
|
||||
|
||||
@@ -51,8 +51,6 @@ public:
|
||||
void inline transactionFinished() override;
|
||||
constexpr static unsigned int NumberOfTracePlayers = 4;
|
||||
|
||||
void bindSockets();
|
||||
void calculateNumberOfTransaction(std::vector<Device> devices, string pathToResources);
|
||||
private:
|
||||
std::string traceName;
|
||||
DramSetup dramSetup;
|
||||
@@ -77,6 +75,8 @@ private:
|
||||
void setupDebugManager(const string& traceName);
|
||||
void setupTlmRecorder(const string &traceName, const string &pathToResources, const DramSetup &setup, const std::vector<Device> &devices);
|
||||
void instantiateModules(const string &pathToResources, const std::vector<Device> &devices);
|
||||
void bindSockets();
|
||||
void calculateNumberOfTransaction(std::vector<Device> devices, string pathToResources);
|
||||
};
|
||||
|
||||
} /* namespace simulation */
|
||||
|
||||
Reference in New Issue
Block a user