diff --git a/DRAMSys/library/CMakeLists.txt b/DRAMSys/library/CMakeLists.txt index 8549b70d..4f401e8d 100644 --- a/DRAMSys/library/CMakeLists.txt +++ b/DRAMSys/library/CMakeLists.txt @@ -142,6 +142,7 @@ add_library(DRAMSysLibrary src/controller/scheduler/SchedulerFifo.cpp src/controller/scheduler/SchedulerFrFcfs.cpp src/controller/scheduler/SchedulerFrFcfsGrp.cpp + src/controller/scheduler/SchedulerFrFcfsWatermark.cpp src/controller/scheduler/BufferCounterIF.h src/controller/scheduler/BufferCounterBankwise.cpp diff --git a/DRAMSys/library/src/configuration/Configuration.cpp b/DRAMSys/library/src/configuration/Configuration.cpp index 41d8a994..8846dc7d 100644 --- a/DRAMSys/library/src/configuration/Configuration.cpp +++ b/DRAMSys/library/src/configuration/Configuration.cpp @@ -103,6 +103,8 @@ void Configuration::setParameter(const std::string &name, const nlohmann::json & scheduler = Scheduler::FrFcfs; else if (value == "FrFcfsGrp") scheduler = Scheduler::FrFcfsGrp; + else if (value == "FrFcfsWatermark") + scheduler = Scheduler::FrFcfsWatermark; else SC_REPORT_FATAL("Configuration", "Unsupported scheduler!"); } @@ -117,6 +119,10 @@ void Configuration::setParameter(const std::string &name, const nlohmann::json & else SC_REPORT_FATAL("Configuration", "Unsupported scheduler buffer!"); } + else if (name == "LowWatermark") + lowWatermark = value; + else if (name == "HighWatermark") + highWatermark = value; else if (name == "RequestBufferSize") { requestBufferSize = value; diff --git a/DRAMSys/library/src/configuration/Configuration.h b/DRAMSys/library/src/configuration/Configuration.h index 71f590eb..49450d68 100644 --- a/DRAMSys/library/src/configuration/Configuration.h +++ b/DRAMSys/library/src/configuration/Configuration.h @@ -66,8 +66,10 @@ public: // MCConfig: enum class PagePolicy {Open, Closed, OpenAdaptive, ClosedAdaptive} pagePolicy = PagePolicy::Open; - enum class Scheduler {Fifo, FrFcfs, FrFcfsGrp} scheduler = Scheduler::FrFcfs; + enum class Scheduler {Fifo, FrFcfs, FrFcfsGrp, FrFcfsWatermark} scheduler = Scheduler::FrFcfs; enum class SchedulerBuffer {Bankwise, ReadWrite, Shared} schedulerBuffer = SchedulerBuffer::Bankwise; + unsigned int lowWatermark = 8; + unsigned int highWatermark = 16; enum class CmdMux {Oldest, Strict} cmdMux = CmdMux::Oldest; enum class RespQueue {Fifo, Reorder} respQueue = RespQueue::Fifo; enum class Arbiter {Simple, Fifo, Reorder} arbiter = Arbiter::Simple; diff --git a/DRAMSys/library/src/controller/Controller.cpp b/DRAMSys/library/src/controller/Controller.cpp index 3953620c..25d4ea6e 100644 --- a/DRAMSys/library/src/controller/Controller.cpp +++ b/DRAMSys/library/src/controller/Controller.cpp @@ -52,6 +52,7 @@ #include "scheduler/SchedulerFifo.h" #include "scheduler/SchedulerFrFcfs.h" #include "scheduler/SchedulerFrFcfsGrp.h" +#include "scheduler/SchedulerFrFcfsWatermark.h" #include "cmdmux/CmdMuxStrict.h" #include "cmdmux/CmdMuxOldest.h" #include "respqueue/RespQueueFifo.h" @@ -118,6 +119,8 @@ Controller::Controller(const sc_module_name &name) : scheduler = new SchedulerFrFcfs(); else if (config.scheduler == Configuration::Scheduler::FrFcfsGrp) scheduler = new SchedulerFrFcfsGrp(); + else if (config.scheduler == Configuration::Scheduler::FrFcfsWatermark) + scheduler = new SchedulerFrFcfsWatermark(); if (config.cmdMux == Configuration::CmdMux::Oldest) { diff --git a/DRAMSys/library/src/controller/scheduler/BufferCounterBankwise.cpp b/DRAMSys/library/src/controller/scheduler/BufferCounterBankwise.cpp index 7acc2482..0792d0f1 100644 --- a/DRAMSys/library/src/controller/scheduler/BufferCounterBankwise.cpp +++ b/DRAMSys/library/src/controller/scheduler/BufferCounterBankwise.cpp @@ -48,18 +48,32 @@ bool BufferCounterBankwise::hasBufferSpace() const return (numRequestsOnBank[lastBankID] < requestBufferSize); } -void BufferCounterBankwise::storeRequest(tlm_generic_payload *payload) +void BufferCounterBankwise::storeRequest(const tlm_generic_payload *payload) { lastBankID = DramExtension::getBank(payload).ID(); numRequestsOnBank[lastBankID]++; + if (payload->is_write()) + numWriteRequests++; } -void BufferCounterBankwise::removeRequest(tlm_generic_payload *payload) +void BufferCounterBankwise::removeRequest(const tlm_generic_payload *payload) { numRequestsOnBank[DramExtension::getBank(payload).ID()]--; + if (payload->is_write()) + numWriteRequests--; } const std::vector &BufferCounterBankwise::getBufferDepth() const { return numRequestsOnBank; } + +unsigned BufferCounterBankwise::getNumReadRequests() const +{ + return numReadRequests; +} + +unsigned BufferCounterBankwise::getNumWriteRequests() const +{ + return numWriteRequests; +} \ No newline at end of file diff --git a/DRAMSys/library/src/controller/scheduler/BufferCounterBankwise.h b/DRAMSys/library/src/controller/scheduler/BufferCounterBankwise.h index 02725b81..821e28b8 100644 --- a/DRAMSys/library/src/controller/scheduler/BufferCounterBankwise.h +++ b/DRAMSys/library/src/controller/scheduler/BufferCounterBankwise.h @@ -45,14 +45,18 @@ class BufferCounterBankwise final : public BufferCounterIF public: BufferCounterBankwise(unsigned requestBufferSize, unsigned numberOfBanks); bool hasBufferSpace() const override; - void storeRequest(tlm::tlm_generic_payload *payload) override; - void removeRequest(tlm::tlm_generic_payload *payload) override; + void storeRequest(const tlm::tlm_generic_payload *payload) override; + void removeRequest(const tlm::tlm_generic_payload *payload) override; const std::vector &getBufferDepth() const override; + unsigned getNumReadRequests() const override; + unsigned getNumWriteRequests() const override; private: const unsigned requestBufferSize; std::vector numRequestsOnBank; unsigned lastBankID = 0; + unsigned numReadRequests = 0; + unsigned numWriteRequests = 0; }; #endif // BUFFERCOUNTERBANKWISE_H diff --git a/DRAMSys/library/src/controller/scheduler/BufferCounterIF.h b/DRAMSys/library/src/controller/scheduler/BufferCounterIF.h index 38ca4340..d0c0d3b5 100644 --- a/DRAMSys/library/src/controller/scheduler/BufferCounterIF.h +++ b/DRAMSys/library/src/controller/scheduler/BufferCounterIF.h @@ -44,9 +44,11 @@ class BufferCounterIF public: virtual ~BufferCounterIF() = default; virtual bool hasBufferSpace() const = 0; - virtual void storeRequest(tlm::tlm_generic_payload *payload) = 0; - virtual void removeRequest(tlm::tlm_generic_payload *payload) = 0; + virtual void storeRequest(const tlm::tlm_generic_payload *payload) = 0; + virtual void removeRequest(const tlm::tlm_generic_payload *payload) = 0; virtual const std::vector &getBufferDepth() const = 0; + virtual unsigned getNumReadRequests() const = 0; + virtual unsigned getNumWriteRequests() const = 0; }; #endif // BUFFERCOUNTERIF_H diff --git a/DRAMSys/library/src/controller/scheduler/BufferCounterReadWrite.cpp b/DRAMSys/library/src/controller/scheduler/BufferCounterReadWrite.cpp index 3a036e0a..837b7d65 100644 --- a/DRAMSys/library/src/controller/scheduler/BufferCounterReadWrite.cpp +++ b/DRAMSys/library/src/controller/scheduler/BufferCounterReadWrite.cpp @@ -47,7 +47,7 @@ bool BufferCounterReadWrite::hasBufferSpace() const return (numReadWriteRequests[0] < requestBufferSize && numReadWriteRequests[1] < requestBufferSize); } -void BufferCounterReadWrite::storeRequest(tlm_generic_payload *payload) +void BufferCounterReadWrite::storeRequest(const tlm_generic_payload *payload) { if (payload->is_read()) numReadWriteRequests[0]++; @@ -55,7 +55,7 @@ void BufferCounterReadWrite::storeRequest(tlm_generic_payload *payload) numReadWriteRequests[1]++; } -void BufferCounterReadWrite::removeRequest(tlm_generic_payload *payload) +void BufferCounterReadWrite::removeRequest(const tlm_generic_payload *payload) { if (payload->is_read()) numReadWriteRequests[0]--; @@ -67,3 +67,13 @@ const std::vector &BufferCounterReadWrite::getBufferDepth() const { return numReadWriteRequests; } + +unsigned BufferCounterReadWrite::getNumReadRequests() const +{ + return numReadWriteRequests[0]; +} + +unsigned BufferCounterReadWrite::getNumWriteRequests() const +{ + return numReadWriteRequests[1]; +} \ No newline at end of file diff --git a/DRAMSys/library/src/controller/scheduler/BufferCounterReadWrite.h b/DRAMSys/library/src/controller/scheduler/BufferCounterReadWrite.h index f0d28a90..d783f480 100644 --- a/DRAMSys/library/src/controller/scheduler/BufferCounterReadWrite.h +++ b/DRAMSys/library/src/controller/scheduler/BufferCounterReadWrite.h @@ -45,9 +45,11 @@ class BufferCounterReadWrite final : public BufferCounterIF public: explicit BufferCounterReadWrite(unsigned requestBufferSize); bool hasBufferSpace() const override; - void storeRequest(tlm::tlm_generic_payload *payload) override; - void removeRequest(tlm::tlm_generic_payload *payload) override; + void storeRequest(const tlm::tlm_generic_payload *payload) override; + void removeRequest(const tlm::tlm_generic_payload *payload) override; const std::vector &getBufferDepth() const override; + unsigned getNumReadRequests() const override; + unsigned getNumWriteRequests() const override; private: const unsigned requestBufferSize; diff --git a/DRAMSys/library/src/controller/scheduler/BufferCounterShared.cpp b/DRAMSys/library/src/controller/scheduler/BufferCounterShared.cpp index a4b80ef1..55821ff5 100644 --- a/DRAMSys/library/src/controller/scheduler/BufferCounterShared.cpp +++ b/DRAMSys/library/src/controller/scheduler/BufferCounterShared.cpp @@ -47,17 +47,31 @@ bool BufferCounterShared::hasBufferSpace() const return (numRequests[0] < requestBufferSize); } -void BufferCounterShared::storeRequest(tlm_generic_payload *) +void BufferCounterShared::storeRequest(const tlm_generic_payload *trans) { numRequests[0]++; + if (trans->is_write()) + numWriteRequests++; } -void BufferCounterShared::removeRequest(tlm_generic_payload *) +void BufferCounterShared::removeRequest(const tlm_generic_payload *trans) { numRequests[0]--; + if (trans->is_write()) + numWriteRequests--; } const std::vector &BufferCounterShared::getBufferDepth() const { return numRequests; } + +unsigned BufferCounterShared::getNumReadRequests() const +{ + return numReadRequests; +} + +unsigned BufferCounterShared::getNumWriteRequests() const +{ + return numWriteRequests; +} diff --git a/DRAMSys/library/src/controller/scheduler/BufferCounterShared.h b/DRAMSys/library/src/controller/scheduler/BufferCounterShared.h index 7e530579..7a760bd6 100644 --- a/DRAMSys/library/src/controller/scheduler/BufferCounterShared.h +++ b/DRAMSys/library/src/controller/scheduler/BufferCounterShared.h @@ -45,13 +45,17 @@ class BufferCounterShared final : public BufferCounterIF public: explicit BufferCounterShared(unsigned requestBufferSize); bool hasBufferSpace() const override; - void storeRequest(tlm::tlm_generic_payload *payload) override; - void removeRequest(tlm::tlm_generic_payload *payload) override; + void storeRequest(const tlm::tlm_generic_payload *payload) override; + void removeRequest(const tlm::tlm_generic_payload *payload) override; const std::vector &getBufferDepth() const override; + unsigned getNumReadRequests() const override; + unsigned getNumWriteRequests() const override; private: const unsigned requestBufferSize; std::vector numRequests; + unsigned numReadRequests = 0; + unsigned numWriteRequests = 0; }; #endif // BUFFERCOUNTERSHARED_H diff --git a/DRAMSys/library/src/controller/scheduler/SchedulerFifo.cpp b/DRAMSys/library/src/controller/scheduler/SchedulerFifo.cpp index 90d38301..bd17c244 100644 --- a/DRAMSys/library/src/controller/scheduler/SchedulerFifo.cpp +++ b/DRAMSys/library/src/controller/scheduler/SchedulerFifo.cpp @@ -75,7 +75,7 @@ void SchedulerFifo::removeRequest(tlm_generic_payload *payload) bufferCounter->removeRequest(payload); } -tlm_generic_payload *SchedulerFifo::getNextRequest(BankMachine *bankMachine) const +tlm_generic_payload *SchedulerFifo::getNextRequest(const BankMachine *bankMachine) const { unsigned bankID = bankMachine->getBank().ID(); if (!buffer[bankID].empty()) diff --git a/DRAMSys/library/src/controller/scheduler/SchedulerFifo.h b/DRAMSys/library/src/controller/scheduler/SchedulerFifo.h index b6c6f645..94af4765 100644 --- a/DRAMSys/library/src/controller/scheduler/SchedulerFifo.h +++ b/DRAMSys/library/src/controller/scheduler/SchedulerFifo.h @@ -52,7 +52,7 @@ public: bool hasBufferSpace() const override; void storeRequest(tlm::tlm_generic_payload *) override; void removeRequest(tlm::tlm_generic_payload *) override; - tlm::tlm_generic_payload *getNextRequest(BankMachine *) const override; + tlm::tlm_generic_payload *getNextRequest(const BankMachine *) const override; bool hasFurtherRowHit(Bank, Row) const override; bool hasFurtherRequest(Bank) const override; const std::vector &getBufferDepth() const override; diff --git a/DRAMSys/library/src/controller/scheduler/SchedulerFrFcfs.cpp b/DRAMSys/library/src/controller/scheduler/SchedulerFrFcfs.cpp index 23f6046e..7b91e9ba 100644 --- a/DRAMSys/library/src/controller/scheduler/SchedulerFrFcfs.cpp +++ b/DRAMSys/library/src/controller/scheduler/SchedulerFrFcfs.cpp @@ -83,7 +83,7 @@ void SchedulerFrFcfs::removeRequest(tlm_generic_payload *payload) } } -tlm_generic_payload *SchedulerFrFcfs::getNextRequest(BankMachine *bankMachine) const +tlm_generic_payload *SchedulerFrFcfs::getNextRequest(const BankMachine *bankMachine) const { unsigned bankID = bankMachine->getBank().ID(); if (!buffer[bankID].empty()) diff --git a/DRAMSys/library/src/controller/scheduler/SchedulerFrFcfs.h b/DRAMSys/library/src/controller/scheduler/SchedulerFrFcfs.h index 0f5bd219..e445b2f5 100644 --- a/DRAMSys/library/src/controller/scheduler/SchedulerFrFcfs.h +++ b/DRAMSys/library/src/controller/scheduler/SchedulerFrFcfs.h @@ -52,7 +52,7 @@ public: bool hasBufferSpace() const override; void storeRequest(tlm::tlm_generic_payload *) override; void removeRequest(tlm::tlm_generic_payload *) override; - tlm::tlm_generic_payload *getNextRequest(BankMachine *) const override; + tlm::tlm_generic_payload *getNextRequest(const BankMachine *) const override; bool hasFurtherRowHit(Bank, Row) const override; bool hasFurtherRequest(Bank) const override; const std::vector &getBufferDepth() const override; diff --git a/DRAMSys/library/src/controller/scheduler/SchedulerFrFcfsGrp.cpp b/DRAMSys/library/src/controller/scheduler/SchedulerFrFcfsGrp.cpp index 16177905..ffe60a34 100644 --- a/DRAMSys/library/src/controller/scheduler/SchedulerFrFcfsGrp.cpp +++ b/DRAMSys/library/src/controller/scheduler/SchedulerFrFcfsGrp.cpp @@ -84,49 +84,100 @@ void SchedulerFrFcfsGrp::removeRequest(tlm_generic_payload *payload) } } -tlm_generic_payload *SchedulerFrFcfsGrp::getNextRequest(BankMachine *bankMachine) const +tlm_generic_payload *SchedulerFrFcfsGrp::getNextRequest(const BankMachine *bankMachine) const { + // search row hits, search wrd/wr hits + // search rd/wr hits, search row hits unsigned bankID = bankMachine->getBank().ID(); if (!buffer[bankID].empty()) { - if (bankMachine->isActivated()) + if (lastCommand == tlm::TLM_READ_COMMAND) { - // Filter all row hits - Row openRow = bankMachine->getOpenRow(); - std::list rowHits; - for (auto it : buffer[bankID]) + // Filter out read requests + std::vector readRequests; + for (auto it: buffer[bankID]) { - if (DramExtension::getRow(it) == openRow) - rowHits.push_back(it); + if (it->is_read()) + readRequests.push_back(it); } - if (!rowHits.empty()) + if (!readRequests.empty()) { - for (auto outerIt = rowHits.begin(); outerIt != rowHits.end(); outerIt++) + if (bankMachine->isActivated()) { - if ((*outerIt)->get_command() == lastCommand) + // Search for row hit + Row openRow = bankMachine->getOpenRow(); + for (auto it: readRequests) { - bool hazardDetected = false; - for (auto innerIt = rowHits.begin(); *innerIt != *outerIt; innerIt++) - { - if ((*outerIt)->get_address() == (*innerIt)->get_address()) - { - hazardDetected = true; - break; - } - } - if (!hazardDetected) - return *outerIt; + if (DramExtension::getRow(it) == openRow) + return it; } } - // no rd/wr hit found -> take first row hit - return *rowHits.begin(); + // No row hit found or bank precharged + return readRequests.front(); + } + else + { + const std::list& writeRequests = buffer[bankID]; + if (bankMachine->isActivated()) + { + // Search for row hit + Row openRow = bankMachine->getOpenRow(); + for (auto it: writeRequests) + { + if (DramExtension::getRow(it) == openRow) + return it; + } + } + // No row hit found or bank precharged + return writeRequests.front(); + } + } + else + { + // Filter out write requests + std::vector writeRequests; + for (auto it: buffer[bankID]) + { + if (it->is_write()) + writeRequests.push_back(it); + } + + if (!writeRequests.empty()) + { + if (bankMachine->isActivated()) + { + // Search for row hit + Row openRow = bankMachine->getOpenRow(); + for (auto it: writeRequests) + { + if (DramExtension::getRow(it) == openRow) + return it; + } + } + // No row hit found or bank precharged + return writeRequests.front(); + } + else + { + const std::list& readRequests = buffer[bankID]; + if (bankMachine->isActivated()) + { + // Search for row hit + Row openRow = bankMachine->getOpenRow(); + for (auto it: readRequests) + { + if (DramExtension::getRow(it) == openRow) + return it; + } + } + // No row hit found or bank precharged + return readRequests.front(); } } - // No row hit found or bank precharged - return buffer[bankID].front(); } - return nullptr; + else + return nullptr; } bool SchedulerFrFcfsGrp::hasFurtherRowHit(Bank bank, Row row) const diff --git a/DRAMSys/library/src/controller/scheduler/SchedulerFrFcfsGrp.h b/DRAMSys/library/src/controller/scheduler/SchedulerFrFcfsGrp.h index 7090b9cb..80f4cf9e 100644 --- a/DRAMSys/library/src/controller/scheduler/SchedulerFrFcfsGrp.h +++ b/DRAMSys/library/src/controller/scheduler/SchedulerFrFcfsGrp.h @@ -52,7 +52,7 @@ public: bool hasBufferSpace() const override; void storeRequest(tlm::tlm_generic_payload *) override; void removeRequest(tlm::tlm_generic_payload *) override; - tlm::tlm_generic_payload *getNextRequest(BankMachine *) const override; + tlm::tlm_generic_payload *getNextRequest(const BankMachine *) const override; bool hasFurtherRowHit(Bank, Row) const override; bool hasFurtherRequest(Bank) const override; const std::vector &getBufferDepth() const override; diff --git a/DRAMSys/library/src/controller/scheduler/SchedulerFrFcfsWatermark.cpp b/DRAMSys/library/src/controller/scheduler/SchedulerFrFcfsWatermark.cpp new file mode 100644 index 00000000..bc8f6fc8 --- /dev/null +++ b/DRAMSys/library/src/controller/scheduler/SchedulerFrFcfsWatermark.cpp @@ -0,0 +1,194 @@ +/* + * Copyright (c) 2022, Technische Universität Kaiserslautern + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER + * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Author: Lukas Steiner + */ + +#include "SchedulerFrFcfsWatermark.h" +#include "../../configuration/Configuration.h" +#include "BufferCounterBankwise.h" +#include "BufferCounterReadWrite.h" +#include "BufferCounterShared.h" + +using namespace tlm; + +SchedulerFrFcfsWatermark::SchedulerFrFcfsWatermark() : lowWatermark(0), highWatermark(0) +{ + Configuration &config = Configuration::getInstance(); + readBuffer = std::vector>(config.memSpec->numberOfBanks); + writeBuffer = std::vector>(config.memSpec->numberOfBanks); + + if (config.schedulerBuffer == Configuration::SchedulerBuffer::Bankwise) + bufferCounter = new BufferCounterBankwise(config.requestBufferSize, config.memSpec->numberOfBanks); + else if (config.schedulerBuffer == Configuration::SchedulerBuffer::ReadWrite) + bufferCounter = new BufferCounterReadWrite(config.requestBufferSize); + else if (config.schedulerBuffer == Configuration::SchedulerBuffer::Shared) + bufferCounter = new BufferCounterShared(config.requestBufferSize); + + lowWatermark = config.lowWatermark; + highWatermark = config.highWatermark; +} + +SchedulerFrFcfsWatermark::~SchedulerFrFcfsWatermark() +{ + delete bufferCounter; +} + +bool SchedulerFrFcfsWatermark::hasBufferSpace() const +{ + return bufferCounter->hasBufferSpace(); +} + +void SchedulerFrFcfsWatermark::storeRequest(tlm_generic_payload *payload) +{ + if (payload->is_read()) + readBuffer[DramExtension::getBank(payload).ID()].push_back(payload); + else + writeBuffer[DramExtension::getBank(payload).ID()].push_back(payload); + bufferCounter->storeRequest(payload); + evaluateWriteMode(); +} + +void SchedulerFrFcfsWatermark::removeRequest(tlm_generic_payload *payload) +{ + bufferCounter->removeRequest(payload); + unsigned bankID = DramExtension::getBank(payload).ID(); + + if (payload->is_read()) + readBuffer[bankID].remove(payload); + else + writeBuffer[bankID].remove(payload); + + evaluateWriteMode(); +} + +tlm_generic_payload *SchedulerFrFcfsWatermark::getNextRequest(const BankMachine *bankMachine) const +{ + unsigned bankID = bankMachine->getBank().ID(); + if (!writeMode) + { + if (!readBuffer[bankID].empty()) + { + if (bankMachine->isActivated()) + { + // Search for row hit + Row openRow = bankMachine->getOpenRow(); + for (auto it : readBuffer[bankID]) + { + if (DramExtension::getRow(it) == openRow) + return it; + } + } + // No row hit found or bank precharged + return readBuffer[bankID].front(); + } + else + return nullptr; + } + else + { + if (!writeBuffer[bankID].empty()) + { + if (bankMachine->isActivated()) + { + // Search for row hit + Row openRow = bankMachine->getOpenRow(); + for (auto it : writeBuffer[bankID]) + { + if (DramExtension::getRow(it) == openRow) + return it; + } + } + // No row hit found or bank precharged + return writeBuffer[bankID].front(); + } + else + return nullptr; + } +} + +bool SchedulerFrFcfsWatermark::hasFurtherRowHit(Bank bank, Row row) const +{ + unsigned rowHitCounter = 0; + if (!writeMode) + { + for (auto it : readBuffer[bank.ID()]) + { + if (DramExtension::getRow(it) == row) + { + rowHitCounter++; + if (rowHitCounter == 2) + return true; + } + } + return false; + } + else + { + for (auto it : writeBuffer[bank.ID()]) + { + if (DramExtension::getRow(it) == row) + { + rowHitCounter++; + if (rowHitCounter == 2) + return true; + } + } + return false; + } +} + +bool SchedulerFrFcfsWatermark::hasFurtherRequest(Bank bank) const +{ + if (!writeMode) + return (readBuffer[bank.ID()].size() >= 2); + else + return (writeBuffer[bank.ID()].size() >= 2); +} + +const std::vector &SchedulerFrFcfsWatermark::getBufferDepth() const +{ + return bufferCounter->getBufferDepth(); +} + +void SchedulerFrFcfsWatermark::evaluateWriteMode() +{ + if (writeMode) + { + if (bufferCounter->getNumWriteRequests() <= lowWatermark && bufferCounter->getNumReadRequests() != 0) + writeMode = false; + } + else + { + if (bufferCounter->getNumWriteRequests() > highWatermark || bufferCounter->getNumReadRequests() == 0) + writeMode = true; + } +} \ No newline at end of file diff --git a/DRAMSys/library/src/controller/scheduler/SchedulerFrFcfsWatermark.h b/DRAMSys/library/src/controller/scheduler/SchedulerFrFcfsWatermark.h new file mode 100644 index 00000000..881a3aea --- /dev/null +++ b/DRAMSys/library/src/controller/scheduler/SchedulerFrFcfsWatermark.h @@ -0,0 +1,71 @@ +/* + * Copyright (c) 2022, Technische Universität Kaiserslautern + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER + * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Author: Lukas Steiner + */ + +#ifndef SCHEDULERFRFCFSWATERMARK_H +#define SCHEDULERFRFCFSWATERMARK_H + +#include +#include + +#include +#include "SchedulerIF.h" +#include "../../common/dramExtensions.h" +#include "../BankMachine.h" +#include "BufferCounterIF.h" + +class SchedulerFrFcfsWatermark final : public SchedulerIF +{ +public: + SchedulerFrFcfsWatermark(); + ~SchedulerFrFcfsWatermark() override; + bool hasBufferSpace() const override; + void storeRequest(tlm::tlm_generic_payload *) override; + void removeRequest(tlm::tlm_generic_payload *) override; + tlm::tlm_generic_payload *getNextRequest(const BankMachine *) const override; + bool hasFurtherRowHit(Bank, Row) const override; + bool hasFurtherRequest(Bank) const override; + const std::vector &getBufferDepth() const override; + +private: + void evaluateWriteMode(); + + std::vector> readBuffer; + std::vector> writeBuffer; + BufferCounterIF *bufferCounter; + unsigned lowWatermark; + unsigned highWatermark; + bool writeMode = false; +}; + +#endif // SCHEDULERFRFCFSWATERMARK_H diff --git a/DRAMSys/library/src/controller/scheduler/SchedulerIF.h b/DRAMSys/library/src/controller/scheduler/SchedulerIF.h index a440f8bb..a34f9972 100644 --- a/DRAMSys/library/src/controller/scheduler/SchedulerIF.h +++ b/DRAMSys/library/src/controller/scheduler/SchedulerIF.h @@ -49,7 +49,7 @@ public: virtual bool hasBufferSpace() const = 0; virtual void storeRequest(tlm::tlm_generic_payload *) = 0; virtual void removeRequest(tlm::tlm_generic_payload *) = 0; - virtual tlm::tlm_generic_payload *getNextRequest(BankMachine *) const = 0; + virtual tlm::tlm_generic_payload *getNextRequest(const BankMachine *) const = 0; virtual bool hasFurtherRowHit(Bank, Row) const = 0; virtual bool hasFurtherRequest(Bank) const = 0; virtual const std::vector &getBufferDepth() const = 0;