diff --git a/dram/resources/scripts/createTraceDB.sql b/dram/resources/scripts/createTraceDB.sql index b0b952df..179d1e22 100644 --- a/dram/resources/scripts/createTraceDB.sql +++ b/dram/resources/scripts/createTraceDB.sql @@ -49,7 +49,10 @@ CREATE TABLE Transactions( TBank INTEGER, TRow INTEGER, TColumn INTEGER, - Command TEXT); + Command TEXT, + DataStrobeBegin INTEGER, + DataStrobeEnd INTEGER + ); CREATE INDEX ranges_index ON Transactions(Range); CREATE INDEX "phasesTransactions" ON "Phases" ("Transact" ASC); diff --git a/dram/resources/scripts/metrics.py b/dram/resources/scripts/metrics.py index 4055effc..f1081033 100644 --- a/dram/resources/scripts/metrics.py +++ b/dram/resources/scripts/metrics.py @@ -35,7 +35,7 @@ def getTraceLength(connection): @metric def average_response_latency_in_ns(connection): cursor = connection.cursor() - cursor.execute("""SELECT avg(ranges.end-ranges.begin) FROM transactions INNER JOIN ranges + cursor.execute("""SELECT avg(ranges.end-ranges.begin)/1000 FROM transactions INNER JOIN ranges ON transactions.range = ranges.ID where TThread != 0""") result = cursor.fetchone() @@ -44,7 +44,7 @@ def average_response_latency_in_ns(connection): @threadMetric def average_response_latency_in_ns(connection, thread): cursor = connection.cursor() - query = """SELECT avg(ranges.end-ranges.begin) FROM transactions INNER JOIN ranges + query = """SELECT avg(ranges.end-ranges.begin)/1000 FROM transactions INNER JOIN ranges ON transactions.range = ranges.ID where TThread = :Thread """ cursor.execute(query, {"Thread": thread}) diff --git a/dram/src/common/TlmRecorder.cpp b/dram/src/common/TlmRecorder.cpp index 9d3b0928..73a4dbae 100644 --- a/dram/src/common/TlmRecorder.cpp +++ b/dram/src/common/TlmRecorder.cpp @@ -89,9 +89,11 @@ void TlmRecorder::setUpTransactionTerminatingPhases() void TlmRecorder::prepareSqlStatements() { insertTransactionString = - "INSERT INTO Transactions VALUES (:id,:rangeID,:address,:burstlength,:thread,:channel,:bank,:row,:column,:command)"; + "INSERT INTO Transactions VALUES (:id,:rangeID,:address,:burstlength,:thread,:channel,:bank,:row,:column,:command,:dataStrobeBegin,:dataStrobeEnd)"; insertRangeString = "INSERT INTO Ranges VALUES (:id,:begin,:end)"; updateRangeString = "UPDATE Ranges SET End = :end WHERE ID = :id"; + updateDataStrobeString = "UPDATE Transactions SET DataStrobeBegin = :begin, DataStrobeEnd = :end WHERE ID = :id"; + insertPhaseString = "INSERT INTO Phases (PhaseName,PhaseBegin,PhaseEnd,Transact) VALUES (:name,:begin,:end,:transaction)"; updatePhaseString = @@ -99,11 +101,13 @@ void TlmRecorder::prepareSqlStatements() insertGeneralInfoString = "INSERT INTO GeneralInfo (NumberOfTransactions,TraceEnd,NumberOfBanks,description,clk,UnitOfTime) Values (:numberOfTransactions,:end,:numberOfBanks,:description,:clk,:unitOfTime)"; insertDebugMessageString = "INSERT INTO DebugMessages (Time,Message) Values (:time,:message)"; + sqlite3_prepare(db, insertTransactionString.c_str(), -1, &insertTransactionStatement, 0); sqlite3_prepare(db, insertRangeString.c_str(), -1, &insertRangeStatement, 0); sqlite3_prepare(db, updateRangeString.c_str(), -1, &updateRangeStatement, 0); sqlite3_prepare(db, insertPhaseString.c_str(), -1, &insertPhaseStatement, 0); sqlite3_prepare(db, updatePhaseString.c_str(), -1, &updatePhaseStatement, 0); + sqlite3_prepare(db, updateDataStrobeString.c_str(), -1, &updateDataStrobeStatement, 0); sqlite3_prepare(db, insertGeneralInfoString.c_str(), -1, &insertGeneralInfoStatement, 0); sqlite3_prepare(db, insertDebugMessageString.c_str(), -1, &insertDebugMessageStatement, 0); } @@ -150,6 +154,8 @@ void TlmRecorder::insertTransactionInDB(unsigned int id, tlm::tlm_generic_payloa sqlite3_bind_int(insertTransactionStatement, 7, extension.getBank().ID()); sqlite3_bind_int(insertTransactionStatement, 8, extension.getRow().ID()); sqlite3_bind_int(insertTransactionStatement, 9, extension.getColumn().ID()); + sqlite3_bind_int(insertTransactionStatement, 10, 0); + sqlite3_bind_int(insertTransactionStatement, 11, 0); executeSqlStatement(insertTransactionStatement); } @@ -181,6 +187,15 @@ void TlmRecorder::updatePhaseEndInDB(string phaseName, const sc_time& time, executeSqlStatement(updatePhaseStatement); } +void TlmRecorder::updateDataStrobe(const sc_time& begin,const sc_time& end, tlm::tlm_generic_payload& trans) +{ + unsigned int id = getElementFromMap(currentTransactionsInSystem, &trans); + sqlite3_bind_int64(updateDataStrobeStatement, 1, begin.value()); + sqlite3_bind_int64(updateDataStrobeStatement, 2, end.value()); + sqlite3_bind_int(updateDataStrobeStatement, 3, id); + executeSqlStatement(updateDataStrobeStatement); +} + void TlmRecorder::introduceNewTransactionToSystem(const sc_time& time, tlm::tlm_generic_payload& trans) { @@ -242,8 +257,12 @@ string TlmRecorder::getFileContents(string filename) in.close(); return (contents); } - throw(errno); -} + else + { + reportFatal("Error in TraceRecorder", "Could not load sql script from " + filename); + return ""; + } + } void TlmRecorder::printDebugMessage(std::string message) { diff --git a/dram/src/common/TlmRecorder.h b/dram/src/common/TlmRecorder.h index 707a1d9b..a719b506 100755 --- a/dram/src/common/TlmRecorder.h +++ b/dram/src/common/TlmRecorder.h @@ -28,6 +28,7 @@ public: void recordPhase(tlm::tlm_generic_payload &trans, tlm::tlm_phase phase, sc_time time); void recordPhase(tlm::tlm_generic_payload &trans, std::string name, sc_time begin, sc_time end); void recordDebugMessage(std::string message, sc_time time); + void updateDataStrobe(const sc_time& begin, const sc_time& end, tlm::tlm_generic_payload& trans); void closeConnection(); private: @@ -61,8 +62,8 @@ private: std::vector transactionTerminatingPhases; sqlite3 *db; sqlite3_stmt *insertTransactionStatement, *insertRangeStatement, *updateRangeStatement, - *insertPhaseStatement, *updatePhaseStatement, *insertGeneralInfoStatement, *insertDebugMessageStatement; + *insertPhaseStatement, *updatePhaseStatement, *insertGeneralInfoStatement, *insertDebugMessageStatement, *updateDataStrobeStatement; std::string insertTransactionString, insertRangeString, updateRangeString, insertPhaseString, updatePhaseString, insertGeneralInfoString, - insertDebugMessageString; + insertDebugMessageString, updateDataStrobeString; }; #endif diff --git a/dram/src/core/ControllerCore.cpp b/dram/src/core/ControllerCore.cpp index 28067b2c..d8fdd2b0 100644 --- a/dram/src/core/ControllerCore.cpp +++ b/dram/src/core/ControllerCore.cpp @@ -24,9 +24,11 @@ namespace core { std::string ControllerCore::senderName = "Controller Core"; -ControllerCore::ControllerCore(IWrapperConnector& wrapperConnector, std::map& numberOfPayloads) : - config(Configuration::getInstance()), state(&config), wrapper(wrapperConnector), commandChecker(), numberOfPayloads(numberOfPayloads), savedState( - &config), commandSequenceGenerator(state), commandSequenceScheduler(*this) +ControllerCore::ControllerCore(IWrapperConnector& wrapperConnector, + std::map& numberOfPayloads) : + config(Configuration::getInstance()), state(&config), wrapper(wrapperConnector), commandChecker(), numberOfPayloads( + numberOfPayloads), savedState(&config), commandSequenceGenerator(state), commandSequenceScheduler( + *this) { commandChecker[Command::Activate] = new ActivateChecker(config, state); @@ -106,7 +108,7 @@ void ControllerCore::triggerWakeUp(tlm::tlm_generic_payload& payload, sc_time ti bool ControllerCore::scheduleRequest(sc_time start, tlm::tlm_generic_payload& payload) { - start = clkAlign(start, config.Timings.clk); + start = clkAlign(start); state.cleanUp(start); saveState(); @@ -136,7 +138,7 @@ bool ControllerCore::isBusy(sc_time time, Bank bank) { return (time < lastScheduledCommand.getStart()); } - else if(lastScheduledCommand.commandIsIn({Command::WriteA, Command::ReadA})) + else if (lastScheduledCommand.commandIsIn( { Command::WriteA, Command::ReadA })) { return (time < lastScheduledCommand.getEnd()); } diff --git a/dram/src/core/configuration/Configuration.h b/dram/src/core/configuration/Configuration.h index 5985520e..24a1c12f 100644 --- a/dram/src/core/configuration/Configuration.h +++ b/dram/src/core/configuration/Configuration.h @@ -22,8 +22,8 @@ struct Configuration static Configuration& getInstance(); - string MemoryId; - string MemoryType; + std::string MemoryId; + std::string MemoryType; //MemSpecification unsigned int NumberOfBanks; @@ -42,7 +42,7 @@ struct Configuration bool AdaptiveOpenPagePolicy; bool RefreshAwareScheduling; unsigned int MaxNrOfTransactions; - string Scheduler; + std::string Scheduler; unsigned int Capsize; private: diff --git a/dram/src/core/configuration/MemSpecLoader.cpp b/dram/src/core/configuration/MemSpecLoader.cpp index 6e0050f9..effa1eef 100644 --- a/dram/src/core/configuration/MemSpecLoader.cpp +++ b/dram/src/core/configuration/MemSpecLoader.cpp @@ -72,10 +72,11 @@ void MemSpecLoader::loadDDR4(Configuration& config, XMLElement* memspec) double clkMhz = queryDoubleParameter(timings, "clkMhz"); sc_time clk = sc_time(1 / clkMhz, SC_US); config.Timings.clk = clk; -//TODO + config.Timings.tRP = clk * queryUIntParameter(timings, "RP"); config.Timings.tRAS = clk * queryUIntParameter(timings, "RAS"); config.Timings.tRC = clk * queryUIntParameter(timings, "RC"); + config.Timings.tRTP = clk * queryUIntParameter(timings, "RTP"); config.Timings.tRRD_S = clk * queryUIntParameter(timings, "RRD_S"); config.Timings.tRRD_L = clk * queryUIntParameter(timings, "RRD_L"); config.Timings.tCCD_S = clk * queryUIntParameter(timings, "CCD_S"); @@ -135,6 +136,7 @@ void MemSpecLoader::loadWideIO(Configuration& config, XMLElement* memspec) config.Timings.tWR = clk * queryUIntParameter(timings, "WR"); config.Timings.tWTR_S = clk * queryUIntParameter(timings, "WTR"); config.Timings.tWTR_L = config.Timings.tWTR_S; + config.Timings.tRTP = SC_ZERO_TIME; //TODO .. not defined in jedec. bl on datastrobe used config.Timings.tCKESR = clk * queryUIntParameter(timings, "CKESR"); config.Timings.tCKE = clk * queryUIntParameter(timings, "CKE"); config.Timings.tXP = clk * queryUIntParameter(timings, "XP"); diff --git a/dram/src/core/configuration/TimingConfiguration.h b/dram/src/core/configuration/TimingConfiguration.h index 83cd11e4..79ea3574 100644 --- a/dram/src/core/configuration/TimingConfiguration.h +++ b/dram/src/core/configuration/TimingConfiguration.h @@ -32,6 +32,7 @@ struct TimingConfiguration sc_time tRC; //RAS-cycle-time (min time bw 2 succesive ACT to same bank) sc_time tCCD_S; //TODO: relevant? max(bl, tCCD) sc_time tCCD_L; + sc_time tRTP; //Read to precharge sc_time tRRD_S; //min time bw 2 succesive ACT to different banks (different bank group) sc_time tRRD_L; //.. (same bank group) sc_time tRCD; //act -> read/write diff --git a/dram/src/core/powerdown/PowerDownManager.cpp b/dram/src/core/powerdown/PowerDownManager.cpp index 963049d7..f6c0c82b 100644 --- a/dram/src/core/powerdown/PowerDownManager.cpp +++ b/dram/src/core/powerdown/PowerDownManager.cpp @@ -207,7 +207,7 @@ Command PowerDownManager::getWakeUpCommand(PowerDownState state) void PowerDownManager::sendPowerDownPayload(sc_time time, Bank bank, Command cmd) { - time = clkAlign(time, controller.config.Timings.clk); //TODO is clkaligned already? + time = clkAlign(time); //TODO is clkaligned already? tlm_generic_payload& payload = getPayload(bank); ScheduledCommand pdn(cmd, time, controller.config.Timings.clk, DramExtension::getExtension(payload)); diff --git a/dram/src/core/powerdown/PowerDownManagerGrouped.cpp b/dram/src/core/powerdown/PowerDownManagerGrouped.cpp index 5ea04c53..ea232562 100644 --- a/dram/src/core/powerdown/PowerDownManagerGrouped.cpp +++ b/dram/src/core/powerdown/PowerDownManagerGrouped.cpp @@ -112,7 +112,7 @@ void PowerDownManagerGrouped::wakeUpAllForRefresh(sc_time time) void PowerDownManagerGrouped::sendPowerDownPayload(sc_time time, Command cmd) { - time = clkAlign(time, controller.config.Timings.clk); + time = clkAlign(time); //just to find slot tlm_generic_payload& payload = getPayload(Bank(0)); diff --git a/dram/src/core/refresh/RefreshManager.cpp b/dram/src/core/refresh/RefreshManager.cpp index 837a808e..dda7c261 100644 --- a/dram/src/core/refresh/RefreshManager.cpp +++ b/dram/src/core/refresh/RefreshManager.cpp @@ -79,7 +79,7 @@ void RefreshManager::planNextRefresh() void RefreshManager::reInitialize(tlm::tlm_generic_payload& payload, sc_time time) { - nextPlannedRefresh = clkAlign(time, controller.config.Timings.clk, Alignment::DOWN); + nextPlannedRefresh = clkAlign(time, Alignment::DOWN); planNextRefresh(); } diff --git a/dram/src/core/refresh/RefreshManagerBankwise.cpp b/dram/src/core/refresh/RefreshManagerBankwise.cpp index 563a628e..13e0446b 100644 --- a/dram/src/core/refresh/RefreshManagerBankwise.cpp +++ b/dram/src/core/refresh/RefreshManagerBankwise.cpp @@ -104,7 +104,7 @@ void RefreshManagerBankwise::RefreshManagerForBank::planNextRefresh() void RefreshManagerBankwise::RefreshManagerForBank::reInitialize(tlm::tlm_generic_payload& payload, sc_time time) { - nextPlannedRefresh = clkAlign(time, controller.config.Timings.clk, Alignment::DOWN); + nextPlannedRefresh = clkAlign(time, Alignment::DOWN); planNextRefresh(); } diff --git a/dram/src/core/scheduling/ScheduledCommand.cpp b/dram/src/core/scheduling/ScheduledCommand.cpp index a2d15a06..1fc7ec2d 100644 --- a/dram/src/core/scheduling/ScheduledCommand.cpp +++ b/dram/src/core/scheduling/ScheduledCommand.cpp @@ -7,6 +7,7 @@ #include "ScheduledCommand.h" #include "../utils/Utils.h" #include "../../common/Utils.h" +#include "../configuration/Configuration.h" namespace core { @@ -82,5 +83,33 @@ bool ScheduledCommand::commandIsIn(const std::vector& commandSet) const return isIn(command, commandSet); } +TimeInterval ScheduledCommand::getIntervalOnDataStrobe() const +{ + sc_assert( + getCommand() == Command::Read || getCommand() == Command::ReadA + || getCommand() == Command::Write + || getCommand() == Command::WriteA); + + TimingConfiguration& timings = Configuration::getInstance().Timings; + + sc_time burstLengthOnDataStrobe = getBurstLengthOnDataStrobe(getBurstLength()); + + if (getCommand() == Command::Read || getCommand() == Command::ReadA) + { + return TimeInterval(getStart() + timings.tRL, + getStart() + timings.tRL + burstLengthOnDataStrobe); + } + else + { + return TimeInterval(getStart() + timings.tWL - timings.clk / 2, + getStart() + timings.tWL + burstLengthOnDataStrobe - timings.clk / 2); + } +} + +bool ScheduledCommand::collidesOnDataStrobe(const ScheduledCommand& cmd) const +{ + return cmd.getIntervalOnDataStrobe().intersects(getIntervalOnDataStrobe()); +} + } diff --git a/dram/src/core/scheduling/ScheduledCommand.h b/dram/src/core/scheduling/ScheduledCommand.h index b4e9876e..5a56dcfe 100644 --- a/dram/src/core/scheduling/ScheduledCommand.h +++ b/dram/src/core/scheduling/ScheduledCommand.h @@ -13,6 +13,7 @@ #include "../Command.h" #include "../../common/dramExtension.h" #include "../../common/TlmRecorder.h" +#include "../utils/Utils.h" namespace core { @@ -52,6 +53,9 @@ public: bool commandIsIn(const std::vector& commandSet) const; + TimeInterval getIntervalOnDataStrobe() const; + + bool collidesOnDataStrobe(const ScheduledCommand& command) const; private: Command command; diff --git a/dram/src/core/scheduling/checker/PrechargeChecker.cpp b/dram/src/core/scheduling/checker/PrechargeChecker.cpp index 315d2a3d..85fe737e 100644 --- a/dram/src/core/scheduling/checker/PrechargeChecker.cpp +++ b/dram/src/core/scheduling/checker/PrechargeChecker.cpp @@ -23,7 +23,7 @@ void PrechargeChecker::delayToSatisfyConstraints(ScheduledCommand& command) cons if (lastCommand.getCommand() == Command::Read) { command.delayToMeetConstraint(lastCommand.getStart(), - lastCommand.getBurstLength() * config.Timings.clk); + max(config.Timings.tRTP , lastCommand.getIntervalOnDataStrobe().getLength())); } else if (lastCommand.getCommand() == Command::Write) { diff --git a/dram/src/core/scheduling/checker/ReadChecker.cpp b/dram/src/core/scheduling/checker/ReadChecker.cpp index 58c4c95b..13748dd6 100644 --- a/dram/src/core/scheduling/checker/ReadChecker.cpp +++ b/dram/src/core/scheduling/checker/ReadChecker.cpp @@ -23,7 +23,8 @@ void ReadChecker::delayToSatisfyConstraints(ScheduledCommand& command) const { command.delayToMeetConstraint(lastCommand.getEnd(), SC_ZERO_TIME); } - else if (lastCommand.getCommand() == Command::Read || lastCommand.getCommand() == Command::Write) + else if (lastCommand.getCommand() == Command::Read + || lastCommand.getCommand() == Command::Write) { } else if (lastCommand.getCommand() == Command::PDNAX) @@ -41,21 +42,6 @@ void ReadChecker::delayToSatisfyConstraints(ScheduledCommand& command) const } } -sc_time ReadChecker::getExecutionTime(const tlm::tlm_generic_payload& payload, - Command command) const -{ - assert(command == Command::Read || command == Command::ReadA); - - if (command == Command::Read) - { - return config.Timings.tRL + config.Timings.clk * payload.get_streaming_width(); - } - else - { - return config.Timings.clk * payload.get_streaming_width() + max(config.Timings.tRP,config.Timings.tRL); - } -} - bool ReadChecker::collidesOnDataStrobe(ScheduledCommand& read) const { for (ScheduledCommand& strobeCommand : state.lastDataStrobeCommands) @@ -67,18 +53,32 @@ bool ReadChecker::collidesOnDataStrobe(ScheduledCommand& read) const return false; } +sc_time ReadChecker::getExecutionTime(const tlm::tlm_generic_payload& payload, + Command command) const +{ + if (command == Command::Read) + { + return config.Timings.tRL + getBurstLengthOnDataStrobe(payload.get_streaming_width()); + } + else + { + return getBurstLengthOnDataStrobe(payload.get_streaming_width()) + max(config.Timings.tRP, config.Timings.tRL); + } +} + bool ReadChecker::collidesWithStrobeCommand(ScheduledCommand& read, ScheduledCommand& strobeCommand) const { //read to read if (strobeCommand.getCommand() == Command::Read || strobeCommand.getCommand() == Command::ReadA) { - bool collision = getIntervalOnDataStrobe(read).intersects(getIntervalOnDataStrobe(strobeCommand)); + bool collision = read.collidesOnDataStrobe(strobeCommand); sc_time tCCD = (getBankGroup(read.getBank()) == getBankGroup(strobeCommand.getBank())) ? config.Timings.tCCD_L : config.Timings.tCCD_S; - bool casToCas = (getDistance(read.getStart(), strobeCommand.getStart()) < tCCD) ? true : false; + bool casToCas = + (getDistance(read.getStart(), strobeCommand.getStart()) < tCCD) ? true : false; return collision || casToCas; } @@ -88,7 +88,7 @@ bool ReadChecker::collidesWithStrobeCommand(ScheduledCommand& read, //read to write if (strobeCommand.getStart() >= read.getStart()) { - return !(strobeCommand.getStart() >= getIntervalOnDataStrobe(read).end); + return strobeCommand.getStart() < read.getIntervalOnDataStrobe().end; } //write to read else @@ -97,7 +97,8 @@ bool ReadChecker::collidesWithStrobeCommand(ScheduledCommand& read, (getBankGroup(read.getBank()) == getBankGroup(strobeCommand.getBank())) ? config.Timings.tWTR_L : config.Timings.tWTR_S; - return !(read.getStart()>= getIntervalOnDataStrobe(strobeCommand).end + tWTR); + return read.getStart() + < clkAlign(strobeCommand.getIntervalOnDataStrobe().end, Alignment::DOWN) + tWTR; } } else diff --git a/dram/src/core/scheduling/checker/ReadChecker.h b/dram/src/core/scheduling/checker/ReadChecker.h index c2278c0e..60c8f514 100644 --- a/dram/src/core/scheduling/checker/ReadChecker.h +++ b/dram/src/core/scheduling/checker/ReadChecker.h @@ -22,6 +22,7 @@ public: virtual void delayToSatisfyConstraints(ScheduledCommand& command) const override; virtual sc_time getExecutionTime(const tlm::tlm_generic_payload& payload, Command command) const override; + private: const Configuration& config; ControllerState& state; diff --git a/dram/src/core/scheduling/checker/WriteChecker.cpp b/dram/src/core/scheduling/checker/WriteChecker.cpp index f53a04dd..ec0935b0 100644 --- a/dram/src/core/scheduling/checker/WriteChecker.cpp +++ b/dram/src/core/scheduling/checker/WriteChecker.cpp @@ -47,13 +47,19 @@ sc_time WriteChecker::getExecutionTime(const tlm::tlm_generic_payload& payload, Command command) const { assert(command == Command::Write || command == Command::WriteA); + + sc_time lengthOnDataStrobe = getBurstLengthOnDataStrobe(payload.get_streaming_width()); + if(Configuration::getInstance().DataRate == 1) + lengthOnDataStrobe -= Configuration::getInstance().Timings.clk; + + if (command == Command::Write) { - return config.Timings.tWL + config.Timings.clk * (payload.get_streaming_width() - 1); + return config.Timings.tWL + lengthOnDataStrobe; } else { - return config.Timings.tWL + config.Timings.clk * payload.get_streaming_width() + config.Timings.tWR; + return config.Timings.tWL + lengthOnDataStrobe + config.Timings.tWR; } } @@ -75,7 +81,7 @@ bool WriteChecker::collidesWithStrobeCommand(ScheduledCommand& write, if (strobeCommand.getCommand() == Command::Write || strobeCommand.getCommand() == Command::WriteA) { - bool collision = getIntervalOnDataStrobe(write).intersects(getIntervalOnDataStrobe(strobeCommand)); + bool collision = write.collidesOnDataStrobe(strobeCommand); sc_time tCCD = (getBankGroup(write.getBank()) == getBankGroup(strobeCommand.getBank())) ? @@ -94,14 +100,13 @@ bool WriteChecker::collidesWithStrobeCommand(ScheduledCommand& write, (getBankGroup(write.getBank()) == getBankGroup(strobeCommand.getBank())) ? config.Timings.tWTR_L : config.Timings.tWTR_S; - return !(strobeCommand.getStart() - >= getIntervalOnDataStrobe(write).end + tWTR); + return strobeCommand.getStart() + < clkAlign(write.getIntervalOnDataStrobe().end, Alignment::DOWN) + tWTR; } - //read to write else { - return !(write.getStart() >= getIntervalOnDataStrobe(strobeCommand).end); + return write.getStart() < strobeCommand.getIntervalOnDataStrobe().end; } } else diff --git a/dram/src/core/utils/Utils.cpp b/dram/src/core/utils/Utils.cpp index 3789b8a3..3a2ef906 100644 --- a/dram/src/core/utils/Utils.cpp +++ b/dram/src/core/utils/Utils.cpp @@ -34,39 +34,15 @@ sc_time getDelayToMeetConstraint(sc_time previous, sc_time start, sc_time constr return SC_ZERO_TIME; } -const sc_time clkAlign(sc_time time, sc_time clk, Alignment alignment) +const sc_time clkAlign(sc_time time, Alignment alignment) { + sc_time clk = Configuration::getInstance().Timings.clk; if (alignment == UP) return ceil(time / clk) * clk; else return floor(time / clk) * clk; } -TimeInterval getIntervalOnDataStrobe(const ScheduledCommand& command) -{ - sc_assert( - command.getCommand() == Command::Read || command.getCommand() == Command::ReadA - || command.getCommand() == Command::Write - || command.getCommand() == Command::WriteA); - - TimingConfiguration& timings = Configuration::getInstance().Timings; - - sc_assert((command.getBurstLength() / Configuration::getInstance().DataRate) > 0); - sc_time burstLength = timings.clk - * (command.getBurstLength() / Configuration::getInstance().DataRate); - - if (command.getCommand() == Command::Read || command.getCommand() == Command::ReadA) - { - return TimeInterval(command.getStart() + timings.tRL, - command.getStart() + timings.tRL + burstLength); - } - else - { - return TimeInterval(command.getStart() + timings.tWL, - command.getStart() + timings.tWL + burstLength); - } -} - bool isClkAligned(sc_time time, sc_time clk) { return !((time / clk) - ceil(time / clk)); @@ -99,3 +75,11 @@ BankGroup getBankGroup(Bank bank) } } + +sc_time core::getBurstLengthOnDataStrobe(unsigned int burstlength) +{ + Configuration& config = Configuration::getInstance(); + sc_assert((burstlength / config.DataRate) > 0); + + return config.Timings.clk * (burstlength / config.DataRate); +} diff --git a/dram/src/core/utils/Utils.h b/dram/src/core/utils/Utils.h index 3ace036a..f07b1d0e 100644 --- a/dram/src/core/utils/Utils.h +++ b/dram/src/core/utils/Utils.h @@ -11,29 +11,30 @@ #include #include #include "../../common/dramExtension.h" -#include "../scheduling/ScheduledCommand.h" namespace core { unsigned int getStartAddress(const Bank& bank); +sc_time getDistance(sc_time a, sc_time b); struct TimeInterval { sc_time start,end; + TimeInterval() : start(SC_ZERO_TIME), end(SC_ZERO_TIME){} TimeInterval(sc_time start,sc_time end) : start(start), end(end){} + sc_time getLength() {return getDistance(start,end);} bool timeIsInInterval(sc_time time); bool intersects(TimeInterval other); }; -sc_time getDistance(sc_time a, sc_time b); +sc_time getBurstLengthOnDataStrobe(unsigned int burstlength); struct TimingConfiguration; sc_time getDelayToMeetConstraint(sc_time previous, sc_time start, sc_time constraint); -TimeInterval getIntervalOnDataStrobe(const ScheduledCommand& command); enum Alignment {UP, DOWN}; -const sc_time clkAlign(sc_time time, sc_time clk, Alignment alignment = UP); +const sc_time clkAlign(sc_time time, Alignment alignment = UP); bool isClkAligned(sc_time time, sc_time clk); BankGroup getBankGroup(Bank bank); diff --git a/dram/src/simulation/Controller.h b/dram/src/simulation/Controller.h index d342a4ef..fe4047b2 100644 --- a/dram/src/simulation/Controller.h +++ b/dram/src/simulation/Controller.h @@ -61,12 +61,14 @@ public: void buildScheduler() { string selectedScheduler = Configuration::getInstance().Scheduler; - if(selectedScheduler == "FR_FCFS") - scheduler = new FR_FCFS(*controller,Configuration::getInstance().RefreshAwareScheduling,Configuration::getInstance().AdaptiveOpenPagePolicy); - else if(selectedScheduler == "FIFO") + if (selectedScheduler == "FR_FCFS") + scheduler = new FR_FCFS(*controller, + Configuration::getInstance().RefreshAwareScheduling, + Configuration::getInstance().AdaptiveOpenPagePolicy); + else if (selectedScheduler == "FIFO") scheduler = new Fifo(); else - reportFatal(name(),"unsupporeted scheduler: " + selectedScheduler); + reportFatal(name(), "unsupported scheduler: " + selectedScheduler); } void terminateSimulation() @@ -81,57 +83,98 @@ public: { assert(command.getStart() >= sc_time_stamp()); + TimeInterval dataStrobe; + + TlmRecorder& rec = TlmRecorder::getInstance(); switch (command.getCommand()) { case Command::Read: + rec.recordPhase(payload, BEGIN_RD, command.getStart()); + dataStrobe = command.getIntervalOnDataStrobe(); + rec.updateDataStrobe(dataStrobe.start, dataStrobe.end, payload); + rec.recordPhase(payload, END_RD, command.getEnd()); + dramPEQ.notify(payload, BEGIN_RD, command.getStart() - sc_time_stamp()); dramPEQ.notify(payload, END_RD, command.getEnd() - sc_time_stamp()); break; case Command::ReadA: + rec.recordPhase(payload, BEGIN_RDA, command.getStart()); + dataStrobe = command.getIntervalOnDataStrobe(); + rec.updateDataStrobe(dataStrobe.start, dataStrobe.end, payload); + rec.recordPhase(payload, END_RDA, command.getEnd()); + dramPEQ.notify(payload, BEGIN_RDA, command.getStart() - sc_time_stamp()); dramPEQ.notify(payload, END_RDA, command.getEnd() - sc_time_stamp()); break; case Command::Write: + rec.recordPhase(payload, BEGIN_WR, command.getStart()); + dataStrobe = command.getIntervalOnDataStrobe(); + rec.updateDataStrobe(dataStrobe.start, dataStrobe.end, payload); + rec.recordPhase(payload, END_WR, command.getEnd()); + dramPEQ.notify(payload, BEGIN_WR, command.getStart() - sc_time_stamp()); dramPEQ.notify(payload, END_WR, command.getEnd() - sc_time_stamp()); break; case Command::WriteA: + rec.recordPhase(payload, BEGIN_WRA, command.getStart()); + dataStrobe = command.getIntervalOnDataStrobe(); + rec.updateDataStrobe(dataStrobe.start, dataStrobe.end, payload); + rec.recordPhase(payload, END_WRA, command.getEnd()); + dramPEQ.notify(payload, BEGIN_WRA, command.getStart() - sc_time_stamp()); dramPEQ.notify(payload, END_WRA, command.getEnd() - sc_time_stamp()); break; case Command::AutoRefresh: + rec.recordPhase(payload, BEGIN_AUTO_REFRESH, command.getStart()); + rec.recordPhase(payload, END_AUTO_REFRESH, command.getEnd()); + dramPEQ.notify(payload, BEGIN_AUTO_REFRESH, command.getStart() - sc_time_stamp()); dramPEQ.notify(payload, END_AUTO_REFRESH, command.getEnd() - sc_time_stamp()); break; case Command::Activate: + rec.recordPhase(payload, BEGIN_ACT, command.getStart()); + rec.recordPhase(payload, END_ACT, command.getEnd()); + dramPEQ.notify(payload, BEGIN_ACT, command.getStart() - sc_time_stamp()); dramPEQ.notify(payload, END_ACT, command.getEnd() - sc_time_stamp()); break; case Command::Precharge: + rec.recordPhase(payload, BEGIN_PRE, command.getStart()); + rec.recordPhase(payload, END_PRE, command.getEnd()); + dramPEQ.notify(payload, BEGIN_PRE, command.getStart() - sc_time_stamp()); dramPEQ.notify(payload, END_PRE, command.getEnd() - sc_time_stamp()); break; case Command::PrechargeAll: + rec.recordPhase(payload, BEGIN_PRE_ALL, command.getStart()); + rec.recordPhase(payload, END_PRE_ALL, command.getEnd()); + dramPEQ.notify(payload, BEGIN_PRE_ALL, command.getStart() - sc_time_stamp()); dramPEQ.notify(payload, END_PRE_ALL, command.getEnd() - sc_time_stamp()); break; case Command::PDNA: dramPEQ.notify(payload, BEGIN_PDNA, command.getStart() - sc_time_stamp()); + rec.recordPhase(payload, BEGIN_PDNA, command.getStart()); break; case Command::PDNP: dramPEQ.notify(payload, BEGIN_PDNP, command.getStart() - sc_time_stamp()); + rec.recordPhase(payload, BEGIN_PDNP, command.getStart()); break; case Command::SREF: dramPEQ.notify(payload, BEGIN_SREF, command.getStart() - sc_time_stamp()); + rec.recordPhase(payload, BEGIN_SREF, command.getStart()); break; case Command::PDNAX: dramPEQ.notify(payload, END_PDNA, command.getStart() - sc_time_stamp()); + rec.recordPhase(payload, END_PDNA, command.getStart()); break; case Command::PDNPX: dramPEQ.notify(payload, END_PDNP, command.getStart() - sc_time_stamp()); + rec.recordPhase(payload, END_PDNP, command.getStart()); break; case Command::SREFX: dramPEQ.notify(payload, END_SREF, command.getStart() - sc_time_stamp()); + rec.recordPhase(payload, END_SREF, command.getStart()); break; default: SC_REPORT_FATAL(0, "unsupported command in controller"); @@ -195,7 +238,7 @@ private: void scheduleNextPayload(Bank bank) { - if(bank.ID() == 5) + if (bank.ID() == 5) { int i = 5; ++i; @@ -282,8 +325,6 @@ private: void dramPEQCallback(tlm_generic_payload& payload, const tlm_phase& phase) { - TlmRecorder::getInstance().recordPhase(payload, phase, sc_time_stamp()); - Bank bank = DramExtension::getExtension(payload).getBank(); if (phase == BEGIN_RD || phase == BEGIN_WR) { @@ -303,7 +344,7 @@ private: payloadLeavesSystem(payload); scheduleNextPayload(bank); } - else if (isIn(phase, { BEGIN_ACT, BEGIN_PRE, BEGIN_PRE_ALL, BEGIN_RDA,BEGIN_WRA })) + else if (isIn(phase, { BEGIN_ACT, BEGIN_PRE, BEGIN_PRE_ALL, BEGIN_RDA, BEGIN_WRA })) { sendToDram(payload, phase, SC_ZERO_TIME); } diff --git a/dram/src/simulation/SimulationManager.cpp b/dram/src/simulation/SimulationManager.cpp index 9c9dd974..dbd96f8b 100644 --- a/dram/src/simulation/SimulationManager.cpp +++ b/dram/src/simulation/SimulationManager.cpp @@ -18,35 +18,38 @@ using namespace std; namespace simulation { SimulationManager::SimulationManager(sc_module_name name, string memconfig, string memspec, - string stl1, unsigned int burstlength1, string stl2, - unsigned int burstlenght2, string traceName, string pathToResources, - bool silent) : - dram("dram"), arbiter("arbiter"), controller("controller"), player1("player1", - pathToResources + string("traces/") + stl1,burstlength1, this), player2("player2", - pathToResources + string("traces/") + stl2,burstlenght2, this), traceName(traceName) + string stl1, unsigned int burstlength1, string stl2, unsigned int burstlenght2, + string traceName, string pathToResources, bool silent) : + traceName(traceName) { SC_THREAD(terminationThread); - cout << pathToResources + string("configs/memconfigs/") + memconfig << endl; - cout << pathToResources + string("configs/memspecs/") + memspec << endl; - - xmlAddressDecoder::addressConfigURI = pathToResources + string("configs/addressConfig.xml"); TlmRecorder::dbName = traceName; TlmRecorder::sqlScriptURI = pathToResources + string("scripts/createTraceDB.sql"); + Configuration::memconfigUri = pathToResources + string("configs/memconfigs/") + memconfig; + Configuration::memspecUri = pathToResources + string("configs/memspecs/") + memspec; - player1.iSocket.bind(arbiter.tSockets[0]); - player2.iSocket.bind(arbiter.tSockets[1]); - arbiter.iSocket.bind(controller.tSocket); - controller.iSocket.bind(dram.tSocket); + dram = new Dram<>("dram"); + arbiter = new Arbiter("arbiter"); + controller = new Controller<>("controller"); + player1 = new TracePlayer<>("player1", pathToResources + string("traces/") + stl1, burstlength1, + this); + player2 = new TracePlayer<>("player2", pathToResources + string("traces/") + stl2, burstlenght2, + this); + + player1->iSocket.bind(arbiter->tSockets[0]); + player2->iSocket.bind(arbiter->tSockets[1]); + arbiter->iSocket.bind(controller->tSocket); + controller->iSocket.bind(dram->tSocket); vector whiteList; - if(!silent) + if (!silent) { - whiteList.push_back(controller.name()); - whiteList.push_back(player2.name()); - whiteList.push_back(player1.name()); + 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); @@ -55,14 +58,24 @@ SimulationManager::SimulationManager(sc_module_name name, string memconfig, stri DebugManager::getInstance().addToWhiteList(whiteList); } +SimulationManager::~SimulationManager() +{ + delete dram; + delete arbiter; + delete controller; + delete player1; + delete player2; +} + + void SimulationManager::startSimulation() { clock_t begin = clock(); DebugManager::getInstance().printDebugMessage(name(), "Starting simulation"); - player1.start(); - player2.start(); + player1->start(); + player2->start(); sc_start(); clock_t end = clock(); @@ -87,13 +100,11 @@ void SimulationManager::terminationThread() { wait(terminateSimulation); DebugManager::getInstance().printDebugMessage(this->name(), "Terminating simulation"); - controller.terminateSimulation(); + controller->terminateSimulation(); //waits for the termination of all pending powerdown phases in the dram system wait(sc_time(50, SC_NS)); TlmRecorder::getInstance().closeConnection(); sc_stop(); } - - } /* namespace simulation */ diff --git a/dram/src/simulation/SimulationManager.h b/dram/src/simulation/SimulationManager.h index c1bb1a3f..fc7f0f52 100644 --- a/dram/src/simulation/SimulationManager.h +++ b/dram/src/simulation/SimulationManager.h @@ -26,6 +26,7 @@ public: std::string stl1, unsigned int burstlength1, std::string stl2, unsigned int burstlenght2, std::string traceName, std::string pathToResources, bool silent = false); + ~SimulationManager(); void startSimulation(); void tracePlayerFinishedCallback(string name) override; @@ -34,11 +35,11 @@ private: sc_event terminateSimulation; constexpr static unsigned int numberOfTracePlayers = 2; std::string traceName; - Dram<> dram; - Arbiter arbiter; - Controller<> controller; - TracePlayer<> player1; - TracePlayer<> player2; + Dram<> *dram; + Arbiter *arbiter; + Controller<> *controller; + TracePlayer<> *player1; + TracePlayer<> *player2; }; } /* namespace simulation */ diff --git a/dram/src/simulation/main.cpp b/dram/src/simulation/main.cpp index 7bb7f030..26a75e68 100644 --- a/dram/src/simulation/main.cpp +++ b/dram/src/simulation/main.cpp @@ -10,6 +10,8 @@ #include "SimulationManager.h" #include "../core/configuration/Configuration.h" +#include + using namespace std; using namespace simulation; @@ -32,21 +34,15 @@ int sc_main(int argc, char **argv) string resources = pathOfFile(argv[0]) + string("/../resources/"); string memconfig = "memconfig.xml"; - string memspec = "MatzesWideIO.xml"; + string memspec = "MICRON_4Gb_DDR4-1866_8bit_A.xml"; +// string memspec = "MatzesWideIO.xml"; string stl1 = "chstone-sha_32.stl"; stl1 = "empty.stl"; - unsigned int burstlength1 = 8; + unsigned int burstlength1 = 4; string stl2 = "mediabench-h263decode_32.stl"; - stl2 = "trace.stl"; - unsigned int burstlength2 = 8; - string traceName = "unaware_long.tdb"; - - Configuration::memspecUri = "/home/jonny/git/dram/dram/resources/configs/memspecs/MatzesWideIO.xml"; - Configuration::memspecUri = "/home/jonny/git/dram/dram/resources/configs/memspecs/MICRON_4Gb_DDR4-1866_8bit_A.xml"; - Configuration::memconfigUri = "/home/jonny/git/dram/dram/resources/configs/memconfigs/memconfig.xml"; - -// Configuration::memconfigUri = resources + string("configs/memconfigs/") + memconfig; -// Configuration::memconfigUri = resources + string("configs/memspecs/") + memspec; + // stl2 = "trace.stl"; + unsigned int burstlength2 = 4; + string traceName = "tpr.tdb"; SimulationManager simulationManager("sim",memconfig,memspec,stl1,burstlength1, stl2,burstlength2, traceName, resources,false); simulationManager.startSimulation();