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 |
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), |
98 nextReqTime(0), activeRank(0), timeStampOffset(0), 99 lastStatsResetTick(0) |
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 |
747 if (ranks[dram_pkt->rank]->inRefIdleState()) { |
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; |
760 if (ranks[dram_pkt->rank]->inRefIdleState()) { |
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 |
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()) { |
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) { |
1274 if (!r->inRefIdleState()) { |
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(); |
1391 assert(dram_pkt->rankRef.inRefIdleState()); |
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 |
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. |
1453 if (!found_write) 1454 return; 1455 1456 DRAMPacket* dram_pkt = writeQueue.front(); |
1457 assert(dram_pkt->rankRef.inRefIdleState()); |
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) { |
1549 if (p->rankRef.inRefIdleState()) |
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. |
1563 assert(ranks[i]->inRefIdleState()); |
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) { |
2185 // set refresh state to REF_SREF_EXIT, ensuring inRefIdleState |
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 |
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); |
2248 |
2249 // Get the energy from DRAMPower 2250 Data::MemoryPowerModel::Energy energy = power.powerlib.getEnergy(); |
2251 |
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; |
2264 |
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); |
2276} 2277 2278void 2279DRAMCtrl::Rank::computeStats() 2280{ |
2281 DPRINTF(DRAM,"Computing stats due to a dump callback\n"); |
2282 |
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 |
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)); |
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 |
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) { |
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; |
2696 } 2697 return all_ranks_drained; 2698} 2699 2700void 2701DRAMCtrl::drainResume() 2702{ 2703 if (!isTimingMode && system()->isTimingMode()) { --- 61 unchanged lines hidden --- |