122 lines
3.2 KiB
C++
122 lines
3.2 KiB
C++
/*
|
|
* WriteChecker.cpp
|
|
*
|
|
* Created on: Mar 13, 2014
|
|
* Author: jonny
|
|
*/
|
|
|
|
#include "WriteChecker.h"
|
|
#include "../../utils/Utils.h"
|
|
#include "../../../common/Utils.h"
|
|
|
|
namespace core {
|
|
|
|
void WriteChecker::delayToSatisfyConstraints(ScheduledCommand& command) const
|
|
{
|
|
assert(command.getCommand() == Command::Write || command.getCommand() == Command::WriteA);
|
|
|
|
ScheduledCommand lastCommand = state.getLastScheduledCommand(command.getBank());
|
|
|
|
if (lastCommand.isValidCommand())
|
|
{
|
|
if (lastCommand.getCommand() == Command::Activate)
|
|
{
|
|
command.delayToMeetConstraint(lastCommand.getEnd(), SC_ZERO_TIME);
|
|
}
|
|
else if (lastCommand.getCommand() == Command::Read
|
|
|| lastCommand.getCommand() == Command::Write)
|
|
{
|
|
|
|
}
|
|
else if (lastCommand.getCommand() == Command::PDNAX)
|
|
{
|
|
command.delayToMeetConstraint(lastCommand.getEnd(), config.Timings.tXP);
|
|
}
|
|
else
|
|
reportFatal("Write Checker",
|
|
"Write can not follow " + commandToString(lastCommand.getCommand()));
|
|
}
|
|
|
|
while (!state.bus.isFree(command.getStart()) || collidesOnDataStrobe(command))
|
|
{
|
|
command.delayStart(config.Timings.clk);
|
|
}
|
|
}
|
|
|
|
sc_time WriteChecker::getExecutionTime(const tlm::tlm_generic_payload& payload,
|
|
Command command) const
|
|
{
|
|
assert(command == Command::Write || command == Command::WriteA);
|
|
|
|
sc_time lengthOnDataStrobe = getBurstLengthOnDataStrobe(payload.get_streaming_width());
|
|
if(Configuration::getInstance().DataRate == 1)
|
|
lengthOnDataStrobe -= Configuration::getInstance().Timings.clk;
|
|
|
|
|
|
if (command == Command::Write)
|
|
{
|
|
return config.Timings.tWL + lengthOnDataStrobe;
|
|
}
|
|
else
|
|
{
|
|
return config.Timings.tWL + lengthOnDataStrobe + config.Timings.tWR;
|
|
}
|
|
}
|
|
|
|
bool WriteChecker::collidesOnDataStrobe(ScheduledCommand& write) const
|
|
{
|
|
for (ScheduledCommand& strobeCommand : state.lastDataStrobeCommands)
|
|
{
|
|
if (collidesWithStrobeCommand(write, strobeCommand))
|
|
return true;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
bool WriteChecker::collidesWithStrobeCommand(ScheduledCommand& write,
|
|
ScheduledCommand& strobeCommand) const
|
|
{
|
|
//write to write
|
|
if (strobeCommand.getCommand() == Command::Write
|
|
|| strobeCommand.getCommand() == Command::WriteA)
|
|
{
|
|
bool collision = write.collidesOnDataStrobe(strobeCommand);
|
|
|
|
sc_time tCCD =
|
|
(getBankGroup(write.getBank()) == getBankGroup(strobeCommand.getBank())) ?
|
|
config.Timings.tCCD_L : config.Timings.tCCD_S;
|
|
bool casToCas = (getDistance(write.getStart(), strobeCommand.getStart()) < tCCD) ? true : false;
|
|
|
|
return collision || casToCas;
|
|
}
|
|
else if (strobeCommand.getCommand() == Command::Read
|
|
|| strobeCommand.getCommand() == Command::ReadA)
|
|
{
|
|
//write to read
|
|
if (strobeCommand.getStart() >= write.getStart())
|
|
{
|
|
sc_time tWTR =
|
|
(getBankGroup(write.getBank()) == getBankGroup(strobeCommand.getBank())) ?
|
|
config.Timings.tWTR_L : config.Timings.tWTR_S;
|
|
|
|
return strobeCommand.getStart()
|
|
< clkAlign(write.getIntervalOnDataStrobe().end, Alignment::DOWN) + tWTR;
|
|
}
|
|
//read to write
|
|
else
|
|
{
|
|
return write.getStart() < strobeCommand.getIntervalOnDataStrobe().end;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
reportFatal("Write Checker",
|
|
"Invalid strobeCommand in data strobe commands "
|
|
+ commandToString(strobeCommand.getCommand()));
|
|
return true;
|
|
}
|
|
}
|
|
|
|
} /* namespace controller */
|