80class ERC_MARKER_PLACER
83 explicit ERC_MARKER_PLACER(
const SCHEMATIC& aSchematic ) :
84 m_schematic( aSchematic )
88 const SCH_SHEET_PATH* Find(
const KIID_PATH& aSheet )
92 m_hierarchy = m_schematic.Hierarchy();
95 for(
const SCH_SHEET_PATH&
path : m_hierarchy )
96 m_paths->emplace(
path.PathRef(), &
path );
99 if(
const auto found = m_paths->find( aSheet ); found != m_paths->end() )
100 return found->second;
102 wxLogTrace(
"KICAD_CONNECTIVITY",
"ERC connectivity references unknown sheet instance %s", aSheet.
AsString() );
106 void Place( std::shared_ptr<ERC_ITEM> aItem,
const KIID_PATH& aSheet,
const VECTOR2I& aPosition,
107 ITEM_PATHS aItemPaths = ITEM_PATHS::NONE,
bool aSheetSpecific =
true )
109 const SCH_SHEET_PATH* sheet = Find( aSheet );
114 if( aItemPaths == ITEM_PATHS::BOTH && aItem->GetAuxItemID() !=
niluuid )
115 aItem->SetItemsSheetPaths( *sheet, *sheet );
116 else if( aItemPaths != ITEM_PATHS::NONE )
117 aItem->SetItemsSheetPaths( *sheet );
119 append( std::move( aItem ), *sheet, aPosition, aSheetSpecific );
122 void Place( std::shared_ptr<ERC_ITEM> aItem,
const KIID_PATH& aSheet,
const VECTOR2I& aPosition,
123 const KIID_PATH& aMainItemSheet,
const KIID_PATH& aAuxItemSheet )
125 const SCH_SHEET_PATH* sheet = Find( aSheet );
126 const SCH_SHEET_PATH*
main = Find( aMainItemSheet );
127 const SCH_SHEET_PATH* aux = Find( aAuxItemSheet );
129 if( !sheet || !
main || !aux )
132 aItem->SetItemsSheetPaths( *
main, *aux );
133 append( std::move( aItem ), *sheet, aPosition );
137 ITEM_PATHS aItemPaths = ITEM_PATHS::NONE,
const wxString& aMessage = wxEmptyString )
140 item->SetItems( aItems );
142 if( !aMessage.empty() )
143 item->SetErrorMessage( aMessage );
145 Place( std::move( item ), aSheet, aPosition, aItemPaths );
148 int Count()
const {
return m_count; }
151 void append( std::shared_ptr<ERC_ITEM> aItem,
const SCH_SHEET_PATH& aSheet,
const VECTOR2I& aPosition,
152 bool aSheetSpecific =
true )
155 aItem->SetSheetSpecificPath( aSheet );
157 aSheet.
LastScreen()->
Append(
new SCH_MARKER( std::move( aItem ), aPosition ) );
162 SCH_SHEET_LIST m_hierarchy;
163 std::optional<std::map<KIID_PATH, const SCH_SHEET_PATH*>> m_paths;
172 std::vector<SCH_CONNECTIVITY::FOOTPRINT_SOURCE>
result;
178 const auto& symbol = *
static_cast<SCH_SYMBOL*
>( item );
179 const auto&
library = symbol.GetLibSymbolRef();
180 result.push_back( {
path.PathRef(), symbol.m_Uuid, symbol.GetPosition(),
189template <
typename LOCATION>
190int reportSourceErrors(
SCHEMATIC& aSchematic,
int aCode,
const std::vector<LOCATION>& aSources )
192 ERC_MARKER_PLACER markers( aSchematic );
194 for(
const auto&
source : aSources )
195 markers.Report( aCode, {
source.item },
source.sheet,
source.position, ITEM_PATHS::MAIN );
197 return markers.Count();
200std::vector<SCH_CONNECTIVITY::NAMED_ITEM> collectNamedItems(
SCHEMATIC& aSchematic,
bool aSimilar )
206 std::vector<SCH_CONNECTIVITY::NAMED_ITEM>
result;
214 for(
SCH_ITEM* item : subgraph->GetItems() )
220 result.push_back( { sheet.
PathRef(), item->m_Uuid, item->GetPosition(),
221 label->GetShownText( &sheet,
FOR_NETNAME ), item->Type(),
229 if( !
pin->IsPower() || !symbol )
244void reportNameConflict( ERC_MARKER_PLACER& aMarkers,
ERC_SETTINGS& aSettings,
ERCE_T aCode,
251 item->SetItems( aMain.
item, aAux.
item );
277 _(
"Bidirectional Pin" ),
278 _(
"Tri-State Pin" ),
281 _(
"Unspecified Pin" ),
282 _(
"Power Input Pin" ),
283 _(
"Power Output Pin" ),
284 _(
"Open Collector" ),
294 _(
"Bidirectional Pin" ),
295 _(
"Tri-State Pin" ),
298 _(
"Unspecified Pin" ),
299 _(
"Power Input Pin" ),
300 _(
"Power Output Pin" ),
301 _(
"Open Collector" ),
340 m_sheetList( aSchematic->BuildSheetListSortedByPageNumbers() ),
342 m_nets( aSchematic->ConnectionGraph()->GetNetMap() ),
357 const auto errors =
m_schematic->Connectivity().Engine().DuplicateSheetNames();
360 for(
const auto& error : errors )
366 return markers.Count();
372 std::vector<SCH_SHEET*> list;
375 list.push_back(
static_cast<SCH_SHEET*
>( item ) );
377 for(
size_t i = 0; i < list.size(); i++ )
381 for(
size_t j = i + 1; j < list.size(); j++ )
388 const wxString variant =
m_schematic->GetCurrentVariant();
389 const wxString
name =
391 const wxString other =
394 if(
name.IsSameAs( other,
false ) )
399 ercItem->SetItems( sheet, test_item );
400 ercItem->SetSheetSpecificPath(
path );
401 ercItem->SetItemsSheetPaths(
path,
path );
424 typedef void ( *PAD_NUMBERS_FN_PTR )(
const wxString&,
PROJECT*, std::set<wxString>& );
426 PAD_NUMBERS_FN_PTR padFetcher =
429 std::map<wxString, std::set<wxString>> padCache;
431 auto getPads = [&](
const wxString& aFootprintId ) ->
const std::set<wxString>&
433 auto it = padCache.find( aFootprintId );
435 if( it != padCache.end() )
438 std::set<wxString>& pads = padCache[aFootprintId];
440 if( padFetcher && !aFootprintId.IsEmpty() )
441 padFetcher( aFootprintId, aProject, pads );
450 std::vector<SCH_CONNECTIVITY::PIN_MAP_FACT> sources;
454 sources =
m_schematic->Connectivity().Engine().PinMapSymbols( screen->ConnectivityId() );
461 sources.push_back( std::move( *
source ) );
465 for(
const auto&
source : sources )
468 const auto& pinNumbers =
source.pinNumbers;
469 const auto& jumperGroups =
source.jumperGroups;
471 auto sharesJumperGroup = [&](
const wxString& aPinA,
const wxString& aPinB )
475 if(
group.Contains( aPinA ) &&
group.Contains( aPinB ) )
488 if( pinNumbers.count( entry.m_PinNumber ) )
492 ercItem->SetItems(
source.id );
493 ercItem->SetErrorMessage(
494 wxString::Format(
_(
"Pin map '%s' references unknown symbol pin '%s'" ), map.GetName(),
495 entry.m_PinNumber ) );
504 std::map<wxString, wxString> padToPin;
510 auto it = padToPin.find(
pad );
512 if( it == padToPin.end() )
514 padToPin[
pad] = entry.m_PinNumber;
516 else if( it->second != entry.m_PinNumber
517 && !sharesJumperGroup( it->second, entry.m_PinNumber ) )
520 ercItem->SetItems(
source.id );
521 ercItem->SetErrorMessage(
522 wxString::Format(
_(
"Symbol pins '%s' and '%s' both map to pad '%s'" ),
523 it->second, entry.m_PinNumber,
pad ) );
532 if( checkBadPad && padFetcher )
550 if( pads.count(
pad ) )
554 ercItem->SetItems(
source.id );
555 ercItem->SetErrorMessage( wxString::Format(
556 _(
"Pin map '%s' references pad '%s' not present on footprint '%s'" ),
570 const wxString& number,
const wxString& footprint )
573 error->SetItems(
pin );
574 error->SetSheetSpecificPath( sheet );
575 error->SetItemsSheetPaths( sheet );
576 error->SetErrorMessage( wxString::Format(
577 _(
"Pin '%s' is connected but maps to no pad on footprint '%s'" ), number, footprint ) );
586 for(
const auto&
pin :
m_schematic->Connectivity().Engine().UnmappedPinCandidates() )
594 footprint.
Parse(
pin.footprint,
true );
598 report( *sheet,
pin.item,
pin.position,
pin.number,
pin.footprint );
619 if( fpText.IsEmpty() || fpId.
Parse( fpText,
true ) >= 0 )
629 if(
pin->IsDangling() )
633 pin->GetEffectivePadNumber( sheet, variant, fpId, &pads, &state );
635 if( state != SCH_PIN::PAD_RESOLUTION::UNMAPPED )
638 report( sheet,
pin->m_Uuid,
pin->GetPosition(),
pin->GetNumber(), fpText );
654 static wxRegEx varRefRegEx( wxT(
"(^|[^\\\\])\\$\\{.*\\}.*" ) );
656 auto reportAssertions =
658 const std::vector<SCH_CONNECTIVITY::TEXT_ASSERTION>& assertions,
const VECTOR2I& pos )
660 for(
const auto& assertion : assertions )
663 wxString
message = assertion.message;
667 ercItem->SetItems( std::vector<KIID>{ item } );
668 ercItem->SetItemsSheetPaths( sheet );
672 message +=
_(
" (in drawing sheet)" );
675 ercItem->SetSheetSpecificPath( sheet );
676 ercItem->SetErrorMessage(
message );
677 screen->Append(
new SCH_MARKER( std::move( ercItem ), pos ) );
680 return !assertions.empty();
699 ?
m_schematic->Connectivity().TextChecks( sheet.PathRef() )
702 for(
const auto&
source : sources )
704 if( reportAssertions(
source.assertionItem, sheet, screen,
source.assertions,
source.assertionPosition ) )
707 if( !varRefRegEx.Matches(
source.shownText ) )
711 ercItem->SetItems( std::vector<KIID>{
source.item } );
712 ercItem->SetSheetSpecificPath( sheet );
713 ercItem->SetItemsSheetPaths( sheet );
719 for(
const auto&
source :
m_schematic->Connectivity().TextChecks( sheet.PathRef(),
true ) )
721 if( reportAssertions(
niluuid, sheet, screen,
source.assertions,
source.assertionPosition ) )
724 if( varRefRegEx.Matches(
source.shownText ) )
727 ercItem->SetErrorMessage(
_(
"Unresolved text variable in drawing sheet" ) );
728 ercItem->SetSheetSpecificPath( sheet );
738 if( reportAssertions(
niluuid, sheet, screen,
740 text->GetPosition() ) )
747 ercItem->SetErrorMessage(
_(
"Unresolved text variable in drawing sheet" ) );
748 ercItem->SetSheetSpecificPath( sheet );
764 m_schematic->Connectivity().Engine().EmptyLabels() );
783 text.Trim(
false ).Trim(
true );
788 ercItem->SetItems( label );
789 ercItem->SetItemsSheetPaths( sheet );
790 ercItem->SetSheetSpecificPath( sheet );
810 const auto errors =
m_schematic->Connectivity().Engine().InvalidFieldNames();
813 for(
const auto& error : errors )
816 error.field.position, ITEM_PATHS::BOTH,
817 wxString::Format(
_(
"Field name has leading or trailing whitespace: '%s'" ),
818 error.field.name ) );
821 return markers.Count();
834 wxString trimmedFieldName = field.GetName();
835 trimmedFieldName.Trim();
836 trimmedFieldName.Trim(
false );
838 if( field.GetName() != trimmedFieldName )
841 ercItem->SetItems( symbol, &field );
842 ercItem->SetItemsSheetPaths( sheet, sheet );
843 ercItem->SetSheetSpecificPath( sheet );
844 ercItem->SetErrorMessage(
846 _(
"Field name has leading or trailing whitespace: '%s'" ),
862 wxString trimmedFieldName = field.GetName();
863 trimmedFieldName.Trim();
864 trimmedFieldName.Trim(
false );
866 if( field.GetName() != trimmedFieldName )
869 ercItem->SetItems( subSheet, &field );
870 ercItem->SetItemsSheetPaths( sheet, sheet );
871 ercItem->SetSheetSpecificPath( sheet );
872 ercItem->SetErrorMessage(
874 _(
"Field name has leading or trailing whitespace: '%s'" ),
894 return m_schematic->Connectivity().Engine().MultiUnitSymbols();
896 std::vector<MULTI_UNIT_GROUP>
result;
898 for(
const auto& [reference, refs] :
m_refMap )
900 if( refs.GetCount() == 0 )
904 group.reference = reference;
907 for(
size_t i = 0; i < refs.GetCount(); ++i )
931 for(
const auto& unit :
group.instances )
933 if( !unit.footprint.IsEmpty() )
944 for(
const auto& unit :
group.instances )
946 if( unit.item == reference->
item && unit.footprint == reference->
footprint
947 && unit.name == reference->
name && unit.sheet < reference->
sheet )
953 for(
const auto& unit :
group.instances )
955 if( unit.footprint.IsEmpty() || unit.footprint == reference->
footprint )
959 error->SetErrorMessage( wxString::Format(
_(
"Different footprints assigned to %s and %s" ),
960 reference->
name, unit.name ) );
961 error->SetItems( std::vector<KIID>{ reference->
item, unit.item } );
962 markers.Place( std::move( error ), unit.sheet, unit.position, reference->
sheet, unit.sheet );
966 return markers.Count();
976 if(
group.instances.empty() )
979 const auto& base =
group.instances.front();
980 std::set<int> placed;
982 for(
const auto& instance :
group.instances )
983 placed.insert( instance.unit );
985 std::set<int> missing;
988 std::set<int> bidirectional;
990 for(
size_t i = 0; i <
group.units.size(); ++i )
992 const int unit =
static_cast<int>( i ) + 1;
994 if( placed.contains( unit ) )
997 missing.insert( unit );
999 if(
group.units[i].powerInput )
1000 power.insert( unit );
1002 if(
group.units[i].input )
1003 input.insert( unit );
1005 if(
group.units[i].bidirectional )
1006 bidirectional.insert( unit );
1010 [&](
const std::set<int>& units,
const wxString&
message,
int code )
1012 if( units.empty() || !
m_settings.IsTestEnabled( code ) )
1015 wxString names = wxS(
"[ " );
1018 for(
int unit : units )
1024 names += wxS(
", " );
1026 names +=
group.units[unit - 1].name;
1029 if( units.size() > 3 )
1030 names += wxS(
", ..." );
1032 names += wxS(
" ]" );
1033 markers.Report( code, { base.item }, base.sheet, base.position, ITEM_PATHS::MAIN,
1037 report( missing,
_(
"Symbol %s has unplaced units %s" ),
1039 report( power,
_(
"Symbol %s has input power pins in units %s that are not placed" ),
1041 report( input,
_(
"Symbol %s has input pins in units %s that are not placed" ),
1043 report( bidirectional,
_(
"Symbol %s has bidirectional pins in units %s that are not placed" ),
1047 return markers.Count();
1054 std::shared_ptr<NET_SETTINGS>& settings =
m_schematic->Project().GetProjectFile().NetSettings();
1055 wxString defaultNetclass = settings->GetDefaultNetclass()->GetName();
1064 ercItem->SetItems( std::vector<KIID>{ item } );
1065 ercItem->SetSheetSpecificPath( sheet );
1066 ercItem->SetItemsSheetPaths( sheet );
1067 ercItem->SetErrorMessage( wxString::Format(
_(
"Netclass %s is not defined" ), netclass ) );
1077 for(
const auto& reference :
m_schematic->Connectivity().Engine().NetclassReferences() )
1079 if( reference.name == defaultNetclass || settings->HasNetclass( reference.name ) )
1082 if(
const SCH_SHEET_PATH* sheet = sheets.Find( reference.sheet ) )
1083 logError( *sheet, reference.item, reference.position, reference.name );
1093 item->RunOnChildren(
1105 if( !netclass.empty()
1106 && !netclass.IsSameAs( defaultNetclass )
1107 && !settings->HasNetclass( netclass ) )
1109 logError( sheet, item->m_Uuid, item->GetPosition(), netclass );
1132 for(
const auto& conflict :
m_schematic->Connectivity().Engine().LabelWireConflicts() )
1134 std::vector<KIID> witnesses{ conflict.label };
1135 witnesses.insert( witnesses.end(), conflict.wires.begin(),
1136 conflict.wires.begin() + std::min<std::ptrdiff_t>( 3, std::ssize( conflict.wires ) ) );
1138 wxString::Format(
_(
"Label connects more than one wire at %d, %d" ),
1139 conflict.position.x, conflict.position.y ) );
1142 return markers.Count();
1147 std::map<VECTOR2I, std::vector<SCH_ITEM*>> connMap;
1154 connMap[pt].emplace_back( label );
1157 for(
const std::pair<
const VECTOR2I, std::vector<SCH_ITEM*>>& pair : connMap )
1159 std::vector<SCH_ITEM*> lines;
1170 lines.emplace_back( line );
1173 if( lines.size() > 1 )
1180 ercItem->SetItems( pair.second.front(), lines[0], lines[1], lines[2] );
1181 ercItem->SetErrorMessage( wxString::Format(
_(
"Label connects more than one wire at %d, %d" ),
1182 pair.first.x, pair.first.y ) );
1183 ercItem->SetSheetSpecificPath( sheet );
1203 for(
const auto& junction :
m_schematic->Connectivity().Engine().FourWayJunctions() )
1206 junction.sheet, junction.position, ITEM_PATHS::NONE,
1207 wxString::Format(
_(
"Four items connected at %d, %d" ),
1208 junction.position.x, junction.position.y ) );
1211 return markers.Count();
1214 auto pinStackAlreadyRepresented =
1215 [](
SCH_PIN*
pin, std::vector<SCH_ITEM*>& collection ) ->
bool
1217 for(
SCH_ITEM*& item : collection )
1219 if( item->Type() ==
SCH_PIN_T && item->GetParentSymbol() ==
pin->GetParentSymbol() )
1233 std::map<VECTOR2I, std::vector<SCH_ITEM*>> connMap;
1242 std::vector<SCH_ITEM*>& entry = connMap[
pin->GetPosition()];
1245 if( pinStackAlreadyRepresented(
pin, entry ) )
1248 entry.emplace_back(
pin );
1260 connMap[pt].emplace_back( line );
1263 for(
const std::pair<
const VECTOR2I, std::vector<SCH_ITEM*>>& pair : connMap )
1265 if( pair.second.size() >= 4 )
1271 ercItem->SetItems( pair.second[0], pair.second[1], pair.second[2], pair.second[3] );
1273 ercItem->SetErrorMessage( wxString::Format(
_(
"Four items connected at %d, %d" ),
1274 pair.first.x, pair.first.y ) );
1276 ercItem->SetSheetSpecificPath( sheet );
1299 for(
const auto& conflict :
m_schematic->Connectivity().Engine().NoConnectPinConflicts() )
1302 const auto witnessPins = std::min<std::ptrdiff_t>( 3, std::ssize( conflict.pins ) );
1303 std::vector<KIID> items( conflict.pins.begin(), conflict.pins.begin() + witnessPins );
1304 const auto witnessOthers = std::min<std::ptrdiff_t>( 4 - witnessPins, std::ssize( conflict.others ) );
1305 items.insert( items.end(), conflict.others.begin(), conflict.others.begin() + witnessOthers );
1307 _(
"Pin with 'no connection' type is connected" ) );
1310 return markers.Count();
1315 std::map<VECTOR2I, std::vector<SCH_ITEM*>> pinMap;
1320 if( pinMap.count( pt ) )
1321 pinMap[pt].emplace_back( aOther );
1331 pinMap[
pin->GetPosition()].emplace_back(
pin );
1344 addOther(
pin->GetPosition(),
pin );
1349 for(
const VECTOR2I& pt : item->GetConnectionPoints() )
1350 addOther( pt, item );
1354 for(
const std::pair<
const VECTOR2I, std::vector<SCH_ITEM*>>& pair : pinMap )
1356 if( pair.second.size() > 1 )
1360 for(
SCH_ITEM* item : pair.second )
1384 ercItem->SetItems( pair.second[0], pair.second[1],
1385 pair.second.size() > 2 ? pair.second[2] :
nullptr,
1386 pair.second.size() > 3 ? pair.second[3] :
nullptr );
1387 ercItem->SetErrorMessage(
_(
"Pin with 'no connection' type is connected" ) );
1388 ercItem->SetSheetSpecificPath( sheet );
1414 std::map<wxString, const SCH_CONNECTIVITY::ERC_PIN_NET*> byName;
1415 std::set<wxString> powerDriven;
1417 ERC_MARKER_PLACER markers( aSchematic );
1420 [](
const PIN& a,
const PIN& b )
1422 int order =
StrNumCmp( a.reference, b.reference );
1425 order =
StrNumCmp( a.pin.number, b.pin.number );
1431 if( a.sheet != b.sheet )
1432 return a.sheet < b.sheet;
1434 return a.pin.id < b.pin.id;
1437 const auto mismatch =
1438 [&](
const PIN& a,
const PIN& b )
1445 const auto reportPair =
1448 std::shared_ptr<ERC_ITEM> item =
ERC_ITEM::Create( ercErrorCode( pinError ) );
1450 item->SetItems( std::vector<KIID>{ a.pin.id, b.pin.id } );
1454 item->SetErrorMessage( wxString::Format(
_(
"Pins of type %s and %s are connected" ),
1460 item->SetErrorMessage( wxString::Format(
_(
"Pins of type %s and %s are connected via "
1466 markers.Place( std::move( item ), a.sheet, a.pin.position, a.sheet, b.sheet );
1469 const auto passiveOrNic =
1484 for(
auto& net : nets )
1486 std::sort( net.pins.begin(), net.pins.end(), less );
1487 byName.emplace( net.name, &net );
1489 if( net.powerDriven )
1490 powerDriven.insert( net.name );
1493 for(
const auto& net : nets )
1495 const std::vector<PIN>& pins = net.pins;
1496 const bool powerNet = std::ranges::any_of( pins,
1501 const PIN* preferred =
nullptr;
1502 std::vector<const PIN*> needsDriver;
1503 std::vector<const PIN*> nonPowerInputs;
1504 std::vector<const PIN*> powerInputs;
1505 std::vector<MISMATCH> mismatches;
1506 std::map<size_t, int> weights;
1507 bool hasDriver = net.powerDriven;
1509 for(
size_t i = 0; i < pins.size(); ++i )
1511 const PIN&
pin = pins[i];
1517 needsDriver.push_back( &
pin );
1519 if( !
pin.pin.globalPower && !
pin.pin.localPower )
1520 nonPowerInputs.push_back( &
pin );
1523 powerInputs.push_back( &
pin );
1526 || ( preferred->pin.invisible && !
pin.pin.invisible )
1534 for(
size_t j = i + 1; j < pins.size(); ++j )
1536 const PIN& other = pins[j];
1537 const bool stacked =
pin.sheet == other.sheet
1538 &&
pin.owner == other.owner
1539 &&
pin.pin.position == other.pin.position
1540 &&
pin.pin.name == other.pin.name
1541 && (
pin.pin.type == other.pin.type
1542 || passiveOrNic(
pin.pin.type )
1543 || passiveOrNic( other.pin.type ) );
1553 mismatches.push_back( { i, j, error } );
1569 std::vector<std::pair<int, size_t>> worst;
1571 for(
const auto& [
index, weight] : weights )
1572 worst.emplace_back( weight,
index );
1574 std::stable_sort( worst.begin(), worst.end(),
1575 [](
const auto& a,
const auto& b )
1577 return a.first > b.first;
1580 for(
const auto& [weight,
index] : worst )
1583 const PIN* nearest =
nullptr;
1585 std::optional<double> nearestDistance;
1587 std::erase_if( mismatches,
1588 [&](
const MISMATCH& candidate )
1590 if( candidate.first !=
index && candidate.second !=
index )
1593 const PIN& other = pins[candidate.first ==
index ? candidate.second : candidate.first];
1596 if( other.sheet !=
pin.sheet )
1598 if( !nearestDistance )
1601 error = candidate.error;
1604 else if(
const double distance =
pin.pin.position.Distance( other.pin.position );
1605 !nearestDistance ||
distance < *nearestDistance )
1609 error = candidate.error;
1616 reportPair(
pin, *nearest, error, wxString() );
1619 if( !preferred || hasDriver || net.noConnect )
1622 bool chainDriver =
false;
1626 for(
const auto&
chain : chains )
1628 if( !
chain || !
chain->GetNets().contains( net.name ) )
1631 chainDriver = std::ranges::any_of(
chain->GetNets(),
1632 [&](
const wxString&
name )
1634 return name != net.name && powerDriven.contains( name );
1645 if( aShowAllErrors )
1647 const auto& selected = powerNet && !powerInputs.empty() ? powerInputs
1648 : !nonPowerInputs.empty() ? nonPowerInputs
1651 for(
const PIN*
pin : selected )
1652 markers.Report( code, {
pin->pin.id },
pin->sheet,
pin->pin.position, ITEM_PATHS::MAIN );
1656 const PIN&
pin = powerNet && !powerInputs.empty() ? *powerInputs.front()
1658 markers.Report( code, {
pin.pin.id },
pin.sheet,
pin.pin.position, ITEM_PATHS::MAIN );
1662 for(
const std::unique_ptr<SCH_NETCHAIN>&
chain : chains )
1670 const wxString* net;
1672 std::vector<CHAIN_PIN> pins;
1674 for(
const wxString&
name :
chain->GetNets() )
1676 const auto net = byName.find(
name );
1678 if( net == byName.end() )
1681 for(
const PIN&
pin : net->second->pins )
1682 pins.push_back( { &
pin, &net->first } );
1685 std::sort( pins.begin(), pins.end(),
1686 [&](
const CHAIN_PIN& a,
const CHAIN_PIN& b )
1688 return less( *a.pin, *b.pin );
1691 for(
size_t i = 0; i < pins.size(); ++i )
1693 for(
size_t j = i + 1; j < pins.size(); ++j )
1695 if( *pins[i].net == *pins[j].net )
1699 reportPair( *pins[i].
pin, *pins[j].
pin, error,
chain->GetName() );
1704 return markers.Count();
1715 std::set<wxString> powerDrivenNets;
1717 if( !
m_schematic->ConnectionGraph()->GetCommittedNetChains().empty() )
1719 for(
const auto& [key, subgraphs] :
m_nets )
1723 for(
SCH_ITEM* item : subgraph->GetItems() )
1731 powerDrivenNets.insert( key.Name );
1740 std::unordered_map<wxString, std::vector<ERC_SCH_PIN_CONTEXT>> netToPins;
1744 using iterator_t = std::vector<ERC_SCH_PIN_CONTEXT>::iterator;
1745 std::vector<ERC_SCH_PIN_CONTEXT> pins;
1746 std::unordered_map<EDA_ITEM*, SCH_SCREEN*> pinToScreenMap;
1747 bool has_noconnect =
false;
1752 has_noconnect =
true;
1758 pins.emplace_back(
static_cast<SCH_PIN*
>( item ), subgraph->
GetSheet() );
1759 netToPins[ net.first.Name ].emplace_back(
static_cast<SCH_PIN*
>( item ), subgraph->
GetSheet() );
1765 std::sort( pins.begin(), pins.end(),
1768 int ret = StrNumCmp( lhs.Pin()->GetParentSymbol()->GetRef( &lhs.Sheet() ),
1769 rhs.Pin()->GetParentSymbol()->GetRef( &rhs.Sheet() ) );
1772 ret = StrNumCmp( lhs.Pin()->GetNumber(), rhs.Pin()->GetNumber() );
1774 return ret != 0 ? ret < 0 : lhs < rhs;
1779 bool hasDriver =
false;
1780 std::vector<ERC_SCH_PIN_CONTEXT*> pinsNeedingDrivers;
1781 std::vector<ERC_SCH_PIN_CONTEXT*> nonPowerPinsNeedingDrivers;
1782 std::vector<ERC_SCH_PIN_CONTEXT*> powerInPinsNeedingDrivers;
1787 bool ispowerNet =
false;
1798 std::vector<std::tuple<iterator_t, iterator_t, PIN_ERROR>> pin_mismatches;
1799 std::map<iterator_t, int> pin_mismatch_counts;
1801 for(
auto refIt = pins.begin(); refIt != pins.end(); ++refIt )
1811 pinsNeedingDrivers.push_back( &refPin );
1814 nonPowerPinsNeedingDrivers.push_back( &refPin );
1817 powerInPinsNeedingDrivers.push_back( &refPin );
1819 if( !needsDriver.
Pin()
1824 needsDriver = refPin;
1825 needsDriverType = needsDriver.
Pin()->
GetType();
1834 for(
auto testIt = refIt + 1; testIt != pins.end(); ++testIt )
1855 pin_mismatches.emplace_back( std::tuple<iterator_t, iterator_t,
1856 PIN_ERROR>{ refIt, testIt, pinError } );
1860 pin_mismatch_counts[refIt] =
m_settings.GetPinTypeWeight( refIt->Pin()->GetType() );
1861 pin_mismatch_counts[testIt] =
m_settings.GetPinTypeWeight( testIt->Pin()->GetType() );
1865 if( !pin_mismatch_counts.contains( testIt ) )
1866 pin_mismatch_counts.emplace( testIt, 1 );
1868 pin_mismatch_counts[testIt]++;
1870 if( !pin_mismatch_counts.contains( refIt ) )
1871 pin_mismatch_counts.emplace( refIt, 1 );
1873 pin_mismatch_counts[refIt]++;
1879 std::multimap<size_t, iterator_t, std::greater<size_t>> pins_dsc;
1881 std::transform( pin_mismatch_counts.begin(), pin_mismatch_counts.end(),
1882 std::inserter( pins_dsc, pins_dsc.begin() ),
1885 return std::pair<size_t, iterator_t>( p.second, p.first );
1888 for(
const auto& [amount, pinItBind] : pins_dsc )
1890 auto& pinIt = pinItBind;
1892 if( pin_mismatches.empty() )
1898 iterator_t nearest_pin = pins.end();
1899 double smallest_distance = std::numeric_limits<double>::infinity();
1904 [&](
const auto& tuple )
1908 if( pinIt == std::get<0>( tuple ) )
1909 other = std::get<1>( tuple );
1910 else if( pinIt == std::get<1>( tuple ) )
1911 other = std::get<0>( tuple );
1915 if( ( *pinIt ).Sheet().Cmp( ( *other ).Sheet() ) != 0 )
1917 if( std::isinf( smallest_distance ) )
1919 nearest_pin = other;
1920 pinError = std::get<2>( tuple );
1927 if( std::isinf( smallest_distance ) ||
distance < smallest_distance )
1930 nearest_pin = other;
1931 pinError = std::get<2>( tuple );
1938 if( nearest_pin != pins.end() )
1940 SCH_PIN* other_pin = nearest_pin->Pin();
1941 std::shared_ptr<ERC_ITEM> ercItem =
ERC_ITEM::Create( ercErrorCode( pinError ) );
1943 ercItem->SetItems(
pin, other_pin );
1944 ercItem->SetSheetSpecificPath( pinIt->Sheet() );
1945 ercItem->SetItemsSheetPaths( pinIt->Sheet(), nearest_pin->Sheet() );
1947 ercItem->SetErrorMessage( wxString::Format(
_(
"Pins of type %s and %s are connected" ),
1952 pinToScreenMap[
pin]->Append( marker );
1957 if( needsDriver.
Pin() && !hasDriver && !has_noconnect )
1965 bool suppressForNetChainDriver =
false;
1969 const wxString& thisNetName = net.first.Name;
1970 const auto& netChains =
m_schematic->ConnectionGraph()->GetCommittedNetChains();
1972 for(
const auto& sig : netChains )
1977 const auto& sigNets = sig->GetNets();
1978 bool containsThisNet = std::find( sigNets.begin(), sigNets.end(), thisNetName ) != sigNets.end();
1980 if( !containsThisNet )
1984 for(
const wxString& otherNet : sigNets )
1986 if( otherNet == thisNetName )
1989 if( powerDrivenNets.contains( otherNet ) )
1991 suppressForNetChainDriver =
true;
2000 if( !suppressForNetChainDriver &&
m_settings.IsTestEnabled( err_code ) )
2002 std::vector<ERC_SCH_PIN_CONTEXT*> pinsToMark;
2011 if( ispowerNet && !powerInPinsNeedingDrivers.empty() )
2012 pinsToMark = powerInPinsNeedingDrivers;
2013 else if( !nonPowerPinsNeedingDrivers.empty() )
2014 pinsToMark = nonPowerPinsNeedingDrivers;
2016 pinsToMark = pinsNeedingDrivers;
2020 if( ispowerNet && !powerInPinsNeedingDrivers.empty() )
2021 pinsToMark.push_back( powerInPinsNeedingDrivers.front() );
2023 pinsToMark.push_back( &needsDriver );
2030 ercItem->SetItems( pinCtx->Pin() );
2031 ercItem->SetSheetSpecificPath( pinCtx->Sheet() );
2032 ercItem->SetItemsSheetPaths( pinCtx->Sheet() );
2035 pinToScreenMap[pinCtx->Pin()]->Append( marker );
2050 auto& netChains =
m_schematic->ConnectionGraph()->GetCommittedNetChains();
2051 wxLogTrace(
traceSchNetChain,
"ERC TestPinToPin: cross-chain phase start chains=%zu",
2054 for(
const auto& sig : netChains )
2059 const wxString chainName = sig->GetName();
2060 const auto& sigNets = sig->GetNets();
2066 const wxString* net;
2068 std::vector<CHAIN_PIN> netChainPins;
2069 netChainPins.reserve( sigNets.size() * 4 );
2071 for(
const wxString& n : sigNets )
2073 auto it = netToPins.find( n );
2074 if( it != netToPins.end() )
2077 netChainPins.push_back( { context, &it->first } );
2081 if( netChainPins.size() < 2 )
2085 "ERC TestPinToPin: chain '%s' nets=%zu collectedPins=%zu",
2086 TO_UTF8( chainName ), sigNets.size(), netChainPins.size() );
2089 std::sort( netChainPins.begin(), netChainPins.end(),
2090 [](
const CHAIN_PIN&
left,
const CHAIN_PIN&
right )
2092 const auto& lhs = left.context;
2093 const auto& rhs = right.context;
2094 int ret = StrNumCmp( lhs.Pin()->GetParentSymbol()->GetRef( &lhs.Sheet() ),
2095 rhs.Pin()->GetParentSymbol()->GetRef( &rhs.Sheet() ) );
2097 ret = StrNumCmp( lhs.Pin()->GetNumber(), rhs.Pin()->GetNumber() );
2098 return ret != 0 ? ret < 0 : lhs < rhs;
2101 for(
size_t i = 0; i < netChainPins.size(); ++i )
2103 const auto& aContext = netChainPins[i].context;
2104 SCH_PIN* aPin = aContext.Pin();
2106 const wxString& aNet = *netChainPins[i].net;
2108 for(
size_t j = i + 1; j < netChainPins.size(); ++j )
2110 const auto& bContext = netChainPins[j].context;
2111 SCH_PIN* bPin = bContext.Pin();
2112 const wxString& bNet = *netChainPins[j].net;
2122 std::shared_ptr<ERC_ITEM> ercItem =
ERC_ITEM::Create( ercErrorCode( pinError ) );
2124 ercItem->SetItems( aPin, bPin );
2125 ercItem->SetSheetSpecificPath( aContext.Sheet() );
2126 ercItem->SetItemsSheetPaths( aContext.Sheet(), bContext.Sheet() );
2127 ercItem->SetErrorMessage( wxString::Format(
_(
"Pins of type %s and %s are connected via "
2133 aContext.Sheet().LastScreen()->Append( marker );
2153 for(
const auto& conflict :
m_schematic->Connectivity().Engine().MultiUnitPinConflicts() )
2156 ercItem->SetErrorMessage( wxString::Format(
_(
"Pin %s is connected to both %s and %s" ),
2159 conflict.firstNet ) );
2160 ercItem->SetItems( std::vector<KIID>{ conflict.other.item, conflict.first.item } );
2161 markers.Place( std::move( ercItem ), conflict.other.sheet, conflict.other.position, conflict.other.sheet,
2162 conflict.first.sheet );
2165 return markers.Count();
2175 std::unordered_map<wxString, std::vector<PIN_ON_NET>> pinToNetMap;
2179 const wxString& netName = net.first.Name;
2190 if( !
pin->GetParentSymbol()->IsMultiUnit() )
2193 wxString
name =
pin->GetParentSymbol()->GetRef( &sheet ) +
":" +
pin->GetShownNumber();
2195 pinToNetMap[
name].push_back( { netName,
pin, sheet } );
2202 std::vector<wxString> conflicted;
2204 for(
const auto& [
name, pins] : pinToNetMap )
2206 for(
const PIN_ON_NET& candidate : pins )
2208 if( candidate.m_netName != pins.front().m_netName )
2210 conflicted.push_back(
name );
2216 std::sort( conflicted.begin(), conflicted.end() );
2218 for(
const wxString&
name : conflicted )
2220 std::vector<PIN_ON_NET> pins = pinToNetMap[
name];
2222 std::sort( pins.begin(), pins.end(),
2223 [](
const PIN_ON_NET& a,
const PIN_ON_NET& b )
2225 if( a.m_netName != b.m_netName )
2226 return a.m_netName < b.m_netName;
2228 return a.m_pin->m_Uuid < b.m_pin->m_Uuid;
2231 const PIN_ON_NET& first = pins.front();
2233 for(
const PIN_ON_NET& other : pins )
2235 if( other.m_netName == first.m_netName )
2240 ercItem->SetErrorMessage( wxString::Format(
_(
"Pin %s is connected to both %s and %s" ),
2241 other.m_pin->GetShownNumber(),
2243 first.m_netName ) );
2245 ercItem->SetItems( other.m_pin, first.m_pin );
2246 ercItem->SetSheetSpecificPath( other.m_sheet );
2247 ercItem->SetItemsSheetPaths( other.m_sheet, first.m_sheet );
2250 other.m_sheet.LastScreen()->Append( marker );
2264 ERC_MARKER_PLACER markers( aSchematic );
2271 ercItem->SetItems(
pin.item );
2272 markers.Place( std::move( ercItem ),
pin.sheet,
pin.position, ITEM_PATHS::MAIN );
2281 ercItem->SetItems( conflict.first, conflict.second );
2282 ercItem->SetErrorMessage( wxString::Format(
_(
"Both %s and %s are attached to the same items; "
2283 "%s will be used in the netlist" ),
2285 conflict.secondName,
2286 conflict.firstName ) );
2287 markers.Place( std::move( ercItem ), conflict.sheet, conflict.position, ITEM_PATHS::BOTH );
2296 ercItem->SetItems( endpoint.item );
2297 ercItem->SetErrorMessage( endpoint.busEntry ?
_(
"Unconnected wire to bus entry" )
2298 :
_(
"Unconnected wire endpoint" ) );
2299 markers.Place( std::move( ercItem ), endpoint.sheet, endpoint.position );
2308 ercItem->SetItems( conflict.net, conflict.bus );
2309 markers.Place( std::move( ercItem ), conflict.sheet, conflict.position );
2318 ercItem->SetItems( conflict.canonical, conflict.other );
2320 if( conflict.mixedShapes )
2321 ercItem->SetErrorMessage(
_(
"Bus vector and bus group are graphically connected" ) );
2323 markers.Place( std::move( ercItem ), conflict.sheet, conflict.position );
2332 ercItem->SetItems( conflict.entry, conflict.bus );
2333 ercItem->SetErrorMessage( wxString::Format(
_(
"Net %s is graphically connected to bus %s but is not a"
2334 " member of that bus" ),
2337 markers.Place( std::move( ercItem ), conflict.sheet, conflict.position );
2350 markers.Report( code,
2353 diagnostic.sheet, diagnostic.position, ITEM_PATHS::MAIN );
2369 const bool mismatch = error.kind == ERROR_KIND::MISSING_LABEL || error.kind == ERROR_KIND::MISSING_PIN;
2376 ercItem->SetItems( std::vector<KIID>{ error.item } );
2379 switch( error.kind )
2381 case ERROR_KIND::ROOT_LABEL:
2382 ercItem->SetErrorMessage( wxString::Format(
_(
"Hierarchical label '%s' in root sheet cannot be "
2383 "connected to non-existent parent sheet" ),
2387 case ERROR_KIND::MISSING_LABEL:
2388 ercItem->SetErrorMessage( wxString::Format(
_(
"Sheet pin %s has no matching hierarchical label "
2389 "inside the sheet" ),
2393 case ERROR_KIND::MISSING_PIN:
2394 ercItem->SetErrorMessage( wxString::Format(
_(
"Hierarchical label %s has no matching sheet pin "
2395 "in the parent sheet" ),
2399 case ERROR_KIND::DANGLING_PIN:
2404 const bool rootLabel = error.kind == ERROR_KIND::ROOT_LABEL;
2405 markers.Place( std::move( ercItem ), error.sheet, error.position,
2406 rootLabel ? ITEM_PATHS::NONE : ITEM_PATHS::MAIN, !rootLabel );
2417 markers.Report( code, { label.item }, label.sheet, label.position );
2442 return markers.Count();
2466 std::vector<SCH_PIN*> pins = symbol->
GetPins( &sheet );
2468 std::map<wxString, std::vector<std::pair<SCH_PIN*, wxString>>> pinsByNumber;
2475 netName =
pin->GetConnectionName( &sheet ).value_or( wxString() );
2477 netName = conn->GetNetName();
2479 pinsByNumber[
pin->GetNumber()].emplace_back(
pin, netName );
2482 for(
const auto& [pinNumber, pinNetPairs] : pinsByNumber )
2484 if( pinNetPairs.size() < 2 )
2487 wxString firstNet = pinNetPairs[0].second;
2488 bool hasDifferentNets =
false;
2489 SCH_PIN* conflictPin =
nullptr;
2491 for(
size_t i = 1; i < pinNetPairs.size(); i++ )
2493 if( pinNetPairs[i].second != firstNet )
2495 hasDifferentNets =
true;
2496 conflictPin = pinNetPairs[i].first;
2501 if( hasDifferentNets )
2506 msg.Printf(
_(
"Pin %s on symbol '%s' is connected to different nets: %s and %s" ),
2508 symbol->
GetRef( &sheet ),
2509 firstNet.IsEmpty() ?
_(
"<no net>" ) : firstNet,
2510 pinNetPairs[1].second.IsEmpty() ?
_(
"<no net>" ) : pinNetPairs[1].second );
2512 ercItem->SetErrorMessage( msg );
2513 ercItem->SetItems( pinNetPairs[0].first, conflictPin );
2514 ercItem->SetSheetSpecificPath( sheet );
2515 ercItem->SetItemsSheetPaths( sheet, sheet );
2517 SCH_MARKER* marker =
new SCH_MARKER( std::move( ercItem ), pinNetPairs[0].first->GetPosition() );
2518 screen->
Append( marker );
2537 for(
const auto& mismatch :
m_schematic->Connectivity().Engine().GroundPinErrors() )
2541 wxString::Format(
_(
"Pin %s not connected to ground net" ), mismatch.name ) );
2544 return markers.Count();
2548 [](
const wxString& txt )
2550 wxString upper = txt.Upper();
2552 return upper.Contains( wxT(
"GND" ) )
2553 || upper == wxT(
"EARTH" )
2554 || upper.StartsWith( wxT(
"EARTH_" ) )
2555 || upper == wxT(
"VSS" )
2556 || upper == wxT(
"VSSA" );
2566 bool hasGroundNet =
false;
2567 std::vector<SCH_PIN*> mismatched;
2579 const wxString net = conn ? conn->
Name(
true ) : wxString();
2580 const bool netIsGround = isGround( net );
2583 hasGroundNet =
true;
2585 if( isGround(
pin->GetShownName() ) && !netIsGround )
2586 mismatched.push_back(
pin );
2595 ercItem->SetErrorMessage( wxString::Format(
_(
"Pin %s not connected to ground net" ),
2596 pin->GetShownName() ) );
2597 ercItem->SetItems(
pin );
2598 ercItem->SetSheetSpecificPath( sheet );
2599 ercItem->SetItemsSheetPaths( sheet );
2602 screen->
Append( marker );
2618 m_schematic->Connectivity().Engine().InvalidPinNotation() );
2634 pin->GetStackedPinNumbers( &valid );
2639 ercItem->SetItems(
pin );
2640 ercItem->SetSheetSpecificPath( sheet );
2641 ercItem->SetItemsSheetPaths( sheet );
2644 screen->
Append( marker );
2658 std::map<wxString, NAMED_ITEM> globalLabels;
2659 std::map<wxString, NAMED_ITEM> localLabels;
2666 auto& labels = item.global ? globalLabels : localLabels;
2667 auto found = labels.find( item.name );
2670 if( found == labels.end()
2671 || item.item < found->second.item
2672 || ( item.item == found->second.item && item.sheet < found->second.sheet ) )
2674 labels[item.name] = item;
2680 for(
const auto& [
name, global] : globalLabels )
2682 const auto local = localLabels.find(
name );
2684 if( local == localLabels.end() )
2689 reportNameConflict( markers,
m_settings, code, global, local->second );
2692 return markers.Count();
2699 std::map<wxString, std::vector<NAMED_ITEM>> generalMap;
2701 auto normalizeLabel =
2702 [](
const wxString& aLabel )
2704 wxString stripped = aLabel.Strip( wxString::leading ).Strip( wxString::trailing );
2711 if( prefix == wxT(
"+" ) )
2712 prefix = wxEmptyString;
2715 units.Replace( wxS(
"µ" ),
'u' );
2716 units.Replace( wxS(
"μ" ),
'u' );
2718 return prefix.Lower() + value.Lower() + units.Lower();
2722 generalMap[normalizeLabel( item.name )].push_back( item );
2726 for(
auto& [
name, entries] : generalMap )
2731 if( a.sheet != b.sheet )
2732 return a.sheet.AsString() < b.sheet.AsString();
2734 return a.item < b.item;
2738 for(
size_t ii = 0; ii < entries.size(); ++ii )
2740 for(
size_t jj = ii + 1; jj < entries.size(); ++jj )
2759 reportNameConflict( markers,
m_settings, code, a, b );
2764 return markers.Count();
2778 struct LIBRARY_ISSUE
2787 std::vector<LIBRARY_ISSUE> issues;
2791 if( !optRow || ( *optRow )->Disabled() )
2796 wxString::Format(
_(
"The current configuration does not include the "
2797 "symbol library '%s'" ),
2810 wxCHECK2( uri.has_value(), uri = wxEmptyString );
2812 wxString::Format(
_(
"The symbol library '%s' was not found at '%s'" ),
2828 wxString::Format(
_(
"Symbol '%s' not found in symbol library '%s'" ),
2840 std::unique_ptr<LIB_SYMBOL> flattenedSymbol = libSymbol->
Flatten();
2841 const int flags =
m_schematic->Settings().SymbolCompareFlags();
2842 bool mismatch =
false;
2854 wxCHECK( aSymbol && aSymbol->GetLibSymbolRef(), issues );
2856 LIB_SYMBOL* embedded = aSymbol->GetLibSymbolRef().get();
2857 std::vector<wxString> messages;
2866 mismatch = messages.empty() && flattenedSymbol->Compare( *embedded, flags ) != 0;
2872 wxString::Format(
_(
"Symbol '%s' doesn't match copy in library '%s'" ),
2882 std::map<std::pair<const SCH_SCREEN*, KIID>, std::vector<LIBRARY_ISSUE>> results;
2887 std::vector<SCH_CONNECTIVITY::LIBRARY_SYMBOL_FACT> sources;
2890 std::vector<const SCH_SYMBOL*> symbols;
2894 sources =
m_schematic->Connectivity().Engine().LibrarySymbols(
path.PathRef() );
2907 symbols.push_back( symbol );
2911 std::vector<SCH_MARKER*> markers;
2913 for(
size_t ii = 0; ii < sources.size(); ++ii )
2915 const auto&
source = sources[ii];
2917 if( !
source.hasEmbeddedSymbol )
2922 if(
result == results.end() )
2924 const SCH_SYMBOL* symbol = captured ? nullptr : symbols[ii];
2925 result = results.emplace( std::make_pair( screen,
source.id ), check(
source, symbol ) ).first;
2928 for(
const LIBRARY_ISSUE& issue :
result->second )
2931 ercItem->SetItems( std::vector<KIID>{
source.id } );
2932 ercItem->SetSheetSpecificPath(
path );
2933 ercItem->SetItemsSheetPaths(
path );
2934 ercItem->SetErrorMessage( issue.message );
2935 markers.emplace_back(
new SCH_MARKER( std::move( ercItem ),
source.position ) );
2941 screen->
Append( marker );
2954 if( std::optional<LIBRARY_MANAGER_ADAPTER*> adapter =
2957 ( *adapter )->BlockUntilLoaded();
2960 typedef int (*TESTER_FN_PTR)(
const wxString&,
PROJECT* );
2967 if(
source.footprint.IsEmpty() )
2975 msg.Printf(
_(
"'%s' is not a valid footprint identifier" ),
source.footprint );
2981 const int ret = linkTester(
source.footprint, aProject );
2985 msg.Printf(
_(
"The current configuration does not include the footprint library '%s'" ),
2990 msg.Printf(
_(
"The footprint library '%s' is not enabled in the current configuration" ),
2995 msg.Printf(
_(
"Footprint '%s' not found in library '%s'" ), fpName, libName );
3007 return markers.Count();
3018 if(
source.filters.empty() )
3021 const wxString lowerId =
source.footprint.Lower();
3025 if( footprint.
Parse( lowerId ) > 0 )
3029 const bool found = std::ranges::any_of(
source.filters,
3030 [&](
const wxString&
filter )
3033 return filter.Contains( wxS(
":" ) ) ? lowerId.Matches( filter.Lower() )
3034 : lowerItemName.Matches( filter.Lower() );
3041 wxString::Format(
_(
"Assigned footprint (%s) doesn't match footprint filters (%s)" ),
3045 return markers.Count();
3058 const int gridSize =
m_schematic->Settings().m_ConnectionGridSize;
3063 std::vector<SCH_MARKER*> markers;
3065 for(
SCH_ITEM* item : screen->Items() )
3067 if( item->Type() ==
SCH_LINE_T && item->IsConnectable() )
3075 ercItem->SetItems( line );
3083 ercItem->SetItems( line );
3094 if( ( point.x % gridSize ) != 0
3095 || ( point.y % gridSize ) != 0 )
3098 ercItem->SetItems( entry );
3100 markers.emplace_back(
new SCH_MARKER( std::move( ercItem ), point ) );
3115 if( ( pinPos.
x % gridSize ) != 0 || ( pinPos.
y % gridSize ) != 0 )
3118 ercItem->SetItems(
pin );
3120 markers.emplace_back(
new SCH_MARKER( std::move( ercItem ), pinPos ) );
3129 screen->Append( marker );
3143 wxString variant =
m_schematic->GetCurrentVariant();
3150 std::vector<SCH_MARKER*> markers;
3152 for(
const auto&
source : sources )
3159 wxString msg =
reporter.GetMessages();
3165 ercItem->SetErrorMessage( msg );
3166 ercItem->SetItems(
source.id );
3167 ercItem->SetSheetSpecificPath( sheet );
3168 ercItem->SetItemsSheetPaths( sheet );
3170 markers.emplace_back(
new SCH_MARKER( std::move( ercItem ),
source.position ) );
3197 std::map<wxString, std::unique_ptr<LIB_SYMBOL>> flatAltCache;
3206 std::vector<SCH_MARKER*> markers;
3207 std::vector<SCH_CONNECTIVITY::VARIANT_SYMBOL_FACT> sources;
3208 std::vector<SCH_CONNECTIVITY::LIBRARY_SYMBOL_FACT> libraries;
3214 if( sources.empty() )
3229 auto& base = libraries.emplace_back();
3234 base.id = symbol->
m_Uuid;
3237 sources.push_back( std::move( *
source ) );
3240 std::sort( libraries.begin(), libraries.end(),
3241 [](
const auto& a,
const auto& b )
3247 for(
const auto&
source : sources )
3249 const auto base = std::lower_bound( libraries.begin(), libraries.end(),
source.id,
3250 [](
const auto& a,
const KIID&
id )
3255 if( base == libraries.end() || base->id !=
source.id )
3259 [&](
int aErrorCode,
const wxString& aMessage )
3263 ercItem->SetItems( std::vector<KIID>{
source.id } );
3264 ercItem->SetSheetSpecificPath( sheet );
3265 ercItem->SetItemsSheetPaths( sheet );
3266 ercItem->SetErrorMessage( aMessage );
3268 markers.emplace_back(
new SCH_MARKER( std::move( ercItem ), base->position ) );
3272 for(
const auto& [variantName, libId] :
source.overrides )
3274 wxString libIdStr = libId.Format();
3277 if( libId == base->library )
3280 auto cacheIt = flatAltCache.find( libIdStr );
3282 if( cacheIt == flatAltCache.end() )
3284 std::unique_ptr<LIB_SYMBOL> flatAlt;
3289 flatAlt = altSymbol->Flatten();
3295 cacheIt = flatAltCache.emplace( libIdStr, std::move( flatAlt ) ).first;
3298 const LIB_SYMBOL* flatAlt = cacheIt->second.get();
3305 wxString::Format(
_(
"Variant '%s': symbol '%s' not found in libraries" ),
3306 variantName, libIdStr ) );
3315 if( !base->hasEmbeddedSymbol )
3318 std::vector<VARIANT_COMPAT_RESULT> issues =
3324 wxString::Format(
_(
"Variant '%s', alternate '%s': %s" ),
3325 variantName, libIdStr, issue.detail ) );
3331 screen->
Append( marker );
3361 m_schematic->RebuildConnectivity(
nullptr, aProgressReporter );
3380 if( aProgressReporter )
3381 aProgressReporter->
AdvancePhase(
_(
"Checking sheet names..." ) );
3390 if( aProgressReporter )
3391 aProgressReporter->
AdvancePhase(
_(
"Checking pin maps..." ) );
3396 if( aProgressReporter )
3397 aProgressReporter->
AdvancePhase(
_(
"Checking conflicts..." ) );
3404 if( aProgressReporter )
3405 aProgressReporter->
AdvancePhase(
_(
"Checking units..." ) );
3410 if( aProgressReporter )
3411 aProgressReporter->
AdvancePhase(
_(
"Checking footprints..." ) );
3424 if( aProgressReporter )
3454 if( aProgressReporter )
3455 aProgressReporter->
AdvancePhase(
_(
"Checking similar labels..." ) );
3463 if( aProgressReporter )
3464 aProgressReporter->
AdvancePhase(
_(
"Checking local and global labels..." ) );
3471 if( aProgressReporter )
3472 aProgressReporter->
AdvancePhase(
_(
"Checking for unresolved variables..." ) );
3479 if( aProgressReporter )
3480 aProgressReporter->
AdvancePhase(
_(
"Checking field names..." ) );
3487 if( aProgressReporter )
3488 aProgressReporter->
AdvancePhase(
_(
"Checking for empty label names..." ) );
3495 if( aProgressReporter )
3496 aProgressReporter->
AdvancePhase(
_(
"Checking SPICE models..." ) );
3503 if( aProgressReporter )
3504 aProgressReporter->
AdvancePhase(
_(
"Checking no connect pins for connections..." ) );
3512 if( aProgressReporter )
3513 aProgressReporter->
AdvancePhase(
_(
"Checking for library symbol issues..." ) );
3520 if( aProgressReporter )
3521 aProgressReporter->
AdvancePhase(
_(
"Checking for footprint link issues..." ) );
3528 if( aProgressReporter )
3529 aProgressReporter->
AdvancePhase(
_(
"Checking footprint assignments against footprint filters..." ) );
3536 if( aProgressReporter )
3537 aProgressReporter->
AdvancePhase(
_(
"Checking for off grid pins and wires..." ) );
3544 if( aProgressReporter )
3545 aProgressReporter->
AdvancePhase(
_(
"Checking for four way junctions..." ) );
3552 if( aProgressReporter )
3553 aProgressReporter->
AdvancePhase(
_(
"Checking for labels on more than one wire..." ) );
3560 if( aProgressReporter )
3561 aProgressReporter->
AdvancePhase(
_(
"Checking for undefined netclasses..." ) );
3569 if( aProgressReporter )
3570 aProgressReporter->
AdvancePhase(
_(
"Checking variant symbols..." ) );
constexpr EDA_IU_SCALE schIUScale
static const ADVANCED_CFG & GetCfg()
Get the singleton instance's config, which is shared by all consumers.
const NET_MAP & GetNetMap() 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()
KICAD_T Type() const
Returns the type of object.
virtual const wxString & GetText() const
Return the string associated with the text object.
EE_TYPE Overlapping(const BOX2I &aRect) const
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.
Container for ERC settings.
bool IsTestEnabled(int aErrorCode) const
ERC_PIN_SORTING_METRIC GetERCSortingMetric() const
Get the type of sorting metric the ERC checker should use to resolve multi-pin errors.
PIN_ERROR GetPinMapValue(int aFirstType, int aSecondType) const
int GetPinTypeWeight(ELECTRICAL_PINTYPE aPinType) const
Get the weight for an electrical pin type.
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.
ERC_TESTER(SCHEMATIC *aSchematic, bool aShowAllErrors=false)
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 TestEmptyLabelNames()
Check for labels with empty or whitespace-only names.
int TestFootprintLinkIssues(KIFACE *aCvPcb, PROJECT *aProject)
Test footprint links against the current footprint libraries.
static int TestConnectivity(SCHEMATIC &aSchematic)
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 TestPinMap(KIFACE *aCvPcb, PROJECT *aProject)
Check pin-to-pad maps (issue #2282): stale pin references, duplicate pad targets, bad pads and unmapp...
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.
std::vector< SCH_CONNECTIVITY::MULTI_UNIT_GROUP > multiUnitSources() const
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 TestVariantSymbols()
Test all variant symbol overrides for resolution and pin compatibility.
int TestMultiunitFootprints()
Test if all units of each multiunit symbol have the same footprint assigned.
Hold an error message and may be used when throwing exceptions containing meaningful error messages.
Represents a group of jumper pins or pads, keyed by name.
wxString AsString() const
bool IsLibraryLoaded(const wxString &aNickname)
std::optional< wxString > GetFullURI(LIBRARY_TABLE_TYPE aType, const wxString &aNickname, bool aSubstituted=false)
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)
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.
wxString GetUniStringLibId() const
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.
const std::vector< ASSOCIATED_FOOTPRINT > & GetEffectiveAssociatedFootprints() const
std::unique_ptr< LIB_SYMBOL > Flatten() const
Return a flattened symbol inheritance to the caller.
bool GetDuplicatePinNumbersAreJumpers() const
virtual LIBRARY_MANAGER & GetLibraryManager() const
A symbol-owned ordered set of named pin maps.
const std::vector< PIN_MAP > & GetAll() const
const PIN_MAP * FindByName(const wxString &aName) const
const std::vector< PIN_MAP_ENTRY > & GetEntries() const
const wxString & GetName() 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.
std::vector< KIID > KIIDS
Holds all the data relating to one schematic.
SCH_CONNECTIVITY::NETCHAIN_MANAGER & NetChains() const
SCH_SHEET_LIST Hierarchy() const
Return the full schematic flattened hierarchical sheet list.
SCH_CONNECTIVITY::FACADE & Connectivity() const
CONNECTION_GRAPH * ConnectionGraph() const
ERC_SETTINGS & ErcSettings() const
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 Name(bool aIgnoreSheet=false) const
std::vector< ERC_PIN_NET > PinNets() const
Active pins for each named net, in net name order.
std::vector< NAMED_ITEM > NamedItems() const
Every label and power pin with its resolved name, on every instance.
std::vector< FOOTPRINT_SOURCE > FootprintSources() const
Resolved footprint and filters of every symbol on every instance.
const ENGINE & Engine() const
const std::vector< std::unique_ptr< SCH_NETCHAIN > > & GetCommittedNetChains() const
Return user-created (committed) net chains (legacy accessor retained under net-chain API).
Schematic editor (Eeschema) main window.
bool RecalculateConnections(SCH_COMMIT *aCommit, SCH_CLEANUP_FLAGS aCleanupFlags, PROGRESS_REPORTER *aProgressReporter=nullptr, bool aCleanupDone=false)
Generate the connection data for the entire schematic hierarchy.
wxString GetUntranslatedName() const
Get the untranslated field name for storage, variable look-up, etc.
wxString GetShownText(const SCH_SHEET_PATH *aPath, RESOLUTION_CONTEXT aContext, const wxString &aVariantName=wxEmptyString, int aDepth=0) const
Base class for any item which can be embedded within the SCHEMATIC container class,...
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)
PAD_RESOLUTION
Outcome of pin-to-pad resolution (issue #2282).
VECTOR2I GetPosition() const override
bool IsStacked(const SCH_PIN *aPin) const
static bool HasIdentityPad(const wxString &aPinNumber, const std::set< wxString > &aPads)
bool IsPower() const
Check if the pin is either a global or local power pin.
ELECTRICAL_PINTYPE GetType() const
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
void Append(SCH_ITEM *aItem, bool aUpdateLibSymbol=true)
EE_RTREE & Items()
Get the full RTree, usually for iterating.
Handle access to a stack of flattened SCH_SHEET objects by way of a path for creating a flattened sch...
const SCH_SHEET * GetSheet(unsigned aIndex) const
SCH_SCREEN * LastScreen()
const KIID_PATH & PathRef() const
Borrow the cached path until this sheet path is modified or destroyed.
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.
SCH_FIELD * GetField(FIELD_T aFieldType)
Return a mandatory field in this sheet.
VECTOR2I GetPosition() const override
const wxString GetFootprintFieldText(const SCH_SHEET_PATH *aPath, RESOLUTION_CONTEXT aContext, const wxString &aVariantName=wxEmptyString) 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.
bool IsGlobalPower() const override
void GetFields(std::vector< SCH_FIELD * > &aVector, bool aVisibleOnly) const override
Populate a std::vector with SCH_FIELDs, sorted in ordinal order.
VECTOR2I GetPosition() const override
const LIB_ID & GetLibId() const override
const wxString GetValue(const SCH_SHEET_PATH *aPath, RESOLUTION_CONTEXT aContext, const wxString &aVariantName=wxEmptyString) const override
std::unique_ptr< LIB_SYMBOL > & GetLibSymbolRef()
const wxString GetRef(const SCH_SHEET_PATH *aSheet, bool aIncludeUnit=false) const override
VECTOR2I GetPosition() const override
SIM_MODEL & CreateModel(SIM_MODEL::TYPE aType, std::span< const wxString > 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.
double Distance(const VECTOR2< extended_type > &aVector) const
Compute the distance between two vectors.
A wrapper for reporting to a wxString object.
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_DRIVER_CONFLICT
Conflicting drivers (labels, etc) on a subgraph.
@ 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_UNCONNECTED_WIRE_ENDPOINT
A label is connected to more than one wire.
@ 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_VARIANT_SYMBOL_INCOMPATIBLE
Variant symbol override fails pin compatibility.
@ ERCE_STACKED_PIN_SYNTAX
Pin name resembles stacked pin notation.
@ ERCE_LABEL_NOT_CONNECTED
Label not connected to any pins.
@ ERCE_ENDPOINT_OFF_GRID
Pin or wire-end off grid.
@ ERCE_EMPTY_LABEL_NAME
Label has an empty or whitespace-only name.
@ ERCE_SAME_LOCAL_GLOBAL_LABEL
2 labels are equal for case insensitive comparisons.
@ ERCE_BUS_TO_BUS_CONFLICT
A connection between bus objects doesn't share at least one net.
@ ERCE_SIMILAR_LABEL_AND_POWER
label and pin are equal for case insensitive comparisons.
@ ERCE_SAME_LOCAL_GLOBAL_POWER
Local power port and global power port have the same name.
@ ERCE_PIN_MAP_BAD_PAD
Pin map references a pad absent from the footprint.
@ ERCE_LABEL_SINGLE_PIN
A label is connected only to a single pin.
@ ERCE_BUS_ENTRY_CONFLICT
A wire connected to a bus doesn't match the bus.
@ ERCE_FOOTPRINT_LINK_ISSUES
The footprint link is invalid, or points to a missing (or inactive) footprint or library.
@ ERCE_PIN_MAP_DUPLICATE_PAD
Two symbol pins map to one pad (not stacked/jumper).
@ ERCE_BUS_TO_NET_CONFLICT
A bus wire is graphically connected to a net port/pin (or vice versa).
@ ERCE_DUPLICATE_PIN_ERROR
@ ERCE_NOCONNECT_NOT_CONNECTED
A no connect symbol is not connected to anything.
@ 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_PIN_NOT_CONNECTED
Pin not connected and not no connect symbol.
@ 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_PIN_MAP_STALE_PIN
Pin map references a pin number not on the symbol.
@ 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_HIERACHICAL_LABEL
Mismatch between hierarchical labels and pins sheets.
@ ERCE_WIRE_DANGLING
Some wires are not connected to anything else.
@ ERCE_VARIANT_SYMBOL_INVALID
Variant symbol override LIB_ID cannot be resolved.
@ ERCE_SINGLE_GLOBAL_LABEL
A label only exists once in the schematic.
@ ERCE_PIN_MAP_UNMAPPED_PIN
A connected pin resolves to no footprint pad.
@ ERCE_LABEL_MULTIPLE_WIRES
A label is connected to more than one wire.
@ ERCE_WIRED_IMPLICIT_POWER
Wired hidden power input also joins its global net by name.
PIN_ERROR
The values a pin-to-pin entry in the pin matrix can take on.
bool m_ConnectivityEngine
Use the schematic connectivity engine instead of CONNECTION_GRAPH.
const wxChar *const traceSchNetChain
Flag to enable tracing of schematic net chain rebuild and ERC cross-chain checks.
#define TO_UTF8(wxstring)
Convert a wxString to a UTF8 encoded C string for all wxWidgets build modes.
@ KIFACE_TEST_FOOTPRINT_LINK_LIBRARY_NOT_ENABLED
@ KIFACE_TEST_FOOTPRINT_LINK
@ KIFACE_TEST_FOOTPRINT_LINK_NO_LIBRARY
@ KIFACE_TEST_FOOTPRINT_LINK_NO_FOOTPRINT
@ KIFACE_FOOTPRINT_PAD_NUMBERS
Function pointer type: void (*)( const wxString& aFootprint, PROJECT* aProject, std::set<wxString>& a...
Value keys and the key session of the schematic connectivity engine.
SOURCE_LOCATION UNCONNECTED_PIN
std::optional< PIN_MAP_FACT > ExtractPinMapFacts(const SCH_SYMBOL &aSymbol)
std::vector< SIMULATION_MODEL_FACT > ExtractSimulationModelFacts(const SCH_SHEET_PATH &aPath, const wxString &aVariantName)
std::vector< TEXT_CHECK_FACT > ExtractTextChecks(const SCH_SCREEN &aScreen, const SCH_SHEET_PATH &aPath)
SOURCE_LOCATION LABEL_LOCATION
LIBRARY_SYMBOL_FACT ExtractLibrarySymbolFact(const LIB_SYMBOL &aSymbol)
std::vector< TEXT_ASSERTION > ExtractTextAssertions(const wxString &aText)
std::optional< VARIANT_SYMBOL_FACT > ExtractVariantSymbolFact(const SCH_SYMBOL &aSymbol, const SCH_SHEET_PATH &aPath)
std::vector< UNIT_FACT > ExtractUnitFacts(const LIB_SYMBOL &aSymbol)
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_NIC
not internally connected (may be connected to anything)
@ 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)
static const std::vector< KICAD_T > labelTypes
int StrNumCmp(const wxString &aString1, const wxString &aString2, bool aIgnoreCase)
Compare two strings with alphanumerical content.
std::vector< wxString > ExpandStackedPinNotation(const wxString &aPinName, bool *aValid)
Expand stacked pin notation like [1,2,3], [1-4], [A1-A4], or [AA1-AA3,AB4,CD12-CD14] into individual ...
wxString UnescapeString(const wxString &aSource)
int SplitString(const wxString &strToSplit, wxString *strBeginning, wxString *strDigits, wxString *strEnd)
Break a string into three parts: he alphabetic preamble, the numeric part, and any alphabetic ending.
Implement a participant in the KIWAY alchemy.
virtual void * IfaceOrAddress(int aDataId)=0
Return pointer to the requested object.
bool duplicatePinNumbersAreJumpers
One symbol-pin to footprint-pad mapping inside a PIN_MAP.
Two bus claims on one island that share no member, or a bus vector joined to a bus group.
A bus wire entry whose net is not a member of the bus it touches.
An island that mixes net and bus items.
Two different strong names on one island.
One active symbol pin on one sheet instance, with the reference of its symbol.
Up to four wires and bus entries of one island that has no driver.
A hierarchical label or sheet pin with no partner, or a dangling sheet pin.
A label that connects to nothing, or to only one pin.
bool HasDuplicatePins() const
bool Matches(const LIBRARY_SYMBOL_FACT &aOther, int aCompareFlags) const
LIB_SYMBOL_ATTRIBUTES attributes
All placed units that share one reference, with the unit table of the library symbol.
One placed unit of an annotated multi-unit symbol.
A label or a power pin with its resolved net name.
A no-connect flag on a net with more than one pin, or on a net with no pin and no label.
One item on one sheet instance, for a diagnostic that needs only a location.
One dangling end of a wire or a bus wire entry.
IbisParser parser & reporter
static std::set< FOOTPRINT * > collectFootprints(const PCB_GROUP *aGroup)
const SHAPE_LINE_CHAIN chain
wxString result
Test unit parsing edge cases and error handling.
wxLogTrace helper definitions.
KICAD_T
The set of class identification values stored in EDA_ITEM::m_structType.
std::vector< VARIANT_COMPAT_RESULT > ValidateVariantSymbolCompatibility(const LIB_SYMBOL &aBase, const LIB_SYMBOL &aCandidate)
Check whether aCandidate can be used as a variant symbol override for aBase.
VECTOR2< int32_t > VECTOR2I