diff --git a/DRAM/src/common/dramextension.cpp b/DRAM/src/common/dramextension.cpp index 2db16157..5a057f56 100644 --- a/DRAM/src/common/dramextension.cpp +++ b/DRAM/src/common/dramextension.cpp @@ -30,6 +30,7 @@ const DramExtension& DramExtension::getExtension(const tlm_generic_payload *payl return *result; } + bool operator ==(const Thread& lhs, const Thread& rhs) { return lhs.ID() == rhs.ID(); diff --git a/DRAM/src/core/Controller.cpp b/DRAM/src/core/Controller.cpp index 3644b47e..9fd7fae4 100644 --- a/DRAM/src/core/Controller.cpp +++ b/DRAM/src/core/Controller.cpp @@ -41,11 +41,22 @@ Controller::~Controller() commandChecker.clear(); } -bool Controller::schedule(sc_time currentTime, tlm::tlm_generic_payload* externalTransaction) +bool Controller::schedule(sc_time currentTime, tlm::tlm_generic_payload& externalTransaction) { - assert(currentTime == SC_ZERO_TIME); bus.cleanUpBus(currentTime); + CommandSequence sequence = commandSequenceGenerator.generateCommandSequence(externalTransaction); + CommandSchedule schedule = commandSequenceScheduler.prepareSchedule(currentTime, externalTransaction, sequence); + + while(refreshManager.hasCollision(schedule)) + { + refreshManager.scheduleRefresh(currentTime); + sequence = commandSequenceGenerator.generateCommandSequence(externalTransaction); + schedule = commandSequenceScheduler.prepareSchedule(currentTime, externalTransaction, sequence); + assert(schedule.getExecutionTime() < config.Timings.refreshTimings[0].tREFI);//TODO make nice + } + + bus.schedule(schedule); return true; } diff --git a/DRAM/src/core/Controller.h b/DRAM/src/core/Controller.h index fa2e3ffc..dcf442a4 100644 --- a/DRAM/src/core/Controller.h +++ b/DRAM/src/core/Controller.h @@ -26,7 +26,7 @@ public: Controller(); virtual ~Controller(); - bool schedule(sc_time currentTime, tlm::tlm_generic_payload* externalTransaction); //TODO return TLM status?? + bool schedule(sc_time currentTime, tlm::tlm_generic_payload& externalTransaction); //TODO return TLM status?? const ICommandChecker& getChecker(Command command) const; private: diff --git a/DRAM/src/core/refresh/RefreshManager.cpp b/DRAM/src/core/refresh/RefreshManager.cpp index c1813f07..f524e505 100644 --- a/DRAM/src/core/refresh/RefreshManager.cpp +++ b/DRAM/src/core/refresh/RefreshManager.cpp @@ -14,20 +14,27 @@ namespace controller { RefreshManager::RefreshManager(const RefreshTiming& refreshTiming, IInternalScheduler& internalScheduler) : - refreshTiming(refreshTiming), internalScheduler(internalScheduler), nextPlannedRefresh( - refreshTransaction, Command::Refresh, SC_ZERO_TIME, refreshTiming.tRFC) + refreshTiming(refreshTiming), internalScheduler(internalScheduler) { setupTransaction(refreshTransaction, Bank(0)); - planNextRefresh(nextPlannedRefresh); + nextPlannedRefresh = new ScheduledCommand(refreshTransaction, Command::Refresh, SC_ZERO_TIME, + refreshTiming.tRFC); + planNextRefresh(*nextPlannedRefresh); } RefreshManager::RefreshManager(const RefreshTiming& refreshTiming, IInternalScheduler& internalScheduler, Bank bank) : - refreshTiming(refreshTiming), internalScheduler(internalScheduler), nextPlannedRefresh( - refreshTransaction, Command::Refresh, SC_ZERO_TIME, refreshTiming.tRFC) + refreshTiming(refreshTiming), internalScheduler(internalScheduler) { setupTransaction(refreshTransaction, bank); - planNextRefresh(nextPlannedRefresh); + nextPlannedRefresh = new ScheduledCommand(refreshTransaction, Command::Refresh, SC_ZERO_TIME, + refreshTiming.tRFC); + planNextRefresh(*nextPlannedRefresh); +} + +RefreshManager::~RefreshManager() +{ + delete nextPlannedRefresh; } /* @@ -38,21 +45,20 @@ RefreshManager::RefreshManager(const RefreshTiming& refreshTiming, */ bool RefreshManager::hasCollision(const CommandSchedule& schedule) { - if (schedule.getEnd() < nextPlannedRefresh.getStart()) + if (schedule.getEnd() < nextPlannedRefresh->getStart()) { return false; } else { - scheduleRefresh(nextPlannedRefresh); return true; } } void RefreshManager::scheduleRefresh(sc_time time) { - if (time == nextPlannedRefresh.getStart()) - scheduleRefresh(nextPlannedRefresh); + if (time <= nextPlannedRefresh->getStart()) + scheduleRefresh(*nextPlannedRefresh); } void RefreshManager::scheduleRefresh(ScheduledCommand& refresh) diff --git a/DRAM/src/core/refresh/RefreshManager.h b/DRAM/src/core/refresh/RefreshManager.h index b5a96321..54a19d06 100644 --- a/DRAM/src/core/refresh/RefreshManager.h +++ b/DRAM/src/core/refresh/RefreshManager.h @@ -18,7 +18,7 @@ class RefreshManager : public IRefreshManager public: RefreshManager(const RefreshTiming& refreshTiming, IInternalScheduler& internalScheduler); RefreshManager(const RefreshTiming& refreshTiming, IInternalScheduler& internalScheduler, common::Bank bank); - virtual ~RefreshManager(){} + virtual ~RefreshManager(); virtual bool hasCollision(const CommandSchedule& schedule); virtual void scheduleRefresh(sc_time time); @@ -28,12 +28,12 @@ private: IInternalScheduler& internalScheduler; tlm::tlm_generic_payload refreshTransaction; - ScheduledCommand nextPlannedRefresh; + ScheduledCommand* nextPlannedRefresh; void scheduleRefresh(ScheduledCommand& refresh); void planNextRefresh(ScheduledCommand& refresh); - void setupTransaction(tlm::tlm_generic_payload& transaction, common::Bank bank); + static void setupTransaction(tlm::tlm_generic_payload& transaction, common::Bank bank); }; } /* namespace controller */ diff --git a/DRAM/src/core/scheduling/Command.h b/DRAM/src/core/scheduling/Command.h index cdaa83e0..d791a2a0 100644 --- a/DRAM/src/core/scheduling/Command.h +++ b/DRAM/src/core/scheduling/Command.h @@ -10,7 +10,7 @@ namespace controller { -enum class Command {Precharge, PrechargeAll, Activate, Read, Write, ReadA, WriteA, Refresh}; +enum class Command {NOP, Precharge, PrechargeAll, Activate, Read, Write, ReadA, WriteA, Refresh}; typedef std::vector CommandSequence; diff --git a/DRAM/src/core/scheduling/CommandBus.cpp b/DRAM/src/core/scheduling/CommandBus.cpp index 6b1c4a13..f69435a4 100644 --- a/DRAM/src/core/scheduling/CommandBus.cpp +++ b/DRAM/src/core/scheduling/CommandBus.cpp @@ -10,6 +10,15 @@ namespace controller { +void CommandBus::schedule(const CommandSchedule& schedule) +{ + const std::vector& commands = schedule.getScheduledCommands(); + + for(std::vector::const_iterator it = commands.begin();it != commands.end();++it) + { + scheduleCommand(*it); + } +} void CommandBus::scheduleCommand(const ScheduledCommand& command) { @@ -17,9 +26,10 @@ void CommandBus::scheduleCommand(const ScheduledCommand& command) changeControllerState(command); pendingBusCommands.insert(command.getStart()); - lastCommandsOnBus[command.getCommand()][command.getBank()] = command.getStart(); + lastCommandsOnBus[command.getCommand()][command.getBank()] = command; //notify tlm wrapper + lastCommandsOnBus[command.getCommand()][command.getBank()].invalidateTransaction(); } void CommandBus::scheduleTrigger(const Trigger command, sc_time time) @@ -27,21 +37,21 @@ void CommandBus::scheduleTrigger(const Trigger command, sc_time time) //notify tlm wrapper } -sc_time CommandBus::getLastCommand(Command command, common::Bank bank) +ScheduledCommand& CommandBus::getLastCommand(Command command, common::Bank bank) { return lastCommandsOnBus[command][bank]; } -sc_time CommandBus::getLastCommand(Command command) +ScheduledCommand& CommandBus::getLastCommand(Command command) { - sc_time max; + ScheduledCommand* max = &getLastCommand(command, common::Bank(0)); for (unsigned int i = 0; i < config.numberOfBanks; ++i) { - sc_time current = getLastCommand(command, common::Bank(i)); - if (current > max) + ScheduledCommand* current = &getLastCommand(command, common::Bank(i)); + if (current->getStart() > max->getStart()) max = current; } - return max; + return *max; } bool CommandBus::notYetScheduled(Command command) const @@ -49,6 +59,11 @@ bool CommandBus::notYetScheduled(Command command) const return (lastCommandsOnBus.count(command) == 0); } +bool CommandBus::notYetScheduled(Command command, common::Bank bank) const +{ + return (notYetScheduled(command) || lastCommandsOnBus.find(command)->second.count(bank) == 0); +} + sc_time CommandBus::getEarliestStartTime(const ScheduledCommand& command) const { sc_time newStart = command.getStart(); @@ -96,6 +111,7 @@ void CommandBus::refresh(const ScheduledCommand& command) { state.bankStates.closeAllRowBuffers(); } + } void CommandBus::precharge(const ScheduledCommand& command) @@ -119,3 +135,4 @@ void CommandBus::activate(const ScheduledCommand& command) } } /* namespace controller */ + diff --git a/DRAM/src/core/scheduling/CommandBus.h b/DRAM/src/core/scheduling/CommandBus.h index f2cebb38..0740b50a 100644 --- a/DRAM/src/core/scheduling/CommandBus.h +++ b/DRAM/src/core/scheduling/CommandBus.h @@ -23,14 +23,16 @@ class CommandBus : public IInternalScheduler { public: CommandBus(const Configuration& config, controller::ControllerState& state,std::vector& checker) : config(config), state(state), checker(checker) {} + virtual void schedule(const CommandSchedule& schedule);//TODO add to interface virtual void scheduleCommand(const ScheduledCommand& command); virtual void scheduleTrigger(const Trigger trigger, sc_time time); void cleanUpBus(sc_time currentTime); - sc_time getLastCommand(Command command, common::Bank bank);//TODO simple way to make it const? - sc_time getLastCommand(Command command); + ScheduledCommand& getLastCommand(Command command, common::Bank bank);//TODO simple way to make it const? + ScheduledCommand& getLastCommand(Command command); bool notYetScheduled(Command command) const; + bool notYetScheduled(Command command, common::Bank bank) const; sc_time getEarliestStartTime(const ScheduledCommand& command) const; const std::set& getPendingBusCommands() const {return pendingBusCommands;} @@ -40,13 +42,13 @@ private: controller::ControllerState& state; std::vector& checker; - std::map> lastCommandsOnBus; + std::map> lastCommandsOnBus; std::set pendingBusCommands; + void changeControllerState(const ScheduledCommand& command); void refresh(const ScheduledCommand& command); void precharge(const ScheduledCommand& command); void activate(const ScheduledCommand& command); - void changeControllerState(const ScheduledCommand& command); }; } diff --git a/DRAM/src/core/scheduling/CommandSchedule.h b/DRAM/src/core/scheduling/CommandSchedule.h index 4abb111a..087590e3 100644 --- a/DRAM/src/core/scheduling/CommandSchedule.h +++ b/DRAM/src/core/scheduling/CommandSchedule.h @@ -12,18 +12,24 @@ #include "common/dramextension.h" #include "ScheduledCommand.h" - namespace controller { -class CommandSchedule { +class CommandSchedule +{ public: - CommandSchedule(const tlm::tlm_generic_payload& transaction) : transaction(transaction) {}; - virtual ~CommandSchedule() {} + CommandSchedule(tlm::tlm_generic_payload& transaction) : + transaction(&transaction), extension(common::DramExtension::getExtension(&transaction)) + { + } + + virtual ~CommandSchedule() + { + } ScheduledCommand& add(Command command, sc_time time, sc_time executionTime) { assert(scheduledCommands.empty() || time >= scheduledCommands.back().getEnd()); - scheduledCommands.push_back(ScheduledCommand(transaction, command, time, executionTime)); + scheduledCommands.push_back(ScheduledCommand(*transaction, command, time, executionTime)); return scheduledCommands.back(); } @@ -49,12 +55,14 @@ public: common::Bank getBank() const { - return common::DramExtension::getExtension(&transaction).getBank(); + return extension.getBank(); } private: std::vector scheduledCommands; - const tlm::tlm_generic_payload& transaction; + tlm::tlm_generic_payload* transaction; + + common::DramExtension extension; }; } /* namespace controller */ diff --git a/DRAM/src/core/scheduling/ScheduledCommand.h b/DRAM/src/core/scheduling/ScheduledCommand.h index 8ceed8a9..cd3e4fb1 100644 --- a/DRAM/src/core/scheduling/ScheduledCommand.h +++ b/DRAM/src/core/scheduling/ScheduledCommand.h @@ -18,12 +18,24 @@ namespace controller { class ScheduledCommand { public: - ScheduledCommand(const tlm::tlm_generic_payload& transaction, Command command, sc_time time, + static const ScheduledCommand NoCommand; + + ScheduledCommand(tlm::tlm_generic_payload& transaction, Command command, sc_time time, sc_time executionTime) : - transaction(transaction), command(command), start(time), executionTime(executionTime) + transaction(&transaction), command(command), start(time), executionTime(executionTime), extension(common::DramExtension::getExtension(&transaction)) { } + ScheduledCommand() : + transaction(NULL), command(Command::NOP), start(SC_ZERO_TIME), executionTime(SC_ZERO_TIME), extension() + { + } + + bool isNoCommand() const + { + return (*this == ScheduledCommand::NoCommand); + } + const sc_time getStart() const { return start; @@ -49,33 +61,40 @@ public: return executionTime; } - const tlm::tlm_generic_payload& getTransaction() const + tlm::tlm_generic_payload& getTransaction() const { - return transaction; + assert(transaction); + return *transaction; } common::Bank getBank() const { - return common::DramExtension::getExtension(&transaction).getBank(); + return extension.getBank(); } common::Row getRow() const { - return common::DramExtension::getExtension(&transaction).getRow(); + return extension.getRow(); } inline bool operator==(const ScheduledCommand& b) const { - return b.command == command && b.start == start && b.executionTime == executionTime - && &b.transaction == &transaction; + return b.command == command && b.start == start && b.executionTime == executionTime; + } + + void invalidateTransaction() + { + transaction = NULL; } private: - const tlm::tlm_generic_payload& transaction; - const Command command; + tlm::tlm_generic_payload* transaction; + + Command command; sc_time start; sc_time executionTime; + common::DramExtension extension; }; } /* namespace controller */ diff --git a/DRAM/src/core/scheduling/checker/ActivateChecker.cpp b/DRAM/src/core/scheduling/checker/ActivateChecker.cpp index 326099d7..3fd6b39e 100644 --- a/DRAM/src/core/scheduling/checker/ActivateChecker.cpp +++ b/DRAM/src/core/scheduling/checker/ActivateChecker.cpp @@ -35,8 +35,8 @@ void ActivateChecker::check_activateToActivate(ScheduledCommand& command) const if (bus.notYetScheduled(Command::Activate)) return; - sc_time lastActivate = bus.getLastCommand(Command::Activate); - sc_time lastActivateOnBank = bus.getLastCommand(Command::Activate, command.getBank()); + sc_time lastActivate = bus.getLastCommand(Command::Activate).getStart(); + sc_time lastActivateOnBank = bus.getLastCommand(Command::Activate, command.getBank()).getStart(); command.delayStart(delayByConstraint(lastActivate, command.getStart(), config.Timings.tRRD)); command.delayStart( @@ -46,8 +46,8 @@ void ActivateChecker::check_activateToActivate(ScheduledCommand& command) const void ActivateChecker::check_prechargeToActivate(ScheduledCommand& command) const { sc_time lastPrechargeOnBank = std::max( - bus.getLastCommand(Command::Precharge, command.getBank()), - bus.getLastCommand(Command::PrechargeAll, command.getBank())); + bus.getLastCommand(Command::Precharge, command.getBank()).getStart(), + bus.getLastCommand(Command::PrechargeAll, command.getBank()).getStart()); command.delayStart( delayByConstraint(lastPrechargeOnBank, command.getStart(), config.Timings.tRC)); } diff --git a/DRAM/testing/BankwiseRefreshManager_test.cpp b/DRAM/testing/BankwiseRefreshManager_test.cpp index 6eb2b9bc..627f2810 100644 --- a/DRAM/testing/BankwiseRefreshManager_test.cpp +++ b/DRAM/testing/BankwiseRefreshManager_test.cpp @@ -69,8 +69,8 @@ TEST_F(BankwiseRefreshManagerTest, RefreshsAreScheduledAfterStartup) TEST_F(BankwiseRefreshManagerTest, hasCollisionExpectCollisionOnBank2) { - EXPECT_CALL(internalScheduler, scheduleTrigger(Trigger::RefreshTrigger, _)).Times(config.numberOfBanks + 1); - EXPECT_CALL(internalScheduler, scheduleCommand(_)).Times(1); + EXPECT_CALL(internalScheduler, scheduleTrigger(Trigger::RefreshTrigger, _)).Times(config.numberOfBanks); + EXPECT_CALL(internalScheduler, scheduleCommand(_)).Times(0); BankwiseRefreshManager manager(config.Timings.refreshTimings, internalScheduler); EXPECT_TRUE(manager.hasCollision(getCollidingWithFirstRefreshOnBank(2))); diff --git a/DRAM/testing/CommandBus_test.cpp b/DRAM/testing/CommandBus_test.cpp index cb7eedd5..32d28cae 100644 --- a/DRAM/testing/CommandBus_test.cpp +++ b/DRAM/testing/CommandBus_test.cpp @@ -93,9 +93,9 @@ TEST_F(CommandBusTest, getLastCommandWorks) bus.scheduleCommand(read0); bus.scheduleCommand(read2); - EXPECT_EQ(2*clk, bus.getLastCommand(Command::Read, read0.getBank())); - EXPECT_EQ(3*clk, bus.getLastCommand(Command::Read, read2.getBank())); - EXPECT_EQ(3*clk, bus.getLastCommand(Command::Read)); + EXPECT_EQ(read0, bus.getLastCommand(Command::Read, read0.getBank())); + EXPECT_EQ(read2, bus.getLastCommand(Command::Read, read2.getBank())); + EXPECT_EQ(read2.getStart(), bus.getLastCommand(Command::Read).getStart()); } TEST_F(CommandBusTest, notYetScheduledWorks) diff --git a/DRAM/testing/RefreshManager_test.cpp b/DRAM/testing/RefreshManager_test.cpp index 222baa6a..57243419 100644 --- a/DRAM/testing/RefreshManager_test.cpp +++ b/DRAM/testing/RefreshManager_test.cpp @@ -86,8 +86,8 @@ TEST_F(RefreshManagerTest, FinishedRefreshTriggersNewRefresh) TEST_F(RefreshManagerTest, hasCollisionExpectCollision) { - EXPECT_CALL(internalScheduler, scheduleTrigger(Trigger::RefreshTrigger, _)).Times(2); - EXPECT_CALL(internalScheduler, scheduleCommand(_)).Times(1); + EXPECT_CALL(internalScheduler, scheduleTrigger(Trigger::RefreshTrigger, _)).Times(1); + EXPECT_CALL(internalScheduler, scheduleCommand(_)).Times(0); RefreshManager manager(config.Timings.refreshTimings.at(0), internalScheduler);