![]() |
![]() |
![]() |
![]() |
Using checkpoint/restore with the FLI
In order to use checkpoint/restore with the FLI, any data structures that have been allocated in foreign models and certain IDs passed back from FLI function calls must be explicitly saved and restored. We have provided a number of features to make this as painless as possible.
The main feature is a set of memory allocation functions. Memory allocated by such a function will be automatically restored for you to the same location in memory, ensuring that pointers into the memory will still be valid.
The second feature is a collection of explicit functions to save and restore data. You will need to use these functions for any pointers to your data structures, and for IDs returned from FLI functions. Pointers that you save and restore must be global, not variables on the stack. If you choose not to use the MTI provided memory allocation functions, you will have to explicitly save and restore your allocated memory structures as well.
You must code your model assuming that the code could reside in a different memory location when restored. This requires that you update all process pointers during a restore and re-register all callback functions after the restore is complete.
The following is a C model of a two-input AND gate (the same model as provided in
/<install_dir>/modeltech/examples/foreign/example_two/gates.c) adapted for checkpoint/restore. The lines added for checkpoint/restore are marked with comments./* * This program creates a process sensitive to two signals and * whenever one or both of the signals change it does an AND operation * and drives the value onto a third signal. */ #include <stdio.h> #include "mti.h" typedef struct { mtiSignalIdT in1; mtiSignalIdT in2; mtiDriverIdT out1; mtiProcessIdT proc; /* new */ } inst_rec; void do_and( inst_rec *ip ) { mtiInt32T val1, val2; mtiInt32T result; val1 = mti_GetSignalValue( ip->in1 ); val2 = mti_GetSignalValue( ip->in2 ); result = val1 & val2; mti_ScheduleDriver( ip->out1, result, 0, MTI_INERTIAL ); } void save_data( void * param ) /* new function */ { inst_rec * ip = (inst_rec *)param; mti_SaveBlock( (char*)&ip, sizeof(ip) ); } void restore_data( void * param ) /* new function */ { inst_rec * ip; mti_RestoreBlock( (char*)&ip ); mti_RestoreProcess( ip->proc, "p1", do_and, ip ); } void and_gate_init( mtiRegionIdT region, char *param, mtiInterfaceListT *generics, mtiInterfaceListT *ports ) { inst_rec *ip; mtiSignalIdT outp; if ( ! mti_IsRestore() ) { /* new */ ip = (inst_rec *)mti_Malloc( sizeof(inst_rec) ); ip->in1 = mti_FindPort( ports, "in1" ); ip->in2 = mti_FindPort( ports, "in2" ); outp = mti_FindPort( ports, "out1" ); ip->out1 = mti_CreateDriver( outp ); ip->proc = mti_CreateProcess( "p1", do_and, ip ); /* changed */ mti_Sensitize( ip->proc, ip->in1, MTI_EVENT ); /* changed */ mti_Sensitize( ip->proc, ip->in2, MTI_EVENT ); /* changed */ } mti_AddSaveCB( save_data, ip ); /* new */ mti_AddRestoreCB( restore_data, 0 ); /* new */ }The above example displays the following features:
- mti_Malloc( ) is used instead of malloc( ).
- A callback is added using mti_AddSaveCB( ) to save the ip pointer.
- The mti_IsRestore( ) flag is checked for restore.
- When a restore is being done, mti_RestoreBlock( ) is used to restore the ip pointer because mti_SaveBlock( ) was used to save it. (Note that restores must be performed in the same order as saves.)
- mti_RestoreProcess( ) is used to update the process created by mti_CreateProcess( ) with the possibly new address of the do_and( ) function. (This is in case the foreign code gets loaded into a different memory location.) All processes must be restored in this manner.
- All callbacks are added on first init and on restore. The restore does not restore callbacks because the routines might be located at different places after the restore operation.
![]() Model Technology Inc. Voice: (503) 641-1340 Fax: (503)526-5410 http://www.model.com sales@model.com |
![]() |
![]() |
![]() |
![]() |