changed metrics
This commit is contained in:
2
dram/resources/.gitignore
vendored
2
dram/resources/.gitignore
vendored
@@ -1 +1,3 @@
|
||||
*.pyc
|
||||
configs
|
||||
simulations
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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("================================")
|
||||
|
||||
@@ -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 --------------------
|
||||
|
||||
|
||||
@@ -1,13 +1,16 @@
|
||||
<simulation id = "first">
|
||||
<memspec>JEDEC_256Mb_WIDEIO_SDR-266_128bit.xml</memspec>
|
||||
<!-- <memspec>JEDEC_256Mb_WIDEIO_SDR-266_128bit.xml</memspec>
|
||||
<addressmapping>am_wideioFourBanks.xml</addressmapping>
|
||||
-->
|
||||
<memspec>MICRON_4Gb_DDR4-2400_8bit_A.xml</memspec>
|
||||
<addressmapping>am_ddr4.xml</addressmapping>
|
||||
<memconfigs>
|
||||
<memconfig>fr_fcfs.xml</memconfig>
|
||||
<memconfig>fr_fcfs_bankwise.xml</memconfig>
|
||||
</memconfigs>
|
||||
<!-- <memconfig>fr_fcfs_bankwise.xml</memconfig>
|
||||
--> </memconfigs>
|
||||
<trace-setups>
|
||||
<trace-setup id="1">
|
||||
<device >mediabench-fractal_32.stl</device>
|
||||
<device >chstone-jpeg_32.stl</device>
|
||||
</trace-setup>
|
||||
</trace-setups>
|
||||
</simulation>
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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<const GenerationExtension&>(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;
|
||||
}
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
|
||||
#include <tlm.h>
|
||||
#include <iostream>
|
||||
#include <systemc.h>
|
||||
|
||||
class Thread
|
||||
{
|
||||
@@ -197,4 +198,19 @@ public:
|
||||
static DramExtension& getExtension(const tlm::tlm_generic_payload &payload);
|
||||
};
|
||||
|
||||
|
||||
class GenerationExtension : public tlm::tlm_extension<GenerationExtension>
|
||||
{
|
||||
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_ */
|
||||
|
||||
@@ -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()));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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 + " ";
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
Reference in New Issue
Block a user