Skip to content

Commit

Permalink
Try more thorough approach
Browse files Browse the repository at this point in the history
  • Loading branch information
rowleya committed Sep 26, 2023
1 parent 1b91001 commit f0f8522
Show file tree
Hide file tree
Showing 4 changed files with 85 additions and 45 deletions.
15 changes: 12 additions & 3 deletions link_test/link_test_vertex.py
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,10 @@ class ConfigData(LittleEndianStructure):
# uint32_t receive_keys[N_LINKS];
("receive_keys", c_uint32 * N_LINKS),

#: Masks to expect from neighbours
# uint32_t receive_masks[N_LINKS];
("receive_masks", c_uint32 * N_LINKS),

#: How many times to send per time step
# uint32_t sends_per_timestep;
("sends_per_timestep", c_uint32),
Expand Down Expand Up @@ -135,10 +139,12 @@ def generate_machine_data_specification(
for i in range(N_LINKS):
if self.__neighbours[i] is None:
config[0].receive_keys[i] = 0xFFFFFFFF
config[0].receive_masks[i] = 0
else:
config[0].receive_keys[i] = \
r_info.get_first_key_from_pre_vertex(
self.__neighbours[i], PARTITION_NAME)
info = r_info.get_routing_info_from_pre_vertex(
self.__neighbours[i], PARTITION_NAME)
config[0].receive_keys[i] = info.key
config[0].receive_masks[i] = info.mask
config[0].sends_per_timestep = self.__sends_per_ts
config[0].time_between_sends_us = int((ts / 2) / self.__sends_per_ts)
config[0].packet_count_ok = (
Expand Down Expand Up @@ -203,3 +209,6 @@ def _n_additional_data_items(self):

def check_failure(self):
assert not self.__failed

def get_n_keys_for_partition(self, partition_id):
return self.__sends_per_ts
2 changes: 1 addition & 1 deletion link_test/link_tester.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ def run():
# Put link test on all chips
chips = dict()
for c_x, c_y in machine.chip_coordinates:
chips[c_x, c_y] = LinkTestVertex(c_x, c_y, 100, 1, run_time)
chips[c_x, c_y] = LinkTestVertex(c_x, c_y, 256, 0, run_time)
front_end.add_machine_vertex_instance(chips[c_x, c_y])

# Connect links together
Expand Down
106 changes: 67 additions & 39 deletions link_test/run_link_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,60 +12,88 @@
# See the License for the specific language governing permissions and
# limitations under the License.

from time import sleep
import time
import os
import tempfile
import sys
import traceback
from shutil import rmtree
import pytest
from spalloc.job import Job
from spalloc.states import JobState
import spinnaker_graph_front_end as front_end
from _pytest.outcomes import Skipped
from spinnman.spalloc.spalloc_client import SpallocClient
from spinnman.spalloc.spalloc_state import SpallocState
from link_test.link_tester import run

SPALLOC_URL = "https://spinnaker.cs.man.ac.uk/spalloc"
SPALLOC_USERNAME = "jenkins"
SPALLOC_PASSWORD = os.getenv("SPALLOC_PASSWORD")
SPALLOC_MACHINE = "SpiNNaker1M"
WIDTH = 2
HEIGHT = 2


class LinkTest(object):

def do_run(self):
run()


boards = [(x, y, b) for x in range(20) for y in range(20) for b in range(3)]
boards = [(b_x, b_y) for b_x in range(0, 20, 2) for b_y in range(0, 20, 2)]
boards += [(b_x, b_y) for b_x in range(1, 20, 2) for b_y in range(1, 20, 2)]


@pytest.mark.parametrize("b_x,b_y,b_b", boards)
def test_run(b_x, b_y, b_b):
tmp_dir = os.path.abspath(os.path.join(
front_end.__path__[0], os.path.pardir, "link_test"))
job = Job(b_x, b_y, b_b, hostname="spinnaker.cs.man.ac.uk",
owner="Jenkins Link Test")
# Sleep before checking for queued in case of multiple jobs running
sleep(2.0)
if job.state == JobState.queued:
job.destroy("Queued")
pytest.skip(f"Board {b_x}, {b_y}, {b_b} is in use")
elif job.state == JobState.destroyed:
pytest.skip(f"Board {b_x}, {b_y}, {b_b} could not be allocated")
@pytest.mark.parametrize("x,y", boards)
def test_run(x, y):
test_dir = os.path.dirname(__file__)
client = SpallocClient(SPALLOC_URL, SPALLOC_USERNAME, SPALLOC_PASSWORD)
job = client.create_job_rect_at_board(
WIDTH, HEIGHT, triad=(x, y, 0), machine_name=SPALLOC_MACHINE)
with job:
with tempfile.TemporaryDirectory(
prefix=f"{b_x}_{b_y}_{b_b}", dir=tmp_dir) as tmpdir:
os.chdir(tmpdir)
with open("spiNNakerGraphFrontEnd.cfg", "w", encoding="utf-8") as f:
f.write("[Machine]\n")
f.write("spalloc_server = None\n")
f.write(f"machine_name = {job.hostname}\n")
f.write("version = 5\n")
test = LinkTest()
test.do_run()
job.launch_keepalive_task()
# Wait for not queued for up to 30 seconds
time.sleep(1.0)
state = job.get_state(wait_for_change=True)
# If queued or destroyed skip test
if state == SpallocState.QUEUED:
job.destroy("Queued")
pytest.skip(f"Some boards starting at {x}, {y}, 0 are in use"
f" on job {job}")
elif state == SpallocState.DESTROYED:
pytest.skip(
f"Boards {x}, {y}, 0 could not be allocated on job {job}")
# Actually wait for ready now (as might be powering on)
job.wait_until_ready()
tmpdir = tempfile.mkdtemp(prefix=f"{x}_{y}_0", dir=test_dir)
os.chdir(tmpdir)
with open("spynnaker.cfg", "w", encoding="utf-8") as f:
f.write("[Machine]\n")
f.write("spalloc_server = None\n")
f.write(f"machine_name = {job.get_root_host()}\n")
f.write("version = 5\n")
f.write("\n")
f.write("[Reports]\n")
f.write("reports_enabled = False\n")
f.write("write_routing_table_reports = False\n")
f.write("write_routing_tables_from_machine_reports = False\n")
f.write("write_tag_allocation_reports = False\n")
f.write("write_algorithm_timings = False\n")
f.write("write_sdram_usage_report_per_chip = False\n")
f.write("write_partitioner_reports = False\n")
f.write("write_application_graph_placer_report = False\n")
f.write("write_redundant_packet_count_report = False\n")
f.write("write_data_speed_up_reports = False\n")
f.write("write_router_info_report = False\n")
f.write("write_network_specification_report = False\n")
f.write("write_provenance = False\n")
f.write("read_graph_provenance_data = False\n")
f.write("read_placements_provenance_data = False\n")
f.write("read_profile_data = False\n")

test = LinkTest()
test.do_run()

# If no errors we will get here and we can remove the tree;
# then only error folders will be left
rmtree(tmpdir)


if __name__ == "__main__":
for x, y, b in boards:
print("", file=sys.stderr,)
print(f"*************** Testing {x}, {y}, {b} *******************",
file=sys.stderr)
try:
test_run(x, y, b)
except Skipped:
traceback.print_exc()
link_test = LinkTest()
link_test.do_run()
7 changes: 5 additions & 2 deletions link_test/src/link_test.c
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,9 @@ typedef struct {
// Keys to expect from neighbours
uint32_t receive_keys[N_LINKS];

// Masks to expect from neighbours
uint32_t receive_masks[N_LINKS];

// How many times to send per time step
uint32_t sends_per_timestep;

Expand Down Expand Up @@ -118,7 +121,7 @@ static p2p_data_t data_to_send;
static void receive_data(uint key, uint payload) {
uint32_t key_found = 0;
for (uint32_t i = 0; i < N_LINKS; i++) {
if (key == config.receive_keys[i]) {
if ((key & config.receive_masks[i]) == config.receive_keys[i]) {
packets_received[i]++;
if (payload != expected_data[i]) {
fails_received[i]++;
Expand Down Expand Up @@ -184,7 +187,7 @@ static void send_data(UNUSED uint a, UNUSED uint b) {
}

for (uint32_t i = 0; i < config.sends_per_timestep; i++) {
spin1_send_mc_packet(config.send_key, data_to_send.data, 1);
spin1_send_mc_packet(config.send_key + i, data_to_send.data, 1);
spin1_delay_us(config.time_between_sends_us);
}
}
Expand Down

0 comments on commit f0f8522

Please sign in to comment.