OdbDesignLib
OdbDesign ODB++ Parsing Library
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 
13 namespace 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