From 8c861d81c9b4c4ff66ff4512d6ab41d5d9f9dc5a Mon Sep 17 00:00:00 2001 From: Derek Christ Date: Tue, 29 Apr 2025 10:46:33 +0200 Subject: [PATCH 1/4] Decouple initiator clock from memory responses Previously, the initiators were implicitly coupled to the responses of the memory, calculating each new initiator clock relatively based on the time of the BEGIN_RESP phase. This lead to an implicit coupling as same rounding error of the initiator clock to the memory clock was applied each time again. Now, initiators are in itself self-clocked and only send requests based on backpressure. --- .../DRAMSys/controller/Controller.cpp | 4 +- src/simulator/CMakeLists.txt | 6 +- src/simulator/simulator/SimpleInitiator.h | 71 ------- src/simulator/simulator/Simulator.cpp | 77 ++++---- src/simulator/simulator/Simulator.h | 8 +- .../GeneratorState.h} | 23 +-- .../{RandomProducer.cpp => RandomState.cpp} | 17 +- .../{RandomProducer.h => RandomState.h} | 19 +- ...entialProducer.cpp => SequentialState.cpp} | 16 +- ...SequentialProducer.h => SequentialState.h} | 23 ++- .../simulator/generator/TrafficGenerator.cpp | 97 ++++------ .../simulator/generator/TrafficGenerator.h | 40 ++-- .../simulator/generator/definitions.h | 41 ---- src/simulator/simulator/hammer/RowHammer.cpp | 10 +- src/simulator/simulator/hammer/RowHammer.h | 12 +- src/simulator/simulator/player/StlPlayer.cpp | 181 +++++++++--------- src/simulator/simulator/player/StlPlayer.h | 48 +++-- src/simulator/simulator/request/Request.h | 11 +- .../simulator/request/RequestIssuer.cpp | 123 ++++++------ .../simulator/request/RequestIssuer.h | 40 ++-- .../simulator/request/RequestProducer.h | 5 +- .../DRAMSys_ddr3-dual-rank_ddr3_ch0.tdb | 4 +- .../DRAMSys_hbm2-example_hbm2_ch0.tdb | 2 +- .../DRAMSys_hbm3-example_hbm3_ch0.tdb | 4 +- 24 files changed, 389 insertions(+), 493 deletions(-) delete mode 100644 src/simulator/simulator/SimpleInitiator.h rename src/simulator/simulator/{Initiator.h => generator/GeneratorState.h} (77%) rename src/simulator/simulator/generator/{RandomProducer.cpp => RandomState.cpp} (87%) rename src/simulator/simulator/generator/{RandomProducer.h => RandomState.h} (86%) rename src/simulator/simulator/generator/{SequentialProducer.cpp => SequentialState.cpp} (89%) rename src/simulator/simulator/generator/{SequentialProducer.h => SequentialState.h} (84%) delete mode 100644 src/simulator/simulator/generator/definitions.h diff --git a/src/libdramsys/DRAMSys/controller/Controller.cpp b/src/libdramsys/DRAMSys/controller/Controller.cpp index f1cd0599..39598248 100644 --- a/src/libdramsys/DRAMSys/controller/Controller.cpp +++ b/src/libdramsys/DRAMSys/controller/Controller.cpp @@ -598,8 +598,8 @@ void Controller::manageRequests(const sc_time& delay) transToAcquire.payload->acquire(); // The following logic assumes that transactions are naturally aligned - const uint64_t address = transToAcquire.payload->get_address(); - const uint64_t dataLength = transToAcquire.payload->get_data_length(); + uint64_t address = transToAcquire.payload->get_address(); + [[maybe_unused]] uint64_t dataLength = transToAcquire.payload->get_data_length(); assert((dataLength & (dataLength - 1)) == 0); // Data length must be a power of 2 assert(address % dataLength == 0); // Check if naturally aligned diff --git a/src/simulator/CMakeLists.txt b/src/simulator/CMakeLists.txt index b218184a..2a4dcd63 100644 --- a/src/simulator/CMakeLists.txt +++ b/src/simulator/CMakeLists.txt @@ -28,7 +28,7 @@ # NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS # SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # -# Authors: +# Authors: # Matthias Jung # Lukas Steiner # Derek Christ @@ -45,8 +45,8 @@ add_library(simulator simulator/EccModule.cpp simulator/MemoryManager.cpp simulator/Simulator.cpp - simulator/generator/RandomProducer.cpp - simulator/generator/SequentialProducer.cpp + simulator/generator/RandomState.cpp + simulator/generator/SequentialState.cpp simulator/generator/TrafficGenerator.cpp simulator/hammer/RowHammer.cpp simulator/player/StlPlayer.cpp diff --git a/src/simulator/simulator/SimpleInitiator.h b/src/simulator/simulator/SimpleInitiator.h deleted file mode 100644 index 8c134b1a..00000000 --- a/src/simulator/simulator/SimpleInitiator.h +++ /dev/null @@ -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 class SimpleInitiator : public Initiator -{ -public: - SimpleInitiator(sc_core::sc_module_name const& name, - MemoryManager& memoryManager, - sc_core::sc_time interfaceClk, - std::optional maxPendingReadRequests, - std::optional maxPendingWriteRequests, - std::function transactionFinished, - std::function terminate, - Producer&& producer) : - producer(std::forward(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; -}; diff --git a/src/simulator/simulator/Simulator.cpp b/src/simulator/simulator/Simulator.cpp index e2c363c7..86dc0b7d 100644 --- a/src/simulator/simulator/Simulator.cpp +++ b/src/simulator/simulator/Simulator.cpp @@ -35,18 +35,19 @@ #include "Simulator.h" -#include "SimpleInitiator.h" #include "generator/TrafficGenerator.h" #include "hammer/RowHammer.h" #include "player/StlPlayer.h" +#include "simulator/request/RequestIssuer.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), memoryManager(storageEnabled), configuration(std::move(configuration)), dramSys(std::make_unique("DRAMSys", this->configuration)), - baseConfig(baseConfig) + baseConfig(std::move(baseConfig)) { terminateInitiator = [this]() { @@ -74,12 +75,12 @@ Simulator::Simulator(DRAMSys::Config::Configuration configuration, std::filesyst { auto initiator = instantiateInitiator(initiatorConfig); totalTransactions += initiator->totalRequests(); - initiator->bind(dramSys->tSocket); + initiator->iSocket.bind(dramSys->tSocket); initiators.push_back(std::move(initiator)); } } -std::unique_ptr +std::unique_ptr Simulator::instantiateInitiator(const DRAMSys::Config::Initiator& initiator) { uint64_t memorySize = dramSys->getMemSpec().getSimMemSizeInBytes(); @@ -87,19 +88,23 @@ Simulator::instantiateInitiator(const DRAMSys::Config::Initiator& initiator) unsigned int defaultDataLength = dramSys->getMemSpec().defaultBytesPerBurst; return std::visit( - [=](auto&& config) -> std::unique_ptr + [=](auto&& config) -> std::unique_ptr { using T = std::decay_t; if constexpr (std::is_same_v || std::is_same_v) { - return std::make_unique(config, - interfaceClk, - memorySize, - defaultDataLength, - memoryManager, - finishTransaction, - terminateInitiator); + auto generator = + std::make_unique(config, memorySize, defaultDataLength); + + return std::make_unique(config.name.c_str(), + std::move(generator), + memoryManager, + interfaceClk, + config.maxPendingReadRequests, + config.maxPendingWriteRequests, + finishTransaction, + terminateInitiator); } else if constexpr (std::is_same_v) { @@ -119,33 +124,33 @@ Simulator::instantiateInitiator(const DRAMSys::Config::Initiator& initiator) SC_REPORT_FATAL("Simulator", report.c_str()); } - StlPlayer player(tracePath.c_str(), - config.clkMhz, - defaultDataLength, - *traceType, - storageEnabled); + auto player = std::make_unique(tracePath.c_str(), + config.clkMhz, + defaultDataLength, + *traceType, + storageEnabled); - return std::make_unique>(config.name.c_str(), - memoryManager, - interfaceClk, - std::nullopt, - std::nullopt, - finishTransaction, - terminateInitiator, - std::move(player)); + return std::make_unique(config.name.c_str(), + std::move(player), + memoryManager, + interfaceClk, + std::nullopt, + std::nullopt, + finishTransaction, + terminateInitiator); } else if constexpr (std::is_same_v) { - RowHammer hammer(config.numRequests, config.rowIncrement, defaultDataLength); + auto hammer = std::make_unique(config, defaultDataLength); - return std::make_unique>(config.name.c_str(), - memoryManager, - interfaceClk, - 1, - 1, - finishTransaction, - terminateInitiator, - std::move(hammer)); + return std::make_unique(config.name.c_str(), + std::move(hammer), + memoryManager, + interfaceClk, + 1, + 1, + finishTransaction, + terminateInitiator); } }, initiator.getVariant()); @@ -175,5 +180,5 @@ void Simulator::run() auto finish = std::chrono::high_resolution_clock::now(); std::chrono::duration 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"; } diff --git a/src/simulator/simulator/Simulator.h b/src/simulator/simulator/Simulator.h index 4d7a5434..37cc1c07 100644 --- a/src/simulator/simulator/Simulator.h +++ b/src/simulator/simulator/Simulator.h @@ -35,8 +35,8 @@ #pragma once -#include "Initiator.h" #include "MemoryManager.h" +#include "simulator/request/RequestIssuer.h" #include #include @@ -49,15 +49,15 @@ public: void run(); private: - std::unique_ptr instantiateInitiator(const DRAMSys::Config::Initiator& initiator); + std::unique_ptr instantiateInitiator(const DRAMSys::Config::Initiator& initiator); - const bool storageEnabled; + bool storageEnabled; MemoryManager memoryManager; DRAMSys::Config::Configuration configuration; std::unique_ptr dramSys; - std::vector> initiators; + std::vector> initiators; std::function terminateInitiator; std::function finishTransaction; diff --git a/src/simulator/simulator/Initiator.h b/src/simulator/simulator/generator/GeneratorState.h similarity index 77% rename from src/simulator/simulator/Initiator.h rename to src/simulator/simulator/generator/GeneratorState.h index eeb99b3b..02cdd947 100644 --- a/src/simulator/simulator/Initiator.h +++ b/src/simulator/simulator/generator/GeneratorState.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2023, RPTU Kaiserslautern-Landau + * Copyright (c) 2025, RPTU Kaiserslautern-Landau * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -35,20 +35,21 @@ #pragma once -#include +#include "simulator/request/Request.h" -class Initiator +class GeneratorState { protected: - Initiator(const Initiator&) = default; - Initiator(Initiator&&) = default; - Initiator& operator=(const Initiator&) = default; - Initiator& operator=(Initiator&&) = default; + GeneratorState(const GeneratorState&) = default; + GeneratorState(GeneratorState&&) = default; + GeneratorState& operator=(const GeneratorState&) = default; + GeneratorState& operator=(GeneratorState&&) = default; public: - Initiator() = default; - virtual ~Initiator() = default; + GeneratorState() = default; + virtual ~GeneratorState() = default; - virtual void bind(tlm_utils::multi_target_base<>& target) = 0; + virtual Request nextRequest() = 0; virtual uint64_t totalRequests() = 0; -}; + virtual void reset() {} +}; \ No newline at end of file diff --git a/src/simulator/simulator/generator/RandomProducer.cpp b/src/simulator/simulator/generator/RandomState.cpp similarity index 87% rename from src/simulator/simulator/generator/RandomProducer.cpp rename to src/simulator/simulator/generator/RandomState.cpp index b954bd46..eab5f9b8 100644 --- a/src/simulator/simulator/generator/RandomProducer.cpp +++ b/src/simulator/simulator/generator/RandomState.cpp @@ -33,11 +33,12 @@ * Derek Christ */ -#include "RandomProducer.h" -#include "definitions.h" +#include "RandomState.h" -RandomProducer::RandomProducer(uint64_t numRequests, - std::optional seed, +#include + +RandomState::RandomState(uint64_t numRequests, + uint64_t seed, double rwRatio, std::optional minAddress, std::optional maxAddress, @@ -45,13 +46,12 @@ RandomProducer::RandomProducer(uint64_t numRequests, unsigned int dataLength, unsigned int dataAlignment) : numberOfRequests(numRequests), - seed(seed.value_or(DEFAULT_SEED)), + seed(seed), rwRatio(rwRatio), dataLength(dataLength), dataAlignment(dataAlignment), randomGenerator(this->seed), - randomAddressDistribution(minAddress.value_or(DEFAULT_MIN_ADDRESS), - maxAddress.value_or((memorySize)-dataLength)) + randomAddressDistribution(minAddress.value_or(0), maxAddress.value_or((memorySize)-dataLength)) { if (minAddress > memorySize - 1) 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); } -Request RandomProducer::nextRequest() +Request RandomState::nextRequest() { Request request; request.address = randomAddressDistribution(randomGenerator); @@ -76,7 +76,6 @@ Request RandomProducer::nextRequest() request.command = readWriteDistribution(randomGenerator) < rwRatio ? Request::Command::Read : Request::Command::Write; request.length = dataLength; - request.delay = sc_core::SC_ZERO_TIME; return request; } diff --git a/src/simulator/simulator/generator/RandomProducer.h b/src/simulator/simulator/generator/RandomState.h similarity index 86% rename from src/simulator/simulator/generator/RandomProducer.h rename to src/simulator/simulator/generator/RandomState.h index 062c3acf..e517ba83 100644 --- a/src/simulator/simulator/generator/RandomProducer.h +++ b/src/simulator/simulator/generator/RandomState.h @@ -35,16 +35,16 @@ #pragma once -#include "simulator/request/RequestProducer.h" +#include "simulator/generator/GeneratorState.h" #include #include -class RandomProducer : public RequestProducer +class RandomState : public GeneratorState { public: - RandomProducer(uint64_t numRequests, - std::optional seed, + RandomState(uint64_t numRequests, + uint64_t seed, double rwRatio, std::optional minAddress, std::optional maxAddress, @@ -53,14 +53,13 @@ public: unsigned int dataAlignment); Request nextRequest() override; - uint64_t totalRequests() override { return numberOfRequests; } - const uint64_t numberOfRequests; - const uint64_t seed; - const double rwRatio; - const unsigned int dataLength; - const unsigned int dataAlignment; + uint64_t numberOfRequests; + uint64_t seed; + double rwRatio; + unsigned int dataLength; + unsigned int dataAlignment; std::default_random_engine randomGenerator; std::uniform_real_distribution readWriteDistribution{0.0, 1.0}; diff --git a/src/simulator/simulator/generator/SequentialProducer.cpp b/src/simulator/simulator/generator/SequentialState.cpp similarity index 89% rename from src/simulator/simulator/generator/SequentialProducer.cpp rename to src/simulator/simulator/generator/SequentialState.cpp index 43cfa525..380acfe1 100644 --- a/src/simulator/simulator/generator/SequentialProducer.cpp +++ b/src/simulator/simulator/generator/SequentialState.cpp @@ -33,11 +33,12 @@ * Derek Christ */ -#include "SequentialProducer.h" -#include "definitions.h" +#include "SequentialState.h" -SequentialProducer::SequentialProducer(uint64_t numRequests, - std::optional seed, +#include + +SequentialState::SequentialState(uint64_t numRequests, + uint64_t seed, double rwRatio, std::optional addressIncrement, std::optional minAddress, @@ -46,9 +47,9 @@ SequentialProducer::SequentialProducer(uint64_t numRequests, unsigned int dataLength) : numberOfRequests(numRequests), addressIncrement(addressIncrement.value_or(dataLength)), - minAddress(minAddress.value_or(DEFAULT_MIN_ADDRESS)), + minAddress(minAddress.value_or(0)), maxAddress(maxAddress.value_or(memorySize - 1)), - seed(seed.value_or(DEFAULT_SEED)), + seed(seed), rwRatio(rwRatio), dataLength(dataLength), randomGenerator(this->seed) @@ -65,14 +66,13 @@ SequentialProducer::SequentialProducer(uint64_t numRequests, rwRatio = std::clamp(rwRatio, 0.0, 1.0); } -Request SequentialProducer::nextRequest() +Request SequentialState::nextRequest() { Request request; request.address = generatedRequests * addressIncrement % (maxAddress - minAddress) + minAddress; request.command = readWriteDistribution(randomGenerator) < rwRatio ? Request::Command::Read : Request::Command::Write; request.length = dataLength; - request.delay = sc_core::SC_ZERO_TIME; generatedRequests++; return request; diff --git a/src/simulator/simulator/generator/SequentialProducer.h b/src/simulator/simulator/generator/SequentialState.h similarity index 84% rename from src/simulator/simulator/generator/SequentialProducer.h rename to src/simulator/simulator/generator/SequentialState.h index d3f64e6e..a9547698 100644 --- a/src/simulator/simulator/generator/SequentialProducer.h +++ b/src/simulator/simulator/generator/SequentialState.h @@ -35,16 +35,16 @@ #pragma once -#include "simulator/request/RequestProducer.h" +#include "simulator/generator/GeneratorState.h" #include #include -class SequentialProducer : public RequestProducer +class SequentialState : public GeneratorState { public: - SequentialProducer(uint64_t numRequests, - std::optional seed, + SequentialState(uint64_t numRequests, + uint64_t seed, double rwRatio, std::optional addressIncrement, std::optional minAddress, @@ -53,17 +53,16 @@ public: unsigned int dataLength); Request nextRequest() override; - uint64_t totalRequests() override { return numberOfRequests; } void reset() override { generatedRequests = 0; } - const uint64_t numberOfRequests; - const uint64_t addressIncrement; - const uint64_t minAddress; - const uint64_t maxAddress; - const uint64_t seed; - const double rwRatio; - const unsigned int dataLength; + uint64_t numberOfRequests; + uint64_t addressIncrement; + uint64_t minAddress; + uint64_t maxAddress; + uint64_t seed; + double rwRatio; + unsigned int dataLength; std::default_random_engine randomGenerator; std::uniform_real_distribution readWriteDistribution{0.0, 1.0}; diff --git a/src/simulator/simulator/generator/TrafficGenerator.cpp b/src/simulator/simulator/generator/TrafficGenerator.cpp index 71599190..92f33a7d 100644 --- a/src/simulator/simulator/generator/TrafficGenerator.cpp +++ b/src/simulator/simulator/generator/TrafficGenerator.cpp @@ -35,27 +35,14 @@ #include "TrafficGenerator.h" -#include "RandomProducer.h" -#include "SequentialProducer.h" +#include "RandomState.h" +#include "SequentialState.h" TrafficGenerator::TrafficGenerator(DRAMSys::Config::TrafficGeneratorStateMachine const& config, - sc_core::sc_time interfaceClk, uint64_t memorySize, - unsigned int defaultDataLength, - MemoryManager& memoryManager, - std::function transactionFinished, - std::function terminateInitiator) : + unsigned int defaultDataLength) : stateTransistions(config.transitions), - generatorPeriod(sc_core::sc_time(1.0 / static_cast(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)) + generatorPeriod(sc_core::sc_time(1.0 / static_cast(config.clkMhz), sc_core::SC_US)) { unsigned int dataLength = config.dataLength.value_or(defaultDataLength); unsigned int dataAlignment = config.dataAlignment.value_or(dataLength); @@ -74,8 +61,8 @@ TrafficGenerator::TrafficGenerator(DRAMSys::Config::TrafficGeneratorStateMachine if (activeState.addressDistribution == DRAMSys::Config::AddressDistribution::Random) { - auto producer = std::make_unique(activeState.numRequests, - config.seed, + auto producer = std::make_unique(activeState.numRequests, + config.seed.value_or(0), activeState.rwRatio, activeState.minAddress, activeState.maxAddress, @@ -88,8 +75,8 @@ TrafficGenerator::TrafficGenerator(DRAMSys::Config::TrafficGeneratorStateMachine else { auto producer = - std::make_unique(activeState.numRequests, - config.seed, + std::make_unique(activeState.numRequests, + config.seed.value_or(0), activeState.rwRatio, activeState.addressIncrement, activeState.minAddress, @@ -111,30 +98,17 @@ TrafficGenerator::TrafficGenerator(DRAMSys::Config::TrafficGeneratorStateMachine } TrafficGenerator::TrafficGenerator(DRAMSys::Config::TrafficGenerator const& config, - sc_core::sc_time interfaceClk, uint64_t memorySize, - unsigned int defaultDataLength, - MemoryManager& memoryManager, - std::function transactionFinished, - std::function terminateInitiator) : - generatorPeriod(sc_core::sc_time(1.0 / static_cast(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 defaultDataLength) : + generatorPeriod(sc_core::sc_time(1.0 / static_cast(config.clkMhz), sc_core::SC_US)) { unsigned int dataLength = config.dataLength.value_or(defaultDataLength); unsigned int dataAlignment = config.dataAlignment.value_or(dataLength); if (config.addressDistribution == DRAMSys::Config::AddressDistribution::Random) { - auto producer = std::make_unique(config.numRequests, - config.seed, + auto producer = std::make_unique(config.numRequests, + config.seed.value_or(0), config.rwRatio, config.minAddress, config.maxAddress, @@ -145,8 +119,8 @@ TrafficGenerator::TrafficGenerator(DRAMSys::Config::TrafficGenerator const& conf } else { - auto producer = std::make_unique(config.numRequests, - config.seed, + auto producer = std::make_unique(config.numRequests, + config.seed.value_or(0), config.rwRatio, config.addressIncrement, config.minAddress, @@ -159,7 +133,14 @@ TrafficGenerator::TrafficGenerator(DRAMSys::Config::TrafficGenerator const& conf 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()) { // Reset current producer to its initial state @@ -167,30 +148,24 @@ Request TrafficGenerator::nextRequest() auto newState = stateTransition(currentState); - if (!newState.has_value()) - return Request{Request::Command::Stop}; - - auto idleStateIt = idleStateClks.find(newState.value()); + auto idleStateIt = idleStateClks.find(newState); while (idleStateIt != idleStateClks.cend()) { - clksToIdle += idleStateIt->second; - newState = stateTransition(currentState); - - if (!newState.has_value()) - return Request{Request::Command::Stop}; - - currentState = newState.value(); - idleStateIt = idleStateClks.find(newState.value()); + ticksToIdle += idleStateIt->second; + newState = stateTransition(newState); + idleStateIt = idleStateClks.find(newState); } - currentState = newState.value(); + currentState = newState; 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(clksToIdle); return request; } @@ -208,9 +183,9 @@ uint64_t TrafficGenerator::totalRequests() if (producers.find(currentState) != producers.cend()) 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()) totalRequests += producers.at(currentState)->totalRequests(); @@ -222,7 +197,7 @@ uint64_t TrafficGenerator::totalRequests() return totalRequests; } -std::optional TrafficGenerator::stateTransition(unsigned int from) +unsigned int TrafficGenerator::stateTransition(unsigned int from) { using Transition = DRAMSys::Config::TrafficGeneratorStateTransition; @@ -233,7 +208,7 @@ std::optional TrafficGenerator::stateTransition(unsigned int from) [from](Transition transition) { return transition.from == from; }); if (relevantTransitions.empty()) - return std::nullopt; + return STOP_STATE; std::vector propabilities; std::for_each(relevantTransitions.cbegin(), diff --git a/src/simulator/simulator/generator/TrafficGenerator.h b/src/simulator/simulator/generator/TrafficGenerator.h index 335abc2d..466cb42c 100644 --- a/src/simulator/simulator/generator/TrafficGenerator.h +++ b/src/simulator/simulator/generator/TrafficGenerator.h @@ -35,52 +35,44 @@ #pragma once -#include "simulator/Initiator.h" -#include "simulator/MemoryManager.h" -#include "simulator/request/RequestIssuer.h" +#include "GeneratorState.h" +#include "simulator/request/RequestProducer.h" #include + #include class RequestProducer; -class TrafficGenerator : public Initiator +class TrafficGenerator : public RequestProducer { public: TrafficGenerator(DRAMSys::Config::TrafficGenerator const& config, - sc_core::sc_time interfaceClk, uint64_t memorySize, - unsigned int defaultDataLength, - MemoryManager& memoryManager, - std::function transactionFinished, - std::function terminateInitiator); + unsigned int defaultDataLength); TrafficGenerator(DRAMSys::Config::TrafficGeneratorStateMachine const& config, - sc_core::sc_time interfaceClk, uint64_t memorySize, - unsigned int defaultDataLength, - MemoryManager& memoryManager, - std::function transactionFinished, - std::function terminateInitiator); - - void bind(tlm_utils::multi_target_base<>& target) override { issuer.iSocket.bind(target); } + unsigned int defaultDataLength); uint64_t totalRequests() override; - Request nextRequest(); + Request nextRequest() override; + sc_core::sc_time nextTrigger() override { return nextTriggerTime; } - std::optional stateTransition(unsigned int from); + unsigned int stateTransition(unsigned int from); private: + static constexpr unsigned int STOP_STATE = UINT_MAX; + uint64_t requestsInState = 0; unsigned int currentState = 0; - const std::vector stateTransistions; + sc_core::sc_time nextTriggerTime = sc_core::SC_ZERO_TIME; + std::vector stateTransistions; - using IdleClks = uint64_t; - std::unordered_map idleStateClks; - const sc_core::sc_time generatorPeriod; + std::unordered_map idleStateClks; + sc_core::sc_time generatorPeriod; std::default_random_engine randomGenerator; - std::unordered_map> producers; - RequestIssuer issuer; + std::unordered_map> producers; }; diff --git a/src/simulator/simulator/generator/definitions.h b/src/simulator/simulator/generator/definitions.h deleted file mode 100644 index 30aff0f7..00000000 --- a/src/simulator/simulator/generator/definitions.h +++ /dev/null @@ -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 - -inline constexpr uint64_t DEFAULT_SEED = 0; -inline constexpr uint64_t DEFAULT_MIN_ADDRESS = 0; diff --git a/src/simulator/simulator/hammer/RowHammer.cpp b/src/simulator/simulator/hammer/RowHammer.cpp index 7da74d8a..d65a8fef 100644 --- a/src/simulator/simulator/hammer/RowHammer.cpp +++ b/src/simulator/simulator/hammer/RowHammer.cpp @@ -35,10 +35,11 @@ #include "RowHammer.h" -RowHammer::RowHammer(uint64_t numRequests, uint64_t rowIncrement, unsigned int dataLength) : - numberOfRequests(numRequests), - dataLength(dataLength), - rowIncrement(rowIncrement) +RowHammer::RowHammer(DRAMSys::Config::RowHammer const& config, unsigned int dataLength) : + generatorPeriod(sc_core::sc_time(1.0 / static_cast(config.clkMhz), sc_core::SC_US)), + numberOfRequests(config.numRequests), + rowIncrement(config.rowIncrement), + dataLength(dataLength) { } @@ -58,6 +59,5 @@ Request RowHammer::nextRequest() request.address = currentAddress; request.command = Request::Command::Read; request.length = dataLength; - request.delay = sc_core::SC_ZERO_TIME; return request; } diff --git a/src/simulator/simulator/hammer/RowHammer.h b/src/simulator/simulator/hammer/RowHammer.h index 82c6d547..1d75b6e9 100644 --- a/src/simulator/simulator/hammer/RowHammer.h +++ b/src/simulator/simulator/hammer/RowHammer.h @@ -37,19 +37,23 @@ #include "simulator/request/RequestProducer.h" +#include + #include class RowHammer : public RequestProducer { public: - RowHammer(uint64_t numRequests, uint64_t rowIncrement, unsigned int dataLength); + RowHammer(DRAMSys::Config::RowHammer const& config, unsigned int dataLength); Request nextRequest() override; + sc_core::sc_time nextTrigger() override { return generatorPeriod; } uint64_t totalRequests() override { return numberOfRequests; } - const uint64_t numberOfRequests; - const unsigned int dataLength; - const uint64_t rowIncrement; + sc_core::sc_time generatorPeriod; + uint64_t numberOfRequests; + uint64_t rowIncrement; + unsigned int dataLength; uint64_t generatedRequests = 0; uint64_t currentAddress = 0x00; diff --git a/src/simulator/simulator/player/StlPlayer.cpp b/src/simulator/simulator/player/StlPlayer.cpp index e82f61a8..c96cafa9 100644 --- a/src/simulator/simulator/player/StlPlayer.cpp +++ b/src/simulator/simulator/player/StlPlayer.cpp @@ -42,7 +42,9 @@ #include -StlPlayer::StlPlayer(std::string_view tracePath, +static constexpr std::size_t LINE_BUFFER_SIZE = 10000; + +StlPlayer::StlPlayer(std::filesystem::path const& trace, unsigned int clkMhz, unsigned int defaultDataLength, TraceType traceType, @@ -51,18 +53,11 @@ StlPlayer::StlPlayer(std::string_view tracePath, storageEnabled(storageEnabled), playerPeriod(sc_core::sc_time(1.0 / static_cast(clkMhz), sc_core::SC_US)), defaultDataLength(defaultDataLength), - traceFile(tracePath.data()), - lineBuffers( - {std::make_shared>(), std::make_shared>()}), - parseBuffer(lineBuffers.at(1)), - readoutBuffer(lineBuffers.at(0)) + traceFile(trace) { - readoutBuffer->reserve(LINE_BUFFER_SIZE); - parseBuffer->reserve(LINE_BUFFER_SIZE); - if (!traceFile.is_open()) 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; @@ -72,60 +67,99 @@ StlPlayer::StlPlayer(std::string_view tracePath, numberOfLines++; } 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.seekg(0); } 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::currentLine() const +{ + if (readoutIt == lineBuffers.at(consumeIndex).cend()) + return std::nullopt; + + return *readoutIt; } Request StlPlayer::nextRequest() { - if (readoutIt == readoutBuffer->cend()) - { - readoutIt = swapBuffers(); - if (readoutIt == readoutBuffer->cend()) - { - if (parserThread.joinable()) - parserThread.join(); + auto currentLineContent = currentLine(); - // The file is read in completely. Nothing more to do. - return Request{Request::Command::Stop}; + if (!currentLineContent.has_value()) + { + // 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; - 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; + return nextTrigger; } void StlPlayer::parseTraceFile() { unsigned parsedLines = 0; - parseBuffer->clear(); + auto& parseBuffer = lineBuffers.at(parseIndex); + parseBuffer.clear(); while (traceFile && !traceFile.eof() && parsedLines < LINE_BUFFER_SIZE) { // Get a new line from the input file. std::string line; std::getline(traceFile, line); - currentLine++; + currentParsedLine++; // If the line is empty (\n or \r\n) or starts with '#' (comment) the transaction is // ignored. @@ -133,8 +167,8 @@ void StlPlayer::parseTraceFile() continue; parsedLines++; - parseBuffer->emplace_back(); - Request& content = parseBuffer->back(); + parseBuffer.emplace_back(); + LineContent& content = parseBuffer.back(); // Trace files MUST provide timestamp, command and address for every // transaction. The data information depends on the storage mode @@ -148,90 +182,63 @@ void StlPlayer::parseTraceFile() { // 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(std::stoull(element)); + content.cycle = 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) == '(') { element.erase(0, 1); - content.length = std::stoul(element); + content.dataLength = 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; + content.command = LineContent::Command::Read; else if (element == "write") - content.command = Request::Command::Write; + content.command = LineContent::Command::Write; else - SC_REPORT_FATAL( - "StlPlayer", - ("Malformed trace file line " + std::to_string(currentLine) + ".").c_str()); + throw std::runtime_error("Unable to parse command"); // 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); + static constexpr unsigned HEX = 16; + content.address = std::stoull(element, nullptr, HEX); // 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. 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( - std::stoi(element.substr(i * 2 + 2, 2), nullptr, 16))); + // We need two characters to represent 1 byte in hexadecimal. + // Offset for 0x prefix. + for (std::size_t i = 2; i < element.length(); i += 2) + { + uint8_t byte = std::stoi(element.substr(i, 2), nullptr, HEX); + content.data.push_back(byte); + } } } catch (...) { SC_REPORT_FATAL( "StlPlayer", - ("Malformed trace file line " + std::to_string(currentLine) + ".").c_str()); + ("Malformed trace file line " + std::to_string(currentParsedLine) + ".").c_str()); } } } -std::vector::const_iterator StlPlayer::swapBuffers() +void StlPlayer::swapBuffers() { // Wait for parser to finish if (parserThread.joinable()) parserThread.join(); // Swap buffers - std::swap(readoutBuffer, parseBuffer); + std::swap(parseIndex, consumeIndex); // Start new parser thread parserThread = std::thread(&StlPlayer::parseTraceFile, this); - - return readoutBuffer->cbegin(); } diff --git a/src/simulator/simulator/player/StlPlayer.h b/src/simulator/simulator/player/StlPlayer.h index 76d2586f..28d887e1 100644 --- a/src/simulator/simulator/player/StlPlayer.h +++ b/src/simulator/simulator/player/StlPlayer.h @@ -40,57 +40,71 @@ #pragma once -#include "simulator/request/Request.h" #include "simulator/request/RequestProducer.h" #include #include #include +#include #include -#include +#include #include #include class StlPlayer : public RequestProducer { public: - enum class TraceType + enum class TraceType : uint8_t { Absolute, Relative, }; - StlPlayer(std::string_view tracePath, + StlPlayer(std::filesystem::path const& trace, unsigned int clkMhz, unsigned int defaultDataLength, TraceType traceType, bool storageEnabled); Request nextRequest() override; - + sc_core::sc_time nextTrigger() override; uint64_t totalRequests() override { return numberOfLines; } private: + struct LineContent + { + unsigned cycle{}; + enum class Command : uint8_t + { + Read, + Write + } command{}; + uint64_t address{}; + std::optional dataLength; + std::vector data; + }; + + std::optional currentLine() const; + void parseTraceFile(); - std::vector::const_iterator swapBuffers(); + void swapBuffers(); + void incrementLine(); - static constexpr std::size_t LINE_BUFFER_SIZE = 10000; - - const TraceType traceType; - const bool storageEnabled; - const sc_core::sc_time playerPeriod; - const unsigned int defaultDataLength; + TraceType traceType; + bool storageEnabled; + sc_core::sc_time playerPeriod; + unsigned int defaultDataLength; std::ifstream traceFile; - uint64_t currentLine = 0; + uint64_t currentParsedLine = 0; uint64_t numberOfLines = 0; - std::array>, 2> lineBuffers; - std::shared_ptr> parseBuffer; - std::shared_ptr> readoutBuffer; + std::array, 2> lineBuffers; + std::size_t parseIndex = 0; + std::size_t consumeIndex = 1; - std::vector::const_iterator readoutIt; + std::vector::const_iterator readoutIt; std::thread parserThread; }; diff --git a/src/simulator/simulator/request/Request.h b/src/simulator/simulator/request/Request.h index 61eccb0f..2f4718ee 100644 --- a/src/simulator/simulator/request/Request.h +++ b/src/simulator/simulator/request/Request.h @@ -36,18 +36,17 @@ #pragma once #include -#include +#include struct Request { - enum class Command + enum class Command : uint8_t { Read, Write, Stop } command; - uint64_t address{}; - std::size_t length{}; - sc_core::sc_time delay{}; - std::vector data{}; + uint64_t address = 0; + std::size_t length = 0; + std::vector data; }; diff --git a/src/simulator/simulator/request/RequestIssuer.cpp b/src/simulator/simulator/request/RequestIssuer.cpp index ca13580e..553d442d 100644 --- a/src/simulator/simulator/request/RequestIssuer.cpp +++ b/src/simulator/simulator/request/RequestIssuer.cpp @@ -36,22 +36,22 @@ #include "RequestIssuer.h" RequestIssuer::RequestIssuer(sc_core::sc_module_name const& name, + std::unique_ptr producer, MemoryManager& memoryManager, sc_core::sc_time interfaceClk, std::optional maxPendingReadRequests, std::optional maxPendingWriteRequests, - std::function nextRequest, std::function transactionFinished, std::function terminate) : sc_module(name), + producer(std::move(producer)), payloadEventQueue(this, &RequestIssuer::peqCallback), memoryManager(memoryManager), interfaceClk(interfaceClk), maxPendingReadRequests(maxPendingReadRequests), maxPendingWriteRequests(maxPendingWriteRequests), transactionFinished(std::move(transactionFinished)), - terminate(std::move(terminate)), - nextRequest(std::move(nextRequest)) + terminate(std::move(terminate)) { SC_THREAD(sendNextRequest); 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() { - Request request = nextRequest(); - - if (request.command == Request::Command::Stop) + while (true) { - finished = true; - return; + Request request = producer->nextRequest(); + + 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 @@ -121,37 +128,31 @@ void RequestIssuer::peqCallback(tlm::tlm_generic_payload& payload, const tlm::tl { if (phase == tlm::END_REQ) { + requestInProgress = false; + endReq.notify(sc_core::SC_ZERO_TIME); + lastEndRequest = sc_core::sc_time_stamp(); - if (nextRequestSendable()) - sendNextRequest(); - else + if (!nextRequestSendable()) transactionPostponed = true; } 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++; + transactionFinished(); if (payload.get_command() == tlm::TLM_READ_COMMAND) pendingReadRequests--; else if (payload.get_command() == tlm::TLM_WRITE_COMMAND) pendingWriteRequests--; - // If the initiator wasn't able to send the next payload in the END_REQ phase, do it - // now. - if (transactionPostponed && nextRequestSendable()) - { - sendNextRequest(); - transactionPostponed = false; - } + beginResp.notify(sc_core::SC_ZERO_TIME); + + // Send END_RESP + tlm::tlm_phase nextPhase = tlm::END_RESP; + sc_core::sc_time delay = interfaceClk; + iSocket->nb_transport_fw(payload, nextPhase, delay); + payload.release(); // If all answers were received: if (finished && transactionsSent == transactionsReceived) diff --git a/src/simulator/simulator/request/RequestIssuer.h b/src/simulator/simulator/request/RequestIssuer.h index 1c86b70d..33fa7c63 100644 --- a/src/simulator/simulator/request/RequestIssuer.h +++ b/src/simulator/simulator/request/RequestIssuer.h @@ -36,8 +36,10 @@ #pragma once #include "Request.h" +#include "RequestProducer.h" #include "simulator/MemoryManager.h" +#include #include #include #include @@ -51,21 +53,43 @@ public: tlm_utils::simple_initiator_socket iSocket; RequestIssuer(sc_core::sc_module_name const& name, + std::unique_ptr producer, MemoryManager& memoryManager, sc_core::sc_time interfaceClk, std::optional maxPendingReadRequests, std::optional maxPendingWriteRequests, - std::function nextRequest, std::function transactionFinished, std::function terminate); SC_HAS_PROCESS(RequestIssuer); + uint64_t totalRequests() { return producer->totalRequests(); }; + 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 producer; + tlm_utils::peq_with_cb_and_phase payloadEventQueue; MemoryManager& memoryManager; sc_core::sc_time interfaceClk; + bool requestInProgress = false; bool transactionPostponed = false; bool finished = false; @@ -80,18 +104,4 @@ private: std::function transactionFinished; std::function terminate; - std::function 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); }; diff --git a/src/simulator/simulator/request/RequestProducer.h b/src/simulator/simulator/request/RequestProducer.h index ad4a01bb..cbda5fa3 100644 --- a/src/simulator/simulator/request/RequestProducer.h +++ b/src/simulator/simulator/request/RequestProducer.h @@ -37,6 +37,8 @@ #include "Request.h" +#include + class RequestProducer { protected: @@ -50,6 +52,7 @@ public: virtual ~RequestProducer() = default; virtual Request nextRequest() = 0; + virtual sc_core::sc_time nextTrigger() = 0; virtual uint64_t totalRequests() = 0; - virtual void reset(){}; + virtual void reset() {}; }; diff --git a/tests/tests_regression/DDR3/expected/DRAMSys_ddr3-dual-rank_ddr3_ch0.tdb b/tests/tests_regression/DDR3/expected/DRAMSys_ddr3-dual-rank_ddr3_ch0.tdb index 2002c1c2..0f26fab4 100644 --- a/tests/tests_regression/DDR3/expected/DRAMSys_ddr3-dual-rank_ddr3_ch0.tdb +++ b/tests/tests_regression/DDR3/expected/DRAMSys_ddr3-dual-rank_ddr3_ch0.tdb @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:42e35a7b37068126ad611610231d0ed8b665bc8a442b20b6a94d93fd2dec94e4 -size 139264 +oid sha256:c9d3def51c6e79b7cf767a7deec65c066cb2d43205237ca5fc4084667bbdecfc +size 147456 diff --git a/tests/tests_regression/HBM2/expected/DRAMSys_hbm2-example_hbm2_ch0.tdb b/tests/tests_regression/HBM2/expected/DRAMSys_hbm2-example_hbm2_ch0.tdb index 72b1a455..d84e76e1 100644 --- a/tests/tests_regression/HBM2/expected/DRAMSys_hbm2-example_hbm2_ch0.tdb +++ b/tests/tests_regression/HBM2/expected/DRAMSys_hbm2-example_hbm2_ch0.tdb @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:4e1a66644ba415a3821042624586f6ad20a44d6e0c2f999dc6a882d8aa4eda5c +oid sha256:8aeec8ba320fd0568fdee24a3731cf415d840ae28ae716ab9b84465e74aa5815 size 692224 diff --git a/tests/tests_regression/HBM3/expected/DRAMSys_hbm3-example_hbm3_ch0.tdb b/tests/tests_regression/HBM3/expected/DRAMSys_hbm3-example_hbm3_ch0.tdb index 379cce48..f06ca3ca 100644 --- a/tests/tests_regression/HBM3/expected/DRAMSys_hbm3-example_hbm3_ch0.tdb +++ b/tests/tests_regression/HBM3/expected/DRAMSys_hbm3-example_hbm3_ch0.tdb @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:caa32221ae565b3c7d3d61025dadb0a28c7644a323f2b2ad278eac49cf92e528 -size 1376256 +oid sha256:4affa5da1a02f965c781fd3dd4635f58abab006836b61fd20336e287c83b3bfe +size 1413120 From caba02396484251a5d70841fceaedfb6001f111b Mon Sep 17 00:00:00 2001 From: Derek Christ Date: Tue, 6 May 2025 09:28:00 +0200 Subject: [PATCH 2/4] Update the simulator readme --- src/simulator/README.md | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/src/simulator/README.md b/src/simulator/README.md index e2ffe592..267fd43b 100644 --- a/src/simulator/README.md +++ b/src/simulator/README.md @@ -2,18 +2,13 @@ The **standalone** simulator features a set of trace players, traffic generators and miscellaneous components that can be coupled with DRAMSys. ## 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. -**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` 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. +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. **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 A detailed description on how to configure the traffic generators of the simulator can be found [here](../../configs/README.md). From 565e725cf6dbb0a651551a15de71b9abc1ff9405 Mon Sep 17 00:00:00 2001 From: Derek Christ Date: Wed, 7 May 2025 09:13:00 +0200 Subject: [PATCH 3/4] Make dataLength parameter required for initiators --- configs/ddr3-example.json | 1 + configs/ddr4-example.json | 1 + configs/ddr4-full-example.json | 1 + configs/hbm2-example.json | 1 + configs/lpddr4-example.json | 1 + configs/stt-mram-example.json | 1 + extensions/configs/ddr5-example.json | 1 + .../configs/ddr5-generator-example.json | 2 + extensions/configs/hbm3-example.json | 1 + extensions/configs/lpddr5-example.json | 1 + src/configuration/DRAMSys/config/TraceSetup.h | 11 ++-- src/simulator/simulator/Simulator.cpp | 13 ++-- .../simulator/generator/TrafficGenerator.cpp | 66 +++++++++---------- .../simulator/generator/TrafficGenerator.h | 7 +- src/simulator/simulator/hammer/RowHammer.cpp | 4 +- src/simulator/simulator/hammer/RowHammer.h | 2 +- src/simulator/simulator/player/StlPlayer.cpp | 9 ++- src/simulator/simulator/player/StlPlayer.h | 7 +- tests/tests_configuration/reference.json | 4 ++ .../test_configuration.cpp | 8 +++ tests/tests_regression/DDR3/ddr3-example.json | 1 + tests/tests_regression/DDR4/ddr4-example.json | 1 + tests/tests_regression/DDR5/ddr5-example.json | 1 + tests/tests_regression/HBM2/hbm2-example.json | 2 + tests/tests_regression/HBM3/hbm3-example.json | 2 + .../LPDDR4/lpddr4-example.json | 1 + .../LPDDR5/lpddr5-example.json | 1 + 27 files changed, 88 insertions(+), 63 deletions(-) diff --git a/configs/ddr3-example.json b/configs/ddr3-example.json index 8be3a4f4..0a265f58 100644 --- a/configs/ddr3-example.json +++ b/configs/ddr3-example.json @@ -9,6 +9,7 @@ { "type": "player", "clkMhz": 800, + "dataLength": 64, "name": "traces/example.stl" } ] diff --git a/configs/ddr4-example.json b/configs/ddr4-example.json index 989a1f3f..998d7f1c 100644 --- a/configs/ddr4-example.json +++ b/configs/ddr4-example.json @@ -9,6 +9,7 @@ { "type": "player", "clkMhz": 200, + "dataLength": 64, "name": "traces/example.stl" } ] diff --git a/configs/ddr4-full-example.json b/configs/ddr4-full-example.json index 45722879..08ad90f6 100644 --- a/configs/ddr4-full-example.json +++ b/configs/ddr4-full-example.json @@ -212,6 +212,7 @@ { "type": "player", "clkMhz": 200, + "dataLength": 64, "name": "traces/example.stl" } ] diff --git a/configs/hbm2-example.json b/configs/hbm2-example.json index b59ffc15..085b7b57 100644 --- a/configs/hbm2-example.json +++ b/configs/hbm2-example.json @@ -9,6 +9,7 @@ { "type": "player", "clkMhz": 1000, + "dataLength": 32, "name": "traces/example.stl" } ] diff --git a/configs/lpddr4-example.json b/configs/lpddr4-example.json index 7b1f8996..5408ecaf 100644 --- a/configs/lpddr4-example.json +++ b/configs/lpddr4-example.json @@ -9,6 +9,7 @@ { "type": "player", "clkMhz": 200, + "dataLength": 32, "name": "traces/example.stl" } ] diff --git a/configs/stt-mram-example.json b/configs/stt-mram-example.json index 8ecf6da2..6537c1ee 100644 --- a/configs/stt-mram-example.json +++ b/configs/stt-mram-example.json @@ -9,6 +9,7 @@ { "type": "player", "clkMhz": 800, + "dataLength": 64, "name": "traces/example.stl" } ] diff --git a/extensions/configs/ddr5-example.json b/extensions/configs/ddr5-example.json index e73395c1..7cbf1a8f 100644 --- a/extensions/configs/ddr5-example.json +++ b/extensions/configs/ddr5-example.json @@ -9,6 +9,7 @@ { "type": "player", "clkMhz": 2000, + "dataLength": 64, "name": "../../configs/traces/example.stl" } ] diff --git a/extensions/configs/ddr5-generator-example.json b/extensions/configs/ddr5-generator-example.json index 1fcfbc3f..874b8e95 100644 --- a/extensions/configs/ddr5-generator-example.json +++ b/extensions/configs/ddr5-generator-example.json @@ -8,6 +8,7 @@ "tracesetup": [ { "clkMhz": 2000, + "dataLength": 64, "type": "generator", "name": "gen0", "numRequests": 2000, @@ -19,6 +20,7 @@ }, { "clkMhz": 2000, + "dataLength": 64, "type": "generator", "name": "gen1", "numRequests": 2000, diff --git a/extensions/configs/hbm3-example.json b/extensions/configs/hbm3-example.json index 7d30ae27..3aae6e96 100644 --- a/extensions/configs/hbm3-example.json +++ b/extensions/configs/hbm3-example.json @@ -8,6 +8,7 @@ "tracesetup": [ { "clkMhz": 2000, + "dataLength": 32, "type": "generator", "name": "gen0", "numRequests": 2000, diff --git a/extensions/configs/lpddr5-example.json b/extensions/configs/lpddr5-example.json index 41878a8f..7f498bd9 100644 --- a/extensions/configs/lpddr5-example.json +++ b/extensions/configs/lpddr5-example.json @@ -9,6 +9,7 @@ { "type": "player", "clkMhz": 200, + "dataLength": 32, "name": "../../configs/traces/example.stl" } ] diff --git a/src/configuration/DRAMSys/config/TraceSetup.h b/src/configuration/DRAMSys/config/TraceSetup.h index 0de42183..c6a809ed 100644 --- a/src/configuration/DRAMSys/config/TraceSetup.h +++ b/src/configuration/DRAMSys/config/TraceSetup.h @@ -79,12 +79,13 @@ struct TracePlayer uint64_t clkMhz{}; std::string name; + unsigned dataLength; std::optional maxPendingReadRequests; std::optional maxPendingWriteRequests; }; NLOHMANN_JSONIFY_ALL_THINGS( - TracePlayer, clkMhz, name, maxPendingReadRequests, maxPendingWriteRequests) + TracePlayer, clkMhz, name, dataLength, maxPendingReadRequests, maxPendingWriteRequests) struct TrafficGeneratorActiveState { @@ -136,7 +137,7 @@ struct TrafficGenerator std::optional seed; std::optional maxTransactions; - std::optional dataLength; + unsigned dataLength; std::optional dataAlignment; uint64_t numRequests{}; @@ -174,7 +175,7 @@ struct TrafficGeneratorStateMachine std::optional seed; std::optional maxTransactions; - std::optional dataLength; + unsigned dataLength; std::optional dataAlignment; std::vector> states; std::vector transitions; @@ -200,7 +201,8 @@ struct RowHammer std::string name; std::optional maxPendingReadRequests; std::optional maxPendingWriteRequests; - + + unsigned dataLength; uint64_t numRequests{}; uint64_t rowIncrement{}; }; @@ -210,6 +212,7 @@ NLOHMANN_JSONIFY_ALL_THINGS(RowHammer, name, maxPendingReadRequests, maxPendingWriteRequests, + dataLength, numRequests, rowIncrement) diff --git a/src/simulator/simulator/Simulator.cpp b/src/simulator/simulator/Simulator.cpp index 86dc0b7d..369548b0 100644 --- a/src/simulator/simulator/Simulator.cpp +++ b/src/simulator/simulator/Simulator.cpp @@ -85,7 +85,6 @@ Simulator::instantiateInitiator(const DRAMSys::Config::Initiator& initiator) { uint64_t memorySize = dramSys->getMemSpec().getSimMemSizeInBytes(); sc_core::sc_time interfaceClk = dramSys->getMemSpec().tCK; - unsigned int defaultDataLength = dramSys->getMemSpec().defaultBytesPerBurst; return std::visit( [=](auto&& config) -> std::unique_ptr @@ -94,8 +93,7 @@ Simulator::instantiateInitiator(const DRAMSys::Config::Initiator& initiator) if constexpr (std::is_same_v || std::is_same_v) { - auto generator = - std::make_unique(config, memorySize, defaultDataLength); + auto generator = std::make_unique(config, memorySize); return std::make_unique(config.name.c_str(), std::move(generator), @@ -124,11 +122,8 @@ Simulator::instantiateInitiator(const DRAMSys::Config::Initiator& initiator) SC_REPORT_FATAL("Simulator", report.c_str()); } - auto player = std::make_unique(tracePath.c_str(), - config.clkMhz, - defaultDataLength, - *traceType, - storageEnabled); + auto player = std::make_unique( + config, tracePath.c_str(), *traceType, storageEnabled); return std::make_unique(config.name.c_str(), std::move(player), @@ -141,7 +136,7 @@ Simulator::instantiateInitiator(const DRAMSys::Config::Initiator& initiator) } else if constexpr (std::is_same_v) { - auto hammer = std::make_unique(config, defaultDataLength); + auto hammer = std::make_unique(config); return std::make_unique(config.name.c_str(), std::move(hammer), diff --git a/src/simulator/simulator/generator/TrafficGenerator.cpp b/src/simulator/simulator/generator/TrafficGenerator.cpp index 92f33a7d..dc36c37c 100644 --- a/src/simulator/simulator/generator/TrafficGenerator.cpp +++ b/src/simulator/simulator/generator/TrafficGenerator.cpp @@ -39,12 +39,11 @@ #include "SequentialState.h" TrafficGenerator::TrafficGenerator(DRAMSys::Config::TrafficGeneratorStateMachine const& config, - uint64_t memorySize, - unsigned int defaultDataLength) : + uint64_t memorySize) : stateTransistions(config.transitions), generatorPeriod(sc_core::sc_time(1.0 / static_cast(config.clkMhz), sc_core::SC_US)) { - unsigned int dataLength = config.dataLength.value_or(defaultDataLength); + unsigned int dataLength = config.dataLength; unsigned int dataAlignment = config.dataAlignment.value_or(dataLength); for (auto const& state : config.states) @@ -62,13 +61,13 @@ TrafficGenerator::TrafficGenerator(DRAMSys::Config::TrafficGeneratorStateMachine DRAMSys::Config::AddressDistribution::Random) { auto producer = std::make_unique(activeState.numRequests, - config.seed.value_or(0), - activeState.rwRatio, - activeState.minAddress, - activeState.maxAddress, - memorySize, - dataLength, - dataAlignment); + config.seed.value_or(0), + activeState.rwRatio, + activeState.minAddress, + activeState.maxAddress, + memorySize, + dataLength, + dataAlignment); producers.emplace(activeState.id, std::move(producer)); } @@ -76,13 +75,13 @@ TrafficGenerator::TrafficGenerator(DRAMSys::Config::TrafficGeneratorStateMachine { auto producer = std::make_unique(activeState.numRequests, - config.seed.value_or(0), - activeState.rwRatio, - activeState.addressIncrement, - activeState.minAddress, - activeState.maxAddress, - memorySize, - dataLength); + config.seed.value_or(0), + activeState.rwRatio, + activeState.addressIncrement, + activeState.minAddress, + activeState.maxAddress, + memorySize, + dataLength); producers.emplace(activeState.id, std::move(producer)); } @@ -98,35 +97,34 @@ TrafficGenerator::TrafficGenerator(DRAMSys::Config::TrafficGeneratorStateMachine } TrafficGenerator::TrafficGenerator(DRAMSys::Config::TrafficGenerator const& config, - uint64_t memorySize, - unsigned int defaultDataLength) : + uint64_t memorySize) : generatorPeriod(sc_core::sc_time(1.0 / static_cast(config.clkMhz), sc_core::SC_US)) { - unsigned int dataLength = config.dataLength.value_or(defaultDataLength); + unsigned int dataLength = config.dataLength; unsigned int dataAlignment = config.dataAlignment.value_or(dataLength); if (config.addressDistribution == DRAMSys::Config::AddressDistribution::Random) { auto producer = std::make_unique(config.numRequests, - config.seed.value_or(0), - config.rwRatio, - config.minAddress, - config.maxAddress, - memorySize, - dataLength, - dataAlignment); + config.seed.value_or(0), + config.rwRatio, + config.minAddress, + config.maxAddress, + memorySize, + dataLength, + dataAlignment); producers.emplace(0, std::move(producer)); } else { auto producer = std::make_unique(config.numRequests, - config.seed.value_or(0), - config.rwRatio, - config.addressIncrement, - config.minAddress, - config.maxAddress, - memorySize, - dataLength); + config.seed.value_or(0), + config.rwRatio, + config.addressIncrement, + config.minAddress, + config.maxAddress, + memorySize, + dataLength); producers.emplace(0, std::move(producer)); } } diff --git a/src/simulator/simulator/generator/TrafficGenerator.h b/src/simulator/simulator/generator/TrafficGenerator.h index 466cb42c..5a6602b3 100644 --- a/src/simulator/simulator/generator/TrafficGenerator.h +++ b/src/simulator/simulator/generator/TrafficGenerator.h @@ -47,13 +47,10 @@ class RequestProducer; class TrafficGenerator : public RequestProducer { public: - TrafficGenerator(DRAMSys::Config::TrafficGenerator const& config, - uint64_t memorySize, - unsigned int defaultDataLength); + TrafficGenerator(DRAMSys::Config::TrafficGenerator const& config, uint64_t memorySize); TrafficGenerator(DRAMSys::Config::TrafficGeneratorStateMachine const& config, - uint64_t memorySize, - unsigned int defaultDataLength); + uint64_t memorySize); uint64_t totalRequests() override; Request nextRequest() override; diff --git a/src/simulator/simulator/hammer/RowHammer.cpp b/src/simulator/simulator/hammer/RowHammer.cpp index d65a8fef..4dbf9825 100644 --- a/src/simulator/simulator/hammer/RowHammer.cpp +++ b/src/simulator/simulator/hammer/RowHammer.cpp @@ -35,11 +35,11 @@ #include "RowHammer.h" -RowHammer::RowHammer(DRAMSys::Config::RowHammer const& config, unsigned int dataLength) : +RowHammer::RowHammer(DRAMSys::Config::RowHammer const& config) : generatorPeriod(sc_core::sc_time(1.0 / static_cast(config.clkMhz), sc_core::SC_US)), numberOfRequests(config.numRequests), rowIncrement(config.rowIncrement), - dataLength(dataLength) + dataLength(config.dataLength) { } diff --git a/src/simulator/simulator/hammer/RowHammer.h b/src/simulator/simulator/hammer/RowHammer.h index 1d75b6e9..2c83b797 100644 --- a/src/simulator/simulator/hammer/RowHammer.h +++ b/src/simulator/simulator/hammer/RowHammer.h @@ -44,7 +44,7 @@ class RowHammer : public RequestProducer { public: - RowHammer(DRAMSys::Config::RowHammer const& config, unsigned int dataLength); + RowHammer(DRAMSys::Config::RowHammer const& config); Request nextRequest() override; sc_core::sc_time nextTrigger() override { return generatorPeriod; } diff --git a/src/simulator/simulator/player/StlPlayer.cpp b/src/simulator/simulator/player/StlPlayer.cpp index c96cafa9..e823d6d6 100644 --- a/src/simulator/simulator/player/StlPlayer.cpp +++ b/src/simulator/simulator/player/StlPlayer.cpp @@ -44,15 +44,14 @@ static constexpr std::size_t LINE_BUFFER_SIZE = 10000; -StlPlayer::StlPlayer(std::filesystem::path const& trace, - unsigned int clkMhz, - unsigned int defaultDataLength, +StlPlayer::StlPlayer(DRAMSys::Config::TracePlayer const& config, + std::filesystem::path const& trace, TraceType traceType, bool storageEnabled) : traceType(traceType), storageEnabled(storageEnabled), - playerPeriod(sc_core::sc_time(1.0 / static_cast(clkMhz), sc_core::SC_US)), - defaultDataLength(defaultDataLength), + playerPeriod(sc_core::sc_time(1.0 / static_cast(config.clkMhz), sc_core::SC_US)), + defaultDataLength(config.dataLength), traceFile(trace) { if (!traceFile.is_open()) diff --git a/src/simulator/simulator/player/StlPlayer.h b/src/simulator/simulator/player/StlPlayer.h index 28d887e1..53f567fd 100644 --- a/src/simulator/simulator/player/StlPlayer.h +++ b/src/simulator/simulator/player/StlPlayer.h @@ -42,6 +42,8 @@ #include "simulator/request/RequestProducer.h" +#include + #include #include @@ -61,9 +63,8 @@ public: Relative, }; - StlPlayer(std::filesystem::path const& trace, - unsigned int clkMhz, - unsigned int defaultDataLength, + StlPlayer(DRAMSys::Config::TracePlayer const& config, + std::filesystem::path const& trace, TraceType traceType, bool storageEnabled); diff --git a/tests/tests_configuration/reference.json b/tests/tests_configuration/reference.json index b61019a6..90b80bb9 100644 --- a/tests/tests_configuration/reference.json +++ b/tests/tests_configuration/reference.json @@ -215,6 +215,7 @@ { "type": "player", "clkMhz": 100, + "dataLength": 64, "name": "mytrace.stl" }, { @@ -222,12 +223,14 @@ "addressDistribution": "random", "clkMhz": 100, "name": "MyTestGen", + "dataLength": 64, "numRequests": 1000, "rwRatio": 0.5 }, { "type": "statemachine", "clkMhz": 100, + "dataLength": 64, "maxPendingReadRequests": 8, "name": "MyTestGen", "states": [ @@ -260,6 +263,7 @@ { "type": "rowhammer", "clkMhz": 100, + "dataLength": 64, "name": "MyTestHammer", "numRequests": 4000, "rowIncrement": 2097152 diff --git a/tests/tests_configuration/test_configuration.cpp b/tests/tests_configuration/test_configuration.cpp index 2d8d138e..959267ef 100644 --- a/tests/tests_configuration/test_configuration.cpp +++ b/tests/tests_configuration/test_configuration.cpp @@ -318,6 +318,7 @@ DRAMSys::Config::TracePlayer ConfigurationTest::createTracePlayer() { DRAMSys::Config::TracePlayer player; player.clkMhz = 100; + player.dataLength = 64; player.name = "mytrace.stl"; return player; @@ -327,6 +328,7 @@ DRAMSys::Config::TrafficGenerator ConfigurationTest::createTraceGeneratorOneStat { DRAMSys::Config::TrafficGenerator gen; gen.clkMhz = 100; + gen.dataLength = 64; gen.name = "MyTestGen"; gen.numRequests = 1000; @@ -345,6 +347,7 @@ ConfigurationTest::createTraceGeneratorMultipleStates() DRAMSys::Config::TrafficGeneratorStateMachine gen; gen.clkMhz = 100; + gen.dataLength = 64; gen.name = "MyTestGen"; gen.maxPendingReadRequests = 8; @@ -381,6 +384,7 @@ DRAMSys::Config::RowHammer ConfigurationTest::createTraceHammer() DRAMSys::Config::RowHammer hammer; hammer.clkMhz = 100; + hammer.dataLength = 64; hammer.name = "MyTestHammer"; hammer.numRequests = 4000; hammer.rowIncrement = 2097152; @@ -720,12 +724,14 @@ TEST_F(ConfigurationTest, TraceSetup) { "type": "player", "clkMhz": 100, + "dataLength": 64, "name": "mytrace.stl" }, { "type": "generator", "addressDistribution": "random", "clkMhz": 100, + "dataLength": 64, "name": "MyTestGen", "numRequests": 1000, "rwRatio": 0.5 @@ -733,6 +739,7 @@ TEST_F(ConfigurationTest, TraceSetup) { "type": "statemachine", "clkMhz": 100, + "dataLength": 64, "maxPendingReadRequests": 8, "name": "MyTestGen", "states": [ @@ -765,6 +772,7 @@ TEST_F(ConfigurationTest, TraceSetup) { "type": "rowhammer", "clkMhz": 100, + "dataLength": 64, "name": "MyTestHammer", "numRequests": 4000, "rowIncrement": 2097152 diff --git a/tests/tests_regression/DDR3/ddr3-example.json b/tests/tests_regression/DDR3/ddr3-example.json index 0d201661..fead0578 100644 --- a/tests/tests_regression/DDR3/ddr3-example.json +++ b/tests/tests_regression/DDR3/ddr3-example.json @@ -137,6 +137,7 @@ { "type": "player", "clkMhz": 533, + "dataLength": 64, "name": "traces/trace_test2.stl" } ] diff --git a/tests/tests_regression/DDR4/ddr4-example.json b/tests/tests_regression/DDR4/ddr4-example.json index fd26fc30..88f82348 100644 --- a/tests/tests_regression/DDR4/ddr4-example.json +++ b/tests/tests_regression/DDR4/ddr4-example.json @@ -213,6 +213,7 @@ { "type": "player", "clkMhz": 933, + "dataLength": 64, "name": "traces/trace_test3.stl" } ] diff --git a/tests/tests_regression/DDR5/ddr5-example.json b/tests/tests_regression/DDR5/ddr5-example.json index 49e91043..0a6d353a 100644 --- a/tests/tests_regression/DDR5/ddr5-example.json +++ b/tests/tests_regression/DDR5/ddr5-example.json @@ -220,6 +220,7 @@ { "type": "player", "clkMhz": 1600, + "dataLength": 64, "name": "traces/trace_test3.stl" } ] diff --git a/tests/tests_regression/HBM2/hbm2-example.json b/tests/tests_regression/HBM2/hbm2-example.json index f0494361..9a548aab 100644 --- a/tests/tests_regression/HBM2/hbm2-example.json +++ b/tests/tests_regression/HBM2/hbm2-example.json @@ -128,11 +128,13 @@ { "type": "player", "clkMhz": 1000, + "dataLength": 64, "name": "traces/trace1_test4.stl" }, { "type": "player", "clkMhz": 1000, + "dataLength": 64, "name": "traces/trace2_test4.stl" } ] diff --git a/tests/tests_regression/HBM3/hbm3-example.json b/tests/tests_regression/HBM3/hbm3-example.json index 238bb66e..b7e0f8e1 100644 --- a/tests/tests_regression/HBM3/hbm3-example.json +++ b/tests/tests_regression/HBM3/hbm3-example.json @@ -131,11 +131,13 @@ { "type": "player", "clkMhz": 1600, + "dataLength": 32, "name": "traces/trace1_test4.stl" }, { "type": "player", "clkMhz": 1600, + "dataLength": 32, "name": "traces/trace2_test4.stl" } ] diff --git a/tests/tests_regression/LPDDR4/lpddr4-example.json b/tests/tests_regression/LPDDR4/lpddr4-example.json index f44abaee..500908b7 100644 --- a/tests/tests_regression/LPDDR4/lpddr4-example.json +++ b/tests/tests_regression/LPDDR4/lpddr4-example.json @@ -183,6 +183,7 @@ { "type": "player", "clkMhz": 1600, + "dataLength": 32, "name": "traces/trace_lpddr4.stl" } ] diff --git a/tests/tests_regression/LPDDR5/lpddr5-example.json b/tests/tests_regression/LPDDR5/lpddr5-example.json index 53da1716..348426d6 100644 --- a/tests/tests_regression/LPDDR5/lpddr5-example.json +++ b/tests/tests_regression/LPDDR5/lpddr5-example.json @@ -205,6 +205,7 @@ { "type": "player", "clkMhz": 1600, + "dataLength": 32, "name": "traces/trace_lpddr5.stl" } ] From 11049f6a265cbad215cb03104b8627c795f5b308 Mon Sep 17 00:00:00 2001 From: Derek Christ Date: Wed, 21 May 2025 17:18:32 +0200 Subject: [PATCH 4/4] Fix StlPlayer crash at end --- src/simulator/simulator/player/StlPlayer.h | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/simulator/simulator/player/StlPlayer.h b/src/simulator/simulator/player/StlPlayer.h index 53f567fd..369d1226 100644 --- a/src/simulator/simulator/player/StlPlayer.h +++ b/src/simulator/simulator/player/StlPlayer.h @@ -68,6 +68,12 @@ public: TraceType traceType, bool storageEnabled); + //TODO temporary fix + ~StlPlayer() { + if (parserThread.joinable()) + parserThread.join(); + } + Request nextRequest() override; sc_core::sc_time nextTrigger() override; uint64_t totalRequests() override { return numberOfLines; }