sPyNNaker neural_modelling  7.4.2
connection_generator_kernel.h
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2017 The University of Manchester
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * https://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
22 #include <stdbool.h>
26 
30 struct kernel {
31  // put in the relevant kernel connector parameters here
32  uint16_t commonWidth;
33  uint16_t commonHeight;
34 
36  uint16_t preWidth;
38  uint16_t preHeight;
40  uint16_t postWidth;
42  uint16_t postHeight;
43 
45  uint16_t startPreWidth;
47  uint16_t startPreHeight;
49  uint16_t startPostWidth;
51  uint16_t startPostHeight;
52 
54  uint16_t stepPreWidth;
56  uint16_t stepPreHeight;
58  uint16_t stepPostWidth;
60  uint16_t stepPostHeight;
61 
63  uint16_t kernelWidth;
65  uint16_t kernelHeight;
66 
68  uint16_t weightsPresent;
70  uint16_t delaysPresent;
71 
76 };
77 
85  struct kernel *params_sdram = *region;
86 
87  // Allocate the data structure for parameters
88  uint32_t kernelSize = params_sdram->kernelWidth * params_sdram->kernelHeight;
89  uint32_t size = sizeof(struct kernel);
90  uint32_t extra = 0;
91  if (params_sdram->weightsPresent) {
92  size += kernelSize * sizeof(accum);
93  extra += kernelSize;
94  }
95  if (params_sdram->delaysPresent) {
96  size += kernelSize * sizeof(accum);
97  extra += kernelSize;
98  }
99  struct kernel *obj = spin1_malloc(size);
100 
101  // Copy the parameters into the data structure
102  spin1_memcpy(obj, params_sdram, size);
103  *region = &(params_sdram->kernelWeightsAndDelays[extra]);
104 
105  log_debug("Kernel connector, m_kernelWidth, m_kernelHeight = %u %u",
106  obj->kernelWidth, obj->kernelHeight);
107 
108  return obj;
109 }
110 
115 static void connection_generator_kernel_free(void *generator) {
116  sark_free(generator);
117 }
118 
139  void *generator, uint32_t pre_lo, uint32_t pre_hi,
140  uint32_t post_lo, uint32_t post_hi, UNUSED uint32_t post_index,
141  uint32_t post_slice_start, uint32_t post_slice_count,
142  unsigned long accum weight_scale, accum timestep_per_delay,
143  param_generator_t weight_generator, param_generator_t delay_generator,
144  matrix_generator_t matrix_generator) {
145 
146  struct kernel *obj = generator;
147  uint16_t hlf_kw = obj->kernelWidth >> 1;
148  uint16_t hlf_kh = obj->kernelHeight >> 1;
149  int16_t k_r, k_c;
150  uint32_t k_offset = obj->kernelWidth * obj->kernelHeight;
151 
152  // Get the actual ranges to generate within
153  uint32_t post_start = max(post_slice_start, post_lo);
154  uint32_t post_end = min(post_slice_start + post_slice_count - 1, post_hi);
155 
156  // Go through and find the coordinates needed
157  for (uint32_t pre = pre_lo; pre <= pre_hi; pre++) {
158  uint16_t pre_c = 0;
159  uint16_t pre_r = uidiv(pre, obj->preWidth, &pre_c);
160  for (uint32_t post = post_start; post <= post_end; post++) {
161  uint16_t post_r, post_c; //post raw
162  uint16_t pac_r, pac_c; // post as common
163  int16_t pap_r, pap_c; // post as pre
164  post_r = uidiv(post, obj->postWidth, &post_c);
165 
166  //move post coordinates into common coordinate system
168  post_r, post_c, obj->startPostHeight, obj->startPostWidth,
169  obj->stepPostHeight, obj->stepPostWidth, &pac_r, &pac_c);
170 
171  //move common to pre coords
173  pac_r, pac_c, obj->startPreHeight, obj->startPreWidth,
174  obj->stepPreHeight, obj->stepPreWidth, &pap_r, &pap_c);
175 
176  int16_t r_diff = (int16_t) pap_r - (int16_t) pre_r;
177  int16_t c_diff = (int16_t) pap_c - (int16_t) pre_c;
178 
179  k_r = hlf_kh - r_diff;
180  k_c = hlf_kw - c_diff;
181 
182  if ((0 <= k_r) && (k_r < obj->kernelHeight) && (0 <= k_c)
183  && (k_c < obj->kernelWidth)) {
184  uint32_t local_post = post - post_slice_start;
185  accum weight;
186  accum delay;
187  uint32_t k = (k_r * obj->kernelWidth) + k_c;
188  if (obj->weightsPresent && obj->delaysPresent) {
189  weight = obj->kernelWeightsAndDelays[k];
190  delay = obj->kernelWeightsAndDelays[k + k_offset];
191  } else if (obj->weightsPresent) {
192  weight = obj->kernelWeightsAndDelays[k];
193  delay = param_generator_generate(delay_generator);
194  } else if (obj->delaysPresent) {
195  weight = param_generator_generate(weight_generator);
196  delay = obj->kernelWeightsAndDelays[k];
197  } else {
198  weight = param_generator_generate(weight_generator);
199  delay = param_generator_generate(delay_generator);
200  }
202  matrix_generator, pre, local_post,
203  weight, rescale_delay(delay, timestep_per_delay),
204  weight_scale)) {
205  log_error("Matrix size is wrong!");
206  return false;
207  }
208  }
209  }
210  }
211  return true;
212 }
void pre_in_post_world(uint16_t in_row, uint16_t in_col, uint16_t start_row, uint16_t start_col, uint16_t step_row, uint16_t step_col, int16_t *out_row, int16_t *out_col)
Get the pre's coordinates in the post's coordinate system.
Definition: common_kernel.c:49
uint16_t uidiv(uint32_t dividend, uint16_t divider, uint16_t *remainder)
Unsigned integer division.
Definition: common_kernel.c:29
void post_in_pre_world(uint16_t in_row, uint16_t in_col, uint16_t start_row, uint16_t start_col, uint16_t step_row, uint16_t step_col, uint16_t *out_row, uint16_t *out_col)
Get the post's coordinates in the pre's coordinate system.
Definition: common_kernel.c:41
Common functions for kernel generation.
Utility functions for working with memory.
uint16_t startPostWidth
Postpopulation grid X offset.
static void connection_generator_kernel_free(void *generator)
Free the convolution-kernel connection generator.
uint16_t preWidth
Prepopulation grid width.
uint16_t startPostHeight
Postpopulation grid Y offset.
uint16_t stepPostHeight
Postpopulation grid Y step.
uint16_t startPreWidth
Prepopulation grid X offset.
uint16_t startPreHeight
Prepopulation grid Y offset.
uint16_t delaysPresent
True if delays are present in the array below.
uint16_t kernelHeight
Convolution kernel grid height.
uint16_t weightsPresent
True if weights are present in the array below.
uint16_t stepPreHeight
Prepopulation grid Y step.
uint16_t stepPreWidth
Prepopulation grid X step.
uint16_t preHeight
Prepopulation grid height.
uint16_t postWidth
Postpopulation grid width.
static bool connection_generator_kernel_generate(void *generator, uint32_t pre_lo, uint32_t pre_hi, uint32_t post_lo, uint32_t post_hi, uint32_t post_index, uint32_t post_slice_start, uint32_t post_slice_count, unsigned long accum weight_scale, accum timestep_per_delay, param_generator_t weight_generator, param_generator_t delay_generator, matrix_generator_t matrix_generator)
Generate connections with the convolution-kernel connection generator.
static void * connection_generator_kernel_initialise(void **region)
Initialise the convolution-kernel connection generator.
uint16_t stepPostWidth
Postpopulation grid X step.
uint16_t kernelWidth
Convolution kernel grid width.
uint16_t postHeight
Postpopulation grid height.
accum kernelWeightsAndDelays[]
The parameters to be passed around for this connector.
General types associated with generators.
static uint16_t rescale_delay(accum delay, accum timestep_per_delay)
Rescales a delay to account for timesteps and type-converts it.
bool matrix_generator_write_synapse(matrix_generator_t generator, uint32_t pre_index, uint16_t post_index, accum weight, uint16_t delay, unsigned long accum weight_scale)
Write a synapse with a matrix generator.
The data for a matrix generator.
accum param_generator_generate(param_generator_t generator)
Generate value with a parameter generator.
region
spike source array region IDs in human readable form