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