From 75a5dca81e934748c5704b873957e8572302ddc5 Mon Sep 17 00:00:00 2001 From: robert Date: Sun, 30 Mar 2014 12:52:12 +0200 Subject: [PATCH] all constraints implemented --- dram/resources/scripts/sampleStlGeneration.py | 11 +-- dram/resources/scripts/stlGenerator.py | 2 +- dram/src/common/DebugManager.cpp | 5 + dram/src/common/DebugManager.h | 3 + dram/src/core/Configuration.h | 2 +- dram/src/core/Controller.cpp | 22 ++--- dram/src/core/Controller.h | 3 - dram/src/core/ControllerState.cpp | 41 +++++++- dram/src/core/ControllerState.h | 26 +++-- dram/src/core/Slots.cpp | 73 ++++++++++++++ dram/src/core/Slots.h | 35 +++++++ dram/src/core/TimingConfiguration.h | 10 +- .../core/refresh/RefreshManagerBankwise.cpp | 4 +- .../scheduling/CommandSequenceScheduler.cpp | 15 ++- dram/src/core/scheduling/ScheduledCommand.h | 13 ++- .../scheduling/checker/ActivateChecker.cpp | 33 ++++--- .../core/scheduling/checker/BusChecker.cpp | 29 ------ dram/src/core/scheduling/checker/BusChecker.h | 30 ------ .../scheduling/checker/PrechargeChecker.cpp | 28 +++++- .../core/scheduling/checker/ReadChecker.cpp | 94 +++++++++++++++++-- .../src/core/scheduling/checker/ReadChecker.h | 2 + .../core/scheduling/checker/WriteChecker.cpp | 82 +++++++++++++++- .../core/scheduling/checker/WriteChecker.h | 2 + dram/src/core/utils/Utils.cpp | 23 ++++- dram/src/core/utils/Utils.h | 20 +++- dram/src/simulation/main.cpp | 9 +- 26 files changed, 471 insertions(+), 146 deletions(-) create mode 100644 dram/src/core/Slots.cpp create mode 100644 dram/src/core/Slots.h delete mode 100644 dram/src/core/scheduling/checker/BusChecker.cpp delete mode 100644 dram/src/core/scheduling/checker/BusChecker.h diff --git a/dram/resources/scripts/sampleStlGeneration.py b/dram/resources/scripts/sampleStlGeneration.py index 202e9c15..b9c4afac 100644 --- a/dram/resources/scripts/sampleStlGeneration.py +++ b/dram/resources/scripts/sampleStlGeneration.py @@ -7,12 +7,11 @@ def simple_frfcfs(): stlGenerator.clear() stlGenerator.addAction(0, 0) stlGenerator.addAction(0, 1) - stlGenerator.addAction(0, 0) - - stlGenerator.addAction(0, 1) - stlGenerator.addAction(0, 0) - stlGenerator.addAction(0, 1) - stlGenerator.generateStl('test2.stl') + stlGenerator.addAction(2, 0) + stlGenerator.addAction(3, 0) + stlGenerator.addAction(4, 0) + stlGenerator.addAction(5, 0) + stlGenerator.generateStl('../traces/test2.stl') if __name__ == '__main__': simple_frfcfs(); diff --git a/dram/resources/scripts/stlGenerator.py b/dram/resources/scripts/stlGenerator.py index 3b78064e..7aa7552d 100644 --- a/dram/resources/scripts/stlGenerator.py +++ b/dram/resources/scripts/stlGenerator.py @@ -22,7 +22,7 @@ class DramConfigReader: def __init__(self): root = ET.parse( - os.path.dirname(os.path.realpath(sys.argv[0])) + '/addressConfig.xml').getroot() + os.path.dirname(os.path.realpath(sys.argv[0])) + '/../configs/addressConfig.xml').getroot() self.__extractAdressEncoding(root, 'channel') self.__extractAdressEncoding(root, 'bank') self.__extractAdressEncoding(root, 'row') diff --git a/dram/src/common/DebugManager.cpp b/dram/src/common/DebugManager.cpp index b0b1d8a8..8a96c59c 100644 --- a/dram/src/common/DebugManager.cpp +++ b/dram/src/common/DebugManager.cpp @@ -72,3 +72,8 @@ string DebugManager::senderToString(Sender sender) } return "unknown sender"; } + +void reportFatal(std::string sender, std::string message) +{ + SC_REPORT_FATAL(sender.c_str(), message.c_str()); +} diff --git a/dram/src/common/DebugManager.h b/dram/src/common/DebugManager.h index 528a122e..7d708128 100644 --- a/dram/src/common/DebugManager.h +++ b/dram/src/common/DebugManager.h @@ -13,6 +13,9 @@ enum class Importance {Warning, Info}; enum class Sender {DramController, DramWrapper, Scheduler, TracePlayer, TraceRecorder}; +void reportFatal(std::string sender, std::string message); + + class DebugManager { public: diff --git a/dram/src/core/Configuration.h b/dram/src/core/Configuration.h index 90a88619..a0d47ad8 100644 --- a/dram/src/core/Configuration.h +++ b/dram/src/core/Configuration.h @@ -15,7 +15,7 @@ namespace core{ struct Configuration { - Configuration(): numberOfBanks(8), burstlength(2), Timings(numberOfBanks), RefreshBankwise(false), + Configuration(): numberOfBanks(8), burstlength(2), Timings(numberOfBanks), RefreshBankwise(true), nActivate(2) {} unsigned int numberOfBanks; diff --git a/dram/src/core/Controller.cpp b/dram/src/core/Controller.cpp index b7a36690..29981864 100644 --- a/dram/src/core/Controller.cpp +++ b/dram/src/core/Controller.cpp @@ -17,10 +17,8 @@ namespace core { Controller::Controller(IWrapperConnector& wrapperConnector, TlmRecorder& recorder) : - config(), state(config.numberOfBanks, config.nActivate), busChecker(config, state), wrapper( - wrapperConnector), commandChecker(), recorder(recorder), savedState( - config.numberOfBanks, config.nActivate), commandSequenceGenerator(state), commandSequenceScheduler( - *this) + config(), state(&config), wrapper(wrapperConnector), commandChecker(), recorder(recorder), savedState( + &config), commandSequenceGenerator(state), commandSequenceScheduler(*this) { commandChecker[Command::Activate] = new ActivateChecker(config, state); @@ -28,7 +26,7 @@ Controller::Controller(IWrapperConnector& wrapperConnector, TlmRecorder& recorde commandChecker[Command::Read] = new ReadChecker(config, state); commandChecker[Command::Write] = new WriteChecker(config, state); - if(config.RefreshBankwise) + if (config.RefreshBankwise) refreshManager = new RefreshManagerBankwise(*this); else refreshManager = new RefreshManager(*this); @@ -55,15 +53,14 @@ void Controller::resetState() void Controller::scheduleRefresh(tlm::tlm_generic_payload& payload, sc_time time) { - cleanUpBus(time); + state.cleanUp(time); refreshManager->scheduleRefresh(payload, time); } bool Controller::schedule(sc_time start, tlm::tlm_generic_payload& payload) { - cleanUpBus(start); - start = clkAlign(start, config.Timings.clk); + state.cleanUp(start); payload.set_streaming_width(config.burstlength); saveState(); @@ -85,7 +82,7 @@ bool Controller::schedule(sc_time start, tlm::tlm_generic_payload& payload) bool Controller::isBusy(sc_time currentTime, Bank bank) { - ScheduledCommand lastScheduledCommand = state.getLastCommand(bank); + ScheduledCommand lastScheduledCommand = state.getLastScheduledCommand(bank); if (lastScheduledCommand.isNoCommand()) return false; else if (lastScheduledCommand.getCommand() == Command::Write @@ -113,12 +110,5 @@ void Controller::send(const CommandSchedule& schedule) const } } - -void Controller::cleanUpBus(sc_time currentTime) -{ - state.pendingBusCommands.erase(state.pendingBusCommands.begin(), - state.pendingBusCommands.lower_bound(currentTime)); -} - } /* namespace controller */ diff --git a/dram/src/core/Controller.h b/dram/src/core/Controller.h index 2cad8892..33f6e2fb 100644 --- a/dram/src/core/Controller.h +++ b/dram/src/core/Controller.h @@ -16,7 +16,6 @@ #include "refresh/IRefreshManager.h" #include "scheduling/CommandSequenceGenerator.h" #include "scheduling/checker/ICommandChecker.h" -#include "scheduling/checker/BusChecker.h" #include "scheduling/CommandSequenceScheduler.h" #include "../common/TlmRecorder.h" @@ -39,12 +38,10 @@ public: void saveState(); void resetState(); - void cleanUpBus(sc_time time); void send(const CommandSchedule& schedule) const; Configuration config; ControllerState state; - BusChecker busChecker; IWrapperConnector& wrapper; std::map commandChecker; TlmRecorder& recorder; diff --git a/dram/src/core/ControllerState.cpp b/dram/src/core/ControllerState.cpp index 90a1314a..7adabe6f 100644 --- a/dram/src/core/ControllerState.cpp +++ b/dram/src/core/ControllerState.cpp @@ -6,6 +6,7 @@ */ #include "ControllerState.h" +#include namespace core { @@ -27,7 +28,7 @@ const ScheduledCommand ControllerState::getLastCommand(Command command) return max; } -const ScheduledCommand ControllerState::getLastCommand(Bank bank) +const ScheduledCommand ControllerState::getLastScheduledCommand(Bank bank) { ScheduledCommand lastCommand; for (std::map >::iterator it = @@ -42,23 +43,39 @@ const ScheduledCommand ControllerState::getLastCommand(Bank bank) void ControllerState::change(const ScheduledCommand& scheduledCommand) { - pendingBusCommands.insert(scheduledCommand.getStart()); + bus.blockSlot(scheduledCommand.getStart()); lastCommandsOnBus[scheduledCommand.getCommand()][scheduledCommand.getBank()] = scheduledCommand; lastCommandsOnBus[scheduledCommand.getCommand()][scheduledCommand.getBank()].invalidateTransaction(); switch (scheduledCommand.getCommand()) { + case Command::Read: + lastDataStrobeCommands.emplace_back(scheduledCommand); + break; + case Command::ReadA: + bankStates.closeRowBuffer(scheduledCommand.getBank()); + lastDataStrobeCommands.emplace_back(scheduledCommand); + break; + case Command::Write: + lastDataStrobeCommands.emplace_back(scheduledCommand); + break; + case Command::WriteA: + bankStates.closeRowBuffer(scheduledCommand.getBank()); + lastDataStrobeCommands.emplace_back(scheduledCommand); + break; case Command::AutoRefresh: break; case Command::Activate: bankStates.openRowInRowBuffer(scheduledCommand.getBank(), scheduledCommand.getRow()); nActivateWindow.put(scheduledCommand.getStart()); + activates.blockSlots(scheduledCommand.getStart() - config->Timings.tRRD, + scheduledCommand.getStart() + config->Timings.tRRD, true); break; case Command::Precharge: bankStates.closeRowBuffer(scheduledCommand.getBank()); break; case Command::PrechargeAll: - bankStates.closeAllRowBuffers(); + bankStates.closeAllRowBuffers(); break; default: break; @@ -66,5 +83,21 @@ void ControllerState::change(const ScheduledCommand& scheduledCommand) } -} /* namespace controller */ +void ControllerState::cleanUp(sc_time time) +{ + bus.cleanUpSlots(time); + activates.cleanUpSlots(time); + //remove_if(lastDataStrobeCommands.begin(),lastDataStrobeCommands.end(), [&](ScheduledCommand command){return command.getEnd() < time;}); + vector tmp; + for(ScheduledCommand& command: lastDataStrobeCommands) + { + if(command.getEnd() >= time ) + { + tmp.emplace_back(command); + } + } + lastDataStrobeCommands = tmp; +} + +} /* namespace controller */ diff --git a/dram/src/core/ControllerState.h b/dram/src/core/ControllerState.h index d37b627e..acb5d65b 100644 --- a/dram/src/core/ControllerState.h +++ b/dram/src/core/ControllerState.h @@ -12,32 +12,44 @@ #include "BankStates.h" #include "utils/RingBuffer.h" #include "scheduling/ScheduledCommand.h" +#include "Slots.h" +#include "Configuration.h" #include #include #include namespace core { -class ControllerState { +class ControllerState +{ public: - ControllerState(unsigned int numberOfBanks, unsigned int nActivates) : bankStates(numberOfBanks), nActivateWindow(nActivates){} - virtual ~ControllerState(){} + ControllerState(Configuration* config) : + bankStates(config->numberOfBanks), nActivateWindow(config->nActivate), bus( + config->Timings.clk), activates(config->Timings.clk), config(config) + { + } + virtual ~ControllerState() + { + } const ScheduledCommand getLastCommand(Command command, Bank bank); const ScheduledCommand getLastCommand(Command command); - const ScheduledCommand getLastCommand(Bank bank); + const ScheduledCommand getLastScheduledCommand(Bank bank); void change(const ScheduledCommand& scheduledCommand); + void cleanUp(sc_time time); BankStates bankStates; //used by the various checkers RingBuffer nActivateWindow; - std::vector nACT; std::map > lastCommandsOnBus; - std::set pendingBusCommands; -private: + Slots bus; + Slots activates; + std::vector lastDataStrobeCommands; +private: + Configuration* config; }; } /* namespace controller */ diff --git a/dram/src/core/Slots.cpp b/dram/src/core/Slots.cpp new file mode 100644 index 00000000..e8195bc5 --- /dev/null +++ b/dram/src/core/Slots.cpp @@ -0,0 +1,73 @@ +/* + * Slots.cpp + * + * Created on: Mar 29, 2014 + * Author: robert + */ + +#include "Slots.h" +#include "utils/Utils.h" + +namespace core { + +Slots::Slots(sc_time clk) : + clk(clk) +{ + +} + +Slots::~Slots() +{ +} + +void Slots::moveCommandToNextFreeSlot(ScheduledCommand& command) +{ + sc_time newStart = command.getStart(); + + sc_assert(isClkAligned(newStart, clk)); + std::set::iterator it = slotSet.begin(); + + while (it != slotSet.end() && *it <= newStart) + { + if (*it == newStart) + newStart += clk; + ++it; + } + command.setStart(newStart); +} + +void Slots::cleanUpSlots(sc_time time) +{ + slotSet.erase(slotSet.begin(), slotSet.lower_bound(time)); +} + +void Slots::blockSlot(sc_time time) +{ + sc_assert(isClkAligned(time, clk)); + slotSet.insert(time); +} + +bool Slots::isFree(sc_time time) +{ + return (slotSet.count(time) == 0); +} + +void Slots::blockSlots(sc_time begin, sc_time end, bool excludeBorders) +{ + sc_assert(isClkAligned(begin, clk)); + sc_assert(isClkAligned(end, clk)); + + if (excludeBorders) + { + begin += clk; + end -= clk; + } + + for (sc_time time = begin; time <= end; time += clk) + { + slotSet.insert(time); + } + +} + +} /* namespace core */ diff --git a/dram/src/core/Slots.h b/dram/src/core/Slots.h new file mode 100644 index 00000000..3c2c1e75 --- /dev/null +++ b/dram/src/core/Slots.h @@ -0,0 +1,35 @@ +/* + * Slots.h + * + * Created on: Mar 29, 2014 + * Author: robert + */ + +#ifndef SLOTS_H_ +#define SLOTS_H_ +#include +#include +#include "scheduling/ScheduledCommand.h" + +namespace core { + +class Slots +{ +public: + Slots(sc_time clk); + virtual ~Slots(); + void moveCommandToNextFreeSlot(ScheduledCommand& command); + void cleanUpSlots(sc_time time); + void blockSlots(sc_time begin, sc_time end, bool excludeBorders); + void blockSlot(sc_time time); + bool isFree(sc_time); + +private: + std::set slotSet; + sc_time clk; + +}; + +} /* namespace core */ + +#endif /* SLOTS_H_ */ diff --git a/dram/src/core/TimingConfiguration.h b/dram/src/core/TimingConfiguration.h index 71319a24..774793ba 100644 --- a/dram/src/core/TimingConfiguration.h +++ b/dram/src/core/TimingConfiguration.h @@ -45,8 +45,11 @@ struct TimingConfiguration tRCD = 3*clk; //act -> read/write tRL = 3*clk; //read latency (read command start to data strobe) - + tWL = 1*clk; //write latency tTAW = 48*clk; //two activate window + tRR = 2*clk; //min read to read on same rank + tWW = 1*clk; //min write to write on same rank + tWTR = 3*clk;//write to read } sc_time clk; @@ -57,6 +60,11 @@ struct TimingConfiguration sc_time tRCD; sc_time tTAW; sc_time tRL; + sc_time tWL; + sc_time tWTR; + + sc_time tRR; + sc_time tWW; std::vector refreshTimings; diff --git a/dram/src/core/refresh/RefreshManagerBankwise.cpp b/dram/src/core/refresh/RefreshManagerBankwise.cpp index 877f0f59..b61ae684 100644 --- a/dram/src/core/refresh/RefreshManagerBankwise.cpp +++ b/dram/src/core/refresh/RefreshManagerBankwise.cpp @@ -81,13 +81,13 @@ void RefreshManagerBankwise::RefreshManagerForBank::scheduleRefresh(sc_time time ScheduledCommand precharge(refreshPayload, Command::Precharge, time, controller.config.Timings.tRP); - controller.busChecker.findSlotOnBus(precharge); + controller.state.bus.moveCommandToNextFreeSlot(precharge); nextRefresh.setStart(precharge.getEnd()); controller.state.change(precharge); controller.wrapper.send(precharge); } - controller.busChecker.findSlotOnBus(nextRefresh); + controller.state.bus.moveCommandToNextFreeSlot(nextRefresh); controller.state.change(nextRefresh); controller.wrapper.send(nextRefresh); diff --git a/dram/src/core/scheduling/CommandSequenceScheduler.cpp b/dram/src/core/scheduling/CommandSequenceScheduler.cpp index 05787ccf..ebe96515 100644 --- a/dram/src/core/scheduling/CommandSequenceScheduler.cpp +++ b/dram/src/core/scheduling/CommandSequenceScheduler.cpp @@ -7,6 +7,7 @@ #include "CommandSequenceScheduler.h" #include "../Controller.h" +#include "../../common/DebugManager.h" namespace core { @@ -15,18 +16,24 @@ CommandSchedule CommandSequenceScheduler::schedule(CommandSequence commands, sc_ { CommandSchedule schedule(transaction); - sc_time endOfPrevious = start; for (Command cmd : commands) { + if(start >= sc_time(28723164,SC_NS)) + { + int i = 5; + i++; + } + + DebugManager::getInstance().printDebugMessage("Scheduling command " + commandToString(cmd),Sender::DramWrapper); + ICommandChecker& checker = *controller.commandChecker.at(cmd); sc_time executionTime = checker.getExecutionTime(transaction, cmd); - ScheduledCommand& scheduledCommand = schedule.add(cmd, endOfPrevious, executionTime); + ScheduledCommand& scheduledCommand = schedule.add(cmd, start, executionTime); checker.delayToSatisfyConstraints(scheduledCommand); - controller.busChecker.findSlotOnBus(scheduledCommand); + sc_assert(scheduledCommand.getStart()>=start && scheduledCommand.getStart() < scheduledCommand.getEnd()); controller.state.change(scheduledCommand); - endOfPrevious = scheduledCommand.getEnd(); } return schedule; diff --git a/dram/src/core/scheduling/ScheduledCommand.h b/dram/src/core/scheduling/ScheduledCommand.h index 75f7dc08..8b495c75 100644 --- a/dram/src/core/scheduling/ScheduledCommand.h +++ b/dram/src/core/scheduling/ScheduledCommand.h @@ -22,13 +22,13 @@ public: ScheduledCommand(tlm::tlm_generic_payload& payload, Command command, sc_time time, sc_time executionTime) : - payload(&payload), command(command), start(time), executionTime(executionTime), extension( - DramExtension::getExtension(payload)) + payload(&payload), command(command), start(time), executionTime(executionTime), burstLength(payload.get_streaming_width()), + extension(DramExtension::getExtension(payload)) { } ScheduledCommand() : - payload(NULL), command(Command::NOP), start(SC_ZERO_TIME), executionTime(SC_ZERO_TIME), extension() + payload(NULL), command(Command::NOP), start(SC_ZERO_TIME), executionTime(SC_ZERO_TIME), burstLength(0), extension() { } @@ -88,6 +88,10 @@ public: return extension.getRow(); } + unsigned int getBurstLength() + { + return burstLength; + } inline bool operator==(const ScheduledCommand& b) const { return b.command == command && b.start == start && b.executionTime == executionTime; @@ -99,13 +103,14 @@ public: } + private: tlm::tlm_generic_payload* payload; Command command; sc_time start; sc_time executionTime; - + unsigned int burstLength; DramExtension extension; }; diff --git a/dram/src/core/scheduling/checker/ActivateChecker.cpp b/dram/src/core/scheduling/checker/ActivateChecker.cpp index dc1a1078..adeec7bb 100644 --- a/dram/src/core/scheduling/checker/ActivateChecker.cpp +++ b/dram/src/core/scheduling/checker/ActivateChecker.cpp @@ -9,7 +9,7 @@ #include #include "../../utils/Utils.h" #include "ActivateChecker.h" - +#include "../../../common/DebugManager.h" #include namespace core { @@ -17,16 +17,24 @@ namespace core { void ActivateChecker::delayToSatisfyConstraints(ScheduledCommand& command) const { sc_assert(command.getCommand() == Command::Activate); - ScheduledCommand lastCommandOnBank = state.getLastCommand(command.getBank()); + ScheduledCommand lastCommandOnBank = state.getLastScheduledCommand(command.getBank()); - if(lastCommandOnBank.isValidCommand()) - //implies precharge to activate (tRP) and refresh to activate (tFRC) - sc_assert(command.getStart() >= state.getLastCommand(command.getBank()).getStart()); + if (lastCommandOnBank.isValidCommand()) + { + Command lastCommand = lastCommandOnBank.getCommand(); + if (lastCommand == Command::Precharge || lastCommand == Command::PrechargeAll + || lastCommand == Command::AutoRefresh || lastCommand == Command::ReadA + || lastCommand == Command::WriteA) + command.delayStart(getDelayToMeetConstraint(lastCommandOnBank.getEnd(),command.getStart(), SC_ZERO_TIME)); + else + reportFatal("Activate Checker", "Activate can not follow " + commandToString(lastCommandOnBank.getCommand())); + } satisfy_activateToActivate_sameBank(command); satisfy_activateToActivate_differentBank(command); satisfy_nActivateWindow(command); + state.bus.moveCommandToNextFreeSlot(command); } sc_time ActivateChecker::getExecutionTime(const tlm::tlm_generic_payload& transaction, @@ -38,20 +46,19 @@ sc_time ActivateChecker::getExecutionTime(const tlm::tlm_generic_payload& transa void ActivateChecker::satisfy_activateToActivate_differentBank(ScheduledCommand& command) const { - ScheduledCommand lastActivate = state.getLastCommand(Command::Activate); - if (lastActivate.isValidCommand()) - command.delayStart( - delayByConstraint(lastActivate.getStart(), command.getStart(), - config.Timings.tRRD)); + state.activates.moveCommandToNextFreeSlot(command); } void ActivateChecker::satisfy_activateToActivate_sameBank(ScheduledCommand& command) const { - ScheduledCommand lastActivateOnBank = state.getLastCommand(Command::Activate, command.getBank()); + ScheduledCommand lastActivateOnBank = state.getLastCommand(Command::Activate, + command.getBank()); if (lastActivateOnBank.isValidCommand()) + { command.delayStart( - delayByConstraint(lastActivateOnBank.getStart(), command.getStart(), + getDelayToMeetConstraint(lastActivateOnBank.getStart(), command.getStart(), config.Timings.tRC)); + } } void ActivateChecker::satisfy_nActivateWindow(ScheduledCommand& command) const @@ -60,7 +67,7 @@ void ActivateChecker::satisfy_nActivateWindow(ScheduledCommand& command) const return; command.delayStart( - delayByConstraint(state.nActivateWindow.getOldest(), command.getStart(), + getDelayToMeetConstraint(state.nActivateWindow.getOldest(), command.getStart(), config.Timings.tTAW)); } diff --git a/dram/src/core/scheduling/checker/BusChecker.cpp b/dram/src/core/scheduling/checker/BusChecker.cpp deleted file mode 100644 index df560d20..00000000 --- a/dram/src/core/scheduling/checker/BusChecker.cpp +++ /dev/null @@ -1,29 +0,0 @@ -/* - * BusChecker.cpp - * - * Created on: Mar 21, 2014 - * Author: jonny - */ - -#include "BusChecker.h" - -namespace core { - -void BusChecker::findSlotOnBus(ScheduledCommand& command) -{ - sc_time newStart = command.getStart(); - - sc_assert(isClkAligned(newStart, config.Timings.clk)); - std::set::iterator it = state.pendingBusCommands.begin(); - - while (it != state.pendingBusCommands.end() && *it <= newStart) - { - if (*it == newStart) - newStart += config.Timings.clk; - ++it; - } - command.setStart(newStart); -} - -} /* namespace core */ - diff --git a/dram/src/core/scheduling/checker/BusChecker.h b/dram/src/core/scheduling/checker/BusChecker.h deleted file mode 100644 index ed9abcf1..00000000 --- a/dram/src/core/scheduling/checker/BusChecker.h +++ /dev/null @@ -1,30 +0,0 @@ -/* - * BusChecker.h - * - * Created on: Mar 21, 2014 - * Author: jonny - */ - -#ifndef BUSCHECKER_H_ -#define BUSCHECKER_H_ - -#include "../../Configuration.h" -#include "../../ControllerState.h" - -namespace core { - -class BusChecker -{ -public: - BusChecker(const Configuration& config, ControllerState& state) : config(config), state(state){} - ~BusChecker(){} - - void findSlotOnBus(ScheduledCommand& command); - - const Configuration& config; - ControllerState& state; -}; - -} /* namespace controller */ - -#endif /* BUSCHECKER_H_ */ diff --git a/dram/src/core/scheduling/checker/PrechargeChecker.cpp b/dram/src/core/scheduling/checker/PrechargeChecker.cpp index a5ede2a0..634a7634 100644 --- a/dram/src/core/scheduling/checker/PrechargeChecker.cpp +++ b/dram/src/core/scheduling/checker/PrechargeChecker.cpp @@ -11,10 +11,30 @@ namespace core { void PrechargeChecker::delayToSatisfyConstraints(ScheduledCommand& command) const { - sc_assert(command.getCommand() == Command::Precharge || command.getCommand() == Command::PrechargeAll); - ScheduledCommand lastCommandOnBank = state.getLastCommand(command.getBank()); - if(lastCommandOnBank.isValidCommand()) - sc_assert(command.getStart() >= state.getLastCommand(command.getBank()).getStart()); + sc_assert(command.getCommand() == Command::Precharge || command.getCommand() == Command::PrechargeAll); + ScheduledCommand lastCommandOnBank = state.getLastScheduledCommand(command.getBank()); + + if (lastCommandOnBank.isValidCommand()) + { + if (lastCommandOnBank.getCommand() == Command::Read) + { + command.delayStart( + getDelayToMeetConstraint(lastCommandOnBank.getStart(), command.getStart(), + lastCommandOnBank.getBurstLength() * config.Timings.clk)); + } + else if (lastCommandOnBank.getCommand() == Command::Write) + { + command.delayStart( + getDelayToMeetConstraint(lastCommandOnBank.getStart(), command.getStart(), + (lastCommandOnBank.getBurstLength() - 1) * config.Timings.clk + + config.Timings.tWL)); + } + else + reportFatal("Precharge Checker", + "Precharge can not follow " + commandToString(lastCommandOnBank.getCommand())); + } + + state.bus.moveCommandToNextFreeSlot(command); } sc_time PrechargeChecker::getExecutionTime(const tlm::tlm_generic_payload& payload, diff --git a/dram/src/core/scheduling/checker/ReadChecker.cpp b/dram/src/core/scheduling/checker/ReadChecker.cpp index ff633b0e..6846fbc4 100644 --- a/dram/src/core/scheduling/checker/ReadChecker.cpp +++ b/dram/src/core/scheduling/checker/ReadChecker.cpp @@ -12,21 +12,103 @@ namespace core { void ReadChecker::delayToSatisfyConstraints(ScheduledCommand& command) const { - ScheduledCommand lastCommand = state.getLastCommand(command.getBank()); - if(lastCommand.isValidCommand() && lastCommand.getEnd() > command.getStart()) + assert(command.getCommand() == Command::Read || command.getCommand() == Command::ReadA); + + ScheduledCommand lastCommandOnBank = state.getLastScheduledCommand(command.getBank()); + + if (lastCommandOnBank.isValidCommand()) { - command.delayStart(lastCommand.getEnd()-command.getStart()); + if (lastCommandOnBank.getCommand() == Command::Activate) + { + command.delayStart(getDelayToMeetConstraint(lastCommandOnBank.getEnd(),command.getStart(), SC_ZERO_TIME)); + } + else if (lastCommandOnBank.getCommand() == Command::Read + || lastCommandOnBank.getCommand() == Command::Write) + { + } + else + reportFatal("Read Checker", + "Read can not follow " + commandToString(lastCommandOnBank.getCommand())); } + while (!state.bus.isFree(command.getStart()) || collidesOnDataStrobe(command)) + { + command.delayStart(config.Timings.clk); + } } sc_time ReadChecker::getExecutionTime(const tlm::tlm_generic_payload& payload, Command command) const { assert(command == Command::Read || command == Command::ReadA); - //return config.Timings.tRL + config.Timings.clk*getBurstLengthInBytes(transaction, config.buswidth); - sc_time result = config.Timings.tRL + config.Timings.clk*payload.get_streaming_width(); - return result; + + if (command == Command::Read) + { + return config.Timings.tRL + config.Timings.clk * payload.get_streaming_width(); + } + else + { + return config.Timings.tRL + config.Timings.clk * payload.get_streaming_width() + + config.Timings.tRP; + } +} + +bool ReadChecker::collidesOnDataStrobe(ScheduledCommand& read) const +{ + for (ScheduledCommand& strobeCommand : state.lastDataStrobeCommands) + { + if (collidesWithStrobeCommand(read, strobeCommand)) + return true; + } + + return false; +} + +bool ReadChecker::collidesWithStrobeCommand(ScheduledCommand& read, + ScheduledCommand& strobeCommand) const +{ + 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)) + { + 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); + } + else + { + return false; + } + } + else if (strobeCommand.getCommand() == Command::Write + || strobeCommand.getCommand() == Command::WriteA) + { + //read to write + if (strobeCommand.getStart() >= read.getStart()) + { + return !(strobeCommand.getStart() >= getIntervalOnDataStrobe(read, config.Timings).end); + } + //write to read + else + { + return !(read.getStart()>= getIntervalOnDataStrobe(strobeCommand, config.Timings).end + config.Timings.tWTR); + } + } + else + { + reportFatal("Read Checker", + "Invalid strobeCommand in data strobe commands " + + commandToString(strobeCommand.getCommand())); + return true; + } } } /* namespace controller */ diff --git a/dram/src/core/scheduling/checker/ReadChecker.h b/dram/src/core/scheduling/checker/ReadChecker.h index ff52f5ce..f6d24073 100644 --- a/dram/src/core/scheduling/checker/ReadChecker.h +++ b/dram/src/core/scheduling/checker/ReadChecker.h @@ -25,6 +25,8 @@ public: private: const Configuration& config; ControllerState& state; + bool collidesOnDataStrobe(ScheduledCommand& read) const; + bool collidesWithStrobeCommand(ScheduledCommand& read, ScheduledCommand& strobeCommand) const; }; } /* namespace controller */ diff --git a/dram/src/core/scheduling/checker/WriteChecker.cpp b/dram/src/core/scheduling/checker/WriteChecker.cpp index 305d0d60..2cda4270 100644 --- a/dram/src/core/scheduling/checker/WriteChecker.cpp +++ b/dram/src/core/scheduling/checker/WriteChecker.cpp @@ -6,16 +6,38 @@ */ #include "WriteChecker.h" +#include "../../utils/Utils.h" namespace core { void WriteChecker::delayToSatisfyConstraints(ScheduledCommand& command) const { - - ScheduledCommand lastCommand = state.getLastCommand(command.getBank()); - if(lastCommand.isValidCommand() && lastCommand.getEnd() > command.getStart()) + if(command.getStart() >= sc_time(62885689,SC_NS)) { - command.delayStart(lastCommand.getEnd()-command.getStart()); + int i = 5; + i++; + } + assert(command.getCommand() == Command::Write || command.getCommand() == Command::WriteA); + + ScheduledCommand lastCommandOnBank = state.getLastScheduledCommand(command.getBank()); + + if (lastCommandOnBank.isValidCommand()) + { + if (lastCommandOnBank.getCommand() == Command::Activate) + { + command.delayStart(getDelayToMeetConstraint(lastCommandOnBank.getEnd(),command.getStart(), SC_ZERO_TIME)); + } + else if (lastCommandOnBank.getCommand() == Command::Read + || lastCommandOnBank.getCommand() == Command::Write) + { + } + else + reportFatal("Write Checker", "Write can not follow " + commandToString(lastCommandOnBank.getCommand())); + } + + while (!state.bus.isFree(command.getStart()) || collidesOnDataStrobe(command)) + { + command.delayStart(config.Timings.clk); } } @@ -23,7 +45,57 @@ sc_time WriteChecker::getExecutionTime(const tlm::tlm_generic_payload& payload, Command command) const { assert(command == Command::Write || command == Command::WriteA); - return config.Timings.clk*8; + if (command == Command::Write) + { + return config.Timings.tWL + config.Timings.clk * (payload.get_streaming_width()-1); + } + else + { + return config.Timings.tWL + config.Timings.clk * (payload.get_streaming_width()-1) + config.Timings.tRP; + } +} + +bool WriteChecker::collidesOnDataStrobe(ScheduledCommand& write) const +{ + for (ScheduledCommand& strobeCommand : state.lastDataStrobeCommands) + { + if (collidesWithStrobeCommand(write, strobeCommand)) + return true; + } + + return false; +} + +bool WriteChecker::collidesWithStrobeCommand(ScheduledCommand& write, + ScheduledCommand& strobeCommand) const +{ + if (strobeCommand.getCommand() == Command::Write || strobeCommand.getCommand() == Command::WriteA) + { + //write to write (implicitly checked by checking the command bus first) + return false; + } + else if (strobeCommand.getCommand() == Command::Read + || strobeCommand.getCommand() == Command::ReadA) + { + //write to read + if (strobeCommand.getStart() >= write.getStart()) + { + return !(strobeCommand.getStart()>= getIntervalOnDataStrobe(write, config.Timings).end + config.Timings.tWTR); + } + + //read to write + else + { + return !(write.getStart() >= getIntervalOnDataStrobe(strobeCommand, config.Timings).end); + } + } + else + { + reportFatal("Write Checker", + "Invalid strobeCommand in data strobe commands " + + commandToString(strobeCommand.getCommand())); + return true; + } } } /* namespace controller */ diff --git a/dram/src/core/scheduling/checker/WriteChecker.h b/dram/src/core/scheduling/checker/WriteChecker.h index f29c513a..e07e8cc4 100644 --- a/dram/src/core/scheduling/checker/WriteChecker.h +++ b/dram/src/core/scheduling/checker/WriteChecker.h @@ -23,6 +23,8 @@ public: virtual void delayToSatisfyConstraints(ScheduledCommand& command) const override; virtual sc_time getExecutionTime(const tlm::tlm_generic_payload& payload, Command command) const override; private: + bool collidesOnDataStrobe(ScheduledCommand& write) const; + bool collidesWithStrobeCommand(ScheduledCommand& write, ScheduledCommand& strobeCommand) const; const Configuration& config; ControllerState& state; }; diff --git a/dram/src/core/utils/Utils.cpp b/dram/src/core/utils/Utils.cpp index 1953ce20..72e77ca7 100644 --- a/dram/src/core/utils/Utils.cpp +++ b/dram/src/core/utils/Utils.cpp @@ -6,18 +6,18 @@ */ #include "Utils.h" +#include "../TimingConfiguration.h" + +namespace core +{ unsigned int getStartAddress(Bank bank) { return 0; } -unsigned int getBurstLengthInBytes(const tlm::tlm_generic_payload& payload, unsigned int buswidth) -{ - return payload.get_data_length() / (buswidth/8); -} -sc_time delayByConstraint(sc_time previous, sc_time start, sc_time constraint) +sc_time getDelayToMeetConstraint(sc_time previous, sc_time start, sc_time constraint) { if (previous + constraint > start) return previous + constraint - start; @@ -33,7 +33,20 @@ const sc_time clkAlign(sc_time time, sc_time clk, Alignment alignment) return floor(time / clk) * clk; } +TimeInterval getIntervalOnDataStrobe(const ScheduledCommand& command, const TimingConfiguration& config) +{ + sc_assert(command.getCommand() == Command::Read || command.getCommand() == Command::ReadA || + command.getCommand() == Command::Write ||command.getCommand() == Command::WriteA); + + if(command.getCommand() == Command::ReadA || command.getCommand() == Command::WriteA) + return TimeInterval(command.getStart(), command.getEnd() - config.tRP); + else + return TimeInterval(command.getStart(),command.getEnd()); +} + bool isClkAligned(sc_time time, sc_time clk) { return !((time / clk) - ceil(time / clk)); } + +} diff --git a/dram/src/core/utils/Utils.h b/dram/src/core/utils/Utils.h index 30dd817a..6a6b8b8a 100644 --- a/dram/src/core/utils/Utils.h +++ b/dram/src/core/utils/Utils.h @@ -11,14 +11,30 @@ #include #include #include "../../common/dramExtension.h" +#include "../scheduling/ScheduledCommand.h" +namespace core +{ unsigned int getStartAddress(Bank bank); -unsigned int getBurstLengthInBytes(const tlm::tlm_generic_payload& payload, unsigned int buswidth); -sc_time delayByConstraint(sc_time previous, sc_time start, sc_time constraint); +struct TimeInterval +{ + sc_time start,end; + TimeInterval(sc_time start,sc_time end) : start(start), end(end){} + bool timeIsInInterval(sc_time time) + { + return (start<=time && time<=end); + } +}; + +struct TimingConfiguration; + +sc_time getDelayToMeetConstraint(sc_time previous, sc_time start, sc_time constraint); +TimeInterval getIntervalOnDataStrobe(const ScheduledCommand& command, const TimingConfiguration& config); enum Alignment {UP, DOWN}; const sc_time clkAlign(sc_time time, sc_time clk, Alignment alignment = UP); bool isClkAligned(sc_time time, sc_time clk); +}; #endif /* UTILS_H_ */ diff --git a/dram/src/simulation/main.cpp b/dram/src/simulation/main.cpp index b1e4044e..452eff2b 100644 --- a/dram/src/simulation/main.cpp +++ b/dram/src/simulation/main.cpp @@ -34,7 +34,8 @@ int sc_main(int argc, char **argv) string resources = pathOfFile(argv[0]) + string("/../resources/"); xmlAddressDecoder::addressConfigURI = resources + string("configs/addressConfig.xml"); TlmRecorder recorder("tpr.tdb", resources + string("scripts/createTraceDB.sql")); - TracePlayer<> player("player", resources + string("traces/chstone-mips_32.stl")); + //TracePlayer<> player("player", resources + string("traces/mediabench-fractal_32.stl")); + TracePlayer<> player("player", resources + string("traces/mediabench-h263encode_32.stl")); Dram<> dram("dram"); Arbiter<> arbiter("arbiter"); @@ -44,8 +45,10 @@ int sc_main(int argc, char **argv) arbiter.iSocket.bind(controller.tSocket); controller.iSocket.bind(dram.tSocket); - DebugManager::getInstance().addToWhiteList(Sender::TraceRecorder); - DebugManager::getInstance().addToWhiteList(Sender::TracePlayer); +// DebugManager::getInstance().addToWhiteList(Sender::TraceRecorder); +// DebugManager::getInstance().addToWhiteList(Sender::TracePlayer); + //DebugManager::getInstance().addToWhiteList(Sender::DramWrapper); + //DebugManager::getInstance().addToWhiteList(Sender::DramController); cout << "Toplevel: simulation start" << std::endl; clock_t begin = clock();