31#include <unordered_map>
32#include <unordered_set>
73 return static_cast<ssize_t
>(
m_items.size() )
141 if( old_conn && new_conn )
143 new_conn->
Clone( *old_conn );
177 owner =
pin->GetParentSymbol()->m_Uuid;
178 number =
pin->GetNumber();
211 return pa > pb ? -1 : 1;
218 if( b_in_a && !a_in_b )
221 if( a_in_b && !b_in_a )
230 SYMBOL* parentA =
pinA->GetLibPin() ?
pinA->GetLibPin()->GetParentSymbol() :
nullptr;
236 if( aGlobal != bGlobal )
237 return aGlobal ? -1 : 1;
242 if( aLocal != bLocal )
243 return aLocal ? -1 : 1;
261 bool aLowQuality = aAName.Contains( wxS(
"-Pad" ) );
262 bool bLowQuality = aBName.Contains( wxS(
"-Pad" ) );
264 if( aLowQuality != bLowQuality )
265 return aLowQuality ? 1 : -1;
267 if( aAName < aBName )
270 if( aBName < aAName )
286 std::set<SCH_ITEM*> strong_drivers;
310 strong_drivers.insert( item );
312 if( item_priority > highest_priority )
316 highest_priority = item_priority;
318 else if( !
candidates.empty() && ( item_priority == highest_priority ) )
348 if( strong_drivers.size() > 1 )
355 m_drivers.insert( strong_drivers.begin(), strong_drivers.end() );
377 std::set<CONNECTION_SUBGRAPH*>& aSubgraphs )
389 if( aSubgraphs.insert( sg ).second ==
false )
395 aItems.emplace(
m_sheet, item );
409#ifdef CONNECTIVITY_DEBUG
410 wxASSERT_MSG(
false, wxS(
"Tried to get the net name of an item with no connection" ) );
422 std::vector<SCH_ITEM*> labels;
426 switch( item->Type() )
436 labels.push_back( item );
452 std::vector<SCH_ITEM*> labels;
456 switch( item->Type() )
466 labels.push_back( item );
482 switch( aItem->
Type() )
489 return pin->GetDefaultNetName(
m_sheet, forceNoConnect );
516 wxFAIL_MSG( wxS(
"Unhandled item type in GetNameForDriver" ) );
517 return wxEmptyString;
537const std::vector<std::pair<wxString, SCH_ITEM*>>
540 std::vector<std::pair<wxString, SCH_ITEM*>> foundNetclasses;
542 const std::unordered_set<SCH_RULE_AREA*>& ruleAreaCache = aItem->
GetRuleAreaCache();
547 const std::vector<std::pair<wxString, SCH_ITEM*>> ruleAreaNetclasses =
548 ruleArea->GetResolvedNetclasses( &
m_sheet );
550 if( ruleAreaNetclasses.size() > 0 )
552 foundNetclasses.insert( foundNetclasses.end(), ruleAreaNetclasses.begin(),
553 ruleAreaNetclasses.end() );
569 if( netclass != wxEmptyString )
570 foundNetclasses.push_back( { netclass, aItem } );
577 foundNetclasses.begin(), foundNetclasses.end(),
578 [](
const std::pair<wxString, SCH_ITEM*>& i1,
const std::pair<wxString, SCH_ITEM*>& i2 )
580 return i1.first < i2.first;
583 return foundNetclasses;
612 child->m_absorbed_by =
this;
615 set_absorbed_by( subchild );
623 set_absorbed_by( aOther );
673 if(
const std::unique_ptr<LIB_SYMBOL>& part = symbol->GetLibSymbolRef() )
674 return part->GetReferenceField().GetText();
676 return wxEmptyString;
679 switch( aDriver->
Type() )
710 std::back_inserter(
m_items ) );
761 existing.push_back( sg );
782 wxCHECK2( aOldItem->
Type() == aNewItem->
Type(),
return );
792 std::vector<CONNECTION_SUBGRAPH*> sgs = std::move( it->second );
795 sg->ExchangeItem( aOld, aNew );
799 aNew->registerConnectivityOwner(
m_lifetime );
820 wxCHECK2( oldPins.size() == newPins.size(),
return );
822 for(
size_t ii = 0; ii < oldPins.size(); ii++ )
823 exchange( oldPins[ii], newPins[ii] );
833 if( subgraph->m_graph ==
this )
859 std::function<
void(
SCH_ITEM* )>* aChangedItemHandler,
863 PROF_TIMER recalc_time(
"CONNECTION_GRAPH::Recalculate" );
864 monitorTrans.
Start();
869 monitorTrans.
StartSpan(
"updateItemConnectivity",
"" );
870 PROF_TIMER update_items(
"updateItemConnectivity" );
873 std::set<SCH_ITEM*> dirty_items;
875 int count = aSheetList.size() * 2;
880 if( aProgressReporter )
886 std::vector<SCH_ITEM*> items;
889 std::vector<std::pair<SCH_SYMBOL*, int>> symbolsChanged;
891 for(
SCH_ITEM* item : sheet.LastScreen()->Items() )
893 if( item->IsConnectable() && ( aUnconditional || item->IsConnectivityDirty() ) )
895 wxLogTrace(
ConnTrace, wxT(
"Adding item %s to connectivity graph update" ), item->GetTypeDesc() );
896 items.push_back( item );
897 dirty_items.insert( item );
906 if(
pin->IsConnectivityDirty() )
908 dirty_items.insert(
pin );
920 if(
pin->IsConnectivityDirty() )
922 dirty_items.insert(
pin );
935 if(
pin->IsConnectivityDirty() )
937 items.push_back(
pin );
938 dirty_items.insert(
pin );
948 if(
pin->IsConnectivityDirty() )
950 items.push_back(
pin );
951 dirty_items.insert(
pin );
964 if( symbol->
GetUnit() != new_unit )
965 symbolsChanged.push_back( { symbol, symbol->
GetUnit() } );
975 if( aProgressReporter )
982 sheet.LastScreen()->TestDanglingEnds( &sheet, aChangedItemHandler );
985 for(
const auto& [ symbol, originalUnit ] : symbolsChanged )
986 symbol->SetUnit( originalUnit );
997 item->SetConnectivityDirty(
false );
1002 update_items.
Show();
1004 PROF_TIMER build_graph(
"buildConnectionGraph" );
1005 monitorTrans.
StartSpan(
"BuildConnectionGraph",
"" );
1026std::set<std::pair<SCH_SHEET_PATH, SCH_ITEM*>>
1029 std::set<std::pair<SCH_SHEET_PATH, SCH_ITEM*>> retvals;
1030 std::set<CONNECTION_SUBGRAPH*> subgraphs;
1032 auto traverse_subgraph =
1036 while( aSubgraph->m_absorbed_by )
1039 wxASSERT( aSubgraph->m_graph == aSubgraph->m_absorbed_by->m_graph );
1040 aSubgraph = aSubgraph->m_absorbed_by;
1044 while( aSubgraph->m_hier_parent )
1047 wxASSERT( aSubgraph->m_graph == aSubgraph->m_hier_parent->m_graph );
1048 aSubgraph = aSubgraph->m_hier_parent;
1052 aSubgraph->getAllConnectedItems( retvals, subgraphs );
1055 auto scan_subgraphs =
1056 [&traverse_subgraph](
const std::vector<CONNECTION_SUBGRAPH*>& aScanList )
1060 traverse_subgraph( sg );
1062 for(
auto& bus_it : sg->m_bus_neighbors )
1065 traverse_subgraph( bus_sg );
1068 for(
auto& bus_it : sg->m_bus_parents )
1071 traverse_subgraph( bus_sg );
1076 auto extract_element =
1083 wxLogTrace(
ConnTrace, wxT(
"Item %s not found in connection graph" ),
1084 aItem->GetTypeDesc() );
1088 if( aItem->HasCachedDriverName() )
1096 wxLogTrace(
ConnTrace, wxT(
"Item %s in subgraph %ld (%p) has no driver" ),
1097 aItem->GetTypeDesc(), item_sg->
m_code, item_sg );
1102 if( sg_to_scan.empty() )
1104 wxLogTrace(
ConnTrace, wxT(
"Item %s in subgraph %ld with net %s has no neighbors" ),
1106 sg_to_scan.push_back( item_sg );
1109 wxLogTrace(
ConnTrace, wxT(
"Removing all item %s connections from subgraph %ld with net %s: "
1110 "Found %zu subgraphs" ),
1111 aItem->GetTypeDesc(), item_sg->
m_code, item_sg->
GetNetName(), sg_to_scan.size() );
1113 scan_subgraphs( sg_to_scan );
1125 extract_element(
pin );
1132 extract_element(
pin );
1136 extract_element( item );
1142 for(
const auto& [
path, item] : retvals )
1156 [aItem](
const std::pair<SCH_SHEET_PATH, SCH_PIN*>& aEntry )
1158 return aEntry.second == aItem;
1183 wxLogTrace(
ConnTrace, wxT(
"Removing %zu subgraphs" ), aSubgraphs.size() );
1186 std::set<int> codes_to_remove;
1190 std::sort( el.second.begin(), el.second.end() );
1195 for(
auto& it : sg->m_bus_neighbors )
1201 for(
auto test = parents.begin();
test != parents.end(); )
1209 if( parents.empty() )
1214 for(
auto& it : sg->m_bus_parents )
1220 for(
auto test = neighbors.begin();
test != neighbors.end(); )
1228 if( neighbors.empty() )
1249 auto it = std::lower_bound( el.second.begin(), el.second.end(), sg );
1251 while( it != el.second.end() && *it == sg )
1252 it = el.second.erase( it );
1255 auto remove_sg = [sg](
auto it ) ->
bool
1268 if( remove_sg( it ) )
1276 if( remove_sg( it ) )
1285 if( remove_sg( it ) )
1287 codes_to_remove.insert( it->first.Netcode );
1299 if( remove_sg( it ) )
1307 std::erase( it->second, sg );
1309 if( it->second.empty() )
1320 if( codes_to_remove.contains( it->second ) )
1328 if( codes_to_remove.contains( it->second ) )
1337 sg->m_graph =
nullptr;
1344 std::map<
VECTOR2I, std::vector<SCH_ITEM*>>& aConnectionMap )
1355 aConn->SetName(
name );
1360 std::map<wxString, std::vector<SCH_PIN*>> pinNumberMap;
1366 updatePin(
pin, conn );
1367 aConnectionMap[
pin->GetPosition() ].push_back(
pin );
1368 pinNumberMap[
pin->GetNumber()].emplace_back(
pin );
1371 auto linkPinsInVec =
1372 [&](
const std::vector<SCH_PIN*>& aVec )
1374 for(
size_t i = 0; i < aVec.size(); ++i )
1376 for(
size_t j = i + 1; j < aVec.size(); ++j )
1378 aVec[i]->AddConnectionTo( aSheet, aVec[j] );
1379 aVec[j]->AddConnectionTo( aSheet, aVec[i] );
1388 for(
const auto& [number,
group] : pinNumberMap )
1389 linkPinsInVec(
group );
1394 std::vector<SCH_PIN*> pins;
1396 for(
const wxString& pinNumber :
group.GetNames() )
1415 pins.emplace_back( found );
1418 linkPinsInVec( pins );
1441 std::map<
VECTOR2I, std::vector<SCH_ITEM*>>& aConnectionMap )
1446 m_items.emplace_back( aItem );
1449 switch( aItem->
Type() )
1462 if( points.empty() )
1463 points = {
static_cast<SCH_PIN*
>( aItem )->GetPosition() };
1476 for(
const VECTOR2I& point : points )
1477 aConnectionMap[point].push_back( aItem );
1482 const std::vector<SCH_ITEM*>& aItemList )
1484 wxLogTrace( wxT(
"Updating connectivity for sheet %s with %zu items" ),
1486 std::map<VECTOR2I, std::vector<SCH_ITEM*>> connection_map;
1490 std::vector<VECTOR2I> points = item->GetConnectionPoints();
1491 item->ClearConnectedItems( aSheet );
1496 pin->InitializeConnection( aSheet,
this );
1498 pin->ClearConnectedItems( aSheet );
1500 connection_map[
pin->GetTextPos() ].push_back(
pin );
1517 VECTOR2I point = item->GetPosition();
1520 std::vector<SCH_ITEM*> overlapping_items;
1522 std::copy_if( items.begin(), items.end(), std::back_inserter( overlapping_items ),
1525 return test_item->Type() == SCH_LINE_T
1526 && test_item->HitTest( point, -1 );
1531 if( overlapping_items.size() < 2 )
continue;
1533 for(
SCH_ITEM* test_item : overlapping_items )
1534 connection_map[point].push_back( test_item );
1543 VECTOR2I point = item->GetPosition();
1547 connection_map[point].push_back( wire );
1552 for(
auto& [point, connection_vec] : connection_map )
1554 std::sort( connection_vec.begin(), connection_vec.end() );
1560 for(
SCH_ITEM* connected_item : connection_vec )
1574 if( connection_vec.size() == 1 )
1590 if( point == bus_entry->GetPosition() )
1593 bus_entry->m_connected_bus_items[1] = busLine;
1606 for(
SCH_ITEM* test_item : connection_vec )
1608 bool bus_connection_ok =
true;
1610 if( test_item == connected_item )
1616 if( test_item->GetLayer() ==
LAYER_BUS )
1635 if( connected_item->ConnectionPropagatesTo( test_item )
1636 && test_item->ConnectionPropagatesTo( connected_item )
1637 && bus_connection_ok )
1639 connected_item->AddConnectionTo( aSheet, test_item );
1650 if( !bus_entry->m_connected_bus_item )
1656 bus_entry->m_connected_bus_item = bus;
1667 wxCHECK_RET(
m_schematic, wxS(
"Connection graph cannot be built without schematic pointer" ) );
1671 for(
const std::shared_ptr<BUS_ALIAS>& alias :
m_schematic->GetAllBusAliases() )
1680 std::unordered_map<SCH_SHEET_PATH, size_t> sheetOrder;
1689 auto it = sheetOrder.find( aSheet );
1691 return ( it == sheetOrder.end() ) ? std::numeric_limits<size_t>::max()
1697 std::vector<std::tuple<size_t, SCH_SHEET_PATH, SCH_CONNECTION*>> ordered;
1702 ordered.reserve( item->m_connection_map.size() );
1706 for(
const auto& [sheet, connection] : item->m_connection_map )
1707 ordered.emplace_back( sheetRank( sheet ), sheet, connection );
1709 std::sort( ordered.begin(), ordered.end(),
1710 [](
const auto& a,
const auto& b )
1712 return std::get<0>( a ) < std::get<0>( b );
1715 for(
const auto& [rank, sheet, connection] : ordered )
1717 if( connection->SubgraphCode() == 0 )
1726 connection->SetSubgraphCode( subgraph->
m_code );
1728 item->registerConnectivityOwner(
m_lifetime );
1730 std::list<SCH_ITEM*> memberlist;
1735 SCH_CONNECTION* conn = aItem->GetOrInitConnection( sheet,
this );
1741 return ( unique && conn && ( conn->
SubgraphCode() == 0 ) );
1744 std::copy_if( item->ConnectedItems( sheet ).begin(),
1745 item->ConnectedItems( sheet ).end(),
1746 std::back_inserter( memberlist ), get_items );
1748 for(
SCH_ITEM* connected_item : memberlist )
1753 SCH_CONNECTION* connected_conn = connected_item->Connection( &sheet );
1755 wxCHECK2( connected_conn,
continue );
1761 connected_item->registerConnectivityOwner(
m_lifetime );
1762 subgraph->
AddItem( connected_item );
1769 if( get_items( citem ) )
1770 memberlist.push_back( citem );
1775 for(
SCH_ITEM* connected_item : memberlist )
1789 std::vector<CONNECTION_SUBGRAPH*> dirty_graphs;
1794 return candidate->m_dirty;
1797 wxLogTrace(
ConnTrace, wxT(
"Resolving drivers for %zu subgraphs" ), dirty_graphs.size() );
1799 std::vector<std::future<size_t>> returns( dirty_graphs.size() );
1801 auto update_lambda =
1804 if( !subgraph->m_dirty )
1808 for(
SCH_ITEM* item : subgraph->m_items )
1810 switch( item->
Type() )
1813 subgraph->m_no_connect = item;
1817 subgraph->m_bus_entry = item;
1825 subgraph->m_no_connect = item;
1835 subgraph->ResolveDrivers(
true );
1836 subgraph->m_dirty =
false;
1843 auto results =
tp.submit_loop( 0, dirty_graphs.size(),
1846 update_lambda( dirty_graphs[ii] );
1855 return candidate->m_driver;
1868 wxString full_name = subgraph->m_driver_connection->Name();
1869 wxString
name = subgraph->m_driver_connection->Name(
true );
1878 wxString prefixOnly = full_name.BeforeFirst(
'[' ) + wxT(
"[]" );
1882 subgraph->m_dirty =
true;
1884 if( subgraph->m_strong_driver )
1886 SCH_ITEM* driver = subgraph->m_driver;
1889 switch( driver->
Type() )
1905 if(
pin->IsGlobalPower() )
1909 else if(
pin->IsLocalPower() )
1916 wxLogTrace(
ConnTrace, wxS(
"Unexpected normal pin %s" ),
1926 wxLogTrace(
ConnTrace, wxS(
"Unexpected strong driver %s" ),
1938 std::vector<CONNECTION_SUBGRAPH*> new_subgraphs;
1942 for(
SCH_ITEM* item : subgraph->GetAllBusLabels() )
1947 dummy.SetGraph(
this );
1950 wxLogTrace(
ConnTrace, wxS(
"new bus label (%s)" ),
1953 for(
const auto& conn :
dummy.Members() )
1956 if( !conn->IsNet() )
1959 wxString
name = conn->FullLocalName();
1966 auto new_conn = std::make_unique<SCH_CONNECTION>( item, subgraph->m_sheet );
1967 new_conn->SetGraph(
this );
1968 new_conn->SetName(
name );
1971 SCH_CONNECTION* new_conn_ptr = subgraph->StoreImplicitConnection( std::move( new_conn ) );
1974 wxLogTrace(
ConnTrace, wxS(
"SG(%ld), Adding full local name (%s) with sg (%d) on subsheet %s" ),
1975 subgraph->m_code,
name, code, subgraph->m_sheet.PathHumanReadable() );
1988 new_subgraphs.push_back( new_sg );
1993 std::copy( new_subgraphs.begin(), new_subgraphs.end(),
2009 [](
const std::pair<SCH_SHEET_PATH, SCH_PIN*>& a,
2010 const std::pair<SCH_SHEET_PATH, SCH_PIN*>& b )
2012 int pathCmp = a.first.Cmp( b.first );
2017 const SCH_SYMBOL* symA = static_cast<const SCH_SYMBOL*>( a.second->GetParentSymbol() );
2018 const SCH_SYMBOL* symB = static_cast<const SCH_SYMBOL*>( b.second->GetParentSymbol() );
2020 wxString refA = symA ? symA->GetRef( &a.first, false ) : wxString();
2021 wxString refB = symB ? symB->GetRef( &b.first, false ) : wxString();
2023 int refCmp = refA.Cmp( refB );
2028 return a.second->GetNumber().Cmp( b.second->GetNumber() ) < 0;
2031 std::unordered_map<int, CONNECTION_SUBGRAPH*> global_power_pin_subgraphs;
2035 SYMBOL* libParent =
pin->GetLibPin() ?
pin->GetLibPin()->GetParentSymbol() :
nullptr;
2037 if( !
pin->ConnectedItems( sheet ).empty()
2063 auto jj = global_power_pin_subgraphs.find( code );
2065 if( jj != global_power_pin_subgraphs.end() )
2067 subgraph = jj->second;
2085 global_power_pin_subgraphs[code] = subgraph;
2098 std::unordered_map<wxString, std::vector<size_t>> weakConflicts;
2107 const wxString
name = connection->
Name();
2111 weakConflicts[
name].push_back( i );
2117 for(
const auto& [
name, positions] : weakConflicts )
2119 if( positions.size() < 2 )
2124 std::vector<std::pair<SUBGRAPH_IDENTITY, CONNECTION_SUBGRAPH*>> ordered;
2125 ordered.reserve( positions.size() );
2127 for(
size_t position : positions )
2135 std::sort( ordered.begin(), ordered.end(),
2136 [](
const auto&
left,
const auto&
right )
2138 return left.first < right.first;
2141 for(
size_t i = 0; i < positions.size(); ++i )
2149 std::unordered_set<CONNECTION_SUBGRAPH*> invalidated_subgraphs;
2153 if( subgraph->m_absorbed )
2158 wxString
name = connection->
Name();
2161 unsigned suffix = 1;
2163 wxString base_name = connection->
Name();
2165 auto create_new_name =
2168 wxString suffixStr = std::to_wstring( suffix );
2175 wxString prefix = aConn->BusPrefix();
2177 if( prefix.empty() )
2178 prefix = wxT(
"BUS" );
2183 wxString members = base_name.Mid( aConn->BusPrefix().length() );
2186 newName << prefix << wxT(
"_" ) << suffixStr << members;
2188 aConn->ConfigureFromLabel( newName );
2194 aConn->SetSuffix( wxString( wxT(
"_" ) ) << suffixStr );
2198 return aConn->Name();
2205 auto promote_sheet_pin_driver =
2208 if( !subgraph->m_driver || subgraph->m_driver->Type() !=
SCH_SHEET_PIN_T )
2211 wxString global_name = connection->
Name(
true );
2218 if( candidate->
m_sheet == sheet )
2221 wxS(
"%ld (%s) skipped for promotion due to potential conflict" ),
2222 subgraph->m_code, connection->
Name() );
2228 subgraph->m_strong_driver =
true;
2231 if( !subgraph->m_strong_driver )
2233 std::vector<CONNECTION_SUBGRAPH*> vec_empty;
2234 std::vector<CONNECTION_SUBGRAPH*>* vec = &vec_empty;
2243 wxString prefixOnly =
name.BeforeFirst(
'[' ) + wxT(
"[]" );
2249 if( vec->size() > 1 )
2251 wxString new_name = create_new_name( connection );
2254 new_name = create_new_name( connection );
2256 wxLogTrace(
ConnTrace, wxS(
"%ld (%s) is weakly driven and not unique. Changing to %s." ),
2257 subgraph->m_code,
name, new_name );
2259 std::erase( *vec, subgraph );
2267 promote_sheet_pin_driver();
2269 else if( subgraph->m_driver )
2271 promote_sheet_pin_driver();
2276 if( connection->
IsBus() )
2300 subgraph->m_dirty =
true;
2308 if( !subgraph->m_strong_driver )
2315 std::vector<CONNECTION_SUBGRAPH*> candidate_subgraphs;
2318 std::back_inserter( candidate_subgraphs ),
2321 return ( !candidate->m_absorbed &&
2322 candidate->m_strong_driver &&
2323 candidate != subgraph );
2329 std::vector< std::shared_ptr<SCH_CONNECTION> > connections_to_check;
2332 connections_to_check.push_back( std::make_shared<SCH_CONNECTION>( *connection ) );
2334 auto add_connections_to_check =
2337 for(
SCH_ITEM* possible_driver : aSubgraph->m_items )
2339 if( possible_driver == aSubgraph->m_driver )
2346 if( c->Type() != aSubgraph->m_driver_connection->Type() )
2349 if( c->Name(
true ) == aSubgraph->m_driver_connection->Name(
true ) )
2352 connections_to_check.push_back( c );
2353 wxLogTrace(
ConnTrace, wxS(
"%lu (%s): Adding secondary driver %s" ),
2355 aSubgraph->m_driver_connection->Name(
true ),
2364 add_connections_to_check( subgraph );
2366 std::set<SCH_CONNECTION*> checked_connections;
2368 for(
unsigned i = 0; i < connections_to_check.size(); i++ )
2370 auto member = connections_to_check[i];
2373 if( !checked_connections.insert( member.get() ).second )
2376 if( member->IsBus() )
2378 connections_to_check.insert( connections_to_check.end(),
2379 member->Members().begin(),
2380 member->Members().end() );
2383 wxString test_name = member->Name(
true );
2387 if( candidate->
m_absorbed || candidate == subgraph )
2403 if( driver == candidate->
m_driver )
2415 &&
pin->GetDefaultNetName( sheet ) == test_name )
2428 if( subgraph->GetNameForDriver( driver ) == test_name )
2441 wxLogTrace(
ConnTrace, wxS(
"%lu (%s) has bus child %lu (%s)" ),
2442 subgraph->m_code, connection->
Name(),
2443 candidate->
m_code, member->Name() );
2445 subgraph->m_bus_neighbors[member].insert( candidate );
2448 else if( ( !connection->
IsBus()
2452 wxLogTrace(
ConnTrace, wxS(
"%lu (%s) absorbs neighbor %lu (%s)" ),
2453 subgraph->m_code, connection->
Name(),
2457 add_connections_to_check( candidate );
2459 subgraph->Absorb( candidate );
2460 invalidated_subgraphs.insert( subgraph );
2470 if( subgraph->m_absorbed )
2473 if( !subgraph->ResolveDrivers() )
2476 if( subgraph->m_driver_connection->IsBus() )
2481 wxLogTrace(
ConnTrace, wxS(
"Re-resolving drivers for %lu (%s)" ),
2482 subgraph->m_code, subgraph->m_driver_connection->Name() );
2501 bool aUnconditional )
2504 wxCHECK_RET(
m_schematic, wxT(
"Connection graph cannot be built without schematic pointer" ) );
2508 for(
const std::shared_ptr<BUS_ALIAS>& alias :
m_schematic->GetAllBusAliases() )
2514 PROF_TIMER sub_graph(
"buildItemSubGraphs" );
2533 PROF_TIMER proc_sub_graph(
"ProcessSubGraphs" );
2537 proc_sub_graph.
Show();
2546 std::vector<CONNECTION_SUBGRAPH*> global_subgraphs;
2548 std::back_inserter( global_subgraphs ),
2551 return !candidate->m_local_driver;
2565 m_driver_subgraphs[ii]->UpdateItemConnections();
2587 if( !global_subgraphs.empty() )
2589 std::unordered_map<CONNECTION_SUBGRAPH*, CONNECTION_SUBGRAPH*> sg_root;
2598 auto it = sg_root.find( cur );
2600 if( it == sg_root.end() || it->second == cur )
2605 auto parent_it = sg_root.find( it->second );
2607 if( parent_it != sg_root.end() && parent_it->second != it->second )
2608 it->second = parent_it->second;
2618 auto prefer_as_representative =
2623 aB->m_driver, aB->m_driver_connection,
2624 aB->m_driver_connection->Name() ) < 0;
2630 sg_root.try_emplace( aA, aA );
2631 sg_root.try_emplace( aB, aB );
2636 if( root_a == root_b )
2639 if( prefer_as_representative( root_a, root_b ) )
2640 sg_root[root_b] = root_a;
2642 sg_root[root_a] = root_b;
2645 std::unordered_map<wxString, std::vector<CONNECTION_SUBGRAPH*>> name_to_sgs;
2649 for(
SCH_ITEM* driver : subgraph->m_drivers )
2657 name_to_sgs[subgraph->GetNameForDriver( driver )].push_back( subgraph );
2661 for(
auto& [
name, sgs] : name_to_sgs )
2663 if( sgs.size() < 2 )
2666 for(
size_t ii = 1; ii < sgs.size(); ++ii )
2667 union_sgs( sgs[0], sgs[ii] );
2673 for(
const auto& entry : sg_root )
2684 wxLogTrace(
ConnTrace, wxS(
"Global %lu (%s) canonicalized to %lu (%s)" ),
2697 if( !subgraph->m_dirty )
2700 wxLogTrace(
ConnTrace, wxS(
"Processing %lu (%s) for propagation" ),
2701 subgraph->m_code, subgraph->m_driver_connection->Name() );
2707 if( !subgraph->m_local_driver && subgraph->m_multiple_drivers )
2709 for(
SCH_ITEM* driver : subgraph->m_drivers )
2711 if( driver == subgraph->m_driver )
2714 const wxString& secondary_name = subgraph->GetNameForDriver( driver );
2716 if( secondary_name == subgraph->m_driver_connection->Name() )
2724 if( candidate == subgraph )
2727 if( !secondary_is_global && candidate->
m_sheet != subgraph->m_sheet )
2734 wxLogTrace(
ConnTrace, wxS(
"Global %lu (%s) promoted to %s" ),
2736 subgraph->m_driver_connection->Name() );
2758 if( subgraph->m_dirty )
2775 wxASSERT_MSG( !subgraph->m_dirty,
2776 wxS(
"Subgraph not processed by propagateToNeighbors!" ) );
2778 if( subgraph->m_bus_parents.size() < 2 )
2783 wxLogTrace(
ConnTrace, wxS(
"%lu (%s) has multiple bus parents" ),
2784 subgraph->m_code, conn->
Name() );
2787 wxCHECK2( conn->
IsNet(),
continue );
2789 for(
const auto& ii : subgraph->m_bus_parents )
2802 wxLogTrace(
ConnTrace, wxS(
"Warning: could not match %s inside %lu (%s)" ),
2807 if( conn->
Name() != match->
Name() )
2809 wxString old_name = match->
Name();
2811 wxLogTrace(
ConnTrace, wxS(
"Updating %lu (%s) member %s to %s" ),
2814 match->
Clone( *conn );
2822 std::vector<CONNECTION_SUBGRAPH*> old_subgraphs = jj->second;
2826 while( old_sg->m_absorbed )
2827 old_sg = old_sg->m_absorbed_by;
2829 wxString old_sg_name = old_sg->m_driver_connection->Name();
2830 old_sg->m_driver_connection->Clone( *conn );
2832 if( old_sg_name != old_sg->m_driver_connection->Name() )
2843 auto propagateConnectionsTask =
2847 if( !subgraph->m_strong_driver
2848 && subgraph->m_drivers.size() == 1
2849 && subgraph->m_driver->Type() ==
SCH_PIN_T )
2852 wxString
name =
pin->GetDefaultNetName( subgraph->m_sheet,
true );
2854 subgraph->m_driver_connection->ConfigureFromLabel(
name );
2857 subgraph->m_dirty =
false;
2858 subgraph->UpdateItemConnections();
2864 propagateConnectionsTask( m_driver_subgraphs[ii] );
2873 if( subgraph->m_driver_connection->IsBus() )
2876 if( !subgraph->m_driver || subgraph->m_driver->Type() !=
SCH_SHEET_PIN_T )
2895 path.push_back( sheet );
2899 if( parent_conn && parent_conn->
IsBus() )
2913 subgraph->m_driver_connection->NetCode() };
2919 std::shared_ptr<NET_SETTINGS>& netSettings =
m_schematic->Project().GetProjectFile().m_NetSettings;
2920 std::map<wxString, std::set<wxString>> oldAssignments = netSettings->GetNetclassLabelAssignments();
2921 std::set<wxString> affectedNetclassNetAssignments;
2923 netSettings->ClearNetclassLabelAssignments();
2925 auto dirtySubgraphs =
2926 [&](
const std::vector<CONNECTION_SUBGRAPH*>& subgraphs )
2928 if( aChangedItemHandler )
2932 for(
SCH_ITEM* item : subgraph->m_items )
2933 (*aChangedItemHandler)( item );
2938 auto checkNetclassDrivers =
2939 [&](
const wxString& netName,
const std::vector<CONNECTION_SUBGRAPH*>& subgraphs )
2941 wxCHECK_RET( !subgraphs.empty(), wxS(
"Invalid empty subgraph" ) );
2943 std::set<wxString> netclasses;
2948 for(
SCH_ITEM* item : subgraph->m_items )
2950 for(
const auto& [
name, provider] : subgraph->GetNetclassesForDriver( item ) )
2951 netclasses.insert(
name );
2958 if( subgraph->m_driver_connection->IsBus() )
2960 auto processBusMember = [&,
this](
const SCH_CONNECTION* member )
2962 if( !netclasses.empty() )
2964 netSettings->AppendNetclassLabelAssignment( member->Name(), netclasses );
2969 if( oldAssignments.count( member->Name() ) )
2971 if( oldAssignments[member->Name()] != netclasses )
2973 affectedNetclassNetAssignments.insert( member->Name() );
2976 dirtySubgraphs( ii->second );
2979 else if( !netclasses.empty() )
2981 affectedNetclassNetAssignments.insert( member->Name() );
2984 dirtySubgraphs( ii->second );
2988 for(
const std::shared_ptr<SCH_CONNECTION>& member : subgraph->m_driver_connection->Members() )
2992 if( member->IsBus() )
2994 for(
const std::shared_ptr<SCH_CONNECTION>& nestedMember : member->Members() )
2995 processBusMember( nestedMember.get() );
2999 processBusMember( member.get() );
3006 if( !netclasses.empty() )
3008 netSettings->AppendNetclassLabelAssignment( netName, netclasses );
3011 if( oldAssignments.count( netName ) )
3013 if( oldAssignments[netName] != netclasses )
3015 affectedNetclassNetAssignments.insert( netName );
3016 dirtySubgraphs( subgraphs );
3019 else if( !netclasses.empty() )
3021 affectedNetclassNetAssignments.insert( netName );
3022 dirtySubgraphs( subgraphs );
3028 checkNetclassDrivers( netname, subgraphs );
3030 if( !aUnconditional )
3032 for(
auto& [netname, netclasses] : oldAssignments )
3034 if( netSettings->GetNetclassLabelAssignments().count( netname )
3035 || affectedNetclassNetAssignments.count( netname ) )
3040 netSettings->SetNetclassLabelAssignment( netname, netclasses );
3063 std::unordered_map<SCH_SHEET_PATH, SCH_CONNECTIVITY::NETCHAIN_INPUT::SHEET*> sheets;
3068 sheets.emplace(
path, &connectivity.
sheets.back() );
3081 const auto sheet = sheets.find( subgraph->GetSheet() );
3083 if( sheet == sheets.end() )
3086 while( subgraph && subgraph->m_absorbed )
3087 subgraph = subgraph->m_absorbed_by;
3091 const wxString
name = subgraph->GetNetName();
3092 sheet->second->nets.insert_or_assign(
3105 const std::map<std::pair<wxString, wxString>, wxString>& aRefPinToNet,
3106 const std::vector<std::unique_ptr<SCH_NETCHAIN>>& aPotentials,
3107 const wxString& aChainName )
3110 aTermRefs, aRefPinToNet, aPotentials, aChainName );
3125 return m_netChains->DeleteCommittedNetChain( aName );
3130 return m_netChains->RenameCommittedNetChain( aOld, aNew );
3142 return m_netChains->CreateNetChainFromPotential( aPotential, aName );
3146 const std::set<SCH_SYMBOL*>& aSymbols,
const std::set<wxString>& aNets,
3147 const KIID& aTerminalPinA,
const KIID& aTerminalPinB,
3148 const wxString& aRefA,
const wxString& aPinNumA,
3149 const wxString& aRefB,
const wxString& aPinNumB )
3151 return m_netChains->CreateManualNetChain( aName, aSymbols, aNets, aTerminalPinA, aTerminalPinB,
3152 aRefA, aPinNumA, aRefB, aPinNumB );
3188 std::vector<std::shared_ptr<SCH_CONNECTION>> connections_to_check( aConnection->
Members() );
3190 for(
unsigned i = 0; i < connections_to_check.size(); i++ )
3192 const std::shared_ptr<SCH_CONNECTION>& member = connections_to_check[i];
3194 if( member->IsBus() )
3196 connections_to_check.insert( connections_to_check.end(),
3197 member->Members().begin(),
3198 member->Members().end() );
3210 std::vector<CONNECTION_SUBGRAPH*> search_list;
3211 std::unordered_set<CONNECTION_SUBGRAPH*> visited;
3212 std::unordered_set<SCH_CONNECTION*> stale_bus_members;
3219 path.push_back(
pin->GetParent() );
3230 || visited.contains( candidate ) )
3239 wxLogTrace(
ConnTrace, wxS(
"%lu: found child %lu (%s)" ), aParent->m_code,
3247 wxASSERT( candidate->
m_graph == aParent->m_graph );
3249 search_list.push_back( candidate );
3269 || visited.contains( candidate )
3275 const KIID& last_parent_uuid = aParent->m_sheet.Last()->m_Uuid;
3280 if(
pin->GetParent()->m_Uuid != last_parent_uuid )
3286 if( pin_path != aParent->m_sheet )
3291 wxLogTrace(
ConnTrace, wxS(
"%lu: found additional parent %lu (%s)" ),
3294 aParent->m_hier_children.insert( candidate );
3295 search_list.push_back( candidate );
3309 std::vector<std::shared_ptr<SCH_CONNECTION>> sortedMembers;
3311 for(
const auto&
kv : aParentGraph->m_bus_neighbors )
3312 sortedMembers.push_back(
kv.first );
3314 std::sort( sortedMembers.begin(), sortedMembers.end(),
3315 [](
const std::shared_ptr<SCH_CONNECTION>& a,
3316 const std::shared_ptr<SCH_CONNECTION>& b )
3318 return a->Name() < b->Name();
3321 for(
const std::shared_ptr<SCH_CONNECTION>& member_conn : sortedMembers )
3323 const auto& kv_it = aParentGraph->m_bus_neighbors.find( member_conn );
3325 if( kv_it == aParentGraph->m_bus_neighbors.end() )
3368 wxLogTrace(
ConnTrace, wxS(
"Could not match bus member %s in %s" ),
3369 member_conn->Name(), parent->
Name() );
3375 wxCHECK2( neighbor_conn,
continue );
3377 wxString neighbor_name = neighbor_conn->
Name();
3380 if( neighbor_name == member->
Name() )
3390 if( neighbor_conn->
Sheet() != parent->
Sheet() )
3401 bool alreadyUpdatedByBusMember =
false;
3403 for(
const auto& m : parent->
Members() )
3405 if( m->Name() == neighbor_name )
3407 alreadyUpdatedByBusMember =
true;
3412 if( alreadyUpdatedByBusMember )
3417 wxCHECK2_MSG( neighbor_conn->
IsNet(),
continue,
3418 wxS(
"\"" ) + neighbor_name + wxS(
"\" is not a net." ) );
3420 wxLogTrace(
ConnTrace, wxS(
"%lu (%s) connected to bus member %s (local %s)" ),
3427 member->
Clone( *neighbor_conn );
3428 stale_bus_members.insert( member );
3432 neighbor_conn->
Clone( *member );
3445 if( neighbor_conn->
Name() != member->
Name() )
3447 member->
Clone( *neighbor_conn );
3448 stale_bus_members.insert( member );
3457 propagate_bus_neighbors( aSubgraph );
3464 wxLogTrace(
ConnTrace, wxS(
"%lu (%s) has both hier ports and pins; deferring processing" ),
3470 wxLogTrace(
ConnTrace, wxS(
"%lu (%s) has no hier pins or ports on sheet %s; marking clean" ),
3476 visited.insert( aSubgraph );
3478 wxLogTrace(
ConnTrace, wxS(
"Propagating %lu (%s) to subsheets" ),
3483 for(
unsigned i = 0; i < search_list.size(); i++ )
3485 auto child = search_list[i];
3487 if( visited.insert( child ).second )
3490 child->m_dirty =
false;
3504 if( subgraph == aSubgraph )
3511 wxString candidateName = subgraph->m_driver_connection->Name();
3512 bool shorterPath = subgraph->m_sheet.size() < bestDriver->
m_sheet.
size();
3513 bool asGoodPath = subgraph->m_sheet.size() <= bestDriver->
m_sheet.
size();
3521 if( ( !bestIsStrong && candidateStrong ) ||
3522 ( priority > highest && candidateStrong ) ||
3523 ( priority == highest && candidateStrong && shorterPath ) ||
3524 ( ( bestIsStrong == candidateStrong ) && asGoodPath && ( priority == highest ) &&
3525 ( candidateName < bestName ) ) )
3527 bestDriver = subgraph;
3529 bestIsStrong = candidateStrong;
3530 bestName = candidateName;
3535 if( bestDriver != aSubgraph )
3537 wxLogTrace(
ConnTrace, wxS(
"%lu (%s) overridden by new driver %lu (%s)" ),
3546 wxString old_name = subgraph->m_driver_connection->Name();
3548 subgraph->m_driver_connection->Clone( *conn );
3550 if( old_name != conn->
Name() )
3554 propagate_bus_neighbors( subgraph );
3560 if( conn->
IsBus() && !stale_bus_members.empty() )
3562 std::unordered_set<SCH_CONNECTION*> cached_members = stale_bus_members;
3572 wxLogTrace(
ConnTrace, wxS(
"WARNING: failed to match stale member %s in %s." ),
3573 stale_member->Name(), subgraph->m_driver_connection->Name() );
3577 wxLogTrace(
ConnTrace, wxS(
"Updating %lu (%s) member %s to %s" ), subgraph->m_code,
3578 subgraph->m_driver_connection->Name(), member->
LocalName(), stale_member->Name() );
3580 member->
Clone( *stale_member );
3582 propagate_bus_neighbors( subgraph );
3594 std::shared_ptr<SCH_CONNECTION> c = std::shared_ptr<SCH_CONNECTION>(
nullptr );
3596 switch( aItem->
Type() )
3599 if(
static_cast<SCH_PIN*
>( aItem )->IsPower() )
3600 c = std::make_shared<SCH_CONNECTION>( aItem, aSubgraph->
m_sheet );
3607 c = std::make_shared<SCH_CONNECTION>( aItem, aSubgraph->
m_sheet );
3616 c->SetGraph(
this );
3627 if( !aBusConnection->
IsBus() )
3637 for(
const std::shared_ptr<SCH_CONNECTION>& bus_member : aBusConnection->
Members() )
3639 if( bus_member->VectorIndex() == aSearch->
VectorIndex() )
3641 match = bus_member.get();
3649 for(
const std::shared_ptr<SCH_CONNECTION>& c : aBusConnection->
Members() )
3656 for(
const std::shared_ptr<SCH_CONNECTION>& bus_member : c->Members() )
3658 if( bus_member->LocalName() == aSearch->
LocalName() )
3660 match = bus_member.get();
3665 else if( c->LocalName() == aSearch->
LocalName() )
3676 for(
const std::shared_ptr<SCH_CONNECTION>& c : aBusConnection->
Members() )
3680 for(
const std::shared_ptr<SCH_CONNECTION>& bus_member : c->Members() )
3684 match = bus_member.get();
3718 std::vector<CONNECTION_SUBGRAPH*>& vec = it->second;
3719 std::erase( vec, aSubgraph );
3722 wxLogTrace(
ConnTrace, wxS(
"recacheSubgraphName: %s => %s" ), aOldName,
3739 std::vector<const CONNECTION_SUBGRAPH*> ret;
3745 wxASSERT( !subgraph->m_dirty );
3747 if( !subgraph->m_driver )
3753 if( !connection->
IsBus() )
3756 auto labels = subgraph->GetVectorBusLabels();
3758 if( labels.size() > 1 )
3760 bool different =
false;
3763 for(
unsigned i = 1; i < labels.size(); ++i )
3775 wxLogTrace(
ConnTrace, wxS(
"SG %ld (%s) has multiple bus labels" ), subgraph->m_code,
3776 connection->
Name() );
3778 ret.push_back( subgraph );
3799 if( graph == aSubGraph )
3820 wxASSERT( !it->second.empty() );
3822 return it->second[0];
3851 for(
auto rit = it->second.rbegin(); rit != it->second.rend(); ++rit )
3858 if( subgraph && subgraph->
m_sheet == aSheetPath )
3866const std::vector<CONNECTION_SUBGRAPH*>&
3869 static const std::vector<CONNECTION_SUBGRAPH*> subgraphs;
3882 std::vector<wxString> equivalents;
3888 wxString
group = aBusName;
3889 size_t lastSlash = aBusName.find_last_of(
'/' );
3891 if( lastSlash != wxString::npos )
3893 path = aBusName.Left( lastSlash + 1 );
3894 group = aBusName.Mid( lastSlash + 1 );
3898 std::vector<wxString> members;
3904 if( !prefix.IsEmpty() )
3909 for( wxString& member : members )
3911 member.Replace( wxT(
"\\ " ), wxT(
" " ) );
3918 if( members.size() == 1 )
3924 selfAlias = members[0];
3925 members = aliasIt->second->Members();
3930 wxString expandedLabel =
path + wxT(
"{" );
3932 for(
size_t i = 0; i < members.size(); ++i )
3935 expandedLabel += wxT(
" " );
3938 escaped.Replace( wxT(
" " ), wxT(
"\\ " ) );
3939 expandedLabel += escaped;
3942 expandedLabel += wxT(
"}" );
3944 if( expandedLabel != aBusName )
3945 equivalents.push_back( expandedLabel );
3948 std::multiset<wxString> memberSet( members.begin(), members.end() );
3952 if( aliasName == selfAlias || alias->Members().size() != members.size() )
3955 std::multiset<wxString> aliasMembers( alias->Members().begin(), alias->Members().end() );
3957 if( memberSet == aliasMembers )
3958 equivalents.push_back(
path + wxT(
"{" ) + aliasName + wxT(
"}" ) );
3967 int error_count = 0;
3969 wxCHECK_MSG(
m_schematic, 0, wxS(
"Null m_schematic in CONNECTION_GRAPH::RunERC" ) );
3978 std::set<SCH_ITEM*> seenDriverInstances;
3983 wxCHECK2( subgraph,
continue );
3987 wxASSERT( !subgraph->m_dirty );
3989 if( subgraph->m_absorbed )
3992 if( seenDriverInstances.count( subgraph->m_driver ) )
3995 if( subgraph->m_driver )
3996 seenDriverInstances.insert( subgraph->m_driver );
4014 subgraph->ResolveDrivers(
false );
4085 wxCHECK( aSubgraph,
false );
4091 if( driver == aSubgraph->
m_driver )
4102 if( primaryName == secondaryName )
4105 wxString msg = wxString::Format(
_(
"Both %s and %s are attached to the same "
4106 "items; %s will be used in the netlist" ),
4107 primaryName, secondaryName, primaryName );
4110 ercItem->SetItems( aSubgraph->
m_driver, driver );
4111 ercItem->SetSheetSpecificPath( aSubgraph->
GetSheet() );
4112 ercItem->SetItemsSheetPaths( aSubgraph->
GetSheet(), aSubgraph->
m_sheet );
4113 ercItem->SetErrorMessage( msg );
4145 switch( item->
Type() )
4150 pick( bus_item, item );
4152 pick( net_item, item );
4166 pick( bus_item, item );
4168 pick( net_item, item );
4178 if( net_item && bus_item )
4181 ercItem->SetSheetSpecificPath( sheet );
4182 ercItem->SetItems( net_item, bus_item );
4185 screen->
Append( marker );
4204 switch( item->
Type() )
4231 if(
test != member && member->Name() ==
test->Name() )
4245 ercItem->SetSheetSpecificPath( sheet );
4246 ercItem->SetItems( label, port );
4249 screen->
Append( marker );
4261 bool conflict =
false;
4277 switch( item->
Type() )
4307 std::set<wxString> test_names;
4319 for(
const auto& sub_member : member->Members() )
4321 if( test_names.count( sub_member->FullLocalName() ) )
4325 else if( test_names.count( member->FullLocalName() ) )
4344 wxString msg = wxString::Format(
_(
"Net %s is graphically connected to bus %s but is not a"
4345 " member of that bus" ),
4349 ercItem->SetSheetSpecificPath( sheet );
4350 ercItem->SetItems( bus_entry, bus_wire );
4351 ercItem->SetErrorMessage( msg );
4354 screen->
Append( marker );
4371 std::set<SCH_PIN*> unique_pins;
4372 std::set<SCH_LABEL_BASE*> unique_labels;
4373 std::set<const SCH_ITEM*> absorbedItems;
4376 absorbedItems.insert( absorbed->
m_items.begin(), absorbed->
m_items.end() );
4384 for(
SCH_ITEM* item : aProcessGraph->m_items )
4386 switch( item->
Type() )
4397 if( aProcessGraph == aSubgraph && !absorbedItems.contains( test_pin ) && !powerFlag
4403 if( std::none_of( unique_pins.begin(), unique_pins.end(),
4406 return test_pin->IsStacked( aPin );
4410 unique_pins.insert( test_pin );
4433 process_subgraph( subgraph );
4438 process_subgraph( aSubgraph );
4454 switch( item->
Type() )
4501 ercItem->SetSheetSpecificPath( sheet );
4502 ercItem->SetItemsSheetPaths( sheet );
4509 pos =
pin->GetPosition();
4518 screen->
Append( marker );
4523 if( unique_pins.empty() && unique_labels.empty() &&
4528 ercItem->SetSheetSpecificPath( sheet );
4529 ercItem->SetItemsSheetPaths( sheet );
4532 screen->
Append( marker );
4539 bool has_other_connections =
false;
4540 std::vector<SCH_PIN*> pins;
4547 switch( item->
Type() )
4554 if( !has_other_connections && !pins.empty()
4557 for(
SCH_PIN* other_pin : pins )
4561 has_other_connections =
true;
4567 pins.emplace_back(
static_cast<SCH_PIN*
>( item ) );
4574 has_other_connections =
true;
4581 pin = pins.empty() ? nullptr : pins[0];
4584 for(
SCH_PIN* test_pin : pins )
4601 ?
pin->GetLibPin()->GetParentSymbol() :
nullptr;
4603 if(
pin && !has_other_connections
4605 && ( !pinLibParent || !pinLibParent->
IsPower() ) )
4607 wxString
name =
pin->Connection( &sheet )->Name();
4608 wxString local_name =
pin->Connection( &sheet )->Name(
true );
4613 has_other_connections =
true;
4618 if(
pin && !has_other_connections
4624 ercItem->SetSheetSpecificPath( sheet );
4625 ercItem->SetItemsSheetPaths( sheet );
4626 ercItem->SetItems(
pin );
4629 screen->
Append( marker );
4637 if( pins.size() > 1 )
4639 for(
SCH_PIN* testPin : pins )
4644 SYMBOL* testLibParent = testPin->GetLibPin()
4648 if( testLibParent && testLibParent->
IsPower()
4649 && testPin->ConnectedItems( sheet ).empty()
4653 ercItem->SetSheetSpecificPath( sheet );
4654 ercItem->SetItemsSheetPaths( sheet );
4655 ercItem->SetItems( testPin );
4658 screen->
Append( marker );
4691 ercItem->SetItems( line );
4692 ercItem->SetSheetSpecificPath( sheet );
4693 ercItem->SetErrorMessage(
_(
"Unconnected wire endpoint" ) );
4715 ercItem->SetItems( entry );
4716 ercItem->SetSheetSpecificPath( sheet );
4717 ercItem->SetErrorMessage(
_(
"Unconnected wire to bus entry" ) );
4734 return err_count > 0;
4744 std::vector<SCH_ITEM*> wires;
4751 wires.emplace_back( item );
4753 wires.emplace_back( item );
4756 if( !wires.empty() )
4761 ercItem->SetSheetSpecificPath( sheet );
4762 ercItem->SetItems( wires[0],
4763 wires.size() > 1 ? wires[1] :
nullptr,
4764 wires.size() > 2 ? wires[2] :
nullptr,
4765 wires.size() > 3 ? wires[3] :
nullptr );
4768 screen->
Append( marker );
4778 std::unordered_set<const CONNECTION_SUBGRAPH*>& aOut )
const
4780 while( aBusParent && aBusParent->
m_absorbed )
4793 for(
const auto& [sibMemberConn, sibMembers] : siblingBus->
m_bus_neighbors )
4795 if( sibMemberConn->Name() != aMemberName )
4799 aOut.insert( sibling );
4824 size_t pinCount = 0;
4827 std::map<KICAD_T, std::vector<SCH_TEXT*>> label_map;
4833 return std::count_if( aLocSubgraph->m_items.begin(), aLocSubgraph->m_items.end(),
4836 return item->Type() == SCH_PIN_T;
4841 [&](
SCH_TEXT* aText,
int errCode )
4846 ercItem->SetSheetSpecificPath( sheet );
4847 ercItem->SetItems( aText );
4854 pinCount =
hasPins( aSubgraph );
4858 switch( item->
Type() )
4866 label_map[item->
Type()].push_back(
text );
4871 if(
text->IsDangling() )
4885 if( label_map.empty() )
4891 std::unordered_set<const CONNECTION_SUBGRAPH*> busMemberSiblings;
4893 for(
auto& [memberConn, busParents] : aSubgraph->
m_bus_parents )
4895 wxString memberName = memberConn->Name();
4899 if( busParent->m_no_connect )
4904 if( hp->m_no_connect )
4914 wxCHECK_MSG(
m_schematic,
true, wxS(
"Null m_schematic in CONNECTION_GRAPH::ercCheckLabels" ) );
4921 for(
auto& [type, label_vec] : label_map )
4925 size_t allPins = pinCount;
4926 size_t localPins = pinCount;
4927 bool hasLocalHierarchy =
false;
4935 std::set<wxString> uniquePortNames;
4939 if( aSubgraph->
m_hier_pins.size() + uniquePortNames.size() > 1 )
4941 hasLocalHierarchy =
true;
4946 for(
auto& [connection, busParents] : aSubgraph->
m_bus_parents )
4950 if( busParent->m_sheet == sheet
4951 && ( !busParent->m_hier_pins.empty()
4952 || !busParent->m_hier_ports.empty() ) )
4954 hasLocalHierarchy =
true;
4959 if( hasLocalHierarchy )
4964 std::unordered_set<const CONNECTION_SUBGRAPH*> creditedNeighbors;
4965 creditedNeighbors.insert( aSubgraph );
4969 if( !creditedNeighbors.insert( neighbor ).second )
4972 if( neighbor->m_no_connect )
4975 size_t neighborPins =
hasPins( neighbor );
4976 allPins += neighborPins;
4978 if( neighbor->m_sheet == sheet )
4980 localPins += neighborPins;
4982 if( !neighbor->m_hier_pins.empty() || !neighbor->m_hier_ports.empty() )
4984 hasLocalHierarchy =
true;
4994 creditNeighbor( neighbor );
4998 creditNeighbor( sibling );
5000 if( allPins == 1 && !has_nc )
5011 || ( type ==
SCH_LABEL_T && localPins == 0 && allPins > 1
5012 && !has_nc && !hasLocalHierarchy ) )
5028 std::map<wxString, std::tuple<int, const SCH_ITEM*, SCH_SHEET_PATH>> labelData;
5037 if( labelData.find( resolvedLabelText ) == labelData.end() )
5039 labelData[resolvedLabelText] = { 1, item, sheet };
5043 std::get<0>( labelData[resolvedLabelText] ) += 1;
5044 std::get<1>( labelData[resolvedLabelText] ) =
nullptr;
5045 std::get<2>( labelData[resolvedLabelText] ) = sheet;
5050 for(
const auto& label : labelData )
5052 if( std::get<0>( label.second ) == 1 )
5055 const SCH_ITEM* item = std::get<1>( label.second );
5058 ercItem->SetItems( std::get<1>( label.second ) );
5059 ercItem->SetSheetSpecificPath( sheet );
5060 ercItem->SetItemsSheetPaths( sheet );
5075 int error_count = 0;
5087 ercItem->SetSheetSpecificPath( sheet );
5088 ercItem->SetItems(
text );
5091 sheet.LastScreen()->Append( marker );
5111 if( sheet.Last()->IsTopLevelSheet() )
5117 wxCHECK2( label,
continue );
5119 msg.Printf(
_(
"Hierarchical label '%s' in root sheet cannot be connected to non-existent "
5123 ercItem->SetItems( item );
5124 ercItem->SetErrorMessage( msg );
5127 sheet.LastScreen()->Append( marker );
5138 parentSheetPath.
push_back( parentSheet );
5140 std::map<wxString, SCH_SHEET_PIN*> pins;
5141 std::map<wxString, SCH_HIERLABEL*> labels;
5151 ercItem->SetItems(
pin );
5152 ercItem->SetSheetSpecificPath( sheet );
5153 ercItem->SetItemsSheetPaths( sheet );
5156 sheet.LastScreen()->Append( marker );
5164 std::set<wxString> matchedPins;
5173 if( !pins.contains( labelText ) )
5174 labels[ labelText ] = label;
5176 matchedPins.insert( labelText );
5180 for(
const wxString& matched : matchedPins )
5181 pins.erase( matched );
5183 for(
const auto& [
name,
pin] : pins )
5185 msg.Printf(
_(
"Sheet pin %s has no matching hierarchical label inside the sheet" ),
5189 ercItem->SetItems(
pin );
5190 ercItem->SetErrorMessage( msg );
5191 ercItem->SetSheetSpecificPath( sheet );
5192 ercItem->SetItemsSheetPaths( sheet );
5195 sheet.LastScreen()->Append( marker );
5200 for(
const auto& [
name, label] : labels )
5202 msg.Printf(
_(
"Hierarchical label %s has no matching sheet pin in the parent sheet" ),
5206 ercItem->SetItems( label );
5207 ercItem->SetErrorMessage( msg );
5208 ercItem->SetSheetSpecificPath( parentSheetPath );
5209 ercItem->SetItemsSheetPaths( parentSheetPath );
constexpr EDA_IU_SCALE schIUScale
static const ADVANCED_CFG & GetCfg()
Get the singleton instance's config, which is shared by all consumers.
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.
std::shared_ptr< CONNECTION_GRAPH_LIFETIME > m_lifetime
Retired before graph teardown so late item destruction cannot enter this 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.
SCH_NETCHAIN * GetNetChainByName(const wxString &aName)
bool ercCheckLabels(const CONNECTION_SUBGRAPH *aSubgraph)
Check one subgraph for proper connection of labels.
std::unordered_map< SCH_ITEM *, std::vector< CONNECTION_SUBGRAPH * > > m_item_to_subgraph_map
Every subgraph referencing the item, one per instantiating sheet path for items on shared screens.
void RemoveItem(SCH_ITEM *aItem)
void collectAllDriverValues()
Map the driver values for each subgraph.
int ercCheckDirectiveLabels()
Check directive labels should be connected to something.
void recacheSubgraphName(CONNECTION_SUBGRAPH *aSubgraph, const wxString &aOldName)
CONNECTION_GRAPH(SCHEMATIC *aSchematic=nullptr, SCH_CONNECTIVITY::NETCHAIN_MANAGER *aNetChains=nullptr)
static std::function< void(SCH_CONNECTIVITY::NETCHAIN_MANAGER &)> & RebuildNetChainsTestHook()
QA hook receives candidate state before publication and may throw to test rollback.
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::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.
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.
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 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
bool IsMinor() const
We modify how we handle the connectivity graph for small graphs vs large graphs.
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.
bool ercCheckNoConnects(const CONNECTION_SUBGRAPH *aSubgraph)
Check one subgraph for proper presence or absence of no-connect symbols.
SCH_CONNECTIVITY::NETCHAIN_MANAGER::CHAIN_TERMINAL_REFS CHAIN_TERMINAL_REFS
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.
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_CONNECTIVITY::NETCHAIN_MANAGER * m_netChains
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.
std::vector< CONNECTION_SUBGRAPH * > m_driver_subgraphs
Cache of a subset of m_subgraphs.
std::vector< wxString > GetEquivalentBusNames(const wxString &aBusName) const
Map a bus group name between its alias and expanded forms ({MIXED_BUS} <-> {FOO BAR HAM EGGS}...
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.
void ApplyNetChainNetclasses()
Mirror each committed net chain's netclass override into the project NET_SETTINGS as a chain-derived ...
CONNECTION_SUBGRAPH * GetSubgraphForItemOnSheet(SCH_ITEM *aItem, const SCH_SHEET_PATH &aSheetPath) const
Return the subgraph containing an item on a specific sheet path.
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.
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)
Replace 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.
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
static int TestConnectivity(SCHEMATIC &aSchematic)
const std::vector< JUMPER_GROUP > & GetAll() const
Represents a group of jumper pins or pads, keyed by name.
JUMPER_GROUP_SET & JumperPinGroups()
Each jumper pin group is a set of pin numbers that should be treated as internally connected.
bool GetDuplicatePinNumbersAreJumpers() const
static bool ParseBusGroup(const wxString &aGroup, wxString *name, std::vector< wxString > *aMemberList, size_t *aPrefixEnd=nullptr)
Parse a bus group label into the name and a list of components.
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
Persistent chain configuration and the derived chains for one schematic.
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 ...
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,...
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.
const std::vector< SCH_ITEM * > & ConnectedItems(const SCH_SHEET_PATH &aPath) const
Retrieve the set of items connected to this item on the given sheet.
void AddConnectionTo(const SCH_SHEET_PATH &aPath, SCH_ITEM *aItem)
Add a connection link between this item and another.
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
void registerConnectivityOwner(const std::shared_ptr< CONNECTION_GRAPH_LIFETIME > &aOwner)
Graph membership belongs to this item identity and must not propagate to clones.
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.
bool IsDangling() const override
LABEL_FLAG_SHAPE GetShape() const
wxString GetShownText(const SCH_SHEET_PATH *aPath, RESOLUTION_CONTEXT aContext, int aDepth=0) const override
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
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.
static wxString MakeKey(const wxString &aName, uint32_t aComponent)
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
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
KIID_PATH Path() const
Get the sheet path as an KIID_PATH.
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()
std::vector< const SCH_PIN * > GetPins(const SCH_SHEET_PATH *aSheet) const
Retrieve a list of the SCH_PINs for the given sheet path.
std::vector< SCH_PIN * > GetGraphicalPins(int aUnit, int aBodyStyle) const override
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()
VECTOR2I GetPosition() const override
virtual wxString GetShownText(const SCH_SHEET_PATH *aPath, RESOLUTION_CONTEXT aContext, 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
std::pair< KIID_PATH, DRIVER_IDENTITY > SUBGRAPH_IDENTITY
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 DRIVER_IDENTITY stableDriverIdentity(SCH_ITEM *aDriver)
std::tuple< KIID, wxString, int, VECTOR2I > DRIVER_IDENTITY
#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.
int m_MinorSchematicGraphSize
Set the number of items in a schematic graph for it to be considered "minor".
static const wxChar DanglingProfileMask[]
Flag to enable connectivity profiling.
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.
bool contains(const _Container &__container, _Value __value)
Returns true if the container contains the given value.
@ PT_NC
not connected (must be left open)
@ PT_NIC
not internally connected (may be connected to anything)
@ 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.
@ 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:...
static std::vector< int > candidates(const SEGMENT_INDEX &aIndex, const SEG &aQuery, int aPadding)
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