31#include <unordered_map>
32#include <unordered_set>
85 if( !aRawNetName.IsEmpty() && aRawNetName.Find( wxS(
"<NO NET>" ) ) == wxNOT_FOUND )
102static inline wxString
netChainKeyFor(
const wxString& aRawNetName,
long aSubgraphCode )
152 if( old_conn && new_conn )
154 new_conn->
Clone( *old_conn );
202 return pa > pb ? -1 : 1;
209 if( b_in_a && !a_in_b )
212 if( a_in_b && !b_in_a )
221 SYMBOL* parentA =
pinA->GetLibPin() ?
pinA->GetLibPin()->GetParentSymbol() :
nullptr;
227 if( aGlobal != bGlobal )
228 return aGlobal ? -1 : 1;
233 if( aLocal != bLocal )
234 return aLocal ? -1 : 1;
252 bool aLowQuality = aAName.Contains( wxS(
"-Pad" ) );
253 bool bLowQuality = aBName.Contains( wxS(
"-Pad" ) );
255 if( aLowQuality != bLowQuality )
256 return aLowQuality ? 1 : -1;
258 if( aAName < aBName )
261 if( aBName < aAName )
276 std::vector<SCH_ITEM*> candidates;
277 std::set<SCH_ITEM*> strong_drivers;
301 strong_drivers.insert( item );
303 if( item_priority > highest_priority )
306 candidates.push_back( item );
307 highest_priority = item_priority;
309 else if( !candidates.empty() && ( item_priority == highest_priority ) )
311 candidates.push_back( item );
321 if( !candidates.empty() )
331 std::sort( candidates.begin(), candidates.end(), candidate_cmp );
336 if( strong_drivers.size() > 1 )
343 m_drivers.insert( strong_drivers.begin(), strong_drivers.end() );
365 std::set<CONNECTION_SUBGRAPH*>& aSubgraphs )
377 if( aSubgraphs.insert( sg ).second ==
false )
383 aItems.emplace(
m_sheet, item );
397#ifdef CONNECTIVITY_DEBUG
398 wxASSERT_MSG(
false, wxS(
"Tried to get the net name of an item with no connection" ) );
410 std::vector<SCH_ITEM*> labels;
414 switch( item->Type() )
424 labels.push_back( item );
440 std::vector<SCH_ITEM*> labels;
444 switch( item->Type() )
454 labels.push_back( item );
470 switch( aItem->
Type() )
477 return pin->GetDefaultNetName(
m_sheet, forceNoConnect );
504 wxFAIL_MSG( wxS(
"Unhandled item type in GetNameForDriver" ) );
505 return wxEmptyString;
525const std::vector<std::pair<wxString, SCH_ITEM*>>
528 std::vector<std::pair<wxString, SCH_ITEM*>> foundNetclasses;
530 const std::unordered_set<SCH_RULE_AREA*>& ruleAreaCache = aItem->
GetRuleAreaCache();
535 const std::vector<std::pair<wxString, SCH_ITEM*>> ruleAreaNetclasses =
536 ruleArea->GetResolvedNetclasses( &
m_sheet );
538 if( ruleAreaNetclasses.size() > 0 )
540 foundNetclasses.insert( foundNetclasses.end(), ruleAreaNetclasses.begin(),
541 ruleAreaNetclasses.end() );
557 if( netclass != wxEmptyString )
558 foundNetclasses.push_back( { netclass, aItem } );
565 foundNetclasses.begin(), foundNetclasses.end(),
566 [](
const std::pair<wxString, SCH_ITEM*>& i1,
const std::pair<wxString, SCH_ITEM*>& i2 )
568 return i1.first < i2.first;
571 return foundNetclasses;
597 child->m_absorbed_by =
this;
600 set_absorbed_by( subchild );
608 set_absorbed_by( aOther );
658 if(
const std::unique_ptr<LIB_SYMBOL>& part = symbol->GetLibSymbolRef() )
659 return part->GetReferenceField().GetText();
661 return wxEmptyString;
664 switch( aDriver->
Type() )
695 std::back_inserter(
m_items ) );
785 wxCHECK2( aOldItem->
Type() == aNewItem->
Type(),
return );
820 wxCHECK2( oldPins.size() == newPins.size(),
return );
822 for(
size_t ii = 0; ii < oldPins.size(); ii++ )
824 exchange( oldPins[ii], newPins[ii] );
835 if( subgraph->m_graph ==
this )
862 chain->ClearSymbols();
871 std::function<
void(
SCH_ITEM* )>* aChangedItemHandler,
875 PROF_TIMER recalc_time(
"CONNECTION_GRAPH::Recalculate" );
876 monitorTrans.
Start();
881 monitorTrans.
StartSpan(
"updateItemConnectivity",
"" );
882 PROF_TIMER update_items(
"updateItemConnectivity" );
885 std::set<SCH_ITEM*> dirty_items;
887 int count = aSheetList.size() * 2;
892 if( aProgressReporter )
898 std::vector<SCH_ITEM*> items;
901 std::vector<std::pair<SCH_SYMBOL*, int>> symbolsChanged;
903 for(
SCH_ITEM* item : sheet.LastScreen()->Items() )
905 if( item->IsConnectable() && ( aUnconditional || item->IsConnectivityDirty() ) )
907 wxLogTrace(
ConnTrace, wxT(
"Adding item %s to connectivity graph update" ),
908 item->GetTypeDesc() );
909 items.push_back( item );
910 dirty_items.insert( item );
919 if(
pin->IsConnectivityDirty() )
921 dirty_items.insert(
pin );
934 if(
pin->IsConnectivityDirty() )
936 items.push_back(
pin );
937 dirty_items.insert(
pin );
947 if(
pin->IsConnectivityDirty() )
949 items.push_back(
pin );
950 dirty_items.insert(
pin );
963 if( symbol->
GetUnit() != new_unit )
964 symbolsChanged.push_back( { symbol, symbol->
GetUnit() } );
974 if( aProgressReporter )
981 sheet.LastScreen()->TestDanglingEnds( &sheet, aChangedItemHandler );
984 for(
const auto& [ symbol, originalUnit ] : symbolsChanged )
985 symbol->SetUnit( originalUnit );
996 item->SetConnectivityDirty(
false );
1001 update_items.
Show();
1003 PROF_TIMER build_graph(
"buildConnectionGraph" );
1004 monitorTrans.
StartSpan(
"BuildConnectionGraph",
"" );
1023 const std::set<SCH_ITEM*> &aItems )
1025 std::set<std::pair<SCH_SHEET_PATH, SCH_ITEM*>> retvals;
1026 std::set<CONNECTION_SUBGRAPH*> subgraphs;
1031 while( aSubgraph->m_absorbed_by )
1034 wxASSERT( aSubgraph->m_graph == aSubgraph->m_absorbed_by->m_graph );
1035 aSubgraph = aSubgraph->m_absorbed_by;
1039 while( aSubgraph->m_hier_parent )
1042 wxASSERT( aSubgraph->m_graph == aSubgraph->m_hier_parent->m_graph );
1043 aSubgraph = aSubgraph->m_hier_parent;
1047 aSubgraph->getAllConnectedItems( retvals, subgraphs );
1050 auto extract_element = [&](
SCH_ITEM* aItem )
1056 wxLogTrace(
ConnTrace, wxT(
"Item %s not found in connection graph" ),
1057 aItem->GetTypeDesc() );
1063 wxLogTrace(
ConnTrace, wxT(
"Item %s in subgraph %ld (%p) has no driver" ),
1064 aItem->GetTypeDesc(), item_sg->
m_code, item_sg );
1069 if( sg_to_scan.empty() )
1071 wxLogTrace(
ConnTrace, wxT(
"Item %s in subgraph %ld with net %s has no neighbors" ),
1073 sg_to_scan.push_back( item_sg );
1077 wxT(
"Removing all item %s connections from subgraph %ld with net %s: Found "
1080 sg_to_scan.size() );
1084 traverse_subgraph( sg );
1086 for(
auto& bus_it : sg->m_bus_neighbors )
1089 traverse_subgraph( bus_sg );
1092 for(
auto& bus_it : sg->m_bus_parents )
1095 traverse_subgraph( bus_sg );
1109 extract_element(
pin );
1116 extract_element(
pin );
1120 extract_element( item );
1126 for(
const auto& [
path, item] : retvals )
1153 wxLogTrace(
ConnTrace, wxT(
"Removing %zu subgraphs" ), aSubgraphs.size() );
1156 std::set<int> codes_to_remove;
1160 std::sort( el.second.begin(), el.second.end() );
1165 for(
auto& it : sg->m_bus_neighbors )
1171 for(
auto test = parents.begin();
test != parents.end(); )
1179 if( parents.empty() )
1184 for(
auto& it : sg->m_bus_parents )
1190 for(
auto test = neighbors.begin();
test != neighbors.end(); )
1198 if( neighbors.empty() )
1219 auto it = std::lower_bound( el.second.begin(), el.second.end(), sg );
1221 while( it != el.second.end() && *it == sg )
1222 it = el.second.erase( it );
1225 auto remove_sg = [sg](
auto it ) ->
bool
1238 if( remove_sg( it ) )
1246 if( remove_sg( it ) )
1255 if( remove_sg( it ) )
1257 codes_to_remove.insert( it->first.Netcode );
1269 if( remove_sg( it ) )
1277 if( it->second == sg )
1288 if( codes_to_remove.contains( it->second ) )
1296 if( codes_to_remove.contains( it->second ) )
1305 sg->m_graph =
nullptr;
1312 std::map<
VECTOR2I, std::vector<SCH_ITEM*>>& aConnectionMap )
1323 aConn->SetName(
name );
1328 std::map<wxString, std::vector<SCH_PIN*>> pinNumberMap;
1334 updatePin(
pin, conn );
1335 aConnectionMap[
pin->GetPosition() ].push_back(
pin );
1336 pinNumberMap[
pin->GetNumber()].emplace_back(
pin );
1339 auto linkPinsInVec =
1340 [&](
const std::vector<SCH_PIN*>& aVec )
1342 for(
size_t i = 0; i < aVec.size(); ++i )
1344 for(
size_t j = i + 1; j < aVec.size(); ++j )
1346 aVec[i]->AddConnectionTo( aSheet, aVec[j] );
1347 aVec[j]->AddConnectionTo( aSheet, aVec[i] );
1356 for(
const auto& [number,
group] : pinNumberMap )
1357 linkPinsInVec(
group );
1362 std::vector<SCH_PIN*> pins;
1364 for(
const wxString& pinNumber :
group )
1367 pins.emplace_back(
pin );
1370 linkPinsInVec( pins );
1393 std::map<
VECTOR2I, std::vector<SCH_ITEM*>>& aConnectionMap )
1398 m_items.emplace_back( aItem );
1401 switch( aItem->
Type() )
1414 if( points.empty() )
1415 points = {
static_cast<SCH_PIN*
>( aItem )->GetPosition() };
1428 for(
const VECTOR2I& point : points )
1429 aConnectionMap[point].push_back( aItem );
1434 const std::vector<SCH_ITEM*>& aItemList )
1436 wxLogTrace( wxT(
"Updating connectivity for sheet %s with %zu items" ),
1438 std::map<VECTOR2I, std::vector<SCH_ITEM*>> connection_map;
1442 std::vector<VECTOR2I> points = item->GetConnectionPoints();
1443 item->ClearConnectedItems( aSheet );
1448 pin->InitializeConnection( aSheet,
this );
1450 pin->ClearConnectedItems( aSheet );
1452 connection_map[
pin->GetTextPos() ].push_back(
pin );
1469 VECTOR2I point = item->GetPosition();
1472 std::vector<SCH_ITEM*> overlapping_items;
1474 std::copy_if( items.begin(), items.end(), std::back_inserter( overlapping_items ),
1477 return test_item->Type() == SCH_LINE_T
1478 && test_item->HitTest( point, -1 );
1483 if( overlapping_items.size() < 2 )
continue;
1485 for(
SCH_ITEM* test_item : overlapping_items )
1486 connection_map[point].push_back( test_item );
1495 VECTOR2I point = item->GetPosition();
1499 connection_map[point].push_back( wire );
1504 for(
auto& [point, connection_vec] : connection_map )
1506 std::sort( connection_vec.begin(), connection_vec.end() );
1512 for(
SCH_ITEM* connected_item : connection_vec )
1526 if( connection_vec.size() == 1 )
1542 if( point == bus_entry->GetPosition() )
1545 bus_entry->m_connected_bus_items[1] = busLine;
1558 for(
SCH_ITEM* test_item : connection_vec )
1560 bool bus_connection_ok =
true;
1562 if( test_item == connected_item )
1568 if( test_item->GetLayer() ==
LAYER_BUS )
1587 if( connected_item->ConnectionPropagatesTo( test_item )
1588 && test_item->ConnectionPropagatesTo( connected_item )
1589 && bus_connection_ok )
1591 connected_item->AddConnectionTo( aSheet, test_item );
1602 if( !bus_entry->m_connected_bus_item )
1608 bus_entry->m_connected_bus_item = bus;
1619 wxCHECK_RET(
m_schematic, wxS(
"Connection graph cannot be built without schematic pointer" ) );
1623 for(
const std::shared_ptr<BUS_ALIAS>& alias :
m_schematic->GetAllBusAliases() )
1632 std::unordered_map<SCH_SHEET_PATH, size_t> sheetOrder;
1641 auto it = sheetOrder.find( aSheet );
1643 return ( it == sheetOrder.end() ) ? std::numeric_limits<size_t>::max()
1649 std::vector<std::tuple<size_t, SCH_SHEET_PATH, SCH_CONNECTION*>> ordered;
1654 ordered.reserve( item->m_connection_map.size() );
1658 for(
const auto& [sheet, connection] : item->m_connection_map )
1659 ordered.emplace_back( sheetRank( sheet ), sheet, connection );
1661 std::sort( ordered.begin(), ordered.end(),
1662 [](
const auto& a,
const auto& b )
1664 return std::get<0>( a ) < std::get<0>( b );
1667 for(
const auto& [rank, sheet, connection] : ordered )
1669 if( connection->SubgraphCode() == 0 )
1678 connection->SetSubgraphCode( subgraph->
m_code );
1681 std::list<SCH_ITEM*> memberlist;
1686 SCH_CONNECTION* conn = aItem->GetOrInitConnection( sheet,
this );
1692 return ( unique && conn && ( conn->
SubgraphCode() == 0 ) );
1695 std::copy_if( item->ConnectedItems( sheet ).begin(),
1696 item->ConnectedItems( sheet ).end(),
1697 std::back_inserter( memberlist ), get_items );
1699 for(
SCH_ITEM* connected_item : memberlist )
1704 SCH_CONNECTION* connected_conn = connected_item->Connection( &sheet );
1706 wxCHECK2( connected_conn,
continue );
1712 subgraph->
AddItem( connected_item );
1719 if( get_items( citem ) )
1720 memberlist.push_back( citem );
1725 for(
SCH_ITEM* connected_item : memberlist )
1739 std::vector<CONNECTION_SUBGRAPH*> dirty_graphs;
1744 return candidate->m_dirty;
1747 wxLogTrace(
ConnTrace, wxT(
"Resolving drivers for %zu subgraphs" ), dirty_graphs.size() );
1749 std::vector<std::future<size_t>> returns( dirty_graphs.size() );
1751 auto update_lambda =
1754 if( !subgraph->m_dirty )
1758 for(
SCH_ITEM* item : subgraph->m_items )
1760 switch( item->
Type() )
1763 subgraph->m_no_connect = item;
1767 subgraph->m_bus_entry = item;
1775 subgraph->m_no_connect = item;
1785 subgraph->ResolveDrivers(
true );
1786 subgraph->m_dirty =
false;
1793 auto results =
tp.submit_loop( 0, dirty_graphs.size(),
1796 update_lambda( dirty_graphs[ii] );
1805 return candidate->m_driver;
1818 wxString full_name = subgraph->m_driver_connection->Name();
1819 wxString
name = subgraph->m_driver_connection->Name(
true );
1828 wxString prefixOnly = full_name.BeforeFirst(
'[' ) + wxT(
"[]" );
1832 subgraph->m_dirty =
true;
1834 if( subgraph->m_strong_driver )
1836 SCH_ITEM* driver = subgraph->m_driver;
1839 switch( driver->
Type() )
1855 if(
pin->IsGlobalPower() )
1859 else if(
pin->IsLocalPower() )
1866 wxLogTrace(
ConnTrace, wxS(
"Unexpected normal pin %s" ),
1876 wxLogTrace(
ConnTrace, wxS(
"Unexpected strong driver %s" ),
1888 std::vector<CONNECTION_SUBGRAPH*> new_subgraphs;
1892 for(
SCH_ITEM* item : subgraph->GetAllBusLabels() )
1897 dummy.SetGraph(
this );
1900 wxLogTrace(
ConnTrace, wxS(
"new bus label (%s)" ),
1903 for(
const auto& conn :
dummy.Members() )
1906 if( !conn->IsNet() )
1909 wxString
name = conn->FullLocalName();
1916 auto new_conn = std::make_unique<SCH_CONNECTION>( item, subgraph->m_sheet );
1917 new_conn->SetGraph(
this );
1918 new_conn->SetName(
name );
1921 SCH_CONNECTION* new_conn_ptr = subgraph->StoreImplicitConnection( std::move( new_conn ) );
1924 wxLogTrace(
ConnTrace, wxS(
"SG(%ld), Adding full local name (%s) with sg (%d) on subsheet %s" ),
1925 subgraph->m_code,
name, code, subgraph->m_sheet.PathHumanReadable() );
1938 new_subgraphs.push_back( new_sg );
1943 std::copy( new_subgraphs.begin(), new_subgraphs.end(),
1959 [](
const std::pair<SCH_SHEET_PATH, SCH_PIN*>& a,
1960 const std::pair<SCH_SHEET_PATH, SCH_PIN*>& b )
1962 int pathCmp = a.first.Cmp( b.first );
1967 const SCH_SYMBOL* symA = static_cast<const SCH_SYMBOL*>( a.second->GetParentSymbol() );
1968 const SCH_SYMBOL* symB = static_cast<const SCH_SYMBOL*>( b.second->GetParentSymbol() );
1970 wxString refA = symA ? symA->GetRef( &a.first, false ) : wxString();
1971 wxString refB = symB ? symB->GetRef( &b.first, false ) : wxString();
1973 int refCmp = refA.Cmp( refB );
1978 return a.second->GetNumber().Cmp( b.second->GetNumber() ) < 0;
1981 std::unordered_map<int, CONNECTION_SUBGRAPH*> global_power_pin_subgraphs;
1985 SYMBOL* libParent =
pin->GetLibPin() ?
pin->GetLibPin()->GetParentSymbol() :
nullptr;
1987 if( !
pin->ConnectedItems( sheet ).empty()
2004 connection->
SetName(
pin->GetParentSymbol()->GetValue(
true, &sheet,
false ) );
2013 auto jj = global_power_pin_subgraphs.find( code );
2015 if( jj != global_power_pin_subgraphs.end() )
2017 subgraph = jj->second;
2035 global_power_pin_subgraphs[code] = subgraph;
2052 std::unordered_set<CONNECTION_SUBGRAPH*> invalidated_subgraphs;
2056 if( subgraph->m_absorbed )
2061 wxString
name = connection->
Name();
2064 unsigned suffix = 1;
2066 auto create_new_name =
2070 wxString suffixStr = std::to_wstring( suffix );
2077 wxString prefix = aConn->BusPrefix();
2079 if( prefix.empty() )
2080 prefix = wxT(
"BUS" );
2085 wxString members = aConn->Name().Mid( aConn->BusPrefix().length() );
2087 newName << prefix << wxT(
"_" ) << suffixStr << members;
2089 aConn->ConfigureFromLabel( newName );
2093 newName << aConn->Name() << wxT(
"_" ) << suffixStr;
2094 aConn->SetSuffix( wxString( wxT(
"_" ) ) << suffixStr );
2101 if( !subgraph->m_strong_driver )
2103 std::vector<CONNECTION_SUBGRAPH*> vec_empty;
2104 std::vector<CONNECTION_SUBGRAPH*>* vec = &vec_empty;
2113 wxString prefixOnly =
name.BeforeFirst(
'[' ) + wxT(
"[]" );
2119 if( vec->size() > 1 )
2121 wxString new_name = create_new_name( connection );
2124 new_name = create_new_name( connection );
2126 wxLogTrace(
ConnTrace, wxS(
"%ld (%s) is weakly driven and not unique. Changing to %s." ),
2127 subgraph->m_code,
name, new_name );
2129 std::erase( *vec, subgraph );
2135 else if( subgraph->m_driver )
2147 bool conflict =
false;
2148 wxString global_name = connection->
Name(
true );
2155 std::vector<CONNECTION_SUBGRAPH*>& candidates = kk->second;
2159 if( candidate->m_sheet == sheet )
2166 wxLogTrace(
ConnTrace, wxS(
"%ld (%s) skipped for promotion due to potential conflict" ),
2167 subgraph->m_code,
name );
2173 wxLogTrace(
ConnTrace, wxS(
"%ld (%s) weakly driven by unique sheet pin %s, promoting" ),
2174 subgraph->m_code,
name,
2175 subgraph->m_driver->GetItemDescription( &unitsProvider,
true ) );
2177 subgraph->m_strong_driver =
true;
2184 if( connection->
IsBus() )
2208 subgraph->m_dirty =
true;
2216 if( !subgraph->m_strong_driver )
2223 std::vector<CONNECTION_SUBGRAPH*> candidate_subgraphs;
2226 std::back_inserter( candidate_subgraphs ),
2229 return ( !candidate->m_absorbed &&
2230 candidate->m_strong_driver &&
2231 candidate != subgraph );
2237 std::vector< std::shared_ptr<SCH_CONNECTION> > connections_to_check;
2240 connections_to_check.push_back( std::make_shared<SCH_CONNECTION>( *connection ) );
2242 auto add_connections_to_check =
2245 for(
SCH_ITEM* possible_driver : aSubgraph->m_items )
2247 if( possible_driver == aSubgraph->m_driver )
2254 if( c->Type() != aSubgraph->m_driver_connection->Type() )
2257 if( c->Name(
true ) == aSubgraph->m_driver_connection->Name(
true ) )
2260 connections_to_check.push_back( c );
2261 wxLogTrace(
ConnTrace, wxS(
"%lu (%s): Adding secondary driver %s" ),
2263 aSubgraph->m_driver_connection->Name(
true ),
2272 add_connections_to_check( subgraph );
2274 std::set<SCH_CONNECTION*> checked_connections;
2276 for(
unsigned i = 0; i < connections_to_check.size(); i++ )
2278 auto member = connections_to_check[i];
2281 if( !checked_connections.insert( member.get() ).second )
2284 if( member->IsBus() )
2286 connections_to_check.insert( connections_to_check.end(),
2287 member->Members().begin(),
2288 member->Members().end() );
2291 wxString test_name = member->Name(
true );
2295 if( candidate->
m_absorbed || candidate == subgraph )
2311 if( driver == candidate->
m_driver )
2323 &&
pin->GetDefaultNetName( sheet ) == test_name )
2336 if( subgraph->GetNameForDriver( driver ) == test_name )
2349 wxLogTrace(
ConnTrace, wxS(
"%lu (%s) has bus child %lu (%s)" ),
2350 subgraph->m_code, connection->
Name(),
2351 candidate->
m_code, member->Name() );
2353 subgraph->m_bus_neighbors[member].insert( candidate );
2356 else if( ( !connection->
IsBus()
2360 wxLogTrace(
ConnTrace, wxS(
"%lu (%s) absorbs neighbor %lu (%s)" ),
2361 subgraph->m_code, connection->
Name(),
2365 add_connections_to_check( candidate );
2367 subgraph->Absorb( candidate );
2368 invalidated_subgraphs.insert( subgraph );
2378 if( subgraph->m_absorbed )
2381 if( !subgraph->ResolveDrivers() )
2384 if( subgraph->m_driver_connection->IsBus() )
2389 wxLogTrace(
ConnTrace, wxS(
"Re-resolving drivers for %lu (%s)" ),
2390 subgraph->m_code, subgraph->m_driver_connection->Name() );
2409 bool aUnconditional )
2412 wxCHECK_RET(
m_schematic, wxT(
"Connection graph cannot be built without schematic pointer" ) );
2416 for(
const std::shared_ptr<BUS_ALIAS>& alias :
m_schematic->GetAllBusAliases() )
2422 PROF_TIMER sub_graph(
"buildItemSubGraphs" );
2441 PROF_TIMER proc_sub_graph(
"ProcessSubGraphs" );
2445 proc_sub_graph.
Show();
2454 std::vector<CONNECTION_SUBGRAPH*> global_subgraphs;
2456 std::back_inserter( global_subgraphs ),
2459 return !candidate->m_local_driver;
2473 m_driver_subgraphs[ii]->UpdateItemConnections();
2495 if( !global_subgraphs.empty() )
2497 std::unordered_map<CONNECTION_SUBGRAPH*, CONNECTION_SUBGRAPH*> sg_root;
2506 auto it = sg_root.find( cur );
2508 if( it == sg_root.end() || it->second == cur )
2513 auto parent_it = sg_root.find( it->second );
2515 if( parent_it != sg_root.end() && parent_it->second != it->second )
2516 it->second = parent_it->second;
2526 auto prefer_as_representative =
2531 aB->m_driver, aB->m_driver_connection,
2532 aB->m_driver_connection->Name() ) < 0;
2538 sg_root.try_emplace( aA, aA );
2539 sg_root.try_emplace( aB, aB );
2544 if( root_a == root_b )
2547 if( prefer_as_representative( root_a, root_b ) )
2548 sg_root[root_b] = root_a;
2550 sg_root[root_a] = root_b;
2553 std::unordered_map<wxString, std::vector<CONNECTION_SUBGRAPH*>> name_to_sgs;
2557 for(
SCH_ITEM* driver : subgraph->m_drivers )
2565 name_to_sgs[subgraph->GetNameForDriver( driver )].push_back( subgraph );
2569 for(
auto& [
name, sgs] : name_to_sgs )
2571 if( sgs.size() < 2 )
2574 for(
size_t ii = 1; ii < sgs.size(); ++ii )
2575 union_sgs( sgs[0], sgs[ii] );
2581 for(
const auto& entry : sg_root )
2592 wxLogTrace(
ConnTrace, wxS(
"Global %lu (%s) canonicalized to %lu (%s)" ),
2605 if( !subgraph->m_dirty )
2608 wxLogTrace(
ConnTrace, wxS(
"Processing %lu (%s) for propagation" ),
2609 subgraph->m_code, subgraph->m_driver_connection->Name() );
2615 if( !subgraph->m_local_driver && subgraph->m_multiple_drivers )
2617 for(
SCH_ITEM* driver : subgraph->m_drivers )
2619 if( driver == subgraph->m_driver )
2622 const wxString& secondary_name = subgraph->GetNameForDriver( driver );
2624 if( secondary_name == subgraph->m_driver_connection->Name() )
2632 if( candidate == subgraph )
2635 if( !secondary_is_global && candidate->
m_sheet != subgraph->m_sheet )
2642 wxLogTrace(
ConnTrace, wxS(
"Global %lu (%s) promoted to %s" ),
2644 subgraph->m_driver_connection->Name() );
2666 if( subgraph->m_dirty )
2683 wxASSERT_MSG( !subgraph->m_dirty,
2684 wxS(
"Subgraph not processed by propagateToNeighbors!" ) );
2686 if( subgraph->m_bus_parents.size() < 2 )
2691 wxLogTrace(
ConnTrace, wxS(
"%lu (%s) has multiple bus parents" ),
2692 subgraph->m_code, conn->
Name() );
2695 wxCHECK2( conn->
IsNet(),
continue );
2697 for(
const auto& ii : subgraph->m_bus_parents )
2710 wxLogTrace(
ConnTrace, wxS(
"Warning: could not match %s inside %lu (%s)" ),
2715 if( conn->
Name() != match->
Name() )
2717 wxString old_name = match->
Name();
2719 wxLogTrace(
ConnTrace, wxS(
"Updating %lu (%s) member %s to %s" ),
2722 match->
Clone( *conn );
2730 std::vector<CONNECTION_SUBGRAPH*> old_subgraphs = jj->second;
2734 while( old_sg->m_absorbed )
2735 old_sg = old_sg->m_absorbed_by;
2737 wxString old_sg_name = old_sg->m_driver_connection->Name();
2738 old_sg->m_driver_connection->Clone( *conn );
2740 if( old_sg_name != old_sg->m_driver_connection->Name() )
2751 auto propagateConnectionsTask =
2755 if( !subgraph->m_strong_driver
2756 && subgraph->m_drivers.size() == 1
2757 && subgraph->m_driver->Type() ==
SCH_PIN_T )
2760 wxString
name =
pin->GetDefaultNetName( subgraph->m_sheet,
true );
2762 subgraph->m_driver_connection->ConfigureFromLabel(
name );
2765 subgraph->m_dirty =
false;
2766 subgraph->UpdateItemConnections();
2772 propagateConnectionsTask( m_driver_subgraphs[ii] );
2781 if( subgraph->m_driver_connection->IsBus() )
2784 if( !subgraph->m_driver || subgraph->m_driver->Type() !=
SCH_SHEET_PIN_T )
2793 wxString pinText =
pin->GetShownText(
false );
2800 if( label->
GetShownText( &subgraph->m_sheet,
false ) == pinText )
2803 path.push_back( sheet );
2807 if( parent_conn && parent_conn->
IsBus() )
2821 subgraph->m_driver_connection->NetCode() };
2827 std::shared_ptr<NET_SETTINGS>& netSettings =
m_schematic->Project().GetProjectFile().m_NetSettings;
2828 std::map<wxString, std::set<wxString>> oldAssignments = netSettings->GetNetclassLabelAssignments();
2829 std::set<wxString> affectedNetclassNetAssignments;
2831 netSettings->ClearNetclassLabelAssignments();
2833 auto dirtySubgraphs =
2834 [&](
const std::vector<CONNECTION_SUBGRAPH*>& subgraphs )
2836 if( aChangedItemHandler )
2840 for(
SCH_ITEM* item : subgraph->m_items )
2841 (*aChangedItemHandler)( item );
2846 auto checkNetclassDrivers =
2847 [&](
const wxString& netName,
const std::vector<CONNECTION_SUBGRAPH*>& subgraphs )
2849 wxCHECK_RET( !subgraphs.empty(), wxS(
"Invalid empty subgraph" ) );
2851 std::set<wxString> netclasses;
2856 for(
SCH_ITEM* item : subgraph->m_items )
2858 for(
const auto& [
name, provider] : subgraph->GetNetclassesForDriver( item ) )
2859 netclasses.insert(
name );
2866 if( subgraph->m_driver_connection->IsBus() )
2868 auto processBusMember = [&,
this](
const SCH_CONNECTION* member )
2870 if( !netclasses.empty() )
2872 netSettings->AppendNetclassLabelAssignment( member->Name(), netclasses );
2877 if( oldAssignments.count( member->Name() ) )
2879 if( oldAssignments[member->Name()] != netclasses )
2881 affectedNetclassNetAssignments.insert( member->Name() );
2884 dirtySubgraphs( ii->second );
2887 else if( !netclasses.empty() )
2889 affectedNetclassNetAssignments.insert( member->Name() );
2892 dirtySubgraphs( ii->second );
2896 for(
const std::shared_ptr<SCH_CONNECTION>& member : subgraph->m_driver_connection->Members() )
2900 if( member->IsBus() )
2902 for(
const std::shared_ptr<SCH_CONNECTION>& nestedMember : member->Members() )
2903 processBusMember( nestedMember.get() );
2907 processBusMember( member.get() );
2914 if( !netclasses.empty() )
2916 netSettings->AppendNetclassLabelAssignment( netName, netclasses );
2919 if( oldAssignments.count( netName ) )
2921 if( oldAssignments[netName] != netclasses )
2923 affectedNetclassNetAssignments.insert( netName );
2924 dirtySubgraphs( subgraphs );
2927 else if( !netclasses.empty() )
2929 affectedNetclassNetAssignments.insert( netName );
2930 dirtySubgraphs( subgraphs );
2936 checkNetclassDrivers( netname, subgraphs );
2938 if( !aUnconditional )
2940 for(
auto& [netname, netclasses] : oldAssignments )
2942 if( netSettings->GetNetclassLabelAssignments().count( netname )
2943 || affectedNetclassNetAssignments.count( netname ) )
2948 netSettings->SetNetclassLabelAssignment( netname, netclasses );
2968 auto getSubgraphNet = [&](
SCH_PIN* aPin ) -> wxString
2981 result.edges.reserve( 256 );
2990 auto findWireOnScreen = [&](
SCH_PIN* aPin,
SCH_LINE*& aWire ) ->
bool
2994 auto consider = [&](
SCH_ITEM* cand ) ->
bool
3007 if( s.
y == e.
y && p.
y == s.
y )
3009 int minx = std::min( s.
x, e.
x );
3010 int maxx = std::max( s.
x, e.
x );
3012 if( p.
x >= minx && p.
x <= maxx )
3018 else if( s.
x == e.
x && p.
x == s.
x )
3020 int miny = std::min( s.
y, e.
y );
3021 int maxy = std::max( s.
y, e.
y );
3023 if( p.
y >= miny && p.
y <= maxy )
3047 std::vector<SCH_PIN*> pins = symbol->
GetPins( &sheetPath );
3049 if( pins.size() != 2 )
3058 if( !findWireOnScreen( pins[0], wireA ) || !findWireOnScreen( pins[1], wireB ) )
3069 if( pins[0]->IsPower() || pins[1]->IsPower() )
3077 if( aS.
x == aE.
x && bS.
x == bE.
x && aS.
x == bS.
x )
3079 else if( aS.
y == aE.
y && bS.
y == bE.
y && aS.
y == bS.
y )
3086 wxString netA = getSubgraphNet( pins[0] );
3087 wxString netB = getSubgraphNet( pins[1] );
3089 if( netA.IsEmpty() || netB.IsEmpty() || netA == netB )
3092 result.edges.push_back( { netA, netB, symbol } );
3100 std::set<long> powerSubgraphs;
3101 std::map<wxString, long> netToCode;
3113 std::vector<SCH_PIN*> pins = sym->
GetPins( &sheetPath );
3119 netToCode[
netChainKeyFor( sg->GetNetName(), sg->m_code )] = sg->m_code;
3122 || ( p->GetParentSymbol() && p->GetParentSymbol()->IsPower() ) )
3124 powerSubgraphs.insert( sg->m_code );
3135 std::set<wxString> powerAdjacentNets;
3142 if(
auto it = netToCode.find( be.
a ); it != netToCode.end() )
3145 if(
auto it = netToCode.find( be.
b ); it != netToCode.end() )
3148 if( ca == -1 || cb == -1 )
3151 if( powerSubgraphs.contains( ca ) || powerSubgraphs.contains( cb ) )
3153 if( !powerSubgraphs.contains( ca ) )
3154 powerAdjacentNets.insert( be.
a );
3156 if( !powerSubgraphs.contains( cb ) )
3157 powerAdjacentNets.insert( be.
b );
3162 result.adjacency[be.
a].push_back( { be.
b, be.
sym } );
3163 result.adjacency[be.
b].push_back( { be.
a, be.
sym } );
3169 std::map<wxString, int> degree;
3171 for(
const auto&
kv :
result.adjacency )
3172 degree[
kv.first] =
static_cast<int>(
kv.second.size() );
3174 if(
result.adjacency.size() <= 2 )
3175 powerAdjacentNets.clear();
3177 if( powerAdjacentNets.size() <= 2 )
3178 powerAdjacentNets.clear();
3180 std::queue<wxString> q;
3181 std::set<wxString> removed;
3183 for(
const auto&
kv : degree )
3185 if(
kv.second <= 1 && powerAdjacentNets.contains(
kv.first ) )
3191 wxString n = q.front();
3194 if( removed.contains( n ) )
3197 removed.insert( n );
3201 if( removed.contains( e.other ) )
3204 if( degree.count( e.other ) )
3208 if( degree[e.other] <= 1 && powerAdjacentNets.contains( e.other ) )
3214 if( !removed.empty() )
3216 std::map<wxString, std::vector<BRIDGE_NEIGHBOR>> newAdj;
3218 for(
const auto&
kv :
result.adjacency )
3220 if( removed.contains(
kv.first ) )
3225 if( removed.contains( e.
other ) )
3228 newAdj[
kv.first].push_back( e );
3232 result.adjacency.swap( newAdj );
3248 wxLogTrace(
traceSchNetChain,
"RebuildNetChains: begin (items=%zu, schematic=%p)",
3258 std::map<wxString, SCH_NETCHAIN*> netToNetChain;
3262 std::vector<SCH_SCREEN*> allScreens;
3267 allScreens.push_back( sc );
3274 static_cast<SCH_SYMBOL*
>( item )->SetNetChainName( wxEmptyString );
3276 wxLogTrace(
traceSchNetChain,
"RebuildNetChains: screens=%zu (global build)", allScreens.size() );
3285 wxLogTrace(
traceSchNetChain,
"RebuildNetChains: pass 1 (per-sheet 2-pin symbols)" );
3287 auto getSubgraphNet = [&](
SCH_PIN* aPin ) -> wxString
3298 auto& bridgeEdges = bridgeGraph.
edges;
3299 auto& adjacency = bridgeGraph.
adjacency;
3301 wxLogTrace(
traceSchNetChain,
"RebuildNetChains: bridgeEdges=%zu adjacency=%zu",
3302 bridgeEdges.size(), adjacency.size() );
3308 wxLogTrace(
traceSchNetChain,
"RebuildNetChains: targeted stub pruning start (adj=%zu)", adjacency.size() );
3309 std::map<wxString,std::vector<BRIDGE_NEIGHBOR>> snapshot = adjacency;
3310 std::set<wxString> seen;
3311 std::set<wxString> globalPrune;
3312 for(
const auto&
kv : snapshot )
3314 const wxString& start =
kv.first;
3315 if( seen.contains( start ) )
continue;
3317 std::vector<wxString>
comp; std::queue<wxString> q; q.push( start ); seen.insert( start );
3320 wxString cur = q.front(); q.pop();
comp.push_back( cur );
3321 for(
const BRIDGE_NEIGHBOR& e : snapshot[cur] )
if( !seen.contains( e.other ) ) { seen.insert( e.other ); q.push( e.other ); }
3324 if(
comp.size() <= 4 )
continue;
3325 std::map<wxString,int> degree;
3326 for(
const wxString& n :
comp ) degree[n] = (int) snapshot[n].size();
3327 std::vector<wxString> candidates;
3328 for(
const wxString& n :
comp )
3330 const auto& nbrs = snapshot[n];
3331 if( nbrs.size() == 1 )
3333 const wxString neigh = nbrs[0].other;
3334 if( degree.count( neigh ) && degree[neigh] > 2 ) candidates.push_back( n );
3338 if( candidates.empty() )
continue;
3339 std::sort( candidates.begin(), candidates.end(), [](
const wxString& a,
const wxString& b ){ return a.CmpNoCase( b ) < 0; } );
3340 size_t needPrune =
comp.size() - 4;
if( needPrune > candidates.size() ) needPrune = candidates.size();
3342 for(
size_t i = 0; i < needPrune; ++i ) globalPrune.insert( candidates[i] );
3344 if( !globalPrune.empty() )
3346 std::map<wxString,std::vector<BRIDGE_NEIGHBOR>> newAdj;
3347 for(
const auto& kv2 : adjacency )
3349 if( globalPrune.contains( kv2.first ) )
continue;
3352 if( globalPrune.contains( e.
other ) )
continue;
3353 newAdj[kv2.first].push_back( e );
3356 adjacency.swap( newAdj );
3357 wxLogTrace(
traceSchNetChain,
"RebuildNetChains: pruned %zu targeted stub nets", globalPrune.size() );
3362 auto neighbors_of = [&](
const wxString& n ) ->
const std::vector<BRIDGE_NEIGHBOR>*
3364 if(
auto it = adjacency.find(n); it != adjacency.end() )
return &it->second;
3373 std::set<wxString> netsAll;
3374 for(
const auto&
kv : adjacency ) netsAll.insert(
kv.first );
3377 std::set<wxString> visited;
3378 for(
const wxString& start : netsAll )
3380 if( visited.contains( start ) )
continue;
3381 std::queue<wxString> q; q.push( start );
3382 std::set<wxString>
comp;
comp.insert( start ); visited.insert( start );
3385 wxString cur = q.front(); q.pop();
3386 if(
auto nbrs = neighbors_of( cur ) )
3390 if( visited.contains( e.other ) )
continue;
3391 visited.insert( e.other );
3392 comp.insert( e.other );
3397 if(
comp.size() >= 2 )
3399 auto sig = std::make_unique<SCH_NETCHAIN>();
3400 for(
const wxString& n :
comp ) sig->AddNet( n );
3402 if(
comp.contains( be.a ) &&
comp.contains( be.b ) && be.sym )
3403 sig->AddSymbol( be.sym );
3408 netToNetChain.clear();
3410 if( sigUP )
for(
const wxString& n : sigUP->GetNets() ) netToNetChain[n] = sigUP.get();
3416 if( !sigUP )
continue;
3419 for(
const wxString& n : sigUP->GetNets() )
3424 netsStr += wxS(
" ");
3428 netsStr += wxS(
"...");
3433 wxLogTrace(
traceSchNetChain,
" chain %p name='%s' nets=%zu [%s]", (
void*) sigUP.get(),
3434 sigUP->GetName(), sigUP->GetNets().size(), netsStr );
3442 std::set<wxString> committedNames;
3447 committedNames.insert(
chain->GetName() );
3459 net = sg->GetNetName();
3462 if( !net.IsEmpty() && net.Length() < 2048 && netToNetChain.count( net ) )
3465 if(
name.Length() > 512 )
3466 name.Truncate( 512 );
3467 if(
name.StartsWith( wxS(
"/" ) ) )
3472 if( !committedNames.count(
name ) )
3473 netToNetChain[net]->SetName(
name );
3479 wxLogTrace(
traceSchNetChain,
"RebuildNetChains: pass 3 (default naming)" );
3482 if( sig->GetName().IsEmpty() )
3484 sig->SetName( wxString::Format( wxT(
"NetChain%d" ), idx ) );
3489 wxLogTrace(
traceSchNetChain,
"RebuildNetChains: pass 4 (terminal pins)" );
3498 std::vector<PIN_INFO> pins;
3502 SCH_SCREEN* sc = sheetPath.LastScreen();
if( !sc )
continue;
3508 wxString net = getSubgraphNet( p );
3509 if( sig->GetNets().count( net ) )
3510 pins.push_back( { p, sym, &sheetPath } );
3517 size_t bestI = 0, bestJ = 0;
3519 for(
size_t i = 0; i < pins.size(); ++i )
3521 for(
size_t j = i + 1; j < pins.size(); ++j )
3523 VECTOR2I pa = pins[i].pin->GetPosition();
3524 VECTOR2I pb = pins[j].pin->GetPosition();
3525 int64_t dx = pa.
x - pb.
x;
3526 int64_t dy = pa.
y - pb.
y;
3527 int64_t d = dx * dx + dy * dy;
3532 a = pins[i].pin->m_Uuid;
3533 b = pins[j].pin->m_Uuid;
3540 sig->SetTerminalPins( a, b );
3542 if( best >= 0 && bestI < pins.size() && bestJ < pins.size() )
3544 sig->SetTerminalRefs( pins[bestI].sym->GetRef( pins[bestI].sheet ), pins[bestI].pin->GetNumber(),
3545 pins[bestJ].sym->GetRef( pins[bestJ].sheet ), pins[bestJ].pin->GetNumber() );
3551 sig->SetTerminalPins( ov.first, ov.second );
3555 wxLogTrace(
traceSchNetChain,
"RebuildNetChains: pass 5 (apply symbol names)" );
3562 sym->SetNetChainName( sig->
GetName() );
3565 for(
const wxString& n : sig->
GetNets() ) { netsStr += n + wxS(
" "); }
3575 std::set<wxString> alreadyCommitted;
3580 alreadyCommitted.insert(
chain->GetName() );
3584 std::map<std::pair<wxString, wxString>, wxString> refPinToNet;
3596 wxString ref = sym->
GetRef( &sp );
3606 refPinToNet[{ ref,
pin->GetNumber() }] =
3615 std::unordered_map<wxString, SCH_NETCHAIN*> committedByName;
3620 committedByName[
chain->GetName()] =
chain.get();
3625 std::set<wxString> refreshedThisPass;
3635 if( alreadyCommitted.count( chainName ) )
3637 auto it = committedByName.find( chainName );
3639 if( it != committedByName.end() && it->second )
3642 refreshedThisPass.insert( chainName );
3649 alreadyCommitted.insert( chainName );
3650 refreshedThisPass.insert( chainName );
3657 if( memberNets.empty() )
3662 if( alreadyCommitted.count( chainName ) && refreshedThisPass.count( chainName ) )
3672 SCH_PIN* terminalPinA =
nullptr;
3673 SCH_PIN* terminalPinB =
nullptr;
3674 std::set<SCH_SYMBOL*> symbols;
3686 wxString ref = sym->
GetRef( &sp );
3687 bool symContributes =
false;
3697 symContributes =
true;
3699 if( ref == termRefs.first.ref &&
pin->GetNumber() == termRefs.first.pin )
3702 if( ref == termRefs.second.ref &&
pin->GetNumber() == termRefs.second.pin )
3706 if( symContributes )
3707 symbols.insert( sym );
3711 if( !terminalPinA || !terminalPinB || symbols.empty() )
3714 "RebuildNetChains: cannot restore manual chain '%s' "
3715 "(terminals or member nets unresolved)",
3720 if( alreadyCommitted.count( chainName ) )
3722 auto it = committedByName.find( chainName );
3724 if( it != committedByName.end() && it->second )
3728 termRefs.first.ref, termRefs.first.pin,
3729 termRefs.second.ref, termRefs.second.pin );
3736 terminalPinB->
m_Uuid, termRefs.first.ref, termRefs.first.pin,
3737 termRefs.second.ref, termRefs.second.pin );
3738 alreadyCommitted.insert( chainName );
3750 sym->SetNetChainName(
chain->GetName() );
3763 catch(
const std::exception& e )
3765 wxFAIL_MSG( wxString::Format(
"RebuildNetChains threw: %s", e.what() ) );
3766 wxLogError(
_(
"Net chain rebuild failed: %s. The schematic may have stale chain "
3767 "data; reload to recover." ),
3768 wxString( e.what() ) );
3779 wxFAIL_MSG(
"RebuildNetChains threw an unknown exception" );
3780 wxLogError(
_(
"Net chain rebuild failed with an unknown error. The schematic may "
3781 "have stale chain data; reload to recover." ) );
3794 const std::map<std::pair<wxString, wxString>, wxString>& aRefPinToNet,
3795 const std::vector<std::unique_ptr<SCH_NETCHAIN>>& aPotentials,
3796 const wxString& aChainName )
3798 auto itFrom = aRefPinToNet.find( { aTermRefs.first.ref, aTermRefs.first.pin } );
3799 auto itTo = aRefPinToNet.find( { aTermRefs.second.ref, aTermRefs.second.pin } );
3801 if( itFrom == aRefPinToNet.end() || itTo == aRefPinToNet.end() )
3804 "RebuildNetChains: cannot restore chain '%s' (terminal %s.%s/%s.%s unresolved)",
3805 aChainName, aTermRefs.first.ref, aTermRefs.first.pin,
3806 aTermRefs.second.ref, aTermRefs.second.pin );
3810 for(
const auto& pot : aPotentials )
3812 if( pot && pot->GetNets().count( itFrom->second ) && pot->GetNets().count( itTo->second ) )
3817 "RebuildNetChains: no potential chain spans both terminals of '%s' (%s/%s)",
3818 aChainName, itFrom->second, itTo->second );
3825 if( !aPinA || !aPinB )
3837 if( netA.IsEmpty() || netB.IsEmpty() )
3842 if( sigUP && sigUP->GetNets().contains( netA ) && sigUP->GetNets().contains( netB ) )
3851 if( aName.IsEmpty() )
3855 [&](
const std::unique_ptr<SCH_NETCHAIN>& aChain )
3857 return aChain && aChain->GetName() == aName;
3868 sym->SetNetChainName( wxEmptyString );
3886 if( aOld.IsEmpty() || aNew.IsEmpty() || aOld == aNew )
3889 auto findByName = [&](
const wxString& aName ) ->
SCH_NETCHAIN*
3907 if( findByName( aNew ) )
3915 sym->SetNetChainName( aNew );
3929 auto rekey = [&](
auto& aMap )
3931 auto it = aMap.find( aOld );
3933 if( it != aMap.end() )
3935 auto val = std::move( it->second );
3937 aMap[aNew] = std::move( val );
3950 const std::set<wxString>& aNets,
3951 const std::set<SCH_SYMBOL*>& aSymbols,
3952 const KIID& aTerminalPinA,
3953 const KIID& aTerminalPinB,
3954 const wxString& aRefA,
3955 const wxString& aPinNumA,
3956 const wxString& aRefB,
3957 const wxString& aPinNumB )
3962 std::set<wxString> filtered;
3964 for(
const wxString& net : aNets )
3966 if( !net.IsEmpty() )
3967 filtered.insert( net );
3983 aTarget->
SetTerminalPins( termOverride->second.first, termOverride->second.second );
3990 sym->SetNetChainName( aTarget->
GetName() );
4008 auto sig = std::make_unique<SCH_NETCHAIN>();
4009 for(
const wxString& n : aPotential->
GetNets() )
4012 sig->AddSymbol( sym );
4013 sig->SetName( aName );
4022 sig->SetNetClass( ncIt->second );
4028 sig->SetColor( colIt->second );
4032 sym->SetNetChainName( sig->GetName() );
4047 std::set<wxString> persistableNets;
4049 for(
const wxString& net : sig->GetNets() )
4057 persistableNets.insert( net );
4060 if( !persistableNets.empty() )
4072 const std::set<SCH_SYMBOL*>& aSymbols,
4073 const std::set<wxString>& aNets,
4074 const KIID& aTerminalPinA,
4075 const KIID& aTerminalPinB,
4076 const wxString& aRefA,
4077 const wxString& aPinNumA,
4078 const wxString& aRefB,
4079 const wxString& aPinNumB )
4089 for(
const wxString& net : aNets )
4098 auto sig = std::make_unique<SCH_NETCHAIN>();
4099 sig->SetName( aName );
4101 for(
const wxString& net : aNets )
4110 sig->AddSymbol( sym );
4112 sig->SetTerminalPins( aTerminalPinA, aTerminalPinB );
4113 sig->SetTerminalRefs( aRefA, aPinNumA, aRefB, aPinNumB );
4118 sig->SetNetClass( ncIt->second );
4123 sig->SetColor( colIt->second );
4126 sym->SetNetChainName( sig->GetName() );
4143 wxLogTrace(
traceSchNetChain,
"CONNECTION_GRAPH::GetNetChainForNet(%s)", aNet );
4149 if( sig->GetNets().count( aNet ) )
4151 wxLogTrace(
traceSchNetChain,
"GetNetChainForNet: found chain '%s'", sig->GetName() );
4166 std::shared_ptr<NET_SETTINGS> netSettings =
m_schematic->Project().GetProjectFile().NetSettings();
4172 [](
const std::unique_ptr<SCH_NETCHAIN>& aChain )
4174 return aChain && !aChain->GetNetClass().IsEmpty();
4179 if( !anyOverride && !netSettings->HasChainPatternAssignments() )
4182 netSettings->ClearChainPatternAssignments();
4189 const wxString& netclass =
chain->GetNetClass();
4191 if( netclass.IsEmpty() || !netSettings->HasNetclass( netclass ) )
4194 for(
const wxString& net :
chain->GetNets() )
4200 netSettings->SetChainPatternAssignment( net, netclass );
4208 wxLogTrace(
traceSchNetChain,
"CONNECTION_GRAPH::GetNetChainByName(%s)", aName );
4211 if( sig->GetName() == aName )
4226 wxLogTrace(
traceSchNetChain,
"ReplaceNetChainTerminalPin: chain='%s' prev=%s new=%s",
4230 sig->ReplaceTerminalPin( aPrev, aNew );
4232 sig->GetTerminalPinB() );
4233 wxLogTrace(
traceSchNetChain,
"ReplaceNetChainTerminalPin: updated overrides to (%s,%s)",
4234 sig->GetTerminalPinA().AsString(), sig->GetTerminalPinB().AsString() );
4240 std::pair<KIID, KIID>>& aOverrides )
4280 std::vector<std::shared_ptr<SCH_CONNECTION>> connections_to_check( aConnection->
Members() );
4282 for(
unsigned i = 0; i < connections_to_check.size(); i++ )
4284 const std::shared_ptr<SCH_CONNECTION>& member = connections_to_check[i];
4286 if( member->IsBus() )
4288 connections_to_check.insert( connections_to_check.end(),
4289 member->Members().begin(),
4290 member->Members().end() );
4302 std::vector<CONNECTION_SUBGRAPH*> search_list;
4303 std::unordered_set<CONNECTION_SUBGRAPH*> visited;
4304 std::unordered_set<SCH_CONNECTION*> stale_bus_members;
4311 path.push_back(
pin->GetParent() );
4322 || visited.contains( candidate ) )
4331 wxLogTrace(
ConnTrace, wxS(
"%lu: found child %lu (%s)" ), aParent->m_code,
4339 wxASSERT( candidate->
m_graph == aParent->m_graph );
4341 search_list.push_back( candidate );
4361 || visited.contains( candidate )
4367 const KIID& last_parent_uuid = aParent->m_sheet.Last()->m_Uuid;
4372 if(
pin->GetParent()->m_Uuid != last_parent_uuid )
4378 if( pin_path != aParent->m_sheet )
4383 wxLogTrace(
ConnTrace, wxS(
"%lu: found additional parent %lu (%s)" ),
4386 aParent->m_hier_children.insert( candidate );
4387 search_list.push_back( candidate );
4401 std::vector<std::shared_ptr<SCH_CONNECTION>> sortedMembers;
4403 for(
const auto&
kv : aParentGraph->m_bus_neighbors )
4404 sortedMembers.push_back(
kv.first );
4406 std::sort( sortedMembers.begin(), sortedMembers.end(),
4407 [](
const std::shared_ptr<SCH_CONNECTION>& a,
4408 const std::shared_ptr<SCH_CONNECTION>& b )
4410 return a->Name() < b->Name();
4413 for(
const std::shared_ptr<SCH_CONNECTION>& member_conn : sortedMembers )
4415 const auto& kv_it = aParentGraph->m_bus_neighbors.find( member_conn );
4417 if( kv_it == aParentGraph->m_bus_neighbors.end() )
4460 wxLogTrace(
ConnTrace, wxS(
"Could not match bus member %s in %s" ),
4461 member_conn->Name(), parent->
Name() );
4467 wxCHECK2( neighbor_conn,
continue );
4469 wxString neighbor_name = neighbor_conn->
Name();
4472 if( neighbor_name == member->
Name() )
4482 if( neighbor_conn->
Sheet() != parent->
Sheet() )
4493 bool alreadyUpdatedByBusMember =
false;
4495 for(
const auto& m : parent->
Members() )
4497 if( m->Name() == neighbor_name )
4499 alreadyUpdatedByBusMember =
true;
4504 if( alreadyUpdatedByBusMember )
4509 wxCHECK2_MSG( neighbor_conn->
IsNet(),
continue,
4510 wxS(
"\"" ) + neighbor_name + wxS(
"\" is not a net." ) );
4512 wxLogTrace(
ConnTrace, wxS(
"%lu (%s) connected to bus member %s (local %s)" ),
4519 member->
Clone( *neighbor_conn );
4520 stale_bus_members.insert( member );
4524 neighbor_conn->
Clone( *member );
4537 if( neighbor_conn->
Name() != member->
Name() )
4539 member->
Clone( *neighbor_conn );
4540 stale_bus_members.insert( member );
4549 propagate_bus_neighbors( aSubgraph );
4556 wxLogTrace(
ConnTrace, wxS(
"%lu (%s) has both hier ports and pins; deferring processing" ),
4562 wxLogTrace(
ConnTrace, wxS(
"%lu (%s) has no hier pins or ports on sheet %s; marking clean" ),
4568 visited.insert( aSubgraph );
4570 wxLogTrace(
ConnTrace, wxS(
"Propagating %lu (%s) to subsheets" ),
4575 for(
unsigned i = 0; i < search_list.size(); i++ )
4577 auto child = search_list[i];
4579 if( visited.insert( child ).second )
4582 child->m_dirty =
false;
4596 if( subgraph == aSubgraph )
4603 wxString candidateName = subgraph->m_driver_connection->Name();
4604 bool shorterPath = subgraph->m_sheet.size() < bestDriver->
m_sheet.
size();
4605 bool asGoodPath = subgraph->m_sheet.size() <= bestDriver->
m_sheet.
size();
4615 ( !bestIsStrong && candidateStrong ) ||
4616 ( priority > highest && candidateStrong ) ||
4617 ( priority == highest && candidateStrong && shorterPath ) ||
4618 ( ( bestIsStrong == candidateStrong ) && asGoodPath && ( priority == highest ) &&
4619 ( candidateName < bestName ) ) )
4621 bestDriver = subgraph;
4623 bestIsStrong = candidateStrong;
4624 bestName = candidateName;
4629 if( bestDriver != aSubgraph )
4631 wxLogTrace(
ConnTrace, wxS(
"%lu (%s) overridden by new driver %lu (%s)" ),
4640 wxString old_name = subgraph->m_driver_connection->Name();
4642 subgraph->m_driver_connection->Clone( *conn );
4644 if( old_name != conn->
Name() )
4648 propagate_bus_neighbors( subgraph );
4654 if( conn->
IsBus() && !stale_bus_members.empty() )
4656 std::unordered_set<SCH_CONNECTION*> cached_members = stale_bus_members;
4666 wxLogTrace(
ConnTrace, wxS(
"WARNING: failed to match stale member %s in %s." ),
4667 stale_member->Name(), subgraph->m_driver_connection->Name() );
4671 wxLogTrace(
ConnTrace, wxS(
"Updating %lu (%s) member %s to %s" ), subgraph->m_code,
4672 subgraph->m_driver_connection->Name(), member->
LocalName(), stale_member->Name() );
4674 member->
Clone( *stale_member );
4676 propagate_bus_neighbors( subgraph );
4688 std::shared_ptr<SCH_CONNECTION> c = std::shared_ptr<SCH_CONNECTION>(
nullptr );
4690 switch( aItem->
Type() )
4693 if(
static_cast<SCH_PIN*
>( aItem )->IsPower() )
4694 c = std::make_shared<SCH_CONNECTION>( aItem, aSubgraph->
m_sheet );
4701 c = std::make_shared<SCH_CONNECTION>( aItem, aSubgraph->
m_sheet );
4710 c->SetGraph(
this );
4721 if( !aBusConnection->
IsBus() )
4731 for(
const std::shared_ptr<SCH_CONNECTION>& bus_member : aBusConnection->
Members() )
4733 if( bus_member->VectorIndex() == aSearch->
VectorIndex() )
4735 match = bus_member.get();
4743 for(
const std::shared_ptr<SCH_CONNECTION>& c : aBusConnection->
Members() )
4750 for(
const std::shared_ptr<SCH_CONNECTION>& bus_member : c->Members() )
4752 if( bus_member->LocalName() == aSearch->
LocalName() )
4754 match = bus_member.get();
4759 else if( c->LocalName() == aSearch->
LocalName() )
4770 for(
const std::shared_ptr<SCH_CONNECTION>& c : aBusConnection->
Members() )
4774 for(
const std::shared_ptr<SCH_CONNECTION>& bus_member : c->Members() )
4778 match = bus_member.get();
4812 std::vector<CONNECTION_SUBGRAPH*>& vec = it->second;
4813 std::erase( vec, aSubgraph );
4816 wxLogTrace(
ConnTrace, wxS(
"recacheSubgraphName: %s => %s" ), aOldName,
4833 std::vector<const CONNECTION_SUBGRAPH*> ret;
4839 wxASSERT( !subgraph->m_dirty );
4841 if( !subgraph->m_driver )
4847 if( !connection->
IsBus() )
4850 auto labels = subgraph->GetVectorBusLabels();
4852 if( labels.size() > 1 )
4854 bool different =
false;
4857 for(
unsigned i = 1; i < labels.size(); ++i )
4869 wxLogTrace(
ConnTrace, wxS(
"SG %ld (%s) has multiple bus labels" ), subgraph->m_code,
4870 connection->
Name() );
4872 ret.push_back( subgraph );
4893 if( graph == aSubGraph )
4936 wxASSERT( !it->second.empty() );
4938 return it->second[0];
4954const std::vector<CONNECTION_SUBGRAPH*>&
4957 static const std::vector<CONNECTION_SUBGRAPH*> subgraphs;
4970 int error_count = 0;
4972 wxCHECK_MSG(
m_schematic,
true, wxS(
"Null m_schematic in CONNECTION_GRAPH::RunERC" ) );
4978 std::set<SCH_ITEM*> seenDriverInstances;
4983 wxCHECK2( subgraph,
continue );
4987 wxASSERT( !subgraph->m_dirty );
4989 if( subgraph->m_absorbed )
4992 if( seenDriverInstances.count( subgraph->m_driver ) )
4995 if( subgraph->m_driver )
4996 seenDriverInstances.insert( subgraph->m_driver );
5014 subgraph->ResolveDrivers(
false );
5085 wxCHECK( aSubgraph,
false );
5091 if( driver == aSubgraph->
m_driver )
5102 if( primaryName == secondaryName )
5105 wxString msg = wxString::Format(
_(
"Both %s and %s are attached to the same "
5106 "items; %s will be used in the netlist" ),
5107 primaryName, secondaryName, primaryName );
5110 ercItem->SetItems( aSubgraph->
m_driver, driver );
5111 ercItem->SetSheetSpecificPath( aSubgraph->
GetSheet() );
5112 ercItem->SetItemsSheetPaths( aSubgraph->
GetSheet(), aSubgraph->
m_sheet );
5113 ercItem->SetErrorMessage( msg );
5138 switch( item->
Type() )
5143 bus_item = ( !bus_item ) ? item : bus_item;
5145 net_item = ( !net_item ) ? item : net_item;
5159 bus_item = ( !bus_item ) ? item : bus_item;
5161 net_item = ( !net_item ) ? item : net_item;
5171 if( net_item && bus_item )
5174 ercItem->SetSheetSpecificPath( sheet );
5175 ercItem->SetItems( net_item, bus_item );
5178 screen->
Append( marker );
5197 switch( item->
Type() )
5224 if(
test != member && member->Name() ==
test->Name() )
5238 ercItem->SetSheetSpecificPath( sheet );
5239 ercItem->SetItems( label, port );
5242 screen->
Append( marker );
5254 bool conflict =
false;
5270 switch( item->
Type() )
5300 std::set<wxString> test_names;
5312 for(
const auto& sub_member : member->Members() )
5314 if( test_names.count( sub_member->FullLocalName() ) )
5318 else if( test_names.count( member->FullLocalName() ) )
5337 wxString msg = wxString::Format(
_(
"Net %s is graphically connected to bus %s but is not a"
5338 " member of that bus" ),
5342 ercItem->SetSheetSpecificPath( sheet );
5343 ercItem->SetItems( bus_entry, bus_wire );
5344 ercItem->SetErrorMessage( msg );
5347 screen->
Append( marker );
5364 std::set<SCH_PIN*> unique_pins;
5365 std::set<SCH_LABEL_BASE*> unique_labels;
5373 for(
SCH_ITEM* item : aProcessGraph->m_items )
5375 switch( item->
Type() )
5382 if( aProcessGraph == aSubgraph )
5385 if( std::none_of( unique_pins.begin(), unique_pins.end(),
5388 return test_pin->IsStacked( aPin );
5392 unique_pins.insert( test_pin );
5415 process_subgraph( subgraph );
5420 process_subgraph( aSubgraph );
5436 switch( item->
Type() )
5483 ercItem->SetSheetSpecificPath( sheet );
5484 ercItem->SetItemsSheetPaths( sheet );
5491 pos =
pin->GetPosition();
5500 screen->
Append( marker );
5505 if( unique_pins.empty() && unique_labels.empty() &&
5510 ercItem->SetSheetSpecificPath( sheet );
5511 ercItem->SetItemsSheetPaths( sheet );
5514 screen->
Append( marker );
5521 bool has_other_connections =
false;
5522 std::vector<SCH_PIN*> pins;
5529 switch( item->
Type() )
5536 if( !has_other_connections && !pins.empty()
5539 for(
SCH_PIN* other_pin : pins )
5543 has_other_connections =
true;
5549 pins.emplace_back(
static_cast<SCH_PIN*
>( item ) );
5556 has_other_connections =
true;
5563 pin = pins.empty() ? nullptr : pins[0];
5566 for(
SCH_PIN* test_pin : pins )
5583 ?
pin->GetLibPin()->GetParentSymbol() :
nullptr;
5585 if(
pin && !has_other_connections
5587 && ( !pinLibParent || !pinLibParent->
IsPower() ) )
5589 wxString
name =
pin->Connection( &sheet )->Name();
5590 wxString local_name =
pin->Connection( &sheet )->Name(
true );
5595 has_other_connections =
true;
5600 if(
pin && !has_other_connections
5606 ercItem->SetSheetSpecificPath( sheet );
5607 ercItem->SetItemsSheetPaths( sheet );
5608 ercItem->SetItems(
pin );
5611 screen->
Append( marker );
5619 if( pins.size() > 1 )
5621 for(
SCH_PIN* testPin : pins )
5626 SYMBOL* testLibParent = testPin->GetLibPin()
5630 if( testLibParent && testLibParent->
IsPower()
5631 && testPin->ConnectedItems( sheet ).empty()
5635 ercItem->SetSheetSpecificPath( sheet );
5636 ercItem->SetItemsSheetPaths( sheet );
5637 ercItem->SetItems( testPin );
5640 screen->
Append( marker );
5673 ercItem->SetItems( line );
5674 ercItem->SetSheetSpecificPath( sheet );
5675 ercItem->SetErrorMessage(
_(
"Unconnected wire endpoint" ) );
5697 ercItem->SetItems( entry );
5698 ercItem->SetSheetSpecificPath( sheet );
5699 ercItem->SetErrorMessage(
_(
"Unconnected wire to bus entry" ) );
5716 return err_count > 0;
5726 std::vector<SCH_ITEM*> wires;
5733 wires.emplace_back( item );
5735 wires.emplace_back( item );
5738 if( !wires.empty() )
5743 ercItem->SetSheetSpecificPath( sheet );
5744 ercItem->SetItems( wires[0],
5745 wires.size() > 1 ? wires[1] :
nullptr,
5746 wires.size() > 2 ? wires[2] :
nullptr,
5747 wires.size() > 3 ? wires[3] :
nullptr );
5750 screen->
Append( marker );
5760 std::unordered_set<const CONNECTION_SUBGRAPH*>& aOut )
const
5769 for(
const auto& [sibMemberConn, sibMembers] : siblingBus->
m_bus_neighbors )
5771 if( sibMemberConn->Name() != aMemberName )
5775 aOut.insert( sibling );
5800 size_t pinCount = 0;
5803 std::map<KICAD_T, std::vector<SCH_TEXT*>> label_map;
5809 return std::count_if( aLocSubgraph->m_items.begin(), aLocSubgraph->m_items.end(),
5812 return item->Type() == SCH_PIN_T;
5817 [&](
SCH_TEXT* aText,
int errCode )
5822 ercItem->SetSheetSpecificPath( sheet );
5823 ercItem->SetItems( aText );
5830 pinCount =
hasPins( aSubgraph );
5834 switch( item->
Type() )
5842 label_map[item->
Type()].push_back(
text );
5847 if(
text->IsDangling() )
5861 if( label_map.empty() )
5867 std::unordered_set<const CONNECTION_SUBGRAPH*> busMemberSiblings;
5869 for(
auto& [memberConn, busParents] : aSubgraph->
m_bus_parents )
5871 wxString memberName = memberConn->Name();
5875 if( busParent->m_no_connect )
5880 if( hp->m_no_connect )
5890 wxCHECK_MSG(
m_schematic,
true, wxS(
"Null m_schematic in CONNECTION_GRAPH::ercCheckLabels" ) );
5897 for(
auto& [type, label_vec] : label_map )
5901 size_t allPins = pinCount;
5902 size_t localPins = pinCount;
5903 bool hasLocalHierarchy =
false;
5911 std::set<wxString> uniquePortNames;
5915 if( aSubgraph->
m_hier_pins.size() + uniquePortNames.size() > 1 )
5917 hasLocalHierarchy =
true;
5922 for(
auto& [connection, busParents] : aSubgraph->
m_bus_parents )
5926 if( busParent->m_sheet == sheet
5927 && ( !busParent->m_hier_pins.empty()
5928 || !busParent->m_hier_ports.empty() ) )
5930 hasLocalHierarchy =
true;
5935 if( hasLocalHierarchy )
5940 std::unordered_set<const CONNECTION_SUBGRAPH*> creditedNeighbors;
5941 creditedNeighbors.insert( aSubgraph );
5945 if( !creditedNeighbors.insert( neighbor ).second )
5948 if( neighbor->m_no_connect )
5951 size_t neighborPins =
hasPins( neighbor );
5952 allPins += neighborPins;
5954 if( neighbor->m_sheet == sheet )
5956 localPins += neighborPins;
5958 if( !neighbor->m_hier_pins.empty() || !neighbor->m_hier_ports.empty() )
5960 hasLocalHierarchy =
true;
5970 creditNeighbor( neighbor );
5974 creditNeighbor( sibling );
5976 if( allPins == 1 && !has_nc )
5987 || ( type ==
SCH_LABEL_T && localPins == 0 && allPins > 1
5988 && !has_nc && !hasLocalHierarchy ) )
6004 std::map<wxString, std::tuple<int, const SCH_ITEM*, SCH_SHEET_PATH>> labelData;
6011 wxString resolvedLabelText =
6014 if( labelData.find( resolvedLabelText ) == labelData.end() )
6016 labelData[resolvedLabelText] = { 1, item, sheet };
6020 std::get<0>( labelData[resolvedLabelText] ) += 1;
6021 std::get<1>( labelData[resolvedLabelText] ) =
nullptr;
6022 std::get<2>( labelData[resolvedLabelText] ) = sheet;
6027 for(
const auto& label : labelData )
6029 if( std::get<0>( label.second ) == 1 )
6032 const SCH_ITEM* item = std::get<1>( label.second );
6035 ercItem->SetItems( std::get<1>( label.second ) );
6036 ercItem->SetSheetSpecificPath( sheet );
6037 ercItem->SetItemsSheetPaths( sheet );
6052 int error_count = 0;
6064 ercItem->SetSheetSpecificPath( sheet );
6065 ercItem->SetItems(
text );
6068 sheet.LastScreen()->Append( marker );
6088 if( sheet.Last()->IsTopLevelSheet() )
6094 wxCHECK2( label,
continue );
6096 msg.Printf(
_(
"Hierarchical label '%s' in root sheet cannot be connected to non-existent "
6100 ercItem->SetItems( item );
6101 ercItem->SetErrorMessage( msg );
6104 sheet.LastScreen()->Append( marker );
6115 parentSheetPath.
push_back( parentSheet );
6117 std::map<wxString, SCH_SHEET_PIN*> pins;
6118 std::map<wxString, SCH_HIERLABEL*> labels;
6123 pins[
pin->GetShownText( &parentSheetPath,
false ) ] =
pin;
6128 ercItem->SetItems(
pin );
6129 ercItem->SetSheetSpecificPath( sheet );
6130 ercItem->SetItemsSheetPaths( sheet );
6133 sheet.LastScreen()->Append( marker );
6141 std::set<wxString> matchedPins;
6148 wxString labelText = label->
GetShownText( &parentSheetPath,
false );
6150 if( !pins.contains( labelText ) )
6151 labels[ labelText ] = label;
6153 matchedPins.insert( labelText );
6157 for(
const wxString& matched : matchedPins )
6158 pins.erase( matched );
6160 for(
const auto& [
name,
pin] : pins )
6162 msg.Printf(
_(
"Sheet pin %s has no matching hierarchical label inside the sheet" ),
6166 ercItem->SetItems(
pin );
6167 ercItem->SetErrorMessage( msg );
6168 ercItem->SetSheetSpecificPath( sheet );
6169 ercItem->SetItemsSheetPaths( sheet );
6172 sheet.LastScreen()->Append( marker );
6177 for(
const auto& [
name, label] : labels )
6179 msg.Printf(
_(
"Hierarchical label %s has no matching sheet pin in the parent sheet" ),
6183 ercItem->SetItems( label );
6184 ercItem->SetErrorMessage( msg );
6185 ercItem->SetSheetSpecificPath( parentSheetPath );
6186 ercItem->SetItemsSheetPaths( parentSheetPath );
constexpr EDA_IU_SCALE schIUScale
This represents a sentry transaction which is used for time-performance metrics You start a transacti...
void StartSpan(const std::string &aOperation, const std::string &aDescription)
static SCH_NETCHAIN * resolvePotentialChainByTerminals(const CHAIN_TERMINAL_REFS &aTermRefs, const std::map< std::pair< wxString, wxString >, wxString > &aRefPinToNet, const std::vector< std::unique_ptr< SCH_NETCHAIN > > &aPotentials, const wxString &aChainName)
Disambiguate the saved (refA.pinA, refB.pinB) terminal pair against the current set of potential net ...
int RunERC()
Run electrical rule checks on the connectivity graph.
bool ercCheckBusToBusConflicts(const CONNECTION_SUBGRAPH *aSubgraph)
Check one subgraph for conflicting connections between two bus items.
void processSubGraphs()
Process all subgraphs to assign netcodes and merge subgraphs based on labels.
void refreshCommittedChainFromPotential(SCH_NETCHAIN *aTarget, const SCH_NETCHAIN &aSource)
Thin forwarder over refreshCommittedChainPayload that pulls payload fields from an inferred potential...
std::map< wxString, wxString > m_netChainNetClassOverrides
std::pair< CHAIN_TERMINAL_REF, CHAIN_TERMINAL_REF > CHAIN_TERMINAL_REFS
SCH_NETCHAIN * GetNetChainByName(const wxString &aName)
bool ercCheckLabels(const CONNECTION_SUBGRAPH *aSubgraph)
Check one subgraph for proper connection of labels.
void RemoveItem(SCH_ITEM *aItem)
std::map< wxString, COLOR4D > m_netChainColorOverrides
void collectAllDriverValues()
Map the driver values for each subgraph.
CONNECTION_SUBGRAPH * FindSubgraphByName(const wxString &aNetName, const SCH_SHEET_PATH &aPath)
Return the subgraph for a given net name on a given sheet.
int ercCheckDirectiveLabels()
Check directive labels should be connected to something.
void recacheSubgraphName(CONNECTION_SUBGRAPH *aSubgraph, const wxString &aOldName)
static SCH_CONNECTION * matchBusMember(SCH_CONNECTION *aBusConnection, SCH_CONNECTION *aSearch)
Search for a matching bus member inside a bus connection.
std::unordered_map< wxString, std::shared_ptr< BUS_ALIAS > > m_bus_alias_cache
SCHEMATIC * m_schematic
The schematic this graph represents.
void updateGenericItemConnectivity(const SCH_SHEET_PATH &aSheet, SCH_ITEM *aItem, std::map< VECTOR2I, std::vector< SCH_ITEM * > > &aConnectionMap)
Update the connectivity of items that are not pins or symbols.
std::vector< std::unique_ptr< SCH_NETCHAIN > > m_committedNetChains
std::unordered_map< SCH_SHEET_PATH, std::vector< CONNECTION_SUBGRAPH * > > m_sheet_to_subgraphs_map
Cache to lookup subgraphs in m_driver_subgraphs by sheet path.
void updateSymbolConnectivity(const SCH_SHEET_PATH &aSheet, SCH_SYMBOL *aSymbol, std::map< VECTOR2I, std::vector< SCH_ITEM * > > &aConnectionMap)
Update the connectivity of a symbol and its pins.
CONNECTION_SUBGRAPH * FindFirstSubgraphByName(const wxString &aNetName)
Retrieve a subgraph for the given net name, if one exists.
void propagateToNeighbors(CONNECTION_SUBGRAPH *aSubgraph, bool aForce)
Update all neighbors of a subgraph with this one's connectivity info.
void buildItemSubGraphs()
Generate individual item subgraphs on a per-sheet basis.
SCH_NETCHAIN * GetNetChainForNet(const wxString &aNet)
const std::vector< CONNECTION_SUBGRAPH * > & GetAllSubgraphs(const wxString &aNetName) const
bool ercCheckMultipleDrivers(const CONNECTION_SUBGRAPH *aSubgraph)
If the subgraph has multiple drivers of equal priority that are graphically connected,...
SCH_SHEET_LIST m_sheetList
All the sheets in the schematic (as long as we don't have partial updates).
void generateGlobalPowerPinSubGraphs()
Iterate through the global power pins to collect the global labels as drivers.
std::map< wxString, CHAIN_TERMINAL_REFS > m_netChainTerminalRefOverrides
BRIDGE_GRAPH buildBridgeAdjacency()
Build the bridge graph used for net-chain discovery.
SCH_NETCHAIN * CreateNetChainFromPotential(SCH_NETCHAIN *aPotential, const wxString &aName)
Promote a potential net chain to an actual user net chain with the provided name.
std::unordered_map< wxString, int > m_net_name_to_code_map
int ercCheckSingleGlobalLabel()
Check that a global label is instantiated more that once across the schematic hierarchy.
int ercCheckHierSheets()
Check that a hierarchical sheet has at least one matching label inside the sheet for each port on the...
bool ercCheckBusToNetConflicts(const CONNECTION_SUBGRAPH *aSubgraph)
Check one subgraph for conflicting connections between net and bus labels.
std::shared_ptr< SCH_CONNECTION > getDefaultConnection(SCH_ITEM *aItem, CONNECTION_SUBGRAPH *aSubgraph)
Build a new default connection for the given item based on its properties.
static std::function< void(CONNECTION_GRAPH &)> & RebuildNetChainsTestHook()
Test-only hook fired inside RebuildNetChains() after the restore passes have finished but before the ...
bool RenameCommittedNetChain(const wxString &aOld, const wxString &aNew)
Rename a committed net chain.
std::vector< const CONNECTION_SUBGRAPH * > GetBusesNeedingMigration()
Determine which subgraphs have more than one conflicting bus label.
void Recalculate(const SCH_SHEET_LIST &aSheetList, bool aUnconditional=false, std::function< void(SCH_ITEM *)> *aChangedItemHandler=nullptr, PROGRESS_REPORTER *aProgressReporter=nullptr)
Update the connection graph for the given list of sheets.
int assignNewNetCode(SCH_CONNECTION &aConnection)
Helper to assign a new net code to a connection.
std::map< std::pair< SCH_SHEET_PATH, wxString >, std::vector< const CONNECTION_SUBGRAPH * > > m_local_label_cache
int getOrCreateNetCode(const wxString &aNetName)
void collectBusMemberSiblings(const CONNECTION_SUBGRAPH *aBusParent, const wxString &aMemberName, std::unordered_set< const CONNECTION_SUBGRAPH * > &aOut) const
Find bus members on other sheets that share aBusParent's bus and member name.
bool ercCheckDanglingWireEndpoints(const CONNECTION_SUBGRAPH *aSubgraph)
Check one subgraph for dangling wire endpoints.
void refreshCommittedChainPayload(SCH_NETCHAIN *aTarget, const std::set< wxString > &aNets, const std::set< class SCH_SYMBOL * > &aSymbols, const KIID &aTerminalPinA, const KIID &aTerminalPinB, const wxString &aRefA, const wxString &aPinNumA, const wxString &aRefB, const wxString &aPinNumB)
Replace the derived-view payload on aTarget with explicitly supplied member nets, symbols,...
void assignNetCodesToBus(SCH_CONNECTION *aConnection)
Ensure all members of the bus connection have a valid net code assigned.
std::unordered_map< wxString, int > m_bus_name_to_code_map
std::unordered_map< wxString, std::vector< const CONNECTION_SUBGRAPH * > > m_global_label_cache
std::vector< CONNECTION_SUBGRAPH * > m_subgraphs
The owner of all CONNECTION_SUBGRAPH objects.
std::vector< std::pair< SCH_SHEET_PATH, SCH_PIN * > > m_global_power_pins
SCH_NETCHAIN * CreateManualNetChain(const wxString &aName, const std::set< class SCH_SYMBOL * > &aSymbols, const std::set< wxString > &aNets, const KIID &aTerminalPinA, const KIID &aTerminalPinB, const wxString &aRefA, const wxString &aPinNumA, const wxString &aRefB, const wxString &aPinNumB)
Commit a manually-defined net chain that the inferred-potential pass did not produce.
CONNECTION_GRAPH(SCHEMATIC *aSchematic=nullptr)
bool ercCheckNoConnects(const CONNECTION_SUBGRAPH *aSubgraph)
Check one subgraph for proper presence or absence of no-connect symbols.
size_t hasPins(const CONNECTION_SUBGRAPH *aLocSubgraph)
Get the number of pins in a given subgraph.
std::vector< SCH_ITEM * > m_items
All connectable items in the schematic.
void SetNetChainTerminalOverrides(const std::map< wxString, std::pair< KIID, KIID > > &aOverrides)
std::vector< std::unique_ptr< SCH_NETCHAIN > > m_potentialNetChains
last built potential (uncommitted) net chains
std::unordered_map< wxString, std::vector< CONNECTION_SUBGRAPH * > > m_net_name_to_subgraphs_map
std::shared_ptr< BUS_ALIAS > GetBusAlias(const wxString &aName)
Return a bus alias pointer for the given name if it exists (from cache)
void removeSubgraphs(std::set< CONNECTION_SUBGRAPH * > &aSubgraphs)
Remove references to the given subgraphs from all structures in the connection graph.
SCH_NETCHAIN * FindPotentialNetChainBetweenPins(SCH_PIN *aPinA, SCH_PIN *aPinB)
Locate a potential net chain that contains both pins (by subgraph net membership).
std::unordered_map< SCH_ITEM *, CONNECTION_SUBGRAPH * > m_item_to_subgraph_map
std::set< std::pair< SCH_SHEET_PATH, SCH_ITEM * > > ExtractAffectedItems(const std::set< SCH_ITEM * > &aItems)
For a set of items, this will remove the connected items and their associated data including subgraph...
wxString GetResolvedSubgraphName(const CONNECTION_SUBGRAPH *aSubGraph) const
Return the fully-resolved netname for a given subgraph.
bool ercCheckBusToBusEntryConflicts(const CONNECTION_SUBGRAPH *aSubgraph)
Check one subgraph for conflicting bus entry to bus connections.
void ReplaceNetChainTerminalPin(const wxString &aNetChain, const KIID &aPrev, const KIID &aNew)
std::vector< CONNECTION_SUBGRAPH * > m_driver_subgraphs
Cache of a subset of m_subgraphs.
void ExchangeItem(SCH_ITEM *aOldItem, SCH_ITEM *aNewItem)
Replace all references to #aOldItem with #aNewItem in the graph.
NET_MAP m_net_code_to_subgraphs_map
bool ercCheckFloatingWires(const CONNECTION_SUBGRAPH *aSubgraph)
Check one subgraph for floating wires.
static wxString MakeNetChainKey(const wxString &aRawNetName, long aSubgraphCode)
Map a subgraph's raw net name and code to the stable key used as a SCH_NETCHAIN member.
void ApplyNetChainNetclasses()
Mirror each committed net chain's netclass override into the project NET_SETTINGS as a chain-derived ...
void rekeyOverrideMaps(const wxString &aOld, const wxString &aNew)
Move every net-chain override map entry keyed by aOld to aNew.
void buildConnectionGraph(std::function< void(SCH_ITEM *)> *aChangedItemHandler, bool aUnconditional)
Generate the connection graph (after all item connectivity has been updated).
void Merge(CONNECTION_GRAPH &aGraph)
Combine the input graph contents into the current graph.
void updatePinConnectivity(const SCH_SHEET_PATH &aSheet, SCH_PIN *aPin, SCH_CONNECTION *aConnection)
Update the connectivity of a pin and its connections.
void resolveAllDrivers()
Find all subgraphs in the connection graph and calls ResolveDrivers() in parallel.
void updateItemConnectivity(const SCH_SHEET_PATH &aSheet, const std::vector< SCH_ITEM * > &aItemList)
Update the graphical connectivity between items (i.e.
CONNECTION_SUBGRAPH * GetSubgraphForItem(SCH_ITEM *aItem) const
void generateBusAliasMembers()
Iterate through labels to create placeholders for bus elements.
bool DeleteCommittedNetChain(const wxString &aName)
Delete a committed net chain by name.
std::map< wxString, std::set< wxString > > m_netChainMemberNetOverrides
std::map< wxString, std::pair< KIID, KIID > > m_netChainTerminalOverrides
A subgraph is a set of items that are electrically connected on a single sheet.
wxString driverName(SCH_ITEM *aItem) const
PRIORITY GetDriverPriority()
bool m_strong_driver
True if the driver is "strong": a label or power object.
SCH_ITEM * m_no_connect
No-connect item in graph, if any.
std::set< CONNECTION_SUBGRAPH * > m_absorbed_subgraphs
Set of subgraphs that have been absorbed by this subgraph.
static PRIORITY GetDriverPriority(SCH_ITEM *aDriver)
Return the priority (higher is more important) of a candidate driver.
std::mutex m_driver_name_cache_mutex
A cache of escaped netnames from schematic items.
SCH_SHEET_PATH m_sheet
On which logical sheet is the subgraph contained.
void UpdateItemConnections()
Update all items to match the driver connection.
std::set< SCH_SHEET_PIN * > m_hier_pins
Cache for lookup of any hierarchical (sheet) pins on this subgraph (for referring down).
std::unordered_map< std::shared_ptr< SCH_CONNECTION >, std::unordered_set< CONNECTION_SUBGRAPH * > > m_bus_neighbors
If a subgraph is a bus, this map contains links between the bus members and any local sheet neighbors...
CONNECTION_GRAPH * m_graph
std::vector< SCH_ITEM * > GetAllBusLabels() const
Return all the all bus labels attached to this subgraph (if any).
std::unordered_map< SCH_ITEM *, wxString > m_driver_name_cache
const wxString & GetNameForDriver(SCH_ITEM *aItem) const
Return the candidate net name for a driver.
wxString GetNetName() const
Return the fully-qualified net name for this subgraph (if one exists)
std::vector< SCH_ITEM * > GetVectorBusLabels() const
Return all the vector-based bus labels attached to this subgraph (if any).
const SCH_SHEET_PATH & GetSheet() const
bool m_multiple_drivers
True if this subgraph contains more than one driver that should be shorted together in the netlist.
bool ResolveDrivers(bool aCheckMultipleDrivers=false)
Determine which potential driver should drive the subgraph.
std::set< SCH_ITEM * > m_drivers
bool m_absorbed
True if this subgraph has been absorbed into another. No pointers here are safe if so!
SCH_CONNECTION * m_driver_connection
Cache for driver connection.
CONNECTION_SUBGRAPH * m_absorbed_by
If this subgraph is absorbed, points to the absorbing (and valid) subgraph.
std::unordered_set< CONNECTION_SUBGRAPH * > m_hier_children
If not null, this indicates the subgraph(s) on a lower level sheet that are linked to this one.
void AddItem(SCH_ITEM *aItem)
Add a new item to the subgraph.
const std::vector< std::pair< wxString, SCH_ITEM * > > GetNetclassesForDriver(SCH_ITEM *aItem) const
Return the resolved netclasses for the item, and the source item providing the netclass.
void Absorb(CONNECTION_SUBGRAPH *aOther)
Combine another subgraph on the same sheet into this one.
std::set< SCH_ITEM * > m_items
Contents of the subgraph.
std::unordered_map< std::shared_ptr< SCH_CONNECTION >, std::unordered_set< CONNECTION_SUBGRAPH * > > m_bus_parents
If this is a net, this vector contains links to any same-sheet buses that contain it.
SCH_ITEM * m_driver
Fully-resolved driver for the subgraph (might not exist in this subgraph).
CONNECTION_SUBGRAPH(CONNECTION_GRAPH *aGraph)
std::mutex m_driver_mutex
bool m_is_bus_member
True if the subgraph is not actually part of a net.
void ExchangeItem(SCH_ITEM *aOldItem, SCH_ITEM *aNewItem)
Replaces all references to #aOldItem with #aNewItem in the subgraph.
CONNECTION_SUBGRAPH * m_hier_parent
If not null, this indicates the subgraph on a higher level sheet that is linked to this one.
void RemoveItem(SCH_ITEM *aItem)
bool m_local_driver
True if the driver is a local (i.e. non-global) type.
std::set< SCH_HIERLABEL * > m_hier_ports
Cache for lookup of any hierarchical ports on this subgraph (for referring up).
void getAllConnectedItems(std::set< std::pair< SCH_SHEET_PATH, SCH_ITEM * > > &aItems, std::set< CONNECTION_SUBGRAPH * > &aSubgraphs)
Find all items in the subgraph as well as child subgraphs recursively.
virtual VECTOR2I GetPosition() const
virtual wxString GetItemDescription(UNITS_PROVIDER *aUnitsProvider, bool aFull) const
Return a user-visible description string of this item.
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.
Container for ERC settings.
bool IsTestEnabled(int aErrorCode) const
wxString AsString() const
bool GetDuplicatePinNumbersAreJumpers() const
std::vector< std::set< wxString > > & JumperPinGroups()
Each jumper pin group is a set of pin numbers that should be treated as internally connected.
A small class to help profiling.
void Show(std::ostream &aStream=std::cerr)
Print the elapsed time (in a suitable unit) to a stream.
void Stop()
Save the time when this function was called, and set the counter stane to stop.
A progress reporter interface for use in multi-threaded environments.
virtual bool KeepRefreshing(bool aWait=false)=0
Update the UI (if any).
virtual void SetCurrentProgress(double aProgress)=0
Set the progress value to aProgress (0..1).
Class for a bus to bus entry.
SCH_ITEM * m_connected_bus_items[2]
Pointer to the bus items (usually bus wires) connected to this bus-bus entry (either or both may be n...
bool IsStartDangling() const
VECTOR2I GetPosition() const override
bool IsEndDangling() const
std::vector< VECTOR2I > GetConnectionPoints() const override
Add all the connection points for this item to aPoints.
Class for a wire to bus entry.
SCH_ITEM * m_connected_bus_item
Pointer to the bus item (usually a bus wire) connected to this bus-wire entry, if it is connected to ...
Each graphical item can have a SCH_CONNECTION describing its logical connection (to a bus or net).
wxString FullLocalName() const
void ConfigureFromLabel(const wxString &aLabel)
Configures the connection given a label.
void SetSubgraphCode(int aCode)
void SetBusCode(int aCode)
void SetName(const wxString &aName)
SCH_SHEET_PATH Sheet() const
CONNECTION_TYPE Type() const
void SetNetCode(int aCode)
SCH_ITEM * m_driver
The SCH_ITEM that drives this connection's net.
bool IsDriver() const
Checks if the SCH_ITEM this connection is attached to can drive connections Drivers can be labels,...
void SetType(CONNECTION_TYPE aType)
wxString LocalName() const
wxString Name(bool aIgnoreSheet=false) const
bool IsSubsetOf(SCH_CONNECTION *aOther) const
Returns true if this connection is contained within aOther (but not the same as aOther)
void SetDriver(SCH_ITEM *aItem)
void Clone(const SCH_CONNECTION &aOther)
Copies connectivity information (but not parent) from another connection.
void SetGraph(CONNECTION_GRAPH *aGraph)
const std::vector< std::shared_ptr< SCH_CONNECTION > > & Members() const
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,...
void ClearConnectedItems(const SCH_SHEET_PATH &aPath)
Clear all connections to this item.
virtual void RunOnChildren(const std::function< void(SCH_ITEM *)> &aFunction, RECURSE_MODE aMode)
const SYMBOL * GetParentSymbol() const
virtual const wxString & GetCachedDriverName() const
const std::unordered_set< SCH_RULE_AREA * > & GetRuleAreaCache() const
Get the cache of rule areas enclosing this item.
SCH_CONNECTION * InitializeConnection(const SCH_SHEET_PATH &aPath, CONNECTION_GRAPH *aGraph)
Create a new connection object associated with this object.
void AddConnectionTo(const SCH_SHEET_PATH &aPath, SCH_ITEM *aItem)
Add a connection link between this item and another.
const std::vector< SCH_ITEM * > & ConnectedItems(const SCH_SHEET_PATH &aPath)
Retrieve the set of items connected to this item on the given sheet.
SCH_LAYER_ID GetLayer() const
Return the layer this item is on.
void SetConnectionGraph(CONNECTION_GRAPH *aGraph)
Update the connection graph for all connections in this item.
virtual void SetUnit(int aUnit)
virtual bool HasCachedDriverName() const
SCH_CONNECTION * GetOrInitConnection(const SCH_SHEET_PATH &aPath, CONNECTION_GRAPH *aGraph)
SCH_CONNECTION * Connection(const SCH_SHEET_PATH *aSheet=nullptr) const
Retrieve the connection associated with this object in the given sheet.
virtual std::vector< VECTOR2I > GetConnectionPoints() const
Add all the connection points for this item to aPoints.
wxString GetShownText(const SCH_SHEET_PATH *aPath, bool aAllowExtraText, int aDepth=0) const override
bool IsDangling() const override
LABEL_FLAG_SHAPE GetShape() const
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.
bool IsStartDangling() const
VECTOR2I GetEndPoint() const
VECTOR2I GetStartPoint() const
bool IsEndDangling() const
bool IsGraphicLine() const
Return if the line is a graphic (non electrical line)
A net chain is a collection of nets that are connected together through passive components.
const KIID & GetTerminalPinB() const
const std::set< wxString > & GetNets() const
void AddSymbol(class SCH_SYMBOL *aSymbol)
const wxString & GetTerminalRef(int aIdx) const
const wxString & GetName() const
static constexpr char SYNTHETIC_NET_PREFIX[]
Prefix used when synthesising net names for unnamed subgraphs.
static bool IsValidName(const wxString &aName)
void SetTerminalPins(const KIID &aPinA, const KIID &aPinB)
void ReplaceNets(const std::set< wxString > &aNew)
const std::set< class SCH_SYMBOL * > & GetSymbols() const
const wxString & GetTerminalPinNum(int aIdx) const
const KIID & GetTerminalPinA() const
void SetName(const wxString &aName)
void SetTerminalRefs(const wxString &aRefA, const wxString &aPinA, const wxString &aRefB, const wxString &aPinB)
bool IsGlobalPower() const
Return whether this pin forms a global power connection: i.e., is part of a power symbol and of type ...
bool IsLocalPower() const
Local power pin is the same except that it is sheet-local and it does not support the legacy hidden p...
SCH_PIN * GetLibPin() const
VECTOR2I GetPosition() const override
bool IsStacked(const SCH_PIN *aPin) const
wxString GetDefaultNetName(const SCH_SHEET_PATH &aPath, bool aForceNoConnect=false)
bool IsPower() const
Check if the pin is either a global or local power pin.
ELECTRICAL_PINTYPE GetType() const
void Append(SCH_ITEM *aItem, bool aUpdateLibSymbol=true)
void TestDanglingEnds(const SCH_SHEET_PATH *aPath=nullptr, std::function< void(SCH_ITEM *)> *aChangedHandler=nullptr) const
Test all of the connectable objects in the schematic for unused connection points.
std::vector< SCH_LINE * > GetBusesAndWires(const VECTOR2I &aPosition, bool aIgnoreEndpoints=false) const
Return buses and wires passing through aPosition.
EE_RTREE & Items()
Get the full RTree, usually for iterating.
SCH_LINE * GetBus(const VECTOR2I &aPosition, int aAccuracy=0, SCH_LINE_TEST_T aSearchType=ENTIRE_LENGTH_T) const
A container for handling SCH_SHEET_PATH objects in a flattened hierarchy.
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()
wxString PathHumanReadable(bool aUseShortRootName=true, bool aStripTrailingSeparator=false, bool aEscapeSheetNames=false) const
Return the sheet path in a human readable form made from the sheet names.
SCH_SHEET * Last() const
Return a pointer to the last SCH_SHEET of the list.
void push_back(SCH_SHEET *aSheet)
Forwarded method from std::vector.
size_t size() const
Forwarded method from std::vector.
Define a sheet pin (label) used in sheets to create hierarchical schematics.
SCH_SHEET * GetParent() const
Get the parent sheet object of this sheet pin.
Sheet symbol placed in a schematic, and is the entry point for a sub schematic.
wxString GetFileName() const
Return the filename corresponding to this sheet.
SCH_SCREEN * GetScreen() const
std::vector< SCH_SHEET_PIN * > & GetPins()
PASSTHROUGH_MODE GetPassthroughMode() 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 GetExcludedFromBoard(const SCH_SHEET_PATH *aInstance=nullptr, const wxString &aVariantName=wxEmptyString) const override
int GetUnitSelection(const SCH_SHEET_PATH *aSheet) const
Return the instance-specific unit selection for the given sheet path.
SCH_PIN * GetPin(const wxString &number) const
Find a symbol pin by number.
std::unique_ptr< LIB_SYMBOL > & GetLibSymbolRef()
const wxString GetRef(const SCH_SHEET_PATH *aSheet, bool aIncludeUnit=false) const override
VECTOR2I GetPosition() const override
virtual wxString GetShownText(const SCH_SHEET_PATH *aPath, bool aAllowExtraText, int aDepth=0) const
A base class for LIB_SYMBOL and SCH_SYMBOL.
virtual bool IsGlobalPower() const =0
virtual bool IsLocalPower() const =0
virtual bool IsPower() const =0
static int compareDrivers(SCH_ITEM *aA, SCH_CONNECTION *aAConn, const wxString &aAName, SCH_ITEM *aB, SCH_CONNECTION *aBConn, const wxString &aBName)
Unified driver ranking used by CONNECTION_SUBGRAPH::ResolveDrivers (within a single subgraph) and by ...
static wxString netChainKeyFor(const wxString &aRawNetName, long aSubgraphCode)
#define CONNECTIVITY_CANDIDATE
flag indicating that the structure is connected for connectivity
@ ERCE_DRIVER_CONFLICT
Conflicting drivers (labels, etc) on a subgraph.
@ ERCE_UNCONNECTED_WIRE_ENDPOINT
A label is connected to more than one wire.
@ ERCE_LABEL_NOT_CONNECTED
Label not connected to any pins.
@ ERCE_BUS_TO_BUS_CONFLICT
A connection between bus objects doesn't share at least one net.
@ 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_BUS_TO_NET_CONFLICT
A bus wire is graphically connected to a net port/pin (or vice versa).
@ ERCE_NOCONNECT_NOT_CONNECTED
A no connect symbol is not connected to anything.
@ ERCE_PIN_NOT_CONNECTED
Pin not connected and not no connect symbol.
@ ERCE_NOCONNECT_CONNECTED
A no connect symbol is connected to more than 1 pin.
@ ERCE_HIERACHICAL_LABEL
Mismatch between hierarchical labels and pins sheets.
@ ERCE_WIRE_DANGLING
Some wires are not connected to anything else.
@ ERCE_SINGLE_GLOBAL_LABEL
A label only exists once in the schematic.
static const wxChar DanglingProfileMask[]
Flag to enable connectivity profiling.
const wxChar *const traceSchNetChain
Flag to enable tracing of schematic net chain rebuild and ERC cross-chain checks.
static const wxChar ConnTrace[]
Flag to enable connectivity tracing.
#define KI_FALLTHROUGH
The KI_FALLTHROUGH macro is to be used when switch statement cases should purposely fallthrough from ...
void remove_duplicates(_Container &__c)
Deletes all duplicate values from __c.
@ PT_NC
not connected (must be left open)
@ PT_NIC
not internally connected (may be connected to anything)
@ PT_POWER_IN
power input (GND, VCC for ICs). Must be connected to a power output.
@ BUS
This item represents a bus vector.
@ NET
This item represents a net.
@ BUS_GROUP
This item represents a bus group.
Definition of the SCH_SHEET_PATH and SCH_SHEET_LIST classes for Eeschema.
std::vector< FAB_LAYER_COLOR > dummy
wxString UnescapeString(const wxString &aSource)
wxString EscapeString(const wxString &aSource, ESCAPE_CONTEXT aContext)
The Escape/Unescape routines use HTML-entity-reference-style encoding to handle characters which are:...
std::vector< BRIDGE_EDGE > edges
std::map< wxString, std::vector< BRIDGE_NEIGHBOR > > adjacency
const SHAPE_LINE_CHAIN chain
wxString result
Test unit parsing edge cases and error handling.
thread_pool & GetKiCadThreadPool()
Get a reference to the current thread pool.
BS::priority_thread_pool thread_pool
wxLogTrace helper definitions.
Functions to provide common constants and other functions to assist in making a consistent UI.
VECTOR2< int32_t > VECTOR2I