From 354c87104701aa0ed512647c363ecf773c3fbdd7 Mon Sep 17 00:00:00 2001 From: robert Date: Sun, 20 Apr 2014 17:28:05 +0200 Subject: [PATCH] changed metrics --- dram/resources/.gitignore | 2 + dram/resources/scripts/createTraceDB.sql | 5 +- dram/resources/scripts/metrics.py | 64 ++++++++++- dram/resources/scripts/tests.py | 125 ++++++++++++---------- dram/resources/simulations/first.xml | 11 +- dram/src/common/TlmRecorder.cpp | 7 +- dram/src/common/dramExtension.cpp | 20 ++++ dram/src/common/dramExtension.h | 16 +++ dram/src/simulation/Controller.h | 2 +- dram/src/simulation/SimulationManager.cpp | 28 +++-- dram/src/simulation/TracePlayer.h | 4 + dram/src/simulation/main.cpp | 2 +- 12 files changed, 206 insertions(+), 80 deletions(-) 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);