gem5  v22.1.0.0
dram_interface.cc
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2010-2020 ARM Limited
3  * All rights reserved
4  *
5  * The license below extends only to copyright in the software and shall
6  * not be construed as granting a license to any other intellectual
7  * property including but not limited to intellectual property relating
8  * to a hardware implementation of the functionality of the software
9  * licensed hereunder. You may use the software subject to the license
10  * terms below provided that you ensure that this notice is replicated
11  * unmodified and in its entirety in all distributions of the software,
12  * modified or unmodified, in source code or in binary form.
13  *
14  * Copyright (c) 2013 Amin Farmahini-Farahani
15  * All rights reserved.
16  *
17  * Redistribution and use in source and binary forms, with or without
18  * modification, are permitted provided that the following conditions are
19  * met: redistributions of source code must retain the above copyright
20  * notice, this list of conditions and the following disclaimer;
21  * redistributions in binary form must reproduce the above copyright
22  * notice, this list of conditions and the following disclaimer in the
23  * documentation and/or other materials provided with the distribution;
24  * neither the name of the copyright holders nor the names of its
25  * contributors may be used to endorse or promote products derived from
26  * this software without specific prior written permission.
27  *
28  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
29  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
30  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
31  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
32  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
33  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
34  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
35  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
36  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
37  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
38  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
39  */
40 
41 #include "mem/dram_interface.hh"
42 
43 #include "base/bitfield.hh"
44 #include "base/cprintf.hh"
45 #include "base/trace.hh"
46 #include "debug/DRAM.hh"
47 #include "debug/DRAMPower.hh"
48 #include "debug/DRAMState.hh"
49 #include "sim/system.hh"
50 
51 namespace gem5
52 {
53 
54 using namespace Data;
55 
56 namespace memory
57 {
58 
60 DRAMInterface::chooseNextFRFCFS(MemPacketQueue& queue, Tick min_col_at) const
61 {
62  std::vector<uint32_t> earliest_banks(ranksPerChannel, 0);
63 
64  // Has minBankPrep been called to populate earliest_banks?
65  bool filled_earliest_banks = false;
66  // can the PRE/ACT sequence be done without impacting utlization?
67  bool hidden_bank_prep = false;
68 
69  // search for seamless row hits first, if no seamless row hit is
70  // found then determine if there are other packets that can be issued
71  // without incurring additional bus delay due to bank timing
72  // Will select closed rows first to enable more open row possibilies
73  // in future selections
74  bool found_hidden_bank = false;
75 
76  // remember if we found a row hit, not seamless, but bank prepped
77  // and ready
78  bool found_prepped_pkt = false;
79 
80  // if we have no row hit, prepped or not, and no seamless packet,
81  // just go for the earliest possible
82  bool found_earliest_pkt = false;
83 
84  Tick selected_col_at = MaxTick;
85  auto selected_pkt_it = queue.end();
86 
87  for (auto i = queue.begin(); i != queue.end() ; ++i) {
88  MemPacket* pkt = *i;
89 
90  // select optimal DRAM packet in Q
91  if (pkt->isDram() && (pkt->pseudoChannel == pseudoChannel)) {
92  const Bank& bank = ranks[pkt->rank]->banks[pkt->bank];
93  const Tick col_allowed_at = pkt->isRead() ? bank.rdAllowedAt :
94  bank.wrAllowedAt;
95 
96  DPRINTF(DRAM, "%s checking DRAM packet in bank %d, row %d\n",
97  __func__, pkt->bank, pkt->row);
98 
99  // check if rank is not doing a refresh and thus is available,
100  // if not, jump to the next packet
101  if (burstReady(pkt)) {
102 
103  DPRINTF(DRAM,
104  "%s bank %d - Rank %d available\n", __func__,
105  pkt->bank, pkt->rank);
106 
107  // check if it is a row hit
108  if (bank.openRow == pkt->row) {
109  // no additional rank-to-rank or same bank-group
110  // delays, or we switched read/write and might as well
111  // go for the row hit
112  if (col_allowed_at <= min_col_at) {
113  // FCFS within the hits, giving priority to
114  // commands that can issue seamlessly, without
115  // additional delay, such as same rank accesses
116  // and/or different bank-group accesses
117  DPRINTF(DRAM, "%s Seamless buffer hit\n", __func__);
118  selected_pkt_it = i;
119  selected_col_at = col_allowed_at;
120  // no need to look through the remaining queue entries
121  break;
122  } else if (!found_hidden_bank && !found_prepped_pkt) {
123  // if we did not find a packet to a closed row that can
124  // issue the bank commands without incurring delay, and
125  // did not yet find a packet to a prepped row, remember
126  // the current one
127  selected_pkt_it = i;
128  selected_col_at = col_allowed_at;
129  found_prepped_pkt = true;
130  DPRINTF(DRAM, "%s Prepped row buffer hit\n", __func__);
131  }
132  } else if (!found_earliest_pkt) {
133  // if we have not initialised the bank status, do it
134  // now, and only once per scheduling decisions
135  if (!filled_earliest_banks) {
136  // determine entries with earliest bank delay
137  std::tie(earliest_banks, hidden_bank_prep) =
138  minBankPrep(queue, min_col_at);
139  filled_earliest_banks = true;
140  }
141 
142  // bank is amongst first available banks
143  // minBankPrep will give priority to packets that can
144  // issue seamlessly
145  if (bits(earliest_banks[pkt->rank],
146  pkt->bank, pkt->bank)) {
147  found_earliest_pkt = true;
148  found_hidden_bank = hidden_bank_prep;
149 
150  // give priority to packets that can issue
151  // bank commands 'behind the scenes'
152  // any additional delay if any will be due to
153  // col-to-col command requirements
154  if (hidden_bank_prep || !found_prepped_pkt) {
155  selected_pkt_it = i;
156  selected_col_at = col_allowed_at;
157  }
158  }
159  }
160  } else {
161  DPRINTF(DRAM, "%s bank %d - Rank %d not available\n", __func__,
162  pkt->bank, pkt->rank);
163  }
164  }
165  }
166 
167  if (selected_pkt_it == queue.end()) {
168  DPRINTF(DRAM, "%s no available DRAM ranks found\n", __func__);
169  }
170 
171  return std::make_pair(selected_pkt_it, selected_col_at);
172 }
173 
174 void
175 DRAMInterface::activateBank(Rank& rank_ref, Bank& bank_ref,
176  Tick act_tick, uint32_t row)
177 {
178  assert(rank_ref.actTicks.size() == activationLimit);
179 
180  // verify that we have command bandwidth to issue the activate
181  // if not, shift to next burst window
182  Tick act_at;
183  if (twoCycleActivate)
184  act_at = ctrl->verifyMultiCmd(act_tick, maxCommandsPerWindow, tAAD);
185  else
186  act_at = ctrl->verifySingleCmd(act_tick, maxCommandsPerWindow, true);
187 
188  DPRINTF(DRAM, "Activate at tick %d\n", act_at);
189 
190  // update the open row
191  assert(bank_ref.openRow == Bank::NO_ROW);
192  bank_ref.openRow = row;
193 
194  // start counting anew, this covers both the case when we
195  // auto-precharged, and when this access is forced to
196  // precharge
197  bank_ref.bytesAccessed = 0;
198  bank_ref.rowAccesses = 0;
199 
200  ++rank_ref.numBanksActive;
201  assert(rank_ref.numBanksActive <= banksPerRank);
202 
203  DPRINTF(DRAM, "Activate bank %d, rank %d at tick %lld, now got "
204  "%d active\n", bank_ref.bank, rank_ref.rank, act_at,
205  ranks[rank_ref.rank]->numBanksActive);
206 
207  rank_ref.cmdList.push_back(Command(MemCommand::ACT, bank_ref.bank,
208  act_at));
209 
210  DPRINTF(DRAMPower, "%llu,ACT,%d,%d\n", divCeil(act_at, tCK) -
211  timeStampOffset, bank_ref.bank, rank_ref.rank);
212 
213  // The next access has to respect tRAS for this bank
214  bank_ref.preAllowedAt = act_at + tRAS;
215 
216  // Respect the row-to-column command delay for both read and write cmds
217  bank_ref.rdAllowedAt = std::max(act_at + tRCD_RD, bank_ref.rdAllowedAt);
218  bank_ref.wrAllowedAt = std::max(act_at + tRCD_WR, bank_ref.wrAllowedAt);
219 
220  // start by enforcing tRRD
221  for (int i = 0; i < banksPerRank; i++) {
222  // next activate to any bank in this rank must not happen
223  // before tRRD
224  if (bankGroupArch && (bank_ref.bankgr == rank_ref.banks[i].bankgr)) {
225  // bank group architecture requires longer delays between
226  // ACT commands within the same bank group. Use tRRD_L
227  // in this case
228  rank_ref.banks[i].actAllowedAt = std::max(act_at + tRRD_L,
229  rank_ref.banks[i].actAllowedAt);
230  } else {
231  // use shorter tRRD value when either
232  // 1) bank group architecture is not supportted
233  // 2) bank is in a different bank group
234  rank_ref.banks[i].actAllowedAt = std::max(act_at + tRRD,
235  rank_ref.banks[i].actAllowedAt);
236  }
237  }
238 
239  // next, we deal with tXAW, if the activation limit is disabled
240  // then we directly schedule an activate power event
241  if (!rank_ref.actTicks.empty()) {
242  // sanity check
243  if (rank_ref.actTicks.back() &&
244  (act_at - rank_ref.actTicks.back()) < tXAW) {
245  panic("Got %d activates in window %d (%llu - %llu) which "
246  "is smaller than %llu\n", activationLimit, act_at -
247  rank_ref.actTicks.back(), act_at,
248  rank_ref.actTicks.back(), tXAW);
249  }
250 
251  // shift the times used for the book keeping, the last element
252  // (highest index) is the oldest one and hence the lowest value
253  rank_ref.actTicks.pop_back();
254 
255  // record an new activation (in the future)
256  rank_ref.actTicks.push_front(act_at);
257 
258  // cannot activate more than X times in time window tXAW, push the
259  // next one (the X + 1'st activate) to be tXAW away from the
260  // oldest in our window of X
261  if (rank_ref.actTicks.back() &&
262  (act_at - rank_ref.actTicks.back()) < tXAW) {
263  DPRINTF(DRAM, "Enforcing tXAW with X = %d, next activate "
264  "no earlier than %llu\n", activationLimit,
265  rank_ref.actTicks.back() + tXAW);
266  for (int j = 0; j < banksPerRank; j++)
267  // next activate must not happen before end of window
268  rank_ref.banks[j].actAllowedAt =
269  std::max(rank_ref.actTicks.back() + tXAW,
270  rank_ref.banks[j].actAllowedAt);
271  }
272  }
273 
274  // at the point when this activate takes place, make sure we
275  // transition to the active power state
276  if (!rank_ref.activateEvent.scheduled())
277  schedule(rank_ref.activateEvent, act_at);
278  else if (rank_ref.activateEvent.when() > act_at)
279  // move it sooner in time
280  reschedule(rank_ref.activateEvent, act_at);
281 }
282 
283 void
284 DRAMInterface::prechargeBank(Rank& rank_ref, Bank& bank, Tick pre_tick,
285  bool auto_or_preall, bool trace)
286 {
287  // make sure the bank has an open row
288  assert(bank.openRow != Bank::NO_ROW);
289 
290  // sample the bytes per activate here since we are closing
291  // the page
292  stats.bytesPerActivate.sample(bank.bytesAccessed);
293 
294  bank.openRow = Bank::NO_ROW;
295 
296  Tick pre_at = pre_tick;
297  if (auto_or_preall) {
298  // no precharge allowed before this one
299  bank.preAllowedAt = pre_at;
300  } else {
301  // Issuing an explicit PRE command
302  // Verify that we have command bandwidth to issue the precharge
303  // if not, shift to next burst window
304  pre_at = ctrl->verifySingleCmd(pre_tick, maxCommandsPerWindow, true);
305  // enforce tPPD
306  for (int i = 0; i < banksPerRank; i++) {
307  rank_ref.banks[i].preAllowedAt = std::max(pre_at + tPPD,
308  rank_ref.banks[i].preAllowedAt);
309  }
310  }
311 
312  Tick pre_done_at = pre_at + tRP;
313 
314  bank.actAllowedAt = std::max(bank.actAllowedAt, pre_done_at);
315 
316  assert(rank_ref.numBanksActive != 0);
317  --rank_ref.numBanksActive;
318 
319  DPRINTF(DRAM, "Precharging bank %d, rank %d at tick %lld, now got "
320  "%d active\n", bank.bank, rank_ref.rank, pre_at,
321  rank_ref.numBanksActive);
322 
323  if (trace) {
324 
325  rank_ref.cmdList.push_back(Command(MemCommand::PRE, bank.bank,
326  pre_at));
327  DPRINTF(DRAMPower, "%llu,PRE,%d,%d\n", divCeil(pre_at, tCK) -
328  timeStampOffset, bank.bank, rank_ref.rank);
329  }
330 
331  // if we look at the current number of active banks we might be
332  // tempted to think the DRAM is now idle, however this can be
333  // undone by an activate that is scheduled to happen before we
334  // would have reached the idle state, so schedule an event and
335  // rather check once we actually make it to the point in time when
336  // the (last) precharge takes place
337  if (!rank_ref.prechargeEvent.scheduled()) {
338  schedule(rank_ref.prechargeEvent, pre_done_at);
339  // New event, increment count
340  ++rank_ref.outstandingEvents;
341  } else if (rank_ref.prechargeEvent.when() < pre_done_at) {
342  reschedule(rank_ref.prechargeEvent, pre_done_at);
343  }
344 }
345 
347 DRAMInterface::doBurstAccess(MemPacket* mem_pkt, Tick next_burst_at,
348  const std::vector<MemPacketQueue>& queue)
349 {
350  DPRINTF(DRAM, "Timing access to addr %#x, rank/bank/row %d %d %d\n",
351  mem_pkt->addr, mem_pkt->rank, mem_pkt->bank, mem_pkt->row);
352 
353  // get the rank
354  Rank& rank_ref = *ranks[mem_pkt->rank];
355 
356  assert(rank_ref.inRefIdleState());
357 
358  // are we in or transitioning to a low-power state and have not scheduled
359  // a power-up event?
360  // if so, wake up from power down to issue RD/WR burst
361  if (rank_ref.inLowPowerState) {
362  assert(rank_ref.pwrState != PWR_SREF);
363  rank_ref.scheduleWakeUpEvent(tXP);
364  }
365 
366  // get the bank
367  Bank& bank_ref = rank_ref.banks[mem_pkt->bank];
368 
369  // for the state we need to track if it is a row hit or not
370  bool row_hit = true;
371 
372  // Determine the access latency and update the bank state
373  if (bank_ref.openRow == mem_pkt->row) {
374  // nothing to do
375  } else {
376  row_hit = false;
377 
378  // If there is a page open, precharge it.
379  if (bank_ref.openRow != Bank::NO_ROW) {
380  prechargeBank(rank_ref, bank_ref, std::max(bank_ref.preAllowedAt,
381  curTick()));
382  }
383 
384  // next we need to account for the delay in activating the page
385  Tick act_tick = std::max(bank_ref.actAllowedAt, curTick());
386 
387  // Record the activation and deal with all the global timing
388  // constraints caused be a new activation (tRRD and tXAW)
389  activateBank(rank_ref, bank_ref, act_tick, mem_pkt->row);
390  }
391 
392  // respect any constraints on the command (e.g. tRCD or tCCD)
393  const Tick col_allowed_at = mem_pkt->isRead() ?
394  bank_ref.rdAllowedAt : bank_ref.wrAllowedAt;
395 
396  // we need to wait until the bus is available before we can issue
397  // the command; need to ensure minimum bus delay requirement is met
398  Tick cmd_at = std::max({col_allowed_at, next_burst_at, curTick()});
399 
400  // verify that we have command bandwidth to issue the burst
401  // if not, shift to next burst window
402  Tick max_sync = clkResyncDelay + (mem_pkt->isRead() ? tRL : tWL);
403  if (dataClockSync && ((cmd_at - rank_ref.lastBurstTick) > max_sync))
404  cmd_at = ctrl->verifyMultiCmd(cmd_at, maxCommandsPerWindow, tCK);
405  else
406  cmd_at = ctrl->verifySingleCmd(cmd_at, maxCommandsPerWindow, false);
407 
408  // if we are interleaving bursts, ensure that
409  // 1) we don't double interleave on next burst issue
410  // 2) we are at an interleave boundary; if not, shift to next boundary
411  Tick burst_gap = tBURST_MIN;
412  if (burstInterleave) {
413  if (cmd_at == (rank_ref.lastBurstTick + tBURST_MIN)) {
414  // already interleaving, push next command to end of full burst
415  burst_gap = tBURST;
416  } else if (cmd_at < (rank_ref.lastBurstTick + tBURST)) {
417  // not at an interleave boundary after bandwidth check
418  // Shift command to tBURST boundary to avoid data contention
419  // Command will remain in the same burst window given that
420  // tBURST is less than tBURST_MAX
421  cmd_at = rank_ref.lastBurstTick + tBURST;
422  }
423  }
424  DPRINTF(DRAM, "Schedule RD/WR burst at tick %d\n", cmd_at);
425 
426  // update the packet ready time
427  if (mem_pkt->isRead()) {
428  mem_pkt->readyTime = cmd_at + tRL + tBURST;
429  } else {
430  mem_pkt->readyTime = cmd_at + tWL + tBURST;
431  }
432 
433  rank_ref.lastBurstTick = cmd_at;
434 
435  // update the time for the next read/write burst for each
436  // bank (add a max with tCCD/tCCD_L/tCCD_L_WR here)
437  Tick dly_to_rd_cmd;
438  Tick dly_to_wr_cmd;
439  for (int j = 0; j < ranksPerChannel; j++) {
440  for (int i = 0; i < banksPerRank; i++) {
441  if (mem_pkt->rank == j) {
442  if (bankGroupArch &&
443  (bank_ref.bankgr == ranks[j]->banks[i].bankgr)) {
444  // bank group architecture requires longer delays between
445  // RD/WR burst commands to the same bank group.
446  // tCCD_L is default requirement for same BG timing
447  // tCCD_L_WR is required for write-to-write
448  // Need to also take bus turnaround delays into account
449  dly_to_rd_cmd = mem_pkt->isRead() ?
450  tCCD_L : std::max(tCCD_L, wrToRdDlySameBG);
451  dly_to_wr_cmd = mem_pkt->isRead() ?
452  std::max(tCCD_L, rdToWrDlySameBG) :
453  tCCD_L_WR;
454  } else {
455  // tBURST is default requirement for diff BG timing
456  // Need to also take bus turnaround delays into account
457  dly_to_rd_cmd = mem_pkt->isRead() ? burst_gap :
458  writeToReadDelay();
459  dly_to_wr_cmd = mem_pkt->isRead() ? readToWriteDelay() :
460  burst_gap;
461  }
462  } else {
463  // different rank is by default in a different bank group and
464  // doesn't require longer tCCD or additional RTW, WTR delays
465  // Need to account for rank-to-rank switching
466  dly_to_wr_cmd = rankToRankDelay();
467  dly_to_rd_cmd = rankToRankDelay();
468  }
469  ranks[j]->banks[i].rdAllowedAt = std::max(cmd_at + dly_to_rd_cmd,
470  ranks[j]->banks[i].rdAllowedAt);
471  ranks[j]->banks[i].wrAllowedAt = std::max(cmd_at + dly_to_wr_cmd,
472  ranks[j]->banks[i].wrAllowedAt);
473  }
474  }
475 
476  // Save rank of current access
477  activeRank = mem_pkt->rank;
478 
479  // If this is a write, we also need to respect the write recovery
480  // time before a precharge, in the case of a read, respect the
481  // read to precharge constraint
482  bank_ref.preAllowedAt = std::max(bank_ref.preAllowedAt,
483  mem_pkt->isRead() ? cmd_at + tRTP :
484  mem_pkt->readyTime + tWR);
485 
486  // increment the bytes accessed and the accesses per row
487  bank_ref.bytesAccessed += burstSize;
488  ++bank_ref.rowAccesses;
489 
490  // if we reached the max, then issue with an auto-precharge
491  bool auto_precharge = pageMgmt == enums::close ||
492  bank_ref.rowAccesses == maxAccessesPerRow;
493 
494  // if we did not hit the limit, we might still want to
495  // auto-precharge
496  if (!auto_precharge &&
497  (pageMgmt == enums::open_adaptive ||
498  pageMgmt == enums::close_adaptive)) {
499  // a twist on the open and close page policies:
500  // 1) open_adaptive page policy does not blindly keep the
501  // page open, but close it if there are no row hits, and there
502  // are bank conflicts in the queue
503  // 2) close_adaptive page policy does not blindly close the
504  // page, but closes it only if there are no row hits in the queue.
505  // In this case, only force an auto precharge when there
506  // are no same page hits in the queue
507  bool got_more_hits = false;
508  bool got_bank_conflict = false;
509 
510  for (uint8_t i = 0; i < ctrl->numPriorities(); ++i) {
511  auto p = queue[i].begin();
512  // keep on looking until we find a hit or reach the end of the
513  // queue
514  // 1) if a hit is found, then both open and close adaptive
515  // policies keep the page open
516  // 2) if no hit is found, got_bank_conflict is set to true if a
517  // bank conflict request is waiting in the queue
518  // 3) make sure we are not considering the packet that we are
519  // currently dealing with
520  while (!got_more_hits && p != queue[i].end()) {
521 
522  if ((*p)->pseudoChannel != pseudoChannel) {
523  // only consider if this pkt belongs to this interface
524  ++p;
525  continue;
526  }
527 
528  if (mem_pkt != (*p)) {
529  bool same_rank_bank = (mem_pkt->rank == (*p)->rank) &&
530  (mem_pkt->bank == (*p)->bank);
531 
532  bool same_row = mem_pkt->row == (*p)->row;
533  got_more_hits |= same_rank_bank && same_row;
534  got_bank_conflict |= same_rank_bank && !same_row;
535  }
536  ++p;
537  }
538 
539  if (got_more_hits)
540  break;
541  }
542 
543  // auto pre-charge when either
544  // 1) open_adaptive policy, we have not got any more hits, and
545  // have a bank conflict
546  // 2) close_adaptive policy and we have not got any more hits
547  auto_precharge = !got_more_hits &&
548  (got_bank_conflict || pageMgmt == enums::close_adaptive);
549  }
550 
551  // DRAMPower trace command to be written
552  std::string mem_cmd = mem_pkt->isRead() ? "RD" : "WR";
553 
554  // MemCommand required for DRAMPower library
555  MemCommand::cmds command = (mem_cmd == "RD") ? MemCommand::RD :
556  MemCommand::WR;
557 
558  rank_ref.cmdList.push_back(Command(command, mem_pkt->bank, cmd_at));
559 
560  DPRINTF(DRAMPower, "%llu,%s,%d,%d\n", divCeil(cmd_at, tCK) -
561  timeStampOffset, mem_cmd, mem_pkt->bank, mem_pkt->rank);
562 
563  // if this access should use auto-precharge, then we are
564  // closing the row after the read/write burst
565  if (auto_precharge) {
566  // if auto-precharge push a PRE command at the correct tick to the
567  // list used by DRAMPower library to calculate power
568  prechargeBank(rank_ref, bank_ref, std::max(curTick(),
569  bank_ref.preAllowedAt), true);
570 
571  DPRINTF(DRAM, "Auto-precharged bank: %d\n", mem_pkt->bankId);
572  }
573 
574  // Update the stats and schedule the next request
575  if (mem_pkt->isRead()) {
576  // Every respQueue which will generate an event, increment count
577  ++rank_ref.outstandingEvents;
578 
579  stats.readBursts++;
580  if (row_hit)
581  stats.readRowHits++;
582  stats.bytesRead += burstSize;
583  stats.perBankRdBursts[mem_pkt->bankId]++;
584 
585  // Update latency stats
586  stats.totMemAccLat += mem_pkt->readyTime - mem_pkt->entryTime;
587  stats.totQLat += cmd_at - mem_pkt->entryTime;
588  stats.totBusLat += tBURST;
589  } else {
590  // Schedule write done event to decrement event count
591  // after the readyTime has been reached
592  // Only schedule latest write event to minimize events
593  // required; only need to ensure that final event scheduled covers
594  // the time that writes are outstanding and bus is active
595  // to holdoff power-down entry events
596  if (!rank_ref.writeDoneEvent.scheduled()) {
597  schedule(rank_ref.writeDoneEvent, mem_pkt->readyTime);
598  // New event, increment count
599  ++rank_ref.outstandingEvents;
600 
601  } else if (rank_ref.writeDoneEvent.when() < mem_pkt->readyTime) {
602  reschedule(rank_ref.writeDoneEvent, mem_pkt->readyTime);
603  }
604  // will remove write from queue when returned to parent function
605  // decrement count for DRAM rank
606  --rank_ref.writeEntries;
607 
608  stats.writeBursts++;
609  if (row_hit)
610  stats.writeRowHits++;
611  stats.bytesWritten += burstSize;
612  stats.perBankWrBursts[mem_pkt->bankId]++;
613 
614  }
615  // Update bus state to reflect when previous command was issued
616  return std::make_pair(cmd_at, cmd_at + burst_gap);
617 }
618 
619 void
620 DRAMInterface::addRankToRankDelay(Tick cmd_at)
621 {
622  // update timing for DRAM ranks due to bursts issued
623  // to ranks on other media interfaces
624  for (auto n : ranks) {
625  for (int i = 0; i < banksPerRank; i++) {
626  // different rank by default
627  // Need to only account for rank-to-rank switching
628  n->banks[i].rdAllowedAt = std::max(cmd_at + rankToRankDelay(),
629  n->banks[i].rdAllowedAt);
630  n->banks[i].wrAllowedAt = std::max(cmd_at + rankToRankDelay(),
631  n->banks[i].wrAllowedAt);
632  }
633  }
634 }
635 
636 DRAMInterface::DRAMInterface(const DRAMInterfaceParams &_p)
637  : MemInterface(_p),
638  bankGroupsPerRank(_p.bank_groups_per_rank),
639  bankGroupArch(_p.bank_groups_per_rank > 0),
640  tRL(_p.tCL),
641  tWL(_p.tCWL),
642  tBURST_MIN(_p.tBURST_MIN), tBURST_MAX(_p.tBURST_MAX),
643  tCCD_L_WR(_p.tCCD_L_WR), tCCD_L(_p.tCCD_L),
644  tRCD_RD(_p.tRCD), tRCD_WR(_p.tRCD_WR),
645  tRP(_p.tRP), tRAS(_p.tRAS), tWR(_p.tWR), tRTP(_p.tRTP),
646  tRFC(_p.tRFC), tREFI(_p.tREFI), tRRD(_p.tRRD), tRRD_L(_p.tRRD_L),
647  tPPD(_p.tPPD), tAAD(_p.tAAD),
648  tXAW(_p.tXAW), tXP(_p.tXP), tXS(_p.tXS),
649  clkResyncDelay(_p.tBURST_MAX),
650  dataClockSync(_p.data_clock_sync),
651  burstInterleave(tBURST != tBURST_MIN),
652  twoCycleActivate(_p.two_cycle_activate),
653  activationLimit(_p.activation_limit),
654  wrToRdDlySameBG(tWL + _p.tBURST_MAX + _p.tWTR_L),
655  rdToWrDlySameBG(_p.tRTW + _p.tBURST_MAX),
656  pageMgmt(_p.page_policy),
657  maxAccessesPerRow(_p.max_accesses_per_row),
658  timeStampOffset(0), activeRank(0),
659  enableDRAMPowerdown(_p.enable_dram_powerdown),
660  lastStatsResetTick(0),
661  stats(*this)
662 {
663  DPRINTF(DRAM, "Setting up DRAM Interface\n");
664 
665  fatal_if(!isPowerOf2(burstSize), "DRAM burst size %d is not allowed, "
666  "must be a power of two\n", burstSize);
667 
668  // sanity check the ranks since we rely on bit slicing for the
669  // address decoding
670  fatal_if(!isPowerOf2(ranksPerChannel), "DRAM rank count of %d is "
671  "not allowed, must be a power of two\n", ranksPerChannel);
672 
673  for (int i = 0; i < ranksPerChannel; i++) {
674  DPRINTF(DRAM, "Creating DRAM rank %d \n", i);
675  Rank* rank = new Rank(_p, i, *this);
676  ranks.push_back(rank);
677  }
678 
679  // determine the dram actual capacity from the DRAM config in Mbytes
680  uint64_t deviceCapacity = deviceSize / (1024 * 1024) * devicesPerRank *
682 
683  uint64_t capacity = 1ULL << ceilLog2(AbstractMemory::size());
684 
685  DPRINTF(DRAM, "Memory capacity %lld (%lld) bytes\n", capacity,
687 
688  // if actual DRAM size does not match memory capacity in system warn!
689  if (deviceCapacity != capacity / (1024 * 1024))
690  warn("DRAM device capacity (%d Mbytes) does not match the "
691  "address range assigned (%d Mbytes)\n", deviceCapacity,
692  capacity / (1024 * 1024));
693 
694  DPRINTF(DRAM, "Row buffer size %d bytes with %d bursts per row buffer\n",
696 
698 
699  // some basic sanity checks
700  if (tREFI <= tRP || tREFI <= tRFC) {
701  fatal("tREFI (%d) must be larger than tRP (%d) and tRFC (%d)\n",
702  tREFI, tRP, tRFC);
703  }
704 
705  // basic bank group architecture checks ->
706  if (bankGroupArch) {
707  // must have at least one bank per bank group
709  fatal("banks per rank (%d) must be equal to or larger than "
710  "banks groups per rank (%d)\n",
712  }
713  // must have same number of banks in each bank group
714  if ((banksPerRank % bankGroupsPerRank) != 0) {
715  fatal("Banks per rank (%d) must be evenly divisible by bank "
716  "groups per rank (%d) for equal banks per bank group\n",
718  }
719  // tCCD_L should be greater than minimal, back-to-back burst delay
720  if (tCCD_L <= tBURST) {
721  fatal("tCCD_L (%d) should be larger than the minimum bus delay "
722  "(%d) when bank groups per rank (%d) is greater than 1\n",
724  }
725  // tCCD_L_WR should be greater than minimal, back-to-back burst delay
726  if (tCCD_L_WR <= tBURST) {
727  fatal("tCCD_L_WR (%d) should be larger than the minimum bus delay "
728  " (%d) when bank groups per rank (%d) is greater than 1\n",
730  }
731  // tRRD_L is greater than minimal, same bank group ACT-to-ACT delay
732  // some datasheets might specify it equal to tRRD
733  if (tRRD_L < tRRD) {
734  fatal("tRRD_L (%d) should be larger than tRRD (%d) when "
735  "bank groups per rank (%d) is greater than 1\n",
737  }
738  }
739 }
740 
741 void
743 {
745 
746  // a bit of sanity checks on the interleaving, save it for here to
747  // ensure that the system pointer is initialised
748  if (range.interleaved()) {
749  if (addrMapping == enums::RoRaBaChCo) {
750  if (rowBufferSize != range.granularity()) {
751  fatal("Channel interleaving of %s doesn't match RoRaBaChCo "
752  "address map\n", name());
753  }
754  } else if (addrMapping == enums::RoRaBaCoCh ||
755  addrMapping == enums::RoCoRaBaCh) {
756  // for the interleavings with channel bits in the bottom,
757  // if the system uses a channel striping granularity that
758  // is larger than the DRAM burst size, then map the
759  // sequential accesses within a stripe to a number of
760  // columns in the DRAM, effectively placing some of the
761  // lower-order column bits as the least-significant bits
762  // of the address (above the ones denoting the burst size)
763  assert(burstsPerStripe >= 1);
764 
765  // channel striping has to be done at a granularity that
766  // is equal or larger to a cache line
767  if (system()->cacheLineSize() > range.granularity()) {
768  fatal("Channel interleaving of %s must be at least as large "
769  "as the cache line size\n", name());
770  }
771 
772  // ...and equal or smaller than the row-buffer size
773  if (rowBufferSize < range.granularity()) {
774  fatal("Channel interleaving of %s must be at most as large "
775  "as the row-buffer size\n", name());
776  }
777  // this is essentially the check above, so just to be sure
779  }
780  }
781 }
782 
783 void
785 {
786  if (system()->isTimingMode()) {
787  // timestamp offset should be in clock cycles for DRAMPower
789 
790  for (auto r : ranks) {
791  r->startup(curTick() + tREFI - tRP);
792  }
793  }
794 }
795 
796 bool
797 DRAMInterface::isBusy(bool read_queue_empty, bool all_writes_nvm)
798 {
799  int busy_ranks = 0;
800  for (auto r : ranks) {
801  if (!r->inRefIdleState()) {
802  if (r->pwrState != PWR_SREF) {
803  // rank is busy refreshing
804  DPRINTF(DRAMState, "Rank %d is not available\n", r->rank);
805  busy_ranks++;
806 
807  // let the rank know that if it was waiting to drain, it
808  // is now done and ready to proceed
809  r->checkDrainDone();
810  }
811 
812  // check if we were in self-refresh and haven't started
813  // to transition out
814  if ((r->pwrState == PWR_SREF) && r->inLowPowerState) {
815  DPRINTF(DRAMState, "Rank %d is in self-refresh\n", r->rank);
816  // if we have commands queued to this rank and we don't have
817  // a minimum number of active commands enqueued,
818  // exit self-refresh
819  if (r->forceSelfRefreshExit()) {
820  DPRINTF(DRAMState, "rank %d was in self refresh and"
821  " should wake up\n", r->rank);
822  //wake up from self-refresh
823  r->scheduleWakeUpEvent(tXS);
824  // things are brought back into action once a refresh is
825  // performed after self-refresh
826  // continue with selection for other ranks
827  }
828  }
829  }
830  }
831  return (busy_ranks == ranksPerChannel);
832 }
833 
834 MemPacket*
836  unsigned size, bool is_read, uint8_t pseudo_channel)
837 {
838  // decode the address based on the address mapping scheme, with
839  // Ro, Ra, Co, Ba and Ch denoting row, rank, column, bank and
840  // channel, respectively
841  uint8_t rank;
842  uint8_t bank;
843  // use a 64-bit unsigned during the computations as the row is
844  // always the top bits, and check before creating the packet
845  uint64_t row;
846 
847  // Get packed address, starting at 0
848  Addr addr = getCtrlAddr(pkt_addr);
849 
850  // truncate the address to a memory burst, which makes it unique to
851  // a specific buffer, row, bank, rank and channel
852  addr = addr / burstSize;
853 
854  // we have removed the lowest order address bits that denote the
855  // position within the column
856  if (addrMapping == enums::RoRaBaChCo || addrMapping == enums::RoRaBaCoCh) {
857  // the lowest order bits denote the column to ensure that
858  // sequential cache lines occupy the same row
860 
861  // after the channel bits, get the bank bits to interleave
862  // over the banks
863  bank = addr % banksPerRank;
864  addr = addr / banksPerRank;
865 
866  // after the bank, we get the rank bits which thus interleaves
867  // over the ranks
868  rank = addr % ranksPerChannel;
870 
871  // lastly, get the row bits, no need to remove them from addr
872  row = addr % rowsPerBank;
873  } else if (addrMapping == enums::RoCoRaBaCh) {
874  // with emerging technologies, could have small page size with
875  // interleaving granularity greater than row buffer
877  // remove column bits which are a subset of burstsPerStripe
879  } else {
880  // remove lower column bits below channel bits
882  }
883 
884  // start with the bank bits, as this provides the maximum
885  // opportunity for parallelism between requests
886  bank = addr % banksPerRank;
887  addr = addr / banksPerRank;
888 
889  // next get the rank bits
890  rank = addr % ranksPerChannel;
892 
893  // next, the higher-order column bites
896  }
897 
898  // lastly, get the row bits, no need to remove them from addr
899  row = addr % rowsPerBank;
900  } else
901  panic("Unknown address mapping policy chosen!");
902 
903  assert(rank < ranksPerChannel);
904  assert(bank < banksPerRank);
905  assert(row < rowsPerBank);
906  assert(row < Bank::NO_ROW);
907 
908  DPRINTF(DRAM, "Address: %#x Rank %d Bank %d Row %d\n",
909  pkt_addr, rank, bank, row);
910 
911  // create the corresponding memory packet with the entry time and
912  // ready time set to the current tick, the latter will be updated
913  // later
914  uint16_t bank_id = banksPerRank * rank + bank;
915 
916  return new MemPacket(pkt, is_read, true, pseudo_channel, rank, bank, row,
917  bank_id, pkt_addr, size);
918 }
919 
920 void DRAMInterface::setupRank(const uint8_t rank, const bool is_read)
921 {
922  // increment entry count of the rank based on packet type
923  if (is_read) {
924  ++ranks[rank]->readEntries;
925  } else {
926  ++ranks[rank]->writeEntries;
927  }
928 }
929 
930 void
932 {
933  Rank& rank_ref = *ranks[rank];
934 
935  // if a read has reached its ready-time, decrement the number of reads
936  // At this point the packet has been handled and there is a possibility
937  // to switch to low-power mode if no other packet is available
938  --rank_ref.readEntries;
939  DPRINTF(DRAM, "number of read entries for rank %d is %d\n",
940  rank, rank_ref.readEntries);
941 
942  // counter should at least indicate one outstanding request
943  // for this read
944  assert(rank_ref.outstandingEvents > 0);
945  // read response received, decrement count
946  --rank_ref.outstandingEvents;
947 
948  // at this moment should not have transitioned to a low-power state
949  assert((rank_ref.pwrState != PWR_SREF) &&
950  (rank_ref.pwrState != PWR_PRE_PDN) &&
951  (rank_ref.pwrState != PWR_ACT_PDN));
952 
953  // track if this is the last packet before idling
954  // and that there are no outstanding commands to this rank
955  if (rank_ref.isQueueEmpty() && rank_ref.outstandingEvents == 0 &&
956  rank_ref.inRefIdleState() && enableDRAMPowerdown) {
957  // verify that there are no events scheduled
958  assert(!rank_ref.activateEvent.scheduled());
959  assert(!rank_ref.prechargeEvent.scheduled());
960 
961  // if coming from active state, schedule power event to
962  // active power-down else go to precharge power-down
963  DPRINTF(DRAMState, "Rank %d sleep at tick %d; current power state is "
964  "%d\n", rank, curTick(), rank_ref.pwrState);
965 
966  // default to ACT power-down unless already in IDLE state
967  // could be in IDLE if PRE issued before data returned
968  PowerState next_pwr_state = PWR_ACT_PDN;
969  if (rank_ref.pwrState == PWR_IDLE) {
970  next_pwr_state = PWR_PRE_PDN;
971  }
972 
973  rank_ref.powerDownSleep(next_pwr_state, curTick());
974  }
975 }
976 
977 void
979 {
980  Rank& rank_ref = *ranks[rank];
981 
982  if ((rank_ref.refreshState == REF_PRE) &&
983  !rank_ref.prechargeEvent.scheduled()) {
984  // kick the refresh event loop into action again if banks already
985  // closed and just waiting for read to complete
986  schedule(rank_ref.refreshEvent, curTick());
987  }
988 }
989 
990 void
992 {
993  // also need to kick off events to exit self-refresh
994  for (auto r : ranks) {
995  // force self-refresh exit, which in turn will issue auto-refresh
996  if (r->pwrState == PWR_SREF) {
997  DPRINTF(DRAM,"Rank%d: Forcing self-refresh wakeup in drain\n",
998  r->rank);
999  r->scheduleWakeUpEvent(tXS);
1000  }
1001  }
1002 }
1003 
1004 bool
1006 {
1007  // true until proven false
1008  bool all_ranks_drained = true;
1009  for (auto r : ranks) {
1010  // then verify that the power state is IDLE ensuring all banks are
1011  // closed and rank is not in a low power state. Also verify that rank
1012  // is idle from a refresh point of view.
1013  all_ranks_drained = r->inPwrIdleState() && r->inRefIdleState() &&
1014  all_ranks_drained;
1015  }
1016  return all_ranks_drained;
1017 }
1018 
1019 void
1021 {
1022  for (auto r : ranks) {
1023  r->suspend();
1024  }
1025 }
1026 
1029  Tick min_col_at) const
1030 {
1031  Tick min_act_at = MaxTick;
1032  std::vector<uint32_t> bank_mask(ranksPerChannel, 0);
1033 
1034  // Flag condition when burst can issue back-to-back with previous burst
1035  bool found_seamless_bank = false;
1036 
1037  // Flag condition when bank can be opened without incurring additional
1038  // delay on the data bus
1039  bool hidden_bank_prep = false;
1040 
1041  // determine if we have queued transactions targetting the
1042  // bank in question
1043  std::vector<bool> got_waiting(ranksPerChannel * banksPerRank, false);
1044  for (const auto& p : queue) {
1045  if (p->pseudoChannel != pseudoChannel)
1046  continue;
1047  if (p->isDram() && ranks[p->rank]->inRefIdleState())
1048  got_waiting[p->bankId] = true;
1049  }
1050 
1051  // Find command with optimal bank timing
1052  // Will prioritize commands that can issue seamlessly.
1053  for (int i = 0; i < ranksPerChannel; i++) {
1054  for (int j = 0; j < banksPerRank; j++) {
1055  uint16_t bank_id = i * banksPerRank + j;
1056 
1057  // if we have waiting requests for the bank, and it is
1058  // amongst the first available, update the mask
1059  if (got_waiting[bank_id]) {
1060  // make sure this rank is not currently refreshing.
1061  assert(ranks[i]->inRefIdleState());
1062  // simplistic approximation of when the bank can issue
1063  // an activate, ignoring any rank-to-rank switching
1064  // cost in this calculation
1065  Tick act_at = ranks[i]->banks[j].openRow == Bank::NO_ROW ?
1066  std::max(ranks[i]->banks[j].actAllowedAt, curTick()) :
1067  std::max(ranks[i]->banks[j].preAllowedAt, curTick()) + tRP;
1068 
1069  // latest Tick for which ACT can occur without
1070  // incurring additoinal delay on the data bus
1071  const Tick tRCD = ctrl->inReadBusState(false) ?
1072  tRCD_RD : tRCD_WR;
1073  const Tick hidden_act_max =
1074  std::max(min_col_at - tRCD, curTick());
1075 
1076  // When is the earliest the R/W burst can issue?
1077  const Tick col_allowed_at = ctrl->inReadBusState(false) ?
1078  ranks[i]->banks[j].rdAllowedAt :
1079  ranks[i]->banks[j].wrAllowedAt;
1080  Tick col_at = std::max(col_allowed_at, act_at + tRCD);
1081 
1082  // bank can issue burst back-to-back (seamlessly) with
1083  // previous burst
1084  bool new_seamless_bank = col_at <= min_col_at;
1085 
1086  // if we found a new seamless bank or we have no
1087  // seamless banks, and got a bank with an earlier
1088  // activate time, it should be added to the bit mask
1089  if (new_seamless_bank ||
1090  (!found_seamless_bank && act_at <= min_act_at)) {
1091  // if we did not have a seamless bank before, and
1092  // we do now, reset the bank mask, also reset it
1093  // if we have not yet found a seamless bank and
1094  // the activate time is smaller than what we have
1095  // seen so far
1096  if (!found_seamless_bank &&
1097  (new_seamless_bank || act_at < min_act_at)) {
1098  std::fill(bank_mask.begin(), bank_mask.end(), 0);
1099  }
1100 
1101  found_seamless_bank |= new_seamless_bank;
1102 
1103  // ACT can occur 'behind the scenes'
1104  hidden_bank_prep = act_at <= hidden_act_max;
1105 
1106  // set the bit corresponding to the available bank
1107  replaceBits(bank_mask[i], j, j, 1);
1108  min_act_at = act_at;
1109  }
1110  }
1111  }
1112  }
1113 
1114  return std::make_pair(bank_mask, hidden_bank_prep);
1115 }
1116 
1117 DRAMInterface::Rank::Rank(const DRAMInterfaceParams &_p,
1118  int _rank, DRAMInterface& _dram)
1119  : EventManager(&_dram), dram(_dram),
1120  pwrStateTrans(PWR_IDLE), pwrStatePostRefresh(PWR_IDLE),
1121  pwrStateTick(0), refreshDueAt(0), pwrState(PWR_IDLE),
1122  refreshState(REF_IDLE), inLowPowerState(false), rank(_rank),
1123  readEntries(0), writeEntries(0), outstandingEvents(0),
1124  wakeUpAllowedAt(0), power(_p, false), banks(_p.banks_per_rank),
1125  numBanksActive(0), actTicks(_p.activation_limit, 0), lastBurstTick(0),
1126  writeDoneEvent([this]{ processWriteDoneEvent(); }, name()),
1127  activateEvent([this]{ processActivateEvent(); }, name()),
1128  prechargeEvent([this]{ processPrechargeEvent(); }, name()),
1129  refreshEvent([this]{ processRefreshEvent(); }, name()),
1130  powerEvent([this]{ processPowerEvent(); }, name()),
1131  wakeUpEvent([this]{ processWakeUpEvent(); }, name()),
1132  stats(_dram, *this)
1133 {
1134  for (int b = 0; b < _p.banks_per_rank; b++) {
1135  banks[b].bank = b;
1136  // GDDR addressing of banks to BG is linear.
1137  // Here we assume that all DRAM generations address bank groups as
1138  // follows:
1139  if (_p.bank_groups_per_rank > 0) {
1140  // Simply assign lower bits to bank group in order to
1141  // rotate across bank groups as banks are incremented
1142  // e.g. with 4 banks per bank group and 16 banks total:
1143  // banks 0,4,8,12 are in bank group 0
1144  // banks 1,5,9,13 are in bank group 1
1145  // banks 2,6,10,14 are in bank group 2
1146  // banks 3,7,11,15 are in bank group 3
1147  banks[b].bankgr = b % _p.bank_groups_per_rank;
1148  } else {
1149  // No bank groups; simply assign to bank number
1150  banks[b].bankgr = b;
1151  }
1152  }
1153 }
1154 
1155 void
1157 {
1158  assert(ref_tick > curTick());
1159 
1160  pwrStateTick = curTick();
1161 
1162  // kick off the refresh, and give ourselves enough time to
1163  // precharge
1164  schedule(refreshEvent, ref_tick);
1165 }
1166 
1167 void
1169 {
1170  deschedule(refreshEvent);
1171 
1172  // Update the stats
1173  updatePowerStats();
1174 
1175  // don't automatically transition back to LP state after next REF
1176  pwrStatePostRefresh = PWR_IDLE;
1177 }
1178 
1179 bool
1181 {
1182  // check commmands in Q based on current bus direction
1183  bool no_queued_cmds = (dram.ctrl->inReadBusState(true) &&
1184  (readEntries == 0))
1185  || (dram.ctrl->inWriteBusState(true) &&
1186  (writeEntries == 0));
1187  return no_queued_cmds;
1188 }
1189 
1190 void
1192 {
1193  // if this rank was waiting to drain it is now able to proceed to
1194  // precharge
1195  if (refreshState == REF_DRAIN) {
1196  DPRINTF(DRAM, "Refresh drain done, now precharging\n");
1197 
1198  refreshState = REF_PD_EXIT;
1199 
1200  // hand control back to the refresh event loop
1201  schedule(refreshEvent, curTick());
1202  }
1203 }
1204 
1205 void
1207 {
1208  // at the moment sort the list of commands and update the counters
1209  // for DRAMPower libray when doing a refresh
1210  sort(cmdList.begin(), cmdList.end(), DRAMInterface::sortTime);
1211 
1212  auto next_iter = cmdList.begin();
1213  // push to commands to DRAMPower
1214  for ( ; next_iter != cmdList.end() ; ++next_iter) {
1215  Command cmd = *next_iter;
1216  if (cmd.timeStamp <= curTick()) {
1217  // Move all commands at or before curTick to DRAMPower
1218  power.powerlib.doCommand(cmd.type, cmd.bank,
1219  divCeil(cmd.timeStamp, dram.tCK) -
1220  dram.timeStampOffset);
1221  } else {
1222  // done - found all commands at or before curTick()
1223  // next_iter references the 1st command after curTick
1224  break;
1225  }
1226  }
1227  // reset cmdList to only contain commands after curTick
1228  // if there are no commands after curTick, updated cmdList will be empty
1229  // in this case, next_iter is cmdList.end()
1230  cmdList.assign(next_iter, cmdList.end());
1231 }
1232 
1233 void
1235 {
1236  // we should transition to the active state as soon as any bank is active
1237  if (pwrState != PWR_ACT)
1238  // note that at this point numBanksActive could be back at
1239  // zero again due to a precharge scheduled in the future
1240  schedulePowerEvent(PWR_ACT, curTick());
1241 }
1242 
1243 void
1245 {
1246  // counter should at least indicate one outstanding request
1247  // for this precharge
1248  assert(outstandingEvents > 0);
1249  // precharge complete, decrement count
1250  --outstandingEvents;
1251 
1252  // if we reached zero, then special conditions apply as we track
1253  // if all banks are precharged for the power models
1254  if (numBanksActive == 0) {
1255  // no reads to this rank in the Q and no pending
1256  // RD/WR or refresh commands
1257  if (isQueueEmpty() && outstandingEvents == 0 &&
1258  dram.enableDRAMPowerdown) {
1259  // should still be in ACT state since bank still open
1260  assert(pwrState == PWR_ACT);
1261 
1262  // All banks closed - switch to precharge power down state.
1263  DPRINTF(DRAMState, "Rank %d sleep at tick %d\n",
1264  rank, curTick());
1265  powerDownSleep(PWR_PRE_PDN, curTick());
1266  } else {
1267  // we should transition to the idle state when the last bank
1268  // is precharged
1269  schedulePowerEvent(PWR_IDLE, curTick());
1270  }
1271  }
1272 }
1273 
1274 void
1276 {
1277  // counter should at least indicate one outstanding request
1278  // for this write
1279  assert(outstandingEvents > 0);
1280  // Write transfer on bus has completed
1281  // decrement per rank counter
1282  --outstandingEvents;
1283 }
1284 
1285 void
1287 {
1288  // when first preparing the refresh, remember when it was due
1289  if ((refreshState == REF_IDLE) || (refreshState == REF_SREF_EXIT)) {
1290  // remember when the refresh is due
1291  refreshDueAt = curTick();
1292 
1293  // proceed to drain
1294  refreshState = REF_DRAIN;
1295 
1296  // make nonzero while refresh is pending to ensure
1297  // power down and self-refresh are not entered
1298  ++outstandingEvents;
1299 
1300  DPRINTF(DRAM, "Refresh due\n");
1301  }
1302 
1303  // let any scheduled read or write to the same rank go ahead,
1304  // after which it will
1305  // hand control back to this event loop
1306  if (refreshState == REF_DRAIN) {
1307  // if a request is at the moment being handled and this request is
1308  // accessing the current rank then wait for it to finish
1309  if ((rank == dram.activeRank)
1310  && (dram.ctrl->requestEventScheduled(dram.pseudoChannel))) {
1311  // hand control over to the request loop until it is
1312  // evaluated next
1313  DPRINTF(DRAM, "Refresh awaiting draining\n");
1314  return;
1315  } else {
1316  refreshState = REF_PD_EXIT;
1317  }
1318  }
1319 
1320  // at this point, ensure that rank is not in a power-down state
1321  if (refreshState == REF_PD_EXIT) {
1322  // if rank was sleeping and we have't started exit process,
1323  // wake-up for refresh
1324  if (inLowPowerState) {
1325  DPRINTF(DRAM, "Wake Up for refresh\n");
1326  // save state and return after refresh completes
1327  scheduleWakeUpEvent(dram.tXP);
1328  return;
1329  } else {
1330  refreshState = REF_PRE;
1331  }
1332  }
1333 
1334  // at this point, ensure that all banks are precharged
1335  if (refreshState == REF_PRE) {
1336  // precharge any active bank
1337  if (numBanksActive != 0) {
1338  // at the moment, we use a precharge all even if there is
1339  // only a single bank open
1340  DPRINTF(DRAM, "Precharging all\n");
1341 
1342  // first determine when we can precharge
1343  Tick pre_at = curTick();
1344 
1345  for (auto &b : banks) {
1346  // respect both causality and any existing bank
1347  // constraints, some banks could already have a
1348  // (auto) precharge scheduled
1349  pre_at = std::max(b.preAllowedAt, pre_at);
1350  }
1351 
1352  // make sure all banks per rank are precharged, and for those that
1353  // already are, update their availability
1354  Tick act_allowed_at = pre_at + dram.tRP;
1355 
1356  for (auto &b : banks) {
1357  if (b.openRow != Bank::NO_ROW) {
1358  dram.prechargeBank(*this, b, pre_at, true, false);
1359  } else {
1360  b.actAllowedAt = std::max(b.actAllowedAt, act_allowed_at);
1361  b.preAllowedAt = std::max(b.preAllowedAt, pre_at);
1362  }
1363  }
1364 
1365  // precharge all banks in rank
1366  cmdList.push_back(Command(MemCommand::PREA, 0, pre_at));
1367 
1368  DPRINTF(DRAMPower, "%llu,PREA,0,%d\n",
1369  divCeil(pre_at, dram.tCK) -
1370  dram.timeStampOffset, rank);
1371  } else if ((pwrState == PWR_IDLE) && (outstandingEvents == 1)) {
1372  // Banks are closed, have transitioned to IDLE state, and
1373  // no outstanding ACT,RD/WR,Auto-PRE sequence scheduled
1374  DPRINTF(DRAM, "All banks already precharged, starting refresh\n");
1375 
1376  // go ahead and kick the power state machine into gear since
1377  // we are already idle
1378  schedulePowerEvent(PWR_REF, curTick());
1379  } else {
1380  // banks state is closed but haven't transitioned pwrState to IDLE
1381  // or have outstanding ACT,RD/WR,Auto-PRE sequence scheduled
1382  // should have outstanding precharge or read response event
1383  assert(prechargeEvent.scheduled() ||
1384  dram.ctrl->respondEventScheduled(dram.pseudoChannel));
1385  // will start refresh when pwrState transitions to IDLE
1386  }
1387 
1388  assert(numBanksActive == 0);
1389 
1390  // wait for all banks to be precharged or read to complete
1391  // When precharge commands are done, power state machine will
1392  // transition to the idle state, and automatically move to a
1393  // refresh, at that point it will also call this method to get
1394  // the refresh event loop going again
1395  // Similarly, when read response completes, if all banks are
1396  // precharged, will call this method to get loop re-started
1397  return;
1398  }
1399 
1400  // last but not least we perform the actual refresh
1401  if (refreshState == REF_START) {
1402  // should never get here with any banks active
1403  assert(numBanksActive == 0);
1404  assert(pwrState == PWR_REF);
1405 
1406  Tick ref_done_at = curTick() + dram.tRFC;
1407 
1408  for (auto &b : banks) {
1409  b.actAllowedAt = ref_done_at;
1410  }
1411 
1412  // at the moment this affects all ranks
1413  cmdList.push_back(Command(MemCommand::REF, 0, curTick()));
1414 
1415  // Update the stats
1416  updatePowerStats();
1417 
1418  DPRINTF(DRAMPower, "%llu,REF,0,%d\n", divCeil(curTick(), dram.tCK) -
1419  dram.timeStampOffset, rank);
1420 
1421  // Update for next refresh
1422  refreshDueAt += dram.tREFI;
1423 
1424  // make sure we did not wait so long that we cannot make up
1425  // for it
1426  if (refreshDueAt < ref_done_at) {
1427  fatal("Refresh was delayed so long we cannot catch up\n");
1428  }
1429 
1430  // Run the refresh and schedule event to transition power states
1431  // when refresh completes
1432  refreshState = REF_RUN;
1433  schedule(refreshEvent, ref_done_at);
1434  return;
1435  }
1436 
1437  if (refreshState == REF_RUN) {
1438  // should never get here with any banks active
1439  assert(numBanksActive == 0);
1440  assert(pwrState == PWR_REF);
1441 
1442  assert(!powerEvent.scheduled());
1443 
1444  if ((dram.ctrl->drainState() == DrainState::Draining) ||
1445  (dram.ctrl->drainState() == DrainState::Drained)) {
1446  // if draining, do not re-enter low-power mode.
1447  // simply go to IDLE and wait
1448  schedulePowerEvent(PWR_IDLE, curTick());
1449  } else {
1450  // At the moment, we sleep when the refresh ends and wait to be
1451  // woken up again if previously in a low-power state.
1452  if (pwrStatePostRefresh != PWR_IDLE) {
1453  // power State should be power Refresh
1454  assert(pwrState == PWR_REF);
1455  DPRINTF(DRAMState, "Rank %d sleeping after refresh and was in "
1456  "power state %d before refreshing\n", rank,
1457  pwrStatePostRefresh);
1458  powerDownSleep(pwrState, curTick());
1459 
1460  // Force PRE power-down if there are no outstanding commands
1461  // in Q after refresh.
1462  } else if (isQueueEmpty() && dram.enableDRAMPowerdown) {
1463  // still have refresh event outstanding but there should
1464  // be no other events outstanding
1465  assert(outstandingEvents == 1);
1466  DPRINTF(DRAMState, "Rank %d sleeping after refresh but was NOT"
1467  " in a low power state before refreshing\n", rank);
1468  powerDownSleep(PWR_PRE_PDN, curTick());
1469 
1470  } else {
1471  // move to the idle power state once the refresh is done, this
1472  // will also move the refresh state machine to the refresh
1473  // idle state
1474  schedulePowerEvent(PWR_IDLE, curTick());
1475  }
1476  }
1477 
1478  // At this point, we have completed the current refresh.
1479  // In the SREF bypass case, we do not get to this state in the
1480  // refresh STM and therefore can always schedule next event.
1481  // Compensate for the delay in actually performing the refresh
1482  // when scheduling the next one
1483  schedule(refreshEvent, refreshDueAt - dram.tRP);
1484 
1485  DPRINTF(DRAMState, "Refresh done at %llu and next refresh"
1486  " at %llu\n", curTick(), refreshDueAt);
1487  }
1488 }
1489 
1490 void
1492 {
1493  // respect causality
1494  assert(tick >= curTick());
1495 
1496  if (!powerEvent.scheduled()) {
1497  DPRINTF(DRAMState, "Scheduling power event at %llu to state %d\n",
1498  tick, pwr_state);
1499 
1500  // insert the new transition
1501  pwrStateTrans = pwr_state;
1502 
1503  schedule(powerEvent, tick);
1504  } else {
1505  panic("Scheduled power event at %llu to state %d, "
1506  "with scheduled event at %llu to %d\n", tick, pwr_state,
1507  powerEvent.when(), pwrStateTrans);
1508  }
1509 }
1510 
1511 void
1513 {
1514  // if low power state is active low, schedule to active low power state.
1515  // in reality tCKE is needed to enter active low power. This is neglected
1516  // here and could be added in the future.
1517  if (pwr_state == PWR_ACT_PDN) {
1518  schedulePowerEvent(pwr_state, tick);
1519  // push command to DRAMPower
1520  cmdList.push_back(Command(MemCommand::PDN_F_ACT, 0, tick));
1521  DPRINTF(DRAMPower, "%llu,PDN_F_ACT,0,%d\n", divCeil(tick,
1522  dram.tCK) - dram.timeStampOffset, rank);
1523  } else if (pwr_state == PWR_PRE_PDN) {
1524  // if low power state is precharge low, schedule to precharge low
1525  // power state. In reality tCKE is needed to enter active low power.
1526  // This is neglected here.
1527  schedulePowerEvent(pwr_state, tick);
1528  //push Command to DRAMPower
1529  cmdList.push_back(Command(MemCommand::PDN_F_PRE, 0, tick));
1530  DPRINTF(DRAMPower, "%llu,PDN_F_PRE,0,%d\n", divCeil(tick,
1531  dram.tCK) - dram.timeStampOffset, rank);
1532  } else if (pwr_state == PWR_REF) {
1533  // if a refresh just occurred
1534  // transition to PRE_PDN now that all banks are closed
1535  // precharge power down requires tCKE to enter. For simplicity
1536  // this is not considered.
1537  schedulePowerEvent(PWR_PRE_PDN, tick);
1538  //push Command to DRAMPower
1539  cmdList.push_back(Command(MemCommand::PDN_F_PRE, 0, tick));
1540  DPRINTF(DRAMPower, "%llu,PDN_F_PRE,0,%d\n", divCeil(tick,
1541  dram.tCK) - dram.timeStampOffset, rank);
1542  } else if (pwr_state == PWR_SREF) {
1543  // should only enter SREF after PRE-PD wakeup to do a refresh
1544  assert(pwrStatePostRefresh == PWR_PRE_PDN);
1545  // self refresh requires time tCKESR to enter. For simplicity,
1546  // this is not considered.
1547  schedulePowerEvent(PWR_SREF, tick);
1548  // push Command to DRAMPower
1549  cmdList.push_back(Command(MemCommand::SREN, 0, tick));
1550  DPRINTF(DRAMPower, "%llu,SREN,0,%d\n", divCeil(tick,
1551  dram.tCK) - dram.timeStampOffset, rank);
1552  }
1553  // Ensure that we don't power-down and back up in same tick
1554  // Once we commit to PD entry, do it and wait for at least 1tCK
1555  // This could be replaced with tCKE if/when that is added to the model
1556  wakeUpAllowedAt = tick + dram.tCK;
1557 
1558  // Transitioning to a low power state, set flag
1559  inLowPowerState = true;
1560 }
1561 
1562 void
1564 {
1565  Tick wake_up_tick = std::max(curTick(), wakeUpAllowedAt);
1566 
1567  DPRINTF(DRAMState, "Scheduling wake-up for rank %d at tick %d\n",
1568  rank, wake_up_tick);
1569 
1570  // if waking for refresh, hold previous state
1571  // else reset state back to IDLE
1572  if (refreshState == REF_PD_EXIT) {
1573  pwrStatePostRefresh = pwrState;
1574  } else {
1575  // don't automatically transition back to LP state after next REF
1576  pwrStatePostRefresh = PWR_IDLE;
1577  }
1578 
1579  // schedule wake-up with event to ensure entry has completed before
1580  // we try to wake-up
1581  schedule(wakeUpEvent, wake_up_tick);
1582 
1583  for (auto &b : banks) {
1584  // respect both causality and any existing bank
1585  // constraints, some banks could already have a
1586  // (auto) precharge scheduled
1587  b.wrAllowedAt = std::max(wake_up_tick + exit_delay, b.wrAllowedAt);
1588  b.rdAllowedAt = std::max(wake_up_tick + exit_delay, b.rdAllowedAt);
1589  b.preAllowedAt = std::max(wake_up_tick + exit_delay, b.preAllowedAt);
1590  b.actAllowedAt = std::max(wake_up_tick + exit_delay, b.actAllowedAt);
1591  }
1592  // Transitioning out of low power state, clear flag
1593  inLowPowerState = false;
1594 
1595  // push to DRAMPower
1596  // use pwrStateTrans for cases where we have a power event scheduled
1597  // to enter low power that has not yet been processed
1598  if (pwrStateTrans == PWR_ACT_PDN) {
1599  cmdList.push_back(Command(MemCommand::PUP_ACT, 0, wake_up_tick));
1600  DPRINTF(DRAMPower, "%llu,PUP_ACT,0,%d\n", divCeil(wake_up_tick,
1601  dram.tCK) - dram.timeStampOffset, rank);
1602 
1603  } else if (pwrStateTrans == PWR_PRE_PDN) {
1604  cmdList.push_back(Command(MemCommand::PUP_PRE, 0, wake_up_tick));
1605  DPRINTF(DRAMPower, "%llu,PUP_PRE,0,%d\n", divCeil(wake_up_tick,
1606  dram.tCK) - dram.timeStampOffset, rank);
1607  } else if (pwrStateTrans == PWR_SREF) {
1608  cmdList.push_back(Command(MemCommand::SREX, 0, wake_up_tick));
1609  DPRINTF(DRAMPower, "%llu,SREX,0,%d\n", divCeil(wake_up_tick,
1610  dram.tCK) - dram.timeStampOffset, rank);
1611  }
1612 }
1613 
1614 void
1616 {
1617  // Should be in a power-down or self-refresh state
1618  assert((pwrState == PWR_ACT_PDN) || (pwrState == PWR_PRE_PDN) ||
1619  (pwrState == PWR_SREF));
1620 
1621  // Check current state to determine transition state
1622  if (pwrState == PWR_ACT_PDN) {
1623  // banks still open, transition to PWR_ACT
1624  schedulePowerEvent(PWR_ACT, curTick());
1625  } else {
1626  // transitioning from a precharge power-down or self-refresh state
1627  // banks are closed - transition to PWR_IDLE
1628  schedulePowerEvent(PWR_IDLE, curTick());
1629  }
1630 }
1631 
1632 void
1634 {
1635  assert(curTick() >= pwrStateTick);
1636  // remember where we were, and for how long
1637  Tick duration = curTick() - pwrStateTick;
1638  PowerState prev_state = pwrState;
1639 
1640  // update the accounting
1641  stats.pwrStateTime[prev_state] += duration;
1642 
1643  // track to total idle time
1644  if ((prev_state == PWR_PRE_PDN) || (prev_state == PWR_ACT_PDN) ||
1645  (prev_state == PWR_SREF)) {
1646  stats.totalIdleTime += duration;
1647  }
1648 
1649  pwrState = pwrStateTrans;
1650  pwrStateTick = curTick();
1651 
1652  // if rank was refreshing, make sure to start scheduling requests again
1653  if (prev_state == PWR_REF) {
1654  // bus IDLED prior to REF
1655  // counter should be one for refresh command only
1656  assert(outstandingEvents == 1);
1657  // REF complete, decrement count and go back to IDLE
1658  --outstandingEvents;
1659  refreshState = REF_IDLE;
1660 
1661  DPRINTF(DRAMState, "Was refreshing for %llu ticks\n", duration);
1662  // if moving back to power-down after refresh
1663  if (pwrState != PWR_IDLE) {
1664  assert(pwrState == PWR_PRE_PDN);
1665  DPRINTF(DRAMState, "Switching to power down state after refreshing"
1666  " rank %d at %llu tick\n", rank, curTick());
1667  }
1668 
1669  // completed refresh event, ensure next request is scheduled
1670  if (!(dram.ctrl->requestEventScheduled(dram.pseudoChannel))) {
1671  DPRINTF(DRAM, "Scheduling next request after refreshing"
1672  " rank %d\n", rank);
1673  dram.ctrl->restartScheduler(curTick(), dram.pseudoChannel);
1674  }
1675  }
1676 
1677  if ((pwrState == PWR_ACT) && (refreshState == REF_PD_EXIT)) {
1678  // have exited ACT PD
1679  assert(prev_state == PWR_ACT_PDN);
1680 
1681  // go back to REF event and close banks
1682  refreshState = REF_PRE;
1683  schedule(refreshEvent, curTick());
1684  } else if (pwrState == PWR_IDLE) {
1685  DPRINTF(DRAMState, "All banks precharged\n");
1686  if (prev_state == PWR_SREF) {
1687  // set refresh state to REF_SREF_EXIT, ensuring inRefIdleState
1688  // continues to return false during tXS after SREF exit
1689  // Schedule a refresh which kicks things back into action
1690  // when it finishes
1691  refreshState = REF_SREF_EXIT;
1692  schedule(refreshEvent, curTick() + dram.tXS);
1693  } else {
1694  // if we have a pending refresh, and are now moving to
1695  // the idle state, directly transition to, or schedule refresh
1696  if ((refreshState == REF_PRE) || (refreshState == REF_PD_EXIT)) {
1697  // ensure refresh is restarted only after final PRE command.
1698  // do not restart refresh if controller is in an intermediate
1699  // state, after PRE_PDN exit, when banks are IDLE but an
1700  // ACT is scheduled.
1701  if (!activateEvent.scheduled()) {
1702  // there should be nothing waiting at this point
1703  assert(!powerEvent.scheduled());
1704  if (refreshState == REF_PD_EXIT) {
1705  // exiting PRE PD, will be in IDLE until tXP expires
1706  // and then should transition to PWR_REF state
1707  assert(prev_state == PWR_PRE_PDN);
1708  schedulePowerEvent(PWR_REF, curTick() + dram.tXP);
1709  } else if (refreshState == REF_PRE) {
1710  // can directly move to PWR_REF state and proceed below
1711  pwrState = PWR_REF;
1712  }
1713  } else {
1714  // must have PRE scheduled to transition back to IDLE
1715  // and re-kick off refresh
1716  assert(prechargeEvent.scheduled());
1717  }
1718  }
1719  }
1720  }
1721 
1722  // transition to the refresh state and re-start refresh process
1723  // refresh state machine will schedule the next power state transition
1724  if (pwrState == PWR_REF) {
1725  // completed final PRE for refresh or exiting power-down
1726  assert(refreshState == REF_PRE || refreshState == REF_PD_EXIT);
1727 
1728  // exited PRE PD for refresh, with no pending commands
1729  // bypass auto-refresh and go straight to SREF, where memory
1730  // will issue refresh immediately upon entry
1731  if (pwrStatePostRefresh == PWR_PRE_PDN && isQueueEmpty() &&
1732  (dram.ctrl->drainState() != DrainState::Draining) &&
1733  (dram.ctrl->drainState() != DrainState::Drained) &&
1734  dram.enableDRAMPowerdown) {
1735  DPRINTF(DRAMState, "Rank %d bypassing refresh and transitioning "
1736  "to self refresh at %11u tick\n", rank, curTick());
1737  powerDownSleep(PWR_SREF, curTick());
1738 
1739  // Since refresh was bypassed, remove event by decrementing count
1740  assert(outstandingEvents == 1);
1741  --outstandingEvents;
1742 
1743  // reset state back to IDLE temporarily until SREF is entered
1744  pwrState = PWR_IDLE;
1745 
1746  // Not bypassing refresh for SREF entry
1747  } else {
1748  DPRINTF(DRAMState, "Refreshing\n");
1749 
1750  // there should be nothing waiting at this point
1751  assert(!powerEvent.scheduled());
1752 
1753  // kick the refresh event loop into action again, and that
1754  // in turn will schedule a transition to the idle power
1755  // state once the refresh is done
1756  schedule(refreshEvent, curTick());
1757 
1758  // Banks transitioned to IDLE, start REF
1759  refreshState = REF_START;
1760  }
1761  }
1762 
1763 }
1764 
1765 void
1767 {
1768  // All commands up to refresh have completed
1769  // flush cmdList to DRAMPower
1770  flushCmdList();
1771 
1772  // Call the function that calculates window energy at intermediate update
1773  // events like at refresh, stats dump as well as at simulation exit.
1774  // Window starts at the last time the calcWindowEnergy function was called
1775  // and is upto current time.
1776  power.powerlib.calcWindowEnergy(divCeil(curTick(), dram.tCK) -
1777  dram.timeStampOffset);
1778 
1779  // Get the energy from DRAMPower
1780  Data::MemoryPowerModel::Energy energy = power.powerlib.getEnergy();
1781 
1782  // The energy components inside the power lib are calculated over
1783  // the window so accumulate into the corresponding gem5 stat
1784  stats.actEnergy += energy.act_energy * dram.devicesPerRank;
1785  stats.preEnergy += energy.pre_energy * dram.devicesPerRank;
1786  stats.readEnergy += energy.read_energy * dram.devicesPerRank;
1787  stats.writeEnergy += energy.write_energy * dram.devicesPerRank;
1788  stats.refreshEnergy += energy.ref_energy * dram.devicesPerRank;
1789  stats.actBackEnergy += energy.act_stdby_energy * dram.devicesPerRank;
1790  stats.preBackEnergy += energy.pre_stdby_energy * dram.devicesPerRank;
1791  stats.actPowerDownEnergy += energy.f_act_pd_energy * dram.devicesPerRank;
1792  stats.prePowerDownEnergy += energy.f_pre_pd_energy * dram.devicesPerRank;
1793  stats.selfRefreshEnergy += energy.sref_energy * dram.devicesPerRank;
1794 
1795  // Accumulate window energy into the total energy.
1796  stats.totalEnergy += energy.window_energy * dram.devicesPerRank;
1797  // Average power must not be accumulated but calculated over the time
1798  // since last stats reset. sim_clock::Frequency is tick period not tick
1799  // frequency.
1800  // energy (pJ) 1e-9
1801  // power (mW) = ----------- * ----------
1802  // time (tick) tick_frequency
1803  stats.averagePower = (stats.totalEnergy.value() /
1804  (curTick() - dram.lastStatsResetTick)) *
1805  (sim_clock::Frequency / 1000000000.0);
1806 }
1807 
1808 void
1810 {
1811  DPRINTF(DRAM,"Computing stats due to a dump callback\n");
1812 
1813  // Update the stats
1814  updatePowerStats();
1815 
1816  // final update of power state times
1817  stats.pwrStateTime[pwrState] += (curTick() - pwrStateTick);
1818  pwrStateTick = curTick();
1819 }
1820 
1821 void
1823  // The only way to clear the counters in DRAMPower is to call
1824  // calcWindowEnergy function as that then calls clearCounters. The
1825  // clearCounters method itself is private.
1826  power.powerlib.calcWindowEnergy(divCeil(curTick(), dram.tCK) -
1827  dram.timeStampOffset);
1828 
1829 }
1830 
1831 bool
1833  return (readEntries != 0) ||
1834  (dram.ctrl->inWriteBusState(true) && (writeEntries != 0));
1835 }
1836 
1837 void
1839 {
1840  dram.lastStatsResetTick = curTick();
1841 }
1842 
1844  : statistics::Group(&_dram),
1845  dram(_dram),
1846 
1847  ADD_STAT(readBursts, statistics::units::Count::get(),
1848  "Number of DRAM read bursts"),
1849  ADD_STAT(writeBursts, statistics::units::Count::get(),
1850  "Number of DRAM write bursts"),
1851 
1852  ADD_STAT(perBankRdBursts, statistics::units::Count::get(),
1853  "Per bank write bursts"),
1854  ADD_STAT(perBankWrBursts, statistics::units::Count::get(),
1855  "Per bank write bursts"),
1856 
1857  ADD_STAT(totQLat, statistics::units::Tick::get(),
1858  "Total ticks spent queuing"),
1859  ADD_STAT(totBusLat, statistics::units::Tick::get(),
1860  "Total ticks spent in databus transfers"),
1861  ADD_STAT(totMemAccLat, statistics::units::Tick::get(),
1862  "Total ticks spent from burst creation until serviced "
1863  "by the DRAM"),
1864 
1865  ADD_STAT(avgQLat, statistics::units::Rate<
1866  statistics::units::Tick, statistics::units::Count>::get(),
1867  "Average queueing delay per DRAM burst"),
1868  ADD_STAT(avgBusLat, statistics::units::Rate<
1869  statistics::units::Tick, statistics::units::Count>::get(),
1870  "Average bus latency per DRAM burst"),
1871  ADD_STAT(avgMemAccLat, statistics::units::Rate<
1872  statistics::units::Tick, statistics::units::Count>::get(),
1873  "Average memory access latency per DRAM burst"),
1874 
1875  ADD_STAT(readRowHits, statistics::units::Count::get(),
1876  "Number of row buffer hits during reads"),
1877  ADD_STAT(writeRowHits, statistics::units::Count::get(),
1878  "Number of row buffer hits during writes"),
1879  ADD_STAT(readRowHitRate, statistics::units::Ratio::get(),
1880  "Row buffer hit rate for reads"),
1881  ADD_STAT(writeRowHitRate, statistics::units::Ratio::get(),
1882  "Row buffer hit rate for writes"),
1883 
1884  ADD_STAT(bytesPerActivate, statistics::units::Byte::get(),
1885  "Bytes accessed per row activation"),
1886  ADD_STAT(bytesRead, statistics::units::Byte::get(),
1887  "Total bytes read"),
1888  ADD_STAT(bytesWritten, statistics::units::Byte::get(),
1889  "Total bytes written"),
1890 
1891  ADD_STAT(avgRdBW, statistics::units::Rate<
1892  statistics::units::Byte, statistics::units::Second>::get(),
1893  "Average DRAM read bandwidth in MiBytes/s"),
1894  ADD_STAT(avgWrBW, statistics::units::Rate<
1895  statistics::units::Byte, statistics::units::Second>::get(),
1896  "Average DRAM write bandwidth in MiBytes/s"),
1897  ADD_STAT(peakBW, statistics::units::Rate<
1898  statistics::units::Byte, statistics::units::Second>::get(),
1899  "Theoretical peak bandwidth in MiByte/s"),
1900 
1901  ADD_STAT(busUtil, statistics::units::Ratio::get(),
1902  "Data bus utilization in percentage"),
1903  ADD_STAT(busUtilRead, statistics::units::Ratio::get(),
1904  "Data bus utilization in percentage for reads"),
1905  ADD_STAT(busUtilWrite, statistics::units::Ratio::get(),
1906  "Data bus utilization in percentage for writes"),
1907 
1908  ADD_STAT(pageHitRate, statistics::units::Ratio::get(),
1909  "Row buffer hit rate, read and write combined")
1910 
1911 {
1912 }
1913 
1914 void
1916 {
1917  using namespace statistics;
1918 
1919  avgQLat.precision(2);
1920  avgBusLat.precision(2);
1921  avgMemAccLat.precision(2);
1922 
1923  readRowHitRate.precision(2);
1924  writeRowHitRate.precision(2);
1925 
1926  perBankRdBursts.init(dram.banksPerRank * dram.ranksPerChannel);
1927  perBankWrBursts.init(dram.banksPerRank * dram.ranksPerChannel);
1928 
1929  bytesPerActivate
1930  .init(dram.maxAccessesPerRow ?
1931  dram.maxAccessesPerRow : dram.rowBufferSize)
1932  .flags(nozero);
1933 
1934  peakBW.precision(2);
1935  busUtil.precision(2);
1936  busUtilWrite.precision(2);
1937  busUtilRead.precision(2);
1938 
1939  pageHitRate.precision(2);
1940 
1941  // Formula stats
1942  avgQLat = totQLat / readBursts;
1943  avgBusLat = totBusLat / readBursts;
1944  avgMemAccLat = totMemAccLat / readBursts;
1945 
1946  readRowHitRate = (readRowHits / readBursts) * 100;
1947  writeRowHitRate = (writeRowHits / writeBursts) * 100;
1948 
1949  avgRdBW = (bytesRead / 1000000) / simSeconds;
1950  avgWrBW = (bytesWritten / 1000000) / simSeconds;
1951  peakBW = (sim_clock::Frequency / dram.burstDelay()) *
1952  dram.bytesPerBurst() / 1000000;
1953 
1954  busUtil = (avgRdBW + avgWrBW) / peakBW * 100;
1955  busUtilRead = avgRdBW / peakBW * 100;
1956  busUtilWrite = avgWrBW / peakBW * 100;
1957 
1958  pageHitRate = (writeRowHits + readRowHits) /
1959  (writeBursts + readBursts) * 100;
1960 }
1961 
1963  : statistics::Group(&_dram, csprintf("rank%d", _rank.rank).c_str()),
1964  rank(_rank),
1965 
1966  ADD_STAT(actEnergy, statistics::units::Joule::get(),
1967  "Energy for activate commands per rank (pJ)"),
1968  ADD_STAT(preEnergy, statistics::units::Joule::get(),
1969  "Energy for precharge commands per rank (pJ)"),
1970  ADD_STAT(readEnergy, statistics::units::Joule::get(),
1971  "Energy for read commands per rank (pJ)"),
1972  ADD_STAT(writeEnergy, statistics::units::Joule::get(),
1973  "Energy for write commands per rank (pJ)"),
1974  ADD_STAT(refreshEnergy, statistics::units::Joule::get(),
1975  "Energy for refresh commands per rank (pJ)"),
1976  ADD_STAT(actBackEnergy, statistics::units::Joule::get(),
1977  "Energy for active background per rank (pJ)"),
1978  ADD_STAT(preBackEnergy, statistics::units::Joule::get(),
1979  "Energy for precharge background per rank (pJ)"),
1980  ADD_STAT(actPowerDownEnergy, statistics::units::Joule::get(),
1981  "Energy for active power-down per rank (pJ)"),
1982  ADD_STAT(prePowerDownEnergy, statistics::units::Joule::get(),
1983  "Energy for precharge power-down per rank (pJ)"),
1984  ADD_STAT(selfRefreshEnergy, statistics::units::Joule::get(),
1985  "Energy for self refresh per rank (pJ)"),
1986 
1987  ADD_STAT(totalEnergy, statistics::units::Joule::get(),
1988  "Total energy per rank (pJ)"),
1989  ADD_STAT(averagePower, statistics::units::Watt::get(),
1990  "Core power per rank (mW)"),
1991 
1992  ADD_STAT(totalIdleTime, statistics::units::Tick::get(),
1993  "Total Idle time Per DRAM Rank"),
1994  ADD_STAT(pwrStateTime, statistics::units::Tick::get(),
1995  "Time in different power states")
1996 {
1997 }
1998 
1999 void
2001 {
2003 
2004  pwrStateTime
2005  .init(6)
2006  .subname(0, "IDLE")
2007  .subname(1, "REF")
2008  .subname(2, "SREF")
2009  .subname(3, "PRE_PDN")
2010  .subname(4, "ACT")
2011  .subname(5, "ACT_PDN");
2012 }
2013 
2014 void
2016 {
2018 
2019  rank.resetStats();
2020 }
2021 
2022 void
2024 {
2026 
2027  rank.computeStats();
2028 }
2029 
2030 } // namespace memory
2031 } // namespace gem5
#define DPRINTF(x,...)
Definition: trace.hh:186
#define RD
Definition: bitfields.hh:14
DRAMPower is a standalone tool which calculates the power consumed by a DRAM in the system.
Definition: drampower.hh:57
virtual std::string name() const
Definition: named.hh:47
A Packet is used to encapsulate a transfer between two objects in the memory system (e....
Definition: packet.hh:294
uint64_t size() const
Get the memory size.
System * system() const
read the system pointer Implemented for completeness with the setter
Rank class includes a vector of banks.
void computeStats()
Computes stats just prior to dump event.
void powerDownSleep(PowerState pwr_state, Tick tick)
Schedule a transition to power-down (sleep)
void checkDrainDone()
Let the rank check if it was waiting for requests to drain to allow it to transition states.
void resetStats()
Reset stats on a stats event.
uint8_t outstandingEvents
Number of ACT, RD, and WR events currently scheduled Incremented when a refresh event is started as w...
bool inRefIdleState() const
Check if there is no refresh and no preparation of refresh ongoing i.e.
PowerState pwrState
Current power state.
EventFunctionWrapper activateEvent
std::deque< Tick > actTicks
List to keep track of activate ticks.
bool inLowPowerState
rank is in or transitioning to power-down or self-refresh
EventFunctionWrapper prechargeEvent
uint32_t readEntries
Track number of packets in read queue going to this rank.
RefreshState refreshState
current refresh state
unsigned int numBanksActive
To track number of banks which are currently active for this rank.
void startup(Tick ref_tick)
Kick off accounting for power and refresh states and schedule initial refresh.
std::vector< Command > cmdList
List of commands issued, to be sent to DRAMPpower at refresh and stats dump.
std::vector< Bank > banks
Vector of Banks.
Tick lastBurstTick
Track when we issued the last read/write burst.
void scheduleWakeUpEvent(Tick exit_delay)
schedule and event to wake-up from power-down or self-refresh and update bank timing parameters
void schedulePowerEvent(PowerState pwr_state, Tick tick)
Schedule a power state transition in the future, and potentially override an already scheduled transi...
uint8_t rank
Current Rank index.
void suspend()
Stop the refresh events.
void updatePowerStats()
Function to update Power Stats.
EventFunctionWrapper writeDoneEvent
bool isQueueEmpty() const
Check if the command queue of current rank is idle.
Rank(const DRAMInterfaceParams &_p, int _rank, DRAMInterface &_dram)
bool forceSelfRefreshExit() const
Trigger a self-refresh exit if there are entries enqueued Exit if there are any read entries regardle...
uint32_t writeEntries
Track number of packets in write queue going to this rank.
void flushCmdList()
Push command out of cmdList queue that are scheduled at or before curTick() to DRAMPower library All ...
Interface to DRAM devices with media specific parameters, statistics, and functions.
std::vector< Rank * > ranks
Vector of dram ranks.
void checkRefreshState(uint8_t rank) override
Check the refresh state to determine if refresh needs to be kicked back into action after a read resp...
void respondEvent(uint8_t rank) override
Complete response process for DRAM when read burst is complete This will update the counters and chec...
bool allRanksDrained() const override
Return true once refresh is complete for all ranks and there are no additional commands enqueued.
void drainRanks() override
Iterate through dram ranks to exit self-refresh in order to drain.
bool isBusy(bool read_queue_empty, bool all_writes_nvm) override
This function checks if ranks are actively refreshing and therefore busy.
const uint32_t bankGroupsPerRank
DRAM specific device characteristics.
PowerState
The power state captures the different operational states of the DRAM and interacts with the bus read...
MemPacket * decodePacket(const PacketPtr pkt, Addr pkt_addr, unsigned int size, bool is_read, uint8_t pseudo_channel=0) override
Address decoder to figure out physical mapping onto ranks, banks, and rows.
void startup() override
Iterate through dram ranks and instantiate per rank startup routine.
bool enableDRAMPowerdown
Enable or disable DRAM powerdown states.
std::pair< std::vector< uint32_t >, bool > minBankPrep(const MemPacketQueue &queue, Tick min_col_at) const
Find which are the earliest banks ready to issue an activate for the enqueued requests.
static bool sortTime(const Command &cmd, const Command &cmd_next)
Function for sorting Command structures based on timeStamp.
void init() override
Initialize the DRAM interface and verify parameters.
void suspend() override
Iterate through DRAM ranks and suspend them.
void setupRank(const uint8_t rank, const bool is_read) override
Setup the rank based on packet received.
bool inReadBusState(bool next_state) const
Check the current direction of the memory channel.
Definition: mem_ctrl.cc:764
A basic class to track the bank state, i.e.
static const uint32_t NO_ROW
General interface to memory device Includes functions and parameters shared across media types.
const uint32_t burstsPerStripe
enums::AddrMap addrMapping
Memory controller configuration initialized based on parameter values.
MemCtrl * ctrl
A pointer to the parent memory controller instance.
const uint32_t ranksPerChannel
Addr getCtrlAddr(Addr addr)
Get an address in a dense range which starts from 0.
uint8_t pseudoChannel
pseudo channel number used for HBM modeling
const uint32_t burstSize
General device and channel characteristics The rowsPerBank is determined based on the capacity,...
const uint32_t burstsPerRowBuffer
GEM5_CLASS_VAR_USED const Tick tCK
General timing requirements.
A memory packet stores packets along with the timestamp of when the packet entered the queue,...
Definition: mem_ctrl.hh:99
Tick readyTime
When will request leave the controller.
Definition: mem_ctrl.hh:106
const uint8_t pseudoChannel
pseudo channel num
Definition: mem_ctrl.hh:120
const uint16_t bankId
Bank id is calculated considering banks in all the ranks eg: 2 ranks each with 8 banks,...
Definition: mem_ctrl.hh:132
const uint32_t row
Definition: mem_ctrl.hh:125
const uint8_t bank
Definition: mem_ctrl.hh:124
Addr addr
The starting address of the packet.
Definition: mem_ctrl.hh:140
bool isDram() const
Return true if its a DRAM access.
Definition: mem_ctrl.hh:204
bool isRead() const
Return true if its a read packet (interface compatibility with Packet)
Definition: mem_ctrl.hh:193
const Tick entryTime
When did request enter the controller.
Definition: mem_ctrl.hh:103
const uint8_t rank
Will be populated by address decoder.
Definition: mem_ctrl.hh:123
Statistics container.
Definition: group.hh:94
STL deque class.
Definition: stl.hh:44
STL pair class.
Definition: stl.hh:58
DRAMInterface declaration.
#define ADD_STAT(n,...)
Convenience macro to add a stat to a statistics group.
Definition: group.hh:75
bool interleaved() const
Determine if the range is interleaved or not.
Definition: addr_range.hh:284
uint64_t granularity() const
Determing the interleaving granularity of the range.
Definition: addr_range.hh:294
static constexpr int ceilLog2(const T &n)
Definition: intmath.hh:84
static constexpr bool isPowerOf2(const T &n)
Definition: intmath.hh:98
static constexpr T divCeil(const T &a, const U &b)
Definition: intmath.hh:110
constexpr T bits(T val, unsigned first, unsigned last)
Extract the bitfield from position 'first' to 'last' (inclusive) from 'val' and right justify it.
Definition: bitfield.hh:76
constexpr void replaceBits(T &val, unsigned first, unsigned last, B bit_val)
A convenience function to replace bits first to last of val with bit_val in place.
Definition: bitfield.hh:197
@ Draining
Draining buffers pending serialization/handover.
@ Drained
Buffers drained, ready for serialization/handover.
void deschedule(Event &event)
Definition: eventq.hh:1028
bool scheduled() const
Determine if the current event is scheduled.
Definition: eventq.hh:465
void schedule(Event &event, Tick when)
Definition: eventq.hh:1019
Tick when() const
Get the time that the event is scheduled.
Definition: eventq.hh:508
#define panic(...)
This implements a cprintf based panic() function.
Definition: logging.hh:178
#define fatal_if(cond,...)
Conditional fatal macro that checks the supplied condition and only causes a fatal error if the condi...
Definition: logging.hh:226
#define fatal(...)
This implements a cprintf based fatal() function.
Definition: logging.hh:190
virtual void init()
init() is called after all C++ SimObjects have been created and all ports are connected.
Definition: sim_object.cc:76
virtual void regStats()
Callback to set stat parameters.
Definition: group.cc:69
virtual void preDumpStats()
Callback before stats are dumped.
Definition: group.cc:99
virtual void resetStats()
Callback to reset stats.
Definition: group.cc:86
#define warn(...)
Definition: logging.hh:246
Bitfield< 31 > n
Definition: misc_types.hh:462
Bitfield< 7 > b
Definition: misc_types.hh:388
Bitfield< 7 > i
Definition: misc_types.hh:67
Bitfield< 24 > j
Definition: misc_types.hh:57
Bitfield< 5 > r
Definition: pagetable.hh:60
Bitfield< 54 > p
Definition: pagetable.hh:70
Bitfield< 3 > addr
Definition: types.hh:84
Tick Frequency
The simulated frequency of curTick(). (In ticks per second)
Definition: core.cc:48
const FlagsType nozero
Don't print if this is zero.
Definition: info.hh:68
Reference material can be found at the JEDEC website: UFS standard http://www.jedec....
Tick curTick()
The universal simulation clock.
Definition: cur_tick.hh:46
uint64_t Addr
Address type This will probably be moved somewhere else in the near future.
Definition: types.hh:147
uint64_t Tick
Tick count type.
Definition: types.hh:58
const Tick MaxTick
Definition: types.hh:60
std::string csprintf(const char *format, const Args &...args)
Definition: cprintf.hh:161
statistics::Formula & simSeconds
Definition: stats.cc:45
Simple structure to hold the values needed to keep track of commands for DRAMPower.
void resetStats() override
Callback to reset stats.
void regStats() override
Callback to set stat parameters.
void resetStats() override
Callback to reset stats.
void preDumpStats() override
Callback before stats are dumped.
void regStats() override
Callback to set stat parameters.
RankStats(DRAMInterface &dram, Rank &rank)
Definition: mem.h:38

Generated on Wed Dec 21 2022 10:22:37 for gem5 by doxygen 1.9.1