diff --git a/dram/.settings/language.settings.xml b/dram/.settings/language.settings.xml index 127cd8ac..278289a3 100644 --- a/dram/.settings/language.settings.xml +++ b/dram/.settings/language.settings.xml @@ -4,7 +4,7 @@ - + diff --git a/dram/resources/scripts/createTraceDB.sql b/dram/resources/scripts/createTraceDB.sql index 6acb961b..b0b952df 100644 --- a/dram/resources/scripts/createTraceDB.sql +++ b/dram/resources/scripts/createTraceDB.sql @@ -43,6 +43,7 @@ CREATE TABLE Transactions( ID INTEGER PRIMARY KEY, Range INTEGER, Address INTEGER, + Burstlength INTEGER, TThread INTEGER, TChannel INTEGER, TBank INTEGER, diff --git a/dram/resources/scripts/metrics.py b/dram/resources/scripts/metrics.py index c6c18641..f5be0fbf 100644 --- a/dram/resources/scripts/metrics.py +++ b/dram/resources/scripts/metrics.py @@ -26,6 +26,11 @@ def getNumberOfBanks(connection): 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 average_response_latency_in_ns(connection): @@ -60,6 +65,46 @@ def number_of_precharges(connection): result = cursor.fetchone() return result[0] + +def timeInPowerStates(connection): + totalTimeAllBanks = getTraceLength(connection)*getNumberOfBanks(connection) + cursor = connection.cursor() + result = [] + + cursor.execute("SELECT SUM(PhaseEnd-PhaseBegin) from Phases where PhaseName = 'PDNA'") + timeInPDNA = cursor.fetchone() + if(timeInPDNA != None): + totalTimeInPDNA = timeInPDNA[0] + else: + totalTimeInPDNA = 0 + fractionInPDNA = totalTimeInPDNA*1.0/totalTimeAllBanks + result.append(("Time in PDNA (%)", fractionInPDNA*100)) + print("{0} {1}".format(result[-1][0],result[-1][1])) + + cursor.execute("SELECT SUM(PhaseEnd-PhaseBegin) from Phases where PhaseName = 'PDNP'") + timeInPDNP = cursor.fetchone() + if(timeInPDNP != None): + totalTimeInPDNP = timeInPDNP[0] + else: + totalTimeInPDNP = 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() + if(timeInSREF != None): + totalTimeInSREF = timeInSREF[0] + else: + totalTimeInSREF = 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)) + print("{0} {1}".format(result[0][0],result[0][1])) + + return result + def passRatio(connection): numberOfPassWins = {} @@ -95,9 +140,14 @@ def passRatio(connection): result = [] for thread in getThreads(connection): - print("Thread {0} passed other threads {1} times and was passed {2} times. Ratio is {3}".format - (thread, numberOfPassWins[thread], numberOfPassLosses[thread], numberOfPassWins[thread]*1.0/(numberOfPassWins[thread]+numberOfPassLosses[thread]))) - result.append(("Thread {0} pass ratio".format(thread), numberOfPassWins[thread]*1.0/(numberOfPassWins[thread]+numberOfPassLosses[thread]))) + 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 @@ -122,7 +172,7 @@ def calculateMetrics(pathToTrace): calculatedMetrics.append(res) calculatedMetrics.extend(passRatio(connection)) - + calculatedMetrics.extend(timeInPowerStates(connection)) connection.close() return calculatedMetrics diff --git a/dram/resources/scripts/tests.py b/dram/resources/scripts/tests.py index 46faa6be..e0f15613 100644 --- a/dram/resources/scripts/tests.py +++ b/dram/resources/scripts/tests.py @@ -7,10 +7,11 @@ class DramConfig(object): unitOfTime = "ns" nActivateWindow = 0 - burstLengtht = 2 clk = numberOfBanks = 0 tRP = tRAS = tRC = tRRD = tRCD = tTAW = tRL = tWL = tWTR = tRFC = tWR = 0 tReadLength = tWriteLength = 0 + bankwiseRefresh = False + bankwisePowerdown = False def clkAlign(self, value): return math.ceil(1.0*value/self.clk)*self.clk @@ -32,15 +33,21 @@ class DramConfig(object): self.tWR = 2*self.clk self.tTAW = self.clkAlign(50) self.tRFC = self.clkAlign(130) - - self.tReadLength = self.tRL + self.burstLength * self.clk - self.tWriteLength = self.tWL + (self.burstLength - 1) *self.clk + self.tCKESR = self.clkAlign(max(3*self.clk, 15)) def __init__(self): self.parseFromXml() dramconfig = DramConfig() + +def calculateReadLength(burstLength): + return dramconfig.tRL + burstLength * dramconfig.clk + +def calculateWriteLength(burstLength): + return dramconfig.tWL + burstLength * dramconfig.clk + + # ----------- test utils --------------------------------------- @@ -88,11 +95,23 @@ def commands_are_clockaligned(connection): def commandbus_slots_are_used_once(connection): """Checks that no two phases on the command bus start at the same time""" cursor = connection.cursor() - cursor.execute("SELECT PhaseBegin,count FROM (SELECT phaseBegin,count(phasebegin) AS count FROM Phases WHERE PhaseName NOT IN ('RESP','REQ') GROUP BY phaseBegin) WHERE count>1") - result = cursor.fetchone() + + if dramconfig.bankwisePowerdown and dramconfig.bankwiseRefresh: + excludedPhases = "('REQ','RESP','PRE_ALL')" + elif (not dramconfig.bankwisePowerdown and dramconfig.bankwiseRefresh): + excludedPhases = "('REQ','RESP','PRE_ALL','PDNA','PDNP','SREF')" + elif dramconfig.bankwisePowerdown and not dramconfig.bankwiseRefresh: + excludedPhases = "('REQ','RESP','PRE_ALL','AUTO_REFRESH')" + else: + excludedPhases = "('REQ','RESP','PRE_ALL','PDNA','PDNP','SREF','AUTO_REFRESH')" + + query = """SELECT PhaseBegin,count FROM (SELECT phaseBegin,count(phasebegin) AS count + FROM Phases WHERE PhaseName NOT IN """ + excludedPhases + """ AND phasebegin>0 GROUP BY phaseBegin) WHERE count>1""" + cursor.execute(query) + result = cursor.fetchone() if(result != None): - return TestFailed("Slot on commandbus at time {0} is used twice".format(formatTime(result[0]))) + return TestFailed("Slot on commandbus at time {0} is used multiple times".format(formatTime(result[0]))) return TestSuceeded() @@ -171,29 +190,23 @@ def phases_on_bank_are_sequential(connection): @test def phase_lengths_are_correct(connection): - query = """SELECT ID,PhaseEnd-PhaseBegin FROM Phases WHERE PhaseName = :command and (PhaseEnd-PhaseBegin)!= :length""" - commandLengths = [('RD', dramconfig.tReadLength), - ('RDA', dramconfig.tReadLength + dramconfig.tRP), - ('WR', dramconfig.tWriteLength), - ('WRA', dramconfig.tWriteLength + dramconfig.tRP), - ('PRE', dramconfig.tRP), - ('ACT', dramconfig.tRCD), - ('AUTO_REFRESH', dramconfig.tRFC)] - - for commandLength in commandLengths: - command = commandLength[0] - length = commandLength[1] - cursor = connection.cursor() - cursor.execute(query, {"command":command, "length" : length}) - result = cursor.fetchone() - if(result != None): - return TestFailed("Phase with ID {0}({1}) has invalid length {2}".format(result[0],command,formatTime(result[1]))) - + query = """SELECT phases.ID,PhaseName, PhaseEnd-PhaseBegin,Burstlength FROM Phases INNER JOIN transactions ON transactions.ID = phases.transact """ + cursor = connection.cursor() + cursor.execute(query) + + for currentRow in cursor: + command = currentRow[1] + commandLength = currentRow[2] + burstlength = currentRow[3] + if(command == "RD" and commandLength != calculateReadLength(burstlength) or + command == "WR" and commandLength != calculateWriteLength(burstLength) or + command == "RDA" and commandLength != calculateReadLength(burstlength)+dramconfig.tRP or + command == "WRA" and commandLength != calculateReadLength(burstlength)+dramconfig.tRP or + (command == "PRE" or command=="PRE_ALL") and commandLength != dramconfig.tRP or + command == "AUTO_REFRESH" and commandLength != dramconfig.tRFC): + return TestFailed("Phase with ID {0}({1}) has invalid length of {2}".format(currentRow[0],command,formatTime(commandLength))) return TestSuceeded() - - - #----------- activate checks --------------------------------------- @test @@ -325,6 +338,16 @@ def write_or_read_to_precharge(connection): lastRow = currentRow return TestSuceeded() + +@test +def sref_active_for_minimal_time(connection): + """Checks if SREF is active for at least a minimal time (JEDEC 229, P. 41)""" + cursor = connection.cursor() + cursor.execute("SELECT ID, PhaseEnd-PhaseBegin FROM Phases WHERE PhaseName = 'SREF'") + for currentRow in cursor: + 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() # -------------------------- interface methods -------------------- def runTests(pathToTrace): diff --git a/dram/src/common/TlmRecorder.cpp b/dram/src/common/TlmRecorder.cpp index 286c8ced..8a8c8738 100644 --- a/dram/src/common/TlmRecorder.cpp +++ b/dram/src/common/TlmRecorder.cpp @@ -88,7 +88,7 @@ void TlmRecorder::setUpTransactionTerminatingPhases() void TlmRecorder::prepareSqlStatements() { insertTransactionString = - "INSERT INTO Transactions VALUES (:id,:rangeID,:address,:thread,:channel,:bank,:row,:column,:command)"; + "INSERT INTO Transactions VALUES (:id,:rangeID,:address,:burstlength,:thread,:channel,:bank,:row,:column,:command)"; insertRangeString = "INSERT INTO Ranges VALUES (:id,:begin,:end)"; updateRangeString = "UPDATE Ranges SET End = :end WHERE ID = :id"; insertPhaseString = @@ -139,15 +139,16 @@ void TlmRecorder::insertTransactionInDB(unsigned int id, tlm::tlm_generic_payloa sqlite3_bind_int(insertTransactionStatement, 1, id); sqlite3_bind_int(insertTransactionStatement, 2, id); sqlite3_bind_int(insertTransactionStatement, 3, trans.get_address()); - sqlite3_bind_text(insertTransactionStatement, 9, + sqlite3_bind_int(insertTransactionStatement, 4, trans.get_streaming_width()); + sqlite3_bind_text(insertTransactionStatement, 10, trans.get_command() == tlm::TLM_READ_COMMAND ? "R" : "W", 1, 0); const DramExtension& extension = DramExtension::getExtension(trans); - sqlite3_bind_int(insertTransactionStatement, 4, extension.getThread().ID()); - sqlite3_bind_int(insertTransactionStatement, 5, extension.getChannel().ID()); - sqlite3_bind_int(insertTransactionStatement, 6, extension.getBank().ID()); - sqlite3_bind_int(insertTransactionStatement, 7, extension.getRow().ID()); - sqlite3_bind_int(insertTransactionStatement, 8, extension.getColumn().ID()); + sqlite3_bind_int(insertTransactionStatement, 5, extension.getThread().ID()); + sqlite3_bind_int(insertTransactionStatement, 6, extension.getChannel().ID()); + sqlite3_bind_int(insertTransactionStatement, 7, extension.getBank().ID()); + sqlite3_bind_int(insertTransactionStatement, 8, extension.getRow().ID()); + sqlite3_bind_int(insertTransactionStatement, 9, extension.getColumn().ID()); executeSqlStatement(insertTransactionStatement); } @@ -258,3 +259,4 @@ void TlmRecorder::closeConnection() sqlite3_close(db); db = NULL; } + diff --git a/dram/src/common/dramExtension.h b/dram/src/common/dramExtension.h index 7ef2d124..d515be44 100644 --- a/dram/src/common/dramExtension.h +++ b/dram/src/common/dramExtension.h @@ -103,20 +103,20 @@ private: Bank bank; Row row; Column column; - + unsigned int burstlength; public: - DramExtension():thread(0),channel(0),bank(0),row(0),column(0){} - DramExtension(const Thread& thread, const Bank& bank, const Row& row, const Column& column) : - thread(thread),channel(0),bank(bank),row(row),column(column){} - DramExtension(const Thread& thread,const Channel& channel, const Bank& bank, const Row& row, const Column& column) : - thread(thread),channel(channel),bank(bank),row(row),column(column){} + DramExtension():thread(0),channel(0),bank(0),row(0),column(0),burstlength(0){} + DramExtension(const Thread& thread, const Bank& bank, const Row& row, const Column& column, unsigned int burstlength=0) : + thread(thread),channel(0),bank(bank),row(row),column(column), burstlength(burstlength){} + DramExtension(const Thread& thread,const Channel& channel, const Bank& bank, const Row& row, const Column& column, unsigned int burstlength=0) : + thread(thread),channel(channel),bank(bank),row(row),column(column), burstlength(burstlength){} ~DramExtension(){} virtual tlm_extension_base* clone() const { - return new DramExtension(thread, bank, row, column); + return new DramExtension(thread, bank, row, column, burstlength); } virtual void copy_from(const tlm_extension_base& ext) { @@ -125,6 +125,7 @@ public: bank = cpyFrom.bank; row = cpyFrom.row; column = cpyFrom.column; + burstlength = cpyFrom.burstlength; } const Thread& getThread() const{return thread;} @@ -132,6 +133,7 @@ public: const Bank& getBank() const{return bank;} const Row& getRow() const{return row;} const Column& getColumn() const{return column;} + const unsigned int getBurstlength() const{return burstlength;} static const DramExtension& getExtension(const tlm::tlm_generic_payload *payload); diff --git a/dram/src/common/xmlAddressdecoder.cpp b/dram/src/common/xmlAddressdecoder.cpp index 8e438365..7271b39c 100644 --- a/dram/src/common/xmlAddressdecoder.cpp +++ b/dram/src/common/xmlAddressdecoder.cpp @@ -19,6 +19,7 @@ xmlAddressDecoder::xmlAddressDecoder(string addressConfigURI) // get channel: TiXmlElement* channel = addressmap->FirstChildElement("channel"); + from = getAttribute(channel, "from"); to = getAttribute(channel, "to"); diff --git a/dram/src/core/BankStates.cpp b/dram/src/core/BankStates.cpp index 81bf9b91..b89136f1 100644 --- a/dram/src/core/BankStates.cpp +++ b/dram/src/core/BankStates.cpp @@ -6,6 +6,8 @@ */ #include "BankStates.h" +#include "ControllerCore.h" +#include "../common/DebugManager.h" using namespace std; @@ -34,11 +36,13 @@ Row BankStates::getRowInRowBuffer(const Bank &bank) const void BankStates::openRowInRowBuffer(const Bank &bank, const Row &row) { + DebugManager::getInstance().printDebugMessage(ControllerCore::senderName, "Row buffer for bank " + to_string(bank.ID()) + " is now open"); rowsInRowBuffers.at(bank.ID()) = row; } void BankStates::closeRowBuffer(const Bank &bank) { + DebugManager::getInstance().printDebugMessage(ControllerCore::senderName, "Row buffer for bank " + to_string(bank.ID()) + " is now closed"); rowsInRowBuffers.at(bank.ID()) = Row::NO_ROW; } diff --git a/dram/src/core/Configuration.h b/dram/src/core/Configuration.h index 3e4224ff..3b6399e2 100644 --- a/dram/src/core/Configuration.h +++ b/dram/src/core/Configuration.h @@ -15,7 +15,7 @@ namespace core{ struct Configuration { - Configuration(): NumberOfBanks(8), NumberOfBankGroups(4), Burstlength(2), Timings(NumberOfBanks), BankwiseRefresh(true),BankwisePowerDown(true), + Configuration(): NumberOfBanks(8), NumberOfBankGroups(4), Burstlength(2), Timings(NumberOfBanks), BankwiseRefresh(false),BankwisePowerDown(false), nActivate(2) {} unsigned int NumberOfBanks; diff --git a/dram/src/core/ControllerCore.cpp b/dram/src/core/ControllerCore.cpp index bd116391..a43bac47 100644 --- a/dram/src/core/ControllerCore.cpp +++ b/dram/src/core/ControllerCore.cpp @@ -79,9 +79,15 @@ void ControllerCore::triggerRefresh(tlm::tlm_generic_payload& payload, sc_time t if (!powerDownManager->isInSelfRefresh(bank)) { if(config.BankwiseRefresh) - powerDownManager->wakeUpForRefresh(bank, time);//expect PDNA and PDNP to exit without delay + { + printDebugMessage("Waking up bank " + to_string(bank.ID()) + " for refresh"); + powerDownManager->wakeUpForRefresh(bank, time);//expects PDNA and PDNP to exit without delay + } else + { + printDebugMessage("Waking up all banks for refresh"); powerDownManager->wakeUpAllForRefresh(time); + } refreshManager->scheduleRefresh(payload, time); } @@ -96,7 +102,6 @@ bool ControllerCore::scheduleRequest(sc_time start, tlm::tlm_generic_payload& pa { start = clkAlign(start, config.Timings.clk); state.cleanUp(start); - payload.set_streaming_width(config.Burstlength); saveState(); diff --git a/dram/src/core/powerdown/PowerDownManager.cpp b/dram/src/core/powerdown/PowerDownManager.cpp index eba8b183..1f1c29b0 100644 --- a/dram/src/core/powerdown/PowerDownManager.cpp +++ b/dram/src/core/powerdown/PowerDownManager.cpp @@ -45,10 +45,6 @@ void PowerDownManager::sleep(Bank bank, sc_time time) sendPowerDownPayload(time, bank, getSleepCommand(getPowerDownState(bank))); } - else - { - SC_REPORT_FATAL("Power Down Manager", "Sleep triggered even though already in sleep"); - } } void PowerDownManager::wakeUp(Bank bank, sc_time time) @@ -260,7 +256,6 @@ void PowerDownManager::init() controller.state.change(pdn); controller.wrapper.send(pdn, payload); powerDownStates[bank] = PowerDownState::PDNPrecharge; - //setState(PowerDownState::PDNPrecharge, bank); } } diff --git a/dram/src/core/powerdown/PowerDownManagerGrouped.cpp b/dram/src/core/powerdown/PowerDownManagerGrouped.cpp index 62dd10ea..dba2806a 100644 --- a/dram/src/core/powerdown/PowerDownManagerGrouped.cpp +++ b/dram/src/core/powerdown/PowerDownManagerGrouped.cpp @@ -25,9 +25,7 @@ PowerDownManagerGrouped::~PowerDownManagerGrouped() void PowerDownManagerGrouped::sleep(Bank bank, sc_time time) { - assert(!isInPowerDown());//cause nobody calls sleep if already sleeping on all banks - - //all banks can sleep and no pending refresh + //all banks can sleep and no pending refresh in system if (!canSleep() || (controller.state.getLastCommand(Command::AutoRefresh).getEnd() > time)) return; @@ -43,19 +41,20 @@ void PowerDownManagerGrouped::sleep(Bank bank, sc_time time) } else if (state == PowerDownState::AwakeForRefresh)//coming from refresh interrupting power down { - //last running refresh triggers sleep - if (controller.state.getLastCommand(Command::PDNA).getStart() - > controller.state.getLastCommand(Command::PDNP).getStart()) - setState(PowerDownState::PDNPrecharge); + if(controller.state.bankStates.allRowBuffersAreClosed()) + { + if (controller.state.getLastCommand(Command::PDNA).getStart() + > controller.state.getLastCommand(Command::PDNP).getStart()) + setState(PowerDownState::PDNPrecharge); + else + setState(PowerDownState::PDNSelfRefresh); + } else - setState(PowerDownState::PDNSelfRefresh); - + { + setState(PowerDownState::PDNActive); + } sendPowerDownPayload(time, getSleepCommand(getPowerDownState())); } - else - { - SC_REPORT_FATAL("PowerDownManagerGrouped", "Sleep triggered even though already in sleep"); - } } void PowerDownManagerGrouped::wakeUp(Bank bank, sc_time time) @@ -105,10 +104,7 @@ void PowerDownManagerGrouped::wakeUpAllForRefresh(sc_time time) { if(isInPowerDown()) { - for (Bank bank : controller.getBanks()) - { - sendPowerDownPayload(time, getWakeUpCommand(getPowerDownState())); - } + sendPowerDownPayload(time, getWakeUpCommand(getPowerDownState())); setState(PowerDownState::AwakeForRefresh); } diff --git a/dram/src/core/scheduling/CommandSchedule.h b/dram/src/core/scheduling/CommandSchedule.h index 6af549cd..41588a34 100644 --- a/dram/src/core/scheduling/CommandSchedule.h +++ b/dram/src/core/scheduling/CommandSchedule.h @@ -18,7 +18,7 @@ class CommandSchedule { public: CommandSchedule(tlm::tlm_generic_payload& transaction) : - extension(DramExtension::getExtension(&transaction)), burstLength(transaction.get_streaming_width()) + extension(DramExtension::getExtension(&transaction)) { } @@ -28,7 +28,7 @@ public: ScheduledCommand& add(Command command, sc_time start, sc_time executionTime) { - scheduledCommands.push_back(ScheduledCommand(command, start, executionTime, extension, burstLength)); + scheduledCommands.push_back(ScheduledCommand(command, start, executionTime, extension)); return scheduledCommands.back(); } @@ -59,7 +59,6 @@ public: private: std::vector scheduledCommands; - unsigned int burstLength; DramExtension extension; }; diff --git a/dram/src/core/scheduling/ScheduledCommand.cpp b/dram/src/core/scheduling/ScheduledCommand.cpp index d3b35fef..81c451d8 100644 --- a/dram/src/core/scheduling/ScheduledCommand.cpp +++ b/dram/src/core/scheduling/ScheduledCommand.cpp @@ -69,7 +69,7 @@ Row ScheduledCommand::getRow() const unsigned int ScheduledCommand::getBurstLength() { - return burstLength; + return extension.getBurstlength(); } bool ScheduledCommand::operator ==(const ScheduledCommand& b) const diff --git a/dram/src/core/scheduling/ScheduledCommand.h b/dram/src/core/scheduling/ScheduledCommand.h index a393ef67..87bf162c 100644 --- a/dram/src/core/scheduling/ScheduledCommand.h +++ b/dram/src/core/scheduling/ScheduledCommand.h @@ -20,15 +20,15 @@ class ScheduledCommand { public: - ScheduledCommand(Command command, sc_time start, sc_time executionTime, const DramExtension& extension, unsigned int burstLength = 0) : - command(command), start(start), executionTime(executionTime),end(start+executionTime), burstLength(burstLength), + ScheduledCommand(Command command, sc_time start, sc_time executionTime, const DramExtension& extension) : + command(command), start(start), executionTime(executionTime),end(start+executionTime), extension(extension) { } ScheduledCommand() : - command(Command::NOP), start(SC_ZERO_TIME), executionTime(SC_ZERO_TIME), end(SC_ZERO_TIME), burstLength(0), extension() + command(Command::NOP), start(SC_ZERO_TIME), executionTime(SC_ZERO_TIME), end(SC_ZERO_TIME), extension() { } @@ -58,7 +58,6 @@ private: sc_time start; sc_time executionTime; sc_time end; - unsigned int burstLength; DramExtension extension; }; } /* namespace controller */ diff --git a/dram/src/core/scheduling/checker/ReadChecker.cpp b/dram/src/core/scheduling/checker/ReadChecker.cpp index ef4df9f9..2123a238 100644 --- a/dram/src/core/scheduling/checker/ReadChecker.cpp +++ b/dram/src/core/scheduling/checker/ReadChecker.cpp @@ -78,22 +78,13 @@ bool ReadChecker::collidesWithStrobeCommand(ScheduledCommand& read, if (strobeCommand.getCommand() == Command::Read || strobeCommand.getCommand() == Command::ReadA) { //read to read - TimeInterval readOnStrobe = getIntervalOnDataStrobe(read, config.Timings); - TimeInterval otherReadOnStrobe = getIntervalOnDataStrobe(strobeCommand, config.Timings); - - if (readOnStrobe.timeIsInInterval(otherReadOnStrobe.start)) + if(read.getStart() < strobeCommand.getStart()) { - return !isClkAligned(otherReadOnStrobe.start - readOnStrobe.start, - 2 * config.Timings.clk); - } - else if (otherReadOnStrobe.timeIsInInterval(readOnStrobe.start)) - { - return !isClkAligned(readOnStrobe.start - otherReadOnStrobe.start, - 2 * config.Timings.clk); + return (strobeCommand.getStart() - read.getStart() < read.getBurstLength()*config.Timings.clk); } else { - return false; + return (read.getStart() - strobeCommand.getStart() < strobeCommand.getBurstLength()*config.Timings.clk); } } else if (strobeCommand.getCommand() == Command::Write diff --git a/dram/src/core/scheduling/checker/WriteChecker.cpp b/dram/src/core/scheduling/checker/WriteChecker.cpp index c126fd8c..c048a385 100644 --- a/dram/src/core/scheduling/checker/WriteChecker.cpp +++ b/dram/src/core/scheduling/checker/WriteChecker.cpp @@ -27,7 +27,8 @@ void WriteChecker::delayToSatisfyConstraints(ScheduledCommand& command) const } } else if (lastCommand.getCommand() == Command::Read - || lastCommand.getCommand() == Command::Write || lastCommand.getCommand() == Command::PDNAX) + || lastCommand.getCommand() == Command::Write + || lastCommand.getCommand() == Command::PDNAX) { } else @@ -73,8 +74,17 @@ bool WriteChecker::collidesWithStrobeCommand(ScheduledCommand& write, if (strobeCommand.getCommand() == Command::Write || strobeCommand.getCommand() == Command::WriteA) { - //write to write (implicitly checked by checking the command bus first) - return false; + //write to write + if (write.getStart() < strobeCommand.getStart()) + { + return (strobeCommand.getStart() - write.getStart() + < write.getBurstLength() * config.Timings.clk); + } + else + { + return (write.getStart() - strobeCommand.getStart() + < strobeCommand.getBurstLength() * config.Timings.clk); + } } else if (strobeCommand.getCommand() == Command::Read || strobeCommand.getCommand() == Command::ReadA) diff --git a/dram/src/simulation/Arbiter.h b/dram/src/simulation/Arbiter.h index 1bba6133..cf6612d7 100644 --- a/dram/src/simulation/Arbiter.h +++ b/dram/src/simulation/Arbiter.h @@ -132,9 +132,10 @@ private: void appendDramExtension(int socketId, tlm_generic_payload& payload) { + unsigned int burstlength = payload.get_streaming_width(); node n; xmlAddressDecoder::getInstance().getNode(static_cast(payload.get_address()), &n); - DramExtension* extension = new DramExtension(Thread(socketId+1), Channel(n.channel), Bank(n.bank), Row(n.row), Column(n.colum)); + DramExtension* extension = new DramExtension(Thread(socketId+1), Channel(n.channel), Bank(n.bank), Row(n.row), Column(n.colum),burstlength); payload.set_auto_extension(extension); } }; diff --git a/dram/src/simulation/Controller.h b/dram/src/simulation/Controller.h index 26bbf6f1..f7a2e056 100644 --- a/dram/src/simulation/Controller.h +++ b/dram/src/simulation/Controller.h @@ -177,7 +177,7 @@ private: void scheduleNextPayload(Bank bank) { - printDebugMessage("Try to schedule next payload on bank " + to_string(bank.ID())); + printDebugMessage("Triggering schedule next payload on bank " + to_string(bank.ID())); if (scheduler->hasTransactionForBank(bank)) { @@ -188,8 +188,8 @@ private: } if (controller->powerDownManager->isInPowerDown(bank)) { + printDebugMessage("\t-> break: wake up bank first"); controller->powerDownManager->wakeUp(bank, sc_time_stamp()); - printDebugMessage("\t-> break: wake up power down"); return; } else if (controller->powerDownManager->isAwakeForRefresh(bank)) @@ -302,7 +302,10 @@ private: { printDebugMessage("Finished auto refresh on bank " + to_string(bank.ID())); if (numberOfPayloadsInSystem[bank] == 0) + { + printDebugMessage("\t -> Triggering sleep on bank " + to_string(bank.ID())); controller->powerDownManager->sleep(bank, sc_time_stamp()); + } scheduleNextPayload(DramExtension::getExtension(payload).getBank()); } else if (isIn(phase, { END_PRE, END_PRE_ALL, END_ACT })) diff --git a/dram/src/simulation/ISimulationManager.h b/dram/src/simulation/ISimulationManager.h index cb0dbd2c..4335496a 100644 --- a/dram/src/simulation/ISimulationManager.h +++ b/dram/src/simulation/ISimulationManager.h @@ -8,7 +8,7 @@ class ISimulationManager { public: virtual ~ISimulationManager(){} - virtual void tracePlayerFinishedCallback() = 0; + virtual void tracePlayerFinishedCallback(string name) = 0; }; } // namespace simulation diff --git a/dram/src/simulation/SimulationManager.cpp b/dram/src/simulation/SimulationManager.cpp index f01706ed..038cefbd 100644 --- a/dram/src/simulation/SimulationManager.cpp +++ b/dram/src/simulation/SimulationManager.cpp @@ -17,13 +17,15 @@ using namespace std; namespace simulation { -SimulationManager::SimulationManager(sc_module_name name, std::string stl1, std::string stl2, +SimulationManager::SimulationManager(sc_module_name name, std::string stl1, + unsigned int burstlength1, std::string stl2, unsigned int burstlenght2, std::string traceName, std::string pathToResources) : dram("dram"), arbiter("arbiter"), controller("controller"), player1("player1", - pathToResources + string("traces/") + stl1, this), player2("player2", - pathToResources + string("traces/") + stl2, this), traceName(traceName) + pathToResources + string("traces/") + stl1,burstlength1, this), player2("player2", + pathToResources + string("traces/") + stl2,burstlenght2, this), traceName(traceName) { + SC_THREAD(terminationThread); xmlAddressDecoder::addressConfigURI = pathToResources + string("configs/addressConfig.xml"); TlmRecorder::dbName = traceName; @@ -38,6 +40,7 @@ SimulationManager::SimulationManager(sc_module_name name, std::string stl1, std: whiteList.push_back(controller.name()); whiteList.push_back(player2.name()); whiteList.push_back(player1.name()); + whiteList.push_back(this->name()); whiteList.push_back(TlmRecorder::senderName); whiteList.push_back(ControllerCore::senderName); whiteList.push_back(PowerDownManager::senderName); @@ -49,21 +52,21 @@ void SimulationManager::startSimulation() clock_t begin = clock(); - cout << "Toplevel: simulation start" << std::endl; + DebugManager::getInstance().printDebugMessage(name(), "Starting simulation"); + player1.start(); + player2.start(); sc_start(); clock_t end = clock(); double elapsed_secs = double(end - begin) / CLOCKS_PER_SEC; - cout << "Simulation took " << elapsed_secs << " seconds." << endl; - cout << this->name(); - - string p = getenv("trace"); - string run_tpr = p + " " + traceName; - system(run_tpr.c_str()); + DebugManager::getInstance().printDebugMessage(name(), + "Simulation took " + to_string(elapsed_secs) + " seconds"); } -void SimulationManager::tracePlayerFinishedCallback() +void SimulationManager::tracePlayerFinishedCallback(string name) { + + DebugManager::getInstance().printDebugMessage(this->name(), "Traceplayer " + name + " finshed"); static int finishedPlayers = 0; finishedPlayers++; if (finishedPlayers == numberOfTracePlayers) @@ -75,9 +78,10 @@ void SimulationManager::tracePlayerFinishedCallback() void SimulationManager::terminationThread() { wait(terminateSimulation); + DebugManager::getInstance().printDebugMessage(this->name(), "Terminating simulation"); controller.terminateSimulation(); //waits for the termination of all pending powerdown phases in the dram system - wait(sc_time(50,SC_NS)); + wait(sc_time(50, SC_NS)); TlmRecorder::getInstance().closeConnection(); sc_stop(); } diff --git a/dram/src/simulation/SimulationManager.h b/dram/src/simulation/SimulationManager.h index 6b459917..2a220ce8 100644 --- a/dram/src/simulation/SimulationManager.h +++ b/dram/src/simulation/SimulationManager.h @@ -22,10 +22,11 @@ class SimulationManager : public ISimulationManager, public sc_module { public: SC_HAS_PROCESS(SimulationManager); - SimulationManager(sc_module_name name,std::string stl1, std::string stl2, - std::string traceName, std::string pathToResources); + SimulationManager(sc_module_name name, std::string stl1, + unsigned int burstlength1, std::string stl2, unsigned int burstlenght2, + std::string traceName, std::string pathToResources); void startSimulation(); - void tracePlayerFinishedCallback() override; + void tracePlayerFinishedCallback(string name) override; private: void terminationThread(); diff --git a/dram/src/simulation/TracePlayer.h b/dram/src/simulation/TracePlayer.h index 9f858ec6..c6e7a6f9 100644 --- a/dram/src/simulation/TracePlayer.h +++ b/dram/src/simulation/TracePlayer.h @@ -28,28 +28,36 @@ struct TracePlayer: public sc_module { public: tlm_utils::simple_initiator_socket iSocket; - TracePlayer(sc_module_name name, string pathToTrace, + TracePlayer(sc_module_name name, string pathToTrace, unsigned int burstlength, simulation::ISimulationManager* simulationManager) : - payloadEventQueue(this, &TracePlayer::peqCallback), file(pathToTrace), numberOfPendingTransactions( + payloadEventQueue(this, &TracePlayer::peqCallback), file(pathToTrace), burstlenght(burstlength), numberOfPendingTransactions( 0), transactionsSent(0), transactionsReceived(0), simulationManager( simulationManager) { if (!file.is_open()) SC_REPORT_FATAL(0, (string("Could not open trace ") + pathToTrace).c_str()); - if (!file) - { - SC_REPORT_FATAL(0, "trace is empty! Simulation stops"); - } - iSocket.register_nb_transport_bw(this, &TracePlayer::nb_transport_bw); - scheduleNextPayload(); + } + + void start() + { + bool fileIsEmpty = file.peek() == std::ifstream::traits_type::eof(); + if (fileIsEmpty) + { + simulationManager->tracePlayerFinishedCallback(name()); + } + else + { + scheduleNextPayload(); + } } private: tlm_utils::peq_with_cb_and_phase payloadEventQueue; MemoryManager memoryManager; ifstream file; + unsigned int burstlenght; unsigned int numberOfPendingTransactions; unsigned int transactionsSent; unsigned int transactionsReceived; @@ -89,7 +97,7 @@ private: payload->set_response_status(TLM_INCOMPLETE_RESPONSE); payload->set_dmi_allowed(false); payload->set_byte_enable_length(0); - payload->set_streaming_width(0); + payload->set_streaming_width(burstlenght); sc_time sendingTime = sc_time(std::stoi(time.c_str()), SC_NS); if (sendingTime <= sc_time_stamp()) @@ -137,7 +145,7 @@ private: + std::to_string(transactionsSent - transactionsReceived)); if (numberOfPendingTransactions == 0) - simulationManager->tracePlayerFinishedCallback(); + simulationManager->tracePlayerFinishedCallback(name()); } else if (phase == END_RESP) diff --git a/dram/src/simulation/main.cpp b/dram/src/simulation/main.cpp index 1be2ce4a..1a6eac07 100644 --- a/dram/src/simulation/main.cpp +++ b/dram/src/simulation/main.cpp @@ -17,15 +17,26 @@ string pathOfFile(string file) return file.substr(0, file.find_last_of('/')); } +void startTraceAnalyzer(string traceName) +{ + string p = getenv("trace"); + string run_tpr = p + " " + traceName; + system(run_tpr.c_str()); +} + int sc_main(int argc, char **argv) { sc_set_time_resolution(1, SC_NS); string resources = pathOfFile(argv[0]) + string("/../resources/"); string stl1 = "chstone-mips_32.stl"; - string stl2 = "chstone-motion_32.stl"; - SimulationManager simulationManager("sim",stl1,stl2,"tpr.tdb", resources); + unsigned int burstlength1 = 4; + string stl2 = "empty.stl"; + unsigned int burstlength2 = 2; + string traceName = "tpr.tdb"; + SimulationManager simulationManager("sim", stl1,burstlength1, stl2,burstlength2, traceName, resources); simulationManager.startSimulation(); + startTraceAnalyzer(traceName); return 0; }