83 _(
"Bidirectional Pin" ),
87 _(
"Unspecified Pin" ),
88 _(
"Power Input Pin" ),
89 _(
"Power Output Pin" ),
90 _(
"Open Collector" ),
100 _(
"Bidirectional Pin" ),
101 _(
"Tri-State Pin" ),
104 _(
"Unspecified Pin" ),
105 _(
"Power Input Pin" ),
106 _(
"Power Output Pin" ),
107 _(
"Open Collector" ),
149 std::vector<SCH_SHEET*> list;
152 list.push_back(
static_cast<SCH_SHEET*
>( item ) );
154 for(
size_t i = 0; i < list.size(); i++ )
158 for(
size_t j = i + 1; j < list.size(); j++ )
170 ercItem->SetItems( sheet, test_item );
173 screen->Append( marker );
191 [
this]( wxString str )
194 return str.Matches( wxS(
"*${*}*" ) );
201 static wxRegEx warningExpr( wxS(
"^\\$\\{ERC_WARNING\\s*([^}]*)\\}(.*)$" ) );
202 static wxRegEx errorExpr( wxS(
"^\\$\\{ERC_ERROR\\s*([^}]*)\\}(.*)$" ) );
204 if( warningExpr.Matches(
text ) )
207 wxString ercText = warningExpr.GetMatch(
text, 1 );
210 ercItem->SetItems( item );
212 ercText +=
_(
" (in drawing sheet)" );
214 ercItem->SetSheetSpecificPath( sheet );
215 ercItem->SetErrorMessage( ercText );
218 screen->Append( marker );
223 if( errorExpr.Matches(
text ) )
226 wxString ercText = errorExpr.GetMatch(
text, 1 );
229 ercItem->SetItems( item );
231 ercText +=
_(
" (in drawing sheet)" );
233 ercItem->SetSheetSpecificPath( sheet );
234 ercItem->SetErrorMessage( ercText );
237 screen->Append( marker );
268 if( unresolved( field.GetShownText( &sheet,
true ) ) )
271 ercItem->SetItems( symbol );
272 ercItem->SetSheetSpecificPath( sheet );
278 testAssertion( &field, sheet, screen, field.GetText(), field.
GetPosition() );
294 if( unresolved( textItem->
GetShownText( &sheet,
true ) ) )
297 ercItem->SetItems( symbol );
298 ercItem->SetSheetSpecificPath( sheet );
308 testAssertion( symbol, sheet, screen, textItem->
GetText(),
315 if( unresolved( textboxItem->
GetShownText(
nullptr, &sheet,
true ) ) )
318 ercItem->SetItems( symbol );
319 ercItem->SetSheetSpecificPath( sheet );
329 testAssertion( symbol, sheet, screen, textboxItem->
GetText(),
338 for(
SCH_FIELD& field : label->GetFields() )
340 if( unresolved( field.GetShownText( &sheet,
true ) ) )
343 ercItem->SetItems( label );
344 ercItem->SetSheetSpecificPath( sheet );
350 testAssertion( &field, sheet, screen, field.GetText(), field.
GetPosition() );
359 if( unresolved( field.GetShownText( &sheet,
true ) ) )
362 ercItem->SetItems( subSheet );
363 ercItem->SetSheetSpecificPath( sheet );
369 testAssertion( &field, sheet, screen, field.GetText(), field.
GetPosition() );
377 if(
pin->GetShownText( &subSheetPath,
true ).Matches( wxS(
"*${*}*" ) ) )
380 ercItem->SetItems(
pin );
381 ercItem->SetSheetSpecificPath( sheet );
390 if(
text->GetShownText( &sheet,
true ).Matches( wxS(
"*${*}*" ) ) )
393 ercItem->SetItems(
text );
394 ercItem->SetSheetSpecificPath( sheet );
400 testAssertion(
text, sheet, screen,
text->GetText(),
text->GetPosition() );
404 if( textBox->GetShownText(
nullptr, &sheet,
true ).Matches( wxS(
"*${*}*" ) ) )
407 ercItem->SetItems( textBox );
408 ercItem->SetSheetSpecificPath( sheet );
414 testAssertion( textBox, sheet, screen, textBox->GetText(), textBox->
GetPosition() );
422 if( testAssertion(
nullptr, sheet, screen,
text->GetText(),
text->GetPosition() ) )
426 else if(
text->GetShownText(
true ).Matches( wxS(
"*${*}*" ) ) )
429 ercItem->SetErrorMessage(
_(
"Unresolved text variable in drawing sheet" ) );
430 ercItem->SetSheetSpecificPath( sheet );
455 wxString trimmedFieldName = field.GetName();
456 trimmedFieldName.Trim();
457 trimmedFieldName.Trim(
false );
459 if( field.GetName() != trimmedFieldName )
462 ercItem->SetItems( symbol, &field );
463 ercItem->SetItemsSheetPaths( sheet, sheet );
464 ercItem->SetSheetSpecificPath( sheet );
465 ercItem->SetErrorMessage(
467 _(
"Field name has leading or trailing whitespace: '%s'" ),
483 wxString trimmedFieldName = field.GetName();
484 trimmedFieldName.Trim();
485 trimmedFieldName.Trim(
false );
487 if( field.GetName() != trimmedFieldName )
490 ercItem->SetItems( subSheet, &field );
491 ercItem->SetItemsSheetPaths( sheet, sheet );
492 ercItem->SetSheetSpecificPath( sheet );
493 ercItem->SetErrorMessage(
495 _(
"Field name has leading or trailing whitespace: '%s'" ),
514 for( std::pair<const wxString, SCH_REFERENCE_LIST>& symbol :
m_refMap )
529 for(
size_t ii = 0; ii < refList.
GetCount(); ++ii )
534 if( !unitFP.IsEmpty() )
537 unitName = unit->
GetRef( &sheetPath,
true );
542 for(
size_t ii = 0; ii < refList.
GetCount(); ++ii )
550 if( unit && !secondFp.IsEmpty() && unitFP != secondFp )
552 msg.Printf(
_(
"Different footprints assigned to %s and %s" ),
553 unitName, secondName );
556 ercItem->SetErrorMessage( msg );
557 ercItem->SetItems( unit, secondUnit );
575 for( std::pair<const wxString, SCH_REFERENCE_LIST>& symbol :
m_refMap )
579 wxCHECK2( refList.
GetCount(),
continue );
589 std::set<int> lib_units;
590 std::set<int> instance_units;
591 std::set<int> missing_units;
594 [&]( std::set<int>& aMissingUnits,
const wxString& aErrorMsg,
int aErrorCode )
597 wxString missing_pin_units = wxS(
"[ " );
600 for(
int missing_unit : aMissingUnits )
604 missing_pin_units += wxS(
"..." );
611 missing_pin_units.Truncate( missing_pin_units.length() - 2 );
612 missing_pin_units += wxS(
" ]" );
614 msg.Printf( aErrorMsg, symbol.first, missing_pin_units );
617 ercItem->SetErrorMessage( msg );
618 ercItem->SetItems( unit );
619 ercItem->SetSheetSpecificPath( base_ref.
GetSheetPath() );
628 for(
int ii = 1; ii <= libSymbol->
GetUnitCount(); ++ii )
629 lib_units.insert( lib_units.end(), ii );
631 for(
size_t ii = 0; ii < refList.
GetCount(); ++ii )
632 instance_units.insert( instance_units.end(), refList.
GetItem( ii ).
GetUnit() );
634 std::set_difference( lib_units.begin(), lib_units.end(),
635 instance_units.begin(), instance_units.end(),
636 std::inserter( missing_units, missing_units.begin() ) );
643 std::set<int> missing_power;
644 std::set<int> missing_input;
645 std::set<int> missing_bidi;
647 for(
int missing_unit : missing_units )
651 for(
size_t ii = 0; ii < refList.
GetCount(); ++ii )
662 switch(
pin->GetType() )
665 missing_power.insert( missing_unit );
669 missing_bidi.insert( missing_unit );
673 missing_input.insert( missing_unit );
684 report( missing_power,
_(
"Symbol %s has input power pins in units %s that are not placed" ),
690 report( missing_input,
_(
"Symbol %s has input pins in units %s that are not placed" ),
696 report( missing_bidi,
_(
"Symbol %s has bidirectional pins in units %s that are not placed" ),
708 std::shared_ptr<NET_SETTINGS>& settings =
m_schematic->Project().GetProjectFile().NetSettings();
709 wxString defaultNetclass = settings->GetDefaultNetclass()->GetName();
718 ercItem->SetItems( item );
719 ercItem->SetErrorMessage( wxString::Format(
_(
"Netclass %s is not defined" ), netclass ) );
738 wxString netclass = field->
GetShownText( &sheet,
false );
740 if( !netclass.empty() && !netclass.IsSameAs( defaultNetclass )
741 && !settings->HasNetclass( netclass ) )
743 logError( sheet, item, netclass );
764 std::map<VECTOR2I, std::vector<SCH_ITEM*>> connMap;
771 connMap[pt].emplace_back( label );
774 for(
const std::pair<
const VECTOR2I, std::vector<SCH_ITEM*>>& pair : connMap )
776 std::vector<SCH_ITEM*> lines;
778 for(
SCH_ITEM* item : sheet.LastScreen()->Items().Overlapping(
SCH_LINE_T, pair.first ) )
787 lines.emplace_back( line );
790 if( lines.size() > 1 )
796 wxString msg = wxString::Format(
_(
"Label connects more than one wire at %d, %d" ),
797 pair.first.x, pair.first.y );
799 ercItem->SetItems( pair.second.front(), lines[0], lines[1], lines[2] );
800 ercItem->SetErrorMessage( msg );
801 ercItem->SetSheetSpecificPath( sheet );
804 sheet.LastScreen()->Append( marker );
817 auto pinStackAlreadyRepresented =
818 [](
SCH_PIN*
pin, std::vector<SCH_ITEM*>& collection ) ->
bool
822 if( item->Type() ==
SCH_PIN_T && item->GetParentSymbol() ==
pin->GetParentSymbol() )
836 std::map<VECTOR2I, std::vector<SCH_ITEM*>> connMap;
845 std::vector<SCH_ITEM*>& entry = connMap[
pin->GetPosition()];
848 if( pinStackAlreadyRepresented(
pin, entry ) )
851 entry.emplace_back(
pin );
863 connMap[pt].emplace_back( line );
866 for(
const std::pair<
const VECTOR2I, std::vector<SCH_ITEM*>>& pair : connMap )
868 if( pair.second.size() >= 4 )
874 ercItem->SetItems( pair.second[0], pair.second[1], pair.second[2], pair.second[3] );
876 wxString msg = wxString::Format(
_(
"Four items connected at %d, %d" ),
877 pair.first.x, pair.first.y );
878 ercItem->SetErrorMessage( msg );
880 ercItem->SetSheetSpecificPath( sheet );
883 sheet.LastScreen()->Append( marker );
898 std::map<VECTOR2I, std::vector<SCH_ITEM*>> pinMap;
903 if( pinMap.count( pt ) )
904 pinMap[pt].emplace_back( aOther );
914 pinMap[
pin->GetPosition()].emplace_back(
pin );
918 for(
SCH_ITEM* item : sheet.LastScreen()->Items() )
927 addOther(
pin->GetPosition(),
pin );
932 for(
const VECTOR2I& pt : item->GetConnectionPoints() )
933 addOther( pt, item );
937 for(
const std::pair<
const VECTOR2I, std::vector<SCH_ITEM*>>& pair : pinMap )
939 if( pair.second.size() > 1 )
967 ercItem->SetItems( pair.second[0], pair.second[1],
968 pair.second.size() > 2 ? pair.second[2] :
nullptr,
969 pair.second.size() > 3 ? pair.second[3] :
nullptr );
970 ercItem->SetErrorMessage(
_(
"Pin with 'no connection' type is connected" ) );
971 ercItem->SetSheetSpecificPath( sheet );
974 sheet.LastScreen()->Append( marker );
989 using iterator_t = std::vector<ERC_SCH_PIN_CONTEXT>::iterator;
990 std::vector<ERC_SCH_PIN_CONTEXT> pins;
991 std::unordered_map<EDA_ITEM*, SCH_SCREEN*> pinToScreenMap;
992 bool has_noconnect =
false;
997 has_noconnect =
true;
1003 pins.emplace_back(
static_cast<SCH_PIN*
>( item ), subgraph->
GetSheet() );
1009 std::sort( pins.begin(), pins.end(),
1012 int ret = StrNumCmp( lhs.Pin()->GetParentSymbol()->GetRef( &lhs.Sheet() ),
1013 rhs.Pin()->GetParentSymbol()->GetRef( &rhs.Sheet() ) );
1016 ret = StrNumCmp( lhs.Pin()->GetNumber(), rhs.Pin()->GetNumber() );
1026 bool hasDriver =
false;
1027 std::vector<ERC_SCH_PIN_CONTEXT*> pinsNeedingDrivers;
1028 std::vector<ERC_SCH_PIN_CONTEXT*> nonPowerPinsNeedingDrivers;
1033 bool ispowerNet =
false;
1044 std::vector<std::tuple<iterator_t, iterator_t, PIN_ERROR>> pin_mismatches;
1045 std::map<iterator_t, int> pin_mismatch_counts;
1047 for(
auto refIt = pins.begin(); refIt != pins.end(); ++refIt )
1057 pinsNeedingDrivers.push_back( &refPin );
1060 nonPowerPinsNeedingDrivers.push_back( &refPin );
1062 if( !needsDriver.
Pin()
1067 needsDriver = refPin;
1068 needsDriverType = needsDriver.
Pin()->
GetType();
1077 for(
auto testIt = refIt + 1; testIt != pins.end(); ++testIt )
1098 pin_mismatches.emplace_back( std::tuple<iterator_t, iterator_t, PIN_ERROR>{ refIt, testIt,
erc } );
1102 pin_mismatch_counts[refIt] =
m_settings.GetPinTypeWeight( ( *refIt ).Pin()->GetType() );
1103 pin_mismatch_counts[testIt] =
m_settings.GetPinTypeWeight( ( *testIt ).Pin()->GetType() );
1107 if( !pin_mismatch_counts.contains( testIt ) )
1108 pin_mismatch_counts.emplace( testIt, 1 );
1110 pin_mismatch_counts[testIt]++;
1112 if( !pin_mismatch_counts.contains( refIt ) )
1113 pin_mismatch_counts.emplace( refIt, 1 );
1115 pin_mismatch_counts[refIt]++;
1121 std::multimap<size_t, iterator_t, std::greater<size_t>> pins_dsc;
1123 std::transform( pin_mismatch_counts.begin(), pin_mismatch_counts.end(),
1124 std::inserter( pins_dsc, pins_dsc.begin() ),
1127 return std::pair<size_t, iterator_t>( p.second, p.first );
1130 for(
const auto& [amount, pinItBind] : pins_dsc )
1132 auto& pinIt = pinItBind;
1134 if( pin_mismatches.empty() )
1140 iterator_t nearest_pin = pins.end();
1141 double smallest_distance = std::numeric_limits<double>::infinity();
1146 [&](
const auto& tuple )
1150 if( pinIt == std::get<0>( tuple ) )
1151 other = std::get<1>( tuple );
1152 else if( pinIt == std::get<1>( tuple ) )
1153 other = std::get<0>( tuple );
1157 if( ( *pinIt ).Sheet().Cmp( ( *other ).Sheet() ) != 0 )
1159 if( std::isinf( smallest_distance ) )
1161 nearest_pin = other;
1162 erc = std::get<2>( tuple );
1169 if( std::isinf( smallest_distance ) ||
distance < smallest_distance )
1172 nearest_pin = other;
1173 erc = std::get<2>( tuple );
1180 if( nearest_pin != pins.end() )
1182 SCH_PIN* other_pin = ( *nearest_pin ).Pin();
1186 ercItem->SetItems(
pin, other_pin );
1187 ercItem->SetSheetSpecificPath( ( *pinIt ).Sheet() );
1188 ercItem->SetItemsSheetPaths( ( *pinIt ).Sheet(), ( *nearest_pin ).Sheet() );
1190 ercItem->SetErrorMessage( wxString::Format(
_(
"Pins of type %s and %s are connected" ),
1195 pinToScreenMap[
pin]->Append( marker );
1200 if( needsDriver.
Pin() && !hasDriver && !has_noconnect )
1206 std::vector<ERC_SCH_PIN_CONTEXT*> pinsToMark;
1210 if( !nonPowerPinsNeedingDrivers.empty() )
1211 pinsToMark = nonPowerPinsNeedingDrivers;
1213 pinsToMark = pinsNeedingDrivers;
1217 if( !nonPowerPinsNeedingDrivers.empty() )
1218 pinsToMark.push_back( nonPowerPinsNeedingDrivers.front() );
1220 pinsToMark.push_back( &needsDriver );
1227 ercItem->SetItems( pinCtx->Pin() );
1228 ercItem->SetSheetSpecificPath( pinCtx->Sheet() );
1229 ercItem->SetItemsSheetPaths( pinCtx->Sheet() );
1232 pinToScreenMap[pinCtx->Pin()]->Append( marker );
1247 std::unordered_map<wxString, std::pair<wxString, SCH_PIN*>> pinToNetMap;
1251 const wxString& netName = net.first.Name;
1262 if( !
pin->GetParentSymbol()->IsMultiUnit() )
1265 wxString
name =
pin->GetParentSymbol()->GetRef( &sheet ) +
":" +
pin->GetShownNumber();
1267 if( !pinToNetMap.count(
name ) )
1269 pinToNetMap[
name] = std::make_pair( netName,
pin );
1271 else if( pinToNetMap[
name].first != netName )
1275 ercItem->SetErrorMessage( wxString::Format(
_(
"Pin %s is connected to both %s and %s" ),
1276 pin->GetShownNumber(),
1278 pinToNetMap[
name].first ) );
1280 ercItem->SetItems(
pin, pinToNetMap[
name].second );
1281 ercItem->SetSheetSpecificPath( sheet );
1282 ercItem->SetItemsSheetPaths( sheet, sheet );
1316 std::vector<SCH_PIN*> pins = symbol->
GetPins( &sheet );
1318 std::map<wxString, std::vector<std::pair<SCH_PIN*, wxString>>> pinsByNumber;
1323 wxString netName = conn ? conn->
GetNetName() : wxString();
1325 pinsByNumber[
pin->GetNumber()].emplace_back(
pin, netName );
1328 for(
const auto& [pinNumber, pinNetPairs] : pinsByNumber )
1330 if( pinNetPairs.size() < 2 )
1333 wxString firstNet = pinNetPairs[0].second;
1334 bool hasDifferentNets =
false;
1335 SCH_PIN* conflictPin =
nullptr;
1337 for(
size_t i = 1; i < pinNetPairs.size(); i++ )
1339 if( pinNetPairs[i].second != firstNet )
1341 hasDifferentNets =
true;
1342 conflictPin = pinNetPairs[i].first;
1347 if( hasDifferentNets )
1352 msg.Printf(
_(
"Pin %s on symbol '%s' is connected to different nets: %s and %s" ),
1354 symbol->
GetRef( &sheet ),
1355 firstNet.IsEmpty() ?
_(
"<no net>" ) : firstNet,
1356 pinNetPairs[1].second.IsEmpty() ?
_(
"<no net>" ) : pinNetPairs[1].second );
1358 ercItem->SetErrorMessage( msg );
1359 ercItem->SetItems( pinNetPairs[0].first, conflictPin );
1360 ercItem->SetSheetSpecificPath( sheet );
1361 ercItem->SetItemsSheetPaths( sheet, sheet );
1364 pinNetPairs[0].first->GetPosition() );
1365 screen->
Append( marker );
1381 [](
const wxString& txt )
1383 wxString upper = txt.Upper();
1384 return upper.Contains( wxT(
"GND" ) );
1394 bool hasGroundNet =
false;
1395 std::vector<SCH_PIN*> mismatched;
1400 wxString net = conn ? conn->
GetNetName() : wxString();
1401 bool netIsGround = isGround( net );
1411 hasGroundNet =
true;
1413 if( isGround(
pin->GetShownName() ) && !netIsGround )
1414 mismatched.push_back(
pin );
1423 ercItem->SetErrorMessage( wxString::Format(
_(
"Pin %s not connected to ground net" ),
1424 pin->GetShownName() ) );
1425 ercItem->SetItems(
pin );
1426 ercItem->SetSheetSpecificPath( sheet );
1427 ercItem->SetItemsSheetPaths( sheet );
1430 screen->
Append( marker );
1456 pin->GetStackedPinNumbers( &valid );
1461 ercItem->SetItems(
pin );
1462 ercItem->SetSheetSpecificPath( sheet );
1463 ercItem->SetItemsSheetPaths( sheet );
1466 screen->
Append( marker );
1481 std::unordered_map<wxString, std::pair<SCH_ITEM*, SCH_SHEET_PATH>> globalLabels;
1482 std::unordered_map<wxString, std::pair<SCH_ITEM*, SCH_SHEET_PATH>> localLabels;
1497 auto& map = item->Type() ==
SCH_LABEL_T ? localLabels : globalLabels;
1499 if( !map.count(
text ) )
1501 map[
text] = std::make_pair( label, sheet );
1508 for(
auto& [globalText, globalItem] : globalLabels )
1510 for(
auto& [localText, localItem] : localLabels )
1512 if( globalText == localText )
1515 ercItem->SetItems( globalItem.first, localItem.first );
1516 ercItem->SetSheetSpecificPath( globalItem.second );
1517 ercItem->SetItemsSheetPaths( globalItem.second, localItem.second );
1520 globalItem.second.LastScreen()->Append( marker );
1534 std::unordered_map<wxString, std::vector<std::tuple<wxString, SCH_ITEM*, SCH_SHEET_PATH>>> generalMap;
1538 const std::tuple<wxString, SCH_ITEM*, SCH_SHEET_PATH>& other )
1540 auto& [otherText, otherItem, otherSheet] = other;
1560 ercItem->SetItems( item, otherItem );
1561 ercItem->SetSheetSpecificPath( sheet );
1562 ercItem->SetItemsSheetPaths( sheet, otherSheet );
1565 sheet.LastScreen()->Append( marker );
1576 switch( item->Type() )
1583 wxString unnormalized = label->
GetShownText( &sheet,
false );
1584 wxString normalized = unnormalized.Lower();
1586 generalMap[normalized].emplace_back( std::make_tuple( unnormalized, label, sheet ) );
1588 for(
const auto& otherTuple : generalMap.at( normalized ) )
1590 const auto& [otherText, otherItem, otherSheet] = otherTuple;
1592 if( unnormalized != otherText )
1596 && sheet != otherSheet )
1601 logError( normalized, label, sheet, otherTuple );
1612 if( !
pin->IsPower() )
1616 wxString unnormalized = symbol->
GetValue(
true, &sheet,
false );
1617 wxString normalized = unnormalized.Lower();
1619 generalMap[normalized].emplace_back( std::make_tuple( unnormalized,
pin, sheet ) );
1621 for(
const auto& otherTuple : generalMap.at( normalized ) )
1623 const auto& [otherText, otherItem, otherSheet] = otherTuple;
1625 if( unnormalized != otherText )
1627 logError( normalized,
pin, sheet, otherTuple );
1657 std::vector<SCH_MARKER*> markers;
1664 if( !libSymbolInSchematic )
1669 std::optional<const LIBRARY_TABLE_ROW*> optRow =
1672 if( !optRow || ( *optRow )->Disabled() )
1677 ercItem->SetItems( symbol );
1678 msg.Printf(
_(
"The current configuration does not include the symbol library '%s'" ),
1680 ercItem->SetErrorMessage( msg );
1692 std::optional<wxString> uri =
1694 wxCHECK2( uri.has_value(), uri = wxEmptyString );
1695 ercItem->SetItems( symbol );
1696 msg.Printf(
_(
"The symbol library '%s' was not found at '%s'" ),
1698 ercItem->SetErrorMessage( msg );
1709 if( libSymbol ==
nullptr )
1714 ercItem->SetItems( symbol );
1715 msg.Printf(
_(
"Symbol '%s' not found in symbol library '%s'" ),
1718 ercItem->SetErrorMessage( msg );
1726 std::unique_ptr<LIB_SYMBOL> flattenedSymbol = libSymbol->
Flatten();
1735 std::vector<wxString> messages;
1743 if( messages.empty() && flattenedSymbol->Compare( *libSymbolInSchematic, flags ) != 0 )
1746 ercItem->SetItems( symbol );
1747 msg.Printf(
_(
"Symbol '%s' doesn't match copy in library '%s'" ),
1750 ercItem->SetErrorMessage( msg );
1759 screen->Append( marker );
1775 typedef int (*TESTER_FN_PTR)(
const wxString&,
PROJECT* );
1781 std::vector<SCH_MARKER*> markers;
1788 if( footprint.IsEmpty() )
1793 if( fpID.
Parse( footprint,
true ) >= 0 )
1796 msg.Printf(
_(
"'%s' is not a valid footprint identifier" ), footprint );
1797 ercItem->SetErrorMessage( msg );
1798 ercItem->SetItems( symbol );
1805 int ret = (linkTester)( footprint, aProject );
1810 msg.Printf(
_(
"The current configuration does not include the footprint library '%s'" ),
1812 ercItem->SetErrorMessage( msg );
1813 ercItem->SetItems( symbol );
1819 msg.Printf(
_(
"The footprint library '%s' is not enabled in the current configuration" ),
1821 ercItem->SetErrorMessage( msg );
1822 ercItem->SetItems( symbol );
1828 msg.Printf(
_(
"Footprint '%s' not found in library '%s'" ),
1831 ercItem->SetErrorMessage( msg );
1832 ercItem->SetItems( symbol );
1839 sheet.LastScreen()->Append( marker );
1857 std::vector<SCH_MARKER*> markers;
1862 std::unique_ptr<LIB_SYMBOL>& lib_symbol = sch_symbol->
GetLibSymbolRef();
1867 wxArrayString filters = lib_symbol->GetFPFilters();
1869 if( filters.empty() )
1875 if( footprint.
Parse( lowerId ) > 0 )
1881 for( wxString
filter : filters )
1886 if(
filter.Contains( wxS(
":" ) ) )
1887 found |= lowerId.Matches(
filter );
1889 found |= lowerItemName.Matches(
filter );
1898 msg.Printf(
_(
"Assigned footprint (%s) doesn't match footprint filters (%s)" ),
1900 wxJoin( filters,
' ' ) );
1901 ercItem->SetErrorMessage( msg );
1902 ercItem->SetItems( sch_symbol );
1909 sheet.LastScreen()->Append( marker );
1920 const int gridSize =
m_schematic->Settings().m_ConnectionGridSize;
1925 std::vector<SCH_MARKER*> markers;
1927 for(
SCH_ITEM* item : screen->Items() )
1929 if( item->Type() ==
SCH_LINE_T && item->IsConnectable() )
1937 ercItem->SetItems( line );
1945 ercItem->SetItems( line );
1956 if( ( point.x % gridSize ) != 0
1957 || ( point.y % gridSize ) != 0 )
1960 ercItem->SetItems( entry );
1962 markers.emplace_back(
new SCH_MARKER( std::move( ercItem ), point ) );
1977 if( ( pinPos.
x % gridSize ) != 0 || ( pinPos.
y % gridSize ) != 0 )
1980 ercItem->SetItems(
pin );
1982 markers.emplace_back(
new SCH_MARKER( std::move( ercItem ), pinPos ) );
1991 screen->Append( marker );
2005 wxString variant =
m_schematic->GetCurrentVariant();
2009 if( sheet.GetExcludedFromSim( variant ) )
2012 std::vector<SCH_MARKER*> markers;
2036 ercItem->SetErrorMessage( msg );
2037 ercItem->SetItems( symbol );
2045 sheet.LastScreen()->Append( marker );
2063 if( aProgressReporter )
2064 aProgressReporter->
AdvancePhase(
_(
"Checking sheet names..." ) );
2070 if( aProgressReporter )
2071 aProgressReporter->
AdvancePhase(
_(
"Checking conflicts..." ) );
2084 if( aProgressReporter )
2085 aProgressReporter->
AdvancePhase(
_(
"Checking units..." ) );
2090 if( aProgressReporter )
2091 aProgressReporter->
AdvancePhase(
_(
"Checking footprints..." ) );
2104 if( aProgressReporter )
2133 if( aProgressReporter )
2134 aProgressReporter->
AdvancePhase(
_(
"Checking similar labels..." ) );
2141 if( aProgressReporter )
2142 aProgressReporter->
AdvancePhase(
_(
"Checking local and global labels..." ) );
2149 if( aProgressReporter )
2150 aProgressReporter->
AdvancePhase(
_(
"Checking for unresolved variables..." ) );
2157 if( aProgressReporter )
2158 aProgressReporter->
AdvancePhase(
_(
"Checking field names..." ) );
2165 if( aProgressReporter )
2166 aProgressReporter->
AdvancePhase(
_(
"Checking SPICE models..." ) );
2173 if( aProgressReporter )
2174 aProgressReporter->
AdvancePhase(
_(
"Checking no connect pins for connections..." ) );
2182 if( aProgressReporter )
2183 aProgressReporter->
AdvancePhase(
_(
"Checking for library symbol issues..." ) );
2190 if( aProgressReporter )
2191 aProgressReporter->
AdvancePhase(
_(
"Checking for footprint link issues..." ) );
2198 if( aProgressReporter )
2199 aProgressReporter->
AdvancePhase(
_(
"Checking footprint assignments against footprint filters..." ) );
2206 if( aProgressReporter )
2207 aProgressReporter->
AdvancePhase(
_(
"Checking for off grid pins and wires..." ) );
2214 if( aProgressReporter )
2215 aProgressReporter->
AdvancePhase(
_(
"Checking for four way junctions..." ) );
2222 if( aProgressReporter )
2223 aProgressReporter->
AdvancePhase(
_(
"Checking for labels on more than one wire..." ) );
2230 if( aProgressReporter )
2231 aProgressReporter->
AdvancePhase(
_(
"Checking for undefined netclasses..." ) );
constexpr EDA_IU_SCALE schIUScale
static const ADVANCED_CFG & GetCfg()
Get the singleton instance's config, which is shared by all consumers.
constexpr Vec Centre() const
A subgraph is a set of items that are electrically connected on a single sheet.
const std::set< SCH_ITEM * > & GetItems() const
Provide a read-only reference to the items in the subgraph.
const SCH_ITEM * GetNoConnect() const
const SCH_SHEET_PATH & GetSheet() const
Base class to handle basic graphic items.
Store the list of graphic items: rect, lines, polygons and texts to draw/plot the title block and fra...
DS_DRAW_ITEM_BASE * GetFirst()
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.
void SetSheetName(const wxString &aSheetName)
Set the sheet name to draw/plot.
void SetSheetLayer(const wxString &aSheetLayer)
Set the sheet layer to draw/plot.
void SetSheetCount(int aSheetCount)
Set the value of the count of sheets, for basic inscriptions.
void SetPageNumber(const wxString &aPageNumber)
Set the value of the sheet number.
DS_DRAW_ITEM_BASE * GetNext()
void SetProject(const PROJECT *aProject)
const PAGE_INFO & GetPageInfo()
const TITLE_BLOCK & GetTitleBlock()
virtual VECTOR2I GetPosition() const
KICAD_T Type() const
Returns the type of object.
virtual const wxString & GetText() const
Return the string associated with the text object.
EE_TYPE OfType(KICAD_T aType) const
static std::shared_ptr< ERC_ITEM > Create(int aErrorCode)
Constructs an ERC_ITEM for the given error code.
A class used to associate a SCH_PIN with its owning SCH_SHEET_PATH, in order to handle ERC checks acr...
const SCH_SHEET_PATH & Sheet() const
Get the SCH_SHEET_PATH context for the paired SCH_PIN.
SCH_PIN * Pin() const
Get the SCH_PIN for this context.
int TestLibSymbolIssues()
Test symbols for changed library symbols and broken symbol library links.
int TestStackedPinNotation()
Checks for pin numbers that resemble stacked pin notation but are invalid.
void TestTextVars(DS_PROXY_VIEW_ITEM *aDrawingSheet)
Check for any unresolved text variable references.
int TestPinToPin()
Checks the full netlist against the pin-to-pin connectivity requirements.
int TestSimilarLabels()
Checks for labels that differ only in capitalization.
SCH_MULTI_UNIT_REFERENCE_MAP m_refMap
int TestFootprintLinkIssues(KIFACE *aCvPcb, PROJECT *aProject)
Test footprint links against the current footprint libraries.
int TestOffGridEndpoints()
Test pins and wire ends for being off grid.
int TestDuplicateSheetNames(bool aCreateMarker)
Inside a given sheet, one cannot have sheets with duplicate names (file names can be duplicated).
int TestSameLocalGlobalLabel()
Checks for global and local labels with the same name.
int TestMultUnitPinConflicts()
Checks if shared pins on multi-unit symbols have been connected to different nets.
int TestNoConnectPins()
In KiCad 5 and earlier, you could connect stuff up to pins with NC electrical type.
int TestFootprintFilters()
Test symbols to ensure that assigned footprint passes any given footprint filters.
int TestFieldNameWhitespace()
Check for field names with leading or trailing whitespace.
int TestDuplicatePinNets()
Checks if duplicate pin numbers within a symbol are connected to different nets.
ERC_SETTINGS & m_settings
int TestFourWayJunction()
Test to see if there are potentially confusing 4-way junctions in the schematic.
int TestMissingNetclasses()
Tests for netclasses that are referenced but not defined.
int TestSimModelIssues()
Test SPICE models for various issues.
SCH_SHEET_LIST m_sheetList
int TestGroundPins()
Checks for ground-labeled pins not on a ground net while another pin is.
void RunTests(DS_PROXY_VIEW_ITEM *aDrawingSheet, SCH_EDIT_FRAME *aEditFrame, KIFACE *aCvPcb, PROJECT *aProject, PROGRESS_REPORTER *aProgressReporter)
int TestMissingUnits()
Test for uninstantiated units of multi unit symbols.
int TestLabelMultipleWires()
Test to see if there are labels that are connected to more than one wire.
int TestMultiunitFootprints()
Test if all units of each multiunit symbol have the same footprint assigned.
bool IsLibraryLoaded(const wxString &aNickname)
std::optional< wxString > GetFullURI(LIBRARY_TABLE_TYPE aType, const wxString &aNickname, bool aSubstituted=false) const
Return the full location specifying URI for the LIB, either in original UI form or in environment var...
std::optional< LIBRARY_TABLE_ROW * > GetRow(LIBRARY_TABLE_TYPE aType, const wxString &aNickname, LIBRARY_TABLE_SCOPE aScope=LIBRARY_TABLE_SCOPE::BOTH) const
A logical library item identifier and consists of various portions much like a URI.
int Parse(const UTF8 &aId, bool aFix=false)
Parse LIB_ID with the information from aId.
const wxString GetUniStringLibItemName() const
Get strings for display messages in dialogs.
const UTF8 & GetLibItemName() const
const UTF8 & GetLibNickname() const
Return the logical library name portion of a LIB_ID.
Define a library symbol object.
std::vector< const SCH_PIN * > GetGraphicalPins(int aUnit=0, int aBodyStyle=0) const
Graphical pins: Return schematic pin objects as drawn (unexpanded), filtered by unit/body.
void RunOnChildren(const std::function< void(SCH_ITEM *)> &aFunction, RECURSE_MODE aMode) override
int GetUnitCount() const override
std::unique_ptr< LIB_SYMBOL > Flatten() const
Return a flattened symbol inheritance to the caller.
bool GetDuplicatePinNumbersAreJumpers() const
wxString GetUnitDisplayName(int aUnit, bool aLabel) const override
Return the user-defined display name for aUnit for symbols with units.
virtual LIBRARY_MANAGER & GetLibraryManager() const
A progress reporter interface for use in multi-threaded environments.
virtual void AdvancePhase()=0
Use the next available virtual zone of the dialog progress bar.
static SYMBOL_LIBRARY_ADAPTER * SymbolLibAdapter(PROJECT *aProject)
Accessor for project symbol library manager adapter.
Container for project specific data.
virtual bool HasMessage() const
Returns true if any messages were reported.
std::vector< VECTOR2I > GetConnectionPoints() const override
Add all the connection points for this item to aPoints.
Class for a wire to bus entry.
Each graphical item can have a SCH_CONNECTION describing its logical connection (to a bus or net).
wxString GetNetName() const
Schematic editor (Eeschema) main window.
void RecalculateConnections(SCH_COMMIT *aCommit, SCH_CLEANUP_FLAGS aCleanupFlags, PROGRESS_REPORTER *aProgressReporter=nullptr)
Generate the connection data for the entire schematic hierarchy.
wxString GetCanonicalName() const
Get a non-language-specific name for a field which can be used for storage, variable look-up,...
wxString GetShownText(const SCH_SHEET_PATH *aPath, bool aAllowExtraText, int aDepth=0, const wxString &aVariantName=wxEmptyString) const
Base class for any item which can be embedded within the SCHEMATIC container class,...
bool ResolveExcludedFromSim(const SCH_SHEET_PATH *aInstance=nullptr, const wxString &aVariantName=wxEmptyString) const
wxString GetShownText(const SCH_SHEET_PATH *aPath, bool aAllowExtraText, int aDepth=0) const override
std::vector< VECTOR2I > GetConnectionPoints() const override
Add all the connection points for this item to aPoints.
Segment description base class to describe items which have 2 end points (track, wire,...
std::vector< VECTOR2I > GetConnectionPoints() const override
Add all the connection points for this item to aPoints.
VECTOR2I GetEndPoint() const
VECTOR2I GetStartPoint() const
bool IsEndPoint(const VECTOR2I &aPoint) const override
Test if aPt is an end point of this schematic object.
bool IsGraphicLine() const
Return if the line is a graphic (non electrical line)
bool IsStacked(const SCH_PIN *aPin) const
bool IsPower() const
Check if the pin is either a global or local power pin.
ELECTRICAL_PINTYPE GetType() const
Container to create a flattened list of symbols because in a complex hierarchy, a symbol can be used ...
SCH_REFERENCE & GetItem(size_t aIdx)
A helper to define a symbol's reference designator in a schematic.
const SCH_SHEET_PATH & GetSheetPath() const
const wxString GetFootprint() const
SCH_SYMBOL * GetSymbol() const
LIB_SYMBOL * GetLibPart() const
void Append(SCH_ITEM *aItem, bool aUpdateLibSymbol=true)
EE_RTREE & Items()
Get the full RTree, usually for iterating.
const BOX2I GetBoundingBox() const override
Return the orthogonal bounding box of this object for display purposes.
VECTOR2I GetPosition() const override
Handle access to a stack of flattened SCH_SHEET objects by way of a path for creating a flattened sch...
SCH_SCREEN * LastScreen()
void push_back(SCH_SHEET *aSheet)
Forwarded method from std::vector.
Define a sheet pin (label) used in sheets to create hierarchical schematics.
Sheet symbol placed in a schematic, and is the entry point for a sub schematic.
std::vector< SCH_FIELD > & GetFields()
Return a reference to the vector holding the sheet's fields.
VECTOR2I GetPosition() const override
std::vector< SCH_SHEET_PIN * > & GetPins()
wxString GetShownName(bool aAllowExtraText) const
std::vector< const SCH_PIN * > GetPins(const SCH_SHEET_PATH *aSheet) const
Retrieve a list of the SCH_PINs for the given sheet path.
const wxString GetValue(bool aResolve, const SCH_SHEET_PATH *aPath, bool aAllowExtraText, const wxString &aVariantName=wxEmptyString) const override
void GetFields(std::vector< SCH_FIELD * > &aVector, bool aVisibleOnly) const override
Populate a std::vector with SCH_FIELDs, sorted in ordinal order.
const wxString GetFootprintFieldText(bool aResolve, const SCH_SHEET_PATH *aPath, bool aAllowExtraText, const wxString &aVariantName=wxEmptyString) const
VECTOR2I GetPosition() const override
const LIB_ID & GetLibId() const override
std::unique_ptr< LIB_SYMBOL > & GetLibSymbolRef()
const wxString GetRef(const SCH_SHEET_PATH *aSheet, bool aIncludeUnit=false) const override
virtual wxString GetShownText(const RENDER_SETTINGS *aSettings, const SCH_SHEET_PATH *aPath, bool aAllowExtraText, int aDepth=0) const
VECTOR2I GetPosition() const override
const BOX2I GetBoundingBox() const override
Return the orthogonal bounding box of this object for display purposes.
virtual wxString GetShownText(const SCH_SHEET_PATH *aPath, bool aAllowExtraText, int aDepth=0) const
SIM_MODEL & CreateModel(SIM_MODEL::TYPE aType, const std::vector< SCH_PIN * > &aPins, REPORTER &aReporter)
An interface to the global shared library manager that is schematic-specific and linked to one projec...
LIB_SYMBOL * LoadSymbol(const wxString &aNickname, const wxString &aName)
Load a LIB_SYMBOL having aName from the library given by aNickname.
const TRANSFORM & GetTransform() const
double Distance(const VECTOR2< extended_type > &aVector) const
Compute the distance between two vectors.
A wrapper for reporting to a wxString object.
const wxString & GetMessages() const
const wxString ExpandEnvVarSubstitutions(const wxString &aString, const PROJECT *aProject)
Replace any environment variable & text variable references with their values.
#define FOR_ERC_DRC
Expand '${var-name}' templates in text.
void CheckDuplicatePins(LIB_SYMBOL *aSymbol, std::vector< wxString > &aMessages, UNITS_PROVIDER *aUnitsProvider)
const wxString CommentERC_V[]
const wxString CommentERC_H[]
const std::set< ELECTRICAL_PINTYPE > DrivenPinTypes
const std::set< ELECTRICAL_PINTYPE > DrivingPinTypes
const std::set< ELECTRICAL_PINTYPE > DrivingPowerPinTypes
@ ERCE_POWERPIN_NOT_DRIVEN
Power input pin connected to some others pins but no power out pin to drive it.
@ ERCE_SIMILAR_POWER
2 power pins are equal for case insensitive comparisons.
@ ERCE_MISSING_POWER_INPUT_PIN
Symbol has power input pins that are not placed on the schematic.
@ ERCE_GROUND_PIN_NOT_GROUND
A ground-labeled pin is not on a ground net while another pin is.
@ ERCE_SIMILAR_LABELS
2 labels are equal for case insensitive comparisons.
@ ERCE_STACKED_PIN_SYNTAX
Pin name resembles stacked pin notation.
@ ERCE_ENDPOINT_OFF_GRID
Pin or wire-end off grid.
@ ERCE_SAME_LOCAL_GLOBAL_LABEL
2 labels are equal for case insensitive comparisons.
@ ERCE_SIMILAR_LABEL_AND_POWER
label and pin are equal for case insensitive comparisons.
@ ERCE_FOOTPRINT_LINK_ISSUES
The footprint link is invalid, or points to a missing (or inactive) footprint or library.
@ ERCE_DUPLICATE_PIN_ERROR
@ ERCE_DIFFERENT_UNIT_NET
Shared pin in a multi-unit symbol is connected to more than one net.
@ ERCE_FOUR_WAY_JUNCTION
A four-way junction was found.
@ ERCE_UNDEFINED_NETCLASS
A netclass was referenced but not defined.
@ ERCE_UNRESOLVED_VARIABLE
A text variable could not be resolved.
@ ERCE_SIMULATION_MODEL
An error was found in the simulation model.
@ ERCE_LIB_SYMBOL_MISMATCH
Symbol doesn't match copy in library.
@ ERCE_DIFFERENT_UNIT_FP
Different units of the same symbol have different footprints assigned.
@ ERCE_NOCONNECT_CONNECTED
A no connect symbol is connected to more than 1 pin.
@ ERCE_PIN_TO_PIN_WARNING
@ ERCE_PIN_NOT_DRIVEN
Pin connected to some others pins but no pin to drive it.
@ ERCE_MISSING_INPUT_PIN
Symbol has input pins that are not placed.
@ ERCE_MISSING_UNIT
Symbol has units that are not placed on the schematic.
@ ERCE_FIELD_NAME_WHITESPACE
Field name has leading or trailing whitespace.
@ ERCE_DUPLICATE_SHEET_NAME
Duplicate sheet names within a given sheet.
@ ERCE_MISSING_BIDI_PIN
Symbol has bi-directional pins that are not placed.
@ ERCE_LIB_SYMBOL_ISSUES
Symbol not found in active libraries.
@ ERCE_FOOTPRINT_FILTERS
The assigned footprint doesn't match the footprint filters.
@ ERCE_LABEL_MULTIPLE_WIRES
A label is connected to more than one wire.
PIN_ERROR
The values a pin-to-pin entry in the pin matrix can take on.
@ KIFACE_TEST_FOOTPRINT_LINK_LIBRARY_NOT_ENABLED
@ KIFACE_TEST_FOOTPRINT_LINK
@ KIFACE_TEST_FOOTPRINT_LINK_NO_LIBRARY
@ KIFACE_TEST_FOOTPRINT_LINK_NO_FOOTPRINT
PGM_BASE & Pgm()
The global program "get" accessor.
ELECTRICAL_PINTYPE
The symbol library pin object electrical types used in ERC tests.
@ PT_INPUT
usual pin input: must be connected
@ PT_NC
not connected (must be left open)
@ PT_TRISTATE
tri state bus pin
@ PT_BIDI
input or output (like port for a microprocessor)
@ PT_POWER_OUT
output of a regulator: intended to be connected to power input pins
@ PT_POWER_IN
power input (GND, VCC for ICs). Must be connected to a power output.
@ PT_UNSPECIFIED
unknown electrical properties: creates always a warning when connected
@ PT_PASSIVE
pin for passive symbols: must be connected, and can be connected to any pin.
wxString ElectricalPinTypeGetText(ELECTRICAL_PINTYPE)
static float distance(const SFVEC2UI &a, const SFVEC2UI &b)
wxString UnescapeString(const wxString &aSource)
Implement a participant in the KIWAY alchemy.
virtual void * IfaceOrAddress(int aDataId)=0
Return pointer to the requested object.
VECTOR2< int32_t > VECTOR2I