Skip to content

Commit

Permalink
Created devices package, cpp_standalone package, CPPStandaloneCodeObject
Browse files Browse the repository at this point in the history
  • Loading branch information
thesamovar committed Aug 19, 2013
1 parent 38f24b8 commit b8f17c9
Show file tree
Hide file tree
Showing 8 changed files with 217 additions and 0 deletions.
2 changes: 2 additions & 0 deletions brian2/codegen/_prefs.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
from .codeobject import CodeObject
from brian2.core.preferences import brian_prefs, BrianPreference

# Preferences
Expand All @@ -19,5 +20,6 @@
Or it can be a ``CodeObject`` class.
''',
validator=lambda target: isinstance(target, str) or issubclass(target, CodeObject),
),
)
Empty file added brian2/devices/__init__.py
Empty file.
4 changes: 4 additions & 0 deletions brian2/devices/cpp_standalone/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
from brian2.core.preferences import brian_prefs
from codeobject import CPPStandaloneCodeObject

brian_prefs['codegen.target'] = CPPStandaloneCodeObject
24 changes: 24 additions & 0 deletions brian2/devices/cpp_standalone/codeobject.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import os
import numpy

from brian2.codegen.codeobject import CodeObject
from brian2.codegen.templates import Templater
from brian2.codegen.languages.cpp_lang import CPPLanguage

__all__ = ['CPPStandaloneCodeObject']


class CPPStandaloneCodeObject(CodeObject):
'''
C++ standalone code object
The ``code`` should be a `~brian2.codegen.languages.templates.MultiTemplate`
object with two macros defined, ``main`` (for the main loop code) and
``support_code`` for any support code (e.g. function definitions).
'''
templater = Templater(os.path.join(os.path.split(__file__)[0],
'templates'))
language = CPPLanguage()

def run(self):
raise RuntimeError("Cannot run in C++ standalone mode")
40 changes: 40 additions & 0 deletions brian2/devices/cpp_standalone/templates/reset.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
////////////////////////////////////////////////////////////////////////////
//// MAIN CODE /////////////////////////////////////////////////////////////

{% macro main() %}
// USES_VARIABLES { _spikes }

////// HANDLE DENORMALS ///
{% for line in denormals_code_lines %}
{{line}}
{% endfor %}

////// HASH DEFINES ///////
{% for line in hashdefine_lines %}
{{line}}
{% endfor %}

///// POINTERS ////////////
{% for line in pointers_lines %}
{{line}}
{% endfor %}

//// MAIN CODE ////////////
for(int _index_spikes=0; _index_spikes<_num_spikes; _index_spikes++)
{
const int _idx = _spikes[_index_spikes];
const int _vectorisation_idx = _idx;
{% for line in code_lines %}
{{line}}
{% endfor %}
}
{% endmacro %}

////////////////////////////////////////////////////////////////////////////
//// SUPPORT CODE //////////////////////////////////////////////////////////

{% macro support_code() %}
{% for line in support_code_lines %}
{{line}}
{% endfor %}
{% endmacro %}
44 changes: 44 additions & 0 deletions brian2/devices/cpp_standalone/templates/stateupdate.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
////////////////////////////////////////////////////////////////////////////
//// MAIN CODE /////////////////////////////////////////////////////////////

{% macro main() %}

////// SUPPORT CODE ///
{% for line in support_code_lines %}
//{{line}}
{% endfor %}

////// HANDLE DENORMALS ///
{% for line in denormals_code_lines %}
{{line}}
{% endfor %}

////// HASH DEFINES ///////
{% for line in hashdefine_lines %}
{{line}}
{% endfor %}

///// POINTERS ////////////
{% for line in pointers_lines %}
{{line}}
{% endfor %}

//// MAIN CODE ////////////
for(int _idx=0; _idx<_num_idx; _idx++)
{
// THIS MESSAGE IS JUST TO LET YOU KNOW WE'RE IN THE STANDALONE NOT WEAVE TEMPLATE
const int _vectorisation_idx = _idx;
{% for line in code_lines %}
{{line}}
{% endfor %}
}
{% endmacro %}

////////////////////////////////////////////////////////////////////////////
//// SUPPORT CODE //////////////////////////////////////////////////////////

{% macro support_code() %}
{% for line in support_code_lines %}
{{line}}
{% endfor %}
{% endmacro %}
53 changes: 53 additions & 0 deletions brian2/devices/cpp_standalone/templates/threshold.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
////////////////////////////////////////////////////////////////////////////
//// MAIN CODE /////////////////////////////////////////////////////////////

{% macro main() %}
// USES_VARIABLES { not_refractory, lastspike, t, _spikespace }
////// SUPPORT CODE ///////
{% for line in support_code_lines %}
// {{line}}
{% endfor %}

////// HANDLE DENORMALS ///
{% for line in denormals_code_lines %}
{{line}}
{% endfor %}

////// HASH DEFINES ///////
{% for line in hashdefine_lines %}
{{line}}
{% endfor %}

///// POINTERS ////////////
{% for line in pointers_lines %}
{{line}}
{% endfor %}

//// MAIN CODE ////////////
long _cpp_numspikes = 0;
for(int _idx=0; _idx<_num_idx; _idx++)
{
const int _vectorisation_idx = _idx;
{% for line in code_lines %}
{{line}}
{% endfor %}
if(_cond) {
_spikespace[_cpp_numspikes++] = _idx;
// We have to use the pointer names directly here: The condition
// might contain references to not_refractory or lastspike and in
// that case the names will refer to a single entry.
_ptr{{_array_not_refractory}}[_idx] = false;
_ptr{{_array_lastspike}}[_idx] = t;
}
}
_spikespace[_num_idx] = _cpp_numspikes;
{% endmacro %}

////////////////////////////////////////////////////////////////////////////
//// SUPPORT CODE //////////////////////////////////////////////////////////

{% macro support_code() %}
{% for line in support_code_lines %}
// {{line}}
{% endfor %}
{% endmacro %}
50 changes: 50 additions & 0 deletions dev/ideas/devices/cpp_standalone.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
from numpy import *
from brian2 import *
from brian2.utils.stringtools import *
from brian2.codegen.languages.cpp_lang import *
from brian2.devices.cpp_standalone import *

##### Define the model
tau = 10*ms
eqs = '''
dV/dt = -V/tau : volt (unless-refractory)
'''
threshold = 'V>-50*mV'
reset = 'V=-60*mV'
refractory = 5*ms
groupname = 'gp'
N = 1000

##### Generate C++ code

# Use a NeuronGroup to fake the whole process
G = NeuronGroup(N, eqs, reset=reset, threshold=threshold,
refractory=refractory, name=groupname,
)
# Run the network for 0 seconds to generate the code
net = Network(G)
net.run(0*second)

# Extract the necessary information
ns = G.state_updater.codeobj.namespace
code = deindent(G.state_updater.codeobj.code.main)
arrays = []
# Freeze all constants
for k, v in ns.items():
if isinstance(v, float):
code = ('const double %s = %s;\n' % (k, repr(v)))+code
elif isinstance(v, int):
code = ('const int %s = %s;\n' % (k, repr(v)))+code
elif isinstance(v, ndarray):
if k.startswith('_array'):
dtype_spec = c_data_type(v.dtype)
arrays.append((k, dtype_spec, N))

print '*********** DECLARATIONS **********'
# This is just an example of what you could do with declarations, generate your
# own code here...
for varname, dtype_spec, N in arrays:
print '%s *%s = new %s [%s];' % (dtype_spec, varname, dtype_spec, N)

print '*********** MAIN LOOP *************'
print code

0 comments on commit b8f17c9

Please sign in to comment.