OdbDesignLib
OdbDesign ODB++ Parsing Library
 
Loading...
Searching...
No Matches
Design.cpp
1#include "Design.h"
2#include "Design.h"
3#include "Package.h"
4#include "Logger.h"
5#include "../enums.h"
6#include "Part.h"
7#include <memory>
8#include "Net.h"
9#include "../FileModel/Design/FileArchive.h"
10#include "../FileModel/Design/EdaDataFile.h"
11
12
13namespace Odb::Lib::ProductModel
14{
15 Design::Design()
16 {
17 }
18
19 Design::~Design()
20 {
21 m_components.clear();
22 m_componentsByName.clear();
23 m_nets.clear();
24 m_netsByName.clear();
25 m_packages.clear();
26 m_packagesByName.clear();
27 m_parts.clear();
28 m_partsByName.clear();
29 }
30
31 const std::string& Design::GetName() const
32 {
33 return m_name;
34 }
35
36 const std::string& Design::GetProductModel() const
37 {
38 return m_productModel;
39 }
40
41 const Net::Vector& Design::GetNets() const
42 {
43 return m_nets;
44 }
45
46 const Net::StringMap Design::GetNetsByName() const
47 {
48 return m_netsByName;
49 }
50
51 const Package::Vector& Design::GetPackages() const
52 {
53 return m_packages;
54 }
55
56 const Package::StringMap& Design::GetPackagesByName() const
57 {
58 return m_packagesByName;
59 }
60
61 const Component::Vector& Design::GetComponents() const
62 {
63 return m_components;
64 }
65
66 const Component::StringMap& Design::GetComponentsByName() const
67 {
68 return m_componentsByName;
69 }
70
71 std::shared_ptr<Component> Design::GetComponent(const std::string& refDes) const
72 {
73 auto findIt = m_componentsByName.find(refDes);
74 if (findIt != m_componentsByName.end())
75 {
76 return findIt->second;
77 }
78
79 return nullptr;
80 }
81
82 const Part::Vector& Design::GetParts() const
83 {
84 return m_parts;
85 }
86
87 const Part::StringMap& Design::GetPartsByName() const
88 {
89 return m_partsByName;
90 }
91
92 std::shared_ptr<Net> Design::GetNet(const std::string& name) const
93 {
94 auto findIt = m_netsByName.find(name);
95 if (findIt != m_netsByName.end())
96 {
97 return findIt->second;
98 }
99 return nullptr;
100 }
101
102 std::shared_ptr<Net> Design::GetNoneNet() const
103 {
104 return GetNet(NONE_NET_NAME);
105 }
106
107 bool Design::Build(std::string path)
108 {
109 auto pFileModel = std::make_shared<FileModel::Design::FileArchive>(path);
110 if (pFileModel->ParseFileModel())
111 {
112 return Build(pFileModel);
113 }
114 return false;
115 }
116
117 bool Design::Build(std::shared_ptr<FileModel::Design::FileArchive> pFileModel)
118 {
119 if (pFileModel == nullptr) return false;
120
121 m_pFileModel = pFileModel;
122
123 //m_productModel = m_pFileModel->GetProductName();
124 //m_name = m_pFileModel->GetProductName();
125
126 // atomic elements
127 if (! BuildNets()) return false;
128 if (! BuildPackages()) return false;
129 if (! BuildAllParts()) return false;
130 if (! BuildAllComponents()) return false;
131
132 // built from relationships between atomic elements
133 if (! BuildPlacementsFromComponentsFiles()) return false;
134
135 // already built from BuildPlacements()
136 //if (! BuildNoneNet()) return false;
137 //if (! BreakSinglePinNets()) return false;
138
139 if (CLIP_FILEMODEL_AFTER_BUILD)
140 {
141 ClipFileModel();
142 }
143
144 return true;
145 }
146
147 std::shared_ptr<FileModel::Design::FileArchive> Design::GetFileModel() const
148 {
149 return m_pFileModel;
150 }
151
152 void Design::ClipFileModel()
153 {
154 m_pFileModel = nullptr;
155 }
156
157 std::unique_ptr<Odb::Lib::Protobuf::ProductModel::Design> Design::to_protobuf() const
158 {
159 auto pDesignMsg = std::make_unique<Odb::Lib::Protobuf::ProductModel::Design>();
160 pDesignMsg->set_name(m_name);
161 pDesignMsg->set_productmodel(m_productModel);
162
163 if (m_pFileModel != nullptr)
164 {
165 pDesignMsg->mutable_filemodel()->CopyFrom(*m_pFileModel->to_protobuf());
166 }
167
168 for (const auto& pNet : m_nets)
169 {
170 pDesignMsg->add_nets()->CopyFrom(*pNet->to_protobuf());
171 }
172
173 for (const auto& kvNet : m_netsByName)
174 {
175 (*pDesignMsg->mutable_netsbyname())[kvNet.first] = *kvNet.second->to_protobuf();
176 }
177
178 for (const auto& pPackage : m_packages)
179 {
180 pDesignMsg->add_packages()->CopyFrom(*pPackage->to_protobuf());
181 }
182
183 for (const auto& kvPackage : m_packagesByName)
184 {
185 (*pDesignMsg->mutable_packagesbyname())[kvPackage.first] = *kvPackage.second->to_protobuf();
186 }
187
188 for (const auto& pComponent : m_components)
189 {
190 pDesignMsg->add_components()->CopyFrom(*pComponent->to_protobuf());
191 }
192
193 for (const auto& kvComponent : m_componentsByName)
194 {
195 (*pDesignMsg->mutable_componentsbyname())[kvComponent.first] = *kvComponent.second->to_protobuf();
196 }
197
198 for (const auto& pPart : m_parts)
199 {
200 pDesignMsg->add_parts()->CopyFrom(*pPart->to_protobuf());
201 }
202
203 for (const auto& kvPart : m_partsByName)
204 {
205 (*pDesignMsg->mutable_partsbyname())[kvPart.first] = *kvPart.second->to_protobuf();
206 }
207
208 return pDesignMsg;
209 }
210
211 void Design::from_protobuf(const Odb::Lib::Protobuf::ProductModel::Design& message)
212 {
213 m_name = message.name();
214 m_productModel = message.productmodel();
215
216 m_pFileModel = std::make_shared<FileModel::Design::FileArchive>();
217 m_pFileModel->from_protobuf(message.filemodel());
218
219 for (const auto& pNetMsg : message.nets())
220 {
221 auto pNet = std::make_shared<Net>("", -1);
222 pNet->from_protobuf(pNetMsg);
223 m_nets.push_back(pNet);
224 }
225
226 for (const auto& kvNetMsg : message.netsbyname())
227 {
228 auto pNet = std::make_shared<Net>("", -1);
229 pNet->from_protobuf(kvNetMsg.second);
230 m_netsByName[kvNetMsg.first] = pNet;
231 }
232
233 for (const auto& pPackageMsg : message.packages())
234 {
235 auto pPackage = std::make_shared<Package>("", -1);
236 pPackage->from_protobuf(pPackageMsg);
237 m_packages.push_back(pPackage);
238 }
239
240 for (const auto& kvPackageMsg : message.packagesbyname())
241 {
242 auto pPackage = std::make_shared<Package>("", -1);
243 pPackage->from_protobuf(kvPackageMsg.second);
244 m_packagesByName[kvPackageMsg.first] = pPackage;
245 }
246
247 for (const auto& pComponentMsg : message.components())
248 {
249 auto pComponent = std::make_shared<Component>("", "", nullptr, -1, BoardSide::BsNone, nullptr);
250 pComponent->from_protobuf(pComponentMsg);
251 m_components.push_back(pComponent);
252 }
253
254 for (const auto& kvComponentMsg : message.componentsbyname())
255 {
256 auto pComponent = std::make_shared<Component>("", "", nullptr, -1, BoardSide::BsNone, nullptr);
257 pComponent->from_protobuf(kvComponentMsg.second);
258 m_componentsByName[kvComponentMsg.first] = pComponent;
259 }
260
261 for (const auto& pPartMsg : message.parts())
262 {
263 auto pPart = std::make_shared<Part>("");
264 pPart->from_protobuf(pPartMsg);
265 m_parts.push_back(pPart);
266 }
267
268 for (const auto& kvPartMsg : message.partsbyname())
269 {
270 auto pPart = std::make_shared<Part>("");
271 pPart->from_protobuf(kvPartMsg.second);
272 m_partsByName[kvPartMsg.first] = pPart;
273 }
274 }
275
276 bool Design::BuildAllComponents()
277 {
278 if (m_pFileModel == nullptr) return false;
279 const auto& steps = m_pFileModel->GetStepsByName();
280 if (steps.empty()) return false;
281 auto& pStepDirectory = steps.begin()->second;
282
283 // top components layer
284 auto pTopComponentsFile = pStepDirectory->GetTopComponentsFile();
285 if (pTopComponentsFile == nullptr) return false;
286 if (! BuildComponents(pTopComponentsFile)) return false;
287
288 // bottom layer components
289 auto pBottomComponentsFile = pStepDirectory->GetBottomComponentsFile();
290 if (pBottomComponentsFile == nullptr) return false;
291 if (!BuildComponents(pBottomComponentsFile)) return false;
292
293 return true;
294 }
295
296 bool Design::BuildComponents(const Odb::Lib::FileModel::Design::ComponentsFile* pComponentsFile)
297 {
298 const auto& componentRecords = pComponentsFile->GetComponentRecords();
299 for (const auto& pComponentRecord : componentRecords)
300 {
301 auto& pPackage = m_packages[pComponentRecord->pkgRef];
302 auto index = pComponentRecord->index;
303 auto& pPart = m_partsByName[pComponentRecord->partName];
304 auto pComponent = std::make_shared<Component>(pComponentRecord->compName, pComponentRecord->partName, pPackage, index, pComponentsFile->GetSide(), pPart);
305
306 m_components.push_back(pComponent);
307 m_componentsByName[pComponent->GetRefDes()] = pComponent;
308 }
309
310 return true;
311 }
312
313 bool Design::BuildVias()
314 {
315 return false;
316 }
317
318 bool Design::BuildNets()
319 {
320 if (m_pFileModel == nullptr) return false;
321
322 const auto& steps = m_pFileModel->GetStepsByName();
323 if (steps.empty()) return false;
324
325 auto& pStepDirectory = steps.begin()->second;
326 const auto& edaData = pStepDirectory->GetEdaDataFile();
327 const auto& netRecords = edaData.GetNetRecords();
328
329 for (const auto& pNetRecord : netRecords)
330 {
331 auto pNet = std::make_shared<Net>(pNetRecord->name, pNetRecord->index);
332 m_nets.push_back(pNet);
333 m_netsByName[pNet->GetName()] = pNet;
334 }
335
336 return true;
337 }
338
339 bool Design::BuildPackages()
340 {
341 if (m_pFileModel == nullptr) return false;
342
343 const auto& steps = m_pFileModel->GetStepsByName();
344 if (steps.empty()) return false;
345
346 auto& pStepDirectory = steps.begin()->second;
347 const auto& edaData = pStepDirectory->GetEdaDataFile();
348 const auto& packageRecords = edaData.GetPackageRecords();
349
350 for (const auto& pPackageRecord : packageRecords)
351 {
352 auto index = pPackageRecord->index;
353 auto pPackage = std::make_shared<Package>(pPackageRecord->name, index);
354
355 for (const auto& pPinRecord : pPackageRecord->m_pinRecords)
356 {
357 // TODO: figure out how to handle size_t -> non-size_t conversion
358 pPackage->AddPin(pPinRecord->name);
359 }
360
361 m_packages.push_back(pPackage);
362 m_packagesByName[pPackage->GetName()] = pPackage;
363 }
364
365 return true;
366 }
367
368 bool Design::BuildAllParts()
369 {
370 if (m_pFileModel == nullptr) return false;
371
372 const auto& steps = m_pFileModel->GetStepsByName();
373 if (steps.empty()) return false;
374
375 auto& pStepDirectory = steps.begin()->second;
376
377 auto pTopComponentsFile = pStepDirectory->GetTopComponentsFile();
378 if (pTopComponentsFile == nullptr) return false;
379 if (! BuildParts(pTopComponentsFile)) return false;
380
381 auto pBottomComponentsFile = pStepDirectory->GetBottomComponentsFile();
382 if (pBottomComponentsFile == nullptr) return false;
383 if (! BuildParts(pBottomComponentsFile)) return false;
384
385 return true;
386 }
387
388 bool Design::BuildParts(const Odb::Lib::FileModel::Design::ComponentsFile* pComponentsFile)
389 {
390 const auto& componentRecords = pComponentsFile->GetComponentRecords();
391 for (const auto& pComponentRecord : componentRecords)
392 {
393 auto& partName = pComponentRecord->partName;
394 auto findIt = m_partsByName.find(partName);
395 if (findIt == m_partsByName.end())
396 {
397 auto pPart = std::make_shared<Part>(partName);
398 m_parts.push_back(pPart);
399 m_partsByName[partName] = pPart;
400 }
401 }
402
403 return true;
404 }
405
406 bool Design::BuildPlacementsFromComponentsFiles()
407 {
408 if (m_pFileModel == nullptr) return false;
409
410 const auto& steps = m_pFileModel->GetStepsByName();
411 if (steps.empty()) return false;
412
413 // "first" step when there are >1 steps
414 auto& pStepDirectory = steps.begin()->second;
415
416 auto pTopComponentsFile = pStepDirectory->GetTopComponentsFile();
417 if (pTopComponentsFile == nullptr) return false;
418 if (! BuildPlacementsFromComponentsFile(pTopComponentsFile)) return false;
419
420 auto pBottomComponentsFile = pStepDirectory->GetBottomComponentsFile();
421 if (pBottomComponentsFile == nullptr) return false;
422 if (!BuildPlacementsFromComponentsFile(pBottomComponentsFile)) return false;
423
424 return true;
425 }
426
427 bool Design::BuildPlacementsFromComponentsFile(const Odb::Lib::FileModel::Design::ComponentsFile* pComponentsFile)
428 {
429 const auto& componentRecords = pComponentsFile->GetComponentRecords();
430 for (const auto& pComponentRecord : componentRecords)
431 {
432 const auto& toeprintRecords = pComponentRecord->m_toeprintRecords;
433 for (const auto& pToeprintRecord : toeprintRecords)
434 {
435 auto& toeprintName = pToeprintRecord->name;
436 auto pinNumber = pToeprintRecord->pinNumber;
437 auto netNumber = pToeprintRecord->netNumber;
438 auto& refDes = pComponentRecord->compName;
439 //auto subnetNumber = pToeprintRecord->subnetNumber;
440
441 // -1 means no connection for the component pin
442 if (netNumber != static_cast<unsigned int>(-1))
443 {
444 if (!CreatePinConnection(refDes, netNumber, pinNumber, toeprintName)) return false;
445 }
446 }
447 }
448
449 return true;
450 }
451
452 bool Design::CreatePinConnection(const std::string& refDes, unsigned int netNumber, unsigned int pinNumber, const std::string& pinName)
453 {
454 if (netNumber < m_nets.size())
455 {
456 auto& pComponent = m_componentsByName[refDes];
457 if (pComponent == nullptr) return false;
458
459 auto pPin = pComponent->GetPackage()->GetPin(pinNumber);
460 if (pPin == nullptr) return false;
461
462 auto& pNet = m_nets[netNumber];
463 if (pNet == nullptr) return false;
464
465 if (!pNet->AddPinConnection(pComponent, pPin)) return false;
466 return true;
467 }
468 else
469 {
470 logwarn("netNumber out of range: " + std::to_string(netNumber) + ", size = " + std::to_string(m_nets.size()));
471 }
472
473 return false;
474 }
475
476 bool Design::BuildNoneNet()
477 {
478 auto pStepDirectory = m_pFileModel->GetStepDirectory();
479 if (pStepDirectory == nullptr) return false;
480
481 const auto& edaData = pStepDirectory->GetEdaDataFile();
482 auto findIt = edaData.GetNetRecordsByName().find(NONE_NET_NAME);
483 if (findIt == edaData.GetNetRecordsByName().end()) return false;
484
485 auto& pNoneNet = findIt->second;
486 if (pNoneNet == nullptr) return false;
487
488 if (!CreateNetConnections(pNoneNet, pStepDirectory)) return false;
489
490 return true;
491 }
492
493 bool Design::BreakSinglePinNets()
494 {
495 const auto& pNoneNet = GetNoneNet();
496 if (pNoneNet == nullptr) return false;
497
498 auto& pinConnections = pNoneNet->GetPinConnections();
499 while (!pinConnections.empty())
500 {
501 const auto& pExistingPinConnection = pinConnections.back();
502
503 std::string newNetName = "$NC_" + pExistingPinConnection->GetComponent()->GetRefDes() + "_" + pExistingPinConnection->GetPin()->GetName();
504 auto pNewNet = std::make_shared<Net>(newNetName, -1);
505 pNewNet->AddPinConnection(pExistingPinConnection->GetComponent(), pExistingPinConnection->GetPin());
506 m_nets.push_back(pNewNet);
507 m_netsByName[pNewNet->GetName()] = pNewNet;
508
509 pinConnections.pop_back();
510 }
511
512 return true;
513 }
514
515 bool Design::BuildPlacementsFromEdaDataFile()
516 {
517 auto pStepDirectory = m_pFileModel->GetStepDirectory();
518 if (pStepDirectory == nullptr) return false;
519
520 const auto& edaData = pStepDirectory->GetEdaDataFile();
521
522 for (const auto& pNetRecord : edaData.GetNetRecords())
523 {
524 if (!CreateNetConnections(pNetRecord, pStepDirectory)) return false;
525 }
526
527 return true;
528 }
529
530 bool Design::CreateNetConnections(const std::shared_ptr<Odb::Lib::FileModel::Design::EdaDataFile::NetRecord>& pNetRecord, const std::shared_ptr<FileModel::Design::StepDirectory>& pStepDirectory)
531 {
532 for (const auto& pSubnetRecord : pNetRecord->m_subnetRecords)
533 {
534 if (pSubnetRecord->type == FileModel::Design::EdaDataFile::NetRecord::SubnetRecord::Type::Toeprint)
535 {
536 const FileModel::Design::ComponentsFile* pComponentsFileToUse = nullptr;
537
538 auto side = pSubnetRecord->side;
539 if (side == BoardSide::Top)
540 {
541 pComponentsFileToUse = pStepDirectory->GetTopComponentsFile();
542 }
543 else //if (side == BoardSide::Bottom)
544 {
545 pComponentsFileToUse = pStepDirectory->GetBottomComponentsFile();
546 }
547
548 if (pComponentsFileToUse == nullptr) return false;
549
550 auto componentNumber = pSubnetRecord->componentNumber;
551 if (componentNumber >= pComponentsFileToUse->GetComponentRecords().size()) return false;
552
553 auto& pComponentRecord = pComponentsFileToUse->GetComponentRecords()[componentNumber];
554 if (pComponentRecord == nullptr) return false;
555
556 auto toeprintNumber = pSubnetRecord->toeprintNumber;
557 if (toeprintNumber >= pComponentRecord->m_toeprintRecords.size()) return false;
558
559 auto& pToeprintRecord = pComponentRecord->m_toeprintRecords[toeprintNumber];
560 if (pToeprintRecord == nullptr) return false;
561
562 auto& toeprintName = pToeprintRecord->name;
563 auto pinNumber = pToeprintRecord->pinNumber;
564 auto netNumber = pToeprintRecord->netNumber;
565 auto& refDes = pComponentRecord->compName;
566 //auto subnetNumber = pToeprintRecord->subnetNumber;
567
568 if (!CreatePinConnection(refDes, netNumber, pinNumber, toeprintName)) return false;
569 }
570 else if (pSubnetRecord->type == FileModel::Design::EdaDataFile::NetRecord::SubnetRecord::Type::Via)
571 {
572 // ?
573 }
574 }
575
576 return true;
577 }
578
579} // namespace Odb::Lib::ProductModel