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 )
449 foundNetclasses.insert( foundNetclasses.end(), ruleNetclasses.begin(),
450 ruleNetclasses.end() );
460 SCH_FIELD* field = static_cast<SCH_FIELD*>( aChild );
462 if( field->GetCanonicalName() == wxT(
"Netclass" ) )
464 wxString netclass = field->GetShownText( &m_sheet, false );
466 if( netclass != wxEmptyString )
467 foundNetclasses.push_back( { netclass, aItem } );
473 foundNetclasses.begin(), foundNetclasses.end(),
474 [](
const std::pair<wxString, SCH_ITEM*>& i1,
const std::pair<wxString, SCH_ITEM*>& i2 )
476 return i1.first < i2.first;
479 return foundNetclasses;
505 child->m_absorbed_by =
this;
508 set_absorbed_by( subchild );
516 set_absorbed_by( aOther );
566 switch( aDriver->
Type() )
580 || sym->
GetLibSymbolRef()->GetReferenceField().GetText().StartsWith(
'#' ) )
594 std::back_inserter(
m_items ) );
651 wxCHECK2( aOldItem->
Type() == aNewItem->
Type(),
return );
686 wxCHECK2( oldPins.size() == newPins.size(),
return );
688 for(
size_t ii = 0; ii < oldPins.size(); ii++ )
690 exchange( oldPins[ii], newPins[ii] );
701 if( subgraph->m_graph ==
this )
725 std::function<
void(
SCH_ITEM* )>* aChangedItemHandler )
727 PROF_TIMER recalc_time(
"CONNECTION_GRAPH::Recalculate" );
732 PROF_TIMER update_items(
"updateItemConnectivity" );
735 std::set<SCH_ITEM*> dirty_items;
739 std::vector<SCH_ITEM*> items;
742 std::vector<std::pair<SCH_SYMBOL*, int>> symbolsChanged;
744 for(
SCH_ITEM* item : sheet.LastScreen()->Items() )
746 if( item->IsConnectable() && ( aUnconditional || item->IsConnectivityDirty() ) )
748 wxLogTrace(
ConnTrace, wxT(
"Adding item %s to connectivity graph update" ),
749 item->GetTypeDesc() );
750 items.push_back( item );
751 dirty_items.insert( item );
760 if(
pin->IsConnectivityDirty() )
762 dirty_items.insert(
pin );
775 if(
pin->IsConnectivityDirty() )
777 items.push_back(
pin );
778 dirty_items.insert(
pin );
788 if(
pin->IsConnectivityDirty() )
790 items.push_back(
pin );
791 dirty_items.insert(
pin );
804 if( symbol->
GetUnit() != new_unit )
805 symbolsChanged.push_back( { symbol, symbol->
GetUnit() } );
807 symbol->SetUnit( new_unit );
816 sheet.LastScreen()->TestDanglingEnds( &sheet, aChangedItemHandler );
819 for(
const auto& [ symbol, originalUnit ] : symbolsChanged )
820 symbol->SetUnit( originalUnit );
825 m_schematic->CurrentSheet().LastScreen()->TestDanglingEnds( &m_schematic->CurrentSheet(),
826 aChangedItemHandler );
829 item->SetConnectivityDirty(
false );
834 PROF_TIMER build_graph(
"buildConnectionGraph" );
836 buildConnectionGraph( aChangedItemHandler, aUnconditional );
849 const std::set<SCH_ITEM*> &aItems )
851 std::set<std::pair<SCH_SHEET_PATH, SCH_ITEM*>> retvals;
852 std::set<CONNECTION_SUBGRAPH*> subgraphs;
857 while( aSubgraph->m_absorbed_by )
859 wxASSERT( aSubgraph->m_graph == aSubgraph->m_absorbed_by->m_graph );
860 aSubgraph = aSubgraph->m_absorbed_by;
864 while( aSubgraph->m_hier_parent )
866 wxASSERT( aSubgraph->m_graph == aSubgraph->m_hier_parent->m_graph );
867 aSubgraph = aSubgraph->m_hier_parent;
871 aSubgraph->getAllConnectedItems( retvals, subgraphs );
874 auto extract_element = [&](
SCH_ITEM* aItem )
880 wxLogTrace(
ConnTrace, wxT(
"Item %s not found in connection graph" ), aItem->GetTypeDesc() );
885 wxLogTrace(
ConnTrace, wxT(
"Item %s in subgraph %ld (%p) has no driver" ),
886 aItem->GetTypeDesc(), item_sg->
m_code, item_sg );
891 if( sg_to_scan.empty() )
893 wxLogTrace(
ConnTrace, wxT(
"Item %s in subgraph %ld with net %s has no neighbors" ),
895 sg_to_scan.push_back( item_sg );
899 wxT(
"Removing all item %s connections from subgraph %ld with net %s: Found "
907 traverse_subgraph( sg );
909 for(
auto& bus_it : sg->m_bus_neighbors )
912 traverse_subgraph( bus_sg );
915 for(
auto& bus_it : sg->m_bus_parents )
918 traverse_subgraph( bus_sg );
932 extract_element(
pin );
939 extract_element(
pin );
943 extract_element( item );
949 for(
const auto& [
path, item] : retvals )
976 wxLogTrace(
ConnTrace, wxT(
"Removing %zu subgraphs" ), aSubgraphs.size() );
979 std::set<int> codes_to_remove;
983 std::sort( el.second.begin(), el.second.end() );
988 for(
auto& it : sg->m_bus_neighbors )
994 for(
auto test = parents.begin();
test != parents.end(); )
1002 if( parents.empty() )
1007 for(
auto& it : sg->m_bus_parents )
1013 for(
auto test = neighbors.begin();
test != neighbors.end(); )
1021 if( neighbors.empty() )
1042 auto it = std::lower_bound( el.second.begin(), el.second.end(), sg );
1044 while( it != el.second.end() && *it == sg )
1045 it = el.second.erase( it );
1048 auto remove_sg = [sg](
auto it ) ->
bool
1061 if( remove_sg( it ) )
1069 if( remove_sg( it ) )
1078 if( remove_sg( it ) )
1080 codes_to_remove.insert( it->first.Netcode );
1090 if( remove_sg( it ) )
1098 if( it->second == sg )
1109 if( codes_to_remove.contains( it->second ) )
1117 if( codes_to_remove.contains( it->second ) )
1126 sg->m_graph =
nullptr;
1133 const std::vector<SCH_ITEM*>& aItemList )
1135 wxLogTrace( wxT(
"Updating connectivity for sheet %s with %zu items" ),
1137 std::map<VECTOR2I, std::vector<SCH_ITEM*>> connection_map;
1141 aConn->SetType( CONNECTION_TYPE::NET );
1150 aConn->SetName(
name );
1157 std::vector<VECTOR2I> points = item->GetConnectionPoints();
1158 item->ClearConnectedItems( aSheet );
1164 pin->InitializeConnection( aSheet,
this );
1166 pin->ClearConnectedItems( aSheet );
1168 connection_map[
pin->GetTextPos() ].push_back(
pin );
1180 updatePin(
pin, conn );
1181 connection_map[
pin->GetPosition() ].push_back(
pin );
1187 SCH_CONNECTION* conn = item->InitializeConnection( aSheet,
this );
1190 switch( item->Type() )
1194 CONNECTION_TYPE::NET );
1198 conn->
SetType( CONNECTION_TYPE::BUS );
1206 if( points.empty() )
1207 points = {
static_cast<SCH_PIN*
>( item )->GetPosition() };
1209 updatePin(
static_cast<SCH_PIN*
>( item ), conn );
1213 conn->
SetType( CONNECTION_TYPE::NET );
1223 for(
const VECTOR2I& point : points )
1224 connection_map[ point ].push_back( item );
1228 for(
const auto& it : connection_map )
1230 std::vector<SCH_ITEM*> connection_vec = it.second;
1231 std::sort( connection_vec.begin(), connection_vec.end() );
1237 std::mutex update_mutex;
1239 auto update_lambda = [&](
SCH_ITEM* connected_item ) ->
size_t
1253 if( connection_vec.size() == 1 )
1266 if( connection_vec.size() < 2 )
1272 if( it.first == bus_entry->GetPosition() )
1275 bus_entry->m_connected_bus_items[1] = busLine;
1277 std::lock_guard<std::mutex> lock( update_mutex );
1290 for(
SCH_ITEM* test_item : connection_vec )
1292 bool bus_connection_ok =
true;
1294 if( test_item == connected_item )
1300 if( test_item->GetLayer() ==
LAYER_BUS )
1319 if( connected_item->ConnectionPropagatesTo( test_item ) &&
1320 test_item->ConnectionPropagatesTo( connected_item ) &&
1323 connected_item->AddConnectionTo( aSheet, test_item );
1334 if( !bus_entry->m_connected_bus_item )
1340 bus_entry->m_connected_bus_item = bus;
1349 tp.push_loop( connection_vec.size(),
1350 [&](
const int a,
const int b)
1352 for( int ii = a; ii < b; ++ii )
1353 update_lambda( connection_vec[ii] );
1355 tp.wait_for_tasks();
1363 wxCHECK_RET(
m_schematic, wxS(
"Connection graph cannot be built without schematic pointer" ) );
1369 for(
const std::shared_ptr<BUS_ALIAS>& alias : screen->GetBusAliases() )
1376 for(
const auto& it : item->m_connection_map )
1393 std::list<SCH_ITEM*> memberlist;
1398 SCH_CONNECTION* conn = aItem->GetOrInitConnection( sheet,
this );
1399 bool unique = !( aItem->GetFlags() &
CANDIDATE );
1404 return ( unique && conn && ( conn->
SubgraphCode() == 0 ) );
1407 std::copy_if( item->ConnectedItems( sheet ).begin(),
1408 item->ConnectedItems( sheet ).end(),
1409 std::back_inserter( memberlist ), get_items );
1411 for(
SCH_ITEM* connected_item : memberlist )
1416 SCH_CONNECTION* connected_conn = connected_item->Connection( &sheet );
1418 wxASSERT( connected_conn );
1424 subgraph->
AddItem( connected_item );
1425 const SCH_ITEM_VEC& citemset = connected_item->ConnectedItems( sheet );
1432 if( get_items( citem ) )
1433 memberlist.push_back( citem );
1438 for(
SCH_ITEM* connected_item : memberlist )
1439 connected_item->ClearFlags(
CANDIDATE );
1452 std::vector<CONNECTION_SUBGRAPH*> dirty_graphs;
1457 return candidate->m_dirty;
1460 wxLogTrace(
ConnTrace, wxT(
"Resolving drivers for %zu subgraphs" ), dirty_graphs.size() );
1462 std::vector<std::future<size_t>> returns( dirty_graphs.size() );
1466 if( !subgraph->m_dirty )
1470 for(
SCH_ITEM* item : subgraph->m_items )
1472 switch( item->
Type() )
1475 subgraph->m_no_connect = item;
1479 subgraph->m_bus_entry = item;
1486 if(
pin->GetType() == ELECTRICAL_PINTYPE::PT_NC )
1487 subgraph->m_no_connect = item;
1497 subgraph->ResolveDrivers(
true );
1498 subgraph->m_dirty =
false;
1505 tp.push_loop( dirty_graphs.size(),
1506 [&](
const int a,
const int b)
1508 for( int ii = a; ii < b; ++ii )
1509 update_lambda( dirty_graphs[ii] );
1511 tp.wait_for_tasks();
1518 return candidate->m_driver;
1531 wxString full_name = subgraph->m_driver_connection->Name();
1532 wxString
name = subgraph->m_driver_connection->Name(
true );
1539 if( subgraph->m_driver_connection->Type() == CONNECTION_TYPE::BUS )
1541 wxString prefixOnly = full_name.BeforeFirst(
'[' ) + wxT(
"[]" );
1545 subgraph->m_dirty =
true;
1547 if( subgraph->m_strong_driver )
1549 SCH_ITEM* driver = subgraph->m_driver;
1552 switch( driver->
Type() )
1568 wxASSERT(
pin->IsGlobalPower() );
1576 wxLogTrace(
ConnTrace, wxS(
"Unexpected strong driver %s" ),
1588 std::vector<CONNECTION_SUBGRAPH*> new_subgraphs;
1599 dummy.SetGraph(
this );
1602 wxLogTrace(
ConnTrace, wxS(
"new bus label (%s)" ),
1605 for(
const auto& conn :
dummy.Members() )
1607 wxString
name = conn->FullLocalName();
1617 new_conn->
SetType( CONNECTION_TYPE::NET );
1618 subgraph->StoreImplicitConnection( new_conn );
1621 wxLogTrace(
ConnTrace, wxS(
"SG(%ld), Adding full local name (%s) with sg (%d) "
1623 subgraph->m_code,
name, code, subgraph->m_sheet.PathHumanReadable() );
1636 new_subgraphs.push_back( new_sg );
1641 std::copy( new_subgraphs.begin(), new_subgraphs.end(),
1652 std::unordered_map<int, CONNECTION_SUBGRAPH*> global_power_pin_subgraphs;
1659 if( !
pin->ConnectedItems( sheet ).empty() && !
pin->GetLibPin()->GetParentSymbol()->IsPower() )
1674 if(
pin->GetLibPin()->GetParentSymbol()->IsPower() )
1675 connection->
SetName(
pin->GetParentSymbol()->GetValue(
true, &sheet,
false ) );
1684 auto jj = global_power_pin_subgraphs.find( code );
1686 if( jj != global_power_pin_subgraphs.end() )
1688 subgraph = jj->second;
1706 global_power_pin_subgraphs[code] = subgraph;
1723 std::unordered_set<CONNECTION_SUBGRAPH*> invalidated_subgraphs;
1727 if( subgraph->m_absorbed )
1732 wxString
name = connection->
Name();
1735 unsigned suffix = 1;
1737 auto create_new_name =
1741 wxString suffixStr = std::to_wstring( suffix );
1746 if( aConn->Type() == CONNECTION_TYPE::BUS_GROUP )
1748 wxString prefix = aConn->BusPrefix();
1750 if( prefix.empty() )
1751 prefix = wxT(
"BUS" );
1753 wxString oldName = aConn->Name().AfterFirst(
'{' );
1755 newName << prefix << wxT(
"_" ) << suffixStr << wxT(
"{" ) << oldName;
1757 aConn->ConfigureFromLabel( newName );
1761 newName << aConn->Name() << wxT(
"_" ) << suffixStr;
1762 aConn->SetSuffix( wxString( wxT(
"_" ) ) << suffixStr );
1769 if( !subgraph->m_strong_driver )
1771 std::vector<CONNECTION_SUBGRAPH*> vec_empty;
1772 std::vector<CONNECTION_SUBGRAPH*>* vec = &vec_empty;
1779 if( vec->size() <= 1 && subgraph->m_driver_connection->Type() == CONNECTION_TYPE::BUS )
1781 wxString prefixOnly =
name.BeforeFirst(
'[' ) + wxT(
"[]" );
1787 if( vec->size() > 1 )
1789 wxString new_name = create_new_name( connection );
1792 new_name = create_new_name( connection );
1795 wxS(
"%ld (%s) is weakly driven and not unique. Changing to %s." ),
1796 subgraph->m_code,
name, new_name );
1804 else if( subgraph->m_driver )
1816 bool conflict =
false;
1817 wxString global_name = connection->
Name(
true );
1824 std::vector<CONNECTION_SUBGRAPH*>& candidates = kk->second;
1828 if( candidate->m_sheet == sheet )
1836 wxS(
"%ld (%s) skipped for promotion due to potential "
1838 subgraph->m_code,
name );
1845 wxS(
"%ld (%s) weakly driven by unique sheet pin %s, "
1847 subgraph->m_code,
name,
1848 subgraph->m_driver->GetItemDescription( &unitsProvider,
true ) );
1850 subgraph->m_strong_driver =
true;
1857 if( connection->
IsBus() )
1881 subgraph->m_dirty =
true;
1889 if( !subgraph->m_strong_driver )
1896 std::vector<CONNECTION_SUBGRAPH*> candidate_subgraphs;
1899 std::back_inserter( candidate_subgraphs ),
1902 return ( !candidate->m_absorbed &&
1903 candidate->m_strong_driver &&
1904 candidate != subgraph );
1910 std::vector< std::shared_ptr<SCH_CONNECTION> > connections_to_check;
1913 connections_to_check.push_back( std::make_shared<SCH_CONNECTION>( *connection ) );
1915 auto add_connections_to_check =
1918 for(
SCH_ITEM* possible_driver : aSubgraph->m_items )
1920 if( possible_driver == aSubgraph->m_driver )
1927 if( c->Type() != aSubgraph->m_driver_connection->Type() )
1930 if( c->Name(
true ) == aSubgraph->m_driver_connection->Name(
true ) )
1933 connections_to_check.push_back( c );
1935 wxS(
"%lu (%s): Adding secondary driver %s" ),
1937 aSubgraph->m_driver_connection->Name(
true ),
1946 add_connections_to_check( subgraph );
1948 std::set<SCH_CONNECTION*> checked_connections;
1950 for(
unsigned i = 0; i < connections_to_check.size(); i++ )
1952 auto member = connections_to_check[i];
1955 if( !checked_connections.insert( member.get() ).second )
1958 if( member->IsBus() )
1960 connections_to_check.insert( connections_to_check.end(),
1961 member->Members().begin(),
1962 member->Members().end() );
1965 wxString test_name = member->Name(
true );
1969 if( candidate->
m_absorbed || candidate == subgraph )
1985 if( driver == candidate->
m_driver )
1996 if(
pin->IsGlobalPower()
1997 &&
pin->GetDefaultNetName( sheet ) == test_name )
2009 if( subgraph->GetNameForDriver( driver ) == test_name )
2022 wxLogTrace(
ConnTrace, wxS(
"%lu (%s) has bus child %lu (%s)" ),
2023 subgraph->m_code, connection->
Name(),
2024 candidate->
m_code, member->Name() );
2026 subgraph->m_bus_neighbors[member].insert( candidate );
2031 wxLogTrace(
ConnTrace, wxS(
"%lu (%s) absorbs neighbor %lu (%s)" ),
2032 subgraph->m_code, connection->
Name(),
2036 add_connections_to_check( candidate );
2038 subgraph->Absorb( candidate );
2039 invalidated_subgraphs.insert( subgraph );
2049 if( subgraph->m_absorbed )
2052 if( !subgraph->ResolveDrivers() )
2055 if( subgraph->m_driver_connection->IsBus() )
2060 wxLogTrace(
ConnTrace, wxS(
"Re-resolving drivers for %lu (%s)" ), subgraph->m_code,
2061 subgraph->m_driver_connection->Name() );
2082 wxCHECK_RET(
m_schematic, wxT(
"Connection graph cannot be built without schematic pointer" ) );
2088 for(
const std::shared_ptr<BUS_ALIAS>& alias : screen->GetBusAliases() )
2092 PROF_TIMER sub_graph(
"buildItemSubGraphs" );
2112 PROF_TIMER proc_sub_graph(
"ProcessSubGraphs" );
2116 proc_sub_graph.
Show();
2125 std::vector<CONNECTION_SUBGRAPH*> global_subgraphs;
2127 std::back_inserter( global_subgraphs ),
2130 return !candidate->m_local_driver;
2142 [&](
const int a,
const int b)
2144 for( int ii = a; ii < b; ++ii )
2145 m_driver_subgraphs[ii]->UpdateItemConnections();
2147 tp.wait_for_tasks();
2154 if( !subgraph->m_dirty )
2157 wxLogTrace(
ConnTrace, wxS(
"Processing %lu (%s) for propagation" ), subgraph->m_code,
2158 subgraph->m_driver_connection->Name() );
2164 if( !subgraph->m_local_driver && subgraph->m_multiple_drivers )
2166 for(
SCH_ITEM* driver : subgraph->m_drivers )
2168 if( driver == subgraph->m_driver )
2171 const wxString& secondary_name = subgraph->GetNameForDriver( driver );
2173 if( secondary_name == subgraph->m_driver_connection->Name() )
2181 if( candidate == subgraph )
2184 if( !secondary_is_global && candidate->
m_sheet != subgraph->m_sheet )
2189 if( conn->
Name() == secondary_name )
2191 wxLogTrace(
ConnTrace, wxS(
"Global %lu (%s) promoted to %s" ),
2193 subgraph->m_driver_connection->Name() );
2195 conn->
Clone( *subgraph->m_driver_connection );
2214 if( subgraph->m_dirty )
2230 wxASSERT_MSG( !subgraph->m_dirty,
2231 wxS(
"Subgraph not processed by propagateToNeighbors!" ) );
2233 if( subgraph->m_bus_parents.size() < 2 )
2238 wxLogTrace(
ConnTrace, wxS(
"%lu (%s) has multiple bus parents" ),
2239 subgraph->m_code, conn->
Name() );
2241 wxASSERT( conn->
IsNet() );
2243 for(
const auto& ii : subgraph->m_bus_parents )
2256 wxLogTrace(
ConnTrace, wxS(
"Warning: could not match %s inside %lu (%s)" ),
2261 if( conn->
Name() != match->
Name() )
2263 wxString old_name = match->
Name();
2265 wxLogTrace(
ConnTrace, wxS(
"Updating %lu (%s) member %s to %s" ),
2267 old_name, conn->
Name() );
2269 match->
Clone( *conn );
2288 auto updateItemConnectionsTask =
2292 if( !subgraph->m_strong_driver && subgraph->m_drivers.size() == 1 &&
2293 subgraph->m_driver->Type() ==
SCH_PIN_T )
2296 wxString
name =
pin->GetDefaultNetName( subgraph->m_sheet,
true );
2298 subgraph->m_driver_connection->ConfigureFromLabel(
name );
2301 subgraph->m_dirty =
false;
2302 subgraph->UpdateItemConnections();
2305 if( subgraph->m_driver_connection->IsBus() )
2310 if( subgraph->m_driver && subgraph->m_driver->Type() ==
SCH_SHEET_PIN_T )
2316 wxString pinText =
pin->GetShownText(
false );
2323 if( label->
GetShownText( &subgraph->m_sheet,
false ) == pinText )
2326 path.push_back( sheet );
2330 if( parent_conn && parent_conn->
IsBus() )
2331 subgraph->m_driver_connection->
SetType( CONNECTION_TYPE::BUS );
2337 if( subgraph->m_driver_connection->IsBus() )
2346 [&](
const int a,
const int b)
2348 for(
int ii = a; ii < b; ++ii )
2351 tp.wait_for_tasks();
2359 subgraph->m_driver_connection->NetCode() };
2366 std::map<wxString, std::set<wxString>> oldAssignments =
2367 netSettings->GetNetclassLabelAssignments();
2368 std::set<wxString> affectedNetclassNetAssignments;
2370 netSettings->ClearNetclassLabelAssignments();
2372 auto dirtySubgraphs =
2373 [&](
const std::vector<CONNECTION_SUBGRAPH*>& subgraphs )
2375 if( aChangedItemHandler )
2379 for(
SCH_ITEM* item : subgraph->m_items )
2380 (*aChangedItemHandler)( item );
2385 auto checkNetclassDrivers =
2386 [&](
const wxString& netName,
const std::vector<CONNECTION_SUBGRAPH*>& subgraphs )
2388 wxCHECK_RET( !subgraphs.empty(), wxS(
"Invalid empty subgraph" ) );
2390 std::set<wxString> netclasses;
2395 for(
SCH_ITEM* item : subgraph->m_items )
2397 std::vector<std::pair<wxString, SCH_ITEM*>> netclassesWithProviders =
2398 subgraph->GetNetclassesForDriver( item );
2400 for( std::pair<wxString, SCH_ITEM*>& ncPair : netclassesWithProviders )
2401 netclasses.insert( std::move( ncPair.first ) );
2408 if( subgraph->m_driver_connection->IsBus() )
2410 auto processBusMember = [&,
this](
const SCH_CONNECTION* member )
2412 if( !netclasses.empty() )
2414 netSettings->AppendNetclassLabelAssignment( member->Name(), netclasses );
2419 if( oldAssignments.count( member->Name() ) )
2421 if( oldAssignments[member->Name()] != netclasses )
2423 affectedNetclassNetAssignments.insert( member->Name() );
2426 dirtySubgraphs( ii->second );
2429 else if( !netclasses.empty() )
2431 affectedNetclassNetAssignments.insert( member->Name() );
2434 dirtySubgraphs( ii->second );
2438 for(
const std::shared_ptr<SCH_CONNECTION>& member :
2439 subgraph->m_driver_connection->Members() )
2444 if( member->IsBus() )
2446 for(
const std::shared_ptr<SCH_CONNECTION>& nestedMember :
2449 processBusMember( nestedMember.get() );
2454 processBusMember( member.get() );
2461 if( !netclasses.empty() )
2463 netSettings->AppendNetclassLabelAssignment( netName, netclasses );
2466 if( oldAssignments.count( netName ) )
2468 if( oldAssignments[netName] != netclasses )
2470 affectedNetclassNetAssignments.insert( netName );
2471 dirtySubgraphs( subgraphs );
2474 else if( !netclasses.empty() )
2476 affectedNetclassNetAssignments.insert( netName );
2477 dirtySubgraphs( subgraphs );
2483 checkNetclassDrivers( netname, subgraphs );
2485 if( !aUnconditional )
2487 for(
auto& [netname, netclasses] : oldAssignments )
2489 if( netSettings->GetNetclassLabelAssignments().count( netname )
2490 || affectedNetclassNetAssignments.count( netname ) )
2495 netSettings->SetNetclassLabelAssignment( netname, netclasses );
2533 std::vector<std::shared_ptr<SCH_CONNECTION>> connections_to_check( aConnection->
Members() );
2535 for(
unsigned i = 0; i < connections_to_check.size(); i++ )
2537 const std::shared_ptr<SCH_CONNECTION>& member = connections_to_check[i];
2539 if( member->IsBus() )
2541 connections_to_check.insert( connections_to_check.end(),
2542 member->Members().begin(),
2543 member->Members().end() );
2555 std::vector<CONNECTION_SUBGRAPH*> search_list;
2556 std::unordered_set<CONNECTION_SUBGRAPH*> visited;
2557 std::unordered_set<SCH_CONNECTION*> stale_bus_members;
2564 path.push_back(
pin->GetParent() );
2575 || visited.contains( candidate ) )
2584 wxLogTrace(
ConnTrace, wxS(
"%lu: found child %lu (%s)" ), aParent->m_code,
2590 wxASSERT( candidate->
m_graph == aParent->m_graph );
2592 search_list.push_back( candidate );
2612 || visited.contains( candidate )
2618 const KIID& last_parent_uuid = aParent->m_sheet.Last()->m_Uuid;
2623 if(
pin->GetParent()->m_Uuid != last_parent_uuid )
2629 if( pin_path != aParent->m_sheet )
2634 wxLogTrace(
ConnTrace, wxS(
"%lu: found additional parent %lu (%s)" ),
2635 aParent->m_code, candidate->
m_code,
2638 aParent->m_hier_children.insert( candidate );
2639 search_list.push_back( candidate );
2649 for(
const auto&
kv : aParentGraph->m_bus_neighbors )
2691 wxLogTrace(
ConnTrace, wxS(
"Could not match bus member %s in %s" ),
2692 kv.first->Name(), parent->
Name() );
2697 auto neighbor_name = neighbor_conn->
Name();
2700 if( neighbor_name == member->
Name() )
2704 if( neighbor_conn->Sheet() != neighbor->
m_sheet )
2708 wxASSERT( neighbor_conn->IsNet() );
2710 wxLogTrace(
ConnTrace, wxS(
"%lu (%s) connected to bus member %s (local %s)" ),
2717 member->
Clone( *neighbor_conn );
2718 stale_bus_members.insert( member );
2722 neighbor_conn->Clone( *member );
2736 propagate_bus_neighbors( aSubgraph );
2743 wxLogTrace(
ConnTrace, wxS(
"%lu (%s) has both hier ports and pins; deferring processing" ),
2750 wxS(
"%lu (%s) has no hier pins or ports on sheet %s; marking clean" ),
2756 visited.insert( aSubgraph );
2758 wxLogTrace(
ConnTrace, wxS(
"Propagating %lu (%s) to subsheets" ),
2763 for(
unsigned i = 0; i < search_list.size(); i++ )
2765 auto child = search_list[i];
2767 if( visited.insert( child ).second )
2770 child->m_dirty =
false;
2785 if( subgraph == aSubgraph )
2792 wxString candidateName = subgraph->m_driver_connection->Name();
2793 bool shorterPath = subgraph->m_sheet.size() < bestDriver->
m_sheet.
size();
2794 bool asGoodPath = subgraph->m_sheet.size() <= bestDriver->
m_sheet.
size();
2804 ( !bestIsStrong && candidateStrong ) ||
2805 ( priority > highest && candidateStrong ) ||
2806 ( priority == highest && candidateStrong && shorterPath ) ||
2807 ( ( bestIsStrong == candidateStrong ) && asGoodPath && ( priority == highest ) &&
2808 ( candidateName < bestName ) ) )
2810 bestDriver = subgraph;
2812 bestIsStrong = candidateStrong;
2813 bestName = candidateName;
2818 if( bestDriver != aSubgraph )
2820 wxLogTrace(
ConnTrace, wxS(
"%lu (%s) overridden by new driver %lu (%s)" ),
2829 wxString old_name = subgraph->m_driver_connection->
Name();
2831 subgraph->m_driver_connection->Clone( *conn );
2833 if( old_name != conn->
Name() )
2837 propagate_bus_neighbors( subgraph );
2843 if( conn->
IsBus() && !stale_bus_members.empty() )
2845 std::unordered_set<SCH_CONNECTION*> cached_members = stale_bus_members;
2856 wxLogTrace(
ConnTrace, wxS(
"WARNING: failed to match stale member %s in %s." ),
2857 stale_member->Name(), subgraph->m_driver_connection->Name() );
2861 wxLogTrace(
ConnTrace, wxS(
"Updating %lu (%s) member %s to %s" ), subgraph->m_code,
2862 subgraph->m_driver_connection->Name(), member->
LocalName(),
2863 stale_member->Name() );
2865 member->
Clone( *stale_member );
2867 propagate_bus_neighbors( subgraph );
2879 std::shared_ptr<SCH_CONNECTION> c = std::shared_ptr<SCH_CONNECTION>(
nullptr );
2881 switch( aItem->
Type() )
2887 if(
pin->IsGlobalPower() )
2888 c = std::make_shared<SCH_CONNECTION>( aItem, aSubgraph->
m_sheet );
2897 c = std::make_shared<SCH_CONNECTION>( aItem, aSubgraph->
m_sheet );
2907 c->SetGraph(
this );
2918 wxASSERT( aBusConnection->
IsBus() );
2922 if( aBusConnection->
Type() == CONNECTION_TYPE::BUS )
2927 for(
const std::shared_ptr<SCH_CONNECTION>& bus_member : aBusConnection->
Members() )
2929 if( bus_member->VectorIndex() == aSearch->
VectorIndex() )
2931 match = bus_member.get();
2939 for(
const std::shared_ptr<SCH_CONNECTION>& c : aBusConnection->
Members() )
2944 if( c->Type() == CONNECTION_TYPE::BUS )
2946 for(
const std::shared_ptr<SCH_CONNECTION>& bus_member : c->Members() )
2948 if( bus_member->LocalName() == aSearch->
LocalName() )
2950 match = bus_member.get();
2955 else if( c->LocalName() == aSearch->
LocalName() )
2968 const wxString& aOldName )
2974 std::vector<CONNECTION_SUBGRAPH*>& vec = it->second;
2978 wxLogTrace(
ConnTrace, wxS(
"recacheSubgraphName: %s => %s" ), aOldName,
2995 std::vector<const CONNECTION_SUBGRAPH*> ret;
3000 wxASSERT( !subgraph->m_dirty );
3002 if( !subgraph->m_driver )
3008 if( !connection->
IsBus() )
3011 auto labels = subgraph->GetVectorBusLabels();
3013 if( labels.size() > 1 )
3015 bool different =
false;
3016 wxString first =
static_cast<SCH_TEXT*
>( labels.at( 0 ) )->GetShownText( sheet,
false );
3018 for(
unsigned i = 1; i < labels.size(); ++i )
3030 wxLogTrace(
ConnTrace, wxS(
"SG %ld (%s) has multiple bus labels" ), subgraph->m_code,
3031 connection->
Name() );
3033 ret.push_back( subgraph );
3054 if( graph == aSubGraph )
3095 wxASSERT( !it->second.empty() );
3097 return it->second[0];
3113const std::vector<CONNECTION_SUBGRAPH*>
3116 std::vector<CONNECTION_SUBGRAPH*> subgraphs;
3129 int error_count = 0;
3131 wxCHECK_MSG(
m_schematic,
true, wxS(
"Null m_schematic in CONNECTION_GRAPH::RunERC" ) );
3137 std::set<SCH_ITEM*> seenDriverInstances;
3142 wxCHECK2( subgraph,
continue );
3145 wxASSERT( !subgraph->m_dirty );
3147 if( subgraph->m_absorbed )
3150 if( seenDriverInstances.count( subgraph->m_driver ) )
3153 if( subgraph->m_driver )
3154 seenDriverInstances.insert( subgraph->m_driver );
3172 subgraph->ResolveDrivers(
false );
3243 wxCHECK( aSubgraph,
false );
3249 if( driver == aSubgraph->
m_driver )
3261 if( primaryName == secondaryName )
3264 wxString msg = wxString::Format(
_(
"Both %s and %s are attached to the same "
3265 "items; %s will be used in the netlist" ),
3266 primaryName, secondaryName, primaryName );
3269 ercItem->SetItems( aSubgraph->
m_driver, driver );
3270 ercItem->SetSheetSpecificPath( aSubgraph->
GetSheet() );
3271 ercItem->SetItemsSheetPaths( aSubgraph->
GetSheet(), aSubgraph->
m_sheet );
3272 ercItem->SetErrorMessage( msg );
3297 switch( item->
Type() )
3302 bus_item = ( !bus_item ) ? item : bus_item;
3304 net_item = ( !net_item ) ? item : net_item;
3319 bus_item = ( !bus_item ) ? item : bus_item;
3321 net_item = ( !net_item ) ? item : net_item;
3331 if( net_item && bus_item )
3334 ercItem->SetSheetSpecificPath( sheet );
3335 ercItem->SetItems( net_item, bus_item );
3338 screen->
Append( marker );
3357 switch( item->
Type() )
3388 if(
test != member && member->Name() ==
test->Name() )
3402 ercItem->SetSheetSpecificPath( sheet );
3403 ercItem->SetItems( label, port );
3406 screen->
Append( marker );
3418 bool conflict =
false;
3434 switch( item->
Type() )
3464 std::set<wxString> test_names;
3474 if( member->Type() == CONNECTION_TYPE::BUS )
3476 for(
const auto& sub_member : member->Members() )
3478 if( test_names.count( sub_member->FullLocalName() ) )
3482 else if( test_names.count( member->FullLocalName() ) )
3501 wxString msg = wxString::Format(
_(
"Net %s is graphically connected to bus %s but is not a"
3502 " member of that bus" ),
3506 ercItem->SetSheetSpecificPath( sheet );
3507 ercItem->SetItems( bus_entry, bus_wire );
3508 ercItem->SetErrorMessage( msg );
3511 screen->
Append( marker );
3528 std::set<SCH_PIN*> unique_pins;
3529 std::set<SCH_LABEL_BASE*> unique_labels;
3537 for(
SCH_ITEM* item : aProcessGraph->m_items )
3539 switch( item->
Type() )
3546 if( aProcessGraph == aSubgraph )
3549 if( std::none_of( unique_pins.begin(), unique_pins.end(),
3556 unique_pins.insert( test_pin );
3579 process_subgraph( subgraph );
3584 process_subgraph( aSubgraph );
3609 ercItem->SetSheetSpecificPath( sheet );
3610 ercItem->SetItemsSheetPaths( sheet );
3617 pos =
pin->GetPosition();
3626 screen->
Append( marker );
3631 if( unique_pins.empty() && unique_labels.empty() &&
3636 ercItem->SetSheetSpecificPath( sheet );
3637 ercItem->SetItemsSheetPaths( sheet );
3640 screen->
Append( marker );
3647 bool has_other_connections =
false;
3648 std::vector<SCH_PIN*> pins;
3655 switch( item->
Type() )
3664 for(
SCH_PIN* other_pin : pins )
3668 has_other_connections =
true;
3674 pins.emplace_back(
static_cast<SCH_PIN*
>( item ) );
3681 has_other_connections =
true;
3688 pin = pins.empty() ? nullptr : pins[0];
3691 for(
SCH_PIN* test_pin : pins )
3696 if( test_pin->GetType() == ELECTRICAL_PINTYPE::PT_POWER_IN
3697 && !test_pin->IsGlobalPower() )
3708 if(
pin && !has_other_connections
3709 && !
pin->IsGlobalPower()
3710 && !
pin->GetLibPin()->GetParentSymbol()->IsPower() )
3712 wxString
name =
pin->Connection( &sheet )->Name();
3713 wxString local_name =
pin->Connection( &sheet )->Name(
true );
3718 has_other_connections =
true;
3723 if(
pin && !has_other_connections
3724 &&
pin->GetType() != ELECTRICAL_PINTYPE::PT_NC
3725 &&
pin->GetType() != ELECTRICAL_PINTYPE::PT_NIC
3729 ercItem->SetSheetSpecificPath( sheet );
3730 ercItem->SetItemsSheetPaths( sheet );
3731 ercItem->SetItems(
pin );
3734 screen->
Append( marker );
3742 if( pins.size() > 1 )
3744 for(
SCH_PIN* testPin : pins )
3749 if( testPin->GetLibPin()->GetParentSymbol()->IsPower()
3750 && testPin->ConnectedItems( sheet ).empty()
3754 ercItem->SetSheetSpecificPath( sheet );
3755 ercItem->SetItemsSheetPaths( sheet );
3756 ercItem->SetItems( testPin );
3759 screen->
Append( marker );
3786 auto report_error = [&](
VECTOR2I& location )
3790 ercItem->SetItems( line );
3791 ercItem->SetSheetSpecificPath( sheet );
3792 ercItem->SetErrorMessage(
_(
"Unconnected wire endpoint" ) );
3807 return err_count > 0;
3817 std::vector<SCH_ITEM*> wires;
3824 wires.emplace_back( item );
3826 wires.emplace_back( item );
3829 if( !wires.empty() )
3834 ercItem->SetSheetSpecificPath( sheet );
3835 ercItem->SetItems( wires[0],
3836 wires.size() > 1 ? wires[1] :
nullptr,
3837 wires.size() > 2 ? wires[2] :
nullptr,
3838 wires.size() > 3 ? wires[3] :
nullptr );
3841 screen->
Append( marker );
3869 size_t pinCount = 0;
3872 std::map<KICAD_T, std::vector<SCH_TEXT*>> label_map;
3878 return std::count_if( aLocSubgraph->m_items.begin(), aLocSubgraph->m_items.end(),
3881 return item->Type() == SCH_PIN_T;
3886 [&](
SCH_TEXT* aText,
int errCode )
3891 ercItem->SetSheetSpecificPath( sheet );
3892 ercItem->SetItems( aText );
3899 pinCount =
hasPins( aSubgraph );
3903 switch( item->
Type() )
3911 label_map[item->
Type()].push_back(
text );
3916 if(
text->IsDangling() )
3932 if( label_map.empty() )
3937 for(
auto& [ connection, subgraphs ] : aSubgraph->
m_bus_parents )
3941 if( busParent->m_no_connect )
3964 wxCHECK_MSG(
m_schematic,
true, wxS(
"Null m_schematic in CONNECTION_GRAPH::ercCheckLabels" ) );
3971 for(
auto& [type, label_vec] : label_map )
3989 size_t allPins = pinCount;
3997 if( neighbor == aSubgraph )
4003 allPins +=
hasPins( neighbor );
4007 if( allPins == 1 && !has_nc )
4031 std::map<wxString, std::tuple<int, const SCH_ITEM*, SCH_SHEET_PATH>> labelData;
4038 wxString resolvedLabelText =
4041 if( labelData.find( resolvedLabelText ) == labelData.end() )
4043 labelData[resolvedLabelText] = { 1, item, sheet };
4047 std::get<0>( labelData[resolvedLabelText] ) += 1;
4048 std::get<1>( labelData[resolvedLabelText] ) =
nullptr;
4049 std::get<2>( labelData[resolvedLabelText] ) = sheet;
4054 for(
const auto& label : labelData )
4056 if( std::get<0>( label.second ) == 1 )
4059 const SCH_ITEM* item = std::get<1>( label.second );
4062 ercItem->SetItems( std::get<1>( label.second ) );
4063 ercItem->SetSheetSpecificPath( sheet );
4064 ercItem->SetItemsSheetPaths( sheet );
4079 int error_count = 0;
4091 ercItem->SetSheetSpecificPath( sheet );
4092 ercItem->SetItems(
text );
4095 sheet.LastScreen()->Append( marker );
4118 parentSheetPath.
push_back( parentSheet );
4120 std::map<wxString, SCH_SHEET_PIN*> pins;
4121 std::map<wxString, SCH_HIERLABEL*> labels;
4126 pins[
pin->GetShownText( &parentSheetPath,
false ) ] =
pin;
4131 ercItem->SetItems(
pin );
4132 ercItem->SetSheetSpecificPath( sheet );
4133 ercItem->SetItemsSheetPaths( sheet );
4136 sheet.LastScreen()->Append( marker );
4144 std::set<wxString> matchedPins;
4151 wxString labelText = label->
GetShownText( &parentSheetPath,
false );
4153 if( !pins.count( labelText ) )
4154 labels[ labelText ] = label;
4156 matchedPins.insert( labelText );
4160 for(
const wxString& matched : matchedPins )
4161 pins.erase( matched );
4163 for(
const std::pair<const wxString, SCH_SHEET_PIN*>& unmatched : pins )
4165 wxString msg = wxString::Format(
_(
"Sheet pin %s has no matching hierarchical "
4166 "label inside the sheet" ),
4170 ercItem->SetItems( unmatched.second );
4171 ercItem->SetErrorMessage( msg );
4172 ercItem->SetSheetSpecificPath( sheet );
4173 ercItem->SetItemsSheetPaths( sheet );
4176 sheet.LastScreen()->Append( marker );
4181 for(
const std::pair<const wxString, SCH_HIERLABEL*>& unmatched : labels )
4183 wxString msg = wxString::Format(
_(
"Hierarchical label %s has no matching "
4184 "sheet pin in the parent sheet" ),
4188 ercItem->SetItems( unmatched.second );
4189 ercItem->SetErrorMessage( msg );
4190 ercItem->SetSheetSpecificPath( parentSheetPath );
4191 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 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.
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,...
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)
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
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.
CONNECTION_SUBGRAPH * GetSubgraphForItem(SCH_ITEM *aItem) const
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.
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).
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 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
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
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 ...
SCH_PIN * GetLibPin() const
bool IsStacked(const SCH_PIN *aPin) const
wxString GetDefaultNetName(const SCH_SHEET_PATH &aPath, bool aForceNoConnect=false)
Container class that holds multiple SCH_SCREEN objects in a hierarchy.
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_UNCONNECTED_WIRE_ENDPOINT
A label is connected to more than one wire.
@ 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_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_GLOBLABEL_DANGLING
A global label is dangling.
@ 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.