Merge remote-tracking branch 'upstream/master'

This commit is contained in:
Éder F. Zulian
2016-02-17 22:10:20 -02:00
13 changed files with 774 additions and 567 deletions

2
.gitignore vendored
View File

@@ -14,4 +14,6 @@ build*/
._.DS_Store
.DS_Store
*.swp
*.swo
cscope*
DRAMSys/analyzer/scripts/__pycache__/

View File

@@ -52,10 +52,18 @@
using namespace std;
TraceDB::TraceDB(QString path,bool openExisting)
TraceDB::TraceDB(QString path, bool openExisting)
{
this->pathToDB = path;
database = QSqlDatabase::addDatabase("QSQLITE",path);
database = QSqlDatabase::database(path);
if (database.isValid() && database.isOpen()) {
// Close the database connection if it exists and was not closed yet.
database.removeDatabase(path);
database.close();
}
database = QSqlDatabase::addDatabase("QSQLITE", path);
database.setDatabaseName(path);
database.open();
if(!openExisting)

View File

@@ -0,0 +1,57 @@
import sys
import sqlite3
import xml.etree.ElementTree as ET
class MemConfig(object):
""" Memory Configuration Class
The format used in memory specification XML files differs from the
format used in memory configuration XML files. Each class uses the
proper format when searching for elements.
"""
def getValue(self, id):
return self.xmlMemConfig.findall(id)[0].attrib['value']
def getIntValue(self, id):
return int(self.getValue(id))
def __init__(self, dbconnection):
cursor = dbconnection.cursor()
cursor.execute("SELECT Memconfig FROM GeneralInfo")
result = cursor.fetchone()
self.xmlMemConfig = ET.parse(result[0])
class MemSpec(object):
""" Memory Specification Class
The format used in memory specification XML files differs from the
format used in memory configuration XML files. Each class uses the
proper format when searching for elements.
"""
def getValue(self, id):
return self.xmlMemSpec.findall(".//parameter[@id='{0}']".format(id))[0].attrib['value']
def getIntValue(self, id):
return int(self.getValue(id))
def __init__(self, dbconnection):
cursor = dbconnection.cursor()
cursor.execute("SELECT Memspec FROM GeneralInfo")
result = cursor.fetchone()
self.xmlMemSpec = ET.parse(result[0])
def getClock(dbconnection):
cursor = dbconnection.cursor()
cursor.execute("SELECT clk, UnitOfTime FROM GeneralInfo")
clock, unit = cursor.fetchone()
return (clock, unit)
def getNumberOfBanks(dbconnection):
cursor = dbconnection.cursor()
cursor.execute("SELECT NumberOfBanks FROM generalInfo")
result = cursor.fetchone()
return result[0]

View File

@@ -1,63 +1,51 @@
import sys
import sqlite3
from memUtil import *
metrics = []
threadMetrics = []
def metric(function):
metrics.append(function)
return function
metrics.append(function)
return function
def threadMetric(function):
threadMetrics.append(function)
return function
threadMetrics.append(function)
return function
def getThreads(connection):
cursor = connection.cursor()
cursor.execute("SELECT DISTINCT(TThread) FROM transactions WHERE TThread != 0 ORDER BY TThread")
result = []
for currentRow in cursor:
result.append(currentRow[0])
return result
cursor = connection.cursor()
cursor.execute("SELECT DISTINCT(TThread) FROM transactions WHERE TThread != 0 ORDER BY TThread")
result = []
for currentRow in cursor:
result.append(currentRow[0])
return result
def getNumberOfBanks(connection):
cursor = connection.cursor()
cursor.execute("SELECT NumberOfBanks FROM generalInfo")
result = cursor.fetchone()
return result[0]
def getTraceLength(connection):
cursor = connection.cursor()
cursor.execute("SELECT TraceEnd FROM GeneralInfo")
result = cursor.fetchone()
return result[0]
# @metric
# def latency_histogram(connection):
# cursor = connection.cursor()
# cursor.execute("SELECT ((p2.PhaseEnd - p1.PhaseEnd)/1000) FROM Transactions t, Phases p1, Phases p2 WHERE t.id = p1.Transact and t.id = p2.Transact and p1.PhaseName = \"REQ\" and p2.PhaseName = \"RESP\" ")
# result = cursor.fetchall()
# #result.sort()
# #print(max(result)[0])
# import matplotlib.pyplot as plt
# plt.hist(result, bins=max(result)[0], histtype='barstacked')
# plt.savefig('hist.png')
# return "Saved as hist.png"
def getClock(connection):
cursor = connection.cursor()
cursor.execute("SELECT clk FROM GeneralInfo")
result = cursor.fetchone()
return result[0]
#@metric
#def latency_histogram(connection):
# cursor = connection.cursor()
# cursor.execute("SELECT ((p2.PhaseEnd - p1.PhaseEnd)/1000) FROM Transactions t, Phases p1, Phases p2 WHERE t.id = p1.Transact and t.id = p2.Transact and p1.PhaseName = \"REQ\" and p2.PhaseName = \"RESP\" ")
# result = cursor.fetchall()
# #result.sort()
# #print(max(result)[0])
# import matplotlib.pyplot as plt
# plt.hist(result, bins=max(result)[0], histtype='barstacked')
# plt.savefig('hist.png')
# return "Saved as hist.png"
#@metric
#def average_response_latency_in_ns(connection):
# cursor = connection.cursor()
# cursor.execute("""SELECT avg(PhaseBegin-timeOfGeneration)/1000 FROM transactions INNER JOIN Phases
# ON phases.transact = transactions.ID WHERE PhaseName='RESP' """)
# @metric
# def average_response_latency_in_ns(connection):
# cursor = connection.cursor()
# 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)
# result = cursor.fetchone()
# return round(result[0],1)
@metric
def trace_length_in_ns(connection):
@@ -66,300 +54,372 @@ def trace_length_in_ns(connection):
result = cursor.fetchone()
return result[0]
@metric
def average_response_latency_in_ns(connection):
cursor = connection.cursor()
cursor.execute("""SELECT AVG(RESP.PHASEBEGIN - REQ.PHASEBEGIN)/1000 FROM PHASES REQ, PHASES RESP WHERE REQ.PHASENAME = 'REQ' AND RESP.PHASENAME='RESP' AND REQ.TRANSACT = RESP.TRANSACT """)
cursor = connection.cursor()
cursor.execute("""SELECT AVG(RESP.PHASEBEGIN - REQ.PHASEBEGIN)/1000 FROM PHASES REQ, PHASES RESP WHERE REQ.PHASENAME = 'REQ' AND RESP.PHASENAME='RESP' AND REQ.TRANSACT = RESP.TRANSACT """)
result = cursor.fetchone()
return round(result[0], 1)
result = cursor.fetchone()
return round(result[0],1)
@metric
def trans_with_max_response_latency(connection):
cursor = connection.cursor()
cursor.execute(""" SELECT REQ.TRANSACT, max(RESP.PHASEBEGIN - REQ.PHASEBEGIN)/1000 FROM PHASES REQ, PHASES RESP WHERE REQ.PHASENAME = 'REQ' AND RESP.PHASENAME='RESP' AND REQ.TRANSACT = RESP.TRANSACT """)
cursor = connection.cursor()
cursor.execute(""" SELECT REQ.TRANSACT, max(RESP.PHASEBEGIN - REQ.PHASEBEGIN)/1000 FROM PHASES REQ, PHASES RESP WHERE REQ.PHASENAME = 'REQ' AND RESP.PHASENAME='RESP' AND REQ.TRANSACT = RESP.TRANSACT """)
result = cursor.fetchone()
return result[0]
result = cursor.fetchone()
return result[0]
@metric
def memory_active(connection):
cursor = connection.cursor()
cursor.execute(""" SELECT sum(DataStrobeEnd - DataStrobeBegin) FROM transactions """)
active = cursor.fetchone()
cursor = connection.cursor()
cursor.execute(""" SELECT clk FROM GeneralInfo """)
clk = cursor.fetchone()
return (active[0]/clk[0])
cursor = connection.cursor()
cursor.execute(""" SELECT sum(DataStrobeEnd - DataStrobeBegin) FROM transactions """)
active = cursor.fetchone()
cursor = connection.cursor()
cursor.execute(""" SELECT clk FROM GeneralInfo """)
clk = cursor.fetchone()
return (active[0]/clk[0])
@metric
def memory_total(connection):
cursor = connection.cursor()
cursor.execute(""" SELECT max(DataStrobeEnd) FROM Transactions """)
total = cursor.fetchone()
cursor = connection.cursor()
cursor.execute(""" SELECT clk FROM GeneralInfo """)
clk = cursor.fetchone()
return (total[0]/clk[0])
cursor = connection.cursor()
cursor.execute(""" SELECT max(DataStrobeEnd) FROM Transactions """)
total = cursor.fetchone()
cursor = connection.cursor()
cursor.execute(""" SELECT clk FROM GeneralInfo """)
clk = cursor.fetchone()
return (total[0]/clk[0])
@metric
def memory_idle(connection):
cursor = connection.cursor()
cursor.execute(""" SELECT sum(p1.PhaseEnd - p2.PhaseBegin) FROM Phases p1, Phases p2 Where p1.PhaseName = "REQ" and p2.PhaseName = "RESP" and ((p1.Transact-1) = (p2.Transact)) and (p1.PhaseEnd > p2.PhaseBegin) """)
idle = cursor.fetchone()
cursor = connection.cursor()
cursor.execute(""" SELECT clk FROM GeneralInfo """)
clk = cursor.fetchone()
if idle[0] == None:
return 0;
else:
return (idle[0]/clk[0])
cursor = connection.cursor()
cursor.execute(""" SELECT sum(p1.PhaseEnd - p2.PhaseBegin) FROM Phases p1, Phases p2 Where p1.PhaseName = "REQ" and p2.PhaseName = "RESP" and ((p1.Transact-1) = (p2.Transact)) and (p1.PhaseEnd > p2.PhaseBegin) """)
idle = cursor.fetchone()
cursor = connection.cursor()
cursor.execute(""" SELECT clk FROM GeneralInfo """)
clk = cursor.fetchone()
if (idle[0] is None):
return 0
else:
return (idle[0]/clk[0])
@metric
def memory_utilisation_percent_new(connection):
total = memory_total(connection)
active = memory_active(connection)
idle = memory_idle(connection)
return (active/(total-idle))*100
total = memory_total(connection)
active = memory_active(connection)
idle = memory_idle(connection)
return (active/(total-idle))*100
@metric
def memory_utilisation_percent_old(connection):
cursor = connection.cursor()
cursor.execute(""" SELECT sum(DataStrobeEnd - DataStrobeBegin) FROM transactions """)
active = cursor.fetchone()
cursor = connection.cursor()
cursor.execute(""" SELECT max(DataStrobeEnd) FROM Transactions """)
total = cursor.fetchone()
return (active[0]/total[0])*100
cursor = connection.cursor()
cursor.execute(""" SELECT sum(DataStrobeEnd - DataStrobeBegin) FROM transactions """)
active = cursor.fetchone()
cursor = connection.cursor()
cursor.execute(""" SELECT max(DataStrobeEnd) FROM Transactions """)
total = cursor.fetchone()
return (active[0]/total[0])*100
def refreshMissDecision(connection, calculatedMetrics):
cursor = connection.cursor()
cursor.execute("""SELECT phases.ID,PhaseBegin,PhaseEnd,TBank FROM Phases INNER JOIN transactions on transactions.id = phases.transact WHERE PhaseName='AUTO_REFRESH' """)
queryMinREQ = """SELECT id,min(PhaseBegin) FROM (SELECT transactions.id, PhaseBegin FROM transactions
inner join ranges on ranges.id = transactions.range inner join phases on phases.transact = transactions.id
where tthread != 0 and tbank = :bank and PhaseName = "REQ" and ranges.begin<:begin and ranges.end>:end)"""
def refreshMissDecision(connection,calculatedMetrics):
cursor = connection.cursor()
cursor.execute("""SELECT phases.ID,PhaseBegin,PhaseEnd,TBank FROM Phases INNER JOIN transactions on transactions.id = phases.transact WHERE PhaseName='AUTO_REFRESH' """)
queryMinREQ = """SELECT id,min(PhaseBegin) FROM (SELECT transactions.id, PhaseBegin FROM transactions
inner join ranges on ranges.id = transactions.range inner join phases on phases.transact = transactions.id
where tthread != 0 and tbank = :bank and PhaseName = "REQ" and ranges.begin<:begin and ranges.end>:end)"""
queryMinRESP = """SELECT id,min(PhaseBegin) FROM (SELECT transactions.id, PhaseBegin FROM transactions
inner join ranges on ranges.id = transactions.range inner join phases on phases.transact = transactions.id
where tthread != 0 and tbank = :bank and PhaseName = "RESP" and ranges.begin<:begin and ranges.end>:end) """
queryMinRESP = """SELECT id,min(PhaseBegin) FROM (SELECT transactions.id, PhaseBegin FROM transactions
inner join ranges on ranges.id = transactions.range inner join phases on phases.transact = transactions.id
where tthread != 0 and tbank = :bank and PhaseName = "RESP" and ranges.begin<:begin and ranges.end>:end) """
missDecisions = 0
totalDecisios = 0
missDecisions = 0
totalDecisios = 0
for refresh in cursor:
id = refresh[0]
begin = refresh[1]
end = refresh[2]
bank = refresh[3]
#print('Refresh: {0} {1} {2} {3}'.format(id,begin,end,bank))
cursorMinREQ = connection.cursor()
cursorMinRESP = connection.cursor()
cursorMinREQ.execute(queryMinREQ, {"bank":bank, "begin":begin, "end":end})
cursorMinRESP.execute(queryMinRESP, {"bank":bank, "begin":begin, "end":end})
for refresh in cursor:
id = refresh[0]
begin = refresh[1]
end = refresh[2]
bank = refresh[3]
# print('Refresh: {0} {1} {2} {3}'.format(id,begin,end,bank))
earliestReq = cursorMinREQ.fetchone()
earliestResp = cursorMinRESP.fetchone()
if(earliestReq[0] != None):
totalDecisios = totalDecisios + 1
cursorMinREQ = connection.cursor()
cursorMinRESP = connection.cursor()
cursorMinREQ.execute(queryMinREQ, {"bank": bank, "begin": begin, "end": end})
cursorMinRESP.execute(queryMinRESP, {"bank": bank, "begin": begin, "end": end})
earliestReq = cursorMinREQ.fetchone()
earliestResp = cursorMinRESP.fetchone()
if (earliestReq[0] is not None):
totalDecisios = totalDecisios + 1
if(earliestReq[0] != earliestResp[0]):
missDecisions = missDecisions + 1
#print("earliest Req: {0}| earliest Res: {1}".format(earliestReq[0], earliestResp[0]))
end
missDecisions = missDecisions + 1
# print("earliest Req: {0}| earliest Res: {1}".format(earliestReq[0], earliestResp[0]))
if (totalDecisios != 0):
# calculatedMetrics.append(("Total Missdecisions", missDecisions))
calculatedMetrics.append(("Relative Missdecisions", 1.0*missDecisions/totalDecisios))
else:
calculatedMetrics.append(("Total Missdecisions", 0))
calculatedMetrics.append(("Relative Missdecisions", 0))
if(totalDecisios != 0):
#calculatedMetrics.append(("Total Missdecisions", missDecisions))
calculatedMetrics.append(("Relative Missdecisions", 1.0*missDecisions/totalDecisios))
else:
calculatedMetrics.append(("Total Missdecisions", 0))
calculatedMetrics.append(("Relative Missdecisions", 0))
@threadMetric
def average_response_latency_in_ns(connection, thread):
cursor = connection.cursor()
query = """SELECT avg(PhaseBegin-timeOfGeneration)/1000 FROM transactions INNER JOIN Phases
ON phases.transact = transactions.ID WHERE PhaseName='RESP' AND TThread = :Thread """
cursor = connection.cursor()
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)
cursor.execute(query, {"Thread": thread})
result = cursor.fetchone()
return round(result[0], 1)
def addStallTime(times,begin,end):
time = begin
while time <= end:
if(time in times):
times[time] = times[time] + 1
else:
times[time] = 1
time = time + 1
#@threadMetric
def addStallTime(times, begin, end):
time = begin
while time <= end:
if(time in times):
times[time] = times[time] + 1
else:
times[time] = 1
time = time + 1
# @threadMetric
def paralellism(connection, thread):
cursor = connection.cursor()
stalltimes = {}
query = """SELECT transactions.ID,MIN(phaseBegin)/:clk,MAX(phaseEnd)/:clk
from phases inner join transactions on phases.transact=transactions.id
where phaseName Not in ('REQ','RESP') and tthread=:Thread group by transactions.ID """
cursor = connection.cursor()
stalltimes = {}
query = """SELECT transactions.ID,MIN(phaseBegin)/:clk,MAX(phaseEnd)/:clk
from phases inner join transactions on phases.transact=transactions.id
where phaseName Not in ('REQ','RESP') and tthread=:Thread group by transactions.ID """
clk, unit = getClock(connection)
cursor.execute(query, {"Thread": thread, "clk": clk})
for currentRow in cursor:
addStallTime(stalltimes, currentRow[1], currentRow[2])
para = 0
for time in stalltimes:
para = para + stalltimes[time]
return round(para/len(stalltimes), 2)
cursor.execute(query, {"Thread": thread, "clk" : getClock(connection)})
for currentRow in cursor:
addStallTime(stalltimes,currentRow[1],currentRow[2])
para = 0
for time in stalltimes:
para = para + stalltimes[time]
return round(para/len(stalltimes),2)
@metric
def number_of_activates(connection):
cursor = connection.cursor()
cursor.execute("SELECT COUNT(*) FROM Phases WHERE PhaseName = 'ACT'")
result = cursor.fetchone()
return result[0]
cursor = connection.cursor()
cursor.execute("SELECT COUNT(*) FROM Phases WHERE PhaseName = 'ACT'")
result = cursor.fetchone()
return result[0]
@metric
def number_of_accesses(connection):
cursor = connection.cursor()
cursor.execute("SELECT COUNT(*) FROM Phases WHERE PhaseName IN ('REQ')")
result = cursor.fetchone()
return result[0]
cursor = connection.cursor()
cursor.execute("SELECT COUNT(*) FROM Phases WHERE PhaseName IN ('REQ')")
result = cursor.fetchone()
return result[0]
# @metric
# def number_of_precharges(connection):
# cursor = connection.cursor()
# cursor.execute("SELECT COUNT(*) FROM Phases WHERE PhaseName IN ('PRE','PRE_ALL','RDA','WRA')")
# result = cursor.fetchone()
# return result[0]
# cursor = connection.cursor()
# cursor.execute("SELECT COUNT(*) FROM Phases WHERE PhaseName IN ('PRE','PRE_ALL','RDA','WRA')")
# 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)
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 get_total_time_in_phase(connection, phase):
cursor = connection.cursor()
query = "SELECT SUM(PhaseEnd - PhaseBegin) / 1000 from Phases where PhaseName = :phase"
cursor.execute(query, {"phase": phase})
time = cursor.fetchone()
totalTime = time[0]
if (totalTime is None):
totalTime = 0.0
return totalTime
def time_in_PDNA_in_ns(connection):
return get_total_time_in_phase(connection, "PDNA")
def time_in_PDNA_percent(connection):
return (time_in_PDNA_in_ns(connection) * 1.0 / trace_length_in_ns(connection)) * 100
def time_in_PDNP_in_ns(connection):
return get_total_time_in_phase(connection, "PDNP")
def time_in_PDNP_percent(connection):
return (time_in_PDNP_in_ns(connection) * 1.0 / trace_length_in_ns(connection)) * 100
def time_in_SREF_in_ns(connection):
return get_total_time_in_phase(connection, "SREF")
def time_in_SREF_percent(connection):
return (time_in_SREF_in_ns(connection) * 1.0 / trace_length_in_ns(connection)) * 100
def time_in_PDNAB_in_ns(connection):
return get_total_time_in_phase(connection, "PDNAB")
def time_in_PDNAB_percent(connection):
totalTimeAllBanks = trace_length_in_ns(connection) * getNumberOfBanks(connection)
return (time_in_PDNAB_in_ns(connection) * 1.0 / totalTimeAllBanks) * 100
def time_in_PDNPB_in_ns(connection):
return get_total_time_in_phase(connection, "PDNPB")
def time_in_PDNPB_percent(connection):
totalTimeAllBanks = trace_length_in_ns(connection) * getNumberOfBanks(connection)
return (time_in_PDNPB_in_ns(connection) * 1.0 / totalTimeAllBanks) * 100
def time_in_SREFB_in_ns(connection):
return get_total_time_in_phase(connection, "SREFB")
def time_in_SREFB_percent(connection):
totalTimeAllBanks = trace_length_in_ns(connection) * getNumberOfBanks(connection)
return (time_in_SREFB_in_ns(connection) * 1.0 / totalTimeAllBanks) * 100
@metric
def timeInPowerStates(connection):
totalTimeAllBanks = getTraceLength(connection)#*getNumberOfBanks(connection)
cursor = connection.cursor()
result = []
def time_in_power_down_states_in_ns(connection):
memconfig = MemConfig(connection)
bankwiseLogic = memconfig.getValue("BankwiseLogic")
if bankwiseLogic == "0":
totalTimeInPDNA = time_in_PDNA_in_ns(connection)
totalTimeInPDNP = time_in_PDNP_in_ns(connection)
totalTimeInSREF = time_in_SREF_in_ns(connection)
totalTimePdnStates = totalTimeInPDNA + totalTimeInPDNP + totalTimeInSREF
else:
totalTimeInPDNAB = time_in_PDNAB_in_ns(connection)
totalTimeInPDNPB = time_in_PDNPB_in_ns(connection)
totalTimeInSREFB = time_in_SREFB_in_ns(connection)
totalTimePdnStates = totalTimeInPDNAB + totalTimeInPDNPB + totalTimeInSREFB
cursor.execute("SELECT SUM(PhaseEnd-PhaseBegin) from Phases where PhaseName = 'PDNA'")
timeInPDNA = cursor.fetchone()
totalTimeInPDNA = timeInPDNA[0]
if(totalTimeInPDNA == None):
totalTimeInPDNA = 0.0
fractionInPDNA = totalTimeInPDNA*1.0/totalTimeAllBanks
result.append(("Time in PDNA (%)", fractionInPDNA*100))
print("{0} {1}".format(result[-1][0],result[-1][1]))
return totalTimePdnStates
cursor.execute("SELECT SUM(PhaseEnd-PhaseBegin) from Phases where PhaseName = 'PDNP'")
timeInPDNP = cursor.fetchone()
totalTimeInPDNP = timeInPDNP[0]
if(totalTimeInPDNP == None):
totalTimeInPDNP = 0.0
fractionInPDNP = totalTimeInPDNP*1.0/totalTimeAllBanks
result.append(("Time in PDNP (%)", fractionInPDNP*100))
print("{0} {1}".format(result[-1][0],result[-1][1]))
cursor.execute("SELECT SUM(PhaseEnd-PhaseBegin) from Phases where PhaseName = 'SREF'")
timeInSREF = cursor.fetchone()
totalTimeInSREF = timeInSREF[0]
if(totalTimeInSREF == None):
totalTimeInSREF = 0.0
fractionInSREF = totalTimeInSREF*1.0/totalTimeAllBanks
result.append(("Time in SREF (%)", fractionInSREF*100))
print("{0} {1}".format(result[-1][0],result[-1][1]))
result.insert(0,("Active time (%)", (1-fractionInPDNA-fractionInPDNP-fractionInSREF)*100))
print("{0} {1}".format(result[0][0],result[0][1]))
@metric
def time_in_power_down_states_percent(connection):
memconfig = MemConfig(connection)
bankwiseLogic = memconfig.getValue("BankwiseLogic")
if bankwiseLogic == "0":
totalTimeAllBanks = trace_length_in_ns(connection)
else:
totalTimeAllBanks = trace_length_in_ns(connection) * getNumberOfBanks(connection)
return (time_in_power_down_states_in_ns(connection) * 1.0 / totalTimeAllBanks) * 100
return result
def passRatio(connection):
numberOfPassWins = {}
numberOfPassLosses = {}
numberOfPassWins = {}
numberOfPassLosses = {}
for thread in getThreads(connection):
numberOfPassWins[thread] = 0
numberOfPassLosses[thread] = 0
for thread in getThreads(connection):
numberOfPassWins[thread] = 0
numberOfPassLosses[thread] = 0
for bankNumber in range(getNumberOfBanks(connection)):
cursor = connection.cursor()
query = """SELECT begin,end,transactions.ID,TThread,
TBank from transactions inner join ranges on transactions.range = ranges.id WHERE TBank = :Bank AND TThread != 0"""
cursor.execute(query, {"Bank":bankNumber})
for bankNumber in range(getNumberOfBanks(connection)):
cursor = connection.cursor()
query = """SELECT begin,end,transactions.ID,TThread,
TBank from transactions inner join ranges on transactions.range = ranges.id WHERE TBank = :Bank AND TThread != 0"""
cursor.execute(query, {"Bank": bankNumber})
for passedRequest in cursor:
passedBegin = passedRequest[0]
passedEnd = passedRequest[1]
passedId = passedRequest[2]
passedThread = passedRequest[3]
cursor2 = connection.cursor()
query2 = """SELECT begin,end,transactions.ID,TThread,
TBank from transactions inner join ranges on transactions.range = ranges.id
WHERE TBank = :Bank AND :Begin<begin AND end<:End AND TThread != :Thread AND TThread != 0"""
cursor2.execute(query2, {"Bank" : bankNumber, "Thread": passedThread, "Begin" : passedBegin, "End" : passedEnd})
for passingRequest in cursor2:
numberOfPassLosses[passedThread] += 1
numberOfPassWins[passingRequest[3]] += 1
# print("""Transaction {0} (thread:{1} begin:{2} end:{3}) was passed by Transaction {4} (thread:{5} begin:{6} end:{7}) on bank {8}""".format(passedId,passedThread, passedBegin,passedEnd,
# passingRequest[2], passingRequest[3], passingRequest[0], passingRequest[1], bankNumber))
result = []
for thread in getThreads(connection):
totalPassedInvolved = numberOfPassWins[thread]+numberOfPassLosses[thread]
if(totalPassedInvolved > 0):
passRatio = numberOfPassWins[thread]*1.0/(numberOfPassWins[thread]+numberOfPassLosses[thread])
else:
passRatio = 0.5
print("Thread {0} passed other threads {1} times and was passed {2} times. Pass ratio is {3}".format
(thread, numberOfPassWins[thread], numberOfPassLosses[thread],passRatio))
result.append(("Thread {0} pass ratio".format(thread), passRatio))
return result
for passedRequest in cursor:
passedBegin = passedRequest[0]
passedEnd = passedRequest[1]
passedId = passedRequest[2]
passedThread = passedRequest[3]
cursor2 = connection.cursor()
query2 = """SELECT begin,end,transactions.ID,TThread,
TBank from transactions inner join ranges on transactions.range = ranges.id
WHERE TBank = :Bank AND :Begin<begin AND end<:End AND TThread != :Thread AND TThread != 0"""
cursor2.execute(query2, {"Bank": bankNumber, "Thread": passedThread, "Begin": passedBegin, "End": passedEnd})
for passingRequest in cursor2:
numberOfPassLosses[passedThread] += 1
numberOfPassWins[passingRequest[3]] += 1
# print("""Transaction {0} (thread:{1} begin:{2} end:{3}) was passed by Transaction {4} (thread:{5} begin:{6} end:{7}) on bank {8}""".format(passedId,passedThread, passedBegin,passedEnd,
# passingRequest[2], passingRequest[3], passingRequest[0], passingRequest[1], bankNumber))
result = []
for thread in getThreads(connection):
totalPassedInvolved = numberOfPassWins[thread]+numberOfPassLosses[thread]
if(totalPassedInvolved > 0):
passRatio = numberOfPassWins[thread]*1.0/(numberOfPassWins[thread]+numberOfPassLosses[thread])
else:
passRatio = 0.5
print("Thread {0} passed other threads {1} times and was passed {2} times. Pass ratio is {3}".format(thread, numberOfPassWins[thread], numberOfPassLosses[thread], passRatio))
result.append(("Thread {0} pass ratio".format(thread), passRatio))
return result
def calculateMetrics(pathToTrace):
connection = sqlite3.connect(pathToTrace)
calculatedMetrics = []
calculatedMetrics = []
connection = sqlite3.connect(pathToTrace)
print("================================")
print("Calculating metrics for {0}".format(pathToTrace))
memconfig = MemConfig(connection)
bankwiseLogic = memconfig.getValue("BankwiseLogic")
if bankwiseLogic == "0":
pdnMetrics = [time_in_PDNA_in_ns, time_in_PDNA_percent, time_in_PDNP_in_ns, time_in_PDNP_percent, time_in_SREF_in_ns, time_in_SREF_percent]
else:
pdnMetrics = [time_in_PDNAB_in_ns, time_in_PDNAB_percent, time_in_PDNPB_in_ns, time_in_PDNPB_percent, time_in_SREFB_in_ns, time_in_SREFB_percent]
if(len(getThreads(connection))==1):
for metric in metrics:
res = (metric.__name__.replace("_"," "), metric(connection))
print("{0}: {1}".format(res[0],res[1]))
calculatedMetrics.append(res)
for m in pdnMetrics:
if m not in metrics:
metrics.append(m)
if(len(getThreads(connection))>1):
# for thread in getThreads(connection):
# for metric in threadMetrics:
# res = ("Thread " + str(thread) + " " + metric.__name__.replace("_"," "), metric(connection, thread))
# print("{0}: {1}".format(res[0],res[1]))
# calculatedMetrics.append(res)
calculatedMetrics.extend(passRatio(connection))
#refreshMissDecision(connection, calculatedMetrics)
print("================================")
print("Calculating metrics for {0}".format(pathToTrace))
#calculatedMetrics.extend(timeInPowerStates(connection))
#print(calculatedMetrics[-1])
#print(calculatedMetrics[-2])
#refreshMissDecision(connection, calculatedMetrics)
print(calculatedMetrics[-1])
print(calculatedMetrics[-2])
connection.close()
return calculatedMetrics
print("Number of threads is {0}".format(len(getThreads(connection))))
if (len(getThreads(connection)) == 1):
for metric in metrics:
res = (metric.__name__.replace("_", " "), metric(connection))
print("{0}: {1}".format(res[0], res[1]))
calculatedMetrics.append(res)
if (len(getThreads(connection)) > 1):
# for thread in getThreads(connection):
# for metric in threadMetrics:
# res = ("Thread " + str(thread) + " " + metric.__name__.replace("_"," "), metric(connection, thread))
# print("{0}: {1}".format(res[0],res[1]))
# calculatedMetrics.append(res)
calculatedMetrics.extend(passRatio(connection))
# refreshMissDecision(connection, calculatedMetrics)
if (len(getThreads(connection)) == 0):
res = ("No accesses were performed for this channel, number of metrics generated", 0.0)
calculatedMetrics.append(res)
# refreshMissDecision(connection, calculatedMetrics)
connection.close()
return calculatedMetrics
if __name__ == "__main__":
path = sys.argv[1]
calculateMetrics(path)
path = sys.argv[1]
calculateMetrics(path)

View File

@@ -3,35 +3,8 @@ import traceback
import sqlite3
import os
import xml.etree.ElementTree as ET
from memUtil import *
def getPathToConfigs():
return os.path.dirname(os.path.abspath(__file__).replace("/scripts","/configs"))
def getValueFromConfigXML(root, id):
return root.findall(".//parameter[@id='{0}']".format(id))[0].attrib['value']
def getIntValueFromConfigXML(root, id):
return int(root.findall(".//parameter[@id='{0}']".format(id))[0].attrib['value'])
def getMemconfig(connection):
cursor = connection.cursor()
cursor.execute("SELECT Memconfig FROM GeneralInfo")
result = cursor.fetchone()
memconfig = result[0]
return ET.parse(memconfig)
def getMemspec(connection):
cursor = connection.cursor()
cursor.execute("SELECT Memspec FROM GeneralInfo")
result = cursor.fetchone()
memspec = result[0]
return ET.parse(memspec)
def getClock(connection):
cursor = connection.cursor()
cursor.execute("SELECT clk, UnitOfTime FROM GeneralInfo")
result = cursor.fetchone()
return (result[0],result[1])
class DramConfig(object):
memoryType = ""
@@ -43,98 +16,99 @@ class DramConfig(object):
nActivateWindow = numberOfBanks = 0
clk = 0
tRP = 0 #precharge-time (pre -> act same bank)
tRAS = 0 #active-time (act -> pre same bank)
tRC = 0 #RAS-cycle-time (min time bw 2 succesive ACT to same bank)
tCCD_S = 0 #TODO: relevant? max(bl, tCCD)
tRP = 0 # precharge-time (pre -> act same bank)
tRAS = 0 # active-time (act -> pre same bank)
tRC = 0 # RAS-cycle-time (min time bw 2 succesive ACT to same bank)
tCCD_S = 0 # TODO: relevant? max(bl, tCCD)
tCCD_L = 0
tRTP = 0 #Read to precharge
tRRD_S = 0 #min time bw 2 succesive ACT to different banks (different bank group)
tRRD_L = 0 #.. (same bank group)
tRCD = 0 #act -> read/write
tNAW = 0 #n activate window
tRL = 0 #read latency (read command start to data strobe)
tWL = 0 #write latency
tWR = 0 #write recovery (write to precharge)
tWTR_S = 0 #write to read (different bank group)
tWTR_L = 0 #.. (same bank group)
tCKESR = 0 #min time in sref
tCKE = 0 #min time in pdna or pdnp
tXP = 0 #min delay to row access command after pdnpx pdnax
tXPDLL = 0 #min delay to row access command after pdnpx pdnax for dll commands
tXSR = 0 #min delay to row access command after srefx
tXSRDLL = 0 #min delay to row access command after srefx for dll commands
tAL = 0 #additive delay (delayed execution in dram)
tRFC = 0 #min ref->act delay
tRTP = 0 # Read to precharge
tRRD_S = 0 # min time between 2 succesive ACT to different banks (different bank group)
tRRD_L = 0 # min time between 2 succesive ACT to different banks (same bank group)
tRCD = 0 # act -> read/write
tNAW = 0 # n activate window
tRL = 0 # read latency (read command start to data strobe)
tWL = 0 # write latency
tWR = 0 # write recovery (write to precharge)
tWTR_S = 0 # write to read (different bank group)
tWTR_L = 0 # write to read (same bank group)
tCKESR = 0 # min time in sref
tCKE = 0 # min time in pdna or pdnp
tXP = 0 # min delay to row access command after pdnpx pdnax
tXPDLL = 0 # min delay to row access command after pdnpx pdnax for dll commands
tXSR = 0 # min delay to row access command after srefx
tXSRDLL = 0 # min delay to row access command after srefx for dll commands
tAL = 0 # additive delay (delayed execution in dram)
tRFC = 0 # min ref->act delay
def readConfigFromFiles(self, connection):
print("Parsing dram configuration")
memspec = getMemspec(connection)
memconfig = MemConfig(connection)
memspec = MemSpec(connection)
clkWithUnit = getClock(connection)
self.clk = clkWithUnit[0]
self.unitOfTime = clkWithUnit[1].lower()
print(getMemconfig(connection))
self.bankwiseLogic = getMemconfig(connection).findall("BankwiseLogic")[0].attrib['value']
self.scheduler = getMemconfig(connection).findall("Scheduler")[0].attrib['value']
self.numberOfBanks = getIntValueFromConfigXML(memspec, "nbrOfBanks")
self.burstLength = getIntValueFromConfigXML(memspec, "burstLength")
self.memoryType = getValueFromConfigXML(memspec, "memoryType")
self.dataRate = getIntValueFromConfigXML(memspec, "dataRate")
self.bankwiseLogic = memconfig.getValue("BankwiseLogic")
self.scheduler = memconfig.getValue("Scheduler")
if(self.memoryType == "WIDEIO_SDR"):
self.nActivateWindow = 2;
self.tRP = self.clk * getIntValueFromConfigXML(memspec, "RP")
self.tRAS = self.clk * getIntValueFromConfigXML(memspec, "RAS")
self.tRC = self.clk * getIntValueFromConfigXML(memspec, "RC")
self.tRRD_S = self.clk * getIntValueFromConfigXML(memspec, "RRD")
self.numberOfBanks = memspec.getIntValue("nbrOfBanks")
self.burstLength = memspec.getIntValue("burstLength")
self.memoryType = memspec.getValue("memoryType")
self.dataRate = memspec.getIntValue("dataRate")
if (self.memoryType == "WIDEIO_SDR"):
self.nActivateWindow = 2
self.tRP = self.clk * memspec.getIntValue("RP")
self.tRAS = self.clk * memspec.getIntValue("RAS")
self.tRC = self.clk * memspec.getIntValue("RC")
self.tRRD_S = self.clk * memspec.getIntValue("RRD")
self.tRRD_L = self.tRRD_S
self.tCCD_S = self.clk * getIntValueFromConfigXML(memspec, "CCD")
self.tCCD_S = self.clk * memspec.getIntValue("CCD")
self.tCCD_L = self.tCCD_S
self.tRCD = self.clk * getIntValueFromConfigXML(memspec, "RCD")
self.tNAW = self.clk * getIntValueFromConfigXML(memspec, "TAW")
self.tRL = self.clk * getIntValueFromConfigXML(memspec, "RL")
self.tWL = self.clk * getIntValueFromConfigXML(memspec, "WL")
self.tWR = self.clk * getIntValueFromConfigXML(memspec, "WR")
self.tWTR_S = self.clk * getIntValueFromConfigXML(memspec, "WTR")
self.tRCD = self.clk * memspec.getIntValue("RCD")
self.tNAW = self.clk * memspec.getIntValue("TAW")
self.tRL = self.clk * memspec.getIntValue("RL")
self.tWL = self.clk * memspec.getIntValue("WL")
self.tWR = self.clk * memspec.getIntValue("WR")
self.tWTR_S = self.clk * memspec.getIntValue("WTR")
self.tWTR_L = self.tWTR_S
self.tRTP = self.clk * getIntValueFromConfigXML(memspec, "RTP");
self.tCKESR = self.clk * getIntValueFromConfigXML(memspec, "CKESR")
self.tCKE = self.clk * getIntValueFromConfigXML(memspec, "CKE")
self.tXP = self.clk * getIntValueFromConfigXML(memspec, "XP")
self.tRTP = self.clk * memspec.getIntValue("RTP")
self.tCKESR = self.clk * memspec.getIntValue("CKESR")
self.tCKE = self.clk * memspec.getIntValue("CKE")
self.tXP = self.clk * memspec.getIntValue("XP")
self.tXPDLL = self.tXP
self.tXSR = self.clk * getIntValueFromConfigXML(memspec, "XS")
self.tXSR = self.clk * memspec.getIntValue("XS")
self.tXSRDLL = self.tXSR
self.tAL = self.clk * getIntValueFromConfigXML(memspec, "AL")
self.tRFC = self.clk * getIntValueFromConfigXML(memspec, "RFC")
self.tAL = self.clk * memspec.getIntValue("AL")
self.tRFC = self.clk * memspec.getIntValue("RFC")
elif(self. memoryType == "DDR4"):
self.nActivateWindow = 4;
self.tRP = self.clk * getIntValueFromConfigXML(memspec, "RP");
self.tRAS = self.clk * getIntValueFromConfigXML(memspec, "RAS");
self.tRC = self.clk * getIntValueFromConfigXML(memspec, "RC");
self.tRTP = self.clk * getIntValueFromConfigXML(memspec, "RTP");
self.tRRD_S = self.clk * getIntValueFromConfigXML(memspec, "RRD_S");
self.tRRD_L = self.clk * getIntValueFromConfigXML(memspec, "RRD_L");
self.tCCD_S = self.clk * getIntValueFromConfigXML(memspec, "CCD_S");
self.tCCD_L = self.clk * getIntValueFromConfigXML(memspec, "CCD_L");
self.tRCD = self.clk * getIntValueFromConfigXML(memspec, "RCD");
self.tNAW = self.clk * getIntValueFromConfigXML(memspec, "FAW");
self.tRL = self.clk * getIntValueFromConfigXML(memspec, "RL");
self.tWL = self.clk * getIntValueFromConfigXML(memspec, "WL");
self.tWR = self.clk * getIntValueFromConfigXML(memspec, "WR");
self.tWTR_S = self.clk * getIntValueFromConfigXML(memspec, "WTR_S");
self.tWTR_L = self.clk * getIntValueFromConfigXML(memspec, "WTR_L");
self.tCKESR = self.clk * getIntValueFromConfigXML(memspec, "CKESR");
self.tCKE = self.clk * getIntValueFromConfigXML(memspec, "CKE");
self.tXP = self.clk * getIntValueFromConfigXML(memspec, "XP");
self.tXPDLL = self.clk * getIntValueFromConfigXML(memspec, "XPDLL");
self.tXSR = self.clk * getIntValueFromConfigXML(memspec, "XS");
self.tXSRDLL = self.clk * getIntValueFromConfigXML(memspec, "XSDLL");
self.tAL = self.clk * getIntValueFromConfigXML(memspec, "AL");
self.tRFC = self.clk * getIntValueFromConfigXML(memspec, "RFC");
elif (self. memoryType == "DDR4"):
self.nActivateWindow = 4
self.tRP = self.clk * memspec.getIntValue("RP")
self.tRAS = self.clk * memspec.getIntValue("RAS")
self.tRC = self.clk * memspec.getIntValue("RC")
self.tRTP = self.clk * memspec.getIntValue("RTP")
self.tRRD_S = self.clk * memspec.getIntValue("RRD_S")
self.tRRD_L = self.clk * memspec.getIntValue("RRD_L")
self.tCCD_S = self.clk * memspec.getIntValue("CCD_S")
self.tCCD_L = self.clk * memspec.getIntValue("CCD_L")
self.tRCD = self.clk * memspec.getIntValue("RCD")
self.tNAW = self.clk * memspec.getIntValue("FAW")
self.tRL = self.clk * memspec.getIntValue("RL")
self.tWL = self.clk * memspec.getIntValue("WL")
self.tWR = self.clk * memspec.getIntValue("WR")
self.tWTR_S = self.clk * memspec.getIntValue("WTR_S")
self.tWTR_L = self.clk * memspec.getIntValue("WTR_L")
self.tCKESR = self.clk * memspec.getIntValue("CKESR")
self.tCKE = self.clk * memspec.getIntValue("CKE")
self.tXP = self.clk * memspec.getIntValue("XP")
self.tXPDLL = self.clk * memspec.getIntValue("XPDLL")
self.tXSR = self.clk * memspec.getIntValue("XS")
self.tXSRDLL = self.clk * memspec.getIntValue("XSDLL")
self.tAL = self.clk * memspec.getIntValue("AL")
self.tRFC = self.clk * memspec.getIntValue("RFC")
else:
raise Exception("MemoryType not supported yet. Insert a coin into the coin machine and try again")
@@ -144,7 +118,7 @@ class DramConfig(object):
return math.ceil(1.0*value/self.clk)*self.clk
def getWriteAccessTime(self):
if(self.dataRate == 1):
if (self.dataRate == 1):
return self.clk*(self.burstLength - 1)
elif (self.memoryType == "DDR4"):
return self.clk*self.burstLength/self.dataRate
@@ -152,44 +126,54 @@ class DramConfig(object):
def getReadAccessTime(self):
return self.burstLength/self.dataRate * dramconfig.clk
def __init__(self):
pass
dramconfig = DramConfig()
def calculateReadLength(burstLength):
return dramconfig.tRL + burstLength * dramconfig.clk
def calculateWriteLength(burstLength):
return dramconfig.tWL + burstLength * dramconfig.clk
# ----------- test utils ---------------------------------------
tests = []
def test(function):
tests.append(function)
return function
class TestResult(object):
passed = True
message = ''
def __init__(self, passed = True, message = ''):
def __init__(self, passed=True, message=''):
self.passed = passed
self.message = message
def TestSuceeded():
return TestResult()
def TestFailed(message):
return TestResult(False,message);
return TestResult(False, message)
def formatTime(time):
return ('{0} {1}'.format(time, dramconfig.unitOfTime))
# ----------- checks ---------------------------------------
@test
def commands_are_clockaligned(connection):
"""Checks that all commands on the command bus are aligned to the system clock"""
@@ -200,11 +184,11 @@ def commands_are_clockaligned(connection):
result = cursor.fetchone()
if(result != None):
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)))
if (result is not None):
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
def commandbus_slots_are_used_once(connection):
"""Checks that no two phases on the command bus start at the same time"""
@@ -221,7 +205,7 @@ def commandbus_slots_are_used_once(connection):
cursor.execute(query)
result = cursor.fetchone()
if(result != None):
if (result is not None):
return TestFailed("Slot on commandbus at time {0} is used multiple times".format(formatTime(result[0])))
return TestSuceeded()
@@ -235,37 +219,36 @@ def phase_transitions_are_valid(connection):
# validTransitions tells you which phases are allowed to follow the last transaction.
if(dramconfig.bankwiseLogic == "1"):
if (dramconfig.bankwiseLogic == "1"):
validTransitions['PRE'] = set(['ACT', 'REFB'])
validTransitions['ACT'] = set(['RD', 'RDA', 'WR', 'WRA', 'PRE', 'PRE_ALL'])
validTransitions['RD'] = set(['PRE','RD','RDA', 'WR', 'WRA', 'PDNAB'])
validTransitions['WR'] = set(['PRE', 'RD','RDA', 'WR', 'WRA', 'PDNAB'])
validTransitions['RD'] = set(['PRE', 'RD', 'RDA', 'WR', 'WRA', 'PDNAB'])
validTransitions['WR'] = set(['PRE', 'RD', 'RDA', 'WR', 'WRA', 'PDNAB'])
validTransitions['RDA'] = set(['ACT', 'REFB', 'PDNPB'])
validTransitions['WRA'] = set(['ACT', 'REFB', 'PDNPB'])
validTransitions['REFB'] = set(['ACT', 'PDNPB', 'SREFB'])
validTransitions['PDNAB'] = set(['PRE', 'RD','RDA', 'WR', 'WRA', 'REFB'])
validTransitions['PDNAB'] = set(['PRE', 'RD', 'RDA', 'WR', 'WRA', 'REFB'])
validTransitions['PDNPB'] = set(['ACT', 'REFB'])
validTransitions['SREFB'] = set(['ACT'])
else:
validTransitions['PRE'] = set(['ACT','PRE_ALL'])
validTransitions['PRE'] = set(['ACT', 'PRE_ALL'])
validTransitions['PRE_ALL'] = set(['REFA'])
validTransitions['ACT'] = set(['RD', 'RDA', 'WR', 'WRA', 'PRE_ALL'])
validTransitions['RD'] = set(['PRE', 'PRE_ALL','RD','RDA', 'WR', 'WRA', 'PDNA'])
validTransitions['WR'] = set(['PRE', 'PRE_ALL','RD','RDA', 'WR', 'WRA', 'PDNA'])
validTransitions['RD'] = set(['PRE', 'PRE_ALL', 'RD', 'RDA', 'WR', 'WRA', 'PDNA'])
validTransitions['WR'] = set(['PRE', 'PRE_ALL', 'RD', 'RDA', 'WR', 'WRA', 'PDNA'])
validTransitions['RDA'] = set(['PRE_ALL', 'ACT', 'REFA', 'PDNA', 'PDNP'])
validTransitions['WRA'] = set(['PRE_ALL', 'ACT', 'REFA', 'PDNA', 'PDNP'])
validTransitions['REFA'] = set(['PRE_ALL', 'ACT','REFA', 'PDNA', 'PDNP', 'SREF'])
validTransitions['REFA'] = set(['PRE_ALL', 'ACT', 'REFA', 'PDNA', 'PDNP', 'SREF'])
validTransitions['PDNA'] = set(['PRE','PRE_ALL','ACT', 'RD', 'RDA', 'WR', 'WRA', 'REFA', 'PDNA', 'PDNP'])
validTransitions['PDNA'] = set(['PRE', 'PRE_ALL', 'ACT', 'RD', 'RDA', 'WR', 'WRA', 'REFA', 'PDNA', 'PDNP'])
validTransitions['PDNP'] = set(['PRE_ALL', 'ACT', 'REFA', 'PDNA', 'PDNP'])
validTransitions['SREF'] = set(['PRE_ALL', 'ACT', 'REFA', 'PDNA', 'PDNP'])
# This was the original query:
# 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"""
# However, refreshes and pre_all are attributed to Bank 0 therefore this must be added to the order evaluation:
@@ -282,10 +265,10 @@ def phase_transitions_are_valid(connection):
lastRow = cursor.fetchone()
for currentRow in cursor:
currentPhase = currentRow[0]
lastPhase = lastRow[0]
lastPhase = lastRow[0]
if(currentPhase not in validTransitions[lastPhase]):
return TestFailed("Phase {0}({1}) is not allowed to follow phase {2}({3})".format(currentRow[1],currentPhase,lastRow[1],lastPhase))
if (currentPhase not in validTransitions[lastPhase]):
return TestFailed("Phase {0}({1}) is not allowed to follow phase {2}({3})".format(currentRow[1], currentPhase, lastRow[1], lastPhase))
lastRow = currentRow
return TestSuceeded()
@@ -295,60 +278,66 @@ def timing_constraint(FirstPhase, SecondPhase):
FirstPhaseName = FirstPhase[0]
SecondPhaseName = SecondPhase[0]
if(FirstPhaseName == "PRE" or FirstPhaseName == "PRE_ALL"):
if (FirstPhaseName == "PRE" or FirstPhaseName == "PRE_ALL"):
return dramconfig.tRP
elif(FirstPhaseName == "ACT"):
elif (FirstPhaseName == "ACT"):
return dramconfig.tRCD
elif(FirstPhaseName == "RD"):
if(SecondPhaseName in ["PRE, PRE_ALL"]):
elif (FirstPhaseName == "RD"):
if (SecondPhaseName in ["PRE, PRE_ALL"]):
return dramconfig.tRTP
elif(SecondPhaseName in ["RD, RDA"]):
elif (SecondPhaseName in ["RD, RDA"]):
return max(dramconfig.tCCD_L, getReadAccessTime())
elif(SecondPhase in ["WR","WRA"]):
return dramconfig.tRL + getReadAccessTime() - dramconfig.tWL + 2*dramconfig.clk
elif(SecondPhase == "PDNA" ):
elif (SecondPhase in ["WR", "WRA"]):
return dramconfig.tRL + getReadAccessTime() - dramconfig.tWL + 2 * dramconfig.clk
elif (SecondPhase == "PDNA"):
return dramconfig.tRL + getReadAccessTime() + dramconfig.clk
elif(FirstPhaseName == "WR"):
if(SecondPhaseName in ["PRE, PRE_ALL", "PDNA"]):
elif (FirstPhaseName == "WR"):
if (SecondPhaseName in ["PRE, PRE_ALL", "PDNA"]):
return dramconfig.tWL + dramconfig.getWriteAccessTime() + dramconfig.tWR
elif(SecondPhaseName in ["RD, RDA"]):
elif (SecondPhaseName in ["RD, RDA"]):
return dramconfig.tWL + dramconfig.getWriteAccessTime() + dramconfig.tWTR_L
elif(SecondPhaseName in ["WR, WRA"]):
elif (SecondPhaseName in ["WR, WRA"]):
return max(dramconfig.tCCD_L, burstlength/dramconfig.dataRate)
elif(FirstPhaseName == "RDA"):
if(SecondPhaseName in ["ACT", "PRE_ALL", "REFA"]):
elif (FirstPhaseName == "RDA"):
if (SecondPhaseName in ["ACT", "PRE_ALL", "REFA"]):
return dramconfig.tRTP + dramconfig.tRP
elif(SecondPhaseName in ["PDNA","PDNP"]):
elif (SecondPhaseName in ["PDNA", "PDNP"]):
return dramconfig.tRL + getReadAccessTime() + dramconfig.clk
elif(FirstPhaseName == "WRA"):
if(SecondPhaseName in ["ACT", "PRE_ALL", "REFA"]):
elif (FirstPhaseName == "WRA"):
if (SecondPhaseName in ["ACT", "PRE_ALL", "REFA"]):
return dramconfig.tWL + getWriteAccessTime() + dramconfig.tWR + dramconfig.tRP
elif(SecondPhaseName in ["PDNA","PDNP"]):
elif (SecondPhaseName in ["PDNA", "PDNP"]):
return dramconfig.tWL + dramconfig.getWriteAccessTime() + dramconfig.tWR + dramconfig.clk
elif(FirstPhaseName == "REFA"):
elif (FirstPhaseName == "REFA"):
return dramconfig.tRFC
elif(FirstPhaseName in ["PDNA","PDNP"]):
elif (FirstPhaseName in ["PDNA", "PDNP"]):
print("{0}".format(FirstPhaseName))
print("{0}".format(formatTime(FirstPhase[3])))
print("{0}".format(formatTime(FirstPhase[2])))
print("{0}".format(formatTime(dramconfig.tXP)))
print("{0}".format(formatTime(dramconfig.clk)))
return (FirstPhase[3] - FirstPhase[2]) + dramconfig.tXP - dramconfig.clk
elif(FirstPhaseName == "SREF"):
elif (FirstPhaseName == "SREF"):
return (FirstPhase[3] - FirstPhase[2]) + dramconfig.tXSR - dramconfig.clk
return 0
@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"""
"""Checks that all transitions of two consecutive phases on the same bank meet their timing constraints"""
cursor = connection.cursor()
validTransitions = {}
query = """SELECT PhaseName, phases.ID,PhaseBegin,PhaseEnd FROM phases INNER JOIN transactions ON phases.transact=transactions.ID WHERE TBank=:bank
query = """SELECT PhaseName, phases.ID, PhaseBegin, PhaseEnd FROM phases INNER JOIN transactions ON phases.transact=transactions.ID WHERE TBank=:bank
AND PhaseName NOT IN ('REQ','RESP') ORDER BY PhaseBegin"""
for bankNumber in range(dramconfig.numberOfBanks):
@@ -356,13 +345,14 @@ def timing_constraits_on_the_same_bank_hold(connection):
lastRow = cursor.fetchone()
for currentRow in cursor:
constraint = timing_constraint(lastRow,currentRow)
if(currentRow[2] - lastRow[2] + constraint < 0):
return TestFailed("Phase {0}({1}) starts {2} after Start of Phase {3}({4}). Minimal time is {5}".format(
currentRow[1],currentRow[0],formatTime(currentRow[2]-lastRow[2]),lastRow[1],lastRow[0], formatTime(constraint)))
constraint = timing_constraint(lastRow, currentRow)
if (currentRow[2] - (lastRow[2] + constraint) < 0):
return TestFailed("Phase {0}({1}) starts {2} after Start of Phase {3}({4}). Minimal time is {5}".format(currentRow[1], currentRow[0], formatTime(currentRow[2] - lastRow[2]), lastRow[1], lastRow[0], formatTime(constraint)))
lastRow = currentRow
return TestSuceeded()
@test
def row_buffer_is_used_correctly(connection):
"""Checks that each bank's row buffer is used correctly"""
@@ -379,39 +369,37 @@ def row_buffer_is_used_correctly(connection):
((TBank=:bank) OR (PhaseNAME = "REFA" AND TBank=0) OR (PhaseNAME = "PRE_ALL" AND TBank=0))
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 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 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', 'REFA', 'SREF'])
# phases that require the bank to be in precharged state and the robuffer to be closed
idlePhases = set(['ACT', 'PDNP', 'REFA', 'SREF'])
for bankNumber in range(dramconfig.numberOfBanks):
cursor.execute(query,{"bank": bankNumber})
cursor.execute(query, {"bank": bankNumber})
rowBufferIsClosed = True
for currentRow in cursor:
if(currentRow[0] in accessingPhases and rowBufferIsClosed == True):
if ((currentRow[0] in accessingPhases) and (rowBufferIsClosed is True)):
return TestFailed("Phase {0}({1}) acesses a closed rowbuffer".format(currentRow[1], currentRow[0]))
if(currentRow[0] in idlePhases and rowBufferIsClosed == False):
if ((currentRow[0] in idlePhases) and (rowBufferIsClosed is False)):
return TestFailed("Phase {0}({1}) needs a closed rowbuffer".format(currentRow[1], currentRow[0]))
if(currentRow[0] == 'ACT'):
if (currentRow[0] == 'ACT'):
rowBufferIsClosed = False
if(currentRow[0] in prechargingPhases):
if (currentRow[0] in prechargingPhases):
rowBufferIsClosed = True
return TestSuceeded()
#----------- activate checks ---------------------------------------
# ----------- activate checks ---------------------------------------
@test
def activate_to_activate_holds(connection):
"""Checks that all activates are far enough apart(JESD229 229, P. 27)"""
@@ -420,14 +408,13 @@ def activate_to_activate_holds(connection):
lastRow = cursor.fetchone()
for currentRow in cursor:
timeBetweenActivates = currentRow[1] - lastRow[1]
timeBetweenActivates = currentRow[1] - lastRow[1]
if (currentRow[2] == lastRow[2]):
minTime = dramconfig.tRRD_L
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), formatTime(minTime)))
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), formatTime(minTime)))
lastRow = currentRow
@@ -441,19 +428,19 @@ def activate_to_activate_on_same_bank_holds(connection):
query = "SELECT Phases.ID,PhaseBegin from Phases INNER JOIN Transactions ON Phases.Transact = Transactions.ID WHERE PhaseName = 'ACT' AND TBANK = :bank ORDER BY PhaseBegin"
for bankNumber in range(dramconfig.numberOfBanks):
cursor.execute(query,{"bank": bankNumber})
cursor.execute(query, {"bank": bankNumber})
lastRow = cursor.fetchone()
for currentRow in cursor:
timeBetweenActivates = currentRow[1] - lastRow[1];
if(timeBetweenActivates < dramconfig.tRC):
return TestFailed("Activates with PhaseIDs {0} and {1} are {2} apart. Minimum time between two activates is {3}, since they are on the same bank({4})".
format(currentRow[0], lastRow[0],formatTime(timeBetweenActivates), dramconfig.tRC))
timeBetweenActivates = currentRow[1] - lastRow[1]
if (timeBetweenActivates < dramconfig.tRC):
return TestFailed("Activates with PhaseIDs {0} and {1} are {2} apart. Minimum time between two activates is {3}, since they are on the same bank({4})".format(currentRow[0], lastRow[0], formatTime(timeBetweenActivates), dramconfig.tRC))
else:
lastRow = currentRow
return TestSuceeded()
@test
def n_activate_window_holds(connection):
"""Checks that the n-Activate constraint is met everywhere(JEDEC 229, P. 27)"""
@@ -463,15 +450,14 @@ def n_activate_window_holds(connection):
for currentRow in cursor:
activateWindow.append(currentRow[1])
if(len(activateWindow) > dramconfig.nActivateWindow + 1):
if (len(activateWindow) > dramconfig.nActivateWindow + 1):
activateWindow.pop(0)
if(activateWindow[dramconfig.nActivateWindow] - activateWindow[0] < dramconfig.tNAW):
return TestFailed("Activate with PhaseID {0} and the {1} preceeding activates violate the '{1} activate window' constraint."
" No more than {1} activates should be in rolling time window of {2}".format(currentRow[0], dramconfig.nActivateWindow,formatTime(dramconfig.tNAW)))
if (activateWindow[dramconfig.nActivateWindow] - activateWindow[0] < dramconfig.tNAW):
return TestFailed("Activate with PhaseID {0} and the {1} preceeding activates violate the '{1} activate window' constraint. No more than {1} activates should be in rolling time window of {2}".format(currentRow[0], dramconfig.nActivateWindow, formatTime(dramconfig.tNAW)))
return TestSuceeded()
# ----------- read/write checks ---------------------------------------
# ----------- read/write checks ---------------------------------------
@test
def read_to_read_holds(connection):
"""Check that the read operations do not intefere with each other on the data bus"""
@@ -480,13 +466,13 @@ def read_to_read_holds(connection):
lastRow = cursor.fetchone()
for currentRow in cursor:
timeBetweenReads = currentRow[1] - lastRow[1]
timeBetweenReads = currentRow[1] - lastRow[1]
if (currentRow[2] == lastRow[2]):
minTime = max(dramconfig.tCCD_L,dramconfig.getReadAccessTime())
minTime = max(dramconfig.tCCD_L, dramconfig.getReadAccessTime())
else:
minTime = max(dramconfig.tCCD_S,dramconfig.getReadAccessTime())
if(timeBetweenReads < minTime):
return TestFailed("Reads with PhaseIDs {0} and {1} are {2} apart. Minimum time between two reads is {3}".format(currentRow[0], lastRow[0],formatTime(timeBetweenReads), minTime))
minTime = max(dramconfig.tCCD_S, dramconfig.getReadAccessTime())
if (timeBetweenReads < minTime):
return TestFailed("Reads with PhaseIDs {0} and {1} are {2} apart. Minimum time between two reads is {3}".format(currentRow[0], lastRow[0], formatTime(timeBetweenReads), minTime))
lastRow = currentRow
return TestSuceeded()
@@ -501,16 +487,17 @@ def write_to_write_holds(connection):
lastRow = cursor.fetchone()
for currentRow in cursor:
timeBetweenWrites = currentRow[1] - lastRow[1]
timeBetweenWrites = currentRow[1] - lastRow[1]
if (currentRow[2] == lastRow[2]):
minTime = max(dramconfig.tCCD_L,dramconfig.getWriteAccessTime())
minTime = max(dramconfig.tCCD_L, dramconfig.getWriteAccessTime())
else:
minTime = max(dramconfig.tCCD_S,dramconfig.getWriteAccessTime())
if(timeBetweenWrites < minTime):
return TestFailed("Writes with PhaseIDs {0} and {1} are {2} apart. Minimum time between two writes is {3}".format(currentRow[0], lastRow[0],formatTime(timeBetweenWrites), minTime))
minTime = max(dramconfig.tCCD_S, dramconfig.getWriteAccessTime())
if (timeBetweenWrites < minTime):
return TestFailed("Writes with PhaseIDs {0} and {1} are {2} apart. Minimum time between two writes is {3}".format(currentRow[0], lastRow[0], formatTime(timeBetweenWrites), minTime))
lastRow = currentRow
return TestSuceeded()
@test
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
@@ -524,9 +511,8 @@ def write_to_read_and_read_to_write_hold(connection):
lastRow = cursor.fetchone()
for currentRow in cursor:
if(currentRow[2] in ["RD","RDA"] and lastRow[2] in ["WR","WRA"]):
#write to read
if (currentRow[2] in ["RD", "RDA"] and lastRow[2] in ["WR", "WRA"]):
# write to read
if (currentRow[3] == lastRow[3]):
tWTR = dramconfig.tWTR_L
else:
@@ -535,22 +521,21 @@ def write_to_read_and_read_to_write_hold(connection):
minWriteToRead = dramconfig.tWL + dramconfig.getWriteAccessTime() + tWTR
writeToRead = currentRow[1] - lastRow[1]
if(writeToRead < minWriteToRead ):
return TestFailed("Read {0} starts {1} after start of write {2}. Minimum time is {3}".
format(currentRow[0],formatTime(writeToRead),lastRow[0], formatTime(minWriteToRead)))
if (writeToRead < minWriteToRead):
return TestFailed("Read {0} starts {1} after start of write {2}. Minimum time is {3}".format(currentRow[0], formatTime(writeToRead), lastRow[0], formatTime(minWriteToRead)))
elif(currentRow[2] in ["WR","WRA"] and lastRow[2] in ["RD","RDA"]):
#read to write
elif (currentRow[2] in ["WR", "WRA"] and lastRow[2] in ["RD", "RDA"]):
# read to write
minReadToWrite = dramconfig.tRL + dramconfig.getReadAccessTime() - dramconfig.tWL + dramconfig.clk * 2
readToWrite = currentRow[1] - lastRow[1]
if(readToWrite < minReadToWrite ):
return TestFailed("Write {0} starts {1} after start of read {2}. Minimum time is {3}".
format(currentRow[0],formatTime(readToWrite),lastRow[0], formatTime(minWriteToRead)))
if (readToWrite < minReadToWrite):
return TestFailed("Write {0} starts {1} after start of read {2}. Minimum time is {3}".format(currentRow[0], formatTime(readToWrite), lastRow[0], formatTime(minWriteToRead)))
lastRow = currentRow
return TestSuceeded()
# TODO: Check if this test still is correct!
@test
def read_holds_dll_constraint_after_sref(connection):
@@ -561,17 +546,17 @@ def read_holds_dll_constraint_after_sref(connection):
WHERE PhaseName IN ('RD', 'RDA', 'SREF') ORDER BY PhaseBegin"""
for bankNumber in range(dramconfig.numberOfBanks):
cursor.execute(query,{"bank": bankNumber})
cursor.execute(query, {"bank": bankNumber})
lastRow = cursor.fetchone()
for currentRow in cursor:
if(currentRow[2] in ["RD","RDA"] and lastRow[2] == 'SREF'):
if (currentRow[2] in ["RD", "RDA"] and lastRow[2] == 'SREF'):
srefEndToRead = currentRow[1] - (lastRow[1] - dramconfig.clk)
if(srefEndToRead < dramconfig.tXSRDLL ):
return TestFailed("Read {0} starts {1} after end of sref {2}. Minimum time is {3}".
format(currentRow[0],formatTime(srefEndToRead),lastRow[0], formatTime(dramconfig.tXSRDLL)))
if (srefEndToRead < dramconfig.tXSRDLL):
return TestFailed("Read {0} starts {1} after end of sref {2}. Minimum time is {3}".format(currentRow[0], formatTime(srefEndToRead), lastRow[0], formatTime(dramconfig.tXSRDLL)))
lastRow = currentRow
return TestSuceeded()
@test
def strict_transaction_order(connection):
"""Checks that all transactions are processed in the right order"""
@@ -584,14 +569,14 @@ def strict_transaction_order(connection):
for currentRow in cursor:
transactions += str(currentRow[0]) + ","
if(transactions != ""):
if(dramconfig.scheduler == "FIFO_STRICT"):
if (transactions != ""):
if (dramconfig.scheduler == "FIFO_STRICT"):
return TestFailed("Transactions {0} is/are not in Order ".format(transactions))
else:
return TestResult(True, "Transactions are not in Order, however this is okay since no FIFO_STRICT was choosen");
return TestResult(True, "Transactions are not in Order, however this is okay since no FIFO_STRICT was choosen")
return TestSuceeded()
# ----------- powerdown checks ---------------------------------------
# ----------- powerdown checks ---------------------------------------
# @test
# def sref_active_for_minimal_time(connection):
@@ -600,7 +585,7 @@ def strict_transaction_order(connection):
# 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):
# 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()
@@ -611,48 +596,47 @@ def strict_transaction_order(connection):
# 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):
# 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 --------------------
def runTests(pathToTrace):
connection = sqlite3.connect(pathToTrace)
dramconfig.readConfigFromFiles(connection)
connection = sqlite3.connect(pathToTrace)
dramconfig.readConfigFromFiles(connection)
testResults = []
numberOfFailedTest = 0
print("================================")
print("RUNNING TEST ON {0}".format(pathToTrace))
testResults = []
numberOfFailedTest = 0
print("================================")
print("RUNNING TEST ON {0}".format(pathToTrace))
print("-----------------------------\n")
print("-----------------------------\n")
for test in tests:
testResult = test(connection)
testName = test.__name__.replace("_"," ")
testResults.append((testName, testResult.passed,testResult.message))
for test in tests:
testResult = test(connection)
testName = test.__name__.replace("_", " ")
testResults.append((testName, testResult.passed, testResult.message))
if (testResult.passed):
print("[passed] {0}".format(testName))
else:
print("[failed] {0} failed. Message: {1}".format(testName, testResult.message))
numberOfFailedTest = numberOfFailedTest + 1
if(testResult.passed):
print("[passed] {0}".format(testName))
else:
print("[failed] {0} failed. Message: {1}".format(testName, testResult.message))
numberOfFailedTest = numberOfFailedTest + 1
print("\n-----------------------------")
print("\n-----------------------------")
if(numberOfFailedTest == 0):
if (numberOfFailedTest == 0):
print("All tests passed")
else:
print("{0} of {1} tests passed".format(len(tests) - numberOfFailedTest,len(tests)))
else:
print("{0} of {1} tests passed".format(len(tests) - numberOfFailedTest, len(tests)))
print("================================")
connection.close()
print("================================")
connection.close()
return testResults
return testResults
if __name__ == "__main__":
sys.stdout = os.fdopen(sys.stdout.fileno(), 'w')
for i in range(1,len(sys.argv)):
for i in range(1, len(sys.argv)):
runTests(sys.argv[i])

View File

@@ -63,9 +63,14 @@ TraceAnalyzer::TraceAnalyzer(QWidget *parent) :
ui(new Ui::TraceAnalyzer)
{
setUpGui();
// Disable actions except for "Open" until some file is open.
ui->actionReload_all->setEnabled(false);
ui->actionSaveChangesToDB->setEnabled(false);
ui->actionClose_all->setEnabled(false);
ui->actionTest->setEnabled(false);
ui->actionMetrics->setEnabled(false);
}
TraceAnalyzer::TraceAnalyzer(QSet<QString> paths, StartupOption option, QWidget *parent):
QMainWindow(parent),
ui(new Ui::TraceAnalyzer)
@@ -104,9 +109,18 @@ void TraceAnalyzer::openTracefile(const QString &path)
return;
TraceFileTab* tab = new TraceFileTab(this, path);
connect(tab, SIGNAL(statusChanged(QString)), this, SLOT(statusChanged(QString)));
connect(tab, SIGNAL(statusChanged(QString, bool)), this, SLOT(statusChanged(QString, bool)));
ui->traceFileTabs->addTab(tab,QFileInfo(path).baseName());
openedTraceFiles.insert(path);
// Enable actions
ui->actionReload_all->setEnabled(true);
ui->actionSaveChangesToDB->setEnabled(true);
ui->actionClose_all->setEnabled(true);
ui->actionTest->setEnabled(true);
ui->actionMetrics->setEnabled(true);
statusLabel->clear();
}
void TraceAnalyzer::on_traceFileTabs_tabCloseRequested(int index)
@@ -121,13 +135,65 @@ void TraceAnalyzer::on_actionClose_all_triggered()
{
while(ui->traceFileTabs->count())
on_traceFileTabs_tabCloseRequested(0);
// All files closed. Disable actions except for "Open".
ui->actionReload_all->setEnabled(false);
ui->actionSaveChangesToDB->setEnabled(false);
ui->actionClose_all->setEnabled(false);
ui->actionTest->setEnabled(false);
ui->actionMetrics->setEnabled(false);
statusLabel->clear();
}
void TraceAnalyzer::statusChanged(QString message)
void TraceAnalyzer::on_actionReload_all_triggered()
{
statusLabel->setText(message + " - (" + QTime::currentTime().toString() + ")");
TraceFileTab *traceFileTab;
// Remove all tabs
int tabIndex = 0;
while (ui->traceFileTabs->count() != 0) {
traceFileTab = static_cast<TraceFileTab*>(ui->traceFileTabs->widget(0));
std::cout << "Closing tab #" << tabIndex << " \"" << traceFileTab->getPathToTraceFile().toStdString() << "\"" << std::endl;
ui->traceFileTabs->removeTab(0);
delete traceFileTab;
tabIndex++;
}
QList<QString> list = openedTraceFiles.toList();
qSort(list);
// Recreate all tabs
tabIndex = 0;
for (auto path : list) {
std::cout << "Reopening tab# " << tabIndex << " \"" << path.toStdString() << "\"" << std::endl;
traceFileTab = new TraceFileTab(this, path);
connect(traceFileTab, SIGNAL(statusChanged(QString, bool)), this, SLOT(statusChanged(QString, bool)));
ui->traceFileTabs->addTab(traceFileTab, QFileInfo(path).baseName());
tabIndex++;
}
this->statusChanged(QString("All databases reloaded "), true);
}
void TraceAnalyzer::on_actionSaveChangesToDB_triggered()
{
for (int index = 0; index < ui->traceFileTabs->count(); index++) {
// Changes in the database files will trigger the file watchers from
// the TraceFileTab class. They generate signals connected to TraceAnalyzer::statusChanged().
TraceFileTab *traceFileTab = static_cast<TraceFileTab *>(ui->traceFileTabs->widget(index));
traceFileTab->commitChangesToDB();
}
}
void TraceAnalyzer::statusChanged(QString message, bool saveChangesEnable)
{
statusLabel->setText(message + QTime::currentTime().toString());
ui->actionSaveChangesToDB->setEnabled(saveChangesEnable);
}
void TraceAnalyzer::on_actionTest_triggered()
@@ -142,5 +208,5 @@ void TraceAnalyzer::on_actionMetrics_triggered()
evaluationTool.raise();
evaluationTool.activateWindow();
evaluationTool.showAndEvaluateMetrics(openedTraceFiles.toList());
}

View File

@@ -73,6 +73,8 @@ private:
private Q_SLOTS:
void on_actionOpen_triggered();
void on_actionReload_all_triggered();
void on_actionSaveChangesToDB_triggered();
void on_traceFileTabs_tabCloseRequested(int index);
void on_actionClose_all_triggered();
void on_actionTest_triggered();
@@ -80,10 +82,11 @@ private Q_SLOTS:
void on_actionMetrics_triggered();
public Q_SLOTS:
void statusChanged(QString message);
void statusChanged(QString message, bool saveChangesEnable = false);
private:
Ui::TraceAnalyzer *ui;
};
#endif // TRACEANALYZER_H

View File

@@ -57,6 +57,8 @@
<string>File</string>
</property>
<addaction name="actionOpen"/>
<addaction name="actionReload_all"/>
<addaction name="actionSaveChangesToDB"/>
<addaction name="actionClose_all"/>
<addaction name="separator"/>
<addaction name="actionTest"/>
@@ -81,10 +83,29 @@
<string>Ctrl+O</string>
</property>
</action>
<action name="actionReload_all">
<property name="text">
<string>Reload databases</string>
</property>
<property name="shortcut">
<string>CTRL+R</string>
</property>
</action>
<action name="actionSaveChangesToDB">
<property name="text">
<string>Save changes to DB</string>
</property>
<property name="shortcut">
<string>CTRL+S</string>
</property>
</action>
<action name="actionClose_all">
<property name="text">
<string>Close all</string>
</property>
<property name="shortcut">
<string>CTRL+Q</string>
</property>
</action>
<action name="actionInfo">
<property name="text">

View File

@@ -41,14 +41,15 @@
#include "QFileInfo"
#include "qmessagebox.h"
#include <iostream>
#include <iostream>
TraceFileTab::TraceFileTab(QWidget *parent,const QString& path) :
QWidget(parent),
ui(new Ui::TraceFileTab)
QWidget(parent), ui(new Ui::TraceFileTab), savingChangesToDB(false)
{
ui->setupUi(this);
this->path = path;
std::cout << "Opening new tab for \"" << path.toStdString() << "\"" << std::endl;
initNavigatorAndItsDependentWidgets(path);
setUpFileWatcher(path);
ui->fileDescriptionEdit->setPlainText(navigator->GeneralTraceInfo().description);
@@ -57,10 +58,15 @@ TraceFileTab::TraceFileTab(QWidget *parent,const QString& path) :
TraceFileTab::~TraceFileTab()
{
navigator->commitChangesToDB();
delete ui;
}
void TraceFileTab::commitChangesToDB()
{
savingChangesToDB = true;
navigator->commitChangesToDB();
}
void TraceFileTab::initNavigatorAndItsDependentWidgets(QString path)
{
navigator = new TraceNavigator(path,this);
@@ -82,15 +88,20 @@ void TraceFileTab::setUpFileWatcher(QString path)
QObject::connect(fileWatcher,SIGNAL(fileChanged(QString)),this,SLOT(tracefileChanged()));
}
void TraceFileTab::tracefileChanged()
{
Q_EMIT statusChanged(QString("Last Database Refresh"));
if (savingChangesToDB == true) {
// Database has changed due to user action (e.g., saving comments).
// No need to disable the "Save changes to DB" menu.
savingChangesToDB = false;
Q_EMIT statusChanged(QString("Changes saved "), true);
} else {
// External event changed the database file (e.g., the database file
// was overwritten when running a new test).
// The "Save changes to DB" menu must be disabled to avoid saving
// changes to a corrupted or inconsistent file.
Q_EMIT statusChanged(QString("At least one database has changed on disk "), false);
}
navigator->refreshData();
}

View File

@@ -60,6 +60,7 @@ public:
void setUpFileWatcher(QString filename);
void initNavigatorAndItsDependentWidgets(QString path);
QString getPathToTraceFile(){return path;}
void commitChangesToDB(void);
private:
QString path;
@@ -67,14 +68,15 @@ private:
TraceNavigator *navigator;
QFileSystemWatcher *fileWatcher;
void setUpQueryEditor(QString path);
bool savingChangesToDB;
public Q_SLOTS:
void tracefileChanged();
Q_SIGNALS:
void statusChanged(QString);
void statusChanged(QString message, bool saveChangesEnable = false);
void colorGroupingChanged(ColorGrouping colorgrouping);
};
#endif // TRACEFILETAB_H

View File

@@ -110,7 +110,7 @@ void Simulation::setupTlmRecorders(const string &traceName, const string &pathTo
void Simulation::instantiateModules(const string &traceName, const string &pathToResources, const std::vector<Device> &devices)
{
// The first call to getInstance() creates the Temperature Controller.
// The same instance will can be accessed by all other modules.
// The same instance will be accessed by all other modules.
TemperatureController::getInstance();
for (size_t i = 0; i < Configuration::getInstance().NumberOfTracePlayers; i++) {

View File

@@ -49,18 +49,21 @@ template<unsigned int BUSWIDTH = 128>
struct StlDataPlayer: public TracePlayer<BUSWIDTH>
{
public:
StlDataPlayer(sc_module_name /*name*/, string pathToTrace, unsigned int clkMhz,
TracePlayerListener* listener);
StlDataPlayer(sc_module_name /*name*/, string pathToTrace, unsigned int clkMhz, TracePlayerListener* listener);
virtual void nextPayload() override
{
string line;
while(line.empty() && file)
{
std::string line;
while (line.empty() && file) {
std::getline(file, line);
// Ignore lines which begin with '#' (commented lines)
if (!line.empty() && line.at(0) == '#') {
line.clear();
}
}
if(!file)
{
if(!file) {
this->terminate();
return;
}
@@ -118,26 +121,19 @@ public:
dataElement[i] = std::stoi(byteString.c_str(), 0, 16);
}
}
}
else
{
SC_REPORT_FATAL(0,
(string("Corrupted tracefile, command ") + command + string(" unknown")).c_str());
} else {
SC_REPORT_FATAL(0, (string("Corrupted tracefile, command ") + command + string(" unknown")).c_str());
}
sc_time sendingTime = std::stoull(time.c_str())*clk;
if (sendingTime <= sc_time_stamp())
{
if (sendingTime <= sc_time_stamp()) {
this->payloadEventQueue.notify(*payload, BEGIN_REQ, SC_ZERO_TIME);
}
else
{
} else {
this->payloadEventQueue.notify(*payload, BEGIN_REQ, sendingTime - sc_time_stamp());
}
}
private:
ifstream file;
unsigned int burstlength;
@@ -164,3 +160,4 @@ StlDataPlayer<BUSWIDTH>::StlDataPlayer(sc_module_name /*name*/, string pathToTra
}
#endif // STLDATAPLAYER_H

View File

@@ -49,23 +49,25 @@ template<unsigned int BUSWIDTH = 128>
struct StlPlayer: public TracePlayer<BUSWIDTH>
{
public:
StlPlayer(sc_module_name /*name*/, string pathToTrace, unsigned int clkMhz,
TracePlayerListener* listener);
StlPlayer(sc_module_name /*name*/, string pathToTrace, unsigned int clkMhz, TracePlayerListener *listener);
virtual void nextPayload() override
{
string line;
while(line.empty() && file)
{
std::string line;
while (line.empty() && file) {
std::getline(file, line);
// Ignore lines which begin with '#' (commented lines)
if (!line.empty() && line.at(0) == '#') {
line.clear();
}
}
if(!file)
{
if(!file) {
this->terminate();
return;
}
std::istringstream iss(line);
string time, command, address;
iss >> time >> command >> address;
@@ -105,26 +107,19 @@ public:
dataElement[i] = std::stoi(byteString.c_str(), 0, 16);
}
}
}
else
{
SC_REPORT_FATAL(0,
(string("Corrupted tracefile, command ") + command + string(" unknown")).c_str());
} else {
SC_REPORT_FATAL(0, (string("Corrupted tracefile, command ") + command + string(" unknown")).c_str());
}
sc_time sendingTime = std::stoull(time.c_str())*clk;
if (sendingTime <= sc_time_stamp())
{
if (sendingTime <= sc_time_stamp()) {
this->payloadEventQueue.notify(*payload, BEGIN_REQ, SC_ZERO_TIME);
}
else
{
} else {
this->payloadEventQueue.notify(*payload, BEGIN_REQ, sendingTime - sc_time_stamp());
}
}
private:
ifstream file;
unsigned int burstlength;
@@ -151,3 +146,4 @@ StlPlayer<BUSWIDTH>::StlPlayer(sc_module_name /*name*/, string pathToTrace, unsi
}
#endif // STLPLAYER_H