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