Introduce demonstrator for new simulator concept
This commit is contained in:
@@ -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)
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
6
src/configuration/Notes.txt
Normal file
6
src/configuration/Notes.txt
Normal 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
|
||||
@@ -54,4 +54,3 @@ target_link_libraries(DRAMSys
|
||||
)
|
||||
|
||||
build_source_group()
|
||||
diagnostics_print(DRAMSys)
|
||||
47
src/simulator/simulator/Initiator.h
Normal file
47
src/simulator/simulator/Initiator.h
Normal 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;
|
||||
};
|
||||
70
src/simulator/simulator/SimpleInitiator.h
Normal file
70
src/simulator/simulator/SimpleInitiator.h
Normal 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;
|
||||
};
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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(¬ifier->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;
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
79
src/simulator/simulator/generator/RandomProducer.cpp
Normal file
79
src/simulator/simulator/generator/RandomProducer.cpp
Normal 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;
|
||||
}
|
||||
69
src/simulator/simulator/generator/RandomProducer.h
Normal file
69
src/simulator/simulator/generator/RandomProducer.h
Normal 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;
|
||||
};
|
||||
82
src/simulator/simulator/generator/SequentialProducer.cpp
Normal file
82
src/simulator/simulator/generator/SequentialProducer.cpp
Normal 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;
|
||||
}
|
||||
75
src/simulator/simulator/generator/SequentialProducer.h
Normal file
75
src/simulator/simulator/generator/SequentialProducer.h
Normal 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;
|
||||
};
|
||||
238
src/simulator/simulator/generator/TrafficGenerator.cpp
Normal file
238
src/simulator/simulator/generator/TrafficGenerator.cpp
Normal 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;
|
||||
}
|
||||
82
src/simulator/simulator/generator/TrafficGenerator.h
Normal file
82
src/simulator/simulator/generator/TrafficGenerator.h
Normal 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;
|
||||
};
|
||||
41
src/simulator/simulator/generator/definitions.h
Normal file
41
src/simulator/simulator/generator/definitions.h
Normal 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;
|
||||
67
src/simulator/simulator/hammer/RowHammer.cpp
Normal file
67
src/simulator/simulator/hammer/RowHammer.cpp
Normal 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;
|
||||
}
|
||||
61
src/simulator/simulator/hammer/RowHammer.h
Normal file
61
src/simulator/simulator/hammer/RowHammer.h
Normal 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;
|
||||
};
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
221
src/simulator/simulator/player/StlPlayer.cpp
Normal file
221
src/simulator/simulator/player/StlPlayer.cpp
Normal 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();
|
||||
}
|
||||
@@ -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
|
||||
53
src/simulator/simulator/request/Request.h
Normal file
53
src/simulator/simulator/request/Request.h
Normal 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;
|
||||
};
|
||||
153
src/simulator/simulator/request/RequestIssuer.cpp
Normal file
153
src/simulator/simulator/request/RequestIssuer.cpp
Normal 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");
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
};
|
||||
49
src/simulator/simulator/request/RequestProducer.h
Normal file
49
src/simulator/simulator/request/RequestProducer.h
Normal 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(){};
|
||||
};
|
||||
75
src/simulator/simulator/util.cpp
Normal file
75
src/simulator/simulator/util.cpp
Normal 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;
|
||||
}
|
||||
@@ -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);
|
||||
@@ -35,6 +35,7 @@
|
||||
*
|
||||
* Authors:
|
||||
* Thomas Psota
|
||||
* Derek Christ
|
||||
*/
|
||||
|
||||
|
||||
|
||||
@@ -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";
|
||||
|
||||
Reference in New Issue
Block a user