gem5  v20.1.0.0
sector_tags.cc
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2018 Inria
3  * All rights reserved.
4  *
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.
15  *
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.
27  */
28 
35 
36 #include <cassert>
37 #include <memory>
38 #include <string>
39 
40 #include "base/intmath.hh"
41 #include "base/logging.hh"
42 #include "base/types.hh"
43 #include "mem/cache/base.hh"
47 
48 SectorTags::SectorTags(const SectorTagsParams *p)
49  : BaseTags(p), allocAssoc(p->assoc),
50  sequentialAccess(p->sequential_access),
51  replacementPolicy(p->replacement_policy),
52  numBlocksPerSector(p->num_blocks_per_sector),
53  numSectors(numBlocks / numBlocksPerSector),
54  sectorShift(floorLog2(blkSize)), sectorMask(numBlocksPerSector - 1),
55  sectorStats(stats, *this)
56 {
57  // Check parameters
59  "Block size must be at least 4 and a power of 2");
61  "# of blocks per sector must be non-zero and a power of 2");
62 }
63 
64 void
66 {
67  // Create blocks and sector blocks
70 
71  // Initialize all blocks
72  unsigned blk_index = 0; // index into blks array
73  for (unsigned sec_blk_index = 0; sec_blk_index < numSectors;
74  sec_blk_index++)
75  {
76  // Locate next cache sector
77  SectorBlk* sec_blk = &secBlks[sec_blk_index];
78 
79  // Associate a replacement data entry to the sector
81 
82  // Initialize all blocks in this sector
83  sec_blk->blks.resize(numBlocksPerSector);
84  for (unsigned k = 0; k < numBlocksPerSector; ++k){
85  // Select block within the set to be linked
86  SectorSubBlk*& blk = sec_blk->blks[k];
87 
88  // Locate next cache block
89  blk = &blks[blk_index];
90 
91  // Associate a data chunk to the block
92  blk->data = &dataBlks[blkSize*blk_index];
93 
94  // Associate sector block to this block
95  blk->setSectorBlock(sec_blk);
96 
97  // Associate the sector replacement data to this block
98  blk->replacementData = sec_blk->replacementData;
99 
100  // Set its index and sector offset
101  blk->setSectorOffset(k);
102 
103  // Update block index
104  ++blk_index;
105  }
106 
107  // Link block to indexing policy
108  indexingPolicy->setEntry(sec_blk, sec_blk_index);
109  }
110 }
111 
112 void
114 {
116 
117  // Get block's sector
118  SectorSubBlk* sub_blk = static_cast<SectorSubBlk*>(blk);
119  const SectorBlk* sector_blk = sub_blk->getSectorBlock();
120 
121  // When a block in a sector is invalidated, it does not make the tag
122  // invalid automatically, as there might be other blocks in the sector
123  // using it. The tag is invalidated only when there is a single block
124  // in the sector.
125  if (!sector_blk->isValid()) {
126  // Decrease the number of tags in use
127  stats.tagsInUse--;
128 
129  // Invalidate replacement data, as we're invalidating the sector
131  }
132 }
133 
134 CacheBlk*
135 SectorTags::accessBlock(Addr addr, bool is_secure, Cycles &lat)
136 {
137  CacheBlk *blk = findBlock(addr, is_secure);
138 
139  // Access all tags in parallel, hence one in each way. The data side
140  // either accesses all blocks in parallel, or one block sequentially on
141  // a hit. Sequential access with a miss doesn't access data.
143  if (sequentialAccess) {
144  if (blk != nullptr) {
145  stats.dataAccesses += 1;
146  }
147  } else {
149  }
150 
151  // If a cache hit
152  if (blk != nullptr) {
153  // Update number of references to accessed block
154  blk->refCount++;
155 
156  // Get block's sector
157  SectorSubBlk* sub_blk = static_cast<SectorSubBlk*>(blk);
158  const SectorBlk* sector_blk = sub_blk->getSectorBlock();
159 
160  // Update replacement data of accessed block, which is shared with
161  // the whole sector it belongs to
163  }
164 
165  // The tag lookup latency is the same for a hit or a miss
166  lat = lookupLatency;
167 
168  return blk;
169 }
170 
171 void
173 {
174  // Get block's sector
175  SectorSubBlk* sub_blk = static_cast<SectorSubBlk*>(blk);
176  const SectorBlk* sector_blk = sub_blk->getSectorBlock();
177 
178  // When a block is inserted, the tag is only a newly used tag if the
179  // sector was not previously present in the cache.
180  if (sector_blk->isValid()) {
181  // An existing entry's replacement data is just updated
183  } else {
184  // Increment tag counter
185  stats.tagsInUse++;
186 
187  // A new entry resets the replacement data
189  }
190 
191  // Do common block insertion functionality
192  BaseTags::insertBlock(pkt, blk);
193 }
194 
195 CacheBlk*
196 SectorTags::findBlock(Addr addr, bool is_secure) const
197 {
198  // Extract sector tag
199  const Addr tag = extractTag(addr);
200 
201  // The address can only be mapped to a specific location of a sector
202  // due to sectors being composed of contiguous-address entries
204 
205  // Find all possible sector entries that may contain the given address
206  const std::vector<ReplaceableEntry*> entries =
208 
209  // Search for block
210  for (const auto& sector : entries) {
211  auto blk = static_cast<SectorBlk*>(sector)->blks[offset];
212  if (blk->getTag() == tag && blk->isValid() &&
213  blk->isSecure() == is_secure) {
214  return blk;
215  }
216  }
217 
218  // Did not find block
219  return nullptr;
220 }
221 
222 CacheBlk*
223 SectorTags::findVictim(Addr addr, const bool is_secure, const std::size_t size,
224  std::vector<CacheBlk*>& evict_blks)
225 {
226  // Get possible entries to be victimized
227  const std::vector<ReplaceableEntry*> sector_entries =
229 
230  // Check if the sector this address belongs to has been allocated
231  Addr tag = extractTag(addr);
232  SectorBlk* victim_sector = nullptr;
233  for (const auto& sector : sector_entries) {
234  SectorBlk* sector_blk = static_cast<SectorBlk*>(sector);
235  if ((tag == sector_blk->getTag()) && sector_blk->isValid() &&
236  (is_secure == sector_blk->isSecure())){
237  victim_sector = sector_blk;
238  break;
239  }
240  }
241 
242  // If the sector is not present
243  if (victim_sector == nullptr){
244  // Choose replacement victim from replacement candidates
245  victim_sector = static_cast<SectorBlk*>(replacementPolicy->getVictim(
246  sector_entries));
247  }
248 
249  // Get the entry of the victim block within the sector
250  SectorSubBlk* victim = victim_sector->blks[extractSectorOffset(addr)];
251 
252  // Get evicted blocks. Blocks are only evicted if the sectors mismatch and
253  // the currently existing sector is valid.
254  if ((tag == victim_sector->getTag()) &&
255  (is_secure == victim_sector->isSecure())){
256  // It would be a hit if victim was valid, and upgrades do not call
257  // findVictim, so it cannot happen
258  assert(!victim->isValid());
259  } else {
260  // The whole sector must be evicted to make room for the new sector
261  for (const auto& blk : victim_sector->blks){
262  if (blk->isValid()) {
263  evict_blks.push_back(blk);
264  }
265  }
266  }
267 
268  // Update number of sub-blocks evicted due to a replacement
269  sectorStats.evictionsReplacement[evict_blks.size()]++;
270 
271  return victim;
272 }
273 
274 int
276 {
277  return (addr >> sectorShift) & sectorMask;
278 }
279 
280 Addr
282 {
283  const SectorSubBlk* blk_cast = static_cast<const SectorSubBlk*>(blk);
284  const SectorBlk* sec_blk = blk_cast->getSectorBlock();
285  const Addr sec_addr = indexingPolicy->regenerateAddr(blk->tag, sec_blk);
286  return sec_addr | ((Addr)blk_cast->getSectorOffset() << sectorShift);
287 }
288 
290  SectorTags& _tags)
291  : Stats::Group(&base_group), tags(_tags),
292  evictionsReplacement(this, "evictions_replacement",
293  "Number of blocks evicted due to a replacement")
294 {
295 }
296 
297 void
299 {
301 
302  evictionsReplacement.init(tags.numBlocksPerSector + 1);
303  for (unsigned i = 0; i <= tags.numBlocksPerSector; ++i) {
304  evictionsReplacement.subname(i, std::to_string(i));
305  evictionsReplacement.subdesc(i, "Number of replacements that caused " \
306  "the eviction of " + std::to_string(i) + " blocks");
307  }
308 }
309 
310 void
311 SectorTags::forEachBlk(std::function<void(CacheBlk &)> visitor)
312 {
313  for (SectorSubBlk& blk : blks) {
314  visitor(blk);
315  }
316 }
317 
318 bool
319 SectorTags::anyBlk(std::function<bool(CacheBlk &)> visitor)
320 {
321  for (SectorSubBlk& blk : blks) {
322  if (visitor(blk)) {
323  return true;
324  }
325  }
326  return false;
327 }
328 
329 SectorTags *
330 SectorTagsParams::create()
331 {
332  // There must be a indexing policy
333  fatal_if(!indexing_policy, "An indexing policy is required");
334 
335  return new SectorTags(this);
336 }
SectorTags::extractSectorOffset
int extractSectorOffset(Addr addr) const
Calculate a block's offset in a sector from the address.
Definition: sector_tags.cc:275
SectorTags::replacementPolicy
BaseReplacementPolicy * replacementPolicy
Replacement policy.
Definition: sector_tags.hh:74
BaseTags::dataBlks
std::unique_ptr< uint8_t[]> dataBlks
The data blocks, 1 per cache block.
Definition: base.hh:100
SectorTags::sequentialAccess
const bool sequentialAccess
Whether tags and data are accessed sequentially.
Definition: sector_tags.hh:71
Stats::Group::regStats
virtual void regStats()
Callback to set stat parameters.
Definition: group.cc:64
SectorTags::anyBlk
bool anyBlk(std::function< bool(CacheBlk &)> visitor) override
Find if any of the sub-blocks satisfies a condition.
Definition: sector_tags.cc:319
SectorTags::forEachBlk
void forEachBlk(std::function< void(CacheBlk &)> visitor) override
Visit each sub-block in the tags and apply a visitor.
Definition: sector_tags.cc:311
BaseTags::numBlocks
const unsigned numBlocks
the number of blocks in the cache
Definition: base.hh:97
base.hh
SectorTags::numBlocksPerSector
const unsigned numBlocksPerSector
Number of data blocks per sector.
Definition: sector_tags.hh:77
ArmISA::i
Bitfield< 7 > i
Definition: miscregs_types.hh:63
BaseReplacementPolicy::invalidate
virtual void invalidate(const std::shared_ptr< ReplacementData > &replacement_data) const =0
Invalidate replacement data to set it as the next probable victim.
SectorTags::allocAssoc
unsigned allocAssoc
The allocatable associativity of the cache (alloc mask).
Definition: sector_tags.hh:68
BaseIndexingPolicy::regenerateAddr
virtual Addr regenerateAddr(const Addr tag, const ReplaceableEntry *entry) const =0
Regenerate an entry's address from its tag and assigned indexing bits.
SectorTags::regenerateBlkAddr
Addr regenerateBlkAddr(const CacheBlk *blk) const override
Regenerate the block address from the tag and location.
Definition: sector_tags.cc:281
sc_dt::to_string
const std::string to_string(sc_enc enc)
Definition: sc_fxdefs.cc:91
SectorTags::secBlks
std::vector< SectorBlk > secBlks
The cache sector blocks.
Definition: sector_tags.hh:64
SectorTags::SectorTagsStats::evictionsReplacement
Stats::Vector evictionsReplacement
Number of sub-blocks evicted due to a replacement.
Definition: sector_tags.hh:99
SectorTags::tagsInit
void tagsInit() override
Initialize blocks as SectorBlk and SectorSubBlk instances.
Definition: sector_tags.cc:65
std::vector< SectorSubBlk >
BaseTags::extractTag
virtual Addr extractTag(const Addr addr) const
Generate the tag from the given address.
Definition: base.cc:128
floorLog2
std::enable_if< std::is_integral< T >::value, int >::type floorLog2(T x)
Definition: intmath.hh:63
BaseReplacementPolicy::instantiateEntry
virtual std::shared_ptr< ReplacementData > instantiateEntry()=0
Instantiate a replacement data entry.
SectorTags::findBlock
CacheBlk * findBlock(Addr addr, bool is_secure) const override
Finds the given address in the cache, do not update replacement data.
Definition: sector_tags.cc:196
SectorTags::SectorTagsStats::regStats
void regStats() override
Callback to set stat parameters.
Definition: sector_tags.cc:298
base.hh
replaceable_entry.hh
sector_tags.hh
BaseTags::invalidate
virtual void invalidate(CacheBlk *blk)
This function updates the tags when a block is invalidated.
Definition: base.hh:251
SectorBlk::getTag
Addr getTag() const
Get tag associated to this block.
Definition: sector_blk.cc:148
SectorBlk::blks
std::vector< SectorSubBlk * > blks
List of blocks associated to this sector.
Definition: sector_blk.hh:167
BaseTags::BaseTagStats::tagsInUse
Stats::Average tagsInUse
Per cycle average of the number of tags that hold valid data.
Definition: base.hh:115
MipsISA::k
Bitfield< 23 > k
Definition: dt_constants.hh:78
SectorTags::insertBlock
void insertBlock(const PacketPtr pkt, CacheBlk *blk) override
Insert the new block into the cache and update replacement data.
Definition: sector_tags.cc:172
SectorSubBlk::setSectorBlock
void setSectorBlock(SectorBlk *sector_blk)
Set sector block associated to this block.
Definition: sector_blk.cc:42
SectorTags::SectorTagsStats::SectorTagsStats
SectorTagsStats(BaseTagStats &base_group, SectorTags &_tags)
Definition: sector_tags.cc:289
BaseTags
A common base class of Cache tagstore objects.
Definition: base.hh:70
SectorTags
A SectorTags cache tag store.
Definition: sector_tags.hh:58
BaseTags::insertBlock
virtual void insertBlock(const PacketPtr pkt, CacheBlk *blk)
Insert the new block into the cache and update stats.
Definition: base.cc:100
BaseTags::BaseTagStats::tagAccesses
Stats::Scalar tagAccesses
Number of tags consulted over all accesses.
Definition: base.hh:152
BaseIndexingPolicy::setEntry
void setEntry(ReplaceableEntry *entry, const uint64_t index)
Associate a pointer to an entry to its physical counterpart.
Definition: base.cc:78
SectorTags::sectorShift
const int sectorShift
The amount to shift the address to get the sector tag.
Definition: sector_tags.hh:85
BaseTags::blkSize
const unsigned blkSize
The block size of the cache.
Definition: base.hh:74
BaseReplacementPolicy::getVictim
virtual ReplaceableEntry * getVictim(const ReplacementCandidates &candidates) const =0
Find replacement victim among candidates.
SectorTags::sectorStats
SectorTags::SectorTagsStats sectorStats
BaseTags::BaseTagStats
TODO: It would be good if these stats were acquired after warmup.
Definition: base.hh:105
base.hh
CacheBlk::refCount
unsigned refCount
Number of references to this block since it was brought in.
Definition: cache_blk.hh:114
BaseTags::indexingPolicy
BaseIndexingPolicy * indexingPolicy
Indexing policy.
Definition: base.hh:86
Addr
uint64_t Addr
Address type This will probably be moved somewhere else in the near future.
Definition: types.hh:142
SectorTags::blks
std::vector< SectorSubBlk > blks
The cache blocks.
Definition: sector_tags.hh:62
BaseIndexingPolicy::getPossibleEntries
virtual std::vector< ReplaceableEntry * > getPossibleEntries(const Addr addr) const =0
Find all possible entries for insertion and replacement of an address.
BaseTags::BaseTagStats::dataAccesses
Stats::Scalar dataAccesses
Number of data blocks consulted over all accesses.
Definition: base.hh:154
SectorTags::SectorTags
SectorTags(const Params *p)
Construct and initialize this tag store.
Definition: sector_tags.cc:48
SectorBlk::isValid
bool isValid() const
Checks that a sector block is valid.
Definition: sector_blk.cc:122
CacheBlk::tag
Addr tag
Data block tag value.
Definition: cache_blk.hh:91
BaseTags::stats
BaseTags::BaseTagStats stats
CacheBlk::isValid
bool isValid() const
Checks that a block is valid.
Definition: cache_blk.hh:203
SectorBlk::isSecure
bool isSecure() const
Checks that a sector block is secure.
Definition: sector_blk.cc:135
CacheBlk::data
uint8_t * data
Contains a copy of the data in this block for easy access.
Definition: cache_blk.hh:99
SectorTags::findVictim
CacheBlk * findVictim(Addr addr, const bool is_secure, const std::size_t size, std::vector< CacheBlk * > &evict_blks) override
Find replacement victim based on address.
Definition: sector_tags.cc:223
CacheBlk
A Basic Cache block.
Definition: cache_blk.hh:84
SectorSubBlk::setSectorOffset
void setSectorOffset(const int sector_offset)
Set offset of this sub-block within the sector.
Definition: sector_blk.cc:55
types.hh
SectorTags::numSectors
const unsigned numSectors
The number of sectors in the cache.
Definition: sector_tags.hh:80
SectorSubBlk::getSectorOffset
int getSectorOffset() const
Get offset of this sub-block within the sector.
Definition: sector_blk.cc:61
Packet
A Packet is used to encapsulate a transfer between two objects in the memory system (e....
Definition: packet.hh:257
BaseReplacementPolicy::touch
virtual void touch(const std::shared_ptr< ReplacementData > &replacement_data) const =0
Update replacement data.
SectorSubBlk::getSectorBlock
const SectorBlk * getSectorBlock() const
Get sector block associated to this block.
Definition: sector_blk.cc:49
addr
ip6_addr_t addr
Definition: inet.hh:423
logging.hh
Cycles
Cycles is a wrapper class for representing cycle counts, i.e.
Definition: types.hh:83
SectorSubBlk
A sector is composed of sub-blocks, and each sub-block has information regarding its sector and a poi...
Definition: sector_blk.hh:48
ReplaceableEntry::replacementData
std::shared_ptr< ReplacementData > replacementData
Replacement data associated to this entry.
Definition: replaceable_entry.hh:74
BaseReplacementPolicy::reset
virtual void reset(const std::shared_ptr< ReplacementData > &replacement_data) const =0
Reset replacement data.
BaseTags::lookupLatency
const Cycles lookupLatency
The tag lookup latency of the cache.
Definition: base.hh:80
Stats
Definition: statistics.cc:61
SectorBlk
A Basic Sector block.
Definition: sector_blk.hh:143
MipsISA::p
Bitfield< 0 > p
Definition: pra_constants.hh:323
intmath.hh
SectorTags::accessBlock
CacheBlk * accessBlock(Addr addr, bool is_secure, Cycles &lat) override
Access block and update replacement data.
Definition: sector_tags.cc:135
fatal_if
#define fatal_if(cond,...)
Conditional fatal macro that checks the supplied condition and only causes a fatal error if the condi...
Definition: logging.hh:219
isPowerOf2
bool isPowerOf2(const T &n)
Definition: intmath.hh:102
SectorTags::sectorMask
const unsigned sectorMask
Mask out all bits that aren't part of the sector tag.
Definition: sector_tags.hh:88
SectorTags::invalidate
void invalidate(CacheBlk *blk) override
This function updates the tags when a block is invalidated but does not invalidate the block itself.
Definition: sector_tags.cc:113
ArmISA::offset
Bitfield< 23, 0 > offset
Definition: types.hh:153

Generated on Wed Sep 30 2020 14:02:12 for gem5 by doxygen 1.8.17