Skip to content

File atomic.h

File List > fu > lsu > atomic.h

Go to the documentation of this file

#pragma once

#include <cassert>
#include <string>
#include <utility>
#include <vector>

#include "sm/fu/lsu/base.h"

namespace simtix {

// Class: TimingLoadStoreUnit
//   A load/store unit that takes memory delay into consideration, which
//   separates requests from instructions and outstanding requests in 2
//   separated queues. <TimingLoadStoreUnit> will always accept <InstrPtr> for
//   Read/Write, putting them into sized <pending_requests_> queue. The
//   number of outstanding requests is determined by the parameter during
//   construction of <TimingLoadStoreUnit>. The requests will be processed
//   in the order of arrival, and the responses will be put into
//   <response_requests_> queue.

class AtomicLoadStoreUnit : public BaseLoadStoreUnit, sim::Clocked {
 public:
  struct Request {
    Request() = default;

    Request(const Payload &payload, bool is_write, OnResp on_resp)
        : payload(payload),
          valid(true),
          accepted(false),
          is_write(is_write),
          on_resp(std::move(on_resp)) {}

    Request(Request &&other)
        : payload(other.payload),
          valid(other.valid),
          accepted(other.accepted),
          is_write(other.is_write),
          on_resp(std::move(other.on_resp)) {}

    Request &operator=(Request &&other) {
      payload = other.payload;
      valid = other.valid;
      accepted = other.accepted;
      is_write = other.is_write;
      on_resp = std::move(other.on_resp);
      return *this;
    }

    Payload payload;
    bool valid;
    bool accepted;
    bool is_write;
    OnResp on_resp;
  };

  explicit AtomicLoadStoreUnit(const std::string &name,
                               uint32_t num_outstanding_requests,
                               const ArchParam &p = kDefaultArchParam)
      : BaseLoadStoreUnit(name, p),
        sim::Clocked(name),
        outstanding_requests_(p.kThreadsPerWarp()) {}

  ~AtomicLoadStoreUnit() {}

  bool Busy() override;

  bool Put(InstrPtr instr) override;

  std::optional<InstrPtr> Get() override;

  void PushWriteRequest(uint32_t tid, Payload payload, OnResp on_resp) override;

  void PushReadRequest(uint32_t tid, Payload payload, OnResp on_resp) override;

 protected:
  void Tick() override;

  bool HasPendingTasks() override;

  std::vector<Request> outstanding_requests_;

  bool requesting_ = false;
};

}  // namespace simtix