dram_ctrl.cc (10206:823f7fd1a82f) | dram_ctrl.cc (10207:3112b31596f0) |
---|---|
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 --- 42 unchanged lines hidden (view full) --- 51 52using namespace std; 53 54DRAMCtrl::DRAMCtrl(const DRAMCtrlParams* p) : 55 AbstractMemory(p), 56 port(name() + ".port", *this), 57 retryRdReq(false), retryWrReq(false), 58 rowHitFlag(false), busState(READ), | 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 --- 42 unchanged lines hidden (view full) --- 51 52using namespace std; 53 54DRAMCtrl::DRAMCtrl(const DRAMCtrlParams* p) : 55 AbstractMemory(p), 56 port(name() + ".port", *this), 57 retryRdReq(false), retryWrReq(false), 58 rowHitFlag(false), busState(READ), |
59 respondEvent(this), 60 refreshEvent(this), nextReqEvent(this), drainManager(NULL), | 59 respondEvent(this), refreshEvent(this), 60 nextReqEvent(this), drainManager(NULL), |
61 deviceBusWidth(p->device_bus_width), burstLength(p->burst_length), 62 deviceRowBufferSize(p->device_rowbuffer_size), 63 devicesPerRank(p->devices_per_rank), 64 burstSize((devicesPerRank * burstLength * deviceBusWidth) / 8), 65 rowBufferSize(devicesPerRank * deviceRowBufferSize), 66 columnsPerRowBuffer(rowBufferSize / burstSize), 67 ranksPerChannel(p->ranks_per_channel), 68 banksPerRank(p->banks_per_rank), channels(p->channels), rowsPerBank(0), --- 7 unchanged lines hidden (view full) --- 76 tRCD(p->tRCD), tCL(p->tCL), tRP(p->tRP), tRAS(p->tRAS), 77 tRFC(p->tRFC), tREFI(p->tREFI), tRRD(p->tRRD), 78 tXAW(p->tXAW), activationLimit(p->activation_limit), 79 memSchedPolicy(p->mem_sched_policy), addrMapping(p->addr_mapping), 80 pageMgmt(p->page_policy), 81 maxAccessesPerRow(p->max_accesses_per_row), 82 frontendLatency(p->static_frontend_latency), 83 backendLatency(p->static_backend_latency), | 61 deviceBusWidth(p->device_bus_width), burstLength(p->burst_length), 62 deviceRowBufferSize(p->device_rowbuffer_size), 63 devicesPerRank(p->devices_per_rank), 64 burstSize((devicesPerRank * burstLength * deviceBusWidth) / 8), 65 rowBufferSize(devicesPerRank * deviceRowBufferSize), 66 columnsPerRowBuffer(rowBufferSize / burstSize), 67 ranksPerChannel(p->ranks_per_channel), 68 banksPerRank(p->banks_per_rank), channels(p->channels), rowsPerBank(0), --- 7 unchanged lines hidden (view full) --- 76 tRCD(p->tRCD), tCL(p->tCL), tRP(p->tRP), tRAS(p->tRAS), 77 tRFC(p->tRFC), tREFI(p->tREFI), tRRD(p->tRRD), 78 tXAW(p->tXAW), activationLimit(p->activation_limit), 79 memSchedPolicy(p->mem_sched_policy), addrMapping(p->addr_mapping), 80 pageMgmt(p->page_policy), 81 maxAccessesPerRow(p->max_accesses_per_row), 82 frontendLatency(p->static_frontend_latency), 83 backendLatency(p->static_backend_latency), |
84 busBusyUntil(0), prevArrival(0), 85 nextReqTime(0), startTickPrechargeAll(0), numBanksActive(0) | 84 busBusyUntil(0), refreshDueAt(0), refreshState(REF_IDLE), prevArrival(0), 85 nextReqTime(0), idleStartTick(0), numBanksActive(0) |
86{ 87 // create the bank states based on the dimensions of the ranks and 88 // banks 89 banks.resize(ranksPerChannel); 90 actTicks.resize(ranksPerChannel); 91 for (size_t c = 0; c < ranksPerChannel; ++c) { 92 banks[c].resize(banksPerRank); 93 actTicks[c].resize(activationLimit, 0); --- 32 unchanged lines hidden (view full) --- 126 "address map\n", name()); 127 } 128 } else if (addrMapping == Enums::RoCoRaBaCh) { 129 if (system()->cacheLineSize() != range.granularity()) 130 fatal("Interleaving of %s doesn't match RoCoRaBaCh " 131 "address map\n", name()); 132 } 133 } | 86{ 87 // create the bank states based on the dimensions of the ranks and 88 // banks 89 banks.resize(ranksPerChannel); 90 actTicks.resize(ranksPerChannel); 91 for (size_t c = 0; c < ranksPerChannel; ++c) { 92 banks[c].resize(banksPerRank); 93 actTicks[c].resize(activationLimit, 0); --- 32 unchanged lines hidden (view full) --- 126 "address map\n", name()); 127 } 128 } else if (addrMapping == Enums::RoCoRaBaCh) { 129 if (system()->cacheLineSize() != range.granularity()) 130 fatal("Interleaving of %s doesn't match RoCoRaBaCh " 131 "address map\n", name()); 132 } 133 } |
134 135 // some basic sanity checks 136 if (tREFI <= tRP || tREFI <= tRFC) { 137 fatal("tREFI (%d) must be larger than tRP (%d) and tRFC (%d)\n", 138 tREFI, tRP, tRFC); 139 } |
|
134} 135 136void 137DRAMCtrl::init() 138{ 139 if (!port.isConnected()) { 140 fatal("DRAMCtrl %s is unconnected!\n", name()); 141 } else { 142 port.sendRangeChange(); 143 } 144} 145 146void 147DRAMCtrl::startup() 148{ 149 // update the start tick for the precharge accounting to the 150 // current tick | 140} 141 142void 143DRAMCtrl::init() 144{ 145 if (!port.isConnected()) { 146 fatal("DRAMCtrl %s is unconnected!\n", name()); 147 } else { 148 port.sendRangeChange(); 149 } 150} 151 152void 153DRAMCtrl::startup() 154{ 155 // update the start tick for the precharge accounting to the 156 // current tick |
151 startTickPrechargeAll = curTick(); | 157 idleStartTick = curTick(); |
152 153 // shift the bus busy time sufficiently far ahead that we never 154 // have to worry about negative values when computing the time for 155 // the next request, this will add an insignificant bubble at the 156 // start of simulation 157 busBusyUntil = curTick() + tRP + tRCD + tCL; 158 159 // print the configuration of the controller 160 printParams(); 161 | 158 159 // shift the bus busy time sufficiently far ahead that we never 160 // have to worry about negative values when computing the time for 161 // the next request, this will add an insignificant bubble at the 162 // start of simulation 163 busBusyUntil = curTick() + tRP + tRCD + tCL; 164 165 // print the configuration of the controller 166 printParams(); 167 |
162 // kick off the refresh 163 schedule(refreshEvent, curTick() + tREFI); | 168 // kick off the refresh, and give ourselves enough time to 169 // precharge 170 schedule(refreshEvent, curTick() + tREFI - tRP); |
164} 165 166Tick 167DRAMCtrl::recvAtomic(PacketPtr pkt) 168{ 169 DPRINTF(DRAM, "recvAtomic: %s 0x%x\n", pkt->cmdString(), pkt->getAddr()); 170 171 // do the actual memory access and turn the packet into a response --- 658 unchanged lines hidden (view full) --- 830 // then add cas latency. 831 Tick freeTime = std::max(bank.tRASDoneAt, bank.freeAt); 832 833 if (freeTime > inTime) 834 accLat += freeTime - inTime; 835 836 // If the there is no open row (open adaptive), then there 837 // is no precharge delay, otherwise go with tRP | 171} 172 173Tick 174DRAMCtrl::recvAtomic(PacketPtr pkt) 175{ 176 DPRINTF(DRAM, "recvAtomic: %s 0x%x\n", pkt->cmdString(), pkt->getAddr()); 177 178 // do the actual memory access and turn the packet into a response --- 658 unchanged lines hidden (view full) --- 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 (open adaptive), then there 844 // is no precharge delay, otherwise go with tRP |
838 Tick precharge_delay = bank.openRow == -1 ? 0 : tRP; | 845 Tick precharge_delay = bank.openRow == Bank::NO_ROW ? 0 : tRP; |
839 840 //The bank is free, and you may be able to activate 841 potentialActTick = inTime + accLat + precharge_delay; 842 if (potentialActTick < bank.actAllowedAt) 843 accLat += bank.actAllowedAt - potentialActTick; 844 845 accLat += precharge_delay + tRCD + tCL; 846 bankLat += precharge_delay + tRCD + tCL; --- 18 unchanged lines hidden (view full) --- 865 866 DPRINTF(DRAM, "Returning < %lld, %lld > from estimateLatency()\n", 867 bankLat, accLat); 868 869 return make_pair(bankLat, accLat); 870} 871 872void | 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; --- 18 unchanged lines hidden (view full) --- 872 873 DPRINTF(DRAM, "Returning < %lld, %lld > from estimateLatency()\n", 874 bankLat, accLat); 875 876 return make_pair(bankLat, accLat); 877} 878 879void |
873DRAMCtrl::recordActivate(Tick act_tick, uint8_t rank, uint8_t bank) | 880DRAMCtrl::recordActivate(Tick act_tick, uint8_t rank, uint8_t bank, 881 uint16_t row) |
874{ 875 assert(0 <= rank && rank < ranksPerChannel); 876 assert(actTicks[rank].size() == activationLimit); 877 878 DPRINTF(DRAM, "Activate at tick %d\n", act_tick); 879 | 882{ 883 assert(0 <= rank && rank < ranksPerChannel); 884 assert(actTicks[rank].size() == activationLimit); 885 886 DPRINTF(DRAM, "Activate at tick %d\n", act_tick); 887 |
880 // Tracking accesses after all banks are precharged. 881 // startTickPrechargeAll: is the tick when all the banks were again 882 // precharged. The difference between act_tick and startTickPrechargeAll 883 // gives the time for which DRAM doesn't get any accesses after refreshing 884 // or after a page is closed in closed-page or open-adaptive-page policy. 885 if ((numBanksActive == 0) && (act_tick > startTickPrechargeAll)) { 886 prechargeAllTime += act_tick - startTickPrechargeAll; | 888 // idleStartTick is the tick when all the banks were 889 // precharged. Thus, the difference between act_tick and 890 // idleStartTick gives the time for which the DRAM is in an idle 891 // state with all banks precharged. Note that we may end up 892 // "changing history" by scheduling an activation before an 893 // already scheduled precharge, effectively canceling it out. 894 if (numBanksActive == 0 && act_tick > idleStartTick) { 895 prechargeAllTime += act_tick - idleStartTick; |
887 } 888 | 896 } 897 |
889 // No need to update number of active banks for closed-page policy as only 1 890 // bank will be activated at any given point, which will be instatntly 891 // precharged 892 if (pageMgmt == Enums::open || pageMgmt == Enums::open_adaptive || 893 pageMgmt == Enums::close_adaptive) 894 ++numBanksActive; | 898 // update the open row 899 assert(banks[rank][bank].openRow == Bank::NO_ROW); 900 banks[rank][bank].openRow = row; |
895 | 901 |
902 // start counting anew, this covers both the case when we 903 // auto-precharged, and when this access is forced to 904 // precharge 905 banks[rank][bank].bytesAccessed = 0; 906 banks[rank][bank].rowAccesses = 0; 907 908 ++numBanksActive; 909 assert(numBanksActive <= banksPerRank * ranksPerChannel); 910 911 DPRINTF(DRAM, "Activate bank at tick %lld, now got %d active\n", 912 act_tick, numBanksActive); 913 |
|
896 // start by enforcing tRRD 897 for(int i = 0; i < banksPerRank; i++) { 898 // next activate must not happen before tRRD 899 banks[rank][i].actAllowedAt = act_tick + tRRD; 900 } 901 // tRC should be added to activation tick of the bank currently accessed, 902 // where tRC = tRAS + tRP, this is just for a check as actAllowedAt for same 903 // bank is already captured by bank.freeAt and bank.tRASDoneAt --- 27 unchanged lines hidden (view full) --- 931 "than %d\n", activationLimit, actTicks[rank].back() + tXAW); 932 for(int j = 0; j < banksPerRank; j++) 933 // next activate must not happen before end of window 934 banks[rank][j].actAllowedAt = actTicks[rank].back() + tXAW; 935 } 936} 937 938void | 914 // start by enforcing tRRD 915 for(int i = 0; i < banksPerRank; i++) { 916 // next activate must not happen before tRRD 917 banks[rank][i].actAllowedAt = act_tick + tRRD; 918 } 919 // tRC should be added to activation tick of the bank currently accessed, 920 // where tRC = tRAS + tRP, this is just for a check as actAllowedAt for same 921 // bank is already captured by bank.freeAt and bank.tRASDoneAt --- 27 unchanged lines hidden (view full) --- 949 "than %d\n", activationLimit, actTicks[rank].back() + tXAW); 950 for(int j = 0; j < banksPerRank; j++) 951 // next activate must not happen before end of window 952 banks[rank][j].actAllowedAt = actTicks[rank].back() + tXAW; 953 } 954} 955 956void |
957DRAMCtrl::prechargeBank(Bank& bank, Tick free_at) 958{ 959 // make sure the bank has an open row 960 assert(bank.openRow != Bank::NO_ROW); 961 962 // sample the bytes per activate here since we are closing 963 // the page 964 bytesPerActivate.sample(bank.bytesAccessed); 965 966 bank.openRow = Bank::NO_ROW; 967 968 bank.freeAt = free_at; 969 970 assert(numBanksActive != 0); 971 --numBanksActive; 972 973 DPRINTF(DRAM, "Precharged bank, done at tick %lld, now got %d active\n", 974 bank.freeAt, numBanksActive); 975 976 // if we reached zero, then special conditions apply as we track 977 // if all banks are precharged for the power models 978 if (numBanksActive == 0) { 979 idleStartTick = std::max(idleStartTick, bank.freeAt); 980 DPRINTF(DRAM, "All banks precharged at tick: %ld\n", 981 idleStartTick); 982 } 983} 984 985void |
|
939DRAMCtrl::doDRAMAccess(DRAMPacket* dram_pkt) 940{ 941 942 DPRINTF(DRAM, "Timing access to addr %lld, rank/bank/row %d %d %d\n", 943 dram_pkt->addr, dram_pkt->rank, dram_pkt->bank, dram_pkt->row); 944 945 // estimate the bank and access latency 946 pair<Tick, Tick> lat = estimateLatency(dram_pkt, curTick()); --- 9 unchanged lines hidden (view full) --- 956 Tick addDelay = (curTick() + accessLat < busBusyUntil) ? 957 busBusyUntil - (curTick() + accessLat) : 0; 958 959 Bank& bank = dram_pkt->bankRef; 960 961 // Update bank state 962 if (pageMgmt == Enums::open || pageMgmt == Enums::open_adaptive || 963 pageMgmt == Enums::close_adaptive) { | 986DRAMCtrl::doDRAMAccess(DRAMPacket* dram_pkt) 987{ 988 989 DPRINTF(DRAM, "Timing access to addr %lld, rank/bank/row %d %d %d\n", 990 dram_pkt->addr, dram_pkt->rank, dram_pkt->bank, dram_pkt->row); 991 992 // estimate the bank and access latency 993 pair<Tick, Tick> lat = estimateLatency(dram_pkt, curTick()); --- 9 unchanged lines hidden (view full) --- 1003 Tick addDelay = (curTick() + accessLat < busBusyUntil) ? 1004 busBusyUntil - (curTick() + accessLat) : 0; 1005 1006 Bank& bank = dram_pkt->bankRef; 1007 1008 // Update bank state 1009 if (pageMgmt == Enums::open || pageMgmt == Enums::open_adaptive || 1010 pageMgmt == Enums::close_adaptive) { |
964 bank.freeAt = curTick() + addDelay + accessLat; | |
965 | 1011 |
966 // If you activated a new row do to this access, the next access 967 // will have to respect tRAS for this bank. 968 if (!rowHitFlag) { | 1012 if (rowHitFlag) { 1013 bank.freeAt = curTick() + addDelay + accessLat; 1014 } else { 1015 // If there is a page open, precharge it. 1016 if (bank.openRow != Bank::NO_ROW) { 1017 prechargeBank(bank, std::max(std::max(bank.freeAt, 1018 bank.tRASDoneAt), 1019 curTick()) + tRP); 1020 } 1021 1022 // Any precharge is already part of the latency 1023 // estimation, so update the bank free time 1024 bank.freeAt = curTick() + addDelay + accessLat; 1025 |
969 // any waiting for banks account for in freeAt 970 actTick = bank.freeAt - tCL - tRCD; | 1026 // any waiting for banks account for in freeAt 1027 actTick = bank.freeAt - tCL - tRCD; |
1028 1029 // If you activated a new row do to this access, the next access 1030 // will have to respect tRAS for this bank |
|
971 bank.tRASDoneAt = actTick + tRAS; | 1031 bank.tRASDoneAt = actTick + tRAS; |
972 recordActivate(actTick, dram_pkt->rank, dram_pkt->bank); | |
973 | 1032 |
974 // if we closed an open row as a result of this access, 975 // then sample the number of bytes accessed before 976 // resetting it 977 if (bank.openRow != -1) 978 bytesPerActivate.sample(bank.bytesAccessed); 979 980 // update the open row 981 bank.openRow = dram_pkt->row; 982 983 // start counting anew, this covers both the case when we 984 // auto-precharged, and when this access is forced to 985 // precharge 986 bank.bytesAccessed = 0; 987 bank.rowAccesses = 0; | 1033 recordActivate(actTick, dram_pkt->rank, dram_pkt->bank, 1034 dram_pkt->row); |
988 } 989 990 // increment the bytes accessed and the accesses per row 991 bank.bytesAccessed += burstSize; 992 ++bank.rowAccesses; 993 994 // if we reached the max, then issue with an auto-precharge 995 bool auto_precharge = bank.rowAccesses == maxAccessesPerRow; --- 41 unchanged lines hidden (view full) --- 1037 // 2) close_adaptive policy and we have not got any more hits 1038 auto_precharge = !got_more_hits && 1039 (got_bank_conflict || pageMgmt == Enums::close_adaptive); 1040 } 1041 1042 // if this access should use auto-precharge, then we are 1043 // closing the row 1044 if (auto_precharge) { | 1035 } 1036 1037 // increment the bytes accessed and the accesses per row 1038 bank.bytesAccessed += burstSize; 1039 ++bank.rowAccesses; 1040 1041 // if we reached the max, then issue with an auto-precharge 1042 bool auto_precharge = bank.rowAccesses == maxAccessesPerRow; --- 41 unchanged lines hidden (view full) --- 1084 // 2) close_adaptive policy and we have not got any more hits 1085 auto_precharge = !got_more_hits && 1086 (got_bank_conflict || pageMgmt == Enums::close_adaptive); 1087 } 1088 1089 // if this access should use auto-precharge, then we are 1090 // closing the row 1091 if (auto_precharge) { |
1045 bank.openRow = -1; 1046 bank.freeAt = std::max(bank.freeAt, bank.tRASDoneAt) + tRP; 1047 --numBanksActive; 1048 if (numBanksActive == 0) { 1049 startTickPrechargeAll = std::max(startTickPrechargeAll, 1050 bank.freeAt); 1051 DPRINTF(DRAM, "All banks precharged at tick: %ld\n", 1052 startTickPrechargeAll); 1053 } | 1092 prechargeBank(bank, std::max(bank.freeAt, bank.tRASDoneAt) + tRP); |
1054 | 1093 |
1055 // sample the bytes per activate here since we are closing 1056 // the page 1057 bytesPerActivate.sample(bank.bytesAccessed); 1058 | |
1059 DPRINTF(DRAM, "Auto-precharged bank: %d\n", dram_pkt->bankId); 1060 } 1061 1062 DPRINTF(DRAM, "doDRAMAccess::bank.freeAt is %lld\n", bank.freeAt); 1063 } else if (pageMgmt == Enums::close) { 1064 actTick = curTick() + addDelay + accessLat - tRCD - tCL; | 1094 DPRINTF(DRAM, "Auto-precharged bank: %d\n", dram_pkt->bankId); 1095 } 1096 1097 DPRINTF(DRAM, "doDRAMAccess::bank.freeAt is %lld\n", bank.freeAt); 1098 } else if (pageMgmt == Enums::close) { 1099 actTick = curTick() + addDelay + accessLat - tRCD - tCL; |
1065 recordActivate(actTick, dram_pkt->rank, dram_pkt->bank); | 1100 recordActivate(actTick, dram_pkt->rank, dram_pkt->bank, dram_pkt->row); |
1066 | 1101 |
1067 // If the DRAM has a very quick tRAS, bank can be made free 1068 // after consecutive tCL,tRCD,tRP times. In general, however, 1069 // an additional wait is required to respect tRAS. 1070 bank.freeAt = std::max(actTick + tRAS + tRP, 1071 actTick + tRCD + tCL + tRP); | 1102 bank.freeAt = actTick + tRCD + tCL; 1103 bank.tRASDoneAt = actTick + tRAS; 1104 1105 // sample the relevant values when precharging 1106 bank.bytesAccessed = burstSize; 1107 bank.rowAccesses = 1; 1108 1109 prechargeBank(bank, std::max(bank.freeAt, bank.tRASDoneAt) + tRP); |
1072 DPRINTF(DRAM, "doDRAMAccess::bank.freeAt is %lld\n", bank.freeAt); | 1110 DPRINTF(DRAM, "doDRAMAccess::bank.freeAt is %lld\n", bank.freeAt); |
1073 bytesPerActivate.sample(burstSize); 1074 startTickPrechargeAll = std::max(startTickPrechargeAll, bank.freeAt); | |
1075 } else 1076 panic("No page management policy chosen\n"); 1077 1078 // Update request parameters 1079 dram_pkt->readyTime = curTick() + addDelay + accessLat + tBURST; 1080 1081 1082 DPRINTF(DRAM, "Req %lld: curtick is %lld accessLat is %d " \ --- 99 unchanged lines hidden (view full) --- 1182 "waiting\n", writesThisTime, writeQueue.size()); 1183 1184 wrPerTurnAround.sample(writesThisTime); 1185 writesThisTime = 0; 1186 1187 busState = READ; 1188 } 1189 | 1111 } else 1112 panic("No page management policy chosen\n"); 1113 1114 // Update request parameters 1115 dram_pkt->readyTime = curTick() + addDelay + accessLat + tBURST; 1116 1117 1118 DPRINTF(DRAM, "Req %lld: curtick is %lld accessLat is %d " \ --- 99 unchanged lines hidden (view full) --- 1218 "waiting\n", writesThisTime, writeQueue.size()); 1219 1220 wrPerTurnAround.sample(writesThisTime); 1221 writesThisTime = 0; 1222 1223 busState = READ; 1224 } 1225 |
1226 if (refreshState != REF_IDLE) { 1227 // if a refresh waiting for this event loop to finish, then hand 1228 // over now, and do not schedule a new nextReqEvent 1229 if (refreshState == REF_DRAIN) { 1230 DPRINTF(DRAM, "Refresh drain done, now precharging\n"); 1231 1232 refreshState = REF_PRE; 1233 1234 // hand control back to the refresh event loop 1235 schedule(refreshEvent, curTick()); 1236 } 1237 1238 // let the refresh finish before issuing any further requests 1239 return; 1240 } 1241 |
|
1190 // when we get here it is either a read or a write 1191 if (busState == READ) { 1192 1193 // track if we should switch or not 1194 bool switch_to_writes = false; 1195 1196 if (readQueue.empty()) { 1197 // In the case there is no read request to go next, --- 95 unchanged lines hidden (view full) --- 1293 // cause a nextReqEvent to be scheduled before we do so as part of 1294 // the next request processing 1295 if (retryWrReq && writeQueue.size() < writeBufferSize) { 1296 retryWrReq = false; 1297 port.sendRetry(); 1298 } 1299} 1300 | 1242 // when we get here it is either a read or a write 1243 if (busState == READ) { 1244 1245 // track if we should switch or not 1246 bool switch_to_writes = false; 1247 1248 if (readQueue.empty()) { 1249 // In the case there is no read request to go next, --- 95 unchanged lines hidden (view full) --- 1345 // cause a nextReqEvent to be scheduled before we do so as part of 1346 // the next request processing 1347 if (retryWrReq && writeQueue.size() < writeBufferSize) { 1348 retryWrReq = false; 1349 port.sendRetry(); 1350 } 1351} 1352 |
1301Tick 1302DRAMCtrl::maxBankFreeAt() const 1303{ 1304 Tick banksFree = 0; 1305 1306 for(int i = 0; i < ranksPerChannel; i++) 1307 for(int j = 0; j < banksPerRank; j++) 1308 banksFree = std::max(banks[i][j].freeAt, banksFree); 1309 1310 return banksFree; 1311} 1312 | |
1313uint64_t 1314DRAMCtrl::minBankFreeAt(const deque<DRAMPacket*>& queue) const 1315{ 1316 uint64_t bank_mask = 0; 1317 Tick freeAt = MaxTick; 1318 1319 // detemrine if we have queued transactions targetting the 1320 // bank in question --- 19 unchanged lines hidden (view full) --- 1340 } 1341 } 1342 return bank_mask; 1343} 1344 1345void 1346DRAMCtrl::processRefreshEvent() 1347{ | 1353uint64_t 1354DRAMCtrl::minBankFreeAt(const deque<DRAMPacket*>& queue) const 1355{ 1356 uint64_t bank_mask = 0; 1357 Tick freeAt = MaxTick; 1358 1359 // detemrine if we have queued transactions targetting the 1360 // bank in question --- 19 unchanged lines hidden (view full) --- 1380 } 1381 } 1382 return bank_mask; 1383} 1384 1385void 1386DRAMCtrl::processRefreshEvent() 1387{ |
1348 DPRINTF(DRAM, "Refreshing at tick %ld\n", curTick()); | 1388 // when first preparing the refresh, remember when it was due 1389 if (refreshState == REF_IDLE) { 1390 // remember when the refresh is due 1391 refreshDueAt = curTick(); |
1349 | 1392 |
1350 Tick banksFree = std::max(curTick(), maxBankFreeAt()) + tRFC; | 1393 // proceed to drain 1394 refreshState = REF_DRAIN; |
1351 | 1395 |
1352 for(int i = 0; i < ranksPerChannel; i++) 1353 for(int j = 0; j < banksPerRank; j++) { 1354 banks[i][j].freeAt = banksFree; 1355 banks[i][j].openRow = -1; | 1396 DPRINTF(DRAM, "Refresh due\n"); 1397 } 1398 1399 // let any scheduled read or write go ahead, after which it will 1400 // hand control back to this event loop 1401 if (refreshState == REF_DRAIN) { 1402 if (nextReqEvent.scheduled()) { 1403 // hand control over to the request loop until it is 1404 // evaluated next 1405 DPRINTF(DRAM, "Refresh awaiting draining\n"); 1406 1407 return; 1408 } else { 1409 refreshState = REF_PRE; |
1356 } | 1410 } |
1411 } |
|
1357 | 1412 |
1358 // updating startTickPrechargeAll, isprechargeAll 1359 numBanksActive = 0; 1360 startTickPrechargeAll = banksFree; | 1413 // at this point, ensure that all banks are precharged 1414 if (refreshState == REF_PRE) { 1415 DPRINTF(DRAM, "Precharging all\n"); |
1361 | 1416 |
1362 schedule(refreshEvent, curTick() + tREFI); | 1417 // precharge any active bank 1418 for (int i = 0; i < ranksPerChannel; i++) { 1419 for (int j = 0; j < banksPerRank; j++) { 1420 if (banks[i][j].openRow != Bank::NO_ROW) { 1421 // respect both causality and any existing bank 1422 // constraints 1423 Tick free_at = std::max(std::max(banks[i][j].freeAt, 1424 banks[i][j].tRASDoneAt), 1425 curTick()) + tRP; 1426 1427 prechargeBank(banks[i][j], free_at); 1428 } 1429 } 1430 } 1431 1432 if (numBanksActive != 0) 1433 panic("Refresh scheduled with %d active banks\n", numBanksActive); 1434 1435 // advance the state 1436 refreshState = REF_RUN; 1437 1438 // call ourselves in the future 1439 schedule(refreshEvent, std::max(curTick(), idleStartTick)); 1440 return; 1441 } 1442 1443 // last but not least we perform the actual refresh 1444 if (refreshState == REF_RUN) { 1445 // should never get here with any banks active 1446 assert(numBanksActive == 0); 1447 1448 Tick banksFree = curTick() + tRFC; 1449 1450 for (int i = 0; i < ranksPerChannel; i++) { 1451 for (int j = 0; j < banksPerRank; j++) { 1452 banks[i][j].freeAt = banksFree; 1453 } 1454 } 1455 1456 // make sure we did not wait so long that we cannot make up 1457 // for it 1458 if (refreshDueAt + tREFI < banksFree) { 1459 fatal("Refresh was delayed so long we cannot catch up\n"); 1460 } 1461 1462 // compensate for the delay in actually performing the refresh 1463 // when scheduling the next one 1464 schedule(refreshEvent, refreshDueAt + tREFI - tRP); 1465 1466 // back to business as usual 1467 refreshState = REF_IDLE; 1468 1469 // we are now refreshing until tRFC is done 1470 idleStartTick = banksFree; 1471 1472 // kick the normal request processing loop into action again 1473 // as early as possible, i.e. when the request is done, the 1474 // scheduling of this event also prevents any new requests 1475 // from going ahead before the scheduled point in time 1476 nextReqTime = banksFree; 1477 schedule(nextReqEvent, nextReqTime); 1478 } |
1363} 1364 1365void 1366DRAMCtrl::regStats() 1367{ 1368 using namespace Stats; 1369 1370 AbstractMemory::regStats(); --- 361 unchanged lines hidden --- | 1479} 1480 1481void 1482DRAMCtrl::regStats() 1483{ 1484 using namespace Stats; 1485 1486 AbstractMemory::regStats(); --- 361 unchanged lines hidden --- |