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_SOURCE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/src")
|
||||||
set(DRAMSYS_LIBRARY_DIR "${CMAKE_CURRENT_SOURCE_DIR}/lib")
|
set(DRAMSYS_LIBRARY_DIR "${CMAKE_CURRENT_SOURCE_DIR}/lib")
|
||||||
set(DRAMSYS_TESTS_DIR "${CMAKE_CURRENT_SOURCE_DIR}/tests")
|
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")
|
set(DRAMSYS_EXTENSIONS_DIR "${CMAKE_CURRENT_SOURCE_DIR}/extensions")
|
||||||
|
|
||||||
### Build options ###
|
### Build options ###
|
||||||
@@ -137,6 +137,7 @@ FetchContent_Declare(
|
|||||||
GIT_REPOSITORY https://github.com/accellera-official/systemc.git
|
GIT_REPOSITORY https://github.com/accellera-official/systemc.git
|
||||||
GIT_TAG 2.3.4)
|
GIT_TAG 2.3.4)
|
||||||
|
|
||||||
|
set(DISABLE_COPYRIGHT_MESSAGE True)
|
||||||
FetchContent_MakeAvailable(systemc)
|
FetchContent_MakeAvailable(systemc)
|
||||||
set_target_properties(systemc PROPERTIES FOLDER lib)
|
set_target_properties(systemc PROPERTIES FOLDER lib)
|
||||||
|
|
||||||
|
|||||||
@@ -89,8 +89,6 @@ struct TrafficGeneratorActiveState
|
|||||||
std::optional<uint64_t> addressIncrement;
|
std::optional<uint64_t> addressIncrement;
|
||||||
std::optional<uint64_t> minAddress;
|
std::optional<uint64_t> minAddress;
|
||||||
std::optional<uint64_t> maxAddress;
|
std::optional<uint64_t> maxAddress;
|
||||||
std::optional<uint64_t> clksPerRequest;
|
|
||||||
std::optional<std::string> notify;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
NLOHMANN_JSONIFY_ALL_THINGS(TrafficGeneratorActiveState,
|
NLOHMANN_JSONIFY_ALL_THINGS(TrafficGeneratorActiveState,
|
||||||
@@ -100,9 +98,7 @@ NLOHMANN_JSONIFY_ALL_THINGS(TrafficGeneratorActiveState,
|
|||||||
addressDistribution,
|
addressDistribution,
|
||||||
addressIncrement,
|
addressIncrement,
|
||||||
minAddress,
|
minAddress,
|
||||||
maxAddress,
|
maxAddress)
|
||||||
clksPerRequest,
|
|
||||||
notify)
|
|
||||||
|
|
||||||
struct TrafficGeneratorIdleState
|
struct TrafficGeneratorIdleState
|
||||||
{
|
{
|
||||||
@@ -139,9 +135,6 @@ struct TrafficGenerator
|
|||||||
std::optional<uint64_t> addressIncrement;
|
std::optional<uint64_t> addressIncrement;
|
||||||
std::optional<uint64_t> minAddress;
|
std::optional<uint64_t> minAddress;
|
||||||
std::optional<uint64_t> maxAddress;
|
std::optional<uint64_t> maxAddress;
|
||||||
std::optional<uint64_t> clksPerRequest;
|
|
||||||
|
|
||||||
std::optional<std::string> idleUntil;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
NLOHMANN_JSONIFY_ALL_THINGS(TrafficGenerator,
|
NLOHMANN_JSONIFY_ALL_THINGS(TrafficGenerator,
|
||||||
@@ -157,9 +150,7 @@ NLOHMANN_JSONIFY_ALL_THINGS(TrafficGenerator,
|
|||||||
addressDistribution,
|
addressDistribution,
|
||||||
addressIncrement,
|
addressIncrement,
|
||||||
minAddress,
|
minAddress,
|
||||||
maxAddress,
|
maxAddress)
|
||||||
clksPerRequest,
|
|
||||||
idleUntil)
|
|
||||||
|
|
||||||
struct TrafficGeneratorStateMachine
|
struct TrafficGeneratorStateMachine
|
||||||
{
|
{
|
||||||
@@ -173,7 +164,6 @@ struct TrafficGeneratorStateMachine
|
|||||||
std::optional<unsigned> dataLength;
|
std::optional<unsigned> dataLength;
|
||||||
std::vector<std::variant<TrafficGeneratorActiveState, TrafficGeneratorIdleState>> states;
|
std::vector<std::variant<TrafficGeneratorActiveState, TrafficGeneratorIdleState>> states;
|
||||||
std::vector<TrafficGeneratorStateTransition> transitions;
|
std::vector<TrafficGeneratorStateTransition> transitions;
|
||||||
std::optional<std::string> idleUntil;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
NLOHMANN_JSONIFY_ALL_THINGS(TrafficGeneratorStateMachine,
|
NLOHMANN_JSONIFY_ALL_THINGS(TrafficGeneratorStateMachine,
|
||||||
@@ -185,10 +175,9 @@ NLOHMANN_JSONIFY_ALL_THINGS(TrafficGeneratorStateMachine,
|
|||||||
maxTransactions,
|
maxTransactions,
|
||||||
dataLength,
|
dataLength,
|
||||||
states,
|
states,
|
||||||
transitions,
|
transitions)
|
||||||
idleUntil)
|
|
||||||
|
|
||||||
struct TraceHammer
|
struct RowHammer
|
||||||
{
|
{
|
||||||
uint64_t clkMhz;
|
uint64_t clkMhz;
|
||||||
std::string name;
|
std::string name;
|
||||||
@@ -200,7 +189,7 @@ struct TraceHammer
|
|||||||
};
|
};
|
||||||
|
|
||||||
NLOHMANN_JSONIFY_ALL_THINGS(
|
NLOHMANN_JSONIFY_ALL_THINGS(
|
||||||
TraceHammer, clkMhz, name, maxPendingReadRequests, maxPendingWriteRequests, numRequests, rowIncrement)
|
RowHammer, clkMhz, name, maxPendingReadRequests, maxPendingWriteRequests, numRequests, rowIncrement)
|
||||||
|
|
||||||
struct TraceSetupConstants
|
struct TraceSetupConstants
|
||||||
{
|
{
|
||||||
@@ -209,7 +198,7 @@ struct TraceSetupConstants
|
|||||||
};
|
};
|
||||||
|
|
||||||
using TraceSetup = std::vector<
|
using TraceSetup = std::vector<
|
||||||
std::variant<TracePlayer, TrafficGenerator, TrafficGeneratorStateMachine, TraceHammer>>;
|
std::variant<TracePlayer, TrafficGenerator, TrafficGeneratorStateMachine, RowHammer>>;
|
||||||
|
|
||||||
} // namespace Configuration
|
} // 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()
|
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.
|
* All rights reserved.
|
||||||
*
|
*
|
||||||
* Redistribution and use in source and binary forms, with or without
|
* Redistribution and use in source and binary forms, with or without
|
||||||
@@ -30,105 +30,158 @@
|
|||||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
*
|
*
|
||||||
* Authors:
|
* Authors:
|
||||||
* Robert Gernhardt
|
|
||||||
* Matthias Jung
|
|
||||||
* Luiza Correa
|
|
||||||
* Lukas Steiner
|
|
||||||
* Derek Christ
|
* Derek Christ
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "simulator/TraceSetup.h"
|
#include "Initiator.h"
|
||||||
#include "simulator/TrafficInitiator.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/simulation/DRAMSysRecordable.h"
|
|
||||||
#include "DRAMSys/config/DRAMSysConfiguration.h"
|
|
||||||
|
|
||||||
#include <iostream>
|
|
||||||
#include <memory>
|
|
||||||
#include <string>
|
|
||||||
#include <vector>
|
|
||||||
#include <chrono>
|
|
||||||
#include <systemc>
|
#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)
|
static constexpr std::string_view TRACE_DIRECTORY = "traces";
|
||||||
{
|
|
||||||
return file.substr(0, file.find_last_of('/'));
|
|
||||||
}
|
|
||||||
|
|
||||||
int main(int argc, char **argv)
|
|
||||||
{
|
|
||||||
return sc_main(argc, argv);
|
|
||||||
}
|
|
||||||
|
|
||||||
int sc_main(int argc, char **argv)
|
int sc_main(int argc, char **argv)
|
||||||
{
|
{
|
||||||
sc_set_time_resolution(1, SC_PS);
|
std::filesystem::path resourceDirectory = "configs";
|
||||||
|
if (argc >= 3)
|
||||||
std::string resources;
|
|
||||||
std::string simulationJson;
|
|
||||||
// Run only with default config (ddr3-example.json):
|
|
||||||
if (argc == 1)
|
|
||||||
{
|
{
|
||||||
// Get path of resources:
|
resourceDirectory = argv[2];
|
||||||
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];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
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:
|
if (!configuration.tracesetup.has_value())
|
||||||
std::unique_ptr<DRAMSys::DRAMSys> dramSys;
|
SC_REPORT_FATAL("Simulator", "No traffic initiators specified");
|
||||||
|
|
||||||
if (configLib.simconfig.DatabaseRecording.value_or(false))
|
DRAMSys::DRAMSysRecordable dramSys("DRAMSys", configuration);
|
||||||
dramSys = std::make_unique<DRAMSys::DRAMSysRecordable>("DRAMSys", configLib);
|
|
||||||
else
|
|
||||||
dramSys = std::make_unique<DRAMSys::DRAMSys>("DRAMSys", configLib);
|
|
||||||
|
|
||||||
if (!configLib.tracesetup.has_value())
|
MemoryManager memoryManager(false);
|
||||||
SC_REPORT_FATAL("sc_main", "No trace setup section provided.");
|
|
||||||
|
|
||||||
// Instantiate STL Players:
|
std::vector<std::unique_ptr<Initiator>> initiators;
|
||||||
TraceSetup setup(dramSys->getConfig(), configLib.tracesetup.value(), resources, players);
|
|
||||||
|
|
||||||
// Bind STL Players with DRAMSys:
|
unsigned int terminatedInitiators = 0;
|
||||||
for (auto& player : players)
|
auto termianteInitiator = [&initiators, &terminatedInitiators]()
|
||||||
player->iSocket.bind(dramSys->tSocket);
|
{
|
||||||
|
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:
|
// Store the starting of the simulation in wall-clock time:
|
||||||
auto start = std::chrono::high_resolution_clock::now();
|
auto start = std::chrono::high_resolution_clock::now();
|
||||||
|
|
||||||
// Start SystemC Simulation:
|
// Start the SystemC simulation
|
||||||
sc_set_stop_mode(SC_STOP_FINISH_DELTA);
|
sc_set_stop_mode(sc_core::SC_STOP_FINISH_DELTA);
|
||||||
sc_start();
|
sc_core::sc_start();
|
||||||
|
|
||||||
if (!sc_end_of_simulation_invoked())
|
if (!sc_core::sc_end_of_simulation_invoked())
|
||||||
{
|
{
|
||||||
SC_REPORT_WARNING("sc_main", "Simulation stopped without explicit sc_stop()");
|
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();
|
auto finish = std::chrono::high_resolution_clock::now();
|
||||||
std::chrono::duration<double> elapsed = finish - start;
|
std::chrono::duration<double> elapsed = finish - start;
|
||||||
std::cout << "Simulation took " + std::to_string(elapsed.count()) + " seconds." << std::endl;
|
std::cout << "Simulation took " + std::to_string(elapsed.count()) + " seconds." << std::endl;
|
||||||
|
|
||||||
return 0;
|
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.
|
* All rights reserved.
|
||||||
*
|
*
|
||||||
* Redistribution and use in source and binary forms, with or without
|
* Redistribution and use in source and binary forms, with or without
|
||||||
@@ -38,65 +38,59 @@
|
|||||||
* Derek Christ
|
* Derek Christ
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef STLPLAYER_H
|
#pragma once
|
||||||
#define STLPLAYER_H
|
|
||||||
|
|
||||||
#include "simulator/TraceSetup.h"
|
#include "simulator/request/Request.h"
|
||||||
#include "simulator/TrafficInitiator.h"
|
#include "simulator/request/RequestProducer.h"
|
||||||
|
|
||||||
#include <sstream>
|
|
||||||
#include <vector>
|
|
||||||
#include <array>
|
|
||||||
#include <thread>
|
|
||||||
#include <fstream>
|
|
||||||
#include <systemc>
|
#include <systemc>
|
||||||
#include <tlm>
|
#include <tlm>
|
||||||
|
|
||||||
class StlPlayer : public TrafficInitiator
|
#include <fstream>
|
||||||
|
#include <memory>
|
||||||
|
#include <thread>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
class StlPlayer : public RequestProducer
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
StlPlayer(const sc_core::sc_module_name &name,
|
enum class TraceType
|
||||||
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
|
|
||||||
{
|
{
|
||||||
sc_core::sc_time sendingTime;
|
Absolute,
|
||||||
unsigned dataLength;
|
Relative,
|
||||||
tlm::tlm_command command;
|
|
||||||
uint64_t address;
|
|
||||||
std::vector<unsigned char> data;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
void parseTraceFile();
|
StlPlayer(std::string_view tracePath,
|
||||||
std::vector<LineContent>::const_iterator swapBuffers();
|
unsigned int clkMhz,
|
||||||
|
unsigned int defaultDataLength,
|
||||||
|
TraceType traceType,
|
||||||
|
bool storageEnabled);
|
||||||
|
|
||||||
std::ifstream file;
|
Request nextRequest() override;
|
||||||
uint64_t lineCnt = 0;
|
|
||||||
|
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;
|
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<Request>::const_iterator readoutIt;
|
||||||
|
|
||||||
std::vector<LineContent>* currentBuffer;
|
|
||||||
std::vector<LineContent>* parseBuffer;
|
|
||||||
std::array<std::vector<LineContent>, 2> lineContents;
|
|
||||||
std::vector<LineContent>::const_iterator lineIterator;
|
|
||||||
|
|
||||||
std::thread parserThread;
|
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.
|
* All rights reserved.
|
||||||
*
|
*
|
||||||
* Redistribution and use in source and binary forms, with or without
|
* Redistribution and use in source and binary forms, with or without
|
||||||
@@ -30,70 +30,68 @@
|
|||||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
*
|
*
|
||||||
* Authors:
|
* Authors:
|
||||||
* Robert Gernhardt
|
|
||||||
* Matthias Jung
|
|
||||||
* Éder F. Zulian
|
|
||||||
* Felipe S. Prado
|
|
||||||
* Derek Christ
|
* Derek Christ
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef TRAFFICINITIATOR_H
|
#pragma once
|
||||||
#define TRAFFICINITIATOR_H
|
|
||||||
|
|
||||||
#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 <systemc>
|
||||||
#include <tlm_utils/simple_initiator_socket.h>
|
#include <tlm>
|
||||||
#include <tlm_utils/peq_with_cb_and_phase.h>
|
#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:
|
public:
|
||||||
tlm_utils::simple_initiator_socket<TrafficInitiator> iSocket;
|
tlm_utils::simple_initiator_socket<RequestIssuer> 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;
|
|
||||||
|
|
||||||
protected:
|
RequestIssuer(sc_core::sc_module_name const &name,
|
||||||
static sc_core::sc_time evaluateGeneratorClk(const DRAMSys::Config::TrafficInitiator &conf);
|
MemoryManager &memoryManager,
|
||||||
|
std::optional<unsigned int> maxPendingReadRequests,
|
||||||
tlm_utils::peq_with_cb_and_phase<TrafficInitiator> payloadEventQueue;
|
std::optional<unsigned int> maxPendingWriteRequests,
|
||||||
void terminate();
|
std::function<Request()> nextRequest,
|
||||||
TraceSetup& setup;
|
std::function<void()> transactionFinished,
|
||||||
void sendToTarget(tlm::tlm_generic_payload &payload, const tlm::tlm_phase &phase,
|
std::function<void()> terminate);
|
||||||
const sc_core::sc_time &delay);
|
SC_HAS_PROCESS(RequestIssuer);
|
||||||
|
|
||||||
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;
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
tlm::tlm_sync_enum nb_transport_bw(tlm::tlm_generic_payload &payload, tlm::tlm_phase &phase,
|
tlm_utils::peq_with_cb_and_phase<RequestIssuer> payloadEventQueue;
|
||||||
sc_core::sc_time &bwDelay);
|
MemoryManager &memoryManager;
|
||||||
void peqCallback(tlm::tlm_generic_payload &payload, const tlm::tlm_phase &phase);
|
|
||||||
bool nextPayloadSendable() const;
|
|
||||||
};
|
|
||||||
|
|
||||||
#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.
|
* All rights reserved.
|
||||||
*
|
*
|
||||||
* Redistribution and use in source and binary forms, with or without
|
* Redistribution and use in source and binary forms, with or without
|
||||||
@@ -34,43 +34,8 @@
|
|||||||
* Derek Christ
|
* Derek Christ
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef TRACESETUP_H
|
#pragma once
|
||||||
#define TRACESETUP_H
|
|
||||||
|
|
||||||
#include "simulator/MemoryManager.h"
|
#include <cstdint>
|
||||||
|
|
||||||
#include "DRAMSys/config/DRAMSysConfiguration.h"
|
void loadBar(uint64_t x, uint64_t n, unsigned int w = 50, unsigned int granularity = 1);
|
||||||
#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
|
|
||||||
@@ -35,6 +35,7 @@
|
|||||||
*
|
*
|
||||||
* Authors:
|
* Authors:
|
||||||
* Thomas Psota
|
* Thomas Psota
|
||||||
|
* Derek Christ
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -60,7 +60,7 @@ protected:
|
|||||||
static DRAMSys::Config::TracePlayer createTracePlayer();
|
static DRAMSys::Config::TracePlayer createTracePlayer();
|
||||||
static DRAMSys::Config::TrafficGenerator createTraceGeneratorOneState();
|
static DRAMSys::Config::TrafficGenerator createTraceGeneratorOneState();
|
||||||
static DRAMSys::Config::TrafficGeneratorStateMachine createTraceGeneratorMultipleStates();
|
static DRAMSys::Config::TrafficGeneratorStateMachine createTraceGeneratorMultipleStates();
|
||||||
static DRAMSys::Config::TraceHammer createTraceHammer();
|
static DRAMSys::Config::RowHammer createTraceHammer();
|
||||||
|
|
||||||
DRAMSys::Config::AddressMapping addressMapping{
|
DRAMSys::Config::AddressMapping addressMapping{
|
||||||
{{{0, 1}},
|
{{{0, 1}},
|
||||||
@@ -109,7 +109,7 @@ protected:
|
|||||||
DRAMSys::Config::TracePlayer tracePlayer;
|
DRAMSys::Config::TracePlayer tracePlayer;
|
||||||
DRAMSys::Config::TrafficGenerator traceGeneratorOneState;
|
DRAMSys::Config::TrafficGenerator traceGeneratorOneState;
|
||||||
DRAMSys::Config::TrafficGeneratorStateMachine traceGeneratorMultipleStates;
|
DRAMSys::Config::TrafficGeneratorStateMachine traceGeneratorMultipleStates;
|
||||||
DRAMSys::Config::TraceHammer traceHammer;
|
DRAMSys::Config::RowHammer traceHammer;
|
||||||
DRAMSys::Config::TraceSetup traceSetup{{tracePlayer, traceGeneratorOneState, traceGeneratorMultipleStates, traceHammer}};
|
DRAMSys::Config::TraceSetup traceSetup{{tracePlayer, traceGeneratorOneState, traceGeneratorMultipleStates, traceHammer}};
|
||||||
|
|
||||||
DRAMSys::Config::Configuration configuration{
|
DRAMSys::Config::Configuration configuration{
|
||||||
@@ -183,7 +183,6 @@ DRAMSys::Config::TrafficGenerator ConfigurationTest::createTraceGeneratorOneStat
|
|||||||
gen.addressIncrement = {};
|
gen.addressIncrement = {};
|
||||||
gen.minAddress = {};
|
gen.minAddress = {};
|
||||||
gen.maxAddress = {};
|
gen.maxAddress = {};
|
||||||
gen.clksPerRequest = {};
|
|
||||||
|
|
||||||
return gen;
|
return gen;
|
||||||
}
|
}
|
||||||
@@ -203,7 +202,6 @@ DRAMSys::Config::TrafficGeneratorStateMachine ConfigurationTest::createTraceGene
|
|||||||
state0.addressIncrement = 256;
|
state0.addressIncrement = 256;
|
||||||
state0.minAddress = {};
|
state0.minAddress = {};
|
||||||
state0.maxAddress = 1024;
|
state0.maxAddress = 1024;
|
||||||
state0.clksPerRequest = {};
|
|
||||||
state0.id = 0;
|
state0.id = 0;
|
||||||
|
|
||||||
DRAMSys::Config::TrafficGeneratorActiveState state1;
|
DRAMSys::Config::TrafficGeneratorActiveState state1;
|
||||||
@@ -213,7 +211,6 @@ DRAMSys::Config::TrafficGeneratorStateMachine ConfigurationTest::createTraceGene
|
|||||||
state1.addressIncrement = 512;
|
state1.addressIncrement = 512;
|
||||||
state1.minAddress = 1024;
|
state1.minAddress = 1024;
|
||||||
state1.maxAddress = 2048;
|
state1.maxAddress = 2048;
|
||||||
state1.clksPerRequest = {};
|
|
||||||
state1.id = 1;
|
state1.id = 1;
|
||||||
|
|
||||||
gen.states.push_back(state0);
|
gen.states.push_back(state0);
|
||||||
@@ -226,9 +223,9 @@ DRAMSys::Config::TrafficGeneratorStateMachine ConfigurationTest::createTraceGene
|
|||||||
return gen;
|
return gen;
|
||||||
}
|
}
|
||||||
|
|
||||||
DRAMSys::Config::TraceHammer ConfigurationTest::createTraceHammer()
|
DRAMSys::Config::RowHammer ConfigurationTest::createTraceHammer()
|
||||||
{
|
{
|
||||||
DRAMSys::Config::TraceHammer hammer;
|
DRAMSys::Config::RowHammer hammer;
|
||||||
|
|
||||||
hammer.clkMhz = 100;
|
hammer.clkMhz = 100;
|
||||||
hammer.name = "MyTestHammer";
|
hammer.name = "MyTestHammer";
|
||||||
|
|||||||
Reference in New Issue
Block a user