dram_ctrl.cc (10210:793e5ff26e0b) | dram_ctrl.cc (10211:e084db2b1527) |
---|---|
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#include "sim/system.hh" 52 53using namespace std; 54 55DRAMCtrl::DRAMCtrl(const DRAMCtrlParams* p) : 56 AbstractMemory(p), 57 port(name() + ".port", *this), 58 retryRdReq(false), retryWrReq(false), | 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#include "sim/system.hh" 52 53using namespace std; 54 55DRAMCtrl::DRAMCtrl(const DRAMCtrlParams* p) : 56 AbstractMemory(p), 57 port(name() + ".port", *this), 58 retryRdReq(false), retryWrReq(false), |
59 rowHitFlag(false), busState(READ), | 59 busState(READ), |
60 nextReqEvent(this), respondEvent(this), activateEvent(this), 61 prechargeEvent(this), refreshEvent(this), powerEvent(this), 62 drainManager(NULL), 63 deviceBusWidth(p->device_bus_width), burstLength(p->burst_length), 64 deviceRowBufferSize(p->device_rowbuffer_size), 65 devicesPerRank(p->devices_per_rank), 66 burstSize((devicesPerRank * burstLength * deviceBusWidth) / 8), 67 rowBufferSize(devicesPerRank * deviceRowBufferSize), --- 667 unchanged lines hidden (view full) --- 735 bool found_earliest_pkt = false; 736 auto selected_pkt_it = queue.begin(); 737 738 for (auto i = queue.begin(); i != queue.end() ; ++i) { 739 DRAMPacket* dram_pkt = *i; 740 const Bank& bank = dram_pkt->bankRef; 741 // Check if it is a row hit 742 if (bank.openRow == dram_pkt->row) { | 60 nextReqEvent(this), respondEvent(this), activateEvent(this), 61 prechargeEvent(this), refreshEvent(this), powerEvent(this), 62 drainManager(NULL), 63 deviceBusWidth(p->device_bus_width), burstLength(p->burst_length), 64 deviceRowBufferSize(p->device_rowbuffer_size), 65 devicesPerRank(p->devices_per_rank), 66 burstSize((devicesPerRank * burstLength * deviceBusWidth) / 8), 67 rowBufferSize(devicesPerRank * deviceRowBufferSize), --- 667 unchanged lines hidden (view full) --- 735 bool found_earliest_pkt = false; 736 auto selected_pkt_it = queue.begin(); 737 738 for (auto i = queue.begin(); i != queue.end() ; ++i) { 739 DRAMPacket* dram_pkt = *i; 740 const Bank& bank = dram_pkt->bankRef; 741 // Check if it is a row hit 742 if (bank.openRow == dram_pkt->row) { |
743 // FCFS within the hits |
|
743 DPRINTF(DRAM, "Row buffer hit\n"); 744 selected_pkt_it = i; 745 break; 746 } else if (!found_earliest_pkt) { 747 // No row hit, go for first ready 748 if (earliest_banks == 0) | 744 DPRINTF(DRAM, "Row buffer hit\n"); 745 selected_pkt_it = i; 746 break; 747 } else if (!found_earliest_pkt) { 748 // No row hit, go for first ready 749 if (earliest_banks == 0) |
749 earliest_banks = minBankFreeAt(queue); | 750 earliest_banks = minBankActAt(queue); |
750 | 751 |
752 // simplistic approximation of when the bank can issue an 753 // activate, this is calculated in minBankActAt and could 754 // be cached 755 Tick act_at = bank.openRow == Bank::NO_ROW ? 756 bank.actAllowedAt : 757 std::max(bank.preAllowedAt, curTick()) + tRP; 758 |
|
751 // Bank is ready or is the first available bank | 759 // Bank is ready or is the first available bank |
752 if (bank.freeAt <= curTick() || | 760 if (act_at <= curTick() || |
753 bits(earliest_banks, dram_pkt->bankId, dram_pkt->bankId)) { 754 // Remember the packet to be scheduled to one of the earliest | 761 bits(earliest_banks, dram_pkt->bankId, dram_pkt->bankId)) { 762 // Remember the packet to be scheduled to one of the earliest |
755 // banks available | 763 // banks available, FCFS amongst the earliest banks |
756 selected_pkt_it = i; 757 found_earliest_pkt = true; 758 } 759 } 760 } 761 762 DRAMPacket* selected_pkt = *selected_pkt_it; 763 queue.erase(selected_pkt_it); --- 27 unchanged lines hidden (view full) --- 791 pendingDelete.push_back(pkt); 792 } 793 794 DPRINTF(DRAM, "Done\n"); 795 796 return; 797} 798 | 764 selected_pkt_it = i; 765 found_earliest_pkt = true; 766 } 767 } 768 } 769 770 DRAMPacket* selected_pkt = *selected_pkt_it; 771 queue.erase(selected_pkt_it); --- 27 unchanged lines hidden (view full) --- 799 pendingDelete.push_back(pkt); 800 } 801 802 DPRINTF(DRAM, "Done\n"); 803 804 return; 805} 806 |
799pair<Tick, Tick> 800DRAMCtrl::estimateLatency(DRAMPacket* dram_pkt, Tick inTime) 801{ 802 // If a request reaches a bank at tick 'inTime', how much time 803 // *after* that does it take to finish the request, depending 804 // on bank status and page open policy. Note that this method 805 // considers only the time taken for the actual read or write 806 // to complete, NOT any additional time thereafter for tRAS or 807 // tRP. 808 Tick accLat = 0; 809 Tick bankLat = 0; 810 rowHitFlag = false; 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 potentially close an existing row, 836 // then open the new one, then add CAS latency 837 Tick free_at = bank.freeAt; 838 Tick precharge_delay = 0; 839 840 // Check if we first need to precharge 841 if (bank.openRow != Bank::NO_ROW) { 842 free_at = std::max(bank.preAllowedAt, free_at); 843 precharge_delay = tRP; 844 } 845 846 // If the earliest time to issue the command is in the future, 847 // add it to the access latency 848 if (free_at > inTime) 849 accLat += free_at - inTime; 850 851 // We also need to account for the earliest activation time, 852 // and potentially add that as well to the access latency 853 Tick act_at = inTime + accLat + precharge_delay; 854 if (act_at < bank.actAllowedAt) 855 accLat += bank.actAllowedAt - act_at; 856 857 accLat += precharge_delay + tRCD + tCL; 858 bankLat += precharge_delay + tRCD + tCL; 859 } 860 861 DPRINTF(DRAM, "Returning < %lld, %lld > from estimateLatency()\n", 862 bankLat, accLat); 863 864 return make_pair(bankLat, accLat); 865} 866 | |
867void 868DRAMCtrl::activateBank(Tick act_tick, uint8_t rank, uint8_t bank, 869 uint16_t row, Bank& bank_ref) 870{ 871 assert(0 <= rank && rank < ranksPerChannel); 872 assert(actTicks[rank].size() == activationLimit); 873 874 DPRINTF(DRAM, "Activate at tick %d\n", act_tick); --- 9 unchanged lines hidden (view full) --- 884 bank_ref.rowAccesses = 0; 885 886 ++numBanksActive; 887 assert(numBanksActive <= banksPerRank * ranksPerChannel); 888 889 DPRINTF(DRAM, "Activate bank at tick %lld, now got %d active\n", 890 act_tick, numBanksActive); 891 | 807void 808DRAMCtrl::activateBank(Tick act_tick, uint8_t rank, uint8_t bank, 809 uint16_t row, Bank& bank_ref) 810{ 811 assert(0 <= rank && rank < ranksPerChannel); 812 assert(actTicks[rank].size() == activationLimit); 813 814 DPRINTF(DRAM, "Activate at tick %d\n", act_tick); --- 9 unchanged lines hidden (view full) --- 824 bank_ref.rowAccesses = 0; 825 826 ++numBanksActive; 827 assert(numBanksActive <= banksPerRank * ranksPerChannel); 828 829 DPRINTF(DRAM, "Activate bank at tick %lld, now got %d active\n", 830 act_tick, numBanksActive); 831 |
832 // The next access has to respect tRAS for this bank 833 bank_ref.preAllowedAt = act_tick + tRAS; 834 835 // Respect the row-to-column command delay 836 bank_ref.colAllowedAt = act_tick + tRCD; 837 |
|
892 // start by enforcing tRRD 893 for(int i = 0; i < banksPerRank; i++) { 894 // next activate to any bank in this rank must not happen 895 // before tRRD 896 banks[rank][i].actAllowedAt = std::max(act_tick + tRRD, 897 banks[rank][i].actAllowedAt); 898 } 899 --- 44 unchanged lines hidden (view full) --- 944 // we should transition to the active state as soon as any bank is active 945 if (pwrState != PWR_ACT) 946 // note that at this point numBanksActive could be back at 947 // zero again due to a precharge scheduled in the future 948 schedulePowerEvent(PWR_ACT, curTick()); 949} 950 951void | 838 // start by enforcing tRRD 839 for(int i = 0; i < banksPerRank; i++) { 840 // next activate to any bank in this rank must not happen 841 // before tRRD 842 banks[rank][i].actAllowedAt = std::max(act_tick + tRRD, 843 banks[rank][i].actAllowedAt); 844 } 845 --- 44 unchanged lines hidden (view full) --- 890 // we should transition to the active state as soon as any bank is active 891 if (pwrState != PWR_ACT) 892 // note that at this point numBanksActive could be back at 893 // zero again due to a precharge scheduled in the future 894 schedulePowerEvent(PWR_ACT, curTick()); 895} 896 897void |
952DRAMCtrl::prechargeBank(Bank& bank, Tick free_at) | 898DRAMCtrl::prechargeBank(Bank& bank, Tick pre_at) |
953{ 954 // make sure the bank has an open row 955 assert(bank.openRow != Bank::NO_ROW); 956 957 // sample the bytes per activate here since we are closing 958 // the page 959 bytesPerActivate.sample(bank.bytesAccessed); 960 961 bank.openRow = Bank::NO_ROW; 962 | 899{ 900 // make sure the bank has an open row 901 assert(bank.openRow != Bank::NO_ROW); 902 903 // sample the bytes per activate here since we are closing 904 // the page 905 bytesPerActivate.sample(bank.bytesAccessed); 906 907 bank.openRow = Bank::NO_ROW; 908 |
963 bank.freeAt = free_at; | 909 Tick pre_done_at = pre_at + tRP; |
964 | 910 |
911 bank.actAllowedAt = std::max(bank.actAllowedAt, pre_done_at); 912 |
|
965 assert(numBanksActive != 0); 966 --numBanksActive; 967 | 913 assert(numBanksActive != 0); 914 --numBanksActive; 915 |
968 DPRINTF(DRAM, "Precharged bank, done at tick %lld, now got %d active\n", 969 bank.freeAt, numBanksActive); | 916 DPRINTF(DRAM, "Precharging bank at tick %lld, now got %d active\n", 917 pre_at, numBanksActive); |
970 971 // if we look at the current number of active banks we might be 972 // tempted to think the DRAM is now idle, however this can be 973 // undone by an activate that is scheduled to happen before we 974 // would have reached the idle state, so schedule an event and 975 // rather check once we actually make it to the point in time when 976 // the (last) precharge takes place 977 if (!prechargeEvent.scheduled()) | 918 919 // if we look at the current number of active banks we might be 920 // tempted to think the DRAM is now idle, however this can be 921 // undone by an activate that is scheduled to happen before we 922 // would have reached the idle state, so schedule an event and 923 // rather check once we actually make it to the point in time when 924 // the (last) precharge takes place 925 if (!prechargeEvent.scheduled()) |
978 schedule(prechargeEvent, free_at); 979 else if (prechargeEvent.when() < free_at) 980 reschedule(prechargeEvent, free_at); | 926 schedule(prechargeEvent, pre_done_at); 927 else if (prechargeEvent.when() < pre_done_at) 928 reschedule(prechargeEvent, pre_done_at); |
981} 982 983void 984DRAMCtrl::processPrechargeEvent() 985{ 986 // if we reached zero, then special conditions apply as we track 987 // if all banks are precharged for the power models 988 if (numBanksActive == 0) { 989 // we should transition to the idle state when the last bank 990 // is precharged 991 schedulePowerEvent(PWR_IDLE, curTick()); 992 } 993} 994 995void 996DRAMCtrl::doDRAMAccess(DRAMPacket* dram_pkt) 997{ | 929} 930 931void 932DRAMCtrl::processPrechargeEvent() 933{ 934 // if we reached zero, then special conditions apply as we track 935 // if all banks are precharged for the power models 936 if (numBanksActive == 0) { 937 // we should transition to the idle state when the last bank 938 // is precharged 939 schedulePowerEvent(PWR_IDLE, curTick()); 940 } 941} 942 943void 944DRAMCtrl::doDRAMAccess(DRAMPacket* dram_pkt) 945{ |
998 | |
999 DPRINTF(DRAM, "Timing access to addr %lld, rank/bank/row %d %d %d\n", 1000 dram_pkt->addr, dram_pkt->rank, dram_pkt->bank, dram_pkt->row); 1001 | 946 DPRINTF(DRAM, "Timing access to addr %lld, rank/bank/row %d %d %d\n", 947 dram_pkt->addr, dram_pkt->rank, dram_pkt->bank, dram_pkt->row); 948 |
1002 // estimate the bank and access latency 1003 pair<Tick, Tick> lat = estimateLatency(dram_pkt, curTick()); 1004 Tick bankLat = lat.first; 1005 Tick accessLat = lat.second; 1006 Tick actTick; | 949 // get the bank 950 Bank& bank = dram_pkt->bankRef; |
1007 | 951 |
1008 // This request was woken up at this time based on a prior call 1009 // to estimateLatency(). However, between then and now, both the 1010 // accessLatency and/or busBusyUntil may have changed. We need 1011 // to correct for that. 1012 Tick addDelay = (curTick() + accessLat < busBusyUntil) ? 1013 busBusyUntil - (curTick() + accessLat) : 0; | 952 // for the state we need to track if it is a row hit or not 953 bool row_hit = true; |
1014 | 954 |
1015 // Update request parameters 1016 dram_pkt->readyTime = curTick() + addDelay + accessLat + tBURST; | 955 // respect any constraints on the command (e.g. tRCD or tCCD) 956 Tick cmd_at = std::max(bank.colAllowedAt, curTick()); |
1017 | 957 |
1018 DPRINTF(DRAM, "Req %lld: curtick is %lld accessLat is %d " \ 1019 "readytime is %lld busbusyuntil is %lld. " \ 1020 "Scheduling at readyTime\n", dram_pkt->addr, 1021 curTick(), accessLat, dram_pkt->readyTime, busBusyUntil); 1022 1023 // Make sure requests are not overlapping on the databus 1024 assert(dram_pkt->readyTime - busBusyUntil >= tBURST); 1025 1026 Bank& bank = dram_pkt->bankRef; 1027 1028 // Update bank state 1029 if (rowHitFlag) { 1030 bank.freeAt = curTick() + addDelay + accessLat; | 958 // Determine the access latency and update the bank state 959 if (bank.openRow == dram_pkt->row) { 960 // nothing to do |
1031 } else { | 961 } else { |
962 row_hit = false; 963 |
|
1032 // If there is a page open, precharge it. 1033 if (bank.openRow != Bank::NO_ROW) { | 964 // If there is a page open, precharge it. 965 if (bank.openRow != Bank::NO_ROW) { |
1034 prechargeBank(bank, std::max(std::max(bank.freeAt, 1035 bank.preAllowedAt), 1036 curTick()) + tRP); | 966 prechargeBank(bank, std::max(bank.preAllowedAt, curTick())); |
1037 } 1038 | 967 } 968 |
1039 // Any precharge is already part of the latency 1040 // estimation, so update the bank free time 1041 bank.freeAt = curTick() + addDelay + accessLat; | 969 // next we need to account for the delay in activating the 970 // page 971 Tick act_tick = std::max(bank.actAllowedAt, curTick()); |
1042 | 972 |
1043 // any waiting for banks account for in freeAt 1044 actTick = bank.freeAt - tCL - tRCD; 1045 1046 // The next access has to respect tRAS for this bank 1047 bank.preAllowedAt = actTick + tRAS; 1048 | |
1049 // Record the activation and deal with all the global timing 1050 // constraints caused be a new activation (tRRD and tXAW) | 973 // Record the activation and deal with all the global timing 974 // constraints caused be a new activation (tRRD and tXAW) |
1051 activateBank(actTick, dram_pkt->rank, dram_pkt->bank, | 975 activateBank(act_tick, dram_pkt->rank, dram_pkt->bank, |
1052 dram_pkt->row, bank); 1053 | 976 dram_pkt->row, bank); 977 |
978 // issue the command as early as possible 979 cmd_at = bank.colAllowedAt; |
|
1054 } 1055 | 980 } 981 |
982 // we need to wait until the bus is available before we can issue 983 // the command 984 cmd_at = std::max(cmd_at, busBusyUntil - tCL); 985 986 // update the packet ready time 987 dram_pkt->readyTime = cmd_at + tCL + tBURST; 988 989 // only one burst can use the bus at any one point in time 990 assert(dram_pkt->readyTime - busBusyUntil >= tBURST); 991 992 // not strictly necessary, but update the time for the next 993 // read/write (add a max with tCCD here) 994 bank.colAllowedAt = cmd_at + tBURST; 995 |
|
1056 // If this is a write, we also need to respect the write 1057 // recovery time before a precharge 1058 if (!dram_pkt->isRead) { 1059 bank.preAllowedAt = std::max(bank.preAllowedAt, 1060 dram_pkt->readyTime + tWR); 1061 } 1062 | 996 // If this is a write, we also need to respect the write 997 // recovery time before a precharge 998 if (!dram_pkt->isRead) { 999 bank.preAllowedAt = std::max(bank.preAllowedAt, 1000 dram_pkt->readyTime + tWR); 1001 } 1002 |
1063 // We also have to respect tRP, and any constraints on when we may 1064 // precharge the bank, in the case of reads this is really only 1065 // going to cause any change if we did not have a row hit and are 1066 // now forced to respect tRAS 1067 bank.actAllowedAt = std::max(bank.actAllowedAt, 1068 bank.preAllowedAt + tRP); 1069 | |
1070 // increment the bytes accessed and the accesses per row 1071 bank.bytesAccessed += burstSize; 1072 ++bank.rowAccesses; 1073 1074 // if we reached the max, then issue with an auto-precharge 1075 bool auto_precharge = pageMgmt == Enums::close || 1076 bank.rowAccesses == maxAccessesPerRow; 1077 --- 40 unchanged lines hidden (view full) --- 1118 // 2) close_adaptive policy and we have not got any more hits 1119 auto_precharge = !got_more_hits && 1120 (got_bank_conflict || pageMgmt == Enums::close_adaptive); 1121 } 1122 1123 // if this access should use auto-precharge, then we are 1124 // closing the row 1125 if (auto_precharge) { | 1003 // increment the bytes accessed and the accesses per row 1004 bank.bytesAccessed += burstSize; 1005 ++bank.rowAccesses; 1006 1007 // if we reached the max, then issue with an auto-precharge 1008 bool auto_precharge = pageMgmt == Enums::close || 1009 bank.rowAccesses == maxAccessesPerRow; 1010 --- 40 unchanged lines hidden (view full) --- 1051 // 2) close_adaptive policy and we have not got any more hits 1052 auto_precharge = !got_more_hits && 1053 (got_bank_conflict || pageMgmt == Enums::close_adaptive); 1054 } 1055 1056 // if this access should use auto-precharge, then we are 1057 // closing the row 1058 if (auto_precharge) { |
1126 prechargeBank(bank, std::max(bank.freeAt, bank.preAllowedAt) + tRP); | 1059 prechargeBank(bank, std::max(curTick(), bank.preAllowedAt)); |
1127 1128 DPRINTF(DRAM, "Auto-precharged bank: %d\n", dram_pkt->bankId); 1129 } 1130 | 1060 1061 DPRINTF(DRAM, "Auto-precharged bank: %d\n", dram_pkt->bankId); 1062 } 1063 |
1131 DPRINTF(DRAM, "doDRAMAccess::bank.freeAt is %lld\n", bank.freeAt); 1132 | |
1133 // Update bus state 1134 busBusyUntil = dram_pkt->readyTime; 1135 | 1064 // Update bus state 1065 busBusyUntil = dram_pkt->readyTime; 1066 |
1136 DPRINTF(DRAM,"Access time is %lld\n", 1137 dram_pkt->readyTime - dram_pkt->entryTime); | 1067 DPRINTF(DRAM, "Access to %lld, ready at %lld bus busy until %lld.\n", 1068 dram_pkt->addr, dram_pkt->readyTime, busBusyUntil); |
1138 1139 // Update the minimum timing between the requests, this is a 1140 // conservative estimate of when we have to schedule the next 1141 // request to not introduce any unecessary bubbles. In most cases 1142 // we will wake up sooner than we have to. 1143 nextReqTime = busBusyUntil - (tRP + tRCD + tCL); 1144 1145 // Update the stats and schedule the next request 1146 if (dram_pkt->isRead) { 1147 ++readsThisTime; | 1069 1070 // Update the minimum timing between the requests, this is a 1071 // conservative estimate of when we have to schedule the next 1072 // request to not introduce any unecessary bubbles. In most cases 1073 // we will wake up sooner than we have to. 1074 nextReqTime = busBusyUntil - (tRP + tRCD + tCL); 1075 1076 // Update the stats and schedule the next request 1077 if (dram_pkt->isRead) { 1078 ++readsThisTime; |
1148 if (rowHitFlag) | 1079 if (row_hit) |
1149 readRowHits++; 1150 bytesReadDRAM += burstSize; 1151 perBankRdBursts[dram_pkt->bankId]++; 1152 1153 // Update latency stats 1154 totMemAccLat += dram_pkt->readyTime - dram_pkt->entryTime; | 1080 readRowHits++; 1081 bytesReadDRAM += burstSize; 1082 perBankRdBursts[dram_pkt->bankId]++; 1083 1084 // Update latency stats 1085 totMemAccLat += dram_pkt->readyTime - dram_pkt->entryTime; |
1155 totBankLat += bankLat; | |
1156 totBusLat += tBURST; | 1086 totBusLat += tBURST; |
1157 totQLat += dram_pkt->readyTime - dram_pkt->entryTime - bankLat - 1158 tBURST; | 1087 totQLat += cmd_at - dram_pkt->entryTime; |
1159 } else { 1160 ++writesThisTime; | 1088 } else { 1089 ++writesThisTime; |
1161 if (rowHitFlag) | 1090 if (row_hit) |
1162 writeRowHits++; 1163 bytesWritten += burstSize; 1164 perBankWrBursts[dram_pkt->bankId]++; 1165 } 1166} 1167 1168void 1169DRAMCtrl::moveToRespQ() --- 183 unchanged lines hidden (view full) --- 1353 // the next request processing 1354 if (retryWrReq && writeQueue.size() < writeBufferSize) { 1355 retryWrReq = false; 1356 port.sendRetry(); 1357 } 1358} 1359 1360uint64_t | 1091 writeRowHits++; 1092 bytesWritten += burstSize; 1093 perBankWrBursts[dram_pkt->bankId]++; 1094 } 1095} 1096 1097void 1098DRAMCtrl::moveToRespQ() --- 183 unchanged lines hidden (view full) --- 1282 // the next request processing 1283 if (retryWrReq && writeQueue.size() < writeBufferSize) { 1284 retryWrReq = false; 1285 port.sendRetry(); 1286 } 1287} 1288 1289uint64_t |
1361DRAMCtrl::minBankFreeAt(const deque<DRAMPacket*>& queue) const | 1290DRAMCtrl::minBankActAt(const deque<DRAMPacket*>& queue) const |
1362{ 1363 uint64_t bank_mask = 0; | 1291{ 1292 uint64_t bank_mask = 0; |
1364 Tick freeAt = MaxTick; | 1293 Tick min_act_at = MaxTick; |
1365 | 1294 |
1366 // detemrine if we have queued transactions targetting the | 1295 // deterimne if we have queued transactions targetting a |
1367 // bank in question 1368 vector<bool> got_waiting(ranksPerChannel * banksPerRank, false); 1369 for (auto p = queue.begin(); p != queue.end(); ++p) { 1370 got_waiting[(*p)->bankId] = true; 1371 } 1372 1373 for (int i = 0; i < ranksPerChannel; i++) { 1374 for (int j = 0; j < banksPerRank; j++) { | 1296 // bank in question 1297 vector<bool> got_waiting(ranksPerChannel * banksPerRank, false); 1298 for (auto p = queue.begin(); p != queue.end(); ++p) { 1299 got_waiting[(*p)->bankId] = true; 1300 } 1301 1302 for (int i = 0; i < ranksPerChannel; i++) { 1303 for (int j = 0; j < banksPerRank; j++) { |
1304 uint8_t bank_id = i * banksPerRank + j; 1305 |
|
1375 // if we have waiting requests for the bank, and it is 1376 // amongst the first available, update the mask | 1306 // if we have waiting requests for the bank, and it is 1307 // amongst the first available, update the mask |
1377 if (got_waiting[i * banksPerRank + j] && 1378 banks[i][j].freeAt <= freeAt) { 1379 // reset bank mask if new minimum is found 1380 if (banks[i][j].freeAt < freeAt) 1381 bank_mask = 0; 1382 // set the bit corresponding to the available bank 1383 uint8_t bit_index = i * ranksPerChannel + j; 1384 replaceBits(bank_mask, bit_index, bit_index, 1); 1385 freeAt = banks[i][j].freeAt; | 1308 if (got_waiting[bank_id]) { 1309 // simplistic approximation of when the bank can issue 1310 // an activate, ignoring any rank-to-rank switching 1311 // cost 1312 Tick act_at = banks[i][j].openRow == Bank::NO_ROW ? 1313 banks[i][j].actAllowedAt : 1314 std::max(banks[i][j].preAllowedAt, curTick()) + tRP; 1315 1316 if (act_at <= min_act_at) { 1317 // reset bank mask if new minimum is found 1318 if (act_at < min_act_at) 1319 bank_mask = 0; 1320 // set the bit corresponding to the available bank 1321 replaceBits(bank_mask, bank_id, bank_id, 1); 1322 min_act_at = act_at; 1323 } |
1386 } 1387 } 1388 } | 1324 } 1325 } 1326 } |
1327 |
|
1389 return bank_mask; 1390} 1391 1392void 1393DRAMCtrl::processRefreshEvent() 1394{ 1395 // when first preparing the refresh, remember when it was due 1396 if (refreshState == REF_IDLE) { --- 26 unchanged lines hidden (view full) --- 1423 // state 1424 if (pwrState != PWR_IDLE) { 1425 DPRINTF(DRAM, "Precharging all\n"); 1426 for (int i = 0; i < ranksPerChannel; i++) { 1427 for (int j = 0; j < banksPerRank; j++) { 1428 if (banks[i][j].openRow != Bank::NO_ROW) { 1429 // respect both causality and any existing bank 1430 // constraints | 1328 return bank_mask; 1329} 1330 1331void 1332DRAMCtrl::processRefreshEvent() 1333{ 1334 // when first preparing the refresh, remember when it was due 1335 if (refreshState == REF_IDLE) { --- 26 unchanged lines hidden (view full) --- 1362 // state 1363 if (pwrState != PWR_IDLE) { 1364 DPRINTF(DRAM, "Precharging all\n"); 1365 for (int i = 0; i < ranksPerChannel; i++) { 1366 for (int j = 0; j < banksPerRank; j++) { 1367 if (banks[i][j].openRow != Bank::NO_ROW) { 1368 // respect both causality and any existing bank 1369 // constraints |
1431 Tick free_at = 1432 std::max(std::max(banks[i][j].freeAt, 1433 banks[i][j].preAllowedAt), 1434 curTick()) + tRP; | 1370 Tick pre_at = std::max(banks[i][j].preAllowedAt, 1371 curTick()); |
1435 | 1372 |
1436 prechargeBank(banks[i][j], free_at); | 1373 prechargeBank(banks[i][j], pre_at); |
1437 } 1438 } 1439 } 1440 } else { 1441 DPRINTF(DRAM, "All banks already precharged, starting refresh\n"); 1442 1443 // go ahead and kick the power state machine into gear if 1444 // we are already idle --- 11 unchanged lines hidden (view full) --- 1456 } 1457 1458 // last but not least we perform the actual refresh 1459 if (refreshState == REF_RUN) { 1460 // should never get here with any banks active 1461 assert(numBanksActive == 0); 1462 assert(pwrState == PWR_REF); 1463 | 1374 } 1375 } 1376 } 1377 } else { 1378 DPRINTF(DRAM, "All banks already precharged, starting refresh\n"); 1379 1380 // go ahead and kick the power state machine into gear if 1381 // we are already idle --- 11 unchanged lines hidden (view full) --- 1393 } 1394 1395 // last but not least we perform the actual refresh 1396 if (refreshState == REF_RUN) { 1397 // should never get here with any banks active 1398 assert(numBanksActive == 0); 1399 assert(pwrState == PWR_REF); 1400 |
1464 Tick banksFree = curTick() + tRFC; | 1401 Tick ref_done_at = curTick() + tRFC; |
1465 1466 for (int i = 0; i < ranksPerChannel; i++) { 1467 for (int j = 0; j < banksPerRank; j++) { | 1402 1403 for (int i = 0; i < ranksPerChannel; i++) { 1404 for (int j = 0; j < banksPerRank; j++) { |
1468 banks[i][j].freeAt = banksFree; | 1405 banks[i][j].actAllowedAt = ref_done_at; |
1469 } 1470 } 1471 1472 // make sure we did not wait so long that we cannot make up 1473 // for it | 1406 } 1407 } 1408 1409 // make sure we did not wait so long that we cannot make up 1410 // for it |
1474 if (refreshDueAt + tREFI < banksFree) { | 1411 if (refreshDueAt + tREFI < ref_done_at) { |
1475 fatal("Refresh was delayed so long we cannot catch up\n"); 1476 } 1477 1478 // compensate for the delay in actually performing the refresh 1479 // when scheduling the next one 1480 schedule(refreshEvent, refreshDueAt + tREFI - tRP); 1481 1482 assert(!powerEvent.scheduled()); 1483 1484 // move to the idle power state once the refresh is done, this 1485 // will also move the refresh state machine to the refresh 1486 // idle state | 1412 fatal("Refresh was delayed so long we cannot catch up\n"); 1413 } 1414 1415 // compensate for the delay in actually performing the refresh 1416 // when scheduling the next one 1417 schedule(refreshEvent, refreshDueAt + tREFI - tRP); 1418 1419 assert(!powerEvent.scheduled()); 1420 1421 // move to the idle power state once the refresh is done, this 1422 // will also move the refresh state machine to the refresh 1423 // idle state |
1487 schedulePowerEvent(PWR_IDLE, banksFree); | 1424 schedulePowerEvent(PWR_IDLE, ref_done_at); |
1488 1489 DPRINTF(DRAMState, "Refresh done at %llu and next refresh at %llu\n", | 1425 1426 DPRINTF(DRAMState, "Refresh done at %llu and next refresh at %llu\n", |
1490 banksFree, refreshDueAt + tREFI); | 1427 ref_done_at, refreshDueAt + tREFI); |
1491 } 1492} 1493 1494void 1495DRAMCtrl::schedulePowerEvent(PowerState pwr_state, Tick tick) 1496{ 1497 // respect causality 1498 assert(tick >= curTick()); --- 123 unchanged lines hidden (view full) --- 1622 .name(name() + ".avgWrQLen") 1623 .desc("Average write queue length when enqueuing") 1624 .precision(2); 1625 1626 totQLat 1627 .name(name() + ".totQLat") 1628 .desc("Total ticks spent queuing"); 1629 | 1428 } 1429} 1430 1431void 1432DRAMCtrl::schedulePowerEvent(PowerState pwr_state, Tick tick) 1433{ 1434 // respect causality 1435 assert(tick >= curTick()); --- 123 unchanged lines hidden (view full) --- 1559 .name(name() + ".avgWrQLen") 1560 .desc("Average write queue length when enqueuing") 1561 .precision(2); 1562 1563 totQLat 1564 .name(name() + ".totQLat") 1565 .desc("Total ticks spent queuing"); 1566 |
1630 totBankLat 1631 .name(name() + ".totBankLat") 1632 .desc("Total ticks spent accessing banks"); 1633 | |
1634 totBusLat 1635 .name(name() + ".totBusLat") 1636 .desc("Total ticks spent in databus transfers"); 1637 1638 totMemAccLat 1639 .name(name() + ".totMemAccLat") 1640 .desc("Total ticks spent from burst creation until serviced " 1641 "by the DRAM"); 1642 1643 avgQLat 1644 .name(name() + ".avgQLat") 1645 .desc("Average queueing delay per DRAM burst") 1646 .precision(2); 1647 1648 avgQLat = totQLat / (readBursts - servicedByWrQ); 1649 | 1567 totBusLat 1568 .name(name() + ".totBusLat") 1569 .desc("Total ticks spent in databus transfers"); 1570 1571 totMemAccLat 1572 .name(name() + ".totMemAccLat") 1573 .desc("Total ticks spent from burst creation until serviced " 1574 "by the DRAM"); 1575 1576 avgQLat 1577 .name(name() + ".avgQLat") 1578 .desc("Average queueing delay per DRAM burst") 1579 .precision(2); 1580 1581 avgQLat = totQLat / (readBursts - servicedByWrQ); 1582 |
1650 avgBankLat 1651 .name(name() + ".avgBankLat") 1652 .desc("Average bank access latency per DRAM burst") 1653 .precision(2); 1654 1655 avgBankLat = totBankLat / (readBursts - servicedByWrQ); 1656 | |
1657 avgBusLat 1658 .name(name() + ".avgBusLat") 1659 .desc("Average bus latency per DRAM burst") 1660 .precision(2); 1661 1662 avgBusLat = totBusLat / (readBursts - servicedByWrQ); 1663 1664 avgMemAccLat --- 273 unchanged lines hidden --- | 1583 avgBusLat 1584 .name(name() + ".avgBusLat") 1585 .desc("Average bus latency per DRAM burst") 1586 .precision(2); 1587 1588 avgBusLat = totBusLat / (readBursts - servicedByWrQ); 1589 1590 avgMemAccLat --- 273 unchanged lines hidden --- |