Merge branch 'feat/length_conversion' into 'develop'
Length conversion, variable transaction length in stl files. See merge request ems/astdm/modeling.dram/dram.sys!342
This commit is contained in:
@@ -34,6 +34,7 @@
|
||||
* Robert Gernhardt
|
||||
* Matthias Jung
|
||||
* Eder F. Zulian
|
||||
* Lukas Steiner
|
||||
*/
|
||||
|
||||
#include <fstream>
|
||||
@@ -69,7 +70,7 @@ TlmRecorder::TlmRecorder(const std::string &name, const std::string &dbName) :
|
||||
PRINTDEBUGMESSAGE(name, "Starting new database transaction");
|
||||
}
|
||||
|
||||
TlmRecorder::~TlmRecorder()
|
||||
void TlmRecorder::finalize()
|
||||
{
|
||||
if (db)
|
||||
closeConnection();
|
||||
|
||||
@@ -34,6 +34,7 @@
|
||||
* Robert Gernhardt
|
||||
* Matthias Jung
|
||||
* Eder F. Zulian
|
||||
* Lukas Steiner
|
||||
*/
|
||||
|
||||
#ifndef TLMRECORDER_H
|
||||
@@ -54,7 +55,8 @@ class TlmRecorder
|
||||
{
|
||||
public:
|
||||
TlmRecorder(const std::string &name, const std::string &dbName);
|
||||
~TlmRecorder();
|
||||
TlmRecorder(const TlmRecorder&) = delete;
|
||||
TlmRecorder(TlmRecorder&&) = default;
|
||||
|
||||
void recordMcConfig(std::string _mcconfig)
|
||||
{
|
||||
@@ -78,7 +80,7 @@ public:
|
||||
void recordDebugMessage(const std::string &message, const sc_core::sc_time &time);
|
||||
void updateDataStrobe(const sc_core::sc_time &begin, const sc_core::sc_time &end,
|
||||
tlm::tlm_generic_payload &trans);
|
||||
void closeConnection();
|
||||
void finalize();
|
||||
|
||||
private:
|
||||
struct Transaction
|
||||
@@ -113,6 +115,7 @@ private:
|
||||
static void executeSqlStatement(sqlite3_stmt *statement);
|
||||
|
||||
void openDB(const std::string &dbName);
|
||||
void closeConnection();
|
||||
|
||||
void introduceTransactionSystem(tlm::tlm_generic_payload &trans);
|
||||
void removeTransactionFromSystem(tlm::tlm_generic_payload &trans);
|
||||
|
||||
@@ -163,7 +163,6 @@ public:
|
||||
BankGroup bankGroup, Bank bank, Row row,
|
||||
Column column, unsigned int burstLength,
|
||||
uint64_t threadPayloadID, uint64_t channelPayloadID);
|
||||
|
||||
tlm::tlm_extension_base *clone() const override;
|
||||
void copy_from(const tlm::tlm_extension_base &ext) override;
|
||||
|
||||
|
||||
@@ -163,7 +163,7 @@ void setUpDummy(tlm_generic_payload &payload, uint64_t channelPayloadID, Rank ra
|
||||
payload.set_dmi_allowed(false);
|
||||
payload.set_byte_enable_length(0);
|
||||
payload.set_streaming_width(0);
|
||||
payload.set_extension(new DramExtension(Thread(UINT_MAX), Channel(0), rank, bankGroup,
|
||||
bank, Row(0), Column(0), 0, 0, channelPayloadID));
|
||||
payload.set_extension(new DramExtension(Thread(UINT_MAX), Channel(0), rank, bankGroup, bank, Row(0), Column(0),
|
||||
0, 0, channelPayloadID));
|
||||
payload.set_extension(new GenerationExtension(SC_ZERO_TIME));
|
||||
}
|
||||
|
||||
@@ -38,8 +38,6 @@
|
||||
* Luiza Correa
|
||||
*/
|
||||
|
||||
#include <cassert>
|
||||
|
||||
#include "Configuration.h"
|
||||
#include "memspec/MemSpecDDR3.h"
|
||||
#include "memspec/MemSpecDDR4.h"
|
||||
@@ -227,15 +225,6 @@ void Configuration::setParameter(const std::string &name, const nlohmann::json &
|
||||
useMalloc = value;
|
||||
else if (name == "CheckTLM2Protocol")
|
||||
checkTLM2Protocol = value;
|
||||
else if (name == "ECCControllerMode")
|
||||
{
|
||||
if (value == "Disabled")
|
||||
eccMode = ECCMode::Disabled;
|
||||
else if (value == "Hamming")
|
||||
eccMode = ECCMode::Hamming;
|
||||
else
|
||||
SC_REPORT_FATAL("Configuration", "Unsupported ECC mode!");
|
||||
}
|
||||
// Specification for ErrorChipSeed, ErrorCSVFile path and StoreMode
|
||||
else if (name == "ErrorChipSeed")
|
||||
errorChipSeed = value;
|
||||
@@ -285,8 +274,8 @@ void Configuration::setParameter(const std::string &name, const nlohmann::json &
|
||||
else if (name == "GeneratePowerMap")
|
||||
temperatureSim.generatePowerMap = value;
|
||||
else
|
||||
SC_REPORT_FATAL("Configuration",
|
||||
("Parameter " + name + " not defined in Configuration").c_str());
|
||||
SC_REPORT_WARNING("Configuration",
|
||||
("Parameter " + name + " not defined in Configuration").c_str());
|
||||
}
|
||||
|
||||
void Configuration::setPathToResources(const std::string &path)
|
||||
@@ -294,19 +283,6 @@ void Configuration::setPathToResources(const std::string &path)
|
||||
temperatureSim.setPathToResources(path);
|
||||
}
|
||||
|
||||
// Changes the number of bytes depeding on the ECC Controller. This function is needed for modules which get data directly or indirectly from the ECC Controller
|
||||
unsigned int Configuration::adjustNumBytesAfterECC(unsigned nBytes) const
|
||||
{
|
||||
// Manipulate the number of bytes only if there is an ECC Controller selected
|
||||
if (eccMode == ECCMode::Disabled)
|
||||
return nBytes;
|
||||
else // if (eccMode == ECCMode::Hamming)
|
||||
{
|
||||
assert(pECC != nullptr);
|
||||
return pECC->AllocationSize(nBytes);
|
||||
}
|
||||
}
|
||||
|
||||
void Configuration::loadSimConfig(Configuration &config, const std::string &simconfigUri)
|
||||
{
|
||||
json doc = parseJSON(simconfigUri);
|
||||
|
||||
@@ -45,7 +45,6 @@
|
||||
|
||||
#include <systemc>
|
||||
#include "memspec/MemSpec.h"
|
||||
#include "../error/eccbaseclass.h"
|
||||
#include "TemperatureSimConfig.h"
|
||||
|
||||
class Configuration
|
||||
@@ -97,8 +96,6 @@ public:
|
||||
bool thermalSimulation = false;
|
||||
bool simulationProgressBar = false;
|
||||
bool checkTLM2Protocol = false;
|
||||
enum class ECCMode {Disabled, Hamming} eccMode = ECCMode::Disabled;
|
||||
ECCBaseClass *pECC = nullptr;
|
||||
bool useMalloc = false;
|
||||
unsigned long long int addressOffset = 0;
|
||||
|
||||
@@ -115,7 +112,6 @@ public:
|
||||
// Temperature Simulation related
|
||||
TemperatureSimConfig temperatureSim;
|
||||
|
||||
unsigned int adjustNumBytesAfterECC(unsigned bytes) const;
|
||||
void setPathToResources(const std::string &path);
|
||||
|
||||
static void loadMCConfig(Configuration &config, const std::string &_mcconfigUri);
|
||||
|
||||
@@ -55,16 +55,19 @@ MemSpec::MemSpec(json &memspec, MemoryType memoryType,
|
||||
numberOfDevices(numberOfDevices),
|
||||
numberOfRows(parseUint(memspec["memarchitecturespec"], "nbrOfRows")),
|
||||
numberOfColumns(parseUint(memspec["memarchitecturespec"], "nbrOfColumns")),
|
||||
burstLength(parseUint(memspec["memarchitecturespec"], "burstLength")),
|
||||
defaultBurstLength(parseUint(memspec["memarchitecturespec"], "burstLength")),
|
||||
maxBurstLength(memspec["memarchitecturespec"]["maxBurstLength"].is_number_unsigned() ?
|
||||
static_cast<unsigned>(memspec["memarchitecturespec"]["maxBurstLength"]) : defaultBurstLength),
|
||||
dataRate(parseUint(memspec["memarchitecturespec"], "dataRate")),
|
||||
bitWidth(parseUint(memspec["memarchitecturespec"], "width")),
|
||||
dataBusWidth(bitWidth * numberOfDevices),
|
||||
bytesPerBurst((burstLength * dataBusWidth) / 8),
|
||||
defaultBytesPerBurst((defaultBurstLength * dataBusWidth) / 8),
|
||||
maxBytesPerBurst((maxBurstLength * dataBusWidth) / 8),
|
||||
fCKMHz(parseUdouble(memspec["memtimingspec"], "clkMhz")),
|
||||
tCK(sc_time(1.0 / fCKMHz, SC_US)),
|
||||
memoryId(parseString(memspec, "memoryId")),
|
||||
memoryType(memoryType),
|
||||
burstDuration(tCK * (static_cast<double>(burstLength) / dataRate)),
|
||||
burstDuration(tCK * (static_cast<double>(defaultBurstLength) / dataRate)),
|
||||
memorySizeBytes(0)
|
||||
{
|
||||
commandLengthInCycles = std::vector<unsigned>(Command::numberOfCommands(), 1);
|
||||
|
||||
@@ -60,11 +60,13 @@ public:
|
||||
const unsigned numberOfDevices;
|
||||
const unsigned numberOfRows;
|
||||
const unsigned numberOfColumns;
|
||||
const unsigned burstLength;
|
||||
const unsigned defaultBurstLength;
|
||||
const unsigned maxBurstLength;
|
||||
const unsigned dataRate;
|
||||
const unsigned bitWidth;
|
||||
const unsigned dataBusWidth;
|
||||
const unsigned bytesPerBurst;
|
||||
const unsigned defaultBytesPerBurst;
|
||||
const unsigned maxBytesPerBurst;
|
||||
|
||||
// Clock
|
||||
const double fCKMHz;
|
||||
|
||||
@@ -39,7 +39,7 @@
|
||||
using namespace sc_core;
|
||||
using namespace tlm;
|
||||
|
||||
ControllerRecordable::ControllerRecordable(const sc_module_name &name, TlmRecorder *tlmRecorder)
|
||||
ControllerRecordable::ControllerRecordable(const sc_module_name &name, TlmRecorder& tlmRecorder)
|
||||
: Controller(name), tlmRecorder(tlmRecorder)
|
||||
{
|
||||
if (Configuration::getInstance().enableWindowing)
|
||||
@@ -78,7 +78,7 @@ void ControllerRecordable::sendToDram(Command command, tlm_generic_payload *payl
|
||||
if (command.isCasCommand())
|
||||
{
|
||||
TimeInterval dataStrobe = Configuration::getInstance().memSpec->getIntervalOnDataStrobe(command, *payload);
|
||||
tlmRecorder->updateDataStrobe(sc_time_stamp() + delay + dataStrobe.start,
|
||||
tlmRecorder.updateDataStrobe(sc_time_stamp() + delay + dataStrobe.start,
|
||||
sc_time_stamp() + delay + dataStrobe.end, *payload);
|
||||
}
|
||||
tlm_phase phase = command.toPhase();
|
||||
@@ -103,7 +103,7 @@ void ControllerRecordable::recordPhase(tlm_generic_payload &trans, const tlm_pha
|
||||
bg) + " bank " + std::to_string(bank) + " row " + std::to_string(row) + " column " +
|
||||
std::to_string(col) + " id " + std::to_string(id) + " at " + recTime.to_string());
|
||||
|
||||
tlmRecorder->recordPhase(trans, phase, recTime);
|
||||
tlmRecorder.recordPhase(trans, phase, recTime);
|
||||
}
|
||||
|
||||
void ControllerRecordable::controllerMethod()
|
||||
@@ -128,7 +128,7 @@ void ControllerRecordable::controllerMethod()
|
||||
slidingAverageBufferDepth[index] = SC_ZERO_TIME;
|
||||
}
|
||||
|
||||
tlmRecorder->recordBufferDepth(sc_time_stamp().to_seconds(), windowAverageBufferDepth);
|
||||
tlmRecorder.recordBufferDepth(sc_time_stamp().to_seconds(), windowAverageBufferDepth);
|
||||
|
||||
Controller::controllerMethod();
|
||||
|
||||
@@ -136,7 +136,7 @@ void ControllerRecordable::controllerMethod()
|
||||
lastNumberOfBeatsServed = numberOfBeatsServed;
|
||||
sc_time windowActiveTime = activeTimeMultiplier * static_cast<double>(windowNumberOfBeatsServed);
|
||||
double windowAverageBandwidth = windowActiveTime / windowSizeTime;
|
||||
tlmRecorder->recordBandwidth(sc_time_stamp().to_seconds(), windowAverageBandwidth);
|
||||
tlmRecorder.recordBandwidth(sc_time_stamp().to_seconds(), windowAverageBandwidth);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
@@ -43,7 +43,7 @@
|
||||
class ControllerRecordable final : public Controller
|
||||
{
|
||||
public:
|
||||
ControllerRecordable(const sc_core::sc_module_name &name, TlmRecorder *tlmRecorder);
|
||||
ControllerRecordable(const sc_core::sc_module_name &name, TlmRecorder& tlmRecorder);
|
||||
~ControllerRecordable() override = default;
|
||||
|
||||
protected:
|
||||
@@ -59,7 +59,7 @@ protected:
|
||||
|
||||
private:
|
||||
void recordPhase(tlm::tlm_generic_payload &trans, const tlm::tlm_phase &phase, const sc_core::sc_time &delay);
|
||||
TlmRecorder *tlmRecorder;
|
||||
TlmRecorder& tlmRecorder;
|
||||
|
||||
sc_core::sc_event windowEvent;
|
||||
sc_core::sc_time windowSizeTime;
|
||||
|
||||
@@ -54,7 +54,7 @@ CheckerDDR3::CheckerDDR3()
|
||||
lastCommandOnBus = sc_max_time();
|
||||
last4Activates = std::vector<std::queue<sc_time>>(memSpec->numberOfRanks);
|
||||
|
||||
tBURST = memSpec->burstLength / memSpec->dataRate * memSpec->tCK;
|
||||
tBURST = memSpec->defaultBurstLength / memSpec->dataRate * memSpec->tCK;
|
||||
tRDWR = memSpec->tRL + tBURST + 2 * memSpec->tCK - memSpec->tWL;
|
||||
tRDWR_R = memSpec->tRL + tBURST + memSpec->tRTRS - memSpec->tWL;
|
||||
tWRRD = memSpec->tWL + tBURST + memSpec->tWTR - memSpec->tAL;
|
||||
@@ -75,6 +75,8 @@ sc_time CheckerDDR3::timeToSatisfyConstraints(Command command, tlm_generic_paylo
|
||||
|
||||
if (command == Command::RD || command == Command::RDA)
|
||||
{
|
||||
assert(DramExtension::getBurstLength(payload) == 8);
|
||||
|
||||
lastCommandStart = lastScheduledByCommandAndBank[Command::ACT][bank.ID()];
|
||||
if (lastCommandStart != sc_max_time())
|
||||
earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRCD - memSpec->tAL);
|
||||
@@ -128,6 +130,8 @@ sc_time CheckerDDR3::timeToSatisfyConstraints(Command command, tlm_generic_paylo
|
||||
}
|
||||
else if (command == Command::WR || command == Command::WRA)
|
||||
{
|
||||
assert(DramExtension::getBurstLength(payload) == 8);
|
||||
|
||||
lastCommandStart = lastScheduledByCommandAndBank[Command::ACT][bank.ID()];
|
||||
if (lastCommandStart != sc_max_time())
|
||||
earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRCD - memSpec->tAL);
|
||||
|
||||
@@ -56,7 +56,7 @@ CheckerDDR4::CheckerDDR4()
|
||||
lastCommandOnBus = sc_max_time();
|
||||
last4Activates = std::vector<std::queue<sc_time>>(memSpec->numberOfRanks);
|
||||
|
||||
tBURST = memSpec->burstLength / memSpec->dataRate * memSpec->tCK;
|
||||
tBURST = memSpec->defaultBurstLength / memSpec->dataRate * memSpec->tCK;
|
||||
tRDWR = memSpec->tRL + tBURST + memSpec->tCK - memSpec->tWL + memSpec->tWPRE;
|
||||
tRDWR_R = memSpec->tRL + tBURST + memSpec->tRTRS - memSpec->tWL + memSpec->tWPRE;
|
||||
tWRRD_S = memSpec->tWL + tBURST + memSpec->tWTR_S - memSpec->tAL;
|
||||
@@ -79,6 +79,8 @@ sc_time CheckerDDR4::timeToSatisfyConstraints(Command command, tlm_generic_paylo
|
||||
|
||||
if (command == Command::RD || command == Command::RDA)
|
||||
{
|
||||
assert(DramExtension::getBurstLength(payload) == 8);
|
||||
|
||||
lastCommandStart = lastScheduledByCommandAndBank[Command::ACT][bank.ID()];
|
||||
if (lastCommandStart != sc_max_time())
|
||||
earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRCD - memSpec->tAL);
|
||||
@@ -148,6 +150,8 @@ sc_time CheckerDDR4::timeToSatisfyConstraints(Command command, tlm_generic_paylo
|
||||
}
|
||||
else if (command == Command::WR || command == Command::WRA)
|
||||
{
|
||||
assert(DramExtension::getBurstLength(payload) == 8);
|
||||
|
||||
lastCommandStart = lastScheduledByCommandAndBank[Command::ACT][bank.ID()];
|
||||
if (lastCommandStart != sc_max_time())
|
||||
earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRCD - memSpec->tAL);
|
||||
|
||||
@@ -131,7 +131,9 @@ sc_time CheckerDDR5::timeToSatisfyConstraints(Command command, tlm_generic_paylo
|
||||
if (command == Command::RD || command == Command::RDA)
|
||||
{
|
||||
unsigned burstLength = DramExtension::getBurstLength(payload);
|
||||
assert((burstLength == 16) || (burstLength == 32));
|
||||
assert(!(burstLength == 32) || (memSpec->bitWidth == 4));
|
||||
assert(burstLength <= memSpec->maxBurstLength);
|
||||
|
||||
lastCommandStart = lastScheduledByCommandAndBank[Command::ACT][bank.ID()];
|
||||
if (lastCommandStart != sc_max_time())
|
||||
@@ -316,7 +318,9 @@ sc_time CheckerDDR5::timeToSatisfyConstraints(Command command, tlm_generic_paylo
|
||||
else if (command == Command::WR || command == Command::WRA)
|
||||
{
|
||||
unsigned burstLength = DramExtension::getBurstLength(payload);
|
||||
assert((burstLength == 16) || (burstLength == 32));
|
||||
assert(!(burstLength == 32) || (memSpec->bitWidth == 4));
|
||||
assert(burstLength <= memSpec->maxBurstLength);
|
||||
|
||||
lastCommandStart = lastScheduledByCommandAndBank[Command::ACT][bank.ID()];
|
||||
if (lastCommandStart != sc_max_time())
|
||||
|
||||
@@ -59,7 +59,7 @@ CheckerGDDR5::CheckerGDDR5()
|
||||
|
||||
bankwiseRefreshCounter = std::vector<unsigned>(memSpec->numberOfRanks);
|
||||
|
||||
tBURST = memSpec->burstLength / memSpec->dataRate * memSpec->tCK;
|
||||
tBURST = memSpec->defaultBurstLength / memSpec->dataRate * memSpec->tCK;
|
||||
tRDSRE = memSpec->tCL + memSpec->tWCK2CKPIN + memSpec->tWCK2CK + memSpec->tWCK2DQO + tBURST;
|
||||
tWRSRE = memSpec->tWL + memSpec->tWCK2CKPIN + memSpec->tWCK2CK + memSpec->tWCK2DQI + tBURST;
|
||||
tRDWR_R = memSpec->tCL + tBURST + memSpec->tRTRS - memSpec->tWL;
|
||||
@@ -80,6 +80,8 @@ sc_time CheckerGDDR5::timeToSatisfyConstraints(Command command, tlm_generic_payl
|
||||
|
||||
if (command == Command::RD || command == Command::RDA)
|
||||
{
|
||||
assert(DramExtension::getBurstLength(payload) == 8);
|
||||
|
||||
lastCommandStart = lastScheduledByCommandAndBank[Command::ACT][bank.ID()];
|
||||
if (lastCommandStart != sc_max_time())
|
||||
earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRCDRD);
|
||||
@@ -149,6 +151,8 @@ sc_time CheckerGDDR5::timeToSatisfyConstraints(Command command, tlm_generic_payl
|
||||
}
|
||||
else if (command == Command::WR || command == Command::WRA)
|
||||
{
|
||||
assert(DramExtension::getBurstLength(payload) == 8);
|
||||
|
||||
lastCommandStart = lastScheduledByCommandAndBank[Command::ACT][bank.ID()];
|
||||
if (lastCommandStart != sc_max_time())
|
||||
earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRCDWR);
|
||||
|
||||
@@ -59,7 +59,7 @@ CheckerGDDR5X::CheckerGDDR5X()
|
||||
|
||||
bankwiseRefreshCounter = std::vector<unsigned>(memSpec->numberOfRanks);
|
||||
|
||||
tBURST = memSpec->burstLength / memSpec->dataRate * memSpec->tCK;
|
||||
tBURST = memSpec->defaultBurstLength / memSpec->dataRate * memSpec->tCK;
|
||||
tRDSRE = memSpec->tRL + memSpec->tWCK2CKPIN + memSpec->tWCK2CK + memSpec->tWCK2DQO + tBURST;
|
||||
tWRSRE = memSpec->tWL + memSpec->tWCK2CKPIN + memSpec->tWCK2CK + memSpec->tWCK2DQI + tBURST;
|
||||
tRDWR_R = memSpec->tRL + tBURST + memSpec->tRTRS - memSpec->tWL;
|
||||
@@ -80,6 +80,10 @@ sc_time CheckerGDDR5X::timeToSatisfyConstraints(Command command, tlm_generic_pay
|
||||
|
||||
if (command == Command::RD || command == Command::RDA)
|
||||
{
|
||||
unsigned burstLength = DramExtension::getBurstLength(payload);
|
||||
assert(!(memSpec->dataRate == 4) || (burstLength == 8)); // DDR mode (QDR wrt CK)
|
||||
assert(!(memSpec->dataRate == 8) || (burstLength == 16)); // QDR mode (ODR wrt CK)
|
||||
|
||||
lastCommandStart = lastScheduledByCommandAndBank[Command::ACT][bank.ID()];
|
||||
if (lastCommandStart != sc_max_time())
|
||||
earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRCDRD);
|
||||
@@ -149,6 +153,10 @@ sc_time CheckerGDDR5X::timeToSatisfyConstraints(Command command, tlm_generic_pay
|
||||
}
|
||||
else if (command == Command::WR || command == Command::WRA)
|
||||
{
|
||||
unsigned burstLength = DramExtension::getBurstLength(payload);
|
||||
assert(!(memSpec->dataRate == 4) || (burstLength == 8)); // DDR mode (QDR wrt CK)
|
||||
assert(!(memSpec->dataRate == 8) || (burstLength == 16)); // QDR mode (ODR wrt CK)
|
||||
|
||||
lastCommandStart = lastScheduledByCommandAndBank[Command::ACT][bank.ID()];
|
||||
if (lastCommandStart != sc_max_time())
|
||||
earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRCDWR);
|
||||
|
||||
@@ -58,7 +58,7 @@ CheckerGDDR6::CheckerGDDR6()
|
||||
|
||||
bankwiseRefreshCounter = std::vector<unsigned>(memSpec->numberOfRanks);
|
||||
|
||||
tBURST = memSpec->burstLength / memSpec->dataRate * memSpec->tCK;
|
||||
tBURST = memSpec->defaultBurstLength / memSpec->dataRate * memSpec->tCK;
|
||||
tRDSRE = memSpec->tRL + memSpec->tWCK2CKPIN + memSpec->tWCK2CK + memSpec->tWCK2DQO + tBURST;
|
||||
tWRSRE = memSpec->tWL + memSpec->tWCK2CKPIN + memSpec->tWCK2CK + memSpec->tWCK2DQI + tBURST;
|
||||
tRDWR_R = memSpec->tRL + tBURST + memSpec->tRTRS - memSpec->tWL;
|
||||
@@ -79,6 +79,8 @@ sc_time CheckerGDDR6::timeToSatisfyConstraints(Command command, tlm_generic_payl
|
||||
|
||||
if (command == Command::RD || command == Command::RDA)
|
||||
{
|
||||
assert(DramExtension::getBurstLength(payload) == 16);
|
||||
|
||||
lastCommandStart = lastScheduledByCommandAndBank[Command::ACT][bank.ID()];
|
||||
if (lastCommandStart != sc_max_time())
|
||||
earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRCDRD);
|
||||
@@ -148,6 +150,8 @@ sc_time CheckerGDDR6::timeToSatisfyConstraints(Command command, tlm_generic_payl
|
||||
}
|
||||
else if (command == Command::WR || command == Command::WRA)
|
||||
{
|
||||
assert(DramExtension::getBurstLength(payload) == 16);
|
||||
|
||||
lastCommandStart = lastScheduledByCommandAndBank[Command::ACT][bank.ID()];
|
||||
if (lastCommandStart != sc_max_time())
|
||||
earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRCDWR);
|
||||
|
||||
@@ -59,7 +59,7 @@ CheckerHBM2::CheckerHBM2()
|
||||
|
||||
bankwiseRefreshCounter = std::vector<unsigned>(memSpec->numberOfRanks);
|
||||
|
||||
tBURST = memSpec->burstLength / memSpec->dataRate * memSpec->tCK;
|
||||
tBURST = memSpec->defaultBurstLength / memSpec->dataRate * memSpec->tCK;
|
||||
tRDPDE = memSpec->tRL + memSpec->tPL + tBURST + memSpec->tCK;
|
||||
tRDSRE = tRDPDE;
|
||||
tWRPRE = memSpec->tWL + tBURST + memSpec->tWR;
|
||||
@@ -80,6 +80,10 @@ sc_time CheckerHBM2::timeToSatisfyConstraints(Command command, tlm_generic_paylo
|
||||
|
||||
if (command == Command::RD || command == Command::RDA)
|
||||
{
|
||||
unsigned burstLength = DramExtension::getBurstLength(payload);
|
||||
assert(!(memSpec->numberOfRanks == 1) || (burstLength == 2)); // Legacy mode
|
||||
assert(!(memSpec->numberOfRanks == 2) || (burstLength == 4)); // Pseudo-channel mode
|
||||
|
||||
lastCommandStart = lastScheduledByCommandAndBank[Command::ACT][bank.ID()];
|
||||
if (lastCommandStart != sc_max_time())
|
||||
earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRCDRD + memSpec->tCK);
|
||||
@@ -131,6 +135,10 @@ sc_time CheckerHBM2::timeToSatisfyConstraints(Command command, tlm_generic_paylo
|
||||
}
|
||||
else if (command == Command::WR || command == Command::WRA)
|
||||
{
|
||||
unsigned burstLength = DramExtension::getBurstLength(payload);
|
||||
assert(!(memSpec->numberOfRanks == 1) || (burstLength == 2)); // Legacy mode
|
||||
assert(!(memSpec->numberOfRanks == 2) || (burstLength == 4)); // Pseudo-channel mode
|
||||
|
||||
lastCommandStart = lastScheduledByCommandAndBank[Command::ACT][bank.ID()];
|
||||
if (lastCommandStart != sc_max_time())
|
||||
earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRCDWR + memSpec->tCK);
|
||||
|
||||
@@ -54,7 +54,7 @@ CheckerLPDDR4::CheckerLPDDR4()
|
||||
lastCommandOnBus = sc_max_time();
|
||||
last4Activates = std::vector<std::queue<sc_time>>(memSpec->numberOfRanks);
|
||||
|
||||
tBURST = memSpec->burstLength / memSpec->dataRate * memSpec->tCK;
|
||||
tBURST = memSpec->defaultBurstLength / memSpec->dataRate * memSpec->tCK;
|
||||
tRDWR = memSpec->tRL + memSpec->tDQSCK + tBURST - memSpec->tWL + memSpec->tWPRE + memSpec->tRPST;
|
||||
tRDWR_R = memSpec->tRL + tBURST + memSpec->tRTRS - memSpec->tWL;
|
||||
tWRRD = memSpec->tWL + memSpec->tCK + tBURST + memSpec->tWTR;
|
||||
@@ -81,6 +81,10 @@ sc_time CheckerLPDDR4::timeToSatisfyConstraints(Command command, tlm_generic_pay
|
||||
|
||||
if (command == Command::RD || command == Command::RDA)
|
||||
{
|
||||
unsigned burstLength = DramExtension::getBurstLength(payload);
|
||||
assert((burstLength == 16) || (burstLength == 32)); // TODO: BL16/32 OTF
|
||||
assert(burstLength <= memSpec->maxBurstLength);
|
||||
|
||||
lastCommandStart = lastScheduledByCommandAndBank[Command::ACT][bank.ID()];
|
||||
if (lastCommandStart != sc_max_time())
|
||||
earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRCD);
|
||||
@@ -130,6 +134,10 @@ sc_time CheckerLPDDR4::timeToSatisfyConstraints(Command command, tlm_generic_pay
|
||||
}
|
||||
else if (command == Command::WR || command == Command::WRA)
|
||||
{
|
||||
unsigned burstLength = DramExtension::getBurstLength(payload);
|
||||
assert((burstLength == 16) || (burstLength == 32));
|
||||
assert(burstLength <= memSpec->maxBurstLength);
|
||||
|
||||
lastCommandStart = lastScheduledByCommandAndBank[Command::ACT][bank.ID()];
|
||||
if (lastCommandStart != sc_max_time())
|
||||
earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRCD);
|
||||
|
||||
@@ -84,7 +84,8 @@ sc_time CheckerLPDDR5::timeToSatisfyConstraints(Command command, tlm_generic_pay
|
||||
{
|
||||
unsigned burstLength = DramExtension::getBurstLength(payload);
|
||||
assert(!(memSpec->bitWidth == 8) || (burstLength == 32)); // x8 device -> BL32
|
||||
assert(!(memSpec->groupsPerRank > 1) || (burstLength == 16)); // BG mode -> BL16
|
||||
assert(!(memSpec->groupsPerRank > 1) || (burstLength == 16)); // BG mode -> BL16 (TODO: BL32)
|
||||
assert(burstLength <= memSpec->maxBurstLength);
|
||||
|
||||
lastCommandStart = lastScheduledByCommandAndBank[Command::ACT][bank.ID()];
|
||||
if (lastCommandStart != sc_max_time())
|
||||
@@ -195,7 +196,8 @@ sc_time CheckerLPDDR5::timeToSatisfyConstraints(Command command, tlm_generic_pay
|
||||
{
|
||||
unsigned burstLength = DramExtension::getBurstLength(payload);
|
||||
assert(!(memSpec->bitWidth == 8) || (burstLength == 32)); // x8 device -> BL32
|
||||
assert(!(memSpec->groupsPerRank > 1) || (burstLength == 16)); // BG mode -> BL16
|
||||
assert(!(memSpec->groupsPerRank > 1) || (burstLength == 16)); // BG mode -> BL16 (TODO: BL32)
|
||||
assert(burstLength <= memSpec->maxBurstLength);
|
||||
|
||||
lastCommandStart = lastScheduledByCommandAndBank[Command::ACT][bank.ID()];
|
||||
if (lastCommandStart != sc_max_time())
|
||||
|
||||
@@ -54,7 +54,7 @@ CheckerSTTMRAM::CheckerSTTMRAM()
|
||||
lastCommandOnBus = sc_max_time();
|
||||
last4Activates = std::vector<std::queue<sc_time>>(memSpec->numberOfRanks);
|
||||
|
||||
tBURST = memSpec->burstLength / memSpec->dataRate * memSpec->tCK;
|
||||
tBURST = memSpec->defaultBurstLength / memSpec->dataRate * memSpec->tCK;
|
||||
tRDWR = memSpec->tRL + tBURST + 2 * memSpec->tCK - memSpec->tWL;
|
||||
tRDWR_R = memSpec->tRL + tBURST + memSpec->tRTRS - memSpec->tWL;
|
||||
tWRRD = memSpec->tWL + tBURST + memSpec->tWTR - memSpec->tAL;
|
||||
@@ -75,6 +75,8 @@ sc_time CheckerSTTMRAM::timeToSatisfyConstraints(Command command, tlm_generic_pa
|
||||
|
||||
if (command == Command::RD || command == Command::RDA)
|
||||
{
|
||||
assert(DramExtension::getBurstLength(payload) == 8);
|
||||
|
||||
lastCommandStart = lastScheduledByCommandAndBank[Command::ACT][bank.ID()];
|
||||
if (lastCommandStart != sc_max_time())
|
||||
earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRCD - memSpec->tAL);
|
||||
@@ -130,6 +132,8 @@ sc_time CheckerSTTMRAM::timeToSatisfyConstraints(Command command, tlm_generic_pa
|
||||
}
|
||||
else if (command == Command::WR || command == Command::WRA)
|
||||
{
|
||||
assert(DramExtension::getBurstLength(payload) == 8);
|
||||
|
||||
lastCommandStart = lastScheduledByCommandAndBank[Command::ACT][bank.ID()];
|
||||
if (lastCommandStart != sc_max_time())
|
||||
earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRCD - memSpec->tAL);
|
||||
|
||||
@@ -54,7 +54,7 @@ CheckerWideIO::CheckerWideIO()
|
||||
lastCommandOnBus = sc_max_time();
|
||||
last2Activates = std::vector<std::queue<sc_time>>(memSpec->numberOfRanks);
|
||||
|
||||
tBURST = memSpec->burstLength * memSpec->tCK;
|
||||
tBURST = memSpec->defaultBurstLength * memSpec->tCK;
|
||||
tRDWR = memSpec->tRL + tBURST + memSpec->tCK;
|
||||
tRDWR_R = memSpec->tRL + tBURST + memSpec->tRTRS - memSpec->tWL;
|
||||
tWRPRE = memSpec->tWL + tBURST - memSpec->tCK + memSpec->tWR;
|
||||
@@ -75,6 +75,10 @@ sc_time CheckerWideIO::timeToSatisfyConstraints(Command command, tlm_generic_pay
|
||||
|
||||
if (command == Command::RD || command == Command::RDA)
|
||||
{
|
||||
unsigned burstLength = DramExtension::getBurstLength(payload);
|
||||
assert((burstLength == 2) || (burstLength == 4));
|
||||
assert(burstLength <= memSpec->maxBurstLength);
|
||||
|
||||
lastCommandStart = lastScheduledByCommandAndBank[Command::ACT][bank.ID()];
|
||||
if (lastCommandStart != sc_max_time())
|
||||
earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRCD);
|
||||
@@ -124,6 +128,10 @@ sc_time CheckerWideIO::timeToSatisfyConstraints(Command command, tlm_generic_pay
|
||||
}
|
||||
else if (command == Command::WR || command == Command::WRA)
|
||||
{
|
||||
unsigned burstLength = DramExtension::getBurstLength(payload);
|
||||
assert((burstLength == 2) || (burstLength == 4));
|
||||
assert(burstLength <= memSpec->maxBurstLength);
|
||||
|
||||
lastCommandStart = lastScheduledByCommandAndBank[Command::ACT][bank.ID()];
|
||||
if (lastCommandStart != sc_max_time())
|
||||
earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRCD);
|
||||
|
||||
@@ -54,7 +54,7 @@ CheckerWideIO2::CheckerWideIO2()
|
||||
lastCommandOnBus = sc_max_time();
|
||||
last4Activates = std::vector<std::queue<sc_time>>(memSpec->numberOfRanks);
|
||||
|
||||
tBURST = memSpec->burstLength / memSpec->dataRate * memSpec->tCK;
|
||||
tBURST = memSpec->defaultBurstLength / memSpec->dataRate * memSpec->tCK;
|
||||
tRDPRE = tBURST + std::max(2 * memSpec->tCK, memSpec->tRTP) - 2 * memSpec->tCK;
|
||||
tRDPDEN = memSpec->tRL + memSpec->tDQSCK + tBURST + memSpec->tCK;
|
||||
tRDWR = memSpec->tRL + memSpec->tDQSCK + tBURST + memSpec->tCK - memSpec->tWL;
|
||||
@@ -76,6 +76,10 @@ sc_time CheckerWideIO2::timeToSatisfyConstraints(Command command, tlm_generic_pa
|
||||
|
||||
if (command == Command::RD || command == Command::RDA)
|
||||
{
|
||||
unsigned burstLength = DramExtension::getBurstLength(payload);
|
||||
assert((burstLength == 4) || (burstLength == 8)); // TODO: BL4/8 OTF
|
||||
assert(burstLength <= memSpec->maxBurstLength);
|
||||
|
||||
lastCommandStart = lastScheduledByCommandAndBank[Command::ACT][bank.ID()];
|
||||
if (lastCommandStart != sc_max_time())
|
||||
earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRCD);
|
||||
@@ -125,6 +129,10 @@ sc_time CheckerWideIO2::timeToSatisfyConstraints(Command command, tlm_generic_pa
|
||||
}
|
||||
else if (command == Command::WR || command == Command::WRA)
|
||||
{
|
||||
unsigned burstLength = DramExtension::getBurstLength(payload);
|
||||
assert((burstLength == 4) || (burstLength == 8));
|
||||
assert(burstLength <= memSpec->maxBurstLength);
|
||||
|
||||
lastCommandStart = lastScheduledByCommandAndBank[Command::ACT][bank.ID()];
|
||||
if (lastCommandStart != sc_max_time())
|
||||
earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRCD);
|
||||
|
||||
@@ -53,13 +53,12 @@ void errorModel::init()
|
||||
powerAnalysis = Configuration::getInstance().powerAnalysis;
|
||||
thermalSim = Configuration::getInstance().thermalSimulation;
|
||||
// Get Configuration parameters:
|
||||
burstLenght = Configuration::getInstance().memSpec->burstLength;
|
||||
burstLenght = Configuration::getInstance().memSpec->defaultBurstLength;
|
||||
numberOfColumns = Configuration::getInstance().memSpec->numberOfColumns;
|
||||
bytesPerColumn = std::log2(Configuration::getInstance().memSpec->dataBusWidth);
|
||||
|
||||
// Adjust number of bytes per column dynamically to the selected ecc controller
|
||||
bytesPerColumn = Configuration::getInstance().adjustNumBytesAfterECC(
|
||||
bytesPerColumn);
|
||||
//TODO: bytesPerColumn = Configuration::getInstance().adjustNumBytesAfterECC(bytesPerColumn);
|
||||
|
||||
numberOfRows = Configuration::getInstance().memSpec->numberOfRows;
|
||||
numberOfBitErrorEvents = 0;
|
||||
|
||||
@@ -74,9 +74,6 @@ DRAMSys::DRAMSys(const sc_core::sc_module_name &name,
|
||||
bool initAndBind)
|
||||
: sc_module(name), tSocket("DRAMSys_tSocket")
|
||||
{
|
||||
// Initialize ecc pointer
|
||||
ecc = nullptr;
|
||||
|
||||
logo();
|
||||
|
||||
// Read Configuration Setup:
|
||||
@@ -119,25 +116,6 @@ DRAMSys::DRAMSys(const sc_core::sc_module_name &name,
|
||||
}
|
||||
}
|
||||
|
||||
DRAMSys::~DRAMSys()
|
||||
{
|
||||
delete ecc;
|
||||
|
||||
delete arbiter;
|
||||
|
||||
for (auto dram : drams)
|
||||
delete dram;
|
||||
|
||||
for (auto controller : controllers)
|
||||
delete controller;
|
||||
|
||||
for (auto tlmChecker : playersTlmCheckers)
|
||||
delete tlmChecker;
|
||||
|
||||
for (auto tlmChecker : controllersTlmCheckers)
|
||||
delete tlmChecker;
|
||||
}
|
||||
|
||||
void DRAMSys::logo()
|
||||
{
|
||||
#define GREENTXT(s) std::string(("\u001b[38;5;28m"+std::string((s))+"\033[0m"))
|
||||
@@ -182,69 +160,47 @@ void DRAMSys::instantiateModules(const std::string &pathToResources,
|
||||
TemperatureController::getInstance();
|
||||
Configuration &config = Configuration::getInstance();
|
||||
|
||||
// Create new ECC Controller
|
||||
if (config.eccMode == Configuration::ECCMode::Hamming)
|
||||
ecc = new ECCHamming("ECCHamming");
|
||||
else if (config.eccMode == Configuration::ECCMode::Disabled)
|
||||
ecc = nullptr;
|
||||
|
||||
// Save ECC Controller into the configuration struct to adjust it dynamically
|
||||
config.pECC = ecc;
|
||||
|
||||
// Create arbiter
|
||||
if (config.arbiter == Configuration::Arbiter::Simple)
|
||||
arbiter = new ArbiterSimple("arbiter", pathToResources + "configs/amconfigs/" + amconfig);
|
||||
arbiter = std::unique_ptr<Arbiter>(new ArbiterSimple("arbiter", pathToResources + "configs/amconfigs/" + amconfig));
|
||||
else if (config.arbiter == Configuration::Arbiter::Fifo)
|
||||
arbiter = new ArbiterFifo("arbiter", pathToResources + "configs/amconfigs/" + amconfig);
|
||||
arbiter = std::unique_ptr<Arbiter>(new ArbiterFifo("arbiter", pathToResources + "configs/amconfigs/" + amconfig));
|
||||
else if (config.arbiter == Configuration::Arbiter::Reorder)
|
||||
arbiter = new ArbiterReorder("arbiter", pathToResources + "configs/amconfigs/" + amconfig);
|
||||
arbiter = std::unique_ptr<Arbiter>(new ArbiterReorder("arbiter", pathToResources + "configs/amconfigs/" + amconfig));
|
||||
|
||||
// Create controllers and DRAMs
|
||||
MemSpec::MemoryType memoryType = config.memSpec->memoryType;
|
||||
for (std::size_t i = 0; i < config.memSpec->numberOfChannels; i++)
|
||||
{
|
||||
std::string str = "controller" + std::to_string(i);
|
||||
|
||||
ControllerIF *controller = new Controller(str.c_str());
|
||||
controllers.push_back(controller);
|
||||
|
||||
str = "dram" + std::to_string(i);
|
||||
Dram *dram;
|
||||
controllers.emplace_back(new Controller(("controller" + std::to_string(i)).c_str()));
|
||||
|
||||
if (memoryType == MemSpec::MemoryType::DDR3)
|
||||
dram = new DramDDR3(str.c_str());
|
||||
drams.emplace_back(new DramDDR3(("dram" + std::to_string(i)).c_str()));
|
||||
else if (memoryType == MemSpec::MemoryType::DDR4)
|
||||
dram = new DramDDR4(str.c_str());
|
||||
drams.emplace_back(new DramDDR4(("dram" + std::to_string(i)).c_str()));
|
||||
else if (memoryType == MemSpec::MemoryType::DDR5)
|
||||
dram = new DramDDR5(str.c_str());
|
||||
drams.emplace_back(new DramDDR5(("dram" + std::to_string(i)).c_str()));
|
||||
else if (memoryType == MemSpec::MemoryType::WideIO)
|
||||
dram = new DramWideIO(str.c_str());
|
||||
drams.emplace_back(new DramWideIO(("dram" + std::to_string(i)).c_str()));
|
||||
else if (memoryType == MemSpec::MemoryType::LPDDR4)
|
||||
dram = new DramLPDDR4(str.c_str());
|
||||
drams.emplace_back(new DramLPDDR4(("dram" + std::to_string(i)).c_str()));
|
||||
else if (memoryType == MemSpec::MemoryType::LPDDR5)
|
||||
dram = new DramLPDDR5(str.c_str());
|
||||
drams.emplace_back(new DramLPDDR5(("dram" + std::to_string(i)).c_str()));
|
||||
else if (memoryType == MemSpec::MemoryType::WideIO2)
|
||||
dram = new DramWideIO2(str.c_str());
|
||||
drams.emplace_back(new DramWideIO2(("dram" + std::to_string(i)).c_str()));
|
||||
else if (memoryType == MemSpec::MemoryType::HBM2)
|
||||
dram = new DramHBM2(str.c_str());
|
||||
drams.emplace_back(new DramHBM2(("dram" + std::to_string(i)).c_str()));
|
||||
else if (memoryType == MemSpec::MemoryType::GDDR5)
|
||||
dram = new DramGDDR5(str.c_str());
|
||||
drams.emplace_back(new DramGDDR5(("dram" + std::to_string(i)).c_str()));
|
||||
else if (memoryType == MemSpec::MemoryType::GDDR5X)
|
||||
dram = new DramGDDR5X(str.c_str());
|
||||
drams.emplace_back(new DramGDDR5X(("dram" + std::to_string(i)).c_str()));
|
||||
else if (memoryType == MemSpec::MemoryType::GDDR6)
|
||||
dram = new DramGDDR6(str.c_str());
|
||||
drams.emplace_back(new DramGDDR6(("dram" + std::to_string(i)).c_str()));
|
||||
else if (memoryType == MemSpec::MemoryType::STTMRAM)
|
||||
dram = new DramSTTMRAM(str.c_str());
|
||||
drams.emplace_back(new DramSTTMRAM(("dram" + std::to_string(i)).c_str()));
|
||||
|
||||
drams.push_back(dram);
|
||||
|
||||
if (Configuration::getInstance().checkTLM2Protocol)
|
||||
{
|
||||
str = "TLMCheckerController" + std::to_string(i);
|
||||
tlm_utils::tlm2_base_protocol_checker<> *controllerTlmChecker =
|
||||
new tlm_utils::tlm2_base_protocol_checker<>(str.c_str());
|
||||
controllersTlmCheckers.push_back(controllerTlmChecker);
|
||||
}
|
||||
if (config.checkTLM2Protocol)
|
||||
controllersTlmCheckers.push_back(new tlm_utils::tlm2_base_protocol_checker<>(("TlmCheckerController" + std::to_string(i)).c_str()));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -252,32 +208,20 @@ void DRAMSys::bindSockets()
|
||||
{
|
||||
Configuration &config = Configuration::getInstance();
|
||||
|
||||
// If ECC Controller enabled, put it between Trace and arbiter
|
||||
if (config.eccMode == Configuration::ECCMode::Hamming)
|
||||
{
|
||||
assert(ecc != nullptr);
|
||||
tSocket.bind(ecc->t_socket);
|
||||
ecc->i_socket.bind(arbiter->tSocket);
|
||||
}
|
||||
else if (config.eccMode == Configuration::ECCMode::Disabled)
|
||||
tSocket.bind(arbiter->tSocket);
|
||||
tSocket.bind(arbiter->tSocket);
|
||||
|
||||
if (config.checkTLM2Protocol)
|
||||
for (unsigned i = 0; i < config.memSpec->numberOfChannels; i++)
|
||||
{
|
||||
for (std::size_t i = 0; i < config.memSpec->numberOfChannels; i++)
|
||||
if (config.checkTLM2Protocol)
|
||||
{
|
||||
arbiter->iSocket.bind(controllersTlmCheckers[i]->target_socket);
|
||||
controllersTlmCheckers[i]->initiator_socket.bind(controllers[i]->tSocket);
|
||||
controllers[i]->iSocket.bind(drams[i]->tSocket);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (std::size_t i = 0; i < config.memSpec->numberOfChannels; i++)
|
||||
else
|
||||
{
|
||||
arbiter->iSocket.bind(controllers[i]->tSocket);
|
||||
controllers[i]->iSocket.bind(drams[i]->tSocket);
|
||||
}
|
||||
controllers[i]->iSocket.bind(drams[i]->tSocket);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -41,6 +41,8 @@
|
||||
#define DRAMSYS_H
|
||||
|
||||
#include <string>
|
||||
#include <list>
|
||||
#include <memory>
|
||||
|
||||
#include <systemc>
|
||||
#include "dram/Dram.h"
|
||||
@@ -57,16 +59,11 @@ class DRAMSys : public sc_core::sc_module
|
||||
public:
|
||||
tlm_utils::multi_passthrough_target_socket<DRAMSys> tSocket;
|
||||
|
||||
std::vector<tlm_utils::tlm2_base_protocol_checker<>*>
|
||||
playersTlmCheckers;
|
||||
|
||||
SC_HAS_PROCESS(DRAMSys);
|
||||
DRAMSys(const sc_core::sc_module_name &name,
|
||||
const std::string &simulationToRun,
|
||||
const std::string &pathToResources);
|
||||
|
||||
~DRAMSys() override;
|
||||
|
||||
protected:
|
||||
DRAMSys(const sc_core::sc_module_name &name,
|
||||
const std::string &simulationToRun,
|
||||
@@ -74,32 +71,28 @@ protected:
|
||||
bool initAndBind);
|
||||
|
||||
//TLM 2.0 Protocol Checkers
|
||||
std::vector<tlm_utils::tlm2_base_protocol_checker<>*>
|
||||
controllersTlmCheckers;
|
||||
|
||||
// All transactions pass first through the ECC Controller
|
||||
ECCBaseClass *ecc;
|
||||
std::vector<tlm_utils::tlm2_base_protocol_checker<>*> controllersTlmCheckers;
|
||||
|
||||
// TODO: Each DRAM has a reorder buffer (check this!)
|
||||
ReorderBuffer *reorder;
|
||||
std::unique_ptr<ReorderBuffer> reorder;
|
||||
|
||||
// All transactions pass through the same arbiter
|
||||
Arbiter *arbiter;
|
||||
std::unique_ptr<Arbiter> arbiter;
|
||||
|
||||
// Each DRAM unit has a controller
|
||||
std::vector<ControllerIF *> controllers;
|
||||
std::vector<std::unique_ptr<ControllerIF>> controllers;
|
||||
|
||||
// DRAM units
|
||||
std::vector<Dram *> drams;
|
||||
std::vector<std::unique_ptr<Dram>> drams;
|
||||
|
||||
void report(const std::string &message);
|
||||
void bindSockets();
|
||||
|
||||
private:
|
||||
static void logo();
|
||||
|
||||
void instantiateModules(const std::string &pathToResources,
|
||||
const std::string &amconfig);
|
||||
void bindSockets();
|
||||
|
||||
static void setupDebugManager(const std::string &traceName);
|
||||
};
|
||||
|
||||
@@ -80,17 +80,17 @@ DRAMSysRecordable::DRAMSysRecordable(const sc_module_name &name,
|
||||
report(headline);
|
||||
}
|
||||
|
||||
DRAMSysRecordable::~DRAMSysRecordable()
|
||||
void DRAMSysRecordable::end_of_simulation()
|
||||
{
|
||||
// Report power before TLM recorders are deleted
|
||||
if (Configuration::getInstance().powerAnalysis)
|
||||
{
|
||||
for (auto dram : drams)
|
||||
for (auto& dram : drams)
|
||||
dram->reportPower();
|
||||
}
|
||||
|
||||
for (auto rec : tlmRecorders)
|
||||
delete rec;
|
||||
for (auto& tlmRecorder : tlmRecorders)
|
||||
tlmRecorder.finalize();
|
||||
}
|
||||
|
||||
void DRAMSysRecordable::setupTlmRecorders(const std::string &traceName)
|
||||
@@ -99,18 +99,12 @@ void DRAMSysRecordable::setupTlmRecorders(const std::string &traceName)
|
||||
for (std::size_t i = 0; i < Configuration::getInstance().memSpec->numberOfChannels; i++)
|
||||
{
|
||||
std::string dbName = traceName + std::string("_ch") + std::to_string(i) + ".tdb";
|
||||
|
||||
std::string recorderName = "tlmRecorder" + std::to_string(i);
|
||||
|
||||
TlmRecorder *tlmRecorder =
|
||||
new TlmRecorder(recorderName, dbName);
|
||||
tlmRecorder->recordMcConfig(Configuration::mcconfigUri);
|
||||
tlmRecorder->recordMemspec(Configuration::memspecUri);
|
||||
|
||||
std::string traceNames = Configuration::getInstance().simulationName;
|
||||
tlmRecorder->recordTraceNames(traceNames);
|
||||
|
||||
tlmRecorders.push_back(tlmRecorder);
|
||||
tlmRecorders.emplace_back(recorderName, dbName);
|
||||
tlmRecorders.back().recordMcConfig(Configuration::mcconfigUri);
|
||||
tlmRecorders.back().recordMemspec(Configuration::memspecUri);
|
||||
tlmRecorders.back().recordTraceNames(Configuration::getInstance().simulationName);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -128,101 +122,47 @@ void DRAMSysRecordable::instantiateModules(const std::string &traceName,
|
||||
// They need to be ready before creating some modules.
|
||||
setupTlmRecorders(traceName);
|
||||
|
||||
// Create new ECC Controller
|
||||
if (config.eccMode == Configuration::ECCMode::Hamming)
|
||||
ecc = new ECCHamming("ECCHamming");
|
||||
else if (config.eccMode == Configuration::ECCMode::Disabled)
|
||||
ecc = nullptr;
|
||||
|
||||
// Save ECC Controller into the configuration struct to adjust it dynamically
|
||||
config.pECC = ecc;
|
||||
|
||||
// Create arbiter
|
||||
if (config.arbiter == Configuration::Arbiter::Simple)
|
||||
arbiter = new ArbiterSimple("arbiter", pathToResources + "configs/amconfigs/" + amconfig);
|
||||
arbiter = std::unique_ptr<Arbiter>(new ArbiterSimple("arbiter", pathToResources + "configs/amconfigs/" + amconfig));
|
||||
else if (config.arbiter == Configuration::Arbiter::Fifo)
|
||||
arbiter = new ArbiterFifo("arbiter", pathToResources + "configs/amconfigs/" + amconfig);
|
||||
arbiter = std::unique_ptr<Arbiter>(new ArbiterFifo("arbiter", pathToResources + "configs/amconfigs/" + amconfig));
|
||||
else if (config.arbiter == Configuration::Arbiter::Reorder)
|
||||
arbiter = new ArbiterReorder("arbiter", pathToResources + "configs/amconfigs/" + amconfig);
|
||||
arbiter = std::unique_ptr<Arbiter>(new ArbiterReorder("arbiter", pathToResources + "configs/amconfigs/" + amconfig));
|
||||
|
||||
// Create controllers and DRAMs
|
||||
MemSpec::MemoryType memoryType = config.memSpec->memoryType;
|
||||
for (std::size_t i = 0; i < config.memSpec->numberOfChannels; i++)
|
||||
{
|
||||
std::string str = "controller" + std::to_string(i);
|
||||
|
||||
ControllerIF *controller = new ControllerRecordable(str.c_str(), tlmRecorders[i]);
|
||||
controllers.push_back(controller);
|
||||
|
||||
str = "dram" + std::to_string(i);
|
||||
Dram *dram;
|
||||
controllers.emplace_back(new ControllerRecordable(("controller" + std::to_string(i)).c_str(), tlmRecorders[i]));
|
||||
|
||||
if (memoryType == MemSpec::MemoryType::DDR3)
|
||||
dram = new DramRecordable<DramDDR3>(str.c_str(), tlmRecorders[i]);
|
||||
drams.emplace_back(new DramRecordable<DramDDR3>(("dram" + std::to_string(i)).c_str(), tlmRecorders[i]));
|
||||
else if (memoryType == MemSpec::MemoryType::DDR4)
|
||||
dram = new DramRecordable<DramDDR4>(str.c_str(), tlmRecorders[i]);
|
||||
drams.emplace_back(new DramRecordable<DramDDR4>(("dram" + std::to_string(i)).c_str(), tlmRecorders[i]));
|
||||
else if (memoryType == MemSpec::MemoryType::DDR5)
|
||||
dram = new DramRecordable<DramDDR5>(str.c_str(), tlmRecorders[i]);
|
||||
drams.emplace_back(new DramRecordable<DramDDR5>(("dram" + std::to_string(i)).c_str(), tlmRecorders[i]));
|
||||
else if (memoryType == MemSpec::MemoryType::WideIO)
|
||||
dram = new DramRecordable<DramWideIO>(str.c_str(), tlmRecorders[i]);
|
||||
drams.emplace_back(new DramRecordable<DramWideIO>(("dram" + std::to_string(i)).c_str(), tlmRecorders[i]));
|
||||
else if (memoryType == MemSpec::MemoryType::LPDDR4)
|
||||
dram = new DramRecordable<DramLPDDR4>(str.c_str(), tlmRecorders[i]);
|
||||
drams.emplace_back(new DramRecordable<DramLPDDR4>(("dram" + std::to_string(i)).c_str(), tlmRecorders[i]));
|
||||
else if (memoryType == MemSpec::MemoryType::LPDDR5)
|
||||
dram = new DramRecordable<DramLPDDR5>(str.c_str(), tlmRecorders[i]);
|
||||
drams.emplace_back(new DramRecordable<DramLPDDR5>(("dram" + std::to_string(i)).c_str(), tlmRecorders[i]));
|
||||
else if (memoryType == MemSpec::MemoryType::WideIO2)
|
||||
dram = new DramRecordable<DramWideIO2>(str.c_str(), tlmRecorders[i]);
|
||||
drams.emplace_back(new DramRecordable<DramWideIO2>(("dram" + std::to_string(i)).c_str(), tlmRecorders[i]));
|
||||
else if (memoryType == MemSpec::MemoryType::HBM2)
|
||||
dram = new DramRecordable<DramHBM2>(str.c_str(), tlmRecorders[i]);
|
||||
drams.emplace_back(new DramRecordable<DramHBM2>(("dram" + std::to_string(i)).c_str(), tlmRecorders[i]));
|
||||
else if (memoryType == MemSpec::MemoryType::GDDR5)
|
||||
dram = new DramRecordable<DramGDDR5>(str.c_str(), tlmRecorders[i]);
|
||||
drams.emplace_back(new DramRecordable<DramGDDR5>(("dram" + std::to_string(i)).c_str(), tlmRecorders[i]));
|
||||
else if (memoryType == MemSpec::MemoryType::GDDR5X)
|
||||
dram = new DramRecordable<DramGDDR5X>(str.c_str(), tlmRecorders[i]);
|
||||
drams.emplace_back(new DramRecordable<DramGDDR5X>(("dram" + std::to_string(i)).c_str(), tlmRecorders[i]));
|
||||
else if (memoryType == MemSpec::MemoryType::GDDR6)
|
||||
dram = new DramRecordable<DramGDDR6>(str.c_str(), tlmRecorders[i]);
|
||||
drams.emplace_back(new DramRecordable<DramGDDR6>(("dram" + std::to_string(i)).c_str(), tlmRecorders[i]));
|
||||
else if (memoryType == MemSpec::MemoryType::STTMRAM)
|
||||
dram = new DramRecordable<DramSTTMRAM>(str.c_str(), tlmRecorders[i]);
|
||||
|
||||
drams.push_back(dram);
|
||||
drams.emplace_back(new DramRecordable<DramSTTMRAM>(("dram" + std::to_string(i)).c_str(), tlmRecorders[i]));
|
||||
|
||||
if (config.checkTLM2Protocol)
|
||||
{
|
||||
str = "TLMCheckerController" + std::to_string(i);
|
||||
tlm_utils::tlm2_base_protocol_checker<> *controllerTlmChecker =
|
||||
new tlm_utils::tlm2_base_protocol_checker<>(str.c_str());
|
||||
controllersTlmCheckers.push_back(controllerTlmChecker);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void DRAMSysRecordable::bindSockets()
|
||||
{
|
||||
Configuration &config = Configuration::getInstance();
|
||||
|
||||
// If ECC Controller enabled, put it between Trace and arbiter
|
||||
if (config.eccMode == Configuration::ECCMode::Hamming)
|
||||
{
|
||||
assert(ecc != nullptr);
|
||||
tSocket.bind(ecc->t_socket);
|
||||
ecc->i_socket.bind(arbiter->tSocket);
|
||||
}
|
||||
else if (config.eccMode == Configuration::ECCMode::Disabled)
|
||||
tSocket.bind(arbiter->tSocket);
|
||||
|
||||
if (config.checkTLM2Protocol)
|
||||
{
|
||||
for (std::size_t i = 0; i < config.memSpec->numberOfChannels; i++)
|
||||
{
|
||||
arbiter->iSocket.bind(controllersTlmCheckers[i]->target_socket);
|
||||
controllersTlmCheckers[i]->initiator_socket.bind(controllers[i]->tSocket);
|
||||
controllers[i]->iSocket.bind(drams[i]->tSocket);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (std::size_t i = 0; i < config.memSpec->numberOfChannels; i++)
|
||||
{
|
||||
arbiter->iSocket.bind(controllers[i]->tSocket);
|
||||
controllers[i]->iSocket.bind(drams[i]->tSocket);
|
||||
}
|
||||
controllersTlmCheckers.emplace_back(new tlm_utils::tlm2_base_protocol_checker<>(("TLMCheckerController"
|
||||
+ std::to_string(i)).c_str()));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -46,20 +46,18 @@ public:
|
||||
const std::string &simulationToRun,
|
||||
const std::string &pathToResources);
|
||||
|
||||
~DRAMSysRecordable() override;
|
||||
|
||||
private:
|
||||
// Transaction Recorders (one per channel).
|
||||
// They generate the output databases.
|
||||
std::vector<TlmRecorder *> tlmRecorders;
|
||||
std::vector<TlmRecorder> tlmRecorders;
|
||||
|
||||
void end_of_simulation() override;
|
||||
|
||||
void setupTlmRecorders(const std::string &traceName);
|
||||
|
||||
void instantiateModules(const std::string &traceName,
|
||||
const std::string &pathToResources,
|
||||
const std::string &amconfig);
|
||||
|
||||
void bindSockets();
|
||||
};
|
||||
|
||||
#endif // DRAMSYSRECORDABLE_H
|
||||
|
||||
@@ -65,8 +65,6 @@ using namespace DRAMPower;
|
||||
Dram::Dram(const sc_module_name &name) : sc_module(name), tSocket("socket")
|
||||
{
|
||||
Configuration &config = Configuration::getInstance();
|
||||
// Adjust number of bytes per burst dynamically to the selected ecc controller
|
||||
bytesPerBurst = config.adjustNumBytesAfterECC(bytesPerBurst);
|
||||
|
||||
storeMode = config.storeMode;
|
||||
|
||||
|
||||
@@ -50,7 +50,6 @@
|
||||
class Dram : public sc_core::sc_module
|
||||
{
|
||||
private:
|
||||
unsigned int bytesPerBurst = Configuration::getInstance().memSpec->bytesPerBurst;
|
||||
bool powerReported = false;
|
||||
|
||||
protected:
|
||||
|
||||
@@ -53,7 +53,7 @@ DramDDR3::DramDDR3(const sc_module_name &name) : Dram(name)
|
||||
SC_REPORT_FATAL("DramDDR3", "Wrong MemSpec chosen");
|
||||
|
||||
MemArchitectureSpec memArchSpec;
|
||||
memArchSpec.burstLength = memSpec->burstLength;
|
||||
memArchSpec.burstLength = memSpec->defaultBurstLength;
|
||||
memArchSpec.dataRate = memSpec->dataRate;
|
||||
memArchSpec.nbrOfRows = memSpec->numberOfRows;
|
||||
memArchSpec.nbrOfBanks = memSpec->numberOfBanks;
|
||||
|
||||
@@ -53,7 +53,7 @@ DramDDR4::DramDDR4(const sc_module_name &name) : Dram(name)
|
||||
SC_REPORT_FATAL("DramDDR4", "Wrong MemSpec chosen");
|
||||
|
||||
MemArchitectureSpec memArchSpec;
|
||||
memArchSpec.burstLength = memSpec->burstLength;
|
||||
memArchSpec.burstLength = memSpec->defaultBurstLength;
|
||||
memArchSpec.dataRate = memSpec->dataRate;
|
||||
memArchSpec.nbrOfRows = memSpec->numberOfRows;
|
||||
memArchSpec.nbrOfBanks = memSpec->numberOfBanks;
|
||||
|
||||
@@ -55,7 +55,7 @@ using namespace sc_core;
|
||||
using namespace tlm;
|
||||
|
||||
template<class BaseDram>
|
||||
DramRecordable<BaseDram>::DramRecordable(const sc_module_name &name, TlmRecorder *tlmRecorder)
|
||||
DramRecordable<BaseDram>::DramRecordable(const sc_module_name &name, TlmRecorder& tlmRecorder)
|
||||
: BaseDram(name), tlmRecorder(tlmRecorder)
|
||||
{
|
||||
// Create a thread that is triggered every $powerWindowSize
|
||||
@@ -68,7 +68,7 @@ template<class BaseDram>
|
||||
void DramRecordable<BaseDram>::reportPower()
|
||||
{
|
||||
BaseDram::reportPower();
|
||||
tlmRecorder->recordPower(sc_time_stamp().to_seconds(),
|
||||
tlmRecorder.recordPower(sc_time_stamp().to_seconds(),
|
||||
this->DRAMPower->getPower().window_average_power
|
||||
* Configuration::getInstance().memSpec->numberOfDevices);
|
||||
}
|
||||
@@ -103,12 +103,12 @@ void DramRecordable<BaseDram>::recordPhase(tlm_generic_payload &trans, const tlm
|
||||
bg) + " bank " + std::to_string(bank) + " row " + std::to_string(row) + " column " +
|
||||
std::to_string(col) + " at " + recTime.to_string());
|
||||
|
||||
tlmRecorder->recordPhase(trans, phase, recTime);
|
||||
tlmRecorder.recordPhase(trans, phase, recTime);
|
||||
|
||||
if (phaseNeedsEnd(phase))
|
||||
{
|
||||
recTime += this->memSpec->getExecutionTime(Command(phase), trans);
|
||||
tlmRecorder->recordPhase(trans, getEndPhase(phase), recTime);
|
||||
tlmRecorder.recordPhase(trans, getEndPhase(phase), recTime);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -134,7 +134,7 @@ void DramRecordable<BaseDram>::powerWindow()
|
||||
assert(!isEqual(this->DRAMPower->getEnergy().window_energy, 0.0));
|
||||
|
||||
// Store the time (in seconds) and the current average power (in mW) into the database
|
||||
tlmRecorder->recordPower(sc_time_stamp().to_seconds(),
|
||||
tlmRecorder.recordPower(sc_time_stamp().to_seconds(),
|
||||
this->DRAMPower->getPower().window_average_power
|
||||
* Configuration::getInstance().memSpec->numberOfDevices);
|
||||
|
||||
|
||||
@@ -46,7 +46,7 @@ template<class BaseDram>
|
||||
class DramRecordable final : public BaseDram
|
||||
{
|
||||
public:
|
||||
DramRecordable(const sc_core::sc_module_name &name, TlmRecorder *);
|
||||
DramRecordable(const sc_core::sc_module_name &name, TlmRecorder& tlmRecorder);
|
||||
SC_HAS_PROCESS(DramRecordable);
|
||||
|
||||
void reportPower() override;
|
||||
@@ -57,7 +57,7 @@ private:
|
||||
|
||||
void recordPhase(tlm::tlm_generic_payload &trans, const tlm::tlm_phase &phase, const sc_core::sc_time &delay);
|
||||
|
||||
TlmRecorder *tlmRecorder;
|
||||
TlmRecorder& tlmRecorder;
|
||||
|
||||
sc_core::sc_time powerWindowSize = Configuration::getInstance().memSpec->tCK *
|
||||
Configuration::getInstance().windowSize;
|
||||
|
||||
@@ -54,7 +54,7 @@ DramWideIO::DramWideIO(const sc_module_name &name) : Dram(name)
|
||||
SC_REPORT_FATAL("DramWideIO", "Wrong MemSpec chosen");
|
||||
|
||||
MemArchitectureSpec memArchSpec;
|
||||
memArchSpec.burstLength = memSpec->burstLength;
|
||||
memArchSpec.burstLength = memSpec->defaultBurstLength;
|
||||
memArchSpec.dataRate = memSpec->dataRate;
|
||||
memArchSpec.nbrOfRows = memSpec->numberOfRows;
|
||||
memArchSpec.nbrOfBanks = memSpec->numberOfBanks;
|
||||
@@ -74,9 +74,9 @@ DramWideIO::DramWideIO(const sc_module_name &name) : Dram(name)
|
||||
//FIXME: memTimingSpec.RRDB_L = memSpec->tRRD / memSpec->tCK;
|
||||
//FIXME: memTimingSpec.RRDB_S = memSpec->tRRD / memSpec->tCK;
|
||||
memTimingSpec.AL = 0;
|
||||
memTimingSpec.CCD = memSpec->burstLength;
|
||||
memTimingSpec.CCD_L = memSpec->burstLength;
|
||||
memTimingSpec.CCD_S = memSpec->burstLength;
|
||||
memTimingSpec.CCD = memSpec->defaultBurstLength;
|
||||
memTimingSpec.CCD_L = memSpec->defaultBurstLength;
|
||||
memTimingSpec.CCD_S = memSpec->defaultBurstLength;
|
||||
memTimingSpec.CKE = memSpec->tCKE / memSpec->tCK;
|
||||
memTimingSpec.CKESR = memSpec->tCKESR / memSpec->tCK;
|
||||
memTimingSpec.clkMhz = memSpec->fCKMHz;
|
||||
@@ -94,7 +94,7 @@ DramWideIO::DramWideIO(const sc_module_name &name) : Dram(name)
|
||||
memTimingSpec.RRD = memSpec->tRRD / memSpec->tCK;
|
||||
memTimingSpec.RRD_L = memSpec->tRRD / memSpec->tCK;
|
||||
memTimingSpec.RRD_S = memSpec->tRRD / memSpec->tCK;
|
||||
memTimingSpec.RTP = memSpec->burstLength;
|
||||
memTimingSpec.RTP = memSpec->defaultBurstLength;
|
||||
memTimingSpec.TAW = memSpec->tTAW / memSpec->tCK;
|
||||
memTimingSpec.WL = memSpec->tWL / memSpec->tCK;
|
||||
memTimingSpec.WR = memSpec->tWR / memSpec->tCK;
|
||||
|
||||
@@ -52,6 +52,7 @@ add_executable(DRAMSys
|
||||
TrafficGenerator.cpp
|
||||
TrafficInitiator.cpp
|
||||
TraceSetup.cpp
|
||||
LengthConverter.cpp
|
||||
)
|
||||
|
||||
if(EXISTS ${CMAKE_CURRENT_LIST_DIR}/../library/src/simulation/DRAMSysRecordable.cpp)
|
||||
|
||||
236
DRAMSys/simulator/LengthConverter.cpp
Normal file
236
DRAMSys/simulator/LengthConverter.cpp
Normal file
@@ -0,0 +1,236 @@
|
||||
/*
|
||||
* Copyright (c) 2022, Technische Universität 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:
|
||||
* Lukas Steiner
|
||||
*/
|
||||
|
||||
#include "LengthConverter.h"
|
||||
|
||||
using namespace sc_core;
|
||||
using namespace tlm;
|
||||
|
||||
// TODO: return status, TLM_INCOMPLETE_RESPONSE, acquire + release
|
||||
|
||||
LengthConverter::LengthConverter(const sc_module_name &name, unsigned maxOutputLength, bool storageEnabled) :
|
||||
sc_module(name), payloadEventQueue(this, &LengthConverter::peqCallback), storageEnabled(storageEnabled),
|
||||
memoryManager(storageEnabled, maxOutputLength), maxOutputLength(maxOutputLength)
|
||||
{
|
||||
iSocket.register_nb_transport_bw(this, &LengthConverter::nb_transport_bw);
|
||||
tSocket.register_nb_transport_fw(this, &LengthConverter::nb_transport_fw);
|
||||
tSocket.register_transport_dbg(this, &LengthConverter::transport_dbg);
|
||||
}
|
||||
|
||||
tlm_sync_enum LengthConverter::nb_transport_fw(tlm_generic_payload& trans,
|
||||
tlm_phase& phase, sc_time& fwDelay)
|
||||
{
|
||||
if (phase == BEGIN_REQ)
|
||||
trans.acquire();
|
||||
|
||||
payloadEventQueue.notify(trans, phase, fwDelay);
|
||||
return TLM_ACCEPTED;
|
||||
}
|
||||
|
||||
tlm_sync_enum LengthConverter::nb_transport_bw(tlm_generic_payload &payload,
|
||||
tlm_phase &phase, sc_time &bwDelay)
|
||||
{
|
||||
payloadEventQueue.notify(payload, phase, bwDelay);
|
||||
return TLM_ACCEPTED;
|
||||
}
|
||||
|
||||
unsigned int LengthConverter::transport_dbg(tlm_generic_payload &trans)
|
||||
{
|
||||
return iSocket->transport_dbg(trans);
|
||||
}
|
||||
|
||||
void LengthConverter::peqCallback(tlm_generic_payload &cbTrans, const tlm_phase &cbPhase)
|
||||
{
|
||||
if (cbPhase == BEGIN_REQ) // from initiator
|
||||
{
|
||||
if (cbTrans.get_data_length() <= maxOutputLength)
|
||||
{
|
||||
// pipe transaction through
|
||||
tlm_phase fwPhase = BEGIN_REQ;
|
||||
sc_time fwDelay = SC_ZERO_TIME;
|
||||
tlm_sync_enum returnStatus = iSocket->nb_transport_fw(cbTrans, fwPhase, fwDelay);
|
||||
// TODO: END_REQ/BEGIN_RESP shortcut
|
||||
}
|
||||
else
|
||||
{
|
||||
// split transaction up into multiple sub-transactions
|
||||
createChildTranses(&cbTrans);
|
||||
tlm_generic_payload* firstChildTrans = cbTrans.get_extension<ParentExtension>()->getNextChildTrans();
|
||||
tlm_phase fwPhase = BEGIN_REQ;
|
||||
sc_time fwDelay = SC_ZERO_TIME;
|
||||
tlm_sync_enum returnStatus = iSocket->nb_transport_fw(*firstChildTrans, fwPhase, fwDelay);
|
||||
}
|
||||
}
|
||||
else if (cbPhase == END_REQ)
|
||||
{
|
||||
if (ChildExtension::isChildTrans(&cbTrans))
|
||||
{
|
||||
tlm_generic_payload* nextChildTrans = cbTrans.get_extension<ChildExtension>()->getNextChildTrans();
|
||||
if (nextChildTrans != nullptr)
|
||||
{
|
||||
tlm_phase fwPhase = BEGIN_REQ;
|
||||
//sc_time fwDelay = SC_ZERO_TIME;
|
||||
sc_time fwDelay = sc_time(1, SC_NS);
|
||||
tlm_sync_enum returnStatus = iSocket->nb_transport_fw(*nextChildTrans, fwPhase, fwDelay);
|
||||
}
|
||||
else
|
||||
{
|
||||
tlm_generic_payload* parentTrans = cbTrans.get_extension<ChildExtension>()->getParentTrans();
|
||||
tlm_phase bwPhase = END_REQ;
|
||||
sc_time bwDelay = SC_ZERO_TIME;
|
||||
tlm_sync_enum returnStatus = tSocket->nb_transport_bw(*parentTrans, bwPhase, bwDelay);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
tlm_phase bwPhase = END_REQ;
|
||||
sc_time bwDelay = SC_ZERO_TIME;
|
||||
tlm_sync_enum returnStatus = tSocket->nb_transport_bw(cbTrans, bwPhase, bwDelay);
|
||||
}
|
||||
}
|
||||
else if (cbPhase == BEGIN_RESP)
|
||||
{
|
||||
if (ChildExtension::isChildTrans(&cbTrans))
|
||||
{
|
||||
{
|
||||
tlm_phase fwPhase = END_RESP;
|
||||
sc_time fwDelay = SC_ZERO_TIME;
|
||||
tlm_sync_enum returnStatus = iSocket->nb_transport_fw(cbTrans, fwPhase, fwDelay);
|
||||
}
|
||||
|
||||
if (storageEnabled && cbTrans.is_read())
|
||||
{
|
||||
tlm_generic_payload* parentTrans = cbTrans.get_extension<ChildExtension>()->getParentTrans();
|
||||
std::copy(cbTrans.get_data_ptr(), cbTrans.get_data_ptr() + maxOutputLength,
|
||||
parentTrans->get_data_ptr() + (cbTrans.get_address() - parentTrans->get_address()));
|
||||
}
|
||||
|
||||
if (cbTrans.get_extension<ChildExtension>()->notifyChildTransCompletion()) // all children finished
|
||||
{
|
||||
// BEGIN_RESP über tSocket
|
||||
tlm_generic_payload* parentTrans = cbTrans.get_extension<ChildExtension>()->getParentTrans();
|
||||
tlm_phase bwPhase = BEGIN_RESP;
|
||||
sc_time bwDelay = SC_ZERO_TIME;
|
||||
tlm_sync_enum returnStatus = tSocket->nb_transport_bw(*parentTrans, bwPhase, bwDelay);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
tlm_phase bwPhase = BEGIN_RESP;
|
||||
sc_time bwDelay = SC_ZERO_TIME;
|
||||
tlm_sync_enum returnStatus = tSocket->nb_transport_bw(cbTrans, bwPhase, bwDelay);
|
||||
}
|
||||
}
|
||||
else if (cbPhase == END_RESP)
|
||||
{
|
||||
if (ParentExtension::isParentTrans(&cbTrans))
|
||||
{
|
||||
cbTrans.get_extension<ParentExtension>()->releaseChildTranses();
|
||||
}
|
||||
else
|
||||
{
|
||||
tlm_phase fwPhase = END_RESP;
|
||||
sc_time fwDelay = SC_ZERO_TIME;
|
||||
tlm_sync_enum returnStatus = iSocket->nb_transport_fw(cbTrans, fwPhase, fwDelay);
|
||||
}
|
||||
cbTrans.release();
|
||||
}
|
||||
else
|
||||
SC_REPORT_FATAL(0, "Payload event queue in LengthConverter was triggered with unknown phase");
|
||||
}
|
||||
|
||||
void LengthConverter::createChildTranses(tlm_generic_payload* parentTrans)
|
||||
{
|
||||
unsigned numChildTranses = parentTrans->get_data_length() / maxOutputLength;
|
||||
std::vector<tlm_generic_payload*> childTranses;
|
||||
|
||||
for (unsigned childId = 0; childId < numChildTranses; childId++)
|
||||
{
|
||||
tlm_generic_payload* childTrans = memoryManager.allocate();
|
||||
childTrans->acquire();
|
||||
childTrans->set_command(parentTrans->get_command());
|
||||
childTrans->set_address(parentTrans->get_address() + childId * maxOutputLength);
|
||||
childTrans->set_data_length(maxOutputLength);
|
||||
if (storageEnabled && parentTrans->is_write())
|
||||
std::copy(parentTrans->get_data_ptr() + childId * maxOutputLength, parentTrans->get_data_ptr() +
|
||||
(childId + 1) * maxOutputLength, childTrans->get_data_ptr());
|
||||
ChildExtension::setExtension(childTrans, parentTrans);
|
||||
childTranses.push_back(childTrans);
|
||||
}
|
||||
ParentExtension::setExtension(parentTrans, std::move(childTranses));
|
||||
}
|
||||
|
||||
LengthConverter::MemoryManager::MemoryManager(bool storageEnabled, unsigned maxDataLength)
|
||||
: storageEnabled(storageEnabled), maxDataLength(maxDataLength)
|
||||
{}
|
||||
|
||||
LengthConverter::MemoryManager::~MemoryManager()
|
||||
{
|
||||
while (!freePayloads.empty())
|
||||
{
|
||||
tlm_generic_payload* payload = freePayloads.top();
|
||||
if (storageEnabled)
|
||||
delete[] payload->get_data_ptr();
|
||||
payload->reset();
|
||||
delete payload;
|
||||
freePayloads.pop();
|
||||
}
|
||||
}
|
||||
|
||||
tlm_generic_payload* LengthConverter::MemoryManager::allocate()
|
||||
{
|
||||
if (freePayloads.empty())
|
||||
{
|
||||
auto* payload = new tlm_generic_payload(this);
|
||||
|
||||
if (storageEnabled)
|
||||
{
|
||||
auto* data = new unsigned char[maxDataLength];
|
||||
payload->set_data_ptr(data);
|
||||
}
|
||||
return payload;
|
||||
}
|
||||
else
|
||||
{
|
||||
tlm_generic_payload* result = freePayloads.top();
|
||||
freePayloads.pop();
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
void LengthConverter::MemoryManager::free(tlm_generic_payload* payload)
|
||||
{
|
||||
freePayloads.push(payload);
|
||||
}
|
||||
233
DRAMSys/simulator/LengthConverter.h
Normal file
233
DRAMSys/simulator/LengthConverter.h
Normal file
@@ -0,0 +1,233 @@
|
||||
/*
|
||||
* Copyright (c) 2022, Technische Universität 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:
|
||||
* Lukas Steiner
|
||||
*/
|
||||
|
||||
#ifndef LENGTHCONVERTER_H
|
||||
#define LENGTHCONVERTER_H
|
||||
|
||||
#include <iostream>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
#include <queue>
|
||||
#include <set>
|
||||
#include <unordered_map>
|
||||
#include <stack>
|
||||
|
||||
#include <tlm>
|
||||
#include <systemc>
|
||||
#include <tlm_utils/simple_initiator_socket.h>
|
||||
#include <tlm_utils/simple_target_socket.h>
|
||||
#include <tlm_utils/peq_with_cb_and_phase.h>
|
||||
|
||||
//TLM_DECLARE_EXTENDED_PHASE(REQ_ARBITRATION);
|
||||
//TLM_DECLARE_EXTENDED_PHASE(RESP_ARBITRATION);
|
||||
|
||||
class LengthConverter : public sc_core::sc_module
|
||||
{
|
||||
public:
|
||||
tlm_utils::simple_initiator_socket<LengthConverter> iSocket;
|
||||
tlm_utils::simple_target_socket<LengthConverter> tSocket;
|
||||
|
||||
LengthConverter(const sc_core::sc_module_name& name, unsigned maxOutputLength, bool storageEnabled);
|
||||
SC_HAS_PROCESS(LengthConverter);
|
||||
|
||||
private:
|
||||
tlm_utils::peq_with_cb_and_phase<LengthConverter> payloadEventQueue;
|
||||
void peqCallback(tlm::tlm_generic_payload &payload, const tlm::tlm_phase &phase);
|
||||
|
||||
//std::vector<bool> tSocketIsBusy;
|
||||
//std::vector<bool> iSocketIsBusy;
|
||||
|
||||
const unsigned maxOutputLength;
|
||||
const bool storageEnabled;
|
||||
|
||||
void createChildTranses(tlm::tlm_generic_payload* parentTrans);
|
||||
|
||||
//std::uint64_t getTargetAddress(std::uint64_t address) const;
|
||||
//int getISocketId(std::uint64_t address) const;
|
||||
|
||||
//std::vector<std::queue<tlm::tlm_generic_payload *>> pendingRequests;
|
||||
|
||||
tlm::tlm_sync_enum nb_transport_fw(tlm::tlm_generic_payload &trans, tlm::tlm_phase &phase,
|
||||
sc_core::sc_time &fwDelay);
|
||||
tlm::tlm_sync_enum nb_transport_bw(tlm::tlm_generic_payload &payload, tlm::tlm_phase &phase,
|
||||
sc_core::sc_time &bwDelay);
|
||||
unsigned int transport_dbg(tlm::tlm_generic_payload &trans);
|
||||
|
||||
class MemoryManager : public tlm::tlm_mm_interface
|
||||
{
|
||||
public:
|
||||
MemoryManager(bool storageEnabled, unsigned maxDataLength);
|
||||
~MemoryManager() override;
|
||||
tlm::tlm_generic_payload* allocate();
|
||||
void free(tlm::tlm_generic_payload* payload) override;
|
||||
|
||||
private:
|
||||
std::stack<tlm::tlm_generic_payload*> freePayloads;
|
||||
bool storageEnabled = false;
|
||||
unsigned maxDataLength;
|
||||
} memoryManager;
|
||||
|
||||
class ChildExtension : public tlm::tlm_extension<ChildExtension>
|
||||
{
|
||||
private:
|
||||
tlm::tlm_generic_payload* parentTrans;
|
||||
explicit ChildExtension(tlm::tlm_generic_payload* parentTrans) : parentTrans(parentTrans) {}
|
||||
|
||||
public:
|
||||
//ChildExtension() = delete;
|
||||
|
||||
tlm_extension_base* clone() const override
|
||||
{
|
||||
return new ChildExtension(parentTrans);
|
||||
}
|
||||
|
||||
void copy_from(tlm_extension_base const &ext) override
|
||||
{
|
||||
const auto& cpyFrom = dynamic_cast<const ChildExtension&>(ext);
|
||||
parentTrans = cpyFrom.parentTrans;
|
||||
}
|
||||
|
||||
tlm::tlm_generic_payload* getParentTrans()
|
||||
{
|
||||
return parentTrans;
|
||||
}
|
||||
|
||||
static void setExtension(tlm::tlm_generic_payload* childTrans, tlm::tlm_generic_payload* parentTrans)
|
||||
{
|
||||
auto *extension = childTrans->get_extension<ChildExtension>();
|
||||
|
||||
if (extension != nullptr)
|
||||
{
|
||||
extension->parentTrans = parentTrans;
|
||||
}
|
||||
else
|
||||
{
|
||||
extension = new ChildExtension(parentTrans);
|
||||
childTrans->set_auto_extension(extension);
|
||||
}
|
||||
}
|
||||
|
||||
static bool isChildTrans(const tlm::tlm_generic_payload* trans)
|
||||
{
|
||||
if (trans->get_extension<ChildExtension>() != nullptr)
|
||||
return true;
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
tlm::tlm_generic_payload* getNextChildTrans()
|
||||
{
|
||||
return parentTrans->get_extension<ParentExtension>()->getNextChildTrans();
|
||||
}
|
||||
|
||||
bool notifyChildTransCompletion()
|
||||
{
|
||||
return parentTrans->get_extension<ParentExtension>()->notifyChildTransCompletion();
|
||||
}
|
||||
};
|
||||
|
||||
class ParentExtension : public tlm::tlm_extension<ParentExtension>
|
||||
{
|
||||
private:
|
||||
std::vector<tlm::tlm_generic_payload*> childTranses;
|
||||
unsigned nextEndReqChildId = 0;
|
||||
unsigned completedChildTranses = 0;
|
||||
explicit ParentExtension(std::vector<tlm::tlm_generic_payload*> _childTranses)
|
||||
: childTranses(std::move(_childTranses)) {}
|
||||
|
||||
public:
|
||||
ParentExtension() = delete;
|
||||
|
||||
tlm_extension_base* clone() const override
|
||||
{
|
||||
return new ParentExtension(childTranses);
|
||||
}
|
||||
|
||||
void copy_from(tlm_extension_base const &ext) override
|
||||
{
|
||||
const auto& cpyFrom = dynamic_cast<const ParentExtension&>(ext);
|
||||
childTranses = cpyFrom.childTranses;
|
||||
}
|
||||
|
||||
static bool isParentTrans(const tlm::tlm_generic_payload* trans)
|
||||
{
|
||||
auto* extension = trans->get_extension<ParentExtension>();
|
||||
if (extension != nullptr)
|
||||
return !extension->childTranses.empty();
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
static void setExtension(tlm::tlm_generic_payload* parentTrans, std::vector<tlm::tlm_generic_payload*> childTranses)
|
||||
{
|
||||
auto* extension = parentTrans->get_extension<ParentExtension>();
|
||||
|
||||
if (extension != nullptr)
|
||||
{
|
||||
extension->childTranses = std::move(childTranses);
|
||||
extension->nextEndReqChildId = 0;
|
||||
extension->completedChildTranses = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
extension = new ParentExtension(std::move(childTranses));
|
||||
parentTrans->set_auto_extension(extension);
|
||||
}
|
||||
}
|
||||
|
||||
tlm::tlm_generic_payload* getNextChildTrans()
|
||||
{
|
||||
if (nextEndReqChildId < childTranses.size())
|
||||
return childTranses[nextEndReqChildId++];
|
||||
else
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
bool notifyChildTransCompletion()
|
||||
{
|
||||
completedChildTranses++;
|
||||
return completedChildTranses == childTranses.size();
|
||||
}
|
||||
|
||||
void releaseChildTranses()
|
||||
{
|
||||
std::for_each(childTranses.begin(), childTranses.end(),
|
||||
[](tlm::tlm_generic_payload* childTrans){childTrans->release();});
|
||||
childTranses.clear();
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
#endif // LENGTHCONVERTER_H
|
||||
@@ -51,17 +51,18 @@ MemoryManager::MemoryManager()
|
||||
|
||||
MemoryManager::~MemoryManager()
|
||||
{
|
||||
for (tlm_generic_payload *payload : freePayloads)
|
||||
for (auto& innerBuffer : freePayloads)
|
||||
{
|
||||
if (storageEnabled)
|
||||
while (!innerBuffer.second.empty())
|
||||
{
|
||||
// Delete data buffer
|
||||
delete[] payload->get_data_ptr();
|
||||
tlm_generic_payload* payload = innerBuffer.second.top();
|
||||
if (storageEnabled)
|
||||
delete[] payload->get_data_ptr();
|
||||
payload->reset();
|
||||
delete payload;
|
||||
innerBuffer.second.pop();
|
||||
numberOfFrees++;
|
||||
}
|
||||
// Delete all extensions
|
||||
payload->reset();
|
||||
delete payload;
|
||||
numberOfFrees++;
|
||||
}
|
||||
|
||||
// Comment in if you are suspecting a memory leak in the manager
|
||||
@@ -69,18 +70,17 @@ MemoryManager::~MemoryManager()
|
||||
//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->bytesPerBurst;
|
||||
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;
|
||||
};
|
||||
|
||||
|
||||
@@ -48,9 +48,10 @@ StlPlayer::StlPlayer(const sc_module_name &name,
|
||||
const sc_time &playerClk,
|
||||
unsigned int maxPendingReadRequests,
|
||||
unsigned int maxPendingWriteRequests,
|
||||
bool addLengthConverter,
|
||||
TraceSetup *setup,
|
||||
bool relative) :
|
||||
TrafficInitiator(name, setup, maxPendingReadRequests, maxPendingWriteRequests),
|
||||
TrafficInitiator(name, setup, maxPendingReadRequests, maxPendingWriteRequests, addLengthConverter),
|
||||
file(pathToTrace), relative(relative), playerClk(playerClk)
|
||||
{
|
||||
currentBuffer = &lineContents[0];
|
||||
@@ -73,9 +74,6 @@ StlPlayer::StlPlayer(const sc_module_name &name,
|
||||
SC_REPORT_FATAL("StlPlayer", "Trace file is empty");
|
||||
}
|
||||
|
||||
burstLength = Configuration::getInstance().memSpec->burstLength;
|
||||
dataLength = Configuration::getInstance().memSpec->bytesPerBurst;
|
||||
|
||||
currentBuffer->reserve(lineBufferSize);
|
||||
parseBuffer->reserve(lineBufferSize);
|
||||
|
||||
@@ -103,17 +101,16 @@ 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.
|
||||
payload->set_address(lineIterator->addr);
|
||||
payload->set_address(lineIterator->address);
|
||||
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_command(lineIterator->cmd);
|
||||
payload->set_data_length(lineIterator->dataLength);
|
||||
payload->set_command(lineIterator->command);
|
||||
std::copy(lineIterator->data.begin(), lineIterator->data.end(), payload->get_data_ptr());
|
||||
|
||||
sc_time sendingTime;
|
||||
@@ -164,64 +161,60 @@ void StlPlayer::parseTraceFile()
|
||||
// Trace files MUST provide timestamp, command and address for every
|
||||
// transaction. The data information depends on the storage mode
|
||||
// configuration.
|
||||
std::string time, command, address, dataStr;
|
||||
std::string element;
|
||||
std::istringstream iss;
|
||||
|
||||
iss.str(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 = playerClk * static_cast<double>(std::stoull(time));
|
||||
iss >> element;
|
||||
if (element.empty())
|
||||
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 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_READ_COMMAND;
|
||||
else if (command == "write")
|
||||
content.cmd = TLM_WRITE_COMMAND;
|
||||
// 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());
|
||||
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());
|
||||
}
|
||||
else
|
||||
SC_REPORT_FATAL("StlPlayer",
|
||||
(std::string("Corrupted tracefile, command ") + command +
|
||||
std::string(" unknown")).c_str());
|
||||
content.dataLength = defaultDataLength;
|
||||
|
||||
if (element == "read")
|
||||
content.command = TLM_READ_COMMAND;
|
||||
else if (element == "write")
|
||||
content.command = TLM_WRITE_COMMAND;
|
||||
else
|
||||
SC_REPORT_FATAL("StlPlayer", ("Malformed trace file line " + std::to_string(lineCnt) + ".").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, nullptr, 16);
|
||||
iss >> element;
|
||||
if (element.empty())
|
||||
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.
|
||||
if (storageEnabled && content.cmd == TLM_WRITE_COMMAND)
|
||||
if (storageEnabled && content.command == 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());
|
||||
iss >> element;
|
||||
|
||||
// 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());
|
||||
if (element.length() != (content.dataLength * 2 + 2))
|
||||
SC_REPORT_FATAL("StlPlayer", ("Malformed trace file line " + std::to_string(lineCnt) + ".").c_str());
|
||||
|
||||
// Set data
|
||||
for (unsigned i = 0; i < dataLength; i++)
|
||||
for (unsigned i = 0; i < content.dataLength; i++)
|
||||
content.data.emplace_back(static_cast<unsigned char>
|
||||
(std::stoi(dataStr.substr(i * 2 + 2, 2), nullptr, 16)));
|
||||
(std::stoi(element.substr(i * 2 + 2, 2), nullptr, 16)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -55,8 +55,9 @@
|
||||
struct LineContent
|
||||
{
|
||||
sc_core::sc_time sendingTime;
|
||||
tlm::tlm_command cmd;
|
||||
uint64_t addr;
|
||||
unsigned dataLength;
|
||||
tlm::tlm_command command;
|
||||
uint64_t address;
|
||||
std::vector<unsigned char> data;
|
||||
};
|
||||
|
||||
@@ -68,6 +69,7 @@ public:
|
||||
const sc_core::sc_time &playerClk,
|
||||
unsigned int maxPendingReadRequests,
|
||||
unsigned int maxPendingWriteRequests,
|
||||
bool addLengthConverter,
|
||||
TraceSetup *setup,
|
||||
bool relative);
|
||||
|
||||
|
||||
@@ -45,7 +45,7 @@ using namespace tlm;
|
||||
|
||||
TraceSetup::TraceSetup(const std::string &uri,
|
||||
const std::string &pathToResources,
|
||||
std::vector<TrafficInitiator *> &players)
|
||||
std::vector<std::unique_ptr<TrafficInitiator>> &players)
|
||||
{
|
||||
// Load Simulation:
|
||||
nlohmann::json simulationdoc = parseJSON(uri);
|
||||
@@ -83,6 +83,10 @@ TraceSetup::TraceSetup(const std::string &uri,
|
||||
if (value["maxPendingWriteRequests"].is_number_unsigned())
|
||||
maxPendingWriteRequests = value["maxPendingWriteRequests"];
|
||||
|
||||
bool addLengthConverter = false;
|
||||
if (value["addLengthConverter"].is_boolean())
|
||||
addLengthConverter = value["addLengthConverter"];
|
||||
|
||||
std::string type;
|
||||
|
||||
// Defaulting to type "player" when not specified
|
||||
@@ -112,16 +116,17 @@ TraceSetup::TraceSetup(const std::string &uri,
|
||||
StlPlayer *player;
|
||||
if (ext == "stl")
|
||||
player = new StlPlayer(moduleName.c_str(), stlFile, playerClk,
|
||||
maxPendingReadRequests, maxPendingWriteRequests, this, false);
|
||||
maxPendingReadRequests, maxPendingWriteRequests,
|
||||
addLengthConverter, this, false);
|
||||
else if (ext == "rstl")
|
||||
player = new StlPlayer(moduleName.c_str(), stlFile, playerClk,
|
||||
maxPendingReadRequests, maxPendingWriteRequests, this, true);
|
||||
maxPendingReadRequests, maxPendingWriteRequests,
|
||||
addLengthConverter, this, true);
|
||||
else
|
||||
throw std::runtime_error("Unsupported file extension in " + name);
|
||||
|
||||
players.push_back(player);
|
||||
|
||||
totalTransactions += player->getNumberOfLines();
|
||||
players.push_back(std::unique_ptr<TrafficInitiator>(player));
|
||||
}
|
||||
else if (type == "generator")
|
||||
{
|
||||
@@ -180,8 +185,6 @@ TraceSetup::TraceSetup(const std::string &uri,
|
||||
if (maxAddress < minAddress)
|
||||
SC_REPORT_FATAL("TraceSetup", "maxAddress is smaller than minAddress.");
|
||||
|
||||
TrafficInitiator* generator;
|
||||
|
||||
if (addressDistribution == "sequential")
|
||||
{
|
||||
uint64_t addressIncrement = 0x0;
|
||||
@@ -190,20 +193,17 @@ TraceSetup::TraceSetup(const std::string &uri,
|
||||
else
|
||||
addressIncrement = value["addressIncrement"];
|
||||
|
||||
generator = new TrafficGeneratorSequential(name.c_str(), playerClk, numRequests,
|
||||
maxPendingReadRequests, maxPendingWriteRequests,
|
||||
minAddress, maxAddress, rwRatio, addressIncrement, seed,
|
||||
this);
|
||||
players.push_back(std::unique_ptr<TrafficInitiator>(new TrafficGeneratorSequential(name.c_str(),
|
||||
playerClk, numRequests, maxPendingReadRequests, maxPendingWriteRequests, addLengthConverter,
|
||||
minAddress, maxAddress, rwRatio, addressIncrement, seed, this)));
|
||||
}
|
||||
else
|
||||
{
|
||||
generator = new TrafficGeneratorRandom(name.c_str(), playerClk, numRequests,
|
||||
maxPendingReadRequests, maxPendingWriteRequests,
|
||||
minAddress, maxAddress, rwRatio, seed, this);
|
||||
players.push_back(std::unique_ptr<TrafficInitiator>(new TrafficGeneratorRandom(name.c_str(),
|
||||
playerClk, numRequests, maxPendingReadRequests, maxPendingWriteRequests, addLengthConverter,
|
||||
minAddress, maxAddress, rwRatio, seed, this)));
|
||||
}
|
||||
|
||||
players.push_back(generator);
|
||||
|
||||
totalTransactions += numRequests;
|
||||
}
|
||||
else if (type == "hammer")
|
||||
@@ -216,9 +216,8 @@ TraceSetup::TraceSetup(const std::string &uri,
|
||||
SC_REPORT_FATAL("TraceSetup", "Row increment is not a number.");
|
||||
uint64_t rowIncrement = value["rowIncrement"];
|
||||
|
||||
TrafficInitiator* generator = new TrafficGeneratorHammer(name.c_str(), playerClk, numRequests,
|
||||
rowIncrement, this);
|
||||
players.push_back(generator);
|
||||
players.push_back(std::unique_ptr<TrafficInitiator>(new TrafficGeneratorHammer(name.c_str(), playerClk,
|
||||
numRequests, rowIncrement, this)));
|
||||
}
|
||||
}
|
||||
else
|
||||
@@ -227,6 +226,7 @@ TraceSetup::TraceSetup(const std::string &uri,
|
||||
|
||||
remainingTransactions = totalTransactions;
|
||||
numberOfTrafficInitiators = players.size();
|
||||
defaultDataLength = Configuration::getInstance().memSpec->defaultBytesPerBurst;
|
||||
}
|
||||
|
||||
void TraceSetup::trafficInitiatorTerminates()
|
||||
@@ -247,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)
|
||||
|
||||
@@ -39,6 +39,7 @@
|
||||
|
||||
#include <vector>
|
||||
#include <string>
|
||||
#include <memory>
|
||||
|
||||
#include <tlm>
|
||||
#include "MemoryManager.h"
|
||||
@@ -50,10 +51,11 @@ class TraceSetup
|
||||
public:
|
||||
TraceSetup(const std::string &uri,
|
||||
const std::string &pathToResources,
|
||||
std::vector<TrafficInitiator *> &devices);
|
||||
std::vector<std::unique_ptr<TrafficInitiator>> &devices);
|
||||
|
||||
void trafficInitiatorTerminates();
|
||||
void transactionFinished();
|
||||
tlm::tlm_generic_payload *allocatePayload(unsigned dataLength);
|
||||
tlm::tlm_generic_payload *allocatePayload();
|
||||
|
||||
private:
|
||||
@@ -62,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);
|
||||
};
|
||||
|
||||
@@ -46,17 +46,14 @@ TrafficGenerator::TrafficGenerator(const sc_module_name &name,
|
||||
uint64_t numRequests,
|
||||
unsigned int maxPendingReadRequests,
|
||||
unsigned int maxPendingWriteRequests,
|
||||
bool addLengthConverter,
|
||||
float rwRatio,
|
||||
unsigned int seed,
|
||||
TraceSetup *setup) :
|
||||
TrafficInitiator(name, setup, maxPendingReadRequests, maxPendingWriteRequests),
|
||||
generatorClk(generatorClk), numRequests(numRequests), rwRatio(rwRatio)
|
||||
{
|
||||
burstLength = Configuration::getInstance().memSpec->burstLength;
|
||||
dataLength = Configuration::getInstance().memSpec->bytesPerBurst;
|
||||
|
||||
randomGenerator = std::default_random_engine(seed);
|
||||
}
|
||||
TrafficInitiator(name, setup, maxPendingReadRequests, maxPendingWriteRequests, addLengthConverter),
|
||||
generatorClk(generatorClk), numRequests(numRequests), rwRatio(rwRatio),
|
||||
randomGenerator(std::default_random_engine(seed))
|
||||
{}
|
||||
|
||||
void TrafficGenerator::sendNextPayload()
|
||||
{
|
||||
@@ -89,8 +86,7 @@ void TrafficGenerator::sendNextPayload()
|
||||
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_length(defaultDataLength);
|
||||
payload->set_command(command);
|
||||
|
||||
sc_time sendingOffset;
|
||||
@@ -111,13 +107,14 @@ TrafficGeneratorRandom::TrafficGeneratorRandom(const sc_core::sc_module_name &na
|
||||
uint64_t numRequests,
|
||||
unsigned int maxPendingReadRequests,
|
||||
unsigned int maxPendingWriteRequests,
|
||||
bool addLengthConverter,
|
||||
uint64_t minAddress,
|
||||
uint64_t maxAddress,
|
||||
float rwRatio,
|
||||
unsigned int seed,
|
||||
TraceSetup *setup) :
|
||||
TrafficGenerator(name, generatorClk, numRequests, maxPendingReadRequests, maxPendingWriteRequests, rwRatio, seed,
|
||||
setup)
|
||||
TrafficGenerator(name, generatorClk, numRequests, maxPendingReadRequests, maxPendingWriteRequests,
|
||||
addLengthConverter, rwRatio, seed, setup)
|
||||
{
|
||||
randomAddressDistribution = std::uniform_int_distribution<uint64_t> (minAddress, maxAddress);
|
||||
}
|
||||
@@ -132,14 +129,16 @@ TrafficGeneratorSequential::TrafficGeneratorSequential(const sc_core::sc_module_
|
||||
uint64_t numRequests,
|
||||
unsigned int maxPendingReadRequests,
|
||||
unsigned int maxPendingWriteRequests,
|
||||
bool addLengthConverter,
|
||||
uint64_t minAddress,
|
||||
uint64_t maxAddress,
|
||||
float rwRatio,
|
||||
uint64_t addressIncrement,
|
||||
unsigned int seed,
|
||||
TraceSetup *setup) :
|
||||
TrafficGenerator(name, generatorClk, numRequests, maxPendingReadRequests, maxPendingWriteRequests, rwRatio, seed,
|
||||
setup), minAddress(minAddress), maxAddress(maxAddress), addressIncrement(addressIncrement),
|
||||
TrafficGenerator(name, generatorClk, numRequests, maxPendingReadRequests, maxPendingWriteRequests,
|
||||
addLengthConverter, rwRatio, seed, setup),
|
||||
minAddress(minAddress), maxAddress(maxAddress), addressIncrement(addressIncrement),
|
||||
currentAddress(minAddress)
|
||||
{
|
||||
}
|
||||
@@ -159,7 +158,7 @@ TrafficGeneratorHammer::TrafficGeneratorHammer(const sc_core::sc_module_name &na
|
||||
uint64_t numRequests,
|
||||
uint64_t rowIncrement,
|
||||
TraceSetup *setup) :
|
||||
TrafficGenerator(name, generatorClk, numRequests, 1, 1, 1.0f, 1, setup), rowIncrement(rowIncrement)
|
||||
TrafficGenerator(name, generatorClk, numRequests, 1, 1, false, 1.0f, 1, setup), rowIncrement(rowIncrement)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
@@ -52,6 +52,7 @@ protected:
|
||||
uint64_t numRequests,
|
||||
unsigned int maxPendingReadRequests,
|
||||
unsigned int maxPendingWriteRequests,
|
||||
bool addLengthConverter,
|
||||
float rwRatio,
|
||||
unsigned int seed,
|
||||
TraceSetup *setup);
|
||||
@@ -78,6 +79,7 @@ public:
|
||||
uint64_t numRequests,
|
||||
unsigned int maxPendingReadRequests,
|
||||
unsigned int maxPendingWriteRequests,
|
||||
bool addLengthConverter,
|
||||
uint64_t minAddress,
|
||||
uint64_t maxAddress,
|
||||
float rwRatio,
|
||||
@@ -98,6 +100,7 @@ public:
|
||||
uint64_t numRequests,
|
||||
unsigned int maxPendingReadRequests,
|
||||
unsigned int maxPendingWriteRequests,
|
||||
bool addLengthConverter,
|
||||
uint64_t minAddress,
|
||||
uint64_t maxAddress,
|
||||
float rwRatio,
|
||||
|
||||
@@ -44,18 +44,18 @@ using namespace sc_core;
|
||||
using namespace tlm;
|
||||
|
||||
TrafficInitiator::TrafficInitiator(const sc_module_name &name, TraceSetup *setup,
|
||||
unsigned int maxPendingReadRequests, unsigned int maxPendingWriteRequests) :
|
||||
sc_module(name), payloadEventQueue(this, &TrafficInitiator::peqCallback),
|
||||
unsigned int maxPendingReadRequests, unsigned int maxPendingWriteRequests, bool addLengthConverter) :
|
||||
sc_module(name),
|
||||
payloadEventQueue(this, &TrafficInitiator::peqCallback),
|
||||
setup(setup),
|
||||
maxPendingReadRequests(maxPendingReadRequests), maxPendingWriteRequests(maxPendingWriteRequests)
|
||||
maxPendingReadRequests(maxPendingReadRequests),
|
||||
maxPendingWriteRequests(maxPendingWriteRequests),
|
||||
addLengthConverter(addLengthConverter),
|
||||
defaultDataLength(Configuration::getInstance().memSpec->defaultBytesPerBurst),
|
||||
storageEnabled(Configuration::getInstance().storeMode != Configuration::StoreMode::NoStorage)
|
||||
{
|
||||
SC_METHOD(sendNextPayload);
|
||||
iSocket.register_nb_transport_bw(this, &TrafficInitiator::nb_transport_bw);
|
||||
|
||||
if (Configuration::getInstance().storeMode == Configuration::StoreMode::NoStorage)
|
||||
storageEnabled = false;
|
||||
else
|
||||
storageEnabled = true;
|
||||
}
|
||||
|
||||
void TrafficInitiator::terminate()
|
||||
|
||||
@@ -57,14 +57,14 @@ class TrafficInitiator : public sc_core::sc_module
|
||||
public:
|
||||
tlm_utils::simple_initiator_socket<TrafficInitiator> iSocket;
|
||||
TrafficInitiator(const sc_core::sc_module_name &name, TraceSetup *setup,
|
||||
unsigned int maxPendingReadRequests, unsigned int maxPendingWriteRequests);
|
||||
unsigned int maxPendingReadRequests, unsigned int maxPendingWriteRequests, bool addLengthConverter);
|
||||
SC_HAS_PROCESS(TrafficInitiator);
|
||||
virtual void sendNextPayload() = 0;
|
||||
const bool addLengthConverter = false;
|
||||
|
||||
protected:
|
||||
tlm_utils::peq_with_cb_and_phase<TrafficInitiator> payloadEventQueue;
|
||||
void terminate();
|
||||
bool storageEnabled = false;
|
||||
TraceSetup *setup;
|
||||
void sendToTarget(tlm::tlm_generic_payload &payload, const tlm::tlm_phase &phase,
|
||||
const sc_core::sc_time &delay);
|
||||
@@ -73,13 +73,12 @@ protected:
|
||||
uint64_t transactionsSent = 0;
|
||||
unsigned int pendingReadRequests = 0;
|
||||
unsigned int pendingWriteRequests = 0;
|
||||
unsigned int maxPendingReadRequests = 0;
|
||||
unsigned int maxPendingWriteRequests = 0;
|
||||
const unsigned int maxPendingReadRequests = 0;
|
||||
const unsigned int maxPendingWriteRequests = 0;
|
||||
bool payloadPostponed = false;
|
||||
bool finished = false;
|
||||
|
||||
unsigned int burstLength;
|
||||
unsigned int dataLength;
|
||||
const unsigned int defaultDataLength = 64;
|
||||
const bool storageEnabled = false;
|
||||
|
||||
private:
|
||||
tlm::tlm_sync_enum nb_transport_bw(tlm::tlm_generic_payload &payload, tlm::tlm_phase &phase,
|
||||
|
||||
@@ -40,12 +40,15 @@
|
||||
#include <string>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
#include <list>
|
||||
#include <chrono>
|
||||
#include <memory>
|
||||
|
||||
#include <systemc>
|
||||
#include "simulation/DRAMSys.h"
|
||||
#include "TraceSetup.h"
|
||||
#include "TrafficInitiator.h"
|
||||
#include "LengthConverter.h"
|
||||
|
||||
#ifdef RECORDING
|
||||
#include "simulation/DRAMSysRecordable.h"
|
||||
@@ -95,39 +98,40 @@ int sc_main(int argc, char **argv)
|
||||
resources = argv[2];
|
||||
}
|
||||
|
||||
std::vector<TrafficInitiator *> players;
|
||||
std::vector<std::unique_ptr<TrafficInitiator>> players;
|
||||
std::vector<std::unique_ptr<LengthConverter>> lengthConverters;
|
||||
|
||||
// Instantiate DRAMSys:
|
||||
DRAMSys *dramSys;
|
||||
std::unique_ptr<DRAMSys> dramSys;
|
||||
#ifdef RECORDING
|
||||
json simulationdoc = parseJSON(simulationJson);
|
||||
json simulatordoc = parseJSON(resources + "configs/simulator/"
|
||||
+ std::string(simulationdoc["simulation"]["simconfig"]));
|
||||
|
||||
if (simulatordoc["simconfig"]["DatabaseRecording"])
|
||||
dramSys = new DRAMSysRecordable("DRAMSys", simulationJson, resources);
|
||||
if (simulatordoc["simconfig"]["DatabaseRecording"].is_boolean() && simulatordoc["simconfig"]["DatabaseRecording"])
|
||||
dramSys = std::unique_ptr<DRAMSys>(new DRAMSysRecordable("DRAMSys", simulationJson, resources));
|
||||
else
|
||||
#endif
|
||||
dramSys = new DRAMSys("DRAMSys", simulationJson, resources);
|
||||
dramSys = std::unique_ptr<DRAMSys>(new DRAMSys("DRAMSys", simulationJson, resources));
|
||||
|
||||
// Instantiate STL Players:
|
||||
TraceSetup *setup = new TraceSetup(simulationJson, resources, players);
|
||||
// Instantiate STL Players (config of DRAMSys required!):
|
||||
TraceSetup setup(simulationJson, resources, players);
|
||||
|
||||
// Bind STL Players with DRAMSys:
|
||||
for (size_t i = 0; i < players.size(); i++)
|
||||
for (auto& player : players)
|
||||
{
|
||||
if (Configuration::getInstance().checkTLM2Protocol)
|
||||
if (player->addLengthConverter)
|
||||
{
|
||||
std::string str = "TLMCheckerPlayer" + std::to_string(i);
|
||||
tlm_utils::tlm2_base_protocol_checker<> *playerTlmChecker =
|
||||
new tlm_utils::tlm2_base_protocol_checker<>(str.c_str());
|
||||
dramSys->playersTlmCheckers.push_back(playerTlmChecker);
|
||||
players[i]->iSocket.bind(dramSys->playersTlmCheckers[i]->target_socket);
|
||||
dramSys->playersTlmCheckers[i]->initiator_socket.bind(dramSys->tSocket);
|
||||
std::string converterName("Converter_");
|
||||
lengthConverters.emplace_back(new LengthConverter(converterName.append(player->name()).c_str(),
|
||||
Configuration::getInstance().memSpec->maxBytesPerBurst,
|
||||
Configuration::getInstance().storeMode != Configuration::StoreMode::NoStorage));
|
||||
player->iSocket.bind(lengthConverters.back()->tSocket);
|
||||
lengthConverters.back()->iSocket.bind(dramSys->tSocket);
|
||||
}
|
||||
else
|
||||
{
|
||||
players[i]->iSocket.bind(dramSys->tSocket);
|
||||
player->iSocket.bind(dramSys->tSocket);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -147,11 +151,5 @@ int sc_main(int argc, char **argv)
|
||||
auto finish = std::chrono::high_resolution_clock::now();
|
||||
std::chrono::duration<double> elapsed = finish - start;
|
||||
std::cout << "Simulation took " + std::to_string(elapsed.count()) + " seconds." << std::endl;
|
||||
|
||||
delete dramSys;
|
||||
for (auto player : players)
|
||||
delete player;
|
||||
delete setup;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
26
README.md
26
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)]
|
||||
31: read 0x400140
|
||||
33: read 0x400160
|
||||
56: write 0x7fff8000 0x123456789abcdef...
|
||||
81: read 0x400180
|
||||
# cycle: [(length)] command hex-address [hex-data]
|
||||
31: read 0x400140
|
||||
33: read 0x400160
|
||||
56: write 0x7fff8000 0x123456789abcdef...
|
||||
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)]
|
||||
31: read 0x400140
|
||||
2: read 0x400160
|
||||
23: write 0x7fff8000 0x123456789abcdef...
|
||||
25: read 0x400180
|
||||
# cycle: [(length)] command hex-address [hex-data]
|
||||
31: read 0x400140
|
||||
2: (512) read 0x400160
|
||||
23: write 0x7fff8000 0x123456789abcdef...
|
||||
10: read 0x400180
|
||||
```
|
||||
|
||||
##### Elastic Traces
|
||||
|
||||
Reference in New Issue
Block a user