The reference engine does not require any special software aside from a standard C++ compiler and the STL (usually installed along with the C++ compiler). In addition, a support for C++0x is required when working with the optimized engine, and C++11 for the multithread engine. We are currently working with the GNU compiler g++ version 4.8.2, and for ABI compatibility issues we recommend to use g++ version 4.8 or higher when compiling the generated code.
Go to the download page for the BIP tools. As for the compiler, you may install the engines separately using specific archives, or you can install everything at once (compiler & engines). Only the first installation procedure is presented here. For the one archive installation, read the Downloading & installing.
The archive is a self-contained. You need to extract it in a dedicated directory, for example /home/a_user/local/bip2:
$ mkdir /home/a_user/local/bip2
$ cd /home/a_user/local/bip2
$ tar zxvf /path/to/the/BIP-reference-engine_2012.01.tar.gz
BIP-reference-engine-2012.01/
...
...
For easier use, set the following environment variables:
This can be done adding the following in your ~/.bashrc (if you are using bash):
export BIP2_ENGINE_SPECIFIC_DIR=/path/to/BIP-reference-engine-2012.01/include/specific
export BIP2_ENGINE_GENERIC_DIR=/path/to/BIP-reference-engine-2012.01/include/generic
export BIP2_ENGINE_LIB_DIR=/path/to/BIP-reference-engine-2012.01/lib/static
After extracting the archive, you should have a similar setup:
.
÷── generic/
│ `── include
│ ÷── AtomExportPortItf.hpp
│ ÷── AtomInternalPortItf.hpp
│ ÷── AtomItf.hpp
│ ÷── bip-engineiface-config.hpp
│ ÷── BipErrorItf.hpp
│
÷── specific/
│ `── include
│ ÷── AtomExportPort.hpp
│ ÷── Atom.hpp
│ ÷── AtomInternalPort.hpp
│ ...
`── lib/
`── libengine.a
You need to generate code from your BIP source as explained in More about C++ code generator.
You need to create a build subdirectory where all the compiled code will be located. Usually, this directory is a sub-directory within the generated code tree. For example, if the output directory contains all our generated code:
/home/a_user/output $ mkdir build && cd build
Then you need to invoke cmake from within this new build directory by pointing to the directory containing the generated code (in our example, ..). If you did not set environment variables as detailed in the Installation of the engine, then you need to provide cmake with absolutes paths to engine files: BIP2_ENGINE_GENERIC_DIR and BIP2_ENGINE_SPECIFIC_DIR for the engine interface code (ie. header files), and BIP2_ENGINE_LIB_DIR for the compiled engine code.
Example cmake invocation with environment variables set:
$ cmake ..
-- The C compiler identification is GNU
-- The CXX compiler identification is GNU
-- Check for working C compiler: /usr/bin/gcc
-- Check for working C compiler: /usr/bin/gcc -- works
-- Detecting C compiler ABI info
-- Detecting C compiler ABI info - done
-- Check for working CXX compiler: /usr/bin/c++
-- Check for working CXX compiler: /usr/bin/c++ -- works
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
-- Configuring done
-- Generating done
-- Build files have been written to: /home/a_user/output/build
Example cmake invocation without environment variables set:
$ cmake \
-DBIP2_ENGINE_GENERIC_DIR=/absolute/path/to/engines/BIP-reference-engine-2012.01/include/generic/ \
-DBIP2_ENGINE_SPECIFIC_DIR=/absolute/path/to/engines/BIP-reference-engine-2012.01/include/specific/ \
-DBIP2_ENGINE_LIB_DIR=/absolute/path/to/engines/BIP-reference-engine-2012.01/lib/static \
..
-- The C compiler identification is GNU
-- The CXX compiler identification is GNU
-- Check for working C compiler: /usr/bin/gcc
-- Check for working C compiler: /usr/bin/gcc -- works
-- Detecting C compiler ABI info
-- Detecting C compiler ABI info - done
-- Check for working CXX compiler: /usr/bin/c++
-- Check for working CXX compiler: /usr/bin/c++ -- works
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
-- Configuring done
-- Generating done
-- Build files have been written to: /home/a_user/output/build
If your output matches the examples, you can proceed to the actual C++ compilation & linking by simply invoking make:
$ make
The result will be a single executable file called system.
The resulting executable is called system and is created in the build directory created previously (see previous section). It includes both the code generated specifically for the considered BIP2 model and the reference engine. Engines are runtime used for scheduling execution sequences of BIP models.
Once the executable is built, help information is provided when executing system with option --help:
./system --help
Usage: ./system [options]
BIP Engine general options:
-d, --debug allows debug of the system, i.e. diplays the state of the system
--execute execute a single sequence of interactions (default)
--explore compute all possible sequences of interactions
-h, --help display this help and exit
-i, --interactive interactive mode of execution
-l, --limit LIMIT limits the execution to LIMIT interactions
--seed SEED set the seed for random to SEED
-s, --silent disables the display of the sequence of enabled/chosen interactions
-v, --verbose enables the display of the sequence of enabled/chosen interactions (default)
-V, --version displays engine version and exits
BIP Engine semantics options (WARNING: modify the official semantics of BIP!):
--disable-maximal-progress disable the application of maximal progress priorities
An execution sequence can be scheduled simply by running directly system without any option (execution of a single sequence is a default mode):
$ ./system
Notice that the reference engine is in verbose mode by default. At each state, it displays the enabled interactions and internal ports, and the chosen sequence , e.g.:
...
[BIP ENGINE]: initialize components...
[BIP ENGINE]: random scheduling based on seed=6
[BIP ENGINE]: state #0: 14 interactions:
[BIP ENGINE]: [0] ROOT.f1take1: ROOT.f1.take() ROOT.p1.take_left()
[BIP ENGINE]: [1] ROOT.f1take2: ROOT.f1.take() ROOT.p7.take_right()
[BIP ENGINE]: [2] ROOT.f2take1: ROOT.f2.take() ROOT.p2.take_left()
[BIP ENGINE]: [3] ROOT.f2take2: ROOT.f2.take() ROOT.p1.take_right()
[BIP ENGINE]: [4] ROOT.f3take1: ROOT.f3.take() ROOT.p3.take_left()
[BIP ENGINE]: [5] ROOT.f3take2: ROOT.f3.take() ROOT.p2.take_right()
[BIP ENGINE]: [6] ROOT.f4take1: ROOT.f4.take() ROOT.p4.take_left()
[BIP ENGINE]: [7] ROOT.f4take2: ROOT.f4.take() ROOT.p3.take_right()
[BIP ENGINE]: [8] ROOT.f5take1: ROOT.f5.take() ROOT.p5.take_left()
[BIP ENGINE]: [9] ROOT.f5take2: ROOT.f5.take() ROOT.p4.take_right()
[BIP ENGINE]: [10] ROOT.f6take1: ROOT.f6.take() ROOT.p6.take_left()
[BIP ENGINE]: [11] ROOT.f6take2: ROOT.f6.take() ROOT.p5.take_right()
[BIP ENGINE]: [12] ROOT.f7take1: ROOT.f7.take() ROOT.p7.take_left()
[BIP ENGINE]: [13] ROOT.f7take2: ROOT.f7.take() ROOT.p6.take_right()
[BIP ENGINE]: -> choose [1] ROOT.f1take2: ROOT.f1.take() ROOT.p7.take_right()
[BIP ENGINE]: state #1: 12 interactions:
[BIP ENGINE]: [0] ROOT.f2take1: ROOT.f2.take() ROOT.p2.take_left()
[BIP ENGINE]: [1] ROOT.f2take2: ROOT.f2.take() ROOT.p1.take_right()
[BIP ENGINE]: [2] ROOT.f3take1: ROOT.f3.take() ROOT.p3.take_left()
[BIP ENGINE]: [3] ROOT.f3take2: ROOT.f3.take() ROOT.p2.take_right()
[BIP ENGINE]: [4] ROOT.f4take1: ROOT.f4.take() ROOT.p4.take_left()
[BIP ENGINE]: [5] ROOT.f4take2: ROOT.f4.take() ROOT.p3.take_right()
[BIP ENGINE]: [6] ROOT.f5take1: ROOT.f5.take() ROOT.p5.take_left()
[BIP ENGINE]: [7] ROOT.f5take2: ROOT.f5.take() ROOT.p4.take_right()
[BIP ENGINE]: [8] ROOT.f6take1: ROOT.f6.take() ROOT.p6.take_left()
[BIP ENGINE]: [9] ROOT.f6take2: ROOT.f6.take() ROOT.p5.take_right()
[BIP ENGINE]: [10] ROOT.f7take1: ROOT.f7.take() ROOT.p7.take_left()
[BIP ENGINE]: [11] ROOT.f7take2: ROOT.f7.take() ROOT.p6.take_right()
[BIP ENGINE]: -> choose [11] ROOT.f7take2: ROOT.f7.take() ROOT.p6.take_right()
...
[BIP ENGINE]: state #26: 2 interactions:
[BIP ENGINE]: [0] ROOT.f7take1: ROOT.f7.take() ROOT.p7.take_left()
[BIP ENGINE]: [1] ROOT.f7take2: ROOT.f7.take() ROOT.p6.take_right()
[BIP ENGINE]: -> choose [1] ROOT.f7take2: ROOT.f7.take() ROOT.p6.take_right()
[BIP ENGINE]: state #27: deadlock!
Interactions or internal ports are chosen randomly amongst the enabled ones. The reference engine is based on a uniform distribution of probability for the choice of the interactions or internal ports. By default, the seed used to initialize randomize choices is computed from the current value of time, but it can be set to a given value using option --seed. The execution is stopped if no interaction and no internal port is enabled, or if ctrl-D is hit.
Option --explore allows the exhaustive execution of the sequences defined by a model. In order to perform back-tracking, this mode of execution requires the generation of additional code, which is enforced using option --gencpp-enable-marshalling when compiling the model.
Important
Enabling option --gencpp-enable-marshalling generates code for storing and retrieving states of atomic components, which requires storing / retrieving their variables. For custom types, such code has to be provided by the user (as the definition of the type). For a custom type custom_t, the generated code expect the presence of an implementation for following methods:
Notice that the exploration mode requires comparison of states. It assumes deterministic execution of the above methods, that is, they must provide the same results for the same input values. Obviously, the application of fromBytes to the sequence of bytes computed by toBytes for a variable v must assign to v the value it had when calling toBytes.
The current version of the engine displays dots each time an interaction or an internal port is executed. Moreover, the number of reachable states, deadlocks, and errors is displayed, e.g.:
$ ./system --explore
...
[BIP ENGINE]: initialize components...
[BIP ENGINE]: computing reachable states:..............................................
.......................................................................................
.......................................................................................
.......................................................................................
.......................................................................................
...
.................... found 27303 reachable states, 2 deadlocks, and 0 error in 0 state
Since the reference engine (presented in the previous section) can be very, very slow, we recommend to use the optimized engine whenever performance is an issue. The optimized engine implements minimal optimizations required for reasonable runtime performances in terms of both execution time and memory usage. It currently passes the same tests as the reference engine, and it accepts the same general options.
For installing and using the optimized engine, proceeds as explained above for the reference engine (see Installation of the engine), after downloading the optimized engine instead of the reference engine from download page. Performances can be again improved when combining the use of the optimized engine and the activation of optimizations in the code generator (see Optimisation).
To allow maximal optimization, combine the following:
The multithread engine is proposed for increasing further the performance when running on multicore platforms. It is available in a beta version that is experimental is and should not be considered as mature as the reference and the optimized engine. It relies on the latest standard C++11 of C++, requiring version 4.8 or higher of GCC for compiling the generated C++ code. Moreover, it may require additional library implementing threads, e.g. to use pthread add the option --gencpp-ld-l pthread when invoking the BIP compiler.
The options proposed by the multithread engine are listed below:
BIP Engine general options:
(i.e. executes interactions in parallel, if obs. equivalent)
-d, --debug allows debug of the system, i.e. diplays the state of the system
-h, --help display this help and exit
-i, --interactive interactive mode of execution
-l, --limit LIMIT limits the execution to LIMIT interactions
--seed SEED set the seed for random to SEED
--threads NB set the number of threads (by default, use the maximal HW
parallelism or 8)
-s, --silent disables the display of the sequence of enabled/chosen interactions
-v, --verbose enables the display of the sequence of enabled/chosen interactions
(default)
-V, --version displays engine version and exits
The multithread engine does not support any exploration mode and can only execute sequences of interactions. It executes components involved in interactions is parallel, based on the notion of partial state: interactions can start from partial states, that is, even if some components are still running. The multithread engine guarantees that interactions are always started in an order meeting the global state semantics which is implemented in the reference and the optimized engine.
Option --threads can be used to control the total number of threads used for executing the model. Notice that these threads are used not only for executing the atomic components, but also for computing the enabled interactions: connectors evaluate enabled interactions in a parallel and concurrent way.
Important
Notice that performances obtained when using the multithread engine depend on many factors, and may be worse than the ones obtained when using the optimized engine. This is due to the overhead introduced by the use of threads and threads synchronizations, which is inherent to the concurrent design implemented by the multithread engine.
If you get the following error:
CMake Error: The following variables are used in this project, but they are set to NOTFOUND.
Please set them or make sure they are set and tested correctly in the CMake files:
libengine_path
linked by target "system" in directory ..../output
It’s probably because you are trying to use a relative path for the BIP2_ENGINE_LIB_DIR. Always use absolute paths!
If you get:
In file included from .../src/simple/AT_At1.cpp:3:
.../include/simple/AT_At1.hpp:6:20: error: Atom.hpp: No such file or directory
It’s probably because you are trying to use a relative path for one or both BIP2_ENGINE_GENERIC_DIR and BIP2_ENGINE_SPECIFIC_DIR. Always use absolute paths !