diff --git a/dram/resources/configs/memspecs/MatzesWideIO.xml b/dram/resources/configs/memspecs/MatzesWideIO.xml
index 79ff68ba..12f75921 100644
--- a/dram/resources/configs/memspecs/MatzesWideIO.xml
+++ b/dram/resources/configs/memspecs/MatzesWideIO.xml
@@ -32,7 +32,7 @@
-
+
diff --git a/dram/src/core/ControllerCore.cpp b/dram/src/core/ControllerCore.cpp
index a5961cb3..28067b2c 100644
--- a/dram/src/core/ControllerCore.cpp
+++ b/dram/src/core/ControllerCore.cpp
@@ -156,22 +156,6 @@ bool ControllerCore::isBusy(sc_time time, Bank bank)
}
-BankGroup ControllerCore::getBankGroup(Bank bank) const
-{
- static std::map bankgroups;
- if (bankgroups.size() == 0)
- {
- SC_ASSERT_(config.NumberOfBanks % config.NumberOfBankGroups == 0, "Number of banks must be a multiple of number of bankgroups");
-
- for (unsigned int bank = 0; bank < config.NumberOfBanks; bank++)
- {
- unsigned int group = bank / config.NumberOfBankGroups;
- bankgroups.insert(std::pair(Bank(bank), BankGroup(group)));
- }
- }
- return bankgroups.at(bank);
-}
-
const std::vector& ControllerCore::getBanks() const
{
static std::vector banks;
diff --git a/dram/src/core/ControllerCore.h b/dram/src/core/ControllerCore.h
index 605a0b2b..0e3d7d19 100644
--- a/dram/src/core/ControllerCore.h
+++ b/dram/src/core/ControllerCore.h
@@ -37,8 +37,8 @@ public:
void saveState();
void resetState();
- BankGroup getBankGroup(Bank bank) const;
- const std::vector& getBanks() const;
+
+ const std::vector& getBanks() const;//TODO put in config?
void send(const CommandSchedule& schedule, tlm::tlm_generic_payload& payload) const;
ICommandChecker& getCommandChecker(Command command);
diff --git a/dram/src/core/ControllerState.cpp b/dram/src/core/ControllerState.cpp
index 11ade252..d9848d82 100644
--- a/dram/src/core/ControllerState.cpp
+++ b/dram/src/core/ControllerState.cpp
@@ -68,7 +68,7 @@ void ControllerState::change(const ScheduledCommand& scheduledCommand)
break;
case Command::Activate:
bankStates.openRowInRowBuffer(scheduledCommand.getBank(), scheduledCommand.getRow());
- lastActivates.emplace(scheduledCommand.getStart());
+ lastActivates.emplace(scheduledCommand.getStart(), scheduledCommand.getBank());
break;
case Command::Precharge:
diff --git a/dram/src/core/ControllerState.h b/dram/src/core/ControllerState.h
index 76899b44..4a896cad 100644
--- a/dram/src/core/ControllerState.h
+++ b/dram/src/core/ControllerState.h
@@ -44,7 +44,7 @@ public:
std::map > lastCommandsOnBus;
Slots bus;
std::list lastDataStrobeCommands;
- std::set lastActivates;
+ std::map lastActivates;
private:
Configuration* config;
diff --git a/dram/src/core/configuration/MemSpecLoader.cpp b/dram/src/core/configuration/MemSpecLoader.cpp
index f43fe809..b56d3674 100644
--- a/dram/src/core/configuration/MemSpecLoader.cpp
+++ b/dram/src/core/configuration/MemSpecLoader.cpp
@@ -57,7 +57,50 @@ void MemSpecLoader::loadConfig(Configuration& config, XMLElement* memspec)
void MemSpecLoader::loadDDR4(Configuration& config, XMLElement* memspec)
{
+ //MemSpecification
+ XMLElement* architecture = memspec->FirstChildElement("memarchitecturespec");
+ config.NumberOfBanks = queryUIntParameter(architecture, "nbrOfBanks");
+ config.NumberOfBankGroups = queryUIntParameter(architecture, "nbrOfBankGroups");
+ config.BurstLength = queryUIntParameter(architecture, "burstLength");
+ config.nActivate = 4;
+ config.DataRate = queryUIntParameter(architecture, "dataRate");
+ config.NumberOfRows = queryUIntParameter(architecture, "nbrOfRows");
+
+ //MemTimings
+ XMLElement* timings = memspec->FirstChildElement("memtimingspec");
+ double clkMhz = queryDoubleParameter(timings, "clkMhz");
+ sc_time clk = sc_time(1 / clkMhz, SC_US);
+ config.Timings.clk = clk;
+//TODO
+ config.Timings.tRP = clk * queryUIntParameter(timings, "RP");
+ config.Timings.tRAS = clk * queryUIntParameter(timings, "RAS");
+ config.Timings.tRC = clk * queryUIntParameter(timings, "RC");
+ config.Timings.tRRD_S = clk * queryUIntParameter(timings, "RRD_S");
+ config.Timings.tRRD_L = clk * queryUIntParameter(timings, "RRD_L");
+ config.Timings.tCCD_S = clk * queryUIntParameter(timings, "CCD_S");
+ config.Timings.tCCD_L = clk * queryUIntParameter(timings, "CCD_L");
+ config.Timings.tRCD = clk * queryUIntParameter(timings, "RCD");
+ config.Timings.tNAW = clk * queryUIntParameter(timings, "TAW");
+ config.Timings.tRL = clk * queryUIntParameter(timings, "RL");
+ config.Timings.tWL = clk * queryUIntParameter(timings, "WL");
+ config.Timings.tWR = clk * queryUIntParameter(timings, "WR");
+ config.Timings.tWTR_S = clk * queryUIntParameter(timings, "WTR_S");
+ config.Timings.tWTR_L = clk * queryUIntParameter(timings, "WTR_L");
+ config.Timings.tCKESR = clk * queryUIntParameter(timings, "CKESR");
+ config.Timings.tCKE = clk * queryUIntParameter(timings, "CKE");
+ config.Timings.tXP = clk * queryUIntParameter(timings, "XP");
+ config.Timings.tXSR = clk * queryUIntParameter(timings, "XS");
+ config.Timings.tAL = clk * queryUIntParameter(timings, "AL");
+ config.Timings.tRFC = clk * queryUIntParameter(timings, "RFC");
+ config.Timings.tREFI = clk * queryUIntParameter(timings, "REFI");
+
+ config.Timings.refreshTimings.clear();
+ for (unsigned int i = 0; i < config.NumberOfBanks; ++i)
+ {
+ config.Timings.refreshTimings.push_back(
+ RefreshTiming(config.Timings.tRFC, config.Timings.tREFI));
+ }
}
void MemSpecLoader::loadWideIO(Configuration& config, XMLElement* memspec)
@@ -81,13 +124,17 @@ void MemSpecLoader::loadWideIO(Configuration& config, XMLElement* memspec)
config.Timings.tRP = clk * queryUIntParameter(timings, "RP");
config.Timings.tRAS = clk * queryUIntParameter(timings, "RAS");
config.Timings.tRC = clk * queryUIntParameter(timings, "RC");
- config.Timings.tRRD = clk * queryUIntParameter(timings, "RRD");
+ config.Timings.tRRD_S = clk * queryUIntParameter(timings, "RRD");
+ config.Timings.tRRD_L = config.Timings.tRRD_S;
+ config.Timings.tCCD_S = clk * queryUIntParameter(timings, "CCD");
+ config.Timings.tCCD_L = config.Timings.tCCD_S;
config.Timings.tRCD = clk * queryUIntParameter(timings, "RCD");
config.Timings.tNAW = clk * queryUIntParameter(timings, "TAW");
config.Timings.tRL = clk * queryUIntParameter(timings, "RL");
config.Timings.tWL = clk * queryUIntParameter(timings, "WL");
config.Timings.tWR = clk * queryUIntParameter(timings, "WR");
- config.Timings.tWTR = clk * queryUIntParameter(timings, "WTR");
+ config.Timings.tWTR_S = clk * queryUIntParameter(timings, "WTR");
+ config.Timings.tWTR_L = config.Timings.tWTR_S;
config.Timings.tCKESR = clk * queryUIntParameter(timings, "CKESR");
config.Timings.tCKE = clk * queryUIntParameter(timings, "CKE");
config.Timings.tXP = clk * queryUIntParameter(timings, "XP");
diff --git a/dram/src/core/configuration/TimingConfiguration.h b/dram/src/core/configuration/TimingConfiguration.h
index 9ec92340..83cd11e4 100644
--- a/dram/src/core/configuration/TimingConfiguration.h
+++ b/dram/src/core/configuration/TimingConfiguration.h
@@ -30,17 +30,17 @@ struct TimingConfiguration
sc_time tRP; //precharge-time (pre -> act same bank)
sc_time tRAS; //active-time (act -> pre same bank)
sc_time tRC; //RAS-cycle-time (min time bw 2 succesive ACT to same bank)
- sc_time tCCD; //TODO: relevant? max(bl, tCCD)
- //sc_time tCCD_L;
- sc_time tRRD; //min time bw 2 succesive ACT to different banks (different bank group)
- //sc_time tRRD_L; //.. (same bank group)
+ sc_time tCCD_S; //TODO: relevant? max(bl, tCCD)
+ sc_time tCCD_L;
+ sc_time tRRD_S; //min time bw 2 succesive ACT to different banks (different bank group)
+ sc_time tRRD_L; //.. (same bank group)
sc_time tRCD; //act -> read/write
sc_time tNAW; //n activate window
sc_time tRL; //read latency (read command start to data strobe)
sc_time tWL; //write latency
sc_time tWR; //write recovery (write to precharge)
- sc_time tWTR; //write to read (different bank group)
- //sc_time tWTR_L; //.. (same bank group)
+ sc_time tWTR_S; //write to read (different bank group)
+ sc_time tWTR_L; //.. (same bank group)
sc_time tCKESR; //min time in sref
sc_time tCKE; //min time in pdna or pdnp
sc_time tXP; //min delay to row access command after pdnpx pdnax
@@ -54,7 +54,7 @@ struct TimingConfiguration
//act and read/write commands remain for this timespan in history
sc_time tActHistory(){return tNAW;}
- sc_time tDataStrobeHistory(){return tWTR;}
+ sc_time tDataStrobeHistory(){return tWTR_L;}
};
} /* namespace core */
diff --git a/dram/src/core/scheduling/checker/ActivateChecker.cpp b/dram/src/core/scheduling/checker/ActivateChecker.cpp
index 85645851..994f8738 100644
--- a/dram/src/core/scheduling/checker/ActivateChecker.cpp
+++ b/dram/src/core/scheduling/checker/ActivateChecker.cpp
@@ -33,7 +33,7 @@ void ActivateChecker::delayToSatisfyConstraints(ScheduledCommand& command) const
{
command.delayToMeetConstraint(lastCommandOnBank.getEnd(), config.Timings.tXP);
}
- else if(lastCommandOnBank.getCommand() == Command::SREFX)
+ else if (lastCommandOnBank.getCommand() == Command::SREFX)
{
command.delayToMeetConstraint(lastCommandOnBank.getEnd(), config.Timings.tXSR);
}
@@ -72,11 +72,16 @@ void ActivateChecker::delay_to_satisfy_activateToActivate_sameBank(ScheduledComm
bool ActivateChecker::satsfies_activateToActivate_differentBank(ScheduledCommand& command) const
{
- for (sc_time time : state.lastActivates)
+ for (auto act : state.lastActivates)
{
- if ((time < command.getStart() && command.getStart() - time < config.Timings.tRRD)
- || (command.getStart() <= time && time - command.getStart() < config.Timings.tRRD))
- return false;
+ sc_time time = act.first;
+ sc_time tRRD =
+ (getBankGroup(command.getBank()) == getBankGroup(act.second)) ?
+ config.Timings.tRRD_L : config.Timings.tRRD_S;
+
+ if ((time < command.getStart() && command.getStart() - time < tRRD)
+ || (command.getStart() <= time && time - command.getStart() < tRRD))
+ return false;
}
return true;
}
@@ -90,15 +95,15 @@ bool ActivateChecker::satisfies_nActivateWindow(ScheduledCommand& command) const
*/
if (state.lastActivates.size() >= config.nActivate)
{
- set lastActivates = state.lastActivates;
- lastActivates.emplace(command.getStart());
+ map lastActivates = state.lastActivates;
+ lastActivates.emplace(command.getStart(), command.getBank());
auto upper = lastActivates.begin();
advance(upper, config.nActivate);
auto lower = lastActivates.begin();
while (upper != lastActivates.end())
{
- if (*upper - *lower < config.Timings.tNAW)
+ if (upper->first - lower->first < config.Timings.tNAW)
return false;
++upper;
++lower;
diff --git a/dram/src/core/scheduling/checker/ReadChecker.cpp b/dram/src/core/scheduling/checker/ReadChecker.cpp
index e2d9c605..e1e2d84e 100644
--- a/dram/src/core/scheduling/checker/ReadChecker.cpp
+++ b/dram/src/core/scheduling/checker/ReadChecker.cpp
@@ -85,7 +85,11 @@ bool ReadChecker::collidesWithStrobeCommand(ScheduledCommand& read,
//write to read
else
{
- return !(read.getStart()>= getIntervalOnDataStrobe(strobeCommand).end + config.Timings.tWTR);
+ sc_time tWTR =
+ (getBankGroup(read.getBank()) == getBankGroup(strobeCommand.getBank())) ?
+ config.Timings.tWTR_L : config.Timings.tWTR_S;
+
+ return !(read.getStart()>= getIntervalOnDataStrobe(strobeCommand).end + tWTR);
}
}
else
diff --git a/dram/src/core/scheduling/checker/WriteChecker.cpp b/dram/src/core/scheduling/checker/WriteChecker.cpp
index 05cb9c0a..9b52d2c9 100644
--- a/dram/src/core/scheduling/checker/WriteChecker.cpp
+++ b/dram/src/core/scheduling/checker/WriteChecker.cpp
@@ -82,8 +82,12 @@ bool WriteChecker::collidesWithStrobeCommand(ScheduledCommand& write,
//write to read
if (strobeCommand.getStart() >= write.getStart())
{
+ sc_time tWTR =
+ (getBankGroup(write.getBank()) == getBankGroup(strobeCommand.getBank())) ?
+ config.Timings.tWTR_L : config.Timings.tWTR_S;
+
return !(strobeCommand.getStart()
- >= getIntervalOnDataStrobe(write).end + config.Timings.tWTR);
+ >= getIntervalOnDataStrobe(write).end + tWTR);
}
//read to write
diff --git a/dram/src/core/utils/Utils.cpp b/dram/src/core/utils/Utils.cpp
index d4a851b6..aa49010b 100644
--- a/dram/src/core/utils/Utils.cpp
+++ b/dram/src/core/utils/Utils.cpp
@@ -70,4 +70,20 @@ bool TimeInterval::intersects(TimeInterval other)
return other.timeIsInInterval(this->start) || this->timeIsInInterval(other.start);
}
+BankGroup getBankGroup(Bank bank)
+{
+ static std::map bankgroups;
+ if (bankgroups.size() == 0)
+ {
+ SC_ASSERT_(config.NumberOfBanks % config.NumberOfBankGroups == 0, "Number of banks must be a multiple of number of bankgroups");
+
+ for (unsigned int bank = 0; bank < Configuration::getInstance().NumberOfBanks; bank++)
+ {
+ unsigned int group = bank / Configuration::getInstance().NumberOfBankGroups;
+ bankgroups.insert(std::pair(Bank(bank), BankGroup(group)));
+ }
+ }
+ return bankgroups.at(bank);
+}
+
}
diff --git a/dram/src/core/utils/Utils.h b/dram/src/core/utils/Utils.h
index b979475e..2b2fef07 100644
--- a/dram/src/core/utils/Utils.h
+++ b/dram/src/core/utils/Utils.h
@@ -34,6 +34,7 @@ enum Alignment {UP, DOWN};
const sc_time clkAlign(sc_time time, sc_time clk, Alignment alignment = UP);
bool isClkAligned(sc_time time, sc_time clk);
+BankGroup getBankGroup(Bank bank);
};
#endif /* UTILS_H_ */