gem5 v24.0.0.0
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
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"
54#include "mem/cache/base.hh"
59
60namespace gem5
61{
62
63SectorTags::SectorTags(const SectorTagsParams &p)
64 : BaseTags(p), allocAssoc(p.assoc),
65 sequentialAccess(p.sequential_access),
66 replacementPolicy(p.replacement_policy),
67 numBlocksPerSector(p.num_blocks_per_sector),
68 numSectors(numBlocks / numBlocksPerSector),
69 sectorShift(floorLog2(blkSize)), sectorMask(numBlocksPerSector - 1),
70 sectorStats(stats, *this)
71{
72 // There must be a indexing policy
73 fatal_if(!p.indexing_policy, "An indexing policy is required");
74
75 // Check parameters
77 "Block size must be at least 4 and a power of 2");
79 "# of blocks per sector must be non-zero and a power of 2");
81 "Using cache partitioning policies with sector and/or compressed "
82 "tags is not fully tested.");
83}
84
85void
87{
88 // Create blocks and sector blocks
91
92 // Initialize all blocks
93 unsigned blk_index = 0; // index into blks array
94 for (unsigned sec_blk_index = 0; sec_blk_index < numSectors;
95 sec_blk_index++)
96 {
97 // Locate next cache sector
98 SectorBlk* sec_blk = &secBlks[sec_blk_index];
99
100 // Associate a replacement data entry to the sector
102
103 // Initialize all blocks in this sector
104 sec_blk->blks.resize(numBlocksPerSector);
105 for (unsigned k = 0; k < numBlocksPerSector; ++k){
106 // Select block within the set to be linked
107 SectorSubBlk*& blk = sec_blk->blks[k];
108
109 // Locate next cache block
110 blk = &blks[blk_index];
111
112 // Associate a data chunk to the block
113 blk->data = &dataBlks[blkSize*blk_index];
114
115 // Associate sector block to this block
116 blk->setSectorBlock(sec_blk);
117
118 // Associate the sector replacement data to this block
119 blk->replacementData = sec_blk->replacementData;
120
121 // Set its index and sector offset
122 blk->setSectorOffset(k);
123
124 // Update block index
125 ++blk_index;
126 }
127
128 // Link block to indexing policy
129 indexingPolicy->setEntry(sec_blk, sec_blk_index);
130 }
131}
132
133void
135{
137
138 // Get block's sector
139 SectorSubBlk* sub_blk = static_cast<SectorSubBlk*>(blk);
140 const SectorBlk* sector_blk = sub_blk->getSectorBlock();
141
142 // When a block in a sector is invalidated, it does not make the tag
143 // invalid automatically, as there might be other blocks in the sector
144 // using it. The tag is invalidated only when there is a single block
145 // in the sector.
146 if (!sector_blk->isValid()) {
147 // Decrease the number of tags in use
149 assert(stats.tagsInUse.value() >= 0);
150
151 // Invalidate replacement data, as we're invalidating the sector
153 }
154}
155
158{
159 CacheBlk *blk = findBlock(pkt->getAddr(), pkt->isSecure());
160
161 // Access all tags in parallel, hence one in each way. The data side
162 // either accesses all blocks in parallel, or one block sequentially on
163 // a hit. Sequential access with a miss doesn't access data.
165 if (sequentialAccess) {
166 if (blk != nullptr) {
167 stats.dataAccesses += 1;
168 }
169 } else {
171 }
172
173 // If a cache hit
174 if (blk != nullptr) {
175 // Update number of references to accessed block
176 blk->increaseRefCount();
177
178 // Get block's sector
179 SectorSubBlk* sub_blk = static_cast<SectorSubBlk*>(blk);
180 const SectorBlk* sector_blk = sub_blk->getSectorBlock();
181
182 // Update replacement data of accessed block, which is shared with
183 // the whole sector it belongs to
184 replacementPolicy->touch(sector_blk->replacementData, pkt);
185 }
186
187 // The tag lookup latency is the same for a hit or a miss
188 lat = lookupLatency;
189
190 return blk;
191}
192
193void
195{
196 // Get block's sector
197 SectorSubBlk* sub_blk = static_cast<SectorSubBlk*>(blk);
198 const SectorBlk* sector_blk = sub_blk->getSectorBlock();
199
200 // When a block is inserted, the tag is only a newly used tag if the
201 // sector was not previously present in the cache.
202 if (sector_blk->isValid()) {
203 // An existing entry's replacement data is just updated
204 replacementPolicy->touch(sector_blk->replacementData, pkt);
205 } else {
206 // Increment tag counter
208 assert(stats.tagsInUse.value() <= numSectors);
209
210 // A new entry resets the replacement data
211 replacementPolicy->reset(sector_blk->replacementData, pkt);
212 }
213
214 // Do common block insertion functionality
215 BaseTags::insertBlock(pkt, blk);
216}
217
218void
220{
221 const bool dest_was_valid =
222 static_cast<SectorSubBlk*>(dest_blk)->getSectorBlock()->isValid();
223
224 BaseTags::moveBlock(src_blk, dest_blk);
225
226 // Get blocks' sectors. The blocks have effectively been swapped by now,
227 // so src points to an invalid block, and dest to the moved valid one.
228 SectorSubBlk* src_sub_blk = static_cast<SectorSubBlk*>(src_blk);
229 const SectorBlk* src_sector_blk = src_sub_blk->getSectorBlock();
230 SectorSubBlk* dest_sub_blk = static_cast<SectorSubBlk*>(dest_blk);
231 const SectorBlk* dest_sector_blk = dest_sub_blk->getSectorBlock();
232
233 // Since the blocks were using different replacement data pointers,
234 // we must touch the replacement data of the new entry, and invalidate
235 // the one that is being moved.
236 // When a block in a sector is invalidated, it does not make the tag
237 // invalid automatically, as there might be other blocks in the sector
238 // using it. The tag is invalidated only when there is a single block
239 // in the sector.
240 if (!src_sector_blk->isValid()) {
241 // Invalidate replacement data, as we're invalidating the sector
243
244 if (dest_was_valid) {
245 // If destination sector was valid, and the source sector became
246 // invalid, there is one less tag being used
248 assert(stats.tagsInUse.value() >= 0);
249 }
250 } else if (!dest_was_valid) {
251 // If destination sector was invalid and became valid, and the source
252 // sector is still valid, there is one extra tag being used
254 assert(stats.tagsInUse.value() <= numSectors);
255 }
256
257 if (dest_was_valid) {
258 replacementPolicy->touch(dest_sector_blk->replacementData);
259 } else {
260 replacementPolicy->reset(dest_sector_blk->replacementData);
261 }
262}
263
265SectorTags::findBlock(Addr addr, bool is_secure) const
266{
267 // Extract sector tag
268 const Addr tag = extractTag(addr);
269
270 // The address can only be mapped to a specific location of a sector
271 // due to sectors being composed of contiguous-address entries
273
274 // Find all possible sector entries that may contain the given address
275 const std::vector<ReplaceableEntry*> entries =
277
278 // Search for block
279 for (const auto& sector : entries) {
280 auto blk = static_cast<SectorBlk*>(sector)->blks[offset];
281 if (blk->matchTag(tag, is_secure)) {
282 return blk;
283 }
284 }
285
286 // Did not find block
287 return nullptr;
288}
289
291SectorTags::findVictim(Addr addr, const bool is_secure, const std::size_t size,
292 std::vector<CacheBlk*>& evict_blks,
293 const uint64_t partition_id)
294{
295 // Get possible entries to be victimized
296 std::vector<ReplaceableEntry*> sector_entries =
298
299 // Filter entries based on PartitionID
301 partitionManager->filterByPartition(sector_entries, partition_id);
302
303 // Check if the sector this address belongs to has been allocated
304 Addr tag = extractTag(addr);
305 SectorBlk* victim_sector = nullptr;
306 for (const auto& sector : sector_entries) {
307 SectorBlk* sector_blk = static_cast<SectorBlk*>(sector);
308 if (sector_blk->matchTag(tag, is_secure)) {
309 victim_sector = sector_blk;
310 break;
311 }
312 }
313
314 // If the sector is not present
315 if (victim_sector == nullptr){
316 // check if partitioning policy limited allocation and if true - return
317 // this assumes that sector_entries would not be empty if partitioning
318 // policy is not in place
319 if (sector_entries.size() == 0){
320 return nullptr;
321 }
322 // Choose replacement victim from replacement candidates
323 victim_sector = static_cast<SectorBlk*>(replacementPolicy->getVictim(
324 sector_entries));
325 }
326
327 // Get the entry of the victim block within the sector
328 SectorSubBlk* victim = victim_sector->blks[extractSectorOffset(addr)];
329
330 // Get evicted blocks. Blocks are only evicted if the sectors mismatch and
331 // the currently existing sector is valid.
332 if (victim_sector->matchTag(tag, is_secure)) {
333 // It would be a hit if victim was valid, and upgrades do not call
334 // findVictim, so it cannot happen
335 assert(!victim->isValid());
336 } else {
337 // The whole sector must be evicted to make room for the new sector
338 for (const auto& blk : victim_sector->blks){
339 if (blk->isValid()) {
340 evict_blks.push_back(blk);
341 }
342 }
343 }
344
345 // Update number of sub-blocks evicted due to a replacement
346 sectorStats.evictionsReplacement[evict_blks.size()]++;
347
348 return victim;
349}
350
351int
356
357Addr
359{
360 const SectorSubBlk* blk_cast = static_cast<const SectorSubBlk*>(blk);
361 const SectorBlk* sec_blk = blk_cast->getSectorBlock();
362 const Addr sec_addr =
363 indexingPolicy->regenerateAddr(blk->getTag(), sec_blk);
364 return sec_addr | ((Addr)blk_cast->getSectorOffset() << sectorShift);
365}
366
368 SectorTags& _tags)
369 : statistics::Group(&base_group), tags(_tags),
370 ADD_STAT(evictionsReplacement, statistics::units::Count::get(),
371 "Number of blocks evicted due to a replacement")
372{
373}
374
375void
377{
379
380 evictionsReplacement.init(tags.numBlocksPerSector + 1);
381 for (unsigned i = 0; i <= tags.numBlocksPerSector; ++i) {
382 evictionsReplacement.subname(i, std::to_string(i));
383 evictionsReplacement.subdesc(i, "Number of replacements that caused " \
384 "the eviction of " + std::to_string(i) + " blocks");
385 }
386}
387
388bool
389SectorTags::anyBlk(std::function<bool(CacheBlk &)> visitor)
390{
391 for (SectorSubBlk& blk : blks) {
392 if (visitor(blk)) {
393 return true;
394 }
395 }
396 return false;
397}
398
399} // namespace gem5
Defines global host-dependent types: Counter, Tick, and (indirectly) {int,uint}{8,...
virtual Addr regenerateAddr(const Addr tag, const ReplaceableEntry *entry) const =0
Regenerate an entry's address from its tag and assigned indexing bits.
void setEntry(ReplaceableEntry *entry, const uint64_t index)
Associate a pointer to an entry to its physical counterpart.
Definition base.cc:81
virtual std::vector< ReplaceableEntry * > getPossibleEntries(const Addr addr) const =0
Find all possible entries for insertion and replacement of an address.
A common base class of Cache tagstore objects.
Definition base.hh:74
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:104
virtual Addr extractTag(const Addr addr) const
Generate the tag from the given address.
Definition base.cc:147
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:134
BaseIndexingPolicy * indexingPolicy
Indexing policy.
Definition base.hh:89
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
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
virtual Addr getTag() const
Get tag associated to this block.
virtual bool isValid() const
Checks if the entry is valid.
Cycles is a wrapper class for representing cycle counts, i.e.
Definition types.hh:79
A Packet is used to encapsulate a transfer between two objects in the memory system (e....
Definition packet.hh:295
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
A SectorTags cache tag store.
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 * findVictim(Addr addr, const bool is_secure, const std::size_t size, std::vector< CacheBlk * > &evict_blks, const uint64_t partition_id) override
Find replacement victim based on address.
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.
CacheBlk * findBlock(Addr addr, bool is_secure) const override
Finds the given address in the cache, do not update replacement data.
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.
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 matchTag(Addr tag, bool is_secure) const
Checks if the given tag information corresponds to this entry's.
void filterByPartition(std::vector< ReplaceableEntry * > &entries, const uint64_t partition_id) const
virtual void invalidate(const std::shared_ptr< ReplacementData > &replacement_data)=0
Invalidate replacement data to set it as the next probable victim.
virtual void reset(const std::shared_ptr< ReplacementData > &replacement_data, const PacketPtr pkt)
Reset replacement data.
Definition base.hh:89
virtual void touch(const std::shared_ptr< ReplacementData > &replacement_data, const PacketPtr pkt)
Update replacement data.
Definition base.hh:75
virtual ReplaceableEntry * getVictim(const ReplacementCandidates &candidates) const =0
Find replacement victim among candidates.
virtual std::shared_ptr< ReplacementData > instantiateEntry()=0
Instantiate a replacement data entry.
Statistics container.
Definition group.hh:93
Counter value() const
Return the current value of this stat as its base type.
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:236
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:283
Declares a basic cache interface BaseCache.
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
Copyright (c) 2024 - Pranith Kumar Copyright (c) 2020 Inria 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
Declaration of a sector tag store.
TODO: It would be good if these stats were acquired after warmup.
Definition base.hh:112
statistics::Scalar tagAccesses
Number of tags consulted over all accesses.
Definition base.hh:158
statistics::Scalar dataAccesses
Number of data blocks consulted over all accesses.
Definition base.hh:160
statistics::Average tagsInUse
Per tick average of the number of tags that hold valid data.
Definition base.hh:121
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 Tue Jun 18 2024 16:24:05 for gem5 by doxygen 1.11.0