diff --git a/DRAMSys/library/src/controller/Controller.cpp b/DRAMSys/library/src/controller/Controller.cpp index 35922e48..8b658d52 100644 --- a/DRAMSys/library/src/controller/Controller.cpp +++ b/DRAMSys/library/src/controller/Controller.cpp @@ -53,11 +53,10 @@ Controller::Controller(sc_module_name name) : GenericController(name) { SC_METHOD(controllerMethod); - sensitive << beginReqEvent << endRespEvent << bankMachineEvent - << refreshEvent << dataResponseEventQueue; + sensitive << beginReqEvent << endRespEvent << controllerEvent << dataResponseEventQueue; dont_initialize(); - Configuration config = Configuration::getInstance(); + Configuration &config = Configuration::getInstance(); MemSpec *memSpec = config.memSpec; maxNumberOfPayloads = config.MaxNrOfTransactions; @@ -127,7 +126,7 @@ Controller::Controller(sc_module_name name) : RefreshManagerIF *manager = new RefreshManagerBankwise (bankMachinesOnRank[rankID], Rank(rankID), checker); refreshManagers.push_back(manager); - refreshEvent.notify(manager->start()); + controllerEvent.notify(manager->start()); } } else @@ -137,7 +136,7 @@ Controller::Controller(sc_module_name name) : RefreshManagerIF *manager = new RefreshManager (bankMachinesOnRank[rankID], Rank(rankID), checker); refreshManagers.push_back(manager); - refreshEvent.notify(manager->start()); + controllerEvent.notify(manager->start()); } } @@ -190,18 +189,22 @@ void Controller::controllerMethod() PRINTDEBUGMESSAGE(name(), "Total number of payloads exceeded, backpressure!"); } - // (4) Choose one request and send it to DRAM + // (4) Start refresh managers to issue requests for the current time + for (auto it : refreshManagers) + it->start(); + + // (5) Choose one request and send it to DRAM std::pair commandPair; std::vector> readyCommands; - // (4.1) Check for refresh command (PREA/PRE or REFA/REFB) - for (auto it : refreshManagers) + // (5.1) Check for bank commands (PRE, ACT, RD/RDA or WR/WRA) + for (auto it : bankMachines) { commandPair = it->getNextCommand(); if (commandPair.second != nullptr) readyCommands.push_back(commandPair); } - // (4.2) Check for other commands (PRE, ACT, RD or WR) - for (auto it : bankMachines) + // (5.2) Check for refresh commands (PREA/PRE or REFA/REFB) + for (auto it : refreshManagers) { commandPair = it->getNextCommand(); if (commandPair.second != nullptr) @@ -228,16 +231,15 @@ void Controller::controllerMethod() } } - // (5) Restart bank machines and refresh managers to issue new requests for the future - for (auto it : refreshManagers) - bankMachineEvent.notify(it->start()); - // TODO: order, first BM then RM? + // (6) Restart bank machines and refresh managers to issue new requests for the future for (auto it : bankMachines) { sc_time delay = it->start(); if (delay != SC_ZERO_TIME) // TODO: must be checked to avoid livelock - bankMachineEvent.notify(delay); + controllerEvent.notify(delay); } + for (auto it : refreshManagers) + controllerEvent.notify(it->start()); } tlm_sync_enum Controller::nb_transport_fw(tlm_generic_payload &trans, diff --git a/DRAMSys/library/src/controller/Controller.h b/DRAMSys/library/src/controller/Controller.h index 1ceca538..fd08a178 100644 --- a/DRAMSys/library/src/controller/Controller.h +++ b/DRAMSys/library/src/controller/Controller.h @@ -91,7 +91,7 @@ private: void acquirePayload(); void controllerMethod(); - sc_event beginReqEvent, endRespEvent, bankMachineEvent, refreshEvent; + sc_event beginReqEvent, endRespEvent, controllerEvent; sc_event_queue dataResponseEventQueue; // Bandwidth related diff --git a/DRAMSys/library/src/controller/checker/CheckerDDR3.cpp b/DRAMSys/library/src/controller/checker/CheckerDDR3.cpp index 2cf18177..5ac42425 100644 --- a/DRAMSys/library/src/controller/checker/CheckerDDR3.cpp +++ b/DRAMSys/library/src/controller/checker/CheckerDDR3.cpp @@ -36,7 +36,7 @@ CheckerDDR3::CheckerDDR3() { - Configuration config = Configuration::getInstance(); + Configuration &config = Configuration::getInstance(); memSpec = dynamic_cast(config.memSpec); if (memSpec == nullptr) SC_REPORT_FATAL("CheckerDDR3", "Wrong MemSpec chosen"); @@ -208,7 +208,7 @@ sc_time CheckerDDR3::delayToSatisfyConstraints(Command command, Rank rank, BankG reportFatal("CheckerDDR3", "Unknown command!"); } // Check if command bus is free - earliestTimeToStart = std::max(earliestTimeToStart, lastScheduled + memSpec->clk); + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandOnBus + memSpec->clk); return (earliestTimeToStart - sc_time_stamp()); } @@ -221,7 +221,7 @@ void CheckerDDR3::insert(Command command, Rank rank, BankGroup, Bank bank) lastScheduledByCommandAndBank[command][bank.ID()] = sc_time_stamp(); lastScheduledByCommandAndRank[command][rank.ID()] = sc_time_stamp(); lastScheduledByCommand[command] = sc_time_stamp(); - lastScheduled = sc_time_stamp(); + lastCommandOnBus = sc_time_stamp(); if (command == Command::ACT) { diff --git a/DRAMSys/library/src/controller/checker/CheckerDDR3.h b/DRAMSys/library/src/controller/checker/CheckerDDR3.h index b901abf9..10723fa2 100644 --- a/DRAMSys/library/src/controller/checker/CheckerDDR3.h +++ b/DRAMSys/library/src/controller/checker/CheckerDDR3.h @@ -54,7 +54,7 @@ private: std::vector> lastScheduledByCommandAndBank; std::vector> lastScheduledByCommandAndRank; std::vector lastScheduledByCommand; - sc_time lastScheduled; + sc_time lastCommandOnBus; // Four activate window std::vector> lastActivates; diff --git a/DRAMSys/library/src/controller/checker/CheckerDDR4.cpp b/DRAMSys/library/src/controller/checker/CheckerDDR4.cpp index f35bd770..80081016 100644 --- a/DRAMSys/library/src/controller/checker/CheckerDDR4.cpp +++ b/DRAMSys/library/src/controller/checker/CheckerDDR4.cpp @@ -36,7 +36,7 @@ CheckerDDR4::CheckerDDR4() { - Configuration config = Configuration::getInstance(); + Configuration &config = Configuration::getInstance(); memSpec = dynamic_cast(config.memSpec); if (memSpec == nullptr) SC_REPORT_FATAL("CheckerDDR4", "Wrong MemSpec chosen"); diff --git a/DRAMSys/library/src/controller/checker/CheckerLPDDR4.cpp b/DRAMSys/library/src/controller/checker/CheckerLPDDR4.cpp index e2dbd2af..825087a7 100644 --- a/DRAMSys/library/src/controller/checker/CheckerLPDDR4.cpp +++ b/DRAMSys/library/src/controller/checker/CheckerLPDDR4.cpp @@ -36,7 +36,7 @@ CheckerLPDDR4::CheckerLPDDR4() { - Configuration config = Configuration::getInstance(); + Configuration &config = Configuration::getInstance(); memSpec = dynamic_cast(config.memSpec); if (memSpec == nullptr) SC_REPORT_FATAL("CheckerLPDDR4", "Wrong MemSpec chosen"); @@ -94,8 +94,8 @@ sc_time CheckerLPDDR4::delayToSatisfyConstraints(Command command, Rank rank, Ban if (lastCommandStart != SC_ZERO_TIME) earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRRD - 2 * memSpec->clk); - if (lastActivates[rank.ID()].size() >= 4) - earliestTimeToStart = std::max(earliestTimeToStart, lastActivates[rank.ID()].front() + memSpec->tFAW); + if (lastActivates[rank.ID()].size() == 4) + earliestTimeToStart = std::max(earliestTimeToStart, lastActivates[rank.ID()].front() + memSpec->tFAW - 3 * memSpec->clk); } else if (command == Command::RD || command == Command::RDA) { @@ -177,9 +177,9 @@ sc_time CheckerLPDDR4::delayToSatisfyConstraints(Command command, Rank rank, Ban if (lastCommandStart != SC_ZERO_TIME) earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tWL + memSpec->tCCD + memSpec->tWR + 3 * memSpec->clk); - lastCommandStart = lastScheduledByCommandAndRank[Command::REFB][rank.ID()]; - if (lastCommandStart != SC_ZERO_TIME) - earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRFCpb); +// lastCommandStart = lastScheduledByCommandAndRank[Command::REFB][rank.ID()]; +// if (lastCommandStart != SC_ZERO_TIME) +// earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRFCpb); } else if (command == Command::REFA) { @@ -208,9 +208,9 @@ sc_time CheckerLPDDR4::delayToSatisfyConstraints(Command command, Rank rank, Ban if (lastCommandStart != SC_ZERO_TIME) earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRFCab); - lastCommandStart = lastScheduledByCommandAndRank[Command::REFB][rank.ID()]; // remove this if REFA and REFB are not mixed - if (lastCommandStart != SC_ZERO_TIME) - earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRFCpb); +// lastCommandStart = lastScheduledByCommandAndRank[Command::REFB][rank.ID()]; +// if (lastCommandStart != SC_ZERO_TIME) +// earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRFCpb); } else if (command == Command::REFB) { @@ -235,17 +235,20 @@ sc_time CheckerLPDDR4::delayToSatisfyConstraints(Command command, Rank rank, Ban if (lastCommandStart != SC_ZERO_TIME) earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRPpb); - lastCommandStart = lastScheduledByCommandAndRank[Command::PREA][rank.ID()]; // remove this - if (lastCommandStart != SC_ZERO_TIME) - earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRPab); +// lastCommandStart = lastScheduledByCommandAndRank[Command::PREA][rank.ID()]; +// if (lastCommandStart != SC_ZERO_TIME) +// earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRPab); - lastCommandStart = lastScheduledByCommandAndRank[Command::REFA][rank.ID()]; // remove this - if (lastCommandStart != SC_ZERO_TIME) - earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRFCab); +// lastCommandStart = lastScheduledByCommandAndRank[Command::REFA][rank.ID()]; +// if (lastCommandStart != SC_ZERO_TIME) +// earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRFCab); lastCommandStart = lastScheduledByCommandAndRank[Command::REFB][rank.ID()]; if (lastCommandStart != SC_ZERO_TIME) earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRFCpb); + + if (lastActivates[rank.ID()].size() == 4) + earliestTimeToStart = std::max(earliestTimeToStart, lastActivates[rank.ID()].front() + memSpec->tFAW - memSpec->clk); } else { @@ -267,10 +270,10 @@ void CheckerLPDDR4::insert(Command command, Rank rank, BankGroup, Bank bank) lastScheduledByCommand[command] = sc_time_stamp(); lastCommandOnBus = sc_time_stamp() + (memSpec->getCommandLength(command) - 1) * memSpec->clk; - if (command == Command::ACT) // TODO: FAW for REFB + if (command == Command::ACT || command == Command::REFB) { if (lastActivates[rank.ID()].size() == 4) lastActivates[rank.ID()].pop(); - lastActivates[rank.ID()].push(sc_time_stamp()); + lastActivates[rank.ID()].push(lastCommandOnBus); } } diff --git a/DRAMSys/library/src/controller/checker/CheckerWideIO.cpp b/DRAMSys/library/src/controller/checker/CheckerWideIO.cpp index 895bbcb2..065f954a 100644 --- a/DRAMSys/library/src/controller/checker/CheckerWideIO.cpp +++ b/DRAMSys/library/src/controller/checker/CheckerWideIO.cpp @@ -36,7 +36,7 @@ CheckerWideIO::CheckerWideIO() { - Configuration config = Configuration::getInstance(); + Configuration &config = Configuration::getInstance(); memSpec = dynamic_cast(config.memSpec); if (memSpec == nullptr) SC_REPORT_FATAL("CheckerWideIO", "Wrong MemSpec chosen"); diff --git a/DRAMSys/library/src/controller/refresh/RefreshManager.cpp b/DRAMSys/library/src/controller/refresh/RefreshManager.cpp index 3935c7d2..962206c2 100644 --- a/DRAMSys/library/src/controller/refresh/RefreshManager.cpp +++ b/DRAMSys/library/src/controller/refresh/RefreshManager.cpp @@ -40,9 +40,15 @@ RefreshManager::RefreshManager(std::vector &bankMachines, Rank rank, CheckerIF *checker) : bankMachines(bankMachines), rank(rank), checker(checker) { - memSpec = Configuration::getInstance().memSpec; + Configuration &config = Configuration::getInstance(); + memSpec = config.memSpec; timeForNextTrigger = memSpec->getRefreshIntervalAB(); setUpDummy(refreshPayload, rank); + + if (config.ControllerCoreRefEnablePostpone) + maxPostponed = config.ControllerCoreRefMaxPostponed; + if (config.ControllerCoreRefEnablePullIn) + maxPulledin = -config.ControllerCoreRefMaxPulledIn; } std::pair RefreshManager::getNextCommand() @@ -60,11 +66,30 @@ sc_time RefreshManager::start() sc_time delay; if (state == RmState::IDLE) { + if (flexibleCounter != maxPostponed || isPulledinRefresh) + { + for (auto it : bankMachines) + { + if (!it->isIdle()) + { + if (!isPulledinRefresh) + flexibleCounter++; + isPulledinRefresh = false; + timeForNextTrigger += memSpec->getRefreshIntervalAB(); + return timeForNextTrigger - sc_time_stamp(); + } + } + } + else + { + for (auto it : bankMachines) + it->block(); + } + // TODO: If we do not block the bankmachines we have to check this each time bool doPrecharge = false; for (auto it : bankMachines) { - it->block(); if (it->getState() == BmState::Activated) doPrecharge = true; } @@ -78,10 +103,11 @@ sc_time RefreshManager::start() { delay = checker->delayToSatisfyConstraints(Command::REFA, rank, BankGroup(0), Bank(0)); nextCommand = Command::REFA; - state = RmState::PRECHARGED; + if (flexibleCounter == maxPostponed) + state = RmState::PRECHARGED; } } - else + else // if (state == RmState::PRECHARGED) { delay = checker->delayToSatisfyConstraints(Command::REFA, rank, BankGroup(0), Bank(0)); nextCommand = Command::REFA; @@ -98,8 +124,22 @@ void RefreshManager::updateState(Command command, tlm_generic_payload *) if (command == Command::REFA) { state = RmState::IDLE; - timeForNextTrigger += memSpec->getRefreshIntervalAB(); + + if (isPulledinRefresh) + flexibleCounter--; + else + isPulledinRefresh = true; + + if (flexibleCounter == maxPulledin) + { + isPulledinRefresh = false; + timeForNextTrigger += memSpec->getRefreshIntervalAB(); + } } else if (command == Command::PREA) + { + for (auto it : bankMachines) + it->block(); state = RmState::PRECHARGED; + } } diff --git a/DRAMSys/library/src/controller/refresh/RefreshManager.h b/DRAMSys/library/src/controller/refresh/RefreshManager.h index 9f730d8e..0bfe6d69 100644 --- a/DRAMSys/library/src/controller/refresh/RefreshManager.h +++ b/DRAMSys/library/src/controller/refresh/RefreshManager.h @@ -61,6 +61,11 @@ private: Rank rank; CheckerIF *checker; Command nextCommand; + + int flexibleCounter = 0; + int maxPostponed = 0; + int maxPulledin = 0; + bool isPulledinRefresh = false; }; #endif // REFRESHMANAGER_H