GPAClib is a header-only library implemented in C++ for defining and simulating analog circuits (GPAC = General Purpose Analog Computer). The library comes with a parser that allows to define circuit in a format that is specifed below.
In order to use GPAClib, you need to have:
- a compiler with support for C++14
- Boost library (more specifically: System, Program Options, Iostreams, Odeint and Spirit)
- OpenMP
If you want to compile the example code provided, you will need CMake version >= 3.1.
Since GPAClib is header-only, the usage is very simple: one just has to include the main header file GPAC.hpp. The header file GPACparser.hpp provides the tool to load a circuit from a specification file. A simple example of usage of GPAClib (loading a circuit and simulating it) is given in file GPACsim.cpp, which can be compiled by entering the following command while being in the main directory:
mkdir -p build
cd build
cmake ..
make
It creates a program called GPACsim that takes a specification file name as argument and simulates the corresponding circuit. Execute GPACsim --help for more information about the options.
You can generate the documentation of GPAClib using Doxygen:
cd doc
doxygen
The documentation is generated in subdirectories html (open index.html with your favorite web browser) and latex.
It is possible to comment a circuit specification file by inserting a # symbol: all remaining symbols on the line are then ignored.
The first way of defining a circuit is by specifying its gates:
Circuit <circuit_name>:
<gate_name>: ....
<gate_name>: ....
<gate_name>: ....
;
Circuit names cannot contain spaces and should not be named as builtin circuits provided in the following.
Moreover, t is a reserved name and circuit names should not be confusable with floating point numbers.
The gate specification is the following:
- for constant gate:
<value> - for product gates:
<operand1> * <operand2> - for addition gate:
<operand1> + <operand2> - for integration gates:
int <integrated> d(<variable>) | <initial_value> - for a copy of a previously defined circuit:
<identifier>
Operands are names of gates defined (before or after) in the same circuit or t. The last type allows to import a copy of a previously defined circuit and to use the gate as the output of this circuit. Gate names cannot be empty, cannot start with underscore and t is reserved. A value is either an integer or a floating point number, it can be negative. The last gate entered is the output gate.
The second way to define a circuit is by combination of previously defined circuits:
Circuit <circuit_name> = <expression>;
where expressions are defined with the following grammar:
<op> ::= + | * | @ | - | /
<expr> ::= <value> | <identifier> | <identifier>[<integer>] | (<expr> <op> <expr>)
| (<expr> <op> <expr>)[<integer>] | (int <expr> d(<expr>) | <value>)
| max(<expr>,<expr>) | select(<value>,<value>,<value>,<value>)
| deriv(<expr>) | deriv(<expr>, <integer>)
The @ operator corresponds to composition of circuits. An identifier is the name of a previously defined circuit, or the name of a builtin circuits, or t. An integer is non-negative and a value is a floating point number or an integer (no sign restriction). The [] operator is for iterating an expression or a circuit, e.g. C[5] represents circuit C iterated 5 times. select(a,b,x,y) corresponds to a circuit computing a function that has value x for t <= a and y for t >= b.
Warning: always leave a space between the - operator and values.
List of builtin circuits:
Exp: exponentialSin,Cos,TanTanhSqrtArctanInverse: function1/(1+t)Id: identity (same ast)L2: approximation of a "toggle" (close to 0 fort< 1/4 and close to 1 fort> 3/4)Abs: approximation of the absolute value functionRound: approximation of rounding function, contracts any real which is not an half integer to the closest integerMod10: approximation of the mod 10 function
Examples of circuit files are given in the circuits folder.