diff --git a/DRAMSys/analyzer/businessObjects/generalinfo.h b/DRAMSys/analyzer/businessObjects/generalinfo.h index e103f47c..46b6b3ee 100644 --- a/DRAMSys/analyzer/businessObjects/generalinfo.h +++ b/DRAMSys/analyzer/businessObjects/generalinfo.h @@ -49,10 +49,11 @@ struct GeneralInfo QString description; QString unitOfTime; unsigned int clkPeriod; + unsigned long long timeWindowSize; public: - GeneralInfo(unsigned int numberOfTransactions,unsigned int numberOfPhases, Timespan span,unsigned int numberOfBanks,const QString& description, QString unitOfTime,unsigned int clkPeriod) : - numberOfTransactions(numberOfTransactions) , numberOfPhases(numberOfPhases), span(span), numberOfBanks(numberOfBanks), description(description), unitOfTime(unitOfTime),clkPeriod(clkPeriod) + GeneralInfo(unsigned int numberOfTransactions,unsigned int numberOfPhases,Timespan span,unsigned int numberOfBanks,const QString& description, QString unitOfTime,unsigned int clkPeriod, unsigned long long timeWindowSize) : + numberOfTransactions(numberOfTransactions) , numberOfPhases(numberOfPhases),span(span), numberOfBanks(numberOfBanks), description(description), unitOfTime(unitOfTime), clkPeriod(clkPeriod), timeWindowSize(timeWindowSize) { } diff --git a/DRAMSys/analyzer/data/tracedb.cpp b/DRAMSys/analyzer/data/tracedb.cpp index 89cd17cb..115dc46a 100644 --- a/DRAMSys/analyzer/data/tracedb.cpp +++ b/DRAMSys/analyzer/data/tracedb.cpp @@ -199,7 +199,7 @@ ID TraceDB::getTransactionIDFromPhaseID(ID phaseID) GeneralInfo TraceDB::getGeneralInfoFromDB() { QSqlQuery query(database); - query.prepare("SELECT NumberOfTransactions,TraceEnd,NumberOfBanks,Clk,UnitOfTime,Traces,Memspec,Memconfig FROM GeneralInfo"); + query.prepare("SELECT NumberOfTransactions,TraceEnd,NumberOfBanks,Clk,UnitOfTime,Traces,Memspec,Memconfig,TimeWindowSize FROM GeneralInfo"); executeQuery(query); if(query.next()) @@ -214,15 +214,17 @@ GeneralInfo TraceDB::getGeneralInfoFromDB() QString traces = "Traces: " + query.value(5).toString(); QString memspec = "Memspec: " + query.value(6).toString(); QString memconfig = "Memconfig: " + query.value(7).toString(); + unsigned long long timeWindowSize = query.value(8).toLongLong(); QString description = (traces + "\n"); description += memconfig + "\n"; description += memspec + "\n"; description += "Number of Transactions: " + QString::number(numberOfTransactions) + "\n"; description += "Clock period: " + QString::number(clkPeriod) + " " + unitOfTime + "\n"; - description += "Length of trace: " + prettyFormatTime(traceEnd); + description += "Length of trace: " + prettyFormatTime(traceEnd) + "\n"; + description += "Time windows size: " + prettyFormatTime(timeWindowSize); - return GeneralInfo(numberOfTransactions, numberOfPhases, Timespan(0,traceEnd),numberOfBanks,description,unitOfTime,clkPeriod); + return GeneralInfo(numberOfTransactions, numberOfPhases, Timespan(0,traceEnd),numberOfBanks,description,unitOfTime,clkPeriod,timeWindowSize); } else { diff --git a/DRAMSys/analyzer/scripts/plots.py b/DRAMSys/analyzer/scripts/plots.py index e14b32c3..06d0619a 100755 --- a/DRAMSys/analyzer/scripts/plots.py +++ b/DRAMSys/analyzer/scripts/plots.py @@ -22,25 +22,23 @@ def memory_utilisation_window(connection, tracePath): # Besides, extracting the data from the memory specs, it is feasible to calculate the maximum data rate of the memory and then determine the bandwidth in Gbit/s. # The bandwidth data are then plotted in two graphics. - steps = 1000 cursor = connection.cursor() - cursor.execute(""" SELECT max(DataStrobeEnd) FROM Transactions """) - total = cursor.fetchone() - windowSize = ceil(float(total[0])/float(steps)) - if (windowSize == 0): - windowSize = 1 - # print(steps) + cursor.execute("SELECT TimeWindowSize FROM generalInfo") + windowSize = cursor.fetchone()[0] + cursor.execute("SELECT TraceEnd FROM generalInfo") + traceEnd = cursor.fetchone()[0] + steps = ceil(float(traceEnd)/float(windowSize)) # All possible cases of data transfers inside a time window queryFull = """ SELECT sum(DataStrobeEnd - DataStrobeBegin) FROM transactions Where DataStrobeBegin > ? and DataStrobeEnd < ?""" # The data transfer begins and ends inside the time window queryEnd = """ SELECT sum(DataStrobeEnd - ?) FROM transactions Where DataStrobeBegin < ? and DataStrobeEnd > ? and DataStrobeEnd <=?""" # Only the end of the data transfer is inside the time window queryBegin = """ SELECT sum(? - DataStrobeBegin) FROM transactions Where DataStrobeBegin >= ? and DataStrobeBegin < ? and DataStrobeEnd > ?""" # Only the beginning of the data transfer is inside the time window queryPart = """ SELECT DataStrobeBegin FROM transactions Where DataStrobeBegin <= ? and DataStrobeEnd >= ?""" # The data transfer occupies all the time window maxDataRate = maximum_data_rate(connection) - # print(width) - # print(clk) - # print(rate) - bandwidthPercentage = [0] * steps - bandwidth = [0] * steps + maximumPercentage = 0 + bandwidthPercentage = [0] * (steps+1) + bandwidth = [0] * (steps+1) + bandwidthPercentage[0] = 0 + bandwidth[0] = 0 for i in range(steps): # print(i) bandwidthPercentage[i] = 0 @@ -65,9 +63,11 @@ def memory_utilisation_window(connection, tracePath): else: bandwidthPercentage[i] = windowSize # print(bandwidthPercentage[i]) - bandwidthPercentage[i] = float(bandwidthPercentage[i]/windowSize) - bandwidth[i] = float(bandwidthPercentage[i])*float(maxDataRate)/1024 - bandwidthPercentage[i] *= 100 + bandwidthPercentage[i+1] = float(bandwidthPercentage[i+1]/windowSize) + bandwidth[i+1] = float(bandwidthPercentage[i+1])*float(maxDataRate)/1024 + bandwidthPercentage[i+1] *= 100 + if(maximumPercentage < 100 and maximumPercentage < bandwidthPercentage[i+1]): + maximumPercentage = bandwidthPercentage[i+1] name = ntpath.basename(tracePath) basename, extension = os.path.splitext(name) @@ -86,9 +86,9 @@ def memory_utilisation_window(connection, tracePath): subplotIndex = 211 plt.subplot(subplotIndex) plt.plot(time/1000, bandwidthPercentage) - plt.xlabel('Time (ns)') + #plt.xlabel('Time (ns)') plt.ylabel('Bandwidth (%)') - plt.ylim(0, 100) + plt.ylim(0, maximumPercentage + (10 - maximumPercentage%10)) plt.grid(True) subplotIndex += 1 @@ -108,37 +108,41 @@ def memory_utilisation_window(connection, tracePath): @plot def power_window(connection, tracePath): cursor = connection.cursor() - cursor.execute(""" SELECT max(time) FROM Power """) - maxTime = cursor.fetchone() - cursor.execute(""" SELECT min(time) FROM Power WHERE time > 0""") - windowSize = cursor.fetchone() - steps = ceil(float(maxTime[0])/float(windowSize[0])) - cursor.execute(""" SELECT * FROM Power """) - time = [0] * steps - power = [0] * steps - for i in range(steps): - result = cursor.fetchone() - time[i] = float(result[0]) * 1000000000 # convertion of seconds to nanoseconds - power[i] = float(result[1]) # values are stored in mW + cursor.execute(""" SELECT time FROM Power """) - name = ntpath.basename(tracePath) - basename, extension = os.path.splitext(name) + if(cursor.fetchone() is not None): + cursor.execute("SELECT TimeWindowSize FROM generalInfo") + windowSize = cursor.fetchone()[0] + cursor.execute("SELECT TraceEnd FROM generalInfo") + traceEnd = cursor.fetchone()[0] + steps = ceil(float(traceEnd)/float(windowSize)) + cursor.execute(""" SELECT * FROM Power """) + time = [0] * (steps+1) + power = [0] * (steps+1) + time[0] = 0 + power[0] = 0 + for i in range((steps)): + result = cursor.fetchone() + time[i+1] = float(result[0])*1000000000 + power[i+1] = float(result[1]) - OUTPUT_FILE = 'power_' + basename + '.pdf' - print("Output file is {0}".format(OUTPUT_FILE)) + name = ntpath.basename(tracePath) + basename, extension = os.path.splitext(name) - import matplotlib.pyplot as plt - from matplotlib.backends.backend_pdf import PdfPages + OUTPUT_FILE = 'power_' + basename + '.pdf' + print("Output file is {0}".format(OUTPUT_FILE)) - plt.plot(time, power) - plt.xlabel('Time (ns)') - plt.ylabel('Power (mW)') - plt.gca().set_ylim(bottom=0) - plt.grid(True) - pdf = PdfPages(OUTPUT_FILE) - pdf.savefig() - pdf.close() - plt.close() + import matplotlib.pyplot as plt + from matplotlib.backends.backend_pdf import PdfPages + + plt.plot(time, power) + plt.xlabel('Time (ns)') + plt.ylabel('Power (mW)') + plt.grid(True) + pdf = PdfPages(OUTPUT_FILE) + pdf.savefig() + pdf.close() + plt.close() return # @plot @@ -161,6 +165,7 @@ def generatePlots(pathToTrace): print("================================") print("Generating plots for {0}".format(pathToTrace)) + for p in plots: p(connection, pathToTrace) diff --git a/DRAMSys/simulator/resources/scripts/createTraceDB.sql b/DRAMSys/simulator/resources/scripts/createTraceDB.sql index a8bad1fe..1f72d197 100644 --- a/DRAMSys/simulator/resources/scripts/createTraceDB.sql +++ b/DRAMSys/simulator/resources/scripts/createTraceDB.sql @@ -15,14 +15,15 @@ CREATE TABLE Phases( ); CREATE TABLE GeneralInfo( - NumberOfTransactions INTEGER, + NumberOfTransactions INTEGER, TraceEnd INTEGER, NumberOfBanks INTEGER, - clk INTEGER, + clk INTEGER, UnitOfTime TEXT, - Memconfig TEXT, + Memconfig TEXT, Memspec TEXT, - Traces TEXT + Traces TEXT, + TimeWindowSize INTEGER ); CREATE TABLE Power( @@ -43,13 +44,13 @@ CREATE TABLE DebugMessages( -- use SQLITE R* TREE Module to make queries on timespans effecient (see http://www.sqlite.org/rtree.html) CREATE VIRTUAL TABLE ranges USING rtree( - id, - begin, end + id, + begin, end ); CREATE TABLE Transactions( ID INTEGER, - Range INTEGER, + Range INTEGER, Address INTEGER, Burstlength INTEGER, TThread INTEGER, @@ -61,7 +62,7 @@ CREATE TABLE Transactions( DataStrobeBegin INTEGER, DataStrobeEnd INTEGER, TimeOfGeneration INTEGER, - Command TEXT + Command TEXT ); CREATE INDEX ranges_index ON Transactions(Range); diff --git a/DRAMSys/simulator/resources/simulations/ddr3-example.xml b/DRAMSys/simulator/resources/simulations/ddr3-example.xml index f4793a45..776656ce 100644 --- a/DRAMSys/simulator/resources/simulations/ddr3-example.xml +++ b/DRAMSys/simulator/resources/simulations/ddr3-example.xml @@ -4,12 +4,12 @@ - - + + diff --git a/DRAMSys/simulator/resources/simulations/sim-batch.xml b/DRAMSys/simulator/resources/simulations/sim-batch.xml index b356d01c..3ea21963 100644 --- a/DRAMSys/simulator/resources/simulations/sim-batch.xml +++ b/DRAMSys/simulator/resources/simulations/sim-batch.xml @@ -4,12 +4,12 @@ - - + + diff --git a/DRAMSys/simulator/src/common/TlmRecorder.cpp b/DRAMSys/simulator/src/common/TlmRecorder.cpp index 270f04ea..c2c8a41b 100644 --- a/DRAMSys/simulator/src/common/TlmRecorder.cpp +++ b/DRAMSys/simulator/src/common/TlmRecorder.cpp @@ -270,8 +270,8 @@ void TlmRecorder::prepareSqlStatements() updatePhaseString = "UPDATE Phases SET PhaseEnd = :end WHERE Transact = :trans AND PhaseName = :name"; insertGeneralInfoString = - "INSERT INTO GeneralInfo (NumberOfTransactions,TraceEnd,NumberOfBanks,clk,UnitOfTime,Memconfig,Memspec,Traces) Values " - "(:numberOfTransactions,:end,:numberOfBanks,:clk,:unitOfTime,:memconfig,:memspec,:traces)"; + "INSERT INTO GeneralInfo (NumberOfTransactions,TraceEnd,NumberOfBanks,clk,UnitOfTime,Memconfig,Memspec,Traces,TimeWindowSize) VALUES" + "(:numberOfTransactions,:end,:numberOfBanks,:clk,:unitOfTime,:memconfig,:memspec,:traces,:timeWindowSize)"; insertDebugMessageString = "INSERT INTO DebugMessages (Time,Message) Values (:time,:message)"; insertPowerString = "INSERT INTO Power VALUES (:time,:averagePower)"; @@ -304,6 +304,9 @@ void TlmRecorder::insertGeneralInfo() sqlite3_bind_text(insertGeneralInfoStatement, 6, memconfig.c_str(), memconfig.length(), NULL); sqlite3_bind_text(insertGeneralInfoStatement, 7, memspec.c_str(), memspec.length(), NULL); sqlite3_bind_text(insertGeneralInfoStatement, 8, traces.c_str(), traces.length(), NULL); + sqlite3_bind_int64(insertGeneralInfoStatement, 9, + Configuration::getInstance().TraceLength.value()/Configuration::getInstance().NumberOfTimeWindows); + executeSqlStatement(insertGeneralInfoStatement); } diff --git a/DRAMSys/simulator/src/controller/core/ControllerCore.cpp b/DRAMSys/simulator/src/controller/core/ControllerCore.cpp index f18c1630..e8c079f5 100644 --- a/DRAMSys/simulator/src/controller/core/ControllerCore.cpp +++ b/DRAMSys/simulator/src/controller/core/ControllerCore.cpp @@ -140,10 +140,12 @@ void ControllerCore::scheduleRequest(Command command, tlm::tlm_generic_payload & { sc_time start = clkAlign(sc_time_stamp()); state->cleanUp(start); - ScheduledCommand scheduledCommand = schedule(command, start, payload); - state->change(scheduledCommand); - controller.send(scheduledCommand, payload); + if(!(command == Command::Precharge && refreshManager->hasCollision(scheduledCommand))) + { + state->change(scheduledCommand); + controller.send(scheduledCommand, payload); + } } ScheduledCommand ControllerCore::schedule(Command command, sc_time start, diff --git a/DRAMSys/simulator/src/controller/core/configuration/Configuration.cpp b/DRAMSys/simulator/src/controller/core/configuration/Configuration.cpp index 4959d5a7..04ef17da 100644 --- a/DRAMSys/simulator/src/controller/core/configuration/Configuration.cpp +++ b/DRAMSys/simulator/src/controller/core/configuration/Configuration.cpp @@ -136,30 +136,35 @@ void Configuration::setParameter(std::string name, std::string value) DatabaseRecording = string2bool(value); else if(name == "PowerAnalysis") PowerAnalysis = string2bool(value); - else if (name == "PowerWindowSize") - PowerWindowSize = std::stod(value.c_str()); - else if (name == "PowerWindowUnit") - PowerWindowUnit = string2TimeUnit(value); + else if (name == "NumberOfTimeWindows") { + if(string2int(value) < 1) { + SC_REPORT_FATAL("Configuration", ("Invalid value for parameter " + name + ". This parameter must be at least one.").c_str()); + throw; + } + NumberOfTimeWindows = string2int(value); + } else if(name == "Debug") Debug = string2bool(value); else if (name == "NumberOfTracePlayers") NumberOfTracePlayers = string2int(value); else if (name == "NumberOfMemChannels") { NumberOfMemChannels = string2int(value); - unsigned int maxNumberofMemChannels = xmlAddressDecoder::getInstance().amount["channel"]; - if (NumberOfMemChannels > maxNumberofMemChannels) { + unsigned int maxNumberofMemChannels = xmlAddressDecoder::getInstance().amount["channel"]; + if (NumberOfMemChannels > maxNumberofMemChannels) { SC_REPORT_FATAL("Configuration", ("Invalid value for parameter " + name + ". Value is out of range. The maximum value according to " + "the address mapping configuration file is " + std::to_string(maxNumberofMemChannels) + ".").c_str()); throw; - } + } } else if (name == "ControllerCoreDisableRefresh") ControllerCoreDisableRefresh = string2bool(value); else if (name == "ThermalSimulation") ThermalSimulation = string2bool(value); + else if(name == "SimulationProgressBar") + SimulationProgressBar = string2bool(value); // Specification for ErrorChipSeed, ErrorCSVFile path and ErrorStoreMode else if(name == "ErrorChipSeed") ErrorChipSeed = string2int(value); diff --git a/DRAMSys/simulator/src/controller/core/configuration/Configuration.h b/DRAMSys/simulator/src/controller/core/configuration/Configuration.h index e6abb2ae..6c27b786 100644 --- a/DRAMSys/simulator/src/controller/core/configuration/Configuration.h +++ b/DRAMSys/simulator/src/controller/core/configuration/Configuration.h @@ -75,13 +75,14 @@ struct Configuration //SimConfig bool DatabaseRecording = true; bool PowerAnalysis = false; - double PowerWindowSize; - enum sc_time_unit PowerWindowUnit; + sc_time TraceLength; + unsigned int NumberOfTimeWindows; bool Debug = false; unsigned int NumberOfTracePlayers = 1; unsigned int NumberOfMemChannels = 1; bool ControllerCoreDisableRefresh = false; bool ThermalSimulation = false; + bool SimulationProgressBar; //MemSpec(from DRAM-Power XML) MemSpec memSpec; diff --git a/DRAMSys/simulator/src/controller/core/refresh/RefreshManager.cpp b/DRAMSys/simulator/src/controller/core/refresh/RefreshManager.cpp index c3acac16..d2049f2f 100644 --- a/DRAMSys/simulator/src/controller/core/refresh/RefreshManager.cpp +++ b/DRAMSys/simulator/src/controller/core/refresh/RefreshManager.cpp @@ -58,7 +58,7 @@ RefreshManager::~RefreshManager() bool RefreshManager::hasCollision(const ScheduledCommand& command) { - return command.getStart() < controllerCore.state->getLastCommand(Command::AutoRefresh).getEnd() || command.getEnd() > nextPlannedRefresh; + return command.getStart() < controllerCore.state->getLastCommand(Command::AutoRefresh).getEnd() || command.getEnd() >= nextPlannedRefresh; } void RefreshManager::scheduleRefresh(tlm::tlm_generic_payload& payload __attribute__((unused)), sc_time time) diff --git a/DRAMSys/simulator/src/controller/core/scheduling/checker/RefreshChecker.cpp b/DRAMSys/simulator/src/controller/core/scheduling/checker/RefreshChecker.cpp index ffc8ebfa..3978253e 100644 --- a/DRAMSys/simulator/src/controller/core/scheduling/checker/RefreshChecker.cpp +++ b/DRAMSys/simulator/src/controller/core/scheduling/checker/RefreshChecker.cpp @@ -37,45 +37,87 @@ #include "RefreshChecker.h" #include "../../TimingCalculation.h" - - void RefreshChecker::delayToSatisfyConstraints(ScheduledCommand& command) const { sc_assert(command.getCommand() == Command::AutoRefresh); - ScheduledCommand lastCommandOnBank = state.getLastScheduledCommand(command.getBank()); - - if (lastCommandOnBank.isValidCommand()) + if(config.BankwiseLogic) { - if (lastCommandOnBank.getCommand() == Command::Precharge || lastCommandOnBank.getCommand() == Command::PrechargeAll) + ScheduledCommand lastCommandOnBank = state.getLastScheduledCommand(command.getBank()); + + if (lastCommandOnBank.isValidCommand()) { - command.establishMinDistanceFromStart(lastCommandOnBank.getStart(), config.memSpec.tRP); + if (lastCommandOnBank.getCommand() == Command::Precharge || lastCommandOnBank.getCommand() == Command::PrechargeAll) + { + command.establishMinDistanceFromStart(lastCommandOnBank.getStart(), config.memSpec.tRP); + } + else if (lastCommandOnBank.getCommand() == Command::ReadA) + { + command.establishMinDistanceFromStart(lastCommandOnBank.getStart(), config.memSpec.tRTP + config.memSpec.tRP); + } + else if (lastCommandOnBank.getCommand() == Command::WriteA) + { + command.establishMinDistanceFromStart(lastCommandOnBank.getStart(), + config.memSpec.tWL + getWriteAccessTime() + config.memSpec.tWR + config.memSpec.tRP); + } + else if (lastCommandOnBank.getCommand() == Command::PDNPX || lastCommandOnBank.getCommand() == Command::PDNAX) + { + command.establishMinDistanceFromStart(lastCommandOnBank.getStart(), config.memSpec.tXP); + } + else if (lastCommandOnBank.getCommand() == Command::SREFX) + { + command.establishMinDistanceFromStart(lastCommandOnBank.getStart(), config.memSpec.tXSR); + } + else if (lastCommandOnBank.getCommand() == Command::AutoRefresh) + { + } + else + reportFatal("Refresh Checker", "Refresh can not follow " + commandToString(lastCommandOnBank.getCommand())); } - else if (lastCommandOnBank.getCommand() == Command::ReadA) + } + else + { + for (unsigned int bank = 0; bank < config.memSpec.NumberOfBanks; ++bank) { - command.establishMinDistanceFromStart(lastCommandOnBank.getStart(), config.memSpec.tRTP + config.memSpec.tRP); - } - else if (lastCommandOnBank.getCommand() == Command::WriteA) - { - command.establishMinDistanceFromStart(lastCommandOnBank.getStart(), - config.memSpec.tWL + getWriteAccessTime() + config.memSpec.tWR + config.memSpec.tRP); - } - else if (lastCommandOnBank.getCommand() == Command::PDNPX || lastCommandOnBank.getCommand() == Command::PDNAX) - { - command.establishMinDistanceFromStart(lastCommandOnBank.getStart(), config.memSpec.tXP); - } - else if (lastCommandOnBank.getCommand() == Command::SREFX) + ScheduledCommand lastCommand = state.getLastScheduledCommand(Bank(bank)); + if (lastCommand.isValidCommand()) + { + if(lastCommand.getCommand() == Command::Precharge || lastCommand.getCommand() == Command::PrechargeAll) { - command.establishMinDistanceFromStart(lastCommandOnBank.getStart(), config.memSpec.tXSR); + command.establishMinDistanceFromStart(lastCommand.getStart(), config.memSpec.tRP); } - else if (lastCommandOnBank.getCommand() == Command::AutoRefresh) - { + else if(lastCommand.getCommand() == Command::Activate) + { + command.establishMinDistanceFromStart(lastCommand.getStart(), config.memSpec.tRCD); + } + else if (lastCommand.getCommand() == Command::ReadA) + { + command.establishMinDistanceFromStart(lastCommand.getStart(), config.memSpec.tRTP + config.memSpec.tRP); + } + else if(lastCommand.getCommand() == Command::WriteA) + { + command.establishMinDistanceFromStart(lastCommand.getStart(), config.memSpec.tWL + getWriteAccessTime() + config.memSpec.tWR + config.memSpec.tRP); + } + else if (lastCommand.getCommand() == Command::PDNAX || lastCommand.getCommand() == Command::PDNPX) + { + command.establishMinDistanceFromStart(lastCommand.getStart(), config.memSpec.tXP); + } + else if (lastCommand.getCommand() == Command::SREFX) + { + command.establishMinDistanceFromStart(lastCommand.getEnd(), config.memSpec.tXSR); + } + else if (lastCommand.getCommand() == Command::AutoRefresh) + { + } + else + reportFatal("Refresh Checker", "Refresh can not follow " + commandToString(lastCommand.getCommand())); + } } - else - reportFatal("Refresh Checker", "Refresh can not follow " + commandToString(lastCommandOnBank.getCommand())); } state.bus.moveCommandToNextFreeSlot(command); + + } diff --git a/DRAMSys/simulator/src/simulation/Dram.h b/DRAMSys/simulator/src/simulation/Dram.h index 6125e25f..b295de1b 100644 --- a/DRAMSys/simulator/src/simulation/Dram.h +++ b/DRAMSys/simulator/src/simulation/Dram.h @@ -68,9 +68,7 @@ struct Dram : sc_module // Power Model related bool powerAnalysis = Configuration::getInstance().PowerAnalysis; - double pWindowSize = Configuration::getInstance().PowerWindowSize; - enum sc_time_unit pWindowUnit = Configuration::getInstance().PowerWindowUnit; - sc_time powerWindowSize = sc_time(pWindowSize, pWindowUnit); + sc_time powerWindowSize = Configuration::getInstance().TraceLength/Configuration::getInstance().NumberOfTimeWindows; libDRAMPower *DRAMPower; double sumOfEnergyWindows = 0.0; @@ -278,6 +276,7 @@ struct Dram : sc_module // (log10(2^53)). The implementation sets the number of digits // (DBL_DIG) to 15, not 16, because it has to round down. // + sumOfEnergyWindows += currentTotalEnergy; // Store the time (in seconds) and the current average power (in mW) into the database @@ -286,6 +285,7 @@ struct Dram : sc_module // Here considering that DRAMPower provides the energy in pJ and the power in mW printDebugMessage(string("\tCurrent Energy: \t") + to_string(currentTotalEnergy) + string("\t[pJ]")); printDebugMessage(string("\tAverage Power: \t") + to_string(currentAveragePower) + string("\t[mW]")); + } while(true); } diff --git a/DRAMSys/simulator/src/simulation/Simulation.cpp b/DRAMSys/simulator/src/simulation/Simulation.cpp index d889e233..b22216c8 100644 --- a/DRAMSys/simulator/src/simulation/Simulation.cpp +++ b/DRAMSys/simulator/src/simulation/Simulation.cpp @@ -121,14 +121,23 @@ void Simulation::instantiateModules(const string &traceName, const string &pathT // or if you simply dont care about the data the normal StlPlayer is used. if(Configuration::getInstance().ErrorStoreMode == ErrorStorageMode::NoStorage) { - player = new StlPlayer<>(playerStr.c_str(), pathToResources + string("traces/") + devices[i].trace, devices[i].clkMhz, this); + 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 { - player = new StlDataPlayer<>(playerStr.c_str(), pathToResources + string("traces/") + devices[i].trace, devices[i].clkMhz, this); + 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); @@ -177,7 +186,7 @@ Simulation::~Simulation() } for (auto rec : tlmRecorders) { - delete rec; + delete rec; } } @@ -189,7 +198,7 @@ void Simulation::start() report(" -> memspec: \t\t" + Configuration::getInstance().memSpec.MemoryId); cout << endl; simulationStartTime = clock(); - + for (auto player : players) { player->nextPayload(); } @@ -224,6 +233,17 @@ void Simulation::stop() 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); diff --git a/DRAMSys/simulator/src/simulation/Simulation.h b/DRAMSys/simulator/src/simulation/Simulation.h index 0721c763..3b5d24fb 100644 --- a/DRAMSys/simulator/src/simulation/Simulation.h +++ b/DRAMSys/simulator/src/simulation/Simulation.h @@ -86,6 +86,7 @@ public: void stop(); virtual void tracePlayerTerminates() override; + virtual void transactionFinished() override; private: std::string traceName; @@ -107,6 +108,9 @@ private: // Transaction Recorders (one per channel). They generate the output databases. std::vector tlmRecorders; + unsigned int totalTransactions = 0; + unsigned int remainingTransactions; + clock_t simulationStartTime; void report(std::string message); void setupTlmRecorders(const string &traceName, const string &pathToResources, const std::vector &devices); diff --git a/DRAMSys/simulator/src/simulation/StlDataPlayer.h b/DRAMSys/simulator/src/simulation/StlDataPlayer.h index d4b55638..8c29b30b 100644 --- a/DRAMSys/simulator/src/simulation/StlDataPlayer.h +++ b/DRAMSys/simulator/src/simulation/StlDataPlayer.h @@ -134,6 +134,63 @@ public: } } + void getTraceLength(string pathToTrace) + { + ifstream newFile; + newFile.open(pathToTrace); + if(newFile.is_open()) { + newFile.seekg(-1,ios_base::end);// go to one spot before the EOF + char ch; + newFile.get(ch); + + if(ch == file.eof()) + SC_REPORT_FATAL(0, (string("Empty Trace ") + pathToTrace).c_str()); + + if(ch == '\n') + newFile.seekg(-2,ios_base::end); + + bool keepLooping = true; + while(keepLooping) { + + newFile.get(ch); // Get current byte's data + + if((int)newFile.tellg() <= 1) { // If the data was at or before the 0th byte + newFile.seekg(0); // The first line is the last line + keepLooping = false; // So stop there + } + else if(ch == '\n') { // If the data was a newline + keepLooping = false; // Stop at the current position. + } + else { // If the data was neither a newline nor at the 0 byte + newFile.seekg(-2,ios_base::cur); // Move to the front of that data, then to the front of the data before it + } + } + + string lastLine; + getline(newFile,lastLine); // Read the current line + std::istringstream iss(lastLine); + string time; + iss >> time; + Configuration::getInstance().TraceLength = std::stoull(time.c_str())*clk; + newFile.close(); + } + + } + + unsigned int getNumberOfLines(string pathToTrace) + { + ifstream newFile; + newFile.open(pathToTrace); + newFile.unsetf(std::ios_base::skipws); // new lines will be skipped unless we stop it from happening: + // count the newlines with an algorithm specialized for counting: + unsigned int lineCount = std::count(std::istream_iterator(newFile), std::istream_iterator(), '\n'); + + newFile.close(); + return lineCount; + } + + + private: ifstream file; unsigned int burstlength; diff --git a/DRAMSys/simulator/src/simulation/StlPlayer.h b/DRAMSys/simulator/src/simulation/StlPlayer.h index 918eae84..809a4da7 100644 --- a/DRAMSys/simulator/src/simulation/StlPlayer.h +++ b/DRAMSys/simulator/src/simulation/StlPlayer.h @@ -120,6 +120,64 @@ public: } } + + + void getTraceLength(string pathToTrace) + { + ifstream newFile; + newFile.open(pathToTrace); + if(newFile.is_open()) { + newFile.seekg(-1,ios_base::end);// go to one spot before the EOF + char ch; + newFile.get(ch); + + if(ch == file.eof()) + SC_REPORT_FATAL(0, (string("Empty Trace ") + pathToTrace).c_str()); + + if(ch == '\n') + newFile.seekg(-2,ios_base::end); + + bool keepLooping = true; + while(keepLooping) { + + newFile.get(ch); // Get current byte's data + + if((int)newFile.tellg() <= 1) { // If the data was at or before the 0th byte + newFile.seekg(0); // The first line is the last line + keepLooping = false; // So stop there + } + else if(ch == '\n') { // If the data was a newline + keepLooping = false; // Stop at the current position. + } + else { // If the data was neither a newline nor at the 0 byte + newFile.seekg(-2,ios_base::cur); // Move to the front of that data, then to the front of the data before it + } + } + + string lastLine; + getline(newFile,lastLine); // Read the current line + std::istringstream iss(lastLine); + string time; + iss >> time; + Configuration::getInstance().TraceLength = std::stoull(time.c_str())*clk; + newFile.close(); + } + + } + + unsigned int getNumberOfLines(string pathToTrace) + { + ifstream newFile; + newFile.open(pathToTrace); + newFile.unsetf(std::ios_base::skipws); // new lines will be skipped unless we stop it from happening: + // count the newlines with an algorithm specialized for counting: + unsigned int lineCount = std::count(std::istream_iterator(newFile), std::istream_iterator(), '\n'); + + newFile.close(); + return lineCount; + } + + private: ifstream file; unsigned int burstlength; diff --git a/DRAMSys/simulator/src/simulation/TracePlayer.h b/DRAMSys/simulator/src/simulation/TracePlayer.h index 7a6d4523..070b8127 100644 --- a/DRAMSys/simulator/src/simulation/TracePlayer.h +++ b/DRAMSys/simulator/src/simulation/TracePlayer.h @@ -96,7 +96,7 @@ gp *TracePlayer::allocatePayload() template void TracePlayer::terminate() { - cout << sc_time_stamp() << " " << this->name() << " terminated" << std::endl; + cout << sc_time_stamp() << " " << this->name() << " terminated " << std::endl; listener->tracePlayerTerminates(); } @@ -159,6 +159,9 @@ void TracePlayer::peqCallback(tlm_generic_payload &payload, const tlm_ sendToTarget(payload, END_RESP, SC_ZERO_TIME); payload.release(); + if(Configuration::getInstance().SimulationProgressBar) + listener->transactionFinished(); + } else if (phase == END_RESP) { diff --git a/DRAMSys/simulator/src/simulation/TracePlayerListener.h b/DRAMSys/simulator/src/simulation/TracePlayerListener.h index 36a0cdd5..95c52773 100644 --- a/DRAMSys/simulator/src/simulation/TracePlayerListener.h +++ b/DRAMSys/simulator/src/simulation/TracePlayerListener.h @@ -42,6 +42,7 @@ class TracePlayerListener { public: virtual void tracePlayerTerminates() = 0; + virtual void transactionFinished() = 0; }; #endif // TRACEPLAYERLISTENER_H diff --git a/README.md b/README.md index 84a10c31..a85fa5cd 100644 --- a/README.md +++ b/README.md @@ -319,12 +319,12 @@ The DRAMSys' main configuration file is presented below. - - + + @@ -419,12 +419,12 @@ The XML code below shows a typic configuration: - - + + @@ -532,15 +532,8 @@ Below are listed the configuration sections and configuration fields. - *PowerAnalysis* (boolean) - "1": enables live power analysis with the DRAMPower tool - "0": disables power analysis - - *PowerWindowSize* (double) - - Size of the time window used to evaluate averate power consumption - - *PowerWindowUnit* (string) - - "s": seconds - - "ms": millisecond - - "us": microseconds - - "ns": nanoseconds - - "ps": picoseconds - - "fs": femtoseconds + - *NumberOfTimeWindows* (int) + - number of time windows used to evaluate average bandwidth and average power consumption - *NumberOfTracePlayers* (unsigned int) - Number of trace players - *NumberOfMemChannels* (unsigned int) @@ -551,6 +544,9 @@ Below are listed the configuration sections and configuration fields. - *ThermalSimulation* (boolean) - "1": enables thermal simulation - "0": static temperature during simulation + - *SimulationProgressBar* (boolean) + - "1": enables the simulation progress bar + - "0": disables the simulation progress bar - **Temperature Simulator Configuration** - *TemperatureScale* (string)