Implement a more advanced TraceGenerator
Implementation of a more advanced TraceGenerator that can be configured using the Json config file. The new TraceGenerator is capable of specifing the number of requests to make, the ratio of read and write accesses, the distribution of the addresses, the address increment value in case of a sequential address distribution, a seed in case of a random address distribution and the maximum number of pending read or write requests. The maximum number of pending requests was also implemented for the StlPlayer.
This commit is contained in:
@@ -0,0 +1,34 @@
|
||||
{
|
||||
"simulation": {
|
||||
"addressmapping": "am_ddr5_2x8x2Gbx4_dimm_p1KB_rbc.json",
|
||||
"mcconfig": "fr_fcfs.json",
|
||||
"memspec": "JEDEC_2x8x2Gbx4_DDR5-3200A.json",
|
||||
"simconfig": "ddr5.json",
|
||||
"simulationid": "ddr5-example",
|
||||
"thermalconfig": "config.json",
|
||||
"tracesetup": [
|
||||
{
|
||||
"clkMhz": 2000,
|
||||
"type": "generator",
|
||||
"name": "gen0",
|
||||
"numRequests": 2000,
|
||||
"rwRatio": 0.85,
|
||||
"addressDistribution": "sequential",
|
||||
"addressIncrement": 256,
|
||||
"maxPendingReadRequests": 8,
|
||||
"maxPendingWriteRequests": 8
|
||||
},
|
||||
{
|
||||
"clkMhz": 2000,
|
||||
"type": "generator",
|
||||
"name": "gen1",
|
||||
"numRequests": 2000,
|
||||
"rwRatio": 0.85,
|
||||
"addressDistribution": "random",
|
||||
"seed": 123456,
|
||||
"maxPendingReadRequests": 8,
|
||||
"maxPendingWriteRequests": 8
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
@@ -41,9 +41,11 @@
|
||||
|
||||
using namespace tlm;
|
||||
|
||||
StlPlayer::StlPlayer(sc_module_name name,
|
||||
std::string pathToTrace,
|
||||
StlPlayer::StlPlayer(const sc_module_name &name,
|
||||
const std::string &pathToTrace,
|
||||
sc_time playerClk,
|
||||
unsigned int maxPendingReadRequests,
|
||||
unsigned int maxPendingWriteRequests,
|
||||
TraceSetup *setup,
|
||||
bool relative)
|
||||
: TracePlayer(name, setup), file(pathToTrace),
|
||||
@@ -54,6 +56,9 @@ StlPlayer::StlPlayer(sc_module_name name,
|
||||
if (!file.is_open())
|
||||
SC_REPORT_FATAL("StlPlayer", (std::string("Could not open trace ") + pathToTrace).c_str());
|
||||
|
||||
this->maxPendingReadRequests = maxPendingReadRequests;
|
||||
this->maxPendingWriteRequests = maxPendingWriteRequests;
|
||||
|
||||
this->playerClk = playerClk;
|
||||
burstlength = Configuration::getInstance().memSpec->burstLength;
|
||||
dataLength = Configuration::getInstance().memSpec->bytesPerBurst;
|
||||
@@ -117,6 +122,12 @@ void StlPlayer::nextPayload()
|
||||
sendToTarget(*payload, BEGIN_REQ, sendingTime - sc_time_stamp());
|
||||
|
||||
transactionsSent++;
|
||||
|
||||
if (payload->get_command() == tlm::TLM_READ_COMMAND)
|
||||
pendingReadRequests++;
|
||||
else if (payload->get_command() == tlm::TLM_WRITE_COMMAND)
|
||||
pendingWriteRequests++;
|
||||
|
||||
PRINTDEBUGMESSAGE(name(), "Performing request #" + std::to_string(transactionsSent));
|
||||
lineIterator++;
|
||||
}
|
||||
|
||||
@@ -58,9 +58,11 @@ struct LineContent
|
||||
class StlPlayer : public TracePlayer
|
||||
{
|
||||
public:
|
||||
StlPlayer(sc_module_name name,
|
||||
std::string pathToTrace,
|
||||
StlPlayer(const sc_module_name &name,
|
||||
const std::string &pathToTrace,
|
||||
sc_time playerClk,
|
||||
unsigned int maxPendingReadRequests,
|
||||
unsigned int maxPendingWriteRequests,
|
||||
TraceSetup *setup,
|
||||
bool relative);
|
||||
|
||||
|
||||
@@ -37,40 +37,84 @@
|
||||
|
||||
#include "TraceGenerator.h"
|
||||
|
||||
TraceGenerator::TraceGenerator(sc_module_name name,
|
||||
unsigned int fCKMhz, TraceSetup *setup)
|
||||
: TracePlayer(name, setup), transCounter(0)
|
||||
TraceGenerator::TraceGenerator(const sc_module_name &name,
|
||||
const sc_time &tCK,
|
||||
uint64_t numRequests,
|
||||
unsigned int maxPendingReadRequests,
|
||||
unsigned int maxPendingWriteRequests,
|
||||
float rwRatio,
|
||||
AddressDistribution addressDistribution,
|
||||
unsigned int addressIncrement,
|
||||
unsigned int seed,
|
||||
TraceSetup *setup) :
|
||||
TracePlayer(name, setup), tCK(tCK), numRequests(numRequests),
|
||||
rwRatio(rwRatio), addressDistribution(addressDistribution),
|
||||
addressIncrement(addressIncrement)
|
||||
{
|
||||
if (fCKMhz == 0)
|
||||
tCK = Configuration::getInstance().memSpec->tCK;
|
||||
else
|
||||
tCK = sc_time(1.0 / fCKMhz, SC_US);
|
||||
|
||||
burstlenght = Configuration::getInstance().memSpec->burstLength;
|
||||
|
||||
this->maxPendingReadRequests = maxPendingReadRequests;
|
||||
this->maxPendingWriteRequests = maxPendingWriteRequests;
|
||||
|
||||
randomGenerator = std::default_random_engine(seed);
|
||||
randomAddressDistribution = std::uniform_int_distribution<uint64_t>(
|
||||
0, Configuration::getInstance().memSpec->getSimMemSizeInBytes());
|
||||
|
||||
}
|
||||
|
||||
void TraceGenerator::nextPayload()
|
||||
{
|
||||
if (transCounter >= 1000) // TODO set limit!
|
||||
terminate();
|
||||
if (transCounter >= numRequests) {
|
||||
finished = true;
|
||||
return;
|
||||
}
|
||||
|
||||
tlm::tlm_generic_payload *payload = setup->allocatePayload();
|
||||
payload->acquire();
|
||||
unsigned char *dataElement = new unsigned char[16];
|
||||
// TODO: column / burst breite
|
||||
|
||||
payload->set_address(0x0);
|
||||
uint64_t address;
|
||||
if (addressDistribution == AddressDistribution::Sequential) {
|
||||
address = currentAddress;
|
||||
currentAddress += addressIncrement;
|
||||
} else {
|
||||
// AddressDistribution::Random
|
||||
address = randomAddressDistribution(randomGenerator);
|
||||
}
|
||||
|
||||
tlm::tlm_command command;
|
||||
if (randomRwDistribution(randomGenerator) < rwRatio) {
|
||||
command = tlm::TLM_READ_COMMAND;
|
||||
} else {
|
||||
command = tlm::TLM_WRITE_COMMAND;
|
||||
}
|
||||
|
||||
payload->set_address(address);
|
||||
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);
|
||||
payload->set_command(command);
|
||||
transCounter++;
|
||||
|
||||
sc_time sendingOffset;
|
||||
if (lastEndReq == sc_time_stamp())
|
||||
sendingOffset = tCK;
|
||||
else
|
||||
sendingOffset = SC_ZERO_TIME;
|
||||
|
||||
// TODO: do not send two requests in the same cycle
|
||||
sendToTarget(*payload, tlm::BEGIN_REQ, SC_ZERO_TIME);
|
||||
sendToTarget(*payload, tlm::BEGIN_REQ, sendingOffset);
|
||||
|
||||
transactionsSent++;
|
||||
|
||||
if (command == tlm::TLM_READ_COMMAND)
|
||||
pendingReadRequests++;
|
||||
else if (command == tlm::TLM_WRITE_COMMAND)
|
||||
pendingWriteRequests++;
|
||||
|
||||
PRINTDEBUGMESSAGE(name(), "Performing request #" + std::to_string(transactionsSent));
|
||||
}
|
||||
|
||||
@@ -41,16 +41,39 @@
|
||||
#include "TracePlayer.h"
|
||||
#include "TraceSetup.h"
|
||||
|
||||
#include <random>
|
||||
|
||||
enum class AddressDistribution {Sequential, Random};
|
||||
|
||||
class TraceGenerator : public TracePlayer
|
||||
{
|
||||
public:
|
||||
TraceGenerator(sc_module_name name, unsigned int fCKMhz, TraceSetup *setup);
|
||||
TraceGenerator(const sc_module_name &name,
|
||||
const sc_time &tCK,
|
||||
uint64_t numRequests,
|
||||
unsigned int maxPendingReadRequests,
|
||||
unsigned int maxPendingWriteRequests,
|
||||
float rwRatio,
|
||||
AddressDistribution addressDistribution,
|
||||
unsigned int addressIncrement,
|
||||
unsigned int seed,
|
||||
TraceSetup *setup);
|
||||
|
||||
virtual void nextPayload() override;
|
||||
|
||||
private:
|
||||
unsigned int burstlenght;
|
||||
sc_time tCK;
|
||||
unsigned int transCounter;
|
||||
unsigned int numRequests;
|
||||
float rwRatio;
|
||||
AddressDistribution addressDistribution;
|
||||
unsigned int addressIncrement;
|
||||
unsigned int transCounter = 0;
|
||||
unsigned int currentAddress = 0x0;
|
||||
|
||||
std::default_random_engine randomGenerator;
|
||||
std::uniform_int_distribution<uint64_t> randomAddressDistribution;
|
||||
std::uniform_real_distribution<float> randomRwDistribution = std::uniform_real_distribution<float>(0.0f, 1.0f);
|
||||
};
|
||||
|
||||
#endif // TRACEGENERATOR_H
|
||||
|
||||
@@ -74,7 +74,11 @@ void TracePlayer::peqCallback(tlm_generic_payload &payload,
|
||||
if (phase == END_REQ)
|
||||
{
|
||||
lastEndReq = sc_time_stamp();
|
||||
nextPayload();
|
||||
|
||||
if (nextPayloadSendable())
|
||||
nextPayload();
|
||||
else
|
||||
payloadPostponed = true;
|
||||
}
|
||||
else if (phase == BEGIN_RESP)
|
||||
{
|
||||
@@ -85,8 +89,19 @@ void TracePlayer::peqCallback(tlm_generic_payload &payload,
|
||||
|
||||
transactionsReceived++;
|
||||
|
||||
if (payload.get_command() == tlm::TLM_READ_COMMAND)
|
||||
pendingReadRequests--;
|
||||
else if (payload.get_command() == tlm::TLM_WRITE_COMMAND)
|
||||
pendingWriteRequests--;
|
||||
|
||||
// If the initiator wasn't able to send the next payload in the END_REQ phase, do it now.
|
||||
if (payloadPostponed) {
|
||||
nextPayload();
|
||||
payloadPostponed = false;
|
||||
}
|
||||
|
||||
// If all answers were received:
|
||||
if (finished == true && numberOfTransactions == transactionsReceived)
|
||||
if (finished == true && transactionsSent == transactionsReceived)
|
||||
terminate();
|
||||
}
|
||||
else
|
||||
@@ -128,3 +143,21 @@ uint64_t TracePlayer::getNumberOfLines(std::string pathToTrace)
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
bool TracePlayer::nextPayloadSendable()
|
||||
{
|
||||
bool sendable = true;
|
||||
|
||||
// If either the maxPendingReadRequests or maxPendingWriteRequests
|
||||
// limit is reached, do not send next payload.
|
||||
if (pendingReadRequests >= maxPendingReadRequests && maxPendingReadRequests != 0)
|
||||
{
|
||||
sendable = false;
|
||||
}
|
||||
else if (pendingWriteRequests >= maxPendingWriteRequests && maxPendingWriteRequests != 0)
|
||||
{
|
||||
sendable = false;
|
||||
}
|
||||
|
||||
return sendable;
|
||||
}
|
||||
|
||||
@@ -66,16 +66,24 @@ protected:
|
||||
TraceSetup *setup;
|
||||
void sendToTarget(tlm::tlm_generic_payload &payload, const tlm::tlm_phase &phase,
|
||||
const sc_time &delay);
|
||||
|
||||
uint64_t numberOfTransactions = 0;
|
||||
uint64_t transactionsReceived = 0;
|
||||
uint64_t transactionsSent = 0;
|
||||
unsigned int pendingReadRequests = 0;
|
||||
unsigned int pendingWriteRequests = 0;
|
||||
unsigned int maxPendingReadRequests = 0;
|
||||
unsigned int maxPendingWriteRequests = 0;
|
||||
bool payloadPostponed = false;
|
||||
bool finished = false;
|
||||
sc_time lastEndReq = sc_max_time();
|
||||
sc_event transactionFinished;
|
||||
|
||||
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);
|
||||
uint64_t transactionsReceived = 0;
|
||||
bool nextPayloadSendable();
|
||||
};
|
||||
|
||||
#endif // TRACEPLAYER_H
|
||||
|
||||
@@ -36,12 +36,13 @@
|
||||
|
||||
#include "TraceSetup.h"
|
||||
#include "StlPlayer.h"
|
||||
#include "TraceGenerator.h"
|
||||
|
||||
using namespace tlm;
|
||||
|
||||
TraceSetup::TraceSetup(std::string uri,
|
||||
std::string pathToResources,
|
||||
std::vector<TracePlayer *> *players)
|
||||
TraceSetup::TraceSetup(const std::string &uri,
|
||||
const std::string &pathToResources,
|
||||
std::vector<TracePlayer *> &players)
|
||||
{
|
||||
// Load Simulation:
|
||||
nlohmann::json simulationdoc = parseJSON(uri);
|
||||
@@ -53,52 +54,129 @@ TraceSetup::TraceSetup(std::string uri,
|
||||
// Load TracePlayers:
|
||||
if (simulationdoc["simulation"]["tracesetup"].empty())
|
||||
SC_REPORT_FATAL("TraceSetup", "tracesetup is empty");
|
||||
for (auto it : simulationdoc["simulation"]["tracesetup"].items())
|
||||
for (auto &it : simulationdoc["simulation"]["tracesetup"].items())
|
||||
{
|
||||
auto value = it.value();
|
||||
if (!value.empty())
|
||||
{
|
||||
sc_time playerClk;
|
||||
if (!value["clkMhz"].is_number_unsigned())
|
||||
SC_REPORT_FATAL("TraceSetup", "Frequency is not a number.");
|
||||
|
||||
unsigned int frequencyMHz = value["clkMhz"];
|
||||
|
||||
if (frequencyMHz == 0)
|
||||
SC_REPORT_FATAL("TraceSetup", "No frequency defined");
|
||||
SC_REPORT_FATAL("TraceSetup", "Frequency must not be zero.");
|
||||
else
|
||||
playerClk = sc_time(1.0 / frequencyMHz, SC_US);
|
||||
|
||||
if (!value["name"].is_string())
|
||||
SC_REPORT_FATAL("TraceSetup", "No trace name defined.");
|
||||
|
||||
std::string name = value["name"];
|
||||
|
||||
size_t pos = name.rfind('.');
|
||||
if (pos == std::string::npos)
|
||||
throw std::runtime_error("Name of the trace file does not contain a valid extension.");
|
||||
unsigned int maxPendingReadRequests = 0;
|
||||
unsigned int maxPendingWriteRequests = 0;
|
||||
|
||||
// Get the extension and make it lower case
|
||||
std::string ext = name.substr(pos + 1);
|
||||
std::transform(ext.begin(), ext.end(), ext.begin(), ::tolower);
|
||||
if (value["maxPendingReadRequests"].is_number_unsigned())
|
||||
maxPendingReadRequests = value["maxPendingReadRequests"];
|
||||
|
||||
std::string stlFile = pathToResources + std::string("traces/") + name;
|
||||
std::string moduleName = name;
|
||||
if (value["maxPendingWriteRequests"].is_number_unsigned())
|
||||
maxPendingWriteRequests = value["maxPendingWriteRequests"];
|
||||
|
||||
// replace all '.' to '_'
|
||||
std::replace(moduleName.begin(), moduleName.end(), '.', '_');
|
||||
std::string type;
|
||||
|
||||
TracePlayer *player;
|
||||
if (ext == "stl")
|
||||
player = new StlPlayer(moduleName.c_str(), stlFile, playerClk, this, false);
|
||||
else if (ext == "rstl")
|
||||
player = new StlPlayer(moduleName.c_str(), stlFile, playerClk, this, true);
|
||||
// Defaulting to type "player" when not specified
|
||||
if (!value["type"].is_string())
|
||||
type = "player";
|
||||
else
|
||||
throw std::runtime_error("Unsupported file extension in " + name);
|
||||
type = value["type"];
|
||||
|
||||
players->push_back(player);
|
||||
if (type == "player")
|
||||
{
|
||||
size_t pos = name.rfind('.');
|
||||
if (pos == std::string::npos)
|
||||
throw std::runtime_error("Name of the trace file does not contain a valid extension.");
|
||||
|
||||
if (Configuration::getInstance().simulationProgressBar)
|
||||
totalTransactions += player->getNumberOfLines(stlFile);
|
||||
// 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 + std::string("traces/") + name;
|
||||
std::string moduleName = name;
|
||||
|
||||
// replace all '.' to '_'
|
||||
std::replace(moduleName.begin(), moduleName.end(), '.', '_');
|
||||
|
||||
TracePlayer *player;
|
||||
if (ext == "stl")
|
||||
player = new StlPlayer(moduleName.c_str(), stlFile, playerClk,
|
||||
maxPendingReadRequests, maxPendingWriteRequests, this, false);
|
||||
else if (ext == "rstl")
|
||||
player = new StlPlayer(moduleName.c_str(), stlFile, playerClk,
|
||||
maxPendingReadRequests, maxPendingWriteRequests, this, true);
|
||||
else
|
||||
throw std::runtime_error("Unsupported file extension in " + name);
|
||||
|
||||
players.push_back(player);
|
||||
|
||||
if (Configuration::getInstance().simulationProgressBar)
|
||||
totalTransactions += player->getNumberOfLines(stlFile);
|
||||
}
|
||||
else if (type == "generator")
|
||||
{
|
||||
if (!value["numRequests"].is_number_unsigned())
|
||||
SC_REPORT_FATAL("TraceSetup", "Number of requests is not a number.");
|
||||
|
||||
uint64_t numRequests = value["numRequests"];
|
||||
|
||||
if (!value["rwRatio"].is_number_float())
|
||||
SC_REPORT_FATAL("TraceSetup", "Read/Write ratio is not a floating point number.");
|
||||
|
||||
float rwRatio = value["rwRatio"];
|
||||
|
||||
if (!value["addressDistribution"].is_string())
|
||||
SC_REPORT_FATAL("TraceSetup", "Address distribution not defined.");
|
||||
|
||||
AddressDistribution addressDistribution = AddressDistribution::Sequential;
|
||||
std::string addressDistributionString = value["addressDistribution"];
|
||||
if (addressDistributionString == "sequential")
|
||||
addressDistribution = AddressDistribution::Sequential;
|
||||
else if (addressDistributionString == "random")
|
||||
addressDistribution = AddressDistribution::Random;
|
||||
else
|
||||
SC_REPORT_FATAL("TraceSetup", "Address distribution must either be sequential or random.");
|
||||
|
||||
unsigned int addressIncrement = 0x0;
|
||||
unsigned int seed = 0;
|
||||
if (addressDistribution == AddressDistribution::Sequential) {
|
||||
if (!value["addressIncrement"].is_number_unsigned())
|
||||
SC_REPORT_FATAL("TraceSetup", "Address increment is not a number.");
|
||||
|
||||
addressIncrement = value["addressIncrement"];
|
||||
} else {
|
||||
// addressDistribution == AddressDistribution::Random
|
||||
if (!value["seed"].is_number_unsigned())
|
||||
SC_REPORT_FATAL("TraceSetup", "Seed is not a number.");
|
||||
|
||||
seed = value["seed"];
|
||||
}
|
||||
|
||||
TracePlayer *player = new TraceGenerator(name.c_str(), playerClk, numRequests,
|
||||
maxPendingReadRequests, maxPendingWriteRequests,
|
||||
rwRatio, addressDistribution,
|
||||
addressIncrement, seed, this);
|
||||
|
||||
players.push_back(player);
|
||||
|
||||
if (Configuration::getInstance().simulationProgressBar)
|
||||
totalTransactions += numRequests;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
remainingTransactions = totalTransactions;
|
||||
numberOfTracePlayers = players->size();
|
||||
numberOfTracePlayers = players.size();
|
||||
}
|
||||
|
||||
void TraceSetup::tracePlayerTerminates()
|
||||
|
||||
@@ -46,9 +46,9 @@ class TracePlayer;
|
||||
class TraceSetup
|
||||
{
|
||||
public:
|
||||
TraceSetup(std::string uri,
|
||||
std::string pathToResources,
|
||||
std::vector<TracePlayer *> *devices);
|
||||
TraceSetup(const std::string &uri,
|
||||
const std::string &pathToResources,
|
||||
std::vector<TracePlayer *> &devices);
|
||||
|
||||
void tracePlayerTerminates();
|
||||
void transactionFinished();
|
||||
|
||||
@@ -109,7 +109,7 @@ int sc_main(int argc, char **argv)
|
||||
dramSys = new DRAMSys("DRAMSys", simulationJson, resources);
|
||||
|
||||
// Instantiate STL Players:
|
||||
TraceSetup *setup = 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++)
|
||||
|
||||
Reference in New Issue
Block a user