diff --git a/spinnman/board_test_configuration.py b/spinnman/board_test_configuration.py index 77d1883ee..5e38edaf7 100644 --- a/spinnman/board_test_configuration.py +++ b/spinnman/board_test_configuration.py @@ -12,10 +12,6 @@ # See the License for the specific language governing permissions and # limitations under the License. -import configparser -from contextlib import closing -import os -import socket import unittest from spinn_utilities.config_holder import set_config from spinn_utilities.ping import Ping @@ -31,7 +27,6 @@ class BoardTestConfiguration(object): def __init__(self): - #self.localhost = None self.localport = None self.remotehost = None self.board_version = None @@ -39,7 +34,6 @@ def __init__(self): self.auto_detect_bmp = None def set_up_local_virtual_board(self): - #self.localhost = _LOCALHOST self.localport = _PORT self.remotehost = _LOCALHOST self.board_version = 5 @@ -61,15 +55,10 @@ def set_up_remote_board(self): else: raise unittest.SkipTest("None of the test boards reachable") - if self.bmp_names == "None": - self.bmp_names = None - else: - # it always was None but this is what to do if not - self.bmp_names = [BMPConnectionData( - 0, 0, self.bmp_names, [0], None)] + # it always was None but this is what to do if not + # self.bmp_names = BMPConnectionData(0, 0, self.bmp_names, [0], None) def set_up_nonexistent_board(self): - self.localhost = None self.localport = _PORT self.remotehost = _NOHOST self.board_version = None diff --git a/spinnman/connections/udp_packet_connections/bmp_connection.py b/spinnman/connections/udp_packet_connections/bmp_connection.py index 458327a99..43ad50002 100644 --- a/spinnman/connections/udp_packet_connections/bmp_connection.py +++ b/spinnman/connections/udp_packet_connections/bmp_connection.py @@ -29,9 +29,7 @@ class BMPConnection(UDPConnection, AbstractSCPConnection): A BMP connection which supports queries to the BMP of a SpiNNaker machine. """ __slots__ = [ - "_boards", - "_cabinet", - "_frame"] + "_boards"] def __init__(self, connection_data): """ @@ -42,28 +40,8 @@ def __init__(self, connection_data): else connection_data.port_num super().__init__( remote_host=connection_data.ip_address, remote_port=port) - self._cabinet = connection_data.cabinet - self._frame = connection_data.frame self._boards = connection_data.boards - @property - def cabinet(self): - """ - The cabinet ID of the BMP. - - :rtype: int - """ - return self._cabinet - - @property - def frame(self): - """ - The frame ID of the BMP. - - :rtype: int - """ - return self._frame - @property def boards(self): """ @@ -106,7 +84,7 @@ def send_scp_request(self, scp_request): def __repr__(self): return ( - f"BMPConnection(cabinet={self._cabinet}, frame={self._frame}, " + f"BMPConnection(" f"boards={self._boards}, local_host={self.local_ip_address}, " f"local_port={self.local_port}, " f"remote_host={self.remote_ip_address}, " diff --git a/spinnman/extended/extended_transceiver.py b/spinnman/extended/extended_transceiver.py index f2120267f..5ae7038f5 100644 --- a/spinnman/extended/extended_transceiver.py +++ b/spinnman/extended/extended_transceiver.py @@ -427,7 +427,7 @@ def execute_application(self, executable_targets, app_id): # Send a signal telling the application to start self.send_signal(app_id, Signal.START) - def set_led(self, led, action, board, cabinet, frame): + def set_led(self, led, action, board): """ Set the LED state of a board in the machine. @@ -442,19 +442,16 @@ def set_led(self, led, action, board, cabinet, frame): :param LEDAction action: State to set the LED to, either on, off or toggle :param board: Specifies the board to control the LEDs of. This may - also be an iterable of multiple boards (in the same frame). The + also be an iterable of multiple boards. The command will actually be sent to the first board in the iterable. :type board: int or iterable(int) - :param int cabinet: the cabinet this is targeting - :param int frame: the frame this is targeting """ warn_once(logger, "The set_led method is deprecated and " "untested due to no known use.") - process = SendSingleCommandProcess( - self._bmp_connection(cabinet, frame)) + process = SendSingleCommandProcess(self._bmp_selector) process.execute(BMPSetLed(led, action, board)) - def read_adc_data(self, board, cabinet, frame): + def read_adc_data(self, board): """ Read the BMP ADC data. @@ -463,16 +460,13 @@ def read_adc_data(self, board, cabinet, frame): known use. Same functionality provided by ybug and bmpc. Retained in case needed for hardware debugging. - :param int cabinet: cabinet: the cabinet this is targeting - :param int frame: the frame this is targeting :param int board: which board to request the ADC data from :return: the FPGA's ADC data object :rtype: ADCInfo """ warn_once(logger, "The read_adc_data method is deprecated and " "untested due to no known use.") - process = SendSingleCommandProcess( - self._bmp_connection(cabinet, frame)) + process = SendSingleCommandProcess(self._bmp_selector) response = process.execute(ReadADC(board)) return response.adc_info # pylint: disable=no-member @@ -791,26 +785,11 @@ def number_of_boards_located(self): """ warn_once(logger, "The number_of_boards_located method is deprecated " "and likely to be removed.") - boards = 0 - for bmp_connection in self._bmp_connections: - boards += len(bmp_connection.boards) - - # if no BMPs are available, then there's still at least one board - return max(1, boards) - - @property - def bmp_connection(self): - """ - The BMP connections. - - .. warning:: - This property is currently deprecated and likely to be removed. - - :rtype: dict(tuple(int,int),MostDirectConnectionSelector) - """ - warn_once(logger, "The bmp_connection property is deprecated and " - "likely to be removed.") - return self._bmp_connection_selectors + if self._bmp_connection is not None: + return max(1, len(self._bmp_connection.boards)) + else: + # if no BMPs are available, then there's still at least one board + return 1 def get_heap(self, x, y, heap=SystemVariableDefinition.sdram_heap_address): """ diff --git a/spinnman/model/bmp_connection_data.py b/spinnman/model/bmp_connection_data.py index 0439fd6ca..4b2507190 100644 --- a/spinnman/model/bmp_connection_data.py +++ b/spinnman/model/bmp_connection_data.py @@ -19,37 +19,15 @@ class BMPConnectionData(object): """ __slots__ = [ "_boards", - "_cabinet", - "_frame", "_ip_address", "_port_num"] - def __init__(self, cabinet, frame, ip_address, boards, port_num): + def __init__(self, ip_address, boards, port_num): # pylint: disable=too-many-arguments - self._cabinet = cabinet - self._frame = frame self._ip_address = ip_address self._boards = boards self._port_num = port_num - @property - def cabinet(self): - """ - The cabinet number. - - :rtype: int - """ - return self._cabinet - - @property - def frame(self): - """ - The frame number. - - :rtype: int - """ - return self._frame - @property def ip_address(self): """ @@ -78,8 +56,7 @@ def port_num(self): return self._port_num def __str__(self): - return (f"{self._cabinet}:{self._frame}:{self._ip_address}:" - f"{self._boards}:{self._port_num}") + return (f"{self._ip_address}:{self._boards}:{self._port_num}") def __repr__(self): return self.__str__() diff --git a/spinnman/spinnman.cfg b/spinnman/spinnman.cfg index 118829780..e530f855f 100644 --- a/spinnman/spinnman.cfg +++ b/spinnman/spinnman.cfg @@ -13,15 +13,13 @@ report_waiting_logs = False turn_off_machine = False # format is: -# bmp_names = [:]* -# = [[;];][/(|board_id[,board_id]*)] +# bmp_names = [/(|board_id[,board_id]*) # = - # where: -# is the ID of a cabinet -# is the ID of a frame in a cabinet # is the hostname or IP address of the BMP # is a range of boards that the BMP can speak to # is the ID of a single board in a frame +# Note this no longer supports multiple host nor cabinet or frame bmp_names = None auto_detect_bmp = False diff --git a/spinnman/transceiver.py b/spinnman/transceiver.py index 394f36877..5f58a9b7c 100644 --- a/spinnman/transceiver.py +++ b/spinnman/transceiver.py @@ -109,7 +109,7 @@ def create_transceiver_from_hostname( :param int version: the type of SpiNNaker board used within the SpiNNaker machine being used. If a Spinn-5 board, then the version will be 5, Spinn-3 would equal 3 and so on. - :param list(BMPConnectionData) bmp_connection_data: + :param BMPConnectionData bmp_connection_data: the details of the BMP connections used to boot multi-board systems :param bool auto_detect_bmp: ``True`` if the BMP of version 4 or 5 boards should be @@ -141,12 +141,10 @@ def create_transceiver_from_hostname( # handle BMP connections if bmp_connection_data is not None: - bmp_ip_list = list() - for conn_data in bmp_connection_data: - bmp_connection = BMPConnection(conn_data) - connections.append(bmp_connection) - bmp_ip_list.append(bmp_connection.remote_ip_address) - logger.info("Transceiver using BMPs: {}", bmp_ip_list) + bmp_connection = BMPConnection(bmp_connection_data) + connections.append(bmp_connection) + logger.info("Transceiver using BMP: {}", + bmp_connection.remote_ip_address) connections.append(SCAMPConnection(remote_host=hostname)) @@ -174,8 +172,8 @@ class Transceiver(AbstractContextManager): """ __slots__ = [ "_all_connections", - "_bmp_connection_selectors", - "_bmp_connections", + "_bmp_selector", + "_bmp_connection", "_boot_send_connection", "_chip_execute_lock_condition", "_chip_execute_locks", @@ -234,10 +232,10 @@ def __init__( self._scamp_connections = list() # The BMP connections - self._bmp_connections = list() + self._bmp_connection = None # build connection selectors for the processes. - self._bmp_connection_selectors = dict() + self._bmp_selector = None self._scamp_connection_selector = \ self.__identify_connections(connections) @@ -251,7 +249,7 @@ def __init__( self._n_chip_execute_locks = 0 # Check that the BMP connections are valid - self.__check_bmp_connections() + self.__check_bmp_connection() self._machine_off = False @@ -288,9 +286,11 @@ def __identify_connections(self, connections): # Locate any connections that talk to a BMP if isinstance(conn, BMPConnection): # If it is a BMP conn, add it here - self._bmp_connections.append(conn) - self._bmp_connection_selectors[conn.cabinet, conn.frame] =\ - FixedConnectionSelector(conn) + if self._bmp_connection is not None: + raise NotImplementedError( + "Only one BMP connection supported") + self._bmp_connection = conn + self._bmp_selector = FixedConnectionSelector(conn) # Otherwise, check if it can send and receive SCP (talk to SCAMP) elif isinstance(conn, SCAMPConnection): self._scamp_connections.append(conn) @@ -298,7 +298,7 @@ def __identify_connections(self, connections): # update the transceiver with the conn selectors. return MostDirectConnectionSelector(self._scamp_connections) - def __check_bmp_connections(self): + def __check_bmp_connection(self): """ Check that the BMP connections are actually connected to valid BMPs. @@ -306,13 +306,13 @@ def __check_bmp_connections(self): """ # check that the UDP BMP conn is actually connected to a BMP # via the sver command - for conn in self._bmp_connections: + if self._bmp_connection is not None: + conn = self._bmp_connection # try to send a BMP sver to check if it responds as expected try: version_info = self._get_scamp_version( - conn.chip_x, conn.chip_y, - self._bmp_connection_selectors[conn.cabinet, conn.frame]) + conn.chip_x, conn.chip_y, self._bmp_selector) fail_version_name = version_info.name != _BMP_NAME fail_version_num = \ version_info.version_number[0] not in _BMP_MAJOR_VERSIONS @@ -670,7 +670,7 @@ def ensure_board_is_ready(self, n_retries=5, extra_boot_values=None): INITIAL_FIND_SCAMP_RETRIES_COUNT, extra_boot_values) # If we fail to get a SCAMP version this time, try other things - if version_info is None and self._bmp_connections: + if version_info is None and self._bmp_connection is not None: # start by powering up each BMP connection logger.info("Attempting to power on machine") @@ -1053,25 +1053,19 @@ def _power_on_machine(self): :rtype bool :return success of failure to power on machine """ - if not self._bmp_connections: + if self._bmp_connection is None: logger.warning("No BMP connections, so can't power on") return False - for bmp_connection in self._bmp_connections: - self.power_on(bmp_connection.boards, bmp_connection.cabinet, - bmp_connection.frame) + self.power_on(self._bmp_connection) return True - def power_on(self, boards=0, cabinet=0, frame=0): + def power_on(self, boards=0): """ Power on a set of boards in the machine. :param int boards: The board or boards to power on - :param int cabinet: the ID of the cabinet containing the frame, or 0 - if the frame is not in a cabinet - :param int frame: the ID of the frame in the cabinet containing the - board(s), or 0 if the board is not in a frame """ - self._power(PowerCommand.POWER_ON, boards, cabinet, frame) + self._power(PowerCommand.POWER_ON, boards) def power_off_machine(self): """ @@ -1080,52 +1074,29 @@ def power_off_machine(self): :rtype bool :return success or failure to power off the machine """ - if not self._bmp_connections: + if self._bmp_connection is None: logger.warning("No BMP connections, so can't power off") return False logger.info("Turning off machine") - for bmp_connection in self._bmp_connections: - self.power_off(bmp_connection.boards, bmp_connection.cabinet, - bmp_connection.frame) + self.power_off(self._bmp_connection) return True - def power_off(self, boards=0, cabinet=0, frame=0): + def power_off(self, boards=0): """ Power off a set of boards in the machine. :param int boards: The board or boards to power off - :param int cabinet: the ID of the cabinet containing the frame, or 0 - if the frame is not in a cabinet - :param int frame: the ID of the frame in the cabinet containing the - board(s), or 0 if the board is not in a frame """ - self._power(PowerCommand.POWER_OFF, boards, cabinet, frame) + self._power(PowerCommand.POWER_OFF, boards) - def _bmp_connection(self, cabinet, frame): - """ - :param int cabinet: - :param int frame: - :rtype: FixedConnectionSelector - """ - key = (cabinet, frame) - if key not in self._bmp_connection_selectors: - raise SpinnmanInvalidParameterException( - "cabinet and frame", f"{cabinet} and {frame}", - "Unknown combination") - return self._bmp_connection_selectors[key] - - def _power(self, power_command, boards=0, cabinet=0, frame=0): + def _power(self, power_command, boards=0): """ Send a power request to the machine. :param PowerCommand power_command: The power command to send :param boards: The board or boards to send the command to - :param int cabinet: the ID of the cabinet containing the frame, or 0 - if the frame is not in a cabinet - :param int frame: the ID of the frame in the cabinet containing the - board(s), or 0 if the board is not in a frame """ - connection_selector = self._bmp_connection(cabinet, frame) + connection_selector = self._bmp_selector timeout = ( BMP_POWER_ON_TIMEOUT if power_command == PowerCommand.POWER_ON @@ -1139,7 +1110,8 @@ def _power(self, power_command, boards=0, cabinet=0, frame=0): if not self._machine_off: time.sleep(BMP_POST_POWER_ON_SLEEP_TIME) - def read_fpga_register(self, fpga_num, register, cabinet, frame, board): + def read_fpga_register( + self, fpga_num, register, board=0): """ Read a register on a FPGA of a board. The meaning of the register's contents will depend on the FPGA's configuration. @@ -1148,20 +1120,16 @@ def read_fpga_register(self, fpga_num, register, cabinet, frame, board): :param int register: Register address to read to (will be rounded down to the nearest 32-bit word boundary). - :param int cabinet: cabinet: the cabinet this is targeting - :param int frame: the frame this is targeting :param int board: which board to request the FPGA register from :return: the register data :rtype: int """ - process = SendSingleCommandProcess( - self._bmp_connection(cabinet, frame), timeout=1.0) + process = SendSingleCommandProcess(self._bmp_selector, timeout=1.0) response = process.execute( ReadFPGARegister(fpga_num, register, board)) return response.fpga_register # pylint: disable=no-member - def write_fpga_register(self, fpga_num, register, value, cabinet, frame, - board): + def write_fpga_register(self, fpga_num, register, value, board=0): """ Write a register on a FPGA of a board. The meaning of setting the register's contents will depend on the FPGA's configuration. @@ -1171,26 +1139,20 @@ def write_fpga_register(self, fpga_num, register, value, cabinet, frame, Register address to read to (will be rounded down to the nearest 32-bit word boundary). :param int value: the value to write into the FPGA register - :param int cabinet: cabinet: the cabinet this is targeting - :param int frame: the frame this is targeting :param int board: which board to write the FPGA register to """ - process = SendSingleCommandProcess( - self._bmp_connection(cabinet, frame)) + process = SendSingleCommandProcess(self._bmp_selector) process.execute( WriteFPGARegister(fpga_num, register, value, board)) - def read_bmp_version(self, board, cabinet, frame): + def read_bmp_version(self, board): """ Read the BMP version. - :param int cabinet: cabinet: the cabinet this is targeting - :param int frame: the frame this is targeting :param int board: which board to request the data from :return: the sver from the BMP """ - process = SendSingleCommandProcess( - self._bmp_connection(cabinet, frame)) + process = SendSingleCommandProcess(self._bmp_selector) response = process.execute(BMPGetVersion(board)) return response.version_info # pylint: disable=no-member @@ -1975,7 +1937,7 @@ def close(self): """ Close the transceiver and any threads that are running. """ - if self._bmp_connections: + if self._bmp_connection is not None: if get_config_bool("Machine", "turn_off_machine"): self.power_off_machine() diff --git a/spinnman/utilities/utility_functions.py b/spinnman/utilities/utility_functions.py index 31320dcbc..014b670c5 100644 --- a/spinnman/utilities/utility_functions.py +++ b/spinnman/utilities/utility_functions.py @@ -50,7 +50,7 @@ def work_out_bmp_from_machine_details(hostname, number_of_boards): board_range = range(number_of_boards) # Assume a single board with no cabinet or frame specified - return BMPConnectionData(cabinet=0, frame=0, ip_address=bmp_ip_address, + return BMPConnectionData(ip_address=bmp_ip_address, boards=board_range, port_num=SCP_SCAMP_PORT) diff --git a/unittests/connection_tests/test_udp_connection.py b/unittests/connection_tests/test_udp_connection.py index d3ce2663e..3aedd39b4 100644 --- a/unittests/connection_tests/test_udp_connection.py +++ b/unittests/connection_tests/test_udp_connection.py @@ -22,7 +22,6 @@ from spinnman.board_test_configuration import BoardTestConfiguration - class TestUDPConnection(unittest.TestCase): def setUp(self): diff --git a/unittests/model_tests/test_iptag_model.py b/unittests/model_tests/test_iptag_model.py index c45b9fc49..e870b6424 100644 --- a/unittests/model_tests/test_iptag_model.py +++ b/unittests/model_tests/test_iptag_model.py @@ -18,7 +18,6 @@ from spinnman.config_setup import unittest_setup - class TestIptag(unittest.TestCase): def setUp(self): diff --git a/unittests/test_transceiver.py b/unittests/test_transceiver.py index 2926f314e..6cee5bde8 100644 --- a/unittests/test_transceiver.py +++ b/unittests/test_transceiver.py @@ -65,10 +65,8 @@ class MockExtendedTransceiver(MockWriteTransceiver, ExtendedTransceiver): class TestTransceiver(unittest.TestCase): - def setUp(self): unittest_setup() - set_config("Machine", "version", 5) self.board_config = BoardTestConfiguration() def test_create_new_transceiver_to_board(self): @@ -132,6 +130,7 @@ def test_boot_board(self): trans._boot_board() def test_set_watch_dog(self): + set_config("Machine", "version", 5) connections = [] connections.append(SCAMPConnection(remote_host=None)) tx = MockExtendedTransceiver(version=5, connections=connections)