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