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:
Lukas Steiner
2020-09-09 14:39:11 +02:00
5 changed files with 120 additions and 92 deletions

View File

@@ -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

View File

@@ -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

View 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;

View File

@@ -103,6 +103,7 @@ void TraceSetup::tracePlayerTerminates()
if (finishedTracePlayers == numberOfTracePlayers)
sc_stop();
}
void TraceSetup::transactionFinished()
{
remainingTransactions--;

View File

@@ -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;