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 ) );
742 existing.push_back( sg );
796 wxCHECK2( aOldItem->
Type() == aNewItem->
Type(),
return );
805 std::vector<CONNECTION_SUBGRAPH*> sgs = std::move( it->second );
808 sg->ExchangeItem( aOld, aNew );
832 wxCHECK2( oldPins.size() == newPins.size(),
return );
834 for(
size_t ii = 0; ii < oldPins.size(); ii++ )
836 exchange( oldPins[ii], newPins[ii] );
847 if( subgraph->m_graph ==
this )
874 chain->ClearSymbols();
883 std::function<
void(
SCH_ITEM* )>* aChangedItemHandler,
887 PROF_TIMER recalc_time(
"CONNECTION_GRAPH::Recalculate" );
888 monitorTrans.
Start();
893 monitorTrans.
StartSpan(
"updateItemConnectivity",
"" );
894 PROF_TIMER update_items(
"updateItemConnectivity" );
897 std::set<SCH_ITEM*> dirty_items;
899 int count = aSheetList.size() * 2;
904 if( aProgressReporter )
910 std::vector<SCH_ITEM*> items;
913 std::vector<std::pair<SCH_SYMBOL*, int>> symbolsChanged;
915 for(
SCH_ITEM* item : sheet.LastScreen()->Items() )
917 if( item->IsConnectable() && ( aUnconditional || item->IsConnectivityDirty() ) )
919 wxLogTrace(
ConnTrace, wxT(
"Adding item %s to connectivity graph update" ),
920 item->GetTypeDesc() );
921 items.push_back( item );
922 dirty_items.insert( item );
931 if(
pin->IsConnectivityDirty() )
933 dirty_items.insert(
pin );
946 if(
pin->IsConnectivityDirty() )
948 items.push_back(
pin );
949 dirty_items.insert(
pin );
959 if(
pin->IsConnectivityDirty() )
961 items.push_back(
pin );
962 dirty_items.insert(
pin );
975 if( symbol->
GetUnit() != new_unit )
976 symbolsChanged.push_back( { symbol, symbol->
GetUnit() } );
986 if( aProgressReporter )
993 sheet.LastScreen()->TestDanglingEnds( &sheet, aChangedItemHandler );
996 for(
const auto& [ symbol, originalUnit ] : symbolsChanged )
997 symbol->SetUnit( originalUnit );
1007 for(
SCH_ITEM* item : dirty_items )
1008 item->SetConnectivityDirty(
false );
1013 update_items.
Show();
1015 PROF_TIMER build_graph(
"buildConnectionGraph" );
1016 monitorTrans.
StartSpan(
"BuildConnectionGraph",
"" );
1035 const std::set<SCH_ITEM*> &aItems )
1037 std::set<std::pair<SCH_SHEET_PATH, SCH_ITEM*>> retvals;
1038 std::set<CONNECTION_SUBGRAPH*> subgraphs;
1043 while( aSubgraph->m_absorbed_by )
1046 wxASSERT( aSubgraph->m_graph == aSubgraph->m_absorbed_by->m_graph );
1047 aSubgraph = aSubgraph->m_absorbed_by;
1051 while( aSubgraph->m_hier_parent )
1054 wxASSERT( aSubgraph->m_graph == aSubgraph->m_hier_parent->m_graph );
1055 aSubgraph = aSubgraph->m_hier_parent;
1059 aSubgraph->getAllConnectedItems( retvals, subgraphs );
1062 auto extract_element = [&](
SCH_ITEM* aItem )
1068 wxLogTrace(
ConnTrace, wxT(
"Item %s not found in connection graph" ),
1069 aItem->GetTypeDesc() );
1075 wxLogTrace(
ConnTrace, wxT(
"Item %s in subgraph %ld (%p) has no driver" ),
1076 aItem->GetTypeDesc(), item_sg->
m_code, item_sg );
1081 if( sg_to_scan.empty() )
1083 wxLogTrace(
ConnTrace, wxT(
"Item %s in subgraph %ld with net %s has no neighbors" ),
1085 sg_to_scan.push_back( item_sg );
1089 wxT(
"Removing all item %s connections from subgraph %ld with net %s: Found "
1092 sg_to_scan.size() );
1096 traverse_subgraph( sg );
1098 for(
auto& bus_it : sg->m_bus_neighbors )
1101 traverse_subgraph( bus_sg );
1104 for(
auto& bus_it : sg->m_bus_parents )
1107 traverse_subgraph( bus_sg );
1121 extract_element(
pin );
1128 extract_element(
pin );
1132 extract_element( item );
1138 for(
const auto& [
path, item] : retvals )
1169 wxLogTrace(
ConnTrace, wxT(
"Removing %zu subgraphs" ), aSubgraphs.size() );
1172 std::set<int> codes_to_remove;
1176 std::sort( el.second.begin(), el.second.end() );
1181 for(
auto& it : sg->m_bus_neighbors )
1187 for(
auto test = parents.begin();
test != parents.end(); )
1195 if( parents.empty() )
1200 for(
auto& it : sg->m_bus_parents )
1206 for(
auto test = neighbors.begin();
test != neighbors.end(); )
1214 if( neighbors.empty() )
1235 auto it = std::lower_bound( el.second.begin(), el.second.end(), sg );
1237 while( it != el.second.end() && *it == sg )
1238 it = el.second.erase( it );
1241 auto remove_sg = [sg](
auto it ) ->
bool
1254 if( remove_sg( it ) )
1262 if( remove_sg( it ) )
1271 if( remove_sg( it ) )
1273 codes_to_remove.insert( it->first.Netcode );
1285 if( remove_sg( it ) )
1293 std::erase( it->second, sg );
1295 if( it->second.empty() )
1306 if( codes_to_remove.contains( it->second ) )
1314 if( codes_to_remove.contains( it->second ) )
1323 sg->m_graph =
nullptr;
1330 std::map<
VECTOR2I, std::vector<SCH_ITEM*>>& aConnectionMap )
1341 aConn->SetName(
name );
1346 std::map<wxString, std::vector<SCH_PIN*>> pinNumberMap;
1352 updatePin(
pin, conn );
1353 aConnectionMap[
pin->GetPosition() ].push_back(
pin );
1354 pinNumberMap[
pin->GetNumber()].emplace_back(
pin );
1357 auto linkPinsInVec =
1358 [&](
const std::vector<SCH_PIN*>& aVec )
1360 for(
size_t i = 0; i < aVec.size(); ++i )
1362 for(
size_t j = i + 1; j < aVec.size(); ++j )
1364 aVec[i]->AddConnectionTo( aSheet, aVec[j] );
1365 aVec[j]->AddConnectionTo( aSheet, aVec[i] );
1374 for(
const auto& [number,
group] : pinNumberMap )
1375 linkPinsInVec(
group );
1380 std::vector<SCH_PIN*> pins;
1382 for(
const wxString& pinNumber :
group )
1385 pins.emplace_back(
pin );
1388 linkPinsInVec( pins );
1411 std::map<
VECTOR2I, std::vector<SCH_ITEM*>>& aConnectionMap )
1416 m_items.emplace_back( aItem );
1419 switch( aItem->
Type() )
1432 if( points.empty() )
1433 points = {
static_cast<SCH_PIN*
>( aItem )->GetPosition() };
1446 for(
const VECTOR2I& point : points )
1447 aConnectionMap[point].push_back( aItem );
1452 const std::vector<SCH_ITEM*>& aItemList )
1454 wxLogTrace( wxT(
"Updating connectivity for sheet %s with %zu items" ),
1456 std::map<VECTOR2I, std::vector<SCH_ITEM*>> connection_map;
1460 std::vector<VECTOR2I> points = item->GetConnectionPoints();
1461 item->ClearConnectedItems( aSheet );
1466 pin->InitializeConnection( aSheet,
this );
1468 pin->ClearConnectedItems( aSheet );
1470 connection_map[
pin->GetTextPos() ].push_back(
pin );
1487 VECTOR2I point = item->GetPosition();
1490 std::vector<SCH_ITEM*> overlapping_items;
1492 std::copy_if( items.begin(), items.end(), std::back_inserter( overlapping_items ),
1495 return test_item->Type() == SCH_LINE_T
1496 && test_item->HitTest( point, -1 );
1501 if( overlapping_items.size() < 2 )
continue;
1503 for(
SCH_ITEM* test_item : overlapping_items )
1504 connection_map[point].push_back( test_item );
1513 VECTOR2I point = item->GetPosition();
1517 connection_map[point].push_back( wire );
1522 for(
auto& [point, connection_vec] : connection_map )
1524 std::sort( connection_vec.begin(), connection_vec.end() );
1530 for(
SCH_ITEM* connected_item : connection_vec )
1544 if( connection_vec.size() == 1 )
1560 if( point == bus_entry->GetPosition() )
1563 bus_entry->m_connected_bus_items[1] = busLine;
1576 for(
SCH_ITEM* test_item : connection_vec )
1578 bool bus_connection_ok =
true;
1580 if( test_item == connected_item )
1586 if( test_item->GetLayer() ==
LAYER_BUS )
1605 if( connected_item->ConnectionPropagatesTo( test_item )
1606 && test_item->ConnectionPropagatesTo( connected_item )
1607 && bus_connection_ok )
1609 connected_item->AddConnectionTo( aSheet, test_item );
1620 if( !bus_entry->m_connected_bus_item )
1626 bus_entry->m_connected_bus_item = bus;
1637 wxCHECK_RET(
m_schematic, wxS(
"Connection graph cannot be built without schematic pointer" ) );
1641 for(
const std::shared_ptr<BUS_ALIAS>& alias :
m_schematic->GetAllBusAliases() )
1650 std::unordered_map<SCH_SHEET_PATH, size_t> sheetOrder;
1659 auto it = sheetOrder.find( aSheet );
1661 return ( it == sheetOrder.end() ) ? std::numeric_limits<size_t>::max()
1667 std::vector<std::tuple<size_t, SCH_SHEET_PATH, SCH_CONNECTION*>> ordered;
1672 ordered.reserve( item->m_connection_map.size() );
1676 for(
const auto& [sheet, connection] : item->m_connection_map )
1677 ordered.emplace_back( sheetRank( sheet ), sheet, connection );
1679 std::sort( ordered.begin(), ordered.end(),
1680 [](
const auto& a,
const auto& b )
1682 return std::get<0>( a ) < std::get<0>( b );
1685 for(
const auto& [rank, sheet, connection] : ordered )
1687 if( connection->SubgraphCode() == 0 )
1696 connection->SetSubgraphCode( subgraph->
m_code );
1699 std::list<SCH_ITEM*> memberlist;
1704 SCH_CONNECTION* conn = aItem->GetOrInitConnection( sheet,
this );
1710 return ( unique && conn && ( conn->
SubgraphCode() == 0 ) );
1713 std::copy_if( item->ConnectedItems( sheet ).begin(),
1714 item->ConnectedItems( sheet ).end(),
1715 std::back_inserter( memberlist ), get_items );
1717 for(
SCH_ITEM* connected_item : memberlist )
1722 SCH_CONNECTION* connected_conn = connected_item->Connection( &sheet );
1724 wxCHECK2( connected_conn,
continue );
1730 subgraph->
AddItem( connected_item );
1737 if( get_items( citem ) )
1738 memberlist.push_back( citem );
1743 for(
SCH_ITEM* connected_item : memberlist )
1757 std::vector<CONNECTION_SUBGRAPH*> dirty_graphs;
1762 return candidate->m_dirty;
1765 wxLogTrace(
ConnTrace, wxT(
"Resolving drivers for %zu subgraphs" ), dirty_graphs.size() );
1767 std::vector<std::future<size_t>> returns( dirty_graphs.size() );
1769 auto update_lambda =
1772 if( !subgraph->m_dirty )
1776 for(
SCH_ITEM* item : subgraph->m_items )
1778 switch( item->
Type() )
1781 subgraph->m_no_connect = item;
1785 subgraph->m_bus_entry = item;
1793 subgraph->m_no_connect = item;
1803 subgraph->ResolveDrivers(
true );
1804 subgraph->m_dirty =
false;
1811 auto results =
tp.submit_loop( 0, dirty_graphs.size(),
1814 update_lambda( dirty_graphs[ii] );
1823 return candidate->m_driver;
1836 wxString full_name = subgraph->m_driver_connection->Name();
1837 wxString
name = subgraph->m_driver_connection->Name(
true );
1846 wxString prefixOnly = full_name.BeforeFirst(
'[' ) + wxT(
"[]" );
1850 subgraph->m_dirty =
true;
1852 if( subgraph->m_strong_driver )
1854 SCH_ITEM* driver = subgraph->m_driver;
1857 switch( driver->
Type() )
1873 if(
pin->IsGlobalPower() )
1877 else if(
pin->IsLocalPower() )
1884 wxLogTrace(
ConnTrace, wxS(
"Unexpected normal pin %s" ),
1894 wxLogTrace(
ConnTrace, wxS(
"Unexpected strong driver %s" ),
1906 std::vector<CONNECTION_SUBGRAPH*> new_subgraphs;
1910 for(
SCH_ITEM* item : subgraph->GetAllBusLabels() )
1915 dummy.SetGraph(
this );
1918 wxLogTrace(
ConnTrace, wxS(
"new bus label (%s)" ),
1921 for(
const auto& conn :
dummy.Members() )
1924 if( !conn->IsNet() )
1927 wxString
name = conn->FullLocalName();
1934 auto new_conn = std::make_unique<SCH_CONNECTION>( item, subgraph->m_sheet );
1935 new_conn->SetGraph(
this );
1936 new_conn->SetName(
name );
1939 SCH_CONNECTION* new_conn_ptr = subgraph->StoreImplicitConnection( std::move( new_conn ) );
1942 wxLogTrace(
ConnTrace, wxS(
"SG(%ld), Adding full local name (%s) with sg (%d) on subsheet %s" ),
1943 subgraph->m_code,
name, code, subgraph->m_sheet.PathHumanReadable() );
1956 new_subgraphs.push_back( new_sg );
1961 std::copy( new_subgraphs.begin(), new_subgraphs.end(),
1977 [](
const std::pair<SCH_SHEET_PATH, SCH_PIN*>& a,
1978 const std::pair<SCH_SHEET_PATH, SCH_PIN*>& b )
1980 int pathCmp = a.first.Cmp( b.first );
1985 const SCH_SYMBOL* symA = static_cast<const SCH_SYMBOL*>( a.second->GetParentSymbol() );
1986 const SCH_SYMBOL* symB = static_cast<const SCH_SYMBOL*>( b.second->GetParentSymbol() );
1988 wxString refA = symA ? symA->GetRef( &a.first, false ) : wxString();
1989 wxString refB = symB ? symB->GetRef( &b.first, false ) : wxString();
1991 int refCmp = refA.Cmp( refB );
1996 return a.second->GetNumber().Cmp( b.second->GetNumber() ) < 0;
1999 std::unordered_map<int, CONNECTION_SUBGRAPH*> global_power_pin_subgraphs;
2003 SYMBOL* libParent =
pin->GetLibPin() ?
pin->GetLibPin()->GetParentSymbol() :
nullptr;
2005 if( !
pin->ConnectedItems( sheet ).empty()
2022 connection->
SetName(
pin->GetParentSymbol()->GetValue(
true, &sheet,
false ) );
2031 auto jj = global_power_pin_subgraphs.find( code );
2033 if( jj != global_power_pin_subgraphs.end() )
2035 subgraph = jj->second;
2053 global_power_pin_subgraphs[code] = subgraph;
2070 std::unordered_set<CONNECTION_SUBGRAPH*> invalidated_subgraphs;
2074 if( subgraph->m_absorbed )
2079 wxString
name = connection->
Name();
2082 unsigned suffix = 1;
2084 wxString base_name = connection->
Name();
2086 auto create_new_name =
2089 wxString suffixStr = std::to_wstring( suffix );
2096 wxString prefix = aConn->BusPrefix();
2098 if( prefix.empty() )
2099 prefix = wxT(
"BUS" );
2104 wxString members = base_name.Mid( aConn->BusPrefix().length() );
2107 newName << prefix << wxT(
"_" ) << suffixStr << members;
2109 aConn->ConfigureFromLabel( newName );
2115 aConn->SetSuffix( wxString( wxT(
"_" ) ) << suffixStr );
2119 return aConn->Name();
2126 auto promote_sheet_pin_driver =
2129 if( !subgraph->m_driver || subgraph->m_driver->Type() !=
SCH_SHEET_PIN_T )
2132 wxString global_name = connection->
Name(
true );
2139 if( candidate->
m_sheet == sheet )
2142 wxS(
"%ld (%s) skipped for promotion due to potential conflict" ),
2143 subgraph->m_code, connection->
Name() );
2149 subgraph->m_strong_driver =
true;
2152 if( !subgraph->m_strong_driver )
2154 std::vector<CONNECTION_SUBGRAPH*> vec_empty;
2155 std::vector<CONNECTION_SUBGRAPH*>* vec = &vec_empty;
2164 wxString prefixOnly =
name.BeforeFirst(
'[' ) + wxT(
"[]" );
2170 if( vec->size() > 1 )
2172 wxString new_name = create_new_name( connection );
2175 new_name = create_new_name( connection );
2177 wxLogTrace(
ConnTrace, wxS(
"%ld (%s) is weakly driven and not unique. Changing to %s." ),
2178 subgraph->m_code,
name, new_name );
2180 std::erase( *vec, subgraph );
2188 promote_sheet_pin_driver();
2190 else if( subgraph->m_driver )
2192 promote_sheet_pin_driver();
2197 if( connection->
IsBus() )
2221 subgraph->m_dirty =
true;
2229 if( !subgraph->m_strong_driver )
2236 std::vector<CONNECTION_SUBGRAPH*> candidate_subgraphs;
2239 std::back_inserter( candidate_subgraphs ),
2242 return ( !candidate->m_absorbed &&
2243 candidate->m_strong_driver &&
2244 candidate != subgraph );
2250 std::vector< std::shared_ptr<SCH_CONNECTION> > connections_to_check;
2253 connections_to_check.push_back( std::make_shared<SCH_CONNECTION>( *connection ) );
2255 auto add_connections_to_check =
2258 for(
SCH_ITEM* possible_driver : aSubgraph->m_items )
2260 if( possible_driver == aSubgraph->m_driver )
2267 if( c->Type() != aSubgraph->m_driver_connection->Type() )
2270 if( c->Name(
true ) == aSubgraph->m_driver_connection->Name(
true ) )
2273 connections_to_check.push_back( c );
2274 wxLogTrace(
ConnTrace, wxS(
"%lu (%s): Adding secondary driver %s" ),
2276 aSubgraph->m_driver_connection->Name(
true ),
2285 add_connections_to_check( subgraph );
2287 std::set<SCH_CONNECTION*> checked_connections;
2289 for(
unsigned i = 0; i < connections_to_check.size(); i++ )
2291 auto member = connections_to_check[i];
2294 if( !checked_connections.insert( member.get() ).second )
2297 if( member->IsBus() )
2299 connections_to_check.insert( connections_to_check.end(),
2300 member->Members().begin(),
2301 member->Members().end() );
2304 wxString test_name = member->Name(
true );
2308 if( candidate->
m_absorbed || candidate == subgraph )
2324 if( driver == candidate->
m_driver )
2336 &&
pin->GetDefaultNetName( sheet ) == test_name )
2349 if( subgraph->GetNameForDriver( driver ) == test_name )
2362 wxLogTrace(
ConnTrace, wxS(
"%lu (%s) has bus child %lu (%s)" ),
2363 subgraph->m_code, connection->
Name(),
2364 candidate->
m_code, member->Name() );
2366 subgraph->m_bus_neighbors[member].insert( candidate );
2369 else if( ( !connection->
IsBus()
2373 wxLogTrace(
ConnTrace, wxS(
"%lu (%s) absorbs neighbor %lu (%s)" ),
2374 subgraph->m_code, connection->
Name(),
2378 add_connections_to_check( candidate );
2380 subgraph->Absorb( candidate );
2381 invalidated_subgraphs.insert( subgraph );
2391 if( subgraph->m_absorbed )
2394 if( !subgraph->ResolveDrivers() )
2397 if( subgraph->m_driver_connection->IsBus() )
2402 wxLogTrace(
ConnTrace, wxS(
"Re-resolving drivers for %lu (%s)" ),
2403 subgraph->m_code, subgraph->m_driver_connection->Name() );
2422 bool aUnconditional )
2425 wxCHECK_RET(
m_schematic, wxT(
"Connection graph cannot be built without schematic pointer" ) );
2429 for(
const std::shared_ptr<BUS_ALIAS>& alias :
m_schematic->GetAllBusAliases() )
2435 PROF_TIMER sub_graph(
"buildItemSubGraphs" );
2454 PROF_TIMER proc_sub_graph(
"ProcessSubGraphs" );
2458 proc_sub_graph.
Show();
2467 std::vector<CONNECTION_SUBGRAPH*> global_subgraphs;
2469 std::back_inserter( global_subgraphs ),
2472 return !candidate->m_local_driver;
2486 m_driver_subgraphs[ii]->UpdateItemConnections();
2508 if( !global_subgraphs.empty() )
2510 std::unordered_map<CONNECTION_SUBGRAPH*, CONNECTION_SUBGRAPH*> sg_root;
2519 auto it = sg_root.find( cur );
2521 if( it == sg_root.end() || it->second == cur )
2526 auto parent_it = sg_root.find( it->second );
2528 if( parent_it != sg_root.end() && parent_it->second != it->second )
2529 it->second = parent_it->second;
2539 auto prefer_as_representative =
2544 aB->m_driver, aB->m_driver_connection,
2545 aB->m_driver_connection->Name() ) < 0;
2551 sg_root.try_emplace( aA, aA );
2552 sg_root.try_emplace( aB, aB );
2557 if( root_a == root_b )
2560 if( prefer_as_representative( root_a, root_b ) )
2561 sg_root[root_b] = root_a;
2563 sg_root[root_a] = root_b;
2566 std::unordered_map<wxString, std::vector<CONNECTION_SUBGRAPH*>> name_to_sgs;
2570 for(
SCH_ITEM* driver : subgraph->m_drivers )
2578 name_to_sgs[subgraph->GetNameForDriver( driver )].push_back( subgraph );
2582 for(
auto& [
name, sgs] : name_to_sgs )
2584 if( sgs.size() < 2 )
2587 for(
size_t ii = 1; ii < sgs.size(); ++ii )
2588 union_sgs( sgs[0], sgs[ii] );
2594 for(
const auto& entry : sg_root )
2605 wxLogTrace(
ConnTrace, wxS(
"Global %lu (%s) canonicalized to %lu (%s)" ),
2618 if( !subgraph->m_dirty )
2621 wxLogTrace(
ConnTrace, wxS(
"Processing %lu (%s) for propagation" ),
2622 subgraph->m_code, subgraph->m_driver_connection->Name() );
2628 if( !subgraph->m_local_driver && subgraph->m_multiple_drivers )
2630 for(
SCH_ITEM* driver : subgraph->m_drivers )
2632 if( driver == subgraph->m_driver )
2635 const wxString& secondary_name = subgraph->GetNameForDriver( driver );
2637 if( secondary_name == subgraph->m_driver_connection->Name() )
2645 if( candidate == subgraph )
2648 if( !secondary_is_global && candidate->
m_sheet != subgraph->m_sheet )
2655 wxLogTrace(
ConnTrace, wxS(
"Global %lu (%s) promoted to %s" ),
2657 subgraph->m_driver_connection->Name() );
2679 if( subgraph->m_dirty )
2696 wxASSERT_MSG( !subgraph->m_dirty,
2697 wxS(
"Subgraph not processed by propagateToNeighbors!" ) );
2699 if( subgraph->m_bus_parents.size() < 2 )
2704 wxLogTrace(
ConnTrace, wxS(
"%lu (%s) has multiple bus parents" ),
2705 subgraph->m_code, conn->
Name() );
2708 wxCHECK2( conn->
IsNet(),
continue );
2710 for(
const auto& ii : subgraph->m_bus_parents )
2723 wxLogTrace(
ConnTrace, wxS(
"Warning: could not match %s inside %lu (%s)" ),
2728 if( conn->
Name() != match->
Name() )
2730 wxString old_name = match->
Name();
2732 wxLogTrace(
ConnTrace, wxS(
"Updating %lu (%s) member %s to %s" ),
2735 match->
Clone( *conn );
2743 std::vector<CONNECTION_SUBGRAPH*> old_subgraphs = jj->second;
2747 while( old_sg->m_absorbed )
2748 old_sg = old_sg->m_absorbed_by;
2750 wxString old_sg_name = old_sg->m_driver_connection->Name();
2751 old_sg->m_driver_connection->Clone( *conn );
2753 if( old_sg_name != old_sg->m_driver_connection->Name() )
2764 auto propagateConnectionsTask =
2768 if( !subgraph->m_strong_driver
2769 && subgraph->m_drivers.size() == 1
2770 && subgraph->m_driver->Type() ==
SCH_PIN_T )
2773 wxString
name =
pin->GetDefaultNetName( subgraph->m_sheet,
true );
2775 subgraph->m_driver_connection->ConfigureFromLabel(
name );
2778 subgraph->m_dirty =
false;
2779 subgraph->UpdateItemConnections();
2785 propagateConnectionsTask( m_driver_subgraphs[ii] );
2794 if( subgraph->m_driver_connection->IsBus() )
2797 if( !subgraph->m_driver || subgraph->m_driver->Type() !=
SCH_SHEET_PIN_T )
2806 wxString pinText =
pin->GetShownText(
false );
2813 if( label->
GetShownText( &subgraph->m_sheet,
false ) == pinText )
2816 path.push_back( sheet );
2820 if( parent_conn && parent_conn->
IsBus() )
2834 subgraph->m_driver_connection->NetCode() };
2840 std::shared_ptr<NET_SETTINGS>& netSettings =
m_schematic->Project().GetProjectFile().m_NetSettings;
2841 std::map<wxString, std::set<wxString>> oldAssignments = netSettings->GetNetclassLabelAssignments();
2842 std::set<wxString> affectedNetclassNetAssignments;
2844 netSettings->ClearNetclassLabelAssignments();
2846 auto dirtySubgraphs =
2847 [&](
const std::vector<CONNECTION_SUBGRAPH*>& subgraphs )
2849 if( aChangedItemHandler )
2853 for(
SCH_ITEM* item : subgraph->m_items )
2854 (*aChangedItemHandler)( item );
2859 auto checkNetclassDrivers =
2860 [&](
const wxString& netName,
const std::vector<CONNECTION_SUBGRAPH*>& subgraphs )
2862 wxCHECK_RET( !subgraphs.empty(), wxS(
"Invalid empty subgraph" ) );
2864 std::set<wxString> netclasses;
2869 for(
SCH_ITEM* item : subgraph->m_items )
2871 for(
const auto& [
name, provider] : subgraph->GetNetclassesForDriver( item ) )
2872 netclasses.insert(
name );
2879 if( subgraph->m_driver_connection->IsBus() )
2881 auto processBusMember = [&,
this](
const SCH_CONNECTION* member )
2883 if( !netclasses.empty() )
2885 netSettings->AppendNetclassLabelAssignment( member->Name(), netclasses );
2890 if( oldAssignments.count( member->Name() ) )
2892 if( oldAssignments[member->Name()] != netclasses )
2894 affectedNetclassNetAssignments.insert( member->Name() );
2897 dirtySubgraphs( ii->second );
2900 else if( !netclasses.empty() )
2902 affectedNetclassNetAssignments.insert( member->Name() );
2905 dirtySubgraphs( ii->second );
2909 for(
const std::shared_ptr<SCH_CONNECTION>& member : subgraph->m_driver_connection->Members() )
2913 if( member->IsBus() )
2915 for(
const std::shared_ptr<SCH_CONNECTION>& nestedMember : member->Members() )
2916 processBusMember( nestedMember.get() );
2920 processBusMember( member.get() );
2927 if( !netclasses.empty() )
2929 netSettings->AppendNetclassLabelAssignment( netName, netclasses );
2932 if( oldAssignments.count( netName ) )
2934 if( oldAssignments[netName] != netclasses )
2936 affectedNetclassNetAssignments.insert( netName );
2937 dirtySubgraphs( subgraphs );
2940 else if( !netclasses.empty() )
2942 affectedNetclassNetAssignments.insert( netName );
2943 dirtySubgraphs( subgraphs );
2949 checkNetclassDrivers( netname, subgraphs );
2951 if( !aUnconditional )
2953 for(
auto& [netname, netclasses] : oldAssignments )
2955 if( netSettings->GetNetclassLabelAssignments().count( netname )
2956 || affectedNetclassNetAssignments.count( netname ) )
2961 netSettings->SetNetclassLabelAssignment( netname, netclasses );
2981 auto getSubgraphNet = [&](
SCH_PIN* aPin ) -> wxString
2994 result.edges.reserve( 256 );
3003 auto findWireOnScreen = [&](
SCH_PIN* aPin,
SCH_LINE*& aWire ) ->
bool
3007 auto consider = [&](
SCH_ITEM* cand ) ->
bool
3020 if( s.
y == e.
y && p.
y == s.
y )
3022 int minx = std::min( s.
x, e.
x );
3023 int maxx = std::max( s.
x, e.
x );
3025 if( p.
x >= minx && p.
x <= maxx )
3031 else if( s.
x == e.
x && p.
x == s.
x )
3033 int miny = std::min( s.
y, e.
y );
3034 int maxy = std::max( s.
y, e.
y );
3036 if( p.
y >= miny && p.
y <= maxy )
3060 std::vector<SCH_PIN*> pins = symbol->
GetPins( &sheetPath );
3062 if( pins.size() != 2 )
3071 if( !findWireOnScreen( pins[0], wireA ) || !findWireOnScreen( pins[1], wireB ) )
3082 if( pins[0]->IsPower() || pins[1]->IsPower() )
3090 if( aS.
x == aE.
x && bS.
x == bE.
x && aS.
x == bS.
x )
3092 else if( aS.
y == aE.
y && bS.
y == bE.
y && aS.
y == bS.
y )
3099 wxString netA = getSubgraphNet( pins[0] );
3100 wxString netB = getSubgraphNet( pins[1] );
3102 if( netA.IsEmpty() || netB.IsEmpty() || netA == netB )
3105 result.edges.push_back( { netA, netB, symbol } );
3113 std::set<long> powerSubgraphs;
3114 std::map<wxString, long> netToCode;
3126 std::vector<SCH_PIN*> pins = sym->
GetPins( &sheetPath );
3132 netToCode[
netChainKeyFor( sg->GetNetName(), sg->m_code )] = sg->m_code;
3135 || ( p->GetParentSymbol() && p->GetParentSymbol()->IsPower() ) )
3137 powerSubgraphs.insert( sg->m_code );
3148 std::set<wxString> powerAdjacentNets;
3155 if(
auto it = netToCode.find( be.
a ); it != netToCode.end() )
3158 if(
auto it = netToCode.find( be.
b ); it != netToCode.end() )
3161 if( ca == -1 || cb == -1 )
3164 if( powerSubgraphs.contains( ca ) || powerSubgraphs.contains( cb ) )
3166 if( !powerSubgraphs.contains( ca ) )
3167 powerAdjacentNets.insert( be.
a );
3169 if( !powerSubgraphs.contains( cb ) )
3170 powerAdjacentNets.insert( be.
b );
3175 result.adjacency[be.
a].push_back( { be.
b, be.
sym } );
3176 result.adjacency[be.
b].push_back( { be.
a, be.
sym } );
3182 std::map<wxString, int> degree;
3184 for(
const auto&
kv :
result.adjacency )
3185 degree[
kv.first] =
static_cast<int>(
kv.second.size() );
3187 if(
result.adjacency.size() <= 2 )
3188 powerAdjacentNets.clear();
3190 if( powerAdjacentNets.size() <= 2 )
3191 powerAdjacentNets.clear();
3193 std::queue<wxString> q;
3194 std::set<wxString> removed;
3196 for(
const auto&
kv : degree )
3198 if(
kv.second <= 1 && powerAdjacentNets.contains(
kv.first ) )
3204 wxString n = q.front();
3207 if( removed.contains( n ) )
3210 removed.insert( n );
3214 if( removed.contains( e.other ) )
3217 if( degree.count( e.other ) )
3221 if( degree[e.other] <= 1 && powerAdjacentNets.contains( e.other ) )
3227 if( !removed.empty() )
3229 std::map<wxString, std::vector<BRIDGE_NEIGHBOR>> newAdj;
3231 for(
const auto&
kv :
result.adjacency )
3233 if( removed.contains(
kv.first ) )
3238 if( removed.contains( e.
other ) )
3241 newAdj[
kv.first].push_back( e );
3245 result.adjacency.swap( newAdj );
3261 wxLogTrace(
traceSchNetChain,
"RebuildNetChains: begin (items=%zu, schematic=%p)",
3271 std::map<wxString, SCH_NETCHAIN*> netToNetChain;
3275 std::vector<SCH_SCREEN*> allScreens;
3280 allScreens.push_back( sc );
3287 static_cast<SCH_SYMBOL*
>( item )->SetNetChainName( wxEmptyString );
3289 wxLogTrace(
traceSchNetChain,
"RebuildNetChains: screens=%zu (global build)", allScreens.size() );
3298 wxLogTrace(
traceSchNetChain,
"RebuildNetChains: pass 1 (per-sheet 2-pin symbols)" );
3300 auto getSubgraphNet = [&](
SCH_PIN* aPin ) -> wxString
3311 auto& bridgeEdges = bridgeGraph.
edges;
3312 auto& adjacency = bridgeGraph.
adjacency;
3314 wxLogTrace(
traceSchNetChain,
"RebuildNetChains: bridgeEdges=%zu adjacency=%zu",
3315 bridgeEdges.size(), adjacency.size() );
3321 wxLogTrace(
traceSchNetChain,
"RebuildNetChains: targeted stub pruning start (adj=%zu)", adjacency.size() );
3322 std::map<wxString,std::vector<BRIDGE_NEIGHBOR>> snapshot = adjacency;
3323 std::set<wxString> seen;
3324 std::set<wxString> globalPrune;
3325 for(
const auto&
kv : snapshot )
3327 const wxString& start =
kv.first;
3328 if( seen.contains( start ) )
continue;
3330 std::vector<wxString>
comp; std::queue<wxString> q; q.push( start ); seen.insert( start );
3333 wxString cur = q.front(); q.pop();
comp.push_back( cur );
3334 for(
const BRIDGE_NEIGHBOR& e : snapshot[cur] )
if( !seen.contains( e.other ) ) { seen.insert( e.other ); q.push( e.other ); }
3337 if(
comp.size() <= 4 )
continue;
3338 std::map<wxString,int> degree;
3339 for(
const wxString& n :
comp ) degree[n] = (int) snapshot[n].size();
3340 std::vector<wxString> candidates;
3341 for(
const wxString& n :
comp )
3343 const auto& nbrs = snapshot[n];
3344 if( nbrs.size() == 1 )
3346 const wxString neigh = nbrs[0].other;
3347 if( degree.count( neigh ) && degree[neigh] > 2 ) candidates.push_back( n );
3351 if( candidates.empty() )
continue;
3352 std::sort( candidates.begin(), candidates.end(), [](
const wxString& a,
const wxString& b ){ return a.CmpNoCase( b ) < 0; } );
3353 size_t needPrune =
comp.size() - 4;
if( needPrune > candidates.size() ) needPrune = candidates.size();
3355 for(
size_t i = 0; i < needPrune; ++i ) globalPrune.insert( candidates[i] );
3357 if( !globalPrune.empty() )
3359 std::map<wxString,std::vector<BRIDGE_NEIGHBOR>> newAdj;
3360 for(
const auto& kv2 : adjacency )
3362 if( globalPrune.contains( kv2.first ) )
continue;
3365 if( globalPrune.contains( e.
other ) )
continue;
3366 newAdj[kv2.first].push_back( e );
3369 adjacency.swap( newAdj );
3370 wxLogTrace(
traceSchNetChain,
"RebuildNetChains: pruned %zu targeted stub nets", globalPrune.size() );
3375 auto neighbors_of = [&](
const wxString& n ) ->
const std::vector<BRIDGE_NEIGHBOR>*
3377 if(
auto it = adjacency.find(n); it != adjacency.end() )
return &it->second;
3386 std::set<wxString> netsAll;
3387 for(
const auto&
kv : adjacency ) netsAll.insert(
kv.first );
3390 std::set<wxString> visited;
3391 for(
const wxString& start : netsAll )
3393 if( visited.contains( start ) )
continue;
3394 std::queue<wxString> q; q.push( start );
3395 std::set<wxString>
comp;
comp.insert( start ); visited.insert( start );
3398 wxString cur = q.front(); q.pop();
3399 if(
auto nbrs = neighbors_of( cur ) )
3403 if( visited.contains( e.other ) )
continue;
3404 visited.insert( e.other );
3405 comp.insert( e.other );
3410 if(
comp.size() >= 2 )
3412 auto sig = std::make_unique<SCH_NETCHAIN>();
3413 for(
const wxString& n :
comp ) sig->AddNet( n );
3415 if(
comp.contains( be.a ) &&
comp.contains( be.b ) && be.sym )
3416 sig->AddSymbol( be.sym );
3421 netToNetChain.clear();
3423 if( sigUP )
for(
const wxString& n : sigUP->GetNets() ) netToNetChain[n] = sigUP.get();
3429 if( !sigUP )
continue;
3432 for(
const wxString& n : sigUP->GetNets() )
3437 netsStr += wxS(
" ");
3441 netsStr += wxS(
"...");
3446 wxLogTrace(
traceSchNetChain,
" chain %p name='%s' nets=%zu [%s]", (
void*) sigUP.get(),
3447 sigUP->GetName(), sigUP->GetNets().size(), netsStr );
3455 std::set<wxString> committedNames;
3460 committedNames.insert(
chain->GetName() );
3472 net = sg->GetNetName();
3475 if( !net.IsEmpty() && net.Length() < 2048 && netToNetChain.count( net ) )
3478 if(
name.Length() > 512 )
3479 name.Truncate( 512 );
3480 if(
name.StartsWith( wxS(
"/" ) ) )
3485 if( !committedNames.count(
name ) )
3486 netToNetChain[net]->SetName(
name );
3492 wxLogTrace(
traceSchNetChain,
"RebuildNetChains: pass 3 (default naming)" );
3495 if( sig->GetName().IsEmpty() )
3497 sig->SetName( wxString::Format( wxT(
"NetChain%d" ), idx ) );
3502 wxLogTrace(
traceSchNetChain,
"RebuildNetChains: pass 4 (terminal pins)" );
3511 std::vector<PIN_INFO> pins;
3515 SCH_SCREEN* sc = sheetPath.LastScreen();
if( !sc )
continue;
3521 wxString net = getSubgraphNet( p );
3522 if( sig->GetNets().count( net ) )
3523 pins.push_back( { p, sym, &sheetPath } );
3530 size_t bestI = 0, bestJ = 0;
3532 for(
size_t i = 0; i < pins.size(); ++i )
3534 for(
size_t j = i + 1; j < pins.size(); ++j )
3536 VECTOR2I pa = pins[i].pin->GetPosition();
3537 VECTOR2I pb = pins[j].pin->GetPosition();
3538 int64_t dx = pa.
x - pb.
x;
3539 int64_t dy = pa.
y - pb.
y;
3540 int64_t d = dx * dx + dy * dy;
3545 a = pins[i].pin->m_Uuid;
3546 b = pins[j].pin->m_Uuid;
3553 sig->SetTerminalPins( a, b );
3555 if( best >= 0 && bestI < pins.size() && bestJ < pins.size() )
3557 sig->SetTerminalRefs( pins[bestI].sym->GetRef( pins[bestI].sheet ), pins[bestI].pin->GetNumber(),
3558 pins[bestJ].sym->GetRef( pins[bestJ].sheet ), pins[bestJ].pin->GetNumber() );
3564 sig->SetTerminalPins( ov.first, ov.second );
3568 wxLogTrace(
traceSchNetChain,
"RebuildNetChains: pass 5 (apply symbol names)" );
3575 sym->SetNetChainName( sig->
GetName() );
3578 for(
const wxString& n : sig->
GetNets() ) { netsStr += n + wxS(
" "); }
3588 std::set<wxString> alreadyCommitted;
3593 alreadyCommitted.insert(
chain->GetName() );
3597 std::map<std::pair<wxString, wxString>, wxString> refPinToNet;
3609 wxString ref = sym->
GetRef( &sp );
3619 refPinToNet[{ ref,
pin->GetNumber() }] =
3628 std::unordered_map<wxString, SCH_NETCHAIN*> committedByName;
3633 committedByName[
chain->GetName()] =
chain.get();
3638 std::set<wxString> refreshedThisPass;
3648 if( alreadyCommitted.count( chainName ) )
3650 auto it = committedByName.find( chainName );
3652 if( it != committedByName.end() && it->second )
3655 refreshedThisPass.insert( chainName );
3662 alreadyCommitted.insert( chainName );
3663 refreshedThisPass.insert( chainName );
3670 if( memberNets.empty() )
3675 if( alreadyCommitted.count( chainName ) && refreshedThisPass.count( chainName ) )
3685 SCH_PIN* terminalPinA =
nullptr;
3686 SCH_PIN* terminalPinB =
nullptr;
3687 std::set<SCH_SYMBOL*> symbols;
3699 wxString ref = sym->
GetRef( &sp );
3700 bool symContributes =
false;
3710 symContributes =
true;
3712 if( ref == termRefs.first.ref &&
pin->GetNumber() == termRefs.first.pin )
3715 if( ref == termRefs.second.ref &&
pin->GetNumber() == termRefs.second.pin )
3719 if( symContributes )
3720 symbols.insert( sym );
3724 if( !terminalPinA || !terminalPinB || symbols.empty() )
3727 "RebuildNetChains: cannot restore manual chain '%s' "
3728 "(terminals or member nets unresolved)",
3733 if( alreadyCommitted.count( chainName ) )
3735 auto it = committedByName.find( chainName );
3737 if( it != committedByName.end() && it->second )
3741 termRefs.first.ref, termRefs.first.pin,
3742 termRefs.second.ref, termRefs.second.pin );
3749 terminalPinB->
m_Uuid, termRefs.first.ref, termRefs.first.pin,
3750 termRefs.second.ref, termRefs.second.pin );
3751 alreadyCommitted.insert( chainName );
3763 sym->SetNetChainName(
chain->GetName() );
3776 catch(
const std::exception& e )
3778 wxFAIL_MSG( wxString::Format(
"RebuildNetChains threw: %s", e.what() ) );
3779 wxLogError(
_(
"Net chain rebuild failed: %s. The schematic may have stale chain "
3780 "data; reload to recover." ),
3781 wxString( e.what() ) );
3792 wxFAIL_MSG(
"RebuildNetChains threw an unknown exception" );
3793 wxLogError(
_(
"Net chain rebuild failed with an unknown error. The schematic may "
3794 "have stale chain data; reload to recover." ) );
3807 const std::map<std::pair<wxString, wxString>, wxString>& aRefPinToNet,
3808 const std::vector<std::unique_ptr<SCH_NETCHAIN>>& aPotentials,
3809 const wxString& aChainName )
3811 auto itFrom = aRefPinToNet.find( { aTermRefs.first.ref, aTermRefs.first.pin } );
3812 auto itTo = aRefPinToNet.find( { aTermRefs.second.ref, aTermRefs.second.pin } );
3814 if( itFrom == aRefPinToNet.end() || itTo == aRefPinToNet.end() )
3817 "RebuildNetChains: cannot restore chain '%s' (terminal %s.%s/%s.%s unresolved)",
3818 aChainName, aTermRefs.first.ref, aTermRefs.first.pin,
3819 aTermRefs.second.ref, aTermRefs.second.pin );
3823 for(
const auto& pot : aPotentials )
3825 if( pot && pot->GetNets().count( itFrom->second ) && pot->GetNets().count( itTo->second ) )
3830 "RebuildNetChains: no potential chain spans both terminals of '%s' (%s/%s)",
3831 aChainName, itFrom->second, itTo->second );
3838 if( !aPinA || !aPinB )
3850 if( netA.IsEmpty() || netB.IsEmpty() )
3855 if( sigUP && sigUP->GetNets().contains( netA ) && sigUP->GetNets().contains( netB ) )
3864 if( aName.IsEmpty() )
3868 [&](
const std::unique_ptr<SCH_NETCHAIN>& aChain )
3870 return aChain && aChain->GetName() == aName;
3881 sym->SetNetChainName( wxEmptyString );
3899 if( aOld.IsEmpty() || aNew.IsEmpty() || aOld == aNew )
3902 auto findByName = [&](
const wxString& aName ) ->
SCH_NETCHAIN*
3920 if( findByName( aNew ) )
3928 sym->SetNetChainName( aNew );
3942 auto rekey = [&](
auto& aMap )
3944 auto it = aMap.find( aOld );
3946 if( it != aMap.end() )
3948 auto val = std::move( it->second );
3950 aMap[aNew] = std::move( val );
3963 const std::set<wxString>& aNets,
3964 const std::set<SCH_SYMBOL*>& aSymbols,
3965 const KIID& aTerminalPinA,
3966 const KIID& aTerminalPinB,
3967 const wxString& aRefA,
3968 const wxString& aPinNumA,
3969 const wxString& aRefB,
3970 const wxString& aPinNumB )
3975 std::set<wxString> filtered;
3977 for(
const wxString& net : aNets )
3979 if( !net.IsEmpty() )
3980 filtered.insert( net );
3996 aTarget->
SetTerminalPins( termOverride->second.first, termOverride->second.second );
4003 sym->SetNetChainName( aTarget->
GetName() );
4021 auto sig = std::make_unique<SCH_NETCHAIN>();
4022 for(
const wxString& n : aPotential->
GetNets() )
4025 sig->AddSymbol( sym );
4026 sig->SetName( aName );
4035 sig->SetNetClass( ncIt->second );
4041 sig->SetColor( colIt->second );
4045 sym->SetNetChainName( sig->GetName() );
4060 std::set<wxString> persistableNets;
4062 for(
const wxString& net : sig->GetNets() )
4070 persistableNets.insert( net );
4073 if( !persistableNets.empty() )
4085 const std::set<SCH_SYMBOL*>& aSymbols,
4086 const std::set<wxString>& aNets,
4087 const KIID& aTerminalPinA,
4088 const KIID& aTerminalPinB,
4089 const wxString& aRefA,
4090 const wxString& aPinNumA,
4091 const wxString& aRefB,
4092 const wxString& aPinNumB )
4102 for(
const wxString& net : aNets )
4111 auto sig = std::make_unique<SCH_NETCHAIN>();
4112 sig->SetName( aName );
4114 for(
const wxString& net : aNets )
4123 sig->AddSymbol( sym );
4125 sig->SetTerminalPins( aTerminalPinA, aTerminalPinB );
4126 sig->SetTerminalRefs( aRefA, aPinNumA, aRefB, aPinNumB );
4131 sig->SetNetClass( ncIt->second );
4136 sig->SetColor( colIt->second );
4139 sym->SetNetChainName( sig->GetName() );
4156 wxLogTrace(
traceSchNetChain,
"CONNECTION_GRAPH::GetNetChainForNet(%s)", aNet );
4162 if( sig->GetNets().count( aNet ) )
4164 wxLogTrace(
traceSchNetChain,
"GetNetChainForNet: found chain '%s'", sig->GetName() );
4179 std::shared_ptr<NET_SETTINGS> netSettings =
m_schematic->Project().GetProjectFile().NetSettings();
4185 [](
const std::unique_ptr<SCH_NETCHAIN>& aChain )
4187 return aChain && !aChain->GetNetClass().IsEmpty();
4202 const wxString& netclass =
chain->GetNetClass();
4204 if( netclass.IsEmpty() || !netSettings->HasNetclass( netclass ) )
4207 for(
const wxString& net :
chain->GetNets() )
4221 wxLogTrace(
traceSchNetChain,
"CONNECTION_GRAPH::GetNetChainByName(%s)", aName );
4224 if( sig->GetName() == aName )
4239 wxLogTrace(
traceSchNetChain,
"ReplaceNetChainTerminalPin: chain='%s' prev=%s new=%s",
4243 sig->ReplaceTerminalPin( aPrev, aNew );
4245 sig->GetTerminalPinB() );
4246 wxLogTrace(
traceSchNetChain,
"ReplaceNetChainTerminalPin: updated overrides to (%s,%s)",
4247 sig->GetTerminalPinA().AsString(), sig->GetTerminalPinB().AsString() );
4253 std::pair<KIID, KIID>>& aOverrides )
4293 std::vector<std::shared_ptr<SCH_CONNECTION>> connections_to_check( aConnection->
Members() );
4295 for(
unsigned i = 0; i < connections_to_check.size(); i++ )
4297 const std::shared_ptr<SCH_CONNECTION>& member = connections_to_check[i];
4299 if( member->IsBus() )
4301 connections_to_check.insert( connections_to_check.end(),
4302 member->Members().begin(),
4303 member->Members().end() );
4315 std::vector<CONNECTION_SUBGRAPH*> search_list;
4316 std::unordered_set<CONNECTION_SUBGRAPH*> visited;
4317 std::unordered_set<SCH_CONNECTION*> stale_bus_members;
4324 path.push_back(
pin->GetParent() );
4335 || visited.contains( candidate ) )
4344 wxLogTrace(
ConnTrace, wxS(
"%lu: found child %lu (%s)" ), aParent->m_code,
4352 wxASSERT( candidate->
m_graph == aParent->m_graph );
4354 search_list.push_back( candidate );
4374 || visited.contains( candidate )
4380 const KIID& last_parent_uuid = aParent->m_sheet.Last()->m_Uuid;
4385 if(
pin->GetParent()->m_Uuid != last_parent_uuid )
4391 if( pin_path != aParent->m_sheet )
4396 wxLogTrace(
ConnTrace, wxS(
"%lu: found additional parent %lu (%s)" ),
4399 aParent->m_hier_children.insert( candidate );
4400 search_list.push_back( candidate );
4414 std::vector<std::shared_ptr<SCH_CONNECTION>> sortedMembers;
4416 for(
const auto&
kv : aParentGraph->m_bus_neighbors )
4417 sortedMembers.push_back(
kv.first );
4419 std::sort( sortedMembers.begin(), sortedMembers.end(),
4420 [](
const std::shared_ptr<SCH_CONNECTION>& a,
4421 const std::shared_ptr<SCH_CONNECTION>& b )
4423 return a->Name() < b->Name();
4426 for(
const std::shared_ptr<SCH_CONNECTION>& member_conn : sortedMembers )
4428 const auto& kv_it = aParentGraph->m_bus_neighbors.find( member_conn );
4430 if( kv_it == aParentGraph->m_bus_neighbors.end() )
4473 wxLogTrace(
ConnTrace, wxS(
"Could not match bus member %s in %s" ),
4474 member_conn->Name(), parent->
Name() );
4480 wxCHECK2( neighbor_conn,
continue );
4482 wxString neighbor_name = neighbor_conn->
Name();
4485 if( neighbor_name == member->
Name() )
4495 if( neighbor_conn->
Sheet() != parent->
Sheet() )
4506 bool alreadyUpdatedByBusMember =
false;
4508 for(
const auto& m : parent->
Members() )
4510 if( m->Name() == neighbor_name )
4512 alreadyUpdatedByBusMember =
true;
4517 if( alreadyUpdatedByBusMember )
4522 wxCHECK2_MSG( neighbor_conn->
IsNet(),
continue,
4523 wxS(
"\"" ) + neighbor_name + wxS(
"\" is not a net." ) );
4525 wxLogTrace(
ConnTrace, wxS(
"%lu (%s) connected to bus member %s (local %s)" ),
4532 member->
Clone( *neighbor_conn );
4533 stale_bus_members.insert( member );
4537 neighbor_conn->
Clone( *member );
4550 if( neighbor_conn->
Name() != member->
Name() )
4552 member->
Clone( *neighbor_conn );
4553 stale_bus_members.insert( member );
4562 propagate_bus_neighbors( aSubgraph );
4569 wxLogTrace(
ConnTrace, wxS(
"%lu (%s) has both hier ports and pins; deferring processing" ),
4575 wxLogTrace(
ConnTrace, wxS(
"%lu (%s) has no hier pins or ports on sheet %s; marking clean" ),
4581 visited.insert( aSubgraph );
4583 wxLogTrace(
ConnTrace, wxS(
"Propagating %lu (%s) to subsheets" ),
4588 for(
unsigned i = 0; i < search_list.size(); i++ )
4590 auto child = search_list[i];
4592 if( visited.insert( child ).second )
4595 child->m_dirty =
false;
4609 if( subgraph == aSubgraph )
4616 wxString candidateName = subgraph->m_driver_connection->Name();
4617 bool shorterPath = subgraph->m_sheet.size() < bestDriver->
m_sheet.
size();
4618 bool asGoodPath = subgraph->m_sheet.size() <= bestDriver->
m_sheet.
size();
4628 ( !bestIsStrong && candidateStrong ) ||
4629 ( priority > highest && candidateStrong ) ||
4630 ( priority == highest && candidateStrong && shorterPath ) ||
4631 ( ( bestIsStrong == candidateStrong ) && asGoodPath && ( priority == highest ) &&
4632 ( candidateName < bestName ) ) )
4634 bestDriver = subgraph;
4636 bestIsStrong = candidateStrong;
4637 bestName = candidateName;
4642 if( bestDriver != aSubgraph )
4644 wxLogTrace(
ConnTrace, wxS(
"%lu (%s) overridden by new driver %lu (%s)" ),
4653 wxString old_name = subgraph->m_driver_connection->Name();
4655 subgraph->m_driver_connection->Clone( *conn );
4657 if( old_name != conn->
Name() )
4661 propagate_bus_neighbors( subgraph );
4667 if( conn->
IsBus() && !stale_bus_members.empty() )
4669 std::unordered_set<SCH_CONNECTION*> cached_members = stale_bus_members;
4679 wxLogTrace(
ConnTrace, wxS(
"WARNING: failed to match stale member %s in %s." ),
4680 stale_member->Name(), subgraph->m_driver_connection->Name() );
4684 wxLogTrace(
ConnTrace, wxS(
"Updating %lu (%s) member %s to %s" ), subgraph->m_code,
4685 subgraph->m_driver_connection->Name(), member->
LocalName(), stale_member->Name() );
4687 member->
Clone( *stale_member );
4689 propagate_bus_neighbors( subgraph );
4701 std::shared_ptr<SCH_CONNECTION> c = std::shared_ptr<SCH_CONNECTION>(
nullptr );
4703 switch( aItem->
Type() )
4706 if(
static_cast<SCH_PIN*
>( aItem )->IsPower() )
4707 c = std::make_shared<SCH_CONNECTION>( aItem, aSubgraph->
m_sheet );
4714 c = std::make_shared<SCH_CONNECTION>( aItem, aSubgraph->
m_sheet );
4723 c->SetGraph(
this );
4734 if( !aBusConnection->
IsBus() )
4744 for(
const std::shared_ptr<SCH_CONNECTION>& bus_member : aBusConnection->
Members() )
4746 if( bus_member->VectorIndex() == aSearch->
VectorIndex() )
4748 match = bus_member.get();
4756 for(
const std::shared_ptr<SCH_CONNECTION>& c : aBusConnection->
Members() )
4763 for(
const std::shared_ptr<SCH_CONNECTION>& bus_member : c->Members() )
4765 if( bus_member->LocalName() == aSearch->
LocalName() )
4767 match = bus_member.get();
4772 else if( c->LocalName() == aSearch->
LocalName() )
4783 for(
const std::shared_ptr<SCH_CONNECTION>& c : aBusConnection->
Members() )
4787 for(
const std::shared_ptr<SCH_CONNECTION>& bus_member : c->Members() )
4791 match = bus_member.get();
4825 std::vector<CONNECTION_SUBGRAPH*>& vec = it->second;
4826 std::erase( vec, aSubgraph );
4829 wxLogTrace(
ConnTrace, wxS(
"recacheSubgraphName: %s => %s" ), aOldName,
4846 std::vector<const CONNECTION_SUBGRAPH*> ret;
4852 wxASSERT( !subgraph->m_dirty );
4854 if( !subgraph->m_driver )
4860 if( !connection->
IsBus() )
4863 auto labels = subgraph->GetVectorBusLabels();
4865 if( labels.size() > 1 )
4867 bool different =
false;
4870 for(
unsigned i = 1; i < labels.size(); ++i )
4882 wxLogTrace(
ConnTrace, wxS(
"SG %ld (%s) has multiple bus labels" ), subgraph->m_code,
4883 connection->
Name() );
4885 ret.push_back( subgraph );
4906 if( graph == aSubGraph )
4949 wxASSERT( !it->second.empty() );
4951 return it->second[0];
4972const std::vector<CONNECTION_SUBGRAPH*>&
4975 static const std::vector<CONNECTION_SUBGRAPH*> subgraphs;
4988 std::vector<wxString> equivalents;
4994 wxString
group = aBusName;
4995 size_t lastSlash = aBusName.find_last_of(
'/' );
4997 if( lastSlash != wxString::npos )
4999 path = aBusName.Left( lastSlash + 1 );
5000 group = aBusName.Mid( lastSlash + 1 );
5004 std::vector<wxString> members;
5010 if( !prefix.IsEmpty() )
5015 for( wxString& member : members )
5017 member.Replace( wxT(
"\\ " ), wxT(
" " ) );
5024 if( members.size() == 1 )
5030 selfAlias = members[0];
5031 members = aliasIt->second->Members();
5036 wxString expandedLabel =
path + wxT(
"{" );
5038 for(
size_t i = 0; i < members.size(); ++i )
5041 expandedLabel += wxT(
" " );
5044 escaped.Replace( wxT(
" " ), wxT(
"\\ " ) );
5045 expandedLabel += escaped;
5048 expandedLabel += wxT(
"}" );
5050 if( expandedLabel != aBusName )
5051 equivalents.push_back( expandedLabel );
5054 std::multiset<wxString> memberSet( members.begin(), members.end() );
5058 if( aliasName == selfAlias || alias->Members().size() != members.size() )
5061 std::multiset<wxString> aliasMembers( alias->Members().begin(), alias->Members().end() );
5063 if( memberSet == aliasMembers )
5064 equivalents.push_back(
path + wxT(
"{" ) + aliasName + wxT(
"}" ) );
5073 int error_count = 0;
5075 wxCHECK_MSG(
m_schematic,
true, wxS(
"Null m_schematic in CONNECTION_GRAPH::RunERC" ) );
5081 std::set<SCH_ITEM*> seenDriverInstances;
5086 wxCHECK2( subgraph,
continue );
5090 wxASSERT( !subgraph->m_dirty );
5092 if( subgraph->m_absorbed )
5095 if( seenDriverInstances.count( subgraph->m_driver ) )
5098 if( subgraph->m_driver )
5099 seenDriverInstances.insert( subgraph->m_driver );
5117 subgraph->ResolveDrivers(
false );
5188 wxCHECK( aSubgraph,
false );
5194 if( driver == aSubgraph->
m_driver )
5205 if( primaryName == secondaryName )
5208 wxString msg = wxString::Format(
_(
"Both %s and %s are attached to the same "
5209 "items; %s will be used in the netlist" ),
5210 primaryName, secondaryName, primaryName );
5213 ercItem->SetItems( aSubgraph->
m_driver, driver );
5214 ercItem->SetSheetSpecificPath( aSubgraph->
GetSheet() );
5215 ercItem->SetItemsSheetPaths( aSubgraph->
GetSheet(), aSubgraph->
m_sheet );
5216 ercItem->SetErrorMessage( msg );
5241 switch( item->
Type() )
5246 bus_item = ( !bus_item ) ? item : bus_item;
5248 net_item = ( !net_item ) ? item : net_item;
5262 bus_item = ( !bus_item ) ? item : bus_item;
5264 net_item = ( !net_item ) ? item : net_item;
5274 if( net_item && bus_item )
5277 ercItem->SetSheetSpecificPath( sheet );
5278 ercItem->SetItems( net_item, bus_item );
5281 screen->
Append( marker );
5300 switch( item->
Type() )
5327 if(
test != member && member->Name() ==
test->Name() )
5341 ercItem->SetSheetSpecificPath( sheet );
5342 ercItem->SetItems( label, port );
5345 screen->
Append( marker );
5357 bool conflict =
false;
5373 switch( item->
Type() )
5403 std::set<wxString> test_names;
5415 for(
const auto& sub_member : member->Members() )
5417 if( test_names.count( sub_member->FullLocalName() ) )
5421 else if( test_names.count( member->FullLocalName() ) )
5440 wxString msg = wxString::Format(
_(
"Net %s is graphically connected to bus %s but is not a"
5441 " member of that bus" ),
5445 ercItem->SetSheetSpecificPath( sheet );
5446 ercItem->SetItems( bus_entry, bus_wire );
5447 ercItem->SetErrorMessage( msg );
5450 screen->
Append( marker );
5467 std::set<SCH_PIN*> unique_pins;
5468 std::set<SCH_LABEL_BASE*> unique_labels;
5476 for(
SCH_ITEM* item : aProcessGraph->m_items )
5478 switch( item->
Type() )
5485 if( aProcessGraph == aSubgraph )
5488 if( std::none_of( unique_pins.begin(), unique_pins.end(),
5491 return test_pin->IsStacked( aPin );
5495 unique_pins.insert( test_pin );
5518 process_subgraph( subgraph );
5523 process_subgraph( aSubgraph );
5539 switch( item->
Type() )
5586 ercItem->SetSheetSpecificPath( sheet );
5587 ercItem->SetItemsSheetPaths( sheet );
5594 pos =
pin->GetPosition();
5603 screen->
Append( marker );
5608 if( unique_pins.empty() && unique_labels.empty() &&
5613 ercItem->SetSheetSpecificPath( sheet );
5614 ercItem->SetItemsSheetPaths( sheet );
5617 screen->
Append( marker );
5624 bool has_other_connections =
false;
5625 std::vector<SCH_PIN*> pins;
5632 switch( item->
Type() )
5639 if( !has_other_connections && !pins.empty()
5642 for(
SCH_PIN* other_pin : pins )
5646 has_other_connections =
true;
5652 pins.emplace_back(
static_cast<SCH_PIN*
>( item ) );
5659 has_other_connections =
true;
5666 pin = pins.empty() ? nullptr : pins[0];
5669 for(
SCH_PIN* test_pin : pins )
5686 ?
pin->GetLibPin()->GetParentSymbol() :
nullptr;
5688 if(
pin && !has_other_connections
5690 && ( !pinLibParent || !pinLibParent->
IsPower() ) )
5692 wxString
name =
pin->Connection( &sheet )->Name();
5693 wxString local_name =
pin->Connection( &sheet )->Name(
true );
5698 has_other_connections =
true;
5703 if(
pin && !has_other_connections
5709 ercItem->SetSheetSpecificPath( sheet );
5710 ercItem->SetItemsSheetPaths( sheet );
5711 ercItem->SetItems(
pin );
5714 screen->
Append( marker );
5722 if( pins.size() > 1 )
5724 for(
SCH_PIN* testPin : pins )
5729 SYMBOL* testLibParent = testPin->GetLibPin()
5733 if( testLibParent && testLibParent->
IsPower()
5734 && testPin->ConnectedItems( sheet ).empty()
5738 ercItem->SetSheetSpecificPath( sheet );
5739 ercItem->SetItemsSheetPaths( sheet );
5740 ercItem->SetItems( testPin );
5743 screen->
Append( marker );
5776 ercItem->SetItems( line );
5777 ercItem->SetSheetSpecificPath( sheet );
5778 ercItem->SetErrorMessage(
_(
"Unconnected wire endpoint" ) );
5800 ercItem->SetItems( entry );
5801 ercItem->SetSheetSpecificPath( sheet );
5802 ercItem->SetErrorMessage(
_(
"Unconnected wire to bus entry" ) );
5819 return err_count > 0;
5829 std::vector<SCH_ITEM*> wires;
5836 wires.emplace_back( item );
5838 wires.emplace_back( item );
5841 if( !wires.empty() )
5846 ercItem->SetSheetSpecificPath( sheet );
5847 ercItem->SetItems( wires[0],
5848 wires.size() > 1 ? wires[1] :
nullptr,
5849 wires.size() > 2 ? wires[2] :
nullptr,
5850 wires.size() > 3 ? wires[3] :
nullptr );
5853 screen->
Append( marker );
5863 std::unordered_set<const CONNECTION_SUBGRAPH*>& aOut )
const
5872 for(
const auto& [sibMemberConn, sibMembers] : siblingBus->
m_bus_neighbors )
5874 if( sibMemberConn->Name() != aMemberName )
5878 aOut.insert( sibling );
5903 size_t pinCount = 0;
5906 std::map<KICAD_T, std::vector<SCH_TEXT*>> label_map;
5912 return std::count_if( aLocSubgraph->m_items.begin(), aLocSubgraph->m_items.end(),
5915 return item->Type() == SCH_PIN_T;
5920 [&](
SCH_TEXT* aText,
int errCode )
5925 ercItem->SetSheetSpecificPath( sheet );
5926 ercItem->SetItems( aText );
5933 pinCount =
hasPins( aSubgraph );
5937 switch( item->
Type() )
5945 label_map[item->
Type()].push_back(
text );
5950 if(
text->IsDangling() )
5964 if( label_map.empty() )
5970 std::unordered_set<const CONNECTION_SUBGRAPH*> busMemberSiblings;
5972 for(
auto& [memberConn, busParents] : aSubgraph->
m_bus_parents )
5974 wxString memberName = memberConn->Name();
5978 if( busParent->m_no_connect )
5983 if( hp->m_no_connect )
5993 wxCHECK_MSG(
m_schematic,
true, wxS(
"Null m_schematic in CONNECTION_GRAPH::ercCheckLabels" ) );
6000 for(
auto& [type, label_vec] : label_map )
6004 size_t allPins = pinCount;
6005 size_t localPins = pinCount;
6006 bool hasLocalHierarchy =
false;
6014 std::set<wxString> uniquePortNames;
6018 if( aSubgraph->
m_hier_pins.size() + uniquePortNames.size() > 1 )
6020 hasLocalHierarchy =
true;
6025 for(
auto& [connection, busParents] : aSubgraph->
m_bus_parents )
6029 if( busParent->m_sheet == sheet
6030 && ( !busParent->m_hier_pins.empty()
6031 || !busParent->m_hier_ports.empty() ) )
6033 hasLocalHierarchy =
true;
6038 if( hasLocalHierarchy )
6043 std::unordered_set<const CONNECTION_SUBGRAPH*> creditedNeighbors;
6044 creditedNeighbors.insert( aSubgraph );
6048 if( !creditedNeighbors.insert( neighbor ).second )
6051 if( neighbor->m_no_connect )
6054 size_t neighborPins =
hasPins( neighbor );
6055 allPins += neighborPins;
6057 if( neighbor->m_sheet == sheet )
6059 localPins += neighborPins;
6061 if( !neighbor->m_hier_pins.empty() || !neighbor->m_hier_ports.empty() )
6063 hasLocalHierarchy =
true;
6073 creditNeighbor( neighbor );
6077 creditNeighbor( sibling );
6079 if( allPins == 1 && !has_nc )
6090 || ( type ==
SCH_LABEL_T && localPins == 0 && allPins > 1
6091 && !has_nc && !hasLocalHierarchy ) )
6107 std::map<wxString, std::tuple<int, const SCH_ITEM*, SCH_SHEET_PATH>> labelData;
6114 wxString resolvedLabelText =
6117 if( labelData.find( resolvedLabelText ) == labelData.end() )
6119 labelData[resolvedLabelText] = { 1, item, sheet };
6123 std::get<0>( labelData[resolvedLabelText] ) += 1;
6124 std::get<1>( labelData[resolvedLabelText] ) =
nullptr;
6125 std::get<2>( labelData[resolvedLabelText] ) = sheet;
6130 for(
const auto& label : labelData )
6132 if( std::get<0>( label.second ) == 1 )
6135 const SCH_ITEM* item = std::get<1>( label.second );
6138 ercItem->SetItems( std::get<1>( label.second ) );
6139 ercItem->SetSheetSpecificPath( sheet );
6140 ercItem->SetItemsSheetPaths( sheet );
6155 int error_count = 0;
6167 ercItem->SetSheetSpecificPath( sheet );
6168 ercItem->SetItems(
text );
6171 sheet.LastScreen()->Append( marker );
6191 if( sheet.Last()->IsTopLevelSheet() )
6197 wxCHECK2( label,
continue );
6199 msg.Printf(
_(
"Hierarchical label '%s' in root sheet cannot be connected to non-existent "
6203 ercItem->SetItems( item );
6204 ercItem->SetErrorMessage( msg );
6207 sheet.LastScreen()->Append( marker );
6218 parentSheetPath.
push_back( parentSheet );
6220 std::map<wxString, SCH_SHEET_PIN*> pins;
6221 std::map<wxString, SCH_HIERLABEL*> labels;
6226 pins[
pin->GetShownText( &parentSheetPath,
false ) ] =
pin;
6231 ercItem->SetItems(
pin );
6232 ercItem->SetSheetSpecificPath( sheet );
6233 ercItem->SetItemsSheetPaths( sheet );
6236 sheet.LastScreen()->Append( marker );
6244 std::set<wxString> matchedPins;
6251 wxString labelText = label->
GetShownText( &parentSheetPath,
false );
6253 if( !pins.contains( labelText ) )
6254 labels[ labelText ] = label;
6256 matchedPins.insert( labelText );
6260 for(
const wxString& matched : matchedPins )
6261 pins.erase( matched );
6263 for(
const auto& [
name,
pin] : pins )
6265 msg.Printf(
_(
"Sheet pin %s has no matching hierarchical label inside the sheet" ),
6269 ercItem->SetItems(
pin );
6270 ercItem->SetErrorMessage( msg );
6271 ercItem->SetSheetSpecificPath( sheet );
6272 ercItem->SetItemsSheetPaths( sheet );
6275 sheet.LastScreen()->Append( marker );
6280 for(
const auto& [
name, label] : labels )
6282 msg.Printf(
_(
"Hierarchical label %s has no matching sheet pin in the parent sheet" ),
6286 ercItem->SetItems( label );
6287 ercItem->SetErrorMessage( msg );
6288 ercItem->SetSheetSpecificPath( parentSheetPath );
6289 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.
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)
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::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.
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.
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.
static bool ParseBusGroup(const wxString &aGroup, wxString *name, std::vector< wxString > *aMemberList)
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
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.
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_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