KiCad PCB EDA Suite
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 <common.h> // for ExpandEnvVarSubstitutions
28 #include <erc.h>
29 #include <kicad_string.h>
30 #include <lib_pin.h>
31 #include <sch_edit_frame.h>
32 #include <sch_marker.h>
33 #include <sch_reference_list.h>
34 #include <sch_sheet.h>
35 #include <sch_sheet_pin.h>
36 #include <schematic.h>
39 #include <wx/ffile.h>
40 
41 
42 /* ERC tests :
43  * 1 - conflicts between connected pins ( example: 2 connected outputs )
44  * 2 - minimal connections requirements ( 1 input *must* be connected to an
45  * output, or a passive pin )
46  */
47 
48 /*
49  * Minimal ERC requirements:
50  * All pins *must* be connected (except ELECTRICAL_PINTYPE::PT_NC).
51  * When a pin is not connected in schematic, the user must place a "non
52  * connected" symbol to this pin.
53  * This ensures a forgotten connection will be detected.
54  */
55 
56 // Messages for matrix rows:
57 const wxString CommentERC_H[] =
58 {
59  _( "Input Pin" ),
60  _( "Output Pin" ),
61  _( "Bidirectional Pin" ),
62  _( "Tri-State Pin" ),
63  _( "Passive Pin" ),
64  _( "Free Pin" ),
65  _( "Unspecified Pin" ),
66  _( "Power Input Pin" ),
67  _( "Power Output Pin" ),
68  _( "Open Collector" ),
69  _( "Open Emitter" ),
70  _( "No Connection" )
71 };
72 
73 // Messages for matrix columns
74 const wxString CommentERC_V[] =
75 {
76  _( "Input Pin" ),
77  _( "Output Pin" ),
78  _( "Bidirectional Pin" ),
79  _( "Tri-State Pin" ),
80  _( "Passive Pin" ),
81  _( "Free Pin" ),
82  _( "Unspecified Pin" ),
83  _( "Power Input Pin" ),
84  _( "Power Output Pin" ),
85  _( "Open Collector" ),
86  _( "Open Emitter" ),
87  _( "No Connection" )
88 };
89 
90 
91 // List of pin types that are considered drivers for usual input pins
92 // i.e. pin type = ELECTRICAL_PINTYPE::PT_INPUT, but not PT_POWER_IN
93 // that need only a PT_POWER_OUT pin type to be driven
94 const std::set<ELECTRICAL_PINTYPE> DrivingPinTypes =
95  {
101  };
102 
103 // List of pin types that are considered drivers for power pins
104 // In fact only a ELECTRICAL_PINTYPE::PT_POWER_OUT pin type can drive
105 // power input pins
106 const std::set<ELECTRICAL_PINTYPE> DrivingPowerPinTypes =
107  {
109  };
110 
111 // List of pin types that require a driver elsewhere on the net
112 const std::set<ELECTRICAL_PINTYPE> DrivenPinTypes =
113  {
116  };
117 
118 int ERC_TESTER::TestDuplicateSheetNames( bool aCreateMarker )
119 {
120  SCH_SCREEN* screen;
121  int err_count = 0;
122 
123  SCH_SCREENS screenList( m_schematic->Root() );
124 
125  for( screen = screenList.GetFirst(); screen != nullptr; screen = screenList.GetNext() )
126  {
127  std::vector<SCH_SHEET*> list;
128 
129  for( SCH_ITEM* item : screen->Items().OfType( SCH_SHEET_T ) )
130  list.push_back( static_cast<SCH_SHEET*>( item ) );
131 
132  for( size_t i = 0; i < list.size(); i++ )
133  {
134  SCH_SHEET* sheet = list[i];
135 
136  for( size_t j = i + 1; j < list.size(); j++ )
137  {
138  SCH_SHEET* test_item = list[j];
139 
140  // We have found a second sheet: compare names
141  // we are using case insensitive comparison to avoid mistakes between
142  // similar names like Mysheet and mysheet
143  if( sheet->GetName().CmpNoCase( test_item->GetName() ) == 0 )
144  {
145  if( aCreateMarker )
146  {
147  std::shared_ptr<ERC_ITEM> ercItem = ERC_ITEM::Create( ERCE_DUPLICATE_SHEET_NAME );
148  ercItem->SetItems( sheet, test_item );
149 
150  SCH_MARKER* marker = new SCH_MARKER( ercItem, sheet->GetPosition() );
151  screen->Append( marker );
152  }
153 
154  err_count++;
155  }
156  }
157  }
158  }
159 
160  return err_count;
161 }
162 
163 
165 {
166  DS_DRAW_ITEM_LIST wsItems;
167 
168  auto unresolved = [this]( wxString str )
169  {
170  str = ExpandEnvVarSubstitutions( str, &m_schematic->Prj() );
171  return str.Matches( wxT( "*${*}*" ) );
172  };
173 
174  if( aDrawingSheet )
175  {
176  wsItems.SetMilsToIUfactor( IU_PER_MILS );
177  wsItems.SetPageNumber( "1" );
178  wsItems.SetSheetCount( 1 );
179  wsItems.SetFileName( "dummyFilename" );
180  wsItems.SetSheetName( "dummySheet" );
181  wsItems.SetSheetLayer( "dummyLayer" );
182  wsItems.SetProject( &m_schematic->Prj() );
183  wsItems.BuildDrawItemsList( aDrawingSheet->GetPageInfo(), aDrawingSheet->GetTitleBlock());
184  }
185 
186  SCH_SHEET_PATH savedCurrentSheet = m_schematic->CurrentSheet();
188 
189  for( SCH_SHEET_PATH& sheet : sheets )
190  {
191  m_schematic->SetCurrentSheet( sheet );
192  SCH_SCREEN* screen = sheet.LastScreen();
193 
194  for( SCH_ITEM* item : screen->Items().OfType( SCH_LOCATE_ANY_T ) )
195  {
196  if( item->Type() == SCH_COMPONENT_T )
197  {
198  SCH_COMPONENT* symbol = static_cast<SCH_COMPONENT*>( item );
199 
200  for( SCH_FIELD& field : symbol->GetFields() )
201  {
202  if( unresolved( field.GetShownText() ) )
203  {
204  wxPoint pos = field.GetPosition() - symbol->GetPosition();
205  pos = symbol->GetTransform().TransformCoordinate( pos );
206  pos += symbol->GetPosition();
207 
208  std::shared_ptr<ERC_ITEM> ercItem = ERC_ITEM::Create( ERCE_UNRESOLVED_VARIABLE );
209  ercItem->SetItems( &field );
210 
211  SCH_MARKER* marker = new SCH_MARKER( ercItem, pos );
212  screen->Append( marker );
213  }
214  }
215  }
216  else if( item->Type() == SCH_SHEET_T )
217  {
218  SCH_SHEET* subSheet = static_cast<SCH_SHEET*>( item );
219 
220  for( SCH_FIELD& field : subSheet->GetFields() )
221  {
222  if( unresolved( field.GetShownText() ) )
223  {
224  std::shared_ptr<ERC_ITEM> ercItem = ERC_ITEM::Create( ERCE_UNRESOLVED_VARIABLE );
225  ercItem->SetItems( &field );
226 
227  SCH_MARKER* marker = new SCH_MARKER( ercItem, field.GetPosition() );
228  screen->Append( marker );
229  }
230  }
231 
232  for( SCH_SHEET_PIN* pin : static_cast<SCH_SHEET*>( item )->GetPins() )
233  {
234  if( pin->GetShownText().Matches( wxT( "*${*}*" ) ) )
235  {
236  std::shared_ptr<ERC_ITEM> ercItem = ERC_ITEM::Create( ERCE_UNRESOLVED_VARIABLE );
237  ercItem->SetItems( pin );
238 
239  SCH_MARKER* marker = new SCH_MARKER( ercItem, pin->GetPosition() );
240  screen->Append( marker );
241  }
242  }
243  }
244  else if( SCH_TEXT* text = dynamic_cast<SCH_TEXT*>( item ) )
245  {
246  if( text->GetShownText().Matches( wxT( "*${*}*" ) ) )
247  {
248  std::shared_ptr<ERC_ITEM> ercItem = ERC_ITEM::Create( ERCE_UNRESOLVED_VARIABLE );
249  ercItem->SetItems( text );
250 
251  SCH_MARKER* marker = new SCH_MARKER( ercItem, text->GetPosition() );
252  screen->Append( marker );
253  }
254  }
255  }
256 
257  for( DS_DRAW_ITEM_BASE* item = wsItems.GetFirst(); item; item = wsItems.GetNext() )
258  {
259  if( DS_DRAW_ITEM_TEXT* text = dynamic_cast<DS_DRAW_ITEM_TEXT*>( item ) )
260  {
261  if( text->GetShownText().Matches( wxT( "*${*}*" ) ) )
262  {
263  std::shared_ptr<ERC_ITEM> ercItem = ERC_ITEM::Create( ERCE_UNRESOLVED_VARIABLE );
264  ercItem->SetErrorMessage( _( "Unresolved text variable in drawing sheet." ) );
265 
266  SCH_MARKER* marker = new SCH_MARKER( ercItem, text->GetPosition() );
267  screen->Append( marker );
268  }
269  }
270  }
271  }
272 
273  m_schematic->SetCurrentSheet( savedCurrentSheet );
274 }
275 
276 
278 {
279  wxString msg;
280  int err_count = 0;
281 
282  SCH_SCREENS screens( m_schematic->Root() );
283  std::vector< std::shared_ptr<BUS_ALIAS> > aliases;
284 
285  for( SCH_SCREEN* screen = screens.GetFirst(); screen != NULL; screen = screens.GetNext() )
286  {
287  std::unordered_set< std::shared_ptr<BUS_ALIAS> > screen_aliases = screen->GetBusAliases();
288 
289  for( const std::shared_ptr<BUS_ALIAS>& alias : screen_aliases )
290  {
291  for( const std::shared_ptr<BUS_ALIAS>& test : aliases )
292  {
293  if( alias->GetName() == test->GetName() && alias->Members() != test->Members() )
294  {
295  msg.Printf( _( "Bus alias %s has conflicting definitions on %s and %s" ),
296  alias->GetName(),
297  alias->GetParent()->GetFileName(),
298  test->GetParent()->GetFileName() );
299 
300  std::shared_ptr<ERC_ITEM> ercItem = ERC_ITEM::Create( ERCE_BUS_ALIAS_CONFLICT );
301  ercItem->SetErrorMessage( msg );
302 
303  SCH_MARKER* marker = new SCH_MARKER( ercItem, wxPoint() );
304  test->GetParent()->Append( marker );
305 
306  ++err_count;
307  }
308  }
309  }
310 
311  aliases.insert( aliases.end(), screen_aliases.begin(), screen_aliases.end() );
312  }
313 
314  return err_count;
315 }
316 
317 
319 {
321 
322  int errors = 0;
323  std::map<wxString, LIB_ID> footprints;
325  sheets.GetMultiUnitSymbols( refMap, true );
326 
327  for( std::pair<const wxString, SCH_REFERENCE_LIST>& component : refMap )
328  {
329  SCH_REFERENCE_LIST& refList = component.second;
330 
331  if( refList.GetCount() == 0 )
332  {
333  wxFAIL; // it should not happen
334  continue;
335  }
336 
337  // Reference footprint
338  SCH_COMPONENT* unit = nullptr;
339  wxString unitName;
340  wxString unitFP;
341 
342  for( unsigned i = 0; i < refList.GetCount(); ++i )
343  {
344  SCH_SHEET_PATH sheetPath = refList.GetItem( i ).GetSheetPath();
345  unitFP = refList.GetItem( i ).GetFootprint();
346 
347  if( !unitFP.IsEmpty() )
348  {
349  unit = refList.GetItem( i ).GetSymbol();
350  unitName = unit->GetRef( &sheetPath, true );
351  break;
352  }
353  }
354 
355  for( unsigned i = 0; i < refList.GetCount(); ++i )
356  {
357  SCH_REFERENCE& secondRef = refList.GetItem( i );
358  SCH_COMPONENT* secondUnit = secondRef.GetSymbol();
359  wxString secondName = secondUnit->GetRef( &secondRef.GetSheetPath(), true );
360  const wxString secondFp = secondRef.GetFootprint();
361  wxString msg;
362 
363  if( unit && !secondFp.IsEmpty() && unitFP != secondFp )
364  {
365  msg.Printf( _( "Different footprints assigned to %s and %s" ),
366  unitName, secondName );
367 
368  std::shared_ptr<ERC_ITEM> ercItem = ERC_ITEM::Create( ERCE_DIFFERENT_UNIT_FP );
369  ercItem->SetErrorMessage( msg );
370  ercItem->SetItems( unit, secondUnit );
371 
372  SCH_MARKER* marker = new SCH_MARKER( ercItem, secondUnit->GetPosition() );
373  secondRef.GetSheetPath().LastScreen()->Append( marker );
374 
375  ++errors;
376  }
377  }
378  }
379 
380  return errors;
381 }
382 
383 
385 {
386  int err_count = 0;
387 
388  for( const SCH_SHEET_PATH& sheet : m_schematic->GetSheets() )
389  {
390  std::map<wxPoint, std::vector<SCH_PIN*>> pinMap;
391 
392  for( SCH_ITEM* item : sheet.LastScreen()->Items().OfType( SCH_COMPONENT_T ) )
393  {
394  SCH_COMPONENT* symbol = static_cast<SCH_COMPONENT*>( item );
395 
396  for( SCH_PIN* pin : symbol->GetPins( &sheet ) )
397  {
398  if( pin->GetLibPin()->GetType() == ELECTRICAL_PINTYPE::PT_NC )
399  pinMap[pin->GetPosition()].emplace_back( pin );
400  }
401  }
402 
403  for( auto& pair : pinMap )
404  {
405  if( pair.second.size() > 1 )
406  {
407  err_count++;
408 
409  std::shared_ptr<ERC_ITEM> ercItem = ERC_ITEM::Create( ERCE_NOCONNECT_CONNECTED );
410 
411  ercItem->SetItems( pair.second[0], pair.second[1],
412  pair.second.size() > 2 ? pair.second[2] : nullptr,
413  pair.second.size() > 3 ? pair.second[3] : nullptr );
414  ercItem->SetErrorMessage( _( "Pins with \"no connection\" type are connected" ) );
415 
416  SCH_MARKER* marker = new SCH_MARKER( ercItem, pair.first );
417  sheet.LastScreen()->Append( marker );
418  }
419  }
420  }
421 
422  return err_count;
423 }
424 
425 
427 {
428  ERC_SETTINGS& settings = m_schematic->ErcSettings();
429  const NET_MAP& nets = m_schematic->ConnectionGraph()->GetNetMap();
430 
431  int errors = 0;
432 
433  for( const std::pair<NET_NAME_CODE, std::vector<CONNECTION_SUBGRAPH*>> net : nets )
434  {
435  std::vector<SCH_PIN*> pins;
436  std::unordered_map<EDA_ITEM*, SCH_SCREEN*> pinToScreenMap;
437 
438  for( CONNECTION_SUBGRAPH* subgraph: net.second )
439  {
440  for( EDA_ITEM* item : subgraph->m_items )
441  {
442  if( item->Type() == SCH_PIN_T )
443  {
444  pins.emplace_back( static_cast<SCH_PIN*>( item ) );
445  pinToScreenMap[item] = subgraph->m_sheet.LastScreen();
446  }
447  }
448  }
449 
450  // Single-pin nets are handled elsewhere
451  if( pins.size() < 2 )
452  continue;
453 
454  std::set<std::pair<SCH_PIN*, SCH_PIN*>> tested;
455 
456  SCH_PIN* needsDriver = nullptr;
457  bool hasDriver = false;
458 
459  // We need different drivers for power nets and normal nets.
460  // A power net has at least one pin having the ELECTRICAL_PINTYPE::PT_POWER_IN
461  // and power nets can be driven only by ELECTRICAL_PINTYPE::PT_POWER_OUT pins
462  bool ispowerNet = false;
463 
464  for( SCH_PIN* refPin : pins )
465  {
466  if( refPin->GetType() == ELECTRICAL_PINTYPE::PT_POWER_IN )
467  {
468  ispowerNet = true;
469  break;
470  }
471  }
472 
473  for( SCH_PIN* refPin : pins )
474  {
475  ELECTRICAL_PINTYPE refType = refPin->GetType();
476 
477  if( DrivenPinTypes.count( refType ) )
478  {
479  // needsDriver will be the pin shown in the error report eventually, so try to
480  // upgrade to a "better" pin if possible: something visible and only a power symbol
481  // if this net needs a power driver
482  if( !needsDriver ||
483  ( !needsDriver->IsVisible() && refPin->IsVisible() ) ||
484  ( ispowerNet != needsDriver->IsPowerConnection() &&
485  ispowerNet == refPin->IsPowerConnection() ) )
486  {
487  needsDriver = refPin;
488  }
489  }
490 
491  if( ispowerNet )
492  hasDriver |= ( DrivingPowerPinTypes.count( refType ) != 0 );
493  else
494  hasDriver |= ( DrivingPinTypes.count( refType ) != 0 );
495 
496  for( SCH_PIN* testPin : pins )
497  {
498  if( testPin == refPin )
499  continue;
500 
501  std::pair<SCH_PIN*, SCH_PIN*> pair1 = std::make_pair( refPin, testPin );
502  std::pair<SCH_PIN*, SCH_PIN*> pair2 = std::make_pair( testPin, refPin );
503 
504  if( tested.count( pair1 ) || tested.count( pair2 ) )
505  continue;
506 
507  tested.insert( pair1 );
508  tested.insert( pair2 );
509 
510  ELECTRICAL_PINTYPE testType = testPin->GetType();
511 
512  if( ispowerNet )
513  hasDriver |= ( DrivingPowerPinTypes.count( testType ) != 0 );
514  else
515  hasDriver |= ( DrivingPinTypes.count( testType ) != 0 );
516 
517  PIN_ERROR erc = settings.GetPinMapValue( refType, testType );
518 
519  if( erc != PIN_ERROR::OK )
520  {
521  std::shared_ptr<ERC_ITEM> ercItem =
524  ercItem->SetItems( refPin, testPin );
525  ercItem->SetIsSheetSpecific();
526 
527  ercItem->SetErrorMessage(
528  wxString::Format( _( "Pins of type %s and %s are connected" ),
529  ElectricalPinTypeGetText( refType ),
530  ElectricalPinTypeGetText( testType ) ) );
531 
532  SCH_MARKER* marker =
533  new SCH_MARKER( ercItem, refPin->GetTransformedPosition() );
534  pinToScreenMap[refPin]->Append( marker );
535  errors++;
536  }
537  }
538  }
539 
540  if( needsDriver && !hasDriver )
541  {
542  int err_code = ispowerNet ? ERCE_POWERPIN_NOT_DRIVEN : ERCE_PIN_NOT_DRIVEN;
543  std::shared_ptr<ERC_ITEM> ercItem = ERC_ITEM::Create( err_code );
544 
545  ercItem->SetItems( needsDriver );
546 
547  SCH_MARKER* marker = new SCH_MARKER( ercItem, needsDriver->GetTransformedPosition() );
548  pinToScreenMap[needsDriver]->Append( marker );
549  errors++;
550  }
551  }
552 
553  return errors;
554 }
555 
556 
558 {
559  const NET_MAP& nets = m_schematic->ConnectionGraph()->GetNetMap();
560 
561  int errors = 0;
562 
563  std::unordered_map<wxString, std::pair<wxString, SCH_PIN*>> pinToNetMap;
564 
565  for( const std::pair<NET_NAME_CODE, std::vector<CONNECTION_SUBGRAPH*>> net : nets )
566  {
567  const wxString& netName = net.first.first;
568  std::vector<SCH_PIN*> pins;
569 
570  for( CONNECTION_SUBGRAPH* subgraph : net.second )
571  {
572  for( EDA_ITEM* item : subgraph->m_items )
573  {
574  if( item->Type() == SCH_PIN_T )
575  {
576  SCH_PIN* pin = static_cast<SCH_PIN*>( item );
577 
578  if( !pin->GetLibPin()->GetParent()->IsMulti() )
579  continue;
580 
581  wxString name = pin->GetParentSymbol()->GetRef( &subgraph->m_sheet ) +
582  + ":" + pin->GetNumber();
583 
584  if( !pinToNetMap.count( name ) )
585  {
586  pinToNetMap[name] = std::make_pair( netName, pin );
587  }
588  else if( pinToNetMap[name].first != netName )
589  {
590  std::shared_ptr<ERC_ITEM> ercItem =
592 
593  ercItem->SetErrorMessage( wxString::Format(
594  _( "Pin %s is connected to both %s and %s" ),
595  pin->GetNumber(), netName, pinToNetMap[name].first ) );
596 
597  ercItem->SetItems( pin, pinToNetMap[name].second );
598  ercItem->SetIsSheetSpecific();
599 
600  SCH_MARKER* marker = new SCH_MARKER( ercItem,
601  pin->GetTransformedPosition() );
602  subgraph->m_sheet.LastScreen()->Append( marker );
603  errors += 1;
604  }
605  }
606  }
607  }
608  }
609 
610  return errors;
611 }
612 
613 
615 {
616  const NET_MAP& nets = m_schematic->ConnectionGraph()->GetNetMap();
617 
618  int errors = 0;
619 
620  std::unordered_map<wxString, SCH_TEXT*> labelMap;
621 
622  for( const std::pair<NET_NAME_CODE, std::vector<CONNECTION_SUBGRAPH*>> net : nets )
623  {
624  std::vector<SCH_PIN*> pins;
625 
626  for( CONNECTION_SUBGRAPH* subgraph : net.second )
627  {
628  for( EDA_ITEM* item : subgraph->m_items )
629  {
630  switch( item->Type() )
631  {
632  case SCH_LABEL_T:
633  case SCH_HIER_LABEL_T:
634  case SCH_GLOBAL_LABEL_T:
635  {
636  SCH_TEXT* text = static_cast<SCH_TEXT*>( item );
637 
638  wxString normalized = text->GetShownText().Lower();
639 
640  if( !labelMap.count( normalized ) )
641  {
642  labelMap[normalized] = text;
643  }
644  else if( labelMap.at( normalized )->GetShownText() != text->GetShownText() )
645  {
646  std::shared_ptr<ERC_ITEM> ercItem = ERC_ITEM::Create( ERCE_SIMILAR_LABELS );
647  ercItem->SetItems( text, labelMap.at( normalized ) );
648 
649  SCH_MARKER* marker = new SCH_MARKER( ercItem, text->GetPosition() );
650  subgraph->m_sheet.LastScreen()->Append( marker );
651  errors += 1;
652  }
653 
654  break;
655  }
656 
657  default:
658  break;
659  }
660  }
661  }
662  }
663 
664  return errors;
665 }
666 
667 
669 {
670  wxCHECK( m_schematic, 0 );
671 
672  SYMBOL_LIB_TABLE* libTable = m_schematic->Prj().SchSymbolLibTable();
673  wxString msg;
674  int err_count = 0;
675 
676  SCH_SCREENS screens( m_schematic->Root() );
677 
678  for( SCH_SCREEN* screen = screens.GetFirst(); screen != NULL; screen = screens.GetNext() )
679  {
680  std::vector<SCH_MARKER*> markers;
681 
682  for( SCH_ITEM* item : screen->Items().OfType( SCH_COMPONENT_T ) )
683  {
684  SCH_COMPONENT* symbol = dynamic_cast<SCH_COMPONENT*>( item );
685 
686  wxCHECK2( symbol, continue );
687 
688  LIB_PART* libSymbolInSchematic = symbol->GetPartRef().get();
689 
690  wxCHECK2( libSymbolInSchematic, continue );
691 
692  wxString libName = symbol->GetLibId().GetLibNickname();
693  LIB_TABLE_ROW* libTableRow = libTable->FindRow( libName, true );
694 
695  if( !libTableRow )
696  {
697  std::shared_ptr<ERC_ITEM> ercItem = ERC_ITEM::Create( ERCE_LIB_SYMBOL_ISSUES );
698  ercItem->SetItems( symbol );
699  msg.Printf( _( "The current configuration does not include the library '%s'." ),
700  libName );
701  ercItem->SetErrorMessage( msg );
702 
703  markers.emplace_back( new SCH_MARKER( ercItem, symbol->GetPosition() ) );
704  break;
705  }
706  else if( !libTable->HasLibrary( libName, true ) )
707  {
708  std::shared_ptr<ERC_ITEM> ercItem = ERC_ITEM::Create( ERCE_LIB_SYMBOL_ISSUES );
709  ercItem->SetItems( symbol );
710  msg.Printf( _( "The library '%s' is not enabled in the current configuration." ),
711  libName );
712  ercItem->SetErrorMessage( msg );
713 
714  markers.emplace_back( new SCH_MARKER( ercItem, symbol->GetPosition() ) );
715  break;
716  }
717 
718  wxString symbolName = symbol->GetLibId().GetLibItemName();
719  LIB_PART* libSymbol = SchGetLibPart( symbol->GetLibId(), libTable );
720 
721  if( libSymbol == nullptr )
722  {
723  std::shared_ptr<ERC_ITEM> ercItem = ERC_ITEM::Create( ERCE_LIB_SYMBOL_ISSUES );
724  ercItem->SetItems( symbol );
725  msg.Printf( "Symbol '%s' not found in symbol library '%s'.",
726  symbolName,
727  libName );
728  ercItem->SetErrorMessage( msg );
729 
730  markers.emplace_back( new SCH_MARKER( ercItem, symbol->GetPosition() ) );
731  break;
732  }
733 
734  std::unique_ptr<LIB_PART> flattenedSymbol = libSymbol->Flatten();
735 
736  if( *flattenedSymbol != *libSymbolInSchematic )
737  {
738  std::shared_ptr<ERC_ITEM> ercItem = ERC_ITEM::Create( ERCE_LIB_SYMBOL_ISSUES );
739  ercItem->SetItems( symbol );
740  msg.Printf( "Symbol '%s' has been modified in library '%s'.",
741  symbolName,
742  libName );
743  ercItem->SetErrorMessage( msg );
744 
745  markers.emplace_back( new SCH_MARKER( ercItem, symbol->GetPosition() ) );
746  }
747  }
748 
749  for( SCH_MARKER* marker : markers )
750  {
751  screen->Append( marker );
752  err_count += 1;
753  }
754  }
755 
756  return err_count;
757 }
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:216
const std::set< ELECTRICAL_PINTYPE > DrivenPinTypes
Definition: erc.cpp:112
Instances are attached to a symbol or sheet and provide a place for the symbol's value,...
Definition: sch_field.h:50
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 std::set< ELECTRICAL_PINTYPE > DrivingPowerPinTypes
Definition: erc.cpp:106
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 symbols have been connected to different nets.
Definition: erc.cpp:557
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:129
void TestTextVars(DS_PROXY_VIEW_ITEM *aDrawingSheet)
Check for any unresolved text variable references.
Definition: erc.cpp:164
const SCH_SHEET_PATH & GetSheetPath() const
bool IsVisible() const
Definition: sch_pin.h:103
static std::shared_ptr< ERC_ITEM > Create(int aErrorCode)
Constructs an ERC_ITEM for the given error code.
Definition: erc_item.cpp:189
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
const wxString CommentERC_H[]
Definition: erc.cpp:57
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
const std::set< ELECTRICAL_PINTYPE > DrivingPinTypes
Definition: erc.cpp:94
PIN_ERROR
The values a pin-to-pin entry in the pin matrix can take on.
Definition: erc_settings.h:84
const wxString ExpandEnvVarSubstitutions(const wxString &aString, PROJECT *aProject)
Replace any environment variable & text variable references with their values.
Definition: common.cpp:273
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)
Populate a std::vector with SCH_FIELDs.
Definition: sch_symbol.cpp:701
std::vector< SCH_FIELD > & GetFields()
Definition: sch_sheet.h:88
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.
Definition: erc.cpp:277
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:101
int TestMultiunitFootprints()
Test if all units of each multiunit symbol have the same footprint assigned.
Definition: erc.cpp:318
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
size_t GetCount() const
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_pin.h:65
TRANSFORM & GetTransform()
Definition: sch_symbol.h:231
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:164
std::unique_ptr< LIB_PART > Flatten() const
Return a flattened symbol inheritance to the caller.
Definition: lib_symbol.cpp:334
wxPoint GetPosition() const override
Definition: sch_sheet.h:379
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
Retrieve a list of the SCH_PINs for the given sheet path.
Definition: sch_symbol.cpp:856
SCH_COMPONENT * GetSymbol() const
Sheet symbol placed in a schematic, and is the entry point for a sub schematic.
Definition: sch_sheet.h:54
PROJECT & Prj() const override
Return a reference to the project this schematic is part of.
Definition: schematic.h:75
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
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.
Definition: erc.cpp:668
SCH_SHEET_LIST GetSheets() const override
Builds and returns an updated schematic hierarchy TODO: can this be cached?
Definition: schematic.h:87
void BuildDrawItemsList(const PAGE_INFO &aPageInfo, const TITLE_BLOCK &aTitleBlock)
Drawing or plot the page layout.
SCH_SHEET & Root() const
Definition: schematic.h:92
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:35
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:128
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.
Definition: erc.cpp:426
ELECTRICAL_PINTYPE GetType() const
Definition: sch_pin.cpp:88
EE_RTREE & Items()
Definition: sch_screen.h:103
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:641
#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:124
A base class for most all the KiCad significant classes used in schematics and boards.
Definition: eda_item.h:150
The common library.
void SetSheetCount(int aSheetCount)
Set the value of the count of sheets, for basic inscriptions.
Definition: ds_draw_item.h:468
const wxString CommentERC_V[]
Definition: erc.cpp:74
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.
bool IsPowerConnection() const
Definition: sch_pin.h:123
ERC_SETTINGS & ErcSettings() const
Definition: schematic.cpp:136
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.
Definition: erc.cpp:614
Duplicate sheet names within a given sheet.
Definition: erc_settings.h:40
SCH_SHEET_PATH & CurrentSheet() const override
Definition: schematic.h:119
not connected (must be left open)
const LIB_ID & GetLibId() const
Definition: sch_symbol.h:147
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:197
int TestNoConnectPins()
In KiCad 5 and earlier, you could connect stuff up to pins with NC electrical type.
Definition: erc.cpp:384
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:549
KICAD_T Type() const
Returns the type of object.
Definition: eda_item.h:163
const wxString GetRef(const SCH_SHEET_PATH *aSheet, bool aIncludeUnit=false) const
Return the reference for the given sheet path.
Definition: sch_symbol.cpp:431
int TestDuplicateSheetNames(bool aCreateMarker)
Inside a given sheet, one cannot have sheets with duplicate names (file names can be duplicated).
Definition: erc.cpp:118
wxPoint GetTransformedPosition() const
Definition: sch_pin.cpp:275