From: Matthew Poremba Date: Wed, 1 May 2019 18:32:49 +0000 (-0700) Subject: mem: Option to toggle DRAM low-power states X-Git-Tag: v19.0.0.0~781 X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=f2be9f195c5aa226fa546e79c9acf95c8a800915;p=gem5.git mem: Option to toggle DRAM low-power states Adding an option to enable DRAM low-power states. The low power states can have a significant impact on application performance (sim_ticks) on the order of 2-3x, especially for compute-gpu apps. The options allows for it to easily be enabled/disabled to compare performance numbers. The option is disabled by default. Change-Id: Ib9bddbb792a1a6a4afb5339003472ff8f00a5859 Reviewed-on: https://gem5-review.googlesource.com/c/public/gem5/+/18548 Reviewed-by: Wendy Elsasser Reviewed-by: Andreas Sandberg Maintainer: Jason Lowe-Power Tested-by: kokoro --- diff --git a/configs/common/MemConfig.py b/configs/common/MemConfig.py index 29c41388c..d09869285 100644 --- a/configs/common/MemConfig.py +++ b/configs/common/MemConfig.py @@ -224,6 +224,11 @@ def config_mem(options, system): if issubclass(cls, m5.objects.DRAMCtrl) and opt_mem_ranks: mem_ctrl.ranks_per_channel = opt_mem_ranks + # Enable low-power DRAM states if option is set + if issubclass(cls, m5.objects.DRAMCtrl): + mem_ctrl.enable_dram_powerdown = \ + options.enable_dram_powerdown + if opt_elastic_trace_en: mem_ctrl.latency = '1ns' print("For elastic trace, over-riding Simple Memory " diff --git a/configs/common/Options.py b/configs/common/Options.py index 4279b8006..f6fa0d031 100644 --- a/configs/common/Options.py +++ b/configs/common/Options.py @@ -104,6 +104,8 @@ def addNoISAOptions(parser): parser.add_option("--mem-size", action="store", type="string", default="512MB", help="Specify the physical memory size (single memory)") + parser.add_option("--enable-dram-powerdown", action="store_true", + help="Enable low-power states in DRAMCtrl") parser.add_option("--memchecker", action="store_true") diff --git a/configs/ruby/Ruby.py b/configs/ruby/Ruby.py index 2d69ac19a..c9ae251d9 100644 --- a/configs/ruby/Ruby.py +++ b/configs/ruby/Ruby.py @@ -130,6 +130,11 @@ def setup_memory_controllers(system, ruby, dir_cntrls, options): else: mem_ctrl.port = dir_cntrl.memory + # Enable low-power DRAM states if option is set + if issubclass(MemConfig.get(options.mem_type), DRAMCtrl): + mem_ctrl.enable_dram_powerdown = \ + options.enable_dram_powerdown + index += 1 dir_cntrl.addr_ranges = dir_ranges diff --git a/src/mem/DRAMCtrl.py b/src/mem/DRAMCtrl.py index 93ea7d56f..14db3d3c9 100644 --- a/src/mem/DRAMCtrl.py +++ b/src/mem/DRAMCtrl.py @@ -135,6 +135,10 @@ class DRAMCtrl(QoSMemCtrl): # to be instantiated for a multi-channel configuration channels = Param.Unsigned(1, "Number of channels") + # Enable DRAM powerdown states if True. This is False by default due to + # performance being lower when enabled + enable_dram_powerdown = Param.Bool(False, "Enable powerdown states") + # For power modelling we need to know if the DRAM has a DLL or not dll = Param.Bool(True, "DRAM has DLL or not") diff --git a/src/mem/dram_ctrl.cc b/src/mem/dram_ctrl.cc index 08465aa70..06c540ba6 100644 --- a/src/mem/dram_ctrl.cc +++ b/src/mem/dram_ctrl.cc @@ -97,7 +97,7 @@ DRAMCtrl::DRAMCtrl(const DRAMCtrlParams* p) : backendLatency(p->static_backend_latency), nextBurstAt(0), prevArrival(0), nextReqTime(0), activeRank(0), timeStampOffset(0), - lastStatsResetTick(0) + lastStatsResetTick(0), enableDRAMPowerdown(p->enable_dram_powerdown) { // sanity check the ranks since we rely on bit slicing for the // address decoding @@ -705,7 +705,7 @@ DRAMCtrl::processRespondEvent() // track if this is the last packet before idling // and that there are no outstanding commands to this rank if (dram_pkt->rankRef.isQueueEmpty() && - dram_pkt->rankRef.outstandingEvents == 0) { + dram_pkt->rankRef.outstandingEvents == 0 && enableDRAMPowerdown) { // verify that there are no events scheduled assert(!dram_pkt->rankRef.activateEvent.scheduled()); assert(!dram_pkt->rankRef.prechargeEvent.scheduled()); @@ -1856,7 +1856,8 @@ DRAMCtrl::Rank::processPrechargeEvent() if (numBanksActive == 0) { // no reads to this rank in the Q and no pending // RD/WR or refresh commands - if (isQueueEmpty() && outstandingEvents == 0) { + if (isQueueEmpty() && outstandingEvents == 0 && + memory.enableDRAMPowerdown) { // should still be in ACT state since bank still open assert(pwrState == PWR_ACT); @@ -2057,7 +2058,7 @@ DRAMCtrl::Rank::processRefreshEvent() // Force PRE power-down if there are no outstanding commands // in Q after refresh. - } else if (isQueueEmpty()) { + } else if (isQueueEmpty() && memory.enableDRAMPowerdown) { // still have refresh event outstanding but there should // be no other events outstanding assert(outstandingEvents == 1); @@ -2328,7 +2329,8 @@ DRAMCtrl::Rank::processPowerEvent() // will issue refresh immediately upon entry if (pwrStatePostRefresh == PWR_PRE_PDN && isQueueEmpty() && (memory.drainState() != DrainState::Draining) && - (memory.drainState() != DrainState::Drained)) { + (memory.drainState() != DrainState::Drained) && + memory.enableDRAMPowerdown) { DPRINTF(DRAMState, "Rank %d bypassing refresh and transitioning " "to self refresh at %11u tick\n", rank, curTick()); powerDownSleep(PWR_SREF, curTick()); diff --git a/src/mem/dram_ctrl.hh b/src/mem/dram_ctrl.hh index 54826e0a8..7de0872ea 100644 --- a/src/mem/dram_ctrl.hh +++ b/src/mem/dram_ctrl.hh @@ -1140,6 +1140,9 @@ class DRAMCtrl : public QoS::MemCtrl /** The time when stats were last reset used to calculate average power */ Tick lastStatsResetTick; + /** Enable or disable DRAM powerdown states. */ + bool enableDRAMPowerdown; + /** * Upstream caches need this packet until true is returned, so * hold it for deletion until a subsequent call