GeNN  4.9.0
GPU enhanced Neuronal Networks (GeNN)
codeGenUtils.h
Go to the documentation of this file.
1 #pragma once
2 
3 // Standard includes
4 #include <algorithm>
5 #include <set>
6 #include <string>
7 #include <unordered_map>
8 #include <vector>
9 #include <regex>
10 
11 // GeNN includes
12 #include "gennExport.h"
13 #include "gennUtils.h"
14 #include "neuronGroupInternal.h"
15 #include "variableMode.h"
16 
17 // GeNN code generator includes
18 #include "backendBase.h"
19 #include "codeStream.h"
20 #include "substitutions.h"
21 #include "teeStream.h"
22 
23 //--------------------------------------------------------------------------
24 // CodeGenerator
25 //--------------------------------------------------------------------------
26 namespace CodeGenerator
27 {
28 //--------------------------------------------------------------------------
30 //--------------------------------------------------------------------------
31 GENN_EXPORT void substitute(std::string &s, const std::string &trg, const std::string &rep);
32 
33 //--------------------------------------------------------------------------
35 //--------------------------------------------------------------------------
36 GENN_EXPORT bool regexVarSubstitute(std::string &s, const std::string &trg, const std::string &rep);
37 
38 //--------------------------------------------------------------------------
40 //--------------------------------------------------------------------------
41 GENN_EXPORT bool regexFuncSubstitute(std::string &s, const std::string &trg, const std::string &rep);
42 
43 //--------------------------------------------------------------------------
53 //--------------------------------------------------------------------------
54 GENN_EXPORT void functionSubstitute(std::string &code, const std::string &funcName,
55  unsigned int numParams, const std::string &replaceFuncTemplate);
56 
58 inline size_t ceilDivide(size_t numerator, size_t denominator)
59 {
60  return ((numerator + denominator - 1) / denominator);
61 }
62 
64 inline size_t padSize(size_t size, size_t blockSize)
65 {
66  return ceilDivide(size, blockSize) * blockSize;
67 }
68 
69 GENN_EXPORT void genTypeRange(CodeStream &os, const std::string &precision, const std::string &prefix);
70 
71 //--------------------------------------------------------------------------
74 //--------------------------------------------------------------------------
75 GENN_EXPORT std::string ensureFtype(const std::string &oldcode, const std::string &type);
76 
77 //--------------------------------------------------------------------------
79 //--------------------------------------------------------------------------
80 GENN_EXPORT std::string getReductionInitialValue(const BackendBase &backend, VarAccessMode access, const std::string &type);
81 
82 //--------------------------------------------------------------------------
84 //--------------------------------------------------------------------------
85 GENN_EXPORT std::string getReductionOperation(const std::string &reduction, const std::string &value, VarAccessMode access, const std::string &type);
86 
87 //--------------------------------------------------------------------------
90 //--------------------------------------------------------------------------
91 GENN_EXPORT void checkUnreplacedVariables(const std::string &code, const std::string &codeName);
92 
93 //--------------------------------------------------------------------------
96  //--------------------------------------------------------------------------
97 GENN_EXPORT std::string disambiguateNamespaceFunction(const std::string supportCode, const std::string code, std::string namespaceName);
98 
99 //-------------------------------------------------------------------------
103 //-------------------------------------------------------------------------
104 template<typename P, typename D, typename V, typename S>
106  const std::string &delayOffset, const std::string &sourceSuffix, const std::string &destSuffix,
107  const std::string &varPrefix, const std::string &varSuffix, bool useLocalNeuronVars,
108  P isParamHeterogeneousFn, D isDerivedParamHeterogeneousFn, V getVarIndexFn, S getPrevSpikeTimeIndexFn)
109 {
110 
111  // Substitute spike times
112  const bool delay = archetypeNG->isDelayRequired();
113  const std::string spikeTimeVarIndex = getVarIndexFn(delay, VarAccessDuplication::DUPLICATE);
114  const std::string prevSpikeTimeVarIndex = getPrevSpikeTimeIndexFn(delay, VarAccessDuplication::DUPLICATE);
115  substitutions.addVarSubstitution("sT" + sourceSuffix,
116  "(" + delayOffset + varPrefix + "group->sT" + destSuffix + "[" + spikeTimeVarIndex + "]" + varSuffix + ")");
117  substitutions.addVarSubstitution("prev_sT" + sourceSuffix,
118  "(" + delayOffset + varPrefix + "group->prevST" + destSuffix + "[" + prevSpikeTimeVarIndex + "]" + varSuffix + ")");
119 
120  // Substitute spike-like-event times
121  substitutions.addVarSubstitution("seT" + sourceSuffix,
122  "(" + delayOffset + varPrefix + "group->seT" + destSuffix + "[" + spikeTimeVarIndex + "]" + varSuffix + ")");
123  substitutions.addVarSubstitution("prev_seT" + sourceSuffix,
124  "(" + delayOffset + varPrefix + "group->prevSET" + destSuffix + "[" + prevSpikeTimeVarIndex + "]" + varSuffix + ")");
125 
126  // Substitute neuron variables
127  const auto *nm = archetypeNG->getNeuronModel();
128  if(useLocalNeuronVars) {
129  substitutions.addVarNameSubstitution(nm->getVars(), sourceSuffix, "l");
130  }
131  else {
132  for(const auto &v : nm->getVars()) {
133  const std::string varIdx = getVarIndexFn(delay && archetypeNG->isVarQueueRequired(v.name),
134  getVarAccessDuplication(v.access));
135 
136  substitutions.addVarSubstitution(v.name + sourceSuffix,
137  varPrefix + "group->" + v.name + destSuffix + "[" + varIdx + "]" + varSuffix);
138  }
139  }
140 
141  // Substitute (potentially heterogeneous) parameters and derived parameters from neuron model
142  substitutions.addParamValueSubstitution(nm->getParamNames(), archetypeNG->getParams(), isParamHeterogeneousFn,
143  sourceSuffix, "group->", destSuffix);
144  substitutions.addVarValueSubstitution(nm->getDerivedParams(), archetypeNG->getDerivedParams(), isDerivedParamHeterogeneousFn,
145  sourceSuffix, "group->", destSuffix);
146 
147  // Substitute extra global parameters from neuron model
148  substitutions.addVarNameSubstitution(nm->getExtraGlobalParams(), sourceSuffix, "group->", destSuffix);
149 }
150 
151 template<typename G, typename K>
152 bool isKernelSizeHeterogeneous(const G *group, size_t dimensionIndex, K getKernelSizeFn)
153 {
154  // Get size of this kernel dimension for archetype
155  const unsigned archetypeValue = getKernelSizeFn(group->getArchetype()).at(dimensionIndex);
156 
157  // Return true if any of the other groups have a different value
158  return std::any_of(group->getGroups().cbegin(), group->getGroups().cend(),
159  [archetypeValue, dimensionIndex, getKernelSizeFn]
160  (const typename G::GroupInternal& g)
161  {
162  return (getKernelSizeFn(g).at(dimensionIndex) != archetypeValue);
163  });
164 }
165 
166 template<typename G, typename K>
167 std::string getKernelSize(const G *group, size_t dimensionIndex, K getKernelSizeFn)
168 {
169  // If kernel size if heterogeneous in this dimension, return group structure entry
170  if (isKernelSizeHeterogeneous(group, dimensionIndex, getKernelSizeFn)) {
171  return "group->kernelSize" + std::to_string(dimensionIndex);
172  }
173  // Otherwise, return literal
174  else {
175  return std::to_string(getKernelSizeFn(group->getArchetype()).at(dimensionIndex));
176  }
177 }
178 
179 template<typename G, typename K>
180 void genKernelIndex(const G *group, std::ostream &os, const CodeGenerator::Substitutions &subs,
181  K getKernelSizeFn)
182 {
183  // Loop through kernel dimensions to calculate array index
184  const auto &kernelSize = getKernelSizeFn(group->getArchetype());
185  for (size_t i = 0; i < kernelSize.size(); i++) {
186  os << "(" << subs["id_kernel_" + std::to_string(i)];
187  // Loop through remainining dimensions of kernel and multiply
188  for (size_t j = i + 1; j < kernelSize.size(); j++) {
189  os << " * " << getKernelSize(group, j, getKernelSizeFn);
190  }
191  os << ")";
192 
193  // If this isn't the last dimension, add +
194  if (i != (kernelSize.size() - 1)) {
195  os << " + ";
196  }
197  }
198 }
199 } // namespace CodeGenerator
GENN_EXPORT void checkUnreplacedVariables(const std::string &code, const std::string &codeName)
This function checks for unknown variable definitions and returns a gennError if any are found...
Definition: codeGenUtils.cc:513
Definition: neuronGroupInternal.h:9
VarAccessMode
Supported combination of VarAccessModeAttribute.
Definition: varAccess.h:19
bool isDelayRequired() const
Definition: neuronGroup.h:148
void genKernelIndex(const G *group, std::ostream &os, const CodeGenerator::Substitutions &subs, K getKernelSizeFn)
Definition: codeGenUtils.h:180
#define GENN_EXPORT
Definition: gennExport.h:13
GENN_EXPORT std::string disambiguateNamespaceFunction(const std::string supportCode, const std::string code, std::string namespaceName)
This function substitutes function names in a code with namespace as prefix of the function name for ...
Definition: codeGenUtils.cc:533
bool isVarQueueRequired(const std::string &var) const
Definition: neuronGroup.cc:480
Helper class for generating code - automatically inserts brackets, indents etc.
Definition: backendBase.h:30
Definition: codeStream.h:21
void addParamValueSubstitution(const std::vector< std::string > &paramNames, const std::vector< double > &values, const std::string &sourceSuffix="")
Definition: substitutions.cc:9
Definition: substitutions.h:21
GENN_EXPORT bool regexVarSubstitute(std::string &s, const std::string &trg, const std::string &rep)
Tool for substituting variable names in the neuron code strings or other templates using regular expr...
Definition: codeGenUtils.cc:211
void neuronSubstitutionsInSynapticCode(CodeGenerator::Substitutions &substitutions, const NeuronGroupInternal *archetypeNG, const std::string &delayOffset, const std::string &sourceSuffix, const std::string &destSuffix, const std::string &varPrefix, const std::string &varSuffix, bool useLocalNeuronVars, P isParamHeterogeneousFn, D isDerivedParamHeterogeneousFn, V getVarIndexFn, S getPrevSpikeTimeIndexFn)
Function for performing the code and value substitutions necessary to insert neuron related variables...
Definition: codeGenUtils.h:105
size_t ceilDivide(size_t numerator, size_t denominator)
Divide two integers, rounding up i.e. effectively taking ceil.
Definition: codeGenUtils.h:58
const NeuronModels::Base * getNeuronModel() const
Gets the neuron model used by this group.
Definition: neuronGroup.h:135
GENN_EXPORT void functionSubstitute(std::string &code, const std::string &funcName, unsigned int numParams, const std::string &replaceFuncTemplate)
This function substitutes function calls in the form:
Definition: codeGenUtils.cc:253
void addVarSubstitution(const std::string &source, const std::string &destionation, bool allowOverride=false)
Definition: substitutions.cc:25
Definition: backendBase.h:176
size_t padSize(size_t size, size_t blockSize)
Pad an integer to a multiple of another.
Definition: codeGenUtils.h:64
const std::vector< double > & getParams() const
Definition: neuronGroup.h:137
bool isKernelSizeHeterogeneous(const G *group, size_t dimensionIndex, K getKernelSizeFn)
Definition: codeGenUtils.h:152
void addVarValueSubstitution(const std::vector< T > &variables, const std::vector< double > &values, const std::string &sourceSuffix="")
Definition: substitutions.h:82
std::string getKernelSize(const G *group, size_t dimensionIndex, K getKernelSizeFn)
Definition: codeGenUtils.h:167
void addVarNameSubstitution(const std::vector< T > &variables, const std::string &sourceSuffix="", const std::string &destPrefix="", const std::string &destSuffix="")
Definition: substitutions.h:62
GENN_EXPORT std::string ensureFtype(const std::string &oldcode, const std::string &type)
This function implements a parser that converts any floating point constant in a code snippet to a fl...
Definition: codeGenUtils.cc:373
const std::vector< double > & getDerivedParams() const
Definition: neuronGroup.h:245
GENN_EXPORT bool regexFuncSubstitute(std::string &s, const std::string &trg, const std::string &rep)
Tool for substituting function names in the neuron code strings or other templates using regular expr...
Definition: codeGenUtils.cc:228
VarAccessDuplication getVarAccessDuplication(VarAccess type)
Definition: varAccess.h:79
GENN_EXPORT void genTypeRange(CodeStream &os, const std::string &precision, const std::string &prefix)
Definition: codeGenUtils.cc:344
GENN_EXPORT std::string getReductionInitialValue(const BackendBase &backend, VarAccessMode access, const std::string &type)
Get the initial value to start reduction operations from.
Definition: codeGenUtils.cc:470
GENN_EXPORT std::string getReductionOperation(const std::string &reduction, const std::string &value, VarAccessMode access, const std::string &type)
Generate a reduction operation to reduce value into reduction.
Definition: codeGenUtils.cc:486
GENN_EXPORT void substitute(std::string &s, const std::string &trg, const std::string &rep)
Tool for substituting strings in the neuron code strings or other templates.
Definition: codeGenUtils.cc:199