125 lines
3.1 KiB
C++
125 lines
3.1 KiB
C++
/*
|
|
* controller.cpp
|
|
*
|
|
* Created on: Mar 5, 2014
|
|
* Author: jonny
|
|
*/
|
|
|
|
#include <systemc.h>
|
|
#include "Controller.h"
|
|
#include "scheduling/checker/ActivateChecker.h"
|
|
#include "scheduling/checker/PrechargeChecker.h"
|
|
#include "scheduling/checker/ReadChecker.h"
|
|
#include "scheduling/checker/WriteChecker.h"
|
|
#include "refresh/RefreshManagerBankwise.h"
|
|
#include "refresh/RefreshManager.h"
|
|
|
|
namespace core {
|
|
|
|
Controller::Controller(IWrapperConnector& wrapperConnector, TlmRecorder& recorder) :
|
|
config(), state(config.numberOfBanks, config.nActivate), busChecker(config, state), wrapper(
|
|
wrapperConnector), commandChecker(), recorder(recorder), savedState(
|
|
config.numberOfBanks, config.nActivate), commandSequenceGenerator(state), commandSequenceScheduler(
|
|
*this)
|
|
|
|
{
|
|
commandChecker[Command::Activate] = new ActivateChecker(config, state);
|
|
commandChecker[Command::Precharge] = new PrechargeChecker(config, state);
|
|
commandChecker[Command::Read] = new ReadChecker(config, state);
|
|
commandChecker[Command::Write] = new WriteChecker(config, state);
|
|
|
|
if(config.RefreshBankwise)
|
|
refreshManager = new RefreshManagerBankwise(*this);
|
|
else
|
|
refreshManager = new RefreshManager(*this);
|
|
}
|
|
|
|
Controller::~Controller()
|
|
{
|
|
delete commandChecker[Command::Activate];
|
|
delete commandChecker[Command::Precharge];
|
|
delete commandChecker[Command::Read];
|
|
delete commandChecker[Command::Write];
|
|
delete refreshManager;
|
|
}
|
|
|
|
void Controller::saveState()
|
|
{
|
|
savedState = state;
|
|
}
|
|
|
|
void Controller::resetState()
|
|
{
|
|
state = savedState;
|
|
}
|
|
|
|
void Controller::scheduleRefresh(tlm::tlm_generic_payload& payload, sc_time time)
|
|
{
|
|
cleanUpBus(time);
|
|
refreshManager->scheduleRefresh(payload, time);
|
|
}
|
|
|
|
bool Controller::schedule(sc_time start, tlm::tlm_generic_payload& payload)
|
|
{
|
|
cleanUpBus(start);
|
|
|
|
start = clkAlign(start, config.Timings.clk);
|
|
payload.set_streaming_width(config.burstlength);
|
|
|
|
saveState();
|
|
|
|
CommandSequence sequence = commandSequenceGenerator.generateCommandSequence(payload);
|
|
CommandSchedule schedule = commandSequenceScheduler.schedule(sequence, start, payload);
|
|
|
|
if (refreshManager->hasCollision(schedule))
|
|
{
|
|
resetState();
|
|
return false;
|
|
}
|
|
else
|
|
{
|
|
send(schedule);
|
|
return true;
|
|
}
|
|
}
|
|
|
|
bool Controller::isBusy(sc_time currentTime, Bank bank)
|
|
{
|
|
ScheduledCommand lastScheduledCommand = state.getLastCommand(bank);
|
|
if (lastScheduledCommand.isNoCommand())
|
|
return false;
|
|
else if (lastScheduledCommand.getCommand() == Command::Write
|
|
|| lastScheduledCommand.getCommand() == Command::Read)
|
|
{
|
|
return (currentTime < lastScheduledCommand.getStart());
|
|
}
|
|
else if (lastScheduledCommand.getCommand() == Command::AutoRefresh)
|
|
{
|
|
return (currentTime < lastScheduledCommand.getEnd());
|
|
}
|
|
else
|
|
{
|
|
SC_ASSERT_(false, "last command in command sequence was activate or precharge");
|
|
return false;
|
|
}
|
|
|
|
}
|
|
|
|
void Controller::send(const CommandSchedule& schedule) const
|
|
{
|
|
for (const ScheduledCommand& cmd : schedule.getScheduledCommands())
|
|
{
|
|
wrapper.send(cmd);
|
|
}
|
|
}
|
|
|
|
|
|
void Controller::cleanUpBus(sc_time currentTime)
|
|
{
|
|
state.pendingBusCommands.erase(state.pendingBusCommands.begin(),
|
|
state.pendingBusCommands.lower_bound(currentTime));
|
|
}
|
|
|
|
} /* namespace controller */
|
|
|