Merge branch 'develop' into 'master'

Command mux with more freedom, small bugfixes.

See merge request ems/astdm/dram.sys!265
This commit is contained in:
Lukas Steiner
2020-08-10 13:40:05 +02:00
29 changed files with 202 additions and 215 deletions

View File

@@ -140,7 +140,7 @@ std::string parseString(json &obj, std::string name)
SC_REPORT_FATAL("Query json", ("Parameter '" + name + "' does not exist.").c_str());
}
void setUpDummy(tlm_generic_payload &payload, Rank rank, Bank bank)
void setUpDummy(tlm_generic_payload &payload, uint64_t payloadID, Rank rank, BankGroup bankgroup, Bank bank)
{
payload.set_address(bank.getStartAddress());
payload.set_command(TLM_READ_COMMAND);
@@ -149,6 +149,6 @@ void setUpDummy(tlm_generic_payload &payload, Rank rank, Bank bank)
payload.set_dmi_allowed(false);
payload.set_byte_enable_length(0);
payload.set_streaming_width(0);
payload.set_extension(new DramExtension(Thread(UINT_MAX), rank, BankGroup(0),
bank, Row(0), Column(0), 0, 0));
payload.set_extension(new DramExtension(Thread(UINT_MAX), rank, bankgroup,
bank, Row(0), Column(0), 0, payloadID));
}

View File

@@ -110,7 +110,7 @@ unsigned int parseUint(nlohmann::json &obj, std::string name);
double parseUdouble(nlohmann::json &obj, std::string name);
std::string parseString(nlohmann::json &obj, std::string name);
void setUpDummy(tlm::tlm_generic_payload &payload, Rank rank = Rank(0), Bank bank = Bank(0));
void setUpDummy(tlm::tlm_generic_payload &payload, uint64_t payloadID, Rank rank = Rank(0), BankGroup bankgroup = BankGroup(0), Bank bank = Bank(0));
#endif // UTILS_H

View File

@@ -44,12 +44,9 @@ BankMachine::BankMachine(SchedulerIF *scheduler, CheckerIF *checker, Bank bank)
bankgroup = BankGroup(bank.ID() / memSpec->banksPerGroup);
}
std::pair<Command, tlm_generic_payload *> BankMachine::getNextCommand()
std::tuple<Command, tlm_generic_payload *, sc_time> BankMachine::getNextCommand()
{
if (sc_time_stamp() == timeToSchedule)
return std::pair<Command, tlm_generic_payload *>(nextCommand, currentPayload);
else
return std::pair<Command, tlm_generic_payload *>(Command::NOP, nullptr);
return std::tuple<Command, tlm_generic_payload *, sc_time>(nextCommand, currentPayload, timeToSchedule);
}
void BankMachine::updateState(Command command)
@@ -124,6 +121,7 @@ BankMachineOpen::BankMachineOpen(SchedulerIF *scheduler, CheckerIF *checker, Ban
sc_time BankMachineOpen::start()
{
timeToSchedule = sc_max_time();
nextCommand = Command::NOP;
if (sleeping)
return timeToSchedule;
@@ -134,30 +132,26 @@ sc_time BankMachineOpen::start()
if (currentState == BmState::Precharged && !blocked) // row miss
{
timeToSchedule = checker->timeToSatisfyConstraints(Command::ACT, rank, bankgroup, bank);
nextCommand = Command::ACT;
timeToSchedule = checker->timeToSatisfyConstraints(nextCommand, rank, bankgroup, bank);
}
else if (currentState == BmState::Activated)
{
if (DramExtension::getRow(currentPayload) == currentRow) // row hit
{
if (currentPayload->get_command() == TLM_READ_COMMAND)
{
timeToSchedule = checker->timeToSatisfyConstraints(Command::RD, rank, bankgroup, bank);
if (currentPayload->get_command() == TLM_READ_COMMAND)
nextCommand = Command::RD;
}
else if (currentPayload->get_command() == TLM_WRITE_COMMAND)
{
timeToSchedule = checker->timeToSatisfyConstraints(Command::WR, rank, bankgroup, bank);
nextCommand = Command::WR;
}
else
SC_REPORT_FATAL("BankMachine", "Wrong TLM command");
timeToSchedule = checker->timeToSatisfyConstraints(nextCommand, rank, bankgroup, bank);
}
else if (!blocked) // row miss
{
timeToSchedule = checker->timeToSatisfyConstraints(Command::PRE, rank, bankgroup, bank);
nextCommand = Command::PRE;
timeToSchedule = checker->timeToSatisfyConstraints(nextCommand, rank, bankgroup, bank);
}
}
return timeToSchedule;
@@ -169,6 +163,7 @@ BankMachineClosed::BankMachineClosed(SchedulerIF *scheduler, CheckerIF *checker,
sc_time BankMachineClosed::start()
{
timeToSchedule = sc_max_time();
nextCommand = Command::NOP;
if (sleeping)
return timeToSchedule;
@@ -179,23 +174,19 @@ sc_time BankMachineClosed::start()
if (currentState == BmState::Precharged && !blocked) // row miss
{
timeToSchedule = checker->timeToSatisfyConstraints(Command::ACT, rank, bankgroup, bank);
nextCommand = Command::ACT;
timeToSchedule = checker->timeToSatisfyConstraints(nextCommand, rank, bankgroup, bank);
}
else if (currentState == BmState::Activated)
{
if (currentPayload->get_command() == TLM_READ_COMMAND)
{
timeToSchedule = checker->timeToSatisfyConstraints(Command::RDA, rank, bankgroup, bank);
nextCommand = Command::RDA;
}
else if (currentPayload->get_command() == TLM_WRITE_COMMAND)
{
timeToSchedule = checker->timeToSatisfyConstraints(Command::WRA, rank, bankgroup, bank);
nextCommand = Command::WRA;
}
else
SC_REPORT_FATAL("BankMachine", "Wrong TLM command");
timeToSchedule = checker->timeToSatisfyConstraints(nextCommand, rank, bankgroup, bank);
}
return timeToSchedule;
}
@@ -206,6 +197,7 @@ BankMachineOpenAdaptive::BankMachineOpenAdaptive(SchedulerIF *scheduler, Checker
sc_time BankMachineOpenAdaptive::start()
{
timeToSchedule = sc_max_time();
nextCommand = Command::NOP;
if (sleeping)
return timeToSchedule;
@@ -216,8 +208,8 @@ sc_time BankMachineOpenAdaptive::start()
if (currentState == BmState::Precharged && !blocked) // row miss
{
timeToSchedule = checker->timeToSatisfyConstraints(Command::ACT, rank, bankgroup, bank);
nextCommand = Command::ACT;
timeToSchedule = checker->timeToSatisfyConstraints(nextCommand, rank, bankgroup, bank);
}
else if (currentState == BmState::Activated)
{
@@ -226,38 +218,27 @@ sc_time BankMachineOpenAdaptive::start()
if (scheduler->hasFurtherRequest(bank) && !scheduler->hasFurtherRowHit(bank, currentRow))
{
if (currentPayload->get_command() == TLM_READ_COMMAND)
{
timeToSchedule = checker->timeToSatisfyConstraints(Command::RDA, rank, bankgroup, bank);
nextCommand = Command::RDA;
}
else if (currentPayload->get_command() == TLM_WRITE_COMMAND)
{
timeToSchedule = checker->timeToSatisfyConstraints(Command::WRA, rank, bankgroup, bank);
nextCommand = Command::WRA;
}
else
SC_REPORT_FATAL("BankMachine", "Wrong TLM command");
}
else
{
if (currentPayload->get_command() == TLM_READ_COMMAND)
{
timeToSchedule = checker->timeToSatisfyConstraints(Command::RD, rank, bankgroup, bank);
nextCommand = Command::RD;
}
else if (currentPayload->get_command() == TLM_WRITE_COMMAND)
{
timeToSchedule = checker->timeToSatisfyConstraints(Command::WR, rank, bankgroup, bank);
nextCommand = Command::WR;
}
else
SC_REPORT_FATAL("BankMachine", "Wrong TLM command");
SC_REPORT_FATAL("BankMachine", "Wrong TLM command");
}
timeToSchedule = checker->timeToSatisfyConstraints(nextCommand, rank, bankgroup, bank);
}
else if (!blocked) // row miss
{
timeToSchedule = checker->timeToSatisfyConstraints(Command::PRE, rank, bankgroup, bank);
nextCommand = Command::PRE;
timeToSchedule = checker->timeToSatisfyConstraints(nextCommand, rank, bankgroup, bank);
}
}
return timeToSchedule;
@@ -269,6 +250,7 @@ BankMachineClosedAdaptive::BankMachineClosedAdaptive(SchedulerIF *scheduler, Che
sc_time BankMachineClosedAdaptive::start()
{
timeToSchedule = sc_max_time();
nextCommand = Command::NOP;
if (sleeping)
return timeToSchedule;
@@ -279,8 +261,8 @@ sc_time BankMachineClosedAdaptive::start()
if (currentState == BmState::Precharged && !blocked) // row miss
{
timeToSchedule = checker->timeToSatisfyConstraints(Command::ACT, rank, bankgroup, bank);
nextCommand = Command::ACT;
timeToSchedule = checker->timeToSatisfyConstraints(nextCommand, rank, bankgroup, bank);
}
else if (currentState == BmState::Activated)
{
@@ -289,38 +271,27 @@ sc_time BankMachineClosedAdaptive::start()
if (scheduler->hasFurtherRowHit(bank, currentRow))
{
if (currentPayload->get_command() == TLM_READ_COMMAND)
{
timeToSchedule = checker->timeToSatisfyConstraints(Command::RD, rank, bankgroup, bank);
nextCommand = Command::RD;
}
else if (currentPayload->get_command() == TLM_WRITE_COMMAND)
{
timeToSchedule = checker->timeToSatisfyConstraints(Command::WR, rank, bankgroup, bank);
nextCommand = Command::WR;
}
else
SC_REPORT_FATAL("BankMachine", "Wrong TLM command");
}
else
{
if (currentPayload->get_command() == TLM_READ_COMMAND)
{
timeToSchedule = checker->timeToSatisfyConstraints(Command::RDA, rank, bankgroup, bank);
nextCommand = Command::RDA;
}
else if (currentPayload->get_command() == TLM_WRITE_COMMAND)
{
timeToSchedule = checker->timeToSatisfyConstraints(Command::WRA, rank, bankgroup, bank);
nextCommand = Command::WRA;
}
else
SC_REPORT_FATAL("BankMachine", "Wrong TLM command");
}
timeToSchedule = checker->timeToSatisfyConstraints(nextCommand, rank, bankgroup, bank);
}
else if (!blocked) // row miss TODO: remove this, can never happen
{
timeToSchedule = checker->timeToSatisfyConstraints(Command::PRE, rank, bankgroup, bank);
nextCommand = Command::PRE;
timeToSchedule = checker->timeToSatisfyConstraints(nextCommand, rank, bankgroup, bank);
SC_REPORT_FATAL("BankMachine", "Should never be reached for this policy");
}
}

View File

@@ -58,7 +58,7 @@ class BankMachine
public:
virtual ~BankMachine() {}
virtual sc_time start() = 0;
std::pair<Command, tlm::tlm_generic_payload *> getNextCommand();
std::tuple<Command, tlm::tlm_generic_payload *, sc_time> getNextCommand();
void updateState(Command);
void block();
@@ -74,7 +74,7 @@ protected:
tlm::tlm_generic_payload *currentPayload = nullptr;
SchedulerIF *scheduler;
CheckerIF *checker;
Command nextCommand;
Command nextCommand = Command::NOP;
BmState currentState = BmState::Precharged;
Row currentRow;
sc_time timeToSchedule = sc_max_time();

View File

@@ -239,29 +239,27 @@ void Controller::controllerMethod()
it->start();
// (5) Choose one request and send it to DRAM
std::pair<Command, tlm_generic_payload *> commandPair;
std::vector<std::pair<Command, tlm_generic_payload *>> readyCommands;
// (5.1) Check for power-down commands (PDEA/PDEP/SREFEN or PDXA/PDXP/SREFEX)
std::tuple<Command, tlm_generic_payload *, sc_time> commandTuple;
std::list<std::tuple<Command, tlm_generic_payload *, sc_time>> readyCommands;
for (unsigned rankID = 0; rankID < memSpec->numberOfRanks; rankID++)
{
commandPair = powerDownManagers[rankID]->getNextCommand();
if (commandPair.second != nullptr)
readyCommands.push_back(commandPair);
// (5.1) Check for power-down commands (PDEA/PDEP/SREFEN or PDXA/PDXP/SREFEX)
commandTuple = powerDownManagers[rankID]->getNextCommand();
if (std::get<0>(commandTuple) != Command::NOP)
readyCommands.push_back(commandTuple);
else
{
// (5.2) Check for refresh commands (PREA/PRE or REFA/REFB)
commandPair = refreshManagers[rankID]->getNextCommand();
if (commandPair.second != nullptr)
readyCommands.push_back(commandPair);
else
commandTuple = refreshManagers[rankID]->getNextCommand();
if (std::get<0>(commandTuple) != Command::NOP)
readyCommands.push_back(commandTuple);
// (5.3) Check for bank commands (PRE, ACT, RD/RDA or WR/WRA)
for (auto it : bankMachinesOnRank[rankID])
{
// (5.3) Check for bank commands (PRE, ACT, RD/RDA or WR/WRA)
for (auto it : bankMachinesOnRank[rankID])
{
commandPair = it->getNextCommand();
if (commandPair.second != nullptr)
readyCommands.push_back(commandPair);
}
commandTuple = it->getNextCommand();
if (std::get<0>(commandTuple) != Command::NOP)
readyCommands.push_back(commandTuple);
}
}
}
@@ -269,29 +267,29 @@ void Controller::controllerMethod()
bool readyCmdBlocked = false;
if (!readyCommands.empty())
{
commandPair = cmdMux->selectCommand(readyCommands);
if (commandPair.second != nullptr) // can happen with FIFO strict
commandTuple = cmdMux->selectCommand(readyCommands);
if (std::get<0>(commandTuple) != Command::NOP) // can happen with FIFO strict
{
Rank rank = DramExtension::getRank(commandPair.second);
BankGroup bankgroup = DramExtension::getBankGroup(commandPair.second);
Bank bank = DramExtension::getBank(commandPair.second);
Rank rank = DramExtension::getRank(std::get<1>(commandTuple));
BankGroup bankgroup = DramExtension::getBankGroup(std::get<1>(commandTuple));
Bank bank = DramExtension::getBank(std::get<1>(commandTuple));
if (isRankCommand(commandPair.first))
if (isRankCommand(std::get<0>(commandTuple)))
{
for (auto it : bankMachinesOnRank[rank.ID()])
it->updateState(commandPair.first);
it->updateState(std::get<0>(commandTuple));
}
else
bankMachines[bank.ID()]->updateState(commandPair.first);
bankMachines[bank.ID()]->updateState(std::get<0>(commandTuple));
refreshManagers[rank.ID()]->updateState(commandPair.first, commandPair.second);
powerDownManagers[rank.ID()]->updateState(commandPair.first);
checker->insert(commandPair.first, rank, bankgroup, bank);
refreshManagers[rank.ID()]->updateState(std::get<0>(commandTuple));
powerDownManagers[rank.ID()]->updateState(std::get<0>(commandTuple));
checker->insert(std::get<0>(commandTuple), rank, bankgroup, bank);
if (isCasCommand(commandPair.first))
if (isCasCommand(std::get<0>(commandTuple)))
{
scheduler->removeRequest(commandPair.second);
respQueue->insertPayload(commandPair.second, memSpec->getIntervalOnDataStrobe(commandPair.first).end);
scheduler->removeRequest(std::get<1>(commandTuple));
respQueue->insertPayload(std::get<1>(commandTuple), memSpec->getIntervalOnDataStrobe(std::get<0>(commandTuple)).end);
sc_time triggerTime = respQueue->getTriggerTime();
if (triggerTime != sc_max_time())
@@ -302,7 +300,7 @@ void Controller::controllerMethod()
if (ranksNumberOfPayloads[rank.ID()] == 0)
powerDownManagers[rank.ID()]->triggerEntry();
sendToDram(commandPair.first, commandPair.second);
sendToDram(std::get<0>(commandTuple), std::get<1>(commandTuple));
}
else
readyCmdBlocked = true;

View File

@@ -65,9 +65,9 @@ public:
virtual ~Controller();
protected:
virtual tlm::tlm_sync_enum nb_transport_fw(tlm::tlm_generic_payload &, tlm::tlm_phase &, sc_time &);
virtual tlm::tlm_sync_enum nb_transport_bw(tlm::tlm_generic_payload &, tlm::tlm_phase &, sc_time &);
virtual unsigned int transport_dbg(tlm::tlm_generic_payload &);
virtual tlm::tlm_sync_enum nb_transport_fw(tlm::tlm_generic_payload &, tlm::tlm_phase &, sc_time &) override;
virtual tlm::tlm_sync_enum nb_transport_bw(tlm::tlm_generic_payload &, tlm::tlm_phase &, sc_time &) override;
virtual unsigned int transport_dbg(tlm::tlm_generic_payload &) override;
virtual void sendToFrontend(tlm::tlm_generic_payload *, tlm::tlm_phase);
virtual void sendToDram(Command, tlm::tlm_generic_payload *);

View File

@@ -60,35 +60,35 @@ public:
/ Configuration::getInstance().memSpec->dataRate
* Configuration::getInstance().memSpec->tCK;
double bandwidth = (activeTime / sc_time_stamp() * 100);
double bandwidthWoIdle = ((activeTime) / (sc_time_stamp() - idleTimeCollector.getIdleTime()) * 100);
double bandwidth = activeTime / sc_time_stamp();
double bandwidthWoIdle = activeTime / (sc_time_stamp() - idleTimeCollector.getIdleTime());
double maxBandwidth = (
// fCK in Mhz e.g. 800 [MHz]:
(1000000 / Configuration::getInstance().memSpec->tCK.to_double())
// fCK in GHz e.g. 1 [GHz] (tCK in ps):
(1000 / Configuration::getInstance().memSpec->tCK.to_double())
// DataRate e.g. 2
* Configuration::getInstance().memSpec->dataRate
// BusWidth e.g. 8 or 64
* Configuration::getInstance().memSpec->bitWidth
// Number of devices on a DIMM e.g. 8
* Configuration::getInstance().memSpec->numberOfDevicesOnDIMM ) / ( 1024 );
* Configuration::getInstance().memSpec->numberOfDevicesOnDIMM );
std::cout << name() << std::string(" Total Time: ")
<< sc_time_stamp().to_string()
<< std::endl;
std::cout << name() << std::string(" AVG BW: ")
<< std::fixed << std::setprecision(2)
<< ((bandwidth / 100) * maxBandwidth)
<< " Gibit/s (" << bandwidth << " %)"
<< (bandwidth * maxBandwidth)
<< " Gb/s (" << (bandwidth * 100) << " %)"
<< std::endl;
std::cout << name() << std::string(" AVG BW\\IDLE: ")
<< std::fixed << std::setprecision(2)
<< ((bandwidthWoIdle / 100) * maxBandwidth)
<< " Gibit/s (" << bandwidthWoIdle << " %)"
<< (bandwidthWoIdle * maxBandwidth)
<< " Gb/s (" << (bandwidthWoIdle * 100) << " %)"
<< endl;
std::cout << name() << std::string(" MAX BW: ")
<< std::fixed << std::setprecision(2)
<< maxBandwidth << " Gibit/s"
<< maxBandwidth << " Gb/s"
<< std::endl;
}

View File

@@ -44,17 +44,17 @@ public:
ControllerRecordable(sc_module_name name, TlmRecorder *tlmRecorder) :
Controller(name), tlmRecorder(tlmRecorder) {}
protected:
virtual tlm::tlm_sync_enum nb_transport_fw(tlm::tlm_generic_payload &trans,
tlm::tlm_phase &phase, sc_time &delay) override;
virtual tlm::tlm_sync_enum nb_transport_bw(tlm::tlm_generic_payload &trans,
tlm::tlm_phase &phase, sc_time &delay) override;
virtual void sendToFrontend(tlm::tlm_generic_payload *, tlm::tlm_phase) override;
virtual void sendToDram(Command, tlm::tlm_generic_payload *) override;
private:
tlm::tlm_sync_enum nb_transport_fw(tlm::tlm_generic_payload &trans,
tlm::tlm_phase &phase, sc_time &delay) override;
tlm::tlm_sync_enum nb_transport_bw(tlm::tlm_generic_payload &trans,
tlm::tlm_phase &phase, sc_time &delay) override;
void sendToFrontend(tlm::tlm_generic_payload *, tlm::tlm_phase) override;
void sendToDram(Command, tlm::tlm_generic_payload *) override;
void recordPhase(tlm::tlm_generic_payload &trans, tlm::tlm_phase phase, sc_time delay);
TlmRecorder *tlmRecorder;
};

View File

@@ -35,17 +35,18 @@
#ifndef CMDMUXIF_H
#define CMDMUXIF_H
#include <systemc.h>
#include <tlm.h>
#include <utility>
#include <vector>
#include <list>
#include "../Command.h"
class CmdMuxIF
{
public:
virtual ~CmdMuxIF() {}
virtual std::pair<Command, tlm::tlm_generic_payload *>
selectCommand(std::vector<std::pair<Command, tlm::tlm_generic_payload *>> &) = 0;
virtual std::tuple<Command, tlm::tlm_generic_payload *, sc_time>
selectCommand(std::list<std::tuple<Command, tlm::tlm_generic_payload *, sc_time>> &) = 0;
};
#endif // CMDMUXIF_H

View File

@@ -38,23 +38,30 @@
using namespace tlm;
std::pair<Command, tlm_generic_payload *>
CmdMuxOldest::selectCommand(std::vector<std::pair<Command, tlm_generic_payload *>> &readyCommands)
{
auto it = readyCommands.begin();
auto result = it;
unsigned lastPayloadID = DramExtension::getPayloadID(it->second);
it++;
std::tuple<Command, tlm_generic_payload *, sc_time>
CmdMuxOldest::selectCommand(std::list<std::tuple<Command, tlm_generic_payload *, sc_time>> &readyCommands)
{
readyCommands.remove_if([](std::tuple<Command, tlm_generic_payload *, sc_time> element){return std::get<2>(element) != sc_time_stamp();});
while (it != readyCommands.end())
if (!readyCommands.empty())
{
unsigned newPayloadID = DramExtension::getPayloadID(it->second);
if (newPayloadID < lastPayloadID)
{
lastPayloadID = newPayloadID;
result = it;
}
auto it = readyCommands.begin();
auto result = it;
uint64_t lastPayloadID = DramExtension::getPayloadID(std::get<1>(*it));
it++;
while (it != readyCommands.end())
{
uint64_t newPayloadID = DramExtension::getPayloadID(std::get<1>(*it));
if (newPayloadID < lastPayloadID)
{
lastPayloadID = newPayloadID;
result = it;
}
it++;
}
return *result;
}
return *result;
else
return std::tuple<Command, tlm_generic_payload *, sc_time>(Command::NOP, nullptr, sc_max_time());
}

View File

@@ -40,8 +40,8 @@
class CmdMuxOldest : public CmdMuxIF
{
public:
std::pair<Command, tlm::tlm_generic_payload *>
selectCommand(std::vector<std::pair<Command, tlm::tlm_generic_payload *>> &);
std::tuple<Command, tlm::tlm_generic_payload *, sc_time>
selectCommand(std::list<std::tuple<Command, tlm::tlm_generic_payload *, sc_time>> &);
};
#endif // CMDMUXOLDEST_H

View File

@@ -38,24 +38,29 @@
using namespace tlm;
std::pair<Command, tlm_generic_payload *>
CmdMuxStrict::selectCommand(std::vector<std::pair<Command, tlm_generic_payload *>> &readyCommands)
std::tuple<Command, tlm_generic_payload *, sc_time>
CmdMuxStrict::selectCommand(std::list<std::tuple<Command, tlm_generic_payload *, sc_time>> &readyCommands)
{
for (auto it : readyCommands)
readyCommands.remove_if([](std::tuple<Command, tlm_generic_payload *, sc_time> element){return std::get<2>(element) != sc_time_stamp();});
if (!readyCommands.empty())
{
if (isCasCommand(it.first))
for (auto it : readyCommands)
{
if (DramExtension::getPayloadID(it.second) == nextPayloadID)
if (isCasCommand(std::get<0>(it)))
{
nextPayloadID++;
return it;
if (DramExtension::getPayloadID(std::get<1>(it)) == nextPayloadID)
{
nextPayloadID++;
return it;
}
}
}
for (auto it : readyCommands)
{
if (isRasCommand(std::get<0>(it)))
return it;
}
}
for (auto it : readyCommands)
{
if (isRasCommand(it.first))
return it;
}
return std::pair<Command, tlm_generic_payload *>(Command::NOP, nullptr);
return std::tuple<Command, tlm_generic_payload *, sc_time>(Command::NOP, nullptr, sc_max_time());
}

View File

@@ -40,8 +40,8 @@
class CmdMuxStrict : public CmdMuxIF
{
public:
std::pair<Command, tlm::tlm_generic_payload *>
selectCommand(std::vector<std::pair<Command, tlm::tlm_generic_payload *>> &);
std::tuple<Command, tlm::tlm_generic_payload *, sc_time>
selectCommand(std::list<std::tuple<Command, tlm::tlm_generic_payload *, sc_time>> &);
private:
uint64_t nextPayloadID = 0;

View File

@@ -36,9 +36,9 @@
using namespace tlm;
std::pair<Command, tlm_generic_payload *> PowerDownManagerDummy::getNextCommand()
std::tuple<Command, tlm_generic_payload *, sc_time> PowerDownManagerDummy::getNextCommand()
{
return std::pair<Command, tlm_generic_payload *>(Command::NOP, nullptr);
return std::tuple<Command, tlm_generic_payload *, sc_time>(Command::NOP, nullptr, sc_max_time());
}
sc_time PowerDownManagerDummy::start()

View File

@@ -46,7 +46,7 @@ public:
virtual void triggerExit() override {}
virtual void triggerInterruption() override {}
virtual std::pair<Command, tlm::tlm_generic_payload *> getNextCommand() override;
virtual std::tuple<Command, tlm::tlm_generic_payload *, sc_time> getNextCommand() override;
virtual void updateState(Command) override {}
virtual sc_time start() override;
};

View File

@@ -49,7 +49,7 @@ public:
virtual void triggerExit() = 0;
virtual void triggerInterruption() = 0;
virtual std::pair<Command, tlm::tlm_generic_payload *> getNextCommand() = 0;
virtual std::tuple<Command, tlm::tlm_generic_payload *, sc_time> getNextCommand() = 0;
virtual void updateState(Command) = 0;
virtual sc_time start() = 0;
};

View File

@@ -40,7 +40,7 @@ using namespace tlm;
PowerDownManagerStaggered::PowerDownManagerStaggered(Rank rank, CheckerIF *checker)
: rank(rank), checker(checker)
{
setUpDummy(powerDownPayload, rank);
setUpDummy(powerDownPayload, UINT64_MAX, rank);
}
void PowerDownManagerStaggered::triggerEntry()
@@ -69,17 +69,15 @@ void PowerDownManagerStaggered::triggerInterruption()
exitTriggered = true;
}
std::pair<Command, tlm_generic_payload *> PowerDownManagerStaggered::getNextCommand()
std::tuple<Command, tlm_generic_payload *, sc_time> PowerDownManagerStaggered::getNextCommand()
{
if (sc_time_stamp() == timeToSchedule)
return std::pair<Command, tlm_generic_payload *>(nextCommand, &powerDownPayload);
else
return std::pair<Command, tlm_generic_payload *>(Command::NOP, nullptr);
return std::tuple<Command, tlm_generic_payload *, sc_time>(nextCommand, &powerDownPayload, timeToSchedule);
}
sc_time PowerDownManagerStaggered::start()
{
timeToSchedule = sc_max_time();
nextCommand = Command::NOP;
if (exitTriggered)
{

View File

@@ -48,7 +48,7 @@ public:
virtual void triggerExit() override;
virtual void triggerInterruption() override;
virtual std::pair<Command, tlm::tlm_generic_payload *> getNextCommand() override;
virtual std::tuple<Command, tlm::tlm_generic_payload *, sc_time> getNextCommand() override;
virtual void updateState(Command) override;
virtual sc_time start() override;
@@ -59,7 +59,7 @@ private:
CheckerIF *checker;
sc_time timeToSchedule = sc_max_time();
Command nextCommand;
Command nextCommand = Command::NOP;
bool controllerIdle = true;
bool entryTriggered = true;

View File

@@ -50,27 +50,26 @@ RefreshManagerBankwise::RefreshManagerBankwise(std::vector<BankMachine *> &bankM
refreshPayloads = std::vector<tlm_generic_payload>(memSpec->banksPerRank);
for (unsigned bankID = 0; bankID < memSpec->banksPerRank; bankID++)
{
setUpDummy(refreshPayloads[bankID], rank, bankMachines[bankID]->getBank());
setUpDummy(refreshPayloads[bankID], 0, rank, bankMachines[bankID]->getBankGroup(), bankMachines[bankID]->getBank());
allBankMachines.push_back(bankMachines[bankID]);
}
remainingBankMachines = allBankMachines;
currentBankMachine = *remainingBankMachines.begin();
maxPostponed = config.refreshMaxPostponed * memSpec->banksPerRank;
maxPulledin = -(config.refreshMaxPulledin * memSpec->banksPerRank);
}
std::pair<Command, tlm_generic_payload *> RefreshManagerBankwise::getNextCommand()
std::tuple<Command, tlm_generic_payload *, sc_time> RefreshManagerBankwise::getNextCommand()
{
if (sc_time_stamp() == timeToSchedule)
return std::pair<Command, tlm_generic_payload *>
(nextCommand, &refreshPayloads[currentBankMachine->getBank().ID() % memSpec->banksPerRank]);
else
return std::pair<Command, tlm_generic_payload *>(Command::NOP, nullptr);
return std::tuple<Command, tlm_generic_payload *, sc_time>
(nextCommand, &refreshPayloads[currentBankMachine->getBank().ID() % memSpec->banksPerRank], timeToSchedule);
}
sc_time RefreshManagerBankwise::start()
{
timeToSchedule = sc_max_time();
nextCommand = Command::NOP;
if (sc_time_stamp() >= timeForNextTrigger)
{
@@ -86,13 +85,14 @@ sc_time RefreshManagerBankwise::start()
if (state == RmState::Regular)
{
currentIterator = remainingBankMachines.begin();
currentBankMachine = *remainingBankMachines.begin();
bool forcedRefresh = (flexibilityCounter == maxPostponed);
bool allBanksBusy = true;
if (!skipSelection)
{
currentIterator = remainingBankMachines.begin();
currentBankMachine = *remainingBankMachines.begin();
for (auto it = remainingBankMachines.begin(); it != remainingBankMachines.end(); it++)
{
if ((*it)->isIdle())
@@ -168,7 +168,7 @@ sc_time RefreshManagerBankwise::start()
return timeForNextTrigger;
}
void RefreshManagerBankwise::updateState(Command command, tlm_generic_payload *payload)
void RefreshManagerBankwise::updateState(Command command)
{
switch (command)
{

View File

@@ -48,9 +48,9 @@ class RefreshManagerBankwise final : public RefreshManagerIF
public:
RefreshManagerBankwise(std::vector<BankMachine *> &, PowerDownManagerIF *, Rank, CheckerIF *);
virtual std::pair<Command, tlm::tlm_generic_payload *> getNextCommand() override;
virtual std::tuple<Command, tlm::tlm_generic_payload *, sc_time> getNextCommand() override;
virtual sc_time start() override;
virtual void updateState(Command, tlm::tlm_generic_payload *) override;
virtual void updateState(Command) override;
private:
enum class RmState {Regular, Pulledin} state = RmState::Regular;
@@ -62,7 +62,7 @@ private:
sc_time timeToSchedule = sc_max_time();
Rank rank;
CheckerIF *checker;
Command nextCommand;
Command nextCommand = Command::NOP;
std::list<BankMachine *> remainingBankMachines;
std::list<BankMachine *> allBankMachines;

View File

@@ -36,9 +36,9 @@
using namespace tlm;
std::pair<Command, tlm_generic_payload *> RefreshManagerDummy::getNextCommand()
std::tuple<Command, tlm_generic_payload *, sc_time> RefreshManagerDummy::getNextCommand()
{
return std::pair<Command, tlm_generic_payload *>(Command::NOP, nullptr);
return std::tuple<Command, tlm_generic_payload *, sc_time>(Command::NOP, nullptr, sc_max_time());
}
sc_time RefreshManagerDummy::start()

View File

@@ -44,9 +44,9 @@
class RefreshManagerDummy final : public RefreshManagerIF
{
public:
virtual std::pair<Command, tlm::tlm_generic_payload *> getNextCommand() override;
virtual std::tuple<Command, tlm::tlm_generic_payload *, sc_time> getNextCommand() override;
virtual sc_time start() override;
virtual void updateState(Command, tlm::tlm_generic_payload *) override {}
virtual void updateState(Command) override {}
};
#endif // REFRESHMANAGERDUMMY_H

View File

@@ -45,9 +45,9 @@ class RefreshManagerIF
public:
virtual ~RefreshManagerIF() {}
virtual std::pair<Command, tlm::tlm_generic_payload *> getNextCommand() = 0;
virtual std::tuple<Command, tlm::tlm_generic_payload *, sc_time> getNextCommand() = 0;
virtual sc_time start() = 0;
virtual void updateState(Command, tlm::tlm_generic_payload *) = 0;
virtual void updateState(Command) = 0;
};
#endif // REFRESHMANAGERIF_H

View File

@@ -46,23 +46,21 @@ RefreshManagerRankwise::RefreshManagerRankwise(std::vector<BankMachine *> &bankM
Configuration &config = Configuration::getInstance();
memSpec = config.memSpec;
timeForNextTrigger = memSpec->getRefreshIntervalAB();
setUpDummy(refreshPayload, rank);
setUpDummy(refreshPayload, 0, rank);
maxPostponed = config.refreshMaxPostponed;
maxPulledin = -config.refreshMaxPulledin;
}
std::pair<Command, tlm_generic_payload *> RefreshManagerRankwise::getNextCommand()
std::tuple<Command, tlm_generic_payload *, sc_time> RefreshManagerRankwise::getNextCommand()
{
if (sc_time_stamp() == timeToSchedule)
return std::pair<Command, tlm_generic_payload *>(nextCommand, &refreshPayload);
else
return std::pair<Command, tlm_generic_payload *>(Command::NOP, nullptr);
return std::tuple<Command, tlm_generic_payload *, sc_time>(nextCommand, &refreshPayload, timeToSchedule);
}
sc_time RefreshManagerRankwise::start()
{
timeToSchedule = sc_max_time();
nextCommand = Command::NOP;
if (sc_time_stamp() >= timeForNextTrigger)
{
@@ -130,7 +128,7 @@ sc_time RefreshManagerRankwise::start()
}
else
{
// nextCommand stays Command::REFA
nextCommand = Command::REFA;
timeToSchedule = checker->timeToSatisfyConstraints(nextCommand, rank, BankGroup(0), Bank(0));
return timeToSchedule;
}
@@ -140,7 +138,7 @@ sc_time RefreshManagerRankwise::start()
return timeForNextTrigger;
}
void RefreshManagerRankwise::updateState(Command command, tlm_generic_payload *)
void RefreshManagerRankwise::updateState(Command command)
{
switch (command)
{

View File

@@ -46,9 +46,9 @@ class RefreshManagerRankwise final : public RefreshManagerIF
public:
RefreshManagerRankwise(std::vector<BankMachine *> &, PowerDownManagerIF *, Rank, CheckerIF *);
virtual std::pair<Command, tlm::tlm_generic_payload *> getNextCommand() override;
virtual std::tuple<Command, tlm::tlm_generic_payload *, sc_time> getNextCommand() override;
virtual sc_time start() override;
virtual void updateState(Command, tlm::tlm_generic_payload *) override;
virtual void updateState(Command) override;
private:
enum class RmState {Regular, Pulledin} state = RmState::Regular;
@@ -60,7 +60,7 @@ private:
sc_time timeToSchedule = sc_max_time();
Rank rank;
CheckerIF *checker;
Command nextCommand;
Command nextCommand = Command::NOP;
unsigned activatedBanks = 0;

View File

@@ -82,7 +82,7 @@ private:
tlm::tlm_sync_enum nb_transport_bw(int channelId, tlm::tlm_generic_payload &payload,
tlm::tlm_phase &phase, sc_time &bwDelay);
virtual unsigned int transport_dbg(int /*id*/, tlm::tlm_generic_payload &trans);
unsigned int transport_dbg(int /*id*/, tlm::tlm_generic_payload &trans);
void peqCallback(tlm::tlm_generic_payload &payload, const tlm::tlm_phase &phase);

View File

@@ -143,19 +143,27 @@ DRAMSys::~DRAMSys()
void DRAMSys::logo()
{
#define REDTXT(s) std::string("\033[0;31m" + std::string(s) + "\033[0m")
#define BOLDBLUETXT(s) std::string("\033[1;34m" + std::string(s) + "\033[0m")
std::cout << std::endl;
std::cout << REDTXT(" |||") << std::endl;
std::cout << REDTXT(" +---+ Microelectronic Systems") << std::endl;
std::cout << REDTXT("=| |= Design Research Group") << std::endl;
std::cout << REDTXT("=| |= ") << BOLDBLUETXT("Technische Universität Kaiserslautern")
#define GREENTXT(s) std::string(("\u001b[38;5;28m"+std::string((s))+"\033[0m"))
#define DGREENTXT(s) std::string(("\u001b[38;5;22m"+std::string((s))+"\033[0m"))
#define LGREENTXT(s) std::string(("\u001b[38;5;82m"+std::string((s))+"\033[0m"))
#define BLACKTXT(s) std::string(("\u001b[38;5;232m"+std::string((s))+"\033[0m"))
#define BOLDTXT(s) std::string(("\033[1;37m"+std::string((s))+"\033[0m"))
cout << std::endl
<< BLACKTXT("■ ■ ")<< DGREENTXT("")
<< BOLDTXT("DRAMSys4.0, Copyright (c) 2020")
<< std::endl
<< BLACKTXT("") << DGREENTXT("") << GREENTXT("")
<< "Technische Universitaet Kaiserslautern,"
<< std::endl
<< DGREENTXT("") << GREENTXT("") << LGREENTXT("" )
<< "Fraunhofer IESE"
<< std::endl
<< std::endl;
std::cout << REDTXT(" +---+ ") << std::endl;
std::cout << REDTXT(" ||| ") << "DRAMSys4.0" << std::endl;
std::cout << std::endl;
#undef REDTXT
#undef BOLDBLUETXT
#undef GREENTXT
#undef DGREENTXT
#undef LGREENTXT
#undef BLACKTXT
#undef BOLDTXT
}
void DRAMSys::setupDebugManager(const std::string &traceName __attribute__((unused)))

View File

@@ -48,8 +48,9 @@ class DramRecordable final : public BaseDram
public:
DramRecordable(sc_module_name, TlmRecorder *);
SC_HAS_PROCESS(DramRecordable);
virtual ~DramRecordable() {}
virtual void reportPower();
virtual void reportPower() override;
private:
virtual tlm::tlm_sync_enum nb_transport_fw(tlm::tlm_generic_payload &payload,

View File

@@ -31,6 +31,18 @@ A UML diagram of the software architecture is presented below; different compone
<img src="DRAMSys/docs/images/dramsys_uml.png" alt="UML" />
## Trace Analyzer Consulting and Custom-Tailored Modifications
To provide better analysis capabilities for DRAM subsystem design space exploration than the usual performance-related outputs to the console, DRAMSys offers the Trace Analyzer.
All requests, responses and DRAM commands can be recorded in an SQLite trace database during a simulation and visualized with the tool afterwards. An evaluation of the trace databases can be performed with the powerful Python interface of the Trace Analyzer. Different metrics are described as SQL statements and formulas in Python, which can be customized or extended without recompilation.
The Trace Analyzer's main window is shown below.
If you are interested in the database recording feature and the Trace Analyzer, if you need support on how to setup DRAMSys in a virtual platform of your company, or if you require custom modifications of the simulator please contact [Matthias Jung](mailto:matthias.jung@iese.fraunhofer.de).
![Trace Analyzer Main Window](DRAMSys/docs/images/traceanalyzer.png)
## Basic Setup
Start using DRAMSys by cloning the repository.
@@ -204,7 +216,7 @@ The content of [ddr3.json](DRAMSys/library/resources/configs/simulator/ddr3.json
}
```
- *SimulationName* (boolean)
- *SimulationName* (string)
- Give the name of the simulation for distinguishing from other simulations.
- *Debug* (boolean)
- true: enables debug output on console (only supported by a debug build)
@@ -342,7 +354,7 @@ An example follows.
## DRAMSys with Thermal Simulation
The thermal simulation is performed by a **3D-ICE** [8] server accessed through the network. Therefore users interested in thermal simulation during their DRAMSys simulations need to make sure they have a 3D-ICE server up and running before starting. For more information about 3D-ICE visit the [official website](https://www.epfl.ch/labs/esl/open-source-software-projects/3d-ice/).
The thermal simulation is performed by a **3D-ICE** [8] server accessed through the network. Therefore users interested in thermal simulation during their DRAMSys simulations need to make sure they have a 3D-ICE server up and running before starting. For more information about 3D-ICE visit the [official website](https://www.epfl.ch/labs/esl/open-source-software-projects/3d-ice/). An example video that visualizes the results of a thermal simulation is provided on [Youtube](https://www.youtube.com/watch?v=Eacsq71hHtY).
#### Installing 3D-ICE
@@ -506,18 +518,6 @@ The content of [config.json](DRAMSys/library/resources/configs/thermalsim/config
- true: generate power map files during thermal simulation
- false: do not generate power map files during thermal simulation
## Trace Analyzer Consulting and Custom-Tailored Modifications
To provide better analysis capabilities for DRAM subsystem design space exploration than the usual performance-related outputs to the console, DRAMSys offers the Trace Analyzer.
All requests, responses and DRAM commands can be recorded in an SQLite trace database during a simulation and visualized with the tool afterwards. An evaluation of the trace databases can be performed with the powerful Python interface of the Trace Analyzer. Different metrics are described as SQL statements and formulas in Python, which can be customized or extended without recompilation.
The Trace Analyzer's main window is shown below.
If you are interested in the database recording feature and the Trace Analyzer, if you need support on how to setup DRAMSys in a virtual platform of your company, or if you require custom modifications of the simulator please contact [Matthias Jung](mailto:matthias.jung@iese.fraunhofer.de).
![Trace Analyzer Main Window](DRAMSys/docs/images/traceanalyzer.png)
## Acknowledgements
The development of DRAMSys was supported by the German Research Foundation (DFG) as part of the priority program [Dependable Embedded Systems SPP1500](http://spp1500.itec.kit.edu) and the DFG grant no. [WE2442/10-1](https://www.uni-kl.de/en/3d-dram/). Furthermore, it was supported within the Fraunhofer and DFG cooperation program (grant no. [WE2442/14-1](https://www.iese.fraunhofer.de/en/innovation_trends/autonomous-systems/memtonomy.html)) and by the [Fraunhofer High Performance Center for Simulation- and Software-Based Innovation](https://www.leistungszentrum-simulation-software.de/en.html). Special thanks go to all listed contributors for their work and commitment during seven years of development.