blob: 752014b902b048e405e2ac92903fcc9ca6cbb95f [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 Shelleyb9a8e762020-05-11 21:41:32 -05003#include <register/hei_scom_register.hpp>
Zane Shelleydd69c962020-05-05 22:19:11 -05004
5namespace libhei
6{
7
8//------------------------------------------------------------------------------
9
10using FileKeyword_t = uint64_t;
11
12constexpr FileKeyword_t KW_CHIPDATA = 0x4348495044415441; // "CHIPDATA" ASCII
13
14using SectionKeyword_t = uint32_t;
15
Zane Shelleyb9a8e762020-05-11 21:41:32 -050016constexpr SectionKeyword_t KW_REGS = 0x52454753; // "REGS" ASCII
Zane Shelleydd69c962020-05-05 22:19:11 -050017constexpr SectionKeyword_t KW_NODE = 0x4e4f4445; // "NODE" ASCII
18constexpr SectionKeyword_t KW_ROOT = 0x524f4f54; // "ROOT" ASCII
19
20using Version_t = uint8_t;
21
22constexpr Version_t VERSION_1 = 0x01;
23
24//------------------------------------------------------------------------------
25
Zane Shelley4de8ff82020-05-14 15:39:01 -050026void __readRegister(ChipDataStream& io_stream, IsolationChip::Ptr& io_isoChip)
Zane Shelleyb9a8e762020-05-11 21:41:32 -050027{
28 // Read the register metadata.
29 RegisterId_t id;
30 RegisterType_t type;
31 RegisterAttributeFlags_t attr;
32 Instance_t numInsts;
33 io_stream >> id >> type >> attr >> numInsts;
34
35 // Must have at least one instance.
36 HEI_ASSERT(0 != numInsts);
37
Zane Shelley0165edc2020-05-11 22:28:29 -050038 for (unsigned int i = 0; i < numInsts; i++)
Zane Shelleyb9a8e762020-05-11 21:41:32 -050039 {
40 // Read the register instance metadata.
41 Instance_t inst;
42 io_stream >> inst;
43
44 // The address size is dependent on the register type.
45 if (REG_TYPE_SCOM == type)
46 {
47 uint32_t addr; // 4-byte address.
48 io_stream >> addr;
49
50 // Get this register from the flyweight factory.
51 auto& factory = Flyweight<const ScomRegister>::getSingleton();
Zane Shelley4de8ff82020-05-14 15:39:01 -050052 auto hwReg = factory.get(id, inst, attr, addr);
Zane Shelleyb9a8e762020-05-11 21:41:32 -050053
54 // Add this register to the isolation chip.
55 io_isoChip->addHardwareRegister(hwReg);
56 }
57 else if (REG_TYPE_ID_SCOM == type)
58 {
59 uint64_t addr; // 8-byte address.
60 io_stream >> addr;
61
62 // Get this register from the flyweight factory.
63 auto& factory = Flyweight<const IdScomRegister>::getSingleton();
Zane Shelley4de8ff82020-05-14 15:39:01 -050064 auto hwReg = factory.get(id, inst, attr, addr);
Zane Shelleyb9a8e762020-05-11 21:41:32 -050065
66 // Add this register to the isolation chip.
67 io_isoChip->addHardwareRegister(hwReg);
68 }
69 else
70 {
71 HEI_ASSERT(false); // Register type unsupported.
72 }
73 }
74}
75
76//------------------------------------------------------------------------------
77
Zane Shelley6eb61902020-05-15 22:25:58 -050078void __readExpr(ChipDataStream& io_stream, const IsolationChip::Ptr& i_isoChip,
79 IsolationNode::Ptr& io_isoNode)
Zane Shelley0165edc2020-05-11 22:28:29 -050080{
81 uint8_t exprType;
82 io_stream >> exprType;
83 switch (exprType)
84 {
85 case 0x01: // register reference
86 {
87 RegisterId_t regId;
88 Instance_t regInst;
89 io_stream >> regId >> regInst;
Zane Shelley6eb61902020-05-15 22:25:58 -050090
91 // Find the hardware register that is stored in this isolation chip
92 // and add it to the list of capture registers. This ensures all
93 // registers referenced in the rules are are captured by default.
94 // Note that this will assert that the target register must exist in
95 // the isolation chip.
96 auto hwReg = i_isoChip->getHardwareRegister({regId, regInst});
97
98 // Add the register to the isolation node.
99 io_isoNode->addCaptureRegister(hwReg);
100
Zane Shelley0165edc2020-05-11 22:28:29 -0500101 break;
102 }
103 case 0x02: // integer constant
104 {
Zane Shelley6eb61902020-05-15 22:25:58 -0500105 if (REG_TYPE_SCOM == io_isoNode->getRegisterType() ||
106 REG_TYPE_ID_SCOM == io_isoNode->getRegisterType())
Zane Shelley0165edc2020-05-11 22:28:29 -0500107 {
108 uint64_t constant; // 8-byte value
109 io_stream >> constant;
110 }
111 else
112 {
113 HEI_ASSERT(false); // register type unsupported
114 }
115 break;
116 }
117 case 0x10: // AND operation
118 {
119 uint8_t numSubExpr;
120 io_stream >> numSubExpr;
121 for (uint8_t i = 0; i < numSubExpr; i++)
122 {
Zane Shelley6eb61902020-05-15 22:25:58 -0500123 __readExpr(io_stream, i_isoChip, io_isoNode);
Zane Shelley0165edc2020-05-11 22:28:29 -0500124 }
125 break;
126 }
127 case 0x11: // OR operation
128 {
129 uint8_t numSubExpr;
130 io_stream >> numSubExpr;
131 for (uint8_t i = 0; i < numSubExpr; i++)
132 {
Zane Shelley6eb61902020-05-15 22:25:58 -0500133 __readExpr(io_stream, i_isoChip, io_isoNode);
Zane Shelley0165edc2020-05-11 22:28:29 -0500134 }
135 break;
136 }
137 case 0x12: // NOT operation
138 {
Zane Shelley6eb61902020-05-15 22:25:58 -0500139 __readExpr(io_stream, i_isoChip, io_isoNode);
Zane Shelley0165edc2020-05-11 22:28:29 -0500140 break;
141 }
142 case 0x13: // left shift operation
143 {
144 uint8_t shiftValue;
145 io_stream >> shiftValue;
Zane Shelley6eb61902020-05-15 22:25:58 -0500146 __readExpr(io_stream, i_isoChip, io_isoNode);
Zane Shelley0165edc2020-05-11 22:28:29 -0500147 break;
148 }
149 case 0x14: // right shift operation
150 {
151 uint8_t shiftValue;
152 io_stream >> shiftValue;
Zane Shelley6eb61902020-05-15 22:25:58 -0500153 __readExpr(io_stream, i_isoChip, io_isoNode);
Zane Shelley0165edc2020-05-11 22:28:29 -0500154 break;
155 }
156 default:
157 HEI_ASSERT(false); // unsupported expression type
158 }
159}
160
161//------------------------------------------------------------------------------
162
Zane Shelley4de8ff82020-05-14 15:39:01 -0500163void __readNode(ChipDataStream& io_stream, IsolationChip::Ptr& io_isoChip)
Zane Shelley0165edc2020-05-11 22:28:29 -0500164{
165 // Read the node metadata.
166 NodeId_t nodeId;
167 RegisterType_t regType;
168 Instance_t numInsts;
169 io_stream >> nodeId >> regType >> numInsts;
170
171 for (unsigned int i = 0; i < numInsts; i++)
172 {
173 // Read the node instance metadata.
174 Instance_t nodeInst;
175 uint8_t numCapRegs, numIsoRules, numChildNodes;
176 io_stream >> nodeInst >> numCapRegs >> numIsoRules >> numChildNodes;
177
Zane Shelley6eb61902020-05-15 22:25:58 -0500178 // There must be at least one isolation rule defined.
179 HEI_ASSERT(0 != numIsoRules);
180
181 // Allocate memory for this isolation node.
182 auto isoNode =
183 std::make_shared<IsolationNode>(nodeId, nodeInst, regType);
184
Zane Shelley0165edc2020-05-11 22:28:29 -0500185 // Add capture registers.
186 for (unsigned int j = 0; j < numCapRegs; j++)
187 {
Zane Shelley6eb61902020-05-15 22:25:58 -0500188 // Read the capture register metadata.
Zane Shelley0165edc2020-05-11 22:28:29 -0500189 RegisterId_t regId;
190 Instance_t regInst;
191 io_stream >> regId >> regInst;
Zane Shelley6eb61902020-05-15 22:25:58 -0500192
193 // Find the hardware register that is stored in this isolation chip
194 // and add it to the list of capture registers. Note that this will
195 // assert that the target register must exist in the isolation chip.
196 auto hwReg = io_isoChip->getHardwareRegister({regId, regInst});
197
198 // Add the register to the isolation node.
199 isoNode->addCaptureRegister(hwReg);
Zane Shelley0165edc2020-05-11 22:28:29 -0500200 }
201
202 // Add isolation rules.
203 for (unsigned int j = 0; j < numIsoRules; j++)
204 {
Zane Shelley6eb61902020-05-15 22:25:58 -0500205 // Read the rule metadata.
Zane Shelley0165edc2020-05-11 22:28:29 -0500206 AttentionType_t attnType;
207 io_stream >> attnType;
Zane Shelley6eb61902020-05-15 22:25:58 -0500208 __readExpr(io_stream, io_isoChip, isoNode);
Zane Shelley0165edc2020-05-11 22:28:29 -0500209 }
210
211 // Add child nodes.
212 for (unsigned int j = 0; j < numChildNodes; j++)
213 {
Zane Shelley6eb61902020-05-15 22:25:58 -0500214 // Read the child node metadata.
Zane Shelley0165edc2020-05-11 22:28:29 -0500215 BitPosition_t bit;
Zane Shelleyd0659242020-05-15 23:02:29 -0500216 NodeId_t childId;
217 Instance_t childInst;
218 io_stream >> bit >> childId >> childInst;
Zane Shelley0165edc2020-05-11 22:28:29 -0500219 }
Zane Shelley6eb61902020-05-15 22:25:58 -0500220
221 // Add this node to the isolation chip.
222 io_isoChip->addIsolationNode(isoNode);
Zane Shelley0165edc2020-05-11 22:28:29 -0500223 }
224}
225
226//------------------------------------------------------------------------------
227
Zane Shelley4de8ff82020-05-14 15:39:01 -0500228void __readRoot(ChipDataStream& io_stream, IsolationChip::Ptr& io_isoChip)
Zane Shelley0165edc2020-05-11 22:28:29 -0500229{
230 AttentionType_t attnType;
231 NodeId_t id;
232 Instance_t inst;
233 io_stream >> attnType >> id >> inst;
234}
235
236//------------------------------------------------------------------------------
237
Zane Shelleydd69c962020-05-05 22:19:11 -0500238void parseChipDataFile(void* i_buffer, size_t i_bufferSize,
Zane Shelley4de8ff82020-05-14 15:39:01 -0500239 IsolationChip::Map& io_isoChips)
Zane Shelleydd69c962020-05-05 22:19:11 -0500240{
241 ChipDataStream stream{i_buffer, i_bufferSize};
242
243 // Read the file metadata.
Zane Shelleyb9a8e762020-05-11 21:41:32 -0500244 FileKeyword_t fileKeyword;
245 ChipType_t chipType;
246 Version_t version;
247 stream >> fileKeyword >> chipType >> version;
Zane Shelleydd69c962020-05-05 22:19:11 -0500248
Zane Shelleyb9a8e762020-05-11 21:41:32 -0500249 // Check the file keyword.
250 HEI_ASSERT(KW_CHIPDATA == fileKeyword);
Zane Shelleydd69c962020-05-05 22:19:11 -0500251
252 // This chip type should not already exist.
253 HEI_ASSERT(io_isoChips.end() == io_isoChips.find(chipType));
254
Zane Shelleyb9a8e762020-05-11 21:41:32 -0500255 // So far there is only one supported version type so check it here.
256 HEI_ASSERT(VERSION_1 == version);
257
Zane Shelleydd69c962020-05-05 22:19:11 -0500258 // Allocate memory for the new isolation chip.
259 auto isoChip = std::make_unique<IsolationChip>(chipType);
260
Zane Shelleyb9a8e762020-05-11 21:41:32 -0500261 // Read the register list metadata.
262 SectionKeyword_t regsKeyword;
263 RegisterId_t numRegs;
264 stream >> regsKeyword >> numRegs;
265
266 // Check the register keyword.
267 HEI_ASSERT(KW_REGS == regsKeyword);
268
269 // There must be at least one register defined.
270 HEI_ASSERT(0 != numRegs);
271
Zane Shelley0165edc2020-05-11 22:28:29 -0500272 for (unsigned int i = 0; i < numRegs; i++)
Zane Shelleyb9a8e762020-05-11 21:41:32 -0500273 {
274 __readRegister(stream, isoChip);
275 }
Zane Shelleydd69c962020-05-05 22:19:11 -0500276
Zane Shelley0165edc2020-05-11 22:28:29 -0500277 // Read the node list metadata.
278 SectionKeyword_t nodeKeyword;
279 NodeId_t numNodes;
280 stream >> nodeKeyword >> numNodes;
281
282 // Check the node keyword.
283 HEI_ASSERT(KW_NODE == nodeKeyword);
284
285 // There must be at least one node defined.
286 HEI_ASSERT(0 != numNodes);
287
288 for (unsigned int i = 0; i < numNodes; i++)
289 {
290 __readNode(stream, isoChip);
291 }
292
293 // Read the root node list metadata.
294 SectionKeyword_t rootKeyword;
295 AttentionType_t numRoots;
296 stream >> rootKeyword >> numRoots;
297
298 // Check the root node keyword.
299 HEI_ASSERT(KW_ROOT == rootKeyword);
300
301 // There must be at least one register defined.
302 HEI_ASSERT(0 != numRoots);
303
304 for (unsigned int i = 0; i < numRoots; i++)
305 {
306 __readRoot(stream, isoChip);
307 }
308
309 // At this point, the stream is done and it should be at the end of the
310 // file.
311 HEI_ASSERT(stream.eof());
312
Zane Shelleydd69c962020-05-05 22:19:11 -0500313 // Add this isolation chip to the collective list of isolation chips.
314 auto ret = io_isoChips.emplace(chipType, std::move(isoChip));
315 HEI_ASSERT(ret.second); // Just in case.
316}
317
318//------------------------------------------------------------------------------
319
320} // namespace libhei