Use separate thread for database creation.
This commit is contained in:
@@ -42,15 +42,18 @@
|
||||
#include "TlmRecorder.h"
|
||||
#include "dramExtensions.h"
|
||||
#include "../configuration/Configuration.h"
|
||||
#include "../controller/Command.h"
|
||||
|
||||
using namespace tlm;
|
||||
|
||||
TlmRecorder::TlmRecorder(const std::string &name, const std::string &dbName) :
|
||||
name(name), totalNumTransactions(0), simulationTimeCoveredByRecording(SC_ZERO_TIME)
|
||||
name(name), totalNumTransactions(0), simulationTimeCoveredByRecording(SC_ZERO_TIME)
|
||||
{
|
||||
recordedData.reserve(transactionCommitRate);
|
||||
setUpTransactionTerminatingPhases();
|
||||
currentDataBuffer = &recordingDataBuffer[0];
|
||||
storageDataBuffer = &recordingDataBuffer[1];
|
||||
|
||||
currentDataBuffer->reserve(transactionCommitRate);
|
||||
storageDataBuffer->reserve(transactionCommitRate);
|
||||
|
||||
openDB(dbName);
|
||||
char *sErrMsg;
|
||||
sqlite3_exec(db, "PRAGMA main.page_size = 4096", nullptr, nullptr, &sErrMsg);
|
||||
@@ -111,29 +114,28 @@ void TlmRecorder::recordBandwidth(double timeInSeconds, double averageBandwidth)
|
||||
void TlmRecorder::recordPhase(tlm_generic_payload &trans,
|
||||
tlm_phase phase, const sc_time &time)
|
||||
{
|
||||
if (currentTransactionsInSystem.count(&trans) == 0)
|
||||
if (currentTransactionsInSystem.find(&trans) == currentTransactionsInSystem.end())
|
||||
introduceTransactionSystem(trans);
|
||||
|
||||
std::string phaseName = getPhaseName(phase);
|
||||
std::string phaseBeginPrefix = "BEGIN_";
|
||||
std::string phaseEndPrefix = "END_";
|
||||
|
||||
if (phaseName.find(phaseBeginPrefix) != std::string::npos)
|
||||
if (phase == END_REQ || phase == END_RESP || phase >= END_PDNA)
|
||||
{
|
||||
phaseName.erase(0, phaseBeginPrefix.length());
|
||||
assert(currentTransactionsInSystem.count(&trans) != 0);
|
||||
currentTransactionsInSystem[&trans].insertPhase(phaseName, time);
|
||||
phaseName.erase(0, phaseEndPrefix.length());
|
||||
currentTransactionsInSystem[&trans].setPhaseEnd(phaseName, time);
|
||||
}
|
||||
else
|
||||
{
|
||||
phaseName.erase(0, phaseEndPrefix.length());
|
||||
assert(currentTransactionsInSystem.count(&trans) != 0);
|
||||
currentTransactionsInSystem[&trans].setPhaseEnd(phaseName, time);
|
||||
phaseName.erase(0, phaseBeginPrefix.length());
|
||||
currentTransactionsInSystem[&trans].insertPhase(phaseName, time);
|
||||
}
|
||||
|
||||
if (currentTransactionsInSystem[&trans].cmd == 'X')
|
||||
{
|
||||
if (std::count(transactionTerminatingPhases.begin(), transactionTerminatingPhases.end(), phase) == 1)
|
||||
if (phase == END_REFA || phase == END_REFB || phase == END_REFSB
|
||||
|| phase == END_PDNA || phase == END_PDNP || phase == END_SREF)
|
||||
removeTransactionFromSystem(trans);
|
||||
}
|
||||
else
|
||||
@@ -181,14 +183,6 @@ void TlmRecorder::introduceTransactionSystem(tlm_generic_payload &trans)
|
||||
|
||||
PRINTDEBUGMESSAGE(name, "New transaction #" + std::to_string(totalNumTransactions) + " generation time " +
|
||||
currentTransactionsInSystem[&trans].timeOfGeneration.to_string());
|
||||
|
||||
if (totalNumTransactions % transactionCommitRate == 0)
|
||||
{
|
||||
PRINTDEBUGMESSAGE(name, "Committing transactions " +
|
||||
std::to_string(totalNumTransactions - transactionCommitRate + 1)
|
||||
+ " - " + std::to_string(totalNumTransactions));
|
||||
commitRecordedDataToDB();
|
||||
}
|
||||
}
|
||||
|
||||
void TlmRecorder::removeTransactionFromSystem(tlm_generic_payload &trans)
|
||||
@@ -199,8 +193,20 @@ void TlmRecorder::removeTransactionFromSystem(tlm_generic_payload &trans)
|
||||
std::to_string(currentTransactionsInSystem[&trans].id));
|
||||
|
||||
Transaction &recordingData = currentTransactionsInSystem[&trans];
|
||||
recordedData.push_back(recordingData);
|
||||
currentDataBuffer->push_back(recordingData);
|
||||
currentTransactionsInSystem.erase(&trans);
|
||||
|
||||
if (currentDataBuffer->size() == transactionCommitRate)
|
||||
{
|
||||
if (storageThread.joinable())
|
||||
storageThread.join();
|
||||
|
||||
std::swap(currentDataBuffer, storageDataBuffer);
|
||||
|
||||
storageThread = std::thread(&TlmRecorder::commitRecordedDataToDB, this);
|
||||
currentDataBuffer->clear();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void TlmRecorder::terminateRemainingTransactions()
|
||||
@@ -228,7 +234,7 @@ void TlmRecorder::terminateRemainingTransactions()
|
||||
void TlmRecorder::commitRecordedDataToDB()
|
||||
{
|
||||
sqlite3_exec(db, "BEGIN;", nullptr, nullptr, nullptr);
|
||||
for (Transaction &recordingData : recordedData)
|
||||
for (Transaction &recordingData : *storageDataBuffer)
|
||||
{
|
||||
assert(!recordingData.recordedPhases.empty());
|
||||
insertTransactionInDB(recordingData);
|
||||
@@ -248,7 +254,6 @@ void TlmRecorder::commitRecordedDataToDB()
|
||||
}
|
||||
|
||||
sqlite3_exec(db, "COMMIT;", nullptr, nullptr, nullptr);
|
||||
recordedData.clear();
|
||||
}
|
||||
|
||||
|
||||
@@ -293,55 +298,36 @@ void TlmRecorder::openDB(const std::string &dbName)
|
||||
}
|
||||
}
|
||||
|
||||
void TlmRecorder::setUpTransactionTerminatingPhases()
|
||||
{
|
||||
transactionTerminatingPhases.emplace_back(END_RESP);
|
||||
|
||||
// Refresh All
|
||||
transactionTerminatingPhases.push_back(END_REFA);
|
||||
|
||||
// Refresh Bank
|
||||
transactionTerminatingPhases.push_back(END_REFB);
|
||||
|
||||
// Refresh Same Bank
|
||||
transactionTerminatingPhases.push_back(END_REFSB);
|
||||
|
||||
// Phases for Power Down
|
||||
transactionTerminatingPhases.push_back(END_PDNA);
|
||||
transactionTerminatingPhases.push_back(END_PDNP);
|
||||
transactionTerminatingPhases.push_back(END_SREF);
|
||||
}
|
||||
|
||||
void TlmRecorder::prepareSqlStatements()
|
||||
{
|
||||
insertTransactionString =
|
||||
"INSERT INTO Transactions VALUES (:id,:rangeID,:address,:burstlength,:thread,:channel,:rank,"
|
||||
":bankgroup,:bank,:row,:column,:dataStrobeBegin,:dataStrobeEnd, :timeOfGeneration,:command)";
|
||||
|
||||
"INSERT INTO Transactions VALUES (:id,:rangeID,:address,:burstlength,:thread,:channel,:rank,"
|
||||
":bankgroup,:bank,:row,:column,:dataStrobeBegin,:dataStrobeEnd, :timeOfGeneration,:command)";
|
||||
|
||||
insertRangeString = "INSERT INTO Ranges VALUES (:id,:begin,:end)";
|
||||
|
||||
updateRangeString = "UPDATE Ranges SET End = :end WHERE ID = :id";
|
||||
|
||||
updateDataStrobeString =
|
||||
"UPDATE Transactions SET DataStrobeBegin = :begin, DataStrobeEnd = :end WHERE ID = :id";
|
||||
"UPDATE Transactions SET DataStrobeBegin = :begin, DataStrobeEnd = :end WHERE ID = :id";
|
||||
|
||||
insertPhaseString =
|
||||
"INSERT INTO Phases (PhaseName,PhaseBegin,PhaseEnd,Transact) VALUES (:name,:begin,:end,:transaction)";
|
||||
"INSERT INTO Phases (PhaseName,PhaseBegin,PhaseEnd,Transact) VALUES (:name,:begin,:end,:transaction)";
|
||||
|
||||
updatePhaseString =
|
||||
"UPDATE Phases SET PhaseEnd = :end WHERE Transact = :trans AND PhaseName = :name";
|
||||
"UPDATE Phases SET PhaseEnd = :end WHERE Transact = :trans AND PhaseName = :name";
|
||||
|
||||
insertGeneralInfoString =
|
||||
"INSERT INTO GeneralInfo VALUES"
|
||||
"(:numberOfTransactions,:end,:numberOfRanks,:numberOfBankgroups,:numberOfBanks,:clk,:unitOfTime,:mcconfig,:memspec,"
|
||||
":traces,:windowSize, :flexibleRefresh, :maxRefBurst, :controllerThread, :maxBufferDepth)";
|
||||
"INSERT INTO GeneralInfo VALUES"
|
||||
"(:numberOfTransactions,:end,:numberOfRanks,:numberOfBankgroups,:numberOfBanks,:clk,:unitOfTime,:mcconfig,:memspec,"
|
||||
":traces,:windowSize, :flexibleRefresh, :maxRefBurst, :controllerThread, :maxBufferDepth)";
|
||||
|
||||
insertCommandLengthsString =
|
||||
"INSERT INTO CommandLengths VALUES"
|
||||
"(:NOP, :RD, :WR, :RDA, :WRA, :ACT, :PRE, :REFB, :PRESB, :REFSB, :PREA, :REFA, :PDEA, :PDXA, :PDEP, :PDXP, :SREFEN, :SREFEX)";
|
||||
"INSERT INTO CommandLengths VALUES"
|
||||
"(:NOP, :RD, :WR, :RDA, :WRA, :ACT, :PRE, :REFB, :PRESB, :REFSB, :PREA, :REFA, :PDEA, :PDXA, :PDEP, :PDXP, :SREFEN, :SREFEX)";
|
||||
|
||||
insertDebugMessageString =
|
||||
"INSERT INTO DebugMessages (Time,Message) Values (:time,:message)";
|
||||
"INSERT INTO DebugMessages (Time,Message) Values (:time,:message)";
|
||||
|
||||
insertPowerString = "INSERT INTO Power VALUES (:time,:averagePower)";
|
||||
insertBufferDepthString = "INSERT INTO BufferDepth VALUES (:time,:bufferNumber,:averageBufferDepth)";
|
||||
@@ -384,18 +370,18 @@ void TlmRecorder::insertGeneralInfo()
|
||||
sqlite3_bind_int64(insertGeneralInfoStatement, 11, 0);
|
||||
else
|
||||
sqlite3_bind_int64(insertGeneralInfoStatement, 11,
|
||||
static_cast<int64_t>((Configuration::getInstance().memSpec->tCK *
|
||||
Configuration::getInstance().windowSize).value()));
|
||||
|
||||
static_cast<int64_t>((Configuration::getInstance().memSpec->tCK *
|
||||
Configuration::getInstance().windowSize).value()));
|
||||
|
||||
if ((Configuration::getInstance().refreshMaxPostponed > 0)
|
||||
|| (Configuration::getInstance().refreshMaxPulledin > 0))
|
||||
|| (Configuration::getInstance().refreshMaxPulledin > 0))
|
||||
{
|
||||
sqlite3_bind_int(insertGeneralInfoStatement, 12, 1);
|
||||
sqlite3_bind_int(insertGeneralInfoStatement, 13,
|
||||
static_cast<int>(std::max(Configuration::getInstance().refreshMaxPostponed,
|
||||
Configuration::getInstance().refreshMaxPulledin)));
|
||||
}
|
||||
else
|
||||
static_cast<int>(std::max(Configuration::getInstance().refreshMaxPostponed,
|
||||
Configuration::getInstance().refreshMaxPulledin)));
|
||||
}
|
||||
else
|
||||
{
|
||||
sqlite3_bind_int(insertGeneralInfoStatement, 12, 0);
|
||||
sqlite3_bind_int(insertGeneralInfoStatement, 13, 0);
|
||||
@@ -490,7 +476,7 @@ void TlmRecorder::executeSqlStatement(sqlite3_stmt *statement)
|
||||
int errorCode = sqlite3_step(statement);
|
||||
if (errorCode != SQLITE_DONE)
|
||||
SC_REPORT_FATAL("Error in TraceRecorder",
|
||||
(std::string("Could not execute statement. Error code: ") + std::to_string(errorCode)).c_str());
|
||||
(std::string("Could not execute statement. Error code: ") + std::to_string(errorCode)).c_str());
|
||||
|
||||
sqlite3_reset(statement);
|
||||
}
|
||||
@@ -512,6 +498,9 @@ void TlmRecorder::executeInitialSqlCommand()
|
||||
void TlmRecorder::closeConnection()
|
||||
{
|
||||
terminateRemainingTransactions();
|
||||
if (storageThread.joinable())
|
||||
storageThread.join();
|
||||
std::swap(currentDataBuffer, storageDataBuffer);
|
||||
commitRecordedDataToDB();
|
||||
insertGeneralInfo();
|
||||
insertCommandLengths();
|
||||
|
||||
@@ -46,6 +46,7 @@
|
||||
#include <algorithm>
|
||||
#include <fstream>
|
||||
#include <cerrno>
|
||||
#include <thread>
|
||||
#include <tlm.h>
|
||||
#include <systemc.h>
|
||||
#include "sqlite3.h"
|
||||
@@ -116,7 +117,6 @@ private:
|
||||
static void executeSqlStatement(sqlite3_stmt *statement);
|
||||
|
||||
void openDB(const std::string &dbName);
|
||||
void setUpTransactionTerminatingPhases();
|
||||
|
||||
void introduceTransactionSystem(tlm::tlm_generic_payload &trans);
|
||||
void removeTransactionFromSystem(tlm::tlm_generic_payload &trans);
|
||||
@@ -131,24 +131,27 @@ private:
|
||||
uint64_t transactionID);
|
||||
void insertDebugMessageInDB(const std::string &message, const sc_time &time);
|
||||
|
||||
static constexpr unsigned transactionCommitRate = 1024;
|
||||
std::vector<Transaction> recordedData;
|
||||
static constexpr unsigned transactionCommitRate = 8192;
|
||||
std::array<std::vector<Transaction>, 2> recordingDataBuffer;
|
||||
std::vector<Transaction> *currentDataBuffer;
|
||||
std::vector<Transaction> *storageDataBuffer;
|
||||
std::thread storageThread;
|
||||
|
||||
std::unordered_map<tlm::tlm_generic_payload *, Transaction> currentTransactionsInSystem;
|
||||
|
||||
uint64_t totalNumTransactions;
|
||||
sc_time simulationTimeCoveredByRecording;
|
||||
|
||||
std::vector<tlm::tlm_phase> transactionTerminatingPhases;
|
||||
sqlite3 *db = nullptr;
|
||||
sqlite3_stmt *insertTransactionStatement, *insertRangeStatement,
|
||||
*updateRangeStatement, *insertPhaseStatement, *updatePhaseStatement,
|
||||
*insertGeneralInfoStatement, *insertCommandLengthsStatement,
|
||||
*insertDebugMessageStatement, *updateDataStrobeStatement,
|
||||
*insertPowerStatement, *insertBufferDepthStatement, *insertBandwidthStatement;
|
||||
*updateRangeStatement, *insertPhaseStatement, *updatePhaseStatement,
|
||||
*insertGeneralInfoStatement, *insertCommandLengthsStatement,
|
||||
*insertDebugMessageStatement, *updateDataStrobeStatement,
|
||||
*insertPowerStatement, *insertBufferDepthStatement, *insertBandwidthStatement;
|
||||
std::string insertTransactionString, insertRangeString, updateRangeString, insertPhaseString,
|
||||
updatePhaseString, insertGeneralInfoString, insertCommandLengthsString,
|
||||
insertDebugMessageString, updateDataStrobeString, insertPowerString,
|
||||
insertBufferDepthString, insertBandwidthString;
|
||||
updatePhaseString, insertGeneralInfoString, insertCommandLengthsString,
|
||||
insertDebugMessageString, updateDataStrobeString, insertPowerString,
|
||||
insertBufferDepthString, insertBandwidthString;
|
||||
|
||||
std::string initialCommand =
|
||||
"DROP TABLE IF EXISTS Phases; \n"
|
||||
@@ -265,4 +268,3 @@ private:
|
||||
};
|
||||
|
||||
#endif // TLMRECORDER_H
|
||||
|
||||
|
||||
@@ -88,24 +88,24 @@ class Command
|
||||
public:
|
||||
enum Type : uint8_t
|
||||
{
|
||||
NOP,
|
||||
RD,
|
||||
WR,
|
||||
RDA,
|
||||
WRA,
|
||||
ACT,
|
||||
PRE,
|
||||
REFB,
|
||||
PRESB,
|
||||
REFSB,
|
||||
PREA,
|
||||
REFA,
|
||||
PDEA,
|
||||
PDEP,
|
||||
SREFEN,
|
||||
PDXA,
|
||||
PDXP,
|
||||
SREFEX
|
||||
NOP, // 0
|
||||
RD, // 1
|
||||
WR, // 2
|
||||
RDA, // 3
|
||||
WRA, // 4
|
||||
ACT, // 5
|
||||
PRE, // 6
|
||||
REFB, // 7
|
||||
PRESB, // 8
|
||||
REFSB, // 9
|
||||
PREA, // 10
|
||||
REFA, // 11
|
||||
PDEA, // 12
|
||||
PDEP, // 13
|
||||
SREFEN, // 14
|
||||
PDXA, // 15
|
||||
PDXP, // 16
|
||||
SREFEX // 17
|
||||
};
|
||||
|
||||
private:
|
||||
|
||||
@@ -50,9 +50,11 @@ StlPlayer::StlPlayer(const sc_module_name &name,
|
||||
TraceSetup *setup,
|
||||
bool relative) :
|
||||
TrafficInitiator(name, setup, maxPendingReadRequests, maxPendingWriteRequests),
|
||||
file(pathToTrace), currentBuffer(&lineContents[0]), parseBuffer(&lineContents[1]),
|
||||
relative(relative), playerClk(playerClk)
|
||||
file(pathToTrace), relative(relative), playerClk(playerClk)
|
||||
{
|
||||
currentBuffer = &lineContents[0];
|
||||
parseBuffer = &lineContents[1];
|
||||
|
||||
if (!file.is_open())
|
||||
SC_REPORT_FATAL("StlPlayer", (std::string("Could not open trace ") + pathToTrace).c_str());
|
||||
else
|
||||
|
||||
Reference in New Issue
Block a user