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