Sinelabore Homepage

Generate production quality code from state diagrams created with Enterprise Architect#

SinelaboreRT generates readable and maintainable code from hierarchical UML state machines created with Enterprise Architect. With its C/C++ backend it is well suited for embedded real-time and low-power applications. With support for code generation in additional widely used programming languages, it is also well suited for backend and IoT software.

General Code Generator Features#

  • Automated robustness checks before code generation
  • No runtime environment needed
  • Works with any CPU and with/without OS or RTOS
  • Focus on embedded real-time and high-availability systems
  • Fits foreground/background and RTOS-based designs
  • No gap between design and code
  • Support for automatic test-case generation
  • Interactive and batch simulation
  • Optional trace code generation
  • Generated code works well with static code checkers

Supported State Machine Elements#

A rich set of state machine features is available to model complex behavior:

  • Hierarchical states with initial and final pseudo states aw well as deep and shallow history.
  • Signal events with event name, guard and action
  • Conditional events (boolean triggers)
  • Choices and junctions
  • Constraints
  • Submachine states on multiple levels
  • Entry and exit pseudo states
  • Regions on multiple levels

These are the general modeling and code generation capabilities. The next section shows how to apply them with Enterprise Architect.

Using Enterprise Architect#

The following example shows how the code generator workflow works with Enterprise Architect using a simple microwave oven.

Microwave oven with requirements

Requirements#

  1. Cooking time can be adjusted from 0 s to 60 s.
  2. Cooking starts if the cooking time is > 0s and the door is closed.
  3. If the door is opened during cooking, the microwave generator is switched off and the cooking time stops.
  4. Cooking continues if the cooking time is not over and the door is closed again.
  5. Cooking stops if the cooking time is over or the time is adjusted to zero.
  6. Cooking time and power can be changed at any time.
  7. The state machine below shows a possible solution.

The basis is a class model that contains the oven class with the state machine. The class can contain attributes and methods which are added to the generated code.

Adding attributes and operations in Enterprise Architect

The key point is that the state machine for the microwave oven looks as follows:

State machine of a simple microwave oven

To generate C code, export your model to XMI and call the code generator as follows. With -t you can specify which class to generate code from. The path must match the path to the class in your model.

java -jar codegen.jar -p EA -t "Model:View:testclass" -o oven oven.xml

After model validation (for example duplicate-state checks), full state machine code is generated.

The following generated files provide a concrete example of the resulting code structure and API.

oven.c
/*
 * (c) Sinelabore Software Tools GmbH, 2026
 *
 * All rights reserved. Reproduction, modification,
 * use or disclosure to third parties without express
 * authority is forbidden.
 */

/* Command line options: -p EA -t Model:Class Model:first_example_step3 -o oven first_example_step3.xml   */
/* This file is generated from first_example_step3.xml - do not edit manually  */
/* Generated on: Wed Oct 05 20:37:16 CEST 2011 / version 2.5 */


#include "mydefs.h"
#include "oven.h"
#include "oven_ext.h"
#include "oven_hlp.h"
#include <stdio.h>

extern unsigned char msg;
extern T_PWR pwr;

void  oven(OVEN_INSTANCEDATA_T *instanceVar){

	OVEN_EV_CONSUMED_FLAG_T evConsumed = 0U;

	
	/*execute entry code of default state once to init machine */
	if(instanceVar->superEntry==1U){
		ovenOff();

		instanceVar->superEntry=0U;
	}

	/* action code */
	/* just a comment */


	switch (instanceVar->stateVar) {

		case Super:

			switch (instanceVar->stateVarSuper) {

				case Completed:
					if(msg==(OVEN_EVENT_T)evDoorOpen){
						/* Transition from Completed to Idle */
						evConsumed=1U;

						/* OnEntry code of state Idle */
						ovenOff();

						/* adjust state variables  */
						instanceVar->stateVarSuper = Idle;
					}else{
						/* Intentionally left blank */
					} /*end of event selection */
				break; /* end of case Completed  */

				case Cooking:
					if(msg==(OVEN_EVENT_T)evDoorOpen){
						/* Transition from Cooking to CookingPause */
						evConsumed=1U;

						/* Action code for transition  */
						ovenOff();
						timer_pause();


						/* adjust state variables  */
						instanceVar->stateVarSuper = CookingPause;
					}else if(msg==(OVEN_EVENT_T)evTimeout){
						/* Transition from Cooking to Completed */
						evConsumed=1U;

						/* Action code for transition  */
						ovenOff();
						timer_clear();


						/* adjust state variables  */
						instanceVar->stateVarSuper = Completed;
					}else{
						/* Intentionally left blank */
					} /*end of event selection */
				break; /* end of case Cooking  */

				case CookingPause:
					if(msg==(OVEN_EVENT_T)evDoorClosed){
						/* Transition from CookingPause to Cooking */
						evConsumed=1U;

						/* Action code for transition  */
						timer_cont();

						/* OnEntry code of state Cooking */
						ovenOn();

						/* adjust state variables  */
						instanceVar->stateVarSuper = Cooking;
					}else{
						/* Intentionally left blank */
					} /*end of event selection */
				break; /* end of case CookingPause  */

				case Idle:
					if(msg==(OVEN_EVENT_T)evDoorClosed){
						if(timer_preset()>0){
							/* Transition from Idle to Cooking */
							evConsumed=1U;

							/* Action code for transition  */
							timer_start();

							/* OnEntry code of state Cooking */
							ovenOn();

							/* adjust state variables  */
							instanceVar->stateVarSuper = Cooking;
						}else{
							/* Intentionally left blank */
						} /*end of event selection */
					}else{
						/* Intentionally left blank */
					} /*end of event selection */
				break; /* end of case Idle  */

				default:
					/* Intentionally left blank */
				break;
			} /* end switch Super */

		/* Check if event was already processed  */
		if(evConsumed==0U){

			if(msg==(OVEN_EVENT_T)evDec){
				/* Transition from Super to Super */
				evConsumed=1U;
				
				if(instanceVar->stateVarSuper==Completed){
					

				}else if(instanceVar->stateVarSuper==Cooking){
					

				}else if(instanceVar->stateVarSuper==CookingPause){
					

				}else if(instanceVar->stateVarSuper==Idle){
					
				}

				/* Action code for transition  */
				timer_dec();

				instanceVar->stateVar = Super;/* entry chain  */
				if(instanceVar->stateVarSuper==Completed){
					
				}else if(instanceVar->stateVarSuper==Cooking){
					ovenOn();

				}else if(instanceVar->stateVarSuper==CookingPause){
					
				}else if(instanceVar->stateVarSuper==Idle){
					ovenOff();

				}

			}else if(msg==(OVEN_EVENT_T)evInc){
				/* Transition from Super to Super */
				evConsumed=1U;
				
				if(instanceVar->stateVarSuper==Completed){
					

				}else if(instanceVar->stateVarSuper==Cooking){
					

				}else if(instanceVar->stateVarSuper==CookingPause){
					

				}else if(instanceVar->stateVarSuper==Idle){
					
				}

				/* Action code for transition  */
				timer_inc();

				instanceVar->stateVar = Super;/* entry chain  */
				if(instanceVar->stateVarSuper==Completed){
					
				}else if(instanceVar->stateVarSuper==Cooking){
					ovenOn();

				}else if(instanceVar->stateVarSuper==CookingPause){
					
				}else if(instanceVar->stateVarSuper==Idle){
					ovenOff();

				}

			}else if(msg==(OVEN_EVENT_T)evPwr){
				/* Transition from Super to Super */
				evConsumed=1U;
				
				if(instanceVar->stateVarSuper==Completed){
					

				}else if(instanceVar->stateVarSuper==Cooking){
					

				}else if(instanceVar->stateVarSuper==CookingPause){
					

				}else if(instanceVar->stateVarSuper==Idle){
					
				}

				/* Action code for transition  */
				ovenSetPwr(pwr);

				instanceVar->stateVar = Super;/* entry chain  */
				if(instanceVar->stateVarSuper==Completed){
					
				}else if(instanceVar->stateVarSuper==Cooking){
					ovenOn();

				}else if(instanceVar->stateVarSuper==CookingPause){
					
				}else if(instanceVar->stateVarSuper==Idle){
					ovenOff();

				}

			}else{
				/* Intentionally left blank */
			} /*end of event selection */
		}
		break; /* end of case Super  */

		default:
			/* Intentionally left blank */
		break;
	} /* end switch stateVar_root */
}

/* Implementation of the reset machine function */
void ovenResetMachine(OVEN_INSTANCEDATA_T *instanceVar){
	instanceVar->superEntry = 1U;
	instanceVar->stateVar = Super;
	instanceVar->stateVarSuper = Idle;

}
// Helper(s) to reset history
void ovenResetHistorySuper(OVEN_INSTANCEDATA_T *instanceVar){
	instanceVar->stateVarSuper=Idle;
}


// Helper(s) to find out if the machine is in a certain state

uint8_t ovenIsInSuper(OVEN_INSTANCEDATA_T *instanceVar){
	return(((instanceVar->stateVar== Super)) ? (1U) : (0U));
}

uint8_t ovenIsInIdle(OVEN_INSTANCEDATA_T *instanceVar){
	return(((instanceVar->stateVarSuper== Idle)&&(instanceVar->stateVar== Super)) ? (1U) : (0U));
}

uint8_t ovenIsInCompleted(OVEN_INSTANCEDATA_T *instanceVar){
	return(((instanceVar->stateVarSuper== Completed)&&(instanceVar->stateVar== Super)) ? (1U) : (0U));
}

uint8_t ovenIsInCookingPause(OVEN_INSTANCEDATA_T *instanceVar){
	return(((instanceVar->stateVarSuper== CookingPause)&&(instanceVar->stateVar== Super)) ? (1U) : (0U));
}

uint8_t ovenIsInCooking(OVEN_INSTANCEDATA_T *instanceVar){
	return(((instanceVar->stateVarSuper== Cooking)&&(instanceVar->stateVar== Super)) ? (1U) : (0U));
}
oven.h
/*
 * (c) Sinelabore Software Tools GmbH, 2026
 *
 * All rights reserved. Reproduction, modification,
 * use or disclosure to third parties without express
 * authority is forbidden.
 */

/* Command line options: -p EA -t Model:Class Model:first_example_step3 -o oven first_example_step3.xml   */
/* This file is generated from oven.h - do not edit manually*/
/* Generated on: Wed Oct 05 20:37:16 CEST 2011 / version 2.5 */


#ifndef __OVEN_H__
#define __OVEN_H__


/* Header to define simple data types */
#include <stdint.h>

/* State definitions */
typedef enum{
	Super,
	Idle,
	Completed,
	CookingPause,
	Cooking,
	__OVEN_LAST_STATE__} OVEN_STATES_T;






/* Predefined types required by the codegen. You can provide your own  */
/* definitions by setting the following define somewhere in your built env. */
#ifndef __PROVIDE_OWN_OVEN_STATEMACHINE_TYPES__
	typedef uint8_t OVEN_ENTRY_FLAG_T;
	typedef OVEN_STATES_T OVEN_STATEVAR_T;
	typedef uint8_t OVEN_INST_ID_T;
	typedef uint8_t OVEN_EV_CONSUMED_FLAG_T;
#endif




/* Instance data definition of state machine */
typedef struct{
	OVEN_ENTRY_FLAG_T superEntry;
	OVEN_STATEVAR_T stateVar;
	OVEN_STATEVAR_T stateVarSuper;
	OVEN_INST_ID_T inst_id;
} OVEN_INSTANCEDATA_T;

/* Helper to initialize the machine's instance data */
#define OVEN_INSTANCEDATA_INIT {\
	1,\
	(OVEN_STATEVAR_T) Super /* set init state of top state */,\
	(OVEN_STATEVAR_T) Idle /* set init state of Super */,\
	0 /* instance id */ } 

/* Helper(s) to reset history */
#define OVEN_RESET_HISTORY_SUPER(instance) ((&instance)->stateVarSuper=Idle)

/*Prototype of the state machine function */
void  oven(OVEN_INSTANCEDATA_T *instanceVar);


/*Prototoye of the reset machine function */
void ovenResetMachine(OVEN_INSTANCEDATA_T *instanceVar);

// Helper(s) to reset history
void ovenResetHistorySuper(OVEN_INSTANCEDATA_T *instanceVar);

// Helper(s) to find out if the machine is in a certain state
uint8_t ovenIsInSuper(OVEN_INSTANCEDATA_T *instanceVar);
uint8_t ovenIsInIdle(OVEN_INSTANCEDATA_T *instanceVar);
uint8_t ovenIsInCompleted(OVEN_INSTANCEDATA_T *instanceVar);
uint8_t ovenIsInCookingPause(OVEN_INSTANCEDATA_T *instanceVar);
uint8_t ovenIsInCooking(OVEN_INSTANCEDATA_T *instanceVar);


/* Macros to test if the machine is in a certain state. */
#define OVEN_IS_IN_SUPER(instance)((((&instance)->stateVar==Super)) ? (1U) : (0U))
#define OVEN_IS_IN_IDLE(instance)((((&instance)->stateVarSuper==Idle)&&((&instance)->stateVar==Super)) ? (1U) : (0U))
#define OVEN_IS_IN_COMPLETED(instance)((((&instance)->stateVarSuper==Completed)&&((&instance)->stateVar==Super)) ? (1U) : (0U))
#define OVEN_IS_IN_COOKINGPAUSE(instance)((((&instance)->stateVarSuper==CookingPause)&&((&instance)->stateVar==Super)) ? (1U) : (0U))
#define OVEN_IS_IN_COOKING(instance)((((&instance)->stateVarSuper==Cooking)&&((&instance)->stateVar==Super)) ? (1U) : (0U))

#endif
oven_ext.h
/*
 * (c) Sinelabore Software Tools GmbH, 2026
 *
 * All rights reserved. Reproduction, modification,
 * use or disclosure to third parties without express
 * authority is forbidden.
 */

/* Command line options: -p EA -t Model:Class Model:first_example_step3 -o oven first_example_step3.xml   */
/* This file is generated from first_example_step3.xml - do not edit manually */
/* Generated on: Wed Oct 05 20:37:16 CEST 2011 */


#ifndef __OVEN_EXT_H__ 
#define __OVEN_EXT_H__ 

/*Events which can be sent to the state-machine  */
typedef enum
{
	evDoorOpen=0U,
	evDec,
	evTimeout,
	evPwr,
	evDoorClosed,
	evInc,
	OVEN_NO_MSG
} OVEN_EVENT_T;


#endif

More Information#