116 lines
3.4 KiB
C++
116 lines
3.4 KiB
C++
/*
|
|
* 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 */
|