Jump to content
Roman Popov

Passing event to SC_CTHREAD macro

Recommended Posts

Why SystemC does not allow to pass event directly to SC_CTHREAD macro?

For example:

#include <systemc.h>

SC_MODULE(test) {
    sc_clock clkgen{"clkgen", 10, SC_NS};
    sc_in_clk clk{"clk"};

    SC_CTOR(test) {
        clk(clkgen);

        SC_CTHREAD(test_cthread, clk.pos()); // OK
        SC_CTHREAD(test_cthread, clkgen.posedge_event());  // Compile error!
    }
  
  void test_cthread();
};

If I inline macro I can do what I want:

{ ::sc_core::sc_process_handle test_cthread_handle =
  sc_core::sc_get_curr_simcontext()->create_cthread_process(
    "test_cthread",
    false,
    static_cast<sc_core::SC_ENTRY_FUNC>(&SC_CURRENT_USER_MODULE::test_cthread),
    this,
    0);
  /// this->sensitive.operator()(test_cthread_handle, clkgen.posedge_event());   /// Error 
  sc_sensitive::make_static_sensitivity(test_cthread_handle,clkgen.posedge_event());  /// OK
};

This looks to me as inconvenience without a good reason. 

Share this post


Link to post
Share on other sites

For your particular use case, you can just pass in the clock signal directly:

  SC_CTHREAD(test_cthread, clkgen); // posedge by default for CTHREADs

If you need a negedge triggered process, you can also write the equivalent SC_THREAD instead:

  SC_THREAD(test_cthread);
    sensitive << clkgen.negedge_event();
    dont_initialize();

Allowing plain events for CTHREAD sensitivity was probably just never needed. 

Share this post


Link to post
Share on other sites

The only use I see for SC_CTHREAD is synthesis tools, and this is really just a legacy issue and a vendor tools issue. The same SC_THREAD could have been used for posedge_event. This would change the coding of wait in your code though:

wait(5); // 5 clock delay

becomes

for(int i=5; i--;) wait();// prior to C++17

which could easily be addressed with:

void nWait(size_t n) { while(n--) wait(); }

and allows

nWait(5);

 

Share this post


Link to post
Share on other sites
4 hours ago, David Black said:

The only use I see for SC_CTHREAD is synthesis tools, and this is really just a legacy issue and a vendor tools issue.

There is a difference: in SC_CTHREADs you can't wait on event. Since this would not be synthesizable.

sc_clock    clk{"clk", 1, SC_NS};

SC_CTOR(test) {
  SC_THREAD(test_thread);
  sensitive << clk.posedge_event();

  SC_CTHREAD(test_cthread, clk);
}

void test_thread() {
  wait(clk.negedge_event()); // OK
}

void test_cthread() {
  wait(clk.negedge_event()); // RUNTIME ERROR
}

So I always use SC_CTHREADs in synthesizable code, to specify my intent and prevent accidental calls to non-synthesizable methods with wait(event).

23 hours ago, Philipp A Hartmann said:

  SC_CTHREAD(test_cthread, clkgen); // posedge by default for CTHREADs

Indeed, did not know about it. This works for me. In my practice I did not yet encountered a case where I need to create a CTHREAD sensitive to negedge.

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

×