Files
DRAMSys/dram/src/core/scheduling/checker/ReadChecker.cpp
2014-04-14 03:01:11 +02:00

112 lines
3.8 KiB
C++

/*
* ReadChecker.cpp
*
* Created on: Mar 13, 2014
* Author: jonny
*/
#include "ReadChecker.h"
#include "../../TimingCalculation.h"
#include "../../../common/Utils.h"
#include "WriteChecker.h"
namespace core {
void ReadChecker::delayToSatisfyConstraints(ScheduledCommand& command) const
{
sc_assert(command.getCommand() == Command::Read || command.getCommand() == Command::ReadA);
delayToSatisfyDLL(command);
ScheduledCommand lastCommand = state.getLastScheduledCommand(command.getBank());
if (lastCommand.isValidCommand())
{
if (lastCommand.getCommand() == Command::Activate)
{
command.delayToMeetConstraint(lastCommand.getStart(), config.Timings.tRCD);
}
else if (lastCommand.getCommand() == Command::Read)
{
command.delayToMeetConstraint(lastCommand.getStart(), ReadChecker::readToRead(lastCommand,command));
}
else if (lastCommand.getCommand() == Command::Write)
{
command.delayToMeetConstraint(lastCommand.getStart(), ReadChecker::writeToRead(lastCommand, command));
}
else if (lastCommand.getCommand() == Command::PDNPX || lastCommand.getCommand() == Command::PDNAX)
{
command.delayToMeetConstraint(lastCommand.getStart(), config.Timings.tXP);
}
else
reportFatal("Read Checker", "Read can not follow " + commandToString(lastCommand.getCommand()));
}
while (!state.bus.isFree(command.getStart()) || collidesOnDataStrobe(command))
{
command.delayStart(config.Timings.clk);
}
}
bool ReadChecker::collidesOnDataStrobe(ScheduledCommand& read) const
{
for (ScheduledCommand& strobeCommand : state.lastDataStrobeCommands)
{
if (collidesWithStrobeCommand(read, strobeCommand))
return true;
}
return false;
}
bool ReadChecker::collidesWithStrobeCommand(ScheduledCommand& read, ScheduledCommand& strobeCommand) const
{
if (strobeCommand.getCommand() == Command::Read || strobeCommand.getCommand() == Command::ReadA)
{
return getDistance(read.getStart(),strobeCommand.getStart()) < ReadChecker::readToRead(strobeCommand,read);
}
else if (strobeCommand.getCommand() == Command::Write || strobeCommand.getCommand() == Command::WriteA)
{
if (strobeCommand.getStart() >= read.getStart())
return getDistance(read.getStart(), strobeCommand.getStart()) < WriteChecker::readToWrite(read,strobeCommand);
else
return getDistance(strobeCommand.getStart(), read.getStart()) < ReadChecker::writeToRead(strobeCommand, read);
}
else
{
reportFatal("Read Checker",
"Invalid strobeCommand in data strobe commands " + commandToString(strobeCommand.getCommand()));
return true;
}
}
void ReadChecker::delayToSatisfyDLL(ScheduledCommand& read) const
{
ScheduledCommand lastSREFX = state.getLastCommand(Command::SREFX, read.getBank());
if (lastSREFX.isValidCommand())
read.delayToMeetConstraint(lastSREFX.getStart(), config.Timings.tXSRDLL);
}
sc_time ReadChecker::readToRead(ScheduledCommand& firstRead, ScheduledCommand& secondRead)
{
sc_assert(firstRead.getCommand() == Command::Read || firstRead.getCommand() == Command::ReadA);
sc_assert(secondRead.getCommand() == Command::Read || secondRead.getCommand() == Command::ReadA);
TimingConfiguration& config = Configuration::getInstance().Timings;
sc_time tCCD = (firstRead.getBankGroup() == secondRead.getBankGroup()) ? config.tCCD_L : config.tCCD_S;
return max(tCCD, getReadAccessTime());
}
sc_time ReadChecker::writeToRead(ScheduledCommand& write, ScheduledCommand& read)
{
sc_assert(read.getCommand() == Command::Read || read.getCommand() == Command::ReadA);
sc_assert(write.getCommand() == Command::Write || write.getCommand() == Command::WriteA);
TimingConfiguration& config = Configuration::getInstance().Timings;
sc_time tWTR = (write.getBankGroup() == read.getBankGroup()) ? config.tWTR_L : config.tWTR_S;
return config.tWL + getWriteAccessTime() + tWTR;
}
} /* namespace controller */