From 3bbf81584caa664441c96ebe269e67cfc2cab78c Mon Sep 17 00:00:00 2001 From: Janik Schlemminger Date: Wed, 9 Apr 2014 13:56:24 +0200 Subject: [PATCH] first ddr4 changes --- .../configs/memspecs/MatzesWideIO.xml | 2 +- dram/src/core/ControllerCore.cpp | 16 ------ dram/src/core/ControllerCore.h | 4 +- dram/src/core/ControllerState.cpp | 2 +- dram/src/core/ControllerState.h | 2 +- dram/src/core/configuration/MemSpecLoader.cpp | 51 ++++++++++++++++++- .../core/configuration/TimingConfiguration.h | 14 ++--- .../scheduling/checker/ActivateChecker.cpp | 21 +++++--- .../core/scheduling/checker/ReadChecker.cpp | 6 ++- .../core/scheduling/checker/WriteChecker.cpp | 6 ++- dram/src/core/utils/Utils.cpp | 16 ++++++ dram/src/core/utils/Utils.h | 1 + 12 files changed, 101 insertions(+), 40 deletions(-) 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_ */