Files
DRAMSys/dram/src/core/refresh/RefreshManager.cpp
2014-04-09 13:54:37 +02:00

109 lines
3.1 KiB
C++

/*
* RefreshManager.cpp
*
* Created on: Mar 29, 2014
* Author: robert
*/
#include "RefreshManager.h"
#include "../ControllerCore.h"
using namespace tlm;
namespace core {
RefreshManager::RefreshManager(ControllerCore& controller) :
controller(controller), timing(controller.config.Timings.refreshTimings.at(0)), nextPlannedRefresh(
SC_ZERO_TIME), refreshPayloads(controller.config.NumberOfBanks)
{
setupTransactions();
planNextRefresh();
}
RefreshManager::~RefreshManager()
{
}
bool RefreshManager::hasCollision(const CommandSchedule& schedule)
{
return !(schedule.getEnd() < nextPlannedRefresh);
}
void RefreshManager::scheduleRefresh(tlm::tlm_generic_payload& payload, sc_time time)
{
sc_assert(!isInvalidated(payload, time));
ScheduledCommand nextRefresh(Command::AutoRefresh, time, timing.tRFC,
DramExtension::getExtension(refreshPayloads.at(0)));
if (!controller.state.bankStates.allRowBuffersAreClosed())
{
ScheduledCommand precharge(Command::PrechargeAll, time, controller.config.Timings.tRP,
DramExtension::getExtension(refreshPayloads.at(0)));
controller.getCommandChecker(Command::PrechargeAll).delayToSatisfyConstraints(precharge);
nextRefresh.setStart(precharge.getEnd());
for (tlm::tlm_generic_payload& payload : refreshPayloads)
{
ScheduledCommand prechargeToSend(Command::PrechargeAll, precharge.getStart(),
controller.config.Timings.tRP, DramExtension::getExtension(payload));
controller.state.change(prechargeToSend);
controller.wrapper.send(prechargeToSend, payload);
}
}
else
{
//no precharge all
controller.state.bus.moveCommandToNextFreeSlot(nextRefresh);
}
for (tlm::tlm_generic_payload& payload : refreshPayloads)
{
Row currentrow = DramExtension::getExtension(payload).getRow();
DramExtension::getExtension(payload).setRow(Row((currentrow.ID()+1)%Configuration::getInstance().NumberOfBanks));
ScheduledCommand refreshToSend(Command::AutoRefresh, nextRefresh.getStart(), timing.tRFC,
DramExtension::getExtension(payload));
controller.state.change(refreshToSend);
controller.wrapper.send(refreshToSend, payload);
}
planNextRefresh();
}
void RefreshManager::planNextRefresh()
{
nextPlannedRefresh += timing.tREFI;
controller.wrapper.send(RefreshTrigger, nextPlannedRefresh, refreshPayloads.at(0));
}
void RefreshManager::reInitialize(tlm::tlm_generic_payload& payload, sc_time time)
{
nextPlannedRefresh = clkAlign(time, controller.config.Timings.clk, Alignment::DOWN);
planNextRefresh();
}
bool core::RefreshManager::isInvalidated(tlm::tlm_generic_payload& payload, sc_time time)
{
return nextPlannedRefresh > time;
}
void RefreshManager::setupTransactions()
{
for (Bank bank : controller.getBanks())
{
tlm_generic_payload& payload = refreshPayloads.at(bank.ID());
payload.set_address(getStartAddress(bank));
payload.set_command(tlm::TLM_READ_COMMAND);
payload.set_data_length(0);
payload.set_response_status(tlm::TLM_OK_RESPONSE);
payload.set_dmi_allowed(false);
payload.set_byte_enable_length(0);
payload.set_streaming_width(0);
payload.set_extension(new DramExtension(Thread(0), bank, Row(0), Column(0))); //payload takes ownership
}
}
} /* namespace core */