Skip to content
This repository was archived by the owner on Mar 20, 2023. It is now read-only.

Commit 543878e

Browse files
author
Omar Awile
authored
Added documentaiton for BBCOREPOINTER (#379)
1 parent 1fa5428 commit 543878e

File tree

2 files changed

+94
-0
lines changed

2 files changed

+94
-0
lines changed

docs/index.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ Welcome to CoreNEURON's documentation!
66
:caption: User documentation:
77

88
userdoc/BinaryFormat/BinaryFormat.md
9+
userdoc/MemoryManagement/bbcorepointer.md
910

1011
.. toctree::
1112
:maxdepth: 2
Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,93 @@
1+
2+
## Transferring dynamically allocated data between NEURON and CoreNEURON
3+
4+
5+
User-allocated data can be managed in NMODL using the `POINTER` type. It allows the
6+
programmer to reference data that has been allocated in HOC or in VERBATIM blocks. This
7+
allows for more advanced data-structures that are not natively supported in NMODL.
8+
9+
Since NEURON itself has no knowledge of the layout and size of this data it cannot
10+
transfer `POINTER` data automatically to CoreNEURON. Furtheremore, in many cases there
11+
is no need to transfer the data between the two instances. In some cases, however, the
12+
programmer would like to transfer certain user-defined data into CoreNEURON. The most
13+
prominent example are random123 RNG stream parameters used in synapse mechanisms. To
14+
support this use-case the `BBCOREPOINTER` type was introduced. Variables that are declared as
15+
`BBCOREPOINTER` behave exactly the same as `POINTER` but are additionally taken into account
16+
when NEURON is serializing mechanism data (for file writing or direct-memory transfer).
17+
For NEURON to be able to write (and indeed CoreNEURON to be able to read) `BBCOREPOINTER`
18+
data, the programmer has to additionally provide two C functions that are called as part
19+
of the serialization/deserialization.
20+
21+
```
22+
static void bbcore_write(double* x, int* d, int* d_offset, int* x_offset, _threadargsproto_);
23+
24+
static void bbcore_read(double* x, int* d, int* d_offset, int* x_offset, _threadargsproto_);
25+
```
26+
27+
The implementation of `bbcore_write` and `bbcore_read` determines the serialization and
28+
deserialization of the per-instance mechanism data referenced through the various
29+
`BBCOREPOINTER`s.
30+
31+
NEURON will call `bbcore_write` twice per mechanism instance. In a first sweep, the call is used to
32+
determine the required memory to be allocated on the serialization arrays. In the second sweep the
33+
call is used to fill in the data per mechanism instance.
34+
35+
The functions take following arguments
36+
37+
* `x`: A `double` type array that will be allocated by NEURON to fill with real-valued data. In the
38+
first call, `x` is NULL as it has not been allocated yet.
39+
* `d`: An `int` type array that will be allocated by NEURON to fill with integer-valued data. In the
40+
first call, `d` is NULL as it has not been allocated yet.
41+
* `x_offset`: The offset in `x` at which the mechanism instance should write its real-valued
42+
`BBCOREPOINTER` data. In the first call this is an output argument that is expected to be updated
43+
by the per-instance size to be allocated.
44+
* `d_offset`: The offset in `x` at which the mechanism instance should write its integer-valued
45+
`BBCOREPOINTER` data. In the first call this is an output argument that is expected to be updated
46+
by the per-instance size to be allocated.
47+
* `_threadargsproto_`: a macro placeholder for NEURON/CoreNEURON data-structure parameters. They
48+
are typically only used through generated defines and not by the programmer. The macro is defined
49+
as follows:
50+
51+
```
52+
#define _threadargsproto_ \
53+
int _iml, int _cntml_padded, double *_p, Datum *_ppvar, ThreadDatum *_thread, NrnThread *_nt, \
54+
double _v
55+
```
56+
57+
Putting all of this together, the following is a minimal MOD using BBCOREPOINTER:
58+
59+
```
60+
TITLE A BBCOREPOINTER Example
61+
62+
NEURON {
63+
BBCOREPOINTER my_data
64+
}
65+
66+
ASSIGNED {
67+
my_data
68+
}
69+
70+
: Do something interesting with my_data ...
71+
72+
VERBATIM
73+
static void bbcore_write(double* x, int* d, int* x_offset, int* d_offset, _threadargsproto_) {
74+
if (x) {
75+
double* x_i = x + *x_offset;
76+
x_i[0] = _p_my_data[0];
77+
x_i[1] = _p_my_data[1];
78+
}
79+
*x_offset += 2; // reserve 2 doubles on serialization buffer x
80+
}
81+
82+
static void bbcore_read(double* x, int* d, int* x_offset, int* d_offset, _threadargsproto_) {
83+
assert(!_p_my_data);
84+
double* x_i = x + *x_offset;
85+
// my_data needs to be allocated somehow
86+
_p_my_data = (double*)malloc(sizeof(double)*2);
87+
_p_my_data[0] = x_i[0];
88+
_p_my_data[1] = x_i[1];
89+
*x_offset += 2;
90+
}
91+
ENDVERBATIM
92+
```
93+

0 commit comments

Comments
 (0)