integrated scheduler into core

This commit is contained in:
robert
2014-03-19 20:48:06 +01:00
parent 23076bcf7d
commit bc9e35bd61
25 changed files with 434 additions and 76 deletions

View File

@@ -0,0 +1,59 @@
/*
* BankStates.cpp
*
* Created on: Feb 24, 2014
* Author: robert
*/
#include "BankStates.h"
using namespace std;
namespace core
{
BankStates::BankStates(unsigned int numberOfBanks) :
rowsInRowBuffers(numberOfBanks)
{
for (unsigned int i = 0; i < numberOfBanks; ++i)
{
banks.push_back(Bank(i));
}
closeAllRowBuffers();
}
BankStates::~BankStates()
{
}
bool BankStates::rowBufferIsOpen(const Bank &bank) const
{
return rowsInRowBuffers.at(bank.ID()) != Row::NO_ROW;
}
Row BankStates::getRowInRowBuffer(const Bank &bank) const
{
return rowsInRowBuffers.at(bank.ID());
}
void BankStates::openRowInRowBuffer(const Bank &bank, const Row &row)
{
rowsInRowBuffers.at(bank.ID()) = row;
}
void BankStates::closeRowBuffer(const Bank &bank)
{
rowsInRowBuffers.at(bank.ID()) = Row::NO_ROW;
}
void BankStates::closeAllRowBuffers()
{
for(vector<Bank>::iterator it = banks.begin(); it != banks.end(); ++it)
{
closeRowBuffer(*it);
}
}
}

View File

@@ -0,0 +1,38 @@
/*
* BankStates.h
*
* Created on: Feb 24, 2014
* Author: robert
*/
#ifndef BANKSTATES_H_
#define BANKSTATES_H_
#include <vector>
#include "common/dramExtension.h"
namespace core
{
class BankStates {
public:
BankStates(unsigned int numberOfBanks);
virtual ~BankStates();
unsigned int getNumberOfBanks() const {return rowsInRowBuffers.size();}
const std::vector<Bank>& getBanks() const {return banks;}
bool rowBufferIsOpen(const Bank &bank) const;
Row getRowInRowBuffer(const Bank &bank) const;
void openRowInRowBuffer(const Bank &bank, const Row &row);
void closeRowBuffer(const Bank &bank);
void closeAllRowBuffers();
private:
std::vector<Bank> banks;
std::vector<Row> rowsInRowBuffers;
};
}
#endif /* BANKSTATES_H_ */

View File

@@ -19,8 +19,20 @@ void CommandBus::schedule(ScheduledCommand& command)
changeControllerState(command);
state.pendingBusCommands.insert(command.getStart());
state.lastCommandsOnBus[command.getCommand()][command.getBank()] = command;
state.lastCommandsOnBus[command.getCommand()][command.getBank()].invalidateTransaction();
//TODO do in refresh manager
if(command.getCommand() == Refresh)
{
for(unsigned int i = 0; i < config.numberOfBanks; ++i)
{
state.lastCommandsOnBus[command.getCommand()][Bank(i)] = command;
}
}
else
{
state.lastCommandsOnBus[command.getCommand()][command.getBank()] = command;
//state.lastCommandsOnBus[command.getCommand()][command.getBank()].invalidateTransaction();
}
if(command.getCommand() == Activate)
{
@@ -28,11 +40,12 @@ void CommandBus::schedule(ScheduledCommand& command)
}
}
void CommandBus::scheduleOnBus(ScheduledCommand& command)
{
//TODO write nicer
//TODO write nicer -- make own bus checker
sc_time newStart = command.getStart();
assert(isClkAligned(newStart, config.Timings.clk));
sc_assert(isClkAligned(newStart, config.Timings.clk));
std::set<sc_time>::iterator it = state.pendingBusCommands.begin();
while (it != state.pendingBusCommands.end() && *it <= newStart)

View File

@@ -49,7 +49,7 @@ void DramController::scheduleRefresh(sc_time time)
refreshManager.scheduleRefresh(time);
}
void DramController::schedule(sc_time start, tlm::tlm_generic_payload& payload)
bool DramController::schedule(sc_time start, tlm::tlm_generic_payload& payload)
{
bus.cleanUpBus(start);
@@ -62,30 +62,39 @@ void DramController::schedule(sc_time start, tlm::tlm_generic_payload& payload)
payload);
CommandSchedule schedule = commandSequenceScheduler.schedule(sequence, start, payload);
//commandbuschecker (schedule)
while (refreshManager.hasCollision(schedule))
if (refreshManager.hasCollision(schedule))
{
resetState();
refreshManager.scheduleRefresh(start);
saveState();
sequence = commandSequenceGenerator.generateCommandSequence(payload);
schedule = commandSequenceScheduler.schedule(sequence, start, payload);
assert(schedule.getExecutionTime() < config.Timings.refreshTimings[0].tREFI); //TODO make nice
return false;
}
else
{
bus.send(schedule);
return true;
}
bus.send(schedule);
}
/*const ICommandChecker& DramController::getChecker(Command command) const
bool core::DramController::isBusy(sc_time currentTime, Bank bank)
{
std::map<Command, ICommandChecker*>::const_iterator result = commandChecker.find(command);
assert(result != commandChecker.end());
return *(result->second);
}*/
ScheduledCommand lastScheduledCommand = state.getLastCommand(bank);
if(lastScheduledCommand.isNoCommand())
return false;
else if(lastScheduledCommand.getCommand() == Write || lastScheduledCommand.getCommand() == Read)
{
return (currentTime < lastScheduledCommand.getStart());
}
else if(lastScheduledCommand.getCommand() == Refresh)
{
return (currentTime < lastScheduledCommand.getEnd());
}
else
{
SC_ASSERT_(false, "last command in command sequence was activate or precharge");
return false;
}
}
} /* namespace controller */

View File

@@ -27,10 +27,14 @@ public:
DramController(IWrapperConnector& wrapper);
virtual ~DramController() ;
void schedule(sc_time currentTime, tlm::tlm_generic_payload& payload);
bool schedule(sc_time currentTime, tlm::tlm_generic_payload& payload);
bool isBusy(sc_time currentTime, Bank bank);
void scheduleRefresh(sc_time time);
const ICommandChecker& getChecker(Command command) const;
Configuration config;
const BankStates& getBankStates(){return state.bankStates;}
void saveState();
void resetState();

View File

@@ -9,7 +9,7 @@
#define CONTROLLER_STATE_H_
#include <systemc.h>
#include "common/BankStates.h"
#include "BankStates.h"
#include "utils/RingBuffer.h"
#include "scheduling/ScheduledCommand.h"
#include <map>
@@ -29,6 +29,7 @@ public:
BankStates bankStates;
//used by the various checkers
RingBuffer<sc_time> nActivateWindow;
std::vector<sc_time> nACT;
std::map<Command, std::map<Bank, ScheduledCommand> > lastCommandsOnBus;

View File

@@ -29,7 +29,8 @@ struct TimingConfiguration
for (unsigned int i = 0; i < numberOfBanks; ++i)
{
sc_time tRFC = 18*clk;
sc_time tRFC = 21*clk;
//sc_time tREFI = 100*clk;
sc_time tREFI = sc_time(15.6, SC_US); //TODO align
//tREFI = sc_time(301268, SC_NS);
refreshTimings.push_back(RefreshTiming(tRFC, tREFI));

View File

@@ -17,7 +17,6 @@ PowerDownManager::PowerDownManager()
PowerDownManager::~PowerDownManager()
{
// TODO Auto-generated destructor stub
}
} /* namespace controller */

View File

@@ -18,8 +18,8 @@ RefreshManager::RefreshManager(CommandBus& bus, const RefreshTiming& refreshTimi
setupTransaction(refreshTransaction, Bank(0));
nextPlannedRefresh = new ScheduledCommand(refreshTransaction, Refresh, SC_ZERO_TIME,
refreshTiming.tRFC);
assert(refreshTiming.tRFC > SC_ZERO_TIME);
assert(nextPlannedRefresh->getExecutionTime()>SC_ZERO_TIME);
sc_assert(refreshTiming.tRFC > SC_ZERO_TIME);
sc_assert(nextPlannedRefresh->getExecutionTime()>SC_ZERO_TIME);
planNextRefresh(*nextPlannedRefresh);
}

View File

@@ -15,14 +15,16 @@ CommandSchedule CommandSequenceScheduler::schedule(CommandSequence commands, sc_
{
CommandSchedule schedule(transaction);
sc_time endOfPrevious = start;
for (Command cmd : commands)
{
ICommandChecker& checker = *commandChecker.at(cmd);
sc_time executionTime = checker.getExecutionTime(transaction, cmd);
ScheduledCommand& scheduledCommand = schedule.add(cmd, start, executionTime);
ScheduledCommand& scheduledCommand = schedule.add(cmd, endOfPrevious, executionTime);
checker.delayToSatisfyConstraints(scheduledCommand);
bus.schedule(scheduledCommand);
endOfPrevious = scheduledCommand.getEnd();
}
return schedule;

View File

@@ -73,7 +73,7 @@ public:
tlm::tlm_generic_payload& getTransaction() const
{
assert(transaction);
sc_assert(transaction);
return *transaction;
}

View File

@@ -19,11 +19,11 @@ void ActivateChecker::delayToSatisfyConstraints(ScheduledCommand& command) const
if (command.getCommand() != Activate)
return;
satisfy_activateToActivate_sameBank(command);
satisfy_activateToActivate_differentBank(command);
satisfy_nActivateWindow(command);
satisfy_prechargeToActivate(command);
//satisfy_activateToActivate_differentBank(command);
//satisfy_nActivateWindow(command);
//satisfy_prechargeToActivate(command);
satisfy_refreshToActivate(command);
//satisfy_refreshToActivate(command);
}
sc_time ActivateChecker::getExecutionTime(const tlm::tlm_generic_payload& transaction,

View File

@@ -22,8 +22,8 @@ public:
ActivateChecker(const Configuration& config, ControllerState& state) : config(config), state(state){}
virtual ~ActivateChecker(){}
virtual void delayToSatisfyConstraints(ScheduledCommand& command) const;
virtual sc_time getExecutionTime(const tlm::tlm_generic_payload& payload, Command command) const;
virtual void delayToSatisfyConstraints(ScheduledCommand& command) const override;
virtual sc_time getExecutionTime(const tlm::tlm_generic_payload& payload, Command command) const override;
private:
const Configuration& config;

View File

@@ -20,8 +20,8 @@ public:
PrechargeChecker(const Configuration& config, ControllerState& state) : config(config), state(state) {}
virtual ~PrechargeChecker() {}
virtual void delayToSatisfyConstraints(ScheduledCommand& command) const;
virtual sc_time getExecutionTime(const tlm::tlm_generic_payload& payload, Command command) const;
virtual void delayToSatisfyConstraints(ScheduledCommand& command) const override;
virtual sc_time getExecutionTime(const tlm::tlm_generic_payload& payload, Command command) const override;
private:
const Configuration& config;
ControllerState& state;//TODO make const

View File

@@ -25,7 +25,8 @@ sc_time ReadChecker::getExecutionTime(const tlm::tlm_generic_payload& payload,
{
assert(command == Read || command == ReadA);
//return config.Timings.tRL + config.Timings.clk*getBurstLengthInBytes(transaction, config.buswidth);
return config.Timings.tRL + config.Timings.clk*payload.get_streaming_width();
sc_time result = config.Timings.tRL + config.Timings.clk*payload.get_streaming_width();
return result;
}
} /* namespace controller */

View File

@@ -20,8 +20,8 @@ public:
ReadChecker(Configuration& config, ControllerState& state) : config(config), state(state) {}
virtual ~ReadChecker() {}
virtual void delayToSatisfyConstraints(ScheduledCommand& command) const;
virtual sc_time getExecutionTime(const tlm::tlm_generic_payload& payload, Command command) const;
virtual void delayToSatisfyConstraints(ScheduledCommand& command) const override;
virtual sc_time getExecutionTime(const tlm::tlm_generic_payload& payload, Command command) const override;
private:
const Configuration& config;
ControllerState& state;

View File

@@ -11,6 +11,12 @@ namespace core {
void WriteChecker::delayToSatisfyConstraints(ScheduledCommand& command) const
{
ScheduledCommand lastCommand = state.getLastCommand(command.getBank());
if(lastCommand.isValidCommand() && lastCommand.getEnd() > command.getStart())
{
command.delayStart(lastCommand.getEnd()-command.getStart());
}
}
sc_time WriteChecker::getExecutionTime(const tlm::tlm_generic_payload& payload,

View File

@@ -20,8 +20,8 @@ public:
WriteChecker(const Configuration& config, ControllerState& state) : config(config), state(state) {}
virtual ~WriteChecker() {}
virtual void delayToSatisfyConstraints(ScheduledCommand& command) const;
virtual sc_time getExecutionTime(const tlm::tlm_generic_payload& payload, Command command) const;
virtual void delayToSatisfyConstraints(ScheduledCommand& command) const override;
virtual sc_time getExecutionTime(const tlm::tlm_generic_payload& payload, Command command) const override;
private:
const Configuration& config;
ControllerState& state;

View File

@@ -0,0 +1,37 @@
/*
* Fifo.cpp
*
* Created on: Mar 19, 2014
* Author: robert
*/
#include "Fifo.h"
namespace scheduler {
bool scheduler::Fifo::hasTransactionForBank(Bank bank)
{
return (!buffer.at(bank.ID()).empty());
}
void scheduler::Fifo::schedule(gp* payload)
{
buffer.at(DramExtension::getExtension(payload).getBank().ID()).push_back(payload);
}
gp* scheduler::Fifo::getTransactionForBank(Bank bank)
{
sc_assert(hasTransactionForBank(bank));
gp* result = buffer.at(bank.ID()).front();
return result;
}
void scheduler::Fifo::popTransactionForBank(Bank bank)
{
sc_assert(hasTransactionForBank(bank));
buffer.at(bank.ID()).pop_front();
}
} /* namespace scheduler */

37
dram/src/scheduler/Fifo.h Normal file
View File

@@ -0,0 +1,37 @@
/*
* Fifo.h
*
* Created on: Mar 19, 2014
* Author: robert
*/
#ifndef FIFO_H_
#define FIFO_H_
#include "Scheduler.h"
#include "../core/BankStates.h"
#include <deque>
#include <vector>
namespace scheduler {
class Fifo : public Scheduler
{
public:
Fifo(const core::BankStates& bankstates) : buffer(bankstates.getNumberOfBanks())
{}
virtual ~Fifo()
{}
virtual bool hasTransactionForBank(Bank bank) override;
virtual void schedule(gp* payload) override;
virtual gp* getTransactionForBank(Bank bank) override;
virtual void popTransactionForBank(Bank bank) override;
private:
std::vector<std::deque<gp*>> buffer;
};
} /* namespace scheduler */
#endif /* FIFO_H_ */

View File

@@ -0,0 +1,26 @@
//#include "Fr_Fcfs.h"
//#include "assert.h"
//#include "common/dramExtension.h"
//
//using namespace tlm;
//using namespace std;
//
//namespace scheduler {
//
//bool FR_FCFS::hasScheduledTransactions(Bank bank)
//{
// return rowHitBuffer.hasBufferedTransaction(bank);
//}
//
//gp* FR_FCFS::getNextScheduledTransaction(Bank bank)
//{
// gp* result = rowHitBuffer.getRowHitOrOldest(bank);
// return result;
//}
//
//void FR_FCFS::schedule(gp* payload)
//{
// rowHitBuffer.bufferTransaction(payload);
//}
//
//}

View File

@@ -0,0 +1,26 @@
//#ifndef FR_FCFS_H
//#define FR_FCFS_H
//#include <list>
//#include <vector>
//#include "Scheduler.h"
//#include "RowHitBuffer.h"
//#include "../core/BankStates.h"
//
//namespace scheduler{
//
//class FR_FCFS : public Scheduler
//{
//public:
// FR_FCFS(const core::BankStates& bankstates): rowHitBuffer(bankstates){}
// virtual ~FR_FCFS(){}
// virtual bool hasScheduledTransactions(Bank bank) override;
// virtual void schedule(gp* payload) override;
// virtual gp* getNextScheduledTransaction(Bank bank) override;
//
//private:
// RowHitBuffer rowHitBuffer;
//};
//
//}
//
//#endif // FR_FCFS_H

View File

@@ -0,0 +1,27 @@
#ifndef SCHEDULER_H
#define SCHEDULER_H
#include <tlm.h>
#include "common/dramExtension.h"
namespace scheduler {
typedef tlm::tlm_generic_payload gp;
class Scheduler
{
public:
virtual ~Scheduler(){};
virtual void schedule(gp* payload) = 0;
//TODO Rename to payload
virtual bool hasTransactionForBank(Bank bank) = 0;
virtual gp* getTransactionForBank(Bank bank) = 0;
virtual void popTransactionForBank(Bank bank) = 0;
};
}
#endif // SCHEDULER_H

View File

@@ -14,15 +14,19 @@
#include <tlm_utils/simple_initiator_socket.h>
#include <tlm_utils/peq_with_cb_and_phase.h>
#include <iostream>
#include <map>
#include "common/protocol.h"
#include "common/tlmDBPhaseRecorder.h"
#include "dram/core/IWrapperConnector.h"
#include "dram/core/Controller.h"
#include "../core/IWrapperConnector.h"
#include "../core/Controller.h"
#include "../scheduler/Scheduler.h"
#include "../scheduler/Fifo.h"
using namespace std;
using namespace tlm;
using namespace core;
using namespace scheduler;
template<unsigned int BUSWIDTH = 128>
struct ControllerWrapper: public sc_module, public IWrapperConnector
@@ -38,21 +42,27 @@ public:
&ControllerWrapper::controllerPEQCallback), tpr(tpr)
{
controller = new DramController(*this);
scheduler = new Fifo(controller->getBankStates());
inputBufferDelay = controller->config.Timings.clk;
iSocket.register_nb_transport_bw(this, &ControllerWrapper::nb_transport_bw);
tSocket.register_nb_transport_fw(this, &ControllerWrapper::nb_transport_fw);
for(Bank bank:controller->getBankStates().getBanks())
bankIsFreeForRequest[bank] = true;
}
~ControllerWrapper()
{
delete controller;
delete scheduler;
}
virtual void send(const ScheduledCommand& command)
virtual void send(const ScheduledCommand& command) override
{
assert(command.getStart() >= sc_time_stamp()||command.getStart()<sc_time(100000, SC_NS));
assert(command.getStart() >= sc_time_stamp());
sc_time delay = command.getStart() - sc_time_stamp();
tlm::tlm_phase phase;
switch (command.getCommand())
{
case Read:
@@ -78,7 +88,7 @@ public:
dramPEQ.notify(command.getTransaction(), phase, delay);
}
virtual void send(Trigger trigger, sc_time time)
virtual void send(Trigger trigger, sc_time time) override
{
assert(time >= sc_time_stamp());
sc_time delay = time - sc_time_stamp();
@@ -87,6 +97,9 @@ public:
private:
DramController* controller;
Scheduler* scheduler;
map<Bank, bool> bankIsFreeForRequest;
tlm_utils::peq_with_cb_and_phase<ControllerWrapper> frontendPEQ;
tlm_utils::peq_with_cb_and_phase<ControllerWrapper> dramPEQ;
tlm_utils::peq_with_cb_and_phase<ControllerWrapper> controllerPEQ;
@@ -95,6 +108,45 @@ private:
tlm::tlm_generic_payload triggerDummy;
tlmDBPhaseRecorder& tpr;
void payloadEntersSystem(tlm_generic_payload& payload)
{
//std::cout << "----------------------------------------------------------------------- " << std::endl;
//std::cout << "Transaction enters system at " << sc_time_stamp() << std::endl;
Bank bank = DramExtension::getExtension(payload).getBank();
scheduler->schedule(&payload);
scheduleNextPayload(bank);
}
void scheduleNextPayload(Bank bank)
{
//std::cout << "----------------------------------------------------------------------- " << std::endl;
//std::cout << "In trigger for bank " << bank.ID() << std::endl;
if(controller->isBusy(sc_time_stamp(), bank))
return;
else if(scheduler->hasTransactionForBank(bank))
{
tlm_generic_payload* nextTransaction = scheduler->getTransactionForBank(bank);
if(controller->schedule(sc_time_stamp(), *nextTransaction))
{
//std::cout << "Next payload was scheduled by core " << std::endl;
scheduler->popTransactionForBank(bank);
}
else
{
//std::cout << "Next payload was not scheduled because of refresh " << std::endl;
}
}
}
void payloadLeavesSystem(tlm_generic_payload& payload)
{
}
// Initiated by dram
tlm_sync_enum nb_transport_bw(tlm_generic_payload& payload, tlm_phase& phase, sc_time& bwDelay)
{
@@ -105,57 +157,76 @@ private:
// Initiated by dram frontend
tlm_sync_enum nb_transport_fw(tlm_generic_payload& payload, tlm_phase& phase, sc_time& fwDelay)
{
if (phase == BEGIN_REQ)
payload.acquire();
else if (phase == END_RESP)
payload.release();
DramExtension::getExtension(payload);
tpr.recordPhase(payload,phase,sc_time_stamp());
if (phase == BEGIN_REQ)
{
payload.acquire();
frontendPEQ.notify(payload, phase, inputBufferDelay);
}
else if (phase == END_RESP)
{
payloadLeavesSystem(payload);
payload.release();
}
frontendPEQ.notify(payload, phase, fwDelay);
return TLM_ACCEPTED;
}
void frontendPEQCallback(tlm_generic_payload& payload, const tlm_phase& phase)
{
tpr.recordPhase(payload,phase,sc_time_stamp());
if (phase == BEGIN_REQ)
{
controller->schedule(sc_time_stamp() + inputBufferDelay, payload);
frontendPEQ.notify(payload,END_REQ,inputBufferDelay);
}
else if(phase == END_REQ)
{
payloadEntersSystem(payload);
payload.set_response_status(tlm::TLM_OK_RESPONSE);
sendToFrontend(payload,phase,SC_ZERO_TIME);
tpr.recordPhase(payload, END_REQ, sc_time_stamp());
sendToFrontend(payload, END_REQ, SC_ZERO_TIME);
}
else if (phase == BEGIN_RESP)
{
sendToFrontend(payload, phase, SC_ZERO_TIME);
}
else if (phase == END_RESP)
{
}
else
{
SC_REPORT_FATAL(0,
"Payload event queue in controller wrapper was triggered with unknown phase");
"Frontend PEQ event queue in controller wrapper was triggered with unknown phase");
}
}
void dramPEQCallback(tlm_generic_payload& payload, const tlm_phase& phase)
{
tpr.recordPhase(payload,phase,sc_time_stamp());
if (phase == BEGIN_RD || phase == BEGIN_WR || phase == BEGIN_REFA || phase == BEGIN_ACT
DramExtension *result = NULL;
payload.get_extension(result);
if(result==NULL)
{
cout << "ERROR AT TIME " << sc_time_stamp() << std::endl;
cout << "Payload " << payload.get_address() << " " << phase;
assert(result != NULL);
}
if (phase == BEGIN_RD || phase == BEGIN_WR)
{
//std::cout << "BEGIN_RD at " <<sc_time_stamp() << " on Bank " << DramExtension::getExtension(payload).getBank().ID() << std::endl;
scheduleNextPayload(DramExtension::getExtension(payload).getBank());
sendToDram(payload, phase, SC_ZERO_TIME);
}
else if(phase == BEGIN_REFA || phase == BEGIN_ACT
|| phase == BEGIN_PRE)
{
sendToDram(payload, phase, SC_ZERO_TIME);//TODO delay in send mehtod instead of way through PEQ
sendToDram(payload, phase, SC_ZERO_TIME);
}
else if(phase == END_REFA)
{
//std::cout << " --- END_REFA --- @:" <<sc_time_stamp() << std::endl;
for(Bank bank:controller->getBankStates().getBanks())
scheduleNextPayload(bank);
}
else if (phase == END_RD || phase == END_WR)
{
frontendPEQ.notify(payload, BEGIN_RESP, SC_ZERO_TIME);
tpr.recordPhase(payload, BEGIN_RESP, sc_time_stamp());
sendToFrontend(payload, BEGIN_RESP, SC_ZERO_TIME);
}
else if (phase == END_PRE || phase == END_ACT || phase == END_REFA)
else if (phase == END_PRE || phase == END_ACT)
{
}
@@ -181,6 +252,7 @@ private:
void sendToDram(tlm_generic_payload& payload, const tlm_phase& phase, const sc_time& delay)
{
DramExtension::getExtension(payload);
tlm_phase TPhase = phase;
sc_time TDelay = delay;
iSocket->nb_transport_fw(payload, TPhase, TDelay);