Skip to content

File nbhb_cache.h

File List > mem > nbhb_cache > nbhb_cache.h

Go to the documentation of this file

#pragma once

#include <simtix/mem.h>

#include <deque>
#include <string>
#include <vector>

namespace simtix {

namespace mem {

class NBHBCacheImpl {
 public:
  using Payload = MemoryInterface::Payload;
  using OnResp = MemoryInterface::OnResp;
  using RespStatus = MemoryInterface::RespStatus;

  NBHBCacheImpl(const std::string &name, MemoryInterface *next_level,
                const NBHBCache::Param &param)
      : stat_(std::make_shared<Stat>(name)),
        name_(name),
        kBlockSizeBytes(param.kBlockSizeBytes),
        kBanks(param.kBanks),
        bank_occupied_(kBanks, false),
        next_level_(next_level) {
    for (size_t i = 0; i < kBanks; i++) {
      Cache::Param bank_param = param;
      bank_param.kSizeBytes = param.kSizeBytes / kBanks;
      banks_.emplace_back(fmt::format("{}.bank[{}]", name, i), next_level,
                          bank_param);
    }
    for (size_t i = 0; i < kBanks; i++) {
      stat_->AddStatGroup(banks_[i].stat());
    }
  }

  // Function: ForwardRequest
  //   Forward the request to the corresponding bank. If the bank is occupied by
  //   any request, return false to indicate the request is not accepted.
  bool ForwardRequest(const Payload &payload, OnResp on_resp, bool is_write);

 protected:
  inline uint64_t ToBankIndex(uint64_t addr) {
    return addr / kBlockSizeBytes % kBanks;
  }

  struct Stat : stat::Group {
    explicit Stat(const std::string &s)
        : Group(s),
          STAT(bank_conflict, "Number of bank conflicts", "N/A"),
          STAT(bank_available, "Number of available banks when request is sent",
               "N/A"),
          STAT(total_write_requests,
               "Total number of write requests send to NBHB cache", "N/A"),
          STAT(total_read_requests,
               "Total number of read requests send to NBHB cache", "N/A"),
          STAT(forwarded_requests, "Number of forwarded requests", "N/A"),
          STAT(total_requests, "Total number of requests send to NBHB cache",
               "N/A"),
          STAT(bank_utilization, "Bank utilization of NBHB cache", "N/A") {
      total_requests = total_write_requests + total_read_requests;
      bank_utilization = forwarded_requests / bank_available;
    }
    stat::Integer bank_conflict;
    stat::Integer bank_available;
    stat::Integer total_write_requests;
    stat::Integer total_read_requests;
    stat::Integer forwarded_requests;

    stat::Formula<stat::Integer> total_requests;
    stat::Formula<stat::Real> bank_utilization;
  };

  std::shared_ptr<Stat> stat_;

  void ResetStat() {
    stat_ = std::make_shared<Stat>(name_);
    for (size_t i = 0; i < kBanks; i++) {
      banks_[i].ResetStat();
      stat_->AddStatGroup(banks_[i].stat());
    }
  }

  const std::string name_;
  const size_t kBlockSizeBytes;
  const size_t kBanks;
  std::deque<Cache> banks_;
  std::vector<bool> bank_occupied_;
  MemoryInterface *next_level_;
};

class NBHBCache::Impl : NBHBCacheImpl {
 public:
  Impl(const std::string &name, MemoryInterface *next_level, const Param &param)
      : NBHBCacheImpl(name, next_level, param) {}

 protected:
  friend class NBHBCache;
};

}  // namespace mem

}  // namespace simtix