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 <string_utils.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_SYMBOL_T )
197  {
198  SCH_SYMBOL* symbol = static_cast<SCH_SYMBOL*>( 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 =
210  ercItem->SetItems( &field );
211 
212  SCH_MARKER* marker = new SCH_MARKER( ercItem, pos );
213  screen->Append( marker );
214  }
215  }
216  }
217  else if( item->Type() == SCH_SHEET_T )
218  {
219  SCH_SHEET* subSheet = static_cast<SCH_SHEET*>( item );
220 
221  for( SCH_FIELD& field : subSheet->GetFields() )
222  {
223  if( unresolved( field.GetShownText() ) )
224  {
225  std::shared_ptr<ERC_ITEM> ercItem =
227  ercItem->SetItems( &field );
228 
229  SCH_MARKER* marker = new SCH_MARKER( ercItem, field.GetPosition() );
230  screen->Append( marker );
231  }
232  }
233 
234  for( SCH_SHEET_PIN* pin : static_cast<SCH_SHEET*>( item )->GetPins() )
235  {
236  if( pin->GetShownText().Matches( wxT( "*${*}*" ) ) )
237  {
238  std::shared_ptr<ERC_ITEM> ercItem =
240  ercItem->SetItems( pin );
241 
242  SCH_MARKER* marker = new SCH_MARKER( ercItem, pin->GetPosition() );
243  screen->Append( marker );
244  }
245  }
246  }
247  else if( SCH_TEXT* text = dynamic_cast<SCH_TEXT*>( item ) )
248  {
249  if( text->GetShownText().Matches( wxT( "*${*}*" ) ) )
250  {
251  std::shared_ptr<ERC_ITEM> ercItem =
253  ercItem->SetItems( text );
254 
255  SCH_MARKER* marker = new SCH_MARKER( ercItem, text->GetPosition() );
256  screen->Append( marker );
257  }
258  }
259  }
260 
261  for( DS_DRAW_ITEM_BASE* item = wsItems.GetFirst(); item; item = wsItems.GetNext() )
262  {
263  if( DS_DRAW_ITEM_TEXT* text = dynamic_cast<DS_DRAW_ITEM_TEXT*>( item ) )
264  {
265  if( text->GetShownText().Matches( wxT( "*${*}*" ) ) )
266  {
267  std::shared_ptr<ERC_ITEM> ercItem =
269  ercItem->SetErrorMessage( _( "Unresolved text variable in drawing sheet." ) );
270 
271  SCH_MARKER* marker = new SCH_MARKER( ercItem, text->GetPosition() );
272  screen->Append( marker );
273  }
274  }
275  }
276  }
277 
278  m_schematic->SetCurrentSheet( savedCurrentSheet );
279 }
280 
281 
283 {
284  wxString msg;
285  int err_count = 0;
286 
287  SCH_SCREENS screens( m_schematic->Root() );
288  std::vector< std::shared_ptr<BUS_ALIAS> > aliases;
289 
290  for( SCH_SCREEN* screen = screens.GetFirst(); screen != nullptr; screen = screens.GetNext() )
291  {
292  std::unordered_set< std::shared_ptr<BUS_ALIAS> > screen_aliases = screen->GetBusAliases();
293 
294  for( const std::shared_ptr<BUS_ALIAS>& alias : screen_aliases )
295  {
296  for( const std::shared_ptr<BUS_ALIAS>& test : aliases )
297  {
298  if( alias->GetName() == test->GetName() && alias->Members() != test->Members() )
299  {
300  msg.Printf( _( "Bus alias %s has conflicting definitions on %s and %s" ),
301  alias->GetName(),
302  alias->GetParent()->GetFileName(),
303  test->GetParent()->GetFileName() );
304 
305  std::shared_ptr<ERC_ITEM> ercItem = ERC_ITEM::Create( ERCE_BUS_ALIAS_CONFLICT );
306  ercItem->SetErrorMessage( msg );
307 
308  SCH_MARKER* marker = new SCH_MARKER( ercItem, wxPoint() );
309  test->GetParent()->Append( marker );
310 
311  ++err_count;
312  }
313  }
314  }
315 
316  aliases.insert( aliases.end(), screen_aliases.begin(), screen_aliases.end() );
317  }
318 
319  return err_count;
320 }
321 
322 
324 {
326 
327  int errors = 0;
328  std::map<wxString, LIB_ID> footprints;
330  sheets.GetMultiUnitSymbols( refMap, true );
331 
332  for( std::pair<const wxString, SCH_REFERENCE_LIST>& symbol : refMap )
333  {
334  SCH_REFERENCE_LIST& refList = symbol.second;
335 
336  if( refList.GetCount() == 0 )
337  {
338  wxFAIL; // it should not happen
339  continue;
340  }
341 
342  // Reference footprint
343  SCH_SYMBOL* unit = nullptr;
344  wxString unitName;
345  wxString unitFP;
346 
347  for( unsigned i = 0; i < refList.GetCount(); ++i )
348  {
349  SCH_SHEET_PATH sheetPath = refList.GetItem( i ).GetSheetPath();
350  unitFP = refList.GetItem( i ).GetFootprint();
351 
352  if( !unitFP.IsEmpty() )
353  {
354  unit = refList.GetItem( i ).GetSymbol();
355  unitName = unit->GetRef( &sheetPath, true );
356  break;
357  }
358  }
359 
360  for( unsigned i = 0; i < refList.GetCount(); ++i )
361  {
362  SCH_REFERENCE& secondRef = refList.GetItem( i );
363  SCH_SYMBOL* secondUnit = secondRef.GetSymbol();
364  wxString secondName = secondUnit->GetRef( &secondRef.GetSheetPath(), true );
365  const wxString secondFp = secondRef.GetFootprint();
366  wxString msg;
367 
368  if( unit && !secondFp.IsEmpty() && unitFP != secondFp )
369  {
370  msg.Printf( _( "Different footprints assigned to %s and %s" ),
371  unitName, secondName );
372 
373  std::shared_ptr<ERC_ITEM> ercItem = ERC_ITEM::Create( ERCE_DIFFERENT_UNIT_FP );
374  ercItem->SetErrorMessage( msg );
375  ercItem->SetItems( unit, secondUnit );
376 
377  SCH_MARKER* marker = new SCH_MARKER( ercItem, secondUnit->GetPosition() );
378  secondRef.GetSheetPath().LastScreen()->Append( marker );
379 
380  ++errors;
381  }
382  }
383  }
384 
385  return errors;
386 }
387 
388 
390 {
391  int err_count = 0;
392 
393  for( const SCH_SHEET_PATH& sheet : m_schematic->GetSheets() )
394  {
395  std::map<wxPoint, std::vector<SCH_PIN*>> pinMap;
396 
397  for( SCH_ITEM* item : sheet.LastScreen()->Items().OfType( SCH_SYMBOL_T ) )
398  {
399  SCH_SYMBOL* symbol = static_cast<SCH_SYMBOL*>( item );
400 
401  for( SCH_PIN* pin : symbol->GetPins( &sheet ) )
402  {
403  if( pin->GetLibPin()->GetType() == ELECTRICAL_PINTYPE::PT_NC )
404  pinMap[pin->GetPosition()].emplace_back( pin );
405  }
406  }
407 
408  for( auto& pair : pinMap )
409  {
410  if( pair.second.size() > 1 )
411  {
412  err_count++;
413 
414  std::shared_ptr<ERC_ITEM> ercItem = ERC_ITEM::Create( ERCE_NOCONNECT_CONNECTED );
415 
416  ercItem->SetItems( pair.second[0], pair.second[1],
417  pair.second.size() > 2 ? pair.second[2] : nullptr,
418  pair.second.size() > 3 ? pair.second[3] : nullptr );
419  ercItem->SetErrorMessage( _( "Pins with \"no connection\" type are connected" ) );
420 
421  SCH_MARKER* marker = new SCH_MARKER( ercItem, pair.first );
422  sheet.LastScreen()->Append( marker );
423  }
424  }
425  }
426 
427  return err_count;
428 }
429 
430 
432 {
433  ERC_SETTINGS& settings = m_schematic->ErcSettings();
434  const NET_MAP& nets = m_schematic->ConnectionGraph()->GetNetMap();
435 
436  int errors = 0;
437 
438  for( const std::pair<NET_NAME_CODE, std::vector<CONNECTION_SUBGRAPH*>> net : nets )
439  {
440  std::vector<SCH_PIN*> pins;
441  std::unordered_map<EDA_ITEM*, SCH_SCREEN*> pinToScreenMap;
442 
443  for( CONNECTION_SUBGRAPH* subgraph: net.second )
444  {
445  for( EDA_ITEM* item : subgraph->m_items )
446  {
447  if( item->Type() == SCH_PIN_T )
448  {
449  pins.emplace_back( static_cast<SCH_PIN*>( item ) );
450  pinToScreenMap[item] = subgraph->m_sheet.LastScreen();
451  }
452  }
453  }
454 
455  // Single-pin nets are handled elsewhere
456  if( pins.size() < 2 )
457  continue;
458 
459  std::set<std::pair<SCH_PIN*, SCH_PIN*>> tested;
460 
461  SCH_PIN* needsDriver = nullptr;
462  bool hasDriver = false;
463 
464  // We need different drivers for power nets and normal nets.
465  // A power net has at least one pin having the ELECTRICAL_PINTYPE::PT_POWER_IN
466  // and power nets can be driven only by ELECTRICAL_PINTYPE::PT_POWER_OUT pins
467  bool ispowerNet = false;
468 
469  for( SCH_PIN* refPin : pins )
470  {
471  if( refPin->GetType() == ELECTRICAL_PINTYPE::PT_POWER_IN )
472  {
473  ispowerNet = true;
474  break;
475  }
476  }
477 
478  for( SCH_PIN* refPin : pins )
479  {
480  ELECTRICAL_PINTYPE refType = refPin->GetType();
481 
482  if( DrivenPinTypes.count( refType ) )
483  {
484  // needsDriver will be the pin shown in the error report eventually, so try to
485  // upgrade to a "better" pin if possible: something visible and only a power symbol
486  // if this net needs a power driver
487  if( !needsDriver ||
488  ( !needsDriver->IsVisible() && refPin->IsVisible() ) ||
489  ( ispowerNet != ( needsDriver->GetType() == ELECTRICAL_PINTYPE::PT_POWER_IN ) &&
490  ispowerNet == ( refType == ELECTRICAL_PINTYPE::PT_POWER_IN ) ) )
491  {
492  needsDriver = refPin;
493  }
494  }
495 
496  if( ispowerNet )
497  hasDriver |= ( DrivingPowerPinTypes.count( refType ) != 0 );
498  else
499  hasDriver |= ( DrivingPinTypes.count( refType ) != 0 );
500 
501  for( SCH_PIN* testPin : pins )
502  {
503  if( testPin == refPin )
504  continue;
505 
506  std::pair<SCH_PIN*, SCH_PIN*> pair1 = std::make_pair( refPin, testPin );
507  std::pair<SCH_PIN*, SCH_PIN*> pair2 = std::make_pair( testPin, refPin );
508 
509  if( tested.count( pair1 ) || tested.count( pair2 ) )
510  continue;
511 
512  tested.insert( pair1 );
513  tested.insert( pair2 );
514 
515  ELECTRICAL_PINTYPE testType = testPin->GetType();
516 
517  if( ispowerNet )
518  hasDriver |= ( DrivingPowerPinTypes.count( testType ) != 0 );
519  else
520  hasDriver |= ( DrivingPinTypes.count( testType ) != 0 );
521 
522  PIN_ERROR erc = settings.GetPinMapValue( refType, testType );
523 
524  if( erc != PIN_ERROR::OK )
525  {
526  std::shared_ptr<ERC_ITEM> ercItem =
529  ercItem->SetItems( refPin, testPin );
530  ercItem->SetIsSheetSpecific();
531 
532  ercItem->SetErrorMessage(
533  wxString::Format( _( "Pins of type %s and %s are connected" ),
534  ElectricalPinTypeGetText( refType ),
535  ElectricalPinTypeGetText( testType ) ) );
536 
537  SCH_MARKER* marker =
538  new SCH_MARKER( ercItem, refPin->GetTransformedPosition() );
539  pinToScreenMap[refPin]->Append( marker );
540  errors++;
541  }
542  }
543  }
544 
545  if( needsDriver && !hasDriver )
546  {
547  int err_code = ispowerNet ? ERCE_POWERPIN_NOT_DRIVEN : ERCE_PIN_NOT_DRIVEN;
548  std::shared_ptr<ERC_ITEM> ercItem = ERC_ITEM::Create( err_code );
549 
550  ercItem->SetItems( needsDriver );
551 
552  SCH_MARKER* marker = new SCH_MARKER( ercItem, needsDriver->GetTransformedPosition() );
553  pinToScreenMap[needsDriver]->Append( marker );
554  errors++;
555  }
556  }
557 
558  return errors;
559 }
560 
561 
563 {
564  const NET_MAP& nets = m_schematic->ConnectionGraph()->GetNetMap();
565 
566  int errors = 0;
567 
568  std::unordered_map<wxString, std::pair<wxString, SCH_PIN*>> pinToNetMap;
569 
570  for( const std::pair<NET_NAME_CODE, std::vector<CONNECTION_SUBGRAPH*>> net : nets )
571  {
572  const wxString& netName = net.first.first;
573  std::vector<SCH_PIN*> pins;
574 
575  for( CONNECTION_SUBGRAPH* subgraph : net.second )
576  {
577  for( EDA_ITEM* item : subgraph->m_items )
578  {
579  if( item->Type() == SCH_PIN_T )
580  {
581  SCH_PIN* pin = static_cast<SCH_PIN*>( item );
582 
583  if( !pin->GetLibPin()->GetParent()->IsMulti() )
584  continue;
585 
586  wxString name = pin->GetParentSymbol()->GetRef( &subgraph->m_sheet ) +
587  + ":" + pin->GetShownNumber();
588 
589  if( !pinToNetMap.count( name ) )
590  {
591  pinToNetMap[name] = std::make_pair( netName, pin );
592  }
593  else if( pinToNetMap[name].first != netName )
594  {
595  std::shared_ptr<ERC_ITEM> ercItem =
597 
598  ercItem->SetErrorMessage( wxString::Format(
599  _( "Pin %s is connected to both %s and %s" ),
600  pin->GetShownNumber(),
601  netName,
602  pinToNetMap[name].first ) );
603 
604  ercItem->SetItems( pin, pinToNetMap[name].second );
605  ercItem->SetIsSheetSpecific();
606 
607  SCH_MARKER* marker = new SCH_MARKER( ercItem,
608  pin->GetTransformedPosition() );
609  subgraph->m_sheet.LastScreen()->Append( marker );
610  errors += 1;
611  }
612  }
613  }
614  }
615  }
616 
617  return errors;
618 }
619 
620 
622 {
623  const NET_MAP& nets = m_schematic->ConnectionGraph()->GetNetMap();
624 
625  int errors = 0;
626 
627  std::unordered_map<wxString, SCH_TEXT*> labelMap;
628 
629  for( const std::pair<NET_NAME_CODE, std::vector<CONNECTION_SUBGRAPH*>> net : nets )
630  {
631  std::vector<SCH_PIN*> pins;
632 
633  for( CONNECTION_SUBGRAPH* subgraph : net.second )
634  {
635  for( EDA_ITEM* item : subgraph->m_items )
636  {
637  switch( item->Type() )
638  {
639  case SCH_LABEL_T:
640  case SCH_HIER_LABEL_T:
641  case SCH_GLOBAL_LABEL_T:
642  {
643  SCH_TEXT* text = static_cast<SCH_TEXT*>( item );
644 
645  wxString normalized = text->GetShownText().Lower();
646 
647  if( !labelMap.count( normalized ) )
648  {
649  labelMap[normalized] = text;
650  }
651  else if( labelMap.at( normalized )->GetShownText() != text->GetShownText() )
652  {
653  std::shared_ptr<ERC_ITEM> ercItem = ERC_ITEM::Create( ERCE_SIMILAR_LABELS );
654  ercItem->SetItems( text, labelMap.at( normalized ) );
655 
656  SCH_MARKER* marker = new SCH_MARKER( ercItem, text->GetPosition() );
657  subgraph->m_sheet.LastScreen()->Append( marker );
658  errors += 1;
659  }
660 
661  break;
662  }
663 
664  default:
665  break;
666  }
667  }
668  }
669  }
670 
671  return errors;
672 }
673 
674 
676 {
677  wxCHECK( m_schematic, 0 );
678 
679  SYMBOL_LIB_TABLE* libTable = m_schematic->Prj().SchSymbolLibTable();
680  wxString msg;
681  int err_count = 0;
682 
683  SCH_SCREENS screens( m_schematic->Root() );
684 
685  for( SCH_SCREEN* screen = screens.GetFirst(); screen != nullptr; screen = screens.GetNext() )
686  {
687  std::vector<SCH_MARKER*> markers;
688 
689  for( SCH_ITEM* item : screen->Items().OfType( SCH_SYMBOL_T ) )
690  {
691  SCH_SYMBOL* symbol = dynamic_cast<SCH_SYMBOL*>( item );
692 
693  wxCHECK2( symbol, continue );
694 
695  LIB_SYMBOL* libSymbolInSchematic = symbol->GetLibSymbolRef().get();
696 
697  wxCHECK2( libSymbolInSchematic, continue );
698 
699  wxString libName = symbol->GetLibId().GetLibNickname();
700  LIB_TABLE_ROW* libTableRow = libTable->FindRow( libName, true );
701 
702  if( !libTableRow )
703  {
704  std::shared_ptr<ERC_ITEM> ercItem = ERC_ITEM::Create( ERCE_LIB_SYMBOL_ISSUES );
705  ercItem->SetItems( symbol );
706  msg.Printf( _( "The current configuration does not include the library '%s'." ),
707  UnescapeString( libName ) );
708  ercItem->SetErrorMessage( msg );
709 
710  markers.emplace_back( new SCH_MARKER( ercItem, symbol->GetPosition() ) );
711  continue;
712  }
713  else if( !libTable->HasLibrary( libName, true ) )
714  {
715  std::shared_ptr<ERC_ITEM> ercItem = ERC_ITEM::Create( ERCE_LIB_SYMBOL_ISSUES );
716  ercItem->SetItems( symbol );
717  msg.Printf( _( "The library '%s' is not enabled in the current configuration." ),
718  UnescapeString( libName ) );
719  ercItem->SetErrorMessage( msg );
720 
721  markers.emplace_back( new SCH_MARKER( ercItem, symbol->GetPosition() ) );
722  continue;
723  }
724 
725  wxString symbolName = symbol->GetLibId().GetLibItemName();
726  LIB_SYMBOL* libSymbol = SchGetLibSymbol( symbol->GetLibId(), libTable );
727 
728  if( libSymbol == nullptr )
729  {
730  std::shared_ptr<ERC_ITEM> ercItem = ERC_ITEM::Create( ERCE_LIB_SYMBOL_ISSUES );
731  ercItem->SetItems( symbol );
732  msg.Printf( "Symbol '%s' not found in symbol library '%s'.",
733  UnescapeString( symbolName ),
734  UnescapeString( libName ) );
735  ercItem->SetErrorMessage( msg );
736 
737  markers.emplace_back( new SCH_MARKER( ercItem, symbol->GetPosition() ) );
738  continue;
739  }
740 
741  std::unique_ptr<LIB_SYMBOL> flattenedSymbol = libSymbol->Flatten();
742 
743  if( *flattenedSymbol != *libSymbolInSchematic )
744  {
745  std::shared_ptr<ERC_ITEM> ercItem = ERC_ITEM::Create( ERCE_LIB_SYMBOL_ISSUES );
746  ercItem->SetItems( symbol );
747  msg.Printf( "Symbol '%s' has been modified in library '%s'.",
748  UnescapeString( symbolName ),
749  UnescapeString( libName ) );
750  ercItem->SetErrorMessage( msg );
751 
752  markers.emplace_back( new SCH_MARKER( ercItem, symbol->GetPosition() ) );
753  }
754  }
755 
756  for( SCH_MARKER* marker : markers )
757  {
758  screen->Append( marker );
759  err_count += 1;
760  }
761  }
762 
763  return err_count;
764 }
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:49
SCH_REFERENCE & GetItem(int aIdx)
const UTF8 & GetLibItemName() const
Definition: lib_id.h:104
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 symbol 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:562
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:131
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:104
static std::shared_ptr< ERC_ITEM > Create(int aErrorCode)
Constructs an ERC_ITEM for the given error code.
Definition: erc_item.cpp:194
wxString ElectricalPinTypeGetText(ELECTRICAL_PINTYPE aType)
Definition: pin_type.cpp:237
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 symbols: must be connected, and can be connected to any pin
void GetFields(std::vector< SCH_FIELD * > &aVector, bool aVisibleOnly)
Populate a std::vector with SCH_FIELDs.
Definition: sch_symbol.cpp:711
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:85
SCH_SYMBOL * GetSymbol() const
const wxString GetRef(const SCH_SHEET_PATH *aSheet, bool aIncludeUnit=false) const
Return the reference for the given sheet path.
Definition: sch_symbol.cpp:441
const wxString ExpandEnvVarSubstitutions(const wxString &aString, PROJECT *aProject)
Replace any environment variable & text variable references with their values.
Definition: common.cpp:267
LIB_SYMBOL * SchGetLibSymbol(const LIB_ID &aLibId, SYMBOL_LIB_TABLE *aLibTable, SYMBOL_LIB *aCacheLib, wxWindow *aParent, bool aShowErrorMsg)
Load symbol from symbol library table.
Define a library symbol object.
Definition: lib_symbol.h:96
TRANSFORM & GetTransform()
Definition: sch_symbol.h:231
A subgraph is a set of items that are electrically connected on a single sheet.
std::unique_ptr< LIB_SYMBOL > Flatten() const
Return a flattened symbol inheritance to the caller.
Definition: lib_symbol.cpp:331
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
std::unique_ptr< LIB_SYMBOL > & GetLibSymbolRef()
Definition: sch_symbol.h:164
Container to create a flattened list of symbols because in a complex hierarchy, a symbol can be used ...
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:282
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
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:323
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 symbol 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
size_t GetCount() const
const wxString GetFootprint() const
#define _(s)
const UTF8 & GetLibNickname() const
Return the logical library name portion of a LIB_ID.
Definition: lib_id.h:90
Define a sheet pin (label) used in sheets to create hierarchical schematics.
Definition: sch_sheet_pin.h:65
Container for ERC settings.
Definition: erc_settings.h:106
Handle access to a stack of flattened SCH_SHEET objects by way of a path for creating a flattened sch...
wxPoint GetPosition() const override
Definition: sch_sheet.h:380
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
wxString UnescapeString(const wxString &aSource)
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:675
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 drawing sheet.
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
Schematic symbol object.
Definition: sch_symbol.h:78
SCH_SCREEN * LastScreen()
const char * name
Definition: DXF_plotter.cpp:56
ELECTRICAL_PINTYPE
The symbol 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:146
const TITLE_BLOCK & GetTitleBlock()
usual pin input: must be connected
int TestPinToPin()
Checks the full netlist against the pin-to-pin connectivity requirements.
Definition: erc.cpp:431
ELECTRICAL_PINTYPE GetType() const
Definition: sch_pin.cpp:113
EE_RTREE & Items()
Gets the full RTree, usually for iterating.
Definition: sch_screen.h:110
void SetProject(const PROJECT *aProject)
Definition: ds_draw_item.h:400
#define IU_PER_MILS
Definition: plotter.cpp:136
Conflicting bus alias definitions across sheets.
Definition: erc_settings.h:55
PIN_ERROR GetPinMapValue(int aFirstType, int aSecondType) const
Definition: erc_settings.h:134
void SetCurrentSheet(const SCH_SHEET_PATH &aPath) override
Definition: schematic.h:126
wxPoint GetPosition() const override
Definition: sch_symbol.h:644
A base class for most all the KiCad significant classes used in schematics and boards.
Definition: eda_item.h:100
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)
ERC_SETTINGS & ErcSettings() const
Definition: schematic.cpp:174
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:621
Duplicate sheet names within a given sheet.
Definition: erc_settings.h:40
SCH_SHEET_PATH & CurrentSheet() const override
Definition: schematic.h:121
not connected (must be left open)
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:182
int TestNoConnectPins()
In KiCad 5 and earlier, you could connect stuff up to pins with NC electrical type.
Definition: erc.cpp:389
output of a regulator: intended to be connected to power input pins
A helper to define a symbol's reference designator in a schematic.
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:866
Container class that holds multiple SCH_SCREEN objects in a hierarchy.
Definition: sch_screen.h:568
KICAD_T Type() const
Returns the type of object.
Definition: eda_item.h:113
const LIB_ID & GetLibId() const
Definition: sch_symbol.h:147
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:284