Source code for spinnman.model.version_info
# Copyright (c) 2014 The University of Manchester
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# https://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
import re
import struct
from time import localtime, asctime
from typing import cast, Final, Tuple
from typing_extensions import TypeAlias
from spinnman.exceptions import SpinnmanInvalidParameterException
_VERSION_PATTERN = struct.Struct("<BBBBHHI")
_V: Final['TypeAlias'] = Tuple[int, int, int]
[docs]
class VersionInfo(object):
"""
Decodes SC&MP/SARK version information as returned by the SVER command.
"""
__slots__ = [
"_build_date",
"_hardware",
"_name",
"_physical_cpu_id",
"_version_number",
"_version_string",
"_x", "_y", "_p"]
def __init__(self, version_data: bytes, offset: int = 0):
"""
:param version_data:
bytes from an SCP packet containing version information
:param offset:
the offset in the bytes from an SCP packet containing
version information
:raise SpinnmanInvalidParameterException:
If the message does not contain valid version information
"""
(self._p, self._physical_cpu_id, self._y, self._x, _,
version_no, self._build_date) = _VERSION_PATTERN.unpack_from(
memoryview(version_data), offset)
version_str = version_data[offset + 12:-1].decode("utf-8")
self._version_number: _V
if version_no < 0xFFFF:
try:
self._version_number = (version_no // 100, version_no % 100, 0)
self._name, self._hardware = version_str.split("/")
self._version_string = version_str
except ValueError as exception:
raise SpinnmanInvalidParameterException(
"version_data", version_str,
f"Incorrect format: {exception}") from exception
else:
name_hardware, _, version = version_str.partition("\0")
self._version_string = version
matches = re.match(r"(\d+)\.(\d+)\.(\d+)", version)
if matches is None:
raise SpinnmanInvalidParameterException(
"version", version, "Cannot be parsed")
self._version_number = cast(_V, tuple(
map(int, matches.group(1, 2, 3))))
self._name, self._hardware = name_hardware.rstrip("\0").split("/")
@property
def name(self) -> str:
"""
The name of the software.
"""
return self._name
@property
def version_number(self) -> _V:
"""
The version number of the software.
"""
return self._version_number
@property
def hardware(self) -> str:
"""
The hardware being run on.
"""
return self._hardware
@property
def x(self) -> int:
"""
The X-coordinate of the chip where the information was obtained.
"""
return self._x
@property
def y(self) -> int:
"""
The Y-coordinate of the chip where the information was obtained.
"""
return self._y
@property
def p(self) -> int:
"""
The processor ID of the processor where the information was obtained.
"""
return self._p
@property
def build_date(self) -> int:
"""
The build date of the software, in seconds since 1st January 1970.
"""
return self._build_date
@property
def version_string(self) -> str:
"""
The version information as text.
"""
return self._version_string
def __str__(self) -> str:
return (f"[Version: {self._name} {self._version_string} at "
f"{self._hardware}:{self._x}:{self._y}:{self._p} "
f"(built {asctime(localtime(self._build_date))})]")