Split the bandwidth recording in two modules

This allows separate recording of the bandwidth between Arbiter -
Controller and Controller - Dram
This commit is contained in:
Jonathan Hager
2025-03-11 12:57:02 +01:00
parent f1445ab851
commit 0479184f72
8 changed files with 241 additions and 51 deletions

View File

@@ -39,7 +39,8 @@
add_library(libdramsys
DRAMSys/common/DebugManager.cpp
DRAMSys/common/TlmRecorder.cpp
DRAMSys/common/TlmRecorderWrapper.cpp
DRAMSys/common/TlmRecorderArbiter.cpp
DRAMSys/common/TlmRecorderDram.cpp
DRAMSys/common/dramExtensions.cpp
DRAMSys/common/utils.cpp
DRAMSys/configuration/memspec/MemSpec.cpp

View File

@@ -0,0 +1,99 @@
#include "TlmRecorderArbiter.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
{
TlmRecorderArbiter::TlmRecorderArbiter(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, &TlmRecorderArbiter::nb_transport_bw);
tSocket.register_nb_transport_fw(this, &TlmRecorderArbiter::nb_transport_fw);
if (enableBandwidth)
{
SC_METHOD(recordBandwidth);
sensitive << windowEvent;
if (enableWindowing)
{
windowEvent.notify(windowSizeTime);
nextWindowEventTime = windowSizeTime;
}
}
}
tlm::tlm_sync_enum TlmRecorderArbiter::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 TlmRecorderArbiter::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 TlmRecorderArbiter::recordBandwidth()
{
if (enableBandwidth && enableWindowing && sc_core::sc_time_stamp() == nextWindowEventTime)
{
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);
// sc_core::sc_time windowActiveTime =
// activeTimeMultiplier * static_cast<double>(windowNumberOfBytesServed);
// double windowAverageBandwidth = windowNumberOfBytesServed / maxBandwidth;
// tlmRecorder.recordBandwidth(sc_core::sc_time_stamp().to_seconds(),
// windowAverageBandwidth);
}
}
} // namespace DRAMSys

View File

@@ -0,0 +1,61 @@
#ifndef TLMRECORDERARBITER_H
#define TLMRECORDERARBITER_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 TlmRecorderArbiter : public sc_core::sc_module
{
SC_HAS_PROCESS(TlmRecorderArbiter);
public:
tlm_utils::simple_initiator_socket<TlmRecorderArbiter> iSocket;
tlm_utils::simple_target_socket<TlmRecorderArbiter> tSocket;
TlmRecorderArbiter(const sc_core::sc_module_name& name,
const SimConfig& simConfig,
const MemSpec& memspec,
TlmRecorder& tlmRecorder,
bool enableBandwidth);
~TlmRecorderArbiter() = 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);
private:
const MemSpec& memSpec;
// HACK: Refactor with shared pointers?
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 // TLMRECORDERARBITER_H

View File

@@ -1,4 +1,4 @@
#include "TlmRecorderWrapper.h"
#include "TlmRecorderDram.h"
#include "DRAMSys/configuration/memspec/MemSpec.h"
#include "DRAMSys/controller/Command.h"
#include "DRAMSys/simulation/SimConfig.h"
@@ -9,10 +9,11 @@
namespace DRAMSys
{
TlmRecorderWrapper::TlmRecorderWrapper(const sc_core::sc_module_name& name,
TlmRecorderDram::TlmRecorderDram(const sc_core::sc_module_name& name,
const SimConfig& simConfig,
const MemSpec& memSpec,
TlmRecorder& tlmRecorder) :
TlmRecorder& tlmRecorder,
bool enableBandwidth) :
sc_module(name),
tlmRecorder(tlmRecorder),
enableWindowing(simConfig.enableWindowing),
@@ -20,26 +21,30 @@ TlmRecorderWrapper::TlmRecorderWrapper(const sc_core::sc_module_name& name,
ranksPerChannel(memSpec.ranksPerChannel),
windowSizeTime(simConfig.windowSize * memSpec.tCK),
numberOfBeatsServed(memSpec.ranksPerChannel, 0),
activeTimeMultiplier(memSpec.tCK / memSpec.dataRate)
activeTimeMultiplier(memSpec.tCK / memSpec.dataRate),
enableBandwidth(enableBandwidth)
{
iSocket.register_nb_transport_bw(this, &TlmRecorderWrapper::nb_transport_bw);
tSocket.register_nb_transport_fw(this, &TlmRecorderWrapper::nb_transport_fw);
iSocket.register_nb_transport_bw(this, &TlmRecorderDram::nb_transport_bw);
tSocket.register_nb_transport_fw(this, &TlmRecorderDram::nb_transport_fw);
SC_METHOD(recordBandwidth);
sensitive << windowEvent;
if (enableWindowing)
if (enableBandwidth)
{
windowEvent.notify(windowSizeTime);
nextWindowEventTime = windowSizeTime;
SC_METHOD(recordBandwidth);
sensitive << windowEvent;
if (enableWindowing)
{
windowEvent.notify(windowSizeTime);
nextWindowEventTime = windowSizeTime;
}
}
}
tlm::tlm_sync_enum TlmRecorderWrapper::nb_transport_fw(tlm::tlm_generic_payload& trans,
tlm::tlm_sync_enum TlmRecorderDram::nb_transport_fw(tlm::tlm_generic_payload& trans,
tlm::tlm_phase& phase,
sc_core::sc_time& delay)
{
if (enableWindowing)
if (enableBandwidth && enableWindowing)
{
Command cmd{phase};
if (cmd.isCasCommand())
@@ -54,7 +59,7 @@ tlm::tlm_sync_enum TlmRecorderWrapper::nb_transport_fw(tlm::tlm_generic_payload&
return iSocket->nb_transport_fw(trans, phase, delay);
}
tlm::tlm_sync_enum TlmRecorderWrapper::nb_transport_bw(tlm::tlm_generic_payload& trans,
tlm::tlm_sync_enum TlmRecorderDram::nb_transport_bw(tlm::tlm_generic_payload& trans,
tlm::tlm_phase& phase,
sc_core::sc_time& delay)
{
@@ -62,9 +67,9 @@ tlm::tlm_sync_enum TlmRecorderWrapper::nb_transport_bw(tlm::tlm_generic_payload&
return tSocket->nb_transport_bw(trans, phase, delay);
}
void TlmRecorderWrapper::recordBandwidth()
void TlmRecorderDram::recordBandwidth()
{
if (enableWindowing && sc_core::sc_time_stamp() == nextWindowEventTime)
if (enableBandwidth && enableWindowing && sc_core::sc_time_stamp() == nextWindowEventTime)
{
windowEvent.notify(windowSizeTime);
nextWindowEventTime += windowSizeTime;

View File

@@ -1,5 +1,5 @@
#ifndef TLMRECORDERWRAPPER_H
#define TLMRECORDERWRAPPER_H
#ifndef TLMRECORDERDRAM_H
#define TLMRECORDERDRAM_H
#include "DRAMSys/configuration/memspec/MemSpec.h"
#include "DRAMSys/simulation/SimConfig.h"
@@ -14,20 +14,21 @@
namespace DRAMSys
{
class TlmRecorderWrapper : public sc_core::sc_module
class TlmRecorderDram : public sc_core::sc_module
{
SC_HAS_PROCESS(TlmRecorderWrapper);
SC_HAS_PROCESS(TlmRecorderDram);
public:
tlm_utils::simple_initiator_socket<TlmRecorderWrapper> iSocket;
tlm_utils::simple_target_socket<TlmRecorderWrapper> tSocket;
tlm_utils::simple_initiator_socket<TlmRecorderDram> iSocket;
tlm_utils::simple_target_socket<TlmRecorderDram> tSocket;
TlmRecorderWrapper(const sc_core::sc_module_name& name,
TlmRecorderDram(const sc_core::sc_module_name& name,
const SimConfig& simConfig,
const MemSpec& memspec,
TlmRecorder& tlmRecorder);
~TlmRecorderWrapper() = default;
TlmRecorder& tlmRecorder,
bool enableBandwidth);
~TlmRecorderDram() = default;
tlm::tlm_sync_enum nb_transport_fw(tlm::tlm_generic_payload& trans,
tlm::tlm_phase& phase,
@@ -49,9 +50,11 @@ private:
uint64_t lastNumberOfBeatsServed = 0;
const sc_core::sc_time activeTimeMultiplier;
bool enableBandwidth = false;
void recordBandwidth();
};
} // namespace DRAMSys
#endif // TLMRECORDERWRAPPER_H
#endif // TLMRECORDERDRAM_H

View File

@@ -342,10 +342,8 @@ void Controller::registerIdleCallback(std::function<void()> idleCallback)
void Controller::recordBufferDepth()
{
std::cout << "Method called ";
if (sc_time_stamp() == nextWindowEventTime)
{
std::cout << "If entered\n";
windowEvent.notify(windowSizeTime);
nextWindowEventTime += windowSizeTime;
@@ -355,7 +353,6 @@ void Controller::recordBufferDepth()
slidingAverageBufferDepth[index] = SC_ZERO_TIME;
}
std::cout << windowAverageBufferDepth[0] << "\n";
tlmRecorder.recordBufferDepth(sc_time_stamp().to_seconds(), windowAverageBufferDepth);
}
}

View File

@@ -106,16 +106,13 @@ DRAMSys::DRAMSys(const sc_core::sc_module_name& name, const Config::Configuratio
// Create controllers and DRAMs
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]));
controllers.emplace_back(std::make_unique<Controller>(
("controller" + std::to_string(i)).c_str(), mcConfig, *memSpec, simConfig, *addressDecoder, tlmRecorders[i]));
controllers.emplace_back(
std::make_unique<Controller>(("controller" + std::to_string(i)).c_str(),
mcConfig,
*memSpec,
simConfig,
*addressDecoder,
tlmRecorders[i]));
drams.emplace_back(std::make_unique<Dram>(
("dram" + std::to_string(i)).c_str(), simConfig, *memSpec, tlmRecorders[i]));
@@ -125,19 +122,34 @@ DRAMSys::DRAMSys(const sc_core::sc_module_name& name, const Config::Configuratio
std::make_unique<tlm_utils::tlm2_base_protocol_checker<>>(
("TLMCheckerController" + std::to_string(i)).c_str()));
tlmWrappers.emplace_back(std::make_unique<TlmRecorderWrapper>(
// Not recording bandwidth between Arbiter - Controller
tlmWrappersArbiter.emplace_back(std::make_unique<TlmRecorderArbiter>(
("TlmRecorderWrapper" + std::to_string(i)).c_str(),
simConfig,
*memSpec,
tlmRecorders[i]));
tlmRecorders[i],
false));
// Recording bandwidth between Controller - DRAM
tlmWrappersDram.emplace_back(std::make_unique<TlmRecorderDram>(
("TlmRecorderWrapper" + 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, simConfig, *addressDecoder, tlmRecorders[i]));
controllers.emplace_back(
std::make_unique<Controller>(("controller" + std::to_string(i)).c_str(),
mcConfig,
*memSpec,
simConfig,
*addressDecoder,
tlmRecorders[i]));
drams.emplace_back(std::make_unique<Dram>(
("dram" + std::to_string(i)).c_str(), simConfig, *memSpec, tlmRecorders[i]));
@@ -155,11 +167,22 @@ DRAMSys::DRAMSys(const sc_core::sc_module_name& name, const Config::Configuratio
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(tlmWrappersArbiter[i]->tSocket);
tlmWrappersArbiter[i]->iSocket.bind(controllers[i]->tSocket);
}
else if (simConfig.checkTLM2Protocol)
{
arbiter->iSocket.bind(controllersTlmCheckers[i]->target_socket);
controllersTlmCheckers[i]->initiator_socket.bind(controllers[i]->tSocket);
}
else if (simConfig.databaseRecording)
{
arbiter->iSocket.bind(tlmWrappersArbiter[i]->tSocket);
tlmWrappersArbiter[i]->iSocket.bind(controllers[i]->tSocket);
}
else
{
arbiter->iSocket.bind(controllers[i]->tSocket);
@@ -168,8 +191,8 @@ DRAMSys::DRAMSys(const sc_core::sc_module_name& name, const Config::Configuratio
// TODO: comments
if (simConfig.databaseRecording)
{
controllers[i]->iSocket.bind(tlmWrappers[i]->tSocket);
tlmWrappers[i]->iSocket.bind(drams[i]->tSocket);
controllers[i]->iSocket.bind(tlmWrappersDram[i]->tSocket);
tlmWrappersDram[i]->iSocket.bind(drams[i]->tSocket);
}
else
{

View File

@@ -42,7 +42,8 @@
#define DRAMSYS_H
#include "DRAMSys/common/TlmRecorder.h"
#include "DRAMSys/common/TlmRecorderWrapper.h"
#include "DRAMSys/common/TlmRecorderArbiter.h"
#include "DRAMSys/common/TlmRecorderDram.h"
#include "DRAMSys/common/tlm2_base_protocol_checker.h"
#include "DRAMSys/config/DRAMSysConfiguration.h"
#include "DRAMSys/controller/Controller.h"
@@ -128,8 +129,8 @@ private:
// They generate the output databases.
std::vector<TlmRecorder> tlmRecorders;
// TODO: Comments
std::vector<std::unique_ptr<TlmRecorderWrapper>> tlmWrappers;
std::vector<std::unique_ptr<TlmRecorderArbiter>> tlmWrappersArbiter;
std::vector<std::unique_ptr<TlmRecorderDram>> tlmWrappersDram;
};
} // namespace DRAMSys