base.cc (13748:de3b813c4b90) | base.cc (13749:b2486662285d) |
---|---|
1/* 2 * Copyright (c) 2012-2013, 2018 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 --- 876 unchanged lines hidden (view full) --- 885} 886 887///////////////////////////////////////////////////// 888// 889// Access path: requests coming in from the CPU side 890// 891///////////////////////////////////////////////////// 892Cycles | 1/* 2 * Copyright (c) 2012-2013, 2018 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 --- 876 unchanged lines hidden (view full) --- 885} 886 887///////////////////////////////////////////////////// 888// 889// Access path: requests coming in from the CPU side 890// 891///////////////////////////////////////////////////// 892Cycles |
893BaseCache::calculateTagOnlyLatency(const uint32_t delay, 894 const Cycles lookup_lat) const 895{ 896 // A tag-only access has to wait for the packet to arrive in order to 897 // perform the tag lookup. 898 return ticksToCycles(delay) + lookup_lat; 899} 900 901Cycles |
|
893BaseCache::calculateAccessLatency(const CacheBlk* blk, const uint32_t delay, 894 const Cycles lookup_lat) const 895{ 896 Cycles lat(0); 897 898 if (blk != nullptr) { 899 // As soon as the access arrives, for sequential accesses first access 900 // tags, then the data entry. In the case of parallel accesses the --- 8 unchanged lines hidden (view full) --- 909 // access latency on top of when the block is ready to be accessed. 910 const Tick tick = curTick() + delay; 911 const Tick when_ready = blk->getWhenReady(); 912 if (when_ready > tick && 913 ticksToCycles(when_ready - tick) > lat) { 914 lat += ticksToCycles(when_ready - tick); 915 } 916 } else { | 902BaseCache::calculateAccessLatency(const CacheBlk* blk, const uint32_t delay, 903 const Cycles lookup_lat) const 904{ 905 Cycles lat(0); 906 907 if (blk != nullptr) { 908 // As soon as the access arrives, for sequential accesses first access 909 // tags, then the data entry. In the case of parallel accesses the --- 8 unchanged lines hidden (view full) --- 918 // access latency on top of when the block is ready to be accessed. 919 const Tick tick = curTick() + delay; 920 const Tick when_ready = blk->getWhenReady(); 921 if (when_ready > tick && 922 ticksToCycles(when_ready - tick) > lat) { 923 lat += ticksToCycles(when_ready - tick); 924 } 925 } else { |
917 // In case of a miss, apply lookup latency on top of the metadata 918 // delay, as the access can only start when it arrives. 919 lat = ticksToCycles(delay) + lookup_lat; | 926 // In case of a miss, we neglect the data access in a parallel 927 // configuration (i.e., the data access will be stopped as soon as 928 // we find out it is a miss), and use the tag-only latency. 929 lat = calculateTagOnlyLatency(delay, lookup_lat); |
920 } 921 922 return lat; 923} 924 925bool 926BaseCache::access(PacketPtr pkt, CacheBlk *&blk, Cycles &lat, 927 PacketList &writebacks) --- 4 unchanged lines hidden (view full) --- 932 chatty_assert(!(isReadOnly && pkt->isWrite()), 933 "Should never see a write in a read-only cache %s\n", 934 name()); 935 936 // Access block in the tags 937 Cycles tag_latency(0); 938 blk = tags->accessBlock(pkt->getAddr(), pkt->isSecure(), tag_latency); 939 | 930 } 931 932 return lat; 933} 934 935bool 936BaseCache::access(PacketPtr pkt, CacheBlk *&blk, Cycles &lat, 937 PacketList &writebacks) --- 4 unchanged lines hidden (view full) --- 942 chatty_assert(!(isReadOnly && pkt->isWrite()), 943 "Should never see a write in a read-only cache %s\n", 944 name()); 945 946 // Access block in the tags 947 Cycles tag_latency(0); 948 blk = tags->accessBlock(pkt->getAddr(), pkt->isSecure(), tag_latency); 949 |
940 // Calculate access latency on top of when the packet arrives. This 941 // takes into account the bus delay. 942 lat = calculateAccessLatency(blk, pkt->headerDelay, 943 tag_latency); 944 | |
945 DPRINTF(Cache, "%s for %s %s\n", __func__, pkt->print(), 946 blk ? "hit " + blk->print() : "miss"); 947 948 if (pkt->req->isCacheMaintenance()) { 949 // A cache maintenance operation is always forwarded to the 950 // memory below even if the block is found in dirty state. 951 952 // We defer any changes to the state of the block until we 953 // create and mark as in service the mshr for the downstream 954 // packet. | 950 DPRINTF(Cache, "%s for %s %s\n", __func__, pkt->print(), 951 blk ? "hit " + blk->print() : "miss"); 952 953 if (pkt->req->isCacheMaintenance()) { 954 // A cache maintenance operation is always forwarded to the 955 // memory below even if the block is found in dirty state. 956 957 // We defer any changes to the state of the block until we 958 // create and mark as in service the mshr for the downstream 959 // packet. |
960 961 // Calculate access latency on top of when the packet arrives. This 962 // takes into account the bus delay. 963 lat = calculateTagOnlyLatency(pkt->headerDelay, tag_latency); 964 |
|
955 return false; 956 } 957 958 if (pkt->isEviction()) { 959 // We check for presence of block in above caches before issuing 960 // Writeback or CleanEvict to write buffer. Therefore the only 961 // possible cases can be of a CleanEvict packet coming from above 962 // encountering a Writeback generated in this cache peer cache and --- 13 unchanged lines hidden (view full) --- 976 // peer caches of the same level while traversing the 977 // crossbar. If a copy of the block is found, the 978 // packet is deleted in the crossbar. Hence, none of 979 // the other upper level caches connected to this 980 // cache have the block, so we can clear the 981 // BLOCK_CACHED flag in the Writeback if set and 982 // discard the CleanEvict by returning true. 983 wbPkt->clearBlockCached(); | 965 return false; 966 } 967 968 if (pkt->isEviction()) { 969 // We check for presence of block in above caches before issuing 970 // Writeback or CleanEvict to write buffer. Therefore the only 971 // possible cases can be of a CleanEvict packet coming from above 972 // encountering a Writeback generated in this cache peer cache and --- 13 unchanged lines hidden (view full) --- 986 // peer caches of the same level while traversing the 987 // crossbar. If a copy of the block is found, the 988 // packet is deleted in the crossbar. Hence, none of 989 // the other upper level caches connected to this 990 // cache have the block, so we can clear the 991 // BLOCK_CACHED flag in the Writeback if set and 992 // discard the CleanEvict by returning true. 993 wbPkt->clearBlockCached(); |
994 995 // A clean evict does not need to access the data array 996 lat = calculateTagOnlyLatency(pkt->headerDelay, tag_latency); 997 |
|
984 return true; 985 } else { 986 assert(pkt->cmd == MemCmd::WritebackDirty); 987 // Dirty writeback from above trumps our clean 988 // writeback... discard here 989 // Note: markInService will remove entry from writeback buffer. 990 markInService(wb_entry); 991 delete wbPkt; --- 9 unchanged lines hidden (view full) --- 1001 // we could get a clean writeback while we are having 1002 // outstanding accesses to a block, do the simple thing for 1003 // now and drop the clean writeback so that we do not upset 1004 // any ordering/decisions about ownership already taken 1005 if (pkt->cmd == MemCmd::WritebackClean && 1006 mshrQueue.findMatch(pkt->getAddr(), pkt->isSecure())) { 1007 DPRINTF(Cache, "Clean writeback %#llx to block with MSHR, " 1008 "dropping\n", pkt->getAddr()); | 998 return true; 999 } else { 1000 assert(pkt->cmd == MemCmd::WritebackDirty); 1001 // Dirty writeback from above trumps our clean 1002 // writeback... discard here 1003 // Note: markInService will remove entry from writeback buffer. 1004 markInService(wb_entry); 1005 delete wbPkt; --- 9 unchanged lines hidden (view full) --- 1015 // we could get a clean writeback while we are having 1016 // outstanding accesses to a block, do the simple thing for 1017 // now and drop the clean writeback so that we do not upset 1018 // any ordering/decisions about ownership already taken 1019 if (pkt->cmd == MemCmd::WritebackClean && 1020 mshrQueue.findMatch(pkt->getAddr(), pkt->isSecure())) { 1021 DPRINTF(Cache, "Clean writeback %#llx to block with MSHR, " 1022 "dropping\n", pkt->getAddr()); |
1023 1024 // A writeback searches for the block, then writes the data. 1025 // As the writeback is being dropped, the data is not touched, 1026 // and we just had to wait for the time to find a match in the 1027 // MSHR. As of now assume a mshr queue search takes as long as 1028 // a tag lookup for simplicity. 1029 lat = calculateTagOnlyLatency(pkt->headerDelay, tag_latency); 1030 |
|
1009 return true; 1010 } 1011 1012 if (!blk) { 1013 // need to do a replacement 1014 blk = allocateBlock(pkt, writebacks); 1015 if (!blk) { 1016 // no replaceable block available: give up, fwd to next level. 1017 incMissCount(pkt); | 1031 return true; 1032 } 1033 1034 if (!blk) { 1035 // need to do a replacement 1036 blk = allocateBlock(pkt, writebacks); 1037 if (!blk) { 1038 // no replaceable block available: give up, fwd to next level. 1039 incMissCount(pkt); |
1040 1041 // A writeback searches for the block, then writes the data. 1042 // As the block could not be found, it was a tag-only access. 1043 lat = calculateTagOnlyLatency(pkt->headerDelay, tag_latency); 1044 |
|
1018 return false; 1019 } 1020 1021 blk->status |= BlkReadable; 1022 } 1023 // only mark the block dirty if we got a writeback command, 1024 // and leave it as is for a clean writeback 1025 if (pkt->cmd == MemCmd::WritebackDirty) { --- 12 unchanged lines hidden (view full) --- 1038 DPRINTF(Cache, "%s new state is %s\n", __func__, blk->print()); 1039 incHitCount(pkt); 1040 1041 // When the packet metadata arrives, the tag lookup will be done while 1042 // the payload is arriving. Then the block will be ready to access as 1043 // soon as the fill is done 1044 blk->setWhenReady(clockEdge(fillLatency) + pkt->headerDelay + 1045 std::max(cyclesToTicks(tag_latency), (uint64_t)pkt->payloadDelay)); | 1045 return false; 1046 } 1047 1048 blk->status |= BlkReadable; 1049 } 1050 // only mark the block dirty if we got a writeback command, 1051 // and leave it as is for a clean writeback 1052 if (pkt->cmd == MemCmd::WritebackDirty) { --- 12 unchanged lines hidden (view full) --- 1065 DPRINTF(Cache, "%s new state is %s\n", __func__, blk->print()); 1066 incHitCount(pkt); 1067 1068 // When the packet metadata arrives, the tag lookup will be done while 1069 // the payload is arriving. Then the block will be ready to access as 1070 // soon as the fill is done 1071 blk->setWhenReady(clockEdge(fillLatency) + pkt->headerDelay + 1072 std::max(cyclesToTicks(tag_latency), (uint64_t)pkt->payloadDelay)); |
1073 1074 // A writeback searches for the block, then writes the data 1075 lat = calculateAccessLatency(blk, pkt->headerDelay, tag_latency); 1076 |
|
1046 return true; 1047 } else if (pkt->cmd == MemCmd::CleanEvict) { | 1077 return true; 1078 } else if (pkt->cmd == MemCmd::CleanEvict) { |
1079 // A CleanEvict does not need to access the data array 1080 lat = calculateTagOnlyLatency(pkt->headerDelay, tag_latency); 1081 |
|
1048 if (blk) { 1049 // Found the block in the tags, need to stop CleanEvict from 1050 // propagating further down the hierarchy. Returning true will 1051 // treat the CleanEvict like a satisfied write request and delete 1052 // it. 1053 return true; 1054 } 1055 // We didn't find the block here, propagate the CleanEvict further --- 5 unchanged lines hidden (view full) --- 1061 // WriteClean handling is a special case. We can allocate a 1062 // block directly if it doesn't exist and we can update the 1063 // block immediately. The WriteClean transfers the ownership 1064 // of the block as well. 1065 assert(blkSize == pkt->getSize()); 1066 1067 if (!blk) { 1068 if (pkt->writeThrough()) { | 1082 if (blk) { 1083 // Found the block in the tags, need to stop CleanEvict from 1084 // propagating further down the hierarchy. Returning true will 1085 // treat the CleanEvict like a satisfied write request and delete 1086 // it. 1087 return true; 1088 } 1089 // We didn't find the block here, propagate the CleanEvict further --- 5 unchanged lines hidden (view full) --- 1095 // WriteClean handling is a special case. We can allocate a 1096 // block directly if it doesn't exist and we can update the 1097 // block immediately. The WriteClean transfers the ownership 1098 // of the block as well. 1099 assert(blkSize == pkt->getSize()); 1100 1101 if (!blk) { 1102 if (pkt->writeThrough()) { |
1103 // A writeback searches for the block, then writes the data. 1104 // As the block could not be found, it was a tag-only access. 1105 lat = calculateTagOnlyLatency(pkt->headerDelay, tag_latency); 1106 |
|
1069 // if this is a write through packet, we don't try to 1070 // allocate if the block is not present 1071 return false; 1072 } else { 1073 // a writeback that misses needs to allocate a new block 1074 blk = allocateBlock(pkt, writebacks); 1075 if (!blk) { 1076 // no replaceable block available: give up, fwd to 1077 // next level. 1078 incMissCount(pkt); | 1107 // if this is a write through packet, we don't try to 1108 // allocate if the block is not present 1109 return false; 1110 } else { 1111 // a writeback that misses needs to allocate a new block 1112 blk = allocateBlock(pkt, writebacks); 1113 if (!blk) { 1114 // no replaceable block available: give up, fwd to 1115 // next level. 1116 incMissCount(pkt); |
1117 1118 // A writeback searches for the block, then writes the 1119 // data. As the block could not be found, it was a tag-only 1120 // access. 1121 lat = calculateTagOnlyLatency(pkt->headerDelay, 1122 tag_latency); 1123 |
|
1079 return false; 1080 } 1081 1082 blk->status |= BlkReadable; 1083 } 1084 } 1085 1086 // at this point either this is a writeback or a write-through --- 12 unchanged lines hidden (view full) --- 1099 incHitCount(pkt); 1100 1101 // When the packet metadata arrives, the tag lookup will be done while 1102 // the payload is arriving. Then the block will be ready to access as 1103 // soon as the fill is done 1104 blk->setWhenReady(clockEdge(fillLatency) + pkt->headerDelay + 1105 std::max(cyclesToTicks(tag_latency), (uint64_t)pkt->payloadDelay)); 1106 | 1124 return false; 1125 } 1126 1127 blk->status |= BlkReadable; 1128 } 1129 } 1130 1131 // at this point either this is a writeback or a write-through --- 12 unchanged lines hidden (view full) --- 1144 incHitCount(pkt); 1145 1146 // When the packet metadata arrives, the tag lookup will be done while 1147 // the payload is arriving. Then the block will be ready to access as 1148 // soon as the fill is done 1149 blk->setWhenReady(clockEdge(fillLatency) + pkt->headerDelay + 1150 std::max(cyclesToTicks(tag_latency), (uint64_t)pkt->payloadDelay)); 1151 |
1152 // A writeback searches for the block, then writes the data 1153 lat = calculateAccessLatency(blk, pkt->headerDelay, tag_latency); 1154 |
|
1107 // if this a write-through packet it will be sent to cache 1108 // below 1109 return !pkt->writeThrough(); 1110 } else if (blk && (pkt->needsWritable() ? blk->isWritable() : 1111 blk->isReadable())) { 1112 // OK to satisfy access 1113 incHitCount(pkt); 1114 satisfyRequest(pkt, blk); 1115 maintainClusivity(pkt->fromCache(), blk); 1116 | 1155 // if this a write-through packet it will be sent to cache 1156 // below 1157 return !pkt->writeThrough(); 1158 } else if (blk && (pkt->needsWritable() ? blk->isWritable() : 1159 blk->isReadable())) { 1160 // OK to satisfy access 1161 incHitCount(pkt); 1162 satisfyRequest(pkt, blk); 1163 maintainClusivity(pkt->fromCache(), blk); 1164 |
1165 // Calculate access latency based on the need to access the data array 1166 if (pkt->isRead() || pkt->isWrite()) { 1167 lat = calculateAccessLatency(blk, pkt->headerDelay, tag_latency); 1168 } else { 1169 lat = calculateTagOnlyLatency(pkt->headerDelay, tag_latency); 1170 } 1171 |
|
1117 return true; 1118 } 1119 1120 // Can't satisfy access normally... either no block (blk == nullptr) 1121 // or have block but need writable 1122 1123 incMissCount(pkt); 1124 | 1172 return true; 1173 } 1174 1175 // Can't satisfy access normally... either no block (blk == nullptr) 1176 // or have block but need writable 1177 1178 incMissCount(pkt); 1179 |
1180 lat = calculateAccessLatency(blk, pkt->headerDelay, tag_latency); 1181 |
|
1125 if (!blk && pkt->isLLSC() && pkt->isWrite()) { 1126 // complete miss on store conditional... just give up now 1127 pkt->req->setExtraData(0); 1128 return true; 1129 } 1130 1131 return false; 1132} --- 1334 unchanged lines hidden --- | 1182 if (!blk && pkt->isLLSC() && pkt->isWrite()) { 1183 // complete miss on store conditional... just give up now 1184 pkt->req->setExtraData(0); 1185 return true; 1186 } 1187 1188 return false; 1189} --- 1334 unchanged lines hidden --- |