diff --git a/DRAMSys/library/library.pro b/DRAMSys/library/library.pro index 05098c1f..c8a65529 100644 --- a/DRAMSys/library/library.pro +++ b/DRAMSys/library/library.pro @@ -147,7 +147,8 @@ SOURCES += \ src/simulation/DramDDR3.cpp \ src/simulation/DramDDR4.cpp \ src/simulation/DramRecordable.cpp \ - src/simulation/DramWideIO.cpp + src/simulation/DramWideIO.cpp \ + src/controller/core/scheduling/checker/CheckerDDR3.cpp HEADERS += \ src/common/third_party/tinyxml2/tinyxml2.h \ @@ -228,7 +229,8 @@ HEADERS += \ src/simulation/DramDDR3.h \ src/simulation/DramDDR4.h \ src/simulation/DramRecordable.h \ - src/simulation/DramWideIO.h + src/simulation/DramWideIO.h \ + src/controller/core/scheduling/checker/CheckerDDR3.h #src/common/third_party/json/include/nlohmann/json.hpp \ thermalsim = $$(THERMALSIM) diff --git a/DRAMSys/library/src/controller/core/ControllerCore.cpp b/DRAMSys/library/src/controller/core/ControllerCore.cpp index 5c43afcc..73905e3e 100644 --- a/DRAMSys/library/src/controller/core/ControllerCore.cpp +++ b/DRAMSys/library/src/controller/core/ControllerCore.cpp @@ -87,16 +87,6 @@ ControllerCore::ControllerCore(sc_module_name /*name*/, if (config.RowGranularRef) { refreshManager = new RGR("RGR", *this); - // TODO: How to use asserts with new memspec? - /* - assert(config.getTrasb() <= config.memSpec->tRAS); - assert(config.getTrasb() >= config.memSpec->tRCD); - assert(config.getTrrdb_L() <= config.memSpec->tRRD_L); - assert(config.getTrrdb_S() <= config.memSpec->tRRD_S); - assert(config.getTrpb() <= config.memSpec->tRP); - assert(config.getTrcb() <= config.memSpec->tRC); - assert(config.getTfawb() <= config.memSpec->tNAW); - */ } else { if (config.BankwiseLogic) { refreshManager = new RefreshManagerBankwise("refManagerBw", *this); diff --git a/DRAMSys/library/src/controller/core/configuration/Configuration.cpp b/DRAMSys/library/src/controller/core/configuration/Configuration.cpp index eb0918f3..72811ff4 100644 --- a/DRAMSys/library/src/controller/core/configuration/Configuration.cpp +++ b/DRAMSys/library/src/controller/core/configuration/Configuration.cpp @@ -47,10 +47,6 @@ using namespace std; string Configuration::memspecUri = ""; string Configuration::mcconfigUri = ""; -Configuration::Configuration() -{ -} - bool string2bool(string s) { if (s.compare("0") == 0) { diff --git a/DRAMSys/library/src/controller/core/configuration/Configuration.h b/DRAMSys/library/src/controller/core/configuration/Configuration.h index 51d4079e..80f7ae87 100644 --- a/DRAMSys/library/src/controller/core/configuration/Configuration.h +++ b/DRAMSys/library/src/controller/core/configuration/Configuration.h @@ -160,7 +160,7 @@ struct Configuration std::string getPathToResources(); private: - Configuration(); + Configuration() {} unsigned int powerDownTimeoutInClk = 3; }; diff --git a/DRAMSys/library/src/controller/core/configuration/ConfigurationLoader.cpp b/DRAMSys/library/src/controller/core/configuration/ConfigurationLoader.cpp index a4d3f94f..81fd0dba 100644 --- a/DRAMSys/library/src/controller/core/configuration/ConfigurationLoader.cpp +++ b/DRAMSys/library/src/controller/core/configuration/ConfigurationLoader.cpp @@ -143,20 +143,16 @@ void ConfigurationLoader::loadMemSpec(Configuration &config, string memoryType = queryStringParameter(memspec, "memoryType"); if (memoryType == "DDR4") { - Configuration::getInstance().memSpec = - new MemSpecDDR4; + Configuration::getInstance().memSpec = new MemSpecDDR4; loadDDR4(config, memspec); } else if (memoryType == "DDR3") { - Configuration::getInstance().memSpec = - new MemSpecDDR3; + Configuration::getInstance().memSpec = new MemSpecDDR3; loadDDR3(config, memspec); } else if (memoryType == "LPDDR4") { - Configuration::getInstance().memSpec = - new MemSpecLPDDR4; + Configuration::getInstance().memSpec = new MemSpecLPDDR4; loadLPDDR4(config, memspec); } else if (memoryType == "WIDEIO_SDR") { - Configuration::getInstance().memSpec = - new MemSpecWideIO; + Configuration::getInstance().memSpec = new MemSpecWideIO; loadWideIO(config, memspec); } else { reportFatal("ConfigurationLoader", "Unsupported DRAM type"); diff --git a/DRAMSys/library/src/controller/core/configuration/MemSpec.h b/DRAMSys/library/src/controller/core/configuration/MemSpec.h index d13f2701..28503d19 100644 --- a/DRAMSys/library/src/controller/core/configuration/MemSpec.h +++ b/DRAMSys/library/src/controller/core/configuration/MemSpec.h @@ -162,6 +162,8 @@ struct MemSpec { return tWTR_L; } + + virtual ~MemSpec() {} }; struct MemSpecDDR3 : public MemSpec diff --git a/DRAMSys/library/src/controller/core/scheduling/checker/CheckerDDR3.cpp b/DRAMSys/library/src/controller/core/scheduling/checker/CheckerDDR3.cpp new file mode 100644 index 00000000..e5d06288 --- /dev/null +++ b/DRAMSys/library/src/controller/core/scheduling/checker/CheckerDDR3.cpp @@ -0,0 +1,569 @@ +#include "CheckerDDR3.h" + +#include +#include +#include +#include +#include "CheckerDDR3.h" +#include "../../timingCalculations.h" +#include "../../../../common/DebugManager.h" +#include "../../../Command.h" +#include "../../../../common/Utils.h" + +using namespace std; + +void CheckerDDR3::delayToSatisfyConstraints(ScheduledCommand &command) const +{ + ScheduledCommand lastCommandOnBank = state.getLastScheduledCommand(command.getBank()); + Command LastCmd = lastCommandOnBank.getCommand(); + Command NextCmd = command.getCommand(); + + if (NextCmd == Command::Activate) + { + if (lastCommandOnBank.isValidCommand()) + { + switch (LastCmd) + { + case Command::Precharge: + case Command::PrechargeAll: + command.establishMinDistanceFromStart(lastCommandOnBank.getStart(), + memSpec->tRP); + break; + case Command::ReadA: + command.establishMinDistanceFromStart(lastCommandOnBank.getStart(), + memSpec->tRTP + memSpec->tRP); + break; + case Command::WriteA: + command.establishMinDistanceFromStart(lastCommandOnBank.getStart(), + memSpec->tWL + getWriteAccessTime() + + memSpec->tWR + memSpec->tRP); + break; + case Command::PDNPX: + case Command::PDNAX: + command.establishMinDistanceFromStart(lastCommandOnBank.getStart(), + memSpec->tXP); + break; + case Command::SREFX: + command.establishMinDistanceFromStart(lastCommandOnBank.getStart(), + memSpec->tXS); + break; + case Command::AutoRefresh: + command.establishMinDistanceFromStart(lastCommandOnBank.getStart(), + memSpec->tRFC); + break; + default: + reportFatal("Checker DDR3", + "Activate can not follow " + commandToString(LastCmd)); + } + } + + delay_to_satisfy_activateToActivate_sameBank(command); + + while (!(state.bus.isFree(command.getStart()) && + satsfies_activateToActivate_differentBank(command) && satisfies_nActivateWindow(command))) + { + command.delayStart(memSpec->clk); + } + } + else if (NextCmd == Command::Read || NextCmd == Command::ReadA) + { + delayToSatisfyDLL(command); + if (lastCommandOnBank.isValidCommand()) + { + switch (LastCmd) + { + case Command::Activate: + command.establishMinDistanceFromStart(lastCommandOnBank.getStart(), + memSpec->tRCD); + break; + case Command::Read: + command.establishMinDistanceFromStart(lastCommandOnBank.getStart(), + CasToCas(lastCommandOnBank, command)); + break; + case Command::Write: + command.establishMinDistanceFromStart(lastCommandOnBank.getStart(), + writeToRead(lastCommandOnBank, command)); + break; + case Command::PDNPX: + case Command::PDNAX: + command.establishMinDistanceFromStart(lastCommandOnBank.getStart(), + memSpec->tXP); + break; + default: + reportFatal("Checker DDR3", + "Read can not follow " + commandToString(LastCmd) + "First: Activate!"); + } + } + while (!state.bus.isFree(command.getStart()) || collidesOnDataStrobe_RD(command)) + command.delayStart(memSpec->clk); + } + else if (NextCmd == Command::Write || NextCmd == Command::WriteA) + { + if (lastCommandOnBank.isValidCommand()) + { + switch (LastCmd) + { + case Command::Activate: + command.establishMinDistanceFromStart(lastCommandOnBank.getStart(), + memSpec->tRCD); + break; + case Command::Read: + command.establishMinDistanceFromStart(lastCommandOnBank.getStart(), + readToWrite(lastCommandOnBank, command)); + break; + case Command::Write: + command.establishMinDistanceFromStart(lastCommandOnBank.getStart(), + CasToCas(lastCommandOnBank, command)); + break; + case Command::PDNPX: + case Command::PDNAX: + command.establishMinDistanceFromStart(lastCommandOnBank.getStart(), + memSpec->tXP); + break; + default: + reportFatal("Checker DDR3", "Write can not follow " + commandToString(LastCmd)); + } + } + while (!state.bus.isFree(command.getStart()) || collidesOnDataStrobe_WR(command)) + command.delayStart(memSpec->clk); + } + else if (NextCmd == Command::Precharge) + { + if (lastCommandOnBank.isValidCommand()) + { + switch (LastCmd) + { + case Command::Precharge: + command.establishMinDistanceFromStart(lastCommandOnBank.getStart(), + memSpec->tRP); + break; + case Command::Activate: + command.establishMinDistanceFromStart(lastCommandOnBank.getStart(), + memSpec->tRCD); + break; + case Command::Read: + command.establishMinDistanceFromStart(lastCommandOnBank.getStart(), + memSpec->tRTP); + break; + case Command::Write: + command.establishMinDistanceFromStart(lastCommandOnBank.getStart(), + memSpec->tWL + memSpec->tWR + + getWriteAccessTime()); + break; + case Command::PDNAX: + command.establishMinDistanceFromStart(lastCommandOnBank.getStart(), + memSpec->tXP); + break; + default: + reportFatal("Checker DDR3", + "Precharge can not follow " + commandToString(LastCmd)); + } + } + ScheduledCommand lastActivate = state.getLastCommand(Command::Activate, command.getBank()); + if (lastActivate.isValidCommand()) + command.establishMinDistanceFromStart(lastActivate.getStart(), + memSpec->tRAS); + state.bus.moveCommandToNextFreeSlot(command); + } + else if (NextCmd == Command::PrechargeAll) + { + for (unsigned int bank = 0; bank < memSpec->NumberOfBanks; bank++) + { + ScheduledCommand lastCommand = state.getLastScheduledCommand(Bank(bank)); + if (lastCommand.isValidCommand()) + { + switch (lastCommand.getCommand()) + { + case Command::Precharge: + command.establishMinDistanceFromStart(lastCommand.getStart(), + memSpec->tRP); + break; + case Command::Activate: + command.establishMinDistanceFromStart(lastCommand.getStart(), + memSpec->tRCD); + break; + case Command::Read: + command.establishMinDistanceFromStart(lastCommand.getStart(), + memSpec->tRTP); + break; + case Command::Write: + command.establishMinDistanceFromStart(lastCommand.getStart(), + memSpec->tWL + getWriteAccessTime() + + memSpec->tWR); + break; + case Command::WriteA: + command.establishMinDistanceFromStart(lastCommand.getStart(), + memSpec->tWL + getWriteAccessTime() + + memSpec->tWR + memSpec->tRP); + break; + case Command::ReadA: + command.establishMinDistanceFromStart(lastCommand.getStart(), + memSpec->tRTP + memSpec->tRP); + break; + case Command::PDNAX: + case Command::PDNPX: + command.establishMinDistanceFromStart(lastCommand.getStart(), + memSpec->tXP); + break; + case Command::SREFX: + command.establishMinDistanceFromStart(lastCommand.getStart(), + memSpec->tXS); + break; + case Command::AutoRefresh: + command.establishMinDistanceFromStart(lastCommand.getStart(), + memSpec->tRFC); + break; + default: + reportFatal("Checker_DDR3", + "Precharge All can not follow " + commandToString(LastCmd)); + } + } + } + ScheduledCommand lastActivate = state.getLastCommand(Command::Activate, command.getBank()); + if (lastActivate.isValidCommand()) + command.establishMinDistanceFromStart(lastActivate.getStart(), + memSpec->tRAS); + state.bus.moveCommandToNextFreeSlot(command); + } + else if (NextCmd == Command::PDNA || NextCmd == Command::PDNP || NextCmd == Command::SREF ) + { + if (lastCommandOnBank.isValidCommand()) + { + switch (LastCmd) + { + case Command::Precharge: + case Command::PrechargeAll: + command.establishMinDistanceFromStart(lastCommandOnBank.getStart(), + memSpec->tRP); + break; + case Command::Read: + case Command::ReadA: + command.establishMinDistanceFromStart(lastCommandOnBank.getStart(), + memSpec->tRL + getReadAccessTime() + + memSpec->clk); + break; + case Command::Write: + command.establishMinDistanceFromStart(lastCommandOnBank.getStart(), + memSpec->tWL + getWriteAccessTime() + + memSpec->tWR); + break; + case Command::WriteA: + command.establishMinDistanceFromStart(lastCommandOnBank.getStart(), + memSpec->tWL + getWriteAccessTime() + + memSpec->tWR + memSpec->clk); + break; + case Command::AutoRefresh: + command.establishMinDistanceFromStart(lastCommandOnBank.getStart(), + memSpec->tRFC); + break; + case Command::PDNAX: + case Command::PDNPX: + command.establishMinDistanceFromStart(lastCommandOnBank.getStart(), + memSpec->tXP); + break; + case Command::SREFX: + command.establishMinDistanceFromStart(lastCommandOnBank.getStart(), + memSpec->tXS); + break; + default: + reportFatal("Checker DDR3", commandToString(NextCmd) + " can not follow " + + commandToString(LastCmd) + ".First: Precharge!"); + } + } + state.bus.moveCommandToNextFreeSlot(command); + } + else if (NextCmd == Command::PDNAX) + { + // Leaving Precharge Power Down + command.establishMinDistanceFromStart(state.getLastCommand(Command::PDNA, + command.getBank()).getStart(), memSpec->tCKE); + state.bus.moveCommandToNextFreeSlot(command); + } + else if (NextCmd == Command::PDNPX) + { + // Leaving Precharge Power Down + command.establishMinDistanceFromStart(state.getLastCommand(Command::PDNP, + command.getBank()).getStart(), memSpec->tCKE); + state.bus.moveCommandToNextFreeSlot(command); + } + else if (NextCmd == Command::SREFX) + { + // Leaving Self Refresh + command.establishMinDistanceFromStart(state.getLastCommand(Command::SREF, + command.getBank()).getStart(), memSpec->tCKESR); + state.bus.moveCommandToNextFreeSlot(command); + } + else if (NextCmd == Command::AutoRefresh) + { + if (config.BankwiseLogic) { + if (lastCommandOnBank.isValidCommand()) + { + switch (LastCmd) + { + case Command::Precharge: + case Command::PrechargeAll: + command.establishMinDistanceFromStart(lastCommandOnBank.getStart(), + memSpec->tRP); + break; + case Command::ReadA: + command.establishMinDistanceFromStart(lastCommandOnBank.getStart(), + memSpec->tRTP + memSpec->tRP); + break; + case Command::WriteA: + command.establishMinDistanceFromStart(lastCommandOnBank.getStart(), + memSpec->tWL + getWriteAccessTime() + + memSpec->tWR + memSpec->tRP); + break; + case Command::AutoRefresh: + command.establishMinDistanceFromStart(lastCommandOnBank.getStart(), + memSpec->tRFC); + break; + case Command::PDNPX: + case Command::PDNAX: + command.establishMinDistanceFromStart(lastCommandOnBank.getStart(), + memSpec->tXP); + break; + case Command::SREFX: + command.establishMinDistanceFromStart(lastCommandOnBank.getStart(), + memSpec->tXS); + break; + default: + reportFatal("Checker DDR3", + "Refresh can not follow " + commandToString(LastCmd)); + } + } + } + else + { + for (unsigned int bank = 0; bank < memSpec->NumberOfBanks; bank++) + { + ScheduledCommand lastCommand = state.getLastScheduledCommand(Bank(bank)); + + if (lastCommand.isValidCommand()) + { + switch (lastCommand.getCommand()) + { + case Command::Precharge: + case Command::PrechargeAll: + command.establishMinDistanceFromStart(lastCommand.getStart(), + memSpec->tRP); + break; + case Command::Activate: + command.establishMinDistanceFromStart(lastCommand.getStart(), + memSpec->tRCD); + break; + case Command::ReadA: + command.establishMinDistanceFromStart(lastCommand.getStart(), + memSpec->tRTP + memSpec->tRP); + break; + case Command::WriteA: + command.establishMinDistanceFromStart(lastCommand.getStart(), + memSpec->tWL + getWriteAccessTime() + + memSpec->tWR + memSpec->tRP); + break; + case Command::AutoRefresh: + command.establishMinDistanceFromStart(lastCommand.getStart(), + memSpec->tRFC); + break; + case Command::PDNPX: + case Command::PDNAX: + command.establishMinDistanceFromStart(lastCommand.getStart(), + memSpec->tXP); + break; + case Command::SREFX: + command.establishMinDistanceFromStart(lastCommand.getStart(), + memSpec->tXS); + break; + default: + reportFatal("Checker DDR3", + "Refresh can not follow " + commandToString(LastCmd)); + } + } + } + } + state.bus.moveCommandToNextFreeSlot(command); + } +} + +/* +* ActivateChecker +*/ + +void CheckerDDR3::delay_to_satisfy_activateToActivate_sameBank(ScheduledCommand &command) const +{ + ScheduledCommand lastActivateOnBank = state.getLastCommand(Command::Activate, command.getBank()); + if (lastActivateOnBank.isValidCommand()) + command.establishMinDistanceFromStart(lastActivateOnBank.getStart(), memSpec->tRC); +} + +bool CheckerDDR3::satsfies_activateToActivate_differentBank(ScheduledCommand &command) const +{ + for (auto act : state.lastActivates) + { + sc_time time = act.first; + if ((time < command.getStart() && command.getStart() - time < memSpec->tRRD) + || (command.getStart() <= time && time - command.getStart() < memSpec->tRRD)) + return false; + } + return true; + +} + +bool CheckerDDR3::satisfies_nActivateWindow(ScheduledCommand &command) const +{ + /* + * there may be activates scheduled in the future, so emplace + * command in a copied set (not necessarily the last in time), + * and check if the n-act constraint holds for the whole set. + */ + if (state.lastActivates.size() >= memSpec->nActivate) + { + std::map lastActivates = state.lastActivates; + lastActivates.emplace(command.getStart(), command); + auto upper = lastActivates.begin(); + std::advance(upper, memSpec->nActivate); + auto lower = lastActivates.begin(); + + while (upper != lastActivates.end()) + { + if (upper->first - lower->first < memSpec->tNAW) + return false; + upper++; + lower++; + } + } + return true; +} + + +/* + * Read-Checker +*/ + +bool CheckerDDR3::collidesOnDataStrobe_RD(ScheduledCommand &read) const +{ + for (ScheduledCommand &strobeCommand : state.lastDataStrobeCommands) + { + if (collidesWithStrobeCommand_RD(read, strobeCommand)) + return true; + } + return false; +} + +bool CheckerDDR3::collidesWithStrobeCommand_RD(ScheduledCommand &read, + ScheduledCommand &strobeCommand) const +{ + if (strobeCommand.getCommand() == Command::Read || strobeCommand.getCommand() == Command::ReadA) + { + return getDistance(read.getStart(), + strobeCommand.getStart()) < CasToCas(strobeCommand, read); + } + else if (strobeCommand.getCommand() == Command::Write || strobeCommand.getCommand() == Command::WriteA) + { + if (strobeCommand.getStart() >= read.getStart()) + return getDistance(read.getStart(), + strobeCommand.getStart()) < readToWrite(read, strobeCommand); + else + return getDistance(strobeCommand.getStart(), + read.getStart()) < writeToRead(strobeCommand, read); + } else { + reportFatal("Checker DDR3", + "Invalid strobeCommand in data strobe commands " + commandToString( + strobeCommand.getCommand())); + return true; + } + return false; +} + + +void CheckerDDR3::delayToSatisfyDLL(ScheduledCommand &read) const +{ + ScheduledCommand lastSREFX = state.getLastCommand(Command::SREFX, read.getBank()); + if (lastSREFX.isValidCommand()) + read.establishMinDistanceFromStart(lastSREFX.getStart(), memSpec->tXSDLL); +} + + +sc_time CheckerDDR3::writeToRead(ScheduledCommand &write, ScheduledCommand &read) +{ + sc_assert(read.getCommand() == Command::Read || read.getCommand() == Command::ReadA); + sc_assert(write.getCommand() == Command::Write || write.getCommand() == Command::WriteA); + + if (write.getBankGroup() == read.getBankGroup()) + { + return memSpec->tWL + getWriteAccessTime() + memSpec->tWTR; + } +} + +/* CAS-CAS */ + +sc_time CheckerDDR3::CasToCas(ScheduledCommand &firstCAS, ScheduledCommand &secondCAS) +{ + if (firstCAS.getCommand() == Command::Read || firstCAS.getCommand() == Command::ReadA) + { + if (secondCAS.getCommand() == Command::Read || secondCAS.getCommand() == Command::ReadA) + { + if (firstCAS.getBankGroup() == secondCAS.getBankGroup()) + return std::max(memSpec->tCCD, getReadAccessTime()); + } + } + else if (firstCAS.getCommand() == Command::Write || firstCAS.getCommand() == Command::WriteA) + { + if (secondCAS.getCommand() == Command::Write || secondCAS.getCommand() == Command::WriteA) + { + if (firstCAS.getBankGroup() == secondCAS.getBankGroup()) + return std::max(memSpec->tCCD, getWriteAccessTime()); + } + } +} + +/* +* Write-Checker +*/ + +bool CheckerDDR3::collidesOnDataStrobe_WR(ScheduledCommand &write) const +{ + for (ScheduledCommand &strobeCommand : state.lastDataStrobeCommands) + { + if (collidesWithStrobeCommand_WR(write, strobeCommand)) + return true; + } + return false; +} + +bool CheckerDDR3::collidesWithStrobeCommand_WR(ScheduledCommand &write, + ScheduledCommand &strobeCommand) const +{ + if (strobeCommand.getCommand() == Command::Write || strobeCommand.getCommand() == Command::WriteA) + { + // TODO: Cast from sc_time to bool? + return getDistance(write.getStart(), + strobeCommand.getStart()) < CasToCas(strobeCommand, write); + } + else if (strobeCommand.getCommand() == Command::Read || strobeCommand.getCommand() == Command::ReadA) + { + if (strobeCommand.getStart() >= write.getStart()) + return getDistance(write.getStart(), + strobeCommand.getStart()) < writeToRead(write, strobeCommand); + else + return getDistance(strobeCommand.getStart(), + write.getStart()) < readToWrite(strobeCommand, write); + } + else + { + reportFatal("CheckerDDR3", "Invalid strobeCommand in data strobe commands " + + commandToString(strobeCommand.getCommand())); + return true; + } +} + + +sc_time CheckerDDR3::readToWrite(ScheduledCommand &read, ScheduledCommand &write) +{ + sc_assert(read.getCommand() == Command::Read + || read.getCommand() == Command::ReadA); + sc_assert(write.getCommand() == Command::Write + || write.getCommand() == Command::WriteA); + + return memSpec->tRL + getReadAccessTime() - memSpec->tWL + memSpec->clk * 2; +} diff --git a/DRAMSys/library/src/controller/core/scheduling/checker/CheckerDDR3.h b/DRAMSys/library/src/controller/core/scheduling/checker/CheckerDDR3.h new file mode 100644 index 00000000..dde7204d --- /dev/null +++ b/DRAMSys/library/src/controller/core/scheduling/checker/CheckerDDR3.h @@ -0,0 +1,59 @@ +#ifndef CHECKERDDR3_H +#define CHECKERDDR3_H + +#include "ICommandChecker.h" +#include "../../configuration/Configuration.h" +#include "../../../ControllerState.h" + +//Activate +class CheckerDDR3: public ICommandChecker +{ +public: + CheckerDDR3(const Configuration &config, + ControllerState &state) : config(config), state(state) + { + memSpec = dynamic_cast(Configuration::getInstance().memSpec); + if (memSpec == nullptr) + SC_REPORT_FATAL("CheckerDDR3", "Wrong MemSpec chosen."); + } + virtual ~CheckerDDR3() {} + + virtual void delayToSatisfyConstraints(ScheduledCommand &command) const + override; + +private: + static MemSpecDDR3 *memSpec; + + //Activate + void delay_to_satisfy_activateToActivate_sameBank(ScheduledCommand &command) const; + bool satsfies_activateToActivate_differentBank(ScheduledCommand &command) const; + bool satisfies_nActivateWindow(ScheduledCommand &command) const; + + //PowerDown + sc_time getTimeConstraintToEnterPowerDown(Command lastCmd, Command pdnCmd) const; + + //used for Read + void delayToSatisfyDLL(ScheduledCommand &read) const; + bool collidesOnDataStrobe_RD(ScheduledCommand &read) const; + bool collidesWithStrobeCommand_RD(ScheduledCommand &read, + ScheduledCommand &strobeCommand) const; + + //Write + bool collidesOnDataStrobe_WR(ScheduledCommand &write) const; + bool collidesWithStrobeCommand_WR(ScheduledCommand &write, + ScheduledCommand &strobeCommand) const; + + //handles WR->RD + static sc_time writeToRead(ScheduledCommand &write, ScheduledCommand &read); + + //RD->WR + static sc_time readToWrite(ScheduledCommand &read, ScheduledCommand &write); + + //CasToCas Commands (WR->WR)(RD->RD) + static sc_time CasToCas(ScheduledCommand &firstCAS, ScheduledCommand &secondCAS); + + const Configuration &config; + ControllerState &state;//TODO make const +}; + +#endif // CHECKERDDR3_H