blob: 847c0a590b9f98e4266507d8b49521d50478f073 [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;
Zane Shelleydd69c962020-05-05 22:19:11 -050021
22//------------------------------------------------------------------------------
23
Zane Shelley4de8ff82020-05-14 15:39:01 -050024void __readRegister(ChipDataStream& io_stream, IsolationChip::Ptr& io_isoChip)
Zane Shelleyb9a8e762020-05-11 21:41:32 -050025{
26 // Read the register metadata.
27 RegisterId_t id;
28 RegisterType_t type;
29 RegisterAttributeFlags_t attr;
30 Instance_t numInsts;
31 io_stream >> id >> type >> attr >> numInsts;
32
33 // Must have at least one instance.
34 HEI_ASSERT(0 != numInsts);
35
Zane Shelley0165edc2020-05-11 22:28:29 -050036 for (unsigned int i = 0; i < numInsts; i++)
Zane Shelleyb9a8e762020-05-11 21:41:32 -050037 {
38 // Read the register instance metadata.
39 Instance_t inst;
40 io_stream >> inst;
41
42 // The address size is dependent on the register type.
43 if (REG_TYPE_SCOM == type)
44 {
45 uint32_t addr; // 4-byte address.
46 io_stream >> addr;
47
48 // Get this register from the flyweight factory.
49 auto& factory = Flyweight<const ScomRegister>::getSingleton();
Zane Shelley4de8ff82020-05-14 15:39:01 -050050 auto hwReg = factory.get(id, inst, attr, addr);
Zane Shelleyb9a8e762020-05-11 21:41:32 -050051
52 // Add this register to the isolation chip.
53 io_isoChip->addHardwareRegister(hwReg);
54 }
55 else if (REG_TYPE_ID_SCOM == type)
56 {
57 uint64_t addr; // 8-byte address.
58 io_stream >> addr;
59
60 // Get this register from the flyweight factory.
61 auto& factory = Flyweight<const IdScomRegister>::getSingleton();
Zane Shelley4de8ff82020-05-14 15:39:01 -050062 auto hwReg = factory.get(id, inst, attr, addr);
Zane Shelleyb9a8e762020-05-11 21:41:32 -050063
64 // Add this register to the isolation chip.
65 io_isoChip->addHardwareRegister(hwReg);
66 }
67 else
68 {
69 HEI_ASSERT(false); // Register type unsupported.
70 }
71 }
72}
73
74//------------------------------------------------------------------------------
75
Zane Shelleyf8c92f92020-05-16 10:17:16 -050076Register::ConstPtr __readExpr(ChipDataStream& io_stream,
77 const IsolationChip::Ptr& i_isoChip,
78 IsolationNode::Ptr& io_isoNode)
Zane Shelley0165edc2020-05-11 22:28:29 -050079{
Zane Shelleyf8c92f92020-05-16 10:17:16 -050080 Register::ConstPtr expr{};
81
Zane Shelley0165edc2020-05-11 22:28:29 -050082 uint8_t exprType;
83 io_stream >> exprType;
84 switch (exprType)
85 {
86 case 0x01: // register reference
87 {
88 RegisterId_t regId;
89 Instance_t regInst;
90 io_stream >> regId >> regInst;
Zane Shelley6eb61902020-05-15 22:25:58 -050091
92 // Find the hardware register that is stored in this isolation chip
93 // and add it to the list of capture registers. This ensures all
94 // registers referenced in the rules are are captured by default.
95 // Note that this will assert that the target register must exist in
96 // the isolation chip.
97 auto hwReg = i_isoChip->getHardwareRegister({regId, regInst});
98
99 // Add the register to the isolation node.
100 io_isoNode->addCaptureRegister(hwReg);
101
Zane Shelleyf8c92f92020-05-16 10:17:16 -0500102 // Simply return this register.
103 expr = hwReg;
104
Zane Shelley0165edc2020-05-11 22:28:29 -0500105 break;
106 }
107 case 0x02: // integer constant
108 {
Zane Shelleyf8c92f92020-05-16 10:17:16 -0500109 auto& factory = Flyweight<const ConstantRegister>::getSingleton();
110
Zane Shelley6eb61902020-05-15 22:25:58 -0500111 if (REG_TYPE_SCOM == io_isoNode->getRegisterType() ||
112 REG_TYPE_ID_SCOM == io_isoNode->getRegisterType())
Zane Shelley0165edc2020-05-11 22:28:29 -0500113 {
114 uint64_t constant; // 8-byte value
115 io_stream >> constant;
Zane Shelleyf8c92f92020-05-16 10:17:16 -0500116
117 // Create the constant register and put it in the flyweights.
118 expr = factory.get(constant);
Zane Shelley0165edc2020-05-11 22:28:29 -0500119 }
120 else
121 {
122 HEI_ASSERT(false); // register type unsupported
123 }
Zane Shelleyf8c92f92020-05-16 10:17:16 -0500124
Zane Shelley0165edc2020-05-11 22:28:29 -0500125 break;
126 }
127 case 0x10: // AND operation
128 {
Zane Shelleyf8c92f92020-05-16 10:17:16 -0500129 auto& factory = Flyweight<const AndRegister>::getSingleton();
130
Zane Shelley0165edc2020-05-11 22:28:29 -0500131 uint8_t numSubExpr;
132 io_stream >> numSubExpr;
Zane Shelleyf8c92f92020-05-16 10:17:16 -0500133
134 HEI_ASSERT(2 <= numSubExpr); // must be at least two
135
136 // Read the first two sub-expressions.
137 auto e1 = __readExpr(io_stream, i_isoChip, io_isoNode);
138 auto e2 = __readExpr(io_stream, i_isoChip, io_isoNode);
139 HEI_ASSERT(e1 && e2); // Cannot be null
140
141 // Create the AND register and put it in the flyweights.
142 expr = factory.get(e1, e2);
143
144 // Iterate any remaining expressions.
145 for (uint8_t i = 2; i < numSubExpr; i++)
Zane Shelley0165edc2020-05-11 22:28:29 -0500146 {
Zane Shelleyf8c92f92020-05-16 10:17:16 -0500147 // Read the next sub-expressions.
148 e2 = __readExpr(io_stream, i_isoChip, io_isoNode);
149 HEI_ASSERT(e2); // Cannot be null
150
151 // Create the AND register and put it in the flyweights.
152 expr = factory.get(expr, e2);
Zane Shelley0165edc2020-05-11 22:28:29 -0500153 }
Zane Shelleyf8c92f92020-05-16 10:17:16 -0500154
Zane Shelley0165edc2020-05-11 22:28:29 -0500155 break;
156 }
157 case 0x11: // OR operation
158 {
Zane Shelleyf8c92f92020-05-16 10:17:16 -0500159 auto& factory = Flyweight<const OrRegister>::getSingleton();
160
Zane Shelley0165edc2020-05-11 22:28:29 -0500161 uint8_t numSubExpr;
162 io_stream >> numSubExpr;
Zane Shelleyf8c92f92020-05-16 10:17:16 -0500163
164 HEI_ASSERT(2 <= numSubExpr); // must be at least two
165
166 // Read the first two sub-expressions.
167 auto e1 = __readExpr(io_stream, i_isoChip, io_isoNode);
168 auto e2 = __readExpr(io_stream, i_isoChip, io_isoNode);
169 HEI_ASSERT(e1 && e2); // Cannot be null
170
171 // Create the OR register and put it in the flyweights.
172 expr = factory.get(e1, e2);
173
174 // Iterate any remaining expressions.
175 for (uint8_t i = 2; i < numSubExpr; i++)
Zane Shelley0165edc2020-05-11 22:28:29 -0500176 {
Zane Shelleyf8c92f92020-05-16 10:17:16 -0500177 // Read the next sub-expressions.
178 e2 = __readExpr(io_stream, i_isoChip, io_isoNode);
179 HEI_ASSERT(e2); // Cannot be null
180
181 // Create the OR register and put it in the flyweights.
182 expr = factory.get(expr, e2);
Zane Shelley0165edc2020-05-11 22:28:29 -0500183 }
Zane Shelleyf8c92f92020-05-16 10:17:16 -0500184
Zane Shelley0165edc2020-05-11 22:28:29 -0500185 break;
186 }
187 case 0x12: // NOT operation
188 {
Zane Shelleyf8c92f92020-05-16 10:17:16 -0500189 auto& factory = Flyweight<const NotRegister>::getSingleton();
190
191 // Read the sub-expression
192 auto e = __readExpr(io_stream, i_isoChip, io_isoNode);
193 HEI_ASSERT(e); // Cannot be null
194
195 // Create the NOT register and put it in the flyweights.
196 expr = factory.get(e);
197
Zane Shelley0165edc2020-05-11 22:28:29 -0500198 break;
199 }
200 case 0x13: // left shift operation
201 {
Zane Shelleyf8c92f92020-05-16 10:17:16 -0500202 auto& factory = Flyweight<const LeftShiftRegister>::getSingleton();
203
Zane Shelley0165edc2020-05-11 22:28:29 -0500204 uint8_t shiftValue;
205 io_stream >> shiftValue;
Zane Shelleyf8c92f92020-05-16 10:17:16 -0500206
207 // Read the sub-expression
208 auto e = __readExpr(io_stream, i_isoChip, io_isoNode);
209 HEI_ASSERT(e); // Cannot be null
210
211 // Create the left shift register and put it in the flyweights.
212 expr = factory.get(e, shiftValue);
213
Zane Shelley0165edc2020-05-11 22:28:29 -0500214 break;
215 }
216 case 0x14: // right shift operation
217 {
Zane Shelleyf8c92f92020-05-16 10:17:16 -0500218 auto& factory = Flyweight<const RightShiftRegister>::getSingleton();
219
Zane Shelley0165edc2020-05-11 22:28:29 -0500220 uint8_t shiftValue;
221 io_stream >> shiftValue;
Zane Shelleyf8c92f92020-05-16 10:17:16 -0500222
223 // Read the sub-expression
224 auto e = __readExpr(io_stream, i_isoChip, io_isoNode);
225 HEI_ASSERT(e); // Cannot be null
226
227 // Create the right shift register and put it in the flyweights.
228 expr = factory.get(e, shiftValue);
229
Zane Shelley0165edc2020-05-11 22:28:29 -0500230 break;
231 }
232 default:
233 HEI_ASSERT(false); // unsupported expression type
234 }
Zane Shelleyf8c92f92020-05-16 10:17:16 -0500235
236 return expr;
Zane Shelley0165edc2020-05-11 22:28:29 -0500237}
238
239//------------------------------------------------------------------------------
240
Zane Shelleyf229d5f2020-05-17 21:13:41 -0500241using TmpChildNodeMap = std::map<BitPosition_t, IsolationNode::Key>;
242using TmpNodeData = std::pair<IsolationNode::Ptr, TmpChildNodeMap>;
243using TmpNodeMap = std::map<IsolationNode::Key, TmpNodeData>;
244
245void __readNode(ChipDataStream& io_stream, const IsolationChip::Ptr& i_isoChip,
Zane Shelley6b1fe162022-11-18 13:37:42 -0600246 TmpNodeMap& io_tmpNodeMap, Version_t i_version)
Zane Shelley0165edc2020-05-11 22:28:29 -0500247{
248 // Read the node metadata.
249 NodeId_t nodeId;
250 RegisterType_t regType;
251 Instance_t numInsts;
252 io_stream >> nodeId >> regType >> numInsts;
253
254 for (unsigned int i = 0; i < numInsts; i++)
255 {
256 // Read the node instance metadata.
257 Instance_t nodeInst;
258 uint8_t numCapRegs, numIsoRules, numChildNodes;
259 io_stream >> nodeInst >> numCapRegs >> numIsoRules >> numChildNodes;
260
Zane Shelleybcb43952021-07-08 22:13:57 -0500261 // It is possible to have rules defined and no child nodes, However, if
262 // there are no rules defined (FFDC-only node), there should not be
263 // any child nodes defined.
264 HEI_ASSERT(0 != numIsoRules || 0 == numChildNodes);
Zane Shelley6eb61902020-05-15 22:25:58 -0500265
266 // Allocate memory for this isolation node.
267 auto isoNode =
268 std::make_shared<IsolationNode>(nodeId, nodeInst, regType);
269
Zane Shelley0165edc2020-05-11 22:28:29 -0500270 // Add capture registers.
271 for (unsigned int j = 0; j < numCapRegs; j++)
272 {
Zane Shelley6eb61902020-05-15 22:25:58 -0500273 // Read the capture register metadata.
Zane Shelley0165edc2020-05-11 22:28:29 -0500274 RegisterId_t regId;
275 Instance_t regInst;
276 io_stream >> regId >> regInst;
Zane Shelley6eb61902020-05-15 22:25:58 -0500277
Zane Shelley6b1fe162022-11-18 13:37:42 -0600278 BitPosition_t bit = MAX_BIT_POSITION; // default all bits
279 if (VERSION_2 <= i_version)
280 {
281 io_stream >> bit;
282 }
283
Zane Shelley6eb61902020-05-15 22:25:58 -0500284 // Find the hardware register that is stored in this isolation chip
285 // and add it to the list of capture registers. Note that this will
286 // assert that the target register must exist in the isolation chip.
Zane Shelleyf229d5f2020-05-17 21:13:41 -0500287 auto hwReg = i_isoChip->getHardwareRegister({regId, regInst});
Zane Shelley6eb61902020-05-15 22:25:58 -0500288
289 // Add the register to the isolation node.
Zane Shelley6b1fe162022-11-18 13:37:42 -0600290 isoNode->addCaptureRegister(hwReg, bit);
Zane Shelley0165edc2020-05-11 22:28:29 -0500291 }
292
293 // Add isolation rules.
294 for (unsigned int j = 0; j < numIsoRules; j++)
295 {
Zane Shelley6eb61902020-05-15 22:25:58 -0500296 // Read the rule metadata.
Zane Shelley0165edc2020-05-11 22:28:29 -0500297 AttentionType_t attnType;
298 io_stream >> attnType;
Zane Shelleyf8c92f92020-05-16 10:17:16 -0500299
300 // Read out the rule for this attention type.
Zane Shelleyf229d5f2020-05-17 21:13:41 -0500301 auto rule = __readExpr(io_stream, i_isoChip, isoNode);
Zane Shelleyf8c92f92020-05-16 10:17:16 -0500302 HEI_ASSERT(rule); // Cannot be null
303
304 // Add the rule to the isolation node.
305 isoNode->addRule(attnType, rule);
Zane Shelley0165edc2020-05-11 22:28:29 -0500306 }
307
Zane Shelleyf229d5f2020-05-17 21:13:41 -0500308 // At this point, we will need to read out the child node metadata.
309 // However, we can't look up the child nodes and add them to this
310 // isolation node yet because we are still in the process of parsing
311 // them out of the Chip Data File. Therefore, we'll save a temporary map
312 // containing the child node information which will be used to look up
313 // the actual node objects later.
314 TmpChildNodeMap cMap{};
Zane Shelley0165edc2020-05-11 22:28:29 -0500315 for (unsigned int j = 0; j < numChildNodes; j++)
316 {
Zane Shelley6eb61902020-05-15 22:25:58 -0500317 // Read the child node metadata.
Zane Shelley0165edc2020-05-11 22:28:29 -0500318 BitPosition_t bit;
Zane Shelleyd0659242020-05-15 23:02:29 -0500319 NodeId_t childId;
320 Instance_t childInst;
321 io_stream >> bit >> childId >> childInst;
Zane Shelleyf229d5f2020-05-17 21:13:41 -0500322
323 auto ret =
324 cMap.emplace(bit, IsolationNode::Key{childId, childInst});
325 HEI_ASSERT(ret.second); // Should not have duplicate entries
326 }
327
328 // Add this isolation node with the temporary child node map to the
329 // returned map of nodes.
330 auto ret = io_tmpNodeMap.emplace(IsolationNode::Key{nodeId, nodeInst},
331 TmpNodeData{isoNode, cMap});
332 HEI_ASSERT(ret.second); // Should not have duplicate entries
333 }
334}
335
336//------------------------------------------------------------------------------
337
338void __insertNodes(IsolationChip::Ptr& io_isoChip,
339 const TmpNodeMap& i_tmpNodeMap)
340{
341 for (const auto& n : i_tmpNodeMap)
342 {
343 const IsolationNode::Ptr& node = n.second.first;
344 const TmpChildNodeMap& childMap = n.second.second;
345
346 // Link the child nodes, if they exist.
347 for (const auto& c : childMap)
348 {
349 const BitPosition_t& bit = c.first;
350 const IsolationNode::Key& childKey = c.second;
351
352 // Find the child node in the temporary map.
353 auto itr = i_tmpNodeMap.find(childKey);
354 HEI_ASSERT(i_tmpNodeMap.end() != itr); // Child node must exist.
355
356 const IsolationNode::Ptr& child = itr->second.first;
357
358 node->addChild(bit, child);
Zane Shelley0165edc2020-05-11 22:28:29 -0500359 }
Zane Shelley6eb61902020-05-15 22:25:58 -0500360
361 // Add this node to the isolation chip.
Zane Shelleyf229d5f2020-05-17 21:13:41 -0500362 io_isoChip->addIsolationNode(node);
Zane Shelley0165edc2020-05-11 22:28:29 -0500363 }
364}
365
366//------------------------------------------------------------------------------
367
Zane Shelley4de8ff82020-05-14 15:39:01 -0500368void __readRoot(ChipDataStream& io_stream, IsolationChip::Ptr& io_isoChip)
Zane Shelley0165edc2020-05-11 22:28:29 -0500369{
Zane Shelley2467db82020-05-18 19:56:30 -0500370 // Read the root node metadata.
Zane Shelley0165edc2020-05-11 22:28:29 -0500371 AttentionType_t attnType;
372 NodeId_t id;
373 Instance_t inst;
374 io_stream >> attnType >> id >> inst;
Zane Shelley2467db82020-05-18 19:56:30 -0500375
376 // Add the root node.
377 io_isoChip->addRootNode(attnType, io_isoChip->getIsolationNode({id, inst}));
Zane Shelley0165edc2020-05-11 22:28:29 -0500378}
379
380//------------------------------------------------------------------------------
381
Zane Shelleydd69c962020-05-05 22:19:11 -0500382void parseChipDataFile(void* i_buffer, size_t i_bufferSize,
Zane Shelley4de8ff82020-05-14 15:39:01 -0500383 IsolationChip::Map& io_isoChips)
Zane Shelleydd69c962020-05-05 22:19:11 -0500384{
385 ChipDataStream stream{i_buffer, i_bufferSize};
386
387 // Read the file metadata.
Zane Shelleyb9a8e762020-05-11 21:41:32 -0500388 FileKeyword_t fileKeyword;
389 ChipType_t chipType;
390 Version_t version;
391 stream >> fileKeyword >> chipType >> version;
Zane Shelleydd69c962020-05-05 22:19:11 -0500392
Zane Shelleyb9a8e762020-05-11 21:41:32 -0500393 // Check the file keyword.
394 HEI_ASSERT(KW_CHIPDATA == fileKeyword);
Zane Shelleydd69c962020-05-05 22:19:11 -0500395
396 // This chip type should not already exist.
397 HEI_ASSERT(io_isoChips.end() == io_isoChips.find(chipType));
398
Zane Shelley6b1fe162022-11-18 13:37:42 -0600399 // Check supported versions.
400 HEI_ASSERT(VERSION_1 <= version && version <= VERSION_2);
Zane Shelleyb9a8e762020-05-11 21:41:32 -0500401
Zane Shelleydd69c962020-05-05 22:19:11 -0500402 // Allocate memory for the new isolation chip.
Zane Shelleyd5d23632022-12-13 09:34:31 -0600403 auto isoChip = std::make_shared<IsolationChip>(chipType);
Zane Shelleydd69c962020-05-05 22:19:11 -0500404
Zane Shelleyb9a8e762020-05-11 21:41:32 -0500405 // Read the register list metadata.
406 SectionKeyword_t regsKeyword;
407 RegisterId_t numRegs;
408 stream >> regsKeyword >> numRegs;
409
410 // Check the register keyword.
411 HEI_ASSERT(KW_REGS == regsKeyword);
412
413 // There must be at least one register defined.
414 HEI_ASSERT(0 != numRegs);
415
Zane Shelley0165edc2020-05-11 22:28:29 -0500416 for (unsigned int i = 0; i < numRegs; i++)
Zane Shelleyb9a8e762020-05-11 21:41:32 -0500417 {
418 __readRegister(stream, isoChip);
419 }
Zane Shelleydd69c962020-05-05 22:19:11 -0500420
Zane Shelley0165edc2020-05-11 22:28:29 -0500421 // Read the node list metadata.
422 SectionKeyword_t nodeKeyword;
423 NodeId_t numNodes;
424 stream >> nodeKeyword >> numNodes;
425
426 // Check the node keyword.
427 HEI_ASSERT(KW_NODE == nodeKeyword);
428
429 // There must be at least one node defined.
430 HEI_ASSERT(0 != numNodes);
431
Zane Shelleyf229d5f2020-05-17 21:13:41 -0500432 TmpNodeMap tmpNodeMap; // Stores all nodes with child node map.
Zane Shelley0165edc2020-05-11 22:28:29 -0500433 for (unsigned int i = 0; i < numNodes; i++)
434 {
Zane Shelley6b1fe162022-11-18 13:37:42 -0600435 __readNode(stream, isoChip, tmpNodeMap, version);
Zane Shelley0165edc2020-05-11 22:28:29 -0500436 }
Zane Shelleyf229d5f2020-05-17 21:13:41 -0500437 // Link all nodes with their child nodes. Then add them to isoChip.
438 __insertNodes(isoChip, tmpNodeMap);
Zane Shelley0165edc2020-05-11 22:28:29 -0500439
440 // Read the root node list metadata.
441 SectionKeyword_t rootKeyword;
442 AttentionType_t numRoots;
443 stream >> rootKeyword >> numRoots;
444
445 // Check the root node keyword.
446 HEI_ASSERT(KW_ROOT == rootKeyword);
447
448 // There must be at least one register defined.
449 HEI_ASSERT(0 != numRoots);
450
451 for (unsigned int i = 0; i < numRoots; i++)
452 {
453 __readRoot(stream, isoChip);
454 }
455
456 // At this point, the stream is done and it should be at the end of the
457 // file.
458 HEI_ASSERT(stream.eof());
459
Zane Shelleydd69c962020-05-05 22:19:11 -0500460 // Add this isolation chip to the collective list of isolation chips.
Zane Shelleyd5d23632022-12-13 09:34:31 -0600461 auto ret = io_isoChips.emplace(chipType, isoChip);
Zane Shelleydd69c962020-05-05 22:19:11 -0500462 HEI_ASSERT(ret.second); // Just in case.
463}
464
465//------------------------------------------------------------------------------
466
467} // namespace libhei