Jump to content
KEVIN CHACKO

How can I implement SC_FORK JOIN_ANY /SC_FORK JOIN_NONE

Recommended Posts

Read up on sc_spawn and sc_process_handle. Basically, you can do something like:

// Example of fork-join any
std::vector<sc_process_handle> process_handles;
process_handles.push_back( sc_spawn( [&](){ ... } ); //< repeat as needed
...
sc_event_or_list terminated_events;
for( auto& ph : process_handles ) {
    terminated_events |= ph.terminated_event();
}
wait( terminated_events ); //< wait for any process to exit
for( auto& ph : process_handles ) {
  ph.kill();
}
// Example of fork-join none
(void)spawn( [&](){ ... } ); //< repeat as needed
...

 

Share this post


Link to post
Share on other sites

Thank your for the help.

But when I try implementing the fork_join any solution, I get this error

invalid use of sc_(and|or)_event_list: list prematurely destroyed

I am using the fork join any in a run phase process of a uvm systemc driver. This issue is reported specifically for 40th agent i am running out of 65 agents. 

Is it because the size of the process handles or the terminated_event list getting exhausted

 

 

Share this post


Link to post
Share on other sites
2 hours ago, KEVIN CHACKO said:

But when I try implementing the fork_join any solution, I get this error

invalid use of sc_(and|or)_event_list: list prematurely destroyed

This is interesting, comment in source code says that it reports this error when event_list is destroyed, but some process is still waiting for it.

Can you provide a small reproducer (complete code example) showing how you use it?

Share this post


Link to post
Share on other sites

Sure

The code is fine for SC_JOIN all and SC_JOIN NONE implementation. And apparently this issue is there for every uvm_component I instantiate.

#include<systemc.h>
#include<uvm>

template <int TOP_DEPTH=10>
class top: public uvm::uvm_component{
public:


       void fun1() {
         cout<<"Current time is "<< sc_time_stamp() << endl;
     cout<< " =========== fun1========" << endl;
         wait(30,SC_NS);
         cout<<"Current time is "<< sc_time_stamp() << endl;
       }

       void fun2() {
         cout<<"Current time is "<< sc_time_stamp() << endl;
        cout<< " =========== fun2========" << endl;
       wait(20,SC_NS);
         cout<<"Current time is "<< sc_time_stamp() << endl;
       }

   void run_phase(uvm::uvm_phase& phase) {
     
             cout<< " run: before fork/join" << endl;

         /*SC_FORK
                         sc_spawn(sc_bind(&top::fun1, this)),
                         sc_spawn(sc_bind(&top::fun2, this))
             SC_JOIN*/

         /*void(sc_spawn(sc_bind(&top::fun1, this)));
           void(sc_spawn(sc_bind(&top::fun2, this)));*/


 

    
     std::vector<sc_process_handle> process_handles;
     process_handles.push_back(sc_spawn(sc_bind(&top::fun1, this)) );
     process_handles.push_back(sc_spawn(sc_bind(&top::fun2, this)) );
     sc_event_or_list terminated_events;
     for(std::vector<sc_process_handle>::iterator it = process_handles.begin(); it != process_handles.end(); ++it) {
       terminated_events |= (*it).terminated_event();
     }
     wait( terminated_events ); //< wait for any process to exit
     for(std::vector<sc_process_handle>::iterator it = process_handles.begin(); it != process_handles.end(); ++it) {
       (*it).kill();
       }


                 cout << "run: after fork/join" << endl;
                wait(40,SC_NS);
                cout<<"Current time is "<< sc_time_stamp() << endl;
        }


 top (uvm::uvm_component_name name="top") : uvm::uvm_component( name ) {

     }

};

 

int sc_main(int argc, char **argv) {

       top<15>* top_1;

       top_1 = new top<15>("top_1");


       uvm::run_test("");

      return 0;

}
 

Share this post


Link to post
Share on other sites

Ok, thanks a lot for example. 

I'm not using UVM myself and have no idea what it does. But it looks like UVM does not allow you to call wait() inside run_phase, because it terminates the thread immediately.

If you rewrite your code this way:

    void run_phase(uvm::uvm_phase& phase) {

        cout<< " run: before fork/join" << endl;
      
        //

        cout << "run: after fork/join" << endl;
        wait(40,SC_NS);
        cout<<"Current time is "<< sc_time_stamp() << endl;
    }

You will see that "Current time is.." won't get printed.  

And because thread is terminated,  event_list got destroyed and you see the error you see.

From my perspective it is UVM-SystemC bug, it should prevent you from calling wait() from run_phase, by reporting something like "wait() is not allowed inside run_phase". 

I suggest you to post the issue to UVM SystemC support forum (http://forums.accellera.org/forum/38-systemc-verification-uvm-systemc-scv/) and see if anyone of UVM-SystemC developers can help/comment.

 

If you put your code in a regular SC_THREAD you will see that everything works as expected .

 

 

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

×