KiCad PCB EDA Suite
ERC_TESTER Class Reference

#include <erc.h>

Public Member Functions

 ERC_TESTER (SCHEMATIC *aSchematic)
 
void TestOthersItems (NETLIST_OBJECT_LIST *aList, unsigned aNetItemRef, unsigned aNetStart, int *aMinConnexion)
 Perform ERC testing for electrical conflicts between NetItemRef and other items (mainly pin) on the same net. More...
 
int TestDuplicateSheetNames (bool aCreateMarker)
 Inside a given sheet, one cannot have sheets with duplicate names (file names can be duplicated). More...
 
void TestTextVars (DS_PROXY_VIEW_ITEM *aDrawingSheet)
 Check for any unresolved text variable references. More...
 
int TestConflictingBusAliases ()
 Check that there are no conflicting bus alias definitions in the schematic. More...
 
int TestMultiunitFootprints ()
 Test if all units of each multiunit symbol have the same footprint assigned. More...
 
int TestNoConnectPins ()
 In KiCad 5 and earlier, you could connect stuff up to pins with NC electrical type. More...
 
int TestPinToPin ()
 Checks the full netlist against the pin-to-pin connectivity requirements. More...
 
int TestMultUnitPinConflicts ()
 Checks if shared pins on multi-unit symbols have been connected to different nets. More...
 
int TestSimilarLabels ()
 Checks for labels that differ only in capitalization. More...
 
int TestLibSymbolIssues ()
 Test symbols for changed library symbols and broken symbol library links. More...
 
int TestOffGridEndpoints (int aGridSize)
 Test pins and wire ends for being off grid. More...
 
int TestSimModelIssues ()
 Test SPICE models for various issues. More...
 
int TestMissingUnits ()
 Test for uninstantiated units of multi unit symbols. More...
 

Private Attributes

SCHEMATICm_schematic
 

Detailed Description

Definition at line 47 of file erc.h.

Constructor & Destructor Documentation

◆ ERC_TESTER()

ERC_TESTER::ERC_TESTER ( SCHEMATIC aSchematic)
inline

Definition at line 51 of file erc.h.

51 :
52 m_schematic( aSchematic )
53 {
54 }
SCHEMATIC * m_schematic
Definition: erc.h:148

Member Function Documentation

◆ TestConflictingBusAliases()

int ERC_TESTER::TestConflictingBusAliases ( )

Check that there are no conflicting bus alias definitions in the schematic.

(for example, two hierarchical sub-sheets contain different definitions for the same bus alias)

Returns
the error count

Definition at line 300 of file erc.cpp.

301{
302 wxString msg;
303 int err_count = 0;
304
305 SCH_SCREENS screens( m_schematic->Root() );
306 std::vector< std::shared_ptr<BUS_ALIAS> > aliases;
307
308 for( SCH_SCREEN* screen = screens.GetFirst(); screen != nullptr; screen = screens.GetNext() )
309 {
310 const std::set< std::shared_ptr<BUS_ALIAS> > screen_aliases = screen->GetBusAliases();
311
312 for( const std::shared_ptr<BUS_ALIAS>& alias : screen_aliases )
313 {
314 std::vector<wxString> aliasMembers = alias->Members();
315 std::sort( aliasMembers.begin(), aliasMembers.end() );
316
317 for( const std::shared_ptr<BUS_ALIAS>& test : aliases )
318 {
319 std::vector<wxString> testMembers = test->Members();
320 std::sort( testMembers.begin(), testMembers.end() );
321
322 if( alias->GetName() == test->GetName() && aliasMembers != testMembers )
323 {
324 msg.Printf( _( "Bus alias %s has conflicting definitions on %s and %s" ),
325 alias->GetName(),
326 alias->GetParent()->GetFileName(),
327 test->GetParent()->GetFileName() );
328
329 std::shared_ptr<ERC_ITEM> ercItem = ERC_ITEM::Create( ERCE_BUS_ALIAS_CONFLICT );
330 ercItem->SetErrorMessage( msg );
331
332 SCH_MARKER* marker = new SCH_MARKER( ercItem, wxPoint() );
333 test->GetParent()->Append( marker );
334
335 ++err_count;
336 }
337 }
338 }
339
340 aliases.insert( aliases.end(), screen_aliases.begin(), screen_aliases.end() );
341 }
342
343 return err_count;
344}
static std::shared_ptr< ERC_ITEM > Create(int aErrorCode)
Constructs an ERC_ITEM for the given error code.
Definition: erc_item.cpp:232
SCH_SHEET & Root() const
Definition: schematic.h:91
Container class that holds multiple SCH_SCREEN objects in a hierarchy.
Definition: sch_screen.h:638
#define _(s)
@ ERCE_BUS_ALIAS_CONFLICT
Conflicting bus alias definitions across sheets.
Definition: erc_settings.h:60

References _, ERC_ITEM::Create(), ERCE_BUS_ALIAS_CONFLICT, SCH_SCREENS::GetFirst(), SCH_SCREENS::GetNext(), m_schematic, and SCHEMATIC::Root().

Referenced by BOOST_FIXTURE_TEST_CASE(), and DIALOG_ERC::testErc().

◆ TestDuplicateSheetNames()

int ERC_TESTER::TestDuplicateSheetNames ( bool  aCreateMarker)

Inside a given sheet, one cannot have sheets with duplicate names (file names can be duplicated).

Returns
the error count
Parameters
aCreateMarkertrue = create error markers in schematic, false = calculate error count only

Definition at line 125 of file erc.cpp.

126{
127 SCH_SCREEN* screen;
128 int err_count = 0;
129
130 SCH_SCREENS screenList( m_schematic->Root() );
131
132 for( screen = screenList.GetFirst(); screen != nullptr; screen = screenList.GetNext() )
133 {
134 std::vector<SCH_SHEET*> list;
135
136 for( SCH_ITEM* item : screen->Items().OfType( SCH_SHEET_T ) )
137 list.push_back( static_cast<SCH_SHEET*>( item ) );
138
139 for( size_t i = 0; i < list.size(); i++ )
140 {
141 SCH_SHEET* sheet = list[i];
142
143 for( size_t j = i + 1; j < list.size(); j++ )
144 {
145 SCH_SHEET* test_item = list[j];
146
147 // We have found a second sheet: compare names
148 // we are using case insensitive comparison to avoid mistakes between
149 // similar names like Mysheet and mysheet
150 if( sheet->GetName().CmpNoCase( test_item->GetName() ) == 0 )
151 {
152 if( aCreateMarker )
153 {
154 std::shared_ptr<ERC_ITEM> ercItem = ERC_ITEM::Create( ERCE_DUPLICATE_SHEET_NAME );
155 ercItem->SetItems( sheet, test_item );
156
157 SCH_MARKER* marker = new SCH_MARKER( ercItem, sheet->GetPosition() );
158 screen->Append( marker );
159 }
160
161 err_count++;
162 }
163 }
164 }
165 }
166
167 return err_count;
168}
EE_TYPE OfType(KICAD_T aType) const
Definition: sch_rtree.h:238
Base class for any item which can be embedded within the SCHEMATIC container class,...
Definition: sch_item.h:147
EE_RTREE & Items()
Gets the full RTree, usually for iterating.
Definition: sch_screen.h:109
void Append(SCH_ITEM *aItem)
Definition: sch_screen.cpp:145
Sheet symbol placed in a schematic, and is the entry point for a sub schematic.
Definition: sch_sheet.h:57
wxString GetName() const
Definition: sch_sheet.h:103
VECTOR2I GetPosition() const override
Definition: sch_sheet.h:368
@ ERCE_DUPLICATE_SHEET_NAME
Duplicate sheet names within a given sheet.
Definition: erc_settings.h:40
@ SCH_SHEET_T
Definition: typeinfo.h:158

References SCH_SCREEN::Append(), ERC_ITEM::Create(), ERCE_DUPLICATE_SHEET_NAME, SCH_SCREENS::GetFirst(), SCH_SHEET::GetName(), SCH_SCREENS::GetNext(), SCH_SHEET::GetPosition(), SCH_SCREEN::Items(), m_schematic, EE_RTREE::OfType(), SCHEMATIC::Root(), and SCH_SHEET_T.

Referenced by DIALOG_ERC::testErc().

◆ TestLibSymbolIssues()

int ERC_TESTER::TestLibSymbolIssues ( )

Test symbols for changed library symbols and broken symbol library links.

Returns
the number of issues found

Definition at line 857 of file erc.cpp.

858{
859 wxCHECK( m_schematic, 0 );
860
861 SYMBOL_LIB_TABLE* libTable = m_schematic->Prj().SchSymbolLibTable();
862 wxString msg;
863 int err_count = 0;
864
865 SCH_SCREENS screens( m_schematic->Root() );
866
867 for( SCH_SCREEN* screen = screens.GetFirst(); screen != nullptr; screen = screens.GetNext() )
868 {
869 std::vector<SCH_MARKER*> markers;
870
871 for( SCH_ITEM* item : screen->Items().OfType( SCH_SYMBOL_T ) )
872 {
873 SCH_SYMBOL* symbol = static_cast<SCH_SYMBOL*>( item );
874 LIB_SYMBOL* libSymbolInSchematic = symbol->GetLibSymbolRef().get();
875
876 wxCHECK2( libSymbolInSchematic, continue );
877
878 wxString libName = symbol->GetLibId().GetLibNickname();
879 LIB_TABLE_ROW* libTableRow = libTable->FindRow( libName, true );
880
881 if( !libTableRow )
882 {
883 std::shared_ptr<ERC_ITEM> ercItem = ERC_ITEM::Create( ERCE_LIB_SYMBOL_ISSUES );
884 ercItem->SetItems( symbol );
885 msg.Printf( _( "The current configuration does not include the library '%s'" ),
886 UnescapeString( libName ) );
887 ercItem->SetErrorMessage( msg );
888
889 markers.emplace_back( new SCH_MARKER( ercItem, symbol->GetPosition() ) );
890 continue;
891 }
892 else if( !libTable->HasLibrary( libName, true ) )
893 {
894 std::shared_ptr<ERC_ITEM> ercItem = ERC_ITEM::Create( ERCE_LIB_SYMBOL_ISSUES );
895 ercItem->SetItems( symbol );
896 msg.Printf( _( "The library '%s' is not enabled in the current configuration" ),
897 UnescapeString( libName ) );
898 ercItem->SetErrorMessage( msg );
899
900 markers.emplace_back( new SCH_MARKER( ercItem, symbol->GetPosition() ) );
901 continue;
902 }
903
904 wxString symbolName = symbol->GetLibId().GetLibItemName();
905 LIB_SYMBOL* libSymbol = SchGetLibSymbol( symbol->GetLibId(), libTable );
906
907 if( libSymbol == nullptr )
908 {
909 std::shared_ptr<ERC_ITEM> ercItem = ERC_ITEM::Create( ERCE_LIB_SYMBOL_ISSUES );
910 ercItem->SetItems( symbol );
911 msg.Printf( _( "Symbol '%s' not found in symbol library '%s'" ),
912 UnescapeString( symbolName ),
913 UnescapeString( libName ) );
914 ercItem->SetErrorMessage( msg );
915
916 markers.emplace_back( new SCH_MARKER( ercItem, symbol->GetPosition() ) );
917 continue;
918 }
919
920 std::unique_ptr<LIB_SYMBOL> flattenedSymbol = libSymbol->Flatten();
921 constexpr int flags = LIB_ITEM::COMPARE_FLAGS::EQUALITY | LIB_ITEM::COMPARE_FLAGS::ERC;
922
923 if( flattenedSymbol->Compare( *libSymbolInSchematic, flags ) != 0 )
924 {
925 std::shared_ptr<ERC_ITEM> ercItem = ERC_ITEM::Create( ERCE_LIB_SYMBOL_ISSUES );
926 ercItem->SetItems( symbol );
927 msg.Printf( _( "Symbol '%s' has been modified in library '%s'" ),
928 UnescapeString( symbolName ),
929 UnescapeString( libName ) );
930 ercItem->SetErrorMessage( msg );
931
932 markers.emplace_back( new SCH_MARKER( ercItem, symbol->GetPosition() ) );
933 }
934 }
935
936 for( SCH_MARKER* marker : markers )
937 {
938 screen->Append( marker );
939 err_count += 1;
940 }
941 }
942
943 return err_count;
944}
const UTF8 & GetLibItemName() const
Definition: lib_id.h:102
const UTF8 & GetLibNickname() const
Return the logical library name portion of a LIB_ID.
Definition: lib_id.h:87
Define a library symbol object.
Definition: lib_symbol.h:99
std::unique_ptr< LIB_SYMBOL > Flatten() const
Return a flattened symbol inheritance to the caller.
Definition: lib_symbol.cpp:456
Hold a record identifying a library accessed by the appropriate plug in object in the LIB_TABLE.
bool HasLibrary(const wxString &aNickname, bool aCheckEnabled=false) const
Test for the existence of aNickname in the library table.
PROJECT & Prj() const override
Return a reference to the project this schematic is part of.
Definition: schematic.h:76
Schematic symbol object.
Definition: sch_symbol.h:81
VECTOR2I GetPosition() const override
Definition: sch_symbol.h:712
const LIB_ID & GetLibId() const
Definition: sch_symbol.h:175
std::unique_ptr< LIB_SYMBOL > & GetLibSymbolRef()
Definition: sch_symbol.h:192
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...
@ ERCE_LIB_SYMBOL_ISSUES
Library symbol changed from current symbol in schematic or the library symbol link no longer valid.
Definition: erc_settings.h:73
LIB_SYMBOL * SchGetLibSymbol(const LIB_ID &aLibId, SYMBOL_LIB_TABLE *aLibTable, SYMBOL_LIB *aCacheLib, wxWindow *aParent, bool aShowErrorMsg)
Load symbol from symbol library table.
wxString UnescapeString(const wxString &aSource)
@ SCH_SYMBOL_T
Definition: typeinfo.h:156

References _, ERC_ITEM::Create(), ERCE_LIB_SYMBOL_ISSUES, SYMBOL_LIB_TABLE::FindRow(), LIB_SYMBOL::Flatten(), SCH_SCREENS::GetFirst(), SCH_SYMBOL::GetLibId(), LIB_ID::GetLibItemName(), LIB_ID::GetLibNickname(), SCH_SYMBOL::GetLibSymbolRef(), SCH_SCREENS::GetNext(), SCH_SYMBOL::GetPosition(), LIB_TABLE::HasLibrary(), m_schematic, SCHEMATIC::Prj(), SCHEMATIC::Root(), SCH_SYMBOL_T, SchGetLibSymbol(), and UnescapeString().

Referenced by DIALOG_ERC::testErc().

◆ TestMissingUnits()

int ERC_TESTER::TestMissingUnits ( )

Test for uninstantiated units of multi unit symbols.

Definition at line 412 of file erc.cpp.

413{
414 ERC_SETTINGS& settings = m_schematic->ErcSettings();
416
417 int errors = 0;
419 sheets.GetMultiUnitSymbols( refMap, true );
420
421 for( std::pair<const wxString, SCH_REFERENCE_LIST>& symbol : refMap )
422 {
423 SCH_REFERENCE_LIST& refList = symbol.second;
424
425 wxCHECK2( refList.GetCount(), continue );
426
427 // Reference unit
428 SCH_REFERENCE& base_ref = refList.GetItem( 0 );
429 SCH_SYMBOL* unit = base_ref.GetSymbol();
430 LIB_SYMBOL* libSymbol = base_ref.GetLibPart();
431
432 if( static_cast<ssize_t>( refList.GetCount() ) == libSymbol->GetUnitCount() )
433 continue;
434
435 std::set<int> lib_units;
436 std::set<int> instance_units;
437 std::set<int> missing_units;
438
439 auto report_missing = [&]( std::set<int>& aMissingUnits, wxString aErrorMsg, int aErrorCode )
440 {
441 wxString msg;
442 wxString missing_pin_units = wxT( "[ " );
443 int ii = 0;
444
445 for( int missing_unit : aMissingUnits )
446 {
447 if( ii++ == 3 )
448 {
449 missing_pin_units += wxT( "....." );
450 break;
451 }
452
453 missing_pin_units += libSymbol->GetUnitDisplayName( missing_unit ) + ", " ;
454 }
455
456 missing_pin_units.Truncate( missing_pin_units.length() - 2 );
457 missing_pin_units += wxT( " ]" );
458
459 msg.Printf( aErrorMsg, symbol.first, missing_pin_units );
460
461 std::shared_ptr<ERC_ITEM> ercItem = ERC_ITEM::Create( aErrorCode );
462 ercItem->SetErrorMessage( msg );
463 ercItem->SetItems( unit );
464
465 SCH_MARKER* marker = new SCH_MARKER( ercItem, unit->GetPosition() );
466 base_ref.GetSheetPath().LastScreen()->Append( marker );
467
468 ++errors;
469 };
470
471 for( int ii = 1; ii <= libSymbol->GetUnitCount(); ++ii )
472 lib_units.insert( lib_units.end(), ii );
473
474 for( size_t ii = 0; ii < refList.GetCount(); ++ii )
475 instance_units.insert( instance_units.end(), refList.GetItem( ii ).GetUnit() );
476
477 std::set_difference( lib_units.begin(), lib_units.end(),
478 instance_units.begin(), instance_units.end(),
479 std::inserter( missing_units, missing_units.begin() ) );
480
481 if( !missing_units.empty() && settings.IsTestEnabled( ERCE_MISSING_UNIT ) )
482 {
483 report_missing( missing_units, _( "Symbol %s has unplaced units %s" ),
485 }
486
487 std::set<int> missing_power;
488 std::set<int> missing_input;
489 std::set<int> missing_bidi;
490
491 for( int missing_unit : missing_units )
492 {
493 LIB_PINS pins;
494 int convert = 0;
495
496 for( size_t ii = 0; ii < refList.GetCount(); ++ii )
497 {
498 if( refList.GetItem( ii ).GetUnit() == missing_unit )
499 {
500 convert = refList.GetItem( ii ).GetSymbol()->GetConvert();
501 break;
502 }
503 }
504
505 libSymbol->GetPins( pins, missing_unit, convert );
506
507 for( auto pin : pins )
508 {
509 switch( pin->GetType() )
510 {
512 missing_power.insert( missing_unit );
513 break;
514
516 missing_bidi.insert( missing_unit );
517 break;
518
520 missing_input.insert( missing_unit );
521 break;
522
523 default:
524 break;
525 }
526 }
527 }
528
529 if( !missing_power.empty() && settings.IsTestEnabled( ERCE_MISSING_POWER_INPUT_PIN ) )
530 {
531 report_missing( missing_power, _( "Symbol %s has input power pins in units %s that are not placed." ),
533 }
534
535 if( !missing_input.empty() && settings.IsTestEnabled( ERCE_MISSING_INPUT_PIN ) )
536 {
537 report_missing( missing_input, _( "Symbol %s has input pins in units %s that are not placed." ),
539 }
540
541 if( !missing_bidi.empty() && settings.IsTestEnabled( ERCE_MISSING_BIDI_PIN ) )
542 {
543 report_missing( missing_bidi, _( "Symbol %s has bidirectional pins in units %s that are not placed." ),
545 }
546 }
547
548 return errors;
549}
Container for ERC settings.
Definition: erc_settings.h:114
bool IsTestEnabled(int aErrorCode) const
Definition: erc_settings.h:130
wxString GetUnitDisplayName(int aUnit) override
Return the user-defined display name for aUnit for symbols with units.
Definition: lib_symbol.cpp:399
int GetUnitCount() const override
For items with units, return the number of units.
void GetPins(LIB_PINS &aList, int aUnit=0, int aConvert=0) const
Return a list of pin object pointers from the draw item list.
Definition: lib_symbol.cpp:834
SCH_SHEET_LIST GetSheets() const override
Builds and returns an updated schematic hierarchy TODO: can this be cached?
Definition: schematic.h:86
ERC_SETTINGS & ErcSettings() const
Definition: schematic.cpp:185
Container to create a flattened list of symbols because in a complex hierarchy, a symbol can be used ...
size_t GetCount() const
SCH_REFERENCE & GetItem(int aIdx)
A helper to define a symbol's reference designator in a schematic.
const SCH_SHEET_PATH & GetSheetPath() const
SCH_SYMBOL * GetSymbol() const
LIB_SYMBOL * GetLibPart() const
int GetUnit() const
A container for handling SCH_SHEET_PATH objects in a flattened hierarchy.
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...
SCH_SCREEN * LastScreen()
int GetConvert() const
Definition: sch_symbol.h:270
@ ERCE_MISSING_POWER_INPUT_PIN
Symbol has power input pins that are not placed on the schematic.
Definition: erc_settings.h:54
@ ERCE_MISSING_INPUT_PIN
Symbol has input pins that are not placed.
Definition: erc_settings.h:55
@ ERCE_MISSING_UNIT
Symbol has units that are not placed on the schematic.
Definition: erc_settings.h:57
@ ERCE_MISSING_BIDI_PIN
Symbol has bi-directional pins that are not placed.
Definition: erc_settings.h:56
std::vector< LIB_PIN * > LIB_PINS
Helper for defining a list of pin object pointers.
Definition: lib_item.h:54
@ PT_INPUT
usual pin input: must be connected
@ PT_BIDI
input or output (like port for a microprocessor)
@ PT_POWER_IN
power input (GND, VCC for ICs). Must be connected to a power output.
std::map< wxString, SCH_REFERENCE_LIST > SCH_MULTI_UNIT_REFERENCE_MAP
Container to map reference designators for multi-unit parts.

References _, SCH_SCREEN::Append(), convert, ERC_ITEM::Create(), ERCE_MISSING_BIDI_PIN, ERCE_MISSING_INPUT_PIN, ERCE_MISSING_POWER_INPUT_PIN, ERCE_MISSING_UNIT, SCHEMATIC::ErcSettings(), SCH_SYMBOL::GetConvert(), SCH_REFERENCE_LIST::GetCount(), SCH_REFERENCE_LIST::GetItem(), SCH_REFERENCE::GetLibPart(), SCH_SHEET_LIST::GetMultiUnitSymbols(), LIB_SYMBOL::GetPins(), SCH_SYMBOL::GetPosition(), SCH_REFERENCE::GetSheetPath(), SCHEMATIC::GetSheets(), SCH_REFERENCE::GetSymbol(), SCH_REFERENCE::GetUnit(), LIB_SYMBOL::GetUnitCount(), LIB_SYMBOL::GetUnitDisplayName(), ERC_SETTINGS::IsTestEnabled(), SCH_SHEET_PATH::LastScreen(), m_schematic, pin, PT_BIDI, PT_INPUT, and PT_POWER_IN.

Referenced by DIALOG_ERC::testErc().

◆ TestMultiunitFootprints()

int ERC_TESTER::TestMultiunitFootprints ( )

Test if all units of each multiunit symbol have the same footprint assigned.

Returns
The error count.

Definition at line 347 of file erc.cpp.

348{
350
351 int errors = 0;
353 sheets.GetMultiUnitSymbols( refMap, true );
354
355 for( std::pair<const wxString, SCH_REFERENCE_LIST>& symbol : refMap )
356 {
357 SCH_REFERENCE_LIST& refList = symbol.second;
358
359 if( refList.GetCount() == 0 )
360 {
361 wxFAIL; // it should not happen
362 continue;
363 }
364
365 // Reference footprint
366 SCH_SYMBOL* unit = nullptr;
367 wxString unitName;
368 wxString unitFP;
369
370 for( unsigned i = 0; i < refList.GetCount(); ++i )
371 {
372 SCH_SHEET_PATH sheetPath = refList.GetItem( i ).GetSheetPath();
373 unitFP = refList.GetItem( i ).GetFootprint();
374
375 if( !unitFP.IsEmpty() )
376 {
377 unit = refList.GetItem( i ).GetSymbol();
378 unitName = unit->GetRef( &sheetPath, true );
379 break;
380 }
381 }
382
383 for( unsigned i = 0; i < refList.GetCount(); ++i )
384 {
385 SCH_REFERENCE& secondRef = refList.GetItem( i );
386 SCH_SYMBOL* secondUnit = secondRef.GetSymbol();
387 wxString secondName = secondUnit->GetRef( &secondRef.GetSheetPath(), true );
388 const wxString secondFp = secondRef.GetFootprint();
389 wxString msg;
390
391 if( unit && !secondFp.IsEmpty() && unitFP != secondFp )
392 {
393 msg.Printf( _( "Different footprints assigned to %s and %s" ),
394 unitName, secondName );
395
396 std::shared_ptr<ERC_ITEM> ercItem = ERC_ITEM::Create( ERCE_DIFFERENT_UNIT_FP );
397 ercItem->SetErrorMessage( msg );
398 ercItem->SetItems( unit, secondUnit );
399
400 SCH_MARKER* marker = new SCH_MARKER( ercItem, secondUnit->GetPosition() );
401 secondRef.GetSheetPath().LastScreen()->Append( marker );
402
403 ++errors;
404 }
405 }
406 }
407
408 return errors;
409}
const wxString GetFootprint() const
Handle access to a stack of flattened SCH_SHEET objects by way of a path for creating a flattened sch...
const wxString GetRef(const SCH_SHEET_PATH *aSheet, bool aIncludeUnit=false) const
Return the reference for the given sheet path.
Definition: sch_symbol.cpp:652
@ ERCE_DIFFERENT_UNIT_FP
Different units of the same symbol have different footprints assigned.
Definition: erc_settings.h:52

References _, SCH_SCREEN::Append(), ERC_ITEM::Create(), ERCE_DIFFERENT_UNIT_FP, SCH_REFERENCE_LIST::GetCount(), SCH_REFERENCE::GetFootprint(), SCH_REFERENCE_LIST::GetItem(), SCH_SHEET_LIST::GetMultiUnitSymbols(), SCH_SYMBOL::GetPosition(), SCH_SYMBOL::GetRef(), SCH_REFERENCE::GetSheetPath(), SCHEMATIC::GetSheets(), SCH_REFERENCE::GetSymbol(), SCH_SHEET_PATH::LastScreen(), and m_schematic.

Referenced by BOOST_FIXTURE_TEST_CASE(), and DIALOG_ERC::testErc().

◆ TestMultUnitPinConflicts()

int ERC_TESTER::TestMultUnitPinConflicts ( )

Checks if shared pins on multi-unit symbols have been connected to different nets.

Returns
the error count

Definition at line 746 of file erc.cpp.

747{
748 const NET_MAP& nets = m_schematic->ConnectionGraph()->GetNetMap();
749
750 int errors = 0;
751
752 std::unordered_map<wxString, std::pair<wxString, SCH_PIN*>> pinToNetMap;
753
754 for( const std::pair<NET_NAME_CODE_CACHE_KEY, std::vector<CONNECTION_SUBGRAPH*>> net : nets )
755 {
756 const wxString& netName = net.first.Name;
757
758 for( CONNECTION_SUBGRAPH* subgraph : net.second )
759 {
760 for( EDA_ITEM* item : subgraph->m_items )
761 {
762 if( item->Type() == SCH_PIN_T )
763 {
764 SCH_PIN* pin = static_cast<SCH_PIN*>( item );
765
766 if( !pin->GetLibPin()->GetParent()->IsMulti() )
767 continue;
768
769 wxString name = pin->GetParentSymbol()->GetRef( &subgraph->m_sheet ) +
770 + ":" + pin->GetShownNumber();
771
772 if( !pinToNetMap.count( name ) )
773 {
774 pinToNetMap[name] = std::make_pair( netName, pin );
775 }
776 else if( pinToNetMap[name].first != netName )
777 {
778 std::shared_ptr<ERC_ITEM> ercItem =
780
781 ercItem->SetErrorMessage( wxString::Format(
782 _( "Pin %s is connected to both %s and %s" ),
783 pin->GetShownNumber(),
784 netName,
785 pinToNetMap[name].first ) );
786
787 ercItem->SetItems( pin, pinToNetMap[name].second );
788 ercItem->SetSheetSpecificPath( subgraph->m_sheet );
789 ercItem->SetItemsSheetPaths( subgraph->m_sheet, subgraph->m_sheet );
790
791 SCH_MARKER* marker = new SCH_MARKER( ercItem,
792 pin->GetTransformedPosition() );
793 subgraph->m_sheet.LastScreen()->Append( marker );
794 errors += 1;
795 }
796 }
797 }
798 }
799 }
800
801 return errors;
802}
const char * name
Definition: DXF_plotter.cpp:56
const NET_MAP & GetNetMap() const
A subgraph is a set of items that are electrically connected on a single sheet.
std::vector< SCH_ITEM * > m_items
SCH_SHEET_PATH m_sheet
A base class for most all the KiCad significant classes used in schematics and boards.
Definition: eda_item.h:85
KICAD_T Type() const
Returns the type of object.
Definition: eda_item.h:97
CONNECTION_GRAPH * ConnectionGraph() const override
Definition: schematic.h:130
std::unordered_map< NET_NAME_CODE_CACHE_KEY, std::vector< CONNECTION_SUBGRAPH * > > NET_MAP
Associates a NET_CODE_NAME with all the subgraphs in that net.
@ ERCE_DIFFERENT_UNIT_NET
Shared pin in a multi-unit symbol is connected to more than one net.
Definition: erc_settings.h:58
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
@ SCH_PIN_T
Definition: typeinfo.h:159

References _, SCH_SCREEN::Append(), SCHEMATIC::ConnectionGraph(), ERC_ITEM::Create(), ERCE_DIFFERENT_UNIT_NET, Format(), CONNECTION_GRAPH::GetNetMap(), SCH_SHEET_PATH::LastScreen(), CONNECTION_SUBGRAPH::m_items, m_schematic, CONNECTION_SUBGRAPH::m_sheet, name, pin, SCH_PIN_T, and EDA_ITEM::Type().

Referenced by BOOST_FIXTURE_TEST_CASE(), and DIALOG_ERC::testErc().

◆ TestNoConnectPins()

int ERC_TESTER::TestNoConnectPins ( )

In KiCad 5 and earlier, you could connect stuff up to pins with NC electrical type.

In KiCad 6, this no longer results in those pins joining the net, so we need to warn about it

Returns
the error count

Definition at line 552 of file erc.cpp.

553{
554 int err_count = 0;
555
556 for( const SCH_SHEET_PATH& sheet : m_schematic->GetSheets() )
557 {
558 std::map<VECTOR2I, std::vector<SCH_PIN*>> pinMap;
559
560 for( SCH_ITEM* item : sheet.LastScreen()->Items().OfType( SCH_SYMBOL_T ) )
561 {
562 SCH_SYMBOL* symbol = static_cast<SCH_SYMBOL*>( item );
563
564 for( SCH_PIN* pin : symbol->GetPins( &sheet ) )
565 {
566 if( pin->GetLibPin()->GetType() == ELECTRICAL_PINTYPE::PT_NC )
567 pinMap[pin->GetPosition()].emplace_back( pin );
568 }
569 }
570
571 for( const std::pair<const VECTOR2I, std::vector<SCH_PIN*>>& pair : pinMap )
572 {
573 if( pair.second.size() > 1 )
574 {
575 err_count++;
576
577 std::shared_ptr<ERC_ITEM> ercItem = ERC_ITEM::Create( ERCE_NOCONNECT_CONNECTED );
578
579 ercItem->SetItems( pair.second[0], pair.second[1],
580 pair.second.size() > 2 ? pair.second[2] : nullptr,
581 pair.second.size() > 3 ? pair.second[3] : nullptr );
582 ercItem->SetErrorMessage( _( "Pins with 'no connection' type are connected" ) );
583
584 SCH_MARKER* marker = new SCH_MARKER( ercItem, pair.first );
585 sheet.LastScreen()->Append( marker );
586 }
587 }
588 }
589
590 return err_count;
591}
std::vector< SCH_PIN * > GetPins(const SCH_SHEET_PATH *aSheet=nullptr) const
Retrieve a list of the SCH_PINs for the given sheet path.
@ ERCE_NOCONNECT_CONNECTED
A no connect symbol is connected to more than 1 pin.
Definition: erc_settings.h:48
@ PT_NC
not connected (must be left open)

References _, ERC_ITEM::Create(), ERCE_NOCONNECT_CONNECTED, SCH_SYMBOL::GetPins(), SCHEMATIC::GetSheets(), m_schematic, pin, PT_NC, and SCH_SYMBOL_T.

Referenced by BOOST_FIXTURE_TEST_CASE(), and DIALOG_ERC::testErc().

◆ TestOffGridEndpoints()

int ERC_TESTER::TestOffGridEndpoints ( int  aGridSize)

Test pins and wire ends for being off grid.

Returns
the error count

Definition at line 947 of file erc.cpp.

948{
949 // The minimal grid size allowed to place a pin is 25 mils
950 // the best grid size is 50 mils, but 25 mils is still usable
951 // this is because all symbols are using a 50 mils grid to place pins, and therefore
952 // the wires must be on the 50 mils grid
953 // So raise an error if a pin is not on a 25 mil (or bigger: 50 mil or 100 mil) grid
954 const int min_grid_size = schIUScale.MilsToIU( 25 );
955 const int clamped_grid_size = ( aGridSize < min_grid_size ) ? min_grid_size : aGridSize;
956
957 SCH_SCREENS screens( m_schematic->Root() );
958 int err_count = 0;
959
960 for( SCH_SCREEN* screen = screens.GetFirst(); screen != nullptr; screen = screens.GetNext() )
961 {
962 std::vector<SCH_MARKER*> markers;
963
964 for( SCH_ITEM* item : screen->Items() )
965 {
966 if( item->Type() == SCH_LINE_T && item->IsConnectable() )
967 {
968 SCH_LINE* line = static_cast<SCH_LINE*>( item );
969
970 if( ( line->GetStartPoint().x % clamped_grid_size ) != 0
971 || ( line->GetStartPoint().y % clamped_grid_size) != 0 )
972 {
973 std::shared_ptr<ERC_ITEM> ercItem = ERC_ITEM::Create( ERCE_ENDPOINT_OFF_GRID );
974 ercItem->SetItems( line );
975
976 markers.emplace_back( new SCH_MARKER( ercItem, line->GetStartPoint() ) );
977 }
978 else if( ( line->GetEndPoint().x % clamped_grid_size ) != 0
979 || ( line->GetEndPoint().y % clamped_grid_size) != 0 )
980 {
981 std::shared_ptr<ERC_ITEM> ercItem = ERC_ITEM::Create( ERCE_ENDPOINT_OFF_GRID );
982 ercItem->SetItems( line );
983
984 markers.emplace_back( new SCH_MARKER( ercItem, line->GetEndPoint() ) );
985 }
986 }
987 else if( item->Type() == SCH_SYMBOL_T )
988 {
989 SCH_SYMBOL* symbol = static_cast<SCH_SYMBOL*>( item );
990
991 for( SCH_PIN* pin : symbol->GetPins( nullptr ) )
992 {
993 VECTOR2I pinPos = pin->GetTransformedPosition();
994
995 if( ( pinPos.x % clamped_grid_size ) != 0
996 || ( pinPos.y % clamped_grid_size) != 0 )
997 {
998 std::shared_ptr<ERC_ITEM> ercItem = ERC_ITEM::Create( ERCE_ENDPOINT_OFF_GRID );
999 ercItem->SetItems( pin );
1000
1001 markers.emplace_back( new SCH_MARKER( ercItem, pinPos ) );
1002 break;
1003 }
1004 }
1005 }
1006 }
1007
1008 for( SCH_MARKER* marker : markers )
1009 {
1010 screen->Append( marker );
1011 err_count += 1;
1012 }
1013 }
1014
1015 return err_count;
1016}
constexpr EDA_IU_SCALE schIUScale
Definition: base_units.h:111
Segment description base class to describe items which have 2 end points (track, wire,...
Definition: sch_line.h:40
VECTOR2I GetEndPoint() const
Definition: sch_line.h:143
VECTOR2I GetStartPoint() const
Definition: sch_line.h:138
@ ERCE_ENDPOINT_OFF_GRID
Pin or wire-end off grid.
Definition: erc_settings.h:41
constexpr int MilsToIU(int mils) const
Definition: base_units.h:94
@ SCH_LINE_T
Definition: typeinfo.h:146

References ERC_ITEM::Create(), ERCE_ENDPOINT_OFF_GRID, SCH_LINE::GetEndPoint(), SCH_SCREENS::GetFirst(), SCH_SCREENS::GetNext(), SCH_SYMBOL::GetPins(), SCH_LINE::GetStartPoint(), m_schematic, EDA_IU_SCALE::MilsToIU(), pin, SCHEMATIC::Root(), SCH_LINE_T, SCH_SYMBOL_T, schIUScale, VECTOR2< T >::x, and VECTOR2< T >::y.

Referenced by DIALOG_ERC::testErc().

◆ TestOthersItems()

void ERC_TESTER::TestOthersItems ( NETLIST_OBJECT_LIST *  aList,
unsigned  aNetItemRef,
unsigned  aNetStart,
int *  aMinConnexion 
)

Perform ERC testing for electrical conflicts between NetItemRef and other items (mainly pin) on the same net.

Parameters
aList= a reference to the list of connected objects
aNetItemRef= index in list of the current object
aNetStart= index in list of net objects of the first item
aMinConnexion= a pointer to a variable to store the minimal connection found( NOD, DRV, NPI, NET_NC)

◆ TestPinToPin()

int ERC_TESTER::TestPinToPin ( )

Checks the full netlist against the pin-to-pin connectivity requirements.

Returns
the error count

Definition at line 594 of file erc.cpp.

595{
596 ERC_SETTINGS& settings = m_schematic->ErcSettings();
597 const NET_MAP& nets = m_schematic->ConnectionGraph()->GetNetMap();
598
599 int errors = 0;
600
601 for( const std::pair<NET_NAME_CODE_CACHE_KEY, std::vector<CONNECTION_SUBGRAPH*>> net : nets )
602 {
603 std::vector<ERC_SCH_PIN_CONTEXT> pins;
604 std::unordered_map<EDA_ITEM*, SCH_SCREEN*> pinToScreenMap;
605 bool has_noconnect = false;
606
607 for( CONNECTION_SUBGRAPH* subgraph: net.second )
608 {
609 if( subgraph->m_no_connect )
610 has_noconnect = true;
611
612 for( EDA_ITEM* item : subgraph->m_items )
613 {
614 if( item->Type() == SCH_PIN_T )
615 {
616 pins.emplace_back( static_cast<SCH_PIN*>( item ), subgraph->m_sheet );
617 pinToScreenMap[item] = subgraph->m_sheet.LastScreen();
618 }
619 }
620 }
621
622 std::set<std::pair<ERC_SCH_PIN_CONTEXT, ERC_SCH_PIN_CONTEXT>> tested;
623
624 ERC_SCH_PIN_CONTEXT needsDriver;
625 bool hasDriver = false;
626
627 // We need different drivers for power nets and normal nets.
628 // A power net has at least one pin having the ELECTRICAL_PINTYPE::PT_POWER_IN
629 // and power nets can be driven only by ELECTRICAL_PINTYPE::PT_POWER_OUT pins
630 bool ispowerNet = false;
631
632 for( ERC_SCH_PIN_CONTEXT& refPin : pins )
633 {
634 if( refPin.Pin()->GetType() == ELECTRICAL_PINTYPE::PT_POWER_IN )
635 {
636 ispowerNet = true;
637 break;
638 }
639 }
640
641 for( ERC_SCH_PIN_CONTEXT& refPin : pins )
642 {
643 ELECTRICAL_PINTYPE refType = refPin.Pin()->GetType();
644
645 if( DrivenPinTypes.count( refType ) )
646 {
647 // needsDriver will be the pin shown in the error report eventually, so try to
648 // upgrade to a "better" pin if possible: something visible and only a power symbol
649 // if this net needs a power driver
650 if( !needsDriver.Pin()
651 || ( !needsDriver.Pin()->IsVisible() && refPin.Pin()->IsVisible() )
652 || ( ispowerNet
653 != ( needsDriver.Pin()->GetType()
655 && ispowerNet == ( refType == ELECTRICAL_PINTYPE::PT_POWER_IN ) ) )
656 {
657 needsDriver = refPin;
658 }
659 }
660
661 if( ispowerNet )
662 hasDriver |= ( DrivingPowerPinTypes.count( refType ) != 0 );
663 else
664 hasDriver |= ( DrivingPinTypes.count( refType ) != 0 );
665
666 for( ERC_SCH_PIN_CONTEXT& testPin : pins )
667 {
668 if( testPin == refPin )
669 continue;
670
671 ERC_SCH_PIN_CONTEXT first_pin = refPin;
672 ERC_SCH_PIN_CONTEXT second_pin = testPin;
673
674 if( second_pin < first_pin )
675 std::swap( first_pin, second_pin );
676
677 std::pair<ERC_SCH_PIN_CONTEXT, ERC_SCH_PIN_CONTEXT> pair =
678 std::make_pair( first_pin, second_pin );
679
680 if( auto [ins_pin, inserted ] = tested.insert( pair ); !inserted )
681 continue;
682
683 // Multiple pins in the same symbol that share a type,
684 // name and position are considered
685 // "stacked" and shouldn't trigger ERC errors
686 if( refPin.Pin()->GetParent() == testPin.Pin()->GetParent()
687 && refPin.Pin()->GetPosition() == testPin.Pin()->GetPosition()
688 && refPin.Pin()->GetName() == testPin.Pin()->GetName()
689 && refPin.Pin()->GetType() == testPin.Pin()->GetType()
690 && refPin.Sheet() == testPin.Sheet() )
691 continue;
692
693 ELECTRICAL_PINTYPE testType = testPin.Pin()->GetType();
694
695 if( ispowerNet )
696 hasDriver |= ( DrivingPowerPinTypes.count( testType ) != 0 );
697 else
698 hasDriver |= ( DrivingPinTypes.count( testType ) != 0 );
699
700 PIN_ERROR erc = settings.GetPinMapValue( refType, testType );
701
703 {
704 std::shared_ptr<ERC_ITEM> ercItem =
707 ercItem->SetItems( refPin.Pin(), testPin.Pin() );
708 ercItem->SetSheetSpecificPath( refPin.Sheet() );
709 ercItem->SetItemsSheetPaths( refPin.Sheet(), testPin.Sheet() );
710
711 ercItem->SetErrorMessage(
712 wxString::Format( _( "Pins of type %s and %s are connected" ),
713 ElectricalPinTypeGetText( refType ),
714 ElectricalPinTypeGetText( testType ) ) );
715
716 SCH_MARKER* marker =
717 new SCH_MARKER( ercItem, refPin.Pin()->GetTransformedPosition() );
718 pinToScreenMap[refPin.Pin()]->Append( marker );
719 errors++;
720 }
721 }
722 }
723
724 if( needsDriver.Pin() && !hasDriver && !has_noconnect )
725 {
726 int err_code = ispowerNet ? ERCE_POWERPIN_NOT_DRIVEN : ERCE_PIN_NOT_DRIVEN;
727
728 if( settings.IsTestEnabled( err_code ) )
729 {
730 std::shared_ptr<ERC_ITEM> ercItem = ERC_ITEM::Create( err_code );
731
732 ercItem->SetItems( needsDriver.Pin() );
733
734 SCH_MARKER* marker =
735 new SCH_MARKER( ercItem, needsDriver.Pin()->GetTransformedPosition() );
736 pinToScreenMap[needsDriver.Pin()]->Append( marker );
737 errors++;
738 }
739 }
740 }
741
742 return errors;
743}
SCH_ITEM * m_no_connect
No-connect item in graph, if any.
A class used to associate a SCH_PIN with its owning SCH_SHEET_PATH, in order to handle ERC checks acr...
SCH_PIN * Pin()
Gets the SCH_PIN for this context.
PIN_ERROR GetPinMapValue(int aFirstType, int aSecondType) const
Definition: erc_settings.h:141
bool IsVisible() const
Definition: sch_pin.h:135
VECTOR2I GetTransformedPosition() const
Definition: sch_pin.cpp:343
ELECTRICAL_PINTYPE GetType() const
Definition: sch_pin.cpp:117
const std::set< ELECTRICAL_PINTYPE > DrivenPinTypes
Definition: erc.cpp:119
const std::set< ELECTRICAL_PINTYPE > DrivingPinTypes
Definition: erc.cpp:101
const std::set< ELECTRICAL_PINTYPE > DrivingPowerPinTypes
Definition: erc.cpp:113
@ ERCE_POWERPIN_NOT_DRIVEN
Power input pin connected to some others pins but no power out pin to drive it.
Definition: erc_settings.h:45
@ ERCE_PIN_TO_PIN_WARNING
Definition: erc_settings.h:85
@ ERCE_PIN_NOT_DRIVEN
Pin connected to some others pins but no pin to drive it.
Definition: erc_settings.h:43
@ ERCE_PIN_TO_PIN_ERROR
Definition: erc_settings.h:86
PIN_ERROR
The values a pin-to-pin entry in the pin matrix can take on.
Definition: erc_settings.h:93
wxString ElectricalPinTypeGetText(ELECTRICAL_PINTYPE aType)
Definition: pin_type.cpp:240
ELECTRICAL_PINTYPE
The symbol library pin object electrical types used in ERC tests.
Definition: pin_type.h:36

References _, SCHEMATIC::ConnectionGraph(), ERC_ITEM::Create(), DrivenPinTypes, DrivingPinTypes, DrivingPowerPinTypes, ElectricalPinTypeGetText(), erc, ERCE_PIN_NOT_DRIVEN, ERCE_PIN_TO_PIN_ERROR, ERCE_PIN_TO_PIN_WARNING, ERCE_POWERPIN_NOT_DRIVEN, SCHEMATIC::ErcSettings(), Format(), CONNECTION_GRAPH::GetNetMap(), ERC_SETTINGS::GetPinMapValue(), SCH_PIN::GetTransformedPosition(), SCH_PIN::GetType(), ERC_SETTINGS::IsTestEnabled(), SCH_PIN::IsVisible(), SCH_SHEET_PATH::LastScreen(), CONNECTION_SUBGRAPH::m_items, CONNECTION_SUBGRAPH::m_no_connect, m_schematic, CONNECTION_SUBGRAPH::m_sheet, OK, ERC_SCH_PIN_CONTEXT::Pin(), PT_POWER_IN, SCH_PIN_T, EDA_ITEM::Type(), and WARNING.

Referenced by BOOST_FIXTURE_TEST_CASE(), and DIALOG_ERC::testErc().

◆ TestSimilarLabels()

int ERC_TESTER::TestSimilarLabels ( )

Checks for labels that differ only in capitalization.

Returns
the error count

Definition at line 805 of file erc.cpp.

806{
807 const NET_MAP& nets = m_schematic->ConnectionGraph()->GetNetMap();
808
809 int errors = 0;
810
811 std::unordered_map<wxString, SCH_LABEL_BASE*> labelMap;
812
813 for( const std::pair<NET_NAME_CODE_CACHE_KEY, std::vector<CONNECTION_SUBGRAPH*>> net : nets )
814 {
815 for( CONNECTION_SUBGRAPH* subgraph : net.second )
816 {
817 for( EDA_ITEM* item : subgraph->m_items )
818 {
819 switch( item->Type() )
820 {
821 case SCH_LABEL_T:
822 case SCH_HIER_LABEL_T:
824 {
825 SCH_LABEL_BASE* label = static_cast<SCH_LABEL_BASE*>( item );
826
827 wxString normalized = label->GetShownText().Lower();
828
829 if( !labelMap.count( normalized ) )
830 {
831 labelMap[normalized] = label;
832 }
833 else if( labelMap.at( normalized )->GetShownText() != label->GetShownText() )
834 {
835 std::shared_ptr<ERC_ITEM> ercItem = ERC_ITEM::Create( ERCE_SIMILAR_LABELS );
836 ercItem->SetItems( label, labelMap.at( normalized ) );
837
838 SCH_MARKER* marker = new SCH_MARKER( ercItem, label->GetPosition() );
839 subgraph->m_sheet.LastScreen()->Append( marker );
840 errors += 1;
841 }
842
843 break;
844 }
845
846 default:
847 break;
848 }
849 }
850 }
851 }
852
853 return errors;
854}
wxString GetShownText(int aDepth=0, bool aAllowExtraText=true) const override
Return the string actually shown after processing of the base text.
Definition: sch_label.cpp:559
VECTOR2I GetPosition() const override
Definition: sch_text.h:203
@ ERCE_SIMILAR_LABELS
2 labels are equal for case insensitive comparisons.
Definition: erc_settings.h:51
@ SCH_LABEL_T
Definition: typeinfo.h:151
@ SCH_HIER_LABEL_T
Definition: typeinfo.h:153
@ SCH_GLOBAL_LABEL_T
Definition: typeinfo.h:152

References SCH_SCREEN::Append(), SCHEMATIC::ConnectionGraph(), ERC_ITEM::Create(), ERCE_SIMILAR_LABELS, CONNECTION_GRAPH::GetNetMap(), SCH_TEXT::GetPosition(), SCH_LABEL_BASE::GetShownText(), SCH_SHEET_PATH::LastScreen(), CONNECTION_SUBGRAPH::m_items, m_schematic, CONNECTION_SUBGRAPH::m_sheet, SCH_GLOBAL_LABEL_T, SCH_HIER_LABEL_T, SCH_LABEL_T, and EDA_ITEM::Type().

Referenced by BOOST_FIXTURE_TEST_CASE(), and DIALOG_ERC::testErc().

◆ TestSimModelIssues()

int ERC_TESTER::TestSimModelIssues ( )

Test SPICE models for various issues.

Definition at line 1019 of file erc.cpp.

1020{
1021 wxString msg;
1022 WX_STRING_REPORTER reporter( &msg );
1024 int err_count = 0;
1025 SIM_LIB_MGR libMgr( &m_schematic->Prj(), &reporter );
1026
1027 for( SCH_SHEET_PATH& sheet : sheets )
1028 {
1029 std::vector<SCH_MARKER*> markers;
1030
1031 for( SCH_ITEM* item : sheet.LastScreen()->Items().OfType( SCH_SYMBOL_T ) )
1032 {
1033 // Reset for each symbol
1034 msg.Clear();
1035
1036 SCH_SYMBOL* symbol = static_cast<SCH_SYMBOL*>( item );
1037 SIM_LIBRARY::MODEL model = libMgr.CreateModel( &sheet, *symbol );
1038
1039 if( !msg.IsEmpty() )
1040 {
1041 std::shared_ptr<ERC_ITEM> ercItem = ERC_ITEM::Create( ERCE_SIMULATION_MODEL );
1042 ercItem->SetErrorMessage( msg );
1043 ercItem->SetItems( symbol );
1044
1045 markers.emplace_back( new SCH_MARKER( ercItem, symbol->GetPosition() ) );
1046 }
1047 }
1048
1049 for( SCH_MARKER* marker : markers )
1050 {
1051 sheet.LastScreen()->Append( marker );
1052 err_count += 1;
1053 }
1054 }
1055
1056 return err_count;
1057}
A wrapper for reporting to a wxString object.
Definition: reporter.h:164
@ ERCE_SIMULATION_MODEL
An error was found in the simulation model.
Definition: erc_settings.h:71

References ERC_ITEM::Create(), SIM_LIB_MGR::CreateModel(), ERCE_SIMULATION_MODEL, SCH_SYMBOL::GetPosition(), SCHEMATIC::GetSheets(), m_schematic, SCHEMATIC::Prj(), and SCH_SYMBOL_T.

Referenced by DIALOG_ERC::testErc().

◆ TestTextVars()

void ERC_TESTER::TestTextVars ( DS_PROXY_VIEW_ITEM aDrawingSheet)

Check for any unresolved text variable references.

Definition at line 171 of file erc.cpp.

172{
173 DS_DRAW_ITEM_LIST wsItems;
174
175 auto unresolved = [this]( wxString str )
176 {
177 str = ExpandEnvVarSubstitutions( str, &m_schematic->Prj() );
178 return str.Matches( wxT( "*${*}*" ) );
179 };
180
181 if( aDrawingSheet )
182 {
184 wsItems.SetPageNumber( wxS( "1" ) );
185 wsItems.SetSheetCount( 1 );
186 wsItems.SetFileName( wxS( "dummyFilename" ) );
187 wsItems.SetSheetName( wxS( "dummySheet" ) );
188 wsItems.SetSheetLayer( wxS( "dummyLayer" ) );
189 wsItems.SetProject( &m_schematic->Prj() );
190 wsItems.BuildDrawItemsList( aDrawingSheet->GetPageInfo(), aDrawingSheet->GetTitleBlock());
191 }
192
193 SCH_SHEET_PATH savedCurrentSheet = m_schematic->CurrentSheet();
195
196 for( SCH_SHEET_PATH& sheet : sheets )
197 {
199 SCH_SCREEN* screen = sheet.LastScreen();
200
201 for( SCH_ITEM* item : screen->Items().OfType( SCH_LOCATE_ANY_T ) )
202 {
203 if( item->Type() == SCH_SYMBOL_T )
204 {
205 SCH_SYMBOL* symbol = static_cast<SCH_SYMBOL*>( item );
206
207 for( SCH_FIELD& field : symbol->GetFields() )
208 {
209 if( unresolved( field.GetShownText() ) )
210 {
211 VECTOR2I pos = field.GetPosition() - symbol->GetPosition();
212 pos = symbol->GetTransform().TransformCoordinate( pos );
213 pos += symbol->GetPosition();
214
215 std::shared_ptr<ERC_ITEM> ercItem =
217 ercItem->SetItems( &field );
218
219 SCH_MARKER* marker = new SCH_MARKER( ercItem, pos );
220 screen->Append( marker );
221 }
222 }
223 }
224 else if( item->Type() == SCH_SHEET_T )
225 {
226 SCH_SHEET* subSheet = static_cast<SCH_SHEET*>( item );
227
228 for( SCH_FIELD& field : subSheet->GetFields() )
229 {
230 if( unresolved( field.GetShownText() ) )
231 {
232 std::shared_ptr<ERC_ITEM> ercItem =
234 ercItem->SetItems( &field );
235
236 SCH_MARKER* marker = new SCH_MARKER( ercItem, field.GetPosition() );
237 screen->Append( marker );
238 }
239 }
240
241 for( SCH_SHEET_PIN* pin : static_cast<SCH_SHEET*>( item )->GetPins() )
242 {
243 if( pin->GetShownText().Matches( wxT( "*${*}*" ) ) )
244 {
245 std::shared_ptr<ERC_ITEM> ercItem =
247 ercItem->SetItems( pin );
248
249 SCH_MARKER* marker = new SCH_MARKER( ercItem, pin->GetPosition() );
250 screen->Append( marker );
251 }
252 }
253 }
254 else if( SCH_TEXT* text = dynamic_cast<SCH_TEXT*>( item ) )
255 {
256 if( text->GetShownText().Matches( wxT( "*${*}*" ) ) )
257 {
258 std::shared_ptr<ERC_ITEM> ercItem =
260 ercItem->SetItems( text );
261
262 SCH_MARKER* marker = new SCH_MARKER( ercItem, text->GetPosition() );
263 screen->Append( marker );
264 }
265 }
266 else if( SCH_TEXTBOX* textBox = dynamic_cast<SCH_TEXTBOX*>( item ) )
267 {
268 if( textBox->GetShownText().Matches( wxT( "*${*}*" ) ) )
269 {
270 std::shared_ptr<ERC_ITEM> ercItem =
272 ercItem->SetItems( textBox );
273
274 SCH_MARKER* marker = new SCH_MARKER( ercItem, textBox->GetPosition() );
275 screen->Append( marker );
276 }
277 }
278 }
279
280 for( DS_DRAW_ITEM_BASE* item = wsItems.GetFirst(); item; item = wsItems.GetNext() )
281 {
282 if( DS_DRAW_ITEM_TEXT* text = dynamic_cast<DS_DRAW_ITEM_TEXT*>( item ) )
283 {
284 if( text->GetShownText().Matches( wxT( "*${*}*" ) ) )
285 {
286 std::shared_ptr<ERC_ITEM> erc = ERC_ITEM::Create( ERCE_UNRESOLVED_VARIABLE );
287 erc->SetErrorMessage( _( "Unresolved text variable in drawing sheet" ) );
288
289 SCH_MARKER* marker = new SCH_MARKER( erc, text->GetPosition() );
290 screen->Append( marker );
291 }
292 }
293 }
294 }
295
296 m_schematic->SetCurrentSheet( savedCurrentSheet );
297}
Base class to handle basic graphic items.
Definition: ds_draw_item.h:59
Store the list of graphic items: rect, lines, polygons and texts to draw/plot the title block and fra...
Definition: ds_draw_item.h:385
DS_DRAW_ITEM_BASE * GetFirst()
Definition: ds_draw_item.h:483
void BuildDrawItemsList(const PAGE_INFO &aPageInfo, const TITLE_BLOCK &aTitleBlock)
Drawing or plot the drawing sheet.
void SetFileName(const wxString &aFileName)
Set the filename to draw/plot.
Definition: ds_draw_item.h:427
void SetSheetName(const wxString &aSheetName)
Set the sheet name to draw/plot.
Definition: ds_draw_item.h:432
void SetSheetLayer(const wxString &aSheetLayer)
Set the sheet layer to draw/plot.
Definition: ds_draw_item.h:442
void SetSheetCount(int aSheetCount)
Set the value of the count of sheets, for basic inscriptions.
Definition: ds_draw_item.h:470
void SetPageNumber(const wxString &aPageNumber)
Set the value of the sheet number.
Definition: ds_draw_item.h:460
DS_DRAW_ITEM_BASE * GetNext()
Definition: ds_draw_item.h:493
void SetMilsToIUfactor(double aMils2Iu)
Set the scalar to convert pages units (mils) to draw/plot units.
Definition: ds_draw_item.h:450
void SetProject(const PROJECT *aProject)
Definition: ds_draw_item.h:407
A graphic text.
Definition: ds_draw_item.h:303
const PAGE_INFO & GetPageInfo()
const TITLE_BLOCK & GetTitleBlock()
SCH_SHEET_PATH & CurrentSheet() const override
Definition: schematic.h:120
void SetCurrentSheet(const SCH_SHEET_PATH &aPath) override
Definition: schematic.h:125
Instances are attached to a symbol or sheet and provide a place for the symbol's value,...
Definition: sch_field.h:51
Define a sheet pin (label) used in sheets to create hierarchical schematics.
Definition: sch_sheet_pin.h:66
std::vector< SCH_FIELD > & GetFields()
Definition: sch_sheet.h:93
TRANSFORM & GetTransform()
Definition: sch_symbol.h:283
void GetFields(std::vector< SCH_FIELD * > &aVector, bool aVisibleOnly)
Populate a std::vector with SCH_FIELDs.
Definition: sch_symbol.cpp:879
VECTOR2I TransformCoordinate(const VECTOR2I &aPoint) const
Calculate a new coordinate according to the mirror/rotation transform.
Definition: transform.cpp:45
const wxString ExpandEnvVarSubstitutions(const wxString &aString, const PROJECT *aProject)
Replace any environment variable & text variable references with their values.
Definition: common.cpp:299
@ ERCE_UNRESOLVED_VARIABLE
A text variable could not be resolved.
Definition: erc_settings.h:70
const double IU_PER_MILS
Definition: base_units.h:78
@ SCH_LOCATE_ANY_T
Definition: typeinfo.h:183

References _, SCH_SCREEN::Append(), DS_DRAW_ITEM_LIST::BuildDrawItemsList(), ERC_ITEM::Create(), SCHEMATIC::CurrentSheet(), erc, ERCE_UNRESOLVED_VARIABLE, ExpandEnvVarSubstitutions(), SCH_SHEET::GetFields(), SCH_SYMBOL::GetFields(), DS_DRAW_ITEM_LIST::GetFirst(), DS_DRAW_ITEM_LIST::GetNext(), DS_PROXY_VIEW_ITEM::GetPageInfo(), SCH_SYMBOL::GetPosition(), SCHEMATIC::GetSheets(), DS_PROXY_VIEW_ITEM::GetTitleBlock(), SCH_SYMBOL::GetTransform(), SCH_SCREEN::Items(), EDA_IU_SCALE::IU_PER_MILS, m_schematic, EE_RTREE::OfType(), pin, SCHEMATIC::Prj(), SCH_LOCATE_ANY_T, SCH_SHEET_T, SCH_SYMBOL_T, schIUScale, SCHEMATIC::SetCurrentSheet(), DS_DRAW_ITEM_LIST::SetFileName(), DS_DRAW_ITEM_LIST::SetMilsToIUfactor(), DS_DRAW_ITEM_LIST::SetPageNumber(), DS_DRAW_ITEM_LIST::SetProject(), DS_DRAW_ITEM_LIST::SetSheetCount(), DS_DRAW_ITEM_LIST::SetSheetLayer(), DS_DRAW_ITEM_LIST::SetSheetName(), text, and TRANSFORM::TransformCoordinate().

Referenced by DIALOG_ERC::testErc().

Member Data Documentation

◆ m_schematic


The documentation for this class was generated from the following files: