110 lines
3.1 KiB
C++
110 lines
3.1 KiB
C++
/*
|
|
* ActivateScheduler.cpp
|
|
*
|
|
* Created on: Mar 12, 2014
|
|
* Author: jonny
|
|
*/
|
|
|
|
#include <algorithm>
|
|
#include <set>
|
|
#include "ActivateChecker.h"
|
|
#include "../../TimingCalculation.h"
|
|
#include "../../../common/DebugManager.h"
|
|
#include "../../Command.h"
|
|
#include "../../../common/Utils.h"
|
|
#include <iostream>
|
|
|
|
namespace core {
|
|
|
|
void ActivateChecker::delayToSatisfyConstraints(ScheduledCommand& command) const
|
|
{
|
|
sc_assert(command.getCommand() == Command::Activate);
|
|
|
|
ScheduledCommand lastCommandOnBank = state.getLastScheduledCommand(command.getBank());
|
|
if (lastCommandOnBank.isValidCommand())
|
|
{
|
|
if (isIn(lastCommandOnBank.getCommand(), { Command::Precharge, Command::AutoRefresh,
|
|
Command::ReadA, Command::WriteA }))
|
|
{
|
|
command.delayToMeetConstraint(lastCommandOnBank.getEnd(), SC_ZERO_TIME);
|
|
}
|
|
else if (lastCommandOnBank.getCommand() == Command::PDNPX
|
|
|| lastCommandOnBank.getCommand() == Command::PDNAX)
|
|
{
|
|
command.delayToMeetConstraint(lastCommandOnBank.getStart(), config.Timings.tXP);
|
|
}
|
|
else if (lastCommandOnBank.getCommand() == Command::SREFX)
|
|
{
|
|
command.delayToMeetConstraint(lastCommandOnBank.getStart(), config.Timings.tXSR);
|
|
}
|
|
else
|
|
reportFatal("Activate Checker",
|
|
"Activate can not follow " + commandToString(lastCommandOnBank.getCommand()));
|
|
}
|
|
|
|
delay_to_satisfy_activateToActivate_sameBank(command);
|
|
|
|
while (!(state.bus.isFree(command.getStart())
|
|
&& satsfies_activateToActivate_differentBank(command)
|
|
&& satisfies_nActivateWindow(command)))
|
|
{
|
|
command.delayStart(config.Timings.clk);
|
|
}
|
|
|
|
}
|
|
|
|
void ActivateChecker::delay_to_satisfy_activateToActivate_sameBank(ScheduledCommand& command) const
|
|
{
|
|
ScheduledCommand lastActivateOnBank = state.getLastCommand(Command::Activate,
|
|
command.getBank());
|
|
if (lastActivateOnBank.isValidCommand())
|
|
{
|
|
command.delayToMeetConstraint(lastActivateOnBank.getStart(), config.Timings.tRC);
|
|
}
|
|
}
|
|
|
|
bool ActivateChecker::satsfies_activateToActivate_differentBank(ScheduledCommand& command) const
|
|
{
|
|
for (auto act : state.lastActivates)
|
|
{
|
|
sc_time time = act.first;
|
|
sc_time tRRD =
|
|
(command.getBankGroup() == act.second.getBankGroup()) ?
|
|
config.Timings.tRRD_L : config.Timings.tRRD_S;
|
|
|
|
if ((time < command.getStart() && command.getStart() - time < tRRD)
|
|
|| (command.getStart() <= time && time - command.getStart() < tRRD))
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
bool ActivateChecker::satisfies_nActivateWindow(ScheduledCommand& command) const
|
|
{
|
|
/*
|
|
* there may be activates scheduled in the future, so emplace
|
|
* command in a copied set (not necessarily the last in time),
|
|
* and check if the n-act constraint holds for the whole set.
|
|
*/
|
|
if (state.lastActivates.size() >= config.nActivate)
|
|
{
|
|
map<sc_time, Bank> lastActivates = state.lastActivates;
|
|
lastActivates.emplace(command.getStart(), command.getBank());
|
|
auto upper = lastActivates.begin();
|
|
advance(upper, config.nActivate);
|
|
auto lower = lastActivates.begin();
|
|
|
|
while (upper != lastActivates.end())
|
|
{
|
|
if (upper->first - lower->first < config.Timings.tNAW)
|
|
return false;
|
|
++upper;
|
|
++lower;
|
|
}
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
} /* namespace controller */
|