blob: b37eb588bc31599a15a25797f4ab4e6b92a6ae70 [file] [log] [blame]
Zane Shelleydd69c962020-05-05 22:19:11 -05001#include <chip_data/hei_chip_data.hpp>
2#include <chip_data/hei_chip_data_stream.hpp>
Zane Shelleyf8c92f92020-05-16 10:17:16 -05003#include <register/hei_operator_register.hpp>
Zane Shelleyb9a8e762020-05-11 21:41:32 -05004#include <register/hei_scom_register.hpp>
Zane Shelleydd69c962020-05-05 22:19:11 -05005
6namespace libhei
7{
8
9//------------------------------------------------------------------------------
10
Zane Shelleydd69c962020-05-05 22:19:11 -050011using SectionKeyword_t = uint32_t;
12
Zane Shelleyb9a8e762020-05-11 21:41:32 -050013constexpr SectionKeyword_t KW_REGS = 0x52454753; // "REGS" ASCII
Zane Shelleydd69c962020-05-05 22:19:11 -050014constexpr SectionKeyword_t KW_NODE = 0x4e4f4445; // "NODE" ASCII
15constexpr SectionKeyword_t KW_ROOT = 0x524f4f54; // "ROOT" ASCII
16
17using Version_t = uint8_t;
18
19constexpr Version_t VERSION_1 = 0x01;
Zane Shelley6b1fe162022-11-18 13:37:42 -060020constexpr Version_t VERSION_2 = 0x02;
Caleb Palmerf2a29322024-07-25 13:14:26 -050021constexpr Version_t VERSION_3 = 0x03;
Zane Shelleydd69c962020-05-05 22:19:11 -050022
23//------------------------------------------------------------------------------
24
Zane Shelley4de8ff82020-05-14 15:39:01 -050025void __readRegister(ChipDataStream& io_stream, IsolationChip::Ptr& io_isoChip)
Zane Shelleyb9a8e762020-05-11 21:41:32 -050026{
27 // Read the register metadata.
28 RegisterId_t id;
29 RegisterType_t type;
30 RegisterAttributeFlags_t attr;
31 Instance_t numInsts;
32 io_stream >> id >> type >> attr >> numInsts;
33
34 // Must have at least one instance.
35 HEI_ASSERT(0 != numInsts);
36
Zane Shelley0165edc2020-05-11 22:28:29 -050037 for (unsigned int i = 0; i < numInsts; i++)
Zane Shelleyb9a8e762020-05-11 21:41:32 -050038 {
39 // Read the register instance metadata.
40 Instance_t inst;
41 io_stream >> inst;
42
43 // The address size is dependent on the register type.
44 if (REG_TYPE_SCOM == type)
45 {
46 uint32_t addr; // 4-byte address.
47 io_stream >> addr;
48
49 // Get this register from the flyweight factory.
50 auto& factory = Flyweight<const ScomRegister>::getSingleton();
Patrick Williams2f7537d2023-05-10 07:51:39 -050051 auto hwReg = factory.get(id, inst, attr, addr);
Zane Shelleyb9a8e762020-05-11 21:41:32 -050052
53 // Add this register to the isolation chip.
54 io_isoChip->addHardwareRegister(hwReg);
55 }
56 else if (REG_TYPE_ID_SCOM == type)
57 {
58 uint64_t addr; // 8-byte address.
59 io_stream >> addr;
60
61 // Get this register from the flyweight factory.
62 auto& factory = Flyweight<const IdScomRegister>::getSingleton();
Patrick Williams2f7537d2023-05-10 07:51:39 -050063 auto hwReg = factory.get(id, inst, attr, addr);
Zane Shelleyb9a8e762020-05-11 21:41:32 -050064
65 // Add this register to the isolation chip.
66 io_isoChip->addHardwareRegister(hwReg);
67 }
68 else
69 {
70 HEI_ASSERT(false); // Register type unsupported.
71 }
72 }
73}
74
75//------------------------------------------------------------------------------
76
Zane Shelleyf8c92f92020-05-16 10:17:16 -050077Register::ConstPtr __readExpr(ChipDataStream& io_stream,
78 const IsolationChip::Ptr& i_isoChip,
79 IsolationNode::Ptr& io_isoNode)
Zane Shelley0165edc2020-05-11 22:28:29 -050080{
Zane Shelleyf8c92f92020-05-16 10:17:16 -050081 Register::ConstPtr expr{};
82
Zane Shelley0165edc2020-05-11 22:28:29 -050083 uint8_t exprType;
84 io_stream >> exprType;
85 switch (exprType)
86 {
87 case 0x01: // register reference
88 {
89 RegisterId_t regId;
90 Instance_t regInst;
91 io_stream >> regId >> regInst;
Zane Shelley6eb61902020-05-15 22:25:58 -050092
93 // Find the hardware register that is stored in this isolation chip
94 // and add it to the list of capture registers. This ensures all
95 // registers referenced in the rules are are captured by default.
96 // Note that this will assert that the target register must exist in
97 // the isolation chip.
98 auto hwReg = i_isoChip->getHardwareRegister({regId, regInst});
99
100 // Add the register to the isolation node.
101 io_isoNode->addCaptureRegister(hwReg);
102
Zane Shelleyf8c92f92020-05-16 10:17:16 -0500103 // Simply return this register.
104 expr = hwReg;
105
Zane Shelley0165edc2020-05-11 22:28:29 -0500106 break;
107 }
108 case 0x02: // integer constant
109 {
Zane Shelleyf8c92f92020-05-16 10:17:16 -0500110 auto& factory = Flyweight<const ConstantRegister>::getSingleton();
111
Zane Shelley6eb61902020-05-15 22:25:58 -0500112 if (REG_TYPE_SCOM == io_isoNode->getRegisterType() ||
113 REG_TYPE_ID_SCOM == io_isoNode->getRegisterType())
Zane Shelley0165edc2020-05-11 22:28:29 -0500114 {
115 uint64_t constant; // 8-byte value
116 io_stream >> constant;
Zane Shelleyf8c92f92020-05-16 10:17:16 -0500117
118 // Create the constant register and put it in the flyweights.
119 expr = factory.get(constant);
Zane Shelley0165edc2020-05-11 22:28:29 -0500120 }
121 else
122 {
123 HEI_ASSERT(false); // register type unsupported
124 }
Zane Shelleyf8c92f92020-05-16 10:17:16 -0500125
Zane Shelley0165edc2020-05-11 22:28:29 -0500126 break;
127 }
128 case 0x10: // AND operation
129 {
Zane Shelleyf8c92f92020-05-16 10:17:16 -0500130 auto& factory = Flyweight<const AndRegister>::getSingleton();
131
Zane Shelley0165edc2020-05-11 22:28:29 -0500132 uint8_t numSubExpr;
133 io_stream >> numSubExpr;
Zane Shelleyf8c92f92020-05-16 10:17:16 -0500134
135 HEI_ASSERT(2 <= numSubExpr); // must be at least two
136
137 // Read the first two sub-expressions.
138 auto e1 = __readExpr(io_stream, i_isoChip, io_isoNode);
139 auto e2 = __readExpr(io_stream, i_isoChip, io_isoNode);
140 HEI_ASSERT(e1 && e2); // Cannot be null
141
142 // Create the AND register and put it in the flyweights.
143 expr = factory.get(e1, e2);
144
145 // Iterate any remaining expressions.
146 for (uint8_t i = 2; i < numSubExpr; i++)
Zane Shelley0165edc2020-05-11 22:28:29 -0500147 {
Zane Shelleyf8c92f92020-05-16 10:17:16 -0500148 // Read the next sub-expressions.
149 e2 = __readExpr(io_stream, i_isoChip, io_isoNode);
150 HEI_ASSERT(e2); // Cannot be null
151
152 // Create the AND register and put it in the flyweights.
153 expr = factory.get(expr, e2);
Zane Shelley0165edc2020-05-11 22:28:29 -0500154 }
Zane Shelleyf8c92f92020-05-16 10:17:16 -0500155
Zane Shelley0165edc2020-05-11 22:28:29 -0500156 break;
157 }
158 case 0x11: // OR operation
159 {
Zane Shelleyf8c92f92020-05-16 10:17:16 -0500160 auto& factory = Flyweight<const OrRegister>::getSingleton();
161
Zane Shelley0165edc2020-05-11 22:28:29 -0500162 uint8_t numSubExpr;
163 io_stream >> numSubExpr;
Zane Shelleyf8c92f92020-05-16 10:17:16 -0500164
165 HEI_ASSERT(2 <= numSubExpr); // must be at least two
166
167 // Read the first two sub-expressions.
168 auto e1 = __readExpr(io_stream, i_isoChip, io_isoNode);
169 auto e2 = __readExpr(io_stream, i_isoChip, io_isoNode);
170 HEI_ASSERT(e1 && e2); // Cannot be null
171
172 // Create the OR register and put it in the flyweights.
173 expr = factory.get(e1, e2);
174
175 // Iterate any remaining expressions.
176 for (uint8_t i = 2; i < numSubExpr; i++)
Zane Shelley0165edc2020-05-11 22:28:29 -0500177 {
Zane Shelleyf8c92f92020-05-16 10:17:16 -0500178 // Read the next sub-expressions.
179 e2 = __readExpr(io_stream, i_isoChip, io_isoNode);
180 HEI_ASSERT(e2); // Cannot be null
181
182 // Create the OR register and put it in the flyweights.
183 expr = factory.get(expr, e2);
Zane Shelley0165edc2020-05-11 22:28:29 -0500184 }
Zane Shelleyf8c92f92020-05-16 10:17:16 -0500185
Zane Shelley0165edc2020-05-11 22:28:29 -0500186 break;
187 }
188 case 0x12: // NOT operation
189 {
Zane Shelleyf8c92f92020-05-16 10:17:16 -0500190 auto& factory = Flyweight<const NotRegister>::getSingleton();
191
192 // Read the sub-expression
193 auto e = __readExpr(io_stream, i_isoChip, io_isoNode);
194 HEI_ASSERT(e); // Cannot be null
195
196 // Create the NOT register and put it in the flyweights.
197 expr = factory.get(e);
198
Zane Shelley0165edc2020-05-11 22:28:29 -0500199 break;
200 }
201 case 0x13: // left shift operation
202 {
Zane Shelleyf8c92f92020-05-16 10:17:16 -0500203 auto& factory = Flyweight<const LeftShiftRegister>::getSingleton();
204
Zane Shelley0165edc2020-05-11 22:28:29 -0500205 uint8_t shiftValue;
206 io_stream >> shiftValue;
Zane Shelleyf8c92f92020-05-16 10:17:16 -0500207
208 // Read the sub-expression
209 auto e = __readExpr(io_stream, i_isoChip, io_isoNode);
210 HEI_ASSERT(e); // Cannot be null
211
212 // Create the left shift register and put it in the flyweights.
213 expr = factory.get(e, shiftValue);
214
Zane Shelley0165edc2020-05-11 22:28:29 -0500215 break;
216 }
217 case 0x14: // right shift operation
218 {
Zane Shelleyf8c92f92020-05-16 10:17:16 -0500219 auto& factory = Flyweight<const RightShiftRegister>::getSingleton();
220
Zane Shelley0165edc2020-05-11 22:28:29 -0500221 uint8_t shiftValue;
222 io_stream >> shiftValue;
Zane Shelleyf8c92f92020-05-16 10:17:16 -0500223
224 // Read the sub-expression
225 auto e = __readExpr(io_stream, i_isoChip, io_isoNode);
226 HEI_ASSERT(e); // Cannot be null
227
228 // Create the right shift register and put it in the flyweights.
229 expr = factory.get(e, shiftValue);
230
Zane Shelley0165edc2020-05-11 22:28:29 -0500231 break;
232 }
233 default:
234 HEI_ASSERT(false); // unsupported expression type
235 }
Zane Shelleyf8c92f92020-05-16 10:17:16 -0500236
237 return expr;
Zane Shelley0165edc2020-05-11 22:28:29 -0500238}
239
240//------------------------------------------------------------------------------
241
Zane Shelleyf229d5f2020-05-17 21:13:41 -0500242using TmpChildNodeMap = std::map<BitPosition_t, IsolationNode::Key>;
Patrick Williams2f7537d2023-05-10 07:51:39 -0500243using TmpNodeData = std::pair<IsolationNode::Ptr, TmpChildNodeMap>;
244using TmpNodeMap = std::map<IsolationNode::Key, TmpNodeData>;
Zane Shelleyf229d5f2020-05-17 21:13:41 -0500245
246void __readNode(ChipDataStream& io_stream, const IsolationChip::Ptr& i_isoChip,
Zane Shelley6b1fe162022-11-18 13:37:42 -0600247 TmpNodeMap& io_tmpNodeMap, Version_t i_version)
Zane Shelley0165edc2020-05-11 22:28:29 -0500248{
249 // Read the node metadata.
250 NodeId_t nodeId;
251 RegisterType_t regType;
252 Instance_t numInsts;
253 io_stream >> nodeId >> regType >> numInsts;
254
Caleb Palmerf2a29322024-07-25 13:14:26 -0500255 // Version 3 and above: Read any write operations that exist.
256 std::map<OpRuleName_t, std::pair<OpRuleType_t, RegisterId_t>> opRules;
257 if (VERSION_3 <= i_version)
258 {
259 uint8_t numOpRules;
260 io_stream >> numOpRules;
261 for (unsigned int i = 0; i < numOpRules; i++)
262 {
263 OpRuleName_t opName;
264 OpRuleType_t opType;
265 RegisterId_t regId;
266 io_stream >> opName >> opType >> regId;
267
268 std::pair<OpRuleType_t, RegisterId_t> tmpPair = {opType, regId};
269 auto ret = opRules.emplace(opName, tmpPair);
270 HEI_ASSERT(ret.second || ret.first->second == tmpPair);
271 }
272 }
273
Zane Shelley0165edc2020-05-11 22:28:29 -0500274 for (unsigned int i = 0; i < numInsts; i++)
275 {
276 // Read the node instance metadata.
277 Instance_t nodeInst;
278 uint8_t numCapRegs, numIsoRules, numChildNodes;
279 io_stream >> nodeInst >> numCapRegs >> numIsoRules >> numChildNodes;
280
Zane Shelleybcb43952021-07-08 22:13:57 -0500281 // It is possible to have rules defined and no child nodes, However, if
282 // there are no rules defined (FFDC-only node), there should not be
283 // any child nodes defined.
284 HEI_ASSERT(0 != numIsoRules || 0 == numChildNodes);
Zane Shelley6eb61902020-05-15 22:25:58 -0500285
286 // Allocate memory for this isolation node.
Patrick Williams2f7537d2023-05-10 07:51:39 -0500287 auto isoNode = std::make_shared<IsolationNode>(nodeId, nodeInst,
288 regType);
Zane Shelley6eb61902020-05-15 22:25:58 -0500289
Zane Shelley0165edc2020-05-11 22:28:29 -0500290 // Add capture registers.
291 for (unsigned int j = 0; j < numCapRegs; j++)
292 {
Zane Shelley6eb61902020-05-15 22:25:58 -0500293 // Read the capture register metadata.
Zane Shelley0165edc2020-05-11 22:28:29 -0500294 RegisterId_t regId;
295 Instance_t regInst;
296 io_stream >> regId >> regInst;
Zane Shelley6eb61902020-05-15 22:25:58 -0500297
Zane Shelley6b1fe162022-11-18 13:37:42 -0600298 BitPosition_t bit = MAX_BIT_POSITION; // default all bits
299 if (VERSION_2 <= i_version)
300 {
301 io_stream >> bit;
302 }
303
Zane Shelley6eb61902020-05-15 22:25:58 -0500304 // Find the hardware register that is stored in this isolation chip
305 // and add it to the list of capture registers. Note that this will
306 // assert that the target register must exist in the isolation chip.
Zane Shelleyf229d5f2020-05-17 21:13:41 -0500307 auto hwReg = i_isoChip->getHardwareRegister({regId, regInst});
Zane Shelley6eb61902020-05-15 22:25:58 -0500308
309 // Add the register to the isolation node.
Zane Shelley6b1fe162022-11-18 13:37:42 -0600310 isoNode->addCaptureRegister(hwReg, bit);
Zane Shelley0165edc2020-05-11 22:28:29 -0500311 }
312
313 // Add isolation rules.
314 for (unsigned int j = 0; j < numIsoRules; j++)
315 {
Zane Shelley6eb61902020-05-15 22:25:58 -0500316 // Read the rule metadata.
Zane Shelley0165edc2020-05-11 22:28:29 -0500317 AttentionType_t attnType;
318 io_stream >> attnType;
Zane Shelleyf8c92f92020-05-16 10:17:16 -0500319
320 // Read out the rule for this attention type.
Zane Shelleyf229d5f2020-05-17 21:13:41 -0500321 auto rule = __readExpr(io_stream, i_isoChip, isoNode);
Zane Shelleyf8c92f92020-05-16 10:17:16 -0500322 HEI_ASSERT(rule); // Cannot be null
323
324 // Add the rule to the isolation node.
325 isoNode->addRule(attnType, rule);
Zane Shelley0165edc2020-05-11 22:28:29 -0500326 }
327
Zane Shelleyf229d5f2020-05-17 21:13:41 -0500328 // At this point, we will need to read out the child node metadata.
329 // However, we can't look up the child nodes and add them to this
330 // isolation node yet because we are still in the process of parsing
331 // them out of the Chip Data File. Therefore, we'll save a temporary map
332 // containing the child node information which will be used to look up
333 // the actual node objects later.
334 TmpChildNodeMap cMap{};
Zane Shelley0165edc2020-05-11 22:28:29 -0500335 for (unsigned int j = 0; j < numChildNodes; j++)
336 {
Zane Shelley6eb61902020-05-15 22:25:58 -0500337 // Read the child node metadata.
Zane Shelley0165edc2020-05-11 22:28:29 -0500338 BitPosition_t bit;
Zane Shelleyd0659242020-05-15 23:02:29 -0500339 NodeId_t childId;
340 Instance_t childInst;
341 io_stream >> bit >> childId >> childInst;
Zane Shelleyf229d5f2020-05-17 21:13:41 -0500342
Patrick Williams2f7537d2023-05-10 07:51:39 -0500343 auto ret = cMap.emplace(bit,
344 IsolationNode::Key{childId, childInst});
Zane Shelleyf229d5f2020-05-17 21:13:41 -0500345 HEI_ASSERT(ret.second); // Should not have duplicate entries
346 }
347
Caleb Palmerf2a29322024-07-25 13:14:26 -0500348 // Version 3 and above: Add any write operations to the isoNode.
349 if (VERSION_3 <= i_version)
350 {
351 for (const auto& rule : opRules)
352 {
353 isoNode->addOpRule(rule.first, rule.second.first,
354 rule.second.second);
355 }
356 }
357
Zane Shelleyf229d5f2020-05-17 21:13:41 -0500358 // Add this isolation node with the temporary child node map to the
359 // returned map of nodes.
360 auto ret = io_tmpNodeMap.emplace(IsolationNode::Key{nodeId, nodeInst},
361 TmpNodeData{isoNode, cMap});
362 HEI_ASSERT(ret.second); // Should not have duplicate entries
363 }
364}
365
366//------------------------------------------------------------------------------
367
368void __insertNodes(IsolationChip::Ptr& io_isoChip,
369 const TmpNodeMap& i_tmpNodeMap)
370{
371 for (const auto& n : i_tmpNodeMap)
372 {
Patrick Williams2f7537d2023-05-10 07:51:39 -0500373 const IsolationNode::Ptr& node = n.second.first;
Zane Shelleyf229d5f2020-05-17 21:13:41 -0500374 const TmpChildNodeMap& childMap = n.second.second;
375
376 // Link the child nodes, if they exist.
377 for (const auto& c : childMap)
378 {
Patrick Williams2f7537d2023-05-10 07:51:39 -0500379 const BitPosition_t& bit = c.first;
Zane Shelleyf229d5f2020-05-17 21:13:41 -0500380 const IsolationNode::Key& childKey = c.second;
381
382 // Find the child node in the temporary map.
383 auto itr = i_tmpNodeMap.find(childKey);
384 HEI_ASSERT(i_tmpNodeMap.end() != itr); // Child node must exist.
385
386 const IsolationNode::Ptr& child = itr->second.first;
387
388 node->addChild(bit, child);
Zane Shelley0165edc2020-05-11 22:28:29 -0500389 }
Zane Shelley6eb61902020-05-15 22:25:58 -0500390
391 // Add this node to the isolation chip.
Zane Shelleyf229d5f2020-05-17 21:13:41 -0500392 io_isoChip->addIsolationNode(node);
Zane Shelley0165edc2020-05-11 22:28:29 -0500393 }
394}
395
396//------------------------------------------------------------------------------
397
Zane Shelley4de8ff82020-05-14 15:39:01 -0500398void __readRoot(ChipDataStream& io_stream, IsolationChip::Ptr& io_isoChip)
Zane Shelley0165edc2020-05-11 22:28:29 -0500399{
Zane Shelley2467db82020-05-18 19:56:30 -0500400 // Read the root node metadata.
Zane Shelley0165edc2020-05-11 22:28:29 -0500401 AttentionType_t attnType;
402 NodeId_t id;
403 Instance_t inst;
404 io_stream >> attnType >> id >> inst;
Zane Shelley2467db82020-05-18 19:56:30 -0500405
406 // Add the root node.
407 io_isoChip->addRootNode(attnType, io_isoChip->getIsolationNode({id, inst}));
Zane Shelley0165edc2020-05-11 22:28:29 -0500408}
409
410//------------------------------------------------------------------------------
411
Zane Shelleydd69c962020-05-05 22:19:11 -0500412void parseChipDataFile(void* i_buffer, size_t i_bufferSize,
Zane Shelley4de8ff82020-05-14 15:39:01 -0500413 IsolationChip::Map& io_isoChips)
Zane Shelleydd69c962020-05-05 22:19:11 -0500414{
415 ChipDataStream stream{i_buffer, i_bufferSize};
416
417 // Read the file metadata.
Zane Shelleyb9a8e762020-05-11 21:41:32 -0500418 FileKeyword_t fileKeyword;
419 ChipType_t chipType;
420 Version_t version;
421 stream >> fileKeyword >> chipType >> version;
Zane Shelleydd69c962020-05-05 22:19:11 -0500422
Zane Shelleyb9a8e762020-05-11 21:41:32 -0500423 // Check the file keyword.
424 HEI_ASSERT(KW_CHIPDATA == fileKeyword);
Zane Shelleydd69c962020-05-05 22:19:11 -0500425
426 // This chip type should not already exist.
427 HEI_ASSERT(io_isoChips.end() == io_isoChips.find(chipType));
428
Zane Shelley6b1fe162022-11-18 13:37:42 -0600429 // Check supported versions.
Caleb Palmerf2a29322024-07-25 13:14:26 -0500430 HEI_ASSERT(VERSION_1 <= version && version <= VERSION_3);
Zane Shelleyb9a8e762020-05-11 21:41:32 -0500431
Zane Shelleydd69c962020-05-05 22:19:11 -0500432 // Allocate memory for the new isolation chip.
Zane Shelleyd5d23632022-12-13 09:34:31 -0600433 auto isoChip = std::make_shared<IsolationChip>(chipType);
Zane Shelleydd69c962020-05-05 22:19:11 -0500434
Zane Shelleyb9a8e762020-05-11 21:41:32 -0500435 // Read the register list metadata.
436 SectionKeyword_t regsKeyword;
437 RegisterId_t numRegs;
438 stream >> regsKeyword >> numRegs;
439
440 // Check the register keyword.
441 HEI_ASSERT(KW_REGS == regsKeyword);
442
443 // There must be at least one register defined.
444 HEI_ASSERT(0 != numRegs);
445
Zane Shelley0165edc2020-05-11 22:28:29 -0500446 for (unsigned int i = 0; i < numRegs; i++)
Zane Shelleyb9a8e762020-05-11 21:41:32 -0500447 {
448 __readRegister(stream, isoChip);
449 }
Zane Shelleydd69c962020-05-05 22:19:11 -0500450
Zane Shelley0165edc2020-05-11 22:28:29 -0500451 // Read the node list metadata.
452 SectionKeyword_t nodeKeyword;
453 NodeId_t numNodes;
454 stream >> nodeKeyword >> numNodes;
455
456 // Check the node keyword.
457 HEI_ASSERT(KW_NODE == nodeKeyword);
458
459 // There must be at least one node defined.
460 HEI_ASSERT(0 != numNodes);
461
Zane Shelleyf229d5f2020-05-17 21:13:41 -0500462 TmpNodeMap tmpNodeMap; // Stores all nodes with child node map.
Zane Shelley0165edc2020-05-11 22:28:29 -0500463 for (unsigned int i = 0; i < numNodes; i++)
464 {
Zane Shelley6b1fe162022-11-18 13:37:42 -0600465 __readNode(stream, isoChip, tmpNodeMap, version);
Zane Shelley0165edc2020-05-11 22:28:29 -0500466 }
Zane Shelleyf229d5f2020-05-17 21:13:41 -0500467 // Link all nodes with their child nodes. Then add them to isoChip.
468 __insertNodes(isoChip, tmpNodeMap);
Zane Shelley0165edc2020-05-11 22:28:29 -0500469
470 // Read the root node list metadata.
471 SectionKeyword_t rootKeyword;
472 AttentionType_t numRoots;
473 stream >> rootKeyword >> numRoots;
474
475 // Check the root node keyword.
476 HEI_ASSERT(KW_ROOT == rootKeyword);
477
478 // There must be at least one register defined.
479 HEI_ASSERT(0 != numRoots);
480
481 for (unsigned int i = 0; i < numRoots; i++)
482 {
483 __readRoot(stream, isoChip);
484 }
485
486 // At this point, the stream is done and it should be at the end of the
487 // file.
488 HEI_ASSERT(stream.eof());
489
Zane Shelleydd69c962020-05-05 22:19:11 -0500490 // Add this isolation chip to the collective list of isolation chips.
Zane Shelleyd5d23632022-12-13 09:34:31 -0600491 auto ret = io_isoChips.emplace(chipType, isoChip);
Zane Shelleydd69c962020-05-05 22:19:11 -0500492 HEI_ASSERT(ret.second); // Just in case.
493}
494
495//------------------------------------------------------------------------------
496
497} // namespace libhei