• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

SpiNNakerManchester / SpiNNMan / 6574804013

19 Oct 2023 12:47PM UTC coverage: 51.937% (+1.2%) from 50.777%
6574804013

Pull #327

github

Christian-B
typing changes
Pull Request #327: Type Annotations and Checking

105 of 1288 branches covered (0.0%)

Branch coverage included in aggregate %.

2375 of 2375 new or added lines in 180 files covered. (100.0%)

4775 of 8108 relevant lines covered (58.89%)

0.59 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

83.04
/spinnman/model/cpu_info.py
1
# Copyright (c) 2014 The University of Manchester
2
#
3
# Licensed under the Apache License, Version 2.0 (the "License");
4
# you may not use this file except in compliance with the License.
5
# You may obtain a copy of the License at
6
#
7
#     https://www.apache.org/licenses/LICENSE-2.0
8
#
9
# Unless required by applicable law or agreed to in writing, software
10
# distributed under the License is distributed on an "AS IS" BASIS,
11
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
# See the License for the specific language governing permissions and
13
# limitations under the License.
14

15
import struct
1✔
16
from typing import Sequence, Tuple
1✔
17
from typing_extensions import TypeAlias
1✔
18
from spinnman.model.enums import CPUState, RunTimeError, MailboxCommand
1✔
19

20
#: Size of `vcpu_t` in SARK.
21
CPU_INFO_BYTES = 128
1✔
22
CPU_USER_0_START_ADDRESS = 112
1✔
23
#: Offset into data of byte of processor state field.
24
STATE_FIELD_OFFSET = 48
1✔
25

26
#: Corresponds to vcpu_t in sark.h
27
_VCPU_PATTERN = struct.Struct("< 32s 3I 2B 2B 2I 2B H 3I 16s 2I 16x 4I")
1✔
28
_vcpu_t: TypeAlias = Tuple[
1✔
29
    bytes,             # 32s - r0-r7
30
    int, int, int,     # 3I  - psr, sp, lr
31
    int, int,          # 2B  - RT error code, Physical CPU
32
    int, int,          # 2B  - CPU state, Application ID
33
    int, int,          # 2I  - mbox msg MP->AP, mbox msg AP->MP
34
    int, int,          # 2B  - mbox command MP->AP, mbox command AP->MP
35
    int,               # H   - SW error count (saturating)
36
    int, int, int,     # 3I  - SW source filename, Source line, Time of loading
37
    bytes,             # 16s - Application name
38
    int, int,          # 2I  - IO buffer in SDRAM (or 0)
39
    #                    16x - Padding
40
    int, int, int, int]  # 4I- User0, User1, User2, User3
41
_REGISTERS_PATTERN = struct.Struct("<IIIIIIII")
1✔
42

43

44
class CPUInfo(object):
1✔
45
    """
46
    Represents information about the state of a CPU.
47

48
    This is the content of the `vcpu_t` for the processor, maintained by SARK.
49
    """
50
    __slots__ = [
1✔
51
        "__application_id",
52
        "__application_mailbox_command",
53
        "__app_mailbox",
54
        "__application_name",
55
        "__iobuf_address",
56
        "__link_register",
57
        "__monitor_mailbox_command",
58
        "__monitor_mailbox",
59
        "__physical_cpu_id",
60
        "__processor_state_register",
61
        "__registers",
62
        "__run_time_error",
63
        "__software_error_count",
64
        "__filename_address",
65
        "__line_number",
66
        "__software_version",
67
        "__stack_pointer",
68
        "__state",
69
        "__time",
70
        "__user",
71
        "__x", "__y", "__p"]
72

73
    def __init__(self, x: int, y: int, p: int, cpu_data: _vcpu_t):
1✔
74
        """
75
        :param int x: The x-coordinate of a chip
76
        :param int y: The y-coordinate of a chip
77
        :param int p: The ID of a core on the chip
78
        :param tuple cpu_data: A byte-string received from SDRAM on the board
79
        """
80
        # pylint: disable=too-many-arguments
81
        self.__x, self.__y, self.__p = x, y, p
1✔
82

83
        (registers,  # 32s 0
1✔
84
         self.__processor_state_register, self.__stack_pointer,
85
         self.__link_register,  run_time_error,
86
         self.__physical_cpu_id,  # 2B  44
87
         state, self.__application_id,  # 2B  46
88
         self.__app_mailbox, self.__monitor_mailbox,  # 2I  48
89
         app_mailbox_cmd, mon_mailbox_cmd,  # 2B  56
90
         self.__software_error_count,  # H   58
91
         self.__filename_address, self.__line_number, self.__time,  # 3I  60
92
         app_name,  # 16s 72
93
         self.__iobuf_address, self.__software_version,  # 2I  88
94
         # skipped                                                  # 16x 96
95
         user0, user1, user2, user3                                 # 4I  112
96
         ) = cpu_data
97

98
        index = app_name.find(b'\0')
1✔
99
        if index != -1:
1!
100
            app_name = app_name[:index]
1✔
101
        self.__application_name = app_name.decode('ascii')
1✔
102

103
        self.__registers: Sequence[int] = _REGISTERS_PATTERN.unpack(registers)
1✔
104
        self.__run_time_error = RunTimeError(run_time_error)
1✔
105
        self.__state = CPUState(state)
1✔
106

107
        self.__application_mailbox_command = MailboxCommand(app_mailbox_cmd)
1✔
108
        self.__monitor_mailbox_command = MailboxCommand(mon_mailbox_cmd)
1✔
109
        self.__user = (user0, user1, user2, user3)
1✔
110

111
    @property
1✔
112
    def x(self) -> int:
1✔
113
        """
114
        The X-coordinate of the chip containing the core.
115

116
        :return: The x-coordinate of the chip
117
        :rtype: int
118
        """
119
        return self.__x
1✔
120

121
    @property
1✔
122
    def y(self) -> int:
1✔
123
        """
124
        The y-coordinate of the chip containing the core.
125

126
        :return: The y-coordinate of the chip
127
        :rtype: int
128
        """
129
        return self.__y
1✔
130

131
    @property
1✔
132
    def p(self) -> int:
1✔
133
        """
134
        The ID of the core on the chip.
135

136
        :return: The ID of the core
137
        :rtype: int
138
        """
139
        return self.__p
1✔
140

141
    @property
1✔
142
    def state(self) -> CPUState:
1✔
143
        """
144
        The current state of the core.
145

146
        :return: The state of the core
147
        :rtype: CPUState
148
        """
149
        return self.__state
1✔
150

151
    @property
1✔
152
    def physical_cpu_id(self) -> int:
1✔
153
        """
154
        The physical ID of this processor.
155

156
        :return: The physical ID of the processor
157
        :rtype: int
158
        """
159
        return self.__physical_cpu_id
1✔
160

161
    @property
1✔
162
    def application_name(self) -> str:
1✔
163
        """
164
        The name of the application running on the core.
165

166
        :return: The name of the application
167
        :rtype: str
168
        """
169
        return self.__application_name
×
170

171
    @property
1✔
172
    def application_id(self) -> int:
1✔
173
        """
174
        The ID of the application running on the core.
175

176
        :return: The ID of the application
177
        :rtype: int
178
        """
179
        return self.__application_id
×
180

181
    @property
1✔
182
    def time(self) -> int:
1✔
183
        """
184
        The time at which the application started.
185

186
        :return: The time in seconds since 00:00:00 on the 1st January 1970
187
        :rtype: int
188
        """
189
        return self.__time
×
190

191
    @property
1✔
192
    def run_time_error(self) -> RunTimeError:
1✔
193
        """
194
        The reason for a run time error.
195

196
        :return: The run time error
197
        :rtype: RunTimeError
198
        """
199
        return self.__run_time_error
×
200

201
    @property
1✔
202
    def application_mailbox_command(self) -> MailboxCommand:
1✔
203
        """
204
        The command currently in the mailbox being sent from the monitor
205
        processor to the application.
206

207
        :return: The command
208
        :rtype: MailboxCommand
209
        """
210
        return self.__application_mailbox_command
×
211

212
    @property
1✔
213
    def application_mailbox_data_address(self) -> int:
1✔
214
        """
215
        The address of the data in SDRAM for the application mailbox.
216

217
        :return: The address of the data
218
        :rtype: int
219
        """
220
        return self.__app_mailbox
×
221

222
    @property
1✔
223
    def monitor_mailbox_command(self) -> MailboxCommand:
1✔
224
        """
225
        The command currently in the mailbox being sent from the
226
        application to the monitor processor.
227

228
        :return: The command
229
        :rtype: MailboxCommand
230
        """
231
        return self.__monitor_mailbox_command
×
232

233
    @property
1✔
234
    def monitor_mailbox_data_address(self) -> int:
1✔
235
        """
236
        The address of the data in SDRAM of the monitor mailbox.
237

238
        :return: The address of the data
239
        :rtype: int
240
        """
241
        return self.__monitor_mailbox
×
242

243
    @property
1✔
244
    def software_error_count(self) -> int:
1✔
245
        """
246
        The number of software errors counted. Saturating.
247

248
        :return: The number of software errors
249
        :rtype: int
250
        """
251
        return self.__software_error_count
×
252

253
    @property
1✔
254
    def software_source_filename_address(self) -> int:
1✔
255
        """
256
        The address of the filename of the software source.
257

258
        :return: The filename address
259
        :rtype: int
260
        """
261
        return self.__filename_address
×
262

263
    @property
1✔
264
    def software_source_line_number(self) -> int:
1✔
265
        """
266
        The line number of the software source.
267

268
        :return: The line number
269
        :rtype: int
270
        """
271
        return self.__line_number
×
272

273
    @property
1✔
274
    def processor_state_register(self) -> int:
1✔
275
        """
276
        The value in the processor state register.
277

278
        :return: The processor state register value
279
        :rtype: int
280
        """
281
        return self.__processor_state_register
×
282

283
    @property
1✔
284
    def stack_pointer(self) -> int:
1✔
285
        """
286
        The current stack pointer value.
287

288
        :return: The stack pointer value
289
        :rtype: int
290
        """
291
        return self.__stack_pointer
×
292

293
    @property
1✔
294
    def link_register(self) -> int:
1✔
295
        """
296
        The current link register value.
297

298
        :return: The link register value
299
        :rtype: int
300
        """
301
        return self.__link_register
×
302

303
    @property
1✔
304
    def registers(self) -> Sequence[int]:
1✔
305
        """
306
        The current register values (r0 - r7).
307

308
        :return: An array of 8 values, one for each register
309
        :rtype: list(int)
310
        """
311
        return self.__registers
×
312

313
    @property
1✔
314
    def user(self) -> Sequence[int]:
1✔
315
        """
316
        The current user values (user0 - user3).
317

318
        :return: An array of 4 values, one for each user value
319
        :rtype: list(int)
320
        """
321
        return self.__user
×
322

323
    @property
1✔
324
    def iobuf_address(self) -> int:
1✔
325
        """
326
        The address of the IOBUF buffer in SDRAM.
327

328
        :return: The address
329
        :rtype: int
330
        """
331
        return self.__iobuf_address
×
332

333
    @property
1✔
334
    def software_version(self) -> int:
1✔
335
        """
336
        The software version.
337

338
        :return: The software version
339
        :rtype: int
340
        """
341
        return self.__software_version
×
342

343
    def __str__(self) -> str:
1✔
344
        return "{}:{}:{:02n} ({:02n}) {:18} {:16s} {:3n}".format(
1✔
345
            self.x, self.y, self.p, self.physical_cpu_id, self.__state.name,
346
            self.__application_name, self.__application_id)
347

348
    def get_status_string(self) -> str:
1✔
349
        """
350
        Get a string indicating the status of the given core.
351

352
        :rtype: str
353
        """
354
        if self.state == CPUState.RUN_TIME_EXCEPTION:
1✔
355
            return (
1✔
356
                f"{self.__x}:{self.__y}:{self.__p} "
357
                f"(ph: {self.__physical_cpu_id}) "
358
                f"in state {self.__state.name}:{self.__run_time_error.name}\n"
359
                f"    r0={self.__registers[0]}, r1={self.__registers[1]}, "
360
                f"r2={self.__registers[2]}, r3={self.__registers[3]}\n"
361
                f"    r4={self.__registers[4]}, r5={self.__registers[5]}, "
362
                f"r6={self.__registers[6]}, r7={self.__registers[7]}\n"
363
                f"    PSR={self.__processor_state_register}, "
364
                f"SP={self.__stack_pointer}, LR={self.__link_register}\n")
365
        else:
366
            return (
1✔
367
                f"{self.__x}:{self.__y}:{self.__p} "
368
                f"in state {self.__state.name}\n")
369

370
    @staticmethod
1✔
371
    def mock_info(
1✔
372
            x: int, y: int, p: int, physical_cpu_id: int, state: CPUState):
373
        """
374
        Makes a CPU_info object for Testing purposes
375

376
        :param int x:
377
        :param int y:
378
        :param int p:
379
        :param int physical_cpu_id:
380
        :param CPUState CPIstate:
381
        """
382
        registers = b'@\x00\x07\x08\xff\x00\x00\x00\x00\x00\x80\x00\xad\x00' \
1✔
383
                    b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' \
384
                    b'\x00\x00\x00\x00\x00'
385
        time = 1687857627
1✔
386
        application_name = b'scamp-3\x00\x00\x00\x00\x00\x00\x00\x00\x00'
1✔
387
        iobuff_address = 197634
1✔
388
        cpu_data = (
1✔
389
            registers, 0, 0, 0, 0, physical_cpu_id, state.value, 0, 0, 0, 0,
390
            0, 0, 0, 0, time, application_name, iobuff_address, 0, 0, 0, 0, 0)
391
        return CPUInfo(x, y, p, cpu_data)
1✔
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc