From 173622e9e82b7c2b1c6f8146056661b2a6577735 Mon Sep 17 00:00:00 2001 From: Johannes Stoelp Date: Wed, 26 Jul 2023 00:05:14 +0200 Subject: add some initial playground examples + scripts to build --- sc_export2.cc | 103 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 103 insertions(+) create mode 100644 sc_export2.cc (limited to 'sc_export2.cc') diff --git a/sc_export2.cc b/sc_export2.cc new file mode 100644 index 0000000..adf6e31 --- /dev/null +++ b/sc_export2.cc @@ -0,0 +1,103 @@ +#include +#include "utils.h" + +// This file gives an example on how to define an own interface and use that +// interface to communicate between two sc_modules. +// +// One module is the driver and accesses the interface via a sc_port and the +// other module provides an implementation of the interface and exposes it via a +// sc_export. +// +// The sc_port and sc_export are then bound to connect the driver and the +// implementer. +// +// This example lays a foundation in understanding how TLM2 sockets work. + +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_port; + +// -- INTERFACE ---------------------------------------------------------------- + +struct msg_if : sc_interface { + enum message { + kHello, + kPayload, + kGoodbye, + }; + + virtual void send(message) = 0; +}; + +constexpr inline const char* to_str(msg_if::message msg) { + switch (msg) { + case msg_if::kHello: + return "Hello"; + case msg_if::kPayload: + return "Payload"; + case msg_if::kGoodbye: + return "Goodbye"; + } +} + +// -- SENDER ------------------------------------------------------------------- + +struct sender : public sc_module { + SC_HAS_PROCESS(sender); + + explicit sender(sc_module_name nm) : sc_module(nm) { + SC_METHOD(do_protocol); + } + + // A sc_port instantiated with the custom interface. The sc_port is used by + // this module to access the interface implementation. + sc_port p_msg; + + private: + void do_protocol() { + const auto send = [this](msg_if::message msg) { + LOGM("%s", to_str(msg)); + p_msg->send(msg); + }; + + // Send out some messages through the msg_if via the sc_port. + send(msg_if::kHello); + send(msg_if::kPayload); + send(msg_if::kGoodbye); + } +}; + +// -- RECEIVER ----------------------------------------------------------------- + +struct receiver : public sc_module, public msg_if { + explicit receiver(sc_module_name nm) : sc_module(nm) { + // Bind the msg_if implementation against sc_export. + p_msg(*this); + } + + // A sc_export instantiated with the custom interface. The sc_export can be + // bound against a sc_port (with the same interface), which effectively bindd + // the implementation behind the sc_export against the sc_port. + sc_export p_msg; + + private: + virtual void send(msg_if::message msg) override { + LOGM("%s", to_str(msg)); + } +}; + +// -- SC_MAIN ------------------------------------------------------------------ + +extern "C" int sc_main(int, char*[]) { + sender s("sender"); + receiver r{"receiver"}; + + // Bind the sc_port and sc_export, such that the sender will invoke the msg_if + // implemented by the receiver. + s.p_msg(r.p_msg); + + sc_core::sc_start(); + return 0; +} -- cgit v1.2.3