Moved specific timing calculation functions to MemSpecs.
This commit is contained in:
@@ -137,7 +137,6 @@ SOURCES += \
|
||||
src/controller/RecordableController.cpp \
|
||||
src/common/AddressDecoder.cpp \
|
||||
src/simulation/Dram.cpp \
|
||||
src/simulation/RecordableDram.cpp \
|
||||
src/simulation/Arbiter.cpp \
|
||||
src/common/CongenAddressDecoder.cpp \
|
||||
src/common/XmlAddressDecoder.cpp \
|
||||
@@ -148,7 +147,8 @@ SOURCES += \
|
||||
src/simulation/DramDDR4.cpp \
|
||||
src/simulation/DramRecordable.cpp \
|
||||
src/simulation/DramWideIO.cpp \
|
||||
src/controller/core/scheduling/checker/CheckerDDR3.cpp
|
||||
src/controller/core/scheduling/checker/CheckerDDR3.cpp \
|
||||
src/controller/core/configuration/MemSpec.cpp
|
||||
|
||||
HEADERS += \
|
||||
src/common/third_party/tinyxml2/tinyxml2.h \
|
||||
@@ -218,7 +218,6 @@ HEADERS += \
|
||||
src/simulation/IArbiter.h \
|
||||
src/simulation/SimpleArbiter.h \
|
||||
src/controller/RecordableController.h \
|
||||
src/simulation/RecordableDram.h \
|
||||
src/common/AddressDecoder.h \
|
||||
src/common/CongenAddressDecoder.h \
|
||||
src/common/XmlAddressDecoder.h \
|
||||
|
||||
@@ -190,7 +190,7 @@ ScheduledCommand ControllerCore::schedule(Command command, sc_time start,
|
||||
{
|
||||
ControllerCore::printDebugMessage("Scheduling command " + commandToString(
|
||||
command) + " on " + DramExtension::getBank(payload).toString());
|
||||
sc_time executionTime = getExecutionTime(command, payload);
|
||||
sc_time executionTime = Configuration::getInstance().memSpec->getExecutionTime(command, payload);
|
||||
ScheduledCommand scheduledCommand(command, start, executionTime,
|
||||
DramExtension::getExtension(payload));
|
||||
getCommandChecker(command).delayToSatisfyConstraints(scheduledCommand);
|
||||
|
||||
133
DRAMSys/library/src/controller/core/configuration/MemSpec.cpp
Normal file
133
DRAMSys/library/src/controller/core/configuration/MemSpec.cpp
Normal file
@@ -0,0 +1,133 @@
|
||||
/*
|
||||
* Copyright (c) 2015, University of Kaiserslautern
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are
|
||||
* met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* 3. Neither the name of the copyright holder nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from
|
||||
* this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
||||
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER
|
||||
* OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* Authors:
|
||||
* Lukas Steiner
|
||||
*/
|
||||
|
||||
#include "MemSpec.h"
|
||||
|
||||
#include <systemc>
|
||||
#include <tlm>
|
||||
#include "../../Command.h"
|
||||
#include "Configuration.h"
|
||||
|
||||
sc_time MemSpec::getMinExecutionTimeForPowerDownCmd(Command command) const
|
||||
{
|
||||
if (command == Command::PDNA || command == Command::PDNP)
|
||||
return tCKE;
|
||||
else if (command == Command::SREF)
|
||||
return tCKESR;
|
||||
else
|
||||
{
|
||||
SC_REPORT_FATAL("getMinimalExecutionTime",
|
||||
"command is not know or command has a fixed execution time");
|
||||
return SC_ZERO_TIME;
|
||||
}
|
||||
}
|
||||
|
||||
// Returns the execution time for commands that have a fixed execution time
|
||||
sc_time MemSpec::getExecutionTime(Command command, tlm::tlm_generic_payload &payload) const
|
||||
{
|
||||
if (command == Command::PreB)
|
||||
return Configuration::getInstance().getTrpb();
|
||||
else if (command == Command::Precharge || command == Command::PrechargeAll)
|
||||
return tRP;
|
||||
else if (command == Command::ActB)
|
||||
return tRCD;
|
||||
else if (command == Command::Activate)
|
||||
return tRCD;
|
||||
else if (command == Command::Read)
|
||||
return tRL + getReadAccessTime();
|
||||
else if (command == Command::ReadA)
|
||||
return tRTP + tRP;
|
||||
else if (command == Command::Write)
|
||||
return tWL + getWriteAccessTime();
|
||||
else if (command == Command::WriteA)
|
||||
return tWL + getWriteAccessTime() + tWR + tRP;
|
||||
else if (command == Command::PrechargeAll)
|
||||
return tRP;
|
||||
else if (command == Command::AutoRefresh)
|
||||
{
|
||||
return getElementFromMap(refreshTimings,
|
||||
DramExtension::getExtension(payload).getBank()).tRFC;
|
||||
}
|
||||
else if (command == Command::PDNAX || command == Command::PDNPX || command == Command::SREFX)
|
||||
return clk;
|
||||
else
|
||||
{
|
||||
SC_REPORT_FATAL("getExecutionTime",
|
||||
"command not known or command doesn't have a fixed execution time");
|
||||
return SC_ZERO_TIME;
|
||||
}
|
||||
}
|
||||
|
||||
sc_time MemSpecDDR4::getExecutionTime(Command command, tlm::tlm_generic_payload &payload) const
|
||||
{
|
||||
if (command == Command::PreB)
|
||||
return Configuration::getInstance().getTrpb();
|
||||
else if (command == Command::Precharge || command == Command::PrechargeAll)
|
||||
return tRP;
|
||||
else if (command == Command::ActB)
|
||||
return tRCD;
|
||||
else if (command == Command::Activate)
|
||||
return tRCD;
|
||||
else if (command == Command::Read)
|
||||
return tRL + getReadAccessTime();
|
||||
else if (command == Command::ReadA)
|
||||
return tRTP + tRP;
|
||||
else if (command == Command::Write)
|
||||
return tWL + getWriteAccessTime();
|
||||
else if (command == Command::WriteA)
|
||||
return tWL + getWriteAccessTime() + tWR + tRP;
|
||||
else if (command == Command::PrechargeAll)
|
||||
return tRP;
|
||||
else if (command == Command::AutoRefresh)
|
||||
{
|
||||
if (Configuration::getInstance().getRefMode() == 4)
|
||||
return getElementFromMap(refreshTimings,
|
||||
DramExtension::getExtension(payload).getBank()).tRFC4;
|
||||
else if (Configuration::getInstance().getRefMode() == 2)
|
||||
return getElementFromMap(refreshTimings,
|
||||
DramExtension::getExtension(payload).getBank()).tRFC2;
|
||||
else
|
||||
return getElementFromMap(refreshTimings,
|
||||
DramExtension::getExtension(payload).getBank()).tRFC;
|
||||
}
|
||||
else if (command == Command::PDNAX || command == Command::PDNPX || command == Command::SREFX)
|
||||
return clk;
|
||||
else
|
||||
{
|
||||
SC_REPORT_FATAL("getExecutionTime",
|
||||
"command not known or command doesn't have a fixed execution time");
|
||||
return SC_ZERO_TIME;
|
||||
}
|
||||
}
|
||||
@@ -41,6 +41,7 @@
|
||||
#include <systemc.h>
|
||||
#include <map>
|
||||
#include "../../../common/dramExtensions.h"
|
||||
#include "../../Command.h"
|
||||
|
||||
struct RefreshTiming
|
||||
{
|
||||
@@ -57,6 +58,21 @@ struct RefreshTiming
|
||||
|
||||
struct MemSpec
|
||||
{
|
||||
sc_time getWriteAccessTime() const
|
||||
{
|
||||
return clk * (BurstLength / DataRate);
|
||||
}
|
||||
|
||||
sc_time getReadAccessTime() const
|
||||
{
|
||||
return clk * (BurstLength / DataRate);
|
||||
}
|
||||
|
||||
// Returns the minimum execution time for commands that have a variable execution time
|
||||
sc_time getMinExecutionTimeForPowerDownCmd(Command command) const;
|
||||
|
||||
virtual sc_time getExecutionTime(Command command, tlm::tlm_generic_payload &payload) const;
|
||||
|
||||
const std::vector<Bank> &getBanks() const
|
||||
{
|
||||
static std::vector<Bank> banks;
|
||||
@@ -103,7 +119,7 @@ struct MemSpec
|
||||
sc_time tXSR; // min delay to row access command after srefx
|
||||
|
||||
|
||||
sc_time tRP; //precharge-time (pre -> act same bank
|
||||
sc_time tRP; // precharge-time (pre -> act same bank)
|
||||
sc_time tRFC; //min ref->act delay 1X mode
|
||||
sc_time tRFC2; //min ref->act delay 2X mode
|
||||
sc_time tRFC4; //min ref->act delay 4X mode
|
||||
@@ -147,8 +163,8 @@ struct MemSpec
|
||||
double vDD2;
|
||||
|
||||
|
||||
std::map<Bank, RefreshTiming>
|
||||
refreshTimings;//ensure that map is populated completely in memspecloader
|
||||
std::map<Bank, RefreshTiming> refreshTimings;
|
||||
//ensure that map is populated completely in memspecloader
|
||||
|
||||
//act and read/write commands remain for this timespan in history
|
||||
sc_time tActHistory()
|
||||
@@ -194,6 +210,9 @@ struct MemSpecDDR4 : public MemSpec
|
||||
// sc_time tRRD_L;
|
||||
// sc_time tXPDLL;
|
||||
// sc_time tXSDLL;
|
||||
|
||||
// Returns the execution time for commands that have a fixed execution time
|
||||
sc_time getExecutionTime(Command command, tlm::tlm_generic_payload &payload) const;
|
||||
};
|
||||
|
||||
struct MemSpecWideIO : public MemSpec
|
||||
|
||||
@@ -87,7 +87,8 @@ void PowerDownManager::sleep(Bank /*bank*/, sc_time time)
|
||||
}
|
||||
|
||||
Command cmd = IPowerDownManager::getSleepCommand(state);
|
||||
ScheduledCommand pdn(cmd, time, getMinExecutionTimeForPowerDownCmd(cmd),
|
||||
ScheduledCommand pdn(cmd, time,
|
||||
Configuration::getInstance().memSpec->getMinExecutionTimeForPowerDownCmd(cmd),
|
||||
DramExtension::getExtension(powerDownPayloads[Bank(0)]));
|
||||
|
||||
controllerCore.getCommandChecker(cmd).delayToSatisfyConstraints(pdn);
|
||||
@@ -110,7 +111,7 @@ void PowerDownManager::wakeUp(Bank bank, sc_time time)
|
||||
setPowerDownState(PowerDownState::Awake);
|
||||
} else if (isInPowerDown()) { //Request wakes up power down
|
||||
Command cmd = IPowerDownManager::getWakeUpCommand(powerDownState);
|
||||
ScheduledCommand pdn(cmd, time, getExecutionTime(cmd,
|
||||
ScheduledCommand pdn(cmd, time, Configuration::getInstance().memSpec->getExecutionTime(cmd,
|
||||
powerDownPayloads[Bank(0)]),
|
||||
DramExtension::getExtension(powerDownPayloads[Bank(0)]));
|
||||
controllerCore.getCommandChecker(cmd).delayToSatisfyConstraints(pdn);
|
||||
@@ -140,7 +141,7 @@ void PowerDownManager::wakeUpForRefresh(Bank /*bank*/, sc_time time)
|
||||
|
||||
if (isInPowerDown()) {
|
||||
Command cmd = IPowerDownManager::getWakeUpCommand(powerDownState);
|
||||
ScheduledCommand pdn(cmd, time, getExecutionTime(cmd,
|
||||
ScheduledCommand pdn(cmd, time, Configuration::getInstance().memSpec->getExecutionTime(cmd,
|
||||
powerDownPayloads[Bank(0)]),
|
||||
DramExtension::getExtension(powerDownPayloads[Bank(0)]));
|
||||
|
||||
|
||||
@@ -76,7 +76,8 @@ void PowerDownManagerBankwise::sleep(Bank bank, sc_time time)
|
||||
}
|
||||
|
||||
Command cmd = IPowerDownManager::getSleepCommand(state);
|
||||
ScheduledCommand pdn(cmd, time, getMinExecutionTimeForPowerDownCmd(cmd),
|
||||
ScheduledCommand pdn(cmd, time,
|
||||
Configuration::getInstance().memSpec->getMinExecutionTimeForPowerDownCmd(cmd),
|
||||
DramExtension::getExtension(payload));
|
||||
controllerCore.getCommandChecker(cmd).delayToSatisfyConstraints(pdn);
|
||||
|
||||
@@ -103,7 +104,7 @@ void PowerDownManagerBankwise::wakeUp(Bank bank, sc_time time)
|
||||
// Request wake up from power down. A Power Down Exit request will be generated (PDNAX, PDNPX, SREFX).
|
||||
Command pdnExitCmd = IPowerDownManager::getWakeUpCommand(powerDownStates[bank]);
|
||||
// Mount the command to be scheduled
|
||||
ScheduledCommand pdnExit(pdnExitCmd, time, getExecutionTime(pdnExitCmd,
|
||||
ScheduledCommand pdnExit(pdnExitCmd, time, Configuration::getInstance().memSpec->getExecutionTime(pdnExitCmd,
|
||||
powerDownPayloads[bank]), DramExtension::getExtension(powerDownPayloads[bank]));
|
||||
// Ensure that time constraints are respected
|
||||
controllerCore.getCommandChecker(pdnExitCmd).delayToSatisfyConstraints(pdnExit);
|
||||
@@ -140,7 +141,7 @@ void PowerDownManagerBankwise::wakeUpForRefresh(Bank bank, sc_time time)
|
||||
// A Power Down Exit request will be generated (PDNAX, PDNPX, SREFX).
|
||||
Command pdnExitCmd = IPowerDownManager::getWakeUpCommand(powerDownStates[bank]);
|
||||
// Get the execution time for this request
|
||||
sc_time executionTime = getExecutionTime(pdnExitCmd, powerDownPayloads[bank]);
|
||||
sc_time executionTime = Configuration::getInstance().memSpec->getExecutionTime(pdnExitCmd, powerDownPayloads[bank]);
|
||||
// Mount the command to be scheduled
|
||||
ScheduledCommand pdnExit(pdnExitCmd, time, executionTime,
|
||||
DramExtension::getExtension(powerDownPayloads[bank]));
|
||||
|
||||
@@ -91,7 +91,8 @@ void PowerDownManagerTimeout::sleep(Bank /*bank*/, sc_time time)
|
||||
} else { // PowerDownMode == TimeoutSREF
|
||||
if (!controllerCore.state->rowBufferStates->allRowBuffersAreClosed()) {
|
||||
ScheduledCommand prechargeAllMaster(Command::PrechargeAll, time,
|
||||
getExecutionTime(Command::PrechargeAll, powerDownPayloads[Bank(0)]),
|
||||
Configuration::getInstance().memSpec->getExecutionTime(
|
||||
Command::PrechargeAll, powerDownPayloads[Bank(0)]),
|
||||
DramExtension::getExtension(powerDownPayloads[Bank(0)]));
|
||||
|
||||
controllerCore.getCommandChecker(
|
||||
@@ -116,7 +117,8 @@ void PowerDownManagerTimeout::sleep(Bank /*bank*/, sc_time time)
|
||||
}
|
||||
|
||||
Command cmd = IPowerDownManager::getSleepCommand(newState);
|
||||
ScheduledCommand pdn(cmd, time, getMinExecutionTimeForPowerDownCmd(cmd),
|
||||
ScheduledCommand pdn(cmd, time,
|
||||
Configuration::getInstance().memSpec->getMinExecutionTimeForPowerDownCmd(cmd),
|
||||
DramExtension::getExtension(powerDownPayloads[Bank(0)]));
|
||||
|
||||
controllerCore.getCommandChecker(cmd).delayToSatisfyConstraints(pdn);
|
||||
|
||||
@@ -91,7 +91,7 @@ void PowerDownManagerTimeoutBankwise::sleep(Bank bank, sc_time time)
|
||||
} else { // PowerDownMode == TimeoutSREF
|
||||
if (controllerCore.state->rowBufferStates->rowBufferIsOpen(bank)) {
|
||||
ScheduledCommand precharge(Command::Precharge, time,
|
||||
getExecutionTime(Command::Precharge, powerDownPayloads[bank]),
|
||||
Configuration::getInstance().memSpec->getExecutionTime(Command::Precharge, powerDownPayloads[bank]),
|
||||
DramExtension::getExtension(powerDownPayloads[bank]));
|
||||
|
||||
controllerCore.getCommandChecker(Command::Precharge).delayToSatisfyConstraints(
|
||||
@@ -111,7 +111,8 @@ void PowerDownManagerTimeoutBankwise::sleep(Bank bank, sc_time time)
|
||||
|
||||
|
||||
Command cmd = IPowerDownManager::getSleepCommand(newState);
|
||||
ScheduledCommand pdn(cmd, time, getMinExecutionTimeForPowerDownCmd(cmd),
|
||||
ScheduledCommand pdn(cmd, time,
|
||||
Configuration::getInstance().memSpec->getMinExecutionTimeForPowerDownCmd(cmd),
|
||||
DramExtension::getExtension(powerDownPayloads[bank]));
|
||||
|
||||
controllerCore.getCommandChecker(cmd).delayToSatisfyConstraints(pdn);
|
||||
|
||||
@@ -45,7 +45,7 @@
|
||||
using namespace tlm;
|
||||
|
||||
RefreshManager::RefreshManager(sc_module_name,
|
||||
ControllerCore &controller) : controllerCore(controller),
|
||||
ControllerCore &controller) : controllerCore(controller),
|
||||
timing(controller.config.memSpec->refreshTimings[Bank(0)])
|
||||
{
|
||||
auto m = controllerCore.config.getRefMode();
|
||||
@@ -99,7 +99,8 @@ bool RefreshManager::doRefresh(tlm::tlm_generic_payload &payload, sc_time time)
|
||||
if (!controllerCore.state->rowBufferStates->allRowBuffersAreClosed()) {
|
||||
pre = true;
|
||||
ScheduledCommand prechargeAllMaster(Command::PrechargeAll, time,
|
||||
getExecutionTime(Command::PrechargeAll, refreshPayloads[Bank(0)]),
|
||||
Configuration::getInstance().memSpec->getExecutionTime(
|
||||
Command::PrechargeAll, refreshPayloads[Bank(0)]),
|
||||
refreshPayloads[Bank(0)]);
|
||||
controllerCore.getCommandChecker(
|
||||
Command::PrechargeAll).delayToSatisfyConstraints(prechargeAllMaster);
|
||||
@@ -116,7 +117,8 @@ bool RefreshManager::doRefresh(tlm::tlm_generic_payload &payload, sc_time time)
|
||||
|
||||
//Otherwise just the AutoRefresh command is scheduled.
|
||||
ScheduledCommand refreshAllMaster(Command::AutoRefresh, time,
|
||||
getExecutionTime(Command::AutoRefresh, refreshPayloads[Bank(0)]),
|
||||
Configuration::getInstance().memSpec->getExecutionTime(
|
||||
Command::AutoRefresh, refreshPayloads[Bank(0)]),
|
||||
DramExtension::getExtension(refreshPayloads[Bank(0)]));
|
||||
controllerCore.getCommandChecker(
|
||||
Command::AutoRefresh).delayToSatisfyConstraints(refreshAllMaster);
|
||||
|
||||
@@ -102,7 +102,8 @@ bool RefreshManagerBankwise::doRefresh(tlm::tlm_generic_payload &payload,
|
||||
extension.getBank())) {
|
||||
pre = true;
|
||||
ScheduledCommand precharge(Command::Precharge, time,
|
||||
getExecutionTime(Command::Precharge, refreshPayload), extension);
|
||||
Configuration::getInstance().memSpec->getExecutionTime(
|
||||
Command::Precharge, refreshPayload), extension);
|
||||
controllerCore.getCommandChecker(Command::Precharge).delayToSatisfyConstraints(
|
||||
precharge);
|
||||
controllerCore.state->change(precharge);
|
||||
@@ -110,7 +111,8 @@ bool RefreshManagerBankwise::doRefresh(tlm::tlm_generic_payload &payload,
|
||||
}
|
||||
|
||||
ScheduledCommand refresh(Command::AutoRefresh, time,
|
||||
getExecutionTime(Command::AutoRefresh, refreshPayload), extension);
|
||||
Configuration::getInstance().memSpec->getExecutionTime(
|
||||
Command::AutoRefresh, refreshPayload), extension);
|
||||
controllerCore.getCommandChecker(
|
||||
Command::AutoRefresh).delayToSatisfyConstraints(refresh);
|
||||
controllerCore.state->change(refresh);
|
||||
|
||||
@@ -38,6 +38,7 @@
|
||||
#include "../timingCalculations.h"
|
||||
#include "../../../common/utils.h"
|
||||
#include "../configuration/Configuration.h"
|
||||
//#include "../configuration/MemSpec.h"
|
||||
|
||||
bool ScheduledCommand::isNoCommand() const
|
||||
{
|
||||
@@ -131,9 +132,10 @@ TimeInterval ScheduledCommand::getIntervalOnDataStrobe() const
|
||||
|
||||
if (getCommand() == Command::Read || getCommand() == Command::ReadA) {
|
||||
return TimeInterval(getStart() + timings->tRL,
|
||||
getStart() + timings->tRL + getReadAccessTime());
|
||||
getStart() + timings->tRL + timings->getReadAccessTime());
|
||||
} else {
|
||||
return TimeInterval(getStart() + timings->tWL - timings->clk / 2,
|
||||
getStart() + timings->tWL + getWriteAccessTime() - timings->clk / 2);
|
||||
getStart() + timings->tWL + timings->getWriteAccessTime()
|
||||
- timings->clk / 2);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -59,8 +59,8 @@ void ActBChecker::delayToSatisfyConstraints(ScheduledCommand &cmd) const
|
||||
config.memSpec->tRTP + config.memSpec->tRP);
|
||||
} else if (lcb.getCommand() == Command::WriteA) {
|
||||
cmd.establishMinDistanceFromStart(lcb.getStart(),
|
||||
config.memSpec->tWL + getWriteAccessTime() + config.memSpec->tWR +
|
||||
config.memSpec->tRP);
|
||||
config.memSpec->tWL + config.memSpec->getWriteAccessTime()
|
||||
+ config.memSpec->tWR + config.memSpec->tRP);
|
||||
} else if (lcb.getCommand() == Command::AutoRefresh) {
|
||||
auto m = Configuration::getInstance().getRefMode();
|
||||
if (m == 4)
|
||||
|
||||
@@ -62,8 +62,8 @@ void ActivateChecker::delayToSatisfyConstraints(ScheduledCommand &command) const
|
||||
config.memSpec->tRTP + config.memSpec->tRP);
|
||||
} else if (lastCommandOnBank.getCommand() == Command::WriteA) {
|
||||
command.establishMinDistanceFromStart(lastCommandOnBank.getStart(),
|
||||
config.memSpec->tWL + getWriteAccessTime() + config.memSpec->tWR +
|
||||
config.memSpec->tRP);
|
||||
config.memSpec->tWL + config.memSpec->getWriteAccessTime()
|
||||
+ config.memSpec->tWR + config.memSpec->tRP);
|
||||
} else if (lastCommandOnBank.getCommand() == Command::AutoRefresh) {
|
||||
auto m = Configuration::getInstance().getRefMode();
|
||||
if (m == 4)
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
#include "../../../../common/DebugManager.h"
|
||||
#include "../../../Command.h"
|
||||
#include "../../../../common/utils.h"
|
||||
//#include "../../configuration/MemSpec.h"
|
||||
|
||||
using namespace std;
|
||||
|
||||
@@ -35,7 +36,7 @@ void CheckerDDR3::delayToSatisfyConstraints(ScheduledCommand &command) const
|
||||
break;
|
||||
case Command::WriteA:
|
||||
command.establishMinDistanceFromStart(lastCommandOnBank.getStart(),
|
||||
memSpec->tWL + getWriteAccessTime()
|
||||
memSpec->tWL + memSpec->getWriteAccessTime()
|
||||
+ memSpec->tWR + memSpec->tRP);
|
||||
break;
|
||||
case Command::PDNPX:
|
||||
@@ -148,7 +149,7 @@ void CheckerDDR3::delayToSatisfyConstraints(ScheduledCommand &command) const
|
||||
case Command::Write:
|
||||
command.establishMinDistanceFromStart(lastCommandOnBank.getStart(),
|
||||
memSpec->tWL + memSpec->tWR
|
||||
+ getWriteAccessTime());
|
||||
+ memSpec->getWriteAccessTime());
|
||||
break;
|
||||
case Command::PDNAX:
|
||||
command.establishMinDistanceFromStart(lastCommandOnBank.getStart(),
|
||||
@@ -188,12 +189,12 @@ void CheckerDDR3::delayToSatisfyConstraints(ScheduledCommand &command) const
|
||||
break;
|
||||
case Command::Write:
|
||||
command.establishMinDistanceFromStart(lastCommand.getStart(),
|
||||
memSpec->tWL + getWriteAccessTime()
|
||||
memSpec->tWL + memSpec->getWriteAccessTime()
|
||||
+ memSpec->tWR);
|
||||
break;
|
||||
case Command::WriteA:
|
||||
command.establishMinDistanceFromStart(lastCommand.getStart(),
|
||||
memSpec->tWL + getWriteAccessTime()
|
||||
memSpec->tWL + memSpec->getWriteAccessTime()
|
||||
+ memSpec->tWR + memSpec->tRP);
|
||||
break;
|
||||
case Command::ReadA:
|
||||
@@ -239,17 +240,17 @@ void CheckerDDR3::delayToSatisfyConstraints(ScheduledCommand &command) const
|
||||
case Command::Read:
|
||||
case Command::ReadA:
|
||||
command.establishMinDistanceFromStart(lastCommandOnBank.getStart(),
|
||||
memSpec->tRL + getReadAccessTime()
|
||||
memSpec->tRL + memSpec->getReadAccessTime()
|
||||
+ memSpec->clk);
|
||||
break;
|
||||
case Command::Write:
|
||||
command.establishMinDistanceFromStart(lastCommandOnBank.getStart(),
|
||||
memSpec->tWL + getWriteAccessTime()
|
||||
memSpec->tWL + memSpec->getWriteAccessTime()
|
||||
+ memSpec->tWR);
|
||||
break;
|
||||
case Command::WriteA:
|
||||
command.establishMinDistanceFromStart(lastCommandOnBank.getStart(),
|
||||
memSpec->tWL + getWriteAccessTime()
|
||||
memSpec->tWL + memSpec->getWriteAccessTime()
|
||||
+ memSpec->tWR + memSpec->clk);
|
||||
break;
|
||||
case Command::AutoRefresh:
|
||||
@@ -311,7 +312,7 @@ void CheckerDDR3::delayToSatisfyConstraints(ScheduledCommand &command) const
|
||||
break;
|
||||
case Command::WriteA:
|
||||
command.establishMinDistanceFromStart(lastCommandOnBank.getStart(),
|
||||
memSpec->tWL + getWriteAccessTime()
|
||||
memSpec->tWL + memSpec->getWriteAccessTime()
|
||||
+ memSpec->tWR + memSpec->tRP);
|
||||
break;
|
||||
case Command::AutoRefresh:
|
||||
@@ -358,7 +359,7 @@ void CheckerDDR3::delayToSatisfyConstraints(ScheduledCommand &command) const
|
||||
break;
|
||||
case Command::WriteA:
|
||||
command.establishMinDistanceFromStart(lastCommand.getStart(),
|
||||
memSpec->tWL + getWriteAccessTime()
|
||||
memSpec->tWL + memSpec->getWriteAccessTime()
|
||||
+ memSpec->tWR + memSpec->tRP);
|
||||
break;
|
||||
case Command::AutoRefresh:
|
||||
@@ -489,7 +490,7 @@ sc_time CheckerDDR3::writeToRead(ScheduledCommand &write, ScheduledCommand &read
|
||||
sc_assert(read.getCommand() == Command::Read || read.getCommand() == Command::ReadA);
|
||||
sc_assert(write.getCommand() == Command::Write || write.getCommand() == Command::WriteA);
|
||||
|
||||
return memSpec->tWL + getWriteAccessTime() + memSpec->tWTR;
|
||||
return memSpec->tWL + memSpec->getWriteAccessTime() + memSpec->tWTR;
|
||||
}
|
||||
|
||||
/* CAS-CAS */
|
||||
@@ -499,12 +500,12 @@ sc_time CheckerDDR3::CasToCas(ScheduledCommand &firstCAS, ScheduledCommand &seco
|
||||
if (firstCAS.getCommand() == Command::Read || firstCAS.getCommand() == Command::ReadA)
|
||||
{
|
||||
if (secondCAS.getCommand() == Command::Read || secondCAS.getCommand() == Command::ReadA)
|
||||
return std::max(memSpec->tCCD, getReadAccessTime());
|
||||
return std::max(memSpec->tCCD, memSpec->getReadAccessTime());
|
||||
}
|
||||
else if (firstCAS.getCommand() == Command::Write || firstCAS.getCommand() == Command::WriteA)
|
||||
{
|
||||
if (secondCAS.getCommand() == Command::Write || secondCAS.getCommand() == Command::WriteA)
|
||||
return std::max(memSpec->tCCD, getWriteAccessTime());
|
||||
return std::max(memSpec->tCCD, memSpec->getWriteAccessTime());
|
||||
}
|
||||
SC_REPORT_FATAL("CasToCas", "Exception reached");
|
||||
return SC_ZERO_TIME;
|
||||
@@ -558,5 +559,5 @@ sc_time CheckerDDR3::readToWrite(ScheduledCommand &read, ScheduledCommand &write
|
||||
sc_assert(write.getCommand() == Command::Write
|
||||
|| write.getCommand() == Command::WriteA);
|
||||
|
||||
return memSpec->tRL + getReadAccessTime() - memSpec->tWL + memSpec->clk * 2;
|
||||
return memSpec->tRL + memSpec->getReadAccessTime() - memSpec->tWL + memSpec->clk * 2;
|
||||
}
|
||||
|
||||
@@ -47,11 +47,11 @@ sc_time PowerDownChecker::getTimeConstraintToEnterPowerDown(Command lastCmd,
|
||||
sc_time constraint;
|
||||
|
||||
if (lastCmd == Command::Read || lastCmd == Command::ReadA) {
|
||||
constraint = config.memSpec->tRL + getReadAccessTime() + config.memSpec->clk;
|
||||
constraint = config.memSpec->tRL + config.memSpec->getReadAccessTime() + config.memSpec->clk;
|
||||
} else if (lastCmd == Command::Write) {
|
||||
constraint = config.memSpec->tWL + getWriteAccessTime() + config.memSpec->tWR;
|
||||
constraint = config.memSpec->tWL + config.memSpec->getWriteAccessTime() + config.memSpec->tWR;
|
||||
} else if (lastCmd == Command::WriteA) {
|
||||
constraint = config.memSpec->tWL + getWriteAccessTime() + config.memSpec->tWR +
|
||||
constraint = config.memSpec->tWL + config.memSpec->getWriteAccessTime() + config.memSpec->tWR +
|
||||
config.memSpec->clk;
|
||||
} else if (lastCmd == Command::AutoRefresh) {
|
||||
auto m = Configuration::getInstance().getRefMode();
|
||||
|
||||
@@ -55,7 +55,7 @@ void PreBChecker::delayToSatisfyConstraints(ScheduledCommand &cmd) const
|
||||
cmd.establishMinDistanceFromStart(lastCmd.getStart(), config.memSpec->tRTP);
|
||||
} else if (lastCmd.getCommand() == Command::Write) {
|
||||
cmd.establishMinDistanceFromStart(lastCmd.getStart(),
|
||||
config.memSpec->tWL + getWriteAccessTime() + config.memSpec->tWR);
|
||||
config.memSpec->tWL + config.memSpec->getWriteAccessTime() + config.memSpec->tWR);
|
||||
} else if (lastCmd.getCommand() == Command::PDNAX) {
|
||||
cmd.establishMinDistanceFromStart(lastCmd.getStart(), config.memSpec->tXP);
|
||||
} else {
|
||||
|
||||
@@ -64,10 +64,10 @@ const
|
||||
config.memSpec->tRTP + config.memSpec->tRP);
|
||||
} else if (lastCommand.getCommand() == Command::Write) {
|
||||
command.establishMinDistanceFromStart(lastCommand.getStart(),
|
||||
config.memSpec->tWL + getWriteAccessTime() + config.memSpec->tWR);
|
||||
config.memSpec->tWL + config.memSpec->getWriteAccessTime() + config.memSpec->tWR);
|
||||
} else if (lastCommand.getCommand() == Command::WriteA) {
|
||||
command.establishMinDistanceFromStart(lastCommand.getStart(),
|
||||
config.memSpec->tWL + getWriteAccessTime() + config.memSpec->tWR +
|
||||
config.memSpec->tWL + config.memSpec->getWriteAccessTime() + config.memSpec->tWR +
|
||||
config.memSpec->tRP);
|
||||
} else if (lastCommand.getCommand() == Command::AutoRefresh) {
|
||||
auto m = Configuration::getInstance().getRefMode();
|
||||
|
||||
@@ -64,7 +64,7 @@ const
|
||||
config.memSpec->tRTP);
|
||||
} else if (lastCommand.getCommand() == Command::Write) {
|
||||
command.establishMinDistanceFromStart(lastCommand.getStart(),
|
||||
config.memSpec->tWL + getWriteAccessTime() + config.memSpec->tWR);
|
||||
config.memSpec->tWL + config.memSpec->getWriteAccessTime() + config.memSpec->tWR);
|
||||
|
||||
} else if (lastCommand.getCommand() == Command::PDNAX) {
|
||||
command.establishMinDistanceFromStart(lastCommand.getStart(),
|
||||
|
||||
@@ -126,7 +126,7 @@ sc_time ReadChecker::readToRead(ScheduledCommand &firstRead,
|
||||
MemSpec *config = Configuration::getInstance().memSpec;
|
||||
sc_time tCCD = (firstRead.getBankGroup() == secondRead.getBankGroup()) ?
|
||||
config->tCCD_L : config->tCCD_S;
|
||||
return max(tCCD, getReadAccessTime());
|
||||
return max(tCCD, config->getReadAccessTime());
|
||||
}
|
||||
|
||||
sc_time ReadChecker::writeToRead(ScheduledCommand &write,
|
||||
@@ -140,6 +140,6 @@ sc_time ReadChecker::writeToRead(ScheduledCommand &write,
|
||||
MemSpec *config = Configuration::getInstance().memSpec;
|
||||
sc_time tWTR = (write.getBankGroup() == read.getBankGroup()) ? config->tWTR_L :
|
||||
config->tWTR_S;
|
||||
return config->tWL + getWriteAccessTime() + tWTR;
|
||||
return config->tWL + config->getWriteAccessTime() + tWTR;
|
||||
}
|
||||
|
||||
|
||||
@@ -56,7 +56,7 @@ void RefreshChecker::delayToSatisfyConstraints(ScheduledCommand &command) const
|
||||
config.memSpec->tRTP + config.memSpec->tRP);
|
||||
} else if (lastCommandOnBank.getCommand() == Command::WriteA) {
|
||||
command.establishMinDistanceFromStart(lastCommandOnBank.getStart(),
|
||||
config.memSpec->tWL + getWriteAccessTime() + config.memSpec->tWR +
|
||||
config.memSpec->tWL + config.memSpec->getWriteAccessTime() + config.memSpec->tWR +
|
||||
config.memSpec->tRP);
|
||||
} else if (lastCommandOnBank.getCommand() == Command::PDNPX
|
||||
|| lastCommandOnBank.getCommand() == Command::PDNAX) {
|
||||
@@ -88,7 +88,7 @@ void RefreshChecker::delayToSatisfyConstraints(ScheduledCommand &command) const
|
||||
config.memSpec->tRTP + config.memSpec->tRP);
|
||||
} else if (lastCommand.getCommand() == Command::WriteA) {
|
||||
command.establishMinDistanceFromStart(lastCommand.getStart(),
|
||||
config.memSpec->tWL + getWriteAccessTime() + config.memSpec->tWR +
|
||||
config.memSpec->tWL + config.memSpec->getWriteAccessTime() + config.memSpec->tWR +
|
||||
config.memSpec->tRP);
|
||||
} else if (lastCommand.getCommand() == Command::PDNAX
|
||||
|| lastCommand.getCommand() == Command::PDNPX) {
|
||||
|
||||
@@ -117,7 +117,7 @@ sc_time WriteChecker::writeToWrite(ScheduledCommand &firstWrite,
|
||||
MemSpec *config = Configuration::getInstance().memSpec;
|
||||
sc_time tCCD = (firstWrite.getBankGroup() == secondWrite.getBankGroup()) ?
|
||||
config->tCCD_L : config->tCCD_S;
|
||||
return max(tCCD, getWriteAccessTime());
|
||||
return max(tCCD, config->getWriteAccessTime());
|
||||
}
|
||||
|
||||
sc_time WriteChecker::readToWrite(ScheduledCommand &read __attribute__((
|
||||
@@ -129,6 +129,6 @@ sc_time WriteChecker::readToWrite(ScheduledCommand &read __attribute__((
|
||||
|| write.getCommand() == Command::WriteA);
|
||||
|
||||
MemSpec *config = Configuration::getInstance().memSpec;
|
||||
return config->tRL + getReadAccessTime() - config->tWL + config->clk * 2;
|
||||
return config->tRL + config->getReadAccessTime() - config->tWL + config->clk * 2;
|
||||
}
|
||||
|
||||
|
||||
@@ -66,87 +66,9 @@ const sc_time clkAlign(sc_time time, Alignment alignment)
|
||||
return floor(time / clk) * clk;
|
||||
}
|
||||
|
||||
// Returns the execution time for commands that have a fixed execution time
|
||||
sc_time getExecutionTime(Command command, tlm::tlm_generic_payload &payload)
|
||||
{
|
||||
MemSpec *config = Configuration::getInstance().memSpec;
|
||||
|
||||
if (command == Command::PreB) {
|
||||
return Configuration::getInstance().getTrpb();
|
||||
} else if (command == Command::Precharge || command == Command::PrechargeAll) {
|
||||
return config->tRP;
|
||||
} else if (command == Command::ActB) {
|
||||
return config->tRCD;
|
||||
} else if (command == Command::Activate) {
|
||||
return config->tRCD;
|
||||
} else if (command == Command::Read) {
|
||||
return config->tRL + getReadAccessTime();
|
||||
} else if (command == Command::ReadA) {
|
||||
return config->tRTP + config->tRP;
|
||||
} else if (command == Command::Write) {
|
||||
return config->tWL + getWriteAccessTime();
|
||||
} else if (command == Command::WriteA) {
|
||||
return config->tWL + getWriteAccessTime() + config->tWR + config->tRP;
|
||||
} else if (command == Command::PrechargeAll) {
|
||||
return config->tRP;
|
||||
} else if (command == Command::AutoRefresh) {
|
||||
if (Configuration::getInstance().getRefMode() == 4)
|
||||
return getElementFromMap(config->refreshTimings,
|
||||
DramExtension::getExtension(payload).getBank()).tRFC4;
|
||||
else if (Configuration::getInstance().getRefMode() == 2)
|
||||
return getElementFromMap(config->refreshTimings,
|
||||
DramExtension::getExtension(payload).getBank()).tRFC2;
|
||||
else
|
||||
return getElementFromMap(config->refreshTimings,
|
||||
DramExtension::getExtension(payload).getBank()).tRFC;
|
||||
} else if (command == Command::PDNAX || command == Command::PDNPX
|
||||
|| command == Command::SREFX) {
|
||||
return config->clk;
|
||||
} else {
|
||||
SC_REPORT_FATAL("getExecutionTime",
|
||||
"command not known or command doesn't have a fixed execution time");
|
||||
return SC_ZERO_TIME;
|
||||
}
|
||||
}
|
||||
|
||||
// Returns the minimum execution time for commands that have a variable execution time
|
||||
sc_time getMinExecutionTimeForPowerDownCmd(Command command)
|
||||
{
|
||||
MemSpec *config = Configuration::getInstance().memSpec;
|
||||
if (command == Command::PDNA || command == Command::PDNP) {
|
||||
return config->tCKE;
|
||||
} else if (command == Command::SREF) {
|
||||
return config->tCKESR;
|
||||
} else {
|
||||
SC_REPORT_FATAL("getMinimalExecutionTime",
|
||||
"command is not know or command has a fixed execution time");
|
||||
return SC_ZERO_TIME;
|
||||
}
|
||||
}
|
||||
|
||||
bool isClkAligned(sc_time time, sc_time clk)
|
||||
{
|
||||
return !((time / clk) - ceil(time / clk));
|
||||
}
|
||||
|
||||
|
||||
sc_time getReadAccessTime()
|
||||
{
|
||||
Configuration &config = Configuration::getInstance();
|
||||
return (config.memSpec->BurstLength / config.memSpec->DataRate) *
|
||||
config.memSpec->clk;
|
||||
}
|
||||
|
||||
sc_time getWriteAccessTime()
|
||||
{
|
||||
Configuration &config = Configuration::getInstance();
|
||||
|
||||
if (config.memSpec->DataRate == 1) {
|
||||
return config.memSpec->clk * (config.memSpec->BurstLength);
|
||||
} else {
|
||||
return config.memSpec->clk * (config.memSpec->BurstLength /
|
||||
config.memSpec->DataRate);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -42,11 +42,6 @@
|
||||
#include "../../common/dramExtensions.h"
|
||||
#include "../Command.h"
|
||||
|
||||
sc_time getMinExecutionTimeForPowerDownCmd(Command command);
|
||||
sc_time getExecutionTime(Command command, tlm::tlm_generic_payload &payload);
|
||||
|
||||
sc_time getReadAccessTime();
|
||||
sc_time getWriteAccessTime();
|
||||
sc_time getDelayToMeetConstraint(sc_time previous, sc_time start,
|
||||
sc_time constraint);
|
||||
|
||||
|
||||
@@ -42,7 +42,7 @@
|
||||
#include <string>
|
||||
#include <systemc.h>
|
||||
|
||||
#include "RecordableDram.h"
|
||||
#include "DramRecordable.h"
|
||||
#include "Arbiter.h"
|
||||
#include "TraceGenerator.h"
|
||||
#include "ReorderBuffer.h"
|
||||
|
||||
@@ -202,40 +202,41 @@ Dram::~Dram()
|
||||
tlm_sync_enum Dram::nb_transport_fw(tlm_generic_payload &payload,
|
||||
tlm_phase &phase, sc_time &delay)
|
||||
{
|
||||
MemSpec *memSpec = Configuration::getInstance().memSpec;
|
||||
|
||||
unsigned int bank = DramExtension::getExtension(payload).getBank().ID();
|
||||
|
||||
// This is only needed for power simulation:
|
||||
unsigned long long cycle = sc_time_stamp().value() /
|
||||
Configuration::getInstance().memSpec->clk.value();
|
||||
unsigned long long cycle = sc_time_stamp().value() / memSpec->clk.value();
|
||||
|
||||
if (phase == BEGIN_PREB)
|
||||
{
|
||||
DRAMPower->doCommand(MemCommand::PREB, bank, cycle);
|
||||
sendToController(payload, END_PREB, delay + getExecutionTime(Command::PreB,
|
||||
sendToController(payload, END_PREB, delay + memSpec->getExecutionTime(Command::PreB,
|
||||
payload));
|
||||
}
|
||||
else if (phase == BEGIN_PRE)
|
||||
{
|
||||
DRAMPower->doCommand(MemCommand::PRE, bank, cycle);
|
||||
sendToController(payload, END_PRE, delay + getExecutionTime(Command::Precharge,
|
||||
sendToController(payload, END_PRE, delay + memSpec->getExecutionTime(Command::Precharge,
|
||||
payload));
|
||||
}
|
||||
else if (phase == BEGIN_PRE_ALL)
|
||||
{
|
||||
DRAMPower->doCommand(MemCommand::PREA, bank, cycle);
|
||||
sendToController(payload, END_PRE_ALL,
|
||||
delay + getExecutionTime(Command::PrechargeAll, payload));
|
||||
delay + memSpec->getExecutionTime(Command::PrechargeAll, payload));
|
||||
}
|
||||
else if (phase == BEGIN_ACTB)
|
||||
{
|
||||
DRAMPower->doCommand(MemCommand::ACTB, bank, cycle);
|
||||
sendToController(payload, END_ACTB, delay + getExecutionTime(Command::ActB,
|
||||
sendToController(payload, END_ACTB, delay + memSpec->getExecutionTime(Command::ActB,
|
||||
payload));
|
||||
}
|
||||
else if (phase == BEGIN_ACT)
|
||||
{
|
||||
DRAMPower->doCommand(MemCommand::ACT, bank, cycle);
|
||||
sendToController(payload, END_ACT, delay + getExecutionTime(Command::Activate,
|
||||
sendToController(payload, END_ACT, delay + memSpec->getExecutionTime(Command::Activate,
|
||||
payload));
|
||||
}
|
||||
else if (phase == BEGIN_WR)
|
||||
@@ -247,7 +248,7 @@ tlm_sync_enum Dram::nb_transport_fw(tlm_generic_payload &payload,
|
||||
unsigned char *phyAddr = memory + payload.get_address();
|
||||
memcpy(phyAddr, payload.get_data_ptr(), payload.get_data_length());
|
||||
}
|
||||
sendToController(payload, END_WR, delay + getExecutionTime(Command::Write,
|
||||
sendToController(payload, END_WR, delay + memSpec->getExecutionTime(Command::Write,
|
||||
payload));
|
||||
}
|
||||
else if (phase == BEGIN_RD)
|
||||
@@ -259,7 +260,7 @@ tlm_sync_enum Dram::nb_transport_fw(tlm_generic_payload &payload,
|
||||
unsigned char *phyAddr = memory + payload.get_address();
|
||||
memcpy(payload.get_data_ptr(), phyAddr, payload.get_data_length());
|
||||
}
|
||||
sendToController(payload, END_RD, delay + getExecutionTime(Command::Read,
|
||||
sendToController(payload, END_RD, delay + memSpec->getExecutionTime(Command::Read,
|
||||
payload));
|
||||
}
|
||||
else if (phase == BEGIN_WRA)
|
||||
@@ -271,7 +272,7 @@ tlm_sync_enum Dram::nb_transport_fw(tlm_generic_payload &payload,
|
||||
unsigned char *phyAddr = memory + payload.get_address();
|
||||
memcpy(phyAddr, payload.get_data_ptr(), payload.get_data_length());
|
||||
}
|
||||
sendToController(payload, END_WRA, delay + getExecutionTime(Command::WriteA,
|
||||
sendToController(payload, END_WRA, delay + memSpec->getExecutionTime(Command::WriteA,
|
||||
payload));
|
||||
}
|
||||
else if (phase == BEGIN_RDA)
|
||||
@@ -283,20 +284,20 @@ tlm_sync_enum Dram::nb_transport_fw(tlm_generic_payload &payload,
|
||||
unsigned char *phyAddr = memory + payload.get_address();
|
||||
memcpy(payload.get_data_ptr(), phyAddr, payload.get_data_length());
|
||||
}
|
||||
sendToController(payload, END_RDA, delay + getExecutionTime(Command::ReadA,
|
||||
sendToController(payload, END_RDA, delay + memSpec->getExecutionTime(Command::ReadA,
|
||||
payload));
|
||||
}
|
||||
else if (phase == BEGIN_REFA)
|
||||
{
|
||||
DRAMPower->doCommand(MemCommand::REF, bank, cycle);
|
||||
sendToController(payload, END_REFA,
|
||||
delay + getExecutionTime(Command::AutoRefresh, payload));
|
||||
delay + memSpec->getExecutionTime(Command::AutoRefresh, payload));
|
||||
}
|
||||
else if (phase == BEGIN_REFB)
|
||||
{
|
||||
DRAMPower->doCommand(MemCommand::REFB, bank, cycle);
|
||||
sendToController(payload, END_REFB,
|
||||
delay + getExecutionTime(Command::AutoRefresh, payload));
|
||||
delay + memSpec->getExecutionTime(Command::AutoRefresh, payload));
|
||||
}
|
||||
// Powerdown phases have to be started and ended by the controller, because they do not have a fixed length
|
||||
else if (phase == BEGIN_PDNA)
|
||||
|
||||
@@ -65,17 +65,18 @@ template<class BaseDram>
|
||||
tlm_sync_enum DramRecordable<BaseDram>::nb_transport_fw(tlm_generic_payload &payload,
|
||||
tlm_phase &phase, sc_time &delay)
|
||||
{
|
||||
MemSpec *memSpec = Configuration::getInstance().memSpec;
|
||||
// Recording time used by the traceAnalyzer
|
||||
sc_time recTime = sc_time_stamp() + delay;
|
||||
|
||||
// These are terminating phases recorded by the DRAM. The execution
|
||||
// time of the related command must be taken into consideration.
|
||||
if (phase == END_PDNA || phase == END_PDNAB)
|
||||
recTime += getExecutionTime(Command::PDNAX, payload);
|
||||
recTime += memSpec->getExecutionTime(Command::PDNAX, payload);
|
||||
else if (phase == END_PDNP || phase == END_PDNPB)
|
||||
recTime += getExecutionTime(Command::PDNPX, payload);
|
||||
recTime += memSpec->getExecutionTime(Command::PDNPX, payload);
|
||||
else if (phase == END_SREF || phase == END_SREFB)
|
||||
recTime += getExecutionTime(Command::SREFX, payload);
|
||||
recTime += memSpec->getExecutionTime(Command::SREFX, payload);
|
||||
|
||||
unsigned int thr = DramExtension::getExtension(payload).getThread().ID();
|
||||
unsigned int ch = DramExtension::getExtension(payload).getChannel().ID();
|
||||
|
||||
@@ -40,7 +40,6 @@
|
||||
#include <tlm>
|
||||
#include "DramDDR3.h"
|
||||
#include "DramDDR4.h"
|
||||
#include "RecordableDram.h"
|
||||
#include "../common/TlmRecorder.h"
|
||||
|
||||
using namespace tlm;
|
||||
|
||||
@@ -72,6 +72,8 @@ DramWideIO::~DramWideIO()
|
||||
tlm_sync_enum DramWideIO::nb_transport_fw(tlm_generic_payload &payload,
|
||||
tlm_phase &phase, sc_time &delay)
|
||||
{
|
||||
MemSpec *memSpec = Configuration::getInstance().memSpec;
|
||||
|
||||
unsigned int bank = DramExtension::getExtension(payload).getBank().ID();
|
||||
|
||||
// This is only needed for power simulation:
|
||||
@@ -81,25 +83,25 @@ tlm_sync_enum DramWideIO::nb_transport_fw(tlm_generic_payload &payload,
|
||||
if (phase == BEGIN_PREB)
|
||||
{
|
||||
DRAMPower->doCommand(MemCommand::PREB, bank, cycle);
|
||||
sendToController(payload, END_PREB, delay + getExecutionTime(Command::PreB,
|
||||
sendToController(payload, END_PREB, delay + memSpec->getExecutionTime(Command::PreB,
|
||||
payload));
|
||||
}
|
||||
else if (phase == BEGIN_PRE)
|
||||
{
|
||||
DRAMPower->doCommand(MemCommand::PRE, bank, cycle);
|
||||
sendToController(payload, END_PRE, delay + getExecutionTime(Command::Precharge,
|
||||
sendToController(payload, END_PRE, delay + memSpec->getExecutionTime(Command::Precharge,
|
||||
payload));
|
||||
}
|
||||
else if (phase == BEGIN_PRE_ALL)
|
||||
{
|
||||
DRAMPower->doCommand(MemCommand::PREA, bank, cycle);
|
||||
sendToController(payload, END_PRE_ALL,
|
||||
delay + getExecutionTime(Command::PrechargeAll, payload));
|
||||
delay + memSpec->getExecutionTime(Command::PrechargeAll, payload));
|
||||
}
|
||||
else if (phase == BEGIN_ACTB)
|
||||
{
|
||||
DRAMPower->doCommand(MemCommand::ACTB, bank, cycle);
|
||||
sendToController(payload, END_ACTB, delay + getExecutionTime(Command::ActB,
|
||||
sendToController(payload, END_ACTB, delay + memSpec->getExecutionTime(Command::ActB,
|
||||
payload));
|
||||
unsigned int row = DramExtension::getExtension(payload).getRow().ID();
|
||||
if (StoreMode == StorageMode::ErrorModel)
|
||||
@@ -108,7 +110,7 @@ tlm_sync_enum DramWideIO::nb_transport_fw(tlm_generic_payload &payload,
|
||||
else if (phase == BEGIN_ACT)
|
||||
{
|
||||
DRAMPower->doCommand(MemCommand::ACT, bank, cycle);
|
||||
sendToController(payload, END_ACT, delay + getExecutionTime(Command::Activate,
|
||||
sendToController(payload, END_ACT, delay + memSpec->getExecutionTime(Command::Activate,
|
||||
payload));
|
||||
unsigned int row = DramExtension::getExtension(payload).getRow().ID();
|
||||
|
||||
@@ -128,7 +130,7 @@ tlm_sync_enum DramWideIO::nb_transport_fw(tlm_generic_payload &payload,
|
||||
{
|
||||
ememory[bank]->store(payload);
|
||||
}
|
||||
sendToController(payload, END_WR, delay + getExecutionTime(Command::Write,
|
||||
sendToController(payload, END_WR, delay + memSpec->getExecutionTime(Command::Write,
|
||||
payload));
|
||||
}
|
||||
else if (phase == BEGIN_RD)
|
||||
@@ -144,7 +146,7 @@ tlm_sync_enum DramWideIO::nb_transport_fw(tlm_generic_payload &payload,
|
||||
{
|
||||
ememory[bank]->load(payload);
|
||||
}
|
||||
sendToController(payload, END_RD, delay + getExecutionTime(Command::Read,
|
||||
sendToController(payload, END_RD, delay + memSpec->getExecutionTime(Command::Read,
|
||||
payload));
|
||||
}
|
||||
else if (phase == BEGIN_WRA)
|
||||
@@ -160,7 +162,7 @@ tlm_sync_enum DramWideIO::nb_transport_fw(tlm_generic_payload &payload,
|
||||
{
|
||||
ememory[bank]->store(payload);
|
||||
}
|
||||
sendToController(payload, END_WRA, delay + getExecutionTime(Command::WriteA,
|
||||
sendToController(payload, END_WRA, delay + memSpec->getExecutionTime(Command::WriteA,
|
||||
payload));
|
||||
}
|
||||
else if (phase == BEGIN_RDA)
|
||||
@@ -176,14 +178,14 @@ tlm_sync_enum DramWideIO::nb_transport_fw(tlm_generic_payload &payload,
|
||||
{
|
||||
ememory[bank]->load(payload);
|
||||
}
|
||||
sendToController(payload, END_RDA, delay + getExecutionTime(Command::ReadA,
|
||||
sendToController(payload, END_RDA, delay + memSpec->getExecutionTime(Command::ReadA,
|
||||
payload));
|
||||
}
|
||||
else if (phase == BEGIN_REFA)
|
||||
{
|
||||
DRAMPower->doCommand(MemCommand::REF, bank, cycle);
|
||||
sendToController(payload, END_REFA,
|
||||
delay + getExecutionTime(Command::AutoRefresh, payload));
|
||||
delay + memSpec->getExecutionTime(Command::AutoRefresh, payload));
|
||||
unsigned int row = DramExtension::getExtension(payload).getRow().ID();
|
||||
|
||||
if (StoreMode == StorageMode::ErrorModel)
|
||||
@@ -193,7 +195,7 @@ tlm_sync_enum DramWideIO::nb_transport_fw(tlm_generic_payload &payload,
|
||||
{
|
||||
DRAMPower->doCommand(MemCommand::REFB, bank, cycle);
|
||||
sendToController(payload, END_REFB,
|
||||
delay + getExecutionTime(Command::AutoRefresh, payload));
|
||||
delay + memSpec->getExecutionTime(Command::AutoRefresh, payload));
|
||||
}
|
||||
// Powerdown phases have to be started and ended by the controller, because they do not have a fixed length
|
||||
else if (phase == BEGIN_PDNA)
|
||||
|
||||
@@ -1,135 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2018, University of Kaiserslautern
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are
|
||||
* met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* 3. Neither the name of the copyright holder nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from
|
||||
* this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
||||
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER
|
||||
* OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* Authors:
|
||||
* Felipe S. Prado
|
||||
* Matthias Jung
|
||||
*/
|
||||
|
||||
#include "RecordableDram.h"
|
||||
|
||||
using namespace tlm;
|
||||
|
||||
RecordableDram::RecordableDram(sc_module_name name, TlmRecorder *tlmRecorder)
|
||||
: Dram(name), tlmRecorder(tlmRecorder)
|
||||
{
|
||||
// Create a thread that is triggered every $powerWindowSize
|
||||
// to generate a Power over Time plot in the Trace analyzer:
|
||||
if (Configuration::getInstance().PowerAnalysis
|
||||
&& Configuration::getInstance().EnableWindowing)
|
||||
SC_THREAD(powerWindow);
|
||||
}
|
||||
|
||||
RecordableDram::~RecordableDram()
|
||||
{
|
||||
if (Configuration::getInstance().PowerAnalysis)
|
||||
{
|
||||
// Obtain the residual energy which was not covered by
|
||||
// previous windows
|
||||
DRAMPower->calcEnergy();
|
||||
recordPower();
|
||||
}
|
||||
tlmRecorder->closeConnection();
|
||||
}
|
||||
|
||||
|
||||
tlm_sync_enum RecordableDram::nb_transport_fw(tlm_generic_payload &payload,
|
||||
tlm_phase &phase, sc_time &delay)
|
||||
{
|
||||
// Recording time used by the traceAnalyzer
|
||||
sc_time recTime = sc_time_stamp() + delay;
|
||||
|
||||
// These are terminating phases recorded by the DRAM. The execution
|
||||
// time of the related command must be taken into consideration.
|
||||
if (phase == END_PDNA || phase == END_PDNAB) {
|
||||
recTime += getExecutionTime(Command::PDNAX, payload);
|
||||
} else if (phase == END_PDNP || phase == END_PDNPB) {
|
||||
recTime += getExecutionTime(Command::PDNPX, payload);
|
||||
} else if (phase == END_SREF || phase == END_SREFB) {
|
||||
recTime += getExecutionTime(Command::SREFX, payload);
|
||||
}
|
||||
|
||||
unsigned int thr = DramExtension::getExtension(payload).getThread().ID();
|
||||
unsigned int ch = DramExtension::getExtension(payload).getChannel().ID();
|
||||
unsigned int bg = DramExtension::getExtension(payload).getBankGroup().ID();
|
||||
unsigned int bank = DramExtension::getExtension(payload).getBank().ID();
|
||||
unsigned int row = DramExtension::getExtension(payload).getRow().ID();
|
||||
unsigned int col = DramExtension::getExtension(payload).getColumn().ID();
|
||||
|
||||
printDebugMessage("Recording " + phaseNameToString(phase) + " thread " +
|
||||
to_string(thr) + " channel " + to_string(ch) + " bank group " + to_string(
|
||||
bg) + " bank " + to_string(bank) + " row " + to_string(row) + " column " +
|
||||
to_string(col) + " at " + recTime.to_string());
|
||||
|
||||
tlmRecorder->recordPhase(payload, phase, recTime);
|
||||
|
||||
return Dram::nb_transport_fw(payload, phase, delay);
|
||||
}
|
||||
|
||||
// This Thread is only triggered when Power Simulation is enabled.
|
||||
// It estimates the current average power which will be stored in the trace database for visualization purposes.
|
||||
void RecordableDram::powerWindow()
|
||||
{
|
||||
unsigned long long clkCycles = 0;
|
||||
|
||||
do {
|
||||
// At the very beginning (zero clock cycles) the energy is 0, so we wait first
|
||||
wait(powerWindowSize);
|
||||
|
||||
clkCycles = sc_time_stamp().value() /
|
||||
Configuration::getInstance().memSpec->clk.value();
|
||||
|
||||
DRAMPower->calcWindowEnergy(clkCycles);
|
||||
|
||||
// During operation the energy should never be zero since the device is always consuming
|
||||
assert(!isEqual(DRAMPower->getEnergy().window_energy, 0.0));
|
||||
|
||||
// Store the time (in seconds) and the current average power (in mW) into the database
|
||||
recordPower();
|
||||
|
||||
// Here considering that DRAMPower provides the energy in pJ and the power in mW
|
||||
printDebugMessage(string("\tWindow Energy: \t") + to_string(
|
||||
DRAMPower->getEnergy().window_energy *
|
||||
Configuration::getInstance().NumberOfDevicesOnDIMM) + string("\t[pJ]"));
|
||||
printDebugMessage(string("\tWindow Average Power: \t") + to_string(
|
||||
DRAMPower->getPower().window_average_power *
|
||||
Configuration::getInstance().NumberOfDevicesOnDIMM) + string("\t[mW]"));
|
||||
|
||||
} while (true);
|
||||
}
|
||||
|
||||
void RecordableDram::recordPower()
|
||||
{
|
||||
tlmRecorder->recordPower(sc_time_stamp().to_seconds(),
|
||||
DRAMPower->getPower().window_average_power
|
||||
* Configuration::getInstance().NumberOfDevicesOnDIMM);
|
||||
}
|
||||
|
||||
@@ -1,78 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2018, University of Kaiserslautern
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are
|
||||
* met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* 3. Neither the name of the copyright holder nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from
|
||||
* this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
||||
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER
|
||||
* OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* Authors:
|
||||
* Felipe S. Prado
|
||||
* Matthias Jung
|
||||
*/
|
||||
|
||||
#ifndef RECORDABLEDRAM_H
|
||||
#define RECORDABLEDRAM_H
|
||||
|
||||
#include "Dram.h"
|
||||
#include "../common/TlmRecorder.h"
|
||||
|
||||
using namespace tlm;
|
||||
|
||||
class RecordableDram : public Dram
|
||||
{
|
||||
public:
|
||||
RecordableDram(sc_module_name, TlmRecorder *tlmRecorder);
|
||||
SC_HAS_PROCESS(RecordableDram);
|
||||
|
||||
~RecordableDram();
|
||||
|
||||
protected:
|
||||
virtual tlm_sync_enum nb_transport_fw(tlm_generic_payload &payload,
|
||||
tlm_phase &phase, sc_time &delay);
|
||||
|
||||
private:
|
||||
TlmRecorder *tlmRecorder;
|
||||
sc_time powerWindowSize = Configuration::getInstance().memSpec->clk *
|
||||
Configuration::getInstance().WindowSize;
|
||||
|
||||
// When working with floats, we have to decide ourselves what is an
|
||||
// acceptable definition for "equal". Here the number is compared with a
|
||||
// suitable error margin (0.00001).
|
||||
bool isEqual(double a, double b, const double epsilon = 1e-05)
|
||||
{
|
||||
return std::fabs(a - b) < epsilon;
|
||||
}
|
||||
|
||||
// This Thread is only triggered when Power Simulation is enabled.
|
||||
// It estimates the current average power which will be stored in the trace database for visualization purposes.
|
||||
void powerWindow();
|
||||
|
||||
void recordPower();
|
||||
};
|
||||
|
||||
#endif // RECORDABLEDRAM_H
|
||||
|
||||
Reference in New Issue
Block a user