Skip to content

Commit

Permalink
Merge pull request #110 from SpiNNakerManchester/wrapped2
Browse files Browse the repository at this point in the history
Wrapped2
  • Loading branch information
dkfellows committed Jun 12, 2019
2 parents 281cb3b + 3926bff commit 1e4bed6
Show file tree
Hide file tree
Showing 15 changed files with 604 additions and 580 deletions.
690 changes: 345 additions & 345 deletions doc/source/conf.py

Large diffs are not rendered by default.

15 changes: 6 additions & 9 deletions spinn_machine/full_wrap_machine.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,27 +33,24 @@ def get_xys_by_ethernet(self, ethernet_x, ethernet_y):
@overrides(Machine.get_chips_by_ethernet)
def get_chips_by_ethernet(self, ethernet_x, ethernet_y):
for (x, y) in self._local_xys:
chip_xy = (
(x + ethernet_x) % self._width,
(y + ethernet_y) % self._height)
chip_xy = ((x + ethernet_x) % self._width,
(y + ethernet_y) % self._height)
if (chip_xy) in self._chips:
yield self._chips[chip_xy]

@overrides(Machine.get_existing_xys_by_ethernet)
def get_existing_xys_by_ethernet(self, ethernet_x, ethernet_y):
for (x, y) in self._local_xys:
chip_xy = (
(x + ethernet_x) % self._width,
(y + ethernet_y) % self._height)
chip_xy = ((x + ethernet_x) % self._width,
(y + ethernet_y) % self._height)
if (chip_xy) in self._chips:
yield chip_xy

@overrides(Machine.get_down_xys_by_ethernet)
def get_down_xys_by_ethernet(self, ethernet_x, ethernet_y):
for (x, y) in self._local_xys:
chip_xy = (
(x + ethernet_x) % self._width,
(y + ethernet_y) % self._height)
chip_xy = ((x + ethernet_x) % self._width,
(y + ethernet_y) % self._height)
if (chip_xy) not in self._chips:
yield chip_xy

Expand Down
17 changes: 7 additions & 10 deletions spinn_machine/horizontal_wrap_machine.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,27 +33,24 @@ def get_xys_by_ethernet(self, ethernet_x, ethernet_y):
@overrides(Machine.get_chips_by_ethernet)
def get_chips_by_ethernet(self, ethernet_x, ethernet_y):
for (x, y) in self._local_xys:
chip_xy = (
(x + ethernet_x) % self._width,
(y + ethernet_y))
chip_xy = ((x + ethernet_x) % self._width,
(y + ethernet_y))
if (chip_xy) in self._chips:
yield self._chips[chip_xy]

@overrides(Machine.get_existing_xys_by_ethernet)
def get_existing_xys_by_ethernet(self, ethernet_x, ethernet_y):
for (x, y) in self._local_xys:
chip_xy = (
(x + ethernet_x) % self._width,
(y + ethernet_y))
chip_xy = ((x + ethernet_x) % self._width,
(y + ethernet_y))
if (chip_xy) in self._chips:
yield chip_xy

@overrides(Machine.get_down_xys_by_ethernet)
def get_down_xys_by_ethernet(self, ethernet_x, ethernet_y):
for (x, y) in self._local_xys:
chip_xy = (
(x + ethernet_x) % self._width,
(y + ethernet_y))
chip_xy = ((x + ethernet_x) % self._width,
(y + ethernet_y))
if (chip_xy) not in self._chips:
yield chip_xy

Expand All @@ -67,7 +64,7 @@ def xy_over_link(self, x, y, link):
@overrides(Machine.get_local_xy)
def get_local_xy(self, chip):
local_x = (chip.x - chip.nearest_ethernet_x + self._width) \
% self._width
% self._width
local_y = chip.y - chip.nearest_ethernet_y
return local_x, local_y

Expand Down
14 changes: 7 additions & 7 deletions spinn_machine/json_machine.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,10 @@
from .router import Router
from .sdram import SDRAM
from .link import Link
from collections import defaultdict, namedtuple, OrderedDict
try:
from collections.abc import defaultdict, namedtuple, OrderedDict
except ImportError:
from collections import defaultdict, namedtuple, OrderedDict
import json
from .machine_factory import machine_from_size

Expand Down Expand Up @@ -108,12 +111,9 @@ def machine_from_json(j_machine):
if source_link_id not in dead_links:
destination_x, destination_y = machine.xy_over_link(
source_x, source_y, source_link_id)
opposite_link_id = (
(source_link_id + OPPOSITE_LINK_OFFSET) %
Router.MAX_LINKS_PER_ROUTER)
links.append(Link(
source_x, source_y, source_link_id, destination_x,
destination_y, opposite_link_id, opposite_link_id))
destination_y))
router = Router(links, False, clock_speed, router_entries)

# Create and add a chip with this router
Expand All @@ -123,8 +123,8 @@ def machine_from_json(j_machine):
tag_ids)
machine.add_chip(chip)

machine.add_spinnaker_links(version_no=None)
machine.add_fpga_links(version_no=None)
machine.add_spinnaker_links()
machine.add_fpga_links()

return machine

Expand Down
76 changes: 5 additions & 71 deletions spinn_machine/link.py
Original file line number Diff line number Diff line change
@@ -1,21 +1,20 @@
"""
a Link in a SpiNNaker machine
"""
from .exceptions import SpinnMachineAlreadyExistsException


class Link(object):
""" Represents a directional link between SpiNNaker chips in the machine
"""

__slots__ = (
"_destination_x", "_destination_y", "_multicast_default_from",
"_multicast_default_to", "_source_link_id", "_source_x", "_source_y"
"_destination_x", "_destination_y", "_source_link_id", "_source_x",
"_source_y"
)

# pylint: disable=too-many-arguments
def __init__(self, source_x, source_y, source_link_id, destination_x,
destination_y, multicast_default_from, multicast_default_to):
destination_y):
"""
:param source_x: The x-coordinate of the source chip of the link
:type source_x: int
Expand All @@ -29,29 +28,13 @@ def __init__(self, source_x, source_y, source_link_id, destination_x,
:param destination_y: \
The y-coordinate of the destination chip of the link
:type destination_y: int
:param multicast_default_from: Traffic received on the link identified\
by multicast_default_from will be sent to the link herein defined\
if no entry is present in the multicast routing table. On\
SpiNNaker chips, multicast_default_from is usually the same as\
multicast_default_to. None if no such default exists, or the link\
does not exist.
:type multicast_default_from: int
:param multicast_default_to: Traffic received on the link herein\
defined will be sent to the link identified by \
multicast_default_from if no entry is present in the multicast\
routing table. On SpiNNaker chips, multicast_default_to is usually\
the same as multicast_default_from. None if no such link exists,\
or the link does not exist.
:type multicast_default_to: int
:raise None: No known exceptions are raised
"""
self._source_x = source_x
self._source_y = source_y
self._source_link_id = source_link_id
self._destination_x = destination_x
self._destination_y = destination_y
self._multicast_default_from = multicast_default_from
self._multicast_default_to = multicast_default_to

@property
def source_x(self):
Expand Down Expand Up @@ -98,62 +81,13 @@ def destination_y(self):
"""
return self._destination_y

@property
def multicast_default_from(self):
""" The ID of the link for which this link is the default
:return: The ID of a link, or None if no such link
:rtype: int
"""
return self._multicast_default_from

@multicast_default_from.setter
def multicast_default_from(self, multicast_default_from):
""" Sets the ID of the link for which this link is the default,\
if not already set
:param multicast_default_from: The ID of a link
:type multicast_default_from: int
:raise spinn_machine.exceptions.SpinnMachineAlreadyExistsException: \
If a value has already been set
"""
if self._multicast_default_from is not None:
raise SpinnMachineAlreadyExistsException(
"multicast_default_from", str(self._multicast_default_from))
self._multicast_default_from = multicast_default_from

@property
def multicast_default_to(self):
""" The ID of the link to which to send default routed multicast
:return: The ID of a link, or None if no such link
:rtype: int
"""
return self._multicast_default_to

@multicast_default_to.setter
def multicast_default_to(self, multicast_default_to):
""" Sets the ID of the link to which to send default routed multicast
:param multicast_default_to: The ID of a link
:type multicast_default_to: int
:raise spinn_machine.exceptions.SpinnMachineAlreadyExistsException: \
If a value has already been set
"""
if self._multicast_default_to is not None:
raise SpinnMachineAlreadyExistsException(
"multicast_default_to", str(self._multicast_default_to))
self._multicast_default_to = multicast_default_to

__REPR_TEMPLATE = ("[Link: source_x={}, source_y={}, source_link_id={}, "
"destination_x={}, destination_y={}, default_from={}, "
"default_to={}]")
"destination_x={}, destination_y={}]")

def __str__(self):
return self.__REPR_TEMPLATE.format(
self._source_x, self._source_y, self._source_link_id,
self._destination_x, self._destination_y,
self._multicast_default_from, self._multicast_default_to)
self._destination_x, self._destination_y)

def __repr__(self):
return self.__str__()
59 changes: 28 additions & 31 deletions spinn_machine/machine.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
from __future__ import division
try:
from collections.abc import OrderedDict
except ImportError:
Expand Down Expand Up @@ -623,13 +624,13 @@ def get_fpga_link_with_id(self, fpga_id, fpga_link_id, board_address=None):
return self._fpga_links.get(
(board_address, fpga_id, fpga_link_id), None)

def add_spinnaker_links(self, version_no):
def add_spinnaker_links(self):
""" Add SpiNNaker links that are on a given machine depending on the\
version of the board.
:param version_no: which version of board to use
"""
if version_no in self.BOARD_VERSION_FOR_4_CHIPS:
if (self._width == self._height == 2):
chip_0_0 = self.get_chip_at(0, 0)
if not chip_0_0.router.is_link(3):
self._spinnaker_links[chip_0_0.ip_address, 0] = \
Expand All @@ -638,22 +639,22 @@ def add_spinnaker_links(self, version_no):
if not chip.router.is_link(0):
self._spinnaker_links[chip_0_0.ip_address, 1] = \
SpinnakerLinkData(1, 1, 0, 0, chip_0_0.ip_address)
elif (version_no in self.BOARD_VERSION_FOR_48_CHIPS or
version_no is None):
elif (self._width == self._height == 8) or \
self.multiple_48_chip_boards():
for chip in self._ethernet_connected_chips:
if not chip.router.is_link(4):
self._spinnaker_links[
chip.ip_address, 0] = SpinnakerLinkData(
0, chip.x, chip.y, 4, chip.ip_address)

def add_fpga_links(self, version_no):
def add_fpga_links(self):
""" Add FPGA links that are on a given machine depending on the\
version of the board.
:param version_no: which version of board to use
"""
if (version_no in self.BOARD_VERSION_FOR_48_CHIPS or
version_no is None):
if (self._width == self._height == 8) or \
self.multiple_48_chip_boards():

for ethernet_connected_chip in self._ethernet_connected_chips:

Expand Down Expand Up @@ -736,22 +737,21 @@ def __repr__(self):
def get_cores_and_link_count(self):
""" Get the number of cores and links from the machine
Links are assumed to be bidirectional so the total links counted is
half of the unidirectional links found.
Spinnaker and fpga links are not included.
:return: tuple of (n_cores, n_links)
:rtype: tuple(int,int)
"""
cores = 0
total_links = dict()
total_links = 0
for chip_key in self._chips:
chip = self._chips[chip_key]
cores += chip.n_processors
for link in chip.router.links:
key1 = (link.source_x, link.source_y, link.source_link_id)
key2 = (link.destination_x, link.destination_y,
link.multicast_default_from)
if key1 not in total_links and key2 not in total_links:
total_links[key1] = key1
links = len(total_links.keys())
return cores, links
total_links += len(chip.router)
return cores, total_links / 2

def cores_and_link_output_string(self):
""" Get a string detailing the number of cores and links
Expand Down Expand Up @@ -806,19 +806,7 @@ def total_cores(self):
return sum(
1 for chip in self.chips for _processor in chip.processors)

def remove_unreachable_chips(self):
""" Remove chips that can't be reached or that can't reach other chips\
due to missing links
"""
for xy in self._unreachable_incoming_chips:
if xy in self._chips:
del self._chips[xy]
for xy in self._unreachable_outgoing_chips:
if xy in self._chips:
del self._chips[xy]

@property
def _unreachable_outgoing_chips(self):
def unreachable_outgoing_chips(self):
removable_coords = list()
for (x, y) in self.chip_coordinates:
# If no links out of the chip work, remove it
Expand All @@ -831,8 +819,7 @@ def _unreachable_outgoing_chips(self):
removable_coords.append((x, y))
return removable_coords

@property
def _unreachable_incoming_chips(self):
def unreachable_incoming_chips(self):
removable_coords = list()
for (x, y) in self.chip_coordinates:
# Go through all the chips that surround this one
Expand All @@ -849,6 +836,16 @@ def _unreachable_incoming_chips(self):
removable_coords.append((x, y))
return removable_coords

def one_way_links(self):
link_checks = [(0, 3), (1, 4), (2, 5), (3, 0), (4, 1), (5, 2)]
for chip in self.chips:
for out, back in link_checks:
link = chip.router.get_link(out)
if link is not None:
if not self.is_link_at(
link.destination_x, link.destination_y, back):
yield chip.x, chip.y, out

@property
def virtual_chips(self):
return itervalues(self._virtual_chips)
Expand Down
Loading

0 comments on commit 1e4bed6

Please sign in to comment.