Skip to content

High throughput I/O (Multiple Ethernet Connections) #177

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 8 commits into from
Closed
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
83 changes: 83 additions & 0 deletions rig/geometry.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@

from math import sqrt

import numpy as np


def to_xyz(xy):
"""Convert a two-tuple (x, y) coordinate into an (x, y, 0) coordinate."""
Expand Down Expand Up @@ -214,3 +216,84 @@ def standard_system_dimensions(num_boards):
# Convert the number of triads into numbers of chips (each triad of boards
# contributes as 12x12 block of chips).
return (w * 12, h * 12)


def spinn5_eth_coords(width, height):
"""Generate a list of board coordinates with Ethernet connectivity in a
SpiNNaker machine.

Specifically, generates the coordinates for the Ethernet connected chips of
SpiNN-5 boards arranged in a standard torus topology.

Parameters
----------
width : int
Width of the system in chips.
height : int
Height of the system in chips.
"""
# Internally, work with the width and height rounded up to the next
# multiple of 12
w = ((width + 11) // 12) * 12
h = ((height + 11) // 12) * 12

for x in range(0, w, 12):
for y in range(0, h, 12):
for dx, dy in ((0, 0), (4, 8), (8, 4)):
nx = (x + dx) % w
ny = (y + dy) % h
# Skip points which are outside the range available
if nx < width and ny < height:
yield (nx, ny)


def spinn5_local_eth_coord(x, y, w, h):
"""Get the coordinates of a chip's local ethernet connected chip.

.. note::
This function assumes the system is constructed from SpiNN-5 boards
returns the coordinates of the ethernet connected chip on the current
board.

Parameters
----------
x : int
y : int
w : int
Width of the system in chips.
h : int
Height of the system in chips.
"""
dx, dy = SPINN5_ETH_OFFSET[y % 12][x % 12]
return ((x + dx) % w), ((y + dy) % h)


SPINN5_ETH_OFFSET = np.array([
[(vx - x, vy - y) for x, (vx, vy) in enumerate(row)]
for y, row in enumerate([
# Below is an enumeration of the absolute coordinates of the nearest
# ethernet connected chip. Note that the above list comprehension
# changes these into offsets to the nearest chip.
# X: 0 1 2 3 4 5 6 7 8 9 10 11 # noqa Y:
[(+0, +0), (+0, +0), (+0, +0), (+0, +0), (+0, +0), (+4, -4), (+4, -4), (+4, -4), (+4, -4), (+4, -4), (+4, -4), (+4, -4)], # noqa 0
[(+0, +0), (+0, +0), (+0, +0), (+0, +0), (+0, +0), (+0, +0), (+4, -4), (+4, -4), (+4, -4), (+4, -4), (+4, -4), (+4, -4)], # noqa 1
[(+0, +0), (+0, +0), (+0, +0), (+0, +0), (+0, +0), (+0, +0), (+0, +0), (+4, -4), (+4, -4), (+4, -4), (+4, -4), (+4, -4)], # noqa 2
[(+0, +0), (+0, +0), (+0, +0), (+0, +0), (+0, +0), (+0, +0), (+0, +0), (+0, +0), (+4, -4), (+4, -4), (+4, -4), (+4, -4)], # noqa 3
[(-4, +4), (+0, +0), (+0, +0), (+0, +0), (+0, +0), (+0, +0), (+0, +0), (+0, +0), (+8, +4), (+8, +4), (+8, +4), (+8, +4)], # noqa 4
[(-4, +4), (-4, +4), (+0, +0), (+0, +0), (+0, +0), (+0, +0), (+0, +0), (+0, +0), (+8, +4), (+8, +4), (+8, +4), (+8, +4)], # noqa 5
[(-4, +4), (-4, +4), (-4, +4), (+0, +0), (+0, +0), (+0, +0), (+0, +0), (+0, +0), (+8, +4), (+8, +4), (+8, +4), (+8, +4)], # noqa 6
[(-4, +4), (-4, +4), (-4, +4), (-4, +4), (+0, +0), (+0, +0), (+0, +0), (+0, +0), (+8, +4), (+8, +4), (+8, +4), (+8, +4)], # noqa 7
[(-4, +4), (-4, +4), (-4, +4), (-4, +4), (+4, +8), (+4, +8), (+4, +8), (+4, +8), (+4, +8), (+8, +4), (+8, +4), (+8, +4)], # noqa 8
[(-4, +4), (-4, +4), (-4, +4), (-4, +4), (+4, +8), (+4, +8), (+4, +8), (+4, +8), (+4, +8), (+4, +8), (+8, +4), (+8, +4)], # noqa 9
[(-4, +4), (-4, +4), (-4, +4), (-4, +4), (+4, +8), (+4, +8), (+4, +8), (+4, +8), (+4, +8), (+4, +8), (+4, +8), (+8, +4)], # noqa 10
[(-4, +4), (-4, +4), (-4, +4), (-4, +4), (+4, +8), (+4, +8), (+4, +8), (+4, +8), (+4, +8), (+4, +8), (+4, +8), (+4, +8)] # noqa 11
])
], dtype=int)
"""SpiNN-5 ethernet connected chip lookup.

Used by :py:func:`.spinn5_local_eth_coord`. Given an x and y chip position
modulo 12, return the offset of the board's bottom-left chip from the chip's
position.

Note: the order of indexes: ``SPINN5_ETH_OFFSET[y][x]``!
"""
60 changes: 52 additions & 8 deletions rig/machine_control/consts.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,14 +18,6 @@
produce (256 + 8 bytes).
"""

SCP_RC_OK = 0x80
"""SCP response code which indicates that everything was fine."""

SCP_RC_TIMEOUT = {0x8b, 0x8c, 0x8d, 0x8e}
"""SCP response codes which should be treated as if they were a packet timing
out.
"""

SPINNAKER_RTR_BASE = 0xE1000000 # Unbuffered
"""Base address of router hardware registers."""

Expand Down Expand Up @@ -93,6 +85,58 @@ class SCPCommands(enum.IntEnum):
power = 57 # BMP main board power control


@add_int_enums_to_docstring
class SCPReturnCodes(enum.IntEnum):
"""SCP return codes"""
ok = 0x80 # Command completed OK
len = 0x81 # Bad packet length (Fatal)
sum = 0x82 # Bad checksum (Retryable)
cmd = 0x83 # Bad/invalid command (Fatal)
arg = 0x84 # Invalid arguments (Fatal)
port = 0x85 # Bad port number (Fatal)
timeout = 0x86 # Monitor <-> app-core comms timeout (Fatal)
route = 0x87 # No P2P route (Fatal)
cpu = 0x88 # Bad CPU number (Fatal)
dead = 0x89 # SHM dest dead (Fatal)
buf = 0x8a # No free SHM buffers (Fatal)
p2p_noreply = 0x8b # No reply to open (Fatal)
p2p_reject = 0x8c # Open rejected (Fatal)
p2p_busy = 0x8d # Dest busy (Retryable)
p2p_timeout = 0x8e # Eth chip <--> destination comms timeout (Fatal)
pkt_tx = 0x8f # Pkt Tx failed (Fatal)

RETRYABLE_SCP_RETURN_CODES = set([
SCPReturnCodes.sum,
SCPReturnCodes.p2p_busy,
])
"""The set of :py:class:`.SCPReturnCodes` values which indicate a non-fatal
retryable fault."""


FATAL_SCP_RETURN_CODES = {
SCPReturnCodes.len: "Bad command length.",
SCPReturnCodes.cmd: "Bad/invalid command.",
SCPReturnCodes.arg: "Invalid command arguments.",
SCPReturnCodes.port: "Bad port number.",
SCPReturnCodes.timeout:
"Timeout waiting for the application core to respond to "
"the monitor core's request.",
SCPReturnCodes.route: "No P2P route to the target chip is available.",
SCPReturnCodes.cpu: "Bad CPU number.",
SCPReturnCodes.dead: "SHM dest dead.",
SCPReturnCodes.buf: "No free SHM buffers.",
SCPReturnCodes.p2p_noreply:
"No response packets from the target reached the "
"ethernet connected chip.",
SCPReturnCodes.p2p_reject: "The target chip rejected the packet.",
SCPReturnCodes.p2p_timeout:
"Communications between the ethernet connected chip and target chip "
"timedout.",
SCPReturnCodes.pkt_tx: "Packet transmission failed.",
}
"""The set of fatal SCP errors and a human-readable error."""


@add_int_enums_to_docstring
class DataType(enum.IntEnum):
"""Used to specify the size of data being read to/from a SpiNNaker machine
Expand Down
Loading