blob: 8b7369682a6ffd2a0a7b8e8a0bb5690469b7b5a2 [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
11using FileKeyword_t = uint64_t;
12
13constexpr FileKeyword_t KW_CHIPDATA = 0x4348495044415441; // "CHIPDATA" ASCII
14
15using SectionKeyword_t = uint32_t;
16
Zane Shelleyb9a8e762020-05-11 21:41:32 -050017constexpr SectionKeyword_t KW_REGS = 0x52454753; // "REGS" ASCII
Zane Shelleydd69c962020-05-05 22:19:11 -050018constexpr SectionKeyword_t KW_NODE = 0x4e4f4445; // "NODE" ASCII
19constexpr SectionKeyword_t KW_ROOT = 0x524f4f54; // "ROOT" ASCII
20
21using Version_t = uint8_t;
22
23constexpr Version_t VERSION_1 = 0x01;
24
25//------------------------------------------------------------------------------
26
Zane Shelley4de8ff82020-05-14 15:39:01 -050027void __readRegister(ChipDataStream& io_stream, IsolationChip::Ptr& io_isoChip)
Zane Shelleyb9a8e762020-05-11 21:41:32 -050028{
29 // Read the register metadata.
30 RegisterId_t id;
31 RegisterType_t type;
32 RegisterAttributeFlags_t attr;
33 Instance_t numInsts;
34 io_stream >> id >> type >> attr >> numInsts;
35
36 // Must have at least one instance.
37 HEI_ASSERT(0 != numInsts);
38
Zane Shelley0165edc2020-05-11 22:28:29 -050039 for (unsigned int i = 0; i < numInsts; i++)
Zane Shelleyb9a8e762020-05-11 21:41:32 -050040 {
41 // Read the register instance metadata.
42 Instance_t inst;
43 io_stream >> inst;
44
45 // The address size is dependent on the register type.
46 if (REG_TYPE_SCOM == type)
47 {
48 uint32_t addr; // 4-byte address.
49 io_stream >> addr;
50
51 // Get this register from the flyweight factory.
52 auto& factory = Flyweight<const ScomRegister>::getSingleton();
Zane Shelley4de8ff82020-05-14 15:39:01 -050053 auto hwReg = factory.get(id, inst, attr, addr);
Zane Shelleyb9a8e762020-05-11 21:41:32 -050054
55 // Add this register to the isolation chip.
56 io_isoChip->addHardwareRegister(hwReg);
57 }
58 else if (REG_TYPE_ID_SCOM == type)
59 {
60 uint64_t addr; // 8-byte address.
61 io_stream >> addr;
62
63 // Get this register from the flyweight factory.
64 auto& factory = Flyweight<const IdScomRegister>::getSingleton();
Zane Shelley4de8ff82020-05-14 15:39:01 -050065 auto hwReg = factory.get(id, inst, attr, addr);
Zane Shelleyb9a8e762020-05-11 21:41:32 -050066
67 // Add this register to the isolation chip.
68 io_isoChip->addHardwareRegister(hwReg);
69 }
70 else
71 {
72 HEI_ASSERT(false); // Register type unsupported.
73 }
74 }
75}
76
77//------------------------------------------------------------------------------
78
Zane Shelleyf8c92f92020-05-16 10:17:16 -050079Register::ConstPtr __readExpr(ChipDataStream& io_stream,
80 const IsolationChip::Ptr& i_isoChip,
81 IsolationNode::Ptr& io_isoNode)
Zane Shelley0165edc2020-05-11 22:28:29 -050082{
Zane Shelleyf8c92f92020-05-16 10:17:16 -050083 Register::ConstPtr expr{};
84
Zane Shelley0165edc2020-05-11 22:28:29 -050085 uint8_t exprType;
86 io_stream >> exprType;
87 switch (exprType)
88 {
89 case 0x01: // register reference
90 {
91 RegisterId_t regId;
92 Instance_t regInst;
93 io_stream >> regId >> regInst;
Zane Shelley6eb61902020-05-15 22:25:58 -050094
95 // Find the hardware register that is stored in this isolation chip
96 // and add it to the list of capture registers. This ensures all
97 // registers referenced in the rules are are captured by default.
98 // Note that this will assert that the target register must exist in
99 // the isolation chip.
100 auto hwReg = i_isoChip->getHardwareRegister({regId, regInst});
101
102 // Add the register to the isolation node.
103 io_isoNode->addCaptureRegister(hwReg);
104
Zane Shelleyf8c92f92020-05-16 10:17:16 -0500105 // Simply return this register.
106 expr = hwReg;
107
Zane Shelley0165edc2020-05-11 22:28:29 -0500108 break;
109 }
110 case 0x02: // integer constant
111 {
Zane Shelleyf8c92f92020-05-16 10:17:16 -0500112 auto& factory = Flyweight<const ConstantRegister>::getSingleton();
113
Zane Shelley6eb61902020-05-15 22:25:58 -0500114 if (REG_TYPE_SCOM == io_isoNode->getRegisterType() ||
115 REG_TYPE_ID_SCOM == io_isoNode->getRegisterType())
Zane Shelley0165edc2020-05-11 22:28:29 -0500116 {
117 uint64_t constant; // 8-byte value
118 io_stream >> constant;
Zane Shelleyf8c92f92020-05-16 10:17:16 -0500119
120 // Create the constant register and put it in the flyweights.
121 expr = factory.get(constant);
Zane Shelley0165edc2020-05-11 22:28:29 -0500122 }
123 else
124 {
125 HEI_ASSERT(false); // register type unsupported
126 }
Zane Shelleyf8c92f92020-05-16 10:17:16 -0500127
Zane Shelley0165edc2020-05-11 22:28:29 -0500128 break;
129 }
130 case 0x10: // AND operation
131 {
Zane Shelleyf8c92f92020-05-16 10:17:16 -0500132 auto& factory = Flyweight<const AndRegister>::getSingleton();
133
Zane Shelley0165edc2020-05-11 22:28:29 -0500134 uint8_t numSubExpr;
135 io_stream >> numSubExpr;
Zane Shelleyf8c92f92020-05-16 10:17:16 -0500136
137 HEI_ASSERT(2 <= numSubExpr); // must be at least two
138
139 // Read the first two sub-expressions.
140 auto e1 = __readExpr(io_stream, i_isoChip, io_isoNode);
141 auto e2 = __readExpr(io_stream, i_isoChip, io_isoNode);
142 HEI_ASSERT(e1 && e2); // Cannot be null
143
144 // Create the AND register and put it in the flyweights.
145 expr = factory.get(e1, e2);
146
147 // Iterate any remaining expressions.
148 for (uint8_t i = 2; i < numSubExpr; i++)
Zane Shelley0165edc2020-05-11 22:28:29 -0500149 {
Zane Shelleyf8c92f92020-05-16 10:17:16 -0500150 // Read the next sub-expressions.
151 e2 = __readExpr(io_stream, i_isoChip, io_isoNode);
152 HEI_ASSERT(e2); // Cannot be null
153
154 // Create the AND register and put it in the flyweights.
155 expr = factory.get(expr, e2);
Zane Shelley0165edc2020-05-11 22:28:29 -0500156 }
Zane Shelleyf8c92f92020-05-16 10:17:16 -0500157
Zane Shelley0165edc2020-05-11 22:28:29 -0500158 break;
159 }
160 case 0x11: // OR operation
161 {
Zane Shelleyf8c92f92020-05-16 10:17:16 -0500162 auto& factory = Flyweight<const OrRegister>::getSingleton();
163
Zane Shelley0165edc2020-05-11 22:28:29 -0500164 uint8_t numSubExpr;
165 io_stream >> numSubExpr;
Zane Shelleyf8c92f92020-05-16 10:17:16 -0500166
167 HEI_ASSERT(2 <= numSubExpr); // must be at least two
168
169 // Read the first two sub-expressions.
170 auto e1 = __readExpr(io_stream, i_isoChip, io_isoNode);
171 auto e2 = __readExpr(io_stream, i_isoChip, io_isoNode);
172 HEI_ASSERT(e1 && e2); // Cannot be null
173
174 // Create the OR register and put it in the flyweights.
175 expr = factory.get(e1, e2);
176
177 // Iterate any remaining expressions.
178 for (uint8_t i = 2; i < numSubExpr; i++)
Zane Shelley0165edc2020-05-11 22:28:29 -0500179 {
Zane Shelleyf8c92f92020-05-16 10:17:16 -0500180 // Read the next sub-expressions.
181 e2 = __readExpr(io_stream, i_isoChip, io_isoNode);
182 HEI_ASSERT(e2); // Cannot be null
183
184 // Create the OR register and put it in the flyweights.
185 expr = factory.get(expr, e2);
Zane Shelley0165edc2020-05-11 22:28:29 -0500186 }
Zane Shelleyf8c92f92020-05-16 10:17:16 -0500187
Zane Shelley0165edc2020-05-11 22:28:29 -0500188 break;
189 }
190 case 0x12: // NOT operation
191 {
Zane Shelleyf8c92f92020-05-16 10:17:16 -0500192 auto& factory = Flyweight<const NotRegister>::getSingleton();
193
194 // Read the sub-expression
195 auto e = __readExpr(io_stream, i_isoChip, io_isoNode);
196 HEI_ASSERT(e); // Cannot be null
197
198 // Create the NOT register and put it in the flyweights.
199 expr = factory.get(e);
200
Zane Shelley0165edc2020-05-11 22:28:29 -0500201 break;
202 }
203 case 0x13: // left shift operation
204 {
Zane Shelleyf8c92f92020-05-16 10:17:16 -0500205 auto& factory = Flyweight<const LeftShiftRegister>::getSingleton();
206
Zane Shelley0165edc2020-05-11 22:28:29 -0500207 uint8_t shiftValue;
208 io_stream >> shiftValue;
Zane Shelleyf8c92f92020-05-16 10:17:16 -0500209
210 // Read the sub-expression
211 auto e = __readExpr(io_stream, i_isoChip, io_isoNode);
212 HEI_ASSERT(e); // Cannot be null
213
214 // Create the left shift register and put it in the flyweights.
215 expr = factory.get(e, shiftValue);
216
Zane Shelley0165edc2020-05-11 22:28:29 -0500217 break;
218 }
219 case 0x14: // right shift operation
220 {
Zane Shelleyf8c92f92020-05-16 10:17:16 -0500221 auto& factory = Flyweight<const RightShiftRegister>::getSingleton();
222
Zane Shelley0165edc2020-05-11 22:28:29 -0500223 uint8_t shiftValue;
224 io_stream >> shiftValue;
Zane Shelleyf8c92f92020-05-16 10:17:16 -0500225
226 // Read the sub-expression
227 auto e = __readExpr(io_stream, i_isoChip, io_isoNode);
228 HEI_ASSERT(e); // Cannot be null
229
230 // Create the right shift register and put it in the flyweights.
231 expr = factory.get(e, shiftValue);
232
Zane Shelley0165edc2020-05-11 22:28:29 -0500233 break;
234 }
235 default:
236 HEI_ASSERT(false); // unsupported expression type
237 }
Zane Shelleyf8c92f92020-05-16 10:17:16 -0500238
239 return expr;
Zane Shelley0165edc2020-05-11 22:28:29 -0500240}
241
242//------------------------------------------------------------------------------
243
Zane Shelleyf229d5f2020-05-17 21:13:41 -0500244using TmpChildNodeMap = std::map<BitPosition_t, IsolationNode::Key>;
245using TmpNodeData = std::pair<IsolationNode::Ptr, TmpChildNodeMap>;
246using TmpNodeMap = std::map<IsolationNode::Key, TmpNodeData>;
247
248void __readNode(ChipDataStream& io_stream, const IsolationChip::Ptr& i_isoChip,
249 TmpNodeMap& io_tmpNodeMap)
Zane Shelley0165edc2020-05-11 22:28:29 -0500250{
251 // Read the node metadata.
252 NodeId_t nodeId;
253 RegisterType_t regType;
254 Instance_t numInsts;
255 io_stream >> nodeId >> regType >> numInsts;
256
257 for (unsigned int i = 0; i < numInsts; i++)
258 {
259 // Read the node instance metadata.
260 Instance_t nodeInst;
261 uint8_t numCapRegs, numIsoRules, numChildNodes;
262 io_stream >> nodeInst >> numCapRegs >> numIsoRules >> numChildNodes;
263
Zane Shelley6eb61902020-05-15 22:25:58 -0500264 // There must be at least one isolation rule defined.
265 HEI_ASSERT(0 != numIsoRules);
266
267 // Allocate memory for this isolation node.
268 auto isoNode =
269 std::make_shared<IsolationNode>(nodeId, nodeInst, regType);
270
Zane Shelley0165edc2020-05-11 22:28:29 -0500271 // Add capture registers.
272 for (unsigned int j = 0; j < numCapRegs; j++)
273 {
Zane Shelley6eb61902020-05-15 22:25:58 -0500274 // Read the capture register metadata.
Zane Shelley0165edc2020-05-11 22:28:29 -0500275 RegisterId_t regId;
276 Instance_t regInst;
277 io_stream >> regId >> regInst;
Zane Shelley6eb61902020-05-15 22:25:58 -0500278
279 // Find the hardware register that is stored in this isolation chip
280 // and add it to the list of capture registers. Note that this will
281 // assert that the target register must exist in the isolation chip.
Zane Shelleyf229d5f2020-05-17 21:13:41 -0500282 auto hwReg = i_isoChip->getHardwareRegister({regId, regInst});
Zane Shelley6eb61902020-05-15 22:25:58 -0500283
284 // Add the register to the isolation node.
285 isoNode->addCaptureRegister(hwReg);
Zane Shelley0165edc2020-05-11 22:28:29 -0500286 }
287
288 // Add isolation rules.
289 for (unsigned int j = 0; j < numIsoRules; j++)
290 {
Zane Shelley6eb61902020-05-15 22:25:58 -0500291 // Read the rule metadata.
Zane Shelley0165edc2020-05-11 22:28:29 -0500292 AttentionType_t attnType;
293 io_stream >> attnType;
Zane Shelleyf8c92f92020-05-16 10:17:16 -0500294
295 // Read out the rule for this attention type.
Zane Shelleyf229d5f2020-05-17 21:13:41 -0500296 auto rule = __readExpr(io_stream, i_isoChip, isoNode);
Zane Shelleyf8c92f92020-05-16 10:17:16 -0500297 HEI_ASSERT(rule); // Cannot be null
298
299 // Add the rule to the isolation node.
300 isoNode->addRule(attnType, rule);
Zane Shelley0165edc2020-05-11 22:28:29 -0500301 }
302
Zane Shelleyf229d5f2020-05-17 21:13:41 -0500303 // At this point, we will need to read out the child node metadata.
304 // However, we can't look up the child nodes and add them to this
305 // isolation node yet because we are still in the process of parsing
306 // them out of the Chip Data File. Therefore, we'll save a temporary map
307 // containing the child node information which will be used to look up
308 // the actual node objects later.
309 TmpChildNodeMap cMap{};
Zane Shelley0165edc2020-05-11 22:28:29 -0500310 for (unsigned int j = 0; j < numChildNodes; j++)
311 {
Zane Shelley6eb61902020-05-15 22:25:58 -0500312 // Read the child node metadata.
Zane Shelley0165edc2020-05-11 22:28:29 -0500313 BitPosition_t bit;
Zane Shelleyd0659242020-05-15 23:02:29 -0500314 NodeId_t childId;
315 Instance_t childInst;
316 io_stream >> bit >> childId >> childInst;
Zane Shelleyf229d5f2020-05-17 21:13:41 -0500317
318 auto ret =
319 cMap.emplace(bit, IsolationNode::Key{childId, childInst});
320 HEI_ASSERT(ret.second); // Should not have duplicate entries
321 }
322
323 // Add this isolation node with the temporary child node map to the
324 // returned map of nodes.
325 auto ret = io_tmpNodeMap.emplace(IsolationNode::Key{nodeId, nodeInst},
326 TmpNodeData{isoNode, cMap});
327 HEI_ASSERT(ret.second); // Should not have duplicate entries
328 }
329}
330
331//------------------------------------------------------------------------------
332
333void __insertNodes(IsolationChip::Ptr& io_isoChip,
334 const TmpNodeMap& i_tmpNodeMap)
335{
336 for (const auto& n : i_tmpNodeMap)
337 {
338 const IsolationNode::Ptr& node = n.second.first;
339 const TmpChildNodeMap& childMap = n.second.second;
340
341 // Link the child nodes, if they exist.
342 for (const auto& c : childMap)
343 {
344 const BitPosition_t& bit = c.first;
345 const IsolationNode::Key& childKey = c.second;
346
347 // Find the child node in the temporary map.
348 auto itr = i_tmpNodeMap.find(childKey);
349 HEI_ASSERT(i_tmpNodeMap.end() != itr); // Child node must exist.
350
351 const IsolationNode::Ptr& child = itr->second.first;
352
353 node->addChild(bit, child);
Zane Shelley0165edc2020-05-11 22:28:29 -0500354 }
Zane Shelley6eb61902020-05-15 22:25:58 -0500355
356 // Add this node to the isolation chip.
Zane Shelleyf229d5f2020-05-17 21:13:41 -0500357 io_isoChip->addIsolationNode(node);
Zane Shelley0165edc2020-05-11 22:28:29 -0500358 }
359}
360
361//------------------------------------------------------------------------------
362
Zane Shelley4de8ff82020-05-14 15:39:01 -0500363void __readRoot(ChipDataStream& io_stream, IsolationChip::Ptr& io_isoChip)
Zane Shelley0165edc2020-05-11 22:28:29 -0500364{
Zane Shelley2467db82020-05-18 19:56:30 -0500365 // Read the root node metadata.
Zane Shelley0165edc2020-05-11 22:28:29 -0500366 AttentionType_t attnType;
367 NodeId_t id;
368 Instance_t inst;
369 io_stream >> attnType >> id >> inst;
Zane Shelley2467db82020-05-18 19:56:30 -0500370
371 // Add the root node.
372 io_isoChip->addRootNode(attnType, io_isoChip->getIsolationNode({id, inst}));
Zane Shelley0165edc2020-05-11 22:28:29 -0500373}
374
375//------------------------------------------------------------------------------
376
Zane Shelleydd69c962020-05-05 22:19:11 -0500377void parseChipDataFile(void* i_buffer, size_t i_bufferSize,
Zane Shelley4de8ff82020-05-14 15:39:01 -0500378 IsolationChip::Map& io_isoChips)
Zane Shelleydd69c962020-05-05 22:19:11 -0500379{
380 ChipDataStream stream{i_buffer, i_bufferSize};
381
382 // Read the file metadata.
Zane Shelleyb9a8e762020-05-11 21:41:32 -0500383 FileKeyword_t fileKeyword;
384 ChipType_t chipType;
385 Version_t version;
386 stream >> fileKeyword >> chipType >> version;
Zane Shelleydd69c962020-05-05 22:19:11 -0500387
Zane Shelleyb9a8e762020-05-11 21:41:32 -0500388 // Check the file keyword.
389 HEI_ASSERT(KW_CHIPDATA == fileKeyword);
Zane Shelleydd69c962020-05-05 22:19:11 -0500390
391 // This chip type should not already exist.
392 HEI_ASSERT(io_isoChips.end() == io_isoChips.find(chipType));
393
Zane Shelleyb9a8e762020-05-11 21:41:32 -0500394 // So far there is only one supported version type so check it here.
395 HEI_ASSERT(VERSION_1 == version);
396
Zane Shelleydd69c962020-05-05 22:19:11 -0500397 // Allocate memory for the new isolation chip.
398 auto isoChip = std::make_unique<IsolationChip>(chipType);
399
Zane Shelleyb9a8e762020-05-11 21:41:32 -0500400 // Read the register list metadata.
401 SectionKeyword_t regsKeyword;
402 RegisterId_t numRegs;
403 stream >> regsKeyword >> numRegs;
404
405 // Check the register keyword.
406 HEI_ASSERT(KW_REGS == regsKeyword);
407
408 // There must be at least one register defined.
409 HEI_ASSERT(0 != numRegs);
410
Zane Shelley0165edc2020-05-11 22:28:29 -0500411 for (unsigned int i = 0; i < numRegs; i++)
Zane Shelleyb9a8e762020-05-11 21:41:32 -0500412 {
413 __readRegister(stream, isoChip);
414 }
Zane Shelleydd69c962020-05-05 22:19:11 -0500415
Zane Shelley0165edc2020-05-11 22:28:29 -0500416 // Read the node list metadata.
417 SectionKeyword_t nodeKeyword;
418 NodeId_t numNodes;
419 stream >> nodeKeyword >> numNodes;
420
421 // Check the node keyword.
422 HEI_ASSERT(KW_NODE == nodeKeyword);
423
424 // There must be at least one node defined.
425 HEI_ASSERT(0 != numNodes);
426
Zane Shelleyf229d5f2020-05-17 21:13:41 -0500427 TmpNodeMap tmpNodeMap; // Stores all nodes with child node map.
Zane Shelley0165edc2020-05-11 22:28:29 -0500428 for (unsigned int i = 0; i < numNodes; i++)
429 {
Zane Shelleyf229d5f2020-05-17 21:13:41 -0500430 __readNode(stream, isoChip, tmpNodeMap);
Zane Shelley0165edc2020-05-11 22:28:29 -0500431 }
Zane Shelleyf229d5f2020-05-17 21:13:41 -0500432 // Link all nodes with their child nodes. Then add them to isoChip.
433 __insertNodes(isoChip, tmpNodeMap);
Zane Shelley0165edc2020-05-11 22:28:29 -0500434
435 // Read the root node list metadata.
436 SectionKeyword_t rootKeyword;
437 AttentionType_t numRoots;
438 stream >> rootKeyword >> numRoots;
439
440 // Check the root node keyword.
441 HEI_ASSERT(KW_ROOT == rootKeyword);
442
443 // There must be at least one register defined.
444 HEI_ASSERT(0 != numRoots);
445
446 for (unsigned int i = 0; i < numRoots; i++)
447 {
448 __readRoot(stream, isoChip);
449 }
450
451 // At this point, the stream is done and it should be at the end of the
452 // file.
453 HEI_ASSERT(stream.eof());
454
Zane Shelleydd69c962020-05-05 22:19:11 -0500455 // Add this isolation chip to the collective list of isolation chips.
456 auto ret = io_isoChips.emplace(chipType, std::move(isoChip));
457 HEI_ASSERT(ret.second); // Just in case.
458}
459
460//------------------------------------------------------------------------------
461
462} // namespace libhei