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 );
588 if(
const std::unique_ptr<LIB_SYMBOL>& part = symbol->GetLibSymbolRef() )
589 return part->GetReferenceField().GetText();
591 return wxEmptyString;
594 switch( aDriver->
Type() )
625 std::back_inserter(
m_items ) );
680 wxCHECK2( aOldItem->
Type() == aNewItem->
Type(),
return );
715 wxCHECK2( oldPins.size() == newPins.size(),
return );
717 for(
size_t ii = 0; ii < oldPins.size(); ii++ )
719 exchange( oldPins[ii], newPins[ii] );
730 if( subgraph->m_graph ==
this )
754 std::function<
void(
SCH_ITEM* )>* aChangedItemHandler,
758 PROF_TIMER recalc_time(
"CONNECTION_GRAPH::Recalculate" );
759 monitorTrans.
Start();
764 monitorTrans.
StartSpan(
"updateItemConnectivity",
"" );
765 PROF_TIMER update_items(
"updateItemConnectivity" );
768 std::set<SCH_ITEM*> dirty_items;
770 int count = aSheetList.size() * 2;
775 if( aProgressReporter )
781 std::vector<SCH_ITEM*> items;
784 std::vector<std::pair<SCH_SYMBOL*, int>> symbolsChanged;
786 for(
SCH_ITEM* item : sheet.LastScreen()->Items() )
788 if( item->IsConnectable() && ( aUnconditional || item->IsConnectivityDirty() ) )
790 wxLogTrace(
ConnTrace, wxT(
"Adding item %s to connectivity graph update" ),
791 item->GetTypeDesc() );
792 items.push_back( item );
793 dirty_items.insert( item );
802 if(
pin->IsConnectivityDirty() )
804 dirty_items.insert(
pin );
817 if(
pin->IsConnectivityDirty() )
819 items.push_back(
pin );
820 dirty_items.insert(
pin );
830 if(
pin->IsConnectivityDirty() )
832 items.push_back(
pin );
833 dirty_items.insert(
pin );
846 if( symbol->
GetUnit() != new_unit )
847 symbolsChanged.push_back( { symbol, symbol->
GetUnit() } );
857 if( aProgressReporter )
864 sheet.LastScreen()->TestDanglingEnds( &sheet, aChangedItemHandler );
867 for(
const auto& [ symbol, originalUnit ] : symbolsChanged )
868 symbol->SetUnit( originalUnit );
879 item->SetConnectivityDirty(
false );
886 PROF_TIMER build_graph(
"buildConnectionGraph" );
887 monitorTrans.
StartSpan(
"BuildConnectionGraph",
"" );
906 const std::set<SCH_ITEM*> &aItems )
908 std::set<std::pair<SCH_SHEET_PATH, SCH_ITEM*>> retvals;
909 std::set<CONNECTION_SUBGRAPH*> subgraphs;
914 while( aSubgraph->m_absorbed_by )
917 wxASSERT( aSubgraph->m_graph == aSubgraph->m_absorbed_by->m_graph );
918 aSubgraph = aSubgraph->m_absorbed_by;
922 while( aSubgraph->m_hier_parent )
925 wxASSERT( aSubgraph->m_graph == aSubgraph->m_hier_parent->m_graph );
926 aSubgraph = aSubgraph->m_hier_parent;
930 aSubgraph->getAllConnectedItems( retvals, subgraphs );
933 auto extract_element = [&](
SCH_ITEM* aItem )
939 wxLogTrace(
ConnTrace, wxT(
"Item %s not found in connection graph" ),
940 aItem->GetTypeDesc() );
946 wxLogTrace(
ConnTrace, wxT(
"Item %s in subgraph %ld (%p) has no driver" ),
947 aItem->GetTypeDesc(), item_sg->
m_code, item_sg );
952 if( sg_to_scan.empty() )
954 wxLogTrace(
ConnTrace, wxT(
"Item %s in subgraph %ld with net %s has no neighbors" ),
956 sg_to_scan.push_back( item_sg );
960 wxT(
"Removing all item %s connections from subgraph %ld with net %s: Found "
967 traverse_subgraph( sg );
969 for(
auto& bus_it : sg->m_bus_neighbors )
972 traverse_subgraph( bus_sg );
975 for(
auto& bus_it : sg->m_bus_parents )
978 traverse_subgraph( bus_sg );
992 extract_element(
pin );
999 extract_element(
pin );
1003 extract_element( item );
1009 for(
const auto& [
path, item] : retvals )
1036 wxLogTrace(
ConnTrace, wxT(
"Removing %zu subgraphs" ), aSubgraphs.size() );
1039 std::set<int> codes_to_remove;
1043 std::sort( el.second.begin(), el.second.end() );
1048 for(
auto& it : sg->m_bus_neighbors )
1054 for(
auto test = parents.begin();
test != parents.end(); )
1062 if( parents.empty() )
1067 for(
auto& it : sg->m_bus_parents )
1073 for(
auto test = neighbors.begin();
test != neighbors.end(); )
1081 if( neighbors.empty() )
1102 auto it = std::lower_bound( el.second.begin(), el.second.end(), sg );
1104 while( it != el.second.end() && *it == sg )
1105 it = el.second.erase( it );
1108 auto remove_sg = [sg](
auto it ) ->
bool
1121 if( remove_sg( it ) )
1129 if( remove_sg( it ) )
1138 if( remove_sg( it ) )
1140 codes_to_remove.insert( it->first.Netcode );
1152 if( remove_sg( it ) )
1160 if( it->second == sg )
1171 if( codes_to_remove.contains( it->second ) )
1179 if( codes_to_remove.contains( it->second ) )
1188 sg->m_graph =
nullptr;
1195 std::map<
VECTOR2I, std::vector<SCH_ITEM*>>& aConnectionMap )
1206 aConn->SetName(
name );
1211 std::map<wxString, std::vector<SCH_PIN*>> pinNumberMap;
1217 updatePin(
pin, conn );
1218 aConnectionMap[
pin->GetPosition() ].push_back(
pin );
1219 pinNumberMap[
pin->GetNumber()].emplace_back(
pin );
1222 auto linkPinsInVec =
1223 [&](
const std::vector<SCH_PIN*>& aVec )
1225 for(
size_t i = 0; i < aVec.size(); ++i )
1227 for(
size_t j = i + 1; j < aVec.size(); ++j )
1229 aVec[i]->AddConnectionTo( aSheet, aVec[j] );
1230 aVec[j]->AddConnectionTo( aSheet, aVec[i] );
1239 for(
const auto& [number,
group] : pinNumberMap )
1240 linkPinsInVec(
group );
1245 std::vector<SCH_PIN*> pins;
1247 for(
const wxString& pinNumber :
group )
1250 pins.emplace_back(
pin );
1253 linkPinsInVec( pins );
1276 std::map<
VECTOR2I, std::vector<SCH_ITEM*>>& aConnectionMap )
1281 m_items.emplace_back( aItem );
1284 switch( aItem->
Type() )
1297 if( points.empty() )
1298 points = {
static_cast<SCH_PIN*
>( aItem )->GetPosition() };
1311 for(
const VECTOR2I& point : points )
1312 aConnectionMap[point].push_back( aItem );
1317 const std::vector<SCH_ITEM*>& aItemList )
1319 wxLogTrace( wxT(
"Updating connectivity for sheet %s with %zu items" ),
1321 std::map<VECTOR2I, std::vector<SCH_ITEM*>> connection_map;
1325 std::vector<VECTOR2I> points = item->GetConnectionPoints();
1326 item->ClearConnectedItems( aSheet );
1332 pin->InitializeConnection( aSheet,
this );
1334 pin->ClearConnectedItems( aSheet );
1336 connection_map[
pin->GetTextPos() ].push_back(
pin );
1353 VECTOR2I point = item->GetPosition();
1356 std::vector<SCH_ITEM*> overlapping_items;
1358 std::copy_if( items.begin(), items.end(), std::back_inserter( overlapping_items ),
1361 return test_item->Type() == SCH_LINE_T
1362 && test_item->HitTest( point, -1 );
1367 if( overlapping_items.size() < 2 )
continue;
1369 for(
SCH_ITEM* test_item : overlapping_items )
1370 connection_map[point].push_back( test_item );
1375 for(
auto& [point, connection_vec] : connection_map )
1377 std::sort( connection_vec.begin(), connection_vec.end() );
1383 for(
SCH_ITEM* connected_item : connection_vec )
1397 if( connection_vec.size() == 1 )
1413 if( point == bus_entry->GetPosition() )
1416 bus_entry->m_connected_bus_items[1] = busLine;
1429 for(
SCH_ITEM* test_item : connection_vec )
1431 bool bus_connection_ok =
true;
1433 if( test_item == connected_item )
1439 if( test_item->GetLayer() ==
LAYER_BUS )
1458 if( connected_item->ConnectionPropagatesTo( test_item )
1459 && test_item->ConnectionPropagatesTo( connected_item )
1460 && bus_connection_ok )
1462 connected_item->AddConnectionTo( aSheet, test_item );
1473 if( !bus_entry->m_connected_bus_item )
1479 bus_entry->m_connected_bus_item = bus;
1490 wxCHECK_RET(
m_schematic, wxS(
"Connection graph cannot be built without schematic pointer" ) );
1494 for(
const std::shared_ptr<BUS_ALIAS>& alias :
m_schematic->GetAllBusAliases() )
1503 for(
const auto& [sheet, connection] : item->m_connection_map )
1505 if( connection->SubgraphCode() == 0 )
1514 connection->SetSubgraphCode( subgraph->
m_code );
1517 std::list<SCH_ITEM*> memberlist;
1522 SCH_CONNECTION* conn = aItem->GetOrInitConnection( sheet,
this );
1528 return ( unique && conn && ( conn->
SubgraphCode() == 0 ) );
1531 std::copy_if( item->ConnectedItems( sheet ).begin(),
1532 item->ConnectedItems( sheet ).end(),
1533 std::back_inserter( memberlist ), get_items );
1535 for(
SCH_ITEM* connected_item : memberlist )
1540 SCH_CONNECTION* connected_conn = connected_item->Connection( &sheet );
1542 wxCHECK2( connected_conn,
continue );
1548 subgraph->
AddItem( connected_item );
1549 const SCH_ITEM_VEC& citemset = connected_item->ConnectedItems( sheet );
1556 if( get_items( citem ) )
1557 memberlist.push_back( citem );
1562 for(
SCH_ITEM* connected_item : memberlist )
1576 std::vector<CONNECTION_SUBGRAPH*> dirty_graphs;
1581 return candidate->m_dirty;
1584 wxLogTrace(
ConnTrace, wxT(
"Resolving drivers for %zu subgraphs" ), dirty_graphs.size() );
1586 std::vector<std::future<size_t>> returns( dirty_graphs.size() );
1588 auto update_lambda =
1591 if( !subgraph->m_dirty )
1595 for(
SCH_ITEM* item : subgraph->m_items )
1597 switch( item->
Type() )
1600 subgraph->m_no_connect = item;
1604 subgraph->m_bus_entry = item;
1612 subgraph->m_no_connect = item;
1622 subgraph->ResolveDrivers(
true );
1623 subgraph->m_dirty =
false;
1630 auto results =
tp.submit_loop( 0, dirty_graphs.size(),
1633 update_lambda( dirty_graphs[ii] );
1642 return candidate->m_driver;
1655 wxString full_name = subgraph->m_driver_connection->Name();
1656 wxString
name = subgraph->m_driver_connection->Name(
true );
1665 wxString prefixOnly = full_name.BeforeFirst(
'[' ) + wxT(
"[]" );
1669 subgraph->m_dirty =
true;
1671 if( subgraph->m_strong_driver )
1673 SCH_ITEM* driver = subgraph->m_driver;
1676 switch( driver->
Type() )
1692 if(
pin->IsGlobalPower() )
1696 else if(
pin->IsLocalPower() )
1703 wxLogTrace(
ConnTrace, wxS(
"Unexpected normal pin %s" ),
1713 wxLogTrace(
ConnTrace, wxS(
"Unexpected strong driver %s" ),
1725 std::vector<CONNECTION_SUBGRAPH*> new_subgraphs;
1736 dummy.SetGraph(
this );
1739 wxLogTrace(
ConnTrace, wxS(
"new bus label (%s)" ),
1742 for(
const auto& conn :
dummy.Members() )
1745 if( !conn->IsNet() )
1748 wxString
name = conn->FullLocalName();
1755 auto new_conn = std::make_unique<SCH_CONNECTION>( item, subgraph->m_sheet );
1756 new_conn->SetGraph(
this );
1757 new_conn->SetName(
name );
1760 SCH_CONNECTION* new_conn_ptr = subgraph->StoreImplicitConnection( std::move( new_conn ) );
1763 wxLogTrace(
ConnTrace, wxS(
"SG(%ld), Adding full local name (%s) with sg (%d) on subsheet %s" ),
1764 subgraph->m_code,
name, code, subgraph->m_sheet.PathHumanReadable() );
1777 new_subgraphs.push_back( new_sg );
1782 std::copy( new_subgraphs.begin(), new_subgraphs.end(),
1798 [](
const std::pair<SCH_SHEET_PATH, SCH_PIN*>& a,
1799 const std::pair<SCH_SHEET_PATH, SCH_PIN*>& b )
1801 int pathCmp = a.first.Cmp( b.first );
1806 const SCH_SYMBOL* symA = static_cast<const SCH_SYMBOL*>( a.second->GetParentSymbol() );
1807 const SCH_SYMBOL* symB = static_cast<const SCH_SYMBOL*>( b.second->GetParentSymbol() );
1809 wxString refA = symA ? symA->GetRef( &a.first, false ) : wxString();
1810 wxString refB = symB ? symB->GetRef( &b.first, false ) : wxString();
1812 int refCmp = refA.Cmp( refB );
1817 return a.second->GetNumber().Cmp( b.second->GetNumber() ) < 0;
1820 std::unordered_map<int, CONNECTION_SUBGRAPH*> global_power_pin_subgraphs;
1824 SYMBOL* libParent =
pin->GetLibPin() ?
pin->GetLibPin()->GetParentSymbol() :
nullptr;
1826 if( !
pin->ConnectedItems( sheet ).empty()
1843 connection->
SetName(
pin->GetParentSymbol()->GetValue(
true, &sheet,
false ) );
1852 auto jj = global_power_pin_subgraphs.find( code );
1854 if( jj != global_power_pin_subgraphs.end() )
1856 subgraph = jj->second;
1874 global_power_pin_subgraphs[code] = subgraph;
1891 std::unordered_set<CONNECTION_SUBGRAPH*> invalidated_subgraphs;
1895 if( subgraph->m_absorbed )
1900 wxString
name = connection->
Name();
1903 unsigned suffix = 1;
1905 auto create_new_name =
1909 wxString suffixStr = std::to_wstring( suffix );
1916 wxString prefix = aConn->BusPrefix();
1918 if( prefix.empty() )
1919 prefix = wxT(
"BUS" );
1921 wxString oldName = aConn->Name().AfterFirst(
'{' );
1923 newName << prefix << wxT(
"_" ) << suffixStr << wxT(
"{" ) << oldName;
1925 aConn->ConfigureFromLabel( newName );
1929 newName << aConn->Name() << wxT(
"_" ) << suffixStr;
1930 aConn->SetSuffix( wxString( wxT(
"_" ) ) << suffixStr );
1937 if( !subgraph->m_strong_driver )
1939 std::vector<CONNECTION_SUBGRAPH*> vec_empty;
1940 std::vector<CONNECTION_SUBGRAPH*>* vec = &vec_empty;
1949 wxString prefixOnly =
name.BeforeFirst(
'[' ) + wxT(
"[]" );
1955 if( vec->size() > 1 )
1957 wxString new_name = create_new_name( connection );
1960 new_name = create_new_name( connection );
1962 wxLogTrace(
ConnTrace, wxS(
"%ld (%s) is weakly driven and not unique. Changing to %s." ),
1963 subgraph->m_code,
name, new_name );
1965 std::erase( *vec, subgraph );
1971 else if( subgraph->m_driver )
1983 bool conflict =
false;
1984 wxString global_name = connection->
Name(
true );
1991 std::vector<CONNECTION_SUBGRAPH*>& candidates = kk->second;
1995 if( candidate->m_sheet == sheet )
2002 wxLogTrace(
ConnTrace, wxS(
"%ld (%s) skipped for promotion due to potential conflict" ),
2003 subgraph->m_code,
name );
2009 wxLogTrace(
ConnTrace, wxS(
"%ld (%s) weakly driven by unique sheet pin %s, promoting" ),
2010 subgraph->m_code,
name,
2011 subgraph->m_driver->GetItemDescription( &unitsProvider,
true ) );
2013 subgraph->m_strong_driver =
true;
2020 if( connection->
IsBus() )
2044 subgraph->m_dirty =
true;
2052 if( !subgraph->m_strong_driver )
2059 std::vector<CONNECTION_SUBGRAPH*> candidate_subgraphs;
2062 std::back_inserter( candidate_subgraphs ),
2065 return ( !candidate->m_absorbed &&
2066 candidate->m_strong_driver &&
2067 candidate != subgraph );
2073 std::vector< std::shared_ptr<SCH_CONNECTION> > connections_to_check;
2076 connections_to_check.push_back( std::make_shared<SCH_CONNECTION>( *connection ) );
2078 auto add_connections_to_check =
2081 for(
SCH_ITEM* possible_driver : aSubgraph->m_items )
2083 if( possible_driver == aSubgraph->m_driver )
2090 if( c->Type() != aSubgraph->m_driver_connection->Type() )
2093 if( c->Name(
true ) == aSubgraph->m_driver_connection->Name(
true ) )
2096 connections_to_check.push_back( c );
2097 wxLogTrace(
ConnTrace, wxS(
"%lu (%s): Adding secondary driver %s" ),
2099 aSubgraph->m_driver_connection->Name(
true ),
2108 add_connections_to_check( subgraph );
2110 std::set<SCH_CONNECTION*> checked_connections;
2112 for(
unsigned i = 0; i < connections_to_check.size(); i++ )
2114 auto member = connections_to_check[i];
2117 if( !checked_connections.insert( member.get() ).second )
2120 if( member->IsBus() )
2122 connections_to_check.insert( connections_to_check.end(),
2123 member->Members().begin(),
2124 member->Members().end() );
2127 wxString test_name = member->Name(
true );
2131 if( candidate->
m_absorbed || candidate == subgraph )
2147 if( driver == candidate->
m_driver )
2159 &&
pin->GetDefaultNetName( sheet ) == test_name )
2172 if( subgraph->GetNameForDriver( driver ) == test_name )
2185 wxLogTrace(
ConnTrace, wxS(
"%lu (%s) has bus child %lu (%s)" ),
2186 subgraph->m_code, connection->
Name(),
2187 candidate->
m_code, member->Name() );
2189 subgraph->m_bus_neighbors[member].insert( candidate );
2192 else if( !connection->
IsBus()
2195 wxLogTrace(
ConnTrace, wxS(
"%lu (%s) absorbs neighbor %lu (%s)" ),
2196 subgraph->m_code, connection->
Name(),
2200 add_connections_to_check( candidate );
2202 subgraph->Absorb( candidate );
2203 invalidated_subgraphs.insert( subgraph );
2213 if( subgraph->m_absorbed )
2216 if( !subgraph->ResolveDrivers() )
2219 if( subgraph->m_driver_connection->IsBus() )
2224 wxLogTrace(
ConnTrace, wxS(
"Re-resolving drivers for %lu (%s)" ),
2225 subgraph->m_code, subgraph->m_driver_connection->Name() );
2244 bool aUnconditional )
2247 wxCHECK_RET(
m_schematic, wxT(
"Connection graph cannot be built without schematic pointer" ) );
2251 for(
const std::shared_ptr<BUS_ALIAS>& alias :
m_schematic->GetAllBusAliases() )
2257 PROF_TIMER sub_graph(
"buildItemSubGraphs" );
2276 PROF_TIMER proc_sub_graph(
"ProcessSubGraphs" );
2280 proc_sub_graph.
Show();
2289 std::vector<CONNECTION_SUBGRAPH*> global_subgraphs;
2291 std::back_inserter( global_subgraphs ),
2294 return !candidate->m_local_driver;
2308 m_driver_subgraphs[ii]->UpdateItemConnections();
2318 if( !subgraph->m_dirty )
2321 wxLogTrace(
ConnTrace, wxS(
"Processing %lu (%s) for propagation" ),
2322 subgraph->m_code, subgraph->m_driver_connection->Name() );
2328 if( !subgraph->m_local_driver && subgraph->m_multiple_drivers )
2330 for(
SCH_ITEM* driver : subgraph->m_drivers )
2332 if( driver == subgraph->m_driver )
2335 const wxString& secondary_name = subgraph->GetNameForDriver( driver );
2337 if( secondary_name == subgraph->m_driver_connection->Name() )
2345 if( candidate == subgraph )
2348 if( !secondary_is_global && candidate->
m_sheet != subgraph->m_sheet )
2355 wxLogTrace(
ConnTrace, wxS(
"Global %lu (%s) promoted to %s" ),
2357 subgraph->m_driver_connection->Name() );
2379 if( subgraph->m_dirty )
2396 wxASSERT_MSG( !subgraph->m_dirty,
2397 wxS(
"Subgraph not processed by propagateToNeighbors!" ) );
2399 if( subgraph->m_bus_parents.size() < 2 )
2404 wxLogTrace(
ConnTrace, wxS(
"%lu (%s) has multiple bus parents" ),
2405 subgraph->m_code, conn->
Name() );
2408 wxCHECK2( conn->
IsNet(),
continue );
2410 for(
const auto& ii : subgraph->m_bus_parents )
2423 wxLogTrace(
ConnTrace, wxS(
"Warning: could not match %s inside %lu (%s)" ),
2428 if( conn->
Name() != match->
Name() )
2430 wxString old_name = match->
Name();
2432 wxLogTrace(
ConnTrace, wxS(
"Updating %lu (%s) member %s to %s" ),
2435 match->
Clone( *conn );
2443 std::vector<CONNECTION_SUBGRAPH*> old_subgraphs = jj->second;
2447 while( old_sg->m_absorbed )
2448 old_sg = old_sg->m_absorbed_by;
2450 wxString old_sg_name = old_sg->m_driver_connection->Name();
2451 old_sg->m_driver_connection->Clone( *conn );
2453 if( old_sg_name != old_sg->m_driver_connection->Name() )
2461 auto updateItemConnectionsTask =
2465 if( !subgraph->m_strong_driver
2466 && subgraph->m_drivers.size() == 1
2467 && subgraph->m_driver->Type() ==
SCH_PIN_T )
2470 wxString
name =
pin->GetDefaultNetName( subgraph->m_sheet,
true );
2472 subgraph->m_driver_connection->ConfigureFromLabel(
name );
2475 subgraph->m_dirty =
false;
2476 subgraph->UpdateItemConnections();
2479 if( subgraph->m_driver_connection->IsBus() )
2484 if( subgraph->m_driver && subgraph->m_driver->Type() ==
SCH_SHEET_PIN_T )
2490 wxString pinText =
pin->GetShownText(
false );
2497 if( label->
GetShownText( &subgraph->m_sheet,
false ) == pinText )
2500 path.push_back( sheet );
2504 if( parent_conn && parent_conn->
IsBus() )
2511 if( subgraph->m_driver_connection->IsBus() )
2522 updateItemConnectionsTask( m_driver_subgraphs[ii] );
2532 subgraph->m_driver_connection->NetCode() };
2538 std::shared_ptr<NET_SETTINGS>& netSettings =
m_schematic->Project().GetProjectFile().m_NetSettings;
2539 std::map<wxString, std::set<wxString>> oldAssignments = netSettings->GetNetclassLabelAssignments();
2540 std::set<wxString> affectedNetclassNetAssignments;
2542 netSettings->ClearNetclassLabelAssignments();
2544 auto dirtySubgraphs =
2545 [&](
const std::vector<CONNECTION_SUBGRAPH*>& subgraphs )
2547 if( aChangedItemHandler )
2551 for(
SCH_ITEM* item : subgraph->m_items )
2552 (*aChangedItemHandler)( item );
2557 auto checkNetclassDrivers =
2558 [&](
const wxString& netName,
const std::vector<CONNECTION_SUBGRAPH*>& subgraphs )
2560 wxCHECK_RET( !subgraphs.empty(), wxS(
"Invalid empty subgraph" ) );
2562 std::set<wxString> netclasses;
2567 for(
SCH_ITEM* item : subgraph->m_items )
2569 for(
const auto& [
name, provider] : subgraph->GetNetclassesForDriver( item ) )
2570 netclasses.insert(
name );
2577 if( subgraph->m_driver_connection->IsBus() )
2579 auto processBusMember = [&,
this](
const SCH_CONNECTION* member )
2581 if( !netclasses.empty() )
2583 netSettings->AppendNetclassLabelAssignment( member->Name(), netclasses );
2588 if( oldAssignments.count( member->Name() ) )
2590 if( oldAssignments[member->Name()] != netclasses )
2592 affectedNetclassNetAssignments.insert( member->Name() );
2595 dirtySubgraphs( ii->second );
2598 else if( !netclasses.empty() )
2600 affectedNetclassNetAssignments.insert( member->Name() );
2603 dirtySubgraphs( ii->second );
2607 for(
const std::shared_ptr<SCH_CONNECTION>& member : subgraph->m_driver_connection->Members() )
2611 if( member->IsBus() )
2613 for(
const std::shared_ptr<SCH_CONNECTION>& nestedMember : member->Members() )
2614 processBusMember( nestedMember.get() );
2618 processBusMember( member.get() );
2625 if( !netclasses.empty() )
2627 netSettings->AppendNetclassLabelAssignment( netName, netclasses );
2630 if( oldAssignments.count( netName ) )
2632 if( oldAssignments[netName] != netclasses )
2634 affectedNetclassNetAssignments.insert( netName );
2635 dirtySubgraphs( subgraphs );
2638 else if( !netclasses.empty() )
2640 affectedNetclassNetAssignments.insert( netName );
2641 dirtySubgraphs( subgraphs );
2647 checkNetclassDrivers( netname, subgraphs );
2649 if( !aUnconditional )
2651 for(
auto& [netname, netclasses] : oldAssignments )
2653 if( netSettings->GetNetclassLabelAssignments().count( netname )
2654 || affectedNetclassNetAssignments.count( netname ) )
2659 netSettings->SetNetclassLabelAssignment( netname, netclasses );
2697 std::vector<std::shared_ptr<SCH_CONNECTION>> connections_to_check( aConnection->
Members() );
2699 for(
unsigned i = 0; i < connections_to_check.size(); i++ )
2701 const std::shared_ptr<SCH_CONNECTION>& member = connections_to_check[i];
2703 if( member->IsBus() )
2705 connections_to_check.insert( connections_to_check.end(),
2706 member->Members().begin(),
2707 member->Members().end() );
2719 std::vector<CONNECTION_SUBGRAPH*> search_list;
2720 std::unordered_set<CONNECTION_SUBGRAPH*> visited;
2721 std::unordered_set<SCH_CONNECTION*> stale_bus_members;
2728 path.push_back(
pin->GetParent() );
2739 || visited.contains( candidate ) )
2748 wxLogTrace(
ConnTrace, wxS(
"%lu: found child %lu (%s)" ), aParent->m_code,
2756 wxASSERT( candidate->
m_graph == aParent->m_graph );
2758 search_list.push_back( candidate );
2778 || visited.contains( candidate )
2784 const KIID& last_parent_uuid = aParent->m_sheet.Last()->m_Uuid;
2789 if(
pin->GetParent()->m_Uuid != last_parent_uuid )
2795 if( pin_path != aParent->m_sheet )
2800 wxLogTrace(
ConnTrace, wxS(
"%lu: found additional parent %lu (%s)" ),
2803 aParent->m_hier_children.insert( candidate );
2804 search_list.push_back( candidate );
2818 std::vector<std::shared_ptr<SCH_CONNECTION>> sortedMembers;
2820 for(
const auto&
kv : aParentGraph->m_bus_neighbors )
2821 sortedMembers.push_back(
kv.first );
2823 std::sort( sortedMembers.begin(), sortedMembers.end(),
2824 [](
const std::shared_ptr<SCH_CONNECTION>& a,
2825 const std::shared_ptr<SCH_CONNECTION>& b )
2827 return a->Name() < b->Name();
2830 for(
const std::shared_ptr<SCH_CONNECTION>& member_conn : sortedMembers )
2832 const auto& kv_it = aParentGraph->m_bus_neighbors.find( member_conn );
2834 if( kv_it == aParentGraph->m_bus_neighbors.end() )
2877 wxLogTrace(
ConnTrace, wxS(
"Could not match bus member %s in %s" ),
2878 member_conn->Name(), parent->
Name() );
2884 wxCHECK2( neighbor_conn,
continue );
2886 wxString neighbor_name = neighbor_conn->
Name();
2889 if( neighbor_name == member->
Name() )
2899 if( neighbor_conn->
Sheet() != parent->
Sheet() )
2915 wxCHECK2_MSG( neighbor_conn->
IsNet(),
continue,
2916 wxS(
"\"" ) + neighbor_name + wxS(
"\" is not a net." ) );
2918 wxLogTrace(
ConnTrace, wxS(
"%lu (%s) connected to bus member %s (local %s)" ),
2925 member->
Clone( *neighbor_conn );
2926 stale_bus_members.insert( member );
2930 neighbor_conn->
Clone( *member );
2943 if( neighbor_conn->
Name() != member->
Name() )
2945 member->
Clone( *neighbor_conn );
2946 stale_bus_members.insert( member );
2955 propagate_bus_neighbors( aSubgraph );
2962 wxLogTrace(
ConnTrace, wxS(
"%lu (%s) has both hier ports and pins; deferring processing" ),
2968 wxLogTrace(
ConnTrace, wxS(
"%lu (%s) has no hier pins or ports on sheet %s; marking clean" ),
2974 visited.insert( aSubgraph );
2976 wxLogTrace(
ConnTrace, wxS(
"Propagating %lu (%s) to subsheets" ),
2981 for(
unsigned i = 0; i < search_list.size(); i++ )
2983 auto child = search_list[i];
2985 if( visited.insert( child ).second )
2988 child->m_dirty =
false;
3002 if( subgraph == aSubgraph )
3009 wxString candidateName = subgraph->m_driver_connection->Name();
3010 bool shorterPath = subgraph->m_sheet.size() < bestDriver->
m_sheet.
size();
3011 bool asGoodPath = subgraph->m_sheet.size() <= bestDriver->
m_sheet.
size();
3021 ( !bestIsStrong && candidateStrong ) ||
3022 ( priority > highest && candidateStrong ) ||
3023 ( priority == highest && candidateStrong && shorterPath ) ||
3024 ( ( bestIsStrong == candidateStrong ) && asGoodPath && ( priority == highest ) &&
3025 ( candidateName < bestName ) ) )
3027 bestDriver = subgraph;
3029 bestIsStrong = candidateStrong;
3030 bestName = candidateName;
3035 if( bestDriver != aSubgraph )
3037 wxLogTrace(
ConnTrace, wxS(
"%lu (%s) overridden by new driver %lu (%s)" ),
3046 wxString old_name = subgraph->m_driver_connection->Name();
3048 subgraph->m_driver_connection->Clone( *conn );
3050 if( old_name != conn->
Name() )
3054 propagate_bus_neighbors( subgraph );
3060 if( conn->
IsBus() && !stale_bus_members.empty() )
3062 std::unordered_set<SCH_CONNECTION*> cached_members = stale_bus_members;
3072 wxLogTrace(
ConnTrace, wxS(
"WARNING: failed to match stale member %s in %s." ),
3073 stale_member->Name(), subgraph->m_driver_connection->Name() );
3077 wxLogTrace(
ConnTrace, wxS(
"Updating %lu (%s) member %s to %s" ), subgraph->m_code,
3078 subgraph->m_driver_connection->Name(), member->
LocalName(), stale_member->Name() );
3080 member->
Clone( *stale_member );
3082 propagate_bus_neighbors( subgraph );
3094 std::shared_ptr<SCH_CONNECTION> c = std::shared_ptr<SCH_CONNECTION>(
nullptr );
3096 switch( aItem->
Type() )
3099 if(
static_cast<SCH_PIN*
>( aItem )->IsPower() )
3100 c = std::make_shared<SCH_CONNECTION>( aItem, aSubgraph->
m_sheet );
3107 c = std::make_shared<SCH_CONNECTION>( aItem, aSubgraph->
m_sheet );
3116 c->SetGraph(
this );
3128 wxASSERT( aBusConnection->
IsBus() );
3137 for(
const std::shared_ptr<SCH_CONNECTION>& bus_member : aBusConnection->
Members() )
3139 if( bus_member->VectorIndex() == aSearch->
VectorIndex() )
3141 match = bus_member.get();
3149 for(
const std::shared_ptr<SCH_CONNECTION>& c : aBusConnection->
Members() )
3156 for(
const std::shared_ptr<SCH_CONNECTION>& bus_member : c->Members() )
3158 if( bus_member->LocalName() == aSearch->
LocalName() )
3160 match = bus_member.get();
3165 else if( c->LocalName() == aSearch->
LocalName() )
3183 std::vector<CONNECTION_SUBGRAPH*>& vec = it->second;
3184 std::erase( vec, aSubgraph );
3187 wxLogTrace(
ConnTrace, wxS(
"recacheSubgraphName: %s => %s" ), aOldName,
3204 std::vector<const CONNECTION_SUBGRAPH*> ret;
3210 wxASSERT( !subgraph->m_dirty );
3212 if( !subgraph->m_driver )
3218 if( !connection->
IsBus() )
3221 auto labels = subgraph->GetVectorBusLabels();
3223 if( labels.size() > 1 )
3225 bool different =
false;
3228 for(
unsigned i = 1; i < labels.size(); ++i )
3240 wxLogTrace(
ConnTrace, wxS(
"SG %ld (%s) has multiple bus labels" ), subgraph->m_code,
3241 connection->
Name() );
3243 ret.push_back( subgraph );
3264 if( graph == aSubGraph )
3307 wxASSERT( !it->second.empty() );
3309 return it->second[0];
3325const std::vector<CONNECTION_SUBGRAPH*>&
3328 static const std::vector<CONNECTION_SUBGRAPH*> subgraphs;
3341 int error_count = 0;
3343 wxCHECK_MSG(
m_schematic,
true, wxS(
"Null m_schematic in CONNECTION_GRAPH::RunERC" ) );
3349 std::set<SCH_ITEM*> seenDriverInstances;
3354 wxCHECK2( subgraph,
continue );
3358 wxASSERT( !subgraph->m_dirty );
3360 if( subgraph->m_absorbed )
3363 if( seenDriverInstances.count( subgraph->m_driver ) )
3366 if( subgraph->m_driver )
3367 seenDriverInstances.insert( subgraph->m_driver );
3385 subgraph->ResolveDrivers(
false );
3456 wxCHECK( aSubgraph,
false );
3462 if( driver == aSubgraph->
m_driver )
3473 if( primaryName == secondaryName )
3476 wxString msg = wxString::Format(
_(
"Both %s and %s are attached to the same "
3477 "items; %s will be used in the netlist" ),
3478 primaryName, secondaryName, primaryName );
3481 ercItem->SetItems( aSubgraph->
m_driver, driver );
3482 ercItem->SetSheetSpecificPath( aSubgraph->
GetSheet() );
3483 ercItem->SetItemsSheetPaths( aSubgraph->
GetSheet(), aSubgraph->
m_sheet );
3484 ercItem->SetErrorMessage( msg );
3509 switch( item->
Type() )
3514 bus_item = ( !bus_item ) ? item : bus_item;
3516 net_item = ( !net_item ) ? item : net_item;
3530 bus_item = ( !bus_item ) ? item : bus_item;
3532 net_item = ( !net_item ) ? item : net_item;
3542 if( net_item && bus_item )
3545 ercItem->SetSheetSpecificPath( sheet );
3546 ercItem->SetItems( net_item, bus_item );
3549 screen->
Append( marker );
3568 switch( item->
Type() )
3595 if(
test != member && member->Name() ==
test->Name() )
3609 ercItem->SetSheetSpecificPath( sheet );
3610 ercItem->SetItems( label, port );
3613 screen->
Append( marker );
3625 bool conflict =
false;
3641 switch( item->
Type() )
3671 std::set<wxString> test_names;
3683 for(
const auto& sub_member : member->Members() )
3685 if( test_names.count( sub_member->FullLocalName() ) )
3689 else if( test_names.count( member->FullLocalName() ) )
3708 wxString msg = wxString::Format(
_(
"Net %s is graphically connected to bus %s but is not a"
3709 " member of that bus" ),
3713 ercItem->SetSheetSpecificPath( sheet );
3714 ercItem->SetItems( bus_entry, bus_wire );
3715 ercItem->SetErrorMessage( msg );
3718 screen->
Append( marker );
3735 std::set<SCH_PIN*> unique_pins;
3736 std::set<SCH_LABEL_BASE*> unique_labels;
3744 for(
SCH_ITEM* item : aProcessGraph->m_items )
3746 switch( item->
Type() )
3753 if( aProcessGraph == aSubgraph )
3756 if( std::none_of( unique_pins.begin(), unique_pins.end(),
3759 return test_pin->IsStacked( aPin );
3763 unique_pins.insert( test_pin );
3786 process_subgraph( subgraph );
3791 process_subgraph( aSubgraph );
3826 ercItem->SetSheetSpecificPath( sheet );
3827 ercItem->SetItemsSheetPaths( sheet );
3834 pos =
pin->GetPosition();
3843 screen->
Append( marker );
3848 if( unique_pins.empty() && unique_labels.empty() &&
3853 ercItem->SetSheetSpecificPath( sheet );
3854 ercItem->SetItemsSheetPaths( sheet );
3857 screen->
Append( marker );
3864 bool has_other_connections =
false;
3865 std::vector<SCH_PIN*> pins;
3872 switch( item->
Type() )
3879 if( !has_other_connections && !pins.empty()
3882 for(
SCH_PIN* other_pin : pins )
3886 has_other_connections =
true;
3892 pins.emplace_back(
static_cast<SCH_PIN*
>( item ) );
3899 has_other_connections =
true;
3906 pin = pins.empty() ? nullptr : pins[0];
3909 for(
SCH_PIN* test_pin : pins )
3926 ?
pin->GetLibPin()->GetParentSymbol() :
nullptr;
3928 if(
pin && !has_other_connections
3930 && ( !pinLibParent || !pinLibParent->
IsPower() ) )
3932 wxString
name =
pin->Connection( &sheet )->Name();
3933 wxString local_name =
pin->Connection( &sheet )->Name(
true );
3938 has_other_connections =
true;
3943 if(
pin && !has_other_connections
3949 ercItem->SetSheetSpecificPath( sheet );
3950 ercItem->SetItemsSheetPaths( sheet );
3951 ercItem->SetItems(
pin );
3954 screen->
Append( marker );
3962 if( pins.size() > 1 )
3964 for(
SCH_PIN* testPin : pins )
3969 SYMBOL* testLibParent = testPin->GetLibPin()
3973 if( testLibParent && testLibParent->
IsPower()
3974 && testPin->ConnectedItems( sheet ).empty()
3978 ercItem->SetSheetSpecificPath( sheet );
3979 ercItem->SetItemsSheetPaths( sheet );
3980 ercItem->SetItems( testPin );
3983 screen->
Append( marker );
4016 ercItem->SetItems( line );
4017 ercItem->SetSheetSpecificPath( sheet );
4018 ercItem->SetErrorMessage(
_(
"Unconnected wire endpoint" ) );
4040 ercItem->SetItems( entry );
4041 ercItem->SetSheetSpecificPath( sheet );
4042 ercItem->SetErrorMessage(
_(
"Unconnected wire to bus entry" ) );
4059 return err_count > 0;
4069 std::vector<SCH_ITEM*> wires;
4076 wires.emplace_back( item );
4078 wires.emplace_back( item );
4081 if( !wires.empty() )
4086 ercItem->SetSheetSpecificPath( sheet );
4087 ercItem->SetItems( wires[0],
4088 wires.size() > 1 ? wires[1] :
nullptr,
4089 wires.size() > 2 ? wires[2] :
nullptr,
4090 wires.size() > 3 ? wires[3] :
nullptr );
4093 screen->
Append( marker );
4121 size_t pinCount = 0;
4124 std::map<KICAD_T, std::vector<SCH_TEXT*>> label_map;
4130 return std::count_if( aLocSubgraph->m_items.begin(), aLocSubgraph->m_items.end(),
4133 return item->Type() == SCH_PIN_T;
4138 [&](
SCH_TEXT* aText,
int errCode )
4143 ercItem->SetSheetSpecificPath( sheet );
4144 ercItem->SetItems( aText );
4151 pinCount =
hasPins( aSubgraph );
4155 switch( item->
Type() )
4163 label_map[item->
Type()].push_back(
text );
4168 if(
text->IsDangling() )
4182 if( label_map.empty() )
4187 for(
auto& [ connection, subgraphs ] : aSubgraph->
m_bus_parents )
4191 if( busParent->m_no_connect )
4214 wxCHECK_MSG(
m_schematic,
true, wxS(
"Null m_schematic in CONNECTION_GRAPH::ercCheckLabels" ) );
4221 for(
auto& [type, label_vec] : label_map )
4225 size_t allPins = pinCount;
4226 size_t localPins = pinCount;
4240 if( neighbor == aSubgraph )
4246 size_t neighborPins =
hasPins( neighbor );
4247 allPins += neighborPins;
4249 if( neighbor->
m_sheet == sheet )
4250 localPins += neighborPins;
4254 if( allPins == 1 && !has_nc )
4262 if( allPins == 0 || ( isBusMemberLabel && localPins == 0 && !has_nc ) )
4278 std::map<wxString, std::tuple<int, const SCH_ITEM*, SCH_SHEET_PATH>> labelData;
4285 wxString resolvedLabelText =
4288 if( labelData.find( resolvedLabelText ) == labelData.end() )
4290 labelData[resolvedLabelText] = { 1, item, sheet };
4294 std::get<0>( labelData[resolvedLabelText] ) += 1;
4295 std::get<1>( labelData[resolvedLabelText] ) =
nullptr;
4296 std::get<2>( labelData[resolvedLabelText] ) = sheet;
4301 for(
const auto& label : labelData )
4303 if( std::get<0>( label.second ) == 1 )
4306 const SCH_ITEM* item = std::get<1>( label.second );
4309 ercItem->SetItems( std::get<1>( label.second ) );
4310 ercItem->SetSheetSpecificPath( sheet );
4311 ercItem->SetItemsSheetPaths( sheet );
4326 int error_count = 0;
4338 ercItem->SetSheetSpecificPath( sheet );
4339 ercItem->SetItems(
text );
4342 sheet.LastScreen()->Append( marker );
4362 if( sheet.Last()->IsTopLevelSheet() )
4368 wxCHECK2( label,
continue );
4370 msg.Printf(
_(
"Hierarchical label '%s' in root sheet cannot be connected to non-existent "
4374 ercItem->SetItems( item );
4375 ercItem->SetErrorMessage( msg );
4378 sheet.LastScreen()->Append( marker );
4389 parentSheetPath.
push_back( parentSheet );
4391 std::map<wxString, SCH_SHEET_PIN*> pins;
4392 std::map<wxString, SCH_HIERLABEL*> labels;
4397 pins[
pin->GetShownText( &parentSheetPath,
false ) ] =
pin;
4402 ercItem->SetItems(
pin );
4403 ercItem->SetSheetSpecificPath( sheet );
4404 ercItem->SetItemsSheetPaths( sheet );
4407 sheet.LastScreen()->Append( marker );
4415 std::set<wxString> matchedPins;
4422 wxString labelText = label->
GetShownText( &parentSheetPath,
false );
4424 if( !pins.contains( labelText ) )
4425 labels[ labelText ] = label;
4427 matchedPins.insert( labelText );
4431 for(
const wxString& matched : matchedPins )
4432 pins.erase( matched );
4434 for(
const auto& [
name,
pin] : pins )
4436 msg.Printf(
_(
"Sheet pin %s has no matching hierarchical label inside the sheet" ),
4440 ercItem->SetItems(
pin );
4441 ercItem->SetErrorMessage( msg );
4442 ercItem->SetSheetSpecificPath( sheet );
4443 ercItem->SetItemsSheetPaths( sheet );
4446 sheet.LastScreen()->Append( marker );
4451 for(
const auto& [
name, label] : labels )
4453 msg.Printf(
_(
"Hierarchical label %s has no matching sheet pin in the parent sheet" ),
4457 ercItem->SetItems( label );
4458 ercItem->SetErrorMessage( msg );
4459 ercItem->SetSheetSpecificPath( parentSheetPath );
4460 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.
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