Use separate thread for database creation.

This commit is contained in:
Lukas Steiner
2021-06-01 11:11:40 +02:00
parent d6b8e73827
commit 9949c36f83
4 changed files with 89 additions and 96 deletions

View File

@@ -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();

View File

@@ -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

View File

@@ -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:

View File

@@ -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