PowerDown Manager and Bankwise PowerDown

This commit is contained in:
Janik Schlemminger
2014-04-02 16:10:10 +02:00
parent e930002e5c
commit 9b49ca2d64
27 changed files with 757 additions and 102 deletions

View File

@@ -4,7 +4,7 @@
<extension point="org.eclipse.cdt.core.LanguageSettingsProvider">
<provider copy-of="extension" id="org.eclipse.cdt.ui.UserLanguageSettingsProvider"/>
<provider-reference id="org.eclipse.cdt.managedbuilder.core.MBSLanguageSettingsProvider" ref="shared-provider"/>
<provider class="org.eclipse.cdt.managedbuilder.language.settings.providers.GCCBuiltinSpecsDetector" console="false" env-hash="-64906255729110141" id="org.eclipse.cdt.managedbuilder.core.GCCBuiltinSpecsDetector" keep-relative-paths="false" name="CDT GCC Built-in Compiler Settings" parameter="${COMMAND} -E -P -v -dD &quot;${INPUTS}&quot; -std=c++11">
<provider class="org.eclipse.cdt.managedbuilder.language.settings.providers.GCCBuiltinSpecsDetector" console="false" env-hash="-2055719358" id="org.eclipse.cdt.managedbuilder.core.GCCBuiltinSpecsDetector" keep-relative-paths="false" name="CDT GCC Built-in Compiler Settings" parameter="${COMMAND} -E -P -v -dD &quot;${INPUTS}&quot; -std=c++11">
<language-scope id="org.eclipse.cdt.core.gcc"/>
<language-scope id="org.eclipse.cdt.core.g++"/>
</provider>

View File

@@ -31,6 +31,25 @@ std::string commandToString(Command command)
return "AUTO_REFRESH";
break;
case Command::PDNA:
return "PDNA";
break;
case Command::PDNAX:
return "PDNAX";
break;
case Command::PDNP:
return "PDNP";
break;
case Command::PDNPX:
return "PDNPX";
break;
case Command::SREF:
return "SREF";
break;
case Command::SREFX:
return "SREFX";
break;
default:
SC_REPORT_FATAL("command","commandToString was called with unknown command");
break;

View File

@@ -12,7 +12,7 @@
namespace core {
enum class Command {NOP, Precharge, PrechargeAll, Activate, Read, Write, ReadA, WriteA, AutoRefresh};
enum class Command {NOP, Precharge, PrechargeAll, Activate, Read, Write, ReadA, WriteA, AutoRefresh, PDNA, PDNAX, PDNP, PDNPX, SREF, SREFX};
std::string commandToString(Command command);
bool commandIsIn(Command command, std::vector<Command> commands);

View File

@@ -15,7 +15,7 @@ namespace core{
struct Configuration
{
Configuration(): numberOfBanks(8), burstlength(2), Timings(numberOfBanks), RefreshBankwise(true),
Configuration(): numberOfBanks(8), burstlength(2), Timings(numberOfBanks), RefreshBankwise(true),PowerDownBankwise(false),
nActivate(2)
{}
unsigned int numberOfBanks;
@@ -23,6 +23,7 @@ struct Configuration
TimingConfiguration Timings;
bool RefreshBankwise;
bool PowerDownBankwise;
unsigned int nActivate;
};

View File

@@ -13,6 +13,9 @@
#include "scheduling/checker/WriteChecker.h"
#include "refresh/RefreshManagerBankwise.h"
#include "refresh/RefreshManager.h"
#include "../common/dramExtension.h"
#include "powerdown/PowerDownManagerBankwise.h"
#include "powerdown/PowerDownManager.h"
namespace core {
@@ -27,9 +30,22 @@ Controller::Controller(IWrapperConnector& wrapperConnector, TlmRecorder& recorde
commandChecker[Command::Write] = new WriteChecker(config, state);
if (config.RefreshBankwise)
{
refreshManager = new RefreshManagerBankwise(*this);
}
else
{
refreshManager = new RefreshManager(*this);
}
if (config.PowerDownBankwise)
{
powerDownManager = new PowerDownManagerBankwise(*this);
}
else
{
powerDownManager = new PowerDownManager(*this);
}
}
Controller::~Controller()
@@ -39,6 +55,7 @@ Controller::~Controller()
delete commandChecker[Command::Read];
delete commandChecker[Command::Write];
delete refreshManager;
delete powerDownManager;
}
void Controller::saveState()
@@ -54,10 +71,25 @@ void Controller::resetState()
void Controller::scheduleRefresh(tlm::tlm_generic_payload& payload, sc_time time)
{
state.cleanUp(time);
refreshManager->scheduleRefresh(payload, time);
if (time > sc_time(16933400, SC_NS))
{
int i;
i = 5;
}
if (refreshManager->isInvalidated(payload, time))
return;
Bank bank = DramExtension::getExtension(payload).getBank();
if (!powerDownManager->isInSelfRefresh(bank))
{
powerDownManager->wakeUpForRefresh(bank, time);
refreshManager->scheduleRefresh(payload, time);
}
}
bool Controller::schedule(sc_time start, tlm::tlm_generic_payload& payload)
bool Controller::scheduleRequest(sc_time start, tlm::tlm_generic_payload& payload)
{
start = clkAlign(start, config.Timings.clk);
state.cleanUp(start);
@@ -80,19 +112,34 @@ bool Controller::schedule(sc_time start, tlm::tlm_generic_payload& payload)
}
}
bool Controller::isBusy(sc_time currentTime, Bank bank)
bool Controller::isBusy(sc_time time, Bank bank)
{
if(powerDownManager->isActive(bank))
{
powerDownManager->wakeUp(bank, time);
return true;
}
powerDownManager->wakeUp(bank, time);
ScheduledCommand lastScheduledCommand = state.getLastScheduledCommand(bank);
if (lastScheduledCommand.isNoCommand())
return false;
else if (lastScheduledCommand.getCommand() == Command::Write
|| lastScheduledCommand.getCommand() == Command::Read)
else if (lastScheduledCommand.isIn( { Command::Write, Command::Read }))
{
return (currentTime < lastScheduledCommand.getStart());
return (time < lastScheduledCommand.getStart());
}
else if (lastScheduledCommand.getCommand() == Command::AutoRefresh)
{
return (currentTime < lastScheduledCommand.getEnd());
return (time < lastScheduledCommand.getEnd());
}
else if (lastScheduledCommand.isIn( { Command::SREF, Command::PDNP, Command::PDNA }))
{
//powerDownManager->wakeUp(bank, time);
return true;
}
else if (lastScheduledCommand.isIn( { Command::SREFX, Command::PDNPX, Command::PDNAX }))
{
return false;
}
else
{

View File

@@ -12,7 +12,7 @@
#include <map>
#include "IWrapperConnector.h"
#include "Configuration.h"
#include "powerdown/PowerDownManager.h"
#include "powerdown/IPowerDownManager.h"
#include "refresh/IRefreshManager.h"
#include "scheduling/CommandSequenceGenerator.h"
#include "scheduling/checker/ICommandChecker.h"
@@ -27,7 +27,7 @@ public:
Controller(IWrapperConnector& wrapper, TlmRecorder& recorder);
virtual ~Controller() ;
bool schedule(sc_time currentTime, tlm::tlm_generic_payload& payload);
bool scheduleRequest(sc_time currentTime, tlm::tlm_generic_payload& payload);
bool isBusy(sc_time currentTime, Bank bank);
void scheduleRefresh(tlm::tlm_generic_payload& payload, sc_time time);
@@ -46,12 +46,12 @@ public:
std::map<Command, ICommandChecker*> commandChecker;
TlmRecorder& recorder;
IPowerDownManager* powerDownManager;
IRefreshManager* refreshManager;
private:
ControllerState savedState;
CommandSequenceGenerator commandSequenceGenerator;
CommandSequenceScheduler commandSequenceScheduler;
IRefreshManager* refreshManager;
//PowerDownManager powerDownManager;
void addCommandChecker(Command command, ICommandChecker* checker);
};

View File

@@ -43,6 +43,7 @@ const ScheduledCommand ControllerState::getLastScheduledCommand(Bank bank)
void ControllerState::change(const ScheduledCommand& scheduledCommand)
{
//TODO double check if slot free?
bus.blockSlot(scheduledCommand.getStart());
lastCommandsOnBus[scheduledCommand.getCommand()][scheduledCommand.getBank()] = scheduledCommand;

View File

@@ -22,18 +22,8 @@ Slots::~Slots()
void Slots::moveCommandToNextFreeSlot(ScheduledCommand& command)
{
sc_time newStart = command.getStart();
sc_assert(isClkAligned(newStart, clk));
std::set<sc_time>::iterator it = slotSet.begin();
while (it != slotSet.end() && *it <= newStart)
{
if (*it == newStart)
newStart += clk;
++it;
}
command.setStart(newStart);
while(!isFree(command.getStart()))
command.delayStart(clk);
}
void Slots::cleanUpSlots(sc_time time)

View File

@@ -9,6 +9,7 @@
#define TIMINGS_H_
#include <systemc.h>
#include <algorithm>
#include "utils/Utils.h"
namespace core{
@@ -31,11 +32,13 @@ struct TimingConfiguration
{
sc_time tRFC = 21*clk;
//sc_time tREFI = 100*clk;
sc_time tREFI = sc_time(15.6, SC_US); //TODO align
sc_time tREFI = clkAlign(sc_time(15.6, SC_US), clk); //TODO align
//tREFI = sc_time(301268, SC_NS);
refreshTimings.push_back(RefreshTiming(tRFC, tREFI));
}
refreshTimings.at(0).tREFI = clkAlign(sc_time(15.6 / 2, SC_US), clk);
refreshTimings.at(1).tREFI = clkAlign(sc_time(15.6 / 4, SC_US), clk);
tRP = 3*clk; //precharge-time (pre -> act same bank)
tRAS = 6*clk; //active-time (act -> pre same bank)
@@ -50,6 +53,8 @@ struct TimingConfiguration
tRR = 2*clk; //min read to read on same rank
tWW = 1*clk; //min write to write on same rank
tWTR = 3*clk;//write to read
tCKESR = clkAlign(max(3*clk, sc_time(15, SC_NS)), clk);
}
sc_time clk;
@@ -63,6 +68,8 @@ struct TimingConfiguration
sc_time tWL;
sc_time tWTR;
sc_time tCKESR;
sc_time tRR;
sc_time tWW;

View File

@@ -0,0 +1,36 @@
/*
* IPowerDownManager.h
*
* Created on: Mar 31, 2014
* Author: jonny
*/
#ifndef IPOWERDOWNMANAGER_H_
#define IPOWERDOWNMANAGER_H_
#include <systemc.h>
#include "../../common/dramExtension.h"
namespace core {
enum class PowerDownState
{
NoPowerDown, PDNActive, PDNPrecharge, PDNSelfRefresh
};
class IPowerDownManager
{
public:
virtual ~IPowerDownManager()
{
}
virtual void sleep(Bank bank, sc_time time) = 0;
virtual void wakeUp(Bank bank, sc_time time) = 0;
virtual void wakeUpForRefresh(Bank bank, sc_time time) = 0;
virtual bool isInSelfRefresh(Bank bank) = 0;
virtual bool isActive(Bank bank) = 0;
};
}/* namespace core */
#endif /* IPOWERDOWNMANAGER_H_ */

View File

@@ -1,22 +1,212 @@
/*
* PowerDownManager.cpp
*
* Created on: Mar 9, 2014
* Created on: Apr 1, 2014
* Author: jonny
*/
#include <algorithm>
#include "PowerDownManager.h"
#include "../Controller.h"
#include "../utils/Utils.h"
using namespace tlm;
namespace core {
PowerDownManager::PowerDownManager()
PowerDownManager::PowerDownManager(Controller& controller) :
controller(controller), powerDownPayloads(controller.state.bankStates.getNumberOfBanks()), canSleep(
controller.state.bankStates.getNumberOfBanks(), true)
{
// TODO Auto-generated constructor stub
setupPayloads();
init();
}
PowerDownManager::~PowerDownManager()
{
}
} /* namespace controller */
/*
* All Banks are precharged and in Precharge-PowerDown after starting the system
*/
void PowerDownManager::init()
{
for (Bank bank : controller.state.bankStates.getBanks())
{
ScheduledCommand pdn(Command::PDNP, SC_ZERO_TIME, SC_ZERO_TIME,
DramExtension::getExtension(powerDownPayloads.at(bank.ID())));
controller.state.change(pdn);
controller.wrapper.send(pdn, powerDownPayloads.at(bank.ID()));
powerDownState = PowerDownState::PDNPrecharge;
}
}
void PowerDownManager::sleep(Bank bank, sc_time time)
{
canSleep.at(bank.ID()) = true;
if (powerDownState == PowerDownState::NoPowerDown)
{
if (count(canSleep.begin(), canSleep.end(), false) == 0)
{
if (controller.state.bankStates.allRowBuffersAreClosed())
{
powerDownState = PowerDownState::PDNPrecharge;
}
else
{
powerDownState = PowerDownState::PDNActive;
}
sendBegin(time);
}
}
else
{
if (bank == controller.state.getLastCommand(Command::AutoRefresh).getBank())
{
if (powerDownState == PowerDownState::PDNSelfRefresh)
return;
if (powerDownState == PowerDownState::PDNPrecharge)
{
powerDownState = PowerDownState::PDNSelfRefresh;
}
else
{
if (controller.state.bankStates.allRowBuffersAreClosed())
{
powerDownState = PowerDownState::PDNPrecharge;
}
else
{
powerDownState = PowerDownState::PDNActive;
}
}
sendBegin(time);
}
}
}
void PowerDownManager::wakeUp(Bank bank, sc_time time)
{
canSleep.at(bank.ID()) = false;
if (powerDownState != PowerDownState::NoPowerDown)
{
sendEnd(time);
}
powerDownState = PowerDownState::NoPowerDown;
}
void PowerDownManager::wakeUpForRefresh(Bank bank, sc_time time)
{
//canSleep.at(bank.ID()) = false;
if (powerDownState != PowerDownState::NoPowerDown)
{
sendEnd(time);
}
}
bool PowerDownManager::isInSelfRefresh(Bank bank)
{
return powerDownState == PowerDownState::PDNSelfRefresh;
}
bool PowerDownManager::isActive(Bank bank)
{
return powerDownState != PowerDownState::NoPowerDown;
}
void PowerDownManager::sendBegin(sc_time time)
{
Command cmd(Command::NOP);
switch (powerDownState)
{
case PowerDownState::PDNActive:
cmd = Command::PDNA;
break;
case PowerDownState::PDNPrecharge:
cmd = Command::PDNP;
break;
case PowerDownState::PDNSelfRefresh:
cmd = Command::SREF;
break;
}
sc_assert(cmd != Command::NOP);
//time = clkAlign(time, controller.config.Timings.clk);
ScheduledCommand pdn(cmd, time, SC_ZERO_TIME,
DramExtension::getExtension(powerDownPayloads.at(0)));
controller.state.bus.moveCommandToNextFreeSlot(pdn);
for (tlm::tlm_generic_payload& payload : powerDownPayloads)
{
ScheduledCommand pdnToSend(cmd, pdn.getStart(), SC_ZERO_TIME,
DramExtension::getExtension(payload));
controller.state.change(pdnToSend);
controller.wrapper.send(pdnToSend, payload);
}
}
void PowerDownManager::sendEnd(sc_time time)
{
Command cmd(Command::NOP);
switch (powerDownState)
{
case PowerDownState::PDNActive:
cmd = Command::PDNAX;
break;
case PowerDownState::PDNPrecharge:
cmd = Command::PDNPX;
break;
case PowerDownState::PDNSelfRefresh:
time += getDelayToMeetConstraint(
controller.state.getLastCommand(Command::SREF).getStart(), time,
controller.config.Timings.tCKESR);
cmd = Command::SREFX;
break;
}
sc_assert(cmd != Command::NOP);
time = clkAlign(time, controller.config.Timings.clk);
ScheduledCommand pdn(cmd, time, SC_ZERO_TIME,
DramExtension::getExtension(powerDownPayloads.at(0)));
controller.state.bus.moveCommandToNextFreeSlot(pdn);
for (tlm::tlm_generic_payload& payload : powerDownPayloads)
{
ScheduledCommand pdnToSend(cmd, pdn.getStart(), SC_ZERO_TIME,
DramExtension::getExtension(payload));
controller.state.change(pdnToSend);
controller.wrapper.send(pdnToSend, payload);
}
}
void PowerDownManager::setupPayloads()
{
for (Bank bank : controller.state.bankStates.getBanks())
{
tlm_generic_payload& payload = powerDownPayloads.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 */

View File

@@ -1,22 +1,46 @@
/*
* PowerDownManager.h
*
* Created on: Mar 9, 2014
* Created on: Apr 1, 2014
* Author: jonny
*/
#ifndef POWERDOWNMANAGER_H_
#define POWERDOWNMANAGER_H_
#include "IPowerDownManager.h"
namespace core {
class PowerDownManager
class Controller;
class PowerDownManager : public IPowerDownManager
{
public:
PowerDownManager();
PowerDownManager(Controller& controller);
virtual ~PowerDownManager();
virtual void sleep(Bank bank, sc_time time) override;
virtual void wakeUp(Bank bank, sc_time time) override;
virtual void wakeUpForRefresh(Bank bank, sc_time time) override;
virtual bool isInSelfRefresh(Bank bank) override;
virtual bool isActive(Bank bank) override;
private:
Controller& controller;
std::vector<tlm::tlm_generic_payload> powerDownPayloads;
std::vector<bool> canSleep;
PowerDownState powerDownState;
void sendBegin(sc_time time);
void sendEnd(sc_time time);
void setupPayloads();
void init();
};
} /* namespace controller */
} /* namespace core */
#endif /* POWERDOWNMANAGER_H_ */

View File

@@ -0,0 +1,166 @@
/*
* PowerDownManager.cpp
*
* Created on: Mar 9, 2014
* Author: jonny
*/
#include "PowerDownManagerBankwise.h"
#include "../utils/Utils.h"
#include "../Controller.h"
using namespace tlm;
namespace core {
PowerDownManagerBankwise::PowerDownManagerBankwise(Controller& controller) :
controller(controller), powerDownStates(controller.state.bankStates.getNumberOfBanks(),
PowerDownState::NoPowerDown), powerDownPayloads(
controller.state.bankStates.getNumberOfBanks())
{
setupPayloads();
init();
}
PowerDownManagerBankwise::~PowerDownManagerBankwise()
{
}
/*
* All Banks are precharged and in Precharge-PowerDown after starting the system
*/
void PowerDownManagerBankwise::init()
{
for (Bank bank : controller.state.bankStates.getBanks())
{
ScheduledCommand pdn(Command::PDNP, SC_ZERO_TIME, SC_ZERO_TIME,
DramExtension::getExtension(powerDownPayloads.at(bank.ID())));
controller.state.change(pdn);
controller.wrapper.send(pdn, powerDownPayloads.at(bank.ID()));
powerDownStates.at(bank.ID()) = PowerDownState::PDNPrecharge;
}
}
bool PowerDownManagerBankwise::isActive(Bank bank)
{
return powerDownStates.at(bank.ID()) != PowerDownState::NoPowerDown;
}
bool PowerDownManagerBankwise::isInSelfRefresh(Bank bank)
{
return powerDownStates.at(bank.ID()) == PowerDownState::PDNSelfRefresh;
}
void PowerDownManagerBankwise::sleep(Bank bank, sc_time time)
{
if (powerDownStates.at(bank.ID()) == PowerDownState::PDNPrecharge)
{
powerDownStates.at(bank.ID()) = PowerDownState::PDNSelfRefresh;
}
else
{
if (controller.state.bankStates.rowBufferIsOpen(bank))
{
powerDownStates.at(bank.ID()) = PowerDownState::PDNActive;
}
else
{
powerDownStates.at(bank.ID()) = PowerDownState::PDNPrecharge;
}
}
sendBegin(bank, time);
}
void PowerDownManagerBankwise::wakeUp(Bank bank, sc_time time)
{
wakeUpForRefresh(bank, time);
powerDownStates.at(bank.ID()) = PowerDownState::NoPowerDown;
}
void PowerDownManagerBankwise::wakeUpForRefresh(Bank bank, sc_time time)
{
if(powerDownStates.at(bank.ID()) != PowerDownState::NoPowerDown)
{
sendEnd(bank, time);
}
}
void PowerDownManagerBankwise::sendBegin(Bank bank, sc_time time)
{
Command cmd(Command::NOP);
switch (powerDownStates.at(bank.ID()))
{
case PowerDownState::PDNActive:
cmd = Command::PDNA;
break;
case PowerDownState::PDNPrecharge:
cmd = Command::PDNP;
break;
case PowerDownState::PDNSelfRefresh:
cmd = Command::SREF;
break;
}
sc_assert(cmd != Command::NOP);
//time = clkAlign(time, controller.config.Timings.clk);
ScheduledCommand pdn(cmd, time, SC_ZERO_TIME,
DramExtension::getExtension(powerDownPayloads.at(bank.ID())));
controller.state.bus.moveCommandToNextFreeSlot(pdn);
controller.state.change(pdn);
controller.wrapper.send(pdn, powerDownPayloads.at(bank.ID()));
}
void PowerDownManagerBankwise::sendEnd(Bank bank, sc_time time)
{
Command cmd(Command::NOP);
switch (powerDownStates.at(bank.ID()))
{
case PowerDownState::PDNActive:
cmd = Command::PDNAX;
break;
case PowerDownState::PDNPrecharge:
cmd = Command::PDNPX;
break;
case PowerDownState::PDNSelfRefresh:
time += getDelayToMeetConstraint(
controller.state.getLastCommand(Command::SREF, bank).getStart(), time,
controller.config.Timings.tCKESR);
cmd = Command::SREFX;
break;
}
sc_assert(cmd != Command::NOP);
time = clkAlign(time, controller.config.Timings.clk);
ScheduledCommand pdn(cmd, time, SC_ZERO_TIME,
DramExtension::getExtension(powerDownPayloads.at(bank.ID())));
controller.state.bus.moveCommandToNextFreeSlot(pdn);
controller.state.change(pdn);
controller.wrapper.send(pdn, powerDownPayloads.at(bank.ID()));
}
void PowerDownManagerBankwise::setupPayloads()
{
for (Bank bank : controller.state.bankStates.getBanks())
{
tlm_generic_payload& payload = powerDownPayloads.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 */

View File

@@ -0,0 +1,44 @@
/*
* PowerDownManager.h
*
* Created on: Mar 9, 2014
* Author: jonny
*/
#ifndef POWERDOWNMANAGERBANKWISE_H_
#define POWERDOWNMANAGERBANKWISE_H_
#include <systemc.h>
#include "IPowerDownManager.h"
namespace core {
class Controller;
class PowerDownManagerBankwise : public IPowerDownManager
{
public:
PowerDownManagerBankwise(Controller& controller);
virtual ~PowerDownManagerBankwise();
virtual void sleep(Bank bank, sc_time time) override;
virtual void wakeUp(Bank bank, sc_time time) override;
virtual void wakeUpForRefresh(Bank bank, sc_time time) override;
virtual bool isInSelfRefresh(Bank bank) override;
virtual bool isActive(Bank bank) override;
private:
Controller& controller;
std::vector<PowerDownState> powerDownStates;
std::vector<tlm::tlm_generic_payload> powerDownPayloads;
void sendBegin(Bank bank, sc_time time);
void sendEnd(Bank bank, sc_time time);
void setupPayloads();
void init();
};
} /* namespace core */
#endif /* POWERDOWNMANAGERBANKWISE_H_ */

View File

@@ -12,6 +12,9 @@ public:
virtual ~IRefreshManager(){};
virtual bool hasCollision(const CommandSchedule& schedule) = 0;
virtual void scheduleRefresh(tlm::tlm_generic_payload& payload, sc_time time) = 0;
virtual void reInitialize(tlm::tlm_generic_payload& payload, sc_time time) = 0;
virtual bool isInvalidated(tlm::tlm_generic_payload& payload, sc_time time) = 0;
};
} // namespace core

View File

@@ -12,7 +12,7 @@ using namespace tlm;
namespace core {
RefreshManager::RefreshManager(Controller& controller) :
controller(controller), nextPlannedRefresh(SC_ZERO_TIME), timing(controller.config.Timings.refreshTimings.at(0)),
controller(controller), timing(controller.config.Timings.refreshTimings.at(0)), nextPlannedRefresh(SC_ZERO_TIME),
refreshPayloads(controller.state.bankStates.getNumberOfBanks())
{
setupTransactions();
@@ -42,22 +42,21 @@ void RefreshManager::scheduleRefresh(tlm::tlm_generic_payload& payload, sc_time
nextRefresh.setStart(precharge.getEnd());
controller.state.change(precharge);
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);
}
}
controller.state.change(nextRefresh);
for (tlm::tlm_generic_payload& payload : refreshPayloads)
{
ScheduledCommand refreshToSend(Command::AutoRefresh, nextRefresh.getStart(),
timing.tRFC, DramExtension::getExtension(payload));
controller.state.change(refreshToSend);
controller.wrapper.send(refreshToSend, payload);
}
@@ -71,6 +70,12 @@ void RefreshManager::planNextRefresh()
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();
}
void RefreshManager::setupTransactions()
{
for (Bank bank : controller.state.bankStates.getBanks())

View File

@@ -24,12 +24,15 @@ public:
bool hasCollision(const CommandSchedule& schedule) override;
void scheduleRefresh(tlm::tlm_generic_payload& payload, sc_time time) override;
void reInitialize(tlm::tlm_generic_payload& payload, sc_time time) override;
bool isInvalidated(tlm::tlm_generic_payload& payload, sc_time time) override {return false;}
private:
Controller& controller;
RefreshTiming& timing;
std::vector<tlm::tlm_generic_payload> refreshPayloads;
sc_time nextPlannedRefresh;
std::vector<tlm::tlm_generic_payload> refreshPayloads;
void planNextRefresh();
void setupTransactions();

View File

@@ -74,11 +74,20 @@ void RefreshManagerBankwise::RefreshManagerForBank::scheduleRefresh(sc_time time
if (time != nextPlannedRefresh)
return;
ScheduledCommand nextRefresh(Command::AutoRefresh, time, timing.tRFC, DramExtension::getExtension(refreshPayload));
if (time > sc_time(16933400, SC_NS))
{
int i;
i++;
}
ScheduledCommand nextRefresh(Command::AutoRefresh, time, timing.tRFC,
DramExtension::getExtension(refreshPayload));
if (controller.state.bankStates.rowBufferIsOpen(bank))
{
ScheduledCommand precharge(Command::Precharge, time, controller.config.Timings.tRP, DramExtension::getExtension(refreshPayload));
ScheduledCommand precharge(Command::Precharge, time, controller.config.Timings.tRP,
DramExtension::getExtension(refreshPayload));
controller.state.bus.moveCommandToNextFreeSlot(precharge);
nextRefresh.setStart(precharge.getEnd());
@@ -99,6 +108,18 @@ void RefreshManagerBankwise::RefreshManagerForBank::planNextRefresh()
controller.wrapper.send(RefreshTrigger, nextPlannedRefresh, refreshPayload);
}
void RefreshManagerBankwise::RefreshManagerForBank::reInitialize(tlm::tlm_generic_payload& payload,
sc_time time)
{
nextPlannedRefresh = clkAlign(time, controller.config.Timings.clk, Alignment::DOWN);
planNextRefresh();
}
bool RefreshManagerBankwise::RefreshManagerForBank::isInvalidated(sc_time time)
{
return nextPlannedRefresh > time;
}
void RefreshManagerBankwise::RefreshManagerForBank::setupTransaction()
{
refreshPayload.set_address(getStartAddress(bank));
@@ -111,4 +132,19 @@ void RefreshManagerBankwise::RefreshManagerForBank::setupTransaction()
refreshPayload.set_extension(new DramExtension(Thread(0), bank, Row(0), Column(0))); //payload takes ownership
}
} /* namespace controller */
void RefreshManagerBankwise::reInitialize(tlm::tlm_generic_payload& payload, sc_time time)
{
refreshManagerForBanks.at(DramExtension::getExtension(payload).getBank().ID())->reInitialize(
payload, time);
}
bool RefreshManagerBankwise::isInvalidated(tlm::tlm_generic_payload& payload, sc_time time)
{
RefreshManagerForBank& manager = *refreshManagerForBanks.at(
DramExtension::getExtension(payload).getBank().ID());
return manager.isInvalidated(time);
}
} /* namespace core */

View File

@@ -26,6 +26,10 @@ public:
virtual bool hasCollision(const CommandSchedule& schedule) override;
virtual void scheduleRefresh(tlm::tlm_generic_payload& payload, sc_time time) override;
void reInitialize(tlm::tlm_generic_payload& payload, sc_time time) override;
bool isInvalidated(tlm::tlm_generic_payload& payload,sc_time time) override;
private:
class RefreshManagerForBank
@@ -37,6 +41,9 @@ private:
bool hasCollision(const CommandSchedule& schedule);
void scheduleRefresh(sc_time time);
void reInitialize(tlm::tlm_generic_payload& payload, sc_time time);
bool isInvalidated(sc_time);
private:
Controller& controller;
RefreshTiming& timing;

View File

@@ -76,6 +76,10 @@ bool ScheduledCommand::operator ==(const ScheduledCommand& b) const
return b.command == command && b.start == start && b.executionTime == executionTime && b.end == end;
}
bool ScheduledCommand::isIn(std::vector<Command> commandSet) const
{
return commandIsIn(command, commandSet);
}
}

View File

@@ -44,13 +44,14 @@ public:
const Command getCommand() const;
const sc_time getExecutionTime() const;
Bank getBank() const;
Row getRow() const;
unsigned int getBurstLength();
bool operator ==(const ScheduledCommand& b) const;
bool isIn(std::vector<Command> commandSet) const;
private:
Command command;

View File

@@ -29,6 +29,10 @@ void ActivateChecker::delayToSatisfyConstraints(ScheduledCommand& command) const
{
command.setStart(lastCommandOnBank.getEnd());
}
}
else if (lastCommandOnBank.getCommand() == Command::SREFX ||lastCommandOnBank.getCommand() == Command::PDNPX||lastCommandOnBank.getCommand() == Command::PDNAX)
{
}
else
reportFatal("Activate Checker",

View File

@@ -27,6 +27,10 @@ void PrechargeChecker::delayToSatisfyConstraints(ScheduledCommand& command) cons
else if (lastCommand.getCommand() == Command::Write)
{
command.delayToMeetConstraint(lastCommand.getStart(), lastCommand.getExecutionTime());
}
else if (lastCommand.getCommand() == Command::PDNAX)
{
}
else
reportFatal("Precharge Checker",

View File

@@ -14,24 +14,28 @@ void ReadChecker::delayToSatisfyConstraints(ScheduledCommand& command) const
{
assert(command.getCommand() == Command::Read || command.getCommand() == Command::ReadA);
ScheduledCommand lastCommandOnBank = state.getLastScheduledCommand(command.getBank());
ScheduledCommand lastCommand = state.getLastScheduledCommand(command.getBank());
if (lastCommandOnBank.isValidCommand())
if (lastCommand.isValidCommand())
{
if (lastCommandOnBank.getCommand() == Command::Activate)
if (lastCommand.getCommand() == Command::Activate)
{
if (command.getStart() < lastCommandOnBank.getEnd())
if (command.getStart() < lastCommand.getEnd())
{
command.setStart(lastCommandOnBank.getEnd());
command.setStart(lastCommand.getEnd());
}
}
else if (lastCommandOnBank.getCommand() == Command::Read
|| lastCommandOnBank.getCommand() == Command::Write)
else if (lastCommand.getCommand() == Command::Read
|| lastCommand.getCommand() == Command::Write)
{
}
else if (lastCommand.getCommand() == Command::PDNAX)
{
}
else
reportFatal("Read Checker",
"Read can not follow " + commandToString(lastCommandOnBank.getCommand()));
"Read can not follow " + commandToString(lastCommand.getCommand()));
}
while (!state.bus.isFree(command.getStart()) || collidesOnDataStrobe(command))

View File

@@ -26,7 +26,7 @@ void WriteChecker::delayToSatisfyConstraints(ScheduledCommand& command) const
}
}
else if (lastCommand.getCommand() == Command::Read
|| lastCommand.getCommand() == Command::Write)
|| lastCommand.getCommand() == Command::Write || lastCommand.getCommand() == Command::PDNAX)
{
}
else

View File

@@ -39,19 +39,19 @@ public:
tlm_utils::simple_initiator_socket<ControllerWrapper, BUSWIDTH, tlm::tlm_base_protocol_types> iSocket;
tlm_utils::simple_target_socket<ControllerWrapper, BUSWIDTH, tlm::tlm_base_protocol_types> tSocket;
ControllerWrapper(sc_module_name name, TlmRecorder& recorder):
frontendPEQ(this, &ControllerWrapper::frontendPEQCallback), dramPEQ(
this, &ControllerWrapper::dramPEQCallback), controllerPEQ(this,
&ControllerWrapper::controllerPEQCallback), recorder(recorder), debugManager(DebugManager::getInstance())
ControllerWrapper(sc_module_name name, TlmRecorder& recorder) :
frontendPEQ(this, &ControllerWrapper::frontendPEQCallback), dramPEQ(this,
&ControllerWrapper::dramPEQCallback), controllerPEQ(this,
&ControllerWrapper::controllerPEQCallback), recorder(recorder), debugManager(
DebugManager::getInstance())
{
controller = new Controller(*this, recorder);
scheduler = new FR_FCFS(controller->getBankStates());
inputBufferDelay = controller->config.Timings.clk;
scheduler = new Fifo(controller->getBankStates());
inputBufferDelay = controller->config.Timings.clk;
iSocket.register_nb_transport_bw(this, &ControllerWrapper::nb_transport_bw);
tSocket.register_nb_transport_fw(this, &ControllerWrapper::nb_transport_fw);
for(Bank bank:controller->getBankStates().getBanks())
bankIsFreeForRequest[bank] = true;
payloadsInSystem = std::vector<int>(controller->config.numberOfBanks);
}
~ControllerWrapper()
@@ -60,35 +60,53 @@ public:
delete scheduler;
}
virtual void send(const ScheduledCommand& command,tlm_generic_payload& payload) override
virtual void send(const ScheduledCommand& command, tlm_generic_payload& payload) override
{
assert(command.getStart() >= sc_time_stamp());
switch (command.getCommand())
{
case Command::Read:
dramPEQ.notify(payload,BEGIN_RD, command.getStart() - sc_time_stamp());
dramPEQ.notify(payload,END_RD, command.getEnd() - sc_time_stamp());
dramPEQ.notify(payload, BEGIN_RD, command.getStart() - sc_time_stamp());
dramPEQ.notify(payload, END_RD, command.getEnd() - sc_time_stamp());
break;
case Command::Write:
dramPEQ.notify(payload,BEGIN_WR, command.getStart() - sc_time_stamp());
dramPEQ.notify(payload,END_WR, command.getEnd() - sc_time_stamp());
dramPEQ.notify(payload, BEGIN_WR, command.getStart() - sc_time_stamp());
dramPEQ.notify(payload, END_WR, command.getEnd() - sc_time_stamp());
break;
case Command::AutoRefresh:
dramPEQ.notify(payload,BEGIN_AUTO_REFRESH, command.getStart() - sc_time_stamp());
dramPEQ.notify(payload,END_AUTO_REFRESH, command.getEnd() - sc_time_stamp());
dramPEQ.notify(payload, BEGIN_AUTO_REFRESH, command.getStart() - sc_time_stamp());
dramPEQ.notify(payload, END_AUTO_REFRESH, command.getEnd() - sc_time_stamp());
break;
case Command::Activate:
dramPEQ.notify(payload,BEGIN_ACT, command.getStart() - sc_time_stamp());
dramPEQ.notify(payload,END_ACT, command.getEnd() - sc_time_stamp());
dramPEQ.notify(payload, BEGIN_ACT, command.getStart() - sc_time_stamp());
dramPEQ.notify(payload, END_ACT, command.getEnd() - sc_time_stamp());
break;
case Command::Precharge:
dramPEQ.notify(payload,BEGIN_PRE, command.getStart() - sc_time_stamp());
dramPEQ.notify(payload,END_PRE, command.getEnd() - sc_time_stamp());
dramPEQ.notify(payload, BEGIN_PRE, command.getStart() - sc_time_stamp());
dramPEQ.notify(payload, END_PRE, command.getEnd() - sc_time_stamp());
break;
case Command::PrechargeAll:
dramPEQ.notify(payload,BEGIN_PRE_ALL, command.getStart() - sc_time_stamp());
dramPEQ.notify(payload,END_PRE_ALL, command.getEnd() - sc_time_stamp());
dramPEQ.notify(payload, BEGIN_PRE_ALL, command.getStart() - sc_time_stamp());
dramPEQ.notify(payload, END_PRE_ALL, command.getEnd() - sc_time_stamp());
break;
case Command::PDNA:
dramPEQ.notify(payload, BEGIN_PDNA, command.getStart() - sc_time_stamp());
break;
case Command::PDNP:
dramPEQ.notify(payload, BEGIN_PDNP, command.getStart() - sc_time_stamp());
break;
case Command::SREF:
dramPEQ.notify(payload, BEGIN_SREF, command.getStart() - sc_time_stamp());
break;
case Command::PDNAX:
dramPEQ.notify(payload, END_PDNA, command.getStart() - sc_time_stamp());
break;
case Command::PDNPX:
dramPEQ.notify(payload, END_PDNP, command.getStart() - sc_time_stamp());
break;
case Command::SREFX:
dramPEQ.notify(payload, END_SREF, command.getStart() - sc_time_stamp());
break;
default:
SC_REPORT_FATAL(0, "unsupported command in controller wrapper");
@@ -102,12 +120,12 @@ public:
assert(time >= sc_time_stamp());
sc_time delay = time - sc_time_stamp();
controllerPEQ.notify(payload, REFRESH_TRIGGER, delay);
}
}
private:
Controller* controller;
Scheduler* scheduler;
map<Bank, bool> bankIsFreeForRequest;
std::vector<int> payloadsInSystem;
tlm_utils::peq_with_cb_and_phase<ControllerWrapper> frontendPEQ;
tlm_utils::peq_with_cb_and_phase<ControllerWrapper> dramPEQ;
@@ -121,31 +139,43 @@ private:
{
printDebugMessage("Transaction enters system");
Bank bank = DramExtension::getExtension(payload).getBank();
payloadsInSystem.at(bank.ID()) = payloadsInSystem.at(bank.ID()) + 1;
scheduler->schedule(&payload);
scheduleNextPayload(bank);
}
void scheduleNextPayload(Bank bank)
void payloadLeavesSystem(tlm_generic_payload& payload)
{
printDebugMessage("In trigger for bank " + to_string(bank.ID()));
if(controller->isBusy(sc_time_stamp(), bank))
return;
Bank bank = DramExtension::getExtension(payload).getBank();
payloadsInSystem.at(bank.ID()) = payloadsInSystem.at(bank.ID()) - 1;
int numberOfPayloadsOnBank = payloadsInSystem.at(bank.ID());
else if(scheduler->hasTransactionForBank(bank))
sc_assert(numberOfPayloadsOnBank >= 0);
if (numberOfPayloadsOnBank == 0)
{
tlm_generic_payload* nextTransaction = scheduler->getTransactionForBank(bank);
if(controller->schedule(sc_time_stamp(), *nextTransaction))
{
printDebugMessage("Next payload was scheduled by core");
scheduler->popTransactionForBank(bank);
}
controller->powerDownManager->sleep(bank, sc_time_stamp());
}
}
void payloadLeavesSystem(tlm_generic_payload& payload)
void scheduleNextPayload(Bank bank)
{
if (scheduler->hasTransactionForBank(bank))
{
printDebugMessage("Try to schedule next payload on bank " + to_string(bank.ID()));
if (controller->isBusy(sc_time_stamp(), bank))
return;
tlm_generic_payload* nextTransaction = scheduler->getTransactionForBank(bank);
if (controller->scheduleRequest(sc_time_stamp(), *nextTransaction))
{
scheduler->popTransactionForBank(bank);
printDebugMessage(
"Next payload was scheduled by core for bank " + to_string(bank.ID()));
}
printDebugMessage("End try to schedule next payload on bank " + to_string(bank.ID()));
}
}
tlm_sync_enum nb_transport_bw(tlm_generic_payload& payload, tlm_phase& phase, sc_time& bwDelay)
@@ -157,7 +187,7 @@ private:
tlm_sync_enum nb_transport_fw(tlm_generic_payload& payload, tlm_phase& phase, sc_time& fwDelay)
{
DramExtension::getExtension(payload);
recorder.recordPhase(payload,phase,sc_time_stamp());
recorder.recordPhase(payload, phase, sc_time_stamp());
if (phase == BEGIN_REQ)
{
@@ -191,20 +221,40 @@ private:
void dramPEQCallback(tlm_generic_payload& payload, const tlm_phase& phase)
{
recorder.recordPhase(payload, phase, sc_time_stamp());
recorder.recordPhase(payload, phase, sc_time_stamp());
if (phase == BEGIN_RD || phase == BEGIN_WR)
{
scheduleNextPayload(DramExtension::getExtension(payload).getBank());
sendToDram(payload, phase, SC_ZERO_TIME);
}
else if(phase == BEGIN_AUTO_REFRESH || phase == BEGIN_ACT
|| phase == BEGIN_PRE || phase == BEGIN_PRE_ALL)
else if (phase == BEGIN_AUTO_REFRESH || phase == BEGIN_ACT || phase == BEGIN_PRE
|| phase == BEGIN_PRE_ALL || phase == BEGIN_PDNA || phase == BEGIN_PDNP || phase == BEGIN_SREF)
{
sendToDram(payload, phase, SC_ZERO_TIME);
}
else if(phase == END_AUTO_REFRESH)
else if (phase == END_PDNA || phase == END_PDNP)
{
sendToDram(payload, phase, SC_ZERO_TIME);
scheduleNextPayload(DramExtension::getExtension(payload).getBank());
}
else if( phase == END_SREF)
{
sendToDram(payload, phase, SC_ZERO_TIME);
controller->refreshManager->reInitialize(payload, sc_time_stamp());
scheduleNextPayload(DramExtension::getExtension(payload).getBank());
}
else if (phase == END_AUTO_REFRESH)
{
if (controller->powerDownManager->isActive(
DramExtension::getExtension(payload).getBank()))
{
controller->powerDownManager->sleep(DramExtension::getExtension(payload).getBank(),
sc_time_stamp());
}
scheduleNextPayload(DramExtension::getExtension(payload).getBank());
}
else if (phase == END_RD || phase == END_WR)
@@ -220,7 +270,9 @@ private:
{
ostringstream oss;
oss << phase;
string str = string("dramPEQCallback queue in controller wrapper was triggered with unknown phase ") + oss.str();
string str = string(
"dramPEQCallback queue in controller wrapper was triggered with unknown phase ")
+ oss.str();
SC_REPORT_FATAL(0, str.c_str());
}
}
@@ -255,9 +307,16 @@ private:
void printDebugMessage(string message, Importance importance = Importance::Info)
{
debugManager.printDebugMessage(message,Sender::DramWrapper,importance);
debugManager.printDebugMessage(message, Sender::DramWrapper, importance);
}
void stop()
{
for(Bank bank : controller->state.bankStates.getBanks())
{
controller->powerDownManager->wakeUp(bank, sc_time_stamp());
}
}
};
#endif /* CONTROLLERWRAPPER_H_ */

View File

@@ -35,7 +35,7 @@ int sc_main(int argc, char **argv)
string resources = pathOfFile(argv[0]) + string("/../resources/");
xmlAddressDecoder::addressConfigURI = resources + string("configs/addressConfig.xml");
TlmRecorder recorder("tpr.tdb", resources + string("scripts/createTraceDB.sql"));
TracePlayer<> player("player", resources + string("traces/mediabench-fractal_32.stl"));
TracePlayer<> player("player", resources + string("traces/mediabench-adpcmdecode_32.stl"));
//TracePlayer<> player("player", resources + string("traces/mediabench-h263encode_32.stl"));
Dram<> dram("dram");
@@ -48,8 +48,8 @@ int sc_main(int argc, char **argv)
// DebugManager::getInstance().addToWhiteList(Sender::TraceRecorder);
// DebugManager::getInstance().addToWhiteList(Sender::TracePlayer);
//DebugManager::getInstance().addToWhiteList(Sender::DramWrapper);
//DebugManager::getInstance().addToWhiteList(Sender::DramController);
DebugManager::getInstance().addToWhiteList(Sender::DramWrapper);
DebugManager::getInstance().addToWhiteList(Sender::DramController);
cout << "Toplevel: simulation start" << std::endl;
clock_t begin = clock();
@@ -65,7 +65,7 @@ int sc_main(int argc, char **argv)
string runTestCommand = string("python ") + testingScript + string(" tpr.tdb");
//system(runTestCommand.c_str());
string run_tpr = "/home/robert/analyzer/build/traceAnalyzer tpr.tdb";
string run_tpr = "/home/jonny/git/analyzer/build-traceAnalyzer-Desktop-Debug/traceAnalyzer tpr.tdb";
system(run_tpr.c_str());
return 0;
}