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