dram_ctrl.cc (10405:7a618c07e663) dram_ctrl.cc (10432:da98b90b5df0)
1/*
2 * Copyright (c) 2010-2014 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

--- 38 unchanged lines hidden (view full) ---

47#include "debug/DRAM.hh"
48#include "debug/DRAMPower.hh"
49#include "debug/DRAMState.hh"
50#include "debug/Drain.hh"
51#include "mem/dram_ctrl.hh"
52#include "sim/system.hh"
53
54using namespace std;
1/*
2 * Copyright (c) 2010-2014 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

--- 38 unchanged lines hidden (view full) ---

47#include "debug/DRAM.hh"
48#include "debug/DRAMPower.hh"
49#include "debug/DRAMState.hh"
50#include "debug/Drain.hh"
51#include "mem/dram_ctrl.hh"
52#include "sim/system.hh"
53
54using namespace std;
55using namespace Data;
55
56DRAMCtrl::DRAMCtrl(const DRAMCtrlParams* p) :
57 AbstractMemory(p),
58 port(name() + ".port", *this),
59 retryRdReq(false), retryWrReq(false),
60 busState(READ),
61 nextReqEvent(this), respondEvent(this), activateEvent(this),
62 prechargeEvent(this), refreshEvent(this), powerEvent(this),

--- 22 unchanged lines hidden (view full) ---

85 memSchedPolicy(p->mem_sched_policy), addrMapping(p->addr_mapping),
86 pageMgmt(p->page_policy),
87 maxAccessesPerRow(p->max_accesses_per_row),
88 frontendLatency(p->static_frontend_latency),
89 backendLatency(p->static_backend_latency),
90 busBusyUntil(0), refreshDueAt(0), refreshState(REF_IDLE),
91 pwrStateTrans(PWR_IDLE), pwrState(PWR_IDLE), prevArrival(0),
92 nextReqTime(0), pwrStateTick(0), numBanksActive(0),
56
57DRAMCtrl::DRAMCtrl(const DRAMCtrlParams* p) :
58 AbstractMemory(p),
59 port(name() + ".port", *this),
60 retryRdReq(false), retryWrReq(false),
61 busState(READ),
62 nextReqEvent(this), respondEvent(this), activateEvent(this),
63 prechargeEvent(this), refreshEvent(this), powerEvent(this),

--- 22 unchanged lines hidden (view full) ---

86 memSchedPolicy(p->mem_sched_policy), addrMapping(p->addr_mapping),
87 pageMgmt(p->page_policy),
88 maxAccessesPerRow(p->max_accesses_per_row),
89 frontendLatency(p->static_frontend_latency),
90 backendLatency(p->static_backend_latency),
91 busBusyUntil(0), refreshDueAt(0), refreshState(REF_IDLE),
92 pwrStateTrans(PWR_IDLE), pwrState(PWR_IDLE), prevArrival(0),
93 nextReqTime(0), pwrStateTick(0), numBanksActive(0),
93 activeRank(0)
94 activeRank(0), timeStampOffset(0)
94{
95 // create the bank states based on the dimensions of the ranks and
96 // banks
97 banks.resize(ranksPerChannel);
95{
96 // create the bank states based on the dimensions of the ranks and
97 // banks
98 banks.resize(ranksPerChannel);
99
100 //create list of drampower objects. For each rank 1 drampower instance.
101 for (int i = 0; i < ranksPerChannel; i++) {
102 DRAMPower drampower = DRAMPower(p, false);
103 rankPower.emplace_back(drampower);
104 }
105
98 actTicks.resize(ranksPerChannel);
99 for (size_t c = 0; c < ranksPerChannel; ++c) {
100 banks[c].resize(banksPerRank);
101 actTicks[c].resize(activationLimit, 0);
102 }
103
104 // set the bank indices
105 for (int r = 0; r < ranksPerChannel; r++) {

--- 116 unchanged lines hidden (view full) ---

222 } else {
223 port.sendRangeChange();
224 }
225}
226
227void
228DRAMCtrl::startup()
229{
106 actTicks.resize(ranksPerChannel);
107 for (size_t c = 0; c < ranksPerChannel; ++c) {
108 banks[c].resize(banksPerRank);
109 actTicks[c].resize(activationLimit, 0);
110 }
111
112 // set the bank indices
113 for (int r = 0; r < ranksPerChannel; r++) {

--- 116 unchanged lines hidden (view full) ---

230 } else {
231 port.sendRangeChange();
232 }
233}
234
235void
236DRAMCtrl::startup()
237{
238 // timestamp offset should be in clock cycles for DRAMPower
239 timeStampOffset = divCeil(curTick(), tCK);
230 // update the start tick for the precharge accounting to the
231 // current tick
232 pwrStateTick = curTick();
233
234 // shift the bus busy time sufficiently far ahead that we never
235 // have to worry about negative values when computing the time for
236 // the next request, this will add an insignificant bubble at the
237 // start of simulation

--- 618 unchanged lines hidden (view full) ---

856 bank.rowAccesses = 0;
857
858 ++numBanksActive;
859 assert(numBanksActive <= banksPerRank * ranksPerChannel);
860
861 DPRINTF(DRAM, "Activate bank %d, rank %d at tick %lld, now got %d active\n",
862 bank.bank, bank.rank, act_tick, numBanksActive);
863
240 // update the start tick for the precharge accounting to the
241 // current tick
242 pwrStateTick = curTick();
243
244 // shift the bus busy time sufficiently far ahead that we never
245 // have to worry about negative values when computing the time for
246 // the next request, this will add an insignificant bubble at the
247 // start of simulation

--- 618 unchanged lines hidden (view full) ---

866 bank.rowAccesses = 0;
867
868 ++numBanksActive;
869 assert(numBanksActive <= banksPerRank * ranksPerChannel);
870
871 DPRINTF(DRAM, "Activate bank %d, rank %d at tick %lld, now got %d active\n",
872 bank.bank, bank.rank, act_tick, numBanksActive);
873
864 DPRINTF(DRAMPower, "%llu,ACT,%d,%d\n", divCeil(act_tick, tCK), bank.bank,
865 bank.rank);
874 rankPower[bank.rank].powerlib.doCommand(MemCommand::ACT, bank.bank,
875 divCeil(act_tick, tCK) -
876 timeStampOffset);
866
877
878 DPRINTF(DRAMPower, "%llu,ACT,%d,%d\n", divCeil(act_tick, tCK) -
879 timeStampOffset, bank.bank, bank.rank);
880
867 // The next access has to respect tRAS for this bank
868 bank.preAllowedAt = act_tick + tRAS;
869
870 // Respect the row-to-column command delay
871 bank.colAllowedAt = std::max(act_tick + tRCD, bank.colAllowedAt);
872
873 // start by enforcing tRRD
874 for(int i = 0; i < banksPerRank; i++) {

--- 85 unchanged lines hidden (view full) ---

960 bank.actAllowedAt = std::max(bank.actAllowedAt, pre_done_at);
961
962 assert(numBanksActive != 0);
963 --numBanksActive;
964
965 DPRINTF(DRAM, "Precharging bank %d, rank %d at tick %lld, now got "
966 "%d active\n", bank.bank, bank.rank, pre_at, numBanksActive);
967
881 // The next access has to respect tRAS for this bank
882 bank.preAllowedAt = act_tick + tRAS;
883
884 // Respect the row-to-column command delay
885 bank.colAllowedAt = std::max(act_tick + tRCD, bank.colAllowedAt);
886
887 // start by enforcing tRRD
888 for(int i = 0; i < banksPerRank; i++) {

--- 85 unchanged lines hidden (view full) ---

974 bank.actAllowedAt = std::max(bank.actAllowedAt, pre_done_at);
975
976 assert(numBanksActive != 0);
977 --numBanksActive;
978
979 DPRINTF(DRAM, "Precharging bank %d, rank %d at tick %lld, now got "
980 "%d active\n", bank.bank, bank.rank, pre_at, numBanksActive);
981
968 if (trace)
969 DPRINTF(DRAMPower, "%llu,PRE,%d,%d\n", divCeil(pre_at, tCK),
970 bank.bank, bank.rank);
982 if (trace) {
971
983
984 rankPower[bank.rank].powerlib.doCommand(MemCommand::PRE, bank.bank,
985 divCeil(pre_at, tCK) -
986 timeStampOffset);
987 DPRINTF(DRAMPower, "%llu,PRE,%d,%d\n", divCeil(pre_at, tCK) -
988 timeStampOffset, bank.bank, bank.rank);
989 }
972 // if we look at the current number of active banks we might be
973 // tempted to think the DRAM is now idle, however this can be
974 // undone by an activate that is scheduled to happen before we
975 // would have reached the idle state, so schedule an event and
976 // rather check once we actually make it to the point in time when
977 // the (last) precharge takes place
978 if (!prechargeEvent.scheduled())
979 schedule(prechargeEvent, pre_done_at);

--- 155 unchanged lines hidden (view full) ---

1135 // 2) close_adaptive policy and we have not got any more hits
1136 auto_precharge = !got_more_hits &&
1137 (got_bank_conflict || pageMgmt == Enums::close_adaptive);
1138 }
1139
1140 // DRAMPower trace command to be written
1141 std::string mem_cmd = dram_pkt->isRead ? "RD" : "WR";
1142
990 // if we look at the current number of active banks we might be
991 // tempted to think the DRAM is now idle, however this can be
992 // undone by an activate that is scheduled to happen before we
993 // would have reached the idle state, so schedule an event and
994 // rather check once we actually make it to the point in time when
995 // the (last) precharge takes place
996 if (!prechargeEvent.scheduled())
997 schedule(prechargeEvent, pre_done_at);

--- 155 unchanged lines hidden (view full) ---

1153 // 2) close_adaptive policy and we have not got any more hits
1154 auto_precharge = !got_more_hits &&
1155 (got_bank_conflict || pageMgmt == Enums::close_adaptive);
1156 }
1157
1158 // DRAMPower trace command to be written
1159 std::string mem_cmd = dram_pkt->isRead ? "RD" : "WR";
1160
1161 // MemCommand required for DRAMPower library
1162 MemCommand::cmds command = (mem_cmd == "RD") ? MemCommand::RD :
1163 MemCommand::WR;
1164
1143 // if this access should use auto-precharge, then we are
1144 // closing the row
1145 if (auto_precharge) {
1165 // if this access should use auto-precharge, then we are
1166 // closing the row
1167 if (auto_precharge) {
1146 prechargeBank(bank, std::max(curTick(), bank.preAllowedAt), false);
1168 // if auto-precharge push a PRE command at the correct tick to the
1169 // list used by DRAMPower library to calculate power
1170 prechargeBank(bank, std::max(curTick(), bank.preAllowedAt));
1147
1171
1148 mem_cmd.append("A");
1149
1150 DPRINTF(DRAM, "Auto-precharged bank: %d\n", dram_pkt->bankId);
1151 }
1152
1153 // Update bus state
1154 busBusyUntil = dram_pkt->readyTime;
1155
1156 DPRINTF(DRAM, "Access to %lld, ready at %lld bus busy until %lld.\n",
1157 dram_pkt->addr, dram_pkt->readyTime, busBusyUntil);
1158
1172 DPRINTF(DRAM, "Auto-precharged bank: %d\n", dram_pkt->bankId);
1173 }
1174
1175 // Update bus state
1176 busBusyUntil = dram_pkt->readyTime;
1177
1178 DPRINTF(DRAM, "Access to %lld, ready at %lld bus busy until %lld.\n",
1179 dram_pkt->addr, dram_pkt->readyTime, busBusyUntil);
1180
1159 DPRINTF(DRAMPower, "%llu,%s,%d,%d\n", divCeil(cmd_at, tCK), mem_cmd,
1160 dram_pkt->bank, dram_pkt->rank);
1181 rankPower[dram_pkt->rank].powerlib.doCommand(command, dram_pkt->bank,
1182 divCeil(cmd_at, tCK) -
1183 timeStampOffset);
1161
1184
1185 DPRINTF(DRAMPower, "%llu,%s,%d,%d\n", divCeil(cmd_at, tCK) -
1186 timeStampOffset, mem_cmd, dram_pkt->bank, dram_pkt->rank);
1187
1162 // Update the minimum timing between the requests, this is a
1163 // conservative estimate of when we have to schedule the next
1164 // request to not introduce any unecessary bubbles. In most cases
1165 // we will wake up sooner than we have to.
1166 nextReqTime = busBusyUntil - (tRP + tRCD + tCL);
1167
1168 // Update the stats and schedule the next request
1169 if (dram_pkt->isRead) {

--- 335 unchanged lines hidden (view full) ---

1505 banks[i][j].actAllowedAt =
1506 std::max(banks[i][j].actAllowedAt, act_allowed_at);
1507 banks[i][j].preAllowedAt =
1508 std::max(banks[i][j].preAllowedAt, pre_at);
1509 }
1510 }
1511
1512 // at the moment this affects all ranks
1188 // Update the minimum timing between the requests, this is a
1189 // conservative estimate of when we have to schedule the next
1190 // request to not introduce any unecessary bubbles. In most cases
1191 // we will wake up sooner than we have to.
1192 nextReqTime = busBusyUntil - (tRP + tRCD + tCL);
1193
1194 // Update the stats and schedule the next request
1195 if (dram_pkt->isRead) {

--- 335 unchanged lines hidden (view full) ---

1531 banks[i][j].actAllowedAt =
1532 std::max(banks[i][j].actAllowedAt, act_allowed_at);
1533 banks[i][j].preAllowedAt =
1534 std::max(banks[i][j].preAllowedAt, pre_at);
1535 }
1536 }
1537
1538 // at the moment this affects all ranks
1513 DPRINTF(DRAMPower, "%llu,PREA,0,%d\n", divCeil(pre_at, tCK),
1514 i);
1539 rankPower[i].powerlib.doCommand(MemCommand::PREA, 0,
1540 divCeil(pre_at, tCK) -
1541 timeStampOffset);
1542
1543 DPRINTF(DRAMPower, "%llu,PREA,0,%d\n", divCeil(pre_at, tCK) -
1544 timeStampOffset, i);
1515 }
1516 } else {
1517 DPRINTF(DRAM, "All banks already precharged, starting refresh\n");
1518
1519 // go ahead and kick the power state machine into gear if
1520 // we are already idle
1521 schedulePowerEvent(PWR_REF, curTick());
1522 }

--- 17 unchanged lines hidden (view full) ---

1540 Tick ref_done_at = curTick() + tRFC;
1541
1542 for (int i = 0; i < ranksPerChannel; i++) {
1543 for (int j = 0; j < banksPerRank; j++) {
1544 banks[i][j].actAllowedAt = ref_done_at;
1545 }
1546
1547 // at the moment this affects all ranks
1545 }
1546 } else {
1547 DPRINTF(DRAM, "All banks already precharged, starting refresh\n");
1548
1549 // go ahead and kick the power state machine into gear if
1550 // we are already idle
1551 schedulePowerEvent(PWR_REF, curTick());
1552 }

--- 17 unchanged lines hidden (view full) ---

1570 Tick ref_done_at = curTick() + tRFC;
1571
1572 for (int i = 0; i < ranksPerChannel; i++) {
1573 for (int j = 0; j < banksPerRank; j++) {
1574 banks[i][j].actAllowedAt = ref_done_at;
1575 }
1576
1577 // at the moment this affects all ranks
1548 DPRINTF(DRAMPower, "%llu,REF,0,%d\n", divCeil(curTick(), tCK), i);
1578 rankPower[i].powerlib.doCommand(MemCommand::REF, 0,
1579 divCeil(curTick(), tCK) -
1580 timeStampOffset);
1581
1582 // at the moment sort the list of commands and update the counters
1583 // for DRAMPower libray when doing a refresh
1584 sort(rankPower[i].powerlib.cmdList.begin(),
1585 rankPower[i].powerlib.cmdList.end(), DRAMCtrl::sortTime);
1586
1587 // update the counters for DRAMPower, passing false to
1588 // indicate that this is not the last command in the
1589 // list. DRAMPower requires this information for the
1590 // correct calculation of the background energy at the end
1591 // of the simulation. Ideally we would want to call this
1592 // function with true once at the end of the
1593 // simulation. However, the discarded energy is extremly
1594 // small and does not effect the final results.
1595 rankPower[i].powerlib.updateCounters(false);
1596
1597 // call the energy function
1598 rankPower[i].powerlib.calcEnergy();
1599
1600 // Update the stats
1601 updatePowerStats(i);
1602
1603 DPRINTF(DRAMPower, "%llu,REF,0,%d\n", divCeil(curTick(), tCK) -
1604 timeStampOffset, i);
1549 }
1550
1551 // make sure we did not wait so long that we cannot make up
1552 // for it
1553 if (refreshDueAt + tREFI < ref_done_at) {
1554 fatal("Refresh was delayed so long we cannot catch up\n");
1555 }
1556

--- 84 unchanged lines hidden (view full) ---

1641 // in turn will schedule a transition to the idle power
1642 // state once the refresh is done
1643 assert(refreshState == REF_RUN);
1644 processRefreshEvent();
1645 }
1646}
1647
1648void
1605 }
1606
1607 // make sure we did not wait so long that we cannot make up
1608 // for it
1609 if (refreshDueAt + tREFI < ref_done_at) {
1610 fatal("Refresh was delayed so long we cannot catch up\n");
1611 }
1612

--- 84 unchanged lines hidden (view full) ---

1697 // in turn will schedule a transition to the idle power
1698 // state once the refresh is done
1699 assert(refreshState == REF_RUN);
1700 processRefreshEvent();
1701 }
1702}
1703
1704void
1705DRAMCtrl::updatePowerStats(uint8_t rank)
1706{
1707 // Get the energy and power from DRAMPower
1708 Data::MemoryPowerModel::Energy energy =
1709 rankPower[rank].powerlib.getEnergy();
1710 Data::MemoryPowerModel::Power power =
1711 rankPower[rank].powerlib.getPower();
1712
1713 actEnergy[rank] = energy.act_energy * devicesPerRank;
1714 preEnergy[rank] = energy.pre_energy * devicesPerRank;
1715 readEnergy[rank] = energy.read_energy * devicesPerRank;
1716 writeEnergy[rank] = energy.write_energy * devicesPerRank;
1717 refreshEnergy[rank] = energy.ref_energy * devicesPerRank;
1718 actBackEnergy[rank] = energy.act_stdby_energy * devicesPerRank;
1719 preBackEnergy[rank] = energy.pre_stdby_energy * devicesPerRank;
1720 totalEnergy[rank] = energy.total_energy * devicesPerRank;
1721 averagePower[rank] = power.average_power * devicesPerRank;
1722}
1723
1724void
1649DRAMCtrl::regStats()
1650{
1651 using namespace Stats;
1652
1653 AbstractMemory::regStats();
1654
1655 readReqs
1656 .name(name() + ".readReqs")

--- 247 unchanged lines hidden (view full) ---

1904 .init(5)
1905 .name(name() + ".memoryStateTime")
1906 .desc("Time in different power states");
1907 pwrStateTime.subname(0, "IDLE");
1908 pwrStateTime.subname(1, "REF");
1909 pwrStateTime.subname(2, "PRE_PDN");
1910 pwrStateTime.subname(3, "ACT");
1911 pwrStateTime.subname(4, "ACT_PDN");
1725DRAMCtrl::regStats()
1726{
1727 using namespace Stats;
1728
1729 AbstractMemory::regStats();
1730
1731 readReqs
1732 .name(name() + ".readReqs")

--- 247 unchanged lines hidden (view full) ---

1980 .init(5)
1981 .name(name() + ".memoryStateTime")
1982 .desc("Time in different power states");
1983 pwrStateTime.subname(0, "IDLE");
1984 pwrStateTime.subname(1, "REF");
1985 pwrStateTime.subname(2, "PRE_PDN");
1986 pwrStateTime.subname(3, "ACT");
1987 pwrStateTime.subname(4, "ACT_PDN");
1988
1989 actEnergy
1990 .init(ranksPerChannel)
1991 .name(name() + ".actEnergy")
1992 .desc("Energy for activate commands per rank (pJ)");
1993
1994 preEnergy
1995 .init(ranksPerChannel)
1996 .name(name() + ".preEnergy")
1997 .desc("Energy for precharge commands per rank (pJ)");
1998
1999 readEnergy
2000 .init(ranksPerChannel)
2001 .name(name() + ".readEnergy")
2002 .desc("Energy for read commands per rank (pJ)");
2003
2004 writeEnergy
2005 .init(ranksPerChannel)
2006 .name(name() + ".writeEnergy")
2007 .desc("Energy for write commands per rank (pJ)");
2008
2009 refreshEnergy
2010 .init(ranksPerChannel)
2011 .name(name() + ".refreshEnergy")
2012 .desc("Energy for refresh commands per rank (pJ)");
2013
2014 actBackEnergy
2015 .init(ranksPerChannel)
2016 .name(name() + ".actBackEnergy")
2017 .desc("Energy for active background per rank (pJ)");
2018
2019 preBackEnergy
2020 .init(ranksPerChannel)
2021 .name(name() + ".preBackEnergy")
2022 .desc("Energy for precharge background per rank (pJ)");
2023
2024 totalEnergy
2025 .init(ranksPerChannel)
2026 .name(name() + ".totalEnergy")
2027 .desc("Total energy per rank (pJ)");
2028
2029 averagePower
2030 .init(ranksPerChannel)
2031 .name(name() + ".averagePower")
2032 .desc("Core power per rank (mW)");
1912}
1913
1914void
1915DRAMCtrl::recvFunctional(PacketPtr pkt)
1916{
1917 // rely on the abstract memory
1918 functionalAccess(pkt);
1919}

--- 86 unchanged lines hidden ---
2033}
2034
2035void
2036DRAMCtrl::recvFunctional(PacketPtr pkt)
2037{
2038 // rely on the abstract memory
2039 functionalAccess(pkt);
2040}

--- 86 unchanged lines hidden ---