dram_ctrl.cc (12084:5a3769ff3d55) dram_ctrl.cc (12266:63b8da9eeca4)
1/*
2 * Copyright (c) 2010-2017 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

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

37 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
38 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
39 *
40 * Authors: Andreas Hansson
41 * Ani Udipi
42 * Neha Agarwal
43 * Omar Naji
44 * Wendy Elsasser
1/*
2 * Copyright (c) 2010-2017 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

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

37 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
38 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
39 *
40 * Authors: Andreas Hansson
41 * Ani Udipi
42 * Neha Agarwal
43 * Omar Naji
44 * Wendy Elsasser
45 * Radhika Jagtap
45 */
46
47#include "mem/dram_ctrl.hh"
48
49#include "base/bitfield.hh"
50#include "base/trace.hh"
51#include "debug/DRAM.hh"
52#include "debug/DRAMPower.hh"

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

89 tRRD_L(p->tRRD_L), tXAW(p->tXAW), tXP(p->tXP), tXS(p->tXS),
90 activationLimit(p->activation_limit),
91 memSchedPolicy(p->mem_sched_policy), addrMapping(p->addr_mapping),
92 pageMgmt(p->page_policy),
93 maxAccessesPerRow(p->max_accesses_per_row),
94 frontendLatency(p->static_frontend_latency),
95 backendLatency(p->static_backend_latency),
96 busBusyUntil(0), prevArrival(0),
46 */
47
48#include "mem/dram_ctrl.hh"
49
50#include "base/bitfield.hh"
51#include "base/trace.hh"
52#include "debug/DRAM.hh"
53#include "debug/DRAMPower.hh"

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

90 tRRD_L(p->tRRD_L), tXAW(p->tXAW), tXP(p->tXP), tXS(p->tXS),
91 activationLimit(p->activation_limit),
92 memSchedPolicy(p->mem_sched_policy), addrMapping(p->addr_mapping),
93 pageMgmt(p->page_policy),
94 maxAccessesPerRow(p->max_accesses_per_row),
95 frontendLatency(p->static_frontend_latency),
96 backendLatency(p->static_backend_latency),
97 busBusyUntil(0), prevArrival(0),
97 nextReqTime(0), activeRank(0), timeStampOffset(0)
98 nextReqTime(0), activeRank(0), timeStampOffset(0),
99 lastStatsResetTick(0)
98{
99 // sanity check the ranks since we rely on bit slicing for the
100 // address decoding
101 fatal_if(!isPowerOf2(ranksPerChannel), "DRAM rank count of %d is not "
102 "allowed, must be a power of two\n", ranksPerChannel);
103
104 fatal_if(!isPowerOf2(burstSize), "DRAM burst size %d is not allowed, "
105 "must be a power of two\n", burstSize);

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

737 // FCFS, this method does nothing
738 assert(!queue.empty());
739
740 // bool to indicate if a packet to an available rank is found
741 bool found_packet = false;
742 if (queue.size() == 1) {
743 DRAMPacket* dram_pkt = queue.front();
744 // available rank corresponds to state refresh idle
100{
101 // sanity check the ranks since we rely on bit slicing for the
102 // address decoding
103 fatal_if(!isPowerOf2(ranksPerChannel), "DRAM rank count of %d is not "
104 "allowed, must be a power of two\n", ranksPerChannel);
105
106 fatal_if(!isPowerOf2(burstSize), "DRAM burst size %d is not allowed, "
107 "must be a power of two\n", burstSize);

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

739 // FCFS, this method does nothing
740 assert(!queue.empty());
741
742 // bool to indicate if a packet to an available rank is found
743 bool found_packet = false;
744 if (queue.size() == 1) {
745 DRAMPacket* dram_pkt = queue.front();
746 // available rank corresponds to state refresh idle
745 if (ranks[dram_pkt->rank]->isAvailable()) {
747 if (ranks[dram_pkt->rank]->inRefIdleState()) {
746 found_packet = true;
747 DPRINTF(DRAM, "Single request, going to a free rank\n");
748 } else {
749 DPRINTF(DRAM, "Single request, going to a busy rank\n");
750 }
751 return found_packet;
752 }
753
754 if (memSchedPolicy == Enums::fcfs) {
755 // check if there is a packet going to a free rank
756 for (auto i = queue.begin(); i != queue.end() ; ++i) {
757 DRAMPacket* dram_pkt = *i;
748 found_packet = true;
749 DPRINTF(DRAM, "Single request, going to a free rank\n");
750 } else {
751 DPRINTF(DRAM, "Single request, going to a busy rank\n");
752 }
753 return found_packet;
754 }
755
756 if (memSchedPolicy == Enums::fcfs) {
757 // check if there is a packet going to a free rank
758 for (auto i = queue.begin(); i != queue.end() ; ++i) {
759 DRAMPacket* dram_pkt = *i;
758 if (ranks[dram_pkt->rank]->isAvailable()) {
760 if (ranks[dram_pkt->rank]->inRefIdleState()) {
759 queue.erase(i);
760 queue.push_front(dram_pkt);
761 found_packet = true;
762 break;
763 }
764 }
765 } else if (memSchedPolicy == Enums::frfcfs) {
766 found_packet = reorderQueue(queue, extra_col_delay);

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

796 // time we need to issue a column command to be seamless
797 const Tick min_col_at = std::max(busBusyUntil - tCL + extra_col_delay,
798 curTick());
799
800 for (auto i = queue.begin(); i != queue.end() ; ++i) {
801 DRAMPacket* dram_pkt = *i;
802 const Bank& bank = dram_pkt->bankRef;
803
761 queue.erase(i);
762 queue.push_front(dram_pkt);
763 found_packet = true;
764 break;
765 }
766 }
767 } else if (memSchedPolicy == Enums::frfcfs) {
768 found_packet = reorderQueue(queue, extra_col_delay);

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

798 // time we need to issue a column command to be seamless
799 const Tick min_col_at = std::max(busBusyUntil - tCL + extra_col_delay,
800 curTick());
801
802 for (auto i = queue.begin(); i != queue.end() ; ++i) {
803 DRAMPacket* dram_pkt = *i;
804 const Bank& bank = dram_pkt->bankRef;
805
804 // check if rank is available, if not, jump to the next packet
805 if (dram_pkt->rankRef.isAvailable()) {
806 // check if rank is not doing a refresh and thus is available, if not,
807 // jump to the next packet
808 if (dram_pkt->rankRef.inRefIdleState()) {
806 // check if it is a row hit
807 if (bank.openRow == dram_pkt->row) {
808 // no additional rank-to-rank or same bank-group
809 // delays, or we switched read/write and might as well
810 // go for the row hit
811 if (bank.colAllowedAt <= min_col_at) {
812 // FCFS within the hits, giving priority to
813 // commands that can issue seamlessly, without

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

1263 }
1264}
1265
1266void
1267DRAMCtrl::processNextReqEvent()
1268{
1269 int busyRanks = 0;
1270 for (auto r : ranks) {
809 // check if it is a row hit
810 if (bank.openRow == dram_pkt->row) {
811 // no additional rank-to-rank or same bank-group
812 // delays, or we switched read/write and might as well
813 // go for the row hit
814 if (bank.colAllowedAt <= min_col_at) {
815 // FCFS within the hits, giving priority to
816 // commands that can issue seamlessly, without

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

1266 }
1267}
1268
1269void
1270DRAMCtrl::processNextReqEvent()
1271{
1272 int busyRanks = 0;
1273 for (auto r : ranks) {
1271 if (!r->isAvailable()) {
1274 if (!r->inRefIdleState()) {
1272 if (r->pwrState != PWR_SREF) {
1273 // rank is busy refreshing
1274 DPRINTF(DRAMState, "Rank %d is not available\n", r->rank);
1275 busyRanks++;
1276
1277 // let the rank know that if it was waiting to drain, it
1278 // is now done and ready to proceed
1279 r->checkDrainDone();

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

1380 // at this point. There could be writes to the available ranks
1381 // which are above the required threshold. However, to
1382 // avoid adding more complexity to the code, return and wait
1383 // for a refresh event to kick things into action again.
1384 if (!found_read)
1385 return;
1386
1387 DRAMPacket* dram_pkt = readQueue.front();
1275 if (r->pwrState != PWR_SREF) {
1276 // rank is busy refreshing
1277 DPRINTF(DRAMState, "Rank %d is not available\n", r->rank);
1278 busyRanks++;
1279
1280 // let the rank know that if it was waiting to drain, it
1281 // is now done and ready to proceed
1282 r->checkDrainDone();

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

1383 // at this point. There could be writes to the available ranks
1384 // which are above the required threshold. However, to
1385 // avoid adding more complexity to the code, return and wait
1386 // for a refresh event to kick things into action again.
1387 if (!found_read)
1388 return;
1389
1390 DRAMPacket* dram_pkt = readQueue.front();
1388 assert(dram_pkt->rankRef.isAvailable());
1391 assert(dram_pkt->rankRef.inRefIdleState());
1389
1390 // here we get a bit creative and shift the bus busy time not
1391 // just the tWTR, but also a CAS latency to capture the fact
1392 // that we are allowed to prepare a new bank, but not issue a
1393 // read command until after tWTR, in essence we capture a
1394 // bubble on the data bus that is tWTR + tCL
1395 if (switched_cmd_type && dram_pkt->rank == activeRank) {
1396 busBusyUntil += tWTR + tCL;

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

1437 // bool to check if write to free rank is found
1438 bool found_write = false;
1439
1440 // If we are changing command type, incorporate the minimum
1441 // bus turnaround delay
1442 found_write = chooseNext(writeQueue,
1443 switched_cmd_type ? std::min(tRTW, tCS) : 0);
1444
1392
1393 // here we get a bit creative and shift the bus busy time not
1394 // just the tWTR, but also a CAS latency to capture the fact
1395 // that we are allowed to prepare a new bank, but not issue a
1396 // read command until after tWTR, in essence we capture a
1397 // bubble on the data bus that is tWTR + tCL
1398 if (switched_cmd_type && dram_pkt->rank == activeRank) {
1399 busBusyUntil += tWTR + tCL;

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

1440 // bool to check if write to free rank is found
1441 bool found_write = false;
1442
1443 // If we are changing command type, incorporate the minimum
1444 // bus turnaround delay
1445 found_write = chooseNext(writeQueue,
1446 switched_cmd_type ? std::min(tRTW, tCS) : 0);
1447
1445 // if no writes to an available rank are found then return.
1446 // There could be reads to the available ranks. However, to avoid
1447 // adding more complexity to the code, return at this point and wait
1448 // for a refresh event to kick things into action again.
1448 // if there are no writes to a rank that is available to service
1449 // requests (i.e. rank is in refresh idle state) are found then
1450 // return. There could be reads to the available ranks. However, to
1451 // avoid adding more complexity to the code, return at this point and
1452 // wait for a refresh event to kick things into action again.
1449 if (!found_write)
1450 return;
1451
1452 DRAMPacket* dram_pkt = writeQueue.front();
1453 if (!found_write)
1454 return;
1455
1456 DRAMPacket* dram_pkt = writeQueue.front();
1453 assert(dram_pkt->rankRef.isAvailable());
1457 assert(dram_pkt->rankRef.inRefIdleState());
1454 // sanity check
1455 assert(dram_pkt->size <= burstSize);
1456
1457 // add a bubble to the data bus, as defined by the
1458 // tRTW when access is to the same rank as previous burst
1459 // Different rank timing is handled with tCS, which is
1460 // applied to colAllowedAt
1461 if (switched_cmd_type && dram_pkt->rank == activeRank) {

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

1537 // Flag condition when bank can be opened without incurring additional
1538 // delay on the data bus
1539 bool hidden_bank_prep = false;
1540
1541 // determine if we have queued transactions targetting the
1542 // bank in question
1543 vector<bool> got_waiting(ranksPerChannel * banksPerRank, false);
1544 for (const auto& p : queue) {
1458 // sanity check
1459 assert(dram_pkt->size <= burstSize);
1460
1461 // add a bubble to the data bus, as defined by the
1462 // tRTW when access is to the same rank as previous burst
1463 // Different rank timing is handled with tCS, which is
1464 // applied to colAllowedAt
1465 if (switched_cmd_type && dram_pkt->rank == activeRank) {

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

1541 // Flag condition when bank can be opened without incurring additional
1542 // delay on the data bus
1543 bool hidden_bank_prep = false;
1544
1545 // determine if we have queued transactions targetting the
1546 // bank in question
1547 vector<bool> got_waiting(ranksPerChannel * banksPerRank, false);
1548 for (const auto& p : queue) {
1545 if (p->rankRef.isAvailable())
1549 if (p->rankRef.inRefIdleState())
1546 got_waiting[p->bankId] = true;
1547 }
1548
1549 // Find command with optimal bank timing
1550 // Will prioritize commands that can issue seamlessly.
1551 for (int i = 0; i < ranksPerChannel; i++) {
1552 for (int j = 0; j < banksPerRank; j++) {
1553 uint16_t bank_id = i * banksPerRank + j;
1554
1555 // if we have waiting requests for the bank, and it is
1556 // amongst the first available, update the mask
1557 if (got_waiting[bank_id]) {
1558 // make sure this rank is not currently refreshing.
1550 got_waiting[p->bankId] = true;
1551 }
1552
1553 // Find command with optimal bank timing
1554 // Will prioritize commands that can issue seamlessly.
1555 for (int i = 0; i < ranksPerChannel; i++) {
1556 for (int j = 0; j < banksPerRank; j++) {
1557 uint16_t bank_id = i * banksPerRank + j;
1558
1559 // if we have waiting requests for the bank, and it is
1560 // amongst the first available, update the mask
1561 if (got_waiting[bank_id]) {
1562 // make sure this rank is not currently refreshing.
1559 assert(ranks[i]->isAvailable());
1563 assert(ranks[i]->inRefIdleState());
1560 // simplistic approximation of when the bank can issue
1561 // an activate, ignoring any rank-to-rank switching
1562 // cost in this calculation
1563 Tick act_at = ranks[i]->banks[j].openRow == Bank::NO_ROW ?
1564 std::max(ranks[i]->banks[j].actAllowedAt, curTick()) :
1565 std::max(ranks[i]->banks[j].preAllowedAt, curTick()) + tRP;
1566
1567 // When is the earliest the R/W burst can issue?

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

2173
2174 // go back to REF event and close banks
2175 refreshState = REF_PRE;
2176 schedule(refreshEvent, curTick());
2177 }
2178 } else if (pwrState == PWR_IDLE) {
2179 DPRINTF(DRAMState, "All banks precharged\n");
2180 if (prev_state == PWR_SREF) {
1564 // simplistic approximation of when the bank can issue
1565 // an activate, ignoring any rank-to-rank switching
1566 // cost in this calculation
1567 Tick act_at = ranks[i]->banks[j].openRow == Bank::NO_ROW ?
1568 std::max(ranks[i]->banks[j].actAllowedAt, curTick()) :
1569 std::max(ranks[i]->banks[j].preAllowedAt, curTick()) + tRP;
1570
1571 // When is the earliest the R/W burst can issue?

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

2177
2178 // go back to REF event and close banks
2179 refreshState = REF_PRE;
2180 schedule(refreshEvent, curTick());
2181 }
2182 } else if (pwrState == PWR_IDLE) {
2183 DPRINTF(DRAMState, "All banks precharged\n");
2184 if (prev_state == PWR_SREF) {
2181 // set refresh state to REF_SREF_EXIT, ensuring isAvailable
2185 // set refresh state to REF_SREF_EXIT, ensuring inRefIdleState
2182 // continues to return false during tXS after SREF exit
2183 // Schedule a refresh which kicks things back into action
2184 // when it finishes
2185 refreshState = REF_SREF_EXIT;
2186 schedule(refreshEvent, curTick() + memory.tXS);
2187 } else {
2188 // if we have a pending refresh, and are now moving to
2189 // the idle state, directly transition to a refresh

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

2230
2231void
2232DRAMCtrl::Rank::updatePowerStats()
2233{
2234 // All commands up to refresh have completed
2235 // flush cmdList to DRAMPower
2236 flushCmdList();
2237
2186 // continues to return false during tXS after SREF exit
2187 // Schedule a refresh which kicks things back into action
2188 // when it finishes
2189 refreshState = REF_SREF_EXIT;
2190 schedule(refreshEvent, curTick() + memory.tXS);
2191 } else {
2192 // if we have a pending refresh, and are now moving to
2193 // the idle state, directly transition to a refresh

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

2234
2235void
2236DRAMCtrl::Rank::updatePowerStats()
2237{
2238 // All commands up to refresh have completed
2239 // flush cmdList to DRAMPower
2240 flushCmdList();
2241
2238 // update the counters for DRAMPower, passing false to
2239 // indicate that this is not the last command in the
2240 // list. DRAMPower requires this information for the
2241 // correct calculation of the background energy at the end
2242 // of the simulation. Ideally we would want to call this
2243 // function with true once at the end of the
2244 // simulation. However, the discarded energy is extremly
2245 // small and does not effect the final results.
2246 power.powerlib.updateCounters(false);
2242 // Call the function that calculates window energy at intermediate update
2243 // events like at refresh, stats dump as well as at simulation exit.
2244 // Window starts at the last time the calcWindowEnergy function was called
2245 // and is upto current time.
2246 power.powerlib.calcWindowEnergy(divCeil(curTick(), memory.tCK) -
2247 memory.timeStampOffset);
2247
2248
2248 // call the energy function
2249 power.powerlib.calcEnergy();
2249 // Get the energy from DRAMPower
2250 Data::MemoryPowerModel::Energy energy = power.powerlib.getEnergy();
2250
2251
2251 // Get the energy and power from DRAMPower
2252 Data::MemoryPowerModel::Energy energy =
2253 power.powerlib.getEnergy();
2254 Data::MemoryPowerModel::Power rank_power =
2255 power.powerlib.getPower();
2252 // The energy components inside the power lib are calculated over
2253 // the window so accumulate into the corresponding gem5 stat
2254 actEnergy += energy.act_energy * memory.devicesPerRank;
2255 preEnergy += energy.pre_energy * memory.devicesPerRank;
2256 readEnergy += energy.read_energy * memory.devicesPerRank;
2257 writeEnergy += energy.write_energy * memory.devicesPerRank;
2258 refreshEnergy += energy.ref_energy * memory.devicesPerRank;
2259 actBackEnergy += energy.act_stdby_energy * memory.devicesPerRank;
2260 preBackEnergy += energy.pre_stdby_energy * memory.devicesPerRank;
2261 actPowerDownEnergy += energy.f_act_pd_energy * memory.devicesPerRank;
2262 prePowerDownEnergy += energy.f_pre_pd_energy * memory.devicesPerRank;
2263 selfRefreshEnergy += energy.sref_energy * memory.devicesPerRank;
2256
2264
2257 actEnergy = energy.act_energy * memory.devicesPerRank;
2258 preEnergy = energy.pre_energy * memory.devicesPerRank;
2259 readEnergy = energy.read_energy * memory.devicesPerRank;
2260 writeEnergy = energy.write_energy * memory.devicesPerRank;
2261 refreshEnergy = energy.ref_energy * memory.devicesPerRank;
2262 actBackEnergy = energy.act_stdby_energy * memory.devicesPerRank;
2263 preBackEnergy = energy.pre_stdby_energy * memory.devicesPerRank;
2264 actPowerDownEnergy = energy.f_act_pd_energy * memory.devicesPerRank;
2265 prePowerDownEnergy = energy.f_pre_pd_energy * memory.devicesPerRank;
2266 selfRefreshEnergy = energy.sref_energy * memory.devicesPerRank;
2267 totalEnergy = energy.total_energy * memory.devicesPerRank;
2268 averagePower = rank_power.average_power * memory.devicesPerRank;
2265 // Accumulate window energy into the total energy.
2266 totalEnergy += energy.window_energy * memory.devicesPerRank;
2267 // Average power must not be accumulated but calculated over the time
2268 // since last stats reset. SimClock::Frequency is tick period not tick
2269 // frequency.
2270 // energy (pJ) 1e-9
2271 // power (mW) = ----------- * ----------
2272 // time (tick) tick_frequency
2273 averagePower = (totalEnergy.value() /
2274 (curTick() - memory.lastStatsResetTick)) *
2275 (SimClock::Frequency / 1000000000.0);
2269}
2270
2271void
2272DRAMCtrl::Rank::computeStats()
2273{
2276}
2277
2278void
2279DRAMCtrl::Rank::computeStats()
2280{
2274 DPRINTF(DRAM,"Computing final stats\n");
2281 DPRINTF(DRAM,"Computing stats due to a dump callback\n");
2275
2282
2276 // Force DRAM power to update counters based on time spent in
2277 // current state up to curTick()
2278 cmdList.push_back(Command(MemCommand::NOP, 0, curTick()));
2279
2280 // Update the stats
2281 updatePowerStats();
2282
2283 // final update of power state times
2284 pwrStateTime[pwrState] += (curTick() - pwrStateTick);
2285 pwrStateTick = curTick();
2286
2287}
2288
2289void
2283 // Update the stats
2284 updatePowerStats();
2285
2286 // final update of power state times
2287 pwrStateTime[pwrState] += (curTick() - pwrStateTick);
2288 pwrStateTick = curTick();
2289
2290}
2291
2292void
2293DRAMCtrl::Rank::resetStats() {
2294 // The only way to clear the counters in DRAMPower is to call
2295 // calcWindowEnergy function as that then calls clearCounters. The
2296 // clearCounters method itself is private.
2297 power.powerlib.calcWindowEnergy(divCeil(curTick(), memory.tCK) -
2298 memory.timeStampOffset);
2299
2300}
2301
2302void
2290DRAMCtrl::Rank::regStats()
2291{
2292 using namespace Stats;
2293
2294 pwrStateTime
2295 .init(6)
2296 .name(name() + ".memoryStateTime")
2297 .desc("Time in different power states");

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

2350 .name(name() + ".averagePower")
2351 .desc("Core power per rank (mW)");
2352
2353 totalIdleTime
2354 .name(name() + ".totalIdleTime")
2355 .desc("Total Idle time Per DRAM Rank");
2356
2357 registerDumpCallback(new RankDumpCallback(this));
2303DRAMCtrl::Rank::regStats()
2304{
2305 using namespace Stats;
2306
2307 pwrStateTime
2308 .init(6)
2309 .name(name() + ".memoryStateTime")
2310 .desc("Time in different power states");

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

2363 .name(name() + ".averagePower")
2364 .desc("Core power per rank (mW)");
2365
2366 totalIdleTime
2367 .name(name() + ".totalIdleTime")
2368 .desc("Total Idle time Per DRAM Rank");
2369
2370 registerDumpCallback(new RankDumpCallback(this));
2371 registerResetCallback(new RankResetCallback(this));
2358}
2359void
2360DRAMCtrl::regStats()
2361{
2362 using namespace Stats;
2363
2364 AbstractMemory::regStats();
2365
2366 for (auto r : ranks) {
2367 r->regStats();
2368 }
2369
2372}
2373void
2374DRAMCtrl::regStats()
2375{
2376 using namespace Stats;
2377
2378 AbstractMemory::regStats();
2379
2380 for (auto r : ranks) {
2381 r->regStats();
2382 }
2383
2384 registerResetCallback(new MemResetCallback(this));
2385
2370 readReqs
2371 .name(name() + ".readReqs")
2372 .desc("Number of read requests accepted");
2373
2374 writeReqs
2375 .name(name() + ".writeReqs")
2376 .desc("Number of write requests accepted");
2377

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

2667}
2668
2669bool
2670DRAMCtrl::allRanksDrained() const
2671{
2672 // true until proven false
2673 bool all_ranks_drained = true;
2674 for (auto r : ranks) {
2386 readReqs
2387 .name(name() + ".readReqs")
2388 .desc("Number of read requests accepted");
2389
2390 writeReqs
2391 .name(name() + ".writeReqs")
2392 .desc("Number of write requests accepted");
2393

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

2683}
2684
2685bool
2686DRAMCtrl::allRanksDrained() const
2687{
2688 // true until proven false
2689 bool all_ranks_drained = true;
2690 for (auto r : ranks) {
2675 // then verify that the power state is IDLE
2676 // ensuring all banks are closed and rank is not in a low power state
2677 all_ranks_drained = r->inPwrIdleState() && all_ranks_drained;
2691 // then verify that the power state is IDLE ensuring all banks are
2692 // closed and rank is not in a low power state. Also verify that rank
2693 // is idle from a refresh point of view.
2694 all_ranks_drained = r->inPwrIdleState() && r->inRefIdleState() &&
2695 all_ranks_drained;
2678 }
2679 return all_ranks_drained;
2680}
2681
2682void
2683DRAMCtrl::drainResume()
2684{
2685 if (!isTimingMode && system()->isTimingMode()) {

--- 61 unchanged lines hidden ---
2696 }
2697 return all_ranks_drained;
2698}
2699
2700void
2701DRAMCtrl::drainResume()
2702{
2703 if (!isTimingMode && system()->isTimingMode()) {

--- 61 unchanged lines hidden ---