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:
2025-04-15 12:54:06 +00:00
17 changed files with 533 additions and 471 deletions

View File

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

View 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

View 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

View 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

View 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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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