Merge branch 'refactor/database' into 'develop'
Removal of Recordable abstractions See merge request ems/astdm/modeling.dram/dram.sys.5!110
This commit is contained in:
@@ -39,6 +39,8 @@
|
||||
add_library(libdramsys
|
||||
DRAMSys/common/DebugManager.cpp
|
||||
DRAMSys/common/TlmRecorder.cpp
|
||||
DRAMSys/common/TlmATRecorder.cpp
|
||||
DRAMSys/common/DramATRecorder.cpp
|
||||
DRAMSys/common/dramExtensions.cpp
|
||||
DRAMSys/common/utils.cpp
|
||||
DRAMSys/configuration/memspec/MemSpec.cpp
|
||||
@@ -55,7 +57,6 @@ add_library(libdramsys
|
||||
DRAMSys/controller/BankMachine.cpp
|
||||
DRAMSys/controller/Command.cpp
|
||||
DRAMSys/controller/Controller.cpp
|
||||
DRAMSys/controller/ControllerRecordable.cpp
|
||||
DRAMSys/controller/McConfig.cpp
|
||||
DRAMSys/controller/checker/CheckerDDR3.cpp
|
||||
DRAMSys/controller/checker/CheckerDDR4.cpp
|
||||
@@ -90,7 +91,6 @@ add_library(libdramsys
|
||||
DRAMSys/simulation/Arbiter.cpp
|
||||
DRAMSys/simulation/DRAMSys.cpp
|
||||
DRAMSys/simulation/Dram.cpp
|
||||
DRAMSys/simulation/DramRecordable.cpp
|
||||
DRAMSys/simulation/SimConfig.cpp
|
||||
)
|
||||
|
||||
|
||||
101
src/libdramsys/DRAMSys/common/DramATRecorder.cpp
Normal file
101
src/libdramsys/DRAMSys/common/DramATRecorder.cpp
Normal file
@@ -0,0 +1,101 @@
|
||||
#include "DramATRecorder.h"
|
||||
#include "DRAMSys/configuration/memspec/MemSpec.h"
|
||||
#include "DRAMSys/controller/Command.h"
|
||||
#include "DRAMSys/simulation/SimConfig.h"
|
||||
#include <sysc/kernel/sc_module.h>
|
||||
#include <sysc/kernel/sc_simcontext.h>
|
||||
#include <tlm_core/tlm_2/tlm_generic_payload/tlm_phase.h>
|
||||
|
||||
namespace DRAMSys
|
||||
{
|
||||
|
||||
DramATRecorder::DramATRecorder(const sc_core::sc_module_name& name,
|
||||
const SimConfig& simConfig,
|
||||
const MemSpec& memSpec,
|
||||
TlmRecorder& tlmRecorder,
|
||||
bool enableBandwidth) :
|
||||
sc_module(name),
|
||||
tlmRecorder(tlmRecorder),
|
||||
enableWindowing(simConfig.enableWindowing),
|
||||
pseudoChannelMode(memSpec.pseudoChannelMode()),
|
||||
ranksPerChannel(memSpec.ranksPerChannel),
|
||||
windowSizeTime(simConfig.windowSize * memSpec.tCK),
|
||||
numberOfBeatsServed(memSpec.ranksPerChannel, 0),
|
||||
activeTimeMultiplier(memSpec.tCK / memSpec.dataRate),
|
||||
enableBandwidth(enableBandwidth)
|
||||
{
|
||||
iSocket.register_nb_transport_bw(this, &DramATRecorder::nb_transport_bw);
|
||||
tSocket.register_nb_transport_fw(this, &DramATRecorder::nb_transport_fw);
|
||||
tSocket.register_b_transport(this, &DramATRecorder::b_transport);
|
||||
tSocket.register_transport_dbg(this, &DramATRecorder::transport_dbg);
|
||||
|
||||
if (enableBandwidth && enableWindowing)
|
||||
{
|
||||
SC_METHOD(recordBandwidth);
|
||||
dont_initialize();
|
||||
sensitive << windowEvent;
|
||||
|
||||
windowEvent.notify(windowSizeTime);
|
||||
nextWindowEventTime = windowSizeTime;
|
||||
}
|
||||
}
|
||||
|
||||
tlm::tlm_sync_enum DramATRecorder::nb_transport_fw(tlm::tlm_generic_payload& trans,
|
||||
tlm::tlm_phase& phase,
|
||||
sc_core::sc_time& delay)
|
||||
{
|
||||
if (enableBandwidth && enableWindowing)
|
||||
{
|
||||
Command cmd{phase};
|
||||
if (cmd.isCasCommand())
|
||||
{
|
||||
auto rank = ControllerExtension::getRank(trans);
|
||||
numberOfBeatsServed[static_cast<std::size_t>(rank)] +=
|
||||
ControllerExtension::getBurstLength(trans);
|
||||
}
|
||||
}
|
||||
|
||||
tlmRecorder.recordPhase(trans, phase, delay);
|
||||
return iSocket->nb_transport_fw(trans, phase, delay);
|
||||
}
|
||||
|
||||
tlm::tlm_sync_enum DramATRecorder::nb_transport_bw(tlm::tlm_generic_payload& trans,
|
||||
tlm::tlm_phase& phase,
|
||||
sc_core::sc_time& delay)
|
||||
{
|
||||
tlmRecorder.recordPhase(trans, phase, delay);
|
||||
return tSocket->nb_transport_bw(trans, phase, delay);
|
||||
}
|
||||
|
||||
void DramATRecorder::b_transport(tlm::tlm_generic_payload& trans, sc_core::sc_time& delay)
|
||||
{
|
||||
iSocket->b_transport(trans, delay);
|
||||
}
|
||||
|
||||
unsigned int DramATRecorder::transport_dbg(tlm::tlm_generic_payload& trans)
|
||||
{
|
||||
return iSocket->transport_dbg(trans);
|
||||
}
|
||||
|
||||
void DramATRecorder::recordBandwidth()
|
||||
{
|
||||
windowEvent.notify(windowSizeTime);
|
||||
nextWindowEventTime += windowSizeTime;
|
||||
|
||||
std::uint64_t totalNumberOfBeatsServed =
|
||||
std::accumulate(numberOfBeatsServed.begin(), numberOfBeatsServed.end(), 0);
|
||||
|
||||
uint64_t windowNumberOfBeatsServed = totalNumberOfBeatsServed - lastNumberOfBeatsServed;
|
||||
lastNumberOfBeatsServed = totalNumberOfBeatsServed;
|
||||
|
||||
// HBM specific, pseudo channels get averaged
|
||||
if (pseudoChannelMode)
|
||||
windowNumberOfBeatsServed /= ranksPerChannel;
|
||||
|
||||
sc_core::sc_time windowActiveTime =
|
||||
activeTimeMultiplier * static_cast<double>(windowNumberOfBeatsServed);
|
||||
double windowAverageBandwidth = windowActiveTime / windowSizeTime;
|
||||
tlmRecorder.recordBandwidth(sc_core::sc_time_stamp().to_seconds(), windowAverageBandwidth);
|
||||
}
|
||||
|
||||
} // namespace DRAMSys
|
||||
61
src/libdramsys/DRAMSys/common/DramATRecorder.h
Normal file
61
src/libdramsys/DRAMSys/common/DramATRecorder.h
Normal file
@@ -0,0 +1,61 @@
|
||||
#ifndef DRAMATRECORDER_H
|
||||
#define DRAMATRECORDER_H
|
||||
|
||||
#include "DRAMSys/configuration/memspec/MemSpec.h"
|
||||
#include "DRAMSys/simulation/SimConfig.h"
|
||||
#include "TlmRecorder.h"
|
||||
|
||||
#include <sysc/kernel/sc_module.h>
|
||||
#include <tlm>
|
||||
#include <tlm_utils/simple_initiator_socket.h>
|
||||
#include <tlm_utils/simple_target_socket.h>
|
||||
#include <vector>
|
||||
|
||||
namespace DRAMSys
|
||||
{
|
||||
|
||||
class DramATRecorder : public sc_core::sc_module
|
||||
|
||||
{
|
||||
SC_HAS_PROCESS(DramATRecorder);
|
||||
|
||||
public:
|
||||
tlm_utils::simple_initiator_socket<DramATRecorder> iSocket;
|
||||
tlm_utils::simple_target_socket<DramATRecorder> tSocket;
|
||||
|
||||
DramATRecorder(const sc_core::sc_module_name& name,
|
||||
const SimConfig& simConfig,
|
||||
const MemSpec& memspec,
|
||||
TlmRecorder& tlmRecorder,
|
||||
bool enableBandwidth);
|
||||
~DramATRecorder() = default;
|
||||
|
||||
tlm::tlm_sync_enum nb_transport_fw(tlm::tlm_generic_payload& trans,
|
||||
tlm::tlm_phase& phase,
|
||||
sc_core::sc_time& delay);
|
||||
tlm::tlm_sync_enum nb_transport_bw(tlm::tlm_generic_payload& trans,
|
||||
tlm::tlm_phase& phase,
|
||||
sc_core::sc_time& delay);
|
||||
void b_transport(tlm::tlm_generic_payload& trans, sc_core::sc_time& delay);
|
||||
unsigned int transport_dbg(tlm::tlm_generic_payload& trans);
|
||||
|
||||
private:
|
||||
TlmRecorder& tlmRecorder;
|
||||
const bool enableWindowing;
|
||||
const bool pseudoChannelMode;
|
||||
const unsigned int ranksPerChannel;
|
||||
const sc_core::sc_time windowSizeTime;
|
||||
sc_core::sc_event windowEvent;
|
||||
sc_core::sc_time nextWindowEventTime;
|
||||
std::vector<uint64_t> numberOfBeatsServed;
|
||||
uint64_t lastNumberOfBeatsServed = 0;
|
||||
const sc_core::sc_time activeTimeMultiplier;
|
||||
|
||||
bool enableBandwidth = false;
|
||||
|
||||
void recordBandwidth();
|
||||
};
|
||||
|
||||
} // namespace DRAMSys
|
||||
|
||||
#endif // DRAMATRECORDER_H
|
||||
100
src/libdramsys/DRAMSys/common/TlmATRecorder.cpp
Normal file
100
src/libdramsys/DRAMSys/common/TlmATRecorder.cpp
Normal file
@@ -0,0 +1,100 @@
|
||||
#include "TlmATRecorder.h"
|
||||
|
||||
#include "DRAMSys/configuration/memspec/MemSpec.h"
|
||||
#include "DRAMSys/controller/Command.h"
|
||||
#include "DRAMSys/simulation/SimConfig.h"
|
||||
#include <sysc/kernel/sc_module.h>
|
||||
#include <sysc/kernel/sc_simcontext.h>
|
||||
#include <tlm_core/tlm_2/tlm_generic_payload/tlm_phase.h>
|
||||
|
||||
namespace DRAMSys
|
||||
{
|
||||
|
||||
TlmATRecorder::TlmATRecorder(const sc_core::sc_module_name& name,
|
||||
const SimConfig& simConfig,
|
||||
const MemSpec& memSpec,
|
||||
TlmRecorder& tlmRecorder,
|
||||
bool enableBandwidth) :
|
||||
sc_module(name),
|
||||
memSpec(memSpec),
|
||||
tlmRecorder(tlmRecorder),
|
||||
enableWindowing(simConfig.enableWindowing),
|
||||
pseudoChannelMode(memSpec.pseudoChannelMode()),
|
||||
ranksPerChannel(memSpec.ranksPerChannel),
|
||||
windowSizeTime(simConfig.windowSize * memSpec.tCK),
|
||||
numberOfBytesServed(0),
|
||||
activeTimeMultiplier(memSpec.tCK / memSpec.dataRate),
|
||||
enableBandwidth(enableBandwidth)
|
||||
{
|
||||
iSocket.register_nb_transport_bw(this, &TlmATRecorder::nb_transport_bw);
|
||||
tSocket.register_nb_transport_fw(this, &TlmATRecorder::nb_transport_fw);
|
||||
tSocket.register_b_transport(this, &TlmATRecorder::b_transport);
|
||||
tSocket.register_transport_dbg(this, &TlmATRecorder::transport_dbg);
|
||||
|
||||
if (enableBandwidth && enableWindowing)
|
||||
{
|
||||
SC_METHOD(recordBandwidth);
|
||||
dont_initialize();
|
||||
sensitive << windowEvent;
|
||||
|
||||
windowEvent.notify(windowSizeTime);
|
||||
nextWindowEventTime = windowSizeTime;
|
||||
}
|
||||
}
|
||||
|
||||
tlm::tlm_sync_enum TlmATRecorder::nb_transport_fw(tlm::tlm_generic_payload& trans,
|
||||
tlm::tlm_phase& phase,
|
||||
sc_core::sc_time& delay)
|
||||
{
|
||||
if (enableBandwidth && enableWindowing)
|
||||
{
|
||||
if (phase == tlm::BEGIN_REQ && trans.is_write())
|
||||
numberOfBytesServed += trans.get_data_length();
|
||||
}
|
||||
|
||||
tlmRecorder.recordPhase(trans, phase, delay);
|
||||
return iSocket->nb_transport_fw(trans, phase, delay);
|
||||
}
|
||||
|
||||
tlm::tlm_sync_enum TlmATRecorder::nb_transport_bw(tlm::tlm_generic_payload& trans,
|
||||
tlm::tlm_phase& phase,
|
||||
sc_core::sc_time& delay)
|
||||
{
|
||||
if (enableBandwidth && enableWindowing)
|
||||
{
|
||||
if (phase == tlm::BEGIN_RESP && trans.is_read())
|
||||
numberOfBytesServed += trans.get_data_length();
|
||||
}
|
||||
|
||||
tlmRecorder.recordPhase(trans, phase, delay);
|
||||
return tSocket->nb_transport_bw(trans, phase, delay);
|
||||
}
|
||||
|
||||
void TlmATRecorder::b_transport(tlm::tlm_generic_payload& trans, sc_core::sc_time& delay)
|
||||
{
|
||||
iSocket->b_transport(trans, delay);
|
||||
}
|
||||
|
||||
unsigned int TlmATRecorder::transport_dbg(tlm::tlm_generic_payload& trans)
|
||||
{
|
||||
return iSocket->transport_dbg(trans);
|
||||
}
|
||||
|
||||
void TlmATRecorder::recordBandwidth()
|
||||
{
|
||||
windowEvent.notify(windowSizeTime);
|
||||
nextWindowEventTime += windowSizeTime;
|
||||
|
||||
uint64_t windowNumberOfBytesServed = numberOfBytesServed - lastNumberOfBytesServed;
|
||||
lastNumberOfBytesServed = numberOfBytesServed;
|
||||
|
||||
// HBM specific, pseudo channels get averaged
|
||||
if (pseudoChannelMode)
|
||||
windowNumberOfBytesServed /= ranksPerChannel;
|
||||
|
||||
double windowBandwidth =
|
||||
static_cast<double>(windowNumberOfBytesServed) / (windowSizeTime.to_seconds());
|
||||
tlmRecorder.recordBandwidth(sc_core::sc_time_stamp().to_seconds(), windowBandwidth);
|
||||
}
|
||||
|
||||
} // namespace DRAMSys
|
||||
62
src/libdramsys/DRAMSys/common/TlmATRecorder.h
Normal file
62
src/libdramsys/DRAMSys/common/TlmATRecorder.h
Normal file
@@ -0,0 +1,62 @@
|
||||
#ifndef TLMATRECORDER_H
|
||||
#define TLMATRECORDER_H
|
||||
|
||||
#include "DRAMSys/configuration/memspec/MemSpec.h"
|
||||
#include "DRAMSys/simulation/SimConfig.h"
|
||||
#include "TlmRecorder.h"
|
||||
|
||||
#include <sysc/kernel/sc_module.h>
|
||||
#include <tlm>
|
||||
#include <tlm_utils/simple_initiator_socket.h>
|
||||
#include <tlm_utils/simple_target_socket.h>
|
||||
#include <vector>
|
||||
|
||||
namespace DRAMSys
|
||||
{
|
||||
|
||||
class TlmATRecorder : public sc_core::sc_module
|
||||
|
||||
{
|
||||
SC_HAS_PROCESS(TlmATRecorder);
|
||||
|
||||
public:
|
||||
tlm_utils::simple_initiator_socket<TlmATRecorder> iSocket;
|
||||
tlm_utils::simple_target_socket<TlmATRecorder> tSocket;
|
||||
|
||||
TlmATRecorder(const sc_core::sc_module_name& name,
|
||||
const SimConfig& simConfig,
|
||||
const MemSpec& memspec,
|
||||
TlmRecorder& tlmRecorder,
|
||||
bool enableBandwidth);
|
||||
~TlmATRecorder() = default;
|
||||
|
||||
tlm::tlm_sync_enum nb_transport_fw(tlm::tlm_generic_payload& trans,
|
||||
tlm::tlm_phase& phase,
|
||||
sc_core::sc_time& delay);
|
||||
tlm::tlm_sync_enum nb_transport_bw(tlm::tlm_generic_payload& trans,
|
||||
tlm::tlm_phase& phase,
|
||||
sc_core::sc_time& delay);
|
||||
void b_transport(tlm::tlm_generic_payload& trans, sc_core::sc_time& delay);
|
||||
unsigned int transport_dbg(tlm::tlm_generic_payload& trans);
|
||||
|
||||
private:
|
||||
const MemSpec& memSpec;
|
||||
TlmRecorder& tlmRecorder;
|
||||
const bool enableWindowing;
|
||||
const bool pseudoChannelMode;
|
||||
const unsigned int ranksPerChannel;
|
||||
const sc_core::sc_time windowSizeTime;
|
||||
sc_core::sc_event windowEvent;
|
||||
sc_core::sc_time nextWindowEventTime;
|
||||
uint64_t numberOfBytesServed;
|
||||
uint64_t lastNumberOfBytesServed = 0;
|
||||
const sc_core::sc_time activeTimeMultiplier;
|
||||
|
||||
bool enableBandwidth = false;
|
||||
|
||||
void recordBandwidth();
|
||||
};
|
||||
|
||||
} // namespace DRAMSys
|
||||
|
||||
#endif // TLMATRECORDER_H
|
||||
@@ -87,15 +87,29 @@ namespace DRAMSys
|
||||
Controller::Controller(const sc_module_name& name,
|
||||
const McConfig& config,
|
||||
const MemSpec& memSpec,
|
||||
const AddressDecoder& addressDecoder) :
|
||||
const SimConfig& simConfig,
|
||||
const AddressDecoder& addressDecoder,
|
||||
TlmRecorder* tlmRecorder) :
|
||||
sc_module(name),
|
||||
config(config),
|
||||
memSpec(memSpec),
|
||||
simConfig(simConfig),
|
||||
addressDecoder(addressDecoder),
|
||||
tlmRecorder(tlmRecorder),
|
||||
windowSizeTime(simConfig.windowSize * memSpec.tCK),
|
||||
nextWindowEventTime(windowSizeTime),
|
||||
numberOfBeatsServed(memSpec.ranksPerChannel, 0),
|
||||
minBytesPerBurst(memSpec.defaultBytesPerBurst),
|
||||
maxBytesPerBurst(memSpec.maxBytesPerBurst)
|
||||
{
|
||||
if (simConfig.databaseRecording && tlmRecorder != nullptr)
|
||||
{
|
||||
SC_METHOD(recordBufferDepth);
|
||||
dont_initialize();
|
||||
sensitive << windowEvent;
|
||||
windowEvent.notify(windowSizeTime);
|
||||
}
|
||||
|
||||
SC_METHOD(controllerMethod);
|
||||
sensitive << beginReqEvent << endRespEvent << controllerEvent << dataResponseEvent;
|
||||
|
||||
@@ -320,6 +334,9 @@ Controller::Controller(const sc_module_name& name,
|
||||
}
|
||||
else
|
||||
SC_REPORT_FATAL("Controller", "Selected refresh mode not supported!");
|
||||
|
||||
slidingAverageBufferDepth = std::vector<sc_time>(scheduler->getBufferDepth().size());
|
||||
windowAverageBufferDepth = std::vector<double>(scheduler->getBufferDepth().size());
|
||||
}
|
||||
|
||||
void Controller::registerIdleCallback(std::function<void()> idleCallback)
|
||||
@@ -327,8 +344,33 @@ void Controller::registerIdleCallback(std::function<void()> idleCallback)
|
||||
this->idleCallback = std::move(idleCallback);
|
||||
}
|
||||
|
||||
void Controller::recordBufferDepth()
|
||||
{
|
||||
windowEvent.notify(windowSizeTime);
|
||||
nextWindowEventTime += windowSizeTime;
|
||||
|
||||
for (std::size_t index = 0; index < slidingAverageBufferDepth.size(); index++)
|
||||
{
|
||||
windowAverageBufferDepth[index] = slidingAverageBufferDepth[index] / windowSizeTime;
|
||||
slidingAverageBufferDepth[index] = SC_ZERO_TIME;
|
||||
}
|
||||
|
||||
tlmRecorder->recordBufferDepth(sc_time_stamp().to_seconds(), windowAverageBufferDepth);
|
||||
}
|
||||
|
||||
void Controller::controllerMethod()
|
||||
{
|
||||
// Compute and report BufferDepth
|
||||
if (simConfig.databaseRecording && simConfig.enableWindowing)
|
||||
{
|
||||
sc_time timeDiff = sc_time_stamp() - lastTimeCalled;
|
||||
lastTimeCalled = sc_time_stamp();
|
||||
const std::vector<unsigned>& bufferDepth = scheduler->getBufferDepth();
|
||||
|
||||
for (std::size_t index = 0; index < slidingAverageBufferDepth.size(); index++)
|
||||
slidingAverageBufferDepth[index] += bufferDepth[index] * timeDiff;
|
||||
}
|
||||
|
||||
if (isFullCycle(sc_time_stamp(), memSpec.tCK))
|
||||
{
|
||||
// (1) Finish last response (END_RESP) and start new response (BEGIN_RESP)
|
||||
|
||||
@@ -46,6 +46,8 @@
|
||||
#include "refresh/RefreshManagerIF.h"
|
||||
#include "respqueue/RespQueueIF.h"
|
||||
|
||||
#include "DRAMSys/common/TlmRecorder.h"
|
||||
#include "DRAMSys/simulation/SimConfig.h"
|
||||
#include <DRAMSys/common/DebugManager.h>
|
||||
#include <DRAMSys/simulation/AddressDecoder.h>
|
||||
|
||||
@@ -70,7 +72,9 @@ public:
|
||||
Controller(const sc_core::sc_module_name& name,
|
||||
const McConfig& config,
|
||||
const MemSpec& memSpec,
|
||||
const AddressDecoder& addressDecoder);
|
||||
const SimConfig& simConfig,
|
||||
const AddressDecoder& addressDecoder,
|
||||
TlmRecorder* tlmRecorder);
|
||||
SC_HAS_PROCESS(Controller);
|
||||
|
||||
[[nodiscard]] bool idle() const { return totalNumberOfPayloads == 0; }
|
||||
@@ -92,15 +96,25 @@ protected:
|
||||
sendToFrontend(tlm::tlm_generic_payload& trans, tlm::tlm_phase& phase, sc_core::sc_time& delay);
|
||||
|
||||
virtual void controllerMethod();
|
||||
void recordBufferDepth();
|
||||
|
||||
const McConfig& config;
|
||||
const MemSpec& memSpec;
|
||||
const SimConfig& simConfig;
|
||||
const AddressDecoder& addressDecoder;
|
||||
TlmRecorder* const tlmRecorder;
|
||||
|
||||
std::unique_ptr<SchedulerIF> scheduler;
|
||||
|
||||
sc_core::sc_time scMaxTime = sc_core::sc_max_time();
|
||||
|
||||
sc_core::sc_time lastTimeCalled = sc_core::SC_ZERO_TIME;
|
||||
sc_core::sc_event windowEvent;
|
||||
const sc_core::sc_time windowSizeTime;
|
||||
sc_core::sc_time nextWindowEventTime;
|
||||
std::vector<sc_core::sc_time> slidingAverageBufferDepth;
|
||||
std::vector<double> windowAverageBufferDepth;
|
||||
|
||||
std::vector<uint64_t> numberOfBeatsServed;
|
||||
unsigned totalNumberOfPayloads = 0;
|
||||
std::function<void()> idleCallback;
|
||||
|
||||
@@ -1,141 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2019, RPTU Kaiserslautern-Landau
|
||||
* 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.
|
||||
*
|
||||
* Author: Lukas Steiner
|
||||
*/
|
||||
|
||||
#include "ControllerRecordable.h"
|
||||
|
||||
#include "DRAMSys/controller/scheduler/SchedulerIF.h"
|
||||
|
||||
using namespace sc_core;
|
||||
using namespace tlm;
|
||||
|
||||
namespace DRAMSys
|
||||
{
|
||||
|
||||
ControllerRecordable::ControllerRecordable(const sc_module_name& name,
|
||||
const McConfig& config,
|
||||
const SimConfig& simConfig,
|
||||
const MemSpec& memSpec,
|
||||
const AddressDecoder& addressDecoder,
|
||||
TlmRecorder& tlmRecorder) :
|
||||
Controller(name, config, memSpec, addressDecoder),
|
||||
tlmRecorder(tlmRecorder),
|
||||
windowSizeTime(simConfig.windowSize * memSpec.tCK),
|
||||
activeTimeMultiplier(memSpec.tCK / memSpec.dataRate),
|
||||
enableWindowing(simConfig.enableWindowing)
|
||||
{
|
||||
if (enableWindowing)
|
||||
{
|
||||
sensitive << windowEvent;
|
||||
slidingAverageBufferDepth = std::vector<sc_time>(scheduler->getBufferDepth().size());
|
||||
windowAverageBufferDepth = std::vector<double>(scheduler->getBufferDepth().size());
|
||||
windowEvent.notify(windowSizeTime);
|
||||
nextWindowEventTime = windowSizeTime;
|
||||
}
|
||||
}
|
||||
|
||||
tlm_sync_enum
|
||||
ControllerRecordable::nb_transport_fw(tlm_generic_payload& trans, tlm_phase& phase, sc_time& delay)
|
||||
{
|
||||
tlmRecorder.recordPhase(trans, phase, delay);
|
||||
return Controller::nb_transport_fw(trans, phase, delay);
|
||||
}
|
||||
|
||||
tlm_sync_enum ControllerRecordable::nb_transport_bw([[maybe_unused]] tlm_generic_payload& trans,
|
||||
[[maybe_unused]] tlm_phase& phase,
|
||||
[[maybe_unused]] sc_time& delay)
|
||||
{
|
||||
SC_REPORT_FATAL("Controller", "nb_transport_bw of controller must not be called");
|
||||
return TLM_ACCEPTED;
|
||||
}
|
||||
|
||||
void ControllerRecordable::sendToFrontend(tlm_generic_payload& payload,
|
||||
tlm_phase& phase,
|
||||
sc_time& delay)
|
||||
{
|
||||
tlmRecorder.recordPhase(payload, phase, delay);
|
||||
tSocket->nb_transport_bw(payload, phase, delay);
|
||||
}
|
||||
|
||||
void ControllerRecordable::controllerMethod()
|
||||
{
|
||||
if (enableWindowing)
|
||||
{
|
||||
sc_time timeDiff = sc_time_stamp() - lastTimeCalled;
|
||||
lastTimeCalled = sc_time_stamp();
|
||||
const std::vector<unsigned>& bufferDepth = scheduler->getBufferDepth();
|
||||
|
||||
for (std::size_t index = 0; index < slidingAverageBufferDepth.size(); index++)
|
||||
slidingAverageBufferDepth[index] += bufferDepth[index] * timeDiff;
|
||||
|
||||
if (sc_time_stamp() == nextWindowEventTime)
|
||||
{
|
||||
windowEvent.notify(windowSizeTime);
|
||||
nextWindowEventTime += windowSizeTime;
|
||||
|
||||
for (std::size_t index = 0; index < slidingAverageBufferDepth.size(); index++)
|
||||
{
|
||||
windowAverageBufferDepth[index] = slidingAverageBufferDepth[index] / windowSizeTime;
|
||||
slidingAverageBufferDepth[index] = SC_ZERO_TIME;
|
||||
}
|
||||
|
||||
tlmRecorder.recordBufferDepth(sc_time_stamp().to_seconds(), windowAverageBufferDepth);
|
||||
|
||||
Controller::controllerMethod();
|
||||
|
||||
std::uint64_t totalNumberOfBeatsServed = std::accumulate(numberOfBeatsServed.begin(), numberOfBeatsServed.end(), 0);
|
||||
|
||||
uint64_t windowNumberOfBeatsServed = totalNumberOfBeatsServed - lastNumberOfBeatsServed;
|
||||
lastNumberOfBeatsServed = totalNumberOfBeatsServed;
|
||||
|
||||
// HBM specific, pseudo channels get averaged
|
||||
if (memSpec.pseudoChannelMode())
|
||||
windowNumberOfBeatsServed /= memSpec.ranksPerChannel;
|
||||
|
||||
sc_time windowActiveTime =
|
||||
activeTimeMultiplier * static_cast<double>(windowNumberOfBeatsServed);
|
||||
double windowAverageBandwidth = windowActiveTime / windowSizeTime;
|
||||
tlmRecorder.recordBandwidth(sc_time_stamp().to_seconds(), windowAverageBandwidth);
|
||||
}
|
||||
else
|
||||
{
|
||||
Controller::controllerMethod();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Controller::controllerMethod();
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace DRAMSys
|
||||
@@ -1,89 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2019, RPTU Kaiserslautern-Landau
|
||||
* 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.
|
||||
*
|
||||
* Author: Lukas Steiner
|
||||
*/
|
||||
|
||||
#ifndef CONTROLLERRECORDABLE_H
|
||||
#define CONTROLLERRECORDABLE_H
|
||||
|
||||
#include "DRAMSys/common/TlmRecorder.h"
|
||||
#include "DRAMSys/controller/Controller.h"
|
||||
#include "DRAMSys/simulation/SimConfig.h"
|
||||
|
||||
#include <systemc>
|
||||
#include <tlm>
|
||||
|
||||
namespace DRAMSys
|
||||
{
|
||||
|
||||
class ControllerRecordable final : public Controller
|
||||
{
|
||||
public:
|
||||
ControllerRecordable(const sc_core::sc_module_name& name,
|
||||
const McConfig& config,
|
||||
const SimConfig& simConfig,
|
||||
const MemSpec& memSpec,
|
||||
const AddressDecoder& addressDecoder,
|
||||
TlmRecorder& tlmRecorder);
|
||||
|
||||
protected:
|
||||
tlm::tlm_sync_enum nb_transport_fw(tlm::tlm_generic_payload& trans,
|
||||
tlm::tlm_phase& phase,
|
||||
sc_core::sc_time& delay) override;
|
||||
tlm::tlm_sync_enum nb_transport_bw(tlm::tlm_generic_payload& trans,
|
||||
tlm::tlm_phase& phase,
|
||||
sc_core::sc_time& delay) override;
|
||||
|
||||
void sendToFrontend(tlm::tlm_generic_payload& payload,
|
||||
tlm::tlm_phase& phase,
|
||||
sc_core::sc_time& delay) override;
|
||||
|
||||
void controllerMethod() override;
|
||||
|
||||
private:
|
||||
TlmRecorder& tlmRecorder;
|
||||
|
||||
sc_core::sc_event windowEvent;
|
||||
const sc_core::sc_time windowSizeTime;
|
||||
sc_core::sc_time nextWindowEventTime;
|
||||
std::vector<sc_core::sc_time> slidingAverageBufferDepth;
|
||||
std::vector<double> windowAverageBufferDepth;
|
||||
sc_core::sc_time lastTimeCalled = sc_core::SC_ZERO_TIME;
|
||||
|
||||
uint64_t lastNumberOfBeatsServed = 0;
|
||||
const sc_core::sc_time activeTimeMultiplier;
|
||||
const bool enableWindowing;
|
||||
};
|
||||
|
||||
} // namespace DRAMSys
|
||||
|
||||
#endif // CONTROLLERRECORDABLE_H
|
||||
@@ -44,7 +44,6 @@
|
||||
#include "DRAMSys/common/utils.h"
|
||||
|
||||
#include "DRAMSys/simulation/Dram.h"
|
||||
#include "DRAMSys/simulation/DramRecordable.h"
|
||||
|
||||
#include "DRAMSys/configuration/memspec/MemSpecDDR3.h"
|
||||
#include "DRAMSys/configuration/memspec/MemSpecDDR4.h"
|
||||
@@ -95,7 +94,6 @@ DRAMSys::DRAMSys(const sc_core::sc_module_name& name, const Config::Configuratio
|
||||
if (simConfig.databaseRecording)
|
||||
{
|
||||
std::string traceName = simConfig.simulationName;
|
||||
|
||||
if (!config.simulationid.empty())
|
||||
traceName = config.simulationid + '_' + traceName;
|
||||
|
||||
@@ -107,31 +105,52 @@ DRAMSys::DRAMSys(const sc_core::sc_module_name& name, const Config::Configuratio
|
||||
for (std::size_t i = 0; i < memSpec->numberOfChannels; i++)
|
||||
{
|
||||
controllers.emplace_back(
|
||||
std::make_unique<ControllerRecordable>(("controller" + std::to_string(i)).c_str(),
|
||||
mcConfig,
|
||||
simConfig,
|
||||
*memSpec,
|
||||
*addressDecoder,
|
||||
tlmRecorders[i]));
|
||||
std::make_unique<Controller>(("controller" + std::to_string(i)).c_str(),
|
||||
mcConfig,
|
||||
*memSpec,
|
||||
simConfig,
|
||||
*addressDecoder,
|
||||
&tlmRecorders[i]));
|
||||
|
||||
drams.emplace_back(std::make_unique<DramRecordable>(
|
||||
("dram" + std::to_string(i)).c_str(), simConfig, *memSpec, tlmRecorders[i]));
|
||||
drams.emplace_back(std::make_unique<Dram>(
|
||||
("dram" + std::to_string(i)).c_str(), simConfig, *memSpec, &tlmRecorders[i]));
|
||||
|
||||
if (simConfig.checkTLM2Protocol)
|
||||
controllersTlmCheckers.emplace_back(
|
||||
std::make_unique<tlm_utils::tlm2_base_protocol_checker<>>(
|
||||
("TLMCheckerController" + std::to_string(i)).c_str()));
|
||||
|
||||
// Not recording bandwidth between Arbiter - Controller
|
||||
tlmATRecorders.emplace_back(
|
||||
std::make_unique<TlmATRecorder>(("TlmATRecorder" + std::to_string(i)).c_str(),
|
||||
simConfig,
|
||||
*memSpec,
|
||||
tlmRecorders[i],
|
||||
false));
|
||||
|
||||
// Recording bandwidth between Controller - DRAM
|
||||
dramATRecorders.emplace_back(
|
||||
std::make_unique<DramATRecorder>(("DramATRecorder" + std::to_string(i)).c_str(),
|
||||
simConfig,
|
||||
*memSpec,
|
||||
tlmRecorders[i],
|
||||
true));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (std::size_t i = 0; i < memSpec->numberOfChannels; i++)
|
||||
{
|
||||
controllers.emplace_back(std::make_unique<Controller>(
|
||||
("controller" + std::to_string(i)).c_str(), mcConfig, *memSpec, *addressDecoder));
|
||||
controllers.emplace_back(
|
||||
std::make_unique<Controller>(("controller" + std::to_string(i)).c_str(),
|
||||
mcConfig,
|
||||
*memSpec,
|
||||
simConfig,
|
||||
*addressDecoder,
|
||||
nullptr));
|
||||
|
||||
drams.emplace_back(
|
||||
std::make_unique<Dram>(("dram" + std::to_string(i)).c_str(), simConfig, *memSpec));
|
||||
drams.emplace_back(std::make_unique<Dram>(
|
||||
("dram" + std::to_string(i)).c_str(), simConfig, *memSpec, nullptr));
|
||||
|
||||
if (simConfig.checkTLM2Protocol)
|
||||
{
|
||||
@@ -143,19 +162,44 @@ DRAMSys::DRAMSys(const sc_core::sc_module_name& name, const Config::Configuratio
|
||||
}
|
||||
|
||||
// Connect all internal DRAMSys modules:
|
||||
// If database recording is enabled, then the tlmRecorders are placed
|
||||
// on the bus between the modules
|
||||
tSocket.bind(arbiter->tSocket);
|
||||
for (unsigned i = 0; i < memSpec->numberOfChannels; i++)
|
||||
{
|
||||
if (simConfig.checkTLM2Protocol)
|
||||
if (simConfig.checkTLM2Protocol && simConfig.databaseRecording)
|
||||
{
|
||||
arbiter->iSocket.bind(controllersTlmCheckers[i]->target_socket);
|
||||
controllersTlmCheckers[i]->initiator_socket.bind(tlmATRecorders[i]->tSocket);
|
||||
tlmATRecorders[i]->iSocket.bind(controllers[i]->tSocket);
|
||||
}
|
||||
else if (simConfig.checkTLM2Protocol)
|
||||
{
|
||||
// Arbiter <--> tlmRecorder <--> Controller
|
||||
arbiter->iSocket.bind(controllersTlmCheckers[i]->target_socket);
|
||||
controllersTlmCheckers[i]->initiator_socket.bind(controllers[i]->tSocket);
|
||||
}
|
||||
else if (simConfig.databaseRecording)
|
||||
{
|
||||
arbiter->iSocket.bind(tlmATRecorders[i]->tSocket);
|
||||
tlmATRecorders[i]->iSocket.bind(controllers[i]->tSocket);
|
||||
}
|
||||
else
|
||||
{
|
||||
arbiter->iSocket.bind(controllers[i]->tSocket);
|
||||
}
|
||||
controllers[i]->iSocket.bind(drams[i]->tSocket);
|
||||
|
||||
if (simConfig.databaseRecording)
|
||||
{
|
||||
// Controller <--> tlmRecorder <--> Dram
|
||||
controllers[i]->iSocket.bind(dramATRecorders[i]->tSocket);
|
||||
dramATRecorders[i]->iSocket.bind(drams[i]->tSocket);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Controller <--> Dram
|
||||
controllers[i]->iSocket.bind(drams[i]->tSocket);
|
||||
}
|
||||
}
|
||||
|
||||
report();
|
||||
@@ -215,8 +259,11 @@ void DRAMSys::end_of_simulation()
|
||||
dram->reportPower();
|
||||
}
|
||||
|
||||
for (auto& tlmRecorder : tlmRecorders)
|
||||
tlmRecorder.finalize();
|
||||
if (simConfig.databaseRecording)
|
||||
{
|
||||
for (auto& tlmRecorder : tlmRecorders)
|
||||
tlmRecorder.finalize();
|
||||
}
|
||||
}
|
||||
|
||||
void DRAMSys::logo()
|
||||
|
||||
@@ -41,14 +41,16 @@
|
||||
#ifndef DRAMSYS_H
|
||||
#define DRAMSYS_H
|
||||
|
||||
#include "DRAMSys/common/DramATRecorder.h"
|
||||
#include "DRAMSys/common/TlmATRecorder.h"
|
||||
#include "DRAMSys/common/TlmRecorder.h"
|
||||
#include "DRAMSys/common/tlm2_base_protocol_checker.h"
|
||||
#include "DRAMSys/config/DRAMSysConfiguration.h"
|
||||
#include "DRAMSys/controller/Controller.h"
|
||||
#include "DRAMSys/controller/ControllerRecordable.h"
|
||||
#include "DRAMSys/controller/McConfig.h"
|
||||
#include "DRAMSys/simulation/AddressDecoder.h"
|
||||
#include "DRAMSys/simulation/Arbiter.h"
|
||||
#include "DRAMSys/simulation/Dram.h"
|
||||
#include "DRAMSys/simulation/SimConfig.h"
|
||||
|
||||
#include <list>
|
||||
@@ -125,6 +127,9 @@ private:
|
||||
// Transaction Recorders (one per channel).
|
||||
// They generate the output databases.
|
||||
std::vector<TlmRecorder> tlmRecorders;
|
||||
|
||||
std::vector<std::unique_ptr<TlmATRecorder>> tlmATRecorders;
|
||||
std::vector<std::unique_ptr<DramATRecorder>> dramATRecorders;
|
||||
};
|
||||
|
||||
} // namespace DRAMSys
|
||||
|
||||
@@ -41,7 +41,9 @@
|
||||
#include "Dram.h"
|
||||
|
||||
#include "DRAMSys/common/DebugManager.h"
|
||||
#include "DRAMSys/common/TlmRecorder.h"
|
||||
#include "DRAMSys/config/SimConfig.h"
|
||||
#include <sysc/kernel/sc_module.h>
|
||||
|
||||
#ifdef DRAMPOWER
|
||||
#include "LibDRAMPower.h"
|
||||
@@ -67,13 +69,18 @@ using namespace DRAMPower;
|
||||
namespace DRAMSys
|
||||
{
|
||||
|
||||
Dram::Dram(const sc_module_name& name, const SimConfig& simConfig, const MemSpec& memSpec) :
|
||||
Dram::Dram(const sc_module_name& name,
|
||||
const SimConfig& simConfig,
|
||||
const MemSpec& memSpec,
|
||||
TlmRecorder* tlmRecorder) :
|
||||
sc_module(name),
|
||||
memSpec(memSpec),
|
||||
storeMode(simConfig.storeMode),
|
||||
powerAnalysis(simConfig.powerAnalysis),
|
||||
channelSize(memSpec.getSimMemSizeInBytes() / memSpec.numberOfChannels),
|
||||
useMalloc(simConfig.useMalloc)
|
||||
useMalloc(simConfig.useMalloc),
|
||||
tlmRecorder(tlmRecorder),
|
||||
powerWindowSize(memSpec.tCK * simConfig.windowSize)
|
||||
{
|
||||
if (storeMode == Config::StoreModeType::Store)
|
||||
{
|
||||
@@ -109,6 +116,9 @@ Dram::Dram(const sc_module_name& name, const SimConfig& simConfig, const MemSpec
|
||||
{
|
||||
DRAMPower = std::make_unique<libDRAMPower>(memSpec.toDramPowerMemSpec(), false);
|
||||
}
|
||||
|
||||
if (simConfig.powerAnalysis && simConfig.enableWindowing)
|
||||
SC_THREAD(powerWindow);
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -132,6 +142,13 @@ void Dram::reportPower()
|
||||
std::cout << name() << std::string(" Average Power: ") << std::fixed << std::setprecision(2)
|
||||
<< DRAMPower->getPower().average_power * memSpec.devicesPerRank << std::string(" mW")
|
||||
<< std::endl;
|
||||
|
||||
if (tlmRecorder != nullptr)
|
||||
{
|
||||
tlmRecorder->recordPower(sc_time_stamp().to_seconds(),
|
||||
this->DRAMPower->getPower().window_average_power *
|
||||
this->memSpec.devicesPerRank);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -267,4 +284,47 @@ void Dram::deserialize(std::istream& stream)
|
||||
stream.read(reinterpret_cast<char*>(memory), channelSize);
|
||||
}
|
||||
|
||||
#ifdef DRAMPOWER
|
||||
// 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 Dram::powerWindow()
|
||||
{
|
||||
int64_t clkCycles = 0;
|
||||
|
||||
while (true)
|
||||
{
|
||||
// At the very beginning (zero clock cycles) the energy is 0, so we wait first
|
||||
sc_module::wait(powerWindowSize);
|
||||
|
||||
clkCycles = std::lround(sc_time_stamp() / this->memSpec.tCK);
|
||||
|
||||
this->DRAMPower->calcWindowEnergy(clkCycles);
|
||||
|
||||
// During operation the energy should never be zero since the device is always consuming
|
||||
assert(!this->DRAMPower->getEnergy().window_energy < 1e-05);
|
||||
|
||||
if (tlmRecorder)
|
||||
{
|
||||
// Store the time (in seconds) and the current average power (in mW) into the database
|
||||
tlmRecorder->recordPower(sc_time_stamp().to_seconds(),
|
||||
this->DRAMPower->getPower().window_average_power *
|
||||
this->memSpec.devicesPerRank);
|
||||
}
|
||||
|
||||
// Here considering that DRAMPower provides the energy in pJ and the power in mW
|
||||
PRINTDEBUGMESSAGE(this->name(),
|
||||
std::string("\tWindow Energy: \t") +
|
||||
std::to_string(this->DRAMPower->getEnergy().window_energy *
|
||||
this->memSpec.devicesPerRank) +
|
||||
std::string("\t[pJ]"));
|
||||
PRINTDEBUGMESSAGE(this->name(),
|
||||
std::string("\tWindow Average Power: \t") +
|
||||
std::to_string(this->DRAMPower->getPower().window_average_power *
|
||||
this->memSpec.devicesPerRank) +
|
||||
std::string("\t[mW]"));
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
} // namespace DRAMSys
|
||||
|
||||
@@ -43,6 +43,7 @@
|
||||
|
||||
#include "DRAMSys/common/Deserialize.h"
|
||||
#include "DRAMSys/common/Serialize.h"
|
||||
#include "DRAMSys/common/TlmRecorder.h"
|
||||
#include "DRAMSys/configuration/memspec/MemSpec.h"
|
||||
#include "DRAMSys/simulation/SimConfig.h"
|
||||
|
||||
@@ -68,8 +69,15 @@ protected:
|
||||
const uint64_t channelSize;
|
||||
const bool useMalloc;
|
||||
|
||||
TlmRecorder* const tlmRecorder;
|
||||
sc_core::sc_time powerWindowSize;
|
||||
|
||||
#ifdef DRAMPOWER
|
||||
std::unique_ptr<libDRAMPower> DRAMPower;
|
||||
// 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();
|
||||
#endif
|
||||
|
||||
virtual tlm::tlm_sync_enum nb_transport_fw(tlm::tlm_generic_payload& trans,
|
||||
@@ -82,7 +90,10 @@ protected:
|
||||
void executeWrite(const tlm::tlm_generic_payload& trans);
|
||||
|
||||
public:
|
||||
Dram(const sc_core::sc_module_name& name, const SimConfig& simConfig, const MemSpec& memSpec);
|
||||
Dram(const sc_core::sc_module_name& name,
|
||||
const SimConfig& simConfig,
|
||||
const MemSpec& memSpec,
|
||||
TlmRecorder* tlmRecorder);
|
||||
SC_HAS_PROCESS(Dram);
|
||||
|
||||
Dram(const Dram&) = delete;
|
||||
|
||||
@@ -1,121 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2019, RPTU Kaiserslautern-Landau
|
||||
* 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 "DramRecordable.h"
|
||||
|
||||
#include "DRAMSys/common/DebugManager.h"
|
||||
#include "DRAMSys/common/TlmRecorder.h"
|
||||
#include "DRAMSys/common/utils.h"
|
||||
|
||||
using namespace sc_core;
|
||||
using namespace tlm;
|
||||
|
||||
namespace DRAMSys
|
||||
{
|
||||
|
||||
DramRecordable::DramRecordable(const sc_module_name& name,
|
||||
const SimConfig& simConfig,
|
||||
const MemSpec& memSpec,
|
||||
TlmRecorder& tlmRecorder) :
|
||||
Dram(name, simConfig, memSpec),
|
||||
tlmRecorder(tlmRecorder),
|
||||
powerWindowSize(memSpec.tCK * simConfig.windowSize)
|
||||
{
|
||||
#ifdef DRAMPOWER
|
||||
// Create a thread that is triggered every $powerWindowSize
|
||||
// to generate a Power over Time plot in the Trace analyzer:
|
||||
if (simConfig.powerAnalysis && simConfig.enableWindowing)
|
||||
SC_THREAD(powerWindow);
|
||||
#endif
|
||||
}
|
||||
|
||||
void DramRecordable::reportPower()
|
||||
{
|
||||
Dram::reportPower();
|
||||
#ifdef DRAMPOWER
|
||||
tlmRecorder.recordPower(sc_time_stamp().to_seconds(),
|
||||
this->DRAMPower->getPower().window_average_power *
|
||||
this->memSpec.devicesPerRank);
|
||||
#endif
|
||||
}
|
||||
|
||||
tlm_sync_enum
|
||||
DramRecordable::nb_transport_fw(tlm_generic_payload& trans, tlm_phase& phase, sc_time& delay)
|
||||
{
|
||||
tlmRecorder.recordPhase(trans, phase, delay);
|
||||
return Dram::nb_transport_fw(trans, phase, delay);
|
||||
}
|
||||
|
||||
#ifdef DRAMPOWER
|
||||
// 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 DramRecordable::powerWindow()
|
||||
{
|
||||
int64_t clkCycles = 0;
|
||||
|
||||
while (true)
|
||||
{
|
||||
// At the very beginning (zero clock cycles) the energy is 0, so we wait first
|
||||
sc_module::wait(powerWindowSize);
|
||||
|
||||
clkCycles = std::lround(sc_time_stamp() / this->memSpec.tCK);
|
||||
|
||||
this->DRAMPower->calcWindowEnergy(clkCycles);
|
||||
|
||||
// During operation the energy should never be zero since the device is always consuming
|
||||
assert(!isEqual(this->DRAMPower->getEnergy().window_energy, 0.0));
|
||||
|
||||
// Store the time (in seconds) and the current average power (in mW) into the database
|
||||
tlmRecorder.recordPower(sc_time_stamp().to_seconds(),
|
||||
this->DRAMPower->getPower().window_average_power *
|
||||
this->memSpec.devicesPerRank);
|
||||
|
||||
// Here considering that DRAMPower provides the energy in pJ and the power in mW
|
||||
PRINTDEBUGMESSAGE(this->name(),
|
||||
std::string("\tWindow Energy: \t") +
|
||||
std::to_string(this->DRAMPower->getEnergy().window_energy *
|
||||
this->memSpec.devicesPerRank) +
|
||||
std::string("\t[pJ]"));
|
||||
PRINTDEBUGMESSAGE(this->name(),
|
||||
std::string("\tWindow Average Power: \t") +
|
||||
std::to_string(this->DRAMPower->getPower().window_average_power *
|
||||
this->memSpec.devicesPerRank) +
|
||||
std::string("\t[mW]"));
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
} // namespace DRAMSys
|
||||
@@ -1,90 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2019, RPTU Kaiserslautern-Landau
|
||||
* 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
|
||||
*/
|
||||
|
||||
#ifndef DRAMRECORDABLE_H
|
||||
#define DRAMRECORDABLE_H
|
||||
|
||||
#include "DRAMSys/common/TlmRecorder.h"
|
||||
#include "Dram.h"
|
||||
|
||||
#ifdef DRAMPOWER
|
||||
#include "LibDRAMPower.h"
|
||||
#endif
|
||||
|
||||
#include <systemc>
|
||||
#include <tlm>
|
||||
|
||||
namespace DRAMSys
|
||||
{
|
||||
|
||||
class DramRecordable : public Dram
|
||||
{
|
||||
public:
|
||||
DramRecordable(const sc_core::sc_module_name& name,
|
||||
const SimConfig& simConfig,
|
||||
const MemSpec& memSpec,
|
||||
TlmRecorder& tlmRecorder);
|
||||
SC_HAS_PROCESS(DramRecordable);
|
||||
|
||||
void reportPower() override;
|
||||
|
||||
private:
|
||||
tlm::tlm_sync_enum nb_transport_fw(tlm::tlm_generic_payload& trans,
|
||||
tlm::tlm_phase& phase,
|
||||
sc_core::sc_time& delay) override;
|
||||
|
||||
TlmRecorder& tlmRecorder;
|
||||
|
||||
sc_core::sc_time powerWindowSize;
|
||||
|
||||
// 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).
|
||||
static bool isEqual(double a, double b, const double epsilon = 1e-05)
|
||||
{
|
||||
return std::fabs(a - b) < epsilon;
|
||||
}
|
||||
|
||||
#ifdef DRAMPOWER
|
||||
// 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();
|
||||
#endif
|
||||
};
|
||||
|
||||
} // namespace DRAMSys
|
||||
|
||||
#endif // DRAMRECORDABLE_H
|
||||
Binary file not shown.
Binary file not shown.
Reference in New Issue
Block a user