..
This commit is contained in:
@@ -3,7 +3,6 @@
|
|||||||
<name>dram</name>
|
<name>dram</name>
|
||||||
<comment></comment>
|
<comment></comment>
|
||||||
<projects>
|
<projects>
|
||||||
<project>common</project>
|
|
||||||
</projects>
|
</projects>
|
||||||
<buildSpec>
|
<buildSpec>
|
||||||
<buildCommand>
|
<buildCommand>
|
||||||
|
|||||||
@@ -10,150 +10,112 @@
|
|||||||
|
|
||||||
namespace core {
|
namespace core {
|
||||||
|
|
||||||
void CommandBus::schedule(const CommandSchedule& schedule)
|
void CommandBus::schedule(ScheduledCommand& command)
|
||||||
{
|
{
|
||||||
const std::vector<ScheduledCommand>& commands = schedule.getScheduledCommands();
|
|
||||||
|
|
||||||
for (std::vector<ScheduledCommand>::const_iterator it = commands.begin(); it != commands.end();
|
scheduleOnBus(command);
|
||||||
++it)
|
|
||||||
{
|
|
||||||
scheduleCommand(*it);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void CommandBus::scheduleCommand(const ScheduledCommand& command)
|
|
||||||
{
|
|
||||||
assert(!pendingBusCommands.count(command.getStart()));
|
|
||||||
|
|
||||||
|
//TODO state change in state!!
|
||||||
changeControllerState(command);
|
changeControllerState(command);
|
||||||
pendingBusCommands.insert(command.getStart());
|
state.pendingBusCommands.insert(command.getStart());
|
||||||
|
|
||||||
notifyAllCheckersAboutScheduledCommand(command);
|
state.lastCommandsOnBus[command.getCommand()][command.getBank()] = command;
|
||||||
|
state.lastCommandsOnBus[command.getCommand()][command.getBank()].invalidateTransaction();
|
||||||
|
|
||||||
wrapper.sendCommand(command.getStart(), command.getTransaction(), command.getCommand());
|
if(command.getCommand() == Activate)
|
||||||
lastCommandsOnBus[command.getCommand()][command.getBank()] = command;
|
|
||||||
lastCommandsOnBus[command.getCommand()][command.getBank()].invalidateTransaction();
|
|
||||||
}
|
|
||||||
|
|
||||||
void CommandBus::notifyAllCheckersAboutScheduledCommand(const ScheduledCommand& command)
|
|
||||||
{
|
|
||||||
for (std::vector<ICommandChecker*>::iterator it = checker.begin(); it != checker.end(); ++it)
|
|
||||||
{
|
{
|
||||||
(*it)->notifyAboutScheduledCommand(command);
|
state.nActivateWindow.put(command.getStart());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void CommandBus::scheduleTrigger(const Trigger command, sc_time time)
|
void CommandBus::scheduleOnBus(ScheduledCommand& command)
|
||||||
{
|
{
|
||||||
wrapper.sendTrigger(time, command);
|
//TODO write nicer
|
||||||
}
|
sc_time newStart = command.getStart();
|
||||||
|
assert(isClkAligned(newStart, config.Timings.clk));
|
||||||
|
std::set<sc_time>::iterator it = state.pendingBusCommands.begin();
|
||||||
|
|
||||||
ScheduledCommand CommandBus::getLastCommand(Command command, Bank bank)
|
while (it != state.pendingBusCommands.end() && *it <= newStart)
|
||||||
{
|
|
||||||
return lastCommandsOnBus[command][bank];
|
|
||||||
}
|
|
||||||
|
|
||||||
ScheduledCommand CommandBus::getLastCommand(Command command)
|
|
||||||
{
|
|
||||||
ScheduledCommand max;
|
|
||||||
for (unsigned int i = 0; i < config.numberOfBanks; ++i)
|
|
||||||
{
|
{
|
||||||
const ScheduledCommand& current = getLastCommand(command, Bank(i));
|
if (*it == newStart)
|
||||||
if (current.getStart() > max.getStart())
|
newStart += config.Timings.clk;
|
||||||
max = current;
|
++it;
|
||||||
}
|
}
|
||||||
return max;
|
command.setStart(newStart);
|
||||||
}
|
}
|
||||||
|
|
||||||
ScheduledCommand CommandBus::getLastCommand(Bank bank)
|
void CommandBus::send(const Trigger trigger, sc_time time) const
|
||||||
{
|
{
|
||||||
ScheduledCommand lastCommand;
|
wrapperConnector.send(trigger, time);
|
||||||
for(std::map<Command, std::map<Bank, ScheduledCommand> >::iterator it = lastCommandsOnBus.begin(); it != lastCommandsOnBus.end(); ++it)
|
|
||||||
{
|
|
||||||
ScheduledCommand& current = lastCommandsOnBus[it->first][bank];
|
|
||||||
if(current.getStart() > lastCommand.getStart())
|
|
||||||
lastCommand = current;
|
|
||||||
}
|
|
||||||
return lastCommand;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CommandBus::notYetScheduled(Command command) const
|
void CommandBus::send(const ScheduledCommand& command) const
|
||||||
{
|
{
|
||||||
return (lastCommandsOnBus.count(command) == 0);
|
wrapperConnector.send(command);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CommandBus::notYetScheduled(Command command, Bank bank) const
|
void CommandBus::send(const CommandSchedule& schedule) const
|
||||||
{
|
{
|
||||||
return (notYetScheduled(command) || lastCommandsOnBus.find(command)->second.count(bank) == 0);
|
for(const ScheduledCommand& cmd : schedule.getScheduledCommands())
|
||||||
}
|
{
|
||||||
|
send(cmd);
|
||||||
sc_time CommandBus::getEarliestStartTime(const ScheduledCommand& command) const
|
}
|
||||||
{
|
}
|
||||||
sc_time newStart = command.getStart();
|
|
||||||
assert(isClkAligned(newStart, config.Timings.clk));
|
|
||||||
std::set<sc_time>::iterator it = pendingBusCommands.begin();
|
|
||||||
while (it != pendingBusCommands.end() && *it <= newStart)
|
|
||||||
{
|
|
||||||
if (*it == newStart)
|
|
||||||
newStart += config.Timings.clk;
|
|
||||||
++it;
|
|
||||||
}
|
|
||||||
return newStart;
|
|
||||||
}
|
|
||||||
|
|
||||||
void CommandBus::cleanUpBus(sc_time currentTime)
|
void CommandBus::cleanUpBus(sc_time currentTime)
|
||||||
{
|
{
|
||||||
pendingBusCommands.erase(pendingBusCommands.begin(), pendingBusCommands.lower_bound(currentTime));
|
state.pendingBusCommands.erase(state.pendingBusCommands.begin(),
|
||||||
|
state.pendingBusCommands.lower_bound(currentTime));
|
||||||
}
|
}
|
||||||
|
|
||||||
void CommandBus::changeControllerState(const ScheduledCommand& command)
|
void CommandBus::changeControllerState(const ScheduledCommand& command)
|
||||||
{
|
{
|
||||||
switch (command.getCommand())
|
switch (command.getCommand())
|
||||||
{
|
{
|
||||||
case Refresh:
|
case Refresh:
|
||||||
refresh(command);
|
refresh(command);
|
||||||
break;
|
break;
|
||||||
case Activate:
|
case Activate:
|
||||||
activate(command);
|
activate(command);
|
||||||
break;
|
break;
|
||||||
case Precharge:
|
case Precharge:
|
||||||
precharge(command);
|
precharge(command);
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void CommandBus::refresh(const ScheduledCommand& command)
|
void CommandBus::refresh(const ScheduledCommand& command)
|
||||||
{
|
{
|
||||||
if (config.RefreshBankwise)
|
if (config.RefreshBankwise)
|
||||||
{
|
{
|
||||||
state.bankStates.closeRowBuffer(command.getBank());
|
state.bankStates.closeRowBuffer(command.getBank());
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
state.bankStates.closeAllRowBuffers();
|
state.bankStates.closeAllRowBuffers();
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void CommandBus::precharge(const ScheduledCommand& command)
|
void CommandBus::precharge(const ScheduledCommand& command)
|
||||||
{
|
{
|
||||||
if (command.getCommand() == Precharge)
|
if (command.getCommand() == Precharge)
|
||||||
{
|
{
|
||||||
state.bankStates.closeRowBuffer(command.getBank());
|
state.bankStates.closeRowBuffer(command.getBank());
|
||||||
}
|
}
|
||||||
else if (command.getCommand() == PrechargeAll)
|
else if (command.getCommand() == PrechargeAll)
|
||||||
{
|
{
|
||||||
state.bankStates.closeAllRowBuffers();
|
state.bankStates.closeAllRowBuffers();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void CommandBus::activate(const ScheduledCommand& command)
|
void CommandBus::activate(const ScheduledCommand& command)
|
||||||
{
|
{
|
||||||
if (command.getCommand() == Activate)
|
if (command.getCommand() == Activate)
|
||||||
{
|
{
|
||||||
state.bankStates.openRowInRowBuffer(command.getBank(), command.getRow());
|
state.bankStates.openRowInRowBuffer(command.getBank(), command.getRow());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
} /* namespace controller */
|
} /* namespace controller */
|
||||||
|
|||||||
@@ -10,9 +10,8 @@
|
|||||||
|
|
||||||
#include <map>
|
#include <map>
|
||||||
#include <set>
|
#include <set>
|
||||||
#include "../tlm/IControllerWrapper.h"
|
|
||||||
#include "ControllerState.h"
|
#include "ControllerState.h"
|
||||||
#include "IInternalScheduler.h"
|
#include "IWrapperConnector.h"
|
||||||
#include "Configuration.h"
|
#include "Configuration.h"
|
||||||
#include "scheduling/CommandSchedule.h"
|
#include "scheduling/CommandSchedule.h"
|
||||||
#include "scheduling/Trigger.h"
|
#include "scheduling/Trigger.h"
|
||||||
@@ -20,49 +19,36 @@
|
|||||||
|
|
||||||
namespace core {
|
namespace core {
|
||||||
|
|
||||||
class CommandBus: public IInternalScheduler
|
class CommandBus
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
CommandBus(const Configuration& config, core::ControllerState& state,
|
CommandBus(IWrapperConnector& wrapperConnector, const Configuration& config, ControllerState& state):
|
||||||
std::vector<ICommandChecker*>& checker, IControllerWrapper& wrapper):
|
wrapperConnector(wrapperConnector), config(config), state(state)
|
||||||
wrapper(wrapper), config(config), state(state), checker(checker)
|
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
virtual void schedule(const CommandSchedule& schedule); //TODO add to interface
|
~CommandBus(){}
|
||||||
virtual void scheduleCommand(const ScheduledCommand& command);
|
|
||||||
virtual void scheduleTrigger(const Trigger trigger, sc_time time);
|
|
||||||
|
|
||||||
|
void schedule(ScheduledCommand& command);
|
||||||
|
|
||||||
|
void send(const ScheduledCommand& command) const;
|
||||||
|
void send(const Trigger trigger, sc_time time) const;
|
||||||
|
void send(const CommandSchedule& schedule) const;
|
||||||
|
|
||||||
void cleanUpBus(sc_time currentTime);
|
void cleanUpBus(sc_time currentTime);
|
||||||
|
|
||||||
ScheduledCommand getLastCommand(Command command, Bank bank); //TODO simple way to make it const?
|
|
||||||
ScheduledCommand getLastCommand(Command command);
|
|
||||||
ScheduledCommand getLastCommand(Bank bank);
|
|
||||||
|
|
||||||
bool notYetScheduled(Command command) const;
|
|
||||||
bool notYetScheduled(Command command, Bank bank) const;
|
|
||||||
sc_time getEarliestStartTime(const ScheduledCommand& command) const;
|
|
||||||
|
|
||||||
const std::set<sc_time>& getPendingBusCommands() const
|
|
||||||
{
|
|
||||||
return pendingBusCommands;
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
IControllerWrapper& wrapper;
|
IWrapperConnector& wrapperConnector;
|
||||||
const Configuration& config;
|
const Configuration& config;
|
||||||
core::ControllerState& state;
|
core::ControllerState& state;
|
||||||
std::vector<ICommandChecker*>& checker;
|
|
||||||
|
|
||||||
std::map<Command, std::map<Bank, ScheduledCommand> > lastCommandsOnBus;
|
|
||||||
std::set<sc_time> pendingBusCommands;
|
|
||||||
|
|
||||||
void notifyAllCheckersAboutScheduledCommand(const ScheduledCommand& command);
|
|
||||||
void changeControllerState(const ScheduledCommand& command);
|
void changeControllerState(const ScheduledCommand& command);
|
||||||
void refresh(const ScheduledCommand& command);
|
void refresh(const ScheduledCommand& command);
|
||||||
void precharge(const ScheduledCommand& command);
|
void precharge(const ScheduledCommand& command);
|
||||||
void activate(const ScheduledCommand& command);
|
void activate(const ScheduledCommand& command);
|
||||||
|
|
||||||
|
void scheduleOnBus(ScheduledCommand& command);
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif /* INTERNALSCHEDULER_H_ */
|
#endif /* INTERNALSCHEDULER_H_ */
|
||||||
|
|||||||
@@ -14,24 +14,34 @@
|
|||||||
|
|
||||||
namespace core {
|
namespace core {
|
||||||
|
|
||||||
DramController::DramController(IControllerWrapper& wrapper):
|
DramController::DramController(IWrapperConnector& wrapperConnector):
|
||||||
config(),state(config.numberOfBanks), commandSequenceGenerator(state), commandChecker(),allCommandChecker(),commandSequenceScheduler(
|
config(),state(config.numberOfBanks, config.nActivate), savedState(config.numberOfBanks, config.nActivate), commandSequenceGenerator(state), commandChecker(), commandSequenceScheduler(
|
||||||
commandChecker), bus(config, state, allCommandChecker, wrapper), refreshManager(config.Timings.refreshTimings[0], bus)
|
bus, commandChecker), bus(wrapperConnector, config, state), refreshManager(bus, config.Timings.refreshTimings[0])
|
||||||
{
|
{
|
||||||
addCommandChecker(Activate, new ActivateChecker(config, bus));
|
commandChecker[Activate] = new ActivateChecker(config, state);
|
||||||
addCommandChecker(Precharge, new PrechargeChecker(config, bus));
|
|
||||||
addCommandChecker(Read, new ReadChecker(config, bus));
|
commandChecker[Precharge] = new PrechargeChecker(config, state);
|
||||||
addCommandChecker(Write, new WriteChecker(config, bus));
|
commandChecker[Read] = new ReadChecker(config, state);
|
||||||
|
commandChecker[Write] = new WriteChecker(config, state);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
DramController::~DramController()
|
DramController::~DramController()
|
||||||
{
|
{
|
||||||
for (std::vector<ICommandChecker*>::iterator it = allCommandChecker.begin(); it != allCommandChecker.end();++it)
|
delete commandChecker[Activate];
|
||||||
{
|
delete commandChecker[Precharge];
|
||||||
delete *it;
|
delete commandChecker[Read];
|
||||||
}
|
delete commandChecker[Write];
|
||||||
|
}
|
||||||
|
|
||||||
|
void DramController::saveState()
|
||||||
|
{
|
||||||
|
savedState = state;
|
||||||
|
}
|
||||||
|
|
||||||
|
void DramController::resetState()
|
||||||
|
{
|
||||||
|
state = savedState;
|
||||||
}
|
}
|
||||||
|
|
||||||
void DramController::scheduleRefresh(sc_time time)
|
void DramController::scheduleRefresh(sc_time time)
|
||||||
@@ -39,41 +49,43 @@ void DramController::scheduleRefresh(sc_time time)
|
|||||||
refreshManager.scheduleRefresh(time);
|
refreshManager.scheduleRefresh(time);
|
||||||
}
|
}
|
||||||
|
|
||||||
void DramController::addCommandChecker(Command command, ICommandChecker* checker)
|
void DramController::schedule(sc_time start, tlm::tlm_generic_payload& payload)
|
||||||
{
|
{
|
||||||
commandChecker[command] = checker;
|
bus.cleanUpBus(start);
|
||||||
allCommandChecker.push_back(checker);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
start = clkAlign(start, config.Timings.clk);
|
||||||
void DramController::schedule(sc_time currentTime, tlm::tlm_generic_payload& payload)
|
|
||||||
{
|
|
||||||
bus.cleanUpBus(currentTime);
|
|
||||||
payload.set_streaming_width(config.burstlength);
|
payload.set_streaming_width(config.burstlength);
|
||||||
|
|
||||||
|
saveState();
|
||||||
|
|
||||||
CommandSequence sequence = commandSequenceGenerator.generateCommandSequence(
|
CommandSequence sequence = commandSequenceGenerator.generateCommandSequence(
|
||||||
payload);
|
payload);
|
||||||
CommandSchedule schedule = commandSequenceScheduler.prepareSchedule(currentTime,
|
CommandSchedule schedule = commandSequenceScheduler.schedule(sequence, start, payload);
|
||||||
payload, sequence);
|
|
||||||
|
//commandbuschecker (schedule)
|
||||||
|
|
||||||
while (refreshManager.hasCollision(schedule))
|
while (refreshManager.hasCollision(schedule))
|
||||||
{
|
{
|
||||||
refreshManager.scheduleRefresh(currentTime);
|
resetState();
|
||||||
|
refreshManager.scheduleRefresh(start);
|
||||||
|
saveState();
|
||||||
|
|
||||||
|
|
||||||
sequence = commandSequenceGenerator.generateCommandSequence(payload);
|
sequence = commandSequenceGenerator.generateCommandSequence(payload);
|
||||||
schedule = commandSequenceScheduler.prepareSchedule(currentTime, payload,
|
schedule = commandSequenceScheduler.schedule(sequence, start, payload);
|
||||||
sequence);
|
|
||||||
assert(schedule.getExecutionTime() < config.Timings.refreshTimings[0].tREFI); //TODO make nice
|
assert(schedule.getExecutionTime() < config.Timings.refreshTimings[0].tREFI); //TODO make nice
|
||||||
}
|
}
|
||||||
|
|
||||||
bus.schedule(schedule);
|
bus.send(schedule);
|
||||||
}
|
}
|
||||||
|
|
||||||
const ICommandChecker& DramController::getChecker(Command command) const
|
|
||||||
|
/*const ICommandChecker& DramController::getChecker(Command command) const
|
||||||
{
|
{
|
||||||
std::map<Command, ICommandChecker*>::const_iterator result = commandChecker.find(command);
|
std::map<Command, ICommandChecker*>::const_iterator result = commandChecker.find(command);
|
||||||
assert(result != commandChecker.end());
|
assert(result != commandChecker.end());
|
||||||
return *(result->second);
|
return *(result->second);
|
||||||
}
|
}*/
|
||||||
|
|
||||||
} /* namespace controller */
|
} /* namespace controller */
|
||||||
|
|
||||||
|
|||||||
@@ -10,7 +10,7 @@
|
|||||||
|
|
||||||
#include <tlm.h>
|
#include <tlm.h>
|
||||||
#include <map>
|
#include <map>
|
||||||
#include "../tlm/IControllerWrapper.h"
|
#include "IWrapperConnector.h"
|
||||||
#include "CommandBus.h"
|
#include "CommandBus.h"
|
||||||
#include "Configuration.h"
|
#include "Configuration.h"
|
||||||
#include "powerdown/PowerDownManager.h"
|
#include "powerdown/PowerDownManager.h"
|
||||||
@@ -24,24 +24,29 @@ namespace core {
|
|||||||
class DramController
|
class DramController
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
DramController(IControllerWrapper& wrapper);
|
DramController(IWrapperConnector& wrapper);
|
||||||
virtual ~DramController() ;
|
virtual ~DramController() ;
|
||||||
|
|
||||||
void schedule(sc_time currentTime, tlm::tlm_generic_payload& externalTransaction);
|
void schedule(sc_time currentTime, tlm::tlm_generic_payload& payload);
|
||||||
void scheduleRefresh(sc_time time);
|
void scheduleRefresh(sc_time time);
|
||||||
const ICommandChecker& getChecker(Command command) const;
|
const ICommandChecker& getChecker(Command command) const;
|
||||||
Configuration config;
|
Configuration config;
|
||||||
|
|
||||||
|
void saveState();
|
||||||
|
void resetState();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
ControllerState state;
|
ControllerState state;
|
||||||
|
ControllerState savedState;
|
||||||
|
|
||||||
CommandSequenceGenerator commandSequenceGenerator;
|
CommandSequenceGenerator commandSequenceGenerator;
|
||||||
std::map<Command, ICommandChecker*> commandChecker;
|
std::map<Command, ICommandChecker*> commandChecker;
|
||||||
std::vector<ICommandChecker*> allCommandChecker;
|
|
||||||
CommandSequenceScheduler commandSequenceScheduler;
|
CommandSequenceScheduler commandSequenceScheduler;
|
||||||
//PowerDownManager powerDownManager;
|
|
||||||
CommandBus bus;
|
CommandBus bus;
|
||||||
RefreshManager refreshManager;
|
RefreshManager refreshManager;
|
||||||
|
|
||||||
|
//std::vector<ICommandChecker*> allCommandChecker;
|
||||||
|
//PowerDownManager powerDownManager;
|
||||||
|
|
||||||
void addCommandChecker(Command command, ICommandChecker* checker);
|
void addCommandChecker(Command command, ICommandChecker* checker);
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -9,13 +9,35 @@
|
|||||||
|
|
||||||
namespace core {
|
namespace core {
|
||||||
|
|
||||||
ControllerState::ControllerState(unsigned int numberOfBanks) : bankStates(numberOfBanks)
|
const ScheduledCommand ControllerState::getLastCommand(Command command, Bank bank) //TODO const reference? and make const
|
||||||
{
|
{
|
||||||
|
return lastCommandsOnBus[command][bank];
|
||||||
}
|
}
|
||||||
|
|
||||||
ControllerState::~ControllerState() {
|
const ScheduledCommand ControllerState::getLastCommand(Command command)
|
||||||
// TODO Auto-generated destructor stub
|
{
|
||||||
|
ScheduledCommand max;
|
||||||
|
|
||||||
|
for (unsigned int i = 0; i < bankStates.getNumberOfBanks(); ++i)
|
||||||
|
{
|
||||||
|
ScheduledCommand current = getLastCommand(command, Bank(i));
|
||||||
|
if (current.getStart() > max.getStart())
|
||||||
|
max = current;
|
||||||
|
}
|
||||||
|
return max;
|
||||||
|
}
|
||||||
|
|
||||||
|
const ScheduledCommand ControllerState::getLastCommand(Bank bank)
|
||||||
|
{
|
||||||
|
ScheduledCommand lastCommand;
|
||||||
|
for (std::map<Command, std::map<Bank, ScheduledCommand> >::iterator it =
|
||||||
|
lastCommandsOnBus.begin(); it != lastCommandsOnBus.end(); ++it)
|
||||||
|
{
|
||||||
|
ScheduledCommand& current = lastCommandsOnBus[it->first][bank];
|
||||||
|
if (current.getStart() > lastCommand.getStart())
|
||||||
|
lastCommand = current;
|
||||||
|
}
|
||||||
|
return lastCommand;
|
||||||
}
|
}
|
||||||
|
|
||||||
} /* namespace controller */
|
} /* namespace controller */
|
||||||
|
|||||||
@@ -8,16 +8,33 @@
|
|||||||
#ifndef CONTROLLER_STATE_H_
|
#ifndef CONTROLLER_STATE_H_
|
||||||
#define CONTROLLER_STATE_H_
|
#define CONTROLLER_STATE_H_
|
||||||
|
|
||||||
|
#include <systemc.h>
|
||||||
#include "common/BankStates.h"
|
#include "common/BankStates.h"
|
||||||
|
#include "utils/RingBuffer.h"
|
||||||
|
#include "scheduling/ScheduledCommand.h"
|
||||||
|
#include <map>
|
||||||
|
#include <set>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
namespace core {
|
namespace core {
|
||||||
|
|
||||||
class ControllerState {
|
class ControllerState {
|
||||||
public:
|
public:
|
||||||
ControllerState(unsigned int numberOfBanks);
|
ControllerState(unsigned int numberOfBanks, unsigned int nActivates) : bankStates(numberOfBanks), nActivateWindow(nActivates){}
|
||||||
virtual ~ControllerState();
|
virtual ~ControllerState(){}
|
||||||
|
|
||||||
|
const ScheduledCommand getLastCommand(Command command, Bank bank);
|
||||||
|
const ScheduledCommand getLastCommand(Command command);
|
||||||
|
const ScheduledCommand getLastCommand(Bank bank);
|
||||||
|
|
||||||
BankStates bankStates;
|
BankStates bankStates;
|
||||||
|
|
||||||
|
RingBuffer<sc_time> nActivateWindow;
|
||||||
|
std::vector<sc_time> nACT;
|
||||||
|
std::map<Command, std::map<Bank, ScheduledCommand> > lastCommandsOnBus;
|
||||||
|
std::set<sc_time> pendingBusCommands;
|
||||||
|
private:
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
} /* namespace controller */
|
} /* namespace controller */
|
||||||
|
|||||||
@@ -10,16 +10,19 @@
|
|||||||
|
|
||||||
#include <systemc.h>
|
#include <systemc.h>
|
||||||
#include "scheduling/ScheduledCommand.h"
|
#include "scheduling/ScheduledCommand.h"
|
||||||
|
#include "scheduling/Trigger.h"
|
||||||
|
|
||||||
namespace core
|
namespace core
|
||||||
{
|
{
|
||||||
class IInternalScheduler
|
|
||||||
|
class IWrapperConnector
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
virtual ~IInternalScheduler() {}
|
virtual ~IWrapperConnector() {}
|
||||||
virtual void scheduleCommand(const core::ScheduledCommand& command) = 0;
|
virtual void send(const core::ScheduledCommand& command) = 0;
|
||||||
virtual void scheduleTrigger(const core::Trigger trigger, sc_time time) = 0;
|
virtual void send(core::Trigger trigger, sc_time time) = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif /* IINTERNALSCHEDULER_H_ */
|
#endif /* IINTERNALSCHEDULER_H_ */
|
||||||
@@ -24,14 +24,17 @@ struct TimingConfiguration
|
|||||||
{
|
{
|
||||||
TimingConfiguration(unsigned int numberOfBanks)
|
TimingConfiguration(unsigned int numberOfBanks)
|
||||||
{
|
{
|
||||||
|
|
||||||
|
clk = sc_time(6.0, SC_NS); // 166MHz
|
||||||
|
|
||||||
for (unsigned int i = 0; i < numberOfBanks; ++i)
|
for (unsigned int i = 0; i < numberOfBanks; ++i)
|
||||||
{
|
{
|
||||||
sc_time tRFC = 18*clk;
|
sc_time tRFC = 18*clk;
|
||||||
sc_time tREFI = sc_time(15.6, SC_US); //TODO align
|
sc_time tREFI = sc_time(15.6, SC_US); //TODO align
|
||||||
|
//tREFI = sc_time(301268, SC_NS);
|
||||||
refreshTimings.push_back(RefreshTiming(tRFC, tREFI));
|
refreshTimings.push_back(RefreshTiming(tRFC, tREFI));
|
||||||
}
|
}
|
||||||
|
|
||||||
clk = sc_time(6.0, SC_NS); // 166MHz
|
|
||||||
|
|
||||||
tRP = 3*clk; //precharge-time (pre -> act same bank)
|
tRP = 3*clk; //precharge-time (pre -> act same bank)
|
||||||
tRAS = 6*clk; //active-time (act -> pre same bank)
|
tRAS = 6*clk; //active-time (act -> pre same bank)
|
||||||
@@ -42,7 +45,7 @@ struct TimingConfiguration
|
|||||||
|
|
||||||
tRL = 3*clk; //read latency (read command start to data strobe)
|
tRL = 3*clk; //read latency (read command start to data strobe)
|
||||||
|
|
||||||
tTAW = clkAlign(sc_time(50, SC_NS), clk); //two activate window
|
tTAW = clkAlign(sc_time(50, SC_NS), clk, DOWN); //two activate window
|
||||||
}
|
}
|
||||||
|
|
||||||
sc_time clk;
|
sc_time clk;
|
||||||
|
|||||||
@@ -11,14 +11,13 @@ using namespace std;
|
|||||||
|
|
||||||
namespace core {
|
namespace core {
|
||||||
|
|
||||||
BankwiseRefreshManager::BankwiseRefreshManager(vector<RefreshTiming> refreshTimings,
|
BankwiseRefreshManager::BankwiseRefreshManager(CommandBus& bus, vector<RefreshTiming> refreshTimings)
|
||||||
IInternalScheduler& internalScheduler)
|
|
||||||
{
|
{
|
||||||
assert(!refreshTimings.empty());
|
assert(!refreshTimings.empty());
|
||||||
|
|
||||||
for (unsigned int i = 0; i < refreshTimings.size(); ++i)
|
for (unsigned int i = 0; i < refreshTimings.size(); ++i)
|
||||||
{
|
{
|
||||||
RefreshManager* manager = new RefreshManager(refreshTimings.at(i), internalScheduler, Bank(i));
|
RefreshManager* manager = new RefreshManager(bus, refreshTimings.at(i), Bank(i));
|
||||||
refreshManagerForBanks.push_back(manager);
|
refreshManagerForBanks.push_back(manager);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -17,8 +17,7 @@ namespace core {
|
|||||||
class BankwiseRefreshManager : public IRefreshManager
|
class BankwiseRefreshManager : public IRefreshManager
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
BankwiseRefreshManager(std::vector<RefreshTiming> refreshTimings,
|
BankwiseRefreshManager(CommandBus& bus, std::vector<RefreshTiming> refreshTimings);
|
||||||
IInternalScheduler& internalScheduler);
|
|
||||||
virtual ~BankwiseRefreshManager();
|
virtual ~BankwiseRefreshManager();
|
||||||
|
|
||||||
virtual bool hasCollision(const CommandSchedule& schedule);
|
virtual bool hasCollision(const CommandSchedule& schedule);
|
||||||
|
|||||||
@@ -12,19 +12,20 @@
|
|||||||
|
|
||||||
namespace core {
|
namespace core {
|
||||||
|
|
||||||
RefreshManager::RefreshManager(const RefreshTiming& refreshTiming,
|
RefreshManager::RefreshManager(CommandBus& bus, const RefreshTiming& refreshTiming) : bus(bus),
|
||||||
IInternalScheduler& internalScheduler) :
|
refreshTiming(refreshTiming)
|
||||||
refreshTiming(refreshTiming), internalScheduler(internalScheduler)
|
|
||||||
{
|
{
|
||||||
setupTransaction(refreshTransaction, Bank(0));
|
setupTransaction(refreshTransaction, Bank(0));
|
||||||
nextPlannedRefresh = new ScheduledCommand(refreshTransaction, Refresh, SC_ZERO_TIME,
|
nextPlannedRefresh = new ScheduledCommand(refreshTransaction, Refresh, SC_ZERO_TIME,
|
||||||
refreshTiming.tRFC);
|
refreshTiming.tRFC);
|
||||||
|
assert(refreshTiming.tRFC > SC_ZERO_TIME);
|
||||||
|
assert(nextPlannedRefresh->getExecutionTime()>SC_ZERO_TIME);
|
||||||
|
|
||||||
planNextRefresh(*nextPlannedRefresh);
|
planNextRefresh(*nextPlannedRefresh);
|
||||||
}
|
}
|
||||||
|
|
||||||
RefreshManager::RefreshManager(const RefreshTiming& refreshTiming,
|
RefreshManager::RefreshManager(CommandBus& bus, const RefreshTiming& refreshTiming,
|
||||||
IInternalScheduler& internalScheduler, Bank bank) :
|
Bank bank) : bus(bus), refreshTiming(refreshTiming)
|
||||||
refreshTiming(refreshTiming), internalScheduler(internalScheduler)
|
|
||||||
{
|
{
|
||||||
setupTransaction(refreshTransaction, bank);
|
setupTransaction(refreshTransaction, bank);
|
||||||
nextPlannedRefresh = new ScheduledCommand(refreshTransaction, Refresh, SC_ZERO_TIME,
|
nextPlannedRefresh = new ScheduledCommand(refreshTransaction, Refresh, SC_ZERO_TIME,
|
||||||
@@ -63,14 +64,15 @@ void RefreshManager::scheduleRefresh(sc_time time)
|
|||||||
|
|
||||||
void RefreshManager::scheduleRefresh(ScheduledCommand& refresh)
|
void RefreshManager::scheduleRefresh(ScheduledCommand& refresh)
|
||||||
{
|
{
|
||||||
internalScheduler.scheduleCommand(refresh);
|
bus.schedule(refresh);
|
||||||
|
bus.send(refresh);
|
||||||
planNextRefresh(refresh);
|
planNextRefresh(refresh);
|
||||||
}
|
}
|
||||||
|
|
||||||
void RefreshManager::planNextRefresh(ScheduledCommand& refresh) //TODO nicer to return the reference ?
|
void RefreshManager::planNextRefresh(ScheduledCommand& refresh) //TODO nicer to return the reference ?
|
||||||
{
|
{
|
||||||
refresh.delayStart(refreshTiming.tREFI);
|
refresh.delayStart(refreshTiming.tREFI);
|
||||||
internalScheduler.scheduleTrigger(RefreshTrigger, refresh.getStart());
|
bus.send(RefreshTrigger, refresh.getStart());
|
||||||
}
|
}
|
||||||
|
|
||||||
void RefreshManager::setupTransaction(tlm::tlm_generic_payload& transaction, Bank bank)
|
void RefreshManager::setupTransaction(tlm::tlm_generic_payload& transaction, Bank bank)
|
||||||
|
|||||||
@@ -16,16 +16,16 @@ namespace core {
|
|||||||
class RefreshManager : public IRefreshManager
|
class RefreshManager : public IRefreshManager
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
RefreshManager(const RefreshTiming& refreshTiming, IInternalScheduler& internalScheduler);
|
RefreshManager(CommandBus& bus, const RefreshTiming& refreshTiming);
|
||||||
RefreshManager(const RefreshTiming& refreshTiming, IInternalScheduler& internalScheduler, Bank bank);
|
RefreshManager(CommandBus& bus, const RefreshTiming& refreshTiming, Bank bank);
|
||||||
virtual ~RefreshManager();
|
virtual ~RefreshManager();
|
||||||
|
|
||||||
virtual bool hasCollision(const CommandSchedule& schedule);
|
virtual bool hasCollision(const CommandSchedule& schedule);
|
||||||
virtual void scheduleRefresh(sc_time time);
|
virtual void scheduleRefresh(sc_time time);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
CommandBus& bus;
|
||||||
const RefreshTiming& refreshTiming;
|
const RefreshTiming& refreshTiming;
|
||||||
IInternalScheduler& internalScheduler;
|
|
||||||
|
|
||||||
tlm::tlm_generic_payload refreshTransaction;
|
tlm::tlm_generic_payload refreshTransaction;
|
||||||
ScheduledCommand* nextPlannedRefresh;
|
ScheduledCommand* nextPlannedRefresh;
|
||||||
|
|||||||
@@ -28,7 +28,7 @@ public:
|
|||||||
|
|
||||||
ScheduledCommand& add(Command command, sc_time time, sc_time executionTime)
|
ScheduledCommand& add(Command command, sc_time time, sc_time executionTime)
|
||||||
{
|
{
|
||||||
assert(scheduledCommands.empty() || time >= scheduledCommands.back().getEnd());
|
//assert(scheduledCommands.empty() || time >= scheduledCommands.back().getEnd());
|
||||||
scheduledCommands.push_back(ScheduledCommand(*transaction, command, time, executionTime));
|
scheduledCommands.push_back(ScheduledCommand(*transaction, command, time, executionTime));
|
||||||
return scheduledCommands.back();
|
return scheduledCommands.back();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,21 +10,21 @@
|
|||||||
|
|
||||||
namespace core {
|
namespace core {
|
||||||
|
|
||||||
CommandSchedule CommandSequenceScheduler::prepareSchedule(sc_time start,
|
CommandSchedule CommandSequenceScheduler::schedule(CommandSequence commands, sc_time start,
|
||||||
tlm::tlm_generic_payload& transaction, CommandSequence commands)
|
tlm::tlm_generic_payload& transaction)
|
||||||
{
|
{
|
||||||
CommandSchedule schedule(transaction);
|
CommandSchedule schedule(transaction);
|
||||||
for (unsigned int i = 0; i < commands.size(); ++i)
|
|
||||||
{
|
|
||||||
Command command = commands.at(i);
|
|
||||||
ICommandChecker& checker = *commandChecker[command];
|
|
||||||
|
|
||||||
if (i > 0)
|
for (Command cmd : commands)
|
||||||
start = schedule.getEnd();
|
{
|
||||||
sc_time executionTime(checker.getExecutionTime(transaction, command));
|
ICommandChecker& checker = *commandChecker.at(cmd);
|
||||||
ScheduledCommand& scheduledCommand = schedule.add(command, start, executionTime);
|
|
||||||
checker.check(scheduledCommand);
|
sc_time executionTime = checker.getExecutionTime(transaction, cmd);
|
||||||
|
ScheduledCommand& scheduledCommand = schedule.add(cmd, start, executionTime);
|
||||||
|
checker.delayToSatisfyConstraints(scheduledCommand);
|
||||||
|
bus.schedule(scheduledCommand);
|
||||||
}
|
}
|
||||||
|
|
||||||
return schedule;
|
return schedule;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -11,6 +11,7 @@
|
|||||||
#include <map>
|
#include <map>
|
||||||
#include "CommandSchedule.h"
|
#include "CommandSchedule.h"
|
||||||
#include "../Command.h"
|
#include "../Command.h"
|
||||||
|
#include "../CommandBus.h"
|
||||||
#include "checker/ICommandChecker.h"
|
#include "checker/ICommandChecker.h"
|
||||||
|
|
||||||
|
|
||||||
@@ -22,11 +23,13 @@ class DramController;
|
|||||||
class CommandSequenceScheduler
|
class CommandSequenceScheduler
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
CommandSequenceScheduler(std::map<Command, ICommandChecker*>& commandChecker) : commandChecker(commandChecker){}
|
CommandSequenceScheduler(CommandBus& bus, std::map<Command, ICommandChecker*>& commandChecker) : bus(bus), commandChecker(commandChecker){}
|
||||||
virtual ~CommandSequenceScheduler(){}
|
virtual ~CommandSequenceScheduler(){}
|
||||||
CommandSchedule prepareSchedule(sc_time start, tlm::tlm_generic_payload& transaction, CommandSequence commands);
|
|
||||||
|
CommandSchedule schedule(CommandSequence commands, sc_time start, tlm::tlm_generic_payload& transaction);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
CommandBus& bus;
|
||||||
std::map<Command, ICommandChecker*>& commandChecker;
|
std::map<Command, ICommandChecker*>& commandChecker;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -46,6 +46,11 @@ public:
|
|||||||
return start;
|
return start;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void setStart(sc_time newStart)
|
||||||
|
{
|
||||||
|
start = newStart;
|
||||||
|
}
|
||||||
|
|
||||||
void delayStart(sc_time delay)
|
void delayStart(sc_time delay)
|
||||||
{
|
{
|
||||||
start += delay;
|
start += delay;
|
||||||
|
|||||||
@@ -10,15 +10,20 @@
|
|||||||
#include "../../utils/Utils.h"
|
#include "../../utils/Utils.h"
|
||||||
#include "ActivateChecker.h"
|
#include "ActivateChecker.h"
|
||||||
|
|
||||||
|
#include <iostream>
|
||||||
|
|
||||||
namespace core {
|
namespace core {
|
||||||
|
|
||||||
void ActivateChecker::check(ScheduledCommand& command) const
|
void ActivateChecker::delayToSatisfyConstraints(ScheduledCommand& command) const
|
||||||
{
|
{
|
||||||
if (command.getCommand() != Activate)
|
if (command.getCommand() != Activate)
|
||||||
return;
|
return;
|
||||||
check_activateToActivate(command);
|
satisfy_activateToActivate_sameBank(command);
|
||||||
check_nActivateWindow(command);
|
satisfy_activateToActivate_differentBank(command);
|
||||||
check_bus(command);
|
satisfy_nActivateWindow(command);
|
||||||
|
satisfy_prechargeToActivate(command);
|
||||||
|
|
||||||
|
satisfy_refreshToActivate(command);
|
||||||
}
|
}
|
||||||
|
|
||||||
sc_time ActivateChecker::getExecutionTime(const tlm::tlm_generic_payload& transaction,
|
sc_time ActivateChecker::getExecutionTime(const tlm::tlm_generic_payload& transaction,
|
||||||
@@ -28,53 +33,51 @@ sc_time ActivateChecker::getExecutionTime(const tlm::tlm_generic_payload& transa
|
|||||||
return config.Timings.tRCD;
|
return config.Timings.tRCD;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ActivateChecker::check_activateToActivate(ScheduledCommand& command) const
|
void ActivateChecker::satisfy_activateToActivate_differentBank(ScheduledCommand& command) const
|
||||||
{
|
{
|
||||||
if (bus.notYetScheduled(Activate))
|
ScheduledCommand lastActivate = state.getLastCommand(Activate);
|
||||||
return;
|
|
||||||
|
|
||||||
ScheduledCommand lastActivate = bus.getLastCommand(Activate);
|
|
||||||
if (lastActivate.isValidCommand())
|
if (lastActivate.isValidCommand())
|
||||||
command.delayStart(
|
command.delayStart(
|
||||||
delayByConstraint(lastActivate.getStart(), command.getStart(),
|
delayByConstraint(lastActivate.getStart(), command.getStart(),
|
||||||
config.Timings.tRRD));
|
config.Timings.tRRD));
|
||||||
|
}
|
||||||
|
|
||||||
ScheduledCommand lastActivateOnBank = bus.getLastCommand(Activate, command.getBank());
|
void ActivateChecker::satisfy_refreshToActivate(ScheduledCommand& command) const
|
||||||
|
{
|
||||||
|
ScheduledCommand lastRefresh = state.getLastCommand(Refresh);
|
||||||
|
if (lastRefresh.isValidCommand())
|
||||||
|
command.delayStart(
|
||||||
|
delayByConstraint(lastRefresh.getEnd(), command.getStart(),
|
||||||
|
SC_ZERO_TIME));
|
||||||
|
}
|
||||||
|
|
||||||
|
void ActivateChecker::satisfy_activateToActivate_sameBank(ScheduledCommand& command) const
|
||||||
|
{
|
||||||
|
ScheduledCommand lastActivateOnBank = state.getLastCommand(Activate, command.getBank());
|
||||||
if (lastActivateOnBank.isValidCommand())
|
if (lastActivateOnBank.isValidCommand())
|
||||||
command.delayStart(
|
command.delayStart(
|
||||||
delayByConstraint(lastActivateOnBank.getStart(), command.getStart(),
|
delayByConstraint(lastActivateOnBank.getStart(), command.getStart(),
|
||||||
config.Timings.tRC));
|
config.Timings.tRC));
|
||||||
}
|
}
|
||||||
|
|
||||||
void ActivateChecker::check_prechargeToActivate(ScheduledCommand& command) const
|
void ActivateChecker::satisfy_prechargeToActivate(ScheduledCommand& command) const
|
||||||
{
|
{
|
||||||
sc_time lastPrechargeOnBank = std::max(
|
sc_time lastPrechargeOnBank = std::max(
|
||||||
bus.getLastCommand(Precharge, command.getBank()).getStart(),
|
state.getLastCommand(Precharge, command.getBank()).getStart(),
|
||||||
bus.getLastCommand(PrechargeAll, command.getBank()).getStart());
|
state.getLastCommand(PrechargeAll, command.getBank()).getStart());
|
||||||
command.delayStart(
|
command.delayStart(
|
||||||
delayByConstraint(lastPrechargeOnBank, command.getStart(), config.Timings.tRC));
|
delayByConstraint(lastPrechargeOnBank, command.getStart(), config.Timings.tRC));
|
||||||
}
|
}
|
||||||
|
|
||||||
void ActivateChecker::check_nActivateWindow(ScheduledCommand& command) const
|
void ActivateChecker::satisfy_nActivateWindow(ScheduledCommand& command) const
|
||||||
{
|
{
|
||||||
if (!nActivateWindow.isFull())
|
if (!state.nActivateWindow.isFull())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
command.delayStart(
|
command.delayStart(
|
||||||
delayByConstraint(nActivateWindow.getOldest(), command.getStart(),
|
delayByConstraint(state.nActivateWindow.getOldest(), command.getStart(),
|
||||||
config.Timings.tTAW));
|
config.Timings.tTAW));
|
||||||
}
|
|
||||||
|
|
||||||
void ActivateChecker::check_bus(ScheduledCommand& command) const
|
|
||||||
{
|
|
||||||
command.delayStart(bus.getEarliestStartTime(command) - command.getStart());
|
|
||||||
}
|
|
||||||
|
|
||||||
void ActivateChecker::notifyAboutScheduledCommand(const ScheduledCommand& command)
|
|
||||||
{
|
|
||||||
if (command.getCommand() == Activate)
|
|
||||||
{
|
|
||||||
nActivateWindow.put(command.getStart());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
} /* namespace controller */
|
} /* namespace controller */
|
||||||
|
|||||||
@@ -12,29 +12,29 @@
|
|||||||
#include "ICommandChecker.h"
|
#include "ICommandChecker.h"
|
||||||
#include "../../Configuration.h"
|
#include "../../Configuration.h"
|
||||||
#include "../../utils/RingBuffer.h"
|
#include "../../utils/RingBuffer.h"
|
||||||
#include "../../CommandBus.h"
|
#include "../../ControllerState.h"
|
||||||
|
|
||||||
namespace core {
|
namespace core {
|
||||||
|
|
||||||
class ActivateChecker: public core::ICommandChecker
|
class ActivateChecker: public ICommandChecker
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
ActivateChecker(Configuration& config, CommandBus& commandBus) : config(config), bus(commandBus), nActivateWindow(config.nActivate){}
|
ActivateChecker(const Configuration& config, ControllerState& state) : config(config), state(state){}
|
||||||
virtual ~ActivateChecker(){}
|
virtual ~ActivateChecker(){}
|
||||||
|
|
||||||
virtual void check(ScheduledCommand& command) const;
|
virtual void delayToSatisfyConstraints(ScheduledCommand& command) const;
|
||||||
virtual sc_time getExecutionTime(const tlm::tlm_generic_payload& transaction, Command command) const;
|
virtual sc_time getExecutionTime(const tlm::tlm_generic_payload& payload, Command command) const;
|
||||||
virtual void notifyAboutScheduledCommand(const ScheduledCommand& command);
|
|
||||||
private:
|
private:
|
||||||
const Configuration& config;
|
const Configuration& config;
|
||||||
CommandBus& bus;//TODO should be const .. but fucking map access operator!!!!
|
ControllerState& state;//TODO make const
|
||||||
|
|
||||||
void check_activateToActivate(ScheduledCommand& command) const;
|
void satisfy_activateToActivate_sameBank(ScheduledCommand& command) const;
|
||||||
void check_prechargeToActivate(ScheduledCommand& command) const;
|
void satisfy_activateToActivate_differentBank(ScheduledCommand& command) const;
|
||||||
void check_nActivateWindow(ScheduledCommand& command) const;
|
void satisfy_prechargeToActivate(ScheduledCommand& command) const;
|
||||||
void check_bus(ScheduledCommand& command) const;
|
void satisfy_nActivateWindow(ScheduledCommand& command) const;
|
||||||
|
|
||||||
RingBuffer<sc_time> nActivateWindow;
|
void satisfy_refreshToActivate(ScheduledCommand& command) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
} /* namespace controller */
|
} /* namespace controller */
|
||||||
|
|||||||
@@ -8,7 +8,7 @@
|
|||||||
#ifndef ICOMMANDSCHEDULER_H_
|
#ifndef ICOMMANDSCHEDULER_H_
|
||||||
#define ICOMMANDSCHEDULER_H_
|
#define ICOMMANDSCHEDULER_H_
|
||||||
|
|
||||||
#include "systemc.h"
|
#include <systemc.h>
|
||||||
#include "../ScheduledCommand.h"
|
#include "../ScheduledCommand.h"
|
||||||
|
|
||||||
namespace core {
|
namespace core {
|
||||||
@@ -18,9 +18,8 @@ class ICommandChecker
|
|||||||
public:
|
public:
|
||||||
virtual ~ICommandChecker() {}
|
virtual ~ICommandChecker() {}
|
||||||
|
|
||||||
virtual void check(ScheduledCommand& command) const = 0;
|
virtual void delayToSatisfyConstraints(ScheduledCommand& command) const = 0;
|
||||||
virtual sc_time getExecutionTime(const tlm::tlm_generic_payload& transaction, Command command) const = 0;
|
virtual sc_time getExecutionTime(const tlm::tlm_generic_payload& payload, Command command) const = 0;
|
||||||
virtual void notifyAboutScheduledCommand(const ScheduledCommand& command) = 0;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
} /* namespace controller */
|
} /* namespace controller */
|
||||||
|
|||||||
@@ -9,23 +9,20 @@
|
|||||||
|
|
||||||
namespace core {
|
namespace core {
|
||||||
|
|
||||||
void PrechargeChecker::check(ScheduledCommand& command) const
|
void PrechargeChecker::delayToSatisfyConstraints(ScheduledCommand& command) const
|
||||||
{
|
{
|
||||||
ScheduledCommand lastCommand = bus.getLastCommand(command.getBank());
|
ScheduledCommand lastCommand = state.getLastCommand(command.getBank());
|
||||||
if(lastCommand.isValidCommand() && lastCommand.getEnd() > command.getStart())
|
if(lastCommand.isValidCommand() && lastCommand.getEnd() > command.getStart())
|
||||||
{
|
{
|
||||||
command.delayStart(lastCommand.getEnd()-command.getStart());
|
command.delayStart(lastCommand.getEnd()-command.getStart());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
sc_time PrechargeChecker::getExecutionTime(const tlm::tlm_generic_payload& transaction,
|
sc_time PrechargeChecker::getExecutionTime(const tlm::tlm_generic_payload& payload,
|
||||||
Command command) const
|
Command command) const
|
||||||
{
|
{
|
||||||
assert(command == Precharge || command == PrechargeAll);
|
assert(command == Precharge || command == PrechargeAll);
|
||||||
return config.Timings.tRP;
|
return config.Timings.tRP;
|
||||||
}
|
}
|
||||||
void PrechargeChecker::notifyAboutScheduledCommand(const ScheduledCommand& command)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
} /* namespace controller */
|
} /* namespace controller */
|
||||||
|
|||||||
@@ -10,22 +10,21 @@
|
|||||||
|
|
||||||
#include "ICommandChecker.h"
|
#include "ICommandChecker.h"
|
||||||
#include "../../Configuration.h"
|
#include "../../Configuration.h"
|
||||||
#include "../../CommandBus.h"
|
#include "../../ControllerState.h"
|
||||||
|
|
||||||
namespace core {
|
namespace core {
|
||||||
|
|
||||||
class PrechargeChecker: public core::ICommandChecker
|
class PrechargeChecker: public core::ICommandChecker
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
PrechargeChecker(const Configuration& config, CommandBus& commandBus) : config(config), bus(commandBus) {}
|
PrechargeChecker(const Configuration& config, ControllerState& state) : config(config), state(state) {}
|
||||||
virtual ~PrechargeChecker() {}
|
virtual ~PrechargeChecker() {}
|
||||||
|
|
||||||
virtual void check(ScheduledCommand& command) const;
|
virtual void delayToSatisfyConstraints(ScheduledCommand& command) const;
|
||||||
virtual sc_time getExecutionTime(const tlm::tlm_generic_payload& transaction, Command command) const;
|
virtual sc_time getExecutionTime(const tlm::tlm_generic_payload& payload, Command command) const;
|
||||||
virtual void notifyAboutScheduledCommand(const ScheduledCommand& command);
|
|
||||||
private:
|
private:
|
||||||
const Configuration& config;
|
const Configuration& config;
|
||||||
CommandBus& bus;
|
ControllerState& state;//TODO make const
|
||||||
};
|
};
|
||||||
|
|
||||||
} /* namespace controller */
|
} /* namespace controller */
|
||||||
|
|||||||
@@ -10,9 +10,9 @@
|
|||||||
|
|
||||||
namespace core {
|
namespace core {
|
||||||
|
|
||||||
void ReadChecker::check(ScheduledCommand& command) const
|
void ReadChecker::delayToSatisfyConstraints(ScheduledCommand& command) const
|
||||||
{
|
{
|
||||||
ScheduledCommand lastCommand = bus.getLastCommand(command.getBank());
|
ScheduledCommand lastCommand = state.getLastCommand(command.getBank());
|
||||||
if(lastCommand.isValidCommand() && lastCommand.getEnd() > command.getStart())
|
if(lastCommand.isValidCommand() && lastCommand.getEnd() > command.getStart())
|
||||||
{
|
{
|
||||||
command.delayStart(lastCommand.getEnd()-command.getStart());
|
command.delayStart(lastCommand.getEnd()-command.getStart());
|
||||||
@@ -28,8 +28,4 @@ sc_time ReadChecker::getExecutionTime(const tlm::tlm_generic_payload& payload,
|
|||||||
return config.Timings.tRL + config.Timings.clk*payload.get_streaming_width();
|
return config.Timings.tRL + config.Timings.clk*payload.get_streaming_width();
|
||||||
}
|
}
|
||||||
|
|
||||||
void ReadChecker::notifyAboutScheduledCommand(const ScheduledCommand& command)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
} /* namespace controller */
|
} /* namespace controller */
|
||||||
|
|||||||
@@ -10,22 +10,21 @@
|
|||||||
|
|
||||||
#include "ICommandChecker.h"
|
#include "ICommandChecker.h"
|
||||||
#include "../../Configuration.h"
|
#include "../../Configuration.h"
|
||||||
#include "../../CommandBus.h"
|
#include "../../ControllerState.h"
|
||||||
|
|
||||||
namespace core {
|
namespace core {
|
||||||
|
|
||||||
class ReadChecker: public core::ICommandChecker
|
class ReadChecker: public core::ICommandChecker
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
ReadChecker(const Configuration& config, CommandBus& commandBus) : config(config), bus(commandBus) {}
|
ReadChecker(Configuration& config, ControllerState& state) : config(config), state(state) {}
|
||||||
virtual ~ReadChecker() {}
|
virtual ~ReadChecker() {}
|
||||||
|
|
||||||
virtual void check(ScheduledCommand& command) const;
|
virtual void delayToSatisfyConstraints(ScheduledCommand& command) const;
|
||||||
virtual sc_time getExecutionTime(const tlm::tlm_generic_payload& payload, Command command) const;
|
virtual sc_time getExecutionTime(const tlm::tlm_generic_payload& payload, Command command) const;
|
||||||
virtual void notifyAboutScheduledCommand(const ScheduledCommand& command);
|
|
||||||
private:
|
private:
|
||||||
const Configuration& config;
|
const Configuration& config;
|
||||||
CommandBus& bus;
|
ControllerState& state;
|
||||||
};
|
};
|
||||||
|
|
||||||
} /* namespace controller */
|
} /* namespace controller */
|
||||||
|
|||||||
@@ -9,19 +9,15 @@
|
|||||||
|
|
||||||
namespace core {
|
namespace core {
|
||||||
|
|
||||||
void WriteChecker::check(ScheduledCommand& command) const
|
void WriteChecker::delayToSatisfyConstraints(ScheduledCommand& command) const
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
sc_time WriteChecker::getExecutionTime(const tlm::tlm_generic_payload& transaction,
|
sc_time WriteChecker::getExecutionTime(const tlm::tlm_generic_payload& payload,
|
||||||
Command command) const
|
Command command) const
|
||||||
{
|
{
|
||||||
assert(command == Write || command == WriteA);
|
assert(command == Write || command == WriteA);
|
||||||
return config.Timings.clk*8;
|
return config.Timings.clk*8;
|
||||||
}
|
}
|
||||||
|
|
||||||
void WriteChecker::notifyAboutScheduledCommand(const ScheduledCommand& command)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
} /* namespace controller */
|
} /* namespace controller */
|
||||||
|
|||||||
@@ -10,22 +10,21 @@
|
|||||||
|
|
||||||
#include "ICommandChecker.h"
|
#include "ICommandChecker.h"
|
||||||
#include "../../Configuration.h"
|
#include "../../Configuration.h"
|
||||||
#include "../../CommandBus.h"
|
#include "../../ControllerState.h"
|
||||||
|
|
||||||
namespace core {
|
namespace core {
|
||||||
|
|
||||||
class WriteChecker: public core::ICommandChecker
|
class WriteChecker: public core::ICommandChecker
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
WriteChecker(const Configuration& config, const CommandBus& commandBus) : config(config), bus(commandBus) {}
|
WriteChecker(const Configuration& config, ControllerState& state) : config(config), state(state) {}
|
||||||
virtual ~WriteChecker() {}
|
virtual ~WriteChecker() {}
|
||||||
|
|
||||||
virtual void check(ScheduledCommand& command) const;
|
virtual void delayToSatisfyConstraints(ScheduledCommand& command) const;
|
||||||
virtual sc_time getExecutionTime(const tlm::tlm_generic_payload& transaction, Command command) const;
|
virtual sc_time getExecutionTime(const tlm::tlm_generic_payload& payload, Command command) const;
|
||||||
virtual void notifyAboutScheduledCommand(const ScheduledCommand& command);
|
|
||||||
private:
|
private:
|
||||||
const Configuration& config;
|
const Configuration& config;
|
||||||
const CommandBus& bus;
|
ControllerState& state;
|
||||||
};
|
};
|
||||||
|
|
||||||
} /* namespace controller */
|
} /* namespace controller */
|
||||||
|
|||||||
@@ -9,6 +9,7 @@
|
|||||||
#define RINGBUFFER_H_
|
#define RINGBUFFER_H_
|
||||||
|
|
||||||
#include <systemc.h>
|
#include <systemc.h>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
class RingBuffer
|
class RingBuffer
|
||||||
@@ -20,8 +21,8 @@ public:
|
|||||||
void put(T t)
|
void put(T t)
|
||||||
{
|
{
|
||||||
buffer.push_back(t);
|
buffer.push_back(t);
|
||||||
if(getSize()>maxSize)
|
if(getSize() > maxSize)
|
||||||
buffer.pop_front();
|
buffer.erase(buffer.begin());
|
||||||
}
|
}
|
||||||
|
|
||||||
T getOldest() const
|
T getOldest() const
|
||||||
@@ -58,7 +59,7 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::deque<T> buffer;
|
std::vector<T> buffer;
|
||||||
unsigned int maxSize;
|
unsigned int maxSize;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -1,23 +0,0 @@
|
|||||||
/*
|
|
||||||
* IControllerWrapper.h
|
|
||||||
*
|
|
||||||
* Created on: Mar 15, 2014
|
|
||||||
* Author: gernhard
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef ICONTROLLERWRAPPER_H_
|
|
||||||
#define ICONTROLLERWRAPPER_H_
|
|
||||||
#include <tlm.h>
|
|
||||||
#include <systemc.h>
|
|
||||||
#include "../core/Command.h"
|
|
||||||
#include "../core/scheduling/Trigger.h"
|
|
||||||
|
|
||||||
class IControllerWrapper{
|
|
||||||
public:
|
|
||||||
virtual void sendCommand(sc_time startTime, tlm::tlm_generic_payload& payload, core::Command command) = 0;
|
|
||||||
virtual void sendTrigger(sc_time time, core::Trigger trigger) = 0;
|
|
||||||
virtual ~IControllerWrapper(){}
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
#endif /* ICONTROLLERWRAPPER_H_ */
|
|
||||||
@@ -17,7 +17,7 @@
|
|||||||
|
|
||||||
#include "common/protocol.h"
|
#include "common/protocol.h"
|
||||||
#include "common/tlmDBPhaseRecorder.h"
|
#include "common/tlmDBPhaseRecorder.h"
|
||||||
#include "dram/tlm/IControllerWrapper.h"
|
#include "dram/core/IWrapperConnector.h"
|
||||||
#include "dram/core/Controller.h"
|
#include "dram/core/Controller.h"
|
||||||
|
|
||||||
using namespace std;
|
using namespace std;
|
||||||
@@ -25,7 +25,7 @@ using namespace tlm;
|
|||||||
using namespace core;
|
using namespace core;
|
||||||
|
|
||||||
template<unsigned int BUSWIDTH = 128>
|
template<unsigned int BUSWIDTH = 128>
|
||||||
struct ControllerWrapper: public sc_module, public IControllerWrapper
|
struct ControllerWrapper: public sc_module, public IWrapperConnector
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
|
||||||
@@ -48,13 +48,12 @@ public:
|
|||||||
delete controller;
|
delete controller;
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void sendCommand(sc_time startTime, tlm::tlm_generic_payload& payload,
|
virtual void send(const ScheduledCommand& command)
|
||||||
Command command)
|
|
||||||
{
|
{
|
||||||
assert(startTime >= sc_time_stamp());
|
assert(command.getStart() >= sc_time_stamp()||command.getStart()<sc_time(100000, SC_NS));
|
||||||
sc_time delay = startTime - sc_time_stamp();
|
sc_time delay = command.getStart() - sc_time_stamp();
|
||||||
tlm::tlm_phase phase;
|
tlm::tlm_phase phase;
|
||||||
switch (command)
|
switch (command.getCommand())
|
||||||
{
|
{
|
||||||
case Read:
|
case Read:
|
||||||
phase = BEGIN_RD;
|
phase = BEGIN_RD;
|
||||||
@@ -76,15 +75,16 @@ public:
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
dramPEQ.notify(payload, phase, delay);
|
dramPEQ.notify(command.getTransaction(), phase, delay);
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void sendTrigger(sc_time time, Trigger trigger)
|
virtual void send(Trigger trigger, sc_time time)
|
||||||
{
|
{
|
||||||
assert(time >= sc_time_stamp());
|
assert(time >= sc_time_stamp());
|
||||||
sc_time delay = time - sc_time_stamp();
|
sc_time delay = time - sc_time_stamp();
|
||||||
controllerPEQ.notify(triggerDummy,REFRESH_TRIGGER,delay);
|
controllerPEQ.notify(triggerDummy, REFRESH_TRIGGER, delay);
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
DramController* controller;
|
DramController* controller;
|
||||||
tlm_utils::peq_with_cb_and_phase<ControllerWrapper> frontendPEQ;
|
tlm_utils::peq_with_cb_and_phase<ControllerWrapper> frontendPEQ;
|
||||||
@@ -149,7 +149,7 @@ private:
|
|||||||
if (phase == BEGIN_RD || phase == BEGIN_WR || phase == BEGIN_REFA || phase == BEGIN_ACT
|
if (phase == BEGIN_RD || phase == BEGIN_WR || phase == BEGIN_REFA || phase == BEGIN_ACT
|
||||||
|| phase == BEGIN_PRE)
|
|| phase == BEGIN_PRE)
|
||||||
{
|
{
|
||||||
sendToDram(payload, phase, SC_ZERO_TIME);
|
sendToDram(payload, phase, SC_ZERO_TIME);//TODO delay in send mehtod instead of way through PEQ
|
||||||
}
|
}
|
||||||
else if (phase == END_RD || phase == END_WR)
|
else if (phase == END_RD || phase == END_WR)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ using namespace testing;
|
|||||||
|
|
||||||
namespace core {
|
namespace core {
|
||||||
|
|
||||||
class MockInternalScheduler: public IInternalScheduler
|
class MockInternalScheduler: public IBus
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
MOCK_METHOD1(scheduleCommand, void (const ScheduledCommand& command));
|
MOCK_METHOD1(scheduleCommand, void (const ScheduledCommand& command));
|
||||||
|
|||||||
@@ -17,7 +17,7 @@ using namespace testing;
|
|||||||
|
|
||||||
namespace core {
|
namespace core {
|
||||||
|
|
||||||
class MockInternalScheduler: public IInternalScheduler
|
class MockInternalScheduler: public IBus
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
MOCK_METHOD1(scheduleCommand, void (const ScheduledCommand& command));
|
MOCK_METHOD1(scheduleCommand, void (const ScheduledCommand& command));
|
||||||
|
|||||||
@@ -74,9 +74,9 @@ TEST(UtilsTest, RingBufferWorks)
|
|||||||
|
|
||||||
TEST(UtilsTest,getBurstLengthInBytesWorks)
|
TEST(UtilsTest,getBurstLengthInBytesWorks)
|
||||||
{
|
{
|
||||||
tlm::tlm_generic_payload payload;
|
//tlm::tlm_generic_payload payload;
|
||||||
payload.set_data_length(4);
|
// payload.set_data_length(4);
|
||||||
EXPECT_EQ(4,getBurstLengthInBytes(payload,128));
|
// EXPECT_EQ(4,getBurstLengthInBytes(payload,128));
|
||||||
}
|
}
|
||||||
|
|
||||||
} /* namespace controller */
|
} /* namespace controller */
|
||||||
|
|||||||
Reference in New Issue
Block a user