SinelaboreRT Header Logo

SinelaboreRT

It's better when it's simple!

User Tools

Site Tools


wiki:backends:cpp_lang

Generating C++ Code

Since version 1.5 sinelabore supports the generation of C++ code. C++ offers many features that should be used with care in embedded systems. Therefore, the code generator uses only a very small subset of C++ by default. In fact, only classes, public/protected/private member variables and methods are used. More modern features such as virtual functions, templates, etc. are only used if they are enabled. With the various parameters, the generated code can be very flexibly adapted to one's own needs. Some of the new parameters require a compiler that supports at least the 2011 C++ standard (e.g. –std=c++11 for g++ or clang++).

To generate C++ code call the code generator with the command line flag ’-l cppx’.

The generated code does not follow the state pattern as you might expect (if you are familiar with common design patterns). The reason is that the machine code is completely generated and no hand-coding is involved. The following class diagram shows the structure of the generated classes. Class diagram that shows the structure of the generated classes.

The code generator supports code generation from models with regions. A region is an orthogonal part of a state. Regions allow to express parallelism within a state. A state can have two or more regions. Region contains states and transitions. To add a region in astah* right click to a state and select Add region from the context menu.

An example state diagram with regions is shown below. Imagine how much effort it would be to manually write the code for this machine. And even worse how difficult it would be to maintain it over time when new states/events are added.

Available parameters and options:

  • Basic signature:
    int processEvent(const TESTCASE_EVENT_T msg);
  • Using a template parameter that allows elegant and flexible parameter handover:
    template <typename T> 
    int processEvent(const TESTCASE_EVENT_T msg, const T& userdata);
  • Without any parameter:
    int processEvent(void);
  • Command line parameter -Trace enables trace code generation

All details about the C++ backend are available in section “Generating C++ Code” of the manual.

Example code that generated from a state diagram as shown above:

  1. /* Command line options: -v -p CADIFRA -l cppx -o testcase testcase.cdd */
  2. /* This file is generated from testcase.cdd - do not edit manually */
  3. /* Generated on: Thu Feb 13 19:50:07 CET 2020 / version 4.1 */
  4.  
  5.  
  6. #include "testcase.h"
  7. #include "testcase_ext.h"
  8. #include <stdio.h>
  9.  
  10. extern unsigned char msg;
  11. extern unsigned char condition;
  12.  
  13. namespace simulator {
  14.  
  15. testcase::testcase(void)
  16. {
  17. m_initialized=static_cast<int>(0U);
  18. }
  19.  
  20.  
  21.  
  22. /* State names */
  23. const char states[]=
  24. "S3\0S2\0S21\0S22\0S11\0S1\0S12\0";
  25.  
  26. const unsigned short state_idx[]={
  27. 0,3,6,10,14,18,21,25};
  28.  
  29. /* Event names */
  30. const char events[]=
  31. "evA\0NO_MSG\0";
  32.  
  33. const unsigned short evt_idx[]={
  34. 0,4};
  35.  
  36. const char* testcase::getNameByState(const unsigned short state) const {
  37. return states+state_idx[state];
  38. }
  39.  
  40. const char* testcase::getNameByEvent(const TESTCASE_EVENT_T evt) const {
  41. return events+evt_idx[evt];
  42. }
  43.  
  44.  
  45. // Helper(s) to reset history
  46. void testcase::resetHistoryS1(void){
  47. stateVars.stateVarS1=S11;
  48. }
  49.  
  50. void testcase::resetHistoryS2(void){
  51. stateVars.stateVarS2=S21;
  52. }
  53.  
  54.  
  55. // Helper(s) to find out if the machine is in a certain state
  56.  
  57. bool testcase::isInS3(void) const {return(((stateVars.stateVar== S3)) ? (true) : (false));}
  58. bool testcase::isInS2(void) const {return(((stateVars.stateVar== S2)) ? (true) : (false));}
  59. bool testcase::isInS21(void) const {return(((stateVars.stateVarS2== S21)&&(stateVars.stateVar== S2)) ? (true) : (false));}
  60. bool testcase::isInS22(void) const {return(((stateVars.stateVarS2== S22)&&(stateVars.stateVar== S2)) ? (true) : (false));}
  61. bool testcase::isInS11(void) const {return(((stateVars.stateVarS1== S11)&&(stateVars.stateVar== S1)) ? (true) : (false));}
  62. bool testcase::isInS1(void) const {return(((stateVars.stateVar== S1)) ? (true) : (false));}
  63. bool testcase::isInS12(void) const {return(((stateVars.stateVarS1== S12)&&(stateVars.stateVar== S1)) ? (true) : (false));}
  64.  
  65. // Helper to get id of innermost active state
  66.  
  67. testcase::States testcase::getInnermostActiveState(void) const {
  68.  
  69. testcase::States state = NUM_STATES;
  70.  
  71. if(isInS12()){
  72. state = S12;
  73. }else if(isInS11()){
  74. state = S11;
  75. }else if(isInS22()){
  76. state = S22;
  77. }else if(isInS21()){
  78. state = S21;
  79. }else if(isInS3()){
  80. state = S3;
  81. }else{
  82. // intentionally left blank
  83. }
  84. return state;
  85. }
  86.  
  87. // Initialize method. Must be called once to init the machine
  88. void testcase::initialize(){
  89. //call on entry code of default states
  90. if(m_initialized==static_cast<int>(0U)){
  91. m_initialized=static_cast<int>(1U);
  92.  
  93. //Create copy of statevar
  94. stateVarsCopy = stateVars;
  95.  
  96. // Set state vars to default states
  97.  
  98. stateVarsCopy.stateVar = S1; /* set init state of top state */
  99. stateVarsCopy.stateVarS1 = S11; /* set init state of S1 */
  100. stateVarsCopy.stateVarS2 = S21; /* set init state of S2 */
  101.  
  102.  
  103.  
  104. printf("S1 Entry\n");
  105.  
  106. printf("OnEntryS11\n");
  107.  
  108.  
  109. // Copy state variables back
  110. stateVars = stateVarsCopy;
  111.  
  112. }
  113.  
  114. }
  115.  
  116.  
  117. // State machine event handler
  118. int testcase::processEvent(const TESTCASE_EVENT_T msg){
  119.  
  120. int evConsumed = 0U;
  121.  
  122.  
  123.  
  124. if(m_initialized==static_cast<int>(0U)){
  125. return static_cast<int>(0);
  126. }
  127.  
  128. //Create copy of statevar
  129. stateVarsCopy = stateVars;
  130.  
  131. /* action code */
  132. printf("Outer test action\n");
  133.  
  134.  
  135. switch (stateVars.stateVar) {
  136.  
  137. case S1:
  138.  
  139. switch (stateVars.stateVarS1) {
  140.  
  141. case S11:
  142. /* action code */
  143. printf("Action S11\n");
  144.  
  145.  
  146. if(msg==evA){
  147. /* Transition from S11 to S3 */
  148. evConsumed=1U;
  149. /* OnExit code of state S11 */
  150. printf("OnExit S11\n");
  151.  
  152. /* OnExit code of state S1 */
  153. printf("S1 Exit\n");
  154.  
  155. /* Action code for transition */
  156. printf("evA\n");
  157.  
  158. /* OnEntry code of state S3 */
  159. printf("OnEntryS3\n");
  160.  
  161. /* adjust state variables */
  162. stateVarsCopy.stateVar = S3;
  163. stateVarsCopy.stateVarS1 = S11;
  164. }else{
  165. /* Intentionally left blank */
  166. } /*end of event selection */
  167. break; /* end of case S11 */
  168.  
  169. case S12:
  170. break; /* end of case S12 */
  171.  
  172. default:
  173. /* Intentionally left blank */
  174. break;
  175. } /* end switch S1 */
  176. break; /* end of case S1 */
  177.  
  178. case S3:
  179. /* action code */
  180. printf("Action S3\n");
  181.  
  182.  
  183. if(condition==1){
  184. /* Transition from S3 to S11 */
  185. evConsumed=16U;
  186. /* OnExit code of state S3 */
  187. printf("OnExit S3\n");
  188.  
  189. /* Action code for transition */
  190. printf("condition==1\n");
  191.  
  192. /* OnEntry code of state S1 */
  193. printf("S1 Entry\n");
  194.  
  195. /* OnEntry code of state S11 */
  196. printf("OnEntryS11\n");
  197.  
  198. /* adjust state variables */
  199. stateVarsCopy.stateVar = S1;
  200. stateVarsCopy.stateVarS1 = S11;
  201. }else{
  202. /* Intentionally left blank */
  203. } /*end of event selection */
  204. break; /* end of case S3 */
  205.  
  206. case S2:
  207.  
  208. switch (stateVars.stateVarS2) {
  209.  
  210. case S21:
  211. break; /* end of case S21 */
  212.  
  213. case S22:
  214. break; /* end of case S22 */
  215.  
  216. default:
  217. /* Intentionally left blank */
  218. break;
  219. } /* end switch S2 */
  220. break; /* end of case S2 */
  221.  
  222. default:
  223. /* Intentionally left blank */
  224. break;
  225. } /* end switch stateVar_root */
  226. // Copy state variables back
  227. stateVars = stateVarsCopy;
  228.  
  229. return evConsumed;
  230. } // end processEvent
  231.  
  232.  
  233.  
  234.  
  235.  
  236.  
  237.  
  238. } //namespace simulator
This website uses cookies. By using the website, you agree with storing cookies on your computer. Also you acknowledge that you have read and understand our Privacy Policy. If you do not agree leave the website.More information about cookies
wiki/backends/cpp_lang.txt · Last modified: 2022/02/16 20:46 by pmueller

Donate Powered by PHP Valid HTML5 Valid CSS Driven by DokuWiki