KiCad PCB EDA Suite
eeschema/netlist.cpp
Go to the documentation of this file.
1 /*
2  * This program source code file is part of KiCad, a free EDA CAD application.
3  *
4  * Copyright (C) 2015 Jean-Pierre Charras, jp.charras at wanadoo.fr
5  * Copyright (C) 2013 Wayne Stambaugh <stambaughw@gmail.com>
6  * Copyright (C) 1992-2017 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 
30 #include <fctsys.h>
31 #include <schframe.h>
32 #include <confirm.h>
33 #include <netlist_exporter_kicad.h>
34 #include <kiway.h>
35 
36 #include <netlist.h>
37 #include <class_netlist_object.h>
38 #include <class_library.h>
39 #include <lib_pin.h>
40 #include <sch_junction.h>
41 #include <sch_component.h>
42 #include <sch_line.h>
43 #include <sch_no_connect.h>
44 #include <sch_text.h>
45 #include <sch_sheet.h>
46 #include <algorithm>
47 #include <invoke_sch_dialog.h>
48 
49 #define IS_WIRE false
50 #define IS_BUS true
51 
52 //Imported function:
53 int TestDuplicateSheetNames( bool aCreateMarker );
54 
55 
57 {
58  SCH_SCREENS schematic;
59 
60  // Ensure all symbol library links for all sheets valid:
61  schematic.UpdateSymbolLinks();
62 
63  // Ensure all power symbols have a valid reference
64  SCH_SHEET_LIST sheets( g_RootSheet );
65  sheets.AnnotatePowerSymbols();
66 
67  // Performs some controls:
68  if( CheckAnnotate( NULL, 0 ) )
69  {
70  // Schematic must be annotated: call Annotate dialog and tell
71  // the user why that is.
72  InvokeDialogAnnotate( this, _( "Exporting the netlist requires a "
73  "completely\nannotated schematic." ) );
74 
75  if( CheckAnnotate( NULL, 0 ) )
76  return false;
77  }
78 
79  // Test duplicate sheet names:
80  if( TestDuplicateSheetNames( false ) > 0 )
81  {
82  if( !IsOK( NULL, _( "Error: duplicate sheet names. Continue?" ) ) )
83  return false;
84  }
85 
86  // Cleanup the entire hierarchy
87  schematic.SchematicCleanUp();
88 
89  return true;
90 }
91 
92 
94 {
96 
97  NETLIST_EXPORTER_KICAD exporter( net_atoms, Prj().SchSymbolLibTable() );
98 
99  STRING_FORMATTER formatter;
100 
101  // @todo : trim GNL_ALL down to minimum for CVPCB
102  exporter.Format( &formatter, GNL_ALL );
103 
106  formatter.GetString(), // an abbreviated "kicad" (s-expr) netlist
107  this
108  );
109 }
110 
111 
112 bool SCH_EDIT_FRAME::CreateNetlist( int aFormat, const wxString& aFullFileName,
113  unsigned aNetlistOptions, REPORTER* aReporter, bool aSilent )
114 {
115  if( !aSilent ) // checks for errors and invokes annotation dialog as neccessary
116  {
117  if( !prepareForNetlist() )
118  return false;
119  }
120  else // performs similar function as prepareForNetlist but without a dialog.
121  {
122  SCH_SCREENS schematic;
123  schematic.UpdateSymbolLinks();
124  SCH_SHEET_LIST sheets( g_RootSheet );
125  sheets.AnnotatePowerSymbols();
126  schematic.SchematicCleanUp();
127  }
128 
129  std::unique_ptr<NETLIST_OBJECT_LIST> connectedItemsList( BuildNetListBase() );
130 
131  bool success = WriteNetListFile( connectedItemsList.release(), aFormat,
132  aFullFileName, aNetlistOptions, aReporter );
133 
134  return success;
135 }
136 
137 
138 //#define NETLIST_DEBUG
139 
141 {
142  Clear();
143 }
144 
145 
147 {
148  NETLIST_OBJECTS::iterator iter;
149 
150  for( iter = begin(); iter != end(); iter++ )
151  {
152  NETLIST_OBJECT* item = *iter;
153  delete item;
154  }
155 
156  clear();
157 }
158 
159 
161 {
163 }
164 
165 
167 {
169 }
170 
171 
173 {
174  // I own this list until I return it to the new owner.
175  std::unique_ptr<NETLIST_OBJECT_LIST> ret( new NETLIST_OBJECT_LIST() );
176 
177  // Creates the flattened sheet list:
178  SCH_SHEET_LIST aSheets( g_RootSheet );
179 
180  // Build netlist info
181  bool success = ret->BuildNetListInfo( aSheets );
182 
183  if( !success )
184  {
185  if( updateStatusText )
186  SetStatusText( _( "No Objects" ) );
187  return ret.release();
188  }
189 
190  wxString msg = wxString::Format( _( "Net count = %d" ), int( ret->size() ) );
191 
192  if( updateStatusText )
193  SetStatusText( msg );
194 
195  return ret.release();
196 }
197 
198 
200 {
201  SCH_SHEET_PATH* sheet;
202 
203  // Fill list with connected items from the flattened sheet list
204  for( unsigned i = 0; i < aSheets.size(); i++ )
205  {
206  sheet = &aSheets[i];
207 
208  for( SCH_ITEM* item = sheet->LastScreen()->GetDrawItems(); item; item = item->Next() )
209  {
210  item->GetNetListItem( *this, sheet );
211  }
212  }
213 
214  if( size() == 0 )
215  return false;
216 
217  // Sort objects by Sheet
218  SortListbySheet();
219 
220  sheet = &(GetItem( 0 )->m_SheetPath);
222 
223  for( unsigned ii = 0, istart = 0; ii < size(); ii++ )
224  {
225  NETLIST_OBJECT* net_item = GetItem( ii );
226 
227  if( net_item->m_SheetPath != *sheet ) // Sheet change
228  {
229  sheet = &(net_item->m_SheetPath);
230  istart = ii;
231  }
232 
233  switch( net_item->m_Type )
234  {
236  wxMessageBox( wxT( "BuildNetListInfo() error" ) );
237  break;
238 
239  case NET_PIN:
240  case NET_PINLABEL:
241  case NET_SHEETLABEL:
242  case NET_NOCONNECT:
243  if( net_item->GetNet() != 0 )
244  break;
245 
246  case NET_SEGMENT:
247  // Test connections point to point type without bus.
248  if( net_item->GetNet() == 0 )
249  {
250  net_item->SetNet( m_lastNetCode );
251  m_lastNetCode++;
252  }
253 
254  pointToPointConnect( net_item, IS_WIRE, istart );
255  break;
256 
257  case NET_JUNCTION:
258  // Control of the junction outside BUS.
259  if( net_item->GetNet() == 0 )
260  {
261  net_item->SetNet( m_lastNetCode );
262  m_lastNetCode++;
263  }
264 
265  segmentToPointConnect( net_item, IS_WIRE, istart );
266 
267  // Control of the junction, on BUS.
268  if( net_item->m_BusNetCode == 0 )
269  {
270  net_item->m_BusNetCode = m_lastBusNetCode;
272  }
273 
274  segmentToPointConnect( net_item, IS_BUS, istart );
275  break;
276 
277  case NET_LABEL:
278  case NET_HIERLABEL:
279  case NET_GLOBLABEL:
280  // Test connections type junction without bus.
281  if( net_item->GetNet() == 0 )
282  {
283  net_item->SetNet( m_lastNetCode );
284  m_lastNetCode++;
285  }
286 
287  segmentToPointConnect( net_item, IS_WIRE, istart );
288  break;
289 
291  if( net_item->m_BusNetCode != 0 )
292  break;
293 
294  case NET_BUS:
295  // Control type connections point to point mode bus
296  if( net_item->m_BusNetCode == 0 )
297  {
298  net_item->m_BusNetCode = m_lastBusNetCode;
300  }
301 
302  pointToPointConnect( net_item, IS_BUS, istart );
303  break;
304 
305  case NET_BUSLABELMEMBER:
308  // Control connections similar has on BUS
309  if( net_item->GetNet() == 0 )
310  {
311  net_item->m_BusNetCode = m_lastBusNetCode;
313  }
314 
315  segmentToPointConnect( net_item, IS_BUS, istart );
316  break;
317  }
318  }
319 
320 #if defined(NETLIST_DEBUG) && defined(DEBUG)
321  std::cout << "\n\nafter sheet local\n\n";
322  DumpNetTable();
323 #endif
324 
325  // Updating the Bus Labels Netcode connected by Bus
327 
328  // Group objects by label.
329  for( unsigned ii = 0; ii < size(); ii++ )
330  {
331  switch( GetItem( ii )->m_Type )
332  {
333  case NET_PIN:
334  case NET_SHEETLABEL:
335  case NET_SEGMENT:
336  case NET_JUNCTION:
337  case NET_BUS:
338  case NET_NOCONNECT:
339  break;
340 
341  case NET_LABEL:
342  case NET_GLOBLABEL:
343  case NET_PINLABEL:
344  case NET_BUSLABELMEMBER:
346  labelConnect( GetItem( ii ) );
347  break;
348 
350  case NET_HIERLABEL:
352  break;
353 
355  break;
356  }
357  }
358 
359 #if defined(NETLIST_DEBUG) && defined(DEBUG)
360  std::cout << "\n\nafter sheet global\n\n";
361  DumpNetTable();
362 #endif
363 
364  // Connection between hierarchy sheets
365  for( unsigned ii = 0; ii < size(); ii++ )
366  {
367  if( GetItem( ii )->m_Type == NET_SHEETLABEL
368  || GetItem( ii )->m_Type == NET_SHEETBUSLABELMEMBER )
369  sheetLabelConnect( GetItem( ii ) );
370  }
371 
372  // Sort objects by NetCode
374 
375 #if defined(NETLIST_DEBUG) && defined(DEBUG)
376  std::cout << "\n\nafter qsort()\n";
377  DumpNetTable();
378 #endif
379 
380  // Compress numbers of Netcode having consecutive values.
381  int NetCode = 0;
382  m_lastNetCode = 0;
383 
384  for( unsigned ii = 0; ii < size(); ii++ )
385  {
386  if( GetItem( ii )->GetNet() != m_lastNetCode )
387  {
388  NetCode++;
389  m_lastNetCode = GetItem( ii )->GetNet();
390  }
391 
392  GetItem( ii )->SetNet( NetCode );
393  }
394 
395  // Set the minimal connection info:
397 
398  // find the best label object to give the best net name to each net
400 
401  return true;
402 }
403 
404 // Helper function to give a priority to sort labels:
405 // NET_PINLABEL, NET_GLOBBUSLABELMEMBER and NET_GLOBLABEL are global labels
406 // and the priority is high
407 static int getPriority( const NETLIST_OBJECT* Objet )
408 {
409  switch( Objet->m_Type )
410  {
411  case NET_PIN: return 1;
412  case NET_LABEL: return 2;
413  case NET_HIERLABEL: return 3;
414  case NET_PINLABEL: return 4;
415  case NET_GLOBBUSLABELMEMBER: return 5;
416  case NET_GLOBLABEL: return 6;
417  default: break;
418  }
419 
420  return 0;
421 }
422 
423 
424 /* function evalLabelsPriority used by findBestNetNameForEachNet()
425  * evalLabelsPriority calculates the priority of alabel1 and aLabel2
426  * return true if alabel1 has a higher priority than aLabel2
427  */
428 static bool evalLabelsPriority( const NETLIST_OBJECT* aLabel1, const NETLIST_OBJECT* aLabel2 )
429 {
430  // Global labels have the highest prioriy.
431  // For local labels: names are prefixed by their sheetpath
432  // use name defined in the more top level hierarchical sheet
433  // (i.e. shorter timestamp path because paths are /<timestamp1>/<timestamp2>/...
434  // and timestamp = 8 letters.
435  // Note: the final net name uses human sheetpath name, not timestamp sheetpath name
436  // They are equivalent, but not for human readers.
437  if( ! aLabel1->IsLabelGlobal() && ! aLabel2->IsLabelGlobal() )
438  {
439  if( aLabel1->m_SheetPath.Path().Length() != aLabel2->m_SheetPath.Path().Length() )
440  return aLabel1->m_SheetPath.Path().Length() < aLabel2->m_SheetPath.Path().Length();
441  }
442 
443  int priority1 = getPriority( aLabel1 );
444  int priority2 = getPriority( aLabel2 );
445 
446  if( priority1 != priority2 )
447  return priority1 > priority2;
448 
449  // Objects have here the same priority, therefore they have the same type.
450  // for global labels, we select the best candidate by alphabetic order
451  // because they have no sheetpath as prefix name
452  // for other labels, we select them before by sheet deep order
453  // because the actual name is /sheetpath/label
454  // and for a given path length, by alphabetic order
455  if( aLabel1->IsLabelGlobal() )
456  return aLabel1->m_Label.Cmp( aLabel2->m_Label ) < 0;
457 
458  // Sheet paths have here the same length: use alphabetic label name order
459  // For labels on sheets having an equivalent deep in hierarchy, use
460  // alphabetic label name order:
461  if( aLabel1->m_Label.Cmp( aLabel2->m_Label ) != 0 )
462  return aLabel1->m_Label.Cmp( aLabel2->m_Label ) < 0;
463 
464  // For identical labels having the same priority: choose the
465  // alphabetic label full name order
466  return aLabel1->m_SheetPath.PathHumanReadable().Cmp(
467  aLabel2->m_SheetPath.PathHumanReadable() ) < 0;
468 }
469 
470 
472 {
473  // Important note: NET_SHEETLABEL items of sheet items should *NOT* be considered,
474  // because they live in a sheet but their names are actually used in the subsheet.
475  // Moreover, in the parent sheet, the name of NET_SHEETLABEL can be not unique,
476  // ( for instance when 2 different sheets share the same schematic in complex hierarchies
477  // and 2 identical NET_SHEETLABEL labels can be connected to 2 different nets
478 
479  int netcode = 0; // current netcode for tested items
480  unsigned idxstart = 0; // index of the first item of this net
481  NETLIST_OBJECT* item;
482  NETLIST_OBJECT* candidate;
483 
484  // Pass 1: find the best name for labelled nets:
485  candidate = NULL;
486  for( unsigned ii = 0; ii <= size(); ii++ )
487  {
488  if( ii == size() ) // last item already tested
489  item = NULL;
490  else
491  item = GetItem( ii );
492 
493  if( !item || netcode != item->GetNet() ) // End of net found
494  {
495  if( candidate ) // One or more labels exists, find the best
496  {
497  for (unsigned jj = idxstart; jj < ii; jj++ )
498  GetItem( jj )->SetNetNameCandidate( candidate );
499  }
500 
501  if( item == NULL ) // End of list
502  break;
503 
504  // Prepare next net analysis:
505  netcode = item->GetNet();
506  candidate = NULL;
507  idxstart = ii;
508  }
509 
510  switch( item->m_Type )
511  {
512  case NET_HIERLABEL:
513  case NET_LABEL:
514  case NET_PINLABEL:
515  case NET_GLOBLABEL:
517  // A candidate is found: select the better between the previous
518  // and this one
519  if( candidate == NULL )
520  candidate = item;
521  else
522  {
523  if( evalLabelsPriority( item, candidate ) )
524  // item has a highter priority than candidate
525  // so update the best candidate
526  candidate = item;
527  }
528  break;
529 
530  default:
531  break;
532  }
533  }
534 
535  // Pass 2: find the best name for not labelled nets:
536  // The "default" net name is Net-<<Ref cmp>_Pad<num pad>>
537  // (see NETLIST_OBJECT::GetShortNetName())
538  // therefore the "best" is the short net name alphabetically classed first
539  // (to avoid net names changes when the net is not modified,
540  // even if components are moved or deleted and undelete or replaced, as long
541  // the reference is kept)
542 
543  // Build a list of items with no net names
544  NETLIST_OBJECTS list; // no ownership of elements being pointed at
545 
546  for( unsigned ii = 0; ii < size(); ii++ )
547  {
548  item = GetItem( ii );
549 
550  if( !item->HasNetNameCandidate() )
551  list.push_back( item );
552  }
553 
554  if( list.size() == 0 )
555  return;
556 
557  idxstart = 0;
558  candidate = NULL;
559  netcode = list[0]->GetNet();
560 
561  for( unsigned ii = 0; ii <= list.size(); ii++ )
562  {
563  if( ii < list.size() )
564  item = list[ii];
565  else
566  item = NULL;
567 
568  if( !item || netcode != item->GetNet() ) // End of net found
569  {
570  if( candidate )
571  {
572  for (unsigned jj = idxstart; jj < ii; jj++ )
573  {
574  NETLIST_OBJECT* obj = list[jj];
575  obj->SetNetNameCandidate( candidate );
576  }
577  }
578 
579  if( !item )
580  break;
581 
582  netcode = item->GetNet();
583  candidate = NULL;
584  idxstart = ii;
585  }
586 
587  // Examine all pins of the net to find the best candidate,
588  // i.e. the first net name candidate, by alphabetic order
589  // the net names are built by GetShortNetName
590  // (Net-<{reference}-Pad{pad number}> like Net-<U3-Pad5>
591  // Not named nets do not have usually a lot of members.
592  // Many have only 2 members(a pad and a non connection symbol)
593  if( item->m_Type == NET_PIN )
594  {
595  // A candidate is found, however components which are not in
596  // netlist are not candidate because some have their reference
597  // changed each time the netlist is built (power components)
598  // and anyway obviously they are not a good candidate
599  SCH_COMPONENT* link = item->GetComponentParent();
600 
601  if( link && link->IsInNetlist() )
602  {
603  // select the better between the previous and this one
604  item->SetNetNameCandidate( item ); // Needed to calculate GetShortNetName
605 
606  if( candidate == NULL )
607  candidate = item;
608  else
609  {
610  if( item->GetShortNetName().Cmp( candidate->GetShortNetName() ) < 0 )
611  candidate = item;
612  }
613  }
614  }
615  }
616 }
617 
618 
620 {
621  if( SheetLabel->GetNet() == 0 )
622  return;
623 
624  for( unsigned ii = 0; ii < size(); ii++ )
625  {
626  NETLIST_OBJECT* ObjetNet = GetItem( ii );
627 
628  if( ObjetNet->m_SheetPath != SheetLabel->m_SheetPathInclude )
629  continue; //use SheetInclude, not the sheet!!
630 
631  if( (ObjetNet->m_Type != NET_HIERLABEL ) && (ObjetNet->m_Type != NET_HIERBUSLABELMEMBER ) )
632  continue;
633 
634  if( ObjetNet->GetNet() == SheetLabel->GetNet() )
635  continue; //already connected.
636 
637  if( ObjetNet->m_Label != SheetLabel->m_Label )
638  continue; //different names.
639 
640  // Propagate Netcode having all the objects of the same Netcode.
641  if( ObjetNet->GetNet() )
642  propagateNetCode( ObjetNet->GetNet(), SheetLabel->GetNet(), IS_WIRE );
643  else
644  ObjetNet->SetNet( SheetLabel->GetNet() );
645  }
646 }
647 
648 
650 {
651  // Propagate the net code between all bus label member objects connected by they name.
652  // If the net code is not yet existing, a new one is created
653  // Search is done in the entire list
654  for( unsigned ii = 0; ii < size(); ii++ )
655  {
656  NETLIST_OBJECT* Label = GetItem( ii );
657 
658  if( Label->IsLabelBusMemberType() )
659  {
660  if( Label->GetNet() == 0 )
661  {
662  // Not yet existiing net code: create a new one.
663  Label->SetNet( m_lastNetCode );
664  m_lastNetCode++;
665  }
666 
667  for( unsigned jj = ii + 1; jj < size(); jj++ )
668  {
669  NETLIST_OBJECT* LabelInTst = GetItem( jj );
670 
671  if( LabelInTst->IsLabelBusMemberType() )
672  {
673  if( LabelInTst->m_BusNetCode != Label->m_BusNetCode )
674  continue;
675 
676  if( LabelInTst->m_Member != Label->m_Member )
677  continue;
678 
679  if( LabelInTst->GetNet() == 0 )
680  // Append this object to the current net
681  LabelInTst->SetNet( Label->GetNet() );
682  else
683  // Merge the 2 net codes, they are connected.
684  propagateNetCode( LabelInTst->GetNet(), Label->GetNet(), IS_WIRE );
685  }
686  }
687  }
688  }
689 }
690 
691 
692 void NETLIST_OBJECT_LIST::propagateNetCode( int aOldNetCode, int aNewNetCode, bool aIsBus )
693 {
694  if( aOldNetCode == aNewNetCode )
695  return;
696 
697  if( aIsBus == false ) // Propagate NetCode
698  {
699  for( unsigned jj = 0; jj < size(); jj++ )
700  {
701  NETLIST_OBJECT* object = GetItem( jj );
702 
703  if( object->GetNet() == aOldNetCode )
704  object->SetNet( aNewNetCode );
705  }
706  }
707  else // Propagate BusNetCode
708  {
709  for( unsigned jj = 0; jj < size(); jj++ )
710  {
711  NETLIST_OBJECT* object = GetItem( jj );
712 
713  if( object->m_BusNetCode == aOldNetCode )
714  object->m_BusNetCode = aNewNetCode;
715  }
716  }
717 }
718 
719 
720 void NETLIST_OBJECT_LIST::pointToPointConnect( NETLIST_OBJECT* aRef, bool aIsBus, int start )
721 {
722  int netCode;
723 
724  if( aIsBus == false ) // Objects other than BUS and BUSLABELS
725  {
726  netCode = aRef->GetNet();
727 
728  for( unsigned i = start; i < size(); i++ )
729  {
730  NETLIST_OBJECT* item = GetItem( i );
731 
732  if( item->m_SheetPath != aRef->m_SheetPath ) //used to be > (why?)
733  continue;
734 
735  switch( item->m_Type )
736  {
737  case NET_SEGMENT:
738  case NET_PIN:
739  case NET_LABEL:
740  case NET_HIERLABEL:
741  case NET_GLOBLABEL:
742  case NET_SHEETLABEL:
743  case NET_PINLABEL:
744  case NET_JUNCTION:
745  case NET_NOCONNECT:
746  if( aRef->m_Start == item->m_Start
747  || aRef->m_Start == item->m_End
748  || aRef->m_End == item->m_Start
749  || aRef->m_End == item->m_End )
750  {
751  if( item->GetNet() == 0 )
752  item->SetNet( netCode );
753  else
754  propagateNetCode( item->GetNet(), netCode, IS_WIRE );
755  }
756  break;
757 
758  case NET_BUS:
759  case NET_BUSLABELMEMBER:
764  break;
765  }
766  }
767  }
768  else // Object type BUS, BUSLABELS, and junctions.
769  {
770  netCode = aRef->m_BusNetCode;
771 
772  for( unsigned i = start; i < size(); i++ )
773  {
774  NETLIST_OBJECT* item = GetItem( i );
775 
776  if( item->m_SheetPath != aRef->m_SheetPath )
777  continue;
778 
779  switch( item->m_Type )
780  {
782  case NET_SEGMENT:
783  case NET_PIN:
784  case NET_LABEL:
785  case NET_HIERLABEL:
786  case NET_GLOBLABEL:
787  case NET_SHEETLABEL:
788  case NET_PINLABEL:
789  case NET_NOCONNECT:
790  break;
791 
792  case NET_BUS:
793  case NET_BUSLABELMEMBER:
797  case NET_JUNCTION:
798  if( aRef->m_Start == item->m_Start
799  || aRef->m_Start == item->m_End
800  || aRef->m_End == item->m_Start
801  || aRef->m_End == item->m_End )
802  {
803  if( item->m_BusNetCode == 0 )
804  item->m_BusNetCode = netCode;
805  else
806  propagateNetCode( item->m_BusNetCode, netCode, IS_BUS );
807  }
808  break;
809  }
810  }
811  }
812 }
813 
814 
816  bool aIsBus, int aIdxStart )
817 {
818  for( unsigned i = aIdxStart; i < size(); i++ )
819  {
820  NETLIST_OBJECT* segment = GetItem( i );
821 
822  // if different sheets, obviously no physical connection between elements.
823  if( segment->m_SheetPath != aJonction->m_SheetPath )
824  continue;
825 
826  if( aIsBus == IS_WIRE )
827  {
828  if( segment->m_Type != NET_SEGMENT )
829  continue;
830  }
831  else
832  {
833  if( segment->m_Type != NET_BUS )
834  continue;
835  }
836 
837  if( IsPointOnSegment( segment->m_Start, segment->m_End, aJonction->m_Start ) )
838  {
839  // Propagation Netcode has all the objects of the same Netcode.
840  if( aIsBus == IS_WIRE )
841  {
842  if( segment->GetNet() )
843  propagateNetCode( segment->GetNet(), aJonction->GetNet(), aIsBus );
844  else
845  segment->SetNet( aJonction->GetNet() );
846  }
847  else
848  {
849  if( segment->m_BusNetCode )
850  propagateNetCode( segment->m_BusNetCode, aJonction->m_BusNetCode, aIsBus );
851  else
852  segment->m_BusNetCode = aJonction->m_BusNetCode;
853  }
854  }
855  }
856 }
857 
858 
860 {
861  if( aLabelRef->GetNet() == 0 )
862  return;
863 
864  for( unsigned i = 0; i < size(); i++ )
865  {
866  NETLIST_OBJECT* item = GetItem( i );
867 
868  if( item->GetNet() == aLabelRef->GetNet() )
869  continue;
870 
871  if( item->m_SheetPath != aLabelRef->m_SheetPath )
872  {
873  if( item->m_Type != NET_PINLABEL && item->m_Type != NET_GLOBLABEL
874  && item->m_Type != NET_GLOBBUSLABELMEMBER )
875  continue;
876 
877  if( (item->m_Type == NET_GLOBLABEL
878  || item->m_Type == NET_GLOBBUSLABELMEMBER)
879  && item->m_Type != aLabelRef->m_Type )
880  //global labels only connect other global labels.
881  continue;
882  }
883 
884  // NET_HIERLABEL are used to connect sheets.
885  // NET_LABEL are local to a sheet
886  // NET_GLOBLABEL are global.
887  // NET_PINLABEL is a kind of global label (generated by a power pin invisible)
888  if( item->IsLabelType() )
889  {
890  if( item->m_Label != aLabelRef->m_Label )
891  continue;
892 
893  if( item->GetNet() )
894  propagateNetCode( item->GetNet(), aLabelRef->GetNet(), IS_WIRE );
895  else
896  item->SetNet( aLabelRef->GetNet() );
897  }
898  }
899 }
900 
901 
903 {
904  NETLIST_OBJECT* NetItemRef;
905  unsigned NetStart, NetEnd;
906  NET_CONNECTION_T StateFlag;
907 
908  NetStart = NetEnd = 0;
909  StateFlag = UNCONNECTED;
910  for( unsigned ii = 0; ii < size(); ii++ )
911  {
912  NetItemRef = GetItem( ii );
913  if( NetItemRef->m_Type == NET_NOCONNECT && StateFlag != PAD_CONNECT )
914  StateFlag = NOCONNECT_SYMBOL_PRESENT;
915 
916  // Analysis of current net.
917  unsigned idxtoTest = ii + 1;
918 
919  if( ( idxtoTest >= size() )
920  || ( NetItemRef->GetNet() != GetItem( idxtoTest )->GetNet() ) )
921  {
922  // Net analysis to update m_ConnectionType
923  NetEnd = idxtoTest;
924 
925  /* set m_ConnectionType member to StateFlag for all items of
926  * this net: */
927  for( unsigned kk = NetStart; kk < NetEnd; kk++ )
928  GetItem( kk )->m_ConnectionType = StateFlag;
929 
930  if( idxtoTest >= size() )
931  return;
932 
933  // Start Analysis next Net
934  StateFlag = UNCONNECTED;
935  NetStart = idxtoTest;
936  continue;
937  }
938 
939  /* test the current item: if this is a pin and if the reference item
940  * is also a pin, then 2 pins are connected, so set StateFlag to
941  * PAD_CONNECT (can be already done) Of course, if the current
942  * item is a no connect symbol, set StateFlag to
943  * NOCONNECT_SYMBOL_PRESENT to inhibit error diags. However if
944  * StateFlag is already set to PAD_CONNECT this state is kept (the
945  * no connect symbol was surely an error and an ERC will report this)
946  */
947  for( ; ; idxtoTest++ )
948  {
949  if( ( idxtoTest >= size() )
950  || ( NetItemRef->GetNet() != GetItem( idxtoTest )->GetNet() ) )
951  break;
952 
953  switch( GetItem( idxtoTest )->m_Type )
954  {
956  wxMessageBox( wxT( "BuildNetListBase() error" ) );
957  break;
958 
959  case NET_SEGMENT:
960  case NET_LABEL:
961  case NET_HIERLABEL:
962  case NET_GLOBLABEL:
963  case NET_SHEETLABEL:
964  case NET_PINLABEL:
965  case NET_BUS:
966  case NET_BUSLABELMEMBER:
970  case NET_JUNCTION:
971  break;
972 
973  case NET_PIN:
974  if( NetItemRef->m_Type == NET_PIN )
975  StateFlag = PAD_CONNECT;
976 
977  break;
978 
979  case NET_NOCONNECT:
980  if( StateFlag != PAD_CONNECT )
981  StateFlag = NOCONNECT_SYMBOL_PRESENT;
982 
983  break;
984  }
985  }
986  }
987 }
Definition of the SCH_SHEET class for Eeschema.
Class SCH_SHEET_LIST.
void setUnconnectedFlag()
Set the m_FlagOfConnection member of items in list depending on the connection type: UNCONNECTED...
#define IS_WIRE
bool IsLabelGlobal() const
Function IsLabelGlobal.
bool IsPointOnSegment(const wxPoint &aSegStart, const wxPoint &aSegEnd, const wxPoint &aTestPoint)
Function IsPointOnSegment.
Definition: trigo.cpp:39
ITERATOR begin(int aType=UNDEFINED_TYPE)
Definition: multivector.h:183
void sendNetlist()
Send the kicad netlist over to CVPCB.
void connectBusLabels()
Function connectBusLabels Propagate the net code (and create it, if not yet existing) between all bus...
NETLIST_OBJECT_LIST * BuildNetListBase(bool updateStatusText=true)
Create a flat list which stores all connected objects.
KIWAY & Kiway() const
Function Kiway returns a reference to the KIWAY that this object has an opportunity to participate in...
Definition: kiway_player.h:60
NETLIST_OBJECT * GetItem(unsigned aIdx) const
Acces to an item in list.
SCH_SHEET_PATH m_SheetPathInclude
This file is part of the common library.
int CheckAnnotate(wxArrayString *aMessageList, bool aOneSheetOnly)
Check for annotation errors.
Definition: annotate.cpp:187
bool CreateNetlist(int aFormat, const wxString &aFullFileName, unsigned aNetlistOptions, REPORTER *aReporter=NULL, bool silent=false) override
Create a netlist for the current schematic.
bool BuildNetListInfo(SCH_SHEET_LIST &aSheets)
Function BuildNetListInfo the master function of tgis class.
void sort()
Definition: multivector.h:229
NET_CONNECTION_T m_ConnectionType
SCH_SHEET_PATH m_SheetPath
void findBestNetNameForEachNet()
Function findBestNetNameForEachNet fill the .m_NetNameCandidate member of each item of aNetItemBuffer...
SCH_SCREEN * LastScreen() const
Function LastScreen.
Class REPORTER is a pure virtual class used to derive REPORTER objects from.
Definition: reporter.h:61
NETLIST_ITEM_T m_Type
void labelConnect(NETLIST_OBJECT *aLabelRef)
void Format(OUTPUTFORMATTER *aOutputFormatter, int aCtl)
Function Format outputs this s-expression netlist into aOutputFormatter.
SCH_ITEM * Next() const
void Clear()
Delete all objects in list and clear list.
void sheetLabelConnect(NETLIST_OBJECT *aSheetLabel)
Propagate net codes from a parent sheet to an include sheet, from a pin sheet connection.
NET_CONNECTION_T
Class NETLIST_OBJECT_LIST is a container holding and owning NETLIST_OBJECTs, which are connected item...
wxString Path() const
Function Path the path uses the time stamps which do not changes even when editing sheet parameters a...
ITERATOR end(int aType=UNDEFINED_TYPE)
Definition: multivector.h:189
void segmentToPointConnect(NETLIST_OBJECT *aJonction, bool aIsBus, int aIdxStart)
Search connections between a junction and segments Propagate the junction net code to objects connect...
PROJECT & Prj() const
Function Prj returns a reference to the PROJECT "associated with" this KIWAY.
bool IsLabelType() const
Function IsLabelType.
static bool sortItemsBySheet(const NETLIST_OBJECT *Objet1, const NETLIST_OBJECT *Objet2)
std::vector< NETLIST_OBJECT * > NETLIST_OBJECTS
Type NETLIST_OBJECTS is a container referring to (not owning) NETLIST_OBJECTs, which are connected it...
SCH_SHEET * g_RootSheet
Definition: eeschema.cpp:55
bool IsLabelBusMemberType() const
Function IsLabelBusMemberType.
bool prepareForNetlist()
Verify that annotation is complete so that a proper netlist is even possible.
wxString PathHumanReadable() const
Function PathHumanReadable returns the sheet path in a human readable form, i.e.
void SchematicCleanUp()
Merge and break wire segments in the entire schematic hierarchy.
Class NETLIST_EXPORTER_KICAD generates the kicad netlist format supported by pcbnew.
static bool sortItemsbyNetcode(const NETLIST_OBJECT *Objet1, const NETLIST_OBJECT *Objet2)
void propagateNetCode(int aOldNetCode, int aNewNetCode, bool aIsBus)
#define IS_BUS
int InvokeDialogAnnotate(SCH_EDIT_FRAME *aCaller, wxString message)
Create and show DIALOG_ANNOTATE and return whatever DIALOG_ANNOTATE::ShowModal() returns.
size_t size(int aType=UNDEFINED_TYPE)
Definition: multivector.h:207
const std::string & GetString()
Definition: richio.h:475
Class SCH_SHEET_PATH.
bool IsInNetlist() const
SCH_COMPONENT * GetComponentParent() const
For Pins (NET_PINS):
Definition of the NETLIST_OBJECT class.
SCH_ITEM * GetDrawItems() const
Definition the SCH_COMPONENT class for Eeschema.
void UpdateSymbolLinks(bool aForce=false)
Initialize or reinitialize the weak reference to the LIB_PART for each SCH_COMPONENT found in the ful...
void Format(OUTPUTFORMATTER *out, int aNestLevel, int aCtl, CPTREE &aTree)
Function Format outputs a PTREE into s-expression format via an OUTPUTFORMATTER derivative.
Definition: ptree.cpp:205
VTBL_ENTRY void ExpressMail(FRAME_T aDestination, MAIL_T aCommand, const std::string &aPayload, wxWindow *aSource=NULL)
Function ExpressMail send aPayload to aDestination from aSource.
Definition: kiway.cpp:387
int TestDuplicateSheetNames(bool aCreateMarker)
Function TestDuplicateSheetNames( ) inside a given sheet, one cannot have sheets with duplicate names...
Definition: erc.cpp:177
static int getPriority(const NETLIST_OBJECT *Objet)
void SetNet(int aNetCode)
#define GNL_ALL
void SetNetNameCandidate(NETLIST_OBJECT *aCandidate)
Set m_netNameCandidate to a connected item which will be used to calcule the net name of the item Obv...
Class SCH_COMPONENT describes a real schematic component.
Definition: sch_component.h:69
wxString GetShortNetName(bool adoptTimestamp=false) const
Function GetShortNetName.
void pointToPointConnect(NETLIST_OBJECT *aRef, bool aIsBus, int start)
void AnnotatePowerSymbols()
Function AnnotatePowerSymbols Silently annotates the not yet annotated power symbols of the entire hi...
Definition for part library class.
bool WriteNetListFile(NETLIST_OBJECT_LIST *aConnectedItemsList, int aFormat, const wxString &aFullFileName, unsigned aNetlistOptions, REPORTER *aReporter=NULL)
Create a netlist file.
Definition: netform.cpp:46
Class STRING_FORMATTER implements OUTPUTFORMATTER to a memory buffer.
Definition: richio.h:445
Class SCH_ITEM is a base class for any item which can be embedded within the SCHEMATIC container clas...
bool IsOK(wxWindow *aParent, const wxString &aMessage)
Function IsOK displays a yes/no dialog with aMessage and returns the user response.
Definition: confirm.cpp:129
Implementation of the label properties dialog.
static bool evalLabelsPriority(const NETLIST_OBJECT *aLabel1, const NETLIST_OBJECT *aLabel2)
Container class that holds multiple SCH_SCREEN objects in a hierarchy.
EESCHEMA->CVPCB netlist immediately after launching CVPCB.
Definition: mail_type.h:41