Skip to content

Commit

Permalink
Use flood-fill core select packets
Browse files Browse the repository at this point in the history
Changes to SCAMP to speed up flood-fill of applications have introduced
a new packet type (flood-fill core select / FFCS) which allows several
regions to be flood-filled at the same time.  This commit enables use of
this packet type.
  • Loading branch information
mundya committed Sep 10, 2015
1 parent 2a378c5 commit 555e769
Show file tree
Hide file tree
Showing 7 changed files with 48 additions and 23 deletions.
Binary file added rig/boot/scamp-3.boot
Binary file not shown.
Binary file removed rig/boot/scamp.boot
Binary file not shown.
2 changes: 1 addition & 1 deletion rig/machine_control/boot.py
Original file line number Diff line number Diff line change
Expand Up @@ -116,7 +116,7 @@ def boot(hostname, width, height, boot_port=consts.BOOT_PORT,
"""
# Get the boot data if not specified.
if boot_data is None: # pragma: no branch
boot_data = pkg_resources.resource_string("rig", "boot/scamp.boot")
boot_data = pkg_resources.resource_string("rig", "boot/scamp-3.boot")

# Read the struct file and modify the "sv" struct to contain the
# configuration values and write this into the boot data.
Expand Down
1 change: 1 addition & 0 deletions rig/machine_control/consts.py
Original file line number Diff line number Diff line change
Expand Up @@ -198,6 +198,7 @@ class RouterOperations(enum.IntEnum):
class NNCommands(enum.IntEnum):
"""Nearest Neighbour operations."""
flood_fill_start = 6
flood_fill_core_select = 10 # NOTE: LSB of opcode represent core 17
flood_fill_end = 15


Expand Down
43 changes: 26 additions & 17 deletions rig/machine_control/machine_controller.py
Original file line number Diff line number Diff line change
Expand Up @@ -731,16 +731,22 @@ def _get_next_nn_id(self):
self._nn_id = self._nn_id + 1 if self._nn_id < 126 else 1
return self._nn_id * 2

def _send_ffs(self, pid, region, n_blocks, fr):
def _send_ffs(self, pid, n_blocks, fr):
"""Send a flood-fill start packet."""
sfr = fr | (1 << 31)
self._send_scp(
0, 0, 0, SCPCommands.nearest_neighbour_packet,
(NNCommands.flood_fill_start << 24) | (pid << 16) |
(n_blocks << 8),
region, sfr
(n_blocks << 8), 0x0, sfr
)

def _send_ffcs(self, pid, region, core_mask, fr):
"""Send a flood-fill core select packet."""
arg1 = (NNCommands.flood_fill_core_select << 24) | (core_mask << 7)
arg2 = region
self._send_scp(0, 0, 0, SCPCommands.nearest_neighbour_packet,
arg1, arg2, fr | (1 << 31))

def _send_ffd(self, pid, aplx_data, address):
"""Send flood-fill data packets."""
block = 0
Expand All @@ -764,10 +770,10 @@ def _send_ffd(self, pid, aplx_data, address):
address += data_size
pos += data_size

def _send_ffe(self, pid, app_id, app_flags, cores, fr):
def _send_ffe(self, pid, app_id, app_flags, fr):
"""Send a flood-fill end packet."""
arg1 = (NNCommands.flood_fill_end << 24) | pid
arg2 = (app_id << 24) | (app_flags << 18) | (cores & 0x3ffff)
arg2 = (app_id << 24) | (app_flags << 18)
self._send_scp(0, 0, 0, SCPCommands.nearest_neighbour_packet,
arg1, arg2, fr)

Expand Down Expand Up @@ -857,21 +863,24 @@ def flood_fill_aplx(self, *args, **kwargs):
n_blocks = ((len(aplx_data) + self.scp_data_length - 1) //
self.scp_data_length)

# Perform each flood-fill.
for (region, cores) in fills:
# Get an index for the nearest neighbour operation
pid = self._get_next_nn_id()
# Start the flood fill for this application
# Get an index for the nearest neighbour operation
pid = self._get_next_nn_id()

# Send the flood-fill start packet
self._send_ffs(pid, region, n_blocks, fr)
# Send the flood-fill start packet
self._send_ffs(pid, n_blocks, fr)

# Send the core select packets
for (region, cores) in fills:
self._send_ffcs(pid, region, cores, fr)

# Send the data
base_address = self.read_struct_field(
"sv", "sdram_sys", 0, 0)
self._send_ffd(pid, aplx_data, base_address)
# Send the data
base_address = self.read_struct_field(
"sv", "sdram_sys", 0, 0)
self._send_ffd(pid, aplx_data, base_address)

# Send the flood-fill END packet
self._send_ffe(pid, app_id, flags, cores, fr)
# Send the flood-fill END packet
self._send_ffe(pid, app_id, flags, fr)

@ContextMixin.use_contextual_arguments(app_id=Required, n_tries=2,
wait=False,
Expand Down
2 changes: 1 addition & 1 deletion setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ def get_new_url(url):
name="rig",
version=__version__,
packages=find_packages(),
package_data={'rig': ['boot/sark.struct', 'boot/scamp.boot',
package_data={'rig': ['boot/sark.struct', 'boot/scamp-3.boot',
'binaries/*.aplx']
},

Expand Down
23 changes: 19 additions & 4 deletions tests/machine_control/test_machine_controller.py
Original file line number Diff line number Diff line change
Expand Up @@ -1092,7 +1092,7 @@ def test_flood_fill_aplx_single_aplx(self, cn, aplx_file, app_id, wait,

# Assert that the transmitted packets were sensible, do this by
# decoding each call to send_scp.
assert cn._send_scp.call_count == n_blocks + 2
assert cn._send_scp.call_count == n_blocks + 2 + len(targets)
# Flood-fill start
(x, y, p, cmd, arg1, arg2, arg3) = cn._send_scp.call_args_list[0][0]
assert x == y == p == 0
Expand All @@ -1102,12 +1102,27 @@ def test_flood_fill_aplx_single_aplx(self, cn, aplx_file, app_id, wait,
blocks = (arg1 & 0x0000ff00) >> 8
assert blocks == n_blocks

assert arg2 == regions.get_region_for_chip(0, 1, level=3)
assert arg2 == 0 # Used to be region now 0 to indicate that using FFCS

assert arg3 & 0x80000000 # Assert that we allocate ID on SpiNNaker
assert arg3 & 0x0000ff00 == NNConstants.forward << 8
assert arg3 & 0x000000ff == NNConstants.retry

# Flood fill core select
(x, y, p, cmd, arg1, arg2, arg3) = cn._send_scp.call_args_list[1][0]

assert x == y == p == 0
assert cmd == SCPCommands.nearest_neighbour_packet
op = (arg1 & 0xfe000000) >> 24
assert op == NNCommands.flood_fill_core_select
cores = (arg1 & 0x01ffff00) >> 7
assert cores == coremask

assert arg2 == regions.get_region_for_chip(0, 1, level=3)

assert arg3 & 0x0000ff00 == NNConstants.forward << 8
assert arg3 & 0x000000ff == NNConstants.retry

# Flood fill data
address = BASE_ADDRESS
for n in range(0, n_blocks):
Expand All @@ -1117,7 +1132,7 @@ def test_flood_fill_aplx_single_aplx(self, cn, aplx_file, app_id, wait,

# Check the sent SCP packet
(x_, y_, p_, cmd, arg1, arg2, arg3, data) = \
cn._send_scp.call_args_list[n+1][0]
cn._send_scp.call_args_list[n+2][0]

# Assert the x, y and p are the same
assert x_ == x and y_ == y and p_ == p
Expand All @@ -1141,7 +1156,7 @@ def test_flood_fill_aplx_single_aplx(self, cn, aplx_file, app_id, wait,
assert cmd == SCPCommands.nearest_neighbour_packet
assert arg1 & 0xff000000 == NNCommands.flood_fill_end << 24
assert arg2 & 0xff000000 == app_id << 24
assert arg2 & 0x0003ffff == coremask
assert arg2 & 0x0003ffff == 0 # 0 because we're using FFCS

exp_flags = 0x00000000
if wait:
Expand Down

0 comments on commit 555e769

Please sign in to comment.