diff --git a/spynnaker/gsyn_tools.py b/spynnaker/gsyn_tools.py
index 6cbcf077b6e..80ec836511a 100644
--- a/spynnaker/gsyn_tools.py
+++ b/spynnaker/gsyn_tools.py
@@ -54,7 +54,7 @@ def check_sister_gysn(sister, n_neurons, runtime, gsyn):
""" Compare an arrays of conductances with baseline data from a file next\
to a specified module. For testing.
- :param sister: A module. The file read from will be ``gsyn.data`` \
+ :param sister: A module. The file read from will be ``gsyn.data``
adjacent to this module.
:param n_neurons: The number of neurons that produced the data.
:param runtime: The length of time that the generated data represents.
diff --git a/spynnaker/pyNN/abstract_spinnaker_common.py b/spynnaker/pyNN/abstract_spinnaker_common.py
index 1c55c489501..a029f488eb1 100644
--- a/spynnaker/pyNN/abstract_spinnaker_common.py
+++ b/spynnaker/pyNN/abstract_spinnaker_common.py
@@ -17,28 +17,44 @@
import math
import os
from six import with_metaclass
-
-from spinn_front_end_common.utilities.constants import \
- MICRO_TO_MILLISECOND_CONVERSION
from spinn_utilities.abstract_base import AbstractBase
from spinn_utilities.log import FormatAdapter
+from spinn_front_end_common.utilities.constants import (
+ MICRO_TO_MILLISECOND_CONVERSION)
from spinn_front_end_common.interface.abstract_spinnaker_base import (
AbstractSpinnakerBase)
from spinn_front_end_common.utilities.exceptions import ConfigurationException
from spinn_front_end_common.utility_models import CommandSender
from spinn_front_end_common.utilities.utility_objs import ExecutableFinder
-from spinn_front_end_common.utilities import globals_variables
+from spinn_front_end_common.utilities.globals_variables import unset_simulator
from spinn_front_end_common.utilities.helpful_functions import read_config
-from spynnaker.pyNN import extra_algorithms, model_binaries
-from spynnaker.pyNN.utilities import constants
+from spynnaker.pyNN.utilities.constants import (
+ MAX_DELAY_BLOCKS, MAX_SUPPORTED_DELAY_TICS,
+ MAX_TIMER_TICS_SUPPORTED_PER_BLOCK, MIN_SUPPORTED_DELAY)
from spynnaker.pyNN.spynnaker_simulator_interface import (
SpynnakerSimulatorInterface)
from spynnaker.pyNN.utilities.extracted_data import ExtractedData
from spynnaker import __version__ as version
+from spynnaker.pyNN.utilities.utility_calls import round_up
+from spynnaker.pyNN import model_binaries
logger = FormatAdapter(logging.getLogger(__name__))
+def _extra_algo_path():
+ """ List containing the names of the extra algorithms config files.
+
+ .. note::
+ Need to `import` within this to avoid an import loop.
+
+ :rtype: list(str)
+ """
+ import spynnaker.pyNN.extra_algorithms
+ return [os.path.join(
+ os.path.dirname(spynnaker.pyNN.extra_algorithms.__file__),
+ "algorithms_metadata.xml")]
+
+
class AbstractSpiNNakerCommon(with_metaclass(
AbstractBase, AbstractSpinnakerBase, SpynnakerSimulatorInterface)):
""" Main interface for neural code.
@@ -85,7 +101,7 @@ def __init__(
:param user_extra_algorithms_pre_run:
:type user_extra_algorithms_pre_run: list(str) or None
:param time_scale_factor:
- :type time_scale_factor:
+ :type time_scale_factor: int or None
:param extra_post_run_algorithms:
:type extra_post_run_algorithms: list(str) or None
:param extra_mapping_algorithms:
@@ -93,7 +109,7 @@ def __init__(
:param extra_load_algorithms:
:type extra_load_algorithms: list(str) or None
:param front_end_versions:
- :type front_end_versions:
+ :type front_end_versions: list(tuple(str,str)) or None
"""
# pylint: disable=too-many-arguments, too-many-locals
@@ -114,10 +130,7 @@ def __init__(
# create XML path for where to locate sPyNNaker related functions when
# using auto pause and resume
- extra_algorithm_xml_path = list()
- extra_algorithm_xml_path.append(os.path.join(
- os.path.dirname(extra_algorithms.__file__),
- "algorithms_metadata.xml"))
+ extra_algorithm_xml_path = _extra_algo_path()
if user_extra_algorithm_xml_path is not None:
extra_algorithm_xml_path.extend(user_extra_algorithm_xml_path)
@@ -238,7 +251,7 @@ def _set_up_timings(
self.set_up_timings(timestep, time_scale_factor)
else:
self.set_up_timings(
- math.ceil(timestep * MICRO_TO_MILLISECOND_CONVERSION),
+ round_up(timestep * MICRO_TO_MILLISECOND_CONVERSION),
time_scale_factor)
# Sort out the minimum delay
@@ -248,7 +261,7 @@ def _set_up_timings(
raise ConfigurationException(
"Pacman does not support min delays below {} ms with the "
"current machine time step".format(
- constants.MIN_SUPPORTED_DELAY * self.machine_time_step))
+ MIN_SUPPORTED_DELAY * self.machine_time_step))
if min_delay is not None:
self.__min_delay = min_delay
else:
@@ -256,11 +269,9 @@ def _set_up_timings(
self.machine_time_step / MICRO_TO_MILLISECOND_CONVERSION)
# Sort out the maximum delay
- natively_supported_delay_for_models = \
- constants.MAX_SUPPORTED_DELAY_TICS
+ natively_supported_delay_for_models = MAX_SUPPORTED_DELAY_TICS
delay_extension_max_supported_delay = (
- constants.MAX_DELAY_BLOCKS *
- constants.MAX_TIMER_TICS_SUPPORTED_PER_BLOCK)
+ MAX_DELAY_BLOCKS * MAX_TIMER_TICS_SUPPORTED_PER_BLOCK)
max_delay_tics_supported = \
natively_supported_delay_for_models + \
delay_extension_max_supported_delay
@@ -276,8 +287,7 @@ def _set_up_timings(
else:
self.__max_delay = (
max_delay_tics_supported * (
- self.machine_time_step /
- MICRO_TO_MILLISECOND_CONVERSION))
+ self.machine_time_step / MICRO_TO_MILLISECOND_CONVERSION))
# Sort out the time scale factor if not user specified
# (including config)
@@ -387,7 +397,6 @@ def stop(self, turn_off_machine=None, clear_routing_tables=None,
:param clear_tags: informs the tool chain if it should clear the tags
off the machine at stop
:type clear_tags: bool or None
- :rtype: None
"""
# pylint: disable=protected-access
for population in self._populations:
@@ -396,14 +405,13 @@ def stop(self, turn_off_machine=None, clear_routing_tables=None,
super(AbstractSpiNNakerCommon, self).stop(
turn_off_machine, clear_routing_tables, clear_tags)
self.reset_number_of_neurons_per_core()
- globals_variables.unset_simulator(self)
+ unset_simulator(self)
def run(self, run_time):
""" Run the model created.
:param run_time: the time (in milliseconds) to run the simulation for
:type run_time: float or int
- :rtype: None
"""
# pylint: disable=protected-access
@@ -428,7 +436,6 @@ def register_binary_search_path(search_path):
""" Register an additional binary search path for executables.
:param str search_path: absolute search path for binaries
- :rtype: None
"""
# pylint: disable=protected-access
AbstractSpiNNakerCommon.__EXECUTABLE_FINDER.add_path(search_path)
diff --git a/spynnaker/pyNN/connections/ethernet_control_connection.py b/spynnaker/pyNN/connections/ethernet_control_connection.py
index 320d8f3cc43..c74ab85be76 100644
--- a/spynnaker/pyNN/connections/ethernet_control_connection.py
+++ b/spynnaker/pyNN/connections/ethernet_control_connection.py
@@ -13,12 +13,9 @@
# You should have received a copy of the GNU General Public License
# along with this program. If not, see .
-import logging
from spinn_front_end_common.utility_models import MultiCastCommand
from spinn_front_end_common.utilities.connections import LiveEventConnection
-logger = logging.getLogger(__name__)
-
class EthernetControlConnection(LiveEventConnection):
""" A connection that can translate Ethernet control messages received\
diff --git a/spynnaker/pyNN/external_devices_models/__init__.py b/spynnaker/pyNN/external_devices_models/__init__.py
index 4d5871a8583..15eab73669e 100644
--- a/spynnaker/pyNN/external_devices_models/__init__.py
+++ b/spynnaker/pyNN/external_devices_models/__init__.py
@@ -17,7 +17,7 @@
from .abstract_ethernet_sensor import AbstractEthernetSensor
from .abstract_ethernet_translator import AbstractEthernetTranslator
from .abstract_multicast_controllable_device import (
- AbstractMulticastControllableDevice)
+ AbstractMulticastControllableDevice, SendType)
from .arbitrary_fpga_device import ArbitraryFPGADevice
from .external_device_lif_control import ExternalDeviceLifControl
from .external_spinnaker_link_cochlea_device import ExternalCochleaDevice
@@ -32,5 +32,5 @@
"AbstractEthernetTranslator", "ArbitraryFPGADevice",
"AbstractMulticastControllableDevice", "ExternalDeviceLifControl",
"ExternalCochleaDevice", "ExternalFPGARetinaDevice",
- "MunichMotorDevice", "MunichRetinaDevice",
+ "MunichMotorDevice", "MunichRetinaDevice", "SendType",
"ThresholdTypeMulticastDeviceControl"]
diff --git a/spynnaker/pyNN/external_devices_models/abstract_ethernet_translator.py b/spynnaker/pyNN/external_devices_models/abstract_ethernet_translator.py
index 45bb7846079..0e1c62bcddb 100644
--- a/spynnaker/pyNN/external_devices_models/abstract_ethernet_translator.py
+++ b/spynnaker/pyNN/external_devices_models/abstract_ethernet_translator.py
@@ -33,5 +33,4 @@ def translate_control_packet(self, multicast_packet):
:param multicast_packet: A received multicast packet
:type multicast_packet:
~spinnman.messages.eieio.data_messages.AbstractEIEIODataElement
- :rtype: None
"""
diff --git a/spynnaker/pyNN/external_devices_models/external_device_lif_control.py b/spynnaker/pyNN/external_devices_models/external_device_lif_control.py
index 7aaec28d7f0..baaaff54372 100644
--- a/spynnaker/pyNN/external_devices_models/external_device_lif_control.py
+++ b/spynnaker/pyNN/external_devices_models/external_device_lif_control.py
@@ -13,12 +13,11 @@
# You should have received a copy of the GNU General Public License
# along with this program. If not, see .
-import logging
from spinn_utilities.overrides import overrides
from spinn_front_end_common.utilities.exceptions import ConfigurationException
from spynnaker.pyNN.models.neuron import AbstractPyNNNeuronModelStandard
-from spynnaker.pyNN.models.defaults import default_initial_values,\
- default_parameters
+from spynnaker.pyNN.models.defaults import (
+ default_initial_values, default_parameters)
from spynnaker.pyNN.models.neuron.input_types import InputTypeCurrent
from spynnaker.pyNN.models.neuron.neuron_models import (
NeuronModelLeakyIntegrateAndFire)
@@ -27,8 +26,6 @@
from .threshold_type_multicast_device_control import (
ThresholdTypeMulticastDeviceControl)
-logger = logging.getLogger(__name__)
-
class ExternalDeviceLifControl(AbstractPyNNNeuronModelStandard):
""" Abstract control module for the PushBot, based on the LIF neuron,\
diff --git a/spynnaker/pyNN/external_devices_models/external_device_lif_control_vertex.py b/spynnaker/pyNN/external_devices_models/external_device_lif_control_vertex.py
index 34c6ae6e234..8b7977c276a 100644
--- a/spynnaker/pyNN/external_devices_models/external_device_lif_control_vertex.py
+++ b/spynnaker/pyNN/external_devices_models/external_device_lif_control_vertex.py
@@ -14,7 +14,6 @@
# along with this program. If not, see .
from collections import OrderedDict
-import logging
from spinn_utilities.overrides import overrides
from pacman.model.constraints.key_allocator_constraints import (
FixedKeyAndMaskConstraint)
@@ -26,8 +25,6 @@
from spynnaker.pyNN.models.neuron import AbstractPopulationVertex
from .abstract_ethernet_controller import AbstractEthernetController
-logger = logging.getLogger(__name__)
-
class ExternalDeviceLifControlVertex(
AbstractPopulationVertex,
diff --git a/spynnaker/pyNN/external_devices_models/external_spinnaker_link_fpga_retina_device.py b/spynnaker/pyNN/external_devices_models/external_spinnaker_link_fpga_retina_device.py
index 2855636d2a7..f4e775fb65b 100644
--- a/spynnaker/pyNN/external_devices_models/external_spinnaker_link_fpga_retina_device.py
+++ b/spynnaker/pyNN/external_devices_models/external_spinnaker_link_fpga_retina_device.py
@@ -12,8 +12,6 @@
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see .
-
-import logging
from spinn_utilities.overrides import overrides
from pacman.model.constraints.key_allocator_constraints import (
FixedKeyAndMaskConstraint)
@@ -28,8 +26,6 @@
from spinn_front_end_common.utility_models import MultiCastCommand
from spynnaker.pyNN.exceptions import SpynnakerException
-logger = logging.getLogger(__name__)
-
def get_y_from_fpga_retina(key, mode):
if mode == 128:
diff --git a/spynnaker/pyNN/external_devices_models/munich_spinnaker_link_motor_device.py b/spynnaker/pyNN/external_devices_models/munich_spinnaker_link_motor_device.py
index 81bc0e15856..0cfe3d8e376 100644
--- a/spynnaker/pyNN/external_devices_models/munich_spinnaker_link_motor_device.py
+++ b/spynnaker/pyNN/external_devices_models/munich_spinnaker_link_motor_device.py
@@ -13,7 +13,6 @@
# You should have received a copy of the GNU General Public License
# along with this program. If not, see .
-import logging
from spinn_utilities.overrides import overrides
from pacman.executor.injection_decorator import inject_items
from pacman.model.constraints.key_allocator_constraints import (
@@ -36,7 +35,6 @@
from spynnaker.pyNN.exceptions import SpynnakerException
from spynnaker.pyNN.models.defaults import defaults
-logger = logging.getLogger(__name__)
MOTOR_PARTITION_ID = "MOTOR"
diff --git a/spynnaker/pyNN/external_devices_models/push_bot/abstract_push_bot_output_device.py b/spynnaker/pyNN/external_devices_models/push_bot/abstract_push_bot_output_device.py
index 822edc2ad97..0e03de73860 100644
--- a/spynnaker/pyNN/external_devices_models/push_bot/abstract_push_bot_output_device.py
+++ b/spynnaker/pyNN/external_devices_models/push_bot/abstract_push_bot_output_device.py
@@ -14,8 +14,7 @@
# along with this program. If not, see .
from enum import Enum
-from spynnaker.pyNN.external_devices_models\
- .abstract_multicast_controllable_device import SendType
+from spynnaker.pyNN.external_devices_models import SendType
class AbstractPushBotOutputDevice(Enum):
diff --git a/spynnaker/pyNN/external_devices_models/push_bot/push_bot_control_modules/push_bot_lif_ethernet.py b/spynnaker/pyNN/external_devices_models/push_bot/push_bot_control_modules/push_bot_lif_ethernet.py
index a51f02d0f15..54c46d2e080 100644
--- a/spynnaker/pyNN/external_devices_models/push_bot/push_bot_control_modules/push_bot_lif_ethernet.py
+++ b/spynnaker/pyNN/external_devices_models/push_bot/push_bot_control_modules/push_bot_lif_ethernet.py
@@ -16,11 +16,8 @@
from spynnaker.pyNN.models.defaults import default_initial_values
from spynnaker.pyNN.external_devices_models.push_bot.push_bot_ethernet \
import (
- PushBotTranslator)
+ PushBotTranslator, get_pushbot_wifi_connection)
from spynnaker.pyNN.external_devices_models import ExternalDeviceLifControl
-from spynnaker.pyNN.external_devices_models.push_bot.push_bot_ethernet \
- import (
- get_pushbot_wifi_connection)
class PushBotLifEthernet(ExternalDeviceLifControl):
diff --git a/spynnaker/pyNN/external_devices_models/push_bot/push_bot_control_modules/push_bot_lif_spinnaker_link.py b/spynnaker/pyNN/external_devices_models/push_bot/push_bot_control_modules/push_bot_lif_spinnaker_link.py
index 737abdd1d76..7e5e6d6245f 100644
--- a/spynnaker/pyNN/external_devices_models/push_bot/push_bot_control_modules/push_bot_lif_spinnaker_link.py
+++ b/spynnaker/pyNN/external_devices_models/push_bot/push_bot_control_modules/push_bot_lif_spinnaker_link.py
@@ -12,14 +12,10 @@
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see .
-
-import logging
from spynnaker.pyNN.external_devices_models import ExternalDeviceLifControl
from spynnaker.pyNN.protocols import MunichIoSpiNNakerLinkProtocol
from spynnaker.pyNN.models.defaults import default_initial_values
-logger = logging.getLogger(__name__)
-
class PushBotLifSpinnakerLink(ExternalDeviceLifControl):
""" Control module for a PushBot connected to a SpiNNaker Link
diff --git a/spynnaker/pyNN/external_devices_models/push_bot/push_bot_ethernet/push_bot_retina_connection.py b/spynnaker/pyNN/external_devices_models/push_bot/push_bot_ethernet/push_bot_retina_connection.py
index fe016e1f7f3..da2ce6c4f49 100644
--- a/spynnaker/pyNN/external_devices_models/push_bot/push_bot_ethernet/push_bot_retina_connection.py
+++ b/spynnaker/pyNN/external_devices_models/push_bot/push_bot_ethernet/push_bot_retina_connection.py
@@ -12,8 +12,6 @@
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see .
-
-import logging
from threading import RLock
import numpy
from spinnman.connections import ConnectionListener
@@ -23,7 +21,6 @@
import (
PushBotRetinaResolution)
-logger = logging.getLogger(__name__)
_RETINA_PACKET_SIZE = BYTES_PER_SHORT
diff --git a/spynnaker/pyNN/external_devices_models/push_bot/push_bot_ethernet/push_bot_wifi_connection.py b/spynnaker/pyNN/external_devices_models/push_bot/push_bot_ethernet/push_bot_wifi_connection.py
index 14508dcf37c..48e23f5d395 100644
--- a/spynnaker/pyNN/external_devices_models/push_bot/push_bot_ethernet/push_bot_wifi_connection.py
+++ b/spynnaker/pyNN/external_devices_models/push_bot/push_bot_ethernet/push_bot_wifi_connection.py
@@ -14,11 +14,11 @@
# along with this program. If not, see .
import logging
-import platform
import select
import socket
-import subprocess
from six import raise_from
+from spinn_utilities.overrides import overrides
+from spinn_utilities.ping import Ping
from spinnman.connections.abstract_classes import Listenable, Connection
from spinnman.exceptions import SpinnmanIOException, SpinnmanTimeoutException
from spinn_front_end_common.utilities.constants import BYTES_PER_KB
@@ -102,28 +102,9 @@ def __init__(self, remote_host, remote_port=56000):
# Set a general timeout on the socket
self.__socket.settimeout(0)
+ @overrides(Connection.is_connected)
def is_connected(self):
- """ See\
- :py:meth:`~spinnman.connections.Connection.is_connected`
- """
- if platform.platform().lower().startswith("windows"):
- cmd_args = "-n 1 -w 1"
- else:
- cmd_args = "-c 1 -W 1"
-
- # check if machine is active and on the network
- for _ in range(5): # Try up to five times...
- # Start a ping process
- process = subprocess.Popen(
- "ping " + cmd_args + " " + self.__remote_ip_address,
- shell=True, stdout=subprocess.PIPE)
- process.wait()
- if process.returncode == 0:
- # ping worked
- return True
-
- # If the ping fails this number of times, the host cannot be contacted
- return False
+ return Ping.host_is_reachable(self.__remote_ip_address)
@property
def local_ip_address(self):
@@ -190,18 +171,18 @@ def send(self, data):
except Exception as e: # pylint: disable=broad-except
raise_from(SpinnmanIOException(str(e)), e)
+ @overrides(Connection.close)
def close(self):
- """ See\
- :py:meth:`spinnman.connections.Connection.close`
- """
try:
self.__socket.shutdown(socket.SHUT_WR)
except Exception: # pylint: disable=broad-except
pass
self.__socket.close()
+ @overrides(Listenable.is_ready_to_receive, extend_defaults=True)
def is_ready_to_receive(self, timeout=0):
return bool(select.select([self.__socket], [], [], timeout)[0])
+ @overrides(Listenable.get_receive_method)
def get_receive_method(self):
return self.receive
diff --git a/spynnaker/pyNN/external_devices_models/push_bot/push_bot_spinnaker_link/push_bot_spinnaker_link_retina_device.py b/spynnaker/pyNN/external_devices_models/push_bot/push_bot_spinnaker_link/push_bot_spinnaker_link_retina_device.py
index dd583c6ab58..77d25a060a4 100644
--- a/spynnaker/pyNN/external_devices_models/push_bot/push_bot_spinnaker_link/push_bot_spinnaker_link_retina_device.py
+++ b/spynnaker/pyNN/external_devices_models/push_bot/push_bot_spinnaker_link/push_bot_spinnaker_link_retina_device.py
@@ -12,8 +12,6 @@
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see .
-
-import logging
from spinn_utilities.overrides import overrides
from pacman.executor.injection_decorator import inject, supports_injection
from pacman.model.graphs.application import ApplicationSpiNNakerLinkVertex
@@ -21,8 +19,6 @@
from spynnaker.pyNN.external_devices_models.push_bot import (
AbstractPushBotRetinaDevice)
-logger = logging.getLogger(__name__)
-
@supports_injection
class PushBotSpiNNakerLinkRetinaDevice(
@@ -36,15 +32,12 @@ def __init__(
board_address=default_parameters['board_address'],
label=default_parameters['label']):
"""
- :param spinnaker_link_id:
- :param protocol:
- :type protocol: MunichIoSpiNNakerLinkProtocol
- :param resolution:
- :type resolution: PushBotRetinaResolution
- :param board_address:
- :param label:
+ :param int spinnaker_link_id:
+ :param MunichIoSpiNNakerLinkProtocol protocol:
+ :param PushBotRetinaResolution resolution:
+ :param str board_address:
+ :param str label:
"""
-
AbstractPushBotRetinaDevice.__init__(self, protocol, resolution)
ApplicationSpiNNakerLinkVertex.__init__(
self, spinnaker_link_id=spinnaker_link_id,
diff --git a/spynnaker/pyNN/extra_algorithms/graph_edge_filter.py b/spynnaker/pyNN/extra_algorithms/graph_edge_filter.py
index 3c3b16ef6b6..88ca48c670b 100644
--- a/spynnaker/pyNN/extra_algorithms/graph_edge_filter.py
+++ b/spynnaker/pyNN/extra_algorithms/graph_edge_filter.py
@@ -33,9 +33,10 @@ def __call__(self, app_graph, machine_graph):
:param app_graph: The application graph
:type app_graph:
~pacman.model.graphs.application.ApplicationGraph or None
- :param .MachineGraph machine_graph:
+ :param ~pacman.model.graphs.machine.MachineGraph machine_graph:
The machine_graph whose edges are to be filtered
:return: a new, filtered machine graph
+ :rtype: ~pacman.model.graphs.machine.MachineGraph
"""
new_machine_graph = MachineGraph(
label=machine_graph.label, application_graph=app_graph)
@@ -57,10 +58,10 @@ def __call__(self, app_graph, machine_graph):
for partition in progress.over(machine_graph.outgoing_edge_partitions):
for edge in partition.edges:
if self._is_filterable(edge):
- logger.debug("this edge was pruned {}", edge)
+ logger.debug("this edge was pruned: {}", edge)
prune_count += 1
continue
- logger.debug("this edge was not pruned {}", edge)
+ logger.debug("this edge was not pruned: {}", edge)
no_prune_count += 1
self._add_edge_to_new_graph(edge, partition, new_machine_graph)
@@ -73,9 +74,9 @@ def __call__(self, app_graph, machine_graph):
@staticmethod
def _add_edge_to_new_graph(edge, partition, new_graph):
"""
- :param .MachineEdge edge:
- :param .OutgoingEdgePartition partition:
- :param .MachineGraph new_graph:
+ :param ~.MachineEdge edge:
+ :param ~.OutgoingEdgePartition partition:
+ :param ~.MachineGraph new_graph:
"""
new_graph.add_edge(edge, partition.identifier)
edge.associate_application_edge()
@@ -90,16 +91,18 @@ def _add_edge_to_new_graph(edge, partition, new_graph):
@staticmethod
def _is_filterable(edge):
"""
- :param .MachineEdge edge:
+ :param ~.MachineEdge edge:
:rtype: bool
"""
# If our associated application edge wants to say don't filter...
if (isinstance(edge.app_edge, AbstractFilterableEdge)
and not edge.app_edge.filter_edge()):
return False
+
if isinstance(edge, AbstractFilterableEdge):
return edge.filter_edge()
elif isinstance(edge.app_edge, ApplicationEdge):
return False
+ # Bad graph construction?
raise FilterableException(
"cannot figure out if edge {} is prunable or not".format(edge))
diff --git a/spynnaker/pyNN/extra_algorithms/graph_edge_weight_updater.py b/spynnaker/pyNN/extra_algorithms/graph_edge_weight_updater.py
index 5c19d9a890c..03529c2a762 100644
--- a/spynnaker/pyNN/extra_algorithms/graph_edge_weight_updater.py
+++ b/spynnaker/pyNN/extra_algorithms/graph_edge_weight_updater.py
@@ -13,12 +13,9 @@
# You should have received a copy of the GNU General Public License
# along with this program. If not, see .
-import logging
from spinn_utilities.progress_bar import ProgressBar
from spynnaker.pyNN.models.abstract_models import AbstractWeightUpdatable
-logger = logging.getLogger(__name__)
-
class GraphEdgeWeightUpdater(object):
""" Updates the weights of all edges.
@@ -26,9 +23,10 @@ class GraphEdgeWeightUpdater(object):
def __call__(self, machine_graph):
"""
- :param machine_graph: the machine_graph whose edges are to be updated
+ :param ~pacman.model.graphs.machine.MachineGraph machine_graph:
+ the machine_graph whose edges are to be updated
+ :rtype: ~pacman.model.graphs.machine.MachineGraph
"""
-
# create progress bar
progress = ProgressBar(
machine_graph.n_outgoing_edge_partitions,
diff --git a/spynnaker/pyNN/extra_algorithms/on_chip_bit_field_generator.py b/spynnaker/pyNN/extra_algorithms/on_chip_bit_field_generator.py
index 1b02cfd1e03..854705a7384 100644
--- a/spynnaker/pyNN/extra_algorithms/on_chip_bit_field_generator.py
+++ b/spynnaker/pyNN/extra_algorithms/on_chip_bit_field_generator.py
@@ -13,44 +13,62 @@
# You should have received a copy of the GNU General Public License
# along with this program. If not, see .
-import math
-import struct
-import logging
-import os
from collections import defaultdict
-
-from spinn_front_end_common.abstract_models import \
- AbstractSupportsBitFieldGeneration
-from spinn_front_end_common.utilities import system_control_logic
+import os
+import struct
+from spinn_utilities.progress_bar import ProgressBar
+from spinnman.model import ExecutableTargets
+from spinnman.model.enums import CPUState
+from spinn_front_end_common.abstract_models import (
+ AbstractSupportsBitFieldGeneration)
+from spinn_front_end_common.utilities.system_control_logic import (
+ run_system_application)
from spinn_front_end_common.utilities.constants import BYTES_PER_WORD
from spinn_front_end_common.utilities.utility_objs import ExecutableType
+from spynnaker.pyNN.utilities.constants import BITS_PER_WORD
-from spinn_utilities.progress_bar import ProgressBar
+_ONE_WORD = struct.Struct("> bit_in_word) & self._BIT_MASK
+ word_id, bit_in_word = divmod(neuron_id, BITS_PER_WORD)
+ flag = (bit_field[word_id] >> bit_in_word) & cls._BIT_MASK
return flag
- def _calculate_core_data(
- self, app_graph, placements, progress,
- executable_finder, transceiver):
+ def _calculate_core_data(self, app_graph, progress):
""" gets the data needed for the bit field expander for the machine
- :param app_graph: app graph
- :param placements: placements
- :param progress: progress bar
- :param executable_finder: where to find the executable
- :param transceiver: spinnman instance
+ :param ~.ApplicationGraph app_graph: app graph
+ :param ~.ProgressBar progress: progress bar
:return: data and expander cores
+ :rtype: ExecutableTargets
"""
-
# cores to place bitfield expander
expander_cores = ExecutableTargets()
- # bit field expander executable file path
- bit_field_expander_path = executable_finder.get_executable_path(
- self._BIT_FIELD_EXPANDER_APLX)
-
# locate verts which can have a synaptic matrix to begin with
for app_vertex in progress.over(app_graph.vertices, False):
- for machine_vertex in app_vertex.machine_vertices:
- if (isinstance(
- machine_vertex, AbstractSupportsBitFieldGeneration)):
- self.__write_single_core_data(
- machine_vertex, placements, transceiver,
- bit_field_expander_path, expander_cores)
+ for placement in self.__bitfield_placements(app_vertex):
+ self.__write_single_core_data(placement, expander_cores)
return expander_cores
- def __write_single_core_data(
- self, vertex, placements, transceiver, bit_field_expander_path,
- expander_cores):
- placement = placements.get_placement_of_vertex(vertex)
-
+ def __write_single_core_data(self, placement, expander_cores):
+ """
+ :param ~.Placement placement:
+ The vertex must support AbstractSupportsBitFieldGeneration
+ :param ~.ExecutableTargets expander_cores:
+ """
# check if the chip being considered already.
expander_cores.add_processor(
- bit_field_expander_path, placement.x, placement.y,
- placement.p, executable_type=ExecutableType.SYSTEM)
+ self.__binary, placement.x, placement.y, placement.p,
+ executable_type=ExecutableType.SYSTEM)
- bit_field_builder_region = vertex.bit_field_builder_region(
- transceiver, placement)
+ bit_field_builder_region = placement.vertex.bit_field_builder_region(
+ self.__transceiver, placement)
# update user 1 with location
user_1_base_address = \
- transceiver.get_user_1_register_address_from_core(placement.p)
- transceiver.write_memory(
+ self.__transceiver.get_user_1_register_address_from_core(
+ placement.p)
+ self.__transceiver.write_memory(
placement.x, placement.y, user_1_base_address,
- self._ONE_WORDS.pack(bit_field_builder_region),
- self._USER_BYTES)
+ _ONE_WORD.pack(bit_field_builder_region), _ONE_WORD.size)
- def _check_for_success(self, executable_targets, transceiver):
- """ Goes through the cores checking for cores that have failed to\
- expand the bitfield to the core
- :param executable_targets: cores to load bitfield on
- :param transceiver: SpiNNMan instance
- :rtype: None
- """
+def _check_for_success(executable_targets, transceiver):
+ """ Goes through the cores checking for cores that have failed to\
+ expand the bitfield to the core
- for core_subset in executable_targets.all_core_subsets:
- x = core_subset.x
- y = core_subset.y
- for p in core_subset.processor_ids:
- # Read the result from USER0 register
- user_2_base_address = \
- transceiver.get_user_2_register_address_from_core(p)
- result = struct.unpack(
- ".
+from collections import defaultdict
import os
import logging
-from collections import defaultdict
-
from spinn_utilities.log import FormatAdapter
from spynnaker.pyNN.models.neuron import PopulationMachineVertex
@@ -24,10 +23,30 @@
class RedundantPacketCountReport(object):
+ """ Reports how many packets were filtered by the packet filtering.
+
+ :param provenance_items:
+ the collected provenance
+ :type provenance_items:
+ list(~spinn_front_end_common.utilities.utility_objs.ProvenanceDataItem)
+ :param str report_default_directory: where to write reports
+ """
+ # The name of the report we create
_FILE_NAME = "redundant_packet_count.rpt"
+ # The provenance items we care about for a vertex
+ _RELEVANT = frozenset([
+ PopulationMachineVertex.GHOST_SEARCHES,
+ PopulationMachineVertex.BIT_FIELD_FILTERED_PACKETS,
+ PopulationMachineVertex.INVALID_MASTER_POP_HITS,
+ PopulationMachineVertex.SPIKES_PROCESSED])
+
def __call__(self, provenance_items, report_default_directory):
+ """
+ :param list(~.ProvenanceDataItem) provenance_items:
+ :param str report_default_directory:
+ """
file_name = os.path.join(report_default_directory, self._FILE_NAME)
try:
@@ -37,67 +56,48 @@ def __call__(self, provenance_items, report_default_directory):
logger.exception("Generate_placement_reports: Can't open file"
" {} for writing.", self._FILE_NAME)
- @staticmethod
- def _write_report(output, provenance_items):
+ def _write_report(self, output, provenance_items):
data = defaultdict(dict)
-
for provenance_item in provenance_items:
last_name = provenance_item.names[-1]
key = provenance_item.names[0]
- if ((last_name == PopulationMachineVertex.GHOST_SEARCHES) or
- (last_name ==
- PopulationMachineVertex.BIT_FIELD_FILTERED_PACKETS) or
- (last_name ==
- PopulationMachineVertex.INVALID_MASTER_POP_HITS) or
- (last_name == PopulationMachineVertex.SPIKES_PROCESSED)):
-
+ if last_name in self._RELEVANT:
# add to store
data[key][last_name] = provenance_item.value
-
# accum enough data on a core to do summary
- if len(data[key].keys()) == 4:
-
- # total packets received
- total = (
- data[key][PopulationMachineVertex.GHOST_SEARCHES] +
- data[key][
- PopulationMachineVertex.
- BIT_FIELD_FILTERED_PACKETS] +
- data[key][
- PopulationMachineVertex.INVALID_MASTER_POP_HITS] +
- data[key][PopulationMachineVertex.SPIKES_PROCESSED])
+ if len(data[key]) == len(self._RELEVANT):
+ self.__write_core_summary(key, data[key], output)
- # total redundant packets
- redundant = (
- data[key][PopulationMachineVertex.GHOST_SEARCHES] +
- data[key][
- PopulationMachineVertex.
- BIT_FIELD_FILTERED_PACKETS] +
- data[key][
- PopulationMachineVertex.INVALID_MASTER_POP_HITS])
-
- percentage = 0
- if total != 0:
- percentage = (100.0 / total) * redundant
-
- output.write(
- "core {} \n\n"
- " {} packets received.\n"
- " {} were detected as redundant packets by the "
- "bitfield filter.\n"
- " {} were detected as having no "
- "targets after the DMA stage.\n"
- " {} were detected as "
- "packets which we should not have received in the "
- "first place. \n"
- " Overall this makes a redundant "
- "percentage of {}\n".format(
- key, total,
- data[key][
- PopulationMachineVertex.
- BIT_FIELD_FILTERED_PACKETS],
- data[key][PopulationMachineVertex.GHOST_SEARCHES],
- data[key][
- PopulationMachineVertex.
- INVALID_MASTER_POP_HITS],
- percentage))
+ @staticmethod
+ def __write_core_summary(key, items, output):
+ """
+ :param str key: The name of the core
+ :param dict items: The relevant items for a core
+ :param ~io.TextIOBase output:
+ """
+ # Extract
+ ghosts = items[PopulationMachineVertex.GHOST_SEARCHES]
+ filtered = items[PopulationMachineVertex.BIT_FIELD_FILTERED_PACKETS]
+ invalid = items[PopulationMachineVertex.INVALID_MASTER_POP_HITS]
+ spikes = items[PopulationMachineVertex.SPIKES_PROCESSED]
+
+ # total packets received
+ total = ghosts + filtered + invalid + spikes
+
+ # total redundant packets
+ redundant = ghosts + filtered + invalid
+
+ percentage = 0
+ if total != 0:
+ percentage = (100.0 / total) * redundant
+
+ output.write(
+ "core {}\n\n"
+ " {} packets received.\n"
+ " {} were detected as redundant packets by the bitfield "
+ "filter.\n"
+ " {} were detected as having no targets after the DMA stage.\n"
+ " {} were detected as packets which we should not have "
+ "received in the first place.\n"
+ " Overall this makes a redundant percentage of {}\n".format(
+ key, total, filtered, ghosts, invalid, percentage))
diff --git a/spynnaker/pyNN/extra_algorithms/spynnaker_connection_holder_generations.py b/spynnaker/pyNN/extra_algorithms/spynnaker_connection_holder_generations.py
index 90f911c02ed..411342dd365 100644
--- a/spynnaker/pyNN/extra_algorithms/spynnaker_connection_holder_generations.py
+++ b/spynnaker/pyNN/extra_algorithms/spynnaker_connection_holder_generations.py
@@ -13,13 +13,10 @@
# You should have received a copy of the GNU General Public License
# along with this program. If not, see .
-import logging
from spinn_utilities.progress_bar import ProgressBar
from spynnaker.pyNN.models.neuron import ConnectionHolder
from spynnaker.pyNN.models.neural_projections import ProjectionApplicationEdge
-logger = logging.getLogger(__name__)
-
class SpYNNakerConnectionHolderGenerator(object):
""" Sets up connection holders for reports to use.
@@ -28,11 +25,14 @@ class SpYNNakerConnectionHolderGenerator(object):
application_graph:
app graph
:return: the set of connection holders for after DSG generation
- :rtype: dict(tuple(ProjectionApplicationEdge, SynapseInformation), \
+ :rtype: dict(tuple(ProjectionApplicationEdge, SynapseInformation),
ConnectionHolder)
"""
def __call__(self, application_graph):
+ """
+ :param ~.ApplicationGraph application_graph:
+ """
progress = ProgressBar(
application_graph.n_outgoing_edge_partitions,
"Generating connection holders for reporting connection data.")
@@ -41,7 +41,7 @@ def __call__(self, application_graph):
for partition in progress.over(
application_graph.outgoing_edge_partitions):
for edge in partition.edges:
- # add pre run generators so that reports can extract without
+ # add pre-run generators so that reports can extract without
# going to machine.
if isinstance(edge, ProjectionApplicationEdge):
# build connection holders
@@ -52,6 +52,13 @@ def __call__(self, application_graph):
@staticmethod
def _generate_holder_for_edge(edge, data_holders):
+ """
+ :param ProjectionApplicationEdge edge:
+ :param data_holders:
+ :type data_holders:
+ dict(tuple(ProjectionApplicationEdge, SynapseInformation),
+ ConnectionHolder)
+ """
# build connection holders
connection_holder = ConnectionHolder(
None, True, edge.pre_vertex.n_atoms, edge.post_vertex.n_atoms)
diff --git a/spynnaker/pyNN/extra_algorithms/spynnaker_data_specification_writer.py b/spynnaker/pyNN/extra_algorithms/spynnaker_data_specification_writer.py
index c4a34f03b87..c9f6e32c25b 100644
--- a/spynnaker/pyNN/extra_algorithms/spynnaker_data_specification_writer.py
+++ b/spynnaker/pyNN/extra_algorithms/spynnaker_data_specification_writer.py
@@ -28,7 +28,17 @@ def __call__(
self, placements, hostname, report_default_directory,
write_text_specs, machine, data_n_timesteps):
# pylint: disable=too-many-arguments, signature-differs
+ return super(SpynnakerDataSpecificationWriter, self).__call__(
+ placements, hostname, report_default_directory, write_text_specs,
+ machine, data_n_timesteps,
+ placement_order=self._sort_delays_to_end(placements))
+ @staticmethod
+ def _sort_delays_to_end(placements):
+ """
+ :param ~.Placements placements:
+ :rtype: list(~.Placement)
+ """
delay_extensions = list()
placement_order = list()
for placement in placements.placements:
@@ -37,7 +47,4 @@ def __call__(
else:
placement_order.append(placement)
placement_order.extend(delay_extensions)
-
- return super(SpynnakerDataSpecificationWriter, self).__call__(
- placements, hostname, report_default_directory, write_text_specs,
- machine, data_n_timesteps, placement_order)
+ return placement_order
diff --git a/spynnaker/pyNN/extra_algorithms/spynnaker_machine_bit_field_router_compressor.py b/spynnaker/pyNN/extra_algorithms/spynnaker_machine_bit_field_router_compressor.py
index 4e1fbfb3d94..450be66bd60 100644
--- a/spynnaker/pyNN/extra_algorithms/spynnaker_machine_bit_field_router_compressor.py
+++ b/spynnaker/pyNN/extra_algorithms/spynnaker_machine_bit_field_router_compressor.py
@@ -17,24 +17,46 @@
from six import add_metaclass
from spinn_utilities.abstract_base import AbstractBase, abstractmethod
from spinn_utilities.overrides import overrides
-from spinn_front_end_common.abstract_models.\
- abstract_supports_bit_field_generation import \
- AbstractSupportsBitFieldGeneration
+from spinnman.model import ExecutableTargets
+from spinnman.model.enums import CPUState
+from spinn_front_end_common.abstract_models import (
+ AbstractSupportsBitFieldGeneration)
from spinn_front_end_common.interface.interface_functions.\
machine_bit_field_router_compressor import (
MachineBitFieldPairRouterCompressor,
MachineBitFieldUnorderedRouterCompressor)
from spinn_front_end_common.utilities import system_control_logic
from spinn_front_end_common.utilities.utility_objs import ExecutableType
-from spinnman.model import ExecutableTargets
-from spinnman.model.enums import CPUState
-from spynnaker.pyNN.extra_algorithms.synapse_expander import SYNAPSE_EXPANDER
+from .synapse_expander import SYNAPSE_EXPANDER
logger = logging.getLogger(__name__)
@add_metaclass(AbstractBase)
class SpynnakerMachineBitFieldRouterCompressor(object):
+ """ Bitfield-aware on-machine routing table compression algorithm.
+
+ :param ~pacman.model.routing_tables.MulticastRoutingTables routing_tables:
+ routing tables
+ :param ~spinnman.transceiver.Transceiver transceiver: spinnman instance
+ :param ~spinn_machine.Machine machine: spinnMachine instance
+ :param int app_id: app id of the application
+ :param str provenance_file_path: file path for prov data
+ :param ~pacman.model.graphs.machine.MachineGraph machine_graph:
+ machine graph
+ :param ~pacman.model.placements.Placements placements:
+ placements on machine
+ :param int threshold_percentage:
+ the percentage of bitfields to do on chip before its considered a
+ success
+ :param executable_finder: where are binaries are located
+ :type executable_finder:
+ ~spinn_front_end_common.utilities.utility_objs.ExecutableFinder
+ :param bool read_algorithm_iobuf: flag saying if read iobuf
+ :param bool compress_as_much_as_possible:
+ flag asking if should compress as much as possible
+ :param bool read_expander_iobuf: reads the synaptic expander iobuf.
+ """
def __call__(
self, routing_tables, transceiver, machine, app_id,
@@ -47,23 +69,19 @@ def __call__(
compress_as_much_as_possible=False, provenance_data_objects=None):
""" entrance for routing table compression with bit field
- :param routing_tables: routing tables
- :param transceiver: spinnman instance
- :param machine: spinnMachine instance
- :param app_id: app id of the application
- :param provenance_file_path: file path for prov data
- :param machine_graph: machine graph
- :param placements: placements on machine
- :param threshold_percentage: the percentage of bitfields to do on chip\
- before its considered a success
- :param executable_finder: where are binaries are located
- :param read_algorithm_iobuf: bool flag saying if read iobuf
- :param compress_as_much_as_possible: bool flag asking if should \
- compress as much as possible
- :param read_expander_iobuf: reads the synaptic expander iobuf.
- :rtype: None
+ :param ~.MulticastRoutingTables routing_tables:
+ :param ~.Transceiver transceiver:
+ :param ~.Machine machine:
+ :param int app_id:
+ :param str provenance_file_path:
+ :param ~.MachineGraph machine_graph:
+ :param ~.Placements placements:
+ :param int threshold_percentage:
+ :param ~.ExecutableFinder executable_finder:
+ :param bool read_algorithm_iobuf:
+ :param bool compress_as_much_as_possible:
+ :param bool read_expander_iobuf:
"""
-
# build machine compressor
machine_bit_field_router_compressor = self.compressor_factory()
(compressor_executable_targets, prov_items) = \
@@ -99,17 +117,21 @@ def __call__(
@abstractmethod
def compressor_factory(self):
- "Method to call the specific compressor to use"
+ """ Creates the specific compressor to use.
+
+ :rtype:
+ ~spinn_front_end_common.interface.interface_functions.MachineBitFieldRouterCompressor
+ """
- @staticmethod
def _locate_synaptic_expander_cores(
- cores, executable_finder, placements, machine):
+ self, cores, executable_finder, placements, machine):
""" removes host based cores for synaptic matrix regeneration
- :param cores: the cores for everything
- :param executable_finder: way to get binary path
- :param machine: spiNNMachine instance.
+ :param ~.ExecutableTargets cores: the cores for everything
+ :param ~.ExecutableFinder executable_finder: way to get binary path
+ :param ~.Machine machine: spiNNMachine instance.
:return: new targets for synaptic expander
+ :rtype: ~.ExecutableTargets
"""
new_cores = ExecutableTargets()
@@ -120,21 +142,33 @@ def _locate_synaptic_expander_cores(
# if any ones are going to be ran on host, ignore them from the new
# core setup
for core_subset in cores.all_core_subsets:
- chip = machine.get_chip_at(core_subset.x, core_subset.y)
- for processor_id in range(0, chip.n_processors):
- if placements.is_processor_occupied(
- core_subset.x, core_subset.y, processor_id):
- vertex = placements.get_vertex_on_processor(
- core_subset.x, core_subset.y, processor_id)
- app_vertex = vertex.app_vertex
- if isinstance(vertex, AbstractSupportsBitFieldGeneration):
- if app_vertex.gen_on_machine(vertex.vertex_slice):
- new_cores.add_processor(
- expander_executable_path,
- core_subset.x, core_subset.y, processor_id,
- executable_type=ExecutableType.SYSTEM)
+ x = core_subset.x
+ y = core_subset.y
+ for p in range(machine.get_chip_at(x, y).n_processors):
+ if self._gen_bitfield_on_machine(placements, x, y, p):
+ new_cores.add_processor(
+ expander_executable_path, x, y, p,
+ executable_type=ExecutableType.SYSTEM)
return new_cores
+ @staticmethod
+ def _gen_bitfield_on_machine(placements, x, y, p):
+ """ Check if the given core's vertex has bitfields generated on\
+ machine.
+
+ :param ~.Placements placements:
+ :param int x:
+ :param int y:
+ :param int p:
+ :rtype: bool
+ """
+ if placements.is_processor_occupied(x, y, p):
+ vertex = placements.get_vertex_on_processor(x, y, p)
+ if isinstance(vertex, AbstractSupportsBitFieldGeneration):
+ if vertex.app_vertex.gen_on_machine(vertex.vertex_slice):
+ return True
+ return False
+
@staticmethod
def _rerun_synaptic_cores(
synaptic_expander_rerun_cores, transceiver,
@@ -142,13 +176,13 @@ def _rerun_synaptic_cores(
read_expander_iobuf):
""" reruns the synaptic expander
- :param synaptic_expander_rerun_cores: the cores to rerun the synaptic /
- matrix generator for
- :param transceiver: spinnman instance
- :param provenance_file_path: prov file path
- :param executable_finder: finder of binary file paths
- :param read_expander_iobuf: bool for reading off iobuf if needed
- :rtype: None
+ :param ~.ExecutableTargets synaptic_expander_rerun_cores:
+ the cores to rerun the synaptic matrix generator for
+ :param ~.Transceiver transceiver: spinnman instance
+ :param str provenance_file_path: prov file path
+ :param ~.ExecutableFinder executable_finder:
+ finder of binary file paths
+ :param bool read_expander_iobuf: read off iobuf if needed
"""
if synaptic_expander_rerun_cores.total_processors != 0:
logger.info("rerunning synaptic expander")
@@ -162,6 +196,30 @@ def _rerun_synaptic_cores(
class SpynnakerMachineBitFieldUnorderedRouterCompressor(
SpynnakerMachineBitFieldRouterCompressor):
+ """ Bitfield-aware on-machine routing table compression algorithm that \
+ uses the unordered routing compressor.
+
+ :param ~pacman.model.routing_tables.MulticastRoutingTables routing_tables:
+ routing tables
+ :param ~spinnman.transceiver.Transceiver transceiver: spinnman instance
+ :param ~spinn_machine.Machine machine: spinnMachine instance
+ :param int app_id: app id of the application
+ :param str provenance_file_path: file path for prov data
+ :param ~pacman.model.graphs.machine.MachineGraph machine_graph:
+ machine graph
+ :param ~pacman.model.placements.Placements placements:
+ placements on machine
+ :param int threshold_percentage:
+ the percentage of bitfields to do on chip before its considered a
+ success
+ :param executable_finder: where are binaries are located
+ :type executable_finder:
+ ~spinn_front_end_common.utilities.utility_objs.ExecutableFinder
+ :param bool read_algorithm_iobuf: flag saying if read iobuf
+ :param bool compress_as_much_as_possible:
+ flag asking if should compress as much as possible
+ :param bool read_expander_iobuf: reads the synaptic expander iobuf.
+ """
@overrides(SpynnakerMachineBitFieldRouterCompressor.compressor_factory)
def compressor_factory(self):
@@ -170,6 +228,30 @@ def compressor_factory(self):
class SpynnakerMachineBitFieldPairRouterCompressor(
SpynnakerMachineBitFieldRouterCompressor):
+ """ Bitfield-aware on-machine routing table compression algorithm that \
+ uses the paired routing compressor.
+
+ :param ~pacman.model.routing_tables.MulticastRoutingTables routing_tables:
+ routing tables
+ :param ~spinnman.transceiver.Transceiver transceiver: spinnman instance
+ :param ~spinn_machine.Machine machine: spinnMachine instance
+ :param int app_id: app id of the application
+ :param str provenance_file_path: file path for prov data
+ :param ~pacman.model.graphs.machine.MachineGraph machine_graph:
+ machine graph
+ :param ~pacman.model.placements.Placements placements:
+ placements on machine
+ :param int threshold_percentage:
+ the percentage of bitfields to do on chip before its considered a
+ success
+ :param executable_finder: where are binaries are located
+ :type executable_finder:
+ ~spinn_front_end_common.utilities.utility_objs.ExecutableFinder
+ :param bool read_algorithm_iobuf: flag saying if read iobuf
+ :param bool compress_as_much_as_possible:
+ flag asking if should compress as much as possible
+ :param bool read_expander_iobuf: reads the synaptic expander iobuf.
+ """
@overrides(SpynnakerMachineBitFieldRouterCompressor.compressor_factory)
def compressor_factory(self):
diff --git a/spynnaker/pyNN/extra_algorithms/spynnaker_neuron_network_specification_report.py b/spynnaker/pyNN/extra_algorithms/spynnaker_neuron_network_specification_report.py
index 1962a27d08b..1e45ee0b6aa 100644
--- a/spynnaker/pyNN/extra_algorithms/spynnaker_neuron_network_specification_report.py
+++ b/spynnaker/pyNN/extra_algorithms/spynnaker_neuron_network_specification_report.py
@@ -13,14 +13,11 @@
# You should have received a copy of the GNU General Public License
# along with this program. If not, see .
-import logging
import os
from spinn_utilities.progress_bar import ProgressBar
from spynnaker.pyNN.exceptions import SpynnakerException
from spynnaker.pyNN.models.neural_projections import ProjectionApplicationEdge
-logger = logging.getLogger(__name__)
-
class SpYNNakerNeuronGraphNetworkSpecificationReport(object):
""" Produces a report describing the graph created from the neural \
@@ -34,6 +31,10 @@ class SpYNNakerNeuronGraphNetworkSpecificationReport(object):
@staticmethod
def _get_diagram(label):
+ """
+ :param str label:
+ :rtype: ~graphviz.Digraph
+ """
# pylint: disable=import-error
try:
import graphviz
@@ -44,8 +45,12 @@ def _get_diagram(label):
return graphviz.Digraph(comment=label)
def __call__(self, report_folder, application_graph):
+ """
+ :param str report_folder:
+ :param ~.ApplicationGraph application_graph:
+ """
# create holders for data
- vertex_holders = dict()
+ vertex_names = dict()
dot_diagram = self._get_diagram(
"The graph of the network in graphical form")
@@ -56,29 +61,25 @@ def __call__(self, report_folder, application_graph):
"generating the graphical representation of the neural network")
# write vertices into dot diagram
- for vertex_counter, vertex in progress.over(
+ for vertex_index, vertex in progress.over(
enumerate(application_graph.vertices), False):
+ vertex_names[vertex] = str(vertex_index)
dot_diagram.node(
- "{}".format(vertex_counter),
+ vertex_names[vertex],
"{} ({} neurons)".format(vertex.label, vertex.n_atoms))
- vertex_holders[vertex] = vertex_counter
# write edges into dot diagram
for partition in progress.over(
application_graph.outgoing_edge_partitions, False):
for edge in partition.edges:
- source_vertex_id = vertex_holders[edge.pre_vertex]
- dest_vertex_id = vertex_holders[edge.post_vertex]
+ pre_name = vertex_names[edge.pre_vertex]
+ post_name = vertex_names[edge.post_vertex]
if isinstance(edge, ProjectionApplicationEdge):
for synapse_info in edge.synapse_information:
dot_diagram.edge(
- "{}".format(source_vertex_id),
- "{}".format(dest_vertex_id),
- "{}".format(synapse_info.connector))
+ pre_name, post_name, str(synapse_info.connector))
else:
- dot_diagram.edge(
- "{}".format(source_vertex_id),
- "{}".format(dest_vertex_id))
+ dot_diagram.edge(pre_name, post_name)
# write dot file and generate pdf
file_to_output = os.path.join(report_folder, "network_graph.gv")
diff --git a/spynnaker/pyNN/extra_algorithms/synapse_expander.py b/spynnaker/pyNN/extra_algorithms/synapse_expander.py
index 566ba54f795..b867ba73c29 100644
--- a/spynnaker/pyNN/extra_algorithms/synapse_expander.py
+++ b/spynnaker/pyNN/extra_algorithms/synapse_expander.py
@@ -13,21 +13,17 @@
# You should have received a copy of the GNU General Public License
# along with this program. If not, see .
import functools
-import logging
from six import iteritems
-
-from spinn_front_end_common.utilities.system_control_logic import \
- run_system_application
-from spinn_front_end_common.utilities.utility_objs import ExecutableType
from spinn_utilities.progress_bar import ProgressBar
from spinnman.model import ExecutableTargets
from spinnman.model.enums import CPUState
-from spinn_front_end_common.utilities import globals_variables
+from spinn_front_end_common.utilities.system_control_logic import (
+ run_system_application)
+from spinn_front_end_common.utilities.utility_objs import ExecutableType
+from spinn_front_end_common.utilities.globals_variables import get_simulator
from spynnaker.pyNN.models.neuron import AbstractPopulationVertex
from spynnaker.pyNN.models.utility_models.delays import DelayExtensionVertex
-logger = logging.getLogger(__name__)
-
SYNAPSE_EXPANDER = "synapse_expander.aplx"
DELAY_EXPANDER = "delay_expander.aplx"
@@ -81,52 +77,83 @@ def _plan_expansion(app_graph, placements, synapse_expander_bin,
# Add all machine vertices of the population vertex to ones
# that need synapse expansion
if isinstance(vertex, AbstractPopulationVertex):
- gen_on_machine = False
- for m_vertex in vertex.machine_vertices:
- if vertex.gen_on_machine(m_vertex.vertex_slice):
- placement = placements.get_placement_of_vertex(m_vertex)
- expander_cores.add_processor(
- synapse_expander_bin,
- placement.x, placement.y, placement.p,
- executable_type=ExecutableType.SYSTEM)
- gen_on_machine = True
+ gen_on_machine = _plan_expansion_of_vertex(
+ vertex, placements, expander_cores, synapse_expander_bin)
if gen_on_machine:
expanded_pop_vertices.append(vertex)
elif isinstance(vertex, DelayExtensionVertex):
- for m_vertex in vertex.machine_vertices:
- if vertex.gen_on_machine(m_vertex.vertex_slice):
- placement = placements.get_placement_of_vertex(m_vertex)
- expander_cores.add_processor(
- delay_expander_bin,
- placement.x, placement.y, placement.p,
- executable_type=ExecutableType.SYSTEM)
+ _plan_expansion_of_vertex(
+ vertex, placements, expander_cores, delay_expander_bin)
+ # No post-expand actions for these
return expander_cores, expanded_pop_vertices
+def _plan_expansion_of_vertex(
+ vertex, placements, expander_cores, expander_binary):
+ """
+ :param vertex:
+ :type vertex: AbstractPopulationVertex or DelayExtensionVertex
+ :param ~.Placements placements:
+ :param ~.ExecutableTargets expander_cores:
+ :param str expander_binary:
+ :return: True if any expander cores were added
+ :rtype: bool
+ """
+ gen_on_machine = False
+ for m_vertex in vertex.machine_vertices:
+ if vertex.gen_on_machine(m_vertex.vertex_slice):
+ placement = placements.get_placement_of_vertex(m_vertex)
+ expander_cores.add_processor(
+ expander_binary, placement.x, placement.y, placement.p,
+ executable_type=ExecutableType.SYSTEM)
+ gen_on_machine = True
+ return gen_on_machine
+
+
def _fill_in_connection_data(
_expander_cores, transceiver, expanded_pop_vertices, placements):
- """ Once expander has run, fill in the connection data
+ """ Once expander has run, fill in the connection data we have for the\
+ expanded connection matrix.
- :rtype: None
+ :param ~.ExecutableTargets expander_cores:
+ :param ~.Transceiver transceiver:
+ :param list(AbstractPopulationVertex) expanded_pop_vertices:
+ :param ~.Placements placements:
"""
- ctl = globals_variables.get_simulator()
- use_extra_monitors = False
+ # pylint: disable=unused-argument
+ ctl = get_simulator()
for vertex in expanded_pop_vertices:
- conn_holders = vertex.get_connection_holders()
- for (app_edge, synapse_info), conn_holder_list in iteritems(
- conn_holders):
+ for (edge, synapse_info), conn_holders in iteritems(
+ vertex.get_connection_holders()):
# Only do this if this synapse_info has been generated
# on the machine using the expander
if synapse_info.may_generate_on_machine():
- machine_edges = app_edge.machine_edges
- for machine_edge in machine_edges:
- placement = placements.get_placement_of_vertex(
- machine_edge.post_vertex)
- conns = vertex.get_connections_from_machine(
- transceiver, placement, machine_edge,
- ctl.routing_infos, synapse_info, ctl.machine_time_step,
- use_extra_monitors)
- for conn_holder in conn_holder_list:
- conn_holder.add_connections(conns)
+ _read_connections_for_app_edge_from_machine(
+ vertex, placements, transceiver, ctl,
+ edge, synapse_info, conn_holders)
+
+
+def _read_connections_for_app_edge_from_machine(
+ vertex, placements, transceiver, ctl,
+ app_edge, synapse_info, conn_holder_list):
+ """ Reads (and records for later) the connections that were actually \
+ generated on the machine for a particular application edge.
+
+ :param AbstractPopulationVertex vertex:
+ :param ~.Placements placements:
+ :param ~.Transceiver transceiver:
+ :param ~.SimulatorInterface ctl:
+ :param ~.ApplicationEdge app_edge:
+ :param SynapseInformation synapse_info:
+ :param list(ConnectionHolder) conn_holder_list:
+ """
+ use_extra_monitors = False
+ for edge in app_edge.machine_edges:
+ conns = vertex.get_connections_from_machine(
+ transceiver, placements.get_placement_of_vertex(edge.post_vertex),
+ edge, ctl.routing_infos, synapse_info, ctl.machine_time_step,
+ use_extra_monitors)
+ for conn_holder in conn_holder_list:
+ conn_holder.add_connections(conns)
diff --git a/spynnaker/pyNN/models/abstract_models/abstract_accepts_incoming_synapses.py b/spynnaker/pyNN/models/abstract_models/abstract_accepts_incoming_synapses.py
index 1131ab4ae63..7d2b795ac8e 100644
--- a/spynnaker/pyNN/models/abstract_models/abstract_accepts_incoming_synapses.py
+++ b/spynnaker/pyNN/models/abstract_models/abstract_accepts_incoming_synapses.py
@@ -66,7 +66,7 @@ def get_connections_from_machine(
# pylint: disable=too-many-arguments
""" Get the connections from the machine post-run.
- :param ~spinnman.Transceiver transceiver:
+ :param ~spinnman.transceiver.Transceiver transceiver:
:param ~pacman.model.placements.Placement placement:
:param ProjectionMachineEdge edge:
:param ~pacman.model.routing_info.RoutingInfo routing_infos:
@@ -76,11 +76,13 @@ def get_connections_from_machine(
:param placements:
:type placements: None or ~pacman.model.placements.Placements
:param monitor_api:
- :type monitor_api: None or \
+ :type monitor_api: None or
~spinn_front_end_common.utility_models.DataSpeedUpPacketGatherMachineVertex
:param fixed_routes:
:param extra_monitor: the extra monitor for this
- :type fixed_routes: None or \
+ :type extra_monitor:
+ ~spinn_front_end_common.utility_models.ExtraMonitorSupportMachineVertex
+ :type fixed_routes: None or
dict(tuple(int,int),~spinn_machine.FixedRouteEntry)
"""
diff --git a/spynnaker/pyNN/models/abstract_models/abstract_population_settable.py b/spynnaker/pyNN/models/abstract_models/abstract_population_settable.py
index 373af12a5e5..d3643dbfa20 100644
--- a/spynnaker/pyNN/models/abstract_models/abstract_population_settable.py
+++ b/spynnaker/pyNN/models/abstract_models/abstract_population_settable.py
@@ -38,8 +38,8 @@ def get_value_by_selector(self, selector, key):
""" Gets the value for a particular key but only for the selected\
subset.
- :param selector: See \
- :py:meth:`~spinn_utilities.ranged.RangedList.get_value_by_selector`\
+ :param selector: See
+ :py:meth:`~spinn_utilities.ranged.RangedList.get_value_by_selector`
as this is just a pass through method
:type selector: None or slice or int or list(bool) or list(int)
:param str key: the name of the parameter to change
@@ -60,8 +60,8 @@ def set_value_by_selector(self, selector, key, value):
""" Sets the value for a particular key but only for the selected \
subset.
- :param selector: See \
- :py:class:`~spinn_utilities.ranged.RangedList`.set_value_by_selector\
+ :param selector: See
+ :py:meth:`~spinn_utilities.ranged.RangedList.set_value_by_selector`
as this is just a pass through method
:type selector: None or slice or int or list(bool) or list(int)
:param str key: the name of the parameter to change
diff --git a/spynnaker/pyNN/models/abstract_models/abstract_read_parameters_before_set.py b/spynnaker/pyNN/models/abstract_models/abstract_read_parameters_before_set.py
index 4ed297a4769..6ebd72bee0e 100644
--- a/spynnaker/pyNN/models/abstract_models/abstract_read_parameters_before_set.py
+++ b/spynnaker/pyNN/models/abstract_models/abstract_read_parameters_before_set.py
@@ -35,5 +35,4 @@ def read_parameters_from_machine(
the placement of a vertex
:param ~pacman.model.graphs.common.Slice vertex_slice:
the slice of atoms for this vertex
- :rtype: None
"""
diff --git a/spynnaker/pyNN/models/abstract_models/abstract_settable.py b/spynnaker/pyNN/models/abstract_models/abstract_settable.py
index fe91c7105f4..b049d99da7f 100644
--- a/spynnaker/pyNN/models/abstract_models/abstract_settable.py
+++ b/spynnaker/pyNN/models/abstract_models/abstract_settable.py
@@ -27,7 +27,7 @@ class AbstractSettable(object):
@abstractmethod
def get_value(self, key):
- """ Get a property
+ """ Get a property of the model
:param str key: the name of the property
:rtype: Any or float or int or list(float) or list(int)
@@ -35,7 +35,7 @@ def get_value(self, key):
@abstractmethod
def set_value(self, key, value):
- """ Set a property
+ """ Set a property of the model
:param str key: the name of the parameter to change
:param value: the new value of the parameter to assign
diff --git a/spynnaker/pyNN/models/abstract_pynn_model.py b/spynnaker/pyNN/models/abstract_pynn_model.py
index 65048ddf662..0b78ed2212f 100644
--- a/spynnaker/pyNN/models/abstract_pynn_model.py
+++ b/spynnaker/pyNN/models/abstract_pynn_model.py
@@ -100,7 +100,7 @@ def has_parameter(cls, name):
@abstractproperty
def default_population_parameters(self):
""" Get the default values for the parameters at the population level
- These are parameters that can be passed in to the Population\
+ These are parameters that can be passed in to the Population
constructor in addition to the standard PyNN options
:rtype: dict(str, Any)
diff --git a/spynnaker/pyNN/models/common/abstract_neuron_recordable.py b/spynnaker/pyNN/models/common/abstract_neuron_recordable.py
index c2da9491870..e32c34efe3f 100644
--- a/spynnaker/pyNN/models/common/abstract_neuron_recordable.py
+++ b/spynnaker/pyNN/models/common/abstract_neuron_recordable.py
@@ -28,7 +28,7 @@ class AbstractNeuronRecordable(object):
@abstractmethod
def get_recordable_variables(self):
""" Returns a list of the PyNN names of variables this model is \
- expected to collect
+ expected to collect.
:rtype: list(str)
"""
@@ -45,7 +45,7 @@ def is_recording(self, variable):
@abstractmethod
def set_recording(self, variable, new_state=True, sampling_interval=None,
indexes=None):
- """ Sets variable to being recorded
+ """ Sets variable to being recorded.
:param str variable: PyNN name of the variable
:param bool new_state:
@@ -65,7 +65,6 @@ def clear_recording(self, variable, buffer_manager, placements):
~spinn_front_end_common.interface.buffer_management.BufferManager
:param ~pacman.model.placements.Placements placements:
the placements object
- :rtype: None
"""
@abstractmethod
diff --git a/spynnaker/pyNN/models/common/abstract_spike_recordable.py b/spynnaker/pyNN/models/common/abstract_spike_recordable.py
index b18ef17c838..b24c89515b9 100644
--- a/spynnaker/pyNN/models/common/abstract_spike_recordable.py
+++ b/spynnaker/pyNN/models/common/abstract_spike_recordable.py
@@ -26,7 +26,7 @@ class AbstractSpikeRecordable(object):
@abstractmethod
def is_recording_spikes(self):
- """ Determine if spikes are being recorded
+ """ Determine if spikes are being recorded.
:return: True if spikes are being recorded, False otherwise
:rtype: bool
@@ -36,7 +36,7 @@ def is_recording_spikes(self):
def set_recording_spikes(
self, new_state=True, sampling_interval=None, indexes=None):
""" Set spikes to being recorded. \
- If `new_state` is false all other parameters are ignored.
+ If `new_state` is False all other parameters are ignored.
:param bool new_state: Set if the spikes are recording or not
:param sampling_interval: The interval at which spikes are recorded.
@@ -57,7 +57,6 @@ def clear_spike_recording(self, buffer_manager, placements):
~spinn_front_end_common.interface.buffer_management.BufferManager
:param ~pacman.model.placements.Placements placements:
the placements object
- :rtype: None
"""
@abstractmethod
@@ -71,7 +70,7 @@ def get_spikes(self, placements, buffer_manager, machine_time_step):
~spinn_front_end_common.interface.buffer_management.BufferManager
:param int machine_time_step:
the time step of the simulation, in microseconds
- :return: A numpy array of 2-element arrays of (neuron_id, time)\
+ :return: A numpy array of 2-element arrays of (neuron_id, time)
ordered by time, one element per event
:rtype: ~numpy.ndarray(tuple(int,int))
"""
diff --git a/spynnaker/pyNN/models/common/eieio_spike_recorder.py b/spynnaker/pyNN/models/common/eieio_spike_recorder.py
index 0e81829e03f..326d2082065 100644
--- a/spynnaker/pyNN/models/common/eieio_spike_recorder.py
+++ b/spynnaker/pyNN/models/common/eieio_spike_recorder.py
@@ -19,9 +19,9 @@
from spinn_utilities.progress_bar import ProgressBar
from spinn_utilities.log import FormatAdapter
from spinnman.messages.eieio.data_messages import EIEIODataHeader
-from spynnaker.pyNN.models.common import recording_utils
from spinn_front_end_common.utilities.constants import (
BYTES_PER_WORD, MICRO_TO_MILLISECOND_CONVERSION)
+from spynnaker.pyNN.models.common.recording_utils import make_missing_string
logger = FormatAdapter(logging.getLogger(__name__))
_ONE_WORD = struct.Struct(" 0:
+ if n_buffer_times:
+ placement = placements.get_placement_of_vertex(vertex)
raw_spike_data, data_missing = \
buffer_manager.get_data_by_placement(placement, region)
if data_missing:
missing.append(placement)
self._process_spike_data(
- vertex_slice, raw_spike_data, ms_per_tick,
+ vertex.vertex_slice, raw_spike_data, ms_per_tick,
base_key_function(vertex), results)
if missing:
- missing_str = recording_utils.make_missing_string(missing)
+ missing_str = make_missing_string(missing)
logger.warning(
"Population {} is missing spike data in region {} from the"
" following cores: {}", label, region, missing_str)
diff --git a/spynnaker/pyNN/models/common/multi_spike_recorder.py b/spynnaker/pyNN/models/common/multi_spike_recorder.py
index c1d917560fa..c4301d69135 100644
--- a/spynnaker/pyNN/models/common/multi_spike_recorder.py
+++ b/spynnaker/pyNN/models/common/multi_spike_recorder.py
@@ -12,18 +12,17 @@
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see .
-
-import math
import logging
import struct
import numpy
-from pacman.model.resources.constant_sdram import ConstantSDRAM
from spinn_utilities.progress_bar import ProgressBar
from spinn_utilities.log import FormatAdapter
-from spynnaker.pyNN.models.common import recording_utils
-from pacman.model.resources.variable_sdram import VariableSDRAM
+from pacman.model.resources import ConstantSDRAM, VariableSDRAM
from spinn_front_end_common.utilities.constants import (
- BYTES_PER_WORD, BITS_PER_WORD, MICRO_TO_MILLISECOND_CONVERSION)
+ BYTES_PER_WORD, MICRO_TO_MILLISECOND_CONVERSION)
+from spynnaker.pyNN.models.common.recording_utils import make_missing_string
+from spynnaker.pyNN.utilities.utility_calls import ceildiv
+from spynnaker.pyNN.utilities.constants import BITS_PER_WORD
logger = FormatAdapter(logging.getLogger(__name__))
_TWO_WORDS = struct.Struct(".
from __future__ import division
-import logging
import struct
import numpy
from spinn_front_end_common.utilities.helpful_functions import (
@@ -22,7 +21,6 @@
from spinn_front_end_common.utilities.constants import BYTES_PER_WORD
from spynnaker.pyNN.exceptions import MemReadException
-logger = logging.getLogger(__name__)
_RECORDING_COUNT = struct.Struct(".
-
-import logging
import numpy
from spinn_utilities.overrides import overrides
from spinn_front_end_common.utilities.constants import BYTES_PER_WORD
@@ -25,8 +23,6 @@
N_GEN_PARAMS = 1
-logger = logging.getLogger(__file__)
-
class AllToAllConnector(AbstractGenerateConnectorOnMachine,
AbstractConnectorSupportsViewsOnMachine):
diff --git a/spynnaker/pyNN/models/neural_projections/connectors/array_connector.py b/spynnaker/pyNN/models/neural_projections/connectors/array_connector.py
index 8d25c7bdf81..0ccbdde520a 100644
--- a/spynnaker/pyNN/models/neural_projections/connectors/array_connector.py
+++ b/spynnaker/pyNN/models/neural_projections/connectors/array_connector.py
@@ -12,14 +12,10 @@
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see .
-
-import logging
import numpy
from spinn_utilities.overrides import overrides
from .abstract_connector import AbstractConnector
-logger = logging.getLogger(__name__)
-
class ArrayConnector(AbstractConnector):
""" Make connections using an array of integers based on the IDs\
@@ -32,9 +28,9 @@ class ArrayConnector(AbstractConnector):
def __init__(self, array, safe=True, callback=None, verbose=False):
"""
:param array:
- An explicit boolean matrix that specifies the connections\
- between the pre- and post-populations\
- (see PyNN documentation). Must be 2D in practice.
+ An explicit boolean matrix that specifies the connections between
+ the pre- and post-populations (see PyNN documentation).
+ Must be 2D in practice.
:type array: ~numpy.ndarray(2, ~numpy.uint8)
:param bool safe:
:param callable callback: Ignored
diff --git a/spynnaker/pyNN/models/neural_projections/connectors/csa_connector.py b/spynnaker/pyNN/models/neural_projections/connectors/csa_connector.py
index 4c33b01e59a..1ebaa913579 100644
--- a/spynnaker/pyNN/models/neural_projections/connectors/csa_connector.py
+++ b/spynnaker/pyNN/models/neural_projections/connectors/csa_connector.py
@@ -12,8 +12,6 @@
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see .
-
-import logging
import numpy
from spinn_utilities.overrides import overrides
from .abstract_connector import AbstractConnector
@@ -24,8 +22,6 @@
# Importing csa causes problems with readthedocs so allowing it to fail
_csa_found = (False, _ex)
-logger = logging.getLogger(__name__)
-
class CSAConnector(AbstractConnector):
""" Make connections using a Connection Set Algebra (Djurfeldt 2012)\
diff --git a/spynnaker/pyNN/models/neural_projections/connectors/distance_dependent_probability_connector.py b/spynnaker/pyNN/models/neural_projections/connectors/distance_dependent_probability_connector.py
index 84f522378ba..da947829e16 100644
--- a/spynnaker/pyNN/models/neural_projections/connectors/distance_dependent_probability_connector.py
+++ b/spynnaker/pyNN/models/neural_projections/connectors/distance_dependent_probability_connector.py
@@ -12,8 +12,6 @@
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see .
-
-import logging
import math
import numpy
from numpy import (
@@ -22,10 +20,10 @@
minimum, e, pi)
from spinn_utilities.overrides import overrides
from spinn_utilities.safe_eval import SafeEval
-from spynnaker.pyNN.utilities import utility_calls
+from spynnaker.pyNN.utilities.utility_calls import (
+ get_probable_maximum_selected, round_up)
from .abstract_connector import AbstractConnector
-logger = logging.getLogger(__name__)
# support for arbitrary expression for the distance dependence
_d_expr_context = SafeEval(math, numpy, arccos, arcsin, arctan, arctan2, ceil,
cos, cosh, exp, fabs, floor, fmod, hypot, ldexp,
@@ -112,8 +110,7 @@ def _set_probabilities(self, synapse_info):
@overrides(AbstractConnector.get_delay_maximum)
def get_delay_maximum(self, synapse_info):
return self._get_delay_maximum(
- synapse_info.delays,
- utility_calls.get_probable_maximum_selected(
+ synapse_info.delays, get_probable_maximum_selected(
synapse_info.n_pre_neurons * synapse_info.n_post_neurons,
synapse_info.n_pre_neurons * synapse_info.n_post_neurons,
numpy.amax(self.__probs)))
@@ -126,12 +123,12 @@ def get_n_connections_from_pre_vertex_maximum(
max_prob = numpy.amax(
self.__probs[0:synapse_info.n_pre_neurons,
post_vertex_slice.as_slice])
- n_connections = utility_calls.get_probable_maximum_selected(
+ n_connections = get_probable_maximum_selected(
synapse_info.n_pre_neurons * synapse_info.n_post_neurons,
post_vertex_slice.n_atoms, max_prob)
if min_delay is None or max_delay is None:
- return int(math.ceil(n_connections))
+ return round_up(n_connections)
return self._get_n_connections_from_pre_vertex_with_delay_maximum(
synapse_info.delays,
@@ -141,7 +138,7 @@ def get_n_connections_from_pre_vertex_maximum(
@overrides(AbstractConnector.get_n_connections_to_post_vertex_maximum)
def get_n_connections_to_post_vertex_maximum(self, synapse_info):
# pylint: disable=too-many-arguments
- return utility_calls.get_probable_maximum_selected(
+ return get_probable_maximum_selected(
synapse_info.n_pre_neurons * synapse_info.n_post_neurons,
synapse_info.n_post_neurons,
numpy.amax(self.__probs))
@@ -150,8 +147,7 @@ def get_n_connections_to_post_vertex_maximum(self, synapse_info):
def get_weight_maximum(self, synapse_info):
# pylint: disable=too-many-arguments
return self._get_weight_maximum(
- synapse_info.weights,
- utility_calls.get_probable_maximum_selected(
+ synapse_info.weights, get_probable_maximum_selected(
synapse_info.n_pre_neurons * synapse_info.n_post_neurons,
synapse_info.n_pre_neurons * synapse_info.n_post_neurons,
numpy.amax(self.__probs)))
diff --git a/spynnaker/pyNN/models/neural_projections/connectors/fixed_number_post_connector.py b/spynnaker/pyNN/models/neural_projections/connectors/fixed_number_post_connector.py
index da9f71aee1d..463106cd2e5 100644
--- a/spynnaker/pyNN/models/neural_projections/connectors/fixed_number_post_connector.py
+++ b/spynnaker/pyNN/models/neural_projections/connectors/fixed_number_post_connector.py
@@ -14,8 +14,6 @@
# along with this program. If not, see .
from __future__ import print_function
-import logging
-import math
import numpy
from spinn_utilities.overrides import overrides
from spinn_front_end_common.utilities.constants import BYTES_PER_WORD
@@ -24,13 +22,12 @@
AbstractGenerateConnectorOnMachine, ConnectorIDs)
from .abstract_connector_supports_views_on_machine import (
AbstractConnectorSupportsViewsOnMachine)
-from spynnaker.pyNN.utilities import utility_calls
from spynnaker.pyNN.exceptions import SpynnakerException
+from spynnaker.pyNN.utilities.utility_calls import (
+ round_up, get_probable_maximum_selected)
N_GEN_PARAMS = 8
-logger = logging.getLogger(__file__)
-
class FixedNumberPostConnector(AbstractGenerateConnectorOnMachine,
AbstractConnectorSupportsViewsOnMachine):
@@ -202,12 +199,12 @@ def get_n_connections_from_pre_vertex_maximum(
prob_in_slice = min(
post_vertex_slice.n_atoms / float(
synapse_info.n_post_neurons), 1.0)
- n_connections = utility_calls.get_probable_maximum_selected(
+ n_connections = get_probable_maximum_selected(
synapse_info.n_pre_neurons * synapse_info.n_post_neurons,
self.__n_post, prob_in_slice, chance=1.0/100000.0)
if min_delay is None or max_delay is None:
- return int(math.ceil(n_connections))
+ return round_up(n_connections)
return self._get_n_connections_from_pre_vertex_with_delay_maximum(
synapse_info.delays,
@@ -218,11 +215,11 @@ def get_n_connections_from_pre_vertex_maximum(
def get_n_connections_to_post_vertex_maximum(self, synapse_info):
# pylint: disable=too-many-arguments
selection_prob = 1.0 / float(synapse_info.n_post_neurons)
- n_connections = utility_calls.get_probable_maximum_selected(
+ n_connections = get_probable_maximum_selected(
synapse_info.n_pre_neurons * synapse_info.n_post_neurons,
synapse_info.n_pre_neurons, selection_prob,
chance=1.0/100000.0)
- return int(math.ceil(n_connections))
+ return round_up(n_connections)
@overrides(AbstractConnector.get_weight_maximum)
def get_weight_maximum(self, synapse_info):
diff --git a/spynnaker/pyNN/models/neural_projections/connectors/fixed_number_pre_connector.py b/spynnaker/pyNN/models/neural_projections/connectors/fixed_number_pre_connector.py
index 4f31127f1ba..8f3960cc6b5 100644
--- a/spynnaker/pyNN/models/neural_projections/connectors/fixed_number_pre_connector.py
+++ b/spynnaker/pyNN/models/neural_projections/connectors/fixed_number_pre_connector.py
@@ -12,24 +12,20 @@
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see .
-
-import logging
-import math
import numpy
from spinn_utilities.overrides import overrides
from spinn_front_end_common.utilities.constants import BYTES_PER_WORD
from .abstract_connector import AbstractConnector
from .abstract_generate_connector_on_machine import (
AbstractGenerateConnectorOnMachine, ConnectorIDs)
-from spynnaker.pyNN.utilities import utility_calls
+from spynnaker.pyNN.utilities.utility_calls import (
+ get_probable_maximum_selected, round_up)
from spynnaker.pyNN.exceptions import SpynnakerException
from .abstract_connector_supports_views_on_machine import (
AbstractConnectorSupportsViewsOnMachine)
N_GEN_PARAMS = 8
-logger = logging.getLogger(__file__)
-
class FixedNumberPreConnector(AbstractGenerateConnectorOnMachine,
AbstractConnectorSupportsViewsOnMachine):
@@ -70,7 +66,7 @@ def __init__(
:type rng: ~pyNN.random.NumpyRNG or None
"""
# :param ~pyNN.space.Space space:
- # a Space object, needed if you wish to specify distance-dependent\
+ # a Space object, needed if you wish to specify distance-dependent
# weights or delays - not implemented
super(FixedNumberPreConnector, self).__init__(safe, callback, verbose)
self.__n_pre = n
@@ -201,19 +197,19 @@ def get_n_connections_from_pre_vertex_maximum(
max_delay=None):
# pylint: disable=too-many-arguments
prob_selection = 1.0 / float(synapse_info.n_pre_neurons)
- n_connections_total = utility_calls.get_probable_maximum_selected(
+ n_connections_total = get_probable_maximum_selected(
synapse_info.n_pre_neurons * synapse_info.n_post_neurons,
self.__n_pre * synapse_info.n_post_neurons, prob_selection,
chance=1.0/10000.0)
prob_in_slice = min(
float(post_vertex_slice.n_atoms) / float(
synapse_info.n_post_neurons), 1.0)
- n_connections = utility_calls.get_probable_maximum_selected(
+ n_connections = get_probable_maximum_selected(
synapse_info.n_pre_neurons * synapse_info.n_post_neurons,
n_connections_total, prob_in_slice, chance=1.0/100000.0)
if min_delay is None or max_delay is None:
- return int(math.ceil(n_connections))
+ return round_up(n_connections)
return self._get_n_connections_from_pre_vertex_with_delay_maximum(
synapse_info.delays,
diff --git a/spynnaker/pyNN/models/neural_projections/connectors/fixed_probability_connector.py b/spynnaker/pyNN/models/neural_projections/connectors/fixed_probability_connector.py
index 75021337b2c..ce25056ab20 100644
--- a/spynnaker/pyNN/models/neural_projections/connectors/fixed_probability_connector.py
+++ b/spynnaker/pyNN/models/neural_projections/connectors/fixed_probability_connector.py
@@ -12,19 +12,18 @@
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see .
-
-import math
import numpy
from spinn_utilities.overrides import overrides
from data_specification.enums.data_type import DataType
from spinn_front_end_common.utilities.exceptions import ConfigurationException
-from spynnaker.pyNN.utilities import utility_calls
+from spinn_front_end_common.utilities.constants import BYTES_PER_WORD
+from spynnaker.pyNN.utilities.utility_calls import (
+ round_up, get_probable_maximum_selected)
from .abstract_connector import AbstractConnector
from .abstract_generate_connector_on_machine import (
AbstractGenerateConnectorOnMachine, ConnectorIDs)
from .abstract_connector_supports_views_on_machine import (
AbstractConnectorSupportsViewsOnMachine)
-from spinn_front_end_common.utilities.constants import BYTES_PER_WORD
N_GEN_PARAMS = 6
@@ -43,11 +42,11 @@ def __init__(
callback=None, verbose=False, rng=None):
"""
:param float p_connect:
- a float between zero and one. Each potential connection is created\
+ a float between zero and one. Each potential connection is created
with this probability.
:param bool allow_self_connections:
- if the connector is used to connect a Population to itself, this\
- flag determines whether a neuron is allowed to connect to itself,\
+ if the connector is used to connect a Population to itself, this
+ flag determines whether a neuron is allowed to connect to itself,
or only to other neurons in the Population.
:param bool safe:
:param callable callback: Ignored
@@ -67,7 +66,7 @@ def __init__(
@overrides(AbstractConnector.get_delay_maximum)
def get_delay_maximum(self, synapse_info):
- n_connections = utility_calls.get_probable_maximum_selected(
+ n_connections = get_probable_maximum_selected(
synapse_info.n_pre_neurons * synapse_info.n_post_neurons,
synapse_info.n_pre_neurons * synapse_info.n_post_neurons,
self._p_connect)
@@ -78,12 +77,12 @@ def get_n_connections_from_pre_vertex_maximum(
self, post_vertex_slice, synapse_info, min_delay=None,
max_delay=None):
# pylint: disable=too-many-arguments
- n_connections = utility_calls.get_probable_maximum_selected(
+ n_connections = get_probable_maximum_selected(
synapse_info.n_pre_neurons * synapse_info.n_post_neurons,
post_vertex_slice.n_atoms, self._p_connect, chance=1.0/10000.0)
if min_delay is None or max_delay is None:
- return int(math.ceil(n_connections))
+ return round_up(n_connections)
return self._get_n_connections_from_pre_vertex_with_delay_maximum(
synapse_info.delays,
@@ -93,7 +92,7 @@ def get_n_connections_from_pre_vertex_maximum(
@overrides(AbstractConnector.get_n_connections_to_post_vertex_maximum)
def get_n_connections_to_post_vertex_maximum(self, synapse_info):
# pylint: disable=too-many-arguments
- n_connections = utility_calls.get_probable_maximum_selected(
+ n_connections = get_probable_maximum_selected(
synapse_info.n_pre_neurons * synapse_info.n_post_neurons,
synapse_info.n_pre_neurons, self._p_connect,
chance=1.0/10000.0)
@@ -102,7 +101,7 @@ def get_n_connections_to_post_vertex_maximum(self, synapse_info):
@overrides(AbstractConnector.get_weight_maximum)
def get_weight_maximum(self, synapse_info):
# pylint: disable=too-many-arguments
- n_connections = utility_calls.get_probable_maximum_selected(
+ n_connections = get_probable_maximum_selected(
synapse_info.n_pre_neurons * synapse_info.n_post_neurons,
synapse_info.n_pre_neurons * synapse_info.n_post_neurons,
self._p_connect)
diff --git a/spynnaker/pyNN/models/neural_projections/connectors/from_list_connector.py b/spynnaker/pyNN/models/neural_projections/connectors/from_list_connector.py
index 962391e1271..d12e4be4c5b 100644
--- a/spynnaker/pyNN/models/neural_projections/connectors/from_list_connector.py
+++ b/spynnaker/pyNN/models/neural_projections/connectors/from_list_connector.py
@@ -13,18 +13,14 @@
# You should have received a copy of the GNU General Public License
# along with this program. If not, see .
-import logging
import numpy
-
-from spinn_front_end_common.utilities.constants import \
- MICRO_TO_MILLISECOND_CONVERSION
from spinn_utilities.overrides import overrides
-from spinn_front_end_common.utilities import globals_variables
+from spinn_front_end_common.utilities.constants import (
+ MICRO_TO_MILLISECOND_CONVERSION)
+from spinn_front_end_common.utilities.globals_variables import get_simulator
from .abstract_connector import AbstractConnector
from spynnaker.pyNN.exceptions import InvalidParameterType
-logger = logging.getLogger(__name__)
-
# Indices of the source and target in the connection list array
_SOURCE = 0
_TARGET = 1
@@ -337,8 +333,7 @@ def conn_list(self, conn_list):
self.__delays = None
try:
delay_column = column_names.index('delay') + _FIRST_PARAM
- machine_time_step = globals_variables.get_simulator(
- ).machine_time_step
+ machine_time_step = get_simulator().machine_time_step
self.__delays = (numpy.rint(
numpy.array(self.__conn_list[:, delay_column]) * (
MICRO_TO_MILLISECOND_CONVERSION / machine_time_step)) *
@@ -373,9 +368,11 @@ def conn_list(self, conn_list):
@property
def column_names(self):
- """ The names of the columns in the array after the first two. \
- Of particular interest is whether ``weight`` and ``delay`` columns\
- are present.
+ """ The names of the columns in the array after the first two.
+
+ .. note::
+ Of particular interest is whether ``weight`` and ``delay`` columns
+ are present.
:rtype: list(str)
"""
@@ -386,8 +383,8 @@ def column_names(self, column_names):
self.__column_names = column_names
def get_extra_parameters(self):
- """ Getter for the extra parameters. Excludes ``weight`` and\
- ``delay`` columns.
+ """ Getter for the extra parameters. Excludes ``weight`` and
+ ``delay`` columns.
:return: The extra parameters
:rtype: ~numpy.ndarray
diff --git a/spynnaker/pyNN/models/neural_projections/connectors/index_based_probability_connector.py b/spynnaker/pyNN/models/neural_projections/connectors/index_based_probability_connector.py
index 1b7a0250ae3..4e69097e6d6 100644
--- a/spynnaker/pyNN/models/neural_projections/connectors/index_based_probability_connector.py
+++ b/spynnaker/pyNN/models/neural_projections/connectors/index_based_probability_connector.py
@@ -12,8 +12,6 @@
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see .
-
-import logging
import math
import numpy
from numpy import (
@@ -22,10 +20,10 @@
minimum, e, pi)
from spinn_utilities.overrides import overrides
from spinn_utilities.safe_eval import SafeEval
-from spynnaker.pyNN.utilities import utility_calls
+from spynnaker.pyNN.utilities.utility_calls import (
+ get_probable_maximum_selected, round_up)
from .abstract_connector import AbstractConnector
-logger = logging.getLogger(__name__)
# support for arbitrary expression for the indices
_index_expr_context = SafeEval(math, numpy, arccos, arcsin, arctan, arctan2,
ceil, cos, cosh, exp, fabs, floor, fmod, hypot,
@@ -48,9 +46,10 @@ def __init__(
safe=True, callback=None, verbose=False):
"""
:param str index_expression:
- the right-hand side of a valid python expression for
- probability, involving the indices of the pre and post populations,
- that can be parsed by eval(), that computes a probability dist.
+ the right-hand side of a valid Python expression for
+ probability, involving the indices of the pre- and
+ post-populations, that can be parsed by eval(), that computes a
+ probability distribution.
:param bool allow_self_connections:
if the connector is used to connect a Population to itself, this
flag determines whether a neuron is allowed to connect to itself,
@@ -84,7 +83,7 @@ def _update_probs_from_index_expression(self, synapse_info):
@overrides(AbstractConnector.get_delay_maximum)
def get_delay_maximum(self, synapse_info):
self._update_probs_from_index_expression(synapse_info)
- n_connections = utility_calls.get_probable_maximum_selected(
+ n_connections = get_probable_maximum_selected(
synapse_info.n_pre_neurons * synapse_info.n_post_neurons,
synapse_info.n_pre_neurons * synapse_info.n_post_neurons,
numpy.amax(self.__probs))
@@ -95,12 +94,12 @@ def get_n_connections_from_pre_vertex_maximum(
self, post_vertex_slice, synapse_info, min_delay=None,
max_delay=None):
self._update_probs_from_index_expression(synapse_info)
- n_connections = utility_calls.get_probable_maximum_selected(
+ n_connections = get_probable_maximum_selected(
synapse_info.n_pre_neurons * synapse_info.n_post_neurons,
post_vertex_slice.n_atoms, numpy.amax(self.__probs))
if min_delay is None or max_delay is None:
- return int(math.ceil(n_connections))
+ return round_up(n_connections)
return self._get_n_connections_from_pre_vertex_with_delay_maximum(
synapse_info.delays,
@@ -110,14 +109,14 @@ def get_n_connections_from_pre_vertex_maximum(
@overrides(AbstractConnector.get_n_connections_to_post_vertex_maximum)
def get_n_connections_to_post_vertex_maximum(self, synapse_info):
self._update_probs_from_index_expression(synapse_info)
- return utility_calls.get_probable_maximum_selected(
+ return get_probable_maximum_selected(
synapse_info.n_pre_neurons * synapse_info.n_post_neurons,
synapse_info.n_pre_neurons, numpy.amax(self.__probs))
@overrides(AbstractConnector.get_weight_maximum)
def get_weight_maximum(self, synapse_info):
self._update_probs_from_index_expression(synapse_info)
- n_connections = utility_calls.get_probable_maximum_selected(
+ n_connections = get_probable_maximum_selected(
synapse_info.n_pre_neurons * synapse_info.n_post_neurons,
synapse_info.n_pre_neurons * synapse_info.n_post_neurons,
numpy.amax(self.__probs))
@@ -180,9 +179,9 @@ def allow_self_connections(self, new_value):
@property
def index_expression(self):
- """ The right-hand side of a valid python expression for probability,\
- involving the indices of the pre and post populations, that can\
- be parsed by eval(), that computes a probability dist.
+ """ The right-hand side of a valid Python expression for probability,\
+ involving the indices of the pre- and post-populations, that can\
+ be parsed by eval(), that computes a probability distribution.
:rtype: str
"""
diff --git a/spynnaker/pyNN/models/neural_projections/connectors/kernel_connector.py b/spynnaker/pyNN/models/neural_projections/connectors/kernel_connector.py
index b64d4cb1105..a5f9918e255 100644
--- a/spynnaker/pyNN/models/neural_projections/connectors/kernel_connector.py
+++ b/spynnaker/pyNN/models/neural_projections/connectors/kernel_connector.py
@@ -46,6 +46,15 @@ class KernelConnector(AbstractGenerateConnectorOnMachine):
Should these include `allow_self_connections` and `with_replacement`?
"""
+ __slots__ = (
+ "_kernel_w", "_kernel_h", "_hlf_k_w", "_hlf_k_h",
+ "_pre_w", "_pre_h", "_post_w", "_post_h",
+ "_pre_start_w", "_pre_start_h", "_post_start_w", "_post_start_h",
+ "_pre_step_w", "_pre_step_h", "_post_step_w", "_post_step_h",
+ "_krn_weights", "_krn_delays", "_shape_pre", "_shape_post",
+ "_shape_common", "_common_w", "_common_h", "_post_as_pre")
+
+ __KERNEL_ARRAY_TYPES = (numpy.ndarray, ConvolutionKernel)
def __init__(
self, shape_pre, shape_post, shape_kernel, weight_kernel,
@@ -65,11 +74,11 @@ def __init__(
:type shape_kernel: list(int) or tuple(int,int)
:param weight_kernel: (optional)
2D matrix of size shape_kernel describing the weights
- :type weight_kernel: ~numpy.ndarray or ~pyNN.random.NumpyRNG \
+ :type weight_kernel: ~numpy.ndarray or ~pyNN.random.NumpyRNG
or int or float or list(int) or list(float) or None
:param delay_kernel: (optional)
2D matrix of size shape_kernel describing the delays
- :type delay_kernel: ~numpy.ndarray or ~pyNN.random.NumpyRNG \
+ :type delay_kernel: ~numpy.ndarray or ~pyNN.random.NumpyRNG
or int or float or list(int) or list(float) or None
:param shape_common: (optional)
2D shape of common coordinate system (for both pre and post,
@@ -177,13 +186,11 @@ def __post_as_pre(self, post_vertex_slice):
:param ~pacman.model.graphs.common.Slice post_vertex_slice:
:rtype: tuple(~numpy.ndarray, ~numpy.ndarray)
"""
- # TODO: When slices become hashable, update this code to use them
- # directly as the cache index
- if str(post_vertex_slice) not in self._post_as_pre:
+ if post_vertex_slice not in self._post_as_pre:
post_r, post_c = self.__to_post_coords(post_vertex_slice)
- self._post_as_pre[str(post_vertex_slice)] = \
+ self._post_as_pre[post_vertex_slice] = \
self.__map_to_pre_coords(post_r, post_c)
- return self._post_as_pre[str(post_vertex_slice)]
+ return self._post_as_pre[post_vertex_slice]
def __pre_as_post(self, pre_r, pre_c):
""" Write pre coords as post coords.
@@ -200,7 +207,7 @@ def __get_kernel_vals(self, vals):
""" Convert kernel values given into the correct format.
:param vals:
- :type vals: int or float or ~pyNN.random.NumpyRNG or ~numpy.ndarray\
+ :type vals: int or float or ~pyNN.random.NumpyRNG or ~numpy.ndarray
or ConvolutionKernel
:rtype: ~numpy.ndarray
"""
@@ -212,8 +219,8 @@ def __get_kernel_vals(self, vals):
return numpy.array(vals.next(krn_size)).reshape(krn_shape)
elif numpy.isscalar(vals):
return vals * numpy.ones(krn_shape)
- elif ((isinstance(vals, numpy.ndarray) or
- isinstance(vals, ConvolutionKernel)) and
+ elif (
+ isinstance(vals, self.__KERNEL_ARRAY_TYPES) and
vals.shape[HEIGHT] == self._kernel_h and
vals.shape[WIDTH] == self._kernel_w):
return vals.view(ConvolutionKernel)
@@ -228,10 +235,10 @@ def __compute_statistics(
""" Compute the relevant information required for the connections.
:param weights:
- :type weights: int or float or ~pyNN.random.NumpyRNG or \
+ :type weights: int or float or ~pyNN.random.NumpyRNG or
~numpy.ndarray or ConvolutionKernel
:param delays:
- :type delays: int or float or ~pyNN.random.NumpyRNG or ~numpy.ndarray\
+ :type delays: int or float or ~pyNN.random.NumpyRNG or ~numpy.ndarray
or ConvolutionKernel
:param ~pacman.model.graphs.common.Slice pre_vertex_slice:
:param ~pacman.model.graphs.common.Slice post_vertex_slice:
diff --git a/spynnaker/pyNN/models/neural_projections/connectors/multapse_connector.py b/spynnaker/pyNN/models/neural_projections/connectors/multapse_connector.py
index f0229340b0f..060f4d8a023 100644
--- a/spynnaker/pyNN/models/neural_projections/connectors/multapse_connector.py
+++ b/spynnaker/pyNN/models/neural_projections/connectors/multapse_connector.py
@@ -12,16 +12,14 @@
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see .
-
-import logging
-import math
import numpy.random
from six import raise_from
from spinn_utilities.abstract_base import abstractmethod
from spinn_utilities.overrides import overrides
from pacman.model.graphs.common import Slice
from spinn_front_end_common.utilities.constants import BYTES_PER_WORD
-from spynnaker.pyNN.utilities import utility_calls
+from spynnaker.pyNN.utilities.utility_calls import (
+ get_probable_maximum_selected, round_up)
from spynnaker.pyNN.exceptions import SpynnakerException
from .abstract_connector import AbstractConnector
from .abstract_generate_connector_on_machine import (
@@ -31,8 +29,6 @@
N_GEN_PARAMS = 8
-logger = logging.getLogger(__name__)
-
class MultapseConnector(AbstractGenerateConnectorOnMachine,
AbstractConnectorSupportsViewsOnMachine):
@@ -148,14 +144,14 @@ def get_n_connections_from_pre_vertex_maximum(
prob_in_slice = min(
post_vertex_slice.n_atoms / float(synapse_info.n_post_neurons),
1.0)
- max_in_slice = utility_calls.get_probable_maximum_selected(
+ max_in_slice = get_probable_maximum_selected(
self.__num_synapses, self.__num_synapses, prob_in_slice)
prob_in_row = 1.0 / synapse_info.n_pre_neurons
- n_connections = utility_calls.get_probable_maximum_selected(
+ n_connections = get_probable_maximum_selected(
self.__num_synapses, max_in_slice, prob_in_row)
if min_delay is None or max_delay is None:
- return int(math.ceil(n_connections))
+ return round_up(n_connections)
return self._get_n_connections_from_pre_vertex_with_delay_maximum(
synapse_info.delays,
@@ -165,7 +161,7 @@ def get_n_connections_from_pre_vertex_maximum(
@overrides(AbstractConnector.get_n_connections_to_post_vertex_maximum)
def get_n_connections_to_post_vertex_maximum(self, synapse_info):
prob_of_choosing_post_atom = 1.0 / synapse_info.n_post_neurons
- return utility_calls.get_probable_maximum_selected(
+ return get_probable_maximum_selected(
self.__num_synapses, self.__num_synapses,
prob_of_choosing_post_atom)
diff --git a/spynnaker/pyNN/models/neural_projections/connectors/one_to_one_connector.py b/spynnaker/pyNN/models/neural_projections/connectors/one_to_one_connector.py
index f730ddacfb8..77b07d6403a 100644
--- a/spynnaker/pyNN/models/neural_projections/connectors/one_to_one_connector.py
+++ b/spynnaker/pyNN/models/neural_projections/connectors/one_to_one_connector.py
@@ -12,8 +12,6 @@
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see .
-
-import logging
import numpy
from spinn_utilities.overrides import overrides
from .abstract_connector import AbstractConnector
@@ -22,8 +20,6 @@
from .abstract_connector_supports_views_on_machine import (
AbstractConnectorSupportsViewsOnMachine)
-logger = logging.getLogger(__name__)
-
class OneToOneConnector(AbstractGenerateConnectorOnMachine,
AbstractConnectorSupportsViewsOnMachine):
@@ -113,8 +109,7 @@ def create_synaptic_block(
def __repr__(self):
return "OneToOneConnector()"
- def _get_pre_post_limits(
- self, pre_slice, post_slice, synapse_info):
+ def _get_pre_post_limits(self, pre_slice, post_slice, synapse_info):
"""
:param ~pacman.model.graphs.common.Slice pre_slice:
:param ~pacman.model.graphs.common.Slice post_slice:
diff --git a/spynnaker/pyNN/models/neural_projections/connectors/small_world_connector.py b/spynnaker/pyNN/models/neural_projections/connectors/small_world_connector.py
index 9df9a7e4cbd..7c6cc61c870 100644
--- a/spynnaker/pyNN/models/neural_projections/connectors/small_world_connector.py
+++ b/spynnaker/pyNN/models/neural_projections/connectors/small_world_connector.py
@@ -12,11 +12,10 @@
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see .
-import math
-
import numpy
from spinn_utilities.overrides import overrides
from .abstract_connector import AbstractConnector
+from spynnaker.pyNN.utilities.utility_calls import round_up
class SmallWorldConnector(AbstractConnector):
@@ -85,7 +84,7 @@ def _set_n_connections(self, synapse_info):
self.__mask = (d < self.__degree).astype(float)
- self.__n_connections = int(math.ceil(numpy.sum(self.__mask)))
+ self.__n_connections = round_up(numpy.sum(self.__mask))
@overrides(AbstractConnector.get_delay_maximum)
def get_delay_maximum(self, synapse_info):
diff --git a/spynnaker/pyNN/models/neural_projections/delay_afferent_machine_edge.py b/spynnaker/pyNN/models/neural_projections/delay_afferent_machine_edge.py
index 1d4faef5be3..8d8777c1668 100644
--- a/spynnaker/pyNN/models/neural_projections/delay_afferent_machine_edge.py
+++ b/spynnaker/pyNN/models/neural_projections/delay_afferent_machine_edge.py
@@ -12,15 +12,11 @@
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see .
-
-import logging
from spinn_utilities.overrides import overrides
from pacman.model.graphs.machine import MachineEdge
from spynnaker.pyNN.models.abstract_models import (
AbstractWeightUpdatable, AbstractFilterableEdge)
-logger = logging.getLogger(__name__)
-
class DelayAfferentMachineEdge(
MachineEdge, AbstractFilterableEdge, AbstractWeightUpdatable):
diff --git a/spynnaker/pyNN/models/neural_projections/projection_application_edge.py b/spynnaker/pyNN/models/neural_projections/projection_application_edge.py
index 1b617955077..7d21ef22cc4 100644
--- a/spynnaker/pyNN/models/neural_projections/projection_application_edge.py
+++ b/spynnaker/pyNN/models/neural_projections/projection_application_edge.py
@@ -12,14 +12,10 @@
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see .
-
-import logging
from spinn_utilities.overrides import overrides
from pacman.model.graphs.application import ApplicationEdge
from .projection_machine_edge import ProjectionMachineEdge
from spynnaker.pyNN.models.abstract_models import AbstractFilterableEdge
-
-logger = logging.getLogger(__name__)
_DynamicsStructural = None
diff --git a/spynnaker/pyNN/models/neural_projections/synapse_information.py b/spynnaker/pyNN/models/neural_projections/synapse_information.py
index d41264f61c5..500cc325846 100644
--- a/spynnaker/pyNN/models/neural_projections/synapse_information.py
+++ b/spynnaker/pyNN/models/neural_projections/synapse_information.py
@@ -17,7 +17,7 @@
from spynnaker.pyNN.models.neural_projections.connectors import (
AbstractGenerateConnectorOnMachine)
from spynnaker.pyNN.models.neuron.synapse_dynamics import (
- AbstractGenerateOnMachine)
+ AbstractGenerateOnMachine, AbstractSynapseDynamicsStructural)
class SynapseInformation(object):
@@ -47,8 +47,8 @@ def __init__(self, connector, pre_population, post_population,
The population sending spikes to the synapse
:param PyNNPopulationCommon post_population:
The population hosting the synapse
- :param bool prepop_is_view: Whether the prepopulation is a view
- :param bool postpop_is_view: Whether the postpopulation is a view
+ :param bool prepop_is_view: Whether the pre-population is a view
+ :param bool postpop_is_view: Whether the post-population is a view
:param rng: Seeded random number generator
:type rng: ~pyNN.random.NumpyRNG or None
:param AbstractSynapseDynamics synapse_dynamics:
@@ -96,7 +96,7 @@ def post_population(self):
@property
def n_pre_neurons(self):
- """ The number of neurons in the prepopulation
+ """ The number of neurons in the pre-population
:rtype: int
"""
@@ -104,7 +104,7 @@ def n_pre_neurons(self):
@property
def n_post_neurons(self):
- """ The number of neurons in the postpopulation
+ """ The number of neurons in the post-population
:rtype: int
"""
@@ -112,7 +112,7 @@ def n_post_neurons(self):
@property
def prepop_is_view(self):
- """ Whether the prepopulation is a view
+ """ Whether the pre-population is a view
:rtype: bool
"""
@@ -120,7 +120,7 @@ def prepop_is_view(self):
@property
def postpop_is_view(self):
- """ Whether the postpopulation is a view
+ """ Whether the post-population is a view
:rtype: bool
"""
@@ -142,6 +142,16 @@ def synapse_dynamics(self):
"""
return self.__synapse_dynamics
+ @property
+ def is_structural(self):
+ """ Whether the dynamic behaviour of the synapse is structurally \
+ plastic.
+
+ :rtype: bool
+ """
+ return isinstance(self.__synapse_dynamics,
+ AbstractSynapseDynamicsStructural)
+
@property
def synapse_type(self):
""" The type of the synapse
diff --git a/spynnaker/pyNN/models/neural_properties/neural_parameter.py b/spynnaker/pyNN/models/neural_properties/neural_parameter.py
index bc1887e6e84..757d591c976 100644
--- a/spynnaker/pyNN/models/neural_properties/neural_parameter.py
+++ b/spynnaker/pyNN/models/neural_properties/neural_parameter.py
@@ -111,8 +111,8 @@ def __init__(self, value, datatype, slice_start, slice_stop, spec):
""" Iterator that repeats the single values the required number of\
times.
- Allows a single Value parameter to be treated the same as parameters\
- with len. \
+ Allows a single Value parameter to be treated the same as parameters
+ with len.
Caches `cmd_word_list` and `cmd_string` so they are only created once.
:param value: The simple value that is the data for each element
@@ -146,10 +146,10 @@ class NeuronParameter(object):
def __init__(self, value, data_type):
"""
- :param value: what the value of the parameter is; if a list or array,\
+ :param value: what the value of the parameter is; if a list or array,
potentially provides a different value for each neuron
- :type value: int or float or bool or list(int) or list(float) or \
- list(bool) or ~numpy.ndarray or \
+ :type value: int or float or bool or list(int) or list(float) or
+ list(bool) or ~numpy.ndarray or
~spinn_utilities.ranged.AbstractList
:param ~data_specification.enums.DataType data_type:
The serialization type of the parameter in the neuron model.
@@ -164,8 +164,8 @@ def get_value(self):
""" What the value of the parameter is; if a list or array,\
potentially provides a different value for each neuron.
- :rtype: int or float or bool or list(int) or list(float) or \
- list(bool) or ~numpy.ndarray or \
+ :rtype: int or float or bool or list(int) or list(float) or
+ list(bool) or ~numpy.ndarray or
~spinn_utilities.ranged.AbstractList
"""
return self.__value
@@ -186,7 +186,7 @@ def iterator_by_slice(self, slice_start, slice_stop, spec):
:param ~data_specification.DataSpecificationGenerator spec:
The data specification to eventually write to.
(Note that this does not actually do the write).
- :return: Iterator that produces a command to write to the\
+ :return: Iterator that produces a command to write to the
specification for each element in the slice.
:rtype: six.Iterator(tuple(bytearray, str))
"""
diff --git a/spynnaker/pyNN/models/neuron/abstract_population_vertex.py b/spynnaker/pyNN/models/neuron/abstract_population_vertex.py
index bea13ea7574..5be782f0ce6 100644
--- a/spynnaker/pyNN/models/neuron/abstract_population_vertex.py
+++ b/spynnaker/pyNN/models/neuron/abstract_population_vertex.py
@@ -12,10 +12,7 @@
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see .
-
-import logging
import os
-import math
from spinn_utilities.overrides import overrides
from pacman.model.constraints.key_allocator_constraints import (
ContiguousKeyRangeContraint)
@@ -23,6 +20,9 @@
from pacman.model.graphs.application import ApplicationVertex
from pacman.model.resources import (
ConstantSDRAM, CPUCyclesPerTickResource, DTCMResource, ResourceContainer)
+from pacman.utilities.algorithm_utilities.partition_algorithm_utilities \
+ import (
+ determine_max_atoms_for_vertex)
from spinn_front_end_common.abstract_models import (
AbstractChangableAfterRun, AbstractProvidesIncomingPartitionConstraints,
AbstractProvidesOutgoingPartitionConstraints, AbstractHasAssociatedBinary,
@@ -30,29 +30,38 @@
AbstractCanReset)
from spinn_front_end_common.abstract_models.impl import (
ProvidesKeyToAtomMappingImpl)
-from spinn_front_end_common.utilities import (
- constants as common_constants, helpful_functions, globals_variables)
from spinn_front_end_common.utilities.constants import (
- BYTES_PER_WORD, SYSTEM_BYTES_REQUIREMENT)
+ BYTES_PER_WORD, SIMULATION_N_BYTES, SYSTEM_BYTES_REQUIREMENT)
+from spinn_front_end_common.utilities.helpful_functions import (
+ read_config_int, locate_memory_region_for_placement)
+from spinn_front_end_common.utilities.globals_variables import get_simulator
from spinn_front_end_common.utilities.utility_objs import ExecutableType
-from spinn_front_end_common.interface.simulation import simulation_utilities
-from spinn_front_end_common.interface.profiling import profile_utils
-from spynnaker.pyNN.utilities.constants import POPULATION_BASED_REGIONS
-from spynnaker.pyNN.models.common import (
- AbstractSpikeRecordable, AbstractNeuronRecordable, NeuronRecorder)
-from spynnaker.pyNN.utilities import constants, bit_field_utilities
+from spinn_front_end_common.interface.simulation.simulation_utilities import (
+ get_simulation_header_array)
+from spinn_front_end_common.interface.profiling.profile_utils import (
+ get_profile_region_size, reserve_profile_region, write_profile_region_data)
+from spynnaker.pyNN.utilities.constants import (
+ POPULATION_BASED_REGIONS, SPIKE_PARTITION_ID, BITS_PER_WORD)
+from spynnaker.pyNN.utilities.ranged import (
+ SpynnakerRangeDictionary, SpynnakerRangedList)
+from spynnaker.pyNN.utilities.utility_calls import ceildiv
+from spynnaker.pyNN.utilities.bit_field_utilities import (
+ exact_sdram_for_bit_field_builder_region,
+ get_estimated_sdram_for_key_region,
+ reserve_bit_field_regions, write_bitfield_init_data,
+ ELEMENTS_USED_IN_EACH_BIT_FIELD)
+from spynnaker.pyNN.exceptions import InvalidParameterType
from spynnaker.pyNN.models.abstract_models import (
AbstractPopulationInitializable, AbstractAcceptsIncomingSynapses,
AbstractPopulationSettable, AbstractReadParametersBeforeSet,
AbstractContainsUnits)
-from spynnaker.pyNN.exceptions import InvalidParameterType
-from spynnaker.pyNN.utilities.ranged import (
- SpynnakerRangeDictionary, SpynnakerRangedList)
+from spynnaker.pyNN.models.common import (
+ AbstractSpikeRecordable, AbstractNeuronRecordable, NeuronRecorder)
from .synapse_dynamics import AbstractSynapseDynamicsStructural
from .synaptic_manager import SynapticManager
from .population_machine_vertex import PopulationMachineVertex
-
-logger = logging.getLogger(__name__)
+from spynnaker.pyNN.models.utility_models.delays import DelayExtensionVertex
+from spynnaker.pyNN.models.neural_projections import ProjectionApplicationEdge
# TODO: Make sure these values are correct (particularly CPU cycles)
_NEURON_BASE_DTCM_USAGE_IN_BYTES = 9 * BYTES_PER_WORD
@@ -80,7 +89,8 @@ class AbstractPopulationVertex(
AbstractReadParametersBeforeSet, AbstractAcceptsIncomingSynapses,
ProvidesKeyToAtomMappingImpl, AbstractCanReset):
""" Underlying vertex model for Neural Populations.
- Not actually abstract.
+
+ Not actually abstract.
"""
__slots__ = [
@@ -134,8 +144,8 @@ def __init__(
:param spikes_per_second: Expected spike rate
:type spikes_per_second: float or None
:param ring_buffer_sigma:
- How many SD above the mean to go for upper bound of ring buffer \
- size; a good starting choice is 5.0. Given length of simulation \
+ How many SD above the mean to go for upper bound of ring buffer
+ size; a good starting choice is 5.0. Given length of simulation
we can set this for approximate number of saturation events.
:type ring_buffer_sigma: float or None
:param incoming_spike_buffer_size:
@@ -158,7 +168,7 @@ def __init__(
self.__incoming_spike_buffer_size = incoming_spike_buffer_size
# get config from simulator
- config = globals_variables.get_simulator().config
+ config = get_simulator().config
if incoming_spike_buffer_size is None:
self.__incoming_spike_buffer_size = config.getint(
@@ -194,7 +204,7 @@ def __init__(
self.__has_reset_last = True
# Set up for profiling
- self.__n_profile_samples = helpful_functions.read_config_int(
+ self.__n_profile_samples = read_config_int(
config, "Reports", "n_profile_samples")
@property
@@ -275,6 +285,7 @@ def get_cpu_usage_for_atoms(self, vertex_slice):
def get_dtcm_usage_for_atoms(self, vertex_slice):
"""
:param ~pacman.model.graphs.common.Slice vertex_slice:
+ :rtype: int
"""
return (
_NEURON_BASE_DTCM_USAGE_IN_BYTES +
@@ -288,6 +299,7 @@ def _get_sdram_usage_for_neuron_params(self, vertex_slice):
:param ~pacman.model.graphs.common.Slice vertex_slice:
the slice of atoms.
:return: The SDRAM required for the neuron region
+ :rtype: int
"""
return (
self._BYTES_TILL_START_OF_GLOBAL_PARAMETERS +
@@ -295,7 +307,14 @@ def _get_sdram_usage_for_neuron_params(self, vertex_slice):
def _get_sdram_usage_for_atoms(
self, vertex_slice, graph, machine_time_step):
- sdram_requirement = (
+ """
+ :param ~pacman.model.graphs.common.Slice vertex_slice:
+ :param ~.ApplicationGraph graph:
+ :param int machine_time_step:
+ :return: number of bytes
+ :rtype: int
+ """
+ return (
SYSTEM_BYTES_REQUIREMENT +
self._get_sdram_usage_for_neuron_params(vertex_slice) +
self._neuron_recorder.get_static_sdram_usage(vertex_slice) +
@@ -303,14 +322,10 @@ def _get_sdram_usage_for_atoms(
len(PopulationMachineVertex.EXTRA_PROVENANCE_DATA_ENTRIES)) +
self.__synapse_manager.get_sdram_usage_in_bytes(
vertex_slice, machine_time_step, graph, self) +
- profile_utils.get_profile_region_size(
- self.__n_profile_samples) +
- bit_field_utilities.get_estimated_sdram_for_bit_field_region(
- graph, self) +
- bit_field_utilities.get_estimated_sdram_for_key_region(
- graph, self) +
- bit_field_utilities.exact_sdram_for_bit_field_builder_region())
- return sdram_requirement
+ get_profile_region_size(self.__n_profile_samples) +
+ self.__estimate_sdram_for_bit_field_region(graph) +
+ get_estimated_sdram_for_key_region(graph, self) +
+ exact_sdram_for_bit_field_builder_region())
def _reserve_memory_regions(
self, spec, vertex_slice, vertex, machine_graph, n_key_map):
@@ -322,15 +337,14 @@ def _reserve_memory_regions(
the slice of atoms from the application vertex
:param ~.MachineVertex vertex: this vertex
:param ~.MachineGraph machine_graph: machine graph
- :param n_key_map: nkey map
- :return: None
+ :param ~.AbstractMachinePartitionNKeysMap n_key_map: nkey map
"""
spec.comment("\nReserving memory space for data regions:\n\n")
# Reserve memory:
spec.reserve_memory_region(
region=POPULATION_BASED_REGIONS.SYSTEM.value,
- size=common_constants.SIMULATION_N_BYTES,
+ size=SIMULATION_N_BYTES,
label='System')
self._reserve_neuron_params_data_region(spec, vertex_slice)
@@ -340,12 +354,12 @@ def _reserve_memory_regions(
size=self._neuron_recorder.get_static_sdram_usage(vertex_slice),
label="neuron recording")
- profile_utils.reserve_profile_region(
+ reserve_profile_region(
spec, POPULATION_BASED_REGIONS.PROFILING.value,
self.__n_profile_samples)
# reserve bit field region
- bit_field_utilities.reserve_bit_field_regions(
+ reserve_bit_field_regions(
spec, machine_graph, n_key_map, vertex,
POPULATION_BASED_REGIONS.BIT_FIELD_BUILDER.value,
POPULATION_BASED_REGIONS.BIT_FIELD_FILTER.value,
@@ -356,11 +370,10 @@ def _reserve_memory_regions(
def _reserve_neuron_params_data_region(self, spec, vertex_slice):
""" Reserve the neuron parameter data region.
- :param ~data_specification.DataSpecificationGenerator spec:
+ :param ~.DataSpecificationGenerator spec:
the spec to write the DSG region to
:param ~pacman.model.graphs.common.Slice vertex_slice:
the slice of atoms from the application vertex
- :return: None
"""
params_size = self._get_sdram_usage_for_neuron_params(vertex_slice)
spec.reserve_memory_region(
@@ -369,6 +382,12 @@ def _reserve_neuron_params_data_region(self, spec, vertex_slice):
@staticmethod
def __copy_ranged_dict(source, merge=None, merge_keys=None):
+ """
+ :param SpynnakerRangeDictionary source:
+ :param SpynnakerRangeDictionary merge:
+ :param set merge_keys:
+ :rtype: SpynnakerRangeDictionary
+ """
target = SpynnakerRangeDictionary(len(source))
for key in source.keys():
copy_list = SpynnakerRangedList(len(source))
@@ -386,7 +405,14 @@ def __copy_ranged_dict(source, merge=None, merge_keys=None):
def _write_neuron_parameters(
self, spec, key, vertex_slice, machine_time_step,
time_scale_factor):
-
+ """
+ :param ~.DataSpecificationGenerator spec:
+ :param key:
+ :type key: int or None
+ :param ~pacman.model.graphs.common.Slice vertex_slice:
+ :param int machine_time_step:
+ :param int time_scale_factor:
+ """
# If resetting, reset any state variables that need to be reset
if (self.__has_reset_last and
self.__initial_state_variables is not None):
@@ -410,15 +436,13 @@ def _write_neuron_parameters(
n_atoms))
# Set the focus to the memory region 2 (neuron parameters):
- spec.switch_write_focus(
- region=constants.POPULATION_BASED_REGIONS.NEURON_PARAMS.value)
+ spec.switch_write_focus(POPULATION_BASED_REGIONS.NEURON_PARAMS.value)
# Write the random back off value
max_offset = (
machine_time_step * time_scale_factor) // _MAX_OFFSET_DENOMINATOR
spec.write_value(
- int(math.ceil(max_offset / self.__n_subvertices)) *
- self.__n_data_specs)
+ ceildiv(max_offset, self.__n_subvertices) * self.__n_data_specs)
self.__n_data_specs += 1
# Write the number of microseconds between sending spikes
@@ -461,6 +485,11 @@ def _write_neuron_parameters(
def regenerate_data_specification(
self, spec, placement, machine_time_step, time_scale_factor,
routing_info):
+ """
+ :param int machine_time_step: (injected)
+ :param int time_scale_factor: (injected)
+ :param ~pacman.model.routing_info.RoutingInfo routing_info: (injected)
+ """
# pylint: disable=too-many-arguments, arguments-differ
vertex_slice = placement.vertex.vertex_slice
@@ -470,7 +499,7 @@ def regenerate_data_specification(
# write the neuron params into the new DSG region
self._write_neuron_parameters(
key=routing_info.get_first_key_from_pre_vertex(
- placement.vertex, constants.SPIKE_PARTITION_ID),
+ placement.vertex, SPIKE_PARTITION_ID),
machine_time_step=machine_time_step, spec=spec,
time_scale_factor=time_scale_factor,
vertex_slice=vertex_slice)
@@ -508,13 +537,19 @@ def generate_data_specification(
application_graph, machine_graph, routing_info, data_n_time_steps,
n_key_map):
"""
- :param machine_time_step: (injected)
- :param time_scale_factor: (injected)
+ :param int machine_time_step: (injected)
+ :param int time_scale_factor: (injected)
:param application_graph: (injected)
+ :type application_graph:
+ ~pacman.model.graphs.application.ApplicationGraph
:param machine_graph: (injected)
- :param routing_info: (injected)
- :param data_n_time_steps: (injected)
+ :type machine_graph:
+ ~pacman.model.graphs.machine.MachineGraph
+ :param ~pacman.model.routing_info.RoutingInfo routing_info: (injected)
+ :param int data_n_time_steps: (injected)
:param n_key_map: (injected)
+ :type n_key_map:
+ ~pacman.model.routing_info.AbstractMachinePartitionNKeysMap
"""
# pylint: disable=too-many-arguments, arguments-differ
vertex = placement.vertex
@@ -533,11 +568,11 @@ def generate_data_specification(
# Get the key
key = routing_info.get_first_key_from_pre_vertex(
- vertex, constants.SPIKE_PARTITION_ID)
+ vertex, SPIKE_PARTITION_ID)
# Write the setup region
spec.switch_write_focus(POPULATION_BASED_REGIONS.SYSTEM.value)
- spec.write_array(simulation_utilities.get_simulation_header_array(
+ spec.write_array(get_simulation_header_array(
self.get_binary_file_name(), machine_time_step,
time_scale_factor))
@@ -551,7 +586,7 @@ def generate_data_specification(
spec, key, vertex_slice, machine_time_step, time_scale_factor)
# write profile data
- profile_utils.write_profile_region_data(
+ write_profile_region_data(
spec, POPULATION_BASED_REGIONS.PROFILING.value,
self.__n_profile_samples)
@@ -568,7 +603,7 @@ def generate_data_specification(
self.__synapse_manager.on_chip_written_matrix_size)
# write up the bitfield builder data
- bit_field_utilities.write_bitfield_init_data(
+ write_bitfield_init_data(
spec, vertex, machine_graph, routing_info,
n_key_map, POPULATION_BASED_REGIONS.BIT_FIELD_BUILDER.value,
POPULATION_BASED_REGIONS.POPULATION_TABLE.value,
@@ -586,7 +621,6 @@ def generate_data_specification(
@overrides(AbstractHasAssociatedBinary.get_binary_file_name)
def get_binary_file_name(self):
-
# Split binary name into title and extension
binary_title, binary_extension = os.path.splitext(
self.__neuron_impl.binary_name)
@@ -673,6 +707,11 @@ def initialize_parameters(self):
return self.__pynn_model.default_initial_values.keys()
def _get_parameter(self, variable):
+ """
+ :param str variable:
+ :rtype: str
+ :raises KeyError: If the param with that name doesn't exist
+ """
if variable.endswith("_init"):
# method called with "V_init"
key = variable[:-5]
@@ -725,8 +764,6 @@ def conductance_based(self):
@overrides(AbstractPopulationSettable.get_value)
def get_value(self, key):
- """ Get a property of the overall model.
- """
if key not in self._parameters:
raise InvalidParameterType(
"Population {} does not have parameter {}".format(
@@ -735,8 +772,6 @@ def get_value(self, key):
@overrides(AbstractPopulationSettable.set_value)
def set_value(self, key, value):
- """ Set a property of the overall model.
- """
if key not in self._parameters:
raise InvalidParameterType(
"Population {} does not have parameter {}".format(
@@ -747,12 +782,10 @@ def set_value(self, key, value):
@overrides(AbstractReadParametersBeforeSet.read_parameters_from_machine)
def read_parameters_from_machine(
self, transceiver, placement, vertex_slice):
-
# locate SDRAM address to where the neuron parameters are stored
- neuron_region_sdram_address = \
- helpful_functions.locate_memory_region_for_placement(
- placement, POPULATION_BASED_REGIONS.NEURON_PARAMS.value,
- transceiver)
+ neuron_region_sdram_address = locate_memory_region_for_placement(
+ placement, POPULATION_BASED_REGIONS.NEURON_PARAMS.value,
+ transceiver)
# shift past the extra stuff before neuron parameters that we don't
# need to read
@@ -783,6 +816,9 @@ def weight_scale(self):
@property
def ring_buffer_sigma(self):
+ """
+ :rtype: float or None
+ """
return self.__synapse_manager.ring_buffer_sigma
@ring_buffer_sigma.setter
@@ -794,6 +830,9 @@ def reset_ring_buffer_shifts(self):
@property
def spikes_per_second(self):
+ """
+ :rtype: float or None
+ """
return self.__synapse_manager.spikes_per_second
@spikes_per_second.setter
@@ -821,7 +860,7 @@ def add_pre_run_connection_holder(
def get_connection_holders(self):
"""
- :rtype: dict(tuple(ProjectionApplicationEdge,SynapseInformation),\
+ :rtype: dict(tuple(ProjectionApplicationEdge,SynapseInformation),
ConnectionHolder)
"""
return self.__synapse_manager.get_connection_holders()
@@ -848,21 +887,11 @@ def get_maximum_delay_supported_in_ms(self, machine_time_step):
@overrides(AbstractProvidesIncomingPartitionConstraints.
get_incoming_partition_constraints)
def get_incoming_partition_constraints(self, partition):
- """ Gets the constraints for partitions going into this vertex.
-
- :param partition: partition that goes into this vertex
- :return: list of constraints
- """
return self.__synapse_manager.get_incoming_partition_constraints()
@overrides(AbstractProvidesOutgoingPartitionConstraints.
get_outgoing_partition_constraints)
def get_outgoing_partition_constraints(self, partition):
- """ Gets the constraints for partitions going out of this vertex.
-
- :param partition: the partition that leaves this vertex
- :return: list of constraints
- """
return [ContiguousKeyRangeContraint()]
@overrides(
@@ -888,7 +917,6 @@ def _clear_recording_region(
:param buffer_manager: the buffer manager object
:param placements: the placements object
:param recording_region_id: the recorded region ID for clearing
- :rtype: None
"""
for machine_vertex in self.machine_vertices:
placement = placements.get_placement_of_vertex(machine_vertex)
@@ -909,11 +937,11 @@ def get_units(self, variable):
def describe(self):
""" Get a human-readable description of the cell or synapse type.
- The output may be customised by specifying a different template\
- together with an associated template engine\
+ The output may be customised by specifying a different template
+ together with an associated template engine
(see :py:mod:`pyNN.descriptions`).
- If template is None, then a dictionary containing the template context\
+ If template is None, then a dictionary containing the template context
will be returned.
:rtype: dict(str, ...)
@@ -931,6 +959,11 @@ def describe(self):
return context
def get_synapse_id_by_target(self, target):
+ """ Get the ID of a synapse given the name
+
+ :param str target: The name of the synapse
+ :rtype: int
+ """
return self.__neuron_impl.get_synapse_id_by_target(target)
def __str__(self):
@@ -957,3 +990,34 @@ def reset_to_first_timestep(self):
if self.__synapse_manager.changes_during_run:
self.__change_requires_data_generation = True
self.__change_requires_neuron_parameters_reload = False
+
+ def __estimate_sdram_for_bit_field_region(self, app_graph):
+ """ Estimates the SDRAM for the bit field region of this vertex
+
+ :param ~.ApplicationGraph app_graph: the app graph
+ :return: the estimated number of bytes used by the bit field region
+ :rtype: int
+ """
+ return sum(
+ self.__estimate_sdram_for_edge_bit_fields(incoming_edge)
+ for incoming_edge in app_graph.get_edges_ending_at_vertex(self)
+ if isinstance(incoming_edge, ProjectionApplicationEdge))
+
+ @staticmethod
+ def __estimate_sdram_for_edge_bit_fields(edge):
+ """
+ :param ProjectionApplicationEdge edge:
+ :rtype: int
+ """
+ n_atoms = edge.pre_vertex.n_atoms
+ max_atoms = min(
+ determine_max_atoms_for_vertex(edge.pre_vertex), n_atoms)
+
+ # Get the number of likely vertices
+ n_machine_vertices = ceildiv(n_atoms, max_atoms)
+ n_atoms_per_machine_vertex = ceildiv(n_atoms, n_machine_vertices)
+ if isinstance(edge.pre_vertex, DelayExtensionVertex):
+ n_atoms_per_machine_vertex *= edge.pre_vertex.n_delay_stages
+ n_words_for_atoms = ceildiv(n_atoms_per_machine_vertex, BITS_PER_WORD)
+ return BYTES_PER_WORD * (ELEMENTS_USED_IN_EACH_BIT_FIELD + (
+ n_words_for_atoms * n_machine_vertices))
diff --git a/spynnaker/pyNN/models/neuron/abstract_pynn_neuron_model.py b/spynnaker/pyNN/models/neuron/abstract_pynn_neuron_model.py
index f69a8b131ba..f143cb39561 100644
--- a/spynnaker/pyNN/models/neuron/abstract_pynn_neuron_model.py
+++ b/spynnaker/pyNN/models/neuron/abstract_pynn_neuron_model.py
@@ -38,15 +38,26 @@ def __init__(self, model):
@property
def _model(self):
+ """
+ :rtype: AbstractNeuronImpl
+ """
return self.__model
@classmethod
def set_model_max_atoms_per_core(cls, n_atoms=DEFAULT_MAX_ATOMS_PER_CORE):
+ """ Set the maximum number of atoms per core for this model.
+
+ :param int n_atoms: The new maximum
+ """
super(AbstractPyNNNeuronModel, cls).set_model_max_atoms_per_core(
n_atoms)
@classmethod
def get_max_atoms_per_core(cls):
+ """ Get the maximum number of atoms per core for this model.
+
+ :rtype: int
+ """
if cls not in super(AbstractPyNNNeuronModel, cls)._max_atoms_per_core:
return DEFAULT_MAX_ATOMS_PER_CORE
return super(AbstractPyNNNeuronModel, cls).get_max_atoms_per_core()
@@ -56,6 +67,11 @@ def get_max_atoms_per_core(cls):
def create_vertex(
self, n_neurons, label, constraints, spikes_per_second,
ring_buffer_sigma, incoming_spike_buffer_size):
+ """
+ :param float spikes_per_second:
+ :param float ring_buffer_sigma:
+ :param int incoming_spike_buffer_size:
+ """
# pylint: disable=arguments-differ
max_atoms = self.get_max_atoms_per_core()
return AbstractPopulationVertex(
diff --git a/spynnaker/pyNN/models/neuron/abstract_pynn_neuron_model_standard.py b/spynnaker/pyNN/models/neuron/abstract_pynn_neuron_model_standard.py
index dbe3dc24265..78374fbe7c6 100644
--- a/spynnaker/pyNN/models/neuron/abstract_pynn_neuron_model_standard.py
+++ b/spynnaker/pyNN/models/neuron/abstract_pynn_neuron_model_standard.py
@@ -13,9 +13,9 @@
# You should have received a copy of the GNU General Public License
# along with this program. If not, see .
+from spinn_utilities.overrides import overrides
from .abstract_pynn_neuron_model import AbstractPyNNNeuronModel
from spynnaker.pyNN.models.neuron.implementations import NeuronImplStandard
-from spinn_utilities.overrides import overrides
_population_parameters = dict(
AbstractPyNNNeuronModel.default_population_parameters)
diff --git a/spynnaker/pyNN/models/neuron/additional_inputs/additional_input_ca2_adaptive.py b/spynnaker/pyNN/models/neuron/additional_inputs/additional_input_ca2_adaptive.py
index 0c23bafe620..3525cf9cab0 100644
--- a/spynnaker/pyNN/models/neuron/additional_inputs/additional_input_ca2_adaptive.py
+++ b/spynnaker/pyNN/models/neuron/additional_inputs/additional_input_ca2_adaptive.py
@@ -73,11 +73,6 @@ def has_variable(self, variable):
@overrides(AbstractAdditionalInput.get_values)
def get_values(self, parameters, state_variables, vertex_slice, ts):
- """
- :param int ts: machine time step
- """
- # pylint: disable=arguments-differ
-
# Add the rest of the data
return [parameters[TAU_CA2].apply_operation(
operation=lambda x: numpy.exp(float(-ts) / (1000.0 * x))),
diff --git a/spynnaker/pyNN/models/neuron/implementations/abstract_standard_neuron_component.py b/spynnaker/pyNN/models/neuron/implementations/abstract_standard_neuron_component.py
index 9b656e18530..c971e5da948 100644
--- a/spynnaker/pyNN/models/neuron/implementations/abstract_standard_neuron_component.py
+++ b/spynnaker/pyNN/models/neuron/implementations/abstract_standard_neuron_component.py
@@ -87,7 +87,8 @@ def add_state_variables(self, state_variables):
@abstractmethod
def get_values(self, parameters, state_variables, vertex_slice, ts):
- """ Get the values to be written to the machine for this model
+ # The way this docstring is built *is* a hack, but nothing else works
+ (r""" Get the values to be written to the machine for this model
:param ~spinn_utilities.ranged.RangeDictionary parameters:
The holder of the parameters
@@ -97,10 +98,14 @@ def get_values(self, parameters, state_variables, vertex_slice, ts):
The slice of variables being retrieved
:param float ts:
The time to be advanced in one call to the update of this component
- :return: A list with the same length as self.struct.field_types
+ :return: A list with the same length as
+ `self.`\ """
+ ":py:attr:`~spynnaker.pyNN.models.neuron.implementations."
+ r"AbstractStandardNeuronComponent.struct`\ "
+ """`.`\\ :py:attr:`~spynnaker.pyNN.utilities.struct.Struct.field_types`
:rtype: list(int or float or list(int) or list(float) or
~spinn_utilities.ranged.RangedList)
- """
+ """)
def get_data(self, parameters, state_variables, vertex_slice, ts):
""" Get the data *to be written to the machine* for this model.
diff --git a/spynnaker/pyNN/models/neuron/implementations/neuron_impl_standard.py b/spynnaker/pyNN/models/neuron/implementations/neuron_impl_standard.py
index 43023543386..b48e26cee27 100644
--- a/spynnaker/pyNN/models/neuron/implementations/neuron_impl_standard.py
+++ b/spynnaker/pyNN/models/neuron/implementations/neuron_impl_standard.py
@@ -19,7 +19,7 @@
from spinn_utilities.overrides import overrides
from spynnaker.pyNN.models.neuron.input_types import InputTypeConductance
from .abstract_neuron_impl import AbstractNeuronImpl
-from spinn_front_end_common.utilities import globals_variables
+from spinn_front_end_common.utilities.globals_variables import get_simulator
from spinn_front_end_common.utilities.constants import BYTES_PER_WORD
# The size of the n_steps_per_timestep parameter
@@ -187,8 +187,7 @@ def add_state_variables(self, state_variables):
@overrides(AbstractNeuronImpl.get_data)
def get_data(self, parameters, state_variables, vertex_slice):
# Work out the time step per step
- ts = globals_variables.get_simulator().machine_time_step
- ts /= self.__n_steps_per_timestep
+ ts = get_simulator().machine_time_step / self.__n_steps_per_timestep
items = [numpy.array([self.__n_steps_per_timestep], dtype="uint32")]
items.extend(
component.get_data(parameters, state_variables, vertex_slice, ts)
diff --git a/spynnaker/pyNN/models/neuron/master_pop_table.py b/spynnaker/pyNN/models/neuron/master_pop_table.py
index 078c04856c2..84ce2033a15 100644
--- a/spynnaker/pyNN/models/neuron/master_pop_table.py
+++ b/spynnaker/pyNN/models/neuron/master_pop_table.py
@@ -12,19 +12,16 @@
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see .
-
-import logging
-import math
import struct
import numpy
-from spinn_front_end_common.utilities.constants import BYTES_PER_WORD, \
- SARK_PER_MALLOC_SDRAM_USAGE
+from spinn_front_end_common.utilities.constants import (
+ BYTES_PER_WORD, SARK_PER_MALLOC_SDRAM_USAGE)
from spynnaker.pyNN.models.neural_projections import (
ProjectionApplicationEdge, ProjectionMachineEdge)
from spynnaker.pyNN.exceptions import (
SynapseRowTooBigException, SynapticConfigurationException)
+from spynnaker.pyNN.utilities.utility_calls import ceildiv
-logger = logging.getLogger(__name__)
_TWO_WORDS = struct.Struct(".
-from spinn_front_end_common.utilities.constants import \
- MICRO_TO_MILLISECOND_CONVERSION
from spinn_utilities.overrides import overrides
from data_specification.enums import DataType
+from spinn_front_end_common.utilities.constants import (
+ MICRO_TO_MILLISECOND_CONVERSION)
from .abstract_neuron_model import AbstractNeuronModel
from spynnaker.pyNN.models.neuron.implementations import (
AbstractStandardNeuronComponent)
diff --git a/spynnaker/pyNN/models/neuron/plasticity/stdp/common.py b/spynnaker/pyNN/models/neuron/plasticity/stdp/common.py
index c67456a6cda..62b44754fa7 100644
--- a/spynnaker/pyNN/models/neuron/plasticity/stdp/common.py
+++ b/spynnaker/pyNN/models/neuron/plasticity/stdp/common.py
@@ -14,10 +14,8 @@
# along with this program. If not, see .
import math
-import logging
import numpy
-logger = logging.getLogger(__name__)
# Default value of fixed-point one for STDP
STDP_FIXED_POINT_ONE = (1 << 11)
diff --git a/spynnaker/pyNN/models/neuron/plasticity/stdp/timing_dependence/abstract_timing_dependence.py b/spynnaker/pyNN/models/neuron/plasticity/stdp/timing_dependence/abstract_timing_dependence.py
index a11db4e3526..02946be2d5e 100644
--- a/spynnaker/pyNN/models/neuron/plasticity/stdp/timing_dependence/abstract_timing_dependence.py
+++ b/spynnaker/pyNN/models/neuron/plasticity/stdp/timing_dependence/abstract_timing_dependence.py
@@ -89,7 +89,7 @@ def get_provenance_data(self, pre_population_label, post_population_label):
:param str pre_population_label: label of pre.
:param str post_population_label: label of post.
- :rtype: \
+ :rtype:
list(~spinn_front_end_common.utilities.utility_objs.ProvenanceDataItem)
"""
# pylint: disable=unused-argument
diff --git a/spynnaker/pyNN/models/neuron/plasticity/stdp/timing_dependence/timing_dependence_pfister_spike_triplet.py b/spynnaker/pyNN/models/neuron/plasticity/stdp/timing_dependence/timing_dependence_pfister_spike_triplet.py
index 1052c4659a0..00aa32619fe 100644
--- a/spynnaker/pyNN/models/neuron/plasticity/stdp/timing_dependence/timing_dependence_pfister_spike_triplet.py
+++ b/spynnaker/pyNN/models/neuron/plasticity/stdp/timing_dependence/timing_dependence_pfister_spike_triplet.py
@@ -13,19 +13,15 @@
# You should have received a copy of the GNU General Public License
# along with this program. If not, see .
-import logging
from spinn_utilities.overrides import overrides
from spinn_front_end_common.utilities.constants import (
BYTES_PER_WORD, MICRO_TO_MILLISECOND_CONVERSION)
+from spinn_front_end_common.utilities.globals_variables import get_simulator
from spynnaker.pyNN.models.neuron.plasticity.stdp.common import (
get_exp_lut_array)
-from spynnaker.pyNN.models.neuron.plasticity.stdp.timing_dependence\
- import AbstractTimingDependence
-from spynnaker.pyNN.models.neuron.plasticity.stdp.synapse_structure\
- import SynapseStructureWeightOnly
-from spinn_front_end_common.utilities.globals_variables import get_simulator
-
-logger = logging.getLogger(__name__)
+from spynnaker.pyNN.models.neuron.plasticity.stdp.synapse_structure import (
+ SynapseStructureWeightOnly)
+from .abstract_timing_dependence import AbstractTimingDependence
class TimingDependencePfisterSpikeTriplet(AbstractTimingDependence):
@@ -112,19 +108,13 @@ def is_same_as(self, timing_dependence):
(self.__tau_y == timing_dependence.tau_y))
@property
+ @overrides(AbstractTimingDependence.vertex_executable_suffix)
def vertex_executable_suffix(self):
- """ The suffix to be appended to the vertex executable for this rule
-
- :rtype: str
- """
return "pfister_triplet"
@property
+ @overrides(AbstractTimingDependence.pre_trace_n_bytes)
def pre_trace_n_bytes(self):
- """ The number of bytes used by the pre-trace of the rule per neuron
-
- :rtype: int
- """
# Triplet rule trace entries consists of two 16-bit traces - R1 and R2
return BYTES_PER_WORD
@@ -136,16 +126,12 @@ def get_parameters_sdram_usage_in_bytes(self):
return lut_array_words * BYTES_PER_WORD
@property
+ @overrides(AbstractTimingDependence.n_weight_terms)
def n_weight_terms(self):
- """ The number of weight terms expected by this timing rule
-
- :rtype: int
- """
return 2
@overrides(AbstractTimingDependence.write_parameters)
def write_parameters(self, spec, machine_time_step, weight_scales):
-
# Write lookup tables
spec.write_array(self.__tau_plus_data)
spec.write_array(self.__tau_minus_data)
@@ -153,11 +139,8 @@ def write_parameters(self, spec, machine_time_step, weight_scales):
spec.write_array(self.__tau_y_data)
@property
+ @overrides(AbstractTimingDependence.synaptic_structure)
def synaptic_structure(self):
- """ Get the synaptic structure of the plastic part of the rows
-
- :rtype: AbstractSynapseStructure
- """
return self.__synapse_structure
@overrides(AbstractTimingDependence.get_parameter_names)
diff --git a/spynnaker/pyNN/models/neuron/plasticity/stdp/timing_dependence/timing_dependence_recurrent.py b/spynnaker/pyNN/models/neuron/plasticity/stdp/timing_dependence/timing_dependence_recurrent.py
index 1e6d1e9277e..add3beb1820 100644
--- a/spynnaker/pyNN/models/neuron/plasticity/stdp/timing_dependence/timing_dependence_recurrent.py
+++ b/spynnaker/pyNN/models/neuron/plasticity/stdp/timing_dependence/timing_dependence_recurrent.py
@@ -14,12 +14,10 @@
# along with this program. If not, see .
import numpy
-from spinn_front_end_common.utilities.constants import \
- MICRO_TO_MILLISECOND_CONVERSION
from spinn_utilities.overrides import overrides
from data_specification.enums import DataType
from spinn_front_end_common.utilities.constants import (
- BYTES_PER_WORD, BYTES_PER_SHORT)
+ BYTES_PER_WORD, BYTES_PER_SHORT, MICRO_TO_MILLISECOND_CONVERSION)
from .abstract_timing_dependence import AbstractTimingDependence
from spynnaker.pyNN.models.neuron.plasticity.stdp.synapse_structure import (
SynapseStructureWeightAccumulator)
@@ -50,6 +48,13 @@ def __init__(
mean_pre_window=default_parameters['mean_pre_window'],
mean_post_window=default_parameters['mean_post_window'],
dual_fsm=default_parameters['dual_fsm']):
+ """
+ :param int accumulator_depression:
+ :param int accumulator_potentiation:
+ :param float mean_pre_window:
+ :param float mean_post_window:
+ :param bool dual_fsm:
+ """
# pylint: disable=too-many-arguments
self.__accumulator_depression_plus_one = accumulator_depression + 1
self.__accumulator_potentiation_minus_one = \
@@ -75,21 +80,15 @@ def is_same_as(self, timing_dependence):
timing_dependence.mean_post_window))
@property
+ @overrides(AbstractTimingDependence.vertex_executable_suffix)
def vertex_executable_suffix(self):
- """ The suffix to be appended to the vertex executable for this rule
-
- :rtype: str
- """
if self.__dual_fsm:
return "recurrent_dual_fsm"
return "recurrent_pre_stochastic"
@property
+ @overrides(AbstractTimingDependence.pre_trace_n_bytes)
def pre_trace_n_bytes(self):
- """ The number of bytes used by the pre-trace of the rule per neuron
-
- :rtype: int
- """
# When using the separate FSMs, pre-trace contains window length,
# otherwise it's in the synapse
return BYTES_PER_SHORT if self.__dual_fsm else 0
@@ -102,16 +101,12 @@ def get_parameters_sdram_usage_in_bytes(self):
2 * STDP_FIXED_POINT_ONE * BYTES_PER_SHORT)
@property
+ @overrides(AbstractTimingDependence.n_weight_terms)
def n_weight_terms(self):
- """ The number of weight terms expected by this timing rule
-
- :rtype: int
- """
return 1
@overrides(AbstractTimingDependence.write_parameters)
def write_parameters(self, spec, machine_time_step, weight_scales):
-
# Write parameters
spec.write_value(data=self.__accumulator_depression_plus_one,
data_type=DataType.INT32)
@@ -142,11 +137,8 @@ def _write_exp_dist_lut(spec, mean):
inv_cdf.astype(numpy.uint16), data_type=DataType.UINT16)
@property
+ @overrides(AbstractTimingDependence.synaptic_structure)
def synaptic_structure(self):
- """ Get the synaptic structure of the plastic part of the rows
-
- :rtype: AbstractSynapseStructure
- """
return self.__synapse_structure
@overrides(AbstractTimingDependence.get_parameter_names)
diff --git a/spynnaker/pyNN/models/neuron/plasticity/stdp/timing_dependence/timing_dependence_spike_nearest_pair.py b/spynnaker/pyNN/models/neuron/plasticity/stdp/timing_dependence/timing_dependence_spike_nearest_pair.py
index f58d2a826d6..fd0f58afc19 100644
--- a/spynnaker/pyNN/models/neuron/plasticity/stdp/timing_dependence/timing_dependence_spike_nearest_pair.py
+++ b/spynnaker/pyNN/models/neuron/plasticity/stdp/timing_dependence/timing_dependence_spike_nearest_pair.py
@@ -12,20 +12,15 @@
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see .
-
-import logging
from spinn_utilities.overrides import overrides
from spinn_front_end_common.utilities.constants import (
BYTES_PER_WORD, MICRO_TO_MILLISECOND_CONVERSION)
-
+from spinn_front_end_common.utilities.globals_variables import get_simulator
from spynnaker.pyNN.models.neuron.plasticity.stdp.common import (
get_exp_lut_array)
from spynnaker.pyNN.models.neuron.plasticity.stdp.synapse_structure import (
SynapseStructureWeightOnly)
from .abstract_timing_dependence import AbstractTimingDependence
-from spinn_front_end_common.utilities.globals_variables import get_simulator
-
-logger = logging.getLogger(__name__)
class TimingDependenceSpikeNearestPair(AbstractTimingDependence):
@@ -81,19 +76,13 @@ def is_same_as(self, timing_dependence):
self.__tau_minus == timing_dependence.tau_minus)
@property
+ @overrides(AbstractTimingDependence.vertex_executable_suffix)
def vertex_executable_suffix(self):
- """ The suffix to be appended to the vertex executable for this rule
-
- :rtype: str
- """
return "nearest_pair"
@property
+ @overrides(AbstractTimingDependence.pre_trace_n_bytes)
def pre_trace_n_bytes(self):
- """ The number of bytes used by the pre-trace of the rule per neuron
-
- :rtype: int
- """
# Pair rule requires no pre-synaptic trace when only the nearest
# Neighbours are considered and, a single 16-bit R1 trace
return 0
@@ -104,11 +93,8 @@ def get_parameters_sdram_usage_in_bytes(self):
len(self.__tau_minus_data))
@property
+ @overrides(AbstractTimingDependence.n_weight_terms)
def n_weight_terms(self):
- """ The number of weight terms expected by this timing rule
-
- :rtype: int
- """
return 1
@overrides(AbstractTimingDependence.write_parameters)
@@ -119,11 +105,8 @@ def write_parameters(self, spec, machine_time_step, weight_scales):
spec.write_array(self.__tau_minus_data)
@property
+ @overrides(AbstractTimingDependence.synaptic_structure)
def synaptic_structure(self):
- """ Get the synaptic structure of the plastic part of the rows
-
- :rtype: AbstractSynapseStructure
- """
return self.__synapse_structure
@overrides(AbstractTimingDependence.get_parameter_names)
diff --git a/spynnaker/pyNN/models/neuron/plasticity/stdp/timing_dependence/timing_dependence_spike_pair.py b/spynnaker/pyNN/models/neuron/plasticity/stdp/timing_dependence/timing_dependence_spike_pair.py
index 40cb9ee532b..b1671c20205 100644
--- a/spynnaker/pyNN/models/neuron/plasticity/stdp/timing_dependence/timing_dependence_spike_pair.py
+++ b/spynnaker/pyNN/models/neuron/plasticity/stdp/timing_dependence/timing_dependence_spike_pair.py
@@ -12,23 +12,20 @@
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see .
-
-import logging
from spinn_utilities.overrides import overrides
from spinn_front_end_common.utilities.constants import (
BYTES_PER_SHORT, BYTES_PER_WORD, MICRO_TO_MILLISECOND_CONVERSION)
+from spinn_front_end_common.utilities.globals_variables import get_simulator
from spynnaker.pyNN.models.neuron.plasticity.stdp.common import (
get_exp_lut_array)
from .abstract_timing_dependence import AbstractTimingDependence
from spynnaker.pyNN.models.neuron.plasticity.stdp.synapse_structure import (
SynapseStructureWeightOnly)
-from spinn_front_end_common.utilities.globals_variables import get_simulator
-
-logger = logging.getLogger(__name__)
class TimingDependenceSpikePair(AbstractTimingDependence):
- """ A basic timing dependence STDP rule.
+ """ A basic timing dependence STDP rule where relevance decays \
+ exponentially.
"""
__slots__ = [
"__synapse_structure",
@@ -77,19 +74,13 @@ def is_same_as(self, timing_dependence):
self.__tau_minus == timing_dependence.tau_minus)
@property
+ @overrides(AbstractTimingDependence.vertex_executable_suffix)
def vertex_executable_suffix(self):
- """ The suffix to be appended to the vertex executable for this rule
-
- :rtype: str
- """
return "pair"
@property
+ @overrides(AbstractTimingDependence.pre_trace_n_bytes)
def pre_trace_n_bytes(self):
- """ The number of bytes used by the pre-trace of the rule per neuron
-
- :rtype: int
- """
# Pair rule requires no pre-synaptic trace when only the nearest
# Neighbours are considered and, a single 16-bit R1 trace
return BYTES_PER_SHORT
@@ -100,26 +91,19 @@ def get_parameters_sdram_usage_in_bytes(self):
len(self.__tau_minus_data))
@property
+ @overrides(AbstractTimingDependence.n_weight_terms)
def n_weight_terms(self):
- """ The number of weight terms expected by this timing rule
-
- :rtype: int
- """
return 1
@overrides(AbstractTimingDependence.write_parameters)
def write_parameters(self, spec, machine_time_step, weight_scales):
-
# Write lookup tables
spec.write_array(self.__tau_plus_data)
spec.write_array(self.__tau_minus_data)
@property
+ @overrides(AbstractTimingDependence.synaptic_structure)
def synaptic_structure(self):
- """ Get the synaptic structure of the plastic part of the rows
-
- :rtype: AbstractSynapseStructure
- """
return self.__synapse_structure
@overrides(AbstractTimingDependence.get_parameter_names)
diff --git a/spynnaker/pyNN/models/neuron/plasticity/stdp/timing_dependence/timing_dependence_vogels_2011.py b/spynnaker/pyNN/models/neuron/plasticity/stdp/timing_dependence/timing_dependence_vogels_2011.py
index c75f8672b0e..a5d7efb0e81 100644
--- a/spynnaker/pyNN/models/neuron/plasticity/stdp/timing_dependence/timing_dependence_vogels_2011.py
+++ b/spynnaker/pyNN/models/neuron/plasticity/stdp/timing_dependence/timing_dependence_vogels_2011.py
@@ -12,21 +12,16 @@
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see .
-
-import logging
from spinn_utilities.overrides import overrides
from data_specification.enums import DataType
from spinn_front_end_common.utilities.constants import (
BYTES_PER_WORD, BYTES_PER_SHORT, MICRO_TO_MILLISECOND_CONVERSION)
-from spynnaker.pyNN.models.neuron.plasticity.stdp.timing_dependence import (
- AbstractTimingDependence)
+from spinn_front_end_common.utilities.globals_variables import get_simulator
from spynnaker.pyNN.models.neuron.plasticity.stdp.synapse_structure import (
SynapseStructureWeightOnly)
-from spinn_front_end_common.utilities.globals_variables import get_simulator
from spynnaker.pyNN.models.neuron.plasticity.stdp.common import (
float_to_fixed, get_exp_lut_array)
-
-logger = logging.getLogger(__name__)
+from .abstract_timing_dependence import AbstractTimingDependence
class TimingDependenceVogels2011(AbstractTimingDependence):
@@ -80,19 +75,13 @@ def is_same_as(self, timing_dependence):
self.__alpha == timing_dependence.alpha)
@property
+ @overrides(AbstractTimingDependence.vertex_executable_suffix)
def vertex_executable_suffix(self):
- """ The suffix to be appended to the vertex executable for this rule
-
- :rtype: str
- """
return "vogels_2011"
@property
+ @overrides(AbstractTimingDependence.pre_trace_n_bytes)
def pre_trace_n_bytes(self):
- """ The number of bytes used by the pre-trace of the rule per neuron
-
- :rtype: int
- """
# Trace entries consist of a single 16-bit number
return BYTES_PER_SHORT
@@ -101,16 +90,12 @@ def get_parameters_sdram_usage_in_bytes(self):
return BYTES_PER_WORD + BYTES_PER_WORD * len(self.__tau_data)
@property
+ @overrides(AbstractTimingDependence.n_weight_terms)
def n_weight_terms(self):
- """ The number of weight terms expected by this timing rule
-
- :rtype: int
- """
return 1
@overrides(AbstractTimingDependence.write_parameters)
def write_parameters(self, spec, machine_time_step, weight_scales):
-
# Write alpha to spec
fixed_point_alpha = float_to_fixed(self.__alpha)
spec.write_value(data=fixed_point_alpha, data_type=DataType.INT32)
@@ -119,11 +104,8 @@ def write_parameters(self, spec, machine_time_step, weight_scales):
spec.write_array(self.__tau_data)
@property
+ @overrides(AbstractTimingDependence.synaptic_structure)
def synaptic_structure(self):
- """ Get the synaptic structure of the plastic part of the rows
-
- :rtype: AbstractSynapseStructure
- """
return self.__synapse_structure
@overrides(AbstractTimingDependence.get_parameter_names)
diff --git a/spynnaker/pyNN/models/neuron/plasticity/stdp/weight_dependence/abstract_weight_dependence.py b/spynnaker/pyNN/models/neuron/plasticity/stdp/weight_dependence/abstract_weight_dependence.py
index 109ae9ce866..ec47c17ccc8 100644
--- a/spynnaker/pyNN/models/neuron/plasticity/stdp/weight_dependence/abstract_weight_dependence.py
+++ b/spynnaker/pyNN/models/neuron/plasticity/stdp/weight_dependence/abstract_weight_dependence.py
@@ -28,7 +28,7 @@ def get_provenance_data(self, pre_population_label, post_population_label):
:param str pre_population_label: label of pre.
:param str post_population_label: label of post.
:return: the provenance data of the weight dependency
- :rtype: \
+ :rtype:
list(~spinn_front_end_common.utilities.utility_objs.ProvenanceDataItem)
"""
# pylint: disable=unused-argument
diff --git a/spynnaker/pyNN/models/neuron/plasticity/stdp/weight_dependence/weight_dependence_additive.py b/spynnaker/pyNN/models/neuron/plasticity/stdp/weight_dependence/weight_dependence_additive.py
index 24099adaf4c..08cf9ea586a 100644
--- a/spynnaker/pyNN/models/neuron/plasticity/stdp/weight_dependence/weight_dependence_additive.py
+++ b/spynnaker/pyNN/models/neuron/plasticity/stdp/weight_dependence/weight_dependence_additive.py
@@ -68,11 +68,8 @@ def is_same_as(self, weight_dependence):
(self.A_minus == weight_dependence.A_minus))
@property
+ @overrides(AbstractWeightDependence.vertex_executable_suffix)
def vertex_executable_suffix(self):
- """ The suffix to be appended to the vertex executable for this rule
-
- :rtype: str
- """
return "additive"
@overrides(AbstractWeightDependence.get_parameters_sdram_usage_in_bytes)
@@ -106,12 +103,8 @@ def write_parameters(
data_type=DataType.INT32)
@property
+ @overrides(AbstractWeightDependence.weight_maximum)
def weight_maximum(self):
- """ The maximum weight that will ever be set in a synapse as a result\
- of this rule
-
- :rtype: float
- """
return self.__w_max
@overrides(AbstractWeightDependence.get_parameter_names)
diff --git a/spynnaker/pyNN/models/neuron/plasticity/stdp/weight_dependence/weight_dependence_additive_triplet.py b/spynnaker/pyNN/models/neuron/plasticity/stdp/weight_dependence/weight_dependence_additive_triplet.py
index e2a112411b7..23322ffca7d 100644
--- a/spynnaker/pyNN/models/neuron/plasticity/stdp/weight_dependence/weight_dependence_additive_triplet.py
+++ b/spynnaker/pyNN/models/neuron/plasticity/stdp/weight_dependence/weight_dependence_additive_triplet.py
@@ -98,11 +98,8 @@ def is_same_as(self, weight_dependence):
(self.__a3_minus == weight_dependence.A3_minus))
@property
+ @overrides(AbstractWeightDependence.vertex_executable_suffix)
def vertex_executable_suffix(self):
- """ The suffix to be appended to the vertex executable for this rule
-
- :rtype: str
- """
return "additive"
@overrides(AbstractWeightDependence.get_parameters_sdram_usage_in_bytes)
@@ -110,16 +107,14 @@ def get_parameters_sdram_usage_in_bytes(
self, n_synapse_types, n_weight_terms):
if n_weight_terms != 2:
raise NotImplementedError(
- "Additive weight dependence only supports one or two terms")
+ "Additive weight dependence only supports two terms")
return _SPACE_PER_SYNAPSE_TYPE * n_synapse_types
@overrides(AbstractWeightDependence.write_parameters)
def write_parameters(
self, spec, machine_time_step, weight_scales, n_weight_terms):
-
# Loop through each synapse type's weight scale
for w in weight_scales:
-
# Scale the weights
spec.write_value(
data=int(round(self.__w_min * w)), data_type=DataType.INT32)
@@ -143,12 +138,8 @@ def write_parameters(
data_type=DataType.INT32)
@property
+ @overrides(AbstractWeightDependence.weight_maximum)
def weight_maximum(self):
- """ The maximum weight that will ever be set in a synapse as a result\
- of this rule
-
- :rtype: float
- """
return self.__w_max
@overrides(AbstractWeightDependence.get_parameter_names)
diff --git a/spynnaker/pyNN/models/neuron/plasticity/stdp/weight_dependence/weight_dependence_multiplicative.py b/spynnaker/pyNN/models/neuron/plasticity/stdp/weight_dependence/weight_dependence_multiplicative.py
index 5b5ccce85e2..3aee0581c23 100644
--- a/spynnaker/pyNN/models/neuron/plasticity/stdp/weight_dependence/weight_dependence_multiplicative.py
+++ b/spynnaker/pyNN/models/neuron/plasticity/stdp/weight_dependence/weight_dependence_multiplicative.py
@@ -67,11 +67,8 @@ def is_same_as(self, weight_dependence):
(self.A_minus == weight_dependence.A_minus))
@property
+ @overrides(AbstractWeightDependence.vertex_executable_suffix)
def vertex_executable_suffix(self):
- """ The suffix to be appended to the vertex executable for this rule
-
- :rtype: str
- """
return "multiplicative"
@overrides(AbstractWeightDependence.get_parameters_sdram_usage_in_bytes)
@@ -103,12 +100,8 @@ def write_parameters(
data=int(round(self.A_minus * w)), data_type=DataType.INT32)
@property
+ @overrides(AbstractWeightDependence.weight_maximum)
def weight_maximum(self):
- """ The maximum weight that will ever be set in a synapse as a result\
- of this rule
-
- :rtype: float
- """
return self.__w_max
@overrides(AbstractWeightDependence.get_parameter_names)
diff --git a/spynnaker/pyNN/models/neuron/population_machine_vertex.py b/spynnaker/pyNN/models/neuron/population_machine_vertex.py
index 30f6f79aab7..89d60a4e07a 100644
--- a/spynnaker/pyNN/models/neuron/population_machine_vertex.py
+++ b/spynnaker/pyNN/models/neuron/population_machine_vertex.py
@@ -37,6 +37,8 @@ class PopulationMachineVertex(
ProvidesProvenanceDataFromMachineImpl, AbstractRecordable,
AbstractHasProfileData, AbstractSupportsBitFieldGeneration,
AbstractSupportsBitFieldRoutingCompression):
+ """ A machine vertex that implements a neural population.
+ """
__slots__ = [
"__recorded_region_ids",
diff --git a/spynnaker/pyNN/models/neuron/structural_plasticity/synaptogenesis/formation/distance_dependent_formation.py b/spynnaker/pyNN/models/neuron/structural_plasticity/synaptogenesis/formation/distance_dependent_formation.py
index d8460cff3ea..7eb543f7c0f 100644
--- a/spynnaker/pyNN/models/neuron/structural_plasticity/synaptogenesis/formation/distance_dependent_formation.py
+++ b/spynnaker/pyNN/models/neuron/structural_plasticity/synaptogenesis/formation/distance_dependent_formation.py
@@ -15,9 +15,9 @@
import numpy
from spinn_utilities.overrides import overrides
-from .abstract_formation import AbstractFormation
from data_specification.enums.data_type import DataType
from spinn_front_end_common.utilities.constants import BYTES_PER_WORD
+from .abstract_formation import AbstractFormation
# 6 32-bit words (grid_x, grid_y, grid_x_recip, grid_y_recep, ff_prob_size,
# lat_prob_size)
@@ -48,13 +48,13 @@ def __init__(
:param float p_form_forward:
The peak probability of formation on feed-forward connections
:param float sigma_form_forward:
- The spread of probability with distance of formation on\
+ The spread of probability with distance of formation on
feed-forward connections
:param float p_form_lateral:
The peak probability of formation on lateral connections
:param float sigma_form_lateral:
- The spread of probability with distance of formation on\
- lateral connections
+ The spread of probability with distance of formation on lateral
+ connections
"""
self.__grid = numpy.asarray(grid, dtype=int)
self.__p_form_forward = p_form_forward
@@ -63,10 +63,10 @@ def __init__(
self.__sigma_form_lateral = sigma_form_lateral
self.__ff_distance_probabilities = \
- self.generate_distance_probability_array(
+ self._generate_distance_probability_array(
self.__p_form_forward, self.__sigma_form_forward)
self.__lat_distance_probabilities = \
- self.generate_distance_probability_array(
+ self._generate_distance_probability_array(
self.__p_form_lateral, self.__sigma_form_lateral)
@property
@@ -80,7 +80,7 @@ def get_parameters_sdram_usage_in_bytes(self):
len(self.__ff_distance_probabilities) * 2 +
len(self.__lat_distance_probabilities) * 2)
- def generate_distance_probability_array(self, probability, sigma):
+ def _generate_distance_probability_array(self, probability, sigma):
""" Generate the exponentially decaying probability LUTs.
:param float probability: peak probability
diff --git a/spynnaker/pyNN/models/neuron/structural_plasticity/synaptogenesis/partner_selection/last_neuron_selection.py b/spynnaker/pyNN/models/neuron/structural_plasticity/synaptogenesis/partner_selection/last_neuron_selection.py
index e2b03a3b39b..15864a00b1a 100644
--- a/spynnaker/pyNN/models/neuron/structural_plasticity/synaptogenesis/partner_selection/last_neuron_selection.py
+++ b/spynnaker/pyNN/models/neuron/structural_plasticity/synaptogenesis/partner_selection/last_neuron_selection.py
@@ -26,7 +26,7 @@ class LastNeuronSelection(AbstractPartnerSelection):
def __init__(self, spike_buffer_size=64):
"""
- :param spike_buffer_size: The size of the buffer for holding spikes
+ :param int spike_buffer_size: The size of the buffer for holding spikes
"""
self.__spike_buffer_size = spike_buffer_size
diff --git a/spynnaker/pyNN/models/neuron/synapse_dynamics/__init__.py b/spynnaker/pyNN/models/neuron/synapse_dynamics/__init__.py
index 3ea25b6de04..81437512c6d 100644
--- a/spynnaker/pyNN/models/neuron/synapse_dynamics/__init__.py
+++ b/spynnaker/pyNN/models/neuron/synapse_dynamics/__init__.py
@@ -22,7 +22,8 @@
from .pynn_synapse_dynamics import PyNNSynapseDynamics
from .synapse_dynamics_static import SynapseDynamicsStatic
from .synapse_dynamics_stdp import SynapseDynamicsSTDP
-from .synapse_dynamics_structural_common import SynapseDynamicsStructuralCommon
+from .synapse_dynamics_structural_common import (
+ StructuralPlasticityCommon as SynapseDynamicsStructuralCommon)
from .synapse_dynamics_structural_static import SynapseDynamicsStructuralStatic
from .synapse_dynamics_structural_stdp import SynapseDynamicsStructuralSTDP
diff --git a/spynnaker/pyNN/models/neuron/synapse_dynamics/abstract_plastic_synapse_dynamics.py b/spynnaker/pyNN/models/neuron/synapse_dynamics/abstract_plastic_synapse_dynamics.py
index 40be1c50f7b..b87aaf58a1f 100644
--- a/spynnaker/pyNN/models/neuron/synapse_dynamics/abstract_plastic_synapse_dynamics.py
+++ b/spynnaker/pyNN/models/neuron/synapse_dynamics/abstract_plastic_synapse_dynamics.py
@@ -42,13 +42,13 @@ def get_plastic_synaptic_data(
and lengths for the fixed_plastic and plastic-plastic parts of\
each row.
- Data is returned as an array made up of an array of 32-bit words for\
- each row, for each of the fixed-plastic and plastic-plastic data\
- regions. The row into which connection should go is given by\
- `connection_row_indices`, and the total number of rows is given by\
+ Data is returned as an array made up of an array of 32-bit words for
+ each row, for each of the fixed-plastic and plastic-plastic data
+ regions. The row into which connection should go is given by
+ `connection_row_indices`, and the total number of rows is given by
`n_rows`.
- Lengths are returned as an array made up of an integer for each row,\
+ Lengths are returned as an array made up of an integer for each row,
for each of the fixed-plastic and plastic-plastic regions.
:param ~numpy.ndarray connections:
diff --git a/spynnaker/pyNN/models/neuron/synapse_dynamics/abstract_static_synapse_dynamics.py b/spynnaker/pyNN/models/neuron/synapse_dynamics/abstract_static_synapse_dynamics.py
index 3edd43b9210..b6e8233df15 100644
--- a/spynnaker/pyNN/models/neuron/synapse_dynamics/abstract_static_synapse_dynamics.py
+++ b/spynnaker/pyNN/models/neuron/synapse_dynamics/abstract_static_synapse_dynamics.py
@@ -41,12 +41,12 @@ def get_static_synaptic_data(
""" Get the fixed-fixed data for each row, and lengths for the\
fixed-fixed parts of each row.
- Data is returned as an array made up of an array of 32-bit words for\
- each row for the fixed-fixed region. The row into which connection\
- should go is given by `connection_row_indices`, and the total number\
+ Data is returned as an array made up of an array of 32-bit words for
+ each row for the fixed-fixed region. The row into which connection
+ should go is given by `connection_row_indices`, and the total number
of rows is given by `n_rows`.
- Lengths are returned as an array made up of an integer for each row,\
+ Lengths are returned as an array made up of an integer for each row,
for the fixed-fixed region.
:param ~numpy.ndarray connections:
diff --git a/spynnaker/pyNN/models/neuron/synapse_dynamics/abstract_synapse_dynamics.py b/spynnaker/pyNN/models/neuron/synapse_dynamics/abstract_synapse_dynamics.py
index ca31ddaf4bc..4bd162baa2f 100644
--- a/spynnaker/pyNN/models/neuron/synapse_dynamics/abstract_synapse_dynamics.py
+++ b/spynnaker/pyNN/models/neuron/synapse_dynamics/abstract_synapse_dynamics.py
@@ -13,11 +13,11 @@
# You should have received a copy of the GNU General Public License
# along with this program. If not, see .
-import math
import numpy
from six import add_metaclass
from spinn_utilities.abstract_base import (
AbstractBase, abstractmethod, abstractproperty)
+from spynnaker.pyNN.utilities.utility_calls import ceildiv
@add_metaclass(AbstractBase)
@@ -196,7 +196,7 @@ def get_n_items(self, rows, item_size):
:rtype: ~numpy.ndarray
"""
return numpy.array([
- int(math.ceil(float(row.size) / float(item_size)))
+ ceildiv(row.size, item_size)
for row in rows], dtype="uint32").reshape((-1, 1))
def get_words(self, rows):
diff --git a/spynnaker/pyNN/models/neuron/synapse_dynamics/abstract_synapse_dynamics_structural.py b/spynnaker/pyNN/models/neuron/synapse_dynamics/abstract_synapse_dynamics_structural.py
index 624e4229d39..abfa0cf52f4 100644
--- a/spynnaker/pyNN/models/neuron/synapse_dynamics/abstract_synapse_dynamics_structural.py
+++ b/spynnaker/pyNN/models/neuron/synapse_dynamics/abstract_synapse_dynamics_structural.py
@@ -86,6 +86,8 @@ def s_max(self):
@abstractproperty
def seed(self):
""" The seed to control the randomness
+
+ :rtype: int
"""
@abstractproperty
@@ -122,3 +124,16 @@ def elimination(self):
:rtype: AbstractElimination
"""
+
+ def get_per_edge_parameters_sdram_usage_in_bytes(self):
+ """ Get the amount of SDRAM used by the parameters of the rules per \
+ structurally-plastic synapse.
+
+ .. note::
+ The partner selection rule is shared.
+
+ :rtype: int
+ """
+ # pylint: disable=no-member
+ return (self.formation.get_parameters_sdram_usage_in_bytes() +
+ self.elimination.get_parameters_sdram_usage_in_bytes())
diff --git a/spynnaker/pyNN/models/neuron/synapse_dynamics/synapse_dynamics_static.py b/spynnaker/pyNN/models/neuron/synapse_dynamics/synapse_dynamics_static.py
index 6975734fc3b..7028b34c44c 100644
--- a/spynnaker/pyNN/models/neuron/synapse_dynamics/synapse_dynamics_static.py
+++ b/spynnaker/pyNN/models/neuron/synapse_dynamics/synapse_dynamics_static.py
@@ -179,7 +179,8 @@ def requires_mapping(self):
@overrides(AbstractChangableAfterRun.mark_no_changes, extend_doc=False)
def mark_no_changes(self):
""" Marks the point after which changes are reported. Immediately\
- after calling this method, requires_mapping should return False.
+ after calling this method, :py:meth:`requires_mapping` should \
+ return False.
"""
self.__change_requires_mapping = False
diff --git a/spynnaker/pyNN/models/neuron/synapse_dynamics/synapse_dynamics_stdp.py b/spynnaker/pyNN/models/neuron/synapse_dynamics/synapse_dynamics_stdp.py
index 310f096d082..895c6590a10 100644
--- a/spynnaker/pyNN/models/neuron/synapse_dynamics/synapse_dynamics_stdp.py
+++ b/spynnaker/pyNN/models/neuron/synapse_dynamics/synapse_dynamics_stdp.py
@@ -12,8 +12,6 @@
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see .
-
-import math
import numpy
from spinn_utilities.overrides import overrides
from spinn_front_end_common.abstract_models import AbstractChangableAfterRun
@@ -21,16 +19,17 @@
BYTES_PER_WORD, BYTES_PER_SHORT)
from spynnaker.pyNN.models.abstract_models import AbstractSettable
from .abstract_plastic_synapse_dynamics import AbstractPlasticSynapseDynamics
-from .abstract_synapse_dynamics_structural \
- import AbstractSynapseDynamicsStructural
+from .abstract_synapse_dynamics_structural import (
+ AbstractSynapseDynamicsStructural)
from .abstract_generate_on_machine import (
AbstractGenerateOnMachine, MatrixGeneratorID)
-from spynnaker.pyNN.exceptions import InvalidParameterType,\
- SynapticConfigurationException
-from spynnaker.pyNN.utilities.utility_calls import get_n_bits
+from spynnaker.pyNN.exceptions import (
+ InvalidParameterType, SynapticConfigurationException)
+from spynnaker.pyNN.utilities.utility_calls import get_n_bits, ceildiv
# How large are the time-stamps stored with each event
TIME_STAMP_BYTES = BYTES_PER_WORD
+_HALF_WORDS_PER_WORD = 2
class SynapseDynamicsSTDP(
@@ -281,30 +280,25 @@ def _n_header_bytes(self):
# The actual number of bytes is in a word-aligned struct, so work out
# the number of bytes as a number of words
- return int(math.ceil(float(n_bytes) / BYTES_PER_WORD)) * BYTES_PER_WORD
+ return ceildiv(n_bytes, BYTES_PER_WORD) * BYTES_PER_WORD
def __get_n_connections(self, n_connections, check_length_padded=True):
"""
:param int n_connections:
- :rtype: int
:param bool check_length_padded:
- :rtype: bool
+ :rtype: int
"""
synapse_structure = self.__timing_dependence.synaptic_structure
if self.__pad_to_length is not None and check_length_padded:
n_connections = max(n_connections, self.__pad_to_length)
if n_connections == 0:
return 0
- # 2 == two half words per word
- fp_size_words = (
- n_connections // 2 if n_connections % 2 == 0
- else (n_connections + 1) // 2)
- pp_size_bytes = (
- self._n_header_bytes +
- (synapse_structure.get_n_half_words_per_connection() *
- BYTES_PER_SHORT * n_connections))
- pp_size_words = int(math.ceil(float(pp_size_bytes) / BYTES_PER_WORD))
+ fp_size_words = ceildiv(n_connections, _HALF_WORDS_PER_WORD)
+ pp_size_bytes = self._n_header_bytes + (
+ synapse_structure.get_n_half_words_per_connection() *
+ BYTES_PER_SHORT * n_connections)
+ pp_size_words = ceildiv(pp_size_bytes, BYTES_PER_WORD)
return fp_size_words + pp_size_words
def get_n_words_for_plastic_connections(self, n_connections):
@@ -476,7 +470,7 @@ def get_provenance_data(self, pre_population_label, post_population_label):
"""
:param str pre_population_label:
:param str post_population_label:
- :rtype: \
+ :rtype:
list(~spinn_front_end_common.utilities.utility_objs.ProvenanceDataItem)
"""
prov_data = list()
diff --git a/spynnaker/pyNN/models/neuron/synapse_dynamics/synapse_dynamics_structural_common.py b/spynnaker/pyNN/models/neuron/synapse_dynamics/synapse_dynamics_structural_common.py
index 5ed01456971..77b8f5c1095 100644
--- a/spynnaker/pyNN/models/neuron/synapse_dynamics/synapse_dynamics_structural_common.py
+++ b/spynnaker/pyNN/models/neuron/synapse_dynamics/synapse_dynamics_structural_common.py
@@ -12,21 +12,18 @@
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see .
-
import collections
-import math
import numpy
from data_specification.enums.data_type import DataType
from spinn_front_end_common.utilities.constants import (
MICRO_TO_MILLISECOND_CONVERSION, MICRO_TO_SECOND_CONVERSION,
BYTES_PER_WORD, BYTES_PER_SHORT)
from spynnaker.pyNN.models.neural_projections import ProjectionApplicationEdge
-from .abstract_synapse_dynamics_structural import (
- AbstractSynapseDynamicsStructural)
from spynnaker.pyNN.exceptions import SynapticConfigurationException
+from spynnaker.pyNN.utilities.utility_calls import ceildiv
-class SynapseDynamicsStructuralCommon(object):
+class StructuralPlasticityCommon(object):
""" Utility class that holds properties of synaptic rewiring\
both in the presence and absence of STDP.
@@ -106,7 +103,7 @@ def __init__(
:param float initial_weight:
Initial weight assigned to a newly formed connection
:param initial_delay: Delay assigned to a newly formed connection
- :type initial_delay: int or (int, int)
+ :type initial_delay: int or float or tuple(int or float, int or float)
:param int s_max: Maximum fan-in per target layer neuron
:param int seed: seed the random number generators
"""
@@ -157,7 +154,7 @@ def p_rew(self):
""" The period of rewiring.
:return: The period of rewiring
- :rtype: int
+ :rtype: float
"""
return self.__p_rew
@@ -225,17 +222,18 @@ def write_parameters(
def __get_structural_edges(self, app_graph, app_vertex):
"""
- :param ~pacman.model.graphs.application.ApplicationGraph app_graph:
- :param ~pacman.model.graphs.application.ApplicationVertex app_vertex:
+ :param ~.ApplicationGraph app_graph:
+ :param ~.ApplicationVertex app_vertex:
:rtype: list(tuple(ProjectionApplicationEdge, SynapseInformation))
+ :raises SynapticConfigurationException:
+ if there are two structurally-plastic projections on an edge
"""
structural_edges = list()
for app_edge in app_graph.get_edges_ending_at_vertex(app_vertex):
if isinstance(app_edge, ProjectionApplicationEdge):
found = False
for synapse_info in app_edge.synapse_information:
- if isinstance(synapse_info.synapse_dynamics,
- AbstractSynapseDynamicsStructural):
+ if synapse_info.is_structural:
if found:
raise SynapticConfigurationException(
"Only one Projection between each pair of "
@@ -248,16 +246,13 @@ def __write_common_rewiring_data(
self, spec, app_vertex, post_slice, machine_time_step, n_pre_pops):
""" Write the non-sub-population synapse parameters to the spec.
- :param ~data_specification.DataSpecificationGenerator spec:
- the data spec
+ :param ~.DataSpecificationGenerator spec: the data spec
:param AbstractPopulationVertex app_vertex:
the highest level object of the post-synaptic population
:param ~pacman.model.graphs.common.Slice post_slice:
the slice of the app vertex corresponding to this machine vertex
:param int machine_time_step: the duration of a machine time step (ms)
:param int n_pre_pops: the number of pre-populations
- :return: None
- :rtype: None
"""
if (self.__p_rew * MICRO_TO_MILLISECOND_CONVERSION <
machine_time_step / MICRO_TO_MILLISECOND_CONVERSION):
@@ -305,10 +300,11 @@ def __write_prepopulation_info(
routing_info, weight_scales, post_slice, synapse_indices,
machine_time_step):
"""
- :param ~data_specification.DataSpecificationGenerator spec:
+ :param ~.DataSpecificationGenerator spec:
:param AbstractPopulationVertex app_vertex:
- :param list(tuple(ProjectionApplicationEdge,SynapseInformation)) \
- structural_edges:
+ :param structural_edges:
+ :type structural_edges:
+ list(tuple(ProjectionApplicationEdge,SynapseInformation))
:param RoutingInfo routing_info:
:param dict(AbstractSynapseType,float) weight_scales:
:param ~pacman.model.graphs.common.Slice post_slice:
@@ -367,9 +363,10 @@ def __write_post_to_pre_table(
""" Post to pre table is basically the transpose of the synaptic\
matrix.
- :param ~data_specification.DataSpecificationGenerator spec:
- :param dict(tuple(AbstractPopulationVertex,SynapseInformation),int) \
- pop_index:
+ :param ~.DataSpecificationGenerator spec:
+ :param pop_index:
+ :type pop_index:
+ dict(tuple(AbstractPopulationVertex,SynapseInformation),int)
:param AbstractPopulationVertex app_vertex:
:param ~pacman.model.graphs.common.Slice post_slice:
"""
@@ -438,22 +435,18 @@ def get_parameters_sdram_usage_in_bytes(
param_sizes = self.__partner_selection\
.get_parameters_sdram_usage_in_bytes()
for (in_edge, synapse_info) in structural_edges:
- max_atoms = in_edge.pre_vertex.get_max_atoms_per_core()
- if in_edge.pre_vertex.n_atoms < max_atoms:
- max_atoms = in_edge.pre_vertex.n_atoms
- n_sub_edges += int(math.ceil(
- float(in_edge.pre_vertex.n_atoms) / float(max_atoms)))
- dynamics = synapse_info.synapse_dynamics
- param_sizes += dynamics.formation\
- .get_parameters_sdram_usage_in_bytes()
- param_sizes += dynamics.elimination\
- .get_parameters_sdram_usage_in_bytes()
-
- return int((self._REWIRING_DATA_SIZE +
- (self._PRE_POP_INFO_BASE_SIZE * len(structural_edges)) +
- (self._KEY_ATOM_INFO_SIZE * n_sub_edges) +
- (self._POST_TO_PRE_ENTRY_SIZE * n_neurons * self.__s_max) +
- param_sizes))
+ n_sub_edges += ceildiv(in_edge.pre_vertex.n_atoms, min(
+ in_edge.pre_vertex.get_max_atoms_per_core(),
+ in_edge.pre_vertex.n_atoms))
+ param_sizes += synapse_info.synapse_dynamics.\
+ get_per_edge_parameters_sdram_usage_in_bytes()
+
+ return int(
+ self._REWIRING_DATA_SIZE +
+ (self._PRE_POP_INFO_BASE_SIZE * len(structural_edges)) +
+ (self._KEY_ATOM_INFO_SIZE * n_sub_edges) +
+ (self._POST_TO_PRE_ENTRY_SIZE * n_neurons * self.__s_max) +
+ param_sizes)
def synaptic_data_update(
self, connections, post_vertex_slice, app_edge, synapse_info,
@@ -466,8 +459,7 @@ def synaptic_data_update(
:param SynapseInformation synapse_info:
:param ProjectionMachineEdge machine_edge:
"""
- if not isinstance(synapse_info.synapse_dynamics,
- AbstractSynapseDynamicsStructural):
+ if not synapse_info.is_structural:
return
collector = self.__connections.setdefault(
(app_edge.post_vertex, post_vertex_slice.lo_atom), [])
@@ -500,7 +492,7 @@ def get_vertex_executable_suffix(self):
def is_same_as(self, synapse_dynamics):
"""
- :param SynapseDynamicsStructuralCommon synapse_dynamics:
+ :param StructuralPlasticityCommon synapse_dynamics:
:rtype: bool
"""
# Note noqa because exact type comparison is required here
@@ -518,41 +510,64 @@ def is_same_as(self, synapse_dynamics):
@property
def initial_weight(self):
+ """ Initial weight assigned to a newly formed connection
+
+ :rtype: float
+ """
return self.__initial_weight
@property
def initial_delay(self):
+ """ Delay assigned to a newly formed connection
+
+ :rtype: int or float or tuple(int or float, int or float)
+ """
return self.__initial_delay
@property
def f_rew(self):
+ """ Frequency of rewiring (Hz)
+
+ :rtype: float
+ """
return self.__f_rew
@property
def s_max(self):
+ """ Maximum fan-in per target layer neuron
+
+ :rtype: int
+ """
return self.__s_max
@property
def seed(self):
+ """ seed for the random number generators
+
+ :rtype: int
+ """
return self.__seed
@property
def partner_selection(self):
- """
+ """ The partner selection rule
+
:rtype: AbstractPartnerSelection
"""
return self.__partner_selection
@property
def formation(self):
- """
+ """ The formation rule
+
:rtype: AbstractFormation
"""
return self.__formation
@property
def elimination(self):
- """
+ """ The elimination rule
+
:rtype: AbstractElimination
"""
return self.__elimination
diff --git a/spynnaker/pyNN/models/neuron/synapse_dynamics/synapse_dynamics_structural_static.py b/spynnaker/pyNN/models/neuron/synapse_dynamics/synapse_dynamics_structural_static.py
index a15b60fc2ad..b4311afc5af 100644
--- a/spynnaker/pyNN/models/neuron/synapse_dynamics/synapse_dynamics_structural_static.py
+++ b/spynnaker/pyNN/models/neuron/synapse_dynamics/synapse_dynamics_structural_static.py
@@ -16,8 +16,7 @@
from spinn_utilities.overrides import overrides
from .abstract_synapse_dynamics_structural import (
AbstractSynapseDynamicsStructural)
-from .synapse_dynamics_structural_common import (
- SynapseDynamicsStructuralCommon as CommonSP)
+from .synapse_dynamics_structural_common import StructuralPlasticityCommon
from .synapse_dynamics_static import SynapseDynamicsStatic
from .synapse_dynamics_stdp import SynapseDynamicsSTDP
from .synapse_dynamics_structural_stdp import SynapseDynamicsStructuralSTDP
@@ -28,8 +27,8 @@ class SynapseDynamicsStructuralStatic(
SynapseDynamicsStatic, AbstractSynapseDynamicsStructural):
""" Class that enables synaptic rewiring in the absence of STDP.
- It acts as a wrapper around SynapseDynamicsStatic, meaning that \
- rewiring can operate in parallel with static synapses.
+ It acts as a wrapper around :py:class:`SynapseDynamicsStatic`, meaning
+ that rewiring can operate in parallel with static synapses.
Written by Petrut Bogdan.
"""
@@ -37,10 +36,10 @@ class SynapseDynamicsStructuralStatic(
def __init__(
self, partner_selection, formation, elimination,
- f_rew=CommonSP.DEFAULT_F_REW,
- initial_weight=CommonSP.DEFAULT_INITIAL_WEIGHT,
- initial_delay=CommonSP.DEFAULT_INITIAL_DELAY,
- s_max=CommonSP.DEFAULT_S_MAX, seed=None,
+ f_rew=StructuralPlasticityCommon.DEFAULT_F_REW,
+ initial_weight=StructuralPlasticityCommon.DEFAULT_INITIAL_WEIGHT,
+ initial_delay=StructuralPlasticityCommon.DEFAULT_INITIAL_DELAY,
+ s_max=StructuralPlasticityCommon.DEFAULT_S_MAX, seed=None,
weight=0.0, delay=1.0):
"""
:param AbstractPartnerSelection partner_selection:
@@ -55,7 +54,7 @@ def __init__(
a fixed delay value, or a tuple of two values means the delay will
be chosen at random from a uniform distribution between the given
values
- :type initial_delay: float or (float, float)
+ :type initial_delay: int or float or tuple(int or float, int or float)
:param int s_max: Maximum fan-in per target layer neuron
:param int seed: seed the random number generators
:param float weight: The weight of connections formed by the connector
@@ -64,7 +63,7 @@ def __init__(
super(SynapseDynamicsStructuralStatic, self).__init__(
weight=weight, delay=delay, pad_to_length=s_max)
- self.__common_sp = CommonSP(
+ self.__common_sp = StructuralPlasticityCommon(
partner_selection, formation, elimination, f_rew, initial_weight,
initial_delay, s_max, seed)
diff --git a/spynnaker/pyNN/models/neuron/synapse_dynamics/synapse_dynamics_structural_stdp.py b/spynnaker/pyNN/models/neuron/synapse_dynamics/synapse_dynamics_structural_stdp.py
index e0e65182360..d0739801d5b 100644
--- a/spynnaker/pyNN/models/neuron/synapse_dynamics/synapse_dynamics_structural_stdp.py
+++ b/spynnaker/pyNN/models/neuron/synapse_dynamics/synapse_dynamics_structural_stdp.py
@@ -17,9 +17,7 @@
from .synapse_dynamics_stdp import SynapseDynamicsSTDP
from .abstract_synapse_dynamics_structural import (
AbstractSynapseDynamicsStructural)
-from .synapse_dynamics_structural_common import (
- SynapseDynamicsStructuralCommon as
- CommonSP)
+from .synapse_dynamics_structural_common import StructuralPlasticityCommon
from spynnaker.pyNN.exceptions import SynapticConfigurationException
@@ -27,10 +25,10 @@ class SynapseDynamicsStructuralSTDP(
SynapseDynamicsSTDP, AbstractSynapseDynamicsStructural):
""" Class that enables synaptic rewiring in the presence of STDP.
- It acts as a wrapper around SynapseDynamicsSTDP, meaning rewiring can\
- operate in parallel with STDP synapses.
+ It acts as a wrapper around :py:class:`SynapseDynamicsSTDP`, meaning
+ rewiring can operate in parallel with STDP synapses.
- Written by Petrut Bogdan.
+ :codeauthor: Petrut Bogdan
"""
__slots__ = ["__common_sp"]
@@ -38,10 +36,10 @@ def __init__(
self, partner_selection, formation, elimination,
timing_dependence=None, weight_dependence=None,
voltage_dependence=None, dendritic_delay_fraction=1.0,
- f_rew=CommonSP.DEFAULT_F_REW,
- initial_weight=CommonSP.DEFAULT_INITIAL_WEIGHT,
- initial_delay=CommonSP.DEFAULT_INITIAL_DELAY,
- s_max=CommonSP.DEFAULT_S_MAX, seed=None,
+ f_rew=StructuralPlasticityCommon.DEFAULT_F_REW,
+ initial_weight=StructuralPlasticityCommon.DEFAULT_INITIAL_WEIGHT,
+ initial_delay=StructuralPlasticityCommon.DEFAULT_INITIAL_DELAY,
+ s_max=StructuralPlasticityCommon.DEFAULT_S_MAX, seed=None,
weight=0.0, delay=1.0, backprop_delay=True):
"""
:param AbstractPartnerSelection partner_selection:
@@ -63,7 +61,7 @@ def __init__(
a fixed delay value, or a tuple of two values means the delay will
be chosen at random from a uniform distribution between the given
values
- :type initial_delay: float or tuple(float, float)
+ :type initial_delay: int or float or tuple(int or float, int or float)
:param int s_max: Maximum fan-in per target layer neuron
:param int seed: seed the random number generators
:param float weight: The weight of connections formed by the connector
@@ -73,7 +71,7 @@ def __init__(
timing_dependence, weight_dependence, voltage_dependence,
dendritic_delay_fraction, weight, delay, pad_to_length=s_max,
backprop_delay=backprop_delay)
- self.__common_sp = CommonSP(
+ self.__common_sp = StructuralPlasticityCommon(
partner_selection, formation, elimination, f_rew, initial_weight,
initial_delay, s_max, seed)
diff --git a/spynnaker/pyNN/models/neuron/synapse_io.py b/spynnaker/pyNN/models/neuron/synapse_io.py
index acef9f55c7c..5557bcc640e 100644
--- a/spynnaker/pyNN/models/neuron/synapse_io.py
+++ b/spynnaker/pyNN/models/neuron/synapse_io.py
@@ -13,12 +13,10 @@
# You should have received a copy of the GNU General Public License
# along with this program. If not, see .
-import math
import numpy
from six import raise_from
-
-from spinn_front_end_common.utilities.constants import \
- MICRO_TO_MILLISECOND_CONVERSION, BYTES_PER_WORD
+from spinn_front_end_common.utilities.constants import (
+ MICRO_TO_MILLISECOND_CONVERSION, BYTES_PER_WORD)
from spynnaker.pyNN.models.neural_projections.connectors import (
AbstractConnector)
from spynnaker.pyNN.utilities.constants import MAX_SUPPORTED_DELAY_TICS
@@ -26,6 +24,7 @@
from spynnaker.pyNN.models.neuron.synapse_dynamics import (
AbstractStaticSynapseDynamics, AbstractSynapseDynamicsStructural,
AbstractSynapseDynamics)
+from spynnaker.pyNN.utilities.utility_calls import ceildiv
_N_HEADER_WORDS = 3
# There are 16 slots, one per time step
@@ -133,7 +132,7 @@ def _n_words(n_bytes):
:param int n_bytes:
:rtype: int
"""
- return math.ceil(float(n_bytes) / BYTES_PER_WORD)
+ return ceildiv(n_bytes, BYTES_PER_WORD)
@staticmethod
def _get_max_row_length(
@@ -324,7 +323,7 @@ def get_synapses(
:return: (row_data, max_row_length, delayed_row_data,
max_delayed_row_length, delayed_source_ids, stages)
:rtype:
- tuple(~numpy.ndarray, int, ~numpy.ndarray, int, ~numpy.ndarray,\
+ tuple(~numpy.ndarray, int, ~numpy.ndarray, int, ~numpy.ndarray,
~numpy.ndarray)
"""
# pylint: disable=too-many-arguments, too-many-locals
@@ -501,6 +500,11 @@ def __convert_delayed_data(
self, n_synapses, pre_vertex_slice, delayed_connections):
""" Take the delayed_connections and convert the source ids and delay\
values
+
+ :param int n_synapses:
+ :param ~pacman.model.graphs.common.Slice pre_vertex_slice:
+ :param ~numpy.ndarray delayed_connections:
+ :rtype: ~numpy.ndarray
"""
synapse_ids = range(len(n_synapses))
row_stage = numpy.array([
diff --git a/spynnaker/pyNN/models/neuron/synapse_types/synapse_type_semd.py b/spynnaker/pyNN/models/neuron/synapse_types/synapse_type_semd.py
index 3e7a73cb27e..c3cd1f94b27 100644
--- a/spynnaker/pyNN/models/neuron/synapse_types/synapse_type_semd.py
+++ b/spynnaker/pyNN/models/neuron/synapse_types/synapse_type_semd.py
@@ -42,6 +42,8 @@
class SynapseTypeSEMD(AbstractSynapseType):
+ """ Synaptic type for a spiking elementary motion detector.
+ """
__slots__ = [
"__tau_syn_E",
"__tau_syn_E2",
@@ -141,7 +143,6 @@ def init(x):
@overrides(AbstractSynapseType.update_values)
def update_values(self, values, parameters, state_variables):
-
# Read the data
(_decay_E, _init_E, isyn_exc, _decay_E2, _init_E2, isyn_exc2,
_decay_I, _init_I, isyn_inh, _multiplicator, exc2_old) = values
diff --git a/spynnaker/pyNN/models/neuron/synaptic_manager.py b/spynnaker/pyNN/models/neuron/synaptic_manager.py
index f03a3774f0d..4cf4264317c 100644
--- a/spynnaker/pyNN/models/neuron/synaptic_manager.py
+++ b/spynnaker/pyNN/models/neuron/synaptic_manager.py
@@ -30,8 +30,7 @@
AbstractGenerateConnectorOnMachine)
from spynnaker.pyNN.models.neural_projections import ProjectionApplicationEdge
from .synapse_dynamics import (
- AbstractSynapseDynamicsStructural,
- AbstractGenerateOnMachine, SynapseDynamicsStructuralSTDP)
+ AbstractSynapseDynamicsStructural, AbstractGenerateOnMachine)
from spynnaker.pyNN.models.neuron.synapse_io import SynapseIORowBased
from spynnaker.pyNN.models.spike_source.spike_source_poisson_vertex import (
SpikeSourcePoissonVertex)
@@ -39,7 +38,7 @@
from spynnaker.pyNN.utilities.constants import (
POPULATION_BASED_REGIONS, POSSION_SIGMA_SUMMATION_LIMIT)
from spynnaker.pyNN.utilities.utility_calls import (
- get_maximum_probable_value, get_n_bits)
+ get_maximum_probable_value, get_n_bits, ceildiv, round_up)
from spynnaker.pyNN.utilities.running_stats import RunningStats
from spynnaker.pyNN.models.neuron.master_pop_table import (
MasterPopTableAsBinarySearch)
@@ -102,7 +101,8 @@ class SynapticManager(object):
"_direct_matrix_region"]
# TODO make this right
- FUDGE = 0
+ _CPU_FUDGE = 0
+ _DTCM_FUDGE = 0
def __init__(self, n_synapse_types, ring_buffer_sigma, spikes_per_second,
config, population_table_type=None, synapse_io=None):
@@ -127,6 +127,7 @@ def __init__(self, n_synapse_types, ring_buffer_sigma, spikes_per_second,
self.__n_synapse_types = n_synapse_types
self.__ring_buffer_sigma = ring_buffer_sigma
self.__spikes_per_second = spikes_per_second
+ # Overridable (for testing only) region IDs
self._synapse_params_region = \
POPULATION_BASED_REGIONS.SYNAPSE_PARAMS.value
self._pop_table_region = \
@@ -209,22 +210,6 @@ def synapse_dynamics(self):
"""
return self.__synapse_dynamics
- @staticmethod
- def __combine_structural_stdp_dynamics(structural, stdp):
- """
- :param AbstractSynapseDynamicsStructural structural:
- :param SynapseDynamicsSTDP stdp:
- :rtype: SynapseDynamicsStructuralSTDP
- """
- return SynapseDynamicsStructuralSTDP(
- structural.partner_selection, structural.formation,
- structural.elimination,
- stdp.timing_dependence, stdp.weight_dependence,
- # voltage dependence is not supported
- None, stdp.dendritic_delay_fraction,
- structural.f_rew, structural.initial_weight,
- structural.initial_delay, structural.s_max, structural.seed)
-
@synapse_dynamics.setter
def synapse_dynamics(self, synapse_dynamics):
if self.__synapse_dynamics is None:
@@ -259,6 +244,7 @@ def spikes_per_second(self, spikes_per_second):
def get_maximum_delay_supported_in_ms(self, machine_time_step):
"""
+ :param int machine_time_step:
:rtype: int or None
"""
return self.__synapse_io.get_maximum_delay_supported_in_ms(
@@ -287,7 +273,7 @@ def add_pre_run_connection_holder(
def get_connection_holders(self):
"""
- :rtype: dict(tuple(ProjectionApplicationEdge,SynapseInformation),\
+ :rtype: dict(tuple(ProjectionApplicationEdge,SynapseInformation),
ConnectionHolder)
"""
return self.__pre_run_connection_holders
@@ -297,14 +283,14 @@ def get_n_cpu_cycles(self):
:rtype: int
"""
# TODO: Calculate this correctly
- return self.FUDGE
+ return self._CPU_FUDGE
def get_dtcm_usage_in_bytes(self):
"""
:rtype: int
"""
# TODO: Calculate this correctly
- return self.FUDGE
+ return self._DTCM_FUDGE
def _get_synapse_params_size(self):
"""
@@ -383,7 +369,7 @@ def __add_synapse_size(self, memory_size, synapse_info, post_vertex_slice,
def _get_size_of_generator_information(self, in_edges):
""" Get the size of the synaptic expander parameters
- :param list(.ApplicationEdge) in_edges:
+ :param list(~.ApplicationEdge) in_edges:
:rtype: int
"""
gen_on_machine = False
@@ -397,8 +383,8 @@ def _get_size_of_generator_information(self, in_edges):
max_atoms = in_edge.pre_vertex.get_max_atoms_per_core()
if in_edge.pre_vertex.n_atoms < max_atoms:
max_atoms = in_edge.pre_vertex.n_atoms
- n_edge_vertices = int(math.ceil(
- float(in_edge.pre_vertex.n_atoms) / float(max_atoms)))
+ n_edge_vertices = ceildiv(
+ in_edge.pre_vertex.n_atoms, max_atoms)
# Get the size
if synapse_info.may_generate_on_machine():
@@ -531,20 +517,20 @@ def _ring_buffer_expected_upper_bound(
Requires an assessment of maximum Poisson input rate.
- Assumes knowledge of mean and SD of weight distribution, fan-in\
+ Assumes knowledge of mean and SD of weight distribution, fan-in
and timestep.
- All arguments should be assumed real values except n_synapses_in\
+ All arguments should be assumed real values except n_synapses_in
which will be an integer.
- :param float weight_mean: Mean of weight distribution (in either nA or\
+ :param float weight_mean: Mean of weight distribution (in either nA or
microSiemens as required)
:param float weight_std_dev: SD of weight distribution
:param float spikes_per_second: Maximum expected Poisson rate in Hz
:param int machine_timestep: in us
:param int n_synapses_in: No of connected synapses
- :param float sigma: How many SD above the mean to go for upper bound;\
- a good starting choice is 5.0. Given length of simulation we can\
+ :param float sigma: How many SD above the mean to go for upper bound;
+ a good starting choice is 5.0. Given length of simulation we can
set this for approximate number of saturation events.
:rtype: float
"""
@@ -692,7 +678,7 @@ def _get_ring_buffer_to_input_left_shifts(
# Convert these to powers; we could use int.bit_length() for this if
# they were integers, but they aren't...
max_weight_powers = (
- 0 if w <= 0 else int(math.ceil(max(0, math.log(w, 2))))
+ 0 if w <= 0 else round_up(max(0, math.log(w, 2)))
for w in max_weights)
# If 2^max_weight_power equals the max weight, we have to add another
@@ -718,7 +704,7 @@ def __get_weight_scale(ring_buffer_to_input_left_shift):
:param int ring_buffer_to_input_left_shift:
:rtype: float
"""
- return float(math.pow(2, 16 - (ring_buffer_to_input_left_shift + 1)))
+ return 2.0 ** (16 - (ring_buffer_to_input_left_shift + 1))
def _write_synapse_parameters(
self, spec, ring_buffer_shifts, weight_scale):
@@ -1097,7 +1083,7 @@ def __is_direct(
self, single_addr, connector, pre_vertex_slice, post_vertex_slice,
app_edge, synapse_info):
""" Determine if the given connection can be done with a "direct"\
- synaptic matrix - this must have an exactly 1 entry per row
+ synaptic matrix. This must have an exactly 1 entry per row.
:param int single_addr:
:param AbstractConnector connector:
diff --git a/spynnaker/pyNN/models/pynn_population_common.py b/spynnaker/pyNN/models/pynn_population_common.py
index de06723c126..53bd02b32d0 100644
--- a/spynnaker/pyNN/models/pynn_population_common.py
+++ b/spynnaker/pyNN/models/pynn_population_common.py
@@ -24,7 +24,8 @@
MaxVertexAtomsConstraint)
from pacman.model.graphs.application.application_vertex import (
ApplicationVertex)
-from spinn_front_end_common.utilities import globals_variables
+from spinn_front_end_common.utilities.globals_variables import (
+ get_simulator, get_not_running_simulator)
from spinn_front_end_common.utilities.exceptions import ConfigurationException
from spinn_front_end_common.abstract_models import AbstractChangableAfterRun
from spynnaker.pyNN.models.abstract_models import (
@@ -71,7 +72,8 @@ def __init__(
:param spinnaker_control: The simulator engine core.
:type spinnaker_control:
~spinn_front_end_common.interface.abstract_spinnaker_base.AbstractSpinnakerBase
- :param size: The size of the population; external devices may use None
+ :param size: The size of the population; external devices may use
+ `None`
:type size: int or float or None
:param label: The label for the population, or None for a default
:type label: str or None
@@ -86,7 +88,7 @@ def __init__(
:param initial_values: Initialisation for model variables.
:type initial_values: dict(str, Any) or None
:param additional_parameters:
- Any extra parameters to pass to the model's vertex creation \
+ Any extra parameters to pass to the model's vertex creation
function.
:type additional_parameters: dict(str, Any) or None
"""
@@ -165,14 +167,13 @@ def __init__(
# things for pynn demands
self._all_ids = numpy.arange(
- globals_variables.get_simulator().id_counter,
- globals_variables.get_simulator().id_counter + size)
+ get_simulator().id_counter, get_simulator().id_counter + size)
self.__first_id = self._all_ids[0]
self.__last_id = self._all_ids[-1]
# update the simulators id_counter for giving a unique ID for every
# atom
- globals_variables.get_simulator().id_counter += size
+ get_simulator().id_counter += size
# set up initial values if given
if initial_values is not None:
@@ -247,13 +248,13 @@ def get(self, parameter_names, gather=True, simplify=True):
""" Get the values of a parameter for every local cell in the\
population.
- :param parameter_names: Name of parameter. This is either a single\
+ :param parameter_names: Name of parameter. This is either a single
string or a list of strings
:type parameter_names: str or iterable(str)
:param bool gather: pointless on sPyNNaker
:param bool simplify: ignored
- :return: A single list of values (or possibly a single value) if\
- paramter_names is a string, or a dict of these if parameter names\
+ :return: A single list of values (or possibly a single value) if
+ paramter_names is a string, or a dict of these if parameter names
is a list.
:rtype: str or list(str) or dict(str,str) or dict(str,list(str))
"""
@@ -278,15 +279,15 @@ def get_by_selector(self, selector, parameter_names):
""" Get the values of a parameter for the selected cell in the\
population.
- :param selector: a description of the subrange to accept. \
- Or None for all. See: \
+ :param selector: a description of the subrange to accept.
+ Or `None` for all. See
:py:meth:`~spinn_utilities.ranged.AbstractSized.selector_to_ids`
:type selector: slice or int or iterable(bool) or iterable(int)
- :param parameter_names: Name of parameter. This is either a\
+ :param parameter_names: Name of parameter. This is either a
single string or a list of strings
:type parameter_names: str or iterable(str)
- :return: A single list of values (or possibly a single value) if\
- paramter_names is a string or a dict of these if parameter names\
+ :return: A single list of values (or possibly a single value) if
+ paramter_names is a string or a dict of these if parameter names
is a list.
:rtype: str or list(str) or dict(str,str) or dict(str,list(str))
"""
@@ -365,7 +366,7 @@ def _initialize(self, variable, value):
raise KeyError(
"Population does not support the initialisation of {}".format(
variable))
- if globals_variables.get_not_running_simulator().has_ran \
+ if get_not_running_simulator().has_ran \
and not self._vertex_changeable_after_run:
raise Exception("Population does not support changes after run")
self._read_parameters_before_set()
@@ -415,7 +416,7 @@ def _set_check(self, parameter, value):
raise KeyError("Population does not have property {}".format(
parameter))
- if globals_variables.get_not_running_simulator().has_ran \
+ if get_not_running_simulator().has_ran \
and not self._vertex_changeable_after_run:
raise Exception(
" run has been called")
@@ -433,9 +434,9 @@ def _set_check(self, parameter, value):
def set(self, parameter, value=None):
""" Set one or more parameters for every cell in the population.
- param can be a dict, in which case value should not be supplied, or a\
- string giving the parameter name, in which case value is the parameter\
- value. value can be a numeric value, or list of such\
+ param can be a dict, in which case value should not be supplied, or a
+ string giving the parameter name, in which case value is the parameter
+ value. value can be a numeric value, or list of such
(e.g. for setting spike times)::
p.set("tau_m", 20.0).
@@ -460,8 +461,8 @@ def set(self, parameter, value=None):
def set_by_selector(self, selector, parameter, value=None):
""" Set one or more parameters for selected cell in the population.
- param can be a dict, in which case value should not be supplied, or a\
- string giving the parameter name, in which case value is the parameter\
+ param can be a dict, in which case value should not be supplied, or a
+ string giving the parameter name, in which case value is the parameter
value. value can be a numeric value, or list of such
(e.g. for setting spike times)::
@@ -486,27 +487,24 @@ def set_by_selector(self, selector, parameter, value=None):
self.__vertex.set_value_by_selector(selector, key, value)
def _read_parameters_before_set(self):
- """ Reads parameters from the machine before "set" completes
-
- :return: None
+ """ Reads parameters from the machine before "set" completes.
"""
# If the tools have run before, and not reset, and the read
# hasn't already been done, read back the data
- if globals_variables.get_simulator().has_ran \
+ if get_simulator().has_ran \
and self._vertex_read_parameters_before_set \
and not self.__has_read_neuron_parameters_this_run \
- and not globals_variables.get_simulator().use_virtual_board:
+ and not get_simulator().use_virtual_board:
+ placements = get_simulator().placements
# go through each machine vertex and read the neuron parameters
# it contains
for machine_vertex in self.__vertex.machine_vertices:
# tell the core to rewrite neuron params back to the
# SDRAM space.
- placement = globals_variables.get_simulator().placements.\
- get_placement_of_vertex(machine_vertex)
-
self.__vertex.read_parameters_from_machine(
- globals_variables.get_simulator().transceiver, placement,
+ get_simulator().transceiver,
+ placements.get_placement_of_vertex(machine_vertex),
machine_vertex.vertex_slice)
self.__has_read_neuron_parameters_this_run = True
@@ -559,7 +557,7 @@ def set_constraint(self, constraint):
:param ~pacman.model.constraints.AbstractConstraint constraint:
"""
- globals_variables.get_simulator().verify_not_running()
+ get_simulator().verify_not_running()
if not isinstance(constraint, AbstractConstraint):
raise ConfigurationException(
"the constraint entered is not a recognised constraint")
@@ -576,7 +574,7 @@ def add_placement_constraint(self, x, y, p=None):
:param int y: The y-coordinate of the placement constraint
:param int p: The processor ID of the placement constraint (optional)
"""
- globals_variables.get_simulator().verify_not_running()
+ get_simulator().verify_not_running()
self.__vertex.add_constraint(ChipAndCoreConstraint(x, y, p))
# state that something has changed in the population,
@@ -590,7 +588,7 @@ def set_mapping_constraint(self, constraint_dict):
A dictionary containing "x", "y" and optionally "p" as keys, and
ints as values
"""
- globals_variables.get_simulator().verify_not_running()
+ get_simulator().verify_not_running()
self.add_placement_constraint(**constraint_dict)
# state that something has changed in the population,
@@ -603,7 +601,7 @@ def set_max_atoms_per_core(self, max_atoms_per_core):
:param int max_atoms_per_core:
the new value for the max atoms per core.
"""
- globals_variables.get_simulator().verify_not_running()
+ get_simulator().verify_not_running()
self.__vertex.add_constraint(
MaxVertexAtomsConstraint(max_atoms_per_core))
# state that something has changed in the population
diff --git a/spynnaker/pyNN/models/pynn_projection_common.py b/spynnaker/pyNN/models/pynn_projection_common.py
index 2aadb28c0a3..44a16dd0036 100644
--- a/spynnaker/pyNN/models/pynn_projection_common.py
+++ b/spynnaker/pyNN/models/pynn_projection_common.py
@@ -14,7 +14,6 @@
# along with this program. If not, see .
import logging
-import math
import numpy
from pyNN.random import RandomDistribution
from spinn_utilities.progress_bar import ProgressBar
@@ -31,14 +30,16 @@
DelayedApplicationEdge, SynapseInformation,
ProjectionApplicationEdge, DelayAfferentApplicationEdge)
from spynnaker.pyNN.models.utility_models.delays import DelayExtensionVertex
-from spynnaker.pyNN.utilities import constants
+from spynnaker.pyNN.utilities.constants import (
+ MAX_DELAY_BLOCKS, MAX_TIMER_TICS_SUPPORTED_PER_BLOCK, SPIKE_PARTITION_ID)
from spynnaker.pyNN.models.neuron import ConnectionHolder
+from spynnaker.pyNN.utilities.utility_calls import ceildiv
# pylint: disable=protected-access
logger = logging.getLogger(__name__)
_delay_extension_max_supported_delay = (
- constants.MAX_DELAY_BLOCKS * constants.MAX_TIMER_TICS_SUPPORTED_PER_BLOCK)
+ MAX_DELAY_BLOCKS * MAX_TIMER_TICS_SUPPORTED_PER_BLOCK)
# The maximum delay supported by the Delay extension, in ticks.
@@ -181,7 +182,7 @@ def __init__(
# add edge to the graph
spinnaker_control.add_application_edge(
- self.__projection_edge, constants.SPIKE_PARTITION_ID)
+ self.__projection_edge, SPIKE_PARTITION_ID)
# If the delay exceeds the post vertex delay, add a delay extension
if max_delay > post_vertex_max_supported_delay_ms:
@@ -248,8 +249,8 @@ def _find_existing_edge(self, pre_synaptic_vertex, post_synaptic_vertex):
:param post_synaptic_vertex: The destination vertex of the multapse
:type post_synaptic_vertex:
~pacman.model.graphs.application.ApplicationVertex
- :return: None or the edge going to these vertices.
- :rtype: ~.ApplicationEdge
+ :return: the edge going to these vertices, if one exists.
+ :rtype: ~.ApplicationEdge or None
"""
# Find edges ending at the postsynaptic vertex
@@ -297,13 +298,13 @@ def _add_delay_extension(
pre_vertex, delay_vertex, label="{}_to_DelayExtension".format(
pre_vertex.label))
self.__spinnaker_control.add_application_edge(
- delay_afferent_edge, constants.SPIKE_PARTITION_ID)
+ delay_afferent_edge, SPIKE_PARTITION_ID)
# Ensure that the delay extension knows how many states it will
# support
- n_stages = int(math.ceil(
- float(max_delay_for_projection - max_delay_per_neuron) /
- float(max_delay_per_neuron)))
+ n_stages = ceildiv(
+ max_delay_for_projection - max_delay_per_neuron,
+ max_delay_per_neuron)
if n_stages > delay_vertex.n_delay_stages:
delay_vertex.n_delay_stages = n_stages
@@ -315,7 +316,7 @@ def _add_delay_extension(
label="{}_delayed_to_{}".format(
pre_vertex.label, post_vertex.label))
self.__spinnaker_control.add_application_edge(
- delay_edge, constants.SPIKE_PARTITION_ID)
+ delay_edge, SPIKE_PARTITION_ID)
else:
delay_edge.add_synapse_information(self.__synapse_information)
return delay_edge
diff --git a/spynnaker/pyNN/models/recording_common.py b/spynnaker/pyNN/models/recording_common.py
index 5ff82ef5278..bfc86ad9984 100644
--- a/spynnaker/pyNN/models/recording_common.py
+++ b/spynnaker/pyNN/models/recording_common.py
@@ -60,12 +60,11 @@ def _record(self, variable, sampling_interval=None, to_file=None,
indexes=None):
""" Tell the vertex to record data.
- :param str variable: the variable to record, valued variables to\
+ :param str variable: the variable to record, valued variables to
record are: 'gsyn_exc', 'gsyn_inh', 'v', 'spikes'
:param int sampling_interval: the interval to record them
:param indexes: List of indexes to record or None for all
:type indexes: list(int) or None
- :return: None
"""
get_simulator().verify_not_running()
@@ -206,8 +205,6 @@ def _get_spikes(self):
def _turn_off_all_recording(self, indexes=None):
""" Turns off recording, is used by a pop saying `.record()`
-
- :rtype: None
"""
# check for standard record which includes spikes
if isinstance(self.__population._vertex, AbstractNeuronRecordable):
diff --git a/spynnaker/pyNN/models/spike_source/spike_source_array_vertex.py b/spynnaker/pyNN/models/spike_source/spike_source_array_vertex.py
index ad91188f3a3..cb034913176 100644
--- a/spynnaker/pyNN/models/spike_source/spike_source_array_vertex.py
+++ b/spynnaker/pyNN/models/spike_source/spike_source_array_vertex.py
@@ -20,10 +20,10 @@
from spinn_front_end_common.abstract_models import AbstractChangableAfterRun
from spinn_front_end_common.abstract_models.impl import (
ProvidesKeyToAtomMappingImpl)
-from spinn_front_end_common.utilities import globals_variables
+from spinn_front_end_common.utilities.globals_variables import get_simulator
from spynnaker.pyNN.models.common import (
AbstractSpikeRecordable, EIEIOSpikeRecorder, SimplePopulationSettable)
-from spynnaker.pyNN.utilities import constants
+from spynnaker.pyNN.utilities.constants import SPIKE_PARTITION_ID
logger = logging.getLogger(__name__)
@@ -66,7 +66,7 @@ def __init__(
n_keys=n_neurons, label=label, constraints=constraints,
max_atoms_per_core=max_atoms_per_core,
send_buffer_times=_send_buffer_times(spike_times, time_step),
- send_buffer_partition_id=constants.SPIKE_PARTITION_ID)
+ send_buffer_partition_id=SPIKE_PARTITION_ID)
# handle recording
self.__spike_recorder = EIEIOSpikeRecorder()
@@ -118,7 +118,7 @@ def set_recording_spikes(
@overrides(AbstractSpikeRecordable.get_spikes_sampling_interval)
def get_spikes_sampling_interval(self):
- return globals_variables.get_simulator().machine_time_step
+ return get_simulator().machine_time_step
@overrides(AbstractSpikeRecordable.get_spikes)
def get_spikes(self, placements, buffer_manager, machine_time_step):
@@ -141,11 +141,11 @@ def clear_spike_recording(self, buffer_manager, placements):
def describe(self):
""" Returns a human-readable description of the cell or synapse type.
- The output may be customised by specifying a different template\
- together with an associated template engine\
+ The output may be customised by specifying a different template
+ together with an associated template engine
(see :py:mod:`pyNN.descriptions`).
- If template is None, then a dictionary containing the template\
+ If template is `None`, then a dictionary containing the template
context will be returned.
"""
diff --git a/spynnaker/pyNN/models/spike_source/spike_source_poisson_vertex.py b/spynnaker/pyNN/models/spike_source/spike_source_poisson_vertex.py
index 9b3a403ea94..7ba1a6b40c8 100644
--- a/spynnaker/pyNN/models/spike_source/spike_source_poisson_vertex.py
+++ b/spynnaker/pyNN/models/spike_source/spike_source_poisson_vertex.py
@@ -14,11 +14,9 @@
# along with this program. If not, see .
import logging
-import math
import numpy
import scipy.stats
import struct
-
from spinn_utilities.overrides import overrides
from data_specification.enums import DataType
from pacman.executor.injection_decorator import inject_items
@@ -33,29 +31,34 @@
AbstractRewritesDataSpecification)
from spinn_front_end_common.abstract_models.impl import (
ProvidesKeyToAtomMappingImpl)
-from spinn_front_end_common.interface.simulation import simulation_utilities
-from spinn_front_end_common.interface.buffer_management import (
- recording_utilities)
-from spinn_front_end_common.utilities import (
- helpful_functions, globals_variables)
+from spinn_front_end_common.interface.simulation.simulation_utilities import (
+ get_simulation_header_array)
+from spinn_front_end_common.interface.buffer_management.recording_utilities \
+ import (
+ get_recording_header_size, get_recording_data_constant_size,
+ get_recording_header_array)
from spinn_front_end_common.utilities.constants import (
SYSTEM_BYTES_REQUIREMENT, SIMULATION_N_BYTES, BYTES_PER_WORD)
+from spinn_front_end_common.utilities.globals_variables import get_simulator
+from spinn_front_end_common.utilities.helpful_functions import (
+ locate_memory_region_for_placement, read_config_int)
from spinn_front_end_common.utilities.utility_objs import ExecutableType
from spinn_front_end_common.utilities.exceptions import ConfigurationException
-from spinn_front_end_common.interface.profiling import profile_utils
+from spinn_front_end_common.interface.profiling.profile_utils import (
+ get_profile_region_size, reserve_profile_region, write_profile_region_data)
from spynnaker.pyNN.models.common import (
AbstractSpikeRecordable, MultiSpikeRecorder, SimplePopulationSettable)
-from spynnaker.pyNN.utilities import constants
+from spynnaker.pyNN.utilities.constants import (
+ LIVE_POISSON_CONTROL_PARTITION_ID, SPIKE_PARTITION_ID)
from spynnaker.pyNN.models.abstract_models import (
AbstractReadParametersBeforeSet)
+from spynnaker.pyNN.utilities.utility_calls import (
+ validate_mars_kiss_64_seed, ceildiv, round_up)
+from spynnaker.pyNN.utilities.struct import Struct
+from spynnaker.pyNN.utilities.ranged import (
+ SpynnakerRangeDictionary, SpynnakerRangedList)
from .spike_source_poisson_machine_vertex import (
SpikeSourcePoissonMachineVertex)
-from spynnaker.pyNN.utilities.utility_calls import validate_mars_kiss_64_seed
-from spynnaker.pyNN.utilities.struct import Struct
-from spynnaker.pyNN.utilities.ranged.spynnaker_ranged_dict \
- import SpynnakerRangeDictionary
-from spynnaker.pyNN.utilities.ranged.spynnaker_ranged_list \
- import SpynnakerRangedList
logger = logging.getLogger(__name__)
@@ -154,14 +157,18 @@ def __init__(
max_rate=None):
"""
:param int n_neurons:
- :param constraints:
+ :param list(~pacman.model.constrants.AbstractConstraint) constraints:
:param str label:
:param float seed:
:param int max_atoms_per_core:
- :param model:
- :param iterable of float rate:
- :param iterable of int start:
- :param iterable of int duration:
+ :param AbstractPyNNModel model:
+ :param float rate:
+ :param int start:
+ :param int duration:
+ :param iterable(float) rates:
+ :param iterable(int) starts:
+ :param iterable(int) durations:
+ :param float max_rate:
"""
# pylint: disable=too-many-arguments
super(SpikeSourcePoissonVertex, self).__init__(
@@ -302,8 +309,8 @@ def __init__(
self.__machine_time_step = None
# get config from simulator
- config = globals_variables.get_simulator().config
- self.__n_profile_samples = helpful_functions.read_config_int(
+ config = get_simulator().config
+ self.__n_profile_samples = read_config_int(
config, "Reports", "n_profile_samples")
# Prepare for recording, and to get spikes
@@ -446,6 +453,7 @@ def set_value(self, key, value):
def _max_spikes_per_ts(self, machine_time_step):
"""
:param int machine_time_step:
+ :rtype: int or float
"""
ts_per_second = MICROSECONDS_PER_SECOND / float(machine_time_step)
if float(self.__max_rate) / ts_per_second < \
@@ -457,7 +465,7 @@ def _max_spikes_per_ts(self, machine_time_step):
max_spikes_per_ts = scipy.stats.poisson.ppf(
1.0 - (1.0 / float(chance_ts)),
float(self.__max_rate) / ts_per_second)
- return int(math.ceil(max_spikes_per_ts)) + 1.0
+ return round_up(max_spikes_per_ts) + 1.0
def get_recording_sdram_usage(self, vertex_slice, machine_time_step):
"""
@@ -479,8 +487,7 @@ def get_recording_sdram_usage(self, vertex_slice, machine_time_step):
)
def get_resources_used_by_atoms(self, vertex_slice, machine_time_step):
"""
- :param ~pacman.model.graphs.common.Slice vertex_slice:
- :param int machine_time_step:
+ :param int machine_time_step: (injected)
"""
# pylint: disable=arguments-differ
poisson_params_sz = self.get_rates_bytes(vertex_slice)
@@ -488,9 +495,9 @@ def get_resources_used_by_atoms(self, vertex_slice, machine_time_step):
SYSTEM_BYTES_REQUIREMENT +
SpikeSourcePoissonMachineVertex.get_provenance_data_size(0) +
poisson_params_sz +
- recording_utilities.get_recording_header_size(1) +
- recording_utilities.get_recording_data_constant_size(1) +
- profile_utils.get_profile_region_size(self.__n_profile_samples))
+ get_recording_header_size(1) +
+ get_recording_data_constant_size(1) +
+ get_profile_region_size(self.__n_profile_samples))
recording = self.get_recording_sdram_usage(
vertex_slice, machine_time_step)
@@ -546,11 +553,10 @@ def reserve_memory_regions(self, spec, placement):
""" Reserve memory regions for Poisson source parameters and output\
buffer.
- :param ~data_specification.DataSpecification spec:
+ :param ~data_specification.DataSpecificationGenerator spec:
the data specification writer
- :param ~pacman.models.placements.Placement placement:
+ :param ~pacman.model.placements.Placement placement:
the location this vertex resides on in the machine
- :return: None
"""
spec.comment("\nReserving memory space for data regions:\n\n")
@@ -565,10 +571,10 @@ def reserve_memory_regions(self, spec, placement):
spec.reserve_memory_region(
region=_REGIONS.SPIKE_HISTORY_REGION.value,
- size=recording_utilities.get_recording_header_size(1),
+ size=get_recording_header_size(1),
label="Recording")
- profile_utils.reserve_profile_region(
+ reserve_profile_region(
spec, _REGIONS.PROFILER_REGION.value, self.__n_profile_samples)
placement.vertex.reserve_provenance_data_region(spec)
@@ -577,10 +583,8 @@ def _reserve_poisson_params_rates_region(self, placement, spec):
""" Allocate space for the Poisson parameters and rates regions as\
they can be reused for setters after an initial run
- :param ~pacman.models.placements.Placement placement:
- the location on machine for this vertex
- :param ~data_specification.DataSpecification spec: the DSG writer
- :return: None
+ :param ~.Placement placement: the location on machine for this vertex
+ :param ~.DataSpecificationGenerator spec: the DSG writer
"""
spec.reserve_memory_region(
region=_REGIONS.POISSON_PARAMS_REGION.value,
@@ -595,11 +599,10 @@ def _write_poisson_parameters(
vertex_slice, machine_time_step, time_scale_factor):
""" Generate Parameter data for Poisson spike sources
- :param ~data_specification.DataSpecification spec:
- the data specification writer
- :param ~pacman.model.graphs.machine.MachineGraph graph:
- :param ~pacman.model.placements.Placement placement:
- :param ~pacman.model.routing_info.RoutingInfo routing_info:
+ :param ~.DataSpecificationGenerator spec: the data specification writer
+ :param ~.MachineGraph graph:
+ :param ~.Placement placement:
+ :param ~.RoutingInfo routing_info:
:param ~pacman.model.graphs.common.Slice vertex_slice:
the slice of atoms a machine vertex holds from its application
vertex
@@ -616,13 +619,13 @@ def _write_poisson_parameters(
# Write Key info for this core:
key = routing_info.get_first_key_from_pre_vertex(
- placement.vertex, constants.SPIKE_PARTITION_ID)
+ placement.vertex, SPIKE_PARTITION_ID)
spec.write_value(data=1 if key is not None else 0)
spec.write_value(data=key if key is not None else 0)
# Write the incoming mask if there is one
in_edges = graph.get_edges_ending_at_vertex_with_partition_name(
- placement.vertex, constants.LIVE_POISSON_CONTROL_PARTITION_ID)
+ placement.vertex, LIVE_POISSON_CONTROL_PARTITION_ID)
if len(in_edges) > 1:
raise ConfigurationException(
"Only one control edge can end at a Poisson vertex")
@@ -640,8 +643,7 @@ def _write_poisson_parameters(
max_offset = (
machine_time_step * time_scale_factor) // _MAX_OFFSET_DENOMINATOR
spec.write_value(
- int(math.ceil(max_offset / self.__n_subvertices)) *
- self.__n_data_specs)
+ ceildiv(max_offset, self.__n_subvertices) * self.__n_data_specs)
self.__n_data_specs += 1
if self.__max_spikes > 0:
@@ -702,7 +704,7 @@ def _write_poisson_rates(self, spec, vertex_slice, machine_time_step,
first_machine_time_step):
""" Generate Rate data for Poisson spike sources
- :param ~data_specification.DataSpecification spec:
+ :param ~.DataSpecificationGenerator spec:
the data specification writer
:param ~pacman.model.graphs.common.Slice vertex_slice:
the slice of atoms a machine vertex holds from its application
@@ -809,15 +811,15 @@ def _write_poisson_rates(self, spec, vertex_slice, machine_time_step,
@staticmethod
def _convert_ms_to_n_timesteps(value, machine_time_step):
+ """
+ :param ~numpy.ndarray value:
+ :param int machine_time_step:
+ :rtype: ~numpy.ndarray
+ """
return numpy.round(
value * (MICROSECONDS_PER_MILLISECOND /
float(machine_time_step))).astype("uint32")
- @staticmethod
- def _convert_n_timesteps_to_ms(value, machine_time_step):
- return (
- value / (MICROSECONDS_PER_MILLISECOND / float(machine_time_step)))
-
@overrides(AbstractSpikeRecordable.is_recording_spikes)
def is_recording_spikes(self):
return self.__spike_recorder.record
@@ -837,14 +839,20 @@ def set_recording_spikes(
@overrides(AbstractSpikeRecordable.get_spikes_sampling_interval)
def get_spikes_sampling_interval(self):
- return globals_variables.get_simulator().machine_time_step
+ return get_simulator().machine_time_step
@staticmethod
def get_dtcm_usage_for_atoms():
+ """
+ :rtype: int
+ """
return 0
@staticmethod
def get_cpu_usage_for_atoms():
+ """
+ :rtype: int
+ """
return 0
@inject_items({
@@ -862,11 +870,11 @@ def regenerate_data_specification(
self, spec, placement, machine_time_step, time_scale_factor,
routing_info, graph, first_machine_time_step):
"""
- :param int machine_time_step:
- :param int time_scale_factor:
- :param ~pacman.model.routing_info.RoutingInfo routing_info:
- :param ~pacman.model.graphs.machine.MachineGraph graph:
- :param int first_machine_time_step:
+ :param int machine_time_step: (injected)
+ :param int time_scale_factor: (injected)
+ :param ~pacman.model.routing_info.RoutingInfo routing_info: (injected)
+ :param ~pacman.model.graphs.machine.MachineGraph graph: (injected)
+ :param int first_machine_time_step: (injected)
"""
# pylint: disable=too-many-arguments, arguments-differ
@@ -907,18 +915,16 @@ def read_parameters_from_machine(
self, transceiver, placement, vertex_slice):
# locate SDRAM address where parameters are stored
- poisson_params = \
- helpful_functions.locate_memory_region_for_placement(
- placement, _REGIONS.POISSON_PARAMS_REGION.value, transceiver)
+ poisson_params = locate_memory_region_for_placement(
+ placement, _REGIONS.POISSON_PARAMS_REGION.value, transceiver)
seed_array = transceiver.read_memory(
placement.x, placement.y, poisson_params + SEED_OFFSET_BYTES,
SEED_SIZE_BYTES)
self.__kiss_seed[vertex_slice] = struct.unpack_from("<4I", seed_array)
# locate SDRAM address where the rates are stored
- poisson_rate_region_sdram_address = \
- helpful_functions.locate_memory_region_for_placement(
- placement, _REGIONS.RATES_REGION.value, transceiver)
+ poisson_rate_region_sdram_address = locate_memory_region_for_placement(
+ placement, _REGIONS.RATES_REGION.value, transceiver)
# get size of poisson params
size_of_region = self.get_rates_bytes(vertex_slice)
@@ -985,12 +991,12 @@ def generate_data_specification(
self, spec, placement, machine_time_step, time_scale_factor,
routing_info, data_n_time_steps, graph, first_machine_time_step):
"""
- :param int machine_time_step:
- :param int time_scale_factor:
- :param ~pacman.model.routing_info.RoutingInfo routing_info:
- :param int data_n_time_steps:
- :param ~pacman.model.graphs.machine.MachineGraph graph:
- :param int first_machine_time_step:
+ :param int machine_time_step: (injected)
+ :param int time_scale_factor: (injected)
+ :param ~pacman.model.routing_info.RoutingInfo routing_info: (injected)
+ :param int data_n_time_steps: (injected)
+ :param ~pacman.model.graphs.machine.MachineGraph graph: (injected)
+ :param int first_machine_time_step: (injected)
"""
# pylint: disable=too-many-arguments, arguments-differ
self.__machine_time_step = machine_time_step
@@ -1003,7 +1009,7 @@ def generate_data_specification(
# write setup data
spec.switch_write_focus(_REGIONS.SYSTEM_REGION.value)
- spec.write_array(simulation_utilities.get_simulation_header_array(
+ spec.write_array(get_simulation_header_array(
self.get_binary_file_name(), machine_time_step,
time_scale_factor))
@@ -1011,8 +1017,7 @@ def generate_data_specification(
spec.switch_write_focus(_REGIONS.SPIKE_HISTORY_REGION.value)
sdram = self.get_recording_sdram_usage(vertex_slice, machine_time_step)
recorded_region_sizes = [sdram.get_total_sdram(data_n_time_steps)]
- spec.write_array(recording_utilities.get_recording_header_array(
- recorded_region_sizes))
+ spec.write_array(get_recording_header_array(recorded_region_sizes))
# write parameters
self._write_poisson_parameters(
@@ -1024,9 +1029,8 @@ def generate_data_specification(
first_machine_time_step)
# write profile data
- profile_utils.write_profile_region_data(
- spec, _REGIONS.PROFILER_REGION.value,
- self.__n_profile_samples)
+ write_profile_region_data(
+ spec, _REGIONS.PROFILER_REGION.value, self.__n_profile_samples)
# End-of-Spec:
spec.end_specification()
@@ -1062,12 +1066,12 @@ def clear_spike_recording(self, buffer_manager, placements):
def describe(self):
""" Return a human-readable description of the cell or synapse type.
- The output may be customised by specifying a different template\
- together with an associated template engine\
+ The output may be customised by specifying a different template
+ together with an associated template engine
(see :py:mod:`pyNN.descriptions`).
- If template is None, then a dictionary containing the template context\
- will be returned.
+ If template is `None`, then a dictionary containing the template
+ context will be returned.
:rtype: dict(str, ...)
"""
diff --git a/spynnaker/pyNN/models/utility_models/delays/delay_block.py b/spynnaker/pyNN/models/utility_models/delays/delay_block.py
index feea65f6759..d0de1f08422 100644
--- a/spynnaker/pyNN/models/utility_models/delays/delay_block.py
+++ b/spynnaker/pyNN/models/utility_models/delays/delay_block.py
@@ -12,9 +12,9 @@
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see .
-
-import math
import numpy
+from spynnaker.pyNN.utilities.utility_calls import ceildiv
+from spynnaker.pyNN.utilities.constants import BITS_PER_WORD
class DelayBlock(object):
@@ -33,7 +33,7 @@ def __init__(self, n_delay_stages, delay_per_stage, vertex_slice):
"""
self.__delay_per_stage = delay_per_stage
self.__n_delay_stages = n_delay_stages
- n_words_per_row = int(math.ceil(vertex_slice.n_atoms / 32.0))
+ n_words_per_row = ceildiv(vertex_slice.n_atoms, BITS_PER_WORD)
self.__delay_block = numpy.zeros(
(n_delay_stages, n_words_per_row), dtype="uint32")
diff --git a/spynnaker/pyNN/models/utility_models/delays/delay_extension_machine_vertex.py b/spynnaker/pyNN/models/utility_models/delays/delay_extension_machine_vertex.py
index 23c7aef4053..f02ca1c6d9c 100644
--- a/spynnaker/pyNN/models/utility_models/delays/delay_extension_machine_vertex.py
+++ b/spynnaker/pyNN/models/utility_models/delays/delay_extension_machine_vertex.py
@@ -23,6 +23,8 @@
class DelayExtensionMachineVertex(
MachineVertex, ProvidesProvenanceDataFromMachineImpl):
+ """ Implements long delays of spikes.
+ """
__slots__ = [
"__resources"]
@@ -48,11 +50,13 @@ def __init__(self, resources_required, label, constraints=None,
:param ~pacman.model.resources.ResourceContainer resources_required:
The resources required by the vertex
:param str label: The optional name of the vertex
- :param iterable(AbstractConstraint) constraints:
+ :param constraints:
The optional initial constraints of the vertex
- :param ~pacman.model.graphs.application.ApplicationVertex app_vertex:
+ :type constraints:
+ iterable(~pacman.model.constraints.AbstractConstraint)
+ :param DelayExtensionVertex app_vertex:
The application vertex that caused this machine vertex to be
- created. If None, there is no such application vertex.
+ created.
:param ~pacman.model.graphs.common.Slice vertex_slice:
The slice of the application vertex that this machine vertex
implements.
diff --git a/spynnaker/pyNN/models/utility_models/delays/delay_extension_vertex.py b/spynnaker/pyNN/models/utility_models/delays/delay_extension_vertex.py
index 21cd5f1a6c6..1e71dd26592 100644
--- a/spynnaker/pyNN/models/utility_models/delays/delay_extension_vertex.py
+++ b/spynnaker/pyNN/models/utility_models/delays/delay_extension_vertex.py
@@ -12,10 +12,7 @@
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see .
-
from collections import defaultdict
-import logging
-import math
from spinn_utilities.overrides import overrides
from pacman.executor.injection_decorator import inject_items
from pacman.model.constraints.key_allocator_constraints import (
@@ -30,20 +27,19 @@
AbstractProvidesOutgoingPartitionConstraints, AbstractHasAssociatedBinary)
from spinn_front_end_common.interface.simulation import simulation_utilities
from spinn_front_end_common.utilities.constants import (
- SYSTEM_BYTES_REQUIREMENT, SIMULATION_N_BYTES, BITS_PER_WORD,
- BYTES_PER_WORD)
+ SYSTEM_BYTES_REQUIREMENT, SIMULATION_N_BYTES, BYTES_PER_WORD)
from spinn_front_end_common.utilities.utility_objs import ExecutableType
from .delay_block import DelayBlock
from .delay_extension_machine_vertex import DelayExtensionMachineVertex
from .delay_generator_data import DelayGeneratorData
-from spynnaker.pyNN.utilities.constants import SPIKE_PARTITION_ID
+from spynnaker.pyNN.utilities.constants import (
+ SPIKE_PARTITION_ID, BITS_PER_WORD)
from spynnaker.pyNN.models.neural_projections import DelayedApplicationEdge
from spynnaker.pyNN.models.neural_projections.connectors import (
AbstractGenerateConnectorOnMachine)
from spynnaker.pyNN.models.neuron.synapse_dynamics import (
AbstractGenerateOnMachine)
-
-logger = logging.getLogger(__name__)
+from spynnaker.pyNN.utilities.utility_calls import ceildiv
_DELAY_PARAM_HEADER_WORDS = 8
# pylint: disable=protected-access
@@ -87,9 +83,10 @@ def __init__(self, n_neurons, delay_per_stage, source_vertex,
where messages are coming from
:param int machine_time_step: how long is the machine time step
:param int time_scale_factor: what slowdown factor has been applied
- :param iterable(~pacman.model.constraints.AbstractConstraint) \
- constraints:
+ :param constraints:
the vertex constraints
+ :type constraints:
+ iterable(~pacman.model.constraints.AbstractConstraint)
:param str label: the vertex label
"""
# pylint: disable=too-many-arguments
@@ -225,8 +222,7 @@ def generate_data_specification(
# ###################################################################
# Reserve SDRAM space for memory areas:
vertex_slice = vertex.vertex_slice
- n_words_per_stage = int(
- math.ceil(vertex_slice.n_atoms / BITS_PER_WORD))
+ n_words_per_stage = ceildiv(vertex_slice.n_atoms, BITS_PER_WORD)
delay_params_sz = BYTES_PER_WORD * (
_DELAY_PARAM_HEADER_WORDS +
(self.__n_delay_stages * n_words_per_stage))
@@ -289,7 +285,7 @@ def generate_data_specification(
def _write_setup_info(self, spec, machine_time_step, time_scale_factor):
"""
- :param ~data_specification.DataSpecificationGenerator spec:
+ :param ~.DataSpecificationGenerator spec:
:param int machine_time_step:
:param int time_scale_factor:
"""
@@ -340,8 +336,7 @@ def write_delay_parameters(
max_offset = (
machine_time_step * time_scale_factor) // _MAX_OFFSET_DENOMINATOR
spec.write_value(
- int(math.ceil(max_offset / total_n_vertices)) *
- self.__n_data_specs)
+ ceildiv(max_offset, total_n_vertices) * self.__n_data_specs)
self.__n_data_specs += 1
# Write the time between spikes
@@ -384,6 +379,7 @@ def _get_edge_generator_size(self, synapse_info):
""" Get the size of the generator data for a given synapse info object
:param SynapseInformation synapse_info:
+ :rtype: int
"""
connector = synapse_info.connector
dynamics = synapse_info.synapse_dynamics
@@ -394,42 +390,44 @@ def _get_edge_generator_size(self, synapse_info):
synapse_gen = isinstance(
dynamics, AbstractGenerateOnMachine)
if connector_gen and synapse_gen:
- return sum((
- DelayGeneratorData.BASE_SIZE,
- connector.gen_delay_params_size_in_bytes(
- synapse_info.delays),
- connector.gen_connector_params_size_in_bytes,
- ))
+ return (
+ DelayGeneratorData.BASE_SIZE +
+ connector.gen_delay_params_size_in_bytes(synapse_info.delays) +
+ connector.gen_connector_params_size_in_bytes)
return 0
def _get_size_of_generator_information(self, out_edges):
""" Get the size of the generator data for all edges
- :param list(.ApplicationEdge) out_edges:
+ :param list(~.ApplicationEdge) out_edges:
:rtype: int
"""
- gen_on_machine = False
- size = 0
- for out_edge in out_edges:
- if isinstance(out_edge, DelayedApplicationEdge):
- for synapse_info in out_edge.synapse_information:
-
- # Get the number of likely vertices
- max_atoms = out_edge.post_vertex.get_max_atoms_per_core()
- if out_edge.post_vertex.n_atoms < max_atoms:
- max_atoms = out_edge.post_vertex.n_atoms
- n_edge_vertices = int(math.ceil(float(
- out_edge.post_vertex.n_atoms) / float(max_atoms)))
-
- # Get the size
- gen_size = self._get_edge_generator_size(synapse_info)
- if gen_size > 0:
- gen_on_machine = True
- size += gen_size * n_edge_vertices
- if gen_on_machine:
+ size = sum(
+ self.__size_of_edge_generator_info(edge)
+ for edge in out_edges
+ if isinstance(edge, DelayedApplicationEdge))
+ # If there's a non-zero size, we will be generating on machine and we
+ # should add the baseline overhead
+ if size:
size += _EXPANDER_BASE_PARAMS_SIZE
return size
+ def __size_of_edge_generator_info(self, edge):
+ """
+ :param DelayedApplicationEdge edge:
+ :rtype: int
+ """
+ # Get the number of likely vertices
+ max_atoms = min(
+ edge.post_vertex.get_max_atoms_per_core(),
+ edge.post_vertex.n_atoms)
+ n_edge_vertices = ceildiv(edge.post_vertex.n_atoms, max_atoms)
+
+ # Get the size for each synapse type
+ return sum(
+ self._get_edge_generator_size(synapse_info) * n_edge_vertices
+ for synapse_info in edge.synapse_information)
+
def get_dtcm_usage_for_atoms(self, vertex_slice):
"""
:param ~pacman.model.graphs.common.Slice vertex_slice:
diff --git a/spynnaker/pyNN/models/utility_models/spike_injector/spike_injector_vertex.py b/spynnaker/pyNN/models/utility_models/spike_injector/spike_injector_vertex.py
index 1825924a93a..18aba38ba42 100644
--- a/spynnaker/pyNN/models/utility_models/spike_injector/spike_injector_vertex.py
+++ b/spynnaker/pyNN/models/utility_models/spike_injector/spike_injector_vertex.py
@@ -131,8 +131,8 @@ def describe(self):
together with an associated template engine
(see :py:mod:`pyNN.descriptions`).
- If template is None, then a dictionary containing the template context
- will be returned.
+ If template is `None`, then a dictionary containing the template
+ context will be returned.
"""
parameters = dict()
diff --git a/spynnaker/pyNN/protocols/munich_io_spinnaker_link_protocol.py b/spynnaker/pyNN/protocols/munich_io_spinnaker_link_protocol.py
index 638ef8dff91..77242bcea5b 100644
--- a/spynnaker/pyNN/protocols/munich_io_spinnaker_link_protocol.py
+++ b/spynnaker/pyNN/protocols/munich_io_spinnaker_link_protocol.py
@@ -12,14 +12,10 @@
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see .
-
from enum import Enum
-import logging
from spinn_front_end_common.utility_models import MultiCastCommand
from spinn_front_end_common.utilities.exceptions import ConfigurationException
-logger = logging.getLogger(__name__)
-
# structure of command is KKKKKKKKKKKKKKKKKKKKK-IIIIIII-F-DDD
# K = ignored key at the top of the command
# I = instruction
diff --git a/spynnaker/pyNN/spynnaker_external_device_plugin_manager.py b/spynnaker/pyNN/spynnaker_external_device_plugin_manager.py
index 0df662a5f42..9d80087bc57 100644
--- a/spynnaker/pyNN/spynnaker_external_device_plugin_manager.py
+++ b/spynnaker/pyNN/spynnaker_external_device_plugin_manager.py
@@ -16,7 +16,8 @@
from spinn_utilities.socket_address import SocketAddress
from pacman.model.graphs.application import ApplicationEdge
from spinnman.messages.eieio import EIEIOType
-from spinn_front_end_common.utilities import helpful_functions
+from spinn_front_end_common.utilities.helpful_functions import (
+ read_config, read_config_int)
from spinn_front_end_common.utilities.globals_variables import get_simulator
from spinn_front_end_common.utility_models import (
ReverseIpTagMultiCastSource)
@@ -50,15 +51,15 @@ def add_database_socket_address(
"""
config = get_simulator().config
if database_notify_port_num is None:
- database_notify_port_num = helpful_functions.read_config_int(
+ database_notify_port_num = read_config_int(
config, "Database", "notify_port")
if database_notify_host is None:
- database_notify_host = helpful_functions.read_config(
+ database_notify_host = read_config(
config, "Database", "notify_hostname")
elif database_notify_host == "0.0.0.0":
database_notify_host = "localhost"
if database_ack_port_num is None:
- database_ack_port_num = helpful_functions.read_config_int(
+ database_ack_port_num = read_config_int(
config, "Database", "listen_port")
# build the database socket address used by the notification interface
@@ -293,23 +294,31 @@ def add_edge(vertex, device_vertex, partition_id):
:param ~pacman.model.graphs.application.ApplicationVertex vertex:
the pre-vertex to connect the edge from
- :param device_vertex: the post vertex to connect the edge to
+ :param device_vertex: the post-vertex to connect the edge to
:type device_vertex:
~pacman.model.graphs.application.ApplicationVertex
:param str partition_id: the partition identifier for making nets
"""
- _spinnaker = get_simulator()
edge = ApplicationEdge(vertex, device_vertex)
- _spinnaker.add_application_edge(edge, partition_id)
+ get_simulator().add_application_edge(edge, partition_id)
@staticmethod
def add_application_vertex(vertex):
+ """
+ :param ~pacman.model.graphs.application.ApplicationVertex vertex:
+ """
get_simulator().add_application_vertex(vertex)
@staticmethod
def machine_time_step():
+ """
+ :rtype: int
+ """
return get_simulator().machine_time_step
@staticmethod
def time_scale_factor():
+ """
+ :rtype: int
+ """
return get_simulator().time_scale_factor
diff --git a/spynnaker/pyNN/utilities/bit_field_utilities.py b/spynnaker/pyNN/utilities/bit_field_utilities.py
index 4fbe52da452..3e4528cbb44 100644
--- a/spynnaker/pyNN/utilities/bit_field_utilities.py
+++ b/spynnaker/pyNN/utilities/bit_field_utilities.py
@@ -13,14 +13,12 @@
# You should have received a copy of the GNU General Public License
# along with this program. If not, see .
-import math
-
from pacman.utilities.constants import FULL_MASK
+from pacman.utilities.algorithm_utilities.partition_algorithm_utilities \
+ import (
+ determine_max_atoms_for_vertex)
from spinn_front_end_common.utilities.constants import BYTES_PER_WORD
-from pacman.utilities.algorithm_utilities. \
- partition_algorithm_utilities import determine_max_atoms_for_vertex
-from spynnaker.pyNN.models.neural_projections import ProjectionApplicationEdge
-from spynnaker.pyNN.models.utility_models.delays import DelayExtensionVertex
+from .utility_calls import ceildiv
# number of elements
ELEMENTS_USED_IN_EACH_BIT_FIELD = 3 # n words, key, pointer to bitfield
@@ -43,47 +41,16 @@
BIT_IN_A_WORD = 32.0
-def get_estimated_sdram_for_bit_field_region(app_graph, vertex):
- """ estimates the sdram for the bit field region
- :param app_graph: the app graph
- :param vertex: machine vertex
- :return: the estimated number of bytes used by the bit field region
- """
- sdram = 0
- for incoming_edge in app_graph.get_edges_ending_at_vertex(vertex):
- if isinstance(incoming_edge, ProjectionApplicationEdge):
- edge_pre_vertex = incoming_edge.pre_vertex
- max_atoms = determine_max_atoms_for_vertex(edge_pre_vertex)
- if incoming_edge.pre_vertex.n_atoms < max_atoms:
- max_atoms = incoming_edge.pre_vertex.n_atoms
-
- # Get the number of likely vertices
- n_machine_vertices = int(math.ceil(
- float(incoming_edge.pre_vertex.n_atoms) /
- float(max_atoms)))
- n_atoms_per_machine_vertex = int(math.ceil(
- float(incoming_edge.pre_vertex.n_atoms) /
- n_machine_vertices))
- if isinstance(edge_pre_vertex, DelayExtensionVertex):
- n_atoms_per_machine_vertex *= \
- edge_pre_vertex.n_delay_stages
- n_words_for_atoms = int(math.ceil(
- n_atoms_per_machine_vertex / BIT_IN_A_WORD))
- sdram += (
- (ELEMENTS_USED_IN_EACH_BIT_FIELD + (
- n_words_for_atoms * n_machine_vertices)) *
- BYTES_PER_WORD)
- return sdram
-
-
def get_estimated_sdram_for_key_region(app_graph, vertex):
- """ gets an estimate of the bitfield builder region
-
- :param app_graph: the app graph
- :param vertex: machine vertex
- :return: sdram needed
+ """ gets an estimate of the bitfield builder region size
+
+ :param ~pacman.model.graphs.application.ApplicationGraph app_graph:
+ the app graph
+ :param ~pacman.model.graphs.application.ApplicationVertex vertex:
+ app vertex
+ :return: SDRAM needed
+ :rtype: int
"""
-
# basic sdram
sdram = N_KEYS_DATA_SET_IN_WORDS * BYTES_PER_WORD
for in_edge in app_graph.get_edges_ending_at_vertex(vertex):
@@ -93,28 +60,27 @@ def get_estimated_sdram_for_key_region(app_graph, vertex):
max_atoms = determine_max_atoms_for_vertex(edge_pre_vertex)
if in_edge.pre_vertex.n_atoms < max_atoms:
max_atoms = in_edge.pre_vertex.n_atoms
- n_edge_vertices = int(math.ceil(
- float(in_edge.pre_vertex.n_atoms) / float(max_atoms)))
+ n_edge_vertices = ceildiv(in_edge.pre_vertex.n_atoms, max_atoms)
sdram += (n_edge_vertices * N_ELEMENTS_IN_EACH_KEY_N_ATOM_MAP *
BYTES_PER_WORD)
return sdram
-def _exact_sdram_for_bit_field_region(
- machine_graph, vertex, n_key_map):
- """ calculates the correct sdram for the bitfield region based off \
- the machine graph and graph mapper
+def _exact_sdram_for_bit_field_region(machine_graph, vertex, n_key_map):
+ """ Gets the correct SDRAM for the bitfield region based off \
+ the machine graph
- :param machine_graph: machine graph
- :param vertex: the machine vertex
- :param n_key_map: n keys map
+ :param ~.MachineGraph machine_graph: machine graph
+ :param ~.MachineVertex vertex: the machine vertex
+ :param ~.AbstractMachinePartitionNKeysMap n_key_map: n keys map
:return: sdram in bytes
+ :rtype: int
"""
sdram = ELEMENTS_USED_IN_BIT_FIELD_HEADER * BYTES_PER_WORD
for incoming_edge in machine_graph.get_edges_ending_at_vertex(vertex):
n_keys = n_key_map.n_keys_for_partition(
machine_graph.get_outgoing_partition_for_edge(incoming_edge))
- n_words_for_atoms = int(math.ceil(n_keys / BIT_IN_A_WORD))
+ n_words_for_atoms = ceildiv(n_keys, int(BIT_IN_A_WORD))
sdram += (
(ELEMENTS_USED_IN_EACH_BIT_FIELD + n_words_for_atoms) *
@@ -123,23 +89,26 @@ def _exact_sdram_for_bit_field_region(
def exact_sdram_for_bit_field_builder_region():
- """ returns the sdram requirement for the builder region
- :return: returns the sdram requirement for the builder region
+ """ Gets the SDRAM requirement for the builder region
+
+ :return: returns the SDRAM requirement for the builder region
+ :rtype: int
"""
return N_REGIONS_ADDRESSES * BYTES_PER_WORD
def _exact_sdram_for_bit_field_key_region(machine_graph, vertex):
- """ calcs the exact sdram for the bitfield key region
+ """ Calculates the exact SDRAM for the bitfield key region
- :param machine_graph: machine graph
- :param vertex: machine vertex
- :return: bytes
+ :param ~.MachineGraph machine_graph: machine graph
+ :param ~.MachineVertex vertex: machine vertex
+ :return: number of bytes
+ :rtype: int
"""
return (
- N_KEYS_DATA_SET_IN_WORDS +
- len(machine_graph.get_edges_ending_at_vertex(vertex)) *
- N_ELEMENTS_IN_EACH_KEY_N_ATOM_MAP) * BYTES_PER_WORD
+ N_KEYS_DATA_SET_IN_WORDS +
+ len(machine_graph.get_edges_ending_at_vertex(vertex)) *
+ N_ELEMENTS_IN_EACH_KEY_N_ATOM_MAP) * BYTES_PER_WORD
def reserve_bit_field_regions(
@@ -147,16 +116,17 @@ def reserve_bit_field_regions(
bit_filter_region, bit_field_key_region):
""" reserves the regions for the bitfields
- :param spec: dsg file
- :param machine_graph: machine graph
- :param n_key_map: map between partitions and n keys
- :param vertex: machine vertex
- :param bit_field_builder_region: region id for the builder region
- :param bit_filter_region: region id for the bitfield region
- :param bit_field_key_region: region id for the key map
- :rtype: None
+ :param ~data_specification.DataSpecificationGenerator spec: dsg file
+ :param ~pacman.model.graphs.machine.MachineGraph machine_graph:
+ machine graph
+ :param ~pacman.model.routing_info.AbstractMachinePartitionNKeysMap \
+ n_key_map:
+ map between partitions and n keys
+ :param ~pacman.model.graphs.machine.MachineVertex vertex: machine vertex
+ :param int bit_field_builder_region: region id for the builder region
+ :param int bit_filter_region: region id for the bitfield region
+ :param int bit_field_key_region: region id for the key map
"""
-
# reserve the final destination for the bitfields
spec.reserve_memory_region(
region=bit_filter_region,
@@ -185,21 +155,24 @@ def write_bitfield_init_data(
structural_dynamics_region_id, has_structural_dynamics_region):
""" writes the init data needed for the bitfield generator
- :param spec: data spec writer
- :param machine_vertex: machine vertex
- :param machine_graph: machine graph
- :param routing_info: keys
- :param n_key_map: map for edge to n keys
- :param bit_field_builder_region: the region id for the bitfield builder
- :param master_pop_region_id: the region id for the master pop table
- :param synaptic_matrix_region_id: the region id for the synaptic matrix
- :param direct_matrix_region_id: the region id for the direct matrix
- :param bit_field_region_id: the region id for the bit-fields
- :param bit_field_key_map_region_id: the region id for the key map
- :param structural_dynamics_region_id: the region id for the structural
- :param has_structural_dynamics_region: \
- bool saying if the core has a has_structural_dynamics_region or not
- :rtype: None
+ :param ~data_specification.DataSpecificationGenerator spec: data spec writer
+ :param ~pacman.model.graphs.machine.MachineVertex machine_vertex:
+ machine vertex
+ :param ~pacman.model.graphs.machine.MachineGraph machine_graph:
+ machine graph
+ :param ~pacman.model.routing_info.RoutingInfo routing_info: keys
+ :param ~pacman.model.routing_info.AbstractMachinePartitionNKeysMap \
+ n_key_map:
+ map for edge to n keys
+ :param int bit_field_builder_region: the region id for the bitfield builder
+ :param int master_pop_region_id: the region id for the master pop table
+ :param int synaptic_matrix_region_id: the region id for the synaptic matrix
+ :param int direct_matrix_region_id: the region id for the direct matrix
+ :param int bit_field_region_id: the region id for the bit-fields
+ :param int bit_field_key_map_region_id: the region id for the key map
+ :param int structural_dynamics_region_id: the region id for the structural
+ :param bool has_structural_dynamics_region:
+ whether the core has a structural dynamics region
"""
spec.switch_write_focus(bit_field_builder_region)
diff --git a/spynnaker/pyNN/utilities/constants.py b/spynnaker/pyNN/utilities/constants.py
index bf63e59569b..d164f78d619 100644
--- a/spynnaker/pyNN/utilities/constants.py
+++ b/spynnaker/pyNN/utilities/constants.py
@@ -17,6 +17,9 @@
from spinn_front_end_common.utilities.constants import (
BYTES_PER_WORD, BYTES_PER_KB)
+#: The number of bits in a SpiNNaker machine word
+BITS_PER_WORD = 32
+
POSSION_SIGMA_SUMMATION_LIMIT = 3.0
BLOCK_INDEX_HEADER_WORDS = 3
diff --git a/spynnaker/pyNN/utilities/extracted_data.py b/spynnaker/pyNN/utilities/extracted_data.py
index 9252403c1fd..7ca817c9e9a 100644
--- a/spynnaker/pyNN/utilities/extracted_data.py
+++ b/spynnaker/pyNN/utilities/extracted_data.py
@@ -50,6 +50,5 @@ def set(self, projection, attribute, data):
:type attribute: list(int) or tuple(int) or None
:param ConnectionHolder data:
attribute data in a connection holder
- :rtype: None
"""
self.__data[projection][attribute] = data
diff --git a/spynnaker/pyNN/utilities/random_stats/abstract_random_stats.py b/spynnaker/pyNN/utilities/random_stats/abstract_random_stats.py
index 154e4b804ef..a93382bd329 100644
--- a/spynnaker/pyNN/utilities/random_stats/abstract_random_stats.py
+++ b/spynnaker/pyNN/utilities/random_stats/abstract_random_stats.py
@@ -50,12 +50,12 @@ def var(self, dist):
@abstractmethod
def high(self, dist):
- """ Return the high cutoff value of the distribution, or None if the\
+ """ Return the high cutoff value of the distribution, or `None` if the\
distribution is unbounded
"""
@abstractmethod
def low(self, dist):
- """ Return the low cutoff value of the distribution, or None if the\
+ """ Return the low cutoff value of the distribution, or `None` if the\
distribution is unbounded
"""
diff --git a/spynnaker/pyNN/utilities/struct.py b/spynnaker/pyNN/utilities/struct.py
index 567047fb80a..81bd4cf6687 100644
--- a/spynnaker/pyNN/utilities/struct.py
+++ b/spynnaker/pyNN/utilities/struct.py
@@ -65,7 +65,8 @@ def get_size_in_whole_words(self, array_size=1):
return (size_in_bytes + (BYTES_PER_WORD - 1)) // BYTES_PER_WORD
def get_data(self, values, offset=0, array_size=1):
- """ Get a numpy array of uint32 of data for the given values
+ """ Get a numpy array of uint32 of data for the given values. \
+ The array will be suitable for being written to SpiNNaker.
:param values:
A list of values with length the same size as the number of fields
diff --git a/spynnaker/pyNN/utilities/utility_calls.py b/spynnaker/pyNN/utilities/utility_calls.py
index 4cc881fffa8..53b3428b419 100644
--- a/spynnaker/pyNN/utilities/utility_calls.py
+++ b/spynnaker/pyNN/utilities/utility_calls.py
@@ -14,11 +14,10 @@
# along with this program. If not, see .
"""
-utility class containing simple helper methods
+Utility package containing simple helper functions.
"""
-import os
-import logging
import math
+import os
import numpy
from pyNN.random import RandomDistribution
from scipy.stats import binom
@@ -30,7 +29,6 @@
RandomStatsPoissonImpl, RandomStatsRandIntImpl, RandomStatsUniformImpl,
RandomStatsVonmisesImpl, RandomStatsBinomialImpl)
-
MAX_RATE = 2 ** 32 - 1 # To allow a unit32_t to be used to store the rate
STATS_BY_NAME = {
@@ -46,8 +44,6 @@
'randint': RandomStatsRandIntImpl(),
'vonmises': RandomStatsVonmisesImpl()}
-logger = logging.getLogger(__name__)
-
def check_directory_exists_and_create_if_not(filename):
""" Create a parent directory for a file if it doesn't exist
@@ -69,7 +65,6 @@ def convert_param_to_numpy(param, no_atoms):
:return: the converted param as an array of floats
:rtype: ~numpy.ndarray(float)
"""
-
# Deal with random distributions by generating values
if isinstance(param, RandomDistribution):
@@ -205,6 +200,8 @@ def get_probable_maximum_selected(
""" Get the likely maximum number of items that will be selected from a\
set of n_trials from a total set of n_total_trials\
with a probability of selection of selection_prob
+
+ :rtype: float
"""
prob = 1.0 - (chance / float(n_total_trials))
return binom.ppf(prob, n_trials, selection_prob)
@@ -213,6 +210,8 @@ def get_probable_maximum_selected(
def get_probability_within_range(dist, lower, upper):
""" Get the probability that a value will fall within the given range for\
a given RandomDistribution
+
+ :rtype: float
"""
stats = STATS_BY_NAME[dist.name]
return (stats.cdf(dist, upper) - stats.cdf(dist, lower))
@@ -221,6 +220,8 @@ def get_probability_within_range(dist, lower, upper):
def get_maximum_probable_value(dist, n_items, chance=(1.0 / 100.0)):
""" Get the likely maximum value of a RandomDistribution given a\
number of draws
+
+ :rtype: float
"""
stats = STATS_BY_NAME[dist.name]
prob = 1.0 - (chance / float(n_items))
@@ -230,6 +231,8 @@ def get_maximum_probable_value(dist, n_items, chance=(1.0 / 100.0)):
def get_minimum_probable_value(dist, n_items, chance=(1.0 / 100.0)):
""" Get the likely minimum value of a RandomDistribution given a\
number of draws
+
+ :rtype: float
"""
stats = STATS_BY_NAME[dist.name]
prob = chance / float(n_items)
@@ -238,6 +241,8 @@ def get_minimum_probable_value(dist, n_items, chance=(1.0 / 100.0)):
def get_mean(dist):
""" Get the mean of a RandomDistribution
+
+ :rtype: float
"""
stats = STATS_BY_NAME[dist.name]
return stats.mean(dist)
@@ -245,6 +250,8 @@ def get_mean(dist):
def get_standard_deviation(dist):
""" Get the standard deviation of a RandomDistribution
+
+ :rtype: float
"""
stats = STATS_BY_NAME[dist.name]
return stats.std(dist)
@@ -252,6 +259,8 @@ def get_standard_deviation(dist):
def get_variance(dist):
""" Get the variance of a RandomDistribution
+
+ :rtype: float
"""
stats = STATS_BY_NAME[dist.name]
return stats.var(dist)
@@ -261,6 +270,8 @@ def high(dist):
""" Gets the high or max boundary value for this distribution
Could return None
+
+ :rtype: float or None
"""
stats = STATS_BY_NAME[dist.name]
return stats.high(dist)
@@ -270,6 +281,8 @@ def low(dist):
""" Gets the high or min boundary value for this distribution
Could return None
+
+ :rtype: float or None
"""
stats = STATS_BY_NAME[dist.name]
return stats.low(dist)
@@ -287,8 +300,17 @@ def validate_mars_kiss_64_seed(seed):
return seed
+def round_up(value):
+ """ Rounds a value up to the nearest integer.
+
+ :param float value:
+ :rtype: int
+ """
+ return int(math.ceil(value))
+
+
def get_n_bits(n_values):
- """ Determine how many bits are required for the given number of values
+ """ Determine how many bits are required for the given number of values.
:param int n_values: the number of values (starting at 0)
:return: the number of bits required to express that many values
@@ -298,4 +320,13 @@ def get_n_bits(n_values):
return 0
if n_values == 1:
return 1
- return int(math.ceil(math.log(n_values, 2)))
+ return (n_values - 1).bit_length()
+
+
+def ceildiv(x, y):
+ """ Divide `x` by `y` and round *up*.
+
+ :rtype: int
+ """
+ d, m = divmod(x, y)
+ return int(d) + (m != 0)
diff --git a/unittests/mocks.py b/unittests/mocks.py
index 299d83d3179..230e347b587 100644
--- a/unittests/mocks.py
+++ b/unittests/mocks.py
@@ -15,7 +15,8 @@
import configparser
import numpy
-from spinn_front_end_common.utilities import globals_variables
+from spinn_front_end_common.utilities.globals_variables import (
+ set_failed_state, set_simulator)
from spynnaker.pyNN.utilities.spynnaker_failed_state import (
SpynnakerFailedState)
from builtins import property
@@ -132,8 +133,8 @@ def id_counter(self, value):
@classmethod
def setup(cls):
simulator = MockSimulator()
- globals_variables.set_failed_state(SpynnakerFailedState())
- globals_variables.set_simulator(simulator)
+ set_failed_state(SpynnakerFailedState())
+ set_simulator(simulator)
return simulator
@property