From 0fe95079677149ca0791aa5edd7dc99c7276748b Mon Sep 17 00:00:00 2001 From: Jerome Jutteau Date: Wed, 27 Feb 2013 21:54:29 +0100 Subject: digital/ai/src/fsm: update angfsm --- digital/ai/src/fsm/angfsm_host_exec.h | 525 ++++++++++++++++++++++++++++++++++ 1 file changed, 525 insertions(+) create mode 100644 digital/ai/src/fsm/angfsm_host_exec.h (limited to 'digital/ai/src/fsm/angfsm_host_exec.h') diff --git a/digital/ai/src/fsm/angfsm_host_exec.h b/digital/ai/src/fsm/angfsm_host_exec.h new file mode 100644 index 00000000..956ef4ed --- /dev/null +++ b/digital/ai/src/fsm/angfsm_host_exec.h @@ -0,0 +1,525 @@ +/* + AngFSM - Almost Non Generated Finite State Machine + Copyright 2011, 2012 Jerome Jutteau + + This file is part of AngFSM. + + AngFSM is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + AngFSM is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with AngFSM. If not, see . + */ + +/* + You may not include this file in your code, this step is done by angfsm.h + */ + +#ifndef __HOST_EXEC__ +#define __HOST_EXEC__ + +#include +#include + +typedef enum { + ANGFSM_BUILD_ARCH_HOST, + ANGFSM_BUILD_ARCH_AVR, + ANGFSM_BUILD_ARCH_ARM, + ANGFSM_BUILD_ARCH_NB, +} angfsm_build_arch_t; + +extern const char *angfsm_build_arch_name[ANGFSM_BUILD_ARCH_NB]; + +typedef struct { + int embedded_strings; + int sanity_check; + char *gen_dot; + char *gen_code; + int print_trans; +} angfsm_build_user_options_t; + +/* Describe an event. */ +typedef struct { + /* Name of the event. */ + char *var_name; + /* Unique code of the event. */ + uint code; +} angfsm_build_event_t; + +/* Chain of events. */ +typedef struct angfsm_build_event_chain_t { + angfsm_build_event_t event; + struct angfsm_build_event_chain_t *next; +} angfsm_build_event_chain_t; + +/* Describe a state. Same as event. */ +typedef angfsm_build_event_t angfsm_build_state_t; + +/* Chain of state */ +typedef struct angfsm_build_state_chain_t { + angfsm_build_state_t state; + struct angfsm_build_state_chain_t *next; +} angfsm_build_state_chain_t; + +/** + * Describe a branch. It is the output of a transition. + * Branches can be chained when there are several possible output state for + * one event. + */ +typedef struct angfsm_build_branch_chain_t { + /* Pointer to the output state of the branch. */ + angfsm_build_state_t *state; + /* Name of the branch. */ + char *name; + /* Pointer to the next branch when we have the choice of the output */ + struct angfsm_build_branch_chain_t *next; +} angfsm_build_branch_chain_t; + +/** + * Describe a transition. + * When an event occurs, an active state may react to this event an execute a + * transition. The transition function returns the new state which become + * active. + */ +typedef struct { + /* Active state. */ + angfsm_build_state_t *state; + /* Active event. */ + angfsm_build_event_t *event; + /* Possible states the transition will return. */ + angfsm_build_branch_chain_t *output_branches; +} angfsm_build_trans_t; + +/* Chain of transitions. */ +typedef struct angfsm_build_trans_chain_t { + angfsm_build_trans_t trans; + struct angfsm_build_trans_chain_t *next; +} angfsm_build_trans_chain_t; + +/* Pointer to a transition function. */ +typedef angfsm_build_state_t* (*angfsm_build_run_strans_func_t)(void); + +/* Chain of transitions with associated function's pointer. */ +typedef struct angfsm_trans_func_chain_t { + angfsm_build_run_strans_func_t func; + angfsm_build_trans_t trans; + struct angfsm_trans_func_chain_t *next; +} angfsm_trans_func_chain_t; + +/* Timeout structure. */ +typedef struct angfsm_build_timeout_t { + uint timeout; + angfsm_build_trans_t *trans; +} angfsm_build_timeout_t; + +/* Chain of angfsm_timeout_t. */ +typedef struct angfsm_build_timeout_chain_t { + angfsm_build_timeout_t timeout; + struct angfsm_build_timeout_chain_t *next; +} angfsm_build_timeout_chain_t; + +/* Data needed for fsm execution (for host). */ +typedef struct { + /* This table store pointers of aff all transition functions. The first + * dimension correspond to the events and the second to the states. If + * there is no transition of a event/state couple, NULL is set. This + * permit to react quickly to an event during execution but is not the + * best for memory cost. + */ + angfsm_build_run_strans_func_t **trans_table; + /* Store pointer to active states. */ + angfsm_build_state_t **active_states; + /* This array has the size of active_states and store the event who has + * triggered the corresponding active state. This is used for dot + * generation for visual purposes. + */ + angfsm_build_event_t **events_before_active_state; + /* Store all pointers of transition functions. */ + angfsm_trans_func_chain_t *func_pool; + /* Array of counters for timeout events. + * -1 mean counter is off. */ + int *timeout_counters; +} angfsm_build_run_t; + +/* Store all Finite State Machine (fsm) informations. */ +typedef struct { + /* All events. */ + angfsm_build_event_chain_t *events; + /* All states. */ + angfsm_build_state_chain_t *states; + /* All transitions. */ + angfsm_build_trans_chain_t *trans; + /* Name of the fsm. */ + char *name; + /* Maximal number of active states. */ + uint max_active_states; + /* Total number of events. */ + uint event_nb; + /* Total number of states. */ + uint state_nb; + /* First active states. */ + angfsm_build_state_chain_t *starters; + /* All timeout. */ + angfsm_build_timeout_chain_t *timeouts; + /* Data for running purposes. */ + angfsm_build_run_t run; + /* User's options. */ + angfsm_build_user_options_t options; +} angfsm_build_t; + +/* Store all fsm in a chain. */ +typedef struct angfsm_build_chain_t { + angfsm_build_t *fsm; + struct angfsm_build_chain_t *next; +} angfsm_build_chain_t; + +/* Store all fsm. */ +extern angfsm_build_chain_t *fsm_build_all_fsm; +/* Function to initialize angfsm_build_all_fsm. */ +void angfsm_build_init_all_fsm() __attribute__((constructor(101))); + +/** Create the fsm and functions who will be executed before and after main + * function. This permits initilialization of the fsm. */ +extern angfsm_build_t ANGFSM_PASTE_EXPAND(angfsm_, ANGFSM_NAME); +void ANGFSM_PASTE_EXPAND(angfsm_build_init_, ANGFSM_NAME)() __attribute__((constructor(102))); +void ANGFSM_PASTE_EXPAND(angfsm_build_run_init_, ANGFSM_NAME)() __attribute__((constructor(107))); +void ANGFSM_PASTE_EXPAND(angfsm_build_free_, ANGFSM_NAME)() __attribute__((destructor)); + +#define ANGFSM_INIT \ + angfsm_build_t ANGFSM_PASTE_EXPAND (angfsm_, ANGFSM_NAME); \ + void ANGFSM_PASTE_EXPAND (angfsm_build_init_, ANGFSM_NAME)() \ + { \ + angfsm_build_init (ANGFSM_PASTE_EXPAND (&angfsm_, ANGFSM_NAME), XSTR(ANGFSM_NAME)); \ + } \ + void ANGFSM_PASTE_EXPAND (angfsm_build_run_init_, ANGFSM_NAME)() \ + { \ + angfsm_build_run_init (& ANGFSM_PASTE_EXPAND (angfsm_, ANGFSM_NAME)); \ + } \ + void ANGFSM_PASTE_EXPAND (angfsm_build_free_, ANGFSM_NAME)() \ + { \ + angfsm_build_free (& ANGFSM_PASTE_EXPAND (angfsm_, ANGFSM_NAME)); \ + } + +#define ANGFSM_IMPORT(fsm_name) \ +extern angfsm_build_t angfsm_##fsm_name; + +/** Pass options to angfsm though argc and argv. */ +#define ANGFSM_OPTIONS(argc, argv) angfsm_build_options (argc, argv) + +/** Generate source ou header files for the specific architecture */ +#define ANGFSM_GENERATE(arch, string) angfsm_build_gen (#arch, string) + +/** Immediatly handle an event by the fsm. */ +#define ANGFSM_HANDLE(fsm, event) angfsm_build_handle_string (&angfsm_##fsm , #event) + +/** Says if an event can actually be handle or not by the fsm. */ +#define ANGFSM_CAN_HANDLE(fsm, event) \ + angfsm_build_can_handle_string (&angfsm_##fsm, #event) + +/** Reset fsm to it's initial state. */ +#define ANGFSM_RESET(fsm) angfsm_build_reset (&angfsm_##fsm) + +/** Generate dot. */ +#define ANGFSM_GEN_DOT(fsm, output) angfsm_build_gen_dot (&angfsm_##fsm, output) + +/** Define states of the fsm, can be called several times to add other states. */ +#define ANGFSM_STATES(states...) \ + void ANGFSM_PASTE3_EXPAND (fsm_build_states_, ANGFSM_NAME, FIRST (states)) () \ + __attribute__((constructor(103)));\ + void ANGFSM_PASTE3_EXPAND (fsm_build_states_, ANGFSM_NAME, FIRST (states)) () \ + { \ + angfsm_build_states (& ANGFSM_PASTE_EXPAND (angfsm_, ANGFSM_NAME), #states); \ + } + +/** Define events of the fsm, can be called several times to add other events. */ +#define ANGFSM_EVENTS(events...) \ + void ANGFSM_PASTE3_EXPAND (fsm_build_events_, ANGFSM_NAME, FIRST (events)) () \ + __attribute__((constructor(103)));\ + void ANGFSM_PASTE3_EXPAND (fsm_build_events_, ANGFSM_NAME, FIRST (events)) () \ + { \ + angfsm_build_events (& ANGFSM_PASTE_EXPAND (angfsm_, ANGFSM_NAME), #events); \ + } + +/** Define wich state(s) will be active at the beginning. */ +#define ANGFSM_START_WITH(starters...) \ + void ANGFSM_PASTE3_EXPAND (fsm_build_start_with_, ANGFSM_NAME, FIRST (starters))() __attribute__((constructor(104))); \ + void ANGFSM_PASTE3_EXPAND (fsm_build_start_with_, ANGFSM_NAME, FIRST (starters))() \ + { \ + angfsm_build_start_with (& ANGFSM_PASTE_EXPAND (angfsm_, ANGFSM_NAME), #starters); \ + } + +/** + * Define a transition by giving a state, an event and: + * - a event if the transition returns only one state. + * - branches if the transition returns different states. + * See examples for reel usage. + */ +#define ANGFSM_TRANS(state, event, output_branches...) \ +angfsm_build_state_t* ANGFSM_PASTE3_EXPAND (angfsm_trans_, ANGFSM_NAME,_##state##_##event) (); \ + void ANGFSM_PASTE3_EXPAND (angfsm_build_trans_, ANGFSM_NAME,_##state##_##event)() __attribute__((constructor(105))); \ + void ANGFSM_PASTE3_EXPAND (angfsm_build_trans_, ANGFSM_NAME,_##state##_##event)() \ + { \ + angfsm_build_trans (& ANGFSM_PASTE_EXPAND(angfsm_, ANGFSM_NAME), #state, #event, \ + #output_branches, \ + & ANGFSM_PASTE3_EXPAND (angfsm_trans_, ANGFSM_NAME,_##state##_##event)); \ + } \ + angfsm_build_state_t* ANGFSM_PASTE3_EXPAND (angfsm_trans_, ANGFSM_NAME,_##state##_##event) () + +/** + * Used to return next state by giving the actual transition informations and + * the branch (if there are several branches). + * Not directly returning the state can avoid some errors. * + */ +#define ANGFSM_NEXT(state, event, branch...) \ + angfsm_build_get_next_state (& ANGFSM_PASTE_EXPAND (angfsm_, ANGFSM_NAME), #state, #event, #branch) + +/** + * Define a transition when a state times out. + * You have to provide a state, a timeout value and: + * - a event if the transition returns only one state. + * - branches if the transition returns different states. + * See examples for reel usage. + */ +#define ANGFSM_TRANS_TIMEOUT(state, timeout, output_branches...) \ + void ANGFSM_PASTE3_EXPAND (angfsm_build_timeout_, ANGFSM_NAME,_##state##_TIMEOUT)() __attribute__((constructor(106))); \ + void ANGFSM_PASTE3_EXPAND (angfsm_build_timeout_, ANGFSM_NAME,_##state##_TIMEOUT)() \ + { \ + angfsm_build_timeout (& ANGFSM_PASTE_EXPAND(angfsm_, ANGFSM_NAME), #state, XSTR(state##_TIMEOUT), timeout); \ + } \ + ANGFSM_EVENTS (state##_TIMEOUT) \ + ANGFSM_TRANS (state, state##_TIMEOUT, output_branches) + +/** + * Used to return next state after a timeout. + * Same as ANGFSM_NEXT but without specifying an event. + */ +#define ANGFSM_NEXT_TIMEOUT(state, branch...) \ + ANGFSM_NEXT (state, state##_TIMEOUT, branch) + +/** Used to handle timeout events. */ +#define ANGFSM_HANDLE_TIMEOUT(fsm_name) \ + angfsm_build_handle_timeout (& ANGFSM_PASTE_EXPAND (angfsm_, ANGFSM_NAME)) + +/** Transform an event in uint16_t. */ +#define ANGFSM_EVENT(fsm_name, event) \ + angfsm_build_get_event_code (& ANGFSM_PASTE_EXPAND (angfsm_, ANGFSM_NAME), #event) + +/** Handle event from uint16_t. */ +#define ANGFSM_HANDLE_VAR(fsm, event) \ + angfsm_build_handle_integer (& ANGFSM_PASTE_EXPAND (angfsm_, ANGFSM_NAME), event) + +/* Can we handle event from uint16_t ? */ +#define ANGFSM_CAN_HANDLE_VAR(fSM, event) \ + angfsm_build_can_handle_integer (& ANGFSM_PASTE_EXPAND (angfsm_, ANGFSM_NAME), event) + +/** + * Parse a string who contains a list of arguments separated by comma. + * It will create and store each parameters (without space and ") in an array + * and give the number of parsed arguments. + * \param string string to parse + * \param tab pointer to a table of strings where to store the array + * \param nb pointer where to store the number of parsed arguments + */ +void +angfsm_build_arg_parse(char *string, char ***tab, int *nb); + +/** + * Free an array of strings generated by angfsm_build_arg_parse. + * \param tab pointer to the array of strings + * \param nb number of arguments stored in the array. + */ +void +angfsm_build_arg_free(char ***tab, int nb); + +/** + * This function is executed when a state is returned by a transition. + * \param fsm fsm + * \param trans transition where the return occurs + * \param branch branch to transition has chosen. + */ +void +angfsm_build_print(angfsm_build_t *fsm, + angfsm_build_trans_t* trans, + angfsm_build_branch_chain_t* branch); + +/** + * Test the fsm and search for errors. + */ +void +angfsm_build_sanity_check(angfsm_build_t *fsm); + +/** Reset the fsm to it's initial state. */ +void +angfsm_build_reset(angfsm_build_t *fsm); + +/** Generate the dot file of the actual fsm state. + * \param fsm fsm + * \param output output file name. If empty or NULL, it will generate a file + * like "angfsm_{FSM NAME}.dot" . + */ +void +angfsm_build_gen_dot(angfsm_build_t *fsm, char *output); + +/** Initialize the fsm. */ +void +angfsm_build_init(angfsm_build_t *fsm, char *name); + +/** Initialize the running data of the fsm. */ +void +angfsm_build_run_init(angfsm_build_t *fsm); + +/** + * Add some states to the fsm. + * \param fsm fsm + * \param states states separated by comma + **/ +void +angfsm_build_states(angfsm_build_t *fsm, char *states); + +/** + * Add some events to the fsm. + * \param fsm fsm + * \param events events separated by comma + **/ +void +angfsm_build_events(angfsm_build_t *fsm, char *events); + +/** Get event's pointer by giving it's name. */ +angfsm_build_event_t* +angfsm_build_get_event(angfsm_build_t *fsm, char *event); + +/** Get state's pointer by giving it's name. */ +angfsm_build_state_t* +angfsm_build_get_state(angfsm_build_t *fsm, char *state); + +/** Get event's pointer by giving it's code. */ +angfsm_build_event_t* +angfsm_build_get_event_by_code(angfsm_build_t *fsm, uint event); + +/** Get state's pointer by giving it's code. */ +angfsm_build_state_t* +angfsm_build_get_state_by_code(angfsm_build_t *fsm, uint state); + +/** Get event code as uint16_t */ +uint16_t +angfsm_build_get_event_code(angfsm_build_t *fsm, char *event); + +/** + * Add a transition to the fsm. + * \param fsm fsm + * \param state state who will be active for the transition + * \param event event to react + * \param output_branches list of output branches seperated by comma or a + * single state (if there is only one branche). + * For example: + * - If the transition return a single state, it will be "stateX" + * - If the transition can return different states, it will be + * "branch1, state1, branch2, state2, branch3, state3" [...] + * \param trans_func pointer to the transition function. + */ +void +angfsm_build_trans(angfsm_build_t *fsm, + char *state, + char *event, + char *output_branches, + angfsm_build_run_strans_func_t trans_func); + +/* Create transition based on a timeout. + * \param fsm fsm + * \param state state who times out + * \param event name of the timeout (specific to this state and described in + macro) + * \param timeout value of timeout + */ +void +angfsm_build_timeout(angfsm_build_t *fsm, char *state, char *event, uint timeout); + +/** + * Define with which states the fsm will start. + * \param fsm fsm + * \param starters list of states seperated by comma + */ +void +angfsm_build_start_with(angfsm_build_t *fsm, char *starters); + +/** Handle an event by the fsm. + * \param fsm fsm + * \param event event to handle with fsm + * \return zero if event is not handled at all, one otherwise + **/ +int +angfsm_build_handle(angfsm_build_t *fsm, angfsm_build_event_t *event); +int +angfsm_build_handle_string(angfsm_build_t *fsm, char *event); +int +angfsm_build_handle_integer(angfsm_build_t *fsm, uint16_t event); + +/** + * Say if the event can be handled or not. + * \param fsm fsm + * \param event event to test with the fsm + * \return zero if the event can be handled, non-zero otherwhise + */ +int +angfsm_build_can_handle(angfsm_build_t *fsm, angfsm_build_event_t *event); +int +angfsm_build_can_handle_string(angfsm_build_t *fsm, char *event); +int +angfsm_build_can_handle_integer(angfsm_build_t *fsm, uint16_t event); + +/** + * Handle timeout events of the fsm. + * \param fsm fsm + * \return one if an event has been handled, zero otherwise + */ +int +angfsm_build_handle_timeout(angfsm_build_t *fsm); + +/** Give the state at the transition output. */ +angfsm_build_state_t* +angfsm_build_get_next_state(angfsm_build_t *fsm, + char *state, + char *event, + char *branch); + +/** Pass parameters to AngFSM at execution. Try --ang-help + * \param argc argc from your main. + * \param argv argv from your main. + * \return different from zero if any argument has been used, zero otherwhise. + * */ +int +angfsm_build_options(int argc, char **argv); + +/** + * Generate header file for target which provides more optimised version of + * fsm execution + * \param arch specify generated architecture by it's string. + * embedded). + */ +void +angfsm_build_gen(char *arch); +void +angfsm_build_gen_no_opti_h(angfsm_build_t *fsm, angfsm_build_arch_t arch); +void +angfsm_build_gen_no_opti_c(angfsm_build_t *fsm, angfsm_build_arch_t arch); +void +angfsm_build_gen_opti_avr_h(angfsm_build_t *fsm, angfsm_build_arch_t arch); +void +angfsm_build_gen_opti_avr_c(angfsm_build_t *fsm, angfsm_build_arch_t arch); + +/** Free fsm allocated data. */ +void +angfsm_build_free(angfsm_build_t *fsm); + +/** Print help. */ +void +angfsm_build_print_help(); + +#endif -- cgit v1.2.3