Merge branch 'develop' into work/new_json_format_rebased
This commit is contained in:
@@ -35,6 +35,7 @@
|
||||
* Matthias Jung
|
||||
* Eder F. Zulian
|
||||
* Derek Christ
|
||||
* Lukas Steiner
|
||||
*/
|
||||
|
||||
#include <fstream>
|
||||
@@ -70,7 +71,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);
|
||||
|
||||
@@ -44,7 +44,6 @@ void to_json(json &j, const SimConfig &c)
|
||||
{"CheckTLM2Protocol", c.checkTLM2Protocol},
|
||||
{"DatabaseRecording", c.databaseRecording},
|
||||
{"Debug", c.debug},
|
||||
{"ECCControllerMode", c.eccControllerMode},
|
||||
{"EnableWindowing", c.enableWindowing},
|
||||
{"ErrorCSVFile", c.errorCsvFile},
|
||||
{"ErrorChipSeed", c.errorChipSeed},
|
||||
@@ -73,9 +72,6 @@ void from_json(const json &j, SimConfig &c)
|
||||
if (j_simconfig.contains("Debug"))
|
||||
j_simconfig.at("Debug").get_to(c.debug);
|
||||
|
||||
if (j_simconfig.contains("ECCControllerMode"))
|
||||
j_simconfig.at("ECCControllerMode").get_to(c.eccControllerMode);
|
||||
|
||||
if (j_simconfig.contains("EnableWindowing"))
|
||||
j_simconfig.at("EnableWindowing").get_to(c.enableWindowing);
|
||||
|
||||
@@ -106,7 +102,6 @@ void from_json(const json &j, SimConfig &c)
|
||||
if (j_simconfig.contains("WindowSize"))
|
||||
j_simconfig.at("WindowSize").get_to(c.windowSize);
|
||||
|
||||
invalidateEnum(c.eccControllerMode);
|
||||
invalidateEnum(c.storeMode);
|
||||
}
|
||||
|
||||
|
||||
@@ -46,17 +46,6 @@ using json = nlohmann::json;
|
||||
|
||||
const std::string simConfigPath = "configs/simulator";
|
||||
|
||||
enum class ECCControllerMode
|
||||
{
|
||||
Disabled,
|
||||
Hamming,
|
||||
Invalid = -1
|
||||
};
|
||||
|
||||
NLOHMANN_JSON_SERIALIZE_ENUM(ECCControllerMode, {{ECCControllerMode::Invalid, nullptr},
|
||||
{ECCControllerMode::Disabled, "Disabled"},
|
||||
{ECCControllerMode::Hamming, "Hamming"}})
|
||||
|
||||
enum class StoreMode
|
||||
{
|
||||
NoStorage,
|
||||
@@ -76,7 +65,6 @@ struct SimConfig
|
||||
Optional<bool> checkTLM2Protocol;
|
||||
Optional<bool> databaseRecording;
|
||||
Optional<bool> debug;
|
||||
Optional<ECCControllerMode> eccControllerMode;
|
||||
Optional<bool> enableWindowing;
|
||||
Optional<std::string> errorCsvFile;
|
||||
Optional<unsigned int> errorChipSeed;
|
||||
|
||||
@@ -59,6 +59,7 @@ void to_json(json &j, const TraceSetup &c)
|
||||
initiator_j["clkMhz"] = initiator->clkMhz;
|
||||
initiator_j["maxPendingReadRequests"] = initiator->maxPendingReadRequests;
|
||||
initiator_j["maxPendingWriteRequests"] = initiator->maxPendingWriteRequests;
|
||||
initiator_j["addLengthConverter"] = initiator->addLengthConverter;
|
||||
|
||||
if (const auto generator = dynamic_cast<TraceGenerator *>(initiator.get()))
|
||||
{
|
||||
@@ -264,6 +265,9 @@ void from_json(const json &j, TraceSetup &c)
|
||||
if (initiator_j.contains("maxPendingWriteRequests"))
|
||||
initiator_j.at("maxPendingWriteRequests").get_to(initiator->maxPendingWriteRequests);
|
||||
|
||||
if (initiator_j.contains("addLengthConverter"))
|
||||
initiator_j.at("addLengthConverter").get_to(initiator->addLengthConverter);
|
||||
|
||||
c.initiators.emplace_back(std::move(initiator));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -77,6 +77,7 @@ struct TrafficInitiator
|
||||
std::string name;
|
||||
Optional<unsigned int> maxPendingReadRequests;
|
||||
Optional<unsigned int> maxPendingWriteRequests;
|
||||
Optional<bool> addLengthConverter;
|
||||
};
|
||||
|
||||
struct TracePlayer : public TrafficInitiator
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -80,7 +80,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));
|
||||
}
|
||||
|
||||
@@ -39,8 +39,6 @@
|
||||
* Derek Christ
|
||||
*/
|
||||
|
||||
#include <cassert>
|
||||
|
||||
#include "Configuration.h"
|
||||
#include "memspec/MemSpecDDR3.h"
|
||||
#include "memspec/MemSpecDDR4.h"
|
||||
@@ -78,19 +76,6 @@ enum sc_time_unit string2TimeUnit(const std::string &s)
|
||||
}
|
||||
}
|
||||
|
||||
// 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 == DRAMSysConfiguration::ECCControllerMode::Hamming)
|
||||
{
|
||||
assert(pECC != nullptr);
|
||||
return pECC->AllocationSize(nBytes);
|
||||
}
|
||||
}
|
||||
|
||||
void Configuration::loadSimConfig(Configuration &config, const DRAMSysConfiguration::SimConfig &simConfig)
|
||||
{
|
||||
if (simConfig.addressOffset.isValid())
|
||||
@@ -105,16 +90,6 @@ void Configuration::loadSimConfig(Configuration &config, const DRAMSysConfigurat
|
||||
if (simConfig.debug.isValid())
|
||||
config.debug = simConfig.debug.getValue();
|
||||
|
||||
if (simConfig.eccControllerMode.isValid())
|
||||
config.eccMode = [=] {
|
||||
auto mode = simConfig.eccControllerMode.getValue();
|
||||
|
||||
if (mode == DRAMSysConfiguration::ECCControllerMode::Disabled)
|
||||
return ECCMode::Disabled;
|
||||
else
|
||||
return ECCMode::Hamming;
|
||||
}();
|
||||
|
||||
if (simConfig.enableWindowing.isValid())
|
||||
config.enableWindowing = simConfig.enableWindowing.getValue();
|
||||
|
||||
|
||||
@@ -46,7 +46,6 @@
|
||||
#include <Configuration.h>
|
||||
#include <systemc>
|
||||
#include "memspec/MemSpec.h"
|
||||
#include "../error/eccbaseclass.h"
|
||||
#include "TemperatureSimConfig.h"
|
||||
|
||||
class Configuration
|
||||
@@ -95,8 +94,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;
|
||||
|
||||
@@ -111,8 +108,6 @@ public:
|
||||
// Temperature Simulation related
|
||||
TemperatureSimConfig temperatureSim;
|
||||
|
||||
unsigned int adjustNumBytesAfterECC(unsigned bytes) const;
|
||||
|
||||
static void loadMCConfig(Configuration &config, const DRAMSysConfiguration::McConfig &mcConfig);
|
||||
static void loadSimConfig(Configuration &config, const DRAMSysConfiguration::SimConfig &simConfig);
|
||||
static void loadMemSpec(Configuration &config, const DRAMSysConfiguration::MemSpec &memSpec);
|
||||
|
||||
@@ -56,16 +56,21 @@ MemSpec::MemSpec(const DRAMSysConfiguration::MemSpec &memSpec,
|
||||
numberOfDevices(numberOfDevices),
|
||||
numberOfRows(memSpec.memArchitectureSpec.entries.at("nbrOfRows")),
|
||||
numberOfColumns(memSpec.memArchitectureSpec.entries.at("nbrOfColumns")),
|
||||
burstLength(memSpec.memArchitectureSpec.entries.at("burstLength")),
|
||||
defaultBurstLength(memSpec.memArchitectureSpec.entries.at("burstLength")),
|
||||
maxBurstLength(memSpec.memArchitectureSpec.entries.find("maxBurstLength") !=
|
||||
memSpec.memArchitectureSpec.entries.end()
|
||||
? memSpec.memArchitectureSpec.entries.at("maxBurstLength")
|
||||
: defaultBurstLength),
|
||||
dataRate(memSpec.memArchitectureSpec.entries.at("dataRate")),
|
||||
bitWidth(memSpec.memArchitectureSpec.entries.at("width")),
|
||||
dataBusWidth(bitWidth * numberOfDevices),
|
||||
bytesPerBurst((burstLength * dataBusWidth) / 8),
|
||||
defaultBytesPerBurst((defaultBurstLength * dataBusWidth) / 8),
|
||||
maxBytesPerBurst((maxBurstLength * dataBusWidth) / 8),
|
||||
fCKMHz(memSpec.memTimingSpec.entries.at("clkMhz")),
|
||||
tCK(sc_time(1.0 / fCKMHz, SC_US)),
|
||||
memoryId(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;
|
||||
|
||||
@@ -72,9 +72,6 @@ DRAMSys::DRAMSys(const sc_core::sc_module_name &name,
|
||||
bool initAndBind)
|
||||
: sc_module(name), tSocket("DRAMSys_tSocket")
|
||||
{
|
||||
// Initialize ecc pointer
|
||||
ecc = nullptr;
|
||||
|
||||
logo();
|
||||
|
||||
// Load config and initialize modules
|
||||
@@ -99,25 +96,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"))
|
||||
@@ -161,69 +139,47 @@ void DRAMSys::instantiateModules(const DRAMSysConfiguration::AddressMapping &add
|
||||
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", addressMapping);
|
||||
arbiter = std::unique_ptr<Arbiter>(new ArbiterSimple("arbiter", addressMapping));
|
||||
else if (config.arbiter == Configuration::Arbiter::Fifo)
|
||||
arbiter = new ArbiterFifo("arbiter", addressMapping);
|
||||
arbiter = std::unique_ptr<Arbiter>(new ArbiterFifo("arbiter", addressMapping));
|
||||
else if (config.arbiter == Configuration::Arbiter::Reorder)
|
||||
arbiter = new ArbiterReorder("arbiter", addressMapping);
|
||||
arbiter = std::unique_ptr<Arbiter>(new ArbiterReorder("arbiter", addressMapping));
|
||||
|
||||
// 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()));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -231,32 +187,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);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -51,6 +51,8 @@
|
||||
#include <Configuration.h>
|
||||
#include <string>
|
||||
#include <systemc>
|
||||
#include <list>
|
||||
#include <memory>
|
||||
#include <tlm_utils/multi_passthrough_initiator_socket.h>
|
||||
#include <tlm_utils/multi_passthrough_target_socket.h>
|
||||
|
||||
@@ -59,46 +61,37 @@ 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 DRAMSysConfiguration::Configuration &config);
|
||||
|
||||
~DRAMSys() override;
|
||||
|
||||
protected:
|
||||
DRAMSys(const sc_core::sc_module_name &name,
|
||||
const DRAMSysConfiguration::Configuration &config,
|
||||
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 DRAMSysConfiguration::AddressMapping &addressMapping);
|
||||
void bindSockets();
|
||||
|
||||
static void setupDebugManager(const std::string &traceName);
|
||||
};
|
||||
|
||||
@@ -76,17 +76,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, const DRAMSysConfiguration::Configuration &configuration)
|
||||
@@ -95,18 +95,12 @@ void DRAMSysRecordable::setupTlmRecorders(const std::string &traceName, const DR
|
||||
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(DRAMSysConfiguration::dump(configuration.mcConfig));
|
||||
tlmRecorder->recordMemspec(DRAMSysConfiguration::dump(configuration.memSpec));
|
||||
|
||||
std::string traceNames = Configuration::getInstance().simulationName;
|
||||
tlmRecorder->recordTraceNames(traceNames);
|
||||
|
||||
tlmRecorders.push_back(tlmRecorder);
|
||||
tlmRecorders.emplace_back(recorderName, dbName);
|
||||
tlmRecorders.back().recordMcConfig(DRAMSysConfiguration::dump(configuration.mcConfig));
|
||||
tlmRecorders.back().recordMemspec(DRAMSysConfiguration::dump(configuration.memSpec));
|
||||
tlmRecorders.back().recordTraceNames(Configuration::getInstance().simulationName);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -123,101 +117,47 @@ void DRAMSysRecordable::instantiateModules(const std::string &traceName,
|
||||
// They need to be ready before creating some modules.
|
||||
setupTlmRecorders(traceName, configuration);
|
||||
|
||||
// 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", configuration.addressMapping);
|
||||
arbiter = std::unique_ptr<Arbiter>(new ArbiterSimple("arbiter", configuration.addressMapping));
|
||||
else if (config.arbiter == Configuration::Arbiter::Fifo)
|
||||
arbiter = new ArbiterFifo("arbiter", configuration.addressMapping);
|
||||
arbiter = std::unique_ptr<Arbiter>(new ArbiterFifo("arbiter", configuration.addressMapping));
|
||||
else if (config.arbiter == Configuration::Arbiter::Reorder)
|
||||
arbiter = new ArbiterReorder("arbiter", configuration.addressMapping);
|
||||
arbiter = std::unique_ptr<Arbiter>(new ArbiterReorder("arbiter", configuration.addressMapping));
|
||||
|
||||
// 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()));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -48,19 +48,18 @@ public:
|
||||
DRAMSysRecordable(const sc_core::sc_module_name &name,
|
||||
const DRAMSysConfiguration::Configuration &configuration);
|
||||
|
||||
~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, const DRAMSysConfiguration::Configuration &configuration);
|
||||
|
||||
void instantiateModules(const std::string &traceName,
|
||||
const DRAMSysConfiguration::Configuration &configuration);
|
||||
|
||||
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);
|
||||
|
||||
|
||||
@@ -47,7 +47,7 @@ using namespace tlm;
|
||||
|
||||
TraceSetup::TraceSetup(const DRAMSysConfiguration::TraceSetup &traceSetup,
|
||||
const std::string &pathToResources,
|
||||
std::vector<TrafficInitiator *> &players)
|
||||
std::vector<std::unique_ptr<TrafficInitiator>> &players)
|
||||
{
|
||||
if (traceSetup.initiators.empty())
|
||||
SC_REPORT_FATAL("TraceSetup", "No traffic initiators specified");
|
||||
@@ -73,6 +73,13 @@ TraceSetup::TraceSetup(const DRAMSysConfiguration::TraceSetup &traceSetup,
|
||||
return 0;
|
||||
}();
|
||||
|
||||
bool addLengthConverter = [=]() -> bool {
|
||||
if (inititator->addLengthConverter.isValid())
|
||||
return inititator->addLengthConverter.getValue();
|
||||
else
|
||||
return false;
|
||||
}();
|
||||
|
||||
if (std::dynamic_pointer_cast<DRAMSysConfiguration::TracePlayer>(inititator))
|
||||
{
|
||||
size_t pos = name.rfind('.');
|
||||
@@ -94,20 +101,20 @@ TraceSetup::TraceSetup(const DRAMSysConfiguration::TraceSetup &traceSetup,
|
||||
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);
|
||||
players.push_back(std::unique_ptr<TrafficInitiator>(player));
|
||||
totalTransactions += player->getNumberOfLines();
|
||||
}
|
||||
else if (auto generator = std::dynamic_pointer_cast<DRAMSysConfiguration::TraceGenerator>(inititator))
|
||||
{
|
||||
TrafficGenerator *trafficGenerator = new TrafficGenerator(name.c_str(), *generator, this);
|
||||
players.push_back(trafficGenerator);
|
||||
players.push_back(std::unique_ptr<TrafficInitiator>(trafficGenerator));
|
||||
|
||||
totalTransactions += trafficGenerator->getTotalTransactions();
|
||||
}
|
||||
@@ -116,7 +123,7 @@ TraceSetup::TraceSetup(const DRAMSysConfiguration::TraceSetup &traceSetup,
|
||||
uint64_t numRequests = hammer->numRequests;
|
||||
uint64_t rowIncrement = hammer->rowIncrement;
|
||||
|
||||
players.push_back(new TrafficGeneratorHammer(name.c_str(), *hammer, this));
|
||||
players.push_back(std::unique_ptr<TrafficInitiator>(new TrafficGeneratorHammer(name.c_str(), *hammer, this)));
|
||||
totalTransactions += numRequests;
|
||||
}
|
||||
}
|
||||
@@ -132,16 +139,16 @@ TraceSetup::TraceSetup(const DRAMSysConfiguration::TraceSetup &traceSetup,
|
||||
const std::string name = generatorConf->name;
|
||||
auto listenerIt =
|
||||
std::find_if(players.begin(), players.end(),
|
||||
[&name](const TrafficInitiator *initiator) { return initiator->name() == name; });
|
||||
[&name](const std::unique_ptr<TrafficInitiator> &initiator) { return initiator->name() == name; });
|
||||
|
||||
// Should be found
|
||||
auto listener = dynamic_cast<TrafficGenerator *>(*listenerIt);
|
||||
auto listener = dynamic_cast<TrafficGenerator *>(listenerIt->get());
|
||||
|
||||
auto notifierIt =
|
||||
std::find_if(players.begin(), players.end(),
|
||||
[&idleUntil](const TrafficInitiator *initiator)
|
||||
[&idleUntil](const std::unique_ptr<TrafficInitiator> &initiator)
|
||||
{
|
||||
if (auto generator = dynamic_cast<const TrafficGenerator *>(initiator))
|
||||
if (auto generator = dynamic_cast<const TrafficGenerator *>(initiator.get()))
|
||||
{
|
||||
if (generator->hasStateTransitionEvent(idleUntil))
|
||||
return true;
|
||||
@@ -153,7 +160,7 @@ TraceSetup::TraceSetup(const DRAMSysConfiguration::TraceSetup &traceSetup,
|
||||
if (notifierIt == players.end())
|
||||
SC_REPORT_FATAL("TraceSetup", "Event to listen on not found.");
|
||||
|
||||
auto notifier = dynamic_cast<TrafficGenerator *>(*notifierIt);
|
||||
auto notifier = dynamic_cast<TrafficGenerator *>(notifierIt->get());
|
||||
listener->waitUntil(¬ifier->getStateTransitionEvent(idleUntil));
|
||||
}
|
||||
}
|
||||
@@ -161,6 +168,7 @@ TraceSetup::TraceSetup(const DRAMSysConfiguration::TraceSetup &traceSetup,
|
||||
|
||||
remainingTransactions = totalTransactions;
|
||||
numberOfTrafficInitiators = players.size();
|
||||
defaultDataLength = Configuration::getInstance().memSpec->defaultBytesPerBurst;
|
||||
}
|
||||
|
||||
void TraceSetup::trafficInitiatorTerminates()
|
||||
@@ -181,9 +189,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)
|
||||
|
||||
@@ -37,9 +37,10 @@
|
||||
#ifndef TRACESETUP_H
|
||||
#define TRACESETUP_H
|
||||
|
||||
#include <Configuration.h>
|
||||
#include <vector>
|
||||
#include <string>
|
||||
#include <Configuration.h>
|
||||
#include <memory>
|
||||
#include <tlm>
|
||||
|
||||
#include "MemoryManager.h"
|
||||
@@ -51,10 +52,11 @@ class TraceSetup
|
||||
public:
|
||||
TraceSetup(const DRAMSysConfiguration::TraceSetup &traceSetup,
|
||||
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:
|
||||
@@ -63,6 +65,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);
|
||||
};
|
||||
|
||||
@@ -44,11 +44,9 @@ using namespace sc_core;
|
||||
using namespace tlm;
|
||||
|
||||
TrafficGeneratorIf::TrafficGeneratorIf(const sc_core::sc_module_name &name, TraceSetup *setup,
|
||||
unsigned int maxPendingReadRequests, unsigned int maxPendingWriteRequests)
|
||||
: TrafficInitiator(name, setup, maxPendingReadRequests, maxPendingWriteRequests)
|
||||
unsigned int maxPendingReadRequests, unsigned int maxPendingWriteRequests, bool addLengthConverter)
|
||||
: TrafficInitiator(name, setup, maxPendingReadRequests, maxPendingWriteRequests, addLengthConverter)
|
||||
{
|
||||
burstLength = Configuration::getInstance().memSpec->burstLength;
|
||||
dataLength = Configuration::getInstance().memSpec->bytesPerBurst;
|
||||
}
|
||||
|
||||
void TrafficGeneratorIf::sendNextPayload()
|
||||
@@ -75,8 +73,7 @@ void TrafficGeneratorIf::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 generatorClk = getGeneratorClk();
|
||||
@@ -96,7 +93,7 @@ void TrafficGeneratorIf::sendNextPayload()
|
||||
|
||||
TrafficGenerator::TrafficGenerator(const sc_module_name &name, const DRAMSysConfiguration::TraceGenerator &conf,
|
||||
TraceSetup *setup)
|
||||
: TrafficGeneratorIf(name, setup, evaluateMaxPendingReadRequests(conf), evaluateMaxPendingWriteRequests(conf)),
|
||||
: TrafficGeneratorIf(name, setup, evaluateMaxPendingReadRequests(conf), evaluateMaxPendingWriteRequests(conf), evaluateAddLengthConverter(conf)),
|
||||
generatorClk(TrafficInitiator::evaluateGeneratorClk(conf)), conf(conf), maxTransactions(evaluateMaxTransactions(conf)),
|
||||
randomGenerator(std::default_random_engine(evaluateSeed(conf)))
|
||||
{
|
||||
@@ -366,6 +363,14 @@ uint64_t TrafficGenerator::evaluateMaxTransactions(const DRAMSysConfiguration::T
|
||||
return std::numeric_limits<uint64_t>::max();
|
||||
}
|
||||
|
||||
bool TrafficGenerator::evaluateAddLengthConverter(const DRAMSysConfiguration::TraceGenerator &conf)
|
||||
{
|
||||
if (conf.addLengthConverter.isValid())
|
||||
return conf.addLengthConverter.getValue();
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
uint64_t TrafficGenerator::evaluateMinAddress(const DRAMSysConfiguration::TraceGeneratorTrafficState &state)
|
||||
{
|
||||
if (state.minAddress.isValid())
|
||||
@@ -400,7 +405,7 @@ uint64_t TrafficGenerator::evaluateClksPerRequest(const DRAMSysConfiguration::Tr
|
||||
|
||||
TrafficGeneratorHammer::TrafficGeneratorHammer(const sc_core::sc_module_name &name,
|
||||
const DRAMSysConfiguration::TraceHammer &conf, TraceSetup *setup)
|
||||
: TrafficGeneratorIf(name, setup, 1, 1), generatorClk(evaluateGeneratorClk(conf)), rowIncrement(conf.rowIncrement),
|
||||
: TrafficGeneratorIf(name, setup, 1, 1, false), generatorClk(evaluateGeneratorClk(conf)), rowIncrement(conf.rowIncrement),
|
||||
numRequests(conf.numRequests)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -49,7 +49,7 @@ class TrafficGeneratorIf : public TrafficInitiator
|
||||
{
|
||||
public:
|
||||
TrafficGeneratorIf(const sc_core::sc_module_name &name, TraceSetup *setup, unsigned int maxPendingReadRequests,
|
||||
unsigned int maxPendingWriteRequests);
|
||||
unsigned int maxPendingWriteRequests, bool addLengthConverter);
|
||||
|
||||
private:
|
||||
void sendNextPayload() override;
|
||||
@@ -76,6 +76,7 @@ public:
|
||||
private:
|
||||
static uint64_t evaluateSeed(const DRAMSysConfiguration::TraceGenerator &conf);
|
||||
static uint64_t evaluateMaxTransactions(const DRAMSysConfiguration::TraceGenerator &conf);
|
||||
static bool evaluateAddLengthConverter(const DRAMSysConfiguration::TraceGenerator &conf);
|
||||
static uint64_t evaluateMinAddress(const DRAMSysConfiguration::TraceGeneratorTrafficState &state);
|
||||
static uint64_t evaluateMaxAddress(const DRAMSysConfiguration::TraceGeneratorTrafficState &state);
|
||||
static uint64_t evaluateAddressIncrement(const DRAMSysConfiguration::TraceGeneratorTrafficState &state);
|
||||
|
||||
@@ -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),
|
||||
addLengthConverter(addLengthConverter),
|
||||
payloadEventQueue(this, &TrafficInitiator::peqCallback),
|
||||
setup(setup),
|
||||
maxPendingReadRequests(maxPendingReadRequests), maxPendingWriteRequests(maxPendingWriteRequests)
|
||||
maxPendingReadRequests(maxPendingReadRequests),
|
||||
maxPendingWriteRequests(maxPendingWriteRequests),
|
||||
defaultDataLength(Configuration::getInstance().memSpec->defaultBytesPerBurst),
|
||||
storageEnabled(Configuration::getInstance().storeMode != Configuration::StoreMode::NoStorage)
|
||||
{
|
||||
SC_THREAD(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,9 +57,10 @@ 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:
|
||||
static sc_core::sc_time evaluateGeneratorClk(const DRAMSysConfiguration::TrafficInitiator &conf);
|
||||
@@ -68,7 +69,6 @@ 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);
|
||||
@@ -77,13 +77,14 @@ protected:
|
||||
uint64_t transactionsSent = 0;
|
||||
unsigned int pendingReadRequests = 0;
|
||||
unsigned int pendingWriteRequests = 0;
|
||||
const unsigned int maxPendingReadRequests;
|
||||
const unsigned int maxPendingWriteRequests;
|
||||
|
||||
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,
|
||||
|
||||
@@ -41,13 +41,16 @@
|
||||
#include <string>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
#include <list>
|
||||
#include <chrono>
|
||||
#include <Configuration.h>
|
||||
#include <memory>
|
||||
#include <systemc>
|
||||
|
||||
#include "simulation/DRAMSys.h"
|
||||
#include "TraceSetup.h"
|
||||
#include "TrafficInitiator.h"
|
||||
#include "LengthConverter.h"
|
||||
|
||||
#ifdef RECORDING
|
||||
#include "simulation/DRAMSysRecordable.h"
|
||||
@@ -96,41 +99,42 @@ 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;
|
||||
|
||||
DRAMSysConfiguration::Configuration conf = DRAMSysConfiguration::from_path(simulationJson, resources);
|
||||
|
||||
// Instantiate DRAMSys:
|
||||
DRAMSys *dramSys;
|
||||
std::unique_ptr<DRAMSys> dramSys;
|
||||
|
||||
#ifdef RECORDING
|
||||
if (conf.simConfig.databaseRecording.isValid() && conf.simConfig.databaseRecording.getValue())
|
||||
dramSys = new DRAMSysRecordable("DRAMSys", conf);
|
||||
dramSys = std::unique_ptr<DRAMSys>(new DRAMSysRecordable("DRAMSys", conf));
|
||||
else
|
||||
#endif
|
||||
dramSys = new DRAMSys("DRAMSys", conf);
|
||||
dramSys = std::unique_ptr<DRAMSys>(new DRAMSys("DRAMSys", conf));
|
||||
|
||||
if (!conf.traceSetup.isValid())
|
||||
SC_REPORT_FATAL("sc_main", "No tracesetup section provided.");
|
||||
|
||||
// Instantiate STL Players:
|
||||
TraceSetup *setup = new TraceSetup(conf.traceSetup.getValue(), resources, players);
|
||||
TraceSetup setup(conf.traceSetup.getValue(), 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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -150,11 +154,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;
|
||||
}
|
||||
|
||||
@@ -43,14 +43,22 @@ project(TraceAnalyzer)
|
||||
find_package(Python3 COMPONENTS Development)
|
||||
|
||||
# Add QWT Dependency:
|
||||
find_library(QWT_LIBRARY NAMES "qwt-qt5" "qwt" PATHS "$ENV{QWT_HOME}/lib")
|
||||
find_library(QWT_LIBRARY NAMES "qwt-qt5" "qwt" PATHS
|
||||
"$ENV{QWT_HOME}/lib"
|
||||
"/opt/homebrew/opt/qwt-qt5/lib"
|
||||
)
|
||||
find_path(QWT_INCLUDE_DIRS NAMES "qwt_plot.h" PATHS
|
||||
"/usr/include/qwt-qt5"
|
||||
"/usr/include/qwt"
|
||||
"$ENV{QWT_HOME}/include"
|
||||
"/opt/homebrew/opt/qwt-qt5/include"
|
||||
"/opt/homebrew/opt/qwt-qt5/lib/qwt.framework/Headers"
|
||||
)
|
||||
|
||||
# Add QT Library:
|
||||
if (APPLE)
|
||||
set(Qt5_DIR "/opt/homebrew/opt/qt@5/lib/cmake/Qt5")
|
||||
endif(APPLE)
|
||||
find_package(Qt5 COMPONENTS Core Gui Widgets Sql REQUIRED)
|
||||
set(CMAKE_AUTOMOC ON)
|
||||
set(CMAKE_AUTOUIC ON)
|
||||
|
||||
@@ -69,7 +69,7 @@ void Phase::draw(QPainter *painter, const QwtScaleMap &xMap,
|
||||
if (!line->isCollapsed())
|
||||
{
|
||||
drawPhaseSymbol(span.Begin(), span.End(), line->getYVal(),
|
||||
drawingProperties.drawText, getPhaseSymbol(), painter, xMap, yMap);
|
||||
drawingProperties.drawText, getPhaseSymbol(), painter, xMap, yMap, drawingProperties.textColor);
|
||||
|
||||
if (getGranularity() == Granularity::Bankwise)
|
||||
{
|
||||
@@ -90,7 +90,7 @@ void Phase::draw(QPainter *painter, const QwtScaleMap &xMap,
|
||||
for (auto commandBusLine : drawingProperties.getCommandBusLines())
|
||||
{
|
||||
drawPhaseSymbol(span.Begin(), span.End(), commandBusLine->getYVal(),
|
||||
false, PhaseSymbol::Hexagon, painter, xMap, yMap);
|
||||
false, PhaseSymbol::Hexagon, painter, xMap, yMap, drawingProperties.textColor);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -99,14 +99,14 @@ void Phase::draw(QPainter *painter, const QwtScaleMap &xMap,
|
||||
for (auto dataBusLine : drawingProperties.getDataBusLines())
|
||||
{
|
||||
drawPhaseSymbol(spanOnDataBus->Begin(), spanOnDataBus->End(), dataBusLine->getYVal(),
|
||||
false, PhaseSymbol::Hexagon, painter, xMap, yMap);
|
||||
false, PhaseSymbol::Hexagon, painter, xMap, yMap, drawingProperties.textColor);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Phase::drawPhaseSymbol(traceTime begin, traceTime end, double y,
|
||||
bool drawtext, PhaseSymbol symbol, QPainter *painter, const QwtScaleMap &xMap,
|
||||
const QwtScaleMap &yMap) const
|
||||
const QwtScaleMap &yMap, QColor textColor) const
|
||||
{
|
||||
double yVal = yMap.transform(y);
|
||||
double symbolHeight = yMap.transform(0) - yMap.transform(hexagonHeight);
|
||||
@@ -126,7 +126,7 @@ void Phase::drawPhaseSymbol(traceTime begin, traceTime end, double y,
|
||||
|
||||
if (drawtext)
|
||||
drawText(painter, Name(), QPoint(static_cast<int>(xMap.transform(begin)),
|
||||
static_cast<int>(yVal + symbolHeight / 2)), TextPositioning::bottomRight);
|
||||
static_cast<int>(yVal + symbolHeight / 2)), TextPositioning::bottomRight, textColor);
|
||||
}
|
||||
|
||||
void Phase::drawPhaseDependencies(traceTime begin, traceTime end, double y,
|
||||
|
||||
@@ -99,7 +99,7 @@ protected:
|
||||
virtual QColor getPhaseColor() const = 0;
|
||||
virtual void drawPhaseSymbol(traceTime begin, traceTime end, double y,
|
||||
bool drawtext, PhaseSymbol symbol, QPainter *painter, const QwtScaleMap &xMap,
|
||||
const QwtScaleMap &yMap) const;
|
||||
const QwtScaleMap &yMap, QColor textColor) const;
|
||||
virtual void drawPhaseDependencies(traceTime begin, traceTime end, double y,
|
||||
const TraceDrawingProperties &drawingProperties, QPainter *painter,
|
||||
const QwtScaleMap &xMap, const QwtScaleMap &yMap) const;
|
||||
|
||||
@@ -92,6 +92,7 @@ public:
|
||||
bool drawBorder;
|
||||
DependencyOptions drawDependenciesOption;
|
||||
ColorGrouping colorGrouping;
|
||||
QColor textColor;
|
||||
|
||||
unsigned int numberOfRanks = 1;
|
||||
unsigned int numberOfBankGroups = 1;
|
||||
|
||||
@@ -302,6 +302,7 @@ void TracePlot::setUpDrawingProperties()
|
||||
{
|
||||
drawingProperties.init(navigator->getTracePlotLines(), navigator->getTracePlotLineCache(), this);
|
||||
|
||||
drawingProperties.textColor = palette().text().color();
|
||||
drawingProperties.numberOfRanks = navigator->GeneralTraceInfo().numberOfRanks;
|
||||
drawingProperties.numberOfBankGroups = navigator->GeneralTraceInfo().numberOfBankGroups;
|
||||
drawingProperties.numberOfBanks = navigator->GeneralTraceInfo().numberOfBanks;
|
||||
|
||||
@@ -106,6 +106,7 @@ void TraceScroller::setUpDrawingProperties()
|
||||
{
|
||||
drawingProperties.init(navigator->getTracePlotLines(), navigator->getTracePlotLineCache());
|
||||
|
||||
drawingProperties.textColor = palette().text().color();
|
||||
drawingProperties.numberOfRanks = navigator->GeneralTraceInfo().numberOfRanks;
|
||||
drawingProperties.numberOfBankGroups = navigator->GeneralTraceInfo().numberOfBankGroups;
|
||||
drawingProperties.numberOfBanks = navigator->GeneralTraceInfo().numberOfBanks;
|
||||
|
||||
@@ -67,9 +67,6 @@
|
||||
<property name="autoFillBackground">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="styleSheet">
|
||||
<string notr="true"/>
|
||||
</property>
|
||||
<property name="widgetResizable">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
@@ -78,13 +75,10 @@
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>469</width>
|
||||
<height>599</height>
|
||||
<width>467</width>
|
||||
<height>597</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="styleSheet">
|
||||
<string notr="true">background-color:white</string>
|
||||
</property>
|
||||
</widget>
|
||||
</widget>
|
||||
</widget>
|
||||
|
||||
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
|
||||
|
||||
37
utils/install_mac.sh
Executable file
37
utils/install_mac.sh
Executable file
@@ -0,0 +1,37 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
# Copyright (c) 2018, University of Kaiserslautern
|
||||
# All rights reserved.
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without
|
||||
# modification, are permitted provided that the following conditions are
|
||||
# met:
|
||||
#
|
||||
# 1. Redistributions of source code must retain the above copyright notice,
|
||||
# this list of conditions and the following disclaimer.
|
||||
#
|
||||
# 2. Redistributions in binary form must reproduce the above copyright
|
||||
# notice, this list of conditions and the following disclaimer in the
|
||||
# documentation and/or other materials provided with the distribution.
|
||||
#
|
||||
# 3. Neither the name of the copyright holder nor the names of its
|
||||
# contributors may be used to endorse or promote products derived from
|
||||
# this software without specific prior written permission.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
||||
# TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER
|
||||
# OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
# EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
# PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
# LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
# NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
#
|
||||
# Author: Matthias Jung
|
||||
|
||||
brew install qt@5 qwt-qt5
|
||||
|
||||
echo -e "Done."
|
||||
Reference in New Issue
Block a user