27#include <unordered_map>
108 if( old_conn && new_conn )
110 new_conn->
Clone( *old_conn );
140 std::vector<SCH_ITEM*> candidates;
141 std::set<SCH_ITEM*> strong_drivers;
165 strong_drivers.insert( item );
167 if( item_priority > highest_priority )
170 candidates.push_back( item );
171 highest_priority = item_priority;
173 else if( !candidates.empty() && ( item_priority == highest_priority ) )
175 candidates.push_back( item );
185 if( !candidates.empty() )
222 if( aGlobal != bGlobal )
228 if( aLocal != bLocal )
249 bool a_lowQualityName = a_name.Contains(
"-Pad" );
250 bool b_lowQualityName = b_name.Contains(
"-Pad" );
252 if( a_lowQualityName != b_lowQualityName )
253 return !a_lowQualityName;
255 return a_name < b_name;
258 std::sort( candidates.begin(), candidates.end(), candidate_cmp );
263 if( strong_drivers.size() > 1 )
270 m_drivers.insert( strong_drivers.begin(), strong_drivers.end() );
292 std::set<CONNECTION_SUBGRAPH*>& aSubgraphs )
304 if( aSubgraphs.insert( sg ).second ==
false )
310 aItems.emplace(
m_sheet, item );
324#ifdef CONNECTIVITY_DEBUG
325 wxASSERT_MSG(
false, wxS(
"Tried to get the net name of an item with no connection" ) );
337 std::vector<SCH_ITEM*> labels;
341 switch( item->Type() )
351 labels.push_back( item );
367 std::vector<SCH_ITEM*> labels;
371 switch( item->Type() )
381 labels.push_back( item );
397 switch( aItem->
Type() )
404 return pin->GetDefaultNetName(
m_sheet, forceNoConnect );
431 wxFAIL_MSG( wxS(
"Unhandled item type in GetNameForDriver" ) );
432 return wxEmptyString;
452const std::vector<std::pair<wxString, SCH_ITEM*>>
455 std::vector<std::pair<wxString, SCH_ITEM*>> foundNetclasses;
457 const std::unordered_set<SCH_RULE_AREA*>& ruleAreaCache = aItem->
GetRuleAreaCache();
462 const std::vector<std::pair<wxString, SCH_ITEM*>> ruleAreaNetclasses =
463 ruleArea->GetResolvedNetclasses( &
m_sheet );
465 if( ruleAreaNetclasses.size() > 0 )
467 foundNetclasses.insert( foundNetclasses.end(), ruleAreaNetclasses.begin(),
468 ruleAreaNetclasses.end() );
484 if( netclass != wxEmptyString )
485 foundNetclasses.push_back( { netclass, aItem } );
492 foundNetclasses.begin(), foundNetclasses.end(),
493 [](
const std::pair<wxString, SCH_ITEM*>& i1,
const std::pair<wxString, SCH_ITEM*>& i2 )
495 return i1.first < i2.first;
498 return foundNetclasses;
524 child->m_absorbed_by =
this;
527 set_absorbed_by( subchild );
535 set_absorbed_by( aOther );
585 if(
const std::unique_ptr<LIB_SYMBOL>& part = symbol->GetLibSymbolRef() )
586 return part->GetReferenceField().GetText();
588 return wxEmptyString;
591 switch( aDriver->
Type() )
622 std::back_inserter(
m_items ) );
677 wxCHECK2( aOldItem->
Type() == aNewItem->
Type(),
return );
712 wxCHECK2( oldPins.size() == newPins.size(),
return );
714 for(
size_t ii = 0; ii < oldPins.size(); ii++ )
716 exchange( oldPins[ii], newPins[ii] );
727 if( subgraph->m_graph ==
this )
751 std::function<
void(
SCH_ITEM* )>* aChangedItemHandler,
755 PROF_TIMER recalc_time(
"CONNECTION_GRAPH::Recalculate" );
756 monitorTrans.
Start();
761 monitorTrans.
StartSpan(
"updateItemConnectivity",
"" );
762 PROF_TIMER update_items(
"updateItemConnectivity" );
765 std::set<SCH_ITEM*> dirty_items;
767 int count = aSheetList.size() * 2;
772 if( aProgressReporter )
778 std::vector<SCH_ITEM*> items;
781 std::vector<std::pair<SCH_SYMBOL*, int>> symbolsChanged;
783 for(
SCH_ITEM* item : sheet.LastScreen()->Items() )
785 if( item->IsConnectable() && ( aUnconditional || item->IsConnectivityDirty() ) )
787 wxLogTrace(
ConnTrace, wxT(
"Adding item %s to connectivity graph update" ),
788 item->GetTypeDesc() );
789 items.push_back( item );
790 dirty_items.insert( item );
799 if(
pin->IsConnectivityDirty() )
801 dirty_items.insert(
pin );
814 if(
pin->IsConnectivityDirty() )
816 items.push_back(
pin );
817 dirty_items.insert(
pin );
827 if(
pin->IsConnectivityDirty() )
829 items.push_back(
pin );
830 dirty_items.insert(
pin );
843 if( symbol->
GetUnit() != new_unit )
844 symbolsChanged.push_back( { symbol, symbol->
GetUnit() } );
854 if( aProgressReporter )
861 sheet.LastScreen()->TestDanglingEnds( &sheet, aChangedItemHandler );
864 for(
const auto& [ symbol, originalUnit ] : symbolsChanged )
865 symbol->SetUnit( originalUnit );
876 item->SetConnectivityDirty(
false );
883 PROF_TIMER build_graph(
"buildConnectionGraph" );
884 monitorTrans.
StartSpan(
"BuildConnectionGraph",
"" );
903 const std::set<SCH_ITEM*> &aItems )
905 std::set<std::pair<SCH_SHEET_PATH, SCH_ITEM*>> retvals;
906 std::set<CONNECTION_SUBGRAPH*> subgraphs;
911 while( aSubgraph->m_absorbed_by )
914 wxASSERT( aSubgraph->m_graph == aSubgraph->m_absorbed_by->m_graph );
915 aSubgraph = aSubgraph->m_absorbed_by;
919 while( aSubgraph->m_hier_parent )
922 wxASSERT( aSubgraph->m_graph == aSubgraph->m_hier_parent->m_graph );
923 aSubgraph = aSubgraph->m_hier_parent;
927 aSubgraph->getAllConnectedItems( retvals, subgraphs );
930 auto extract_element = [&](
SCH_ITEM* aItem )
936 wxLogTrace(
ConnTrace, wxT(
"Item %s not found in connection graph" ),
937 aItem->GetTypeDesc() );
943 wxLogTrace(
ConnTrace, wxT(
"Item %s in subgraph %ld (%p) has no driver" ),
944 aItem->GetTypeDesc(), item_sg->
m_code, item_sg );
949 if( sg_to_scan.empty() )
951 wxLogTrace(
ConnTrace, wxT(
"Item %s in subgraph %ld with net %s has no neighbors" ),
953 sg_to_scan.push_back( item_sg );
957 wxT(
"Removing all item %s connections from subgraph %ld with net %s: Found "
964 traverse_subgraph( sg );
966 for(
auto& bus_it : sg->m_bus_neighbors )
969 traverse_subgraph( bus_sg );
972 for(
auto& bus_it : sg->m_bus_parents )
975 traverse_subgraph( bus_sg );
989 extract_element(
pin );
996 extract_element(
pin );
1000 extract_element( item );
1006 for(
const auto& [
path, item] : retvals )
1033 wxLogTrace(
ConnTrace, wxT(
"Removing %zu subgraphs" ), aSubgraphs.size() );
1036 std::set<int> codes_to_remove;
1040 std::sort( el.second.begin(), el.second.end() );
1045 for(
auto& it : sg->m_bus_neighbors )
1051 for(
auto test = parents.begin();
test != parents.end(); )
1059 if( parents.empty() )
1064 for(
auto& it : sg->m_bus_parents )
1070 for(
auto test = neighbors.begin();
test != neighbors.end(); )
1078 if( neighbors.empty() )
1099 auto it = std::lower_bound( el.second.begin(), el.second.end(), sg );
1101 while( it != el.second.end() && *it == sg )
1102 it = el.second.erase( it );
1105 auto remove_sg = [sg](
auto it ) ->
bool
1118 if( remove_sg( it ) )
1126 if( remove_sg( it ) )
1135 if( remove_sg( it ) )
1137 codes_to_remove.insert( it->first.Netcode );
1149 if( remove_sg( it ) )
1157 if( it->second == sg )
1168 if( codes_to_remove.contains( it->second ) )
1176 if( codes_to_remove.contains( it->second ) )
1185 sg->m_graph =
nullptr;
1192 std::map<
VECTOR2I, std::vector<SCH_ITEM*>>& aConnectionMap )
1203 aConn->SetName(
name );
1208 std::map<wxString, std::vector<SCH_PIN*>> pinNumberMap;
1214 updatePin(
pin, conn );
1215 aConnectionMap[
pin->GetPosition() ].push_back(
pin );
1216 pinNumberMap[
pin->GetNumber()].emplace_back(
pin );
1219 auto linkPinsInVec =
1220 [&](
const std::vector<SCH_PIN*>& aVec )
1222 for(
size_t i = 0; i < aVec.size(); ++i )
1224 for(
size_t j = i + 1; j < aVec.size(); ++j )
1226 aVec[i]->AddConnectionTo( aSheet, aVec[j] );
1227 aVec[j]->AddConnectionTo( aSheet, aVec[i] );
1236 for(
const auto& [number,
group] : pinNumberMap )
1237 linkPinsInVec(
group );
1242 std::vector<SCH_PIN*> pins;
1244 for(
const wxString& pinNumber :
group )
1247 pins.emplace_back(
pin );
1250 linkPinsInVec( pins );
1273 std::map<
VECTOR2I, std::vector<SCH_ITEM*>>& aConnectionMap )
1278 m_items.emplace_back( aItem );
1281 switch( aItem->
Type() )
1294 if( points.empty() )
1295 points = {
static_cast<SCH_PIN*
>( aItem )->GetPosition() };
1308 for(
const VECTOR2I& point : points )
1309 aConnectionMap[point].push_back( aItem );
1314 const std::vector<SCH_ITEM*>& aItemList )
1316 wxLogTrace( wxT(
"Updating connectivity for sheet %s with %zu items" ),
1318 std::map<VECTOR2I, std::vector<SCH_ITEM*>> connection_map;
1322 std::vector<VECTOR2I> points = item->GetConnectionPoints();
1323 item->ClearConnectedItems( aSheet );
1329 pin->InitializeConnection( aSheet,
this );
1331 pin->ClearConnectedItems( aSheet );
1333 connection_map[
pin->GetTextPos() ].push_back(
pin );
1350 VECTOR2I point = item->GetPosition();
1353 std::vector<SCH_ITEM*> overlapping_items;
1355 std::copy_if( items.begin(), items.end(), std::back_inserter( overlapping_items ),
1358 return test_item->Type() == SCH_LINE_T
1359 && test_item->HitTest( point, -1 );
1364 if( overlapping_items.size() < 2 )
continue;
1366 for(
SCH_ITEM* test_item : overlapping_items )
1367 connection_map[point].push_back( test_item );
1376 VECTOR2I point = item->GetPosition();
1380 connection_map[point].push_back( wire );
1385 for(
auto& [point, connection_vec] : connection_map )
1387 std::sort( connection_vec.begin(), connection_vec.end() );
1393 for(
SCH_ITEM* connected_item : connection_vec )
1407 if( connection_vec.size() == 1 )
1423 if( point == bus_entry->GetPosition() )
1426 bus_entry->m_connected_bus_items[1] = busLine;
1439 for(
SCH_ITEM* test_item : connection_vec )
1441 bool bus_connection_ok =
true;
1443 if( test_item == connected_item )
1449 if( test_item->GetLayer() ==
LAYER_BUS )
1468 if( connected_item->ConnectionPropagatesTo( test_item )
1469 && test_item->ConnectionPropagatesTo( connected_item )
1470 && bus_connection_ok )
1472 connected_item->AddConnectionTo( aSheet, test_item );
1483 if( !bus_entry->m_connected_bus_item )
1489 bus_entry->m_connected_bus_item = bus;
1500 wxCHECK_RET(
m_schematic, wxS(
"Connection graph cannot be built without schematic pointer" ) );
1504 for(
const std::shared_ptr<BUS_ALIAS>& alias :
m_schematic->GetAllBusAliases() )
1513 for(
const auto& [sheet, connection] : item->m_connection_map )
1515 if( connection->SubgraphCode() == 0 )
1524 connection->SetSubgraphCode( subgraph->
m_code );
1527 std::list<SCH_ITEM*> memberlist;
1532 SCH_CONNECTION* conn = aItem->GetOrInitConnection( sheet,
this );
1538 return ( unique && conn && ( conn->
SubgraphCode() == 0 ) );
1541 std::copy_if( item->ConnectedItems( sheet ).begin(),
1542 item->ConnectedItems( sheet ).end(),
1543 std::back_inserter( memberlist ), get_items );
1545 for(
SCH_ITEM* connected_item : memberlist )
1550 SCH_CONNECTION* connected_conn = connected_item->Connection( &sheet );
1552 wxCHECK2( connected_conn,
continue );
1558 subgraph->
AddItem( connected_item );
1559 const SCH_ITEM_VEC& citemset = connected_item->ConnectedItems( sheet );
1566 if( get_items( citem ) )
1567 memberlist.push_back( citem );
1572 for(
SCH_ITEM* connected_item : memberlist )
1586 std::vector<CONNECTION_SUBGRAPH*> dirty_graphs;
1591 return candidate->m_dirty;
1594 wxLogTrace(
ConnTrace, wxT(
"Resolving drivers for %zu subgraphs" ), dirty_graphs.size() );
1596 std::vector<std::future<size_t>> returns( dirty_graphs.size() );
1598 auto update_lambda =
1601 if( !subgraph->m_dirty )
1605 for(
SCH_ITEM* item : subgraph->m_items )
1607 switch( item->
Type() )
1610 subgraph->m_no_connect = item;
1614 subgraph->m_bus_entry = item;
1622 subgraph->m_no_connect = item;
1632 subgraph->ResolveDrivers(
true );
1633 subgraph->m_dirty =
false;
1640 auto results =
tp.submit_loop( 0, dirty_graphs.size(),
1643 update_lambda( dirty_graphs[ii] );
1652 return candidate->m_driver;
1665 wxString full_name = subgraph->m_driver_connection->Name();
1666 wxString
name = subgraph->m_driver_connection->Name(
true );
1675 wxString prefixOnly = full_name.BeforeFirst(
'[' ) + wxT(
"[]" );
1679 subgraph->m_dirty =
true;
1681 if( subgraph->m_strong_driver )
1683 SCH_ITEM* driver = subgraph->m_driver;
1686 switch( driver->
Type() )
1702 if(
pin->IsGlobalPower() )
1706 else if(
pin->IsLocalPower() )
1713 wxLogTrace(
ConnTrace, wxS(
"Unexpected normal pin %s" ),
1723 wxLogTrace(
ConnTrace, wxS(
"Unexpected strong driver %s" ),
1735 std::vector<CONNECTION_SUBGRAPH*> new_subgraphs;
1746 dummy.SetGraph(
this );
1749 wxLogTrace(
ConnTrace, wxS(
"new bus label (%s)" ),
1752 for(
const auto& conn :
dummy.Members() )
1755 if( !conn->IsNet() )
1758 wxString
name = conn->FullLocalName();
1765 auto new_conn = std::make_unique<SCH_CONNECTION>( item, subgraph->m_sheet );
1766 new_conn->SetGraph(
this );
1767 new_conn->SetName(
name );
1770 SCH_CONNECTION* new_conn_ptr = subgraph->StoreImplicitConnection( std::move( new_conn ) );
1773 wxLogTrace(
ConnTrace, wxS(
"SG(%ld), Adding full local name (%s) with sg (%d) on subsheet %s" ),
1774 subgraph->m_code,
name, code, subgraph->m_sheet.PathHumanReadable() );
1787 new_subgraphs.push_back( new_sg );
1792 std::copy( new_subgraphs.begin(), new_subgraphs.end(),
1808 [](
const std::pair<SCH_SHEET_PATH, SCH_PIN*>& a,
1809 const std::pair<SCH_SHEET_PATH, SCH_PIN*>& b )
1811 int pathCmp = a.first.Cmp( b.first );
1816 const SCH_SYMBOL* symA = static_cast<const SCH_SYMBOL*>( a.second->GetParentSymbol() );
1817 const SCH_SYMBOL* symB = static_cast<const SCH_SYMBOL*>( b.second->GetParentSymbol() );
1819 wxString refA = symA ? symA->GetRef( &a.first, false ) : wxString();
1820 wxString refB = symB ? symB->GetRef( &b.first, false ) : wxString();
1822 int refCmp = refA.Cmp( refB );
1827 return a.second->GetNumber().Cmp( b.second->GetNumber() ) < 0;
1830 std::unordered_map<int, CONNECTION_SUBGRAPH*> global_power_pin_subgraphs;
1834 SYMBOL* libParent =
pin->GetLibPin() ?
pin->GetLibPin()->GetParentSymbol() :
nullptr;
1836 if( !
pin->ConnectedItems( sheet ).empty()
1853 connection->
SetName(
pin->GetParentSymbol()->GetValue(
true, &sheet,
false ) );
1862 auto jj = global_power_pin_subgraphs.find( code );
1864 if( jj != global_power_pin_subgraphs.end() )
1866 subgraph = jj->second;
1884 global_power_pin_subgraphs[code] = subgraph;
1901 std::unordered_set<CONNECTION_SUBGRAPH*> invalidated_subgraphs;
1905 if( subgraph->m_absorbed )
1910 wxString
name = connection->
Name();
1913 unsigned suffix = 1;
1915 auto create_new_name =
1919 wxString suffixStr = std::to_wstring( suffix );
1926 wxString prefix = aConn->BusPrefix();
1928 if( prefix.empty() )
1929 prefix = wxT(
"BUS" );
1934 wxString members = aConn->Name().Mid( aConn->BusPrefix().length() );
1936 newName << prefix << wxT(
"_" ) << suffixStr << members;
1938 aConn->ConfigureFromLabel( newName );
1942 newName << aConn->Name() << wxT(
"_" ) << suffixStr;
1943 aConn->SetSuffix( wxString( wxT(
"_" ) ) << suffixStr );
1950 if( !subgraph->m_strong_driver )
1952 std::vector<CONNECTION_SUBGRAPH*> vec_empty;
1953 std::vector<CONNECTION_SUBGRAPH*>* vec = &vec_empty;
1962 wxString prefixOnly =
name.BeforeFirst(
'[' ) + wxT(
"[]" );
1968 if( vec->size() > 1 )
1970 wxString new_name = create_new_name( connection );
1973 new_name = create_new_name( connection );
1975 wxLogTrace(
ConnTrace, wxS(
"%ld (%s) is weakly driven and not unique. Changing to %s." ),
1976 subgraph->m_code,
name, new_name );
1978 std::erase( *vec, subgraph );
1984 else if( subgraph->m_driver )
1996 bool conflict =
false;
1997 wxString global_name = connection->
Name(
true );
2004 std::vector<CONNECTION_SUBGRAPH*>& candidates = kk->second;
2008 if( candidate->m_sheet == sheet )
2015 wxLogTrace(
ConnTrace, wxS(
"%ld (%s) skipped for promotion due to potential conflict" ),
2016 subgraph->m_code,
name );
2022 wxLogTrace(
ConnTrace, wxS(
"%ld (%s) weakly driven by unique sheet pin %s, promoting" ),
2023 subgraph->m_code,
name,
2024 subgraph->m_driver->GetItemDescription( &unitsProvider,
true ) );
2026 subgraph->m_strong_driver =
true;
2033 if( connection->
IsBus() )
2057 subgraph->m_dirty =
true;
2065 if( !subgraph->m_strong_driver )
2072 std::vector<CONNECTION_SUBGRAPH*> candidate_subgraphs;
2075 std::back_inserter( candidate_subgraphs ),
2078 return ( !candidate->m_absorbed &&
2079 candidate->m_strong_driver &&
2080 candidate != subgraph );
2086 std::vector< std::shared_ptr<SCH_CONNECTION> > connections_to_check;
2089 connections_to_check.push_back( std::make_shared<SCH_CONNECTION>( *connection ) );
2091 auto add_connections_to_check =
2094 for(
SCH_ITEM* possible_driver : aSubgraph->m_items )
2096 if( possible_driver == aSubgraph->m_driver )
2103 if( c->Type() != aSubgraph->m_driver_connection->Type() )
2106 if( c->Name(
true ) == aSubgraph->m_driver_connection->Name(
true ) )
2109 connections_to_check.push_back( c );
2110 wxLogTrace(
ConnTrace, wxS(
"%lu (%s): Adding secondary driver %s" ),
2112 aSubgraph->m_driver_connection->Name(
true ),
2121 add_connections_to_check( subgraph );
2123 std::set<SCH_CONNECTION*> checked_connections;
2125 for(
unsigned i = 0; i < connections_to_check.size(); i++ )
2127 auto member = connections_to_check[i];
2130 if( !checked_connections.insert( member.get() ).second )
2133 if( member->IsBus() )
2135 connections_to_check.insert( connections_to_check.end(),
2136 member->Members().begin(),
2137 member->Members().end() );
2140 wxString test_name = member->Name(
true );
2144 if( candidate->
m_absorbed || candidate == subgraph )
2160 if( driver == candidate->
m_driver )
2172 &&
pin->GetDefaultNetName( sheet ) == test_name )
2185 if( subgraph->GetNameForDriver( driver ) == test_name )
2198 wxLogTrace(
ConnTrace, wxS(
"%lu (%s) has bus child %lu (%s)" ),
2199 subgraph->m_code, connection->
Name(),
2200 candidate->
m_code, member->Name() );
2202 subgraph->m_bus_neighbors[member].insert( candidate );
2205 else if( ( !connection->
IsBus()
2209 wxLogTrace(
ConnTrace, wxS(
"%lu (%s) absorbs neighbor %lu (%s)" ),
2210 subgraph->m_code, connection->
Name(),
2214 add_connections_to_check( candidate );
2216 subgraph->Absorb( candidate );
2217 invalidated_subgraphs.insert( subgraph );
2227 if( subgraph->m_absorbed )
2230 if( !subgraph->ResolveDrivers() )
2233 if( subgraph->m_driver_connection->IsBus() )
2238 wxLogTrace(
ConnTrace, wxS(
"Re-resolving drivers for %lu (%s)" ),
2239 subgraph->m_code, subgraph->m_driver_connection->Name() );
2258 bool aUnconditional )
2261 wxCHECK_RET(
m_schematic, wxT(
"Connection graph cannot be built without schematic pointer" ) );
2265 for(
const std::shared_ptr<BUS_ALIAS>& alias :
m_schematic->GetAllBusAliases() )
2271 PROF_TIMER sub_graph(
"buildItemSubGraphs" );
2290 PROF_TIMER proc_sub_graph(
"ProcessSubGraphs" );
2294 proc_sub_graph.
Show();
2303 std::vector<CONNECTION_SUBGRAPH*> global_subgraphs;
2305 std::back_inserter( global_subgraphs ),
2308 return !candidate->m_local_driver;
2322 m_driver_subgraphs[ii]->UpdateItemConnections();
2332 if( !subgraph->m_dirty )
2335 wxLogTrace(
ConnTrace, wxS(
"Processing %lu (%s) for propagation" ),
2336 subgraph->m_code, subgraph->m_driver_connection->Name() );
2342 if( !subgraph->m_local_driver && subgraph->m_multiple_drivers )
2344 for(
SCH_ITEM* driver : subgraph->m_drivers )
2346 if( driver == subgraph->m_driver )
2349 const wxString& secondary_name = subgraph->GetNameForDriver( driver );
2351 if( secondary_name == subgraph->m_driver_connection->Name() )
2359 if( candidate == subgraph )
2362 if( !secondary_is_global && candidate->
m_sheet != subgraph->m_sheet )
2369 wxLogTrace(
ConnTrace, wxS(
"Global %lu (%s) promoted to %s" ),
2371 subgraph->m_driver_connection->Name() );
2393 if( subgraph->m_dirty )
2410 wxASSERT_MSG( !subgraph->m_dirty,
2411 wxS(
"Subgraph not processed by propagateToNeighbors!" ) );
2413 if( subgraph->m_bus_parents.size() < 2 )
2418 wxLogTrace(
ConnTrace, wxS(
"%lu (%s) has multiple bus parents" ),
2419 subgraph->m_code, conn->
Name() );
2422 wxCHECK2( conn->
IsNet(),
continue );
2424 for(
const auto& ii : subgraph->m_bus_parents )
2437 wxLogTrace(
ConnTrace, wxS(
"Warning: could not match %s inside %lu (%s)" ),
2442 if( conn->
Name() != match->
Name() )
2444 wxString old_name = match->
Name();
2446 wxLogTrace(
ConnTrace, wxS(
"Updating %lu (%s) member %s to %s" ),
2449 match->
Clone( *conn );
2457 std::vector<CONNECTION_SUBGRAPH*> old_subgraphs = jj->second;
2461 while( old_sg->m_absorbed )
2462 old_sg = old_sg->m_absorbed_by;
2464 wxString old_sg_name = old_sg->m_driver_connection->Name();
2465 old_sg->m_driver_connection->Clone( *conn );
2467 if( old_sg_name != old_sg->m_driver_connection->Name() )
2475 auto updateItemConnectionsTask =
2479 if( !subgraph->m_strong_driver
2480 && subgraph->m_drivers.size() == 1
2481 && subgraph->m_driver->Type() ==
SCH_PIN_T )
2484 wxString
name =
pin->GetDefaultNetName( subgraph->m_sheet,
true );
2486 subgraph->m_driver_connection->ConfigureFromLabel(
name );
2489 subgraph->m_dirty =
false;
2490 subgraph->UpdateItemConnections();
2493 if( subgraph->m_driver_connection->IsBus() )
2498 if( subgraph->m_driver && subgraph->m_driver->Type() ==
SCH_SHEET_PIN_T )
2504 wxString pinText =
pin->GetShownText(
false );
2511 if( label->
GetShownText( &subgraph->m_sheet,
false ) == pinText )
2514 path.push_back( sheet );
2518 if( parent_conn && parent_conn->
IsBus() )
2525 if( subgraph->m_driver_connection->IsBus() )
2536 updateItemConnectionsTask( m_driver_subgraphs[ii] );
2546 subgraph->m_driver_connection->NetCode() };
2552 std::shared_ptr<NET_SETTINGS>& netSettings =
m_schematic->Project().GetProjectFile().m_NetSettings;
2553 std::map<wxString, std::set<wxString>> oldAssignments = netSettings->GetNetclassLabelAssignments();
2554 std::set<wxString> affectedNetclassNetAssignments;
2556 netSettings->ClearNetclassLabelAssignments();
2558 auto dirtySubgraphs =
2559 [&](
const std::vector<CONNECTION_SUBGRAPH*>& subgraphs )
2561 if( aChangedItemHandler )
2565 for(
SCH_ITEM* item : subgraph->m_items )
2566 (*aChangedItemHandler)( item );
2571 auto checkNetclassDrivers =
2572 [&](
const wxString& netName,
const std::vector<CONNECTION_SUBGRAPH*>& subgraphs )
2574 wxCHECK_RET( !subgraphs.empty(), wxS(
"Invalid empty subgraph" ) );
2576 std::set<wxString> netclasses;
2581 for(
SCH_ITEM* item : subgraph->m_items )
2583 for(
const auto& [
name, provider] : subgraph->GetNetclassesForDriver( item ) )
2584 netclasses.insert(
name );
2591 if( subgraph->m_driver_connection->IsBus() )
2593 auto processBusMember = [&,
this](
const SCH_CONNECTION* member )
2595 if( !netclasses.empty() )
2597 netSettings->AppendNetclassLabelAssignment( member->Name(), netclasses );
2602 if( oldAssignments.count( member->Name() ) )
2604 if( oldAssignments[member->Name()] != netclasses )
2606 affectedNetclassNetAssignments.insert( member->Name() );
2609 dirtySubgraphs( ii->second );
2612 else if( !netclasses.empty() )
2614 affectedNetclassNetAssignments.insert( member->Name() );
2617 dirtySubgraphs( ii->second );
2621 for(
const std::shared_ptr<SCH_CONNECTION>& member : subgraph->m_driver_connection->Members() )
2625 if( member->IsBus() )
2627 for(
const std::shared_ptr<SCH_CONNECTION>& nestedMember : member->Members() )
2628 processBusMember( nestedMember.get() );
2632 processBusMember( member.get() );
2639 if( !netclasses.empty() )
2641 netSettings->AppendNetclassLabelAssignment( netName, netclasses );
2644 if( oldAssignments.count( netName ) )
2646 if( oldAssignments[netName] != netclasses )
2648 affectedNetclassNetAssignments.insert( netName );
2649 dirtySubgraphs( subgraphs );
2652 else if( !netclasses.empty() )
2654 affectedNetclassNetAssignments.insert( netName );
2655 dirtySubgraphs( subgraphs );
2661 checkNetclassDrivers( netname, subgraphs );
2663 if( !aUnconditional )
2665 for(
auto& [netname, netclasses] : oldAssignments )
2667 if( netSettings->GetNetclassLabelAssignments().count( netname )
2668 || affectedNetclassNetAssignments.count( netname ) )
2673 netSettings->SetNetclassLabelAssignment( netname, netclasses );
2711 std::vector<std::shared_ptr<SCH_CONNECTION>> connections_to_check( aConnection->
Members() );
2713 for(
unsigned i = 0; i < connections_to_check.size(); i++ )
2715 const std::shared_ptr<SCH_CONNECTION>& member = connections_to_check[i];
2717 if( member->IsBus() )
2719 connections_to_check.insert( connections_to_check.end(),
2720 member->Members().begin(),
2721 member->Members().end() );
2733 std::vector<CONNECTION_SUBGRAPH*> search_list;
2734 std::unordered_set<CONNECTION_SUBGRAPH*> visited;
2735 std::unordered_set<SCH_CONNECTION*> stale_bus_members;
2742 path.push_back(
pin->GetParent() );
2753 || visited.contains( candidate ) )
2762 wxLogTrace(
ConnTrace, wxS(
"%lu: found child %lu (%s)" ), aParent->m_code,
2770 wxASSERT( candidate->
m_graph == aParent->m_graph );
2772 search_list.push_back( candidate );
2792 || visited.contains( candidate )
2798 const KIID& last_parent_uuid = aParent->m_sheet.Last()->m_Uuid;
2803 if(
pin->GetParent()->m_Uuid != last_parent_uuid )
2809 if( pin_path != aParent->m_sheet )
2814 wxLogTrace(
ConnTrace, wxS(
"%lu: found additional parent %lu (%s)" ),
2817 aParent->m_hier_children.insert( candidate );
2818 search_list.push_back( candidate );
2832 std::vector<std::shared_ptr<SCH_CONNECTION>> sortedMembers;
2834 for(
const auto&
kv : aParentGraph->m_bus_neighbors )
2835 sortedMembers.push_back(
kv.first );
2837 std::sort( sortedMembers.begin(), sortedMembers.end(),
2838 [](
const std::shared_ptr<SCH_CONNECTION>& a,
2839 const std::shared_ptr<SCH_CONNECTION>& b )
2841 return a->Name() < b->Name();
2844 for(
const std::shared_ptr<SCH_CONNECTION>& member_conn : sortedMembers )
2846 const auto& kv_it = aParentGraph->m_bus_neighbors.find( member_conn );
2848 if( kv_it == aParentGraph->m_bus_neighbors.end() )
2891 wxLogTrace(
ConnTrace, wxS(
"Could not match bus member %s in %s" ),
2892 member_conn->Name(), parent->
Name() );
2898 wxCHECK2( neighbor_conn,
continue );
2900 wxString neighbor_name = neighbor_conn->
Name();
2903 if( neighbor_name == member->
Name() )
2913 if( neighbor_conn->
Sheet() != parent->
Sheet() )
2924 bool alreadyUpdatedByBusMember =
false;
2926 for(
const auto& m : parent->
Members() )
2928 if( m->Name() == neighbor_name )
2930 alreadyUpdatedByBusMember =
true;
2935 if( alreadyUpdatedByBusMember )
2940 wxCHECK2_MSG( neighbor_conn->
IsNet(),
continue,
2941 wxS(
"\"" ) + neighbor_name + wxS(
"\" is not a net." ) );
2943 wxLogTrace(
ConnTrace, wxS(
"%lu (%s) connected to bus member %s (local %s)" ),
2950 member->
Clone( *neighbor_conn );
2951 stale_bus_members.insert( member );
2955 neighbor_conn->
Clone( *member );
2968 if( neighbor_conn->
Name() != member->
Name() )
2970 member->
Clone( *neighbor_conn );
2971 stale_bus_members.insert( member );
2980 propagate_bus_neighbors( aSubgraph );
2987 wxLogTrace(
ConnTrace, wxS(
"%lu (%s) has both hier ports and pins; deferring processing" ),
2993 wxLogTrace(
ConnTrace, wxS(
"%lu (%s) has no hier pins or ports on sheet %s; marking clean" ),
2999 visited.insert( aSubgraph );
3001 wxLogTrace(
ConnTrace, wxS(
"Propagating %lu (%s) to subsheets" ),
3006 for(
unsigned i = 0; i < search_list.size(); i++ )
3008 auto child = search_list[i];
3010 if( visited.insert( child ).second )
3013 child->m_dirty =
false;
3027 if( subgraph == aSubgraph )
3034 wxString candidateName = subgraph->m_driver_connection->Name();
3035 bool shorterPath = subgraph->m_sheet.size() < bestDriver->
m_sheet.
size();
3036 bool asGoodPath = subgraph->m_sheet.size() <= bestDriver->
m_sheet.
size();
3046 ( !bestIsStrong && candidateStrong ) ||
3047 ( priority > highest && candidateStrong ) ||
3048 ( priority == highest && candidateStrong && shorterPath ) ||
3049 ( ( bestIsStrong == candidateStrong ) && asGoodPath && ( priority == highest ) &&
3050 ( candidateName < bestName ) ) )
3052 bestDriver = subgraph;
3054 bestIsStrong = candidateStrong;
3055 bestName = candidateName;
3060 if( bestDriver != aSubgraph )
3062 wxLogTrace(
ConnTrace, wxS(
"%lu (%s) overridden by new driver %lu (%s)" ),
3071 wxString old_name = subgraph->m_driver_connection->Name();
3073 subgraph->m_driver_connection->Clone( *conn );
3075 if( old_name != conn->
Name() )
3079 propagate_bus_neighbors( subgraph );
3085 if( conn->
IsBus() && !stale_bus_members.empty() )
3087 std::unordered_set<SCH_CONNECTION*> cached_members = stale_bus_members;
3097 wxLogTrace(
ConnTrace, wxS(
"WARNING: failed to match stale member %s in %s." ),
3098 stale_member->Name(), subgraph->m_driver_connection->Name() );
3102 wxLogTrace(
ConnTrace, wxS(
"Updating %lu (%s) member %s to %s" ), subgraph->m_code,
3103 subgraph->m_driver_connection->Name(), member->
LocalName(), stale_member->Name() );
3105 member->
Clone( *stale_member );
3107 propagate_bus_neighbors( subgraph );
3119 std::shared_ptr<SCH_CONNECTION> c = std::shared_ptr<SCH_CONNECTION>(
nullptr );
3121 switch( aItem->
Type() )
3124 if(
static_cast<SCH_PIN*
>( aItem )->IsPower() )
3125 c = std::make_shared<SCH_CONNECTION>( aItem, aSubgraph->
m_sheet );
3132 c = std::make_shared<SCH_CONNECTION>( aItem, aSubgraph->
m_sheet );
3141 c->SetGraph(
this );
3152 if( !aBusConnection->
IsBus() )
3162 for(
const std::shared_ptr<SCH_CONNECTION>& bus_member : aBusConnection->
Members() )
3164 if( bus_member->VectorIndex() == aSearch->
VectorIndex() )
3166 match = bus_member.get();
3174 for(
const std::shared_ptr<SCH_CONNECTION>& c : aBusConnection->
Members() )
3181 for(
const std::shared_ptr<SCH_CONNECTION>& bus_member : c->Members() )
3183 if( bus_member->LocalName() == aSearch->
LocalName() )
3185 match = bus_member.get();
3190 else if( c->LocalName() == aSearch->
LocalName() )
3208 std::vector<CONNECTION_SUBGRAPH*>& vec = it->second;
3209 std::erase( vec, aSubgraph );
3212 wxLogTrace(
ConnTrace, wxS(
"recacheSubgraphName: %s => %s" ), aOldName,
3229 std::vector<const CONNECTION_SUBGRAPH*> ret;
3235 wxASSERT( !subgraph->m_dirty );
3237 if( !subgraph->m_driver )
3243 if( !connection->
IsBus() )
3246 auto labels = subgraph->GetVectorBusLabels();
3248 if( labels.size() > 1 )
3250 bool different =
false;
3253 for(
unsigned i = 1; i < labels.size(); ++i )
3265 wxLogTrace(
ConnTrace, wxS(
"SG %ld (%s) has multiple bus labels" ), subgraph->m_code,
3266 connection->
Name() );
3268 ret.push_back( subgraph );
3289 if( graph == aSubGraph )
3332 wxASSERT( !it->second.empty() );
3334 return it->second[0];
3350const std::vector<CONNECTION_SUBGRAPH*>&
3353 static const std::vector<CONNECTION_SUBGRAPH*> subgraphs;
3366 int error_count = 0;
3368 wxCHECK_MSG(
m_schematic,
true, wxS(
"Null m_schematic in CONNECTION_GRAPH::RunERC" ) );
3374 std::set<SCH_ITEM*> seenDriverInstances;
3379 wxCHECK2( subgraph,
continue );
3383 wxASSERT( !subgraph->m_dirty );
3385 if( subgraph->m_absorbed )
3388 if( seenDriverInstances.count( subgraph->m_driver ) )
3391 if( subgraph->m_driver )
3392 seenDriverInstances.insert( subgraph->m_driver );
3410 subgraph->ResolveDrivers(
false );
3481 wxCHECK( aSubgraph,
false );
3487 if( driver == aSubgraph->
m_driver )
3498 if( primaryName == secondaryName )
3501 wxString msg = wxString::Format(
_(
"Both %s and %s are attached to the same "
3502 "items; %s will be used in the netlist" ),
3503 primaryName, secondaryName, primaryName );
3506 ercItem->SetItems( aSubgraph->
m_driver, driver );
3507 ercItem->SetSheetSpecificPath( aSubgraph->
GetSheet() );
3508 ercItem->SetItemsSheetPaths( aSubgraph->
GetSheet(), aSubgraph->
m_sheet );
3509 ercItem->SetErrorMessage( msg );
3534 switch( item->
Type() )
3539 bus_item = ( !bus_item ) ? item : bus_item;
3541 net_item = ( !net_item ) ? item : net_item;
3555 bus_item = ( !bus_item ) ? item : bus_item;
3557 net_item = ( !net_item ) ? item : net_item;
3567 if( net_item && bus_item )
3570 ercItem->SetSheetSpecificPath( sheet );
3571 ercItem->SetItems( net_item, bus_item );
3574 screen->
Append( marker );
3593 switch( item->
Type() )
3620 if(
test != member && member->Name() ==
test->Name() )
3634 ercItem->SetSheetSpecificPath( sheet );
3635 ercItem->SetItems( label, port );
3638 screen->
Append( marker );
3650 bool conflict =
false;
3666 switch( item->
Type() )
3696 std::set<wxString> test_names;
3708 for(
const auto& sub_member : member->Members() )
3710 if( test_names.count( sub_member->FullLocalName() ) )
3714 else if( test_names.count( member->FullLocalName() ) )
3733 wxString msg = wxString::Format(
_(
"Net %s is graphically connected to bus %s but is not a"
3734 " member of that bus" ),
3738 ercItem->SetSheetSpecificPath( sheet );
3739 ercItem->SetItems( bus_entry, bus_wire );
3740 ercItem->SetErrorMessage( msg );
3743 screen->
Append( marker );
3760 std::set<SCH_PIN*> unique_pins;
3761 std::set<SCH_LABEL_BASE*> unique_labels;
3769 for(
SCH_ITEM* item : aProcessGraph->m_items )
3771 switch( item->
Type() )
3778 if( aProcessGraph == aSubgraph )
3781 if( std::none_of( unique_pins.begin(), unique_pins.end(),
3784 return test_pin->IsStacked( aPin );
3788 unique_pins.insert( test_pin );
3811 process_subgraph( subgraph );
3816 process_subgraph( aSubgraph );
3851 ercItem->SetSheetSpecificPath( sheet );
3852 ercItem->SetItemsSheetPaths( sheet );
3859 pos =
pin->GetPosition();
3868 screen->
Append( marker );
3873 if( unique_pins.empty() && unique_labels.empty() &&
3878 ercItem->SetSheetSpecificPath( sheet );
3879 ercItem->SetItemsSheetPaths( sheet );
3882 screen->
Append( marker );
3889 bool has_other_connections =
false;
3890 std::vector<SCH_PIN*> pins;
3897 switch( item->
Type() )
3904 if( !has_other_connections && !pins.empty()
3907 for(
SCH_PIN* other_pin : pins )
3911 has_other_connections =
true;
3917 pins.emplace_back(
static_cast<SCH_PIN*
>( item ) );
3924 has_other_connections =
true;
3931 pin = pins.empty() ? nullptr : pins[0];
3934 for(
SCH_PIN* test_pin : pins )
3951 ?
pin->GetLibPin()->GetParentSymbol() :
nullptr;
3953 if(
pin && !has_other_connections
3955 && ( !pinLibParent || !pinLibParent->
IsPower() ) )
3957 wxString
name =
pin->Connection( &sheet )->Name();
3958 wxString local_name =
pin->Connection( &sheet )->Name(
true );
3963 has_other_connections =
true;
3968 if(
pin && !has_other_connections
3974 ercItem->SetSheetSpecificPath( sheet );
3975 ercItem->SetItemsSheetPaths( sheet );
3976 ercItem->SetItems(
pin );
3979 screen->
Append( marker );
3987 if( pins.size() > 1 )
3989 for(
SCH_PIN* testPin : pins )
3994 SYMBOL* testLibParent = testPin->GetLibPin()
3998 if( testLibParent && testLibParent->
IsPower()
3999 && testPin->ConnectedItems( sheet ).empty()
4003 ercItem->SetSheetSpecificPath( sheet );
4004 ercItem->SetItemsSheetPaths( sheet );
4005 ercItem->SetItems( testPin );
4008 screen->
Append( marker );
4041 ercItem->SetItems( line );
4042 ercItem->SetSheetSpecificPath( sheet );
4043 ercItem->SetErrorMessage(
_(
"Unconnected wire endpoint" ) );
4065 ercItem->SetItems( entry );
4066 ercItem->SetSheetSpecificPath( sheet );
4067 ercItem->SetErrorMessage(
_(
"Unconnected wire to bus entry" ) );
4084 return err_count > 0;
4094 std::vector<SCH_ITEM*> wires;
4101 wires.emplace_back( item );
4103 wires.emplace_back( item );
4106 if( !wires.empty() )
4111 ercItem->SetSheetSpecificPath( sheet );
4112 ercItem->SetItems( wires[0],
4113 wires.size() > 1 ? wires[1] :
nullptr,
4114 wires.size() > 2 ? wires[2] :
nullptr,
4115 wires.size() > 3 ? wires[3] :
nullptr );
4118 screen->
Append( marker );
4146 size_t pinCount = 0;
4149 std::map<KICAD_T, std::vector<SCH_TEXT*>> label_map;
4155 return std::count_if( aLocSubgraph->m_items.begin(), aLocSubgraph->m_items.end(),
4158 return item->Type() == SCH_PIN_T;
4163 [&](
SCH_TEXT* aText,
int errCode )
4168 ercItem->SetSheetSpecificPath( sheet );
4169 ercItem->SetItems( aText );
4176 pinCount =
hasPins( aSubgraph );
4180 switch( item->
Type() )
4188 label_map[item->
Type()].push_back(
text );
4193 if(
text->IsDangling() )
4207 if( label_map.empty() )
4212 for(
auto& [ connection, subgraphs ] : aSubgraph->
m_bus_parents )
4216 if( busParent->m_no_connect )
4239 wxCHECK_MSG(
m_schematic,
true, wxS(
"Null m_schematic in CONNECTION_GRAPH::ercCheckLabels" ) );
4246 for(
auto& [type, label_vec] : label_map )
4250 size_t allPins = pinCount;
4251 size_t localPins = pinCount;
4252 bool hasLocalHierarchy =
false;
4260 std::set<wxString> uniquePortNames;
4264 if( aSubgraph->
m_hier_pins.size() + uniquePortNames.size() > 1 )
4266 hasLocalHierarchy =
true;
4271 for(
auto& [connection, busParents] : aSubgraph->
m_bus_parents )
4275 if( busParent->m_sheet == sheet
4276 && ( !busParent->m_hier_pins.empty()
4277 || !busParent->m_hier_ports.empty() ) )
4279 hasLocalHierarchy =
true;
4284 if( hasLocalHierarchy )
4295 if( neighbor == aSubgraph )
4301 size_t neighborPins =
hasPins( neighbor );
4302 allPins += neighborPins;
4304 if( neighbor->
m_sheet == sheet )
4306 localPins += neighborPins;
4311 hasLocalHierarchy =
true;
4317 if( allPins == 1 && !has_nc )
4328 || ( type ==
SCH_LABEL_T && localPins == 0 && allPins > 1
4329 && !has_nc && !hasLocalHierarchy ) )
4345 std::map<wxString, std::tuple<int, const SCH_ITEM*, SCH_SHEET_PATH>> labelData;
4352 wxString resolvedLabelText =
4355 if( labelData.find( resolvedLabelText ) == labelData.end() )
4357 labelData[resolvedLabelText] = { 1, item, sheet };
4361 std::get<0>( labelData[resolvedLabelText] ) += 1;
4362 std::get<1>( labelData[resolvedLabelText] ) =
nullptr;
4363 std::get<2>( labelData[resolvedLabelText] ) = sheet;
4368 for(
const auto& label : labelData )
4370 if( std::get<0>( label.second ) == 1 )
4373 const SCH_ITEM* item = std::get<1>( label.second );
4376 ercItem->SetItems( std::get<1>( label.second ) );
4377 ercItem->SetSheetSpecificPath( sheet );
4378 ercItem->SetItemsSheetPaths( sheet );
4393 int error_count = 0;
4405 ercItem->SetSheetSpecificPath( sheet );
4406 ercItem->SetItems(
text );
4409 sheet.LastScreen()->Append( marker );
4429 if( sheet.Last()->IsTopLevelSheet() )
4435 wxCHECK2( label,
continue );
4437 msg.Printf(
_(
"Hierarchical label '%s' in root sheet cannot be connected to non-existent "
4441 ercItem->SetItems( item );
4442 ercItem->SetErrorMessage( msg );
4445 sheet.LastScreen()->Append( marker );
4456 parentSheetPath.
push_back( parentSheet );
4458 std::map<wxString, SCH_SHEET_PIN*> pins;
4459 std::map<wxString, SCH_HIERLABEL*> labels;
4464 pins[
pin->GetShownText( &parentSheetPath,
false ) ] =
pin;
4469 ercItem->SetItems(
pin );
4470 ercItem->SetSheetSpecificPath( sheet );
4471 ercItem->SetItemsSheetPaths( sheet );
4474 sheet.LastScreen()->Append( marker );
4482 std::set<wxString> matchedPins;
4489 wxString labelText = label->
GetShownText( &parentSheetPath,
false );
4491 if( !pins.contains( labelText ) )
4492 labels[ labelText ] = label;
4494 matchedPins.insert( labelText );
4498 for(
const wxString& matched : matchedPins )
4499 pins.erase( matched );
4501 for(
const auto& [
name,
pin] : pins )
4503 msg.Printf(
_(
"Sheet pin %s has no matching hierarchical label inside the sheet" ),
4507 ercItem->SetItems(
pin );
4508 ercItem->SetErrorMessage( msg );
4509 ercItem->SetSheetSpecificPath( sheet );
4510 ercItem->SetItemsSheetPaths( sheet );
4513 sheet.LastScreen()->Append( marker );
4518 for(
const auto& [
name, label] : labels )
4520 msg.Printf(
_(
"Hierarchical label %s has no matching sheet pin in the parent sheet" ),
4524 ercItem->SetItems( label );
4525 ercItem->SetErrorMessage( msg );
4526 ercItem->SetSheetSpecificPath( parentSheetPath );
4527 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)
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.
bool ercCheckLabels(const CONNECTION_SUBGRAPH *aSubgraph)
Check one subgraph for proper connection of labels.
void RemoveItem(SCH_ITEM *aItem)
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::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.
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::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.
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)
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
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
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.
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.
std::unordered_map< SCH_ITEM *, CONNECTION_SUBGRAPH * > m_item_to_subgraph_map
std::set< std::pair< SCH_SHEET_PATH, SCH_ITEM * > > ExtractAffectedItems(const std::set< SCH_ITEM * > &aItems)
For a set of items, this will remove the connected items and their associated data including subgraph...
wxString GetResolvedSubgraphName(const CONNECTION_SUBGRAPH *aSubGraph) const
Return the fully-resolved netname for a given subgraph.
bool ercCheckBusToBusEntryConflicts(const CONNECTION_SUBGRAPH *aSubgraph)
Check one subgraph for conflicting bus entry to bus connections.
std::vector< CONNECTION_SUBGRAPH * > m_driver_subgraphs
Cache of a subset of m_subgraphs.
void ExchangeItem(SCH_ITEM *aOldItem, SCH_ITEM *aNewItem)
Replace all references to #aOldItem with #aNewItem in the graph.
NET_MAP m_net_code_to_subgraphs_map
bool ercCheckFloatingWires(const CONNECTION_SUBGRAPH *aSubgraph)
Check one subgraph for floating wires.
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.
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.
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
bool GetDuplicatePinNumbersAreJumpers() const
std::vector< std::set< wxString > > & JumperPinGroups()
Each jumper pin group is a set of pin numbers that should be treated as internally connected.
A small class to help profiling.
void Show(std::ostream &aStream=std::cerr)
Print the elapsed time (in a suitable unit) to a stream.
void Stop()
Save the time when this function was called, and set the counter stane to stop.
A progress reporter interface for use in multi-threaded environments.
virtual bool KeepRefreshing(bool aWait=false)=0
Update the UI (if any).
virtual void SetCurrentProgress(double aProgress)=0
Set the progress value to aProgress (0..1).
Class for a bus to bus entry.
SCH_ITEM * m_connected_bus_items[2]
Pointer to the bus items (usually bus wires) connected to this bus-bus entry (either or both may be n...
bool IsStartDangling() const
VECTOR2I GetPosition() const override
bool IsEndDangling() const
std::vector< VECTOR2I > GetConnectionPoints() const override
Add all the connection points for this item to aPoints.
Class for a wire to bus entry.
SCH_ITEM * m_connected_bus_item
Pointer to the bus item (usually a bus wire) connected to this bus-wire entry, if it is connected to ...
Each graphical item can have a SCH_CONNECTION describing its logical connection (to a bus or net).
wxString FullLocalName() const
void ConfigureFromLabel(const wxString &aLabel)
Configures the connection given a label.
void SetSubgraphCode(int aCode)
void SetBusCode(int aCode)
void SetName(const wxString &aName)
SCH_SHEET_PATH Sheet() const
CONNECTION_TYPE Type() const
void SetNetCode(int aCode)
SCH_ITEM * m_driver
The SCH_ITEM that drives this connection's net.
bool IsDriver() const
Checks if the SCH_ITEM this connection is attached to can drive connections Drivers can be labels,...
void SetType(CONNECTION_TYPE aType)
wxString LocalName() const
wxString Name(bool aIgnoreSheet=false) const
bool IsSubsetOf(SCH_CONNECTION *aOther) const
Returns true if this connection is contained within aOther (but not the same as aOther)
void SetDriver(SCH_ITEM *aItem)
void Clone(const SCH_CONNECTION &aOther)
Copies connectivity information (but not parent) from another connection.
void SetGraph(CONNECTION_GRAPH *aGraph)
const std::vector< std::shared_ptr< SCH_CONNECTION > > & Members() const
wxString GetCanonicalName() const
Get a non-language-specific name for a field which can be used for storage, variable look-up,...
wxString GetShownText(const SCH_SHEET_PATH *aPath, bool aAllowExtraText, int aDepth=0, const wxString &aVariantName=wxEmptyString) const
Base class for any item which can be embedded within the SCHEMATIC container class,...
void ClearConnectedItems(const SCH_SHEET_PATH &aPath)
Clear all connections to this item.
virtual void RunOnChildren(const std::function< void(SCH_ITEM *)> &aFunction, RECURSE_MODE aMode)
const SYMBOL * GetParentSymbol() const
virtual const wxString & GetCachedDriverName() const
const std::unordered_set< SCH_RULE_AREA * > & GetRuleAreaCache() const
Get the cache of rule areas enclosing this item.
SCH_CONNECTION * InitializeConnection(const SCH_SHEET_PATH &aPath, CONNECTION_GRAPH *aGraph)
Create a new connection object associated with this object.
void AddConnectionTo(const SCH_SHEET_PATH &aPath, SCH_ITEM *aItem)
Add a connection link between this item and another.
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
bool IsEndDangling() const
bool IsGraphicLine() const
Return if the line is a graphic (non electrical line)
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
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.
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, 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
#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.
static const wxChar ConnTrace[]
Flag to enable connectivity tracing.
#define KI_FALLTHROUGH
The KI_FALLTHROUGH macro is to be used when switch statement cases should purposely fallthrough from ...
void remove_duplicates(_Container &__c)
Deletes all duplicate values from __c.
@ PT_NC
not connected (must be left open)
@ PT_NIC
not internally connected (may be connected to anything)
@ PT_POWER_IN
power input (GND, VCC for ICs). Must be connected to a power output.
@ BUS
This item represents a bus vector.
@ NET
This item represents a net.
@ BUS_GROUP
This item represents a bus group.
std::vector< SCH_ITEM * > SCH_ITEM_VEC
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:...
thread_pool & GetKiCadThreadPool()
Get a reference to the current thread pool.
BS::priority_thread_pool thread_pool
Functions to provide common constants and other functions to assist in making a consistent UI.
VECTOR2< int32_t > VECTOR2I