Introduce demonstrator for new simulator concept

This commit is contained in:
2023-01-02 12:35:34 +01:00
parent d27a29ca80
commit 2d0445d5a7
31 changed files with 1701 additions and 1409 deletions

View File

@@ -77,7 +77,7 @@ endif()
set(DRAMSYS_SOURCE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/src")
set(DRAMSYS_LIBRARY_DIR "${CMAKE_CURRENT_SOURCE_DIR}/lib")
set(DRAMSYS_TESTS_DIR "${CMAKE_CURRENT_SOURCE_DIR}/tests")
set(DRAMSYS_RESOURCE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/resources")
set(DRAMSYS_RESOURCE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/configs")
set(DRAMSYS_EXTENSIONS_DIR "${CMAKE_CURRENT_SOURCE_DIR}/extensions")
### Build options ###
@@ -137,6 +137,7 @@ FetchContent_Declare(
GIT_REPOSITORY https://github.com/accellera-official/systemc.git
GIT_TAG 2.3.4)
set(DISABLE_COPYRIGHT_MESSAGE True)
FetchContent_MakeAvailable(systemc)
set_target_properties(systemc PROPERTIES FOLDER lib)

View File

@@ -89,8 +89,6 @@ struct TrafficGeneratorActiveState
std::optional<uint64_t> addressIncrement;
std::optional<uint64_t> minAddress;
std::optional<uint64_t> maxAddress;
std::optional<uint64_t> clksPerRequest;
std::optional<std::string> notify;
};
NLOHMANN_JSONIFY_ALL_THINGS(TrafficGeneratorActiveState,
@@ -100,9 +98,7 @@ NLOHMANN_JSONIFY_ALL_THINGS(TrafficGeneratorActiveState,
addressDistribution,
addressIncrement,
minAddress,
maxAddress,
clksPerRequest,
notify)
maxAddress)
struct TrafficGeneratorIdleState
{
@@ -139,9 +135,6 @@ struct TrafficGenerator
std::optional<uint64_t> addressIncrement;
std::optional<uint64_t> minAddress;
std::optional<uint64_t> maxAddress;
std::optional<uint64_t> clksPerRequest;
std::optional<std::string> idleUntil;
};
NLOHMANN_JSONIFY_ALL_THINGS(TrafficGenerator,
@@ -157,9 +150,7 @@ NLOHMANN_JSONIFY_ALL_THINGS(TrafficGenerator,
addressDistribution,
addressIncrement,
minAddress,
maxAddress,
clksPerRequest,
idleUntil)
maxAddress)
struct TrafficGeneratorStateMachine
{
@@ -173,7 +164,6 @@ struct TrafficGeneratorStateMachine
std::optional<unsigned> dataLength;
std::vector<std::variant<TrafficGeneratorActiveState, TrafficGeneratorIdleState>> states;
std::vector<TrafficGeneratorStateTransition> transitions;
std::optional<std::string> idleUntil;
};
NLOHMANN_JSONIFY_ALL_THINGS(TrafficGeneratorStateMachine,
@@ -185,10 +175,9 @@ NLOHMANN_JSONIFY_ALL_THINGS(TrafficGeneratorStateMachine,
maxTransactions,
dataLength,
states,
transitions,
idleUntil)
transitions)
struct TraceHammer
struct RowHammer
{
uint64_t clkMhz;
std::string name;
@@ -200,7 +189,7 @@ struct TraceHammer
};
NLOHMANN_JSONIFY_ALL_THINGS(
TraceHammer, clkMhz, name, maxPendingReadRequests, maxPendingWriteRequests, numRequests, rowIncrement)
RowHammer, clkMhz, name, maxPendingReadRequests, maxPendingWriteRequests, numRequests, rowIncrement)
struct TraceSetupConstants
{
@@ -209,7 +198,7 @@ struct TraceSetupConstants
};
using TraceSetup = std::vector<
std::variant<TracePlayer, TrafficGenerator, TrafficGeneratorStateMachine, TraceHammer>>;
std::variant<TracePlayer, TrafficGenerator, TrafficGeneratorStateMachine, RowHammer>>;
} // namespace Configuration

View File

@@ -0,0 +1,6 @@
Things to refactor in the configuration format:
- Embed the resource directory directly into the base configuration OR
- Specify the full (relative) path to each sub-configuration
- Remove diverging sub-config base key names in base config and in the sub-config (i.e. remove the INNER_KEYs in the code)
- Remove redundant CONGEN type from the addressmapping

View File

@@ -54,4 +54,3 @@ target_link_libraries(DRAMSys
)
build_source_group()
diagnostics_print(DRAMSys)

View File

@@ -0,0 +1,47 @@
/*
* Copyright (c) 2023, Technische Universität Kaiserslautern
* 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 <tlm_utils/multi_socket_bases.h>
class Initiator
{
public:
virtual ~Initiator() = default;
virtual void bind(tlm_utils::multi_target_base<> &target) = 0;
virtual uint64_t totalRequests() = 0;
};

View File

@@ -0,0 +1,70 @@
/*
* Copyright (c) 2023, Technische Universität Kaiserslautern
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* 3. Neither the name of the copyright holder nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER
* OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* Authors:
* Derek Christ
*/
#pragma once
#include "Initiator.h"
#include "request/RequestIssuer.h"
template <typename Producer>
class SimpleInitiator : public Initiator
{
public:
SimpleInitiator(sc_core::sc_module_name const &name,
MemoryManager &memoryManager,
std::optional<unsigned int> maxPendingReadRequests,
std::optional<unsigned int> maxPendingWriteRequests,
std::function<void()> transactionFinished,
std::function<void()> terminate,
Producer &&producer)
: producer(std::forward<Producer>(producer)),
issuer(
name,
memoryManager,
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;
};

View File

@@ -1,236 +0,0 @@
/*
* Copyright (c) 2015, Technische Universität Kaiserslautern
* 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:
* Janik Schlemminger
* Robert Gernhardt
* Matthias Jung
* Éder F. Zulian
* Felipe S. Prado
* Derek Christ
*/
#include "StlPlayer.h"
using namespace sc_core;
using namespace tlm;
StlPlayer::StlPlayer(const sc_module_name &name, const Configuration& config, const std::string &pathToTrace,
const sc_time &playerClk, unsigned int maxPendingReadRequests, unsigned int maxPendingWriteRequests,
TraceSetup& setup, bool relative) :
TrafficInitiator(name, config, setup, maxPendingReadRequests, maxPendingWriteRequests,
config.memSpec->defaultBytesPerBurst),
file(pathToTrace), relative(relative), playerClk(playerClk)
{
currentBuffer = &lineContents[0];
parseBuffer = &lineContents[1];
if (!file.is_open())
SC_REPORT_FATAL("StlPlayer", (std::string("Could not open trace ") + pathToTrace).c_str());
else
{
std::string line;
while (std::getline(file, line))
{
if (line.size() > 1 && line[0] != '#')
numberOfLines++;
}
file.clear();
file.seekg(0);
if (numberOfLines == 0)
SC_REPORT_FATAL("StlPlayer", "Trace file is empty");
}
currentBuffer->reserve(lineBufferSize);
parseBuffer->reserve(lineBufferSize);
parseTraceFile();
lineIterator = currentBuffer->cend();
}
StlPlayer::~StlPlayer()
{
if (parserThread.joinable())
parserThread.join();
}
void StlPlayer::sendNextPayload()
{
if (lineIterator == currentBuffer->cend())
{
lineIterator = swapBuffers();
if (lineIterator == currentBuffer->cend())
{
// The file is empty. Nothing more to do.
finished = true;
return;
}
}
// Allocate a generic payload for this request.
tlm_generic_payload& payload = setup.allocatePayload(lineIterator->dataLength);
payload.acquire();
// Fill up the payload.
payload.set_address(lineIterator->address);
payload.set_response_status(TLM_INCOMPLETE_RESPONSE);
payload.set_dmi_allowed(false);
payload.set_byte_enable_length(0);
payload.set_data_length(lineIterator->dataLength);
payload.set_command(lineIterator->command);
std::copy(lineIterator->data.begin(), lineIterator->data.end(), payload.get_data_ptr());
sc_time sendingTime;
sc_time sendingOffset;
if (transactionsSent == 0)
sendingOffset = SC_ZERO_TIME;
else
sendingOffset = playerClk - (sc_time_stamp() % playerClk);
if (!relative)
sendingTime = std::max(sc_time_stamp() + sendingOffset, lineIterator->sendingTime);
else
sendingTime = sc_time_stamp() + sendingOffset + lineIterator->sendingTime;
sendToTarget(payload, BEGIN_REQ, sendingTime - sc_time_stamp());
transactionsSent++;
if (payload.get_command() == tlm::TLM_READ_COMMAND)
pendingReadRequests++;
else if (payload.get_command() == tlm::TLM_WRITE_COMMAND)
pendingWriteRequests++;
PRINTDEBUGMESSAGE(name(), "Performing request #" + std::to_string(transactionsSent));
lineIterator++;
}
void StlPlayer::parseTraceFile()
{
unsigned parsedLines = 0;
parseBuffer->clear();
while (file && !file.eof() && parsedLines < lineBufferSize)
{
// Get a new line from the input file.
std::string line;
std::getline(file, line);
lineCnt++;
// If the line is empty (\n or \r\n) or starts with '#' (comment) the transaction is ignored.
if (line.size() <= 1 || line.at(0) == '#')
continue;
parsedLines++;
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
// configuration.
std::string element;
std::istringstream iss;
iss.str(line);
// Get the timestamp for the transaction.
iss >> element;
if (element.empty())
SC_REPORT_FATAL("StlPlayer", ("Malformed trace file line " + std::to_string(lineCnt) + ".").c_str());
content.sendingTime = playerClk * static_cast<double>(std::stoull(element));
// Get the optional burst length and command
iss >> element;
if (element.empty())
SC_REPORT_FATAL("StlPlayer", ("Malformed trace file line " + std::to_string(lineCnt) + ".").c_str());
if (element.at(0) == '(')
{
element.erase(0, 1);
content.dataLength = std::stoul(element);
iss >> element;
if (element.empty())
SC_REPORT_FATAL("StlPlayer", ("Malformed trace file line " + std::to_string(lineCnt) + ".").c_str());
}
else
content.dataLength = defaultDataLength;
if (element == "read")
content.command = TLM_READ_COMMAND;
else if (element == "write")
content.command = TLM_WRITE_COMMAND;
else
SC_REPORT_FATAL("StlPlayer", ("Malformed trace file line " + std::to_string(lineCnt) + ".").c_str());
// Get the address.
iss >> element;
if (element.empty())
SC_REPORT_FATAL("StlPlayer", ("Malformed trace file line " + std::to_string(lineCnt) + ".").c_str());
content.address = std::stoull(element, nullptr, 16);
// Get the data if necessary.
if (storageEnabled && content.command == TLM_WRITE_COMMAND)
{
// 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.dataLength * 2 + 2))
SC_REPORT_FATAL("StlPlayer", ("Malformed trace file line " + std::to_string(lineCnt) + ".").c_str());
// Set data
for (unsigned i = 0; i < content.dataLength; i++)
content.data.emplace_back(static_cast<unsigned char>
(std::stoi(element.substr(i * 2 + 2, 2), nullptr, 16)));
}
}
}
std::vector<StlPlayer::LineContent>::const_iterator StlPlayer::swapBuffers()
{
// Wait for parser to finish
if (parserThread.joinable())
parserThread.join();
// Swap buffers
std::swap(currentBuffer, parseBuffer);
// Start new parser thread
parserThread = std::thread(&StlPlayer::parseTraceFile, this);
return currentBuffer->cbegin();
}
uint64_t StlPlayer::getNumberOfLines() const
{
return numberOfLines;
}

View File

@@ -1,237 +0,0 @@
/*
* Copyright (c) 2017, Technische Universität Kaiserslautern
* 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:
* Matthias Jung
* Luiza Correa
* Derek Christ
*/
#include "TraceSetup.h"
#include "simulator/StlPlayer.h"
#include "simulator/TrafficGenerator.h"
#include <algorithm>
#include <iomanip>
#include <map>
using namespace sc_core;
using namespace tlm;
TraceSetup::TraceSetup(const Configuration& config,
const DRAMSys::Config::TraceSetup& traceSetup,
const std::string& pathToResources,
std::vector<std::unique_ptr<TrafficInitiator>>& players)
: memoryManager(config.storeMode != Configuration::StoreMode::NoStorage)
{
if (traceSetup.initiators.empty())
SC_REPORT_FATAL("TraceSetup", "No traffic initiators specified");
for (const auto &initiator : traceSetup.initiators)
{
std::visit(
[&](auto &&initiator)
{
std::string name = initiator.name;
double frequencyMHz = initiator.clkMhz;
sc_time playerClk = sc_time(1.0 / frequencyMHz, SC_US);
unsigned int maxPendingReadRequests = [=]() -> unsigned int
{
if (const auto &maxPendingReadRequests = initiator.maxPendingReadRequests)
return *maxPendingReadRequests;
else
return 0;
}();
unsigned int maxPendingWriteRequests = [=]() -> unsigned int
{
if (const auto &maxPendingWriteRequests = initiator.maxPendingWriteRequests)
return *maxPendingWriteRequests;
else
return 0;
}();
using T = std::decay_t<decltype(initiator)>;
if constexpr (std::is_same_v<T, DRAMSys::Config::TracePlayer>)
{
size_t pos = name.rfind('.');
if (pos == std::string::npos)
throw std::runtime_error("Name of the trace file does not contain a valid extension.");
// Get the extension and make it lower case
std::string ext = name.substr(pos + 1);
std::transform(ext.begin(), ext.end(), ext.begin(), ::tolower);
std::stringstream stlFileStream;
stlFileStream << pathToResources << "/traces/" << name;
std::string stlFile = stlFileStream.str();
std::string moduleName = name;
// replace all '.' to '_'
std::replace(moduleName.begin(), moduleName.end(), '.', '_');
StlPlayer *player;
if (ext == "stl")
player = new StlPlayer(moduleName.c_str(), config, stlFile, playerClk, maxPendingReadRequests,
maxPendingWriteRequests, *this, false);
else if (ext == "rstl")
player = new StlPlayer(moduleName.c_str(), config, stlFile, playerClk, maxPendingReadRequests,
maxPendingWriteRequests, *this, true);
else
throw std::runtime_error("Unsupported file extension in " + name);
players.push_back(std::unique_ptr<TrafficInitiator>(player));
totalTransactions += player->getNumberOfLines();
}
else if constexpr (std::is_same_v<T, DRAMSys::Config::TraceGenerator>)
{
auto* trafficGenerator = new TrafficGenerator(name.c_str(), config, initiator, *this);
players.push_back(std::unique_ptr<TrafficInitiator>(trafficGenerator));
totalTransactions += trafficGenerator->getTotalTransactions();
}
else // if constexpr (std::is_same_v<T, DRAMSys::Config::TraceHammer>)
{
uint64_t numRequests = initiator.numRequests;
uint64_t rowIncrement = initiator.rowIncrement;
players.push_back(
std::unique_ptr<TrafficInitiator>(new TrafficGeneratorHammer(name.c_str(), config, initiator, *this)));
totalTransactions += numRequests;
}
},
initiator);
}
for (const auto &inititatorConf : traceSetup.initiators)
{
if (auto generatorConf = std::get_if<DRAMSys::Config::TraceGenerator>(&inititatorConf))
{
if (const auto &idleUntil = generatorConf->idleUntil)
{
const std::string name = generatorConf->name;
auto listenerIt = std::find_if(players.begin(), players.end(),
[&name](const std::unique_ptr<TrafficInitiator> &initiator)
{ return initiator->name() == name; });
// Should be found
auto listener = dynamic_cast<TrafficGenerator *>(listenerIt->get());
auto notifierIt =
std::find_if(players.begin(), players.end(),
[&idleUntil](const std::unique_ptr<TrafficInitiator> &initiator)
{
if (auto generator = dynamic_cast<const TrafficGenerator *>(initiator.get()))
{
if (generator->hasStateTransitionEvent(*idleUntil))
return true;
}
return false;
});
if (notifierIt == players.end())
SC_REPORT_FATAL("TraceSetup", "Event to listen on not found.");
auto notifier = dynamic_cast<TrafficGenerator *>(notifierIt->get());
listener->waitUntil(&notifier->getStateTransitionEvent(*idleUntil));
}
}
}
remainingTransactions = totalTransactions;
numberOfTrafficInitiators = players.size();
defaultDataLength = config.memSpec->defaultBytesPerBurst;
}
void TraceSetup::trafficInitiatorTerminates()
{
finishedTrafficInitiators++;
if (finishedTrafficInitiators == numberOfTrafficInitiators)
sc_stop();
}
void TraceSetup::transactionFinished()
{
remainingTransactions--;
loadBar(totalTransactions - remainingTransactions, totalTransactions);
if (remainingTransactions == 0)
std::cout << std::endl;
}
tlm_generic_payload& TraceSetup::allocatePayload(unsigned dataLength)
{
return memoryManager.allocate(dataLength);
}
tlm_generic_payload& TraceSetup::allocatePayload()
{
return allocatePayload(defaultDataLength);
}
void TraceSetup::loadBar(uint64_t x, uint64_t n, unsigned int w, unsigned int granularity)
{
if ((n < 100) || ((x != n) && (x % (n / 100 * granularity) != 0)))
return;
float ratio = x / (float)n;
unsigned int c = (ratio * w);
float rest = (ratio * w) - c;
std::cout << std::setw(3) << round(ratio * 100) << "% |";
for (unsigned int x = 0; x < c; x++)
std::cout << "";
if (rest >= 0 && rest < 0.125f && c != w)
std::cout << " ";
if (rest >= 0.125f && rest < 2 * 0.125f)
std::cout << "";
if (rest >= 2 * 0.125f && rest < 3 * 0.125f)
std::cout << "";
if (rest >= 3 * 0.125f && rest < 4 * 0.125f)
std::cout << "";
if (rest >= 4 * 0.125f && rest < 5 * 0.125f)
std::cout << "";
if (rest >= 5 * 0.125f && rest < 6 * 0.125f)
std::cout << "";
if (rest >= 6 * 0.125f && rest < 7 * 0.125f)
std::cout << "";
if (rest >= 7 * 0.125f && rest < 8 * 0.125f)
std::cout << "";
for (unsigned int x = c; x < (w - 1); x++)
std::cout << " ";
std::cout << "|\r" << std::flush;
}

View File

@@ -1,412 +0,0 @@
/*
* Copyright (c) 2015, Technische Universität Kaiserslautern
* 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:
* Janik Schlemminger
* Robert Gernhardt
* Matthias Jung
* Derek Christ
*/
#include "TrafficGenerator.h"
#include "simulator/TraceSetup.h"
#include <limits>
using namespace sc_core;
using namespace tlm;
TrafficGeneratorIf::TrafficGeneratorIf(const sc_core::sc_module_name& name, const Configuration& config,
TraceSetup& setup,
unsigned int maxPendingReadRequests, unsigned int maxPendingWriteRequests,
unsigned int dataLength)
: TrafficInitiator(name, config, setup, maxPendingReadRequests, maxPendingWriteRequests, dataLength)
{
}
void TrafficGeneratorIf::sendNextPayload()
{
prepareNextPayload();
if (finished)
return;
// TODO: column / burst breite
uint64_t address = getNextAddress();
tlm_command command = getNextCommand();
if (command == tlm::TLM_READ_COMMAND)
pendingReadRequests++;
else if (command == tlm::TLM_WRITE_COMMAND)
pendingWriteRequests++;
tlm_generic_payload& payload = setup.allocatePayload();
payload.acquire();
payload.set_address(address);
payload.set_response_status(tlm::TLM_INCOMPLETE_RESPONSE);
payload.set_dmi_allowed(false);
payload.set_byte_enable_length(0);
payload.set_data_length(defaultDataLength);
payload.set_command(command);
sc_time generatorClk = getGeneratorClk();
sc_time sendingOffset;
if (transactionsSent == 0)
sendingOffset = SC_ZERO_TIME + generatorClk * clksToIdle();
else
sendingOffset = (generatorClk * clksPerRequest()) - (sc_time_stamp() % generatorClk) + generatorClk * clksToIdle();
// TODO: do not send two requests in the same cycle
sendToTarget(payload, tlm::BEGIN_REQ, sendingOffset);
transactionsSent++;
PRINTDEBUGMESSAGE(name(), "Performing request #" + std::to_string(transactionsSent));
payloadSent();
}
TrafficGenerator::TrafficGenerator(const sc_module_name& name, const Configuration& config,
const DRAMSys::Config::TraceGenerator& conf, TraceSetup& setup)
: TrafficGeneratorIf(name, config, setup, conf.maxPendingReadRequests.value_or(defaultMaxPendingReadRequests),
conf.maxPendingWriteRequests.value_or(defaultMaxPendingWriteRequests),
conf.dataLength.value_or(config.memSpec->defaultBytesPerBurst)),
generatorClk(TrafficInitiator::evaluateGeneratorClk(conf)), conf(conf),
maxTransactions(conf.maxTransactions.value_or(std::numeric_limits<uint64_t>::max())),
simMemSizeInBytes(config.memSpec->getSimMemSizeInBytes()),
randomGenerator(std::default_random_engine(conf.seed.value_or(defaultSeed)))
{
// Perform checks for all states
for (const auto &state : conf.states)
{
if (auto trafficState = std::get_if<DRAMSys::Config::TraceGeneratorTrafficState>(&state.second))
{
uint64_t minAddress = evaluateMinAddress(*trafficState);
uint64_t maxAddress = evaluateMaxAddress(*trafficState, simMemSizeInBytes);
double rwRatio = (*trafficState).rwRatio;
if (minAddress > config.memSpec->getSimMemSizeInBytes() - 1)
SC_REPORT_FATAL("TrafficGenerator", "minAddress is out of range.");
if (maxAddress > config.memSpec->getSimMemSizeInBytes() - 1)
SC_REPORT_FATAL("TrafficGenerator", "minAddress is out of range.");
if (maxAddress < minAddress)
SC_REPORT_FATAL("TrafficGenerator", "maxAddress is smaller than minAddress.");
if (rwRatio < 0 || rwRatio > 1)
SC_REPORT_FATAL("TraceSetup", "Read/Write ratio is not a number between 0 and 1.");
if (const auto &eventName = trafficState->notify)
{
stateTranstitionEvents.emplace(std::piecewise_construct, std::forward_as_tuple(*eventName),
std::forward_as_tuple(eventName->c_str(), state.first));
}
}
}
if (auto trafficState =
std::get_if<DRAMSys::Config::TraceGeneratorTrafficState>(&conf.states.at(currentState)))
{
uint64_t minAddress = evaluateMinAddress(*trafficState);
uint64_t maxAddress = evaluateMaxAddress(*trafficState, simMemSizeInBytes);
randomAddressDistribution = std::uniform_int_distribution<uint64_t>(minAddress, maxAddress);
currentClksPerRequest = trafficState->clksPerRequest.value_or(defaultClksPerRequest);
}
calculateTransitions();
}
void TrafficGenerator::calculateTransitions()
{
unsigned int state = 0;
uint64_t totalTransactions = 0;
stateSequence.push_back(state);
while (true)
{
auto transitionsIt = conf.transitions.equal_range(state);
float probabilityAccumulated = 0.0f;
std::map<unsigned int, std::pair<float, float>> transitionsDistribution;
for (auto it = transitionsIt.first; it != transitionsIt.second; ++it)
{
float lowerLimit = probabilityAccumulated;
probabilityAccumulated += it->second.probability;
float upperLimit = probabilityAccumulated;
transitionsDistribution[it->second.to] = {lowerLimit, upperLimit};
}
if (probabilityAccumulated > 1.001f)
SC_REPORT_WARNING("TrafficGenerator", "Sum of transition probabilities greater than 1.");
float random = randomDistribution(randomGenerator);
bool transitionFound = false;
for (const auto &transition : transitionsDistribution)
{
auto to = transition.first;
auto limits = transition.second;
if (limits.first < random && limits.second > random)
{
state = to;
stateSequence.push_back(state);
transitionFound = true;
break;
}
}
if (transitionFound)
{
if (auto trafficState =
std::get_if<DRAMSys::Config::TraceGeneratorTrafficState>(&conf.states.at(state)))
totalTransactions += trafficState->numRequests;
if (totalTransactions < maxTransactions)
continue;
}
break;
}
stateIt = stateSequence.cbegin();
}
bool TrafficGenerator::hasStateTransitionEvent(const std::string &eventName) const
{
auto it = stateTranstitionEvents.find(eventName);
if (it == stateTranstitionEvents.end())
return false;
return true;
}
const sc_core::sc_event &TrafficGenerator::getStateTransitionEvent(const std::string &eventName) const
{
auto it = stateTranstitionEvents.find(eventName);
if (it == stateTranstitionEvents.end())
SC_REPORT_FATAL("TraceSetup", "StateTransitionEvent not found.");
return it->second.event;
}
uint64_t TrafficGenerator::getTotalTransactions() const
{
uint64_t totalTransactions = 0;
for (auto state : stateSequence)
{
if (auto trafficState = std::get_if<DRAMSys::Config::TraceGeneratorTrafficState>(&conf.states.at(state)))
totalTransactions += trafficState->numRequests;
}
if (totalTransactions > maxTransactions)
totalTransactions = maxTransactions;
return totalTransactions;
}
void TrafficGenerator::waitUntil(const sc_core::sc_event *ev)
{
startEvent = ev;
}
void TrafficGenerator::transitionToNextState()
{
++stateIt;
if (stateIt == stateSequence.cend() || transactionsSent >= maxTransactions)
{
// No transition performed.
finished = true;
return;
}
currentState = *stateIt;
// Notify
for (auto &it : stateTranstitionEvents)
{
if (it.second.stateId == currentState)
it.second.event.notify();
}
if (auto idleState = std::get_if<DRAMSys::Config::TraceGeneratorIdleState>(&conf.states.at(currentState)))
{
currentClksToIdle += idleState->idleClks;
transitionToNextState();
return;
}
else if (auto trafficState =
std::get_if<DRAMSys::Config::TraceGeneratorTrafficState>(&conf.states.at(currentState)))
{
uint64_t minAddress = evaluateMinAddress(*trafficState);
uint64_t maxAddress = evaluateMaxAddress(*trafficState, simMemSizeInBytes);
randomAddressDistribution = std::uniform_int_distribution<uint64_t>(minAddress, maxAddress);
currentClksPerRequest = trafficState->clksPerRequest.value_or(defaultClksPerRequest);
}
currentAddress = 0x00;
transactionsSentInCurrentState = 0;
}
void TrafficGenerator::prepareNextPayload()
{
if (transactionsSent >= maxTransactions)
{
finished = true;
return;
}
if (startEvent && transactionsSent == 0)
wait(*startEvent);
if (auto trafficState =
std::get_if<DRAMSys::Config::TraceGeneratorTrafficState>(&conf.states.at(currentState)))
{
if (transactionsSentInCurrentState >= trafficState->numRequests)
transitionToNextState();
}
// In case we are in an idle state right at the beginning of the simulation,
// set the clksToIdle and transition to the next state.
if (auto idleState =
std::get_if<DRAMSys::Config::TraceGeneratorIdleState>(&conf.states.at(currentState)))
{
currentClksToIdle = idleState->idleClks;
transitionToNextState();
}
}
void TrafficGenerator::payloadSent()
{
// Reset clks to idle.
currentClksToIdle = 0;
transactionsSentInCurrentState++;
}
tlm::tlm_command TrafficGenerator::getNextCommand()
{
// An idle state should never reach this method.
auto &state = std::get<DRAMSys::Config::TraceGeneratorTrafficState>(conf.states.at(currentState));
tlm_command command;
if (randomDistribution(randomGenerator) < state.rwRatio)
command = tlm::TLM_READ_COMMAND;
else
command = tlm::TLM_WRITE_COMMAND;
return command;
}
sc_core::sc_time TrafficGenerator::getGeneratorClk() const
{
return generatorClk;
}
uint64_t TrafficGenerator::getNextAddress()
{
using DRAMSys::Config::AddressDistribution;
// An idle state should never reach this method.
auto &state = std::get<DRAMSys::Config::TraceGeneratorTrafficState>(conf.states.at(currentState));
uint64_t minAddress = evaluateMinAddress(state);
uint64_t maxAddress = evaluateMaxAddress(state, simMemSizeInBytes);
if (state.addressDistribution == AddressDistribution::Sequential)
{
uint64_t addressIncrement = state.addressIncrement.value_or(defaultAddressIncrement);
uint64_t address = currentAddress;
currentAddress += addressIncrement;
if (currentAddress > maxAddress)
currentAddress = minAddress;
return address;
}
else if (state.addressDistribution == AddressDistribution::Random)
{
return randomAddressDistribution(randomGenerator);
}
else
{
return 0x00;
}
}
uint64_t TrafficGenerator::evaluateMinAddress(const DRAMSys::Config::TraceGeneratorTrafficState &state)
{
return state.minAddress.value_or(0x00);
}
uint64_t TrafficGenerator::evaluateMaxAddress(const DRAMSys::Config::TraceGeneratorTrafficState &state,
uint64_t simMemSizeInBytes)
{
return state.maxAddress.value_or(simMemSizeInBytes - 1);
}
TrafficGeneratorHammer::TrafficGeneratorHammer(const sc_core::sc_module_name &name, const Configuration& config,
const DRAMSys::Config::TraceHammer &conf, TraceSetup& setup)
: TrafficGeneratorIf(name, config, setup, 1, 1, config.memSpec->defaultBytesPerBurst),
generatorClk(evaluateGeneratorClk(conf)), rowIncrement(conf.rowIncrement), numRequests(conf.numRequests)
{
}
tlm::tlm_command TrafficGeneratorHammer::getNextCommand()
{
return tlm::TLM_READ_COMMAND;
}
sc_core::sc_time TrafficGeneratorHammer::getGeneratorClk() const
{
return generatorClk;
}
uint64_t TrafficGeneratorHammer::getNextAddress()
{
if (currentAddress == 0x0)
currentAddress = rowIncrement;
else
currentAddress = 0x0;
return currentAddress;
}
void TrafficGeneratorHammer::prepareNextPayload()
{
if (transactionsSent >= numRequests)
finished = true;
}

View File

@@ -1,150 +0,0 @@
/*
* Copyright (c) 2015, Technische Universität Kaiserslautern
* 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:
* Janik Schlemminger
* Robert Gernhardt
* Matthias Jung
* Derek Christ
*/
#ifndef TRAFFICGENERATOR_H
#define TRAFFICGENERATOR_H
#include "simulator/TrafficInitiator.h"
#include "simulator/TraceSetup.h"
#include <cstdint>
#include <map>
#include <random>
class TrafficGeneratorIf : public TrafficInitiator
{
public:
TrafficGeneratorIf(const sc_core::sc_module_name &name, const Configuration& config, TraceSetup& setup,
unsigned int maxPendingReadRequests, unsigned int maxPendingWriteRequests,
unsigned int dataLength);
private:
void sendNextPayload() override;
virtual void prepareNextPayload(){};
virtual uint64_t getNextAddress() = 0;
virtual tlm::tlm_command getNextCommand() = 0;
virtual sc_core::sc_time getGeneratorClk() const = 0;
virtual void payloadSent(){};
virtual uint64_t clksPerRequest() const { return 1; }
virtual uint64_t clksToIdle() const { return 0; }
};
class TrafficGenerator : public TrafficGeneratorIf
{
public:
TrafficGenerator(const sc_core::sc_module_name &name, const Configuration& config,
const DRAMSys::Config::TraceGenerator &conf, TraceSetup& setup);
uint64_t getTotalTransactions() const;
void waitUntil(const sc_core::sc_event *ev);
bool hasStateTransitionEvent(const std::string &eventName) const;
const sc_core::sc_event &getStateTransitionEvent(const std::string &eventName) const;
private:
static uint64_t evaluateMinAddress(const DRAMSys::Config::TraceGeneratorTrafficState& state);
static uint64_t evaluateMaxAddress(const DRAMSys::Config::TraceGeneratorTrafficState& state,
uint64_t simMemSizeInBytes);
void prepareNextPayload() override;
uint64_t getNextAddress() override;
tlm::tlm_command getNextCommand() override;
sc_core::sc_time getGeneratorClk() const override;
void payloadSent() override;
uint64_t clksPerRequest() const override { return currentClksPerRequest; };
uint64_t clksToIdle() const override { return currentClksToIdle; }
void calculateTransitions();
void transitionToNextState();
sc_core::sc_time generatorClk;
const DRAMSys::Config::TraceGenerator &conf;
unsigned int currentState = 0;
uint64_t currentAddress = 0x00;
uint64_t currentClksPerRequest = 1;
uint64_t transactionsSentInCurrentState = 0;
const uint64_t maxTransactions;
const uint64_t simMemSizeInBytes;
uint64_t currentClksToIdle = 0;
std::vector<unsigned int> stateSequence;
std::vector<unsigned int>::const_iterator stateIt;
struct EventPair
{
EventPair(const std::string &name, unsigned int id) : event(name.c_str()), stateId(id)
{
}
sc_core::sc_event event;
unsigned int stateId;
};
std::map<std::string, EventPair> stateTranstitionEvents;
bool idleAtStart = false;
const sc_core::sc_event *startEvent = nullptr;
std::default_random_engine randomGenerator;
std::uniform_real_distribution<float> randomDistribution = std::uniform_real_distribution<float>(0.0f, 1.0f);
std::uniform_int_distribution<uint64_t> randomAddressDistribution;
static constexpr uint64_t defaultSeed = 0;
static constexpr uint64_t defaultClksPerRequest = 1;
static constexpr uint64_t defaultAddressIncrement = 0x00;
};
class TrafficGeneratorHammer final : public TrafficGeneratorIf
{
public:
TrafficGeneratorHammer(const sc_core::sc_module_name &name, const Configuration& config,
const DRAMSys::Config::TraceHammer &conf, TraceSetup& setup);
private:
void prepareNextPayload() override;
uint64_t getNextAddress() override;
tlm::tlm_command getNextCommand() override;
sc_core::sc_time getGeneratorClk() const override;
sc_core::sc_time generatorClk;
uint64_t rowIncrement;
uint64_t currentAddress = 0x0;
uint64_t numRequests;
};
#endif // TRAFFICGENERATOR_H

View File

@@ -1,138 +0,0 @@
/*
* Copyright (c) 2015, Technische Universität Kaiserslautern
* 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:
* Robert Gernhardt
* Matthias Jung
* Éder F. Zulian
* Felipe S. Prado
* Derek Christ
*/
#include "TrafficInitiator.h"
using namespace sc_core;
using namespace tlm;
TrafficInitiator::TrafficInitiator(const sc_module_name &name, const Configuration& config, TraceSetup& setup,
unsigned int maxPendingReadRequests, unsigned int maxPendingWriteRequests, unsigned int defaultDataLength) :
sc_module(name),
payloadEventQueue(this, &TrafficInitiator::peqCallback),
setup(setup),
maxPendingReadRequests(maxPendingReadRequests),
maxPendingWriteRequests(maxPendingWriteRequests),
defaultDataLength(defaultDataLength),
storageEnabled(config.storeMode != Configuration::StoreMode::NoStorage),
simulationProgressBar(config.simulationProgressBar)
{
SC_THREAD(sendNextPayload);
iSocket.register_nb_transport_bw(this, &TrafficInitiator::nb_transport_bw);
}
void TrafficInitiator::terminate()
{
std::cout << sc_time_stamp() << " " << this->name() << " terminated " << std::endl;
setup.trafficInitiatorTerminates();
}
tlm_sync_enum TrafficInitiator::nb_transport_bw(tlm_generic_payload &payload,
tlm_phase &phase, sc_time &bwDelay)
{
payloadEventQueue.notify(payload, phase, bwDelay);
return TLM_ACCEPTED;
}
void TrafficInitiator::peqCallback(tlm_generic_payload &payload,
const tlm_phase &phase)
{
if (phase == END_REQ)
{
if (nextPayloadSendable())
sendNextPayload();
else
payloadPostponed = true;
}
else if (phase == BEGIN_RESP)
{
payload.release();
sendToTarget(payload, END_RESP, SC_ZERO_TIME);
if (simulationProgressBar)
setup.transactionFinished();
transactionsReceived++;
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 (payloadPostponed && nextPayloadSendable())
{
sendNextPayload();
payloadPostponed = false;
}
// If all answers were received:
if (finished && transactionsSent == transactionsReceived)
terminate();
}
else
{
SC_REPORT_FATAL("TrafficInitiator", "PEQ was triggered with unknown phase");
}
}
void TrafficInitiator::sendToTarget(tlm_generic_payload &payload, const tlm_phase &phase, const sc_time &delay)
{
tlm_phase TPhase = phase;
sc_time TDelay = delay;
iSocket->nb_transport_fw(payload, TPhase, TDelay);
}
bool TrafficInitiator::nextPayloadSendable() const
{
// If either the maxPendingReadRequests or maxPendingWriteRequests
// limit is reached, do not send next payload.
if (((pendingReadRequests >= maxPendingReadRequests) && (maxPendingReadRequests != 0))
|| ((pendingWriteRequests >= maxPendingWriteRequests) && (maxPendingWriteRequests != 0)))
return false;
else
return true;
}
sc_core::sc_time TrafficInitiator::evaluateGeneratorClk(const DRAMSys::Config::TrafficInitiator& conf)
{
double frequencyMHz = conf.clkMhz;
sc_time playerClk = sc_time(1.0 / frequencyMHz, SC_US);
return playerClk;
}

View File

@@ -0,0 +1,79 @@
/*
* Copyright (c) 2023, Technische Universität Kaiserslautern
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* 3. Neither the name of the copyright holder nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER
* OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* Authors:
* Derek Christ
*/
#include "RandomProducer.h"
#include "definitions.h"
RandomProducer::RandomProducer(uint64_t numRequests,
std::optional<uint64_t> seed,
double rwRatio,
unsigned int clkMhz,
std::optional<uint64_t> minAddress,
std::optional<uint64_t> maxAddress,
uint64_t memorySize,
unsigned int dataLength)
: numberOfRequests(numRequests),
seed(seed.value_or(DEFAULT_SEED)),
rwRatio(rwRatio),
randomGenerator(this->seed),
generatorPeriod(sc_core::sc_time(1.0 / static_cast<double>(clkMhz), sc_core::SC_US)),
dataLength(dataLength),
randomAddressDistribution(minAddress.value_or(DEFAULT_MIN_ADDRESS),
maxAddress.value_or((memorySize / dataLength) - 1))
{
if (minAddress > memorySize - 1)
SC_REPORT_FATAL("TrafficGenerator", "minAddress is out of range.");
if (maxAddress > memorySize - 1)
SC_REPORT_FATAL("TrafficGenerator", "minAddress is out of range.");
if (maxAddress < minAddress)
SC_REPORT_FATAL("TrafficGenerator", "maxAddress is smaller than minAddress.");
if (rwRatio < 0 || rwRatio > 1)
SC_REPORT_FATAL("TraceSetup", "Read/Write ratio is not a number between 0 and 1.");
}
Request RandomProducer::nextRequest()
{
Request request;
request.address = randomAddressDistribution(randomGenerator) * dataLength;
request.command = readWriteDistribution(randomGenerator) < rwRatio ? Request::Command::Read
: Request::Command::Write;
request.length = dataLength;
request.delay = generatorPeriod;
return request;
}

View File

@@ -0,0 +1,69 @@
/*
* Copyright (c) 2023, Technische Universität Kaiserslautern
* 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 "simulator/request/RequestProducer.h"
#include <optional>
#include <random>
class RandomProducer : public RequestProducer
{
public:
RandomProducer(uint64_t numRequests,
std::optional<uint64_t> seed,
double rwRatio,
unsigned int clkMhz,
std::optional<uint64_t> minAddress,
std::optional<uint64_t> maxAddress,
uint64_t memorySize,
unsigned int dataLength);
Request nextRequest() override;
uint64_t totalRequests() override { return numberOfRequests; }
sc_core::sc_time clkPeriod() override { return generatorPeriod; }
const uint64_t numberOfRequests;
const uint64_t seed;
const double rwRatio;
const sc_core::sc_time generatorPeriod;
const unsigned int dataLength;
std::default_random_engine randomGenerator;
std::uniform_real_distribution<double> readWriteDistribution{0.0, 1.0};
std::uniform_int_distribution<uint64_t> randomAddressDistribution;
};

View File

@@ -0,0 +1,82 @@
/*
* Copyright (c) 2023, Technische Universität Kaiserslautern
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* 3. Neither the name of the copyright holder nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER
* OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* Authors:
* Derek Christ
*/
#include "SequentialProducer.h"
#include "definitions.h"
SequentialProducer::SequentialProducer(uint64_t numRequests,
std::optional<uint64_t> seed,
double rwRatio,
unsigned int clkMhz,
std::optional<uint64_t> addressIncrement,
std::optional<uint64_t> minAddress,
std::optional<uint64_t> maxAddress,
uint64_t memorySize,
unsigned int dataLength)
: numberOfRequests(numRequests),
addressIncrement(addressIncrement.value_or(dataLength)),
minAddress(minAddress.value_or(DEFAULT_MIN_ADDRESS)),
maxAddress(maxAddress.value_or(memorySize - 1)),
seed(seed.value_or(DEFAULT_SEED)),
rwRatio(rwRatio),
randomGenerator(this->seed),
generatorPeriod(sc_core::sc_time(1.0 / static_cast<double>(clkMhz), sc_core::SC_US)),
dataLength(dataLength)
{
if (minAddress > memorySize - 1)
SC_REPORT_FATAL("TrafficGenerator", "minAddress is out of range.");
if (maxAddress > memorySize - 1)
SC_REPORT_FATAL("TrafficGenerator", "minAddress is out of range.");
if (maxAddress < minAddress)
SC_REPORT_FATAL("TrafficGenerator", "maxAddress is smaller than minAddress.");
if (rwRatio < 0 || rwRatio > 1)
SC_REPORT_FATAL("TraceSetup", "Read/Write ratio is not a number between 0 and 1.");
}
Request SequentialProducer::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 = generatorPeriod;
generatedRequests++;
return request;
}

View File

@@ -0,0 +1,75 @@
/*
* Copyright (c) 2023, Technische Universität Kaiserslautern
* 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 "simulator/request/RequestProducer.h"
#include <optional>
#include <random>
class SequentialProducer : public RequestProducer
{
public:
SequentialProducer(uint64_t numRequests,
std::optional<uint64_t> seed,
double rwRatio,
unsigned int clkMhz,
std::optional<uint64_t> addressIncrement,
std::optional<uint64_t> minAddress,
std::optional<uint64_t> maxAddress,
uint64_t memorySize,
unsigned int dataLength);
Request nextRequest() override;
uint64_t totalRequests() override { return numberOfRequests; }
sc_core::sc_time clkPeriod() override { return generatorPeriod; }
void reset() override { generatedRequests = 0; }
const uint64_t numberOfRequests;
const uint64_t addressIncrement;
const uint64_t minAddress;
const uint64_t maxAddress;
const uint64_t seed;
const double rwRatio;
const sc_core::sc_time generatorPeriod;
const unsigned int dataLength;
std::default_random_engine randomGenerator;
std::uniform_real_distribution<double> readWriteDistribution{0.0, 1.0};
uint64_t generatedRequests = 0;
};

View File

@@ -0,0 +1,238 @@
/*
* Copyright (c) 2023, Technische Universität Kaiserslautern
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* 3. Neither the name of the copyright holder nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER
* OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* Authors:
* Derek Christ
*/
#include "TrafficGenerator.h"
TrafficGenerator::TrafficGenerator(DRAMSys::Config::TrafficGeneratorStateMachine const &config,
MemoryManager &memoryManager,
uint64_t memorySize,
unsigned int dataLength,
std::function<void()> transactionFinished,
std::function<void()> terminateInitiator)
: consumer(
config.name.c_str(),
memoryManager,
config.maxPendingReadRequests,
config.maxPendingWriteRequests,
[this] { return nextRequest(); },
std::move(transactionFinished),
std::move(terminateInitiator)),
stateTransistions(config.transitions)
{
for (auto const &state : config.states)
{
std::visit(
[=, &config](auto &&arg)
{
using DRAMSys::Config::TrafficGeneratorActiveState;
using DRAMSys::Config::TrafficGeneratorIdleState;
using T = std::decay_t<decltype(arg)>;
if constexpr (std::is_same_v<T, TrafficGeneratorActiveState>)
{
auto const &activeState = arg;
if (activeState.addressDistribution ==
DRAMSys::Config::AddressDistribution::Random)
{
auto producer = std::make_unique<RandomProducer>(activeState.numRequests,
config.seed,
activeState.rwRatio,
config.clkMhz,
activeState.minAddress,
activeState.maxAddress,
memorySize,
dataLength);
producers.emplace(activeState.id, std::move(producer));
}
else
{
auto producer =
std::make_unique<SequentialProducer>(activeState.numRequests,
config.seed,
activeState.rwRatio,
config.clkMhz,
activeState.addressIncrement,
activeState.minAddress,
activeState.maxAddress,
memorySize,
dataLength);
producers.emplace(activeState.id, std::move(producer));
}
}
else if constexpr (std::is_same_v<T, TrafficGeneratorIdleState>)
{
auto const &idleState = arg;
idleStateClks.emplace(idleState.id, idleState.idleClks);
}
},
state);
}
}
TrafficGenerator::TrafficGenerator(DRAMSys::Config::TrafficGenerator const &config,
MemoryManager &memoryManager,
uint64_t memorySize,
unsigned int dataLength,
std::function<void()> transactionFinished,
std::function<void()> terminateInitiator)
: consumer(
config.name.c_str(),
memoryManager,
config.maxPendingReadRequests,
config.maxPendingWriteRequests,
[this] { return nextRequest(); },
std::move(transactionFinished),
std::move(terminateInitiator))
{
if (config.addressDistribution == DRAMSys::Config::AddressDistribution::Random)
{
auto producer = std::make_unique<RandomProducer>(config.numRequests,
config.seed,
config.rwRatio,
config.clkMhz,
config.minAddress,
config.maxAddress,
memorySize,
dataLength);
producers.emplace(0, std::move(producer));
}
else
{
auto producer = std::make_unique<SequentialProducer>(config.numRequests,
config.seed,
config.rwRatio,
config.clkMhz,
config.addressIncrement,
config.minAddress,
config.maxAddress,
memorySize,
dataLength);
producers.emplace(0, std::move(producer));
}
}
Request TrafficGenerator::nextRequest()
{
uint64_t clksToIdle = 0;
if (requestsInState >= producers[currentState]->totalRequests())
{
// Reset current producer to its initial state
producers[currentState]->reset();
auto newState = stateTransition(currentState);
if (!newState.has_value())
return Request{.command = Request::Command::Stop};
auto idleStateIt = idleStateClks.find(newState.value());
while (idleStateIt != idleStateClks.cend())
{
clksToIdle += idleStateIt->second;
newState = stateTransition(currentState);
if (!newState.has_value())
return Request{.command = Request::Command::Stop};
currentState = newState.value();
idleStateIt = idleStateClks.find(newState.value());
}
currentState = newState.value();
requestsInState = 0;
}
requestsInState++;
Request request = producers[currentState]->nextRequest();
request.delay += producers[currentState]->clkPeriod() * clksToIdle;
return request;
}
uint64_t TrafficGenerator::totalRequests()
{
// Store current state of random generator
std::default_random_engine tempGenerator(randomGenerator);
// Reset generator to initial state
randomGenerator.seed();
uint64_t totalRequests = 0;
unsigned int currentState = 0;
if (producers.find(currentState) != producers.cend())
totalRequests += producers.at(currentState)->totalRequests();
while (auto nextState = stateTransition(currentState))
{
currentState = nextState.value();
if (producers.find(currentState) != producers.cend())
totalRequests += producers.at(currentState)->totalRequests();
}
// Restore state of random generator
randomGenerator = tempGenerator;
return totalRequests;
}
std::optional<unsigned int> TrafficGenerator::stateTransition(unsigned int from)
{
using Transition = DRAMSys::Config::TrafficGeneratorStateTransition;
std::vector<Transition> relevantTransitions;
std::copy_if(stateTransistions.cbegin(),
stateTransistions.cend(),
std::back_inserter(relevantTransitions),
[from](Transition transition) { return transition.from == from; });
if (relevantTransitions.empty())
return std::nullopt;
std::vector<double> propabilities;
std::for_each(relevantTransitions.cbegin(),
relevantTransitions.cend(),
[&propabilities](Transition transition)
{ propabilities.push_back(transition.probability); });
assert(propabilities.size() == relevantTransitions.size());
std::discrete_distribution<std::size_t> stateTransitionDistribution(propabilities.cbegin(),
propabilities.cend());
std::size_t index = stateTransitionDistribution(randomGenerator);
return relevantTransitions[index].to;
}

View File

@@ -0,0 +1,82 @@
/*
* Copyright (c) 2023, Technische Universität Kaiserslautern
* 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 "RandomProducer.h"
#include "SequentialProducer.h"
#include "simulator/Initiator.h"
#include "simulator/MemoryManager.h"
#include "simulator/request/RequestIssuer.h"
#include <DRAMSys/config/DRAMSysConfiguration.h>
class TrafficGenerator : public Initiator
{
public:
TrafficGenerator(DRAMSys::Config::TrafficGenerator const &config,
MemoryManager &memoryManager,
uint64_t memorySize,
unsigned int dataLength,
std::function<void()> transactionFinished,
std::function<void()> terminateInitiator);
TrafficGenerator(DRAMSys::Config::TrafficGeneratorStateMachine const &config,
MemoryManager &memoryManager,
uint64_t memorySize,
unsigned int dataLength,
std::function<void()> transactionFinished,
std::function<void()> terminateInitiator);
void bind(tlm_utils::multi_target_base<> &target) override { consumer.iSocket.bind(target); }
uint64_t totalRequests() override;
Request nextRequest();
std::optional<unsigned int> stateTransition(unsigned int from);
private:
uint64_t requestsInState = 0;
unsigned int currentState = 0;
const std::vector<DRAMSys::Config::TrafficGeneratorStateTransition> stateTransistions;
using IdleClks = uint64_t;
std::unordered_map<unsigned int, IdleClks> idleStateClks;
std::default_random_engine randomGenerator;
std::unordered_map<unsigned int, std::unique_ptr<RequestProducer>> producers;
RequestIssuer consumer;
};

View File

@@ -0,0 +1,41 @@
/*
* Copyright (c) 2023, Technische Universität Kaiserslautern
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* 3. Neither the name of the copyright holder nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER
* OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* Authors:
* Derek Christ
*/
#pragma once
#include <cstdint>
inline constexpr uint64_t DEFAULT_SEED = 0;
inline constexpr uint64_t DEFAULT_MIN_ADDRESS = 0;

View File

@@ -0,0 +1,67 @@
/*
* Copyright (c) 2023, Technische Universität Kaiserslautern
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* 3. Neither the name of the copyright holder nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER
* OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* Authors:
* Derek Christ
*/
#include "RowHammer.h"
RowHammer::RowHammer(uint64_t numRequests,
unsigned int clkMhz,
uint64_t rowIncrement,
unsigned int dataLength)
: numberOfRequests(numRequests),
generatorPeriod(sc_core::sc_time(1.0 / static_cast<double>(clkMhz), sc_core::SC_US)),
dataLength(dataLength),
rowIncrement(rowIncrement)
{
}
Request RowHammer::nextRequest()
{
if (generatedRequests >= numberOfRequests)
return Request{.command = Request::Command::Stop};
generatedRequests++;
if (currentAddress == 0x00)
currentAddress = rowIncrement;
else
currentAddress = 0x00;
Request request;
request.address = currentAddress;
request.command = Request::Command::Read;
request.length = dataLength;
request.delay = generatorPeriod;
return request;
}

View File

@@ -0,0 +1,61 @@
/*
* Copyright (c) 2023, Technische Universität Kaiserslautern
* 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 "simulator/request/RequestProducer.h"
#include <systemc>
class RowHammer : public RequestProducer
{
public:
RowHammer(uint64_t numRequests,
unsigned int clkMhz,
uint64_t rowIncrement,
unsigned int dataLength);
Request nextRequest() override;
sc_core::sc_time clkPeriod() override { return generatorPeriod; }
uint64_t totalRequests() override { return numberOfRequests; }
const uint64_t numberOfRequests;
const sc_core::sc_time generatorPeriod;
const unsigned int dataLength;
const uint64_t rowIncrement;
uint64_t generatedRequests = 0;
uint64_t currentAddress = 0x00;
};

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2015, Technische Universität Kaiserslautern
* Copyright (c) 2023, Technische Universität Kaiserslautern
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -30,105 +30,158 @@
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* Authors:
* Robert Gernhardt
* Matthias Jung
* Luiza Correa
* Lukas Steiner
* Derek Christ
*/
#include "simulator/TraceSetup.h"
#include "simulator/TrafficInitiator.h"
#include "Initiator.h"
#include "MemoryManager.h"
#include "SimpleInitiator.h"
#include "generator/TrafficGenerator.h"
#include "hammer/RowHammer.h"
#include "player/StlPlayer.h"
#include "util.h"
#include "DRAMSys/simulation/DRAMSys.h"
#include "DRAMSys/simulation/DRAMSysRecordable.h"
#include "DRAMSys/config/DRAMSysConfiguration.h"
#include <DRAMSys/simulation/DRAMSysRecordable.h>
#include <iostream>
#include <memory>
#include <string>
#include <vector>
#include <chrono>
#include <systemc>
#include <tlm>
#include <tlm_utils/peq_with_cb_and_phase.h>
#include <tlm_utils/simple_initiator_socket.h>
using namespace sc_core;
#include <filesystem>
#include <fstream>
#include <random>
std::string pathOfFile(const std::string &file)
{
return file.substr(0, file.find_last_of('/'));
}
int main(int argc, char **argv)
{
return sc_main(argc, argv);
}
static constexpr std::string_view TRACE_DIRECTORY = "traces";
int sc_main(int argc, char **argv)
{
sc_set_time_resolution(1, SC_PS);
std::string resources;
std::string simulationJson;
// Run only with default config (ddr3-example.json):
if (argc == 1)
std::filesystem::path resourceDirectory = "configs";
if (argc >= 3)
{
// Get path of resources:
resources = pathOfFile(argv[0])
+ std::string("/../../configs/");
simulationJson = resources + "ddr4-example.json";
}
// Run with specific config but default resource folders:
else if (argc == 2)
{
// Get path of resources:
resources = pathOfFile(argv[0])
+ std::string("/../../configs/");
simulationJson = argv[1];
}
// Run with specific config and specific resource folder:
else if (argc == 3)
{
simulationJson = argv[1];
resources = argv[2];
resourceDirectory = argv[2];
}
std::vector<std::unique_ptr<TrafficInitiator>> players;
std::filesystem::path baseConfig = resourceDirectory / "ddr5-example.json";
if (argc >= 2)
{
baseConfig = argv[1];
}
DRAMSys::Config::Configuration configLib = DRAMSys::Config::from_path(simulationJson, resources);
DRAMSys::Config::Configuration configuration = DRAMSys::Config::from_path(baseConfig.c_str());
// Instantiate DRAMSys:
std::unique_ptr<DRAMSys::DRAMSys> dramSys;
if (!configuration.tracesetup.has_value())
SC_REPORT_FATAL("Simulator", "No traffic initiators specified");
if (configLib.simconfig.DatabaseRecording.value_or(false))
dramSys = std::make_unique<DRAMSys::DRAMSysRecordable>("DRAMSys", configLib);
else
dramSys = std::make_unique<DRAMSys::DRAMSys>("DRAMSys", configLib);
DRAMSys::DRAMSysRecordable dramSys("DRAMSys", configuration);
if (!configLib.tracesetup.has_value())
SC_REPORT_FATAL("sc_main", "No trace setup section provided.");
MemoryManager memoryManager(false);
// Instantiate STL Players:
TraceSetup setup(dramSys->getConfig(), configLib.tracesetup.value(), resources, players);
std::vector<std::unique_ptr<Initiator>> initiators;
// Bind STL Players with DRAMSys:
for (auto& player : players)
player->iSocket.bind(dramSys->tSocket);
unsigned int terminatedInitiators = 0;
auto termianteInitiator = [&initiators, &terminatedInitiators]()
{
terminatedInitiators++;
if (terminatedInitiators == initiators.size())
sc_core::sc_stop();
};
uint64_t totalTransactions{};
uint64_t transactionsFinished = 0;
auto transactionFinished = [&totalTransactions, &transactionsFinished]()
{
transactionsFinished++;
loadBar(transactionsFinished, totalTransactions);
};
for (auto const &initiator_config : configuration.tracesetup.value())
{
uint64_t memorySize = dramSys.getConfig().memSpec->getSimMemSizeInBytes();
unsigned int dataLength = dramSys.getConfig().memSpec->defaultBytesPerBurst;
auto initiator = std::visit(
[=, &memoryManager](auto &&config) -> std::unique_ptr<Initiator>
{
using T = std::decay_t<decltype(config)>;
if constexpr (std::is_same_v<T, DRAMSys::Config::TrafficGenerator> ||
std::is_same_v<T, DRAMSys::Config::TrafficGeneratorStateMachine>)
{
return std::make_unique<TrafficGenerator>(config,
memoryManager,
memorySize,
dataLength,
transactionFinished,
termianteInitiator);
}
else if constexpr (std::is_same_v<T, DRAMSys::Config::TracePlayer>)
{
std::filesystem::path tracePath =
resourceDirectory / TRACE_DIRECTORY / config.name;
StlPlayer::TraceType traceType;
auto extension = tracePath.extension();
if (extension == ".stl")
traceType = StlPlayer::TraceType::Absolute;
else if (extension == ".rtl")
traceType = StlPlayer::TraceType::Relative;
else
{
std::string report = extension.string() + " is not a valid trace format.";
SC_REPORT_FATAL("Simulator", report.c_str());
}
StlPlayer player(
tracePath.c_str(), config.clkMhz, dataLength, traceType, false);
return std::make_unique<SimpleInitiator<StlPlayer>>(config.name.c_str(),
memoryManager,
std::nullopt,
std::nullopt,
transactionFinished,
termianteInitiator,
std::move(player));
}
else if constexpr (std::is_same_v<T, DRAMSys::Config::RowHammer>)
{
RowHammer hammer(
config.numRequests, config.clkMhz, config.rowIncrement, dataLength);
return std::make_unique<SimpleInitiator<RowHammer>>(config.name.c_str(),
memoryManager,
1,
1,
transactionFinished,
termianteInitiator,
std::move(hammer));
}
},
initiator_config);
totalTransactions += initiator->totalRequests();
initiator->bind(dramSys.tSocket);
initiators.push_back(std::move(initiator));
}
// Store the starting of the simulation in wall-clock time:
auto start = std::chrono::high_resolution_clock::now();
// Start SystemC Simulation:
sc_set_stop_mode(SC_STOP_FINISH_DELTA);
sc_start();
if (!sc_end_of_simulation_invoked())
// Start the SystemC simulation
sc_set_stop_mode(sc_core::SC_STOP_FINISH_DELTA);
sc_core::sc_start();
if (!sc_core::sc_end_of_simulation_invoked())
{
SC_REPORT_WARNING("sc_main", "Simulation stopped without explicit sc_stop()");
sc_stop();
sc_core::sc_stop();
}
auto finish = std::chrono::high_resolution_clock::now();
std::chrono::duration<double> elapsed = finish - start;
std::cout << "Simulation took " + std::to_string(elapsed.count()) + " seconds." << std::endl;
return 0;
}

View File

@@ -0,0 +1,221 @@
/*
* Copyright (c) 2023, Technische Universität Kaiserslautern
* 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:
* Janik Schlemminger
* Robert Gernhardt
* Matthias Jung
* Éder F. Zulian
* Felipe S. Prado
* Derek Christ
*/
#include "StlPlayer.h"
#include <sstream>
StlPlayer::StlPlayer(std::string_view tracePath,
unsigned int clkMhz,
unsigned int defaultDataLength,
TraceType traceType,
bool storageEnabled)
: traceFile(tracePath.data()),
playerPeriod(sc_core::sc_time(1.0 / static_cast<double>(clkMhz), sc_core::SC_US)),
defaultDataLength(defaultDataLength),
traceType(traceType),
storageEnabled(storageEnabled),
lineBuffers(
{std::make_shared<std::vector<Request>>(), std::make_shared<std::vector<Request>>()}),
readoutBuffer(lineBuffers.at(0)),
parseBuffer(lineBuffers.at(1))
{
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 line;
while (std::getline(traceFile, line))
{
if (line.size() > 1 && line[0] != '#')
numberOfLines++;
}
traceFile.clear();
traceFile.seekg(0);
}
parseTraceFile();
readoutIt = readoutBuffer->cend();
}
Request StlPlayer::nextRequest()
{
if (readoutIt == readoutBuffer->cend())
{
readoutIt = swapBuffers();
if (readoutIt == readoutBuffer->cend())
{
if (parserThread.joinable())
parserThread.join();
// The file is read in completely. Nothing more to do.
return Request{.command = Request::Command::Stop};
}
}
sc_core::sc_time delay = readoutIt->delay;
if (traceType == TraceType::Absolute)
{
delay = std::max(sc_core::sc_time_stamp(), delay);
delay -= sc_core::sc_time_stamp();
}
Request request(std::move(*readoutIt));
request.delay = delay;
readoutIt++;
return request;
}
void StlPlayer::parseTraceFile()
{
unsigned parsedLines = 0;
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++;
// If the line is empty (\n or \r\n) or starts with '#' (comment) the transaction is
// ignored.
if (line.size() <= 1 || line.at(0) == '#')
continue;
parsedLines++;
parseBuffer->emplace_back();
Request &content = parseBuffer->back();
// Trace files MUST provide timestamp, command and address for every
// transaction. The data information depends on the storage mode
// configuration.
std::string element;
std::istringstream iss;
iss.str(line);
// Get the timestamp for the transaction.
iss >> element;
if (element.empty())
SC_REPORT_FATAL(
"StlPlayer",
("Malformed trace file line " + std::to_string(currentLine) + ".").c_str());
content.delay = playerPeriod * static_cast<double>(std::stoull(element));
// Get the optional burst length and command
iss >> element;
if (element.empty())
SC_REPORT_FATAL(
"StlPlayer",
("Malformed trace file line " + std::to_string(currentLine) + ".").c_str());
if (element.at(0) == '(')
{
element.erase(0, 1);
content.length = std::stoul(element);
iss >> element;
if (element.empty())
SC_REPORT_FATAL(
"StlPlayer",
("Malformed trace file line " + std::to_string(currentLine) + ".").c_str());
}
else
content.length = defaultDataLength;
if (element == "read")
content.command = Request::Command::Read;
else if (element == "write")
content.command = Request::Command::Write;
else
SC_REPORT_FATAL(
"StlPlayer",
("Malformed trace file line " + std::to_string(currentLine) + ".").c_str());
// Get the address.
iss >> element;
if (element.empty())
SC_REPORT_FATAL(
"StlPlayer",
("Malformed trace file line " + std::to_string(currentLine) + ".").c_str());
content.address = std::stoull(element, nullptr, 16);
// Get the data if necessary.
if (storageEnabled && content.command == Request::Command::Write)
{
// The input trace file must provide the data to be stored into the memory.
iss >> element;
// Check if data length in the trace file is correct.
// We need two characters to represent 1 byte in hexadecimal. Offset for 0x prefix.
if (element.length() != (content.length * 2 + 2))
SC_REPORT_FATAL(
"StlPlayer",
("Malformed trace file line " + std::to_string(currentLine) + ".").c_str());
// Set data
for (unsigned i = 0; i < content.length; i++)
content.data.emplace_back(static_cast<unsigned char>(
std::stoi(element.substr(i * 2 + 2, 2), nullptr, 16)));
}
}
}
std::vector<Request>::const_iterator StlPlayer::swapBuffers()
{
// Wait for parser to finish
if (parserThread.joinable())
parserThread.join();
// Swap buffers
std::swap(readoutBuffer, parseBuffer);
// Start new parser thread
parserThread = std::thread(&StlPlayer::parseTraceFile, this);
return readoutBuffer->cbegin();
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2015, Technische Universität Kaiserslautern
* Copyright (c) 2023, Technische Universität Kaiserslautern
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -38,65 +38,59 @@
* Derek Christ
*/
#ifndef STLPLAYER_H
#define STLPLAYER_H
#pragma once
#include "simulator/TraceSetup.h"
#include "simulator/TrafficInitiator.h"
#include "simulator/request/Request.h"
#include "simulator/request/RequestProducer.h"
#include <sstream>
#include <vector>
#include <array>
#include <thread>
#include <fstream>
#include <systemc>
#include <tlm>
class StlPlayer : public TrafficInitiator
#include <fstream>
#include <memory>
#include <thread>
#include <vector>
class StlPlayer : public RequestProducer
{
public:
StlPlayer(const sc_core::sc_module_name &name,
const Configuration& config,
const std::string &pathToTrace,
const sc_core::sc_time &playerClk,
unsigned int maxPendingReadRequests,
unsigned int maxPendingWriteRequests,
TraceSetup& setup,
bool relative);
~StlPlayer() override;
void sendNextPayload() override;
uint64_t getNumberOfLines() const;
private:
struct LineContent
enum class TraceType
{
sc_core::sc_time sendingTime;
unsigned dataLength;
tlm::tlm_command command;
uint64_t address;
std::vector<unsigned char> data;
Absolute,
Relative,
};
void parseTraceFile();
std::vector<LineContent>::const_iterator swapBuffers();
StlPlayer(std::string_view tracePath,
unsigned int clkMhz,
unsigned int defaultDataLength,
TraceType traceType,
bool storageEnabled);
std::ifstream file;
uint64_t lineCnt = 0;
Request nextRequest() override;
sc_core::sc_time clkPeriod() override { return playerPeriod; }
uint64_t totalRequests() override { return numberOfLines; }
private:
void parseTraceFile();
std::vector<Request>::const_iterator swapBuffers();
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;
std::ifstream traceFile;
uint64_t currentLine = 0;
uint64_t numberOfLines = 0;
const sc_core::sc_time playerClk; // May be different from the memory clock!
std::array<std::shared_ptr<std::vector<Request>>, 2> lineBuffers;
std::shared_ptr<std::vector<Request>> parseBuffer;
std::shared_ptr<std::vector<Request>> readoutBuffer;
static constexpr unsigned lineBufferSize = 10000;
std::vector<LineContent>* currentBuffer;
std::vector<LineContent>* parseBuffer;
std::array<std::vector<LineContent>, 2> lineContents;
std::vector<LineContent>::const_iterator lineIterator;
std::vector<Request>::const_iterator readoutIt;
std::thread parserThread;
const bool relative;
};
#endif // STLPLAYER_H

View File

@@ -0,0 +1,53 @@
/*
* Copyright (c) 2023, Technische Universität Kaiserslautern
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* 3. Neither the name of the copyright holder nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER
* OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* Authors:
* Derek Christ
*/
#pragma once
#include <cstdint>
#include <systemc>
struct Request
{
enum class Command
{
Read,
Write,
Stop
} command;
uint64_t address;
std::size_t length;
sc_core::sc_time delay;
std::vector<unsigned char> data;
};

View File

@@ -0,0 +1,153 @@
/*
* Copyright (c) 2023, Technische Universität Kaiserslautern
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* 3. Neither the name of the copyright holder nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER
* OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* Authors:
* Derek Christ
*/
#include "RequestIssuer.h"
RequestIssuer::RequestIssuer(sc_core::sc_module_name const &name,
MemoryManager &memoryManager,
std::optional<unsigned int> maxPendingReadRequests,
std::optional<unsigned int> maxPendingWriteRequests,
std::function<Request()> nextRequest,
std::function<void()> transactionFinished,
std::function<void()> terminate)
: sc_module(name),
memoryManager(memoryManager),
maxPendingReadRequests(maxPendingReadRequests),
maxPendingWriteRequests(maxPendingWriteRequests),
nextRequest(std::move(nextRequest)),
transactionFinished(std::move(transactionFinished)),
terminate(std::move(terminate)),
payloadEventQueue(this, &RequestIssuer::peqCallback)
{
SC_THREAD(sendNextRequest);
iSocket.register_nb_transport_bw(this, &RequestIssuer::nb_transport_bw);
}
void RequestIssuer::sendNextRequest()
{
Request request = nextRequest();
if (request.command == Request::Command::Stop)
{
finished = true;
return;
}
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);
tlm::tlm_phase phase = tlm::BEGIN_REQ;
sc_core::sc_time delay = request.delay;
if (transactionsSent == 0)
delay = sc_core::SC_ZERO_TIME;
iSocket->nb_transport_fw(payload, phase, delay);
transactionInProgress = true;
if (request.command == Request::Command::Read)
pendingReadRequests++;
else if (request.command == Request::Command::Write)
pendingWriteRequests++;
transactionsSent++;
}
bool RequestIssuer::nextRequestSendable() const
{
// If either the maxPendingReadRequests or maxPendingWriteRequests
// limit is reached, do not send next payload.
if (maxPendingReadRequests.has_value() && pendingReadRequests >= maxPendingReadRequests.value())
return false;
if (maxPendingWriteRequests.has_value() &&
pendingWriteRequests >= maxPendingWriteRequests.value())
return false;
return true;
}
void RequestIssuer::peqCallback(tlm::tlm_generic_payload &payload, const tlm::tlm_phase &phase)
{
if (phase == tlm::END_REQ)
{
if (nextRequestSendable())
sendNextRequest();
else
transactionPostponed = true;
}
else if (phase == tlm::BEGIN_RESP)
{
tlm::tlm_phase phase = tlm::END_RESP;
sc_core::sc_time delay = sc_core::SC_ZERO_TIME;
iSocket->nb_transport_fw(payload, phase, delay);
payload.release();
transactionInProgress = false;
transactionFinished();
transactionsReceived++;
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;
}
// If all answers were received:
if (finished && transactionsSent == transactionsReceived)
terminate();
}
else
{
SC_REPORT_FATAL("TrafficInitiator", "PEQ was triggered with unknown phase");
}
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2015, Technische Universität Kaiserslautern
* Copyright (c) 2023, Technische Universität Kaiserslautern
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -30,70 +30,68 @@
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* Authors:
* Robert Gernhardt
* Matthias Jung
* Éder F. Zulian
* Felipe S. Prado
* Derek Christ
*/
#ifndef TRAFFICINITIATOR_H
#define TRAFFICINITIATOR_H
#pragma once
#include "simulator/TraceSetup.h"
#include "Request.h"
#include "simulator/MemoryManager.h"
#include "DRAMSys/configuration/Configuration.h"
#include "DRAMSys/common/DebugManager.h"
#include <deque>
#include <iostream>
#include <string>
#include <tlm>
#include <systemc>
#include <tlm_utils/simple_initiator_socket.h>
#include <tlm>
#include <tlm_utils/peq_with_cb_and_phase.h>
#include <tlm_utils/simple_initiator_socket.h>
class TrafficInitiator : public sc_core::sc_module
#include <optional>
class RequestIssuer : sc_core::sc_module
{
public:
tlm_utils::simple_initiator_socket<TrafficInitiator> iSocket;
TrafficInitiator(const sc_core::sc_module_name &name, const Configuration& config, TraceSetup& setup,
unsigned int maxPendingReadRequests, unsigned int maxPendingWriteRequests, unsigned int defaultDataLength);
SC_HAS_PROCESS(TrafficInitiator);
virtual void sendNextPayload() = 0;
tlm_utils::simple_initiator_socket<RequestIssuer> iSocket;
protected:
static sc_core::sc_time evaluateGeneratorClk(const DRAMSys::Config::TrafficInitiator &conf);
tlm_utils::peq_with_cb_and_phase<TrafficInitiator> payloadEventQueue;
void terminate();
TraceSetup& setup;
void sendToTarget(tlm::tlm_generic_payload &payload, const tlm::tlm_phase &phase,
const sc_core::sc_time &delay);
uint64_t transactionsReceived = 0;
uint64_t transactionsSent = 0;
unsigned int pendingReadRequests = 0;
unsigned int pendingWriteRequests = 0;
const unsigned int maxPendingReadRequests = 0;
const unsigned int maxPendingWriteRequests = 0;
bool payloadPostponed = false;
bool finished = false;
const unsigned int defaultDataLength;
const bool storageEnabled;
const bool simulationProgressBar;
// 0 disables the max value.
static constexpr unsigned int defaultMaxPendingWriteRequests = 0;
static constexpr unsigned int defaultMaxPendingReadRequests = 0;
RequestIssuer(sc_core::sc_module_name const &name,
MemoryManager &memoryManager,
std::optional<unsigned int> maxPendingReadRequests,
std::optional<unsigned int> maxPendingWriteRequests,
std::function<Request()> nextRequest,
std::function<void()> transactionFinished,
std::function<void()> terminate);
SC_HAS_PROCESS(RequestIssuer);
private:
tlm::tlm_sync_enum nb_transport_bw(tlm::tlm_generic_payload &payload, tlm::tlm_phase &phase,
sc_core::sc_time &bwDelay);
void peqCallback(tlm::tlm_generic_payload &payload, const tlm::tlm_phase &phase);
bool nextPayloadSendable() const;
};
tlm_utils::peq_with_cb_and_phase<RequestIssuer> payloadEventQueue;
MemoryManager &memoryManager;
#endif // TRAFFICINITIATOR_H
bool transactionInProgress = false;
bool transactionPostponed = false;
bool finished = false;
uint64_t transactionsSent = 0;
uint64_t transactionsReceived = 0;
unsigned int pendingReadRequests = 0;
unsigned int pendingWriteRequests = 0;
const std::optional<unsigned int> maxPendingReadRequests;
const std::optional<unsigned int> maxPendingWriteRequests;
unsigned int activeProducers = 0;
std::function<void()> transactionFinished;
std::function<void()> terminate;
std::function<Request()> nextRequest;
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);
};

View File

@@ -0,0 +1,49 @@
/*
* Copyright (c) 2023, Technische Universität Kaiserslautern
* 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 "Request.h"
class RequestProducer
{
public:
virtual ~RequestProducer() = default;
virtual Request nextRequest() = 0;
virtual uint64_t totalRequests() = 0;
virtual sc_core::sc_time clkPeriod() = 0;
virtual void reset(){};
};

View File

@@ -0,0 +1,75 @@
/*
* Copyright (c) 2023, Technische Universität Kaiserslautern
* 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:
* Matthias Jung
* Derek Christ
*/
#include "util.h"
#include <cmath>
#include <iomanip>
#include <iostream>
void loadBar(uint64_t x, uint64_t n, unsigned int w, unsigned int granularity)
{
if ((n < 100) || ((x != n) && (x % (n / 100 * granularity) != 0)))
return;
float ratio = x / (float)n;
unsigned int c = (ratio * w);
float rest = (ratio * w) - c;
std::cout << std::setw(3) << std::round(ratio * 100) << "% |";
for (unsigned int x = 0; x < c; x++)
std::cout << "";
if (rest >= 0 && rest < 0.125f && c != w)
std::cout << " ";
if (rest >= 0.125f && rest < 2 * 0.125f)
std::cout << "";
if (rest >= 2 * 0.125f && rest < 3 * 0.125f)
std::cout << "";
if (rest >= 3 * 0.125f && rest < 4 * 0.125f)
std::cout << "";
if (rest >= 4 * 0.125f && rest < 5 * 0.125f)
std::cout << "";
if (rest >= 5 * 0.125f && rest < 6 * 0.125f)
std::cout << "";
if (rest >= 6 * 0.125f && rest < 7 * 0.125f)
std::cout << "";
if (rest >= 7 * 0.125f && rest < 8 * 0.125f)
std::cout << "";
for (unsigned int x = c; x < (w - 1); x++)
std::cout << " ";
std::cout << "|\r" << std::flush;
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2017, Technische Universität Kaiserslautern
* Copyright (c) 2023, Technische Universität Kaiserslautern
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -34,43 +34,8 @@
* Derek Christ
*/
#ifndef TRACESETUP_H
#define TRACESETUP_H
#pragma once
#include "simulator/MemoryManager.h"
#include <cstdint>
#include "DRAMSys/config/DRAMSysConfiguration.h"
#include "DRAMSys/configuration/Configuration.h"
#include <vector>
#include <string>
#include <memory>
#include <tlm>
class TrafficInitiator;
class TraceSetup
{
public:
TraceSetup(const Configuration& config,
const DRAMSys::Config::TraceSetup &traceSetup,
const std::string &pathToResources,
std::vector<std::unique_ptr<TrafficInitiator>> &devices);
void trafficInitiatorTerminates();
void transactionFinished();
tlm::tlm_generic_payload& allocatePayload(unsigned dataLength);
tlm::tlm_generic_payload& allocatePayload();
private:
unsigned int numberOfTrafficInitiators;
uint64_t totalTransactions = 0;
uint64_t remainingTransactions;
unsigned int finishedTrafficInitiators = 0;
MemoryManager memoryManager;
unsigned defaultDataLength = 64;
static void loadBar(uint64_t x, uint64_t n, unsigned int w = 50, unsigned int granularity = 1);
};
#endif // TRACESETUP_H
void loadBar(uint64_t x, uint64_t n, unsigned int w = 50, unsigned int granularity = 1);

View File

@@ -35,6 +35,7 @@
*
* Authors:
* Thomas Psota
* Derek Christ
*/

View File

@@ -60,7 +60,7 @@ protected:
static DRAMSys::Config::TracePlayer createTracePlayer();
static DRAMSys::Config::TrafficGenerator createTraceGeneratorOneState();
static DRAMSys::Config::TrafficGeneratorStateMachine createTraceGeneratorMultipleStates();
static DRAMSys::Config::TraceHammer createTraceHammer();
static DRAMSys::Config::RowHammer createTraceHammer();
DRAMSys::Config::AddressMapping addressMapping{
{{{0, 1}},
@@ -109,7 +109,7 @@ protected:
DRAMSys::Config::TracePlayer tracePlayer;
DRAMSys::Config::TrafficGenerator traceGeneratorOneState;
DRAMSys::Config::TrafficGeneratorStateMachine traceGeneratorMultipleStates;
DRAMSys::Config::TraceHammer traceHammer;
DRAMSys::Config::RowHammer traceHammer;
DRAMSys::Config::TraceSetup traceSetup{{tracePlayer, traceGeneratorOneState, traceGeneratorMultipleStates, traceHammer}};
DRAMSys::Config::Configuration configuration{
@@ -183,7 +183,6 @@ DRAMSys::Config::TrafficGenerator ConfigurationTest::createTraceGeneratorOneStat
gen.addressIncrement = {};
gen.minAddress = {};
gen.maxAddress = {};
gen.clksPerRequest = {};
return gen;
}
@@ -203,7 +202,6 @@ DRAMSys::Config::TrafficGeneratorStateMachine ConfigurationTest::createTraceGene
state0.addressIncrement = 256;
state0.minAddress = {};
state0.maxAddress = 1024;
state0.clksPerRequest = {};
state0.id = 0;
DRAMSys::Config::TrafficGeneratorActiveState state1;
@@ -213,7 +211,6 @@ DRAMSys::Config::TrafficGeneratorStateMachine ConfigurationTest::createTraceGene
state1.addressIncrement = 512;
state1.minAddress = 1024;
state1.maxAddress = 2048;
state1.clksPerRequest = {};
state1.id = 1;
gen.states.push_back(state0);
@@ -226,9 +223,9 @@ DRAMSys::Config::TrafficGeneratorStateMachine ConfigurationTest::createTraceGene
return gen;
}
DRAMSys::Config::TraceHammer ConfigurationTest::createTraceHammer()
DRAMSys::Config::RowHammer ConfigurationTest::createTraceHammer()
{
DRAMSys::Config::TraceHammer hammer;
DRAMSys::Config::RowHammer hammer;
hammer.clkMhz = 100;
hammer.name = "MyTestHammer";