Allow variable data length in memory manager.
This commit is contained in:
@@ -192,7 +192,7 @@ void LengthConverter::createChildTranses(tlm_generic_payload* parentTrans)
|
||||
ParentExtension::setExtension(parentTrans, std::move(childTranses));
|
||||
}
|
||||
|
||||
LengthConverter::MemoryManager::MemoryManager(bool storageEnabled, size_t maxDataLength)
|
||||
LengthConverter::MemoryManager::MemoryManager(bool storageEnabled, unsigned maxDataLength)
|
||||
: storageEnabled(storageEnabled), maxDataLength(maxDataLength)
|
||||
{}
|
||||
|
||||
|
||||
@@ -88,7 +88,7 @@ private:
|
||||
class MemoryManager : public tlm::tlm_mm_interface
|
||||
{
|
||||
public:
|
||||
MemoryManager(bool storageEnabled, std::size_t maxDataLength);
|
||||
MemoryManager(bool storageEnabled, unsigned maxDataLength);
|
||||
~MemoryManager() override;
|
||||
tlm::tlm_generic_payload* allocate();
|
||||
void free(tlm::tlm_generic_payload* payload) override;
|
||||
@@ -96,7 +96,7 @@ private:
|
||||
private:
|
||||
std::stack<tlm::tlm_generic_payload*> freePayloads;
|
||||
bool storageEnabled = false;
|
||||
std::size_t maxDataLength;
|
||||
unsigned maxDataLength;
|
||||
} memoryManager;
|
||||
|
||||
class ChildExtension : public tlm::tlm_extension<ChildExtension>
|
||||
|
||||
@@ -51,36 +51,36 @@ MemoryManager::MemoryManager()
|
||||
|
||||
MemoryManager::~MemoryManager()
|
||||
{
|
||||
for (tlm_generic_payload *payload : freePayloads)
|
||||
for (auto& innerBuffer : freePayloads)
|
||||
{
|
||||
while (!innerBuffer.second.empty())
|
||||
{
|
||||
tlm_generic_payload* payload = innerBuffer.second.top();
|
||||
if (storageEnabled)
|
||||
{
|
||||
// Delete data buffer
|
||||
delete[] payload->get_data_ptr();
|
||||
}
|
||||
// Delete all extensions
|
||||
payload->reset();
|
||||
delete payload;
|
||||
innerBuffer.second.pop();
|
||||
numberOfFrees++;
|
||||
}
|
||||
}
|
||||
|
||||
// Comment in if you are suspecting a memory leak in the manager
|
||||
//PRINTDEBUGMESSAGE("MemoryManager","Number of allocated payloads: " + to_string(numberOfAllocations));
|
||||
//PRINTDEBUGMESSAGE("MemoryManager","Number of freed payloads: " + to_string(numberOfFrees));
|
||||
}
|
||||
|
||||
tlm_generic_payload *MemoryManager::allocate()
|
||||
tlm_generic_payload *MemoryManager::allocate(unsigned dataLength)
|
||||
{
|
||||
if (freePayloads.empty())
|
||||
if (freePayloads[dataLength].empty())
|
||||
{
|
||||
numberOfAllocations++;
|
||||
tlm_generic_payload *payload = new tlm_generic_payload(this);
|
||||
auto* payload = new tlm_generic_payload(this);
|
||||
|
||||
if (storageEnabled)
|
||||
{
|
||||
// Allocate a data buffer and initialize it with zeroes:
|
||||
unsigned int dataLength = Configuration::getInstance().memSpec->maxBytesPerBurst;
|
||||
unsigned char *data = new unsigned char[dataLength];
|
||||
auto* data = new unsigned char[dataLength];
|
||||
std::fill(data, data + dataLength, 0);
|
||||
payload->set_data_ptr(data);
|
||||
}
|
||||
@@ -89,13 +89,14 @@ tlm_generic_payload *MemoryManager::allocate()
|
||||
}
|
||||
else
|
||||
{
|
||||
tlm_generic_payload *result = freePayloads.back();
|
||||
freePayloads.pop_back();
|
||||
tlm_generic_payload *result = freePayloads[dataLength].top();
|
||||
freePayloads[dataLength].pop();
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
void MemoryManager::free(tlm_generic_payload *payload)
|
||||
{
|
||||
freePayloads.push_back(payload);
|
||||
unsigned dataLength = payload->get_data_length();
|
||||
freePayloads[dataLength].push(payload);
|
||||
}
|
||||
|
||||
@@ -37,7 +37,8 @@
|
||||
#ifndef MEMORYMANAGER_H
|
||||
#define MEMORYMANAGER_H
|
||||
|
||||
#include <vector>
|
||||
#include <unordered_map>
|
||||
#include <stack>
|
||||
|
||||
#include <tlm>
|
||||
|
||||
@@ -46,13 +47,13 @@ class MemoryManager : public tlm::tlm_mm_interface
|
||||
public:
|
||||
MemoryManager();
|
||||
~MemoryManager() override;
|
||||
tlm::tlm_generic_payload *allocate();
|
||||
tlm::tlm_generic_payload *allocate(unsigned dataLength);
|
||||
void free(tlm::tlm_generic_payload *payload) override;
|
||||
|
||||
private:
|
||||
uint64_t numberOfAllocations;
|
||||
uint64_t numberOfFrees;
|
||||
std::vector<tlm::tlm_generic_payload *> freePayloads;
|
||||
std::unordered_map<unsigned, std::stack<tlm::tlm_generic_payload *>> freePayloads;
|
||||
bool storageEnabled = false;
|
||||
};
|
||||
|
||||
|
||||
@@ -101,7 +101,7 @@ void StlPlayer::sendNextPayload()
|
||||
}
|
||||
|
||||
// Allocate a generic payload for this request.
|
||||
tlm_generic_payload *payload = setup->allocatePayload();
|
||||
tlm_generic_payload *payload = setup->allocatePayload(lineIterator->dataLength);
|
||||
payload->acquire();
|
||||
|
||||
// Fill up the payload.
|
||||
@@ -169,20 +169,20 @@ void StlPlayer::parseTraceFile()
|
||||
// Get the timestamp for the transaction.
|
||||
iss >> element;
|
||||
if (element.empty())
|
||||
SC_REPORT_FATAL("StlPlayer", ("Malformed trace file line " + std::to_string(lineCnt) + ").").c_str());
|
||||
SC_REPORT_FATAL("StlPlayer", ("Malformed trace file line " + std::to_string(lineCnt) + ".").c_str());
|
||||
content.sendingTime = playerClk * static_cast<double>(std::stoull(element));
|
||||
|
||||
// Get the optional burst length and command
|
||||
iss >> element;
|
||||
if (element.empty())
|
||||
SC_REPORT_FATAL("StlPlayer", ("Malformed trace file line " + std::to_string(lineCnt) + ").").c_str());
|
||||
SC_REPORT_FATAL("StlPlayer", ("Malformed trace file line " + std::to_string(lineCnt) + ".").c_str());
|
||||
if (element.at(0) == '(')
|
||||
{
|
||||
element.erase(0, 1);
|
||||
content.dataLength = std::stoul(element);
|
||||
iss >> element;
|
||||
if (element.empty())
|
||||
SC_REPORT_FATAL("StlPlayer", ("Malformed trace file line " + std::to_string(lineCnt) + ").").c_str());
|
||||
SC_REPORT_FATAL("StlPlayer", ("Malformed trace file line " + std::to_string(lineCnt) + ".").c_str());
|
||||
}
|
||||
else
|
||||
content.dataLength = defaultDataLength;
|
||||
@@ -192,12 +192,12 @@ void StlPlayer::parseTraceFile()
|
||||
else if (element == "write")
|
||||
content.command = TLM_WRITE_COMMAND;
|
||||
else
|
||||
SC_REPORT_FATAL("StlPlayer", ("Malformed trace file line " + std::to_string(lineCnt) + ").").c_str());
|
||||
SC_REPORT_FATAL("StlPlayer", ("Malformed trace file line " + std::to_string(lineCnt) + ".").c_str());
|
||||
|
||||
// Get the address.
|
||||
iss >> element;
|
||||
if (element.empty())
|
||||
SC_REPORT_FATAL("StlPlayer", ("Malformed trace file line " + std::to_string(lineCnt) + ").").c_str());
|
||||
SC_REPORT_FATAL("StlPlayer", ("Malformed trace file line " + std::to_string(lineCnt) + ".").c_str());
|
||||
content.address = std::stoull(element, nullptr, 16);
|
||||
|
||||
// Get the data if necessary.
|
||||
@@ -209,7 +209,7 @@ void StlPlayer::parseTraceFile()
|
||||
// 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 (element.length() != (content.dataLength * 2 + 2))
|
||||
SC_REPORT_FATAL("StlPlayer", ("Malformed trace file line " + std::to_string(lineCnt) + ").").c_str());
|
||||
SC_REPORT_FATAL("StlPlayer", ("Malformed trace file line " + std::to_string(lineCnt) + ".").c_str());
|
||||
|
||||
// Set data
|
||||
for (unsigned i = 0; i < content.dataLength; i++)
|
||||
|
||||
@@ -226,6 +226,7 @@ TraceSetup::TraceSetup(const std::string &uri,
|
||||
|
||||
remainingTransactions = totalTransactions;
|
||||
numberOfTrafficInitiators = players.size();
|
||||
defaultDataLength = Configuration::getInstance().memSpec->defaultBytesPerBurst;
|
||||
}
|
||||
|
||||
void TraceSetup::trafficInitiatorTerminates()
|
||||
@@ -246,9 +247,14 @@ void TraceSetup::transactionFinished()
|
||||
std::cout << std::endl;
|
||||
}
|
||||
|
||||
tlm_generic_payload *TraceSetup::allocatePayload(unsigned dataLength)
|
||||
{
|
||||
return memoryManager.allocate(dataLength);
|
||||
}
|
||||
|
||||
tlm_generic_payload *TraceSetup::allocatePayload()
|
||||
{
|
||||
return memoryManager.allocate();
|
||||
return allocatePayload(defaultDataLength);
|
||||
}
|
||||
|
||||
void TraceSetup::loadBar(uint64_t x, uint64_t n, unsigned int w, unsigned int granularity)
|
||||
|
||||
@@ -55,6 +55,7 @@ public:
|
||||
|
||||
void trafficInitiatorTerminates();
|
||||
void transactionFinished();
|
||||
tlm::tlm_generic_payload *allocatePayload(unsigned dataLength);
|
||||
tlm::tlm_generic_payload *allocatePayload();
|
||||
|
||||
private:
|
||||
@@ -63,6 +64,7 @@ private:
|
||||
uint64_t remainingTransactions;
|
||||
unsigned int finishedTrafficInitiators = 0;
|
||||
MemoryManager memoryManager;
|
||||
unsigned defaultDataLength = 64;
|
||||
|
||||
static void loadBar(uint64_t x, uint64_t n, unsigned int w = 50, unsigned int granularity = 1);
|
||||
};
|
||||
|
||||
16
README.md
16
README.md
@@ -123,7 +123,8 @@ The JSON code below shows an example configuration:
|
||||
"tracesetup": [
|
||||
{
|
||||
"clkMhz": 300,
|
||||
"name": "ddr3_example.stl"
|
||||
"name": "ddr3_example.stl",
|
||||
"addLengthConverter": true
|
||||
},
|
||||
{
|
||||
"clkMhz": 2000,
|
||||
@@ -160,6 +161,7 @@ Fields Description:
|
||||
|
||||
Each **trace setup** device configuration can be a **trace player** ("type": "player"), a **traffic generator** ("type": "generator") or a **row hammer generator** ("type": "hammer"). By not specifing the **type** parameter, the device will act as a **trace player**.
|
||||
All device configurations must define a **clkMhz** (operation frequency of the **traffic initiator**) and a **name** (in case of a trace player this specifies the **trace file** to play; in case of a generator this field is only for identification purposes).
|
||||
The optional parameter **addLengthConverter** adds a transaction length converter between initiator and DRAMSys. This unit divides a large transaction up into several smaller transactions with the maximum length of one DRAM burst access.
|
||||
The **maxPendingReadRequests** and **maxPendingWriteRequests** parameters define the maximum number of outstanding read/write requests. The current implementation delays all memory accesses when one limit is reached. The default value (0) disables the limit.
|
||||
|
||||
A **traffic generator** can be configured to generate **numRequests** requests in total, of which the **rwRatio** field defines the probability of one request being a read request. The **seed** parameter can be used to produce identical results for all simulations. **minAddress** and **maxAddress** specify the address range, by default the whole address range is used. The parameter **addressDistribution** can either be set to **"random"** or **"sequential"**. In case of **"sequential"** the additional **addressIncrement** field must be specified, defining the address increment after each request.
|
||||
@@ -171,7 +173,7 @@ Most configuration fields reference other JSON files which contain more speciali
|
||||
|
||||
#### Trace Files
|
||||
|
||||
A **trace file** is a prerecorded file containing memory transactions. Each memory transaction has a time stamp that tells the simulator when it shall happen, a transaction type (*read* or *write*) and a hexadecimal memory address.
|
||||
A **trace file** is a prerecorded file containing memory transactions. Each memory transaction has a time stamp that tells the simulator when it shall happen, a transaction type (*read* or *write*) and a hexadecimal memory address. The optional length parameter (in bytes) allows sending transactions with a custom length that does not match the length of a single DRAM burst access. In this case a length converter has to be added. Write transactions also have to specify a data field when storage is enabled in DRAMSys.
|
||||
|
||||
There are two different kinds of trace files. They differ in their timing behavior and are distinguished by their file extension.
|
||||
|
||||
@@ -183,11 +185,11 @@ Syntax example:
|
||||
|
||||
```
|
||||
# Comment lines begin with #
|
||||
# [clock-cyle]: [write|read] [hex-address] [hex-data (optional)]
|
||||
# cycle: [(length)] command hex-address [hex-data]
|
||||
31: read 0x400140
|
||||
33: read 0x400160
|
||||
56: write 0x7fff8000 0x123456789abcdef...
|
||||
81: read 0x400180
|
||||
81: (128) read 0x400180
|
||||
```
|
||||
|
||||
##### Relative STL Traces (.rstl)
|
||||
@@ -198,11 +200,11 @@ Syntax example:
|
||||
|
||||
```
|
||||
# Comment lines begin with #
|
||||
# [clock-cyle]: [write|read] [hex-address] [hex-data (optional)]
|
||||
# cycle: [(length)] command hex-address [hex-data]
|
||||
31: read 0x400140
|
||||
2: read 0x400160
|
||||
2: (512) read 0x400160
|
||||
23: write 0x7fff8000 0x123456789abcdef...
|
||||
25: read 0x400180
|
||||
10: read 0x400180
|
||||
```
|
||||
|
||||
##### Elastic Traces
|
||||
|
||||
Reference in New Issue
Block a user