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