Support to multiple TLM recorders - one per channel.

Each module connected to a channel (e.g. channel Controller and DRAM) is able
to access the TLM recorder for that channel.

A module connected to more than one channel must be able to access
multiple TLM recorders (one from each channel) and must also be able to decide
for which TLM recorder records a transaction should be forwarded. The Arbiter
is an example of this kind of module and is currently able to do that.

Output file names after this implementation:

<trace setup ID>_channel[0-9]+.tdb (dependent on the number of channels)
<trace setup ID>.txt (a single file, independent of the number of channels)

Tests were made with this sim-batch.xml:

<simulation>
    <simconfig>
        <Debug value="1" />
        <DatabaseRecording value="1" />
        <PowerAnalysis value="1" />
        <NumberOfTracePlayers value="1"/>
        <NumberOfMemChannels value="4"/>
    </simconfig>

    <memspecs>
        <memspec src="../../DRAMSys/dramSys/resources/configs/memspecs/WideIO.xml"></memspec>
    </memspecs>

    <addressmappings>
        <addressmapping src="../../DRAMSys/dramSys/resources/configs/amconfigs/am_wideio.xml"></addressmapping>
    </addressmappings>

    <memconfigs>
        <memconfig src="../../DRAMSys/dramSys/resources/configs/memconfigs/fifo.xml"/>
    </memconfigs>

    <tracesetups>
        <tracesetup id="fifo">
            <device clkMhz="200">wideio_multi_channel.stl</device>
        </tracesetup>
    </tracesetups>
</simulation>

Output files generated:

fifo_channel0.tdb
fifo_channel1.tdb
fifo_channel2.tdb
fifo_channel3.tdb
fifo.txt
This commit is contained in:
Éder Ferreira Zulian
2015-06-25 13:54:01 +02:00
parent f3d8d596bf
commit 6051946389
21 changed files with 105 additions and 84 deletions

View File

@@ -35,29 +35,21 @@
* Matthias Jung
*/
#include <iostream>
#include <algorithm>
#include <boost/filesystem.hpp>
#include "TlmRecorder.h"
#include "protocol.h"
#include "dramExtension.h"
#include "xmlAddressdecoder.h"
#include "../controller/core/configuration/Configuration.h"
#include <iostream>
#include <algorithm>
#include <boost/filesystem.hpp>
using namespace std;
string TlmRecorder::dbName = "";
string TlmRecorder::sqlScriptURI = "";
string TlmRecorder::senderName = "TlmRecorder";
bool TlmRecorder::recordingEnabled = true;
// ------------- public -----------------------
TlmRecorder::TlmRecorder() :
totalNumTransactions(1), simulationTimeCoveredByRecording(SC_ZERO_TIME)
TlmRecorder::TlmRecorder(string uri, string dbname, bool recenable) : sqlScriptURI(uri), dbName(dbname), senderName("TlmRecorder"), recordingEnabled(recenable), totalNumTransactions(1), simulationTimeCoveredByRecording(SC_ZERO_TIME)
{
if(recordingEnabled)
{
if (TlmRecorder::recordingEnabled == true) {
recordedData.reserve(transactionCommitRate);
setUpTransactionTerminatingPhases();
openDB(TlmRecorder::dbName.c_str());

View File

@@ -52,22 +52,17 @@
#include "DebugManager.h"
#include "Utils.h"
using namespace std;
class TlmRecorder
{
class TlmRecorder {
public:
static std::string sqlScriptURI;
static std::string dbName;
static std::string senderName;
static bool recordingEnabled;
std::string sqlScriptURI;
std::string dbName;
std::string senderName;
bool recordingEnabled;
static inline TlmRecorder& getInstance()
{
static TlmRecorder decoder;
return decoder;
}
TlmRecorder(string uri, string dbname, bool recenable);
~TlmRecorder();
void recordMemconfig(string memconfig){this->memconfig = memconfig;}
void recordMemspec(string memspec){this->memspec = memspec;}
@@ -106,9 +101,6 @@ private:
std::string memconfig,memspec,traces;
TlmRecorder();
~TlmRecorder();
void prepareSqlStatements();
void executeSqlCommand(std::string command);
void executeSqlStatement(sqlite3_stmt* statement);
@@ -143,4 +135,6 @@ private:
std::string insertTransactionString, insertRangeString, updateRangeString, insertPhaseString, updatePhaseString, insertGeneralInfoString,
insertDebugMessageString, updateDataStrobeString;
};
#endif

View File

@@ -74,9 +74,8 @@ template<unsigned int BUSWIDTH = 128>
struct Controller: public sc_module, public IController
{
public:
Controller(sc_module_name /*name*/) :
frontendPEQ(this, &Controller<BUSWIDTH>::frontendPEQCallback), dramPEQ(this, &Controller<BUSWIDTH>::dramPEQCallback), controllerCorePEQ(
this, &Controller<BUSWIDTH>::controllerCorePEQCallback), debugManager(DebugManager::getInstance())
Controller(sc_module_name /*name*/, TlmRecorder *rec) :
frontendPEQ(this, &Controller<BUSWIDTH>::frontendPEQCallback), dramPEQ(this, &Controller<BUSWIDTH>::dramPEQCallback), controllerCorePEQ(this, &Controller<BUSWIDTH>::controllerCorePEQCallback), debugManager(DebugManager::getInstance()), tlmRecorder(rec)
{
controllerCore = new ControllerCore(*this, numberOfPayloadsInSystem);
buildScheduler();
@@ -91,7 +90,6 @@ public:
delete scheduler;
}
void terminateSimulation();
// ------- CONTROLLER CORE ---------
virtual void send(const ScheduledCommand& command, tlm_generic_payload& payload) override;
@@ -137,6 +135,7 @@ private:
tlm_utils::peq_with_cb_and_phase<Controller> controllerCorePEQ;
DebugManager& debugManager;
TlmRecorder *tlmRecorder;
};
// --- IMPLEMENTATION -----
@@ -181,22 +180,22 @@ void Controller<BUSWIDTH>::send(const ScheduledCommand &command, tlm_generic_pay
//TODO: refactor tlm recorder
case Command::Read:
dataStrobe = command.getIntervalOnDataStrobe();
TlmRecorder::getInstance().updateDataStrobe(dataStrobe.start, dataStrobe.end, payload);
tlmRecorder->updateDataStrobe(dataStrobe.start, dataStrobe.end, payload);
controllerCorePEQ.notify(payload, BEGIN_RD, command.getStart() - sc_time_stamp());
break;
case Command::ReadA:
dataStrobe = command.getIntervalOnDataStrobe();
TlmRecorder::getInstance().updateDataStrobe(dataStrobe.start, dataStrobe.end, payload);
tlmRecorder->updateDataStrobe(dataStrobe.start, dataStrobe.end, payload);
controllerCorePEQ.notify(payload, BEGIN_RDA, command.getStart() - sc_time_stamp());
break;
case Command::Write:
dataStrobe = command.getIntervalOnDataStrobe();
TlmRecorder::getInstance().updateDataStrobe(dataStrobe.start, dataStrobe.end, payload);
tlmRecorder->updateDataStrobe(dataStrobe.start, dataStrobe.end, payload);
controllerCorePEQ.notify(payload, BEGIN_WR, command.getStart() - sc_time_stamp());
break;
case Command::WriteA:
dataStrobe = command.getIntervalOnDataStrobe();
TlmRecorder::getInstance().updateDataStrobe(dataStrobe.start, dataStrobe.end, payload);
tlmRecorder->updateDataStrobe(dataStrobe.start, dataStrobe.end, payload);
controllerCorePEQ.notify(payload, BEGIN_WRA, command.getStart() - sc_time_stamp());
break;
case Command::AutoRefresh:
@@ -352,13 +351,13 @@ tlm_sync_enum Controller<BUSWIDTH>::nb_transport_fw(tlm_generic_payload &payload
{
if (phase == BEGIN_REQ)
{
TlmRecorder::getInstance().recordPhase(payload, phase, fwDelay + sc_time_stamp());
tlmRecorder->recordPhase(payload, phase, fwDelay + sc_time_stamp());
frontendPEQ.notify(payload, phase,
clkAlign(sc_time_stamp() + fwDelay) - (sc_time_stamp() + fwDelay) + Configuration::getInstance().memSpec.clk);
}
else if (phase == END_RESP)
{
TlmRecorder::getInstance().recordPhase(payload, phase,
tlmRecorder->recordPhase(payload, phase,
fwDelay + sc_time_stamp() + Configuration::getInstance().memSpec.clk);
frontendPEQ.notify(payload, phase, clkAlign(sc_time_stamp() + fwDelay) - (sc_time_stamp() + fwDelay));
}
@@ -473,7 +472,7 @@ template<unsigned int BUSWIDTH>
tlm_sync_enum Controller<BUSWIDTH>::nb_transport_bw(tlm_generic_payload &payload, tlm_phase &phase, sc_time &bwDelay)
{
dramPEQ.notify(payload, phase, bwDelay);
TlmRecorder::getInstance().recordPhase(payload, phase, bwDelay + sc_time_stamp());
tlmRecorder->recordPhase(payload, phase, bwDelay + sc_time_stamp());
return TLM_ACCEPTED;
}
@@ -573,3 +572,4 @@ void Controller<BUSWIDTH>::terminateSimulation()
}
#endif /* CONTROLLERWRAPPER_H_ */

View File

@@ -38,6 +38,7 @@
#include <algorithm>
#include "core/TimingCalculation.h"
using namespace std;
const ScheduledCommand ControllerState::getLastCommand(Command command, Bank bank) //TODO const reference? and make const
{

View File

@@ -40,15 +40,16 @@
#include <tlm.h>
#include <map>
#include <utility>
#include <string>
#include "../IController.h"
#include "configuration/Configuration.h"
#include "powerdown/PowerDownManager.h"
#include "refresh/IRefreshManager.h"
#include "scheduling/checker/ICommandChecker.h"
#include "../../common/TlmRecorder.h"
#include "../RowBufferStates.h"
#include "../ControllerState.h"
using namespace std;
class ControllerCore
{

View File

@@ -93,3 +93,4 @@ private:
};
#endif /* CONFIGURATION_H_ */

View File

@@ -149,6 +149,5 @@ struct MemSpec
sc_time tDataStrobeHistory(){return tWTR_L;}
};
#endif /* MemSpec_H_ */

View File

@@ -37,6 +37,7 @@
#include "PowerDownManager.h"
#include "../ControllerCore.h"
#include "../../../common/Utils.h"
#include "../../../common/DebugManager.h"
#include "../TimingCalculation.h"
using namespace tlm;

View File

@@ -38,6 +38,7 @@
#include "PowerDownManagerTimeout.h"
#include "../ControllerCore.h"
#include "../../../common/Utils.h"
#include "../../../common/DebugManager.h"
#include "../TimingCalculation.h"
using namespace tlm;

View File

@@ -41,10 +41,8 @@
#include <tlm.h>
#include "../../Command.h"
#include "../../../common/dramExtension.h"
#include "../../../common/TlmRecorder.h"
#include "../../../common/Utils.h"
class ScheduledCommand
{
public:
@@ -88,7 +86,6 @@ public:
TimeInterval getIntervalOnDataStrobe() const;
private:
Command command;
sc_time start;
@@ -98,3 +95,4 @@ private:
};
#endif /* SCHEDULEDCOMMAND_H_ */

View File

@@ -34,6 +34,7 @@
* Matthias Jung
*/
#include <iostream>
#include <algorithm>
#include <set>
#include "ActivateChecker.h"
@@ -41,7 +42,8 @@
#include "../../../../common/DebugManager.h"
#include "../../../Command.h"
#include "../../../../common/Utils.h"
#include <iostream>
using namespace std;
void ActivateChecker::delayToSatisfyConstraints(ScheduledCommand& command) const
{

View File

@@ -39,6 +39,8 @@
#include "../../../../common/Utils.h"
#include "WriteChecker.h"
using namespace std;
void ReadChecker::delayToSatisfyConstraints(ScheduledCommand& command) const
{
sc_assert(command.getCommand() == Command::Read || command.getCommand() == Command::ReadA);
@@ -132,4 +134,3 @@ sc_time ReadChecker::writeToRead(ScheduledCommand& write, ScheduledCommand& read
return config.tWL + getWriteAccessTime() + tWTR;
}

View File

@@ -41,7 +41,6 @@
#include "../../configuration/Configuration.h"
#include "../../../ControllerState.h"
class ReadChecker: public ICommandChecker
{
public:
@@ -62,5 +61,5 @@ private:
bool collidesWithStrobeCommand(ScheduledCommand& read, ScheduledCommand& strobeCommand) const;
};
#endif /* READCHECKER_H_ */

View File

@@ -39,6 +39,7 @@
#include "../../../../common/Utils.h"
#include "ReadChecker.h"
using namespace std;
void WriteChecker::delayToSatisfyConstraints(ScheduledCommand& command) const
{

View File

@@ -81,6 +81,11 @@ public:
}
}
void setTlmRecorders(std::vector<TlmRecorder*> recorders)
{
tlmRecorders = recorders;
}
private:
tlm_utils::peq_with_cb_and_phase<Arbiter> payloadEventQueue;
@@ -93,11 +98,13 @@ private:
// This is a queue of responses comming from the memory side. The phase of these transactions is BEGIN_RESP.
vector<queue<tlm_generic_payload*>> receivedResponses;
std::vector<TlmRecorder*> tlmRecorders;
// Initiated by dram side
// This function is called when an arbiter's initiator socket receives a transaction from a memory controller
tlm_sync_enum nb_transport_bw(__attribute__((unused)) int id, tlm_generic_payload& payload, tlm_phase& phase, sc_time& bwDelay)
tlm_sync_enum nb_transport_bw(int channelId, tlm_generic_payload &payload, tlm_phase &phase, sc_time &bwDelay)
{
TlmRecorder::getInstance().recordPhase(payload, phase, bwDelay + sc_time_stamp());
tlmRecorders[channelId]->recordPhase(payload, phase, bwDelay + sc_time_stamp());
payloadEventQueue.notify(payload, phase, bwDelay);
return TLM_ACCEPTED;
}

View File

@@ -59,7 +59,7 @@ using namespace Data;
template<unsigned int BUSWIDTH = 128, unsigned int WORDS = 4096, bool STORE = true, bool FIXED_BL = false,
unsigned int FIXED_BL_VALUE = 0>
struct Dram: sc_module
struct Dram : sc_module
{
// TLM Related:
tlm_utils::simple_target_socket<Dram, BUSWIDTH, tlm::tlm_base_protocol_types> tSocket;
@@ -75,6 +75,8 @@ struct Dram: sc_module
// Data Storage:
map< unsigned long int, unsigned char[BUSWIDTH/2] > memory;
TlmRecorder *tlmRecorder;
SC_CTOR(Dram) : tSocket("socket")
{
tSocket.register_nb_transport_fw(this, &Dram::nb_transport_fw);
@@ -194,7 +196,7 @@ struct Dram: sc_module
virtual tlm::tlm_sync_enum nb_transport_fw(tlm::tlm_generic_payload& payload, tlm::tlm_phase& phase, sc_time& delay)
{
TlmRecorder::getInstance().recordPhase(payload, phase, sc_time_stamp() + delay);
tlmRecorder->recordPhase(payload, phase, sc_time_stamp() + delay);
// This is only needed for power simulation:
unsigned long long cycle = 0;
@@ -437,6 +439,10 @@ struct Dram: sc_module
DebugManager::getInstance().printDebugMessage(name(), message);
}
void setTlmRecorder(TlmRecorder *rec)
{
tlmRecorder = rec;
}
};
#endif /* DRAM_H_ */

View File

@@ -52,9 +52,7 @@
using namespace std;
Simulation::Simulation(sc_module_name __attribute__((unused)) name, string pathToResources, string traceName, DramSetup setup,
std::vector<Device> devices) :
traceName(traceName), dramSetup(setup)
std::vector<Device> devices) : traceName(traceName), dramSetup(setup)
{
SC_THREAD(stop);
@@ -65,8 +63,7 @@ Simulation::Simulation(sc_module_name __attribute__((unused)) name, string pathT
ConfigurationLoader::loadMemSpec(Configuration::getInstance(), setup.memspec);//pathToResources + string("configs/memspecs/") + setup.memspec);
ConfigurationLoader::loadSimConfig(Configuration::getInstance(), setup.simconfig);
setupTlmRecorder(traceName, pathToResources, devices);
instantiateModules(pathToResources, devices);
instantiateModules(traceName, pathToResources, devices);
bindSockets();
setupDebugManager(traceName);
}
@@ -81,15 +78,20 @@ void Simulation::setupDebugManager(const string& traceName)
dbg.openDebugFile(traceName + ".txt");
}
void Simulation::setupTlmRecorder(const string &traceName, const string &pathToResources, const std::vector<Device> &devices)
void Simulation::setupTlmRecorders(const string &traceName, const string &pathToResources, const std::vector<Device> &devices)
{
if(Configuration::getInstance().DatabaseRecording)
{
TlmRecorder::recordingEnabled = true;
TlmRecorder::dbName = traceName;
TlmRecorder::sqlScriptURI = pathToResources + string("scripts/createTraceDB.sql");
TlmRecorder::getInstance().recordMemconfig(Configuration::getInstance().memconfigUri);
TlmRecorder::getInstance().recordMemspec(Configuration::getInstance().memspecUri);
// Create TLM Recorders, one per channel.
for (size_t i = 0; i < Configuration::getInstance().NumberOfMemChannels; i++) {
std::string sqlScriptURI = pathToResources + string("scripts/createTraceDB.sql");
std::string dbName = traceName + string("_channel") + std::to_string(i) + ".tdb";
TlmRecorder *tlmRecorder = new TlmRecorder(sqlScriptURI.c_str(), dbName.c_str(), true);
tlmRecorder->recordMemconfig(Configuration::getInstance().memconfigUri);
tlmRecorder->recordMemspec(Configuration::getInstance().memspecUri);
tlmRecorders.push_back(tlmRecorder);
std::string traceNames;
for (size_t i = 0; i < devices.size(); i++) {
traceNames.append(devices[i].trace);
@@ -97,15 +99,19 @@ void Simulation::setupTlmRecorder(const string &traceName, const string &pathToR
continue;
traceNames.append(",");
}
TlmRecorder::getInstance().recordTracenames(traceNames);
tlmRecorder->recordTracenames(traceNames);
}
else
{
TlmRecorder::recordingEnabled = false;
// Enable all TLM Recorders. TODO: maybe individually?
for (auto rec : tlmRecorders) {
if (Configuration::getInstance().DatabaseRecording == true)
rec->recordingEnabled = true;
else
rec->recordingEnabled = false;
}
}
void Simulation::instantiateModules(const string &pathToResources, const std::vector<Device>& devices)
void Simulation::instantiateModules(const string &traceName, const string &pathToResources, const std::vector<Device> &devices)
{
for (size_t i = 0; i < Configuration::getInstance().NumberOfTracePlayers; i++) {
std::string playerStr = "player" + std::to_string(i);
@@ -113,15 +119,20 @@ void Simulation::instantiateModules(const string &pathToResources, const std::ve
players.push_back(player);
}
// Create and properly initialize TLM recorders. They need to be ready before creating some modules.
setupTlmRecorders(traceName, pathToResources, devices);
arbiter = new Arbiter<128>("arbiter");
arbiter->setTlmRecorders(tlmRecorders);
for (size_t i = 0; i < Configuration::getInstance().NumberOfMemChannels; i++) {
std::string str = "controller" + std::to_string(i);
Controller<> *controller = new Controller<>(str.c_str());
Controller<> *controller = new Controller<>(str.c_str(), tlmRecorders[i]);
controllers.push_back(controller);
str = "dram" + std::to_string(i);
Dram<> *dram = new Dram<>(str.c_str());
dram->setTlmRecorder(tlmRecorders[i]);
drams.push_back(dram);
}
}
@@ -153,6 +164,10 @@ Simulation::~Simulation()
for (auto dram : drams) {
delete dram;
}
for (auto rec : tlmRecorders) {
delete rec;
}
}
void Simulation::start()
@@ -189,7 +204,9 @@ void Simulation::stop()
controller->terminateSimulation();
}
wait(sc_time(200, SC_NS));
TlmRecorder::getInstance().closeConnection();
for (auto rec : tlmRecorders) {
rec->closeConnection();
}
sc_stop();
double elapsed_secs = double(clock() - simulationStartTime) / CLOCKS_PER_SEC;

View File

@@ -104,13 +104,16 @@ private:
ReorderBuffer<> *reorder;
// DRAM units
std::vector<Dram<>*> drams;
// Transaction Recorders (one per channel). They generate the output databases.
std::vector<TlmRecorder*> tlmRecorders;
clock_t simulationStartTime;
void report(std::string message);
void setupDebugManager(const string& traceName);
void setupTlmRecorder(const string &traceName, const string &pathToResources, const std::vector<Device> &devices);
void setupTlmRecorders(const string &traceName, const string &pathToResources, const std::vector<Device> &devices);
void instantiateModules(const string &pathToResources, const std::vector<Device> &devices);
void bindSockets();
void setupDebugManager(const string& traceName);
};
#endif /* SIMULATIONMANAGER_H_ */

View File

@@ -87,7 +87,7 @@ void SimulationManager::runSimulations()
{
for (auto& traceSetup : batch.traceSetups)
{
string exportname = exportPath + "/" + traceSetup.first + ".tdb";
string exportname = exportPath + "/" + traceSetup.first;
runSimulation(exportname, dramSetup, traceSetup.second);
}
}

View File

@@ -48,7 +48,6 @@
#include "../controller/core/configuration/Configuration.h"
#include "../common/DebugManager.h"
#include "../common/xmlAddressdecoder.h"
#include "../common/TlmRecorder.h"
#include "../common/dramExtension.h"
#include "../controller/core/TimingCalculation.h"
#include "TracePlayerListener.h"
@@ -81,8 +80,6 @@ private:
TracePlayerListener* listener;
};
template<unsigned int BUSWIDTH>
TracePlayer<BUSWIDTH>::TracePlayer(TracePlayerListener* listener) :
payloadEventQueue(this, &TracePlayer<BUSWIDTH>::peqCallback), transactionsSent(0), listener(listener)
@@ -90,7 +87,6 @@ TracePlayer<BUSWIDTH>::TracePlayer(TracePlayerListener* listener) :
iSocket.register_nb_transport_bw(this, &TracePlayer<BUSWIDTH>::nb_transport_bw);
}
template<unsigned int BUSWIDTH>
gp *TracePlayer<BUSWIDTH>::allocatePayload()
{

View File

@@ -322,9 +322,10 @@ Below are listed the configuration sections and configuration fields.
- **Trace setups**
- *id* (string)
- Trace setup id. Two files are generated by DRAMSys: an SQLite database
file (.tdb) and a text file (.txt) containing the program output. The
name of these files comes from this field.
- Trace setup id. Two kinds of output files are generated by DRAMSys:
SQLite databases containing transactions related to each memory channel
(.tdb) and a text file (.txt) with the program output. The base name for
these files comes from this field.
- *clkMhz* (unsigned int)
- Speed of the trace player
- *bl* (unsigned int)