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 --- |