def test_templates(): T1 = Templater('brian2.tests.test_templates.fake_package_1', env_globals={ 'f': lambda: 'F1', 'g': lambda: 'G1' }, extension='.txt') T2 = T1.derive('brian2.tests.test_templates.fake_package_2', env_globals={'f': lambda: 'F2'}) ns = {} for i, T in enumerate([T1, T2], start=1): for c in ['A', 'B', 'C', 'D']: ns[c + str(i)] = getattr(T, c)('', '') # for k, v in ns.items(): # print k, v assert 'A1' in ns['A1'] assert 'B1' in ns['A1'] assert 'F1' in ns['A1'] assert 'G1' in ns['A1'] assert 'A2' in ns['A2'] assert 'F2' in ns['A2'] assert 'G1' in ns['A2'] assert 'B1' not in ns['A2'] assert 'B1' in ns['B1'] assert 'B1' in ns['B2'] assert 'C1' in ns['C1'] assert 'D1' in ns['C1'] assert 'C1' in ns['C2'] assert 'D2' in ns['C2'] assert 'D1' not in ns['C2'] assert 'D1' in ns['D1'] assert 'D2' in ns['D2']
def test_templates(): T1 = Templater('brian2.tests.test_templates.fake_package_1', env_globals={'f': lambda: 'F1', 'g': lambda: 'G1'}, extension='.txt') T2 = T1.derive('brian2.tests.test_templates.fake_package_2', env_globals={'f': lambda: 'F2'}) ns = {} for i, T in enumerate([T1, T2], start=1): for c in ['A', 'B', 'C', 'D']: ns[c+str(i)] = getattr(T, c)('', '') # for k, v in ns.items(): # print k, v assert 'A1' in ns['A1'] assert 'B1' in ns['A1'] assert 'F1' in ns['A1'] assert 'G1' in ns['A1'] assert 'A2' in ns['A2'] assert 'F2' in ns['A2'] assert 'G1' in ns['A2'] assert 'B1' not in ns['A2'] assert 'B1' in ns['B1'] assert 'B1' in ns['B2'] assert 'C1' in ns['C1'] assert 'D1' in ns['C1'] assert 'C1' in ns['C2'] assert 'D2' in ns['C2'] assert 'D1' not in ns['C2'] assert 'D1' in ns['D1'] assert 'D2' in ns['D2']
class CUDAStandaloneCodeObject(CPPStandaloneCodeObject): ''' CUDA standalone code object The ``code`` should be a `~brian2.codegen.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('brian2cuda', '.cu', env_globals={ 'c_data_type': c_data_type, 'constant_or_scalar': constant_or_scalar }) generator_class = CUDACodeGenerator no_or_const_delay_mode = False serializing_form = "syn" runs_every_tick = True #default True, set False in generate_main_source rand_calls = 0 randn_calls = 0 def __call__(self, **kwds): return self.run() def run(self): get_device().main_queue.append(('run_code_object', (self, )))
class GeNNCodeObject(CodeObject): ''' Class of code objects that generate GeNN "code snippets" ''' templater = Templater('brian2genn', '.cpp', env_globals={'c_data_type': c_data_type, 'openmp_pragma': openmp_pragma, 'constant_or_scalar': constant_or_scalar}) generator_class = GeNNCodeGenerator
class CUDAStandaloneCodeObject(CPPStandaloneCodeObject): ''' CUDA standalone code object The ``code`` should be a `~brian2.codegen.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('brian2cuda', '.cu', env_globals={ 'c_data_type': c_data_type, 'constant_or_scalar': constant_or_scalar }) generator_class = CUDACodeGenerator def __init__(self, *args, **kwargs): super(CUDAStandaloneCodeObject, self).__init__(*args, **kwargs) # Whether this code object runs on a clock or only once. Default is True, set # False in `CUDAStandaloneDevice.generate_main_source()` self.runs_every_tick = True # Dictionary collectin the number of RNG function calls in this code object. # Keys are: "rand", "randn", "poisson-<idx>" with one <idx> for each `poisson` # with different (scalar) lambda self.rng_calls = defaultdict(int) # {name: lambda} dictionary for all poisson functions with scalar lambda # (these random numbers will be generated using the curand host side API) self.poisson_lamdas = defaultdict(float) # Whether this codeobject uses curand device API (for binomial functions or # poisson with vectorized lambda) and needs curand states self.needs_curand_states = False def __call__(self, **kwds): return self.run() def compile_block(self, block): pass # Compilation will be handled in device def run_block(self, block): if block == 'run': get_device().main_queue.append((block + '_code_object', (self, ))) else: # Check the C++ code whether there is anything to run cu_code = getattr(self.code, block + '_cu_file') if len(cu_code) and 'EMPTY_CODE_BLOCK' not in cu_code: get_device().main_queue.append( (block + '_code_object', (self, ))) self.before_after_blocks.append(block)
class CPPStandaloneCodeObject(CodeObject): ''' C++ standalone code object The ``code`` should be a `~brian2.codegen.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('brian2.devices.cpp_standalone', env_globals={'c_data_type': c_data_type}) generator_class = CPPCodeGenerator def __call__(self, **kwds): return self.run() def run(self): get_device().main_queue.append(('run_code_object', (self, )))
class CPPStandaloneCodeObject(CodeObject): ''' C++ standalone code object The ``code`` should be a `~brian2.codegen.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('brian2.devices.cpp_standalone', '.cpp', env_globals={ 'c_data_type': c_data_type, 'openmp_pragma': openmp_pragma, 'constant_or_scalar': constant_or_scalar, 'prefs': prefs, 'zip': zip }) generator_class = CPPCodeGenerator def __init__(self, *args, **kwds): super(CPPStandaloneCodeObject, self).__init__(*args, **kwds) #: Store whether this code object defines before/after blocks self.before_after_blocks = [] def __call__(self, **kwds): return self.run() def compile_block(self, block): pass # Compilation will be handled in device def run_block(self, block): if block == 'run': get_device().main_queue.append((block + '_code_object', (self, ))) else: # Check the C++ code whether there is anything to run cpp_code = getattr(self.code, block + '_cpp_file') if len(cpp_code) and 'EMPTY_CODE_BLOCK' not in cpp_code: get_device().main_queue.append( (block + '_code_object', (self, ))) self.before_after_blocks.append(block)
class GeNNCodeObject(CodeObject): ''' Class of code objects that generate GeNN "code snippets" ''' templater = Templater('brian2genn', '.cpp', env_globals={'c_data_type': c_data_type, 'openmp_pragma': openmp_pragma, 'constant_or_scalar': constant_or_scalar, 'zip': zip}) generator_class = GeNNCodeGenerator # Overwrite Brian2 methods, we do not need to compile/run anything here def compile(self): pass def before_run(self): pass def run(self): pass def after_run(self): pass