sPyNNaker neural_modelling 7.1.1
Loading...
Searching...
No Matches
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
30struct 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;
52
54 uint16_t stepPreWidth;
56 uint16_t stepPreHeight;
58 uint16_t stepPostWidth;
61
63 uint16_t kernelWidth;
65 uint16_t kernelHeight;
66
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
115static 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.
uint16_t uidiv(uint32_t dividend, uint16_t divider, uint16_t *remainder)
Unsigned integer division.
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.
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.
static void * connection_generator_kernel_initialise(void **region)
Initialise 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.
uint16_t stepPostWidth
Postpopulation grid X step.
uint16_t kernelWidth
Convolution kernel grid width.
uint16_t postHeight
Postpopulation grid height.
The parameters to be passed around for this connector.
void log_error(const char *message,...)
void log_debug(const char *message,...)
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.
void sark_free(void *ptr)
region
spike source array region IDs in human readable form
void spin1_memcpy(void *dst, void const *src, uint len)
#define min(a, b)