gem5  v20.1.0.0
mem_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/mem_interface.hh"
42 
43 #include "base/bitfield.hh"
44 #include "base/trace.hh"
45 #include "debug/DRAM.hh"
46 #include "debug/DRAMPower.hh"
47 #include "debug/DRAMState.hh"
48 #include "debug/NVM.hh"
49 #include "sim/system.hh"
50 
51 using namespace std;
52 using namespace Data;
53 
54 MemInterface::MemInterface(const MemInterfaceParams* _p)
55  : AbstractMemory(_p),
56  addrMapping(_p->addr_mapping),
57  burstSize((_p->devices_per_rank * _p->burst_length *
58  _p->device_bus_width) / 8),
59  deviceSize(_p->device_size),
60  deviceRowBufferSize(_p->device_rowbuffer_size),
61  devicesPerRank(_p->devices_per_rank),
62  rowBufferSize(devicesPerRank * deviceRowBufferSize),
63  burstsPerRowBuffer(rowBufferSize / burstSize),
64  burstsPerStripe(range.interleaved() ?
65  range.granularity() / burstSize : 1),
66  ranksPerChannel(_p->ranks_per_channel),
67  banksPerRank(_p->banks_per_rank), rowsPerBank(0),
68  tCK(_p->tCK), tCS(_p->tCS), tBURST(_p->tBURST),
69  tRTW(_p->tRTW),
70  tWTR(_p->tWTR),
71  readBufferSize(_p->read_buffer_size),
72  writeBufferSize(_p->write_buffer_size)
73 {}
74 
75 void
76 MemInterface::setCtrl(MemCtrl* _ctrl, unsigned int command_window)
77 {
78  ctrl = _ctrl;
79  maxCommandsPerWindow = command_window / tCK;
80 }
81 
82 MemPacket*
84  unsigned size, bool is_read, bool is_dram)
85 {
86  // decode the address based on the address mapping scheme, with
87  // Ro, Ra, Co, Ba and Ch denoting row, rank, column, bank and
88  // channel, respectively
89  uint8_t rank;
90  uint8_t bank;
91  // use a 64-bit unsigned during the computations as the row is
92  // always the top bits, and check before creating the packet
93  uint64_t row;
94 
95  // Get packed address, starting at 0
96  Addr addr = getCtrlAddr(pkt_addr);
97 
98  // truncate the address to a memory burst, which makes it unique to
99  // a specific buffer, row, bank, rank and channel
100  addr = addr / burstSize;
101 
102  // we have removed the lowest order address bits that denote the
103  // position within the column
104  if (addrMapping == Enums::RoRaBaChCo || addrMapping == Enums::RoRaBaCoCh) {
105  // the lowest order bits denote the column to ensure that
106  // sequential cache lines occupy the same row
108 
109  // after the channel bits, get the bank bits to interleave
110  // over the banks
111  bank = addr % banksPerRank;
112  addr = addr / banksPerRank;
113 
114  // after the bank, we get the rank bits which thus interleaves
115  // over the ranks
116  rank = addr % ranksPerChannel;
118 
119  // lastly, get the row bits, no need to remove them from addr
120  row = addr % rowsPerBank;
121  } else if (addrMapping == Enums::RoCoRaBaCh) {
122  // with emerging technologies, could have small page size with
123  // interleaving granularity greater than row buffer
125  // remove column bits which are a subset of burstsPerStripe
127  } else {
128  // remove lower column bits below channel bits
130  }
131 
132  // start with the bank bits, as this provides the maximum
133  // opportunity for parallelism between requests
134  bank = addr % banksPerRank;
135  addr = addr / banksPerRank;
136 
137  // next get the rank bits
138  rank = addr % ranksPerChannel;
140 
141  // next, the higher-order column bites
144  }
145 
146  // lastly, get the row bits, no need to remove them from addr
147  row = addr % rowsPerBank;
148  } else
149  panic("Unknown address mapping policy chosen!");
150 
151  assert(rank < ranksPerChannel);
152  assert(bank < banksPerRank);
153  assert(row < rowsPerBank);
154  assert(row < Bank::NO_ROW);
155 
156  DPRINTF(DRAM, "Address: %lld Rank %d Bank %d Row %d\n",
157  pkt_addr, rank, bank, row);
158 
159  // create the corresponding memory packet with the entry time and
160  // ready time set to the current tick, the latter will be updated
161  // later
162  uint16_t bank_id = banksPerRank * rank + bank;
163 
164  return new MemPacket(pkt, is_read, is_dram, rank, bank, row, bank_id,
165  pkt_addr, size);
166 }
167 
170 {
171  vector<uint32_t> earliest_banks(ranksPerChannel, 0);
172 
173  // Has minBankPrep been called to populate earliest_banks?
174  bool filled_earliest_banks = false;
175  // can the PRE/ACT sequence be done without impacting utlization?
176  bool hidden_bank_prep = false;
177 
178  // search for seamless row hits first, if no seamless row hit is
179  // found then determine if there are other packets that can be issued
180  // without incurring additional bus delay due to bank timing
181  // Will select closed rows first to enable more open row possibilies
182  // in future selections
183  bool found_hidden_bank = false;
184 
185  // remember if we found a row hit, not seamless, but bank prepped
186  // and ready
187  bool found_prepped_pkt = false;
188 
189  // if we have no row hit, prepped or not, and no seamless packet,
190  // just go for the earliest possible
191  bool found_earliest_pkt = false;
192 
193  Tick selected_col_at = MaxTick;
194  auto selected_pkt_it = queue.end();
195 
196  for (auto i = queue.begin(); i != queue.end() ; ++i) {
197  MemPacket* pkt = *i;
198 
199  // select optimal DRAM packet in Q
200  if (pkt->isDram()) {
201  const Bank& bank = ranks[pkt->rank]->banks[pkt->bank];
202  const Tick col_allowed_at = pkt->isRead() ? bank.rdAllowedAt :
203  bank.wrAllowedAt;
204 
205  DPRINTF(DRAM, "%s checking DRAM packet in bank %d, row %d\n",
206  __func__, pkt->bank, pkt->row);
207 
208  // check if rank is not doing a refresh and thus is available,
209  // if not, jump to the next packet
210  if (burstReady(pkt)) {
211 
212  DPRINTF(DRAM,
213  "%s bank %d - Rank %d available\n", __func__,
214  pkt->bank, pkt->rank);
215 
216  // check if it is a row hit
217  if (bank.openRow == pkt->row) {
218  // no additional rank-to-rank or same bank-group
219  // delays, or we switched read/write and might as well
220  // go for the row hit
221  if (col_allowed_at <= min_col_at) {
222  // FCFS within the hits, giving priority to
223  // commands that can issue seamlessly, without
224  // additional delay, such as same rank accesses
225  // and/or different bank-group accesses
226  DPRINTF(DRAM, "%s Seamless buffer hit\n", __func__);
227  selected_pkt_it = i;
228  selected_col_at = col_allowed_at;
229  // no need to look through the remaining queue entries
230  break;
231  } else if (!found_hidden_bank && !found_prepped_pkt) {
232  // if we did not find a packet to a closed row that can
233  // issue the bank commands without incurring delay, and
234  // did not yet find a packet to a prepped row, remember
235  // the current one
236  selected_pkt_it = i;
237  selected_col_at = col_allowed_at;
238  found_prepped_pkt = true;
239  DPRINTF(DRAM, "%s Prepped row buffer hit\n", __func__);
240  }
241  } else if (!found_earliest_pkt) {
242  // if we have not initialised the bank status, do it
243  // now, and only once per scheduling decisions
244  if (!filled_earliest_banks) {
245  // determine entries with earliest bank delay
246  std::tie(earliest_banks, hidden_bank_prep) =
247  minBankPrep(queue, min_col_at);
248  filled_earliest_banks = true;
249  }
250 
251  // bank is amongst first available banks
252  // minBankPrep will give priority to packets that can
253  // issue seamlessly
254  if (bits(earliest_banks[pkt->rank],
255  pkt->bank, pkt->bank)) {
256  found_earliest_pkt = true;
257  found_hidden_bank = hidden_bank_prep;
258 
259  // give priority to packets that can issue
260  // bank commands 'behind the scenes'
261  // any additional delay if any will be due to
262  // col-to-col command requirements
263  if (hidden_bank_prep || !found_prepped_pkt) {
264  selected_pkt_it = i;
265  selected_col_at = col_allowed_at;
266  }
267  }
268  }
269  } else {
270  DPRINTF(DRAM, "%s bank %d - Rank %d not available\n", __func__,
271  pkt->bank, pkt->rank);
272  }
273  }
274  }
275 
276  if (selected_pkt_it == queue.end()) {
277  DPRINTF(DRAM, "%s no available DRAM ranks found\n", __func__);
278  }
279 
280  return make_pair(selected_pkt_it, selected_col_at);
281 }
282 
283 void
284 DRAMInterface::activateBank(Rank& rank_ref, Bank& bank_ref,
285  Tick act_tick, uint32_t row)
286 {
287  assert(rank_ref.actTicks.size() == activationLimit);
288 
289  // verify that we have command bandwidth to issue the activate
290  // if not, shift to next burst window
291  Tick act_at;
292  if (twoCycleActivate)
293  act_at = ctrl->verifyMultiCmd(act_tick, maxCommandsPerWindow, tAAD);
294  else
295  act_at = ctrl->verifySingleCmd(act_tick, maxCommandsPerWindow);
296 
297  DPRINTF(DRAM, "Activate at tick %d\n", act_at);
298 
299  // update the open row
300  assert(bank_ref.openRow == Bank::NO_ROW);
301  bank_ref.openRow = row;
302 
303  // start counting anew, this covers both the case when we
304  // auto-precharged, and when this access is forced to
305  // precharge
306  bank_ref.bytesAccessed = 0;
307  bank_ref.rowAccesses = 0;
308 
309  ++rank_ref.numBanksActive;
310  assert(rank_ref.numBanksActive <= banksPerRank);
311 
312  DPRINTF(DRAM, "Activate bank %d, rank %d at tick %lld, now got "
313  "%d active\n", bank_ref.bank, rank_ref.rank, act_at,
314  ranks[rank_ref.rank]->numBanksActive);
315 
316  rank_ref.cmdList.push_back(Command(MemCommand::ACT, bank_ref.bank,
317  act_at));
318 
319  DPRINTF(DRAMPower, "%llu,ACT,%d,%d\n", divCeil(act_at, tCK) -
320  timeStampOffset, bank_ref.bank, rank_ref.rank);
321 
322  // The next access has to respect tRAS for this bank
323  bank_ref.preAllowedAt = act_at + tRAS;
324 
325  // Respect the row-to-column command delay for both read and write cmds
326  bank_ref.rdAllowedAt = std::max(act_at + tRCD, bank_ref.rdAllowedAt);
327  bank_ref.wrAllowedAt = std::max(act_at + tRCD, bank_ref.wrAllowedAt);
328 
329  // start by enforcing tRRD
330  for (int i = 0; i < banksPerRank; i++) {
331  // next activate to any bank in this rank must not happen
332  // before tRRD
333  if (bankGroupArch && (bank_ref.bankgr == rank_ref.banks[i].bankgr)) {
334  // bank group architecture requires longer delays between
335  // ACT commands within the same bank group. Use tRRD_L
336  // in this case
337  rank_ref.banks[i].actAllowedAt = std::max(act_at + tRRD_L,
338  rank_ref.banks[i].actAllowedAt);
339  } else {
340  // use shorter tRRD value when either
341  // 1) bank group architecture is not supportted
342  // 2) bank is in a different bank group
343  rank_ref.banks[i].actAllowedAt = std::max(act_at + tRRD,
344  rank_ref.banks[i].actAllowedAt);
345  }
346  }
347 
348  // next, we deal with tXAW, if the activation limit is disabled
349  // then we directly schedule an activate power event
350  if (!rank_ref.actTicks.empty()) {
351  // sanity check
352  if (rank_ref.actTicks.back() &&
353  (act_at - rank_ref.actTicks.back()) < tXAW) {
354  panic("Got %d activates in window %d (%llu - %llu) which "
355  "is smaller than %llu\n", activationLimit, act_at -
356  rank_ref.actTicks.back(), act_at,
357  rank_ref.actTicks.back(), tXAW);
358  }
359 
360  // shift the times used for the book keeping, the last element
361  // (highest index) is the oldest one and hence the lowest value
362  rank_ref.actTicks.pop_back();
363 
364  // record an new activation (in the future)
365  rank_ref.actTicks.push_front(act_at);
366 
367  // cannot activate more than X times in time window tXAW, push the
368  // next one (the X + 1'st activate) to be tXAW away from the
369  // oldest in our window of X
370  if (rank_ref.actTicks.back() &&
371  (act_at - rank_ref.actTicks.back()) < tXAW) {
372  DPRINTF(DRAM, "Enforcing tXAW with X = %d, next activate "
373  "no earlier than %llu\n", activationLimit,
374  rank_ref.actTicks.back() + tXAW);
375  for (int j = 0; j < banksPerRank; j++)
376  // next activate must not happen before end of window
377  rank_ref.banks[j].actAllowedAt =
378  std::max(rank_ref.actTicks.back() + tXAW,
379  rank_ref.banks[j].actAllowedAt);
380  }
381  }
382 
383  // at the point when this activate takes place, make sure we
384  // transition to the active power state
385  if (!rank_ref.activateEvent.scheduled())
386  schedule(rank_ref.activateEvent, act_at);
387  else if (rank_ref.activateEvent.when() > act_at)
388  // move it sooner in time
389  reschedule(rank_ref.activateEvent, act_at);
390 }
391 
392 void
393 DRAMInterface::prechargeBank(Rank& rank_ref, Bank& bank, Tick pre_tick,
394  bool auto_or_preall, bool trace)
395 {
396  // make sure the bank has an open row
397  assert(bank.openRow != Bank::NO_ROW);
398 
399  // sample the bytes per activate here since we are closing
400  // the page
402 
403  bank.openRow = Bank::NO_ROW;
404 
405  Tick pre_at = pre_tick;
406  if (auto_or_preall) {
407  // no precharge allowed before this one
408  bank.preAllowedAt = pre_at;
409  } else {
410  // Issuing an explicit PRE command
411  // Verify that we have command bandwidth to issue the precharge
412  // if not, shift to next burst window
413  pre_at = ctrl->verifySingleCmd(pre_tick, maxCommandsPerWindow);
414  // enforce tPPD
415  for (int i = 0; i < banksPerRank; i++) {
416  rank_ref.banks[i].preAllowedAt = std::max(pre_at + tPPD,
417  rank_ref.banks[i].preAllowedAt);
418  }
419  }
420 
421  Tick pre_done_at = pre_at + tRP;
422 
423  bank.actAllowedAt = std::max(bank.actAllowedAt, pre_done_at);
424 
425  assert(rank_ref.numBanksActive != 0);
426  --rank_ref.numBanksActive;
427 
428  DPRINTF(DRAM, "Precharging bank %d, rank %d at tick %lld, now got "
429  "%d active\n", bank.bank, rank_ref.rank, pre_at,
430  rank_ref.numBanksActive);
431 
432  if (trace) {
433 
434  rank_ref.cmdList.push_back(Command(MemCommand::PRE, bank.bank,
435  pre_at));
436  DPRINTF(DRAMPower, "%llu,PRE,%d,%d\n", divCeil(pre_at, tCK) -
437  timeStampOffset, bank.bank, rank_ref.rank);
438  }
439 
440  // if we look at the current number of active banks we might be
441  // tempted to think the DRAM is now idle, however this can be
442  // undone by an activate that is scheduled to happen before we
443  // would have reached the idle state, so schedule an event and
444  // rather check once we actually make it to the point in time when
445  // the (last) precharge takes place
446  if (!rank_ref.prechargeEvent.scheduled()) {
447  schedule(rank_ref.prechargeEvent, pre_done_at);
448  // New event, increment count
449  ++rank_ref.outstandingEvents;
450  } else if (rank_ref.prechargeEvent.when() < pre_done_at) {
451  reschedule(rank_ref.prechargeEvent, pre_done_at);
452  }
453 }
454 
457  const std::vector<MemPacketQueue>& queue)
458 {
459  DPRINTF(DRAM, "Timing access to addr %lld, rank/bank/row %d %d %d\n",
460  mem_pkt->addr, mem_pkt->rank, mem_pkt->bank, mem_pkt->row);
461 
462  // get the rank
463  Rank& rank_ref = *ranks[mem_pkt->rank];
464 
465  assert(rank_ref.inRefIdleState());
466 
467  // are we in or transitioning to a low-power state and have not scheduled
468  // a power-up event?
469  // if so, wake up from power down to issue RD/WR burst
470  if (rank_ref.inLowPowerState) {
471  assert(rank_ref.pwrState != PWR_SREF);
472  rank_ref.scheduleWakeUpEvent(tXP);
473  }
474 
475  // get the bank
476  Bank& bank_ref = rank_ref.banks[mem_pkt->bank];
477 
478  // for the state we need to track if it is a row hit or not
479  bool row_hit = true;
480 
481  // Determine the access latency and update the bank state
482  if (bank_ref.openRow == mem_pkt->row) {
483  // nothing to do
484  } else {
485  row_hit = false;
486 
487  // If there is a page open, precharge it.
488  if (bank_ref.openRow != Bank::NO_ROW) {
489  prechargeBank(rank_ref, bank_ref, std::max(bank_ref.preAllowedAt,
490  curTick()));
491  }
492 
493  // next we need to account for the delay in activating the page
494  Tick act_tick = std::max(bank_ref.actAllowedAt, curTick());
495 
496  // Record the activation and deal with all the global timing
497  // constraints caused be a new activation (tRRD and tXAW)
498  activateBank(rank_ref, bank_ref, act_tick, mem_pkt->row);
499  }
500 
501  // respect any constraints on the command (e.g. tRCD or tCCD)
502  const Tick col_allowed_at = mem_pkt->isRead() ?
503  bank_ref.rdAllowedAt : bank_ref.wrAllowedAt;
504 
505  // we need to wait until the bus is available before we can issue
506  // the command; need to ensure minimum bus delay requirement is met
507  Tick cmd_at = std::max({col_allowed_at, next_burst_at, curTick()});
508 
509  // verify that we have command bandwidth to issue the burst
510  // if not, shift to next burst window
511  if (dataClockSync && ((cmd_at - rank_ref.lastBurstTick) > clkResyncDelay))
512  cmd_at = ctrl->verifyMultiCmd(cmd_at, maxCommandsPerWindow, tCK);
513  else
514  cmd_at = ctrl->verifySingleCmd(cmd_at, maxCommandsPerWindow);
515 
516  // if we are interleaving bursts, ensure that
517  // 1) we don't double interleave on next burst issue
518  // 2) we are at an interleave boundary; if not, shift to next boundary
519  Tick burst_gap = tBURST_MIN;
520  if (burstInterleave) {
521  if (cmd_at == (rank_ref.lastBurstTick + tBURST_MIN)) {
522  // already interleaving, push next command to end of full burst
523  burst_gap = tBURST;
524  } else if (cmd_at < (rank_ref.lastBurstTick + tBURST)) {
525  // not at an interleave boundary after bandwidth check
526  // Shift command to tBURST boundary to avoid data contention
527  // Command will remain in the same burst window given that
528  // tBURST is less than tBURST_MAX
529  cmd_at = rank_ref.lastBurstTick + tBURST;
530  }
531  }
532  DPRINTF(DRAM, "Schedule RD/WR burst at tick %d\n", cmd_at);
533 
534  // update the packet ready time
535  mem_pkt->readyTime = cmd_at + tCL + tBURST;
536 
537  rank_ref.lastBurstTick = cmd_at;
538 
539  // update the time for the next read/write burst for each
540  // bank (add a max with tCCD/tCCD_L/tCCD_L_WR here)
541  Tick dly_to_rd_cmd;
542  Tick dly_to_wr_cmd;
543  for (int j = 0; j < ranksPerChannel; j++) {
544  for (int i = 0; i < banksPerRank; i++) {
545  if (mem_pkt->rank == j) {
546  if (bankGroupArch &&
547  (bank_ref.bankgr == ranks[j]->banks[i].bankgr)) {
548  // bank group architecture requires longer delays between
549  // RD/WR burst commands to the same bank group.
550  // tCCD_L is default requirement for same BG timing
551  // tCCD_L_WR is required for write-to-write
552  // Need to also take bus turnaround delays into account
553  dly_to_rd_cmd = mem_pkt->isRead() ?
554  tCCD_L : std::max(tCCD_L, wrToRdDlySameBG);
555  dly_to_wr_cmd = mem_pkt->isRead() ?
556  std::max(tCCD_L, rdToWrDlySameBG) :
557  tCCD_L_WR;
558  } else {
559  // tBURST is default requirement for diff BG timing
560  // Need to also take bus turnaround delays into account
561  dly_to_rd_cmd = mem_pkt->isRead() ? burst_gap :
563  dly_to_wr_cmd = mem_pkt->isRead() ? readToWriteDelay() :
564  burst_gap;
565  }
566  } else {
567  // different rank is by default in a different bank group and
568  // doesn't require longer tCCD or additional RTW, WTR delays
569  // Need to account for rank-to-rank switching
570  dly_to_wr_cmd = rankToRankDelay();
571  dly_to_rd_cmd = rankToRankDelay();
572  }
573  ranks[j]->banks[i].rdAllowedAt = std::max(cmd_at + dly_to_rd_cmd,
574  ranks[j]->banks[i].rdAllowedAt);
575  ranks[j]->banks[i].wrAllowedAt = std::max(cmd_at + dly_to_wr_cmd,
576  ranks[j]->banks[i].wrAllowedAt);
577  }
578  }
579 
580  // Save rank of current access
581  activeRank = mem_pkt->rank;
582 
583  // If this is a write, we also need to respect the write recovery
584  // time before a precharge, in the case of a read, respect the
585  // read to precharge constraint
586  bank_ref.preAllowedAt = std::max(bank_ref.preAllowedAt,
587  mem_pkt->isRead() ? cmd_at + tRTP :
588  mem_pkt->readyTime + tWR);
589 
590  // increment the bytes accessed and the accesses per row
591  bank_ref.bytesAccessed += burstSize;
592  ++bank_ref.rowAccesses;
593 
594  // if we reached the max, then issue with an auto-precharge
595  bool auto_precharge = pageMgmt == Enums::close ||
596  bank_ref.rowAccesses == maxAccessesPerRow;
597 
598  // if we did not hit the limit, we might still want to
599  // auto-precharge
600  if (!auto_precharge &&
601  (pageMgmt == Enums::open_adaptive ||
602  pageMgmt == Enums::close_adaptive)) {
603  // a twist on the open and close page policies:
604  // 1) open_adaptive page policy does not blindly keep the
605  // page open, but close it if there are no row hits, and there
606  // are bank conflicts in the queue
607  // 2) close_adaptive page policy does not blindly close the
608  // page, but closes it only if there are no row hits in the queue.
609  // In this case, only force an auto precharge when there
610  // are no same page hits in the queue
611  bool got_more_hits = false;
612  bool got_bank_conflict = false;
613 
614  for (uint8_t i = 0; i < ctrl->numPriorities(); ++i) {
615  auto p = queue[i].begin();
616  // keep on looking until we find a hit or reach the end of the
617  // queue
618  // 1) if a hit is found, then both open and close adaptive
619  // policies keep the page open
620  // 2) if no hit is found, got_bank_conflict is set to true if a
621  // bank conflict request is waiting in the queue
622  // 3) make sure we are not considering the packet that we are
623  // currently dealing with
624  while (!got_more_hits && p != queue[i].end()) {
625  if (mem_pkt != (*p)) {
626  bool same_rank_bank = (mem_pkt->rank == (*p)->rank) &&
627  (mem_pkt->bank == (*p)->bank);
628 
629  bool same_row = mem_pkt->row == (*p)->row;
630  got_more_hits |= same_rank_bank && same_row;
631  got_bank_conflict |= same_rank_bank && !same_row;
632  }
633  ++p;
634  }
635 
636  if (got_more_hits)
637  break;
638  }
639 
640  // auto pre-charge when either
641  // 1) open_adaptive policy, we have not got any more hits, and
642  // have a bank conflict
643  // 2) close_adaptive policy and we have not got any more hits
644  auto_precharge = !got_more_hits &&
645  (got_bank_conflict || pageMgmt == Enums::close_adaptive);
646  }
647 
648  // DRAMPower trace command to be written
649  std::string mem_cmd = mem_pkt->isRead() ? "RD" : "WR";
650 
651  // MemCommand required for DRAMPower library
652  MemCommand::cmds command = (mem_cmd == "RD") ? MemCommand::RD :
653  MemCommand::WR;
654 
655  rank_ref.cmdList.push_back(Command(command, mem_pkt->bank, cmd_at));
656 
657  DPRINTF(DRAMPower, "%llu,%s,%d,%d\n", divCeil(cmd_at, tCK) -
658  timeStampOffset, mem_cmd, mem_pkt->bank, mem_pkt->rank);
659 
660  // if this access should use auto-precharge, then we are
661  // closing the row after the read/write burst
662  if (auto_precharge) {
663  // if auto-precharge push a PRE command at the correct tick to the
664  // list used by DRAMPower library to calculate power
665  prechargeBank(rank_ref, bank_ref, std::max(curTick(),
666  bank_ref.preAllowedAt), true);
667 
668  DPRINTF(DRAM, "Auto-precharged bank: %d\n", mem_pkt->bankId);
669  }
670 
671  // Update the stats and schedule the next request
672  if (mem_pkt->isRead()) {
673  // Every respQueue which will generate an event, increment count
674  ++rank_ref.outstandingEvents;
675 
676  stats.readBursts++;
677  if (row_hit)
678  stats.readRowHits++;
680  stats.perBankRdBursts[mem_pkt->bankId]++;
681 
682  // Update latency stats
683  stats.totMemAccLat += mem_pkt->readyTime - mem_pkt->entryTime;
684  stats.totQLat += cmd_at - mem_pkt->entryTime;
686  } else {
687  // Schedule write done event to decrement event count
688  // after the readyTime has been reached
689  // Only schedule latest write event to minimize events
690  // required; only need to ensure that final event scheduled covers
691  // the time that writes are outstanding and bus is active
692  // to holdoff power-down entry events
693  if (!rank_ref.writeDoneEvent.scheduled()) {
694  schedule(rank_ref.writeDoneEvent, mem_pkt->readyTime);
695  // New event, increment count
696  ++rank_ref.outstandingEvents;
697 
698  } else if (rank_ref.writeDoneEvent.when() < mem_pkt->readyTime) {
699  reschedule(rank_ref.writeDoneEvent, mem_pkt->readyTime);
700  }
701  // will remove write from queue when returned to parent function
702  // decrement count for DRAM rank
703  --rank_ref.writeEntries;
704 
705  stats.writeBursts++;
706  if (row_hit)
709  stats.perBankWrBursts[mem_pkt->bankId]++;
710 
711  }
712  // Update bus state to reflect when previous command was issued
713  return make_pair(cmd_at, cmd_at + burst_gap);
714 }
715 
716 void
718 {
719  // update timing for DRAM ranks due to bursts issued
720  // to ranks on other media interfaces
721  for (auto n : ranks) {
722  for (int i = 0; i < banksPerRank; i++) {
723  // different rank by default
724  // Need to only account for rank-to-rank switching
725  n->banks[i].rdAllowedAt = std::max(cmd_at + rankToRankDelay(),
726  n->banks[i].rdAllowedAt);
727  n->banks[i].wrAllowedAt = std::max(cmd_at + rankToRankDelay(),
728  n->banks[i].wrAllowedAt);
729  }
730  }
731 }
732 
733 DRAMInterface::DRAMInterface(const DRAMInterfaceParams* _p)
734  : MemInterface(_p),
735  bankGroupsPerRank(_p->bank_groups_per_rank),
736  bankGroupArch(_p->bank_groups_per_rank > 0),
737  tCL(_p->tCL),
738  tBURST_MIN(_p->tBURST_MIN), tBURST_MAX(_p->tBURST_MAX),
739  tCCD_L_WR(_p->tCCD_L_WR), tCCD_L(_p->tCCD_L), tRCD(_p->tRCD),
740  tRP(_p->tRP), tRAS(_p->tRAS), tWR(_p->tWR), tRTP(_p->tRTP),
741  tRFC(_p->tRFC), tREFI(_p->tREFI), tRRD(_p->tRRD), tRRD_L(_p->tRRD_L),
742  tPPD(_p->tPPD), tAAD(_p->tAAD),
743  tXAW(_p->tXAW), tXP(_p->tXP), tXS(_p->tXS),
744  clkResyncDelay(tCL + _p->tBURST_MAX),
745  dataClockSync(_p->data_clock_sync),
746  burstInterleave(tBURST != tBURST_MIN),
747  twoCycleActivate(_p->two_cycle_activate),
748  activationLimit(_p->activation_limit),
749  wrToRdDlySameBG(tCL + _p->tBURST_MAX + _p->tWTR_L),
750  rdToWrDlySameBG(_p->tRTW + _p->tBURST_MAX),
751  pageMgmt(_p->page_policy),
752  maxAccessesPerRow(_p->max_accesses_per_row),
753  timeStampOffset(0), activeRank(0),
754  enableDRAMPowerdown(_p->enable_dram_powerdown),
755  lastStatsResetTick(0),
756  stats(*this)
757 {
758  DPRINTF(DRAM, "Setting up DRAM Interface\n");
759 
760  fatal_if(!isPowerOf2(burstSize), "DRAM burst size %d is not allowed, "
761  "must be a power of two\n", burstSize);
762 
763  // sanity check the ranks since we rely on bit slicing for the
764  // address decoding
765  fatal_if(!isPowerOf2(ranksPerChannel), "DRAM rank count of %d is "
766  "not allowed, must be a power of two\n", ranksPerChannel);
767 
768  for (int i = 0; i < ranksPerChannel; i++) {
769  DPRINTF(DRAM, "Creating DRAM rank %d \n", i);
770  Rank* rank = new Rank(_p, i, *this);
771  ranks.push_back(rank);
772  }
773 
774  // determine the dram actual capacity from the DRAM config in Mbytes
775  uint64_t deviceCapacity = deviceSize / (1024 * 1024) * devicesPerRank *
777 
778  uint64_t capacity = ULL(1) << ceilLog2(AbstractMemory::size());
779 
780  DPRINTF(DRAM, "Memory capacity %lld (%lld) bytes\n", capacity,
782 
783  // if actual DRAM size does not match memory capacity in system warn!
784  if (deviceCapacity != capacity / (1024 * 1024))
785  warn("DRAM device capacity (%d Mbytes) does not match the "
786  "address range assigned (%d Mbytes)\n", deviceCapacity,
787  capacity / (1024 * 1024));
788 
789  DPRINTF(DRAM, "Row buffer size %d bytes with %d bursts per row buffer\n",
791 
793 
794  // some basic sanity checks
795  if (tREFI <= tRP || tREFI <= tRFC) {
796  fatal("tREFI (%d) must be larger than tRP (%d) and tRFC (%d)\n",
797  tREFI, tRP, tRFC);
798  }
799 
800  // basic bank group architecture checks ->
801  if (bankGroupArch) {
802  // must have at least one bank per bank group
804  fatal("banks per rank (%d) must be equal to or larger than "
805  "banks groups per rank (%d)\n",
807  }
808  // must have same number of banks in each bank group
809  if ((banksPerRank % bankGroupsPerRank) != 0) {
810  fatal("Banks per rank (%d) must be evenly divisible by bank "
811  "groups per rank (%d) for equal banks per bank group\n",
813  }
814  // tCCD_L should be greater than minimal, back-to-back burst delay
815  if (tCCD_L <= tBURST) {
816  fatal("tCCD_L (%d) should be larger than the minimum bus delay "
817  "(%d) when bank groups per rank (%d) is greater than 1\n",
819  }
820  // tCCD_L_WR should be greater than minimal, back-to-back burst delay
821  if (tCCD_L_WR <= tBURST) {
822  fatal("tCCD_L_WR (%d) should be larger than the minimum bus delay "
823  " (%d) when bank groups per rank (%d) is greater than 1\n",
825  }
826  // tRRD_L is greater than minimal, same bank group ACT-to-ACT delay
827  // some datasheets might specify it equal to tRRD
828  if (tRRD_L < tRRD) {
829  fatal("tRRD_L (%d) should be larger than tRRD (%d) when "
830  "bank groups per rank (%d) is greater than 1\n",
832  }
833  }
834 }
835 
836 void
838 {
840 
841  // a bit of sanity checks on the interleaving, save it for here to
842  // ensure that the system pointer is initialised
843  if (range.interleaved()) {
844  if (addrMapping == Enums::RoRaBaChCo) {
845  if (rowBufferSize != range.granularity()) {
846  fatal("Channel interleaving of %s doesn't match RoRaBaChCo "
847  "address map\n", name());
848  }
849  } else if (addrMapping == Enums::RoRaBaCoCh ||
850  addrMapping == Enums::RoCoRaBaCh) {
851  // for the interleavings with channel bits in the bottom,
852  // if the system uses a channel striping granularity that
853  // is larger than the DRAM burst size, then map the
854  // sequential accesses within a stripe to a number of
855  // columns in the DRAM, effectively placing some of the
856  // lower-order column bits as the least-significant bits
857  // of the address (above the ones denoting the burst size)
858  assert(burstsPerStripe >= 1);
859 
860  // channel striping has to be done at a granularity that
861  // is equal or larger to a cache line
862  if (system()->cacheLineSize() > range.granularity()) {
863  fatal("Channel interleaving of %s must be at least as large "
864  "as the cache line size\n", name());
865  }
866 
867  // ...and equal or smaller than the row-buffer size
868  if (rowBufferSize < range.granularity()) {
869  fatal("Channel interleaving of %s must be at most as large "
870  "as the row-buffer size\n", name());
871  }
872  // this is essentially the check above, so just to be sure
874  }
875  }
876 }
877 
878 void
880 {
881  if (system()->isTimingMode()) {
882  // timestamp offset should be in clock cycles for DRAMPower
884 
885  for (auto r : ranks) {
886  r->startup(curTick() + tREFI - tRP);
887  }
888  }
889 }
890 
891 bool
893 {
894  int busy_ranks = 0;
895  for (auto r : ranks) {
896  if (!r->inRefIdleState()) {
897  if (r->pwrState != PWR_SREF) {
898  // rank is busy refreshing
899  DPRINTF(DRAMState, "Rank %d is not available\n", r->rank);
900  busy_ranks++;
901 
902  // let the rank know that if it was waiting to drain, it
903  // is now done and ready to proceed
904  r->checkDrainDone();
905  }
906 
907  // check if we were in self-refresh and haven't started
908  // to transition out
909  if ((r->pwrState == PWR_SREF) && r->inLowPowerState) {
910  DPRINTF(DRAMState, "Rank %d is in self-refresh\n", r->rank);
911  // if we have commands queued to this rank and we don't have
912  // a minimum number of active commands enqueued,
913  // exit self-refresh
914  if (r->forceSelfRefreshExit()) {
915  DPRINTF(DRAMState, "rank %d was in self refresh and"
916  " should wake up\n", r->rank);
917  //wake up from self-refresh
918  r->scheduleWakeUpEvent(tXS);
919  // things are brought back into action once a refresh is
920  // performed after self-refresh
921  // continue with selection for other ranks
922  }
923  }
924  }
925  }
926  return (busy_ranks == ranksPerChannel);
927 }
928 
929 void DRAMInterface::setupRank(const uint8_t rank, const bool is_read)
930 {
931  // increment entry count of the rank based on packet type
932  if (is_read) {
933  ++ranks[rank]->readEntries;
934  } else {
935  ++ranks[rank]->writeEntries;
936  }
937 }
938 
939 void
941 {
942  Rank& rank_ref = *ranks[rank];
943 
944  // if a read has reached its ready-time, decrement the number of reads
945  // At this point the packet has been handled and there is a possibility
946  // to switch to low-power mode if no other packet is available
947  --rank_ref.readEntries;
948  DPRINTF(DRAM, "number of read entries for rank %d is %d\n",
949  rank, rank_ref.readEntries);
950 
951  // counter should at least indicate one outstanding request
952  // for this read
953  assert(rank_ref.outstandingEvents > 0);
954  // read response received, decrement count
955  --rank_ref.outstandingEvents;
956 
957  // at this moment should not have transitioned to a low-power state
958  assert((rank_ref.pwrState != PWR_SREF) &&
959  (rank_ref.pwrState != PWR_PRE_PDN) &&
960  (rank_ref.pwrState != PWR_ACT_PDN));
961 
962  // track if this is the last packet before idling
963  // and that there are no outstanding commands to this rank
964  if (rank_ref.isQueueEmpty() && rank_ref.outstandingEvents == 0 &&
965  rank_ref.inRefIdleState() && enableDRAMPowerdown) {
966  // verify that there are no events scheduled
967  assert(!rank_ref.activateEvent.scheduled());
968  assert(!rank_ref.prechargeEvent.scheduled());
969 
970  // if coming from active state, schedule power event to
971  // active power-down else go to precharge power-down
972  DPRINTF(DRAMState, "Rank %d sleep at tick %d; current power state is "
973  "%d\n", rank, curTick(), rank_ref.pwrState);
974 
975  // default to ACT power-down unless already in IDLE state
976  // could be in IDLE if PRE issued before data returned
977  PowerState next_pwr_state = PWR_ACT_PDN;
978  if (rank_ref.pwrState == PWR_IDLE) {
979  next_pwr_state = PWR_PRE_PDN;
980  }
981 
982  rank_ref.powerDownSleep(next_pwr_state, curTick());
983  }
984 }
985 
986 void
988 {
989  Rank& rank_ref = *ranks[rank];
990 
991  if ((rank_ref.refreshState == REF_PRE) &&
992  !rank_ref.prechargeEvent.scheduled()) {
993  // kick the refresh event loop into action again if banks already
994  // closed and just waiting for read to complete
995  schedule(rank_ref.refreshEvent, curTick());
996  }
997 }
998 
999 void
1001 {
1002  // also need to kick off events to exit self-refresh
1003  for (auto r : ranks) {
1004  // force self-refresh exit, which in turn will issue auto-refresh
1005  if (r->pwrState == PWR_SREF) {
1006  DPRINTF(DRAM,"Rank%d: Forcing self-refresh wakeup in drain\n",
1007  r->rank);
1008  r->scheduleWakeUpEvent(tXS);
1009  }
1010  }
1011 }
1012 
1013 bool
1015 {
1016  // true until proven false
1017  bool all_ranks_drained = true;
1018  for (auto r : ranks) {
1019  // then verify that the power state is IDLE ensuring all banks are
1020  // closed and rank is not in a low power state. Also verify that rank
1021  // is idle from a refresh point of view.
1022  all_ranks_drained = r->inPwrIdleState() && r->inRefIdleState() &&
1023  all_ranks_drained;
1024  }
1025  return all_ranks_drained;
1026 }
1027 
1028 void
1030 {
1031  for (auto r : ranks) {
1032  r->suspend();
1033  }
1034 }
1035 
1036 pair<vector<uint32_t>, bool>
1038  Tick min_col_at) const
1039 {
1040  Tick min_act_at = MaxTick;
1041  vector<uint32_t> bank_mask(ranksPerChannel, 0);
1042 
1043  // latest Tick for which ACT can occur without incurring additoinal
1044  // delay on the data bus
1045  const Tick hidden_act_max = std::max(min_col_at - tRCD, curTick());
1046 
1047  // Flag condition when burst can issue back-to-back with previous burst
1048  bool found_seamless_bank = false;
1049 
1050  // Flag condition when bank can be opened without incurring additional
1051  // delay on the data bus
1052  bool hidden_bank_prep = false;
1053 
1054  // determine if we have queued transactions targetting the
1055  // bank in question
1056  vector<bool> got_waiting(ranksPerChannel * banksPerRank, false);
1057  for (const auto& p : queue) {
1058  if (p->isDram() && ranks[p->rank]->inRefIdleState())
1059  got_waiting[p->bankId] = true;
1060  }
1061 
1062  // Find command with optimal bank timing
1063  // Will prioritize commands that can issue seamlessly.
1064  for (int i = 0; i < ranksPerChannel; i++) {
1065  for (int j = 0; j < banksPerRank; j++) {
1066  uint16_t bank_id = i * banksPerRank + j;
1067 
1068  // if we have waiting requests for the bank, and it is
1069  // amongst the first available, update the mask
1070  if (got_waiting[bank_id]) {
1071  // make sure this rank is not currently refreshing.
1072  assert(ranks[i]->inRefIdleState());
1073  // simplistic approximation of when the bank can issue
1074  // an activate, ignoring any rank-to-rank switching
1075  // cost in this calculation
1076  Tick act_at = ranks[i]->banks[j].openRow == Bank::NO_ROW ?
1077  std::max(ranks[i]->banks[j].actAllowedAt, curTick()) :
1078  std::max(ranks[i]->banks[j].preAllowedAt, curTick()) + tRP;
1079 
1080  // When is the earliest the R/W burst can issue?
1081  const Tick col_allowed_at = ctrl->inReadBusState(false) ?
1082  ranks[i]->banks[j].rdAllowedAt :
1083  ranks[i]->banks[j].wrAllowedAt;
1084  Tick col_at = std::max(col_allowed_at, act_at + tRCD);
1085 
1086  // bank can issue burst back-to-back (seamlessly) with
1087  // previous burst
1088  bool new_seamless_bank = col_at <= min_col_at;
1089 
1090  // if we found a new seamless bank or we have no
1091  // seamless banks, and got a bank with an earlier
1092  // activate time, it should be added to the bit mask
1093  if (new_seamless_bank ||
1094  (!found_seamless_bank && act_at <= min_act_at)) {
1095  // if we did not have a seamless bank before, and
1096  // we do now, reset the bank mask, also reset it
1097  // if we have not yet found a seamless bank and
1098  // the activate time is smaller than what we have
1099  // seen so far
1100  if (!found_seamless_bank &&
1101  (new_seamless_bank || act_at < min_act_at)) {
1102  std::fill(bank_mask.begin(), bank_mask.end(), 0);
1103  }
1104 
1105  found_seamless_bank |= new_seamless_bank;
1106 
1107  // ACT can occur 'behind the scenes'
1108  hidden_bank_prep = act_at <= hidden_act_max;
1109 
1110  // set the bit corresponding to the available bank
1111  replaceBits(bank_mask[i], j, j, 1);
1112  min_act_at = act_at;
1113  }
1114  }
1115  }
1116  }
1117 
1118  return make_pair(bank_mask, hidden_bank_prep);
1119 }
1120 
1122 DRAMInterfaceParams::create()
1123 {
1124  return new DRAMInterface(this);
1125 }
1126 
1127 DRAMInterface::Rank::Rank(const DRAMInterfaceParams* _p,
1128  int _rank, DRAMInterface& _dram)
1129  : EventManager(&_dram), dram(_dram),
1130  pwrStateTrans(PWR_IDLE), pwrStatePostRefresh(PWR_IDLE),
1131  pwrStateTick(0), refreshDueAt(0), pwrState(PWR_IDLE),
1132  refreshState(REF_IDLE), inLowPowerState(false), rank(_rank),
1133  readEntries(0), writeEntries(0), outstandingEvents(0),
1134  wakeUpAllowedAt(0), power(_p, false), banks(_p->banks_per_rank),
1135  numBanksActive(0), actTicks(_p->activation_limit, 0), lastBurstTick(0),
1136  writeDoneEvent([this]{ processWriteDoneEvent(); }, name()),
1137  activateEvent([this]{ processActivateEvent(); }, name()),
1138  prechargeEvent([this]{ processPrechargeEvent(); }, name()),
1139  refreshEvent([this]{ processRefreshEvent(); }, name()),
1140  powerEvent([this]{ processPowerEvent(); }, name()),
1141  wakeUpEvent([this]{ processWakeUpEvent(); }, name()),
1142  stats(_dram, *this)
1143 {
1144  for (int b = 0; b < _p->banks_per_rank; b++) {
1145  banks[b].bank = b;
1146  // GDDR addressing of banks to BG is linear.
1147  // Here we assume that all DRAM generations address bank groups as
1148  // follows:
1149  if (_p->bank_groups_per_rank > 0) {
1150  // Simply assign lower bits to bank group in order to
1151  // rotate across bank groups as banks are incremented
1152  // e.g. with 4 banks per bank group and 16 banks total:
1153  // banks 0,4,8,12 are in bank group 0
1154  // banks 1,5,9,13 are in bank group 1
1155  // banks 2,6,10,14 are in bank group 2
1156  // banks 3,7,11,15 are in bank group 3
1157  banks[b].bankgr = b % _p->bank_groups_per_rank;
1158  } else {
1159  // No bank groups; simply assign to bank number
1160  banks[b].bankgr = b;
1161  }
1162  }
1163 }
1164 
1165 void
1167 {
1168  assert(ref_tick > curTick());
1169 
1170  pwrStateTick = curTick();
1171 
1172  // kick off the refresh, and give ourselves enough time to
1173  // precharge
1174  schedule(refreshEvent, ref_tick);
1175 }
1176 
1177 void
1179 {
1180  deschedule(refreshEvent);
1181 
1182  // Update the stats
1183  updatePowerStats();
1184 
1185  // don't automatically transition back to LP state after next REF
1186  pwrStatePostRefresh = PWR_IDLE;
1187 }
1188 
1189 bool
1191 {
1192  // check commmands in Q based on current bus direction
1193  bool no_queued_cmds = (dram.ctrl->inReadBusState(true) &&
1194  (readEntries == 0))
1195  || (dram.ctrl->inWriteBusState(true) &&
1196  (writeEntries == 0));
1197  return no_queued_cmds;
1198 }
1199 
1200 void
1202 {
1203  // if this rank was waiting to drain it is now able to proceed to
1204  // precharge
1205  if (refreshState == REF_DRAIN) {
1206  DPRINTF(DRAM, "Refresh drain done, now precharging\n");
1207 
1208  refreshState = REF_PD_EXIT;
1209 
1210  // hand control back to the refresh event loop
1211  schedule(refreshEvent, curTick());
1212  }
1213 }
1214 
1215 void
1217 {
1218  // at the moment sort the list of commands and update the counters
1219  // for DRAMPower libray when doing a refresh
1220  sort(cmdList.begin(), cmdList.end(), DRAMInterface::sortTime);
1221 
1222  auto next_iter = cmdList.begin();
1223  // push to commands to DRAMPower
1224  for ( ; next_iter != cmdList.end() ; ++next_iter) {
1225  Command cmd = *next_iter;
1226  if (cmd.timeStamp <= curTick()) {
1227  // Move all commands at or before curTick to DRAMPower
1228  power.powerlib.doCommand(cmd.type, cmd.bank,
1229  divCeil(cmd.timeStamp, dram.tCK) -
1230  dram.timeStampOffset);
1231  } else {
1232  // done - found all commands at or before curTick()
1233  // next_iter references the 1st command after curTick
1234  break;
1235  }
1236  }
1237  // reset cmdList to only contain commands after curTick
1238  // if there are no commands after curTick, updated cmdList will be empty
1239  // in this case, next_iter is cmdList.end()
1240  cmdList.assign(next_iter, cmdList.end());
1241 }
1242 
1243 void
1245 {
1246  // we should transition to the active state as soon as any bank is active
1247  if (pwrState != PWR_ACT)
1248  // note that at this point numBanksActive could be back at
1249  // zero again due to a precharge scheduled in the future
1250  schedulePowerEvent(PWR_ACT, curTick());
1251 }
1252 
1253 void
1255 {
1256  // counter should at least indicate one outstanding request
1257  // for this precharge
1258  assert(outstandingEvents > 0);
1259  // precharge complete, decrement count
1260  --outstandingEvents;
1261 
1262  // if we reached zero, then special conditions apply as we track
1263  // if all banks are precharged for the power models
1264  if (numBanksActive == 0) {
1265  // no reads to this rank in the Q and no pending
1266  // RD/WR or refresh commands
1267  if (isQueueEmpty() && outstandingEvents == 0 &&
1268  dram.enableDRAMPowerdown) {
1269  // should still be in ACT state since bank still open
1270  assert(pwrState == PWR_ACT);
1271 
1272  // All banks closed - switch to precharge power down state.
1273  DPRINTF(DRAMState, "Rank %d sleep at tick %d\n",
1274  rank, curTick());
1275  powerDownSleep(PWR_PRE_PDN, curTick());
1276  } else {
1277  // we should transition to the idle state when the last bank
1278  // is precharged
1279  schedulePowerEvent(PWR_IDLE, curTick());
1280  }
1281  }
1282 }
1283 
1284 void
1286 {
1287  // counter should at least indicate one outstanding request
1288  // for this write
1289  assert(outstandingEvents > 0);
1290  // Write transfer on bus has completed
1291  // decrement per rank counter
1292  --outstandingEvents;
1293 }
1294 
1295 void
1297 {
1298  // when first preparing the refresh, remember when it was due
1299  if ((refreshState == REF_IDLE) || (refreshState == REF_SREF_EXIT)) {
1300  // remember when the refresh is due
1301  refreshDueAt = curTick();
1302 
1303  // proceed to drain
1304  refreshState = REF_DRAIN;
1305 
1306  // make nonzero while refresh is pending to ensure
1307  // power down and self-refresh are not entered
1308  ++outstandingEvents;
1309 
1310  DPRINTF(DRAM, "Refresh due\n");
1311  }
1312 
1313  // let any scheduled read or write to the same rank go ahead,
1314  // after which it will
1315  // hand control back to this event loop
1316  if (refreshState == REF_DRAIN) {
1317  // if a request is at the moment being handled and this request is
1318  // accessing the current rank then wait for it to finish
1319  if ((rank == dram.activeRank)
1320  && (dram.ctrl->requestEventScheduled())) {
1321  // hand control over to the request loop until it is
1322  // evaluated next
1323  DPRINTF(DRAM, "Refresh awaiting draining\n");
1324 
1325  return;
1326  } else {
1327  refreshState = REF_PD_EXIT;
1328  }
1329  }
1330 
1331  // at this point, ensure that rank is not in a power-down state
1332  if (refreshState == REF_PD_EXIT) {
1333  // if rank was sleeping and we have't started exit process,
1334  // wake-up for refresh
1335  if (inLowPowerState) {
1336  DPRINTF(DRAM, "Wake Up for refresh\n");
1337  // save state and return after refresh completes
1338  scheduleWakeUpEvent(dram.tXP);
1339  return;
1340  } else {
1341  refreshState = REF_PRE;
1342  }
1343  }
1344 
1345  // at this point, ensure that all banks are precharged
1346  if (refreshState == REF_PRE) {
1347  // precharge any active bank
1348  if (numBanksActive != 0) {
1349  // at the moment, we use a precharge all even if there is
1350  // only a single bank open
1351  DPRINTF(DRAM, "Precharging all\n");
1352 
1353  // first determine when we can precharge
1354  Tick pre_at = curTick();
1355 
1356  for (auto &b : banks) {
1357  // respect both causality and any existing bank
1358  // constraints, some banks could already have a
1359  // (auto) precharge scheduled
1360  pre_at = std::max(b.preAllowedAt, pre_at);
1361  }
1362 
1363  // make sure all banks per rank are precharged, and for those that
1364  // already are, update their availability
1365  Tick act_allowed_at = pre_at + dram.tRP;
1366 
1367  for (auto &b : banks) {
1368  if (b.openRow != Bank::NO_ROW) {
1369  dram.prechargeBank(*this, b, pre_at, true, false);
1370  } else {
1371  b.actAllowedAt = std::max(b.actAllowedAt, act_allowed_at);
1372  b.preAllowedAt = std::max(b.preAllowedAt, pre_at);
1373  }
1374  }
1375 
1376  // precharge all banks in rank
1377  cmdList.push_back(Command(MemCommand::PREA, 0, pre_at));
1378 
1379  DPRINTF(DRAMPower, "%llu,PREA,0,%d\n",
1380  divCeil(pre_at, dram.tCK) -
1381  dram.timeStampOffset, rank);
1382  } else if ((pwrState == PWR_IDLE) && (outstandingEvents == 1)) {
1383  // Banks are closed, have transitioned to IDLE state, and
1384  // no outstanding ACT,RD/WR,Auto-PRE sequence scheduled
1385  DPRINTF(DRAM, "All banks already precharged, starting refresh\n");
1386 
1387  // go ahead and kick the power state machine into gear since
1388  // we are already idle
1389  schedulePowerEvent(PWR_REF, curTick());
1390  } else {
1391  // banks state is closed but haven't transitioned pwrState to IDLE
1392  // or have outstanding ACT,RD/WR,Auto-PRE sequence scheduled
1393  // should have outstanding precharge or read response event
1394  assert(prechargeEvent.scheduled() ||
1395  dram.ctrl->respondEventScheduled());
1396  // will start refresh when pwrState transitions to IDLE
1397  }
1398 
1399  assert(numBanksActive == 0);
1400 
1401  // wait for all banks to be precharged or read to complete
1402  // When precharge commands are done, power state machine will
1403  // transition to the idle state, and automatically move to a
1404  // refresh, at that point it will also call this method to get
1405  // the refresh event loop going again
1406  // Similarly, when read response completes, if all banks are
1407  // precharged, will call this method to get loop re-started
1408  return;
1409  }
1410 
1411  // last but not least we perform the actual refresh
1412  if (refreshState == REF_START) {
1413  // should never get here with any banks active
1414  assert(numBanksActive == 0);
1415  assert(pwrState == PWR_REF);
1416 
1417  Tick ref_done_at = curTick() + dram.tRFC;
1418 
1419  for (auto &b : banks) {
1420  b.actAllowedAt = ref_done_at;
1421  }
1422 
1423  // at the moment this affects all ranks
1424  cmdList.push_back(Command(MemCommand::REF, 0, curTick()));
1425 
1426  // Update the stats
1427  updatePowerStats();
1428 
1429  DPRINTF(DRAMPower, "%llu,REF,0,%d\n", divCeil(curTick(), dram.tCK) -
1430  dram.timeStampOffset, rank);
1431 
1432  // Update for next refresh
1433  refreshDueAt += dram.tREFI;
1434 
1435  // make sure we did not wait so long that we cannot make up
1436  // for it
1437  if (refreshDueAt < ref_done_at) {
1438  fatal("Refresh was delayed so long we cannot catch up\n");
1439  }
1440 
1441  // Run the refresh and schedule event to transition power states
1442  // when refresh completes
1443  refreshState = REF_RUN;
1444  schedule(refreshEvent, ref_done_at);
1445  return;
1446  }
1447 
1448  if (refreshState == REF_RUN) {
1449  // should never get here with any banks active
1450  assert(numBanksActive == 0);
1451  assert(pwrState == PWR_REF);
1452 
1453  assert(!powerEvent.scheduled());
1454 
1455  if ((dram.ctrl->drainState() == DrainState::Draining) ||
1456  (dram.ctrl->drainState() == DrainState::Drained)) {
1457  // if draining, do not re-enter low-power mode.
1458  // simply go to IDLE and wait
1459  schedulePowerEvent(PWR_IDLE, curTick());
1460  } else {
1461  // At the moment, we sleep when the refresh ends and wait to be
1462  // woken up again if previously in a low-power state.
1463  if (pwrStatePostRefresh != PWR_IDLE) {
1464  // power State should be power Refresh
1465  assert(pwrState == PWR_REF);
1466  DPRINTF(DRAMState, "Rank %d sleeping after refresh and was in "
1467  "power state %d before refreshing\n", rank,
1468  pwrStatePostRefresh);
1469  powerDownSleep(pwrState, curTick());
1470 
1471  // Force PRE power-down if there are no outstanding commands
1472  // in Q after refresh.
1473  } else if (isQueueEmpty() && dram.enableDRAMPowerdown) {
1474  // still have refresh event outstanding but there should
1475  // be no other events outstanding
1476  assert(outstandingEvents == 1);
1477  DPRINTF(DRAMState, "Rank %d sleeping after refresh but was NOT"
1478  " in a low power state before refreshing\n", rank);
1479  powerDownSleep(PWR_PRE_PDN, curTick());
1480 
1481  } else {
1482  // move to the idle power state once the refresh is done, this
1483  // will also move the refresh state machine to the refresh
1484  // idle state
1485  schedulePowerEvent(PWR_IDLE, curTick());
1486  }
1487  }
1488 
1489  // At this point, we have completed the current refresh.
1490  // In the SREF bypass case, we do not get to this state in the
1491  // refresh STM and therefore can always schedule next event.
1492  // Compensate for the delay in actually performing the refresh
1493  // when scheduling the next one
1494  schedule(refreshEvent, refreshDueAt - dram.tRP);
1495 
1496  DPRINTF(DRAMState, "Refresh done at %llu and next refresh"
1497  " at %llu\n", curTick(), refreshDueAt);
1498  }
1499 }
1500 
1501 void
1503 {
1504  // respect causality
1505  assert(tick >= curTick());
1506 
1507  if (!powerEvent.scheduled()) {
1508  DPRINTF(DRAMState, "Scheduling power event at %llu to state %d\n",
1509  tick, pwr_state);
1510 
1511  // insert the new transition
1512  pwrStateTrans = pwr_state;
1513 
1514  schedule(powerEvent, tick);
1515  } else {
1516  panic("Scheduled power event at %llu to state %d, "
1517  "with scheduled event at %llu to %d\n", tick, pwr_state,
1518  powerEvent.when(), pwrStateTrans);
1519  }
1520 }
1521 
1522 void
1524 {
1525  // if low power state is active low, schedule to active low power state.
1526  // in reality tCKE is needed to enter active low power. This is neglected
1527  // here and could be added in the future.
1528  if (pwr_state == PWR_ACT_PDN) {
1529  schedulePowerEvent(pwr_state, tick);
1530  // push command to DRAMPower
1531  cmdList.push_back(Command(MemCommand::PDN_F_ACT, 0, tick));
1532  DPRINTF(DRAMPower, "%llu,PDN_F_ACT,0,%d\n", divCeil(tick,
1533  dram.tCK) - dram.timeStampOffset, rank);
1534  } else if (pwr_state == PWR_PRE_PDN) {
1535  // if low power state is precharge low, schedule to precharge low
1536  // power state. In reality tCKE is needed to enter active low power.
1537  // This is neglected here.
1538  schedulePowerEvent(pwr_state, tick);
1539  //push Command to DRAMPower
1540  cmdList.push_back(Command(MemCommand::PDN_F_PRE, 0, tick));
1541  DPRINTF(DRAMPower, "%llu,PDN_F_PRE,0,%d\n", divCeil(tick,
1542  dram.tCK) - dram.timeStampOffset, rank);
1543  } else if (pwr_state == PWR_REF) {
1544  // if a refresh just occurred
1545  // transition to PRE_PDN now that all banks are closed
1546  // precharge power down requires tCKE to enter. For simplicity
1547  // this is not considered.
1548  schedulePowerEvent(PWR_PRE_PDN, tick);
1549  //push Command to DRAMPower
1550  cmdList.push_back(Command(MemCommand::PDN_F_PRE, 0, tick));
1551  DPRINTF(DRAMPower, "%llu,PDN_F_PRE,0,%d\n", divCeil(tick,
1552  dram.tCK) - dram.timeStampOffset, rank);
1553  } else if (pwr_state == PWR_SREF) {
1554  // should only enter SREF after PRE-PD wakeup to do a refresh
1555  assert(pwrStatePostRefresh == PWR_PRE_PDN);
1556  // self refresh requires time tCKESR to enter. For simplicity,
1557  // this is not considered.
1558  schedulePowerEvent(PWR_SREF, tick);
1559  // push Command to DRAMPower
1560  cmdList.push_back(Command(MemCommand::SREN, 0, tick));
1561  DPRINTF(DRAMPower, "%llu,SREN,0,%d\n", divCeil(tick,
1562  dram.tCK) - dram.timeStampOffset, rank);
1563  }
1564  // Ensure that we don't power-down and back up in same tick
1565  // Once we commit to PD entry, do it and wait for at least 1tCK
1566  // This could be replaced with tCKE if/when that is added to the model
1567  wakeUpAllowedAt = tick + dram.tCK;
1568 
1569  // Transitioning to a low power state, set flag
1570  inLowPowerState = true;
1571 }
1572 
1573 void
1575 {
1576  Tick wake_up_tick = std::max(curTick(), wakeUpAllowedAt);
1577 
1578  DPRINTF(DRAMState, "Scheduling wake-up for rank %d at tick %d\n",
1579  rank, wake_up_tick);
1580 
1581  // if waking for refresh, hold previous state
1582  // else reset state back to IDLE
1583  if (refreshState == REF_PD_EXIT) {
1584  pwrStatePostRefresh = pwrState;
1585  } else {
1586  // don't automatically transition back to LP state after next REF
1587  pwrStatePostRefresh = PWR_IDLE;
1588  }
1589 
1590  // schedule wake-up with event to ensure entry has completed before
1591  // we try to wake-up
1592  schedule(wakeUpEvent, wake_up_tick);
1593 
1594  for (auto &b : banks) {
1595  // respect both causality and any existing bank
1596  // constraints, some banks could already have a
1597  // (auto) precharge scheduled
1598  b.wrAllowedAt = std::max(wake_up_tick + exit_delay, b.wrAllowedAt);
1599  b.rdAllowedAt = std::max(wake_up_tick + exit_delay, b.rdAllowedAt);
1600  b.preAllowedAt = std::max(wake_up_tick + exit_delay, b.preAllowedAt);
1601  b.actAllowedAt = std::max(wake_up_tick + exit_delay, b.actAllowedAt);
1602  }
1603  // Transitioning out of low power state, clear flag
1604  inLowPowerState = false;
1605 
1606  // push to DRAMPower
1607  // use pwrStateTrans for cases where we have a power event scheduled
1608  // to enter low power that has not yet been processed
1609  if (pwrStateTrans == PWR_ACT_PDN) {
1610  cmdList.push_back(Command(MemCommand::PUP_ACT, 0, wake_up_tick));
1611  DPRINTF(DRAMPower, "%llu,PUP_ACT,0,%d\n", divCeil(wake_up_tick,
1612  dram.tCK) - dram.timeStampOffset, rank);
1613 
1614  } else if (pwrStateTrans == PWR_PRE_PDN) {
1615  cmdList.push_back(Command(MemCommand::PUP_PRE, 0, wake_up_tick));
1616  DPRINTF(DRAMPower, "%llu,PUP_PRE,0,%d\n", divCeil(wake_up_tick,
1617  dram.tCK) - dram.timeStampOffset, rank);
1618  } else if (pwrStateTrans == PWR_SREF) {
1619  cmdList.push_back(Command(MemCommand::SREX, 0, wake_up_tick));
1620  DPRINTF(DRAMPower, "%llu,SREX,0,%d\n", divCeil(wake_up_tick,
1621  dram.tCK) - dram.timeStampOffset, rank);
1622  }
1623 }
1624 
1625 void
1627 {
1628  // Should be in a power-down or self-refresh state
1629  assert((pwrState == PWR_ACT_PDN) || (pwrState == PWR_PRE_PDN) ||
1630  (pwrState == PWR_SREF));
1631 
1632  // Check current state to determine transition state
1633  if (pwrState == PWR_ACT_PDN) {
1634  // banks still open, transition to PWR_ACT
1635  schedulePowerEvent(PWR_ACT, curTick());
1636  } else {
1637  // transitioning from a precharge power-down or self-refresh state
1638  // banks are closed - transition to PWR_IDLE
1639  schedulePowerEvent(PWR_IDLE, curTick());
1640  }
1641 }
1642 
1643 void
1645 {
1646  assert(curTick() >= pwrStateTick);
1647  // remember where we were, and for how long
1648  Tick duration = curTick() - pwrStateTick;
1649  PowerState prev_state = pwrState;
1650 
1651  // update the accounting
1652  stats.pwrStateTime[prev_state] += duration;
1653 
1654  // track to total idle time
1655  if ((prev_state == PWR_PRE_PDN) || (prev_state == PWR_ACT_PDN) ||
1656  (prev_state == PWR_SREF)) {
1657  stats.totalIdleTime += duration;
1658  }
1659 
1660  pwrState = pwrStateTrans;
1661  pwrStateTick = curTick();
1662 
1663  // if rank was refreshing, make sure to start scheduling requests again
1664  if (prev_state == PWR_REF) {
1665  // bus IDLED prior to REF
1666  // counter should be one for refresh command only
1667  assert(outstandingEvents == 1);
1668  // REF complete, decrement count and go back to IDLE
1669  --outstandingEvents;
1670  refreshState = REF_IDLE;
1671 
1672  DPRINTF(DRAMState, "Was refreshing for %llu ticks\n", duration);
1673  // if moving back to power-down after refresh
1674  if (pwrState != PWR_IDLE) {
1675  assert(pwrState == PWR_PRE_PDN);
1676  DPRINTF(DRAMState, "Switching to power down state after refreshing"
1677  " rank %d at %llu tick\n", rank, curTick());
1678  }
1679 
1680  // completed refresh event, ensure next request is scheduled
1681  if (!dram.ctrl->requestEventScheduled()) {
1682  DPRINTF(DRAM, "Scheduling next request after refreshing"
1683  " rank %d\n", rank);
1684  dram.ctrl->restartScheduler(curTick());
1685  }
1686  }
1687 
1688  if ((pwrState == PWR_ACT) && (refreshState == REF_PD_EXIT)) {
1689  // have exited ACT PD
1690  assert(prev_state == PWR_ACT_PDN);
1691 
1692  // go back to REF event and close banks
1693  refreshState = REF_PRE;
1694  schedule(refreshEvent, curTick());
1695  } else if (pwrState == PWR_IDLE) {
1696  DPRINTF(DRAMState, "All banks precharged\n");
1697  if (prev_state == PWR_SREF) {
1698  // set refresh state to REF_SREF_EXIT, ensuring inRefIdleState
1699  // continues to return false during tXS after SREF exit
1700  // Schedule a refresh which kicks things back into action
1701  // when it finishes
1702  refreshState = REF_SREF_EXIT;
1703  schedule(refreshEvent, curTick() + dram.tXS);
1704  } else {
1705  // if we have a pending refresh, and are now moving to
1706  // the idle state, directly transition to, or schedule refresh
1707  if ((refreshState == REF_PRE) || (refreshState == REF_PD_EXIT)) {
1708  // ensure refresh is restarted only after final PRE command.
1709  // do not restart refresh if controller is in an intermediate
1710  // state, after PRE_PDN exit, when banks are IDLE but an
1711  // ACT is scheduled.
1712  if (!activateEvent.scheduled()) {
1713  // there should be nothing waiting at this point
1714  assert(!powerEvent.scheduled());
1715  if (refreshState == REF_PD_EXIT) {
1716  // exiting PRE PD, will be in IDLE until tXP expires
1717  // and then should transition to PWR_REF state
1718  assert(prev_state == PWR_PRE_PDN);
1719  schedulePowerEvent(PWR_REF, curTick() + dram.tXP);
1720  } else if (refreshState == REF_PRE) {
1721  // can directly move to PWR_REF state and proceed below
1722  pwrState = PWR_REF;
1723  }
1724  } else {
1725  // must have PRE scheduled to transition back to IDLE
1726  // and re-kick off refresh
1727  assert(prechargeEvent.scheduled());
1728  }
1729  }
1730  }
1731  }
1732 
1733  // transition to the refresh state and re-start refresh process
1734  // refresh state machine will schedule the next power state transition
1735  if (pwrState == PWR_REF) {
1736  // completed final PRE for refresh or exiting power-down
1737  assert(refreshState == REF_PRE || refreshState == REF_PD_EXIT);
1738 
1739  // exited PRE PD for refresh, with no pending commands
1740  // bypass auto-refresh and go straight to SREF, where memory
1741  // will issue refresh immediately upon entry
1742  if (pwrStatePostRefresh == PWR_PRE_PDN && isQueueEmpty() &&
1743  (dram.ctrl->drainState() != DrainState::Draining) &&
1744  (dram.ctrl->drainState() != DrainState::Drained) &&
1745  dram.enableDRAMPowerdown) {
1746  DPRINTF(DRAMState, "Rank %d bypassing refresh and transitioning "
1747  "to self refresh at %11u tick\n", rank, curTick());
1748  powerDownSleep(PWR_SREF, curTick());
1749 
1750  // Since refresh was bypassed, remove event by decrementing count
1751  assert(outstandingEvents == 1);
1752  --outstandingEvents;
1753 
1754  // reset state back to IDLE temporarily until SREF is entered
1755  pwrState = PWR_IDLE;
1756 
1757  // Not bypassing refresh for SREF entry
1758  } else {
1759  DPRINTF(DRAMState, "Refreshing\n");
1760 
1761  // there should be nothing waiting at this point
1762  assert(!powerEvent.scheduled());
1763 
1764  // kick the refresh event loop into action again, and that
1765  // in turn will schedule a transition to the idle power
1766  // state once the refresh is done
1767  schedule(refreshEvent, curTick());
1768 
1769  // Banks transitioned to IDLE, start REF
1770  refreshState = REF_START;
1771  }
1772  }
1773 
1774 }
1775 
1776 void
1778 {
1779  // All commands up to refresh have completed
1780  // flush cmdList to DRAMPower
1781  flushCmdList();
1782 
1783  // Call the function that calculates window energy at intermediate update
1784  // events like at refresh, stats dump as well as at simulation exit.
1785  // Window starts at the last time the calcWindowEnergy function was called
1786  // and is upto current time.
1787  power.powerlib.calcWindowEnergy(divCeil(curTick(), dram.tCK) -
1788  dram.timeStampOffset);
1789 
1790  // Get the energy from DRAMPower
1791  Data::MemoryPowerModel::Energy energy = power.powerlib.getEnergy();
1792 
1793  // The energy components inside the power lib are calculated over
1794  // the window so accumulate into the corresponding gem5 stat
1795  stats.actEnergy += energy.act_energy * dram.devicesPerRank;
1796  stats.preEnergy += energy.pre_energy * dram.devicesPerRank;
1797  stats.readEnergy += energy.read_energy * dram.devicesPerRank;
1798  stats.writeEnergy += energy.write_energy * dram.devicesPerRank;
1799  stats.refreshEnergy += energy.ref_energy * dram.devicesPerRank;
1800  stats.actBackEnergy += energy.act_stdby_energy * dram.devicesPerRank;
1801  stats.preBackEnergy += energy.pre_stdby_energy * dram.devicesPerRank;
1802  stats.actPowerDownEnergy += energy.f_act_pd_energy * dram.devicesPerRank;
1803  stats.prePowerDownEnergy += energy.f_pre_pd_energy * dram.devicesPerRank;
1804  stats.selfRefreshEnergy += energy.sref_energy * dram.devicesPerRank;
1805 
1806  // Accumulate window energy into the total energy.
1807  stats.totalEnergy += energy.window_energy * dram.devicesPerRank;
1808  // Average power must not be accumulated but calculated over the time
1809  // since last stats reset. SimClock::Frequency is tick period not tick
1810  // frequency.
1811  // energy (pJ) 1e-9
1812  // power (mW) = ----------- * ----------
1813  // time (tick) tick_frequency
1814  stats.averagePower = (stats.totalEnergy.value() /
1815  (curTick() - dram.lastStatsResetTick)) *
1816  (SimClock::Frequency / 1000000000.0);
1817 }
1818 
1819 void
1821 {
1822  DPRINTF(DRAM,"Computing stats due to a dump callback\n");
1823 
1824  // Update the stats
1825  updatePowerStats();
1826 
1827  // final update of power state times
1828  stats.pwrStateTime[pwrState] += (curTick() - pwrStateTick);
1829  pwrStateTick = curTick();
1830 }
1831 
1832 void
1834  // The only way to clear the counters in DRAMPower is to call
1835  // calcWindowEnergy function as that then calls clearCounters. The
1836  // clearCounters method itself is private.
1837  power.powerlib.calcWindowEnergy(divCeil(curTick(), dram.tCK) -
1838  dram.timeStampOffset);
1839 
1840 }
1841 
1842 bool
1844  return (readEntries != 0) ||
1845  (dram.ctrl->inWriteBusState(true) && (writeEntries != 0));
1846 }
1847 
1848 void
1850 {
1851  dram.lastStatsResetTick = curTick();
1852 }
1853 
1855  : Stats::Group(&_dram),
1856  dram(_dram),
1857 
1858  ADD_STAT(readBursts, "Number of DRAM read bursts"),
1859  ADD_STAT(writeBursts, "Number of DRAM write bursts"),
1860 
1861  ADD_STAT(perBankRdBursts, "Per bank write bursts"),
1862  ADD_STAT(perBankWrBursts, "Per bank write bursts"),
1863 
1864  ADD_STAT(totQLat, "Total ticks spent queuing"),
1865  ADD_STAT(totBusLat, "Total ticks spent in databus transfers"),
1866  ADD_STAT(totMemAccLat,
1867  "Total ticks spent from burst creation until serviced "
1868  "by the DRAM"),
1869 
1870  ADD_STAT(avgQLat, "Average queueing delay per DRAM burst"),
1871  ADD_STAT(avgBusLat, "Average bus latency per DRAM burst"),
1872  ADD_STAT(avgMemAccLat, "Average memory access latency per DRAM burst"),
1873 
1874  ADD_STAT(readRowHits, "Number of row buffer hits during reads"),
1875  ADD_STAT(writeRowHits, "Number of row buffer hits during writes"),
1876  ADD_STAT(readRowHitRate, "Row buffer hit rate for reads"),
1877  ADD_STAT(writeRowHitRate, "Row buffer hit rate for writes"),
1878 
1879  ADD_STAT(bytesPerActivate, "Bytes accessed per row activation"),
1880  ADD_STAT(bytesRead, "Total number of bytes read from DRAM"),
1881  ADD_STAT(bytesWritten, "Total number of bytes written to DRAM"),
1882  ADD_STAT(avgRdBW, "Average DRAM read bandwidth in MiBytes/s"),
1883  ADD_STAT(avgWrBW, "Average DRAM write bandwidth in MiBytes/s"),
1884  ADD_STAT(peakBW, "Theoretical peak bandwidth in MiByte/s"),
1885 
1886  ADD_STAT(busUtil, "Data bus utilization in percentage"),
1887  ADD_STAT(busUtilRead, "Data bus utilization in percentage for reads"),
1888  ADD_STAT(busUtilWrite, "Data bus utilization in percentage for writes"),
1889 
1890  ADD_STAT(pageHitRate, "Row buffer hit rate, read and write combined")
1891 
1892 {
1893 }
1894 
1895 void
1897 {
1898  using namespace Stats;
1899 
1900  avgQLat.precision(2);
1901  avgBusLat.precision(2);
1902  avgMemAccLat.precision(2);
1903 
1904  readRowHitRate.precision(2);
1905  writeRowHitRate.precision(2);
1906 
1907  perBankRdBursts.init(dram.banksPerRank * dram.ranksPerChannel);
1908  perBankWrBursts.init(dram.banksPerRank * dram.ranksPerChannel);
1909 
1910  bytesPerActivate
1911  .init(dram.maxAccessesPerRow ?
1912  dram.maxAccessesPerRow : dram.rowBufferSize)
1913  .flags(nozero);
1914 
1915  peakBW.precision(2);
1916  busUtil.precision(2);
1917  busUtilWrite.precision(2);
1918  busUtilRead.precision(2);
1919 
1920  pageHitRate.precision(2);
1921 
1922  // Formula stats
1923  avgQLat = totQLat / readBursts;
1924  avgBusLat = totBusLat / readBursts;
1925  avgMemAccLat = totMemAccLat / readBursts;
1926 
1927  readRowHitRate = (readRowHits / readBursts) * 100;
1928  writeRowHitRate = (writeRowHits / writeBursts) * 100;
1929 
1930  avgRdBW = (bytesRead / 1000000) / simSeconds;
1931  avgWrBW = (bytesWritten / 1000000) / simSeconds;
1932  peakBW = (SimClock::Frequency / dram.burstDelay()) *
1933  dram.bytesPerBurst() / 1000000;
1934 
1935  busUtil = (avgRdBW + avgWrBW) / peakBW * 100;
1936  busUtilRead = avgRdBW / peakBW * 100;
1937  busUtilWrite = avgWrBW / peakBW * 100;
1938 
1939  pageHitRate = (writeRowHits + readRowHits) /
1940  (writeBursts + readBursts) * 100;
1941 }
1942 
1944  : Stats::Group(&_dram, csprintf("rank%d", _rank.rank).c_str()),
1945  rank(_rank),
1946 
1947  ADD_STAT(actEnergy, "Energy for activate commands per rank (pJ)"),
1948  ADD_STAT(preEnergy, "Energy for precharge commands per rank (pJ)"),
1949  ADD_STAT(readEnergy, "Energy for read commands per rank (pJ)"),
1950  ADD_STAT(writeEnergy, "Energy for write commands per rank (pJ)"),
1951  ADD_STAT(refreshEnergy, "Energy for refresh commands per rank (pJ)"),
1952  ADD_STAT(actBackEnergy, "Energy for active background per rank (pJ)"),
1953  ADD_STAT(preBackEnergy, "Energy for precharge background per rank (pJ)"),
1954  ADD_STAT(actPowerDownEnergy,
1955  "Energy for active power-down per rank (pJ)"),
1956  ADD_STAT(prePowerDownEnergy,
1957  "Energy for precharge power-down per rank (pJ)"),
1958  ADD_STAT(selfRefreshEnergy, "Energy for self refresh per rank (pJ)"),
1959 
1960  ADD_STAT(totalEnergy, "Total energy per rank (pJ)"),
1961  ADD_STAT(averagePower, "Core power per rank (mW)"),
1962 
1963  ADD_STAT(totalIdleTime, "Total Idle time Per DRAM Rank"),
1964  ADD_STAT(pwrStateTime, "Time in different power states")
1965 {
1966 }
1967 
1968 void
1970 {
1972 
1973  pwrStateTime
1974  .init(6)
1975  .subname(0, "IDLE")
1976  .subname(1, "REF")
1977  .subname(2, "SREF")
1978  .subname(3, "PRE_PDN")
1979  .subname(4, "ACT")
1980  .subname(5, "ACT_PDN");
1981 }
1982 
1983 void
1985 {
1987 
1988  rank.resetStats();
1989 }
1990 
1991 void
1993 {
1995 
1996  rank.computeStats();
1997 }
1998 
1999 NVMInterface::NVMInterface(const NVMInterfaceParams* _p)
2000  : MemInterface(_p),
2001  maxPendingWrites(_p->max_pending_writes),
2002  maxPendingReads(_p->max_pending_reads),
2003  twoCycleRdWr(_p->two_cycle_rdwr),
2004  tREAD(_p->tREAD), tWRITE(_p->tWRITE), tSEND(_p->tSEND),
2005  stats(*this),
2006  writeRespondEvent([this]{ processWriteRespondEvent(); }, name()),
2007  readReadyEvent([this]{ processReadReadyEvent(); }, name()),
2008  nextReadAt(0), numPendingReads(0), numReadDataReady(0),
2009  numReadsToIssue(0), numWritesQueued(0)
2010 {
2011  DPRINTF(NVM, "Setting up NVM Interface\n");
2012 
2013  fatal_if(!isPowerOf2(burstSize), "NVM burst size %d is not allowed, "
2014  "must be a power of two\n", burstSize);
2015 
2016  // sanity check the ranks since we rely on bit slicing for the
2017  // address decoding
2018  fatal_if(!isPowerOf2(ranksPerChannel), "NVM rank count of %d is "
2019  "not allowed, must be a power of two\n", ranksPerChannel);
2020 
2021  for (int i =0; i < ranksPerChannel; i++) {
2022  // Add NVM ranks to the system
2023  DPRINTF(NVM, "Creating NVM rank %d \n", i);
2024  Rank* rank = new Rank(_p, i, *this);
2025  ranks.push_back(rank);
2026  }
2027 
2028  uint64_t capacity = ULL(1) << ceilLog2(AbstractMemory::size());
2029 
2030  DPRINTF(NVM, "NVM capacity %lld (%lld) bytes\n", capacity,
2032 
2033  rowsPerBank = capacity / (rowBufferSize *
2034  banksPerRank * ranksPerChannel);
2035 
2036 }
2037 
2038 NVMInterface*
2039 NVMInterfaceParams::create()
2040 {
2041  return new NVMInterface(this);
2042 }
2043 
2044 NVMInterface::Rank::Rank(const NVMInterfaceParams* _p,
2045  int _rank, NVMInterface& _nvm)
2046  : EventManager(&_nvm), rank(_rank), banks(_p->banks_per_rank)
2047 {
2048  for (int b = 0; b < _p->banks_per_rank; b++) {
2049  banks[b].bank = b;
2050  // No bank groups; simply assign to bank number
2051  banks[b].bankgr = b;
2052  }
2053 }
2054 
2055 void
2057 {
2059 }
2060 
2061 void NVMInterface::setupRank(const uint8_t rank, const bool is_read)
2062 {
2063  if (is_read) {
2064  // increment count to trigger read and track number of reads in Q
2065  numReadsToIssue++;
2066  } else {
2067  // increment count to track number of writes in Q
2068  numWritesQueued++;
2069  }
2070 }
2071 
2074 {
2075  // remember if we found a hit, but one that cannit issue seamlessly
2076  bool found_prepped_pkt = false;
2077 
2078  auto selected_pkt_it = queue.end();
2079  Tick selected_col_at = MaxTick;
2080 
2081  for (auto i = queue.begin(); i != queue.end() ; ++i) {
2082  MemPacket* pkt = *i;
2083 
2084  // select optimal NVM packet in Q
2085  if (!pkt->isDram()) {
2086  const Bank& bank = ranks[pkt->rank]->banks[pkt->bank];
2087  const Tick col_allowed_at = pkt->isRead() ? bank.rdAllowedAt :
2088  bank.wrAllowedAt;
2089 
2090  // check if rank is not doing a refresh and thus is available,
2091  // if not, jump to the next packet
2092  if (burstReady(pkt)) {
2093  DPRINTF(NVM, "%s bank %d - Rank %d available\n", __func__,
2094  pkt->bank, pkt->rank);
2095 
2096  // no additional rank-to-rank or media delays
2097  if (col_allowed_at <= min_col_at) {
2098  // FCFS within entries that can issue without
2099  // additional delay, such as same rank accesses
2100  // or media delay requirements
2101  selected_pkt_it = i;
2102  selected_col_at = col_allowed_at;
2103  // no need to look through the remaining queue entries
2104  DPRINTF(NVM, "%s Seamless buffer hit\n", __func__);
2105  break;
2106  } else if (!found_prepped_pkt) {
2107  // packet is to prepped region but cannnot issue
2108  // seamlessly; remember this one and continue
2109  selected_pkt_it = i;
2110  selected_col_at = col_allowed_at;
2111  DPRINTF(NVM, "%s Prepped packet found \n", __func__);
2112  found_prepped_pkt = true;
2113  }
2114  } else {
2115  DPRINTF(NVM, "%s bank %d - Rank %d not available\n", __func__,
2116  pkt->bank, pkt->rank);
2117  }
2118  }
2119  }
2120 
2121  if (selected_pkt_it == queue.end()) {
2122  DPRINTF(NVM, "%s no available NVM ranks found\n", __func__);
2123  }
2124 
2125  return make_pair(selected_pkt_it, selected_col_at);
2126 }
2127 
2128 void
2130 {
2131  Tick cmd_at = std::max(curTick(), nextReadAt);
2132 
2133  // This method does the arbitration between non-deterministic read
2134  // requests to NVM. The chosen packet is not removed from the queue
2135  // at this time. Removal from the queue will occur when the data is
2136  // ready and a separate SEND command is issued to retrieve it via the
2137  // chooseNext function in the top-level controller.
2138  assert(!queue.empty());
2139 
2140  assert(numReadsToIssue > 0);
2141  numReadsToIssue--;
2142  // For simplicity, issue non-deterministic reads in order (fcfs)
2143  for (auto i = queue.begin(); i != queue.end() ; ++i) {
2144  MemPacket* pkt = *i;
2145 
2146  // Find 1st NVM read packet that hasn't issued read command
2147  if (pkt->readyTime == MaxTick && !pkt->isDram() && pkt->isRead()) {
2148  // get the bank
2149  Bank& bank_ref = ranks[pkt->rank]->banks[pkt->bank];
2150 
2151  // issueing a read, inc counter and verify we haven't overrun
2152  numPendingReads++;
2153  assert(numPendingReads <= maxPendingReads);
2154 
2155  // increment the bytes accessed and the accesses per row
2156  bank_ref.bytesAccessed += burstSize;
2157 
2158  // Verify command bandiwth to issue
2159  // Host can issue read immediately uith buffering closer
2160  // to the NVM. The actual execution at the NVM may be delayed
2161  // due to busy resources
2162  if (twoCycleRdWr) {
2163  cmd_at = ctrl->verifyMultiCmd(cmd_at,
2165  } else {
2166  cmd_at = ctrl->verifySingleCmd(cmd_at,
2168  }
2169 
2170  // Update delay to next read
2171  // Ensures single read command issued per cycle
2172  nextReadAt = cmd_at + tCK;
2173 
2174  // If accessing a new location in this bank, update timing
2175  // and stats
2176  if (bank_ref.openRow != pkt->row) {
2177  // update the open bank, re-using row field
2178  bank_ref.openRow = pkt->row;
2179 
2180  // sample the bytes accessed to a buffer in this bank
2181  // here when we are re-buffering the data
2183  // start counting anew
2184  bank_ref.bytesAccessed = 0;
2185 
2186  // holdoff next command to this bank until the read completes
2187  // and the data has been successfully buffered
2188  // can pipeline accesses to the same bank, sending them
2189  // across the interface B2B, but will incur full access
2190  // delay between data ready responses to different buffers
2191  // in a bank
2192  bank_ref.actAllowedAt = std::max(cmd_at,
2193  bank_ref.actAllowedAt) + tREAD;
2194  }
2195  // update per packet readyTime to holdoff burst read operation
2196  // overloading readyTime, which will be updated again when the
2197  // burst is issued
2198  pkt->readyTime = std::max(cmd_at, bank_ref.actAllowedAt);
2199 
2200  DPRINTF(NVM, "Issuing NVM Read to bank %d at tick %d. "
2201  "Data ready at %d\n",
2202  bank_ref.bank, cmd_at, pkt->readyTime);
2203 
2204  // Insert into read ready queue. It will be handled after
2205  // the media delay has been met
2206  if (readReadyQueue.empty()) {
2207  assert(!readReadyEvent.scheduled());
2209  } else if (readReadyEvent.when() > pkt->readyTime) {
2210  // move it sooner in time, to the first read with data
2212  } else {
2213  assert(readReadyEvent.scheduled());
2214  }
2215  readReadyQueue.push_back(pkt->readyTime);
2216 
2217  // found an NVM read to issue - break out
2218  break;
2219  }
2220  }
2221 }
2222 
2223 void
2225 {
2226  // signal that there is read data ready to be transmitted
2227  numReadDataReady++;
2228 
2229  DPRINTF(NVM,
2230  "processReadReadyEvent(): Data for an NVM read is ready. "
2231  "numReadDataReady is %d\t numPendingReads is %d\n",
2233 
2234  // Find lowest ready time and verify it is equal to curTick
2235  // also find the next lowest to schedule next event
2236  // Done with this response, erase entry
2237  auto ready_it = readReadyQueue.begin();
2238  Tick next_ready_at = MaxTick;
2239  for (auto i = readReadyQueue.begin(); i != readReadyQueue.end() ; ++i) {
2240  if (*ready_it > *i) {
2241  next_ready_at = *ready_it;
2242  ready_it = i;
2243  } else if ((next_ready_at > *i) && (i != ready_it)) {
2244  next_ready_at = *i;
2245  }
2246  }
2247 
2248  // Verify we found the time of this event and remove it
2249  assert(*ready_it == curTick());
2250  readReadyQueue.erase(ready_it);
2251 
2252  if (!readReadyQueue.empty()) {
2253  assert(readReadyQueue.front() >= curTick());
2254  assert(!readReadyEvent.scheduled());
2255  schedule(readReadyEvent, next_ready_at);
2256  }
2257 
2258  // It is possible that a new command kicks things back into
2259  // action before reaching this point but need to ensure that we
2260  // continue to process new commands as read data becomes ready
2261  // This will also trigger a drain if needed
2262  if (!ctrl->requestEventScheduled()) {
2263  DPRINTF(NVM, "Restart controller scheduler immediately\n");
2265  }
2266 }
2267 
2268 bool
2270  bool read_rdy = pkt->isRead() && (ctrl->inReadBusState(true)) &&
2271  (pkt->readyTime <= curTick()) && (numReadDataReady > 0);
2272  bool write_rdy = !pkt->isRead() && !ctrl->inReadBusState(true) &&
2273  !writeRespQueueFull();
2274  return (read_rdy || write_rdy);
2275 }
2276 
2279 {
2280  DPRINTF(NVM, "NVM Timing access to addr %lld, rank/bank/row %d %d %d\n",
2281  pkt->addr, pkt->rank, pkt->bank, pkt->row);
2282 
2283  // get the bank
2284  Bank& bank_ref = ranks[pkt->rank]->banks[pkt->bank];
2285 
2286  // respect any constraints on the command
2287  const Tick bst_allowed_at = pkt->isRead() ?
2288  bank_ref.rdAllowedAt : bank_ref.wrAllowedAt;
2289 
2290  // we need to wait until the bus is available before we can issue
2291  // the command; need minimum of tBURST between commands
2292  Tick cmd_at = std::max(bst_allowed_at, curTick());
2293 
2294  // we need to wait until the bus is available before we can issue
2295  // the command; need minimum of tBURST between commands
2296  cmd_at = std::max(cmd_at, next_burst_at);
2297 
2298  // Verify there is command bandwidth to issue
2299  // Read burst (send command) is a simple data access and only requires
2300  // one command cycle
2301  // Write command may require multiple cycles to enable larger address space
2302  if (pkt->isRead() || !twoCycleRdWr) {
2303  cmd_at = ctrl->verifySingleCmd(cmd_at, maxCommandsPerWindow);
2304  } else {
2305  cmd_at = ctrl->verifyMultiCmd(cmd_at, maxCommandsPerWindow, tCK);
2306  }
2307  // update the packet ready time to reflect when data will be transferred
2308  // Use the same bus delays defined for NVM
2309  pkt->readyTime = cmd_at + tSEND + tBURST;
2310 
2311  Tick dly_to_rd_cmd;
2312  Tick dly_to_wr_cmd;
2313  for (auto n : ranks) {
2314  for (int i = 0; i < banksPerRank; i++) {
2315  // base delay is a function of tBURST and bus turnaround
2316  dly_to_rd_cmd = pkt->isRead() ? tBURST : writeToReadDelay();
2317  dly_to_wr_cmd = pkt->isRead() ? readToWriteDelay() : tBURST;
2318 
2319  if (pkt->rank != n->rank) {
2320  // adjust timing for different ranks
2321  // Need to account for rank-to-rank switching with tCS
2322  dly_to_wr_cmd = rankToRankDelay();
2323  dly_to_rd_cmd = rankToRankDelay();
2324  }
2325  n->banks[i].rdAllowedAt = std::max(cmd_at + dly_to_rd_cmd,
2326  n->banks[i].rdAllowedAt);
2327 
2328  n->banks[i].wrAllowedAt = std::max(cmd_at + dly_to_wr_cmd,
2329  n->banks[i].wrAllowedAt);
2330  }
2331  }
2332 
2333  DPRINTF(NVM, "NVM Access to %lld, ready at %lld.\n",
2334  pkt->addr, pkt->readyTime);
2335 
2336  if (pkt->isRead()) {
2337  // completed the read, decrement counters
2338  assert(numPendingReads != 0);
2339  assert(numReadDataReady != 0);
2340 
2341  numPendingReads--;
2342  numReadDataReady--;
2343  } else {
2344  // Adjust number of NVM writes in Q
2345  assert(numWritesQueued > 0);
2346  numWritesQueued--;
2347 
2348  // increment the bytes accessed and the accesses per row
2349  // only increment for writes as the reads are handled when
2350  // the non-deterministic read is issued, before the data transfer
2351  bank_ref.bytesAccessed += burstSize;
2352 
2353  // Commands will be issued serially when accessing the same bank
2354  // Commands can issue in parallel to different banks
2355  if ((bank_ref.bank == pkt->bank) &&
2356  (bank_ref.openRow != pkt->row)) {
2357  // update the open buffer, re-using row field
2358  bank_ref.openRow = pkt->row;
2359 
2360  // sample the bytes accessed to a buffer in this bank
2361  // here when we are re-buffering the data
2363  // start counting anew
2364  bank_ref.bytesAccessed = 0;
2365  }
2366 
2367  // Determine when write will actually complete, assuming it is
2368  // scheduled to push to NVM immediately
2369  // update actAllowedAt to serialize next command completion that
2370  // accesses this bank; must wait until this write completes
2371  // Data accesses to the same buffer in this bank
2372  // can issue immediately after actAllowedAt expires, without
2373  // waiting additional delay of tWRITE. Can revisit this
2374  // assumption/simplification in the future.
2375  bank_ref.actAllowedAt = std::max(pkt->readyTime,
2376  bank_ref.actAllowedAt) + tWRITE;
2377 
2378  // Need to track number of outstanding writes to
2379  // ensure 'buffer' on media controller does not overflow
2380  assert(!writeRespQueueFull());
2381 
2382  // Insert into write done queue. It will be handled after
2383  // the media delay has been met
2384  if (writeRespQueueEmpty()) {
2385  assert(!writeRespondEvent.scheduled());
2387  } else {
2388  assert(writeRespondEvent.scheduled());
2389  }
2390  writeRespQueue.push_back(bank_ref.actAllowedAt);
2391  writeRespQueue.sort();
2392  if (writeRespondEvent.when() > bank_ref.actAllowedAt) {
2393  DPRINTF(NVM, "Rescheduled respond event from %lld to %11d\n",
2394  writeRespondEvent.when(), bank_ref.actAllowedAt);
2395  DPRINTF(NVM, "Front of response queue is %11d\n",
2396  writeRespQueue.front());
2398  }
2399 
2400  }
2401 
2402  // Update the stats
2403  if (pkt->isRead()) {
2404  stats.readBursts++;
2406  stats.perBankRdBursts[pkt->bankId]++;
2408 
2409  // Update latency stats
2410  stats.totMemAccLat += pkt->readyTime - pkt->entryTime;
2411  stats.totBusLat += tBURST;
2412  stats.totQLat += cmd_at - pkt->entryTime;
2413  } else {
2414  stats.writeBursts++;
2416  stats.perBankWrBursts[pkt->bankId]++;
2417  }
2418 
2419  return make_pair(cmd_at, cmd_at + tBURST);
2420 }
2421 
2422 void
2424 {
2425  DPRINTF(NVM,
2426  "processWriteRespondEvent(): A NVM write reached its readyTime. "
2427  "%d remaining pending NVM writes\n", writeRespQueue.size());
2428 
2429  // Update stat to track histogram of pending writes
2431 
2432  // Done with this response, pop entry
2433  writeRespQueue.pop_front();
2434 
2435  if (!writeRespQueue.empty()) {
2436  assert(writeRespQueue.front() >= curTick());
2437  assert(!writeRespondEvent.scheduled());
2439  }
2440 
2441  // It is possible that a new command kicks things back into
2442  // action before reaching this point but need to ensure that we
2443  // continue to process new commands as writes complete at the media and
2444  // credits become available. This will also trigger a drain if needed
2445  if (!ctrl->requestEventScheduled()) {
2446  DPRINTF(NVM, "Restart controller scheduler immediately\n");
2448  }
2449 }
2450 
2451 void
2453 {
2454  // update timing for NVM ranks due to bursts issued
2455  // to ranks for other media interfaces
2456  for (auto n : ranks) {
2457  for (int i = 0; i < banksPerRank; i++) {
2458  // different rank by default
2459  // Need to only account for rank-to-rank switching
2460  n->banks[i].rdAllowedAt = std::max(cmd_at + rankToRankDelay(),
2461  n->banks[i].rdAllowedAt);
2462  n->banks[i].wrAllowedAt = std::max(cmd_at + rankToRankDelay(),
2463  n->banks[i].wrAllowedAt);
2464  }
2465  }
2466 }
2467 
2468 bool
2469 NVMInterface::isBusy(bool read_queue_empty, bool all_writes_nvm)
2470 {
2471  DPRINTF(NVM,"isBusy: numReadDataReady = %d\n", numReadDataReady);
2472  // Determine NVM is busy and cannot issue a burst
2473  // A read burst cannot issue when data is not ready from the NVM
2474  // Also check that we have reads queued to ensure we can change
2475  // bus direction to service potential write commands.
2476  // A write cannot issue once we've reached MAX pending writes
2477  // Only assert busy for the write case when there are also
2478  // no reads in Q and the write queue only contains NVM commands
2479  // This allows the bus state to switch and service reads
2480  return (ctrl->inReadBusState(true) ?
2481  (numReadDataReady == 0) && !read_queue_empty :
2482  writeRespQueueFull() && read_queue_empty &&
2483  all_writes_nvm);
2484 }
2485 
2486 
2488  : Stats::Group(&_nvm),
2489  nvm(_nvm),
2490 
2491  ADD_STAT(readBursts, "Number of NVM read bursts"),
2492  ADD_STAT(writeBursts, "Number of NVM write bursts"),
2493 
2494  ADD_STAT(perBankRdBursts, "Per bank write bursts"),
2495  ADD_STAT(perBankWrBursts, "Per bank write bursts"),
2496 
2497  ADD_STAT(totQLat, "Total ticks spent queuing"),
2498  ADD_STAT(totBusLat, "Total ticks spent in databus transfers"),
2499  ADD_STAT(totMemAccLat,
2500  "Total ticks spent from burst creation until serviced "
2501  "by the NVM"),
2502  ADD_STAT(avgQLat, "Average queueing delay per NVM burst"),
2503  ADD_STAT(avgBusLat, "Average bus latency per NVM burst"),
2504  ADD_STAT(avgMemAccLat, "Average memory access latency per NVM burst"),
2505 
2506  ADD_STAT(bytesRead, "Total number of bytes read from DRAM"),
2507  ADD_STAT(bytesWritten, "Total number of bytes written to DRAM"),
2508  ADD_STAT(avgRdBW, "Average DRAM read bandwidth in MiBytes/s"),
2509  ADD_STAT(avgWrBW, "Average DRAM write bandwidth in MiBytes/s"),
2510  ADD_STAT(peakBW, "Theoretical peak bandwidth in MiByte/s"),
2511  ADD_STAT(busUtil, "NVM Data bus utilization in percentage"),
2512  ADD_STAT(busUtilRead, "NVM Data bus read utilization in percentage"),
2513  ADD_STAT(busUtilWrite, "NVM Data bus write utilization in percentage"),
2514 
2515  ADD_STAT(pendingReads, "Reads issued to NVM for which data has not been "
2516  "transferred"),
2517  ADD_STAT(pendingWrites, "Number of outstanding writes to NVM"),
2518  ADD_STAT(bytesPerBank, "Bytes read within a bank before loading "
2519  "new bank")
2520 {
2521 }
2522 
2523 void
2525 {
2526  using namespace Stats;
2527 
2528  perBankRdBursts.init(nvm.ranksPerChannel == 0 ? 1 :
2529  nvm.banksPerRank * nvm.ranksPerChannel);
2530 
2531  perBankWrBursts.init(nvm.ranksPerChannel == 0 ? 1 :
2532  nvm.banksPerRank * nvm.ranksPerChannel);
2533 
2534  avgQLat.precision(2);
2535  avgBusLat.precision(2);
2536  avgMemAccLat.precision(2);
2537 
2538  avgRdBW.precision(2);
2539  avgWrBW.precision(2);
2540  peakBW.precision(2);
2541 
2542  busUtil.precision(2);
2543  busUtilRead.precision(2);
2544  busUtilWrite.precision(2);
2545 
2546  pendingReads
2547  .init(nvm.maxPendingReads)
2548  .flags(nozero);
2549 
2550  pendingWrites
2551  .init(nvm.maxPendingWrites)
2552  .flags(nozero);
2553 
2554  bytesPerBank
2555  .init(nvm.rowBufferSize)
2556  .flags(nozero);
2557 
2558  avgQLat = totQLat / readBursts;
2559  avgBusLat = totBusLat / readBursts;
2560  avgMemAccLat = totMemAccLat / readBursts;
2561 
2562  avgRdBW = (bytesRead / 1000000) / simSeconds;
2563  avgWrBW = (bytesWritten / 1000000) / simSeconds;
2564  peakBW = (SimClock::Frequency / nvm.tBURST) *
2565  nvm.burstSize / 1000000;
2566 
2567  busUtil = (avgRdBW + avgWrBW) / peakBW * 100;
2568  busUtilRead = avgRdBW / peakBW * 100;
2569  busUtilWrite = avgWrBW / peakBW * 100;
2570 }
MemPacket::rank
const uint8_t rank
Will be populated by address decoder.
Definition: mem_ctrl.hh:113
fatal
#define fatal(...)
This implements a cprintf based fatal() function.
Definition: logging.hh:183
DRAMInterface::Rank::updatePowerStats
void updatePowerStats()
Function to update Power Stats.
Definition: mem_interface.cc:1777
DRAMInterface::DRAMInterface
DRAMInterface(const DRAMInterfaceParams *_p)
Definition: mem_interface.cc:733
Stats::Group::regStats
virtual void regStats()
Callback to set stat parameters.
Definition: group.cc:64
Event::scheduled
bool scheduled() const
Determine if the current event is scheduled.
Definition: eventq.hh:460
DRAMInterface::Rank::suspend
void suspend()
Stop the refresh events.
Definition: mem_interface.cc:1178
DRAMInterface::tRTP
const Tick tRTP
Definition: mem_interface.hh:735
NVMInterface::NVMStats::bytesPerBank
Stats::Histogram bytesPerBank
Definition: mem_interface.hh:1099
MemInterface::banksPerRank
const uint32_t banksPerRank
Definition: mem_interface.hh:137
DRAMInterface::Rank::processWriteDoneEvent
void processWriteDoneEvent()
Definition: mem_interface.cc:1285
DRAMInterface::DRAMStats::perBankWrBursts
Stats::Vector perBankWrBursts
Definition: mem_interface.hh:817
NVMInterface::numWritesQueued
uint32_t numWritesQueued
Definition: mem_interface.hh:1148
DRAMInterface::bankGroupArch
const bool bankGroupArch
Definition: mem_interface.hh:721
warn
#define warn(...)
Definition: logging.hh:239
replaceBits
void replaceBits(T &val, int first, int last, B bit_val)
A convenience function to replace bits first to last of val with bit_val in place.
Definition: bitfield.hh:179
NVMInterface::NVMStats::totQLat
Stats::Scalar totQLat
Definition: mem_interface.hh:1076
MemInterface::writeToReadDelay
virtual Tick writeToReadDelay() const
Definition: mem_interface.hh:152
DRAMInterface::Rank::lastBurstTick
Tick lastBurstTick
Track when we issued the last read/write burst.
Definition: mem_interface.hh:584
system.hh
NVMInterface::NVMStats::perBankRdBursts
Stats::Vector perBankRdBursts
Definition: mem_interface.hh:1072
DRAMInterface::doBurstAccess
std::pair< Tick, Tick > doBurstAccess(MemPacket *mem_pkt, Tick next_burst_at, const std::vector< MemPacketQueue > &queue)
Actually do the burst - figure out the latency it will take to service the req based on bank state,...
Definition: mem_interface.cc:456
DRAMInterface::prechargeBank
void prechargeBank(Rank &rank_ref, Bank &bank_ref, Tick pre_tick, bool auto_or_preall=false, bool trace=true)
Precharge a given bank and also update when the precharge is done.
Definition: mem_interface.cc:393
DRAMInterface::RankStats::regStats
void regStats() override
Callback to set stat parameters.
Definition: mem_interface.cc:1969
NVMInterface::maxPendingReads
const uint32_t maxPendingReads
Definition: mem_interface.hh:1050
MemPacket::isDram
bool isDram() const
Return true if its a DRAM access.
Definition: mem_ctrl.hh:194
DRAMInterface::REF_START
@ REF_START
Definition: mem_interface.hh:394
MemPacket::readyTime
Tick readyTime
When will request leave the controller.
Definition: mem_ctrl.hh:99
MemInterface::Bank::actAllowedAt
Tick actAllowedAt
Definition: mem_interface.hh:95
ArmISA::i
Bitfield< 7 > i
Definition: miscregs_types.hh:63
MemCtrl::restartScheduler
void restartScheduler(Tick tick)
restart the controller This can be used by interfaces to restart the scheduler after maintainence com...
Definition: mem_ctrl.hh:676
DRAMInterface::REF_IDLE
@ REF_IDLE
Definition: mem_interface.hh:389
DRAMInterface::Rank::pwrState
PowerState pwrState
Current power state.
Definition: mem_interface.hh:514
NVMInterface::NVMStats::perBankWrBursts
Stats::Vector perBankWrBursts
Definition: mem_interface.hh:1073
EventManager::reschedule
void reschedule(Event &event, Tick when, bool always=false)
Definition: eventq.hh:1023
AddrRange::interleaved
bool interleaved() const
Determine if the range is interleaved or not.
Definition: addr_range.hh:257
DRAMInterface::RankStats::resetStats
void resetStats() override
Callback to reset stats.
Definition: mem_interface.cc:1984
NVMInterface::twoCycleRdWr
const bool twoCycleRdWr
Definition: mem_interface.hh:1051
DRAMInterface::Rank::banks
std::vector< Bank > banks
Vector of Banks.
Definition: mem_interface.hh:570
MemInterface::MemInterface
MemInterface(const Params *_p)
Definition: mem_interface.cc:54
NVMInterface::NVMStats::readBursts
Stats::Scalar readBursts
NVM stats.
Definition: mem_interface.hh:1069
MemInterface::Bank::preAllowedAt
Tick preAllowedAt
Definition: mem_interface.hh:94
MemInterface::Bank::openRow
uint32_t openRow
Definition: mem_interface.hh:88
MemInterface::Bank::rowAccesses
uint32_t rowAccesses
Definition: mem_interface.hh:97
NVMInterface::chooseNextFRFCFS
std::pair< MemPacketQueue::iterator, Tick > chooseNextFRFCFS(MemPacketQueue &queue, Tick min_col_at) const override
For FR-FCFS policy, find first NVM command that can issue default to first command to prepped region.
Definition: mem_interface.cc:2073
DRAMInterface::Rank::processWakeUpEvent
void processWakeUpEvent()
Definition: mem_interface.cc:1626
DRAMInterface::tRAS
const Tick tRAS
Definition: mem_interface.hh:733
QoS::MemCtrl::numPriorities
uint8_t numPriorities() const
Gets the total number of priority levels in the QoS memory controller.
Definition: mem_ctrl.hh:346
DRAMInterface
Interface to DRAM devices with media specific parameters, statistics, and functions.
Definition: mem_interface.hh:301
Clocked::tick
Tick tick
Definition: clocked_object.hh:65
DRAMInterface::respondEvent
void respondEvent(uint8_t rank)
Complete response process for DRAM when read burst is complete This will update the counters and chec...
Definition: mem_interface.cc:940
NVMInterface::NVMStats::writeBursts
Stats::Scalar writeBursts
Definition: mem_interface.hh:1070
DRAMInterface::Rank::prechargeEvent
EventFunctionWrapper prechargeEvent
Definition: mem_interface.hh:689
Tick
uint64_t Tick
Tick count type.
Definition: types.hh:63
DRAMInterface::Rank::resetStats
void resetStats()
Reset stats on a stats event.
Definition: mem_interface.cc:1833
DRAMInterface::isBusy
bool isBusy()
This function checks if ranks are actively refreshing and therefore busy.
Definition: mem_interface.cc:892
DRAMInterface::setupRank
void setupRank(const uint8_t rank, const bool is_read) override
Setup the rank based on packet received.
Definition: mem_interface.cc:929
DRAMInterface::PWR_PRE_PDN
@ PWR_PRE_PDN
Definition: mem_interface.hh:352
NVMInterface::tSEND
const Tick tSEND
Definition: mem_interface.hh:1058
Stats::Group::Group
Group()=delete
DRAMInterface::tAAD
const Tick tAAD
Definition: mem_interface.hh:741
MemInterface::tCK
const Tick M5_CLASS_VAR_USED tCK
General timing requirements.
Definition: mem_interface.hh:143
DRAMInterface::writeToReadDelay
Tick writeToReadDelay() const override
Definition: mem_interface.hh:860
Stats::Group::preDumpStats
virtual void preDumpStats()
Callback before stats are dumped.
Definition: group.cc:95
DRAMInterface::Rank::isQueueEmpty
bool isQueueEmpty() const
Check if the command queue of current rank is idle.
Definition: mem_interface.cc:1190
DRAMInterface::clkResyncDelay
const Tick clkResyncDelay
Definition: mem_interface.hh:745
EventManager::deschedule
void deschedule(Event &event)
Definition: eventq.hh:1014
MemInterface::tBURST
const Tick tBURST
Definition: mem_interface.hh:145
std::vector< uint32_t >
DRAMInterface::Command::type
Data::MemCommand::cmds type
Definition: mem_interface.hh:310
DRAMInterface::tXAW
const Tick tXAW
Definition: mem_interface.hh:742
NVMInterface::init
void init() override
Initialize the NVM interface and verify parameters.
Definition: mem_interface.cc:2056
DRAMInterface::Rank::actTicks
std::deque< Tick > actTicks
List to keep track of activate ticks.
Definition: mem_interface.hh:579
DRAMInterface::Rank::scheduleWakeUpEvent
void scheduleWakeUpEvent(Tick exit_delay)
schedule and event to wake-up from power-down or self-refresh and update bank timing parameters
Definition: mem_interface.cc:1574
NVMInterface::NVMInterface
NVMInterface(const NVMInterfaceParams *_p)
Definition: mem_interface.cc:1999
Event::when
Tick when() const
Get the time that the event is scheduled.
Definition: eventq.hh:503
DRAMInterface::bankGroupsPerRank
const uint32_t bankGroupsPerRank
DRAM specific device characteristics.
Definition: mem_interface.hh:720
MemInterface::Bank::bankgr
uint8_t bankgr
Definition: mem_interface.hh:90
DRAMInterface::Rank::Rank
Rank(const DRAMInterfaceParams *_p, int _rank, DRAMInterface &_dram)
Definition: mem_interface.cc:1127
DRAMInterface::Rank::forceSelfRefreshExit
bool forceSelfRefreshExit() const
Trigger a self-refresh exit if there are entries enqueued Exit if there are any read entries regardle...
Definition: mem_interface.cc:1843
X86ISA::granularity
Bitfield< 6 > granularity
Definition: misc.hh:991
DRAMInterface::RankStats::RankStats
RankStats(DRAMInterface &dram, Rank &rank)
Definition: mem_interface.cc:1943
MemInterface::maxCommandsPerWindow
unsigned int maxCommandsPerWindow
Number of commands that can issue in the defined controller command window, used to verify command ba...
Definition: mem_interface.hh:116
DRAMInterface::PWR_IDLE
@ PWR_IDLE
Definition: mem_interface.hh:349
SimClock::Frequency
Tick Frequency
The simulated frequency of curTick(). (In ticks per second)
Definition: core.cc:46
MemPacket::entryTime
const Tick entryTime
When did request enter the controller.
Definition: mem_ctrl.hh:96
DrainState::Drained
@ Drained
Buffers drained, ready for serialization/handover.
DRAMInterface::REF_DRAIN
@ REF_DRAIN
Definition: mem_interface.hh:390
DRAMInterface::Rank::writeDoneEvent
EventFunctionWrapper writeDoneEvent
Definition: mem_interface.hh:683
DRAMInterface::Rank::inRefIdleState
bool inRefIdleState() const
Check if there is no refresh and no preparation of refresh ongoing i.e.
Definition: mem_interface.hh:610
NVMInterface::setupRank
void setupRank(const uint8_t rank, const bool is_read) override
Setup the rank based on packet received.
Definition: mem_interface.cc:2061
DRAMInterface::Rank::flushCmdList
void flushCmdList()
Push command out of cmdList queue that are scheduled at or before curTick() to DRAMPower library All ...
Definition: mem_interface.cc:1216
ArmISA::n
Bitfield< 31 > n
Definition: miscregs_types.hh:450
AbstractMemory
An abstract memory represents a contiguous block of physical memory, with an associated address range...
Definition: abstract_mem.hh:104
NVMInterface::writeRespQueueFull
bool writeRespQueueFull() const
Check if the write response queue has reached defined threshold.
Definition: mem_interface.hh:1236
Stats::Group::resetStats
virtual void resetStats()
Callback to reset stats.
Definition: group.cc:82
NVMInterface::NVMStats::bytesWritten
Stats::Scalar bytesWritten
Definition: mem_interface.hh:1086
DRAMInterface::tXP
const Tick tXP
Definition: mem_interface.hh:743
DRAMInterface::Rank::computeStats
void computeStats()
Computes stats just prior to dump event.
Definition: mem_interface.cc:1820
ArmISA::j
Bitfield< 24 > j
Definition: miscregs_types.hh:54
ceilLog2
int ceilLog2(const T &n)
Definition: intmath.hh:88
divCeil
T divCeil(const T &a, const U &b)
Definition: intmath.hh:114
NVMInterface
Interface to NVM devices with media specific parameters, statistics, and functions.
Definition: mem_interface.hh:1021
EventManager::schedule
void schedule(Event &event, Tick when)
Definition: eventq.hh:1005
mem_interface.hh
DRAMInterface::tREFI
const Tick tREFI
Definition: mem_interface.hh:737
DRAMInterface::minBankPrep
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.
Definition: mem_interface.cc:1037
DRAMInterface::tXS
const Tick tXS
Definition: mem_interface.hh:744
MemInterface::readToWriteDelay
Tick readToWriteDelay() const
Definition: mem_interface.hh:157
bitfield.hh
DRAMInterface::activateBank
void activateBank(Rank &rank_ref, Bank &bank_ref, Tick act_tick, uint32_t row)
Keep track of when row activations happen, in order to enforce the maximum number of activations in t...
Definition: mem_interface.cc:284
DRAMInterface::maxAccessesPerRow
const uint32_t maxAccessesPerRow
Max column accesses (read and write) per row, before forefully closing it.
Definition: mem_interface.hh:759
DRAMInterface::Rank::cmdList
std::vector< Command > cmdList
List of commands issued, to be sent to DRAMPpower at refresh and stats dump.
Definition: mem_interface.hh:564
DRAMInterface::sortTime
static bool sortTime(const Command &cmd, const Command &cmd_next)
Function for sorting Command structures based on timeStamp.
Definition: mem_interface.hh:712
NVMInterface::Rank::Rank
Rank(const NVMInterfaceParams *_p, int _rank, NVMInterface &_nvm)
Definition: mem_interface.cc:2044
DRAMInterface::burstReady
bool burstReady(MemPacket *pkt) const override
Check if a burst operation can be issued to the DRAM.
Definition: mem_interface.hh:971
AbstractMemory::size
uint64_t size() const
Get the memory size.
Definition: abstract_mem.hh:285
DRAMInterface::checkRefreshState
void checkRefreshState(uint8_t rank)
Check the refresh state to determine if refresh needs to be kicked back into action after a read resp...
Definition: mem_interface.cc:987
DRAMInterface::tWR
const Tick tWR
Definition: mem_interface.hh:734
DPRINTF
#define DPRINTF(x,...)
Definition: trace.hh:234
MemInterface::Bank::NO_ROW
static const uint32_t NO_ROW
Definition: mem_interface.hh:86
ADD_STAT
#define ADD_STAT(n,...)
Convenience macro to add a stat to a statistics group.
Definition: group.hh:67
DRAMInterface::DRAMStats::resetStats
void resetStats() override
Callback to reset stats.
Definition: mem_interface.cc:1849
simSeconds
Stats::Formula simSeconds
Definition: stat_control.cc:61
NVMInterface::writeRespQueue
std::list< Tick > writeRespQueue
Holding queue for non-deterministic write commands, which maintains writes that have been issued but ...
Definition: mem_interface.hh:1122
DRAMInterface::ranks
std::vector< Rank * > ranks
Vector of dram ranks.
Definition: mem_interface.hh:855
DRAMInterface::DRAMStats::totQLat
Stats::Scalar totQLat
Definition: mem_interface.hh:820
MemInterface::Bank::bank
uint8_t bank
Definition: mem_interface.hh:89
NVMInterface::nextReadAt
Tick nextReadAt
Till when must we wait before issuing next read command?
Definition: mem_interface.hh:1136
NVMInterface::writeRespQueueEmpty
bool writeRespQueueEmpty() const
Check if the write response queue is empty.
Definition: mem_interface.hh:1131
MemPacket::row
const uint32_t row
Definition: mem_ctrl.hh:115
PowerState
Helper class for objects that have power states.
Definition: power_state.hh:61
DRAMInterface::DRAMStats::bytesWritten
Stats::Scalar bytesWritten
Definition: mem_interface.hh:837
DRAMInterface::activeRank
uint8_t activeRank
Definition: mem_interface.hh:765
DRAMInterface::REF_RUN
@ REF_RUN
Definition: mem_interface.hh:395
MipsISA::r
r
Definition: pra_constants.hh:95
DRAMInterface::REF_SREF_EXIT
@ REF_SREF_EXIT
Definition: mem_interface.hh:392
MemInterface::ranksPerChannel
const uint32_t ranksPerChannel
Definition: mem_interface.hh:136
DRAMInterface::PWR_REF
@ PWR_REF
Definition: mem_interface.hh:350
MemPacket::bank
const uint8_t bank
Definition: mem_ctrl.hh:114
DRAMInterface::DRAMStats::regStats
void regStats() override
Callback to set stat parameters.
Definition: mem_interface.cc:1896
DRAMInterface::DRAMStats::readRowHits
Stats::Scalar readRowHits
Definition: mem_interface.hh:830
DRAMInterface::DRAMStats::bytesRead
Stats::Scalar bytesRead
Definition: mem_interface.hh:836
MemInterface::Bank::bytesAccessed
uint32_t bytesAccessed
Definition: mem_interface.hh:98
MemPacket
A memory packet stores packets along with the timestamp of when the packet entered the queue,...
Definition: mem_ctrl.hh:91
MemInterface::getCtrlAddr
Addr getCtrlAddr(Addr addr)
Get an address in a dense range which starts from 0.
Definition: mem_interface.hh:193
NVMInterface::isBusy
bool isBusy(bool read_queue_empty, bool all_writes_nvm)
This function checks if ranks are busy.
Definition: mem_interface.cc:2469
MemInterface::setCtrl
void setCtrl(MemCtrl *_ctrl, unsigned int command_window)
Set a pointer to the controller and initialize interface based on controller parameters.
Definition: mem_interface.cc:76
DRAMInterface::DRAMStats::bytesPerActivate
Stats::Histogram bytesPerActivate
Definition: mem_interface.hh:834
DRAMInterface::Command
Simple structure to hold the values needed to keep track of commands for DRAMPower.
Definition: mem_interface.hh:308
NVMInterface::NVMStats::regStats
void regStats() override
Callback to set stat parameters.
Definition: mem_interface.cc:2524
NVMInterface::readReadyQueue
std::deque< Tick > readReadyQueue
Definition: mem_interface.hh:1124
std::pair
STL pair class.
Definition: stl.hh:58
DRAMInterface::startup
void startup() override
Iterate through dram ranks and instantiate per rank startup routine.
Definition: mem_interface.cc:879
MemInterface::burstsPerRowBuffer
const uint32_t burstsPerRowBuffer
Definition: mem_interface.hh:134
DRAMInterface::timeStampOffset
uint64_t timeStampOffset
Definition: mem_interface.hh:762
DRAMInterface::DRAMStats::perBankRdBursts
Stats::Vector perBankRdBursts
DRAM per bank stats.
Definition: mem_interface.hh:816
NVMInterface::numReadsToIssue
uint16_t numReadsToIssue
Definition: mem_interface.hh:1145
DRAMInterface::rdToWrDlySameBG
const Tick rdToWrDlySameBG
Definition: mem_interface.hh:751
NVMInterface::Rank::banks
std::vector< Bank > banks
Vector of NVM banks.
Definition: mem_interface.hh:1040
NVMInterface::NVMStats::pendingReads
Stats::Histogram pendingReads
NVM stats.
Definition: mem_interface.hh:1097
DRAMInterface::twoCycleActivate
const uint8_t twoCycleActivate
Definition: mem_interface.hh:748
Addr
uint64_t Addr
Address type This will probably be moved somewhere else in the near future.
Definition: types.hh:142
RD
#define RD
Definition: bitfields.hh:14
DRAMInterface::Rank::rank
uint8_t rank
Current Rank index.
Definition: mem_interface.hh:529
DRAMInterface::Rank::inLowPowerState
bool inLowPowerState
rank is in or transitioning to power-down or self-refresh
Definition: mem_interface.hh:524
name
const std::string & name()
Definition: trace.cc:50
DRAMInterface::allRanksDrained
bool allRanksDrained() const override
Return true once refresh is complete for all ranks and there are no additional commands enqueued.
Definition: mem_interface.cc:1014
MemInterface::addrMapping
Enums::AddrMap addrMapping
Memory controller configuration initialized based on parameter values.
Definition: mem_interface.hh:122
DRAMInterface::PWR_SREF
@ PWR_SREF
Definition: mem_interface.hh:351
DRAMInterface::tCCD_L
const Tick tCCD_L
Definition: mem_interface.hh:730
DRAMInterface::DRAMStats::writeBursts
Stats::Scalar writeBursts
Definition: mem_interface.hh:813
MemInterface::rowBufferSize
const uint32_t rowBufferSize
Definition: mem_interface.hh:133
NVMInterface::NVMStats::totMemAccLat
Stats::Scalar totMemAccLat
Definition: mem_interface.hh:1078
NVMInterface::NVMStats::bytesRead
Stats::Scalar bytesRead
Definition: mem_interface.hh:1085
Stats::nozero
const FlagsType nozero
Don't print if this is zero.
Definition: info.hh:57
DRAMInterface::tRFC
const Tick tRFC
Definition: mem_interface.hh:736
MemInterface::burstsPerStripe
const uint32_t burstsPerStripe
Definition: mem_interface.hh:135
AbstractMemory::range
AddrRange range
Definition: abstract_mem.hh:109
MemCtrl::requestEventScheduled
bool requestEventScheduled() const
Is there a read/write burst Event scheduled?
Definition: mem_ctrl.hh:667
NVMInterface::processWriteRespondEvent
void processWriteRespondEvent()
Definition: mem_interface.cc:2423
MipsISA::fill
fill
Definition: pra_constants.hh:54
DRAMInterface::Rank::startup
void startup(Tick ref_tick)
Kick off accounting for power and refresh states and schedule initial refresh.
Definition: mem_interface.cc:1166
SimObject::name
virtual const std::string name() const
Definition: sim_object.hh:133
MemCtrl::verifySingleCmd
Tick verifySingleCmd(Tick cmd_tick, Tick max_cmds_per_burst)
Check for command bus contention for single cycle command.
Definition: mem_ctrl.cc:687
DRAMInterface::Rank::readEntries
uint32_t readEntries
Track number of packets in read queue going to this rank.
Definition: mem_interface.hh:534
DRAMInterface::REF_PD_EXIT
@ REF_PD_EXIT
Definition: mem_interface.hh:391
DRAMInterface::Command::timeStamp
Tick timeStamp
Definition: mem_interface.hh:312
DRAMInterface::addRankToRankDelay
void addRankToRankDelay(Tick cmd_at) override
Add rank to rank delay to bus timing to all DRAM banks in alli ranks when access to an alternate inte...
Definition: mem_interface.cc:717
NVMInterface::numPendingReads
uint16_t numPendingReads
Definition: mem_interface.hh:1140
DRAMInterface::wrToRdDlySameBG
const Tick wrToRdDlySameBG
Definition: mem_interface.hh:750
DRAMInterface::pageMgmt
Enums::PageManage pageMgmt
Definition: mem_interface.hh:754
MemCtrl
The memory controller is a single-channel memory controller capturing the most important timing const...
Definition: mem_ctrl.hh:236
NVMInterface::tREAD
const Tick tREAD
NVM specific timing requirements.
Definition: mem_interface.hh:1056
MemCtrl::verifyMultiCmd
Tick verifyMultiCmd(Tick cmd_tick, Tick max_cmds_per_burst, Tick max_multi_cmd_split=0)
Check for command bus contention for multi-cycle (2 currently) command.
Definition: mem_ctrl.cc:710
NVMInterface::processReadReadyEvent
void processReadReadyEvent()
Definition: mem_interface.cc:2224
ArmISA::b
Bitfield< 7 > b
Definition: miscregs_types.hh:376
AddrRange::granularity
uint64_t granularity() const
Determing the interleaving granularity of the range.
Definition: addr_range.hh:266
std
Overload hash function for BasicBlockRange type.
Definition: vec_reg.hh:587
NVMInterface::readReadyEvent
EventFunctionWrapper readReadyEvent
Definition: mem_interface.hh:1107
NVMInterface::addRankToRankDelay
void addRankToRankDelay(Tick cmd_at) override
Add rank to rank delay to bus timing to all NVM banks in alli ranks when access to an alternate inter...
Definition: mem_interface.cc:2452
NVMInterface::NVMStats::NVMStats
NVMStats(NVMInterface &nvm)
Definition: mem_interface.cc:2487
DRAMInterface::Rank::schedulePowerEvent
void schedulePowerEvent(PowerState pwr_state, Tick tick)
Schedule a power state transition in the future, and potentially override an already scheduled transi...
Definition: mem_interface.cc:1502
DRAMInterface::tCL
const Tick tCL
DRAM specific timing requirements.
Definition: mem_interface.hh:726
Packet
A Packet is used to encapsulate a transfer between two objects in the memory system (e....
Definition: packet.hh:257
DRAMInterface::Rank::outstandingEvents
uint8_t outstandingEvents
Number of ACT, RD, and WR events currently scheduled Incremented when a refresh event is started as w...
Definition: mem_interface.hh:546
MemInterface::burstSize
const uint32_t burstSize
General device and channel characteristics The rowsPerBank is determined based on the capacity,...
Definition: mem_interface.hh:129
std::deque< MemPacket * >
MemCtrl::inReadBusState
bool inReadBusState(bool next_state) const
Check the current direction of the memory channel.
Definition: mem_ctrl.cc:774
MemInterface::Bank
A basic class to track the bank state, i.e.
Definition: mem_interface.hh:82
Stats::Group
Statistics container.
Definition: group.hh:83
DRAMInterface::chooseNextFRFCFS
std::pair< MemPacketQueue::iterator, Tick > chooseNextFRFCFS(MemPacketQueue &queue, Tick min_col_at) const override
For FR-FCFS policy, find first DRAM command that can issue.
Definition: mem_interface.cc:169
addr
ip6_addr_t addr
Definition: inet.hh:423
NVMInterface::numReadDataReady
uint16_t numReadDataReady
Definition: mem_interface.hh:1141
DRAMInterface::REF_PRE
@ REF_PRE
Definition: mem_interface.hh:393
DRAMInterface::Rank::writeEntries
uint32_t writeEntries
Track number of packets in write queue going to this rank.
Definition: mem_interface.hh:539
DRAMInterface::Rank::processRefreshEvent
void processRefreshEvent()
Definition: mem_interface.cc:1296
SimObject::init
virtual void init()
init() is called after all C++ SimObjects have been created and all ports are connected.
Definition: sim_object.cc:73
NVMInterface::ranks
std::vector< Rank * > ranks
Vector of nvm ranks.
Definition: mem_interface.hh:1112
Stats::DistBase::sample
void sample(const U &v, int n=1)
Add a value to the distribtion n times.
Definition: statistics.hh:1924
NVMInterface::NVMStats::totBusLat
Stats::Scalar totBusLat
Definition: mem_interface.hh:1077
DRAMInterface::Command::bank
uint8_t bank
Definition: mem_interface.hh:311
DRAMInterface::dataClockSync
const bool dataClockSync
Definition: mem_interface.hh:746
DRAMInterface::init
void init() override
Initialize the DRAM interface and verify parameters.
Definition: mem_interface.cc:837
MemPacket::addr
Addr addr
The starting address of the packet.
Definition: mem_ctrl.hh:130
MemPacket::bankId
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:122
MemInterface::rowsPerBank
uint32_t rowsPerBank
Definition: mem_interface.hh:138
DRAMInterface::tRCD
const Tick tRCD
Definition: mem_interface.hh:731
NVMInterface::writeRespondEvent
EventFunctionWrapper writeRespondEvent
Definition: mem_interface.hh:1104
DRAMInterface::DRAMStats::totBusLat
Stats::Scalar totBusLat
Definition: mem_interface.hh:821
Stats
Definition: statistics.cc:61
EventManager
Definition: eventq.hh:973
MemInterface::Bank::rdAllowedAt
Tick rdAllowedAt
Definition: mem_interface.hh:92
DRAMInterface::Rank::refreshState
RefreshState refreshState
current refresh state
Definition: mem_interface.hh:519
DRAMInterface::RankStats::preDumpStats
void preDumpStats() override
Callback before stats are dumped.
Definition: mem_interface.cc:1992
trace.hh
MemInterface::ctrl
MemCtrl * ctrl
A pointer to the parent MemCtrl instance.
Definition: mem_interface.hh:110
DRAMInterface::DRAMStats::DRAMStats
DRAMStats(DRAMInterface &dram)
Definition: mem_interface.cc:1854
DRAMInterface::Rank::checkDrainDone
void checkDrainDone()
Let the rank check if it was waiting for requests to drain to allow it to transition states.
Definition: mem_interface.cc:1201
DRAMInterface::tRP
const Tick tRP
Definition: mem_interface.hh:732
DRAMInterface::drainRanks
void drainRanks()
Iterate through dram ranks to exit self-refresh in order to drain.
Definition: mem_interface.cc:1000
DRAMInterface::Rank::refreshEvent
EventFunctionWrapper refreshEvent
Definition: mem_interface.hh:692
DRAMInterface::Rank::processPowerEvent
void processPowerEvent()
Definition: mem_interface.cc:1644
MipsISA::p
Bitfield< 0 > p
Definition: pra_constants.hh:323
DRAMInterface::PWR_ACT
@ PWR_ACT
Definition: mem_interface.hh:353
MemInterface::deviceSize
const uint32_t deviceSize
Definition: mem_interface.hh:130
MemInterface::Bank::wrAllowedAt
Tick wrAllowedAt
Definition: mem_interface.hh:93
AbstractMemory::system
System * system() const
read the system pointer Implemented for completeness with the setter
Definition: abstract_mem.hh:244
fatal_if
#define fatal_if(cond,...)
Conditional fatal macro that checks the supplied condition and only causes a fatal error if the condi...
Definition: logging.hh:219
power
uint64_t power(uint32_t n, uint32_t e)
Definition: intmath.hh:43
NVMInterface::chooseRead
void chooseRead(MemPacketQueue &queue)
Select read command to issue asynchronously.
Definition: mem_interface.cc:2129
DRAMInterface::Rank
Rank class includes a vector of banks.
Definition: mem_interface.hh:465
DRAMInterface::tBURST_MIN
const Tick tBURST_MIN
Definition: mem_interface.hh:727
DRAMInterface::enableDRAMPowerdown
bool enableDRAMPowerdown
Enable or disable DRAM powerdown states.
Definition: mem_interface.hh:768
MemInterface::devicesPerRank
const uint32_t devicesPerRank
Definition: mem_interface.hh:132
DRAMInterface::Rank::processActivateEvent
void processActivateEvent()
Definition: mem_interface.cc:1244
DRAMInterface::activationLimit
const uint32_t activationLimit
Definition: mem_interface.hh:749
DRAMInterface::PWR_ACT_PDN
@ PWR_ACT_PDN
Definition: mem_interface.hh:354
isPowerOf2
bool isPowerOf2(const T &n)
Definition: intmath.hh:102
DRAMInterface::Rank::activateEvent
EventFunctionWrapper activateEvent
Definition: mem_interface.hh:686
MemInterface::decodePacket
MemPacket * decodePacket(const PacketPtr pkt, Addr pkt_addr, unsigned int size, bool is_read, bool is_dram)
Address decoder to figure out physical mapping onto ranks, banks, and rows.
Definition: mem_interface.cc:83
DRAMInterface::suspend
void suspend()
Iterate through DRAM ranks and suspend them.
Definition: mem_interface.cc:1029
DRAMInterface::Rank::powerDownSleep
void powerDownSleep(PowerState pwr_state, Tick tick)
Schedule a transition to power-down (sleep)
Definition: mem_interface.cc:1523
MaxTick
const Tick MaxTick
Definition: types.hh:65
DRAMInterface::DRAMStats::readBursts
Stats::Scalar readBursts
total number of DRAM bursts serviced
Definition: mem_interface.hh:812
csprintf
std::string csprintf(const char *format, const Args &...args)
Definition: cprintf.hh:158
DRAMInterface::tCCD_L_WR
const Tick tCCD_L_WR
Definition: mem_interface.hh:729
MemInterface::rankToRankDelay
Tick rankToRankDelay() const
Definition: mem_interface.hh:162
DRAMInterface::Rank::numBanksActive
unsigned int numBanksActive
To track number of banks which are currently active for this rank.
Definition: mem_interface.hh:576
DRAMInterface::Rank::processPrechargeEvent
void processPrechargeEvent()
Definition: mem_interface.cc:1254
MemPacket::isRead
bool isRead() const
Return true if its a read packet (interface compatibility with Packet)
Definition: mem_ctrl.hh:183
ULL
#define ULL(N)
uint64_t constant
Definition: types.hh:50
DRAMInterface::DRAMStats::totMemAccLat
Stats::Scalar totMemAccLat
Definition: mem_interface.hh:822
DRAMPower
DRAMPower is a standalone tool which calculates the power consumed by a DRAM in the system.
Definition: drampower.hh:53
NVMInterface::tWRITE
const Tick tWRITE
Definition: mem_interface.hh:1057
NVMInterface::doBurstAccess
std::pair< Tick, Tick > doBurstAccess(MemPacket *pkt, Tick next_burst_at)
Actually do the burst and update stats.
Definition: mem_interface.cc:2278
DRAMInterface::burstInterleave
const bool burstInterleave
Definition: mem_interface.hh:747
DRAMInterface::tRRD
const Tick tRRD
Definition: mem_interface.hh:738
NVMInterface::NVMStats::pendingWrites
Stats::Histogram pendingWrites
Definition: mem_interface.hh:1098
DrainState::Draining
@ Draining
Draining buffers pending serialization/handover.
DRAMInterface::tPPD
const Tick tPPD
Definition: mem_interface.hh:740
panic
#define panic(...)
This implements a cprintf based panic() function.
Definition: logging.hh:171
NVMInterface::burstReady
bool burstReady(MemPacket *pkt) const override
Check if a burst operation can be issued to the NVM.
Definition: mem_interface.cc:2269
DRAMInterface::DRAMStats::writeRowHits
Stats::Scalar writeRowHits
Definition: mem_interface.hh:831
NVMInterface::stats
NVMStats stats
Definition: mem_interface.hh:1101
curTick
Tick curTick()
The current simulated tick.
Definition: core.hh:45
DRAMInterface::stats
DRAMStats stats
Definition: mem_interface.hh:850
bits
T bits(T val, int first, int last)
Extract the bitfield from position 'first' to 'last' (inclusive) from 'val' and right justify it.
Definition: bitfield.hh:75
DRAMInterface::tRRD_L
const Tick tRRD_L
Definition: mem_interface.hh:739
MemInterface
General interface to memory device Includes functions and parameters shared across media types.
Definition: mem_interface.hh:70

Generated on Wed Sep 30 2020 14:02:13 for gem5 by doxygen 1.8.17