diff --git a/DRAMSys/traceAnalyzer/scripts/metrics.py b/DRAMSys/traceAnalyzer/scripts/metrics.py index 2b7302f9..7c76fad7 100644 --- a/DRAMSys/traceAnalyzer/scripts/metrics.py +++ b/DRAMSys/traceAnalyzer/scripts/metrics.py @@ -59,7 +59,6 @@ def trans_with_max_response_latency(connection): result = cursor.fetchone() return result[0] - @metric def memory_active(connection): cursor = connection.cursor() @@ -68,7 +67,6 @@ def memory_active(connection): clk, unit = getClock(connection) return (active[0]/clk) - @metric def memory_total(connection): cursor = connection.cursor() @@ -109,7 +107,6 @@ def memory_idle(connection): cursor.execute(query) query = """ - SELECT sum(b.BeginRequest - a.EndResponse) AS idle FROM @@ -134,6 +131,155 @@ def memory_delayed(connection): idle = memory_idle(connection) return total - active - idle +def check_miss(connection, ID): + cursor = connection.cursor() + query = """SELECT * FROM phases WHERE PhaseName == "ACT" AND Transact = {};""".format(ID) + cursor.execute(query) + result = cursor.fetchone() + if(result != None) : + return True + else: + return False + +def check(connection, gapBegin, gapEnd, b, e): + cursor = connection.cursor() + query = """SELECT Command FROM Transactions WHERE ID = {};""".format(gapBegin) + cursor.execute(query) + begin = cursor.fetchone()[0] + query = """SELECT Command FROM Transactions WHERE ID = {};""".format(gapEnd) + cursor.execute(query) + end = cursor.fetchone()[0] + return (begin == b and end == e) + +@metric +def delayed_reasons(connection): + cursor = connection.cursor() + + # Create a table with sorted Datastrobes: + # (RowNum, ID, Begin, End) + query = """ DROP TABLE IF EXISTS dataStrobesInOrder; """ + cursor.execute(query) + + query = """ + 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 + + FROM + Transactions t + WHERE + t.DataStrobeBegin <> 0 AND + t.DataStrobeEnd <> 0; + """ + cursor.execute(query) + + # Create a table with phases sorted by BeginResponse: + # (RowNum, BeginRequest, EndRequest, BeginResponse, EndResponse, ID) + query = """ DROP TABLE IF EXISTS phasesInOrder; """ + cursor.execute(query) + + query = """ + CREATE TEMPORARY TABLE phasesInOrder AS + SELECT + ROW_NUMBER () OVER (ORDER BY q.PhaseBegin) RowNum, + p.PhaseBegin AS BeginRequest, + p.PhaseEnd AS EndRequest, + q.PhaseBegin AS BeginResponse, + q.PhaseEnd AS EndResponse, + p.Transact AS ID + FROM + Phases p, + Phases q + WHERE + p.PhaseName = "REQ" + AND q.PhaseName = "RESP" + AND p.Transact = q.Transact; + """ + cursor.execute(query) + + # Create a table with transaction IDs that start a idle time: + # (ID) + query = """ DROP TABLE IF EXISTS idleGaps; """ + cursor.execute(query) + + query = """ + CREATE TEMPORARY TABLE idleGaps AS + SELECT a.ID AS ID + FROM phasesInOrder AS a, phasesInOrder AS b + WHERE + (a.RowNum)=(b.RowNum-1) AND + b.BeginRequest > a.EndResponse; + """ + cursor.execute(query) + + # Create a table which features IDs that form gaps on the databus: + # (gapBeginID, gapEndID) + query = """ DROP TABLE IF EXISTS delayedDataBusGaps; """ + cursor.execute(query) + + query = """ + CREATE TEMPORARY TABLE delayedDataBusGaps AS + SELECT a.ID AS gapBeginID, b.ID AS gapEndID + FROM + dataStrobesInOrder a, + dataStrobesInOrder b + + WHERE + (a.RowNum) = (b.RowNum-1) AND + b.Begin > a.End AND + a.ID not in (SELECT ID FROM idleGaps); + """ + cursor.execute(query) + + query = """ SELECT * FROM delayedDataBusGaps; """; + cursor.execute(query) + + records = cursor.fetchall() + + RR_Miss = 0 + WW_Miss = 0 + RW_Hit = 0 + RW_Miss = 0 + WR_Hit = 0 + WR_Miss = 0 + e = 0 + result = "" + + for row in records: + gapBegin = row[0] + gapEnd = row[1] + + if (check(connection, gapBegin, gapEnd, "R", "R") and check_miss(connection, gapEnd)): + RR_Miss += 1 + elif(check(connection, gapBegin, gapEnd, "W", "W") and check_miss(connection, gapEnd)): + WW_Miss += 1 + elif(check(connection, gapBegin, gapEnd, "R", "W") and (not check_miss(connection, gapEnd))): + RW_Hit += 1 + elif(check(connection, gapBegin, gapEnd, "R", "W") and check_miss(connection, gapEnd)): + RW_Miss += 1 + elif(check(connection, gapBegin, gapEnd, "W", "R") and (not check_miss(connection, gapEnd))): + WR_Hit += 1 + elif(check(connection, gapBegin, gapEnd, "W", "R") and check_miss(connection, gapEnd)): + WR_Miss += 1 + else: + print ("ERROR: This should not happen") + exit(-1) + + total = RR_Miss + WW_Miss + RW_Hit + RW_Miss + WR_Hit + WR_Miss + + RR_Miss /= total + WW_Miss /= total + RW_Hit /= total + RW_Miss /= total + WR_Hit /= total + WR_Miss /= total + + result = "RRM: {}, WWM: {}, RWH: {}, RWM: {}, WRH: {}, WRM: {}".format(RR_Miss, WW_Miss, RW_Hit, RW_Miss, WR_Hit, WR_Miss); + return result + @metric def memory_idle_in_percent(connection): total = memory_total(connection)