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 Wayne Stambaugh <stambaughw@gmail.com>
6  * Copyright (C) 1992-2021 KiCad Developers, see AUTHORS.txt for contributors.
7  *
8  * This program is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU General Public License
10  * as published by the Free Software Foundation; either version 2
11  * of the License, or (at your option) any later version.
12  *
13  * This program is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16  * GNU General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License
19  * along with this program; if not, you may find one here:
20  * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
21  * or you may search the http://www.gnu.org website for the version 2 license,
22  * or you may write to the Free Software Foundation, Inc.,
23  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
24  */
25 
26 #include "connection_graph.h"
27 #include <erc.h>
28 #include <kicad_string.h>
29 #include <lib_pin.h>
30 #include <sch_edit_frame.h>
31 #include <sch_marker.h>
32 #include <sch_reference_list.h>
33 #include <sch_sheet.h>
34 #include <schematic.h>
37 #include <wx/ffile.h>
38 
39 
40 /* ERC tests :
41  * 1 - conflicts between connected pins ( example: 2 connected outputs )
42  * 2 - minimal connections requirements ( 1 input *must* be connected to an
43  * output, or a passive pin )
44  */
45 
46 /*
47  * Minimal ERC requirements:
48  * All pins *must* be connected (except ELECTRICAL_PINTYPE::PT_NC).
49  * When a pin is not connected in schematic, the user must place a "non
50  * connected" symbol to this pin.
51  * This ensures a forgotten connection will be detected.
52  */
53 
54 // Messages for matrix rows:
55 const wxString CommentERC_H[] =
56 {
57  _( "Input Pin" ),
58  _( "Output Pin" ),
59  _( "Bidirectional Pin" ),
60  _( "Tri-State Pin" ),
61  _( "Passive Pin" ),
62  _( "Free Pin" ),
63  _( "Unspecified Pin" ),
64  _( "Power Input Pin" ),
65  _( "Power Output Pin" ),
66  _( "Open Collector" ),
67  _( "Open Emitter" ),
68  _( "No Connection" )
69 };
70 
71 // Messages for matrix columns
72 const wxString CommentERC_V[] =
73 {
74  _( "Input Pin" ),
75  _( "Output Pin" ),
76  _( "Bidirectional Pin" ),
77  _( "Tri-State Pin" ),
78  _( "Passive Pin" ),
79  _( "Free Pin" ),
80  _( "Unspecified Pin" ),
81  _( "Power Input Pin" ),
82  _( "Power Output Pin" ),
83  _( "Open Collector" ),
84  _( "Open Emitter" ),
85  _( "No Connection" )
86 };
87 
88 
89 // List of pin types that are considered drivers for usual input pins
90 // i.e. pin type = ELECTRICAL_PINTYPE::PT_INPUT, but not PT_POWER_IN
91 // that need only a PT_POWER_OUT pin type to be driven
92 const std::set<ELECTRICAL_PINTYPE> DrivingPinTypes =
93  {
99  };
100 
101 // List of pin types that are considered drivers for power pins
102 // In fact only a ELECTRICAL_PINTYPE::PT_POWER_OUT pin type can drive
103 // power input pins
104 const std::set<ELECTRICAL_PINTYPE> DrivingPowerPinTypes =
105  {
107  };
108 
109 // List of pin types that require a driver elsewhere on the net
110 const std::set<ELECTRICAL_PINTYPE> DrivenPinTypes =
111  {
114  };
115 
116 int ERC_TESTER::TestDuplicateSheetNames( bool aCreateMarker )
117 {
118  SCH_SCREEN* screen;
119  int err_count = 0;
120 
121  SCH_SCREENS screenList( m_schematic->Root() );
122 
123  for( screen = screenList.GetFirst(); screen != nullptr; screen = screenList.GetNext() )
124  {
125  std::vector<SCH_SHEET*> list;
126 
127  for( SCH_ITEM* item : screen->Items().OfType( SCH_SHEET_T ) )
128  list.push_back( static_cast<SCH_SHEET*>( item ) );
129 
130  for( size_t i = 0; i < list.size(); i++ )
131  {
132  SCH_SHEET* sheet = list[i];
133 
134  for( size_t j = i + 1; j < list.size(); j++ )
135  {
136  SCH_SHEET* test_item = list[j];
137 
138  // We have found a second sheet: compare names
139  // we are using case insensitive comparison to avoid mistakes between
140  // similar names like Mysheet and mysheet
141  if( sheet->GetName().CmpNoCase( test_item->GetName() ) == 0 )
142  {
143  if( aCreateMarker )
144  {
145  std::shared_ptr<ERC_ITEM> ercItem = ERC_ITEM::Create( ERCE_DUPLICATE_SHEET_NAME );
146  ercItem->SetItems( sheet, test_item );
147 
148  SCH_MARKER* marker = new SCH_MARKER( ercItem, sheet->GetPosition() );
149  screen->Append( marker );
150  }
151 
152  err_count++;
153  }
154  }
155  }
156  }
157 
158  return err_count;
159 }
160 
161 
163 {
164  DS_DRAW_ITEM_LIST wsItems;
165 
166  auto unresolved = [this]( wxString str )
167  {
168  str = ExpandEnvVarSubstitutions( str, &m_schematic->Prj() );
169  return str.Matches( wxT( "*${*}*" ) );
170  };
171 
172  if( aDrawingSheet )
173  {
174  wsItems.SetMilsToIUfactor( IU_PER_MILS );
175  wsItems.SetPageNumber( "1" );
176  wsItems.SetSheetCount( 1 );
177  wsItems.SetFileName( "dummyFilename" );
178  wsItems.SetSheetName( "dummySheet" );
179  wsItems.SetSheetLayer( "dummyLayer" );
180  wsItems.SetProject( &m_schematic->Prj() );
181  wsItems.BuildDrawItemsList( aDrawingSheet->GetPageInfo(), aDrawingSheet->GetTitleBlock());
182  }
183 
184  SCH_SHEET_PATH savedCurrentSheet = m_schematic->CurrentSheet();
186 
187  for( SCH_SHEET_PATH& sheet : sheets )
188  {
189  m_schematic->SetCurrentSheet( sheet );
190  SCH_SCREEN* screen = sheet.LastScreen();
191 
192  for( SCH_ITEM* item : screen->Items().OfType( SCH_LOCATE_ANY_T ) )
193  {
194  if( item->Type() == SCH_COMPONENT_T )
195  {
196  SCH_COMPONENT* component = static_cast<SCH_COMPONENT*>( item );
197 
198  for( SCH_FIELD& field : component->GetFields() )
199  {
200  if( unresolved( field.GetShownText() ) )
201  {
202  wxPoint pos = field.GetPosition() - component->GetPosition();
203  pos = component->GetTransform().TransformCoordinate( pos );
204  pos += component->GetPosition();
205 
206  std::shared_ptr<ERC_ITEM> ercItem = ERC_ITEM::Create( ERCE_UNRESOLVED_VARIABLE );
207  ercItem->SetItems( &field );
208 
209  SCH_MARKER* marker = new SCH_MARKER( ercItem, pos );
210  screen->Append( marker );
211  }
212  }
213  }
214  else if( item->Type() == SCH_SHEET_T )
215  {
216  SCH_SHEET* subSheet = static_cast<SCH_SHEET*>( item );
217 
218  for( SCH_FIELD& field : subSheet->GetFields() )
219  {
220  if( unresolved( field.GetShownText() ) )
221  {
222  std::shared_ptr<ERC_ITEM> ercItem = ERC_ITEM::Create( ERCE_UNRESOLVED_VARIABLE );
223  ercItem->SetItems( &field );
224 
225  SCH_MARKER* marker = new SCH_MARKER( ercItem, field.GetPosition() );
226  screen->Append( marker );
227  }
228  }
229 
230  for( SCH_SHEET_PIN* pin : static_cast<SCH_SHEET*>( item )->GetPins() )
231  {
232  if( pin->GetShownText().Matches( wxT( "*${*}*" ) ) )
233  {
234  std::shared_ptr<ERC_ITEM> ercItem = ERC_ITEM::Create( ERCE_UNRESOLVED_VARIABLE );
235  ercItem->SetItems( pin );
236 
237  SCH_MARKER* marker = new SCH_MARKER( ercItem, pin->GetPosition() );
238  screen->Append( marker );
239  }
240  }
241  }
242  else if( SCH_TEXT* text = dynamic_cast<SCH_TEXT*>( item ) )
243  {
244  if( text->GetShownText().Matches( wxT( "*${*}*" ) ) )
245  {
246  std::shared_ptr<ERC_ITEM> ercItem = ERC_ITEM::Create( ERCE_UNRESOLVED_VARIABLE );
247  ercItem->SetItems( text );
248 
249  SCH_MARKER* marker = new SCH_MARKER( ercItem, text->GetPosition() );
250  screen->Append( marker );
251  }
252  }
253  }
254 
255  for( DS_DRAW_ITEM_BASE* item = wsItems.GetFirst(); item; item = wsItems.GetNext() )
256  {
257  if( DS_DRAW_ITEM_TEXT* text = dynamic_cast<DS_DRAW_ITEM_TEXT*>( item ) )
258  {
259  if( text->GetShownText().Matches( wxT( "*${*}*" ) ) )
260  {
261  std::shared_ptr<ERC_ITEM> ercItem = ERC_ITEM::Create( ERCE_UNRESOLVED_VARIABLE );
262  ercItem->SetErrorMessage( _( "Unresolved text variable in drawing sheet." ) );
263 
264  SCH_MARKER* marker = new SCH_MARKER( ercItem, text->GetPosition() );
265  screen->Append( marker );
266  }
267  }
268  }
269  }
270 
271  m_schematic->SetCurrentSheet( savedCurrentSheet );
272 }
273 
274 
276 {
277  wxString msg;
278  int err_count = 0;
279 
280  SCH_SCREENS screens( m_schematic->Root() );
281  std::vector< std::shared_ptr<BUS_ALIAS> > aliases;
282 
283  for( SCH_SCREEN* screen = screens.GetFirst(); screen != NULL; screen = screens.GetNext() )
284  {
285  std::unordered_set< std::shared_ptr<BUS_ALIAS> > screen_aliases = screen->GetBusAliases();
286 
287  for( const std::shared_ptr<BUS_ALIAS>& alias : screen_aliases )
288  {
289  for( const std::shared_ptr<BUS_ALIAS>& test : aliases )
290  {
291  if( alias->GetName() == test->GetName() && alias->Members() != test->Members() )
292  {
293  msg.Printf( _( "Bus alias %s has conflicting definitions on %s and %s" ),
294  alias->GetName(),
295  alias->GetParent()->GetFileName(),
296  test->GetParent()->GetFileName() );
297 
298  std::shared_ptr<ERC_ITEM> ercItem = ERC_ITEM::Create( ERCE_BUS_ALIAS_CONFLICT );
299  ercItem->SetErrorMessage( msg );
300 
301  SCH_MARKER* marker = new SCH_MARKER( ercItem, wxPoint() );
302  test->GetParent()->Append( marker );
303 
304  ++err_count;
305  }
306  }
307  }
308 
309  aliases.insert( aliases.end(), screen_aliases.begin(), screen_aliases.end() );
310  }
311 
312  return err_count;
313 }
314 
315 
317 {
319 
320  int errors = 0;
321  std::map<wxString, LIB_ID> footprints;
323  sheets.GetMultiUnitSymbols( refMap, true );
324 
325  for( std::pair<const wxString, SCH_REFERENCE_LIST>& component : refMap )
326  {
327  SCH_REFERENCE_LIST& refList = component.second;
328 
329  if( refList.GetCount() == 0 )
330  {
331  wxFAIL; // it should not happen
332  continue;
333  }
334 
335  // Reference footprint
336  SCH_COMPONENT* unit = nullptr;
337  wxString unitName;
338  wxString unitFP;
339 
340  for( unsigned i = 0; i < refList.GetCount(); ++i )
341  {
342  SCH_SHEET_PATH sheetPath = refList.GetItem( i ).GetSheetPath();
343  unitFP = refList.GetItem( i ).GetFootprint();
344 
345  if( !unitFP.IsEmpty() )
346  {
347  unit = refList.GetItem( i ).GetSymbol();
348  unitName = unit->GetRef( &sheetPath, true );
349  break;
350  }
351  }
352 
353  for( unsigned i = 0; i < refList.GetCount(); ++i )
354  {
355  SCH_REFERENCE& secondRef = refList.GetItem( i );
356  SCH_COMPONENT* secondUnit = secondRef.GetSymbol();
357  wxString secondName = secondUnit->GetRef( &secondRef.GetSheetPath(), true );
358  const wxString secondFp = secondRef.GetFootprint();
359  wxString msg;
360 
361  if( unit && !secondFp.IsEmpty() && unitFP != secondFp )
362  {
363  msg.Printf( _( "Different footprints assigned to %s and %s" ),
364  unitName, secondName );
365 
366  std::shared_ptr<ERC_ITEM> ercItem = ERC_ITEM::Create( ERCE_DIFFERENT_UNIT_FP );
367  ercItem->SetErrorMessage( msg );
368  ercItem->SetItems( unit, secondUnit );
369 
370  SCH_MARKER* marker = new SCH_MARKER( ercItem, secondUnit->GetPosition() );
371  secondRef.GetSheetPath().LastScreen()->Append( marker );
372 
373  ++errors;
374  }
375  }
376  }
377 
378  return errors;
379 }
380 
381 
383 {
384  int err_count = 0;
385 
386  for( const SCH_SHEET_PATH& sheet : m_schematic->GetSheets() )
387  {
388  std::map<wxPoint, std::vector<SCH_PIN*>> pinMap;
389 
390  for( SCH_ITEM* item : sheet.LastScreen()->Items().OfType( SCH_COMPONENT_T ) )
391  {
392  SCH_COMPONENT* symbol = static_cast<SCH_COMPONENT*>( item );
393 
394  for( SCH_PIN* pin : symbol->GetPins( &sheet ) )
395  {
396  if( pin->GetLibPin()->GetType() == ELECTRICAL_PINTYPE::PT_NC )
397  pinMap[pin->GetPosition()].emplace_back( pin );
398  }
399  }
400 
401  for( auto& pair : pinMap )
402  {
403  if( pair.second.size() > 1 )
404  {
405  err_count++;
406 
407  std::shared_ptr<ERC_ITEM> ercItem = ERC_ITEM::Create( ERCE_NOCONNECT_CONNECTED );
408 
409  ercItem->SetItems( pair.second[0], pair.second[1],
410  pair.second.size() > 2 ? pair.second[2] : nullptr,
411  pair.second.size() > 3 ? pair.second[3] : nullptr );
412  ercItem->SetErrorMessage( _( "Pins with \"no connection\" type are connected" ) );
413 
414  SCH_MARKER* marker = new SCH_MARKER( ercItem, pair.first );
415  sheet.LastScreen()->Append( marker );
416  }
417  }
418  }
419 
420  return err_count;
421 }
422 
423 
425 {
426  ERC_SETTINGS& settings = m_schematic->ErcSettings();
427  const NET_MAP& nets = m_schematic->ConnectionGraph()->GetNetMap();
428 
429  int errors = 0;
430 
431  for( const std::pair<NET_NAME_CODE, std::vector<CONNECTION_SUBGRAPH*>> net : nets )
432  {
433  std::vector<SCH_PIN*> pins;
434  std::unordered_map<EDA_ITEM*, SCH_SCREEN*> pinToScreenMap;
435 
436  for( CONNECTION_SUBGRAPH* subgraph: net.second )
437  {
438  for( EDA_ITEM* item : subgraph->m_items )
439  {
440  if( item->Type() == SCH_PIN_T )
441  {
442  pins.emplace_back( static_cast<SCH_PIN*>( item ) );
443  pinToScreenMap[item] = subgraph->m_sheet.LastScreen();
444  }
445  }
446  }
447 
448  // Single-pin nets are handled elsewhere
449  if( pins.size() < 2 )
450  continue;
451 
452  std::set<std::pair<SCH_PIN*, SCH_PIN*>> tested;
453 
454  SCH_PIN* needsDriver = nullptr;
455  bool hasDriver = false;
456 
457  // We need different drivers for power nets and normal nets.
458  // A power net has at least one pin having the ELECTRICAL_PINTYPE::PT_POWER_IN
459  // and power nets can be driven only by ELECTRICAL_PINTYPE::PT_POWER_OUT pins
460  bool ispowerNet = false;
461 
462  for( SCH_PIN* refPin : pins )
463  {
464  if( refPin->GetType() == ELECTRICAL_PINTYPE::PT_POWER_IN )
465  {
466  ispowerNet = true;
467  break;
468  }
469  }
470 
471  for( SCH_PIN* refPin : pins )
472  {
473  ELECTRICAL_PINTYPE refType = refPin->GetType();
474 
475  if( DrivenPinTypes.count( refType ) )
476  {
477  // needsDriver will be the pin shown in the error report eventually, so try to
478  // upgrade to a "better" pin if possible: something visible and only a power symbol
479  // if this net needs a power driver
480  if( !needsDriver ||
481  ( !needsDriver->IsVisible() && refPin->IsVisible() ) ||
482  ( ispowerNet != needsDriver->IsPowerConnection() &&
483  ispowerNet == refPin->IsPowerConnection() ) )
484  {
485  needsDriver = refPin;
486  }
487  }
488 
489  if( ispowerNet )
490  hasDriver |= ( DrivingPowerPinTypes.count( refType ) != 0 );
491  else
492  hasDriver |= ( DrivingPinTypes.count( refType ) != 0 );
493 
494  for( SCH_PIN* testPin : pins )
495  {
496  if( testPin == refPin )
497  continue;
498 
499  std::pair<SCH_PIN*, SCH_PIN*> pair1 = std::make_pair( refPin, testPin );
500  std::pair<SCH_PIN*, SCH_PIN*> pair2 = std::make_pair( testPin, refPin );
501 
502  if( tested.count( pair1 ) || tested.count( pair2 ) )
503  continue;
504 
505  tested.insert( pair1 );
506  tested.insert( pair2 );
507 
508  ELECTRICAL_PINTYPE testType = testPin->GetType();
509 
510  if( ispowerNet )
511  hasDriver |= ( DrivingPowerPinTypes.count( testType ) != 0 );
512  else
513  hasDriver |= ( DrivingPinTypes.count( testType ) != 0 );
514 
515  PIN_ERROR erc = settings.GetPinMapValue( refType, testType );
516 
517  if( erc != PIN_ERROR::OK )
518  {
519  std::shared_ptr<ERC_ITEM> ercItem =
522  ercItem->SetItems( refPin, testPin );
523  ercItem->SetIsSheetSpecific();
524 
525  ercItem->SetErrorMessage(
526  wxString::Format( _( "Pins of type %s and %s are connected" ),
527  ElectricalPinTypeGetText( refType ),
528  ElectricalPinTypeGetText( testType ) ) );
529 
530  SCH_MARKER* marker =
531  new SCH_MARKER( ercItem, refPin->GetTransformedPosition() );
532  pinToScreenMap[refPin]->Append( marker );
533  errors++;
534  }
535  }
536  }
537 
538  if( needsDriver && !hasDriver )
539  {
540  int err_code = ispowerNet ? ERCE_POWERPIN_NOT_DRIVEN : ERCE_PIN_NOT_DRIVEN;
541  std::shared_ptr<ERC_ITEM> ercItem = ERC_ITEM::Create( err_code );
542 
543  ercItem->SetItems( needsDriver );
544 
545  SCH_MARKER* marker = new SCH_MARKER( ercItem, needsDriver->GetTransformedPosition() );
546  pinToScreenMap[needsDriver]->Append( marker );
547  errors++;
548  }
549  }
550 
551  return errors;
552 }
553 
554 
556 {
557  const NET_MAP& nets = m_schematic->ConnectionGraph()->GetNetMap();
558 
559  int errors = 0;
560 
561  std::unordered_map<wxString, std::pair<wxString, SCH_PIN*>> pinToNetMap;
562 
563  for( const std::pair<NET_NAME_CODE, std::vector<CONNECTION_SUBGRAPH*>> net : nets )
564  {
565  const wxString& netName = net.first.first;
566  std::vector<SCH_PIN*> pins;
567 
568  for( CONNECTION_SUBGRAPH* subgraph : net.second )
569  {
570  for( EDA_ITEM* item : subgraph->m_items )
571  {
572  if( item->Type() == SCH_PIN_T )
573  {
574  SCH_PIN* pin = static_cast<SCH_PIN*>( item );
575 
576  if( !pin->GetLibPin()->GetParent()->IsMulti() )
577  continue;
578 
579  wxString name = pin->GetParentSymbol()->GetRef( &subgraph->m_sheet ) +
580  + ":" + pin->GetNumber();
581 
582  if( !pinToNetMap.count( name ) )
583  {
584  pinToNetMap[name] = std::make_pair( netName, pin );
585  }
586  else if( pinToNetMap[name].first != netName )
587  {
588  std::shared_ptr<ERC_ITEM> ercItem =
590 
591  ercItem->SetErrorMessage( wxString::Format(
592  _( "Pin %s is connected to both %s and %s" ),
593  pin->GetNumber(), netName, pinToNetMap[name].first ) );
594 
595  ercItem->SetItems( pin, pinToNetMap[name].second );
596  ercItem->SetIsSheetSpecific();
597 
598  SCH_MARKER* marker = new SCH_MARKER( ercItem,
599  pin->GetTransformedPosition() );
600  subgraph->m_sheet.LastScreen()->Append( marker );
601  errors += 1;
602  }
603  }
604  }
605  }
606  }
607 
608  return errors;
609 }
610 
611 
613 {
614  const NET_MAP& nets = m_schematic->ConnectionGraph()->GetNetMap();
615 
616  int errors = 0;
617 
618  std::unordered_map<wxString, SCH_TEXT*> labelMap;
619 
620  for( const std::pair<NET_NAME_CODE, std::vector<CONNECTION_SUBGRAPH*>> net : nets )
621  {
622  std::vector<SCH_PIN*> pins;
623 
624  for( CONNECTION_SUBGRAPH* subgraph : net.second )
625  {
626  for( EDA_ITEM* item : subgraph->m_items )
627  {
628  switch( item->Type() )
629  {
630  case SCH_LABEL_T:
631  case SCH_HIER_LABEL_T:
632  case SCH_GLOBAL_LABEL_T:
633  {
634  SCH_TEXT* text = static_cast<SCH_TEXT*>( item );
635 
636  wxString normalized = text->GetShownText().Lower();
637 
638  if( !labelMap.count( normalized ) )
639  {
640  labelMap[normalized] = text;
641  }
642  else if( labelMap.at( normalized )->GetShownText() != text->GetShownText() )
643  {
644  std::shared_ptr<ERC_ITEM> ercItem = ERC_ITEM::Create( ERCE_SIMILAR_LABELS );
645  ercItem->SetItems( text, labelMap.at( normalized ) );
646 
647  SCH_MARKER* marker = new SCH_MARKER( ercItem, text->GetPosition() );
648  subgraph->m_sheet.LastScreen()->Append( marker );
649  errors += 1;
650  }
651 
652  break;
653  }
654 
655  default:
656  break;
657  }
658  }
659  }
660  }
661 
662  return errors;
663 }
664 
665 
667 {
668  wxCHECK( m_schematic, 0 );
669 
670  SYMBOL_LIB_TABLE* libTable = m_schematic->Prj().SchSymbolLibTable();
671  wxString msg;
672  int err_count = 0;
673 
674  SCH_SCREENS screens( m_schematic->Root() );
675 
676  for( SCH_SCREEN* screen = screens.GetFirst(); screen != NULL; screen = screens.GetNext() )
677  {
678  std::vector<SCH_MARKER*> markers;
679 
680  for( SCH_ITEM* item : screen->Items().OfType( SCH_COMPONENT_T ) )
681  {
682  SCH_COMPONENT* symbol = dynamic_cast<SCH_COMPONENT*>( item );
683 
684  wxCHECK2( symbol, continue );
685 
686  LIB_PART* libSymbolInSchematic = symbol->GetPartRef().get();
687 
688  wxCHECK2( libSymbolInSchematic, continue );
689 
690  wxString libName = symbol->GetLibId().GetLibNickname();
691  LIB_TABLE_ROW* libTableRow = libTable->FindRow( libName, true );
692 
693  if( !libTableRow )
694  {
695  std::shared_ptr<ERC_ITEM> ercItem = ERC_ITEM::Create( ERCE_LIB_SYMBOL_ISSUES );
696  ercItem->SetItems( symbol );
697  msg.Printf( _( "The current configuration does not include the library '%s'." ),
698  libName );
699  ercItem->SetErrorMessage( msg );
700 
701  markers.emplace_back( new SCH_MARKER( ercItem, symbol->GetPosition() ) );
702  break;
703  }
704  else if( !libTable->HasLibrary( libName, true ) )
705  {
706  std::shared_ptr<ERC_ITEM> ercItem = ERC_ITEM::Create( ERCE_LIB_SYMBOL_ISSUES );
707  ercItem->SetItems( symbol );
708  msg.Printf( _( "The library '%s' is not enabled in the current configuration." ),
709  libName );
710  ercItem->SetErrorMessage( msg );
711 
712  markers.emplace_back( new SCH_MARKER( ercItem, symbol->GetPosition() ) );
713  break;
714  }
715 
716  wxString symbolName = symbol->GetLibId().GetLibItemName();
717  LIB_PART* libSymbol = SchGetLibPart( symbol->GetLibId(), libTable );
718 
719  if( libSymbol == nullptr )
720  {
721  std::shared_ptr<ERC_ITEM> ercItem = ERC_ITEM::Create( ERCE_LIB_SYMBOL_ISSUES );
722  ercItem->SetItems( symbol );
723  msg.Printf( "Symbol '%s' not found in symbol library '%s'.",
724  symbolName,
725  libName );
726  ercItem->SetErrorMessage( msg );
727 
728  markers.emplace_back( new SCH_MARKER( ercItem, symbol->GetPosition() ) );
729  break;
730  }
731 
732  std::unique_ptr<LIB_PART> flattenedSymbol = libSymbol->Flatten();
733 
734  if( *flattenedSymbol != *libSymbolInSchematic )
735  {
736  std::shared_ptr<ERC_ITEM> ercItem = ERC_ITEM::Create( ERCE_LIB_SYMBOL_ISSUES );
737  ercItem->SetItems( symbol );
738  msg.Printf( "Symbol '%s' has been modified in library '%s'.",
739  symbolName,
740  libName );
741  ercItem->SetErrorMessage( msg );
742 
743  markers.emplace_back( new SCH_MARKER( ercItem, symbol->GetPosition() ) );
744  }
745  }
746 
747  for( SCH_MARKER* marker : markers )
748  {
749  screen->Append( marker );
750  err_count += 1;
751  }
752  }
753 
754  return err_count;
755 }
power input (GND, VCC for ICs). Must be connected to a power output.
SCH_SHEET_PATH m_sheet
A container for handling SCH_SHEET_PATH objects in a flattened hierarchy.
EE_TYPE OfType(KICAD_T aType) const
Definition: sch_rtree.h:219
SCH_FIELD instances are attached to a component and provide a place for the component's value,...
Definition: sch_field.h:51
LIB_PIN * GetLibPin() const
Definition: sch_pin.h:69
SCH_REFERENCE & GetItem(int aIdx)
const UTF8 & GetLibItemName() const
Definition: lib_id.h:106
bool HasLibrary(const wxString &aNickname, bool aCheckEnabled=false) const
Test for the existence of aNickname in the library table.
const PAGE_INFO & GetPageInfo()
Different units of the same component have different footprints assigned.
Definition: erc_settings.h:51
Hold a record identifying a library accessed by the appropriate plug in object in the LIB_TABLE.
void SetMilsToIUfactor(double aMils2Iu)
Set the scalar to convert pages units (mils) to draw/plot units.
Definition: ds_draw_item.h:442
int TestMultUnitPinConflicts()
Checks if shared pins on multi-unit components have been connected to different nets.
Power input pin connected to some others pins but no power out pin to drive it.
Definition: erc_settings.h:44
void GetMultiUnitSymbols(SCH_MULTI_UNIT_REFERENCE_MAP &aRefList, bool aIncludePowerSymbols=true) const
Add a SCH_REFERENCE_LIST object to aRefList for each same-reference set of multi-unit parts in the li...
CONNECTION_GRAPH * ConnectionGraph() const override
Definition: schematic.h:151
void TestTextVars(DS_PROXY_VIEW_ITEM *aDrawingSheet)
Check for any unresolved text variable references.
const SCH_SHEET_PATH & GetSheetPath() const
bool IsVisible() const
Definition: sch_pin.h:112
const wxString CommentERC_V[]
LIB_PART * GetParent() const
Definition: lib_item.h:149
SCH_COMPONENT * GetParentSymbol() const
Definition: sch_pin.cpp:141
static std::shared_ptr< ERC_ITEM > Create(int aErrorCode)
Constructs an ERC_ITEM for the given error code.
Definition: erc_item.cpp:189
const wxString CommentERC_H[]
wxString ElectricalPinTypeGetText(ELECTRICAL_PINTYPE aType)
Definition: pin_type.cpp:236
void SetFileName(const wxString &aFileName)
Set the filename to draw/plot.
Definition: ds_draw_item.h:415
std::pair< wxString, int > NET_NAME_CODE
Associates a net code with the final name of a net.
pin for passive components: must be connected, and can be connected to any pin
PIN_ERROR
The values a pin-to-pin entry in the pin matrix can take on.
Definition: erc_settings.h:84
wxString GetNumber() const
Definition: sch_pin.h:116
const wxString ExpandEnvVarSubstitutions(const wxString &aString, PROJECT *aProject)
Replace any environment variable & text variable references with their values.
Definition: common.cpp:269
A subgraph is a set of items that are electrically connected on a single sheet.
Library symbol changed from current symbol in schematic or the library symbol link no longer valid.
Definition: erc_settings.h:66
wxPoint TransformCoordinate(const wxPoint &aPoint) const
Calculate a new coordinate according to the mirror/rotation transform.
Definition: transform.cpp:42
Container to create a flattened list of symbols because in a complex hierarchy, a symbol can be used ...
void GetFields(std::vector< SCH_FIELD * > &aVector, bool aVisibleOnly)
Populates a std::vector with SCH_FIELDs.
Definition: sch_symbol.cpp:724
std::vector< SCH_FIELD > & GetFields()
Definition: sch_sheet.h:270
Base class to handle basic graphic items.
Definition: ds_draw_item.h:58
A graphic text.
Definition: ds_draw_item.h:297
int TestConflictingBusAliases()
Check that there are no conflicting bus alias definitions in the schematic.
Pin connected to some others pins but no pin to drive it.
Definition: erc_settings.h:42
DS_DRAW_ITEM_BASE * GetNext()
Definition: ds_draw_item.h:494
#define NULL
wxString GetName() const
Definition: sch_sheet.h:283
int TestMultiunitFootprints()
Test if all units of each multiunit component have the same footprint assigned.
void SetPageNumber(const wxString &aPageNumber)
Set the value of the sheet number.
Definition: ds_draw_item.h:455
std::vector< SCH_ITEM * > m_items
Shared pin in a multi-unit component is connected to more than one net.
Definition: erc_settings.h:53
2 labels are equal for case insensitive comparisons.
Definition: erc_settings.h:50
const NET_MAP & GetNetMap() const
Define a library symbol object.
Definition: lib_symbol.h:93
const wxString GetFootprint() const
const UTF8 & GetLibNickname() const
Return the logical library name portion of a LIB_ID.
Definition: lib_id.h:92
Define a sheet pin (label) used in sheets to create hierarchical schematics.
Definition: sch_sheet.h:85
TRANSFORM & GetTransform()
Definition: sch_symbol.h:272
Container for ERC settings.
Definition: erc_settings.h:105
Handle access to a stack of flattened SCH_SHEET objects by way of a path for creating a flattened sch...
std::unique_ptr< LIB_PART > & GetPartRef()
Definition: sch_symbol.h:205
const std::set< ELECTRICAL_PINTYPE > DrivenPinTypes
std::unique_ptr< LIB_PART > Flatten() const
Return a flattened symbol inheritance to the caller.
Definition: lib_symbol.cpp:334
wxString GetShownText(int aDepth=0) const override
Return the string actually shown after processing of the base text.
Definition: sch_text.cpp:508
wxPoint GetPosition() const override
Definition: sch_text.h:312
wxPoint GetPosition() const override
Definition: sch_sheet.h:572
std::map< wxString, SCH_REFERENCE_LIST > SCH_MULTI_UNIT_REFERENCE_MAP
Container to map reference designators for multi-unit parts.
void SetSheetName(const wxString &aSheetName)
Set the sheet name to draw/plot.
Definition: ds_draw_item.h:423
std::vector< SCH_PIN * > GetPins(const SCH_SHEET_PATH *aSheet=nullptr) const
Retrieves a list of the SCH_PINs for the given sheet path.
Definition: sch_symbol.cpp:863
SCH_COMPONENT * GetSymbol() const
Sheet symbol placed in a schematic, and is the entry point for a sub schematic.
Definition: sch_sheet.h:219
PROJECT & Prj() const override
Return a reference to the project this schematic is part of.
Definition: schematic.h:99
void Format(OUTPUTFORMATTER *out, int aNestLevel, int aCtl, const CPTREE &aTree)
Output a PTREE into s-expression format via an OUTPUTFORMATTER derivative.
Definition: ptree.cpp:200
unsigned GetCount() const
A text variable could not be resolved.
Definition: erc_settings.h:64
A no connect symbol is connected to more than 1 pin.
Definition: erc_settings.h:47
int TestLibSymbolIssues()
Test symbols for changed library symbols and broken symbol library links.
SCH_SHEET_LIST GetSheets() const override
Builds and returns an updated schematic hierarchy TODO: can this be cached?
Definition: schematic.h:111
void BuildDrawItemsList(const PAGE_INFO &aPageInfo, const TITLE_BLOCK &aTitleBlock)
Drawing or plot the page layout.
SCH_SHEET & Root() const
Definition: schematic.h:116
const std::set< ELECTRICAL_PINTYPE > DrivingPinTypes
void SetSheetLayer(const wxString &aSheetLayer)
Set the sheet layer to draw/plot.
Definition: ds_draw_item.h:431
SCH_SCREEN * LastScreen()
const char * name
Definition: DXF_plotter.cpp:59
ELECTRICAL_PINTYPE
The component library pin object electrical types used in ERC tests.
Definition: pin_type.h:34
std::map< NET_NAME_CODE, std::vector< CONNECTION_SUBGRAPH * > > NET_MAP
Associates a NET_CODE_NAME with all the subgraphs in that net.
void Append(SCH_ITEM *aItem)
Definition: sch_screen.cpp:127
const TITLE_BLOCK & GetTitleBlock()
#define _(s)
Definition: 3d_actions.cpp:33
usual pin input: must be connected
int TestPinToPin()
Checks the full netlist against the pin-to-pin connectivity requirements.
ELECTRICAL_PINTYPE GetType() const
Definition: sch_pin.cpp:88
EE_RTREE & Items()
Definition: sch_screen.h:162
void SetProject(const PROJECT *aProject)
Definition: ds_draw_item.h:400
Schematic symbol object.
Definition: sch_symbol.h:78
wxPoint GetPosition() const override
Definition: sch_symbol.h:680
#define IU_PER_MILS
Definition: plotter.cpp:137
Conflicting bus alias definitions across sheets.
Definition: erc_settings.h:55
PIN_ERROR GetPinMapValue(int aFirstType, int aSecondType) const
Definition: erc_settings.h:133
void SetCurrentSheet(const SCH_SHEET_PATH &aPath) override
Definition: schematic.h:146
A base class for most all the KiCad significant classes used in schematics and boards.
Definition: eda_item.h:149
bool IsMulti() const
Definition: lib_symbol.h:495
void SetSheetCount(int aSheetCount)
Set the value of the count of sheets, for basic inscriptions.
Definition: ds_draw_item.h:468
Store the list of graphic items: rect, lines, polygons and texts to draw/plot the title block and fra...
Definition: ds_draw_item.h:376
input or output (like port for a microprocessor)
LIB_PART * SchGetLibPart(const LIB_ID &aLibId, SYMBOL_LIB_TABLE *aLibTable, PART_LIB *aCacheLib, wxWindow *aParent, bool aShowErrorMsg)
Load symbol from symbol library table.
const std::set< ELECTRICAL_PINTYPE > DrivingPowerPinTypes
bool IsPowerConnection() const
Definition: sch_pin.h:132
ERC_SETTINGS & ErcSettings() const
Definition: schematic.cpp:132
SYMBOL_LIB_TABLE_ROW * FindRow(const wxString &aNickName, bool aCheckIfEnabled=false)
Return an SYMBOL_LIB_TABLE_ROW if aNickName is found in this table or in any chained fallBack table f...
SCHEMATIC * m_schematic
Definition: erc.h:133
int TestSimilarLabels()
Checks for labels that differ only in capitalization.
Duplicate sheet names within a given sheet.
Definition: erc_settings.h:40
SCH_SHEET_PATH & CurrentSheet() const override
Definition: schematic.h:141
not connected (must be left open)
const LIB_ID & GetLibId() const
Definition: sch_symbol.h:188
DS_DRAW_ITEM_BASE * GetFirst()
Definition: ds_draw_item.h:484
Base class for any item which can be embedded within the SCHEMATIC container class,...
Definition: sch_item.h:196
int TestNoConnectPins()
In KiCad 5 and earlier, you could connect stuff up to pins with NC electrical type.
output of a regulator: intended to be connected to power input pins
A helper to define a symbol's reference designator in a schematic.
Container class that holds multiple SCH_SCREEN objects in a hierarchy.
Definition: sch_screen.h:536
KICAD_T Type() const
Returns the type of object.
Definition: eda_item.h:162
const wxString GetRef(const SCH_SHEET_PATH *aSheet, bool aIncludeUnit=false) const
Return the reference for the given sheet path.
Definition: sch_symbol.cpp:427
int TestDuplicateSheetNames(bool aCreateMarker)
Inside a given sheet, one cannot have sheets with duplicate names (file names can be duplicated).
wxPoint GetTransformedPosition() const
Returns the pin's position in global coordinates.
Definition: sch_pin.cpp:275