/* * controller.cpp * * Created on: Mar 5, 2014 * Author: jonny */ #include #include "Controller.h" #include "scheduling/checker/ActivateChecker.h" #include "scheduling/checker/PrechargeChecker.h" #include "scheduling/checker/ReadChecker.h" #include "scheduling/checker/WriteChecker.h" #include "refresh/RefreshManagerBankwise.h" #include "refresh/RefreshManager.h" namespace core { Controller::Controller(IWrapperConnector& wrapperConnector, TlmRecorder& recorder) : config(), state(config.numberOfBanks, config.nActivate), busChecker(config, state), wrapper( wrapperConnector), commandChecker(), recorder(recorder), savedState( config.numberOfBanks, config.nActivate), commandSequenceGenerator(state), commandSequenceScheduler( *this) { commandChecker[Command::Activate] = new ActivateChecker(config, state); commandChecker[Command::Precharge] = new PrechargeChecker(config, state); commandChecker[Command::Read] = new ReadChecker(config, state); commandChecker[Command::Write] = new WriteChecker(config, state); if(config.RefreshBankwise) refreshManager = new RefreshManagerBankwise(*this); else refreshManager = new RefreshManager(*this); } Controller::~Controller() { delete commandChecker[Command::Activate]; delete commandChecker[Command::Precharge]; delete commandChecker[Command::Read]; delete commandChecker[Command::Write]; delete refreshManager; } void Controller::saveState() { savedState = state; } void Controller::resetState() { state = savedState; } void Controller::scheduleRefresh(tlm::tlm_generic_payload& payload, sc_time time) { cleanUpBus(time); refreshManager->scheduleRefresh(payload, time); } bool Controller::schedule(sc_time start, tlm::tlm_generic_payload& payload) { cleanUpBus(start); start = clkAlign(start, config.Timings.clk); payload.set_streaming_width(config.burstlength); saveState(); CommandSequence sequence = commandSequenceGenerator.generateCommandSequence(payload); CommandSchedule schedule = commandSequenceScheduler.schedule(sequence, start, payload); if (refreshManager->hasCollision(schedule)) { resetState(); return false; } else { send(schedule); return true; } } bool Controller::isBusy(sc_time currentTime, Bank bank) { ScheduledCommand lastScheduledCommand = state.getLastCommand(bank); if (lastScheduledCommand.isNoCommand()) return false; else if (lastScheduledCommand.getCommand() == Command::Write || lastScheduledCommand.getCommand() == Command::Read) { return (currentTime < lastScheduledCommand.getStart()); } else if (lastScheduledCommand.getCommand() == Command::AutoRefresh) { return (currentTime < lastScheduledCommand.getEnd()); } else { SC_ASSERT_(false, "last command in command sequence was activate or precharge"); return false; } } void Controller::send(const CommandSchedule& schedule) const { for (const ScheduledCommand& cmd : schedule.getScheduledCommands()) { wrapper.send(cmd); } } void Controller::cleanUpBus(sc_time currentTime) { state.pendingBusCommands.erase(state.pendingBusCommands.begin(), state.pendingBusCommands.lower_bound(currentTime)); } } /* namespace controller */