ARI Posted January 22, 2022 Report Posted January 22, 2022 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: 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 Quote
Andy Goodrich Posted January 22, 2022 Report Posted January 22, 2022 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? ARI 1 Quote
Andy Goodrich Posted January 22, 2022 Report Posted January 22, 2022 With the event list consisting of reset and a clock edge. Quote
karthickg Posted January 23, 2022 Report Posted January 23, 2022 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. 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); } ARI 1 Quote
David Black Posted January 23, 2022 Report Posted January 23, 2022 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). ARI 1 Quote
karthickg Posted January 23, 2022 Report Posted January 23, 2022 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! ARI 1 Quote
ARI Posted January 23, 2022 Author Report Posted January 23, 2022 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. 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. Quote
ARI Posted January 23, 2022 Author Report Posted January 23, 2022 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. Quote
Recommended Posts
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.