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 --- 796 unchanged lines hidden (view full) --- 805 // to complete, NOT any additional time thereafter for tRAS or 806 // tRP. 807 Tick accLat = 0; 808 Tick bankLat = 0; 809 rowHitFlag = false; 810 Tick potentialActTick; 811 812 const Bank& bank = dram_pkt->bankRef; |
813 |
814 if (bank.openRow == dram_pkt->row) { 815 // When we have a row-buffer hit, 816 // we don't care about tRAS having expired or not, 817 // but do care about bank being free for access 818 rowHitFlag = true; |
819 |
820 // When a series of requests arrive to the same row, 821 // DDR systems are capable of streaming data continuously 822 // at maximum bandwidth (subject to tCCD). Here, we approximate 823 // this condition, and assume that if whenever a bank is already 824 // busy and a new request comes in, it can be completed with no 825 // penalty beyond waiting for the existing read to complete. 826 if (bank.freeAt > inTime) { 827 accLat += bank.freeAt - inTime; 828 bankLat += 0; |
829 } else { |
830 // CAS latency only 831 accLat += tCL; 832 bankLat += tCL; 833 } 834 } else { 835 // Row-buffer miss, need to close existing row 836 // once tRAS has expired, then open the new one, 837 // then add cas latency. 838 Tick freeTime = std::max(bank.tRASDoneAt, bank.freeAt); |
839 |
840 if (freeTime > inTime) 841 accLat += freeTime - inTime; |
842 |
843 // If the there is no open row, then there is no precharge 844 // delay, otherwise go with tRP 845 Tick precharge_delay = bank.openRow == Bank::NO_ROW ? 0 : tRP; |
846 |
847 //The bank is free, and you may be able to activate |
848 potentialActTick = inTime + accLat + precharge_delay; |
849 if (potentialActTick < bank.actAllowedAt) 850 accLat += bank.actAllowedAt - potentialActTick; 851 |
852 accLat += precharge_delay + tRCD + tCL; 853 bankLat += precharge_delay + tRCD + tCL; 854 } |
855 856 DPRINTF(DRAM, "Returning < %lld, %lld > from estimateLatency()\n", 857 bankLat, accLat); 858 859 return make_pair(bankLat, accLat); 860} 861 862void --- 145 unchanged lines hidden (view full) --- 1008 // to correct for that. 1009 1010 Tick addDelay = (curTick() + accessLat < busBusyUntil) ? 1011 busBusyUntil - (curTick() + accessLat) : 0; 1012 1013 Bank& bank = dram_pkt->bankRef; 1014 1015 // Update bank state |
1016 if (rowHitFlag) { 1017 bank.freeAt = curTick() + addDelay + accessLat; 1018 } else { 1019 // If there is a page open, precharge it. 1020 if (bank.openRow != Bank::NO_ROW) { 1021 prechargeBank(bank, std::max(std::max(bank.freeAt, 1022 bank.tRASDoneAt), 1023 curTick()) + tRP); 1024 } |
1025 |
1026 // Any precharge is already part of the latency 1027 // estimation, so update the bank free time 1028 bank.freeAt = curTick() + addDelay + accessLat; |
1029 |
1030 // any waiting for banks account for in freeAt 1031 actTick = bank.freeAt - tCL - tRCD; |
1032 |
1033 // If you activated a new row do to this access, the next access 1034 // will have to respect tRAS for this bank 1035 bank.tRASDoneAt = actTick + tRAS; |
1036 |
1037 recordActivate(actTick, dram_pkt->rank, dram_pkt->bank, 1038 dram_pkt->row); 1039 } |
1040 |
1041 // increment the bytes accessed and the accesses per row 1042 bank.bytesAccessed += burstSize; 1043 ++bank.rowAccesses; |
1044 |
1045 // if we reached the max, then issue with an auto-precharge 1046 bool auto_precharge = pageMgmt == Enums::close || 1047 bank.rowAccesses == maxAccessesPerRow; |
1048 |
1049 // if we did not hit the limit, we might still want to 1050 // auto-precharge 1051 if (!auto_precharge && 1052 (pageMgmt == Enums::open_adaptive || 1053 pageMgmt == Enums::close_adaptive)) { 1054 // a twist on the open and close page policies: 1055 // 1) open_adaptive page policy does not blindly keep the 1056 // page open, but close it if there are no row hits, and there 1057 // are bank conflicts in the queue 1058 // 2) close_adaptive page policy does not blindly close the 1059 // page, but closes it only if there are no row hits in the queue. 1060 // In this case, only force an auto precharge when there 1061 // are no same page hits in the queue 1062 bool got_more_hits = false; 1063 bool got_bank_conflict = false; |
1064 |
1065 // either look at the read queue or write queue 1066 const deque<DRAMPacket*>& queue = dram_pkt->isRead ? readQueue : 1067 writeQueue; 1068 auto p = queue.begin(); 1069 // make sure we are not considering the packet that we are 1070 // currently dealing with (which is the head of the queue) 1071 ++p; |
1072 |
1073 // keep on looking until we have found required condition or 1074 // reached the end 1075 while (!(got_more_hits && 1076 (got_bank_conflict || pageMgmt == Enums::close_adaptive)) && 1077 p != queue.end()) { 1078 bool same_rank_bank = (dram_pkt->rank == (*p)->rank) && 1079 (dram_pkt->bank == (*p)->bank); 1080 bool same_row = dram_pkt->row == (*p)->row; 1081 got_more_hits |= same_rank_bank && same_row; 1082 got_bank_conflict |= same_rank_bank && !same_row; |
1083 ++p; |
1084 } 1085 |
1086 // auto pre-charge when either 1087 // 1) open_adaptive policy, we have not got any more hits, and 1088 // have a bank conflict 1089 // 2) close_adaptive policy and we have not got any more hits 1090 auto_precharge = !got_more_hits && 1091 (got_bank_conflict || pageMgmt == Enums::close_adaptive); 1092 } |
1093 |
1094 // if this access should use auto-precharge, then we are 1095 // closing the row 1096 if (auto_precharge) { 1097 prechargeBank(bank, std::max(bank.freeAt, bank.tRASDoneAt) + tRP); |
1098 |
1099 DPRINTF(DRAM, "Auto-precharged bank: %d\n", dram_pkt->bankId); 1100 } |
1101 |
1102 DPRINTF(DRAM, "doDRAMAccess::bank.freeAt is %lld\n", bank.freeAt); |
1103 |
1104 // Update request parameters 1105 dram_pkt->readyTime = curTick() + addDelay + accessLat + tBURST; 1106 |
1107 DPRINTF(DRAM, "Req %lld: curtick is %lld accessLat is %d " \ 1108 "readytime is %lld busbusyuntil is %lld. " \ 1109 "Scheduling at readyTime\n", dram_pkt->addr, 1110 curTick(), accessLat, dram_pkt->readyTime, busBusyUntil); 1111 1112 // Make sure requests are not overlapping on the databus 1113 assert(dram_pkt->readyTime - busBusyUntil >= tBURST); 1114 --- 805 unchanged lines hidden --- |