You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

871 lines
27 KiB

  1. /*
  2. * This program source code file is part of KiCad, a free EDA CAD application.
  3. *
  4. * Copyright (C) 2018 Jean-Pierre Charras, jp.charras at wanadoo.fr
  5. * Copyright (C) 2013 Wayne Stambaugh <stambaughw@gmail.com>
  6. * Copyright (C) 1992-2018 KiCad Developers, see AUTHORS.txt for contributors.
  7. *
  8. * This program is free software; you can redistribute it and/or
  9. * modify it under the terms of the GNU General Public License
  10. * as published by the Free Software Foundation; either version 2
  11. * of the License, or (at your option) any later version.
  12. *
  13. * This program is distributed in the hope that it will be useful,
  14. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  15. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  16. * GNU General Public License for more details.
  17. *
  18. * You should have received a copy of the GNU General Public License
  19. * along with this program; if not, you may find one here:
  20. * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
  21. * or you may search the http://www.gnu.org website for the version 2 license,
  22. * or you may write to the Free Software Foundation, Inc.,
  23. * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
  24. */
  25. #include <netlist_object.h>
  26. #include <class_library.h>
  27. #include <macros.h>
  28. #include <sch_junction.h>
  29. #include <sch_component.h>
  30. #include <sch_line.h>
  31. #include <sch_text.h>
  32. #include <sch_screen.h>
  33. #include <sch_sheet.h>
  34. #include <algorithm>
  35. #define IS_WIRE false
  36. #define IS_BUS true
  37. //#define NETLIST_DEBUG
  38. NETLIST_OBJECT_LIST::~NETLIST_OBJECT_LIST()
  39. {
  40. Clear();
  41. }
  42. void NETLIST_OBJECT_LIST::Clear()
  43. {
  44. NETLIST_OBJECTS::iterator iter;
  45. for( iter = begin(); iter != end(); iter++ )
  46. {
  47. NETLIST_OBJECT* item = *iter;
  48. delete item;
  49. }
  50. clear();
  51. }
  52. void NETLIST_OBJECT_LIST::SortListbyNetcode()
  53. {
  54. sort( this->begin(), this->end(), NETLIST_OBJECT_LIST::sortItemsbyNetcode );
  55. }
  56. void NETLIST_OBJECT_LIST::SortListbySheet()
  57. {
  58. sort( this->begin(), this->end(), NETLIST_OBJECT_LIST::sortItemsBySheet );
  59. }
  60. bool NETLIST_OBJECT_LIST::BuildNetListInfo( SCH_SHEET_LIST& aSheets )
  61. {
  62. SCH_SHEET_PATH* sheet;
  63. // Fill list with connected items from the flattened sheet list
  64. for( unsigned i = 0; i < aSheets.size(); i++ )
  65. {
  66. sheet = &aSheets[i];
  67. for( auto item : sheet->LastScreen()->Items() )
  68. item->GetNetListItem( *this, sheet );
  69. }
  70. if( size() == 0 )
  71. return false;
  72. // Sort objects by Sheet
  73. SortListbySheet();
  74. sheet = &(GetItem( 0 )->m_SheetPath);
  75. m_lastNetCode = m_lastBusNetCode = 1;
  76. for( unsigned ii = 0, istart = 0; ii < size(); ii++ )
  77. {
  78. NETLIST_OBJECT* net_item = GetItem( ii );
  79. if( net_item->m_SheetPath != *sheet ) // Sheet change
  80. {
  81. sheet = &(net_item->m_SheetPath);
  82. istart = ii;
  83. }
  84. switch( net_item->m_Type )
  85. {
  86. case NETLIST_ITEM::ITEM_UNSPECIFIED:
  87. wxMessageBox( wxT( "BuildNetListInfo() error" ) );
  88. break;
  89. case NETLIST_ITEM::PIN:
  90. case NETLIST_ITEM::PINLABEL:
  91. case NETLIST_ITEM::SHEETLABEL:
  92. case NETLIST_ITEM::NOCONNECT:
  93. if( net_item->GetNet() != 0 )
  94. break;
  95. // Intentionally fall through if there is no net assigned
  96. KI_FALLTHROUGH;
  97. case NETLIST_ITEM::SEGMENT:
  98. // Test connections point to point type without bus.
  99. if( net_item->GetNet() == 0 )
  100. {
  101. net_item->SetNet( m_lastNetCode );
  102. m_lastNetCode++;
  103. }
  104. pointToPointConnect( net_item, IS_WIRE, istart );
  105. break;
  106. case NETLIST_ITEM::JUNCTION:
  107. // Control of the junction outside BUS.
  108. if( net_item->GetNet() == 0 )
  109. {
  110. net_item->SetNet( m_lastNetCode );
  111. m_lastNetCode++;
  112. }
  113. segmentToPointConnect( net_item, IS_WIRE, istart );
  114. // Control of the junction, on BUS.
  115. if( net_item->m_BusNetCode == 0 )
  116. {
  117. net_item->m_BusNetCode = m_lastBusNetCode;
  118. m_lastBusNetCode++;
  119. }
  120. segmentToPointConnect( net_item, IS_BUS, istart );
  121. break;
  122. case NETLIST_ITEM::LABEL:
  123. case NETLIST_ITEM::HIERLABEL:
  124. case NETLIST_ITEM::GLOBLABEL:
  125. // Test connections type junction without bus.
  126. if( net_item->GetNet() == 0 )
  127. {
  128. net_item->SetNet( m_lastNetCode );
  129. m_lastNetCode++;
  130. }
  131. segmentToPointConnect( net_item, IS_WIRE, istart );
  132. break;
  133. case NETLIST_ITEM::SHEETBUSLABELMEMBER:
  134. if( net_item->m_BusNetCode != 0 )
  135. break;
  136. // Intentionally fall through if there is no bus assigned
  137. KI_FALLTHROUGH;
  138. case NETLIST_ITEM::BUS:
  139. // Control type connections point to point mode bus
  140. if( net_item->m_BusNetCode == 0 )
  141. {
  142. net_item->m_BusNetCode = m_lastBusNetCode;
  143. m_lastBusNetCode++;
  144. }
  145. pointToPointConnect( net_item, IS_BUS, istart );
  146. break;
  147. case NETLIST_ITEM::BUSLABELMEMBER:
  148. case NETLIST_ITEM::HIERBUSLABELMEMBER:
  149. case NETLIST_ITEM::GLOBBUSLABELMEMBER:
  150. // Control connections similar has on BUS
  151. if( net_item->GetNet() == 0 )
  152. {
  153. net_item->m_BusNetCode = m_lastBusNetCode;
  154. m_lastBusNetCode++;
  155. }
  156. segmentToPointConnect( net_item, IS_BUS, istart );
  157. break;
  158. }
  159. }
  160. #if defined(NETLIST_DEBUG) && defined(DEBUG)
  161. std::cout << "\n\nafter sheet local\n\n";
  162. DumpNetTable();
  163. #endif
  164. // Updating the Bus Labels Netcode connected by Bus
  165. connectBusLabels();
  166. // Group objects by label.
  167. for( unsigned ii = 0; ii < size(); ii++ )
  168. {
  169. switch( GetItem( ii )->m_Type )
  170. {
  171. case NETLIST_ITEM::PIN:
  172. case NETLIST_ITEM::SHEETLABEL:
  173. case NETLIST_ITEM::SEGMENT:
  174. case NETLIST_ITEM::JUNCTION:
  175. case NETLIST_ITEM::BUS:
  176. case NETLIST_ITEM::NOCONNECT:
  177. break;
  178. case NETLIST_ITEM::LABEL:
  179. case NETLIST_ITEM::GLOBLABEL:
  180. case NETLIST_ITEM::PINLABEL:
  181. case NETLIST_ITEM::BUSLABELMEMBER:
  182. case NETLIST_ITEM::GLOBBUSLABELMEMBER:
  183. labelConnect( GetItem( ii ) );
  184. break;
  185. case NETLIST_ITEM::SHEETBUSLABELMEMBER:
  186. case NETLIST_ITEM::HIERLABEL:
  187. case NETLIST_ITEM::HIERBUSLABELMEMBER:
  188. break;
  189. case NETLIST_ITEM::ITEM_UNSPECIFIED:
  190. break;
  191. }
  192. }
  193. #if defined(NETLIST_DEBUG) && defined(DEBUG)
  194. std::cout << "\n\nafter sheet global\n\n";
  195. DumpNetTable();
  196. #endif
  197. // Connection between hierarchy sheets
  198. for( unsigned ii = 0; ii < size(); ii++ )
  199. {
  200. if( GetItem( ii )->m_Type == NETLIST_ITEM::SHEETLABEL
  201. || GetItem( ii )->m_Type == NETLIST_ITEM::SHEETBUSLABELMEMBER )
  202. sheetLabelConnect( GetItem( ii ) );
  203. }
  204. // Sort objects by NetCode
  205. SortListbyNetcode();
  206. #if defined(NETLIST_DEBUG) && defined(DEBUG)
  207. std::cout << "\n\nafter qsort()\n";
  208. DumpNetTable();
  209. #endif
  210. // Compress numbers of Netcode having consecutive values.
  211. int NetCode = 0;
  212. m_lastNetCode = 0;
  213. for( unsigned ii = 0; ii < size(); ii++ )
  214. {
  215. if( GetItem( ii )->GetNet() != m_lastNetCode )
  216. {
  217. NetCode++;
  218. m_lastNetCode = GetItem( ii )->GetNet();
  219. }
  220. GetItem( ii )->SetNet( NetCode );
  221. }
  222. // Set the minimal connection info:
  223. setUnconnectedFlag();
  224. // find the best label object to give the best net name to each net
  225. findBestNetNameForEachNet();
  226. return true;
  227. }
  228. // Helper function to give a priority to sort labels:
  229. // NETLIST_ITEM::PINLABEL, NETLIST_ITEM::GLOBBUSLABELMEMBER and NETLIST_ITEM::GLOBLABEL are global labels
  230. // and the priority is high
  231. static int getPriority( const NETLIST_OBJECT* Objet )
  232. {
  233. switch( Objet->m_Type )
  234. {
  235. case NETLIST_ITEM::PIN:
  236. return 1;
  237. case NETLIST_ITEM::LABEL:
  238. return 2;
  239. case NETLIST_ITEM::HIERLABEL:
  240. return 3;
  241. case NETLIST_ITEM::PINLABEL:
  242. return 4;
  243. case NETLIST_ITEM::GLOBBUSLABELMEMBER:
  244. return 5;
  245. case NETLIST_ITEM::GLOBLABEL:
  246. return 6;
  247. default:
  248. break;
  249. }
  250. return 0;
  251. }
  252. /* function evalLabelsPriority used by findBestNetNameForEachNet()
  253. * evalLabelsPriority calculates the priority of alabel1 and aLabel2
  254. * return true if alabel1 has a higher priority than aLabel2
  255. */
  256. static bool evalLabelsPriority( const NETLIST_OBJECT* aLabel1, const NETLIST_OBJECT* aLabel2 )
  257. {
  258. // Global labels have the highest prioriy.
  259. // For local labels: names are prefixed by their sheetpath
  260. // use name defined in the more top level hierarchical sheet
  261. // Note: the final net name uses human sheetpath name, not timestamp sheetpath name
  262. // They are equivalent, but not for human readers.
  263. if( ! aLabel1->IsLabelGlobal() && ! aLabel2->IsLabelGlobal() )
  264. {
  265. if( aLabel1->m_SheetPath.size() != aLabel2->m_SheetPath.size() )
  266. return aLabel1->m_SheetPath.size() < aLabel2->m_SheetPath.size();
  267. }
  268. int priority1 = getPriority( aLabel1 );
  269. int priority2 = getPriority( aLabel2 );
  270. if( priority1 != priority2 )
  271. return priority1 > priority2;
  272. // Objects have here the same priority, therefore they have the same type.
  273. // for global labels, we select the best candidate by alphabetic order
  274. // because they have no sheetpath as prefix name
  275. // for other labels, we select them before by sheet deep order
  276. // because the actual name is /sheetpath/label
  277. // and for a given path length, by alphabetic order
  278. if( aLabel1->IsLabelGlobal() )
  279. return aLabel1->m_Label.Cmp( aLabel2->m_Label ) < 0;
  280. // Sheet paths have here the same length: use alphabetic label name order
  281. // For labels on sheets having an equivalent deep in hierarchy, use
  282. // alphabetic label name order:
  283. if( aLabel1->m_Label.Cmp( aLabel2->m_Label ) != 0 )
  284. return aLabel1->m_Label.Cmp( aLabel2->m_Label ) < 0;
  285. // For identical labels having the same priority: choose the
  286. // alphabetic label full name order
  287. return aLabel1->m_SheetPath.PathHumanReadable().Cmp(
  288. aLabel2->m_SheetPath.PathHumanReadable() ) < 0;
  289. }
  290. void NETLIST_OBJECT_LIST::findBestNetNameForEachNet()
  291. {
  292. // Important note: NETLIST_ITEM::SHEETLABEL items of sheet items should *NOT* be considered,
  293. // because they live in a sheet but their names are actually used in the subsheet.
  294. // Moreover, in the parent sheet, the name of NETLIST_ITEM::SHEETLABEL can be not unique,
  295. // ( for instance when 2 different sheets share the same schematic in complex hierarchies
  296. // and 2 identical NETLIST_ITEM::SHEETLABEL labels can be connected to 2 different nets
  297. int netcode = 0; // current netcode for tested items
  298. unsigned idxstart = 0; // index of the first item of this net
  299. NETLIST_OBJECT* item;
  300. NETLIST_OBJECT* candidate;
  301. // Pass 1: find the best name for labelled nets:
  302. candidate = NULL;
  303. for( unsigned ii = 0; ii <= size(); ii++ )
  304. {
  305. if( ii == size() ) // last item already tested
  306. item = NULL;
  307. else
  308. item = GetItem( ii );
  309. if( !item || netcode != item->GetNet() ) // End of net found
  310. {
  311. if( candidate ) // One or more labels exists, find the best
  312. {
  313. for (unsigned jj = idxstart; jj < ii; jj++ )
  314. GetItem( jj )->SetNetNameCandidate( candidate );
  315. }
  316. if( item == NULL ) // End of list
  317. break;
  318. // Prepare next net analysis:
  319. netcode = item->GetNet();
  320. candidate = NULL;
  321. idxstart = ii;
  322. }
  323. switch( item->m_Type )
  324. {
  325. case NETLIST_ITEM::HIERLABEL:
  326. case NETLIST_ITEM::LABEL:
  327. case NETLIST_ITEM::PINLABEL:
  328. case NETLIST_ITEM::GLOBLABEL:
  329. case NETLIST_ITEM::GLOBBUSLABELMEMBER:
  330. // A candidate is found: select the better between the previous and this one
  331. if( candidate == NULL )
  332. candidate = item;
  333. else
  334. {
  335. if( evalLabelsPriority( item, candidate ) )
  336. // item has a higher priority than candidate so update the best candidate
  337. candidate = item;
  338. }
  339. break;
  340. default:
  341. break;
  342. }
  343. }
  344. // Pass 2: find the best name for not labelled nets:
  345. // The "default" net name is Net-<<Ref cmp>_Pad<num pad>>
  346. // (see NETLIST_OBJECT::GetShortNetName())
  347. // therefore the "best" is the short net name alphabetically classed first
  348. // (to avoid net names changes when the net is not modified,
  349. // even if components are moved or deleted and undelete or replaced, as long
  350. // the reference is kept)
  351. // Build a list of items with no net names
  352. NETLIST_OBJECTS list; // no ownership of elements being pointed at
  353. for( unsigned ii = 0; ii < size(); ii++ )
  354. {
  355. item = GetItem( ii );
  356. if( !item->HasNetNameCandidate() )
  357. list.push_back( item );
  358. }
  359. if( list.size() == 0 )
  360. return;
  361. idxstart = 0;
  362. candidate = NULL;
  363. netcode = list[0]->GetNet();
  364. for( unsigned ii = 0; ii <= list.size(); ii++ )
  365. {
  366. if( ii < list.size() )
  367. item = list[ii];
  368. else
  369. item = NULL;
  370. if( !item || netcode != item->GetNet() ) // End of net found
  371. {
  372. if( candidate )
  373. {
  374. for (unsigned jj = idxstart; jj < ii; jj++ )
  375. {
  376. NETLIST_OBJECT* obj = list[jj];
  377. obj->SetNetNameCandidate( candidate );
  378. }
  379. }
  380. if( !item )
  381. break;
  382. netcode = item->GetNet();
  383. candidate = NULL;
  384. idxstart = ii;
  385. }
  386. // Examine all pins of the net to find the best candidate,
  387. // i.e. the first net name candidate, by alphabetic order
  388. // the net names are built by GetShortNetName
  389. // (Net-<{reference}-Pad{pad number}> like Net-<U3-Pad5>
  390. // Not named nets do not have usually a lot of members.
  391. // Many have only 2 members(a pad and a non connection symbol)
  392. if( item->m_Type == NETLIST_ITEM::PIN )
  393. {
  394. // A candidate is found, however components which are not in
  395. // netlist are not candidate because some have their reference
  396. // changed each time the netlist is built (power components)
  397. // and anyway obviously they are not a good candidate
  398. SCH_COMPONENT* link = item->GetComponentParent();
  399. if( link && link->IsInNetlist() )
  400. {
  401. // select the better between the previous and this one
  402. item->SetNetNameCandidate( item ); // Needed to calculate GetShortNetName
  403. if( candidate == NULL )
  404. candidate = item;
  405. else
  406. {
  407. if( item->GetShortNetName().Cmp( candidate->GetShortNetName() ) < 0 )
  408. candidate = item;
  409. }
  410. }
  411. }
  412. }
  413. }
  414. void NETLIST_OBJECT_LIST::sheetLabelConnect( NETLIST_OBJECT* SheetLabel )
  415. {
  416. if( SheetLabel->GetNet() == 0 )
  417. return;
  418. for( unsigned ii = 0; ii < size(); ii++ )
  419. {
  420. NETLIST_OBJECT* ObjetNet = GetItem( ii );
  421. if( ObjetNet->m_SheetPath != SheetLabel->m_SheetPathInclude )
  422. continue; //use SheetInclude, not the sheet!!
  423. if( ( ObjetNet->m_Type != NETLIST_ITEM::HIERLABEL )
  424. && ( ObjetNet->m_Type != NETLIST_ITEM::HIERBUSLABELMEMBER ) )
  425. continue;
  426. if( ObjetNet->GetNet() == SheetLabel->GetNet() )
  427. continue; //already connected.
  428. if( ObjetNet->m_Label != SheetLabel->m_Label )
  429. continue; //different names.
  430. // Propagate Netcode having all the objects of the same Netcode.
  431. if( ObjetNet->GetNet() )
  432. propagateNetCode( ObjetNet->GetNet(), SheetLabel->GetNet(), IS_WIRE );
  433. else
  434. ObjetNet->SetNet( SheetLabel->GetNet() );
  435. }
  436. }
  437. void NETLIST_OBJECT_LIST::connectBusLabels()
  438. {
  439. // Propagate the net code between all bus label member objects connected by they name.
  440. // If the net code is not yet existing, a new one is created
  441. // Search is done in the entire list
  442. for( unsigned ii = 0; ii < size(); ii++ )
  443. {
  444. NETLIST_OBJECT* Label = GetItem( ii );
  445. if( Label->IsLabelBusMemberType() )
  446. {
  447. if( Label->GetNet() == 0 )
  448. {
  449. // Not yet existiing net code: create a new one.
  450. Label->SetNet( m_lastNetCode );
  451. m_lastNetCode++;
  452. }
  453. for( unsigned jj = ii + 1; jj < size(); jj++ )
  454. {
  455. NETLIST_OBJECT* LabelInTst = GetItem( jj );
  456. if( LabelInTst->IsLabelBusMemberType() )
  457. {
  458. if( LabelInTst->m_BusNetCode != Label->m_BusNetCode )
  459. continue;
  460. if( LabelInTst->m_Member != Label->m_Member )
  461. continue;
  462. if( LabelInTst->GetNet() == 0 )
  463. // Append this object to the current net
  464. LabelInTst->SetNet( Label->GetNet() );
  465. else
  466. // Merge the 2 net codes, they are connected.
  467. propagateNetCode( LabelInTst->GetNet(), Label->GetNet(), IS_WIRE );
  468. }
  469. }
  470. }
  471. }
  472. }
  473. void NETLIST_OBJECT_LIST::propagateNetCode( int aOldNetCode, int aNewNetCode, bool aIsBus )
  474. {
  475. if( aOldNetCode == aNewNetCode )
  476. return;
  477. if( aIsBus == false ) // Propagate NetCode
  478. {
  479. for( unsigned jj = 0; jj < size(); jj++ )
  480. {
  481. NETLIST_OBJECT* object = GetItem( jj );
  482. if( object->GetNet() == aOldNetCode )
  483. object->SetNet( aNewNetCode );
  484. }
  485. }
  486. else // Propagate BusNetCode
  487. {
  488. for( unsigned jj = 0; jj < size(); jj++ )
  489. {
  490. NETLIST_OBJECT* object = GetItem( jj );
  491. if( object->m_BusNetCode == aOldNetCode )
  492. object->m_BusNetCode = aNewNetCode;
  493. }
  494. }
  495. }
  496. void NETLIST_OBJECT_LIST::pointToPointConnect( NETLIST_OBJECT* aRef, bool aIsBus, int start )
  497. {
  498. int netCode;
  499. if( aIsBus == false ) // Objects other than BUS and BUSLABELS
  500. {
  501. netCode = aRef->GetNet();
  502. for( unsigned i = start; i < size(); i++ )
  503. {
  504. NETLIST_OBJECT* item = GetItem( i );
  505. if( item->m_SheetPath != aRef->m_SheetPath ) //used to be > (why?)
  506. continue;
  507. switch( item->m_Type )
  508. {
  509. case NETLIST_ITEM::SEGMENT:
  510. case NETLIST_ITEM::PIN:
  511. case NETLIST_ITEM::LABEL:
  512. case NETLIST_ITEM::HIERLABEL:
  513. case NETLIST_ITEM::GLOBLABEL:
  514. case NETLIST_ITEM::SHEETLABEL:
  515. case NETLIST_ITEM::PINLABEL:
  516. case NETLIST_ITEM::JUNCTION:
  517. case NETLIST_ITEM::NOCONNECT:
  518. if( aRef->m_Start == item->m_Start
  519. || aRef->m_Start == item->m_End
  520. || aRef->m_End == item->m_Start
  521. || aRef->m_End == item->m_End )
  522. {
  523. if( item->GetNet() == 0 )
  524. item->SetNet( netCode );
  525. else
  526. propagateNetCode( item->GetNet(), netCode, IS_WIRE );
  527. }
  528. break;
  529. case NETLIST_ITEM::BUS:
  530. case NETLIST_ITEM::BUSLABELMEMBER:
  531. case NETLIST_ITEM::SHEETBUSLABELMEMBER:
  532. case NETLIST_ITEM::HIERBUSLABELMEMBER:
  533. case NETLIST_ITEM::GLOBBUSLABELMEMBER:
  534. case NETLIST_ITEM::ITEM_UNSPECIFIED:
  535. break;
  536. }
  537. }
  538. }
  539. else // Object type BUS, BUSLABELS, and junctions.
  540. {
  541. netCode = aRef->m_BusNetCode;
  542. for( unsigned i = start; i < size(); i++ )
  543. {
  544. NETLIST_OBJECT* item = GetItem( i );
  545. if( item->m_SheetPath != aRef->m_SheetPath )
  546. continue;
  547. switch( item->m_Type )
  548. {
  549. case NETLIST_ITEM::ITEM_UNSPECIFIED:
  550. case NETLIST_ITEM::SEGMENT:
  551. case NETLIST_ITEM::PIN:
  552. case NETLIST_ITEM::LABEL:
  553. case NETLIST_ITEM::HIERLABEL:
  554. case NETLIST_ITEM::GLOBLABEL:
  555. case NETLIST_ITEM::SHEETLABEL:
  556. case NETLIST_ITEM::PINLABEL:
  557. case NETLIST_ITEM::NOCONNECT:
  558. break;
  559. case NETLIST_ITEM::BUS:
  560. case NETLIST_ITEM::BUSLABELMEMBER:
  561. case NETLIST_ITEM::SHEETBUSLABELMEMBER:
  562. case NETLIST_ITEM::HIERBUSLABELMEMBER:
  563. case NETLIST_ITEM::GLOBBUSLABELMEMBER:
  564. case NETLIST_ITEM::JUNCTION:
  565. if( aRef->m_Start == item->m_Start
  566. || aRef->m_Start == item->m_End
  567. || aRef->m_End == item->m_Start
  568. || aRef->m_End == item->m_End )
  569. {
  570. if( item->m_BusNetCode == 0 )
  571. item->m_BusNetCode = netCode;
  572. else
  573. propagateNetCode( item->m_BusNetCode, netCode, IS_BUS );
  574. }
  575. break;
  576. }
  577. }
  578. }
  579. }
  580. void NETLIST_OBJECT_LIST::segmentToPointConnect( NETLIST_OBJECT* aJonction,
  581. bool aIsBus, int aIdxStart )
  582. {
  583. for( unsigned i = aIdxStart; i < size(); i++ )
  584. {
  585. NETLIST_OBJECT* segment = GetItem( i );
  586. // if different sheets, obviously no physical connection between elements.
  587. if( segment->m_SheetPath != aJonction->m_SheetPath )
  588. continue;
  589. if( aIsBus == IS_WIRE )
  590. {
  591. if( segment->m_Type != NETLIST_ITEM::SEGMENT )
  592. continue;
  593. }
  594. else
  595. {
  596. if( segment->m_Type != NETLIST_ITEM::BUS )
  597. continue;
  598. }
  599. if( IsPointOnSegment( segment->m_Start, segment->m_End, aJonction->m_Start ) )
  600. {
  601. // Propagation Netcode has all the objects of the same Netcode.
  602. if( aIsBus == IS_WIRE )
  603. {
  604. if( segment->GetNet() )
  605. propagateNetCode( segment->GetNet(), aJonction->GetNet(), aIsBus );
  606. else
  607. segment->SetNet( aJonction->GetNet() );
  608. }
  609. else
  610. {
  611. if( segment->m_BusNetCode )
  612. propagateNetCode( segment->m_BusNetCode, aJonction->m_BusNetCode, aIsBus );
  613. else
  614. segment->m_BusNetCode = aJonction->m_BusNetCode;
  615. }
  616. }
  617. }
  618. }
  619. void NETLIST_OBJECT_LIST::labelConnect( NETLIST_OBJECT* aLabelRef )
  620. {
  621. if( aLabelRef->GetNet() == 0 )
  622. return;
  623. for( unsigned i = 0; i < size(); i++ )
  624. {
  625. NETLIST_OBJECT* item = GetItem( i );
  626. if( item->GetNet() == aLabelRef->GetNet() )
  627. continue;
  628. if( item->m_SheetPath != aLabelRef->m_SheetPath )
  629. {
  630. if( item->m_Type != NETLIST_ITEM::PINLABEL && item->m_Type != NETLIST_ITEM::GLOBLABEL
  631. && item->m_Type != NETLIST_ITEM::GLOBBUSLABELMEMBER )
  632. continue;
  633. if( ( item->m_Type == NETLIST_ITEM::GLOBLABEL
  634. || item->m_Type == NETLIST_ITEM::GLOBBUSLABELMEMBER )
  635. && item->m_Type != aLabelRef->m_Type )
  636. //global labels only connect other global labels.
  637. continue;
  638. }
  639. // NETLIST_ITEM::HIERLABEL are used to connect sheets.
  640. // NETLIST_ITEM::LABEL are local to a sheet
  641. // NETLIST_ITEM::GLOBLABEL are global.
  642. // NETLIST_ITEM::PINLABEL is a kind of global label (generated by a power pin invisible)
  643. if( item->IsLabelType() )
  644. {
  645. if( item->m_Label != aLabelRef->m_Label )
  646. continue;
  647. if( item->GetNet() )
  648. propagateNetCode( item->GetNet(), aLabelRef->GetNet(), IS_WIRE );
  649. else
  650. item->SetNet( aLabelRef->GetNet() );
  651. }
  652. }
  653. }
  654. void NETLIST_OBJECT_LIST::setUnconnectedFlag()
  655. {
  656. NETLIST_OBJECT* NetItemRef;
  657. unsigned NetStart, NetEnd;
  658. NET_CONNECTION StateFlag;
  659. NetStart = NetEnd = 0;
  660. StateFlag = NET_CONNECTION::UNCONNECTED;
  661. for( unsigned ii = 0; ii < size(); ii++ )
  662. {
  663. NetItemRef = GetItem( ii );
  664. if( NetItemRef->m_Type == NETLIST_ITEM::NOCONNECT
  665. && StateFlag != NET_CONNECTION::PAD_CONNECT )
  666. StateFlag = NET_CONNECTION::NOCONNECT_SYMBOL_PRESENT;
  667. // Analysis of current net.
  668. unsigned idxtoTest = ii + 1;
  669. if( ( idxtoTest >= size() )
  670. || ( NetItemRef->GetNet() != GetItem( idxtoTest )->GetNet() ) )
  671. {
  672. // Net analysis to update m_ConnectionType
  673. NetEnd = idxtoTest;
  674. /* set m_ConnectionType member to StateFlag for all items of
  675. * this net: */
  676. for( unsigned kk = NetStart; kk < NetEnd; kk++ )
  677. GetItem( kk )->m_ConnectionType = StateFlag;
  678. if( idxtoTest >= size() )
  679. return;
  680. // Start Analysis next Net
  681. StateFlag = NET_CONNECTION::UNCONNECTED;
  682. NetStart = idxtoTest;
  683. continue;
  684. }
  685. /* test the current item: if this is a pin and if the reference item
  686. * is also a pin, then 2 pins are connected, so set StateFlag to
  687. * PAD_CONNECT (can be already done) Of course, if the current
  688. * item is a no connect symbol, set StateFlag to
  689. * NOCONNECT_SYMBOL_PRESENT to inhibit error diags. However if
  690. * StateFlag is already set to PAD_CONNECT this state is kept (the
  691. * no connect symbol was surely an error and an ERC will report this)
  692. */
  693. for( ; ; idxtoTest++ )
  694. {
  695. if( ( idxtoTest >= size() )
  696. || ( NetItemRef->GetNet() != GetItem( idxtoTest )->GetNet() ) )
  697. break;
  698. switch( GetItem( idxtoTest )->m_Type )
  699. {
  700. case NETLIST_ITEM::ITEM_UNSPECIFIED:
  701. wxMessageBox( wxT( "BuildNetListBase() error" ) );
  702. break;
  703. case NETLIST_ITEM::SEGMENT:
  704. case NETLIST_ITEM::LABEL:
  705. case NETLIST_ITEM::HIERLABEL:
  706. case NETLIST_ITEM::GLOBLABEL:
  707. case NETLIST_ITEM::SHEETLABEL:
  708. case NETLIST_ITEM::PINLABEL:
  709. case NETLIST_ITEM::BUS:
  710. case NETLIST_ITEM::BUSLABELMEMBER:
  711. case NETLIST_ITEM::SHEETBUSLABELMEMBER:
  712. case NETLIST_ITEM::HIERBUSLABELMEMBER:
  713. case NETLIST_ITEM::GLOBBUSLABELMEMBER:
  714. case NETLIST_ITEM::JUNCTION:
  715. break;
  716. case NETLIST_ITEM::PIN:
  717. if( NetItemRef->m_Type == NETLIST_ITEM::PIN )
  718. StateFlag = NET_CONNECTION::PAD_CONNECT;
  719. break;
  720. case NETLIST_ITEM::NOCONNECT:
  721. if( StateFlag != NET_CONNECTION::PAD_CONNECT )
  722. StateFlag = NET_CONNECTION::NOCONNECT_SYMBOL_PRESENT;
  723. break;
  724. }
  725. }
  726. }
  727. }