/** @page LEVEL2 Model Source Code This section details the syntax for creating headers and source code that %Trick can process. It also details the operation of the %Trick Interface Code Generator (ICG) that processes headers, and the Module Interface Specification Processor (MIS) that processes source code. @section LEVEL3 Programming Language Support The majority of model source for simulations is written in C and C++ . %Trick supports auto generating IO code to peek and poke C and C++ structures, classes, and enumerations. %Trick also generates the necessary makefile rules to compile and link C and C++ model code into the simulation. Models written in other languages may be included in the simulation. It is possible to include Fortran 77, Fortran 90, Ada, and/or Java code in the simulation. These models cannot be called directly from the %Trick scheduler, but may be called through C language wrapper functions provided by the user that executes the other language calls. @section LEVEL3 C Header Files %Trick processes header files in order to auto generate IO source code for the simulation. IO source code is the heart of how %Trick does its input processing. The following describes the syntax for a header file. @verbatim /* [TRICK_HEADER] PURPOSE: (Purpose statement.) [LANGUAGE: (CPP|C++)] [LIBRARY DEPENDENCY: ( (object.o|model.c|lib.a|lib.so|/lib.a) [(object_n.o|lib_n.a|lib_n.so|/lib_n.a)] )] [ICG IGNORE TYPES: ((Type #1) (Type #n)])] [PYTHON_MODULE: (module_name)] [REFERENCES: ((Reference #1) (Reference #n)])] [ASSUMPTIONS AND LIMITATIONS: ((Assumption #1) (Assumption #n)])] [PROGRAMMERS: (((Name) (Company) (Date) [(other info)]) [((Name) (Company) (Date) [(other info)])]] [ICG: (No|Nocomment)] */ typedef enum { enum_lable [=enum_value], last_enum_label [= enum_value] } enum_name ; [typedef] struct [struct_tag] { char|short|int|long|long long| unsigned char|unsigned short|unsigned int|unsigned long|unsigned long long| float|double [*]* param_name [[dim]]* ; /* [**|*i|*o|*io] trick_io([**|*i|*o|*io]) trick_chkpnt_io([**|*i|*o|*io]) measurement_units [ { [ friend InputProcessor ; friend init_attr() ; ] (public|protected|private): char|short|int|long|long long| unsigned char|unsigned short|unsigned int|unsigned long|unsigned long long| float|double [*]* param_name [[dim]]* ; /* [**|*i|*o|*io] measurement_units [/.a - If you use a relative path to the library, %Trick will search the TRICK_CFLAGS for a directory that contains source code for the library. Once %Trick locates the source code, it will automatically build the library and link it in the simulation. -# .a - If you do NOT specify a relative path, %Trick will NOT build the library for you. It will simply search your -L paths in your TRICK_USER_LINK_LIBS for the library. If found, it will link the library into the simulation. You may also have %Trick link in a shared (lib*.so) library. You must supply the *.so extension. %Trick will not automatically build a shared library, but it is smart enough to use it during link time. The LIBRARY DEPENDENCY field also handles the #ifdef, #else and #endif statements such that different object files and libraries may be linked for different cases. The previous example might look like this: @verbatim LIBRARY DEPENDENCY: ((this.o) (that.o) #ifdef __animals (my_library/libdog.a) (libcow.so) #else (my_library/lib.a) #endif (${FOO_ENV_VAR}/foo.o)) @endverbatim It is good practice to add library dependencies for source code files for prototypes listed in the header. @par ICG_IGNORE_TYPES The ICG IGNORE TYPES field lists the structs or classes to be ignored. Any parameters of this type or inherited from are ignored. The ICG IGNORE TYPES field only valid for the current file. It does not extend to included header files. @par PYTHON_MODULE Specifying a python_module name will place any class/struct and function definitions in this header file in a python module of the same name. All classes and functions are flattened into the python trick namespace by default. This capability allows users to avoid possible name collisions between names when they are flattened. @section LEVEL4 Compiler Directives %Trick handles all compiler directives (#if, #ifdef, #endif, #define, #include, etc.) ICG also uses the -D and -U command line arguments for defines and undefines, respectively. @section LEVEL4 Enumerated Type Definitions %Trick provides complete support for enumerated types. Simple mathematical expressions using enumerated types are supported as well. An example follows: a.h @verbatim typedef enum { FIRST_ENUM = 45 } A_ENUM ; @endverbatim b.h @verbatim #include "a.h" typedef enum { ME_TOO = 2 } OTHER_ENUM; typedef enum { SECOND_ENUM = FIRST_ENUM, THIRD_ENUM = FIRST_ENUM * 3, FOURTH_ENUM = SECOND_ENUM * 4, FIFTH_ENUM = ME_TOO * 6 } B_ENUM ; @endverbatim c.h @verbatim #include "b.h" typedef struct { int dummy; /* No comment necessary */ A_ENUM ae; /* No comment necessary */ B_ENUM be; /* No comment necessary */ int ia1[FIRST_ENUM]; /* No comment necessary */ int ia2[SECOND_ENUM]; /* No comment necessary */ int ia3[FIFTH_ENUM]; /* No comment necessary */ } DATA ; @endverbatim @section LEVEL4 Data Structure Definitions and Parameter Declarations The data structure type definition statements, typedef struct { ... } name;, and typedef union { ... } name; struct Foo { } name; follows standard C syntax, and are supported by %Trick. However, %Trick requires a C comment immediately following every parameter declaration. @section LEVEL4 Parameter Data Types %Trick allows any data type declaration within the data structure typedef statement. However, only the following data types will be processed by %Trick: -# int, -# short, -# long, -# long long -# char, -# (un)signed int, -# (un)signed short, -# (un)signed long, -# (un)signed char, -# (un)singed long long, -# (un)signed short int, -# (un)signed long int, -# float, -# double, -# wchar_t, -# FILE * -# Bit fields (signed and unsigned) and -# previously processed structure, union, enumerated types and typedefs. All other types are ignored. Types may be defined and used within the same header if the types are defined before they are used (this is a C syntax rule, too). @section LEVEL4 Pointers Any combination of pointers and array dimensions up to 8 dimensions may be used for parameter declarations; for example, double ** four_dimensional_array[2][2];, will be processed. Void pointers and function pointers are not processed. Parameters declared with pointers (like four_dimensional_array example), are treated differently; these are called unconstrained arrays. %Trick will generate dynamic memory allocation source code for the developer which allows the developer to size the array dimensions (represented by the pointers) via special syntax in the runstream input file. The developer may 1) use the input file to input data to the arrays, 2) output the data via standard %Trick logging functions, or 3) share the data through the variable server. The user does have the option to perform their own memory management for parameters declared as pointers. In this case, instead of specifying the allocation in the input file, the user may allocate the data in a job. In order for %Trick to process the data as if it was its own managed memory (and provide capabilities like logging, checkpointing, etc.), the memory address, and number and size of the allocation must be passed to the %Trick TMM_declare_extern_var function. The user is also responsible for freeing the memory when done. For a code example, see Section 4.4.11. @section LEVEL4 Intrinsic typedef and struct Support Types declared using typedef struct, typedef union, and typedef enum are recognized by %Trick. Intrinsic typedefs are supported as well and may be nested in structures. The example that follows details a header that %Trick will handle: @verbatim typedef unsigned char my_uchar; typedef char my_char; typedef wchar_t my_wchar; typedef short int my_shortint; typedef short my_short; typedef unsigned short int my_ushortint; typedef unsigned short my_ushort; typedef int my_int; typedef unsigned int my_uint; typedef long int my_longint; typedef long my_long; typedef unsigned long int my_ulongint; typedef unsigned long my_ulong; typedef float my_float; typedef double my_double; typedef my_short my_short2; struct Animal_Sound { int moo ; /* -- Cow */ int baa ; /* -- Lamb */ int sss ; /* -- Snake */ }; typedef struct { my_uchar uc ; /* -- unsigned char */ my_char c ; /* -- char */ my_char ca[80] ; /* -- char */ my_wchar wc; /* -- wchar_t */ my wchar wca[100]; /* -- wchar_t */ my_shortint si ; /* -- short int */ my_short *s ; /* -- short stuff */ my_ushortint usi ; /* -- short stuff */ my_ushort us ; /* -- short stuff */ my_int i ; /* -- count */ my_int ia[5] ; /* -- count */ my_uint ui ; /* -- count */ my_longint li ; /* -- count */ my_long l ; /* -- count */ my_ulongint uli ; /* -- count */ my_ulong ul ; /* -- count */ my_float f ; /* -- count */ my_double d ; /* -- count */ my_short2 s20; /* -- short 20 */ my_short2 s21; /* -- short 21 */ struct Animal_Sound as /* -- Wild Kingdom */ } DATA ; typedef DATA MY_DATA; typedef MY_DATA MY_DATA_2; typedef struct { DATA id; /* -- testing typedef of struct */ MY_DATA mid; /* -- testing typedef of struct */ MY_DATA_2 mid2; /* -- testing typedef of struct */ } DATA_2 ; @endverbatim @section LEVEL4 Parameter Comments Each parameter declaration within a data structure definition may be accompanied by a trailing comment. There are six possible fields in the parameter comment, but only two are required. All six fields of the parameter comment are stored for later reuse at simulation runtime. @par The Input/Output Specification The first three fields in the parameter comment are optional and specify the input/output processing for the parameter. I/O permissions may be set globally or individual capabilities may set their permissions separately. I/O permissions for checkpointing is available to set separately. To set all permissions for general variable access start the comment with one of the following fields, [**|*i|*o|*io]. trick_io([**|*i|*o|*io]) is an equivalent form to set general variable access. - ** indicates that %Trick will not allow input or output for this parameter; i.e. the user can not input this parameter,record this parameter, or view its value. - *i indicates that only input is allowed for the parameter. Parameter may be input through the checkpoint file or ref_assignment, but the parameter will not be recordable or written to a checkpoint file. - *o indicates only output is allowed for the parameter. Parameter may be checkpointed or logged only. They are not reloaded during a checkpoint reload. - *io specifies that both input and output are allowed for the parameter. This is the default condition if the field is omitted from the comment. Parameter may be in input file, may be checkpointed and logged. Checkpoint I/O may be set separately by adding trick_chkpnt_io([**|*i|*o|*io]) to the comment. If this optional field is not present the general I/O access field is used to determine checkpoint permissions. - ** indicates that %Trick will not allow checkpoint input or output. General variable access may still be available. - *i indicates only checkpoint input is allowed for the parameter. Parameters will not be written to the checkpoint. - *o indicates only checkpoint output is allowed for the parameter. Parameter is written to the checkpoint, but not reloaded. - *io specifies that both input and output are allowed for the checkpointing. @par The Measurement Units Specification The second field is a required field and specifies the internal source code units for the parameter. These units are important because they give the input processor the knowledge of what units the user's input data needs to be converted to. The following sections describe the new and the previous units specifications in header files, respectively. Measurement units may be any combination of the below units. Prefixes are allowed only for Metric units. @verbatim Trick Measurement Units Summary ------------------------------- Time: s min hr day Angular Displacement: r d as am rev Voltage: v Amperage: amp Resistance: ohm Sound: dB Unitless: -- cnt one mol English System Units -------------------- Linear Displacement: ft in yd mi n.m. Mass: sl lbm Force: oz lbf Temperature: R F Energy: BTU Power: hp Pressure: psi Metric System Units ------------------- Linear Displacement: m Mass: g mt Force: N Temperature: C K Energy: J TNT Power: W Pressure: Pa atm Frequency: Hz Prefixes for Multiples and Submultiples (Not valid for English system units) --------------------------------------- 10**-1 d 10 da 10**-2 c 10**2 h 10**-3 m 10**3 k 10**-6 u 10**6 M 10**-9 n 10**9 G 10**-12 p 10**12 T 10**-15 f 10**15 P 10**-18 a 10**18 E 10**-21 z 10**21 Z 10**-24 y 10**24 Y @endverbatim @par User Defined Attributes Fields Following the measurement units specification, in the parameter comment, are two optional, user-defined attribute fields. Using these fields, a user can associate (up to 2) character strings with a parameter. These strings are stored in the ATTRIBUTES structures (in the io_src directory) generated by ICG. The first of these optional fields is delimited by brackets (‘[‘ and ‘]’) and is stored in the element ATTRIBUTES->alias. The second is delimited by braces (‘{‘ and ‘}’) and is stored in the element ATTRIBUTES->user_defined. The definition of the ATTRIBUTES structure is found in $TRICK_HOME/trick_source/sim_services/include/attributes.h. @par Description Fields The description field is required and must be the last field of the comment. The description field is basically everything after the first three fields. The description field may span multiple lines. @section LEVEL3 C++ Header Files C++ headers may include constructs and concepts not found in C header files. In addtion to all C syntax, %Trick parses and understandes many C++ features. @section LEVEL4 Public, Protected, and Private Access %Trick is able to access a class's public data and methods for input processing, data recording, ASCII checkpoinint and the variable server. Protected and private variables are not accessible by default. %Trick is able to access this data if two friends are declared in the class. @code friend class InputProcessor ; friend void init_attr() ; @endcode These friends should appear at the top of the class. If the friends are not declared with a class %Trick will ignore private and protected data. @section LEVEL4 Inheritance %Trick may use model code with any type of inheritance. Some limitations are present to Trick's ability to input process, checkpoint, etc. inherited variables. - Public and protected inherited variables are avalable for access. - Protected and private inheritance is ignored. - Multiple inheritance is processed but not well tested. - Template inheritance is not currently supported. @section LEVEL4 Namespaces Currently one level of namespace is supported. Addtional levels of namespaces are ignored. Simliarly classes and enumerations embedded in other classes are ignored. @code namespace my_ns { // BB is processed class BB { public: std::string str ; // Class CC is ignored. class CC { ... } } ; // Everything enclosed in inner_ns is ignored. namespace inner_ns { ... } ; } ; @endcode @section LEVEL4 Function Overloading %Trick parses function declarations for input file use. The python input processor understands class method overloading. Overloaded methods with different arguments may be called in the input files. Default arguments are to methods are understood and honored in the input file. Operator overloading is skipped by %Trick processors. Operator overloading is not implemented in the input file. @section LEVEL4 Templates and the Standard Template Libraries (STL) %Trick attempts to process user defined templates. Simple templates are handled. We do not have a good definintion of simple. Typedefs of templates is supported and encouraged. All protected and private data is ignored within templates. This is because it is not possible to specify the correct io_src friend function. Templates within templates are not processed. Finally abstract templates are not supported by %Trick. These tempaltes should be excldued from %Trick processing. See below to see how to exclude code from processing. STLs may be used in models. However, STL variables are not data recordable, they are not visible in the variable server, nor are they directly accessible in the input file. STL variables may be checkpointed with user help. %Trick provides function templates to checkpoint and restore STLs. The user needs to call 3 functions, a checkpoint, post_checkpoint, and restart class jobs. @code // A class with STLs to be checkpointed. 3 methods are defined to help Trick checkpoint the STLs class STLCheckpoint { public: std::map< int , double > my_double_map ; std::vector < double > my_double_vec ; int checkpoint(string object_name); int post_checkpoint(string object_name); int restart(string object_name); } ; // The checkpoint job converts STLs to array data. int STLCheckpoint::checkpoint(string object_name) { /* checkpoint_stl is a templated function that takes an STL, a sim_object name, and a variable name (usually the same as the STL name) as arguments. It outputs memory_manager arrays named object_name. that contain the data in the STLs. */ checkpoint_stl(my_double_map, object_name , “my_double_map”) ; checkpoint_stl(my_double_vec , object_name ,“my_double_vec”) ; } // The post_checkpoint job frees memory allocated in checkpoint job int STLCheckpoint::post_checkpoint(string object_name) { //delete_stl takes the same arguments as checkpoint_stl checkpoint_stl(my_double_map, object_name , “my_double_map”) ; checkpoint_stl(my_double_vec , object_name ,“my_double_vec”) ; } // The restart job restores STLs from a checkpoint file. int STLCheckpoint::restart(string object_name) { //restore_stl takes the same arguments as checkpoint_stl restore_stl(my_double_map, object_name , “my_double_map”) ; resotre_stl(my_double_vec , object_name ,“my_double_vec”) ; } @endcode Calls to checkpoint the STLs in the S_define. @code class theSimObject : public Trick::SimObject { public: STLCheckpoint stls ; theSimObject() { /* "name" is the string that is the sim_object instance name. It is present in all sim objects and automatically set by Trick. */ ("checkpoint") stls.checkpoint(name) ; ("post_checkpoint") stls.post_checkpoint(name) ; ("restart") stls.restart(name) ; } ; @endcode @section LEVEL4 Noncopyable Objects Sometimes classes contain members that are not copyable or the math modeler wants to prevent the class from being copied. Declaring an unimplemented private copy constructor and assignment, "=", operator prevents the class from being copied. @code class CantCopyMe { private: CantCopyMe( const CantCopyMe & ) ; CantCopyMe & operator = ( const CantCopyMe ) ; } @endcode When using such classes in %Trick, xlasses that include non copyable classes must also declare themselves not copyable. this extendds all the way up to sim objects in the S_define. @code class MysimObject : public Trick::SimObject { public: CantCopyMe ccm ; private: MysimObject( const MysimObject & ) ; MysimObject& operator = ( const MysimObject) ; } @endcode @section LEVEL4 Source Code in Header Files %Trick attempts to skip over class code in header files while searching for class varaibles and method declarations. However, code can sometimes confuse %Trick and cause it to abort processing of header files. It is recommened to keep code out of the header file.. @section LEVEL4 Library Dependencies It is good practice to list all the source code files that define class methods in the class header file. @section LEVEL3 Excluding Header File Code There are several ways to exclude code from processing. @par Excluding Directories Add paths to exclude to the TRICK_ICG_EXCLDUE environment variable or makefile variable. This works for both C and C++ headers. @par Excluding File Add "ICG: (No)" to tht %Trick comment header. @par Excluding Lines When processing header files %Trick defines 2 #define variables, TRICK_ICG and SWIG. Code may be excluded by enclosing it in #ifndef blocks. @code #ifndef TRICK_ICG code that cannot be processed by ICG #ifndef SWIG code that cannot be processed by ICG or SWIG #endif #endif @endcode @section LEVEL3 Source Files By source files, in this context, we mean functional model source code, i.e. *.c files. @verbatim /* [TRICK_HEADER] PURPOSE: (Purpose statement.) [REFERENCES: ((Reference #1) (Reference #n)])] [ASSUMPTIONS AND LIMITATIONS: ((Assumption #1) (Assumption #n)])] [LIBRARY DEPENDENCY: ( (object.o|lib.a|lib.so|/lib.a) [(object_n.o|lib_n.a|lib_n.so|/lib_n.a)] )] [PROGRAMMERS: (((Name) (Company) (Date) [(other info)]) [((Name) (Company) (Date) [(other info)])]] */ // source code... @endverbatim @section LEVEL4 Comment Header The %Trick header is an optional comment block at the top of each source file. It is used for auto-documentation, and more importantly is the means of specifying dependencies to objects or libraries not processed by %Trick. Separate functions within a source file do NOT require additional headers. Since parentheses, ( ), are used to delineate fields within the comment header, parentheses are not allowed as characters within the comment fields. NOTE: Even if you are coding a C++ file, you must still specify the comment header using C style comments (not C++ style comments). @par Job Description - The PURPOSE field should be a brief description of what the module does. - The REFERENCES field may contain any number of references, with each reference possessing any number of sub items; notice the nested parentheses for the REFERENCES field. - The ASSUMPTIONS AND LIMITATIONS field may contain any number of assumptions and limitations delimited by parentheses. - The LIBRARY DEPENDENCIES. See @ref Library_Dependencies secion in the model header section - The PROGRAMMERS field may contain any number of programmer fields, each of which may contain any number of sub items; e.g. programmer name, company, mod date, etc. The programmer fields are meant to provide an in-code means to track code changes. @section LEVEL4 Source Code %Trickis only interested in the header comment if one is present in source code files. Anything goes for the rest of the source code file. @section LEVEL3 Trick Version Compatibility %Trick is always changing. The interface to %Trick functions may change with each major version. Sometimes even monor version upgrades changes the interface. When %Trick builds model source code it includes -DTRICK_VER= and -DTRICK_MINOR= to the TRICK_CFLAGS and TRICK_CXXFLAGS. This allows developers to key off the %Trick version in model source code. If there are any compile issues dependent on %Trick version, this #define may be useful. */