Skip to content

File mshr_file.h

File List > cache > mshr_file.h

Go to the documentation of this file

#pragma once

#include <vector>

#include "mem/cache/cache.h"

namespace simtix {

namespace mem {

class MshrFile {
 public:
  struct MSHR {
    explicit MSHR(size_t block_size, uint32_t core_req_queue_depth)
        : valid(false),
          core_req_queue(core_req_queue_depth),
          data_buf(block_size) {}

    MSHR(const MSHR &other)
        : valid(false),
          core_req_queue(other.core_req_queue.capacity()),
          data_buf(other.data_buf.size()) {}

    bool valid;
    Cache::Payload payload;
    sim::SizedQueue<CacheImpl::CoreRequest> core_req_queue;
    std::vector<uint8_t> data_buf;
  };

  explicit MshrFile(const Cache::Param &param);
  ~MshrFile();

  bool CanAcceptCoreRequestEarly(const CacheImpl::CoreRequest &req,
                                 const uint32_t data_array_req_queue_size);
  bool CanAcceptCoreRequest(const CacheImpl::CoreRequest &req);
  bool AcceptCoreRequest(CacheImpl::CoreRequest &&req);
  bool NotifyFill(uint32_t mshr_id);

  sim::SizedQueue<uint32_t> &pending_mshr_req_queue() {
    return pending_mshr_req_queue_;
  }

  Cache::Payload GetMshrPayload(uint32_t mshr_id);
  const CacheImpl::CoreRequest &GetMshrCoreReqQueueFront(uint32_t mshr_id);
  uint8_t *GetMshrDataBuffer(uint32_t mshr_id);

  bool HasPendingReplayRequest();
  std::optional<CacheImpl::CoreRequest> GetPendingReplayRequest();

  bool HasFreeMshr() { return !free_mshrs_.empty(); }
  bool HasFreeMshrEarly() {
    return free_mshrs_.size() > kDataArrayReqQueueDepth;
  }
  bool HasPendingMshr() { return !free_mshrs_.full(); }

  std::optional<MSHR *> CheckIfMshrHit(const CacheImpl::CoreRequest &req) {
    uint64_t line_addr = ToLineAddr(req.payload.addr);
    for (auto &mshr : mshrs_) {
      if (mshr.valid && mshr.payload.addr == line_addr * kBlockSizeBytes) {
        // MSHR hit, but no room for buffering new core reqeust.
        return &mshr;
      }
    }
    return std::nullopt;
  }

 protected:
  inline uint64_t ToLineAddr(uint64_t addr) { return addr / kBlockSizeBytes; }

  sim::SizedQueue<uint32_t> pending_mshr_req_queue_;
  sim::SizedQueue<uint32_t> pending_mshr_replay_queue_;

  sim::SizedQueue<uint32_t> free_mshrs_;
  std::vector<MSHR> mshrs_;
  uint32_t kDataArrayReqQueueDepth;
  const size_t kBlockSizeBytes;  // block size in bytes
};

}  // namespace mem
}  // namespace simtix