Adapt metrics to new DB format.

This commit is contained in:
Lukas Steiner
2022-05-17 11:18:43 +02:00
parent 5237f70439
commit 005ac89cb3
2 changed files with 231 additions and 245 deletions

View File

@@ -140,25 +140,26 @@ def getControllerThread(connection):
def get_phase_occurrences(connection, phase):
cursor = connection.cursor()
query = "select count(*) from Phases where PhaseName = :phase"
query = "SELECT count(*) FROM Phases WHERE PhaseName = :phase"
cursor.execute(query, {"phase": phase})
r = cursor.fetchone()
cnt = r[0]
if (cnt is None):
if cnt is None:
cnt = 0
return cnt
def get_total_time_in_phase(connection, phase):
cursor = connection.cursor()
query = "select sum(PhaseEnd - PhaseBegin) / 1000 from Phases where PhaseName = :phase"
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):
if totalTime is None:
totalTime = 0.0
return totalTime
def getCommandLengthForPhase(connection, phase):
cursor = connection.cursor()
cursor.execute("SELECT " + phase + " FROM CommandLengths")

View File

@@ -21,8 +21,7 @@ def threadMetric(function):
def getThreads(connection):
cthread = getControllerThread(connection)
cursor = connection.cursor()
query = "SELECT DISTINCT(TThread) FROM transactions WHERE TThread != " + str(cthread) + " ORDER BY TThread"
cursor.execute(query)
cursor.execute("SELECT DISTINCT(Thread) FROM Transactions WHERE Thread != " + str(cthread) + " ORDER BY Thread")
result = []
for currentRow in cursor:
result.append(currentRow[0])
@@ -32,10 +31,11 @@ def getThreads(connection):
@metric
def trace_length_in_ns(connection):
cursor = connection.cursor()
cursor.execute(""" SELECT max(PhaseEnd)/1000 FROM PHASES; """)
cursor.execute("SELECT MAX(PhaseEnd) / 1000 FROM Phases")
result = cursor.fetchone()
return result[0]
@metric
def command_bus_utilisation_in_percent(connection):
cursor = connection.cursor()
@@ -75,7 +75,7 @@ def command_bus_utilisation_in_percent(connection):
ON Phases.PhaseName = CommandLengths.Command
""")
util = cursor.fetchone()[0]
if (util is None):
if util is None:
util = 0
clk, _ = getClock(connection)
@@ -83,142 +83,133 @@ def command_bus_utilisation_in_percent(connection):
commandBusOccupied = util * clk / traceEnd * 100
return ": {}".format(commandBusOccupied)
@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.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)
@metric
def average_rd_response_latency_in_ns(connection):
cursor = connection.cursor()
cursor.execute("""
SELECT
AVG(RESP.PHASEBEGIN - REQ.PHASEBEGIN) / 1000
FROM
PHASES REQ,
PHASES RESP
INNER JOIN
Transactions
ON REQ.TRANSACT = Transactions.ID
WHERE
REQ.PHASENAME = 'REQ'
AND RESP.PHASENAME = 'RESP'
AND REQ.TRANSACT = RESP.TRANSACT
AND Transactions.Command = "R"
SELECT AVG(Resp.PhaseBegin - Req.PhaseBegin) / 1000
FROM Phases Req, Phases Resp
INNER JOIN Transactions
ON Req.Transact = Transactions.ID
WHERE Req.PhaseName = 'REQ' AND Resp.PhaseName = 'RESP'
AND Req.Transact = Resp.Transact AND Transactions.Command = 'R'
""")
result = cursor.fetchone()
return round(result[0], 1)
@metric
def average_wr_response_latency_in_ns(connection):
cursor = connection.cursor()
cursor.execute("""
SELECT
AVG(RESP.PHASEBEGIN - REQ.PHASEBEGIN) / 1000
FROM
PHASES REQ,
PHASES RESP
INNER JOIN
Transactions
ON REQ.TRANSACT = Transactions.ID
WHERE
REQ.PHASENAME = 'REQ'
AND RESP.PHASENAME = 'RESP'
AND REQ.TRANSACT = RESP.TRANSACT
AND Transactions.Command = "W"
SELECT AVG(Resp.PhaseBegin - Req.PhaseBegin) / 1000
FROM Phases Req, Phases Resp
INNER JOIN Transactions
ON Req.Transact = Transactions.ID
WHERE Req.PhaseName = 'REQ' AND Resp.PhaseName = 'RESP'
AND Req.Transact = Resp.Transact AND Transactions.Command = 'W'
""")
result = cursor.fetchone()
return round(result[0], 1)
@metric
def max_response_latency_in_ns(connection):
cursor = connection.cursor()
cursor.execute(""" SELECT 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.execute("""
SELECT 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]
@metric
def max_rd_response_latency_in_ns(connection):
cursor = connection.cursor()
cursor.execute("""
SELECT
max(RESP.PHASEBEGIN - REQ.PHASEBEGIN) / 1000
FROM
PHASES REQ,
PHASES RESP
INNER JOIN
Transactions
ON REQ.TRANSACT = Transactions.ID
WHERE
REQ.PHASENAME = 'REQ'
AND RESP.PHASENAME = 'RESP'
AND REQ.TRANSACT = RESP.TRANSACT
AND Transactions.Command = "R"
SELECT MAX(Resp.PhaseBegin - Req.PhaseBegin) / 1000
FROM Phases Req, Phases Resp
INNER JOIN Transactions
ON Req.Transact = Transactions.ID
WHERE Req.PhaseName = 'REQ' AND Resp.PhaseName = 'RESP'
AND Req.Transact = Resp.Transact AND Transactions.Command = 'R'
""")
result = cursor.fetchone()
return round(result[0], 1)
@metric
def max_wr_response_latency_in_ns(connection):
cursor = connection.cursor()
cursor.execute("""
SELECT
max(RESP.PHASEBEGIN - REQ.PHASEBEGIN) / 1000
FROM
PHASES REQ,
PHASES RESP
INNER JOIN
Transactions
ON REQ.TRANSACT = Transactions.ID
WHERE
REQ.PHASENAME = 'REQ'
AND RESP.PHASENAME = 'RESP'
AND REQ.TRANSACT = RESP.TRANSACT
AND Transactions.Command = "W"
SELECT MAX(Resp.PhaseBegin - Req.PhaseBegin) / 1000
FROM Phases Req, Phases Resp
INNER JOIN Transactions
ON Req.Transact = Transactions.ID
WHERE Req.PhaseName = 'REQ' AND Resp.PhaseName = 'RESP'
AND Req.Transact = Resp.Transact AND Transactions.Command = 'W'
""")
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.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]
@metric
def memory_active_in_clks(connection):
cursor = connection.cursor()
cursor.execute("""SELECT sum(DataStrobeEnd - DataStrobeBegin) FROM Transactions""")
cursor.execute("SELECT SUM(DataStrobeEnd - DataStrobeBegin) FROM Phases")
active = cursor.fetchone()[0]
if getPseudoChannelMode(connection):
active /= 2
clk, _ = getClock(connection)
return (active / clk)
return active / clk
@metric
def memory_total_in_clks(connection):
cursor = connection.cursor()
cursor.execute(""" SELECT max(DataStrobeEnd) FROM Transactions """)
cursor.execute("SELECT MAX(DataStrobeEnd) FROM Phases")
total = cursor.fetchone()
clk, _ = getClock(connection)
return (total[0]/clk)
return total[0] / clk
@metric
def memory_idle_in_clks(connection):
# This complex query identifies idle times where the DRAM is not used.
# This complex query identifies idle times when the DRAM is not used.
# The code works also if schedulers are used.
cursor = connection.cursor()
# Create a table with transactions sorted by BeginRequest:
# (RowNum, BeginRequest)
query = """ DROP TABLE IF EXISTS transactionsInRequestOrder; """
query = """DROP TABLE IF EXISTS transactionsInRequestOrder;"""
cursor.execute(query)
query = """
@@ -229,50 +220,50 @@ def memory_idle_in_clks(connection):
FROM
Phases p
WHERE
p.PhaseName = "REQ";
p.PhaseName = 'REQ';
"""
cursor.execute(query)
# Create a table with transactions sorted by BeginResponse:
# (RowNum, ID, EndResponse)
query = """ DROP TABLE IF EXISTS transactionsInResponseOrder; """
query = """DROP TABLE IF EXISTS transactionsInResponseOrder;"""
cursor.execute(query)
query = """
CREATE TEMPORARY TABLE transactionsInResponseOrder AS
SELECT
ROW_NUMBER () OVER (ORDER BY q.PhaseBegin) RowNum,
q.Transact AS ID,
q.PhaseEnd AS EndResponse
q.PhaseEnd AS EndResponse
FROM
Phases q
WHERE
q.PhaseName = "RESP";
q.PhaseName = 'RESP';
"""
cursor.execute(query)
# Sum up the idle times:
query = """
SELECT
sum(c.BeginRequest - b.EndResponse) AS idle
SUM(c.BeginRequest - b.EndResponse) AS idle
FROM
transactionsInRequestOrder AS a, transactionsInResponseOrder AS b, transactionsInRequestOrder AS c
WHERE
a.RowNum=b.RowNum AND
c.RowNum=(a.RowNum+1) AND
c.BeginRequest>b.EndResponse;
a.RowNum = b.RowNum AND
c.RowNum = (a.RowNum + 1) AND
c.BeginRequest > b.EndResponse;
"""
cursor.execute(query)
idle = cursor.fetchone()
cursor.execute(""" SELECT min(PhaseBegin) FROM Phases WHERE PhaseName = 'REQ' """)
cursor.execute("""SELECT MIN(PhaseBegin) FROM Phases WHERE PhaseName = 'REQ'""")
idle_start = cursor.fetchone()
clk, unit = getClock(connection)
if (idle[0] is None):
return (idle_start[0] / clk)
if idle[0] is None:
return idle_start[0] / clk
else:
return ((idle[0] + idle_start[0]) / clk)
return (idle[0] + idle_start[0]) / clk
@metric
def memory_delayed_in_clks(connection):
@@ -281,71 +272,69 @@ def memory_delayed_in_clks(connection):
idle = memory_idle_in_clks(connection)
return total - active - idle
@metric
def delayed_reasons(connection):
cursor = connection.cursor()
# Create a table with sorted Datastrobes:
# Create a table with sorted data strobes:
# (RowNum, ID, Begin, End)
query = """ DROP TABLE IF EXISTS dataStrobesInOrder; """
cursor.execute(query)
cursor.execute("DROP TABLE IF EXISTS dataStrobesInOrder;")
query = """
cursor.execute("""
CREATE TEMPORARY TABLE dataStrobesInOrder AS
SELECT
ROW_NUMBER () OVER (ORDER BY t.DataStrobeBegin) RowNum,
t.ID as ID,
t.DataStrobeBegin as Begin,
t.DataStrobeEnd as End,
t.TRow as Row,
t.TBank as Bank,
t.Command as Command
ROW_NUMBER () OVER (ORDER BY DataStrobeBegin) RowNum,
Transact AS ID,
DataStrobeBegin AS Begin,
DataStrobeEnd AS End,
Row,
Bank,
PhaseName AS Command
FROM
Transactions t
Phases
WHERE
t.DataStrobeBegin <> 0 AND
t.DataStrobeEnd <> 0;
"""
cursor.execute(query)
DataStrobeBegin <> 0 AND
DataStrobeEnd <> 0;
""")
# Create a table with transactions sorted by BeginRequest:
# (RowNum, BeginRequest)
query = """ DROP TABLE IF EXISTS transactionsInRequestOrder; """
cursor.execute(query)
cursor.execute("""DROP TABLE IF EXISTS transactionsInRequestOrder;""")
query = """
CREATE TEMPORARY TABLE transactionsInRequestOrder AS
SELECT
ROW_NUMBER () OVER (ORDER BY p.PhaseBegin) RowNum,
p.PhaseBegin AS BeginRequest
ROW_NUMBER () OVER (ORDER BY PhaseBegin) RowNum,
PhaseBegin AS BeginRequest
FROM
Phases p
Phases
WHERE
p.PhaseName = "REQ";
PhaseName = 'REQ';
"""
cursor.execute(query)
# Create a table with transactions sorted by BeginResponse:
# (RowNum, ID, EndResponse)
query = """ DROP TABLE IF EXISTS transactionsInResponseOrder; """
query = """DROP TABLE IF EXISTS transactionsInResponseOrder;"""
cursor.execute(query)
query = """
CREATE TEMPORARY TABLE transactionsInResponseOrder AS
SELECT
ROW_NUMBER () OVER (ORDER BY q.PhaseBegin) RowNum,
q.Transact AS ID,
q.PhaseEnd AS EndResponse
ROW_NUMBER () OVER (ORDER BY PhaseBegin) RowNum,
Transact AS ID,
PhaseEnd AS EndResponse
FROM
Phases q
Phases
WHERE
q.PhaseName = "RESP";
PhaseName = 'RESP';
"""
cursor.execute(query)
# Create a table with transaction IDs that start a idle time:
# Create a table with transaction IDs that start an idle time:
# (ID)
query = """ DROP TABLE IF EXISTS idleGaps; """
query = """DROP TABLE IF EXISTS idleGaps;"""
cursor.execute(query)
query = """
@@ -355,15 +344,15 @@ def delayed_reasons(connection):
FROM
transactionsInRequestOrder AS a, transactionsInResponseOrder AS b, transactionsInRequestOrder AS c
WHERE
a.RowNum=b.RowNum AND
c.RowNum=(a.RowNum+1) AND
c.BeginRequest>b.EndResponse;
a.RowNum = b.RowNum AND
c.RowNum = (a.RowNum + 1) AND
c.BeginRequest > b.EndResponse;
"""
cursor.execute(query)
# Create a table which features IDs that form gaps on the databus:
# Create a table which features IDs that form gaps on the data bus:
# (gapBeginID, gapEndID)
query = """ DROP TABLE IF EXISTS delayedDataBusGaps; """
query = """DROP TABLE IF EXISTS delayedDataBusGaps;"""
cursor.execute(query)
query = """
@@ -377,9 +366,9 @@ def delayed_reasons(connection):
dataStrobesInOrder a,
dataStrobesInOrder b
WHERE
(a.RowNum) = (b.RowNum-1) AND
a.RowNum = b.RowNum - 1 AND
b.Begin > a.End AND
a.ID not in (SELECT ID FROM idleGaps);
a.ID NOT IN (SELECT ID FROM idleGaps);
"""
cursor.execute(query)
@@ -389,8 +378,8 @@ def delayed_reasons(connection):
COUNT(*)
FROM delayedDataBusGaps
WHERE
gapBeginCommand = "R" AND
gapEndCommand = "W";
(gapBeginCommand = 'RD' OR gapBeginCommand = 'RDA') AND
(gapEndCommand = 'WR' OR gapEndCommand = 'WRA');
"""
cursor.execute(query)
RW = cursor.fetchone()[0]
@@ -402,8 +391,8 @@ def delayed_reasons(connection):
FROM
delayedDataBusGaps
WHERE
gapBeginCommand = "W" AND
gapEndCommand = "R";
(gapBeginCommand = 'WR' OR gapBeginCommand = 'WRA') AND
(gapEndCommand = 'RD' OR gapEndCommand = 'RDA');
"""
cursor.execute(query)
WR = cursor.fetchone()[0]
@@ -417,10 +406,10 @@ def delayed_reasons(connection):
FROM
delayedDataBusGaps d, Phases p
WHERE
d.gapBeginCommand = "R" AND
d.gapEndCommand = "R" AND
(d.gapBeginCommand = 'RD' OR d.gapBeginCommand = 'RDA') AND
(d.gapEndCommand = 'RD' OR d.gapEndCommand = 'RDA') AND
p.Transact = d.gapEndID AND
p.PhaseName = "ACT"
p.PhaseName = 'ACT'
GROUP BY
d.gapBeginID
)
@@ -437,10 +426,10 @@ def delayed_reasons(connection):
FROM
delayedDataBusGaps d, Phases p
WHERE
d.gapBeginCommand = "W" AND
d.gapEndCommand = "W" AND
(d.gapBeginCommand = 'WR' OR d.gapBeginCommand = 'WRA') AND
(d.gapEndCommand = 'WR' OR d.gapEndCommand = 'WRA') AND
p.Transact = d.gapEndID AND
p.PhaseName = "ACT"
p.PhaseName = 'ACT'
GROUP BY
d.gapBeginID
)
@@ -468,27 +457,33 @@ def delayed_reasons(connection):
result = "RW: {}, WR: {}, RRM: {}, WWM: {}, Other: {}".format(RW, WR, RRM, WWM, other)
return result
@metric
def memory_idle_in_percent(connection):
total = memory_total_in_clks(connection)
idle = memory_idle_in_clks(connection)
return (idle/total)*100
@metric
def memory_active_in_percent(connection):
total = memory_total_in_clks(connection)
active = memory_active_in_clks(connection)
return (active/total)*100
@metric
def memory_delayed_in_percent(connection):
total = memory_total_in_clks(connection)
delayed = memory_delayed_in_clks(connection)
return (delayed/total)*100
@metric
def memory_idle_active_delayed_check(connection):
return memory_idle_in_percent(connection) + memory_active_in_percent(connection) + memory_delayed_in_percent(connection)
return memory_idle_in_percent(connection) + memory_active_in_percent(connection) \
+ memory_delayed_in_percent(connection)
@metric
def memory_utilisation_percent_without_idle(connection):
@@ -497,72 +492,77 @@ def memory_utilisation_percent_without_idle(connection):
idle = memory_idle_in_clks(connection)
return (active/(total-idle))*100
@metric
def memory_utilisation_in_Gibps_without_idle(connection):
# This function calculates the memory utilisation in Gibit/s considering the memory_utilisation_percent_new function result.
# This function calculates the memory utilisation in Gibit/s considering
# the memory_utilisation_percent_new function result.
maxDataRate = maximum_data_rate(connection)
memoryPercent = memory_utilisation_percent_without_idle(connection)
return (memoryPercent/100)*(maxDataRate/1024)
@metric
def memory_utilisation_percent_including_idle(connection):
cursor = connection.cursor()
cursor.execute(""" SELECT sum(DataStrobeEnd - DataStrobeBegin) FROM transactions """)
cursor.execute("""SELECT SUM(DataStrobeEnd - DataStrobeBegin) FROM Phases""")
active = cursor.fetchone()
cursor = connection.cursor()
cursor.execute(""" SELECT max(DataStrobeEnd) FROM Transactions """)
cursor.execute("""SELECT MAX(DataStrobeEnd) FROM Phases""")
total = cursor.fetchone()
return (active[0]/total[0])*100
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 IN ('REFAB')' """)
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) """
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})
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]))
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))
# 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 IN ('REFAB')' """)
# 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) """
#
# missDecisions = 0
# totalDecisions = 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})
#
# earliestReq = cursorMinREQ.fetchone()
# earliestResp = cursorMinRESP.fetchone()
# if earliestReq[0] is not None:
# totalDecisions = totalDecisions + 1
# if earliestReq[0] != earliestResp[0]:
# missDecisions = missDecisions + 1
# # print("earliest Req: {0}| earliest Res: {1}".format(earliestReq[0], earliestResp[0]))
#
# if totalDecisions != 0:
# # calculatedMetrics.append(("Total Missdecisions", missDecisions))
# calculatedMetrics.append(("Relative Missdecisions", 1.0*missDecisions/totalDecisions))
# 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 """
query = """SELECT AVG(Resp.PhaseBegin - Req.PhaseBegin) / 1000 FROM Phases Req, Phases Resp INNER JOIN Transactions
ON Req.Transact = Transactions.ID WHERE Req.Transact = Resp.Transact AND Req.PhaseName = 'REQ'
AND Resp.PhaseName = 'RESP' AND Thread = :thread"""
cursor.execute(query, {"Thread": thread})
result = cursor.fetchone()
@@ -572,7 +572,7 @@ def average_response_latency_in_ns(connection, thread):
def addStallTime(times, begin, end):
time = begin
while time <= end:
if(time in times):
if time in times:
times[time] = times[time] + 1
else:
times[time] = 1
@@ -580,12 +580,12 @@ def addStallTime(times, begin, end):
# @threadMetric
def paralellism(connection, thread):
def parallelism(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 """
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 Thread = :thread GROUP BY Transactions.ID """
clk, unit = getClock(connection)
cursor.execute(query, {"Thread": thread, "clk": clk})
@@ -600,7 +600,9 @@ def paralellism(connection, thread):
@threadMetric
def thread_conclusion_in_ns(connection, thread):
cursor = connection.cursor()
query = """ SELECT max(PhaseEnd)/1000 FROM Phases INNER JOIN Transactions on Phases.transact=Transactions.id WHERE TThread = :Thread """
query = """
SELECT max(PhaseEnd) / 1000 FROM Phases INNER JOIN Transactions
ON Phases.Transact = Transactions.ID WHERE Thread = :thread """
cursor.execute(query, {"Thread": thread})
result = cursor.fetchone()
return result[0]
@@ -738,98 +740,81 @@ def SREFB_count(connection):
@metric
def number_of_accesses(connection):
return REQ_count(connection)
return RD_count(connection) + RDA_count(connection) + WR_count(connection) + WRA_count(connection)
@metric
def accesses_per_activate(connection):
return round(float(REQ_count(connection)) / ACT_count(connection), 1)
return round(float(number_of_accesses(connection)) / ACT_count(connection), 1)
@metric
def bank_overlap_ratio(connection):
# Calculates how many banks are open in parallel
clk, unit = getClock(connection)
numberOfRanks = getNumberOfRanks(connection)
numberOfBankGroups = getNumberOfBankGroups(connection)
numberOfBanks = getNumberOfBanks(connection)
per2BankOffset = getPer2BankOffset(connection)
banksPerRank = int(numberOfBanks / numberOfRanks)
banksPerGroup = int(numberOfBanks / numberOfBankGroups)
cursor = connection.cursor()
cursor.execute("select TraceEnd from GeneralInfo")
cursor.execute("SELECT TraceEnd FROM GeneralInfo")
traceEndTMP = cursor.fetchone()
traceEnd = int(traceEndTMP[0]/clk)
traceEnd = int(traceEndTMP[0] / clk)
trace = []
cursor.execute("""
select p1.PhaseBegin, p1.PhaseName from Phases p1
where
(p1.PhaseName = "ACT" or p1.PhaseName = "PREPB" or p1.PhaseName = "PRE" or p1.PhaseName = "PRESB"
or p1.PhaseName = "PREAB" or p1.PhaseName = "PREA" or p1.PhaseName = "RDA" or p1.PhaseName = "WRA")
order by PhaseBegin
SELECT PhaseBegin, PhaseName, Rank, BankGroup, Bank
FROM Phases
WHERE (PhaseName = 'ACT' OR PhaseName = 'PREPB' OR PhaseName = 'PREP2B' OR PhaseName = 'PRESB'
OR PhaseName = 'PREAB' OR PhaseName = 'RDA' OR PhaseName = 'WRA')
ORDER BY PhaseBegin
""")
prevPhase = "PREAB"
prevTime = 0
# prevPhase = "PREAB"
# prevTime = 0
# clk of command, name, rank, bank group, bank
for c in cursor:
trace.append([(int(c[0]/clk)), c[1]])
trace.append([(int(c[0] / clk)), c[1], c[2], c[3], c[4]])
# Insert a pseudo precharge all to mark the end of the trace
trace.append([traceEnd, "PREAB"])
# Insert a pseudo precharge all to mark the end of the trace on all ranks
for i in range(numberOfRanks):
trace.append([traceEnd, "PREAB", i, 0, 0])
bankCounter = 0
bankTime = []
for i in range(0, getNumberOfBanks(connection)+1):
bankTime.append(0)
bankCounter = [False] * numberOfBanks
# + 1 because we have #banks + 1 active states (0 to all banks active)
bankTime = [0.0] * (numberOfBanks + 1)
currentTime = 0
validBankRange = range(0, getNumberOfBanks(connection) + 1)
# RGR uses ACTB and PREB for refresh
actbCnt = 0
for t in trace:
interval = t[0] - currentTime
bankTime[bankCounter] += interval
bankTime[sum(bankCounter)] += interval
currentTime = t[0]
if(t[1] == "ACT"):
bankCounter += 1
if not (bankCounter in validBankRange):
print("Unexpected ACT. bankCounter was {0} valid range is python range {1}".format(bankCounter, validBankRange))
elif t[1] == "ACTB":
actbCnt += 1
elif(t[1] == "PREAB" or t[1] == "PREA"):
bankCounter = 0
elif(t[1] == "PREPB" or t[1] == "PRE"):
if (bankCounter > 0):
bankCounter -= 1
else:
print("Unexpected PREPB. bankCounter was {0} valid range is python range {1}".format(bankCounter, validBankRange))
elif(t[1] == "PREB"):
# RGR first PREB closes the row ACT follows, then PREB again.
if actbCnt > 0:
# Ignore the second PREB
actbCnt -= 1
else:
# Treat the first PREB which closes the row
if bankCounter > 0:
bankCounter -= 1
else:
print("Unexpected PREB. bankCounter was {0} valid range is python range {1}".format(bankCounter, validBankRange))
elif(t[1] == "WRA"):
if (bankCounter > 0):
bankCounter -= 1
else:
print("Unexpected WRA. bankCounter was {0} valid range is python range {1}".format(bankCounter, validBankRange))
elif(t[1] == "RDA"):
if (bankCounter > 0):
bankCounter -= 1
else:
print("Unexpected RDA. bankCounter was {0} valid range is python range {1}".format(bankCounter, validBankRange))
if t[1] == "ACT":
bankCounter[t[4]] = True
elif t[1] in ["PREPB", "RDA", "WRA"]:
bankCounter[t[4]] = False
elif t[1] == "PREP2B":
bankCounter[t[4]] = False
bankCounter[t[4] + per2BankOffset] = False
elif t[1] == "PRESB":
for i in range(t[4], t[4] + banksPerRank, banksPerGroup):
bankCounter[i] = False
elif t[1] == "PREAB":
for i in range(t[2] * banksPerRank, (t[2] + 1) * banksPerRank):
bankCounter[i] = False
else:
print("ERROR")
return 0
for i in range(0, getNumberOfBanks(connection)+1):
bankTime[i] = round(bankTime[i]/traceEnd * 100, 2)
for i in range(numberOfBanks + 1):
bankTime[i] = round(bankTime[i] / traceEnd * 100, 2)
return ",".join(format(x, "6.2f") for x in bankTime)