46 #include "debug/DRAM.hh"
47 #include "debug/DRAMPower.hh"
48 #include "debug/DRAMState.hh"
49 #include "debug/NVM.hh"
60 MemInterface::MemInterface(
const MemInterfaceParams &_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() ?
72 ranksPerChannel(_p.ranks_per_channel),
73 banksPerRank(_p.banks_per_rank), rowsPerBank(0),
74 tCK(_p.tCK), tCS(_p.tCS), tBURST(_p.tBURST),
77 readBufferSize(_p.read_buffer_size),
78 writeBufferSize(_p.write_buffer_size)
90 unsigned size,
bool is_read,
bool is_dram)
155 panic(
"Unknown address mapping policy chosen!");
162 DPRINTF(DRAM,
"Address: %#x Rank %d Bank %d Row %d\n",
163 pkt_addr, rank, bank, row);
170 return new MemPacket(pkt, is_read, is_dram, rank, bank, row, bank_id,
180 bool filled_earliest_banks =
false;
182 bool hidden_bank_prep =
false;
189 bool found_hidden_bank =
false;
193 bool found_prepped_pkt =
false;
197 bool found_earliest_pkt =
false;
200 auto selected_pkt_it = queue.end();
202 for (
auto i = queue.begin();
i != queue.end() ; ++
i) {
211 DPRINTF(DRAM,
"%s checking DRAM packet in bank %d, row %d\n",
212 __func__, pkt->
bank, pkt->
row);
219 "%s bank %d - Rank %d available\n", __func__,
227 if (col_allowed_at <= min_col_at) {
232 DPRINTF(DRAM,
"%s Seamless buffer hit\n", __func__);
234 selected_col_at = col_allowed_at;
237 }
else if (!found_hidden_bank && !found_prepped_pkt) {
243 selected_col_at = col_allowed_at;
244 found_prepped_pkt =
true;
245 DPRINTF(DRAM,
"%s Prepped row buffer hit\n", __func__);
247 }
else if (!found_earliest_pkt) {
250 if (!filled_earliest_banks) {
252 std::tie(earliest_banks, hidden_bank_prep) =
254 filled_earliest_banks =
true;
262 found_earliest_pkt =
true;
263 found_hidden_bank = hidden_bank_prep;
269 if (hidden_bank_prep || !found_prepped_pkt) {
271 selected_col_at = col_allowed_at;
276 DPRINTF(DRAM,
"%s bank %d - Rank %d not available\n", __func__,
282 if (selected_pkt_it == queue.end()) {
283 DPRINTF(DRAM,
"%s no available DRAM ranks found\n", __func__);
286 return std::make_pair(selected_pkt_it, selected_col_at);
291 Tick act_tick, uint32_t row)
303 DPRINTF(DRAM,
"Activate at tick %d\n", act_at);
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,
343 rank_ref.
banks[
i].actAllowedAt = std::max(act_at +
tRRD_L,
344 rank_ref.
banks[
i].actAllowedAt);
349 rank_ref.
banks[
i].actAllowedAt = std::max(act_at +
tRRD,
350 rank_ref.
banks[
i].actAllowedAt);
360 panic(
"Got %d activates in window %d (%llu - %llu) which "
371 rank_ref.
actTicks.push_front(act_at);
378 DPRINTF(DRAM,
"Enforcing tXAW with X = %d, next activate "
383 rank_ref.
banks[
j].actAllowedAt =
385 rank_ref.
banks[
j].actAllowedAt);
400 bool auto_or_preall,
bool trace)
411 Tick pre_at = pre_tick;
412 if (auto_or_preall) {
422 rank_ref.
banks[
i].preAllowedAt = std::max(pre_at +
tPPD,
423 rank_ref.
banks[
i].preAllowedAt);
427 Tick pre_done_at = pre_at +
tRP;
434 DPRINTF(DRAM,
"Precharging bank %d, rank %d at tick %lld, now got "
435 "%d active\n", bank.
bank, rank_ref.
rank, pre_at,
465 DPRINTF(DRAM,
"Timing access to addr %#x, rank/bank/row %d %d %d\n",
508 const Tick col_allowed_at = mem_pkt->
isRead() ?
513 Tick cmd_at = std::max({col_allowed_at, next_burst_at,
curTick()});
538 DPRINTF(DRAM,
"Schedule RD/WR burst at tick %d\n", cmd_at);
551 if (mem_pkt->
rank ==
j) {
559 dly_to_rd_cmd = mem_pkt->
isRead() ?
561 dly_to_wr_cmd = mem_pkt->
isRead() ?
567 dly_to_rd_cmd = mem_pkt->
isRead() ? burst_gap :
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);
601 bool auto_precharge =
pageMgmt == enums::close ||
606 if (!auto_precharge &&
607 (
pageMgmt == enums::open_adaptive ||
608 pageMgmt == enums::close_adaptive)) {
617 bool got_more_hits =
false;
618 bool got_bank_conflict =
false;
621 auto p = queue[
i].begin();
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);
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;
650 auto_precharge = !got_more_hits &&
651 (got_bank_conflict ||
pageMgmt == enums::close_adaptive);
655 std::string mem_cmd = mem_pkt->
isRead() ?
"RD" :
"WR";
668 if (auto_precharge) {
674 DPRINTF(DRAM,
"Auto-precharged bank: %d\n", mem_pkt->
bankId);
719 return std::make_pair(cmd_at, cmd_at + burst_gap);
732 n->banks[
i].rdAllowedAt);
734 n->banks[
i].wrAllowedAt);
741 bankGroupsPerRank(_p.bank_groups_per_rank),
742 bankGroupArch(_p.bank_groups_per_rank > 0),
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),
764 DPRINTF(DRAM,
"Setting up DRAM Interface\n");
775 DPRINTF(DRAM,
"Creating DRAM rank %d \n",
i);
777 ranks.push_back(rank);
786 DPRINTF(DRAM,
"Memory capacity %lld (%lld) bytes\n", capacity,
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));
795 DPRINTF(DRAM,
"Row buffer size %d bytes with %d bursts per row buffer\n",
802 fatal(
"tREFI (%d) must be larger than tRP (%d) and tRFC (%d)\n",
810 fatal(
"banks per rank (%d) must be equal to or larger than "
811 "banks groups per rank (%d)\n",
816 fatal(
"Banks per rank (%d) must be evenly divisible by bank "
817 "groups per rank (%d) for equal banks per bank group\n",
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",
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",
835 fatal(
"tRRD_L (%d) should be larger than tRRD (%d) when "
836 "bank groups per rank (%d) is greater than 1\n",
852 fatal(
"Channel interleaving of %s doesn't match RoRaBaChCo "
853 "address map\n",
name());
869 fatal(
"Channel interleaving of %s must be at least as large "
870 "as the cache line size\n",
name());
875 fatal(
"Channel interleaving of %s must be at most as large "
876 "as the row-buffer size\n",
name());
887 if (
system()->isTimingMode()) {
902 if (!
r->inRefIdleState()) {
905 DPRINTF(DRAMState,
"Rank %d is not available\n",
r->rank);
915 if ((
r->pwrState ==
PWR_SREF) &&
r->inLowPowerState) {
916 DPRINTF(DRAMState,
"Rank %d is in self-refresh\n",
r->rank);
920 if (
r->forceSelfRefreshExit()) {
921 DPRINTF(DRAMState,
"rank %d was in self refresh and"
922 " should wake up\n",
r->rank);
924 r->scheduleWakeUpEvent(
tXS);
939 ++
ranks[rank]->readEntries;
941 ++
ranks[rank]->writeEntries;
954 DPRINTF(DRAM,
"number of read entries for rank %d is %d\n",
978 DPRINTF(DRAMState,
"Rank %d sleep at tick %d; current power state is "
1012 DPRINTF(DRAM,
"Rank%d: Forcing self-refresh wakeup in drain\n",
1014 r->scheduleWakeUpEvent(
tXS);
1023 bool all_ranks_drained =
true;
1028 all_ranks_drained =
r->inPwrIdleState() &&
r->inRefIdleState() &&
1031 return all_ranks_drained;
1044 Tick min_col_at)
const
1054 bool found_seamless_bank =
false;
1058 bool hidden_bank_prep =
false;
1063 for (
const auto&
p : queue) {
1064 if (
p->isDram() &&
ranks[
p->rank]->inRefIdleState())
1065 got_waiting[
p->bankId] =
true;
1076 if (got_waiting[bank_id]) {
1078 assert(
ranks[
i]->inRefIdleState());
1088 ranks[
i]->banks[
j].rdAllowedAt :
1089 ranks[
i]->banks[
j].wrAllowedAt;
1090 Tick col_at = std::max(col_allowed_at, act_at +
tRCD);
1094 bool new_seamless_bank = col_at <= min_col_at;
1099 if (new_seamless_bank ||
1100 (!found_seamless_bank && act_at <= min_act_at)) {
1106 if (!found_seamless_bank &&
1107 (new_seamless_bank || act_at < min_act_at)) {
1108 std::fill(bank_mask.begin(), bank_mask.end(), 0);
1111 found_seamless_bank |= new_seamless_bank;
1114 hidden_bank_prep = act_at <= hidden_act_max;
1118 min_act_at = act_at;
1124 return std::make_pair(bank_mask, hidden_bank_prep);
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) {
1228 power.powerlib.doCommand(cmd.
type, cmd.
bank,
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();
1855 : statistics::
Group(&_dram),
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"),
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"),
1868 ADD_STAT(totQLat, statistics::units::
Tick::get(),
"Total ticks spent queuing"),
1870 "Total ticks spent in databus transfers"),
1872 "Total ticks spent from burst creation until serviced "
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"),
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"),
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"),
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"),
1917 ADD_STAT(pageHitRate, statistics::units::Ratio::get(),
1918 "Row buffer hit rate, read and write combined")
1926 using namespace statistics;
1928 avgQLat.precision(2);
1929 avgBusLat.precision(2);
1930 avgMemAccLat.precision(2);
1932 readRowHitRate.precision(2);
1933 writeRowHitRate.precision(2);
1935 perBankRdBursts.init(dram.banksPerRank * dram.ranksPerChannel);
1936 perBankWrBursts.init(dram.banksPerRank * dram.ranksPerChannel);
1939 .init(dram.maxAccessesPerRow ?
1940 dram.maxAccessesPerRow : dram.rowBufferSize)
1943 peakBW.precision(2);
1944 busUtil.precision(2);
1945 busUtilWrite.precision(2);
1946 busUtilRead.precision(2);
1948 pageHitRate.precision(2);
1951 avgQLat = totQLat / readBursts;
1952 avgBusLat = totBusLat / readBursts;
1953 avgMemAccLat = totMemAccLat / readBursts;
1955 readRowHitRate = (readRowHits / readBursts) * 100;
1956 writeRowHitRate = (writeRowHits / writeBursts) * 100;
1958 avgRdBW = (bytesRead / 1000000) /
simSeconds;
1959 avgWrBW = (bytesWritten / 1000000) /
simSeconds;
1961 dram.bytesPerBurst() / 1000000;
1963 busUtil = (avgRdBW + avgWrBW) / peakBW * 100;
1964 busUtilRead = avgRdBW / peakBW * 100;
1965 busUtilWrite = avgWrBW / peakBW * 100;
1967 pageHitRate = (writeRowHits + readRowHits) /
1968 (writeBursts + readBursts) * 100;
1972 : statistics::
Group(&_dram,
csprintf(
"rank%d", _rank.rank).c_str()),
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)"),
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)"),
2001 ADD_STAT(totalIdleTime, statistics::units::
Tick::get(),
2002 "Total Idle time Per DRAM Rank"),
2004 "Time in different power states")
2018 .subname(3,
"PRE_PDN")
2020 .subname(5,
"ACT_PDN");
2036 rank.computeStats();
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),
2047 readReadyEvent([
this]{ processReadReadyEvent(); },
name()),
2048 nextReadAt(0), numPendingReads(0), numReadDataReady(0),
2049 numReadsToIssue(0), numWritesQueued(0)
2051 DPRINTF(NVM,
"Setting up NVM Interface\n");
2054 "must be a power of two\n", burstSize);
2059 "not allowed, must be a power of two\n", ranksPerChannel);
2061 for (
int i =0;
i < ranksPerChannel;
i++) {
2063 DPRINTF(NVM,
"Creating NVM rank %d \n",
i);
2064 Rank* rank =
new Rank(_p,
i, *
this);
2065 ranks.push_back(rank);
2070 DPRINTF(NVM,
"NVM capacity %lld (%lld) bytes\n", capacity,
2073 rowsPerBank = capacity / (rowBufferSize *
2074 banksPerRank * ranksPerChannel);
2080 :
EventManager(&_nvm), rank(_rank), banks(_p.banks_per_rank)
2082 for (
int b = 0;
b < _p.banks_per_rank;
b++) {
2110 bool found_prepped_pkt =
false;
2112 auto selected_pkt_it = queue.end();
2115 for (
auto i = queue.begin();
i != queue.end() ; ++
i) {
2127 DPRINTF(NVM,
"%s bank %d - Rank %d available\n", __func__,
2131 if (col_allowed_at <= min_col_at) {
2135 selected_pkt_it =
i;
2136 selected_col_at = col_allowed_at;
2138 DPRINTF(NVM,
"%s Seamless buffer hit\n", __func__);
2140 }
else if (!found_prepped_pkt) {
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;
2149 DPRINTF(NVM,
"%s bank %d - Rank %d not available\n", __func__,
2155 if (selected_pkt_it == queue.end()) {
2156 DPRINTF(NVM,
"%s no available NVM ranks found\n", __func__);
2159 return std::make_pair(selected_pkt_it, selected_col_at);
2172 assert(!queue.empty());
2177 for (
auto i = queue.begin();
i != queue.end() ; ++
i) {
2234 DPRINTF(NVM,
"Issuing NVM Read to bank %d at tick %d. "
2235 "Data ready at %d\n",
2264 "processReadReadyEvent(): Data for an NVM read is ready. "
2265 "numReadDataReady is %d\t numPendingReads is %d\n",
2274 if (*ready_it > *
i) {
2275 next_ready_at = *ready_it;
2277 }
else if ((next_ready_at > *
i) && (
i != ready_it)) {
2283 assert(*ready_it ==
curTick());
2297 DPRINTF(NVM,
"Restart controller scheduler immediately\n");
2308 return (read_rdy || write_rdy);
2314 DPRINTF(NVM,
"NVM Timing access to addr %#x, rank/bank/row %d %d %d\n",
2326 Tick cmd_at = std::max(bst_allowed_at,
curTick());
2330 cmd_at = std::max(cmd_at, next_burst_at);
2353 if (pkt->
rank !=
n->rank) {
2359 n->banks[
i].rdAllowedAt = std::max(cmd_at + dly_to_rd_cmd,
2360 n->banks[
i].rdAllowedAt);
2362 n->banks[
i].wrAllowedAt = std::max(cmd_at + dly_to_wr_cmd,
2363 n->banks[
i].wrAllowedAt);
2367 DPRINTF(NVM,
"NVM Access to %#x, ready at %lld.\n",
2389 if ((bank_ref.
bank == pkt->
bank) &&
2427 DPRINTF(NVM,
"Rescheduled respond event from %lld to %11d\n",
2429 DPRINTF(NVM,
"Front of response queue is %11d\n",
2453 return std::make_pair(cmd_at, cmd_at +
tBURST);
2460 "processWriteRespondEvent(): A NVM write reached its readyTime. "
2480 DPRINTF(NVM,
"Restart controller scheduler immediately\n");
2495 n->banks[
i].rdAllowedAt);
2497 n->banks[
i].wrAllowedAt);
2522 : statistics::
Group(&_nvm),
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"),
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"),
2535 ADD_STAT(totQLat, statistics::units::
Tick::get(),
"Total ticks spent queuing"),
2537 "Total ticks spent in databus transfers"),
2539 "Total ticks spent from burst creation until serviced "
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"),
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"),
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")
2584 using namespace statistics;
2586 perBankRdBursts.init(nvm.ranksPerChannel == 0 ? 1 :
2587 nvm.banksPerRank * nvm.ranksPerChannel);
2589 perBankWrBursts.init(nvm.ranksPerChannel == 0 ? 1 :
2590 nvm.banksPerRank * nvm.ranksPerChannel);
2592 avgQLat.precision(2);
2593 avgBusLat.precision(2);
2594 avgMemAccLat.precision(2);
2596 avgRdBW.precision(2);
2597 avgWrBW.precision(2);
2598 peakBW.precision(2);
2600 busUtil.precision(2);
2601 busUtilRead.precision(2);
2602 busUtilWrite.precision(2);
2605 .init(nvm.maxPendingReads)
2609 .init(nvm.maxPendingWrites)
2613 .init(nvm.rowBufferSize)
2616 avgQLat = totQLat / readBursts;
2617 avgBusLat = totBusLat / readBursts;
2618 avgMemAccLat = totMemAccLat / readBursts;
2620 avgRdBW = (bytesRead / 1000000) /
simSeconds;
2621 avgWrBW = (bytesWritten / 1000000) /
simSeconds;
2623 nvm.burstSize / 1000000;
2625 busUtil = (avgRdBW + avgWrBW) / peakBW * 100;
2626 busUtilRead = avgRdBW / peakBW * 100;
2627 busUtilWrite = avgWrBW / peakBW * 100;