aboutsummaryrefslogblamecommitdiff
path: root/minimal_socket.cc
blob: 7fe7f3872a9d4b0acda89f9d0f0dc5df49eaa159 (plain) (tree)

























































































































                                                                                
#include <systemc>
#include "utils.h"

using sc_core::sc_export;
using sc_core::sc_interface;
using sc_core::sc_module;
using sc_core::sc_module_name;
using sc_core::SC_NS;
using sc_core::sc_port;

// -- INTERFACES ---------------------------------------------------------------

struct fwd_if : sc_interface {
  virtual void fwd(const char* msg) = 0;
};

struct bwd_if : sc_interface {
  virtual void bwd(const char* msg) = 0;
};

// -- INITIATOR SOCKET ---------------------------------------------------------

// An initiator socket provides its owner access to a FWD_IF implementation. The
// initiator socket itself must be bound against a BWD_IF implementation,
// offering the BWD_IF implementation to the target socket that can be bound
// against the initiator socket.
//
// Effectively the initiator socket is a sc_port / sc_export pair, using the
// sc_port to access the FWD_IF and the sc_export to offer the BWD_IF
// implementation.

struct initiator_socket : sc_export<bwd_if> {
  sc_port<fwd_if> p_fwd;

  fwd_if* operator->() {
    return p_fwd.operator->();
  }
};

// -- TARGET SOCKET ------------------------------------------------------------

// A target socket provides its owner access to a BWD_IF implementation. The
// target socket itself must be bound against a FWD_IF implementation,
// offering the FWD_IF implementation to the initiator socket that can be bound
// against the target socket.
//
// Effectively the target socket is a sc_port / sc_export pair, using the
// sc_port to access the BWD_IF and the sc_export to offer the FWD_IF
// implementation.

struct target_socket : sc_export<fwd_if> {
  sc_port<bwd_if> p_bwd;

  void bind(initiator_socket& init) {
    // Bind the sc_port / sc_export pairs between the initiator and target
    // socket.

    // Initiator:sc_port -> Target:sc_export.
    init.p_fwd(*this);

    // Target:sc_port -> Initiator:sc_export.
    p_bwd(init);
  }

  bwd_if* operator->() {
    return p_bwd.operator->();
  }
};

// -- INITIATOR ----------------------------------------------------------------

struct initiator : public sc_module, public bwd_if {
  SC_HAS_PROCESS(initiator);

  initiator_socket p_sock;

  explicit initiator(sc_module_name nm) : sc_module(std::move(nm)) {
    p_sock(*this);
    SC_THREAD(work);
  }

 private:
  virtual void bwd(const char* msg) override {
    LOGM("%s", msg);
  }

  void work() {
    sc_core::wait(10, SC_NS);
    p_sock->fwd("moose");
  }
};

// -- TARGET -------------------------------------------------------------------

struct target : public sc_module, public fwd_if {
  SC_HAS_PROCESS(target);

  target_socket p_sock;

  explicit target(sc_module_name nm) : sc_module(std::move(nm)) {
    p_sock(*this);
  }

 private:
  virtual void fwd(const char* msg) override {
    LOGM("%s", msg);
    p_sock->bwd("meeh");
  }
};

// -- SC_MAIN ------------------------------------------------------------------

extern "C" int sc_main(int, char*[]) {
  initiator I("initiator");
  target T("target");

  // Bind the initiator and target sockets.
  T.p_sock.bind(I.p_sock);

  sc_core::sc_start();
  return 0;
}