KiCad PCB EDA Suite
eeschema/erc.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) 2011-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 
31 #include <fctsys.h>
32 #include <kicad_string.h>
33 #include <sch_edit_frame.h>
34 #include <netlist_object.h>
35 #include <lib_pin.h>
36 #include <erc.h>
37 #include <sch_marker.h>
38 #include <sch_sheet.h>
39 #include <sch_reference_list.h>
40 #include <schematic.h>
41 #include <wx/ffile.h>
42 #include <ws_draw_item.h>
43 #include <ws_proxy_view_item.h>
44 
45 
46 /* ERC tests :
47  * 1 - conflicts between connected pins ( example: 2 connected outputs )
48  * 2 - minimal connections requirements ( 1 input *must* be connected to an
49  * output, or a passive pin )
50  */
51 
52 
53 /*
54  * Minimal ERC requirements:
55  * All pins *must* be connected (except ELECTRICAL_PINTYPE::PT_NC).
56  * When a pin is not connected in schematic, the user must place a "non
57  * connected" symbol to this pin.
58  * This ensures a forgotten connection will be detected.
59  */
60 
61 /* Messages for conflicts :
62  * ELECTRICAL_PINTYPE::PT_INPUT, ELECTRICAL_PINTYPE::PT_OUTPUT, ELECTRICAL_PINTYPE:PT_:BIDI, ELECTRICAL_PINTYPE::PT_TRISTATE, ELECTRICAL_PINTYPE::PT_PASSIVE,
63  * ELECTRICAL_PINTYPE::PT_UNSPECIFIED, ELECTRICAL_PINTYPE::PT_POWER_IN, ELECTRICAL_PINTYPE::PT_POWER_OUT, ELECTRICAL_PINTYPE::PT_OPENCOLLECTOR,
64  * ELECTRICAL_PINTYPE::PT_OPENEMITTER, ELECTRICAL_PINTYPE::PT_NC
65  * These messages are used to show the ERC matrix in ERC dialog
66  */
67 
68 // Messages for matrix rows:
69 const wxString CommentERC_H[] =
70 {
71  _( "Input Pin" ),
72  _( "Output Pin" ),
73  _( "Bidirectional Pin" ),
74  _( "Tri-State Pin" ),
75  _( "Passive Pin" ),
76  _( "Unspecified Pin" ),
77  _( "Power Input Pin" ),
78  _( "Power Output Pin" ),
79  _( "Open Collector" ),
80  _( "Open Emitter" ),
81  _( "No Connection" )
82 };
83 
84 // Messages for matrix columns
85 const wxString CommentERC_V[] =
86 {
87  _( "Input Pin" ),
88  _( "Output Pin" ),
89  _( "Bidirectional Pin" ),
90  _( "Tri-State Pin" ),
91  _( "Passive Pin" ),
92  _( "Unspecified Pin" ),
93  _( "Power Input Pin" ),
94  _( "Power Output Pin" ),
95  _( "Open Collector" ),
96  _( "Open Emitter" ),
97  _( "No Connection" )
98 };
99 
100 
101 int ERC_TESTER::TestDuplicateSheetNames( bool aCreateMarker )
102 {
103  SCH_SCREEN* screen;
104  int err_count = 0;
105 
106  SCH_SCREENS screenList( m_schematic->Root() );
107 
108  for( screen = screenList.GetFirst(); screen != nullptr; screen = screenList.GetNext() )
109  {
110  std::vector<SCH_SHEET*> list;
111 
112  for( SCH_ITEM* item : screen->Items().OfType( SCH_SHEET_T ) )
113  list.push_back( static_cast<SCH_SHEET*>( item ) );
114 
115  for( size_t i = 0; i < list.size(); i++ )
116  {
117  SCH_SHEET* sheet = list[i];
118 
119  for( size_t j = i + 1; j < list.size(); j++ )
120  {
121  SCH_SHEET* test_item = list[j];
122 
123  // We have found a second sheet: compare names
124  // we are using case insensitive comparison to avoid mistakes between
125  // similar names like Mysheet and mysheet
126  if( sheet->GetName().CmpNoCase( test_item->GetName() ) == 0 )
127  {
128  if( aCreateMarker )
129  {
131  ercItem->SetItems( sheet, test_item );
132 
133  SCH_MARKER* marker = new SCH_MARKER( ercItem, sheet->GetPosition() );
134  screen->Append( marker );
135  }
136 
137  err_count++;
138  }
139  }
140  }
141  }
142 
143  return err_count;
144 }
145 
146 
148 {
149  WS_DRAW_ITEM_LIST wsItems;
150 
151  auto unresolved = [this]( wxString str )
152  {
153  str = ExpandEnvVarSubstitutions( str, &m_schematic->Prj() );
154  return str.Matches( wxT( "*${*}*" ) );
155  };
156 
157  if( aWorksheet )
158  {
159  wsItems.SetMilsToIUfactor( IU_PER_MILS );
160  wsItems.BuildWorkSheetGraphicList( aWorksheet->GetPageInfo(), aWorksheet->GetTitleBlock() );
161  }
162 
163  SCH_SCREENS screens( m_schematic->Root() );
164 
165  for( SCH_SCREEN* screen = screens.GetFirst(); screen != NULL; screen = screens.GetNext() )
166  {
167  for( SCH_ITEM* item : screen->Items().OfType( SCH_LOCATE_ANY_T ) )
168  {
169  if( item->Type() == SCH_COMPONENT_T )
170  {
171  SCH_COMPONENT* component = static_cast<SCH_COMPONENT*>( item );
172 
173  for( SCH_FIELD& field : component->GetFields() )
174  {
175  if( unresolved( field.GetShownText() ) )
176  {
177  wxPoint pos = field.GetPosition() - component->GetPosition();
178  pos = component->GetTransform().TransformCoordinate( pos );
179  pos += component->GetPosition();
180 
182  ercItem->SetItems( &field );
183 
184  SCH_MARKER* marker = new SCH_MARKER( ercItem, pos );
185  screen->Append( marker );
186  }
187  }
188  }
189  else if( item->Type() == SCH_SHEET_T )
190  {
191  SCH_SHEET* sheet = static_cast<SCH_SHEET*>( item );
192 
193  for( SCH_FIELD& field : sheet->GetFields() )
194  {
195  if( unresolved( field.GetShownText() ) )
196  {
198  ercItem->SetItems( &field );
199 
200  SCH_MARKER* marker = new SCH_MARKER( ercItem, field.GetPosition() );
201  screen->Append( marker );
202  }
203  }
204 
205  for( SCH_SHEET_PIN* pin : static_cast<SCH_SHEET*>( item )->GetPins() )
206  {
207  if( pin->GetShownText().Matches( wxT( "*${*}*" ) ) )
208  {
210  ercItem->SetItems( pin );
211 
212  SCH_MARKER* marker = new SCH_MARKER( ercItem, pin->GetPosition() );
213  screen->Append( marker );
214  }
215  }
216  }
217  else if( SCH_TEXT* text = dynamic_cast<SCH_TEXT*>( item ) )
218  {
219  if( text->GetShownText().Matches( wxT( "*${*}*" ) ) )
220  {
222  ercItem->SetItems( text );
223 
224  SCH_MARKER* marker = new SCH_MARKER( ercItem, text->GetPosition() );
225  screen->Append( marker );
226  }
227  }
228  }
229 
230  for( WS_DRAW_ITEM_BASE* item = wsItems.GetFirst(); item; item = wsItems.GetNext() )
231  {
232  if( WS_DRAW_ITEM_TEXT* text = dynamic_cast<WS_DRAW_ITEM_TEXT*>( item ) )
233  {
234  if( text->GetShownText().Matches( wxT( "*${*}*" ) ) )
235  {
237  ercItem->SetErrorMessage( _( "Unresolved text variable in worksheet." ) );
238 
239  SCH_MARKER* marker = new SCH_MARKER( ercItem, text->GetPosition() );
240  screen->Append( marker );
241  }
242  }
243  }
244  }
245 }
246 
247 
249 {
250  wxString msg;
251  int err_count = 0;
252 
253  SCH_SCREENS screens( m_schematic->Root() );
254  std::vector< std::shared_ptr<BUS_ALIAS> > aliases;
255 
256  for( SCH_SCREEN* screen = screens.GetFirst(); screen != NULL; screen = screens.GetNext() )
257  {
258  std::unordered_set< std::shared_ptr<BUS_ALIAS> > screen_aliases = screen->GetBusAliases();
259 
260  for( const std::shared_ptr<BUS_ALIAS>& alias : screen_aliases )
261  {
262  for( const std::shared_ptr<BUS_ALIAS>& test : aliases )
263  {
264  if( alias->GetName() == test->GetName() && alias->Members() != test->Members() )
265  {
266  msg.Printf( _( "Bus alias %s has conflicting definitions on %s and %s" ),
267  alias->GetName(),
268  alias->GetParent()->GetFileName(),
269  test->GetParent()->GetFileName() );
270 
272  ercItem->SetErrorMessage( msg );
273 
274  SCH_MARKER* marker = new SCH_MARKER( ercItem, wxPoint() );
275  test->GetParent()->Append( marker );
276 
277  ++err_count;
278  }
279  }
280  }
281 
282  aliases.insert( aliases.end(), screen_aliases.begin(), screen_aliases.end() );
283  }
284 
285  return err_count;
286 }
287 
288 
290 {
292 
293  int errors = 0;
294  std::map<wxString, LIB_ID> footprints;
296  sheets.GetMultiUnitComponents( refMap, true );
297 
298  for( auto& component : refMap )
299  {
300  auto& refList = component.second;
301 
302  if( refList.GetCount() == 0 )
303  {
304  wxFAIL; // it should not happen
305  continue;
306  }
307 
308  // Reference footprint
309  SCH_COMPONENT* unit = nullptr;
310  wxString unitName;
311  wxString unitFP;
312 
313  for( unsigned i = 0; i < component.second.GetCount(); ++i )
314  {
315  SCH_SHEET_PATH sheetPath = refList.GetItem( i ).GetSheetPath();
316  unitFP = refList.GetItem( i ).GetComp()->GetField( FOOTPRINT )->GetText();
317 
318  if( !unitFP.IsEmpty() )
319  {
320  unit = refList.GetItem( i ).GetComp();
321  unitName = unit->GetRef( &sheetPath, true );
322  break;
323  }
324  }
325 
326  for( unsigned i = 0; i < component.second.GetCount(); ++i )
327  {
328  SCH_REFERENCE& secondRef = refList.GetItem( i );
329  SCH_COMPONENT* secondUnit = secondRef.GetComp();
330  wxString secondName = secondUnit->GetRef( &secondRef.GetSheetPath(), true );
331  const wxString secondFp = secondUnit->GetField( FOOTPRINT )->GetText();
332  wxString msg;
333 
334  if( !secondFp.IsEmpty() && unitFP != secondFp )
335  {
336  msg.Printf( _( "Different footprints assigned to %s and %s" ),
337  unitName, secondName );
338 
340  ercItem->SetErrorMessage( msg );
341  ercItem->SetItems( unit, secondUnit );
342 
343  SCH_MARKER* marker = new SCH_MARKER( ercItem, secondUnit->GetPosition() );
344  secondRef.GetSheetPath().LastScreen()->Append( marker );
345 
346  ++errors;
347  }
348  }
349  }
350 
351  return errors;
352 }
353 
354 
355 void ERC_TESTER::diagnose( NETLIST_OBJECT* aNetItemRef, NETLIST_OBJECT* aNetItemTst, int aMinConn,
356  PIN_ERROR aDiag )
357 {
358  if( aDiag == PIN_ERROR::OK || aMinConn < 1 || aNetItemRef->m_Type != NETLIST_ITEM::PIN )
359  return;
360 
361  ERC_SETTINGS& settings = m_schematic->ErcSettings();
362 
363  SCH_PIN* pin = static_cast<SCH_PIN*>( aNetItemRef->m_Comp );
364 
365  if( aNetItemTst == NULL)
366  {
367  if( aMinConn == NOD ) /* Nothing driving the net. */
368  {
370  {
372  ercItem->SetItems( pin );
373 
374  SCH_MARKER* marker = new SCH_MARKER( ercItem, aNetItemRef->m_Start );
375  aNetItemRef->m_SheetPath.LastScreen()->Append( marker );
376  }
377  return;
378  }
379  }
380 
381  if( aNetItemTst && aNetItemTst->m_Type == NETLIST_ITEM::PIN ) /* Error between 2 pins */
382  {
384  {
385  ERC_ITEM* ercItem = ERC_ITEM::Create(
387  ercItem->SetItems( pin, static_cast<SCH_PIN*>( aNetItemTst->m_Comp ) );
388 
389  SCH_MARKER* marker = new SCH_MARKER( ercItem, aNetItemRef->m_Start );
390  aNetItemRef->m_SheetPath.LastScreen()->Append( marker );
391  }
392  }
393 }
394 
395 
396 void ERC_TESTER::TestOthersItems( NETLIST_OBJECT_LIST* aList, unsigned aNetItemRef,
397  unsigned aNetStart, int* aMinConnexion )
398 {
399  ERC_SETTINGS& settings = m_schematic->ErcSettings();
400 
401  unsigned netItemTst = aNetStart;
403  PIN_ERROR erc = PIN_ERROR::OK;
404 
405  /* Analysis of the table of connections. */
406  ELECTRICAL_PINTYPE ref_elect_type = aList->GetItem( aNetItemRef )->m_ElectricalPinType;
407  int local_minconn = NOC;
408 
409  if( ref_elect_type == ELECTRICAL_PINTYPE::PT_NC )
410  local_minconn = NPI;
411 
412  /* Test pins connected to NetItemRef */
413  for( ; ; netItemTst++ )
414  {
415  if( aNetItemRef == netItemTst )
416  continue;
417 
418  // We examine only a given net. We stop the search if the net changes
419  if( ( netItemTst >= aList->size() ) // End of list
420  || ( aList->GetItemNet( aNetItemRef ) !=
421  aList->GetItemNet( netItemTst ) ) ) // End of net
422  {
423  /* End net code found: minimum connection test. */
424  if( ( *aMinConnexion < NET_NC ) && ( local_minconn < NET_NC ) )
425  {
426  /* Not connected or not driven pin. */
427  bool seterr = true;
428 
429  if( local_minconn == NOC && aList->GetItemType( aNetItemRef ) == NETLIST_ITEM::PIN )
430  {
431  /* This pin is not connected: for multiple part per
432  * package, and duplicated pin,
433  * search for another instance of this pin
434  * this will be flagged only if all instances of this pin
435  * are not connected
436  * TODO test also if instances connected are connected to
437  * the same net
438  */
439  for( unsigned duplicate = 0; duplicate < aList->size(); duplicate++ )
440  {
441  if( aList->GetItemType( duplicate ) != NETLIST_ITEM::PIN )
442  continue;
443 
444  if( duplicate == aNetItemRef )
445  continue;
446 
447  if( aList->GetItem( aNetItemRef )->m_PinNum !=
448  aList->GetItem( duplicate )->m_PinNum )
449  continue;
450 
451  if( ( (SCH_COMPONENT*) aList->GetItem( aNetItemRef )->
452  m_Link )->GetRef( &aList->GetItem( aNetItemRef )-> m_SheetPath ) !=
453  ( (SCH_COMPONENT*) aList->GetItem( duplicate )->m_Link )
454  ->GetRef( &aList->GetItem( duplicate )->m_SheetPath ) )
455  continue;
456 
457  // Same component and same pin. Do dot create error for this pin
458  // if the other pin is connected (i.e. if duplicate net has another
459  // item)
460  if( (duplicate > 0)
461  && ( aList->GetItemNet( duplicate ) ==
462  aList->GetItemNet( duplicate - 1 ) ) )
463  seterr = false;
464 
465  if( (duplicate < aList->size() - 1)
466  && ( aList->GetItemNet( duplicate ) ==
467  aList->GetItemNet( duplicate + 1 ) ) )
468  seterr = false;
469  }
470  }
471 
472  if( seterr )
473  {
474  diagnose( aList->GetItem( aNetItemRef ), nullptr, local_minconn,
476  }
477 
478  *aMinConnexion = DRV; // inhibiting other messages of this
479  // type for the net.
480  }
481  return;
482  }
483 
484  switch( aList->GetItemType( netItemTst ) )
485  {
488  case NETLIST_ITEM::BUS:
490  case NETLIST_ITEM::LABEL:
499  break;
500 
502  local_minconn = std::max( NET_NC, local_minconn );
503  break;
504 
505  case NETLIST_ITEM::PIN:
506  jj = aList->GetItem( netItemTst )->m_ElectricalPinType;
507  local_minconn = std::max( settings.GetPinMinDrive( ref_elect_type, jj ),
508  local_minconn );
509 
510  if( netItemTst <= aNetItemRef )
511  break;
512 
513  if( erc == PIN_ERROR::OK )
514  {
515  erc = settings.GetPinMapValue( ref_elect_type, jj );
516 
517  if( erc != PIN_ERROR::OK )
518  {
519  if( aList->GetConnectionType( netItemTst ) == NET_CONNECTION::UNCONNECTED )
520  {
521  aList->SetConnectionType( netItemTst,
523  }
524 
525  diagnose( aList->GetItem( aNetItemRef ), aList->GetItem( netItemTst ), 1, erc );
526  }
527  }
528 
529  break;
530  }
531  }
532 }
533 
534 
536 {
537  int err_count = 0;
538 
539  for( const SCH_SHEET_PATH& sheet : m_schematic->GetSheets() )
540  {
541  std::map<wxPoint, std::vector<SCH_PIN*>> pinMap;
542 
543  for( SCH_ITEM* item : sheet.LastScreen()->Items().OfType( SCH_COMPONENT_T ) )
544  {
545  SCH_COMPONENT* comp = static_cast<SCH_COMPONENT*>( item );
546 
547  for( SCH_PIN* pin : comp->GetSchPins( &sheet ) )
548  {
549  if( pin->GetLibPin()->GetType() == ELECTRICAL_PINTYPE::PT_NC )
550  pinMap[pin->GetPosition()].emplace_back( pin );
551  }
552  }
553 
554  for( auto& pair : pinMap )
555  {
556  if( pair.second.size() > 1 )
557  {
558  err_count++;
559 
561 
562  ercItem->SetItems( pair.second[0], pair.second[1],
563  pair.second.size() > 2 ? pair.second[2] : nullptr,
564  pair.second.size() > 3 ? pair.second[3] : nullptr );
565  ercItem->SetErrorMessage( _( "Pins with \"no connection\" type are connected" ) );
566 
567  SCH_MARKER* marker = new SCH_MARKER( ercItem, pair.first );
568  sheet.LastScreen()->Append( marker );
569  }
570  }
571  }
572 
573  return err_count;
574 }
575 
576 
577 // this code try to detect similar labels, i.e. labels which are identical
578 // when they are compared using case insensitive coparisons.
579 
580 
581 // A helper struct to compare NETLIST_OBJECT items by sheetpath and label texts
582 // for a std::set<NETLIST_OBJECT*> container
583 // the full text is "sheetpath+label" for local labels and "label" for global labels
585 {
586  bool operator() ( const NETLIST_OBJECT* lab1, const NETLIST_OBJECT* lab2 ) const
587  {
588  wxString str1 = lab1->m_SheetPath.PathAsString() + lab1->m_Label;
589  wxString str2 = lab2->m_SheetPath.PathAsString() + lab2->m_Label;
590 
591  return str1.Cmp( str2 ) < 0;
592  }
593 };
594 
596 {
597  bool operator() ( const NETLIST_OBJECT* lab1, const NETLIST_OBJECT* lab2 ) const
598  {
599  return lab1->m_Label.Cmp( lab2->m_Label ) < 0;
600  }
601 };
602 
604 {
605  bool operator() ( const NETLIST_OBJECT* lab1, const NETLIST_OBJECT* lab2 ) const
606  {
607  return lab1->m_SheetPath.Path() < lab2->m_SheetPath.Path();
608  }
609 };
610 
611 // Helper functions to build the warning messages about Similar Labels:
612 static int countIndenticalLabels( std::vector<NETLIST_OBJECT*>& aList, NETLIST_OBJECT* aRef );
613 static void SimilarLabelsDiagnose( NETLIST_OBJECT* aItemA, NETLIST_OBJECT* aItemB );
614 
615 
617 {
618  // Similar labels which are different when using case sensitive comparisons
619  // but are equal when using case insensitive comparisons
620 
621  // list of all labels (used the better item to build diag messages)
622  std::vector<NETLIST_OBJECT*> fullLabelList;
623  // list of all labels , each label appears only once (used to to detect similar labels)
624  std::set<NETLIST_OBJECT*, compare_labels> uniqueLabelList;
625  wxString msg;
626 
627  // Build a list of differents labels. If inside a given sheet there are
628  // more than one given label, only one label is stored.
629  // not also the sheet labels are not taken in account for 2 reasons:
630  // * they are in the root sheet but they are seen only from the child sheet
631  // * any mismatch between child sheet hierarchical labels and the sheet label
632  // already detected by ERC
633  for( unsigned netItem = 0; netItem < size(); ++netItem )
634  {
635  switch( GetItemType( netItem ) )
636  {
637  case NETLIST_ITEM::LABEL:
644  // add this label in lists
645  uniqueLabelList.insert( GetItem( netItem ) );
646  fullLabelList.push_back( GetItem( netItem ) );
647  break;
648 
651  default:
652  break;
653  }
654  }
655 
656  // build global labels and compare
657  std::set<NETLIST_OBJECT*, compare_label_names> loc_labelList;
658 
659  for( NETLIST_OBJECT* label : uniqueLabelList )
660  {
661  if( label->IsLabelGlobal() )
662  loc_labelList.insert( label );
663  }
664 
665  // compare global labels (same label names appears only once in list)
666  for( auto it = loc_labelList.begin(); it != loc_labelList.end(); ++it )
667  {
668  auto it_aux = it;
669 
670  for( ++it_aux; it_aux != loc_labelList.end(); ++it_aux )
671  {
672  if( (*it)->m_Label.CmpNoCase( (*it_aux)->m_Label ) == 0 )
673  {
674  // Create new marker for ERC.
675  int cntA = countIndenticalLabels( fullLabelList, *it );
676  int cntB = countIndenticalLabels( fullLabelList, *it_aux );
677 
678  if( cntA <= cntB )
679  SimilarLabelsDiagnose( (*it), (*it_aux) );
680  else
681  SimilarLabelsDiagnose( (*it_aux), (*it) );
682  }
683  }
684  }
685 
686  // Build paths list
687  std::set<NETLIST_OBJECT*, compare_paths> pathsList;
688 
689  for( NETLIST_OBJECT* label : uniqueLabelList )
690  pathsList.insert( label );
691 
692  // Examine each label inside a sheet path:
693  for( NETLIST_OBJECT* candidate : pathsList )
694  {
695  loc_labelList.clear();
696 
697  for( NETLIST_OBJECT* uniqueLabel : uniqueLabelList)
698  {
699  if( candidate->m_SheetPath.Path() == uniqueLabel->m_SheetPath.Path() )
700  loc_labelList.insert( uniqueLabel );
701  }
702 
703  // at this point, loc_labelList contains labels of the current sheet path.
704  // Detect similar labels (same label names appears only once in list)
705 
706  for( auto ref_it = loc_labelList.begin(); ref_it != loc_labelList.end(); ++ref_it )
707  {
708  NETLIST_OBJECT* ref_item = *ref_it;
709  auto it_aux = ref_it;
710 
711  for( ++it_aux; it_aux != loc_labelList.end(); ++it_aux )
712  {
713  // global label versus global label was already examined.
714  // here, at least one label must be local
715  if( ref_item->IsLabelGlobal() && ( *it_aux )->IsLabelGlobal() )
716  continue;
717 
718  if( ref_item->m_Label.CmpNoCase( ( *it_aux )->m_Label ) == 0 )
719  {
720  // Create new marker for ERC.
721  int cntA = countIndenticalLabels( fullLabelList, ref_item );
722  int cntB = countIndenticalLabels( fullLabelList, *it_aux );
723 
724  if( cntA <= cntB )
725  SimilarLabelsDiagnose( ref_item, ( *it_aux ) );
726  else
727  SimilarLabelsDiagnose( ( *it_aux ), ref_item );
728  }
729  }
730  }
731  }
732 }
733 
734 
735 // Helper function: count the number of labels identical to aLabel
736 // for global label: global labels in the full project
737 // for local label: all labels in the current sheet
738 static int countIndenticalLabels( std::vector<NETLIST_OBJECT*>& aList, NETLIST_OBJECT* aRef )
739 {
740  int count = 0;
741 
742  if( aRef->IsLabelGlobal() )
743  {
744  for( NETLIST_OBJECT* i : aList )
745  {
746  if( i->IsLabelGlobal() && i->m_Label == aRef->m_Label )
747  count++;
748  }
749  }
750  else
751  {
752  for( NETLIST_OBJECT* i : aList )
753  {
754  if( i->m_Label == aRef->m_Label && i->m_SheetPath.Path() == aRef->m_SheetPath.Path() )
755  count++;
756  }
757  }
758 
759  return count;
760 }
761 
762 
763 // Helper function: creates a marker for similar labels ERC warning
764 static void SimilarLabelsDiagnose( NETLIST_OBJECT* aItemA, NETLIST_OBJECT* aItemB )
765 {
767  ercItem->SetItems( aItemA->m_Comp, aItemB->m_Comp );
768 
769  SCH_MARKER* marker = new SCH_MARKER( ercItem, aItemA->m_Start );
770  aItemA->m_SheetPath.LastScreen()->Append( marker );
771 }
SCH_SHEET_LIST.
static int countIndenticalLabels(std::vector< NETLIST_OBJECT * > &aList, NETLIST_OBJECT *aRef)
SCH_FIELD instances are attached to a component and provide a place for the component's value,...
Definition: sch_field.h:52
int GetPinMinDrive(ELECTRICAL_PINTYPE aFirstType, ELECTRICAL_PINTYPE aSecondType) const
Definition: erc_settings.h:150
#define NOC
Definition: erc_settings.h:79
SCH_SHEET_LIST GetSheets() const
Builds and returns an updated schematic hierarchy TODO: can this be cached?
Definition: schematic.h:92
#define NOD
Definition: erc_settings.h:78
const SCH_SHEET_PATH & GetSheetPath() const
#define NET_NC
Definition: erc_settings.h:77
const wxString CommentERC_V[]
const wxString CommentERC_H[]
void SetItems(EDA_ITEM *aItem, EDA_ITEM *bItem=nullptr, EDA_ITEM *cItem=nullptr, EDA_ITEM *dItem=nullptr)
Definition: rc_item.h:115
WS_DRAW_ITEM_BASE * GetNext()
Definition: ws_draw_item.h:480
KIID_PATH Path() const
Get the sheet path as an KIID_PATH.
SCH_COMPONENT * GetComp() const
EE_TYPE OfType(KICAD_T aType)
Definition: sch_rtree.h:219
void diagnose(NETLIST_OBJECT *NetItemRef, NETLIST_OBJECT *NetItemTst, int MinConnexion, PIN_ERROR Diag)
Performs ERC testing and creates an ERC marker to show the ERC problem for aNetItemRef or between aNe...
void TestOthersItems(NETLIST_OBJECT_LIST *aList, unsigned aNetItemRef, unsigned aNetStart, int *aMinConnexion)
Perform ERC testing for electrical conflicts between NetItemRef and other items (mainly pin) on the s...
void TestTextVars(KIGFX::WS_PROXY_VIEW_ITEM *aWorksheet)
Checks for any unresolved text variable references.
PIN_ERROR
The values a pin-to-pin entry in the pin matrix can take on.
Definition: erc_settings.h:66
wxString PathAsString() const
Function PathAsString the path uses the time stamps which do not changes even when editing sheet para...
SCH_SHEET_PATH m_SheetPath
ELECTRICAL_PINTYPE m_ElectricalPinType
WS_DRAW_ITEM_BASE * GetFirst()
Definition: ws_draw_item.h:470
const wxString ExpandEnvVarSubstitutions(const wxString &aString, PROJECT *aProject)
Replace any environment variable & text variable references with their values.
Definition: common.cpp:574
int GetItemNet(unsigned aIdx) const
Acces to an item net code.
EDA_ITEM * m_Comp
Field Name Module PCB, i.e. "16DIP300".
wxPoint TransformCoordinate(const wxPoint &aPoint) const
Calculate a new coordinate according to the mirror/rotation transform.
Definition: transform.cpp:42
void GetMultiUnitComponents(SCH_MULTI_UNIT_REFERENCE_MAP &aRefList, bool aIncludePowerSymbols=true) const
Function GetMultiUnitComponents adds a SCH_REFERENCE_LIST object to aRefList for each same-reference ...
void GetFields(std::vector< SCH_FIELD * > &aVector, bool aVisibleOnly)
Populates a std::vector with SCH_FIELDs.
bool IsLabelGlobal() const
Function IsLabelGlobal.
NETLIST_OBJECT_LIST is a container holding and owning NETLIST_OBJECTs, which are connected items in a...
std::vector< SCH_FIELD > & GetFields()
Definition: sch_sheet.h:268
bool operator()(const NETLIST_OBJECT *lab1, const NETLIST_OBJECT *lab2) const
int TestConflictingBusAliases()
Checks that there are not conflicting bus alias definitions in the schematic.
int GetSeverity(int aErrorCode) const
bool operator()(const NETLIST_OBJECT *lab1, const NETLIST_OBJECT *lab2) const
void TestforSimilarLabels()
Function TestforSimilarLabels detects labels which are different when using case sensitive comparison...
#define NULL
wxString GetName() const
Definition: sch_sheet.h:280
void BuildWorkSheetGraphicList(const PAGE_INFO &aPageInfo, const TITLE_BLOCK &aTitleBlock)
Function BuildWorkSheetGraphicList is a core function for drawing or plotting the page layout with th...
int TestMultiunitFootprints()
Test if all units of each multiunit component have the same footprint assigned.
TRANSFORM & GetTransform() const
void SetMilsToIUfactor(double aScale)
Function SetMilsToIUfactor Set the scalar to convert pages units (mils) to draw/plot units.
Definition: ws_draw_item.h:436
const TITLE_BLOCK & GetTitleBlock()
Define a sheet pin (label) used in sheets to create hierarchical schematics.
Definition: sch_sheet.h:84
Container for ERC settings.
Definition: erc_settings.h:87
SCH_SHEET_PATH.
const wxString GetRef(const SCH_SHEET_PATH *aSheet, bool aIncludeUnit=false)
Return the reference for the given sheet path.
wxPoint GetPosition() const override
Definition: sch_sheet.h:570
NETLIST_ITEM GetItemType(unsigned aIdx) const
Acces to an item type.
std::map< wxString, SCH_REFERENCE_LIST > SCH_MULTI_UNIT_REFERENCE_MAP
Type SCH_MULTI_UNIT_REFERENCE_MAP is used to create a map of reference designators for multi-unit par...
#define NPI
Types of drive on a net (used for legacy ERC)
Definition: erc_settings.h:75
Sheet symbol placed in a schematic, and is the entry point for a sub schematic.
Definition: sch_sheet.h:216
SCH_FIELD * GetField(int aFieldNdx)
Returns a field in this symbol.
NETLIST_OBJECT * GetItem(unsigned aIdx) const
Acces to an item in list.
static ERC_ITEM * Create(int aErrorCode)
Constructs an ERC_ITEM for the given error code.
Definition: erc_item.cpp:144
SCH_SHEET & Root() const
Definition: schematic.h:97
SCH_SCREEN * LastScreen()
Function LastScreen.
ELECTRICAL_PINTYPE
The component library pin object electrical types used in ERC tests.
Definition: pin_type.h:37
void Append(SCH_ITEM *aItem)
Definition: sch_screen.cpp:132
#define _(s)
Definition: 3d_actions.cpp:33
EE_RTREE & Items()
Definition: sch_screen.h:158
Schematic symbol object.
Definition: sch_component.h:88
PROJECT & Prj() const
Return a reference to the project this schematic is part of.
Definition: schematic.h:77
wxPoint GetPosition() const override
#define IU_PER_MILS
Definition: plotter.cpp:138
PIN_ERROR GetPinMapValue(int aFirstType, int aSecondType) const
Definition: erc_settings.h:125
void SetConnectionType(unsigned aIdx, NET_CONNECTION aFlg=NET_CONNECTION::UNCONNECTED)
Set the item connection type: UNCONNECTED Pin or Label not connected (error) NOCONNECT_SYMBOL_PRESENT...
void SetErrorMessage(const wxString &aMessage)
Definition: rc_item.h:113
NET_CONNECTION GetConnectionType(unsigned aIdx)
ERC_SETTINGS & ErcSettings() const
Definition: schematic.cpp:145
SCHEMATIC * m_schematic
Definition: erc.h:118
not connected (must be left open)
Definition of the NETLIST_OBJECT class.
NETLIST_ITEM m_Type
SCH_ITEM * m_Link
bool operator()(const NETLIST_OBJECT *lab1, const NETLIST_OBJECT *lab2) const
Base class for any item which can be embedded within the SCHEMATIC container class,...
Definition: sch_item.h:187
int TestNoConnectPins()
In KiCad 5 and earlier, you could connect stuff up to pins with NC electrical type.
virtual const wxString & GetText() const
Return the string associated with the text object.
Definition: eda_text.h:127
const PAGE_INFO & GetPageInfo()
SCH_PIN_PTRS GetSchPins(const SCH_SHEET_PATH *aSheet=nullptr) const
Retrieves a list of the SCH_PINs for the given sheet path.
SCH_REFERENCE is used as a helper to define a component's reference designator in a schematic.
Container class that holds multiple SCH_SCREEN objects in a hierarchy.
Definition: sch_screen.h:528
int TestDuplicateSheetNames(bool aCreateMarker)
inside a given sheet, one cannot have sheets with duplicate names (file names can be duplicated).
#define DRV
Definition: erc_settings.h:76
static void SimilarLabelsDiagnose(NETLIST_OBJECT *aItemA, NETLIST_OBJECT *aItemB)