refactored refresh manager and powerdown
This commit is contained in:
@@ -1,10 +1,10 @@
|
||||
<memspec>
|
||||
<memconfig>
|
||||
<parameter id="bankwiseLogic" type="bool" value="1" />
|
||||
<parameter id="bankwiseLogic" type="bool" value="0" />
|
||||
<parameter id="openPagePolicy" type="bool" value="1" />
|
||||
<parameter id="adaptiveOpenPagePolicy" type="bool" value="0" />
|
||||
<parameter id="refreshAwareScheduling" type="bool" value="0" />
|
||||
<parameter id="maxNrOfTransactionsInDram" type="uint" value="50" />
|
||||
<parameter id="maxNrOfTransactionsInDram" type="uint" value="1" />
|
||||
<parameter id="scheduler" type="string" value="FR_FCFS" />
|
||||
<parameter id="capsize" type="uint" value="5" />
|
||||
</memconfig>
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
#include <string>
|
||||
#include <tlm.h>
|
||||
#include <fstream>
|
||||
#include "dramExtension.h"
|
||||
|
||||
using namespace std;
|
||||
using namespace tinyxml2;
|
||||
@@ -139,3 +140,15 @@ string loadTextFileContents(string filename)
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
||||
void setUpDummy(tlm::tlm_generic_payload& payload, Bank& bank)
|
||||
{
|
||||
payload.set_address(bank.getStartAddress());
|
||||
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, bank.getBankGroup(), Row(0), Column(0))); //payload takes ownership
|
||||
}
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
#include <string>
|
||||
#include <ostream>
|
||||
#include <tlm.h>
|
||||
|
||||
#include "dramExtension.h"
|
||||
#include "third_party/tinyxml2.h"
|
||||
|
||||
template<typename Key, typename Val>
|
||||
@@ -49,4 +49,6 @@ std::string queryStringParameter(tinyxml2::XMLElement* node, std::string name);
|
||||
bool queryBoolParameter(tinyxml2::XMLElement* node, std::string name);
|
||||
double queryDoubleParameter(tinyxml2::XMLElement* node, std::string name);
|
||||
|
||||
void setUpDummy(tlm::tlm_generic_payload& payload, Bank& bank);
|
||||
|
||||
#endif /* UTILS_COMMON_H_ */
|
||||
|
||||
@@ -12,7 +12,10 @@ DramExtension& DramExtension::getExtension(const tlm_generic_payload *payload)
|
||||
{
|
||||
DramExtension *result = NULL;
|
||||
payload->get_extension(result);
|
||||
assert(result != NULL);
|
||||
if(result == NULL)
|
||||
{
|
||||
SC_REPORT_FATAL("DRAM Extension","Extension is null.");
|
||||
}
|
||||
return *result;
|
||||
}
|
||||
|
||||
@@ -36,7 +39,6 @@ bool operator <(const Thread& lhs, const Thread& rhs)
|
||||
return lhs.ID() < rhs.ID();
|
||||
}
|
||||
|
||||
|
||||
bool operator ==(const Channel& lhs, const Channel& rhs)
|
||||
{
|
||||
return lhs.ID() == rhs.ID();
|
||||
@@ -52,11 +54,12 @@ BankGroup Bank::getBankGroup()
|
||||
static std::map<Bank, BankGroup> bankgroups;
|
||||
if (bankgroups.size() == 0)
|
||||
{
|
||||
core::Configuration& config = core::Configuration::getInstance();
|
||||
SC_ASSERT_(config.NumberOfBanks % config.NumberOfBankGroups == 0, "Number of banks must be a multiple of number of bankgroups");
|
||||
|
||||
for (unsigned int bank = 0; bank < core::Configuration::getInstance().NumberOfBanks; bank++)
|
||||
for (unsigned int bank = 0; bank < config.NumberOfBanks; bank++)
|
||||
{
|
||||
unsigned int group = bank % core::Configuration::getInstance().NumberOfBankGroups;
|
||||
unsigned int group = bank % config.NumberOfBankGroups;
|
||||
bankgroups.insert(std::pair<Bank, BankGroup>(Bank(bank), BankGroup(group)));
|
||||
}
|
||||
}
|
||||
@@ -88,12 +91,17 @@ bool operator <(const Bank& lhs, const Bank& rhs)
|
||||
return lhs.ID() < rhs.ID();
|
||||
}
|
||||
|
||||
|
||||
const Row Row::NO_ROW;
|
||||
|
||||
const Row Row::operator ++()
|
||||
{
|
||||
id = (id + 1) % core::Configuration::getInstance().NumberOfRows;
|
||||
return *this;
|
||||
}
|
||||
|
||||
bool operator ==(const Row& lhs, const Row& rhs)
|
||||
{
|
||||
if(lhs.isNoRow != rhs.isNoRow)
|
||||
if (lhs.isNoRow != rhs.isNoRow)
|
||||
return false;
|
||||
return lhs.ID() == rhs.ID();
|
||||
}
|
||||
@@ -113,4 +121,53 @@ bool operator !=(const Column& lhs, const Column& rhs)
|
||||
return !(lhs == rhs);
|
||||
}
|
||||
|
||||
tlm_extension_base* DramExtension::clone() const
|
||||
{
|
||||
return new DramExtension(thread, bank, bankgroup, row, column, burstlength);
|
||||
}
|
||||
void DramExtension::copy_from(const tlm_extension_base& ext)
|
||||
{
|
||||
const DramExtension& cpyFrom = static_cast<const DramExtension&>(ext);
|
||||
thread = cpyFrom.thread;
|
||||
bank = cpyFrom.bank;
|
||||
bankgroup = cpyFrom.bankgroup;
|
||||
row = cpyFrom.row;
|
||||
column = cpyFrom.column;
|
||||
burstlength = cpyFrom.burstlength;
|
||||
}
|
||||
|
||||
const Thread& DramExtension::getThread() const
|
||||
{
|
||||
return thread;
|
||||
}
|
||||
const Channel& DramExtension::getChannel() const
|
||||
{
|
||||
return channel;
|
||||
}
|
||||
const Bank& DramExtension::getBank() const
|
||||
{
|
||||
return bank;
|
||||
}
|
||||
const BankGroup& DramExtension::getBankGroup() const
|
||||
{
|
||||
return bankgroup;
|
||||
}
|
||||
|
||||
const Row& DramExtension::getRow() const
|
||||
{
|
||||
return row;
|
||||
}
|
||||
|
||||
const Column& DramExtension::getColumn() const
|
||||
{
|
||||
return column;
|
||||
}
|
||||
const unsigned int DramExtension::getBurstlength() const
|
||||
{
|
||||
return burstlength;
|
||||
}
|
||||
|
||||
void DramExtension::increaseRow()
|
||||
{
|
||||
++row;
|
||||
}
|
||||
|
||||
@@ -98,6 +98,8 @@ public:
|
||||
{
|
||||
return id;
|
||||
}
|
||||
|
||||
const Row operator++();
|
||||
private:
|
||||
unsigned int id;
|
||||
bool isNoRow;
|
||||
@@ -157,71 +159,39 @@ public:
|
||||
thread(0), channel(0), bank(0), bankgroup(0), row(0), column(0), burstlength(0)
|
||||
{
|
||||
}
|
||||
DramExtension(const Thread& thread, const Bank& bank, const BankGroup& bankgroup,
|
||||
const Row& row, const Column& column, unsigned int burstlength = 0) :
|
||||
thread(thread), channel(0), bank(bank), bankgroup(bankgroup), row(row), column(column), burstlength(
|
||||
burstlength)
|
||||
DramExtension(const Thread& thread, const Bank& bank, const BankGroup& bankgroup, const Row& row, const Column& column,
|
||||
unsigned int burstlength = 0) :
|
||||
thread(thread), channel(0), bank(bank), bankgroup(bankgroup), row(row), column(column), burstlength(burstlength)
|
||||
{
|
||||
}
|
||||
DramExtension(const Thread& thread, const Channel& channel, const Bank& bank,
|
||||
const BankGroup& bankgroup, const Row& row, const Column& column,
|
||||
unsigned int burstlength = 0) :
|
||||
thread(thread), channel(channel), bank(bank), bankgroup(bankgroup), row(row), column(
|
||||
column), burstlength(burstlength)
|
||||
DramExtension(const Thread& thread, const Channel& channel, const Bank& bank, const BankGroup& bankgroup, const Row& row,
|
||||
const Column& column, unsigned int burstlength = 0) :
|
||||
thread(thread), channel(channel), bank(bank), bankgroup(bankgroup), row(row), column(column), burstlength(burstlength)
|
||||
{
|
||||
}
|
||||
|
||||
~DramExtension()
|
||||
{
|
||||
}
|
||||
virtual tlm_extension_base* clone() const
|
||||
{
|
||||
return new DramExtension(thread, bank, bankgroup, row, column, burstlength);
|
||||
}
|
||||
virtual void copy_from(const tlm_extension_base& ext)
|
||||
{
|
||||
const DramExtension& cpyFrom = static_cast<const DramExtension&>(ext);
|
||||
thread = cpyFrom.thread;
|
||||
bank = cpyFrom.bank;
|
||||
bankgroup = cpyFrom.bankgroup;
|
||||
row = cpyFrom.row;
|
||||
column = cpyFrom.column;
|
||||
burstlength = cpyFrom.burstlength;
|
||||
}
|
||||
|
||||
const Thread& getThread() const
|
||||
{
|
||||
return thread;
|
||||
}
|
||||
const Channel& getChannel() const
|
||||
{
|
||||
return channel;
|
||||
}
|
||||
const Bank& getBank() const
|
||||
{
|
||||
return bank;
|
||||
}
|
||||
const BankGroup& getBankGroup() const
|
||||
{
|
||||
return bankgroup;
|
||||
}
|
||||
const Row& getRow() const
|
||||
{
|
||||
return row;
|
||||
}
|
||||
const Column& getColumn() const
|
||||
{
|
||||
return column;
|
||||
}
|
||||
const unsigned int getBurstlength() const
|
||||
{
|
||||
return burstlength;
|
||||
}
|
||||
virtual tlm_extension_base* clone() const;
|
||||
virtual void copy_from(const tlm_extension_base& ext);
|
||||
|
||||
void setRow(const Row& row)
|
||||
{
|
||||
this->row = row;
|
||||
}
|
||||
const Thread& getThread() const;
|
||||
|
||||
const Channel& getChannel() const;
|
||||
|
||||
const Bank& getBank() const;
|
||||
|
||||
const BankGroup& getBankGroup() const;
|
||||
|
||||
const Row& getRow() const;
|
||||
|
||||
const Column& getColumn() const;
|
||||
|
||||
const unsigned int getBurstlength() const;
|
||||
|
||||
void increaseRow();
|
||||
|
||||
static DramExtension& getExtension(const tlm::tlm_generic_payload *payload);
|
||||
static DramExtension& getExtension(const tlm::tlm_generic_payload &payload);
|
||||
|
||||
@@ -12,23 +12,22 @@
|
||||
#include "scheduling/checker/PrechargeAllChecker.h"
|
||||
#include "scheduling/checker/ReadChecker.h"
|
||||
#include "scheduling/checker/WriteChecker.h"
|
||||
#include "scheduling/checker/RefreshChecker.h"
|
||||
#include "refresh/RefreshManagerBankwise.h"
|
||||
#include "refresh/RefreshManager.h"
|
||||
#include "../common/dramExtension.h"
|
||||
#include "../common/Utils.h"
|
||||
#include "powerdown/PowerDownManager.h"
|
||||
#include "powerdown/PowerDownManagerGrouped.h"
|
||||
#include "powerdown/PowerDownManagerBankwise.h"
|
||||
#include "../common/DebugManager.h"
|
||||
|
||||
namespace core {
|
||||
|
||||
std::string ControllerCore::senderName = "Controller Core";
|
||||
|
||||
ControllerCore::ControllerCore(IWrapperConnector& wrapperConnector,
|
||||
std::map<Bank, int>& numberOfPayloads) :
|
||||
ControllerCore::ControllerCore(IWrapperConnector& wrapperConnector, std::map<Bank, int>& numberOfPayloads) :
|
||||
config(Configuration::getInstance()), state(&config), wrapper(wrapperConnector), commandChecker(), numberOfPayloads(
|
||||
numberOfPayloads), savedState(&config), commandSequenceGenerator(state), commandSequenceScheduler(
|
||||
*this)
|
||||
numberOfPayloads), savedState(&config), commandSequenceGenerator(state), commandSequenceScheduler(*this)
|
||||
|
||||
{
|
||||
commandChecker[Command::Activate] = new ActivateChecker(config, state);
|
||||
@@ -39,15 +38,17 @@ ControllerCore::ControllerCore(IWrapperConnector& wrapperConnector,
|
||||
commandChecker[Command::Write] = new WriteChecker(config, state);
|
||||
commandChecker[Command::WriteA] = commandChecker[Command::Write];
|
||||
|
||||
commandChecker[Command::AutoRefresh] = new RefreshChecker(config, state);
|
||||
|
||||
if (config.BankwiseLogic)
|
||||
{
|
||||
refreshManager = new RefreshManagerBankwise(*this);
|
||||
powerDownManager = new PowerDownManager(*this);
|
||||
powerDownManager = new PowerDownManagerBankwise(*this);
|
||||
}
|
||||
else
|
||||
{
|
||||
refreshManager = new RefreshManager(*this);
|
||||
powerDownManager = new PowerDownManagerGrouped(*this);
|
||||
powerDownManager = new PowerDownManager(*this);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -57,6 +58,7 @@ ControllerCore::~ControllerCore()
|
||||
delete commandChecker[Command::Precharge];
|
||||
delete commandChecker[Command::Read];
|
||||
delete commandChecker[Command::Write];
|
||||
delete commandChecker[Command::AutoRefresh];
|
||||
delete refreshManager;
|
||||
delete powerDownManager;
|
||||
}
|
||||
@@ -78,32 +80,12 @@ void ControllerCore::triggerRefresh(tlm::tlm_generic_payload& payload, sc_time t
|
||||
|
||||
state.cleanUp(time);
|
||||
|
||||
if (refreshManager->isInvalidated(payload, time))
|
||||
return;
|
||||
|
||||
if (config.BankwiseLogic)
|
||||
if (!refreshManager->isInvalidated(payload, time) && !powerDownManager->isInSelfRefresh(bank))
|
||||
{
|
||||
if (!powerDownManager->isInSelfRefresh(bank))
|
||||
{
|
||||
printDebugMessage("Waking up bank " + to_string(bank.ID()) + " for refresh");
|
||||
powerDownManager->wakeUpForRefresh(bank, time); //expects PDNA and PDNP to exit without delay
|
||||
refreshManager->scheduleRefresh(payload, time);
|
||||
}
|
||||
printDebugMessage("Waking up bank " + to_string(bank.ID()) + " for refresh");
|
||||
powerDownManager->wakeUpForRefresh(bank, time); //expects PDNA and PDNP to exit without delay
|
||||
refreshManager->scheduleRefresh(payload, time);
|
||||
}
|
||||
else if (!config.BankwiseLogic)
|
||||
{
|
||||
if (!powerDownManager->allBanksInSelfRefresh())
|
||||
{
|
||||
printDebugMessage("Waking up all banks for refresh");
|
||||
powerDownManager->wakeUpAllForRefresh(time);
|
||||
refreshManager->scheduleRefresh(payload, time);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ControllerCore::triggerWakeUp(tlm::tlm_generic_payload& payload, sc_time time)
|
||||
{
|
||||
powerDownManager->wakeUp(DramExtension::getExtension(payload).getBank(), time);
|
||||
}
|
||||
|
||||
bool ControllerCore::scheduleRequest(sc_time start, tlm::tlm_generic_payload& payload)
|
||||
|
||||
@@ -47,7 +47,7 @@ public:
|
||||
ControllerState state;
|
||||
IWrapperConnector& wrapper;
|
||||
|
||||
PowerDownManager* powerDownManager;
|
||||
IPowerDownManager* powerDownManager;
|
||||
IRefreshManager* refreshManager;
|
||||
std::map<Bank,int>& numberOfPayloads;
|
||||
static std::string senderName;
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
|
||||
#include "ControllerState.h"
|
||||
#include <algorithm>
|
||||
#include "utils/Utils.h"
|
||||
#include "TimingCalculation.h"
|
||||
|
||||
namespace core {
|
||||
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
*/
|
||||
|
||||
#include "Slots.h"
|
||||
#include "utils/Utils.h"
|
||||
#include "TimingCalculation.h"
|
||||
|
||||
namespace core {
|
||||
|
||||
|
||||
130
dram/src/core/TimingCalculation.cpp
Normal file
130
dram/src/core/TimingCalculation.cpp
Normal file
@@ -0,0 +1,130 @@
|
||||
/*
|
||||
* Utils.cpp
|
||||
*
|
||||
* Created on: Mar 12, 2014
|
||||
* Author: jonny
|
||||
*/
|
||||
|
||||
#include "TimingCalculation.h"
|
||||
#include "configuration/TimingConfiguration.h"
|
||||
#include "ControllerCore.h"
|
||||
#include "../common/DebugManager.h"
|
||||
#include "configuration/Configuration.h"
|
||||
#include "../common/Utils.h"
|
||||
|
||||
namespace core {
|
||||
|
||||
|
||||
sc_time getDistance(sc_time a, sc_time b)
|
||||
{
|
||||
if (a > b)
|
||||
return a - b;
|
||||
else
|
||||
return b - a;
|
||||
}
|
||||
|
||||
sc_time getDelayToMeetConstraint(sc_time previous, sc_time start, sc_time constraint)
|
||||
{
|
||||
if (previous + constraint > start)
|
||||
return previous + constraint - start;
|
||||
else
|
||||
return SC_ZERO_TIME;
|
||||
}
|
||||
|
||||
const sc_time clkAlign(sc_time time, Alignment alignment)
|
||||
{
|
||||
sc_time clk = Configuration::getInstance().Timings.clk;
|
||||
if (alignment == UP)
|
||||
return ceil(time / clk) * clk;
|
||||
else
|
||||
return floor(time / clk) * clk;
|
||||
}
|
||||
|
||||
sc_time getExecutionTime(Command command,tlm::tlm_generic_payload& payload)
|
||||
{
|
||||
TimingConfiguration& config = Configuration::getInstance().Timings;
|
||||
|
||||
if(command == Command::Precharge || command == Command::PrechargeAll)
|
||||
{
|
||||
return config.tRP;
|
||||
}
|
||||
else if(command == Command::Activate)
|
||||
{
|
||||
return config.tRCD;
|
||||
}
|
||||
else if(command == Command::Read)
|
||||
{
|
||||
return config.tRL + getBurstLengthOnDataStrobe(payload.get_streaming_width());
|
||||
}
|
||||
else if(command == Command::ReadA)
|
||||
{
|
||||
return getBurstLengthOnDataStrobe(payload.get_streaming_width())
|
||||
+ max(config.tRP, config.tRL);
|
||||
}
|
||||
else if(command == Command::Write || command == Command::WriteA)
|
||||
{
|
||||
sc_time lengthOnDataStrobe = getBurstLengthOnDataStrobe(payload.get_streaming_width());
|
||||
if(Configuration::getInstance().DataRate == 1)
|
||||
lengthOnDataStrobe -= Configuration::getInstance().Timings.clk;
|
||||
|
||||
if (command == Command::Write)
|
||||
{
|
||||
return config.tWL + lengthOnDataStrobe;
|
||||
}
|
||||
else
|
||||
{
|
||||
return config.tWL + lengthOnDataStrobe + config.tWR;
|
||||
}
|
||||
}
|
||||
else if(command == Command::PrechargeAll)
|
||||
{
|
||||
return config.tRP;
|
||||
}
|
||||
else if(command == Command::AutoRefresh)
|
||||
{
|
||||
return getElementFromMap(config.refreshTimings, DramExtension::getExtension(payload).getBank()).tRFC;
|
||||
}
|
||||
else if(command == Command::PDNA || command == Command::PDNP)
|
||||
{
|
||||
assert(config.tCKE == config.clk * 3);
|
||||
return config.tCKE;
|
||||
}
|
||||
else if(command == Command::SREF)
|
||||
{
|
||||
return config.tCKESR;
|
||||
}
|
||||
else if(command == Command::PDNAX || command == Command::PDNPX || command == Command::SREFX)
|
||||
{
|
||||
return config.clk;
|
||||
}
|
||||
else
|
||||
{
|
||||
SC_REPORT_FATAL("getExecutionTime", "unkown command");
|
||||
return SC_ZERO_TIME;
|
||||
}
|
||||
}
|
||||
|
||||
bool isClkAligned(sc_time time, sc_time clk)
|
||||
{
|
||||
return !((time / clk) - ceil(time / clk));
|
||||
}
|
||||
|
||||
bool TimeInterval::timeIsInInterval(sc_time time)
|
||||
{
|
||||
return (start < time && time < end);
|
||||
}
|
||||
|
||||
bool TimeInterval::intersects(TimeInterval other)
|
||||
{
|
||||
return other.timeIsInInterval(this->start) || this->timeIsInInterval(other.start);
|
||||
}
|
||||
|
||||
sc_time getBurstLengthOnDataStrobe(unsigned int burstlength)
|
||||
{
|
||||
Configuration& config = Configuration::getInstance();
|
||||
sc_assert((burstlength / config.DataRate) > 0);
|
||||
|
||||
return config.Timings.clk * (burstlength / config.DataRate);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -10,11 +10,11 @@
|
||||
|
||||
#include <systemc.h>
|
||||
#include <tlm.h>
|
||||
#include "../../common/dramExtension.h"
|
||||
#include "../common/dramExtension.h"
|
||||
#include "Command.h"
|
||||
|
||||
namespace core
|
||||
{
|
||||
unsigned int getStartAddress(const Bank& bank);
|
||||
|
||||
sc_time getDistance(sc_time a, sc_time b);
|
||||
struct TimeInterval
|
||||
@@ -28,16 +28,14 @@ struct TimeInterval
|
||||
bool intersects(TimeInterval other);
|
||||
};
|
||||
|
||||
sc_time getExecutionTime(Command command, tlm::tlm_generic_payload& payload);
|
||||
sc_time getBurstLengthOnDataStrobe(unsigned int burstlength);
|
||||
|
||||
struct TimingConfiguration;
|
||||
sc_time getDelayToMeetConstraint(sc_time previous, sc_time start, sc_time constraint);
|
||||
|
||||
enum Alignment {UP, DOWN};
|
||||
const sc_time clkAlign(sc_time time, Alignment alignment = UP);
|
||||
bool isClkAligned(sc_time time, sc_time clk);
|
||||
|
||||
void setUpDummy(tlm::tlm_generic_payload& payload, Bank& bank);
|
||||
|
||||
};
|
||||
#endif /* UTILS_H_ */
|
||||
@@ -9,9 +9,8 @@
|
||||
#define TIMINGS_H_
|
||||
|
||||
#include <systemc.h>
|
||||
#include "../utils/Utils.h"
|
||||
#include <map>
|
||||
|
||||
#include "../../common/dramExtension.h"
|
||||
namespace core{
|
||||
|
||||
struct RefreshTiming
|
||||
|
||||
99
dram/src/core/powerdown/IPowerDownManager.h
Normal file
99
dram/src/core/powerdown/IPowerDownManager.h
Normal file
@@ -0,0 +1,99 @@
|
||||
/*
|
||||
* IPowerDownManager.h
|
||||
*
|
||||
* Created on: Apr 11, 2014
|
||||
* Author: jonny
|
||||
*/
|
||||
|
||||
#ifndef IPOWERDOWNMANAGER_H_
|
||||
#define IPOWERDOWNMANAGER_H_
|
||||
|
||||
#include <systemc>
|
||||
|
||||
namespace core {
|
||||
|
||||
enum class PowerDownState
|
||||
{
|
||||
Awake, AwakeForRefresh, 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;
|
||||
|
||||
protected:
|
||||
Command getSleepCommand(PowerDownState state);
|
||||
Command getWakeUpCommand(PowerDownState state);
|
||||
|
||||
};
|
||||
|
||||
inline Command IPowerDownManager::getSleepCommand(PowerDownState state)
|
||||
{
|
||||
Command cmd(Command::NOP);
|
||||
switch (state)
|
||||
{
|
||||
case PowerDownState::PDNActive:
|
||||
cmd = Command::PDNA;
|
||||
break;
|
||||
case PowerDownState::PDNPrecharge:
|
||||
cmd = Command::PDNP;
|
||||
break;
|
||||
case PowerDownState::PDNSelfRefresh:
|
||||
cmd = Command::SREF;
|
||||
break;
|
||||
default:
|
||||
SC_REPORT_FATAL("In PowerDownManager sendPowerdownBegin", "invalid powerDownState");
|
||||
}
|
||||
return cmd;
|
||||
}
|
||||
|
||||
inline Command IPowerDownManager::getWakeUpCommand(PowerDownState state)
|
||||
|
||||
{
|
||||
Command cmd(Command::NOP);
|
||||
switch (state)
|
||||
{
|
||||
case PowerDownState::PDNActive:
|
||||
cmd = Command::PDNAX;
|
||||
break;
|
||||
case PowerDownState::PDNPrecharge:
|
||||
cmd = Command::PDNPX;
|
||||
break;
|
||||
case PowerDownState::PDNSelfRefresh:
|
||||
cmd = Command::SREFX;
|
||||
break;
|
||||
default:
|
||||
SC_REPORT_FATAL("In PowerDownManager sendPowerdownEnd", "invalid powerDownState");
|
||||
}
|
||||
return cmd;
|
||||
}
|
||||
|
||||
inline std::string powerDownStateToString(PowerDownState powerDownState)
|
||||
{
|
||||
switch (powerDownState)
|
||||
{
|
||||
case PowerDownState::Awake:
|
||||
return "Awake";
|
||||
case PowerDownState::AwakeForRefresh:
|
||||
return "Awake for refresh";
|
||||
case PowerDownState::PDNActive:
|
||||
return "PDN Active";
|
||||
case PowerDownState::PDNPrecharge:
|
||||
return "PDN Precharged";
|
||||
case PowerDownState::PDNSelfRefresh:
|
||||
return "PDN Self refresh";
|
||||
default:
|
||||
return "unknown state";
|
||||
}
|
||||
}
|
||||
|
||||
} /* namespace core */
|
||||
|
||||
#endif /* IPOWERDOWNMANAGER_H_ */
|
||||
@@ -1,274 +1,174 @@
|
||||
/*
|
||||
* IPowerDownManager.cpp
|
||||
* PowerDownManager.cpp
|
||||
*
|
||||
* Created on: Apr 4, 2014
|
||||
* Created on: Apr 1, 2014
|
||||
* Author: jonny
|
||||
*/
|
||||
|
||||
#include <algorithm>
|
||||
#include <string>
|
||||
#include "PowerDownManager.h"
|
||||
#include "../ControllerCore.h"
|
||||
#include "../TimingCalculation.h"
|
||||
#include "../../common/DebugManager.h"
|
||||
#include <algorithm>
|
||||
#include "../../common/Utils.h"
|
||||
#include "../utils/Utils.h"
|
||||
|
||||
using namespace tlm;
|
||||
using namespace std;
|
||||
|
||||
namespace core {
|
||||
|
||||
std::string PowerDownManager::senderName = "pdn manager";
|
||||
PowerDownManager::PowerDownManager(ControllerCore& controller) :
|
||||
controller(controller)
|
||||
{
|
||||
init();
|
||||
powerDownState = PowerDownState::Awake;
|
||||
for (Bank bank : controller.getBanks())
|
||||
{
|
||||
setUpDummy(powerDownPayloads[bank], bank);
|
||||
}
|
||||
}
|
||||
|
||||
PowerDownManager::~PowerDownManager()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void PowerDownManager::sleep(Bank bank, sc_time time)
|
||||
{
|
||||
assert(canSleep(bank));
|
||||
if (!canSleep() || isInPowerDown())
|
||||
return;
|
||||
|
||||
PowerDownState state = getPowerDownState(bank);
|
||||
sc_time minTime = controller.config.Timings.tCKE;
|
||||
PowerDownState state = powerDownState;
|
||||
|
||||
if (state == PowerDownState::Awake) //coming from active
|
||||
{
|
||||
state = controller.state.bankStates.rowBufferIsOpen(bank) ? PowerDownState::PDNActive : PowerDownState::PDNPrecharge;
|
||||
state = controller.state.bankStates.allRowBuffersAreClosed() ? PowerDownState::PDNPrecharge : PowerDownState::PDNActive;
|
||||
|
||||
}
|
||||
else if (state == PowerDownState::AwakeForRefresh) //coming from refresh interrupting power down
|
||||
{
|
||||
sc_assert(!controller.state.bankStates.rowBufferIsOpen(bank));
|
||||
sc_assert(controller.state.bankStates.allRowBuffersAreClosed());
|
||||
|
||||
if (controller.state.getLastCommand(Command::PDNA, bank).getStart()
|
||||
> controller.state.getLastCommand(Command::PDNP, bank).getStart())
|
||||
if (controller.state.getLastCommand(Command::PDNA).getStart()
|
||||
>= controller.state.getLastCommand(Command::PDNP).getStart())
|
||||
state = PowerDownState::PDNPrecharge;
|
||||
else
|
||||
{
|
||||
state = PowerDownState::PDNSelfRefresh;
|
||||
minTime = controller.config.Timings.tCKESR;
|
||||
}
|
||||
}
|
||||
|
||||
ScheduledCommand pdn(getSleepCommand(state), time, minTime, DramExtension::getExtension(getPayload(bank)));
|
||||
ScheduledCommand pdn(IPowerDownManager::getSleepCommand(state), time,
|
||||
getExecutionTime(IPowerDownManager::getSleepCommand(state), powerDownPayloads[bank]),
|
||||
DramExtension::getExtension(powerDownPayloads[bank]));
|
||||
|
||||
controller.state.bus.moveCommandToNextFreeSlot(pdn);
|
||||
|
||||
//check if pdna or pdnp tcke collides with next refresh
|
||||
if (state != PowerDownState::PDNSelfRefresh && controller.refreshManager->hasCollision(pdn))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
setState(state, bank);
|
||||
sendPowerDownPayload(pdn);
|
||||
else
|
||||
{
|
||||
setState(state);
|
||||
sendPowerDownPayloads(pdn);
|
||||
}
|
||||
}
|
||||
|
||||
void PowerDownManager::wakeUp(Bank bank, sc_time time)
|
||||
{
|
||||
if (isAwakeForRefresh(bank))
|
||||
if (isAwakeForRefresh()) //Request enters system during Refresh
|
||||
{
|
||||
//Request enters system during Refresh (power down already waked up and payload sent)
|
||||
setState(PowerDownState::Awake, bank);
|
||||
setState(PowerDownState::Awake);
|
||||
}
|
||||
else if (isInPowerDown(bank))
|
||||
else if (isInPowerDown()) //Request wakes up power down
|
||||
{
|
||||
time = clkAlign(time);
|
||||
//Request wakes up power down
|
||||
sc_time start(SC_ZERO_TIME);
|
||||
|
||||
switch (getPowerDownState(bank))
|
||||
sc_time startOfExitCommand(SC_ZERO_TIME);
|
||||
switch (powerDownState)
|
||||
{
|
||||
case PowerDownState::PDNActive:
|
||||
start = max(time, controller.state.getLastCommand(Command::PDNA).getEnd());
|
||||
startOfExitCommand = max(time, controller.state.getLastCommand(Command::PDNA).getEnd());
|
||||
break;
|
||||
case PowerDownState::PDNPrecharge:
|
||||
start = max(time, controller.state.getLastCommand(Command::PDNP).getEnd());
|
||||
startOfExitCommand = max(time, controller.state.getLastCommand(Command::PDNP).getEnd());
|
||||
break;
|
||||
case PowerDownState::PDNSelfRefresh:
|
||||
start = max(time, controller.state.getLastCommand(Command::SREF).getEnd());
|
||||
controller.refreshManager->reInitialize(bank, start + controller.config.Timings.clk);
|
||||
startOfExitCommand = max(time, controller.state.getLastCommand(Command::SREF).getEnd());
|
||||
controller.refreshManager->reInitialize(bank,
|
||||
startOfExitCommand + getExecutionTime(Command::SREFX, powerDownPayloads[bank]));
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
Command cmd = IPowerDownManager::getWakeUpCommand(powerDownState);
|
||||
ScheduledCommand pdn(cmd, startOfExitCommand, getExecutionTime(cmd, powerDownPayloads[bank]),
|
||||
DramExtension::getExtension(powerDownPayloads[bank]));
|
||||
|
||||
|
||||
ScheduledCommand pdn(getWakeUpCommand(getPowerDownState(bank)), start, controller.config.Timings.clk,
|
||||
DramExtension::getExtension(getPayload(bank)));
|
||||
|
||||
setState(PowerDownState::Awake, bank);
|
||||
sendPowerDownPayload(pdn);
|
||||
|
||||
setState(PowerDownState::Awake);
|
||||
sendPowerDownPayloads(pdn);
|
||||
}
|
||||
}
|
||||
|
||||
void PowerDownManager::wakeUpForRefresh(Bank bank, sc_time time)
|
||||
{
|
||||
if (isInPowerDown(bank))
|
||||
if (isInPowerDown())
|
||||
{
|
||||
ScheduledCommand pdn(getWakeUpCommand(getPowerDownState(bank)), time, controller.config.Timings.clk,
|
||||
DramExtension::getExtension(getPayload(bank)));
|
||||
setState(PowerDownState::AwakeForRefresh, bank);
|
||||
sendPowerDownPayload(pdn);
|
||||
Command cmd = IPowerDownManager::getWakeUpCommand(powerDownState);
|
||||
ScheduledCommand pdn(cmd, time, getExecutionTime(cmd, powerDownPayloads[bank]),
|
||||
DramExtension::getExtension(powerDownPayloads[bank]));
|
||||
|
||||
setState(PowerDownState::AwakeForRefresh);
|
||||
sendPowerDownPayloads(pdn);
|
||||
}
|
||||
}
|
||||
|
||||
void PowerDownManager::wakeUpAllForRefresh(sc_time time)
|
||||
void PowerDownManager::sendPowerDownPayloads(ScheduledCommand& cmd)
|
||||
{
|
||||
controller.state.bus.moveCommandToNextFreeSlot(cmd);
|
||||
for (Bank bank : controller.getBanks())
|
||||
{
|
||||
wakeUpForRefresh(bank, time);
|
||||
tlm_generic_payload& payloadToSend = powerDownPayloads[bank];
|
||||
ScheduledCommand pdnToSend(cmd.getCommand(), cmd.getStart(), cmd.getExecutionTime(),
|
||||
DramExtension::getExtension(payloadToSend));
|
||||
controller.state.change(pdnToSend);
|
||||
controller.wrapper.send(pdnToSend, payloadToSend);
|
||||
}
|
||||
}
|
||||
|
||||
bool PowerDownManager::isInPowerDown(Bank bank)
|
||||
void PowerDownManager::setState(PowerDownState state)
|
||||
{
|
||||
return isIn(getPowerDownState(bank),
|
||||
{ PowerDownState::PDNActive, PowerDownState::PDNPrecharge, PowerDownState::PDNSelfRefresh });
|
||||
powerDownState = state;
|
||||
DebugManager::getInstance().printDebugMessage(PowerDownManagerBankwise::senderName,
|
||||
"Is now in state " + powerDownStateToString(powerDownState) + " on all banks");
|
||||
}
|
||||
|
||||
bool PowerDownManager::isInSelfRefresh(Bank bank)
|
||||
bool PowerDownManager::isInPowerDown()
|
||||
{
|
||||
return getPowerDownState(bank) == PowerDownState::PDNSelfRefresh;
|
||||
return (powerDownState == PowerDownState::PDNActive || powerDownState == PowerDownState::PDNPrecharge
|
||||
|| powerDownState == PowerDownState::PDNSelfRefresh);
|
||||
}
|
||||
|
||||
bool PowerDownManager::allBanksInSelfRefresh()
|
||||
bool PowerDownManager::canSleep()
|
||||
{
|
||||
for (Bank bank : controller.getBanks())
|
||||
{
|
||||
if (!isInSelfRefresh(bank))
|
||||
if (!controller.numberOfPayloads[bank] == 0)
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool PowerDownManager::isAwakeForRefresh(Bank bank)
|
||||
bool PowerDownManager::isInSelfRefresh(Bank bank)
|
||||
{
|
||||
return getPowerDownState(bank) == PowerDownState::AwakeForRefresh;
|
||||
return powerDownState == PowerDownState::PDNSelfRefresh;
|
||||
}
|
||||
|
||||
bool PowerDownManager::isAwake(Bank bank)
|
||||
bool PowerDownManager::isAwakeForRefresh()
|
||||
{
|
||||
return getPowerDownState(bank) == PowerDownState::Awake;
|
||||
return powerDownState == PowerDownState::AwakeForRefresh;
|
||||
}
|
||||
|
||||
void PowerDownManager::setState(PowerDownState state, Bank bank)
|
||||
{
|
||||
PowerDownState& bankstate = getPowerDownState(bank);
|
||||
bankstate = state;
|
||||
|
||||
string stateName;
|
||||
switch (bankstate)
|
||||
{
|
||||
case PowerDownState::Awake:
|
||||
stateName = "Awake";
|
||||
break;
|
||||
case PowerDownState::AwakeForRefresh:
|
||||
stateName = "Awake for refresh";
|
||||
break;
|
||||
case PowerDownState::PDNActive:
|
||||
stateName = "PDN Active";
|
||||
break;
|
||||
case PowerDownState::PDNPrecharge:
|
||||
stateName = "PDN Precharged";
|
||||
break;
|
||||
case PowerDownState::PDNSelfRefresh:
|
||||
stateName = "PDN Self refresh";
|
||||
break;
|
||||
default:
|
||||
stateName = "unknown state";
|
||||
break;
|
||||
}
|
||||
DebugManager::getInstance().printDebugMessage(PowerDownManager::senderName,
|
||||
"Is now in state " + stateName + " on Bank " + to_string(bank.ID()));
|
||||
}
|
||||
|
||||
Command PowerDownManager::getSleepCommand(PowerDownState state)
|
||||
{
|
||||
Command cmd(Command::NOP);
|
||||
switch (state)
|
||||
{
|
||||
case PowerDownState::PDNActive:
|
||||
cmd = Command::PDNA;
|
||||
break;
|
||||
case PowerDownState::PDNPrecharge:
|
||||
cmd = Command::PDNP;
|
||||
break;
|
||||
case PowerDownState::PDNSelfRefresh:
|
||||
cmd = Command::SREF;
|
||||
break;
|
||||
default:
|
||||
SC_REPORT_FATAL("In PowerDownManager sendPowerdownBegin", "invalid powerDownState");
|
||||
}
|
||||
return cmd;
|
||||
}
|
||||
|
||||
Command PowerDownManager::getWakeUpCommand(PowerDownState state)
|
||||
{
|
||||
Command cmd(Command::NOP);
|
||||
switch (state)
|
||||
{
|
||||
case PowerDownState::PDNActive:
|
||||
cmd = Command::PDNAX;
|
||||
break;
|
||||
case PowerDownState::PDNPrecharge:
|
||||
cmd = Command::PDNPX;
|
||||
break;
|
||||
case PowerDownState::PDNSelfRefresh:
|
||||
cmd = Command::SREFX;
|
||||
break;
|
||||
default:
|
||||
SC_REPORT_FATAL("In PowerDownManager sendPowerdownEnd", "invalid powerDownState");
|
||||
}
|
||||
return cmd;
|
||||
}
|
||||
|
||||
void PowerDownManager::sendPowerDownPayload(ScheduledCommand& pdn)
|
||||
{
|
||||
controller.state.bus.moveCommandToNextFreeSlot(pdn);
|
||||
controller.state.change(pdn);
|
||||
controller.wrapper.send(pdn, powerDownPayloads[pdn.getBank()]);
|
||||
}
|
||||
|
||||
PowerDownState& PowerDownManager::getPowerDownState(Bank bank)
|
||||
{
|
||||
if (powerDownStates.count(bank) == 0)
|
||||
{
|
||||
SC_REPORT_FATAL("Map", "Element not in map");
|
||||
}
|
||||
return powerDownStates.at(bank);
|
||||
}
|
||||
|
||||
bool PowerDownManager::canSleep(Bank bank)
|
||||
{
|
||||
if (powerDownStates.count(bank) == 0)
|
||||
{
|
||||
SC_REPORT_FATAL("Map", "Element not in map");
|
||||
}
|
||||
return controller.numberOfPayloads[bank] == 0;
|
||||
}
|
||||
|
||||
tlm::tlm_generic_payload& PowerDownManager::getPayload(Bank bank)
|
||||
{
|
||||
if (powerDownPayloads.count(bank) == 0)
|
||||
{
|
||||
SC_REPORT_FATAL("Map", "Element not in map");
|
||||
}
|
||||
return powerDownPayloads.at(bank);
|
||||
}
|
||||
|
||||
/*
|
||||
* All Banks are precharged and in Precharge-PowerDown after starting the system
|
||||
*/
|
||||
void PowerDownManager::init()
|
||||
{
|
||||
for (Bank bank : controller.getBanks())
|
||||
{
|
||||
tlm_generic_payload& payload = powerDownPayloads[bank];
|
||||
setUpDummy(payload, bank);
|
||||
|
||||
//send payload
|
||||
ScheduledCommand pdn(Command::PDNP, SC_ZERO_TIME, SC_ZERO_TIME, DramExtension::getExtension(payload));
|
||||
controller.state.change(pdn);
|
||||
controller.wrapper.send(pdn, payload);
|
||||
powerDownStates[bank] = PowerDownState::PDNPrecharge;
|
||||
}
|
||||
}
|
||||
|
||||
}/* namespace core */
|
||||
} /* namespace core */
|
||||
|
||||
|
||||
@@ -1,69 +1,43 @@
|
||||
/*
|
||||
* IPowerDownManager.h
|
||||
* PowerDownManagerGrouped.h
|
||||
*
|
||||
* Created on: Mar 31, 2014
|
||||
* Created on: Apr 1, 2014
|
||||
* Author: jonny
|
||||
*/
|
||||
|
||||
#ifndef IPOWERDOWNMANAGER_H_
|
||||
#define IPOWERDOWNMANAGER_H_
|
||||
#ifndef POWERDOWNMANAGER_H_
|
||||
#define POWERDOWNMANAGER_H_
|
||||
|
||||
#include <systemc.h>
|
||||
#include <tlm.h>
|
||||
#include <map>
|
||||
#include <string>
|
||||
#include "../Command.h"
|
||||
#include "../../common/dramExtension.h"
|
||||
#include "../scheduling/ScheduledCommand.h"
|
||||
#include "PowerDownManagerBankwise.h"
|
||||
|
||||
namespace core {
|
||||
|
||||
class ControllerCore;
|
||||
|
||||
enum class PowerDownState
|
||||
{
|
||||
Awake, AwakeForRefresh, PDNActive, PDNPrecharge, PDNSelfRefresh
|
||||
};
|
||||
|
||||
class PowerDownManager
|
||||
class PowerDownManager: public IPowerDownManager
|
||||
{
|
||||
public:
|
||||
PowerDownManager(ControllerCore& controller);
|
||||
virtual ~PowerDownManager()
|
||||
{
|
||||
}
|
||||
virtual void sleep(Bank bank, sc_time time);
|
||||
virtual void wakeUp(Bank bank, sc_time time);
|
||||
virtual void wakeUpForRefresh(Bank bank, sc_time time);
|
||||
virtual void wakeUpAllForRefresh(sc_time time);
|
||||
virtual ~PowerDownManager();
|
||||
|
||||
virtual bool isInSelfRefresh(Bank bank);
|
||||
virtual bool allBanksInSelfRefresh();
|
||||
virtual bool isInPowerDown(Bank bank);
|
||||
virtual bool isAwake(Bank bank);
|
||||
virtual bool isAwakeForRefresh(Bank bank);
|
||||
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;
|
||||
|
||||
static std::string senderName;
|
||||
protected:
|
||||
virtual bool isInSelfRefresh(Bank bank) override;
|
||||
private:
|
||||
PowerDownState powerDownState;
|
||||
void sendPowerDownPayloads(ScheduledCommand& cmd);
|
||||
|
||||
ControllerCore& controller;
|
||||
bool isInPowerDown();
|
||||
|
||||
void setState(PowerDownState state);
|
||||
bool canSleep();
|
||||
bool isAwakeForRefresh();
|
||||
std::map<Bank, tlm::tlm_generic_payload> powerDownPayloads;
|
||||
std::map<Bank, PowerDownState> powerDownStates;
|
||||
|
||||
virtual PowerDownState& getPowerDownState(Bank bank);
|
||||
virtual tlm::tlm_generic_payload& getPayload(Bank bank);
|
||||
virtual bool canSleep(Bank bank);
|
||||
|
||||
void setState(PowerDownState state, Bank bank);
|
||||
|
||||
Command getWakeUpCommand(PowerDownState state);
|
||||
Command getSleepCommand(PowerDownState state);
|
||||
|
||||
void sendPowerDownPayload(ScheduledCommand& pdn);
|
||||
|
||||
void init();
|
||||
ControllerCore& controller;
|
||||
};
|
||||
|
||||
}/* namespace core */
|
||||
} /* namespace core */
|
||||
|
||||
#endif /* IPOWERDOWNMANAGER_H_ */
|
||||
#endif /* POWERDOWNMANAGER_H_ */
|
||||
|
||||
161
dram/src/core/powerdown/PowerDownManagerBankwise.cpp
Normal file
161
dram/src/core/powerdown/PowerDownManagerBankwise.cpp
Normal file
@@ -0,0 +1,161 @@
|
||||
/*
|
||||
* IPowerDownManager.cpp
|
||||
*
|
||||
* Created on: Apr 4, 2014
|
||||
* Author: jonny
|
||||
*/
|
||||
|
||||
#include "PowerDownManager.h"
|
||||
#include "../ControllerCore.h"
|
||||
#include "../../common/Utils.h"
|
||||
#include "../TimingCalculation.h"
|
||||
|
||||
using namespace tlm;
|
||||
|
||||
namespace core {
|
||||
|
||||
std::string PowerDownManagerBankwise::senderName = "pdn manager";
|
||||
|
||||
PowerDownManagerBankwise::PowerDownManagerBankwise(ControllerCore& controller) :
|
||||
controller(controller)
|
||||
{
|
||||
for (Bank bank : controller.getBanks())
|
||||
{
|
||||
setUpDummy(powerDownPayloads[bank], bank);
|
||||
powerDownStates[bank] = PowerDownState::Awake;
|
||||
}
|
||||
}
|
||||
|
||||
void PowerDownManagerBankwise::sleep(Bank bank, sc_time time)
|
||||
{
|
||||
if (!canSleep(bank))
|
||||
return;
|
||||
|
||||
tlm_generic_payload& payload = powerDownPayloads[bank];
|
||||
sc_time minTime = getExecutionTime(Command::PDNA, payload);
|
||||
|
||||
PowerDownState state = powerDownStates[bank];
|
||||
if (state == PowerDownState::Awake) //coming from active
|
||||
{
|
||||
state = controller.state.bankStates.rowBufferIsOpen(bank) ? PowerDownState::PDNActive : PowerDownState::PDNPrecharge;
|
||||
}
|
||||
else if (state == PowerDownState::AwakeForRefresh) //coming from refresh interrupting power down
|
||||
{
|
||||
sc_assert(!controller.state.bankStates.rowBufferIsOpen(bank));
|
||||
|
||||
if (controller.state.getLastCommand(Command::PDNA, bank).getStart()
|
||||
>= controller.state.getLastCommand(Command::PDNP, bank).getStart())
|
||||
state = PowerDownState::PDNPrecharge;
|
||||
else
|
||||
{
|
||||
state = PowerDownState::PDNSelfRefresh;
|
||||
minTime = getExecutionTime(Command::SREF, payload);
|
||||
}
|
||||
}
|
||||
|
||||
ScheduledCommand pdn(IPowerDownManager::getSleepCommand(state), time, minTime, DramExtension::getExtension(payload));
|
||||
controller.state.bus.moveCommandToNextFreeSlot(pdn);
|
||||
|
||||
if (state != PowerDownState::PDNSelfRefresh && controller.refreshManager->hasCollision(pdn))
|
||||
{
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
setState(state, bank);
|
||||
sendPowerDownPayload(pdn);
|
||||
}
|
||||
}
|
||||
|
||||
void PowerDownManagerBankwise::wakeUp(Bank bank, sc_time time)
|
||||
{
|
||||
if (isAwakeForRefresh(bank))
|
||||
{
|
||||
setState(PowerDownState::Awake, bank);
|
||||
}
|
||||
else if (isInPowerDown(bank))
|
||||
{
|
||||
//Request wakes up power down
|
||||
sc_time startOfExitCommand(SC_ZERO_TIME);
|
||||
switch (powerDownStates[bank])
|
||||
{
|
||||
case PowerDownState::PDNActive:
|
||||
startOfExitCommand = max(time, controller.state.getLastCommand(Command::PDNA).getEnd());
|
||||
break;
|
||||
case PowerDownState::PDNPrecharge:
|
||||
startOfExitCommand = max(time, controller.state.getLastCommand(Command::PDNP).getEnd());
|
||||
break;
|
||||
case PowerDownState::PDNSelfRefresh:
|
||||
startOfExitCommand = max(time, controller.state.getLastCommand(Command::SREF).getEnd());
|
||||
controller.refreshManager->reInitialize(bank,
|
||||
startOfExitCommand + getExecutionTime(Command::SREFX, powerDownPayloads[bank]));
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
Command cmd = IPowerDownManager::getWakeUpCommand(powerDownStates[bank]);
|
||||
ScheduledCommand pdn(cmd, startOfExitCommand, getExecutionTime(cmd, powerDownPayloads[bank]),
|
||||
DramExtension::getExtension(powerDownPayloads[bank]));
|
||||
|
||||
setState(PowerDownState::Awake, bank);
|
||||
sendPowerDownPayload(pdn);
|
||||
}
|
||||
}
|
||||
|
||||
void PowerDownManagerBankwise::wakeUpForRefresh(Bank bank, sc_time time)
|
||||
{
|
||||
if (isInPowerDown(bank))
|
||||
{
|
||||
Command cmd = IPowerDownManager::getWakeUpCommand(powerDownStates[bank]);
|
||||
ScheduledCommand pdn(cmd, time, getExecutionTime(cmd, powerDownPayloads[bank]), DramExtension::getExtension(powerDownPayloads[bank]));
|
||||
|
||||
setState(PowerDownState::AwakeForRefresh, bank);
|
||||
sendPowerDownPayload(pdn);
|
||||
}
|
||||
}
|
||||
|
||||
bool PowerDownManagerBankwise::isInPowerDown(Bank bank)
|
||||
{
|
||||
return isIn(powerDownStates[bank],
|
||||
{ PowerDownState::PDNActive, PowerDownState::PDNPrecharge, PowerDownState::PDNSelfRefresh });
|
||||
}
|
||||
|
||||
bool PowerDownManagerBankwise::isInSelfRefresh(Bank bank)
|
||||
{
|
||||
return powerDownStates[bank] == PowerDownState::PDNSelfRefresh;
|
||||
}
|
||||
|
||||
bool PowerDownManagerBankwise::isAwakeForRefresh(Bank bank)
|
||||
{
|
||||
return powerDownStates[bank] == PowerDownState::AwakeForRefresh;
|
||||
}
|
||||
|
||||
bool PowerDownManagerBankwise::isAwake(Bank bank)
|
||||
{
|
||||
return powerDownStates[bank] == PowerDownState::Awake;
|
||||
}
|
||||
|
||||
void PowerDownManagerBankwise::setState(PowerDownState state, Bank bank)
|
||||
{
|
||||
PowerDownState& bankstate = powerDownStates[bank];
|
||||
bankstate = state;
|
||||
|
||||
DebugManager::getInstance().printDebugMessage(PowerDownManagerBankwise::senderName,
|
||||
"Is now in state " + powerDownStateToString(state) + " on Bank " + to_string(bank.ID()));
|
||||
}
|
||||
|
||||
void PowerDownManagerBankwise::sendPowerDownPayload(ScheduledCommand& pdn)
|
||||
{
|
||||
controller.state.bus.moveCommandToNextFreeSlot(pdn);
|
||||
controller.state.change(pdn);
|
||||
controller.wrapper.send(pdn, powerDownPayloads[pdn.getBank()]);
|
||||
}
|
||||
|
||||
bool PowerDownManagerBankwise::canSleep(Bank bank)
|
||||
{
|
||||
return controller.numberOfPayloads[bank] == 0;
|
||||
}
|
||||
|
||||
}/* namespace core */
|
||||
|
||||
59
dram/src/core/powerdown/PowerDownManagerBankwise.h
Normal file
59
dram/src/core/powerdown/PowerDownManagerBankwise.h
Normal file
@@ -0,0 +1,59 @@
|
||||
/*
|
||||
* PowerDownManagerBankwise.h
|
||||
*
|
||||
* Created on: Mar 31, 2014
|
||||
* Author: jonny
|
||||
*/
|
||||
|
||||
#ifndef POWERDOWNMANAGERBANKWISE_H_
|
||||
#define POWERDOWNMANAGERBANKWISE_H_
|
||||
|
||||
#include <systemc.h>
|
||||
#include <tlm.h>
|
||||
#include <map>
|
||||
#include <string>
|
||||
#include "../Command.h"
|
||||
#include "../../common/dramExtension.h"
|
||||
#include "../scheduling/ScheduledCommand.h"
|
||||
#include "IPowerDownManager.h"
|
||||
|
||||
namespace core {
|
||||
|
||||
class ControllerCore;
|
||||
|
||||
class PowerDownManagerBankwise: public IPowerDownManager
|
||||
{
|
||||
public:
|
||||
PowerDownManagerBankwise(ControllerCore& 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;
|
||||
|
||||
static std::string senderName;
|
||||
|
||||
private:
|
||||
virtual bool isInPowerDown(Bank bank);
|
||||
virtual bool isAwake(Bank bank);
|
||||
virtual bool isAwakeForRefresh(Bank bank);
|
||||
|
||||
ControllerCore& controller;
|
||||
std::map<Bank, tlm::tlm_generic_payload> powerDownPayloads;
|
||||
std::map<Bank, PowerDownState> powerDownStates;
|
||||
|
||||
virtual bool canSleep(Bank bank);
|
||||
|
||||
void setState(PowerDownState state, Bank bank);
|
||||
|
||||
Command getWakeUpCommand(PowerDownState state);
|
||||
Command getSleepCommand(PowerDownState state);
|
||||
|
||||
void sendPowerDownPayload(ScheduledCommand& pdn);
|
||||
};
|
||||
|
||||
}/* namespace core */
|
||||
|
||||
#endif /* POWERDOWNMANAGERBANKWISE_H_ */
|
||||
@@ -1,166 +0,0 @@
|
||||
/*
|
||||
* PowerDownManager.cpp
|
||||
*
|
||||
* Created on: Apr 1, 2014
|
||||
* Author: jonny
|
||||
*/
|
||||
|
||||
#include <algorithm>
|
||||
#include <string>
|
||||
#include "PowerDownManagerGrouped.h"
|
||||
#include "../ControllerCore.h"
|
||||
#include "../utils/Utils.h"
|
||||
#include "../../common/DebugManager.h"
|
||||
#include <algorithm>
|
||||
|
||||
using namespace tlm;
|
||||
using namespace std;
|
||||
|
||||
namespace core {
|
||||
|
||||
PowerDownManagerGrouped::~PowerDownManagerGrouped()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void PowerDownManagerGrouped::sleep(Bank bank, sc_time time)
|
||||
{
|
||||
//all banks can sleep and no pending refresh in system
|
||||
if (!canSleep() || (controller.state.getLastCommand(Command::AutoRefresh).getEnd() > time))
|
||||
return;
|
||||
|
||||
PowerDownState state = getPowerDownState();
|
||||
if (state == PowerDownState::Awake)//coming from active
|
||||
{
|
||||
if (controller.state.bankStates.allRowBuffersAreClosed())
|
||||
setState(PowerDownState::PDNPrecharge);
|
||||
else
|
||||
setState(PowerDownState::PDNActive);
|
||||
|
||||
sendPowerDownPayload(time, getSleepCommand(getPowerDownState()));
|
||||
}
|
||||
else if (state == PowerDownState::AwakeForRefresh)//coming from refresh interrupting power down
|
||||
{
|
||||
if(controller.state.bankStates.allRowBuffersAreClosed())
|
||||
{
|
||||
if (controller.state.getLastCommand(Command::PDNA).getStart()
|
||||
> controller.state.getLastCommand(Command::PDNP).getStart())
|
||||
setState(PowerDownState::PDNPrecharge);
|
||||
else
|
||||
setState(PowerDownState::PDNSelfRefresh);
|
||||
}
|
||||
else
|
||||
{
|
||||
setState(PowerDownState::PDNActive);
|
||||
}
|
||||
sendPowerDownPayload(time, getSleepCommand(getPowerDownState()));
|
||||
}
|
||||
}
|
||||
|
||||
void PowerDownManagerGrouped::wakeUp(Bank bank, sc_time time)
|
||||
{
|
||||
if (isAwakeForRefresh())//Request enters system during Refresh
|
||||
{
|
||||
//power down already waked up and payload sent
|
||||
setState(PowerDownState::Awake);
|
||||
}
|
||||
else if(isInPowerDown())//Request wakes up power down
|
||||
{
|
||||
sc_time delay(SC_ZERO_TIME);
|
||||
switch (getPowerDownState())
|
||||
{
|
||||
case PowerDownState::PDNActive:
|
||||
break;
|
||||
case PowerDownState::PDNPrecharge:
|
||||
break;
|
||||
case PowerDownState::PDNSelfRefresh:
|
||||
delay = getDelayToMeetConstraint(
|
||||
controller.state.getLastCommand(Command::SREF).getStart(), time,
|
||||
controller.config.Timings.tCKESR);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if (delay == SC_ZERO_TIME)
|
||||
{
|
||||
sendPowerDownPayload(time, getWakeUpCommand(getPowerDownState()));
|
||||
setState(PowerDownState::Awake);
|
||||
}
|
||||
else
|
||||
{
|
||||
tlm_generic_payload& p = getPayload(bank);
|
||||
controller.wrapper.send(WakeUpTrigger, time + delay, p);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void PowerDownManagerGrouped::wakeUpForRefresh(Bank bank, sc_time time)
|
||||
{
|
||||
wakeUpAllForRefresh(time);
|
||||
}
|
||||
|
||||
void PowerDownManagerGrouped::wakeUpAllForRefresh(sc_time time)
|
||||
{
|
||||
if(isInPowerDown())
|
||||
{
|
||||
sendPowerDownPayload(time, getWakeUpCommand(getPowerDownState()));
|
||||
setState(PowerDownState::AwakeForRefresh);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void PowerDownManagerGrouped::sendPowerDownPayload(sc_time time, Command cmd)
|
||||
{
|
||||
time = clkAlign(time);
|
||||
|
||||
//just to find slot
|
||||
tlm_generic_payload& payload = getPayload(Bank(0));
|
||||
ScheduledCommand pdn(cmd, time, controller.config.Timings.clk, DramExtension::getExtension(payload));
|
||||
controller.state.bus.moveCommandToNextFreeSlot(pdn);
|
||||
|
||||
|
||||
for (Bank bank : controller.getBanks())
|
||||
{
|
||||
tlm_generic_payload& payloadToSend = getPayload(bank);
|
||||
ScheduledCommand pdnToSend(cmd, pdn.getStart(), controller.config.Timings.clk, DramExtension::getExtension(payloadToSend));
|
||||
controller.state.change(pdnToSend);
|
||||
controller.wrapper.send(pdnToSend, payloadToSend);
|
||||
}
|
||||
}
|
||||
|
||||
void PowerDownManagerGrouped::setState(PowerDownState state)
|
||||
{
|
||||
for (Bank bank : controller.getBanks())
|
||||
{
|
||||
PowerDownManager::setState(state, bank);
|
||||
}
|
||||
}
|
||||
|
||||
bool PowerDownManagerGrouped::isInPowerDown()
|
||||
{
|
||||
return PowerDownManager::isInPowerDown(Bank(0));
|
||||
}
|
||||
|
||||
bool PowerDownManagerGrouped::canSleep()
|
||||
{
|
||||
for (Bank bank : controller.getBanks())
|
||||
{
|
||||
if (!PowerDownManager::canSleep(bank))
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
PowerDownState PowerDownManagerGrouped::getPowerDownState()
|
||||
{
|
||||
return PowerDownManager::getPowerDownState(Bank(0));
|
||||
}
|
||||
|
||||
bool PowerDownManagerGrouped::isAwakeForRefresh()
|
||||
{
|
||||
return PowerDownManager::isAwakeForRefresh(Bank(0));
|
||||
}
|
||||
|
||||
} /* namespace core */
|
||||
|
||||
@@ -1,47 +0,0 @@
|
||||
/*
|
||||
* PowerDownManagerGrouped.h
|
||||
*
|
||||
* Created on: Apr 1, 2014
|
||||
* Author: jonny
|
||||
*/
|
||||
|
||||
#ifndef POWERDOWNMANAGER_H_
|
||||
#define POWERDOWNMANAGER_H_
|
||||
|
||||
#include "PowerDownManager.h"
|
||||
|
||||
namespace core {
|
||||
|
||||
class ControllerCore;
|
||||
|
||||
class PowerDownManagerGrouped: public PowerDownManager
|
||||
{
|
||||
public:
|
||||
using PowerDownManager::PowerDownManager;
|
||||
virtual ~PowerDownManagerGrouped();
|
||||
|
||||
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 void wakeUpAllForRefresh(sc_time time) override;
|
||||
|
||||
//virtual bool isInSelfRefresh(Bank bank) override;
|
||||
//virtual bool isAwakeForRefresh(Bank bank) override;
|
||||
|
||||
private:
|
||||
|
||||
void sendPowerDownPayload(sc_time time, Command cmd);
|
||||
|
||||
void setState(PowerDownState state);
|
||||
|
||||
bool isInPowerDown();
|
||||
bool canSleep();
|
||||
PowerDownState getPowerDownState();
|
||||
bool isAwakeForRefresh();
|
||||
|
||||
|
||||
};
|
||||
|
||||
} /* namespace core */
|
||||
|
||||
#endif /* POWERDOWNMANAGER_H_ */
|
||||
@@ -7,14 +7,15 @@
|
||||
|
||||
#include "RefreshManager.h"
|
||||
#include "../ControllerCore.h"
|
||||
#include "../utils/Utils.h"
|
||||
#include "../TimingCalculation.h"
|
||||
#include "../../common/Utils.h"
|
||||
#include "../TimingCalculation.h"
|
||||
|
||||
using namespace tlm;
|
||||
namespace core {
|
||||
|
||||
RefreshManager::RefreshManager(ControllerCore& controller) :
|
||||
controller(controller), timing(controller.config.Timings.refreshTimings[Bank(0)]), nextPlannedRefresh(
|
||||
SC_ZERO_TIME)
|
||||
controller(controller), timing(controller.config.Timings.refreshTimings[Bank(0)]), nextPlannedRefresh(SC_ZERO_TIME)
|
||||
{
|
||||
setupTransactions();
|
||||
planNextRefresh();
|
||||
@@ -26,12 +27,12 @@ RefreshManager::~RefreshManager()
|
||||
|
||||
bool RefreshManager::hasCollision(const CommandSchedule& schedule)
|
||||
{
|
||||
return !(schedule.getEnd() < nextPlannedRefresh);
|
||||
return schedule.getEnd() > nextPlannedRefresh;
|
||||
}
|
||||
|
||||
bool RefreshManager::hasCollision(const ScheduledCommand& command)
|
||||
{
|
||||
return !(command.getEnd() < nextPlannedRefresh);
|
||||
return command.getEnd() > nextPlannedRefresh;
|
||||
}
|
||||
|
||||
void RefreshManager::scheduleRefresh(tlm::tlm_generic_payload& payload, sc_time time)
|
||||
@@ -40,41 +41,37 @@ void RefreshManager::scheduleRefresh(tlm::tlm_generic_payload& payload, sc_time
|
||||
|
||||
if (!controller.state.bankStates.allRowBuffersAreClosed())
|
||||
{
|
||||
ScheduledCommand precharge(Command::PrechargeAll, time, controller.config.Timings.tRP,
|
||||
ScheduledCommand precharge(Command::PrechargeAll, time, getExecutionTime(Command::PrechargeAll, refreshPayloads[Bank(0)]),
|
||||
DramExtension::getExtension(refreshPayloads[Bank(0)]));
|
||||
|
||||
controller.getCommandChecker(Command::PrechargeAll).delayToSatisfyConstraints(precharge);
|
||||
|
||||
for (Bank bank : controller.getBanks())
|
||||
{
|
||||
tlm_generic_payload& payload = refreshPayloads[bank];
|
||||
ScheduledCommand prechargeToSend(Command::PrechargeAll, precharge.getStart(),
|
||||
controller.config.Timings.tRP, DramExtension::getExtension(payload));
|
||||
controller.state.change(prechargeToSend);
|
||||
controller.wrapper.send(prechargeToSend, payload);
|
||||
}
|
||||
sendToAllBanks(precharge);
|
||||
}
|
||||
|
||||
|
||||
ScheduledCommand nextRefresh(Command::AutoRefresh, time, timing.tRFC,
|
||||
ScheduledCommand nextRefresh(Command::AutoRefresh, time, getExecutionTime(Command::AutoRefresh, refreshPayloads[Bank(0)]),
|
||||
DramExtension::getExtension(refreshPayloads[Bank(0)]));
|
||||
|
||||
controller.getCommandChecker(Command::AutoRefresh).delayToSatisfyConstraints(nextRefresh);
|
||||
sendToAllBanks(nextRefresh);
|
||||
|
||||
for (Bank bank : controller.getBanks())
|
||||
{
|
||||
tlm_generic_payload& payload = refreshPayloads[bank];
|
||||
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);
|
||||
DramExtension::getExtension(refreshPayloads[bank]).increaseRow();
|
||||
}
|
||||
|
||||
planNextRefresh();
|
||||
}
|
||||
|
||||
void RefreshManager::sendToAllBanks(ScheduledCommand& command)
|
||||
{
|
||||
for (Bank bank : controller.getBanks())
|
||||
{
|
||||
tlm_generic_payload& payload = refreshPayloads[bank];
|
||||
DramExtension extension = DramExtension::getExtension(payload);
|
||||
ScheduledCommand cmd(command.getCommand(), command.getStart(), command.getExecutionTime(), extension);
|
||||
controller.state.change(cmd);
|
||||
controller.wrapper.send(cmd, payload);
|
||||
}
|
||||
}
|
||||
|
||||
void RefreshManager::planNextRefresh()
|
||||
{
|
||||
nextPlannedRefresh += timing.tREFI;
|
||||
|
||||
@@ -36,6 +36,8 @@ private:
|
||||
std::map<Bank, tlm::tlm_generic_payload> refreshPayloads;
|
||||
|
||||
void planNextRefresh();
|
||||
|
||||
void sendToAllBanks(ScheduledCommand& command);
|
||||
void setupTransactions();
|
||||
};
|
||||
|
||||
|
||||
@@ -7,7 +7,8 @@
|
||||
|
||||
#include "RefreshManagerBankwise.h"
|
||||
#include "../ControllerCore.h"
|
||||
#include "../utils/Utils.h"
|
||||
#include "../TimingCalculation.h"
|
||||
#include "../../common/Utils.h"
|
||||
|
||||
using namespace std;
|
||||
|
||||
@@ -16,117 +17,71 @@ namespace core {
|
||||
RefreshManagerBankwise::RefreshManagerBankwise(ControllerCore& controller) :
|
||||
controller(controller)
|
||||
{
|
||||
for (Bank bank : controller.getBanks())
|
||||
for(Bank bank : controller.getBanks())
|
||||
{
|
||||
refreshManagerForBanks[bank] = new RefreshManagerForBank(controller, bank);
|
||||
setUpDummy(refreshPayloads[bank], bank);
|
||||
planNextRefresh(bank);
|
||||
}
|
||||
}
|
||||
|
||||
RefreshManagerBankwise::~RefreshManagerBankwise()
|
||||
{
|
||||
for (Bank bank : controller.getBanks())
|
||||
{
|
||||
delete refreshManagerForBanks[bank];
|
||||
}
|
||||
}
|
||||
|
||||
bool RefreshManagerBankwise::hasCollision(const CommandSchedule& schedule)
|
||||
{
|
||||
RefreshManagerForBank& manager = *refreshManagerForBanks[schedule.getBank()];
|
||||
return manager.hasCollision(schedule);
|
||||
return schedule.getEnd() > nextPlannedRefreshs[schedule.getBank()];
|
||||
}
|
||||
|
||||
bool RefreshManagerBankwise::hasCollision(const ScheduledCommand& command)
|
||||
{
|
||||
RefreshManagerForBank& manager = *refreshManagerForBanks[command.getBank()];
|
||||
return manager.hasCollision(command);
|
||||
return command.getEnd() > nextPlannedRefreshs[command.getBank()];
|
||||
}
|
||||
|
||||
void RefreshManagerBankwise::scheduleRefresh(tlm::tlm_generic_payload& payload, sc_time time)
|
||||
{
|
||||
sc_assert(!isInvalidated(payload, time));
|
||||
RefreshManagerForBank& manager = *refreshManagerForBanks[DramExtension::getExtension(payload).getBank()];
|
||||
manager.scheduleRefresh(time);
|
||||
}
|
||||
|
||||
RefreshManagerBankwise::RefreshManagerForBank::RefreshManagerForBank(ControllerCore& controller, Bank bank) :
|
||||
controller(controller), timing(controller.config.Timings.refreshTimings[bank]), bank(bank), nextPlannedRefresh(
|
||||
SC_ZERO_TIME)
|
||||
{
|
||||
setupTransaction();
|
||||
planNextRefresh();
|
||||
}
|
||||
tlm::tlm_generic_payload& refreshPayload = refreshPayloads[DramExtension::getExtension(payload).getBank()];
|
||||
|
||||
RefreshManagerBankwise::RefreshManagerForBank::~RefreshManagerForBank()
|
||||
{
|
||||
}
|
||||
DramExtension& extension = DramExtension::getExtension(refreshPayload);
|
||||
|
||||
bool RefreshManagerBankwise::RefreshManagerForBank::hasCollision(const CommandSchedule& schedule)
|
||||
{
|
||||
return !(schedule.getEnd() < nextPlannedRefresh);
|
||||
}
|
||||
bool RefreshManagerBankwise::RefreshManagerForBank::hasCollision(const ScheduledCommand& command)
|
||||
{
|
||||
return !(command.getEnd() < nextPlannedRefresh);
|
||||
}
|
||||
|
||||
void RefreshManagerBankwise::RefreshManagerForBank::scheduleRefresh(sc_time time)
|
||||
{
|
||||
ScheduledCommand nextRefresh(Command::AutoRefresh, time, timing.tRFC, DramExtension::getExtension(refreshPayload));
|
||||
|
||||
if (controller.state.bankStates.rowBufferIsOpen(bank))
|
||||
if (controller.state.bankStates.rowBufferIsOpen(extension.getBank()))
|
||||
{
|
||||
ScheduledCommand precharge(Command::Precharge, time, controller.config.Timings.tRP,
|
||||
DramExtension::getExtension(refreshPayload));
|
||||
controller.getCommandChecker(Command::Precharge).delayToSatisfyConstraints(precharge);
|
||||
controller.state.bus.moveCommandToNextFreeSlot(precharge);
|
||||
nextRefresh.setStart(precharge.getEnd());
|
||||
ScheduledCommand precharge(Command::Precharge, time, getExecutionTime(Command::Precharge, refreshPayload), extension);
|
||||
|
||||
controller.getCommandChecker(Command::Precharge).delayToSatisfyConstraints(precharge);
|
||||
controller.state.change(precharge);
|
||||
controller.wrapper.send(precharge, refreshPayload);
|
||||
}
|
||||
controller.state.bus.moveCommandToNextFreeSlot(nextRefresh);
|
||||
|
||||
ScheduledCommand nextRefresh(Command::AutoRefresh, time, getExecutionTime(Command::AutoRefresh, refreshPayload), extension);
|
||||
controller.getCommandChecker(Command::AutoRefresh).delayToSatisfyConstraints(nextRefresh);
|
||||
controller.state.change(nextRefresh);
|
||||
Row currentrow = DramExtension::getExtension(refreshPayload).getRow();
|
||||
DramExtension::getExtension(refreshPayload).setRow(Row((currentrow.ID() + 1) % Configuration::getInstance().NumberOfBanks));
|
||||
controller.wrapper.send(nextRefresh, refreshPayload);
|
||||
|
||||
planNextRefresh();
|
||||
extension.increaseRow();
|
||||
planNextRefresh(extension.getBank());
|
||||
}
|
||||
|
||||
void RefreshManagerBankwise::RefreshManagerForBank::planNextRefresh()
|
||||
void RefreshManagerBankwise::planNextRefresh(Bank bank)
|
||||
{
|
||||
nextPlannedRefresh += timing.tREFI;
|
||||
controller.wrapper.send(RefreshTrigger, nextPlannedRefresh, refreshPayload);
|
||||
}
|
||||
|
||||
void RefreshManagerBankwise::RefreshManagerForBank::reInitialize(Bank bank, sc_time time)
|
||||
{
|
||||
nextPlannedRefresh = clkAlign(time, Alignment::DOWN);
|
||||
planNextRefresh();
|
||||
}
|
||||
|
||||
bool RefreshManagerBankwise::RefreshManagerForBank::isInvalidated(sc_time time)
|
||||
{
|
||||
return nextPlannedRefresh > time;
|
||||
}
|
||||
|
||||
void RefreshManagerBankwise::RefreshManagerForBank::setupTransaction()
|
||||
{
|
||||
setUpDummy(refreshPayload, bank);
|
||||
nextPlannedRefreshs[bank] += Configuration::getInstance().Timings.refreshTimings[bank].tREFI;
|
||||
controller.wrapper.send(RefreshTrigger, nextPlannedRefreshs[bank], refreshPayloads[bank]);
|
||||
}
|
||||
|
||||
void RefreshManagerBankwise::reInitialize(Bank bank, sc_time time)
|
||||
{
|
||||
|
||||
refreshManagerForBanks[bank]->reInitialize(bank, time);
|
||||
nextPlannedRefreshs[bank] = clkAlign(time, Alignment::DOWN);
|
||||
planNextRefresh(bank);
|
||||
}
|
||||
|
||||
bool RefreshManagerBankwise::isInvalidated(tlm::tlm_generic_payload& payload, sc_time time)
|
||||
{
|
||||
RefreshManagerForBank& manager = *refreshManagerForBanks[DramExtension::getExtension(payload).getBank()];
|
||||
return manager.isInvalidated(time);
|
||||
return nextPlannedRefreshs[DramExtension::getExtension(payload).getBank()] > time;
|
||||
}
|
||||
|
||||
|
||||
|
||||
} /* namespace core */
|
||||
|
||||
|
||||
@@ -33,35 +33,12 @@ public:
|
||||
|
||||
private:
|
||||
|
||||
class RefreshManagerForBank
|
||||
{
|
||||
public:
|
||||
RefreshManagerForBank(ControllerCore& controller, Bank bank);
|
||||
~RefreshManagerForBank();
|
||||
|
||||
bool hasCollision(const CommandSchedule& schedule);
|
||||
bool hasCollision(const ScheduledCommand& command);
|
||||
void scheduleRefresh(sc_time time);
|
||||
|
||||
void reInitialize(Bank bank, sc_time time);
|
||||
|
||||
bool isInvalidated(sc_time);
|
||||
private:
|
||||
ControllerCore& controller;
|
||||
RefreshTiming& timing;
|
||||
Bank bank;
|
||||
|
||||
tlm::tlm_generic_payload refreshPayload;
|
||||
sc_time nextPlannedRefresh;
|
||||
|
||||
void planNextRefresh();
|
||||
void setupTransaction();
|
||||
};
|
||||
|
||||
ControllerCore& controller;
|
||||
std::map<Bank, RefreshManagerForBank*> refreshManagerForBanks;
|
||||
|
||||
std::map<Bank, tlm::tlm_generic_payload> refreshPayloads;
|
||||
std::map<Bank, sc_time> nextPlannedRefreshs;
|
||||
|
||||
void planNextRefresh(Bank bank);
|
||||
};
|
||||
|
||||
} /* namespace controller */
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
#include "CommandSequenceScheduler.h"
|
||||
#include "../ControllerCore.h"
|
||||
#include "../../common/DebugManager.h"
|
||||
#include "../TimingCalculation.h"
|
||||
|
||||
namespace core {
|
||||
|
||||
@@ -22,7 +23,7 @@ CommandSchedule CommandSequenceScheduler::schedule(CommandSequence commands, sc_
|
||||
|
||||
ICommandChecker& checker = controller.getCommandChecker(cmd);
|
||||
|
||||
sc_time executionTime = checker.getExecutionTime(transaction, cmd);
|
||||
sc_time executionTime = getExecutionTime(cmd,transaction);
|
||||
ScheduledCommand& scheduledCommand = schedule.add(cmd, start, executionTime);
|
||||
checker.delayToSatisfyConstraints(scheduledCommand);
|
||||
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
* Author: robert
|
||||
*/
|
||||
#include "ScheduledCommand.h"
|
||||
#include "../utils/Utils.h"
|
||||
#include "../TimingCalculation.h"
|
||||
#include "../../common/Utils.h"
|
||||
#include "../configuration/Configuration.h"
|
||||
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
#include "../Command.h"
|
||||
#include "../../common/dramExtension.h"
|
||||
#include "../../common/TlmRecorder.h"
|
||||
#include "../utils/Utils.h"
|
||||
#include "../TimingCalculation.h"
|
||||
|
||||
namespace core {
|
||||
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
#include <algorithm>
|
||||
#include <set>
|
||||
#include "ActivateChecker.h"
|
||||
#include "../../utils/Utils.h"
|
||||
#include "../../TimingCalculation.h"
|
||||
#include "../../../common/DebugManager.h"
|
||||
#include "../../Command.h"
|
||||
#include "../../../common/Utils.h"
|
||||
@@ -31,11 +31,11 @@ void ActivateChecker::delayToSatisfyConstraints(ScheduledCommand& command) const
|
||||
else if (lastCommandOnBank.getCommand() == Command::PDNPX
|
||||
|| lastCommandOnBank.getCommand() == Command::PDNAX)
|
||||
{
|
||||
command.delayToMeetConstraint(lastCommandOnBank.getEnd(), config.Timings.tXP);
|
||||
command.delayToMeetConstraint(lastCommandOnBank.getStart(), config.Timings.tXP);
|
||||
}
|
||||
else if (lastCommandOnBank.getCommand() == Command::SREFX)
|
||||
{
|
||||
command.delayToMeetConstraint(lastCommandOnBank.getEnd(), config.Timings.tXSR);
|
||||
command.delayToMeetConstraint(lastCommandOnBank.getStart(), config.Timings.tXSR);
|
||||
}
|
||||
else
|
||||
reportFatal("Activate Checker",
|
||||
@@ -53,13 +53,6 @@ void ActivateChecker::delayToSatisfyConstraints(ScheduledCommand& command) const
|
||||
|
||||
}
|
||||
|
||||
sc_time ActivateChecker::getExecutionTime(const tlm::tlm_generic_payload& transaction,
|
||||
Command command) const
|
||||
{
|
||||
assert(command == Command::Activate);
|
||||
return config.Timings.tRCD;
|
||||
}
|
||||
|
||||
void ActivateChecker::delay_to_satisfy_activateToActivate_sameBank(ScheduledCommand& command) const
|
||||
{
|
||||
ScheduledCommand lastActivateOnBank = state.getLastCommand(Command::Activate,
|
||||
|
||||
@@ -22,8 +22,6 @@ public:
|
||||
virtual ~ActivateChecker(){}
|
||||
|
||||
virtual void delayToSatisfyConstraints(ScheduledCommand& command) const override;
|
||||
virtual sc_time getExecutionTime(const tlm::tlm_generic_payload& payload, Command command) const override;
|
||||
|
||||
private:
|
||||
const Configuration& config;
|
||||
ControllerState& state;//TODO make const
|
||||
|
||||
@@ -17,9 +17,7 @@ class ICommandChecker
|
||||
{
|
||||
public:
|
||||
virtual ~ICommandChecker() {}
|
||||
|
||||
virtual void delayToSatisfyConstraints(ScheduledCommand& command) const = 0;
|
||||
virtual sc_time getExecutionTime(const tlm::tlm_generic_payload& payload, Command command) const = 0;
|
||||
};
|
||||
|
||||
} /* namespace controller */
|
||||
|
||||
@@ -51,13 +51,8 @@ void PrechargeAllChecker::delayToSatisfyConstraints(ScheduledCommand& command) c
|
||||
"Precharge All can not follow " + commandToString(lastCommand.getCommand()));
|
||||
}
|
||||
}
|
||||
|
||||
state.bus.moveCommandToNextFreeSlot(command);
|
||||
}
|
||||
|
||||
sc_time PrechargeAllChecker::getExecutionTime(const tlm::tlm_generic_payload& payload, Command command) const
|
||||
{
|
||||
sc_assert(command == Command::PrechargeAll);
|
||||
return config.Timings.tRP;
|
||||
}
|
||||
|
||||
} /* namespace core */
|
||||
|
||||
@@ -26,8 +26,6 @@ public:
|
||||
}
|
||||
|
||||
virtual void delayToSatisfyConstraints(ScheduledCommand& command) const override;
|
||||
virtual sc_time getExecutionTime(const tlm::tlm_generic_payload& payload, Command command) const
|
||||
override;
|
||||
|
||||
private:
|
||||
const Configuration& config;
|
||||
|
||||
@@ -41,11 +41,4 @@ void PrechargeChecker::delayToSatisfyConstraints(ScheduledCommand& command) cons
|
||||
state.bus.moveCommandToNextFreeSlot(command);
|
||||
}
|
||||
|
||||
sc_time PrechargeChecker::getExecutionTime(const tlm::tlm_generic_payload& payload,
|
||||
Command command) const
|
||||
{
|
||||
sc_assert(command == Command::Precharge || command == Command::PrechargeAll);
|
||||
return config.Timings.tRP;
|
||||
}
|
||||
|
||||
} /* namespace controller */
|
||||
|
||||
@@ -19,9 +19,8 @@ class PrechargeChecker: public core::ICommandChecker
|
||||
public:
|
||||
PrechargeChecker(const Configuration& config, ControllerState& state) : config(config), state(state) {}
|
||||
virtual ~PrechargeChecker() {}
|
||||
|
||||
virtual void delayToSatisfyConstraints(ScheduledCommand& command) const override;
|
||||
virtual sc_time getExecutionTime(const tlm::tlm_generic_payload& payload, Command command) const override;
|
||||
|
||||
private:
|
||||
const Configuration& config;
|
||||
ControllerState& state;
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
*/
|
||||
|
||||
#include "ReadChecker.h"
|
||||
#include "../../utils/Utils.h"
|
||||
#include "../../TimingCalculation.h"
|
||||
#include "../../../common/Utils.h"
|
||||
|
||||
namespace core {
|
||||
@@ -29,7 +29,7 @@ void ReadChecker::delayToSatisfyConstraints(ScheduledCommand& command) const
|
||||
}
|
||||
else if (lastCommand.getCommand() == Command::PDNAX)
|
||||
{
|
||||
command.delayToMeetConstraint(lastCommand.getEnd(), config.Timings.tXP);//TODO DLL also for PDNP and SREF .. not onyl last command
|
||||
command.delayToMeetConstraint(lastCommand.getStart(), config.Timings.tXP);//TODO DLL also for PDNP and SREF .. not onyl last command
|
||||
}
|
||||
else
|
||||
reportFatal("Read Checker",
|
||||
@@ -53,20 +53,6 @@ bool ReadChecker::collidesOnDataStrobe(ScheduledCommand& read) const
|
||||
return false;
|
||||
}
|
||||
|
||||
sc_time ReadChecker::getExecutionTime(const tlm::tlm_generic_payload& payload,
|
||||
Command command) const
|
||||
{
|
||||
if (command == Command::Read)
|
||||
{
|
||||
return config.Timings.tRL + getBurstLengthOnDataStrobe(payload.get_streaming_width());
|
||||
}
|
||||
else
|
||||
{
|
||||
return getBurstLengthOnDataStrobe(payload.get_streaming_width())
|
||||
+ max(config.Timings.tRP, config.Timings.tRL);
|
||||
}
|
||||
}
|
||||
|
||||
bool ReadChecker::collidesWithStrobeCommand(ScheduledCommand& read,
|
||||
ScheduledCommand& strobeCommand) const
|
||||
{
|
||||
|
||||
@@ -21,7 +21,6 @@ public:
|
||||
virtual ~ReadChecker() {}
|
||||
|
||||
virtual void delayToSatisfyConstraints(ScheduledCommand& command) const override;
|
||||
virtual sc_time getExecutionTime(const tlm::tlm_generic_payload& payload, Command command) const override;
|
||||
|
||||
private:
|
||||
const Configuration& config;
|
||||
|
||||
@@ -30,22 +30,14 @@ void RefreshChecker::delayToSatisfyConstraints(ScheduledCommand& command) const
|
||||
{
|
||||
command.delayToMeetConstraint(lastCommandOnBank.getEnd(), config.Timings.tXSR);
|
||||
}
|
||||
else if (lastCommandOnBank.getCommand() == Command::AutoRefresh)
|
||||
{
|
||||
}
|
||||
else
|
||||
reportFatal("Refresh Checker", "Refresh can not follow " + commandToString(lastCommandOnBank.getCommand()));
|
||||
}
|
||||
|
||||
while (!state.bus.isFree(command.getStart()))
|
||||
{
|
||||
command.delayStart(config.Timings.clk);
|
||||
}
|
||||
}
|
||||
|
||||
sc_time RefreshChecker::getExecutionTime(const tlm::tlm_generic_payload& payload, Command command) const
|
||||
{
|
||||
assert(command == Command::AutoRefresh);
|
||||
Bank bank = DramExtension::getExtension(payload).getBank();
|
||||
RefreshTiming timing = config.Timings.refreshTimings.at(bank);
|
||||
return timing.tRFC;
|
||||
state.bus.moveCommandToNextFreeSlot(command);
|
||||
}
|
||||
|
||||
} /* namespace core */
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
|
||||
namespace core {
|
||||
|
||||
class RefreshChecker: ICommandChecker
|
||||
class RefreshChecker: public ICommandChecker
|
||||
{
|
||||
public:
|
||||
RefreshChecker(const Configuration& config, ControllerState& state) :
|
||||
@@ -27,7 +27,6 @@ public:
|
||||
}
|
||||
|
||||
virtual void delayToSatisfyConstraints(ScheduledCommand& command) const override;
|
||||
virtual sc_time getExecutionTime(const tlm::tlm_generic_payload& payload, Command command) const override;
|
||||
|
||||
private:
|
||||
const Configuration& config;
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
*/
|
||||
|
||||
#include "WriteChecker.h"
|
||||
#include "../../utils/Utils.h"
|
||||
#include "../../TimingCalculation.h"
|
||||
#include "../../../common/Utils.h"
|
||||
|
||||
namespace core {
|
||||
@@ -30,7 +30,7 @@ void WriteChecker::delayToSatisfyConstraints(ScheduledCommand& command) const
|
||||
}
|
||||
else if (lastCommand.getCommand() == Command::PDNAX)
|
||||
{
|
||||
command.delayToMeetConstraint(lastCommand.getEnd(), config.Timings.tXP);
|
||||
command.delayToMeetConstraint(lastCommand.getStart(), config.Timings.tXP);
|
||||
}
|
||||
else
|
||||
reportFatal("Write Checker",
|
||||
@@ -43,26 +43,6 @@ void WriteChecker::delayToSatisfyConstraints(ScheduledCommand& command) const
|
||||
}
|
||||
}
|
||||
|
||||
sc_time WriteChecker::getExecutionTime(const tlm::tlm_generic_payload& payload,
|
||||
Command command) const
|
||||
{
|
||||
assert(command == Command::Write || command == Command::WriteA);
|
||||
|
||||
sc_time lengthOnDataStrobe = getBurstLengthOnDataStrobe(payload.get_streaming_width());
|
||||
if(Configuration::getInstance().DataRate == 1)
|
||||
lengthOnDataStrobe -= Configuration::getInstance().Timings.clk;
|
||||
|
||||
|
||||
if (command == Command::Write)
|
||||
{
|
||||
return config.Timings.tWL + lengthOnDataStrobe;
|
||||
}
|
||||
else
|
||||
{
|
||||
return config.Timings.tWL + lengthOnDataStrobe + config.Timings.tWR;
|
||||
}
|
||||
}
|
||||
|
||||
bool WriteChecker::collidesOnDataStrobe(ScheduledCommand& write) const
|
||||
{
|
||||
for (ScheduledCommand& strobeCommand : state.lastDataStrobeCommands)
|
||||
|
||||
@@ -21,7 +21,6 @@ public:
|
||||
virtual ~WriteChecker() {}
|
||||
|
||||
virtual void delayToSatisfyConstraints(ScheduledCommand& command) const override;
|
||||
virtual sc_time getExecutionTime(const tlm::tlm_generic_payload& payload, Command command) const override;
|
||||
private:
|
||||
bool collidesOnDataStrobe(ScheduledCommand& write) const;
|
||||
bool collidesWithStrobeCommand(ScheduledCommand& write, ScheduledCommand& strobeCommand) const;
|
||||
|
||||
@@ -1,79 +0,0 @@
|
||||
/*
|
||||
* Utils.cpp
|
||||
*
|
||||
* Created on: Mar 12, 2014
|
||||
* Author: jonny
|
||||
*/
|
||||
|
||||
#include "Utils.h"
|
||||
#include "../configuration/TimingConfiguration.h"
|
||||
#include "../ControllerCore.h"
|
||||
#include "../../common/DebugManager.h"
|
||||
#include "../configuration/Configuration.h"
|
||||
|
||||
namespace core {
|
||||
|
||||
|
||||
sc_time getDistance(sc_time a, sc_time b)
|
||||
{
|
||||
if (a > b)
|
||||
return a - b;
|
||||
else
|
||||
return b - a;
|
||||
}
|
||||
|
||||
sc_time getDelayToMeetConstraint(sc_time previous, sc_time start, sc_time constraint)
|
||||
{
|
||||
if (previous + constraint > start)
|
||||
return previous + constraint - start;
|
||||
else
|
||||
return SC_ZERO_TIME;
|
||||
}
|
||||
|
||||
const sc_time clkAlign(sc_time time, Alignment alignment)
|
||||
{
|
||||
sc_time clk = Configuration::getInstance().Timings.clk;
|
||||
if (alignment == UP)
|
||||
return ceil(time / clk) * clk;
|
||||
else
|
||||
return floor(time / clk) * clk;
|
||||
}
|
||||
|
||||
bool isClkAligned(sc_time time, sc_time clk)
|
||||
{
|
||||
return !((time / clk) - ceil(time / clk));
|
||||
}
|
||||
|
||||
bool TimeInterval::timeIsInInterval(sc_time time)
|
||||
{
|
||||
return (start < time && time < end);
|
||||
}
|
||||
|
||||
bool TimeInterval::intersects(TimeInterval other)
|
||||
{
|
||||
return other.timeIsInInterval(this->start) || this->timeIsInInterval(other.start);
|
||||
}
|
||||
|
||||
sc_time getBurstLengthOnDataStrobe(unsigned int burstlength)
|
||||
{
|
||||
Configuration& config = Configuration::getInstance();
|
||||
sc_assert((burstlength / config.DataRate) > 0);
|
||||
|
||||
return config.Timings.clk * (burstlength / config.DataRate);
|
||||
}
|
||||
|
||||
|
||||
|
||||
void setUpDummy(tlm::tlm_generic_payload& payload, Bank& bank)
|
||||
{
|
||||
payload.set_address(bank.getStartAddress());
|
||||
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, bank.getBankGroup(), Row(0), Column(0))); //payload takes ownership
|
||||
}
|
||||
|
||||
}
|
||||
@@ -17,7 +17,7 @@
|
||||
#include <tlm_utils/peq_with_cb_and_phase.h>
|
||||
#include "../common/xmlAddressdecoder.h"
|
||||
#include "../common/dramExtension.h"
|
||||
#include "../core/utils/Utils.h"
|
||||
#include "../core/TimingCalculation.h"
|
||||
#include <iostream>
|
||||
|
||||
|
||||
|
||||
@@ -42,8 +42,7 @@ public:
|
||||
tlm_utils::simple_target_socket<Controller, BUSWIDTH, tlm::tlm_base_protocol_types> tSocket;
|
||||
|
||||
Controller(sc_module_name name) :
|
||||
frontendPEQ(this, &Controller::frontendPEQCallback), dramPEQ(this,
|
||||
&Controller::dramPEQCallback), controllerPEQ(this,
|
||||
frontendPEQ(this, &Controller::frontendPEQCallback), dramPEQ(this, &Controller::dramPEQCallback), controllerPEQ(this,
|
||||
&Controller::controllerPEQCallback), debugManager(DebugManager::getInstance())
|
||||
{
|
||||
controller = new ControllerCore(*this, numberOfPayloadsInSystem);
|
||||
@@ -65,19 +64,13 @@ public:
|
||||
|
||||
if (selectedScheduler == "FR_FCFS")
|
||||
{
|
||||
// if(Configuration::getInstance().RefreshAwareScheduling)
|
||||
// cout << "Building refresh aware scheduler" << std::endl;
|
||||
// else
|
||||
// cout << "Building refresh un-aware scheduler" << std::endl;
|
||||
|
||||
scheduler = new FR_FCFS(controller->state.bankStates,
|
||||
Configuration::getInstance().RefreshAwareScheduling,
|
||||
scheduler = new FR_FCFS(controller->state.bankStates, Configuration::getInstance().RefreshAwareScheduling,
|
||||
Configuration::getInstance().AdaptiveOpenPagePolicy);
|
||||
}
|
||||
else if (selectedScheduler == "PAR_BS")
|
||||
{
|
||||
scheduler = new PAR_BS(controller->state.bankStates,
|
||||
Configuration::getInstance().RefreshAwareScheduling,
|
||||
scheduler = new PAR_BS(controller->state.bankStates, Configuration::getInstance().RefreshAwareScheduling,
|
||||
Configuration::getInstance().Capsize);
|
||||
}
|
||||
else if (selectedScheduler == "FIFO")
|
||||
@@ -181,15 +174,15 @@ public:
|
||||
break;
|
||||
case Command::PDNAX:
|
||||
dramPEQ.notify(payload, END_PDNA, command.getStart() - sc_time_stamp());
|
||||
rec.recordPhase(payload, END_PDNA, command.getStart());
|
||||
rec.recordPhase(payload, END_PDNA, command.getEnd());
|
||||
break;
|
||||
case Command::PDNPX:
|
||||
dramPEQ.notify(payload, END_PDNP, command.getStart() - sc_time_stamp());
|
||||
rec.recordPhase(payload, END_PDNP, command.getStart());
|
||||
rec.recordPhase(payload, END_PDNP, command.getEnd());
|
||||
break;
|
||||
case Command::SREFX:
|
||||
dramPEQ.notify(payload, END_SREF, command.getStart() - sc_time_stamp());
|
||||
rec.recordPhase(payload, END_SREF, command.getStart());
|
||||
rec.recordPhase(payload, END_SREF, command.getEnd());
|
||||
break;
|
||||
default:
|
||||
SC_REPORT_FATAL(0, "unsupported command in controller");
|
||||
@@ -207,10 +200,6 @@ public:
|
||||
{
|
||||
controllerPEQ.notify(payload, REFRESH_TRIGGER, delay);
|
||||
}
|
||||
else if (trigger == Trigger::WakeUpTrigger)
|
||||
{
|
||||
controllerPEQ.notify(payload, WAKEUP_TRIGGER, delay);
|
||||
}
|
||||
else
|
||||
{
|
||||
SC_REPORT_FATAL("controller wrapper", "unknown trigger");
|
||||
@@ -234,7 +223,7 @@ private:
|
||||
unsigned int getNumberOfPayloadsInSystem()
|
||||
{
|
||||
unsigned int sum = 0;
|
||||
for(Bank bank : controller->getBanks())
|
||||
for (Bank bank : controller->getBanks())
|
||||
{
|
||||
sum += numberOfPayloadsInSystem[bank];
|
||||
}
|
||||
@@ -245,22 +234,15 @@ private:
|
||||
{
|
||||
Bank bank = DramExtension::getExtension(payload).getBank();
|
||||
printDebugMessage("Transaction enters system on bank " + to_string(bank.ID()));
|
||||
numberOfPayloadsInSystem[bank] = numberOfPayloadsInSystem[bank] + 1;
|
||||
scheduler->schedule(&payload);
|
||||
numberOfPayloadsInSystem[bank]++;
|
||||
}
|
||||
|
||||
void payloadLeavesSystem(tlm_generic_payload& payload)
|
||||
{
|
||||
Bank bank = DramExtension::getExtension(payload).getBank();
|
||||
numberOfPayloadsInSystem[bank]--;
|
||||
if (numberOfPayloadsInSystem[bank] == 0)
|
||||
{
|
||||
printDebugMessage(
|
||||
"Payload leaving system. No more payloads on bank " + to_string(bank.ID())
|
||||
+ ". Trigger sleep.");
|
||||
|
||||
controller->powerDownManager->sleep(bank, sc_time_stamp());
|
||||
}
|
||||
controller->powerDownManager->sleep(bank, sc_time_stamp());
|
||||
}
|
||||
|
||||
void scheduleNextPayload(Bank bank)
|
||||
@@ -275,15 +257,7 @@ private:
|
||||
return;
|
||||
}
|
||||
|
||||
if (controller->powerDownManager->isInPowerDown(bank))
|
||||
{
|
||||
printDebugMessage("\t-> wake up bank first");
|
||||
controller->powerDownManager->wakeUp(bank, sc_time_stamp());
|
||||
}
|
||||
else if (controller->powerDownManager->isAwakeForRefresh(bank))
|
||||
{
|
||||
controller->powerDownManager->wakeUp(bank, sc_time_stamp());
|
||||
}
|
||||
controller->powerDownManager->wakeUp(bank, sc_time_stamp());
|
||||
|
||||
tlm_generic_payload* nextTransaction = scheduler->getTransactionForBank(bank);
|
||||
if (controller->scheduleRequest(sc_time_stamp(), *nextTransaction))
|
||||
@@ -293,13 +267,13 @@ private:
|
||||
}
|
||||
else
|
||||
{
|
||||
printDebugMessage(
|
||||
"\t-> break: payload was not scheduled by core (collision with refresh)");
|
||||
printDebugMessage("\t-> break: payload was not scheduled by core (collision with refresh)");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
printDebugMessage("\t-> break: no transaction for bank");
|
||||
controller->powerDownManager->sleep(bank, sc_time_stamp());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -317,22 +291,25 @@ private:
|
||||
if (phase == BEGIN_REQ)
|
||||
{
|
||||
payload.acquire();
|
||||
if(getNumberOfPayloadsInSystem() == controller->config.MaxNrOfTransactions)
|
||||
payloadEntersSystem(payload);
|
||||
|
||||
if (getNumberOfPayloadsInSystem() > controller->config.MaxNrOfTransactions)
|
||||
{
|
||||
printDebugMessage("##Backpressure: Max number of transactions in system reached");
|
||||
backpressure = &payload;
|
||||
return TLM_ACCEPTED;
|
||||
}
|
||||
|
||||
payloadEntersSystem(payload);
|
||||
frontendPEQ.notify(payload, phase, inputBufferDelay);
|
||||
frontendPEQ.notify(payload, phase,
|
||||
clkAlign(sc_time_stamp()) - sc_time_stamp() + Configuration::getInstance().Timings.clk);
|
||||
}
|
||||
else if (phase == END_RESP)
|
||||
{
|
||||
if(backpressure != NULL)
|
||||
if (backpressure != NULL)
|
||||
{
|
||||
payloadEntersSystem(*backpressure);
|
||||
frontendPEQ.notify(*backpressure, BEGIN_REQ, inputBufferDelay);
|
||||
printDebugMessage("##Backpressure released");
|
||||
//already registered above
|
||||
frontendPEQ.notify(*backpressure, BEGIN_REQ, Configuration::getInstance().Timings.clk);
|
||||
backpressure = NULL;
|
||||
}
|
||||
|
||||
@@ -347,6 +324,7 @@ private:
|
||||
{
|
||||
if (phase == BEGIN_REQ)
|
||||
{
|
||||
scheduler->schedule(&payload);
|
||||
scheduleNextPayload(DramExtension::getExtension(payload).getBank());
|
||||
payload.set_response_status(tlm::TLM_OK_RESPONSE);
|
||||
TlmRecorder::getInstance().recordPhase(payload, END_REQ, sc_time_stamp());
|
||||
@@ -354,8 +332,7 @@ private:
|
||||
}
|
||||
else
|
||||
{
|
||||
SC_REPORT_FATAL(0,
|
||||
"Frontend PEQ event queue in controller wrapper was triggered with unknown phase");
|
||||
SC_REPORT_FATAL(0, "Frontend PEQ event queue in controller wrapper was triggered with unknown phase");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -384,16 +361,12 @@ private:
|
||||
}
|
||||
else if (isIn(phase, { BEGIN_PDNA, BEGIN_PDNP, BEGIN_SREF }))
|
||||
{
|
||||
printDebugMessage(
|
||||
"Entering PowerDown " + phaseNameToString(phase) + " on bank "
|
||||
+ to_string(bank.ID()));
|
||||
printDebugMessage("Entering PowerDown " + phaseNameToString(phase) + " on bank " + to_string(bank.ID()));
|
||||
sendToDram(payload, phase, SC_ZERO_TIME);
|
||||
}
|
||||
else if (isIn(phase, { END_PDNA, END_PDNP, END_SREF }))
|
||||
{
|
||||
printDebugMessage(
|
||||
"Leaving PowerDown " + phaseNameToString(phase) + " on bank "
|
||||
+ to_string(bank.ID()));
|
||||
printDebugMessage("Leaving PowerDown " + phaseNameToString(phase) + " on bank " + to_string(bank.ID()));
|
||||
sendToDram(payload, phase, SC_ZERO_TIME);
|
||||
}
|
||||
else if (phase == BEGIN_AUTO_REFRESH)
|
||||
@@ -404,11 +377,6 @@ private:
|
||||
else if (phase == END_AUTO_REFRESH)
|
||||
{
|
||||
printDebugMessage("Finished auto refresh on bank " + to_string(bank.ID()));
|
||||
if (numberOfPayloadsInSystem[bank] == 0)
|
||||
{
|
||||
printDebugMessage("\t -> Triggering sleep on bank " + to_string(bank.ID()));
|
||||
controller->powerDownManager->sleep(bank, sc_time_stamp());
|
||||
}
|
||||
scheduleNextPayload(DramExtension::getExtension(payload).getBank());
|
||||
}
|
||||
else if (isIn(phase, { END_PRE, END_PRE_ALL, END_ACT }))
|
||||
@@ -419,9 +387,7 @@ 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());
|
||||
}
|
||||
}
|
||||
@@ -432,14 +398,9 @@ private:
|
||||
{
|
||||
controller->triggerRefresh(payload, sc_time_stamp());
|
||||
}
|
||||
else if (phase == WAKEUP_TRIGGER)
|
||||
{
|
||||
controller->triggerWakeUp(payload, sc_time_stamp());
|
||||
}
|
||||
else
|
||||
{
|
||||
SC_REPORT_FATAL(0,
|
||||
"controllerPEQCallback queue in controller wrapper was triggered with unknown phase");
|
||||
SC_REPORT_FATAL(0, "controllerPEQCallback queue in controller wrapper was triggered with unknown phase");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -61,7 +61,7 @@ Simulation::Simulation(sc_module_name name, string pathToResources, string trace
|
||||
whiteList.push_back(this->name());
|
||||
whiteList.push_back(TlmRecorder::senderName);
|
||||
whiteList.push_back(ControllerCore::senderName);
|
||||
whiteList.push_back(PowerDownManager::senderName);
|
||||
whiteList.push_back(PowerDownManagerBankwise::senderName);
|
||||
}
|
||||
|
||||
auto& dbg = DebugManager::getInstance();
|
||||
|
||||
@@ -38,7 +38,7 @@ bool runSimulation(string resources, string traceName, DramSetup setup, vector<D
|
||||
int status = 0;
|
||||
if (pid == 0)
|
||||
{
|
||||
Simulation simulation("sim", resources, traceName, setup, devices, true);
|
||||
Simulation simulation("sim", resources, traceName, setup, devices, false);
|
||||
simulation.startSimulation();
|
||||
return true;
|
||||
}
|
||||
@@ -101,6 +101,7 @@ int sc_main(int argc, char **argv)
|
||||
string trace1 = "chstone-jpeg_32.stl";
|
||||
//trace1 = "trace.stl";
|
||||
|
||||
|
||||
if (runSimulation(resources, traceName, setup, { Device(trace1), Device(trace2) }))
|
||||
startTraceAnalyzer(traceName);
|
||||
return 0;
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
*/
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
#include "core/utils/Utils.h"
|
||||
#include "core/TimingCalculation.h"
|
||||
#include "core/utils/RingBuffer.h"
|
||||
|
||||
//using namespace testing;
|
||||
|
||||
Reference in New Issue
Block a user