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