Merge branch 'develop' into DDR5
This commit is contained in:
@@ -232,24 +232,14 @@ Controller::~Controller()
|
||||
|
||||
void Controller::controllerMethod()
|
||||
{
|
||||
// clear command buffer
|
||||
readyCommands.clear();
|
||||
|
||||
// (1) Release payload if arbiter has accepted the result (finish END_RESP)
|
||||
if (payloadToRelease != nullptr && timeToRelease <= sc_time_stamp())
|
||||
finishEndResp();
|
||||
finishEndResp();
|
||||
|
||||
// (2) Send next result to arbiter (start BEGIN_RESP)
|
||||
if (payloadToRelease == nullptr)
|
||||
startBeginResp();
|
||||
startBeginResp();
|
||||
|
||||
// (3) Insert new request from arbiter into scheduler and restart appropriate BM (finish BEGIN_REQ)
|
||||
if (payloadToAcquire != nullptr && timeToAcquire <= sc_time_stamp())
|
||||
{
|
||||
unsigned bankID = DramExtension::getBank(payloadToAcquire).ID();
|
||||
finishBeginReq();
|
||||
bankMachines[bankID]->start();
|
||||
}
|
||||
finishBeginReq();
|
||||
|
||||
// (4) Start refresh and power-down managers to issue requests for the current time
|
||||
for (auto it : refreshManagers)
|
||||
@@ -257,8 +247,10 @@ void Controller::controllerMethod()
|
||||
for (auto it : powerDownManagers)
|
||||
it->start();
|
||||
|
||||
// (5) Choose one request and send it to DRAM
|
||||
// (5) Collect all ready commands from BMs, RMs and PDMs
|
||||
CommandTuple::Type commandTuple;
|
||||
// clear command buffer
|
||||
readyCommands.clear();
|
||||
|
||||
for (unsigned rankID = 0; rankID < memSpec->numberOfRanks; rankID++)
|
||||
{
|
||||
@@ -283,6 +275,7 @@ void Controller::controllerMethod()
|
||||
}
|
||||
}
|
||||
|
||||
// (6) Select one of the ready commands and issue it to the DRAM
|
||||
bool readyCmdBlocked = false;
|
||||
if (!readyCommands.empty())
|
||||
{
|
||||
@@ -333,12 +326,10 @@ void Controller::controllerMethod()
|
||||
readyCmdBlocked = true;
|
||||
}
|
||||
|
||||
// (6) Accept request from arbiter if scheduler is not full, otherwise backpressure (start END_REQ)
|
||||
if (payloadToAcquire != nullptr && timeToAcquire == sc_max_time())
|
||||
startEndReq();
|
||||
// (7) Accept request from arbiter if scheduler is not full, otherwise backpressure (start END_REQ)
|
||||
startEndReq();
|
||||
|
||||
// (7) Restart bank machines, refresh managers and power-down managers to issue new requests for the future
|
||||
// TODO: check if all calls are necessary
|
||||
// (8) Restart bank machines, refresh managers and power-down managers to issue new requests for the future
|
||||
sc_time timeForNextTrigger = sc_max_time();
|
||||
for (auto it : bankMachines)
|
||||
{
|
||||
@@ -362,13 +353,13 @@ tlm_sync_enum Controller::nb_transport_fw(tlm_generic_payload &trans,
|
||||
|
||||
if (phase == BEGIN_REQ)
|
||||
{
|
||||
payloadToAcquire = &trans;
|
||||
timeToAcquire = sc_time_stamp() + notificationDelay;
|
||||
transToAcquire.payload = &trans;
|
||||
transToAcquire.time = sc_time_stamp() + notificationDelay;
|
||||
beginReqEvent.notify(notificationDelay);
|
||||
}
|
||||
else if (phase == END_RESP)
|
||||
{
|
||||
timeToRelease = sc_time_stamp() + notificationDelay;
|
||||
transToRelease.time = sc_time_stamp() + notificationDelay;
|
||||
endRespEvent.notify(notificationDelay);
|
||||
}
|
||||
else
|
||||
@@ -394,63 +385,80 @@ unsigned int Controller::transport_dbg(tlm_generic_payload &trans)
|
||||
|
||||
void Controller::finishBeginReq()
|
||||
{
|
||||
NDEBUG_UNUSED(uint64_t id) = DramExtension::getPayloadID(payloadToAcquire);
|
||||
PRINTDEBUGMESSAGE(name(), "Payload " + std::to_string(id) + " entered system.");
|
||||
if (transToAcquire.payload != nullptr && transToAcquire.time <= sc_time_stamp())
|
||||
{
|
||||
NDEBUG_UNUSED(uint64_t id) = DramExtension::getPayloadID(transToAcquire.payload);
|
||||
PRINTDEBUGMESSAGE(name(), "Payload " + std::to_string(id) + " entered system.");
|
||||
|
||||
if (totalNumberOfPayloads == 0)
|
||||
idleTimeCollector.end();
|
||||
totalNumberOfPayloads++;
|
||||
if (totalNumberOfPayloads == 0)
|
||||
idleTimeCollector.end();
|
||||
totalNumberOfPayloads++;
|
||||
|
||||
Rank rank = DramExtension::getRank(payloadToAcquire);
|
||||
if (ranksNumberOfPayloads[rank.ID()] == 0)
|
||||
powerDownManagers[rank.ID()]->triggerExit();
|
||||
Rank rank = DramExtension::getRank(transToAcquire.payload);
|
||||
if (ranksNumberOfPayloads[rank.ID()] == 0)
|
||||
powerDownManagers[rank.ID()]->triggerExit();
|
||||
|
||||
ranksNumberOfPayloads[rank.ID()]++;
|
||||
ranksNumberOfPayloads[rank.ID()]++;
|
||||
|
||||
scheduler->storeRequest(payloadToAcquire);
|
||||
payloadToAcquire->acquire();
|
||||
timeToAcquire = sc_max_time();
|
||||
scheduler->storeRequest(transToAcquire.payload);
|
||||
transToAcquire.payload->acquire();
|
||||
transToAcquire.time = sc_max_time();
|
||||
|
||||
Bank bank = DramExtension::getBank(transToAcquire.payload);
|
||||
bankMachines[bank.ID()]->start();
|
||||
}
|
||||
}
|
||||
|
||||
void Controller::startEndReq()
|
||||
{
|
||||
if (scheduler->hasBufferSpace())
|
||||
if (transToAcquire.payload != nullptr && transToAcquire.time == sc_max_time())
|
||||
{
|
||||
payloadToAcquire->set_response_status(TLM_OK_RESPONSE);
|
||||
sendToFrontend(payloadToAcquire, END_REQ);
|
||||
payloadToAcquire = nullptr;
|
||||
if (scheduler->hasBufferSpace())
|
||||
{
|
||||
transToAcquire.payload->set_response_status(TLM_OK_RESPONSE);
|
||||
sendToFrontend(transToAcquire.payload, END_REQ);
|
||||
transToAcquire.payload = nullptr;
|
||||
}
|
||||
else
|
||||
PRINTDEBUGMESSAGE(name(), "Total number of payloads exceeded, backpressure!");
|
||||
}
|
||||
else
|
||||
PRINTDEBUGMESSAGE(name(), "Total number of payloads exceeded, backpressure!");
|
||||
}
|
||||
|
||||
void Controller::startBeginResp()
|
||||
{
|
||||
payloadToRelease = respQueue->nextPayload();
|
||||
|
||||
if (payloadToRelease != nullptr)
|
||||
sendToFrontend(payloadToRelease, BEGIN_RESP);
|
||||
else
|
||||
if (transToRelease.payload == nullptr)
|
||||
{
|
||||
sc_time triggerTime = respQueue->getTriggerTime();
|
||||
if (triggerTime != sc_max_time())
|
||||
dataResponseEvent.notify(triggerTime - sc_time_stamp());
|
||||
transToRelease.payload = respQueue->nextPayload();
|
||||
|
||||
if (transToRelease.payload != nullptr)
|
||||
{
|
||||
transToRelease.time = sc_max_time();
|
||||
sendToFrontend(transToRelease.payload, BEGIN_RESP);
|
||||
}
|
||||
else
|
||||
{
|
||||
sc_time triggerTime = respQueue->getTriggerTime();
|
||||
if (triggerTime != sc_max_time())
|
||||
dataResponseEvent.notify(triggerTime - sc_time_stamp());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Controller::finishEndResp()
|
||||
{
|
||||
NDEBUG_UNUSED(uint64_t id) = DramExtension::getPayloadID(payloadToRelease);
|
||||
PRINTDEBUGMESSAGE(name(), "Payload " + std::to_string(id) + " left system.");
|
||||
if (transToRelease.payload != nullptr && transToRelease.time <= sc_time_stamp())
|
||||
{
|
||||
NDEBUG_UNUSED(uint64_t id) = DramExtension::getPayloadID(transToRelease.payload);
|
||||
PRINTDEBUGMESSAGE(name(), "Payload " + std::to_string(id) + " left system.");
|
||||
|
||||
payloadToRelease->release();
|
||||
payloadToRelease = nullptr;
|
||||
timeToRelease = sc_max_time();
|
||||
numberOfTransactionsServed++;
|
||||
transToRelease.payload->release();
|
||||
transToRelease.payload = nullptr;
|
||||
numberOfTransactionsServed++;
|
||||
|
||||
totalNumberOfPayloads--;
|
||||
if (totalNumberOfPayloads == 0)
|
||||
idleTimeCollector.start();
|
||||
totalNumberOfPayloads--;
|
||||
if (totalNumberOfPayloads == 0)
|
||||
idleTimeCollector.start();
|
||||
}
|
||||
}
|
||||
|
||||
void Controller::sendToFrontend(tlm_generic_payload *payload, tlm_phase phase)
|
||||
|
||||
@@ -88,10 +88,11 @@ private:
|
||||
std::vector<RefreshManagerIF *> refreshManagers;
|
||||
std::vector<PowerDownManagerIF *> powerDownManagers;
|
||||
|
||||
tlm::tlm_generic_payload *payloadToAcquire = nullptr;
|
||||
sc_time timeToAcquire = sc_max_time();
|
||||
tlm::tlm_generic_payload *payloadToRelease = nullptr;
|
||||
sc_time timeToRelease = sc_max_time();
|
||||
struct Transaction
|
||||
{
|
||||
tlm::tlm_generic_payload *payload = nullptr;
|
||||
sc_time time = sc_max_time();
|
||||
} transToAcquire, transToRelease;
|
||||
|
||||
void finishBeginReq();
|
||||
void startEndReq();
|
||||
|
||||
@@ -84,7 +84,7 @@ tlm_sync_enum Arbiter::nb_transport_fw(int id, tlm_generic_payload &payload,
|
||||
|
||||
// In the begin request phase the socket ID is appended to the payload.
|
||||
// It will extracted from the payload and used later.
|
||||
appendDramExtension(id, payload);
|
||||
appendDramExtension(id, payload, fwDelay);
|
||||
payload.acquire();
|
||||
}
|
||||
else if (phase == END_RESP)
|
||||
@@ -105,7 +105,7 @@ tlm_sync_enum Arbiter::nb_transport_bw(int channelId, tlm_generic_payload &paylo
|
||||
tlm_phase &phase, sc_time &bwDelay)
|
||||
{
|
||||
// Check channel ID
|
||||
assert((unsigned int)channelId == DramExtension::getExtension(payload).getChannel().ID());
|
||||
assert(static_cast<unsigned>(channelId) == DramExtension::getExtension(payload).getChannel().ID());
|
||||
|
||||
PRINTDEBUGMESSAGE(name(), "[bw] " + getPhaseName(phase) + " notification in " +
|
||||
bwDelay.to_string());
|
||||
@@ -120,7 +120,7 @@ unsigned int Arbiter::transport_dbg(int /*id*/, tlm::tlm_generic_payload &trans)
|
||||
Configuration::getInstance().addressOffset);
|
||||
|
||||
DecodedAddress decodedAddress = addressDecoder->decodeAddress(trans.get_address());
|
||||
return iSocket[decodedAddress.channel]->transport_dbg(trans);
|
||||
return iSocket[static_cast<int>(decodedAddress.channel)]->transport_dbg(trans);
|
||||
}
|
||||
|
||||
void Arbiter::peqCallback(tlm_generic_payload &payload, const tlm_phase &phase)
|
||||
@@ -141,7 +141,7 @@ void Arbiter::peqCallback(tlm_generic_payload &payload, const tlm_phase &phase)
|
||||
channelIsFree[channelId] = false;
|
||||
tlm_phase tPhase = BEGIN_REQ;
|
||||
sc_time tDelay = SC_ZERO_TIME;
|
||||
iSocket[channelId]->nb_transport_fw(payload, tPhase, tDelay);
|
||||
iSocket[static_cast<int>(channelId)]->nb_transport_fw(payload, tPhase, tDelay);
|
||||
// TODO: early completion of channel controller!!!
|
||||
}
|
||||
else
|
||||
@@ -158,7 +158,7 @@ void Arbiter::peqCallback(tlm_generic_payload &payload, const tlm_phase &phase)
|
||||
// The arbiter receives a transaction which phase is END_REQ from memory controller and forwards it to the requester device.
|
||||
tlm_phase tPhase = END_REQ;
|
||||
sc_time tDelay = SC_ZERO_TIME;
|
||||
tSocket[threadId]->nb_transport_bw(payload, tPhase, tDelay);
|
||||
tlm_sync_enum response = tSocket[static_cast<int>(threadId)]->nb_transport_bw(payload, tPhase, tDelay);
|
||||
|
||||
// This channel is now free! Dispatch a new transaction (phase is BEGIN_REQ) from the queue, if any. Send it to the memory controller.
|
||||
if (!pendingRequests[channelId].empty())
|
||||
@@ -168,7 +168,7 @@ void Arbiter::peqCallback(tlm_generic_payload &payload, const tlm_phase &phase)
|
||||
pendingRequests[channelId].pop();
|
||||
tlm_phase tPhase = BEGIN_REQ;
|
||||
sc_time tDelay = SC_ZERO_TIME;
|
||||
iSocket[channelId]->nb_transport_fw(payloadToSend, tPhase, tDelay);
|
||||
iSocket[static_cast<int>(channelId)]->nb_transport_fw(payloadToSend, tPhase, tDelay);
|
||||
// TODO: early completion of channel controller
|
||||
// Mark the channel as busy again.
|
||||
channelIsFree[channelId] = false;
|
||||
@@ -183,7 +183,7 @@ void Arbiter::peqCallback(tlm_generic_payload &payload, const tlm_phase &phase)
|
||||
{
|
||||
tlm_phase tPhase = BEGIN_RESP;
|
||||
sc_time tDelay = SC_ZERO_TIME;
|
||||
tlm_sync_enum returnValue = tSocket[threadId]->nb_transport_bw(payload, tPhase, tDelay);
|
||||
tlm_sync_enum returnValue = tSocket[static_cast<int>(threadId)]->nb_transport_bw(payload, tPhase, tDelay);
|
||||
if (returnValue != TLM_ACCEPTED)
|
||||
{
|
||||
tPhase = END_RESP;
|
||||
@@ -201,7 +201,7 @@ void Arbiter::peqCallback(tlm_generic_payload &payload, const tlm_phase &phase)
|
||||
{
|
||||
tlm_phase tPhase = END_RESP;
|
||||
sc_time tDelay = SC_ZERO_TIME;
|
||||
iSocket[channelId]->nb_transport_fw(payload, tPhase, tDelay);
|
||||
iSocket[static_cast<int>(channelId)]->nb_transport_fw(payload, tPhase, tDelay);
|
||||
}
|
||||
// Drop one element of the queue of BEGIN_RESP from memory to this device
|
||||
pendingResponses[threadId].pop();
|
||||
@@ -215,7 +215,7 @@ void Arbiter::peqCallback(tlm_generic_payload &payload, const tlm_phase &phase)
|
||||
// Send ONE extra BEGIN_RESP to the device
|
||||
tlm_phase tPhase = BEGIN_RESP;
|
||||
sc_time tDelay = SC_ZERO_TIME;
|
||||
tlm_sync_enum returnValue = tSocket[threadId]->nb_transport_bw(payloadToSend, tPhase, tDelay);
|
||||
tlm_sync_enum returnValue = tSocket[static_cast<int>(threadId)]->nb_transport_bw(payloadToSend, tPhase, tDelay);
|
||||
if (returnValue != TLM_ACCEPTED)
|
||||
{
|
||||
tPhase = END_RESP;
|
||||
@@ -228,14 +228,14 @@ void Arbiter::peqCallback(tlm_generic_payload &payload, const tlm_phase &phase)
|
||||
"Payload event queue in arbiter was triggered with unknown phase");
|
||||
}
|
||||
|
||||
void Arbiter::appendDramExtension(int socketId, tlm_generic_payload &payload)
|
||||
void Arbiter::appendDramExtension(int socketId, tlm_generic_payload &payload, sc_time delay)
|
||||
{
|
||||
// Set Generation Extension and DRAM Extension
|
||||
GenerationExtension::setExtension(&payload, sc_time_stamp());
|
||||
GenerationExtension::setExtension(&payload, sc_time_stamp() + delay);
|
||||
|
||||
unsigned int burstlength = payload.get_streaming_width();
|
||||
DecodedAddress decodedAddress = addressDecoder->decodeAddress(payload.get_address());
|
||||
DramExtension::setExtension(payload, Thread(socketId),
|
||||
DramExtension::setExtension(payload, Thread(static_cast<unsigned>(socketId)),
|
||||
Channel(decodedAddress.channel), Rank(decodedAddress.rank),
|
||||
BankGroup(decodedAddress.bankgroup), Bank(decodedAddress.bank),
|
||||
Row(decodedAddress.row), Column(decodedAddress.column),
|
||||
|
||||
@@ -43,6 +43,7 @@
|
||||
#include <iostream>
|
||||
#include <vector>
|
||||
#include <queue>
|
||||
#include <unordered_map>
|
||||
#include <tlm_utils/multi_passthrough_target_socket.h>
|
||||
#include <tlm_utils/multi_passthrough_initiator_socket.h>
|
||||
#include <tlm_utils/peq_with_cb_and_phase.h>
|
||||
@@ -70,7 +71,7 @@ private:
|
||||
std::vector<std::queue<tlm::tlm_generic_payload *>> pendingRequests;
|
||||
// used to account for the response_accept_delay in the initiators (traceplayer, core etc.)
|
||||
// This is a queue of responses comming from the memory side. The phase of these transactions is BEGIN_RESP.
|
||||
std::map<unsigned int, std::queue<tlm::tlm_generic_payload *>> pendingResponses;
|
||||
std::unordered_map<unsigned int, std::queue<tlm::tlm_generic_payload *>> pendingResponses;
|
||||
|
||||
// Initiated by initiator side
|
||||
// This function is called when an arbiter's target socket receives a transaction from a device
|
||||
@@ -86,7 +87,7 @@ private:
|
||||
|
||||
void peqCallback(tlm::tlm_generic_payload &payload, const tlm::tlm_phase &phase);
|
||||
|
||||
void appendDramExtension(int socketId, tlm::tlm_generic_payload &payload);
|
||||
void appendDramExtension(int socketId, tlm::tlm_generic_payload &payload, sc_time delay);
|
||||
std::vector<uint64_t> nextPayloadID;
|
||||
};
|
||||
|
||||
|
||||
@@ -45,10 +45,9 @@ add_executable(DRAMSys
|
||||
main.cpp
|
||||
ExampleInitiator.h
|
||||
MemoryManager.cpp
|
||||
StlPlayer.h
|
||||
TraceGenerator.h
|
||||
StlPlayer.cpp
|
||||
TraceGenerator.cpp
|
||||
TracePlayer.cpp
|
||||
TracePlayerListener.h
|
||||
TraceSetup.cpp
|
||||
)
|
||||
|
||||
|
||||
@@ -42,14 +42,23 @@
|
||||
using namespace tlm;
|
||||
|
||||
MemoryManager::MemoryManager()
|
||||
: numberOfAllocations(0), numberOfFrees(0) {}
|
||||
: numberOfAllocations(0), numberOfFrees(0)
|
||||
{
|
||||
if (Configuration::getInstance().storeMode == "NoStorage")
|
||||
storageEnabled = false;
|
||||
else
|
||||
storageEnabled = true;
|
||||
}
|
||||
|
||||
MemoryManager::~MemoryManager()
|
||||
{
|
||||
for (tlm_generic_payload *payload : freePayloads)
|
||||
{
|
||||
// Delete data buffer
|
||||
delete[] payload->get_data_ptr();
|
||||
if (storageEnabled)
|
||||
{
|
||||
// Delete data buffer
|
||||
delete[] payload->get_data_ptr();
|
||||
}
|
||||
// Delete all extensions
|
||||
payload->reset();
|
||||
delete payload;
|
||||
@@ -68,12 +77,15 @@ tlm_generic_payload *MemoryManager::allocate()
|
||||
numberOfAllocations++;
|
||||
tlm_generic_payload *payload = new tlm_generic_payload(this);
|
||||
|
||||
// Allocate a data buffer and initialize it with zeroes:
|
||||
unsigned int dataLength = Configuration::getInstance().getBytesPerBurst();
|
||||
unsigned char *data = new unsigned char[dataLength];
|
||||
std::fill(data, data + dataLength, 0);
|
||||
if (storageEnabled)
|
||||
{
|
||||
// Allocate a data buffer and initialize it with zeroes:
|
||||
unsigned int dataLength = Configuration::getInstance().getBytesPerBurst();
|
||||
unsigned char *data = new unsigned char[dataLength];
|
||||
std::fill(data, data + dataLength, 0);
|
||||
payload->set_data_ptr(data);
|
||||
}
|
||||
|
||||
payload->set_data_ptr(data);
|
||||
return payload;
|
||||
}
|
||||
else
|
||||
@@ -88,4 +100,3 @@ void MemoryManager::free(tlm_generic_payload *payload)
|
||||
{
|
||||
freePayloads.push_back(payload);
|
||||
}
|
||||
|
||||
|
||||
@@ -52,6 +52,7 @@ private:
|
||||
uint64_t numberOfAllocations;
|
||||
uint64_t numberOfFrees;
|
||||
std::vector<tlm::tlm_generic_payload *> freePayloads;
|
||||
bool storageEnabled = false;
|
||||
};
|
||||
|
||||
#endif // MEMORYMANAGER_H
|
||||
|
||||
217
DRAMSys/simulator/StlPlayer.cpp
Normal file
217
DRAMSys/simulator/StlPlayer.cpp
Normal file
@@ -0,0 +1,217 @@
|
||||
/*
|
||||
* 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
|
||||
*/
|
||||
|
||||
#include "StlPlayer.h"
|
||||
|
||||
using namespace tlm;
|
||||
|
||||
StlPlayer::StlPlayer(sc_module_name name,
|
||||
std::string pathToTrace,
|
||||
sc_time playerClk,
|
||||
TraceSetup *setup,
|
||||
bool relative)
|
||||
: TracePlayer(name, setup), file(pathToTrace),
|
||||
currentBuffer(&lineContents[0]),
|
||||
parseBuffer(&lineContents[1]),
|
||||
relative(relative)
|
||||
{
|
||||
if (!file.is_open())
|
||||
SC_REPORT_FATAL(0, (std::string("Could not open trace ") + pathToTrace).c_str());
|
||||
|
||||
this->playerClk = playerClk;
|
||||
burstlength = Configuration::getInstance().memSpec->burstLength;
|
||||
dataLength = Configuration::getInstance().getBytesPerBurst();
|
||||
lineCnt = 0;
|
||||
|
||||
currentBuffer->reserve(lineBufferSize);
|
||||
parseBuffer->reserve(lineBufferSize);
|
||||
|
||||
parseTraceFile();
|
||||
lineIterator = currentBuffer->cend();
|
||||
}
|
||||
|
||||
StlPlayer::~StlPlayer()
|
||||
{
|
||||
if (parserThread.joinable())
|
||||
parserThread.join();
|
||||
}
|
||||
|
||||
void StlPlayer::nextPayload()
|
||||
{
|
||||
if (lineIterator == currentBuffer->cend())
|
||||
{
|
||||
lineIterator = swapBuffers();
|
||||
if (lineIterator == currentBuffer->cend())
|
||||
{
|
||||
// The file is empty. Nothing more to do.
|
||||
this->finish();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
numberOfTransactions++;
|
||||
|
||||
// Allocate a generic payload for this request.
|
||||
tlm_generic_payload *payload = setup->allocatePayload();
|
||||
payload->acquire();
|
||||
|
||||
// Fill up the payload.
|
||||
payload->set_address(lineIterator->addr);
|
||||
payload->set_response_status(TLM_INCOMPLETE_RESPONSE);
|
||||
payload->set_dmi_allowed(false);
|
||||
payload->set_byte_enable_length(0);
|
||||
payload->set_streaming_width(burstlength);
|
||||
payload->set_data_length(dataLength);
|
||||
payload->set_command(lineIterator->cmd);
|
||||
std::copy(lineIterator->data.begin(), lineIterator->data.end(), payload->get_data_ptr());
|
||||
|
||||
if (!relative)
|
||||
{
|
||||
if (lineIterator->sendingTime <= sc_time_stamp())
|
||||
sendToTarget(*payload, BEGIN_REQ, SC_ZERO_TIME);
|
||||
else
|
||||
sendToTarget(*payload, BEGIN_REQ, lineIterator->sendingTime - sc_time_stamp());
|
||||
}
|
||||
else
|
||||
sendToTarget(*payload, BEGIN_REQ, lineIterator->sendingTime);
|
||||
|
||||
transactionsSent++;
|
||||
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::getline(file, line);
|
||||
lineCnt++;
|
||||
// If the line starts with '#' (commented lines) the transaction is ignored.
|
||||
if (line.empty() || 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.
|
||||
time.clear();
|
||||
command.clear();
|
||||
address.clear();
|
||||
dataStr.clear();
|
||||
|
||||
iss.clear();
|
||||
iss.str(line);
|
||||
|
||||
// Get the timestamp for the transaction.
|
||||
iss >> time;
|
||||
if (time.empty())
|
||||
SC_REPORT_FATAL("StlPlayer",
|
||||
("Malformed trace file. Timestamp could not be found (line " + std::to_string(
|
||||
lineCnt) + ").").c_str());
|
||||
content.sendingTime = std::stoull(time.c_str()) * playerClk;
|
||||
|
||||
// Get the command.
|
||||
iss >> command;
|
||||
if (command.empty())
|
||||
SC_REPORT_FATAL("StlPlayer",
|
||||
("Malformed trace file. Command could not be found (line " + std::to_string(
|
||||
lineCnt) + ").").c_str());
|
||||
|
||||
if (command == "read")
|
||||
content.cmd = tlm::TLM_READ_COMMAND;
|
||||
else if (command == "write")
|
||||
content.cmd = tlm::TLM_WRITE_COMMAND;
|
||||
else
|
||||
SC_REPORT_FATAL("StlPlayer",
|
||||
(std::string("Corrupted tracefile, command ") + command +
|
||||
std::string(" unknown")).c_str());
|
||||
|
||||
// Get the address.
|
||||
iss >> address;
|
||||
if (address.empty())
|
||||
SC_REPORT_FATAL("StlPlayer",
|
||||
("Malformed trace file. Address could not be found (line "
|
||||
+ std::to_string(lineCnt) + ").").c_str());
|
||||
content.addr = std::stoull(address.c_str(), nullptr, 16);
|
||||
|
||||
// Get the data if necessary.
|
||||
if (storageEnabled && content.cmd == tlm::TLM_WRITE_COMMAND)
|
||||
{
|
||||
// The input trace file must provide the data to be stored into the memory.
|
||||
iss >> dataStr;
|
||||
if (dataStr.empty())
|
||||
SC_REPORT_FATAL("StlPlayer",
|
||||
("Malformed trace file. Data information could not be found (line " + std::to_string(
|
||||
lineCnt) + ").").c_str());
|
||||
|
||||
// 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 (dataStr.length() != (dataLength * 2 + 2))
|
||||
SC_REPORT_FATAL("StlPlayer",
|
||||
("Data in the trace file has an invalid length (line " + std::to_string(
|
||||
lineCnt) + ").").c_str());
|
||||
|
||||
// Set data
|
||||
for (unsigned i = 0; i < dataLength; i++)
|
||||
content.data.emplace_back(static_cast<unsigned char>
|
||||
(std::stoi(dataStr.substr(i * 2 + 2, 2).c_str(), 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();
|
||||
}
|
||||
@@ -44,6 +44,7 @@
|
||||
#include <vector>
|
||||
#include <array>
|
||||
#include <thread>
|
||||
#include "TraceSetup.h"
|
||||
#include "TracePlayer.h"
|
||||
|
||||
struct LineContent
|
||||
@@ -54,186 +55,23 @@ struct LineContent
|
||||
std::vector<unsigned char> data;
|
||||
};
|
||||
|
||||
template<bool relative>
|
||||
class StlPlayer : public TracePlayer
|
||||
{
|
||||
public:
|
||||
StlPlayer(sc_module_name name,
|
||||
std::string pathToTrace,
|
||||
sc_time playerClk,
|
||||
TracePlayerListener *listener) :
|
||||
TracePlayer(name, listener),
|
||||
file(pathToTrace),
|
||||
currentBuffer(&lineContents[0]),
|
||||
parseBuffer(&lineContents[1])
|
||||
{
|
||||
if (!file.is_open())
|
||||
SC_REPORT_FATAL(0, (std::string("Could not open trace ") + pathToTrace).c_str());
|
||||
TraceSetup *setup,
|
||||
bool relative);
|
||||
|
||||
this->playerClk = playerClk;
|
||||
burstlength = Configuration::getInstance().memSpec->burstLength;
|
||||
dataLength = Configuration::getInstance().getBytesPerBurst();
|
||||
lineCnt = 0;
|
||||
virtual ~StlPlayer() override;
|
||||
|
||||
currentBuffer->reserve(lineBufferSize);
|
||||
parseBuffer->reserve(lineBufferSize);
|
||||
|
||||
parseTraceFile();
|
||||
lineIterator = currentBuffer->cend();
|
||||
}
|
||||
|
||||
~StlPlayer()
|
||||
{
|
||||
if (parserThread.joinable())
|
||||
parserThread.join();
|
||||
}
|
||||
virtual void nextPayload() override;
|
||||
|
||||
private:
|
||||
void parseTraceFile()
|
||||
{
|
||||
unsigned parsedLines = 0;
|
||||
parseBuffer->clear();
|
||||
while (file && !file.eof() && parsedLines < lineBufferSize)
|
||||
{
|
||||
// Get a new line from the input file.
|
||||
std::getline(file, line);
|
||||
lineCnt++;
|
||||
// If the line starts with '#' (commented lines) the transaction is ignored.
|
||||
if (line.empty() || line.at(0) == '#')
|
||||
continue;
|
||||
void parseTraceFile();
|
||||
std::vector<LineContent>::const_iterator swapBuffers();
|
||||
|
||||
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.
|
||||
time.clear();
|
||||
command.clear();
|
||||
address.clear();
|
||||
dataStr.clear();
|
||||
|
||||
iss.clear();
|
||||
iss.str(line);
|
||||
|
||||
// Get the timestamp for the transaction.
|
||||
iss >> time;
|
||||
if (time.empty())
|
||||
SC_REPORT_FATAL("StlPlayer",
|
||||
("Malformed trace file. Timestamp could not be found (line " + std::to_string(
|
||||
lineCnt) + ").").c_str());
|
||||
content.sendingTime = std::stoull(time.c_str()) * playerClk;
|
||||
|
||||
// Get the command.
|
||||
iss >> command;
|
||||
if (command.empty())
|
||||
SC_REPORT_FATAL("StlPlayer",
|
||||
("Malformed trace file. Command could not be found (line " + std::to_string(
|
||||
lineCnt) + ").").c_str());
|
||||
|
||||
if (command == "read")
|
||||
content.cmd = tlm::TLM_READ_COMMAND;
|
||||
else if (command == "write")
|
||||
content.cmd = tlm::TLM_WRITE_COMMAND;
|
||||
else
|
||||
SC_REPORT_FATAL("StlPlayer",
|
||||
(std::string("Corrupted tracefile, command ") + command +
|
||||
std::string(" unknown")).c_str());
|
||||
|
||||
// Get the address.
|
||||
iss >> address;
|
||||
if (address.empty())
|
||||
SC_REPORT_FATAL("StlPlayer",
|
||||
("Malformed trace file. Address could not be found (line "
|
||||
+ std::to_string(lineCnt) + ").").c_str());
|
||||
content.addr = std::stoull(address.c_str(), nullptr, 16);
|
||||
|
||||
// Get the data if necessary.
|
||||
if (storageEnabled && content.cmd == tlm::TLM_WRITE_COMMAND)
|
||||
{
|
||||
// The input trace file must provide the data to be stored into the memory.
|
||||
iss >> dataStr;
|
||||
if (dataStr.empty())
|
||||
SC_REPORT_FATAL("StlPlayer",
|
||||
("Malformed trace file. Data information could not be found (line " + std::to_string(
|
||||
lineCnt) + ").").c_str());
|
||||
|
||||
// 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 (dataStr.length() != (dataLength * 2 + 2))
|
||||
SC_REPORT_FATAL("StlPlayer",
|
||||
("Data in the trace file has an invalid length (line " + std::to_string(
|
||||
lineCnt) + ").").c_str());
|
||||
|
||||
// Set data
|
||||
for (unsigned i = 0; i < dataLength; i++)
|
||||
content.data.emplace_back((unsigned char)std::stoi(dataStr.substr(i * 2 + 2, 2).c_str(), nullptr, 16));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<LineContent>::const_iterator 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<relative>::parseTraceFile, this);
|
||||
|
||||
return currentBuffer->cbegin();
|
||||
}
|
||||
|
||||
public:
|
||||
void nextPayload()
|
||||
{
|
||||
if (lineIterator == currentBuffer->cend())
|
||||
{
|
||||
lineIterator = swapBuffers();
|
||||
if (lineIterator == currentBuffer->cend())
|
||||
{
|
||||
// The file is empty. Nothing more to do.
|
||||
this->finish();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
numberOfTransactions++;
|
||||
|
||||
// Allocate a generic payload for this request.
|
||||
tlm::tlm_generic_payload *payload = this->allocatePayload();
|
||||
payload->acquire();
|
||||
|
||||
// Fill up the payload.
|
||||
payload->set_address(lineIterator->addr);
|
||||
payload->set_response_status(tlm::TLM_INCOMPLETE_RESPONSE);
|
||||
payload->set_dmi_allowed(false);
|
||||
payload->set_byte_enable_length(0);
|
||||
payload->set_streaming_width(burstlength);
|
||||
payload->set_data_length(dataLength);
|
||||
payload->set_command(lineIterator->cmd);
|
||||
std::copy(lineIterator->data.begin(), lineIterator->data.end(), payload->get_data_ptr());
|
||||
|
||||
if (relative == false)
|
||||
{
|
||||
// Send the transaction directly or schedule it to be sent in the future.
|
||||
if (lineIterator->sendingTime <= sc_time_stamp())
|
||||
this->payloadEventQueue.notify(*payload, tlm::BEGIN_REQ, SC_ZERO_TIME);
|
||||
else
|
||||
this->payloadEventQueue.notify(*payload, tlm::BEGIN_REQ,
|
||||
lineIterator->sendingTime - sc_time_stamp());
|
||||
}
|
||||
else
|
||||
payloadEventQueue.notify(*payload, tlm::BEGIN_REQ, lineIterator->sendingTime);
|
||||
|
||||
lineIterator++;
|
||||
}
|
||||
|
||||
private:
|
||||
std::ifstream file;
|
||||
unsigned int lineCnt;
|
||||
|
||||
@@ -257,6 +95,8 @@ private:
|
||||
|
||||
std::string line;
|
||||
std::istringstream iss;
|
||||
|
||||
const bool relative;
|
||||
};
|
||||
|
||||
#endif // STLPLAYER_H
|
||||
|
||||
@@ -35,15 +35,41 @@
|
||||
* Matthias Jung
|
||||
*/
|
||||
|
||||
#ifndef TRACEPLAYERLISTENER_H
|
||||
#define TRACEPLAYERLISTENER_H
|
||||
#include "TraceGenerator.h"
|
||||
|
||||
class TracePlayerListener
|
||||
TraceGenerator::TraceGenerator(sc_module_name name,
|
||||
unsigned int fCKMhz, TraceSetup *setup)
|
||||
: TracePlayer(name, setup), transCounter(0)
|
||||
{
|
||||
public:
|
||||
virtual void tracePlayerTerminates() = 0;
|
||||
virtual void transactionFinished() = 0;
|
||||
virtual ~TracePlayerListener() {}
|
||||
};
|
||||
if (fCKMhz == 0)
|
||||
tCK = Configuration::getInstance().memSpec->tCK;
|
||||
else
|
||||
tCK = sc_time(1.0 / fCKMhz, SC_US);
|
||||
|
||||
#endif // TRACEPLAYERLISTENER_H
|
||||
burstlenght = Configuration::getInstance().memSpec->burstLength;
|
||||
}
|
||||
|
||||
void TraceGenerator::nextPayload()
|
||||
{
|
||||
if (transCounter >= 1000) // TODO set limit!
|
||||
terminate();
|
||||
|
||||
tlm::tlm_generic_payload *payload = setup->allocatePayload();
|
||||
payload->acquire();
|
||||
unsigned char *dataElement = new unsigned char[16];
|
||||
// TODO: column / burst breite
|
||||
|
||||
payload->set_address(0x0);
|
||||
payload->set_response_status(tlm::TLM_INCOMPLETE_RESPONSE);
|
||||
payload->set_dmi_allowed(false);
|
||||
payload->set_byte_enable_length(0);
|
||||
payload->set_streaming_width(burstlenght);
|
||||
payload->set_data_ptr(dataElement);
|
||||
payload->set_data_length(16);
|
||||
payload->set_command(tlm::TLM_READ_COMMAND);
|
||||
transCounter++;
|
||||
|
||||
sendToTarget(*payload, tlm::BEGIN_REQ, SC_ZERO_TIME);
|
||||
transactionsSent++;
|
||||
PRINTDEBUGMESSAGE(name(), "Performing request #" + std::to_string(transactionsSent));
|
||||
}
|
||||
@@ -39,43 +39,13 @@
|
||||
#define TRACEGENERATOR_H
|
||||
|
||||
#include "TracePlayer.h"
|
||||
#include "TraceSetup.h"
|
||||
|
||||
struct TraceGenerator : public TracePlayer
|
||||
class TraceGenerator : public TracePlayer
|
||||
{
|
||||
public:
|
||||
TraceGenerator(sc_module_name name, unsigned int fCKMhz, TracePlayerListener *listener)
|
||||
: TracePlayer(name, listener), transCounter(0)
|
||||
{
|
||||
if (fCKMhz == 0)
|
||||
tCK = Configuration::getInstance().memSpec->tCK;
|
||||
else
|
||||
tCK = sc_time(1.0 / fCKMhz, SC_US);
|
||||
|
||||
this->burstlenght = Configuration::getInstance().memSpec->burstLength;
|
||||
}
|
||||
|
||||
virtual void nextPayload() override
|
||||
{
|
||||
if (transCounter >= 1000) { // TODO set limit!
|
||||
this->terminate();
|
||||
}
|
||||
|
||||
tlm::tlm_generic_payload *payload = this->allocatePayload();
|
||||
payload->acquire();
|
||||
unsigned char *dataElement = new unsigned
|
||||
char[16]; // TODO: column / burst breite
|
||||
|
||||
payload->set_address(0x0);
|
||||
payload->set_response_status(tlm::TLM_INCOMPLETE_RESPONSE);
|
||||
payload->set_dmi_allowed(false);
|
||||
payload->set_byte_enable_length(0);
|
||||
payload->set_streaming_width(this->burstlenght);
|
||||
payload->set_data_ptr(dataElement);
|
||||
payload->set_data_length(16);
|
||||
payload->set_command(tlm::TLM_READ_COMMAND);
|
||||
transCounter++;
|
||||
this->payloadEventQueue.notify(*payload, tlm::BEGIN_REQ, SC_ZERO_TIME);
|
||||
}
|
||||
TraceGenerator(sc_module_name name, unsigned int fCKMhz, TraceSetup *setup);
|
||||
virtual void nextPayload() override;
|
||||
|
||||
private:
|
||||
unsigned int burstlenght;
|
||||
|
||||
@@ -37,14 +37,16 @@
|
||||
*/
|
||||
|
||||
#include "TracePlayer.h"
|
||||
#include "TraceSetup.h"
|
||||
|
||||
using namespace tlm;
|
||||
|
||||
TracePlayer::TracePlayer(sc_module_name name, TracePlayerListener *listener) :
|
||||
TracePlayer::TracePlayer(sc_module_name name, TraceSetup *setup) :
|
||||
sc_module(name),
|
||||
payloadEventQueue(this, &TracePlayer::peqCallback),
|
||||
listener(listener)
|
||||
setup(setup)
|
||||
{
|
||||
SC_METHOD(nextPayload);
|
||||
iSocket.register_nb_transport_bw(this, &TracePlayer::nb_transport_bw);
|
||||
|
||||
if (Configuration::getInstance().storeMode == "NoStorage")
|
||||
@@ -53,11 +55,6 @@ TracePlayer::TracePlayer(sc_module_name name, TracePlayerListener *listener) :
|
||||
storageEnabled = true;
|
||||
}
|
||||
|
||||
tlm_generic_payload *TracePlayer::allocatePayload()
|
||||
{
|
||||
return memoryManager.allocate();
|
||||
}
|
||||
|
||||
void TracePlayer::finish()
|
||||
{
|
||||
finished = true;
|
||||
@@ -66,7 +63,7 @@ void TracePlayer::finish()
|
||||
void TracePlayer::terminate()
|
||||
{
|
||||
cout << sc_time_stamp() << " " << this->name() << " terminated " << std::endl;
|
||||
listener->tracePlayerTerminates();
|
||||
setup->tracePlayerTerminates();
|
||||
}
|
||||
|
||||
tlm_sync_enum TracePlayer::nb_transport_bw(tlm_generic_payload &payload,
|
||||
@@ -79,27 +76,25 @@ tlm_sync_enum TracePlayer::nb_transport_bw(tlm_generic_payload &payload,
|
||||
void TracePlayer::peqCallback(tlm_generic_payload &payload,
|
||||
const tlm_phase &phase)
|
||||
{
|
||||
if (phase == BEGIN_REQ) {
|
||||
sendToTarget(payload, phase, SC_ZERO_TIME);
|
||||
transactionsSent++;
|
||||
PRINTDEBUGMESSAGE(name(), "Performing request #" + std::to_string(transactionsSent));
|
||||
} else if (phase == END_REQ) {
|
||||
if (phase == END_REQ)
|
||||
{
|
||||
nextPayload();
|
||||
} else if (phase == BEGIN_RESP) {
|
||||
}
|
||||
else if (phase == BEGIN_RESP)
|
||||
{
|
||||
payload.release();
|
||||
sendToTarget(payload, END_RESP, SC_ZERO_TIME);
|
||||
if (Configuration::getInstance().simulationProgressBar)
|
||||
listener->transactionFinished();
|
||||
setup->transactionFinished();
|
||||
|
||||
transactionsReceived++;
|
||||
|
||||
// If all answers were received:
|
||||
if (finished == true && numberOfTransactions == transactionsReceived)
|
||||
{
|
||||
this->terminate();
|
||||
}
|
||||
} else if (phase == END_RESP) {
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
SC_REPORT_FATAL(0, "TracePlayer PEQ was triggered with unknown phase");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -46,37 +46,35 @@
|
||||
#include <tlm_utils/peq_with_cb_and_phase.h>
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
#include "MemoryManager.h"
|
||||
#include "configuration/Configuration.h"
|
||||
#include "common/DebugManager.h"
|
||||
#include "TracePlayerListener.h"
|
||||
#include "TraceSetup.h"
|
||||
|
||||
struct TracePlayer : public sc_module
|
||||
class TracePlayer : public sc_module
|
||||
{
|
||||
public:
|
||||
tlm_utils::simple_initiator_socket<TracePlayer> iSocket;
|
||||
TracePlayer(sc_module_name name, TracePlayerListener *listener);
|
||||
TracePlayer(sc_module_name name, TraceSetup *setup);
|
||||
SC_HAS_PROCESS(TracePlayer);
|
||||
virtual void nextPayload() = 0;
|
||||
unsigned int getNumberOfLines(std::string pathToTrace);
|
||||
|
||||
protected:
|
||||
tlm::tlm_generic_payload *allocatePayload();
|
||||
tlm_utils::peq_with_cb_and_phase<TracePlayer> payloadEventQueue;
|
||||
void finish();
|
||||
void terminate();
|
||||
unsigned int numberOfTransactions = 0;
|
||||
bool storageEnabled = false;
|
||||
TraceSetup *setup;
|
||||
void sendToTarget(tlm::tlm_generic_payload &payload, const tlm::tlm_phase &phase,
|
||||
const sc_time &delay);
|
||||
unsigned int numberOfTransactions = 0;
|
||||
unsigned int transactionsSent = 0;
|
||||
|
||||
private:
|
||||
tlm::tlm_sync_enum nb_transport_bw(tlm::tlm_generic_payload &payload, tlm::tlm_phase &phase,
|
||||
sc_time &bwDelay);
|
||||
void peqCallback(tlm::tlm_generic_payload &payload, const tlm::tlm_phase &phase);
|
||||
void sendToTarget(tlm::tlm_generic_payload &payload, const tlm::tlm_phase &phase,
|
||||
const sc_time &delay);
|
||||
MemoryManager memoryManager;
|
||||
unsigned int transactionsSent = 0;
|
||||
unsigned int transactionsReceived = 0;
|
||||
TracePlayerListener *listener;
|
||||
bool finished = false;
|
||||
};
|
||||
|
||||
|
||||
@@ -35,10 +35,13 @@
|
||||
*/
|
||||
|
||||
#include "TraceSetup.h"
|
||||
#include "StlPlayer.h"
|
||||
|
||||
using namespace tlm;
|
||||
|
||||
TraceSetup::TraceSetup(std::string uri,
|
||||
std::string pathToResources,
|
||||
std::vector<TracePlayer *> *devices)
|
||||
std::vector<TracePlayer *> *players)
|
||||
{
|
||||
// Load Simulation:
|
||||
nlohmann::json simulationdoc = parseJSON(uri);
|
||||
@@ -79,13 +82,13 @@ TraceSetup::TraceSetup(std::string uri,
|
||||
|
||||
TracePlayer *player;
|
||||
if (ext == "stl")
|
||||
player = new StlPlayer<false>(moduleName.c_str(), stlFile, playerClk, this);
|
||||
player = new StlPlayer(moduleName.c_str(), stlFile, playerClk, this, false);
|
||||
else if (ext == "rstl")
|
||||
player = new StlPlayer<true>(moduleName.c_str(), stlFile, playerClk, this);
|
||||
player = new StlPlayer(moduleName.c_str(), stlFile, playerClk, this, true);
|
||||
else
|
||||
throw std::runtime_error("Unsupported file extension in " + name);
|
||||
|
||||
devices->push_back(player);
|
||||
players->push_back(player);
|
||||
|
||||
if (Configuration::getInstance().simulationProgressBar)
|
||||
totalTransactions += player->getNumberOfLines(stlFile);
|
||||
@@ -93,7 +96,7 @@ TraceSetup::TraceSetup(std::string uri,
|
||||
}
|
||||
|
||||
remainingTransactions = totalTransactions;
|
||||
numberOfTracePlayers = devices->size();
|
||||
numberOfTracePlayers = players->size();
|
||||
}
|
||||
|
||||
void TraceSetup::tracePlayerTerminates()
|
||||
@@ -113,3 +116,8 @@ void TraceSetup::transactionFinished()
|
||||
if (remainingTransactions == 0)
|
||||
std::cout << std::endl;
|
||||
}
|
||||
|
||||
tlm_generic_payload *TraceSetup::allocatePayload()
|
||||
{
|
||||
return memoryManager.allocate();
|
||||
}
|
||||
|
||||
@@ -38,28 +38,28 @@
|
||||
|
||||
#include <vector>
|
||||
#include <string>
|
||||
#include <tlm.h>
|
||||
#include "MemoryManager.h"
|
||||
|
||||
#include "common/utils.h"
|
||||
#include "TracePlayer.h"
|
||||
#include "StlPlayer.h"
|
||||
class TracePlayer;
|
||||
|
||||
|
||||
class TraceSetup : public TracePlayerListener
|
||||
class TraceSetup
|
||||
{
|
||||
public:
|
||||
TraceSetup(std::string uri,
|
||||
std::string pathToResources,
|
||||
std::vector<TracePlayer *> *devices);
|
||||
|
||||
virtual void tracePlayerTerminates() override;
|
||||
virtual void transactionFinished() override;
|
||||
virtual ~TraceSetup() {}
|
||||
void tracePlayerTerminates();
|
||||
void transactionFinished();
|
||||
tlm::tlm_generic_payload *allocatePayload();
|
||||
|
||||
private:
|
||||
unsigned int numberOfTracePlayers;
|
||||
unsigned int totalTransactions = 0;
|
||||
unsigned int remainingTransactions;
|
||||
unsigned int finishedTracePlayers = 0;
|
||||
MemoryManager memoryManager;
|
||||
};
|
||||
|
||||
#endif // TRACESETUP_H
|
||||
|
||||
@@ -45,6 +45,7 @@
|
||||
|
||||
#include "simulation/DRAMSys.h"
|
||||
#include "TraceSetup.h"
|
||||
#include "TracePlayer.h"
|
||||
|
||||
#ifdef RECORDING
|
||||
#include "simulation/DRAMSysRecordable.h"
|
||||
@@ -70,21 +71,24 @@ int sc_main(int argc, char **argv)
|
||||
std::string resources;
|
||||
std::string simulationJson;
|
||||
// Run only with default config (ddr3-example.json):
|
||||
if (argc == 1) {
|
||||
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) {
|
||||
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) {
|
||||
else if (argc == 3)
|
||||
{
|
||||
simulationJson = argv[1];
|
||||
resources = argv[2];
|
||||
}
|
||||
@@ -105,7 +109,7 @@ int sc_main(int argc, char **argv)
|
||||
dramSys = new DRAMSys("DRAMSys", simulationJson, resources);
|
||||
|
||||
// Instantiate STL Players:
|
||||
TraceSetup *ts = new TraceSetup(simulationJson, resources, &players);
|
||||
TraceSetup *setup = new TraceSetup(simulationJson, resources, &players);
|
||||
|
||||
// Bind STL Players with DRAMSys:
|
||||
for (size_t i = 0; i < players.size(); i++)
|
||||
@@ -128,10 +132,6 @@ int sc_main(int argc, char **argv)
|
||||
// Store the starting of the simulation in wallclock time:
|
||||
auto start = std::chrono::high_resolution_clock::now();
|
||||
|
||||
// Kickstart the players:
|
||||
for (auto &p : players)
|
||||
p->nextPayload();
|
||||
|
||||
// Start SystemC Simulation:
|
||||
sc_set_stop_mode(SC_STOP_FINISH_DELTA);
|
||||
sc_start();
|
||||
@@ -143,7 +143,7 @@ int sc_main(int argc, char **argv)
|
||||
delete dramSys;
|
||||
for (auto player : players)
|
||||
delete player;
|
||||
delete ts;
|
||||
delete setup;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user