Moved specific timing calculation functions to MemSpecs.

This commit is contained in:
Lukas Steiner (2)
2019-06-27 16:02:24 +02:00
parent e462287d7c
commit ac4e4c7783
30 changed files with 249 additions and 379 deletions

View File

@@ -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 \

View File

@@ -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);

View 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;
}
}

View File

@@ -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

View File

@@ -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)]));

View File

@@ -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]));

View File

@@ -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);

View File

@@ -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);

View File

@@ -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);

View File

@@ -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);

View File

@@ -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);
}
}

View File

@@ -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)

View File

@@ -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)

View File

@@ -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;
}

View File

@@ -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();

View File

@@ -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 {

View File

@@ -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();

View File

@@ -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(),

View File

@@ -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;
}

View File

@@ -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) {

View File

@@ -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;
}

View File

@@ -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);
}
}

View File

@@ -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);

View File

@@ -42,7 +42,7 @@
#include <string>
#include <systemc.h>
#include "RecordableDram.h"
#include "DramRecordable.h"
#include "Arbiter.h"
#include "TraceGenerator.h"
#include "ReorderBuffer.h"

View File

@@ -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)

View File

@@ -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();

View File

@@ -40,7 +40,6 @@
#include <tlm>
#include "DramDDR3.h"
#include "DramDDR4.h"
#include "RecordableDram.h"
#include "../common/TlmRecorder.h"
using namespace tlm;

View File

@@ -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)

View File

@@ -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);
}

View File

@@ -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