rig.machine_control: Machine Control APIs

Rig provides various high-level APIs for communicating with and controlling SpiNNaker machines. New users are encouraged to start by working through the introductory tutorials:

MachineController: SpiNNaker Control API

class rig.machine_control.MachineController(initial_host, scp_port=17893, boot_port=54321, n_tries=5, timeout=0.5, structs=None, initial_context={'app_id': 66})[source]

A high-level interface for controlling a SpiNNaker system.

This class is essentially a wrapper around key functions provided by the SCP protocol which aims to straight-forwardly handle many of the difficult details and corner cases to ensure easy, efficient and reliable communication with and control of a SpiNNaker machine. A tutorial is available for new users.

Key features at a glance:

  • Machine booting
  • Probing for available resources
  • (Efficient & reliable) loading of applications
  • Application monitoring and control
  • Allocation and loading of routing tables
  • Allocation and loading of memory
  • An optional file-like interface to memory blocks
  • Setting up IPTags
  • Easy-to-use blocking API

Coming soon:

  • (Additional) ‘advanced’ non-blocking, parallel I/O interface
  • (Automagically) handling multiple connections simultaneously

This class does not provide any methods for sending and receiving arbitrary SDP packets to and from applications. For this you should use sockets and the rig.machine_control.packets library (for which a tutorial is also available).

This class features a context system which allows commonly required arguments to be specified for a whole block of code using a ‘with’ statement, for example:

cm = MachineController("spinnaker")

# Commands should refer to chip (2, 3)
with cm(x=2, y=3):
    three_kb_of_joy = cm.sdram_alloc(3*1024)
    cm.write(three_kb_of_joy, b"joy" * 1024)
    core_one_status = cm.get_processor_status(1)
__init__(initial_host, scp_port=17893, boot_port=54321, n_tries=5, timeout=0.5, structs=None, initial_context={'app_id': 66})[source]

Create a new controller for a SpiNNaker machine.

Parameters:
initial_host : string

Hostname or IP address of the SpiNNaker chip to connect to. If the board has not yet been booted, this will be used to boot the machine.

scp_port : int

Port number for SCP connections.

boot_port : int

Port number for booting the board.

n_tries : int

Number of SDP packet retransmission attempts.

timeout : float

Timeout in seconds before an SCP response is assumed lost and the request is retransmitted.

structs : dict or None

A dictionary of struct data defining the memory locations of important values in SARK as produced by rig.machine_control.struct_file.read_struct_file. If None, the default struct file will be used.

initial_context : {argument: value}

Default argument values to pass to methods in this class. By default this just specifies a default App-ID.

__call__(**context_args)[source]

For use with with: set default argument values.

E.g:

with controller(x=3, y=4):
    # All commands in this block now communicate with chip (3, 4)
scp_data_length

The maximum SCP data field length supported by the machine (bytes).

scp_window_size

The maximum number of packets that can be sent to a SpiNNaker board without receiving any acknowledgement packets.

root_chip

The coordinates (x, y) of the chip used to boot the machine.

send_scp(*args, y=Required, x=Required, p=Required, **kwargs)[source]

Transmit an SCP Packet and return the response.

This function is a thin wrapper around rig.machine_control.scp_connection.SCPConnection.send_scp().

This function will attempt to use the SCP connection nearest the destination of the SCP command if multiple connections have been discovered using discover_connections().

Parameters:
x : int
y : int
p : int
*args
**kwargs
boot(width=None, height=None, only_if_needed=True, check_booted=True, **boot_kwargs)[source]

Boot a SpiNNaker machine.

The system will be booted from the Ethernet connected chip whose hostname was given as the argument to the MachineController. With the default arguments this method will only boot systems which have not already been booted and will wait until machine is completely booted (and raise a SpiNNakerBootError on failure).

This method uses rig.machine_control.boot.boot() to send boot commands to the machine and update the struct files contained within this object according to those used during boot.

Warning

Booting the system over the open internet is likely to fail due to the port number being blocked by most ISPs and UDP not being reliable. A proxy such as spinnaker_proxy may be useful in this situation.

Parameters:
width, height : Deprecated

Deprecated. In older versions of SC&MP, it was necessary to indicate the size of the machine being booted. These parameters are now ignored and setting them will produce a deprecation warning.

scamp_binary : filename or None

Filename of the binary to boot the machine with or None to use the SC&MP binary bundled with Rig.

sark_struct : filename or None

The ‘sark.struct’ file which defines the datastructures or None to use the one bundled with Rig.

boot_delay : float

Number of seconds to pause between sending boot data packets.

post_boot_delay : float

Number of seconds to wait after sending last piece of boot data to give SC&MP time to re-initialise the Ethernet interface.

only_if_needed : bool

If only_if_needed is True (the default), this method checks to see if the machine is already booted and only attempts to boot the machine if neccessary.

If only_if_needed is False, the boot commands will be sent to the target machine without checking if it is already booted or not.

Warning

If the machine has already been booted, sending the boot commands again will not ‘reboot’ the machine with the newly supplied boot image, even if only_if_needed is False.

check_booted : bool

If check_booted is True this method waits for the machine to be fully booted before returning. If False, this check is skipped and the function returns as soon as the machine’s Ethernet interface is likely to be up (but not necessarily before booting has completed).

sv_overrides : {name: value, …}

Additional arguments used to override the default values in the ‘sv’ struct defined in the struct file.

Returns:
bool

Returns True if the machine was sent boot commands, False if the machine was already booted.

Raises:
rig.machine_control.machine_controller.SpiNNakerBootError

Raised when check_booted is True and the boot process was unable to boot the machine. Also raised when only_if_needed is True and the remote host is a BMP.

Notes

The constants rig.machine_control.boot.spinX_boot_options can be used to specify boot parameters, for example:

controller.boot(**spin3_boot_options)

This is neccessary on boards such as SpiNN-3 boards if the more than LED 0 are required by an application since by default, only LED 0 is enabled.

discover_connections(x=255, y=255)[source]

Attempt to discover all available Ethernet connections to a machine.

After calling this method, MachineController will attempt to communicate via the Ethernet connection on the same board as the destination chip for all commands.

If called multiple times, existing connections will be retained in preference to new ones.

Note

The system must be booted for this command to succeed.

Note

Currently, only systems comprised of multiple Ethernet-connected SpiNN-5 boards are supported.

Parameters:
x : int
y : int

(Optional) The coordinates of the chip to initially use to query the system for the set of live chips.

Returns:
int

The number of new connections established.

application(app_id)[source]

Update the context to use the given application ID and stop the application when done.

For example:

with cn.application(54):
    # All commands in this block will use app_id=54.
    # On leaving the block `cn.send_signal("stop", 54)` is
    # automatically called.
get_software_version(x=255, y=255, processor=0)[source]

Get the software version for a given SpiNNaker core.

Returns:
:py:class:`.CoreInfo`

Information about the software running on a core.

get_ip_address(x, y)[source]

Get the IP address of a particular SpiNNaker chip’s Ethernet link.

Returns:
str or None

The IPv4 address (as a string) of the chip’s Ethernet link or None if the chip does not have an Ethernet connection or the link is currently down.

write(address, data, x, y, p=0)[source]

Write a bytestring to an address in memory.

It is strongly encouraged to only read and write to blocks of memory allocated using sdram_alloc(). Additionally, sdram_alloc_as_filelike() can be used to safely wrap read/write access to memory with a file-like interface and prevent accidental access to areas outside the allocated block.

Parameters:
address : int

The address at which to start writing the data. Addresses are given within the address space of a SpiNNaker core. See the SpiNNaker datasheet for more information.

data : bytes

Data to write into memory. Writes are automatically broken into a sequence of SCP write commands.

read(address, length_bytes, x, y, p=0)[source]

Read a bytestring from an address in memory.

Parameters:
address : int

The address at which to start reading the data.

length_bytes : int

The number of bytes to read from memory. Large reads are transparently broken into multiple SCP read commands.

Returns:
:py:class:`bytes`

The data is read back from memory as a bytestring.

Write a bytestring to an address in memory on a neigbouring chip.

Warning

This function is intended for low-level debug use only and is not optimised for performance nor intended for more general use.

This method instructs a monitor processor to send ‘POKE’ nearest-neighbour packets to a neighbouring chip. These packets are handled directly by the SpiNNaker router in the neighbouring chip, potentially allowing advanced debug or recovery of a chip rendered otherwise unreachable.

Parameters:
address : int

The address at which to start writing the data. Only addresses in the system-wide address map may be accessed. Addresses must be word aligned.

data : bytes

Data to write into memory. Must be a whole number of words in length. Large writes are automatically broken into a sequence of SCP link-write commands.

x : int
y : int

The coordinates of the chip from which the command will be sent, not the coordinates of the chip on which the write will be performed.

link : rig.links.Links

The link down which the write should be sent.

Read a bytestring from an address in memory on a neigbouring chip.

Warning

This function is intended for low-level debug use only and is not optimised for performance nor intended for more general use.

This method instructs a monitor processor to send ‘PEEK’ nearest-neighbour packets to a neighbouring chip. These packets are handled directly by the SpiNNaker router in the neighbouring chip, potentially allowing advanced debug or recovery of a chip rendered otherwise unreachable.

Parameters:
address : int

The address at which to start reading the data. Only addresses in the system-wide address map may be accessed. Addresses must be word aligned.

length_bytes : int

The number of bytes to read from memory. Must be a multiple of four (i.e. a whole number of words). Large reads are transparently broken into multiple SCP link-read commands.

x : int
y : int

The coordinates of the chip from which the command will be sent, not the coordinates of the chip on which the read will be performed.

link : rig.links.Links

The link down which the read should be sent.

Returns:
:py:class:`bytes`

The data is read back from memory as a bytestring.

read_struct_field(struct_name, field_name, x, y, p=0)[source]

Read the value out of a struct maintained by SARK.

This method is particularly useful for reading fields from the sv struct which, for example, holds information about system status. See sark.h for details.

Parameters:
struct_name : string

Name of the struct to read from, e.g., “sv”

field_name : string

Name of the field to read, e.g., “eth_addr”

Returns:
value

The value returned is unpacked given the struct specification.

Currently arrays are returned as tuples, e.g.:

# Returns a 20-tuple.
cn.read_struct_field("sv", "status_map")

# Fails
cn.read_struct_field("sv", "status_map[1]")
write_struct_field(struct_name, field_name, values, x, y, p=0)[source]

Write a value into a struct.

This method is particularly useful for writing values into the sv struct which contains some configuration data. See sark.h for details.

Parameters:
struct_name : string

Name of the struct to write to, e.g., “sv”

field_name : string

Name of the field to write, e.g., “random”

values :

Value(s) to be written into the field.

.. warning::

Fields which are arrays must currently be written in their entirety.

read_vcpu_struct_field(field_name, x, y, p)[source]

Read a value out of the VCPU struct for a specific core.

Similar to read_struct_field() except this method accesses the individual VCPU struct for to each core and contains application runtime status.

Parameters:
field_name : string

Name of the field to read from the struct (e.g. “cpu_state”)

Returns:
value

A value of the type contained in the specified struct field.

write_vcpu_struct_field(field_name, value, x, y, p)[source]

Write a value to the VCPU struct for a specific core.

Parameters:
field_name : string

Name of the field to write (e.g. “user0”)

value :

Value to write to this field.

get_processor_status(p, x, y)[source]

Get the status of a given core and the application executing on it.

Returns:
:py:class:`.ProcessorStatus`

Representation of the current state of the processor.

get_iobuf(p, x, y)[source]

Read the messages io_printf’d into the IOBUF buffer on a specified core.

See also: get_iobuf_bytes() which returns the undecoded raw bytes in the IOBUF. Useful if the IOBUF contains non-text or non-UTF-8 encoded text.

Returns:
str

The string in the IOBUF, decoded from UTF-8.

get_iobuf_bytes(p, x, y)[source]

Read raw bytes io_printf’d into the IOBUF buffer on a specified core.

This may be useful when the data contained in the IOBUF is not UTF-8 encoded text.

See also: get_iobuf() which returns a decoded string rather than raw bytes.

Returns:
bytes

The raw, undecoded string data in the buffer.

get_router_diagnostics(x, y)[source]

Get the values of the router diagnostic counters.

Returns:
:py:class:`~.RouterDiagnostics`

Description of the state of the counters.

iptag_set(iptag, addr, port, x, y)[source]

Set the value of an IPTag.

Forward SDP packets with the specified IP tag sent by a SpiNNaker application to a given external IP address.

A tutorial example of the use of IP Tags to send and receive SDP packets to and from applications is also available.

Parameters:
iptag : int

Index of the IPTag to set

addr : string

IP address or hostname that the IPTag should point at.

port : int

UDP port that the IPTag should direct packets to.

iptag_get(iptag, x, y)[source]

Get the value of an IPTag.

Parameters:
iptag : int

Index of the IPTag to get

Returns:
:py:class:`.IPTag`

The IPTag returned from SpiNNaker.

iptag_clear(iptag, x, y)[source]

Clear an IPTag.

Parameters:
iptag : int

Index of the IPTag to clear.

set_led(led, action=None, x=Required, y=Required)[source]

Set or toggle the state of an LED.

Note

By default, SARK takes control of LED 0 and so changes to this LED will not typically last long enough to be useful.

Parameters:
led : int or iterable

Number of the LED or an iterable of LEDs to set the state of (0-3)

action : bool or None

State to set the LED to. True for on, False for off, None to toggle (default).

fill(address, data, size, x, y, p)[source]

Fill a region of memory with the specified byte.

Parameters:
data : int

Data with which to fill memory. If address and size are word aligned then data is assumed to be a word; otherwise it is assumed to be a byte.

Notes

If the address and size are word aligned then a fast fill method will be used, otherwise a much slower write will be incurred.

sdram_alloc(size, tag=0, x=Required, y=Required, app_id=Required, clear=False)[source]

Allocate a region of SDRAM for an application.

Requests SARK to allocate a block of SDRAM for an application and raises a SpiNNakerMemoryError on failure. This allocation will be freed when the application is stopped.

Parameters:
size : int

Number of bytes to attempt to allocate in SDRAM.

tag : int

8-bit tag that can be looked up by a SpiNNaker application to discover the address of the allocated block. The tag must be unique for this app_id on this chip. Attempting to allocate two blocks on the same chip and for the same app_id will fail. If 0 (the default) then no tag is applied.

For example, if some SDRAM is allocated with tag=12, a SpiNNaker application can later discover the address using:

void *allocated_data = sark_tag_ptr(12, 0);

A common convention is to allocate one block of SDRAM per application core and give each allocation the associated core number as its tag. This way the underlying SpiNNaker applications can simply call:

void *allocated_data = sark_tag_ptr(sark_core_id(), 0);
clear : bool

If True the requested memory will be filled with zeros before the pointer is returned. If False (the default) the memory will be left as-is.

Returns:
int

Address of the start of the region.

The allocated SDRAM remains valid until either the ‘stop’ signal is sent to the application ID associated with the allocation or sdram_free() is called on the address returned.

Raises:
rig.machine_control.machine_controller.SpiNNakerMemoryError

If the memory cannot be allocated, the tag is already taken or it is invalid.

sdram_alloc_as_filelike(size, tag=0, x=Required, y=Required, app_id=Required, clear=False)[source]

Like sdram_alloc() but returns a file-like object which allows safe reading and writing to the block that is allocated.

Returns:
:py:class:`.MemoryIO`

File-like object which allows accessing the newly allocated region of memory. For example:

>>> # Read, write and seek through the allocated memory just
>>> # like a file
>>> mem = mc.sdram_alloc_as_filelike(12)  
>>> mem.write(b"Hello, world")            
12
>>> mem.seek(0)                           
>>> mem.read(5)                           
b"Hello"
>>> mem.read(7)                           
b", world"

>>> # Reads and writes are truncated to the allocated region,
>>> # preventing accidental clobbering/access of memory.
>>> mem.seek(0)                           
>>> mem.write(b"How are you today?")      
12
>>> mem.seek(0)                           
>>> mem.read(100)                         
b"How are you "

See the MemoryIO class for details of other features of these file-like views of SpiNNaker’s memory.

Raises:
rig.machine_control.machine_controller.SpiNNakerMemoryError

If the memory cannot be allocated, or the tag is already taken or invalid.

sdram_free(ptr, x=Required, y=Required)[source]

Free an allocated block of memory in SDRAM.

Note

All unfreed SDRAM allocations associated with an application are automatically freed when the ‘stop’ signal is sent (e.g. after leaving a application() block). As such, this method is only useful when specific blocks are to be freed while retaining others.

Parameters:
ptr : int

Address of the block of memory to free.

flood_fill_aplx(*args, app_id=Required, wait=True, **kwargs)[source]

Unreliably flood-fill APLX to a set of application cores.

Note

Most users should use the load_application() wrapper around this method which guarantees successful loading.

This method can be called in either of the following ways:

flood_fill_aplx("/path/to/app.aplx", {(x, y): {core, ...}, ...})
flood_fill_aplx({"/path/to/app.aplx": {(x, y): {core, ...}, ...},
                 ...})

Note that the latter format is the same format produced by build_application_map().

Warning

The loading process is likely, but not guaranteed, to succeed. This is because the flood-fill packets used during loading are not guaranteed to arrive. The effect is that some chips may not receive the complete application binary and will silently ignore the application loading request.

As a result, the user is responsible for checking that each core was successfully loaded with the correct binary. At present, the two recommended approaches to this are:

  • If the wait argument is given then the user should check that the correct number of application binaries reach the initial barrier (i.e., the wait state). If the number does not match the expected number of loaded cores the next approach must be used:
  • The user can check the process list of each chip to ensure the application was loaded into the correct set of cores. See read_vcpu_struct_field().
Parameters:
app_id : int
wait : bool (Default: True)

Should the application await the AppSignal.start signal after it has been loaded?

load_application(*args, n_tries=2, app_start_delay=0.1, app_id=Required, wait=False, **kwargs)[source]

Load an application to a set of application cores.

This method guarantees that once it returns, all required cores will have been loaded. If this is not possible after a small number of attempts, a SpiNNakerLoadingError will be raised.

This method can be called in either of the following ways:

load_application("/path/to/app.aplx", {(x, y): {core, ...}, ...})
load_application({"/path/to/app.aplx": {(x, y): {core, ...}, ...},
                  ...})

Note that the latter format is the same format produced by build_application_map().

Parameters:
app_id : int
wait : bool

Leave the application in a wait state after successfully loading it.

n_tries : int

Number attempts to make to load the application.

app_start_delay : float

Time to pause (in seconds) after loading to ensure that the application successfully reaches the wait state before checking for success.

use_count : bool

If True (the default) then the targets dictionary will be assumed to represent _all_ the cores that will be loaded and a faster method to determine whether all applications have been loaded correctly will be used. If False a fallback method will be used.

Raises:
rig.machine_control.machine_controller.SpiNNakerLoadingError

This exception is raised after some cores failed to load after n_tries attempts.

send_signal(signal, app_id)[source]

Transmit a signal to applications.

Warning

In current implementations of SARK, signals are highly likely to arrive but this is not guaranteed (especially when the system’s network is heavily utilised). Users should treat this mechanism with caution. Future versions of SARK may resolve this issue.

Parameters:
signal : string or AppSignal

Signal to transmit. This may be either an entry of the AppSignal enum or, for convenience, the name of a signal (defined in AppSignal) as a string.

count_cores_in_state(state, app_id)[source]

Count the number of cores in a given state.

Warning

In current implementations of SARK, signals (which are used to determine the state of cores) are highly likely to arrive but this is not guaranteed (especially when the system’s network is heavily utilised). Users should treat this mechanism with caution. Future versions of SARK may resolve this issue.

Parameters:
state : string or AppState or

iterable

Count the number of cores currently in this state. This may be either an entry of the AppState enum or, for convenience, the name of a state (defined in AppState) as a string or an iterable of these, in which case the total count will be returned.

wait_for_cores_to_reach_state(state, count, app_id, poll_interval=0.1, timeout=None)[source]

Block until the specified number of cores reach the specified state.

This is a simple utility-wrapper around the count_cores_in_state() method which polls the machine until (at least) the supplied number of cores has reached the specified state.

Warning

In current implementations of SARK, signals (which are used to determine the state of cores) are highly likely to arrive but this is not guaranteed (especially when the system’s network is heavily utilised). As a result, in uncommon-but-possible circumstances, this function may never exit. Users should treat this function with caution. Future versions of SARK may resolve this issue.

Parameters:
state : string or AppState

The state to wait for cores to enter. This may be either an entry of the AppState enum or, for convenience, the name of a state (defined in AppState) as a string.

count : int

The (minimum) number of cores reach the specified state before this method terminates.

poll_interval : float

Number of seconds between state counting requests sent to the machine.

timeout : float or Null

Maximum number of seconds which may elapse before giving up. If None, keep trying forever.

Returns:
int

The number of cores in the given state (which will be less than the number required if the method timed out).

load_routing_tables(routing_tables, app_id)[source]

Allocate space for an load multicast routing tables.

The routing table entries will be removed automatically when the associated application is stopped.

Parameters:
routing_tables : {(x, y): [RoutingTableEntry (…), …], …}

Map of chip co-ordinates to routing table entries, as produced, for example by routing_tree_to_tables() and minimise_tables().

Raises:
rig.machine_control.machine_controller.SpiNNakerRouterError

If it is not possible to allocate sufficient routing table entries.

load_routing_table_entries(entries, x, y, app_id)[source]

Allocate space for and load multicast routing table entries into the router of a SpiNNaker chip.

Note

This method only loads routing table entries for a single chip. Most users should use load_routing_tables() which loads routing tables to multiple chips.

Parameters:
entries : [RoutingTableEntry, …]

List of rig.routing_table.RoutingTableEntrys.

Raises:
rig.machine_control.machine_controller.SpiNNakerRouterError

If it is not possible to allocate sufficient routing table entries.

get_routing_table_entries(x, y)[source]

Dump the multicast routing table of a given chip.

Returns:
[(:py:class:`~rig.routing_table.RoutingTableEntry`, app_id, core) or None, …]

Ordered list of routing table entries with app_ids and core numbers.

clear_routing_table_entries(x, y, app_id)[source]

Clear the routing table entries associated with a given application.

get_p2p_routing_table(x, y)[source]

Dump the contents of a chip’s P2P routing table.

This method can be indirectly used to get a list of functioning chips.

Note

This method only returns the entries for chips within the bounds of the system. E.g. if booted with 8x8 only entries for these 8x8 chips will be returned.

Returns:
{(x, y): :py:class:`~rig.machine_control.consts.P2PTableEntry`, …}
get_chip_info(x, y)[source]

Get general information about the resources available on a chip.

Returns:
:py:class:`.ChipInfo`

A named tuple indicating the number of working cores, the states of all working cores, the set of working links and the size of the largest free block in SDRAM and SRAM.

Return the set of links reported as working.

This command tests each of the links leaving a chip by sending a PEEK nearest-neighbour packet down each link to verify that the remote device is a SpiNNaker chip. If no reply is received via a given link or if the remote device is not a SpiNNaker chip, the link is reported as dead.

See also: get_chip_info().

Returns:
set([:py:class:`rig.links.Links`, …])
get_num_working_cores(x, y)[source]

Return the number of working cores, including the monitor.

See also: get_chip_info().

get_system_info(x=255, y=255)[source]

Discover the integrity and resource availability of a whole SpiNNaker system.

This command performs get_chip_info() on all working chips in the system returning an enhanced dict (SystemInfo) containing a look-up from chip coordinate to ChipInfo. In addition to standard dictionary functionality, SystemInfo provides a number of convenience methods, which allow convenient iteration over various aspects of the information stored.

Note

This method replaces the deprecated get_machine() method. To build a Machine for place-and-route purposes, the rig.place_and_route.utils.build_machine() utility function may be used with get_system_info() like so:

>> from rig.place_and_route.utils import build_machine
>> sys_info = mc.get_system_info()
>> machine = build_machine(sys_info)
Parameters:
x : int
y : int

The coordinates of the chip from which system exploration should begin, by default (255, 255). Most users will not need to change these parameters.

Returns:
:py:class:`.SystemInfo`

An enhanced dict object {(x, y): ChipInfo, …} with a number of utility methods for accessing higher-level system information.

get_machine(x=255, y=255, default_num_cores=18)[source]

Deprecated. Probe the machine to discover which cores and links are working.

Warning

This method has been deprecated in favour of get_system_info() for getting information about the general resources available in a SpiNNaker machine. This method may be removed in the future.

To build a Machine for place-and-route purposes, the rig.place_and_route.utils.build_machine() utility function may be used with get_system_info() like so:

>> from rig.place_and_route import build_machine
>> sys_info = mc.get_system_info()
>> machine = build_machine(sys_info)

This method also historically used the size of the SDRAM and SRAM heaps to set the respective resource values in the Machine. get_machine() since changed to reporting the size of the largest free block in the SDRAM and SRAM heaps on each chip. Most applications should not be negatively impacted by this change.

Note

The chip (x, y) supplied is the one where the search for working chips begins. Selecting anything other than (255, 255), the default, may be useful when debugging very broken machines.

Parameters:
default_num_cores : int

This argument is ignored.

Returns:
:py:class:`~rig.place_and_route.Machine`

This Machine will include all cores reported as working by the system software with the following resources defined:

Cores

Number of working cores on each chip (including the monitor core, any cores already running applications and idle cores).

SDRAM

The size of the largest free block of SDRAM on the heap. This gives a conservative measure of how much SDRAM is free on a given chip (which will underestimate availability if the system’s memory is highly fragmented.

SRAM

The size of the largest free block of SRAM on the heap. This gives a conservative measure of how much SRAM is free on a given chip (which will underestimate availability if the system’s memory is highly fragmented.

class rig.machine_control.machine_controller.MemoryIO(machine_controller, x, y, start_address, end_address)[source]

A file-like view into a subspace of the memory-space of a chip.

A MemoryIO is sliceable to allow construction of new, more specific, file-like views of memory.

For example:

>>> # Read, write and seek through memory as if it was a file
>>> f = MemoryIO(mc, 0, 1, 0x67800000, 0x6780000c)  
>>> f.write(b"Hello, world")                        
12
>>> f.seek(0)                                       
>>> f.read()                                        
b"Hello, world"

>>> # Slice the MemoryIO to produce a new MemoryIO which can only
>>> # access a subset of the memory.
>>> g = f[0:5]                                      
>>> g.read()                                        
b"Hello"
>>> g.seek(0)                                       
>>> g.write(b"Howdy, partner!")                     
5
>>> f.seek(0)                                       
>>> f.read()                                        
b"Howdy, world"
free()[source]

Free the memory referred to by the file-like, any subsequent operations on this file-like or slices of it will fail.

address

Get the current hardware memory address (indexed from 0x00000000).

close()[source]

Flush and close the file-like.

flush()[source]

Flush any buffered writes.

This must be called to ensure that all writes to SpiNNaker made using this file-like object (and its siblings, if any) are completed.

Note

This method is included only for compatibility reasons and does nothing. Writes are not currently buffered.

read(n_bytes=-1)[source]

Read a number of bytes from the memory.

Note

Reads beyond the specified memory range will be truncated.

Note

Produces a TruncationWarning if fewer bytes are read than requested. These warnings can be converted into exceptions using warnings.simplefilter():

>>> import warnings
>>> from rig.machine_control.machine_controller \
...     import TruncationWarning
>>> warnings.simplefilter('error', TruncationWarning)
Parameters:
n_bytes : int

A number of bytes to read. If the number of bytes is negative or omitted then read all data until the end of memory region.

Returns:
:py:class:`bytes`

Data read from SpiNNaker as a bytestring.

seek(n_bytes, from_what=0)[source]

Seek to a new position in the memory region.

Parameters:
n_bytes : int

Number of bytes to seek.

from_what : int

As in the Python standard: 0 seeks from the start of the memory region, 1 seeks from the current position and 2 seeks from the end of the memory region. For example:

mem.seek(-1, 2)  # Goes to the last byte in the region
mem.seek(-5, 1)  # Goes 5 bytes before that point
mem.seek(0)      # Returns to the start of the region

Note that os.SEEK_END, os.SEEK_CUR and os.SEEK_SET are also valid arguments.

tell()[source]

Get the current offset in the memory region.

Returns:
int

Current offset (starting at 0).

write(bytes)[source]

Write data to the memory.

Note

Writes beyond the specified memory range will be truncated and a TruncationWarning is produced. These warnings can be converted into exceptions using warnings.simplefilter():

>>> import warnings
>>> from rig.machine_control.machine_controller \
...     import TruncationWarning
>>> warnings.simplefilter('error', TruncationWarning)
Parameters:
bytes : bytes

Data to write to the memory as a bytestring.

Returns:
int

Number of bytes written.

A high level interface for controlling a SpiNNaker system.

class rig.machine_control.machine_controller.CoreInfo[source]

Information returned about a core by sver.

Parameters:
position : (x, y)

Logical location of the chip in the system.

physical_cpu : int

The physical ID of the core. (Not useful to most users).

virt_cpu : int

The virtual ID of the core. This is the number used by all high-level software APIs.

software_version : (major, minor, patch)

The numerical components of the software version number. See also: software_version_labels.

buffer_size : int

Maximum supported size (in bytes) of the data portion of an SCP packet.

build_date : int

The time at which the software was compiled as a unix timestamp. May be zero if not set.

version_string : string

Human readable, textual version information split in to two fields by a “/”. In the first field is the kernal (e.g. SC&MP or SARK) and the second the hardware platform (e.g. SpiNNaker).

software_version_labels : string

Any additional labels or build information associated with the software version. (See also: software_version and the Semantic Versioning specification).

class rig.machine_control.machine_controller.ChipInfo[source]

Information returned about a chip.

If some parameter is omitted from the constructor, realistic defaults are provided. These should only be used for writing tests and general applications should set all values based on reports from the SpiNNaker machine itself, e.g. using get_chip_info().

Parameters:
num_cores : int

The number of working cores on the chip.

core_states : [AppState, …]

The state of each working core in the machine in a list num_cores in length.

working_links : set([rig.links.Links, …])

The set of working links leaving that chip. For a link to be considered working, the link must work in both directions and the device at the far end must also be a SpiNNaker chip.

largest_free_sdram_block : int

The size (in bytes) of the largest free block of SDRAM.

largest_free_sram_block : int

The size (in bytes) of the largest free block of SRAM.

largest_free_rtr_mc_block : int

Number of entries in the largest free block of multicast router entries.

ethernet_up : bool

True if the chip’s Ethernet connection is connected, False otherwise.

ip_address : str

The IP address of the Chip’s Ethernet connection. If ethernet_up is False, the value of this field is unpredictable and should be ignored.

local_ethernet_chip : (x, y)

The coordinates of the ‘nearest’ Ethernet connected chip to this chip, corresponding with the value in sv->eth_addr.

Note

This value may not literally be the nearest Ethernet connected chip. For example, it could be the Ethernet connected chip on the same board as the chip or chosen by the system at boot by some process which evenly balances load.

class rig.machine_control.machine_controller.SystemInfo(width, height, *args, **kwargs)[source]

An enhanced dict containing a lookup from chip coordinates, (x, y), to chip information, ChipInfo.

This dictionary contains an entry for every working chip in a system and no entry for chips which are dead. In addition to normal dictionary functionality, a number of utility methods are provided for iterating over useful information, for example individual cores and links.

Attributes:
width : int

The width of the system in chips.

height : int

The height of the system in chips.

__init__(width, height, *args, **kwargs)[source]

Construct a SystemInfo object.

Parameters:
width : int

The width of the system, in chips.

height : int

The height of the system, in chips.

Remaining arguments are passed directly to the dict constructor.

chips()[source]

Iterate over the coordinates of working chips.

An alias for __iter__(), included for consistency.

Yields:
(x, y)

The coordinate of a working chip.

ethernet_connected_chips()[source]

Iterate over the coordinates of Ethernet connected chips.

Yields:
((x, y), str)

The coordinate and IP address of each Ethernet connected chip in the system.

dead_chips()[source]

Generate the coordinates of all dead chips.

Yields:
(x, y)

The coordinate of a dead chip.

Generate the coordinates of all working links.

Yields:
(x, y, :py:class:`rig.links.Links`)

A working link leaving a chip from the perspective of the chip. For example (0, 0, Links.north) would be the link going north from chip (0, 0) to chip (0, 1).

Generate the coordinates of all dead links leaving working chips.

Any link leading to a dead chip will also be included in the list of dead links. In non-torroidal SpiNNaker sysmtes (e.g. single SpiNN-5 boards), links on the periphery of the system will be marked as dead.

Yields:
(x, y, :py:class:`rig.links.Links`)

A working link leaving a chip from the perspective of the chip. For example (0, 0, Links.north) would be the link going north from chip (0, 0) to chip (0, 1).

cores()[source]

Generate the set of all cores in the system.

Yields:
(x, y, p, :py:class:`~rig.machine_control.consts.AppState`)

A core in the machine, and its state. Cores related to a specific chip are yielded consecutively in ascending order of core number.

__contains__(chip_core_or_link)[source]

Test if a given chip, core or link is present and alive.

Parameters:
chip_core_or_link : tuple
  • If of the form (x, y, Links), checks the link is present.
  • If of the form (x, y, p), checks the core is present.
  • If of the form (x, y, p, AppState), checks the core is present and in the specified state.
  • If of the form (x, y), checks the chip is present.
__weakref__

list of weak references to the object (if defined)

class rig.machine_control.machine_controller.ProcessorStatus[source]

Information returned about the status of a processor.

Parameters:
registers : list

Register values dumped during a runtime exception. (All zero by default.)

program_status_register : int

CPSR register (dumped during a runtime exception and zero by default).

stack_pointer : int

Stack pointer (dumped during a runtime exception and zero by default).

link_register : int

Link register (dumped during a runtime exception and zero by default).

rt_code : RuntimeException

Code for any run-time exception which may have occurred.

phys_cpu : int

The physical CPU ID.

cpu_state : AppState

Current state of the processor.

mbox_ap_msg : int
mbox_mp_msg : int
mbox_ap_cmd : int
mbox_mp_cmd : int
sw_count : int

Saturating count of software errors. (Calls to sw_err).

sw_file : int

Pointer to a string containing the file name in which the last software error occurred.

sw_line : int

Line number of the last software error.

time : int

Time application was loaded.

app_name : string

Name of the application loaded to the processor core.

iobuf_address : int

Address of the output buffer used by the processor.

app_id : int

ID of the application currently running on the processor.

version : (major, minor, patch)

The version number of the application running on the core.

user_vars : list

List of 4 integer values that may be set by the user.

class rig.machine_control.machine_controller.RouterDiagnostics[source]

A namedtuple of values of a SpiNNaker router’s 16 programmable diagnostic counters.

Counter values can be accessed by subscripting:

>>> diag = mc.get_router_diagnostics(0, 0)  
>>> diag[0]                                 
53491

On boot, the first twelve counters are preconfigured to count commonly used information. As a convenience, these counter values can be selected by name:

>>> diag.dropped_multicast  
41

Note

It is possible to reconfigure all of the router counters to count arbitrary events (see the rFN register in section 10.11 of the SpiNNaker datasheet). If this has been done, using the subscript syntax for accessing counter values from this structure is strongly recommended.

Parameters:
local_multicast : int
external_multicast : int
local_p2p : int
external_p2p : int
local_nearest_neighbour : int
external_nearest_neighbour : int
local_fixed_route : int
external_fixed_route : int

For each of SpiNNaker’s four packet types (multicast, point-to-point, nearest neighbour and fixed-route), there is:

  • A local_* counter which reports the number of packets routed which were sent by local application cores.
  • An external_* counter which reports the number of packets routed which were received from external sources (i.e. neighbouring chips).

Any packets which were dropped by the router are not included in these counts.

dropped_multicast : int
dropped_p2p : int
dropped_nearest_neighbour : int
dropped_fixed_route : int

These counters report the number of each type of packet which were dropped after arrival at this core.

counter12 : int
counter13 : int
counter14 : int
counter15 : int

These counters are disabled by default.

class rig.machine_control.machine_controller.IPTag[source]

An IPTag as read from a SpiNNaker machine.

Parameters:
addr : str

IP address SDP packets are forwarded to

mac : int
port : int

Port number to forward SDP packets to

timeout : int
count : int
rx_port : int
spinn_addr : int
spinn_port : int
exception rig.machine_control.machine_controller.SpiNNakerBootError[source]

Raised when attempting to boot a SpiNNaker machine has failed.

__weakref__

list of weak references to the object (if defined)

exception rig.machine_control.machine_controller.SpiNNakerMemoryError(size, x, y, tag=0, tag_in_use=False)[source]

Raised when it is not possible to allocate memory on a SpiNNaker chip.

Attributes:
size : int

The size of the failed allocation.

chip : (x, y)

The chip coordinates on which the allocation failed.

tag : int

The tag number of the failed allocation.

tag_in_use : bool

Whether the allocation failed because the tag was already in use.

__init__(size, x, y, tag=0, tag_in_use=False)[source]

x.__init__(…) initializes x; see help(type(x)) for signature

__str__() <==> str(x)[source]
__weakref__

list of weak references to the object (if defined)

exception rig.machine_control.machine_controller.SpiNNakerRouterError(count, x, y)[source]

Raised when it is not possible to allocated routing table entries on a SpiNNaker chip.

Attributes:
count : int

The number of routing table entries requested.

chip : (x, y)

The coordinates of the chip the allocation failed on.

__init__(count, x, y)[source]

x.__init__(…) initializes x; see help(type(x)) for signature

__str__() <==> str(x)[source]
__weakref__

list of weak references to the object (if defined)

exception rig.machine_control.machine_controller.SpiNNakerLoadingError(application_map)[source]

Raised when it has not been possible to load applications to cores.

Attributes:
app_map : {“/path/to/app.aplx”: {(x, y): {core, …}, …}, …}

The application map of the cores which could not be loaded.

__init__(application_map)[source]

x.__init__(…) initializes x; see help(type(x)) for signature

__str__() <==> str(x)[source]
__weakref__

list of weak references to the object (if defined)

exception rig.machine_control.machine_controller.TruncationWarning[source]

Warning produced when a reading/writing past the end of a MemoryIO results in a truncated read/write.

__weakref__

list of weak references to the object (if defined)

rig.machine_control.utils.sdram_alloc_for_vertices(controller, placements, allocations, core_as_tag=True, sdram_resource=SDRAM, cores_resource=Cores, clear=False)[source]

Allocate and return a file-like view of a region of SDRAM for each vertex which uses SDRAM as a resource.

The tag assigned to each region of assigned SDRAM is the index of the first core that each vertex is assigned. For example:

placements = {vertex: (0, 5)}
allocations = {vertex: {Cores: slice(3, 6),
                        SDRAM: slice(204, 304)}}
sdram_allocations = sdram_alloc_for_vertices(
    controller, placements, allocations
)

Will allocate a 100-byte block of SDRAM for the vertex which is allocated cores 3-5 on chip (0, 5). The region of SDRAM will be tagged 3 (because this is the index of the first core).

Parameters:
controller : rig.machine_control.MachineController

Controller to use to allocate the SDRAM.

placements : {vertex: (x, y), …}

Mapping of vertices to the chips they have been placed on. Same as produced by placers.

allocations : {vertex: {resource: allocation, …}, …}

Mapping of vertices to the resources they have been allocated.

A block of memory of the size specified by the sdram_resource (default: SDRAM) resource will be allocated for each vertex. Note that location of the supplied allocation is not used.

When core_as_tag=True, the tag allocated will be the ID of the first core used by the vertex (indicated by the cores_resource, default Cores), otherwise the tag will be set to 0.

clear : bool

If True the requested memory will be filled with zeros before the pointer is returned. If False (the default) the memory will be left as-is.

Returns:
{vertex: :py:class:`.MemoryIO`, …}

A file-like object for each vertex which can be used to read and write to the region of SDRAM allocated to the vertex.

Other Parameters:
 
core_as_tag : bool

Use the index of the first allocated core as the tag for the region of memory, otherwise 0 will be used.

sdram_resource : resource (default SDRAM)

Key used to indicate SDRAM usage in the resources dictionary.

cores_resource : resource (default Cores)

Key used to indicate cores which have been allocated in the allocations dictionary.

Raises:
rig.machine_control.machine_controller.SpiNNakerMemoryError

If the memory cannot be allocated, or a tag is already taken or invalid.

BMPController: BMP Control API

class rig.machine_control.BMPController(hosts, scp_port=17893, n_tries=5, timeout=0.5, initial_context={'board': 0, 'cabinet': 0, 'frame': 0})[source]

Control the BMPs (Board Management Processors) onboard SpiNN-5 boards in a SpiNNaker machine.

A tutorial is available which introduces the basic features of this class.

BMPs (and thus boards) are addressed as follows:

          2             1                0
Cabinet --+-------------+----------------+
          |             |                |
+-------------+  +-------------+  +-------------+    Frame
|             |  |             |  |             |      |
| +---------+ |  | +---------+ |  | +---------+ |      |
| | : : : : | |  | | : : : : | |  | | : : : : |--------+ 0
| | : : : : | |  | | : : : : | |  | | : : : : | |      |
| +---------+ |  | +---------+ |  | +---------+ |      |
| | : : : : | |  | | : : : : | |  | | : : : : |--------+ 1
| | : : : : | |  | | : : : : | |  | | : : : : | |      |
| +---------+ |  | +---------+ |  | +---------+ |      |
| | : : : : | |  | | : : : : | |  | | : : : : |--------+ 2
| | : : : : | |  | | : : : : | |  | | : : : : | |      |
| +---------+ |  | +---------+ |  | +---------+ |      |
| | : : : : | |  | | : : : : | |  | | : : : : |--------+ 3
| | : : : : | |  | | : : : : | |  | | : : : : | |
| +---------+ |  | +|-|-|-|-|+ |  | +---------+ |
|             |  |  | | | | |  |  |             |
+-------------+  +--|-|-|-|-|--+  +-------------+
                    | | | | |
         Board -----+-+-+-+-+
                    4 3 2 1 0

Coordinates are conventionally written as 3-tuples of integers (cabinet, frame, board). This gives the upper-right-most board’s coordinate (0, 0, 0).

Communication with BMPs is facilitated either directly via Ethernet or indirectly via the Ethernet connection of another BMP and the CAN bus in the backplane of each frame.

This class aims not to be a complete BMP communication solution (users are referred instead to the general-purpose bmpc utility), but rather to cover common uses of the BMP in normal application usage.

__init__(hosts, scp_port=17893, n_tries=5, timeout=0.5, initial_context={'board': 0, 'cabinet': 0, 'frame': 0})[source]

Create a new controller for BMPs in a SpiNNaker machine.

Parameters:
hosts : string or {coord: string, …}

Hostname or IP address of the BMP to connect to or alternatively, multiple addresses can be given in a dictionary to allow control of many boards. coord may be given as ether (cabinet, frame) or (cabinet, frame, board) tuples. In the former case, the address will be used to communicate with all boards in the specified frame except those listed explicitly. If only a single hostname is supplied it is assumed to be for all boards in cabinet 0, frame 0.

scp_port : int

Port number to use for all SCP connections

n_tries : int

Number of SDP packet retransmission attempts.

timeout : float

SDP response timeout.

initial_context : {argument: value}

Dictionary of default arguments to pass to methods in this class. This defaults to selecting the coordinate (0, 0, 0) which is convenient in single-board systems.

__call__(**context_args)[source]

Create a new context for use with with.

send_scp(*args, frame=Required, board=Required, cabinet=Required, **kwargs)[source]

Transmit an SCP Packet to a specific board.

Automatically determines the appropriate connection to use.

See the arguments for SCPConnection() for details.

Parameters:
cabinet : int
frame : int
board : int
get_software_version(cabinet, frame, board)[source]

Get the software version for a given BMP.

Returns:
:py:class:`.BMPInfo`

Information about the software running on a BMP.

set_power(state, cabinet, frame, board, delay=0.0, post_power_on_delay=5.0)[source]

Control power to the SpiNNaker chips and FPGAs on a board.

Returns:
state : bool

True for power on, False for power off.

board : int or iterable

Specifies the board to control the power of. This may also be an iterable of multiple boards (in the same frame). The command will actually be sent board 0, regardless of the set of boards specified.

delay : float

Number of seconds delay between power state changes of different boards.

post_power_on_delay : float

Number of seconds for this command to block once the power on command has been carried out. A short delay (default) is useful at this point since power-supplies and SpiNNaker chips may still be coming on line immediately after the power-on command is sent.

Warning

If the set of boards to be powered-on does not include board 0, this timeout should be extended by 2-3 seconds. This is due to the fact that BMPs immediately acknowledge power-on commands to boards other than board 0 but wait for the FPGAs to be loaded before responding when board 0 is powered on.

set_led(led, action=None, cabinet=Required, frame=Required, board=Required)[source]

Set or toggle the state of an LED.

Note

At the time of writing, LED 7 is only set by the BMP on start-up to indicate that the watchdog timer reset the board. After this point, the LED is available for use by applications.

Parameters:
led : int or iterable

Number of the LED or an iterable of LEDs to set the state of (0-7)

action : bool or None

State to set the LED to. True for on, False for off, None to toggle (default).

board : int or iterable

Specifies the board to control the LEDs of. This may also be an iterable of multiple boards (in the same frame). The command will actually be sent to the first board in the iterable.

read_fpga_reg(fpga_num, addr, cabinet, frame, board)[source]

Read the value of an FPGA (SPI) register.

See the SpI/O project’s spinnaker_fpga design’s README for a listing of FPGA registers. The SpI/O project can be found on GitHub at: https://github.com/SpiNNakerManchester/spio/

Parameters:
fpga_num : int

FPGA number (0, 1 or 2) to communicate with.

addr : int

Register address to read to (will be rounded down to the nearest 32-bit word boundary).

Returns:
int

The 32-bit value at that address.

write_fpga_reg(fpga_num, addr, value, cabinet, frame, board)[source]

Write the value of an FPGA (SPI) register.

See the SpI/O project’s spinnaker_fpga design’s README for a listing of FPGA registers. The SpI/O project can be found on GitHub at: https://github.com/SpiNNakerManchester/spio/

Parameters:
fpga_num : int

FPGA number (0, 1 or 2) to communicate with.

addr : int

Register address to read or write to (will be rounded down to the nearest 32-bit word boundary).

value : int

A 32-bit int value to write to the register

read_adc(cabinet, frame, board)[source]

Read ADC data from the BMP including voltages and temperature.

Returns:
:py:class:`.ADCInfo`
class rig.machine_control.bmp_controller.BMPInfo[source]

Information returned about a BMP by sver.

Parameters:
code_block : int

The BMP, on power-up, will execute the first valid block in its flash storage. This value which indicates which 64 KB block was selected.

frame_id : int

An identifier programmed into the EEPROM of the backplane which uniquely identifies the frame the board is in. Note: This ID is not necessarily the same as a board’s frame-coordinate.

can_id : int

ID of the board in the backplane CAN bus.

board_id : int

The position of the board in a frame. (This should correspond exactly with a board’s board-coordinate.

version : (major, minor, patch)

Software version number. See also: version_labels.

buffer_size : int

Maximum supported size (in bytes) of the data portion of an SCP packet.

build_date : int

The time at which the software was compiled as a unix timestamp. May be zero if not set.

version_string : string

Human readable, textual version information split in to two fields by a “/”. In the first field is the kernel (e.g. BC&MP) and the second the hardware platform (e.g. Spin5-BMP).

version_labels : string

Any additional labels or build information associated with the software version. (See also: version and the Semantic Versioning specification).

class rig.machine_control.bmp_controller.ADCInfo[source]

ADC data returned by a BMP including voltages and temperature.

Parameters:
voltage_1_2a : float

Measured voltage on the 1.2 V rail A.

voltage_1_2b : float

Measured voltage on the 1.2 V rail B.

voltage_1_2c : float

Measured voltage on the 1.2 V rail C.

voltage_1_8 : float

Measured voltage on the 1.8 V rail.

voltage_3_3 : float

Measured voltage on the 3.3 V rail.

voltage_supply : float

Measured voltage of the (12 V) power supply input.

temp_top : float

Temperature near the top of the board (degrees Celsius)

temp_btm : float

Temperature near the bottom of the board (degrees Celsius)

temp_ext_0 : float

Temperature read from external sensor 0 (degrees Celsius) or None if not connected.

temp_ext_1 : float

Temperature read from external sensor 1 (degrees Celsius) or None if not connected.

fan_0 : int

External fan speed (RPM) of fan 0 or None if not connected.

fan_1 : int

External fan speed (RPM) of fan 1 or None if not connected.

boot: Low-level Machine Booting API

Boot constructs for a SpiNNaker machine.

Warning

Implementation is reconstructed from a Perl implementation which forms a significant part of the documentation for this process.

rig.machine_control.boot.spin1_boot_options = {'hw_ver': 1, 'led0': 483588}

Boot options for boot() for SpiNN-1 boards.

rig.machine_control.boot.spin2_boot_options = {'hw_ver': 2, 'led0': 24835}

Boot options for boot() for SpiNN-2 boards.

rig.machine_control.boot.spin3_boot_options = {'hw_ver': 3, 'led0': 1282}

Boot options for boot() for SpiNN-3 boards.

rig.machine_control.boot.spin4_boot_options = {'hw_ver': 4, 'led0': 1}

Boot options for boot() for SpiNN-4 boards.

rig.machine_control.boot.spin5_boot_options = {'hw_ver': 5, 'led0': 1}

Boot options for boot() for SpiNN-5 boards.

rig.machine_control.boot.boot(hostname, boot_port=54321, scamp_binary=None, sark_struct=None, boot_delay=0.05, post_boot_delay=2.0, sv_overrides={}, **kwargs)[source]

Boot a SpiNNaker machine of the given size.

Parameters:
hostname : str

Hostname or IP address of the SpiNNaker chip to use to boot the system.

boot_port : int

The port number to sent boot packets to.

scamp_binary : filename or None

Filename of the binary to boot the machine with or None to use the SC&MP binary bundled with Rig.

sark_struct : filename or None

The ‘sark.struct’ file which defines the datastructures or None to use the one bundled with Rig.

boot_delay : float

Number of seconds to pause between sending boot data packets.

post_boot_delay : float

Number of seconds to wait after sending last piece of boot data to give SC&MP time to re-initialise the Ethernet interface. Note that this does not wait for the system to fully boot.

sv_overrides : {name: value, …}

Values used to override the defaults in the ‘sv’ struct defined in the struct file.

Returns:
{struct_name: :py:class:`~rig.machine_control.struct_file.Struct`}

Layout of structs in memory.

Notes

The constants rig.machine_control.boot.spinX_boot_options provide boot parameters for specific SpiNNaker board revisions, for example:

boot("board1", **spin3_boot_options)

Will boot the Spin3 board connected with hostname “board1”.

rig.machine_control.unbooted_ping.listen(timeout=6.0, port=54321)[source]

Listen for a ‘ping’ broadcast message from an unbooted SpiNNaker board.

Unbooted SpiNNaker boards send out a UDP broadcast message every 4-ish seconds on port 54321. This function listens for such messages and reports the IP address that it came from.

Parameters:
timeout : float

Number of seconds to wait for a message to arrive.

port : int

The port number to listen on.

Returns:
str or None

The IP address of the SpiNNaker board from which a ping was received or None if no ping was observed.

packets: Raw SDP/SCP Packet Packing/Unpacking

Representations of SDP and SCP Packets.

class rig.machine_control.packets.SDPPacket(reply_expected=False, tag=255, dest_port=None, dest_cpu=None, src_port=7, src_cpu=31, dest_x=None, dest_y=None, src_x=0, src_y=0, data='')[source]

An SDP Packet

__init__(reply_expected=False, tag=255, dest_port=None, dest_cpu=None, src_port=7, src_cpu=31, dest_x=None, dest_y=None, src_x=0, src_y=0, data='')[source]

Create a new SDPPacket.

Parameters:
dest_x : int (0-255)

x co-ordinate of the chip to which the packet should be sent.

dest_y : int (0-255)

y co-ordinate of the chip to which the packet should be sent.

dest_cpu : int (0-17)

Index of the core which should receive the packet.

dest_port : int (0-7)

Port which should receive the packet (0 is reserved for debugging).

data : bytes

Data to append to the packet.

reply_expected : bool

True if a response to this packet is expected, if False (the default) no response is expected.

Other Parameters:
 
tag : int

IPTag used to determine where to send packets over IPv4. The default (0xff) indicates a packet being transmitted into SpiNNaker.

src_port : int

Source port of the packet.

src_cpu : int

Source CPU of the packet.

src_x : int

Source x co-ordinate of the packet.

src_y : int

Source y co-ordinate of the packet.

.. note::

The default values for tag, src_port, src_cpu, src_x and src_y indicate a packet being transmitted to SpiNNaker over the network and will not require changing for this use.

classmethod from_bytestring(bytestring)[source]

Create a new SDPPacket from a bytestring.

Returns:
SDPPacket

An SDPPacket containing the data from the bytestring.

bytestring

Convert the packet into a bytestring.

class rig.machine_control.packets.SCPPacket(reply_expected=False, tag=255, dest_port=None, dest_cpu=None, src_port=7, src_cpu=31, dest_x=None, dest_y=None, src_x=0, src_y=0, cmd_rc=None, seq=0, arg1=None, arg2=None, arg3=None, data='')[source]

An SCP Packet

__init__(reply_expected=False, tag=255, dest_port=None, dest_cpu=None, src_port=7, src_cpu=31, dest_x=None, dest_y=None, src_x=0, src_y=0, cmd_rc=None, seq=0, arg1=None, arg2=None, arg3=None, data='')[source]

Create a new SCP formatted packet.

Parameters:
dest_x : int (0-255)

x co-ordinate of the chip to which the packet should be sent.

dest_y : int (0-255)

y co-ordinate of the chip to which the packet should be sent.

dest_cpu : int (0-17)

Index of the core which should receive the packet.

dest_port : int (0-7)

Port which should receive the packet (0 is reserved for debugging).

cmd_rc : int (1 word)

Command/return code of the packet. This will determine what action occurs if the packet is handled by SARK or SCAMP.

arg1 : int (1 word) or None

If None then ignored.

arg2 : int (1 word) or None

If None then ignored.

arg3 : int (1 word) or None

If None then ignored.

data : bytes

Data to append to the packet after arg1, arg2 and arg3.

reply_expected : bool

True if a response to this packet is expected, if False (the default) no response is expected.

Other Parameters:
 
tag : int

IPTag used to determine where to send packets over IPv4. The default (0xff) indicates a packet being transmitted into SpiNNaker.

src_port : int

Source port of the packet.

src_cpu : int

Source CPU of the packet.

src_x : int

Source x co-ordinate of the packet.

src_y : int

Source y co-ordinate of the packet.

seq : int

Sequence number of the packet, used when communicating the SCAMP or SARK.

.. note::

The default values for tag, src_port, src_cpu, src_x and src_y indicate a packet being transmitted to SpiNNaker over the network and will not require changing for this use.

classmethod from_bytestring(scp_packet, n_args=3)[source]

Create a new SCPPacket from a bytestring.

Parameters:
scp_packet : bytestring

Bytestring containing an SCP packet.

n_args : int

The number of arguments to unpack from the SCP data.

packed_data

Pack the data for the SCP packet.

__repr__()[source]

Produce a human-readable summary of (the most important parts of) the packet.

scp_connection: High-performance SCP protocol implementation

This module presents a high-performance implementation of the SCP protocol which is used to communicate with SC&MP.

A blocking implementation of the SCP protocol.

class rig.machine_control.scp_connection.scpcall[source]

Utility for specifying SCP packets which will be sent using send_scp_burst() and their callbacks.

..note::
The parameters are similar to the parameters for send_scp but for the addition of callback between expected_args and timeout.
Parameters:
x : int
y : int
p : int
cmd : int
arg1 : int
arg2 : int
arg3 : int
data : bytes
callback : function

Function which will be called with the packet that acknowledges the transmission of this packet.

timeout : float

Additional timeout in seconds to wait for a reply on top of the default specified upon instantiation.

class rig.machine_control.scp_connection.SCPConnection(spinnaker_host, port=17893, n_tries=5, timeout=0.5)[source]

Implements the SCP protocol for communicating with a SpiNNaker chip.

__init__(spinnaker_host, port=17893, n_tries=5, timeout=0.5)[source]

Create a new communicator to handle control of the SpiNNaker chip with the supplied hostname.

Parameters:
spinnaker_host : str

A IP address or hostname of the SpiNNaker chip to control.

port : int

Port number to send to.

n_tries : int

The maximum number of tries to communicate with the chip before failing.

timeout : float

The timeout to use on the socket.

send_scp(buffer_size, x, y, p, cmd, arg1=0, arg2=0, arg3=0, data='', expected_args=3, timeout=0.0)[source]

Transmit a packet to the SpiNNaker machine and block until an acknowledgement is received.

Parameters:
buffer_size : int

Number of bytes held in an SCP buffer by SARK, determines how many bytes will be expected in a socket.

x : int
y : int
p : int
cmd : int
arg1 : int
arg2 : int
arg3 : int
data : bytestring
expected_args : int

The number of arguments (0-3) that are expected in the returned packet.

timeout : float

Additional timeout in seconds to wait for a reply on top of the default specified upon instantiation.

Returns:
:py:class:`~rig.machine_control.packets.SCPPacket`

The packet that was received in acknowledgement of the transmitted packet.

send_scp_burst(buffer_size, window_size, parameters_and_callbacks)[source]

Send a burst of SCP packets and call a callback for each returned packet.

Parameters:
buffer_size : int

Number of bytes held in an SCP buffer by SARK, determines how many bytes will be expected in a socket.

window_size : int

Number of packets which can be awaiting replies from the SpiNNaker board.

parameters_and_callbacks: iterable of :py:class:`.scpcall`

Iterable of scpcall elements. These elements can specify a callback which will be called with the returned packet.

read(buffer_size, window_size, x, y, p, address, length_bytes)[source]

Read a bytestring from an address in memory.

..note::
This method is included here to maintain API compatibility with an alternative implementation of SCP.
Parameters:
buffer_size : int

Number of bytes held in an SCP buffer by SARK, determines how many bytes will be expected in a socket and how many bytes of data will be read back in each packet.

window_size : int
x : int
y : int
p : int
address : int

The address at which to start reading the data.

length_bytes : int

The number of bytes to read from memory. Large reads are transparently broken into multiple SCP read commands.

Returns:
:py:class:`bytes`

The data is read back from memory as a bytestring.

write(buffer_size, window_size, x, y, p, address, data)[source]

Write a bytestring to an address in memory.

..note::
This method is included here to maintain API compatibility with an alternative implementation of SCP.
Parameters:
buffer_size : int

Number of bytes held in an SCP buffer by SARK, determines how many bytes will be expected in a socket and how many bytes will be written in each packet.

window_size : int
x : int
y : int
p : int
address : int

The address at which to start writing the data. Addresses are given within the address space of a SpiNNaker core. See the SpiNNaker datasheet for more information.

data : bytes

Data to write into memory. Writes are automatically broken into a sequence of SCP write commands.

close()[source]

Close the SCP connection.

__weakref__

list of weak references to the object (if defined)

exception rig.machine_control.scp_connection.SCPError(message='', packet=None)[source]

Base Error for SCP return codes.

Attributes:
packet : rig.machine_control.packets.SCPPacket

The packet being processed when the error occurred. May be None if no specific packet was involved.

__init__(message='', packet=None)[source]

x.__init__(…) initializes x; see help(type(x)) for signature

__weakref__

list of weak references to the object (if defined)

exception rig.machine_control.scp_connection.TimeoutError(message='', packet=None)[source]

Raised when an SCP is not acknowledged within the given period of time.

exception rig.machine_control.scp_connection.FatalReturnCodeError(return_code=None, packet=None)[source]

Raised when an SCP command returns with an error which is connsidered fatal.

Attributes:
return_code : rig.machine_control.consts.SCPReturnCodes or int

The return code (will be a raw integer if the code is unrecognised).

__init__(return_code=None, packet=None)[source]

x.__init__(…) initializes x; see help(type(x)) for signature

struct_file: SC&MP Struct File Reading

Read struct files for SARK/SC&MP.

rig.machine_control.struct_file.read_struct_file(struct_data)[source]

Interpret a struct file defining the location of variables in memory.

Parameters:
struct_data : bytes

String of bytes containing data to interpret as the struct definition.

Returns:
{struct_name: :py:class:`~.Struct`}

A dictionary mapping the struct name to a Struct instance. Note: the struct name will be a string of bytes, e.g., b”vcpu”.

rig.machine_control.struct_file.num(value)[source]

Convert a value from one of several bases to an int.

class rig.machine_control.struct_file.Struct(name, size=None, base=None)[source]

Represents an instance of a struct.

Elements in the struct are accessible by name, e.g., struct[b”link_up”] and are of type StructField.

Attributes:
name : str

Name of the struct.

size : int

Total size of the struct in bytes.

base : int

Base address of struct in memory.

fields : {field_name: StructField}

Fields of the struct.

__init__(name, size=None, base=None)[source]

x.__init__(…) initializes x; see help(type(x)) for signature

update_default_values(**updates)[source]

Replace the default values of specified fields.

Parameters:
Parameters are taken as keyword-arguments of `field=new_value`.
Raises:
KeyError

If a field doesn’t exist in the struct.

__setitem__(name, field)[source]

Set a field in the struct.

__getitem__(name)[source]

Get a field in the struct.

pack()[source]

Pack the struct (and its default values) into a string of bytes.

Returns:
:py:class:`bytes`

Byte-string representation of struct containing default values.

__weakref__

list of weak references to the object (if defined)

class rig.machine_control.struct_file.StructField[source]
__getnewargs__()

Return self as a plain tuple. Used by copy and pickle.

__getstate__()

Exclude the OrderedDict from pickling

static __new__(_cls, pack_chars, offset, printf, default, length)

Create new instance of StructField(pack_chars, offset, printf, default, length)

__repr__()

Return a nicely formatted representation string

default

Alias for field number 3

length

Alias for field number 4

offset

Alias for field number 1

pack_chars

Alias for field number 0

printf

Alias for field number 2

consts: Machine and Protocol Constants

Constants used in the SCP protocol.

rig.machine_control.consts.BOOT_PORT = 54321

Port used to boot a SpiNNaker machine.

rig.machine_control.consts.SCP_PORT = 17893

Port used for SDP communication.

rig.machine_control.consts.SDP_HEADER_LENGTH = 8

The number of bytes making up the header of an SDP packet.

rig.machine_control.consts.SCP_SVER_RECEIVE_LENGTH_MAX = 512

The smallest power of two large enough to handle that SVER will produce (256 + 8 bytes).

rig.machine_control.consts.SPINNAKER_RTR_BASE = 3774873600

Base address of router hardware registers.

rig.machine_control.consts.SPINNAKER_RTR_P2P = 3774939136

Base address of P2P routing table.

rig.machine_control.consts.BMP_POWER_ON_TIMEOUT = 5.0

Additional timeout for BMP power-on commands to reply.

rig.machine_control.consts.BMP_ADC_MAX = 4096

The range of values the BMP’s 12-bit ADCs can measure.

rig.machine_control.consts.BMP_V_SCALE_2_5 = 0.0006103515625

Multiplier to convert from ADC value to volts for lines less than 2.5 V.

rig.machine_control.consts.BMP_V_SCALE_3_3 = 0.00091552734375

Multiplier to convert from ADC value to volts for 3.3 V lines.

rig.machine_control.consts.BMP_V_SCALE_12 = 0.003662109375

Multiplier to convert from ADC value to volts for 12 V lines.

rig.machine_control.consts.BMP_TEMP_SCALE = 0.00390625

Multiplier to convert from temperature probe values to degrees Celsius.

rig.machine_control.consts.BMP_MISSING_TEMP = -32768

Temperature value returned when a probe is not connected.

rig.machine_control.consts.BMP_MISSING_FAN = -1

Fan speed value returned when a fan is absent.

rig.machine_control.consts.RTR_ENTRIES = 1024

Number of routing table entries in each routing table.

rig.machine_control.consts.RTE_PACK_STRING = '<2H 3I'

Packing string used with routing table entries, values are (next, free, route, key, mask).

class rig.machine_control.consts.SCPCommands[source]

Command codes used in SCP packets.

Attributes:
sver = 0
read = 2
write = 3
fill = 5
link_read = 17
link_write = 18
nearest_neighbour_packet = 20
signal = 22
flood_fill_data = 23
led = 25
iptag = 26
alloc_free = 28
router = 29
info = 31
bmp_info = 48
power = 57
sver = 0

Get the software version

class rig.machine_control.consts.SCPReturnCodes[source]

SCP return codes

Attributes:
ok = 128
len = 129
sum = 130
cmd = 131
arg = 132
port = 133
timeout = 134
route = 135
cpu = 136
dead = 137
buf = 138
p2p_noreply = 139
p2p_reject = 140
p2p_busy = 141
p2p_timeout = 142
pkt_tx = 143
rig.machine_control.consts.RETRYABLE_SCP_RETURN_CODES = set([<SCPReturnCodes.sum: 130>, <SCPReturnCodes.p2p_busy: 141>])

The set of SCPReturnCodes values which indicate a non-fatal retryable fault.

rig.machine_control.consts.FATAL_SCP_RETURN_CODES = {<SCPReturnCodes.len: 129>: 'Bad command length.', <SCPReturnCodes.cmd: 131>: 'Bad/invalid command.', <SCPReturnCodes.arg: 132>: 'Invalid command arguments.', <SCPReturnCodes.port: 133>: 'Bad port number.', <SCPReturnCodes.timeout: 134>: "Timeout waiting for the application core to respond to the monitor core's request.", <SCPReturnCodes.route: 135>: 'No P2P route to the target chip is available.', <SCPReturnCodes.cpu: 136>: 'Bad CPU number.', <SCPReturnCodes.dead: 137>: 'SHM dest dead.', <SCPReturnCodes.buf: 138>: 'No free SHM buffers.', <SCPReturnCodes.p2p_noreply: 139>: 'No response packets from the target reached the ethernet connected chip.', <SCPReturnCodes.p2p_reject: 140>: 'The target chip rejected the packet.', <SCPReturnCodes.p2p_timeout: 142>: 'Communications between the ethernet connected chip and target chip timedout.', <SCPReturnCodes.pkt_tx: 143>: 'Packet transmission failed.'}

The set of fatal SCP errors and a human-readable error.

class rig.machine_control.consts.DataType[source]
Used to specify the size of data being read to/from a SpiNNaker machine
over SCP.
Attributes:
byte = 0
short = 1
word = 2
class rig.machine_control.consts.LEDAction[source]

Indicate the action that should be applied to a given LED.

Attributes:
toggle = 1
off = 2
on = 3
class rig.machine_control.consts.IPTagCommands[source]

Indicate the action that should be performed to the given IPTag.

Attributes:
set = 1
get = 2
clear = 3
class rig.machine_control.consts.AllocOperations[source]

Used to allocate or free regions of SDRAM and routing table entries.

Attributes:
alloc_sdram = 0
free_sdram_by_ptr = 1
free_sdram_by_tag = 2
alloc_rtr = 3
free_rtr_by_pos = 4
free_rtr_by_app = 5
class rig.machine_control.consts.RouterOperations[source]

Operations that may be performed to the router.

Attributes:
init = 0
clear = 1
load = 2
fixed_route_set_get = 3
class rig.machine_control.consts.NNCommands[source]

Nearest Neighbour operations.

Attributes:
flood_fill_start = 6
flood_fill_core_select = 7
flood_fill_end = 15
class rig.machine_control.consts.NNConstants[source]

Constants for use with nearest neighbour commands.

Attributes:
retry = 24
forward = 63
class rig.machine_control.consts.AppFlags[source]

Flags for application loading.

Attributes:
wait = 1
class rig.machine_control.consts.AppState[source]

States that an application may be in.

Attributes:
dead = 0
power_down = 1
runtime_exception = 2
watchdog = 3
init = 4
wait = 5
c_main = 6
run = 7
sync0 = 8
sync1 = 9
pause = 10
exit = 11
idle = 15
class rig.machine_control.consts.RuntimeException[source]

Runtime exceptions as reported by SARK.

Attributes:
none = 0
reset = 1
undefined_instruction = 2
svc = 3
prefetch_abort = 4
data_abort = 5
unhandled_irq = 6
unhandled_fiq = 7
unconfigured_vic = 8
abort = 9
malloc_failure = 10
division_by_zero = 11
event_startup_failure = 12
software_error = 13
iobuf_failure = 14
bad_enable = 15
null_pointer = 16
pkt_startup_failure = 17
timer_startup_failure = 18
api_startup_failure = 19
incompatible_version = 20
class rig.machine_control.consts.AppSignal[source]

Signals that may be transmitted to applications.

Attributes:
init = 0
power_down = 1
stop = 2
start = 3
sync0 = 4
sync1 = 5
pause = 6
cont = 7
exit = 8
timer = 9
usr0 = 10
usr1 = 11
usr2 = 12
usr3 = 13
class rig.machine_control.consts.AppDiagnosticSignal[source]

Signals which interrogate the state of a machine.

Note that a value is returned when any of these signals is sent.
Attributes:
OR = 0
AND = 1
count = 2
class rig.machine_control.consts.MessageType[source]

Internally used to specify the type of a message.

Attributes:
multicast = 0
peer_to_peer = 1
nearest_neighbour = 2
rig.machine_control.consts.signal_types = {<AppSignal.init: 0>: <MessageType.nearest_neighbour: 2>, <AppSignal.power_down: 1>: <MessageType.nearest_neighbour: 2>, <AppSignal.stop: 2>: <MessageType.nearest_neighbour: 2>, <AppSignal.start: 3>: <MessageType.nearest_neighbour: 2>, <AppSignal.sync0: 4>: <MessageType.multicast: 0>, <AppSignal.sync1: 5>: <MessageType.multicast: 0>, <AppSignal.pause: 6>: <MessageType.multicast: 0>, <AppSignal.cont: 7>: <MessageType.multicast: 0>, <AppSignal.exit: 8>: <MessageType.nearest_neighbour: 2>, <AppSignal.timer: 9>: <MessageType.multicast: 0>, <AppSignal.usr0: 10>: <MessageType.multicast: 0>, <AppSignal.usr1: 11>: <MessageType.multicast: 0>, <AppSignal.usr2: 12>: <MessageType.multicast: 0>, <AppSignal.usr3: 13>: <MessageType.multicast: 0>}

Mapping from an AppSignal to the MessageType used to transmit it.

rig.machine_control.consts.diagnostic_signal_types = {<AppDiagnosticSignal.OR: 0>: <MessageType.peer_to_peer: 1>, <AppDiagnosticSignal.AND: 1>: <MessageType.peer_to_peer: 1>, <AppDiagnosticSignal.count: 2>: <MessageType.peer_to_peer: 1>}

Mapping from an AppDiagnosticSignal to the MessageType used to transmit it.

class rig.machine_control.consts.P2PTableEntry[source]

Routing table entry in the point-to-point SpiNNaker routing table.

Attributes:
east = 0
north_east = 1
north = 2
west = 3
south_west = 4
south = 5
none = 6
monitor = 7
class rig.machine_control.consts.BMPInfoType[source]

Type of information to return from a bmp_info SCP command.

Attributes:
serial = 0
can_status = 2
adc = 3
ip_addr = 4