Set up testing infrastructure for Cache
This commit is contained in:
@@ -43,14 +43,25 @@ 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})
|
||||
list(FILTER SOURCE_FILES EXCLUDE REGEX "main.cpp")
|
||||
|
||||
add_library(${PROJECT_NAME} STATIC ${SOURCE_FILES} ${HEADER_FILES})
|
||||
|
||||
target_include_directories(${PROJECT_NAME} PUBLIC ${CMAKE_CURRENT_SOURCE_DIR})
|
||||
|
||||
target_link_libraries(${PROJECT_NAME}
|
||||
PUBLIC
|
||||
Threads::Threads
|
||||
DRAMSys::libdramsys
|
||||
)
|
||||
|
||||
add_executable(DRAMSys
|
||||
main.cpp
|
||||
)
|
||||
|
||||
target_link_libraries(DRAMSys
|
||||
PRIVATE
|
||||
Threads::Threads
|
||||
SystemC::systemc
|
||||
DRAMSys::libdramsys
|
||||
DRAMSys_Simulator
|
||||
)
|
||||
|
||||
build_source_group()
|
||||
|
||||
@@ -33,13 +33,13 @@
|
||||
* Derek Christ
|
||||
*/
|
||||
|
||||
#include "Initiator.h"
|
||||
#include "MemoryManager.h"
|
||||
#include "SimpleInitiator.h"
|
||||
#include "generator/TrafficGenerator.h"
|
||||
#include "hammer/RowHammer.h"
|
||||
#include "player/StlPlayer.h"
|
||||
#include "util.h"
|
||||
#include "simulator/Initiator.h"
|
||||
#include "simulator/MemoryManager.h"
|
||||
#include "simulator/SimpleInitiator.h"
|
||||
#include "simulator/generator/TrafficGenerator.h"
|
||||
#include "simulator/hammer/RowHammer.h"
|
||||
#include "simulator/player/StlPlayer.h"
|
||||
#include "simulator/util.h"
|
||||
|
||||
#include <DRAMSys/simulation/DRAMSysRecordable.h>
|
||||
|
||||
@@ -23,7 +23,8 @@ Cache::Cache(const sc_module_name &name,
|
||||
std::size_t maxTargetListSize,
|
||||
bool storageEnabled,
|
||||
sc_core::sc_time cycleTime,
|
||||
std::size_t hitCycles) :
|
||||
std::size_t hitCycles,
|
||||
MemoryManager &memoryManager) :
|
||||
sc_module(name),
|
||||
payloadEventQueue(this, &Cache::peqCallback),
|
||||
storageEnabled(storageEnabled),
|
||||
@@ -39,7 +40,7 @@ Cache::Cache(const sc_module_name &name,
|
||||
mshrDepth(mshrDepth),
|
||||
writeBufferDepth(writeBufferDepth),
|
||||
maxTargetListSize(maxTargetListSize),
|
||||
memoryManager(storageEnabled)
|
||||
memoryManager(memoryManager)
|
||||
{
|
||||
iSocket.register_nb_transport_bw(this, &Cache::nb_transport_bw);
|
||||
tSocket.register_nb_transport_fw(this, &Cache::nb_transport_fw);
|
||||
@@ -601,7 +602,7 @@ void Cache::processMshrResponse()
|
||||
else
|
||||
{
|
||||
hitIt->hitDelayStarted = true;
|
||||
payloadEventQueue.notify(returnTrans, MISS_HANDLING, hitLatency + sc_time(1, SC_NS));
|
||||
payloadEventQueue.notify(returnTrans, MISS_HANDLING, hitLatency);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -61,7 +61,8 @@ public:
|
||||
std::size_t maxTargetListSize,
|
||||
bool storageEnabled,
|
||||
sc_core::sc_time cycleTime,
|
||||
std::size_t hitCycles);
|
||||
std::size_t hitCycles,
|
||||
MemoryManager &memoryManager);
|
||||
SC_HAS_PROCESS(Cache);
|
||||
|
||||
private:
|
||||
@@ -196,5 +197,5 @@ private:
|
||||
sc_core::sc_time ceilTime(const sc_core::sc_time &inTime) const;
|
||||
sc_core::sc_time ceilDelay(const sc_core::sc_time &inDelay) const;
|
||||
|
||||
MemoryManager memoryManager;
|
||||
MemoryManager &memoryManager;
|
||||
};
|
||||
|
||||
313
src/simulator/simulator/EccModule.cpp
Normal file
313
src/simulator/simulator/EccModule.cpp
Normal file
@@ -0,0 +1,313 @@
|
||||
/*
|
||||
* 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:
|
||||
* Christian Malek
|
||||
* Derek Christ
|
||||
*/
|
||||
|
||||
#include "EccModule.h"
|
||||
|
||||
#include "DRAMSys/common/dramExtensions.h"
|
||||
|
||||
#include <fstream>
|
||||
|
||||
using namespace sc_core;
|
||||
using namespace tlm;
|
||||
|
||||
EccModule::EccModule(sc_module_name name, AddressDecoder const &addressDecoder) :
|
||||
sc_core::sc_module(name),
|
||||
payloadEventQueue(this, &EccModule::peqCallback),
|
||||
addressDecoder(addressDecoder),
|
||||
memoryManager(false)
|
||||
{
|
||||
iSocket.register_nb_transport_bw(this, &EccModule::nb_transport_bw);
|
||||
tSocket.register_nb_transport_fw(this, &EccModule::nb_transport_fw);
|
||||
}
|
||||
|
||||
tlm::tlm_sync_enum EccModule::nb_transport_fw(tlm::tlm_generic_payload &payload,
|
||||
tlm::tlm_phase &phase,
|
||||
sc_core::sc_time &fwDelay)
|
||||
{
|
||||
if (phase == BEGIN_REQ)
|
||||
{
|
||||
payload.acquire();
|
||||
}
|
||||
|
||||
payloadEventQueue.notify(payload, phase, fwDelay);
|
||||
return TLM_ACCEPTED;
|
||||
}
|
||||
|
||||
tlm::tlm_sync_enum EccModule::nb_transport_bw(tlm::tlm_generic_payload &payload,
|
||||
tlm::tlm_phase &phase,
|
||||
sc_core::sc_time &bwDelay)
|
||||
{
|
||||
payloadEventQueue.notify(payload, phase, bwDelay);
|
||||
return TLM_ACCEPTED;
|
||||
}
|
||||
|
||||
void EccModule::peqCallback(tlm::tlm_generic_payload &cbPayload, const tlm::tlm_phase &cbPhase)
|
||||
{
|
||||
if (cbPhase == BEGIN_REQ) // from initiator
|
||||
{
|
||||
// Put transaction into latency map
|
||||
payloadMap.emplace(&cbPayload, sc_time_stamp());
|
||||
|
||||
if (!targetBusy)
|
||||
{
|
||||
targetBusy = true;
|
||||
|
||||
tlm_phase tPhase = BEGIN_REQ;
|
||||
sc_time tDelay = SC_ZERO_TIME;
|
||||
|
||||
DecodedAddress decodedAddress = addressDecoder.decodeAddress(cbPayload.get_address());
|
||||
decodedAddress = calculateOffsetAddress(decodedAddress);
|
||||
|
||||
// Update the original address to account for the offsets
|
||||
cbPayload.set_address(addressDecoder.encodeAddress(decodedAddress));
|
||||
|
||||
auto currentBlock = alignToBlock(decodedAddress.column);
|
||||
|
||||
// In case there is no entry yet.
|
||||
activeEccBlocks.try_emplace(decodedAddress.bank);
|
||||
|
||||
#ifdef ECC_ENABLE
|
||||
if (!activeEccBlock(decodedAddress.bank, decodedAddress.row, currentBlock))
|
||||
{
|
||||
blockedRequest = &cbPayload;
|
||||
|
||||
auto &eccFifo = activeEccBlocks[decodedAddress.bank];
|
||||
eccFifo.push_back({currentBlock, decodedAddress.row});
|
||||
|
||||
// Only hold 4 elements at max.
|
||||
if (eccFifo.size() >= 4)
|
||||
eccFifo.pop_front();
|
||||
|
||||
tlm::tlm_generic_payload *eccPayload = generateEccPayload(decodedAddress);
|
||||
|
||||
iSocket->nb_transport_fw(*eccPayload, tPhase, tDelay);
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
iSocket->nb_transport_fw(cbPayload, tPhase, tDelay);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
pendingRequest = &cbPayload;
|
||||
}
|
||||
}
|
||||
else if (cbPhase == END_REQ) // from target
|
||||
{
|
||||
// Send payload to inititator in case it is not an ECC transaction
|
||||
if (cbPayload.get_extension<EccExtension>() == nullptr)
|
||||
{
|
||||
tlm_phase tPhase = END_REQ;
|
||||
sc_time tDelay = SC_ZERO_TIME;
|
||||
|
||||
tSocket->nb_transport_bw(cbPayload, tPhase, tDelay);
|
||||
}
|
||||
|
||||
if (blockedRequest != nullptr)
|
||||
{
|
||||
tlm_generic_payload &tPayload = *blockedRequest;
|
||||
blockedRequest = nullptr;
|
||||
|
||||
tlm_phase tPhase = BEGIN_REQ;
|
||||
sc_time tDelay = SC_ZERO_TIME;
|
||||
|
||||
iSocket->nb_transport_fw(tPayload, tPhase, tDelay);
|
||||
|
||||
// Do not attempt to send another pending request and hold targetBusy high
|
||||
return;
|
||||
}
|
||||
|
||||
if (pendingRequest != nullptr)
|
||||
{
|
||||
tlm_generic_payload &tPayload = *pendingRequest;
|
||||
|
||||
tlm_phase tPhase = BEGIN_REQ;
|
||||
sc_time tDelay = SC_ZERO_TIME;
|
||||
|
||||
DecodedAddress decodedAddress = addressDecoder.decodeAddress(tPayload.get_address());
|
||||
decodedAddress = calculateOffsetAddress(decodedAddress);
|
||||
auto currentBlock = alignToBlock(decodedAddress.column);
|
||||
#ifdef ECC_ENABLE
|
||||
if (!activeEccBlock(decodedAddress.bank, decodedAddress.row, currentBlock))
|
||||
{
|
||||
blockedRequest = pendingRequest;
|
||||
pendingRequest = nullptr;
|
||||
|
||||
auto &eccFifo = activeEccBlocks[decodedAddress.bank];
|
||||
eccFifo.push_back({currentBlock, decodedAddress.row});
|
||||
|
||||
// Only hold 4 elements at max.
|
||||
if (eccFifo.size() >= 4)
|
||||
eccFifo.pop_front();
|
||||
|
||||
tlm::tlm_generic_payload *eccPayload = generateEccPayload(decodedAddress);
|
||||
|
||||
iSocket->nb_transport_fw(*eccPayload, tPhase, tDelay);
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
iSocket->nb_transport_fw(tPayload, tPhase, tDelay);
|
||||
pendingRequest = nullptr;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
assert(!pendingRequest);
|
||||
assert(!blockedRequest);
|
||||
targetBusy = false;
|
||||
}
|
||||
}
|
||||
else if (cbPhase == BEGIN_RESP) // from memory controller
|
||||
{
|
||||
// Send payload to inititator in case it is not an ECC transaction
|
||||
if (cbPayload.get_extension<EccExtension>() == nullptr)
|
||||
{
|
||||
tlm_phase tPhase = BEGIN_RESP;
|
||||
sc_time tDelay = SC_ZERO_TIME;
|
||||
|
||||
tlm_sync_enum returnValue = tSocket->nb_transport_bw(cbPayload, tPhase, tDelay);
|
||||
|
||||
// Early completion from initiator
|
||||
if (returnValue == TLM_UPDATED)
|
||||
{
|
||||
payloadEventQueue.notify(cbPayload, tPhase, tDelay);
|
||||
}
|
||||
|
||||
Latency latency = sc_time_stamp() - payloadMap.at(&cbPayload);
|
||||
payloadMap.erase(&cbPayload);
|
||||
|
||||
latency = roundLatency(latency);
|
||||
latencyMap.try_emplace(latency, 0);
|
||||
latencyMap.at(latency)++;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Send END_RESP by ourselfes
|
||||
tlm_phase tPhase = END_RESP;
|
||||
sc_time tDelay = SC_ZERO_TIME;
|
||||
|
||||
iSocket->nb_transport_fw(cbPayload, tPhase, tDelay);
|
||||
}
|
||||
}
|
||||
else if (cbPhase == END_RESP) // from initiator
|
||||
{
|
||||
{
|
||||
tlm_phase tPhase = END_RESP;
|
||||
sc_time tDelay = SC_ZERO_TIME;
|
||||
|
||||
iSocket->nb_transport_fw(cbPayload, tPhase, tDelay);
|
||||
}
|
||||
|
||||
cbPayload.release();
|
||||
}
|
||||
else
|
||||
{
|
||||
SC_REPORT_FATAL(0, "Payload event queue in arbiter was triggered with unknown phase");
|
||||
}
|
||||
}
|
||||
|
||||
tlm::tlm_generic_payload *EccModule::generateEccPayload(DecodedAddress decodedAddress)
|
||||
{
|
||||
unsigned int eccAtom = decodedAddress.column / 512;
|
||||
uint64_t eccColumn = 1792 + eccAtom * 32;
|
||||
|
||||
decodedAddress.column = eccColumn;
|
||||
uint64_t eccAddress = addressDecoder.encodeAddress(decodedAddress);
|
||||
|
||||
tlm_generic_payload &payload = memoryManager.allocate(32);
|
||||
payload.acquire();
|
||||
payload.set_address(eccAddress);
|
||||
payload.set_response_status(tlm::TLM_INCOMPLETE_RESPONSE);
|
||||
payload.set_dmi_allowed(false);
|
||||
payload.set_byte_enable_length(0);
|
||||
payload.set_data_length(32);
|
||||
payload.set_streaming_width(32);
|
||||
payload.set_command(tlm::TLM_READ_COMMAND);
|
||||
payload.set_extension<EccExtension>(new EccExtension);
|
||||
|
||||
return &payload;
|
||||
}
|
||||
|
||||
unsigned int EccModule::alignToBlock(unsigned column)
|
||||
{
|
||||
return column & ~(512 - 1);
|
||||
}
|
||||
|
||||
DecodedAddress EccModule::calculateOffsetAddress(DecodedAddress decodedAddress)
|
||||
{
|
||||
unsigned int newRow =
|
||||
std::floor((decodedAddress.row * 256 + decodedAddress.column) / 1792) + decodedAddress.row;
|
||||
unsigned int newColumn = (decodedAddress.row * 256 + decodedAddress.column) % 1792;
|
||||
|
||||
DecodedAddress offsetAddress(decodedAddress);
|
||||
offsetAddress.row = newRow;
|
||||
offsetAddress.column = newColumn;
|
||||
return offsetAddress;
|
||||
}
|
||||
|
||||
void EccModule::end_of_simulation()
|
||||
{
|
||||
uint64_t latencies = 0;
|
||||
uint64_t numberOfLatencies = 0;
|
||||
|
||||
for (auto const &[latency, occurences] : latencyMap)
|
||||
{
|
||||
latencies += (latency.to_double() / 1000.0) * occurences;
|
||||
numberOfLatencies += occurences;
|
||||
}
|
||||
|
||||
std::cout << "Average latency: " << static_cast<double>(latencies) / numberOfLatencies << std::endl;
|
||||
}
|
||||
|
||||
sc_time EccModule::roundLatency(sc_time latency)
|
||||
{
|
||||
static const sc_time BUCKET_SIZE = sc_time(1, SC_NS);
|
||||
latency += BUCKET_SIZE / 2;
|
||||
latency = latency - (latency % BUCKET_SIZE);
|
||||
return latency;
|
||||
}
|
||||
|
||||
bool EccModule::activeEccBlock(Bank bank, Row row, Block block) const
|
||||
{
|
||||
auto eccIt = std::find_if(activeEccBlocks.at(bank).cbegin(), activeEccBlocks.at(bank).cend(),
|
||||
[block, row](EccIdentifier identifier) {
|
||||
return (identifier.first == block) && (identifier.second == row);
|
||||
});
|
||||
|
||||
return eccIt != activeEccBlocks.at(bank).cend();
|
||||
}
|
||||
107
src/simulator/simulator/EccModule.h
Normal file
107
src/simulator/simulator/EccModule.h
Normal file
@@ -0,0 +1,107 @@
|
||||
/*
|
||||
* 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:
|
||||
* Christian Malek
|
||||
* Derek Christ
|
||||
*/
|
||||
|
||||
#ifndef ECCMODULE_H
|
||||
#define ECCMODULE_H
|
||||
|
||||
#include "simulator/MemoryManager.h"
|
||||
|
||||
#include <DRAMSys/simulation/AddressDecoder.h>
|
||||
|
||||
#include <systemc>
|
||||
#include <tlm_utils/peq_with_cb_and_phase.h>
|
||||
#include <tlm_utils/simple_initiator_socket.h>
|
||||
#include <tlm_utils/simple_target_socket.h>
|
||||
#include <unordered_map>
|
||||
#include <map>
|
||||
#include <deque>
|
||||
|
||||
class EccModule : public sc_core::sc_module
|
||||
{
|
||||
public:
|
||||
tlm_utils::simple_initiator_socket<EccModule> iSocket;
|
||||
tlm_utils::simple_target_socket<EccModule> tSocket;
|
||||
|
||||
EccModule(sc_core::sc_module_name name, AddressDecoder const &addressDecoder);
|
||||
SC_HAS_PROCESS(EccModule);
|
||||
|
||||
private:
|
||||
using Block = uint64_t;
|
||||
using Row = uint64_t;
|
||||
using Bank = unsigned int;
|
||||
using EccIdentifier = std::pair<Block, Row>;
|
||||
using EccQueue = std::deque<EccIdentifier>;
|
||||
|
||||
static DecodedAddress calculateOffsetAddress(DecodedAddress decodedAddress);
|
||||
static sc_core::sc_time roundLatency(sc_core::sc_time latency);
|
||||
bool activeEccBlock(Bank bank, Row row, Block block) const;
|
||||
|
||||
void end_of_simulation() override;
|
||||
|
||||
void peqCallback(tlm::tlm_generic_payload &payload, const tlm::tlm_phase &phase);
|
||||
|
||||
tlm::tlm_sync_enum nb_transport_fw(tlm::tlm_generic_payload &payload,
|
||||
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);
|
||||
|
||||
tlm::tlm_generic_payload *generateEccPayload(DecodedAddress decodedAddress);
|
||||
|
||||
static unsigned int alignToBlock(unsigned int column);
|
||||
|
||||
tlm_utils::peq_with_cb_and_phase<EccModule> payloadEventQueue;
|
||||
|
||||
tlm::tlm_generic_payload *pendingRequest = nullptr;
|
||||
tlm::tlm_generic_payload *blockedRequest = nullptr;
|
||||
bool targetBusy = false;
|
||||
|
||||
const sc_core::sc_time tCK;
|
||||
MemoryManager memoryManager;
|
||||
AddressDecoder const &addressDecoder;
|
||||
|
||||
std::unordered_map<Bank, EccQueue> activeEccBlocks;
|
||||
|
||||
using EccPayload = tlm::tlm_generic_payload *;
|
||||
using StartTime = sc_core::sc_time;
|
||||
std::unordered_map<tlm::tlm_generic_payload*, StartTime> payloadMap;
|
||||
|
||||
using Latency = sc_core::sc_time;
|
||||
std::map<Latency, uint64_t> latencyMap;
|
||||
};
|
||||
|
||||
#endif // ECCMODULE_H
|
||||
@@ -4,3 +4,4 @@ add_subdirectory(tests_configuration)
|
||||
add_subdirectory(tests_dramsys)
|
||||
add_subdirectory(tests_regression)
|
||||
add_subdirectory(tests_util)
|
||||
add_subdirectory(tests_simulator)
|
||||
|
||||
27
tests/tests_simulator/CMakeLists.txt
Normal file
27
tests/tests_simulator/CMakeLists.txt
Normal file
@@ -0,0 +1,27 @@
|
||||
###############################################
|
||||
### tests_simulator ###
|
||||
###############################################
|
||||
|
||||
cmake_minimum_required(VERSION 3.1.0)
|
||||
|
||||
project(tests_simulator)
|
||||
|
||||
add_executable(${PROJECT_NAME}
|
||||
main.cpp
|
||||
cache/tests_cache.cpp
|
||||
cache/TargetMemory.cpp
|
||||
cache/ListInitiator.cpp
|
||||
)
|
||||
|
||||
set_target_properties(${PROJECT_NAME} PROPERTIES FOLDER tests/simulator)
|
||||
|
||||
target_link_libraries(${PROJECT_NAME} PRIVATE
|
||||
DRAMSys_Simulator
|
||||
gtest_main
|
||||
)
|
||||
|
||||
gtest_discover_tests(${PROJECT_NAME}
|
||||
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
|
||||
)
|
||||
|
||||
build_source_group()
|
||||
189
tests/tests_simulator/cache/ListInitiator.cpp
vendored
Normal file
189
tests/tests_simulator/cache/ListInitiator.cpp
vendored
Normal file
@@ -0,0 +1,189 @@
|
||||
/*
|
||||
* Copyright (c) 2023, Technische Universität Kaiserslautern
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are
|
||||
* met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* 3. Neither the name of the copyright holder nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from
|
||||
* this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
||||
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER
|
||||
* OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* Authors:
|
||||
* Derek Christ
|
||||
*/
|
||||
|
||||
#include "ListInitiator.h"
|
||||
|
||||
#include <iomanip>
|
||||
#include <iostream>
|
||||
#include <map>
|
||||
#include <queue>
|
||||
#include <systemc>
|
||||
#include <tlm>
|
||||
#include <utility>
|
||||
|
||||
ListInitiator::ListInitiator(const sc_core::sc_module_name &name, MemoryManager &memoryManager)
|
||||
: sc_core::sc_module(name),
|
||||
iSocket("iSocket"),
|
||||
peq(this, &ListInitiator::peqCallback),
|
||||
memoryManager(memoryManager)
|
||||
{
|
||||
iSocket.register_nb_transport_bw(this, &ListInitiator::nb_transport_bw);
|
||||
SC_THREAD(process);
|
||||
}
|
||||
|
||||
void ListInitiator::process()
|
||||
{
|
||||
for (auto &testTransactionData : testTransactionList)
|
||||
{
|
||||
wait(testTransactionData.startTime - sc_core::sc_time_stamp());
|
||||
|
||||
tlm::tlm_command command =
|
||||
testTransactionData.command == TestTransactionData::Command::Write
|
||||
? tlm::TLM_WRITE_COMMAND
|
||||
: tlm::TLM_READ_COMMAND;
|
||||
|
||||
auto &trans = memoryManager.allocate(testTransactionData.dataLength);
|
||||
trans.acquire();
|
||||
|
||||
TestExtension *ext = new TestExtension(testTransactionData);
|
||||
trans.set_auto_extension(ext);
|
||||
|
||||
trans.set_command(command);
|
||||
trans.set_address(testTransactionData.address);
|
||||
trans.set_data_length(testTransactionData.dataLength);
|
||||
trans.set_streaming_width(testTransactionData.dataLength);
|
||||
trans.set_byte_enable_ptr(nullptr);
|
||||
trans.set_dmi_allowed(false);
|
||||
trans.set_response_status(tlm::TLM_INCOMPLETE_RESPONSE);
|
||||
|
||||
if (trans.is_write())
|
||||
std::memcpy(trans.get_data_ptr(), &testTransactionData.data, testTransactionData.dataLength);
|
||||
|
||||
if (requestInProgress != nullptr)
|
||||
{
|
||||
wait(endRequest);
|
||||
}
|
||||
|
||||
requestInProgress = &trans;
|
||||
tlm::tlm_phase phase = tlm::BEGIN_REQ;
|
||||
sc_core::sc_time delay = sc_core::SC_ZERO_TIME;
|
||||
|
||||
std::cout << "\033[1;31m(" << name() << ")@" << std::setfill(' ') << std::setw(12)
|
||||
<< sc_core::sc_time_stamp() << ": " << std::setw(12)
|
||||
<< (command == tlm::TLM_WRITE_COMMAND ? "Write to " : "Read from ")
|
||||
<< "Addr = " << std::setfill('0') << std::setw(8) << std::dec
|
||||
<< testTransactionData.address << " Data = "
|
||||
<< "0x" << std::setfill('0') << std::setw(8) << std::hex
|
||||
<< testTransactionData.data << "(nb_transport) \033[0m" << std::endl;
|
||||
|
||||
tlm::tlm_sync_enum status = iSocket->nb_transport_fw(trans, phase, delay);
|
||||
|
||||
if (status == tlm::TLM_UPDATED)
|
||||
{
|
||||
peq.notify(trans, phase, delay);
|
||||
}
|
||||
else if (status == tlm::TLM_COMPLETED)
|
||||
{
|
||||
requestInProgress = nullptr;
|
||||
checkTransaction(trans);
|
||||
trans.release();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
tlm::tlm_sync_enum ListInitiator::nb_transport_bw(tlm::tlm_generic_payload &trans,
|
||||
tlm::tlm_phase &phase,
|
||||
sc_core::sc_time &delay)
|
||||
{
|
||||
peq.notify(trans, phase, delay);
|
||||
return tlm::TLM_ACCEPTED;
|
||||
}
|
||||
|
||||
void ListInitiator::peqCallback(tlm::tlm_generic_payload &trans, const tlm::tlm_phase &phase)
|
||||
{
|
||||
if (phase == tlm::END_REQ || (&trans == requestInProgress && phase == tlm::BEGIN_RESP))
|
||||
{
|
||||
requestInProgress = nullptr;
|
||||
endRequest.notify();
|
||||
}
|
||||
else if (phase == tlm::BEGIN_REQ || phase == tlm::END_RESP)
|
||||
{
|
||||
SC_REPORT_FATAL(name(), "Illegal transaction phase received");
|
||||
}
|
||||
|
||||
if (phase == tlm::BEGIN_RESP)
|
||||
{
|
||||
checkTransaction(trans);
|
||||
|
||||
tlm::tlm_phase fw_phase = tlm::END_RESP;
|
||||
sc_core::sc_time delay = sc_core::sc_time(1, sc_core::SC_NS);
|
||||
iSocket->nb_transport_fw(trans, fw_phase, delay);
|
||||
|
||||
trans.release();
|
||||
}
|
||||
}
|
||||
|
||||
void ListInitiator::checkTransaction(tlm::tlm_generic_payload &trans)
|
||||
{
|
||||
if (trans.is_response_error())
|
||||
{
|
||||
SC_REPORT_ERROR(name(), "Transaction returned with error!");
|
||||
}
|
||||
|
||||
tlm::tlm_command command = trans.get_command();
|
||||
|
||||
uint64_t transData{};
|
||||
|
||||
if (trans.get_data_length() == 1)
|
||||
transData = *reinterpret_cast<uint8_t *>(trans.get_data_ptr());
|
||||
else if (trans.get_data_length() == 2)
|
||||
transData = *reinterpret_cast<uint16_t *>(trans.get_data_ptr());
|
||||
else if (trans.get_data_length() == 4)
|
||||
transData = *reinterpret_cast<uint32_t *>(trans.get_data_ptr());
|
||||
else if (trans.get_data_length() == 8)
|
||||
transData = *reinterpret_cast<uint64_t *>(trans.get_data_ptr());
|
||||
|
||||
TestExtension *ext = nullptr;
|
||||
trans.get_extension(ext);
|
||||
TestTransactionData data = ext->getTestData();
|
||||
|
||||
std::cout << "\033[1;31m(" << name() << ")@" << std::setfill(' ') << std::setw(12)
|
||||
<< sc_core::sc_time_stamp() << ": " << std::setw(12)
|
||||
<< (command == tlm::TLM_WRITE_COMMAND ? "Check Write " : "Check Read ")
|
||||
<< "Addr = " << std::setfill('0') << std::setw(8) << std::dec << data.address
|
||||
<< " Data = "
|
||||
<< "0x" << std::setfill('0') << std::setw(8) << std::hex << transData << "\033[0m"
|
||||
<< std::endl;
|
||||
|
||||
if (data.expectedEndTime != sc_core::sc_time_stamp())
|
||||
{
|
||||
SC_REPORT_FATAL(name(), "NOT EXPECTED TIME");
|
||||
}
|
||||
|
||||
if (trans.is_read() && data.data != transData)
|
||||
{
|
||||
SC_REPORT_FATAL(name(), "NOT EXPECTED DATA");
|
||||
}
|
||||
}
|
||||
104
tests/tests_simulator/cache/ListInitiator.h
vendored
Normal file
104
tests/tests_simulator/cache/ListInitiator.h
vendored
Normal file
@@ -0,0 +1,104 @@
|
||||
/*
|
||||
* Copyright (c) 2023, Technische Universität Kaiserslautern
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are
|
||||
* met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* 3. Neither the name of the copyright holder nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from
|
||||
* this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
||||
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER
|
||||
* OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* Authors:
|
||||
* Derek Christ
|
||||
*/
|
||||
|
||||
#include "simulator/MemoryManager.h"
|
||||
|
||||
#include <tlm_utils/peq_with_cb_and_phase.h>
|
||||
#include <tlm_utils/simple_initiator_socket.h>
|
||||
|
||||
class ListInitiator : public sc_core::sc_module
|
||||
{
|
||||
public:
|
||||
tlm_utils::simple_initiator_socket<ListInitiator> iSocket;
|
||||
|
||||
SC_HAS_PROCESS(ListInitiator);
|
||||
ListInitiator(const sc_core::sc_module_name &name, MemoryManager &memoryManager);
|
||||
|
||||
struct TestTransactionData
|
||||
{
|
||||
sc_core::sc_time startTime;
|
||||
sc_core::sc_time expectedEndTime;
|
||||
|
||||
enum class Command
|
||||
{
|
||||
Read,
|
||||
Write,
|
||||
} command;
|
||||
|
||||
uint64_t address;
|
||||
uint32_t dataLength;
|
||||
uint64_t data;
|
||||
};
|
||||
|
||||
void appendTestTransactionList(const std::vector<TestTransactionData> &testTransactionList)
|
||||
{
|
||||
std::copy(testTransactionList.cbegin(), testTransactionList.cend(), std::back_inserter(this->testTransactionList));
|
||||
}
|
||||
|
||||
private:
|
||||
class TestExtension : public tlm::tlm_extension<TestExtension>
|
||||
{
|
||||
public:
|
||||
TestExtension(TestTransactionData data) : data(std::move(data)) {}
|
||||
|
||||
tlm_extension_base *clone() const { return new TestExtension(data); }
|
||||
|
||||
void copy_from(const tlm_extension_base &ext)
|
||||
{
|
||||
const TestExtension &cpyFrom = static_cast<const TestExtension &>(ext);
|
||||
data = cpyFrom.getTestData();
|
||||
}
|
||||
|
||||
TestTransactionData getTestData() const { return data; }
|
||||
|
||||
private:
|
||||
TestTransactionData data;
|
||||
};
|
||||
|
||||
void process();
|
||||
|
||||
tlm::tlm_sync_enum nb_transport_bw(tlm::tlm_generic_payload &trans,
|
||||
tlm::tlm_phase &phase,
|
||||
sc_core::sc_time &delay);
|
||||
void peqCallback(tlm::tlm_generic_payload &trans, const tlm::tlm_phase &phase);
|
||||
void checkTransaction(tlm::tlm_generic_payload &trans);
|
||||
|
||||
std::vector<TestTransactionData> testTransactionList;
|
||||
|
||||
sc_core::sc_event endRequest;
|
||||
tlm_utils::peq_with_cb_and_phase<ListInitiator> peq;
|
||||
tlm::tlm_generic_payload *requestInProgress = nullptr;
|
||||
MemoryManager &memoryManager;
|
||||
};
|
||||
231
tests/tests_simulator/cache/TargetMemory.cpp
vendored
Normal file
231
tests/tests_simulator/cache/TargetMemory.cpp
vendored
Normal file
@@ -0,0 +1,231 @@
|
||||
/*
|
||||
* Copyright (c) 2023, Technische Universität Kaiserslautern
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are
|
||||
* met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* 3. Neither the name of the copyright holder nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from
|
||||
* this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
||||
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER
|
||||
* OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* Authors:
|
||||
* Derek Christ
|
||||
*/
|
||||
|
||||
#include "TargetMemory.h"
|
||||
|
||||
#include <algorithm>
|
||||
#include <cstddef>
|
||||
#include <iomanip>
|
||||
#include <iostream>
|
||||
|
||||
DECLARE_EXTENDED_PHASE(INTERNAL);
|
||||
|
||||
TargetMemory::TargetMemory(const sc_core::sc_module_name &name,
|
||||
sc_core::sc_time acceptDelay,
|
||||
sc_core::sc_time memoryLatency,
|
||||
std::size_t bufferSize)
|
||||
: sc_core::sc_module(name),
|
||||
tSocket("tSocket"),
|
||||
bufferSize(bufferSize),
|
||||
peq(this, &TargetMemory::peqCallback),
|
||||
acceptDelay(acceptDelay),
|
||||
memoryLatency(memoryLatency)
|
||||
{
|
||||
tSocket.register_nb_transport_fw(this, &TargetMemory::nb_transport_fw);
|
||||
|
||||
memory.reserve(SIZE);
|
||||
std::fill(memory.begin(), memory.end(), 0);
|
||||
}
|
||||
|
||||
tlm::tlm_sync_enum TargetMemory::nb_transport_fw(tlm::tlm_generic_payload &trans,
|
||||
tlm::tlm_phase &phase,
|
||||
sc_core::sc_time &delay)
|
||||
{
|
||||
peq.notify(trans, phase, delay);
|
||||
return tlm::TLM_ACCEPTED;
|
||||
}
|
||||
|
||||
void TargetMemory::printBuffer(int max, int n)
|
||||
{
|
||||
std::cout << "\033[1;35m(" << name() << ")@" << std::setfill(' ') << std::setw(12)
|
||||
<< sc_core::sc_time_stamp() << " Target Buffer: "
|
||||
<< "[";
|
||||
for (int i = 0; i < n; i++)
|
||||
{
|
||||
std::cout << "█";
|
||||
}
|
||||
for (int i = 0; i < max - n; i++)
|
||||
{
|
||||
std::cout << " ";
|
||||
}
|
||||
std::cout << "]"
|
||||
<< " (Max:" << max << ") "
|
||||
<< "\033[0m" << std::endl;
|
||||
std::cout.flush();
|
||||
}
|
||||
|
||||
void TargetMemory::peqCallback(tlm::tlm_generic_payload &trans, const tlm::tlm_phase &phase)
|
||||
{
|
||||
sc_core::sc_time delay;
|
||||
|
||||
if (phase == tlm::BEGIN_REQ)
|
||||
{
|
||||
trans.acquire();
|
||||
|
||||
if (currentTransactions < bufferSize)
|
||||
{
|
||||
sendEndRequest(trans);
|
||||
}
|
||||
else
|
||||
{
|
||||
endRequestPending = &trans;
|
||||
}
|
||||
}
|
||||
else if (phase == tlm::END_RESP)
|
||||
{
|
||||
if (!responseInProgress)
|
||||
{
|
||||
SC_REPORT_FATAL(name(), "Illegal transaction phase END_RESP received by target");
|
||||
}
|
||||
|
||||
currentTransactions--;
|
||||
printBuffer(bufferSize, currentTransactions);
|
||||
|
||||
responseInProgress = false;
|
||||
if (!responseQueue.empty())
|
||||
{
|
||||
tlm::tlm_generic_payload *next = responseQueue.front();
|
||||
responseQueue.pop();
|
||||
sendResponse(*next);
|
||||
}
|
||||
|
||||
if (endRequestPending != nullptr)
|
||||
{
|
||||
sendEndRequest(*endRequestPending);
|
||||
endRequestPending = nullptr;
|
||||
}
|
||||
}
|
||||
else if (phase == INTERNAL)
|
||||
{
|
||||
executeTransaction(trans);
|
||||
|
||||
if (responseInProgress)
|
||||
{
|
||||
responseQueue.push(&trans);
|
||||
}
|
||||
else
|
||||
{
|
||||
sendResponse(trans);
|
||||
}
|
||||
}
|
||||
else // tlm::END_REQ or tlm::BEGIN_RESP
|
||||
{
|
||||
SC_REPORT_FATAL(name(), "Illegal transaction phase received");
|
||||
}
|
||||
}
|
||||
|
||||
void TargetMemory::sendEndRequest(tlm::tlm_generic_payload &trans)
|
||||
{
|
||||
tlm::tlm_phase bw_phase;
|
||||
sc_core::sc_time delay;
|
||||
|
||||
// Queue the acceptance and the response with the appropriate latency
|
||||
bw_phase = tlm::END_REQ;
|
||||
delay = acceptDelay;
|
||||
|
||||
tlm::tlm_sync_enum status = tSocket->nb_transport_bw(trans, bw_phase, delay);
|
||||
|
||||
// Queue internal event to mark beginning of response
|
||||
delay = delay + memoryLatency; // MEMORY Latency
|
||||
peq.notify(trans, INTERNAL, delay);
|
||||
|
||||
currentTransactions++;
|
||||
printBuffer(bufferSize, currentTransactions);
|
||||
}
|
||||
|
||||
void TargetMemory::sendResponse(tlm::tlm_generic_payload &trans)
|
||||
{
|
||||
sc_assert(responseInProgress == false);
|
||||
|
||||
responseInProgress = true;
|
||||
tlm::tlm_phase bw_phase = tlm::BEGIN_RESP;
|
||||
sc_core::sc_time delay = sc_core::SC_ZERO_TIME;
|
||||
tlm::tlm_sync_enum status = tSocket->nb_transport_bw(trans, bw_phase, delay);
|
||||
|
||||
if (status == tlm::TLM_UPDATED)
|
||||
{
|
||||
peq.notify(trans, bw_phase, delay);
|
||||
}
|
||||
else if (status == tlm::TLM_COMPLETED)
|
||||
{
|
||||
SC_REPORT_FATAL(name(), "This transition is deprecated since TLM2.0.1");
|
||||
}
|
||||
|
||||
trans.release();
|
||||
}
|
||||
|
||||
void TargetMemory::executeTransaction(tlm::tlm_generic_payload &trans)
|
||||
{
|
||||
tlm::tlm_command command = trans.get_command();
|
||||
sc_dt::uint64 address = trans.get_address();
|
||||
unsigned char *data_ptr = trans.get_data_ptr();
|
||||
unsigned int data_length = trans.get_data_length();
|
||||
unsigned char *byte_enable_ptr = trans.get_byte_enable_ptr();
|
||||
unsigned int streaming_width = trans.get_streaming_width();
|
||||
|
||||
if (address >= SIZE - 64)
|
||||
{
|
||||
trans.set_response_status(tlm::TLM_ADDRESS_ERROR_RESPONSE);
|
||||
return;
|
||||
}
|
||||
if (byte_enable_ptr != nullptr)
|
||||
{
|
||||
trans.set_response_status(tlm::TLM_BYTE_ENABLE_ERROR_RESPONSE);
|
||||
return;
|
||||
}
|
||||
if (data_length > 64 || streaming_width < data_length)
|
||||
{
|
||||
trans.set_response_status(tlm::TLM_BURST_ERROR_RESPONSE);
|
||||
return;
|
||||
}
|
||||
|
||||
if (command == tlm::TLM_READ_COMMAND)
|
||||
{
|
||||
std::memcpy(trans.get_data_ptr(), &memory[trans.get_address()], trans.get_data_length());
|
||||
}
|
||||
else if (command == tlm::TLM_WRITE_COMMAND)
|
||||
{
|
||||
memcpy(&memory[trans.get_address()], trans.get_data_ptr(), trans.get_data_length());
|
||||
}
|
||||
|
||||
std::cout << "\033[1;32m(" << name() << ")@" << std::setfill(' ') << std::setw(12)
|
||||
<< sc_core::sc_time_stamp() << ": " << std::setw(12)
|
||||
<< (command == tlm::TLM_WRITE_COMMAND ? "Exec. Write " : "Exec. Read ")
|
||||
<< "Addr = " << std::setfill('0') << std::setw(8) << std::dec << address << " Data = "
|
||||
<< "0x" << std::setfill('0') << std::setw(8) << std::hex
|
||||
<< *reinterpret_cast<int *>(data_ptr) << "\033[0m" << std::endl;
|
||||
|
||||
trans.set_response_status(tlm::TLM_OK_RESPONSE);
|
||||
}
|
||||
83
tests/tests_simulator/cache/TargetMemory.h
vendored
Normal file
83
tests/tests_simulator/cache/TargetMemory.h
vendored
Normal file
@@ -0,0 +1,83 @@
|
||||
/*
|
||||
* Copyright (c) 2023, Technische Universität Kaiserslautern
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are
|
||||
* met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* 3. Neither the name of the copyright holder nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from
|
||||
* this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
||||
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER
|
||||
* OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* Authors:
|
||||
* Derek Christ
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <systemc>
|
||||
#include <tlm>
|
||||
#include <tlm_utils/peq_with_cb_and_phase.h>
|
||||
#include <tlm_utils/simple_target_socket.h>
|
||||
|
||||
#include <queue>
|
||||
|
||||
class TargetMemory : public sc_core::sc_module
|
||||
{
|
||||
public:
|
||||
tlm_utils::simple_target_socket<TargetMemory> tSocket;
|
||||
SC_HAS_PROCESS(TargetMemory);
|
||||
TargetMemory(const sc_core::sc_module_name &name,
|
||||
sc_core::sc_time acceptDelay,
|
||||
sc_core::sc_time memoryLatency,
|
||||
std::size_t bufferSize = DEFAULT_BUFFER_SIZE);
|
||||
|
||||
private:
|
||||
tlm::tlm_sync_enum nb_transport_fw(tlm::tlm_generic_payload &trans,
|
||||
tlm::tlm_phase &phase,
|
||||
sc_core::sc_time &delay);
|
||||
|
||||
void peqCallback(tlm::tlm_generic_payload &trans, const tlm::tlm_phase &phase);
|
||||
|
||||
void sendEndRequest(tlm::tlm_generic_payload &trans);
|
||||
void sendResponse(tlm::tlm_generic_payload &trans);
|
||||
void executeTransaction(tlm::tlm_generic_payload &trans);
|
||||
|
||||
void printBuffer(int max, int n);
|
||||
|
||||
static constexpr std::size_t SIZE = static_cast<const std::size_t>(64 * 1024);
|
||||
static constexpr std::size_t DEFAULT_BUFFER_SIZE = 8;
|
||||
const std::size_t bufferSize;
|
||||
|
||||
const sc_core::sc_time acceptDelay;
|
||||
const sc_core::sc_time memoryLatency;
|
||||
|
||||
std::vector<uint8_t> memory;
|
||||
|
||||
unsigned int currentTransactions = 0;
|
||||
bool responseInProgress = false;
|
||||
tlm::tlm_generic_payload *endRequestPending = nullptr;
|
||||
|
||||
tlm_utils::peq_with_cb_and_phase<TargetMemory> peq;
|
||||
std::queue<tlm::tlm_generic_payload *> responseQueue;
|
||||
};
|
||||
93
tests/tests_simulator/cache/tests_cache.cpp
vendored
Normal file
93
tests/tests_simulator/cache/tests_cache.cpp
vendored
Normal file
@@ -0,0 +1,93 @@
|
||||
/*
|
||||
* Copyright (c) 2023, Technische Universität Kaiserslautern
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are
|
||||
* met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* 3. Neither the name of the copyright holder nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from
|
||||
* this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
||||
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER
|
||||
* OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* Authors:
|
||||
* Derek Christ
|
||||
*/
|
||||
|
||||
#include "ListInitiator.h"
|
||||
#include "TargetMemory.h"
|
||||
|
||||
#include <simulator/Cache.h>
|
||||
#include <simulator/MemoryManager.h>
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
class SystemCTest : public testing::Test
|
||||
{
|
||||
public:
|
||||
~SystemCTest() override { sc_core::sc_get_curr_simcontext()->reset(); }
|
||||
};
|
||||
|
||||
class DirectMappedCache : public SystemCTest
|
||||
{
|
||||
protected:
|
||||
DirectMappedCache()
|
||||
: memoryManager(true),
|
||||
initiator("ListInitiator", memoryManager),
|
||||
target("TargetMemory",
|
||||
sc_core::sc_time(1, sc_core::SC_NS),
|
||||
sc_core::sc_time(10, sc_core::SC_NS)),
|
||||
cache("Cache",
|
||||
32768,
|
||||
1,
|
||||
32,
|
||||
8,
|
||||
8,
|
||||
8,
|
||||
true,
|
||||
sc_core::sc_time(1, sc_core::SC_NS),
|
||||
5,
|
||||
memoryManager)
|
||||
{
|
||||
initiator.iSocket.bind(cache.tSocket);
|
||||
cache.iSocket.bind(target.tSocket);
|
||||
}
|
||||
|
||||
MemoryManager memoryManager;
|
||||
ListInitiator initiator;
|
||||
TargetMemory target;
|
||||
Cache cache;
|
||||
};
|
||||
|
||||
TEST_F(DirectMappedCache, Hello)
|
||||
{
|
||||
std::vector<ListInitiator::TestTransactionData> list{
|
||||
{sc_core::sc_time(1000, sc_core::SC_NS),
|
||||
sc_core::sc_time(1017, sc_core::SC_NS),
|
||||
ListInitiator::TestTransactionData::Command::Read,
|
||||
0x0,
|
||||
4,
|
||||
0x0}};
|
||||
|
||||
initiator.appendTestTransactionList(list);
|
||||
sc_core::sc_start();
|
||||
}
|
||||
43
tests/tests_simulator/main.cpp
Normal file
43
tests/tests_simulator/main.cpp
Normal file
@@ -0,0 +1,43 @@
|
||||
/*
|
||||
* Copyright (c) 2019, 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 <gtest/gtest.h>
|
||||
#include <systemc>
|
||||
|
||||
int sc_main(int argc, char **argv)
|
||||
{
|
||||
testing::InitGoogleTest(&argc, argv);
|
||||
return RUN_ALL_TESTS();
|
||||
}
|
||||
Reference in New Issue
Block a user