integrated scheduler into core
This commit is contained in:
59
dram/src/core/BankStates.cpp
Normal file
59
dram/src/core/BankStates.cpp
Normal 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);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
38
dram/src/core/BankStates.h
Normal file
38
dram/src/core/BankStates.h
Normal 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_ */
|
||||
@@ -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)
|
||||
|
||||
@@ -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 */
|
||||
|
||||
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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));
|
||||
|
||||
@@ -17,7 +17,6 @@ PowerDownManager::PowerDownManager()
|
||||
|
||||
PowerDownManager::~PowerDownManager()
|
||||
{
|
||||
// TODO Auto-generated destructor stub
|
||||
}
|
||||
|
||||
} /* namespace controller */
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -73,7 +73,7 @@ public:
|
||||
|
||||
tlm::tlm_generic_payload& getTransaction() const
|
||||
{
|
||||
assert(transaction);
|
||||
sc_assert(transaction);
|
||||
return *transaction;
|
||||
}
|
||||
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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 */
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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;
|
||||
|
||||
37
dram/src/scheduler/Fifo.cpp
Normal file
37
dram/src/scheduler/Fifo.cpp
Normal 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
37
dram/src/scheduler/Fifo.h
Normal 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_ */
|
||||
26
dram/src/scheduler/Fr_Fcfs.cpp
Normal file
26
dram/src/scheduler/Fr_Fcfs.cpp
Normal 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);
|
||||
//}
|
||||
//
|
||||
//}
|
||||
26
dram/src/scheduler/Fr_Fcfs.h
Normal file
26
dram/src/scheduler/Fr_Fcfs.h
Normal 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
|
||||
27
dram/src/scheduler/Scheduler.h
Normal file
27
dram/src/scheduler/Scheduler.h
Normal 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
|
||||
@@ -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);
|
||||
|
||||
Reference in New Issue
Block a user