7#include "ProtobufMapHelpers.h"
10#include "../FileModel/Design/FileArchive.h"
11#include "../FileModel/Design/EdaDataFile.h"
12#include "../Text/Utf8Sanitizer.h"
15namespace Odb::Lib::ProductModel
24 m_componentsByName.clear();
28 m_packagesByName.clear();
30 m_partsByName.clear();
33 const std::string& Design::GetName()
const
38 const std::string& Design::GetProductModel()
const
40 return m_productModel;
43 const Net::Vector& Design::GetNets()
const
48 const Net::StringMap Design::GetNetsByName()
const
53 const Package::Vector& Design::GetPackages()
const
58 const Package::StringMap& Design::GetPackagesByName()
const
60 return m_packagesByName;
63 const Component::Vector& Design::GetComponents()
const
68 const Component::StringMap& Design::GetComponentsByName()
const
70 return m_componentsByName;
73 std::shared_ptr<Component> Design::GetComponent(
const std::string& refDes)
const
75 auto findIt = m_componentsByName.find(refDes);
76 if (findIt != m_componentsByName.end())
78 return findIt->second;
84 const Part::Vector& Design::GetParts()
const
89 const Part::StringMap& Design::GetPartsByName()
const
94 std::shared_ptr<Net> Design::GetNet(
const std::string& name)
const
96 auto findIt = m_netsByName.find(name);
97 if (findIt != m_netsByName.end())
99 return findIt->second;
104 std::shared_ptr<Net> Design::GetNoneNet()
const
106 return GetNet(NONE_NET_NAME);
109 bool Design::Build(std::string path)
111 auto pFileModel = std::make_shared<FileModel::Design::FileArchive>(path);
112 if (pFileModel->ParseFileModel())
114 return Build(pFileModel);
119 bool Design::Build(std::shared_ptr<FileModel::Design::FileArchive> pFileModel)
121 if (pFileModel ==
nullptr)
return false;
123 m_pFileModel = pFileModel;
129 if (! BuildNets())
return false;
130 if (! BuildPackages())
return false;
131 if (! BuildAllParts())
return false;
132 if (! BuildAllComponents())
return false;
135 if (! BuildPlacementsFromComponentsFiles())
return false;
141 if (CLIP_FILEMODEL_AFTER_BUILD)
149 std::shared_ptr<FileModel::Design::FileArchive> Design::GetFileModel()
const
154 void Design::ClipFileModel()
156 m_pFileModel =
nullptr;
159 std::unique_ptr<Odb::Lib::Protobuf::ProductModel::Design> Design::to_protobuf()
const
161 auto pDesignMsg = std::make_unique<Odb::Lib::Protobuf::ProductModel::Design>();
162 pDesignMsg->set_name(Odb::Lib::Text::ToUtf8(m_name));
163 pDesignMsg->set_productmodel(Odb::Lib::Text::ToUtf8(m_productModel));
165 if (m_pFileModel !=
nullptr)
167 pDesignMsg->mutable_filemodel()->CopyFrom(*m_pFileModel->to_protobuf());
170 for (
const auto& pNet : m_nets)
172 pDesignMsg->add_nets()->CopyFrom(*pNet->to_protobuf());
175 FillProtobufMapWithSanitizedKeys(*pDesignMsg->mutable_netsbyname(), m_netsByName);
177 for (
const auto& pPackage : m_packages)
179 pDesignMsg->add_packages()->CopyFrom(*pPackage->to_protobuf());
182 FillProtobufMapWithSanitizedKeys(*pDesignMsg->mutable_packagesbyname(), m_packagesByName);
184 for (
const auto& pComponent : m_components)
186 pDesignMsg->add_components()->CopyFrom(*pComponent->to_protobuf());
189 FillProtobufMapWithSanitizedKeys(*pDesignMsg->mutable_componentsbyname(), m_componentsByName);
191 for (
const auto& pPart : m_parts)
193 pDesignMsg->add_parts()->CopyFrom(*pPart->to_protobuf());
196 FillProtobufMapWithSanitizedKeys(*pDesignMsg->mutable_partsbyname(), m_partsByName);
206 void Design::from_protobuf(
const Odb::Lib::Protobuf::ProductModel::Design& message)
208 m_name = message.name();
209 m_productModel = message.productmodel();
211 m_pFileModel = std::make_shared<FileModel::Design::FileArchive>();
212 m_pFileModel->from_protobuf(message.filemodel());
214 for (
const auto& pNetMsg : message.nets())
216 auto pNet = std::make_shared<Net>(
"", -1);
217 pNet->from_protobuf(pNetMsg);
218 m_nets.push_back(pNet);
221 for (
const auto& kvNetMsg : message.netsbyname())
223 auto pNet = std::make_shared<Net>(
"", -1);
224 pNet->from_protobuf(kvNetMsg.second);
225 m_netsByName[kvNetMsg.first] = pNet;
228 for (
const auto& pPackageMsg : message.packages())
230 auto pPackage = std::make_shared<Package>(
"", -1);
231 pPackage->from_protobuf(pPackageMsg);
232 m_packages.push_back(pPackage);
235 for (
const auto& kvPackageMsg : message.packagesbyname())
237 auto pPackage = std::make_shared<Package>(
"", -1);
238 pPackage->from_protobuf(kvPackageMsg.second);
239 m_packagesByName[kvPackageMsg.first] = pPackage;
242 for (
const auto& pComponentMsg : message.components())
244 auto pComponent = std::make_shared<Component>(
"",
"",
nullptr, -1, BoardSide::BsNone,
nullptr);
245 pComponent->from_protobuf(pComponentMsg);
246 m_components.push_back(pComponent);
249 for (
const auto& kvComponentMsg : message.componentsbyname())
251 auto pComponent = std::make_shared<Component>(
"",
"",
nullptr, -1, BoardSide::BsNone,
nullptr);
252 pComponent->from_protobuf(kvComponentMsg.second);
253 m_componentsByName[kvComponentMsg.first] = pComponent;
256 for (
const auto& pPartMsg : message.parts())
258 auto pPart = std::make_shared<Part>(
"");
259 pPart->from_protobuf(pPartMsg);
260 m_parts.push_back(pPart);
263 for (
const auto& kvPartMsg : message.partsbyname())
265 auto pPart = std::make_shared<Part>(
"");
266 pPart->from_protobuf(kvPartMsg.second);
267 m_partsByName[kvPartMsg.first] = pPart;
271 bool Design::BuildAllComponents()
273 if (m_pFileModel ==
nullptr)
return false;
274 const auto& steps = m_pFileModel->GetStepsByName();
275 if (steps.empty())
return false;
276 auto& pStepDirectory = steps.begin()->second;
279 auto pTopComponentsFile = pStepDirectory->GetTopComponentsFile();
280 if (pTopComponentsFile ==
nullptr)
return false;
281 if (! BuildComponents(pTopComponentsFile))
return false;
284 auto pBottomComponentsFile = pStepDirectory->GetBottomComponentsFile();
285 if (pBottomComponentsFile ==
nullptr)
return false;
286 if (!BuildComponents(pBottomComponentsFile))
return false;
293 const auto& componentRecords = pComponentsFile->GetComponentRecords();
294 for (
const auto& pComponentRecord : componentRecords)
296 auto& pPackage = m_packages[pComponentRecord->pkgRef];
297 auto index = pComponentRecord->index;
298 auto& pPart = m_partsByName[pComponentRecord->partName];
299 auto pComponent = std::make_shared<Component>(pComponentRecord->compName, pComponentRecord->partName, pPackage, index, pComponentsFile->GetSide(), pPart);
301 m_components.push_back(pComponent);
302 m_componentsByName[pComponent->GetRefDes()] = pComponent;
308 bool Design::BuildVias()
313 bool Design::BuildNets()
315 if (m_pFileModel ==
nullptr)
return false;
317 const auto& steps = m_pFileModel->GetStepsByName();
318 if (steps.empty())
return false;
320 auto& pStepDirectory = steps.begin()->second;
321 const auto& edaData = pStepDirectory->GetEdaDataFile();
322 const auto& netRecords = edaData.GetNetRecords();
324 for (
const auto& pNetRecord : netRecords)
326 auto pNet = std::make_shared<Net>(pNetRecord->name, pNetRecord->index);
327 m_nets.push_back(pNet);
328 m_netsByName[pNet->GetName()] = pNet;
334 bool Design::BuildPackages()
336 if (m_pFileModel ==
nullptr)
return false;
338 const auto& steps = m_pFileModel->GetStepsByName();
339 if (steps.empty())
return false;
341 auto& pStepDirectory = steps.begin()->second;
342 const auto& edaData = pStepDirectory->GetEdaDataFile();
343 const auto& packageRecords = edaData.GetPackageRecords();
345 for (
const auto& pPackageRecord : packageRecords)
347 auto index = pPackageRecord->index;
348 auto pPackage = std::make_shared<Package>(pPackageRecord->name, index);
350 for (
const auto& pPinRecord : pPackageRecord->m_pinRecords)
353 pPackage->AddPin(pPinRecord->name);
356 m_packages.push_back(pPackage);
357 m_packagesByName[pPackage->GetName()] = pPackage;
363 bool Design::BuildAllParts()
365 if (m_pFileModel ==
nullptr)
return false;
367 const auto& steps = m_pFileModel->GetStepsByName();
368 if (steps.empty())
return false;
370 auto& pStepDirectory = steps.begin()->second;
372 auto pTopComponentsFile = pStepDirectory->GetTopComponentsFile();
373 if (pTopComponentsFile ==
nullptr)
return false;
374 if (! BuildParts(pTopComponentsFile))
return false;
376 auto pBottomComponentsFile = pStepDirectory->GetBottomComponentsFile();
377 if (pBottomComponentsFile ==
nullptr)
return false;
378 if (! BuildParts(pBottomComponentsFile))
return false;
385 const auto& componentRecords = pComponentsFile->GetComponentRecords();
386 for (
const auto& pComponentRecord : componentRecords)
388 auto& partName = pComponentRecord->partName;
389 auto findIt = m_partsByName.find(partName);
390 if (findIt == m_partsByName.end())
392 auto pPart = std::make_shared<Part>(partName);
393 m_parts.push_back(pPart);
394 m_partsByName[partName] = pPart;
401 bool Design::BuildPlacementsFromComponentsFiles()
403 if (m_pFileModel ==
nullptr)
return false;
405 const auto& steps = m_pFileModel->GetStepsByName();
406 if (steps.empty())
return false;
409 auto& pStepDirectory = steps.begin()->second;
411 auto pTopComponentsFile = pStepDirectory->GetTopComponentsFile();
412 if (pTopComponentsFile ==
nullptr)
return false;
413 if (! BuildPlacementsFromComponentsFile(pTopComponentsFile))
return false;
415 auto pBottomComponentsFile = pStepDirectory->GetBottomComponentsFile();
416 if (pBottomComponentsFile ==
nullptr)
return false;
417 if (!BuildPlacementsFromComponentsFile(pBottomComponentsFile))
return false;
424 const auto& componentRecords = pComponentsFile->GetComponentRecords();
425 for (
const auto& pComponentRecord : componentRecords)
427 const auto& toeprintRecords = pComponentRecord->m_toeprintRecords;
428 for (
const auto& pToeprintRecord : toeprintRecords)
430 auto& toeprintName = pToeprintRecord->name;
431 auto pinNumber = pToeprintRecord->pinNumber;
432 auto netNumber = pToeprintRecord->netNumber;
433 auto& refDes = pComponentRecord->compName;
437 if (netNumber !=
static_cast<unsigned int>(-1))
439 if (!CreatePinConnection(refDes, netNumber, pinNumber, toeprintName))
return false;
447 bool Design::CreatePinConnection(
const std::string& refDes,
unsigned int netNumber,
unsigned int pinNumber,
const std::string& pinName)
449 if (netNumber < m_nets.size())
451 auto& pComponent = m_componentsByName[refDes];
452 if (pComponent ==
nullptr)
return false;
454 auto pPin = pComponent->GetPackage()->GetPin(pinNumber);
455 if (pPin ==
nullptr)
return false;
457 auto& pNet = m_nets[netNumber];
458 if (pNet ==
nullptr)
return false;
460 if (!pNet->AddPinConnection(pComponent, pPin))
return false;
465 logwarn(
"netNumber out of range: " + std::to_string(netNumber) +
", size = " + std::to_string(m_nets.size()));
471 bool Design::BuildNoneNet()
473 auto pStepDirectory = m_pFileModel->GetStepDirectory();
474 if (pStepDirectory ==
nullptr)
return false;
476 const auto& edaData = pStepDirectory->GetEdaDataFile();
477 auto findIt = edaData.GetNetRecordsByName().find(NONE_NET_NAME);
478 if (findIt == edaData.GetNetRecordsByName().end())
return false;
480 auto& pNoneNet = findIt->second;
481 if (pNoneNet ==
nullptr)
return false;
483 if (!CreateNetConnections(pNoneNet, pStepDirectory))
return false;
488 bool Design::BreakSinglePinNets()
490 const auto& pNoneNet = GetNoneNet();
491 if (pNoneNet ==
nullptr)
return false;
493 auto& pinConnections = pNoneNet->GetPinConnections();
494 while (!pinConnections.empty())
496 const auto& pExistingPinConnection = pinConnections.back();
498 std::string newNetName =
"$NC_" + pExistingPinConnection->GetComponent()->GetRefDes() +
"_" + pExistingPinConnection->GetPin()->GetName();
499 auto pNewNet = std::make_shared<Net>(newNetName, -1);
500 pNewNet->AddPinConnection(pExistingPinConnection->GetComponent(), pExistingPinConnection->GetPin());
501 m_nets.push_back(pNewNet);
502 m_netsByName[pNewNet->GetName()] = pNewNet;
504 pinConnections.pop_back();
510 bool Design::BuildPlacementsFromEdaDataFile()
512 auto pStepDirectory = m_pFileModel->GetStepDirectory();
513 if (pStepDirectory ==
nullptr)
return false;
515 const auto& edaData = pStepDirectory->GetEdaDataFile();
517 for (
const auto& pNetRecord : edaData.GetNetRecords())
519 if (!CreateNetConnections(pNetRecord, pStepDirectory))
return false;
525 bool Design::CreateNetConnections(
const std::shared_ptr<Odb::Lib::FileModel::Design::EdaDataFile::NetRecord>& pNetRecord,
const std::shared_ptr<FileModel::Design::StepDirectory>& pStepDirectory)
527 for (
const auto& pSubnetRecord : pNetRecord->m_subnetRecords)
529 if (pSubnetRecord->type == FileModel::Design::EdaDataFile::NetRecord::SubnetRecord::Type::Toeprint)
531 const FileModel::Design::ComponentsFile* pComponentsFileToUse =
nullptr;
533 auto side = pSubnetRecord->side;
534 if (side == BoardSide::Top)
536 pComponentsFileToUse = pStepDirectory->GetTopComponentsFile();
540 pComponentsFileToUse = pStepDirectory->GetBottomComponentsFile();
543 if (pComponentsFileToUse ==
nullptr)
return false;
545 auto componentNumber = pSubnetRecord->componentNumber;
546 if (componentNumber >= pComponentsFileToUse->GetComponentRecords().size())
return false;
548 auto& pComponentRecord = pComponentsFileToUse->GetComponentRecords()[componentNumber];
549 if (pComponentRecord ==
nullptr)
return false;
551 auto toeprintNumber = pSubnetRecord->toeprintNumber;
552 if (toeprintNumber >= pComponentRecord->m_toeprintRecords.size())
return false;
554 auto& pToeprintRecord = pComponentRecord->m_toeprintRecords[toeprintNumber];
555 if (pToeprintRecord ==
nullptr)
return false;
557 auto& toeprintName = pToeprintRecord->name;
558 auto pinNumber = pToeprintRecord->pinNumber;
559 auto netNumber = pToeprintRecord->netNumber;
560 auto& refDes = pComponentRecord->compName;
563 if (!CreatePinConnection(refDes, netNumber, pinNumber, toeprintName))
return false;
565 else if (pSubnetRecord->type == FileModel::Design::EdaDataFile::NetRecord::SubnetRecord::Type::Via)
void AssertAllStringFieldsAreValidUtf8(const google::protobuf::Message &msg, std::string_view msgName)
Debug-only assertion to verify all string fields in a message are valid UTF-8.