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.
40 * Authors: Erik Hallnor
46 * Definitions of BaseTags.
49 #include "mem/cache/tags/base.hh"
53 #include "base/types.hh"
54 #include "mem/cache/replacement_policies/replaceable_entry.hh"
55 #include "mem/cache/tags/indexing_policies/base.hh"
56 #include "mem/request.hh"
57 #include "sim/core.hh"
58 #include "sim/sim_exit.hh"
59 #include "sim/system.hh"
61 BaseTags::BaseTags(const Params
*p
)
62 : ClockedObject(p
), blkSize(p
->block_size
), blkMask(blkSize
- 1),
63 size(p
->size
), lookupLatency(p
->tag_latency
),
64 system(p
->system
), indexingPolicy(p
->indexing_policy
),
65 warmupBound((p
->warmup_percentage
/100.0) * (p
->size
/ p
->block_size
)),
66 warmedUp(false), numBlocks(p
->size
/ p
->block_size
),
67 dataBlks(new uint8_t[p
->size
]), // Allocate data storage in one big chunk
70 registerExitCallback(new BaseTagsCallback(this));
74 BaseTags::findBlockBySetAndWay(int set
, int way
) const
76 return indexingPolicy
->getEntry(set
, way
);
80 BaseTags::findBlock(Addr addr
, bool is_secure
) const
83 Addr tag
= extractTag(addr
);
85 // Find possible entries that may contain the given address
86 const std::vector
<ReplaceableEntry
*> entries
=
87 indexingPolicy
->getPossibleEntries(addr
);
90 for (const auto& location
: entries
) {
91 CacheBlk
* blk
= static_cast<CacheBlk
*>(location
);
92 if ((blk
->tag
== tag
) && blk
->isValid() &&
93 (blk
->isSecure() == is_secure
)) {
103 BaseTags::insertBlock(const PacketPtr pkt
, CacheBlk
*blk
)
105 assert(!blk
->isValid());
107 // Previous block, if existed, has been removed, and now we have
108 // to insert the new one
110 // Deal with what we are bringing in
111 MasterID master_id
= pkt
->req
->masterId();
112 assert(master_id
< system
->maxMasters());
113 stats
.occupancies
[master_id
]++;
115 // Insert block with tag, src master id and task id
116 blk
->insert(extractTag(pkt
->getAddr()), pkt
->isSecure(), master_id
,
119 // Check if cache warm up is done
120 if (!warmedUp
&& stats
.tagsInUse
.value() >= warmupBound
) {
122 stats
.warmupCycle
= curTick();
125 // We only need to write into one tag and one data block.
126 stats
.tagAccesses
+= 1;
127 stats
.dataAccesses
+= 1;
131 BaseTags::extractTag(const Addr addr
) const
133 return indexingPolicy
->extractTag(addr
);
137 BaseTags::cleanupRefsVisitor(CacheBlk
&blk
)
140 stats
.totalRefs
+= blk
.refCount
;
146 BaseTags::cleanupRefs()
148 forEachBlk([this](CacheBlk
&blk
) { cleanupRefsVisitor(blk
); });
152 BaseTags::computeStatsVisitor(CacheBlk
&blk
)
155 assert(blk
.task_id
< ContextSwitchTaskId::NumTaskId
);
156 stats
.occupanciesTaskId
[blk
.task_id
]++;
157 assert(blk
.tickInserted
<= curTick());
158 Tick age
= curTick() - blk
.tickInserted
;
161 if (age
/ SimClock::Int::us
< 10) { // <10us
163 } else if (age
/ SimClock::Int::us
< 100) { // <100us
165 } else if (age
/ SimClock::Int::ms
< 1) { // <1ms
167 } else if (age
/ SimClock::Int::ms
< 10) { // <10ms
170 age_index
= 4; // >10ms
172 stats
.ageTaskId
[blk
.task_id
][age_index
]++;
177 BaseTags::computeStats()
179 for (unsigned i
= 0; i
< ContextSwitchTaskId::NumTaskId
; ++i
) {
180 stats
.occupanciesTaskId
[i
] = 0;
181 for (unsigned j
= 0; j
< 5; ++j
) {
182 stats
.ageTaskId
[i
][j
] = 0;
186 forEachBlk([this](CacheBlk
&blk
) { computeStatsVisitor(blk
); });
194 auto print_blk
= [&str
](CacheBlk
&blk
) {
196 str
+= csprintf("\tBlock: %s\n", blk
.print());
198 forEachBlk(print_blk
);
201 str
= "no valid tags\n";
206 BaseTags::BaseTagStats::BaseTagStats(BaseTags
&_tags
)
207 : Stats::Group(&_tags
),
210 tagsInUse(this, "tagsinuse",
211 "Cycle average of tags in use"),
212 totalRefs(this, "total_refs",
213 "Total number of references to valid blocks."),
214 sampledRefs(this, "sampled_refs",
215 "Sample count of references to valid blocks."),
216 avgRefs(this, "avg_refs",
217 "Average number of references to valid blocks."),
218 warmupCycle(this, "warmup_cycle",
219 "Cycle when the warmup percentage was hit."),
220 occupancies(this, "occ_blocks",
221 "Average occupied blocks per requestor"),
222 avgOccs(this, "occ_percent",
223 "Average percentage of cache occupancy"),
224 occupanciesTaskId(this, "occ_task_id_blocks",
225 "Occupied blocks per task id"),
226 ageTaskId(this, "age_task_id_blocks", "Occupied blocks per task id"),
227 percentOccsTaskId(this, "occ_task_id_percent",
228 "Percentage of cache occupancy per task id"),
229 tagAccesses(this, "tag_accesses", "Number of tag accesses"),
230 dataAccesses(this, "data_accesses", "Number of data accesses")
235 BaseTags::BaseTagStats::regStats()
237 using namespace Stats
;
239 Stats::Group::regStats();
241 System
*system
= tags
.system
;
243 avgRefs
= totalRefs
/ sampledRefs
;
246 .init(system
->maxMasters())
247 .flags(nozero
| nonan
)
249 for (int i
= 0; i
< system
->maxMasters(); i
++) {
250 occupancies
.subname(i
, system
->getMasterName(i
));
253 avgOccs
.flags(nozero
| total
);
254 for (int i
= 0; i
< system
->maxMasters(); i
++) {
255 avgOccs
.subname(i
, system
->getMasterName(i
));
258 avgOccs
= occupancies
/ Stats::constant(tags
.numBlocks
);
261 .init(ContextSwitchTaskId::NumTaskId
)
262 .flags(nozero
| nonan
)
266 .init(ContextSwitchTaskId::NumTaskId
, 5)
267 .flags(nozero
| nonan
)
270 percentOccsTaskId
.flags(nozero
);
272 percentOccsTaskId
= occupanciesTaskId
/ Stats::constant(tags
.numBlocks
);
276 BaseTags::BaseTagStats::preDumpStats()
278 Stats::Group::preDumpStats();