Merge branch 'feat/smooth_generators' into 'develop'
Make generator frequency more smooth See merge request ems/astdm/modeling.dram/dram.sys.5!122
This commit is contained in:
@@ -9,6 +9,7 @@
|
|||||||
{
|
{
|
||||||
"type": "player",
|
"type": "player",
|
||||||
"clkMhz": 800,
|
"clkMhz": 800,
|
||||||
|
"dataLength": 64,
|
||||||
"name": "traces/example.stl"
|
"name": "traces/example.stl"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
|||||||
@@ -9,6 +9,7 @@
|
|||||||
{
|
{
|
||||||
"type": "player",
|
"type": "player",
|
||||||
"clkMhz": 200,
|
"clkMhz": 200,
|
||||||
|
"dataLength": 64,
|
||||||
"name": "traces/example.stl"
|
"name": "traces/example.stl"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
|||||||
@@ -212,6 +212,7 @@
|
|||||||
{
|
{
|
||||||
"type": "player",
|
"type": "player",
|
||||||
"clkMhz": 200,
|
"clkMhz": 200,
|
||||||
|
"dataLength": 64,
|
||||||
"name": "traces/example.stl"
|
"name": "traces/example.stl"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
|||||||
@@ -9,6 +9,7 @@
|
|||||||
{
|
{
|
||||||
"type": "player",
|
"type": "player",
|
||||||
"clkMhz": 1000,
|
"clkMhz": 1000,
|
||||||
|
"dataLength": 32,
|
||||||
"name": "traces/example.stl"
|
"name": "traces/example.stl"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
|||||||
@@ -9,6 +9,7 @@
|
|||||||
{
|
{
|
||||||
"type": "player",
|
"type": "player",
|
||||||
"clkMhz": 200,
|
"clkMhz": 200,
|
||||||
|
"dataLength": 32,
|
||||||
"name": "traces/example.stl"
|
"name": "traces/example.stl"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
|||||||
@@ -9,6 +9,7 @@
|
|||||||
{
|
{
|
||||||
"type": "player",
|
"type": "player",
|
||||||
"clkMhz": 800,
|
"clkMhz": 800,
|
||||||
|
"dataLength": 64,
|
||||||
"name": "traces/example.stl"
|
"name": "traces/example.stl"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
|||||||
@@ -9,6 +9,7 @@
|
|||||||
{
|
{
|
||||||
"type": "player",
|
"type": "player",
|
||||||
"clkMhz": 2000,
|
"clkMhz": 2000,
|
||||||
|
"dataLength": 64,
|
||||||
"name": "../../configs/traces/example.stl"
|
"name": "../../configs/traces/example.stl"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
|||||||
@@ -8,6 +8,7 @@
|
|||||||
"tracesetup": [
|
"tracesetup": [
|
||||||
{
|
{
|
||||||
"clkMhz": 2000,
|
"clkMhz": 2000,
|
||||||
|
"dataLength": 64,
|
||||||
"type": "generator",
|
"type": "generator",
|
||||||
"name": "gen0",
|
"name": "gen0",
|
||||||
"numRequests": 2000,
|
"numRequests": 2000,
|
||||||
@@ -19,6 +20,7 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"clkMhz": 2000,
|
"clkMhz": 2000,
|
||||||
|
"dataLength": 64,
|
||||||
"type": "generator",
|
"type": "generator",
|
||||||
"name": "gen1",
|
"name": "gen1",
|
||||||
"numRequests": 2000,
|
"numRequests": 2000,
|
||||||
|
|||||||
@@ -8,6 +8,7 @@
|
|||||||
"tracesetup": [
|
"tracesetup": [
|
||||||
{
|
{
|
||||||
"clkMhz": 2000,
|
"clkMhz": 2000,
|
||||||
|
"dataLength": 32,
|
||||||
"type": "generator",
|
"type": "generator",
|
||||||
"name": "gen0",
|
"name": "gen0",
|
||||||
"numRequests": 2000,
|
"numRequests": 2000,
|
||||||
|
|||||||
@@ -9,6 +9,7 @@
|
|||||||
{
|
{
|
||||||
"type": "player",
|
"type": "player",
|
||||||
"clkMhz": 200,
|
"clkMhz": 200,
|
||||||
|
"dataLength": 32,
|
||||||
"name": "../../configs/traces/example.stl"
|
"name": "../../configs/traces/example.stl"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
|||||||
@@ -79,12 +79,13 @@ struct TracePlayer
|
|||||||
|
|
||||||
uint64_t clkMhz{};
|
uint64_t clkMhz{};
|
||||||
std::string name;
|
std::string name;
|
||||||
|
unsigned dataLength;
|
||||||
std::optional<unsigned int> maxPendingReadRequests;
|
std::optional<unsigned int> maxPendingReadRequests;
|
||||||
std::optional<unsigned int> maxPendingWriteRequests;
|
std::optional<unsigned int> maxPendingWriteRequests;
|
||||||
};
|
};
|
||||||
|
|
||||||
NLOHMANN_JSONIFY_ALL_THINGS(
|
NLOHMANN_JSONIFY_ALL_THINGS(
|
||||||
TracePlayer, clkMhz, name, maxPendingReadRequests, maxPendingWriteRequests)
|
TracePlayer, clkMhz, name, dataLength, maxPendingReadRequests, maxPendingWriteRequests)
|
||||||
|
|
||||||
struct TrafficGeneratorActiveState
|
struct TrafficGeneratorActiveState
|
||||||
{
|
{
|
||||||
@@ -136,7 +137,7 @@ struct TrafficGenerator
|
|||||||
|
|
||||||
std::optional<uint64_t> seed;
|
std::optional<uint64_t> seed;
|
||||||
std::optional<uint64_t> maxTransactions;
|
std::optional<uint64_t> maxTransactions;
|
||||||
std::optional<unsigned> dataLength;
|
unsigned dataLength;
|
||||||
std::optional<unsigned> dataAlignment;
|
std::optional<unsigned> dataAlignment;
|
||||||
|
|
||||||
uint64_t numRequests{};
|
uint64_t numRequests{};
|
||||||
@@ -174,7 +175,7 @@ struct TrafficGeneratorStateMachine
|
|||||||
|
|
||||||
std::optional<uint64_t> seed;
|
std::optional<uint64_t> seed;
|
||||||
std::optional<uint64_t> maxTransactions;
|
std::optional<uint64_t> maxTransactions;
|
||||||
std::optional<unsigned> dataLength;
|
unsigned dataLength;
|
||||||
std::optional<unsigned> dataAlignment;
|
std::optional<unsigned> dataAlignment;
|
||||||
std::vector<std::variant<TrafficGeneratorActiveState, TrafficGeneratorIdleState>> states;
|
std::vector<std::variant<TrafficGeneratorActiveState, TrafficGeneratorIdleState>> states;
|
||||||
std::vector<TrafficGeneratorStateTransition> transitions;
|
std::vector<TrafficGeneratorStateTransition> transitions;
|
||||||
@@ -200,7 +201,8 @@ struct RowHammer
|
|||||||
std::string name;
|
std::string name;
|
||||||
std::optional<unsigned int> maxPendingReadRequests;
|
std::optional<unsigned int> maxPendingReadRequests;
|
||||||
std::optional<unsigned int> maxPendingWriteRequests;
|
std::optional<unsigned int> maxPendingWriteRequests;
|
||||||
|
|
||||||
|
unsigned dataLength;
|
||||||
uint64_t numRequests{};
|
uint64_t numRequests{};
|
||||||
uint64_t rowIncrement{};
|
uint64_t rowIncrement{};
|
||||||
};
|
};
|
||||||
@@ -210,6 +212,7 @@ NLOHMANN_JSONIFY_ALL_THINGS(RowHammer,
|
|||||||
name,
|
name,
|
||||||
maxPendingReadRequests,
|
maxPendingReadRequests,
|
||||||
maxPendingWriteRequests,
|
maxPendingWriteRequests,
|
||||||
|
dataLength,
|
||||||
numRequests,
|
numRequests,
|
||||||
rowIncrement)
|
rowIncrement)
|
||||||
|
|
||||||
|
|||||||
@@ -598,8 +598,8 @@ void Controller::manageRequests(const sc_time& delay)
|
|||||||
transToAcquire.payload->acquire();
|
transToAcquire.payload->acquire();
|
||||||
|
|
||||||
// The following logic assumes that transactions are naturally aligned
|
// The following logic assumes that transactions are naturally aligned
|
||||||
const uint64_t address = transToAcquire.payload->get_address();
|
uint64_t address = transToAcquire.payload->get_address();
|
||||||
const uint64_t dataLength = transToAcquire.payload->get_data_length();
|
[[maybe_unused]] uint64_t dataLength = transToAcquire.payload->get_data_length();
|
||||||
assert((dataLength & (dataLength - 1)) == 0); // Data length must be a power of 2
|
assert((dataLength & (dataLength - 1)) == 0); // Data length must be a power of 2
|
||||||
assert(address % dataLength == 0); // Check if naturally aligned
|
assert(address % dataLength == 0); // Check if naturally aligned
|
||||||
|
|
||||||
|
|||||||
@@ -28,7 +28,7 @@
|
|||||||
# NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
# NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
#
|
#
|
||||||
# Authors:
|
# Authors:
|
||||||
# Matthias Jung
|
# Matthias Jung
|
||||||
# Lukas Steiner
|
# Lukas Steiner
|
||||||
# Derek Christ
|
# Derek Christ
|
||||||
@@ -45,8 +45,8 @@ add_library(simulator
|
|||||||
simulator/EccModule.cpp
|
simulator/EccModule.cpp
|
||||||
simulator/MemoryManager.cpp
|
simulator/MemoryManager.cpp
|
||||||
simulator/Simulator.cpp
|
simulator/Simulator.cpp
|
||||||
simulator/generator/RandomProducer.cpp
|
simulator/generator/RandomState.cpp
|
||||||
simulator/generator/SequentialProducer.cpp
|
simulator/generator/SequentialState.cpp
|
||||||
simulator/generator/TrafficGenerator.cpp
|
simulator/generator/TrafficGenerator.cpp
|
||||||
simulator/hammer/RowHammer.cpp
|
simulator/hammer/RowHammer.cpp
|
||||||
simulator/player/StlPlayer.cpp
|
simulator/player/StlPlayer.cpp
|
||||||
|
|||||||
@@ -2,18 +2,13 @@
|
|||||||
The **standalone** simulator features a set of trace players, traffic generators and miscellaneous components that can be coupled with DRAMSys.
|
The **standalone** simulator features a set of trace players, traffic generators and miscellaneous components that can be coupled with DRAMSys.
|
||||||
|
|
||||||
## Concept
|
## Concept
|
||||||
Initiators in the simulator are split up into two disctinct components: **RequestProducers** and **RequestIssuers**.
|
Initiators in the simulator are split up into two disctinct components: **RequestProducers** and the **RequestIssuer**.
|
||||||
|
|
||||||
**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.
|
**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 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.
|
The **RequestIssuer** is the SystemC module that connect to DRAMSys. The Issuer has no knowledge of where the requests are coming from. It simply calls the `nextRequest()` method of its associated producer 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`.
|
|
||||||
The `TrafficGenerator` is one example of a direct implementation of the `Initiator` interface, as it consists of many producers (which represent the states of the state machine) but of only one issuer.
|
|
||||||
|
|
||||||
**Requests** are an abstraction over the TLM payloads the issuer generates. A request describes whether it is a read or a write access or an internal `Stop` request that tells the initiator to terminate.
|
**Requests** are an abstraction over the TLM payloads the issuer generates. A request describes whether it is a read or a write access or an internal `Stop` request that tells the initiator to terminate.
|
||||||
The **delay** field specifies the time that should pass between the issuance of the previous and the current request.
|
|
||||||
|
|
||||||
## Configuration
|
## Configuration
|
||||||
A detailed description on how to configure the traffic generators of the simulator can be found [here](../../configs/README.md).
|
A detailed description on how to configure the traffic generators of the simulator can be found [here](../../configs/README.md).
|
||||||
|
|||||||
@@ -1,71 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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 "request/RequestIssuer.h"
|
|
||||||
|
|
||||||
template <typename Producer> class SimpleInitiator : public Initiator
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
SimpleInitiator(sc_core::sc_module_name const& name,
|
|
||||||
MemoryManager& memoryManager,
|
|
||||||
sc_core::sc_time interfaceClk,
|
|
||||||
std::optional<unsigned int> maxPendingReadRequests,
|
|
||||||
std::optional<unsigned int> maxPendingWriteRequests,
|
|
||||||
std::function<void()> transactionFinished,
|
|
||||||
std::function<void()> terminate,
|
|
||||||
Producer&& producer) :
|
|
||||||
producer(std::forward<Producer>(producer)),
|
|
||||||
issuer(
|
|
||||||
name,
|
|
||||||
memoryManager,
|
|
||||||
interfaceClk,
|
|
||||||
maxPendingReadRequests,
|
|
||||||
maxPendingWriteRequests,
|
|
||||||
[this] { return this->producer.nextRequest(); },
|
|
||||||
std::move(transactionFinished),
|
|
||||||
std::move(terminate))
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
void bind(tlm_utils::multi_target_base<>& target) override { issuer.iSocket.bind(target); }
|
|
||||||
uint64_t totalRequests() override { return producer.totalRequests(); };
|
|
||||||
|
|
||||||
private:
|
|
||||||
Producer producer;
|
|
||||||
RequestIssuer issuer;
|
|
||||||
};
|
|
||||||
@@ -35,18 +35,19 @@
|
|||||||
|
|
||||||
#include "Simulator.h"
|
#include "Simulator.h"
|
||||||
|
|
||||||
#include "SimpleInitiator.h"
|
|
||||||
#include "generator/TrafficGenerator.h"
|
#include "generator/TrafficGenerator.h"
|
||||||
#include "hammer/RowHammer.h"
|
#include "hammer/RowHammer.h"
|
||||||
#include "player/StlPlayer.h"
|
#include "player/StlPlayer.h"
|
||||||
|
#include "simulator/request/RequestIssuer.h"
|
||||||
#include "util.h"
|
#include "util.h"
|
||||||
|
|
||||||
Simulator::Simulator(DRAMSys::Config::Configuration configuration, std::filesystem::path baseConfig) :
|
Simulator::Simulator(DRAMSys::Config::Configuration configuration,
|
||||||
|
std::filesystem::path baseConfig) :
|
||||||
storageEnabled(configuration.simconfig.StoreMode == DRAMSys::Config::StoreModeType::Store),
|
storageEnabled(configuration.simconfig.StoreMode == DRAMSys::Config::StoreModeType::Store),
|
||||||
memoryManager(storageEnabled),
|
memoryManager(storageEnabled),
|
||||||
configuration(std::move(configuration)),
|
configuration(std::move(configuration)),
|
||||||
dramSys(std::make_unique<DRAMSys::DRAMSys>("DRAMSys", this->configuration)),
|
dramSys(std::make_unique<DRAMSys::DRAMSys>("DRAMSys", this->configuration)),
|
||||||
baseConfig(baseConfig)
|
baseConfig(std::move(baseConfig))
|
||||||
{
|
{
|
||||||
terminateInitiator = [this]()
|
terminateInitiator = [this]()
|
||||||
{
|
{
|
||||||
@@ -74,32 +75,34 @@ Simulator::Simulator(DRAMSys::Config::Configuration configuration, std::filesyst
|
|||||||
{
|
{
|
||||||
auto initiator = instantiateInitiator(initiatorConfig);
|
auto initiator = instantiateInitiator(initiatorConfig);
|
||||||
totalTransactions += initiator->totalRequests();
|
totalTransactions += initiator->totalRequests();
|
||||||
initiator->bind(dramSys->tSocket);
|
initiator->iSocket.bind(dramSys->tSocket);
|
||||||
initiators.push_back(std::move(initiator));
|
initiators.push_back(std::move(initiator));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
std::unique_ptr<Initiator>
|
std::unique_ptr<RequestIssuer>
|
||||||
Simulator::instantiateInitiator(const DRAMSys::Config::Initiator& initiator)
|
Simulator::instantiateInitiator(const DRAMSys::Config::Initiator& initiator)
|
||||||
{
|
{
|
||||||
uint64_t memorySize = dramSys->getMemSpec().getSimMemSizeInBytes();
|
uint64_t memorySize = dramSys->getMemSpec().getSimMemSizeInBytes();
|
||||||
sc_core::sc_time interfaceClk = dramSys->getMemSpec().tCK;
|
sc_core::sc_time interfaceClk = dramSys->getMemSpec().tCK;
|
||||||
unsigned int defaultDataLength = dramSys->getMemSpec().defaultBytesPerBurst;
|
|
||||||
|
|
||||||
return std::visit(
|
return std::visit(
|
||||||
[=](auto&& config) -> std::unique_ptr<Initiator>
|
[=](auto&& config) -> std::unique_ptr<RequestIssuer>
|
||||||
{
|
{
|
||||||
using T = std::decay_t<decltype(config)>;
|
using T = std::decay_t<decltype(config)>;
|
||||||
if constexpr (std::is_same_v<T, DRAMSys::Config::TrafficGenerator> ||
|
if constexpr (std::is_same_v<T, DRAMSys::Config::TrafficGenerator> ||
|
||||||
std::is_same_v<T, DRAMSys::Config::TrafficGeneratorStateMachine>)
|
std::is_same_v<T, DRAMSys::Config::TrafficGeneratorStateMachine>)
|
||||||
{
|
{
|
||||||
return std::make_unique<TrafficGenerator>(config,
|
auto generator = std::make_unique<TrafficGenerator>(config, memorySize);
|
||||||
interfaceClk,
|
|
||||||
memorySize,
|
return std::make_unique<RequestIssuer>(config.name.c_str(),
|
||||||
defaultDataLength,
|
std::move(generator),
|
||||||
memoryManager,
|
memoryManager,
|
||||||
finishTransaction,
|
interfaceClk,
|
||||||
terminateInitiator);
|
config.maxPendingReadRequests,
|
||||||
|
config.maxPendingWriteRequests,
|
||||||
|
finishTransaction,
|
||||||
|
terminateInitiator);
|
||||||
}
|
}
|
||||||
else if constexpr (std::is_same_v<T, DRAMSys::Config::TracePlayer>)
|
else if constexpr (std::is_same_v<T, DRAMSys::Config::TracePlayer>)
|
||||||
{
|
{
|
||||||
@@ -119,33 +122,30 @@ Simulator::instantiateInitiator(const DRAMSys::Config::Initiator& initiator)
|
|||||||
SC_REPORT_FATAL("Simulator", report.c_str());
|
SC_REPORT_FATAL("Simulator", report.c_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
StlPlayer player(tracePath.c_str(),
|
auto player = std::make_unique<StlPlayer>(
|
||||||
config.clkMhz,
|
config, tracePath.c_str(), *traceType, storageEnabled);
|
||||||
defaultDataLength,
|
|
||||||
*traceType,
|
|
||||||
storageEnabled);
|
|
||||||
|
|
||||||
return std::make_unique<SimpleInitiator<StlPlayer>>(config.name.c_str(),
|
return std::make_unique<RequestIssuer>(config.name.c_str(),
|
||||||
memoryManager,
|
std::move(player),
|
||||||
interfaceClk,
|
memoryManager,
|
||||||
std::nullopt,
|
interfaceClk,
|
||||||
std::nullopt,
|
std::nullopt,
|
||||||
finishTransaction,
|
std::nullopt,
|
||||||
terminateInitiator,
|
finishTransaction,
|
||||||
std::move(player));
|
terminateInitiator);
|
||||||
}
|
}
|
||||||
else if constexpr (std::is_same_v<T, DRAMSys::Config::RowHammer>)
|
else if constexpr (std::is_same_v<T, DRAMSys::Config::RowHammer>)
|
||||||
{
|
{
|
||||||
RowHammer hammer(config.numRequests, config.rowIncrement, defaultDataLength);
|
auto hammer = std::make_unique<RowHammer>(config);
|
||||||
|
|
||||||
return std::make_unique<SimpleInitiator<RowHammer>>(config.name.c_str(),
|
return std::make_unique<RequestIssuer>(config.name.c_str(),
|
||||||
memoryManager,
|
std::move(hammer),
|
||||||
interfaceClk,
|
memoryManager,
|
||||||
1,
|
interfaceClk,
|
||||||
1,
|
1,
|
||||||
finishTransaction,
|
1,
|
||||||
terminateInitiator,
|
finishTransaction,
|
||||||
std::move(hammer));
|
terminateInitiator);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
initiator.getVariant());
|
initiator.getVariant());
|
||||||
@@ -175,5 +175,5 @@ void Simulator::run()
|
|||||||
|
|
||||||
auto finish = std::chrono::high_resolution_clock::now();
|
auto finish = std::chrono::high_resolution_clock::now();
|
||||||
std::chrono::duration<double> elapsed = finish - start;
|
std::chrono::duration<double> elapsed = finish - start;
|
||||||
std::cout << "Simulation took " + std::to_string(elapsed.count()) + " seconds." << std::endl;
|
std::cout << "Simulation took " + std::to_string(elapsed.count()) + " seconds.\n";
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -35,8 +35,8 @@
|
|||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "Initiator.h"
|
|
||||||
#include "MemoryManager.h"
|
#include "MemoryManager.h"
|
||||||
|
#include "simulator/request/RequestIssuer.h"
|
||||||
|
|
||||||
#include <DRAMSys/config/DRAMSysConfiguration.h>
|
#include <DRAMSys/config/DRAMSysConfiguration.h>
|
||||||
#include <DRAMSys/simulation/DRAMSys.h>
|
#include <DRAMSys/simulation/DRAMSys.h>
|
||||||
@@ -49,15 +49,15 @@ public:
|
|||||||
void run();
|
void run();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::unique_ptr<Initiator> instantiateInitiator(const DRAMSys::Config::Initiator& initiator);
|
std::unique_ptr<RequestIssuer> instantiateInitiator(const DRAMSys::Config::Initiator& initiator);
|
||||||
|
|
||||||
const bool storageEnabled;
|
bool storageEnabled;
|
||||||
MemoryManager memoryManager;
|
MemoryManager memoryManager;
|
||||||
|
|
||||||
DRAMSys::Config::Configuration configuration;
|
DRAMSys::Config::Configuration configuration;
|
||||||
|
|
||||||
std::unique_ptr<DRAMSys::DRAMSys> dramSys;
|
std::unique_ptr<DRAMSys::DRAMSys> dramSys;
|
||||||
std::vector<std::unique_ptr<Initiator>> initiators;
|
std::vector<std::unique_ptr<RequestIssuer>> initiators;
|
||||||
|
|
||||||
std::function<void()> terminateInitiator;
|
std::function<void()> terminateInitiator;
|
||||||
std::function<void()> finishTransaction;
|
std::function<void()> finishTransaction;
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2023, RPTU Kaiserslautern-Landau
|
* Copyright (c) 2025, RPTU Kaiserslautern-Landau
|
||||||
* All rights reserved.
|
* All rights reserved.
|
||||||
*
|
*
|
||||||
* Redistribution and use in source and binary forms, with or without
|
* Redistribution and use in source and binary forms, with or without
|
||||||
@@ -35,20 +35,21 @@
|
|||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <tlm_utils/multi_socket_bases.h>
|
#include "simulator/request/Request.h"
|
||||||
|
|
||||||
class Initiator
|
class GeneratorState
|
||||||
{
|
{
|
||||||
protected:
|
protected:
|
||||||
Initiator(const Initiator&) = default;
|
GeneratorState(const GeneratorState&) = default;
|
||||||
Initiator(Initiator&&) = default;
|
GeneratorState(GeneratorState&&) = default;
|
||||||
Initiator& operator=(const Initiator&) = default;
|
GeneratorState& operator=(const GeneratorState&) = default;
|
||||||
Initiator& operator=(Initiator&&) = default;
|
GeneratorState& operator=(GeneratorState&&) = default;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
Initiator() = default;
|
GeneratorState() = default;
|
||||||
virtual ~Initiator() = default;
|
virtual ~GeneratorState() = default;
|
||||||
|
|
||||||
virtual void bind(tlm_utils::multi_target_base<>& target) = 0;
|
virtual Request nextRequest() = 0;
|
||||||
virtual uint64_t totalRequests() = 0;
|
virtual uint64_t totalRequests() = 0;
|
||||||
};
|
virtual void reset() {}
|
||||||
|
};
|
||||||
@@ -33,11 +33,12 @@
|
|||||||
* Derek Christ
|
* Derek Christ
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "RandomProducer.h"
|
#include "RandomState.h"
|
||||||
#include "definitions.h"
|
|
||||||
|
|
||||||
RandomProducer::RandomProducer(uint64_t numRequests,
|
#include <systemc>
|
||||||
std::optional<uint64_t> seed,
|
|
||||||
|
RandomState::RandomState(uint64_t numRequests,
|
||||||
|
uint64_t seed,
|
||||||
double rwRatio,
|
double rwRatio,
|
||||||
std::optional<uint64_t> minAddress,
|
std::optional<uint64_t> minAddress,
|
||||||
std::optional<uint64_t> maxAddress,
|
std::optional<uint64_t> maxAddress,
|
||||||
@@ -45,13 +46,12 @@ RandomProducer::RandomProducer(uint64_t numRequests,
|
|||||||
unsigned int dataLength,
|
unsigned int dataLength,
|
||||||
unsigned int dataAlignment) :
|
unsigned int dataAlignment) :
|
||||||
numberOfRequests(numRequests),
|
numberOfRequests(numRequests),
|
||||||
seed(seed.value_or(DEFAULT_SEED)),
|
seed(seed),
|
||||||
rwRatio(rwRatio),
|
rwRatio(rwRatio),
|
||||||
dataLength(dataLength),
|
dataLength(dataLength),
|
||||||
dataAlignment(dataAlignment),
|
dataAlignment(dataAlignment),
|
||||||
randomGenerator(this->seed),
|
randomGenerator(this->seed),
|
||||||
randomAddressDistribution(minAddress.value_or(DEFAULT_MIN_ADDRESS),
|
randomAddressDistribution(minAddress.value_or(0), maxAddress.value_or((memorySize)-dataLength))
|
||||||
maxAddress.value_or((memorySize)-dataLength))
|
|
||||||
{
|
{
|
||||||
if (minAddress > memorySize - 1)
|
if (minAddress > memorySize - 1)
|
||||||
SC_REPORT_FATAL("TrafficGenerator", "minAddress is out of range.");
|
SC_REPORT_FATAL("TrafficGenerator", "minAddress is out of range.");
|
||||||
@@ -65,7 +65,7 @@ RandomProducer::RandomProducer(uint64_t numRequests,
|
|||||||
rwRatio = std::clamp(rwRatio, 0.0, 1.0);
|
rwRatio = std::clamp(rwRatio, 0.0, 1.0);
|
||||||
}
|
}
|
||||||
|
|
||||||
Request RandomProducer::nextRequest()
|
Request RandomState::nextRequest()
|
||||||
{
|
{
|
||||||
Request request;
|
Request request;
|
||||||
request.address = randomAddressDistribution(randomGenerator);
|
request.address = randomAddressDistribution(randomGenerator);
|
||||||
@@ -76,7 +76,6 @@ Request RandomProducer::nextRequest()
|
|||||||
request.command = readWriteDistribution(randomGenerator) < rwRatio ? Request::Command::Read
|
request.command = readWriteDistribution(randomGenerator) < rwRatio ? Request::Command::Read
|
||||||
: Request::Command::Write;
|
: Request::Command::Write;
|
||||||
request.length = dataLength;
|
request.length = dataLength;
|
||||||
request.delay = sc_core::SC_ZERO_TIME;
|
|
||||||
|
|
||||||
return request;
|
return request;
|
||||||
}
|
}
|
||||||
@@ -35,16 +35,16 @@
|
|||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "simulator/request/RequestProducer.h"
|
#include "simulator/generator/GeneratorState.h"
|
||||||
|
|
||||||
#include <optional>
|
#include <optional>
|
||||||
#include <random>
|
#include <random>
|
||||||
|
|
||||||
class RandomProducer : public RequestProducer
|
class RandomState : public GeneratorState
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
RandomProducer(uint64_t numRequests,
|
RandomState(uint64_t numRequests,
|
||||||
std::optional<uint64_t> seed,
|
uint64_t seed,
|
||||||
double rwRatio,
|
double rwRatio,
|
||||||
std::optional<uint64_t> minAddress,
|
std::optional<uint64_t> minAddress,
|
||||||
std::optional<uint64_t> maxAddress,
|
std::optional<uint64_t> maxAddress,
|
||||||
@@ -53,14 +53,13 @@ public:
|
|||||||
unsigned int dataAlignment);
|
unsigned int dataAlignment);
|
||||||
|
|
||||||
Request nextRequest() override;
|
Request nextRequest() override;
|
||||||
|
|
||||||
uint64_t totalRequests() override { return numberOfRequests; }
|
uint64_t totalRequests() override { return numberOfRequests; }
|
||||||
|
|
||||||
const uint64_t numberOfRequests;
|
uint64_t numberOfRequests;
|
||||||
const uint64_t seed;
|
uint64_t seed;
|
||||||
const double rwRatio;
|
double rwRatio;
|
||||||
const unsigned int dataLength;
|
unsigned int dataLength;
|
||||||
const unsigned int dataAlignment;
|
unsigned int dataAlignment;
|
||||||
|
|
||||||
std::default_random_engine randomGenerator;
|
std::default_random_engine randomGenerator;
|
||||||
std::uniform_real_distribution<double> readWriteDistribution{0.0, 1.0};
|
std::uniform_real_distribution<double> readWriteDistribution{0.0, 1.0};
|
||||||
@@ -33,11 +33,12 @@
|
|||||||
* Derek Christ
|
* Derek Christ
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "SequentialProducer.h"
|
#include "SequentialState.h"
|
||||||
#include "definitions.h"
|
|
||||||
|
|
||||||
SequentialProducer::SequentialProducer(uint64_t numRequests,
|
#include <systemc>
|
||||||
std::optional<uint64_t> seed,
|
|
||||||
|
SequentialState::SequentialState(uint64_t numRequests,
|
||||||
|
uint64_t seed,
|
||||||
double rwRatio,
|
double rwRatio,
|
||||||
std::optional<uint64_t> addressIncrement,
|
std::optional<uint64_t> addressIncrement,
|
||||||
std::optional<uint64_t> minAddress,
|
std::optional<uint64_t> minAddress,
|
||||||
@@ -46,9 +47,9 @@ SequentialProducer::SequentialProducer(uint64_t numRequests,
|
|||||||
unsigned int dataLength) :
|
unsigned int dataLength) :
|
||||||
numberOfRequests(numRequests),
|
numberOfRequests(numRequests),
|
||||||
addressIncrement(addressIncrement.value_or(dataLength)),
|
addressIncrement(addressIncrement.value_or(dataLength)),
|
||||||
minAddress(minAddress.value_or(DEFAULT_MIN_ADDRESS)),
|
minAddress(minAddress.value_or(0)),
|
||||||
maxAddress(maxAddress.value_or(memorySize - 1)),
|
maxAddress(maxAddress.value_or(memorySize - 1)),
|
||||||
seed(seed.value_or(DEFAULT_SEED)),
|
seed(seed),
|
||||||
rwRatio(rwRatio),
|
rwRatio(rwRatio),
|
||||||
dataLength(dataLength),
|
dataLength(dataLength),
|
||||||
randomGenerator(this->seed)
|
randomGenerator(this->seed)
|
||||||
@@ -65,14 +66,13 @@ SequentialProducer::SequentialProducer(uint64_t numRequests,
|
|||||||
rwRatio = std::clamp(rwRatio, 0.0, 1.0);
|
rwRatio = std::clamp(rwRatio, 0.0, 1.0);
|
||||||
}
|
}
|
||||||
|
|
||||||
Request SequentialProducer::nextRequest()
|
Request SequentialState::nextRequest()
|
||||||
{
|
{
|
||||||
Request request;
|
Request request;
|
||||||
request.address = generatedRequests * addressIncrement % (maxAddress - minAddress) + minAddress;
|
request.address = generatedRequests * addressIncrement % (maxAddress - minAddress) + minAddress;
|
||||||
request.command = readWriteDistribution(randomGenerator) < rwRatio ? Request::Command::Read
|
request.command = readWriteDistribution(randomGenerator) < rwRatio ? Request::Command::Read
|
||||||
: Request::Command::Write;
|
: Request::Command::Write;
|
||||||
request.length = dataLength;
|
request.length = dataLength;
|
||||||
request.delay = sc_core::SC_ZERO_TIME;
|
|
||||||
|
|
||||||
generatedRequests++;
|
generatedRequests++;
|
||||||
return request;
|
return request;
|
||||||
@@ -35,16 +35,16 @@
|
|||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "simulator/request/RequestProducer.h"
|
#include "simulator/generator/GeneratorState.h"
|
||||||
|
|
||||||
#include <optional>
|
#include <optional>
|
||||||
#include <random>
|
#include <random>
|
||||||
|
|
||||||
class SequentialProducer : public RequestProducer
|
class SequentialState : public GeneratorState
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
SequentialProducer(uint64_t numRequests,
|
SequentialState(uint64_t numRequests,
|
||||||
std::optional<uint64_t> seed,
|
uint64_t seed,
|
||||||
double rwRatio,
|
double rwRatio,
|
||||||
std::optional<uint64_t> addressIncrement,
|
std::optional<uint64_t> addressIncrement,
|
||||||
std::optional<uint64_t> minAddress,
|
std::optional<uint64_t> minAddress,
|
||||||
@@ -53,17 +53,16 @@ public:
|
|||||||
unsigned int dataLength);
|
unsigned int dataLength);
|
||||||
|
|
||||||
Request nextRequest() override;
|
Request nextRequest() override;
|
||||||
|
|
||||||
uint64_t totalRequests() override { return numberOfRequests; }
|
uint64_t totalRequests() override { return numberOfRequests; }
|
||||||
void reset() override { generatedRequests = 0; }
|
void reset() override { generatedRequests = 0; }
|
||||||
|
|
||||||
const uint64_t numberOfRequests;
|
uint64_t numberOfRequests;
|
||||||
const uint64_t addressIncrement;
|
uint64_t addressIncrement;
|
||||||
const uint64_t minAddress;
|
uint64_t minAddress;
|
||||||
const uint64_t maxAddress;
|
uint64_t maxAddress;
|
||||||
const uint64_t seed;
|
uint64_t seed;
|
||||||
const double rwRatio;
|
double rwRatio;
|
||||||
const unsigned int dataLength;
|
unsigned int dataLength;
|
||||||
|
|
||||||
std::default_random_engine randomGenerator;
|
std::default_random_engine randomGenerator;
|
||||||
std::uniform_real_distribution<double> readWriteDistribution{0.0, 1.0};
|
std::uniform_real_distribution<double> readWriteDistribution{0.0, 1.0};
|
||||||
@@ -35,29 +35,15 @@
|
|||||||
|
|
||||||
#include "TrafficGenerator.h"
|
#include "TrafficGenerator.h"
|
||||||
|
|
||||||
#include "RandomProducer.h"
|
#include "RandomState.h"
|
||||||
#include "SequentialProducer.h"
|
#include "SequentialState.h"
|
||||||
|
|
||||||
TrafficGenerator::TrafficGenerator(DRAMSys::Config::TrafficGeneratorStateMachine const& config,
|
TrafficGenerator::TrafficGenerator(DRAMSys::Config::TrafficGeneratorStateMachine const& config,
|
||||||
sc_core::sc_time interfaceClk,
|
uint64_t memorySize) :
|
||||||
uint64_t memorySize,
|
|
||||||
unsigned int defaultDataLength,
|
|
||||||
MemoryManager& memoryManager,
|
|
||||||
std::function<void()> transactionFinished,
|
|
||||||
std::function<void()> terminateInitiator) :
|
|
||||||
stateTransistions(config.transitions),
|
stateTransistions(config.transitions),
|
||||||
generatorPeriod(sc_core::sc_time(1.0 / static_cast<double>(config.clkMhz), sc_core::SC_US)),
|
generatorPeriod(sc_core::sc_time(1.0 / static_cast<double>(config.clkMhz), sc_core::SC_US))
|
||||||
issuer(
|
|
||||||
config.name.c_str(),
|
|
||||||
memoryManager,
|
|
||||||
interfaceClk,
|
|
||||||
config.maxPendingReadRequests,
|
|
||||||
config.maxPendingWriteRequests,
|
|
||||||
[this] { return nextRequest(); },
|
|
||||||
std::move(transactionFinished),
|
|
||||||
std::move(terminateInitiator))
|
|
||||||
{
|
{
|
||||||
unsigned int dataLength = config.dataLength.value_or(defaultDataLength);
|
unsigned int dataLength = config.dataLength;
|
||||||
unsigned int dataAlignment = config.dataAlignment.value_or(dataLength);
|
unsigned int dataAlignment = config.dataAlignment.value_or(dataLength);
|
||||||
|
|
||||||
for (auto const& state : config.states)
|
for (auto const& state : config.states)
|
||||||
@@ -74,28 +60,28 @@ TrafficGenerator::TrafficGenerator(DRAMSys::Config::TrafficGeneratorStateMachine
|
|||||||
if (activeState.addressDistribution ==
|
if (activeState.addressDistribution ==
|
||||||
DRAMSys::Config::AddressDistribution::Random)
|
DRAMSys::Config::AddressDistribution::Random)
|
||||||
{
|
{
|
||||||
auto producer = std::make_unique<RandomProducer>(activeState.numRequests,
|
auto producer = std::make_unique<RandomState>(activeState.numRequests,
|
||||||
config.seed,
|
config.seed.value_or(0),
|
||||||
activeState.rwRatio,
|
activeState.rwRatio,
|
||||||
activeState.minAddress,
|
activeState.minAddress,
|
||||||
activeState.maxAddress,
|
activeState.maxAddress,
|
||||||
memorySize,
|
memorySize,
|
||||||
dataLength,
|
dataLength,
|
||||||
dataAlignment);
|
dataAlignment);
|
||||||
|
|
||||||
producers.emplace(activeState.id, std::move(producer));
|
producers.emplace(activeState.id, std::move(producer));
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
auto producer =
|
auto producer =
|
||||||
std::make_unique<SequentialProducer>(activeState.numRequests,
|
std::make_unique<SequentialState>(activeState.numRequests,
|
||||||
config.seed,
|
config.seed.value_or(0),
|
||||||
activeState.rwRatio,
|
activeState.rwRatio,
|
||||||
activeState.addressIncrement,
|
activeState.addressIncrement,
|
||||||
activeState.minAddress,
|
activeState.minAddress,
|
||||||
activeState.maxAddress,
|
activeState.maxAddress,
|
||||||
memorySize,
|
memorySize,
|
||||||
dataLength);
|
dataLength);
|
||||||
|
|
||||||
producers.emplace(activeState.id, std::move(producer));
|
producers.emplace(activeState.id, std::move(producer));
|
||||||
}
|
}
|
||||||
@@ -111,55 +97,48 @@ TrafficGenerator::TrafficGenerator(DRAMSys::Config::TrafficGeneratorStateMachine
|
|||||||
}
|
}
|
||||||
|
|
||||||
TrafficGenerator::TrafficGenerator(DRAMSys::Config::TrafficGenerator const& config,
|
TrafficGenerator::TrafficGenerator(DRAMSys::Config::TrafficGenerator const& config,
|
||||||
sc_core::sc_time interfaceClk,
|
uint64_t memorySize) :
|
||||||
uint64_t memorySize,
|
generatorPeriod(sc_core::sc_time(1.0 / static_cast<double>(config.clkMhz), sc_core::SC_US))
|
||||||
unsigned int defaultDataLength,
|
|
||||||
MemoryManager& memoryManager,
|
|
||||||
std::function<void()> transactionFinished,
|
|
||||||
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,
|
|
||||||
interfaceClk,
|
|
||||||
config.maxPendingReadRequests,
|
|
||||||
config.maxPendingWriteRequests,
|
|
||||||
[this] { return nextRequest(); },
|
|
||||||
std::move(transactionFinished),
|
|
||||||
std::move(terminateInitiator))
|
|
||||||
{
|
{
|
||||||
unsigned int dataLength = config.dataLength.value_or(defaultDataLength);
|
unsigned int dataLength = config.dataLength;
|
||||||
unsigned int dataAlignment = config.dataAlignment.value_or(dataLength);
|
unsigned int dataAlignment = config.dataAlignment.value_or(dataLength);
|
||||||
|
|
||||||
if (config.addressDistribution == DRAMSys::Config::AddressDistribution::Random)
|
if (config.addressDistribution == DRAMSys::Config::AddressDistribution::Random)
|
||||||
{
|
{
|
||||||
auto producer = std::make_unique<RandomProducer>(config.numRequests,
|
auto producer = std::make_unique<RandomState>(config.numRequests,
|
||||||
config.seed,
|
config.seed.value_or(0),
|
||||||
config.rwRatio,
|
config.rwRatio,
|
||||||
config.minAddress,
|
config.minAddress,
|
||||||
config.maxAddress,
|
config.maxAddress,
|
||||||
memorySize,
|
memorySize,
|
||||||
dataLength,
|
dataLength,
|
||||||
dataAlignment);
|
dataAlignment);
|
||||||
producers.emplace(0, std::move(producer));
|
producers.emplace(0, std::move(producer));
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
auto producer = std::make_unique<SequentialProducer>(config.numRequests,
|
auto producer = std::make_unique<SequentialState>(config.numRequests,
|
||||||
config.seed,
|
config.seed.value_or(0),
|
||||||
config.rwRatio,
|
config.rwRatio,
|
||||||
config.addressIncrement,
|
config.addressIncrement,
|
||||||
config.minAddress,
|
config.minAddress,
|
||||||
config.maxAddress,
|
config.maxAddress,
|
||||||
memorySize,
|
memorySize,
|
||||||
dataLength);
|
dataLength);
|
||||||
producers.emplace(0, std::move(producer));
|
producers.emplace(0, std::move(producer));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Request TrafficGenerator::nextRequest()
|
Request TrafficGenerator::nextRequest()
|
||||||
{
|
{
|
||||||
uint64_t clksToIdle = 0;
|
if (currentState == STOP_STATE)
|
||||||
|
return Request{Request::Command::Stop};
|
||||||
|
|
||||||
|
Request request = producers[currentState]->nextRequest();
|
||||||
|
requestsInState++;
|
||||||
|
|
||||||
|
// Switch state if necessary
|
||||||
|
unsigned ticksToIdle = 0;
|
||||||
if (requestsInState >= producers[currentState]->totalRequests())
|
if (requestsInState >= producers[currentState]->totalRequests())
|
||||||
{
|
{
|
||||||
// Reset current producer to its initial state
|
// Reset current producer to its initial state
|
||||||
@@ -167,30 +146,24 @@ Request TrafficGenerator::nextRequest()
|
|||||||
|
|
||||||
auto newState = stateTransition(currentState);
|
auto newState = stateTransition(currentState);
|
||||||
|
|
||||||
if (!newState.has_value())
|
auto idleStateIt = idleStateClks.find(newState);
|
||||||
return Request{Request::Command::Stop};
|
|
||||||
|
|
||||||
auto idleStateIt = idleStateClks.find(newState.value());
|
|
||||||
while (idleStateIt != idleStateClks.cend())
|
while (idleStateIt != idleStateClks.cend())
|
||||||
{
|
{
|
||||||
clksToIdle += idleStateIt->second;
|
ticksToIdle += idleStateIt->second;
|
||||||
newState = stateTransition(currentState);
|
newState = stateTransition(newState);
|
||||||
|
idleStateIt = idleStateClks.find(newState);
|
||||||
if (!newState.has_value())
|
|
||||||
return Request{Request::Command::Stop};
|
|
||||||
|
|
||||||
currentState = newState.value();
|
|
||||||
idleStateIt = idleStateClks.find(newState.value());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
currentState = newState.value();
|
currentState = newState;
|
||||||
requestsInState = 0;
|
requestsInState = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
requestsInState++;
|
if (currentState == STOP_STATE)
|
||||||
|
// Allow the issuer to finish before the response comes back
|
||||||
|
nextTriggerTime = sc_core::SC_ZERO_TIME;
|
||||||
|
else
|
||||||
|
nextTriggerTime = generatorPeriod * (1 + ticksToIdle);
|
||||||
|
|
||||||
Request request = producers[currentState]->nextRequest();
|
|
||||||
request.delay += generatorPeriod + generatorPeriod * static_cast<double>(clksToIdle);
|
|
||||||
return request;
|
return request;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -208,9 +181,9 @@ uint64_t TrafficGenerator::totalRequests()
|
|||||||
if (producers.find(currentState) != producers.cend())
|
if (producers.find(currentState) != producers.cend())
|
||||||
totalRequests += producers.at(currentState)->totalRequests();
|
totalRequests += producers.at(currentState)->totalRequests();
|
||||||
|
|
||||||
while (auto nextState = stateTransition(currentState))
|
while (currentState != STOP_STATE)
|
||||||
{
|
{
|
||||||
currentState = nextState.value();
|
currentState = stateTransition(currentState);
|
||||||
|
|
||||||
if (producers.find(currentState) != producers.cend())
|
if (producers.find(currentState) != producers.cend())
|
||||||
totalRequests += producers.at(currentState)->totalRequests();
|
totalRequests += producers.at(currentState)->totalRequests();
|
||||||
@@ -222,7 +195,7 @@ uint64_t TrafficGenerator::totalRequests()
|
|||||||
return totalRequests;
|
return totalRequests;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::optional<unsigned int> TrafficGenerator::stateTransition(unsigned int from)
|
unsigned int TrafficGenerator::stateTransition(unsigned int from)
|
||||||
{
|
{
|
||||||
using Transition = DRAMSys::Config::TrafficGeneratorStateTransition;
|
using Transition = DRAMSys::Config::TrafficGeneratorStateTransition;
|
||||||
|
|
||||||
@@ -233,7 +206,7 @@ std::optional<unsigned int> TrafficGenerator::stateTransition(unsigned int from)
|
|||||||
[from](Transition transition) { return transition.from == from; });
|
[from](Transition transition) { return transition.from == from; });
|
||||||
|
|
||||||
if (relevantTransitions.empty())
|
if (relevantTransitions.empty())
|
||||||
return std::nullopt;
|
return STOP_STATE;
|
||||||
|
|
||||||
std::vector<double> propabilities;
|
std::vector<double> propabilities;
|
||||||
std::for_each(relevantTransitions.cbegin(),
|
std::for_each(relevantTransitions.cbegin(),
|
||||||
|
|||||||
@@ -35,52 +35,41 @@
|
|||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "simulator/Initiator.h"
|
#include "GeneratorState.h"
|
||||||
#include "simulator/MemoryManager.h"
|
#include "simulator/request/RequestProducer.h"
|
||||||
#include "simulator/request/RequestIssuer.h"
|
|
||||||
|
|
||||||
#include <DRAMSys/config/DRAMSysConfiguration.h>
|
#include <DRAMSys/config/DRAMSysConfiguration.h>
|
||||||
|
|
||||||
#include <random>
|
#include <random>
|
||||||
|
|
||||||
class RequestProducer;
|
class RequestProducer;
|
||||||
|
|
||||||
class TrafficGenerator : public Initiator
|
class TrafficGenerator : public RequestProducer
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
TrafficGenerator(DRAMSys::Config::TrafficGenerator const& config,
|
TrafficGenerator(DRAMSys::Config::TrafficGenerator const& config, uint64_t memorySize);
|
||||||
sc_core::sc_time interfaceClk,
|
|
||||||
uint64_t memorySize,
|
|
||||||
unsigned int defaultDataLength,
|
|
||||||
MemoryManager& memoryManager,
|
|
||||||
std::function<void()> transactionFinished,
|
|
||||||
std::function<void()> terminateInitiator);
|
|
||||||
|
|
||||||
TrafficGenerator(DRAMSys::Config::TrafficGeneratorStateMachine const& config,
|
TrafficGenerator(DRAMSys::Config::TrafficGeneratorStateMachine const& config,
|
||||||
sc_core::sc_time interfaceClk,
|
uint64_t memorySize);
|
||||||
uint64_t memorySize,
|
|
||||||
unsigned int defaultDataLength,
|
|
||||||
MemoryManager& memoryManager,
|
|
||||||
std::function<void()> transactionFinished,
|
|
||||||
std::function<void()> terminateInitiator);
|
|
||||||
|
|
||||||
void bind(tlm_utils::multi_target_base<>& target) override { issuer.iSocket.bind(target); }
|
|
||||||
|
|
||||||
uint64_t totalRequests() override;
|
uint64_t totalRequests() override;
|
||||||
Request nextRequest();
|
Request nextRequest() override;
|
||||||
|
sc_core::sc_time nextTrigger() override { return nextTriggerTime; }
|
||||||
|
|
||||||
std::optional<unsigned int> stateTransition(unsigned int from);
|
unsigned int stateTransition(unsigned int from);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
static constexpr unsigned int STOP_STATE = UINT_MAX;
|
||||||
|
|
||||||
uint64_t requestsInState = 0;
|
uint64_t requestsInState = 0;
|
||||||
unsigned int currentState = 0;
|
unsigned int currentState = 0;
|
||||||
const std::vector<DRAMSys::Config::TrafficGeneratorStateTransition> stateTransistions;
|
sc_core::sc_time nextTriggerTime = sc_core::SC_ZERO_TIME;
|
||||||
|
std::vector<DRAMSys::Config::TrafficGeneratorStateTransition> stateTransistions;
|
||||||
|
|
||||||
using IdleClks = uint64_t;
|
std::unordered_map<unsigned int, unsigned int> idleStateClks;
|
||||||
std::unordered_map<unsigned int, IdleClks> idleStateClks;
|
sc_core::sc_time generatorPeriod;
|
||||||
const sc_core::sc_time generatorPeriod;
|
|
||||||
|
|
||||||
std::default_random_engine randomGenerator;
|
std::default_random_engine randomGenerator;
|
||||||
|
|
||||||
std::unordered_map<unsigned int, std::unique_ptr<RequestProducer>> producers;
|
std::unordered_map<unsigned int, std::unique_ptr<GeneratorState>> producers;
|
||||||
RequestIssuer issuer;
|
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,41 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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 <cstdint>
|
|
||||||
|
|
||||||
inline constexpr uint64_t DEFAULT_SEED = 0;
|
|
||||||
inline constexpr uint64_t DEFAULT_MIN_ADDRESS = 0;
|
|
||||||
@@ -35,10 +35,11 @@
|
|||||||
|
|
||||||
#include "RowHammer.h"
|
#include "RowHammer.h"
|
||||||
|
|
||||||
RowHammer::RowHammer(uint64_t numRequests, uint64_t rowIncrement, unsigned int dataLength) :
|
RowHammer::RowHammer(DRAMSys::Config::RowHammer const& config) :
|
||||||
numberOfRequests(numRequests),
|
generatorPeriod(sc_core::sc_time(1.0 / static_cast<double>(config.clkMhz), sc_core::SC_US)),
|
||||||
dataLength(dataLength),
|
numberOfRequests(config.numRequests),
|
||||||
rowIncrement(rowIncrement)
|
rowIncrement(config.rowIncrement),
|
||||||
|
dataLength(config.dataLength)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -58,6 +59,5 @@ Request RowHammer::nextRequest()
|
|||||||
request.address = currentAddress;
|
request.address = currentAddress;
|
||||||
request.command = Request::Command::Read;
|
request.command = Request::Command::Read;
|
||||||
request.length = dataLength;
|
request.length = dataLength;
|
||||||
request.delay = sc_core::SC_ZERO_TIME;
|
|
||||||
return request;
|
return request;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -37,19 +37,23 @@
|
|||||||
|
|
||||||
#include "simulator/request/RequestProducer.h"
|
#include "simulator/request/RequestProducer.h"
|
||||||
|
|
||||||
|
#include <DRAMSys/config/TraceSetup.h>
|
||||||
|
|
||||||
#include <systemc>
|
#include <systemc>
|
||||||
|
|
||||||
class RowHammer : public RequestProducer
|
class RowHammer : public RequestProducer
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
RowHammer(uint64_t numRequests, uint64_t rowIncrement, unsigned int dataLength);
|
RowHammer(DRAMSys::Config::RowHammer const& config);
|
||||||
|
|
||||||
Request nextRequest() override;
|
Request nextRequest() override;
|
||||||
|
sc_core::sc_time nextTrigger() override { return generatorPeriod; }
|
||||||
uint64_t totalRequests() override { return numberOfRequests; }
|
uint64_t totalRequests() override { return numberOfRequests; }
|
||||||
|
|
||||||
const uint64_t numberOfRequests;
|
sc_core::sc_time generatorPeriod;
|
||||||
const unsigned int dataLength;
|
uint64_t numberOfRequests;
|
||||||
const uint64_t rowIncrement;
|
uint64_t rowIncrement;
|
||||||
|
unsigned int dataLength;
|
||||||
|
|
||||||
uint64_t generatedRequests = 0;
|
uint64_t generatedRequests = 0;
|
||||||
uint64_t currentAddress = 0x00;
|
uint64_t currentAddress = 0x00;
|
||||||
|
|||||||
@@ -42,27 +42,21 @@
|
|||||||
|
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
|
|
||||||
StlPlayer::StlPlayer(std::string_view tracePath,
|
static constexpr std::size_t LINE_BUFFER_SIZE = 10000;
|
||||||
unsigned int clkMhz,
|
|
||||||
unsigned int defaultDataLength,
|
StlPlayer::StlPlayer(DRAMSys::Config::TracePlayer const& config,
|
||||||
|
std::filesystem::path const& trace,
|
||||||
TraceType traceType,
|
TraceType traceType,
|
||||||
bool storageEnabled) :
|
bool storageEnabled) :
|
||||||
traceType(traceType),
|
traceType(traceType),
|
||||||
storageEnabled(storageEnabled),
|
storageEnabled(storageEnabled),
|
||||||
playerPeriod(sc_core::sc_time(1.0 / static_cast<double>(clkMhz), sc_core::SC_US)),
|
playerPeriod(sc_core::sc_time(1.0 / static_cast<double>(config.clkMhz), sc_core::SC_US)),
|
||||||
defaultDataLength(defaultDataLength),
|
defaultDataLength(config.dataLength),
|
||||||
traceFile(tracePath.data()),
|
traceFile(trace)
|
||||||
lineBuffers(
|
|
||||||
{std::make_shared<std::vector<Request>>(), std::make_shared<std::vector<Request>>()}),
|
|
||||||
parseBuffer(lineBuffers.at(1)),
|
|
||||||
readoutBuffer(lineBuffers.at(0))
|
|
||||||
{
|
{
|
||||||
readoutBuffer->reserve(LINE_BUFFER_SIZE);
|
|
||||||
parseBuffer->reserve(LINE_BUFFER_SIZE);
|
|
||||||
|
|
||||||
if (!traceFile.is_open())
|
if (!traceFile.is_open())
|
||||||
SC_REPORT_FATAL("StlPlayer",
|
SC_REPORT_FATAL("StlPlayer",
|
||||||
(std::string("Could not open trace ") + tracePath.data()).c_str());
|
(std::string("Could not open trace ") + trace.string()).c_str());
|
||||||
|
|
||||||
{
|
{
|
||||||
std::string line;
|
std::string line;
|
||||||
@@ -72,60 +66,99 @@ StlPlayer::StlPlayer(std::string_view tracePath,
|
|||||||
numberOfLines++;
|
numberOfLines++;
|
||||||
}
|
}
|
||||||
if (numberOfLines == 0)
|
if (numberOfLines == 0)
|
||||||
SC_REPORT_FATAL("StlPlayer", (std::string("Empty trace ") + tracePath.data()).c_str());
|
SC_REPORT_FATAL("StlPlayer", (std::string("Empty trace ") + trace.string()).c_str());
|
||||||
traceFile.clear();
|
traceFile.clear();
|
||||||
traceFile.seekg(0);
|
traceFile.seekg(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
parseTraceFile();
|
parseTraceFile();
|
||||||
readoutIt = readoutBuffer->cend();
|
swapBuffers();
|
||||||
|
readoutIt = lineBuffers.at(consumeIndex).cbegin();
|
||||||
|
}
|
||||||
|
|
||||||
|
void StlPlayer::incrementLine()
|
||||||
|
{
|
||||||
|
readoutIt++;
|
||||||
|
|
||||||
|
if (readoutIt == lineBuffers.at(consumeIndex).cend())
|
||||||
|
{
|
||||||
|
swapBuffers();
|
||||||
|
readoutIt = lineBuffers.at(consumeIndex).cbegin();
|
||||||
|
|
||||||
|
if (lineBuffers.at(consumeIndex).empty())
|
||||||
|
{
|
||||||
|
if (parserThread.joinable())
|
||||||
|
parserThread.join();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
std::optional<StlPlayer::LineContent> StlPlayer::currentLine() const
|
||||||
|
{
|
||||||
|
if (readoutIt == lineBuffers.at(consumeIndex).cend())
|
||||||
|
return std::nullopt;
|
||||||
|
|
||||||
|
return *readoutIt;
|
||||||
}
|
}
|
||||||
|
|
||||||
Request StlPlayer::nextRequest()
|
Request StlPlayer::nextRequest()
|
||||||
{
|
{
|
||||||
if (readoutIt == readoutBuffer->cend())
|
auto currentLineContent = currentLine();
|
||||||
{
|
|
||||||
readoutIt = swapBuffers();
|
|
||||||
if (readoutIt == readoutBuffer->cend())
|
|
||||||
{
|
|
||||||
if (parserThread.joinable())
|
|
||||||
parserThread.join();
|
|
||||||
|
|
||||||
// The file is read in completely. Nothing more to do.
|
if (!currentLineContent.has_value())
|
||||||
return Request{Request::Command::Stop};
|
{
|
||||||
|
// The file is read in completely. Nothing more to do.
|
||||||
|
return Request{Request::Command::Stop};
|
||||||
|
}
|
||||||
|
|
||||||
|
auto command = currentLineContent->command == LineContent::Command::Read
|
||||||
|
? Request::Command::Read
|
||||||
|
: Request::Command::Write;
|
||||||
|
auto dataLength = currentLineContent->dataLength.has_value()
|
||||||
|
? currentLineContent->dataLength.value()
|
||||||
|
: defaultDataLength;
|
||||||
|
|
||||||
|
Request request{command, currentLineContent->address, dataLength, currentLineContent->data};
|
||||||
|
|
||||||
|
incrementLine();
|
||||||
|
|
||||||
|
return request;
|
||||||
|
}
|
||||||
|
|
||||||
|
sc_core::sc_time StlPlayer::nextTrigger()
|
||||||
|
{
|
||||||
|
auto currentLineContent = currentLine();
|
||||||
|
sc_core::sc_time nextTrigger = sc_core::SC_ZERO_TIME;
|
||||||
|
if (currentLineContent.has_value())
|
||||||
|
{
|
||||||
|
if (traceType == TraceType::Absolute)
|
||||||
|
{
|
||||||
|
sc_core::sc_time cycleTime = currentLineContent->cycle * playerPeriod;
|
||||||
|
bool behindSchedule = sc_core::sc_time_stamp() > cycleTime;
|
||||||
|
nextTrigger =
|
||||||
|
behindSchedule ? sc_core::SC_ZERO_TIME : cycleTime - sc_core::sc_time_stamp();
|
||||||
|
}
|
||||||
|
else // if (traceType == TraceType::Relative)
|
||||||
|
{
|
||||||
|
nextTrigger = currentLineContent->cycle * playerPeriod;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
sc_core::sc_time delay;
|
return nextTrigger;
|
||||||
if (traceType == TraceType::Absolute)
|
|
||||||
{
|
|
||||||
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 = readoutIt->delay;
|
|
||||||
}
|
|
||||||
|
|
||||||
Request request(*readoutIt);
|
|
||||||
request.delay = delay;
|
|
||||||
|
|
||||||
readoutIt++;
|
|
||||||
return request;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void StlPlayer::parseTraceFile()
|
void StlPlayer::parseTraceFile()
|
||||||
{
|
{
|
||||||
unsigned parsedLines = 0;
|
unsigned parsedLines = 0;
|
||||||
parseBuffer->clear();
|
auto& parseBuffer = lineBuffers.at(parseIndex);
|
||||||
|
parseBuffer.clear();
|
||||||
|
|
||||||
while (traceFile && !traceFile.eof() && parsedLines < LINE_BUFFER_SIZE)
|
while (traceFile && !traceFile.eof() && parsedLines < LINE_BUFFER_SIZE)
|
||||||
{
|
{
|
||||||
// Get a new line from the input file.
|
// Get a new line from the input file.
|
||||||
std::string line;
|
std::string line;
|
||||||
std::getline(traceFile, line);
|
std::getline(traceFile, line);
|
||||||
currentLine++;
|
currentParsedLine++;
|
||||||
|
|
||||||
// If the line is empty (\n or \r\n) or starts with '#' (comment) the transaction is
|
// If the line is empty (\n or \r\n) or starts with '#' (comment) the transaction is
|
||||||
// ignored.
|
// ignored.
|
||||||
@@ -133,8 +166,8 @@ void StlPlayer::parseTraceFile()
|
|||||||
continue;
|
continue;
|
||||||
|
|
||||||
parsedLines++;
|
parsedLines++;
|
||||||
parseBuffer->emplace_back();
|
parseBuffer.emplace_back();
|
||||||
Request& content = parseBuffer->back();
|
LineContent& content = parseBuffer.back();
|
||||||
|
|
||||||
// Trace files MUST provide timestamp, command and address for every
|
// Trace files MUST provide timestamp, command and address for every
|
||||||
// transaction. The data information depends on the storage mode
|
// transaction. The data information depends on the storage mode
|
||||||
@@ -148,90 +181,63 @@ void StlPlayer::parseTraceFile()
|
|||||||
{
|
{
|
||||||
// Get the timestamp for the transaction.
|
// Get the timestamp for the transaction.
|
||||||
iss >> element;
|
iss >> element;
|
||||||
if (element.empty())
|
content.cycle = std::stoull(element);
|
||||||
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
|
// Get the optional burst length and command
|
||||||
iss >> element;
|
iss >> element;
|
||||||
if (element.empty())
|
|
||||||
SC_REPORT_FATAL(
|
|
||||||
"StlPlayer",
|
|
||||||
("Malformed trace file line " + std::to_string(currentLine) + ".").c_str());
|
|
||||||
|
|
||||||
if (element.at(0) == '(')
|
if (element.at(0) == '(')
|
||||||
{
|
{
|
||||||
element.erase(0, 1);
|
element.erase(0, 1);
|
||||||
content.length = std::stoul(element);
|
content.dataLength = std::stoul(element);
|
||||||
iss >> 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")
|
if (element == "read")
|
||||||
content.command = Request::Command::Read;
|
content.command = LineContent::Command::Read;
|
||||||
else if (element == "write")
|
else if (element == "write")
|
||||||
content.command = Request::Command::Write;
|
content.command = LineContent::Command::Write;
|
||||||
else
|
else
|
||||||
SC_REPORT_FATAL(
|
throw std::runtime_error("Unable to parse command");
|
||||||
"StlPlayer",
|
|
||||||
("Malformed trace file line " + std::to_string(currentLine) + ".").c_str());
|
|
||||||
|
|
||||||
// Get the address.
|
// Get the address.
|
||||||
iss >> element;
|
iss >> element;
|
||||||
if (element.empty())
|
static constexpr unsigned HEX = 16;
|
||||||
SC_REPORT_FATAL(
|
content.address = std::stoull(element, nullptr, HEX);
|
||||||
"StlPlayer",
|
|
||||||
("Malformed trace file line " + std::to_string(currentLine) + ".").c_str());
|
|
||||||
content.address = std::stoull(element, nullptr, 16);
|
|
||||||
|
|
||||||
// Get the data if necessary.
|
// Get the data if necessary.
|
||||||
if (storageEnabled && content.command == Request::Command::Write)
|
if (storageEnabled && content.command == LineContent::Command::Write)
|
||||||
{
|
{
|
||||||
// The input trace file must provide the data to be stored into the memory.
|
// The input trace file must provide the data to be stored into the memory.
|
||||||
iss >> element;
|
iss >> element;
|
||||||
|
|
||||||
// Check if data length in the trace file is correct.
|
// We need two characters to represent 1 byte in hexadecimal.
|
||||||
// We need two characters to represent 1 byte in hexadecimal. Offset for 0x
|
// Offset for 0x prefix.
|
||||||
// prefix.
|
for (std::size_t i = 2; i < element.length(); i += 2)
|
||||||
if (element.length() != (content.length * 2 + 2))
|
{
|
||||||
SC_REPORT_FATAL(
|
uint8_t byte = std::stoi(element.substr(i, 2), nullptr, HEX);
|
||||||
"StlPlayer",
|
content.data.push_back(byte);
|
||||||
("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 (...)
|
catch (...)
|
||||||
{
|
{
|
||||||
SC_REPORT_FATAL(
|
SC_REPORT_FATAL(
|
||||||
"StlPlayer",
|
"StlPlayer",
|
||||||
("Malformed trace file line " + std::to_string(currentLine) + ".").c_str());
|
("Malformed trace file line " + std::to_string(currentParsedLine) + ".").c_str());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<Request>::const_iterator StlPlayer::swapBuffers()
|
void StlPlayer::swapBuffers()
|
||||||
{
|
{
|
||||||
// Wait for parser to finish
|
// Wait for parser to finish
|
||||||
if (parserThread.joinable())
|
if (parserThread.joinable())
|
||||||
parserThread.join();
|
parserThread.join();
|
||||||
|
|
||||||
// Swap buffers
|
// Swap buffers
|
||||||
std::swap(readoutBuffer, parseBuffer);
|
std::swap(parseIndex, consumeIndex);
|
||||||
|
|
||||||
// Start new parser thread
|
// Start new parser thread
|
||||||
parserThread = std::thread(&StlPlayer::parseTraceFile, this);
|
parserThread = std::thread(&StlPlayer::parseTraceFile, this);
|
||||||
|
|
||||||
return readoutBuffer->cbegin();
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -40,57 +40,78 @@
|
|||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "simulator/request/Request.h"
|
|
||||||
#include "simulator/request/RequestProducer.h"
|
#include "simulator/request/RequestProducer.h"
|
||||||
|
|
||||||
|
#include <DRAMSys/config/TraceSetup.h>
|
||||||
|
|
||||||
#include <systemc>
|
#include <systemc>
|
||||||
#include <tlm>
|
#include <tlm>
|
||||||
|
|
||||||
#include <array>
|
#include <array>
|
||||||
|
#include <filesystem>
|
||||||
#include <fstream>
|
#include <fstream>
|
||||||
#include <memory>
|
#include <optional>
|
||||||
#include <thread>
|
#include <thread>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
class StlPlayer : public RequestProducer
|
class StlPlayer : public RequestProducer
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
enum class TraceType
|
enum class TraceType : uint8_t
|
||||||
{
|
{
|
||||||
Absolute,
|
Absolute,
|
||||||
Relative,
|
Relative,
|
||||||
};
|
};
|
||||||
|
|
||||||
StlPlayer(std::string_view tracePath,
|
StlPlayer(DRAMSys::Config::TracePlayer const& config,
|
||||||
unsigned int clkMhz,
|
std::filesystem::path const& trace,
|
||||||
unsigned int defaultDataLength,
|
|
||||||
TraceType traceType,
|
TraceType traceType,
|
||||||
bool storageEnabled);
|
bool storageEnabled);
|
||||||
|
|
||||||
Request nextRequest() override;
|
//TODO temporary fix
|
||||||
|
~StlPlayer() {
|
||||||
|
if (parserThread.joinable())
|
||||||
|
parserThread.join();
|
||||||
|
}
|
||||||
|
|
||||||
|
Request nextRequest() override;
|
||||||
|
sc_core::sc_time nextTrigger() override;
|
||||||
uint64_t totalRequests() override { return numberOfLines; }
|
uint64_t totalRequests() override { return numberOfLines; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
struct LineContent
|
||||||
|
{
|
||||||
|
unsigned cycle{};
|
||||||
|
enum class Command : uint8_t
|
||||||
|
{
|
||||||
|
Read,
|
||||||
|
Write
|
||||||
|
} command{};
|
||||||
|
uint64_t address{};
|
||||||
|
std::optional<unsigned> dataLength;
|
||||||
|
std::vector<uint8_t> data;
|
||||||
|
};
|
||||||
|
|
||||||
|
std::optional<LineContent> currentLine() const;
|
||||||
|
|
||||||
void parseTraceFile();
|
void parseTraceFile();
|
||||||
std::vector<Request>::const_iterator swapBuffers();
|
void swapBuffers();
|
||||||
|
void incrementLine();
|
||||||
|
|
||||||
static constexpr std::size_t LINE_BUFFER_SIZE = 10000;
|
TraceType traceType;
|
||||||
|
bool storageEnabled;
|
||||||
const TraceType traceType;
|
sc_core::sc_time playerPeriod;
|
||||||
const bool storageEnabled;
|
unsigned int defaultDataLength;
|
||||||
const sc_core::sc_time playerPeriod;
|
|
||||||
const unsigned int defaultDataLength;
|
|
||||||
|
|
||||||
std::ifstream traceFile;
|
std::ifstream traceFile;
|
||||||
uint64_t currentLine = 0;
|
uint64_t currentParsedLine = 0;
|
||||||
uint64_t numberOfLines = 0;
|
uint64_t numberOfLines = 0;
|
||||||
|
|
||||||
std::array<std::shared_ptr<std::vector<Request>>, 2> lineBuffers;
|
std::array<std::vector<LineContent>, 2> lineBuffers;
|
||||||
std::shared_ptr<std::vector<Request>> parseBuffer;
|
std::size_t parseIndex = 0;
|
||||||
std::shared_ptr<std::vector<Request>> readoutBuffer;
|
std::size_t consumeIndex = 1;
|
||||||
|
|
||||||
std::vector<Request>::const_iterator readoutIt;
|
std::vector<LineContent>::const_iterator readoutIt;
|
||||||
|
|
||||||
std::thread parserThread;
|
std::thread parserThread;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -36,18 +36,17 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
#include <systemc>
|
#include <vector>
|
||||||
|
|
||||||
struct Request
|
struct Request
|
||||||
{
|
{
|
||||||
enum class Command
|
enum class Command : uint8_t
|
||||||
{
|
{
|
||||||
Read,
|
Read,
|
||||||
Write,
|
Write,
|
||||||
Stop
|
Stop
|
||||||
} command;
|
} command;
|
||||||
uint64_t address{};
|
uint64_t address = 0;
|
||||||
std::size_t length{};
|
std::size_t length = 0;
|
||||||
sc_core::sc_time delay{};
|
std::vector<unsigned char> data;
|
||||||
std::vector<unsigned char> data{};
|
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -36,22 +36,22 @@
|
|||||||
#include "RequestIssuer.h"
|
#include "RequestIssuer.h"
|
||||||
|
|
||||||
RequestIssuer::RequestIssuer(sc_core::sc_module_name const& name,
|
RequestIssuer::RequestIssuer(sc_core::sc_module_name const& name,
|
||||||
|
std::unique_ptr<RequestProducer> producer,
|
||||||
MemoryManager& memoryManager,
|
MemoryManager& memoryManager,
|
||||||
sc_core::sc_time interfaceClk,
|
sc_core::sc_time interfaceClk,
|
||||||
std::optional<unsigned int> maxPendingReadRequests,
|
std::optional<unsigned int> maxPendingReadRequests,
|
||||||
std::optional<unsigned int> maxPendingWriteRequests,
|
std::optional<unsigned int> maxPendingWriteRequests,
|
||||||
std::function<Request()> nextRequest,
|
|
||||||
std::function<void()> transactionFinished,
|
std::function<void()> transactionFinished,
|
||||||
std::function<void()> terminate) :
|
std::function<void()> terminate) :
|
||||||
sc_module(name),
|
sc_module(name),
|
||||||
|
producer(std::move(producer)),
|
||||||
payloadEventQueue(this, &RequestIssuer::peqCallback),
|
payloadEventQueue(this, &RequestIssuer::peqCallback),
|
||||||
memoryManager(memoryManager),
|
memoryManager(memoryManager),
|
||||||
interfaceClk(interfaceClk),
|
interfaceClk(interfaceClk),
|
||||||
maxPendingReadRequests(maxPendingReadRequests),
|
maxPendingReadRequests(maxPendingReadRequests),
|
||||||
maxPendingWriteRequests(maxPendingWriteRequests),
|
maxPendingWriteRequests(maxPendingWriteRequests),
|
||||||
transactionFinished(std::move(transactionFinished)),
|
transactionFinished(std::move(transactionFinished)),
|
||||||
terminate(std::move(terminate)),
|
terminate(std::move(terminate))
|
||||||
nextRequest(std::move(nextRequest))
|
|
||||||
{
|
{
|
||||||
SC_THREAD(sendNextRequest);
|
SC_THREAD(sendNextRequest);
|
||||||
iSocket.register_nb_transport_bw(this, &RequestIssuer::nb_transport_bw);
|
iSocket.register_nb_transport_bw(this, &RequestIssuer::nb_transport_bw);
|
||||||
@@ -59,48 +59,55 @@ RequestIssuer::RequestIssuer(sc_core::sc_module_name const& name,
|
|||||||
|
|
||||||
void RequestIssuer::sendNextRequest()
|
void RequestIssuer::sendNextRequest()
|
||||||
{
|
{
|
||||||
Request request = nextRequest();
|
while (true)
|
||||||
|
|
||||||
if (request.command == Request::Command::Stop)
|
|
||||||
{
|
{
|
||||||
finished = true;
|
Request request = producer->nextRequest();
|
||||||
return;
|
|
||||||
|
if (request.command == Request::Command::Stop)
|
||||||
|
{
|
||||||
|
finished = true;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (requestInProgress)
|
||||||
|
{
|
||||||
|
wait(endReq);
|
||||||
|
}
|
||||||
|
|
||||||
|
while (!nextRequestSendable())
|
||||||
|
{
|
||||||
|
wait(beginResp);
|
||||||
|
}
|
||||||
|
|
||||||
|
tlm::tlm_generic_payload& payload = memoryManager.allocate(request.length);
|
||||||
|
payload.acquire();
|
||||||
|
payload.set_address(request.address);
|
||||||
|
payload.set_response_status(tlm::TLM_INCOMPLETE_RESPONSE);
|
||||||
|
payload.set_dmi_allowed(false);
|
||||||
|
payload.set_byte_enable_length(0);
|
||||||
|
payload.set_data_length(request.length);
|
||||||
|
payload.set_streaming_width(request.length);
|
||||||
|
payload.set_command(request.command == Request::Command::Read ? tlm::TLM_READ_COMMAND
|
||||||
|
: tlm::TLM_WRITE_COMMAND);
|
||||||
|
|
||||||
|
std::copy(request.data.cbegin(), request.data.cend(), payload.get_data_ptr());
|
||||||
|
|
||||||
|
tlm::tlm_phase phase = tlm::BEGIN_REQ;
|
||||||
|
sc_core::sc_time delay = sc_core::SC_ZERO_TIME;
|
||||||
|
|
||||||
|
iSocket->nb_transport_fw(payload, phase, delay);
|
||||||
|
requestInProgress = true;
|
||||||
|
|
||||||
|
if (request.command == Request::Command::Read)
|
||||||
|
pendingReadRequests++;
|
||||||
|
else if (request.command == Request::Command::Write)
|
||||||
|
pendingWriteRequests++;
|
||||||
|
|
||||||
|
transactionsSent++;
|
||||||
|
|
||||||
|
nextTrigger.notify(producer->nextTrigger());
|
||||||
|
wait(nextTrigger);
|
||||||
}
|
}
|
||||||
|
|
||||||
tlm::tlm_generic_payload& payload = memoryManager.allocate(request.length);
|
|
||||||
payload.acquire();
|
|
||||||
payload.set_address(request.address);
|
|
||||||
payload.set_response_status(tlm::TLM_INCOMPLETE_RESPONSE);
|
|
||||||
payload.set_dmi_allowed(false);
|
|
||||||
payload.set_byte_enable_length(0);
|
|
||||||
payload.set_data_length(request.length);
|
|
||||||
payload.set_streaming_width(request.length);
|
|
||||||
payload.set_command(request.command == Request::Command::Read ? tlm::TLM_READ_COMMAND
|
|
||||||
: tlm::TLM_WRITE_COMMAND);
|
|
||||||
|
|
||||||
std::copy(request.data.cbegin(), request.data.cend(), payload.get_data_ptr());
|
|
||||||
|
|
||||||
tlm::tlm_phase phase = tlm::BEGIN_REQ;
|
|
||||||
sc_core::sc_time delay = request.delay;
|
|
||||||
|
|
||||||
sc_core::sc_time sendingTime = sc_core::sc_time_stamp() + delay;
|
|
||||||
|
|
||||||
bool needsOffset = (sendingTime % interfaceClk) != sc_core::SC_ZERO_TIME;
|
|
||||||
if (needsOffset)
|
|
||||||
{
|
|
||||||
sendingTime += interfaceClk;
|
|
||||||
sendingTime -= sendingTime % interfaceClk;
|
|
||||||
}
|
|
||||||
|
|
||||||
delay = sendingTime - sc_core::sc_time_stamp();
|
|
||||||
iSocket->nb_transport_fw(payload, phase, delay);
|
|
||||||
|
|
||||||
if (request.command == Request::Command::Read)
|
|
||||||
pendingReadRequests++;
|
|
||||||
else if (request.command == Request::Command::Write)
|
|
||||||
pendingWriteRequests++;
|
|
||||||
|
|
||||||
transactionsSent++;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool RequestIssuer::nextRequestSendable() const
|
bool RequestIssuer::nextRequestSendable() const
|
||||||
@@ -121,37 +128,31 @@ void RequestIssuer::peqCallback(tlm::tlm_generic_payload& payload, const tlm::tl
|
|||||||
{
|
{
|
||||||
if (phase == tlm::END_REQ)
|
if (phase == tlm::END_REQ)
|
||||||
{
|
{
|
||||||
|
requestInProgress = false;
|
||||||
|
endReq.notify(sc_core::SC_ZERO_TIME);
|
||||||
|
|
||||||
lastEndRequest = sc_core::sc_time_stamp();
|
lastEndRequest = sc_core::sc_time_stamp();
|
||||||
|
|
||||||
if (nextRequestSendable())
|
if (!nextRequestSendable())
|
||||||
sendNextRequest();
|
|
||||||
else
|
|
||||||
transactionPostponed = true;
|
transactionPostponed = true;
|
||||||
}
|
}
|
||||||
else if (phase == tlm::BEGIN_RESP)
|
else if (phase == tlm::BEGIN_RESP)
|
||||||
{
|
{
|
||||||
tlm::tlm_phase nextPhase = tlm::END_RESP;
|
|
||||||
sc_core::sc_time delay = interfaceClk;
|
|
||||||
iSocket->nb_transport_fw(payload, nextPhase, delay);
|
|
||||||
|
|
||||||
payload.release();
|
|
||||||
|
|
||||||
transactionFinished();
|
|
||||||
|
|
||||||
transactionsReceived++;
|
transactionsReceived++;
|
||||||
|
transactionFinished();
|
||||||
|
|
||||||
if (payload.get_command() == tlm::TLM_READ_COMMAND)
|
if (payload.get_command() == tlm::TLM_READ_COMMAND)
|
||||||
pendingReadRequests--;
|
pendingReadRequests--;
|
||||||
else if (payload.get_command() == tlm::TLM_WRITE_COMMAND)
|
else if (payload.get_command() == tlm::TLM_WRITE_COMMAND)
|
||||||
pendingWriteRequests--;
|
pendingWriteRequests--;
|
||||||
|
|
||||||
// If the initiator wasn't able to send the next payload in the END_REQ phase, do it
|
beginResp.notify(sc_core::SC_ZERO_TIME);
|
||||||
// now.
|
|
||||||
if (transactionPostponed && nextRequestSendable())
|
// Send END_RESP
|
||||||
{
|
tlm::tlm_phase nextPhase = tlm::END_RESP;
|
||||||
sendNextRequest();
|
sc_core::sc_time delay = interfaceClk;
|
||||||
transactionPostponed = false;
|
iSocket->nb_transport_fw(payload, nextPhase, delay);
|
||||||
}
|
payload.release();
|
||||||
|
|
||||||
// If all answers were received:
|
// If all answers were received:
|
||||||
if (finished && transactionsSent == transactionsReceived)
|
if (finished && transactionsSent == transactionsReceived)
|
||||||
|
|||||||
@@ -36,8 +36,10 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "Request.h"
|
#include "Request.h"
|
||||||
|
#include "RequestProducer.h"
|
||||||
#include "simulator/MemoryManager.h"
|
#include "simulator/MemoryManager.h"
|
||||||
|
|
||||||
|
#include <memory>
|
||||||
#include <systemc>
|
#include <systemc>
|
||||||
#include <tlm>
|
#include <tlm>
|
||||||
#include <tlm_utils/peq_with_cb_and_phase.h>
|
#include <tlm_utils/peq_with_cb_and_phase.h>
|
||||||
@@ -51,21 +53,43 @@ public:
|
|||||||
tlm_utils::simple_initiator_socket<RequestIssuer> iSocket;
|
tlm_utils::simple_initiator_socket<RequestIssuer> iSocket;
|
||||||
|
|
||||||
RequestIssuer(sc_core::sc_module_name const& name,
|
RequestIssuer(sc_core::sc_module_name const& name,
|
||||||
|
std::unique_ptr<RequestProducer> producer,
|
||||||
MemoryManager& memoryManager,
|
MemoryManager& memoryManager,
|
||||||
sc_core::sc_time interfaceClk,
|
sc_core::sc_time interfaceClk,
|
||||||
std::optional<unsigned int> maxPendingReadRequests,
|
std::optional<unsigned int> maxPendingReadRequests,
|
||||||
std::optional<unsigned int> maxPendingWriteRequests,
|
std::optional<unsigned int> maxPendingWriteRequests,
|
||||||
std::function<Request()> nextRequest,
|
|
||||||
std::function<void()> transactionFinished,
|
std::function<void()> transactionFinished,
|
||||||
std::function<void()> terminate);
|
std::function<void()> terminate);
|
||||||
SC_HAS_PROCESS(RequestIssuer);
|
SC_HAS_PROCESS(RequestIssuer);
|
||||||
|
|
||||||
|
uint64_t totalRequests() { return producer->totalRequests(); };
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
void sendNextRequest();
|
||||||
|
bool nextRequestSendable() const;
|
||||||
|
|
||||||
|
sc_core::sc_event nextTrigger;
|
||||||
|
sc_core::sc_event endReq;
|
||||||
|
sc_core::sc_event beginResp;
|
||||||
|
|
||||||
|
tlm::tlm_sync_enum nb_transport_bw(tlm::tlm_generic_payload& payload,
|
||||||
|
tlm::tlm_phase& phase,
|
||||||
|
sc_core::sc_time& bwDelay)
|
||||||
|
{
|
||||||
|
payloadEventQueue.notify(payload, phase, bwDelay);
|
||||||
|
return tlm::TLM_ACCEPTED;
|
||||||
|
}
|
||||||
|
|
||||||
|
void peqCallback(tlm::tlm_generic_payload& payload, const tlm::tlm_phase& phase);
|
||||||
|
|
||||||
|
std::unique_ptr<RequestProducer> producer;
|
||||||
|
|
||||||
tlm_utils::peq_with_cb_and_phase<RequestIssuer> payloadEventQueue;
|
tlm_utils::peq_with_cb_and_phase<RequestIssuer> payloadEventQueue;
|
||||||
MemoryManager& memoryManager;
|
MemoryManager& memoryManager;
|
||||||
|
|
||||||
sc_core::sc_time interfaceClk;
|
sc_core::sc_time interfaceClk;
|
||||||
|
|
||||||
|
bool requestInProgress = false;
|
||||||
bool transactionPostponed = false;
|
bool transactionPostponed = false;
|
||||||
bool finished = false;
|
bool finished = false;
|
||||||
|
|
||||||
@@ -80,18 +104,4 @@ private:
|
|||||||
|
|
||||||
std::function<void()> transactionFinished;
|
std::function<void()> transactionFinished;
|
||||||
std::function<void()> terminate;
|
std::function<void()> terminate;
|
||||||
std::function<Request()> nextRequest;
|
|
||||||
|
|
||||||
void sendNextRequest();
|
|
||||||
bool nextRequestSendable() const;
|
|
||||||
|
|
||||||
tlm::tlm_sync_enum nb_transport_bw(tlm::tlm_generic_payload& payload,
|
|
||||||
tlm::tlm_phase& phase,
|
|
||||||
sc_core::sc_time& bwDelay)
|
|
||||||
{
|
|
||||||
payloadEventQueue.notify(payload, phase, bwDelay);
|
|
||||||
return tlm::TLM_ACCEPTED;
|
|
||||||
}
|
|
||||||
|
|
||||||
void peqCallback(tlm::tlm_generic_payload& payload, const tlm::tlm_phase& phase);
|
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -37,6 +37,8 @@
|
|||||||
|
|
||||||
#include "Request.h"
|
#include "Request.h"
|
||||||
|
|
||||||
|
#include <systemc>
|
||||||
|
|
||||||
class RequestProducer
|
class RequestProducer
|
||||||
{
|
{
|
||||||
protected:
|
protected:
|
||||||
@@ -50,6 +52,7 @@ public:
|
|||||||
virtual ~RequestProducer() = default;
|
virtual ~RequestProducer() = default;
|
||||||
|
|
||||||
virtual Request nextRequest() = 0;
|
virtual Request nextRequest() = 0;
|
||||||
|
virtual sc_core::sc_time nextTrigger() = 0;
|
||||||
virtual uint64_t totalRequests() = 0;
|
virtual uint64_t totalRequests() = 0;
|
||||||
virtual void reset(){};
|
virtual void reset() {};
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -215,6 +215,7 @@
|
|||||||
{
|
{
|
||||||
"type": "player",
|
"type": "player",
|
||||||
"clkMhz": 100,
|
"clkMhz": 100,
|
||||||
|
"dataLength": 64,
|
||||||
"name": "mytrace.stl"
|
"name": "mytrace.stl"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -222,12 +223,14 @@
|
|||||||
"addressDistribution": "random",
|
"addressDistribution": "random",
|
||||||
"clkMhz": 100,
|
"clkMhz": 100,
|
||||||
"name": "MyTestGen",
|
"name": "MyTestGen",
|
||||||
|
"dataLength": 64,
|
||||||
"numRequests": 1000,
|
"numRequests": 1000,
|
||||||
"rwRatio": 0.5
|
"rwRatio": 0.5
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"type": "statemachine",
|
"type": "statemachine",
|
||||||
"clkMhz": 100,
|
"clkMhz": 100,
|
||||||
|
"dataLength": 64,
|
||||||
"maxPendingReadRequests": 8,
|
"maxPendingReadRequests": 8,
|
||||||
"name": "MyTestGen",
|
"name": "MyTestGen",
|
||||||
"states": [
|
"states": [
|
||||||
@@ -260,6 +263,7 @@
|
|||||||
{
|
{
|
||||||
"type": "rowhammer",
|
"type": "rowhammer",
|
||||||
"clkMhz": 100,
|
"clkMhz": 100,
|
||||||
|
"dataLength": 64,
|
||||||
"name": "MyTestHammer",
|
"name": "MyTestHammer",
|
||||||
"numRequests": 4000,
|
"numRequests": 4000,
|
||||||
"rowIncrement": 2097152
|
"rowIncrement": 2097152
|
||||||
|
|||||||
@@ -318,6 +318,7 @@ DRAMSys::Config::TracePlayer ConfigurationTest::createTracePlayer()
|
|||||||
{
|
{
|
||||||
DRAMSys::Config::TracePlayer player;
|
DRAMSys::Config::TracePlayer player;
|
||||||
player.clkMhz = 100;
|
player.clkMhz = 100;
|
||||||
|
player.dataLength = 64;
|
||||||
player.name = "mytrace.stl";
|
player.name = "mytrace.stl";
|
||||||
|
|
||||||
return player;
|
return player;
|
||||||
@@ -327,6 +328,7 @@ DRAMSys::Config::TrafficGenerator ConfigurationTest::createTraceGeneratorOneStat
|
|||||||
{
|
{
|
||||||
DRAMSys::Config::TrafficGenerator gen;
|
DRAMSys::Config::TrafficGenerator gen;
|
||||||
gen.clkMhz = 100;
|
gen.clkMhz = 100;
|
||||||
|
gen.dataLength = 64;
|
||||||
gen.name = "MyTestGen";
|
gen.name = "MyTestGen";
|
||||||
|
|
||||||
gen.numRequests = 1000;
|
gen.numRequests = 1000;
|
||||||
@@ -345,6 +347,7 @@ ConfigurationTest::createTraceGeneratorMultipleStates()
|
|||||||
DRAMSys::Config::TrafficGeneratorStateMachine gen;
|
DRAMSys::Config::TrafficGeneratorStateMachine gen;
|
||||||
|
|
||||||
gen.clkMhz = 100;
|
gen.clkMhz = 100;
|
||||||
|
gen.dataLength = 64;
|
||||||
gen.name = "MyTestGen";
|
gen.name = "MyTestGen";
|
||||||
gen.maxPendingReadRequests = 8;
|
gen.maxPendingReadRequests = 8;
|
||||||
|
|
||||||
@@ -381,6 +384,7 @@ DRAMSys::Config::RowHammer ConfigurationTest::createTraceHammer()
|
|||||||
DRAMSys::Config::RowHammer hammer;
|
DRAMSys::Config::RowHammer hammer;
|
||||||
|
|
||||||
hammer.clkMhz = 100;
|
hammer.clkMhz = 100;
|
||||||
|
hammer.dataLength = 64;
|
||||||
hammer.name = "MyTestHammer";
|
hammer.name = "MyTestHammer";
|
||||||
hammer.numRequests = 4000;
|
hammer.numRequests = 4000;
|
||||||
hammer.rowIncrement = 2097152;
|
hammer.rowIncrement = 2097152;
|
||||||
@@ -720,12 +724,14 @@ TEST_F(ConfigurationTest, TraceSetup)
|
|||||||
{
|
{
|
||||||
"type": "player",
|
"type": "player",
|
||||||
"clkMhz": 100,
|
"clkMhz": 100,
|
||||||
|
"dataLength": 64,
|
||||||
"name": "mytrace.stl"
|
"name": "mytrace.stl"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"type": "generator",
|
"type": "generator",
|
||||||
"addressDistribution": "random",
|
"addressDistribution": "random",
|
||||||
"clkMhz": 100,
|
"clkMhz": 100,
|
||||||
|
"dataLength": 64,
|
||||||
"name": "MyTestGen",
|
"name": "MyTestGen",
|
||||||
"numRequests": 1000,
|
"numRequests": 1000,
|
||||||
"rwRatio": 0.5
|
"rwRatio": 0.5
|
||||||
@@ -733,6 +739,7 @@ TEST_F(ConfigurationTest, TraceSetup)
|
|||||||
{
|
{
|
||||||
"type": "statemachine",
|
"type": "statemachine",
|
||||||
"clkMhz": 100,
|
"clkMhz": 100,
|
||||||
|
"dataLength": 64,
|
||||||
"maxPendingReadRequests": 8,
|
"maxPendingReadRequests": 8,
|
||||||
"name": "MyTestGen",
|
"name": "MyTestGen",
|
||||||
"states": [
|
"states": [
|
||||||
@@ -765,6 +772,7 @@ TEST_F(ConfigurationTest, TraceSetup)
|
|||||||
{
|
{
|
||||||
"type": "rowhammer",
|
"type": "rowhammer",
|
||||||
"clkMhz": 100,
|
"clkMhz": 100,
|
||||||
|
"dataLength": 64,
|
||||||
"name": "MyTestHammer",
|
"name": "MyTestHammer",
|
||||||
"numRequests": 4000,
|
"numRequests": 4000,
|
||||||
"rowIncrement": 2097152
|
"rowIncrement": 2097152
|
||||||
|
|||||||
@@ -137,6 +137,7 @@
|
|||||||
{
|
{
|
||||||
"type": "player",
|
"type": "player",
|
||||||
"clkMhz": 533,
|
"clkMhz": 533,
|
||||||
|
"dataLength": 64,
|
||||||
"name": "traces/trace_test2.stl"
|
"name": "traces/trace_test2.stl"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
|||||||
Binary file not shown.
@@ -213,6 +213,7 @@
|
|||||||
{
|
{
|
||||||
"type": "player",
|
"type": "player",
|
||||||
"clkMhz": 933,
|
"clkMhz": 933,
|
||||||
|
"dataLength": 64,
|
||||||
"name": "traces/trace_test3.stl"
|
"name": "traces/trace_test3.stl"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
|||||||
@@ -220,6 +220,7 @@
|
|||||||
{
|
{
|
||||||
"type": "player",
|
"type": "player",
|
||||||
"clkMhz": 1600,
|
"clkMhz": 1600,
|
||||||
|
"dataLength": 64,
|
||||||
"name": "traces/trace_test3.stl"
|
"name": "traces/trace_test3.stl"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
|||||||
Binary file not shown.
@@ -128,11 +128,13 @@
|
|||||||
{
|
{
|
||||||
"type": "player",
|
"type": "player",
|
||||||
"clkMhz": 1000,
|
"clkMhz": 1000,
|
||||||
|
"dataLength": 64,
|
||||||
"name": "traces/trace1_test4.stl"
|
"name": "traces/trace1_test4.stl"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"type": "player",
|
"type": "player",
|
||||||
"clkMhz": 1000,
|
"clkMhz": 1000,
|
||||||
|
"dataLength": 64,
|
||||||
"name": "traces/trace2_test4.stl"
|
"name": "traces/trace2_test4.stl"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
|||||||
Binary file not shown.
@@ -131,11 +131,13 @@
|
|||||||
{
|
{
|
||||||
"type": "player",
|
"type": "player",
|
||||||
"clkMhz": 1600,
|
"clkMhz": 1600,
|
||||||
|
"dataLength": 32,
|
||||||
"name": "traces/trace1_test4.stl"
|
"name": "traces/trace1_test4.stl"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"type": "player",
|
"type": "player",
|
||||||
"clkMhz": 1600,
|
"clkMhz": 1600,
|
||||||
|
"dataLength": 32,
|
||||||
"name": "traces/trace2_test4.stl"
|
"name": "traces/trace2_test4.stl"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
|||||||
@@ -183,6 +183,7 @@
|
|||||||
{
|
{
|
||||||
"type": "player",
|
"type": "player",
|
||||||
"clkMhz": 1600,
|
"clkMhz": 1600,
|
||||||
|
"dataLength": 32,
|
||||||
"name": "traces/trace_lpddr4.stl"
|
"name": "traces/trace_lpddr4.stl"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
|||||||
@@ -205,6 +205,7 @@
|
|||||||
{
|
{
|
||||||
"type": "player",
|
"type": "player",
|
||||||
"clkMhz": 1600,
|
"clkMhz": 1600,
|
||||||
|
"dataLength": 32,
|
||||||
"name": "traces/trace_lpddr5.stl"
|
"name": "traces/trace_lpddr5.stl"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
|||||||
Reference in New Issue
Block a user