Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 20 additions & 6 deletions spynnaker/pyNN/external_devices/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -207,6 +207,7 @@ def EthernetControlPopulation(
local_host: Optional[str] = None, local_port: Optional[int] = None,
database_notify_port_num: Optional[int] = None,
database_ack_port_num: Optional[int] = None,
n_synapse_cores: Optional[int] = None,
**additional_kwargs: Dict[str, Any]) -> Population:
# pylint: disable=invalid-name
"""
Expand All @@ -227,8 +228,16 @@ def EthernetControlPopulation(
:param database_notify_port_num:
The optional port to which notifications from the database
notification protocol are to be sent
:param n_synapse_cores:
Model.create_vertex parameter.
Likely: The number of synapse cores; 0 to force combined cores,
or None to allow the system to choose
:param additional_kwargs:
A nicer way of allowing additional things to the Population
Additional parameters to pass to the Model.create_vertex function.
See the Model's create_vertex method for more details.
These will be ignored if the Model does not accept this parameter.
These will raise an Exception if a Vertex is passed in
There may be additional parameters not listed in this init.
:return:
A pyNN Population which can be used as the target of a Projection.

Expand All @@ -237,9 +246,14 @@ def EthernetControlPopulation(
Projection, but it might not send spikes.
:raises TypeError: If an invalid model class is used.
"""
additional: Dict[str, Any] = dict()
if additional_kwargs:
additional.update(additional_kwargs)
if n_synapse_cores is not None:
additional['n_synapse_cores'] = n_synapse_cores
# pylint: disable=global-statement
population = Population(n_neurons, model, label=label,
**additional_kwargs)
additional_parameters=additional)
vertex, aec, vertex_label = __vtx(population)
translator = aec.get_message_translator()
live_packet_gather_label = "EthernetControlReceiver"
Expand Down Expand Up @@ -306,13 +320,13 @@ def EthernetSensorPopulation(
if not isinstance(device, AbstractEthernetSensor):
raise TypeError(
"Device must be an instance of AbstractEthernetSensor")
injector_params = dict(device.get_injector_parameters())

additional_parameters = dict(device.get_injector_parameters())
if additional_kwargs:
additional_parameters.update(additional_kwargs)
population = Population(
device.get_n_neurons(), SpikeInjector(notify=False),
label=device.get_injector_label(),
additional_parameters=injector_params,
**additional_kwargs)
additional_parameters=additional_parameters)
if isinstance(device, AbstractSendMeMulticastCommandsVertex):
cmd_conn = EthernetCommandConnection(
device.get_translator(), [device], local_host,
Expand Down
70 changes: 68 additions & 2 deletions spynnaker/pyNN/models/populations/population.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,8 @@
from spinn_utilities.logger_utils import warn_once
from spinn_utilities.overrides import overrides

from pacman.model.partitioner_splitters import AbstractSplitterCommon

from spinn_front_end_common.utilities.exceptions import ConfigurationException

from spynnaker.pyNN.data import SpynnakerDataView
Expand Down Expand Up @@ -84,6 +86,15 @@ def __init__(
structure: Optional[BaseStructure] = None,
initial_values: Optional[Dict[str, float]] = None,
label: Optional[str] = None,
*, max_rate: Optional[float] = None,
n_colour_bits: Optional[int] = None,
n_synapse_cores: Optional[int] = None,
neurons_per_core: Optional[Union[int, Tuple[int, ...]]] = None,
port: Optional[int] = None,
reserve_reverse_ip_tag: Optional[bool] = None,
seed: Optional[int] = None,
splitter: Optional[AbstractSplitterCommon] = None,
virtual_key: Optional[int] = None,
additional_parameters: Optional[_ParamDict] = None,
**additional_kwargs: _ParamDict):
"""
Expand All @@ -95,17 +106,72 @@ def __init__(
:param structure:
:param initial_values: Initial values of state variables
:param label: A label for the population
:param max_rate:
Model.create_vertex parameter.
Likely:
The maximum number of spikes for any neuron at any timestamp
:param n_colour_bits:
Model.create_vertex parameter.
Likely: The number of bits to use for colour
:param n_synapse_cores:
Model.create_vertex parameter.
Likely: The number of synapse cores; 0 to force combined cores,
or None to allow the system to choose
:param neurons_per_core:
Model.create_vertex parameter.
Likely: A ceiling on
the number of neurons that can be placed on a single core.
:param port:
Model.create_vertex parameter.
Likely: The live input port the vertex receives spikes on
:param reserve_reverse_ip_tag:
Model.create_vertex parameter.
Likely: Extra flag for input without a reserved port
:param seed:
Model.create_vertex parameter.
Likely: The Population seed,
used to ensure the same random generation on each run.
:param splitter:
Model.create_vertex parameter.
Likely: splitter from application vertices to machine vertices
:param virtual_key:
Model.create_vertex parameter.
Likely:
The virtual_key of the population to identify the population.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this unfortunately adds to the confusion; adding these parameters implies all models accept them but in reality they don't. I would prefer that this is left to the model itself to document therefore.

A note here is that PyNN itself doesn't actually accept additional parameters, so what we do with this is our own; we could, in fact, force that all parameters are something that the vertex accepts.

Additional note is that these are not the same as the cell_params (which are, in fact, deprecated). The cell_params are arguments passed when creating the model, the additional_args are arguments passed when creating the vertex, and model is also one of those arguments. In our case, we accept a vertex in place of a model, so this could be resolved that way instead, but it would then start also to look odd when working with standard models, as you would then have something like p.Population(n_neurons, p.PopulationVertex(..., model=p.IF_curr_exp(...))).

:param additional_parameters:
Additional parameters to pass to the vertex creation function.
Alternative way of entering Model.create_vertex parameter.
Ignored if also provided as a named parameter.
:param additional_kwargs:
A nicer way of allowing additional things
Additional Model.create_vertex parameters.
See the Model's create_vertex method for more details.
create_vertex parameters will be ignored if
the Model does not accept this parameter,
or raise an Exception if a Vertex is passed in
Comment on lines +146 to +149

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I actually think that we should raise an exception in both cases, especially if this is the only use of these additional args.

"""
# Deal with the kwargs!
additional: _ParamDict = dict()
if additional_parameters is not None:
additional.update(additional_parameters)
if additional_kwargs:
additional.update(additional_kwargs)
if max_rate is not None:
additional['max_rate'] = max_rate
if n_colour_bits is not None:
additional['n_colour_bits'] = n_colour_bits
if n_synapse_cores is not None:
additional['n_synapse_cores'] = n_synapse_cores
if neurons_per_core is not None:
additional['neurons_per_core'] = neurons_per_core
if port is not None:
additional['port'] = port
if reserve_reverse_ip_tag is not None:
additional['reserve_reverse_ip_tag'] = reserve_reverse_ip_tag
if seed is not None:
additional['seed'] = seed
if splitter is not None:
additional['splitter'] = splitter
if virtual_key is not None:
additional['virtual_key'] = virtual_key

# build our initial objects
self.__celltype: AbstractPyNNModel
Expand Down
Loading