blob: a0df3a2d55877dbd287edea1db8f88bcb9d760e4 [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 Shelley4de8ff82020-05-14 15:39:01 -0500244void __readNode(ChipDataStream& io_stream, IsolationChip::Ptr& io_isoChip)
Zane Shelley0165edc2020-05-11 22:28:29 -0500245{
246 // Read the node metadata.
247 NodeId_t nodeId;
248 RegisterType_t regType;
249 Instance_t numInsts;
250 io_stream >> nodeId >> regType >> numInsts;
251
252 for (unsigned int i = 0; i < numInsts; i++)
253 {
254 // Read the node instance metadata.
255 Instance_t nodeInst;
256 uint8_t numCapRegs, numIsoRules, numChildNodes;
257 io_stream >> nodeInst >> numCapRegs >> numIsoRules >> numChildNodes;
258
Zane Shelley6eb61902020-05-15 22:25:58 -0500259 // There must be at least one isolation rule defined.
260 HEI_ASSERT(0 != numIsoRules);
261
262 // Allocate memory for this isolation node.
263 auto isoNode =
264 std::make_shared<IsolationNode>(nodeId, nodeInst, regType);
265
Zane Shelley0165edc2020-05-11 22:28:29 -0500266 // Add capture registers.
267 for (unsigned int j = 0; j < numCapRegs; j++)
268 {
Zane Shelley6eb61902020-05-15 22:25:58 -0500269 // Read the capture register metadata.
Zane Shelley0165edc2020-05-11 22:28:29 -0500270 RegisterId_t regId;
271 Instance_t regInst;
272 io_stream >> regId >> regInst;
Zane Shelley6eb61902020-05-15 22:25:58 -0500273
274 // Find the hardware register that is stored in this isolation chip
275 // and add it to the list of capture registers. Note that this will
276 // assert that the target register must exist in the isolation chip.
277 auto hwReg = io_isoChip->getHardwareRegister({regId, regInst});
278
279 // Add the register to the isolation node.
280 isoNode->addCaptureRegister(hwReg);
Zane Shelley0165edc2020-05-11 22:28:29 -0500281 }
282
283 // Add isolation rules.
284 for (unsigned int j = 0; j < numIsoRules; j++)
285 {
Zane Shelley6eb61902020-05-15 22:25:58 -0500286 // Read the rule metadata.
Zane Shelley0165edc2020-05-11 22:28:29 -0500287 AttentionType_t attnType;
288 io_stream >> attnType;
Zane Shelleyf8c92f92020-05-16 10:17:16 -0500289
290 // Read out the rule for this attention type.
291 auto rule = __readExpr(io_stream, io_isoChip, isoNode);
292 HEI_ASSERT(rule); // Cannot be null
293
294 // Add the rule to the isolation node.
295 isoNode->addRule(attnType, rule);
Zane Shelley0165edc2020-05-11 22:28:29 -0500296 }
297
298 // Add child nodes.
299 for (unsigned int j = 0; j < numChildNodes; j++)
300 {
Zane Shelley6eb61902020-05-15 22:25:58 -0500301 // Read the child node metadata.
Zane Shelley0165edc2020-05-11 22:28:29 -0500302 BitPosition_t bit;
Zane Shelleyd0659242020-05-15 23:02:29 -0500303 NodeId_t childId;
304 Instance_t childInst;
305 io_stream >> bit >> childId >> childInst;
Zane Shelley0165edc2020-05-11 22:28:29 -0500306 }
Zane Shelley6eb61902020-05-15 22:25:58 -0500307
308 // Add this node to the isolation chip.
309 io_isoChip->addIsolationNode(isoNode);
Zane Shelley0165edc2020-05-11 22:28:29 -0500310 }
311}
312
313//------------------------------------------------------------------------------
314
Zane Shelley4de8ff82020-05-14 15:39:01 -0500315void __readRoot(ChipDataStream& io_stream, IsolationChip::Ptr& io_isoChip)
Zane Shelley0165edc2020-05-11 22:28:29 -0500316{
317 AttentionType_t attnType;
318 NodeId_t id;
319 Instance_t inst;
320 io_stream >> attnType >> id >> inst;
321}
322
323//------------------------------------------------------------------------------
324
Zane Shelleydd69c962020-05-05 22:19:11 -0500325void parseChipDataFile(void* i_buffer, size_t i_bufferSize,
Zane Shelley4de8ff82020-05-14 15:39:01 -0500326 IsolationChip::Map& io_isoChips)
Zane Shelleydd69c962020-05-05 22:19:11 -0500327{
328 ChipDataStream stream{i_buffer, i_bufferSize};
329
330 // Read the file metadata.
Zane Shelleyb9a8e762020-05-11 21:41:32 -0500331 FileKeyword_t fileKeyword;
332 ChipType_t chipType;
333 Version_t version;
334 stream >> fileKeyword >> chipType >> version;
Zane Shelleydd69c962020-05-05 22:19:11 -0500335
Zane Shelleyb9a8e762020-05-11 21:41:32 -0500336 // Check the file keyword.
337 HEI_ASSERT(KW_CHIPDATA == fileKeyword);
Zane Shelleydd69c962020-05-05 22:19:11 -0500338
339 // This chip type should not already exist.
340 HEI_ASSERT(io_isoChips.end() == io_isoChips.find(chipType));
341
Zane Shelleyb9a8e762020-05-11 21:41:32 -0500342 // So far there is only one supported version type so check it here.
343 HEI_ASSERT(VERSION_1 == version);
344
Zane Shelleydd69c962020-05-05 22:19:11 -0500345 // Allocate memory for the new isolation chip.
346 auto isoChip = std::make_unique<IsolationChip>(chipType);
347
Zane Shelleyb9a8e762020-05-11 21:41:32 -0500348 // Read the register list metadata.
349 SectionKeyword_t regsKeyword;
350 RegisterId_t numRegs;
351 stream >> regsKeyword >> numRegs;
352
353 // Check the register keyword.
354 HEI_ASSERT(KW_REGS == regsKeyword);
355
356 // There must be at least one register defined.
357 HEI_ASSERT(0 != numRegs);
358
Zane Shelley0165edc2020-05-11 22:28:29 -0500359 for (unsigned int i = 0; i < numRegs; i++)
Zane Shelleyb9a8e762020-05-11 21:41:32 -0500360 {
361 __readRegister(stream, isoChip);
362 }
Zane Shelleydd69c962020-05-05 22:19:11 -0500363
Zane Shelley0165edc2020-05-11 22:28:29 -0500364 // Read the node list metadata.
365 SectionKeyword_t nodeKeyword;
366 NodeId_t numNodes;
367 stream >> nodeKeyword >> numNodes;
368
369 // Check the node keyword.
370 HEI_ASSERT(KW_NODE == nodeKeyword);
371
372 // There must be at least one node defined.
373 HEI_ASSERT(0 != numNodes);
374
375 for (unsigned int i = 0; i < numNodes; i++)
376 {
377 __readNode(stream, isoChip);
378 }
379
380 // Read the root node list metadata.
381 SectionKeyword_t rootKeyword;
382 AttentionType_t numRoots;
383 stream >> rootKeyword >> numRoots;
384
385 // Check the root node keyword.
386 HEI_ASSERT(KW_ROOT == rootKeyword);
387
388 // There must be at least one register defined.
389 HEI_ASSERT(0 != numRoots);
390
391 for (unsigned int i = 0; i < numRoots; i++)
392 {
393 __readRoot(stream, isoChip);
394 }
395
396 // At this point, the stream is done and it should be at the end of the
397 // file.
398 HEI_ASSERT(stream.eof());
399
Zane Shelleydd69c962020-05-05 22:19:11 -0500400 // Add this isolation chip to the collective list of isolation chips.
401 auto ret = io_isoChips.emplace(chipType, std::move(isoChip));
402 HEI_ASSERT(ret.second); // Just in case.
403}
404
405//------------------------------------------------------------------------------
406
407} // namespace libhei