Commit of the following:

Changed stlPlayer to template class.
Integrated the relative stl player.
This commit is contained in:
Éder F. Zulian
2018-07-03 15:03:36 +02:00
parent 03760b964c
commit 6c5c49179a
7 changed files with 185 additions and 184 deletions

View File

@@ -112,7 +112,6 @@ SOURCES += \
src/error/errormodel.cpp \
src/controller/Controller.cpp \
src/simulation/TracePlayer.cpp \
src/simulation/StlPlayer.cpp \
src/controller/core/powerdown/PowerDownManagerTimeoutBankwise.cpp \
src/simulation/TraceSetup.cpp \
src/simulation/DRAMSys.cpp \

View File

@@ -1,168 +0,0 @@
/*
* Copyright (c) 2015, University of 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"
StlPlayer::StlPlayer(sc_module_name,
string pathToTrace,
sc_time playerClk,
TracePlayerListener *listener) :
TracePlayer(listener),
file(pathToTrace)
{
if (!file.is_open())
SC_REPORT_FATAL(0, (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;
}
void StlPlayer::nextPayload()
{
std::string line;
while (line.empty() && file) {
// 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 (!file) {
// The file is empty. Nothing more to do.
this->finish();
return;
} else {
numberOfTransactions++;
}
// Allocate a generic payload for this request.
gp *payload = this->allocatePayload();
// Allocate a data buffer and initialize it with zeroes. It may be
// overwritten with data from the trace file depending on the storage
// mode.
unsigned char *data = new unsigned char[dataLength];
std::fill(data, data + dataLength, 0);
// Trace files MUST provide timestamp, command and address for every
// transaction. The data information depends on the storage mode
// configuration.
string time;
string command;
string address;
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 " + 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 " + to_string(
lineCnt) + ").").c_str());
enum tlm_command cmd;
if (command == "read") {
cmd = TLM_READ_COMMAND;
} else if (command == "write") {
cmd = TLM_WRITE_COMMAND;
} else {
SC_REPORT_FATAL("StlPlayer",
(string("Corrupted tracefile, command ") + command +
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 " + to_string(
lineCnt) + ").").c_str());
unsigned long long addr = std::stoull(address.c_str(), 0, 16);
// Get the data if necessary.
if (Configuration::getInstance().StoreMode != StorageMode::NoStorage
&& cmd != TLM_READ_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 " + 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.
if (dataStr.length() != (dataLength * 2))
SC_REPORT_FATAL("StlPlayer",
("Data in the trace file has an invalid length (line " + 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).c_str(), 0, 16);
}
// Fill up the payload.
payload->set_address(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_data_ptr(data);
payload->set_command(cmd);
// Send the transaction directly or schedule it to be sent in the future.
if (sendingTime <= sc_time_stamp())
this->payloadEventQueue.notify(*payload, BEGIN_REQ, SC_ZERO_TIME);
else
this->payloadEventQueue.notify(*payload, BEGIN_REQ,
sendingTime - sc_time_stamp());
}

View File

@@ -46,14 +46,141 @@
using namespace std;
using namespace tlm;
struct StlPlayer: public TracePlayer {
template <bool relative> class StlPlayer: public TracePlayer
{
public:
StlPlayer(sc_module_name /*name*/,
string pathToTrace,
sc_time playerClk,
TracePlayerListener *listener);
TracePlayerListener *listener) :
TracePlayer(listener),
file(pathToTrace)
{
if (!file.is_open())
SC_REPORT_FATAL(0, (string("Could not open trace ") + pathToTrace).c_str());
void nextPayload();
this->playerClk = playerClk;
this->burstlength = Configuration::getInstance().memSpec.BurstLength;
this->dataLength = Configuration::getInstance().getBytesPerBurst();
this->lineCnt = 0;
}
void nextPayload()
{
std::string line;
while (line.empty() && file) {
// 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 (!file) {
// The file is empty. Nothing more to do.
this->finish();
return;
} else {
numberOfTransactions++;
}
// Allocate a generic payload for this request.
gp *payload = this->allocatePayload();
// Allocate a data buffer and initialize it with zeroes. It may be
// overwritten with data from the trace file depending on the storage
// mode.
unsigned char *data = new unsigned char[dataLength];
std::fill(data, data + dataLength, 0);
// Trace files MUST provide timestamp, command and address for every
// transaction. The data information depends on the storage mode
// configuration.
string time;
string command;
string address;
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 " + 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 " + to_string(
lineCnt) + ").").c_str());
enum tlm_command cmd;
if (command == "read") {
cmd = TLM_READ_COMMAND;
} else if (command == "write") {
cmd = TLM_WRITE_COMMAND;
} else {
SC_REPORT_FATAL("StlPlayer",
(string("Corrupted tracefile, command ") + command +
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 " + to_string(
lineCnt) + ").").c_str());
unsigned long long addr = std::stoull(address.c_str(), 0, 16);
// Get the data if necessary.
if (Configuration::getInstance().StoreMode != StorageMode::NoStorage
&& cmd != TLM_READ_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 " + 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.
if (dataStr.length() != (dataLength * 2))
SC_REPORT_FATAL("StlPlayer",
("Data in the trace file has an invalid length (line " + 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).c_str(), 0, 16);
}
// Fill up the payload.
payload->set_address(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_data_ptr(data);
payload->set_command(cmd);
if (relative == false) {
// Send the transaction directly or schedule it to be sent in the future.
if (sendingTime <= sc_time_stamp())
this->payloadEventQueue.notify(*payload, BEGIN_REQ, SC_ZERO_TIME);
else
this->payloadEventQueue.notify(*payload, BEGIN_REQ,
sendingTime - sc_time_stamp());
} else {
payloadEventQueue.notify(*payload, BEGIN_REQ, sendingTime);
}
}
private:
ifstream file;

View File

@@ -37,7 +37,7 @@
traceSetup::traceSetup(std::string uri,
std::string pathToResources,
std::vector<StlPlayer *> *devices)
std::vector<TracePlayer *> * devices)
{
// Load Simulation:
tinyxml2::XMLDocument simulationdoc;
@@ -69,17 +69,37 @@ traceSetup::traceSetup(std::string uri,
}
std::string name = device->GetText();
int pos = name.rfind('.');
if(pos == std::string::npos)
{
throw std::runtime_error("Name of the trace file does not contain a valid extension.");
}
// Get the extension and make it lower case
std::string ext = name.substr(pos+1);
std::transform(ext.begin(), ext.end(), ext.begin(), ::tolower);
std::string stlFile = pathToResources + string("traces/") + name;
std::string moduleName = name;
// replace all '.' to '_'
std::replace( moduleName.begin(), moduleName.end(), '.', '_');
StlPlayer *player = new StlPlayer(moduleName.c_str(),
stlFile,
playerClk,
this);
TracePlayer * player;
if(strcmp(ext.c_str(), "stl") == 0)
{
player = new StlPlayer<false>(moduleName.c_str(), stlFile, playerClk, this);
}
else if(strcmp(ext.c_str(), "rstl") == 0)
{
player = new StlPlayer<true>(moduleName.c_str(), stlFile, playerClk, this);
}
else
{
std::string error = "Unsupported file extension in " + name;
throw std::runtime_error(error);
}
devices->push_back(player);
if (Configuration::getInstance().SimulationProgressBar) {

View File

@@ -49,7 +49,7 @@ class traceSetup : public TracePlayerListener
public:
traceSetup(std::string uri,
std::string pathToResources,
std::vector<StlPlayer *> *devices);
std::vector<TracePlayer*> * devices);
virtual void tracePlayerTerminates() override;
virtual void transactionFinished() override;

View File

@@ -72,7 +72,7 @@ int sc_main(int argc, char **argv)
SimulationXML = resources + "simulations/ddr3-example.xml";
}
std::vector<StlPlayer *> players;
std::vector<TracePlayer*> players;
// Instantiate DRAMSys:
DRAMSys *dramSys = new DRAMSys("DRAMSys", SimulationXML, resources);

View File

@@ -381,11 +381,22 @@ configuration structure.
The **device** configuration consists of two parameters - clkMhz
(operation frequency for this device) - and a **trace file**.
#### Trace files
A **trace file** is a pre-recorded file containing memory transactions. Each
memory transaction has a timestamp that tells the simulator when it shall
happen, a transaction type (read or write) and a memory address given in
hexadecimal.
There are two different kinds of trace files. They differ in their timing behaviour and are distingushed by their file extension.
##### STL Trace (.stl)
The timestamp corresponds to the time the request is to be issued and it is
given in cycles of the bus master device. Example: the device is a FPGA with
frequency 200 MHz (clock period of 5 ns). If the timestamp is 10 it means that
the request is to be issued when time is 50 ns.
Here is an example syntax:
```
@@ -397,10 +408,22 @@ Here is an example syntax:
81: read 0x400180
```
The timestamp corresponds to the time the request is to be issued and it is
given in cycles of the bus master device. Example: the device is a FPGA with
frequency 200 MHz (clock period of 5 ns). If the timestamp is 10 it means that
the request is to be issued when time is 50 ns.
##### Relative STL Traces (.rstl)
The timestamp corresponds to the time the request is to be issued relative to the end of the transaction before or the beginning of the trace. This results in a simulation in which the **trace player** is able to react to possible delays due to DRAM bottlenecks.
Here is an example syntax:
```
# Comment lines begin with #
# [clock-cyle]: [write|read] [hex-address]
31: read 0x400140
2: read 0x400160
23: write 0x7fff8000
25: read 0x400180
```
#### Trace player
A **trace player** is **equivalent** to a bus master **device**
(processor, FPGA, etc.). It reads an input trace file and translates each line into