...
This commit is contained in:
@@ -2,9 +2,10 @@
|
||||
#include "protocol.h"
|
||||
#include "dramExtension.h"
|
||||
#include "xmlAddressdecoder.h"
|
||||
#include "Utils.h"
|
||||
#include "../controller/core/configuration/Configuration.h"
|
||||
#include <iostream>
|
||||
#include <algorithm>
|
||||
#include <boost/filesystem.hpp>
|
||||
|
||||
using namespace std;
|
||||
|
||||
@@ -12,14 +13,24 @@ string TlmRecorder::dbName = "";
|
||||
string TlmRecorder::sqlScriptURI = "";
|
||||
string TlmRecorder::senderName = "TlmRecorder";
|
||||
|
||||
|
||||
// ------------- public -----------------------
|
||||
|
||||
TlmRecorder::TlmRecorder() :
|
||||
transactionIDCounter(1), recordingEndTime(SC_ZERO_TIME)
|
||||
transactionIDCounter(1), recordingEndTime(SC_ZERO_TIME)
|
||||
{
|
||||
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();
|
||||
sqlite3_exec(db, "BEGIN", 0, 0, 0);
|
||||
|
||||
printDebugMessage("Starting new database transaction");
|
||||
}
|
||||
@@ -30,10 +41,30 @@ TlmRecorder::~TlmRecorder()
|
||||
closeConnection();
|
||||
}
|
||||
|
||||
void TlmRecorder::recordDummy(tlm::tlm_generic_payload& trans)
|
||||
{
|
||||
// static unsigned int id = 0;
|
||||
// RecordingData data(id);
|
||||
|
||||
// insertTransactionInDB(data,trans);
|
||||
// insertRangeInDB(id,SC_ZERO_TIME,SC_ZERO_TIME);
|
||||
// for(int i=0;i<5;i++)
|
||||
// {
|
||||
// string phaseName("Phase " + to_string(id));
|
||||
// sqlite3_bind_text(insertPhaseStatement, 1, phaseName.c_str(), phaseName.length(), 0);
|
||||
// sqlite3_bind_int64(insertPhaseStatement, 2, 0);
|
||||
// sqlite3_bind_int64(insertPhaseStatement, 3, 2);
|
||||
// sqlite3_bind_int(insertPhaseStatement, 4, id);
|
||||
// executeSqlStatement(insertPhaseStatement);
|
||||
// }
|
||||
|
||||
// id++;
|
||||
}
|
||||
|
||||
void TlmRecorder::recordPhase(tlm::tlm_generic_payload& trans, tlm::tlm_phase phase, sc_time time)
|
||||
{
|
||||
if (currentTransactionsInSystem.count(&trans) == 0)
|
||||
introduceNewTransactionToSystem(time, trans);
|
||||
introduceNewTransactionToSystem(trans);
|
||||
|
||||
string phaseName = phaseNameToString(phase);
|
||||
string phaseBeginPrefix = "BEGIN_";
|
||||
@@ -42,27 +73,125 @@ void TlmRecorder::recordPhase(tlm::tlm_generic_payload& trans, tlm::tlm_phase ph
|
||||
if (phaseName.find(phaseBeginPrefix) != string::npos)
|
||||
{
|
||||
phaseName.erase(0, phaseBeginPrefix.length());
|
||||
insertPhaseInDB(phaseName, time, time, trans);
|
||||
assert(currentTransactionsInSystem.count(&trans) != 0);
|
||||
currentTransactionsInSystem[&trans].insertPhase(phaseName,time);
|
||||
}
|
||||
else
|
||||
{
|
||||
phaseName.erase(0, phaseEndPrefix.length());
|
||||
updatePhaseEndInDB(phaseName, time, trans);
|
||||
assert(currentTransactionsInSystem.count(&trans) != 0);
|
||||
currentTransactionsInSystem[&trans].setPhaseEnd(phaseName,time);
|
||||
}
|
||||
|
||||
bool phaseTerminatesTransaction = count(transactionTerminatingPhases.begin(),
|
||||
transactionTerminatingPhases.end(), phase) == 1;
|
||||
transactionTerminatingPhases.end(), phase) == 1;
|
||||
if (phaseTerminatesTransaction)
|
||||
removeTransactionFromSystem(time, trans);
|
||||
removeTransactionFromDBAndInsertInDB(trans);
|
||||
|
||||
recordingEndTime = time;
|
||||
}
|
||||
|
||||
|
||||
void TlmRecorder::updateDataStrobe(const sc_time& begin,const sc_time& end, tlm::tlm_generic_payload& trans)
|
||||
{
|
||||
assert(currentTransactionsInSystem.count(&trans) != 0);
|
||||
currentTransactionsInSystem[&trans].timeOnDataStrobe.start = begin;
|
||||
currentTransactionsInSystem[&trans].timeOnDataStrobe.end = end;
|
||||
}
|
||||
|
||||
|
||||
void TlmRecorder::recordDebugMessage(std::string message, sc_time time)
|
||||
{
|
||||
insertDebugMessageInDB(message, time);
|
||||
}
|
||||
|
||||
|
||||
// ------------- internal -----------------------
|
||||
|
||||
void TlmRecorder::introduceNewTransactionToSystem(tlm::tlm_generic_payload& trans)
|
||||
{
|
||||
unsigned int id = transactionIDCounter++;
|
||||
currentTransactionsInSystem[&trans].id = id;
|
||||
currentTransactionsInSystem[&trans].address = trans.get_address();
|
||||
currentTransactionsInSystem[&trans].burstlength = trans.get_streaming_width();
|
||||
currentTransactionsInSystem[&trans].dramExtension = DramExtension::getExtension(trans);
|
||||
|
||||
if(DramExtension::getExtension(trans).getThread().ID() == 0)
|
||||
currentTransactionsInSystem[&trans].timeOfGeneration = SC_ZERO_TIME;
|
||||
else
|
||||
currentTransactionsInSystem[&trans].timeOfGeneration = GenerationExtension::getExtension(&trans).TimeOfGeneration();
|
||||
|
||||
if (id % transactionCommitRate == 0)
|
||||
{
|
||||
printDebugMessage(
|
||||
"Committing transactions " + to_string(id - transactionCommitRate + 1) + " - "
|
||||
+ to_string(id));
|
||||
commitRecordedDataToDB();
|
||||
}
|
||||
}
|
||||
|
||||
void TlmRecorder::removeTransactionFromDBAndInsertInDB(tlm::tlm_generic_payload& trans)
|
||||
{
|
||||
assert(currentTransactionsInSystem.count(&trans) != 0);
|
||||
|
||||
RecordingData& recordingData = currentTransactionsInSystem[&trans];
|
||||
recordedData.push_back(recordingData);
|
||||
currentTransactionsInSystem.erase(&trans);
|
||||
}
|
||||
|
||||
void TlmRecorder::commitRecordedDataToDB()
|
||||
{
|
||||
sqlite3_exec(db, "BEGIN;", 0, 0, 0);
|
||||
for(RecordingData& recordingData: recordedData)
|
||||
{
|
||||
assert(recordingData.recordedPhases.size() > 0);
|
||||
insertTransactionInDB(recordingData);
|
||||
for(RecordingData::PhaseData& phaseData: recordingData.recordedPhases)
|
||||
{
|
||||
insertPhaseInDB(phaseData.name,phaseData.interval.start,phaseData.interval.end,recordingData.id);
|
||||
}
|
||||
|
||||
sc_time rangeBegin = recordingData.recordedPhases.front().interval.start;
|
||||
sc_time rangeEnd = recordingData.recordedPhases.back().interval.end;
|
||||
insertRangeInDB(recordingData.id,rangeBegin,rangeEnd);
|
||||
}
|
||||
|
||||
sqlite3_exec(db, "COMMIT;", 0, 0, 0);
|
||||
recordedData.clear();
|
||||
}
|
||||
|
||||
|
||||
void TlmRecorder::RecordingData::insertPhase(string name, sc_time begin)
|
||||
{
|
||||
recordedPhases.push_back(PhaseData(name,begin));
|
||||
}
|
||||
|
||||
void TlmRecorder::RecordingData::setPhaseEnd(string name, sc_time end)
|
||||
{
|
||||
for(PhaseData& data: recordedPhases)
|
||||
{
|
||||
if(data.name == name)
|
||||
{
|
||||
data.interval.end = end;
|
||||
return;
|
||||
}
|
||||
}
|
||||
SC_REPORT_FATAL("Recording Error", "While trying to set phase end: phaseBegin has not been recorded");
|
||||
}
|
||||
|
||||
void TlmRecorder::openDB(std::string name)
|
||||
{
|
||||
boost::filesystem::wpath file(name);
|
||||
if(boost::filesystem::exists(file))
|
||||
boost::filesystem::remove(file);
|
||||
if (sqlite3_open(name.c_str(), &db))
|
||||
{
|
||||
SC_REPORT_FATAL("Error in TraceRecorder", "Error cannot open database");
|
||||
sqlite3_close(db);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void TlmRecorder::createTables(string pathToURI)
|
||||
{
|
||||
string initial = loadTextFileContents(pathToURI);
|
||||
@@ -95,23 +224,14 @@ void TlmRecorder::prepareSqlStatements()
|
||||
"(:numberOfTransactions,:end,:numberOfBanks,:clk,:unitOfTime,:memconfig,:memspec,:traces)";
|
||||
insertDebugMessageString = "INSERT INTO DebugMessages (Time,Message) Values (:time,:message)";
|
||||
|
||||
sqlite3_prepare(db, insertTransactionString.c_str(), -1, &insertTransactionStatement, 0);
|
||||
sqlite3_prepare(db, insertRangeString.c_str(), -1, &insertRangeStatement, 0);
|
||||
sqlite3_prepare(db, updateRangeString.c_str(), -1, &updateRangeStatement, 0);
|
||||
sqlite3_prepare(db, insertPhaseString.c_str(), -1, &insertPhaseStatement, 0);
|
||||
sqlite3_prepare(db, updatePhaseString.c_str(), -1, &updatePhaseStatement, 0);
|
||||
sqlite3_prepare(db, updateDataStrobeString.c_str(), -1, &updateDataStrobeStatement, 0);
|
||||
sqlite3_prepare(db, insertGeneralInfoString.c_str(), -1, &insertGeneralInfoStatement, 0);
|
||||
sqlite3_prepare(db, insertDebugMessageString.c_str(), -1, &insertDebugMessageStatement, 0);
|
||||
}
|
||||
|
||||
void TlmRecorder::openDB(std::string name)
|
||||
{
|
||||
if (sqlite3_open(name.c_str(), &db))
|
||||
{
|
||||
SC_REPORT_FATAL("Error in TraceRecorder", "Error cannot open database");
|
||||
sqlite3_close(db);
|
||||
}
|
||||
sqlite3_prepare_v2(db, insertTransactionString.c_str(), -1, &insertTransactionStatement, 0);
|
||||
sqlite3_prepare_v2(db, insertRangeString.c_str(), -1, &insertRangeStatement, 0);
|
||||
sqlite3_prepare_v2(db, updateRangeString.c_str(), -1, &updateRangeStatement, 0);
|
||||
sqlite3_prepare_v2(db, insertPhaseString.c_str(), -1, &insertPhaseStatement, 0);
|
||||
sqlite3_prepare_v2(db, updatePhaseString.c_str(), -1, &updatePhaseStatement, 0);
|
||||
sqlite3_prepare_v2(db, updateDataStrobeString.c_str(), -1, &updateDataStrobeStatement, 0);
|
||||
sqlite3_prepare_v2(db, insertGeneralInfoString.c_str(), -1, &insertGeneralInfoStatement, 0);
|
||||
sqlite3_prepare_v2(db, insertDebugMessageString.c_str(), -1, &insertDebugMessageStatement, 0);
|
||||
}
|
||||
|
||||
void TlmRecorder::insertDebugMessageInDB(string message, const sc_time& time)
|
||||
@@ -126,7 +246,7 @@ void TlmRecorder::insertGeneralInfo()
|
||||
sqlite3_bind_int64(insertGeneralInfoStatement, 1, transactionIDCounter - 1);
|
||||
sqlite3_bind_int64(insertGeneralInfoStatement, 2, recordingEndTime.value());
|
||||
sqlite3_bind_int(insertGeneralInfoStatement, 3,
|
||||
core::Configuration::getInstance().NumberOfBanks);
|
||||
core::Configuration::getInstance().NumberOfBanks);
|
||||
sqlite3_bind_int(insertGeneralInfoStatement, 4, core::Configuration::getInstance().Timings.clk.value());
|
||||
sqlite3_bind_text(insertGeneralInfoStatement, 5, "PS", 2, NULL);
|
||||
sqlite3_bind_text(insertGeneralInfoStatement, 6, memconfig.c_str(), memconfig.length(), NULL);
|
||||
@@ -134,102 +254,54 @@ void TlmRecorder::insertGeneralInfo()
|
||||
sqlite3_bind_text(insertGeneralInfoStatement, 8, traces.c_str(), traces.length(), NULL);
|
||||
executeSqlStatement(insertGeneralInfoStatement);
|
||||
}
|
||||
void TlmRecorder::insertTransactionInDB(unsigned int id, tlm::tlm_generic_payload& trans)
|
||||
|
||||
void TlmRecorder::insertTransactionInDB(RecordingData& recordingData)
|
||||
{
|
||||
sqlite3_bind_int(insertTransactionStatement, 1, id);
|
||||
sqlite3_bind_int(insertTransactionStatement, 2, id);
|
||||
sqlite3_bind_int(insertTransactionStatement, 3, trans.get_address());
|
||||
sqlite3_bind_int(insertTransactionStatement, 4, trans.get_streaming_width());
|
||||
|
||||
|
||||
const DramExtension& extension = DramExtension::getExtension(trans);
|
||||
sqlite3_bind_int(insertTransactionStatement, 5, extension.getThread().ID());
|
||||
sqlite3_bind_int(insertTransactionStatement, 6, extension.getChannel().ID());
|
||||
sqlite3_bind_int(insertTransactionStatement, 7, extension.getBank().ID());
|
||||
sqlite3_bind_int(insertTransactionStatement, 8, extension.getBankGroup().ID());
|
||||
sqlite3_bind_int(insertTransactionStatement, 9, extension.getRow().ID());
|
||||
sqlite3_bind_int(insertTransactionStatement, 10, extension.getColumn().ID());
|
||||
sqlite3_bind_int(insertTransactionStatement, 11, 0);
|
||||
sqlite3_bind_int(insertTransactionStatement, 12, 0);
|
||||
|
||||
if(extension.getThread().ID() == 0)
|
||||
sqlite3_bind_int64(insertTransactionStatement, 13, 0);
|
||||
else
|
||||
sqlite3_bind_int64(insertTransactionStatement, 13, GenerationExtension::getExtension(&trans).TimeOfGeneration().value());
|
||||
sqlite3_bind_int(insertTransactionStatement, 1, recordingData.id);
|
||||
sqlite3_bind_int(insertTransactionStatement, 2, recordingData.id);
|
||||
sqlite3_bind_int(insertTransactionStatement, 3, recordingData.address);
|
||||
sqlite3_bind_int(insertTransactionStatement, 4, recordingData.burstlength);
|
||||
sqlite3_bind_int(insertTransactionStatement, 5, recordingData.dramExtension.getThread().ID());
|
||||
sqlite3_bind_int(insertTransactionStatement, 6, recordingData.dramExtension.getChannel().ID());
|
||||
sqlite3_bind_int(insertTransactionStatement, 7, recordingData.dramExtension.getBank().ID());
|
||||
sqlite3_bind_int(insertTransactionStatement, 8, recordingData.dramExtension.getBankGroup().ID());
|
||||
sqlite3_bind_int(insertTransactionStatement, 9, recordingData.dramExtension.getRow().ID());
|
||||
sqlite3_bind_int(insertTransactionStatement, 10, recordingData.dramExtension.getColumn().ID());
|
||||
sqlite3_bind_int(insertTransactionStatement, 11, recordingData.timeOnDataStrobe.start.value());
|
||||
sqlite3_bind_int(insertTransactionStatement, 12, recordingData.timeOnDataStrobe.end.value());
|
||||
sqlite3_bind_int64(insertTransactionStatement, 13, recordingData.timeOfGeneration.value());
|
||||
|
||||
executeSqlStatement(insertTransactionStatement);
|
||||
}
|
||||
void TlmRecorder::insertRangeInDB(unsigned int id, const sc_time& time)
|
||||
|
||||
void TlmRecorder::insertRangeInDB(unsigned int id, const sc_time& begin, const sc_time& end)
|
||||
{
|
||||
sqlite3_bind_int(insertRangeStatement, 1, id);
|
||||
sqlite3_bind_int64(insertRangeStatement, 2, time.value());
|
||||
sqlite3_bind_int64(insertRangeStatement, 3, time.value());
|
||||
sqlite3_bind_int64(insertRangeStatement, 2, begin.value());
|
||||
sqlite3_bind_int64(insertRangeStatement, 3, end.value());
|
||||
executeSqlStatement(insertRangeStatement);
|
||||
}
|
||||
void TlmRecorder::insertPhaseInDB(string phaseName, const sc_time& begin, const sc_time& end,
|
||||
tlm::tlm_generic_payload& trans)
|
||||
unsigned int transactionID)
|
||||
{
|
||||
unsigned int id = getElementFromMap(currentTransactionsInSystem, &trans);
|
||||
sqlite3_bind_text(insertPhaseStatement, 1, phaseName.c_str(), phaseName.length(), 0);
|
||||
sqlite3_bind_int64(insertPhaseStatement, 2, begin.value());
|
||||
sqlite3_bind_int64(insertPhaseStatement, 3, end.value());
|
||||
sqlite3_bind_int(insertPhaseStatement, 4, id);
|
||||
sqlite3_bind_int(insertPhaseStatement, 4, transactionID);
|
||||
executeSqlStatement(insertPhaseStatement);
|
||||
}
|
||||
|
||||
void TlmRecorder::updatePhaseEndInDB(string phaseName, const sc_time& time,
|
||||
tlm::tlm_generic_payload& trans)
|
||||
{
|
||||
unsigned int id = getElementFromMap(currentTransactionsInSystem, &trans);
|
||||
sqlite3_bind_int64(updatePhaseStatement, 1, time.value());
|
||||
sqlite3_bind_int(updatePhaseStatement, 2, id);
|
||||
sqlite3_bind_text(updatePhaseStatement, 3, phaseName.c_str(), phaseName.length(), 0);
|
||||
executeSqlStatement(updatePhaseStatement);
|
||||
}
|
||||
|
||||
void TlmRecorder::updateDataStrobe(const sc_time& begin,const sc_time& end, tlm::tlm_generic_payload& trans)
|
||||
{
|
||||
unsigned int id = getElementFromMap(currentTransactionsInSystem, &trans);
|
||||
sqlite3_bind_int64(updateDataStrobeStatement, 1, begin.value());
|
||||
sqlite3_bind_int64(updateDataStrobeStatement, 2, end.value());
|
||||
sqlite3_bind_int(updateDataStrobeStatement, 3, id);
|
||||
executeSqlStatement(updateDataStrobeStatement);
|
||||
}
|
||||
|
||||
void TlmRecorder::introduceNewTransactionToSystem(const sc_time& time,
|
||||
tlm::tlm_generic_payload& trans)
|
||||
{
|
||||
unsigned int id = transactionIDCounter++;
|
||||
currentTransactionsInSystem[&trans] = id;
|
||||
insertTransactionInDB(id, trans);
|
||||
insertRangeInDB(id, time);
|
||||
if (id % transactionCommitRate == 0)
|
||||
{
|
||||
sqlite3_exec(db, "COMMIT", 0, 0, 0);
|
||||
printDebugMessage(
|
||||
"Committing transactions " + to_string(id - transactionCommitRate + 1) + " - "
|
||||
+ to_string(id));
|
||||
sqlite3_exec(db, "BEGIN", 0, 0, 0);
|
||||
}
|
||||
}
|
||||
|
||||
void TlmRecorder::removeTransactionFromSystem(const sc_time& time, tlm::tlm_generic_payload& trans)
|
||||
{
|
||||
unsigned int id = getElementFromMap(currentTransactionsInSystem, &trans);
|
||||
currentTransactionsInSystem.erase(&trans);
|
||||
sqlite3_bind_int64(updateRangeStatement, 1, time.value());
|
||||
sqlite3_bind_int(updateRangeStatement, 2, id);
|
||||
executeSqlStatement(updateRangeStatement);
|
||||
}
|
||||
|
||||
void TlmRecorder::executeSqlStatement(sqlite3_stmt* statement)
|
||||
{
|
||||
if (sqlite3_step(statement) != SQLITE_DONE)
|
||||
int errorCode = sqlite3_step(statement);
|
||||
if (errorCode != SQLITE_DONE)
|
||||
{
|
||||
SC_REPORT_FATAL("Error in TraceRecorder", "Could not execute statement");
|
||||
reportFatal("Error in TraceRecorder", string("Could not execute statement. Error code: ") + to_string(errorCode));
|
||||
}
|
||||
sqlite3_reset(statement);
|
||||
}
|
||||
|
||||
void TlmRecorder::executeSqlCommand(string command)
|
||||
{
|
||||
printDebugMessage("Creating database by running provided sql script");
|
||||
@@ -245,7 +317,6 @@ void TlmRecorder::executeSqlCommand(string command)
|
||||
printDebugMessage("Database created successfully");
|
||||
}
|
||||
|
||||
|
||||
void TlmRecorder::printDebugMessage(std::string message)
|
||||
{
|
||||
DebugManager::getInstance().printDebugMessage(TlmRecorder::senderName, message);
|
||||
@@ -253,10 +324,10 @@ void TlmRecorder::printDebugMessage(std::string message)
|
||||
|
||||
void TlmRecorder::closeConnection()
|
||||
{
|
||||
commitRecordedDataToDB();
|
||||
insertGeneralInfo();
|
||||
sqlite3_exec(db, "COMMIT", 0, 0, 0);
|
||||
printDebugMessage(
|
||||
"Number of transactions written to DB: " + std::to_string(transactionIDCounter - 1));
|
||||
"Number of transactions written to DB: " + std::to_string(transactionIDCounter - 1));
|
||||
printDebugMessage("tlmPhaseRecorder:\tEnd Recording");
|
||||
sqlite3_close(db);
|
||||
db = NULL;
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
#define TLMPHASERECORDER_H
|
||||
|
||||
#include <iostream>
|
||||
#include <ostream>
|
||||
#include <ostream>
|
||||
#include <string>
|
||||
#include <map>
|
||||
#include <algorithm>
|
||||
@@ -13,6 +13,7 @@
|
||||
#include <systemc.h>
|
||||
#include "xmlAddressdecoder.h"
|
||||
#include "DebugManager.h"
|
||||
#include "Utils.h"
|
||||
|
||||
|
||||
using namespace std;
|
||||
@@ -20,58 +21,89 @@ using namespace std;
|
||||
class TlmRecorder
|
||||
{
|
||||
public:
|
||||
static std::string sqlScriptURI;
|
||||
static std::string dbName;
|
||||
static std::string senderName;
|
||||
static std::string sqlScriptURI;
|
||||
static std::string dbName;
|
||||
static std::string senderName;
|
||||
|
||||
static inline TlmRecorder& getInstance()
|
||||
{
|
||||
static TlmRecorder decoder;
|
||||
return decoder;
|
||||
}
|
||||
static inline TlmRecorder& getInstance()
|
||||
{
|
||||
static TlmRecorder decoder;
|
||||
return decoder;
|
||||
}
|
||||
|
||||
void recordPhase(tlm::tlm_generic_payload &trans, tlm::tlm_phase phase, sc_time time);
|
||||
void recordDebugMessage(std::string message, sc_time time);
|
||||
void updateDataStrobe(const sc_time& begin, const sc_time& end, tlm::tlm_generic_payload& trans);
|
||||
void closeConnection();
|
||||
void recordMemconfig(string memconfig){this->memconfig = memconfig;}
|
||||
void recordMemspec(string memspec){this->memspec = memspec;}
|
||||
void recordTracenames(string traces){this->traces = traces;}
|
||||
void recordDummy(tlm::tlm_generic_payload& trans);
|
||||
void recordPhase(tlm::tlm_generic_payload &trans, tlm::tlm_phase phase, sc_time time);
|
||||
void recordDebugMessage(std::string message, sc_time time);
|
||||
void updateDataStrobe(const sc_time& begin, const sc_time& end, tlm::tlm_generic_payload& trans);
|
||||
void closeConnection();
|
||||
void recordMemconfig(string memconfig){this->memconfig = memconfig;}
|
||||
void recordMemspec(string memspec){this->memspec = memspec;}
|
||||
void recordTracenames(string traces){this->traces = traces;}
|
||||
|
||||
private:
|
||||
std::string memconfig,memspec,traces;
|
||||
TlmRecorder();
|
||||
~TlmRecorder();
|
||||
|
||||
struct RecordingData
|
||||
{
|
||||
RecordingData(){}
|
||||
RecordingData(unsigned int id):id(id){}
|
||||
|
||||
void executeSqlCommand(std::string command);
|
||||
void executeSqlStatement(sqlite3_stmt* statement);
|
||||
void prepareSqlStatements();
|
||||
void openDB(std::string name);
|
||||
void setUpTransactionTerminatingPhases();
|
||||
unsigned int id;
|
||||
unsigned int address;
|
||||
unsigned int burstlength;
|
||||
DramExtension dramExtension;
|
||||
sc_time timeOfGeneration;
|
||||
TimeInterval timeOnDataStrobe;
|
||||
|
||||
void createTables(std::string pathToURI);
|
||||
void insertGeneralInfo();
|
||||
void introduceNewTransactionToSystem(const sc_time& time, tlm::tlm_generic_payload& trans);
|
||||
void removeTransactionFromSystem(const sc_time& time, tlm::tlm_generic_payload& trans);
|
||||
void insertTransactionInDB(unsigned int transactionID, tlm::tlm_generic_payload& trans);
|
||||
void insertRangeInDB(unsigned int transactionID, const sc_time& time);
|
||||
void insertPhaseInDB(string phaseName, const sc_time& begin, const sc_time& end, tlm::tlm_generic_payload& trans);
|
||||
void updatePhaseEndInDB(string phaseName, const sc_time& time, tlm::tlm_generic_payload& trans);
|
||||
void insertDebugMessageInDB(string message, const sc_time& time);
|
||||
struct PhaseData
|
||||
{
|
||||
PhaseData(string name,sc_time begin): name(name), interval(begin,SC_ZERO_TIME){}
|
||||
string name;
|
||||
TimeInterval interval;
|
||||
};
|
||||
std::vector<PhaseData> recordedPhases;
|
||||
|
||||
void printDebugMessage(std::string message);
|
||||
void insertPhase(string name,sc_time begin);
|
||||
void setPhaseEnd(string name,sc_time end);
|
||||
|
||||
static const int transactionCommitRate = 10000;
|
||||
map<tlm::tlm_generic_payload*, unsigned int> currentTransactionsInSystem;
|
||||
unsigned int transactionIDCounter;
|
||||
sc_time recordingEndTime;
|
||||
};
|
||||
|
||||
std::vector<tlm::tlm_phase> transactionTerminatingPhases;
|
||||
sqlite3 *db;
|
||||
sqlite3_stmt *insertTransactionStatement, *insertRangeStatement, *updateRangeStatement,
|
||||
*insertPhaseStatement, *updatePhaseStatement, *insertGeneralInfoStatement, *insertDebugMessageStatement, *updateDataStrobeStatement;
|
||||
std::string insertTransactionString, insertRangeString, updateRangeString, insertPhaseString, updatePhaseString, insertGeneralInfoString,
|
||||
insertDebugMessageString, updateDataStrobeString;
|
||||
std::string memconfig,memspec,traces;
|
||||
|
||||
TlmRecorder();
|
||||
~TlmRecorder();
|
||||
|
||||
void prepareSqlStatements();
|
||||
void executeSqlCommand(std::string command);
|
||||
void executeSqlStatement(sqlite3_stmt* statement);
|
||||
|
||||
void openDB(std::string name);
|
||||
void createTables(std::string pathToURI);
|
||||
void setUpTransactionTerminatingPhases();
|
||||
|
||||
void introduceNewTransactionToSystem(tlm::tlm_generic_payload& trans);
|
||||
void removeTransactionFromDBAndInsertInDB(tlm::tlm_generic_payload& trans);
|
||||
|
||||
void commitRecordedDataToDB();
|
||||
void insertGeneralInfo();
|
||||
void insertTransactionInDB(RecordingData& recordingData);
|
||||
void insertRangeInDB(unsigned int id, const sc_time& begin, const sc_time& end);
|
||||
void insertPhaseInDB(string phaseName, const sc_time& begin, const sc_time& end, unsigned int transactionID);
|
||||
void insertDebugMessageInDB(string message, const sc_time& time);
|
||||
|
||||
void printDebugMessage(std::string message);
|
||||
|
||||
static const int transactionCommitRate = 1000;
|
||||
vector<RecordingData> recordedData;
|
||||
map<tlm::tlm_generic_payload*, RecordingData> currentTransactionsInSystem;
|
||||
|
||||
unsigned int transactionIDCounter;
|
||||
sc_time recordingEndTime;
|
||||
|
||||
std::vector<tlm::tlm_phase> transactionTerminatingPhases;
|
||||
sqlite3 *db;
|
||||
sqlite3_stmt *insertTransactionStatement, *insertRangeStatement, *updateRangeStatement,
|
||||
*insertPhaseStatement, *updatePhaseStatement, *insertGeneralInfoStatement, *insertDebugMessageStatement, *updateDataStrobeStatement;
|
||||
std::string insertTransactionString, insertRangeString, updateRangeString, insertPhaseString, updatePhaseString, insertGeneralInfoString,
|
||||
insertDebugMessageString, updateDataStrobeString;
|
||||
};
|
||||
#endif
|
||||
|
||||
@@ -8,168 +8,186 @@ using namespace std;
|
||||
using namespace tinyxml2;
|
||||
|
||||
|
||||
bool TimeInterval::timeIsInInterval(sc_time time)
|
||||
{
|
||||
return (start < time && time < end);
|
||||
}
|
||||
|
||||
bool TimeInterval::intersects(TimeInterval other)
|
||||
{
|
||||
return other.timeIsInInterval(this->start) || this->timeIsInInterval(other.start);
|
||||
}
|
||||
|
||||
sc_time getDistance(sc_time a, sc_time b)
|
||||
{
|
||||
if (a > b)
|
||||
return a - b;
|
||||
else
|
||||
return b - a;
|
||||
}
|
||||
|
||||
void reportFatal(std::string sender, std::string message)
|
||||
{
|
||||
SC_REPORT_FATAL(sender.c_str(), message.c_str());
|
||||
SC_REPORT_FATAL(sender.c_str(), message.c_str());
|
||||
}
|
||||
|
||||
std::string phaseNameToString(tlm::tlm_phase phase)
|
||||
{
|
||||
std::ostringstream oss;
|
||||
oss << phase;
|
||||
std::string str = oss.str();
|
||||
return str;
|
||||
std::ostringstream oss;
|
||||
oss << phase;
|
||||
std::string str = oss.str();
|
||||
return str;
|
||||
}
|
||||
|
||||
unsigned int queryUIntParameter(XMLElement* node, string name)
|
||||
{
|
||||
int result;
|
||||
XMLElement* element;
|
||||
for (element = node->FirstChildElement("parameter"); element != NULL;
|
||||
element = element->NextSiblingElement("parameter"))
|
||||
{
|
||||
if (element->Attribute("id") == name)
|
||||
{
|
||||
sc_assert(!strcmp(element->Attribute("type"), "uint"));
|
||||
XMLError error = element->QueryIntAttribute("value", &result);
|
||||
sc_assert(!error);
|
||||
return result;
|
||||
}
|
||||
}
|
||||
int result;
|
||||
XMLElement* element;
|
||||
for (element = node->FirstChildElement("parameter"); element != NULL;
|
||||
element = element->NextSiblingElement("parameter"))
|
||||
{
|
||||
if (element->Attribute("id") == name)
|
||||
{
|
||||
sc_assert(!strcmp(element->Attribute("type"), "uint"));
|
||||
XMLError error = element->QueryIntAttribute("value", &result);
|
||||
sc_assert(!error);
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
reportFatal("Query XML", "Parameter '" + name + "' does not exist.");
|
||||
return 0;
|
||||
reportFatal("Query XML", "Parameter '" + name + "' does not exist.");
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool parameterExists(tinyxml2::XMLElement* node, std::string name)
|
||||
{
|
||||
XMLElement* element;
|
||||
for (element = node->FirstChildElement("parameter"); element != NULL;
|
||||
element = element->NextSiblingElement("parameter"))
|
||||
{
|
||||
if (element->Attribute("id") == name)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
XMLElement* element;
|
||||
for (element = node->FirstChildElement("parameter"); element != NULL;
|
||||
element = element->NextSiblingElement("parameter"))
|
||||
{
|
||||
if (element->Attribute("id") == name)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
double queryDoubleParameter(XMLElement* node, string name)
|
||||
{
|
||||
double result;
|
||||
XMLElement* element;
|
||||
for (element = node->FirstChildElement("parameter"); element != NULL;
|
||||
element = element->NextSiblingElement("parameter"))
|
||||
{
|
||||
if (element->Attribute("id") == name)
|
||||
{
|
||||
sc_assert(!strcmp(element->Attribute("type"), "double"));
|
||||
XMLError error = element->QueryDoubleAttribute("value", &result);
|
||||
sc_assert(!error);
|
||||
return result;
|
||||
}
|
||||
}
|
||||
double result;
|
||||
XMLElement* element;
|
||||
for (element = node->FirstChildElement("parameter"); element != NULL;
|
||||
element = element->NextSiblingElement("parameter"))
|
||||
{
|
||||
if (element->Attribute("id") == name)
|
||||
{
|
||||
sc_assert(!strcmp(element->Attribute("type"), "double"));
|
||||
XMLError error = element->QueryDoubleAttribute("value", &result);
|
||||
sc_assert(!error);
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
reportFatal("Query XML", "Parameter '" + name + "' does not exist.");
|
||||
return 0;
|
||||
reportFatal("Query XML", "Parameter '" + name + "' does not exist.");
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool queryBoolParameter(XMLElement* node, string name)
|
||||
{
|
||||
bool result;
|
||||
XMLElement* element;
|
||||
for (element = node->FirstChildElement("parameter"); element != NULL;
|
||||
element = element->NextSiblingElement("parameter"))
|
||||
{
|
||||
if (element->Attribute("id") == name)
|
||||
{
|
||||
sc_assert(!strcmp(element->Attribute("type"), "bool"));
|
||||
XMLError error = element->QueryBoolAttribute("value", &result);
|
||||
sc_assert(!error);
|
||||
return result;
|
||||
}
|
||||
}
|
||||
bool result;
|
||||
XMLElement* element;
|
||||
for (element = node->FirstChildElement("parameter"); element != NULL;
|
||||
element = element->NextSiblingElement("parameter"))
|
||||
{
|
||||
if (element->Attribute("id") == name)
|
||||
{
|
||||
sc_assert(!strcmp(element->Attribute("type"), "bool"));
|
||||
XMLError error = element->QueryBoolAttribute("value", &result);
|
||||
sc_assert(!error);
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
reportFatal("Query XML", "Parameter '" + name + "' does not exist.");
|
||||
return 0;
|
||||
reportFatal("Query XML", "Parameter '" + name + "' does not exist.");
|
||||
return 0;
|
||||
}
|
||||
|
||||
string queryStringParameter(XMLElement* node, string name)
|
||||
{
|
||||
XMLElement* element;
|
||||
for (element = node->FirstChildElement("parameter"); element != NULL;
|
||||
element = element->NextSiblingElement("parameter"))
|
||||
{
|
||||
if (element->Attribute("id") == name)
|
||||
{
|
||||
return element->Attribute("value");
|
||||
}
|
||||
}
|
||||
XMLElement* element;
|
||||
for (element = node->FirstChildElement("parameter"); element != NULL;
|
||||
element = element->NextSiblingElement("parameter"))
|
||||
{
|
||||
if (element->Attribute("id") == name)
|
||||
{
|
||||
return element->Attribute("value");
|
||||
}
|
||||
}
|
||||
|
||||
reportFatal("Query XML", "Parameter '" + name + "' does not exist.");
|
||||
return 0;
|
||||
reportFatal("Query XML", "Parameter '" + name + "' does not exist.");
|
||||
return 0;
|
||||
}
|
||||
|
||||
void loadXML(string uri, XMLDocument& doc)
|
||||
{
|
||||
XMLError error = doc.LoadFile(uri.c_str());
|
||||
XMLError error = doc.LoadFile(uri.c_str());
|
||||
|
||||
if (error)
|
||||
{
|
||||
//TODO specify error
|
||||
reportFatal("Configuration", "Error loading xml from: " + uri);
|
||||
}
|
||||
if (error)
|
||||
{
|
||||
//TODO specify error
|
||||
reportFatal("Configuration", "Error loading xml from: " + uri);
|
||||
}
|
||||
}
|
||||
|
||||
string loadTextFileContents(string filename)
|
||||
{
|
||||
|
||||
ifstream in(filename.c_str(), ios::in | ios::binary);
|
||||
if (in)
|
||||
{
|
||||
string contents;
|
||||
in.seekg(0, ios::end);
|
||||
contents.resize(in.tellg());
|
||||
in.seekg(0, ios::beg);
|
||||
in.read(&contents[0], contents.size());
|
||||
in.close();
|
||||
return (contents);
|
||||
}
|
||||
else
|
||||
{
|
||||
reportFatal("Error loading file", "Could not load textfile from " + filename);
|
||||
return "";
|
||||
}
|
||||
ifstream in(filename.c_str(), ios::in | ios::binary);
|
||||
if (in)
|
||||
{
|
||||
string contents;
|
||||
in.seekg(0, ios::end);
|
||||
contents.resize(in.tellg());
|
||||
in.seekg(0, ios::beg);
|
||||
in.read(&contents[0], contents.size());
|
||||
in.close();
|
||||
return (contents);
|
||||
}
|
||||
else
|
||||
{
|
||||
reportFatal("Error loading file", "Could not load textfile from " + filename);
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
||||
void setUpDummy(tlm::tlm_generic_payload& payload, Bank& bank)
|
||||
{
|
||||
payload.set_address(bank.getStartAddress());
|
||||
payload.set_command(tlm::TLM_READ_COMMAND);
|
||||
payload.set_data_length(0);
|
||||
payload.set_response_status(tlm::TLM_OK_RESPONSE);
|
||||
payload.set_dmi_allowed(false);
|
||||
payload.set_byte_enable_length(0);
|
||||
payload.set_streaming_width(0);
|
||||
payload.set_extension(new DramExtension(Thread(0), bank, bank.getBankGroup(), Row(0), Column(0))); //payload takes ownership
|
||||
payload.set_address(bank.getStartAddress());
|
||||
payload.set_command(tlm::TLM_READ_COMMAND);
|
||||
payload.set_data_length(0);
|
||||
payload.set_response_status(tlm::TLM_OK_RESPONSE);
|
||||
payload.set_dmi_allowed(false);
|
||||
payload.set_byte_enable_length(0);
|
||||
payload.set_streaming_width(0);
|
||||
payload.set_extension(new DramExtension(Thread(0), bank, bank.getBankGroup(), Row(0), Column(0))); //payload takes ownership
|
||||
}
|
||||
|
||||
std::string getFileName(std::string uri)
|
||||
{
|
||||
// Remove directory if present.
|
||||
// Do this before extension removal incase directory has a period character.
|
||||
const size_t last_slash_idx = uri.find_last_of("\\/");
|
||||
if (std::string::npos != last_slash_idx)
|
||||
{
|
||||
uri.erase(0, last_slash_idx + 1);
|
||||
}
|
||||
// Remove directory if present.
|
||||
// Do this before extension removal incase directory has a period character.
|
||||
const size_t last_slash_idx = uri.find_last_of("\\/");
|
||||
if (std::string::npos != last_slash_idx)
|
||||
{
|
||||
uri.erase(0, last_slash_idx + 1);
|
||||
}
|
||||
|
||||
// Remove extension if present.
|
||||
const size_t period_idx = uri.rfind('.');
|
||||
if (std::string::npos != period_idx)
|
||||
{
|
||||
uri.erase(period_idx);
|
||||
}
|
||||
return uri;
|
||||
// Remove extension if present.
|
||||
const size_t period_idx = uri.rfind('.');
|
||||
if (std::string::npos != period_idx)
|
||||
{
|
||||
uri.erase(period_idx);
|
||||
}
|
||||
return uri;
|
||||
}
|
||||
|
||||
@@ -17,7 +17,19 @@
|
||||
#include "third_party/tinyxml2.h"
|
||||
#include <iomanip>
|
||||
|
||||
constexpr const char headline[] = "=========================================================";
|
||||
sc_time getDistance(sc_time a, sc_time b);
|
||||
|
||||
struct TimeInterval
|
||||
{
|
||||
sc_time start,end;
|
||||
TimeInterval() : start(SC_ZERO_TIME), end(SC_ZERO_TIME){}
|
||||
TimeInterval(sc_time start,sc_time end) : start(start), end(end){}
|
||||
|
||||
sc_time getLength() {return getDistance(start,end);}
|
||||
bool timeIsInInterval(sc_time time);
|
||||
bool intersects(TimeInterval other);
|
||||
};
|
||||
|
||||
|
||||
template<typename Key, typename Val>
|
||||
inline Val getElementFromMap(const std::map<Key, Val>& m, Key key)
|
||||
@@ -41,9 +53,11 @@ bool isIn(const T& value, const std::vector<T>& collection)
|
||||
return false;
|
||||
}
|
||||
|
||||
constexpr const char headline[] = "=========================================================";
|
||||
|
||||
static inline void loadbar(unsigned int x, unsigned int n, unsigned int w = 50, unsigned int granularity = 1)
|
||||
{
|
||||
if ((x != n) && (x % (n / 100 * granularity) != 0))
|
||||
if ((n < 100) || ((x != n) && (x % (n / 100 * granularity) != 0)))
|
||||
return;
|
||||
|
||||
float ratio = x / (float) n;
|
||||
|
||||
@@ -161,7 +161,8 @@ const Column& DramExtension::getColumn() const
|
||||
{
|
||||
return column;
|
||||
}
|
||||
const unsigned int DramExtension::getBurstlength() const
|
||||
|
||||
unsigned int DramExtension::getBurstlength() const
|
||||
{
|
||||
return burstlength;
|
||||
}
|
||||
|
||||
@@ -15,113 +15,113 @@
|
||||
class Thread
|
||||
{
|
||||
public:
|
||||
explicit Thread(unsigned int id) :
|
||||
id(id)
|
||||
{
|
||||
}
|
||||
explicit Thread(unsigned int id) :
|
||||
id(id)
|
||||
{
|
||||
}
|
||||
|
||||
unsigned int ID() const
|
||||
{
|
||||
return id;
|
||||
}
|
||||
unsigned int ID() const
|
||||
{
|
||||
return id;
|
||||
}
|
||||
private:
|
||||
unsigned int id;
|
||||
unsigned int id;
|
||||
};
|
||||
|
||||
class Channel
|
||||
{
|
||||
public:
|
||||
explicit Channel(unsigned int id) :
|
||||
id(id)
|
||||
{
|
||||
}
|
||||
unsigned int ID() const
|
||||
{
|
||||
return id;
|
||||
}
|
||||
explicit Channel(unsigned int id) :
|
||||
id(id)
|
||||
{
|
||||
}
|
||||
unsigned int ID() const
|
||||
{
|
||||
return id;
|
||||
}
|
||||
private:
|
||||
unsigned int id;
|
||||
unsigned int id;
|
||||
};
|
||||
|
||||
class BankGroup
|
||||
{
|
||||
public:
|
||||
explicit BankGroup(unsigned int id) :
|
||||
id(id)
|
||||
{
|
||||
}
|
||||
unsigned int ID() const
|
||||
{
|
||||
return id;
|
||||
}
|
||||
explicit BankGroup(unsigned int id) :
|
||||
id(id)
|
||||
{
|
||||
}
|
||||
unsigned int ID() const
|
||||
{
|
||||
return id;
|
||||
}
|
||||
private:
|
||||
unsigned int id;
|
||||
unsigned int id;
|
||||
};
|
||||
|
||||
class Bank
|
||||
{
|
||||
public:
|
||||
explicit Bank(unsigned int id) :
|
||||
id(id)
|
||||
{
|
||||
}
|
||||
unsigned int ID() const
|
||||
{
|
||||
return id;
|
||||
}
|
||||
explicit Bank(unsigned int id) :
|
||||
id(id)
|
||||
{
|
||||
}
|
||||
unsigned int ID() const
|
||||
{
|
||||
return id;
|
||||
}
|
||||
|
||||
unsigned int getStartAddress()
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
unsigned int getStartAddress()
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
BankGroup getBankGroup();
|
||||
BankGroup getBankGroup();
|
||||
|
||||
private:
|
||||
unsigned int id;
|
||||
unsigned int id;
|
||||
};
|
||||
|
||||
class Row
|
||||
{
|
||||
public:
|
||||
static const Row NO_ROW;
|
||||
static const Row NO_ROW;
|
||||
|
||||
Row() :
|
||||
id(0), isNoRow(true)
|
||||
{
|
||||
}
|
||||
explicit Row(unsigned int id) :
|
||||
id(id), isNoRow(false)
|
||||
{
|
||||
}
|
||||
Row() :
|
||||
id(0), isNoRow(true)
|
||||
{
|
||||
}
|
||||
explicit Row(unsigned int id) :
|
||||
id(id), isNoRow(false)
|
||||
{
|
||||
}
|
||||
|
||||
unsigned int ID() const
|
||||
{
|
||||
return id;
|
||||
}
|
||||
unsigned int ID() const
|
||||
{
|
||||
return id;
|
||||
}
|
||||
|
||||
const Row operator++();
|
||||
const Row operator++();
|
||||
private:
|
||||
unsigned int id;
|
||||
bool isNoRow;
|
||||
unsigned int id;
|
||||
bool isNoRow;
|
||||
|
||||
friend bool operator==(const Row &lhs, const Row &rhs);
|
||||
friend bool operator==(const Row &lhs, const Row &rhs);
|
||||
};
|
||||
|
||||
class Column
|
||||
{
|
||||
public:
|
||||
explicit Column(unsigned int id) :
|
||||
id(id)
|
||||
{
|
||||
}
|
||||
explicit Column(unsigned int id) :
|
||||
id(id)
|
||||
{
|
||||
}
|
||||
|
||||
unsigned int ID() const
|
||||
{
|
||||
return id;
|
||||
}
|
||||
unsigned int ID() const
|
||||
{
|
||||
return id;
|
||||
}
|
||||
private:
|
||||
unsigned int id;
|
||||
unsigned int id;
|
||||
};
|
||||
|
||||
bool operator==(const Thread &lhs, const Thread &rhs);
|
||||
@@ -147,70 +147,70 @@ bool operator!=(const Column &lhs, const Column &rhs);
|
||||
class DramExtension: public tlm::tlm_extension<DramExtension>
|
||||
{
|
||||
private:
|
||||
Thread thread;
|
||||
Channel channel;
|
||||
Bank bank;
|
||||
BankGroup bankgroup;
|
||||
Row row;
|
||||
Column column;
|
||||
unsigned int burstlength;
|
||||
Thread thread;
|
||||
Channel channel;
|
||||
Bank bank;
|
||||
BankGroup bankgroup;
|
||||
Row row;
|
||||
Column column;
|
||||
unsigned int burstlength;
|
||||
public:
|
||||
|
||||
DramExtension() :
|
||||
thread(0), channel(0), bank(0), bankgroup(0), row(0), column(0), burstlength(0)
|
||||
{
|
||||
}
|
||||
DramExtension(const Thread& thread, const Bank& bank, const BankGroup& bankgroup, const Row& row, const Column& column,
|
||||
unsigned int burstlength = 0) :
|
||||
thread(thread), channel(0), bank(bank), bankgroup(bankgroup), row(row), column(column), burstlength(burstlength)
|
||||
{
|
||||
}
|
||||
DramExtension(const Thread& thread, const Channel& channel, const Bank& bank, const BankGroup& bankgroup, const Row& row,
|
||||
const Column& column, unsigned int burstlength = 0) :
|
||||
thread(thread), channel(channel), bank(bank), bankgroup(bankgroup), row(row), column(column), burstlength(burstlength)
|
||||
{
|
||||
}
|
||||
DramExtension() :
|
||||
thread(0), channel(0), bank(0), bankgroup(0), row(0), column(0), burstlength(0)
|
||||
{
|
||||
}
|
||||
DramExtension(const Thread& thread, const Bank& bank, const BankGroup& bankgroup, const Row& row, const Column& column,
|
||||
unsigned int burstlength = 0) :
|
||||
thread(thread), channel(0), bank(bank), bankgroup(bankgroup), row(row), column(column), burstlength(burstlength)
|
||||
{
|
||||
}
|
||||
DramExtension(const Thread& thread, const Channel& channel, const Bank& bank, const BankGroup& bankgroup, const Row& row,
|
||||
const Column& column, unsigned int burstlength = 0) :
|
||||
thread(thread), channel(channel), bank(bank), bankgroup(bankgroup), row(row), column(column), burstlength(burstlength)
|
||||
{
|
||||
}
|
||||
|
||||
~DramExtension()
|
||||
{
|
||||
}
|
||||
~DramExtension()
|
||||
{
|
||||
}
|
||||
|
||||
virtual tlm_extension_base* clone() const;
|
||||
virtual void copy_from(const tlm_extension_base& ext);
|
||||
virtual tlm_extension_base* clone() const;
|
||||
virtual void copy_from(const tlm_extension_base& ext);
|
||||
|
||||
const Thread& getThread() const;
|
||||
const Thread& getThread() const;
|
||||
|
||||
const Channel& getChannel() const;
|
||||
const Channel& getChannel() const;
|
||||
|
||||
const Bank& getBank() const;
|
||||
const Bank& getBank() const;
|
||||
|
||||
const BankGroup& getBankGroup() const;
|
||||
const BankGroup& getBankGroup() const;
|
||||
|
||||
const Row& getRow() const;
|
||||
const Row& getRow() const;
|
||||
|
||||
const Column& getColumn() const;
|
||||
const Column& getColumn() const;
|
||||
|
||||
const unsigned int getBurstlength() const;
|
||||
unsigned int getBurstlength() const;
|
||||
|
||||
void increaseRow();
|
||||
void increaseRow();
|
||||
|
||||
static DramExtension& getExtension(const tlm::tlm_generic_payload *payload);
|
||||
static DramExtension& getExtension(const tlm::tlm_generic_payload &payload);
|
||||
static DramExtension& getExtension(const tlm::tlm_generic_payload *payload);
|
||||
static DramExtension& getExtension(const tlm::tlm_generic_payload &payload);
|
||||
};
|
||||
|
||||
|
||||
class GenerationExtension : public tlm::tlm_extension<GenerationExtension>
|
||||
{
|
||||
public:
|
||||
GenerationExtension(sc_time timeOfGeneration) : timeOfGeneration(timeOfGeneration) {}
|
||||
virtual tlm_extension_base* clone() const;
|
||||
virtual void copy_from(const tlm_extension_base& ext);
|
||||
static GenerationExtension& getExtension(const tlm::tlm_generic_payload *payload);
|
||||
GenerationExtension(sc_time timeOfGeneration) : timeOfGeneration(timeOfGeneration) {}
|
||||
virtual tlm_extension_base* clone() const;
|
||||
virtual void copy_from(const tlm_extension_base& ext);
|
||||
static GenerationExtension& getExtension(const tlm::tlm_generic_payload *payload);
|
||||
|
||||
|
||||
sc_time TimeOfGeneration() const {return timeOfGeneration;}
|
||||
sc_time TimeOfGeneration() const {return timeOfGeneration;}
|
||||
private:
|
||||
sc_time timeOfGeneration;
|
||||
sc_time timeOfGeneration;
|
||||
};
|
||||
|
||||
#endif /* DRAMEXTENSION_H_ */
|
||||
|
||||
@@ -129,6 +129,8 @@ public:
|
||||
controllerCorePEQ.notify(payload, BEGIN_WRA, command.getStart() - sc_time_stamp());
|
||||
break;
|
||||
case Command::AutoRefresh:
|
||||
TlmRecorder::getInstance().recordDummy(payload);
|
||||
|
||||
controllerCorePEQ.notify(payload, BEGIN_AUTO_REFRESH, command.getStart() - sc_time_stamp());
|
||||
break;
|
||||
case Command::Activate:
|
||||
@@ -141,12 +143,18 @@ public:
|
||||
controllerCorePEQ.notify(payload, BEGIN_PRE_ALL, command.getStart() - sc_time_stamp());
|
||||
break;
|
||||
case Command::PDNA:
|
||||
TlmRecorder::getInstance().recordDummy(payload);
|
||||
|
||||
controllerCorePEQ.notify(payload, BEGIN_PDNA, command.getStart() - sc_time_stamp());
|
||||
break;
|
||||
case Command::PDNP:
|
||||
TlmRecorder::getInstance().recordDummy(payload);
|
||||
|
||||
controllerCorePEQ.notify(payload, BEGIN_PDNP, command.getStart() - sc_time_stamp());
|
||||
break;
|
||||
case Command::SREF:
|
||||
TlmRecorder::getInstance().recordDummy(payload);
|
||||
|
||||
controllerCorePEQ.notify(payload, BEGIN_SREF, command.getStart() - sc_time_stamp());
|
||||
break;
|
||||
case Command::PDNAX:
|
||||
@@ -274,7 +282,9 @@ private:
|
||||
scheduleNextPayload(DramExtension::getExtension(backpressure).getBank());
|
||||
backpressure = NULL;
|
||||
}
|
||||
|
||||
payloadLeavesSystem(payload);
|
||||
TlmRecorder::getInstance().recordDummy(payload);
|
||||
payload.release();
|
||||
}
|
||||
else
|
||||
|
||||
@@ -18,6 +18,8 @@
|
||||
#include "refresh/RefreshManager.h"
|
||||
#include "../../common/dramExtension.h"
|
||||
#include "../../common/Utils.h"
|
||||
#include "TimingCalculation.h"
|
||||
|
||||
#include "powerdown/PowerDownManager.h"
|
||||
#include "powerdown/PowerDownManagerTimeout.h"
|
||||
#include "powerdown/PowerDownManagerBankwise.h"
|
||||
@@ -28,164 +30,164 @@ namespace core {
|
||||
std::string ControllerCore::senderName = "Controller Core";
|
||||
|
||||
ControllerCore::ControllerCore(IWrapperConnector& wrapperConnector, std::map<Bank, int>& numberOfPayloads) :
|
||||
config(Configuration::getInstance()), state(&config), wrapper(wrapperConnector), commandChecker(), numberOfPayloads(
|
||||
numberOfPayloads), savedState(&config), commandSequenceGenerator(state), commandSequenceScheduler(*this)
|
||||
config(Configuration::getInstance()), state(&config), wrapper(wrapperConnector), commandChecker(), numberOfPayloads(
|
||||
numberOfPayloads), savedState(&config), commandSequenceGenerator(state), commandSequenceScheduler(*this)
|
||||
|
||||
{
|
||||
commandChecker[Command::Activate] = new ActivateChecker(config, state);
|
||||
commandChecker[Command::Precharge] = new PrechargeChecker(config, state);
|
||||
commandChecker[Command::PrechargeAll] = new PrechargeAllChecker(config, state);
|
||||
commandChecker[Command::Read] = new ReadChecker(config, state);
|
||||
commandChecker[Command::ReadA] = commandChecker[Command::Read];
|
||||
commandChecker[Command::Write] = new WriteChecker(config, state);
|
||||
commandChecker[Command::WriteA] = commandChecker[Command::Write];
|
||||
commandChecker[Command::Activate] = new ActivateChecker(config, state);
|
||||
commandChecker[Command::Precharge] = new PrechargeChecker(config, state);
|
||||
commandChecker[Command::PrechargeAll] = new PrechargeAllChecker(config, state);
|
||||
commandChecker[Command::Read] = new ReadChecker(config, state);
|
||||
commandChecker[Command::ReadA] = commandChecker[Command::Read];
|
||||
commandChecker[Command::Write] = new WriteChecker(config, state);
|
||||
commandChecker[Command::WriteA] = commandChecker[Command::Write];
|
||||
|
||||
commandChecker[Command::AutoRefresh] = new RefreshChecker(config, state);
|
||||
commandChecker[Command::PDNA] = new PowerDownChecker(config, state);
|
||||
commandChecker[Command::PDNP] = commandChecker[Command::PDNA];
|
||||
commandChecker[Command::SREF] = commandChecker[Command::PDNA];
|
||||
commandChecker[Command::PDNAX] = commandChecker[Command::PDNA];
|
||||
commandChecker[Command::PDNPX] = commandChecker[Command::PDNA];
|
||||
commandChecker[Command::SREFX] = commandChecker[Command::PDNA];
|
||||
commandChecker[Command::AutoRefresh] = new RefreshChecker(config, state);
|
||||
commandChecker[Command::PDNA] = new PowerDownChecker(config, state);
|
||||
commandChecker[Command::PDNP] = commandChecker[Command::PDNA];
|
||||
commandChecker[Command::SREF] = commandChecker[Command::PDNA];
|
||||
commandChecker[Command::PDNAX] = commandChecker[Command::PDNA];
|
||||
commandChecker[Command::PDNPX] = commandChecker[Command::PDNA];
|
||||
commandChecker[Command::SREFX] = commandChecker[Command::PDNA];
|
||||
|
||||
if (config.BankwiseLogic)
|
||||
{
|
||||
refreshManager = new RefreshManagerBankwise(*this);
|
||||
powerDownManager = new PowerDownManagerBankwise(*this);
|
||||
}
|
||||
else
|
||||
{
|
||||
refreshManager = new RefreshManager(*this);
|
||||
if(config.powerDownMode == PowerDownMode::Staggered)
|
||||
{
|
||||
powerDownManager = new PowerDownManager(*this);
|
||||
}
|
||||
else // TimeoutPDN or TimeoutSREF
|
||||
{
|
||||
powerDownManager = new PowerDownManagerTimeout(*this);
|
||||
}
|
||||
}
|
||||
if (config.BankwiseLogic)
|
||||
{
|
||||
refreshManager = new RefreshManagerBankwise(*this);
|
||||
powerDownManager = new PowerDownManagerBankwise(*this);
|
||||
}
|
||||
else
|
||||
{
|
||||
refreshManager = new RefreshManager(*this);
|
||||
if(config.powerDownMode == PowerDownMode::Staggered)
|
||||
{
|
||||
powerDownManager = new PowerDownManager(*this);
|
||||
}
|
||||
else // TimeoutPDN or TimeoutSREF
|
||||
{
|
||||
powerDownManager = new PowerDownManagerTimeout(*this);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ControllerCore::~ControllerCore()
|
||||
{
|
||||
delete commandChecker[Command::Activate];
|
||||
delete commandChecker[Command::Precharge];
|
||||
delete commandChecker[Command::Read];
|
||||
delete commandChecker[Command::Write];
|
||||
delete commandChecker[Command::AutoRefresh];
|
||||
delete commandChecker[Command::PDNA];
|
||||
delete refreshManager;
|
||||
delete powerDownManager;
|
||||
delete commandChecker[Command::Activate];
|
||||
delete commandChecker[Command::Precharge];
|
||||
delete commandChecker[Command::Read];
|
||||
delete commandChecker[Command::Write];
|
||||
delete commandChecker[Command::AutoRefresh];
|
||||
delete commandChecker[Command::PDNA];
|
||||
delete refreshManager;
|
||||
delete powerDownManager;
|
||||
}
|
||||
|
||||
void ControllerCore::saveState()
|
||||
{
|
||||
savedState = state;
|
||||
savedState = state;
|
||||
}
|
||||
|
||||
void ControllerCore::resetState()
|
||||
{
|
||||
state = savedState;
|
||||
state = savedState;
|
||||
}
|
||||
|
||||
void ControllerCore::triggerRefresh(tlm::tlm_generic_payload& payload, sc_time time)
|
||||
{
|
||||
Bank bank = DramExtension::getExtension(payload).getBank();
|
||||
printDebugMessage("Triggering refresh on bank " + to_string(bank.ID()));
|
||||
Bank bank = DramExtension::getExtension(payload).getBank();
|
||||
printDebugMessage("Triggering refresh on bank " + to_string(bank.ID()));
|
||||
|
||||
state.cleanUp(time);
|
||||
state.cleanUp(time);
|
||||
|
||||
if (!refreshManager->isInvalidated(payload, time) && !powerDownManager->isInSelfRefresh(bank))
|
||||
{
|
||||
powerDownManager->wakeUpForRefresh(bank, time); //expects PDNA and PDNP to exit without delay
|
||||
refreshManager->scheduleRefresh(payload, time);
|
||||
}
|
||||
if (!refreshManager->isInvalidated(payload, time) && !powerDownManager->isInSelfRefresh(bank))
|
||||
{
|
||||
powerDownManager->wakeUpForRefresh(bank, time); //expects PDNA and PDNP to exit without delay
|
||||
refreshManager->scheduleRefresh(payload, time);
|
||||
}
|
||||
}
|
||||
|
||||
bool ControllerCore::scheduleRequest(sc_time start, tlm::tlm_generic_payload& payload)
|
||||
{
|
||||
start = clkAlign(start);
|
||||
state.cleanUp(start);
|
||||
start = clkAlign(start);
|
||||
state.cleanUp(start);
|
||||
|
||||
saveState();
|
||||
saveState();
|
||||
|
||||
CommandSequence sequence = commandSequenceGenerator.generateCommandSequence(payload);
|
||||
CommandSchedule schedule = commandSequenceScheduler.schedule(sequence, start, payload);
|
||||
CommandSequence sequence = commandSequenceGenerator.generateCommandSequence(payload);
|
||||
CommandSchedule schedule = commandSequenceScheduler.schedule(sequence, start, payload);
|
||||
|
||||
if (refreshManager->hasCollision(schedule))
|
||||
{
|
||||
resetState();
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
send(schedule, payload);
|
||||
return true;
|
||||
}
|
||||
if (refreshManager->hasCollision(schedule))
|
||||
{
|
||||
resetState();
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
send(schedule, payload);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
bool ControllerCore::isBusy(sc_time time, Bank bank)
|
||||
{
|
||||
ScheduledCommand lastScheduledCommand = state.getLastScheduledCommand(bank);
|
||||
ScheduledCommand lastScheduledCommand = state.getLastScheduledCommand(bank);
|
||||
|
||||
if (lastScheduledCommand.isNoCommand())
|
||||
return false;
|
||||
else if (lastScheduledCommand.commandIsIn( { Command::Write, Command::Read }))
|
||||
{
|
||||
return (time < lastScheduledCommand.getStart());
|
||||
}
|
||||
else if (lastScheduledCommand.commandIsIn( { Command::WriteA, Command::ReadA }))
|
||||
{
|
||||
return (time < lastScheduledCommand.getEnd());
|
||||
}
|
||||
else if (lastScheduledCommand.getCommand() == Command::AutoRefresh)
|
||||
{
|
||||
return (time < lastScheduledCommand.getEnd());
|
||||
}
|
||||
else if (lastScheduledCommand.commandIsIn( { Command::SREFX, Command::PDNPX, Command::PDNAX, Command::SREF, Command::PDNP,
|
||||
Command::PDNA }))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
SC_REPORT_FATAL("Core", "Last command in command sequence was activate or precharge. This really doesn't make sense :D.");
|
||||
return false;
|
||||
}
|
||||
if (lastScheduledCommand.isNoCommand())
|
||||
return false;
|
||||
else if (lastScheduledCommand.commandIsIn( { Command::Write, Command::Read }))
|
||||
{
|
||||
return (time < lastScheduledCommand.getStart());
|
||||
}
|
||||
else if (lastScheduledCommand.commandIsIn( { Command::WriteA, Command::ReadA }))
|
||||
{
|
||||
return (time < lastScheduledCommand.getEnd());
|
||||
}
|
||||
else if (lastScheduledCommand.getCommand() == Command::AutoRefresh)
|
||||
{
|
||||
return (time < lastScheduledCommand.getEnd());
|
||||
}
|
||||
else if (lastScheduledCommand.commandIsIn( { Command::SREFX, Command::PDNPX, Command::PDNAX, Command::SREF, Command::PDNP,
|
||||
Command::PDNA }))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
SC_REPORT_FATAL("Core", "Last command in command sequence was activate or precharge. This really doesn't make sense :D.");
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
const std::vector<Bank>& ControllerCore::getBanks() const
|
||||
{
|
||||
static std::vector<Bank> banks;
|
||||
if (banks.size() == 0)
|
||||
{
|
||||
for (unsigned int i = 0; i < config.NumberOfBanks; i++)
|
||||
{
|
||||
banks.push_back(Bank(i));
|
||||
}
|
||||
}
|
||||
static std::vector<Bank> banks;
|
||||
if (banks.size() == 0)
|
||||
{
|
||||
for (unsigned int i = 0; i < config.NumberOfBanks; i++)
|
||||
{
|
||||
banks.push_back(Bank(i));
|
||||
}
|
||||
}
|
||||
|
||||
return banks;
|
||||
return banks;
|
||||
}
|
||||
|
||||
void ControllerCore::send(const CommandSchedule& schedule, tlm::tlm_generic_payload& payload) const
|
||||
{
|
||||
for (const ScheduledCommand& cmd : schedule.getScheduledCommands())
|
||||
{
|
||||
wrapper.send(cmd, payload);
|
||||
}
|
||||
for (const ScheduledCommand& cmd : schedule.getScheduledCommands())
|
||||
{
|
||||
wrapper.send(cmd, payload);
|
||||
}
|
||||
}
|
||||
|
||||
ICommandChecker& ControllerCore::getCommandChecker(Command command)
|
||||
{
|
||||
return *getElementFromMap(commandChecker, command);
|
||||
return *getElementFromMap(commandChecker, command);
|
||||
}
|
||||
|
||||
void ControllerCore::printDebugMessage(string message)
|
||||
{
|
||||
DebugManager::getInstance().printDebugMessage(ControllerCore::senderName, message);
|
||||
DebugManager::getInstance().printDebugMessage(ControllerCore::senderName, message);
|
||||
}
|
||||
|
||||
} /* namespace controller */
|
||||
|
||||
@@ -13,7 +13,7 @@ namespace core {
|
||||
|
||||
const ScheduledCommand ControllerState::getLastCommand(Command command, Bank bank) //TODO const reference? and make const
|
||||
{
|
||||
return lastCommandsOnBus[command][bank];
|
||||
return lastScheduledByCommandAndBank[command][bank];
|
||||
}
|
||||
|
||||
const ScheduledCommand ControllerState::getLastCommand(Command command)
|
||||
@@ -26,6 +26,7 @@ const ScheduledCommand ControllerState::getLastCommand(Command command)
|
||||
if (current.getStart() > max.getStart())
|
||||
max = current;
|
||||
}
|
||||
|
||||
return max;
|
||||
}
|
||||
|
||||
@@ -37,7 +38,7 @@ const ScheduledCommand ControllerState::getLastScheduledCommand()
|
||||
{
|
||||
for(Bank bank : Configuration::getInstance().getBanks())
|
||||
{
|
||||
ScheduledCommand& current = lastCommandsOnBus[cmd][bank];
|
||||
ScheduledCommand& current = lastScheduledByCommandAndBank[cmd][bank];
|
||||
if (current.getStart() > lastCommand.getStart())
|
||||
lastCommand = current;
|
||||
}
|
||||
@@ -52,7 +53,7 @@ const ScheduledCommand ControllerState::getLastScheduledCommand(Bank bank)
|
||||
|
||||
for(Command cmd : getAllCommands())
|
||||
{
|
||||
ScheduledCommand& current = lastCommandsOnBus[cmd][bank];
|
||||
ScheduledCommand& current = lastScheduledByCommandAndBank[cmd][bank];
|
||||
if (current.getStart() > lastCommand.getStart())
|
||||
lastCommand = current;
|
||||
}
|
||||
@@ -64,7 +65,13 @@ void ControllerState::change(const ScheduledCommand& scheduledCommand)
|
||||
{
|
||||
//TODO double check if slot free?
|
||||
bus.blockSlot(scheduledCommand.getStart());
|
||||
lastCommandsOnBus[scheduledCommand.getCommand()][scheduledCommand.getBank()] = scheduledCommand;
|
||||
|
||||
// if(getLastCommand(scheduledCommand.getCommand()).getStart() > scheduledCommand.getStart())
|
||||
// cout << commandToString(scheduledCommand.getCommand()) << " wurde vorgezogen! " << std::endl;
|
||||
|
||||
lastScheduledByCommandAndBank[scheduledCommand.getCommand()][scheduledCommand.getBank()] = scheduledCommand;
|
||||
//lastScheduledByBank[scheduledCommand.getCommand()] = scheduledCommand;
|
||||
|
||||
|
||||
switch (scheduledCommand.getCommand())
|
||||
{
|
||||
@@ -100,12 +107,22 @@ void ControllerState::change(const ScheduledCommand& scheduledCommand)
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
// cout << "Last Data Strobe Commands Size: " << lastDataStrobeCommands.size() << std::endl;
|
||||
// cout << "Last Activates Size: " << lastActivates.size() << std::endl;
|
||||
// cout << "Bus Slots: " << bus.slotSet.size();
|
||||
}
|
||||
|
||||
void ControllerState::cleanUp(sc_time time)
|
||||
{
|
||||
bus.cleanUpSlots(time);
|
||||
lastDataStrobeCommands.remove_if([&](ScheduledCommand command){return command.getEnd() < time && getDistance(command.getEnd(), time) > config->Timings.tDataStrobeHistory();});
|
||||
vector<ScheduledCommand> tmp;
|
||||
for(ScheduledCommand& command: lastDataStrobeCommands)
|
||||
{
|
||||
if(command.getEnd() >= time || getDistance(command.getEnd(), time) <= config->Timings.tDataStrobeHistory())
|
||||
tmp.push_back(command);
|
||||
}
|
||||
lastDataStrobeCommands = tmp;
|
||||
lastActivates.erase(lastActivates.begin(), lastActivates.lower_bound(time - config->Timings.tActHistory()));
|
||||
}
|
||||
|
||||
|
||||
@@ -22,32 +22,36 @@ namespace core {
|
||||
class ControllerState
|
||||
{
|
||||
public:
|
||||
ControllerState(Configuration* config) :
|
||||
bankStates(), bus(config->Timings.clk), config(config)
|
||||
{
|
||||
}
|
||||
virtual ~ControllerState()
|
||||
{
|
||||
}
|
||||
ControllerState(Configuration* config) :
|
||||
bankStates(), bus(config->Timings.clk), config(config)
|
||||
{
|
||||
}
|
||||
virtual ~ControllerState()
|
||||
{
|
||||
}
|
||||
|
||||
const ScheduledCommand getLastCommand(Command command, Bank bank);
|
||||
const ScheduledCommand getLastCommand(Command command);
|
||||
const ScheduledCommand getLastScheduledCommand(Bank bank);
|
||||
const ScheduledCommand getLastScheduledCommand();
|
||||
const ScheduledCommand getLastCommand(Command command, Bank bank);
|
||||
const ScheduledCommand getLastCommand(Command command);
|
||||
const ScheduledCommand getLastScheduledCommand(Bank bank);
|
||||
const ScheduledCommand getLastScheduledCommand();
|
||||
|
||||
void change(const ScheduledCommand& scheduledCommand);
|
||||
void cleanUp(sc_time time);
|
||||
void change(const ScheduledCommand& scheduledCommand);
|
||||
void cleanUp(sc_time time);
|
||||
|
||||
BankStates bankStates;
|
||||
BankStates bankStates;
|
||||
|
||||
//used by the various checkers
|
||||
std::map<Command, std::map<Bank, ScheduledCommand> > lastCommandsOnBus;
|
||||
Slots bus;
|
||||
std::list<ScheduledCommand> lastDataStrobeCommands;
|
||||
std::map<sc_time, Bank> lastActivates;
|
||||
//used by the various checkers
|
||||
std::map<Command, std::map<Bank, ScheduledCommand> > lastScheduledByCommandAndBank;
|
||||
std::map<Command, ScheduledCommand> lastScheduledByCommand;
|
||||
std::map<Bank, ScheduledCommand> lastScheduledByBank;
|
||||
ScheduledCommand lastScheduled;
|
||||
|
||||
Slots bus;
|
||||
std::vector<ScheduledCommand> lastDataStrobeCommands;
|
||||
std::map<sc_time, Bank> lastActivates;
|
||||
|
||||
private:
|
||||
Configuration* config;
|
||||
Configuration* config;
|
||||
};
|
||||
|
||||
} /* namespace controller */
|
||||
|
||||
@@ -16,17 +16,17 @@ namespace core {
|
||||
class Slots
|
||||
{
|
||||
public:
|
||||
Slots(sc_time clk);
|
||||
virtual ~Slots();
|
||||
void moveCommandToNextFreeSlot(ScheduledCommand& command);
|
||||
void cleanUpSlots(sc_time time);
|
||||
void blockSlots(sc_time begin, sc_time end, bool excludeBorders);
|
||||
void blockSlot(sc_time time);
|
||||
bool isFree(sc_time);
|
||||
Slots(sc_time clk);
|
||||
virtual ~Slots();
|
||||
void moveCommandToNextFreeSlot(ScheduledCommand& command);
|
||||
void cleanUpSlots(sc_time time);
|
||||
void blockSlots(sc_time begin, sc_time end, bool excludeBorders);
|
||||
void blockSlot(sc_time time);
|
||||
bool isFree(sc_time);
|
||||
std::set<sc_time> slotSet;
|
||||
|
||||
private:
|
||||
std::set<sc_time> slotSet;
|
||||
sc_time clk;
|
||||
sc_time clk;
|
||||
|
||||
};
|
||||
|
||||
|
||||
@@ -14,130 +14,114 @@
|
||||
|
||||
namespace core {
|
||||
|
||||
sc_time getDistance(sc_time a, sc_time b)
|
||||
{
|
||||
if (a > b)
|
||||
return a - b;
|
||||
else
|
||||
return b - a;
|
||||
}
|
||||
|
||||
sc_time getDelayToMeetConstraint(sc_time previous, sc_time start, sc_time constraint)
|
||||
{
|
||||
if (previous + constraint > start)
|
||||
return previous + constraint - start;
|
||||
else
|
||||
return SC_ZERO_TIME;
|
||||
if (previous + constraint > start)
|
||||
return previous + constraint - start;
|
||||
else
|
||||
return SC_ZERO_TIME;
|
||||
}
|
||||
|
||||
const sc_time clkAlign(sc_time time, Alignment alignment)
|
||||
{
|
||||
sc_time clk = Configuration::getInstance().Timings.clk;
|
||||
if (alignment == UP)
|
||||
return ceil(time / clk) * clk;
|
||||
else
|
||||
return floor(time / clk) * clk;
|
||||
sc_time clk = Configuration::getInstance().Timings.clk;
|
||||
if (alignment == UP)
|
||||
return ceil(time / clk) * clk;
|
||||
else
|
||||
return floor(time / clk) * clk;
|
||||
}
|
||||
|
||||
sc_time getExecutionTime(Command command, tlm::tlm_generic_payload& payload)
|
||||
{
|
||||
TimingConfiguration& config = Configuration::getInstance().Timings;
|
||||
TimingConfiguration& config = Configuration::getInstance().Timings;
|
||||
|
||||
if (command == Command::Precharge || command == Command::PrechargeAll)
|
||||
{
|
||||
return config.tRP;
|
||||
}
|
||||
else if (command == Command::Activate)
|
||||
{
|
||||
return config.tRCD;
|
||||
}
|
||||
else if (command == Command::Read)
|
||||
{
|
||||
return config.tRL + getReadAccessTime();
|
||||
}
|
||||
else if (command == Command::ReadA)
|
||||
{
|
||||
return config.tRTP + config.tRP;
|
||||
}
|
||||
else if (command == Command::Write)
|
||||
{
|
||||
return config.tWL + getWriteAccessTime();
|
||||
}
|
||||
else if (command == Command::WriteA)
|
||||
{
|
||||
return config.tWL + getWriteAccessTime() + config.tWR + config.tRP;
|
||||
}
|
||||
else if (command == Command::PrechargeAll)
|
||||
{
|
||||
return config.tRP;
|
||||
}
|
||||
else if (command == Command::AutoRefresh)
|
||||
{
|
||||
return getElementFromMap(config.refreshTimings, DramExtension::getExtension(payload).getBank()).tRFC;
|
||||
}
|
||||
if (command == Command::Precharge || command == Command::PrechargeAll)
|
||||
{
|
||||
return config.tRP;
|
||||
}
|
||||
else if (command == Command::Activate)
|
||||
{
|
||||
return config.tRCD;
|
||||
}
|
||||
else if (command == Command::Read)
|
||||
{
|
||||
return config.tRL + getReadAccessTime();
|
||||
}
|
||||
else if (command == Command::ReadA)
|
||||
{
|
||||
return config.tRTP + config.tRP;
|
||||
}
|
||||
else if (command == Command::Write)
|
||||
{
|
||||
return config.tWL + getWriteAccessTime();
|
||||
}
|
||||
else if (command == Command::WriteA)
|
||||
{
|
||||
return config.tWL + getWriteAccessTime() + config.tWR + config.tRP;
|
||||
}
|
||||
else if (command == Command::PrechargeAll)
|
||||
{
|
||||
return config.tRP;
|
||||
}
|
||||
else if (command == Command::AutoRefresh)
|
||||
{
|
||||
return getElementFromMap(config.refreshTimings, DramExtension::getExtension(payload).getBank()).tRFC;
|
||||
}
|
||||
|
||||
else if (command == Command::PDNAX || command == Command::PDNPX || command == Command::SREFX)
|
||||
{
|
||||
return config.clk;
|
||||
}
|
||||
else
|
||||
{
|
||||
SC_REPORT_FATAL("getExecutionTime", "command not known or command doesn't have a fixed execution time");
|
||||
return SC_ZERO_TIME;
|
||||
}
|
||||
else if (command == Command::PDNAX || command == Command::PDNPX || command == Command::SREFX)
|
||||
{
|
||||
return config.clk;
|
||||
}
|
||||
else
|
||||
{
|
||||
SC_REPORT_FATAL("getExecutionTime", "command not known or command doesn't have a fixed execution time");
|
||||
return SC_ZERO_TIME;
|
||||
}
|
||||
}
|
||||
|
||||
sc_time getMinimalExecutionTime(Command command, tlm::tlm_generic_payload& payload)
|
||||
{
|
||||
TimingConfiguration& config = Configuration::getInstance().Timings;
|
||||
if (command == Command::PDNA || command == Command::PDNP)
|
||||
{
|
||||
return config.tCKE;
|
||||
}
|
||||
else if (command == Command::SREF)
|
||||
{
|
||||
return config.tCKESR;
|
||||
}
|
||||
else
|
||||
{
|
||||
SC_REPORT_FATAL("getMinimalExecutionTime", "command is not know or command has a fixed execution time");
|
||||
return SC_ZERO_TIME;
|
||||
}
|
||||
TimingConfiguration& config = Configuration::getInstance().Timings;
|
||||
if (command == Command::PDNA || command == Command::PDNP)
|
||||
{
|
||||
return config.tCKE;
|
||||
}
|
||||
else if (command == Command::SREF)
|
||||
{
|
||||
return config.tCKESR;
|
||||
}
|
||||
else
|
||||
{
|
||||
SC_REPORT_FATAL("getMinimalExecutionTime", "command is not know or command has a fixed execution time");
|
||||
return SC_ZERO_TIME;
|
||||
}
|
||||
}
|
||||
|
||||
bool isClkAligned(sc_time time, sc_time clk)
|
||||
{
|
||||
return !((time / clk) - ceil(time / clk));
|
||||
return !((time / clk) - ceil(time / clk));
|
||||
}
|
||||
|
||||
bool TimeInterval::timeIsInInterval(sc_time time)
|
||||
{
|
||||
return (start < time && time < end);
|
||||
}
|
||||
|
||||
bool TimeInterval::intersects(TimeInterval other)
|
||||
{
|
||||
return other.timeIsInInterval(this->start) || this->timeIsInInterval(other.start);
|
||||
}
|
||||
|
||||
sc_time getReadAccessTime()
|
||||
{
|
||||
Configuration& config = Configuration::getInstance();
|
||||
return config.BurstLength/config.DataRate*config.Timings.clk;
|
||||
Configuration& config = Configuration::getInstance();
|
||||
return config.BurstLength/config.DataRate*config.Timings.clk;
|
||||
}
|
||||
|
||||
sc_time getWriteAccessTime()
|
||||
{
|
||||
Configuration& config = Configuration::getInstance();
|
||||
Configuration& config = Configuration::getInstance();
|
||||
|
||||
if (config.DataRate == 1)
|
||||
{
|
||||
return config.Timings.clk * (config.BurstLength-1) ;
|
||||
}
|
||||
else
|
||||
{
|
||||
return config.Timings.clk * config.BurstLength / config.DataRate;
|
||||
}
|
||||
if (config.DataRate == 1)
|
||||
{
|
||||
return config.Timings.clk * (config.BurstLength-1) ;
|
||||
}
|
||||
else
|
||||
{
|
||||
return config.Timings.clk * config.BurstLength / config.DataRate;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -16,18 +16,6 @@
|
||||
namespace core
|
||||
{
|
||||
|
||||
sc_time getDistance(sc_time a, sc_time b);
|
||||
struct TimeInterval
|
||||
{
|
||||
sc_time start,end;
|
||||
TimeInterval() : start(SC_ZERO_TIME), end(SC_ZERO_TIME){}
|
||||
TimeInterval(sc_time start,sc_time end) : start(start), end(end){}
|
||||
|
||||
sc_time getLength() {return getDistance(start,end);}
|
||||
bool timeIsInInterval(sc_time time);
|
||||
bool intersects(TimeInterval other);
|
||||
};
|
||||
|
||||
sc_time getMinimalExecutionTime(Command command, tlm::tlm_generic_payload& payload);
|
||||
sc_time getExecutionTime(Command command, tlm::tlm_generic_payload& payload);
|
||||
|
||||
@@ -40,5 +28,5 @@ const sc_time clkAlign(sc_time time, Alignment alignment = UP);
|
||||
bool isClkAligned(sc_time time, sc_time clk);
|
||||
|
||||
|
||||
};
|
||||
}
|
||||
#endif /* UTILS_H_ */
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
#include "PowerDownManagerTimeout.h"
|
||||
#include "../ControllerCore.h"
|
||||
#include "../../../common/Utils.h"
|
||||
#include "../TimingCalculation.h"
|
||||
|
||||
using namespace tlm;
|
||||
|
||||
|
||||
@@ -11,8 +11,8 @@
|
||||
#include "IPowerDownManager.h"
|
||||
#include <systemc.h>
|
||||
#include "../../../common/dramExtension.h"
|
||||
#include <map>
|
||||
#include "../scheduling/ScheduledCommand.h"
|
||||
#include <map>
|
||||
|
||||
namespace core {
|
||||
class ControllerCore;
|
||||
|
||||
@@ -15,10 +15,10 @@ using namespace tlm;
|
||||
namespace core {
|
||||
|
||||
RefreshManager::RefreshManager(ControllerCore& controller) :
|
||||
controller(controller), timing(controller.config.Timings.refreshTimings[Bank(0)]), nextPlannedRefresh(SC_ZERO_TIME)
|
||||
controller(controller), timing(controller.config.Timings.refreshTimings[Bank(0)]), nextPlannedRefresh(SC_ZERO_TIME)
|
||||
{
|
||||
setupTransactions();
|
||||
planNextRefresh();
|
||||
setupTransactions();
|
||||
planNextRefresh();
|
||||
}
|
||||
|
||||
RefreshManager::~RefreshManager()
|
||||
@@ -27,75 +27,75 @@ RefreshManager::~RefreshManager()
|
||||
|
||||
bool RefreshManager::hasCollision(const CommandSchedule& schedule)
|
||||
{
|
||||
return schedule.getStart() < controller.state.getLastCommand(Command::AutoRefresh).getEnd() || schedule.getEnd() > nextPlannedRefresh;
|
||||
return schedule.getStart() < controller.state.getLastCommand(Command::AutoRefresh).getEnd() || schedule.getEnd() > nextPlannedRefresh;
|
||||
}
|
||||
|
||||
bool RefreshManager::hasCollision(const ScheduledCommand& command)
|
||||
{
|
||||
|
||||
return command.getStart() < controller.state.getLastCommand(Command::AutoRefresh).getEnd() || command.getEnd() > nextPlannedRefresh;
|
||||
return command.getStart() < controller.state.getLastCommand(Command::AutoRefresh).getEnd() || command.getEnd() > nextPlannedRefresh;
|
||||
}
|
||||
|
||||
void RefreshManager::scheduleRefresh(tlm::tlm_generic_payload& payload, sc_time time)
|
||||
{
|
||||
sc_assert(!isInvalidated(payload, time));
|
||||
sc_assert(!isInvalidated(payload, time));
|
||||
|
||||
if (!controller.state.bankStates.allRowBuffersAreClosed())
|
||||
{
|
||||
ScheduledCommand precharge(Command::PrechargeAll, time, getExecutionTime(Command::PrechargeAll, refreshPayloads[Bank(0)]),
|
||||
DramExtension::getExtension(refreshPayloads[Bank(0)]));
|
||||
controller.getCommandChecker(Command::PrechargeAll).delayToSatisfyConstraints(precharge);
|
||||
sendToAllBanks(precharge);
|
||||
}
|
||||
if (!controller.state.bankStates.allRowBuffersAreClosed())
|
||||
{
|
||||
ScheduledCommand precharge(Command::PrechargeAll, time, getExecutionTime(Command::PrechargeAll, refreshPayloads[Bank(0)]),
|
||||
DramExtension::getExtension(refreshPayloads[Bank(0)]));
|
||||
controller.getCommandChecker(Command::PrechargeAll).delayToSatisfyConstraints(precharge);
|
||||
sendToAllBanks(precharge);
|
||||
}
|
||||
|
||||
ScheduledCommand nextRefresh(Command::AutoRefresh, time, getExecutionTime(Command::AutoRefresh, refreshPayloads[Bank(0)]),
|
||||
DramExtension::getExtension(refreshPayloads[Bank(0)]));
|
||||
controller.getCommandChecker(Command::AutoRefresh).delayToSatisfyConstraints(nextRefresh);
|
||||
sendToAllBanks(nextRefresh);
|
||||
ScheduledCommand nextRefresh(Command::AutoRefresh, time, getExecutionTime(Command::AutoRefresh, refreshPayloads[Bank(0)]),
|
||||
DramExtension::getExtension(refreshPayloads[Bank(0)]));
|
||||
controller.getCommandChecker(Command::AutoRefresh).delayToSatisfyConstraints(nextRefresh);
|
||||
sendToAllBanks(nextRefresh);
|
||||
|
||||
for (Bank bank : controller.getBanks())
|
||||
{
|
||||
DramExtension::getExtension(refreshPayloads[bank]).increaseRow();
|
||||
}
|
||||
for (Bank bank : controller.getBanks())
|
||||
{
|
||||
DramExtension::getExtension(refreshPayloads[bank]).increaseRow();
|
||||
}
|
||||
|
||||
planNextRefresh();
|
||||
planNextRefresh();
|
||||
}
|
||||
|
||||
void RefreshManager::sendToAllBanks(ScheduledCommand& command)
|
||||
{
|
||||
for (Bank bank : controller.getBanks())
|
||||
{
|
||||
tlm_generic_payload& payload = refreshPayloads[bank];
|
||||
DramExtension extension = DramExtension::getExtension(payload);
|
||||
ScheduledCommand cmd(command.getCommand(), command.getStart(), command.getExecutionTime(), extension);
|
||||
controller.state.change(cmd);
|
||||
controller.wrapper.send(cmd, payload);
|
||||
}
|
||||
for (Bank bank : controller.getBanks())
|
||||
{
|
||||
tlm_generic_payload& payload = refreshPayloads[bank];
|
||||
DramExtension extension = DramExtension::getExtension(payload);
|
||||
ScheduledCommand cmd(command.getCommand(), command.getStart(), command.getExecutionTime(), extension);
|
||||
controller.state.change(cmd);
|
||||
controller.wrapper.send(cmd, payload);
|
||||
}
|
||||
}
|
||||
|
||||
void RefreshManager::planNextRefresh()
|
||||
{
|
||||
nextPlannedRefresh += timing.tREFI;
|
||||
controller.wrapper.send(REFTrigger, nextPlannedRefresh, refreshPayloads[Bank(0)]);
|
||||
nextPlannedRefresh += timing.tREFI;
|
||||
controller.wrapper.send(REFTrigger, nextPlannedRefresh, refreshPayloads[Bank(0)]);
|
||||
}
|
||||
|
||||
void RefreshManager::reInitialize(Bank bank, sc_time time)
|
||||
{
|
||||
nextPlannedRefresh = clkAlign(time, Alignment::DOWN);
|
||||
planNextRefresh();
|
||||
nextPlannedRefresh = clkAlign(time, Alignment::DOWN);
|
||||
planNextRefresh();
|
||||
}
|
||||
|
||||
bool core::RefreshManager::isInvalidated(tlm::tlm_generic_payload& payload, sc_time time)
|
||||
{
|
||||
return nextPlannedRefresh > time;
|
||||
return nextPlannedRefresh > time;
|
||||
}
|
||||
|
||||
void RefreshManager::setupTransactions()
|
||||
{
|
||||
for (Bank bank : controller.getBanks())
|
||||
{
|
||||
setUpDummy(refreshPayloads[bank], bank);
|
||||
}
|
||||
for (Bank bank : controller.getBanks())
|
||||
{
|
||||
setUpDummy(refreshPayloads[bank], bank);
|
||||
}
|
||||
}
|
||||
|
||||
} /* namespace core */
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
#include "../Command.h"
|
||||
#include "../../../common/dramExtension.h"
|
||||
#include "../../../common/TlmRecorder.h"
|
||||
#include "../TimingCalculation.h"
|
||||
#include "../../../common/Utils.h"
|
||||
|
||||
namespace core {
|
||||
|
||||
|
||||
@@ -18,98 +18,98 @@ namespace core {
|
||||
|
||||
void ActivateChecker::delayToSatisfyConstraints(ScheduledCommand& command) const
|
||||
{
|
||||
sc_assert(command.getCommand() == Command::Activate);
|
||||
sc_assert(command.getCommand() == Command::Activate);
|
||||
|
||||
ScheduledCommand lastCommandOnBank = state.getLastScheduledCommand(command.getBank());
|
||||
if (lastCommandOnBank.isValidCommand())
|
||||
{
|
||||
if (lastCommandOnBank.getCommand() == Command::Precharge)
|
||||
{
|
||||
command.delayToMeetConstraint(lastCommandOnBank.getStart(), config.Timings.tRP);
|
||||
}
|
||||
else if (lastCommandOnBank.getCommand() == Command::ReadA)
|
||||
{
|
||||
command.delayToMeetConstraint(lastCommandOnBank.getStart(), config.Timings.tRTP + config.Timings.tRP);
|
||||
}
|
||||
else if (lastCommandOnBank.getCommand() == Command::WriteA)
|
||||
{
|
||||
command.delayToMeetConstraint(lastCommandOnBank.getStart(),
|
||||
config.Timings.tWL + getWriteAccessTime() + config.Timings.tWR + config.Timings.tRP);
|
||||
}
|
||||
else if (lastCommandOnBank.getCommand() == Command::AutoRefresh)
|
||||
{
|
||||
command.delayToMeetConstraint(lastCommandOnBank.getStart(), config.Timings.tRFC);
|
||||
}
|
||||
else if (lastCommandOnBank.getCommand() == Command::PDNPX || lastCommandOnBank.getCommand() == Command::PDNAX)
|
||||
{
|
||||
command.delayToMeetConstraint(lastCommandOnBank.getStart(), config.Timings.tXP);
|
||||
}
|
||||
else if (lastCommandOnBank.getCommand() == Command::SREFX)
|
||||
{
|
||||
command.delayToMeetConstraint(lastCommandOnBank.getStart(), config.Timings.tXSR);
|
||||
}
|
||||
else
|
||||
reportFatal("Activate Checker", "Activate can not follow " + commandToString(lastCommandOnBank.getCommand()));
|
||||
}
|
||||
ScheduledCommand lastCommandOnBank = state.getLastScheduledCommand(command.getBank());
|
||||
if (lastCommandOnBank.isValidCommand())
|
||||
{
|
||||
if (lastCommandOnBank.getCommand() == Command::Precharge)
|
||||
{
|
||||
command.delayToMeetConstraint(lastCommandOnBank.getStart(), config.Timings.tRP);
|
||||
}
|
||||
else if (lastCommandOnBank.getCommand() == Command::ReadA)
|
||||
{
|
||||
command.delayToMeetConstraint(lastCommandOnBank.getStart(), config.Timings.tRTP + config.Timings.tRP);
|
||||
}
|
||||
else if (lastCommandOnBank.getCommand() == Command::WriteA)
|
||||
{
|
||||
command.delayToMeetConstraint(lastCommandOnBank.getStart(),
|
||||
config.Timings.tWL + getWriteAccessTime() + config.Timings.tWR + config.Timings.tRP);
|
||||
}
|
||||
else if (lastCommandOnBank.getCommand() == Command::AutoRefresh)
|
||||
{
|
||||
command.delayToMeetConstraint(lastCommandOnBank.getStart(), config.Timings.tRFC);
|
||||
}
|
||||
else if (lastCommandOnBank.getCommand() == Command::PDNPX || lastCommandOnBank.getCommand() == Command::PDNAX)
|
||||
{
|
||||
command.delayToMeetConstraint(lastCommandOnBank.getStart(), config.Timings.tXP);
|
||||
}
|
||||
else if (lastCommandOnBank.getCommand() == Command::SREFX)
|
||||
{
|
||||
command.delayToMeetConstraint(lastCommandOnBank.getStart(), config.Timings.tXSR);
|
||||
}
|
||||
else
|
||||
reportFatal("Activate Checker", "Activate can not follow " + commandToString(lastCommandOnBank.getCommand()));
|
||||
}
|
||||
|
||||
delay_to_satisfy_activateToActivate_sameBank(command);
|
||||
delay_to_satisfy_activateToActivate_sameBank(command);
|
||||
|
||||
while (!(state.bus.isFree(command.getStart()) && satsfies_activateToActivate_differentBank(command)
|
||||
&& satisfies_nActivateWindow(command)))
|
||||
{
|
||||
command.delayStart(config.Timings.clk);
|
||||
}
|
||||
while (!(state.bus.isFree(command.getStart()) && satsfies_activateToActivate_differentBank(command)
|
||||
&& satisfies_nActivateWindow(command)))
|
||||
{
|
||||
command.delayStart(config.Timings.clk);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void ActivateChecker::delay_to_satisfy_activateToActivate_sameBank(ScheduledCommand& command) const
|
||||
{
|
||||
ScheduledCommand lastActivateOnBank = state.getLastCommand(Command::Activate, command.getBank());
|
||||
if (lastActivateOnBank.isValidCommand())
|
||||
{
|
||||
command.delayToMeetConstraint(lastActivateOnBank.getStart(), config.Timings.tRC);
|
||||
}
|
||||
ScheduledCommand lastActivateOnBank = state.getLastCommand(Command::Activate, command.getBank());
|
||||
if (lastActivateOnBank.isValidCommand())
|
||||
{
|
||||
command.delayToMeetConstraint(lastActivateOnBank.getStart(), config.Timings.tRC);
|
||||
}
|
||||
}
|
||||
|
||||
bool ActivateChecker::satsfies_activateToActivate_differentBank(ScheduledCommand& command) const
|
||||
{
|
||||
for (auto act : state.lastActivates)
|
||||
{
|
||||
sc_time time = act.first;
|
||||
sc_time tRRD = (command.getBankGroup() == act.second.getBankGroup()) ? config.Timings.tRRD_L : config.Timings.tRRD_S;
|
||||
for (auto act : state.lastActivates)
|
||||
{
|
||||
sc_time time = act.first;
|
||||
sc_time tRRD = (command.getBankGroup() == act.second.getBankGroup()) ? config.Timings.tRRD_L : config.Timings.tRRD_S;
|
||||
|
||||
if ((time < command.getStart() && command.getStart() - time < tRRD)
|
||||
|| (command.getStart() <= time && time - command.getStart() < tRRD))
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
if ((time < command.getStart() && command.getStart() - time < tRRD)
|
||||
|| (command.getStart() <= time && time - command.getStart() < tRRD))
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ActivateChecker::satisfies_nActivateWindow(ScheduledCommand& command) const
|
||||
{
|
||||
/*
|
||||
* there may be activates scheduled in the future, so emplace
|
||||
* command in a copied set (not necessarily the last in time),
|
||||
* and check if the n-act constraint holds for the whole set.
|
||||
*/
|
||||
if (state.lastActivates.size() >= config.nActivate)
|
||||
{
|
||||
map<sc_time, Bank> lastActivates = state.lastActivates;
|
||||
lastActivates.emplace(command.getStart(), command.getBank());
|
||||
auto upper = lastActivates.begin();
|
||||
advance(upper, config.nActivate);
|
||||
auto lower = lastActivates.begin();
|
||||
/*
|
||||
* there may be activates scheduled in the future, so emplace
|
||||
* command in a copied set (not necessarily the last in time),
|
||||
* and check if the n-act constraint holds for the whole set.
|
||||
*/
|
||||
if (state.lastActivates.size() >= config.nActivate)
|
||||
{
|
||||
map<sc_time, Bank> lastActivates = state.lastActivates;
|
||||
lastActivates.emplace(command.getStart(), command.getBank());
|
||||
auto upper = lastActivates.begin();
|
||||
advance(upper, config.nActivate);
|
||||
auto lower = lastActivates.begin();
|
||||
|
||||
while (upper != lastActivates.end())
|
||||
{
|
||||
if (upper->first - lower->first < config.Timings.tNAW)
|
||||
return false;
|
||||
++upper;
|
||||
++lower;
|
||||
}
|
||||
}
|
||||
while (upper != lastActivates.end())
|
||||
{
|
||||
if (upper->first - lower->first < config.Timings.tNAW)
|
||||
return false;
|
||||
++upper;
|
||||
++lower;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
return true;
|
||||
}
|
||||
|
||||
} /* namespace controller */
|
||||
|
||||
@@ -6,71 +6,71 @@
|
||||
*/
|
||||
|
||||
#include "PowerDownChecker.h"
|
||||
#include "../../../../common/Utils.h"
|
||||
#include "../../TimingCalculation.h"
|
||||
|
||||
namespace core {
|
||||
void PowerDownChecker::delayToSatisfyConstraints(ScheduledCommand& command) const
|
||||
{
|
||||
sc_assert(
|
||||
command.commandIsIn(
|
||||
{ Command::SREF, Command::PDNA, Command::PDNP, Command::PDNAX, Command::PDNPX, Command::SREFX }));
|
||||
sc_assert(
|
||||
command.commandIsIn(
|
||||
{ Command::SREF, Command::PDNA, Command::PDNP, Command::PDNAX, Command::PDNPX, Command::SREFX }));
|
||||
|
||||
if (command.commandIsIn( { Command::SREF, Command::PDNA, Command::PDNP }))
|
||||
{
|
||||
ScheduledCommand lastCommandOnBank = state.getLastScheduledCommand(command.getBank());
|
||||
if (command.commandIsIn( { Command::SREF, Command::PDNA, Command::PDNP }))
|
||||
{
|
||||
ScheduledCommand lastCommandOnBank = state.getLastScheduledCommand(command.getBank());
|
||||
|
||||
if (lastCommandOnBank.isValidCommand())
|
||||
{
|
||||
if (lastCommandOnBank.getCommand() == Command::Read || lastCommandOnBank.getCommand() == Command::ReadA)
|
||||
{
|
||||
command.delayToMeetConstraint(lastCommandOnBank.getStart(),
|
||||
config.Timings.tRL + getReadAccessTime() + config.Timings.clk);
|
||||
}
|
||||
else if (lastCommandOnBank.getCommand() == Command::Write)
|
||||
{
|
||||
command.delayToMeetConstraint(lastCommandOnBank.getStart(),
|
||||
config.Timings.tWL + getWriteAccessTime() + config.Timings.tWR);
|
||||
}
|
||||
else if (lastCommandOnBank.getCommand() == Command::WriteA)
|
||||
{
|
||||
command.delayToMeetConstraint(lastCommandOnBank.getStart(),
|
||||
config.Timings.tWL + getWriteAccessTime() + config.Timings.tWR + config.Timings.clk);
|
||||
}
|
||||
else if (lastCommandOnBank.getCommand() == Command::AutoRefresh)
|
||||
{
|
||||
command.delayToMeetConstraint(lastCommandOnBank.getStart(), config.Timings.tRFC);
|
||||
}
|
||||
else if (lastCommandOnBank.getCommand() == Command::PDNPX || lastCommandOnBank.getCommand() == Command::PDNAX)
|
||||
{
|
||||
command.delayToMeetConstraint(lastCommandOnBank.getStart(), config.Timings.tXP);
|
||||
}
|
||||
if (lastCommandOnBank.isValidCommand())
|
||||
{
|
||||
if (lastCommandOnBank.getCommand() == Command::Read || lastCommandOnBank.getCommand() == Command::ReadA)
|
||||
{
|
||||
command.delayToMeetConstraint(lastCommandOnBank.getStart(),
|
||||
config.Timings.tRL + getReadAccessTime() + config.Timings.clk);
|
||||
}
|
||||
else if (lastCommandOnBank.getCommand() == Command::Write)
|
||||
{
|
||||
command.delayToMeetConstraint(lastCommandOnBank.getStart(),
|
||||
config.Timings.tWL + getWriteAccessTime() + config.Timings.tWR);
|
||||
}
|
||||
else if (lastCommandOnBank.getCommand() == Command::WriteA)
|
||||
{
|
||||
command.delayToMeetConstraint(lastCommandOnBank.getStart(),
|
||||
config.Timings.tWL + getWriteAccessTime() + config.Timings.tWR + config.Timings.clk);
|
||||
}
|
||||
else if (lastCommandOnBank.getCommand() == Command::AutoRefresh)
|
||||
{
|
||||
command.delayToMeetConstraint(lastCommandOnBank.getStart(), config.Timings.tRFC);
|
||||
}
|
||||
else if (lastCommandOnBank.getCommand() == Command::PDNPX || lastCommandOnBank.getCommand() == Command::PDNAX)
|
||||
{
|
||||
command.delayToMeetConstraint(lastCommandOnBank.getStart(), config.Timings.tXP);
|
||||
}
|
||||
|
||||
else if (lastCommandOnBank.getCommand() == Command::SREFX)
|
||||
{
|
||||
command.delayToMeetConstraint(lastCommandOnBank.getStart(), config.Timings.tXSR);
|
||||
}
|
||||
else if (lastCommandOnBank.getCommand() == Command::SREFX)
|
||||
{
|
||||
command.delayToMeetConstraint(lastCommandOnBank.getStart(), config.Timings.tXSR);
|
||||
}
|
||||
|
||||
else
|
||||
{
|
||||
reportFatal("Powerdown checker", commandToString(command.getCommand()) + " can not follow " + commandToString(lastCommandOnBank.getCommand()));
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
reportFatal("Powerdown checker", commandToString(command.getCommand()) + " can not follow " + commandToString(lastCommandOnBank.getCommand()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
else if (command.getCommand() == Command::PDNAX)
|
||||
{
|
||||
command.delayToMeetConstraint(state.getLastCommand(Command::PDNA).getStart(), config.Timings.tCKE);
|
||||
}
|
||||
else if (command.getCommand() == Command::PDNPX)
|
||||
{
|
||||
command.delayToMeetConstraint(state.getLastCommand(Command::PDNP).getStart(), config.Timings.tCKE);
|
||||
}
|
||||
else if (command.getCommand() == Command::SREFX)
|
||||
{
|
||||
command.delayToMeetConstraint(state.getLastCommand(Command::SREF).getStart(), config.Timings.tCKESR);
|
||||
}
|
||||
else if (command.getCommand() == Command::PDNAX)
|
||||
{
|
||||
command.delayToMeetConstraint(state.getLastCommand(Command::PDNA).getStart(), config.Timings.tCKE);
|
||||
}
|
||||
else if (command.getCommand() == Command::PDNPX)
|
||||
{
|
||||
command.delayToMeetConstraint(state.getLastCommand(Command::PDNP).getStart(), config.Timings.tCKE);
|
||||
}
|
||||
else if (command.getCommand() == Command::SREFX)
|
||||
{
|
||||
command.delayToMeetConstraint(state.getLastCommand(Command::SREF).getStart(), config.Timings.tCKESR);
|
||||
}
|
||||
|
||||
state.bus.moveCommandToNextFreeSlot(command);
|
||||
state.bus.moveCommandToNextFreeSlot(command);
|
||||
}
|
||||
|
||||
} /* namespace core */
|
||||
|
||||
@@ -6,54 +6,54 @@
|
||||
*/
|
||||
|
||||
#include "PrechargeAllChecker.h"
|
||||
#include "../../../../common/Utils.h"
|
||||
#include "../../TimingCalculation.h"
|
||||
|
||||
namespace core {
|
||||
|
||||
void PrechargeAllChecker::delayToSatisfyConstraints(ScheduledCommand& command) const
|
||||
{
|
||||
sc_assert(command.getCommand() == Command::PrechargeAll);
|
||||
sc_assert(command.getCommand() == Command::PrechargeAll);
|
||||
|
||||
for (unsigned int bank = 0; bank < config.NumberOfBanks; ++bank)
|
||||
{
|
||||
ScheduledCommand lastCommand = state.getLastScheduledCommand(Bank(bank));
|
||||
if (lastCommand.isValidCommand())
|
||||
{
|
||||
if (lastCommand.getCommand() == Command::Read)
|
||||
{
|
||||
command.delayToMeetConstraint(lastCommand.getStart(), config.Timings.tRTP);
|
||||
}
|
||||
else if (lastCommand.getCommand() == Command::ReadA)
|
||||
{
|
||||
command.delayToMeetConstraint(lastCommand.getStart(), config.Timings.tRTP + config.Timings.tRP);
|
||||
}
|
||||
else if (lastCommand.getCommand() == Command::Write)
|
||||
{
|
||||
command.delayToMeetConstraint(lastCommand.getStart(), config.Timings.tWL + getWriteAccessTime() + config.Timings.tWR);
|
||||
}
|
||||
else if(lastCommand.getCommand() == Command::WriteA)
|
||||
{
|
||||
command.delayToMeetConstraint(lastCommand.getStart(), config.Timings.tWL + getWriteAccessTime() + config.Timings.tWR + config.Timings.tRP);
|
||||
}
|
||||
else if (lastCommand.getCommand() == Command::AutoRefresh)
|
||||
{
|
||||
command.delayToMeetConstraint(lastCommand.getStart(), config.Timings.tRFC);
|
||||
}
|
||||
else if (lastCommand.getCommand() == Command::PDNAX || lastCommand.getCommand() == Command::PDNPX)
|
||||
{
|
||||
command.delayToMeetConstraint(lastCommand.getStart(), config.Timings.tXP);
|
||||
}
|
||||
else if (lastCommand.getCommand() == Command::SREFX)
|
||||
{
|
||||
command.delayToMeetConstraint(lastCommand.getEnd(), config.Timings.tXSR);
|
||||
}
|
||||
else
|
||||
reportFatal("Precharge All Checker",
|
||||
"Precharge All can not follow " + commandToString(lastCommand.getCommand()));
|
||||
}
|
||||
}
|
||||
for (unsigned int bank = 0; bank < config.NumberOfBanks; ++bank)
|
||||
{
|
||||
ScheduledCommand lastCommand = state.getLastScheduledCommand(Bank(bank));
|
||||
if (lastCommand.isValidCommand())
|
||||
{
|
||||
if (lastCommand.getCommand() == Command::Read)
|
||||
{
|
||||
command.delayToMeetConstraint(lastCommand.getStart(), config.Timings.tRTP);
|
||||
}
|
||||
else if (lastCommand.getCommand() == Command::ReadA)
|
||||
{
|
||||
command.delayToMeetConstraint(lastCommand.getStart(), config.Timings.tRTP + config.Timings.tRP);
|
||||
}
|
||||
else if (lastCommand.getCommand() == Command::Write)
|
||||
{
|
||||
command.delayToMeetConstraint(lastCommand.getStart(), config.Timings.tWL + getWriteAccessTime() + config.Timings.tWR);
|
||||
}
|
||||
else if(lastCommand.getCommand() == Command::WriteA)
|
||||
{
|
||||
command.delayToMeetConstraint(lastCommand.getStart(), config.Timings.tWL + getWriteAccessTime() + config.Timings.tWR + config.Timings.tRP);
|
||||
}
|
||||
else if (lastCommand.getCommand() == Command::AutoRefresh)
|
||||
{
|
||||
command.delayToMeetConstraint(lastCommand.getStart(), config.Timings.tRFC);
|
||||
}
|
||||
else if (lastCommand.getCommand() == Command::PDNAX || lastCommand.getCommand() == Command::PDNPX)
|
||||
{
|
||||
command.delayToMeetConstraint(lastCommand.getStart(), config.Timings.tXP);
|
||||
}
|
||||
else if (lastCommand.getCommand() == Command::SREFX)
|
||||
{
|
||||
command.delayToMeetConstraint(lastCommand.getEnd(), config.Timings.tXSR);
|
||||
}
|
||||
else
|
||||
reportFatal("Precharge All Checker",
|
||||
"Precharge All can not follow " + commandToString(lastCommand.getCommand()));
|
||||
}
|
||||
}
|
||||
|
||||
state.bus.moveCommandToNextFreeSlot(command);
|
||||
state.bus.moveCommandToNextFreeSlot(command);
|
||||
}
|
||||
|
||||
} /* namespace core */
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
*/
|
||||
|
||||
#include "PrechargeChecker.h"
|
||||
#include "../../../../common/Utils.h"
|
||||
#include "../../TimingCalculation.h"
|
||||
|
||||
namespace core {
|
||||
|
||||
@@ -30,14 +30,6 @@ void PrechargeChecker::delayToSatisfyConstraints(ScheduledCommand& command) cons
|
||||
{
|
||||
command.delayToMeetConstraint(lastCommand.getStart(), config.Timings.tXP);
|
||||
}
|
||||
// else if(!Configuration::getInstance().BankwiseLogic && lastCommand.getCommand() == Command::PDNPX)
|
||||
// {
|
||||
// command.delayToMeetConstraint(lastCommand.getStart(), config.Timings.tXP);
|
||||
// }
|
||||
// else if(!Configuration::getInstance().BankwiseLogic && lastCommand.getCommand() == Command::PDNPX)
|
||||
// {
|
||||
// command.delayToMeetConstraint(lastCommand.getStart(), config.Timings.tXSR);
|
||||
// }
|
||||
else
|
||||
reportFatal("Precharge Checker", "Precharge can not follow " + commandToString(lastCommand.getCommand()));
|
||||
}
|
||||
|
||||
@@ -14,97 +14,97 @@ namespace core {
|
||||
|
||||
void ReadChecker::delayToSatisfyConstraints(ScheduledCommand& command) const
|
||||
{
|
||||
sc_assert(command.getCommand() == Command::Read || command.getCommand() == Command::ReadA);
|
||||
sc_assert(command.getCommand() == Command::Read || command.getCommand() == Command::ReadA);
|
||||
|
||||
delayToSatisfyDLL(command);
|
||||
delayToSatisfyDLL(command);
|
||||
|
||||
ScheduledCommand lastCommand = state.getLastScheduledCommand(command.getBank());
|
||||
ScheduledCommand lastCommand = state.getLastScheduledCommand(command.getBank());
|
||||
|
||||
if (lastCommand.isValidCommand())
|
||||
{
|
||||
if (lastCommand.getCommand() == Command::Activate)
|
||||
{
|
||||
command.delayToMeetConstraint(lastCommand.getStart(), config.Timings.tRCD);
|
||||
}
|
||||
else if (lastCommand.getCommand() == Command::Read)
|
||||
{
|
||||
command.delayToMeetConstraint(lastCommand.getStart(), ReadChecker::readToRead(lastCommand,command));
|
||||
}
|
||||
else if (lastCommand.getCommand() == Command::Write)
|
||||
{
|
||||
command.delayToMeetConstraint(lastCommand.getStart(), ReadChecker::writeToRead(lastCommand, command));
|
||||
}
|
||||
else if (lastCommand.getCommand() == Command::PDNPX || lastCommand.getCommand() == Command::PDNAX)
|
||||
{
|
||||
command.delayToMeetConstraint(lastCommand.getStart(), config.Timings.tXP);
|
||||
}
|
||||
else
|
||||
reportFatal("Read Checker", "Read can not follow " + commandToString(lastCommand.getCommand()));
|
||||
}
|
||||
if (lastCommand.isValidCommand())
|
||||
{
|
||||
if (lastCommand.getCommand() == Command::Activate)
|
||||
{
|
||||
command.delayToMeetConstraint(lastCommand.getStart(), config.Timings.tRCD);
|
||||
}
|
||||
else if (lastCommand.getCommand() == Command::Read)
|
||||
{
|
||||
command.delayToMeetConstraint(lastCommand.getStart(), ReadChecker::readToRead(lastCommand,command));
|
||||
}
|
||||
else if (lastCommand.getCommand() == Command::Write)
|
||||
{
|
||||
command.delayToMeetConstraint(lastCommand.getStart(), ReadChecker::writeToRead(lastCommand, command));
|
||||
}
|
||||
else if (lastCommand.getCommand() == Command::PDNPX || lastCommand.getCommand() == Command::PDNAX)
|
||||
{
|
||||
command.delayToMeetConstraint(lastCommand.getStart(), config.Timings.tXP);
|
||||
}
|
||||
else
|
||||
reportFatal("Read Checker", "Read can not follow " + commandToString(lastCommand.getCommand()));
|
||||
}
|
||||
|
||||
while (!state.bus.isFree(command.getStart()) || collidesOnDataStrobe(command))
|
||||
{
|
||||
command.delayStart(config.Timings.clk);
|
||||
}
|
||||
while (!state.bus.isFree(command.getStart()) || collidesOnDataStrobe(command))
|
||||
{
|
||||
command.delayStart(config.Timings.clk);
|
||||
}
|
||||
}
|
||||
|
||||
bool ReadChecker::collidesOnDataStrobe(ScheduledCommand& read) const
|
||||
{
|
||||
for (ScheduledCommand& strobeCommand : state.lastDataStrobeCommands)
|
||||
{
|
||||
if (collidesWithStrobeCommand(read, strobeCommand))
|
||||
return true;
|
||||
}
|
||||
for (ScheduledCommand& strobeCommand : state.lastDataStrobeCommands)
|
||||
{
|
||||
if (collidesWithStrobeCommand(read, strobeCommand))
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
return false;
|
||||
}
|
||||
|
||||
bool ReadChecker::collidesWithStrobeCommand(ScheduledCommand& read, ScheduledCommand& strobeCommand) const
|
||||
{
|
||||
if (strobeCommand.getCommand() == Command::Read || strobeCommand.getCommand() == Command::ReadA)
|
||||
{
|
||||
return getDistance(read.getStart(),strobeCommand.getStart()) < ReadChecker::readToRead(strobeCommand,read);
|
||||
}
|
||||
else if (strobeCommand.getCommand() == Command::Write || strobeCommand.getCommand() == Command::WriteA)
|
||||
{
|
||||
if (strobeCommand.getStart() >= read.getStart())
|
||||
return getDistance(read.getStart(), strobeCommand.getStart()) < WriteChecker::readToWrite(read,strobeCommand);
|
||||
else
|
||||
return getDistance(strobeCommand.getStart(), read.getStart()) < ReadChecker::writeToRead(strobeCommand, read);
|
||||
}
|
||||
else
|
||||
{
|
||||
reportFatal("Read Checker",
|
||||
"Invalid strobeCommand in data strobe commands " + commandToString(strobeCommand.getCommand()));
|
||||
return true;
|
||||
}
|
||||
if (strobeCommand.getCommand() == Command::Read || strobeCommand.getCommand() == Command::ReadA)
|
||||
{
|
||||
return getDistance(read.getStart(),strobeCommand.getStart()) < ReadChecker::readToRead(strobeCommand,read);
|
||||
}
|
||||
else if (strobeCommand.getCommand() == Command::Write || strobeCommand.getCommand() == Command::WriteA)
|
||||
{
|
||||
if (strobeCommand.getStart() >= read.getStart())
|
||||
return getDistance(read.getStart(), strobeCommand.getStart()) < WriteChecker::readToWrite(read,strobeCommand);
|
||||
else
|
||||
return getDistance(strobeCommand.getStart(), read.getStart()) < ReadChecker::writeToRead(strobeCommand, read);
|
||||
}
|
||||
else
|
||||
{
|
||||
reportFatal("Read Checker",
|
||||
"Invalid strobeCommand in data strobe commands " + commandToString(strobeCommand.getCommand()));
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
void ReadChecker::delayToSatisfyDLL(ScheduledCommand& read) const
|
||||
{
|
||||
ScheduledCommand lastSREFX = state.getLastCommand(Command::SREFX, read.getBank());
|
||||
if (lastSREFX.isValidCommand())
|
||||
read.delayToMeetConstraint(lastSREFX.getStart(), config.Timings.tXSRDLL);
|
||||
ScheduledCommand lastSREFX = state.getLastCommand(Command::SREFX, read.getBank());
|
||||
if (lastSREFX.isValidCommand())
|
||||
read.delayToMeetConstraint(lastSREFX.getStart(), config.Timings.tXSRDLL);
|
||||
}
|
||||
|
||||
sc_time ReadChecker::readToRead(ScheduledCommand& firstRead, ScheduledCommand& secondRead)
|
||||
{
|
||||
sc_assert(firstRead.getCommand() == Command::Read || firstRead.getCommand() == Command::ReadA);
|
||||
sc_assert(secondRead.getCommand() == Command::Read || secondRead.getCommand() == Command::ReadA);
|
||||
sc_assert(firstRead.getCommand() == Command::Read || firstRead.getCommand() == Command::ReadA);
|
||||
sc_assert(secondRead.getCommand() == Command::Read || secondRead.getCommand() == Command::ReadA);
|
||||
|
||||
TimingConfiguration& config = Configuration::getInstance().Timings;
|
||||
sc_time tCCD = (firstRead.getBankGroup() == secondRead.getBankGroup()) ? config.tCCD_L : config.tCCD_S;
|
||||
return max(tCCD, getReadAccessTime());
|
||||
TimingConfiguration& config = Configuration::getInstance().Timings;
|
||||
sc_time tCCD = (firstRead.getBankGroup() == secondRead.getBankGroup()) ? config.tCCD_L : config.tCCD_S;
|
||||
return max(tCCD, getReadAccessTime());
|
||||
}
|
||||
|
||||
sc_time ReadChecker::writeToRead(ScheduledCommand& write, ScheduledCommand& read)
|
||||
{
|
||||
sc_assert(read.getCommand() == Command::Read || read.getCommand() == Command::ReadA);
|
||||
sc_assert(write.getCommand() == Command::Write || write.getCommand() == Command::WriteA);
|
||||
sc_assert(read.getCommand() == Command::Read || read.getCommand() == Command::ReadA);
|
||||
sc_assert(write.getCommand() == Command::Write || write.getCommand() == Command::WriteA);
|
||||
|
||||
TimingConfiguration& config = Configuration::getInstance().Timings;
|
||||
sc_time tWTR = (write.getBankGroup() == read.getBankGroup()) ? config.tWTR_L : config.tWTR_S;
|
||||
return config.tWL + getWriteAccessTime() + tWTR;
|
||||
TimingConfiguration& config = Configuration::getInstance().Timings;
|
||||
sc_time tWTR = (write.getBankGroup() == read.getBankGroup()) ? config.tWTR_L : config.tWTR_S;
|
||||
return config.tWL + getWriteAccessTime() + tWTR;
|
||||
}
|
||||
|
||||
} /* namespace controller */
|
||||
|
||||
@@ -6,47 +6,48 @@
|
||||
*/
|
||||
|
||||
#include "RefreshChecker.h"
|
||||
#include "../../../../common/Utils.h"
|
||||
#include "../../TimingCalculation.h"
|
||||
|
||||
|
||||
namespace core {
|
||||
|
||||
void RefreshChecker::delayToSatisfyConstraints(ScheduledCommand& command) const
|
||||
{
|
||||
sc_assert(command.getCommand() == Command::AutoRefresh);
|
||||
sc_assert(command.getCommand() == Command::AutoRefresh);
|
||||
|
||||
ScheduledCommand lastCommandOnBank = state.getLastScheduledCommand(command.getBank());
|
||||
ScheduledCommand lastCommandOnBank = state.getLastScheduledCommand(command.getBank());
|
||||
|
||||
if (lastCommandOnBank.isValidCommand())
|
||||
{
|
||||
if (lastCommandOnBank.getCommand() == Command::Precharge || lastCommandOnBank.getCommand() == Command::PrechargeAll)
|
||||
{
|
||||
command.delayToMeetConstraint(lastCommandOnBank.getStart(), config.Timings.tRP);
|
||||
}
|
||||
else if (lastCommandOnBank.getCommand() == Command::ReadA)
|
||||
{
|
||||
command.delayToMeetConstraint(lastCommandOnBank.getStart(), config.Timings.tRTP + config.Timings.tRP);
|
||||
}
|
||||
else if (lastCommandOnBank.getCommand() == Command::WriteA)
|
||||
{
|
||||
command.delayToMeetConstraint(lastCommandOnBank.getStart(),
|
||||
config.Timings.tWL + getWriteAccessTime() + config.Timings.tWR + config.Timings.tRP);
|
||||
}
|
||||
else if (lastCommandOnBank.getCommand() == Command::PDNPX || lastCommandOnBank.getCommand() == Command::PDNAX)
|
||||
{
|
||||
command.delayToMeetConstraint(lastCommandOnBank.getStart(), config.Timings.tXP);
|
||||
}
|
||||
else if (lastCommandOnBank.getCommand() == Command::SREFX)
|
||||
{
|
||||
command.delayToMeetConstraint(lastCommandOnBank.getStart(), config.Timings.tXSR);
|
||||
}
|
||||
else if (lastCommandOnBank.getCommand() == Command::AutoRefresh)
|
||||
{
|
||||
}
|
||||
else
|
||||
reportFatal("Refresh Checker", "Refresh can not follow " + commandToString(lastCommandOnBank.getCommand()));
|
||||
}
|
||||
if (lastCommandOnBank.isValidCommand())
|
||||
{
|
||||
if (lastCommandOnBank.getCommand() == Command::Precharge || lastCommandOnBank.getCommand() == Command::PrechargeAll)
|
||||
{
|
||||
command.delayToMeetConstraint(lastCommandOnBank.getStart(), config.Timings.tRP);
|
||||
}
|
||||
else if (lastCommandOnBank.getCommand() == Command::ReadA)
|
||||
{
|
||||
command.delayToMeetConstraint(lastCommandOnBank.getStart(), config.Timings.tRTP + config.Timings.tRP);
|
||||
}
|
||||
else if (lastCommandOnBank.getCommand() == Command::WriteA)
|
||||
{
|
||||
command.delayToMeetConstraint(lastCommandOnBank.getStart(),
|
||||
config.Timings.tWL + getWriteAccessTime() + config.Timings.tWR + config.Timings.tRP);
|
||||
}
|
||||
else if (lastCommandOnBank.getCommand() == Command::PDNPX || lastCommandOnBank.getCommand() == Command::PDNAX)
|
||||
{
|
||||
command.delayToMeetConstraint(lastCommandOnBank.getStart(), config.Timings.tXP);
|
||||
}
|
||||
else if (lastCommandOnBank.getCommand() == Command::SREFX)
|
||||
{
|
||||
command.delayToMeetConstraint(lastCommandOnBank.getStart(), config.Timings.tXSR);
|
||||
}
|
||||
else if (lastCommandOnBank.getCommand() == Command::AutoRefresh)
|
||||
{
|
||||
}
|
||||
else
|
||||
reportFatal("Refresh Checker", "Refresh can not follow " + commandToString(lastCommandOnBank.getCommand()));
|
||||
}
|
||||
|
||||
state.bus.moveCommandToNextFreeSlot(command);
|
||||
state.bus.moveCommandToNextFreeSlot(command);
|
||||
}
|
||||
|
||||
} /* namespace core */
|
||||
|
||||
@@ -5,8 +5,9 @@
|
||||
* Author: jonny
|
||||
*/
|
||||
|
||||
#include "SimulationManager.h"
|
||||
#include <sys/wait.h>
|
||||
#include <boost/filesystem.hpp>
|
||||
#include "SimulationManager.h"
|
||||
#include "../common/Utils.h"
|
||||
using namespace std;
|
||||
using namespace tinyxml2;
|
||||
@@ -54,10 +55,10 @@ void SimulationManager::loadSimulationsFromXML(string uri)
|
||||
|
||||
void SimulationManager::runSimulations()
|
||||
{
|
||||
// system(string("rm -rf " + exportPath).c_str());
|
||||
for (auto& batch : simulationsBatches)
|
||||
{
|
||||
//system(string("mkdir -p " + exportPath + "/" + batch.simulationName).c_str());
|
||||
boost::filesystem::path dir(exportPath + "/" + batch.simulationName);
|
||||
boost::filesystem::create_directories(dir);
|
||||
|
||||
for (auto& dramSetup : batch.dramSetups)
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user