45 #include "debug/DRAM.hh"
46 #include "debug/DRAMPower.hh"
47 #include "debug/DRAMState.hh"
48 #include "debug/NVM.hh"
56 addrMapping(_p->addr_mapping),
57 burstSize((_p->devices_per_rank * _p->burst_length *
58 _p->device_bus_width) / 8),
59 deviceSize(_p->device_size),
60 deviceRowBufferSize(_p->device_rowbuffer_size),
61 devicesPerRank(_p->devices_per_rank),
62 rowBufferSize(devicesPerRank * deviceRowBufferSize),
63 burstsPerRowBuffer(rowBufferSize / burstSize),
64 burstsPerStripe(range.interleaved() ?
66 ranksPerChannel(_p->ranks_per_channel),
67 banksPerRank(_p->banks_per_rank), rowsPerBank(0),
68 tCK(_p->tCK), tCS(_p->tCS), tBURST(_p->tBURST),
71 readBufferSize(_p->read_buffer_size),
72 writeBufferSize(_p->write_buffer_size)
84 unsigned size,
bool is_read,
bool is_dram)
149 panic(
"Unknown address mapping policy chosen!");
156 DPRINTF(DRAM,
"Address: %lld Rank %d Bank %d Row %d\n",
157 pkt_addr, rank, bank, row);
164 return new MemPacket(pkt, is_read, is_dram, rank, bank, row, bank_id,
174 bool filled_earliest_banks =
false;
176 bool hidden_bank_prep =
false;
183 bool found_hidden_bank =
false;
187 bool found_prepped_pkt =
false;
191 bool found_earliest_pkt =
false;
194 auto selected_pkt_it = queue.end();
196 for (
auto i = queue.begin();
i != queue.end() ; ++
i) {
205 DPRINTF(DRAM,
"%s checking DRAM packet in bank %d, row %d\n",
206 __func__, pkt->
bank, pkt->
row);
213 "%s bank %d - Rank %d available\n", __func__,
221 if (col_allowed_at <= min_col_at) {
226 DPRINTF(DRAM,
"%s Seamless buffer hit\n", __func__);
228 selected_col_at = col_allowed_at;
231 }
else if (!found_hidden_bank && !found_prepped_pkt) {
237 selected_col_at = col_allowed_at;
238 found_prepped_pkt =
true;
239 DPRINTF(DRAM,
"%s Prepped row buffer hit\n", __func__);
241 }
else if (!found_earliest_pkt) {
244 if (!filled_earliest_banks) {
246 std::tie(earliest_banks, hidden_bank_prep) =
248 filled_earliest_banks =
true;
256 found_earliest_pkt =
true;
257 found_hidden_bank = hidden_bank_prep;
263 if (hidden_bank_prep || !found_prepped_pkt) {
265 selected_col_at = col_allowed_at;
270 DPRINTF(DRAM,
"%s bank %d - Rank %d not available\n", __func__,
276 if (selected_pkt_it == queue.end()) {
277 DPRINTF(DRAM,
"%s no available DRAM ranks found\n", __func__);
280 return make_pair(selected_pkt_it, selected_col_at);
285 Tick act_tick, uint32_t row)
297 DPRINTF(DRAM,
"Activate at tick %d\n", act_at);
312 DPRINTF(DRAM,
"Activate bank %d, rank %d at tick %lld, now got "
313 "%d active\n", bank_ref.
bank, rank_ref.
rank, act_at,
337 rank_ref.
banks[
i].actAllowedAt = std::max(act_at +
tRRD_L,
338 rank_ref.
banks[
i].actAllowedAt);
343 rank_ref.
banks[
i].actAllowedAt = std::max(act_at +
tRRD,
344 rank_ref.
banks[
i].actAllowedAt);
354 panic(
"Got %d activates in window %d (%llu - %llu) which "
365 rank_ref.
actTicks.push_front(act_at);
372 DPRINTF(DRAM,
"Enforcing tXAW with X = %d, next activate "
377 rank_ref.
banks[
j].actAllowedAt =
379 rank_ref.
banks[
j].actAllowedAt);
394 bool auto_or_preall,
bool trace)
405 Tick pre_at = pre_tick;
406 if (auto_or_preall) {
416 rank_ref.
banks[
i].preAllowedAt = std::max(pre_at +
tPPD,
417 rank_ref.
banks[
i].preAllowedAt);
421 Tick pre_done_at = pre_at +
tRP;
428 DPRINTF(DRAM,
"Precharging bank %d, rank %d at tick %lld, now got "
429 "%d active\n", bank.
bank, rank_ref.
rank, pre_at,
459 DPRINTF(DRAM,
"Timing access to addr %lld, rank/bank/row %d %d %d\n",
502 const Tick col_allowed_at = mem_pkt->
isRead() ?
507 Tick cmd_at = std::max({col_allowed_at, next_burst_at,
curTick()});
532 DPRINTF(DRAM,
"Schedule RD/WR burst at tick %d\n", cmd_at);
545 if (mem_pkt->
rank ==
j) {
553 dly_to_rd_cmd = mem_pkt->
isRead() ?
555 dly_to_wr_cmd = mem_pkt->
isRead() ?
561 dly_to_rd_cmd = mem_pkt->
isRead() ? burst_gap :
573 ranks[
j]->banks[
i].rdAllowedAt = std::max(cmd_at + dly_to_rd_cmd,
574 ranks[
j]->banks[
i].rdAllowedAt);
575 ranks[
j]->banks[
i].wrAllowedAt = std::max(cmd_at + dly_to_wr_cmd,
576 ranks[
j]->banks[
i].wrAllowedAt);
595 bool auto_precharge =
pageMgmt == Enums::close ||
600 if (!auto_precharge &&
601 (
pageMgmt == Enums::open_adaptive ||
602 pageMgmt == Enums::close_adaptive)) {
611 bool got_more_hits =
false;
612 bool got_bank_conflict =
false;
615 auto p = queue[
i].begin();
624 while (!got_more_hits &&
p != queue[
i].end()) {
625 if (mem_pkt != (*
p)) {
626 bool same_rank_bank = (mem_pkt->
rank == (*p)->rank) &&
627 (mem_pkt->
bank == (*p)->bank);
629 bool same_row = mem_pkt->
row == (*p)->row;
630 got_more_hits |= same_rank_bank && same_row;
631 got_bank_conflict |= same_rank_bank && !same_row;
644 auto_precharge = !got_more_hits &&
645 (got_bank_conflict ||
pageMgmt == Enums::close_adaptive);
649 std::string mem_cmd = mem_pkt->
isRead() ?
"RD" :
"WR";
662 if (auto_precharge) {
668 DPRINTF(DRAM,
"Auto-precharged bank: %d\n", mem_pkt->
bankId);
713 return make_pair(cmd_at, cmd_at + burst_gap);
726 n->banks[
i].rdAllowedAt);
728 n->banks[
i].wrAllowedAt);
735 bankGroupsPerRank(_p->bank_groups_per_rank),
736 bankGroupArch(_p->bank_groups_per_rank > 0),
738 tBURST_MIN(_p->tBURST_MIN), tBURST_MAX(_p->tBURST_MAX),
739 tCCD_L_WR(_p->tCCD_L_WR), tCCD_L(_p->tCCD_L), tRCD(_p->tRCD),
740 tRP(_p->tRP), tRAS(_p->tRAS), tWR(_p->tWR), tRTP(_p->tRTP),
741 tRFC(_p->tRFC), tREFI(_p->tREFI), tRRD(_p->tRRD), tRRD_L(_p->tRRD_L),
742 tPPD(_p->tPPD), tAAD(_p->tAAD),
743 tXAW(_p->tXAW), tXP(_p->tXP), tXS(_p->tXS),
744 clkResyncDelay(tCL + _p->tBURST_MAX),
745 dataClockSync(_p->data_clock_sync),
746 burstInterleave(tBURST != tBURST_MIN),
747 twoCycleActivate(_p->two_cycle_activate),
748 activationLimit(_p->activation_limit),
749 wrToRdDlySameBG(tCL + _p->tBURST_MAX + _p->tWTR_L),
750 rdToWrDlySameBG(_p->tRTW + _p->tBURST_MAX),
751 pageMgmt(_p->page_policy),
752 maxAccessesPerRow(_p->max_accesses_per_row),
753 timeStampOffset(0), activeRank(0),
754 enableDRAMPowerdown(_p->enable_dram_powerdown),
755 lastStatsResetTick(0),
758 DPRINTF(DRAM,
"Setting up DRAM Interface\n");
769 DPRINTF(DRAM,
"Creating DRAM rank %d \n",
i);
771 ranks.push_back(rank);
780 DPRINTF(DRAM,
"Memory capacity %lld (%lld) bytes\n", capacity,
784 if (deviceCapacity != capacity / (1024 * 1024))
785 warn(
"DRAM device capacity (%d Mbytes) does not match the "
786 "address range assigned (%d Mbytes)\n", deviceCapacity,
787 capacity / (1024 * 1024));
789 DPRINTF(DRAM,
"Row buffer size %d bytes with %d bursts per row buffer\n",
796 fatal(
"tREFI (%d) must be larger than tRP (%d) and tRFC (%d)\n",
804 fatal(
"banks per rank (%d) must be equal to or larger than "
805 "banks groups per rank (%d)\n",
810 fatal(
"Banks per rank (%d) must be evenly divisible by bank "
811 "groups per rank (%d) for equal banks per bank group\n",
816 fatal(
"tCCD_L (%d) should be larger than the minimum bus delay "
817 "(%d) when bank groups per rank (%d) is greater than 1\n",
822 fatal(
"tCCD_L_WR (%d) should be larger than the minimum bus delay "
823 " (%d) when bank groups per rank (%d) is greater than 1\n",
829 fatal(
"tRRD_L (%d) should be larger than tRRD (%d) when "
830 "bank groups per rank (%d) is greater than 1\n",
846 fatal(
"Channel interleaving of %s doesn't match RoRaBaChCo "
847 "address map\n",
name());
863 fatal(
"Channel interleaving of %s must be at least as large "
864 "as the cache line size\n",
name());
869 fatal(
"Channel interleaving of %s must be at most as large "
870 "as the row-buffer size\n",
name());
881 if (
system()->isTimingMode()) {
896 if (!
r->inRefIdleState()) {
899 DPRINTF(DRAMState,
"Rank %d is not available\n",
r->rank);
909 if ((
r->pwrState ==
PWR_SREF) &&
r->inLowPowerState) {
910 DPRINTF(DRAMState,
"Rank %d is in self-refresh\n",
r->rank);
914 if (
r->forceSelfRefreshExit()) {
915 DPRINTF(DRAMState,
"rank %d was in self refresh and"
916 " should wake up\n",
r->rank);
918 r->scheduleWakeUpEvent(
tXS);
933 ++
ranks[rank]->readEntries;
935 ++
ranks[rank]->writeEntries;
948 DPRINTF(DRAM,
"number of read entries for rank %d is %d\n",
972 DPRINTF(DRAMState,
"Rank %d sleep at tick %d; current power state is "
1006 DPRINTF(DRAM,
"Rank%d: Forcing self-refresh wakeup in drain\n",
1008 r->scheduleWakeUpEvent(
tXS);
1017 bool all_ranks_drained =
true;
1022 all_ranks_drained =
r->inPwrIdleState() &&
r->inRefIdleState() &&
1025 return all_ranks_drained;
1038 Tick min_col_at)
const
1048 bool found_seamless_bank =
false;
1052 bool hidden_bank_prep =
false;
1057 for (
const auto&
p : queue) {
1058 if (
p->isDram() &&
ranks[
p->rank]->inRefIdleState())
1059 got_waiting[
p->bankId] =
true;
1070 if (got_waiting[bank_id]) {
1072 assert(
ranks[
i]->inRefIdleState());
1082 ranks[
i]->banks[
j].rdAllowedAt :
1083 ranks[
i]->banks[
j].wrAllowedAt;
1084 Tick col_at = std::max(col_allowed_at, act_at +
tRCD);
1088 bool new_seamless_bank = col_at <= min_col_at;
1093 if (new_seamless_bank ||
1094 (!found_seamless_bank && act_at <= min_act_at)) {
1100 if (!found_seamless_bank &&
1101 (new_seamless_bank || act_at < min_act_at)) {
1102 std::fill(bank_mask.begin(), bank_mask.end(), 0);
1105 found_seamless_bank |= new_seamless_bank;
1108 hidden_bank_prep = act_at <= hidden_act_max;
1112 min_act_at = act_at;
1118 return make_pair(bank_mask, hidden_bank_prep);
1122 DRAMInterfaceParams::create()
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),
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()),
1144 for (
int b = 0;
b < _p->banks_per_rank;
b++) {
1149 if (_p->bank_groups_per_rank > 0) {
1157 banks[
b].bankgr =
b % _p->bank_groups_per_rank;
1160 banks[
b].bankgr =
b;
1193 bool no_queued_cmds = (dram.ctrl->inReadBusState(
true) &&
1195 || (dram.ctrl->inWriteBusState(
true) &&
1196 (writeEntries == 0));
1197 return no_queued_cmds;
1206 DPRINTF(DRAM,
"Refresh drain done, now precharging\n");
1222 auto next_iter = cmdList.begin();
1224 for ( ; next_iter != cmdList.end() ; ++next_iter) {
1230 dram.timeStampOffset);
1240 cmdList.assign(next_iter, cmdList.end());
1258 assert(outstandingEvents > 0);
1260 --outstandingEvents;
1264 if (numBanksActive == 0) {
1267 if (isQueueEmpty() && outstandingEvents == 0 &&
1268 dram.enableDRAMPowerdown) {
1273 DPRINTF(DRAMState,
"Rank %d sleep at tick %d\n",
1289 assert(outstandingEvents > 0);
1292 --outstandingEvents;
1308 ++outstandingEvents;
1310 DPRINTF(DRAM,
"Refresh due\n");
1319 if ((rank == dram.activeRank)
1320 && (dram.ctrl->requestEventScheduled())) {
1323 DPRINTF(DRAM,
"Refresh awaiting draining\n");
1335 if (inLowPowerState) {
1336 DPRINTF(DRAM,
"Wake Up for refresh\n");
1338 scheduleWakeUpEvent(dram.tXP);
1346 if (refreshState ==
REF_PRE) {
1348 if (numBanksActive != 0) {
1351 DPRINTF(DRAM,
"Precharging all\n");
1356 for (
auto &
b : banks) {
1360 pre_at = std::max(
b.preAllowedAt, pre_at);
1365 Tick act_allowed_at = pre_at + dram.tRP;
1367 for (
auto &
b : banks) {
1369 dram.prechargeBank(*
this,
b, pre_at,
true,
false);
1371 b.actAllowedAt = std::max(
b.actAllowedAt, act_allowed_at);
1372 b.preAllowedAt = std::max(
b.preAllowedAt, pre_at);
1377 cmdList.push_back(
Command(MemCommand::PREA, 0, pre_at));
1381 dram.timeStampOffset, rank);
1382 }
else if ((pwrState ==
PWR_IDLE) && (outstandingEvents == 1)) {
1385 DPRINTF(DRAM,
"All banks already precharged, starting refresh\n");
1394 assert(prechargeEvent.scheduled() ||
1395 dram.ctrl->respondEventScheduled());
1399 assert(numBanksActive == 0);
1414 assert(numBanksActive == 0);
1419 for (
auto &
b : banks) {
1420 b.actAllowedAt = ref_done_at;
1430 dram.timeStampOffset, rank);
1433 refreshDueAt += dram.tREFI;
1437 if (refreshDueAt < ref_done_at) {
1438 fatal(
"Refresh was delayed so long we cannot catch up\n");
1444 schedule(refreshEvent, ref_done_at);
1448 if (refreshState ==
REF_RUN) {
1450 assert(numBanksActive == 0);
1453 assert(!powerEvent.scheduled());
1463 if (pwrStatePostRefresh !=
PWR_IDLE) {
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());
1473 }
else if (isQueueEmpty() && dram.enableDRAMPowerdown) {
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);
1494 schedule(refreshEvent, refreshDueAt - dram.tRP);
1496 DPRINTF(DRAMState,
"Refresh done at %llu and next refresh"
1497 " at %llu\n",
curTick(), refreshDueAt);
1507 if (!powerEvent.scheduled()) {
1508 DPRINTF(DRAMState,
"Scheduling power event at %llu to state %d\n",
1512 pwrStateTrans = pwr_state;
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);
1529 schedulePowerEvent(pwr_state,
tick);
1531 cmdList.push_back(
Command(MemCommand::PDN_F_ACT, 0,
tick));
1533 dram.tCK) - dram.timeStampOffset, rank);
1538 schedulePowerEvent(pwr_state,
tick);
1540 cmdList.push_back(
Command(MemCommand::PDN_F_PRE, 0,
tick));
1542 dram.tCK) - dram.timeStampOffset, rank);
1543 }
else if (pwr_state ==
PWR_REF) {
1550 cmdList.push_back(
Command(MemCommand::PDN_F_PRE, 0,
tick));
1552 dram.tCK) - dram.timeStampOffset, rank);
1553 }
else if (pwr_state ==
PWR_SREF) {
1560 cmdList.push_back(
Command(MemCommand::SREN, 0,
tick));
1562 dram.tCK) - dram.timeStampOffset, rank);
1567 wakeUpAllowedAt =
tick + dram.tCK;
1570 inLowPowerState =
true;
1576 Tick wake_up_tick = std::max(
curTick(), wakeUpAllowedAt);
1578 DPRINTF(DRAMState,
"Scheduling wake-up for rank %d at tick %d\n",
1579 rank, wake_up_tick);
1584 pwrStatePostRefresh = pwrState;
1592 schedule(wakeUpEvent, wake_up_tick);
1594 for (
auto &
b : banks) {
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);
1604 inLowPowerState =
false;
1610 cmdList.push_back(
Command(MemCommand::PUP_ACT, 0, wake_up_tick));
1612 dram.tCK) - dram.timeStampOffset, rank);
1615 cmdList.push_back(
Command(MemCommand::PUP_PRE, 0, 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));
1621 dram.tCK) - dram.timeStampOffset, rank);
1646 assert(
curTick() >= pwrStateTick);
1652 stats.pwrStateTime[prev_state] += duration;
1657 stats.totalIdleTime += duration;
1660 pwrState = pwrStateTrans;
1667 assert(outstandingEvents == 1);
1669 --outstandingEvents;
1672 DPRINTF(DRAMState,
"Was refreshing for %llu ticks\n", duration);
1676 DPRINTF(DRAMState,
"Switching to power down state after refreshing"
1677 " rank %d at %llu tick\n", rank,
curTick());
1681 if (!dram.ctrl->requestEventScheduled()) {
1682 DPRINTF(DRAM,
"Scheduling next request after refreshing"
1683 " rank %d\n", rank);
1684 dram.ctrl->restartScheduler(
curTick());
1696 DPRINTF(DRAMState,
"All banks precharged\n");
1712 if (!activateEvent.scheduled()) {
1714 assert(!powerEvent.scheduled());
1720 }
else if (refreshState ==
REF_PRE) {
1727 assert(prechargeEvent.scheduled());
1742 if (pwrStatePostRefresh ==
PWR_PRE_PDN && isQueueEmpty() &&
1745 dram.enableDRAMPowerdown) {
1746 DPRINTF(DRAMState,
"Rank %d bypassing refresh and transitioning "
1747 "to self refresh at %11u tick\n", rank,
curTick());
1751 assert(outstandingEvents == 1);
1752 --outstandingEvents;
1759 DPRINTF(DRAMState,
"Refreshing\n");
1762 assert(!powerEvent.scheduled());
1788 dram.timeStampOffset);
1791 Data::MemoryPowerModel::Energy energy =
power.powerlib.getEnergy();
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;
1807 stats.totalEnergy += energy.window_energy * dram.devicesPerRank;
1814 stats.averagePower = (
stats.totalEnergy.value() /
1815 (
curTick() - dram.lastStatsResetTick)) *
1822 DPRINTF(DRAM,
"Computing stats due to a dump callback\n");
1828 stats.pwrStateTime[pwrState] += (
curTick() - pwrStateTick);
1838 dram.timeStampOffset);
1844 return (readEntries != 0) ||
1845 (dram.ctrl->inWriteBusState(
true) && (writeEntries != 0));
1851 dram.lastStatsResetTick =
curTick();
1858 ADD_STAT(readBursts,
"Number of DRAM read bursts"),
1859 ADD_STAT(writeBursts,
"Number of DRAM write bursts"),
1861 ADD_STAT(perBankRdBursts,
"Per bank write bursts"),
1862 ADD_STAT(perBankWrBursts,
"Per bank write bursts"),
1864 ADD_STAT(totQLat,
"Total ticks spent queuing"),
1865 ADD_STAT(totBusLat,
"Total ticks spent in databus transfers"),
1867 "Total ticks spent from burst creation until serviced "
1870 ADD_STAT(avgQLat,
"Average queueing delay per DRAM burst"),
1871 ADD_STAT(avgBusLat,
"Average bus latency per DRAM burst"),
1872 ADD_STAT(avgMemAccLat,
"Average memory access latency per DRAM burst"),
1874 ADD_STAT(readRowHits,
"Number of row buffer hits during reads"),
1875 ADD_STAT(writeRowHits,
"Number of row buffer hits during writes"),
1876 ADD_STAT(readRowHitRate,
"Row buffer hit rate for reads"),
1877 ADD_STAT(writeRowHitRate,
"Row buffer hit rate for writes"),
1879 ADD_STAT(bytesPerActivate,
"Bytes accessed per row activation"),
1880 ADD_STAT(bytesRead,
"Total number of bytes read from DRAM"),
1881 ADD_STAT(bytesWritten,
"Total number of bytes written to DRAM"),
1882 ADD_STAT(avgRdBW,
"Average DRAM read bandwidth in MiBytes/s"),
1883 ADD_STAT(avgWrBW,
"Average DRAM write bandwidth in MiBytes/s"),
1884 ADD_STAT(peakBW,
"Theoretical peak bandwidth in MiByte/s"),
1886 ADD_STAT(busUtil,
"Data bus utilization in percentage"),
1887 ADD_STAT(busUtilRead,
"Data bus utilization in percentage for reads"),
1888 ADD_STAT(busUtilWrite,
"Data bus utilization in percentage for writes"),
1890 ADD_STAT(pageHitRate,
"Row buffer hit rate, read and write combined")
1898 using namespace Stats;
1900 avgQLat.precision(2);
1901 avgBusLat.precision(2);
1902 avgMemAccLat.precision(2);
1904 readRowHitRate.precision(2);
1905 writeRowHitRate.precision(2);
1907 perBankRdBursts.init(dram.banksPerRank * dram.ranksPerChannel);
1908 perBankWrBursts.init(dram.banksPerRank * dram.ranksPerChannel);
1911 .init(dram.maxAccessesPerRow ?
1912 dram.maxAccessesPerRow : dram.rowBufferSize)
1915 peakBW.precision(2);
1916 busUtil.precision(2);
1917 busUtilWrite.precision(2);
1918 busUtilRead.precision(2);
1920 pageHitRate.precision(2);
1923 avgQLat = totQLat / readBursts;
1924 avgBusLat = totBusLat / readBursts;
1925 avgMemAccLat = totMemAccLat / readBursts;
1927 readRowHitRate = (readRowHits / readBursts) * 100;
1928 writeRowHitRate = (writeRowHits / writeBursts) * 100;
1930 avgRdBW = (bytesRead / 1000000) /
simSeconds;
1931 avgWrBW = (bytesWritten / 1000000) /
simSeconds;
1933 dram.bytesPerBurst() / 1000000;
1935 busUtil = (avgRdBW + avgWrBW) / peakBW * 100;
1936 busUtilRead = avgRdBW / peakBW * 100;
1937 busUtilWrite = avgWrBW / peakBW * 100;
1939 pageHitRate = (writeRowHits + readRowHits) /
1940 (writeBursts + readBursts) * 100;
1947 ADD_STAT(actEnergy,
"Energy for activate commands per rank (pJ)"),
1948 ADD_STAT(preEnergy,
"Energy for precharge commands per rank (pJ)"),
1949 ADD_STAT(readEnergy,
"Energy for read commands per rank (pJ)"),
1950 ADD_STAT(writeEnergy,
"Energy for write commands per rank (pJ)"),
1951 ADD_STAT(refreshEnergy,
"Energy for refresh commands per rank (pJ)"),
1952 ADD_STAT(actBackEnergy,
"Energy for active background per rank (pJ)"),
1953 ADD_STAT(preBackEnergy,
"Energy for precharge background per rank (pJ)"),
1955 "Energy for active power-down per rank (pJ)"),
1957 "Energy for precharge power-down per rank (pJ)"),
1958 ADD_STAT(selfRefreshEnergy,
"Energy for self refresh per rank (pJ)"),
1960 ADD_STAT(totalEnergy,
"Total energy per rank (pJ)"),
1961 ADD_STAT(averagePower,
"Core power per rank (mW)"),
1963 ADD_STAT(totalIdleTime,
"Total Idle time Per DRAM Rank"),
1964 ADD_STAT(pwrStateTime,
"Time in different power states")
1978 .subname(3,
"PRE_PDN")
1980 .subname(5,
"ACT_PDN");
1996 rank.computeStats();
2001 maxPendingWrites(_p->max_pending_writes),
2002 maxPendingReads(_p->max_pending_reads),
2003 twoCycleRdWr(_p->two_cycle_rdwr),
2004 tREAD(_p->tREAD), tWRITE(_p->tWRITE), tSEND(_p->tSEND),
2007 readReadyEvent([
this]{ processReadReadyEvent(); },
name()),
2008 nextReadAt(0), numPendingReads(0), numReadDataReady(0),
2009 numReadsToIssue(0), numWritesQueued(0)
2011 DPRINTF(NVM,
"Setting up NVM Interface\n");
2014 "must be a power of two\n", burstSize);
2019 "not allowed, must be a power of two\n", ranksPerChannel);
2021 for (
int i =0;
i < ranksPerChannel;
i++) {
2023 DPRINTF(NVM,
"Creating NVM rank %d \n",
i);
2024 Rank* rank =
new Rank(_p,
i, *
this);
2025 ranks.push_back(rank);
2030 DPRINTF(NVM,
"NVM capacity %lld (%lld) bytes\n", capacity,
2033 rowsPerBank = capacity / (rowBufferSize *
2034 banksPerRank * ranksPerChannel);
2039 NVMInterfaceParams::create()
2046 :
EventManager(&_nvm), rank(_rank), banks(_p->banks_per_rank)
2048 for (
int b = 0;
b < _p->banks_per_rank;
b++) {
2076 bool found_prepped_pkt =
false;
2078 auto selected_pkt_it = queue.end();
2081 for (
auto i = queue.begin();
i != queue.end() ; ++
i) {
2093 DPRINTF(NVM,
"%s bank %d - Rank %d available\n", __func__,
2097 if (col_allowed_at <= min_col_at) {
2101 selected_pkt_it =
i;
2102 selected_col_at = col_allowed_at;
2104 DPRINTF(NVM,
"%s Seamless buffer hit\n", __func__);
2106 }
else if (!found_prepped_pkt) {
2109 selected_pkt_it =
i;
2110 selected_col_at = col_allowed_at;
2111 DPRINTF(NVM,
"%s Prepped packet found \n", __func__);
2112 found_prepped_pkt =
true;
2115 DPRINTF(NVM,
"%s bank %d - Rank %d not available\n", __func__,
2121 if (selected_pkt_it == queue.end()) {
2122 DPRINTF(NVM,
"%s no available NVM ranks found\n", __func__);
2125 return make_pair(selected_pkt_it, selected_col_at);
2138 assert(!queue.empty());
2143 for (
auto i = queue.begin();
i != queue.end() ; ++
i) {
2200 DPRINTF(NVM,
"Issuing NVM Read to bank %d at tick %d. "
2201 "Data ready at %d\n",
2230 "processReadReadyEvent(): Data for an NVM read is ready. "
2231 "numReadDataReady is %d\t numPendingReads is %d\n",
2240 if (*ready_it > *
i) {
2241 next_ready_at = *ready_it;
2243 }
else if ((next_ready_at > *
i) && (
i != ready_it)) {
2249 assert(*ready_it ==
curTick());
2263 DPRINTF(NVM,
"Restart controller scheduler immediately\n");
2274 return (read_rdy || write_rdy);
2280 DPRINTF(NVM,
"NVM Timing access to addr %lld, rank/bank/row %d %d %d\n",
2292 Tick cmd_at = std::max(bst_allowed_at,
curTick());
2296 cmd_at = std::max(cmd_at, next_burst_at);
2319 if (pkt->
rank !=
n->rank) {
2325 n->banks[
i].rdAllowedAt = std::max(cmd_at + dly_to_rd_cmd,
2326 n->banks[
i].rdAllowedAt);
2328 n->banks[
i].wrAllowedAt = std::max(cmd_at + dly_to_wr_cmd,
2329 n->banks[
i].wrAllowedAt);
2333 DPRINTF(NVM,
"NVM Access to %lld, ready at %lld.\n",
2355 if ((bank_ref.
bank == pkt->
bank) &&
2393 DPRINTF(NVM,
"Rescheduled respond event from %lld to %11d\n",
2395 DPRINTF(NVM,
"Front of response queue is %11d\n",
2419 return make_pair(cmd_at, cmd_at +
tBURST);
2426 "processWriteRespondEvent(): A NVM write reached its readyTime. "
2446 DPRINTF(NVM,
"Restart controller scheduler immediately\n");
2461 n->banks[
i].rdAllowedAt);
2463 n->banks[
i].wrAllowedAt);
2491 ADD_STAT(readBursts,
"Number of NVM read bursts"),
2492 ADD_STAT(writeBursts,
"Number of NVM write bursts"),
2494 ADD_STAT(perBankRdBursts,
"Per bank write bursts"),
2495 ADD_STAT(perBankWrBursts,
"Per bank write bursts"),
2497 ADD_STAT(totQLat,
"Total ticks spent queuing"),
2498 ADD_STAT(totBusLat,
"Total ticks spent in databus transfers"),
2500 "Total ticks spent from burst creation until serviced "
2502 ADD_STAT(avgQLat,
"Average queueing delay per NVM burst"),
2503 ADD_STAT(avgBusLat,
"Average bus latency per NVM burst"),
2504 ADD_STAT(avgMemAccLat,
"Average memory access latency per NVM burst"),
2506 ADD_STAT(bytesRead,
"Total number of bytes read from DRAM"),
2507 ADD_STAT(bytesWritten,
"Total number of bytes written to DRAM"),
2508 ADD_STAT(avgRdBW,
"Average DRAM read bandwidth in MiBytes/s"),
2509 ADD_STAT(avgWrBW,
"Average DRAM write bandwidth in MiBytes/s"),
2510 ADD_STAT(peakBW,
"Theoretical peak bandwidth in MiByte/s"),
2511 ADD_STAT(busUtil,
"NVM Data bus utilization in percentage"),
2512 ADD_STAT(busUtilRead,
"NVM Data bus read utilization in percentage"),
2513 ADD_STAT(busUtilWrite,
"NVM Data bus write utilization in percentage"),
2515 ADD_STAT(pendingReads,
"Reads issued to NVM for which data has not been "
2517 ADD_STAT(pendingWrites,
"Number of outstanding writes to NVM"),
2518 ADD_STAT(bytesPerBank,
"Bytes read within a bank before loading "
2526 using namespace Stats;
2528 perBankRdBursts.init(nvm.ranksPerChannel == 0 ? 1 :
2529 nvm.banksPerRank * nvm.ranksPerChannel);
2531 perBankWrBursts.init(nvm.ranksPerChannel == 0 ? 1 :
2532 nvm.banksPerRank * nvm.ranksPerChannel);
2534 avgQLat.precision(2);
2535 avgBusLat.precision(2);
2536 avgMemAccLat.precision(2);
2538 avgRdBW.precision(2);
2539 avgWrBW.precision(2);
2540 peakBW.precision(2);
2542 busUtil.precision(2);
2543 busUtilRead.precision(2);
2544 busUtilWrite.precision(2);
2547 .init(nvm.maxPendingReads)
2551 .init(nvm.maxPendingWrites)
2555 .init(nvm.rowBufferSize)
2558 avgQLat = totQLat / readBursts;
2559 avgBusLat = totBusLat / readBursts;
2560 avgMemAccLat = totMemAccLat / readBursts;
2562 avgRdBW = (bytesRead / 1000000) /
simSeconds;
2563 avgWrBW = (bytesWritten / 1000000) /
simSeconds;
2565 nvm.burstSize / 1000000;
2567 busUtil = (avgRdBW + avgWrBW) / peakBW * 100;
2568 busUtilRead = avgRdBW / peakBW * 100;
2569 busUtilWrite = avgWrBW / peakBW * 100;