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.

966 lines
30 KiB

18 years ago
18 years ago
  1. /*
  2. * This program source code file is part of KiCad, a free EDA CAD application.
  3. *
  4. * Copyright (C) 2009 Jean-Pierre Charras, jaen-pierre.charras@gipsa-lab.inpg.com
  5. * Copyright (C) 2011 Wayne Stambaugh <stambaughw@verizon.net>
  6. * Copyright (C) 1992-2011 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. /**
  26. * @file eeschema/netlist.cpp
  27. */
  28. #include <fctsys.h>
  29. #include <wxEeschemaStruct.h>
  30. #include <general.h>
  31. #include <netlist.h>
  32. #include <protos.h>
  33. #include <class_library.h>
  34. #include <lib_pin.h>
  35. #include <sch_junction.h>
  36. #include <sch_component.h>
  37. #include <sch_line.h>
  38. #include <sch_no_connect.h>
  39. #include <sch_text.h>
  40. #include <sch_sheet.h>
  41. #include <algorithm>
  42. #include <boost/foreach.hpp>
  43. const SCH_SHEET_PATH BOM_LABEL::emptySheetPath;
  44. // Buffer to build the list of items used in netlist and erc calculations
  45. NETLIST_OBJECT_LIST g_NetObjectslist;
  46. //#define NETLIST_DEBUG
  47. static void PropageNetCode( int OldNetCode, int NewNetCode, int IsBus );
  48. static void SheetLabelConnect( NETLIST_OBJECT* SheetLabel );
  49. static void PointToPointConnect( NETLIST_OBJECT* Ref, int IsBus, int start );
  50. static void SegmentToPointConnect( NETLIST_OBJECT* Jonction, int IsBus, int start );
  51. static void LabelConnect( NETLIST_OBJECT* Label );
  52. static void ConnectBusLabels( NETLIST_OBJECT_LIST& aNetItemBuffer );
  53. static void SetUnconnectedFlag( NETLIST_OBJECT_LIST& aNetItemBuffer );
  54. static void FindBestNetNameForEachNet( NETLIST_OBJECT_LIST& aNetItemBuffer );
  55. static NETLIST_OBJECT* FindBestNetName( NETLIST_OBJECT_LIST& aLabelItemBuffer );
  56. // Sort functions used here:
  57. static bool SortItemsbyNetcode( const NETLIST_OBJECT* Objet1, const NETLIST_OBJECT* Objet2 );
  58. static bool SortItemsBySheet( const NETLIST_OBJECT* Objet1, const NETLIST_OBJECT* Objet2 );
  59. // Local variables
  60. static int LastNetCode, LastBusNetCode;
  61. #if defined(DEBUG)
  62. void dumpNetTable()
  63. {
  64. for( unsigned idx = 0; idx < g_NetObjectslist.size(); ++idx )
  65. {
  66. g_NetObjectslist[idx]->Show( std::cout, idx );
  67. }
  68. }
  69. #endif
  70. wxString BOM_LABEL::GetText() const
  71. {
  72. const SCH_TEXT* tmp = (SCH_TEXT*) m_label;
  73. return tmp->GetText();
  74. }
  75. /*
  76. * Routine to free memory used to calculate the netlist TabNetItems = pointer
  77. * to the main table (list items)
  78. */
  79. void FreeNetObjectsList( NETLIST_OBJECT_LIST& aNetObjectsBuffer )
  80. {
  81. for( unsigned i = 0; i < aNetObjectsBuffer.size(); i++ )
  82. delete aNetObjectsBuffer[i];
  83. aNetObjectsBuffer.clear();
  84. }
  85. /*
  86. * Build net list connection table.
  87. *
  88. * Updates:
  89. * g_NetObjectslist
  90. */
  91. void SCH_EDIT_FRAME::BuildNetListBase()
  92. {
  93. int NetCode;
  94. SCH_SHEET_PATH* sheet;
  95. wxString msg, activity;
  96. wxBusyCursor Busy;
  97. activity = _( "Building net list:" );
  98. SetStatusText( activity );
  99. FreeNetObjectsList( g_NetObjectslist );
  100. /* Build the sheet (not screen) list (flattened)*/
  101. SCH_SHEET_LIST sheets;
  102. /* Fill g_NetObjectslist with items used in connectivity calculation */
  103. for( sheet = sheets.GetFirst(); sheet != NULL; sheet = sheets.GetNext() )
  104. {
  105. for( SCH_ITEM* item = sheet->LastScreen()->GetDrawItems(); item; item = item->Next() )
  106. {
  107. item->GetNetListItem( g_NetObjectslist, sheet );
  108. }
  109. }
  110. if( g_NetObjectslist.size() == 0 )
  111. return; // no objects
  112. activity << wxT( " " ) << _( "net count =" ) << wxT( " " ) << g_NetObjectslist.size();
  113. SetStatusText( activity );
  114. /* Sort objects by Sheet */
  115. sort( g_NetObjectslist.begin(), g_NetObjectslist.end(), SortItemsBySheet );
  116. activity << wxT( ", " ) << _( "connections" ) << wxT( "..." );
  117. SetStatusText( activity );
  118. sheet = &(g_NetObjectslist[0]->m_SheetList);
  119. LastNetCode = LastBusNetCode = 1;
  120. for( unsigned ii = 0, istart = 0; ii < g_NetObjectslist.size(); ii++ )
  121. {
  122. NETLIST_OBJECT* net_item = g_NetObjectslist[ii];
  123. if( net_item->m_SheetList != *sheet ) // Sheet change
  124. {
  125. sheet = &(net_item->m_SheetList);
  126. istart = ii;
  127. }
  128. switch( net_item->m_Type )
  129. {
  130. case NET_ITEM_UNSPECIFIED:
  131. wxMessageBox( wxT( "BuildNetListBase() error" ) );
  132. break;
  133. case NET_PIN:
  134. case NET_PINLABEL:
  135. case NET_SHEETLABEL:
  136. case NET_NOCONNECT:
  137. if( net_item->GetNet() != 0 )
  138. break;
  139. case NET_SEGMENT:
  140. /* Control connections point to point type without bus. */
  141. if( net_item->GetNet() == 0 )
  142. {
  143. net_item->SetNet( LastNetCode );
  144. LastNetCode++;
  145. }
  146. PointToPointConnect( net_item, 0, istart );
  147. break;
  148. case NET_JUNCTION:
  149. /* Control of the junction outside BUS. */
  150. if( net_item->GetNet() == 0 )
  151. {
  152. net_item->SetNet( LastNetCode );
  153. LastNetCode++;
  154. }
  155. SegmentToPointConnect( net_item, 0, istart );
  156. /* Control of the junction, on BUS. */
  157. if( net_item->m_BusNetCode == 0 )
  158. {
  159. net_item->m_BusNetCode = LastBusNetCode;
  160. LastBusNetCode++;
  161. }
  162. SegmentToPointConnect( net_item, ISBUS, istart );
  163. break;
  164. case NET_LABEL:
  165. case NET_HIERLABEL:
  166. case NET_GLOBLABEL:
  167. /* Control connections type junction without bus. */
  168. if( net_item->GetNet() == 0 )
  169. {
  170. net_item->SetNet( LastNetCode );
  171. LastNetCode++;
  172. }
  173. SegmentToPointConnect( net_item, 0, istart );
  174. break;
  175. case NET_SHEETBUSLABELMEMBER:
  176. if( net_item->m_BusNetCode != 0 )
  177. break;
  178. case NET_BUS:
  179. /* Control type connections point to point mode bus */
  180. if( net_item->m_BusNetCode == 0 )
  181. {
  182. net_item->m_BusNetCode = LastBusNetCode;
  183. LastBusNetCode++;
  184. }
  185. PointToPointConnect( net_item, ISBUS, istart );
  186. break;
  187. case NET_BUSLABELMEMBER:
  188. case NET_HIERBUSLABELMEMBER:
  189. case NET_GLOBBUSLABELMEMBER:
  190. /* Control connections similar has on BUS */
  191. if( net_item->GetNet() == 0 )
  192. {
  193. net_item->m_BusNetCode = LastBusNetCode;
  194. LastBusNetCode++;
  195. }
  196. SegmentToPointConnect( net_item, ISBUS, istart );
  197. break;
  198. }
  199. }
  200. #if defined(NETLIST_DEBUG) && defined(DEBUG)
  201. std::cout << "\n\nafter sheet local\n\n";
  202. dumpNetTable();
  203. #endif
  204. activity << _( "done" );
  205. SetStatusText( activity );
  206. /* Updating the Bus Labels Netcode connected by Bus */
  207. ConnectBusLabels( g_NetObjectslist );
  208. activity << wxT( ", " ) << _( "bus labels" ) << wxT( "..." );
  209. SetStatusText( activity );
  210. /* Group objects by label. */
  211. for( unsigned ii = 0; ii < g_NetObjectslist.size(); ii++ )
  212. {
  213. switch( g_NetObjectslist[ii]->m_Type )
  214. {
  215. case NET_PIN:
  216. case NET_SHEETLABEL:
  217. case NET_SEGMENT:
  218. case NET_JUNCTION:
  219. case NET_BUS:
  220. case NET_NOCONNECT:
  221. break;
  222. case NET_LABEL:
  223. case NET_GLOBLABEL:
  224. case NET_PINLABEL:
  225. case NET_BUSLABELMEMBER:
  226. case NET_GLOBBUSLABELMEMBER:
  227. LabelConnect( g_NetObjectslist[ii] );
  228. break;
  229. case NET_SHEETBUSLABELMEMBER:
  230. case NET_HIERLABEL:
  231. case NET_HIERBUSLABELMEMBER:
  232. break;
  233. case NET_ITEM_UNSPECIFIED:
  234. break;
  235. }
  236. }
  237. #if defined(NETLIST_DEBUG) && defined(DEBUG)
  238. std::cout << "\n\nafter sheet global\n\n";
  239. dumpNetTable();
  240. #endif
  241. activity << _( "done" );
  242. SetStatusText( activity );
  243. /* Connection hierarchy. */
  244. activity << wxT( ", " ) << _( "hierarchy..." );
  245. SetStatusText( activity );
  246. for( unsigned ii = 0; ii < g_NetObjectslist.size(); ii++ )
  247. {
  248. if( g_NetObjectslist[ii]->m_Type == NET_SHEETLABEL
  249. || g_NetObjectslist[ii]->m_Type == NET_SHEETBUSLABELMEMBER )
  250. SheetLabelConnect( g_NetObjectslist[ii] );
  251. }
  252. /* Sort objects by NetCode */
  253. sort( g_NetObjectslist.begin(), g_NetObjectslist.end(), SortItemsbyNetcode );
  254. #if defined(NETLIST_DEBUG) && defined(DEBUG)
  255. std::cout << "\n\nafter qsort()\n";
  256. dumpNetTable();
  257. #endif
  258. activity << _( "done" );
  259. SetStatusText( activity );
  260. /* Compress numbers of Netcode having consecutive values. */
  261. LastNetCode = NetCode = 0;
  262. for( unsigned ii = 0; ii < g_NetObjectslist.size(); ii++ )
  263. {
  264. if( g_NetObjectslist[ii]->GetNet() != LastNetCode )
  265. {
  266. NetCode++;
  267. LastNetCode = g_NetObjectslist[ii]->GetNet();
  268. }
  269. g_NetObjectslist[ii]->SetNet( NetCode );
  270. }
  271. /* Assignment of m_FlagOfConnection based connection or not. */
  272. SetUnconnectedFlag( g_NetObjectslist );
  273. /* find the best label object to give the best net name to each net */
  274. FindBestNetNameForEachNet( g_NetObjectslist );
  275. }
  276. /**
  277. * Function FindBestNetNameForEachNet
  278. * fill the .m_NetNameCandidate member of each item of aNetItemBuffer
  279. * with a reference to the "best" NETLIST_OBJECT usable to give a name to the net
  280. * If no suitable object found, .m_NetNameCandidate is filled with 0.
  281. * The "best" NETLIST_OBJECT is a NETLIST_OBJECT that have the type label
  282. * and by priority order:
  283. * the label is global or local
  284. * the label is in the first sheet in a hierarchy (the root sheet has the most priority)
  285. * alphabetic order.
  286. */
  287. void FindBestNetNameForEachNet( NETLIST_OBJECT_LIST& aNetItemBuffer )
  288. {
  289. if( aNetItemBuffer.size() == 0 )
  290. return; // Should not occur: if this function is called, obviously some items exist in list
  291. NETLIST_OBJECT_LIST candidates;
  292. int netcode = 0; // current netcode for tested items
  293. unsigned idxstart = 0; // index of the first item of this net
  294. for( unsigned ii = 0; ii <= aNetItemBuffer.size(); ii++ )
  295. {
  296. NETLIST_OBJECT* item;
  297. if( ii == aNetItemBuffer.size() ) // last item already found
  298. netcode = -2;
  299. else
  300. item = aNetItemBuffer[ii];
  301. if( netcode != item->GetNet() ) // End of net found
  302. {
  303. if( candidates.size() ) // One or more labels exists, find the best
  304. {
  305. NETLIST_OBJECT* bestlabel = FindBestNetName( candidates );
  306. for (unsigned jj = idxstart; jj < ii; jj++ )
  307. aNetItemBuffer[jj]->m_NetNameCandidate = bestlabel;
  308. }
  309. if( netcode == -2 )
  310. break;
  311. netcode = item->GetNet();
  312. candidates.clear();
  313. idxstart = ii;
  314. }
  315. switch( item->m_Type )
  316. {
  317. case NET_HIERLABEL:
  318. case NET_LABEL:
  319. case NET_PINLABEL:
  320. case NET_GLOBLABEL:
  321. candidates.push_back( item );
  322. break;
  323. default:
  324. break;
  325. }
  326. }
  327. }
  328. /**
  329. * Function FindBestNetName
  330. * @return a reference to the "best" label that can be used to give a name
  331. * to a net.
  332. * @param aLabelItemBuffer = list of NETLIST_OBJECT type labels candidates.
  333. * labels are local labels, hierarchical labels or pin labels
  334. * labels in included sheets have a lower priority than labels in the current sheet.
  335. * so labels inside the root sheet have the higher priority.
  336. * pin labels are global labels and have the higher priority
  337. * local labels have the lower priority
  338. * labels having the same priority are sorted by alphabetic order.
  339. *
  340. */
  341. static NETLIST_OBJECT* FindBestNetName( NETLIST_OBJECT_LIST& aLabelItemBuffer )
  342. {
  343. if( aLabelItemBuffer.size() == 0 )
  344. return NULL;
  345. // Define a priority (from low to high) to sort labels:
  346. // NET_PINLABEL and NET_GLOBLABEL are global labels
  347. // and priority >= NET_PRIO_MAX-1 is for global connections
  348. // ( i.e. for labels that are not prefixed by a sheetpath)
  349. #define NET_PRIO_MAX 4
  350. static int priority_order[NET_PRIO_MAX+1] = {
  351. NET_ITEM_UNSPECIFIED,
  352. NET_LABEL,
  353. NET_HIERLABEL,
  354. NET_PINLABEL,
  355. NET_GLOBLABEL };
  356. NETLIST_OBJECT*item = aLabelItemBuffer[0];
  357. // Calculate item priority (initial priority)
  358. int item_priority = 0;
  359. for( unsigned ii = 0; ii <= NET_PRIO_MAX; ii++ )
  360. {
  361. if ( item->m_Type == priority_order[ii] )
  362. {
  363. item_priority = ii;
  364. break;
  365. }
  366. }
  367. for( unsigned ii = 1; ii < aLabelItemBuffer.size(); ii++ )
  368. {
  369. NETLIST_OBJECT* candidate = aLabelItemBuffer[ii];
  370. // Calculate candidate priority
  371. int candidate_priority = 0;
  372. for( unsigned prio = 0; prio <= NET_PRIO_MAX; prio++ )
  373. {
  374. if ( candidate->m_Type == priority_order[prio] )
  375. {
  376. candidate_priority = prio;
  377. break;
  378. }
  379. }
  380. if( candidate_priority > item_priority )
  381. {
  382. item = candidate;
  383. item_priority = candidate_priority;
  384. }
  385. else if( candidate_priority == item_priority )
  386. {
  387. // for global labels, we select the best candidate by alphabetic order
  388. // because they have no sheetpath as prefix name
  389. // for other labels, we select them before by sheet deep order
  390. // because the actual name is /sheetpath/label
  391. // and for a given path length, by alphabetic order
  392. if( item_priority >= NET_PRIO_MAX-1 ) // global label or pin label
  393. { // selection by alphabetic order:
  394. if( candidate->m_Label.Cmp( item->m_Label ) < 0 )
  395. item = candidate;
  396. }
  397. else // not global: names are prefixed by their sheetpath
  398. {
  399. // use name defined in higher hierarchical sheet
  400. // (i.e. shorter path because paths are /<timestamp1>/<timestamp2>/...
  401. // and timestamp = 8 letters.
  402. if( candidate->m_SheetList.Path().Length() < item->m_SheetList.Path().Length() )
  403. {
  404. item = candidate;
  405. }
  406. else if( candidate->m_SheetList.Path().Length() == item->m_SheetList.Path().Length() )
  407. {
  408. // For labels on sheets having an equivalent deep in hierarchy, use
  409. // alphabetic label name order:
  410. if( candidate->m_Label.Cmp( item->m_Label ) < 0 )
  411. item = candidate;
  412. else if( candidate->m_Label.Cmp( item->m_Label ) == 0 )
  413. {
  414. if( candidate->m_SheetList.PathHumanReadable().Cmp( item->m_SheetList.PathHumanReadable() ) < 0 )
  415. item = candidate;
  416. }
  417. }
  418. }
  419. }
  420. }
  421. return item;
  422. }
  423. /*
  424. * Connect sheets by sheetLabels
  425. */
  426. static void SheetLabelConnect( NETLIST_OBJECT* SheetLabel )
  427. {
  428. if( SheetLabel->GetNet() == 0 )
  429. return;
  430. /* Calculate the number of nodes in the corresponding sheetlabel */
  431. /* Comparison with SheetLabel GLABELS sub sheet to group Netcode */
  432. for( unsigned ii = 0; ii < g_NetObjectslist.size(); ii++ )
  433. {
  434. NETLIST_OBJECT* ObjetNet = g_NetObjectslist[ii];
  435. if( ObjetNet->m_SheetList != SheetLabel->m_SheetListInclude )
  436. continue; //use SheetInclude, not the sheet!!
  437. if( (ObjetNet->m_Type != NET_HIERLABEL ) && (ObjetNet->m_Type != NET_HIERBUSLABELMEMBER ) )
  438. continue;
  439. if( ObjetNet->GetNet() == SheetLabel->GetNet() )
  440. continue; //already connected.
  441. if( ObjetNet->m_Label.CmpNoCase( SheetLabel->m_Label ) != 0 )
  442. continue; //different names.
  443. /* Propagate Netcode having all the objects of the same Netcode. */
  444. if( ObjetNet->GetNet() )
  445. PropageNetCode( ObjetNet->GetNet(), SheetLabel->GetNet(), 0 );
  446. else
  447. ObjetNet->SetNet( SheetLabel->GetNet() );
  448. }
  449. }
  450. /*
  451. * Routine that analyzes the type labels xxBUSLABELMEMBER
  452. * Propagate Netcode between the corresponding labels (ie when
  453. * Their member number is the same) when they are connected
  454. * Generally by their BusNetCode
  455. * Uses and updates the variable LastNetCode
  456. */
  457. static void ConnectBusLabels( NETLIST_OBJECT_LIST& aNetItemBuffer )
  458. {
  459. for( unsigned ii = 0; ii < aNetItemBuffer.size(); ii++ )
  460. {
  461. NETLIST_OBJECT* Label = aNetItemBuffer[ii];
  462. if( (Label->m_Type == NET_SHEETBUSLABELMEMBER)
  463. || (Label->m_Type == NET_BUSLABELMEMBER)
  464. || (Label->m_Type == NET_HIERBUSLABELMEMBER) )
  465. {
  466. if( Label->GetNet() == 0 )
  467. {
  468. Label->SetNet( LastNetCode );
  469. LastNetCode++;
  470. }
  471. for( unsigned jj = ii + 1; jj < aNetItemBuffer.size(); jj++ )
  472. {
  473. NETLIST_OBJECT* LabelInTst = aNetItemBuffer[jj];
  474. if( (LabelInTst->m_Type == NET_SHEETBUSLABELMEMBER)
  475. || (LabelInTst->m_Type == NET_BUSLABELMEMBER)
  476. || (LabelInTst->m_Type == NET_HIERBUSLABELMEMBER) )
  477. {
  478. if( LabelInTst->m_BusNetCode != Label->m_BusNetCode )
  479. continue;
  480. if( LabelInTst->m_Member != Label->m_Member )
  481. continue;
  482. if( LabelInTst->GetNet() == 0 )
  483. LabelInTst->SetNet( Label->GetNet() );
  484. else
  485. PropageNetCode( LabelInTst->GetNet(), Label->GetNet(), 0 );
  486. }
  487. }
  488. }
  489. }
  490. }
  491. /*
  492. * PropageNetCode propagates Netcode NewNetCode on all elements
  493. * belonging to the former Netcode OldNetCode
  494. * If IsBus == 0; Netcode is the member who is spreading
  495. * If IsBus != 0; is the member who is spreading BusNetCode
  496. */
  497. static void PropageNetCode( int OldNetCode, int NewNetCode, int IsBus )
  498. {
  499. if( OldNetCode == NewNetCode )
  500. return;
  501. if( IsBus == 0 ) /* Propagate NetCode */
  502. {
  503. for( unsigned jj = 0; jj < g_NetObjectslist.size(); jj++ )
  504. {
  505. NETLIST_OBJECT* Objet = g_NetObjectslist[jj];
  506. if( Objet->GetNet() == OldNetCode )
  507. {
  508. Objet->SetNet( NewNetCode );
  509. }
  510. }
  511. }
  512. else /* Propagate BusNetCode */
  513. {
  514. for( unsigned jj = 0; jj < g_NetObjectslist.size(); jj++ )
  515. {
  516. NETLIST_OBJECT* Objet = g_NetObjectslist[jj];
  517. if( Objet->m_BusNetCode == OldNetCode )
  518. {
  519. Objet->m_BusNetCode = NewNetCode;
  520. }
  521. }
  522. }
  523. }
  524. /*
  525. * Check if Ref element is connected to other elements of the list of objects
  526. * in the schematic, by mode point
  527. * A point (end superimposed)
  528. *
  529. * If IsBus:
  530. * The connection involves elements such as bus
  531. * (Or BUS or BUSLABEL JUNCTION)
  532. * Otherwise
  533. * The connection involves elements such as non-bus
  534. * (Other than BUS or BUSLABEL)
  535. *
  536. * The Ref object must have a valid Netcode.
  537. *
  538. * The list of objects is SUPPOSED class by SheetPath Croissants,
  539. * And research is done from the start element, 1st element
  540. * Leaf schema
  541. * (There can be no physical connection between elements of different sheets)
  542. */
  543. static void PointToPointConnect( NETLIST_OBJECT* Ref, int IsBus, int start )
  544. {
  545. int netCode;
  546. if( IsBus == 0 ) /* Objects other than BUS and BUSLABELS. */
  547. {
  548. netCode = Ref->GetNet();
  549. for( unsigned i = start; i < g_NetObjectslist.size(); i++ )
  550. {
  551. NETLIST_OBJECT* item = g_NetObjectslist[i];
  552. if( item->m_SheetList != Ref->m_SheetList ) //used to be > (why?)
  553. continue;
  554. switch( item->m_Type )
  555. {
  556. case NET_SEGMENT:
  557. case NET_PIN:
  558. case NET_LABEL:
  559. case NET_HIERLABEL:
  560. case NET_GLOBLABEL:
  561. case NET_SHEETLABEL:
  562. case NET_PINLABEL:
  563. case NET_JUNCTION:
  564. case NET_NOCONNECT:
  565. if( Ref->m_Start == item->m_Start
  566. || Ref->m_Start == item->m_End
  567. || Ref->m_End == item->m_Start
  568. || Ref->m_End == item->m_End )
  569. {
  570. if( item->GetNet() == 0 )
  571. item->SetNet( netCode );
  572. else
  573. PropageNetCode( item->GetNet(), netCode, 0 );
  574. }
  575. break;
  576. case NET_BUS:
  577. case NET_BUSLABELMEMBER:
  578. case NET_SHEETBUSLABELMEMBER:
  579. case NET_HIERBUSLABELMEMBER:
  580. case NET_GLOBBUSLABELMEMBER:
  581. case NET_ITEM_UNSPECIFIED:
  582. break;
  583. }
  584. }
  585. }
  586. else /* Object type BUS, BUSLABELS, and junctions. */
  587. {
  588. netCode = Ref->m_BusNetCode;
  589. for( unsigned i = start; i<g_NetObjectslist.size(); i++ )
  590. {
  591. NETLIST_OBJECT* item = g_NetObjectslist[i];
  592. if( item->m_SheetList != Ref->m_SheetList )
  593. continue;
  594. switch( item->m_Type )
  595. {
  596. case NET_ITEM_UNSPECIFIED:
  597. case NET_SEGMENT:
  598. case NET_PIN:
  599. case NET_LABEL:
  600. case NET_HIERLABEL:
  601. case NET_GLOBLABEL:
  602. case NET_SHEETLABEL:
  603. case NET_PINLABEL:
  604. case NET_NOCONNECT:
  605. break;
  606. case NET_BUS:
  607. case NET_BUSLABELMEMBER:
  608. case NET_SHEETBUSLABELMEMBER:
  609. case NET_HIERBUSLABELMEMBER:
  610. case NET_GLOBBUSLABELMEMBER:
  611. case NET_JUNCTION:
  612. if( Ref->m_Start == item->m_Start
  613. || Ref->m_Start == item->m_End
  614. || Ref->m_End == item->m_Start
  615. || Ref->m_End == item->m_End )
  616. {
  617. if( item->m_BusNetCode == 0 )
  618. item->m_BusNetCode = netCode;
  619. else
  620. PropageNetCode( item->m_BusNetCode, netCode, 1 );
  621. }
  622. break;
  623. }
  624. }
  625. }
  626. }
  627. /*
  628. * Search if a junction is connected to segments and propagate the junction Netcode
  629. * to objects connected by the junction.
  630. * The junction must have a valid Netcode
  631. * The list of objects is expected sorted by sheets.
  632. * Search is done from index aIdxStart to the last element of g_NetObjectslist
  633. */
  634. static void SegmentToPointConnect( NETLIST_OBJECT* aJonction, int aIsBus, int aIdxStart )
  635. {
  636. for( unsigned i = aIdxStart; i < g_NetObjectslist.size(); i++ )
  637. {
  638. NETLIST_OBJECT* Segment = g_NetObjectslist[i];
  639. // if different sheets, no physical connection between elements is possible.
  640. if( Segment->m_SheetList != aJonction->m_SheetList )
  641. continue;
  642. if( aIsBus == 0 )
  643. {
  644. if( Segment->m_Type != NET_SEGMENT )
  645. continue;
  646. }
  647. else
  648. {
  649. if( Segment->m_Type != NET_BUS )
  650. continue;
  651. }
  652. if( SegmentIntersect( Segment->m_Start, Segment->m_End, aJonction->m_Start ) )
  653. {
  654. /* Propagation Netcode has all the objects of the same Netcode. */
  655. if( aIsBus == 0 )
  656. {
  657. if( Segment->GetNet() )
  658. PropageNetCode( Segment->GetNet(), aJonction->GetNet(), aIsBus );
  659. else
  660. Segment->SetNet( aJonction->GetNet() );
  661. }
  662. else
  663. {
  664. if( Segment->m_BusNetCode )
  665. PropageNetCode( Segment->m_BusNetCode, aJonction->m_BusNetCode, aIsBus );
  666. else
  667. Segment->m_BusNetCode = aJonction->m_BusNetCode;
  668. }
  669. }
  670. }
  671. }
  672. /*****************************************************************
  673. * Function which connects the groups of object which have the same label
  674. *******************************************************************/
  675. void LabelConnect( NETLIST_OBJECT* LabelRef )
  676. {
  677. if( LabelRef->GetNet() == 0 )
  678. return;
  679. for( unsigned i = 0; i < g_NetObjectslist.size(); i++ )
  680. {
  681. if( g_NetObjectslist[i]->GetNet() == LabelRef->GetNet() )
  682. continue;
  683. if( g_NetObjectslist[i]->m_SheetList != LabelRef->m_SheetList )
  684. {
  685. if( (g_NetObjectslist[i]->m_Type != NET_PINLABEL
  686. && g_NetObjectslist[i]->m_Type != NET_GLOBLABEL
  687. && g_NetObjectslist[i]->m_Type != NET_GLOBBUSLABELMEMBER) )
  688. continue;
  689. if( (g_NetObjectslist[i]->m_Type == NET_GLOBLABEL
  690. || g_NetObjectslist[i]->m_Type == NET_GLOBBUSLABELMEMBER)
  691. && g_NetObjectslist[i]->m_Type != LabelRef->m_Type )
  692. //global labels only connect other global labels.
  693. continue;
  694. }
  695. // regular labels are sheet-local;
  696. // NET_HIERLABEL are used to connect sheets.
  697. // NET_LABEL is sheet-local (***)
  698. // NET_GLOBLABEL is global.
  699. // NET_PINLABEL is a kind of global label (generated by a power pin invisible)
  700. NETLIST_ITEM_T ntype = g_NetObjectslist[i]->m_Type;
  701. if( ntype == NET_LABEL
  702. || ntype == NET_GLOBLABEL
  703. || ntype == NET_HIERLABEL
  704. || ntype == NET_BUSLABELMEMBER
  705. || ntype == NET_GLOBBUSLABELMEMBER
  706. || ntype == NET_HIERBUSLABELMEMBER
  707. || ntype == NET_PINLABEL )
  708. {
  709. if( g_NetObjectslist[i]->m_Label.CmpNoCase( LabelRef->m_Label ) != 0 )
  710. continue;
  711. if( g_NetObjectslist[i]->GetNet() )
  712. PropageNetCode( g_NetObjectslist[i]->GetNet(), LabelRef->GetNet(), 0 );
  713. else
  714. g_NetObjectslist[i]->SetNet( LabelRef->GetNet() );
  715. }
  716. }
  717. }
  718. /* Comparison routine for sorting by increasing Netcode
  719. * table of elements connected (TabPinSort) by qsort ()
  720. */
  721. bool SortItemsbyNetcode( const NETLIST_OBJECT* Objet1, const NETLIST_OBJECT* Objet2 )
  722. {
  723. return Objet1->GetNet() < Objet2->GetNet();
  724. }
  725. /* Comparison routine for sorting items by Sheet Number ( used by qsort )
  726. */
  727. bool SortItemsBySheet( const NETLIST_OBJECT* Objet1, const NETLIST_OBJECT* Objet2 )
  728. {
  729. return Objet1->m_SheetList.Cmp( Objet2->m_SheetList ) < 0;
  730. }
  731. /* Routine positioning member. FlagNoConnect ELEMENTS
  732. * List of objects NetList, sorted by order of Netcode
  733. */
  734. static void SetUnconnectedFlag( NETLIST_OBJECT_LIST& aNetItemBuffer )
  735. {
  736. NETLIST_OBJECT* NetItemRef;
  737. unsigned NetStart, NetEnd;
  738. NET_CONNECTION_T StateFlag;
  739. NetStart = NetEnd = 0;
  740. StateFlag = UNCONNECTED;
  741. for( unsigned ii = 0; ii < aNetItemBuffer.size(); ii++ )
  742. {
  743. NetItemRef = aNetItemBuffer[ii];
  744. if( NetItemRef->m_Type == NET_NOCONNECT && StateFlag != PAD_CONNECT )
  745. StateFlag = NOCONNECT_SYMBOL_PRESENT;
  746. /* Analysis of current net. */
  747. unsigned idxtoTest = ii + 1;
  748. if( ( idxtoTest >= aNetItemBuffer.size() )
  749. || ( NetItemRef->GetNet() != aNetItemBuffer[idxtoTest]->GetNet() ) )
  750. {
  751. /* Net analysis to update m_FlagOfConnection */
  752. NetEnd = idxtoTest;
  753. /* set m_FlagOfConnection member to StateFlag for all items of
  754. * this net: */
  755. for( unsigned kk = NetStart; kk < NetEnd; kk++ )
  756. aNetItemBuffer[kk]->m_FlagOfConnection = StateFlag;
  757. if( idxtoTest >= aNetItemBuffer.size() )
  758. return;
  759. /* Start Analysis next Net */
  760. StateFlag = UNCONNECTED;
  761. NetStart = idxtoTest;
  762. continue;
  763. }
  764. /* test the current item: if this is a pin and if the reference item
  765. * is also a pin, then 2 pins are connected, so set StateFlag to
  766. * PAD_CONNECT (can be already done) Of course, if the current
  767. * item is a no connect symbol, set StateFlag to
  768. * NOCONNECT_SYMBOL_PRESENT to inhibit error diags. However if
  769. * StateFlag is already set to PAD_CONNECT this state is kept (the
  770. * no connect symbol was surely an error and an ERC will report this)
  771. */
  772. for( ; ; idxtoTest++ )
  773. {
  774. if( ( idxtoTest >= aNetItemBuffer.size() )
  775. || ( NetItemRef->GetNet() != aNetItemBuffer[idxtoTest]->GetNet() ) )
  776. break;
  777. switch( aNetItemBuffer[idxtoTest]->m_Type )
  778. {
  779. case NET_ITEM_UNSPECIFIED:
  780. wxMessageBox( wxT( "BuildNetListBase() error" ) );
  781. break;
  782. case NET_SEGMENT:
  783. case NET_LABEL:
  784. case NET_HIERLABEL:
  785. case NET_GLOBLABEL:
  786. case NET_SHEETLABEL:
  787. case NET_PINLABEL:
  788. case NET_BUS:
  789. case NET_BUSLABELMEMBER:
  790. case NET_SHEETBUSLABELMEMBER:
  791. case NET_HIERBUSLABELMEMBER:
  792. case NET_GLOBBUSLABELMEMBER:
  793. case NET_JUNCTION:
  794. break;
  795. case NET_PIN:
  796. if( NetItemRef->m_Type == NET_PIN )
  797. StateFlag = PAD_CONNECT;
  798. break;
  799. case NET_NOCONNECT:
  800. if( StateFlag != PAD_CONNECT )
  801. StateFlag = NOCONNECT_SYMBOL_PRESENT;
  802. break;
  803. }
  804. }
  805. }
  806. }