diff --git a/dram/resources/.gitignore b/dram/resources/.gitignore
index 0d20b648..f6ad1d1b 100644
--- a/dram/resources/.gitignore
+++ b/dram/resources/.gitignore
@@ -1 +1,3 @@
*.pyc
+configs
+simulations
diff --git a/dram/resources/scripts/createTraceDB.sql b/dram/resources/scripts/createTraceDB.sql
index 8f83e275..e8211037 100644
--- a/dram/resources/scripts/createTraceDB.sql
+++ b/dram/resources/scripts/createTraceDB.sql
@@ -52,9 +52,10 @@ CREATE TABLE Transactions(
TBankgroup INTEGER,
TRow INTEGER,
TColumn INTEGER,
- Command TEXT,
DataStrobeBegin INTEGER,
- DataStrobeEnd INTEGER
+ DataStrobeEnd INTEGER,
+ TimeOfGeneration INTEGER,
+ Command TEXT
);
CREATE INDEX ranges_index ON Transactions(Range);
diff --git a/dram/resources/scripts/metrics.py b/dram/resources/scripts/metrics.py
index f771a292..59318a6f 100644
--- a/dram/resources/scripts/metrics.py
+++ b/dram/resources/scripts/metrics.py
@@ -1,6 +1,7 @@
import sys
import sqlite3
-
+import pystaggrelite3
+
metrics = []
threadMetrics = []
@@ -35,17 +36,60 @@ def getTraceLength(connection):
@metric
def average_response_latency_in_ns(connection):
cursor = connection.cursor()
- cursor.execute("""SELECT avg(transactions.DataStrobeEnd-ranges.begin)/1000 FROM transactions INNER JOIN ranges
- ON transactions.range = ranges.ID where TThread != 0""")
+ cursor.execute("""SELECT avg(PhaseBegin-timeOfGeneration)/1000 FROM transactions INNER JOIN Phases
+ ON phases.transact = transactions.ID WHERE PhaseName='RESP' """)
result = cursor.fetchone()
return round(result[0],1)
+@metric
+def median_response_latency_in_ns(connection):
+ cursor = connection.cursor()
+ cursor.execute("""SELECT median(PhaseBegin-timeOfGeneration)/1000 FROM transactions INNER JOIN Phases
+ ON phases.transact = transactions.ID WHERE PhaseName='RESP' """)
+ result = cursor.fetchone()
+ return round(result[0],1)
+
+@metric
+def max_response_latency_in_ns(connection):
+ cursor = connection.cursor()
+ cursor.execute("""SELECT max(PhaseBegin-timeOfGeneration)/1000 FROM transactions INNER JOIN Phases
+ ON phases.transact = transactions.ID WHERE PhaseName='RESP' """)
+ result = cursor.fetchone()
+ return round(result[0],1)
+
+@metric
+def min_response_latency_in_ns(connection):
+ cursor = connection.cursor()
+ cursor.execute("""SELECT min(PhaseBegin-timeOfGeneration)/1000 FROM transactions INNER JOIN Phases
+ ON phases.transact = transactions.ID WHERE PhaseName='RESP' """)
+ result = cursor.fetchone()
+ return round(result[0],1)
+
+@metric
+def stdDev_response_latency_in_ns(connection):
+ cursor = connection.cursor()
+ cursor.execute("""SELECT stdev(PhaseBegin-timeOfGeneration)/1000 FROM transactions INNER JOIN Phases
+ ON phases.transact = transactions.ID WHERE PhaseName='RESP' """)
+ result = cursor.fetchone()
+ return round(result[0],1)
+
+
@threadMetric
def average_response_latency_in_ns(connection, thread):
cursor = connection.cursor()
- query = """SELECT avg(transactions.DataStrobeEnd-ranges.begin)/1000 FROM transactions INNER JOIN ranges
- ON transactions.range = ranges.ID where TThread = :Thread """
+ query = """SELECT avg(PhaseBegin-timeOfGeneration)/1000 FROM transactions INNER JOIN Phases
+ ON phases.transact = transactions.ID WHERE PhaseName='RESP' AND TThread = :Thread """
+
+ cursor.execute(query, {"Thread": thread})
+ result = cursor.fetchone()
+ return round(result[0],1)
+
+@threadMetric
+def median_response_latency_in_ns(connection, thread):
+ cursor = connection.cursor()
+ query = """SELECT median(PhaseBegin-timeOfGeneration)/1000 FROM transactions INNER JOIN Phases
+ ON phases.transact = transactions.ID WHERE PhaseName='RESP' AND TThread = :Thread """
cursor.execute(query, {"Thread": thread})
result = cursor.fetchone()
@@ -65,6 +109,13 @@ def number_of_precharges(connection):
result = cursor.fetchone()
return result[0]
+@metric
+def accesses_per_activate(connection):
+ cursor = connection.cursor()
+ cursor.execute("SELECT COUNT(*) FROM Phases WHERE PhaseName IN ('REQ')")
+ result = cursor.fetchone()
+ return round(result[0]*1.0/number_of_activates(connection),1)
+
def timeInPowerStates(connection):
totalTimeAllBanks = getTraceLength(connection)*getNumberOfBanks(connection)
@@ -151,6 +202,9 @@ def passRatio(connection):
def calculateMetrics(pathToTrace):
connection = sqlite3.connect(pathToTrace)
+ connection.create_aggregate("median", 1, pystaggrelite3.median)
+ connection.create_aggregate("stdev", 1, pystaggrelite3.stdev)
+
calculatedMetrics = []
print("================================")
diff --git a/dram/resources/scripts/tests.py b/dram/resources/scripts/tests.py
index dcd62cb6..14e3bf89 100644
--- a/dram/resources/scripts/tests.py
+++ b/dram/resources/scripts/tests.py
@@ -186,9 +186,10 @@ def formatTime(time):
# ----------- checks ---------------------------------------
-#@test
+@test
def commands_are_clockaligned(connection):
"""Checks that all commands on the command bus are aligned to the system clock"""
+
cursor = connection.cursor()
query = "select ID,PhaseBegin,PhaseEnd from phases where phaseName NOT IN ('REQ','RESP') AND (phaseBegin%:clk!=0 OR phaseEnd%:clk!=0)"
cursor.execute(query, {"clk": dramconfig.clk})
@@ -196,16 +197,16 @@ def commands_are_clockaligned(connection):
result = cursor.fetchone()
if(result != None):
- return TestFailed("Command with PhaseID {0} starts at {1} and ends at, which is not aligned to system clock ({2})".format(
- result[0], formatTime(result[1]), formatTime(result[2]), formatTime(dramconfig.clk)))
+ return TestFailed("Command with PhaseID {0} starts at {1} and ends at. One of those times. is not aligned to system clock ({2})"
+ .format(result[0], formatTime(result[1]), formatTime(result[2]), formatTime(dramconfig.clk)))
return TestSuceeded()
-#@test
+@test
def commandbus_slots_are_used_once(connection):
"""Checks that no two phases on the command bus start at the same time"""
+
cursor = connection.cursor()
-
if dramconfig.bankwiseLogic:
excludedPhases = "('REQ','RESP','PRE_ALL')"
else:
@@ -221,9 +222,10 @@ def commandbus_slots_are_used_once(connection):
return TestSuceeded()
-#@test
+@test
def phase_transitions_are_valid(connection):
- """Checks if the transition of two consequtive phases is valid"""
+ """Checks that all transition of two consequtive phases on the same bank are valid"""
+
cursor = connection.cursor()
validTransitions = {}
@@ -325,9 +327,9 @@ def timing_constraint(FirstPhase, SecondPhase):
return 0
-#@test
-def timing_constraits_same_bank(connection):
- """Checks that two consecutive phases on the same bank satisfy timing constraint"""
+@test
+def timing_constraits_on_the_same_bank_hold(connection):
+ """Checks that all transitions of two consequtive phases on the same bank meet their timing constraints"""
cursor = connection.cursor()
validTransitions = {}
@@ -348,23 +350,28 @@ def timing_constraits_same_bank(connection):
@test
def row_buffer_is_used_correctly(connection):
+ """Checks that each bank's row buffer is used correctly"""
+
cursor = connection.cursor()
query = """SELECT PhaseName, phases.ID FROM phases INNER JOIN transactions ON phases.transact=transactions.ID WHERE TBank=:bank
AND PhaseName NOT IN ('REQ','RESP') ORDER BY PhaseBegin"""
+
+ #phases that precharge the bank and close the rowbuffer
+ prechargingPhases = set(['PRE','PRE_ALL','RDA','WRA'])
+
+ #phases that require the bank to be in active state and the rowbuffer to be opened
+ accessingPhases = set(['RD','RDA', 'WR', 'WRA', 'PRE'])
+
+ #phases that require the bank to be in precharged state and the robuffer to be closed
+ idlePhases = set(['ACT', 'PDNP', 'AUTO_REFRESH', 'SREF'])
+
for bankNumber in range(dramconfig.numberOfBanks):
cursor.execute(query,{"bank": bankNumber})
rowBufferIsClosed = True
+
- #phases that precharge the bank and close the rowbuffer
- prechargingPhases = set(['PRE','PRE_ALL','RDA','WRA'])
-
- #phases that require the bank to be in active state and the rowbuffer to be opened
- accessingPhases = set(['RD','RDA', 'WR', 'WRA'])
-
- #phases that require the bank to be in precharged state and the robuffer to be closed
- idlePhases = set(['PDNP', 'AUTO_REFRESH', 'SREF'])
for currentRow in cursor:
if(currentRow[0] in accessingPhases and rowBufferIsClosed == True):
@@ -374,22 +381,17 @@ def row_buffer_is_used_correctly(connection):
return TestFailed("Phase {0}({1}) needs a closed rowbuffer".format(currentRow[1], currentRow[0]))
if(currentRow[0] == 'ACT'):
- if(rowBufferIsClosed == True):
- rowBufferIsClosed = False
- else:
- return TestFailed("Phase {0}({1}) opens an already opened rowbuffer".format(currentRow[1],currentRow[0]))
+ rowBufferIsClosed = False
if(currentRow[0] in prechargingPhases):
- if(rowBufferIsClosed == True and currentRow[0] != 'PRE_ALL'):
- return TestFailed("Phase {0}({1}) closes an already closed rowbuffer".format(currentRow[1],currentRow[0]))
- else:
- rowBufferIsClosed = True
+ rowBufferIsClosed = True
+
return TestSuceeded()
#----------- activate checks ---------------------------------------
@test
-def activate_to_activate(connection):
- """Checks minimal time between two activates (JESD229 229, P. 27)"""
+def activate_to_activate_holds(connection):
+ """Checks that all activates are far enough apart(JESD229 229, P. 27)"""
cursor = connection.cursor()
cursor.execute("SELECT phases.ID,PhaseBegin,TBankGroup FROM Phases INNER JOIN transactions ON phases.transact=transactions.ID WHERE PhaseName = 'ACT' ORDER BY PhaseBegin")
lastRow = cursor.fetchone()
@@ -401,15 +403,17 @@ def activate_to_activate(connection):
else:
minTime = dramconfig.tRRD_S
if(timeBetweenActivates < minTime):
- return TestFailed("Activates with PhaseIDs {0} and {1} are {2} apart. Minimum time between two activates is {3}".format(currentRow[0], lastRow[0],formatTime(timeBetweenActivates), minTime))
+ return TestFailed("Activates with PhaseIDs {0} and {1} are {2} apart. Minimum time between two activates is {3}".
+ format(currentRow[0], lastRow[0],formatTime(timeBetweenActivates), formatTime(minTime)))
+
lastRow = currentRow
return TestSuceeded()
@test
-def activate_to_activate_on_same_bank(connection):
- """Checks minimal time between two activates on the same bank (JEDEC 229, P. 27)"""
+def activate_to_activate_on_same_bank_holds(connection):
+ """Checks that all activates on the same bank are far enough apart (JEDEC 229, P. 27)"""
cursor = connection.cursor()
query = "SELECT Phases.ID,PhaseBegin from Phases INNER JOIN Transactions ON Phases.Transact = Transactions.ID WHERE PhaseName = 'ACT' AND TBANK = :bank ORDER BY PhaseBegin"
@@ -428,8 +432,8 @@ def activate_to_activate_on_same_bank(connection):
return TestSuceeded()
@test
-def n_activate_window(connection):
- """Checks n-Activate constraint (JEDEC 229, P. 27)"""
+def n_activate_window_holds(connection):
+ """Checks that the n-Activate constraint is met everywhere(JEDEC 229, P. 27)"""
cursor = connection.cursor()
cursor.execute("SELECT ID,PhaseBegin from Phases WHERE PhaseName = 'ACT' ORDER BY PhaseBegin")
activateWindow = []
@@ -446,7 +450,8 @@ def n_activate_window(connection):
# ----------- read/write checks ---------------------------------------
@test
-def read_to_read(connection):
+def read_to_read_holds(connection):
+ """Check that the read operations do not intefere with each other on the data bus"""
cursor = connection.cursor()
cursor.execute("SELECT phases.ID,PhaseBegin,TBankGroup FROM Phases INNER JOIN transactions ON phases.transact=transactions.ID WHERE PhaseName IN ('RD','RDA') ORDER BY PhaseBegin")
lastRow = cursor.fetchone()
@@ -465,7 +470,9 @@ def read_to_read(connection):
@test
-def write_to_write(connection):
+def write_to_write_holds(connection):
+ """Check that the write operations do not intefere with each other on the data bus"""
+
cursor = connection.cursor()
cursor.execute("SELECT phases.ID,PhaseBegin,TBankGroup FROM Phases INNER JOIN transactions ON phases.transact=transactions.ID WHERE PhaseName IN ('WR','WRA') ORDER BY PhaseBegin")
lastRow = cursor.fetchone()
@@ -482,8 +489,10 @@ def write_to_write(connection):
return TestSuceeded()
@test
-def write_to_read_and_read_to_write(connection):
- """Checks minimal time between write and read/read and write (JEDEC 229, P. 33/34)"""
+def write_to_read_and_read_to_write_hold(connection):
+ """Checks that read and write operation do not interfere with each other on the data bus
+ and that the write-to-read constraint is met"""
+
cursor = connection.cursor()
query = """SELECT Phases.ID,PhaseBegin,PhaseName,TBankGroup from Phases INNER JOIN Transactions ON Phases.Transact = Transactions.ID
WHERE PhaseName IN ('RD','WR','RDA','WRA') ORDER BY PhaseBegin"""
@@ -522,6 +531,8 @@ def write_to_read_and_read_to_write(connection):
@test
def read_holds_dll_constraint_after_sref(connection):
+ """Checks that all read operations are delayed long enough after the end of the self refresh powerdown state"""
+
cursor = connection.cursor()
query = """SELECT Phases.ID,PhaseBegin,PhaseName,TBankGroup from Phases INNER JOIN Transactions ON Phases.Transact = Transactions.ID AND TBank = :bank
WHERE PhaseName IN ('RD', 'RDA', 'SREF') ORDER BY PhaseBegin"""
@@ -539,25 +550,29 @@ def read_holds_dll_constraint_after_sref(connection):
lastRow = currentRow
return TestSuceeded()
-@test
-def sref_active_for_minimal_time(connection):
- """Checks that SREF is active for a minimal time (JEDEC 229, P. 41)"""
- cursor = connection.cursor()
- cursor.execute("SELECT ID, PhaseEnd-clk-PhaseBegin FROM Phases, GeneralInfo WHERE PhaseName = 'SREF'")
- for currentRow in cursor:
- if(currentRow[1] < dramconfig.tCKESR):
- return TestFailed("SREF with ID {0} is {1} long. Minimal time in SREF is {2}".format(currentRow[0], formatTime(currentRow[1]), dramconfig.tCKESR))
- return TestSuceeded()
+ # ----------- powerdown checks ---------------------------------------
-@test
-def pdna_pdnp_active_for_minimal_time(connection):
- """Checks that PDNA,PDNP are active for a minimal time (JEDEC 229, P. 41)"""
- cursor = connection.cursor()
- cursor.execute("SELECT ID,PhaseName, PhaseEnd-PhaseBegin FROM Phases, GeneralInfo WHERE PhaseName IN ('PDNA', 'PDNP') ")
- for currentRow in cursor:
- if(currentRow[2] < dramconfig.tCKE):
- return TestFailed("{0} with ID {1} is {2} long. Minimal time in SREF is {3}".format(currentRow[1], currentRow[0], formatTime(currentRow[2]), dramconfig.tCKE))
- return TestSuceeded()
+# @test
+# def sref_active_for_minimal_time(connection):
+# """Checks that after entering self refresh powerndown state, the state is active for a minimal time (JEDEC 229, P. 41)"""
+#
+# cursor = connection.cursor()
+# cursor.execute("SELECT ID, PhaseEnd-clk-PhaseBegin FROM Phases, GeneralInfo WHERE PhaseName = 'SREF'")
+# for currentRow in cursor:
+# if(currentRow[1] < dramconfig.tCKESR):
+# return TestFailed("SREF with ID {0} is {1} long. Minimal time in SREF is {2}".format(currentRow[0], formatTime(currentRow[1]), dramconfig.tCKESR))
+# return TestSuceeded()
+
+# @test
+# def pdna_pdnp_active_for_minimal_time(connection):
+# """Checks that after entering active/precharged powerdown, the state is active for a minimal time (JEDEC 229, P. 41)"""
+#
+# cursor = connection.cursor()
+# cursor.execute("SELECT ID,PhaseName, PhaseEnd-PhaseBegin FROM Phases, GeneralInfo WHERE PhaseName IN ('PDNA', 'PDNP') ")
+# for currentRow in cursor:
+# if(currentRow[2] < dramconfig.tCKE):
+# return TestFailed("{0} with ID {1} is {2} long. Minimal time in SREF is {3}".format(currentRow[1], currentRow[0], formatTime(currentRow[2]), dramconfig.tCKE))
+# return TestSuceeded()
# -------------------------- interface methods --------------------
diff --git a/dram/resources/simulations/first.xml b/dram/resources/simulations/first.xml
index 961267ae..ea5f585a 100644
--- a/dram/resources/simulations/first.xml
+++ b/dram/resources/simulations/first.xml
@@ -1,13 +1,16 @@
- JEDEC_256Mb_WIDEIO_SDR-266_128bit.xml
+
+ MICRON_4Gb_DDR4-2400_8bit_A.xml
+ am_ddr4.xml
fr_fcfs.xml
- fr_fcfs_bankwise.xml
-
+
- mediabench-fractal_32.stl
+ chstone-jpeg_32.stl
diff --git a/dram/src/common/TlmRecorder.cpp b/dram/src/common/TlmRecorder.cpp
index 84fb4f2c..ff10f69b 100644
--- a/dram/src/common/TlmRecorder.cpp
+++ b/dram/src/common/TlmRecorder.cpp
@@ -81,7 +81,7 @@ void TlmRecorder::setUpTransactionTerminatingPhases()
void TlmRecorder::prepareSqlStatements()
{
insertTransactionString =
- "INSERT INTO Transactions VALUES (:id,:rangeID,:address,:burstlength,:thread,:channel,:bank,:bankgroup,:row,:column,:command,:dataStrobeBegin,:dataStrobeEnd)";
+ "INSERT INTO Transactions VALUES (:id,:rangeID,:address,:burstlength,:thread,:channel,:bank,:bankgroup,:row,:column,:dataStrobeBegin,:dataStrobeEnd, :timeOfGeneration,:command)";
insertRangeString = "INSERT INTO Ranges VALUES (:id,:begin,:end)";
updateRangeString = "UPDATE Ranges SET End = :end WHERE ID = :id";
updateDataStrobeString = "UPDATE Transactions SET DataStrobeBegin = :begin, DataStrobeEnd = :end WHERE ID = :id";
@@ -152,6 +152,11 @@ void TlmRecorder::insertTransactionInDB(unsigned int id, tlm::tlm_generic_payloa
sqlite3_bind_int(insertTransactionStatement, 11, 0);
sqlite3_bind_int(insertTransactionStatement, 12, 0);
+ if(extension.getThread().ID() == 0)
+ sqlite3_bind_int64(insertTransactionStatement, 13, 0);
+ else
+ sqlite3_bind_int64(insertTransactionStatement, 13, GenerationExtension::getExtension(&trans).TimeOfGeneration().value());
+
executeSqlStatement(insertTransactionStatement);
}
void TlmRecorder::insertRangeInDB(unsigned int id, const sc_time& time)
diff --git a/dram/src/common/dramExtension.cpp b/dram/src/common/dramExtension.cpp
index 0259c5ab..22534fa2 100644
--- a/dram/src/common/dramExtension.cpp
+++ b/dram/src/common/dramExtension.cpp
@@ -168,3 +168,23 @@ void DramExtension::increaseRow()
{
++row;
}
+
+tlm_extension_base* GenerationExtension::clone() const
+{
+ return new GenerationExtension(timeOfGeneration);
+}
+
+void GenerationExtension::copy_from(const tlm_extension_base& ext)
+{
+ const GenerationExtension& cpyFrom = static_cast(ext);
+ timeOfGeneration = cpyFrom.timeOfGeneration;
+
+}
+
+GenerationExtension& GenerationExtension::getExtension(const tlm::tlm_generic_payload* payload)
+{
+ GenerationExtension *result = NULL;
+ payload->get_extension(result);
+ sc_assert(result!=NULL);
+ return *result;
+}
diff --git a/dram/src/common/dramExtension.h b/dram/src/common/dramExtension.h
index fa5b19fd..089b2469 100644
--- a/dram/src/common/dramExtension.h
+++ b/dram/src/common/dramExtension.h
@@ -10,6 +10,7 @@
#include
#include
+#include
class Thread
{
@@ -197,4 +198,19 @@ public:
static DramExtension& getExtension(const tlm::tlm_generic_payload &payload);
};
+
+class GenerationExtension : public tlm::tlm_extension
+{
+public:
+ GenerationExtension(sc_time timeOfGeneration) : timeOfGeneration(timeOfGeneration) {}
+ virtual tlm_extension_base* clone() const;
+ virtual void copy_from(const tlm_extension_base& ext);
+ static GenerationExtension& getExtension(const tlm::tlm_generic_payload *payload);
+
+
+ sc_time TimeOfGeneration() const {return timeOfGeneration;}
+private:
+ sc_time timeOfGeneration;
+};
+
#endif /* DRAMEXTENSION_H_ */
diff --git a/dram/src/simulation/Controller.h b/dram/src/simulation/Controller.h
index 0c9f5547..5ae57d80 100644
--- a/dram/src/simulation/Controller.h
+++ b/dram/src/simulation/Controller.h
@@ -82,7 +82,7 @@ public:
{
for (Bank bank : controller->getBanks())
{
- controller->powerDownManager->wakeUp(bank, sc_time_stamp());
+ controller->powerDownManager->wakeUp(bank, clkAlign(sc_time_stamp()));
}
}
diff --git a/dram/src/simulation/SimulationManager.cpp b/dram/src/simulation/SimulationManager.cpp
index c5b33140..ae0121ee 100644
--- a/dram/src/simulation/SimulationManager.cpp
+++ b/dram/src/simulation/SimulationManager.cpp
@@ -35,16 +35,12 @@ void SimulationManager::loadSimulationsFromXML(string uri)
cout << "\t-> parsing simulation objects .." << endl;
-
for (XMLElement* element = doc.FirstChildElement("simulation"); element != NULL;
element = element->NextSiblingElement("simulation"))
{
parseSimulationBatch(element);
}
-
-
-
cout << "\t-> checking paths .." << endl;
checkPaths();
@@ -61,14 +57,16 @@ void SimulationManager::runSimulations()
system(string("rm -rf " + exportPath).c_str());
for (auto& batch : simulationsBatches)
{
- system(string("mkdir -p " + exportPath + "/"+batch.simulationName).c_str());
+ system(string("mkdir -p " + exportPath + "/" + batch.simulationName).c_str());
for (auto& dramSetup : batch.dramSetups)
{
string memconfig = getFileName(dramSetup.memconfig);
+ string memspec = getFileName(dramSetup.memspec);
+
for (auto& traceSetup : batch.traceSetups)
{
- runSimulation(exportPath + "/" + batch.simulationName + "/" + memconfig + "-" + traceSetup.first + ".tdb",
+ runSimulation(exportPath + "/" + batch.simulationName + "/" + traceSetup.first + "-" + memconfig + "-" + memspec + ".tdb",
dramSetup, traceSetup.second);
}
}
@@ -80,13 +78,20 @@ void SimulationManager::parseSimulationBatch(XMLElement* simulation)
SimulationBatch batch;
batch.simulationName = simulation->Attribute("id");
- string memspecUri = simulation->FirstChildElement("memspec")->GetText();
+
+ string memspecUri;
string addressmappingUri = simulation->FirstChildElement("addressmapping")->GetText();
- for (XMLElement* element = simulation->FirstChildElement("memconfigs")->FirstChildElement("memconfig"); element != NULL;
- element = element->NextSiblingElement("memconfig"))
+ for (XMLElement* element = simulation->FirstChildElement("memspec"); element != NULL;
+ element = element->NextSiblingElement("memspec"))
{
- batch.dramSetups.push_back(DramSetup(element->GetText(), memspecUri, addressmappingUri));
+ memspecUri = element->GetText();
+
+ for (XMLElement* element = simulation->FirstChildElement("memconfigs")->FirstChildElement("memconfig"); element != NULL;
+ element = element->NextSiblingElement("memconfig"))
+ {
+ batch.dramSetups.push_back(DramSetup(element->GetText(), memspecUri, addressmappingUri));
+ }
}
for (XMLElement* element = simulation->FirstChildElement("trace-setups")->FirstChildElement("trace-setup"); element != NULL;
@@ -96,6 +101,7 @@ void SimulationManager::parseSimulationBatch(XMLElement* simulation)
}
simulationsBatches.push_back(batch);
+
}
void SimulationManager::checkPaths()
@@ -122,7 +128,7 @@ void SimulationManager::startTraceAnalyzer()
{
string p = getenv("trace");
string run_tpr = p + " -f ";
- for(auto batch : simulationsBatches)
+ for (auto batch : simulationsBatches)
{
run_tpr += exportPath + "/" + batch.simulationName + " ";
diff --git a/dram/src/simulation/TracePlayer.h b/dram/src/simulation/TracePlayer.h
index 38423f04..f9a93f70 100644
--- a/dram/src/simulation/TracePlayer.h
+++ b/dram/src/simulation/TracePlayer.h
@@ -21,6 +21,7 @@
#include "../common/DebugManager.h"
#include "../common/xmlAddressdecoder.h"
#include "../common/TlmRecorder.h"
+#include "../common/dramExtension.h"
using namespace std;
using namespace tlm;
@@ -99,6 +100,9 @@ private:
payload->set_streaming_width(burstlenght);
sc_time sendingTime = sc_time(std::stoi(time.c_str()), SC_NS);
+ GenerationExtension* genExtension = new GenerationExtension(sendingTime);
+ payload->set_auto_extension(genExtension);
+
if (sendingTime <= sc_time_stamp())
{
payloadEventQueue.notify(*payload, BEGIN_REQ, SC_ZERO_TIME);
diff --git a/dram/src/simulation/main.cpp b/dram/src/simulation/main.cpp
index 8d2606e4..42cff397 100644
--- a/dram/src/simulation/main.cpp
+++ b/dram/src/simulation/main.cpp
@@ -40,7 +40,7 @@ int sc_main(int argc, char **argv)
if(argc > 1)
simulationToRun = argv[1];
else
- simulationToRun = "datasizes.xml";
+ simulationToRun = "first.xml";
SimulationManager manager(resources);
manager.loadSimulationsFromXML(resources + "/simulations/" + simulationToRun);