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)