Merge develop
This commit is contained in:
@@ -6,7 +6,7 @@ Initiators in the simulator are split up into two disctinct components: **Reques
|
||||
|
||||
**RequestProducers** are simple C++ classes that implement the `RequestProducer` interface. Upon calling the `nextRequest()` method of a producer, a new `Request` is either generated on-the-fly or constructed from a trace file.
|
||||
|
||||
**RequestIssuers** are the SystemC modules that connect with DRAMSys. Issuers have no knowledge of where the requests are coming from. They simply call their `nextRequest()` callback that it has been passed in the constructor to obtain the next request to be sent to DRAMSys. Using this concept, the generation and the issuing of request is completely decoupled to make very flexible initiator designs possible.
|
||||
**RequestIssuers** are the SystemC modules that connect to DRAMSys. Issuers have no knowledge of where the requests are coming from. They simply call their `nextRequest()` callback that it has been passed in the constructor to obtain the next request to be sent to DRAMSys. Using this concept, the generation and the issuing of request is completely decoupled to make very flexible initiator designs possible.
|
||||
|
||||
**Initiators** implement the `Initiator` interface, which describes how the initiator is bound to DRAMSys. This abstracts over the actual socket type used by the initiator.
|
||||
Complex initiators may implement the interface directly, but for simple cases, there exists the templated `SimpleInitiator<Producer>` class. This specialized initiator consists of only one producer and one issuer that operate together. The `StlPlayer` and `RowHammer` issuers make use of the `SimpleInitiator`.
|
||||
|
||||
@@ -33,28 +33,13 @@
|
||||
* Derek Christ
|
||||
*/
|
||||
|
||||
#include "simulator/Initiator.h"
|
||||
#include "simulator/MemoryManager.h"
|
||||
#include "simulator/SimpleInitiator.h"
|
||||
#include "simulator/generator/TrafficGenerator.h"
|
||||
#include "simulator/hammer/RowHammer.h"
|
||||
#include "simulator/player/StlPlayer.h"
|
||||
#include "simulator/util.h"
|
||||
#include "simulator/Simulator.h"
|
||||
|
||||
#include <DRAMSys/simulation/DRAMSysRecordable.h>
|
||||
|
||||
#include <systemc>
|
||||
#include <tlm>
|
||||
#include <tlm_utils/peq_with_cb_and_phase.h>
|
||||
#include <tlm_utils/simple_initiator_socket.h>
|
||||
#include <DRAMSys/config/DRAMSysConfiguration.h>
|
||||
|
||||
#include <filesystem>
|
||||
#include <fstream>
|
||||
#include <random>
|
||||
|
||||
static constexpr std::string_view TRACE_DIRECTORY = "traces";
|
||||
|
||||
int sc_main(int argc, char **argv)
|
||||
int sc_main(int argc, char** argv)
|
||||
{
|
||||
std::filesystem::path resourceDirectory = DRAMSYS_RESOURCE_DIR;
|
||||
if (argc >= 3)
|
||||
@@ -71,129 +56,8 @@ int sc_main(int argc, char **argv)
|
||||
DRAMSys::Config::Configuration configuration =
|
||||
DRAMSys::Config::from_path(baseConfig.c_str(), resourceDirectory.c_str());
|
||||
|
||||
if (!configuration.tracesetup.has_value())
|
||||
SC_REPORT_FATAL("Simulator", "No traffic initiators specified");
|
||||
|
||||
std::unique_ptr<DRAMSys::DRAMSys> dramSys;
|
||||
if (configuration.simconfig.DatabaseRecording.value_or(false))
|
||||
{
|
||||
dramSys = std::make_unique<DRAMSys::DRAMSysRecordable>("DRAMSys", configuration);
|
||||
}
|
||||
else
|
||||
{
|
||||
dramSys = std::make_unique<DRAMSys::DRAMSys>("DRAMSys", configuration);
|
||||
}
|
||||
|
||||
bool storageEnabled = dramSys->getConfig().storeMode == DRAMSys::Configuration::StoreMode::Store;
|
||||
MemoryManager memoryManager(storageEnabled);
|
||||
|
||||
std::vector<std::unique_ptr<Initiator>> initiators;
|
||||
|
||||
unsigned int terminatedInitiators = 0;
|
||||
auto termianteInitiator = [&initiators, &terminatedInitiators]()
|
||||
{
|
||||
terminatedInitiators++;
|
||||
|
||||
if (terminatedInitiators == initiators.size())
|
||||
sc_core::sc_stop();
|
||||
};
|
||||
|
||||
uint64_t totalTransactions{};
|
||||
uint64_t transactionsFinished = 0;
|
||||
auto transactionFinished = [&totalTransactions, &transactionsFinished, &configuration]()
|
||||
{
|
||||
transactionsFinished++;
|
||||
|
||||
if (configuration.simconfig.SimulationProgressBar.value_or(false))
|
||||
loadBar(transactionsFinished, totalTransactions);
|
||||
};
|
||||
|
||||
for (auto const &initiator_config : configuration.tracesetup.value())
|
||||
{
|
||||
uint64_t memorySize = dramSys->getConfig().memSpec->getSimMemSizeInBytes();
|
||||
unsigned int defaultDataLength = dramSys->getConfig().memSpec->defaultBytesPerBurst;
|
||||
|
||||
auto initiator = std::visit(
|
||||
[=, &memoryManager](auto &&config) -> std::unique_ptr<Initiator>
|
||||
{
|
||||
using T = std::decay_t<decltype(config)>;
|
||||
if constexpr (std::is_same_v<T, DRAMSys::Config::TrafficGenerator> ||
|
||||
std::is_same_v<T, DRAMSys::Config::TrafficGeneratorStateMachine>)
|
||||
{
|
||||
return std::make_unique<TrafficGenerator>(config,
|
||||
memoryManager,
|
||||
memorySize,
|
||||
defaultDataLength,
|
||||
transactionFinished,
|
||||
termianteInitiator);
|
||||
}
|
||||
else if constexpr (std::is_same_v<T, DRAMSys::Config::TracePlayer>)
|
||||
{
|
||||
std::filesystem::path tracePath =
|
||||
resourceDirectory / TRACE_DIRECTORY / config.name;
|
||||
|
||||
StlPlayer::TraceType traceType;
|
||||
|
||||
auto extension = tracePath.extension();
|
||||
if (extension == ".stl")
|
||||
traceType = StlPlayer::TraceType::Absolute;
|
||||
else if (extension == ".rstl")
|
||||
traceType = StlPlayer::TraceType::Relative;
|
||||
else
|
||||
{
|
||||
std::string report = extension.string() + " is not a valid trace format.";
|
||||
SC_REPORT_FATAL("Simulator", report.c_str());
|
||||
}
|
||||
|
||||
StlPlayer player(
|
||||
tracePath.c_str(), config.clkMhz, defaultDataLength, traceType, false);
|
||||
|
||||
return std::make_unique<SimpleInitiator<StlPlayer>>(config.name.c_str(),
|
||||
memoryManager,
|
||||
std::nullopt,
|
||||
std::nullopt,
|
||||
transactionFinished,
|
||||
termianteInitiator,
|
||||
std::move(player));
|
||||
}
|
||||
else if constexpr (std::is_same_v<T, DRAMSys::Config::RowHammer>)
|
||||
{
|
||||
RowHammer hammer(
|
||||
config.numRequests, config.clkMhz, config.rowIncrement, defaultDataLength);
|
||||
|
||||
return std::make_unique<SimpleInitiator<RowHammer>>(config.name.c_str(),
|
||||
memoryManager,
|
||||
1,
|
||||
1,
|
||||
transactionFinished,
|
||||
termianteInitiator,
|
||||
std::move(hammer));
|
||||
}
|
||||
},
|
||||
initiator_config);
|
||||
|
||||
totalTransactions += initiator->totalRequests();
|
||||
|
||||
initiator->bind(dramSys->tSocket);
|
||||
initiators.push_back(std::move(initiator));
|
||||
}
|
||||
|
||||
// Store the starting of the simulation in wall-clock time:
|
||||
auto start = std::chrono::high_resolution_clock::now();
|
||||
|
||||
// Start the SystemC simulation
|
||||
sc_set_stop_mode(sc_core::SC_STOP_FINISH_DELTA);
|
||||
sc_core::sc_start();
|
||||
|
||||
if (!sc_core::sc_end_of_simulation_invoked())
|
||||
{
|
||||
SC_REPORT_WARNING("sc_main", "Simulation stopped without explicit sc_stop()");
|
||||
sc_core::sc_stop();
|
||||
}
|
||||
|
||||
auto finish = std::chrono::high_resolution_clock::now();
|
||||
std::chrono::duration<double> elapsed = finish - start;
|
||||
std::cout << "Simulation took " + std::to_string(elapsed.count()) + " seconds." << std::endl;
|
||||
Simulator simulator(std::move(configuration), std::move(resourceDirectory));
|
||||
Simulator::run();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -38,11 +38,6 @@
|
||||
#include "MemoryManager.h"
|
||||
|
||||
#include <cstring>
|
||||
#include <sysc/kernel/sc_simcontext.h>
|
||||
#include <sysc/kernel/sc_time.h>
|
||||
#include <sysc/utils/sc_report.h>
|
||||
#include <tlm_core/tlm_2/tlm_generic_payload/tlm_gp.h>
|
||||
#include <tlm_core/tlm_2/tlm_generic_payload/tlm_phase.h>
|
||||
|
||||
using namespace tlm;
|
||||
using namespace sc_core;
|
||||
@@ -86,7 +81,7 @@ Cache::Cache(const sc_module_name &name,
|
||||
if (storageEnabled)
|
||||
{
|
||||
dataMemory.reserve(size);
|
||||
|
||||
|
||||
for (std::size_t set = 0; set < lineTable.size(); set++)
|
||||
{
|
||||
for (std::size_t way = 0; way < lineTable[set].size(); way++)
|
||||
@@ -593,7 +588,7 @@ void Cache::accessCacheAndSendResponse(tlm_generic_payload &trans)
|
||||
sc_time bwDelay = SC_ZERO_TIME;
|
||||
|
||||
trans.set_response_status(tlm::TLM_OK_RESPONSE);
|
||||
|
||||
|
||||
tlm_sync_enum returnValue = tSocket->nb_transport_bw(trans, bwPhase, bwDelay);
|
||||
if (returnValue == tlm::TLM_UPDATED) // TODO tlm_completed
|
||||
payloadEventQueue.notify(trans, bwPhase, bwDelay);
|
||||
|
||||
@@ -38,6 +38,7 @@
|
||||
|
||||
#include "MemoryManager.h"
|
||||
|
||||
#include <cstdint>
|
||||
#include <list>
|
||||
#include <queue>
|
||||
#include <systemc>
|
||||
|
||||
@@ -44,6 +44,7 @@ class SimpleInitiator : public Initiator
|
||||
public:
|
||||
SimpleInitiator(sc_core::sc_module_name const &name,
|
||||
MemoryManager &memoryManager,
|
||||
unsigned int clkMhz,
|
||||
std::optional<unsigned int> maxPendingReadRequests,
|
||||
std::optional<unsigned int> maxPendingWriteRequests,
|
||||
std::function<void()> transactionFinished,
|
||||
@@ -53,6 +54,7 @@ public:
|
||||
issuer(
|
||||
name,
|
||||
memoryManager,
|
||||
clkMhz,
|
||||
maxPendingReadRequests,
|
||||
maxPendingWriteRequests,
|
||||
[this] { return this->producer.nextRequest(); },
|
||||
|
||||
171
src/simulator/simulator/Simulator.cpp
Normal file
171
src/simulator/simulator/Simulator.cpp
Normal file
@@ -0,0 +1,171 @@
|
||||
/*
|
||||
* Copyright (c) 2023, 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:
|
||||
* Derek Christ
|
||||
*/
|
||||
|
||||
#include "Simulator.h"
|
||||
|
||||
#include "SimpleInitiator.h"
|
||||
#include "generator/TrafficGenerator.h"
|
||||
#include "hammer/RowHammer.h"
|
||||
#include "player/StlPlayer.h"
|
||||
#include "util.h"
|
||||
|
||||
Simulator::Simulator(DRAMSys::Config::Configuration configuration,
|
||||
std::filesystem::path resourceDirectory) :
|
||||
memoryManager(configuration.simconfig.StoreMode == DRAMSys::Config::StoreModeType::Store),
|
||||
configuration(std::move(configuration)),
|
||||
resourceDirectory(std::move(resourceDirectory))
|
||||
{
|
||||
if (this->configuration.simconfig.DatabaseRecording.value_or(false))
|
||||
{
|
||||
dramSys = std::make_unique<DRAMSys::DRAMSysRecordable>("DRAMSys", this->configuration);
|
||||
}
|
||||
else
|
||||
{
|
||||
dramSys = std::make_unique<DRAMSys::DRAMSys>("DRAMSys", this->configuration);
|
||||
}
|
||||
|
||||
terminateInitiator = [this]()
|
||||
{
|
||||
terminatedInitiators++;
|
||||
|
||||
if (terminatedInitiators == initiators.size())
|
||||
sc_core::sc_stop();
|
||||
};
|
||||
|
||||
finishTransaction = [this]()
|
||||
{
|
||||
transactionsFinished++;
|
||||
|
||||
if (this->configuration.simconfig.SimulationProgressBar.value_or(false))
|
||||
loadBar(transactionsFinished, totalTransactions);
|
||||
};
|
||||
|
||||
if (!configuration.tracesetup.has_value())
|
||||
SC_REPORT_FATAL("Simulator", "No traffic initiators specified");
|
||||
|
||||
for (const auto& initiatorConfig : *this->configuration.tracesetup)
|
||||
{
|
||||
auto initiator = instantiateInitiator(initiatorConfig);
|
||||
totalTransactions += initiator->totalRequests();
|
||||
initiator->bind(dramSys->tSocket);
|
||||
initiators.push_back(std::move(initiator));
|
||||
}
|
||||
}
|
||||
|
||||
std::unique_ptr<Initiator>
|
||||
Simulator::instantiateInitiator(const DRAMSys::Config::Initiator& initiator)
|
||||
{
|
||||
uint64_t memorySize = dramSys->getConfig().memSpec->getSimMemSizeInBytes();
|
||||
unsigned int defaultDataLength = dramSys->getConfig().memSpec->defaultBytesPerBurst;
|
||||
|
||||
return std::visit(
|
||||
[=](auto&& config) -> std::unique_ptr<Initiator>
|
||||
{
|
||||
using T = std::decay_t<decltype(config)>;
|
||||
if constexpr (std::is_same_v<T, DRAMSys::Config::TrafficGenerator> ||
|
||||
std::is_same_v<T, DRAMSys::Config::TrafficGeneratorStateMachine>)
|
||||
{
|
||||
return std::make_unique<TrafficGenerator>(config,
|
||||
memoryManager,
|
||||
memorySize,
|
||||
defaultDataLength,
|
||||
finishTransaction,
|
||||
terminateInitiator);
|
||||
}
|
||||
else if constexpr (std::is_same_v<T, DRAMSys::Config::TracePlayer>)
|
||||
{
|
||||
std::filesystem::path tracePath = resourceDirectory / TRACE_DIRECTORY / config.name;
|
||||
|
||||
std::optional<StlPlayer::TraceType> traceType;
|
||||
|
||||
auto extension = tracePath.extension();
|
||||
if (extension == ".stl")
|
||||
traceType = StlPlayer::TraceType::Absolute;
|
||||
else if (extension == ".rstl")
|
||||
traceType = StlPlayer::TraceType::Relative;
|
||||
|
||||
if (!traceType.has_value())
|
||||
{
|
||||
std::string report = extension.string() + " is not a valid trace format.";
|
||||
SC_REPORT_FATAL("Simulator", report.c_str());
|
||||
}
|
||||
|
||||
StlPlayer player(
|
||||
tracePath.c_str(), config.clkMhz, defaultDataLength, *traceType, false);
|
||||
|
||||
return std::make_unique<SimpleInitiator<StlPlayer>>(config.name.c_str(),
|
||||
memoryManager,
|
||||
config.clkMhz,
|
||||
std::nullopt,
|
||||
std::nullopt,
|
||||
finishTransaction,
|
||||
terminateInitiator,
|
||||
std::move(player));
|
||||
}
|
||||
else if constexpr (std::is_same_v<T, DRAMSys::Config::RowHammer>)
|
||||
{
|
||||
RowHammer hammer(config.numRequests, config.rowIncrement, defaultDataLength);
|
||||
|
||||
return std::make_unique<SimpleInitiator<RowHammer>>(config.name.c_str(),
|
||||
memoryManager,
|
||||
config.clkMhz,
|
||||
1,
|
||||
1,
|
||||
finishTransaction,
|
||||
terminateInitiator,
|
||||
std::move(hammer));
|
||||
}
|
||||
},
|
||||
initiator);
|
||||
}
|
||||
|
||||
void Simulator::run()
|
||||
{
|
||||
// Store the starting of the simulation in wall-clock time:
|
||||
auto start = std::chrono::high_resolution_clock::now();
|
||||
|
||||
// Start the SystemC simulation
|
||||
sc_core::sc_start();
|
||||
|
||||
if (!sc_core::sc_end_of_simulation_invoked())
|
||||
{
|
||||
SC_REPORT_WARNING("Simulator", "Simulation stopped without explicit sc_stop()");
|
||||
sc_core::sc_stop();
|
||||
}
|
||||
|
||||
auto finish = std::chrono::high_resolution_clock::now();
|
||||
std::chrono::duration<double> elapsed = finish - start;
|
||||
std::cout << "Simulation took " + std::to_string(elapsed.count()) + " seconds." << std::endl;
|
||||
}
|
||||
71
src/simulator/simulator/Simulator.h
Normal file
71
src/simulator/simulator/Simulator.h
Normal file
@@ -0,0 +1,71 @@
|
||||
/*
|
||||
* Copyright (c) 2023, 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:
|
||||
* Derek Christ
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "Initiator.h"
|
||||
#include "MemoryManager.h"
|
||||
|
||||
#include <DRAMSys/config/DRAMSysConfiguration.h>
|
||||
#include <DRAMSys/simulation/DRAMSysRecordable.h>
|
||||
|
||||
static constexpr std::string_view TRACE_DIRECTORY = "traces";
|
||||
|
||||
class Simulator
|
||||
{
|
||||
public:
|
||||
Simulator(DRAMSys::Config::Configuration configuration,
|
||||
std::filesystem::path resourceDirectory);
|
||||
|
||||
static void run();
|
||||
|
||||
private:
|
||||
std::unique_ptr<Initiator> instantiateInitiator(const DRAMSys::Config::Initiator& initiator);
|
||||
|
||||
MemoryManager memoryManager;
|
||||
|
||||
DRAMSys::Config::Configuration configuration;
|
||||
std::filesystem::path resourceDirectory;
|
||||
|
||||
std::unique_ptr<DRAMSys::DRAMSys> dramSys;
|
||||
std::vector<std::unique_ptr<Initiator>> initiators;
|
||||
|
||||
std::function<void()> terminateInitiator;
|
||||
std::function<void()> finishTransaction;
|
||||
|
||||
unsigned int terminatedInitiators = 0;
|
||||
uint64_t totalTransactions{};
|
||||
uint64_t transactionsFinished = 0;
|
||||
};
|
||||
@@ -39,7 +39,6 @@
|
||||
RandomProducer::RandomProducer(uint64_t numRequests,
|
||||
std::optional<uint64_t> seed,
|
||||
double rwRatio,
|
||||
unsigned int clkMhz,
|
||||
std::optional<uint64_t> minAddress,
|
||||
std::optional<uint64_t> maxAddress,
|
||||
uint64_t memorySize,
|
||||
@@ -48,7 +47,6 @@ RandomProducer::RandomProducer(uint64_t numRequests,
|
||||
: numberOfRequests(numRequests),
|
||||
seed(seed.value_or(DEFAULT_SEED)),
|
||||
rwRatio(rwRatio),
|
||||
generatorPeriod(sc_core::sc_time(1.0 / static_cast<double>(clkMhz), sc_core::SC_US)),
|
||||
dataLength(dataLength),
|
||||
dataAlignment(dataAlignment),
|
||||
randomGenerator(this->seed),
|
||||
@@ -79,7 +77,7 @@ Request RandomProducer::nextRequest()
|
||||
request.command = readWriteDistribution(randomGenerator) < rwRatio ? Request::Command::Read
|
||||
: Request::Command::Write;
|
||||
request.length = dataLength;
|
||||
request.delay = generatorPeriod;
|
||||
request.delay = sc_core::SC_ZERO_TIME;
|
||||
|
||||
return request;
|
||||
}
|
||||
|
||||
@@ -46,7 +46,6 @@ public:
|
||||
RandomProducer(uint64_t numRequests,
|
||||
std::optional<uint64_t> seed,
|
||||
double rwRatio,
|
||||
unsigned int clkMhz,
|
||||
std::optional<uint64_t> minAddress,
|
||||
std::optional<uint64_t> maxAddress,
|
||||
uint64_t memorySize,
|
||||
@@ -56,12 +55,10 @@ public:
|
||||
Request nextRequest() override;
|
||||
|
||||
uint64_t totalRequests() override { return numberOfRequests; }
|
||||
sc_core::sc_time clkPeriod() override { return generatorPeriod; }
|
||||
|
||||
const uint64_t numberOfRequests;
|
||||
const uint64_t seed;
|
||||
const double rwRatio;
|
||||
const sc_core::sc_time generatorPeriod;
|
||||
const unsigned int dataLength;
|
||||
const unsigned int dataAlignment;
|
||||
|
||||
|
||||
@@ -39,7 +39,6 @@
|
||||
SequentialProducer::SequentialProducer(uint64_t numRequests,
|
||||
std::optional<uint64_t> seed,
|
||||
double rwRatio,
|
||||
unsigned int clkMhz,
|
||||
std::optional<uint64_t> addressIncrement,
|
||||
std::optional<uint64_t> minAddress,
|
||||
std::optional<uint64_t> maxAddress,
|
||||
@@ -51,7 +50,6 @@ SequentialProducer::SequentialProducer(uint64_t numRequests,
|
||||
maxAddress(maxAddress.value_or(memorySize - 1)),
|
||||
seed(seed.value_or(DEFAULT_SEED)),
|
||||
rwRatio(rwRatio),
|
||||
generatorPeriod(sc_core::sc_time(1.0 / static_cast<double>(clkMhz), sc_core::SC_US)),
|
||||
dataLength(dataLength),
|
||||
randomGenerator(this->seed)
|
||||
{
|
||||
@@ -75,7 +73,7 @@ Request SequentialProducer::nextRequest()
|
||||
request.command = readWriteDistribution(randomGenerator) < rwRatio ? Request::Command::Read
|
||||
: Request::Command::Write;
|
||||
request.length = dataLength;
|
||||
request.delay = generatorPeriod;
|
||||
request.delay = sc_core::SC_ZERO_TIME;
|
||||
|
||||
generatedRequests++;
|
||||
return request;
|
||||
|
||||
@@ -46,7 +46,6 @@ public:
|
||||
SequentialProducer(uint64_t numRequests,
|
||||
std::optional<uint64_t> seed,
|
||||
double rwRatio,
|
||||
unsigned int clkMhz,
|
||||
std::optional<uint64_t> addressIncrement,
|
||||
std::optional<uint64_t> minAddress,
|
||||
std::optional<uint64_t> maxAddress,
|
||||
@@ -56,7 +55,6 @@ public:
|
||||
Request nextRequest() override;
|
||||
|
||||
uint64_t totalRequests() override { return numberOfRequests; }
|
||||
sc_core::sc_time clkPeriod() override { return generatorPeriod; }
|
||||
void reset() override { generatedRequests = 0; }
|
||||
|
||||
const uint64_t numberOfRequests;
|
||||
@@ -65,7 +63,6 @@ public:
|
||||
const uint64_t maxAddress;
|
||||
const uint64_t seed;
|
||||
const double rwRatio;
|
||||
const sc_core::sc_time generatorPeriod;
|
||||
const unsigned int dataLength;
|
||||
|
||||
std::default_random_engine randomGenerator;
|
||||
|
||||
@@ -35,43 +35,44 @@
|
||||
|
||||
#include "TrafficGenerator.h"
|
||||
|
||||
TrafficGenerator::TrafficGenerator(DRAMSys::Config::TrafficGeneratorStateMachine const &config,
|
||||
MemoryManager &memoryManager,
|
||||
TrafficGenerator::TrafficGenerator(DRAMSys::Config::TrafficGeneratorStateMachine const& config,
|
||||
MemoryManager& memoryManager,
|
||||
uint64_t memorySize,
|
||||
unsigned int defaultDataLength,
|
||||
std::function<void()> transactionFinished,
|
||||
std::function<void()> terminateInitiator)
|
||||
: stateTransistions(config.transitions),
|
||||
consumer(
|
||||
config.name.c_str(),
|
||||
memoryManager,
|
||||
config.maxPendingReadRequests,
|
||||
config.maxPendingWriteRequests,
|
||||
[this] { return nextRequest(); },
|
||||
std::move(transactionFinished),
|
||||
std::move(terminateInitiator))
|
||||
std::function<void()> terminateInitiator) :
|
||||
stateTransistions(config.transitions),
|
||||
generatorPeriod(sc_core::sc_time(1.0 / static_cast<double>(config.clkMhz), sc_core::SC_US)),
|
||||
issuer(
|
||||
config.name.c_str(),
|
||||
memoryManager,
|
||||
config.clkMhz,
|
||||
config.maxPendingReadRequests,
|
||||
config.maxPendingWriteRequests,
|
||||
[this] { return nextRequest(); },
|
||||
std::move(transactionFinished),
|
||||
std::move(terminateInitiator))
|
||||
{
|
||||
unsigned int dataLength = config.dataLength.value_or(defaultDataLength);
|
||||
unsigned int dataAlignment = config.dataAlignment.value_or(dataLength);
|
||||
|
||||
for (auto const &state : config.states)
|
||||
for (auto const& state : config.states)
|
||||
{
|
||||
std::visit(
|
||||
[=, &config](auto &&arg)
|
||||
[=, &config](auto&& arg)
|
||||
{
|
||||
using DRAMSys::Config::TrafficGeneratorActiveState;
|
||||
using DRAMSys::Config::TrafficGeneratorIdleState;
|
||||
using T = std::decay_t<decltype(arg)>;
|
||||
if constexpr (std::is_same_v<T, TrafficGeneratorActiveState>)
|
||||
{
|
||||
auto const &activeState = arg;
|
||||
auto const& activeState = arg;
|
||||
if (activeState.addressDistribution ==
|
||||
DRAMSys::Config::AddressDistribution::Random)
|
||||
{
|
||||
auto producer = std::make_unique<RandomProducer>(activeState.numRequests,
|
||||
config.seed,
|
||||
activeState.rwRatio,
|
||||
config.clkMhz,
|
||||
activeState.minAddress,
|
||||
activeState.maxAddress,
|
||||
memorySize,
|
||||
@@ -86,7 +87,6 @@ TrafficGenerator::TrafficGenerator(DRAMSys::Config::TrafficGeneratorStateMachine
|
||||
std::make_unique<SequentialProducer>(activeState.numRequests,
|
||||
config.seed,
|
||||
activeState.rwRatio,
|
||||
config.clkMhz,
|
||||
activeState.addressIncrement,
|
||||
activeState.minAddress,
|
||||
activeState.maxAddress,
|
||||
@@ -98,7 +98,7 @@ TrafficGenerator::TrafficGenerator(DRAMSys::Config::TrafficGeneratorStateMachine
|
||||
}
|
||||
else if constexpr (std::is_same_v<T, TrafficGeneratorIdleState>)
|
||||
{
|
||||
auto const &idleState = arg;
|
||||
auto const& idleState = arg;
|
||||
idleStateClks.emplace(idleState.id, idleState.idleClks);
|
||||
}
|
||||
},
|
||||
@@ -106,20 +106,22 @@ TrafficGenerator::TrafficGenerator(DRAMSys::Config::TrafficGeneratorStateMachine
|
||||
}
|
||||
}
|
||||
|
||||
TrafficGenerator::TrafficGenerator(DRAMSys::Config::TrafficGenerator const &config,
|
||||
MemoryManager &memoryManager,
|
||||
TrafficGenerator::TrafficGenerator(DRAMSys::Config::TrafficGenerator const& config,
|
||||
MemoryManager& memoryManager,
|
||||
uint64_t memorySize,
|
||||
unsigned int defaultDataLength,
|
||||
std::function<void()> transactionFinished,
|
||||
std::function<void()> terminateInitiator)
|
||||
: consumer(
|
||||
config.name.c_str(),
|
||||
memoryManager,
|
||||
config.maxPendingReadRequests,
|
||||
config.maxPendingWriteRequests,
|
||||
[this] { return nextRequest(); },
|
||||
std::move(transactionFinished),
|
||||
std::move(terminateInitiator))
|
||||
std::function<void()> terminateInitiator) :
|
||||
generatorPeriod(sc_core::sc_time(1.0 / static_cast<double>(config.clkMhz), sc_core::SC_US)),
|
||||
issuer(
|
||||
config.name.c_str(),
|
||||
memoryManager,
|
||||
config.clkMhz,
|
||||
config.maxPendingReadRequests,
|
||||
config.maxPendingWriteRequests,
|
||||
[this] { return nextRequest(); },
|
||||
std::move(transactionFinished),
|
||||
std::move(terminateInitiator))
|
||||
{
|
||||
unsigned int dataLength = config.dataLength.value_or(defaultDataLength);
|
||||
unsigned int dataAlignment = config.dataAlignment.value_or(dataLength);
|
||||
@@ -129,7 +131,6 @@ TrafficGenerator::TrafficGenerator(DRAMSys::Config::TrafficGenerator const &conf
|
||||
auto producer = std::make_unique<RandomProducer>(config.numRequests,
|
||||
config.seed,
|
||||
config.rwRatio,
|
||||
config.clkMhz,
|
||||
config.minAddress,
|
||||
config.maxAddress,
|
||||
memorySize,
|
||||
@@ -142,7 +143,6 @@ TrafficGenerator::TrafficGenerator(DRAMSys::Config::TrafficGenerator const &conf
|
||||
auto producer = std::make_unique<SequentialProducer>(config.numRequests,
|
||||
config.seed,
|
||||
config.rwRatio,
|
||||
config.clkMhz,
|
||||
config.addressIncrement,
|
||||
config.minAddress,
|
||||
config.maxAddress,
|
||||
@@ -183,9 +183,9 @@ Request TrafficGenerator::nextRequest()
|
||||
}
|
||||
|
||||
requestsInState++;
|
||||
|
||||
|
||||
Request request = producers[currentState]->nextRequest();
|
||||
request.delay += producers[currentState]->clkPeriod() * clksToIdle;
|
||||
request.delay += generatorPeriod * static_cast<double>(clksToIdle);
|
||||
return request;
|
||||
}
|
||||
|
||||
|
||||
@@ -60,7 +60,7 @@ public:
|
||||
std::function<void()> transactionFinished,
|
||||
std::function<void()> terminateInitiator);
|
||||
|
||||
void bind(tlm_utils::multi_target_base<> &target) override { consumer.iSocket.bind(target); }
|
||||
void bind(tlm_utils::multi_target_base<> &target) override { issuer.iSocket.bind(target); }
|
||||
|
||||
uint64_t totalRequests() override;
|
||||
Request nextRequest();
|
||||
@@ -74,9 +74,10 @@ private:
|
||||
|
||||
using IdleClks = uint64_t;
|
||||
std::unordered_map<unsigned int, IdleClks> idleStateClks;
|
||||
const sc_core::sc_time generatorPeriod;
|
||||
|
||||
std::default_random_engine randomGenerator;
|
||||
|
||||
std::unordered_map<unsigned int, std::unique_ptr<RequestProducer>> producers;
|
||||
RequestIssuer consumer;
|
||||
RequestIssuer issuer;
|
||||
};
|
||||
|
||||
@@ -36,11 +36,9 @@
|
||||
#include "RowHammer.h"
|
||||
|
||||
RowHammer::RowHammer(uint64_t numRequests,
|
||||
unsigned int clkMhz,
|
||||
uint64_t rowIncrement,
|
||||
unsigned int dataLength)
|
||||
: numberOfRequests(numRequests),
|
||||
generatorPeriod(sc_core::sc_time(1.0 / static_cast<double>(clkMhz), sc_core::SC_US)),
|
||||
dataLength(dataLength),
|
||||
rowIncrement(rowIncrement)
|
||||
{
|
||||
@@ -62,6 +60,6 @@ Request RowHammer::nextRequest()
|
||||
request.address = currentAddress;
|
||||
request.command = Request::Command::Read;
|
||||
request.length = dataLength;
|
||||
request.delay = generatorPeriod;
|
||||
request.delay = sc_core::SC_ZERO_TIME;
|
||||
return request;
|
||||
}
|
||||
|
||||
@@ -43,16 +43,13 @@ class RowHammer : public RequestProducer
|
||||
{
|
||||
public:
|
||||
RowHammer(uint64_t numRequests,
|
||||
unsigned int clkMhz,
|
||||
uint64_t rowIncrement,
|
||||
unsigned int dataLength);
|
||||
|
||||
Request nextRequest() override;
|
||||
sc_core::sc_time clkPeriod() override { return generatorPeriod; }
|
||||
uint64_t totalRequests() override { return numberOfRequests; }
|
||||
|
||||
const uint64_t numberOfRequests;
|
||||
const sc_core::sc_time generatorPeriod;
|
||||
const unsigned int dataLength;
|
||||
const uint64_t rowIncrement;
|
||||
|
||||
|
||||
@@ -71,6 +71,9 @@ StlPlayer::StlPlayer(std::string_view tracePath,
|
||||
if (line.size() > 1 && line[0] != '#')
|
||||
numberOfLines++;
|
||||
}
|
||||
if (numberOfLines == 0)
|
||||
SC_REPORT_FATAL("StlPlayer",
|
||||
(std::string("Empty trace ") + tracePath.data()).c_str());
|
||||
traceFile.clear();
|
||||
traceFile.seekg(0);
|
||||
}
|
||||
@@ -94,17 +97,15 @@ Request StlPlayer::nextRequest()
|
||||
}
|
||||
}
|
||||
|
||||
sc_core::sc_time delay = readoutIt->delay;
|
||||
sc_core::sc_time offset = playerPeriod - (sc_core::sc_time_stamp() % playerPeriod);
|
||||
|
||||
sc_core::sc_time delay;
|
||||
if (traceType == TraceType::Absolute)
|
||||
{
|
||||
delay = std::max(sc_core::sc_time_stamp() + offset, delay);
|
||||
delay -= sc_core::sc_time_stamp();
|
||||
bool behindSchedule = sc_core::sc_time_stamp() > readoutIt->delay;
|
||||
delay = behindSchedule ? sc_core::SC_ZERO_TIME : readoutIt->delay - sc_core::sc_time_stamp();
|
||||
}
|
||||
else // if (traceType == TraceType::Relative)
|
||||
{
|
||||
delay = offset + delay;
|
||||
delay = readoutIt->delay;
|
||||
}
|
||||
|
||||
Request request(*readoutIt);
|
||||
@@ -143,69 +144,78 @@ void StlPlayer::parseTraceFile()
|
||||
|
||||
iss.str(line);
|
||||
|
||||
// Get the timestamp for the transaction.
|
||||
iss >> element;
|
||||
if (element.empty())
|
||||
SC_REPORT_FATAL(
|
||||
"StlPlayer",
|
||||
("Malformed trace file line " + std::to_string(currentLine) + ".").c_str());
|
||||
|
||||
content.delay = playerPeriod * static_cast<double>(std::stoull(element));
|
||||
|
||||
// Get the optional burst length and command
|
||||
iss >> element;
|
||||
if (element.empty())
|
||||
SC_REPORT_FATAL(
|
||||
"StlPlayer",
|
||||
("Malformed trace file line " + std::to_string(currentLine) + ".").c_str());
|
||||
|
||||
if (element.at(0) == '(')
|
||||
try
|
||||
{
|
||||
element.erase(0, 1);
|
||||
content.length = std::stoul(element);
|
||||
// Get the timestamp for the transaction.
|
||||
iss >> element;
|
||||
if (element.empty())
|
||||
SC_REPORT_FATAL(
|
||||
"StlPlayer",
|
||||
("Malformed trace file line " + std::to_string(currentLine) + ".").c_str());
|
||||
}
|
||||
else
|
||||
content.length = defaultDataLength;
|
||||
"StlPlayer",
|
||||
("Malformed trace file line " + std::to_string(currentLine) + ".").c_str());
|
||||
|
||||
if (element == "read")
|
||||
content.command = Request::Command::Read;
|
||||
else if (element == "write")
|
||||
content.command = Request::Command::Write;
|
||||
else
|
||||
SC_REPORT_FATAL(
|
||||
"StlPlayer",
|
||||
("Malformed trace file line " + std::to_string(currentLine) + ".").c_str());
|
||||
content.delay = playerPeriod * static_cast<double>(std::stoull(element));
|
||||
|
||||
// Get the address.
|
||||
iss >> element;
|
||||
if (element.empty())
|
||||
SC_REPORT_FATAL(
|
||||
"StlPlayer",
|
||||
("Malformed trace file line " + std::to_string(currentLine) + ".").c_str());
|
||||
content.address = std::stoull(element, nullptr, 16);
|
||||
|
||||
// Get the data if necessary.
|
||||
if (storageEnabled && content.command == Request::Command::Write)
|
||||
{
|
||||
// The input trace file must provide the data to be stored into the memory.
|
||||
// Get the optional burst length and command
|
||||
iss >> element;
|
||||
|
||||
// Check if data length in the trace file is correct.
|
||||
// We need two characters to represent 1 byte in hexadecimal. Offset for 0x prefix.
|
||||
if (element.length() != (content.length * 2 + 2))
|
||||
if (element.empty())
|
||||
SC_REPORT_FATAL(
|
||||
"StlPlayer",
|
||||
("Malformed trace file line " + std::to_string(currentLine) + ".").c_str());
|
||||
|
||||
if (element.at(0) == '(')
|
||||
{
|
||||
element.erase(0, 1);
|
||||
content.length = std::stoul(element);
|
||||
iss >> element;
|
||||
if (element.empty())
|
||||
SC_REPORT_FATAL(
|
||||
"StlPlayer",
|
||||
("Malformed trace file line " + std::to_string(currentLine) + ".").c_str());
|
||||
}
|
||||
else
|
||||
content.length = defaultDataLength;
|
||||
|
||||
if (element == "read")
|
||||
content.command = Request::Command::Read;
|
||||
else if (element == "write")
|
||||
content.command = Request::Command::Write;
|
||||
else
|
||||
SC_REPORT_FATAL(
|
||||
"StlPlayer",
|
||||
("Malformed trace file line " + std::to_string(currentLine) + ".").c_str());
|
||||
|
||||
// Get the address.
|
||||
iss >> element;
|
||||
if (element.empty())
|
||||
SC_REPORT_FATAL(
|
||||
"StlPlayer",
|
||||
("Malformed trace file line " + std::to_string(currentLine) + ".").c_str());
|
||||
content.address = std::stoull(element, nullptr, 16);
|
||||
|
||||
// Get the data if necessary.
|
||||
if (storageEnabled && content.command == Request::Command::Write)
|
||||
{
|
||||
// The input trace file must provide the data to be stored into the memory.
|
||||
iss >> element;
|
||||
|
||||
// Check if data length in the trace file is correct.
|
||||
// We need two characters to represent 1 byte in hexadecimal. Offset for 0x prefix.
|
||||
if (element.length() != (content.length * 2 + 2))
|
||||
SC_REPORT_FATAL(
|
||||
"StlPlayer",
|
||||
("Malformed trace file line " + std::to_string(currentLine) + ".").c_str());
|
||||
|
||||
// Set data
|
||||
for (unsigned i = 0; i < content.length; i++)
|
||||
content.data.emplace_back(static_cast<unsigned char>(
|
||||
std::stoi(element.substr(i * 2 + 2, 2), nullptr, 16)));
|
||||
}
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
SC_REPORT_FATAL(
|
||||
"StlPlayer",
|
||||
("Malformed trace file line " + std::to_string(currentLine) + ".").c_str());
|
||||
|
||||
// Set data
|
||||
for (unsigned i = 0; i < content.length; i++)
|
||||
content.data.emplace_back(static_cast<unsigned char>(
|
||||
std::stoi(element.substr(i * 2 + 2, 2), nullptr, 16)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -46,6 +46,7 @@
|
||||
#include <systemc>
|
||||
#include <tlm>
|
||||
|
||||
#include <array>
|
||||
#include <fstream>
|
||||
#include <memory>
|
||||
#include <thread>
|
||||
@@ -68,7 +69,6 @@ public:
|
||||
|
||||
Request nextRequest() override;
|
||||
|
||||
sc_core::sc_time clkPeriod() override { return playerPeriod; }
|
||||
uint64_t totalRequests() override { return numberOfLines; }
|
||||
|
||||
private:
|
||||
|
||||
@@ -37,6 +37,7 @@
|
||||
|
||||
RequestIssuer::RequestIssuer(sc_core::sc_module_name const &name,
|
||||
MemoryManager &memoryManager,
|
||||
unsigned int clkMhz,
|
||||
std::optional<unsigned int> maxPendingReadRequests,
|
||||
std::optional<unsigned int> maxPendingWriteRequests,
|
||||
std::function<Request()> nextRequest,
|
||||
@@ -45,6 +46,7 @@ RequestIssuer::RequestIssuer(sc_core::sc_module_name const &name,
|
||||
: sc_module(name),
|
||||
payloadEventQueue(this, &RequestIssuer::peqCallback),
|
||||
memoryManager(memoryManager),
|
||||
clkPeriod(sc_core::sc_time(1.0 / static_cast<double>(clkMhz), sc_core::SC_US)),
|
||||
maxPendingReadRequests(maxPendingReadRequests),
|
||||
maxPendingWriteRequests(maxPendingWriteRequests),
|
||||
transactionFinished(std::move(transactionFinished)),
|
||||
@@ -79,11 +81,22 @@ void RequestIssuer::sendNextRequest()
|
||||
tlm::tlm_phase phase = tlm::BEGIN_REQ;
|
||||
sc_core::sc_time delay = request.delay;
|
||||
|
||||
if (transactionsSent == 0)
|
||||
delay = sc_core::SC_ZERO_TIME;
|
||||
sc_core::sc_time sendingTime = sc_core::sc_time_stamp() + delay;
|
||||
|
||||
bool needsOffset = (sendingTime % clkPeriod) != sc_core::SC_ZERO_TIME;
|
||||
if (needsOffset)
|
||||
{
|
||||
sendingTime += clkPeriod;
|
||||
sendingTime -= sendingTime % clkPeriod;
|
||||
}
|
||||
|
||||
if (sendingTime == lastEndRequest)
|
||||
{
|
||||
sendingTime += clkPeriod;
|
||||
}
|
||||
|
||||
delay = sendingTime - sc_core::sc_time_stamp();
|
||||
iSocket->nb_transport_fw(payload, phase, delay);
|
||||
transactionInProgress = true;
|
||||
|
||||
if (request.command == Request::Command::Read)
|
||||
pendingReadRequests++;
|
||||
@@ -111,6 +124,8 @@ void RequestIssuer::peqCallback(tlm::tlm_generic_payload &payload, const tlm::tl
|
||||
{
|
||||
if (phase == tlm::END_REQ)
|
||||
{
|
||||
lastEndRequest = sc_core::sc_time_stamp();
|
||||
|
||||
if (nextRequestSendable())
|
||||
sendNextRequest();
|
||||
else
|
||||
@@ -118,12 +133,11 @@ void RequestIssuer::peqCallback(tlm::tlm_generic_payload &payload, const tlm::tl
|
||||
}
|
||||
else if (phase == tlm::BEGIN_RESP)
|
||||
{
|
||||
tlm::tlm_phase phase = tlm::END_RESP;
|
||||
tlm::tlm_phase nextPhase = tlm::END_RESP;
|
||||
sc_core::sc_time delay = sc_core::SC_ZERO_TIME;
|
||||
iSocket->nb_transport_fw(payload, phase, delay);
|
||||
iSocket->nb_transport_fw(payload, nextPhase, delay);
|
||||
|
||||
payload.release();
|
||||
transactionInProgress = false;
|
||||
|
||||
transactionFinished();
|
||||
|
||||
|
||||
@@ -52,6 +52,7 @@ public:
|
||||
|
||||
RequestIssuer(sc_core::sc_module_name const &name,
|
||||
MemoryManager &memoryManager,
|
||||
unsigned int clkMhz,
|
||||
std::optional<unsigned int> maxPendingReadRequests,
|
||||
std::optional<unsigned int> maxPendingWriteRequests,
|
||||
std::function<Request()> nextRequest,
|
||||
@@ -63,20 +64,20 @@ private:
|
||||
tlm_utils::peq_with_cb_and_phase<RequestIssuer> payloadEventQueue;
|
||||
MemoryManager &memoryManager;
|
||||
|
||||
bool transactionInProgress = false;
|
||||
const sc_core::sc_time clkPeriod;
|
||||
|
||||
bool transactionPostponed = false;
|
||||
bool finished = false;
|
||||
|
||||
uint64_t transactionsSent = 0;
|
||||
uint64_t transactionsReceived = 0;
|
||||
sc_core::sc_time lastEndRequest = sc_core::sc_max_time();
|
||||
|
||||
unsigned int pendingReadRequests = 0;
|
||||
unsigned int pendingWriteRequests = 0;
|
||||
const std::optional<unsigned int> maxPendingReadRequests;
|
||||
const std::optional<unsigned int> maxPendingWriteRequests;
|
||||
|
||||
unsigned int activeProducers = 0;
|
||||
|
||||
std::function<void()> transactionFinished;
|
||||
std::function<void()> terminate;
|
||||
std::function<Request()> nextRequest;
|
||||
|
||||
@@ -51,6 +51,5 @@ public:
|
||||
|
||||
virtual Request nextRequest() = 0;
|
||||
virtual uint64_t totalRequests() = 0;
|
||||
virtual sc_core::sc_time clkPeriod() = 0;
|
||||
virtual void reset(){};
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user