diff --git a/src/cachesim/cachegraphic.cpp b/src/cachesim/cachegraphic.cpp index f5b4ffac6..130e60dc8 100644 --- a/src/cachesim/cachegraphic.cpp +++ b/src/cachesim/cachegraphic.cpp @@ -98,27 +98,47 @@ void CacheGraphic::updateLineReplFields(unsigned lineIdx) { return; } - if (m_cacheTextItems.at(0).at(0).lru == nullptr) { + if (m_cacheTextItems.at(0).at(0).lru == nullptr && m_cache.getReplacementPolicy() == ReplPolicy::LRU) { // The current cache configuration does not have any replacement field return; } - - for (const auto &way : m_cacheTextItems[lineIdx]) { - // If LRU was just initialized, the actual (software) LRU value may be very - // large. Mask to the number of actual LRU bits. - unsigned lruVal = cacheLine->at(way.first).lru; - lruVal &= vsrtl::generateBitmask(m_cache.getWaysBits()); - const QString lruText = QString::number(lruVal); - way.second.lru->setText(lruText); - - // LRU text might have changed; update LRU field position to center in - // column - const qreal y = lineIdx * m_lineHeight + way.first * m_setHeight; - const qreal x = - m_widthBeforeLRU + m_lruWidth / 2 - m_fm.horizontalAdvance(lruText) / 2; - - way.second.lru->setPos(x, y); + if (m_cacheTextItems.at(0).at(0).fifo == nullptr && m_cache.getReplacementPolicy() == ReplPolicy::FIFO){ + return; + } + if(m_cache.getReplacementPolicy() == ReplPolicy::LRU){ + for (const auto &way : m_cacheTextItems[lineIdx]) { + // If LRU was just initialized, the actual (software) LRU value may be very + // large. Mask to the number of actual LRU bits. + unsigned lruVal = cacheLine->at(way.first).lru; + lruVal &= vsrtl::generateBitmask(m_cache.getWaysBits()); + const QString lruText = QString::number(lruVal); + way.second.lru->setText(lruText); + + // LRU text might have changed; update LRU field position to center in + // column + const qreal y = lineIdx * m_lineHeight + way.first * m_setHeight; + const qreal x = + m_widthBeforeLRU + m_lruWidth / 2 - m_fm.horizontalAdvance(lruText) / 2; + way.second.lru->setPos(x, y); + } + } + if(m_cache.getReplacementPolicy() == ReplPolicy::FIFO){ + for (const auto &way : m_cacheTextItems[lineIdx]) { + // If LRU was just initialized, the actual (software) LRU value may be very + // large. Mask to the number of actual LRU bits. + int fifoVal = cacheLine->at(way.first).fifo; + const QString fifoText = QString::number(fifoVal); + way.second.fifo->setText(fifoText); + + // LRU text might have changed; update LRU field position to center in + // column + const qreal y = lineIdx * m_lineHeight + way.first * m_setHeight; + const qreal x = + m_widthBeforefifo + m_fifoWidth / 2 - m_fm.horizontalAdvance(fifoText) / 2; + way.second.fifo->setPos(x, y); + } } + } QString CacheGraphic::addressString() const { @@ -409,6 +429,7 @@ void CacheGraphic::cacheInvalidated() { m_blockWidth = m_fm.horizontalAdvance(" " + addressString() + " "); m_bitWidth = m_fm.horizontalAdvance("00"); m_lruWidth = m_fm.horizontalAdvance(QString::number(m_cache.getWays()) + " "); + m_fifoWidth = m_fm.horizontalAdvance(QString::number(m_cache.getWays()) + " "); m_cacheHeight = m_lineHeight * m_cache.getLines(); m_tagWidth = m_blockWidth; @@ -436,9 +457,10 @@ void CacheGraphic::cacheInvalidated() { } m_widthBeforeLRU = width; + m_widthBeforefifo = width; - if (m_cache.getReplacementPolicy() == ReplPolicy::LRU && - m_cache.getWays() > 1) { + if (m_cache.getReplacementPolicy() == ReplPolicy::LRU + && m_cache.getWays() > 1) { // Draw LRU bit column new QGraphicsLineItem(width + m_lruWidth, 0, width + m_lruWidth, m_cacheHeight, this); @@ -451,6 +473,23 @@ void CacheGraphic::cacheInvalidated() { width += m_lruWidth; } + + if (m_cache.getReplacementPolicy() == ReplPolicy::FIFO + && m_cache.getWays() > 1) { + // Draw FIFO bit column + new QGraphicsLineItem(width + m_fifoWidth, 0, width + m_fifoWidth, + m_cacheHeight, this); + const QString fifoBitText = "FIFO"; + auto *textItem = drawText(fifoBitText, + width + m_fifoWidth / 2 - + m_fm.horizontalAdvance(fifoBitText) / 2, + -m_fm.height()); + textItem->setToolTip("FIFO bits"); + width += m_fifoWidth; + } + + + m_widthBeforeTag = width; // Draw tag column @@ -705,6 +744,14 @@ void CacheGraphic::initializeControlBits() { m_fm.horizontalAdvance(lruText) / 2; line[setIdx].lru = drawText(lruText, x, y); } + if (m_cache.getReplacementPolicy() == ReplPolicy::FIFO && + m_cache.getWays() > 1) { + const QString fifoText = QString::number(0); + x = m_widthBeforefifo + m_fifoWidth / 2 - + m_fm.horizontalAdvance(fifoText) / 2; + // Create FIFO field + line[setIdx].fifo = drawText("0", x, y); + } } } } diff --git a/src/cachesim/cachegraphic.h b/src/cachesim/cachegraphic.h index 78696ebf7..a9e2cd937 100644 --- a/src/cachesim/cachegraphic.h +++ b/src/cachesim/cachegraphic.h @@ -62,6 +62,7 @@ public slots: std::map> blocks; std::unique_ptr tag = nullptr; QGraphicsSimpleTextItem *lru = nullptr; + QGraphicsSimpleTextItem *fifo = nullptr; QGraphicsSimpleTextItem *valid = nullptr; QGraphicsSimpleTextItem *dirty = nullptr; std::map> dirtyBlocks; @@ -113,9 +114,10 @@ public slots: qreal m_widthBeforeBlocks = 0; qreal m_widthBeforeTag = 0; qreal m_widthBeforeLRU = 0; + qreal m_widthBeforefifo = 0; qreal m_widthBeforeDirty = 0; qreal m_lruWidth = 0; - + qreal m_fifoWidth = 0; static constexpr qreal z_grid = 0; static constexpr qreal z_wires = -1; diff --git a/src/cachesim/cachesim.cpp b/src/cachesim/cachesim.cpp index 20a21a0d4..778ea185f 100644 --- a/src/cachesim/cachesim.cpp +++ b/src/cachesim/cachesim.cpp @@ -52,6 +52,15 @@ void CacheSim::updateCacheLineReplFields(CacheLine &line, unsigned wayIdx) { // Upgrade @p lruIdx to the most recently used line[wayIdx].lru = 0; } + + if (getReplacementPolicy() == ReplPolicy::FIFO) { + for(auto &set : line){ + if(m_fifoflag && set.second.valid){ + set.second.fifo ++; + } + } + m_fifoflag = false; + } } void CacheSim::revertCacheLineReplFields(CacheLine &line, @@ -69,6 +78,15 @@ void CacheSim::revertCacheLineReplFields(CacheLine &line, // Revert the oldWay LRU line[wayIdx].lru = oldWay.lru; } + + if (getReplacementPolicy() == ReplPolicy::FIFO) { + + for(auto &set : line){ + if(set.second.valid && m_fifoflag) set.second.fifo--; + } + m_fifoflag = false; + line[wayIdx].fifo = oldWay.fifo; + } } CacheSim::CacheSize CacheSim::getCacheSize() const { @@ -95,6 +113,13 @@ CacheSim::CacheSize CacheSim::getCacheSize() const { size.bits += componentBits; } + if (m_replPolicy == ReplPolicy::FIFO) { + // FIFO bits + componentBits = getWaysBits() * entries; + size.components.push_back("FIFO bits: " + QString::number(componentBits)); + size.bits += componentBits; + } + // Tag bits componentBits = vsrtl::bitcount(m_tagMask) * entries; size.components.push_back("Tag bits: " + QString::number(componentBits)); @@ -115,13 +140,48 @@ CacheSim::locateEvictionWay(const CacheTransaction &transaction) { std::pair ew; ew.first = s_invalidIndex; ew.second = nullptr; - // Locate a new way based on replacement policy. if (m_replPolicy == ReplPolicy::Random) { // Select a random way ew.first = std::rand() % getWays(); ew.second = &cacheLine[ew.first]; - } else if (m_replPolicy == ReplPolicy::LRU) { + } + else if (m_replPolicy == ReplPolicy::FIFO){ +// ew.first = m_fifoIndexCounter; +// ew.second = &cacheLine[ew.first]; +// m_fifoIndexCounter += 1; +// m_fifoIndexCounter %= getWays(); + if (getWays() == 1) { + // Nothing to do if we are in LRU and only have 1 set. + ew.first = 0; + ew.second = &cacheLine[ew.first]; + } else { + // Lazily initialize all ways in the cacheline before starting to iterate. + for (int i = 0; i < getWays(); ++i) + cacheLine[i]; + + // If there is an invalid cache line, select that. + auto it = + std::find_if(cacheLine.begin(), cacheLine.end(), + [=](const auto &way) { return !way.second.valid; }); + if (it != cacheLine.end()) { + ew.first = it->first; + ew.second = &it->second; + m_fifoflag = true; + } + if (ew.second == nullptr) { + for (auto &way : cacheLine) { + if (static_cast(way.second.fifo) == getWays()){ + ew.first = way.first; + ew.second = &way.second; + m_fifoflag = true; + break; + } + } + } + } + } + else if (m_replPolicy == ReplPolicy::LRU) { if (getWays() == 1) { // Nothing to do if we are in LRU and only have 1 set. ew.first = 0; @@ -150,8 +210,7 @@ CacheSim::locateEvictionWay(const CacheTransaction &transaction) { } } } - } - + } Q_ASSERT(ew.first != s_invalidIndex && "Unable to locate way for eviction"); Q_ASSERT(ew.second != nullptr && "Unable to locate way for eviction"); return ew; @@ -380,6 +439,10 @@ void CacheSim::undo() { else if (!trace.transaction.isHit) { way = oldWay; } + if (!trace.transaction.isHit && getReplacementPolicy() == ReplPolicy::FIFO) { + m_fifoflag = true; + way = oldWay; + } // Case 3: Else, it was a cache hit; Revert replacement fields and dirty // blocks way.dirtyBlocks = oldWay.dirtyBlocks; diff --git a/src/cachesim/cachesim.h b/src/cachesim/cachesim.h index ba8fd31ba..babe46cc9 100644 --- a/src/cachesim/cachesim.h +++ b/src/cachesim/cachesim.h @@ -16,7 +16,7 @@ class CacheSim; enum WriteAllocPolicy { WriteAllocate, NoWriteAllocate }; enum WritePolicy { WriteThrough, WriteBack }; -enum ReplPolicy { Random, LRU }; +enum ReplPolicy { Random, LRU, FIFO }; struct CachePreset { QString name; @@ -91,7 +91,8 @@ class CacheSim : public CacheInterface { Q_OBJECT public: static constexpr unsigned s_invalidIndex = static_cast(-1); - + unsigned m_fifoIndexCounter = 0; + bool m_fifoflag = false; struct CacheSize { unsigned bits = 0; std::vector components; @@ -106,6 +107,7 @@ class CacheSim : public CacheInterface { // LRU algorithm relies on invalid cache ways to have an initial high value. // -1 ensures maximum value for all way sizes. unsigned lru = -1; + int fifo = 0; }; struct CacheIndex { @@ -329,7 +331,7 @@ public slots: }; const static std::map s_cacheReplPolicyStrings{ - {ReplPolicy::Random, "Random"}, {ReplPolicy::LRU, "LRU"}}; + {ReplPolicy::Random, "Random"}, {ReplPolicy::LRU, "LRU"}, {ReplPolicy::FIFO, "FIFO"}}; const static std::map s_cacheWriteAllocateStrings{ {WriteAllocPolicy::WriteAllocate, "Write allocate"}, {WriteAllocPolicy::NoWriteAllocate, "No write allocate"}};