GeNN  4.9.0
GPU enhanced Neuronal Networks (GeNN)
stateVar.h
Go to the documentation of this file.
1 #pragma once
2 
3 // Standard C++ includes
4 #include <functional>
5 
6 // SpineML common includes
7 #include "spineMLLogging.h"
8 
9 //----------------------------------------------------------------------------
10 // SpineMLSimulator::StateVar
11 //----------------------------------------------------------------------------
12 namespace SpineMLSimulator
13 {
14 template <typename T>
15 class StateVar
16 {
17 public:
18  StateVar(const std::string &stateVarName, std::function<void*(const char*,bool)> getLibrarySymbolFunc)
19  {
20  // Get host statevar
21  T **hostStateVar = reinterpret_cast<T**>(getLibrarySymbolFunc(stateVarName.c_str(), true));
22 
23  // If there is no host statevar, it has probably been optimised away so isn't accesible
24  if(hostStateVar == nullptr) {
25  m_Access = Access::None;
26  }
27  // Otherwise
28  else {
29  LOGD_SPINEML << "\t" << stateVarName;
30 
31  // If there is a function to get the current state of variable
32  GetCurrentFunc getCurrentFunc = reinterpret_cast<GetCurrentFunc>(getLibrarySymbolFunc(("getCurrent" + stateVarName).c_str(), true));
33  if(getCurrentFunc) {
34  // Set access mode to indirect
35  m_Access = Access::Indirect;
36 
37  // Populate 'indirect' structure
38  m_Indirect.getFunc = getCurrentFunc;
39  m_Indirect.pushFunc = reinterpret_cast<PushCurrentFunc>(getLibrarySymbolFunc(("pushCurrent" + stateVarName + "ToDevice").c_str(), false));
40  m_PullFunc = reinterpret_cast<PullFunc>(getLibrarySymbolFunc(("pullCurrent" + stateVarName + "FromDevice").c_str(), false));
41 
42  LOGD_SPINEML << "\t\tIndirect with get function:" << m_Indirect.getFunc << ", push function:" << m_Indirect.pushFunc << ", pull function:" << m_PullFunc;
43  }
44  // Otherwise
45  else {
46  // Set access mode, to direct
47  m_Access = Access::Direct;
48 
49  // Populate 'direct' structure
50  m_Direct.hostStateVar = *hostStateVar;
51  m_Direct.pushFunc = reinterpret_cast<PushFunc>(getLibrarySymbolFunc(("push" + stateVarName + "ToDevice").c_str(), false));
52  m_PullFunc = reinterpret_cast<PullFunc>(getLibrarySymbolFunc(("pull" + stateVarName + "FromDevice").c_str(), false));
53 
54  LOGD_SPINEML << "\t\tDirect with host pointer:" << m_Direct.hostStateVar << ", push function:" << m_Direct.pushFunc << ", pull function:" << m_PullFunc;
55  }
56  }
57  }
58 
59  bool isAccessible() const{ return (m_Access != Access::None); }
60 
61  void push() const
62  {
63  if(m_Access == Access::Indirect) {
64  m_Indirect.pushFunc();
65  }
66  else if(m_Access == Access::Direct) {
67  m_Direct.pushFunc(false);
68  }
69  else {
70  throw std::runtime_error("Unable to push inaccessible variable");
71  }
72  }
73 
74  void pull() const
75  {
76  if(m_Access == Access::None) {
77  throw std::runtime_error("Unable to pull inaccessible variable");
78  }
79  else {
80  m_PullFunc();
81  }
82  }
83 
84  T *get()
85  {
86  if(m_Access == Access::Indirect) {
87  return m_Indirect.getFunc();
88  }
89  else if(m_Access == Access::Direct) {
90  return m_Direct.hostStateVar;
91  }
92  else {
93  throw std::runtime_error("Unable to get inaccessible variable");
94  }
95 
96  }
97  const T *get() const
98  {
99  if(m_Access == Access::Indirect) {
100  return m_Indirect.getFunc();
101  }
102  else if(m_Access == Access::Direct) {
103  return m_Direct.hostStateVar;
104  }
105  else {
106  throw std::runtime_error("Unable to get inaccessible variable");
107  }
108  }
109 
110 private:
111  //--------------------------------------------------------------------
112  // Typedefines
113  //--------------------------------------------------------------------
114  typedef T *(*GetCurrentFunc)(void);
115  typedef void (*PushFunc)(bool);
116  typedef void (*PullFunc)(void);
117  typedef void (*PushCurrentFunc)(void);
118 
119  //--------------------------------------------------------------------
120  // Enumerations
121  //--------------------------------------------------------------------
123  enum class Access
124  {
125  None,
126  Direct,
127  Indirect,
128  };
129 
130  //--------------------------------------------------------------------
131  // Indirect
132  //--------------------------------------------------------------------
135  struct Indirect
136  {
137  GetCurrentFunc getFunc;
138  PushCurrentFunc pushFunc;
139  };
140 
141  //--------------------------------------------------------------------
142  // Direct
143  //--------------------------------------------------------------------
146  struct Direct
147  {
148  T *hostStateVar;
149  PushFunc pushFunc;
150  };
151 
152  //--------------------------------------------------------------------
153  // Members
154  //--------------------------------------------------------------------
155  PullFunc m_PullFunc;
156  Access m_Access;
157 
158  union
159  {
160  Indirect m_Indirect;
161  Direct m_Direct;
162  };
163 };
164 } // namespace SpineMLSimulator
Definition: stateVar.h:15
void pull() const
Definition: stateVar.h:74
Direct m_Direct
Definition: stateVar.h:161
Indirect m_Indirect
Definition: stateVar.h:160
Definition: connectors.h:25
bool isAccessible() const
Definition: stateVar.h:59
StateVar(const std::string &stateVarName, std::function< void *(const char *, bool)> getLibrarySymbolFunc)
Definition: stateVar.h:18
void push() const
Definition: stateVar.h:61