Files
DRAMSys/DRAMSys/simulator/src/simulation/Simulation.cpp
2016-06-20 19:46:49 +02:00

265 lines
9.5 KiB
C++

/*
* Copyright (c) 2015, University of Kaiserslautern
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* 3. Neither the name of the copyright holder nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER
* OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* Authors:
* Janik Schlemminger
* Matthias Jung
* Eder F. Zulian
*/
#include <stdlib.h>
#include <iostream>
#include <fstream>
#include <vector>
#include "Simulation.h"
#include "../common/TlmRecorder.h"
#include "../common/DebugManager.h"
#include "../common/xmlAddressdecoder.h"
#include "../controller/core/ControllerCore.h"
#include "../controller/core/configuration/ConfigurationLoader.h"
#include "../common/Utils.h"
#include "../simulation/StlDataPlayer.h"
#include "../simulation/TemperatureController.h"
#include "../controller/Controller.h"
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)
{
SC_THREAD(stop);
// XXX: The xmlAddressDecoder MUST be initialized before calling the
// ConfigurationLoader because some information from the xmlAddressDecoder
// is needed to assure the coherence of the configuration.
xmlAddressDecoder::Initialize(setup.addressmapping);
xmlAddressDecoder::getInstance().print();
ConfigurationLoader::loadMemConfig(Configuration::getInstance(), setup.memconfig);
ConfigurationLoader::loadMemSpec(Configuration::getInstance(), setup.memspec);
ConfigurationLoader::loadSimConfig(Configuration::getInstance(), setup.simconfig);
ConfigurationLoader::loadTemperatureSimConfig(Configuration::getInstance(), setup.thermalsimconfig);
instantiateModules(traceName, pathToResources, devices);
bindSockets();
setupDebugManager(traceName);
}
void Simulation::setupDebugManager(const string& traceName)
{
auto& dbg = DebugManager::getInstance();
dbg.writeToConsole = true;
dbg.writeToFile = true;
if(dbg.writeToFile)
dbg.openDebugFile(traceName + ".txt");
}
void Simulation::setupTlmRecorders(const string &traceName, const string &pathToResources, const std::vector<Device> &devices)
{
// 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";
std::string recorderName = "tlmRecorder" + std::to_string(i);
TlmRecorder *tlmRecorder = new TlmRecorder(recorderName.c_str(), sqlScriptURI.c_str(), dbName.c_str(), Configuration::getInstance().DatabaseRecording);
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);
if (i == devices.size() - 1)
continue;
traceNames.append(",");
}
tlmRecorder->recordTracenames(traceNames);
}
}
void Simulation::instantiateModules(const string &traceName, const string &pathToResources, const std::vector<Device> &devices)
{
// The first call to getInstance() creates the Temperature Controller.
// The same instance will be accessed by all other modules.
TemperatureController::getInstance();
for (size_t i = 0; i < Configuration::getInstance().NumberOfTracePlayers; i++) {
std::string playerStr = "tracePlayer" + std::to_string(i);
TracePlayer<> *player;
// When data should be stored during the simulation the StlDataPlayer is needed.
// Else: no data should be stored, for instance to get a faster simulation
// or if you simply dont care about the data the normal StlPlayer is used.
if(Configuration::getInstance().ErrorStoreMode == ErrorStorageMode::NoStorage)
{
StlPlayer<> *newPlayer = new StlPlayer<>(playerStr.c_str(), pathToResources + string("traces/") + devices[i].trace, devices[i].clkMhz, this);
player = newPlayer;
newPlayer->getTraceLength(pathToResources + string("traces/") + devices[i].trace);
totalTransactions += newPlayer->getNumberOfLines(pathToResources + string("traces/") + devices[i].trace);
}
else
{
StlDataPlayer<> *newPlayer = new StlDataPlayer<>(playerStr.c_str(), pathToResources + string("traces/") + devices[i].trace, devices[i].clkMhz, this);
player = newPlayer;
newPlayer->getTraceLength(pathToResources + string("traces/") + devices[i].trace);
totalTransactions += newPlayer->getNumberOfLines(pathToResources + string("traces/") + devices[i].trace);
}
players.push_back(player);
}
remainingTransactions = totalTransactions;
//player->remainingTransactions = player->totalTransactions;
// 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(), tlmRecorders[i]);
controllers.push_back(controller);
str = "dram" + std::to_string(i);
Dram<> *dram = new Dram<>(str.c_str());
dram->setTlmRecorder(tlmRecorders[i]);
dram->setDramController(controllers[i]);
drams.push_back(dram);
}
}
void Simulation::bindSockets()
{
for (auto player : players) {
player->iSocket.bind(arbiter->tSocket);
}
for (size_t i = 0; i < Configuration::getInstance().NumberOfMemChannels; i++) {
arbiter->iSocket.bind(controllers[i]->tSocket);
controllers[i]->iSocket.bind(drams[i]->tSocket);
}
}
Simulation::~Simulation()
{
for (auto player : players) {
delete player;
}
delete arbiter;
for (auto controller : controllers) {
delete controller;
}
for (auto dram : drams) {
delete dram;
}
for (auto rec : tlmRecorders) {
delete rec;
}
}
void Simulation::start()
{
report("\n\nStarting simulation:");
report(headline);
report(" -> setup: \t\t" + getFileName(traceName));
report(" -> memspec: \t\t" + Configuration::getInstance().memSpec.MemoryId);
cout << endl;
simulationStartTime = clock();
for (auto player : players) {
player->nextPayload();
}
sc_set_stop_mode(SC_STOP_FINISH_DELTA);
sc_start();
}
void inline Simulation::tracePlayerTerminates()
{
static unsigned int finishedTracePlayers = 0;
finishedTracePlayers++;
if (finishedTracePlayers == Configuration::getInstance().NumberOfTracePlayers)
terminateSimulation.notify();
}
void Simulation::stop()
{
wait(terminateSimulation);
unsigned int pending_payloads = 0;
do {
pending_payloads = 0;
for (auto controller : controllers) {
pending_payloads += controller->getTotalNumberOfPayloadsInSystem();
}
wait(sc_time(200, SC_NS));
} while(pending_payloads != 0);
report("\nTerminating simulation");
for (auto controller : controllers) {
controller->terminateSimulation();
}
wait(sc_time(200, SC_NS));
for (auto rec : tlmRecorders) {
rec->closeConnection();
}
sc_stop();
double elapsed_secs = double(clock() - simulationStartTime) / CLOCKS_PER_SEC;
report("Simulation took " + to_string(elapsed_secs) + " seconds");
}
void inline Simulation::transactionFinished()
{
remainingTransactions--;
loadbar(totalTransactions - remainingTransactions, totalTransactions);
if (remainingTransactions == 0)
{
cout << endl;
}
}
void Simulation::report(string message)
{
DebugManager::getInstance().printDebugMessage(this->name(), message);
cout << message << endl;
}