46 #include "debug/DRAM.hh"
47 #include "debug/DRAMPower.hh"
48 #include "debug/DRAMState.hh"
49 #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 std::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 std::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 std::make_pair(bank_mask, hidden_bank_prep);
1124 pwrStateTrans(PWR_IDLE), pwrStatePostRefresh(PWR_IDLE),
1125 pwrStateTick(0), refreshDueAt(0), pwrState(PWR_IDLE),
1126 refreshState(REF_IDLE), inLowPowerState(false), rank(_rank),
1127 readEntries(0), writeEntries(0), outstandingEvents(0),
1128 wakeUpAllowedAt(0),
power(_p, false), banks(_p.banks_per_rank),
1129 numBanksActive(0), actTicks(_p.activation_limit, 0), lastBurstTick(0),
1131 activateEvent([
this]{ processActivateEvent(); },
name()),
1132 prechargeEvent([
this]{ processPrechargeEvent(); },
name()),
1133 refreshEvent([
this]{ processRefreshEvent(); },
name()),
1134 powerEvent([
this]{ processPowerEvent(); },
name()),
1135 wakeUpEvent([
this]{ processWakeUpEvent(); },
name()),
1138 for (
int b = 0;
b < _p.banks_per_rank;
b++) {
1143 if (_p.bank_groups_per_rank > 0) {
1151 banks[
b].bankgr =
b % _p.bank_groups_per_rank;
1154 banks[
b].bankgr =
b;
1187 bool no_queued_cmds = (dram.ctrl->inReadBusState(
true) &&
1189 || (dram.ctrl->inWriteBusState(
true) &&
1190 (writeEntries == 0));
1191 return no_queued_cmds;
1200 DPRINTF(DRAM,
"Refresh drain done, now precharging\n");
1216 auto next_iter = cmdList.begin();
1218 for ( ; next_iter != cmdList.end() ; ++next_iter) {
1224 dram.timeStampOffset);
1234 cmdList.assign(next_iter, cmdList.end());
1252 assert(outstandingEvents > 0);
1254 --outstandingEvents;
1258 if (numBanksActive == 0) {
1261 if (isQueueEmpty() && outstandingEvents == 0 &&
1262 dram.enableDRAMPowerdown) {
1267 DPRINTF(DRAMState,
"Rank %d sleep at tick %d\n",
1283 assert(outstandingEvents > 0);
1286 --outstandingEvents;
1302 ++outstandingEvents;
1304 DPRINTF(DRAM,
"Refresh due\n");
1313 if ((rank == dram.activeRank)
1314 && (dram.ctrl->requestEventScheduled())) {
1317 DPRINTF(DRAM,
"Refresh awaiting draining\n");
1329 if (inLowPowerState) {
1330 DPRINTF(DRAM,
"Wake Up for refresh\n");
1332 scheduleWakeUpEvent(dram.tXP);
1340 if (refreshState ==
REF_PRE) {
1342 if (numBanksActive != 0) {
1345 DPRINTF(DRAM,
"Precharging all\n");
1350 for (
auto &
b : banks) {
1354 pre_at = std::max(
b.preAllowedAt, pre_at);
1359 Tick act_allowed_at = pre_at + dram.tRP;
1361 for (
auto &
b : banks) {
1363 dram.prechargeBank(*
this,
b, pre_at,
true,
false);
1365 b.actAllowedAt = std::max(
b.actAllowedAt, act_allowed_at);
1366 b.preAllowedAt = std::max(
b.preAllowedAt, pre_at);
1371 cmdList.push_back(
Command(MemCommand::PREA, 0, pre_at));
1375 dram.timeStampOffset, rank);
1376 }
else if ((pwrState ==
PWR_IDLE) && (outstandingEvents == 1)) {
1379 DPRINTF(DRAM,
"All banks already precharged, starting refresh\n");
1388 assert(prechargeEvent.scheduled() ||
1389 dram.ctrl->respondEventScheduled());
1393 assert(numBanksActive == 0);
1408 assert(numBanksActive == 0);
1413 for (
auto &
b : banks) {
1414 b.actAllowedAt = ref_done_at;
1424 dram.timeStampOffset, rank);
1427 refreshDueAt += dram.tREFI;
1431 if (refreshDueAt < ref_done_at) {
1432 fatal(
"Refresh was delayed so long we cannot catch up\n");
1438 schedule(refreshEvent, ref_done_at);
1442 if (refreshState ==
REF_RUN) {
1444 assert(numBanksActive == 0);
1447 assert(!powerEvent.scheduled());
1457 if (pwrStatePostRefresh !=
PWR_IDLE) {
1460 DPRINTF(DRAMState,
"Rank %d sleeping after refresh and was in "
1461 "power state %d before refreshing\n", rank,
1462 pwrStatePostRefresh);
1463 powerDownSleep(pwrState,
curTick());
1467 }
else if (isQueueEmpty() && dram.enableDRAMPowerdown) {
1470 assert(outstandingEvents == 1);
1471 DPRINTF(DRAMState,
"Rank %d sleeping after refresh but was NOT"
1472 " in a low power state before refreshing\n", rank);
1488 schedule(refreshEvent, refreshDueAt - dram.tRP);
1490 DPRINTF(DRAMState,
"Refresh done at %llu and next refresh"
1491 " at %llu\n",
curTick(), refreshDueAt);
1501 if (!powerEvent.scheduled()) {
1502 DPRINTF(DRAMState,
"Scheduling power event at %llu to state %d\n",
1506 pwrStateTrans = pwr_state;
1510 panic(
"Scheduled power event at %llu to state %d, "
1511 "with scheduled event at %llu to %d\n",
tick, pwr_state,
1512 powerEvent.when(), pwrStateTrans);
1523 schedulePowerEvent(pwr_state,
tick);
1525 cmdList.push_back(
Command(MemCommand::PDN_F_ACT, 0,
tick));
1527 dram.tCK) - dram.timeStampOffset, rank);
1532 schedulePowerEvent(pwr_state,
tick);
1534 cmdList.push_back(
Command(MemCommand::PDN_F_PRE, 0,
tick));
1536 dram.tCK) - dram.timeStampOffset, rank);
1537 }
else if (pwr_state ==
PWR_REF) {
1544 cmdList.push_back(
Command(MemCommand::PDN_F_PRE, 0,
tick));
1546 dram.tCK) - dram.timeStampOffset, rank);
1547 }
else if (pwr_state ==
PWR_SREF) {
1554 cmdList.push_back(
Command(MemCommand::SREN, 0,
tick));
1556 dram.tCK) - dram.timeStampOffset, rank);
1561 wakeUpAllowedAt =
tick + dram.tCK;
1564 inLowPowerState =
true;
1570 Tick wake_up_tick = std::max(
curTick(), wakeUpAllowedAt);
1572 DPRINTF(DRAMState,
"Scheduling wake-up for rank %d at tick %d\n",
1573 rank, wake_up_tick);
1578 pwrStatePostRefresh = pwrState;
1586 schedule(wakeUpEvent, wake_up_tick);
1588 for (
auto &
b : banks) {
1592 b.wrAllowedAt = std::max(wake_up_tick + exit_delay,
b.wrAllowedAt);
1593 b.rdAllowedAt = std::max(wake_up_tick + exit_delay,
b.rdAllowedAt);
1594 b.preAllowedAt = std::max(wake_up_tick + exit_delay,
b.preAllowedAt);
1595 b.actAllowedAt = std::max(wake_up_tick + exit_delay,
b.actAllowedAt);
1598 inLowPowerState =
false;
1604 cmdList.push_back(
Command(MemCommand::PUP_ACT, 0, wake_up_tick));
1606 dram.tCK) - dram.timeStampOffset, rank);
1609 cmdList.push_back(
Command(MemCommand::PUP_PRE, 0, wake_up_tick));
1611 dram.tCK) - dram.timeStampOffset, rank);
1612 }
else if (pwrStateTrans ==
PWR_SREF) {
1613 cmdList.push_back(
Command(MemCommand::SREX, 0, wake_up_tick));
1615 dram.tCK) - dram.timeStampOffset, rank);
1640 assert(
curTick() >= pwrStateTick);
1646 stats.pwrStateTime[prev_state] += duration;
1651 stats.totalIdleTime += duration;
1654 pwrState = pwrStateTrans;
1661 assert(outstandingEvents == 1);
1663 --outstandingEvents;
1666 DPRINTF(DRAMState,
"Was refreshing for %llu ticks\n", duration);
1670 DPRINTF(DRAMState,
"Switching to power down state after refreshing"
1671 " rank %d at %llu tick\n", rank,
curTick());
1675 if (!dram.ctrl->requestEventScheduled()) {
1676 DPRINTF(DRAM,
"Scheduling next request after refreshing"
1677 " rank %d\n", rank);
1678 dram.ctrl->restartScheduler(
curTick());
1690 DPRINTF(DRAMState,
"All banks precharged\n");
1706 if (!activateEvent.scheduled()) {
1708 assert(!powerEvent.scheduled());
1714 }
else if (refreshState ==
REF_PRE) {
1721 assert(prechargeEvent.scheduled());
1736 if (pwrStatePostRefresh ==
PWR_PRE_PDN && isQueueEmpty() &&
1739 dram.enableDRAMPowerdown) {
1740 DPRINTF(DRAMState,
"Rank %d bypassing refresh and transitioning "
1741 "to self refresh at %11u tick\n", rank,
curTick());
1745 assert(outstandingEvents == 1);
1746 --outstandingEvents;
1753 DPRINTF(DRAMState,
"Refreshing\n");
1756 assert(!powerEvent.scheduled());
1782 dram.timeStampOffset);
1785 Data::MemoryPowerModel::Energy energy =
power.powerlib.getEnergy();
1789 stats.actEnergy += energy.act_energy * dram.devicesPerRank;
1790 stats.preEnergy += energy.pre_energy * dram.devicesPerRank;
1791 stats.readEnergy += energy.read_energy * dram.devicesPerRank;
1792 stats.writeEnergy += energy.write_energy * dram.devicesPerRank;
1793 stats.refreshEnergy += energy.ref_energy * dram.devicesPerRank;
1794 stats.actBackEnergy += energy.act_stdby_energy * dram.devicesPerRank;
1795 stats.preBackEnergy += energy.pre_stdby_energy * dram.devicesPerRank;
1796 stats.actPowerDownEnergy += energy.f_act_pd_energy * dram.devicesPerRank;
1797 stats.prePowerDownEnergy += energy.f_pre_pd_energy * dram.devicesPerRank;
1798 stats.selfRefreshEnergy += energy.sref_energy * dram.devicesPerRank;
1801 stats.totalEnergy += energy.window_energy * dram.devicesPerRank;
1808 stats.averagePower = (
stats.totalEnergy.value() /
1809 (
curTick() - dram.lastStatsResetTick)) *
1816 DPRINTF(DRAM,
"Computing stats due to a dump callback\n");
1822 stats.pwrStateTime[pwrState] += (
curTick() - pwrStateTick);
1832 dram.timeStampOffset);
1838 return (readEntries != 0) ||
1839 (dram.ctrl->inWriteBusState(
true) && (writeEntries != 0));
1845 dram.lastStatsResetTick =
curTick();
1861 "Total ticks spent from burst creation until serviced "
1865 "Average queueing delay per DRAM burst"),
1867 "Average bus latency per DRAM burst"),
1869 "Average memory access latency per DRAM burst"),
1872 "Number of row buffer hits during reads"),
1874 "Number of row buffer hits during writes"),
1882 "Average DRAM read bandwidth in MiBytes/s"),
1884 "Average DRAM write bandwidth in MiBytes/s"),
1886 "Theoretical peak bandwidth in MiByte/s"),
1890 "Data bus utilization in percentage for reads"),
1892 "Data bus utilization in percentage for writes"),
1895 "Row buffer hit rate, read and write combined")
1903 using namespace Stats;
1905 avgQLat.precision(2);
1906 avgBusLat.precision(2);
1907 avgMemAccLat.precision(2);
1909 readRowHitRate.precision(2);
1910 writeRowHitRate.precision(2);
1912 perBankRdBursts.init(dram.banksPerRank * dram.ranksPerChannel);
1913 perBankWrBursts.init(dram.banksPerRank * dram.ranksPerChannel);
1916 .init(dram.maxAccessesPerRow ?
1917 dram.maxAccessesPerRow : dram.rowBufferSize)
1920 peakBW.precision(2);
1921 busUtil.precision(2);
1922 busUtilWrite.precision(2);
1923 busUtilRead.precision(2);
1925 pageHitRate.precision(2);
1928 avgQLat = totQLat / readBursts;
1929 avgBusLat = totBusLat / readBursts;
1930 avgMemAccLat = totMemAccLat / readBursts;
1932 readRowHitRate = (readRowHits / readBursts) * 100;
1933 writeRowHitRate = (writeRowHits / writeBursts) * 100;
1935 avgRdBW = (bytesRead / 1000000) /
simSeconds;
1936 avgWrBW = (bytesWritten / 1000000) /
simSeconds;
1938 dram.bytesPerBurst() / 1000000;
1940 busUtil = (avgRdBW + avgWrBW) / peakBW * 100;
1941 busUtilRead = avgRdBW / peakBW * 100;
1942 busUtilWrite = avgWrBW / peakBW * 100;
1944 pageHitRate = (writeRowHits + readRowHits) /
1945 (writeBursts + readBursts) * 100;
1953 "Energy for activate commands per rank (pJ)"),
1955 "Energy for precharge commands per rank (pJ)"),
1957 "Energy for read commands per rank (pJ)"),
1959 "Energy for write commands per rank (pJ)"),
1961 "Energy for refresh commands per rank (pJ)"),
1963 "Energy for active background per rank (pJ)"),
1965 "Energy for precharge background per rank (pJ)"),
1967 "Energy for active power-down per rank (pJ)"),
1969 "Energy for precharge power-down per rank (pJ)"),
1971 "Energy for self refresh per rank (pJ)"),
1991 .subname(3,
"PRE_PDN")
1993 .subname(5,
"ACT_PDN");
2009 rank.computeStats();
2014 maxPendingWrites(_p.max_pending_writes),
2015 maxPendingReads(_p.max_pending_reads),
2016 twoCycleRdWr(_p.two_cycle_rdwr),
2017 tREAD(_p.tREAD), tWRITE(_p.tWRITE), tSEND(_p.tSEND),
2020 readReadyEvent([
this]{ processReadReadyEvent(); },
name()),
2021 nextReadAt(0), numPendingReads(0), numReadDataReady(0),
2022 numReadsToIssue(0), numWritesQueued(0)
2024 DPRINTF(NVM,
"Setting up NVM Interface\n");
2027 "must be a power of two\n", burstSize);
2032 "not allowed, must be a power of two\n", ranksPerChannel);
2034 for (
int i =0;
i < ranksPerChannel;
i++) {
2036 DPRINTF(NVM,
"Creating NVM rank %d \n",
i);
2037 Rank* rank =
new Rank(_p,
i, *
this);
2038 ranks.push_back(rank);
2043 DPRINTF(NVM,
"NVM capacity %lld (%lld) bytes\n", capacity,
2046 rowsPerBank = capacity / (rowBufferSize *
2047 banksPerRank * ranksPerChannel);
2053 :
EventManager(&_nvm), rank(_rank), banks(_p.banks_per_rank)
2055 for (
int b = 0;
b < _p.banks_per_rank;
b++) {
2083 bool found_prepped_pkt =
false;
2085 auto selected_pkt_it = queue.end();
2088 for (
auto i = queue.begin();
i != queue.end() ; ++
i) {
2100 DPRINTF(NVM,
"%s bank %d - Rank %d available\n", __func__,
2104 if (col_allowed_at <= min_col_at) {
2108 selected_pkt_it =
i;
2109 selected_col_at = col_allowed_at;
2111 DPRINTF(NVM,
"%s Seamless buffer hit\n", __func__);
2113 }
else if (!found_prepped_pkt) {
2116 selected_pkt_it =
i;
2117 selected_col_at = col_allowed_at;
2118 DPRINTF(NVM,
"%s Prepped packet found \n", __func__);
2119 found_prepped_pkt =
true;
2122 DPRINTF(NVM,
"%s bank %d - Rank %d not available\n", __func__,
2128 if (selected_pkt_it == queue.end()) {
2129 DPRINTF(NVM,
"%s no available NVM ranks found\n", __func__);
2132 return std::make_pair(selected_pkt_it, selected_col_at);
2145 assert(!queue.empty());
2150 for (
auto i = queue.begin();
i != queue.end() ; ++
i) {
2207 DPRINTF(NVM,
"Issuing NVM Read to bank %d at tick %d. "
2208 "Data ready at %d\n",
2237 "processReadReadyEvent(): Data for an NVM read is ready. "
2238 "numReadDataReady is %d\t numPendingReads is %d\n",
2247 if (*ready_it > *
i) {
2248 next_ready_at = *ready_it;
2250 }
else if ((next_ready_at > *
i) && (
i != ready_it)) {
2256 assert(*ready_it ==
curTick());
2270 DPRINTF(NVM,
"Restart controller scheduler immediately\n");
2281 return (read_rdy || write_rdy);
2287 DPRINTF(NVM,
"NVM Timing access to addr %lld, rank/bank/row %d %d %d\n",
2299 Tick cmd_at = std::max(bst_allowed_at,
curTick());
2303 cmd_at = std::max(cmd_at, next_burst_at);
2326 if (pkt->
rank !=
n->rank) {
2332 n->banks[
i].rdAllowedAt = std::max(cmd_at + dly_to_rd_cmd,
2333 n->banks[
i].rdAllowedAt);
2335 n->banks[
i].wrAllowedAt = std::max(cmd_at + dly_to_wr_cmd,
2336 n->banks[
i].wrAllowedAt);
2340 DPRINTF(NVM,
"NVM Access to %lld, ready at %lld.\n",
2362 if ((bank_ref.
bank == pkt->
bank) &&
2400 DPRINTF(NVM,
"Rescheduled respond event from %lld to %11d\n",
2402 DPRINTF(NVM,
"Front of response queue is %11d\n",
2426 return std::make_pair(cmd_at, cmd_at +
tBURST);
2433 "processWriteRespondEvent(): A NVM write reached its readyTime. "
2453 DPRINTF(NVM,
"Restart controller scheduler immediately\n");
2468 n->banks[
i].rdAllowedAt);
2470 n->banks[
i].wrAllowedAt);
2507 "Total ticks spent from burst creation until serviced "
2510 "Average queueing delay per NVM burst"),
2512 "Average bus latency per NVM burst"),
2514 "Average memory access latency per NVM burst"),
2519 "Average DRAM read bandwidth in MiBytes/s"),
2521 "Average DRAM write bandwidth in MiBytes/s"),
2523 "Theoretical peak bandwidth in MiByte/s"),
2526 "NVM Data bus read utilization in percentage"),
2528 "NVM Data bus write utilization in percentage"),
2531 "Reads issued to NVM for which data has not been transferred"),
2534 "Bytes read within a bank before loading new bank")
2542 using namespace Stats;
2544 perBankRdBursts.init(nvm.ranksPerChannel == 0 ? 1 :
2545 nvm.banksPerRank * nvm.ranksPerChannel);
2547 perBankWrBursts.init(nvm.ranksPerChannel == 0 ? 1 :
2548 nvm.banksPerRank * nvm.ranksPerChannel);
2550 avgQLat.precision(2);
2551 avgBusLat.precision(2);
2552 avgMemAccLat.precision(2);
2554 avgRdBW.precision(2);
2555 avgWrBW.precision(2);
2556 peakBW.precision(2);
2558 busUtil.precision(2);
2559 busUtilRead.precision(2);
2560 busUtilWrite.precision(2);
2563 .init(nvm.maxPendingReads)
2567 .init(nvm.maxPendingWrites)
2571 .init(nvm.rowBufferSize)
2574 avgQLat = totQLat / readBursts;
2575 avgBusLat = totBusLat / readBursts;
2576 avgMemAccLat = totMemAccLat / readBursts;
2578 avgRdBW = (bytesRead / 1000000) /
simSeconds;
2579 avgWrBW = (bytesWritten / 1000000) /
simSeconds;
2581 nvm.burstSize / 1000000;
2583 busUtil = (avgRdBW + avgWrBW) / peakBW * 100;
2584 busUtilRead = avgRdBW / peakBW * 100;
2585 busUtilWrite = avgWrBW / peakBW * 100;