From 3e4e8e940897627769f0959877b590c452636973 Mon Sep 17 00:00:00 2001 From: "Lukas Steiner (2)" Date: Tue, 9 Jul 2019 15:52:09 +0200 Subject: [PATCH] Included new timing checker for DDR3. --- DRAMSys/library/library.pro | 6 +- .../scheduling/checker/CheckerDDR3New.cpp | 562 ++++++++++++++++++ .../core/scheduling/checker/CheckerDDR3New.h | 58 ++ 3 files changed, 624 insertions(+), 2 deletions(-) create mode 100644 DRAMSys/library/src/controller/core/scheduling/checker/CheckerDDR3New.cpp create mode 100644 DRAMSys/library/src/controller/core/scheduling/checker/CheckerDDR3New.h diff --git a/DRAMSys/library/library.pro b/DRAMSys/library/library.pro index 0a2ada5c..188d67ef 100644 --- a/DRAMSys/library/library.pro +++ b/DRAMSys/library/library.pro @@ -148,7 +148,8 @@ SOURCES += \ src/simulation/DramRecordable.cpp \ src/simulation/DramWideIO.cpp \ src/controller/core/scheduling/checker/CheckerDDR3.cpp \ - src/controller/core/configuration/MemSpec.cpp + src/controller/core/configuration/MemSpec.cpp \ + src/controller/core/scheduling/checker/CheckerDDR3New.cpp HEADERS += \ src/common/third_party/tinyxml2/tinyxml2.h \ @@ -230,7 +231,8 @@ HEADERS += \ src/simulation/DramRecordable.h \ src/simulation/DramWideIO.h \ src/controller/core/scheduling/checker/CheckerDDR3.h \ - src/controller/GenericController.h + src/controller/GenericController.h \ + src/controller/core/scheduling/checker/CheckerDDR3New.h #src/common/third_party/json/include/nlohmann/json.hpp \ thermalsim = $$(THERMALSIM) diff --git a/DRAMSys/library/src/controller/core/scheduling/checker/CheckerDDR3New.cpp b/DRAMSys/library/src/controller/core/scheduling/checker/CheckerDDR3New.cpp new file mode 100644 index 00000000..c7469dab --- /dev/null +++ b/DRAMSys/library/src/controller/core/scheduling/checker/CheckerDDR3New.cpp @@ -0,0 +1,562 @@ +#include "CheckerDDR3New.h" + +#include +#include +#include +#include +#include "../../timingCalculations.h" +#include "../../../../common/DebugManager.h" +#include "../../../Command.h" +#include "../../../../common/utils.h" +//#include "../../configuration/MemSpec.h" + +using namespace std; + +void CheckerDDR3New::delayToSatisfyConstraints(ScheduledCommand &command) const +{ + ScheduledCommand lastCommandOnBank = state.getLastScheduledCommand(command.getBank()); + Command LastCmd = lastCommandOnBank.getCommand(); + Command nextCmd = command.getCommand(); + + if (nextCmd == Command::ACT) + { + // TODO: WRA_bank0 -> PREA -> ACT_bank0: WRA_bank0 and ACT_bank0 have TD, + // but we only consider PREA -> ACT_bank0 TD + if (lastCommandOnBank.isValidCommand()) + { + switch (LastCmd) + { + case Command::PRE: + case Command::PREA: + command.establishMinDistanceFromStart(lastCommandOnBank.getStart(), + memSpec->tRP_old); + break; + case Command::RDA: + command.establishMinDistanceFromStart(lastCommandOnBank.getStart(), + memSpec->tRTP + memSpec->tRP_old); + break; + case Command::WRA: + command.establishMinDistanceFromStart(lastCommandOnBank.getStart(), + memSpec->tWL + memSpec->getWriteAccessTime() + + memSpec->tWR + memSpec->tRP_old); + break; + case Command::PDXP: + case Command::PDXA: + command.establishMinDistanceFromStart(lastCommandOnBank.getStart(), + memSpec->tXP); + break; + case Command::SREFEX: + command.establishMinDistanceFromStart(lastCommandOnBank.getStart(), + memSpec->tXS); + break; + case Command::REFA: + command.establishMinDistanceFromStart(lastCommandOnBank.getStart(), + memSpec->tRFC_old); + break; + default: + reportFatal("CheckerDDR3New", + "Activate can not follow " + commandToString(LastCmd)); + } + } + + delayToSatisfyACTtoACTsameBank(command); + + while (!(state.bus.isFree(command.getStart()) && + satsfiesACTtoACTdifferentBank(command) && satisfiesNActivateWindow(command))) + command.delayStart(memSpec->clk); + } + else if (nextCmd == Command::RD || nextCmd == Command::RDA) + { + delayToSatisfyDLL(command); + if (lastCommandOnBank.isValidCommand()) + { + switch (LastCmd) + { + case Command::ACT: + command.establishMinDistanceFromStart(lastCommandOnBank.getStart(), + memSpec->tRCD); + break; + case Command::RD: + command.establishMinDistanceFromStart(lastCommandOnBank.getStart(), + CasToCas(lastCommandOnBank, command)); + break; + case Command::WR: + command.establishMinDistanceFromStart(lastCommandOnBank.getStart(), + writeToRead(lastCommandOnBank, command)); + break; + case Command::PDXP: + case Command::PDXA: + command.establishMinDistanceFromStart(lastCommandOnBank.getStart(), + memSpec->tXP); + break; + default: + reportFatal("CheckerDDR3New", + "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::WR || nextCmd == Command::WRA) + { + if (lastCommandOnBank.isValidCommand()) + { + switch (LastCmd) + { + case Command::ACT: + command.establishMinDistanceFromStart(lastCommandOnBank.getStart(), + memSpec->tRCD); + break; + case Command::RD: + command.establishMinDistanceFromStart(lastCommandOnBank.getStart(), + readToWrite(lastCommandOnBank, command)); + break; + case Command::WR: + command.establishMinDistanceFromStart(lastCommandOnBank.getStart(), + CasToCas(lastCommandOnBank, command)); + break; + case Command::PDXP: + case Command::PDXA: + command.establishMinDistanceFromStart(lastCommandOnBank.getStart(), + memSpec->tXP); + break; + default: + reportFatal("CheckerDDR3New", "Write can not follow " + commandToString(LastCmd)); + } + } + while (!state.bus.isFree(command.getStart()) || collidesOnDataStrobe_WR(command)) + command.delayStart(memSpec->clk); + } + else if (nextCmd == Command::PRE) + { + if (lastCommandOnBank.isValidCommand()) + { + switch (LastCmd) + { + case Command::PRE: + command.establishMinDistanceFromStart(lastCommandOnBank.getStart(), + memSpec->tRP_old); + break; + case Command::ACT: + command.establishMinDistanceFromStart(lastCommandOnBank.getStart(), + memSpec->tRCD); + break; + case Command::RD: + command.establishMinDistanceFromStart(lastCommandOnBank.getStart(), + memSpec->tRTP); + break; + case Command::WR: + command.establishMinDistanceFromStart(lastCommandOnBank.getStart(), + memSpec->tWL + memSpec->tWR + + memSpec->getWriteAccessTime()); + break; + case Command::PDXA: + command.establishMinDistanceFromStart(lastCommandOnBank.getStart(), + memSpec->tXP); + break; + default: + reportFatal("CheckerDDR3New", + "Precharge can not follow " + commandToString(LastCmd)); + } + } + ScheduledCommand lastActivate = state.getLastCommand(Command::ACT, command.getBank()); + if (lastActivate.isValidCommand()) + command.establishMinDistanceFromStart(lastActivate.getStart(), + memSpec->tRAS); + state.bus.moveCommandToNextFreeSlot(command); + } + else if (nextCmd == Command::PREA) + { + for (unsigned int bank = 0; bank < memSpec->NumberOfBanks; bank++) + { + ScheduledCommand lastCommand = state.getLastScheduledCommand(Bank(bank)); + if (lastCommand.isValidCommand()) + { + switch (lastCommand.getCommand()) + { + case Command::PRE: + command.establishMinDistanceFromStart(lastCommand.getStart(), + memSpec->tRP_old); + break; + case Command::ACT: + command.establishMinDistanceFromStart(lastCommand.getStart(), + memSpec->tRCD); + break; + case Command::RD: + command.establishMinDistanceFromStart(lastCommand.getStart(), + memSpec->tRTP); + break; + case Command::WR: + command.establishMinDistanceFromStart(lastCommand.getStart(), + memSpec->tWL + memSpec->getWriteAccessTime() + + memSpec->tWR); + break; + case Command::WRA: + command.establishMinDistanceFromStart(lastCommand.getStart(), + memSpec->tWL + memSpec->getWriteAccessTime() + + memSpec->tWR + memSpec->tRP_old); + break; + case Command::RDA: + command.establishMinDistanceFromStart(lastCommand.getStart(), + memSpec->tRTP + memSpec->tRP_old); + break; + case Command::PDXA: + case Command::PDXP: + command.establishMinDistanceFromStart(lastCommand.getStart(), + memSpec->tXP); + break; + case Command::SREFEX: + command.establishMinDistanceFromStart(lastCommand.getStart(), + memSpec->tXS); + break; + case Command::REFA: + command.establishMinDistanceFromStart(lastCommand.getStart(), + memSpec->tRFC_old); + break; + default: + reportFatal("CheckerDDR3New", + "Precharge All can not follow " + commandToString(LastCmd)); + } + } + } + ScheduledCommand lastActivate = state.getLastCommand(Command::ACT, command.getBank()); + if (lastActivate.isValidCommand()) + command.establishMinDistanceFromStart(lastActivate.getStart(), + memSpec->tRAS); + state.bus.moveCommandToNextFreeSlot(command); + } + else if (nextCmd == Command::PDEA || nextCmd == Command::PDEP || nextCmd == Command::SREFEN ) + { + if (lastCommandOnBank.isValidCommand()) + { + switch (LastCmd) + { + case Command::PRE: + case Command::PREA: + command.establishMinDistanceFromStart(lastCommandOnBank.getStart(), + memSpec->tRP_old); + break; + case Command::RD: + case Command::RDA: + command.establishMinDistanceFromStart(lastCommandOnBank.getStart(), + memSpec->tRL + memSpec->getReadAccessTime() + + memSpec->clk); + break; + case Command::WR: + command.establishMinDistanceFromStart(lastCommandOnBank.getStart(), + memSpec->tWL + memSpec->getWriteAccessTime() + + memSpec->tWR); + break; + case Command::WRA: + command.establishMinDistanceFromStart(lastCommandOnBank.getStart(), + memSpec->tWL + memSpec->getWriteAccessTime() + + memSpec->tWR + memSpec->clk); + break; + case Command::REFA: + command.establishMinDistanceFromStart(lastCommandOnBank.getStart(), + memSpec->tRFC_old); + break; + case Command::PDXA: + case Command::PDXP: + command.establishMinDistanceFromStart(lastCommandOnBank.getStart(), + memSpec->tXP); + break; + case Command::SREFEX: + command.establishMinDistanceFromStart(lastCommandOnBank.getStart(), + memSpec->tXS); + break; + default: + reportFatal("CheckerDDR3New", commandToString(nextCmd) + " can not follow " + + commandToString(LastCmd) + ".First: Precharge!"); + } + } + state.bus.moveCommandToNextFreeSlot(command); + } + else if (nextCmd == Command::PDXA) + { + // Leaving Precharge Power Down + command.establishMinDistanceFromStart(state.getLastCommand(Command::PDEA, + command.getBank()).getStart(), memSpec->tCKE); + state.bus.moveCommandToNextFreeSlot(command); + } + else if (nextCmd == Command::PDXP) + { + // Leaving Precharge Power Down + command.establishMinDistanceFromStart(state.getLastCommand(Command::PDEP, + command.getBank()).getStart(), memSpec->tCKE); + state.bus.moveCommandToNextFreeSlot(command); + } + else if (nextCmd == Command::SREFEX) + { + // Leaving Self Refresh + command.establishMinDistanceFromStart(state.getLastCommand(Command::SREFEN, + command.getBank()).getStart(), memSpec->tCKESR); + state.bus.moveCommandToNextFreeSlot(command); + } + else if (nextCmd == Command::REFA) + { + if (config.BankwiseLogic) { + if (lastCommandOnBank.isValidCommand()) + { + switch (LastCmd) + { + case Command::PRE: + case Command::PREA: + command.establishMinDistanceFromStart(lastCommandOnBank.getStart(), + memSpec->tRP_old); + break; + case Command::RDA: + command.establishMinDistanceFromStart(lastCommandOnBank.getStart(), + memSpec->tRTP + memSpec->tRP_old); + break; + case Command::WRA: + command.establishMinDistanceFromStart(lastCommandOnBank.getStart(), + memSpec->tWL + memSpec->getWriteAccessTime() + + memSpec->tWR + memSpec->tRP_old); + break; + case Command::REFA: + command.establishMinDistanceFromStart(lastCommandOnBank.getStart(), + memSpec->tRFC_old); + break; + case Command::PDXP: + case Command::PDXA: + command.establishMinDistanceFromStart(lastCommandOnBank.getStart(), + memSpec->tXP); + break; + case Command::SREFEX: + command.establishMinDistanceFromStart(lastCommandOnBank.getStart(), + memSpec->tXS); + break; + default: + reportFatal("CheckerDDR3New", + "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::PRE: + case Command::PREA: + command.establishMinDistanceFromStart(lastCommand.getStart(), + memSpec->tRP_old); + break; + case Command::ACT: + command.establishMinDistanceFromStart(lastCommand.getStart(), + memSpec->tRCD); + break; + case Command::RDA: + command.establishMinDistanceFromStart(lastCommand.getStart(), + memSpec->tRTP + memSpec->tRP_old); + break; + case Command::WRA: + command.establishMinDistanceFromStart(lastCommand.getStart(), + memSpec->tWL + memSpec->getWriteAccessTime() + + memSpec->tWR + memSpec->tRP_old); + break; + case Command::REFA: + command.establishMinDistanceFromStart(lastCommand.getStart(), + memSpec->tRFC_old); + break; + case Command::PDXP: + case Command::PDXA: + command.establishMinDistanceFromStart(lastCommand.getStart(), + memSpec->tXP); + break; + case Command::SREFEX: + command.establishMinDistanceFromStart(lastCommand.getStart(), + memSpec->tXS); + break; + default: + reportFatal("CheckerDDR3New", + "Refresh can not follow " + commandToString(LastCmd)); + } + } + } + } + state.bus.moveCommandToNextFreeSlot(command); + } +} + +/* +* ActivateChecker +*/ + +void CheckerDDR3New::delayToSatisfyACTtoACTsameBank(ScheduledCommand &command) const +{ + ScheduledCommand lastActivateOnBank = state.getLastCommand(Command::ACT, command.getBank()); + if (lastActivateOnBank.isValidCommand()) + command.establishMinDistanceFromStart(lastActivateOnBank.getStart(), memSpec->tRC); +} + +bool CheckerDDR3New::satsfiesACTtoACTdifferentBank(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 CheckerDDR3New::satisfiesNActivateWindow(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_old) + return false; + upper++; + lower++; + } + } + return true; +} + + +/* + * Read-Checker +*/ + +bool CheckerDDR3New::collidesOnDataStrobe_RD(ScheduledCommand &read) const +{ + for (ScheduledCommand &strobeCommand : state.lastDataStrobeCommands) + { + if (collidesWithStrobeCommand_RD(read, strobeCommand)) + return true; + } + return false; +} + +bool CheckerDDR3New::collidesWithStrobeCommand_RD(ScheduledCommand &read, + ScheduledCommand &strobeCommand) const +{ + if (strobeCommand.getCommand() == Command::RD || strobeCommand.getCommand() == Command::RDA) + { + return getDistance(read.getStart(), + strobeCommand.getStart()) < CasToCas(strobeCommand, read); + } + else if (strobeCommand.getCommand() == Command::WR || strobeCommand.getCommand() == Command::WRA) + { + 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("CheckerDDR3New", + "Invalid strobeCommand in data strobe commands " + commandToString( + strobeCommand.getCommand())); + return true; + } + return false; +} + + +void CheckerDDR3New::delayToSatisfyDLL(ScheduledCommand &read) const +{ + ScheduledCommand lastSREFX = state.getLastCommand(Command::SREFEX, read.getBank()); + if (lastSREFX.isValidCommand()) + read.establishMinDistanceFromStart(lastSREFX.getStart(), memSpec->tXSDLL_old); +} + + +sc_time CheckerDDR3New::writeToRead(ScheduledCommand &write, ScheduledCommand &read) const +{ + sc_assert(read.getCommand() == Command::RD || read.getCommand() == Command::RDA); + sc_assert(write.getCommand() == Command::WR || write.getCommand() == Command::WRA); + + return memSpec->tWL + memSpec->getWriteAccessTime() + memSpec->tWTR; +} + +/* CAS-CAS */ + +sc_time CheckerDDR3New::CasToCas(ScheduledCommand &firstCAS, ScheduledCommand &secondCAS) const +{ + if (firstCAS.getCommand() == Command::RD || firstCAS.getCommand() == Command::RDA) + { + if (secondCAS.getCommand() == Command::RD || secondCAS.getCommand() == Command::RDA) + return std::max(memSpec->tCCD, memSpec->getReadAccessTime()); + } + else if (firstCAS.getCommand() == Command::WR || firstCAS.getCommand() == Command::WRA) + { + if (secondCAS.getCommand() == Command::WR || secondCAS.getCommand() == Command::WRA) + return std::max(memSpec->tCCD, memSpec->getWriteAccessTime()); + } + SC_REPORT_FATAL("CasToCas", "Exception reached"); + return SC_ZERO_TIME; +} + +/* +* Write-Checker +*/ + +bool CheckerDDR3New::collidesOnDataStrobe_WR(ScheduledCommand &write) const +{ + for (ScheduledCommand &strobeCommand : state.lastDataStrobeCommands) + { + if (collidesWithStrobeCommand_WR(write, strobeCommand)) + return true; + } + return false; +} + +bool CheckerDDR3New::collidesWithStrobeCommand_WR(ScheduledCommand &write, + ScheduledCommand &strobeCommand) const +{ + if (strobeCommand.getCommand() == Command::WR || strobeCommand.getCommand() == Command::WRA) + { + // TODO: Cast from sc_time to bool? + return getDistance(write.getStart(), + strobeCommand.getStart()) < CasToCas(strobeCommand, write); + } + else if (strobeCommand.getCommand() == Command::RD || strobeCommand.getCommand() == Command::RDA) + { + 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("CheckerDDR3New", "Invalid strobeCommand in data strobe commands " + + commandToString(strobeCommand.getCommand())); + return true; + } +} + + +sc_time CheckerDDR3New::readToWrite(ScheduledCommand &read, ScheduledCommand &write) const +{ + sc_assert(read.getCommand() == Command::RD + || read.getCommand() == Command::RDA); + sc_assert(write.getCommand() == Command::WR + || write.getCommand() == Command::WRA); + + return memSpec->tRL + memSpec->getReadAccessTime() - memSpec->tWL + memSpec->clk * 2; +} diff --git a/DRAMSys/library/src/controller/core/scheduling/checker/CheckerDDR3New.h b/DRAMSys/library/src/controller/core/scheduling/checker/CheckerDDR3New.h new file mode 100644 index 00000000..53ff3fe3 --- /dev/null +++ b/DRAMSys/library/src/controller/core/scheduling/checker/CheckerDDR3New.h @@ -0,0 +1,58 @@ +#ifndef CHECKERDDR3NEW_H +#define CHECKERDDR3NEW_H + +#include "ICommandChecker.h" +#include "../../configuration/Configuration.h" +#include "../../../ControllerState.h" + +//Activate +class CheckerDDR3New : public ICommandChecker +{ +public: + CheckerDDR3New(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 ~CheckerDDR3New() {} + + virtual void delayToSatisfyConstraints(ScheduledCommand &command) const override; + +private: + MemSpecDDR3 *memSpec; + + //Activate + void delayToSatisfyACTtoACTsameBank(ScheduledCommand &command) const; + bool satsfiesACTtoACTdifferentBank(ScheduledCommand &command) const; + bool satisfiesNActivateWindow(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 + sc_time writeToRead(ScheduledCommand &write, ScheduledCommand &read) const; + + //RD->WR + sc_time readToWrite(ScheduledCommand &read, ScheduledCommand &write) const; + + //CasToCas Commands (WR->WR)(RD->RD) + sc_time CasToCas(ScheduledCommand &firstCAS, ScheduledCommand &secondCAS) const; + + const Configuration &config; + ControllerState &state;//TODO make const +}; + +#endif // CHECKERDDR3NEW_H