/* * BankwiseRefreshManager.cpp * * Created on: Mar 9, 2014 * Author: jonny */ #include "RefreshManagerBankwise.h" #include "../Controller.h" #include "../utils/Utils.h" using namespace std; namespace core { RefreshManagerBankwise::RefreshManagerBankwise(Controller& controller) : controller(controller) { assert(!controller.config.Timings.refreshTimings.empty()); for (Bank bank : controller.state.bankStates.getBanks()) { refreshManagerForBanks.push_back(new RefreshManagerForBank(controller, bank)); } } RefreshManagerBankwise::~RefreshManagerBankwise() { for (RefreshManagerForBank* manager : refreshManagerForBanks) { delete manager; } } bool RefreshManagerBankwise::hasCollision(const CommandSchedule& schedule) { RefreshManagerForBank& manager = *refreshManagerForBanks.at(schedule.getBank().ID()); return manager.hasCollision(schedule); } void RefreshManagerBankwise::scheduleRefresh(tlm::tlm_generic_payload& payload, sc_time time) { RefreshManagerForBank& manager = *refreshManagerForBanks.at( DramExtension::getExtension(payload).getBank().ID()); manager.scheduleRefresh(time); } RefreshManagerBankwise::RefreshManagerForBank::RefreshManagerForBank(Controller& controller, Bank bank) : controller(controller), timing(controller.config.Timings.refreshTimings.at(bank.ID())), bank( bank), nextPlannedRefresh(SC_ZERO_TIME) { setupTransaction(); planNextRefresh(); } RefreshManagerBankwise::RefreshManagerForBank::~RefreshManagerForBank() { } /* * Checks for a scheduled CommandSequence, if there is a collision with the current planned, * not yet scheduled, refresh command. In case of a collision the manager schedules the refresh * (sends it out) and plans the next refresh. Afterwards the CommandSequence is re-scheduled * with the new controller state (earliest start time is the end of the just scheduled refresh). */ bool RefreshManagerBankwise::RefreshManagerForBank::hasCollision(const CommandSchedule& schedule) { return !(schedule.getEnd() < nextPlannedRefresh); } void RefreshManagerBankwise::RefreshManagerForBank::scheduleRefresh(sc_time time) { if (time != nextPlannedRefresh) return; ScheduledCommand nextRefresh(refreshPayload, Command::AutoRefresh, time, timing.tRFC); if (controller.state.bankStates.rowBufferIsOpen(bank)) { ScheduledCommand precharge(refreshPayload, Command::Precharge, time, controller.config.Timings.tRP); controller.state.bus.moveCommandToNextFreeSlot(precharge); nextRefresh.setStart(precharge.getEnd()); controller.state.change(precharge); controller.wrapper.send(precharge); } controller.state.bus.moveCommandToNextFreeSlot(nextRefresh); controller.state.change(nextRefresh); controller.wrapper.send(nextRefresh); planNextRefresh(); } void RefreshManagerBankwise::RefreshManagerForBank::planNextRefresh() { nextPlannedRefresh += timing.tREFI; controller.wrapper.send(RefreshTrigger, nextPlannedRefresh, refreshPayload); } void RefreshManagerBankwise::RefreshManagerForBank::setupTransaction() { refreshPayload.set_address(getStartAddress(bank)); refreshPayload.set_command(tlm::TLM_READ_COMMAND); refreshPayload.set_data_length(0); refreshPayload.set_response_status(tlm::TLM_OK_RESPONSE); refreshPayload.set_dmi_allowed(false); refreshPayload.set_byte_enable_length(0); refreshPayload.set_streaming_width(0); refreshPayload.set_extension(new DramExtension(Thread(0), bank, Row(0), Column(0))); //payload takes ownership } } /* namespace controller */