aboutsummaryrefslogtreecommitdiff
path: root/src/minimal_socket.cc
blob: 21107fdb42976218b24a3d3f0ad5196830e91f33 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
#include <systemc>
#include "utils/log.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_init(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_init(I.p_sock);

  sc_core::sc_start();
  return 0;
}