mem-cache: Replace block visitor with std::function
This change modifies forEachBlk tags function to accept std::function as parameter. It also adds an anyBlk tags function that given a condition, it iterates through the blocks and returns whether the condition is met. Finally, it uses forEachBlk to implement the print, computeStats and cleanupRefs functions that also work for the FALRU class. Change-Id: I2f75f4baa1fdd5a1d343a63ecace3eb9458fbf03 Reviewed-by: Andreas Sandberg <andreas.sandberg@arm.com> Reviewed-on: https://gem5-review.googlesource.com/10621 Reviewed-by: Jason Lowe-Power <jason@lowepower.com> Reviewed-by: Daniel Carvalho <odanrc@yahoo.com.br> Maintainer: Nikos Nikoleris <nikos.nikoleris@arm.com>
This commit is contained in:
19
src/mem/cache/base.cc
vendored
19
src/mem/cache/base.cc
vendored
@@ -1326,27 +1326,22 @@ BaseCache::writecleanBlk(CacheBlk *blk, Request::Flags dest, PacketId id)
|
||||
void
|
||||
BaseCache::memWriteback()
|
||||
{
|
||||
CacheBlkVisitorWrapper visitor(*this, &BaseCache::writebackVisitor);
|
||||
tags->forEachBlk(visitor);
|
||||
tags->forEachBlk([this](CacheBlk &blk) { writebackVisitor(blk); });
|
||||
}
|
||||
|
||||
void
|
||||
BaseCache::memInvalidate()
|
||||
{
|
||||
CacheBlkVisitorWrapper visitor(*this, &BaseCache::invalidateVisitor);
|
||||
tags->forEachBlk(visitor);
|
||||
tags->forEachBlk([this](CacheBlk &blk) { invalidateVisitor(blk); });
|
||||
}
|
||||
|
||||
bool
|
||||
BaseCache::isDirty() const
|
||||
{
|
||||
CacheBlkIsDirtyVisitor visitor;
|
||||
tags->forEachBlk(visitor);
|
||||
|
||||
return visitor.isDirty();
|
||||
return tags->anyBlk([](CacheBlk &blk) { return blk.isDirty(); });
|
||||
}
|
||||
|
||||
bool
|
||||
void
|
||||
BaseCache::writebackVisitor(CacheBlk &blk)
|
||||
{
|
||||
if (blk.isDirty()) {
|
||||
@@ -1366,11 +1361,9 @@ BaseCache::writebackVisitor(CacheBlk &blk)
|
||||
|
||||
blk.status &= ~BlkDirty;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
void
|
||||
BaseCache::invalidateVisitor(CacheBlk &blk)
|
||||
{
|
||||
if (blk.isDirty())
|
||||
@@ -1381,8 +1374,6 @@ BaseCache::invalidateVisitor(CacheBlk &blk)
|
||||
assert(!blk.isDirty());
|
||||
invalidateBlock(&blk);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
Tick
|
||||
|
||||
66
src/mem/cache/base.hh
vendored
66
src/mem/cache/base.hh
vendored
@@ -1108,19 +1108,15 @@ class BaseCache : public MemObject
|
||||
/**
|
||||
* Cache block visitor that writes back dirty cache blocks using
|
||||
* functional writes.
|
||||
*
|
||||
* @return Always returns true.
|
||||
*/
|
||||
bool writebackVisitor(CacheBlk &blk);
|
||||
void writebackVisitor(CacheBlk &blk);
|
||||
|
||||
/**
|
||||
* Cache block visitor that invalidates all blocks in the cache.
|
||||
*
|
||||
* @warn Dirty cache lines will not be written back to memory.
|
||||
*
|
||||
* @return Always returns true.
|
||||
*/
|
||||
bool invalidateVisitor(CacheBlk &blk);
|
||||
void invalidateVisitor(CacheBlk &blk);
|
||||
|
||||
/**
|
||||
* Take an MSHR, turn it into a suitable downstream packet, and
|
||||
@@ -1152,62 +1148,4 @@ class BaseCache : public MemObject
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
* Wrap a method and present it as a cache block visitor.
|
||||
*
|
||||
* For example the forEachBlk method in the tag arrays expects a
|
||||
* callable object/function as their parameter. This class wraps a
|
||||
* method in an object and presents callable object that adheres to
|
||||
* the cache block visitor protocol.
|
||||
*/
|
||||
class CacheBlkVisitorWrapper : public CacheBlkVisitor
|
||||
{
|
||||
public:
|
||||
typedef bool (BaseCache::*VisitorPtr)(CacheBlk &blk);
|
||||
|
||||
CacheBlkVisitorWrapper(BaseCache &_cache, VisitorPtr _visitor)
|
||||
: cache(_cache), visitor(_visitor) {}
|
||||
|
||||
bool operator()(CacheBlk &blk) override {
|
||||
return (cache.*visitor)(blk);
|
||||
}
|
||||
|
||||
private:
|
||||
BaseCache &cache;
|
||||
VisitorPtr visitor;
|
||||
};
|
||||
|
||||
/**
|
||||
* Cache block visitor that determines if there are dirty blocks in a
|
||||
* cache.
|
||||
*
|
||||
* Use with the forEachBlk method in the tag array to determine if the
|
||||
* array contains dirty blocks.
|
||||
*/
|
||||
class CacheBlkIsDirtyVisitor : public CacheBlkVisitor
|
||||
{
|
||||
public:
|
||||
CacheBlkIsDirtyVisitor()
|
||||
: _isDirty(false) {}
|
||||
|
||||
bool operator()(CacheBlk &blk) override {
|
||||
if (blk.isDirty()) {
|
||||
_isDirty = true;
|
||||
return false;
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Does the array contain a dirty line?
|
||||
*
|
||||
* @return true if yes, false otherwise.
|
||||
*/
|
||||
bool isDirty() const { return _isDirty; };
|
||||
|
||||
private:
|
||||
bool _isDirty;
|
||||
};
|
||||
|
||||
#endif //__MEM_CACHE_BASE_HH__
|
||||
|
||||
18
src/mem/cache/blk.hh
vendored
18
src/mem/cache/blk.hh
vendored
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2012-2017 ARM Limited
|
||||
* Copyright (c) 2012-2018 ARM Limited
|
||||
* All rights reserved.
|
||||
*
|
||||
* The license below extends only to copyright in the software and shall
|
||||
@@ -409,20 +409,4 @@ class CacheBlkPrintWrapper : public Printable
|
||||
const std::string &prefix = "") const;
|
||||
};
|
||||
|
||||
/**
|
||||
* Base class for cache block visitor, operating on the cache block
|
||||
* base class (later subclassed for the various tag classes). This
|
||||
* visitor class is used as part of the forEachBlk interface in the
|
||||
* tag classes.
|
||||
*/
|
||||
class CacheBlkVisitor
|
||||
{
|
||||
public:
|
||||
|
||||
CacheBlkVisitor() {}
|
||||
virtual ~CacheBlkVisitor() {}
|
||||
|
||||
virtual bool operator()(CacheBlk &blk) = 0;
|
||||
};
|
||||
|
||||
#endif //__MEM_CACHE_BLK_HH__
|
||||
|
||||
73
src/mem/cache/tags/base.cc
vendored
73
src/mem/cache/tags/base.cc
vendored
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2013,2016 ARM Limited
|
||||
* Copyright (c) 2013,2016,2018 ARM Limited
|
||||
* All rights reserved.
|
||||
*
|
||||
* The license below extends only to copyright in the software and shall
|
||||
@@ -110,6 +110,77 @@ BaseTags::insertBlock(PacketPtr pkt, CacheBlk *blk)
|
||||
dataAccesses += 1;
|
||||
}
|
||||
|
||||
void
|
||||
BaseTags::cleanupRefsVisitor(CacheBlk &blk)
|
||||
{
|
||||
if (blk.isValid()) {
|
||||
totalRefs += blk.refCount;
|
||||
++sampledRefs;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
BaseTags::cleanupRefs()
|
||||
{
|
||||
forEachBlk([this](CacheBlk &blk) { cleanupRefsVisitor(blk); });
|
||||
}
|
||||
|
||||
void
|
||||
BaseTags::computeStatsVisitor(CacheBlk &blk)
|
||||
{
|
||||
if (blk.isValid()) {
|
||||
assert(blk.task_id < ContextSwitchTaskId::NumTaskId);
|
||||
occupanciesTaskId[blk.task_id]++;
|
||||
assert(blk.tickInserted <= curTick());
|
||||
Tick age = curTick() - blk.tickInserted;
|
||||
|
||||
int age_index;
|
||||
if (age / SimClock::Int::us < 10) { // <10us
|
||||
age_index = 0;
|
||||
} else if (age / SimClock::Int::us < 100) { // <100us
|
||||
age_index = 1;
|
||||
} else if (age / SimClock::Int::ms < 1) { // <1ms
|
||||
age_index = 2;
|
||||
} else if (age / SimClock::Int::ms < 10) { // <10ms
|
||||
age_index = 3;
|
||||
} else
|
||||
age_index = 4; // >10ms
|
||||
|
||||
ageTaskId[blk.task_id][age_index]++;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
BaseTags::computeStats()
|
||||
{
|
||||
for (unsigned i = 0; i < ContextSwitchTaskId::NumTaskId; ++i) {
|
||||
occupanciesTaskId[i] = 0;
|
||||
for (unsigned j = 0; j < 5; ++j) {
|
||||
ageTaskId[i][j] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
forEachBlk([this](CacheBlk &blk) { computeStatsVisitor(blk); });
|
||||
}
|
||||
|
||||
std::string
|
||||
BaseTags::print()
|
||||
{
|
||||
std::string str;
|
||||
|
||||
auto print_blk = [&str](CacheBlk &blk) {
|
||||
if (blk.isValid())
|
||||
str += csprintf("\tset: %d way: %d %s\n", blk.set, blk.way,
|
||||
blk.print());
|
||||
};
|
||||
forEachBlk(print_blk);
|
||||
|
||||
if (str.empty())
|
||||
str = "no valid tags\n";
|
||||
|
||||
return str;
|
||||
}
|
||||
|
||||
void
|
||||
BaseTags::regStats()
|
||||
{
|
||||
|
||||
46
src/mem/cache/tags/base.hh
vendored
46
src/mem/cache/tags/base.hh
vendored
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2012-2014,2016-2017 ARM Limited
|
||||
* Copyright (c) 2012-2014,2016-2018 ARM Limited
|
||||
* All rights reserved.
|
||||
*
|
||||
* The license below extends only to copyright in the software and shall
|
||||
@@ -50,6 +50,7 @@
|
||||
#define __MEM_CACHE_TAGS_BASE_HH__
|
||||
|
||||
#include <cassert>
|
||||
#include <functional>
|
||||
#include <string>
|
||||
|
||||
#include "base/callback.hh"
|
||||
@@ -177,17 +178,17 @@ class BaseTags : public ClockedObject
|
||||
* Average in the reference count for valid blocks when the simulation
|
||||
* exits.
|
||||
*/
|
||||
virtual void cleanupRefs() {}
|
||||
void cleanupRefs();
|
||||
|
||||
/**
|
||||
* Computes stats just prior to dump event
|
||||
*/
|
||||
virtual void computeStats() {}
|
||||
void computeStats();
|
||||
|
||||
/**
|
||||
* Print all tags used
|
||||
*/
|
||||
virtual std::string print() const = 0;
|
||||
std::string print();
|
||||
|
||||
/**
|
||||
* Find a block using the memory address
|
||||
@@ -289,7 +290,42 @@ class BaseTags : public ClockedObject
|
||||
|
||||
virtual int extractSet(Addr addr) const = 0;
|
||||
|
||||
virtual void forEachBlk(CacheBlkVisitor &visitor) = 0;
|
||||
|
||||
/**
|
||||
* Visit each block in the tags and apply a visitor
|
||||
*
|
||||
* The visitor should be a std::function that takes a cache block
|
||||
* reference as its parameter.
|
||||
*
|
||||
* @param visitor Visitor to call on each block.
|
||||
*/
|
||||
virtual void forEachBlk(std::function<void(CacheBlk &)> visitor) = 0;
|
||||
|
||||
/**
|
||||
* Find if any of the blocks satisfies a condition
|
||||
*
|
||||
* The visitor should be a std::function that takes a cache block
|
||||
* reference as its parameter. The visitor will terminate the
|
||||
* traversal early if the condition is satisfied.
|
||||
*
|
||||
* @param visitor Visitor to call on each block.
|
||||
*/
|
||||
virtual bool anyBlk(std::function<bool(CacheBlk &)> visitor) = 0;
|
||||
|
||||
private:
|
||||
/**
|
||||
* Update the reference stats using data from the input block
|
||||
*
|
||||
* @param blk The input block
|
||||
*/
|
||||
void cleanupRefsVisitor(CacheBlk &blk);
|
||||
|
||||
/**
|
||||
* Update the occupancy and age stats using data from the input block
|
||||
*
|
||||
* @param blk The input block
|
||||
*/
|
||||
void computeStatsVisitor(CacheBlk &blk);
|
||||
};
|
||||
|
||||
class BaseTagsCallback : public Callback
|
||||
|
||||
60
src/mem/cache/tags/base_set_assoc.cc
vendored
60
src/mem/cache/tags/base_set_assoc.cc
vendored
@@ -47,11 +47,9 @@
|
||||
|
||||
#include "mem/cache/tags/base_set_assoc.hh"
|
||||
|
||||
#include <cassert>
|
||||
#include <string>
|
||||
|
||||
#include "base/intmath.hh"
|
||||
#include "mem/request.hh"
|
||||
|
||||
BaseSetAssoc::BaseSetAssoc(const Params *p)
|
||||
:BaseTags(p), assoc(p->assoc), allocAssoc(p->assoc),
|
||||
@@ -134,64 +132,6 @@ BaseSetAssoc::findBlockBySetAndWay(int set, int way) const
|
||||
return sets[set].blks[way];
|
||||
}
|
||||
|
||||
std::string
|
||||
BaseSetAssoc::print() const {
|
||||
std::string cache_state;
|
||||
for (const CacheBlk& blk : blks) {
|
||||
if (blk.isValid())
|
||||
cache_state += csprintf("\tset: %d way: %d %s\n", blk.set,
|
||||
blk.way, blk.print());
|
||||
}
|
||||
if (cache_state.empty())
|
||||
cache_state = "no valid tags\n";
|
||||
return cache_state;
|
||||
}
|
||||
|
||||
void
|
||||
BaseSetAssoc::cleanupRefs()
|
||||
{
|
||||
for (const CacheBlk& blk : blks) {
|
||||
if (blk.isValid()) {
|
||||
totalRefs += blk.refCount;
|
||||
++sampledRefs;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
BaseSetAssoc::computeStats()
|
||||
{
|
||||
for (unsigned i = 0; i < ContextSwitchTaskId::NumTaskId; ++i) {
|
||||
occupanciesTaskId[i] = 0;
|
||||
for (unsigned j = 0; j < 5; ++j) {
|
||||
ageTaskId[i][j] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
for (const CacheBlk& blk : blks) {
|
||||
if (blk.isValid()) {
|
||||
assert(blk.task_id < ContextSwitchTaskId::NumTaskId);
|
||||
occupanciesTaskId[blk.task_id]++;
|
||||
assert(blk.tickInserted <= curTick());
|
||||
Tick age = curTick() - blk.tickInserted;
|
||||
|
||||
int age_index;
|
||||
if (age / SimClock::Int::us < 10) { // <10us
|
||||
age_index = 0;
|
||||
} else if (age / SimClock::Int::us < 100) { // <100us
|
||||
age_index = 1;
|
||||
} else if (age / SimClock::Int::ms < 1) { // <1ms
|
||||
age_index = 2;
|
||||
} else if (age / SimClock::Int::ms < 10) { // <10ms
|
||||
age_index = 3;
|
||||
} else
|
||||
age_index = 4; // >10ms
|
||||
|
||||
ageTaskId[blk.task_id][age_index]++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
BaseSetAssoc *
|
||||
BaseSetAssocParams::create()
|
||||
{
|
||||
|
||||
42
src/mem/cache/tags/base_set_assoc.hh
vendored
42
src/mem/cache/tags/base_set_assoc.hh
vendored
@@ -48,6 +48,7 @@
|
||||
#ifndef __MEM_CACHE_TAGS_BASE_SET_ASSOC_HH__
|
||||
#define __MEM_CACHE_TAGS_BASE_SET_ASSOC_HH__
|
||||
|
||||
#include <functional>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
@@ -298,39 +299,20 @@ class BaseSetAssoc : public BaseTags
|
||||
return ((blk->tag << tagShift) | ((Addr)blk->set << setShift));
|
||||
}
|
||||
|
||||
/**
|
||||
* Called at end of simulation to complete average block reference stats.
|
||||
*/
|
||||
void cleanupRefs() override;
|
||||
|
||||
/**
|
||||
* Print all tags used
|
||||
*/
|
||||
std::string print() const override;
|
||||
|
||||
/**
|
||||
* Called prior to dumping stats to compute task occupancy
|
||||
*/
|
||||
void computeStats() override;
|
||||
|
||||
/**
|
||||
* Visit each block in the tag store and apply a visitor to the
|
||||
* block.
|
||||
*
|
||||
* The visitor should be a function (or object that behaves like a
|
||||
* function) that takes a cache block reference as its parameter
|
||||
* and returns a bool. A visitor can request the traversal to be
|
||||
* stopped by returning false, returning true causes it to be
|
||||
* called for the next block in the tag store.
|
||||
*
|
||||
* \param visitor Visitor to call on each block.
|
||||
*/
|
||||
void forEachBlk(CacheBlkVisitor &visitor) override {
|
||||
void forEachBlk(std::function<void(CacheBlk &)> visitor) override {
|
||||
for (CacheBlk& blk : blks) {
|
||||
if (!visitor(blk))
|
||||
return;
|
||||
visitor(blk);
|
||||
}
|
||||
}
|
||||
|
||||
bool anyBlk(std::function<bool(CacheBlk &)> visitor) override {
|
||||
for (CacheBlk& blk : blks) {
|
||||
if (visitor(blk)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
#endif //__MEM_CACHE_TAGS_BASE_SET_ASSOC_HH__
|
||||
|
||||
32
src/mem/cache/tags/fa_lru.hh
vendored
32
src/mem/cache/tags/fa_lru.hh
vendored
@@ -50,6 +50,7 @@
|
||||
#define __MEM_CACHE_TAGS_FA_LRU_HH__
|
||||
|
||||
#include <cstdint>
|
||||
#include <functional>
|
||||
#include <string>
|
||||
#include <unordered_map>
|
||||
|
||||
@@ -240,30 +241,21 @@ class FALRU : public BaseTags
|
||||
return blk->tag;
|
||||
}
|
||||
|
||||
/**
|
||||
* @todo Implement as in lru. Currently not used
|
||||
*/
|
||||
virtual std::string print() const override { return ""; }
|
||||
|
||||
/**
|
||||
* Visit each block in the tag store and apply a visitor to the
|
||||
* block.
|
||||
*
|
||||
* The visitor should be a function (or object that behaves like a
|
||||
* function) that takes a cache block reference as its parameter
|
||||
* and returns a bool. A visitor can request the traversal to be
|
||||
* stopped by returning false, returning true causes it to be
|
||||
* called for the next block in the tag store.
|
||||
*
|
||||
* \param visitor Visitor to call on each block.
|
||||
*/
|
||||
void forEachBlk(CacheBlkVisitor &visitor) override {
|
||||
void forEachBlk(std::function<void(CacheBlk &)> visitor) override {
|
||||
for (int i = 0; i < numBlocks; i++) {
|
||||
if (!visitor(blks[i]))
|
||||
return;
|
||||
visitor(blks[i]);
|
||||
}
|
||||
}
|
||||
|
||||
bool anyBlk(std::function<bool(CacheBlk &)> visitor) override {
|
||||
for (int i = 0; i < numBlocks; i++) {
|
||||
if (visitor(blks[i])) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private:
|
||||
/**
|
||||
* Mechanism that allows us to simultaneously collect miss
|
||||
|
||||
Reference in New Issue
Block a user