/* * 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 */