Files
DRAMSys/dram/src/controller/core/ControllerCore.cpp
gernhard2 f11adf51dc Relocated the python scripts. They now live in the analyzer directory and are deployed to the output folder when building the analyzer.
Major change to simulation logic in dramSys: Commands in a transaction are now scheduled one at a time, instead of
scheduling a whole transaction at once. Since single commands (e.g. Pre or Act) are not that long, refreshes are allowed to be delayed
to allow a command to finsh. Consequently, the whole loop in the ControllerCore about trying to scheduleding a transaction and aborting it when
it collides with a refresh could be ommitted. Lastly, Fifo_Strict has been added, which is a Fifo Scheduler that forces the read and write transactions, even
between different banks to be executed in order. Fifo and FR_FCFS have been modified to fit into the new scheduling logic.
2015-02-16 08:21:27 +01:00

201 lines
6.6 KiB
C++

/*
* controller.cpp
*
* Created on: Mar 5, 2014
* Author: jonny
*/
#include <systemc.h>
#include "ControllerCore.h"
#include "scheduling/checker/ActivateChecker.h"
#include "scheduling/checker/PrechargeChecker.h"
#include "scheduling/checker/PrechargeAllChecker.h"
#include "scheduling/checker/ReadChecker.h"
#include "scheduling/checker/WriteChecker.h"
#include "scheduling/checker/RefreshChecker.h"
#include "scheduling/checker/PowerDownChecker.h"
#include "refresh/RefreshManagerBankwise.h"
#include "refresh/RefreshManager.h"
#include "../../common/dramExtension.h"
#include "../../common/Utils.h"
#include "TimingCalculation.h"
#include "powerdown/PowerDownManager.h"
#include "powerdown/PowerDownManagerTimeout.h"
#include "powerdown/PowerDownManagerBankwise.h"
#include "powerdown/NoPowerDown.h"
#include "../../common/DebugManager.h"
std::string ControllerCore::senderName = "Controller Core";
ControllerCore::ControllerCore(IController& wrapperConnector, std::map<Bank, int>& numberOfPayloads) :
config(Configuration::getInstance()), state(&config), controller(wrapperConnector), numberOfPayloads(
numberOfPayloads), commandChecker()
{
commandChecker[Command::Activate] = new ActivateChecker(config, state);
commandChecker[Command::Precharge] = new PrechargeChecker(config, state);
commandChecker[Command::PrechargeAll] = new PrechargeAllChecker(config, state);
commandChecker[Command::Read] = new ReadChecker(config, state);
commandChecker[Command::ReadA] = commandChecker[Command::Read];
commandChecker[Command::Write] = new WriteChecker(config, state);
commandChecker[Command::WriteA] = commandChecker[Command::Write];
commandChecker[Command::AutoRefresh] = new RefreshChecker(config, state);
commandChecker[Command::PDNA] = new PowerDownChecker(config, state);
commandChecker[Command::PDNP] = commandChecker[Command::PDNA];
commandChecker[Command::SREF] = commandChecker[Command::PDNA];
commandChecker[Command::PDNAX] = commandChecker[Command::PDNA];
commandChecker[Command::PDNPX] = commandChecker[Command::PDNA];
commandChecker[Command::SREFX] = commandChecker[Command::PDNA];
if (config.BankwiseLogic)
{
refreshManager = new RefreshManagerBankwise(*this);
powerDownManager = new PowerDownManagerBankwise(*this);
}
else
{
refreshManager = new RefreshManager(*this);
if(config.PowerDownMode == EPowerDownMode::Staggered)
{
powerDownManager = new PowerDownManager(*this);
}
else if(config.PowerDownMode == EPowerDownMode::TimeoutPDN || config.PowerDownMode == EPowerDownMode::TimeoutSREF)
{
powerDownManager = new PowerDownManagerTimeout(*this);
}
else if(config.PowerDownMode == EPowerDownMode::NoPowerDown)
{
powerDownManager = new NoPowerDown();
}
else
{
SC_REPORT_FATAL(0, "Unsupported powerdown mode in constructor of controller core");
}
}
}
ControllerCore::~ControllerCore()
{
delete commandChecker[Command::Activate];
delete commandChecker[Command::Precharge];
delete commandChecker[Command::Read];
delete commandChecker[Command::Write];
delete commandChecker[Command::AutoRefresh];
delete commandChecker[Command::PDNA];
delete refreshManager;
delete powerDownManager;
}
void ControllerCore::triggerRefresh(tlm::tlm_generic_payload& payload)
{
sc_time time = sc_time_stamp();
Bank bank = DramExtension::getExtension(payload).getBank();
state.cleanUp(time);
if (!refreshManager->isInvalidated(payload, time) && !powerDownManager->isInSelfRefresh(bank))
{
printDebugMessage("Triggering refresh on bank " + to_string(bank.ID()));
powerDownManager->wakeUpForRefresh(bank, time); //expects PDNA and PDNP to exit without delay
refreshManager->scheduleRefresh(payload, time);
}
}
void ControllerCore::scheduleRequest(Command command, tlm::tlm_generic_payload &payload)
{
sc_time start = clkAlign(sc_time_stamp());
state.cleanUp(start);
ScheduledCommand scheduledCommand = schedule(command, start, payload);
state.change(scheduledCommand);
controller.send(scheduledCommand, payload);
}
ScheduledCommand ControllerCore::schedule(Command command, sc_time start,
tlm::tlm_generic_payload& payload)
{
ControllerCore::printDebugMessage("Scheduling command " + commandToString(command) + " on " + DramExtension::getBank(payload).toString());
ICommandChecker& checker = getCommandChecker(command);
sc_time executionTime = getExecutionTime(command, payload);
ScheduledCommand scheduledCommand(command, start, executionTime, DramExtension::getExtension(payload));
checker.delayToSatisfyConstraints(scheduledCommand);
return scheduledCommand;
}
bool ControllerCore::bankIsBusy(Bank bank)
{
sc_time time = sc_time_stamp();
ScheduledCommand lastScheduledCommand = state.getLastScheduledCommand(bank);
if (lastScheduledCommand.isNoCommand())
return false;
else if (lastScheduledCommand.commandIsIn( { Command::Write, Command::Read }))
{
// Read and writes can overlap, so the bank should not be busy during a rd/wr
return (time < lastScheduledCommand.getStart());
}
else if (lastScheduledCommand.commandIsIn( { Command::WriteA, Command::ReadA, Command::Precharge, Command::PrechargeAll, Command::Activate }))
{
return (time < lastScheduledCommand.getEnd());
}
else if (lastScheduledCommand.getCommand() == Command::AutoRefresh)
{
return (time < lastScheduledCommand.getEnd());
}
else if (lastScheduledCommand.commandIsIn( { Command::SREFX, Command::PDNPX, Command::PDNAX, Command::SREF, Command::PDNP,
Command::PDNA }))
{
return false;
}
else
{
SC_REPORT_FATAL("Core", "Last command unkown");
return false;
}
}
const std::vector<Bank>& ControllerCore::getBanks()
{
static std::vector<Bank> banks;
if (banks.size() == 0)
{
for (unsigned int i = 0; i < config.memSpec.NumberOfBanks; i++)
{
banks.push_back(Bank(i));
}
}
return banks;
}
std::vector<Bank> ControllerCore::getFreeBanks()
{
std::vector<Bank> freeBanks;
for(Bank bank: getBanks())
{
if(!bankIsBusy(bank))
freeBanks.push_back(bank);
}
return freeBanks;
}
ICommandChecker& ControllerCore::getCommandChecker(Command command)
{
return *getElementFromMap(commandChecker, command);
}
void ControllerCore::printDebugMessage(string message)
{
DebugManager::getInstance().printDebugMessage(ControllerCore::senderName, message);
}