Skip to content

Commit

Permalink
Merge pull request #366 from SpiNNakerManchester/simplify_cpu_infos
Browse files Browse the repository at this point in the history
Hide CPUInfo object
  • Loading branch information
rowleya authored Oct 10, 2023
2 parents ba79621 + 0b79fce commit 5669a2a
Show file tree
Hide file tree
Showing 4 changed files with 108 additions and 91 deletions.
43 changes: 43 additions & 0 deletions spinnman/model/cpu_info.py
Original file line number Diff line number Diff line change
Expand Up @@ -329,3 +329,46 @@ def __str__(self):
return "{}:{}:{:02n} ({:02n}) {:18} {:16s} {:3n}".format(
self.x, self.y, self.p, self.physical_cpu_id, self._state.name,
self._application_name, self._application_id)

def get_status_string(self):
"""
Get a string indicating the status of the given core.
:rtype: str
"""
if self.state == CPUState.RUN_TIME_EXCEPTION:
return (
f"{self._x}:{self._y}:{self._p} "
f"(ph: {self._physical_cpu_id}) "
f"in state {self._state.name}:{self._run_time_error.name}\n"
f" r0={self._registers[0]}, r1={self._registers[1]}, "
f"r2={self._registers[2]}, r3={self._registers[3]}\n"
f" r4={self._registers[4]}, r5={self._registers[5]}, "
f"r6={self._registers[6]}, r7={self._registers[7]}\n"
f" PSR={self._processor_state_register}, "
f"SP={self._stack_pointer}, LR={self._link_register}\n")
else:
return (
f"{self._x}:{self._y}:{self._p} in state {self._state.name}\n")

@staticmethod
def mock_info(x, y, p, physical_cpu_id, state):
"""
Makes a CPU_info object for Testing purposes
:param int x:
:param int y:
:param int p:
:param int physical_cpu_id:
:param CPUState CPIstate:
"""
registers = b'@\x00\x07\x08\xff\x00\x00\x00\x00\x00\x80\x00\xad\x00' \
b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' \
b'\x00\x00\x00\x00\x00'
time = 1687857627
application_name = b'scamp-3\x00\x00\x00\x00\x00\x00\x00\x00\x00'
iobuff_address = 197634
cpu_data = (
registers, 0, 0, 0, 0, physical_cpu_id, state.value, 0, 0, 0, 0,
0, 0, 0, 0, time, application_name, iobuff_address, 0, 0, 0, 0, 0)
return CPUInfo(x, y, p, cpu_data)
80 changes: 14 additions & 66 deletions spinnman/model/cpu_infos.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,6 @@
# See the License for the specific language governing permissions and
# limitations under the License.

from spinnman.model.enums import CPUState


class CPUInfos(object):
"""
Expand All @@ -33,60 +31,25 @@ def add_info(self, cpu_info):
"""
self._cpu_infos[cpu_info.x, cpu_info.y, cpu_info.p] = cpu_info

def add_processor(self, x, y, processor_id, cpu_info):
"""
Add a info on a given core.
:param int x: The x-coordinate of the chip
:param int y: The y-coordinate of the chip
:param int processor_id: A processor ID
:param CPUInfo cpu_info:
The CPU information for the core.
Not checked so could be None at test own risk
def add_infos(self, other, states):
"""
self._cpu_infos[x, y, processor_id] = cpu_info
Adds all the infos in the other CPUInfos if the have one of the
required states
@property
def cpu_infos(self):
"""
The one per core core info.
mainly a support method for Transceiver.add_cpu_information_from_core
:return: iterable of x,y,p core info
:rtype: iterable(~spinnman.model.CPUInfo)
:param CPUInfos other: Another Infos object to merge in
:param list(~spinnman.model.enums.CPUState) states:
Only add if the Info has this state
"""
return iter(self._cpu_infos.items())
# pylint: disable=protected-access
for info in other._cpu_infos:
if info.state in states:
self.add_info(other)

def __iter__(self):
return iter(self._cpu_infos)

def iteritems(self):
"""
Get an iterable of (x, y, p), cpu_info.
:rtype: (iterable(tuple(int, int, int), ~spinnman.model.CPUInfo)
"""
return iter(self._cpu_infos.items())

def items(self):
return self._cpu_infos.items()

def values(self):
return self._cpu_infos.values()

def itervalues(self):
"""
Get an iterable of cpu_info.
"""
return iter(self._cpu_infos.items())

def keys(self):
return self._cpu_infos.keys()

def iterkeys(self):
"""
Get an iterable of (x, y, p).
"""
return iter(self._cpu_infos.keys())

def __len__(self):
"""
The total number of processors that are in these core subsets.
Expand Down Expand Up @@ -128,24 +91,9 @@ def get_status_string(self):
:param CPUInfos cpu_infos: A CPUInfos objects
:rtype: str
"""
break_down = "\n"
for (x, y, p), core_info in self.cpu_infos:
if core_info.state == CPUState.RUN_TIME_EXCEPTION:
break_down += " {}:{}:{} (ph: {}) in state {}:{}\n".format(
x, y, p, core_info.physical_cpu_id, core_info.state.name,
core_info.run_time_error.name)
break_down += " r0={}, r1={}, r2={}, r3={}\n".format(
core_info.registers[0], core_info.registers[1],
core_info.registers[2], core_info.registers[3])
break_down += " r4={}, r5={}, r6={}, r7={}\n".format(
core_info.registers[4], core_info.registers[5],
core_info.registers[6], core_info.registers[7])
break_down += " PSR={}, SP={}, LR={}\n".format(
core_info.processor_state_register,
core_info.stack_pointer, core_info.link_register)
else:
break_down += " {}:{}:{} in state {}\n".format(
x, y, p, core_info.state.name)
break_down = ""
for core_info in self._cpu_infos.values():
break_down += core_info.get_status_string()
return break_down

def __str__(self):
Expand Down
38 changes: 32 additions & 6 deletions spinnman/transceiver.py
Original file line number Diff line number Diff line change
Expand Up @@ -918,15 +918,18 @@ def read_user(self, x, y, p, user):
addr = self.__get_user_register_address_from_core(p, user)
return self.read_word(x, y, addr)

def get_cpu_information_from_core(self, x, y, p):
def add_cpu_information_from_core(self, cpu_infos, x, y, p, states):
"""
Get information about a specific processor on the board.
Adds information about a specific processor on the board to the info
:param CPUInfo cpu_infos: Info to add data for this core to
:param int x: The x-coordinate of the chip containing the processor
:param int y: The y-coordinate of the chip containing the processor
:param int p: The ID of the processor to get the information about
:param states:
If provided will only add the info if in one of the states
:type states: list(CPUState)
:return: The CPU information for the selected core
:rtype: CPUInfo
:raise SpinnmanIOException:
If there is an error communicating with the board
:raise SpinnmanInvalidPacketException:
Expand All @@ -939,8 +942,29 @@ def get_cpu_information_from_core(self, x, y, p):
"""
core_subsets = CoreSubsets()
core_subsets.add_processor(x, y, p)
cpu_infos = self.get_cpu_infos(core_subsets)
return cpu_infos.get_cpu_info(x, y, p)
new_infos = self.get_cpu_infos(core_subsets)
cpu_infos.add_infos(new_infos, states)

def get_region_base_address(self, x, y, p):
"""
Gets the base address of the Region Table
:param int x: The x-coordinate of the chip containing the processor
:param int y: The y-coordinate of the chip containing the processor
:param int p: The ID of the processor to get the address
:return: The adddress of the Region table for the selected core
:rtype: int
:raise SpinnmanIOException:
If there is an error communicating with the board
:raise SpinnmanInvalidPacketException:
If a packet is received that is not in the valid format
:raise SpinnmanInvalidParameterException:
* If x, y, p is not a valid processor
* If a packet is received that has invalid parameters
:raise SpinnmanUnexpectedResponseCodeException:
If a response indicates an error during the exchange
"""
return self.read_user(x, y, p, 0)

def get_iobuf(self, core_subsets=None):
"""
Expand Down Expand Up @@ -1425,6 +1449,8 @@ def wait_for_cores_to_be_in_state(
if tries >= counts_between_full_check:
cores_in_state = self.get_cpu_infos(
all_core_subsets, cpu_states, True)
# convert to a list of xyp values
cores_in_state_xyps = list(cores_in_state)
processors_ready = len(cores_in_state)
tries = 0

Expand All @@ -1434,7 +1460,7 @@ def wait_for_cores_to_be_in_state(
for core_subset in all_core_subsets.core_subsets:
for p in core_subset.processor_ids:
if ((core_subset.x, core_subset.y, p) not in
cores_in_state.keys()):
cores_in_state_xyps):
logger.warning(
"waiting on {}:{}:{}",
core_subset.x, core_subset.y, p)
Expand Down
38 changes: 19 additions & 19 deletions unittests/model_tests/test_cpu_infos.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,30 +23,20 @@ class TestCpuInfos(unittest.TestCase):
def setUp(self):
unittest_setup()

def make_info_data(self, physical_cpu_id, state):
registers = b'@\x00\x07\x08\xff\x00\x00\x00\x00\x00\x80\x00\xad\x00' \
b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' \
b'\x00\x00\x00\x00\x00'
time = 1687857627
application_name = b'scamp-3\x00\x00\x00\x00\x00\x00\x00\x00\x00'
iobuff_address = 197634
return (registers, 0, 0, 0, 0, physical_cpu_id, state.value, 0, 0, 0,
0, 0, 0, 0, 0, time, application_name, iobuff_address, 0, 0,
0, 0, 0)

def test_cpu_infos(self):
infos = CPUInfos()

info = CPUInfo(0, 0, 1, self.make_info_data(5, CPUState.RUNNING))
infos.add_info(info)
info = CPUInfo(0, 0, 2, self.make_info_data(6, CPUState.FINISHED))
infos.add_info(info)
info = CPUInfo(1, 0, 1, self.make_info_data(7, CPUState.FINISHED))
infos.add_info(info)
infos.add_info(CPUInfo.mock_info(0, 0, 1, 5, CPUState.RUNNING))
infos.add_info(CPUInfo.mock_info(0, 0, 2, 6, CPUState.FINISHED))
infos.add_info(CPUInfo.mock_info(1, 0, 1, 7, CPUState.FINISHED))
infos.add_info(CPUInfo.mock_info(
1, 1, 2, 4, CPUState.RUN_TIME_EXCEPTION))

self.assertSetEqual(set(infos),
{(1, 0, 1), (0, 0, 1), (0, 0, 2), (1, 1, 2)})
self.assertEqual(
"['0, 0, 1 (ph: 5)', '0, 0, 2 (ph: 6)', '1, 0, 1 (ph: 7)']",
str(infos))
"['0, 0, 1 (ph: 5)', '0, 0, 2 (ph: 6)', '1, 0, 1 (ph: 7)',"
" '1, 1, 2 (ph: 4)']", str(infos))

finished = infos.infos_for_state(CPUState.FINISHED)
self.assertEqual(
Expand All @@ -60,6 +50,16 @@ def test_cpu_infos(self):
self.assertEqual(
"0:0:02 (06) FINISHED scamp-3 0", str(info))

# the str is for example purpose and may change without notice
self.assertEqual(infos.get_status_string(),
"0:0:1 in state RUNNING\n"
"0:0:2 in state FINISHED\n"
"1:0:1 in state FINISHED\n"
"1:1:2 (ph: 4) in state RUN_TIME_EXCEPTION:NONE\n"
" r0=134676544, r1=255, r2=8388608, r3=173\n"
" r4=0, r5=0, r6=0, r7=0\n"
" PSR=0, SP=0, LR=0\n")


if __name__ == '__main__':
unittest.main()

0 comments on commit 5669a2a

Please sign in to comment.