diff --git a/DRAMSys/library/src/common/TlmRecorder.cpp b/DRAMSys/library/src/common/TlmRecorder.cpp index 81b2f1d3..48c4171f 100644 --- a/DRAMSys/library/src/common/TlmRecorder.cpp +++ b/DRAMSys/library/src/common/TlmRecorder.cpp @@ -139,6 +139,7 @@ void TlmRecorder::recordPhase(tlm_generic_payload& trans, const tlm_phase& phase { // BEGIN_RESP is always the last phase of a normal transaction at this point currentTransactionsInSystem.at(&trans).recordedPhases.back().interval.end = currentTime + delay; + removeTransactionFromSystem(trans); } else if (isFixedCommandPhase(phase)) { @@ -169,9 +170,13 @@ void TlmRecorder::recordPhase(tlm_generic_payload& trans, const tlm_phase& phase currentTime + delay + memSpec.getExecutionTime(Command(phase), trans))), std::move(intervalOnDataStrobe), extension.getRank(), extension.getBankGroup(), extension.getBank(), extension.getRow(), extension.getColumn(), extension.getBurstLength()); + + if (isRefreshCommandPhase(phase)) + removeTransactionFromSystem(trans); } else if (isPowerDownEntryPhase(phase)) { + introduceTransactionToSystem(trans); std::string phaseName = getPhaseName(phase).substr(6); // remove "BEGIN_" const ControllerExtension& extension = ControllerExtension::getExtension(trans); currentTransactionsInSystem.at(&trans).recordedPhases.emplace_back(std::move(phaseName), @@ -184,10 +189,8 @@ void TlmRecorder::recordPhase(tlm_generic_payload& trans, const tlm_phase& phase { currentTransactionsInSystem.at(&trans).recordedPhases.back().interval.end = currentTime + delay + memSpec.getCommandLength(Command(phase)); - } - - if (phase == END_RESP || isRefreshCommandPhase(phase) || isPowerDownExitPhase(phase)) removeTransactionFromSystem(trans); + } simulationTimeCoveredByRecording = currentTime + delay; } diff --git a/DRAMSys/traceAnalyzer/businessObjects/phases/phase.h b/DRAMSys/traceAnalyzer/businessObjects/phases/phase.h index e6fab72a..433c8cb5 100644 --- a/DRAMSys/traceAnalyzer/businessObjects/phases/phase.h +++ b/DRAMSys/traceAnalyzer/businessObjects/phases/phase.h @@ -768,6 +768,10 @@ protected: { return Granularity::Rankwise; } + RelevantAttributes getRelevantAttributes() const override + { + return RelevantAttributes::Rank; + } }; class SREFB : public Phase @@ -819,6 +823,10 @@ protected: { return Granularity::Rankwise; } + RelevantAttributes getRelevantAttributes() const override + { + return RelevantAttributes::Rank; + } }; #endif // BANKPHASE_H diff --git a/DRAMSys/traceAnalyzer/scripts/metrics.py b/DRAMSys/traceAnalyzer/scripts/metrics.py index 98e2445f..d712e385 100644 --- a/DRAMSys/traceAnalyzer/scripts/metrics.py +++ b/DRAMSys/traceAnalyzer/scripts/metrics.py @@ -50,7 +50,7 @@ def command_bus_utilisation_in_percent(connection): rowBusUtil = cursor.fetchone()[0] if rowBusUtil is None: rowBusUtil = 0 - + cursor.execute(""" SELECT SUM(CommandLengths.Length) FROM Phases @@ -61,13 +61,13 @@ def command_bus_utilisation_in_percent(connection): columnBusUtil = cursor.fetchone()[0] if columnBusUtil is None: columnBusUtil = 0 - + clk, _ = getClock(connection) traceEnd = getTraceEndTime(connection) rowBusOccupied = rowBusUtil * clk / traceEnd * 100 columnBusOccupied = columnBusUtil * clk / traceEnd * 100 return "row commands: {}, column commands: {}".format(rowBusOccupied, columnBusOccupied) - else: + else: cursor.execute(""" SELECT SUM(CommandLengths.Length) FROM Phases @@ -204,14 +204,14 @@ def memory_total_in_clks(connection): def memory_idle_in_clks(connection): # 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;""" cursor.execute(query) - + query = """ CREATE TEMPORARY TABLE transactionsInRequestOrder AS SELECT @@ -223,12 +223,12 @@ def memory_idle_in_clks(connection): p.PhaseName = 'REQ'; """ cursor.execute(query) - + # Create a table with transactions sorted by BeginResponse: # (RowNum, ID, EndResponse) query = """DROP TABLE IF EXISTS transactionsInResponseOrder;""" cursor.execute(query) - + query = """ CREATE TEMPORARY TABLE transactionsInResponseOrder AS SELECT @@ -240,7 +240,7 @@ def memory_idle_in_clks(connection): q.PhaseName = 'RESP'; """ cursor.execute(query) - + # Sum up the idle times: query = """ SELECT @@ -252,9 +252,9 @@ def memory_idle_in_clks(connection): c.RowNum = (a.RowNum + 1) AND c.BeginRequest > b.EndResponse; """ - cursor.execute(query) + cursor.execute(query) idle = cursor.fetchone() - + cursor.execute("""SELECT MIN(PhaseBegin) FROM Phases WHERE PhaseName = 'REQ'""") idle_start = cursor.fetchone() clk, unit = getClock(connection) @@ -265,7 +265,7 @@ def memory_idle_in_clks(connection): return (idle[0] + idle_start[0]) / clk -@metric +@metric def memory_delayed_in_clks(connection): total = memory_total_in_clks(connection) active = memory_active_in_clks(connection) @@ -297,11 +297,11 @@ def delayed_reasons(connection): DataStrobeBegin <> 0 AND DataStrobeEnd <> 0; """) - + # Create a table with transactions sorted by BeginRequest: # (RowNum, BeginRequest) cursor.execute("""DROP TABLE IF EXISTS transactionsInRequestOrder;""") - + query = """ CREATE TEMPORARY TABLE transactionsInRequestOrder AS SELECT @@ -313,12 +313,12 @@ def delayed_reasons(connection): PhaseName = 'REQ'; """ cursor.execute(query) - + # Create a table with transactions sorted by BeginResponse: # (RowNum, ID, EndResponse) query = """DROP TABLE IF EXISTS transactionsInResponseOrder;""" cursor.execute(query) - + query = """ CREATE TEMPORARY TABLE transactionsInResponseOrder AS SELECT @@ -331,7 +331,7 @@ def delayed_reasons(connection): PhaseName = 'RESP'; """ cursor.execute(query) - + # Create a table with transaction IDs that start an idle time: # (ID) query = """DROP TABLE IF EXISTS idleGaps;""" @@ -354,7 +354,7 @@ def delayed_reasons(connection): # (gapBeginID, gapEndID) query = """DROP TABLE IF EXISTS delayedDataBusGaps;""" cursor.execute(query) - + query = """ CREATE TEMPORARY TABLE delayedDataBusGaps AS SELECT @@ -445,13 +445,13 @@ def delayed_reasons(connection): """ cursor.execute(query) total = cursor.fetchone()[0] - + other = total - RW - WR - RRM - WWM - RW /= total / 100.0 - WR /= total / 100.0 - RRM /= total / 100.0 - WWM /= total / 100.0 + RW /= total / 100.0 + WR /= total / 100.0 + RRM /= total / 100.0 + WWM /= total / 100.0 other /= total / 100.0 result = "RW: {}, WR: {}, RRM: {}, WWM: {}, Other: {}".format(RW, WR, RRM, WWM, other) @@ -462,21 +462,21 @@ def delayed_reasons(connection): def memory_idle_in_percent(connection): total = memory_total_in_clks(connection) idle = memory_idle_in_clks(connection) - return (idle/total)*100 + 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 + 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 + return (delayed / total) * 100 @metric @@ -490,7 +490,7 @@ def memory_utilisation_percent_without_idle(connection): total = memory_total_in_clks(connection) active = memory_active_in_clks(connection) idle = memory_idle_in_clks(connection) - return (active/(total-idle))*100 + return (active / (total - idle)) * 100 @metric @@ -499,7 +499,7 @@ def memory_utilisation_in_Gibps_without_idle(connection): # the memory_utilisation_percent_new function result. maxDataRate = maximum_data_rate(connection) memoryPercent = memory_utilisation_percent_without_idle(connection) - return (memoryPercent/100)*(maxDataRate/1024) + return (memoryPercent / 100) * (maxDataRate / 1024) @metric @@ -557,16 +557,16 @@ def memory_utilisation_percent_including_idle(connection): # calculatedMetrics.append(("Relative Missdecisions", 0)) -@threadMetric -def average_response_latency_in_ns(connection, thread): - cursor = connection.cursor() - 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() - return round(result[0], 1) +# @threadMetric # FIXME: Fix thread metrics +# def average_response_latency_in_ns(connection, thread): +# cursor = connection.cursor() +# 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() +# return round(result[0], 1) def addStallTime(times, begin, end): @@ -579,33 +579,33 @@ def addStallTime(times, begin, end): time = time + 1 -# @threadMetric -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 Thread = :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) +# @threadMetric # FIXME: Fix thread metrics +# 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 Thread = :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) -@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 Thread = :thread """ - cursor.execute(query, {"Thread": thread}) - result = cursor.fetchone() - return result[0] +# @threadMetric # FIXME: Fix thread metrics +# 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 Thread = :Thread """ +# cursor.execute(query, {"Thread": thread}) +# result = cursor.fetchone() +# return result[0] @metric @@ -618,8 +618,8 @@ def RESP_count(connection): return get_phase_occurrences(connection, 'RESP') -#@metric -#def ACTB_count(connection): +# @metric +# def ACTB_count(connection): # return get_phase_occurrences(connection, 'ACTB') @@ -628,8 +628,8 @@ def ACT_count(connection): return get_phase_occurrences(connection, 'ACT') -#@metric -#def PREB_count(connection): +# @metric +# def PREB_count(connection): # return get_phase_occurrences(connection, 'PREB') @@ -881,9 +881,9 @@ def time_in_SREFB_percent(connection): @metric def time_in_power_down_states_in_ns(connection): mcconfig = MCConfig(connection) - #bankwiseLogic = mcconfig.getValue("BankwiseLogic") + # bankwiseLogic = mcconfig.getValue("BankwiseLogic") bankwiseLogic = "0" - + if bankwiseLogic == "0": totalTimeInPDNA = time_in_PDNA_in_ns(connection) totalTimeInPDNP = time_in_PDNP_in_ns(connection) @@ -901,9 +901,9 @@ def time_in_power_down_states_in_ns(connection): @metric def time_in_power_down_states_percent(connection): mcconfig = MCConfig(connection) - #bankwiseLogic = mcconfig.getValue("BankwiseLogic") + # bankwiseLogic = mcconfig.getValue("BankwiseLogic") bankwiseLogic = "0" - + if bankwiseLogic == "0": totalTimeAllBanks = trace_length_in_ns(connection) else: @@ -961,24 +961,26 @@ def getMetrics(pathToTrace): connection = sqlite3.connect(pathToTrace) mcconfig = MCConfig(connection) - #bankwiseLogic = mcconfig.getValue("BankwiseLogic") + # bankwiseLogic = mcconfig.getValue("BankwiseLogic") bankwiseLogic = "0" 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] + 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] + 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] for metric in pdnMetrics: if metric not in metrics: metrics.append(metric) - if (len(getThreads(connection)) >= 1): + if len(getThreads(connection)) >= 1: for metric in metrics: res = metric.__name__.replace("_", " ") selectedMetrics.append(res) - if (len(getThreads(connection)) > 1): + if len(getThreads(connection)) > 1: for thread in getThreads(connection): for threadMetric in threadMetrics: res = "Thread {0}: {1}".format(thread, threadMetric.__name__.replace("_", " ")) @@ -990,23 +992,18 @@ def getMetrics(pathToTrace): return selectedMetrics -def calculateMetrics(pathToTrace, selectedMetrics=[]): - +def calculateMetrics(pathToTrace, selectedMetrics=None): + if selectedMetrics is None: + selectedMetrics = [] calculatedMetrics = [] connection = sqlite3.connect(pathToTrace) mcconfig = MCConfig(connection) - #bankwiseLogic = mcconfig.getValue("BankwiseLogic") - bankwiseLogic = "0" + # bankwiseLogic = mcconfig.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] + 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] for m in pdnMetrics: if m not in metrics: @@ -1018,18 +1015,18 @@ def calculateMetrics(pathToTrace, selectedMetrics=[]): print("Number of threads is {0}".format(len(getThreads(connection)))) if not selectedMetrics: - selectedMetrics = [0] * (len(metrics) + len(getThreads(connection))*len(threadMetrics) + 1) + selectedMetrics = [0] * (len(metrics) + len(getThreads(connection)) * len(threadMetrics) + 1) for i in range(len(selectedMetrics)): selectedMetrics[i] = True - if (len(getThreads(connection)) >= 1): + if len(getThreads(connection)) >= 1: for metric in metrics: if selectedMetrics[metrics.index(metric)]: mres = metric(connection) mname = metric.__name__.replace("_", " ") res = (mname, mres) - if (metric.__name__ == "bank_overlap_ratio"): + if metric.__name__ == "bank_overlap_ratio": values = mres.split(",") nbanks = 0 for v in values: @@ -1037,7 +1034,7 @@ def calculateMetrics(pathToTrace, selectedMetrics=[]): nbanks = nbanks + 1 r = (name, float(v)) calculatedMetrics.append(r) - elif (metric.__name__ == "delayed_reasons" or metric.__name__ == "command_bus_utilisation_in_percent"): + elif metric.__name__ == "delayed_reasons" or metric.__name__ == "command_bus_utilisation_in_percent": values = mres.split(",") for v in values: name = mname + " (" + v.partition(":")[0].strip() + ")" @@ -1049,21 +1046,21 @@ def calculateMetrics(pathToTrace, selectedMetrics=[]): print("{0}: {1}".format(res[0], res[1])) - if (len(getThreads(connection)) > 1): + if len(getThreads(connection)) > 1: for thread in getThreads(connection): for metric in threadMetrics: - if(selectedMetrics[len(metrics) + len(threadMetrics)*(thread-1) + threadMetrics.index(metric)]): + if selectedMetrics[len(metrics) + len(threadMetrics) * (thread - 1) + threadMetrics.index(metric)]: mres = metric(connection, thread) mname = "Thread {0} - {1}".format(thread, metric.__name__.replace("_", " ")) res = (mname, mres) calculatedMetrics.append(res) print("{0}: {1}".format(res[0], res[1])) - if (selectedMetrics[len(selectedMetrics) - 1]): - calculatedMetrics.extend(passRatio(connection)) + # if selectedMetrics[len(selectedMetrics) - 1]: # FIXME: Add pass ratio + # calculatedMetrics.extend(passRatio(connection)) # refreshMissDecision(connection, calculatedMetrics) - if (len(getThreads(connection)) == 0): + if len(getThreads(connection)) == 0: res = ("No accesses were performed for this channel, number of metrics generated", 0.0) calculatedMetrics.append(res) @@ -1071,8 +1068,8 @@ def calculateMetrics(pathToTrace, selectedMetrics=[]): connection.close() return calculatedMetrics -def calculateMetricsFromFuncs(pathToTrace, selectedMetrics): +def calculateMetricsFromFuncs(pathToTrace, selectedMetrics): calculatedMetrics = [] connection = sqlite3.connect(pathToTrace) @@ -1084,7 +1081,7 @@ def calculateMetricsFromFuncs(pathToTrace, selectedMetrics): print("Number of threads is {0}".format(len(getThreads(connection)))) if not selectedMetrics: - selectedMetrics = [0] * (len(metrics) + len(getThreads(connection))*len(threadMetrics) + 1) + selectedMetrics = [0] * (len(metrics) + len(getThreads(connection)) * len(threadMetrics) + 1) for i in range(len(selectedMetrics)): selectedMetrics[i] = True @@ -1093,7 +1090,7 @@ def calculateMetricsFromFuncs(pathToTrace, selectedMetrics): mname = metric.__name__.replace("_", " ") res = (mname, mres) - if (metric.__name__ == "bank_overlap_ratio"): + if metric.__name__ == "bank_overlap_ratio": values = mres.split(",") nbanks = 0 for v in values: @@ -1110,6 +1107,7 @@ def calculateMetricsFromFuncs(pathToTrace, selectedMetrics): connection.close() return calculatedMetrics + if __name__ == "__main__": """ Only non-threaded metrics are implemented for selection through command line @@ -1120,7 +1118,7 @@ if __name__ == "__main__": dic_metric_functions = {} for m in metrics: - parser.add_argument("--"+m.__name__, action='store_true') + parser.add_argument("--" + m.__name__, action='store_true') dic_metric_functions[m.__name__] = m arg_namespace = parser.parse_args(sys.argv[1:]) @@ -1132,8 +1130,7 @@ if __name__ == "__main__": if v: selected_metrics.append(dic_metric_functions[k]) - - if selected_metrics == []: + if not selected_metrics: calculateMetrics(arg_namespace.path) else: calculateMetricsFromFuncs(arg_namespace.path, selected_metrics)