/* * ReadChecker.cpp * * Created on: Mar 13, 2014 * Author: jonny */ #include "ReadChecker.h" #include "../../utils/Utils.h" namespace core { void ReadChecker::delayToSatisfyConstraints(ScheduledCommand& command) const { assert(command.getCommand() == Command::Read || command.getCommand() == Command::ReadA); ScheduledCommand lastCommandOnBank = state.getLastScheduledCommand(command.getBank()); if (lastCommandOnBank.isValidCommand()) { if (lastCommandOnBank.getCommand() == Command::Activate) { command.delayStart(getDelayToMeetConstraint(lastCommandOnBank.getEnd(),command.getStart(), SC_ZERO_TIME)); } else if (lastCommandOnBank.getCommand() == Command::Read || lastCommandOnBank.getCommand() == Command::Write) { } else reportFatal("Read Checker", "Read can not follow " + commandToString(lastCommandOnBank.getCommand())); } while (!state.bus.isFree(command.getStart()) || collidesOnDataStrobe(command)) { command.delayStart(config.Timings.clk); } } sc_time ReadChecker::getExecutionTime(const tlm::tlm_generic_payload& payload, Command command) const { assert(command == Command::Read || command == Command::ReadA); if (command == Command::Read) { return config.Timings.tRL + config.Timings.clk * payload.get_streaming_width(); } else { return config.Timings.tRL + config.Timings.clk * payload.get_streaming_width() + config.Timings.tRP; } } 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) { //read to read TimeInterval readOnStrobe = getIntervalOnDataStrobe(read, config.Timings); TimeInterval otherReadOnStrobe = getIntervalOnDataStrobe(strobeCommand, config.Timings); if (readOnStrobe.timeIsInInterval(otherReadOnStrobe.start)) { return !isClkAligned(otherReadOnStrobe.start - readOnStrobe.start, 2 * config.Timings.clk); } else if (otherReadOnStrobe.timeIsInInterval(readOnStrobe.start)) { return !isClkAligned(readOnStrobe.start - otherReadOnStrobe.start, 2 * config.Timings.clk); } else { return false; } } else if (strobeCommand.getCommand() == Command::Write || strobeCommand.getCommand() == Command::WriteA) { //read to write if (strobeCommand.getStart() >= read.getStart()) { return !(strobeCommand.getStart() >= getIntervalOnDataStrobe(read, config.Timings).end); } //write to read else { return !(read.getStart()>= getIntervalOnDataStrobe(strobeCommand, config.Timings).end + config.Timings.tWTR); } } else { reportFatal("Read Checker", "Invalid strobeCommand in data strobe commands " + commandToString(strobeCommand.getCommand())); return true; } } } /* namespace controller */