gem5  v21.1.0.2
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages
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/cprintf.hh"
45 #include "base/trace.hh"
46 #include "debug/DRAM.hh"
47 #include "debug/DRAMPower.hh"
48 #include "debug/DRAMState.hh"
49 #include "debug/NVM.hh"
50 #include "sim/system.hh"
51 
52 namespace gem5
53 {
54 
55 using namespace Data;
56 
57 namespace memory
58 {
59 
60 MemInterface::MemInterface(const MemInterfaceParams &_p)
61  : AbstractMemory(_p),
62  addrMapping(_p.addr_mapping),
63  burstSize((_p.devices_per_rank * _p.burst_length *
64  _p.device_bus_width) / 8),
65  deviceSize(_p.device_size),
66  deviceRowBufferSize(_p.device_rowbuffer_size),
67  devicesPerRank(_p.devices_per_rank),
68  rowBufferSize(devicesPerRank * deviceRowBufferSize),
69  burstsPerRowBuffer(rowBufferSize / burstSize),
70  burstsPerStripe(range.interleaved() ?
71  range.granularity() / burstSize : 1),
72  ranksPerChannel(_p.ranks_per_channel),
73  banksPerRank(_p.banks_per_rank), rowsPerBank(0),
74  tCK(_p.tCK), tCS(_p.tCS), tBURST(_p.tBURST),
75  tRTW(_p.tRTW),
76  tWTR(_p.tWTR),
77  readBufferSize(_p.read_buffer_size),
78  writeBufferSize(_p.write_buffer_size)
79 {}
80 
81 void
82 MemInterface::setCtrl(MemCtrl* _ctrl, unsigned int command_window)
83 {
84  ctrl = _ctrl;
85  maxCommandsPerWindow = command_window / tCK;
86 }
87 
88 MemPacket*
90  unsigned size, bool is_read, bool is_dram)
91 {
92  // decode the address based on the address mapping scheme, with
93  // Ro, Ra, Co, Ba and Ch denoting row, rank, column, bank and
94  // channel, respectively
95  uint8_t rank;
96  uint8_t bank;
97  // use a 64-bit unsigned during the computations as the row is
98  // always the top bits, and check before creating the packet
99  uint64_t row;
100 
101  // Get packed address, starting at 0
102  Addr addr = getCtrlAddr(pkt_addr);
103 
104  // truncate the address to a memory burst, which makes it unique to
105  // a specific buffer, row, bank, rank and channel
106  addr = addr / burstSize;
107 
108  // we have removed the lowest order address bits that denote the
109  // position within the column
110  if (addrMapping == enums::RoRaBaChCo || addrMapping == enums::RoRaBaCoCh) {
111  // the lowest order bits denote the column to ensure that
112  // sequential cache lines occupy the same row
114 
115  // after the channel bits, get the bank bits to interleave
116  // over the banks
117  bank = addr % banksPerRank;
118  addr = addr / banksPerRank;
119 
120  // after the bank, we get the rank bits which thus interleaves
121  // over the ranks
122  rank = addr % ranksPerChannel;
124 
125  // lastly, get the row bits, no need to remove them from addr
126  row = addr % rowsPerBank;
127  } else if (addrMapping == enums::RoCoRaBaCh) {
128  // with emerging technologies, could have small page size with
129  // interleaving granularity greater than row buffer
131  // remove column bits which are a subset of burstsPerStripe
133  } else {
134  // remove lower column bits below channel bits
136  }
137 
138  // start with the bank bits, as this provides the maximum
139  // opportunity for parallelism between requests
140  bank = addr % banksPerRank;
141  addr = addr / banksPerRank;
142 
143  // next get the rank bits
144  rank = addr % ranksPerChannel;
146 
147  // next, the higher-order column bites
150  }
151 
152  // lastly, get the row bits, no need to remove them from addr
153  row = addr % rowsPerBank;
154  } else
155  panic("Unknown address mapping policy chosen!");
156 
157  assert(rank < ranksPerChannel);
158  assert(bank < banksPerRank);
159  assert(row < rowsPerBank);
160  assert(row < Bank::NO_ROW);
161 
162  DPRINTF(DRAM, "Address: %#x Rank %d Bank %d Row %d\n",
163  pkt_addr, rank, bank, row);
164 
165  // create the corresponding memory packet with the entry time and
166  // ready time set to the current tick, the latter will be updated
167  // later
168  uint16_t bank_id = banksPerRank * rank + bank;
169 
170  return new MemPacket(pkt, is_read, is_dram, rank, bank, row, bank_id,
171  pkt_addr, size);
172 }
173 
176 {
177  std::vector<uint32_t> earliest_banks(ranksPerChannel, 0);
178 
179  // Has minBankPrep been called to populate earliest_banks?
180  bool filled_earliest_banks = false;
181  // can the PRE/ACT sequence be done without impacting utlization?
182  bool hidden_bank_prep = false;
183 
184  // search for seamless row hits first, if no seamless row hit is
185  // found then determine if there are other packets that can be issued
186  // without incurring additional bus delay due to bank timing
187  // Will select closed rows first to enable more open row possibilies
188  // in future selections
189  bool found_hidden_bank = false;
190 
191  // remember if we found a row hit, not seamless, but bank prepped
192  // and ready
193  bool found_prepped_pkt = false;
194 
195  // if we have no row hit, prepped or not, and no seamless packet,
196  // just go for the earliest possible
197  bool found_earliest_pkt = false;
198 
199  Tick selected_col_at = MaxTick;
200  auto selected_pkt_it = queue.end();
201 
202  for (auto i = queue.begin(); i != queue.end() ; ++i) {
203  MemPacket* pkt = *i;
204 
205  // select optimal DRAM packet in Q
206  if (pkt->isDram()) {
207  const Bank& bank = ranks[pkt->rank]->banks[pkt->bank];
208  const Tick col_allowed_at = pkt->isRead() ? bank.rdAllowedAt :
209  bank.wrAllowedAt;
210 
211  DPRINTF(DRAM, "%s checking DRAM packet in bank %d, row %d\n",
212  __func__, pkt->bank, pkt->row);
213 
214  // check if rank is not doing a refresh and thus is available,
215  // if not, jump to the next packet
216  if (burstReady(pkt)) {
217 
218  DPRINTF(DRAM,
219  "%s bank %d - Rank %d available\n", __func__,
220  pkt->bank, pkt->rank);
221 
222  // check if it is a row hit
223  if (bank.openRow == pkt->row) {
224  // no additional rank-to-rank or same bank-group
225  // delays, or we switched read/write and might as well
226  // go for the row hit
227  if (col_allowed_at <= min_col_at) {
228  // FCFS within the hits, giving priority to
229  // commands that can issue seamlessly, without
230  // additional delay, such as same rank accesses
231  // and/or different bank-group accesses
232  DPRINTF(DRAM, "%s Seamless buffer hit\n", __func__);
233  selected_pkt_it = i;
234  selected_col_at = col_allowed_at;
235  // no need to look through the remaining queue entries
236  break;
237  } else if (!found_hidden_bank && !found_prepped_pkt) {
238  // if we did not find a packet to a closed row that can
239  // issue the bank commands without incurring delay, and
240  // did not yet find a packet to a prepped row, remember
241  // the current one
242  selected_pkt_it = i;
243  selected_col_at = col_allowed_at;
244  found_prepped_pkt = true;
245  DPRINTF(DRAM, "%s Prepped row buffer hit\n", __func__);
246  }
247  } else if (!found_earliest_pkt) {
248  // if we have not initialised the bank status, do it
249  // now, and only once per scheduling decisions
250  if (!filled_earliest_banks) {
251  // determine entries with earliest bank delay
252  std::tie(earliest_banks, hidden_bank_prep) =
253  minBankPrep(queue, min_col_at);
254  filled_earliest_banks = true;
255  }
256 
257  // bank is amongst first available banks
258  // minBankPrep will give priority to packets that can
259  // issue seamlessly
260  if (bits(earliest_banks[pkt->rank],
261  pkt->bank, pkt->bank)) {
262  found_earliest_pkt = true;
263  found_hidden_bank = hidden_bank_prep;
264 
265  // give priority to packets that can issue
266  // bank commands 'behind the scenes'
267  // any additional delay if any will be due to
268  // col-to-col command requirements
269  if (hidden_bank_prep || !found_prepped_pkt) {
270  selected_pkt_it = i;
271  selected_col_at = col_allowed_at;
272  }
273  }
274  }
275  } else {
276  DPRINTF(DRAM, "%s bank %d - Rank %d not available\n", __func__,
277  pkt->bank, pkt->rank);
278  }
279  }
280  }
281 
282  if (selected_pkt_it == queue.end()) {
283  DPRINTF(DRAM, "%s no available DRAM ranks found\n", __func__);
284  }
285 
286  return std::make_pair(selected_pkt_it, selected_col_at);
287 }
288 
289 void
290 DRAMInterface::activateBank(Rank& rank_ref, Bank& bank_ref,
291  Tick act_tick, uint32_t row)
292 {
293  assert(rank_ref.actTicks.size() == activationLimit);
294 
295  // verify that we have command bandwidth to issue the activate
296  // if not, shift to next burst window
297  Tick act_at;
298  if (twoCycleActivate)
299  act_at = ctrl->verifyMultiCmd(act_tick, maxCommandsPerWindow, tAAD);
300  else
301  act_at = ctrl->verifySingleCmd(act_tick, maxCommandsPerWindow);
302 
303  DPRINTF(DRAM, "Activate at tick %d\n", act_at);
304 
305  // update the open row
306  assert(bank_ref.openRow == Bank::NO_ROW);
307  bank_ref.openRow = row;
308 
309  // start counting anew, this covers both the case when we
310  // auto-precharged, and when this access is forced to
311  // precharge
312  bank_ref.bytesAccessed = 0;
313  bank_ref.rowAccesses = 0;
314 
315  ++rank_ref.numBanksActive;
316  assert(rank_ref.numBanksActive <= banksPerRank);
317 
318  DPRINTF(DRAM, "Activate bank %d, rank %d at tick %lld, now got "
319  "%d active\n", bank_ref.bank, rank_ref.rank, act_at,
320  ranks[rank_ref.rank]->numBanksActive);
321 
322  rank_ref.cmdList.push_back(Command(MemCommand::ACT, bank_ref.bank,
323  act_at));
324 
325  DPRINTF(DRAMPower, "%llu,ACT,%d,%d\n", divCeil(act_at, tCK) -
326  timeStampOffset, bank_ref.bank, rank_ref.rank);
327 
328  // The next access has to respect tRAS for this bank
329  bank_ref.preAllowedAt = act_at + tRAS;
330 
331  // Respect the row-to-column command delay for both read and write cmds
332  bank_ref.rdAllowedAt = std::max(act_at + tRCD, bank_ref.rdAllowedAt);
333  bank_ref.wrAllowedAt = std::max(act_at + tRCD, bank_ref.wrAllowedAt);
334 
335  // start by enforcing tRRD
336  for (int i = 0; i < banksPerRank; i++) {
337  // next activate to any bank in this rank must not happen
338  // before tRRD
339  if (bankGroupArch && (bank_ref.bankgr == rank_ref.banks[i].bankgr)) {
340  // bank group architecture requires longer delays between
341  // ACT commands within the same bank group. Use tRRD_L
342  // in this case
343  rank_ref.banks[i].actAllowedAt = std::max(act_at + tRRD_L,
344  rank_ref.banks[i].actAllowedAt);
345  } else {
346  // use shorter tRRD value when either
347  // 1) bank group architecture is not supportted
348  // 2) bank is in a different bank group
349  rank_ref.banks[i].actAllowedAt = std::max(act_at + tRRD,
350  rank_ref.banks[i].actAllowedAt);
351  }
352  }
353 
354  // next, we deal with tXAW, if the activation limit is disabled
355  // then we directly schedule an activate power event
356  if (!rank_ref.actTicks.empty()) {
357  // sanity check
358  if (rank_ref.actTicks.back() &&
359  (act_at - rank_ref.actTicks.back()) < tXAW) {
360  panic("Got %d activates in window %d (%llu - %llu) which "
361  "is smaller than %llu\n", activationLimit, act_at -
362  rank_ref.actTicks.back(), act_at,
363  rank_ref.actTicks.back(), tXAW);
364  }
365 
366  // shift the times used for the book keeping, the last element
367  // (highest index) is the oldest one and hence the lowest value
368  rank_ref.actTicks.pop_back();
369 
370  // record an new activation (in the future)
371  rank_ref.actTicks.push_front(act_at);
372 
373  // cannot activate more than X times in time window tXAW, push the
374  // next one (the X + 1'st activate) to be tXAW away from the
375  // oldest in our window of X
376  if (rank_ref.actTicks.back() &&
377  (act_at - rank_ref.actTicks.back()) < tXAW) {
378  DPRINTF(DRAM, "Enforcing tXAW with X = %d, next activate "
379  "no earlier than %llu\n", activationLimit,
380  rank_ref.actTicks.back() + tXAW);
381  for (int j = 0; j < banksPerRank; j++)
382  // next activate must not happen before end of window
383  rank_ref.banks[j].actAllowedAt =
384  std::max(rank_ref.actTicks.back() + tXAW,
385  rank_ref.banks[j].actAllowedAt);
386  }
387  }
388 
389  // at the point when this activate takes place, make sure we
390  // transition to the active power state
391  if (!rank_ref.activateEvent.scheduled())
392  schedule(rank_ref.activateEvent, act_at);
393  else if (rank_ref.activateEvent.when() > act_at)
394  // move it sooner in time
395  reschedule(rank_ref.activateEvent, act_at);
396 }
397 
398 void
399 DRAMInterface::prechargeBank(Rank& rank_ref, Bank& bank, Tick pre_tick,
400  bool auto_or_preall, bool trace)
401 {
402  // make sure the bank has an open row
403  assert(bank.openRow != Bank::NO_ROW);
404 
405  // sample the bytes per activate here since we are closing
406  // the page
408 
409  bank.openRow = Bank::NO_ROW;
410 
411  Tick pre_at = pre_tick;
412  if (auto_or_preall) {
413  // no precharge allowed before this one
414  bank.preAllowedAt = pre_at;
415  } else {
416  // Issuing an explicit PRE command
417  // Verify that we have command bandwidth to issue the precharge
418  // if not, shift to next burst window
419  pre_at = ctrl->verifySingleCmd(pre_tick, maxCommandsPerWindow);
420  // enforce tPPD
421  for (int i = 0; i < banksPerRank; i++) {
422  rank_ref.banks[i].preAllowedAt = std::max(pre_at + tPPD,
423  rank_ref.banks[i].preAllowedAt);
424  }
425  }
426 
427  Tick pre_done_at = pre_at + tRP;
428 
429  bank.actAllowedAt = std::max(bank.actAllowedAt, pre_done_at);
430 
431  assert(rank_ref.numBanksActive != 0);
432  --rank_ref.numBanksActive;
433 
434  DPRINTF(DRAM, "Precharging bank %d, rank %d at tick %lld, now got "
435  "%d active\n", bank.bank, rank_ref.rank, pre_at,
436  rank_ref.numBanksActive);
437 
438  if (trace) {
439 
440  rank_ref.cmdList.push_back(Command(MemCommand::PRE, bank.bank,
441  pre_at));
442  DPRINTF(DRAMPower, "%llu,PRE,%d,%d\n", divCeil(pre_at, tCK) -
443  timeStampOffset, bank.bank, rank_ref.rank);
444  }
445 
446  // if we look at the current number of active banks we might be
447  // tempted to think the DRAM is now idle, however this can be
448  // undone by an activate that is scheduled to happen before we
449  // would have reached the idle state, so schedule an event and
450  // rather check once we actually make it to the point in time when
451  // the (last) precharge takes place
452  if (!rank_ref.prechargeEvent.scheduled()) {
453  schedule(rank_ref.prechargeEvent, pre_done_at);
454  // New event, increment count
455  ++rank_ref.outstandingEvents;
456  } else if (rank_ref.prechargeEvent.when() < pre_done_at) {
457  reschedule(rank_ref.prechargeEvent, pre_done_at);
458  }
459 }
460 
463  const std::vector<MemPacketQueue>& queue)
464 {
465  DPRINTF(DRAM, "Timing access to addr %#x, rank/bank/row %d %d %d\n",
466  mem_pkt->addr, mem_pkt->rank, mem_pkt->bank, mem_pkt->row);
467 
468  // get the rank
469  Rank& rank_ref = *ranks[mem_pkt->rank];
470 
471  assert(rank_ref.inRefIdleState());
472 
473  // are we in or transitioning to a low-power state and have not scheduled
474  // a power-up event?
475  // if so, wake up from power down to issue RD/WR burst
476  if (rank_ref.inLowPowerState) {
477  assert(rank_ref.pwrState != PWR_SREF);
478  rank_ref.scheduleWakeUpEvent(tXP);
479  }
480 
481  // get the bank
482  Bank& bank_ref = rank_ref.banks[mem_pkt->bank];
483 
484  // for the state we need to track if it is a row hit or not
485  bool row_hit = true;
486 
487  // Determine the access latency and update the bank state
488  if (bank_ref.openRow == mem_pkt->row) {
489  // nothing to do
490  } else {
491  row_hit = false;
492 
493  // If there is a page open, precharge it.
494  if (bank_ref.openRow != Bank::NO_ROW) {
495  prechargeBank(rank_ref, bank_ref, std::max(bank_ref.preAllowedAt,
496  curTick()));
497  }
498 
499  // next we need to account for the delay in activating the page
500  Tick act_tick = std::max(bank_ref.actAllowedAt, curTick());
501 
502  // Record the activation and deal with all the global timing
503  // constraints caused be a new activation (tRRD and tXAW)
504  activateBank(rank_ref, bank_ref, act_tick, mem_pkt->row);
505  }
506 
507  // respect any constraints on the command (e.g. tRCD or tCCD)
508  const Tick col_allowed_at = mem_pkt->isRead() ?
509  bank_ref.rdAllowedAt : bank_ref.wrAllowedAt;
510 
511  // we need to wait until the bus is available before we can issue
512  // the command; need to ensure minimum bus delay requirement is met
513  Tick cmd_at = std::max({col_allowed_at, next_burst_at, curTick()});
514 
515  // verify that we have command bandwidth to issue the burst
516  // if not, shift to next burst window
517  if (dataClockSync && ((cmd_at - rank_ref.lastBurstTick) > clkResyncDelay))
518  cmd_at = ctrl->verifyMultiCmd(cmd_at, maxCommandsPerWindow, tCK);
519  else
520  cmd_at = ctrl->verifySingleCmd(cmd_at, maxCommandsPerWindow);
521 
522  // if we are interleaving bursts, ensure that
523  // 1) we don't double interleave on next burst issue
524  // 2) we are at an interleave boundary; if not, shift to next boundary
525  Tick burst_gap = tBURST_MIN;
526  if (burstInterleave) {
527  if (cmd_at == (rank_ref.lastBurstTick + tBURST_MIN)) {
528  // already interleaving, push next command to end of full burst
529  burst_gap = tBURST;
530  } else if (cmd_at < (rank_ref.lastBurstTick + tBURST)) {
531  // not at an interleave boundary after bandwidth check
532  // Shift command to tBURST boundary to avoid data contention
533  // Command will remain in the same burst window given that
534  // tBURST is less than tBURST_MAX
535  cmd_at = rank_ref.lastBurstTick + tBURST;
536  }
537  }
538  DPRINTF(DRAM, "Schedule RD/WR burst at tick %d\n", cmd_at);
539 
540  // update the packet ready time
541  mem_pkt->readyTime = cmd_at + tCL + tBURST;
542 
543  rank_ref.lastBurstTick = cmd_at;
544 
545  // update the time for the next read/write burst for each
546  // bank (add a max with tCCD/tCCD_L/tCCD_L_WR here)
547  Tick dly_to_rd_cmd;
548  Tick dly_to_wr_cmd;
549  for (int j = 0; j < ranksPerChannel; j++) {
550  for (int i = 0; i < banksPerRank; i++) {
551  if (mem_pkt->rank == j) {
552  if (bankGroupArch &&
553  (bank_ref.bankgr == ranks[j]->banks[i].bankgr)) {
554  // bank group architecture requires longer delays between
555  // RD/WR burst commands to the same bank group.
556  // tCCD_L is default requirement for same BG timing
557  // tCCD_L_WR is required for write-to-write
558  // Need to also take bus turnaround delays into account
559  dly_to_rd_cmd = mem_pkt->isRead() ?
560  tCCD_L : std::max(tCCD_L, wrToRdDlySameBG);
561  dly_to_wr_cmd = mem_pkt->isRead() ?
562  std::max(tCCD_L, rdToWrDlySameBG) :
563  tCCD_L_WR;
564  } else {
565  // tBURST is default requirement for diff BG timing
566  // Need to also take bus turnaround delays into account
567  dly_to_rd_cmd = mem_pkt->isRead() ? burst_gap :
569  dly_to_wr_cmd = mem_pkt->isRead() ? readToWriteDelay() :
570  burst_gap;
571  }
572  } else {
573  // different rank is by default in a different bank group and
574  // doesn't require longer tCCD or additional RTW, WTR delays
575  // Need to account for rank-to-rank switching
576  dly_to_wr_cmd = rankToRankDelay();
577  dly_to_rd_cmd = rankToRankDelay();
578  }
579  ranks[j]->banks[i].rdAllowedAt = std::max(cmd_at + dly_to_rd_cmd,
580  ranks[j]->banks[i].rdAllowedAt);
581  ranks[j]->banks[i].wrAllowedAt = std::max(cmd_at + dly_to_wr_cmd,
582  ranks[j]->banks[i].wrAllowedAt);
583  }
584  }
585 
586  // Save rank of current access
587  activeRank = mem_pkt->rank;
588 
589  // If this is a write, we also need to respect the write recovery
590  // time before a precharge, in the case of a read, respect the
591  // read to precharge constraint
592  bank_ref.preAllowedAt = std::max(bank_ref.preAllowedAt,
593  mem_pkt->isRead() ? cmd_at + tRTP :
594  mem_pkt->readyTime + tWR);
595 
596  // increment the bytes accessed and the accesses per row
597  bank_ref.bytesAccessed += burstSize;
598  ++bank_ref.rowAccesses;
599 
600  // if we reached the max, then issue with an auto-precharge
601  bool auto_precharge = pageMgmt == enums::close ||
602  bank_ref.rowAccesses == maxAccessesPerRow;
603 
604  // if we did not hit the limit, we might still want to
605  // auto-precharge
606  if (!auto_precharge &&
607  (pageMgmt == enums::open_adaptive ||
608  pageMgmt == enums::close_adaptive)) {
609  // a twist on the open and close page policies:
610  // 1) open_adaptive page policy does not blindly keep the
611  // page open, but close it if there are no row hits, and there
612  // are bank conflicts in the queue
613  // 2) close_adaptive page policy does not blindly close the
614  // page, but closes it only if there are no row hits in the queue.
615  // In this case, only force an auto precharge when there
616  // are no same page hits in the queue
617  bool got_more_hits = false;
618  bool got_bank_conflict = false;
619 
620  for (uint8_t i = 0; i < ctrl->numPriorities(); ++i) {
621  auto p = queue[i].begin();
622  // keep on looking until we find a hit or reach the end of the
623  // queue
624  // 1) if a hit is found, then both open and close adaptive
625  // policies keep the page open
626  // 2) if no hit is found, got_bank_conflict is set to true if a
627  // bank conflict request is waiting in the queue
628  // 3) make sure we are not considering the packet that we are
629  // currently dealing with
630  while (!got_more_hits && p != queue[i].end()) {
631  if (mem_pkt != (*p)) {
632  bool same_rank_bank = (mem_pkt->rank == (*p)->rank) &&
633  (mem_pkt->bank == (*p)->bank);
634 
635  bool same_row = mem_pkt->row == (*p)->row;
636  got_more_hits |= same_rank_bank && same_row;
637  got_bank_conflict |= same_rank_bank && !same_row;
638  }
639  ++p;
640  }
641 
642  if (got_more_hits)
643  break;
644  }
645 
646  // auto pre-charge when either
647  // 1) open_adaptive policy, we have not got any more hits, and
648  // have a bank conflict
649  // 2) close_adaptive policy and we have not got any more hits
650  auto_precharge = !got_more_hits &&
651  (got_bank_conflict || pageMgmt == enums::close_adaptive);
652  }
653 
654  // DRAMPower trace command to be written
655  std::string mem_cmd = mem_pkt->isRead() ? "RD" : "WR";
656 
657  // MemCommand required for DRAMPower library
658  MemCommand::cmds command = (mem_cmd == "RD") ? MemCommand::RD :
659  MemCommand::WR;
660 
661  rank_ref.cmdList.push_back(Command(command, mem_pkt->bank, cmd_at));
662 
663  DPRINTF(DRAMPower, "%llu,%s,%d,%d\n", divCeil(cmd_at, tCK) -
664  timeStampOffset, mem_cmd, mem_pkt->bank, mem_pkt->rank);
665 
666  // if this access should use auto-precharge, then we are
667  // closing the row after the read/write burst
668  if (auto_precharge) {
669  // if auto-precharge push a PRE command at the correct tick to the
670  // list used by DRAMPower library to calculate power
671  prechargeBank(rank_ref, bank_ref, std::max(curTick(),
672  bank_ref.preAllowedAt), true);
673 
674  DPRINTF(DRAM, "Auto-precharged bank: %d\n", mem_pkt->bankId);
675  }
676 
677  // Update the stats and schedule the next request
678  if (mem_pkt->isRead()) {
679  // Every respQueue which will generate an event, increment count
680  ++rank_ref.outstandingEvents;
681 
682  stats.readBursts++;
683  if (row_hit)
684  stats.readRowHits++;
686  stats.perBankRdBursts[mem_pkt->bankId]++;
687 
688  // Update latency stats
689  stats.totMemAccLat += mem_pkt->readyTime - mem_pkt->entryTime;
690  stats.totQLat += cmd_at - mem_pkt->entryTime;
692  } else {
693  // Schedule write done event to decrement event count
694  // after the readyTime has been reached
695  // Only schedule latest write event to minimize events
696  // required; only need to ensure that final event scheduled covers
697  // the time that writes are outstanding and bus is active
698  // to holdoff power-down entry events
699  if (!rank_ref.writeDoneEvent.scheduled()) {
700  schedule(rank_ref.writeDoneEvent, mem_pkt->readyTime);
701  // New event, increment count
702  ++rank_ref.outstandingEvents;
703 
704  } else if (rank_ref.writeDoneEvent.when() < mem_pkt->readyTime) {
705  reschedule(rank_ref.writeDoneEvent, mem_pkt->readyTime);
706  }
707  // will remove write from queue when returned to parent function
708  // decrement count for DRAM rank
709  --rank_ref.writeEntries;
710 
711  stats.writeBursts++;
712  if (row_hit)
715  stats.perBankWrBursts[mem_pkt->bankId]++;
716 
717  }
718  // Update bus state to reflect when previous command was issued
719  return std::make_pair(cmd_at, cmd_at + burst_gap);
720 }
721 
722 void
724 {
725  // update timing for DRAM ranks due to bursts issued
726  // to ranks on other media interfaces
727  for (auto n : ranks) {
728  for (int i = 0; i < banksPerRank; i++) {
729  // different rank by default
730  // Need to only account for rank-to-rank switching
731  n->banks[i].rdAllowedAt = std::max(cmd_at + rankToRankDelay(),
732  n->banks[i].rdAllowedAt);
733  n->banks[i].wrAllowedAt = std::max(cmd_at + rankToRankDelay(),
734  n->banks[i].wrAllowedAt);
735  }
736  }
737 }
738 
739 DRAMInterface::DRAMInterface(const DRAMInterfaceParams &_p)
740  : MemInterface(_p),
741  bankGroupsPerRank(_p.bank_groups_per_rank),
742  bankGroupArch(_p.bank_groups_per_rank > 0),
743  tCL(_p.tCL),
744  tBURST_MIN(_p.tBURST_MIN), tBURST_MAX(_p.tBURST_MAX),
745  tCCD_L_WR(_p.tCCD_L_WR), tCCD_L(_p.tCCD_L), tRCD(_p.tRCD),
746  tRP(_p.tRP), tRAS(_p.tRAS), tWR(_p.tWR), tRTP(_p.tRTP),
747  tRFC(_p.tRFC), tREFI(_p.tREFI), tRRD(_p.tRRD), tRRD_L(_p.tRRD_L),
748  tPPD(_p.tPPD), tAAD(_p.tAAD),
749  tXAW(_p.tXAW), tXP(_p.tXP), tXS(_p.tXS),
750  clkResyncDelay(tCL + _p.tBURST_MAX),
751  dataClockSync(_p.data_clock_sync),
752  burstInterleave(tBURST != tBURST_MIN),
753  twoCycleActivate(_p.two_cycle_activate),
754  activationLimit(_p.activation_limit),
755  wrToRdDlySameBG(tCL + _p.tBURST_MAX + _p.tWTR_L),
756  rdToWrDlySameBG(_p.tRTW + _p.tBURST_MAX),
757  pageMgmt(_p.page_policy),
758  maxAccessesPerRow(_p.max_accesses_per_row),
759  timeStampOffset(0), activeRank(0),
760  enableDRAMPowerdown(_p.enable_dram_powerdown),
761  lastStatsResetTick(0),
762  stats(*this)
763 {
764  DPRINTF(DRAM, "Setting up DRAM Interface\n");
765 
766  fatal_if(!isPowerOf2(burstSize), "DRAM burst size %d is not allowed, "
767  "must be a power of two\n", burstSize);
768 
769  // sanity check the ranks since we rely on bit slicing for the
770  // address decoding
771  fatal_if(!isPowerOf2(ranksPerChannel), "DRAM rank count of %d is "
772  "not allowed, must be a power of two\n", ranksPerChannel);
773 
774  for (int i = 0; i < ranksPerChannel; i++) {
775  DPRINTF(DRAM, "Creating DRAM rank %d \n", i);
776  Rank* rank = new Rank(_p, i, *this);
777  ranks.push_back(rank);
778  }
779 
780  // determine the dram actual capacity from the DRAM config in Mbytes
781  uint64_t deviceCapacity = deviceSize / (1024 * 1024) * devicesPerRank *
783 
784  uint64_t capacity = 1ULL << ceilLog2(AbstractMemory::size());
785 
786  DPRINTF(DRAM, "Memory capacity %lld (%lld) bytes\n", capacity,
788 
789  // if actual DRAM size does not match memory capacity in system warn!
790  if (deviceCapacity != capacity / (1024 * 1024))
791  warn("DRAM device capacity (%d Mbytes) does not match the "
792  "address range assigned (%d Mbytes)\n", deviceCapacity,
793  capacity / (1024 * 1024));
794 
795  DPRINTF(DRAM, "Row buffer size %d bytes with %d bursts per row buffer\n",
797 
799 
800  // some basic sanity checks
801  if (tREFI <= tRP || tREFI <= tRFC) {
802  fatal("tREFI (%d) must be larger than tRP (%d) and tRFC (%d)\n",
803  tREFI, tRP, tRFC);
804  }
805 
806  // basic bank group architecture checks ->
807  if (bankGroupArch) {
808  // must have at least one bank per bank group
810  fatal("banks per rank (%d) must be equal to or larger than "
811  "banks groups per rank (%d)\n",
813  }
814  // must have same number of banks in each bank group
815  if ((banksPerRank % bankGroupsPerRank) != 0) {
816  fatal("Banks per rank (%d) must be evenly divisible by bank "
817  "groups per rank (%d) for equal banks per bank group\n",
819  }
820  // tCCD_L should be greater than minimal, back-to-back burst delay
821  if (tCCD_L <= tBURST) {
822  fatal("tCCD_L (%d) should be larger than the minimum bus delay "
823  "(%d) when bank groups per rank (%d) is greater than 1\n",
825  }
826  // tCCD_L_WR should be greater than minimal, back-to-back burst delay
827  if (tCCD_L_WR <= tBURST) {
828  fatal("tCCD_L_WR (%d) should be larger than the minimum bus delay "
829  " (%d) when bank groups per rank (%d) is greater than 1\n",
831  }
832  // tRRD_L is greater than minimal, same bank group ACT-to-ACT delay
833  // some datasheets might specify it equal to tRRD
834  if (tRRD_L < tRRD) {
835  fatal("tRRD_L (%d) should be larger than tRRD (%d) when "
836  "bank groups per rank (%d) is greater than 1\n",
838  }
839  }
840 }
841 
842 void
844 {
846 
847  // a bit of sanity checks on the interleaving, save it for here to
848  // ensure that the system pointer is initialised
849  if (range.interleaved()) {
850  if (addrMapping == enums::RoRaBaChCo) {
851  if (rowBufferSize != range.granularity()) {
852  fatal("Channel interleaving of %s doesn't match RoRaBaChCo "
853  "address map\n", name());
854  }
855  } else if (addrMapping == enums::RoRaBaCoCh ||
856  addrMapping == enums::RoCoRaBaCh) {
857  // for the interleavings with channel bits in the bottom,
858  // if the system uses a channel striping granularity that
859  // is larger than the DRAM burst size, then map the
860  // sequential accesses within a stripe to a number of
861  // columns in the DRAM, effectively placing some of the
862  // lower-order column bits as the least-significant bits
863  // of the address (above the ones denoting the burst size)
864  assert(burstsPerStripe >= 1);
865 
866  // channel striping has to be done at a granularity that
867  // is equal or larger to a cache line
868  if (system()->cacheLineSize() > range.granularity()) {
869  fatal("Channel interleaving of %s must be at least as large "
870  "as the cache line size\n", name());
871  }
872 
873  // ...and equal or smaller than the row-buffer size
874  if (rowBufferSize < range.granularity()) {
875  fatal("Channel interleaving of %s must be at most as large "
876  "as the row-buffer size\n", name());
877  }
878  // this is essentially the check above, so just to be sure
880  }
881  }
882 }
883 
884 void
886 {
887  if (system()->isTimingMode()) {
888  // timestamp offset should be in clock cycles for DRAMPower
890 
891  for (auto r : ranks) {
892  r->startup(curTick() + tREFI - tRP);
893  }
894  }
895 }
896 
897 bool
899 {
900  int busy_ranks = 0;
901  for (auto r : ranks) {
902  if (!r->inRefIdleState()) {
903  if (r->pwrState != PWR_SREF) {
904  // rank is busy refreshing
905  DPRINTF(DRAMState, "Rank %d is not available\n", r->rank);
906  busy_ranks++;
907 
908  // let the rank know that if it was waiting to drain, it
909  // is now done and ready to proceed
910  r->checkDrainDone();
911  }
912 
913  // check if we were in self-refresh and haven't started
914  // to transition out
915  if ((r->pwrState == PWR_SREF) && r->inLowPowerState) {
916  DPRINTF(DRAMState, "Rank %d is in self-refresh\n", r->rank);
917  // if we have commands queued to this rank and we don't have
918  // a minimum number of active commands enqueued,
919  // exit self-refresh
920  if (r->forceSelfRefreshExit()) {
921  DPRINTF(DRAMState, "rank %d was in self refresh and"
922  " should wake up\n", r->rank);
923  //wake up from self-refresh
924  r->scheduleWakeUpEvent(tXS);
925  // things are brought back into action once a refresh is
926  // performed after self-refresh
927  // continue with selection for other ranks
928  }
929  }
930  }
931  }
932  return (busy_ranks == ranksPerChannel);
933 }
934 
935 void DRAMInterface::setupRank(const uint8_t rank, const bool is_read)
936 {
937  // increment entry count of the rank based on packet type
938  if (is_read) {
939  ++ranks[rank]->readEntries;
940  } else {
941  ++ranks[rank]->writeEntries;
942  }
943 }
944 
945 void
947 {
948  Rank& rank_ref = *ranks[rank];
949 
950  // if a read has reached its ready-time, decrement the number of reads
951  // At this point the packet has been handled and there is a possibility
952  // to switch to low-power mode if no other packet is available
953  --rank_ref.readEntries;
954  DPRINTF(DRAM, "number of read entries for rank %d is %d\n",
955  rank, rank_ref.readEntries);
956 
957  // counter should at least indicate one outstanding request
958  // for this read
959  assert(rank_ref.outstandingEvents > 0);
960  // read response received, decrement count
961  --rank_ref.outstandingEvents;
962 
963  // at this moment should not have transitioned to a low-power state
964  assert((rank_ref.pwrState != PWR_SREF) &&
965  (rank_ref.pwrState != PWR_PRE_PDN) &&
966  (rank_ref.pwrState != PWR_ACT_PDN));
967 
968  // track if this is the last packet before idling
969  // and that there are no outstanding commands to this rank
970  if (rank_ref.isQueueEmpty() && rank_ref.outstandingEvents == 0 &&
971  rank_ref.inRefIdleState() && enableDRAMPowerdown) {
972  // verify that there are no events scheduled
973  assert(!rank_ref.activateEvent.scheduled());
974  assert(!rank_ref.prechargeEvent.scheduled());
975 
976  // if coming from active state, schedule power event to
977  // active power-down else go to precharge power-down
978  DPRINTF(DRAMState, "Rank %d sleep at tick %d; current power state is "
979  "%d\n", rank, curTick(), rank_ref.pwrState);
980 
981  // default to ACT power-down unless already in IDLE state
982  // could be in IDLE if PRE issued before data returned
983  PowerState next_pwr_state = PWR_ACT_PDN;
984  if (rank_ref.pwrState == PWR_IDLE) {
985  next_pwr_state = PWR_PRE_PDN;
986  }
987 
988  rank_ref.powerDownSleep(next_pwr_state, curTick());
989  }
990 }
991 
992 void
994 {
995  Rank& rank_ref = *ranks[rank];
996 
997  if ((rank_ref.refreshState == REF_PRE) &&
998  !rank_ref.prechargeEvent.scheduled()) {
999  // kick the refresh event loop into action again if banks already
1000  // closed and just waiting for read to complete
1001  schedule(rank_ref.refreshEvent, curTick());
1002  }
1003 }
1004 
1005 void
1007 {
1008  // also need to kick off events to exit self-refresh
1009  for (auto r : ranks) {
1010  // force self-refresh exit, which in turn will issue auto-refresh
1011  if (r->pwrState == PWR_SREF) {
1012  DPRINTF(DRAM,"Rank%d: Forcing self-refresh wakeup in drain\n",
1013  r->rank);
1014  r->scheduleWakeUpEvent(tXS);
1015  }
1016  }
1017 }
1018 
1019 bool
1021 {
1022  // true until proven false
1023  bool all_ranks_drained = true;
1024  for (auto r : ranks) {
1025  // then verify that the power state is IDLE ensuring all banks are
1026  // closed and rank is not in a low power state. Also verify that rank
1027  // is idle from a refresh point of view.
1028  all_ranks_drained = r->inPwrIdleState() && r->inRefIdleState() &&
1029  all_ranks_drained;
1030  }
1031  return all_ranks_drained;
1032 }
1033 
1034 void
1036 {
1037  for (auto r : ranks) {
1038  r->suspend();
1039  }
1040 }
1041 
1044  Tick min_col_at) const
1045 {
1046  Tick min_act_at = MaxTick;
1047  std::vector<uint32_t> bank_mask(ranksPerChannel, 0);
1048 
1049  // latest Tick for which ACT can occur without incurring additoinal
1050  // delay on the data bus
1051  const Tick hidden_act_max = std::max(min_col_at - tRCD, curTick());
1052 
1053  // Flag condition when burst can issue back-to-back with previous burst
1054  bool found_seamless_bank = false;
1055 
1056  // Flag condition when bank can be opened without incurring additional
1057  // delay on the data bus
1058  bool hidden_bank_prep = false;
1059 
1060  // determine if we have queued transactions targetting the
1061  // bank in question
1062  std::vector<bool> got_waiting(ranksPerChannel * banksPerRank, false);
1063  for (const auto& p : queue) {
1064  if (p->isDram() && ranks[p->rank]->inRefIdleState())
1065  got_waiting[p->bankId] = true;
1066  }
1067 
1068  // Find command with optimal bank timing
1069  // Will prioritize commands that can issue seamlessly.
1070  for (int i = 0; i < ranksPerChannel; i++) {
1071  for (int j = 0; j < banksPerRank; j++) {
1072  uint16_t bank_id = i * banksPerRank + j;
1073 
1074  // if we have waiting requests for the bank, and it is
1075  // amongst the first available, update the mask
1076  if (got_waiting[bank_id]) {
1077  // make sure this rank is not currently refreshing.
1078  assert(ranks[i]->inRefIdleState());
1079  // simplistic approximation of when the bank can issue
1080  // an activate, ignoring any rank-to-rank switching
1081  // cost in this calculation
1082  Tick act_at = ranks[i]->banks[j].openRow == Bank::NO_ROW ?
1083  std::max(ranks[i]->banks[j].actAllowedAt, curTick()) :
1084  std::max(ranks[i]->banks[j].preAllowedAt, curTick()) + tRP;
1085 
1086  // When is the earliest the R/W burst can issue?
1087  const Tick col_allowed_at = ctrl->inReadBusState(false) ?
1088  ranks[i]->banks[j].rdAllowedAt :
1089  ranks[i]->banks[j].wrAllowedAt;
1090  Tick col_at = std::max(col_allowed_at, act_at + tRCD);
1091 
1092  // bank can issue burst back-to-back (seamlessly) with
1093  // previous burst
1094  bool new_seamless_bank = col_at <= min_col_at;
1095 
1096  // if we found a new seamless bank or we have no
1097  // seamless banks, and got a bank with an earlier
1098  // activate time, it should be added to the bit mask
1099  if (new_seamless_bank ||
1100  (!found_seamless_bank && act_at <= min_act_at)) {
1101  // if we did not have a seamless bank before, and
1102  // we do now, reset the bank mask, also reset it
1103  // if we have not yet found a seamless bank and
1104  // the activate time is smaller than what we have
1105  // seen so far
1106  if (!found_seamless_bank &&
1107  (new_seamless_bank || act_at < min_act_at)) {
1108  std::fill(bank_mask.begin(), bank_mask.end(), 0);
1109  }
1110 
1111  found_seamless_bank |= new_seamless_bank;
1112 
1113  // ACT can occur 'behind the scenes'
1114  hidden_bank_prep = act_at <= hidden_act_max;
1115 
1116  // set the bit corresponding to the available bank
1117  replaceBits(bank_mask[i], j, j, 1);
1118  min_act_at = act_at;
1119  }
1120  }
1121  }
1122  }
1123 
1124  return std::make_pair(bank_mask, hidden_bank_prep);
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. sim_clock::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  (sim_clock::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  : statistics::Group(&_dram),
1856  dram(_dram),
1857 
1858  ADD_STAT(readBursts, statistics::units::Count::get(),
1859  "Number of DRAM read bursts"),
1860  ADD_STAT(writeBursts, statistics::units::Count::get(),
1861  "Number of DRAM write bursts"),
1862 
1863  ADD_STAT(perBankRdBursts, statistics::units::Count::get(),
1864  "Per bank write bursts"),
1865  ADD_STAT(perBankWrBursts, statistics::units::Count::get(),
1866  "Per bank write bursts"),
1867 
1868  ADD_STAT(totQLat, statistics::units::Tick::get(), "Total ticks spent queuing"),
1869  ADD_STAT(totBusLat, statistics::units::Tick::get(),
1870  "Total ticks spent in databus transfers"),
1871  ADD_STAT(totMemAccLat, statistics::units::Tick::get(),
1872  "Total ticks spent from burst creation until serviced "
1873  "by the DRAM"),
1874 
1875  ADD_STAT(avgQLat, statistics::units::Rate<
1876  statistics::units::Tick, statistics::units::Count>::get(),
1877  "Average queueing delay per DRAM burst"),
1878  ADD_STAT(avgBusLat, statistics::units::Rate<
1879  statistics::units::Tick, statistics::units::Count>::get(),
1880  "Average bus latency per DRAM burst"),
1881  ADD_STAT(avgMemAccLat, statistics::units::Rate<
1882  statistics::units::Tick, statistics::units::Count>::get(),
1883  "Average memory access latency per DRAM burst"),
1884 
1885  ADD_STAT(readRowHits, statistics::units::Count::get(),
1886  "Number of row buffer hits during reads"),
1887  ADD_STAT(writeRowHits, statistics::units::Count::get(),
1888  "Number of row buffer hits during writes"),
1889  ADD_STAT(readRowHitRate, statistics::units::Ratio::get(),
1890  "Row buffer hit rate for reads"),
1891  ADD_STAT(writeRowHitRate, statistics::units::Ratio::get(),
1892  "Row buffer hit rate for writes"),
1893 
1894  ADD_STAT(bytesPerActivate, statistics::units::Byte::get(),
1895  "Bytes accessed per row activation"),
1896  ADD_STAT(bytesRead, statistics::units::Byte::get(),
1897  "Total number of bytes read from DRAM"),
1898  ADD_STAT(bytesWritten, statistics::units::Byte::get(),
1899  "Total number of bytes written to DRAM"),
1900  ADD_STAT(avgRdBW, statistics::units::Rate<
1901  statistics::units::Byte, statistics::units::Second>::get(),
1902  "Average DRAM read bandwidth in MiBytes/s"),
1903  ADD_STAT(avgWrBW, statistics::units::Rate<
1904  statistics::units::Byte, statistics::units::Second>::get(),
1905  "Average DRAM write bandwidth in MiBytes/s"),
1906  ADD_STAT(peakBW, statistics::units::Rate<
1907  statistics::units::Byte, statistics::units::Second>::get(),
1908  "Theoretical peak bandwidth in MiByte/s"),
1909 
1910  ADD_STAT(busUtil, statistics::units::Ratio::get(),
1911  "Data bus utilization in percentage"),
1912  ADD_STAT(busUtilRead, statistics::units::Ratio::get(),
1913  "Data bus utilization in percentage for reads"),
1914  ADD_STAT(busUtilWrite, statistics::units::Ratio::get(),
1915  "Data bus utilization in percentage for writes"),
1916 
1917  ADD_STAT(pageHitRate, statistics::units::Ratio::get(),
1918  "Row buffer hit rate, read and write combined")
1919 
1920 {
1921 }
1922 
1923 void
1925 {
1926  using namespace statistics;
1927 
1928  avgQLat.precision(2);
1929  avgBusLat.precision(2);
1930  avgMemAccLat.precision(2);
1931 
1932  readRowHitRate.precision(2);
1933  writeRowHitRate.precision(2);
1934 
1935  perBankRdBursts.init(dram.banksPerRank * dram.ranksPerChannel);
1936  perBankWrBursts.init(dram.banksPerRank * dram.ranksPerChannel);
1937 
1938  bytesPerActivate
1939  .init(dram.maxAccessesPerRow ?
1940  dram.maxAccessesPerRow : dram.rowBufferSize)
1941  .flags(nozero);
1942 
1943  peakBW.precision(2);
1944  busUtil.precision(2);
1945  busUtilWrite.precision(2);
1946  busUtilRead.precision(2);
1947 
1948  pageHitRate.precision(2);
1949 
1950  // Formula stats
1951  avgQLat = totQLat / readBursts;
1952  avgBusLat = totBusLat / readBursts;
1953  avgMemAccLat = totMemAccLat / readBursts;
1954 
1955  readRowHitRate = (readRowHits / readBursts) * 100;
1956  writeRowHitRate = (writeRowHits / writeBursts) * 100;
1957 
1958  avgRdBW = (bytesRead / 1000000) / simSeconds;
1959  avgWrBW = (bytesWritten / 1000000) / simSeconds;
1960  peakBW = (sim_clock::Frequency / dram.burstDelay()) *
1961  dram.bytesPerBurst() / 1000000;
1962 
1963  busUtil = (avgRdBW + avgWrBW) / peakBW * 100;
1964  busUtilRead = avgRdBW / peakBW * 100;
1965  busUtilWrite = avgWrBW / peakBW * 100;
1966 
1967  pageHitRate = (writeRowHits + readRowHits) /
1968  (writeBursts + readBursts) * 100;
1969 }
1970 
1972  : statistics::Group(&_dram, csprintf("rank%d", _rank.rank).c_str()),
1973  rank(_rank),
1974 
1975  ADD_STAT(actEnergy, statistics::units::Joule::get(),
1976  "Energy for activate commands per rank (pJ)"),
1977  ADD_STAT(preEnergy, statistics::units::Joule::get(),
1978  "Energy for precharge commands per rank (pJ)"),
1979  ADD_STAT(readEnergy, statistics::units::Joule::get(),
1980  "Energy for read commands per rank (pJ)"),
1981  ADD_STAT(writeEnergy, statistics::units::Joule::get(),
1982  "Energy for write commands per rank (pJ)"),
1983  ADD_STAT(refreshEnergy, statistics::units::Joule::get(),
1984  "Energy for refresh commands per rank (pJ)"),
1985  ADD_STAT(actBackEnergy, statistics::units::Joule::get(),
1986  "Energy for active background per rank (pJ)"),
1987  ADD_STAT(preBackEnergy, statistics::units::Joule::get(),
1988  "Energy for precharge background per rank (pJ)"),
1989  ADD_STAT(actPowerDownEnergy, statistics::units::Joule::get(),
1990  "Energy for active power-down per rank (pJ)"),
1991  ADD_STAT(prePowerDownEnergy, statistics::units::Joule::get(),
1992  "Energy for precharge power-down per rank (pJ)"),
1993  ADD_STAT(selfRefreshEnergy, statistics::units::Joule::get(),
1994  "Energy for self refresh per rank (pJ)"),
1995 
1996  ADD_STAT(totalEnergy, statistics::units::Joule::get(),
1997  "Total energy per rank (pJ)"),
1998  ADD_STAT(averagePower, statistics::units::Watt::get(),
1999  "Core power per rank (mW)"),
2000 
2001  ADD_STAT(totalIdleTime, statistics::units::Tick::get(),
2002  "Total Idle time Per DRAM Rank"),
2003  ADD_STAT(pwrStateTime, statistics::units::Tick::get(),
2004  "Time in different power states")
2005 {
2006 }
2007 
2008 void
2010 {
2012 
2013  pwrStateTime
2014  .init(6)
2015  .subname(0, "IDLE")
2016  .subname(1, "REF")
2017  .subname(2, "SREF")
2018  .subname(3, "PRE_PDN")
2019  .subname(4, "ACT")
2020  .subname(5, "ACT_PDN");
2021 }
2022 
2023 void
2025 {
2027 
2028  rank.resetStats();
2029 }
2030 
2031 void
2033 {
2035 
2036  rank.computeStats();
2037 }
2038 
2039 NVMInterface::NVMInterface(const NVMInterfaceParams &_p)
2040  : MemInterface(_p),
2041  maxPendingWrites(_p.max_pending_writes),
2042  maxPendingReads(_p.max_pending_reads),
2043  twoCycleRdWr(_p.two_cycle_rdwr),
2044  tREAD(_p.tREAD), tWRITE(_p.tWRITE), tSEND(_p.tSEND),
2045  stats(*this),
2046  writeRespondEvent([this]{ processWriteRespondEvent(); }, name()),
2047  readReadyEvent([this]{ processReadReadyEvent(); }, name()),
2048  nextReadAt(0), numPendingReads(0), numReadDataReady(0),
2049  numReadsToIssue(0), numWritesQueued(0)
2050 {
2051  DPRINTF(NVM, "Setting up NVM Interface\n");
2052 
2053  fatal_if(!isPowerOf2(burstSize), "NVM burst size %d is not allowed, "
2054  "must be a power of two\n", burstSize);
2055 
2056  // sanity check the ranks since we rely on bit slicing for the
2057  // address decoding
2058  fatal_if(!isPowerOf2(ranksPerChannel), "NVM rank count of %d is "
2059  "not allowed, must be a power of two\n", ranksPerChannel);
2060 
2061  for (int i =0; i < ranksPerChannel; i++) {
2062  // Add NVM ranks to the system
2063  DPRINTF(NVM, "Creating NVM rank %d \n", i);
2064  Rank* rank = new Rank(_p, i, *this);
2065  ranks.push_back(rank);
2066  }
2067 
2068  uint64_t capacity = 1ULL << ceilLog2(AbstractMemory::size());
2069 
2070  DPRINTF(NVM, "NVM capacity %lld (%lld) bytes\n", capacity,
2072 
2073  rowsPerBank = capacity / (rowBufferSize *
2074  banksPerRank * ranksPerChannel);
2075 
2076 }
2077 
2078 NVMInterface::Rank::Rank(const NVMInterfaceParams &_p,
2079  int _rank, NVMInterface& _nvm)
2080  : EventManager(&_nvm), rank(_rank), banks(_p.banks_per_rank)
2081 {
2082  for (int b = 0; b < _p.banks_per_rank; b++) {
2083  banks[b].bank = b;
2084  // No bank groups; simply assign to bank number
2085  banks[b].bankgr = b;
2086  }
2087 }
2088 
2089 void
2091 {
2093 }
2094 
2095 void NVMInterface::setupRank(const uint8_t rank, const bool is_read)
2096 {
2097  if (is_read) {
2098  // increment count to trigger read and track number of reads in Q
2099  numReadsToIssue++;
2100  } else {
2101  // increment count to track number of writes in Q
2102  numWritesQueued++;
2103  }
2104 }
2105 
2108 {
2109  // remember if we found a hit, but one that cannit issue seamlessly
2110  bool found_prepped_pkt = false;
2111 
2112  auto selected_pkt_it = queue.end();
2113  Tick selected_col_at = MaxTick;
2114 
2115  for (auto i = queue.begin(); i != queue.end() ; ++i) {
2116  MemPacket* pkt = *i;
2117 
2118  // select optimal NVM packet in Q
2119  if (!pkt->isDram()) {
2120  const Bank& bank = ranks[pkt->rank]->banks[pkt->bank];
2121  const Tick col_allowed_at = pkt->isRead() ? bank.rdAllowedAt :
2122  bank.wrAllowedAt;
2123 
2124  // check if rank is not doing a refresh and thus is available,
2125  // if not, jump to the next packet
2126  if (burstReady(pkt)) {
2127  DPRINTF(NVM, "%s bank %d - Rank %d available\n", __func__,
2128  pkt->bank, pkt->rank);
2129 
2130  // no additional rank-to-rank or media delays
2131  if (col_allowed_at <= min_col_at) {
2132  // FCFS within entries that can issue without
2133  // additional delay, such as same rank accesses
2134  // or media delay requirements
2135  selected_pkt_it = i;
2136  selected_col_at = col_allowed_at;
2137  // no need to look through the remaining queue entries
2138  DPRINTF(NVM, "%s Seamless buffer hit\n", __func__);
2139  break;
2140  } else if (!found_prepped_pkt) {
2141  // packet is to prepped region but cannnot issue
2142  // seamlessly; remember this one and continue
2143  selected_pkt_it = i;
2144  selected_col_at = col_allowed_at;
2145  DPRINTF(NVM, "%s Prepped packet found \n", __func__);
2146  found_prepped_pkt = true;
2147  }
2148  } else {
2149  DPRINTF(NVM, "%s bank %d - Rank %d not available\n", __func__,
2150  pkt->bank, pkt->rank);
2151  }
2152  }
2153  }
2154 
2155  if (selected_pkt_it == queue.end()) {
2156  DPRINTF(NVM, "%s no available NVM ranks found\n", __func__);
2157  }
2158 
2159  return std::make_pair(selected_pkt_it, selected_col_at);
2160 }
2161 
2162 void
2164 {
2165  Tick cmd_at = std::max(curTick(), nextReadAt);
2166 
2167  // This method does the arbitration between non-deterministic read
2168  // requests to NVM. The chosen packet is not removed from the queue
2169  // at this time. Removal from the queue will occur when the data is
2170  // ready and a separate SEND command is issued to retrieve it via the
2171  // chooseNext function in the top-level controller.
2172  assert(!queue.empty());
2173 
2174  assert(numReadsToIssue > 0);
2175  numReadsToIssue--;
2176  // For simplicity, issue non-deterministic reads in order (fcfs)
2177  for (auto i = queue.begin(); i != queue.end() ; ++i) {
2178  MemPacket* pkt = *i;
2179 
2180  // Find 1st NVM read packet that hasn't issued read command
2181  if (pkt->readyTime == MaxTick && !pkt->isDram() && pkt->isRead()) {
2182  // get the bank
2183  Bank& bank_ref = ranks[pkt->rank]->banks[pkt->bank];
2184 
2185  // issueing a read, inc counter and verify we haven't overrun
2186  numPendingReads++;
2187  assert(numPendingReads <= maxPendingReads);
2188 
2189  // increment the bytes accessed and the accesses per row
2190  bank_ref.bytesAccessed += burstSize;
2191 
2192  // Verify command bandiwth to issue
2193  // Host can issue read immediately uith buffering closer
2194  // to the NVM. The actual execution at the NVM may be delayed
2195  // due to busy resources
2196  if (twoCycleRdWr) {
2197  cmd_at = ctrl->verifyMultiCmd(cmd_at,
2199  } else {
2200  cmd_at = ctrl->verifySingleCmd(cmd_at,
2202  }
2203 
2204  // Update delay to next read
2205  // Ensures single read command issued per cycle
2206  nextReadAt = cmd_at + tCK;
2207 
2208  // If accessing a new location in this bank, update timing
2209  // and stats
2210  if (bank_ref.openRow != pkt->row) {
2211  // update the open bank, re-using row field
2212  bank_ref.openRow = pkt->row;
2213 
2214  // sample the bytes accessed to a buffer in this bank
2215  // here when we are re-buffering the data
2217  // start counting anew
2218  bank_ref.bytesAccessed = 0;
2219 
2220  // holdoff next command to this bank until the read completes
2221  // and the data has been successfully buffered
2222  // can pipeline accesses to the same bank, sending them
2223  // across the interface B2B, but will incur full access
2224  // delay between data ready responses to different buffers
2225  // in a bank
2226  bank_ref.actAllowedAt = std::max(cmd_at,
2227  bank_ref.actAllowedAt) + tREAD;
2228  }
2229  // update per packet readyTime to holdoff burst read operation
2230  // overloading readyTime, which will be updated again when the
2231  // burst is issued
2232  pkt->readyTime = std::max(cmd_at, bank_ref.actAllowedAt);
2233 
2234  DPRINTF(NVM, "Issuing NVM Read to bank %d at tick %d. "
2235  "Data ready at %d\n",
2236  bank_ref.bank, cmd_at, pkt->readyTime);
2237 
2238  // Insert into read ready queue. It will be handled after
2239  // the media delay has been met
2240  if (readReadyQueue.empty()) {
2241  assert(!readReadyEvent.scheduled());
2243  } else if (readReadyEvent.when() > pkt->readyTime) {
2244  // move it sooner in time, to the first read with data
2246  } else {
2247  assert(readReadyEvent.scheduled());
2248  }
2249  readReadyQueue.push_back(pkt->readyTime);
2250 
2251  // found an NVM read to issue - break out
2252  break;
2253  }
2254  }
2255 }
2256 
2257 void
2259 {
2260  // signal that there is read data ready to be transmitted
2261  numReadDataReady++;
2262 
2263  DPRINTF(NVM,
2264  "processReadReadyEvent(): Data for an NVM read is ready. "
2265  "numReadDataReady is %d\t numPendingReads is %d\n",
2267 
2268  // Find lowest ready time and verify it is equal to curTick
2269  // also find the next lowest to schedule next event
2270  // Done with this response, erase entry
2271  auto ready_it = readReadyQueue.begin();
2272  Tick next_ready_at = MaxTick;
2273  for (auto i = readReadyQueue.begin(); i != readReadyQueue.end() ; ++i) {
2274  if (*ready_it > *i) {
2275  next_ready_at = *ready_it;
2276  ready_it = i;
2277  } else if ((next_ready_at > *i) && (i != ready_it)) {
2278  next_ready_at = *i;
2279  }
2280  }
2281 
2282  // Verify we found the time of this event and remove it
2283  assert(*ready_it == curTick());
2284  readReadyQueue.erase(ready_it);
2285 
2286  if (!readReadyQueue.empty()) {
2287  assert(readReadyQueue.front() >= curTick());
2288  assert(!readReadyEvent.scheduled());
2289  schedule(readReadyEvent, next_ready_at);
2290  }
2291 
2292  // It is possible that a new command kicks things back into
2293  // action before reaching this point but need to ensure that we
2294  // continue to process new commands as read data becomes ready
2295  // This will also trigger a drain if needed
2296  if (!ctrl->requestEventScheduled()) {
2297  DPRINTF(NVM, "Restart controller scheduler immediately\n");
2299  }
2300 }
2301 
2302 bool
2304  bool read_rdy = pkt->isRead() && (ctrl->inReadBusState(true)) &&
2305  (pkt->readyTime <= curTick()) && (numReadDataReady > 0);
2306  bool write_rdy = !pkt->isRead() && !ctrl->inReadBusState(true) &&
2307  !writeRespQueueFull();
2308  return (read_rdy || write_rdy);
2309 }
2310 
2313 {
2314  DPRINTF(NVM, "NVM Timing access to addr %#x, rank/bank/row %d %d %d\n",
2315  pkt->addr, pkt->rank, pkt->bank, pkt->row);
2316 
2317  // get the bank
2318  Bank& bank_ref = ranks[pkt->rank]->banks[pkt->bank];
2319 
2320  // respect any constraints on the command
2321  const Tick bst_allowed_at = pkt->isRead() ?
2322  bank_ref.rdAllowedAt : bank_ref.wrAllowedAt;
2323 
2324  // we need to wait until the bus is available before we can issue
2325  // the command; need minimum of tBURST between commands
2326  Tick cmd_at = std::max(bst_allowed_at, curTick());
2327 
2328  // we need to wait until the bus is available before we can issue
2329  // the command; need minimum of tBURST between commands
2330  cmd_at = std::max(cmd_at, next_burst_at);
2331 
2332  // Verify there is command bandwidth to issue
2333  // Read burst (send command) is a simple data access and only requires
2334  // one command cycle
2335  // Write command may require multiple cycles to enable larger address space
2336  if (pkt->isRead() || !twoCycleRdWr) {
2337  cmd_at = ctrl->verifySingleCmd(cmd_at, maxCommandsPerWindow);
2338  } else {
2339  cmd_at = ctrl->verifyMultiCmd(cmd_at, maxCommandsPerWindow, tCK);
2340  }
2341  // update the packet ready time to reflect when data will be transferred
2342  // Use the same bus delays defined for NVM
2343  pkt->readyTime = cmd_at + tSEND + tBURST;
2344 
2345  Tick dly_to_rd_cmd;
2346  Tick dly_to_wr_cmd;
2347  for (auto n : ranks) {
2348  for (int i = 0; i < banksPerRank; i++) {
2349  // base delay is a function of tBURST and bus turnaround
2350  dly_to_rd_cmd = pkt->isRead() ? tBURST : writeToReadDelay();
2351  dly_to_wr_cmd = pkt->isRead() ? readToWriteDelay() : tBURST;
2352 
2353  if (pkt->rank != n->rank) {
2354  // adjust timing for different ranks
2355  // Need to account for rank-to-rank switching with tCS
2356  dly_to_wr_cmd = rankToRankDelay();
2357  dly_to_rd_cmd = rankToRankDelay();
2358  }
2359  n->banks[i].rdAllowedAt = std::max(cmd_at + dly_to_rd_cmd,
2360  n->banks[i].rdAllowedAt);
2361 
2362  n->banks[i].wrAllowedAt = std::max(cmd_at + dly_to_wr_cmd,
2363  n->banks[i].wrAllowedAt);
2364  }
2365  }
2366 
2367  DPRINTF(NVM, "NVM Access to %#x, ready at %lld.\n",
2368  pkt->addr, pkt->readyTime);
2369 
2370  if (pkt->isRead()) {
2371  // completed the read, decrement counters
2372  assert(numPendingReads != 0);
2373  assert(numReadDataReady != 0);
2374 
2375  numPendingReads--;
2376  numReadDataReady--;
2377  } else {
2378  // Adjust number of NVM writes in Q
2379  assert(numWritesQueued > 0);
2380  numWritesQueued--;
2381 
2382  // increment the bytes accessed and the accesses per row
2383  // only increment for writes as the reads are handled when
2384  // the non-deterministic read is issued, before the data transfer
2385  bank_ref.bytesAccessed += burstSize;
2386 
2387  // Commands will be issued serially when accessing the same bank
2388  // Commands can issue in parallel to different banks
2389  if ((bank_ref.bank == pkt->bank) &&
2390  (bank_ref.openRow != pkt->row)) {
2391  // update the open buffer, re-using row field
2392  bank_ref.openRow = pkt->row;
2393 
2394  // sample the bytes accessed to a buffer in this bank
2395  // here when we are re-buffering the data
2397  // start counting anew
2398  bank_ref.bytesAccessed = 0;
2399  }
2400 
2401  // Determine when write will actually complete, assuming it is
2402  // scheduled to push to NVM immediately
2403  // update actAllowedAt to serialize next command completion that
2404  // accesses this bank; must wait until this write completes
2405  // Data accesses to the same buffer in this bank
2406  // can issue immediately after actAllowedAt expires, without
2407  // waiting additional delay of tWRITE. Can revisit this
2408  // assumption/simplification in the future.
2409  bank_ref.actAllowedAt = std::max(pkt->readyTime,
2410  bank_ref.actAllowedAt) + tWRITE;
2411 
2412  // Need to track number of outstanding writes to
2413  // ensure 'buffer' on media controller does not overflow
2414  assert(!writeRespQueueFull());
2415 
2416  // Insert into write done queue. It will be handled after
2417  // the media delay has been met
2418  if (writeRespQueueEmpty()) {
2419  assert(!writeRespondEvent.scheduled());
2421  } else {
2422  assert(writeRespondEvent.scheduled());
2423  }
2424  writeRespQueue.push_back(bank_ref.actAllowedAt);
2425  writeRespQueue.sort();
2426  if (writeRespondEvent.when() > bank_ref.actAllowedAt) {
2427  DPRINTF(NVM, "Rescheduled respond event from %lld to %11d\n",
2428  writeRespondEvent.when(), bank_ref.actAllowedAt);
2429  DPRINTF(NVM, "Front of response queue is %11d\n",
2430  writeRespQueue.front());
2432  }
2433 
2434  }
2435 
2436  // Update the stats
2437  if (pkt->isRead()) {
2438  stats.readBursts++;
2440  stats.perBankRdBursts[pkt->bankId]++;
2442 
2443  // Update latency stats
2444  stats.totMemAccLat += pkt->readyTime - pkt->entryTime;
2445  stats.totBusLat += tBURST;
2446  stats.totQLat += cmd_at - pkt->entryTime;
2447  } else {
2448  stats.writeBursts++;
2450  stats.perBankWrBursts[pkt->bankId]++;
2451  }
2452 
2453  return std::make_pair(cmd_at, cmd_at + tBURST);
2454 }
2455 
2456 void
2458 {
2459  DPRINTF(NVM,
2460  "processWriteRespondEvent(): A NVM write reached its readyTime. "
2461  "%d remaining pending NVM writes\n", writeRespQueue.size());
2462 
2463  // Update stat to track histogram of pending writes
2465 
2466  // Done with this response, pop entry
2467  writeRespQueue.pop_front();
2468 
2469  if (!writeRespQueue.empty()) {
2470  assert(writeRespQueue.front() >= curTick());
2471  assert(!writeRespondEvent.scheduled());
2473  }
2474 
2475  // It is possible that a new command kicks things back into
2476  // action before reaching this point but need to ensure that we
2477  // continue to process new commands as writes complete at the media and
2478  // credits become available. This will also trigger a drain if needed
2479  if (!ctrl->requestEventScheduled()) {
2480  DPRINTF(NVM, "Restart controller scheduler immediately\n");
2482  }
2483 }
2484 
2485 void
2487 {
2488  // update timing for NVM ranks due to bursts issued
2489  // to ranks for other media interfaces
2490  for (auto n : ranks) {
2491  for (int i = 0; i < banksPerRank; i++) {
2492  // different rank by default
2493  // Need to only account for rank-to-rank switching
2494  n->banks[i].rdAllowedAt = std::max(cmd_at + rankToRankDelay(),
2495  n->banks[i].rdAllowedAt);
2496  n->banks[i].wrAllowedAt = std::max(cmd_at + rankToRankDelay(),
2497  n->banks[i].wrAllowedAt);
2498  }
2499  }
2500 }
2501 
2502 bool
2503 NVMInterface::isBusy(bool read_queue_empty, bool all_writes_nvm)
2504 {
2505  DPRINTF(NVM,"isBusy: numReadDataReady = %d\n", numReadDataReady);
2506  // Determine NVM is busy and cannot issue a burst
2507  // A read burst cannot issue when data is not ready from the NVM
2508  // Also check that we have reads queued to ensure we can change
2509  // bus direction to service potential write commands.
2510  // A write cannot issue once we've reached MAX pending writes
2511  // Only assert busy for the write case when there are also
2512  // no reads in Q and the write queue only contains NVM commands
2513  // This allows the bus state to switch and service reads
2514  return (ctrl->inReadBusState(true) ?
2515  (numReadDataReady == 0) && !read_queue_empty :
2516  writeRespQueueFull() && read_queue_empty &&
2517  all_writes_nvm);
2518 }
2519 
2520 
2522  : statistics::Group(&_nvm),
2523  nvm(_nvm),
2524 
2525  ADD_STAT(readBursts, statistics::units::Count::get(),
2526  "Number of NVM read bursts"),
2527  ADD_STAT(writeBursts, statistics::units::Count::get(),
2528  "Number of NVM write bursts"),
2529 
2530  ADD_STAT(perBankRdBursts, statistics::units::Count::get(),
2531  "Per bank write bursts"),
2532  ADD_STAT(perBankWrBursts, statistics::units::Count::get(),
2533  "Per bank write bursts"),
2534 
2535  ADD_STAT(totQLat, statistics::units::Tick::get(), "Total ticks spent queuing"),
2536  ADD_STAT(totBusLat, statistics::units::Tick::get(),
2537  "Total ticks spent in databus transfers"),
2538  ADD_STAT(totMemAccLat, statistics::units::Tick::get(),
2539  "Total ticks spent from burst creation until serviced "
2540  "by the NVM"),
2541  ADD_STAT(avgQLat, statistics::units::Rate<
2542  statistics::units::Tick, statistics::units::Count>::get(),
2543  "Average queueing delay per NVM burst"),
2544  ADD_STAT(avgBusLat, statistics::units::Rate<
2545  statistics::units::Tick, statistics::units::Count>::get(),
2546  "Average bus latency per NVM burst"),
2547  ADD_STAT(avgMemAccLat, statistics::units::Rate<
2548  statistics::units::Tick, statistics::units::Count>::get(),
2549  "Average memory access latency per NVM burst"),
2550 
2551  ADD_STAT(bytesRead, statistics::units::Byte::get(),
2552  "Total number of bytes read from NVM"),
2553  ADD_STAT(bytesWritten, statistics::units::Byte::get(),
2554  "Total number of bytes written to NVM"),
2555  ADD_STAT(avgRdBW, statistics::units::Rate<
2556  statistics::units::Byte, statistics::units::Second>::get(),
2557  "Average DRAM read bandwidth in MiBytes/s"),
2558  ADD_STAT(avgWrBW, statistics::units::Rate<
2559  statistics::units::Byte, statistics::units::Second>::get(),
2560  "Average DRAM write bandwidth in MiBytes/s"),
2561  ADD_STAT(peakBW, statistics::units::Rate<
2562  statistics::units::Byte, statistics::units::Second>::get(),
2563  "Theoretical peak bandwidth in MiByte/s"),
2564  ADD_STAT(busUtil, statistics::units::Ratio::get(),
2565  "NVM Data bus utilization in percentage"),
2566  ADD_STAT(busUtilRead, statistics::units::Ratio::get(),
2567  "NVM Data bus read utilization in percentage"),
2568  ADD_STAT(busUtilWrite, statistics::units::Ratio::get(),
2569  "NVM Data bus write utilization in percentage"),
2570 
2571  ADD_STAT(pendingReads, statistics::units::Count::get(),
2572  "Reads issued to NVM for which data has not been transferred"),
2573  ADD_STAT(pendingWrites, statistics::units::Count::get(),
2574  "Number of outstanding writes to NVM"),
2575  ADD_STAT(bytesPerBank, statistics::units::Byte::get(),
2576  "Bytes read within a bank before loading new bank")
2577 
2578 {
2579 }
2580 
2581 void
2583 {
2584  using namespace statistics;
2585 
2586  perBankRdBursts.init(nvm.ranksPerChannel == 0 ? 1 :
2587  nvm.banksPerRank * nvm.ranksPerChannel);
2588 
2589  perBankWrBursts.init(nvm.ranksPerChannel == 0 ? 1 :
2590  nvm.banksPerRank * nvm.ranksPerChannel);
2591 
2592  avgQLat.precision(2);
2593  avgBusLat.precision(2);
2594  avgMemAccLat.precision(2);
2595 
2596  avgRdBW.precision(2);
2597  avgWrBW.precision(2);
2598  peakBW.precision(2);
2599 
2600  busUtil.precision(2);
2601  busUtilRead.precision(2);
2602  busUtilWrite.precision(2);
2603 
2604  pendingReads
2605  .init(nvm.maxPendingReads)
2606  .flags(nozero);
2607 
2608  pendingWrites
2609  .init(nvm.maxPendingWrites)
2610  .flags(nozero);
2611 
2612  bytesPerBank
2613  .init(nvm.rowBufferSize)
2614  .flags(nozero);
2615 
2616  avgQLat = totQLat / readBursts;
2617  avgBusLat = totBusLat / readBursts;
2618  avgMemAccLat = totMemAccLat / readBursts;
2619 
2620  avgRdBW = (bytesRead / 1000000) / simSeconds;
2621  avgWrBW = (bytesWritten / 1000000) / simSeconds;
2622  peakBW = (sim_clock::Frequency / nvm.tBURST) *
2623  nvm.burstSize / 1000000;
2624 
2625  busUtil = (avgRdBW + avgWrBW) / peakBW * 100;
2626  busUtilRead = avgRdBW / peakBW * 100;
2627  busUtilWrite = avgWrBW / peakBW * 100;
2628 }
2629 
2630 } // namespace memory
2631 } // namespace gem5
gem5::memory::DRAMInterface::Rank::suspend
void suspend()
Stop the refresh events.
Definition: mem_interface.cc:1178
gem5::memory::DRAMInterface::tRRD_L
const Tick tRRD_L
Definition: mem_interface.hh:746
gem5::curTick
Tick curTick()
The universal simulation clock.
Definition: cur_tick.hh:46
fatal
#define fatal(...)
This implements a cprintf based fatal() function.
Definition: logging.hh:189
gem5::memory::DRAMInterface::enableDRAMPowerdown
bool enableDRAMPowerdown
Enable or disable DRAM powerdown states.
Definition: mem_interface.hh:775
gem5::memory::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:2107
gem5::memory::MemInterface::rowsPerBank
uint32_t rowsPerBank
Definition: mem_interface.hh:145
gem5::MipsISA::fill
fill
Definition: pra_constants.hh:57
gem5::memory::NVMInterface
Interface to NVM devices with media specific parameters, statistics, and functions.
Definition: mem_interface.hh:1028
gem5::memory::DRAMInterface::DRAMStats::perBankRdBursts
statistics::Vector perBankRdBursts
DRAM per bank stats.
Definition: mem_interface.hh:823
gem5::memory::MemInterface::Bank::bank
uint8_t bank
Definition: mem_interface.hh:96
gem5::memory::DRAMInterface::burstReady
bool burstReady(MemPacket *pkt) const override
Check if a burst operation can be issued to the DRAM.
Definition: mem_interface.hh:978
gem5::memory::DRAMInterface::tWR
const Tick tWR
Definition: mem_interface.hh:741
gem5::Event::when
Tick when() const
Get the time that the event is scheduled.
Definition: eventq.hh:508
gem5::memory::DRAMInterface::Rank::computeStats
void computeStats()
Computes stats just prior to dump event.
Definition: mem_interface.cc:1820
gem5::memory::NVMInterface::maxPendingReads
const uint32_t maxPendingReads
Definition: mem_interface.hh:1057
gem5::memory::DRAMInterface::Rank::processPrechargeEvent
void processPrechargeEvent()
Definition: mem_interface.cc:1254
gem5::AddrRange::granularity
uint64_t granularity() const
Determing the interleaving granularity of the range.
Definition: addr_range.hh:269
gem5::memory::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:946
gem5::memory::DRAMInterface::Rank::writeEntries
uint32_t writeEntries
Track number of packets in write queue going to this rank.
Definition: mem_interface.hh:546
warn
#define warn(...)
Definition: logging.hh:245
gem5::memory::DRAMInterface::PowerState
PowerState
The power state captures the different operational states of the DRAM and interacts with the bus read...
Definition: mem_interface.hh:354
gem5::memory::DRAMInterface::Rank::processPowerEvent
void processPowerEvent()
Definition: mem_interface.cc:1644
gem5::memory::MemInterface::readToWriteDelay
Tick readToWriteDelay() const
Definition: mem_interface.hh:164
system.hh
gem5::memory::DRAMInterface::DRAMStats::writeRowHits
statistics::Scalar writeRowHits
Definition: mem_interface.hh:838
gem5::memory::DRAMInterface::DRAMStats::writeBursts
statistics::Scalar writeBursts
Definition: mem_interface.hh:820
gem5::memory::NVMInterface::numWritesQueued
uint32_t numWritesQueued
Definition: mem_interface.hh:1155
gem5::memory::MemPacket::readyTime
Tick readyTime
When will request leave the controller.
Definition: mem_ctrl.hh:105
gem5::memory::DRAMInterface::activeRank
uint8_t activeRank
Definition: mem_interface.hh:772
gem5::memory::MemInterface::tBURST
const Tick tBURST
Definition: mem_interface.hh:152
gem5::memory::DRAMInterface::PWR_PRE_PDN
@ PWR_PRE_PDN
Definition: mem_interface.hh:359
gem5::memory::DRAMInterface::DRAMStats::totQLat
statistics::Scalar totQLat
Definition: mem_interface.hh:827
memory
Definition: mem.h:38
gem5::memory::DRAMInterface::Rank::writeDoneEvent
EventFunctionWrapper writeDoneEvent
Definition: mem_interface.hh:690
gem5::memory::NVMInterface::isBusy
bool isBusy(bool read_queue_empty, bool all_writes_nvm)
This function checks if ranks are busy.
Definition: mem_interface.cc:2503
gem5::memory::NVMInterface::NVMInterface
NVMInterface(const NVMInterfaceParams &_p)
Definition: mem_interface.cc:2039
gem5::memory::DRAMInterface::DRAMStats::readBursts
statistics::Scalar readBursts
total number of DRAM bursts serviced
Definition: mem_interface.hh:819
gem5::memory::NVMInterface::readReadyEvent
EventFunctionWrapper readReadyEvent
Definition: mem_interface.hh:1114
gem5::memory::DRAMInterface::tREFI
const Tick tREFI
Definition: mem_interface.hh:744
gem5::memory::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:723
gem5::memory::DRAMInterface::Rank::processWakeUpEvent
void processWakeUpEvent()
Definition: mem_interface.cc:1626
gem5::memory::DRAMInterface::DRAMStats::totBusLat
statistics::Scalar totBusLat
Definition: mem_interface.hh:828
gem5::memory::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:684
gem5::memory::DRAMInterface::Rank::prechargeEvent
EventFunctionWrapper prechargeEvent
Definition: mem_interface.hh:696
gem5::memory::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:82
gem5::memory::DRAMInterface::Rank::inLowPowerState
bool inLowPowerState
rank is in or transitioning to power-down or self-refresh
Definition: mem_interface.hh:531
gem5::memory::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
gem5::replaceBits
constexpr void replaceBits(T &val, unsigned first, unsigned last, B bit_val)
A convenience function to replace bits first to last of val with bit_val in place.
Definition: bitfield.hh:197
gem5::memory::NVMInterface::Rank::banks
std::vector< Bank > banks
Vector of NVM banks.
Definition: mem_interface.hh:1047
gem5::statistics::nozero
const FlagsType nozero
Don't print if this is zero.
Definition: info.hh:68
gem5::memory::DRAMInterface::Command
Simple structure to hold the values needed to keep track of commands for DRAMPower.
Definition: mem_interface.hh:315
gem5::memory::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:704
gem5::memory::DRAMInterface::PWR_REF
@ PWR_REF
Definition: mem_interface.hh:357
gem5::SimObject::init
virtual void init()
init() is called after all C++ SimObjects have been created and all ports are connected.
Definition: sim_object.cc:76
gem5::memory::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:175
gem5::memory::DRAMInterface::ranks
std::vector< Rank * > ranks
Vector of dram ranks.
Definition: mem_interface.hh:862
gem5::memory::NVMInterface::Rank::Rank
Rank(const NVMInterfaceParams &_p, int _rank, NVMInterface &_nvm)
Definition: mem_interface.cc:2078
gem5::memory::MemInterface::deviceSize
const uint32_t deviceSize
Definition: mem_interface.hh:137
gem5::memory::MemInterface::Bank
A basic class to track the bank state, i.e.
Definition: mem_interface.hh:89
gem5::memory::DRAMInterface::tXP
const Tick tXP
Definition: mem_interface.hh:750
gem5::memory::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:290
gem5::memory::MemCtrl
The memory controller is a single-channel memory controller capturing the most important timing const...
Definition: mem_ctrl.hh:242
gem5::memory::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:2486
gem5::memory::DRAMInterface::REF_DRAIN
@ REF_DRAIN
Definition: mem_interface.hh:397
gem5::memory::MemInterface::burstsPerStripe
const uint32_t burstsPerStripe
Definition: mem_interface.hh:142
gem5::sim_clock::Frequency
Tick Frequency
The simulated frequency of curTick(). (In ticks per second)
Definition: core.cc:48
gem5::memory::DRAMInterface::tRCD
const Tick tRCD
Definition: mem_interface.hh:738
gem5::memory::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:1020
gem5::memory::DRAMInterface::Rank::processWriteDoneEvent
void processWriteDoneEvent()
Definition: mem_interface.cc:1285
gem5::MaxTick
const Tick MaxTick
Definition: types.hh:60
gem5::memory::DRAMInterface::bankGroupArch
const bool bankGroupArch
Definition: mem_interface.hh:728
gem5::DRAMPower
DRAMPower is a standalone tool which calculates the power consumed by a DRAM in the system.
Definition: drampower.hh:56
gem5::memory::MemInterface::Bank::wrAllowedAt
Tick wrAllowedAt
Definition: mem_interface.hh:100
gem5::memory::DRAMInterface::Rank::resetStats
void resetStats()
Reset stats on a stats event.
Definition: mem_interface.cc:1833
gem5::memory::DRAMInterface::maxAccessesPerRow
const uint32_t maxAccessesPerRow
Max column accesses (read and write) per row, before forefully closing it.
Definition: mem_interface.hh:766
gem5::memory::NVMInterface::processWriteRespondEvent
void processWriteRespondEvent()
Definition: mem_interface.cc:2457
gem5::memory::NVMInterface::setupRank
void setupRank(const uint8_t rank, const bool is_read) override
Setup the rank based on packet received.
Definition: mem_interface.cc:2095
gem5::memory::NVMInterface::numReadsToIssue
uint16_t numReadsToIssue
Definition: mem_interface.hh:1152
gem5::memory::NVMInterface::NVMStats::pendingReads
statistics::Histogram pendingReads
NVM stats.
Definition: mem_interface.hh:1104
gem5::memory::DRAMInterface::PWR_ACT
@ PWR_ACT
Definition: mem_interface.hh:360
gem5::memory::DRAMInterface::Rank::refreshEvent
EventFunctionWrapper refreshEvent
Definition: mem_interface.hh:699
gem5::EventManager::schedule
void schedule(Event &event, Tick when)
Definition: eventq.hh:1019
gem5::memory::DRAMInterface::DRAMStats::bytesPerActivate
statistics::Histogram bytesPerActivate
Definition: mem_interface.hh:841
gem5::memory::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:553
std::vector< uint32_t >
gem5::memory::DRAMInterface::Rank::activateEvent
EventFunctionWrapper activateEvent
Definition: mem_interface.hh:693
gem5::memory::NVMInterface::tREAD
const Tick tREAD
NVM specific timing requirements.
Definition: mem_interface.hh:1063
gem5::memory::DRAMInterface::PWR_IDLE
@ PWR_IDLE
Definition: mem_interface.hh:356
gem5::csprintf
std::string csprintf(const char *format, const Args &...args)
Definition: cprintf.hh:161
gem5::memory::DRAMInterface::Rank::Rank
Rank(const DRAMInterfaceParams &_p, int _rank, DRAMInterface &_dram)
Definition: mem_interface.cc:1127
gem5::memory::DRAMInterface::tRTP
const Tick tRTP
Definition: mem_interface.hh:742
gem5::memory::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
gem5::memory::DRAMInterface::rdToWrDlySameBG
const Tick rdToWrDlySameBG
Definition: mem_interface.hh:758
gem5::memory::NVMInterface::writeRespQueueFull
bool writeRespQueueFull() const
Check if the write response queue has reached defined threshold.
Definition: mem_interface.hh:1243
gem5::memory::MemInterface::Bank::rowAccesses
uint32_t rowAccesses
Definition: mem_interface.hh:104
gem5::memory::DRAMInterface::Rank::powerDownSleep
void powerDownSleep(PowerState pwr_state, Tick tick)
Schedule a transition to power-down (sleep)
Definition: mem_interface.cc:1523
gem5::ArmISA::i
Bitfield< 7 > i
Definition: misc_types.hh:66
gem5::statistics::Group::resetStats
virtual void resetStats()
Callback to reset stats.
Definition: group.cc:86
gem5::memory::NVMInterface::twoCycleRdWr
const bool twoCycleRdWr
Definition: mem_interface.hh:1058
gem5::isPowerOf2
static constexpr bool isPowerOf2(const T &n)
Definition: intmath.hh:98
gem5::memory::DRAMInterface::drainRanks
void drainRanks()
Iterate through dram ranks to exit self-refresh in order to drain.
Definition: mem_interface.cc:1006
gem5::memory::DRAMInterface::Rank::readEntries
uint32_t readEntries
Track number of packets in read queue going to this rank.
Definition: mem_interface.hh:541
gem5::memory::MemInterface::Bank::preAllowedAt
Tick preAllowedAt
Definition: mem_interface.hh:101
gem5::memory::DRAMInterface::RankStats::regStats
void regStats() override
Callback to set stat parameters.
Definition: mem_interface.cc:2009
gem5::statistics::DistBase::sample
void sample(const U &v, int n=1)
Add a value to the distribtion n times.
Definition: statistics.hh:1325
gem5::memory::MemInterface::burstsPerRowBuffer
const uint32_t burstsPerRowBuffer
Definition: mem_interface.hh:141
gem5::memory::NVMInterface::tWRITE
const Tick tWRITE
Definition: mem_interface.hh:1064
gem5::memory::DRAMInterface::Rank::processRefreshEvent
void processRefreshEvent()
Definition: mem_interface.cc:1296
gem5::memory::DRAMInterface::bankGroupsPerRank
const uint32_t bankGroupsPerRank
DRAM specific device characteristics.
Definition: mem_interface.hh:727
gem5::memory::DRAMInterface::setupRank
void setupRank(const uint8_t rank, const bool is_read) override
Setup the rank based on packet received.
Definition: mem_interface.cc:935
gem5::memory::DRAMInterface::suspend
void suspend()
Iterate through DRAM ranks and suspend them.
Definition: mem_interface.cc:1035
gem5::memory::NVMInterface::readReadyQueue
std::deque< Tick > readReadyQueue
Definition: mem_interface.hh:1131
gem5::memory::MemCtrl::inReadBusState
bool inReadBusState(bool next_state) const
Check the current direction of the memory channel.
Definition: mem_ctrl.cc:791
gem5::memory::DRAMInterface::PWR_SREF
@ PWR_SREF
Definition: mem_interface.hh:358
gem5::memory::DRAMInterface::Rank::processActivateEvent
void processActivateEvent()
Definition: mem_interface.cc:1244
gem5::memory::NVMInterface::NVMStats::totBusLat
statistics::Scalar totBusLat
Definition: mem_interface.hh:1084
gem5::memory::DRAMInterface
Interface to DRAM devices with media specific parameters, statistics, and functions.
Definition: mem_interface.hh:308
gem5::memory::DRAMInterface::Command::type
Data::MemCommand::cmds type
Definition: mem_interface.hh:317
gem5::memory::MemPacket::entryTime
const Tick entryTime
When did request enter the controller.
Definition: mem_ctrl.hh:102
gem5::memory::DRAMInterface::REF_PRE
@ REF_PRE
Definition: mem_interface.hh:400
gem5::memory::MemInterface::addrMapping
enums::AddrMap addrMapping
Memory controller configuration initialized based on parameter values.
Definition: mem_interface.hh:129
gem5::memory::DRAMInterface::Rank::rank
uint8_t rank
Current Rank index.
Definition: mem_interface.hh:536
gem5::EventManager
Definition: eventq.hh:987
gem5::memory::NVMInterface::NVMStats::totMemAccLat
statistics::Scalar totMemAccLat
Definition: mem_interface.hh:1085
gem5::ArmISA::j
Bitfield< 24 > j
Definition: misc_types.hh:57
gem5::memory::MemInterface::Bank::bytesAccessed
uint32_t bytesAccessed
Definition: mem_interface.hh:105
gem5::memory::DRAMInterface::REF_RUN
@ REF_RUN
Definition: mem_interface.hh:402
gem5::memory::DRAMInterface::stats
DRAMStats stats
Definition: mem_interface.hh:857
mem_interface.hh
gem5::memory::DRAMInterface::tPPD
const Tick tPPD
Definition: mem_interface.hh:747
gem5::memory::DRAMInterface::DRAMInterface
DRAMInterface(const DRAMInterfaceParams &_p)
Definition: mem_interface.cc:739
gem5::memory::MemPacket::addr
Addr addr
The starting address of the packet.
Definition: mem_ctrl.hh:136
gem5::memory::MemInterface::Bank::rdAllowedAt
Tick rdAllowedAt
Definition: mem_interface.hh:99
gem5::memory::DRAMInterface::isBusy
bool isBusy()
This function checks if ranks are actively refreshing and therefore busy.
Definition: mem_interface.cc:898
gem5::ArmISA::b
Bitfield< 7 > b
Definition: misc_types.hh:381
gem5::memory::DRAMInterface::DRAMStats::regStats
void regStats() override
Callback to set stat parameters.
Definition: mem_interface.cc:1924
gem5::memory::DRAMInterface::DRAMStats::DRAMStats
DRAMStats(DRAMInterface &dram)
Definition: mem_interface.cc:1854
gem5::memory::MemInterface
General interface to memory device Includes functions and parameters shared across media types.
Definition: mem_interface.hh:77
bitfield.hh
gem5::memory::NVMInterface::NVMStats::bytesRead
statistics::Scalar bytesRead
Definition: mem_interface.hh:1092
gem5::memory::NVMInterface::numPendingReads
uint16_t numPendingReads
Definition: mem_interface.hh:1147
gem5::Named::name
virtual std::string name() const
Definition: named.hh:47
gem5::memory::MemInterface::banksPerRank
const uint32_t banksPerRank
Definition: mem_interface.hh:144
gem5::AddrRange::interleaved
bool interleaved() const
Determine if the range is interleaved or not.
Definition: addr_range.hh:260
gem5::memory::MemInterface::Bank::bankgr
uint8_t bankgr
Definition: mem_interface.hh:97
gem5::memory::MemPacket::row
const uint32_t row
Definition: mem_ctrl.hh:121
gem5::memory::DRAMInterface::Rank::banks
std::vector< Bank > banks
Vector of Banks.
Definition: mem_interface.hh:577
gem5::memory::DRAMInterface::tCL
const Tick tCL
DRAM specific timing requirements.
Definition: mem_interface.hh:733
DPRINTF
#define DPRINTF(x,...)
Definition: trace.hh:186
ADD_STAT
#define ADD_STAT(n,...)
Convenience macro to add a stat to a statistics group.
Definition: group.hh:75
gem5::memory::DRAMInterface::tRP
const Tick tRP
Definition: mem_interface.hh:739
gem5::Packet
A Packet is used to encapsulate a transfer between two objects in the memory system (e....
Definition: packet.hh:283
gem5::memory::DRAMInterface::PWR_ACT_PDN
@ PWR_ACT_PDN
Definition: mem_interface.hh:361
gem5::memory::NVMInterface::writeRespondEvent
EventFunctionWrapper writeRespondEvent
Definition: mem_interface.hh:1111
gem5::memory::DRAMInterface::Rank::refreshState
RefreshState refreshState
current refresh state
Definition: mem_interface.hh:526
gem5::memory::DRAMInterface::tXAW
const Tick tXAW
Definition: mem_interface.hh:749
gem5::memory::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:1043
gem5::memory::DRAMInterface::activationLimit
const uint32_t activationLimit
Definition: mem_interface.hh:756
gem5::MipsISA::p
Bitfield< 0 > p
Definition: pra_constants.hh:326
gem5::memory::AbstractMemory
An abstract memory represents a contiguous block of physical memory, with an associated address range...
Definition: abstract_mem.hh:110
gem5::Tick
uint64_t Tick
Tick count type.
Definition: types.hh:58
gem5::memory::MemPacket::isDram
bool isDram() const
Return true if its a DRAM access.
Definition: mem_ctrl.hh:200
gem5::memory::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
gem5::memory::MemPacket
A memory packet stores packets along with the timestamp of when the packet entered the queue,...
Definition: mem_ctrl.hh:97
gem5::memory::NVMInterface::tSEND
const Tick tSEND
Definition: mem_interface.hh:1065
gem5::memory::DRAMInterface::Rank::actTicks
std::deque< Tick > actTicks
List to keep track of activate ticks.
Definition: mem_interface.hh:586
gem5::memory::NVMInterface::NVMStats::totQLat
statistics::Scalar totQLat
Definition: mem_interface.hh:1083
gem5::memory::DRAMInterface::tRRD
const Tick tRRD
Definition: mem_interface.hh:745
gem5::memory::DRAMInterface::Rank::isQueueEmpty
bool isQueueEmpty() const
Check if the command queue of current rank is idle.
Definition: mem_interface.cc:1190
gem5::memory::DRAMInterface::DRAMStats::readRowHits
statistics::Scalar readRowHits
Definition: mem_interface.hh:837
gem5::memory::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:993
gem5::memory::NVMInterface::NVMStats::NVMStats
NVMStats(NVMInterface &nvm)
Definition: mem_interface.cc:2521
gem5::memory::NVMInterface::processReadReadyEvent
void processReadReadyEvent()
Definition: mem_interface.cc:2258
gem5::EventManager::reschedule
void reschedule(Event &event, Tick when, bool always=false)
Definition: eventq.hh:1037
gem5::memory::DRAMInterface::tXS
const Tick tXS
Definition: mem_interface.hh:751
gem5::memory::MemInterface::devicesPerRank
const uint32_t devicesPerRank
Definition: mem_interface.hh:139
cprintf.hh
gem5::bits
constexpr T bits(T val, unsigned first, unsigned last)
Extract the bitfield from position 'first' to 'last' (inclusive) from 'val' and right justify it.
Definition: bitfield.hh:76
gem5::DrainState::Drained
@ Drained
Buffers drained, ready for serialization/handover.
gem5::memory::DRAMInterface::writeToReadDelay
Tick writeToReadDelay() const override
Definition: mem_interface.hh:867
gem5::memory::DRAMInterface::REF_IDLE
@ REF_IDLE
Definition: mem_interface.hh:396
gem5::memory::DRAMInterface::tAAD
const Tick tAAD
Definition: mem_interface.hh:748
std::pair
STL pair class.
Definition: stl.hh:58
gem5::memory::MemInterface::ctrl
MemCtrl * ctrl
A pointer to the parent MemCtrl instance.
Definition: mem_interface.hh:117
gem5::memory::AbstractMemory::range
AddrRange range
Definition: abstract_mem.hh:115
gem5::Addr
uint64_t Addr
Address type This will probably be moved somewhere else in the near future.
Definition: types.hh:147
gem5::memory::DRAMInterface::Rank::updatePowerStats
void updatePowerStats()
Function to update Power Stats.
Definition: mem_interface.cc:1777
RD
#define RD
Definition: bitfields.hh:14
name
const std::string & name()
Definition: trace.cc:49
gem5::memory::DRAMInterface::tCCD_L
const Tick tCCD_L
Definition: mem_interface.hh:737
gem5::memory::MemInterface::rankToRankDelay
Tick rankToRankDelay() const
Definition: mem_interface.hh:169
gem5::memory::MemInterface::writeToReadDelay
virtual Tick writeToReadDelay() const
Definition: mem_interface.hh:159
gem5::statistics::Group::regStats
virtual void regStats()
Callback to set stat parameters.
Definition: group.cc:69
gem5::memory::DRAMInterface::wrToRdDlySameBG
const Tick wrToRdDlySameBG
Definition: mem_interface.hh:757
gem5::memory::NVMInterface::init
void init() override
Initialize the NVM interface and verify parameters.
Definition: mem_interface.cc:2090
gem5::memory::NVMInterface::NVMStats::writeBursts
statistics::Scalar writeBursts
Definition: mem_interface.hh:1077
gem5::memory::NVMInterface::burstReady
bool burstReady(MemPacket *pkt) const override
Check if a burst operation can be issued to the NVM.
Definition: mem_interface.cc:2303
gem5::memory::DRAMInterface::DRAMStats::totMemAccLat
statistics::Scalar totMemAccLat
Definition: mem_interface.hh:829
gem5::EventManager::deschedule
void deschedule(Event &event)
Definition: eventq.hh:1028
gem5::memory::NVMInterface::chooseRead
void chooseRead(MemPacketQueue &queue)
Select read command to issue asynchronously.
Definition: mem_interface.cc:2163
gem5::memory::DRAMInterface::Rank::lastBurstTick
Tick lastBurstTick
Track when we issued the last read/write burst.
Definition: mem_interface.hh:591
gem5::divCeil
static constexpr T divCeil(const T &a, const U &b)
Definition: intmath.hh:110
gem5::memory::MemInterface::Bank::openRow
uint32_t openRow
Definition: mem_interface.hh:95
gem5::memory::MemCtrl::requestEventScheduled
bool requestEventScheduled() const
Is there a read/write burst Event scheduled?
Definition: mem_ctrl.hh:675
gem5::memory::AbstractMemory::size
uint64_t size() const
Get the memory size.
Definition: abstract_mem.hh:301
gem5::memory::DRAMInterface::twoCycleActivate
const uint8_t twoCycleActivate
Definition: mem_interface.hh:755
gem5::memory::NVMInterface::NVMStats::bytesPerBank
statistics::Histogram bytesPerBank
Definition: mem_interface.hh:1106
gem5::memory::DRAMInterface::REF_START
@ REF_START
Definition: mem_interface.hh:401
gem5::memory::MemInterface::ranksPerChannel
const uint32_t ranksPerChannel
Definition: mem_interface.hh:143
gem5::memory::MemPacket::bank
const uint8_t bank
Definition: mem_ctrl.hh:120
gem5::memory::DRAMInterface::Rank::inRefIdleState
bool inRefIdleState() const
Check if there is no refresh and no preparation of refresh ongoing i.e.
Definition: mem_interface.hh:617
gem5::memory::NVMInterface::doBurstAccess
std::pair< Tick, Tick > doBurstAccess(MemPacket *pkt, Tick next_burst_at)
Actually do the burst and update stats.
Definition: mem_interface.cc:2312
gem5::memory::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:462
gem5::memory::DRAMInterface::REF_PD_EXIT
@ REF_PD_EXIT
Definition: mem_interface.hh:398
gem5::ceilLog2
static constexpr int ceilLog2(const T &n)
Definition: intmath.hh:84
gem5::memory::NVMInterface::ranks
std::vector< Rank * > ranks
Vector of nvm ranks.
Definition: mem_interface.hh:1119
gem5::memory::DRAMInterface::Rank::numBanksActive
unsigned int numBanksActive
To track number of banks which are currently active for this rank.
Definition: mem_interface.hh:583
gem5::memory::DRAMInterface::init
void init() override
Initialize the DRAM interface and verify parameters.
Definition: mem_interface.cc:843
gem5::memory::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:727
gem5::memory::NVMInterface::NVMStats::perBankWrBursts
statistics::Vector perBankWrBursts
Definition: mem_interface.hh:1080
gem5::X86ISA::granularity
Bitfield< 6 > granularity
Definition: misc.hh:997
gem5::ArmISA::n
Bitfield< 31 > n
Definition: misc_types.hh:455
gem5::memory::NVMInterface::NVMStats::regStats
void regStats() override
Callback to set stat parameters.
Definition: mem_interface.cc:2582
gem5::memory::MemPacket::rank
const uint8_t rank
Will be populated by address decoder.
Definition: mem_ctrl.hh:119
gem5::memory::DRAMInterface::tBURST_MIN
const Tick tBURST_MIN
Definition: mem_interface.hh:734
gem5::memory::AbstractMemory::system
System * system() const
read the system pointer Implemented for completeness with the setter
Definition: abstract_mem.hh:266
gem5::memory::DRAMInterface::tCCD_L_WR
const Tick tCCD_L_WR
Definition: mem_interface.hh:736
gem5::memory::DRAMInterface::REF_SREF_EXIT
@ REF_SREF_EXIT
Definition: mem_interface.hh:399
std::deque
STL deque class.
Definition: stl.hh:44
gem5::memory::NVMInterface::NVMStats::readBursts
statistics::Scalar readBursts
NVM stats.
Definition: mem_interface.hh:1076
gem5::memory::DRAMInterface::dataClockSync
const bool dataClockSync
Definition: mem_interface.hh:753
gem5::memory::DRAMInterface::DRAMStats::perBankWrBursts
statistics::Vector perBankWrBursts
Definition: mem_interface.hh:824
gem5::memory::DRAMInterface::burstInterleave
const bool burstInterleave
Definition: mem_interface.hh:754
gem5::memory::qos::MemCtrl::numPriorities
uint8_t numPriorities() const
Gets the total number of priority levels in the QoS memory controller.
Definition: mem_ctrl.hh:367
gem5::Clocked::tick
Tick tick
Definition: clocked_object.hh:68
gem5::simSeconds
statistics::Formula & simSeconds
Definition: stats.cc:45
gem5::memory::DRAMInterface::DRAMStats::bytesRead
statistics::Scalar bytesRead
Definition: mem_interface.hh:843
gem5::memory::NVMInterface::stats
NVMStats stats
Definition: mem_interface.hh:1108
gem5::memory::DRAMInterface::clkResyncDelay
const Tick clkResyncDelay
Definition: mem_interface.hh:752
gem5::statistics::Group
Statistics container.
Definition: group.hh:93
gem5::memory::NVMInterface::NVMStats::perBankRdBursts
statistics::Vector perBankRdBursts
Definition: mem_interface.hh:1079
gem5::memory::DRAMInterface::Command::timeStamp
Tick timeStamp
Definition: mem_interface.hh:319
gem5::memory::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:399
gem5::memory::DRAMInterface::DRAMStats::bytesWritten
statistics::Scalar bytesWritten
Definition: mem_interface.hh:844
gem5::memory::NVMInterface::NVMStats::pendingWrites
statistics::Histogram pendingWrites
Definition: mem_interface.hh:1105
gem5::memory::MemInterface::rowBufferSize
const uint32_t rowBufferSize
Definition: mem_interface.hh:140
gem5::memory::MemInterface::getCtrlAddr
Addr getCtrlAddr(Addr addr)
Get an address in a dense range which starts from 0.
Definition: mem_interface.hh:200
gem5::memory::NVMInterface::nextReadAt
Tick nextReadAt
Till when must we wait before issuing next read command?
Definition: mem_interface.hh:1143
gem5::MipsISA::r
r
Definition: pra_constants.hh:98
gem5::memory::MemInterface::Bank::NO_ROW
static const uint32_t NO_ROW
Definition: mem_interface.hh:93
gem5::memory::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:571
gem5::memory::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:89
trace.hh
gem5::memory::DRAMInterface::tRFC
const Tick tRFC
Definition: mem_interface.hh:743
gem5::memory::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:1129
gem5::memory::DRAMInterface::Rank
Rank class includes a vector of banks.
Definition: mem_interface.hh:472
gem5::memory::MemInterface::Bank::actAllowedAt
Tick actAllowedAt
Definition: mem_interface.hh:102
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:225
gem5
Reference material can be found at the JEDEC website: UFS standard http://www.jedec....
Definition: decoder.cc:40
gem5::memory::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:123
gem5::memory::MemPacket::isRead
bool isRead() const
Return true if its a read packet (interface compatibility with Packet)
Definition: mem_ctrl.hh:189
gem5::memory::DRAMInterface::pageMgmt
enums::PageManage pageMgmt
Definition: mem_interface.hh:761
gem5::memory::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
gem5::memory::DRAMInterface::DRAMStats::resetStats
void resetStats() override
Callback to reset stats.
Definition: mem_interface.cc:1849
gem5::memory::NVMInterface::numReadDataReady
uint16_t numReadDataReady
Definition: mem_interface.hh:1148
gem5::memory::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
gem5::memory::NVMInterface::NVMStats::bytesWritten
statistics::Scalar bytesWritten
Definition: mem_interface.hh:1093
gem5::memory::MemInterface::burstSize
const uint32_t burstSize
General device and channel characteristics The rowsPerBank is determined based on the capacity,...
Definition: mem_interface.hh:136
gem5::memory::NVMInterface::writeRespQueueEmpty
bool writeRespQueueEmpty() const
Check if the write response queue is empty.
Definition: mem_interface.hh:1138
gem5::memory::DRAMInterface::timeStampOffset
uint64_t timeStampOffset
Definition: mem_interface.hh:769
gem5::memory::DRAMInterface::RankStats::preDumpStats
void preDumpStats() override
Callback before stats are dumped.
Definition: mem_interface.cc:2032
gem5::memory::DRAMInterface::Command::bank
uint8_t bank
Definition: mem_interface.hh:318
gem5::memory::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:128
gem5::memory::MemInterface::tCK
const GEM5_CLASS_VAR_USED Tick tCK
General timing requirements.
Definition: mem_interface.hh:150
gem5::memory::DRAMInterface::sortTime
static bool sortTime(const Command &cmd, const Command &cmd_next)
Function for sorting Command structures based on timeStamp.
Definition: mem_interface.hh:719
gem5::statistics::Group::preDumpStats
virtual void preDumpStats()
Callback before stats are dumped.
Definition: group.cc:99
gem5::memory::DRAMInterface::tRAS
const Tick tRAS
Definition: mem_interface.hh:740
gem5::DrainState::Draining
@ Draining
Draining buffers pending serialization/handover.
gem5::memory::DRAMInterface::Rank::pwrState
PowerState pwrState
Current power state.
Definition: mem_interface.hh:521
gem5::Event::scheduled
bool scheduled() const
Determine if the current event is scheduled.
Definition: eventq.hh:465
gem5::memory::DRAMInterface::startup
void startup() override
Iterate through dram ranks and instantiate per rank startup routine.
Definition: mem_interface.cc:885
panic
#define panic(...)
This implements a cprintf based panic() function.
Definition: logging.hh:177
gem5::memory::DRAMInterface::RankStats::RankStats
RankStats(DRAMInterface &dram, Rank &rank)
Definition: mem_interface.cc:1971
gem5::X86ISA::addr
Bitfield< 3 > addr
Definition: types.hh:84
gem5::memory::DRAMInterface::RankStats::resetStats
void resetStats() override
Callback to reset stats.
Definition: mem_interface.cc:2024
gem5::memory::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

Generated on Tue Sep 21 2021 12:25:33 for gem5 by doxygen 1.8.17