Skip to content

Commit

Permalink
Docs and fixes
Browse files Browse the repository at this point in the history
  • Loading branch information
svenk committed Aug 6, 2024
1 parent f897ae9 commit b644f34
Show file tree
Hide file tree
Showing 10 changed files with 430 additions and 56 deletions.
335 changes: 335 additions & 0 deletions docs/compilation.rst
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,343 @@
Circuit notation and Compilation
================================

Lucipy ships with a number of tools to manipulate the LUCIDAC interconnection matrix
(also known as *UCI matrix*).


Reconfigurable analog circuit model
-----------------------------------

The focus of this library is on **REV0** LUCIDAC hardware.
What follows is quickly drawn ASCII diagram of this particular
analog computer topology (we have much nicer schemata available which will evventually
replace this one):

::

┌─────────────────────── ┌──────────────────────────────┐
│Math Block M1 m0 0 -> │U Block │
│4 x Multipliers m1 1 │16 inputs, fanout on │
│2in, 1out each m2 2 │32 outputs (called lanes) │
│ m3 3 │ │
┌───► │ . 4 ───► │It is a 16x32 bitmatrix. │
│ │constant givers . 5 │ │
│ │ . 6 │ │
│ │ . 7 -> │ │
│ └─────────────────────── │ │
│ │ │
│ ┌─────────────────────── │ │
│ │Math Block M2 i0 8 -> │ │
│ │8 x Integrators i1 9 │ │
│ │1in, 1out each i2 10 │ │
│ │ i3 11 ───► │ │
│ ┌► │ i4 12 │ │
│ │ │ i i5 13 │ │
│ │ │ i6 14 │ │
│ │ │ i7 15 -> │ │
│ │ └─────────────────────── └──────────────┬───────────────┘
│ │ │
│ │ ┌──────────────▼───────────────┐
│ │ │C block. │
│ │ │32 coefficients │
│ │ │value [-20,+20] each │
│ │ │ │
│ │ └──────────────┬───────────────┘
│ │ │
│ │ ┌─────────────────────── ┌──────────────▼───────────────┐
│ │ │Math Block M1 m0a 0 <- │I Block │
│ │ │4 x Multipliers m0b 1 │32 inputs, fanin to │
│ │ │2in, 1out each m1a 2 │16 outputs │
│ │ │ m1b 3 ◄───┤ │
└──┼── │ m2a 4 │It is a 32x16 bitmatrix │
│ │constant givers m2b 5 │which performs implicit │
│ │ m3a 6 │summation of currents │
│ │ m3b 7 <- │ │
│ └─────────────────────── │ │
│ │ │
│ ┌─────────────────────── │ │
│ │Math Block M2 i0 8 <- │ │
│ │8 x Integrators i1 9 │ │
│ │1in, 1out each i2 10 │ │
│ │ i3 11 │ │
│ │ i4 12 ◄───┤ │
└───┤ i5 13 │ │
│ i6 14 │ │
│ i7 15 <- │ │
└─────────────────────── └──────────────────────────────┘

Concept
-------

The main usage shall be demonstrated on the Lorenz attractor example
(see also :ref:`example-circuits`). It can be basically entered as
element connection diagram:


.. code-block:: python
from lucipy import Circuit
lorenz = Circuit()
x = lorenz.int(ic=-1)
y = lorenz.int()
z = lorenz.int()
mxy = lorenz.mul() # -x*y
xs = lorenz.mul() # +x*s
c = lorenz.const()
lorenz.connect(x, x, weight=-1)
lorenz.connect(y, x, weight=+1.8)
lorenz.connect(x, mxy.a)
lorenz.connect(y, mxy.b)
lorenz.connect(mxy, z, weight=-1.5)
lorenz.connect(z, z, weight=-0.2667)
lorenz.connect(x, xs.a, weight=-1)
lorenz.connect(z, xs.b, weight=+2.67)
lorenz.connect(c, xs.b, weight=-1)
lorenz.connect(xs, y, weight=-1.536)
lorenz.connect(y, y, weight=-0.1)
Internally, the library stores :py:class:`Route` tuples:

.. code-block:: python
>> print(lorenz)
Routing([Route(uin=8, lane=0, coeff=-1, iout=8),
Route(uin=9, lane=1, coeff=1.8, iout=8),
Route(uin=8, lane=2, coeff=1, iout=0),
Route(uin=9, lane=3, coeff=1, iout=1),
Route(uin=0, lane=4, coeff=-1.5, iout=10),
Route(uin=10, lane=5, coeff=-0.2667, iout=10),
Route(uin=8, lane=14, coeff=-1, iout=2),
Route(uin=10, lane=15, coeff=2.67, iout=3),
Route(uin=4, lane=16, coeff=-1, iout=3),
Route(uin=1, lane=17, coeff=-1.536, iout=9),
Route(uin=9, lane=18, coeff=-0.1, iout=9),
Route(uin=8, lane=8, coeff=0, iout=6),
Route(uin=9, lane=9, coeff=0, iout=6)])
By concept, there is **no symbolic representation** but instead
**immediate destruction of any symbolics**. However, the "initial
format" can be easily decompiled:

.. code-block:: python
>> print(lorenz.reverse())
Connection(Int0, Int0, weight=-1),
Connection(Int1, Int0, weight=1.8),
Connection(Int0, Mul0.a),
Connection(Int1, Mul0.a),
Connection(Mul0, Int2, weight=-1.5),
Connection(Int2, Int2, weight=-0.2667),
Connection(Int0, Mul1.a, weight=-1),
Connection(Int2, Mul1.a, weight=2.67),
Connection(Const0, Mul1.a, weight=-1),
Connection(Mul1, Int1, weight=-1.536),
Connection(Int1, Int1, weight=-0.1),
Connection(Int0, Mul3.a, weight=0),
Connection(Int1, Mul3.a, weight=0)
Where :py:func:`Connection` is just a function that generates a :py:class:`Route`.

Export formats
--------------

There are various methods available to convert a Routing list to
other representations. First of all, the LUCIDAC sparse JSON configuration format can
be generated:

.. code-block:: python
>> lorenz.generate()
{'/U': {'outputs': [8,
9,
8,
9,
0,
10,
None,
None,
8,
9,
None,
None,
None,
None,
8,
10,
4,
1,
9,
None,
None,
None,
None,
None,
None,
None,
None,
None,
None,
None,
None,
None]},
'/C': {'elements': [-1,
1.8,
1,
1,
-1.5,
-0.2667,
0,
0,
0,
0,
0,
0,
0,
0,
-1,
2.67,
-1,
-1.536,
-0.1,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0]},
'/I': {'outputs': [[2],
[3],
[14],
[15, 16],
[],
[],
[8, 9],
[],
[0, 1],
[17, 18],
[4, 5],
[],
[],
[],
[],
[]]},
'/M0': {'elements': [{'k': 10000, 'ic': -1},
{'k': 10000, 'ic': 0},
{'k': 10000, 'ic': 0},
{'k': 10000, 'ic': 0.0},
{'k': 10000, 'ic': 0.0},
{'k': 10000, 'ic': 0.0},
{'k': 10000, 'ic': 0.0},
{'k': 10000, 'ic': 0.0}]},
'/M1': {}}
Therefore one can straight forwardly program a LUCIDAC by writing

.. code-block:: python
from lucipy import LUCIDAC, Circuit
lorenz = Circuit()
# ... the circuit from above ...
hc = LUCIDAC()
hc.set_config(lorenz.generate())
hc.start_run() # ...
Also other formats can be generated, for instance a single dense 16x16 matrix
showing the interconnects, weights and implict sums between the Math
blocks:

.. code-block:: python
>> import numpy as np
>> np.set_printoptions(edgeitems=30, linewidth=1000, suppress=True)
>> lorenz.to_dense_matrix().shape
(16,16)
>> lorenz.to_dense_matrix()
array([[ 0. , 0. , 0. , 0. , 0. , 0. , 0. , 0. , 1. , 0. , 0. , 0. , 0. , 0. , 0. , 0. ],
[ 0. , 0. , 0. , 0. , 0. , 0. , 0. , 0. , 0. , 1. , 0. , 0. , 0. , 0. , 0. , 0. ],
[ 0. , 0. , 0. , 0. , 0. , 0. , 0. , 0. , -1. , 0. , 0. , 0. , 0. , 0. , 0. , 0. ],
[ 0. , 0. , 0. , 0. , -1. , 0. , 0. , 0. , 0. , 0. , 2.67 , 0. , 0. , 0. , 0. , 0. ],
[ 0. , 0. , 0. , 0. , 0. , 0. , 0. , 0. , 0. , 0. , 0. , 0. , 0. , 0. , 0. , 0. ],
[ 0. , 0. , 0. , 0. , 0. , 0. , 0. , 0. , 0. , 0. , 0. , 0. , 0. , 0. , 0. , 0. ],
[ 0. , 0. , 0. , 0. , 0. , 0. , 0. , 0. , 0. , 0. , 0. , 0. , 0. , 0. , 0. , 0. ],
[ 0. , 0. , 0. , 0. , 0. , 0. , 0. , 0. , 0. , 0. , 0. , 0. , 0. , 0. , 0. , 0. ],
[ 0. , 0. , 0. , 0. , 0. , 0. , 0. , 0. , -1. , 1.8 , 0. , 0. , 0. , 0. , 0. , 0. ],
[ 0. , -1.536 , 0. , 0. , 0. , 0. , 0. , 0. , 0. , -0.1 , 0. , 0. , 0. , 0. , 0. , 0. ],
[-1.5 , 0. , 0. , 0. , 0. , 0. , 0. , 0. , 0. , 0. , -0.2667, 0. , 0. , 0. , 0. , 0. ],
[ 0. , 0. , 0. , 0. , 0. , 0. , 0. , 0. , 0. , 0. , 0. , 0. , 0. , 0. , 0. , 0. ],
[ 0. , 0. , 0. , 0. , 0. , 0. , 0. , 0. , 0. , 0. , 0. , 0. , 0. , 0. , 0. , 0. ],
[ 0. , 0. , 0. , 0. , 0. , 0. , 0. , 0. , 0. , 0. , 0. , 0. , 0. , 0. , 0. , 0. ],
[ 0. , 0. , 0. , 0. , 0. , 0. , 0. , 0. , 0. , 0. , 0. , 0. , 0. , 0. , 0. , 0. ],
[ 0. , 0. , 0. , 0. , 0. , 0. , 0. , 0. , 0. , 0. , 0. , 0. , 0. , 0. , 0. , 0. ]])
This is an export to the ``pybrid`` DSL:

.. code-block:: python
>> print(lorenz.to_pybrid_cli())
set-alias * carrier
set-element-config carrier/0/M0/0 ic -1
set-element-config carrier/0/M0/0 k -1
set-element-config carrier/0/M0/1 k 0
set-element-config carrier/0/M0/2 k 0
set-element-config carrier/0/M0/3 k 0.0
set-element-config carrier/0/M0/4 k 0.0
set-element-config carrier/0/M0/5 k 0.0
set-element-config carrier/0/M0/6 k 0.0
set-element-config carrier/0/M0/7 k 0.0
route -- carrier/0 8 0 -1.000 8
route -- carrier/0 9 1 1.800 8
route -- carrier/0 8 2 1.000 0
route -- carrier/0 9 3 1.000 1
route -- carrier/0 0 4 -1.500 10
route -- carrier/0 10 5 -0.267 10
route -- carrier/0 8 14 -1.000 2
route -- carrier/0 10 15 2.670 3
route -- carrier/0 4 16 -1.000 3
route -- carrier/0 1 17 -1.536 9
route -- carrier/0 9 18 -0.100 9
route -- carrier/0 8 8 0.000 6
route -- carrier/0 9 9 0.000 6
# run --op-time 500000
Here comes an export to a Sympy system:

.. code-block:: python
>> lorenz.to_sympy()
[Eq(m_0(t), -i_0(t)*i_1(t)),
Eq(m_1(t), (2.67*i_2(t) - 1.0)*i_0(t)),
Eq(Derivative(i_0(t), t), -i_0(t) + 1.8*i_1(t)),
Eq(Derivative(i_1(t), t), -0.1*i_1(t) - 1.536*m_1(t)),
Eq(Derivative(i_2(t), t), -0.2667*i_2(t) - 1.5*m_0(t))]
This can be tailored in order to have something which can be straightforwardly
numerically solved:

.. code-block:: python
>> [ eq.rhs for eq in lorenz.to_sympy(int_names="xyz", subst_mul=True, no_func_t=True) ]
[-x + 1.8*y, -1.536*x*(2.67*z - 1.0) - 0.1*y, 1.5*x*y - 0.2667*z]
See :ref:`example-circuits` for further examples.


API Docs
--------
Expand Down
28 changes: 28 additions & 0 deletions docs/example-circuits.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
.. _example-circuits:

Example circuits
================

This page collects example codes which mainly demonstrate the :ref:`lucipy-comp` machinery
but also touches other parts of the lucipy library.
Note that this are currently not nicely prepared examples
but more or less work benches demonstrating how to configure a circuit and to simulate it
numerically or run it on real LUCIDACs. If not noted otherwise, the example codes are working.


:download:`Rössler <../examples/roessler.py>`
Rössler attractor on LUCIDAC, as from
`Analog Paradigm Application Note 1 <https://analogparadigm.com/downloads/alpaca_1.pdf>`_.
Coincidentally, see this example in a very similar notation also in the several-years old
`PyAnalog FPAA YML <https://github.com/anabrid/pyanalog/blob/master/examples/fpaa-circuits/Alpaca01-Roessler-Attractor.yml>`_.

:download:`Lorenz <../examples/lorenz.py>`
Lorenz attractor on LUCIDAC, as from
`Analog Paradigm Application Note 2 <https://analogparadigm.com/downloads/alpaca_2.pdf>`_.

:download:`Hindmarsh-Rose <../examples/hindmarsh-rose-neuron.py>`
Single Spiking Neuron Model on LUCIDAC, as from
`Analog Paradigm Application Note 28 <https://analogparadigm.com/downloads/alpaca_28.pdf>`_.

We plan to show better examples as Jupyter Notebooks where one can see graphs, math, etc. all
on one page.
Loading

0 comments on commit b644f34

Please sign in to comment.