2 * Copyright (c) 2004-2005 The Regents of The University of Michigan
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are
7 * met: redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer;
9 * redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution;
12 * neither the name of the copyright holders nor the names of its
13 * contributors may be used to endorse or promote products derived from
14 * this software without specific prior written permission.
16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
33 * Definitions of split cache tag store.
40 #include "base/cprintf.hh"
41 #include "base/intmath.hh"
42 #include "base/output.hh"
43 #include "base/trace.hh"
44 #include "mem/cache/base_cache.hh"
45 #include "mem/cache/tags/split.hh"
46 #include "mem/cache/tags/split_lifo.hh"
47 #include "mem/cache/tags/split_lru.hh"
51 using namespace TheISA
;
53 // create and initialize a partitioned cache structure
54 Split::Split(int _numSets
, int _blkSize
, int total_ways
, int LRU1_assoc
,
55 bool _lifo
, bool _two_queue
, int _hit_latency
) :
56 numSets(_numSets
), blkSize(_blkSize
), lifo(_lifo
), hitLatency(_hit_latency
)
58 DPRINTF(Split
, "new split cache!!\n");
60 DPRINTF(Split
, "lru has %d numSets, %d blkSize, %d assoc, and %d hit_latency\n",
61 numSets
, blkSize
, LRU1_assoc
, hitLatency
);
63 lru
= new SplitLRU(_numSets
, _blkSize
, LRU1_assoc
, _hit_latency
, 1);
65 if (total_ways
- LRU1_assoc
== 0) {
70 DPRINTF(Split
, "Other partition is a LIFO with size %d in bytes. it gets %d ways\n",
71 (total_ways
- LRU1_assoc
)*_numSets
*_blkSize
, (total_ways
- LRU1_assoc
));
72 lifo_net
= new SplitLIFO(_blkSize
, (total_ways
- LRU1_assoc
)*_numSets
*_blkSize
,
73 (total_ways
- LRU1_assoc
), _hit_latency
, _two_queue
, 2);
77 DPRINTF(Split
, "other LRU gets %d ways\n", total_ways
- LRU1_assoc
);
78 lru_net
= new SplitLRU(_numSets
, _blkSize
, total_ways
- LRU1_assoc
, _hit_latency
, 2);
83 blkMask
= blkSize
- 1;
85 if (!isPowerOf2(total_ways
))
86 warn("total cache ways/columns %d should be power of 2",
90 /** @todo Make warmup percentage a parameter. */
91 warmupBound
= numSets
* total_ways
;
105 Split::regStats(const string
&name
)
107 using namespace Stats
;
109 BaseTags::regStats(name
);
111 usedEvictDist
.init(0,3000,40);
112 unusedEvictDist
.init(0,3000,40);
113 useByCPUCycleDist
.init(0,35,1);
116 .name(name
+ ".nic_repl")
117 .desc("number of replacements in the nic partition")
122 .name(name
+ ".cpu_repl")
123 .desc("number of replacements in the cpu partition")
127 lru
->regStats(name
+ ".lru");
129 if (lifo
&& lifo_net
) {
130 lifo_net
->regStats(name
+ ".lifo_net");
131 } else if (lru_net
) {
132 lru_net
->regStats(name
+ ".lru_net");
136 .name(name
+ ".nicUsedWhenEvicted")
137 .desc("number of NIC blks that were used before evicted")
141 .name(name
+ ".nicUsedTotLatency")
142 .desc("total cycles before eviction of used NIC blks")
146 .name(name
+ ".nicUsedTotEvicted")
147 .desc("total number of used NIC blks evicted")
151 .name(name
+ ".nicUsedAvgLatency")
152 .desc("avg number of cycles a used NIC blk is in cache")
155 nicUsedAvgLatency
= nicUsedTotLatency
/ nicUsedTotEvicted
;
158 .name(name
+ ".usedEvictDist")
159 .desc("distribution of used NIC blk eviction times")
164 .name(name
+ ".nicUnusedWhenEvicted")
165 .desc("number of NIC blks that were unused when evicted")
169 .name(name
+ ".nicUnusedTotLatency")
170 .desc("total cycles before eviction of unused NIC blks")
174 .name(name
+ ".nicUnusedTotEvicted")
175 .desc("total number of unused NIC blks evicted")
179 .name(name
+ ".nicUnusedAvgLatency")
180 .desc("avg number of cycles an unused NIC blk is in cache")
183 nicUnusedAvgLatency
= nicUnusedTotLatency
/ nicUnusedTotEvicted
;
186 .name(name
+ ".unusedEvictDist")
187 .desc("distribution of unused NIC blk eviction times")
191 nicUseByCPUCycleTotal
192 .name(name
+ ".nicUseByCPUCycleTotal")
193 .desc("total latency of NIC blks til usage time")
197 .name(name
+ ".nicBlksUsedByCPU")
198 .desc("total number of NIC blks used")
201 nicAvgUsageByCPULatency
202 .name(name
+ ".nicAvgUsageByCPULatency")
203 .desc("average number of cycles before a NIC blk that is used gets used")
206 nicAvgUsageByCPULatency
= nicUseByCPUCycleTotal
/ nicBlksUsedByCPU
;
209 .name(name
+ ".useByCPUCycleDist")
210 .desc("the distribution of cycle time in cache before NIC blk is used")
215 .name(name
+ ".cpuUsedBlks")
216 .desc("number of cpu blks that were used before evicted")
220 .name(name
+ ".cpuUnusedBlks")
221 .desc("number of cpu blks that were unused before evicted")
225 .name(name
+ ".nicAvgLatency")
226 .desc("avg number of cycles a NIC blk is in cache before evicted")
229 nicAvgLatency
= (nicUnusedTotLatency
+ nicUsedTotLatency
) /
230 (nicUnusedTotEvicted
+ nicUsedTotEvicted
);
233 .name(name
+ ".NR_CP_hits")
234 .desc("NIC requests hitting in CPU Partition")
238 .name(name
+ ".NR_NP_hits")
239 .desc("NIC requests hitting in NIC Partition")
243 .name(name
+ ".CR_CP_hits")
244 .desc("CPU requests hitting in CPU partition")
248 .name(name
+ ".CR_NP_hits")
249 .desc("CPU requests hitting in NIC partition")
254 // probe cache for presence of given block.
256 Split::probe(Addr addr
) const
258 bool success
= lru
->probe(addr
);
260 if (lifo
&& lifo_net
)
261 success
= lifo_net
->probe(addr
);
263 success
= lru_net
->probe(addr
);
271 Split::findBlock(Addr addr
, int &lat
)
273 SplitBlk
*blk
= lru
->findBlock(addr
, lat
);
275 if (lifo
&& lifo_net
) {
276 blk
= lifo_net
->findBlock(addr
, lat
);
277 } else if (lru_net
) {
278 blk
= lru_net
->findBlock(addr
, lat
);
286 Split::findBlock(Addr addr
) const
288 SplitBlk
*blk
= lru
->findBlock(addr
);
290 if (lifo
&& lifo_net
) {
291 blk
= lifo_net
->findBlock(addr
);
292 } else if (lru_net
) {
293 blk
= lru_net
->findBlock(addr
);
301 Split::findReplacement(Addr addr
, PacketList
&writebacks
)
307 if (pkt
->nic_pkt()) {
308 DPRINTF(Split
, "finding a replacement for nic_req\n");
310 if (lifo
&& lifo_net
)
311 blk
= lifo_net
->findReplacement(addr
, writebacks
);
313 blk
= lru_net
->findReplacement(addr
, writebacks
);
314 // in this case, this is an LRU only cache, it's non partitioned
316 blk
= lru
->findReplacement(addr
, writebacks
);
318 DPRINTF(Split
, "finding replacement for cpu_req\n");
319 blk
= lru
->findReplacement(addr
, writebacks
);
323 Tick latency
= curTick
- blk
->ts
;
326 nicUsedWhenEvicted
++;
327 usedEvictDist
.sample(latency
);
328 nicUsedTotLatency
+= latency
;
331 nicUnusedWhenEvicted
++;
332 unusedEvictDist
.sample(latency
);
333 nicUnusedTotLatency
+= latency
;
334 nicUnusedTotEvicted
++;
344 // blk attributes for the new blk coming IN
346 blk
->isNIC
= (pkt
->nic_pkt()) ? true : false;
353 Split::invalidateBlk(Split::BlkType
*blk
)
358 if (lifo
&& lifo_net
)
359 blk
= lifo_net
->findBlock(addr
);
361 blk
= lru_net
->findBlock(addr
);
369 blk
->isTouched
= false;
377 if (lifo
&& lifo_net
)
378 lifo_net
->cleanupRefs();
380 lru_net
->cleanupRefs();
382 ofstream
memPrint(simout
.resolve("memory_footprint.txt").c_str(),
385 // this shouldn't be here but it happens at the end, which is what i want
386 memIter end
= memHash
.end();
387 for (memIter iter
= memHash
.begin(); iter
!= end
; ++iter
) {
388 ccprintf(memPrint
, "%8x\t%d\n", (*iter
).first
, (*iter
).second
);
393 Split::regenerateBlkAddr(Addr tag
, int set
) const
396 return lifo_net
->regenerateBlkAddr(tag
, set
);
398 return lru
->regenerateBlkAddr(tag
, set
);
402 Split::extractTag(Addr addr
) const
404 // need to fix this if we want to use it... old interface of
405 // passing in blk was too weird
409 if (blk->part == 2) {
411 return lifo_net->extractTag(addr);
413 return lru_net->extractTag(addr);
415 panic("this shouldn't happen");
417 return lru->extractTag(addr);