Jump to content

FSM implementation in SystemC using SC_METHOD and next_trigger


ARI

Recommended Posts

Hello Everyone,

I was trying to implement FSM in SystemC using SC_METHOD and next_trigger(). 
In the requirement it is mentioned i can't use SC_THREAD and static sensitivity (except reset_input). 
I am facing one problem here, which mentioned in screen-shot.

In the attached screen-shot, whenever the current_state is FIRST then next_state could be SECOND, THIRED, and FOURTH
(the priority of next_state is SECOND > THIRED > FOURTH). I am able to write a code using next_trigger when next_state is only one and not many.

Here is the raw code:

 

main_fsm_acellera_que.thumb.PNG.7e3f947f29d9ace6322d7eee52d1157f.PNG

sc_in<bool> Reset_in; 
sc_in<bool> First_in ;
sc_in<bool> Common_in;
sc_in<bool> Second_in;
sc_in<bool> Third_In;
sc_in<bool> Fourth_in;


  SC_METHOD(FSMMethod)
  sensitive << Reset_in;
  async_reset_signal_is(Reset_in, false);
  dont_initialize();

  void FSMMethod()
  {
    if (Reset_in == false)
	{
        current_state = RESET;
         next_trigger();
    }

    else
    {
    	switch (current_state)
        { 
           case RESET:
                next_state = FIRST;
                next_trigger(First_in.posedge_event()); // now you can see when FSM is in RESET state then if First_in signal value become one 
                                                     //then FSM method will call again due to next_trigger and that time the next_state would be FIRST.
                break;

           case FIRST:  // I am stuck here, if Common_in and Second_in signal true then next_state should be SECOND but the problem 
                        // is during the execution it will go inside the if block, if block not executed then next_trigger condtion 
                        // will not trigger the sc_method again and FSM will not in next_state.
                if (Common_in && Second_in)
                {
                    next_state = SECOND;
                    next_trigger(Common_in.value_changed_event() & Second_in.value_changed_event());
                }
                else if (Common_in && Third_in)
                {
                     next_state = THIRD;
                     next_trigger(Common_in.value_changed_event() & Third_in.value_changed_event());
                }
                else if (Common_in && Fourth_in)
                {
                     next_state = FOURTH;
                     next_trigger(Common_in.value_changed_event() & Fourth_in.value_changed_event());
                }
                break

            }
           current_state = next_state;
      }
}

Hope i am able to put my question but if you guys need more clarification then please let me know.
ultimatly i am not able to call FSMMethod beacuse next_trigger not executed in FIRST state, 
first we to have evalaute the transition condition then only next_trigger will execute.
if in FIRST state if next_state were only one then it would be easy to use 
next_trigger (just in case we used in RESET to FIEST state)
  
Please give me your valauble suggestions so it help to implement this FSM design.
  
Thanks and Regards,
ARI

 

Link to comment
Share on other sites

The code snippet you provided is incomplete, you should have cases for each state, and regardless of how you run through the FSMMethod routine you need to always execute a next_trigger or your method will be orphaned. Why can't you use an SC_CTHREAD for the implementation, what is the rationale for not having a static event list?

Link to comment
Share on other sites

The basic problem in your code is that you are checking the value of the ports Common_in / First_in etc too early. This fragment shows the problem:
 

                if (Common_in && Second_in)
                {
                    next_state = SECOND;
                    next_trigger(Common_in.value_changed_event() & Second_in.value_changed_event());
                }

 

The "if (Common_in && Second_in)" should be checked after the port values are asserted. I would suggest you implement a more basic state machine - like the one here.

image.png.b411fee8735e28186ddfeb4e8e8ce198.png

Here is a sketch (note the case where both Second_in and Third_in are together asserted will cause the switch to "SECOND" in implementation below):

 

void fsm_method()
{
   bool done = true;
   do {
      switch(current_state) {
         case RESET:
            next_state = FIRST;
            next_trigger(First_in.posedge_event());
            break;
         case FIRST:
            if(Second_in == 1) {
               next_state = SECOND;
               done = false; // Move the state immediately
               break;
            } else if (Third_in == 1) {
               next_state = THIRD;
               done = false; // Move the state immediately
            } else {
               next_state = FIRST;
               next_trigger(Second_in.posedge_event() | Third_in.posedge_event());
            }
            break;
         case SECOND:
            // ...
            break;
         case THIRD:
            // ...
            break;
      }
      current_state = next_state;
   } while(done == false);
}

 

Link to comment
Share on other sites

21 hours ago, Andy Goodrich said:

The code snippet you provided is incomplete, you should have cases for each state, and regardless of how you run through the FSMMethod routine you need to always execute a next_trigger or your method will be orphaned. Why can't you use an SC_CTHREAD for the implementation, what is the rationale for not having a static event list?

Likely because it is a school assignment or possibly because they are using a tool that cannot synthesize threads.

Hopefully, not because somebody told them that SC_METHODs are faster than SC_THREADs. That depends heavily upon the implementation of SystemC itself. I know of cases where it is the other way around (SC_THREAD is faster than SC_METHOD).

Link to comment
Share on other sites

31 minutes ago, David Black said:

Hopefully, not because somebody told them that SC_METHODs are faster than SC_THREADs. That depends heavily upon the implementation of SystemC itself. I know of cases where it is the other way around (SC_THREAD is faster than SC_METHOD).

I agree with you. Anecdotally -  I have checked the performance of SC_THREAD vs SC_METHOD with a very synthetic workload (heavily biased towards context switches) and did see that SC_METHOD was faster than SC_THREAD on the Accellera reference simulator. However, on a real simulation, the useful compute operations will dominate, so gains would be marginal.

That said, can you give an intuition on how SC_THREAD can be faster than SC_METHOD? Thanks!

Link to comment
Share on other sites

9 hours ago, karthickg said:

The basic problem in your code is that you are checking the value of the ports Common_in / First_in etc too early. This fragment shows the problem:
 

                if (Common_in && Second_in)
                {
                    next_state = SECOND;
                    next_trigger(Common_in.value_changed_event() & Second_in.value_changed_event());
                }

 

The "if (Common_in && Second_in)" should be checked after the port values are asserted. I would suggest you implement a more basic state machine - like the one here.

image.png.b411fee8735e28186ddfeb4e8e8ce198.png

Here is a sketch (note the case where both Second_in and Third_in are together asserted will cause the switch to "SECOND" in implementation below):

 

void fsm_method()
{
   bool done = true;
   do {
      switch(current_state) {
         case RESET:
            next_state = FIRST;
            next_trigger(First_in.posedge_event());
            break;
         case FIRST:
            if(Second_in == 1) {
               next_state = SECOND;
               done = false; // Move the state immediately
               break;
            } else if (Third_in == 1) {
               next_state = THIRD;
               done = false; // Move the state immediately
            } else {
               next_state = FIRST;
               next_trigger(Second_in.posedge_event() | Third_in.posedge_event());
            }
            break;
         case SECOND:
            // ...
            break;
         case THIRD:
            // ...
            break;
      }
      current_state = next_state;
   } while(done == false);
}

 

Thanks @karthickg for your reply and valuable suggestion, it really help me a lot.

Link to comment
Share on other sites

22 hours ago, Andy Goodrich said:

The code snippet you provided is incomplete, you should have cases for each state, and regardless of how you run through the FSMMethod routine you need to always execute a next_trigger or your method will be orphaned. Why can't you use an SC_CTHREAD for the implementation, what is the rationale for not having a static event list?

Hi @Andy Goodrich Thanks for your reply, why I am not using SC_CTHREAD, the reason behind it, I don't want the FSMMethod call again and again at every posedge of clock. In SystemC we generally design a model at higher abstraction, if we use clock then simulation would be slow, that's why I have to prefer next_trigger.

Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...