From 005ac89cb3c811846f430ded3982a067557267b9 Mon Sep 17 00:00:00 2001 From: Lukas Steiner Date: Tue, 17 May 2022 11:18:43 +0200 Subject: [PATCH] Adapt metrics to new DB format. --- DRAMSys/traceAnalyzer/scripts/memUtil.py | 9 +- DRAMSys/traceAnalyzer/scripts/metrics.py | 467 +++++++++++------------ 2 files changed, 231 insertions(+), 245 deletions(-) diff --git a/DRAMSys/traceAnalyzer/scripts/memUtil.py b/DRAMSys/traceAnalyzer/scripts/memUtil.py index 774006ba..e6444a11 100755 --- a/DRAMSys/traceAnalyzer/scripts/memUtil.py +++ b/DRAMSys/traceAnalyzer/scripts/memUtil.py @@ -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") diff --git a/DRAMSys/traceAnalyzer/scripts/metrics.py b/DRAMSys/traceAnalyzer/scripts/metrics.py index 6bf5529b..98e2445f 100644 --- a/DRAMSys/traceAnalyzer/scripts/metrics.py +++ b/DRAMSys/traceAnalyzer/scripts/metrics.py @@ -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)