26#include <unordered_map>
106 if( old_conn && new_conn )
108 new_conn->
Clone( *old_conn );
157 if( aPower && !bPower )
159 else if( bPower && !aPower )
165 bool a_lowQualityName = a_name.Contains(
"-Pad" );
166 bool b_lowQualityName = b_name.Contains(
"-Pad" );
168 if( a_lowQualityName && !b_lowQualityName )
170 else if( b_lowQualityName && !a_lowQualityName )
173 return a_name < b_name;
177 std::set<
SCH_ITEM*,
decltype( candidate_cmp )> candidates( candidate_cmp );
178 std::set<SCH_ITEM*> strong_drivers;
202 strong_drivers.insert( item );
204 if( item_priority > highest_priority )
207 candidates.insert( item );
208 highest_priority = item_priority;
210 else if( !candidates.empty() && ( item_priority == highest_priority ) )
212 candidates.insert( item );
222 if( !candidates.empty() )
224 if( candidates.size() > 1 )
235 if( p->
GetShape() == LABEL_FLAG_SHAPE::L_OUTPUT )
248 if( strong_drivers.size() > 1 )
255 m_drivers.insert( strong_drivers.begin(), strong_drivers.end() );
277 std::set<CONNECTION_SUBGRAPH*>& aSubgraphs )
289 if( aSubgraphs.insert( sg ).second ==
false )
295 aItems.emplace(
m_sheet, item );
309#ifdef CONNECTIVITY_DEBUG
310 wxASSERT_MSG(
false, wxS(
"Tried to get the net name of an item with no connection" ) );
322 std::vector<SCH_ITEM*> labels;
326 switch( item->Type() )
334 if( type == CONNECTION_TYPE::BUS || type == CONNECTION_TYPE::BUS_GROUP )
335 labels.push_back( item );
351 std::vector<SCH_ITEM*> labels;
355 switch( item->Type() )
363 if( label_conn->
Type() == CONNECTION_TYPE::BUS )
364 labels.push_back( item );
380 switch( aItem->
Type() )
387 return pin->GetDefaultNetName(
m_sheet, forceNoConnect );
414 wxFAIL_MSG( wxS(
"Unhandled item type in GetNameForDriver" ) );
415 return wxEmptyString;
434const std::vector<std::pair<wxString, SCH_ITEM*>>
437 std::vector<std::pair<wxString, SCH_ITEM*>> foundNetclasses;
439 const std::unordered_set<SCH_RULE_AREA*>& ruleAreaCache = aItem->
GetRuleAreaCache();
444 const std::vector<std::pair<wxString, SCH_ITEM*>> ruleNetclasses =
445 ruleArea->GetResolvedNetclasses();
447 if( ruleNetclasses.size() > 0 )
451 foundNetclasses.insert( foundNetclasses.end(), ruleNetclasses.begin(),
452 ruleNetclasses.end() );
456 foundNetclasses.push_back( ruleNetclasses[0] );
457 return foundNetclasses;
468 SCH_FIELD* field = static_cast<SCH_FIELD*>( aChild );
470 if( field->GetCanonicalName() == wxT(
"Netclass" ) )
472 wxString netclass = field->GetText();
474 if( netclass != wxEmptyString )
475 foundNetclasses.push_back( { field->GetText(), aItem } );
484 return foundNetclasses;
510 child->m_absorbed_by =
this;
513 set_absorbed_by( subchild );
521 set_absorbed_by( aOther );
571 switch( aDriver->
Type() )
585 || sym->
GetLibSymbolRef()->GetReferenceField().GetText().StartsWith(
'#' ) )
599 std::back_inserter(
m_items ) );
656 wxCHECK2( aOldItem->
Type() == aNewItem->
Type(),
return );
691 wxCHECK2( oldPins.size() == newPins.size(),
return );
693 for(
size_t ii = 0; ii < oldPins.size(); ii++ )
695 exchange( oldPins[ii], newPins[ii] );
706 if( subgraph->m_graph ==
this )
730 std::function<
void(
SCH_ITEM* )>* aChangedItemHandler )
732 PROF_TIMER recalc_time(
"CONNECTION_GRAPH::Recalculate" );
737 PROF_TIMER update_items(
"updateItemConnectivity" );
740 std::set<SCH_ITEM*> dirty_items;
744 std::vector<SCH_ITEM*> items;
747 std::vector<std::pair<SCH_SYMBOL*, int>> symbolsChanged;
749 for(
SCH_ITEM* item : sheet.LastScreen()->Items() )
751 if( item->IsConnectable() && ( aUnconditional || item->IsConnectivityDirty() ) )
753 wxLogTrace(
ConnTrace, wxT(
"Adding item %s to connectivity graph update" ),
754 item->GetTypeDesc() );
755 items.push_back( item );
756 dirty_items.insert( item );
766 if(
pin->IsConnectivityDirty() )
768 items.push_back(
pin );
769 dirty_items.insert(
pin );
779 if(
pin->IsConnectivityDirty() )
781 items.push_back(
pin );
782 dirty_items.insert(
pin );
795 if( symbol->
GetUnit() != new_unit )
796 symbolsChanged.push_back( { symbol, symbol->
GetUnit() } );
798 symbol->SetUnit( new_unit );
807 sheet.LastScreen()->TestDanglingEnds( &sheet, aChangedItemHandler );
810 for(
const auto& [ symbol, originalUnit ] : symbolsChanged )
811 symbol->SetUnit( originalUnit );
816 m_schematic->CurrentSheet().LastScreen()->TestDanglingEnds( &m_schematic->CurrentSheet(),
817 aChangedItemHandler );
820 item->SetConnectivityDirty(
false );
825 PROF_TIMER build_graph(
"buildConnectionGraph" );
827 buildConnectionGraph( aChangedItemHandler, aUnconditional );
840 const std::set<SCH_ITEM*> &aItems )
842 std::set<std::pair<SCH_SHEET_PATH, SCH_ITEM*>> retvals;
843 std::set<CONNECTION_SUBGRAPH*> subgraphs;
848 while( aSubgraph->m_absorbed_by )
850 wxASSERT( aSubgraph->m_graph == aSubgraph->m_absorbed_by->m_graph );
851 aSubgraph = aSubgraph->m_absorbed_by;
855 while( aSubgraph->m_hier_parent )
857 wxASSERT( aSubgraph->m_graph == aSubgraph->m_hier_parent->m_graph );
858 aSubgraph = aSubgraph->m_hier_parent;
862 aSubgraph->getAllConnectedItems( retvals, subgraphs );
865 auto extract_element = [&](
SCH_ITEM* aItem )
871 wxLogTrace(
ConnTrace, wxT(
"Item %s not found in connection graph" ), aItem->GetTypeDesc() );
876 wxLogTrace(
ConnTrace, wxT(
"Item %s in subgraph %ld (%p) has no driver" ),
877 aItem->GetTypeDesc(), item_sg->
m_code, item_sg );
882 if( sg_to_scan.empty() )
884 wxLogTrace(
ConnTrace, wxT(
"Item %s in subgraph %ld with net %s has no neighbors" ),
886 sg_to_scan.push_back( item_sg );
890 wxT(
"Removing all item %s connections from subgraph %ld with net %s: Found "
898 traverse_subgraph( sg );
900 for(
auto& bus_it : sg->m_bus_neighbors )
903 traverse_subgraph( bus_sg );
906 for(
auto& bus_it : sg->m_bus_parents )
909 traverse_subgraph( bus_sg );
923 extract_element(
pin );
930 extract_element(
pin );
934 extract_element( item );
964 wxLogTrace(
ConnTrace, wxT(
"Removing %zu subgraphs" ), aSubgraphs.size() );
967 std::set<int> codes_to_remove;
971 std::sort( el.second.begin(), el.second.end() );
976 for(
auto& it : sg->m_bus_neighbors )
982 for(
auto test = parents.begin();
test != parents.end(); )
990 if( parents.empty() )
995 for(
auto& it : sg->m_bus_parents )
1001 for(
auto test = neighbors.begin();
test != neighbors.end(); )
1009 if( neighbors.empty() )
1030 auto it = std::lower_bound( el.second.begin(), el.second.end(), sg );
1032 while( it != el.second.end() && *it == sg )
1033 it = el.second.erase( it );
1036 auto remove_sg = [sg](
auto it ) ->
bool
1049 if( remove_sg( it ) )
1057 if( remove_sg( it ) )
1066 if( remove_sg( it ) )
1068 codes_to_remove.insert( it->first.Netcode );
1078 if( remove_sg( it ) )
1086 if( it->second == sg )
1097 if( codes_to_remove.contains( it->second ) )
1105 if( codes_to_remove.contains( it->second ) )
1114 sg->m_graph =
nullptr;
1121 const std::vector<SCH_ITEM*>& aItemList )
1123 wxLogTrace( wxT(
"Updating connectivity for sheet %s with %zu items" ),
1125 std::map<VECTOR2I, std::vector<SCH_ITEM*>> connection_map;
1129 aConn->SetType( CONNECTION_TYPE::NET );
1138 aConn->SetName(
name );
1145 std::vector<VECTOR2I> points = item->GetConnectionPoints();
1146 item->ClearConnectedItems( aSheet );
1152 pin->InitializeConnection( aSheet,
this );
1154 pin->ClearConnectedItems( aSheet );
1156 connection_map[
pin->GetTextPos() ].push_back(
pin );
1168 updatePin(
pin, conn );
1169 connection_map[
pin->GetPosition() ].push_back(
pin );
1175 SCH_CONNECTION* conn = item->InitializeConnection( aSheet,
this );
1178 switch( item->Type() )
1182 CONNECTION_TYPE::NET );
1186 conn->
SetType( CONNECTION_TYPE::BUS );
1194 if( points.empty() )
1195 points = {
static_cast<SCH_PIN*
>( item )->GetPosition() };
1197 updatePin(
static_cast<SCH_PIN*
>( item ), conn );
1201 conn->
SetType( CONNECTION_TYPE::NET );
1211 for(
const VECTOR2I& point : points )
1212 connection_map[ point ].push_back( item );
1216 for(
const auto& it : connection_map )
1218 std::vector<SCH_ITEM*> connection_vec = it.second;
1219 std::sort( connection_vec.begin(), connection_vec.end() );
1225 std::mutex update_mutex;
1227 auto update_lambda = [&](
SCH_ITEM* connected_item ) ->
size_t
1241 if( connection_vec.size() == 1 )
1254 if( connection_vec.size() < 2 )
1260 if( it.first == bus_entry->GetPosition() )
1263 bus_entry->m_connected_bus_items[1] = busLine;
1265 std::lock_guard<std::mutex> lock( update_mutex );
1278 for(
SCH_ITEM* test_item : connection_vec )
1280 bool bus_connection_ok =
true;
1282 if( test_item == connected_item )
1288 if( test_item->GetLayer() ==
LAYER_BUS )
1307 if( connected_item->ConnectionPropagatesTo( test_item ) &&
1308 test_item->ConnectionPropagatesTo( connected_item ) &&
1311 connected_item->AddConnectionTo( aSheet, test_item );
1322 if( !bus_entry->m_connected_bus_item )
1328 bus_entry->m_connected_bus_item = bus;
1337 tp.push_loop( connection_vec.size(),
1338 [&](
const int a,
const int b)
1340 for( int ii = a; ii < b; ++ii )
1341 update_lambda( connection_vec[ii] );
1343 tp.wait_for_tasks();
1351 wxCHECK_RET(
m_schematic, wxS(
"Connection graph cannot be built without schematic pointer" ) );
1355 for(
unsigned i = 0; i < all_sheets.size(); i++ )
1357 for(
const std::shared_ptr<BUS_ALIAS>& alias : all_sheets[i].LastScreen()->GetBusAliases() )
1364 for(
const auto& it : item->m_connection_map )
1381 std::list<SCH_ITEM*> memberlist;
1386 SCH_CONNECTION* conn = aItem->GetOrInitConnection( sheet,
this );
1387 bool unique = !( aItem->GetFlags() &
CANDIDATE );
1392 return ( unique && conn && ( conn->
SubgraphCode() == 0 ) );
1395 std::copy_if( item->ConnectedItems( sheet ).begin(),
1396 item->ConnectedItems( sheet ).end(),
1397 std::back_inserter( memberlist ), get_items );
1399 for(
SCH_ITEM* connected_item : memberlist )
1404 SCH_CONNECTION* connected_conn = connected_item->Connection( &sheet );
1406 wxASSERT( connected_conn );
1412 subgraph->
AddItem( connected_item );
1413 const SCH_ITEM_VEC& citemset = connected_item->ConnectedItems( sheet );
1420 if( get_items( citem ) )
1421 memberlist.push_back( citem );
1426 for(
SCH_ITEM* connected_item : memberlist )
1427 connected_item->ClearFlags(
CANDIDATE );
1440 std::vector<CONNECTION_SUBGRAPH*> dirty_graphs;
1445 return candidate->m_dirty;
1448 wxLogTrace(
ConnTrace, wxT(
"Resolving drivers for %zu subgraphs" ), dirty_graphs.size() );
1450 std::vector<std::future<size_t>> returns( dirty_graphs.size() );
1454 if( !subgraph->m_dirty )
1458 for(
SCH_ITEM* item : subgraph->m_items )
1460 switch( item->
Type() )
1463 subgraph->m_no_connect = item;
1467 subgraph->m_bus_entry = item;
1474 if(
pin->GetType() == ELECTRICAL_PINTYPE::PT_NC )
1475 subgraph->m_no_connect = item;
1485 subgraph->ResolveDrivers(
true );
1486 subgraph->m_dirty =
false;
1493 tp.push_loop( dirty_graphs.size(),
1494 [&](
const int a,
const int b)
1496 for( int ii = a; ii < b; ++ii )
1497 update_lambda( dirty_graphs[ii] );
1499 tp.wait_for_tasks();
1506 return candidate->m_driver;
1519 wxString full_name = subgraph->m_driver_connection->Name();
1520 wxString
name = subgraph->m_driver_connection->Name(
true );
1527 if( subgraph->m_driver_connection->Type() == CONNECTION_TYPE::BUS )
1529 wxString prefixOnly = full_name.BeforeFirst(
'[' ) + wxT(
"[]" );
1533 subgraph->m_dirty =
true;
1535 if( subgraph->m_strong_driver )
1537 SCH_ITEM* driver = subgraph->m_driver;
1540 switch( driver->
Type() )
1556 wxASSERT(
pin->IsGlobalPower() );
1564 wxLogTrace(
ConnTrace, wxS(
"Unexpected strong driver %s" ),
1576 std::vector<CONNECTION_SUBGRAPH*> new_subgraphs;
1587 dummy.SetGraph(
this );
1592 for(
const auto& conn :
dummy.Members() )
1594 wxString
name = conn->FullLocalName();
1604 new_conn->
SetType( CONNECTION_TYPE::NET );
1605 subgraph->StoreImplicitConnection( new_conn );
1608 wxLogTrace(
ConnTrace, wxS(
"SG(%ld), Adding full local name (%s) with sg (%d) "
1610 subgraph->m_code,
name, code, subgraph->m_sheet.PathHumanReadable() );
1623 new_subgraphs.push_back( new_sg );
1628 std::copy( new_subgraphs.begin(), new_subgraphs.end(),
1639 std::unordered_map<int, CONNECTION_SUBGRAPH*> global_power_pin_subgraphs;
1646 if( !
pin->ConnectedItems( sheet ).empty() && !
pin->GetLibPin()->GetParentSymbol()->IsPower() )
1661 if(
pin->GetLibPin()->GetParentSymbol()->IsPower() )
1662 connection->
SetName(
pin->GetParentSymbol()->GetValue(
true, &sheet,
false ) );
1671 auto jj = global_power_pin_subgraphs.find( code );
1673 if( jj != global_power_pin_subgraphs.end() )
1675 subgraph = jj->second;
1693 global_power_pin_subgraphs[code] = subgraph;
1710 std::unordered_set<CONNECTION_SUBGRAPH*> invalidated_subgraphs;
1714 if( subgraph->m_absorbed )
1719 wxString
name = connection->
Name();
1722 unsigned suffix = 1;
1724 auto create_new_name =
1728 wxString suffixStr = std::to_wstring( suffix );
1733 if( aConn->Type() == CONNECTION_TYPE::BUS_GROUP )
1735 wxString prefix = aConn->BusPrefix();
1737 if( prefix.empty() )
1738 prefix = wxT(
"BUS" );
1740 wxString oldName = aConn->Name().AfterFirst(
'{' );
1742 newName << prefix << wxT(
"_" ) << suffixStr << wxT(
"{" ) << oldName;
1744 aConn->ConfigureFromLabel( newName );
1748 newName << aConn->Name() << wxT(
"_" ) << suffixStr;
1749 aConn->SetSuffix( wxString( wxT(
"_" ) ) << suffixStr );
1756 if( !subgraph->m_strong_driver )
1758 std::vector<CONNECTION_SUBGRAPH*> vec_empty;
1759 std::vector<CONNECTION_SUBGRAPH*>* vec = &vec_empty;
1766 if( vec->size() <= 1 && subgraph->m_driver_connection->Type() == CONNECTION_TYPE::BUS )
1768 wxString prefixOnly =
name.BeforeFirst(
'[' ) + wxT(
"[]" );
1774 if( vec->size() > 1 )
1776 wxString new_name = create_new_name( connection );
1779 new_name = create_new_name( connection );
1782 wxS(
"%ld (%s) is weakly driven and not unique. Changing to %s." ),
1783 subgraph->m_code,
name, new_name );
1791 else if( subgraph->m_driver )
1803 bool conflict =
false;
1804 wxString global_name = connection->
Name(
true );
1811 std::vector<CONNECTION_SUBGRAPH*>& candidates = kk->second;
1815 if( candidate->m_sheet == sheet )
1823 wxS(
"%ld (%s) skipped for promotion due to potential "
1825 subgraph->m_code,
name );
1832 wxS(
"%ld (%s) weakly driven by unique sheet pin %s, "
1834 subgraph->m_code,
name,
1835 subgraph->m_driver->GetItemDescription( &unitsProvider ) );
1837 subgraph->m_strong_driver =
true;
1844 if( connection->
IsBus() )
1868 subgraph->m_dirty =
true;
1876 if( !subgraph->m_strong_driver )
1883 std::vector<CONNECTION_SUBGRAPH*> candidate_subgraphs;
1886 std::back_inserter( candidate_subgraphs ),
1889 return ( !candidate->m_absorbed &&
1890 candidate->m_strong_driver &&
1891 candidate != subgraph );
1897 std::vector< std::shared_ptr<SCH_CONNECTION> > connections_to_check;
1900 connections_to_check.push_back( std::make_shared<SCH_CONNECTION>( *connection ) );
1902 auto add_connections_to_check =
1905 for(
SCH_ITEM* possible_driver : aSubgraph->m_items )
1907 if( possible_driver == aSubgraph->m_driver )
1914 if( c->Type() != aSubgraph->m_driver_connection->Type() )
1917 if( c->Name(
true ) == aSubgraph->m_driver_connection->Name(
true ) )
1920 connections_to_check.push_back( c );
1922 wxS(
"%lu (%s): Adding secondary driver %s" ),
1924 aSubgraph->m_driver_connection->Name(
true ),
1933 add_connections_to_check( subgraph );
1935 std::set<SCH_CONNECTION*> checked_connections;
1937 for(
unsigned i = 0; i < connections_to_check.size(); i++ )
1939 auto member = connections_to_check[i];
1942 if( !checked_connections.insert( member.get() ).second )
1945 if( member->IsBus() )
1947 connections_to_check.insert( connections_to_check.end(),
1948 member->Members().begin(),
1949 member->Members().end() );
1952 wxString test_name = member->Name(
true );
1956 if( candidate->
m_absorbed || candidate == subgraph )
1972 if( driver == candidate->
m_driver )
1983 if(
pin->IsGlobalPower()
1984 &&
pin->GetDefaultNetName( sheet ) == test_name )
1996 if( subgraph->GetNameForDriver( driver ) == test_name )
2009 wxLogTrace(
ConnTrace, wxS(
"%lu (%s) has bus child %lu (%s)" ),
2010 subgraph->m_code, connection->
Name(),
2011 candidate->
m_code, member->Name() );
2013 subgraph->m_bus_neighbors[member].insert( candidate );
2018 wxLogTrace(
ConnTrace, wxS(
"%lu (%s) absorbs neighbor %lu (%s)" ),
2019 subgraph->m_code, connection->
Name(),
2023 add_connections_to_check( candidate );
2025 subgraph->Absorb( candidate );
2026 invalidated_subgraphs.insert( subgraph );
2036 if( subgraph->m_absorbed )
2039 if( !subgraph->ResolveDrivers() )
2042 if( subgraph->m_driver_connection->IsBus() )
2047 wxLogTrace(
ConnTrace, wxS(
"Re-resolving drivers for %lu (%s)" ), subgraph->m_code,
2048 subgraph->m_driver_connection->Name() );
2069 wxCHECK_RET(
m_schematic, wxT(
"Connection graph cannot be built without schematic pointer" ) );
2073 for(
unsigned i = 0; i < all_sheets.size(); i++ )
2075 for(
const std::shared_ptr<BUS_ALIAS>& alias : all_sheets[i].LastScreen()->GetBusAliases() )
2079 PROF_TIMER sub_graph(
"buildItemSubGraphs" );
2099 PROF_TIMER proc_sub_graph(
"ProcessSubGraphs" );
2103 proc_sub_graph.
Show();
2112 std::vector<CONNECTION_SUBGRAPH*> global_subgraphs;
2114 std::back_inserter( global_subgraphs ),
2117 return !candidate->m_local_driver;
2129 [&](
const int a,
const int b)
2131 for( int ii = a; ii < b; ++ii )
2132 m_driver_subgraphs[ii]->UpdateItemConnections();
2134 tp.wait_for_tasks();
2141 if( !subgraph->m_dirty )
2144 wxLogTrace(
ConnTrace, wxS(
"Processing %lu (%s) for propagation" ), subgraph->m_code,
2145 subgraph->m_driver_connection->Name() );
2151 if( !subgraph->m_local_driver && subgraph->m_multiple_drivers )
2153 for(
SCH_ITEM* driver : subgraph->m_drivers )
2155 if( driver == subgraph->m_driver )
2158 const wxString& secondary_name = subgraph->GetNameForDriver( driver );
2160 if( secondary_name == subgraph->m_driver_connection->Name() )
2168 if( candidate == subgraph )
2171 if( !secondary_is_global && candidate->
m_sheet != subgraph->m_sheet )
2176 if( conn->
Name() == secondary_name )
2178 wxLogTrace(
ConnTrace, wxS(
"Global %lu (%s) promoted to %s" ),
2180 subgraph->m_driver_connection->Name() );
2182 conn->
Clone( *subgraph->m_driver_connection );
2201 if( subgraph->m_dirty )
2217 wxASSERT_MSG( !subgraph->m_dirty,
2218 wxS(
"Subgraph not processed by propagateToNeighbors!" ) );
2220 if( subgraph->m_bus_parents.size() < 2 )
2225 wxLogTrace(
ConnTrace, wxS(
"%lu (%s) has multiple bus parents" ),
2226 subgraph->m_code, conn->
Name() );
2228 wxASSERT( conn->
IsNet() );
2230 for(
const auto& ii : subgraph->m_bus_parents )
2243 wxLogTrace(
ConnTrace, wxS(
"Warning: could not match %s inside %lu (%s)" ),
2248 if( conn->
Name() != match->
Name() )
2250 wxString old_name = match->
Name();
2252 wxLogTrace(
ConnTrace, wxS(
"Updating %lu (%s) member %s to %s" ),
2254 old_name, conn->
Name() );
2256 match->
Clone( *conn );
2275 auto updateItemConnectionsTask =
2279 if( !subgraph->m_strong_driver && subgraph->m_drivers.size() == 1 &&
2280 subgraph->m_driver->Type() ==
SCH_PIN_T )
2283 wxString
name =
pin->GetDefaultNetName( subgraph->m_sheet,
true );
2285 subgraph->m_driver_connection->ConfigureFromLabel(
name );
2288 subgraph->m_dirty =
false;
2289 subgraph->UpdateItemConnections();
2292 if( subgraph->m_driver_connection->IsBus() )
2297 if( subgraph->m_driver && subgraph->m_driver->Type() ==
SCH_SHEET_PIN_T )
2303 wxString pinText =
pin->GetText();
2310 if( label->
GetText() == pinText )
2313 path.push_back( sheet );
2317 if( parent_conn && parent_conn->
IsBus() )
2318 subgraph->m_driver_connection->
SetType( CONNECTION_TYPE::BUS );
2324 if( subgraph->m_driver_connection->IsBus() )
2333 [&](
const int a,
const int b)
2335 for(
int ii = a; ii < b; ++ii )
2338 tp.wait_for_tasks();
2346 subgraph->m_driver_connection->NetCode() };
2353 std::map<wxString, wxString> oldAssignments = netSettings->m_NetClassLabelAssignments;
2355 netSettings->m_NetClassLabelAssignments.clear();
2357 auto dirtySubgraphs =
2358 [&](
const std::vector<CONNECTION_SUBGRAPH*>& subgraphs )
2360 if( aChangedItemHandler )
2364 for(
SCH_ITEM* item : subgraph->m_items )
2365 (*aChangedItemHandler)( item );
2370 auto checkNetclassDrivers =
2371 [&](
const std::vector<CONNECTION_SUBGRAPH*>& subgraphs )
2376 wxCHECK_RET( !subgraphs.empty(), wxS(
"Invalid empty subgraph" ) );
2380 for(
SCH_ITEM* item : subgraph->m_items )
2382 const std::vector<std::pair<wxString, SCH_ITEM*>> netclassesWithProviders =
2383 subgraph->GetNetclassesForDriver( item,
false );
2385 if( netclassesWithProviders.size() > 0 )
2387 netclass = netclassesWithProviders[0].first;
2392 if( !netclass.IsEmpty() )
2394 driverSubgraph = subgraph;
2399 if( !driverSubgraph )
2400 driverSubgraph = subgraphs.front();
2402 const wxString netname = driverSubgraph->
GetNetName();
2408 netSettings->m_NetClassLabelAssignments[ member->Name() ] = netclass;
2413 dirtySubgraphs( ii->second );
2417 netSettings->m_NetClassLabelAssignments[ netname ] = netclass;
2419 if( oldAssignments[ netname ] != netclass )
2420 dirtySubgraphs( subgraphs );
2424 checkNetclassDrivers( subgraphs );
2426 if( !aUnconditional )
2428 for(
auto& [ netname, netclass ] : oldAssignments )
2430 if( netSettings->m_NetClassLabelAssignments.count( netname ) )
2433 netSettings->m_NetClassLabelAssignments[ netname ] = netclass;
2471 std::vector<std::shared_ptr<SCH_CONNECTION>> connections_to_check( aConnection->
Members() );
2473 for(
unsigned i = 0; i < connections_to_check.size(); i++ )
2475 const std::shared_ptr<SCH_CONNECTION>& member = connections_to_check[i];
2477 if( member->IsBus() )
2479 connections_to_check.insert( connections_to_check.end(),
2480 member->Members().begin(),
2481 member->Members().end() );
2493 std::vector<CONNECTION_SUBGRAPH*> search_list;
2494 std::unordered_set<CONNECTION_SUBGRAPH*> visited;
2495 std::unordered_set<SCH_CONNECTION*> stale_bus_members;
2502 path.push_back(
pin->GetParent() );
2513 || visited.contains( candidate ) )
2522 wxLogTrace(
ConnTrace, wxS(
"%lu: found child %lu (%s)" ), aParent->m_code,
2528 wxASSERT( candidate->
m_graph == aParent->m_graph );
2530 search_list.push_back( candidate );
2550 || visited.contains( candidate )
2556 const KIID& last_parent_uuid = aParent->m_sheet.Last()->m_Uuid;
2561 if(
pin->GetParent()->m_Uuid != last_parent_uuid )
2567 if( pin_path != aParent->m_sheet )
2572 wxLogTrace(
ConnTrace, wxS(
"%lu: found additional parent %lu (%s)" ),
2573 aParent->m_code, candidate->
m_code,
2576 aParent->m_hier_children.insert( candidate );
2577 search_list.push_back( candidate );
2587 for(
const auto&
kv : aParentGraph->m_bus_neighbors )
2629 wxLogTrace(
ConnTrace, wxS(
"Could not match bus member %s in %s" ),
2630 kv.first->Name(), parent->
Name() );
2635 auto neighbor_name = neighbor_conn->
Name();
2638 if( neighbor_name == member->
Name() )
2642 if( neighbor_conn->Sheet() != neighbor->
m_sheet )
2646 wxASSERT( neighbor_conn->IsNet() );
2648 wxLogTrace(
ConnTrace, wxS(
"%lu (%s) connected to bus member %s (local %s)" ),
2655 member->
Clone( *neighbor_conn );
2656 stale_bus_members.insert( member );
2660 neighbor_conn->Clone( *member );
2674 propagate_bus_neighbors( aSubgraph );
2681 wxLogTrace(
ConnTrace, wxS(
"%lu (%s) has both hier ports and pins; deferring processing" ),
2688 wxS(
"%lu (%s) has no hier pins or ports on sheet %s; marking clean" ),
2694 visited.insert( aSubgraph );
2696 wxLogTrace(
ConnTrace, wxS(
"Propagating %lu (%s) to subsheets" ),
2701 for(
unsigned i = 0; i < search_list.size(); i++ )
2703 auto child = search_list[i];
2705 if( visited.insert( child ).second )
2708 child->m_dirty =
false;
2723 if( subgraph == aSubgraph )
2730 wxString candidateName = subgraph->m_driver_connection->Name();
2731 bool shorterPath = subgraph->m_sheet.size() < bestDriver->
m_sheet.
size();
2732 bool asGoodPath = subgraph->m_sheet.size() <= bestDriver->
m_sheet.
size();
2742 ( !bestIsStrong && candidateStrong ) ||
2743 ( priority > highest && candidateStrong ) ||
2744 ( priority == highest && candidateStrong && shorterPath ) ||
2745 ( ( bestIsStrong == candidateStrong ) && asGoodPath && ( priority == highest ) &&
2746 ( candidateName < bestName ) ) )
2748 bestDriver = subgraph;
2750 bestIsStrong = candidateStrong;
2751 bestName = candidateName;
2756 if( bestDriver != aSubgraph )
2758 wxLogTrace(
ConnTrace, wxS(
"%lu (%s) overridden by new driver %lu (%s)" ),
2767 wxString old_name = subgraph->m_driver_connection->
Name();
2769 subgraph->m_driver_connection->Clone( *conn );
2771 if( old_name != conn->
Name() )
2775 propagate_bus_neighbors( subgraph );
2781 if( conn->
IsBus() && !stale_bus_members.empty() )
2783 std::unordered_set<SCH_CONNECTION*> cached_members = stale_bus_members;
2794 wxLogTrace(
ConnTrace, wxS(
"WARNING: failed to match stale member %s in %s." ),
2795 stale_member->Name(), subgraph->m_driver_connection->Name() );
2799 wxLogTrace(
ConnTrace, wxS(
"Updating %lu (%s) member %s to %s" ), subgraph->m_code,
2800 subgraph->m_driver_connection->Name(), member->
LocalName(),
2801 stale_member->Name() );
2803 member->
Clone( *stale_member );
2805 propagate_bus_neighbors( subgraph );
2817 std::shared_ptr<SCH_CONNECTION> c = std::shared_ptr<SCH_CONNECTION>(
nullptr );
2819 switch( aItem->
Type() )
2825 if(
pin->IsGlobalPower() )
2826 c = std::make_shared<SCH_CONNECTION>( aItem, aSubgraph->
m_sheet );
2835 c = std::make_shared<SCH_CONNECTION>( aItem, aSubgraph->
m_sheet );
2845 c->SetGraph(
this );
2856 wxASSERT( aBusConnection->
IsBus() );
2860 if( aBusConnection->
Type() == CONNECTION_TYPE::BUS )
2865 for(
const std::shared_ptr<SCH_CONNECTION>& bus_member : aBusConnection->
Members() )
2867 if( bus_member->VectorIndex() == aSearch->
VectorIndex() )
2869 match = bus_member.get();
2877 for(
const std::shared_ptr<SCH_CONNECTION>& c : aBusConnection->
Members() )
2882 if( c->Type() == CONNECTION_TYPE::BUS )
2884 for(
const std::shared_ptr<SCH_CONNECTION>& bus_member : c->Members() )
2886 if( bus_member->LocalName() == aSearch->
LocalName() )
2888 match = bus_member.get();
2893 else if( c->LocalName() == aSearch->
LocalName() )
2906 const wxString& aOldName )
2912 std::vector<CONNECTION_SUBGRAPH*>& vec = it->second;
2916 wxLogTrace(
ConnTrace, wxS(
"recacheSubgraphName: %s => %s" ), aOldName,
2933 std::vector<const CONNECTION_SUBGRAPH*> ret;
2938 wxASSERT( !subgraph->m_dirty );
2940 if( !subgraph->m_driver )
2946 if( !connection->
IsBus() )
2949 auto labels = subgraph->GetVectorBusLabels();
2951 if( labels.size() > 1 )
2953 bool different =
false;
2954 wxString first =
static_cast<SCH_TEXT*
>( labels.at( 0 ) )->GetShownText( sheet,
false );
2956 for(
unsigned i = 1; i < labels.size(); ++i )
2968 wxLogTrace(
ConnTrace, wxS(
"SG %ld (%s) has multiple bus labels" ), subgraph->m_code,
2969 connection->
Name() );
2971 ret.push_back( subgraph );
2992 if( graph == aSubGraph )
3033 wxASSERT( !it->second.empty() );
3035 return it->second[0];
3051const std::vector<CONNECTION_SUBGRAPH*>
3054 std::vector<CONNECTION_SUBGRAPH*> subgraphs;
3067 int error_count = 0;
3069 wxCHECK_MSG(
m_schematic,
true, wxS(
"Null m_schematic in CONNECTION_GRAPH::RunERC" ) );
3075 std::set<SCH_ITEM*> seenDriverInstances;
3080 wxCHECK2( subgraph,
continue );
3083 wxASSERT( !subgraph->m_dirty );
3085 if( subgraph->m_absorbed )
3088 if( seenDriverInstances.count( subgraph->m_driver ) )
3091 if( subgraph->m_driver )
3092 seenDriverInstances.insert( subgraph->m_driver );
3110 subgraph->ResolveDrivers(
false );
3179 wxCHECK( aSubgraph,
false );
3185 if( driver == aSubgraph->
m_driver )
3197 if( primaryName == secondaryName )
3200 wxString msg = wxString::Format(
_(
"Both %s and %s are attached to the same "
3201 "items; %s will be used in the netlist" ),
3202 primaryName, secondaryName, primaryName );
3205 ercItem->SetItems( aSubgraph->
m_driver, driver );
3206 ercItem->SetSheetSpecificPath( aSubgraph->
GetSheet() );
3207 ercItem->SetItemsSheetPaths( aSubgraph->
GetSheet(), aSubgraph->
m_sheet );
3208 ercItem->SetErrorMessage( msg );
3224 wxString firstNetclass;
3225 SCH_ITEM* firstNetclassDriver =
nullptr;
3227 bool conflictFound =
false;
3231 for(
SCH_ITEM* item : subgraph->m_items )
3233 const std::vector<std::pair<wxString, SCH_ITEM*>> netclassesWithProvider =
3234 subgraph->GetNetclassesForDriver( item,
true );
3236 if( netclassesWithProvider.size() == 0 )
3239 auto checkNetclass = [&](
const std::pair<wxString, SCH_ITEM*>& netclass )
3241 if( netclass.first != firstNetclass )
3243 if( !firstNetclassDriver )
3245 firstNetclass = netclass.first;
3246 firstNetclassDriver = netclass.second;
3247 firstNetclassDriverSheet = &subgraph->
GetSheet();
3251 conflictFound =
true;
3253 std::shared_ptr<ERC_ITEM> ercItem =
3255 ercItem->SetItems( firstNetclassDriver, netclass.second );
3256 ercItem->SetSheetSpecificPath( subgraph->GetSheet() );
3257 ercItem->SetItemsSheetPaths( *firstNetclassDriverSheet,
3261 new SCH_MARKER( ercItem, netclass.second->GetPosition() );
3262 subgraph->m_sheet.LastScreen()->Append( marker );
3267 for(
const std::pair<wxString, SCH_ITEM*>& netclass : netclassesWithProvider )
3268 checkNetclass( netclass );
3272 return conflictFound;
3287 switch( item->
Type() )
3292 bus_item = ( !bus_item ) ? item : bus_item;
3294 net_item = ( !net_item ) ? item : net_item;
3309 bus_item = ( !bus_item ) ? item : bus_item;
3311 net_item = ( !net_item ) ? item : net_item;
3321 if( net_item && bus_item )
3324 ercItem->SetSheetSpecificPath( sheet );
3325 ercItem->SetItems( net_item, bus_item );
3328 screen->
Append( marker );
3347 switch( item->
Type() )
3378 if(
test != member && member->Name() ==
test->Name() )
3392 ercItem->SetSheetSpecificPath( sheet );
3393 ercItem->SetItems( label, port );
3396 screen->
Append( marker );
3408 bool conflict =
false;
3424 switch( item->
Type() )
3454 std::set<wxString> test_names;
3464 if( member->Type() == CONNECTION_TYPE::BUS )
3466 for(
const auto& sub_member : member->Members() )
3468 if( test_names.count( sub_member->FullLocalName() ) )
3472 else if( test_names.count( member->FullLocalName() ) )
3491 wxString msg = wxString::Format(
_(
"Net %s is graphically connected to bus %s but is not a"
3492 " member of that bus" ),
3496 ercItem->SetSheetSpecificPath( sheet );
3497 ercItem->SetItems( bus_entry, bus_wire );
3498 ercItem->SetErrorMessage( msg );
3501 screen->
Append( marker );
3518 std::set<SCH_PIN*> unique_pins;
3519 std::set<SCH_LABEL_BASE*> unique_labels;
3527 for(
SCH_ITEM* item : aProcessGraph->m_items )
3529 switch( item->
Type() )
3536 if( aProcessGraph == aSubgraph )
3539 if( std::none_of( unique_pins.begin(), unique_pins.end(),
3546 unique_pins.insert( test_pin );
3569 process_subgraph( subgraph );
3574 process_subgraph( aSubgraph );
3599 ercItem->SetSheetSpecificPath( sheet );
3600 ercItem->SetItemsSheetPaths( sheet );
3607 pos =
pin->GetPosition();
3616 screen->
Append( marker );
3621 if( unique_pins.empty() && unique_labels.empty() &&
3626 ercItem->SetSheetSpecificPath( sheet );
3627 ercItem->SetItemsSheetPaths( sheet );
3630 screen->
Append( marker );
3637 bool has_other_connections =
false;
3638 std::vector<SCH_PIN*> pins;
3645 switch( item->
Type() )
3654 for(
SCH_PIN* other_pin : pins )
3658 has_other_connections =
true;
3664 pins.emplace_back(
static_cast<SCH_PIN*
>( item ) );
3671 has_other_connections =
true;
3678 pin = pins.empty() ? nullptr : pins[0];
3681 for(
SCH_PIN* test_pin : pins )
3686 if( test_pin->GetType() == ELECTRICAL_PINTYPE::PT_POWER_IN
3687 && !test_pin->IsGlobalPower() )
3698 if(
pin && !has_other_connections
3699 && !
pin->IsGlobalPower()
3700 && !
pin->GetLibPin()->GetParentSymbol()->IsPower() )
3702 wxString
name =
pin->Connection( &sheet )->Name();
3703 wxString local_name =
pin->Connection( &sheet )->Name(
true );
3708 has_other_connections =
true;
3713 if(
pin && !has_other_connections
3714 &&
pin->GetType() != ELECTRICAL_PINTYPE::PT_NC
3715 &&
pin->GetType() != ELECTRICAL_PINTYPE::PT_NIC
3719 ercItem->SetSheetSpecificPath( sheet );
3720 ercItem->SetItemsSheetPaths( sheet );
3721 ercItem->SetItems(
pin );
3724 screen->
Append( marker );
3732 if( pins.size() > 1 )
3734 for(
SCH_PIN* testPin : pins )
3739 if( testPin->GetLibPin()->GetParentSymbol()->IsPower()
3740 && testPin->ConnectedItems( sheet ).empty()
3744 ercItem->SetSheetSpecificPath( sheet );
3745 ercItem->SetItemsSheetPaths( sheet );
3746 ercItem->SetItems( testPin );
3749 screen->
Append( marker );
3767 std::vector<SCH_ITEM*> wires;
3774 wires.emplace_back( item );
3776 wires.emplace_back( item );
3779 if( !wires.empty() )
3784 ercItem->SetSheetSpecificPath( sheet );
3785 ercItem->SetItems( wires[0],
3786 wires.size() > 1 ? wires[1] :
nullptr,
3787 wires.size() > 2 ? wires[2] :
nullptr,
3788 wires.size() > 3 ? wires[3] :
nullptr );
3791 screen->
Append( marker );
3822 std::map<KICAD_T, std::vector<SCH_TEXT*>> label_map;
3829 std::count_if( aLocSubgraph->m_items.begin(), aLocSubgraph->m_items.end(),
3832 return item->Type() == SCH_PIN_T;
3836 auto reportError = [&](
SCH_TEXT* aText,
int errCode )
3841 ercItem->SetSheetSpecificPath( sheet );
3842 ercItem->SetItems( aText );
3849 pinCount =
hasPins( aSubgraph );
3853 switch( item->
Type() )
3861 label_map[item->
Type()].push_back(
text );
3866 if(
text->IsDangling() )
3880 if( label_map.empty() )
3912 wxCHECK_MSG(
m_schematic,
true, wxS(
"Null m_schematic in CONNECTION_GRAPH::ercCheckLabels" ) );
3919 for(
auto& [type, label_vec] : label_map )
3938 int allPins = pinCount;
3946 if( neighbor == aSubgraph )
3952 allPins +=
hasPins( neighbor );
3956 if( allPins == 1 && !has_nc )
3980 std::map<wxString, std::tuple<int, const SCH_ITEM*, SCH_SHEET_PATH>> labelData;
3987 wxString resolvedLabelText =
3990 if( labelData.find( resolvedLabelText ) == labelData.end() )
3992 labelData[resolvedLabelText] = { 1, item, sheet };
3996 std::get<0>( labelData[resolvedLabelText] ) += 1;
3997 std::get<1>( labelData[resolvedLabelText] ) =
nullptr;
3998 std::get<2>( labelData[resolvedLabelText] ) = sheet;
4003 for(
const auto& label : labelData )
4005 if( std::get<0>( label.second ) == 1 )
4008 const SCH_ITEM* item = std::get<1>( label.second );
4011 ercItem->SetItems( std::get<1>( label.second ) );
4012 ercItem->SetSheetSpecificPath( sheet );
4013 ercItem->SetItemsSheetPaths( sheet );
4039 parentSheetPath.
push_back( parentSheet );
4041 std::map<wxString, SCH_SHEET_PIN*> pins;
4042 std::map<wxString, SCH_HIERLABEL*> labels;
4047 pins[
pin->GetShownText( &parentSheetPath,
false ) ] =
pin;
4052 ercItem->SetItems(
pin );
4053 ercItem->SetSheetSpecificPath( sheet );
4054 ercItem->SetItemsSheetPaths( sheet );
4057 sheet.LastScreen()->Append( marker );
4065 std::set<wxString> matchedPins;
4072 wxString labelText = label->
GetShownText( &parentSheetPath,
false );
4074 if( !pins.count( labelText ) )
4075 labels[ labelText ] = label;
4077 matchedPins.insert( labelText );
4081 for(
const wxString& matched : matchedPins )
4082 pins.erase( matched );
4084 for(
const std::pair<const wxString, SCH_SHEET_PIN*>& unmatched : pins )
4086 wxString msg = wxString::Format(
_(
"Sheet pin %s has no matching hierarchical "
4087 "label inside the sheet" ),
4091 ercItem->SetItems( unmatched.second );
4092 ercItem->SetErrorMessage( msg );
4093 ercItem->SetSheetSpecificPath( sheet );
4094 ercItem->SetItemsSheetPaths( sheet );
4097 sheet.LastScreen()->Append( marker );
4102 for(
const std::pair<const wxString, SCH_HIERLABEL*>& unmatched : labels )
4104 wxString msg = wxString::Format(
_(
"Hierarchical label %s has no matching "
4105 "sheet pin in the parent sheet" ),
4109 ercItem->SetItems( unmatched.second );
4110 ercItem->SetErrorMessage( msg );
4111 ercItem->SetSheetSpecificPath( parentSheetPath );
4112 ercItem->SetItemsSheetPaths( parentSheetPath );
constexpr EDA_IU_SCALE schIUScale
Calculate the connectivity of a schematic and generates netlists.
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 ercCheckNetclassConflicts(const std::vector< CONNECTION_SUBGRAPH * > &subgraphs)
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.
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.
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.
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.
bool ercCheckMultipleDrivers(const CONNECTION_SUBGRAPH *aSubgraph)
If the subgraph has multiple drivers of equal priority that are graphically connected,...
CONNECTION_SUBGRAPH * GetSubgraphForItem(SCH_ITEM *aItem)
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.
const std::vector< CONNECTION_SUBGRAPH * > GetAllSubgraphs(const wxString &aNetName) const
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 heirarchy.
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.
int assignNewNetCode(SCH_CONNECTION &aConnection)
Helper to assign a new net code to a connection.
std::map< std::pair< SCH_SHEET_PATH, wxString >, std::vector< const CONNECTION_SUBGRAPH * > > m_local_label_cache
int getOrCreateNetCode(const wxString &aNetName)
void 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
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 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.
void Recalculate(const SCH_SHEET_LIST &aSheetList, bool aUnconditional=false, std::function< void(SCH_ITEM *)> *aChangedItemHandler=nullptr)
Update the connection graph for the given list of sheets.
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.
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
A cache of escaped netnames from schematic items.
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.
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).
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)
const std::vector< std::pair< wxString, SCH_ITEM * > > GetNetclassesForDriver(SCH_ITEM *aItem, bool returnAll) const
Return the resolved netclasses for the item, and the source item providing the netclass.
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
KICAD_T Type() const
Returns the type of object.
virtual wxString GetItemDescription(UNITS_PROVIDER *aUnitsProvider) const
Return a user-visible description string of this item.
virtual const wxString & GetText() const
Return the string associated with the text object.
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
A small class to help profiling.
void Show(std::ostream &aStream=std::cerr)
Print the elapsed time (in a suitable unit) to a stream.
std::shared_ptr< NET_SETTINGS > m_NetSettings
Net settings for this project (owned here)
virtual PROJECT_FILE & GetProjectFile() const
SCH_SHEET_PATH & CurrentSheet() const override
SCH_SHEET_LIST GetSheets() const override
Builds and returns an updated schematic hierarchy TODO: can this be cached?
PROJECT & Prj() const override
Return a reference to the project this schematic is part of.
ERC_SETTINGS & ErcSettings() const
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...
VECTOR2I GetPosition() const override
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)
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
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.
const SYMBOL * GetParentSymbol() const
virtual const wxString & GetCachedDriverName() const
const std::unordered_set< SCH_RULE_AREA * > & GetRuleAreaCache() const
Gets the cache of rule areas enclosing this item.
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.
virtual void RunOnChildren(const std::function< void(SCH_ITEM *)> &aFunction)
void SetConnectionGraph(CONNECTION_GRAPH *aGraph)
Updates the connection graph for all connections in this item.
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.
wxString GetShownText(const SCH_SHEET_PATH *aPath, bool aAllowExtraText, int aDepth=0) const override
LABEL_FLAG_SHAPE GetShape() const
Segment description base class to describe items which have 2 end points (track, wire,...
bool IsGlobalPower() const
Return whether this pin forms a global power connection: i.e., is part of a power symbol and of type ...
SCH_PIN * GetLibPin() const
bool IsStacked(const SCH_PIN *aPin) const
wxString GetDefaultNetName(const SCH_SHEET_PATH &aPath, bool aForceNoConnect=false)
void Append(SCH_ITEM *aItem, bool aUpdateLibSymbol=true)
EE_RTREE & Items()
Gets 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
wxString PathHumanReadable(bool aUseShortRootName=true, bool aStripTrailingSeparator=false) const
Return the sheet path in a human readable form made from the sheet names.
SCH_SCREEN * LastScreen()
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< SCH_PIN * > GetPins(const SCH_SHEET_PATH *aSheet=nullptr) const
Retrieve a list of the SCH_PINs for the given sheet path.
int GetUnitSelection(const SCH_SHEET_PATH *aSheet) const
Return the instance-specific unit selection for the given sheet path.
std::unique_ptr< LIB_SYMBOL > & GetLibSymbolRef()
VECTOR2I GetPosition() const override
virtual wxString GetShownText(const SCH_SHEET_PATH *aPath, bool aAllowExtraText, int aDepth=0) const
bool GetExcludedFromBoard() const
virtual bool IsPower() const =0
#define CANDIDATE
flag indicating that the structure is connected
@ ERCE_DRIVER_CONFLICT
Conflicting drivers (labels, etc) on a subgraph.
@ ERCE_LABEL_NOT_CONNECTED
Label not connected to anything.
@ ERCE_BUS_TO_BUS_CONFLICT
A connection between bus objects doesn't share at least one net.
@ ERCE_BUS_ENTRY_CONFLICT
A wire connected to a bus doesn't match the bus.
@ ERCE_NETCLASS_CONFLICT
Multiple labels assign different netclasses to same net.
@ ERCE_GLOBLABEL
A global label is unique.
@ 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 global 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 delete_if(_Container &__c, _Function &&__f)
Deletes all values from __c for which __f returns true.
void remove_duplicates(_Container &__c)
Deletes all duplicate values from __c.
void delete_matching(_Container &__c, _Value __value)
Covers for the horrifically named std::remove and std::remove_if (neither of which remove anything).
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:...
BS::thread_pool thread_pool
thread_pool & GetKiCadThreadPool()
Get a reference to the current thread pool.
Functions to provide common constants and other functions to assist in making a consistent UI.