RecordableController and RecordableDram
This commit is contained in:
@@ -123,6 +123,7 @@ SOURCES += \
|
||||
src/error/ecchamming.cpp \
|
||||
src/controller/scheduler/Fr_Fcfs_read_priority.cpp \
|
||||
src/controller/scheduler/Fr_Fcfs_grouper.cpp \
|
||||
src/controller/RecordableController.cpp \
|
||||
src/common/AddressDecoder.cpp \
|
||||
src/common/jsonAddressDecoder.cpp
|
||||
|
||||
@@ -201,6 +202,8 @@ HEADERS += \
|
||||
src/controller/scheduler/Fr_Fcfs_grouper.h \
|
||||
src/simulation/IArbiter.h \
|
||||
src/simulation/SimpleArbiter.h \
|
||||
src/controller/RecordableController.h \
|
||||
src/simulation/RecordableDram.h \
|
||||
src/common/AddressDecoder.h \
|
||||
src/common/jsonAddressDecoder.h
|
||||
#src/common/third_party/json/include/nlohmann/json.hpp \
|
||||
|
||||
@@ -48,90 +48,90 @@
|
||||
|
||||
using namespace std;
|
||||
|
||||
TlmRecorder::TlmRecorder(sc_module_name /*name*/, string uri, string dbname,
|
||||
bool recenable) : sqlScriptURI(uri), dbName(dbname),
|
||||
recordingEnabled(recenable), totalNumTransactions(1),
|
||||
|
||||
TlmRecorder::TlmRecorder(sc_module_name /*name*/, string uri,
|
||||
string dbname) : sqlScriptURI(uri), dbName(dbname), totalNumTransactions(1),
|
||||
simulationTimeCoveredByRecording(SC_ZERO_TIME)
|
||||
{
|
||||
if (TlmRecorder::recordingEnabled == true) {
|
||||
recordedData.reserve(transactionCommitRate);
|
||||
setUpTransactionTerminatingPhases();
|
||||
openDB(TlmRecorder::dbName.c_str());
|
||||
char *sErrMsg;
|
||||
sqlite3_exec(db, "PRAGMA main.page_size = 4096", NULL, NULL, &sErrMsg);
|
||||
sqlite3_exec(db, "PRAGMA main.cache_size=10000", NULL, NULL, &sErrMsg);
|
||||
sqlite3_exec(db, "PRAGMA main.locking_mode=EXCLUSIVE", NULL, NULL, &sErrMsg);
|
||||
sqlite3_exec(db, "PRAGMA main.synchronous=OFF", NULL, NULL, &sErrMsg);
|
||||
sqlite3_exec(db, "PRAGMA journal_mode = OFF", NULL, NULL, &sErrMsg);
|
||||
recordedData.reserve(transactionCommitRate);
|
||||
setUpTransactionTerminatingPhases();
|
||||
openDB(TlmRecorder::dbName.c_str());
|
||||
char *sErrMsg;
|
||||
sqlite3_exec(db, "PRAGMA main.page_size = 4096", NULL, NULL, &sErrMsg);
|
||||
sqlite3_exec(db, "PRAGMA main.cache_size=10000", NULL, NULL, &sErrMsg);
|
||||
sqlite3_exec(db, "PRAGMA main.locking_mode=EXCLUSIVE", NULL, NULL, &sErrMsg);
|
||||
sqlite3_exec(db, "PRAGMA main.synchronous=OFF", NULL, NULL, &sErrMsg);
|
||||
sqlite3_exec(db, "PRAGMA journal_mode = OFF", NULL, NULL, &sErrMsg);
|
||||
|
||||
createTables(TlmRecorder::sqlScriptURI);
|
||||
prepareSqlStatements();
|
||||
createTables(TlmRecorder::sqlScriptURI);
|
||||
prepareSqlStatements();
|
||||
|
||||
printDebugMessage("Starting new database transaction");
|
||||
}
|
||||
printDebugMessage("Starting new database transaction");
|
||||
}
|
||||
|
||||
TlmRecorder::~TlmRecorder()
|
||||
{
|
||||
if (db)
|
||||
closeConnection();
|
||||
sqlite3_finalize(insertTransactionStatement);
|
||||
sqlite3_finalize(insertRangeStatement);
|
||||
sqlite3_finalize(updateRangeStatement);
|
||||
sqlite3_finalize(insertPhaseStatement);
|
||||
sqlite3_finalize(updatePhaseStatement);
|
||||
sqlite3_finalize(insertGeneralInfoStatement);
|
||||
sqlite3_finalize(insertDebugMessageStatement);
|
||||
sqlite3_finalize(updateDataStrobeStatement);
|
||||
sqlite3_finalize(insertPowerStatement);
|
||||
}
|
||||
|
||||
void TlmRecorder::recordPower(double timeInSeconds, double averagePower)
|
||||
{
|
||||
if (TlmRecorder::recordingEnabled) {
|
||||
sqlite3_bind_double(insertPowerStatement, 1, timeInSeconds);
|
||||
sqlite3_bind_double(insertPowerStatement, 2, averagePower);
|
||||
executeSqlStatement(insertPowerStatement);
|
||||
}
|
||||
sqlite3_bind_double(insertPowerStatement, 1, timeInSeconds);
|
||||
sqlite3_bind_double(insertPowerStatement, 2, averagePower);
|
||||
executeSqlStatement(insertPowerStatement);
|
||||
}
|
||||
|
||||
void TlmRecorder::recordPhase(tlm::tlm_generic_payload &trans,
|
||||
tlm::tlm_phase phase, sc_time time)
|
||||
{
|
||||
if (TlmRecorder::recordingEnabled) {
|
||||
if (currentTransactionsInSystem.count(&trans) == 0)
|
||||
introduceTransactionSystem(trans);
|
||||
if (currentTransactionsInSystem.count(&trans) == 0)
|
||||
introduceTransactionSystem(trans);
|
||||
|
||||
string phaseName = phaseNameToString(phase);
|
||||
string phaseBeginPrefix = "BEGIN_";
|
||||
string phaseEndPrefix = "END_";
|
||||
string phaseName = phaseNameToString(phase);
|
||||
string phaseBeginPrefix = "BEGIN_";
|
||||
string phaseEndPrefix = "END_";
|
||||
|
||||
if (phaseName.find(phaseBeginPrefix) != string::npos) {
|
||||
phaseName.erase(0, phaseBeginPrefix.length());
|
||||
assert(currentTransactionsInSystem.count(&trans) != 0);
|
||||
currentTransactionsInSystem[&trans].insertPhase(phaseName, time);
|
||||
} else {
|
||||
phaseName.erase(0, phaseEndPrefix.length());
|
||||
assert(currentTransactionsInSystem.count(&trans) != 0);
|
||||
currentTransactionsInSystem[&trans].setPhaseEnd(phaseName, time);
|
||||
}
|
||||
|
||||
bool phaseTerminatesTransaction = count(transactionTerminatingPhases.begin(),
|
||||
transactionTerminatingPhases.end(), phase) == 1;
|
||||
if (phaseTerminatesTransaction)
|
||||
removeTransactionFromSystem(trans);
|
||||
|
||||
simulationTimeCoveredByRecording = time;
|
||||
if (phaseName.find(phaseBeginPrefix) != string::npos) {
|
||||
phaseName.erase(0, phaseBeginPrefix.length());
|
||||
assert(currentTransactionsInSystem.count(&trans) != 0);
|
||||
currentTransactionsInSystem[&trans].insertPhase(phaseName, time);
|
||||
} else {
|
||||
phaseName.erase(0, phaseEndPrefix.length());
|
||||
assert(currentTransactionsInSystem.count(&trans) != 0);
|
||||
currentTransactionsInSystem[&trans].setPhaseEnd(phaseName, time);
|
||||
}
|
||||
|
||||
bool phaseTerminatesTransaction = count(transactionTerminatingPhases.begin(),
|
||||
transactionTerminatingPhases.end(), phase) == 1;
|
||||
if (phaseTerminatesTransaction)
|
||||
removeTransactionFromSystem(trans);
|
||||
|
||||
simulationTimeCoveredByRecording = time;
|
||||
}
|
||||
|
||||
|
||||
void TlmRecorder::updateDataStrobe(const sc_time &begin, const sc_time &end,
|
||||
tlm::tlm_generic_payload &trans)
|
||||
{
|
||||
if (TlmRecorder::recordingEnabled) {
|
||||
assert(currentTransactionsInSystem.count(&trans) != 0);
|
||||
currentTransactionsInSystem[&trans].timeOnDataStrobe.start = begin;
|
||||
currentTransactionsInSystem[&trans].timeOnDataStrobe.end = end;
|
||||
}
|
||||
assert(currentTransactionsInSystem.count(&trans) != 0);
|
||||
currentTransactionsInSystem[&trans].timeOnDataStrobe.start = begin;
|
||||
currentTransactionsInSystem[&trans].timeOnDataStrobe.end = end;
|
||||
}
|
||||
|
||||
|
||||
void TlmRecorder::recordDebugMessage(std::string message, sc_time time)
|
||||
{
|
||||
if (TlmRecorder::recordingEnabled)
|
||||
insertDebugMessageInDB(message, time);
|
||||
insertDebugMessageInDB(message, time);
|
||||
}
|
||||
|
||||
|
||||
@@ -434,24 +434,13 @@ void TlmRecorder::printDebugMessage(std::string message)
|
||||
|
||||
void TlmRecorder::closeConnection()
|
||||
{
|
||||
if (TlmRecorder::recordingEnabled) {
|
||||
commitRecordedDataToDB();
|
||||
insertGeneralInfo();
|
||||
printDebugMessage(
|
||||
"Number of transactions written to DB: " + std::to_string(
|
||||
totalNumTransactions - 1));
|
||||
printDebugMessage("tlmPhaseRecorder:\tEnd Recording");
|
||||
sqlite3_finalize(insertTransactionStatement);
|
||||
sqlite3_finalize(insertRangeStatement);
|
||||
sqlite3_finalize(updateRangeStatement);
|
||||
sqlite3_finalize(insertPhaseStatement);
|
||||
sqlite3_finalize(updatePhaseStatement);
|
||||
sqlite3_finalize(insertGeneralInfoStatement);
|
||||
sqlite3_finalize(insertDebugMessageStatement);
|
||||
sqlite3_finalize(updateDataStrobeStatement);
|
||||
sqlite3_finalize(insertPowerStatement);
|
||||
sqlite3_close(db);
|
||||
db = NULL;
|
||||
}
|
||||
commitRecordedDataToDB();
|
||||
insertGeneralInfo();
|
||||
printDebugMessage(
|
||||
"Number of transactions written to DB: " + std::to_string(
|
||||
totalNumTransactions - 1));
|
||||
printDebugMessage("tlmPhaseRecorder:\tEnd Recording");
|
||||
sqlite3_close(db);
|
||||
db = NULL;
|
||||
}
|
||||
|
||||
|
||||
@@ -60,9 +60,8 @@ class TlmRecorder : public sc_module
|
||||
public:
|
||||
std::string sqlScriptURI;
|
||||
std::string dbName;
|
||||
bool recordingEnabled;
|
||||
|
||||
TlmRecorder(sc_module_name /*name*/, string uri, string dbname, bool recenable);
|
||||
TlmRecorder(sc_module_name /*name*/, string uri, string dbname);
|
||||
~TlmRecorder();
|
||||
|
||||
void recordMCconfig(string mcconfig)
|
||||
|
||||
@@ -75,114 +75,83 @@ void Controller::send(const ScheduledCommand &command,
|
||||
tlm_generic_payload &payload)
|
||||
{
|
||||
sc_assert(command.getStart() >= sc_time_stamp());
|
||||
TimeInterval dataStrobe;
|
||||
|
||||
tlm_phase phase;
|
||||
|
||||
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());
|
||||
phase = BEGIN_RD;
|
||||
break;
|
||||
case Command::ReadA:
|
||||
dataStrobe = command.getIntervalOnDataStrobe();
|
||||
tlmRecorder->updateDataStrobe(dataStrobe.start, dataStrobe.end, payload);
|
||||
controllerCorePEQ.notify(payload, BEGIN_RDA,
|
||||
command.getStart() - sc_time_stamp());
|
||||
phase = BEGIN_RDA;
|
||||
break;
|
||||
case Command::Write:
|
||||
dataStrobe = command.getIntervalOnDataStrobe();
|
||||
tlmRecorder->updateDataStrobe(dataStrobe.start, dataStrobe.end, payload);
|
||||
controllerCorePEQ.notify(payload, BEGIN_WR,
|
||||
command.getStart() - sc_time_stamp());
|
||||
phase = BEGIN_WR;
|
||||
break;
|
||||
case Command::WriteA:
|
||||
dataStrobe = command.getIntervalOnDataStrobe();
|
||||
tlmRecorder->updateDataStrobe(dataStrobe.start, dataStrobe.end, payload);
|
||||
controllerCorePEQ.notify(payload, BEGIN_WRA,
|
||||
command.getStart() - sc_time_stamp());
|
||||
phase = BEGIN_WRA;
|
||||
break;
|
||||
case Command::AutoRefresh:
|
||||
if (!Configuration::getInstance().BankwiseLogic) {
|
||||
controllerCorePEQ.notify(payload, BEGIN_REFA,
|
||||
command.getStart() - sc_time_stamp());
|
||||
phase = BEGIN_REFA;
|
||||
} else
|
||||
controllerCorePEQ.notify(payload, BEGIN_REFB,
|
||||
command.getStart() - sc_time_stamp());
|
||||
break;
|
||||
case Command::ActB:
|
||||
controllerCorePEQ.notify(payload, BEGIN_ACTB,
|
||||
command.getStart() - sc_time_stamp());
|
||||
phase = BEGIN_REFB;
|
||||
break;
|
||||
case Command::Activate:
|
||||
controllerCorePEQ.notify(payload, BEGIN_ACT,
|
||||
command.getStart() - sc_time_stamp());
|
||||
break;
|
||||
case Command::PreB:
|
||||
controllerCorePEQ.notify(payload, BEGIN_PREB,
|
||||
command.getStart() - sc_time_stamp());
|
||||
phase = BEGIN_ACT;
|
||||
break;
|
||||
case Command::Precharge:
|
||||
controllerCorePEQ.notify(payload, BEGIN_PRE,
|
||||
command.getStart() - sc_time_stamp());
|
||||
phase = BEGIN_PRE;
|
||||
break;
|
||||
case Command::PrechargeAll:
|
||||
controllerCorePEQ.notify(payload, BEGIN_PRE_ALL,
|
||||
command.getStart() - sc_time_stamp());
|
||||
phase = BEGIN_PRE_ALL;
|
||||
break;
|
||||
case Command::PDNA:
|
||||
if (!Configuration::getInstance().BankwiseLogic) {
|
||||
controllerCorePEQ.notify(payload, BEGIN_PDNA,
|
||||
command.getStart() - sc_time_stamp());
|
||||
phase = BEGIN_PDNA;
|
||||
} else
|
||||
controllerCorePEQ.notify(payload, BEGIN_PDNAB,
|
||||
command.getStart() - sc_time_stamp());
|
||||
phase = BEGIN_PDNAB;
|
||||
break;
|
||||
case Command::PDNAX:
|
||||
if (!Configuration::getInstance().BankwiseLogic) {
|
||||
controllerCorePEQ.notify(payload, END_PDNA,
|
||||
command.getStart() - sc_time_stamp());
|
||||
phase = END_PDNA;
|
||||
} else
|
||||
controllerCorePEQ.notify(payload, END_PDNAB,
|
||||
command.getStart() - sc_time_stamp());
|
||||
phase = END_PDNAB;
|
||||
break;
|
||||
case Command::PDNP:
|
||||
if (!Configuration::getInstance().BankwiseLogic) {
|
||||
controllerCorePEQ.notify(payload, BEGIN_PDNP,
|
||||
command.getStart() - sc_time_stamp());
|
||||
phase = BEGIN_PDNP;
|
||||
} else
|
||||
controllerCorePEQ.notify(payload, BEGIN_PDNPB,
|
||||
command.getStart() - sc_time_stamp());
|
||||
phase = BEGIN_PDNPB;
|
||||
break;
|
||||
case Command::PDNPX:
|
||||
if (!Configuration::getInstance().BankwiseLogic) {
|
||||
controllerCorePEQ.notify(payload, END_PDNP,
|
||||
command.getStart() - sc_time_stamp());
|
||||
phase = END_PDNP;
|
||||
} else
|
||||
controllerCorePEQ.notify(payload, END_PDNPB,
|
||||
command.getStart() - sc_time_stamp());
|
||||
phase = END_PDNPB;
|
||||
break;
|
||||
case Command::SREF:
|
||||
if (!Configuration::getInstance().BankwiseLogic) {
|
||||
controllerCorePEQ.notify(payload, BEGIN_SREF,
|
||||
command.getStart() - sc_time_stamp());
|
||||
phase = BEGIN_SREF;
|
||||
} else
|
||||
controllerCorePEQ.notify(payload, BEGIN_SREFB,
|
||||
command.getStart() - sc_time_stamp());
|
||||
phase = BEGIN_SREFB;
|
||||
break;
|
||||
case Command::SREFX:
|
||||
if (!Configuration::getInstance().BankwiseLogic) {
|
||||
controllerCorePEQ.notify(payload, END_SREF,
|
||||
command.getStart() - sc_time_stamp());
|
||||
phase = END_SREF;
|
||||
} else
|
||||
controllerCorePEQ.notify(payload, END_SREFB,
|
||||
command.getStart() - sc_time_stamp());
|
||||
phase = END_SREFB;
|
||||
break;
|
||||
default:
|
||||
SC_REPORT_FATAL(0, "unsupported command was sent by controller");
|
||||
break;
|
||||
}
|
||||
|
||||
sc_time notDelay = command.getStart() - sc_time_stamp();
|
||||
printDebugMessage(phaseNameToString(phase) + " notification in " +
|
||||
notDelay.to_string());
|
||||
controllerCorePEQ.notify(payload, phase, notDelay);
|
||||
}
|
||||
|
||||
//Trigger the next planned refresh or the power down mode on the DRAM
|
||||
@@ -191,14 +160,20 @@ void Controller::send(Trigger trigger, sc_time time,
|
||||
{
|
||||
sc_assert(time >= sc_time_stamp());
|
||||
|
||||
sc_time delay = time - sc_time_stamp();
|
||||
tlm_phase phase;
|
||||
|
||||
if (trigger == Trigger::REFTrigger) {
|
||||
controllerCorePEQ.notify(payload, REF_TRIGGER, delay);
|
||||
phase = REF_TRIGGER;
|
||||
} else if (trigger == Trigger::PDNTrigger) {
|
||||
controllerCorePEQ.notify(payload, PDN_TRIGGER, delay);
|
||||
phase = PDN_TRIGGER;
|
||||
} else {
|
||||
SC_REPORT_FATAL("controller wrapper", "unknown trigger");
|
||||
}
|
||||
|
||||
sc_time delay = time - sc_time_stamp();
|
||||
printDebugMessage(phaseNameToString(phase) + " notification in " +
|
||||
delay.to_string());
|
||||
controllerCorePEQ.notify(payload, phase, delay);
|
||||
}
|
||||
|
||||
void Controller::controllerCorePEQCallback(tlm_generic_payload &payload,
|
||||
@@ -237,63 +212,33 @@ void Controller::controllerCorePEQCallback(tlm_generic_payload &payload,
|
||||
}
|
||||
else
|
||||
SC_REPORT_FATAL(0,
|
||||
"refreshTriggerPEQCallback queue in controller wrapper was triggered with unsupported phase");
|
||||
"Controller Core PEQ 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;
|
||||
|
||||
unsigned int thr = DramExtension::getExtension(payload).getThread().ID();
|
||||
unsigned int ch = DramExtension::getExtension(payload).getChannel().ID();
|
||||
unsigned int bg = DramExtension::getExtension(payload).getBankGroup().ID();
|
||||
unsigned int bank = DramExtension::getExtension(payload).getBank().ID();
|
||||
unsigned int row = DramExtension::getExtension(payload).getRow().ID();
|
||||
unsigned int col = DramExtension::getExtension(payload).getColumn().ID();
|
||||
sc_time notDelay = fwDelay;
|
||||
|
||||
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) + " thread " + to_string(thr) + " channel " + to_string(
|
||||
ch) + " bank group " + to_string(bg) + " bank " + to_string(
|
||||
bank) + " row " + to_string(row) + " column " + to_string(
|
||||
col) + " at " + recTime.to_string() + " notification in " +
|
||||
notDelay.to_string());
|
||||
|
||||
tlmRecorder->recordPhase(payload, phase, recTime);
|
||||
frontendPEQ.notify(payload, phase, notDelay);
|
||||
notDelay += Configuration::getInstance().memSpec.clk;
|
||||
|
||||
//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) + " thread " + to_string(thr) + " channel " + to_string(
|
||||
ch) + " bank group " + to_string(bg) + " bank " + to_string(
|
||||
bank) + " row " + to_string(row) + " column " + to_string(
|
||||
col) + " 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);
|
||||
|
||||
}
|
||||
|
||||
printDebugMessage("[fw] " + phaseNameToString(phase) + " notification in " +
|
||||
notDelay.to_string());
|
||||
frontendPEQ.notify(payload, phase, notDelay);
|
||||
|
||||
return TLM_ACCEPTED;
|
||||
}
|
||||
|
||||
@@ -319,7 +264,7 @@ void Controller::frontendPEQCallback(tlm_generic_payload &payload,
|
||||
payload.set_response_status(tlm::TLM_OK_RESPONSE);
|
||||
sendToFrontend(payload, END_REQ, SC_ZERO_TIME);
|
||||
|
||||
scheduler->schedule(&payload);
|
||||
scheduler->storeRequest(&payload);
|
||||
scheduleNextFromScheduler(DramExtension::getExtension(payload).getBank());
|
||||
} else if (phase == PendingRequest) {
|
||||
// Schedule a pending request.
|
||||
@@ -330,7 +275,7 @@ void Controller::frontendPEQCallback(tlm_generic_payload &payload,
|
||||
backpressure->set_response_status(tlm::TLM_OK_RESPONSE);
|
||||
sendToFrontend(*backpressure, END_REQ, SC_ZERO_TIME);
|
||||
|
||||
scheduler->schedule(backpressure);
|
||||
scheduler->storeRequest(backpressure);
|
||||
scheduleNextFromScheduler(DramExtension::getExtension(backpressure).getBank());
|
||||
backpressure = NULL;
|
||||
}
|
||||
@@ -339,7 +284,7 @@ void Controller::frontendPEQCallback(tlm_generic_payload &payload,
|
||||
payload.release();
|
||||
} else {
|
||||
SC_REPORT_FATAL(0,
|
||||
"Frontend PEQ event queue in controller wrapper was triggered with unknown phase");
|
||||
"Front-end PEQ in controller wrapper was triggered with unknown phase");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -381,7 +326,6 @@ unsigned int Controller::getTotalNumberOfPayloadsInSystem()
|
||||
|
||||
void Controller::scheduleNextFromScheduler(Bank bank)
|
||||
{
|
||||
|
||||
if (controllerCore->bankIsBusy(bank)) {
|
||||
return;
|
||||
}
|
||||
@@ -390,11 +334,7 @@ void Controller::scheduleNextFromScheduler(Bank bank)
|
||||
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) + "]");
|
||||
schedule(nextRequest.first, *nextRequest.second);
|
||||
} else {
|
||||
gp *pendingRequest = scheduler->getPendingRequest(bank);
|
||||
if (pendingRequest != NULL) {
|
||||
@@ -412,11 +352,7 @@ void Controller::scheduleNextFromScheduler(Bank bank)
|
||||
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)");
|
||||
schedule(nextRequest.first, *nextRequest.second);
|
||||
} else {
|
||||
gp *pendingRequest = scheduler->getPendingRequest(bank);
|
||||
if (pendingRequest != NULL) {
|
||||
@@ -433,6 +369,16 @@ void Controller::scheduleNextFromScheduler(Bank bank)
|
||||
blockedRequests = blocked;
|
||||
}
|
||||
|
||||
void Controller::schedule(Command command, gp &payload)
|
||||
{
|
||||
controllerCore->powerDownManager->wakeUp(DramExtension::getBank(payload),
|
||||
sc_time_stamp());
|
||||
if (controllerCore->scheduleRequest(command, payload)) {
|
||||
printDebugMessage("\t-> Next payload was scheduled by core [" + commandToString(
|
||||
command) + "] (unblocked)");
|
||||
}
|
||||
}
|
||||
|
||||
void Controller::sendToFrontend(tlm_generic_payload &payload,
|
||||
const tlm_phase &phase, const sc_time &delay)
|
||||
{
|
||||
@@ -444,26 +390,9 @@ void Controller::sendToFrontend(tlm_generic_payload &payload,
|
||||
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;
|
||||
|
||||
unsigned int thr = DramExtension::getExtension(payload).getThread().ID();
|
||||
unsigned int ch = DramExtension::getExtension(payload).getChannel().ID();
|
||||
unsigned int bg = DramExtension::getExtension(payload).getBankGroup().ID();
|
||||
unsigned int bank = DramExtension::getExtension(payload).getBank().ID();
|
||||
unsigned int row = DramExtension::getExtension(payload).getRow().ID();
|
||||
unsigned int col = DramExtension::getExtension(payload).getColumn().ID();
|
||||
|
||||
printDebugMessage("[bw] Recording " + phaseNameToString(
|
||||
phase) + " thread " + to_string(thr) + " channel " + to_string(
|
||||
ch) + " bank group " + to_string(bg) + " bank " + to_string(
|
||||
bank) + " row " + to_string(row) + " column " + to_string(
|
||||
col) + " at " + recTime.to_string() + " notification in " +
|
||||
notDelay.to_string());
|
||||
|
||||
dramPEQ.notify(payload, phase, notDelay);
|
||||
tlmRecorder->recordPhase(payload, phase, recTime);
|
||||
|
||||
printDebugMessage("[bw] " + phaseNameToString(phase) + " notification in " +
|
||||
bwDelay.to_string());
|
||||
dramPEQ.notify(payload, phase, bwDelay);
|
||||
return TLM_ACCEPTED;
|
||||
}
|
||||
|
||||
@@ -510,7 +439,7 @@ void Controller::dramPEQCallback(tlm_generic_payload &payload,
|
||||
// scheduler implementation)
|
||||
} else {
|
||||
string str =
|
||||
string("dramPEQCallback queue in controller wrapper was triggered with unsupported phase ")
|
||||
string("DRAM PEQ in controller wrapper was triggered with unsupported phase ")
|
||||
+ phaseNameToString(phase);
|
||||
SC_REPORT_FATAL(0, str.c_str());
|
||||
}
|
||||
|
||||
@@ -80,11 +80,11 @@ DECLARE_EXTENDED_PHASE(PendingRequest);
|
||||
class Controller: public sc_module, public IController
|
||||
{
|
||||
public:
|
||||
Controller(sc_module_name /*name*/, TlmRecorder *rec) :
|
||||
Controller(sc_module_name /*name*/) :
|
||||
frontendPEQ(this, &Controller::frontendPEQCallback), dramPEQ(this,
|
||||
&Controller::dramPEQCallback), controllerCorePEQ(this,
|
||||
&Controller::controllerCorePEQCallback),
|
||||
debugManager(DebugManager::getInstance()), tlmRecorder(rec)
|
||||
debugManager(DebugManager::getInstance())
|
||||
{
|
||||
controllerCore = new ControllerCore("core", *this, numberOfPayloadsInSystem);
|
||||
buildScheduler();
|
||||
@@ -121,27 +121,28 @@ public:
|
||||
return controllerThreadId;
|
||||
}
|
||||
|
||||
private:
|
||||
protected:
|
||||
void buildScheduler();
|
||||
void payloadEntersSystem(tlm_generic_payload &payload);
|
||||
void payloadLeavesSystem(tlm_generic_payload &payload);
|
||||
|
||||
// --- FRONTEND ------
|
||||
tlm_sync_enum nb_transport_fw(tlm_generic_payload &payload, tlm_phase &phase,
|
||||
sc_time &fwDelay);
|
||||
virtual tlm_sync_enum nb_transport_fw(tlm_generic_payload &payload,
|
||||
tlm_phase &phase, sc_time &fwDelay);
|
||||
virtual unsigned int transport_dbg(tlm::tlm_generic_payload &trans);
|
||||
void frontendPEQCallback(tlm_generic_payload &payload, const tlm_phase &phase);
|
||||
void sendToFrontend(tlm_generic_payload &payload, const tlm_phase &phase,
|
||||
const sc_time &delay);
|
||||
virtual 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);
|
||||
virtual 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 ---------
|
||||
virtual void schedule(Command command, gp &payload);
|
||||
void controllerCorePEQCallback(tlm_generic_payload &payload,
|
||||
const tlm_phase &phase);
|
||||
|
||||
@@ -161,7 +162,6 @@ private:
|
||||
tlm_utils::peq_with_cb_and_phase<Controller> controllerCorePEQ;
|
||||
|
||||
DebugManager &debugManager;
|
||||
TlmRecorder *tlmRecorder;
|
||||
|
||||
// Bandwidth realted:
|
||||
sc_time idleStart;
|
||||
|
||||
92
DRAMSys/library/src/controller/RecordableController.cpp
Normal file
92
DRAMSys/library/src/controller/RecordableController.cpp
Normal file
@@ -0,0 +1,92 @@
|
||||
/*
|
||||
* Copyright (c) 2018, 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:
|
||||
* Felipe S. Prado
|
||||
* Matthias Jung
|
||||
*/
|
||||
|
||||
#include "RecordableController.h"
|
||||
|
||||
tlm_sync_enum RecordableController::nb_transport_fw(tlm_generic_payload
|
||||
&payload, tlm_phase &phase, sc_time &fwDelay)
|
||||
{
|
||||
recordPhase(payload, phase, fwDelay);
|
||||
|
||||
return Controller::nb_transport_fw(payload, phase, fwDelay);
|
||||
}
|
||||
|
||||
void RecordableController::sendToFrontend(tlm_generic_payload &payload,
|
||||
const tlm_phase &phase, const sc_time &delay)
|
||||
{
|
||||
recordPhase(payload, phase, delay);
|
||||
|
||||
Controller::sendToFrontend(payload, phase, delay);
|
||||
}
|
||||
|
||||
tlm_sync_enum RecordableController::nb_transport_bw(tlm_generic_payload
|
||||
&payload, tlm_phase &phase, sc_time &bwDelay)
|
||||
{
|
||||
recordPhase(payload, phase, bwDelay);
|
||||
|
||||
return Controller::nb_transport_bw(payload, phase, bwDelay);
|
||||
}
|
||||
|
||||
void RecordableController::recordPhase(tlm::tlm_generic_payload &trans,
|
||||
tlm::tlm_phase phase, sc_time delay)
|
||||
{
|
||||
sc_time recTime = delay + sc_time_stamp();
|
||||
|
||||
unsigned int thr = DramExtension::getExtension(trans).getThread().ID();
|
||||
unsigned int ch = DramExtension::getExtension(trans).getChannel().ID();
|
||||
unsigned int bg = DramExtension::getExtension(trans).getBankGroup().ID();
|
||||
unsigned int bank = DramExtension::getExtension(trans).getBank().ID();
|
||||
unsigned int row = DramExtension::getExtension(trans).getRow().ID();
|
||||
unsigned int col = DramExtension::getExtension(trans).getColumn().ID();
|
||||
|
||||
printDebugMessage("Recording " + phaseNameToString(phase) + " thread " +
|
||||
to_string(thr) + " channel " + to_string(ch) + " bank group " + to_string(
|
||||
bg) + " bank " + to_string(bank) + " row " + to_string(row) + " column " +
|
||||
to_string(col) + " at " + recTime.to_string());
|
||||
|
||||
tlmRecorder->recordPhase(trans, phase, recTime);
|
||||
}
|
||||
|
||||
void RecordableController::schedule(Command command, gp &payload)
|
||||
{
|
||||
Controller::schedule(command, payload);
|
||||
if (commandIsIn(command, {Command::Read, Command::ReadA, Command::Write, Command::WriteA})) {
|
||||
ScheduledCommand scheduledCommand = controllerCore->state->getLastCommand(
|
||||
command, DramExtension::getBank(payload));
|
||||
TimeInterval dataStrobe = scheduledCommand.getIntervalOnDataStrobe();
|
||||
tlmRecorder->updateDataStrobe(dataStrobe.start, dataStrobe.end, payload);
|
||||
}
|
||||
}
|
||||
64
DRAMSys/library/src/controller/RecordableController.h
Normal file
64
DRAMSys/library/src/controller/RecordableController.h
Normal file
@@ -0,0 +1,64 @@
|
||||
/*
|
||||
* Copyright (c) 2018, 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:
|
||||
* Felipe S. Prado
|
||||
* Matthias Jung
|
||||
*/
|
||||
|
||||
#ifndef RECORDABLECONTROLLER_H
|
||||
#define RECORDABLECONTROLLER_H
|
||||
|
||||
#include "Controller.h"
|
||||
|
||||
struct RecordableController: public Controller {
|
||||
public:
|
||||
RecordableController(sc_module_name name, TlmRecorder *rec) :
|
||||
Controller(name), tlmRecorder(rec)
|
||||
{
|
||||
}
|
||||
|
||||
protected:
|
||||
TlmRecorder *tlmRecorder;
|
||||
|
||||
virtual tlm_sync_enum nb_transport_fw(tlm_generic_payload &payload,
|
||||
tlm_phase &phase, sc_time &fwDelay) override;
|
||||
virtual tlm_sync_enum nb_transport_bw(tlm_generic_payload &payload,
|
||||
tlm_phase &phase, sc_time &bwDelay) override;
|
||||
virtual void sendToFrontend(tlm_generic_payload &payload,
|
||||
const tlm_phase &phase, const sc_time &delay) override;
|
||||
virtual void schedule(Command command, tlm_generic_payload &payload) override;
|
||||
|
||||
void recordPhase(tlm::tlm_generic_payload &trans, tlm::tlm_phase phase,
|
||||
sc_time delay);
|
||||
};
|
||||
|
||||
#endif // RECORDABLECONTROLLER_H
|
||||
@@ -166,7 +166,7 @@ void ControllerCore::triggerRefresh(tlm::tlm_generic_payload &payload)
|
||||
}
|
||||
}
|
||||
|
||||
void ControllerCore::scheduleRequest(Command command,
|
||||
bool ControllerCore::scheduleRequest(Command command,
|
||||
tlm::tlm_generic_payload &payload)
|
||||
{
|
||||
sc_time start = clkAlign(sc_time_stamp());
|
||||
@@ -175,13 +175,16 @@ void ControllerCore::scheduleRequest(Command command,
|
||||
if (config.ControllerCoreDisableRefresh == true) {
|
||||
state->change(scheduledCommand);
|
||||
controller.send(scheduledCommand, payload);
|
||||
return true;
|
||||
} else {
|
||||
if (!((command == Command::Precharge || command == Command::Activate)
|
||||
&& refreshManager->hasCollision(scheduledCommand))) {
|
||||
state->change(scheduledCommand);
|
||||
controller.send(scheduledCommand, payload);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
ScheduledCommand ControllerCore::schedule(Command command, sc_time start,
|
||||
@@ -236,7 +239,6 @@ bool ControllerCore::bankIsBusy(Bank bank)
|
||||
SC_REPORT_FATAL("Core", "Last command unkown");
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
const std::vector<Bank> &ControllerCore::getBanks()
|
||||
|
||||
@@ -58,7 +58,7 @@ public:
|
||||
std::map<Bank, int> &numberOfPayloads);
|
||||
virtual ~ControllerCore();
|
||||
|
||||
void scheduleRequest(Command command, tlm::tlm_generic_payload &payload);
|
||||
bool scheduleRequest(Command command, tlm::tlm_generic_payload &payload);
|
||||
void triggerRefresh(tlm::tlm_generic_payload &payload);
|
||||
|
||||
const std::vector<Bank> &getBanks();
|
||||
|
||||
@@ -172,7 +172,6 @@ void PowerDownManager::sendPowerDownPayload(ScheduledCommand &pdnToSend)
|
||||
pdnToSend.getCommand()) + " on bank " + to_string(pdnToSend.getBank().ID()) +
|
||||
" start time " + pdnToSend.getStart().to_string() + " end time " +
|
||||
pdnToSend.getEnd().to_string());
|
||||
|
||||
}
|
||||
|
||||
void PowerDownManager::setPowerDownState(PowerDownState state)
|
||||
|
||||
@@ -45,7 +45,6 @@ bool ScheduledCommand::isNoCommand() const
|
||||
&& executionTime == SC_ZERO_TIME && end == SC_ZERO_TIME);
|
||||
}
|
||||
|
||||
|
||||
bool ScheduledCommand::isValidCommand() const
|
||||
{
|
||||
return !isNoCommand();
|
||||
|
||||
@@ -62,7 +62,6 @@ public:
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
ScheduledCommand() :
|
||||
command(Command::NOP), start(SC_ZERO_TIME), executionTime(SC_ZERO_TIME),
|
||||
end(SC_ZERO_TIME), extension()
|
||||
|
||||
@@ -38,7 +38,7 @@
|
||||
|
||||
using namespace std;
|
||||
|
||||
void Fifo::schedule(gp *payload)
|
||||
void Fifo::storeRequest(gp *payload)
|
||||
{
|
||||
buffer[DramExtension::getExtension(payload).getBank()].emplace_back(payload);
|
||||
}
|
||||
|
||||
@@ -50,7 +50,7 @@ public:
|
||||
Fifo(ControllerCore &controllerCore) : IScheduler(controllerCore) {}
|
||||
virtual ~Fifo() {}
|
||||
|
||||
void schedule(gp *payload) override;
|
||||
void storeRequest(gp *payload) override;
|
||||
std::pair<Command, tlm::tlm_generic_payload *> getNextRequest(
|
||||
Bank bank) override;
|
||||
virtual gp *getPendingRequest(Bank bank) override;
|
||||
|
||||
@@ -38,7 +38,7 @@
|
||||
|
||||
#include "FifoStrict.h"
|
||||
|
||||
void FifoStrict::schedule(tlm::tlm_generic_payload *payload)
|
||||
void FifoStrict::storeRequest(tlm::tlm_generic_payload *payload)
|
||||
{
|
||||
Bank bank = DramExtension::getExtension(payload).getBank();
|
||||
buffer.push_back(std::pair<Bank, tlm::tlm_generic_payload *>(bank, payload));
|
||||
|
||||
@@ -56,7 +56,7 @@ public:
|
||||
controller(controller) {}
|
||||
virtual ~FifoStrict() {}
|
||||
|
||||
void schedule(gp *payload) override;
|
||||
void storeRequest(gp *payload) override;
|
||||
std::pair<Command, tlm::tlm_generic_payload *> getNextRequest(
|
||||
Bank bank) override;
|
||||
virtual gp *getPendingRequest(Bank bank) override;
|
||||
|
||||
@@ -58,9 +58,8 @@ using namespace std;
|
||||
// Bank6: OOOOO0XX
|
||||
// Bank7: XXXXXXXX
|
||||
|
||||
void FR_FCFS::schedule(gp *payload)
|
||||
void FR_FCFS::storeRequest(gp *payload)
|
||||
{
|
||||
|
||||
// FIXME: Question: what if the buffer is full? IMHO the schedule function
|
||||
// should provide a true or false when the placement into the buffer worked
|
||||
// out or not (?).
|
||||
|
||||
@@ -51,7 +51,7 @@ public:
|
||||
FR_FCFS(ControllerCore &controllerCore) : IScheduler(controllerCore) {}
|
||||
virtual ~FR_FCFS() {}
|
||||
|
||||
void schedule(gp *payload) override;
|
||||
void storeRequest(gp *payload) override;
|
||||
std::pair<Command, tlm::tlm_generic_payload *> getNextRequest(
|
||||
Bank bank) override;
|
||||
virtual gp *getPendingRequest(Bank bank) override;
|
||||
|
||||
@@ -52,7 +52,7 @@ public:
|
||||
virtual ~IScheduler() {}
|
||||
IScheduler(ControllerCore &controllerCore) : controllerCore(controllerCore) {}
|
||||
|
||||
virtual void schedule(gp *payload) = 0;
|
||||
virtual void storeRequest(gp *payload) = 0;
|
||||
virtual std::pair<Command, gp *> getNextRequest(Bank bank) = 0;
|
||||
virtual gp *getPendingRequest(Bank bank) = 0;
|
||||
static std::string sendername;
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
|
||||
using namespace std;
|
||||
|
||||
void SMS::schedule(gp *payload)
|
||||
void SMS::storeRequest(gp *payload)
|
||||
{
|
||||
Thread thread = DramExtension::getExtension(payload).getThread();
|
||||
bool wasEmpty = isRequestBuffersEmpty();
|
||||
|
||||
@@ -46,7 +46,7 @@ public:
|
||||
{
|
||||
}
|
||||
|
||||
virtual void schedule(gp *payload) override;
|
||||
virtual void storeRequest(gp *payload) override;
|
||||
virtual std::pair<Command, gp *> getNextRequest(Bank bank) override;
|
||||
virtual gp *getPendingRequest(Bank bank) override;
|
||||
|
||||
|
||||
@@ -79,11 +79,6 @@ public:
|
||||
tSocket.register_transport_dbg(this, &Arbiter::transport_dbg);
|
||||
}
|
||||
|
||||
void setTlmRecorders(std::vector<TlmRecorder *> recorders)
|
||||
{
|
||||
tlmRecorders = recorders;
|
||||
}
|
||||
|
||||
private:
|
||||
tlm_utils::peq_with_cb_and_phase<Arbiter> payloadEventQueue;
|
||||
|
||||
@@ -96,8 +91,6 @@ private:
|
||||
// This is a queue of responses comming from the memory side. The phase of these transactions is BEGIN_RESP.
|
||||
std::map<unsigned int, queue<tlm_generic_payload *>> receivedResponses;
|
||||
|
||||
std::vector<TlmRecorder *> tlmRecorders;
|
||||
|
||||
//used to map the transaction from devices to the arbiter's target socket ID.
|
||||
std::map<tlm_generic_payload *, int> routeMap;
|
||||
|
||||
@@ -111,15 +104,10 @@ private:
|
||||
payload).getChannel().ID()) {
|
||||
SC_REPORT_FATAL("Arbiter", "Payload extension was corrupted");
|
||||
}
|
||||
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());
|
||||
|
||||
tlmRecorders[channelId]->recordPhase(payload, phase, recTime);
|
||||
payloadEventQueue.notify(payload, phase, notDelay);
|
||||
printDebugMessage("[bw] " + phaseNameToString(phase) + " notification in " +
|
||||
bwDelay.to_string());
|
||||
payloadEventQueue.notify(payload, phase, bwDelay);
|
||||
return TLM_ACCEPTED;
|
||||
}
|
||||
|
||||
@@ -128,6 +116,8 @@ private:
|
||||
tlm_sync_enum nb_transport_fw(int id, tlm_generic_payload &payload,
|
||||
tlm_phase &phase, sc_time &fwDelay)
|
||||
{
|
||||
sc_time notDelay = clkAlign(sc_time_stamp() + fwDelay) -
|
||||
(sc_time_stamp() + fwDelay);
|
||||
if (phase == BEGIN_REQ) {
|
||||
// adjust address offset:
|
||||
payload.set_address(payload.get_address() -
|
||||
@@ -141,12 +131,15 @@ private:
|
||||
appendDramExtension(id, payload);
|
||||
payload.acquire();
|
||||
} else if (phase == END_RESP) {
|
||||
notDelay += Configuration::getInstance().memSpec.clk;
|
||||
// Erase before the payload is released.
|
||||
routeMap.erase(&payload);
|
||||
payload.release();
|
||||
}
|
||||
|
||||
payloadEventQueue.notify(payload, phase, fwDelay);
|
||||
printDebugMessage("[fw] " + phaseNameToString(phase) + " notification in " +
|
||||
notDelay.to_string());
|
||||
payloadEventQueue.notify(payload, phase, notDelay);
|
||||
return TLM_ACCEPTED;
|
||||
}
|
||||
|
||||
|
||||
@@ -198,8 +198,7 @@ void DRAMSys::setupTlmRecorders(const string &traceName,
|
||||
TlmRecorder *tlmRecorder =
|
||||
new TlmRecorder(recorderName.c_str(),
|
||||
sqlScriptURI.c_str(),
|
||||
dbName.c_str(),
|
||||
Configuration::getInstance().DatabaseRecording);
|
||||
dbName.c_str());
|
||||
tlmRecorder->recordMCconfig(Configuration::getInstance().mcconfigUri);
|
||||
tlmRecorder->recordMemspec(Configuration::getInstance().memspecUri);
|
||||
|
||||
@@ -219,7 +218,9 @@ void DRAMSys::instantiateModules(const string &traceName,
|
||||
|
||||
// Create and properly initialize TLM recorders.
|
||||
// They need to be ready before creating some modules.
|
||||
setupTlmRecorders(traceName, pathToResources);
|
||||
bool recordingEnabled = Configuration::getInstance().DatabaseRecording;
|
||||
if (recordingEnabled)
|
||||
setupTlmRecorders(traceName, pathToResources);
|
||||
|
||||
// Create new ECC Controller
|
||||
switch (Configuration::getInstance().ECCMode) {
|
||||
@@ -236,19 +237,26 @@ void DRAMSys::instantiateModules(const string &traceName,
|
||||
|
||||
// Create arbiter
|
||||
arbiter = new Arbiter("arbiter");
|
||||
arbiter->setTlmRecorders(tlmRecorders);
|
||||
|
||||
// Create DRAM
|
||||
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;
|
||||
if (recordingEnabled)
|
||||
controller = new RecordableController(str.c_str(), tlmRecorders[i]);
|
||||
else
|
||||
controller = new Controller(str.c_str());
|
||||
controllers.push_back(controller);
|
||||
|
||||
str = "dram" + std::to_string(i);
|
||||
Dram *dram = new Dram(str.c_str());
|
||||
dram->setTlmRecorder(tlmRecorders[i]);
|
||||
Dram *dram;
|
||||
if (recordingEnabled)
|
||||
dram = new RecordableDram(str.c_str(), tlmRecorders[i]);
|
||||
else
|
||||
dram = new Dram(str.c_str());
|
||||
dram->setDramController(controllers[i]);
|
||||
drams.push_back(dram);
|
||||
|
||||
|
||||
@@ -42,13 +42,13 @@
|
||||
#include <string>
|
||||
#include <systemc.h>
|
||||
|
||||
#include "Dram.h"
|
||||
#include "RecordableDram.h"
|
||||
#include "Arbiter.h"
|
||||
#include "TraceGenerator.h"
|
||||
#include "ReorderBuffer.h"
|
||||
#include <tlm_utils/multi_passthrough_target_socket.h>
|
||||
#include <tlm_utils/multi_passthrough_initiator_socket.h>
|
||||
#include "../controller/Controller.h"
|
||||
#include "../controller/RecordableController.h"
|
||||
#include "../common/third_party/tinyxml2/tinyxml2.h"
|
||||
#include "../common/tlm2_base_protocol_checker.h"
|
||||
#include "../error/eccbaseclass.h"
|
||||
|
||||
@@ -56,7 +56,6 @@
|
||||
#include "../controller/core/configuration/Configuration.h"
|
||||
#include "../common/protocol.h"
|
||||
#include "../common/Utils.h"
|
||||
#include "../common/TlmRecorder.h"
|
||||
#include "../common/third_party/DRAMPower/src/libdrampower/LibDRAMPower.h"
|
||||
#include "../error/errormodel.h"
|
||||
|
||||
@@ -72,8 +71,6 @@ struct Dram : sc_module {
|
||||
|
||||
// Power Model related
|
||||
bool powerAnalysis = Configuration::getInstance().PowerAnalysis;
|
||||
sc_time powerWindowSize = Configuration::getInstance().memSpec.clk *
|
||||
Configuration::getInstance().WindowSize;
|
||||
libDRAMPower *DRAMPower;
|
||||
|
||||
// Bandwidth realted:
|
||||
@@ -88,7 +85,6 @@ struct Dram : sc_module {
|
||||
// Data Storage:
|
||||
unsigned char *memory;
|
||||
|
||||
TlmRecorder *tlmRecorder;
|
||||
Controller *dramController;
|
||||
|
||||
SC_CTOR(Dram) : tSocket("socket")
|
||||
@@ -97,7 +93,6 @@ struct Dram : sc_module {
|
||||
bytesPerBurst = Configuration::getInstance().adjustNumBytesAfterECC(
|
||||
bytesPerBurst);
|
||||
dramController = NULL;
|
||||
tlmRecorder = NULL;
|
||||
|
||||
std::uint64_t memorySize = Configuration::getInstance().getSimMemSizeInBytes();
|
||||
// allocate and model storage of one DRAM channel using memory map
|
||||
@@ -209,11 +204,6 @@ struct Dram : sc_module {
|
||||
memSpec.memArchSpec = memArchSpec;
|
||||
|
||||
DRAMPower = new libDRAMPower( memSpec, 0 );
|
||||
|
||||
// Create a thread that is triggered every $powerWindowSize
|
||||
// to generate a Power over Time plot in the Trace analyzer:
|
||||
if (Configuration::getInstance().EnableWindowing)
|
||||
SC_THREAD(powerWindow);
|
||||
}
|
||||
|
||||
// Bandwidth Calculation:
|
||||
@@ -244,13 +234,8 @@ struct Dram : sc_module {
|
||||
~Dram()
|
||||
{
|
||||
if (powerAnalysis == true) {
|
||||
// Obtain the residual energy which was not covered by
|
||||
// previous windows
|
||||
DRAMPower->calcEnergy();
|
||||
|
||||
tlmRecorder->recordPower(sc_time_stamp().to_seconds(),
|
||||
DRAMPower->getPower().window_average_power
|
||||
* Configuration::getInstance().NumberOfDevicesOnDIMM);
|
||||
if (!Configuration::getInstance().DatabaseRecording)
|
||||
DRAMPower->calcEnergy();
|
||||
|
||||
// Print the final total energy and the average power for
|
||||
// the simulation:
|
||||
@@ -313,88 +298,18 @@ struct Dram : sc_module {
|
||||
for (auto e : ememory) {
|
||||
delete e;
|
||||
}
|
||||
|
||||
tlmRecorder->closeConnection();
|
||||
}
|
||||
|
||||
// When working with floats, we have to decide ourselves what is an
|
||||
// acceptable definition for "equal". Here the number is compared with a
|
||||
// suitable error margin (0.00001).
|
||||
bool is_equal(double a, double b, const double epsilon = 1e-05)
|
||||
{
|
||||
return std::fabs(a - b) < epsilon;
|
||||
}
|
||||
|
||||
// This Thread is only triggered when Power Simulation is enabled.
|
||||
// It estimates the current average power which will be stored in the trace database for visualization purposes.
|
||||
void powerWindow()
|
||||
{
|
||||
unsigned long long clk_cycles = 0;
|
||||
|
||||
do {
|
||||
// At the very beginning (zero clock cycles) the energy is 0, so we wait first
|
||||
wait(powerWindowSize);
|
||||
|
||||
clk_cycles = sc_time_stamp().value() /
|
||||
Configuration::getInstance().memSpec.clk.value();
|
||||
|
||||
DRAMPower->calcWindowEnergy(clk_cycles);
|
||||
|
||||
// During operation the energy should never be zero since the device is always consuming
|
||||
assert(!is_equal(DRAMPower->getEnergy().window_energy, 0.0));
|
||||
|
||||
// Store the time (in seconds) and the current average power (in mW) into the database
|
||||
tlmRecorder->recordPower(sc_time_stamp().to_seconds(),
|
||||
DRAMPower->getPower().window_average_power *
|
||||
Configuration::getInstance().NumberOfDevicesOnDIMM);
|
||||
|
||||
// Here considering that DRAMPower provides the energy in pJ and the power in mW
|
||||
printDebugMessage(string("\tWindow Energy: \t") + to_string(
|
||||
DRAMPower->getEnergy().window_energy *
|
||||
Configuration::getInstance().NumberOfDevicesOnDIMM) + string("\t[pJ]"));
|
||||
printDebugMessage(string("\tWindow Average Power: \t") + to_string(
|
||||
DRAMPower->getPower().window_average_power *
|
||||
Configuration::getInstance().NumberOfDevicesOnDIMM) + string("\t[mW]"));
|
||||
|
||||
} while (true);
|
||||
}
|
||||
|
||||
virtual tlm::tlm_sync_enum nb_transport_fw(tlm::tlm_generic_payload &payload,
|
||||
tlm::tlm_phase &phase, sc_time &delay)
|
||||
{
|
||||
// Recording time used by the traceAnalyzer
|
||||
sc_time recTime = sc_time_stamp() + delay;
|
||||
|
||||
if (numberOfTransactionsServed == 0) {
|
||||
firstAccess = sc_time_stamp();
|
||||
} else {
|
||||
lastAccess = sc_time_stamp();
|
||||
}
|
||||
|
||||
|
||||
// These are terminating phases recorded by the DRAM. The execution
|
||||
// time of the related command must be taken into consideration.
|
||||
if (phase == END_PDNA || phase == END_PDNAB) {
|
||||
recTime += getExecutionTime(Command::PDNAX, payload);
|
||||
} else if (phase == END_PDNP || phase == END_PDNPB) {
|
||||
recTime += getExecutionTime(Command::PDNPX, payload);
|
||||
} else if (phase == END_SREF || phase == END_SREFB) {
|
||||
recTime += getExecutionTime(Command::SREFX, payload);
|
||||
}
|
||||
|
||||
unsigned int thr = DramExtension::getExtension(payload).getThread().ID();
|
||||
unsigned int ch = DramExtension::getExtension(payload).getChannel().ID();
|
||||
unsigned int bg = DramExtension::getExtension(payload).getBankGroup().ID();
|
||||
unsigned int bank = DramExtension::getExtension(payload).getBank().ID();
|
||||
unsigned int row = DramExtension::getExtension(payload).getRow().ID();
|
||||
unsigned int col = DramExtension::getExtension(payload).getColumn().ID();
|
||||
|
||||
printDebugMessage("[fw] Recording " + phaseNameToString(
|
||||
phase) + " thread " + to_string(thr) + " channel " + to_string(
|
||||
ch) + " bank group " + to_string(bg) + " bank " + to_string(
|
||||
bank) + " row " + to_string(row) + " column " + to_string(
|
||||
col) + " at " + recTime.to_string());
|
||||
tlmRecorder->recordPhase(payload, phase, recTime);
|
||||
|
||||
// This is only needed for power simulation:
|
||||
unsigned long long cycle = 0;
|
||||
@@ -650,10 +565,6 @@ struct Dram : sc_module {
|
||||
DebugManager::getInstance().printDebugMessage(name(), message);
|
||||
}
|
||||
|
||||
void setTlmRecorder(TlmRecorder *rec)
|
||||
{
|
||||
tlmRecorder = rec;
|
||||
}
|
||||
void setDramController(Controller *contr)
|
||||
{
|
||||
dramController = contr;
|
||||
|
||||
152
DRAMSys/library/src/simulation/RecordableDram.h
Normal file
152
DRAMSys/library/src/simulation/RecordableDram.h
Normal file
@@ -0,0 +1,152 @@
|
||||
/*
|
||||
* Copyright (c) 2018, 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:
|
||||
* Felipe S. Prado
|
||||
* Matthias Jung
|
||||
*/
|
||||
|
||||
#ifndef RECORDABLEDRAM_H_
|
||||
#define RECORDABLEDRAM_H_
|
||||
|
||||
#include "Dram.h"
|
||||
#include "../common/TlmRecorder.h"
|
||||
|
||||
struct RecordableDram : public Dram {
|
||||
SC_HAS_PROCESS(RecordableDram);
|
||||
RecordableDram(sc_module_name name, TlmRecorder *tlmRecorder):
|
||||
Dram(name), tlmRecorder(tlmRecorder)
|
||||
{
|
||||
// Create a thread that is triggered every $powerWindowSize
|
||||
// to generate a Power over Time plot in the Trace analyzer:
|
||||
if (Configuration::getInstance().PowerAnalysis
|
||||
&& Configuration::getInstance().EnableWindowing)
|
||||
SC_THREAD(powerWindow);
|
||||
}
|
||||
|
||||
~RecordableDram()
|
||||
{
|
||||
if (Configuration::getInstance().PowerAnalysis) {
|
||||
// Obtain the residual energy which was not covered by
|
||||
// previous windows
|
||||
DRAMPower->calcEnergy();
|
||||
recordPower();
|
||||
}
|
||||
tlmRecorder->closeConnection();
|
||||
}
|
||||
|
||||
TlmRecorder *tlmRecorder;
|
||||
sc_time powerWindowSize = Configuration::getInstance().memSpec.clk *
|
||||
Configuration::getInstance().WindowSize;
|
||||
|
||||
virtual tlm::tlm_sync_enum nb_transport_fw(tlm::tlm_generic_payload &payload,
|
||||
tlm::tlm_phase &phase, sc_time &delay)
|
||||
{
|
||||
// Recording time used by the traceAnalyzer
|
||||
sc_time recTime = sc_time_stamp() + delay;
|
||||
|
||||
// These are terminating phases recorded by the DRAM. The execution
|
||||
// time of the related command must be taken into consideration.
|
||||
if (phase == END_PDNA || phase == END_PDNAB) {
|
||||
recTime += getExecutionTime(Command::PDNAX, payload);
|
||||
} else if (phase == END_PDNP || phase == END_PDNPB) {
|
||||
recTime += getExecutionTime(Command::PDNPX, payload);
|
||||
} else if (phase == END_SREF || phase == END_SREFB) {
|
||||
recTime += getExecutionTime(Command::SREFX, payload);
|
||||
}
|
||||
|
||||
unsigned int thr = DramExtension::getExtension(payload).getThread().ID();
|
||||
unsigned int ch = DramExtension::getExtension(payload).getChannel().ID();
|
||||
unsigned int bg = DramExtension::getExtension(payload).getBankGroup().ID();
|
||||
unsigned int bank = DramExtension::getExtension(payload).getBank().ID();
|
||||
unsigned int row = DramExtension::getExtension(payload).getRow().ID();
|
||||
unsigned int col = DramExtension::getExtension(payload).getColumn().ID();
|
||||
|
||||
printDebugMessage("Recording " + phaseNameToString(phase) + " thread " +
|
||||
to_string(thr) + " channel " + to_string(ch) + " bank group " + to_string(
|
||||
bg) + " bank " + to_string(bank) + " row " + to_string(row) + " column " +
|
||||
to_string(col) + " at " + recTime.to_string());
|
||||
|
||||
tlmRecorder->recordPhase(payload, phase, recTime);
|
||||
|
||||
return Dram::nb_transport_fw(payload, phase, delay);
|
||||
}
|
||||
|
||||
// When working with floats, we have to decide ourselves what is an
|
||||
// acceptable definition for "equal". Here the number is compared with a
|
||||
// suitable error margin (0.00001).
|
||||
bool is_equal(double a, double b, const double epsilon = 1e-05)
|
||||
{
|
||||
return std::fabs(a - b) < epsilon;
|
||||
}
|
||||
|
||||
// This Thread is only triggered when Power Simulation is enabled.
|
||||
// It estimates the current average power which will be stored in the trace database for visualization purposes.
|
||||
void powerWindow()
|
||||
{
|
||||
unsigned long long clk_cycles = 0;
|
||||
|
||||
do {
|
||||
// At the very beginning (zero clock cycles) the energy is 0, so we wait first
|
||||
wait(powerWindowSize);
|
||||
|
||||
clk_cycles = sc_time_stamp().value() /
|
||||
Configuration::getInstance().memSpec.clk.value();
|
||||
|
||||
DRAMPower->calcWindowEnergy(clk_cycles);
|
||||
|
||||
// During operation the energy should never be zero since the device is always consuming
|
||||
assert(!is_equal(DRAMPower->getEnergy().window_energy, 0.0));
|
||||
|
||||
// Store the time (in seconds) and the current average power (in mW) into the database
|
||||
recordPower();
|
||||
|
||||
// Here considering that DRAMPower provides the energy in pJ and the power in mW
|
||||
printDebugMessage(string("\tWindow Energy: \t") + to_string(
|
||||
DRAMPower->getEnergy().window_energy *
|
||||
Configuration::getInstance().NumberOfDevicesOnDIMM) + string("\t[pJ]"));
|
||||
printDebugMessage(string("\tWindow Average Power: \t") + to_string(
|
||||
DRAMPower->getPower().window_average_power *
|
||||
Configuration::getInstance().NumberOfDevicesOnDIMM) + string("\t[mW]"));
|
||||
|
||||
} while (true);
|
||||
}
|
||||
|
||||
void recordPower()
|
||||
{
|
||||
tlmRecorder->recordPower(sc_time_stamp().to_seconds(),
|
||||
DRAMPower->getPower().window_average_power
|
||||
* Configuration::getInstance().NumberOfDevicesOnDIMM);
|
||||
}
|
||||
};
|
||||
|
||||
#endif /* RECORDABLEDRAM_H_ */
|
||||
|
||||
Reference in New Issue
Block a user