Intensive refactor of DRAMSys project structure and CMakeFiles
This commit is contained in:
60
src/simulator/CMakeLists.txt
Normal file
60
src/simulator/CMakeLists.txt
Normal file
@@ -0,0 +1,60 @@
|
||||
# Copyright (c) 2020, 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
|
||||
# Lukas Steiner
|
||||
# Derek Christ
|
||||
# Thomas Psota
|
||||
|
||||
########################################
|
||||
### DRAMSys::simulator ###
|
||||
########################################
|
||||
|
||||
project(DRAMSys_Simulator)
|
||||
|
||||
file(GLOB_RECURSE SOURCE_FILES CONFIGURE_DEPENDS *.cpp)
|
||||
file(GLOB_RECURSE HEADER_FILES CONFIGURE_DEPENDS *.h;*.hpp)
|
||||
|
||||
add_executable(DRAMSys ${SOURCE_FILES} ${HEADER_FILES} )
|
||||
target_include_directories(DRAMSys PRIVATE ${CMAKE_CURRENT_SOURCE_DIR})
|
||||
|
||||
if(EXISTS ${CMAKE_CURRENT_LIST_DIR}/../library/src/simulation/DRAMSysRecordable.cpp)
|
||||
target_compile_definitions(DRAMSys PRIVATE RECORDING)
|
||||
endif()
|
||||
|
||||
target_link_libraries(DRAMSys
|
||||
PRIVATE
|
||||
Threads::Threads
|
||||
DRAMSys::libdramsys
|
||||
)
|
||||
|
||||
build_source_group()
|
||||
diagnostics_print(DRAMSys)
|
||||
142
src/simulator/main.cpp
Normal file
142
src/simulator/main.cpp
Normal file
@@ -0,0 +1,142 @@
|
||||
/*
|
||||
* 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
|
||||
* Luiza Correa
|
||||
* Lukas Steiner
|
||||
* Derek Christ
|
||||
*/
|
||||
|
||||
#include <iostream>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
#include <list>
|
||||
#include <chrono>
|
||||
#include <DRAMSys/config/DRAMSysConfiguration.h>
|
||||
#include <memory>
|
||||
#include <systemc>
|
||||
|
||||
#include <DRAMSys/simulation/DRAMSys.h>
|
||||
|
||||
#include <simulator/TraceSetup.h>
|
||||
#include <simulator/TrafficInitiator.h>
|
||||
|
||||
#ifdef RECORDING
|
||||
#include "simulation/DRAMSysRecordable.h"
|
||||
#endif
|
||||
|
||||
using namespace sc_core;
|
||||
|
||||
std::string pathOfFile(const std::string &file)
|
||||
{
|
||||
return file.substr(0, file.find_last_of('/'));
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
return sc_main(argc, argv);
|
||||
}
|
||||
|
||||
int sc_main(int argc, char **argv)
|
||||
{
|
||||
sc_set_time_resolution(1, SC_PS);
|
||||
|
||||
std::string resources;
|
||||
std::string simulationJson;
|
||||
// Run only with default config (ddr3-example.json):
|
||||
if (argc == 1)
|
||||
{
|
||||
// Get path of resources:
|
||||
resources = pathOfFile(argv[0])
|
||||
+ std::string("/../../DRAMSys/library/resources/");
|
||||
simulationJson = resources + "simulations/ddr5-example.json";
|
||||
}
|
||||
// Run with specific config but default resource folders:
|
||||
else if (argc == 2)
|
||||
{
|
||||
// Get path of resources:
|
||||
resources = pathOfFile(argv[0])
|
||||
+ std::string("/../../DRAMSys/library/resources/");
|
||||
simulationJson = argv[1];
|
||||
}
|
||||
// Run with spefific config and specific resource folder:
|
||||
else if (argc == 3)
|
||||
{
|
||||
simulationJson = argv[1];
|
||||
resources = argv[2];
|
||||
}
|
||||
|
||||
std::vector<std::unique_ptr<TrafficInitiator>> players;
|
||||
|
||||
DRAMSys::Config::Configuration configLib = DRAMSys::Config::from_path(simulationJson, resources);
|
||||
|
||||
// Instantiate DRAMSys:
|
||||
std::unique_ptr<DRAMSys::DRAMSys> dramSys;
|
||||
|
||||
#ifdef RECORDING
|
||||
if (configLib.simConfig.databaseRecording.value_or(false))
|
||||
dramSys = std::make_unique<DRAMSysRecordable>("DRAMSys", configLib);
|
||||
else
|
||||
#endif
|
||||
dramSys = std::make_unique<DRAMSys::DRAMSys>("DRAMSys", configLib);
|
||||
|
||||
if (!configLib.traceSetup.has_value())
|
||||
SC_REPORT_FATAL("sc_main", "No tracesetup section provided.");
|
||||
|
||||
// Instantiate STL Players:
|
||||
TraceSetup setup(dramSys->getConfig(), configLib.traceSetup.value(), resources, players);
|
||||
|
||||
// Bind STL Players with DRAMSys:
|
||||
for (auto& player : players)
|
||||
player->iSocket.bind(dramSys->tSocket);
|
||||
|
||||
// Store the starting of the simulation in wallclock time:
|
||||
auto start = std::chrono::high_resolution_clock::now();
|
||||
|
||||
// Start SystemC Simulation:
|
||||
sc_set_stop_mode(SC_STOP_FINISH_DELTA);
|
||||
sc_start();
|
||||
|
||||
if (!sc_end_of_simulation_invoked())
|
||||
{
|
||||
SC_REPORT_WARNING("sc_main", "Simulation stopped without explicit sc_stop()");
|
||||
sc_stop();
|
||||
}
|
||||
|
||||
auto finish = std::chrono::high_resolution_clock::now();
|
||||
std::chrono::duration<double> elapsed = finish - start;
|
||||
std::cout << "Simulation took " + std::to_string(elapsed.count()) + " seconds." << std::endl;
|
||||
return 0;
|
||||
}
|
||||
238
src/simulator/simulator/ExampleInitiator.h
Normal file
238
src/simulator/simulator/ExampleInitiator.h
Normal file
@@ -0,0 +1,238 @@
|
||||
/*
|
||||
* Copyright (c) 2016, 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:
|
||||
* Eder F. Zulian
|
||||
*/
|
||||
|
||||
#ifndef EXAMPLEINITIATOR_H
|
||||
#define EXAMPLEINITIATOR_H
|
||||
|
||||
#include <cstdlib>
|
||||
#include <iostream>
|
||||
|
||||
#include <systemc>
|
||||
#include "MemoryManager.h"
|
||||
#include "common/dramExtensions.h"
|
||||
#include "TracePlayer.h"
|
||||
|
||||
struct ExampleInitiator : sc_core::sc_module
|
||||
{
|
||||
// TLM-2 socket, defaults to 32-bits wide, base protocol
|
||||
tlm_utils::simple_initiator_socket<ExampleInitiator> socket;
|
||||
|
||||
SC_CTOR(ExampleInitiator)
|
||||
: socket("socket"),
|
||||
request_in_progress(nullptr),
|
||||
m_peq(this, &ExampleInitiator::peq_cb)
|
||||
{
|
||||
socket.register_nb_transport_bw(this, &ExampleInitiator::nb_transport_bw);
|
||||
SC_THREAD(thread_process);
|
||||
}
|
||||
|
||||
void thread_process()
|
||||
{
|
||||
tlm::tlm_generic_payload *trans;
|
||||
tlm::tlm_phase phase;
|
||||
sc_core::sc_time delay;
|
||||
|
||||
dump_mem();
|
||||
init_mem();
|
||||
dump_mem();
|
||||
|
||||
for (unsigned char &i : data)
|
||||
i = 0x55;
|
||||
|
||||
// Generate 2 write transactions
|
||||
for (int i = 0; i < 2; i++) {
|
||||
int adr = i * 64;
|
||||
|
||||
tlm::tlm_command cmd = tlm::TLM_WRITE_COMMAND;
|
||||
|
||||
// Grab a new transaction from the memory manager
|
||||
trans = m_mm.allocate();
|
||||
trans->acquire();
|
||||
|
||||
trans->set_command(cmd);
|
||||
trans->set_address(adr);
|
||||
trans->set_data_ptr(reinterpret_cast<unsigned char *>(&data[0]));
|
||||
trans->set_data_length(64);
|
||||
trans->set_streaming_width(4);
|
||||
trans->set_byte_enable_ptr(nullptr);
|
||||
trans->set_dmi_allowed(false);
|
||||
trans->set_response_status(tlm::TLM_INCOMPLETE_RESPONSE);
|
||||
|
||||
// ExampleInitiator must honor BEGIN_REQ/END_REQ exclusion rule
|
||||
if (request_in_progress)
|
||||
wait(end_request_event);
|
||||
request_in_progress = trans;
|
||||
phase = tlm::BEGIN_REQ;
|
||||
|
||||
// Timing annotation models processing time of initiator prior to call
|
||||
delay = sc_core::sc_time(100000, sc_core::SC_PS);
|
||||
|
||||
std::cout << "Address " << std::hex << adr << " new, cmd=" << (cmd ? "write" : "read")
|
||||
<< ", data=" << std::hex << data[0] << " at time " << sc_core::sc_time_stamp()
|
||||
<< " in " << name() << std::endl;
|
||||
|
||||
GenerationExtension *genExtension = new GenerationExtension(sc_core::sc_time_stamp());
|
||||
trans->set_auto_extension(genExtension);
|
||||
|
||||
|
||||
// Non-blocking transport call on the forward path
|
||||
tlm::tlm_sync_enum status;
|
||||
status = socket->nb_transport_fw( *trans, phase, delay );
|
||||
|
||||
// Check value returned from nb_transport_fw
|
||||
if (status == tlm::TLM_UPDATED) {
|
||||
// The timing annotation must be honored
|
||||
m_peq.notify( *trans, phase, delay );
|
||||
} else if (status == tlm::TLM_COMPLETED) {
|
||||
// The completion of the transaction necessarily ends the BEGIN_REQ phase
|
||||
request_in_progress = nullptr;
|
||||
|
||||
// The target has terminated the transaction
|
||||
check_transaction( *trans );
|
||||
|
||||
// Allow the memory manager to free the transaction object
|
||||
trans->release();
|
||||
}
|
||||
|
||||
sc_core::wait(sc_core::sc_time(500, sc_core::SC_NS));
|
||||
|
||||
dump_mem();
|
||||
}
|
||||
|
||||
sc_core::wait(sc_core::sc_time(500, sc_core::SC_NS));
|
||||
sc_core::sc_stop();
|
||||
}
|
||||
|
||||
static void init_mem()
|
||||
{
|
||||
unsigned char buffer[64];
|
||||
for (unsigned char &i : buffer)
|
||||
i = 0xff;
|
||||
|
||||
for (int addr = 0; addr < 128; addr += 64) {
|
||||
tlm::tlm_generic_payload trans;
|
||||
trans.set_command( tlm::TLM_WRITE_COMMAND );
|
||||
trans.set_address( addr );
|
||||
trans.set_data_ptr( buffer );
|
||||
trans.set_data_length( 64 );
|
||||
|
||||
socket->transport_dbg( trans );
|
||||
}
|
||||
}
|
||||
|
||||
static void dump_mem()
|
||||
{
|
||||
for (int addr = 0; addr < 128; addr += 64) {
|
||||
unsigned char buffer[64];
|
||||
tlm::tlm_generic_payload trans;
|
||||
trans.set_command( tlm::TLM_READ_COMMAND );
|
||||
trans.set_address( addr );
|
||||
trans.set_data_ptr( buffer );
|
||||
trans.set_data_length( 64 );
|
||||
|
||||
socket->transport_dbg( trans );
|
||||
|
||||
std::cout << "\nMemory dump\n";
|
||||
for (int i = 0; i < 64; i++)
|
||||
std::cout << "mem[" << addr + i << "] = " << std::hex << (int)buffer[i] << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
// TLM-2 backward non-blocking transport method
|
||||
|
||||
virtual tlm::tlm_sync_enum nb_transport_bw( tlm::tlm_generic_payload &trans,
|
||||
tlm::tlm_phase &phase, sc_core::sc_time &delay )
|
||||
{
|
||||
m_peq.notify( trans, phase, delay );
|
||||
return tlm::TLM_ACCEPTED;
|
||||
}
|
||||
|
||||
// Payload event queue callback to handle transactions from target
|
||||
// Transaction could have arrived through return path or backward path
|
||||
|
||||
void peq_cb(tlm::tlm_generic_payload &trans, const tlm::tlm_phase &phase)
|
||||
{
|
||||
if (phase == tlm::END_REQ || (&trans == request_in_progress
|
||||
&& phase == tlm::BEGIN_RESP)) {
|
||||
// The end of the BEGIN_REQ phase
|
||||
request_in_progress = nullptr;
|
||||
end_request_event.notify();
|
||||
} else if (phase == tlm::BEGIN_REQ || phase == tlm::END_RESP)
|
||||
SC_REPORT_FATAL("TLM-2", "Illegal transaction phase received by initiator");
|
||||
|
||||
if (phase == tlm::BEGIN_RESP) {
|
||||
check_transaction( trans );
|
||||
|
||||
// Send final phase transition to target
|
||||
tlm::tlm_phase fw_phase = tlm::END_RESP;
|
||||
sc_core::sc_time delay = sc_core::sc_time(60000, sc_core::SC_PS);
|
||||
socket->nb_transport_fw( trans, fw_phase, delay );
|
||||
// Ignore return value
|
||||
|
||||
// Allow the memory manager to free the transaction object
|
||||
trans.release();
|
||||
}
|
||||
}
|
||||
|
||||
// Called on receiving BEGIN_RESP or TLM_COMPLETED
|
||||
void check_transaction(tlm::tlm_generic_payload &trans)
|
||||
{
|
||||
if ( trans.is_response_error() ) {
|
||||
char txt[100];
|
||||
sprintf(txt, "Transaction returned with error, response status = %s",
|
||||
trans.get_response_string().c_str());
|
||||
SC_REPORT_ERROR("TLM-2", txt);
|
||||
}
|
||||
|
||||
tlm::tlm_command cmd = trans.get_command();
|
||||
uint64_t adr = trans.get_address();
|
||||
int *ptr = reinterpret_cast<int *>( trans.get_data_ptr() );
|
||||
|
||||
std::cout << std::hex << adr << " check, cmd=" << (cmd ? "write" : "read")
|
||||
<< ", data=" << std::hex << *ptr << " at time " << sc_core::sc_time_stamp()
|
||||
<< " in " << sc_core::name() << std::endl;
|
||||
|
||||
if (cmd == tlm::TLM_READ_COMMAND)
|
||||
assert( *ptr == -int(adr) );
|
||||
}
|
||||
|
||||
MemoryManager m_mm;
|
||||
unsigned char data[64];
|
||||
tlm::tlm_generic_payload *request_in_progress;
|
||||
sc_core::sc_event end_request_event;
|
||||
tlm_utils::peq_with_cb_and_phase<ExampleInitiator> m_peq;
|
||||
};
|
||||
|
||||
#endif // EXAMPLEINITIATOR_H
|
||||
238
src/simulator/simulator/LengthConverter.cpp
Normal file
238
src/simulator/simulator/LengthConverter.cpp
Normal file
@@ -0,0 +1,238 @@
|
||||
/*
|
||||
* Copyright (c) 2022, 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:
|
||||
* Lukas Steiner
|
||||
*/
|
||||
|
||||
#include "LengthConverter.h"
|
||||
|
||||
using namespace sc_core;
|
||||
using namespace tlm;
|
||||
|
||||
// TODO: return status, TLM_INCOMPLETE_RESPONSE, acquire + release
|
||||
|
||||
LengthConverter::LengthConverter(const sc_module_name &name, unsigned maxOutputLength, bool storageEnabled) :
|
||||
sc_module(name), payloadEventQueue(this, &LengthConverter::peqCallback), storageEnabled(storageEnabled),
|
||||
memoryManager(storageEnabled, maxOutputLength), maxOutputLength(maxOutputLength)
|
||||
{
|
||||
iSocket.register_nb_transport_bw(this, &LengthConverter::nb_transport_bw);
|
||||
tSocket.register_nb_transport_fw(this, &LengthConverter::nb_transport_fw);
|
||||
tSocket.register_transport_dbg(this, &LengthConverter::transport_dbg);
|
||||
}
|
||||
|
||||
tlm_sync_enum LengthConverter::nb_transport_fw(tlm_generic_payload& trans,
|
||||
tlm_phase& phase, sc_time& fwDelay)
|
||||
{
|
||||
if (phase == BEGIN_REQ)
|
||||
trans.acquire();
|
||||
|
||||
payloadEventQueue.notify(trans, phase, fwDelay);
|
||||
return TLM_ACCEPTED;
|
||||
}
|
||||
|
||||
tlm_sync_enum LengthConverter::nb_transport_bw(tlm_generic_payload &payload,
|
||||
tlm_phase &phase, sc_time &bwDelay)
|
||||
{
|
||||
payloadEventQueue.notify(payload, phase, bwDelay);
|
||||
return TLM_ACCEPTED;
|
||||
}
|
||||
|
||||
unsigned int LengthConverter::transport_dbg(tlm_generic_payload &trans)
|
||||
{
|
||||
return iSocket->transport_dbg(trans);
|
||||
}
|
||||
|
||||
void LengthConverter::peqCallback(tlm_generic_payload &cbTrans, const tlm_phase &cbPhase)
|
||||
{
|
||||
if (cbPhase == BEGIN_REQ) // from initiator
|
||||
{
|
||||
if (cbTrans.get_data_length() <= maxOutputLength)
|
||||
{
|
||||
// pipe transaction through
|
||||
tlm_phase fwPhase = BEGIN_REQ;
|
||||
sc_time fwDelay = SC_ZERO_TIME;
|
||||
tlm_sync_enum returnStatus = iSocket->nb_transport_fw(cbTrans, fwPhase, fwDelay);
|
||||
// TODO: END_REQ/BEGIN_RESP shortcut
|
||||
}
|
||||
else
|
||||
{
|
||||
// split transaction up into multiple sub-transactions
|
||||
createChildTranses(&cbTrans);
|
||||
tlm_generic_payload* firstChildTrans = cbTrans.get_extension<ParentExtension>()->getNextChildTrans();
|
||||
tlm_phase fwPhase = BEGIN_REQ;
|
||||
sc_time fwDelay = SC_ZERO_TIME;
|
||||
tlm_sync_enum returnStatus = iSocket->nb_transport_fw(*firstChildTrans, fwPhase, fwDelay);
|
||||
}
|
||||
}
|
||||
else if (cbPhase == END_REQ)
|
||||
{
|
||||
if (ChildExtension::isChildTrans(&cbTrans))
|
||||
{
|
||||
tlm_generic_payload* nextChildTrans = cbTrans.get_extension<ChildExtension>()->getNextChildTrans();
|
||||
if (nextChildTrans != nullptr)
|
||||
{
|
||||
tlm_phase fwPhase = BEGIN_REQ;
|
||||
//sc_time fwDelay = SC_ZERO_TIME;
|
||||
sc_time fwDelay = sc_time(1, SC_NS);
|
||||
tlm_sync_enum returnStatus = iSocket->nb_transport_fw(*nextChildTrans, fwPhase, fwDelay);
|
||||
}
|
||||
else
|
||||
{
|
||||
tlm_generic_payload* parentTrans = cbTrans.get_extension<ChildExtension>()->getParentTrans();
|
||||
tlm_phase bwPhase = END_REQ;
|
||||
sc_time bwDelay = SC_ZERO_TIME;
|
||||
tlm_sync_enum returnStatus = tSocket->nb_transport_bw(*parentTrans, bwPhase, bwDelay);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
tlm_phase bwPhase = END_REQ;
|
||||
sc_time bwDelay = SC_ZERO_TIME;
|
||||
tlm_sync_enum returnStatus = tSocket->nb_transport_bw(cbTrans, bwPhase, bwDelay);
|
||||
}
|
||||
}
|
||||
else if (cbPhase == BEGIN_RESP)
|
||||
{
|
||||
if (ChildExtension::isChildTrans(&cbTrans))
|
||||
{
|
||||
{
|
||||
tlm_phase fwPhase = END_RESP;
|
||||
sc_time fwDelay = SC_ZERO_TIME;
|
||||
tlm_sync_enum returnStatus = iSocket->nb_transport_fw(cbTrans, fwPhase, fwDelay);
|
||||
}
|
||||
|
||||
if (storageEnabled && cbTrans.is_read())
|
||||
{
|
||||
tlm_generic_payload* parentTrans = cbTrans.get_extension<ChildExtension>()->getParentTrans();
|
||||
std::copy(cbTrans.get_data_ptr(), cbTrans.get_data_ptr() + maxOutputLength,
|
||||
parentTrans->get_data_ptr() + (cbTrans.get_address() - parentTrans->get_address()));
|
||||
}
|
||||
|
||||
if (cbTrans.get_extension<ChildExtension>()->notifyChildTransCompletion()) // all children finished
|
||||
{
|
||||
// BEGIN_RESP über tSocket
|
||||
tlm_generic_payload* parentTrans = cbTrans.get_extension<ChildExtension>()->getParentTrans();
|
||||
tlm_phase bwPhase = BEGIN_RESP;
|
||||
sc_time bwDelay = SC_ZERO_TIME;
|
||||
parentTrans->set_response_status(tlm::TLM_OK_RESPONSE);
|
||||
tlm_sync_enum returnStatus = tSocket->nb_transport_bw(*parentTrans, bwPhase, bwDelay);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
tlm_phase bwPhase = BEGIN_RESP;
|
||||
sc_time bwDelay = SC_ZERO_TIME;
|
||||
cbTrans.set_response_status(tlm::TLM_OK_RESPONSE);
|
||||
tlm_sync_enum returnStatus = tSocket->nb_transport_bw(cbTrans, bwPhase, bwDelay);
|
||||
}
|
||||
}
|
||||
else if (cbPhase == END_RESP)
|
||||
{
|
||||
if (ParentExtension::isParentTrans(&cbTrans))
|
||||
{
|
||||
cbTrans.get_extension<ParentExtension>()->releaseChildTranses();
|
||||
}
|
||||
else
|
||||
{
|
||||
tlm_phase fwPhase = END_RESP;
|
||||
sc_time fwDelay = SC_ZERO_TIME;
|
||||
tlm_sync_enum returnStatus = iSocket->nb_transport_fw(cbTrans, fwPhase, fwDelay);
|
||||
}
|
||||
cbTrans.release();
|
||||
}
|
||||
else
|
||||
SC_REPORT_FATAL(0, "Payload event queue in LengthConverter was triggered with unknown phase");
|
||||
}
|
||||
|
||||
void LengthConverter::createChildTranses(tlm_generic_payload* parentTrans)
|
||||
{
|
||||
unsigned numChildTranses = parentTrans->get_data_length() / maxOutputLength;
|
||||
std::vector<tlm_generic_payload*> childTranses;
|
||||
|
||||
for (unsigned childId = 0; childId < numChildTranses; childId++)
|
||||
{
|
||||
tlm_generic_payload* childTrans = memoryManager.allocate();
|
||||
childTrans->acquire();
|
||||
childTrans->set_command(parentTrans->get_command());
|
||||
childTrans->set_address(parentTrans->get_address() + childId * maxOutputLength);
|
||||
childTrans->set_data_length(maxOutputLength);
|
||||
if (storageEnabled && parentTrans->is_write())
|
||||
std::copy(parentTrans->get_data_ptr() + childId * maxOutputLength, parentTrans->get_data_ptr() +
|
||||
(childId + 1) * maxOutputLength, childTrans->get_data_ptr());
|
||||
ChildExtension::setExtension(childTrans, parentTrans);
|
||||
childTranses.push_back(childTrans);
|
||||
}
|
||||
ParentExtension::setExtension(parentTrans, std::move(childTranses));
|
||||
}
|
||||
|
||||
LengthConverter::MemoryManager::MemoryManager(bool storageEnabled, unsigned maxDataLength)
|
||||
: storageEnabled(storageEnabled), maxDataLength(maxDataLength)
|
||||
{}
|
||||
|
||||
LengthConverter::MemoryManager::~MemoryManager()
|
||||
{
|
||||
while (!freePayloads.empty())
|
||||
{
|
||||
tlm_generic_payload* payload = freePayloads.top();
|
||||
if (storageEnabled)
|
||||
delete[] payload->get_data_ptr();
|
||||
payload->reset();
|
||||
delete payload;
|
||||
freePayloads.pop();
|
||||
}
|
||||
}
|
||||
|
||||
tlm_generic_payload* LengthConverter::MemoryManager::allocate()
|
||||
{
|
||||
if (freePayloads.empty())
|
||||
{
|
||||
auto* payload = new tlm_generic_payload(this);
|
||||
|
||||
if (storageEnabled)
|
||||
{
|
||||
auto* data = new unsigned char[maxDataLength];
|
||||
payload->set_data_ptr(data);
|
||||
}
|
||||
return payload;
|
||||
}
|
||||
else
|
||||
{
|
||||
tlm_generic_payload* result = freePayloads.top();
|
||||
freePayloads.pop();
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
void LengthConverter::MemoryManager::free(tlm_generic_payload* payload)
|
||||
{
|
||||
freePayloads.push(payload);
|
||||
}
|
||||
233
src/simulator/simulator/LengthConverter.h
Normal file
233
src/simulator/simulator/LengthConverter.h
Normal file
@@ -0,0 +1,233 @@
|
||||
/*
|
||||
* Copyright (c) 2022, 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:
|
||||
* Lukas Steiner
|
||||
*/
|
||||
|
||||
#ifndef LENGTHCONVERTER_H
|
||||
#define LENGTHCONVERTER_H
|
||||
|
||||
#include <iostream>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
#include <queue>
|
||||
#include <set>
|
||||
#include <unordered_map>
|
||||
#include <stack>
|
||||
|
||||
#include <tlm>
|
||||
#include <systemc>
|
||||
#include <tlm_utils/simple_initiator_socket.h>
|
||||
#include <tlm_utils/simple_target_socket.h>
|
||||
#include <tlm_utils/peq_with_cb_and_phase.h>
|
||||
|
||||
//TLM_DECLARE_EXTENDED_PHASE(REQ_ARBITRATION);
|
||||
//TLM_DECLARE_EXTENDED_PHASE(RESP_ARBITRATION);
|
||||
|
||||
class LengthConverter : public sc_core::sc_module
|
||||
{
|
||||
public:
|
||||
tlm_utils::simple_initiator_socket<LengthConverter> iSocket;
|
||||
tlm_utils::simple_target_socket<LengthConverter> tSocket;
|
||||
|
||||
LengthConverter(const sc_core::sc_module_name& name, unsigned maxOutputLength, bool storageEnabled);
|
||||
SC_HAS_PROCESS(LengthConverter);
|
||||
|
||||
private:
|
||||
tlm_utils::peq_with_cb_and_phase<LengthConverter> payloadEventQueue;
|
||||
void peqCallback(tlm::tlm_generic_payload &payload, const tlm::tlm_phase &phase);
|
||||
|
||||
//std::vector<bool> tSocketIsBusy;
|
||||
//std::vector<bool> iSocketIsBusy;
|
||||
|
||||
const unsigned maxOutputLength;
|
||||
const bool storageEnabled;
|
||||
|
||||
void createChildTranses(tlm::tlm_generic_payload* parentTrans);
|
||||
|
||||
//std::uint64_t getTargetAddress(std::uint64_t address) const;
|
||||
//int getISocketId(std::uint64_t address) const;
|
||||
|
||||
//std::vector<std::queue<tlm::tlm_generic_payload *>> pendingRequests;
|
||||
|
||||
tlm::tlm_sync_enum nb_transport_fw(tlm::tlm_generic_payload &trans, tlm::tlm_phase &phase,
|
||||
sc_core::sc_time &fwDelay);
|
||||
tlm::tlm_sync_enum nb_transport_bw(tlm::tlm_generic_payload &payload, tlm::tlm_phase &phase,
|
||||
sc_core::sc_time &bwDelay);
|
||||
unsigned int transport_dbg(tlm::tlm_generic_payload &trans);
|
||||
|
||||
class MemoryManager : public tlm::tlm_mm_interface
|
||||
{
|
||||
public:
|
||||
MemoryManager(bool storageEnabled, unsigned maxDataLength);
|
||||
~MemoryManager() override;
|
||||
tlm::tlm_generic_payload* allocate();
|
||||
void free(tlm::tlm_generic_payload* payload) override;
|
||||
|
||||
private:
|
||||
std::stack<tlm::tlm_generic_payload*> freePayloads;
|
||||
bool storageEnabled = false;
|
||||
unsigned maxDataLength;
|
||||
} memoryManager;
|
||||
|
||||
class ChildExtension : public tlm::tlm_extension<ChildExtension>
|
||||
{
|
||||
private:
|
||||
tlm::tlm_generic_payload* parentTrans;
|
||||
explicit ChildExtension(tlm::tlm_generic_payload* parentTrans) : parentTrans(parentTrans) {}
|
||||
|
||||
public:
|
||||
//ChildExtension() = delete;
|
||||
|
||||
tlm_extension_base* clone() const override
|
||||
{
|
||||
return new ChildExtension(parentTrans);
|
||||
}
|
||||
|
||||
void copy_from(tlm_extension_base const &ext) override
|
||||
{
|
||||
const auto& cpyFrom = dynamic_cast<const ChildExtension&>(ext);
|
||||
parentTrans = cpyFrom.parentTrans;
|
||||
}
|
||||
|
||||
tlm::tlm_generic_payload* getParentTrans()
|
||||
{
|
||||
return parentTrans;
|
||||
}
|
||||
|
||||
static void setExtension(tlm::tlm_generic_payload* childTrans, tlm::tlm_generic_payload* parentTrans)
|
||||
{
|
||||
auto *extension = childTrans->get_extension<ChildExtension>();
|
||||
|
||||
if (extension != nullptr)
|
||||
{
|
||||
extension->parentTrans = parentTrans;
|
||||
}
|
||||
else
|
||||
{
|
||||
extension = new ChildExtension(parentTrans);
|
||||
childTrans->set_auto_extension(extension);
|
||||
}
|
||||
}
|
||||
|
||||
static bool isChildTrans(const tlm::tlm_generic_payload* trans)
|
||||
{
|
||||
if (trans->get_extension<ChildExtension>() != nullptr)
|
||||
return true;
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
tlm::tlm_generic_payload* getNextChildTrans()
|
||||
{
|
||||
return parentTrans->get_extension<ParentExtension>()->getNextChildTrans();
|
||||
}
|
||||
|
||||
bool notifyChildTransCompletion()
|
||||
{
|
||||
return parentTrans->get_extension<ParentExtension>()->notifyChildTransCompletion();
|
||||
}
|
||||
};
|
||||
|
||||
class ParentExtension : public tlm::tlm_extension<ParentExtension>
|
||||
{
|
||||
private:
|
||||
std::vector<tlm::tlm_generic_payload*> childTranses;
|
||||
unsigned nextEndReqChildId = 0;
|
||||
unsigned completedChildTranses = 0;
|
||||
explicit ParentExtension(std::vector<tlm::tlm_generic_payload*> _childTranses)
|
||||
: childTranses(std::move(_childTranses)) {}
|
||||
|
||||
public:
|
||||
ParentExtension() = delete;
|
||||
|
||||
tlm_extension_base* clone() const override
|
||||
{
|
||||
return new ParentExtension(childTranses);
|
||||
}
|
||||
|
||||
void copy_from(tlm_extension_base const &ext) override
|
||||
{
|
||||
const auto& cpyFrom = dynamic_cast<const ParentExtension&>(ext);
|
||||
childTranses = cpyFrom.childTranses;
|
||||
}
|
||||
|
||||
static bool isParentTrans(const tlm::tlm_generic_payload* trans)
|
||||
{
|
||||
auto* extension = trans->get_extension<ParentExtension>();
|
||||
if (extension != nullptr)
|
||||
return !extension->childTranses.empty();
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
static void setExtension(tlm::tlm_generic_payload* parentTrans, std::vector<tlm::tlm_generic_payload*> childTranses)
|
||||
{
|
||||
auto* extension = parentTrans->get_extension<ParentExtension>();
|
||||
|
||||
if (extension != nullptr)
|
||||
{
|
||||
extension->childTranses = std::move(childTranses);
|
||||
extension->nextEndReqChildId = 0;
|
||||
extension->completedChildTranses = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
extension = new ParentExtension(std::move(childTranses));
|
||||
parentTrans->set_auto_extension(extension);
|
||||
}
|
||||
}
|
||||
|
||||
tlm::tlm_generic_payload* getNextChildTrans()
|
||||
{
|
||||
if (nextEndReqChildId < childTranses.size())
|
||||
return childTranses[nextEndReqChildId++];
|
||||
else
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
bool notifyChildTransCompletion()
|
||||
{
|
||||
completedChildTranses++;
|
||||
return completedChildTranses == childTranses.size();
|
||||
}
|
||||
|
||||
void releaseChildTranses()
|
||||
{
|
||||
std::for_each(childTranses.begin(), childTranses.end(),
|
||||
[](tlm::tlm_generic_payload* childTrans){childTrans->release();});
|
||||
childTranses.clear();
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
#endif // LENGTHCONVERTER_H
|
||||
98
src/simulator/simulator/MemoryManager.cpp
Normal file
98
src/simulator/simulator/MemoryManager.cpp
Normal file
@@ -0,0 +1,98 @@
|
||||
/*
|
||||
* 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
|
||||
*/
|
||||
|
||||
#include "MemoryManager.h"
|
||||
|
||||
#include <DRAMSys/common/DebugManager.h>
|
||||
#include <DRAMSys/configuration/Configuration.h>
|
||||
|
||||
using namespace tlm;
|
||||
|
||||
MemoryManager::MemoryManager(bool storageEnabled)
|
||||
: numberOfAllocations(0), numberOfFrees(0), storageEnabled(storageEnabled)
|
||||
{}
|
||||
|
||||
MemoryManager::~MemoryManager()
|
||||
{
|
||||
for (auto& innerBuffer : freePayloads)
|
||||
{
|
||||
while (!innerBuffer.second.empty())
|
||||
{
|
||||
tlm_generic_payload* payload = innerBuffer.second.top();
|
||||
if (storageEnabled)
|
||||
delete[] payload->get_data_ptr();
|
||||
payload->reset();
|
||||
delete payload;
|
||||
innerBuffer.second.pop();
|
||||
numberOfFrees++;
|
||||
}
|
||||
}
|
||||
|
||||
// Comment in if you are suspecting a memory leak in the manager
|
||||
//PRINTDEBUGMESSAGE("MemoryManager","Number of allocated payloads: " + to_string(numberOfAllocations));
|
||||
//PRINTDEBUGMESSAGE("MemoryManager","Number of freed payloads: " + to_string(numberOfFrees));
|
||||
}
|
||||
|
||||
tlm_generic_payload& MemoryManager::allocate(unsigned dataLength)
|
||||
{
|
||||
if (freePayloads[dataLength].empty())
|
||||
{
|
||||
numberOfAllocations++;
|
||||
auto* payload = new tlm_generic_payload(this);
|
||||
|
||||
if (storageEnabled)
|
||||
{
|
||||
// Allocate a data buffer and initialize it with zeroes:
|
||||
auto* data = new unsigned char[dataLength];
|
||||
std::fill(data, data + dataLength, 0);
|
||||
payload->set_data_ptr(data);
|
||||
}
|
||||
|
||||
return *payload;
|
||||
}
|
||||
else
|
||||
{
|
||||
tlm_generic_payload* result = freePayloads[dataLength].top();
|
||||
freePayloads[dataLength].pop();
|
||||
return *result;
|
||||
}
|
||||
}
|
||||
|
||||
void MemoryManager::free(tlm_generic_payload* payload)
|
||||
{
|
||||
unsigned dataLength = payload->get_data_length();
|
||||
freePayloads[dataLength].push(payload);
|
||||
}
|
||||
60
src/simulator/simulator/MemoryManager.h
Normal file
60
src/simulator/simulator/MemoryManager.h
Normal file
@@ -0,0 +1,60 @@
|
||||
/*
|
||||
* 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
|
||||
*/
|
||||
|
||||
#ifndef MEMORYMANAGER_H
|
||||
#define MEMORYMANAGER_H
|
||||
|
||||
#include <unordered_map>
|
||||
#include <stack>
|
||||
|
||||
#include <tlm>
|
||||
|
||||
class MemoryManager : public tlm::tlm_mm_interface
|
||||
{
|
||||
public:
|
||||
MemoryManager(bool storageEnabled);
|
||||
~MemoryManager() override;
|
||||
tlm::tlm_generic_payload& allocate(unsigned dataLength);
|
||||
void free(tlm::tlm_generic_payload* payload) override;
|
||||
|
||||
private:
|
||||
uint64_t numberOfAllocations;
|
||||
uint64_t numberOfFrees;
|
||||
std::unordered_map<unsigned, std::stack<tlm::tlm_generic_payload*>> freePayloads;
|
||||
bool storageEnabled = false;
|
||||
};
|
||||
|
||||
#endif // MEMORYMANAGER_H
|
||||
236
src/simulator/simulator/StlPlayer.cpp
Normal file
236
src/simulator/simulator/StlPlayer.cpp
Normal file
@@ -0,0 +1,236 @@
|
||||
/*
|
||||
* 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<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;
|
||||
}
|
||||
102
src/simulator/simulator/StlPlayer.h
Normal file
102
src/simulator/simulator/StlPlayer.h
Normal file
@@ -0,0 +1,102 @@
|
||||
/*
|
||||
* 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
|
||||
*/
|
||||
|
||||
#ifndef STLPLAYER_H
|
||||
#define STLPLAYER_H
|
||||
|
||||
#include <sstream>
|
||||
#include <vector>
|
||||
#include <array>
|
||||
#include <thread>
|
||||
#include <fstream>
|
||||
|
||||
#include <systemc>
|
||||
#include <tlm>
|
||||
#include "TraceSetup.h"
|
||||
#include "TrafficInitiator.h"
|
||||
|
||||
struct LineContent
|
||||
{
|
||||
sc_core::sc_time sendingTime;
|
||||
unsigned dataLength;
|
||||
tlm::tlm_command command;
|
||||
uint64_t address;
|
||||
std::vector<unsigned char> data;
|
||||
};
|
||||
|
||||
class StlPlayer : public TrafficInitiator
|
||||
{
|
||||
public:
|
||||
StlPlayer(const sc_core::sc_module_name &name,
|
||||
const Configuration& config,
|
||||
const std::string &pathToTrace,
|
||||
const sc_core::sc_time &playerClk,
|
||||
unsigned int maxPendingReadRequests,
|
||||
unsigned int maxPendingWriteRequests,
|
||||
TraceSetup& setup,
|
||||
bool relative);
|
||||
|
||||
~StlPlayer() override;
|
||||
void sendNextPayload() override;
|
||||
uint64_t getNumberOfLines() const;
|
||||
|
||||
private:
|
||||
void parseTraceFile();
|
||||
std::vector<LineContent>::const_iterator swapBuffers();
|
||||
|
||||
std::ifstream file;
|
||||
uint64_t lineCnt = 0;
|
||||
uint64_t numberOfLines = 0;
|
||||
|
||||
const sc_core::sc_time playerClk; // May be different from the memory clock!
|
||||
|
||||
static constexpr unsigned lineBufferSize = 10000;
|
||||
|
||||
std::vector<LineContent>* currentBuffer;
|
||||
std::vector<LineContent>* parseBuffer;
|
||||
std::array<std::vector<LineContent>, 2> lineContents;
|
||||
std::vector<LineContent>::const_iterator lineIterator;
|
||||
|
||||
std::thread parserThread;
|
||||
|
||||
const bool relative;
|
||||
};
|
||||
|
||||
#endif // STLPLAYER_H
|
||||
235
src/simulator/simulator/TraceSetup.cpp
Normal file
235
src/simulator/simulator/TraceSetup.cpp
Normal file
@@ -0,0 +1,235 @@
|
||||
/*
|
||||
* 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 "StlPlayer.h"
|
||||
#include "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>)
|
||||
{
|
||||
TrafficGenerator *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;
|
||||
}
|
||||
77
src/simulator/simulator/TraceSetup.h
Normal file
77
src/simulator/simulator/TraceSetup.h
Normal file
@@ -0,0 +1,77 @@
|
||||
/*
|
||||
* 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
|
||||
* Derek Christ
|
||||
*/
|
||||
|
||||
#ifndef TRACESETUP_H
|
||||
#define TRACESETUP_H
|
||||
|
||||
#include <DRAMSys/config/DRAMSysConfiguration.h>
|
||||
|
||||
#include <DRAMSys/configuration/Configuration.h>
|
||||
|
||||
#include <vector>
|
||||
#include <string>
|
||||
#include <memory>
|
||||
#include <tlm>
|
||||
|
||||
#include "MemoryManager.h"
|
||||
|
||||
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
|
||||
411
src/simulator/simulator/TrafficGenerator.cpp
Normal file
411
src/simulator/simulator/TrafficGenerator.cpp
Normal file
@@ -0,0 +1,411 @@
|
||||
/*
|
||||
* 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 "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;
|
||||
}
|
||||
150
src/simulator/simulator/TrafficGenerator.h
Normal file
150
src/simulator/simulator/TrafficGenerator.h
Normal file
@@ -0,0 +1,150 @@
|
||||
/*
|
||||
* 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 "TrafficInitiator.h"
|
||||
#include "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
|
||||
139
src/simulator/simulator/TrafficInitiator.cpp
Normal file
139
src/simulator/simulator/TrafficInitiator.cpp
Normal file
@@ -0,0 +1,139 @@
|
||||
/*
|
||||
* 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"
|
||||
#include "TraceSetup.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;
|
||||
}
|
||||
|
||||
100
src/simulator/simulator/TrafficInitiator.h
Normal file
100
src/simulator/simulator/TrafficInitiator.h
Normal file
@@ -0,0 +1,100 @@
|
||||
/*
|
||||
* 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
|
||||
*/
|
||||
|
||||
#ifndef TRAFFICINITIATOR_H
|
||||
#define TRAFFICINITIATOR_H
|
||||
|
||||
#include <deque>
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
|
||||
#include <tlm>
|
||||
#include <systemc>
|
||||
#include <tlm_utils/simple_initiator_socket.h>
|
||||
#include <tlm_utils/peq_with_cb_and_phase.h>
|
||||
|
||||
#include <DRAMSys/configuration/Configuration.h>
|
||||
#include <DRAMSys/common/DebugManager.h>
|
||||
|
||||
#include "TraceSetup.h"
|
||||
|
||||
class TrafficInitiator : public sc_core::sc_module
|
||||
{
|
||||
public:
|
||||
tlm_utils::simple_initiator_socket<TrafficInitiator> iSocket;
|
||||
TrafficInitiator(const sc_core::sc_module_name &name, const Configuration& config, TraceSetup& setup,
|
||||
unsigned int maxPendingReadRequests, unsigned int maxPendingWriteRequests, unsigned int defaultDataLength);
|
||||
SC_HAS_PROCESS(TrafficInitiator);
|
||||
virtual void sendNextPayload() = 0;
|
||||
|
||||
protected:
|
||||
static sc_core::sc_time evaluateGeneratorClk(const DRAMSys::Config::TrafficInitiator &conf);
|
||||
|
||||
tlm_utils::peq_with_cb_and_phase<TrafficInitiator> payloadEventQueue;
|
||||
void terminate();
|
||||
TraceSetup& setup;
|
||||
void sendToTarget(tlm::tlm_generic_payload &payload, const tlm::tlm_phase &phase,
|
||||
const sc_core::sc_time &delay);
|
||||
|
||||
uint64_t transactionsReceived = 0;
|
||||
uint64_t transactionsSent = 0;
|
||||
unsigned int pendingReadRequests = 0;
|
||||
unsigned int pendingWriteRequests = 0;
|
||||
|
||||
const unsigned int maxPendingReadRequests = 0;
|
||||
const unsigned int maxPendingWriteRequests = 0;
|
||||
|
||||
bool payloadPostponed = false;
|
||||
bool finished = false;
|
||||
const unsigned int defaultDataLength;
|
||||
const bool storageEnabled;
|
||||
const bool simulationProgressBar;
|
||||
|
||||
// 0 disables the max value.
|
||||
static constexpr unsigned int defaultMaxPendingWriteRequests = 0;
|
||||
static constexpr unsigned int defaultMaxPendingReadRequests = 0;
|
||||
|
||||
private:
|
||||
tlm::tlm_sync_enum nb_transport_bw(tlm::tlm_generic_payload &payload, tlm::tlm_phase &phase,
|
||||
sc_core::sc_time &bwDelay);
|
||||
void peqCallback(tlm::tlm_generic_payload &payload, const tlm::tlm_phase &phase);
|
||||
bool nextPayloadSendable() const;
|
||||
};
|
||||
|
||||
#endif // TRAFFICINITIATOR_H
|
||||
Reference in New Issue
Block a user