gem5 [DEVELOP-FOR-25.1]
Loading...
Searching...
No Matches
sector_tags.cc
Go to the documentation of this file.
1/*
2 * Copyright (c) 2024 ARM Limited
3 *
4 * The license below extends only to copyright in the software and shall
5 * not be construed as granting a license to any other intellectual
6 * property including but not limited to intellectual property relating
7 * to a hardware implementation of the functionality of the software
8 * licensed hereunder. You may use the software subject to the license
9 * terms below provided that you ensure that this notice is replicated
10 * unmodified and in its entirety in all distributions of the software,
11 * modified or unmodified, in source code or in binary form.
12 *
13 * Copyright (c) 2018, 2020 Inria
14 * All rights reserved.
15 *
16 * Redistribution and use in source and binary forms, with or without
17 * modification, are permitted provided that the following conditions are
18 * met: redistributions of source code must retain the above copyright
19 * notice, this list of conditions and the following disclaimer;
20 * redistributions in binary form must reproduce the above copyright
21 * notice, this list of conditions and the following disclaimer in the
22 * documentation and/or other materials provided with the distribution;
23 * neither the name of the copyright holders nor the names of its
24 * contributors may be used to endorse or promote products derived from
25 * this software without specific prior written permission.
26 *
27 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
28 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
29 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
30 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
31 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
32 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
33 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
34 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
35 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
36 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
37 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
38 */
39
44
46
47#include <cassert>
48#include <memory>
49#include <string>
50
51#include "base/intmath.hh"
52#include "base/logging.hh"
53#include "base/types.hh"
58
59namespace gem5
60{
61
62SectorTags::SectorTags(const SectorTagsParams &p)
63 : BaseTags(p), allocAssoc(p.assoc),
64 sequentialAccess(p.sequential_access),
66 numBlocksPerSector(p.num_blocks_per_sector),
69 sectorStats(stats, *this)
70{
71 // There must be a indexing policy
72 fatal_if(!p.indexing_policy, "An indexing policy is required");
73
74 // Check parameters
76 "Block size must be at least 4 and a power of 2");
78 "# of blocks per sector must be non-zero and a power of 2");
80 "Using cache partitioning policies with sector and/or compressed "
81 "tags is not fully tested.");
82}
83
84void
86{
87 // Create blocks and sector blocks
90
91 // Initialize all blocks
92 unsigned blk_index = 0; // index into blks array
93 for (unsigned sec_blk_index = 0; sec_blk_index < numSectors;
94 sec_blk_index++)
95 {
96 // Locate next cache sector
97 SectorBlk* sec_blk = &secBlks[sec_blk_index];
98
99 // Associate a replacement data entry to the sector
100 sec_blk->replacementData = replacementPolicy->instantiateEntry();
101
102 // Initialize all blocks in this sector
103 sec_blk->blks.resize(numBlocksPerSector);
104 for (unsigned k = 0; k < numBlocksPerSector; ++k){
105 // Select block within the set to be linked
106 SectorSubBlk*& blk = sec_blk->blks[k];
107
108 // Locate next cache block
109 blk = &blks[blk_index];
110
111 // Associate a data chunk to the block
112 blk->data = &dataBlks[blkSize*blk_index];
113
114 // Associate sector block to this block
115 blk->setSectorBlock(sec_blk);
116
117 // Associate the sector replacement data to this block
118 blk->replacementData = sec_blk->replacementData;
119
120 // Set its index and sector offset
121 blk->setSectorOffset(k);
122
123 // Update block index
124 ++blk_index;
125 }
126
127 // Link block to indexing policy
128 indexingPolicy->setEntry(sec_blk, sec_blk_index);
129 }
130}
131
132void
134{
136
137 // Get block's sector
138 SectorSubBlk* sub_blk = static_cast<SectorSubBlk*>(blk);
139 const SectorBlk* sector_blk = sub_blk->getSectorBlock();
140
141 // When a block in a sector is invalidated, it does not make the tag
142 // invalid automatically, as there might be other blocks in the sector
143 // using it. The tag is invalidated only when there is a single block
144 // in the sector.
145 if (!sector_blk->isValid()) {
146 // Decrease the number of tags in use
147 stats.tagsInUse--;
148 assert(stats.tagsInUse.value() >= 0);
149
150 // Invalidate replacement data, as we're invalidating the sector
151 replacementPolicy->invalidate(sector_blk->replacementData);
152 }
153}
154
157{
158 CacheBlk *blk = findBlock({pkt->getAddr(), pkt->isSecure()});
159
160 // Access all tags in parallel, hence one in each way. The data side
161 // either accesses all blocks in parallel, or one block sequentially on
162 // a hit. Sequential access with a miss doesn't access data.
163 stats.tagAccesses += allocAssoc;
164 if (sequentialAccess) {
165 if (blk != nullptr) {
166 stats.dataAccesses += 1;
167 }
168 } else {
169 stats.dataAccesses += allocAssoc*numBlocksPerSector;
170 }
171
172 // If a cache hit
173 if (blk != nullptr) {
174 // Update number of references to accessed block
175 blk->increaseRefCount();
176
177 // Get block's sector
178 SectorSubBlk* sub_blk = static_cast<SectorSubBlk*>(blk);
179 const SectorBlk* sector_blk = sub_blk->getSectorBlock();
180
181 // Update replacement data of accessed block, which is shared with
182 // the whole sector it belongs to
183 replacementPolicy->touch(sector_blk->replacementData, pkt);
184 }
185
186 // The tag lookup latency is the same for a hit or a miss
187 lat = lookupLatency;
188
189 return blk;
190}
191
192void
194{
195 // Get block's sector
196 SectorSubBlk* sub_blk = static_cast<SectorSubBlk*>(blk);
197 const SectorBlk* sector_blk = sub_blk->getSectorBlock();
198
199 // When a block is inserted, the tag is only a newly used tag if the
200 // sector was not previously present in the cache.
201 if (sector_blk->isValid()) {
202 // An existing entry's replacement data is just updated
203 replacementPolicy->touch(sector_blk->replacementData, pkt);
204 } else {
205 // Increment tag counter
206 stats.tagsInUse++;
207 assert(stats.tagsInUse.value() <= numSectors);
208
209 // A new entry resets the replacement data
210 replacementPolicy->reset(sector_blk->replacementData, pkt);
211 }
212
213 // Do common block insertion functionality
214 BaseTags::insertBlock(pkt, blk);
215}
216
217void
219{
220 const bool dest_was_valid =
221 static_cast<SectorSubBlk*>(dest_blk)->getSectorBlock()->isValid();
222
223 BaseTags::moveBlock(src_blk, dest_blk);
224
225 // Get blocks' sectors. The blocks have effectively been swapped by now,
226 // so src points to an invalid block, and dest to the moved valid one.
227 SectorSubBlk* src_sub_blk = static_cast<SectorSubBlk*>(src_blk);
228 const SectorBlk* src_sector_blk = src_sub_blk->getSectorBlock();
229 SectorSubBlk* dest_sub_blk = static_cast<SectorSubBlk*>(dest_blk);
230 const SectorBlk* dest_sector_blk = dest_sub_blk->getSectorBlock();
231
232 // Since the blocks were using different replacement data pointers,
233 // we must touch the replacement data of the new entry, and invalidate
234 // the one that is being moved.
235 // When a block in a sector is invalidated, it does not make the tag
236 // invalid automatically, as there might be other blocks in the sector
237 // using it. The tag is invalidated only when there is a single block
238 // in the sector.
239 if (!src_sector_blk->isValid()) {
240 // Invalidate replacement data, as we're invalidating the sector
241 replacementPolicy->invalidate(src_sector_blk->replacementData);
242
243 if (dest_was_valid) {
244 // If destination sector was valid, and the source sector became
245 // invalid, there is one less tag being used
246 stats.tagsInUse--;
247 assert(stats.tagsInUse.value() >= 0);
248 }
249 } else if (!dest_was_valid) {
250 // If destination sector was invalid and became valid, and the source
251 // sector is still valid, there is one extra tag being used
252 stats.tagsInUse++;
253 assert(stats.tagsInUse.value() <= numSectors);
254 }
255
256 if (dest_was_valid) {
257 replacementPolicy->touch(dest_sector_blk->replacementData);
258 } else {
259 replacementPolicy->reset(dest_sector_blk->replacementData);
260 }
261}
262
265{
266 // The address can only be mapped to a specific location of a sector
267 // due to sectors being composed of contiguous-address entries
269
270 // Find all possible sector entries that may contain the given address
271 const std::vector<ReplaceableEntry*> entries =
272 indexingPolicy->getPossibleEntries(key);
273
274 // Search for block
275 for (const auto& sector : entries) {
276 auto blk = static_cast<SectorBlk*>(sector)->blks[offset];
277 if (blk->match(key)) {
278 return blk;
279 }
280 }
281
282 // Did not find block
283 return nullptr;
284}
285
288 const std::size_t size,
289 std::vector<CacheBlk*>& evict_blks,
290 const uint64_t partition_id)
291{
292 // Get possible entries to be victimized
293 std::vector<ReplaceableEntry*> sector_entries =
294 indexingPolicy->getPossibleEntries(key);
295
296 // Filter entries based on PartitionID
298 partitionManager->filterByPartition(sector_entries, partition_id);
299
300 // Check if the sector this address belongs to has been allocated
301 SectorBlk* victim_sector = nullptr;
302 for (const auto& sector : sector_entries) {
303 SectorBlk* sector_blk = static_cast<SectorBlk*>(sector);
304 if (sector_blk->match(key)) {
305 victim_sector = sector_blk;
306 break;
307 }
308 }
309
310 // If the sector is not present
311 if (victim_sector == nullptr){
312 // check if partitioning policy limited allocation and if true - return
313 // this assumes that sector_entries would not be empty if partitioning
314 // policy is not in place
315 if (sector_entries.size() == 0){
316 return nullptr;
317 }
318 // Choose replacement victim from replacement candidates
319 victim_sector = static_cast<SectorBlk*>(replacementPolicy->getVictim(
320 sector_entries));
321 }
322
323 // Get the entry of the victim block within the sector
324 SectorSubBlk* victim = victim_sector->blks[
326
327 // Get evicted blocks. Blocks are only evicted if the sectors mismatch and
328 // the currently existing sector is valid.
329 if (victim_sector->match(key)) {
330 // It would be a hit if victim was valid, and upgrades do not call
331 // findVictim, so it cannot happen
332 assert(!victim->isValid());
333 } else {
334 // The whole sector must be evicted to make room for the new sector
335 for (const auto& blk : victim_sector->blks){
336 if (blk->isValid()) {
337 evict_blks.push_back(blk);
338 }
339 }
340 }
341
342 // Update number of sub-blocks evicted due to a replacement
343 sectorStats.evictionsReplacement[evict_blks.size()]++;
344
345 return victim;
346}
347
348int
353
354Addr
356{
357 const SectorSubBlk* blk_cast = static_cast<const SectorSubBlk*>(blk);
358 const SectorBlk* sec_blk = blk_cast->getSectorBlock();
359 const Addr sec_addr =
360 indexingPolicy->regenerateAddr(
361 {blk->getTag(), blk->isSecure()}, sec_blk);
362 return sec_addr | ((Addr)blk_cast->getSectorOffset() << sectorShift);
363}
364
366 SectorTags& _tags)
367 : statistics::Group(&base_group), tags(_tags),
369 "Number of blocks evicted due to a replacement")
370{
371}
372
373void
375{
377
378 evictionsReplacement.init(tags.numBlocksPerSector + 1);
379 for (unsigned i = 0; i <= tags.numBlocksPerSector; ++i) {
380 evictionsReplacement.subname(i, std::to_string(i));
381 evictionsReplacement.subdesc(i, "Number of replacements that caused " \
382 "the eviction of " + std::to_string(i) + " blocks");
383 }
384}
385
386bool
387SectorTags::anyBlk(std::function<bool(CacheBlk &)> visitor)
388{
389 for (SectorSubBlk& blk : blks) {
390 if (visitor(blk)) {
391 return true;
392 }
393 }
394 return false;
395}
396
397} // namespace gem5
Defines global host-dependent types: Counter, Tick, and (indirectly) {int,uint}{8,...
partitioning_policy::PartitionManager * partitionManager
Partitioning manager.
Definition base.hh:92
virtual void insertBlock(const PacketPtr pkt, CacheBlk *blk)
Insert the new block into the cache and update stats.
Definition base.cc:101
BaseTags(const Params &p)
Definition base.cc:62
const unsigned size
The size of the cache.
Definition base.hh:81
const unsigned numBlocks
the number of blocks in the cache
Definition base.hh:103
virtual void invalidate(CacheBlk *blk)
This function updates the tags when a block is invalidated.
Definition base.hh:257
gem5::BaseTags::BaseTagStats stats
virtual void moveBlock(CacheBlk *src_blk, CacheBlk *dest_blk)
Move a block's metadata to another location decided by the replacement policy.
Definition base.cc:131
std::unique_ptr< uint8_t[]> dataBlks
The data blocks, 1 per cache block.
Definition base.hh:106
const Cycles lookupLatency
The tag lookup latency of the cache.
Definition base.hh:83
TaggedIndexingPolicy * indexingPolicy
Indexing policy.
Definition base.hh:89
const unsigned blkSize
The block size of the cache.
Definition base.hh:77
A Basic Cache block.
Definition cache_blk.hh:72
void increaseRefCount()
Get the number of references to this block since insertion.
Definition cache_blk.hh:300
uint8_t * data
Contains a copy of the data in this block for easy access.
Definition cache_blk.hh:104
Cycles is a wrapper class for representing cycle counts, i.e.
Definition types.hh:79
bool isSecure() const
Definition packet.hh:836
Addr getAddr() const
Definition packet.hh:807
std::shared_ptr< replacement_policy::ReplacementData > replacementData
Replacement data associated to this entry.
A Basic Sector block.
std::vector< SectorSubBlk * > blks
List of blocks associated to this sector.
bool isValid() const override
Checks that a sector block is valid.
A sector is composed of sub-blocks, and each sub-block has information regarding its sector and a poi...
Definition sector_blk.hh:52
int getSectorOffset() const
Get offset of this sub-block within the sector.
Definition sector_blk.cc:64
void setSectorBlock(SectorBlk *sector_blk)
Set sector block associated to this block.
Definition sector_blk.cc:45
void setSectorOffset(const int sector_offset)
Set offset of this sub-block within the sector.
Definition sector_blk.cc:58
SectorBlk * getSectorBlock() const
Get sector block associated to this block.
Definition sector_blk.cc:52
Addr regenerateBlkAddr(const CacheBlk *blk) const override
Regenerate the block address from the tag and location.
const unsigned sectorMask
Mask out all bits that aren't part of the sector tag.
CacheBlk * findBlock(const CacheBlk::KeyType &key) const override
Finds the given address in the cache, do not update replacement data.
std::vector< SectorSubBlk > blks
The cache blocks.
replacement_policy::Base * replacementPolicy
Replacement policy.
gem5::SectorTags::SectorTagsStats sectorStats
int extractSectorOffset(Addr addr) const
Calculate a block's offset in a sector from the address.
SectorTags(const Params &p)
Construct and initialize this tag store.
std::vector< SectorBlk > secBlks
The cache sector blocks.
const bool sequentialAccess
Whether tags and data are accessed sequentially.
bool anyBlk(std::function< bool(CacheBlk &)> visitor) override
Find if any of the sub-blocks satisfies a condition.
void tagsInit() override
Initialize blocks as SectorBlk and SectorSubBlk instances.
void insertBlock(const PacketPtr pkt, CacheBlk *blk) override
Insert the new block into the cache and update replacement data.
CacheBlk * findVictim(const CacheBlk::KeyType &key, const std::size_t size, std::vector< CacheBlk * > &evict_blks, const uint64_t partition_id) override
Find replacement victim based on address.
const unsigned numSectors
The number of sectors in the cache.
const unsigned numBlocksPerSector
Number of data blocks per sector.
const int sectorShift
The amount to shift the address to get the sector tag.
unsigned allocAssoc
The allocatable associativity of the cache (alloc mask).
void invalidate(CacheBlk *blk) override
This function updates the tags when a block is invalidated but does not invalidate the block itself.
CacheBlk * accessBlock(const PacketPtr pkt, Cycles &lat) override
Access block and update replacement data.
void moveBlock(CacheBlk *src_blk, CacheBlk *dest_blk) override
Move a block's metadata to another location decided by the replacement policy.
virtual bool isValid() const
Checks if the entry is valid.
bool match(const KeyType &key) const
Checks if the given tag information corresponds to this entry's.
TaggedTypes::KeyType KeyType
bool isSecure() const
Check if this block holds data from the secure memory space.
virtual Addr getTag() const
Get tag associated to this block.
STL vector class.
Definition stl.hh:37
#define ADD_STAT(n,...)
Convenience macro to add a stat to a statistics group.
Definition group.hh:75
static constexpr std::enable_if_t< std::is_integral_v< T >, int > floorLog2(T x)
Definition intmath.hh:59
static constexpr bool isPowerOf2(const T &n)
Definition intmath.hh:98
#define fatal_if(cond,...)
Conditional fatal macro that checks the supplied condition and only causes a fatal error if the condi...
Definition logging.hh:268
virtual void regStats()
Callback to set stat parameters.
Definition group.cc:68
#define warn_if(cond,...)
Conditional warning macro that checks the supplied condition and only prints a warning if the conditi...
Definition logging.hh:315
Declaration of a common framework for indexing policies.
Bitfield< 7 > i
Definition misc_types.hh:67
Bitfield< 23, 0 > offset
Definition types.hh:144
Bitfield< 0 > p
Bitfield< 23 > k
Bitfield< 3 > addr
Definition types.hh:84
Units for Stats.
Definition units.hh:113
Copyright (c) 2024 Arm Limited All rights reserved.
Definition binary32.hh:36
uint64_t Addr
Address type This will probably be moved somewhere else in the near future.
Definition types.hh:147
Packet * PacketPtr
Declaration of a sector tag store.
TODO: It would be good if these stats were acquired after warmup.
Definition base.hh:112
void regStats() override
Callback to set stat parameters.
statistics::Vector evictionsReplacement
Number of sub-blocks evicted due to a replacement.
SectorTagsStats(BaseTagStats &base_group, SectorTags &_tags)

Generated on Mon Oct 27 2025 04:13:03 for gem5 by doxygen 1.14.0