Skip to content

File to_tlm.h

File List > bindings > simtix > to_tlm.h

Go to the documentation of this file

#pragma once

#include <simtix/mem.h>
#include <sysc/kernel/sc_event.h>
#include <systemc.h>
#include <tlm.h>
#include <tlm_utils/peq_with_get.h>
#include <tlm_utils/simple_initiator_socket.h>

#include <deque>
#include <sol/sol.hpp>
#include <unordered_map>

namespace simtix {

class ToTlm : public mem::MemoryInterface, sc_module {
 public:
  explicit ToTlm(const sc_module_name &name, uint32_t fifo_size = 16);

  ~ToTlm() override = default;

  using Target =
      tlm_utils::simple_initiator_socket<ToTlm>::base_target_socket_type;

  struct Request {
    Request() = default;
    ~Request() {}
    Request(const Payload &payload, bool is_write, OnResp on_resp)
        : payload(payload), is_write(is_write), on_resp(std::move(on_resp)) {}

    Request(const Request &other)
        : payload(other.payload),
          is_write(other.is_write),
          on_resp(other.on_resp) {}

    Request &operator=(const Request &other) {
      payload = other.payload;
      is_write = other.is_write;
      on_resp = other.on_resp;
      return *this;
    }

    Payload payload;
    bool is_write;
    OnResp on_resp;
  };

  bool Read(Payload payload, OnResp on_resp) override;

  bool Write(Payload payload, OnResp on_resp) override;

  uint8_t &operator[](const uint64_t addr) override;

  void Tick() override;

  bool HasPendingTasks() override;

  void set_target(Target *t);
  Target *target() const;

  void set_clock(std::shared_ptr<sc_clock> clock);
  sc_clock *clock() const;

  tlm_utils::simple_initiator_socket<ToTlm> mem_port_;

 private:
  Target *target_;
  std::shared_ptr<sc_clock> clock_;

  sc_in<bool> clock_i_;

  sc_event target_ready_;

  // Variable: fifo_size_
  //   Size of request and response FIFOs.
  uint32_t fifo_size_;

  // Variable: req_fifo_
  //   FIFO of requests to be sent to the target.
  std::deque<Request> req_fifo_;

  uint8_t dummy_byte_ = 0;

  // Variable: resp_fifo_
  //   FIFO of responses from the target. Each response is associated with a
  //   request. The entry will not be removed until the response is accepted by
  //   the initiator.
  std::deque<std::pair<tlm::tlm_generic_payload *, Request>> resp_fifo_;

  // Variable: req_map_
  //   Map of requests to be sent to the target. The key is the transaction and
  //   the value is the original request.
  std::unordered_map<tlm::tlm_generic_payload *, Request> req_map_;

  // Payload event queue
  tlm_utils::peq_with_get<tlm::tlm_generic_payload> peq_;

  bool AcceptRequest(const Payload &payload, bool is_write, OnResp on_resp);

  void ProcessRequest();

  void ProcessResponse();

  void EndResponse();

  // Callbacks for TLM transactions
  tlm::tlm_sync_enum nb_transport_bw(tlm::tlm_generic_payload &trans,
                                     tlm::tlm_phase &phase, sc_time &delay);
};
}  // namespace simtix