2 * Copyright (c) 2013,2016,2018-2019 ARM Limited
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
9 * licensed hereunder. You may use the software subject to the license
10 * terms below provided that you ensure that this notice is replicated
11 * unmodified and in its entirety in all distributions of the software,
12 * modified or unmodified, in source code or in binary form.
14 * Copyright (c) 2003-2005 The Regents of The University of Michigan
15 * All rights reserved.
17 * Redistribution and use in source and binary forms, with or without
18 * modification, are permitted provided that the following conditions are
19 * met: redistributions of source code must retain the above copyright
20 * notice, this list of conditions and the following disclaimer;
21 * redistributions in binary form must reproduce the above copyright
22 * notice, this list of conditions and the following disclaimer in the
23 * documentation and/or other materials provided with the distribution;
24 * neither the name of the copyright holders nor the names of its
25 * contributors may be used to endorse or promote products derived from
26 * this software without specific prior written permission.
28 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
29 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
30 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
31 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
32 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
33 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
34 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
35 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
36 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
37 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
38 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
43 * Definitions of BaseTags.
46 #include "mem/cache/tags/base.hh"
50 #include "base/types.hh"
51 #include "mem/cache/replacement_policies/replaceable_entry.hh"
52 #include "mem/cache/tags/indexing_policies/base.hh"
53 #include "mem/request.hh"
54 #include "sim/core.hh"
55 #include "sim/sim_exit.hh"
56 #include "sim/system.hh"
58 BaseTags::BaseTags(const Params
&p
)
59 : ClockedObject(p
), blkSize(p
.block_size
), blkMask(blkSize
- 1),
60 size(p
.size
), lookupLatency(p
.tag_latency
),
61 system(p
.system
), indexingPolicy(p
.indexing_policy
),
62 warmupBound((p
.warmup_percentage
/100.0) * (p
.size
/ p
.block_size
)),
63 warmedUp(false), numBlocks(p
.size
/ p
.block_size
),
64 dataBlks(new uint8_t[p
.size
]), // Allocate data storage in one big chunk
67 registerExitCallback([this]() { cleanupRefs(); });
71 BaseTags::findBlockBySetAndWay(int set
, int way
) const
73 return indexingPolicy
->getEntry(set
, way
);
77 BaseTags::findBlock(Addr addr
, bool is_secure
) const
80 Addr tag
= extractTag(addr
);
82 // Find possible entries that may contain the given address
83 const std::vector
<ReplaceableEntry
*> entries
=
84 indexingPolicy
->getPossibleEntries(addr
);
87 for (const auto& location
: entries
) {
88 CacheBlk
* blk
= static_cast<CacheBlk
*>(location
);
89 if (blk
->matchTag(tag
, is_secure
)) {
99 BaseTags::insertBlock(const PacketPtr pkt
, CacheBlk
*blk
)
101 assert(!blk
->isValid());
103 // Previous block, if existed, has been removed, and now we have
104 // to insert the new one
106 // Deal with what we are bringing in
107 RequestorID requestor_id
= pkt
->req
->requestorId();
108 assert(requestor_id
< system
->maxRequestors());
109 stats
.occupancies
[requestor_id
]++;
111 // Insert block with tag, src requestor id and task id
112 blk
->insert(extractTag(pkt
->getAddr()), pkt
->isSecure(), requestor_id
,
115 // Check if cache warm up is done
116 if (!warmedUp
&& stats
.tagsInUse
.value() >= warmupBound
) {
118 stats
.warmupTick
= curTick();
121 // We only need to write into one tag and one data block.
122 stats
.tagAccesses
+= 1;
123 stats
.dataAccesses
+= 1;
127 BaseTags::moveBlock(CacheBlk
*src_blk
, CacheBlk
*dest_blk
)
129 assert(!dest_blk
->isValid());
130 assert(src_blk
->isValid());
132 // Move src's contents to dest's
133 *dest_blk
= std::move(*src_blk
);
135 assert(dest_blk
->isValid());
136 assert(!src_blk
->isValid());
140 BaseTags::extractTag(const Addr addr
) const
142 return indexingPolicy
->extractTag(addr
);
146 BaseTags::cleanupRefsVisitor(CacheBlk
&blk
)
149 stats
.totalRefs
+= blk
.getRefCount();
155 BaseTags::cleanupRefs()
157 forEachBlk([this](CacheBlk
&blk
) { cleanupRefsVisitor(blk
); });
161 BaseTags::computeStatsVisitor(CacheBlk
&blk
)
164 const uint32_t task_id
= blk
.getTaskId();
165 assert(task_id
< ContextSwitchTaskId::NumTaskId
);
166 stats
.occupanciesTaskId
[task_id
]++;
167 Tick age
= blk
.getAge();
170 if (age
/ SimClock::Int::us
< 10) { // <10us
172 } else if (age
/ SimClock::Int::us
< 100) { // <100us
174 } else if (age
/ SimClock::Int::ms
< 1) { // <1ms
176 } else if (age
/ SimClock::Int::ms
< 10) { // <10ms
179 age_index
= 4; // >10ms
181 stats
.ageTaskId
[task_id
][age_index
]++;
186 BaseTags::computeStats()
188 for (unsigned i
= 0; i
< ContextSwitchTaskId::NumTaskId
; ++i
) {
189 stats
.occupanciesTaskId
[i
] = 0;
190 for (unsigned j
= 0; j
< 5; ++j
) {
191 stats
.ageTaskId
[i
][j
] = 0;
195 forEachBlk([this](CacheBlk
&blk
) { computeStatsVisitor(blk
); });
203 auto print_blk
= [&str
](CacheBlk
&blk
) {
205 str
+= csprintf("\tBlock: %s\n", blk
.print());
207 forEachBlk(print_blk
);
210 str
= "no valid tags\n";
215 BaseTags::BaseTagStats::BaseTagStats(BaseTags
&_tags
)
216 : Stats::Group(&_tags
),
219 ADD_STAT(tagsInUse
, UNIT_RATE(Stats::Units::Tick
, Stats::Units::Count
),
220 "Average ticks per tags in use"),
221 ADD_STAT(totalRefs
, UNIT_COUNT
,
222 "Total number of references to valid blocks."),
223 ADD_STAT(sampledRefs
, UNIT_COUNT
,
224 "Sample count of references to valid blocks."),
225 ADD_STAT(avgRefs
, UNIT_RATE(Stats::Units::Count
, Stats::Units::Count
),
226 "Average number of references to valid blocks."),
227 ADD_STAT(warmupTick
, UNIT_TICK
,
228 "The tick when the warmup percentage was hit."),
229 ADD_STAT(occupancies
, UNIT_RATE(Stats::Units::Count
, Stats::Units::Tick
),
230 "Average occupied blocks per tick, per requestor"),
231 ADD_STAT(avgOccs
, UNIT_RATE(Stats::Units::Ratio
, Stats::Units::Tick
),
232 "Average percentage of cache occupancy"),
233 ADD_STAT(occupanciesTaskId
, UNIT_COUNT
, "Occupied blocks per task id"),
234 ADD_STAT(ageTaskId
, UNIT_COUNT
,
235 "Occupied blocks per task id, per block age"),
236 ADD_STAT(ratioOccsTaskId
, UNIT_RATIO
,
237 "Ratio of occupied blocks and all blocks, per task id"),
238 ADD_STAT(tagAccesses
, UNIT_COUNT
, "Number of tag accesses"),
239 ADD_STAT(dataAccesses
, UNIT_COUNT
, "Number of data accesses")
244 BaseTags::BaseTagStats::regStats()
246 using namespace Stats
;
248 Stats::Group::regStats();
250 System
*system
= tags
.system
;
252 avgRefs
= totalRefs
/ sampledRefs
;
255 .init(system
->maxRequestors())
256 .flags(nozero
| nonan
)
258 for (int i
= 0; i
< system
->maxRequestors(); i
++) {
259 occupancies
.subname(i
, system
->getRequestorName(i
));
262 avgOccs
.flags(nozero
| total
);
263 for (int i
= 0; i
< system
->maxRequestors(); i
++) {
264 avgOccs
.subname(i
, system
->getRequestorName(i
));
267 avgOccs
= occupancies
/ Stats::constant(tags
.numBlocks
);
270 .init(ContextSwitchTaskId::NumTaskId
)
271 .flags(nozero
| nonan
)
275 .init(ContextSwitchTaskId::NumTaskId
, 5)
276 .flags(nozero
| nonan
)
279 ratioOccsTaskId
.flags(nozero
);
281 ratioOccsTaskId
= occupanciesTaskId
/ Stats::constant(tags
.numBlocks
);
285 BaseTags::BaseTagStats::preDumpStats()
287 Stats::Group::preDumpStats();