aboutsummaryrefslogblamecommitdiff
path: root/event.cc
blob: 96750bc850a8a496033707b052a2109ea3540bee (plain) (tree)











































































































































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

using sc_core::sc_event;
using sc_core::sc_module;
using sc_core::sc_module_name;
using sc_core::SC_NS;
using sc_core::sc_start;
using sc_core::sc_time;
using sc_core::SC_ZERO_TIME;

// -- MOD_METHOD ---------------------------------------------------------------

struct mod_method : public sc_module {
  SC_HAS_PROCESS(mod_method);

  explicit mod_method(sc_module_name nm) : sc_module(nm) {
    SC_METHOD(ev_method);
    // STATIC sensitivity for ev_method, the METHOD will become RUNNABLE when
    // the event is notified.
    sensitive << m_method_event;
    // DONT run method initially at time 0s, only after it is triggered.
    // By default SC_METHODs are made RUNNABLE at time 0s.
    dont_initialize();

    // Helper to drive the method example.
    SC_THREAD(run_method);
  }

 private:
  sc_event m_method_event;

  void ev_method() {
    // No calls to wait() in METHODS.
    // Methods are triggered by static sensitivity or dynamic sensitivity.

    CLOGM(GREEN, "triggered by_static_event_not_next_trigger=%d timed_out=%d",
          m_method_event.triggered(), timed_out());

    if (m_method_event.triggered()) {
      // Create DYNAMIC sensitivity list, either by time or event.
      // The DYNAMIC sensitivity OVERRIDES the STATIC sensitivity, therefore if
      // the event is not listed here, the method will only be triggered by the
      // TIME value no matter if the EVENT (static sensitivity) is triggered.
      next_trigger(5000, SC_NS, m_method_event);
    }
  }

  void run_method() {
    // Notify event in the future.
    CLOGM(YELLOW, "TIMED NOTIFY");
    m_method_event.notify(100, SC_NS);

    wait(200, SC_NS);

    // Notify event in the next delta cycle.
    CLOGM(YELLOW, "DELTA NOTIFY");
    m_method_event.notify(SC_ZERO_TIME);

    wait(200, SC_NS);

    // Notify event in the current delta cycle.
    CLOGM(YELLOW, "IMMEDIATE NOTIFY");
    m_method_event.notify();

    wait(200, SC_NS);
  }
};

// -- MOD_THREAD ---------------------------------------------------------------

struct mod_thread : public sc_module {
  SC_HAS_PROCESS(mod_thread);

  explicit mod_thread(sc_module_name nm) : sc_module(nm) {
    SC_THREAD(ev_thread);
    // STATIC sensitivity for ev_thread.
    sensitive << m_thread_event;

    // Helper to drive the example and drive the simulator.
    SC_THREAD(run_thread);
  }

 private:
  sc_event m_thread_event;

  void ev_thread() {
    // WAIT on STATIC sensitivity event.
    wait();

    while (true) {
      CLOGM(CYAN, "WAIT TIMED or EVENT");
      // Create DYNAMIC sensitivity list, WAIT on either TIMEOUT or EVENT.
      wait(sc_time(2000, SC_NS), m_thread_event);
      CLOGM(CYAN, "done by_event_not_time=%d timed_out=%d",
            m_thread_event.triggered(), timed_out());

      CLOGM(CYAN, "WAIT STATIC SENSITIVITY");
      // WAIT on static sensitivity trigger.
      wait();
      CLOGM(CYAN, "done");
    }
  }

  void run_thread() {
    // Some initial wait, to run at different time than the method example.
    wait(10000, SC_NS);
    m_thread_event.notify(SC_ZERO_TIME);

    CLOGM(MAGENTA, "big TIMED WAIT -> should timeout thread");
    wait(10000, SC_NS);

    CLOGM(MAGENTA, "TIMED NOTIFY");
    m_thread_event.notify(100, SC_NS);

    wait(1000, SC_NS);

    CLOGM(MAGENTA, "TIMED NOTIFY");
    m_thread_event.notify(200, SC_NS);

    wait(1000, SC_NS);

    CLOGM(MAGENTA, "DELTA NOTIFY");
    m_thread_event.notify(SC_ZERO_TIME);
  }
};

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

extern "C" int sc_main(int, char*[]) {
  // timed_out() is deprecated, but it is just used for visualization here.
  sc_core::sc_report_handler::set_actions("/IEEE_Std_1666/deprecated",
                                          sc_core::SC_DO_NOTHING);

  mod_method method("method");
  mod_thread thread("thread");

  sc_start();
  return 0;
}