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

SpiNNakerManchester / JavaSpiNNaker / 6233274834

19 Sep 2023 08:46AM UTC coverage: 36.409% (-0.6%) from 36.982%
6233274834

Pull #658

github

dkfellows
Merge branch 'master' into java-17
Pull Request #658: Update Java version to 17

1656 of 1656 new or added lines in 260 files covered. (100.0%)

8373 of 22997 relevant lines covered (36.41%)

0.36 hits per line

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

0.0
/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/transceiver/GetMachineProcess.java
1
/*
2
 * Copyright (c) 2018 The University of Manchester
3
 *
4
 * Licensed under the Apache License, Version 2.0 (the "License");
5
 * you may not use this file except in compliance with the License.
6
 * You may obtain a copy of the License at
7
 *
8
 *     https://www.apache.org/licenses/LICENSE-2.0
9
 *
10
 * Unless required by applicable law or agreed to in writing, software
11
 * distributed under the License is distributed on an "AS IS" BASIS,
12
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
 * See the License for the specific language governing permissions and
14
 * limitations under the License.
15
 */
16
package uk.ac.manchester.spinnaker.transceiver;
17

18
import static java.lang.Math.min;
19
import static java.util.Arrays.asList;
20
import static java.util.Collections.unmodifiableMap;
21
import static org.slf4j.LoggerFactory.getLogger;
22
import static uk.ac.manchester.spinnaker.messages.model.CPUState.IDLE;
23
import static uk.ac.manchester.spinnaker.messages.model.P2PTable.getColumnOffset;
24
import static uk.ac.manchester.spinnaker.messages.model.P2PTable.getNumColumnBytes;
25
import static uk.ac.manchester.spinnaker.transceiver.CommonMemoryLocations.ROUTER_P2P;
26
import static uk.ac.manchester.spinnaker.utils.CollectionUtils.range;
27

28
import java.io.IOException;
29
import java.nio.ByteBuffer;
30
import java.util.ArrayList;
31
import java.util.EnumSet;
32
import java.util.HashMap;
33
import java.util.List;
34
import java.util.Map;
35
import java.util.Set;
36

37
import org.slf4j.Logger;
38

39
import uk.ac.manchester.spinnaker.connections.ConnectionSelector;
40
import uk.ac.manchester.spinnaker.connections.SCPConnection;
41
import uk.ac.manchester.spinnaker.machine.Chip;
42
import uk.ac.manchester.spinnaker.machine.ChipLocation;
43
import uk.ac.manchester.spinnaker.machine.Direction;
44
import uk.ac.manchester.spinnaker.machine.HasChipLocation;
45
import uk.ac.manchester.spinnaker.machine.Link;
46
import uk.ac.manchester.spinnaker.machine.Machine;
47
import uk.ac.manchester.spinnaker.machine.MachineDimensions;
48
import uk.ac.manchester.spinnaker.machine.Processor;
49
import uk.ac.manchester.spinnaker.machine.Router;
50
import uk.ac.manchester.spinnaker.messages.model.ChipSummaryInfo;
51
import uk.ac.manchester.spinnaker.messages.model.P2PTable;
52
import uk.ac.manchester.spinnaker.messages.scp.GetChipInfo;
53
import uk.ac.manchester.spinnaker.messages.scp.ReadMemory;
54

55
/** A process for getting the machine details over a set of connections. */
56
final class GetMachineProcess extends TxrxProcess {
57
        private static final Logger log = getLogger(GetMachineProcess.class);
×
58

59
        /** A dictionary of (x, y) → ChipInfo. */
60
        private final Map<ChipLocation, ChipSummaryInfo> chipInfo;
61

62
        private final Set<ChipLocation> ignoreChips;
63

64
        private final Map<ChipLocation, Set<Integer>> ignoreCoresMap;
65

66
        private final Map<ChipLocation, EnumSet<Direction>> ignoreLinksMap;
67

68
        private final Integer maxSDRAMSize;
69

70
        private static <T> Set<T> def(Set<T> c) {
71
                return c == null ? Set.of() : c;
×
72
        }
73

74
        private static <K, V> Map<K, V> def(Map<K, V> m) {
75
                return m == null ? Map.of() : m;
×
76
        }
77

78
        private static int clamp(int value, Integer limit) {
79
                if (limit == null) {
×
80
                        return value;
×
81
                }
82
                return min(value, limit);
×
83
        }
84

85
        private static final int THROTTLED = 3;
86

87
        /**
88
         * @param connectionSelector
89
         *            How to talk to the machine.
90
         * @param ignoreChips
91
         *            The chip blacklist. Note that cores on this chip are also
92
         *            blacklisted, and links to and from this chip are also
93
         *            blacklisted.
94
         * @param ignoreCoresMap
95
         *            The core blacklist.
96
         * @param ignoreLinksMap
97
         *            The link blacklist.
98
         * @param maxSDRAMSize
99
         *            The maximum SDRAM size, or {@code null} for the system's
100
         *            standard limit. For debugging.
101
         * @param retryTracker
102
         *            Object used to track how many retries were used in an
103
         *            operation. May be {@code null} if no suck tracking is
104
         *            required.
105
         */
106
        GetMachineProcess(
107
                        ConnectionSelector<? extends SCPConnection> connectionSelector,
108
                        Set<ChipLocation> ignoreChips,
109
                        Map<ChipLocation, Set<Integer>> ignoreCoresMap,
110
                        Map<ChipLocation, EnumSet<Direction>> ignoreLinksMap,
111
                        Integer maxSDRAMSize, RetryTracker retryTracker) {
112
                super(connectionSelector, SCP_RETRIES, SCP_TIMEOUT, THROTTLED,
×
113
                                THROTTLED - 1, retryTracker);
114
                this.ignoreChips = def(ignoreChips);
×
115
                this.ignoreCoresMap = def(ignoreCoresMap);
×
116
                this.ignoreLinksMap = def(ignoreLinksMap);
×
117
                this.maxSDRAMSize = maxSDRAMSize;
×
118
                this.chipInfo = new HashMap<>();
×
119
        }
×
120

121
        /**
122
         * Get a full, booted machine, populated with information directly from the
123
         * physical hardware.
124
         *
125
         * @param bootChip
126
         *            Which chip is used to boot the machine.
127
         * @param size
128
         *            The dimensions of the machine.
129
         * @return The machine description.
130
         * @throws IOException
131
         *             If anything goes wrong with networking.
132
         * @throws ProcessException
133
         *             If SpiNNaker rejects a message.
134
         * @throws InterruptedException
135
         *             If the communications were interrupted.
136
         */
137
        Machine getMachineDetails(HasChipLocation bootChip, MachineDimensions size)
138
                        throws IOException, ProcessException, InterruptedException {
139
                // Get the P2P table; 8 entries are packed into each 32-bit word
140
                var p2pColumnData = new ByteBuffer[size.width()];
×
141
                int byteLength = getNumColumnBytes(size.height());
×
142
                for (int col : range(0, size.width())) {
×
143
                        sendGet(new ReadMemory(bootChip,
×
144
                                        ROUTER_P2P.add(getColumnOffset(col)), byteLength),
×
145
                                        bytes -> p2pColumnData[col] = bytes);
×
146
                }
×
147
                finishBatch();
×
148
                var p2pTable = new P2PTable(size, asList(p2pColumnData));
×
149

150
                // Get the chip information for each chip
151
                for (var chip : p2pTable.getChips()) {
×
152
                        sendGet(new GetChipInfo(chip), info -> chipInfo.put(chip, info));
×
153
                }
×
154
                try {
155
                        finishBatch();
×
156
                } catch (ProcessException ignored) {
×
157
                        /*
158
                         * Ignore errors from the SpiNNaker side, as any error here just
159
                         * means that a chip is down that wasn't marked as down
160
                         */
161
                }
×
162

163
                // Warn about unexpected missing chips
164
                for (var chip : p2pTable.getChips()) {
×
165
                        if (!chipInfo.containsKey(chip)) {
×
166
                                log.warn("Chip {},{} was expected but didn't reply",
×
167
                                                chip.getX(), chip.getY());
×
168
                        }
169
                }
×
170

171
                // Build a Machine
172
                var machine = new Machine(size, bootChip);
×
173
                chipInfo.forEach((chip, data) -> {
×
174
                        if (!ignoreChips.contains(chip)) {
×
175
                                machine.addChip(makeChip(size, data));
×
176
                        }
177
                });
×
178
                return machine;
×
179
        }
180

181
        /**
182
         * Creates a chip from a ChipSummaryInfo structure.
183
         *
184
         * @param size
185
         *            The size of the machine containing the chip.
186
         * @param chipInfo
187
         *            The ChipSummaryInfo structure to create the chip from.
188
         * @return The created chip.
189
         */
190
        private Chip makeChip(MachineDimensions size, ChipSummaryInfo chipInfo) {
191
                // Create the processor list
192
                var processors = new ArrayList<Processor>();
×
193
                var location = chipInfo.chip.asChipLocation();
×
194
                var ignoreCores = ignoreCoresMap.getOrDefault(location, Set.of());
×
195
                for (int id = 0; id < chipInfo.numCores; id++) {
×
196
                        // Add the core provided it is not to be ignored
197
                        if (ignoreCores != null && !ignoreCores.contains(id)) {
×
198
                                if (id == 0) {
×
199
                                        processors.add(Processor.factory(id, true));
×
200
                                } else if (chipInfo.coreStates.get(id) == IDLE) {
×
201
                                        processors.add(Processor.factory(id));
×
202
                                } else {
203
                                        log.warn("Not using core {},{},{} in state {}",
×
204
                                                        location.getX(), location.getY(), id,
×
205
                                                        chipInfo.coreStates.get(id));
×
206
                                }
207
                        }
208
                }
209

210
                // Create the chip
211
                List<Link> links;
212
                if (ignoreLinksMap.containsKey(location)) {
×
213
                        links = makeLinks(chipInfo, size, ignoreLinksMap.get(location));
×
214
                } else {
215
                        links = makeLinks(chipInfo, size);
×
216
                }
217
                return new Chip(location, processors,
×
218
                                new Router(links, chipInfo.numFreeMulticastRoutingEntries),
219
                                clamp(chipInfo.largestFreeSDRAMBlock, maxSDRAMSize),
×
220
                                chipInfo.ethernetIPAddress, chipInfo.nearestEthernetChip);
221
        }
222

223
        private List<Link> makeLinks(ChipSummaryInfo chipInfo,
224
                        MachineDimensions size, Set<Direction> ignoreLinks) {
225
                var chip = chipInfo.chip;
×
226
                var links = new ArrayList<Link>();
×
227
                for (var link : chipInfo.workingLinks) {
×
228
                        var dest = getChipOverLink(chip, size, link);
×
229
                        if (!ignoreLinks.contains(link) && !ignoreChips.contains(dest)
×
230
                                        && this.chipInfo.containsKey(dest)) {
×
231
                                links.add(new Link(chip, link, dest));
×
232
                        }
233
                }
×
234
                return links;
×
235
        }
236

237
        private List<Link> makeLinks(ChipSummaryInfo chipInfo,
238
                        MachineDimensions size) {
239
                var chip = chipInfo.chip;
×
240
                var links = new ArrayList<Link>();
×
241
                for (var link : chipInfo.workingLinks) {
×
242
                        var dest = getChipOverLink(chip, size, link);
×
243
                        if (!ignoreChips.contains(dest)
×
244
                                        && this.chipInfo.containsKey(dest)) {
×
245
                                links.add(new Link(chip, link, dest));
×
246
                        }
247
                }
×
248
                return links;
×
249
        }
250

251
        private static ChipLocation getChipOverLink(HasChipLocation chip,
252
                        MachineDimensions size, Direction link) {
253
                /// TODO CHECK negative wraparound!
254
                int x = (chip.getX() + link.xChange + size.width()) % size.width();
×
255
                int y = (chip.getY() + link.yChange + size.height()) % size.height();
×
256
                return new ChipLocation(x, y);
×
257
        }
258

259
        /**
260
         * Get the chip information for the machine. Note that
261
         * {@link #getMachineDetails(HasChipLocation,MachineDimensions)
262
         * getMachineDetails(...)} must have been called first.
263
         *
264
         * @return The description of what the state of each chip is.
265
         */
266
        Map<ChipLocation, ChipSummaryInfo> getChipInfo() {
267
                return unmodifiableMap(chipInfo);
×
268
        }
269
}
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

© 2026 Coveralls, Inc