Skip to content

File tag_array.h

File List > cache > tag_array.h

Go to the documentation of this file

#pragma once

#include <simtix/mem.h>

#include <vector>

namespace simtix {

namespace mem {

class TagArray {
 public:
  // Tag with valid bit; using full address as tag.
  struct Tag {
    bool valid = false;
    bool dirty = false;
    uint64_t tag = 0;
    uint64_t timestamp = 0;
    uint32_t wid = 0;
  };

  struct Rep {
    int way;
    std::optional<uint64_t> victim;
  };

  explicit TagArray(const Cache::Param &param);

  ~TagArray();

  // Test if the given address is present in the cache.
  int Probe(uint64_t addr, bool is_write, uint32_t *wid);

  // Update the tag array with given address, and return the victim if present.
  Rep Replace(uint64_t addr, uint32_t wid);

  // Look if tag with corresponding index is dirty for write back
  Rep FindDirtyTag(uint64_t flush_tag_arr_index);

 protected:
  inline uint64_t ToLineAddr(uint64_t addr) { return addr / kBlockSizeBytes; }
  inline uint64_t ToBankAddr(uint64_t addr) {
    return ToLineAddr(addr) / kBanks;
  }
  inline uint32_t ToSetIndex(uint64_t addr) { return ToBankAddr(addr) % kSets; }

  inline Tag *GetSet(uint64_t addr) { return &arr_[ToSetIndex(addr) * kWays]; }

  inline void UpdateTag(Tag *tag, uint64_t addr, uint32_t wid) {
    tag->valid = true;
    tag->dirty = false;
    tag->tag = ToBankAddr(addr);
    tag->timestamp = simtix::sim::CurTick();
    tag->wid = wid;
  }

  const size_t kSizeBytes;
  const size_t kBlockSizeBytes;
  const uint8_t kBanks;
  const uint8_t kWays;
  const size_t kSets;
  const Cache::Param::ReplacementPolicies kReplacementPolicy;
  const Cache::Param::WriteHitPolicies kWriteHitPolicy;

  // Tag array with valid bit; using full address as tag.
  std::vector<Tag> arr_;
};

}  // namespace mem
}  // namespace simtix