Skip to content

File pipelined.h

File List > arbitrator > pipelined.h

Go to the documentation of this file

#pragma once

#include <simtix/param.h>

#include <cstddef>
#include <cstdint>
#include <memory>
#include <string>
#include <utility>
#include <vector>

#include "simtix/sm.h"
#include "sm/arbitrator/base.h"

namespace simtix {

// Class: PipelinedArbitrator
class PipelinedArbitrator : public BaseArbitrator {
 public:
  struct Request {
    const std::vector<Thread *> *active_threads;
    uint32_t reg_id;
    int64_t *data_arr;
    int64_t data;
    OnReady on_ready;
    bool is_write;
    uint32_t req_bank;

    Request(const std::vector<Thread *> *active_threads, uint32_t reg_id,
            int64_t *data_arr, int64_t data, OnReady on_ready, bool is_write,
            uint32_t req_bank)
        : active_threads(active_threads),
          reg_id(reg_id),
          data_arr(data_arr),
          data(data),
          on_ready(std::move(on_ready)),
          is_write(is_write),
          req_bank(req_bank) {}
  };

  explicit PipelinedArbitrator(const std::string &name, const ArchParam &p,
                               const pipelined::PipelinedSM::Param &pp);
  ~PipelinedArbitrator() = default;

  void PushRegfileReadReq(const std::vector<Thread *> &active_threads,
                          uint32_t reg_id, int64_t *data,
                          OnReady on_ready) override;

  void PushRegfileWriteReq(const std::vector<Thread *> &active_threads,
                           uint32_t reg_id, int64_t *data,
                           OnReady on_ready) override;

  void PushRegfileWriteReq(const std::vector<Thread *> &active_threads,
                           uint32_t reg_id, int64_t data,
                           OnReady on_ready) override;

  int64_t ReadRegfile(uint32_t wid, uint32_t tid, uint32_t reg_id) override {
    return regfile_[ToRegfileIndex(wid, tid, reg_id)] * (reg_id != 0);
  }

  void WriteRegfile(uint32_t wid, uint32_t tid, uint32_t reg_id,
                    int64_t data) override {
    regfile_[ToRegfileIndex(wid, tid, reg_id)] = data * (reg_id != 0);
  }

  void ArbitrateReq();

  void Reset();

  void ResetStat() { stat_ = std::make_shared<Stat>(name_); }

  const std::shared_ptr<stat::Group> stat() const { return stat_; }

 protected:
  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 banked regfile", "N/A"),
          STAT(total_read_requests,
               "Total number of read requests send to banked regfile", "N/A"),
          STAT(forwarded_requests, "Number of forwarded requests", "N/A"),
          STAT(total_requests,
               "Total number of requests send to banked regfile", "N/A"),
          STAT(bank_utilization, "Bank utilization of banked regfile", "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_;

 private:
  const std::string name_;
  const uint32_t kThreadsPerWarp;
  const uint32_t kWarpsPerCore;
  const uint32_t kWarpsPerWarpGroup;
  const bool kSwizzle;
  const size_t kSharedPorts;
  const size_t kReadPorts;
  const size_t kWritePorts;
  const uint32_t kRegfileBanks;

  uint32_t ToRegfileBank(uint32_t wid, uint32_t reg_id);
  uint32_t ToRegfileIndex(uint32_t wid, uint32_t tid, uint32_t reg_id);
  void AccessRegfile(Request req);

  std::vector<int64_t> regfile_;

  std::vector<std::vector<Request> *> req_buf_arr_;
  std::vector<std::vector<Request>> req_buf_;
  std::vector<Request> *read_req_buf_;
  std::vector<Request> *write_req_buf_;

  std::vector<std::vector<size_t> *> bank_mask_arr_;
  std::vector<std::vector<size_t>> bank_mask_;
  std::vector<size_t> *read_bank_mask_;
  std::vector<size_t> *write_bank_mask_;
};

}  // namespace simtix