Finalize new schedulers.

This commit is contained in:
Lukas Steiner
2022-03-07 10:25:39 +01:00
parent 6d0be56a3d
commit 7f9646961c
24 changed files with 477 additions and 242 deletions

View File

@@ -142,7 +142,8 @@ 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/SchedulerGrpFrFcfs.cpp
src/controller/scheduler/SchedulerGrpFrFcfsWm.cpp
src/controller/scheduler/BufferCounterIF.h
src/controller/scheduler/BufferCounterBankwise.cpp

View File

@@ -70,13 +70,17 @@ enum class Scheduler
Fifo,
FrFcfs,
FrFcfsGrp,
GrpFrFcfs,
GrpFrFcfsWm,
Invalid = -1
};
NLOHMANN_JSON_SERIALIZE_ENUM(Scheduler, {{Scheduler::Invalid, nullptr},
{Scheduler::Fifo, "Fifo"},
{Scheduler::FrFcfs, "FrFcfs"},
{Scheduler::FrFcfsGrp, "FrFcfsGrp"}})
{Scheduler::FrFcfsGrp, "FrFcfsGrp"},
{Scheduler::GrpFrFcfs, "GrpFrFcfs"},
{Scheduler::GrpFrFcfsWm, "GrpFrFcfsWm"}})
enum class SchedulerBuffer
{

View File

@@ -196,8 +196,12 @@ void Configuration::loadMCConfig(Configuration &config, const DRAMSysConfigurati
return Scheduler::Fifo;
else if (scheduler == DRAMSysConfiguration::Scheduler::FrFcfs)
return Scheduler::FrFcfs;
else
else if (scheduler == DRAMSysConfiguration::Scheduler::FrFcfsGrp)
return Scheduler::FrFcfsGrp;
else if (scheduler == DRAMSysConfiguration::Scheduler::GrpFrFcfs)
return Scheduler::GrpFrFcfs;
else
return Scheduler::GrpFrFcfsWm;
}();
if (const auto &schedulerBuffer = mcConfig.schedulerBuffer)

View File

@@ -64,7 +64,7 @@ private:
public:
// MCConfig:
enum class PagePolicy {Open, Closed, OpenAdaptive, ClosedAdaptive} pagePolicy = PagePolicy::Open;
enum class Scheduler {Fifo, FrFcfs, FrFcfsGrp, FrFcfsWatermark} scheduler = Scheduler::FrFcfs;
enum class Scheduler {Fifo, FrFcfs, FrFcfsGrp, GrpFrFcfs, GrpFrFcfsWm} scheduler = Scheduler::FrFcfs;
enum class SchedulerBuffer {Bankwise, ReadWrite, Shared} schedulerBuffer = SchedulerBuffer::Bankwise;
unsigned int lowWatermark = 8;
unsigned int highWatermark = 16;

View File

@@ -165,7 +165,7 @@ sc_time BankMachineOpen::start()
if (!(sleeping || blocked))
{
currentPayload = scheduler.getNextRequest(this);
currentPayload = scheduler.getNextRequest(*this);
if (currentPayload != nullptr)
{
if (state == State::Precharged) // bank precharged
@@ -200,7 +200,7 @@ sc_time BankMachineClosed::start()
if (!(sleeping || blocked))
{
currentPayload = scheduler.getNextRequest(this);
currentPayload = scheduler.getNextRequest(*this);
if (currentPayload != nullptr)
{
if (state == State::Precharged) // bank precharged
@@ -230,7 +230,7 @@ sc_time BankMachineOpenAdaptive::start()
if (!(sleeping || blocked))
{
currentPayload = scheduler.getNextRequest(this);
currentPayload = scheduler.getNextRequest(*this);
if (currentPayload != nullptr)
{
if (state == State::Precharged) // bank precharged
@@ -239,7 +239,8 @@ sc_time BankMachineOpenAdaptive::start()
{
if (DramExtension::getRow(currentPayload) == openRow) // row hit
{
if (scheduler.hasFurtherRequest(bank) && !scheduler.hasFurtherRowHit(bank, openRow))
if (scheduler.hasFurtherRequest(bank, currentPayload->get_command())
&&!scheduler.hasFurtherRowHit(bank, openRow, currentPayload->get_command()))
{
if (currentPayload->is_read())
nextCommand = Command::RDA;
@@ -277,7 +278,7 @@ sc_time BankMachineClosedAdaptive::start()
if (!(sleeping || blocked))
{
currentPayload = scheduler.getNextRequest(this);
currentPayload = scheduler.getNextRequest(*this);
if (currentPayload != nullptr)
{
if (state == State::Precharged && !blocked) // bank precharged
@@ -286,7 +287,7 @@ sc_time BankMachineClosedAdaptive::start()
{
if (DramExtension::getRow(currentPayload) == openRow) // row hit
{
if (scheduler.hasFurtherRowHit(bank, openRow))
if (scheduler.hasFurtherRowHit(bank, openRow, currentPayload->get_command()))
{
if (currentPayload->is_read())
nextCommand = Command::RD;

View File

@@ -52,6 +52,8 @@
#include "scheduler/SchedulerFifo.h"
#include "scheduler/SchedulerFrFcfs.h"
#include "scheduler/SchedulerFrFcfsGrp.h"
#include "scheduler/SchedulerGrpFrFcfs.h"
#include "scheduler/SchedulerGrpFrFcfsWm.h"
#include "cmdmux/CmdMuxStrict.h"
#include "cmdmux/CmdMuxOldest.h"
#include "respqueue/RespQueueFifo.h"
@@ -118,6 +120,10 @@ Controller::Controller(const sc_module_name &name) :
scheduler = std::make_unique<SchedulerFrFcfs>();
else if (config.scheduler == Configuration::Scheduler::FrFcfsGrp)
scheduler = std::make_unique<SchedulerFrFcfsGrp>();
else if (config.scheduler == Configuration::Scheduler::GrpFrFcfs)
scheduler = std::make_unique<SchedulerGrpFrFcfs>();
else if (config.scheduler == Configuration::Scheduler::GrpFrFcfsWm)
scheduler = std::make_unique<SchedulerGrpFrFcfsWm>();
if (config.cmdMux == Configuration::CmdMux::Oldest)
{
@@ -314,7 +320,7 @@ void Controller::controllerMethod()
if (command.isCasCommand())
{
scheduler->removeRequest(payload);
scheduler->removeRequest(*payload);
manageRequests(thinkDelayFw);
respQueue->insertPayload(payload, sc_time_stamp()
+ thinkDelayFw + phyDelayFw
@@ -417,7 +423,7 @@ void Controller::manageRequests(const sc_time &delay)
ranksNumberOfPayloads[rank.ID()]++;
scheduler->storeRequest(transToAcquire.payload);
scheduler->storeRequest(*transToAcquire.payload);
transToAcquire.payload->acquire();
Bank bank = DramExtension::getBank(transToAcquire.payload);

View File

@@ -48,18 +48,22 @@ bool BufferCounterBankwise::hasBufferSpace() const
return (numRequestsOnBank[lastBankID] < requestBufferSize);
}
void BufferCounterBankwise::storeRequest(const tlm_generic_payload *payload)
void BufferCounterBankwise::storeRequest(const tlm_generic_payload& trans)
{
lastBankID = DramExtension::getBank(payload).ID();
lastBankID = DramExtension::getBank(trans).ID();
numRequestsOnBank[lastBankID]++;
if (payload->is_write())
if (trans.is_read())
numReadRequests++;
else
numWriteRequests++;
}
void BufferCounterBankwise::removeRequest(const tlm_generic_payload *payload)
void BufferCounterBankwise::removeRequest(const tlm_generic_payload& trans)
{
numRequestsOnBank[DramExtension::getBank(payload).ID()]--;
if (payload->is_write())
numRequestsOnBank[DramExtension::getBank(trans).ID()]--;
if (trans.is_read())
numReadRequests--;
else
numWriteRequests--;
}

View File

@@ -45,8 +45,8 @@ class BufferCounterBankwise final : public BufferCounterIF
public:
BufferCounterBankwise(unsigned requestBufferSize, unsigned numberOfBanks);
bool hasBufferSpace() const override;
void storeRequest(const tlm::tlm_generic_payload *payload) override;
void removeRequest(const tlm::tlm_generic_payload *payload) override;
void storeRequest(const tlm::tlm_generic_payload& trans) override;
void removeRequest(const tlm::tlm_generic_payload& trans) override;
const std::vector<unsigned> &getBufferDepth() const override;
unsigned getNumReadRequests() const override;
unsigned getNumWriteRequests() const override;

View File

@@ -44,8 +44,8 @@ class BufferCounterIF
public:
virtual ~BufferCounterIF() = default;
virtual bool hasBufferSpace() const = 0;
virtual void storeRequest(const tlm::tlm_generic_payload *payload) = 0;
virtual void removeRequest(const tlm::tlm_generic_payload *payload) = 0;
virtual void storeRequest(const tlm::tlm_generic_payload& trans) = 0;
virtual void removeRequest(const tlm::tlm_generic_payload& trans) = 0;
virtual const std::vector<unsigned> &getBufferDepth() const = 0;
virtual unsigned getNumReadRequests() const = 0;
virtual unsigned getNumWriteRequests() const = 0;

View File

@@ -47,17 +47,17 @@ bool BufferCounterReadWrite::hasBufferSpace() const
return (numReadWriteRequests[0] < requestBufferSize && numReadWriteRequests[1] < requestBufferSize);
}
void BufferCounterReadWrite::storeRequest(const tlm_generic_payload *payload)
void BufferCounterReadWrite::storeRequest(const tlm_generic_payload& trans)
{
if (payload->is_read())
if (trans.is_read())
numReadWriteRequests[0]++;
else
numReadWriteRequests[1]++;
}
void BufferCounterReadWrite::removeRequest(const tlm_generic_payload *payload)
void BufferCounterReadWrite::removeRequest(const tlm_generic_payload& trans)
{
if (payload->is_read())
if (trans.is_read())
numReadWriteRequests[0]--;
else
numReadWriteRequests[1]--;

View File

@@ -45,8 +45,8 @@ class BufferCounterReadWrite final : public BufferCounterIF
public:
explicit BufferCounterReadWrite(unsigned requestBufferSize);
bool hasBufferSpace() const override;
void storeRequest(const tlm::tlm_generic_payload *payload) override;
void removeRequest(const tlm::tlm_generic_payload *payload) override;
void storeRequest(const tlm::tlm_generic_payload& trans) override;
void removeRequest(const tlm::tlm_generic_payload& trans) override;
const std::vector<unsigned> &getBufferDepth() const override;
unsigned getNumReadRequests() const override;
unsigned getNumWriteRequests() const override;

View File

@@ -47,17 +47,21 @@ bool BufferCounterShared::hasBufferSpace() const
return (numRequests[0] < requestBufferSize);
}
void BufferCounterShared::storeRequest(const tlm_generic_payload *trans)
void BufferCounterShared::storeRequest(const tlm_generic_payload& trans)
{
numRequests[0]++;
if (trans->is_write())
if (trans.is_read())
numReadRequests++;
else
numWriteRequests++;
}
void BufferCounterShared::removeRequest(const tlm_generic_payload *trans)
void BufferCounterShared::removeRequest(const tlm_generic_payload& trans)
{
numRequests[0]--;
if (trans->is_write())
if (trans.is_read())
numReadRequests--;
else
numWriteRequests--;
}

View File

@@ -45,8 +45,8 @@ class BufferCounterShared final : public BufferCounterIF
public:
explicit BufferCounterShared(unsigned requestBufferSize);
bool hasBufferSpace() const override;
void storeRequest(const tlm::tlm_generic_payload *payload) override;
void removeRequest(const tlm::tlm_generic_payload *payload) override;
void storeRequest(const tlm::tlm_generic_payload& trans) override;
void removeRequest(const tlm::tlm_generic_payload& trans) override;
const std::vector<unsigned> &getBufferDepth() const override;
unsigned getNumReadRequests() const override;
unsigned getNumWriteRequests() const override;

View File

@@ -46,16 +46,11 @@ SchedulerFifo::SchedulerFifo()
buffer = std::vector<std::deque<tlm_generic_payload *>>(config.memSpec->banksPerChannel);
if (config.schedulerBuffer == Configuration::SchedulerBuffer::Bankwise)
bufferCounter = new BufferCounterBankwise(config.requestBufferSize, config.memSpec->banksPerChannel);
bufferCounter = std::make_unique<BufferCounterBankwise>(config.requestBufferSize, config.memSpec->banksPerChannel);
else if (config.schedulerBuffer == Configuration::SchedulerBuffer::ReadWrite)
bufferCounter = new BufferCounterReadWrite(config.requestBufferSize);
bufferCounter = std::make_unique<BufferCounterReadWrite>(config.requestBufferSize);
else if (config.schedulerBuffer == Configuration::SchedulerBuffer::Shared)
bufferCounter = new BufferCounterShared(config.requestBufferSize);
}
SchedulerFifo::~SchedulerFifo()
{
delete bufferCounter;
bufferCounter = std::make_unique<BufferCounterShared>(config.requestBufferSize);
}
bool SchedulerFifo::hasBufferSpace() const
@@ -63,28 +58,28 @@ bool SchedulerFifo::hasBufferSpace() const
return bufferCounter->hasBufferSpace();
}
void SchedulerFifo::storeRequest(tlm_generic_payload *payload)
void SchedulerFifo::storeRequest(tlm_generic_payload& payload)
{
buffer[DramExtension::getBank(payload).ID()].push_back(payload);
buffer[DramExtension::getBank(payload).ID()].push_back(&payload);
bufferCounter->storeRequest(payload);
}
void SchedulerFifo::removeRequest(tlm_generic_payload *payload)
void SchedulerFifo::removeRequest(tlm_generic_payload& payload)
{
buffer[DramExtension::getBank(payload).ID()].pop_front();
bufferCounter->removeRequest(payload);
}
tlm_generic_payload *SchedulerFifo::getNextRequest(const BankMachine *bankMachine) const
tlm_generic_payload *SchedulerFifo::getNextRequest(const BankMachine& bankMachine) const
{
unsigned bankID = bankMachine->getBank().ID();
unsigned bankID = bankMachine.getBank().ID();
if (!buffer[bankID].empty())
return buffer[bankID].front();
else
return nullptr;
}
bool SchedulerFifo::hasFurtherRowHit(Bank bank, Row row) const
bool SchedulerFifo::hasFurtherRowHit(Bank bank, Row row, tlm_command command) const
{
if (buffer[bank.ID()].size() >= 2)
{
@@ -95,7 +90,7 @@ bool SchedulerFifo::hasFurtherRowHit(Bank bank, Row row) const
return false;
}
bool SchedulerFifo::hasFurtherRequest(Bank bank) const
bool SchedulerFifo::hasFurtherRequest(Bank bank, tlm_command command) const
{
if (buffer[bank.ID()].size() >= 2)
return true;

View File

@@ -37,6 +37,7 @@
#include <vector>
#include <deque>
#include <memory>
#include <tlm>
#include "SchedulerIF.h"
@@ -48,18 +49,17 @@ class SchedulerFifo final : public SchedulerIF
{
public:
SchedulerFifo();
~SchedulerFifo() 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;
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, tlm::tlm_command) const override;
bool hasFurtherRequest(Bank, tlm::tlm_command) const override;
const std::vector<unsigned> &getBufferDepth() const override;
private:
std::vector<std::deque<tlm::tlm_generic_payload *>> buffer;
BufferCounterIF *bufferCounter;
std::unique_ptr<BufferCounterIF> bufferCounter;
};
#endif // SCHEDULERFIFO_H

View File

@@ -46,16 +46,11 @@ SchedulerFrFcfs::SchedulerFrFcfs()
buffer = std::vector<std::list<tlm_generic_payload *>>(config.memSpec->banksPerChannel);
if (config.schedulerBuffer == Configuration::SchedulerBuffer::Bankwise)
bufferCounter = new BufferCounterBankwise(config.requestBufferSize, config.memSpec->banksPerChannel);
bufferCounter = std::make_unique<BufferCounterBankwise>(config.requestBufferSize, config.memSpec->banksPerChannel);
else if (config.schedulerBuffer == Configuration::SchedulerBuffer::ReadWrite)
bufferCounter = new BufferCounterReadWrite(config.requestBufferSize);
bufferCounter = std::make_unique<BufferCounterReadWrite>(config.requestBufferSize);
else if (config.schedulerBuffer == Configuration::SchedulerBuffer::Shared)
bufferCounter = new BufferCounterShared(config.requestBufferSize);
}
SchedulerFrFcfs::~SchedulerFrFcfs()
{
delete bufferCounter;
bufferCounter = std::make_unique<BufferCounterShared>(config.requestBufferSize);
}
bool SchedulerFrFcfs::hasBufferSpace() const
@@ -63,19 +58,19 @@ bool SchedulerFrFcfs::hasBufferSpace() const
return bufferCounter->hasBufferSpace();
}
void SchedulerFrFcfs::storeRequest(tlm_generic_payload *payload)
void SchedulerFrFcfs::storeRequest(tlm_generic_payload& trans)
{
buffer[DramExtension::getBank(payload).ID()].push_back(payload);
bufferCounter->storeRequest(payload);
buffer[DramExtension::getBank(trans).ID()].push_back(&trans);
bufferCounter->storeRequest(trans);
}
void SchedulerFrFcfs::removeRequest(tlm_generic_payload *payload)
void SchedulerFrFcfs::removeRequest(tlm_generic_payload& trans)
{
bufferCounter->removeRequest(payload);
unsigned bankID = DramExtension::getBank(payload).ID();
bufferCounter->removeRequest(trans);
unsigned bankID = DramExtension::getBank(trans).ID();
for (auto it = buffer[bankID].begin(); it != buffer[bankID].end(); it++)
{
if (*it == payload)
if (*it == &trans)
{
buffer[bankID].erase(it);
break;
@@ -83,15 +78,15 @@ void SchedulerFrFcfs::removeRequest(tlm_generic_payload *payload)
}
}
tlm_generic_payload *SchedulerFrFcfs::getNextRequest(const BankMachine *bankMachine) const
tlm_generic_payload *SchedulerFrFcfs::getNextRequest(const BankMachine& bankMachine) const
{
unsigned bankID = bankMachine->getBank().ID();
unsigned bankID = bankMachine.getBank().ID();
if (!buffer[bankID].empty())
{
if (bankMachine->isActivated())
if (bankMachine.isActivated())
{
// Search for row hit
Row openRow = bankMachine->getOpenRow();
Row openRow = bankMachine.getOpenRow();
for (auto it : buffer[bankID])
{
if (DramExtension::getRow(it) == openRow)
@@ -104,7 +99,7 @@ tlm_generic_payload *SchedulerFrFcfs::getNextRequest(const BankMachine *bankMach
return nullptr;
}
bool SchedulerFrFcfs::hasFurtherRowHit(Bank bank, Row row) const
bool SchedulerFrFcfs::hasFurtherRowHit(Bank bank, Row row, tlm_command command) const
{
unsigned rowHitCounter = 0;
for (auto it : buffer[bank.ID()])
@@ -119,7 +114,7 @@ bool SchedulerFrFcfs::hasFurtherRowHit(Bank bank, Row row) const
return false;
}
bool SchedulerFrFcfs::hasFurtherRequest(Bank bank) const
bool SchedulerFrFcfs::hasFurtherRequest(Bank bank, tlm_command command) const
{
return (buffer[bank.ID()].size() >= 2);
}

View File

@@ -37,6 +37,7 @@
#include <vector>
#include <list>
#include <memory>
#include <tlm>
#include "SchedulerIF.h"
@@ -48,18 +49,17 @@ class SchedulerFrFcfs final : public SchedulerIF
{
public:
SchedulerFrFcfs();
~SchedulerFrFcfs() 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;
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, tlm::tlm_command) const override;
bool hasFurtherRequest(Bank, tlm::tlm_command) const override;
const std::vector<unsigned> &getBufferDepth() const override;
private:
std::vector<std::list<tlm::tlm_generic_payload *>> buffer;
BufferCounterIF *bufferCounter;
std::unique_ptr<BufferCounterIF> bufferCounter;
};
#endif // SCHEDULERFRFCFS_H

View File

@@ -46,16 +46,11 @@ SchedulerFrFcfsGrp::SchedulerFrFcfsGrp()
buffer = std::vector<std::list<tlm_generic_payload *>>(config.memSpec->banksPerChannel);
if (config.schedulerBuffer == Configuration::SchedulerBuffer::Bankwise)
bufferCounter = new BufferCounterBankwise(config.requestBufferSize, config.memSpec->banksPerChannel);
bufferCounter = std::make_unique<BufferCounterBankwise>(config.requestBufferSize, config.memSpec->banksPerChannel);
else if (config.schedulerBuffer == Configuration::SchedulerBuffer::ReadWrite)
bufferCounter = new BufferCounterReadWrite(config.requestBufferSize);
bufferCounter = std::make_unique<BufferCounterReadWrite>(config.requestBufferSize);
else if (config.schedulerBuffer == Configuration::SchedulerBuffer::Shared)
bufferCounter = new BufferCounterShared(config.requestBufferSize);
}
SchedulerFrFcfsGrp::~SchedulerFrFcfsGrp()
{
delete bufferCounter;
bufferCounter = std::make_unique<BufferCounterShared>(config.requestBufferSize);
}
bool SchedulerFrFcfsGrp::hasBufferSpace() const
@@ -63,20 +58,20 @@ bool SchedulerFrFcfsGrp::hasBufferSpace() const
return bufferCounter->hasBufferSpace();
}
void SchedulerFrFcfsGrp::storeRequest(tlm_generic_payload *payload)
void SchedulerFrFcfsGrp::storeRequest(tlm_generic_payload& trans)
{
buffer[DramExtension::getBank(payload).ID()].push_back(payload);
bufferCounter->storeRequest(payload);
buffer[DramExtension::getBank(trans).ID()].push_back(&trans);
bufferCounter->storeRequest(trans);
}
void SchedulerFrFcfsGrp::removeRequest(tlm_generic_payload *payload)
void SchedulerFrFcfsGrp::removeRequest(tlm_generic_payload& trans)
{
bufferCounter->removeRequest(payload);
lastCommand = payload->get_command();
unsigned bankID = DramExtension::getBank(payload).ID();
bufferCounter->removeRequest(trans);
lastCommand = trans.get_command();
unsigned bankID = DramExtension::getBank(trans).ID();
for (auto it = buffer[bankID].begin(); it != buffer[bankID].end(); it++)
{
if (*it == payload)
if (*it == &trans)
{
buffer[bankID].erase(it);
break;
@@ -84,103 +79,52 @@ void SchedulerFrFcfsGrp::removeRequest(tlm_generic_payload *payload)
}
}
tlm_generic_payload *SchedulerFrFcfsGrp::getNextRequest(const 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();
unsigned bankID = bankMachine.getBank().ID();
if (!buffer[bankID].empty())
{
if (lastCommand == tlm::TLM_READ_COMMAND)
if (bankMachine.isActivated())
{
// Filter out read requests
std::vector<tlm_generic_payload*> readRequests;
for (auto it: buffer[bankID])
// Filter all row hits
Row openRow = bankMachine.getOpenRow();
std::list<tlm_generic_payload *> rowHits;
for (auto it : buffer[bankID])
{
if (it->is_read())
readRequests.push_back(it);
if (DramExtension::getRow(it) == openRow)
rowHits.push_back(it);
}
if (!readRequests.empty())
if (!rowHits.empty())
{
if (bankMachine->isActivated())
for (auto outerIt = rowHits.begin(); outerIt != rowHits.end(); outerIt++)
{
// Search for row hit
Row openRow = bankMachine->getOpenRow();
for (auto it: readRequests)
if ((*outerIt)->get_command() == lastCommand)
{
if (DramExtension::getRow(it) == openRow)
return it;
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;
}
}
// No row hit found or bank precharged
return readRequests.front();
}
else
{
const std::list<tlm_generic_payload*>& 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<tlm_generic_payload*> 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<tlm_generic_payload*>& 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 rd/wr hit found -> take first row hit
return *rowHits.begin();
}
}
// No row hit found or bank precharged
return buffer[bankID].front();
}
else
return nullptr;
return nullptr;
}
bool SchedulerFrFcfsGrp::hasFurtherRowHit(Bank bank, Row row) const
bool SchedulerFrFcfsGrp::hasFurtherRowHit(Bank bank, Row row, tlm_command command) const
{
unsigned rowHitCounter = 0;
for (auto it : buffer[bank.ID()])
@@ -195,7 +139,7 @@ bool SchedulerFrFcfsGrp::hasFurtherRowHit(Bank bank, Row row) const
return false;
}
bool SchedulerFrFcfsGrp::hasFurtherRequest(Bank bank) const
bool SchedulerFrFcfsGrp::hasFurtherRequest(Bank bank, tlm_command command) const
{
if (buffer[bank.ID()].size() >= 2)
return true;

View File

@@ -37,6 +37,7 @@
#include <vector>
#include <list>
#include <memory>
#include <tlm>
#include "SchedulerIF.h"
@@ -48,19 +49,18 @@ class SchedulerFrFcfsGrp final : public SchedulerIF
{
public:
SchedulerFrFcfsGrp();
~SchedulerFrFcfsGrp() 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;
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, tlm::tlm_command) const override;
bool hasFurtherRequest(Bank, tlm::tlm_command) const override;
const std::vector<unsigned> &getBufferDepth() const override;
private:
std::vector<std::list<tlm::tlm_generic_payload *>> buffer;
tlm::tlm_command lastCommand = tlm::TLM_READ_COMMAND;
BufferCounterIF *bufferCounter;
std::unique_ptr<BufferCounterIF> bufferCounter;
};
#endif // SCHEDULERFRFCFSGRP_H

View File

@@ -0,0 +1,214 @@
/*
* 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 "SchedulerGrpFrFcfs.h"
#include "../../configuration/Configuration.h"
#include "BufferCounterBankwise.h"
#include "BufferCounterReadWrite.h"
#include "BufferCounterShared.h"
using namespace tlm;
SchedulerGrpFrFcfs::SchedulerGrpFrFcfs()
{
Configuration &config = Configuration::getInstance();
readBuffer = std::vector<std::list<tlm_generic_payload *>>(config.memSpec->banksPerChannel);
writeBuffer = std::vector<std::list<tlm_generic_payload *>>(config.memSpec->banksPerChannel);
if (config.schedulerBuffer == Configuration::SchedulerBuffer::Bankwise)
bufferCounter = std::make_unique<BufferCounterBankwise>(config.requestBufferSize, config.memSpec->banksPerChannel);
else if (config.schedulerBuffer == Configuration::SchedulerBuffer::ReadWrite)
bufferCounter = std::make_unique<BufferCounterReadWrite>(config.requestBufferSize);
else if (config.schedulerBuffer == Configuration::SchedulerBuffer::Shared)
bufferCounter = std::make_unique<BufferCounterShared>(config.requestBufferSize);
}
bool SchedulerGrpFrFcfs::hasBufferSpace() const
{
return bufferCounter->hasBufferSpace();
}
void SchedulerGrpFrFcfs::storeRequest(tlm_generic_payload& trans)
{
if (trans.is_read())
readBuffer[DramExtension::getBank(trans).ID()].push_back(&trans);
else
writeBuffer[DramExtension::getBank(trans).ID()].push_back(&trans);
bufferCounter->storeRequest(trans);
}
void SchedulerGrpFrFcfs::removeRequest(tlm_generic_payload& trans)
{
bufferCounter->removeRequest(trans);
lastCommand = trans.get_command();
unsigned bankID = DramExtension::getBank(trans).ID();
if (trans.is_read())
readBuffer[bankID].remove(&trans);
else
writeBuffer[bankID].remove(&trans);
}
tlm_generic_payload *SchedulerGrpFrFcfs::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 (lastCommand == tlm::TLM_READ_COMMAND)
{
if (!readBuffer[bankID].empty())
{
if (bankMachine.isActivated())
{
// Search for read row hit
Row openRow = bankMachine.getOpenRow();
for (auto it : readBuffer[bankID])
{
if (DramExtension::getRow(it) == openRow)
return it;
}
}
// No read row hit found or bank precharged
return readBuffer[bankID].front();
}
else if (!writeBuffer[bankID].empty())
{
if (bankMachine.isActivated())
{
// Search for write row hit
Row openRow = bankMachine.getOpenRow();
for (auto it : writeBuffer[bankID])
{
if (DramExtension::getRow(it) == openRow)
return it;
}
}
// No write row hit found or bank precharged
return writeBuffer[bankID].front();
}
else
return nullptr;
}
else
{
if (!writeBuffer[bankID].empty())
{
if (bankMachine.isActivated())
{
// Search for write row hit
Row openRow = bankMachine.getOpenRow();
for (auto it : writeBuffer[bankID])
{
if (DramExtension::getRow(it) == openRow)
return it;
}
}
// No write row hit found or bank precharged
return writeBuffer[bankID].front();
}
else if (!readBuffer[bankID].empty())
{
if (bankMachine.isActivated())
{
// Search for read row hit
Row openRow = bankMachine.getOpenRow();
for (auto it : readBuffer[bankID])
{
if (DramExtension::getRow(it) == openRow)
return it;
}
}
// No read row hit found or bank precharged
return readBuffer[bankID].front();
}
else
return nullptr;
}
}
bool SchedulerGrpFrFcfs::hasFurtherRowHit(Bank bank, Row row, tlm_command command) const
{
// TODO: do this based on current RD/WR mode
unsigned rowHitCounter = 0;
if (command == tlm::TLM_READ_COMMAND)
{
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 SchedulerGrpFrFcfs::hasFurtherRequest(Bank bank, tlm_command command) const
{
if (command == tlm::TLM_READ_COMMAND)
{
if (readBuffer[bank.ID()].size() >= 2)
return true;
else
return false;
}
else
{
if (writeBuffer[bank.ID()].size() >= 2)
return true;
else
return false;
}
}
const std::vector<unsigned> &SchedulerGrpFrFcfs::getBufferDepth() const
{
return bufferCounter->getBufferDepth();
}

View File

@@ -0,0 +1,67 @@
/*
* 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 SCHEDULERGRPFRFCFS_H
#define SCHEDULERGRPFRFCFS_H
#include <vector>
#include <list>
#include <memory>
#include <tlm>
#include "SchedulerIF.h"
#include "../../common/dramExtensions.h"
#include "../BankMachine.h"
#include "BufferCounterIF.h"
class SchedulerGrpFrFcfs final : public SchedulerIF
{
public:
SchedulerGrpFrFcfs();
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, tlm::tlm_command) const override;
bool hasFurtherRequest(Bank, tlm::tlm_command) const override;
const std::vector<unsigned> &getBufferDepth() const override;
private:
std::vector<std::list<tlm::tlm_generic_payload *>> readBuffer;
std::vector<std::list<tlm::tlm_generic_payload *>> writeBuffer;
tlm::tlm_command lastCommand = tlm::TLM_READ_COMMAND;
std::unique_ptr<BufferCounterIF> bufferCounter;
};
#endif // SCHEDULERGRPFRFCFS_H

View File

@@ -32,7 +32,7 @@
* Author: Lukas Steiner
*/
#include "SchedulerFrFcfsWatermark.h"
#include "SchedulerGrpFrFcfsWm.h"
#include "../../configuration/Configuration.h"
#include "BufferCounterBankwise.h"
#include "BufferCounterReadWrite.h"
@@ -40,74 +40,70 @@
using namespace tlm;
SchedulerFrFcfsWatermark::SchedulerFrFcfsWatermark() : lowWatermark(0), highWatermark(0)
SchedulerGrpFrFcfsWm::SchedulerGrpFrFcfsWm() : lowWatermark(0), highWatermark(0)
{
Configuration &config = Configuration::getInstance();
readBuffer = std::vector<std::list<tlm_generic_payload *>>(config.memSpec->numberOfBanks);
writeBuffer = std::vector<std::list<tlm_generic_payload *>>(config.memSpec->numberOfBanks);
readBuffer = std::vector<std::list<tlm_generic_payload *>>(config.memSpec->banksPerChannel);
writeBuffer = std::vector<std::list<tlm_generic_payload *>>(config.memSpec->banksPerChannel);
if (config.schedulerBuffer == Configuration::SchedulerBuffer::Bankwise)
bufferCounter = new BufferCounterBankwise(config.requestBufferSize, config.memSpec->numberOfBanks);
bufferCounter = std::make_unique<BufferCounterBankwise>(config.requestBufferSize, config.memSpec->banksPerChannel);
else if (config.schedulerBuffer == Configuration::SchedulerBuffer::ReadWrite)
bufferCounter = new BufferCounterReadWrite(config.requestBufferSize);
bufferCounter = std::make_unique<BufferCounterReadWrite>(config.requestBufferSize);
else if (config.schedulerBuffer == Configuration::SchedulerBuffer::Shared)
bufferCounter = new BufferCounterShared(config.requestBufferSize);
bufferCounter = std::make_unique<BufferCounterShared>(config.requestBufferSize);
lowWatermark = config.lowWatermark;
highWatermark = config.highWatermark;
}
SchedulerFrFcfsWatermark::~SchedulerFrFcfsWatermark()
{
delete bufferCounter;
}
bool SchedulerFrFcfsWatermark::hasBufferSpace() const
bool SchedulerGrpFrFcfsWm::hasBufferSpace() const
{
return bufferCounter->hasBufferSpace();
}
void SchedulerFrFcfsWatermark::storeRequest(tlm_generic_payload *payload)
void SchedulerGrpFrFcfsWm::storeRequest(tlm_generic_payload& trans)
{
if (payload->is_read())
readBuffer[DramExtension::getBank(payload).ID()].push_back(payload);
if (trans.is_read())
readBuffer[DramExtension::getBank(trans).ID()].push_back(&trans);
else
writeBuffer[DramExtension::getBank(payload).ID()].push_back(payload);
bufferCounter->storeRequest(payload);
writeBuffer[DramExtension::getBank(trans).ID()].push_back(&trans);
bufferCounter->storeRequest(trans);
evaluateWriteMode();
}
void SchedulerFrFcfsWatermark::removeRequest(tlm_generic_payload *payload)
void SchedulerGrpFrFcfsWm::removeRequest(tlm_generic_payload& trans)
{
bufferCounter->removeRequest(payload);
unsigned bankID = DramExtension::getBank(payload).ID();
bufferCounter->removeRequest(trans);
unsigned bankID = DramExtension::getBank(trans).ID();
if (payload->is_read())
readBuffer[bankID].remove(payload);
if (trans.is_read())
readBuffer[bankID].remove(&trans);
else
writeBuffer[bankID].remove(payload);
writeBuffer[bankID].remove(&trans);
evaluateWriteMode();
}
tlm_generic_payload *SchedulerFrFcfsWatermark::getNextRequest(const BankMachine *bankMachine) const
tlm_generic_payload *SchedulerGrpFrFcfsWm::getNextRequest(const BankMachine& bankMachine) const
{
unsigned bankID = bankMachine->getBank().ID();
unsigned bankID = bankMachine.getBank().ID();
if (!writeMode)
{
if (!readBuffer[bankID].empty())
{
if (bankMachine->isActivated())
if (bankMachine.isActivated())
{
// Search for row hit
Row openRow = bankMachine->getOpenRow();
// Search for read 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
// No read row hit found or bank precharged
return readBuffer[bankID].front();
}
else
@@ -117,10 +113,10 @@ tlm_generic_payload *SchedulerFrFcfsWatermark::getNextRequest(const BankMachine
{
if (!writeBuffer[bankID].empty())
{
if (bankMachine->isActivated())
if (bankMachine.isActivated())
{
// Search for row hit
Row openRow = bankMachine->getOpenRow();
// Search for write row hit
Row openRow = bankMachine.getOpenRow();
for (auto it : writeBuffer[bankID])
{
if (DramExtension::getRow(it) == openRow)
@@ -135,7 +131,7 @@ tlm_generic_payload *SchedulerFrFcfsWatermark::getNextRequest(const BankMachine
}
}
bool SchedulerFrFcfsWatermark::hasFurtherRowHit(Bank bank, Row row) const
bool SchedulerGrpFrFcfsWm::hasFurtherRowHit(Bank bank, Row row, tlm::tlm_command command) const
{
unsigned rowHitCounter = 0;
if (!writeMode)
@@ -166,7 +162,7 @@ bool SchedulerFrFcfsWatermark::hasFurtherRowHit(Bank bank, Row row) const
}
}
bool SchedulerFrFcfsWatermark::hasFurtherRequest(Bank bank) const
bool SchedulerGrpFrFcfsWm::hasFurtherRequest(Bank bank, tlm::tlm_command command) const
{
if (!writeMode)
return (readBuffer[bank.ID()].size() >= 2);
@@ -174,12 +170,12 @@ bool SchedulerFrFcfsWatermark::hasFurtherRequest(Bank bank) const
return (writeBuffer[bank.ID()].size() >= 2);
}
const std::vector<unsigned> &SchedulerFrFcfsWatermark::getBufferDepth() const
const std::vector<unsigned> &SchedulerGrpFrFcfsWm::getBufferDepth() const
{
return bufferCounter->getBufferDepth();
}
void SchedulerFrFcfsWatermark::evaluateWriteMode()
void SchedulerGrpFrFcfsWm::evaluateWriteMode()
{
if (writeMode)
{

View File

@@ -32,11 +32,12 @@
* Author: Lukas Steiner
*/
#ifndef SCHEDULERFRFCFSWATERMARK_H
#define SCHEDULERFRFCFSWATERMARK_H
#ifndef SCHEDULERGRPFRFCFSWM_H
#define SCHEDULERGRPFRFCFSWM_H
#include <vector>
#include <list>
#include <memory>
#include <tlm>
#include "SchedulerIF.h"
@@ -44,17 +45,16 @@
#include "../BankMachine.h"
#include "BufferCounterIF.h"
class SchedulerFrFcfsWatermark final : public SchedulerIF
class SchedulerGrpFrFcfsWm final : public SchedulerIF
{
public:
SchedulerFrFcfsWatermark();
~SchedulerFrFcfsWatermark() override;
SchedulerGrpFrFcfsWm();
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;
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, tlm::tlm_command) const override;
bool hasFurtherRequest(Bank, tlm::tlm_command) const override;
const std::vector<unsigned> &getBufferDepth() const override;
private:
@@ -62,10 +62,10 @@ private:
std::vector<std::list<tlm::tlm_generic_payload *>> readBuffer;
std::vector<std::list<tlm::tlm_generic_payload *>> writeBuffer;
BufferCounterIF *bufferCounter;
std::unique_ptr<BufferCounterIF> bufferCounter;
unsigned lowWatermark;
unsigned highWatermark;
bool writeMode = false;
};
#endif // SCHEDULERFRFCFSWATERMARK_H
#endif // SCHEDULERGRPFRFCFSWM_H

View File

@@ -47,11 +47,11 @@ class SchedulerIF
public:
virtual ~SchedulerIF() = default;
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(const BankMachine *) const = 0;
virtual bool hasFurtherRowHit(Bank, Row) const = 0;
virtual bool hasFurtherRequest(Bank) const = 0;
virtual void storeRequest(tlm::tlm_generic_payload&) = 0;
virtual void removeRequest(tlm::tlm_generic_payload&) = 0;
virtual tlm::tlm_generic_payload *getNextRequest(const BankMachine&) const = 0;
virtual bool hasFurtherRowHit(Bank, Row, tlm::tlm_command) const = 0;
virtual bool hasFurtherRequest(Bank, tlm::tlm_command) const = 0;
virtual const std::vector<unsigned> &getBufferDepth() const = 0;
};