Merge branch 'stlplayer_speedup' into 'develop'
Parse larger chunks of the input file to create less system calls. See merge request ems/astdm/dram.sys!266
This commit is contained in:
@@ -43,6 +43,14 @@
|
||||
#include <sstream>
|
||||
#include "TracePlayer.h"
|
||||
|
||||
struct LineContent
|
||||
{
|
||||
sc_time sendingTime;
|
||||
tlm::tlm_command cmd;
|
||||
uint64_t addr;
|
||||
std::vector<unsigned char> data;
|
||||
};
|
||||
|
||||
template<bool relative>
|
||||
class StlPlayer : public TracePlayer
|
||||
{
|
||||
@@ -58,120 +66,141 @@ public:
|
||||
SC_REPORT_FATAL(0, (std::string("Could not open trace ") + pathToTrace).c_str());
|
||||
|
||||
this->playerClk = playerClk;
|
||||
this->burstlength = Configuration::getInstance().memSpec->burstLength;
|
||||
this->dataLength = Configuration::getInstance().getBytesPerBurst();
|
||||
this->lineCnt = 0;
|
||||
burstlength = Configuration::getInstance().memSpec->burstLength;
|
||||
dataLength = Configuration::getInstance().getBytesPerBurst();
|
||||
lineCnt = 0;
|
||||
|
||||
parseTraceFile();
|
||||
}
|
||||
|
||||
void nextPayload()
|
||||
void parseTraceFile()
|
||||
{
|
||||
std::string line;
|
||||
while (line.empty() && file) {
|
||||
unsigned parsedLines = 0;
|
||||
lineContents.clear();
|
||||
while (file && !file.eof() && parsedLines < 10000)
|
||||
{
|
||||
// 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) == '#')
|
||||
line.clear();
|
||||
if (line.empty() || line.at(0) == '#')
|
||||
continue;
|
||||
|
||||
parsedLines++;
|
||||
lineContents.emplace_back();
|
||||
LineContent &content = lineContents.back();
|
||||
|
||||
// Trace files MUST provide timestamp, command and address for every
|
||||
// transaction. The data information depends on the storage mode
|
||||
// configuration.
|
||||
std::string time;
|
||||
std::string command;
|
||||
std::string address;
|
||||
std::string dataStr;
|
||||
|
||||
std::istringstream iss(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));
|
||||
}
|
||||
}
|
||||
lineIterator = lineContents.cbegin();
|
||||
}
|
||||
|
||||
void nextPayload()
|
||||
{
|
||||
if (lineIterator == lineContents.cend())
|
||||
{
|
||||
// Read new lines of file.
|
||||
parseTraceFile();
|
||||
if (lineIterator == lineContents.cend())
|
||||
{
|
||||
// The file is empty. Nothing more to do.
|
||||
this->finish();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (!file) {
|
||||
// The file is empty. Nothing more to do.
|
||||
this->finish();
|
||||
return;
|
||||
} else {
|
||||
numberOfTransactions++;
|
||||
}
|
||||
numberOfTransactions++;
|
||||
|
||||
// Allocate a generic payload for this request.
|
||||
tlm::tlm_generic_payload *payload = this->allocatePayload();
|
||||
payload->acquire();
|
||||
unsigned char *data = payload->get_data_ptr();
|
||||
|
||||
// Trace files MUST provide timestamp, command and address for every
|
||||
// transaction. The data information depends on the storage mode
|
||||
// configuration.
|
||||
std::string time;
|
||||
std::string command;
|
||||
std::string address;
|
||||
std::string dataStr;
|
||||
|
||||
std::istringstream iss(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());
|
||||
sc_time 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());
|
||||
enum tlm::tlm_command cmd;
|
||||
if (command == "read") {
|
||||
cmd = tlm::TLM_READ_COMMAND;
|
||||
} else if (command == "write") {
|
||||
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());
|
||||
unsigned long long addr = std::stoull(address.c_str(), 0, 16);
|
||||
|
||||
// Get the data if necessary.
|
||||
if (storageEnabled && 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++)
|
||||
data[i] = (unsigned char)std::stoi(dataStr.substr(i * 2 + 2, 2).c_str(), 0, 16);
|
||||
}
|
||||
|
||||
// Fill up the payload.
|
||||
payload->set_address(addr);
|
||||
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_data_ptr(data);
|
||||
payload->set_command(cmd);
|
||||
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 (sendingTime <= sc_time_stamp())
|
||||
if (lineIterator->sendingTime <= sc_time_stamp())
|
||||
this->payloadEventQueue.notify(*payload, tlm::BEGIN_REQ, SC_ZERO_TIME);
|
||||
else
|
||||
this->payloadEventQueue.notify(*payload, tlm::BEGIN_REQ,
|
||||
sendingTime - sc_time_stamp());
|
||||
lineIterator->sendingTime - sc_time_stamp());
|
||||
}
|
||||
else
|
||||
payloadEventQueue.notify(*payload, tlm::BEGIN_REQ, sendingTime);
|
||||
payloadEventQueue.notify(*payload, tlm::BEGIN_REQ, lineIterator->sendingTime);
|
||||
|
||||
lineIterator++;
|
||||
}
|
||||
|
||||
private:
|
||||
@@ -181,7 +210,9 @@ private:
|
||||
unsigned int burstlength;
|
||||
unsigned int dataLength;
|
||||
sc_time playerClk; // May be different from the memory clock!
|
||||
|
||||
std::vector<LineContent> lineContents;
|
||||
std::vector<LineContent>::const_iterator lineIterator;
|
||||
};
|
||||
|
||||
#endif // STLPLAYER_H
|
||||
|
||||
|
||||
@@ -111,11 +111,6 @@ void TracePlayer::sendToTarget(tlm_generic_payload &payload, const tlm_phase &ph
|
||||
iSocket->nb_transport_fw(payload, TPhase, TDelay);
|
||||
}
|
||||
|
||||
void TracePlayer::setNumberOfTransactions(unsigned int n)
|
||||
{
|
||||
numberOfTransactions = n;
|
||||
}
|
||||
|
||||
unsigned int TracePlayer::getNumberOfLines(std::string pathToTrace)
|
||||
{
|
||||
// Reference: http://stackoverflow.com/questions/3482064/counting-the-number-of-lines-in-a-text-file
|
||||
|
||||
@@ -64,7 +64,6 @@ protected:
|
||||
tlm_utils::peq_with_cb_and_phase<TracePlayer> payloadEventQueue;
|
||||
void finish();
|
||||
void terminate();
|
||||
void setNumberOfTransactions(unsigned int n);
|
||||
unsigned int numberOfTransactions = 0;
|
||||
bool storageEnabled = false;
|
||||
|
||||
|
||||
@@ -103,6 +103,7 @@ void TraceSetup::tracePlayerTerminates()
|
||||
if (finishedTracePlayers == numberOfTracePlayers)
|
||||
sc_stop();
|
||||
}
|
||||
|
||||
void TraceSetup::transactionFinished()
|
||||
{
|
||||
remainingTransactions--;
|
||||
|
||||
@@ -141,6 +141,8 @@ int sc_main(int argc, char **argv)
|
||||
std::cout << "Simulation took " + std::to_string(elapsed.count()) + " seconds." << std::endl;
|
||||
|
||||
delete dramSys;
|
||||
for (auto player : players)
|
||||
delete player;
|
||||
delete ts;
|
||||
|
||||
return 0;
|
||||
|
||||
Reference in New Issue
Block a user