Skip to content

Commit 90f083d

Browse files
committed
Add Cache Replacement Policy LFU
LFU version 1 is done. TO DO: How to deal with the situation if frequency bit is too high. The variable and data structure which are newly added need more optimization.
1 parent 101dc8c commit 90f083d

File tree

4 files changed

+118
-22
lines changed

4 files changed

+118
-22
lines changed

src/cachesim/cachegraphic.cpp

Lines changed: 64 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -98,26 +98,45 @@ void CacheGraphic::updateLineReplFields(unsigned lineIdx) {
9898
return;
9999
}
100100

101-
if (m_cacheTextItems.at(0).at(0).lru == nullptr) {
101+
if (m_cacheTextItems.at(0).at(0).lru == nullptr && m_cache.getReplacementPolicy() == ReplPolicy::LRU) {
102102
// The current cache configuration does not have any replacement field
103103
return;
104104
}
105-
106-
for (const auto &way : m_cacheTextItems[lineIdx]) {
107-
// If LRU was just initialized, the actual (software) LRU value may be very
108-
// large. Mask to the number of actual LRU bits.
109-
unsigned lruVal = cacheLine->at(way.first).lru;
110-
lruVal &= vsrtl::generateBitmask(m_cache.getWaysBits());
111-
const QString lruText = QString::number(lruVal);
112-
way.second.lru->setText(lruText);
113-
114-
// LRU text might have changed; update LRU field position to center in
115-
// column
116-
const qreal y = lineIdx * m_lineHeight + way.first * m_setHeight;
117-
const qreal x =
118-
m_widthBeforeLRU + m_lruWidth / 2 - m_fm.horizontalAdvance(lruText) / 2;
119-
120-
way.second.lru->setPos(x, y);
105+
if (m_cacheTextItems.at(0).at(0).lfu == nullptr && m_cache.getReplacementPolicy() == ReplPolicy::LFU){
106+
return;
107+
}
108+
if(m_cache.getReplacementPolicy() == ReplPolicy::LRU){
109+
for (const auto &way : m_cacheTextItems[lineIdx]) {
110+
// If LRU was just initialized, the actual (software) LRU value may be very
111+
// large. Mask to the number of actual LRU bits.
112+
unsigned lruVal = cacheLine->at(way.first).lru;
113+
lruVal &= vsrtl::generateBitmask(m_cache.getWaysBits());
114+
const QString lruText = QString::number(lruVal);
115+
way.second.lru->setText(lruText);
116+
117+
// LRU text might have changed; update LRU field position to center in
118+
// column
119+
const qreal y = lineIdx * m_lineHeight + way.first * m_setHeight;
120+
const qreal x =
121+
m_widthBeforeLRU + m_lruWidth / 2 - m_fm.horizontalAdvance(lruText) / 2;
122+
way.second.lru->setPos(x, y);
123+
}
124+
}
125+
if(m_cache.getReplacementPolicy() == ReplPolicy::LFU){
126+
for (const auto &way : m_cacheTextItems[lineIdx]) {
127+
// If LRU was just initialized, the actual (software) LRU value may be very
128+
// large. Mask to the number of actual LRU bits.
129+
int lfuVal = cacheLine->at(way.first).lfu;
130+
const QString lfuText = QString::number(lfuVal);
131+
way.second.lfu->setText(lfuText);
132+
133+
// LRU text might have changed; update LRU field position to center in
134+
// column
135+
const qreal y = lineIdx * m_lineHeight + way.first * m_setHeight;
136+
const qreal x =
137+
m_widthBeforeLFU + m_lfuWidth / 2 - m_fm.horizontalAdvance(lfuText) / 2;
138+
way.second.lfu->setPos(x, y);
139+
}
121140
}
122141
}
123142

@@ -409,6 +428,7 @@ void CacheGraphic::cacheInvalidated() {
409428
m_blockWidth = m_fm.horizontalAdvance(" " + addressString() + " ");
410429
m_bitWidth = m_fm.horizontalAdvance("00");
411430
m_lruWidth = m_fm.horizontalAdvance(QString::number(m_cache.getWays()) + " ");
431+
m_lfuWidth = m_fm.horizontalAdvance(QString::number(m_cache.getWays()) + " ");
412432
m_cacheHeight = m_lineHeight * m_cache.getLines();
413433
m_tagWidth = m_blockWidth;
414434

@@ -436,9 +456,10 @@ void CacheGraphic::cacheInvalidated() {
436456
}
437457

438458
m_widthBeforeLRU = width;
459+
m_widthBeforeLFU = width;
439460

440-
if (m_cache.getReplacementPolicy() == ReplPolicy::LRU &&
441-
m_cache.getWays() > 1) {
461+
if (m_cache.getReplacementPolicy() == ReplPolicy::LRU
462+
&& m_cache.getWays() > 1) {
442463
// Draw LRU bit column
443464
new QGraphicsLineItem(width + m_lruWidth, 0, width + m_lruWidth,
444465
m_cacheHeight, this);
@@ -451,6 +472,22 @@ void CacheGraphic::cacheInvalidated() {
451472
width += m_lruWidth;
452473
}
453474

475+
if (m_cache.getReplacementPolicy() == ReplPolicy::LFU
476+
&& m_cache.getWays() > 1) {
477+
// Draw LFU bit column
478+
new QGraphicsLineItem(width + m_lfuWidth, 0, width + m_lfuWidth,
479+
m_cacheHeight, this);
480+
const QString LFUBitText = "LFU";
481+
auto *textItem = drawText(LFUBitText,
482+
width + m_lfuWidth / 2 -
483+
m_fm.horizontalAdvance(LFUBitText) / 2,
484+
-m_fm.height());
485+
textItem->setToolTip("Least Frequently Used bits");
486+
width += m_lfuWidth;
487+
}
488+
489+
490+
454491
m_widthBeforeTag = width;
455492

456493
// Draw tag column
@@ -705,6 +742,14 @@ void CacheGraphic::initializeControlBits() {
705742
m_fm.horizontalAdvance(lruText) / 2;
706743
line[setIdx].lru = drawText(lruText, x, y);
707744
}
745+
if (m_cache.getReplacementPolicy() == ReplPolicy::LFU &&
746+
m_cache.getWays() > 1) {
747+
const QString lfuText = QString::number(0);
748+
x = m_widthBeforeLFU + m_lfuWidth / 2 -
749+
m_fm.horizontalAdvance(lfuText) / 2;
750+
// Create LFU field
751+
line[setIdx].lfu = drawText("0", x, y);
752+
}
708753
}
709754
}
710755
}

src/cachesim/cachegraphic.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,7 @@ public slots:
6262
std::map<unsigned, std::unique_ptr<QGraphicsSimpleTextItem>> blocks;
6363
std::unique_ptr<QGraphicsSimpleTextItem> tag = nullptr;
6464
QGraphicsSimpleTextItem *lru = nullptr;
65+
QGraphicsSimpleTextItem *lfu = nullptr;
6566
QGraphicsSimpleTextItem *valid = nullptr;
6667
QGraphicsSimpleTextItem *dirty = nullptr;
6768
std::map<unsigned, std::unique_ptr<QGraphicsRectItem>> dirtyBlocks;
@@ -113,9 +114,10 @@ public slots:
113114
qreal m_widthBeforeBlocks = 0;
114115
qreal m_widthBeforeTag = 0;
115116
qreal m_widthBeforeLRU = 0;
117+
qreal m_widthBeforeLFU = 0;
116118
qreal m_widthBeforeDirty = 0;
117119
qreal m_lruWidth = 0;
118-
120+
qreal m_lfuWidth = 0;
119121
static constexpr qreal z_grid = 0;
120122
static constexpr qreal z_wires = -1;
121123

src/cachesim/cachesim.cpp

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,10 @@ void CacheSim::updateCacheLineReplFields(CacheLine &line, unsigned wayIdx) {
5252
// Upgrade @p lruIdx to the most recently used
5353
line[wayIdx].lru = 0;
5454
}
55+
56+
if (getReplacementPolicy() == ReplPolicy::LFU) {
57+
line[wayIdx].lfu += 1;
58+
}
5559
}
5660

5761
void CacheSim::revertCacheLineReplFields(CacheLine &line,
@@ -95,6 +99,13 @@ CacheSim::CacheSize CacheSim::getCacheSize() const {
9599
size.bits += componentBits;
96100
}
97101

102+
if (m_replPolicy == ReplPolicy::LFU) {
103+
// LFU bits
104+
componentBits = getWaysBits() * entries;
105+
size.components.push_back("LFU bits: " + QString::number(componentBits));
106+
size.bits += componentBits;
107+
}
108+
98109
// Tag bits
99110
componentBits = vsrtl::bitcount(m_tagMask) * entries;
100111
size.components.push_back("Tag bits: " + QString::number(componentBits));
@@ -156,6 +167,42 @@ CacheSim::locateEvictionWay(const CacheTransaction &transaction) {
156167
}
157168
}
158169
}
170+
}
171+
else if (m_replPolicy == ReplPolicy::LFU) {
172+
if (getWays() == 1) {
173+
// Nothing to do if we are in LRU and only have 1 set.
174+
ew.first = 0;
175+
ew.second = &cacheLine[ew.first];
176+
} else {
177+
// Lazily initialize all ways in the cacheline before starting to iterate.
178+
for (int i = 0; i < getWays(); ++i)
179+
cacheLine[i];
180+
181+
// If there is an invalid cache line, select that.
182+
auto it =
183+
std::find_if(cacheLine.begin(), cacheLine.end(),
184+
[=](const auto &way) { return !way.second.valid; });
185+
if (it != cacheLine.end()) {
186+
ew.first = it->first;
187+
ew.second = &it->second;
188+
}
189+
if (ew.second == nullptr) {
190+
// Else, Find LFU way.
191+
int save_num = 0;
192+
int tmp = 1000; // let it big enough. 1000 for test.
193+
int loop_counter = 0;
194+
for (auto &way : cacheLine) {
195+
if (static_cast<long>(way.second.lfu) < tmp) {
196+
tmp = way.second.lfu;
197+
save_num = loop_counter;
198+
}
199+
loop_counter+=1;
200+
}
201+
ew.first = save_num;
202+
ew.second = &cacheLine[ew.first];
203+
}
204+
}
205+
159206
}
160207

161208
Q_ASSERT(ew.first != s_invalidIndex && "Unable to locate way for eviction");

src/cachesim/cachesim.h

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ class CacheSim;
1616

1717
enum WriteAllocPolicy { WriteAllocate, NoWriteAllocate };
1818
enum WritePolicy { WriteThrough, WriteBack };
19-
enum ReplPolicy { Random, LRU, FIFO};
19+
enum ReplPolicy { Random, LRU, FIFO, LFU};
2020

2121
struct CachePreset {
2222
QString name;
@@ -106,6 +106,7 @@ class CacheSim : public CacheInterface {
106106
// LRU algorithm relies on invalid cache ways to have an initial high value.
107107
// -1 ensures maximum value for all way sizes.
108108
unsigned lru = -1;
109+
int lfu = 0;
109110
};
110111

111112
struct CacheIndex {
@@ -329,7 +330,8 @@ public slots:
329330
};
330331

331332
const static std::map<ReplPolicy, QString> s_cacheReplPolicyStrings{
332-
{ReplPolicy::Random, "Random"}, {ReplPolicy::LRU, "LRU"}, {ReplPolicy::FIFO, "FIFO"}};
333+
{ReplPolicy::Random, "Random"}, {ReplPolicy::LRU, "LRU"}, {ReplPolicy::FIFO, "FIFO"},
334+
{ReplPolicy::LFU, "LFU"}};
333335
const static std::map<WriteAllocPolicy, QString> s_cacheWriteAllocateStrings{
334336
{WriteAllocPolicy::WriteAllocate, "Write allocate"},
335337
{WriteAllocPolicy::NoWriteAllocate, "No write allocate"}};

0 commit comments

Comments
 (0)