27#include <unordered_map>
108 if( old_conn && new_conn )
110 new_conn->
Clone( *old_conn );
140 std::vector<SCH_ITEM*> candidates;
141 std::set<SCH_ITEM*> strong_drivers;
165 strong_drivers.insert( item );
167 if( item_priority > highest_priority )
170 candidates.push_back( item );
171 highest_priority = item_priority;
173 else if( !candidates.empty() && ( item_priority == highest_priority ) )
175 candidates.push_back( item );
185 if( !candidates.empty() )
214 if( aGlobal != bGlobal )
220 if( aLocal != bLocal )
231 if( sa->
GetShape() == LABEL_FLAG_SHAPE::L_OUTPUT )
233 if( sb->
GetShape() == LABEL_FLAG_SHAPE::L_OUTPUT )
241 bool a_lowQualityName = a_name.Contains(
"-Pad" );
242 bool b_lowQualityName = b_name.Contains(
"-Pad" );
244 if( a_lowQualityName != b_lowQualityName )
245 return !a_lowQualityName;
247 return a_name < b_name;
250 std::sort( candidates.begin(), candidates.end(), candidate_cmp );
255 if( strong_drivers.size() > 1 )
262 m_drivers.insert( strong_drivers.begin(), strong_drivers.end() );
284 std::set<CONNECTION_SUBGRAPH*>& aSubgraphs )
296 if( aSubgraphs.insert( sg ).second ==
false )
302 aItems.emplace(
m_sheet, item );
316#ifdef CONNECTIVITY_DEBUG
317 wxASSERT_MSG(
false, wxS(
"Tried to get the net name of an item with no connection" ) );
329 std::vector<SCH_ITEM*> labels;
333 switch( item->Type() )
341 if( type == CONNECTION_TYPE::BUS || type == CONNECTION_TYPE::BUS_GROUP )
342 labels.push_back( item );
358 std::vector<SCH_ITEM*> labels;
362 switch( item->Type() )
370 if( label_conn->
Type() == CONNECTION_TYPE::BUS )
371 labels.push_back( item );
387 switch( aItem->
Type() )
394 return pin->GetDefaultNetName(
m_sheet, forceNoConnect );
421 wxFAIL_MSG( wxS(
"Unhandled item type in GetNameForDriver" ) );
422 return wxEmptyString;
442const std::vector<std::pair<wxString, SCH_ITEM*>>
445 std::vector<std::pair<wxString, SCH_ITEM*>> foundNetclasses;
447 const std::unordered_set<SCH_RULE_AREA*>& ruleAreaCache = aItem->
GetRuleAreaCache();
452 const std::vector<std::pair<wxString, SCH_ITEM*>> ruleNetclasses =
453 ruleArea->GetResolvedNetclasses();
455 if( ruleNetclasses.size() > 0 )
457 foundNetclasses.insert( foundNetclasses.end(), ruleNetclasses.begin(),
458 ruleNetclasses.end() );
468 SCH_FIELD* field = static_cast<SCH_FIELD*>( aChild );
470 if( field->GetCanonicalName() == wxT(
"Netclass" ) )
472 wxString netclass = field->GetShownText( &m_sheet, false );
474 if( netclass != wxEmptyString )
475 foundNetclasses.push_back( { netclass, aItem } );
482 foundNetclasses.begin(), foundNetclasses.end(),
483 [](
const std::pair<wxString, SCH_ITEM*>& i1,
const std::pair<wxString, SCH_ITEM*>& i2 )
485 return i1.first < i2.first;
488 return foundNetclasses;
514 child->m_absorbed_by =
this;
517 set_absorbed_by( subchild );
525 set_absorbed_by( aOther );
575 switch( aDriver->
Type() )
591 || sym->
GetLibSymbolRef()->GetReferenceField().GetText().StartsWith(
'#' ) )
605 std::back_inserter(
m_items ) );
662 wxCHECK2( aOldItem->
Type() == aNewItem->
Type(),
return );
697 wxCHECK2( oldPins.size() == newPins.size(),
return );
699 for(
size_t ii = 0; ii < oldPins.size(); ii++ )
701 exchange( oldPins[ii], newPins[ii] );
712 if( subgraph->m_graph ==
this )
736 std::function<
void(
SCH_ITEM* )>* aChangedItemHandler,
740 PROF_TIMER recalc_time(
"CONNECTION_GRAPH::Recalculate" );
741 monitorTrans.
Start();
746 monitorTrans.
StartSpan(
"updateItemConnectivity",
"" );
747 PROF_TIMER update_items(
"updateItemConnectivity" );
750 std::set<SCH_ITEM*> dirty_items;
752 int count = aSheetList.size() * 2;
757 if( aProgressReporter )
763 std::vector<SCH_ITEM*> items;
766 std::vector<std::pair<SCH_SYMBOL*, int>> symbolsChanged;
768 for(
SCH_ITEM* item : sheet.LastScreen()->Items() )
770 if( item->IsConnectable() && ( aUnconditional || item->IsConnectivityDirty() ) )
772 wxLogTrace(
ConnTrace, wxT(
"Adding item %s to connectivity graph update" ),
773 item->GetTypeDesc() );
774 items.push_back( item );
775 dirty_items.insert( item );
784 if(
pin->IsConnectivityDirty() )
786 dirty_items.insert(
pin );
799 if(
pin->IsConnectivityDirty() )
801 items.push_back(
pin );
802 dirty_items.insert(
pin );
812 if(
pin->IsConnectivityDirty() )
814 items.push_back(
pin );
815 dirty_items.insert(
pin );
828 if( symbol->
GetUnit() != new_unit )
829 symbolsChanged.push_back( { symbol, symbol->
GetUnit() } );
831 symbol->SetUnit( new_unit );
839 if( aProgressReporter )
846 sheet.LastScreen()->TestDanglingEnds( &sheet, aChangedItemHandler );
849 for(
const auto& [ symbol, originalUnit ] : symbolsChanged )
850 symbol->SetUnit( originalUnit );
855 m_schematic->CurrentSheet().LastScreen()->TestDanglingEnds( &m_schematic->CurrentSheet(),
856 aChangedItemHandler );
859 item->SetConnectivityDirty(
false );
862 monitorTrans.FinishSpan();
866 PROF_TIMER build_graph(
"buildConnectionGraph" );
867 monitorTrans.StartSpan(
"BuildConnectionGraph",
"" );
869 buildConnectionGraph( aChangedItemHandler, aUnconditional );
874 monitorTrans.FinishSpan();
881 monitorTrans.Finish();
886 const std::set<SCH_ITEM*> &aItems )
888 std::set<std::pair<SCH_SHEET_PATH, SCH_ITEM*>> retvals;
889 std::set<CONNECTION_SUBGRAPH*> subgraphs;
894 while( aSubgraph->m_absorbed_by )
897 wxASSERT( aSubgraph->m_graph == aSubgraph->m_absorbed_by->m_graph );
898 aSubgraph = aSubgraph->m_absorbed_by;
902 while( aSubgraph->m_hier_parent )
905 wxASSERT( aSubgraph->m_graph == aSubgraph->m_hier_parent->m_graph );
906 aSubgraph = aSubgraph->m_hier_parent;
910 aSubgraph->getAllConnectedItems( retvals, subgraphs );
913 auto extract_element = [&](
SCH_ITEM* aItem )
919 wxLogTrace(
ConnTrace, wxT(
"Item %s not found in connection graph" ),
920 aItem->GetTypeDesc() );
926 wxLogTrace(
ConnTrace, wxT(
"Item %s in subgraph %ld (%p) has no driver" ),
927 aItem->GetTypeDesc(), item_sg->
m_code, item_sg );
932 if( sg_to_scan.empty() )
934 wxLogTrace(
ConnTrace, wxT(
"Item %s in subgraph %ld with net %s has no neighbors" ),
936 sg_to_scan.push_back( item_sg );
940 wxT(
"Removing all item %s connections from subgraph %ld with net %s: Found "
947 traverse_subgraph( sg );
949 for(
auto& bus_it : sg->m_bus_neighbors )
952 traverse_subgraph( bus_sg );
955 for(
auto& bus_it : sg->m_bus_parents )
958 traverse_subgraph( bus_sg );
972 extract_element(
pin );
979 extract_element(
pin );
983 extract_element( item );
989 for(
const auto& [
path, item] : retvals )
1016 wxLogTrace(
ConnTrace, wxT(
"Removing %zu subgraphs" ), aSubgraphs.size() );
1019 std::set<int> codes_to_remove;
1023 std::sort( el.second.begin(), el.second.end() );
1028 for(
auto& it : sg->m_bus_neighbors )
1034 for(
auto test = parents.begin();
test != parents.end(); )
1042 if( parents.empty() )
1047 for(
auto& it : sg->m_bus_parents )
1053 for(
auto test = neighbors.begin();
test != neighbors.end(); )
1061 if( neighbors.empty() )
1082 auto it = std::lower_bound( el.second.begin(), el.second.end(), sg );
1084 while( it != el.second.end() && *it == sg )
1085 it = el.second.erase( it );
1088 auto remove_sg = [sg](
auto it ) ->
bool
1101 if( remove_sg( it ) )
1109 if( remove_sg( it ) )
1118 if( remove_sg( it ) )
1120 codes_to_remove.insert( it->first.Netcode );
1132 if( remove_sg( it ) )
1140 if( it->second == sg )
1151 if( codes_to_remove.contains( it->second ) )
1159 if( codes_to_remove.contains( it->second ) )
1168 sg->m_graph =
nullptr;
1176 std::map<
VECTOR2I, std::vector<SCH_ITEM*>>& aConnectionMap )
1180 aConn->SetType( CONNECTION_TYPE::NET );
1186 aConn->SetName(
name );
1191 std::map<wxString, std::vector<SCH_PIN*>> pinNumberMap;
1197 updatePin(
pin, conn );
1198 aConnectionMap[
pin->GetPosition() ].push_back(
pin );
1199 pinNumberMap[
pin->GetNumber()].emplace_back(
pin );
1202 auto linkPinsInVec = [&](
const std::vector<SCH_PIN*>& aVec )
1204 for(
size_t i = 0; i < aVec.size(); ++i )
1206 for(
size_t j = i + 1; j < aVec.size(); ++j )
1208 aVec[i]->AddConnectionTo( aSheet, aVec[j] );
1209 aVec[j]->AddConnectionTo( aSheet, aVec[i] );
1218 for(
const auto& [number,
group] : pinNumberMap )
1219 linkPinsInVec(
group );
1224 std::vector<SCH_PIN*> pins;
1226 for(
const wxString& pinNumber :
group )
1227 pins.emplace_back( aSymbol->
GetPin( pinNumber ) );
1229 linkPinsInVec( pins );
1237 aConn->
SetType( CONNECTION_TYPE::NET );
1252 std::map<
VECTOR2I, std::vector<SCH_ITEM*>>& aConnectionMap )
1257 m_items.emplace_back( aItem );
1260 switch( aItem->
Type() )
1267 conn->
SetType( CONNECTION_TYPE::BUS );
1273 if( points.empty() )
1274 points = {
static_cast<SCH_PIN*
>( aItem )->GetPosition() };
1280 conn->
SetType( CONNECTION_TYPE::NET );
1287 for(
const VECTOR2I& point : points )
1288 aConnectionMap[point].push_back( aItem );
1293 const std::vector<SCH_ITEM*>& aItemList )
1295 wxLogTrace( wxT(
"Updating connectivity for sheet %s with %zu items" ),
1297 std::map<VECTOR2I, std::vector<SCH_ITEM*>> connection_map;
1301 std::vector<VECTOR2I> points = item->GetConnectionPoints();
1302 item->ClearConnectedItems( aSheet );
1308 pin->InitializeConnection( aSheet,
this );
1310 pin->ClearConnectedItems( aSheet );
1312 connection_map[
pin->GetTextPos() ].push_back(
pin );
1326 for(
const auto& it : connection_map )
1328 std::vector<SCH_ITEM*> connection_vec = it.second;
1329 std::sort( connection_vec.begin(), connection_vec.end() );
1335 for(
SCH_ITEM* connected_item : connection_vec )
1349 if( connection_vec.size() == 1 )
1366 if( it.first == bus_entry->GetPosition() )
1369 bus_entry->m_connected_bus_items[1] = busLine;
1383 for(
SCH_ITEM* test_item : connection_vec )
1385 bool bus_connection_ok =
true;
1387 if( test_item == connected_item )
1393 if( test_item->GetLayer() ==
LAYER_BUS )
1412 if( connected_item->ConnectionPropagatesTo( test_item ) &&
1413 test_item->ConnectionPropagatesTo( connected_item ) &&
1416 connected_item->AddConnectionTo( aSheet, test_item );
1427 if( !bus_entry->m_connected_bus_item )
1433 bus_entry->m_connected_bus_item = bus;
1444 wxCHECK_RET(
m_schematic, wxS(
"Connection graph cannot be built without schematic pointer" ) );
1450 for(
const std::shared_ptr<BUS_ALIAS>& alias : screen->GetBusAliases() )
1457 for(
const auto& it : item->m_connection_map )
1474 std::list<SCH_ITEM*> memberlist;
1479 SCH_CONNECTION* conn = aItem->GetOrInitConnection( sheet,
this );
1485 return ( unique && conn && ( conn->
SubgraphCode() == 0 ) );
1488 std::copy_if( item->ConnectedItems( sheet ).begin(),
1489 item->ConnectedItems( sheet ).end(),
1490 std::back_inserter( memberlist ), get_items );
1492 for(
SCH_ITEM* connected_item : memberlist )
1497 SCH_CONNECTION* connected_conn = connected_item->Connection( &sheet );
1499 wxCHECK2( connected_conn,
continue );
1505 subgraph->
AddItem( connected_item );
1506 const SCH_ITEM_VEC& citemset = connected_item->ConnectedItems( sheet );
1513 if( get_items( citem ) )
1514 memberlist.push_back( citem );
1519 for(
SCH_ITEM* connected_item : memberlist )
1534 std::vector<CONNECTION_SUBGRAPH*> dirty_graphs;
1539 return candidate->m_dirty;
1542 wxLogTrace(
ConnTrace, wxT(
"Resolving drivers for %zu subgraphs" ), dirty_graphs.size() );
1544 std::vector<std::future<size_t>> returns( dirty_graphs.size() );
1548 if( !subgraph->m_dirty )
1552 for(
SCH_ITEM* item : subgraph->m_items )
1554 switch( item->
Type() )
1557 subgraph->m_no_connect = item;
1561 subgraph->m_bus_entry = item;
1568 if(
pin->GetType() == ELECTRICAL_PINTYPE::PT_NC )
1569 subgraph->m_no_connect = item;
1579 subgraph->ResolveDrivers(
true );
1580 subgraph->m_dirty =
false;
1587 auto results =
tp.parallelize_loop( dirty_graphs.size(),
1588 [&](
const int a,
const int b)
1590 for( int ii = a; ii < b; ++ii )
1591 update_lambda( dirty_graphs[ii] );
1600 return candidate->m_driver;
1613 wxString full_name = subgraph->m_driver_connection->Name();
1614 wxString
name = subgraph->m_driver_connection->Name(
true );
1621 if( subgraph->m_driver_connection->Type() == CONNECTION_TYPE::BUS )
1623 wxString prefixOnly = full_name.BeforeFirst(
'[' ) + wxT(
"[]" );
1627 subgraph->m_dirty =
true;
1629 if( subgraph->m_strong_driver )
1631 SCH_ITEM* driver = subgraph->m_driver;
1634 switch( driver->
Type() )
1650 if(
pin->IsGlobalPower() )
1654 else if(
pin->IsLocalPower() )
1661 wxLogTrace(
ConnTrace, wxS(
"Unexpected normal pin %s" ),
1671 wxLogTrace(
ConnTrace, wxS(
"Unexpected strong driver %s" ),
1683 std::vector<CONNECTION_SUBGRAPH*> new_subgraphs;
1694 dummy.SetGraph(
this );
1697 wxLogTrace(
ConnTrace, wxS(
"new bus label (%s)" ),
1700 for(
const auto& conn :
dummy.Members() )
1702 wxString
name = conn->FullLocalName();
1712 new_conn->
SetType( CONNECTION_TYPE::NET );
1713 subgraph->StoreImplicitConnection( new_conn );
1716 wxLogTrace(
ConnTrace, wxS(
"SG(%ld), Adding full local name (%s) with sg (%d) "
1718 subgraph->m_code,
name, code, subgraph->m_sheet.PathHumanReadable() );
1731 new_subgraphs.push_back( new_sg );
1736 std::copy( new_subgraphs.begin(), new_subgraphs.end(),
1748 std::unordered_map<int, CONNECTION_SUBGRAPH*> global_power_pin_subgraphs;
1755 if( !
pin->ConnectedItems( sheet ).empty()
1756 && !
pin->GetLibPin()->GetParentSymbol()->IsGlobalPower() )
1771 if(
pin->GetLibPin()->GetParentSymbol()->IsGlobalPower() )
1772 connection->
SetName(
pin->GetParentSymbol()->GetValue(
true, &sheet,
false ) );
1781 auto jj = global_power_pin_subgraphs.find( code );
1783 if( jj != global_power_pin_subgraphs.end() )
1785 subgraph = jj->second;
1803 global_power_pin_subgraphs[code] = subgraph;
1820 std::unordered_set<CONNECTION_SUBGRAPH*> invalidated_subgraphs;
1824 if( subgraph->m_absorbed )
1829 wxString
name = connection->
Name();
1832 unsigned suffix = 1;
1834 auto create_new_name =
1838 wxString suffixStr = std::to_wstring( suffix );
1843 if( aConn->Type() == CONNECTION_TYPE::BUS_GROUP )
1845 wxString prefix = aConn->BusPrefix();
1847 if( prefix.empty() )
1848 prefix = wxT(
"BUS" );
1850 wxString oldName = aConn->Name().AfterFirst(
'{' );
1852 newName << prefix << wxT(
"_" ) << suffixStr << wxT(
"{" ) << oldName;
1854 aConn->ConfigureFromLabel( newName );
1858 newName << aConn->Name() << wxT(
"_" ) << suffixStr;
1859 aConn->SetSuffix( wxString( wxT(
"_" ) ) << suffixStr );
1866 if( !subgraph->m_strong_driver )
1868 std::vector<CONNECTION_SUBGRAPH*> vec_empty;
1869 std::vector<CONNECTION_SUBGRAPH*>* vec = &vec_empty;
1876 if( vec->size() <= 1 && subgraph->m_driver_connection->Type() == CONNECTION_TYPE::BUS )
1878 wxString prefixOnly =
name.BeforeFirst(
'[' ) + wxT(
"[]" );
1884 if( vec->size() > 1 )
1886 wxString new_name = create_new_name( connection );
1889 new_name = create_new_name( connection );
1892 wxS(
"%ld (%s) is weakly driven and not unique. Changing to %s." ),
1893 subgraph->m_code,
name, new_name );
1895 std::erase( *vec, subgraph );
1901 else if( subgraph->m_driver )
1913 bool conflict =
false;
1914 wxString global_name = connection->
Name(
true );
1921 std::vector<CONNECTION_SUBGRAPH*>& candidates = kk->second;
1925 if( candidate->m_sheet == sheet )
1933 wxS(
"%ld (%s) skipped for promotion due to potential "
1935 subgraph->m_code,
name );
1942 wxS(
"%ld (%s) weakly driven by unique sheet pin %s, "
1944 subgraph->m_code,
name,
1945 subgraph->m_driver->GetItemDescription( &unitsProvider,
1948 subgraph->m_strong_driver =
true;
1955 if( connection->
IsBus() )
1979 subgraph->m_dirty =
true;
1987 if( !subgraph->m_strong_driver )
1994 std::vector<CONNECTION_SUBGRAPH*> candidate_subgraphs;
1997 std::back_inserter( candidate_subgraphs ),
2000 return ( !candidate->m_absorbed &&
2001 candidate->m_strong_driver &&
2002 candidate != subgraph );
2008 std::vector< std::shared_ptr<SCH_CONNECTION> > connections_to_check;
2011 connections_to_check.push_back( std::make_shared<SCH_CONNECTION>( *connection ) );
2013 auto add_connections_to_check =
2016 for(
SCH_ITEM* possible_driver : aSubgraph->m_items )
2018 if( possible_driver == aSubgraph->m_driver )
2025 if( c->Type() != aSubgraph->m_driver_connection->Type() )
2028 if( c->Name(
true ) == aSubgraph->m_driver_connection->Name(
true ) )
2031 connections_to_check.push_back( c );
2033 wxS(
"%lu (%s): Adding secondary driver %s" ),
2035 aSubgraph->m_driver_connection->Name(
true ),
2044 add_connections_to_check( subgraph );
2046 std::set<SCH_CONNECTION*> checked_connections;
2048 for(
unsigned i = 0; i < connections_to_check.size(); i++ )
2050 auto member = connections_to_check[i];
2053 if( !checked_connections.insert( member.get() ).second )
2056 if( member->IsBus() )
2058 connections_to_check.insert( connections_to_check.end(),
2059 member->Members().begin(),
2060 member->Members().end() );
2063 wxString test_name = member->Name(
true );
2067 if( candidate->
m_absorbed || candidate == subgraph )
2083 if( driver == candidate->
m_driver )
2095 &&
pin->GetDefaultNetName( sheet ) == test_name )
2108 if( subgraph->GetNameForDriver( driver ) == test_name )
2121 wxLogTrace(
ConnTrace, wxS(
"%lu (%s) has bus child %lu (%s)" ),
2122 subgraph->m_code, connection->
Name(),
2123 candidate->
m_code, member->Name() );
2125 subgraph->m_bus_neighbors[member].insert( candidate );
2128 else if( !connection->
IsBus()
2131 wxLogTrace(
ConnTrace, wxS(
"%lu (%s) absorbs neighbor %lu (%s)" ),
2132 subgraph->m_code, connection->
Name(),
2136 add_connections_to_check( candidate );
2138 subgraph->Absorb( candidate );
2139 invalidated_subgraphs.insert( subgraph );
2149 if( subgraph->m_absorbed )
2152 if( !subgraph->ResolveDrivers() )
2155 if( subgraph->m_driver_connection->IsBus() )
2160 wxLogTrace(
ConnTrace, wxS(
"Re-resolving drivers for %lu (%s)" ), subgraph->m_code,
2161 subgraph->m_driver_connection->Name() );
2180 bool aUnconditional )
2183 wxCHECK_RET(
m_schematic, wxT(
"Connection graph cannot be built without schematic pointer" ) );
2189 for(
const std::shared_ptr<BUS_ALIAS>& alias : screen->GetBusAliases() )
2193 PROF_TIMER sub_graph(
"buildItemSubGraphs" );
2212 PROF_TIMER proc_sub_graph(
"ProcessSubGraphs" );
2216 proc_sub_graph.
Show();
2225 std::vector<CONNECTION_SUBGRAPH*> global_subgraphs;
2227 std::back_inserter( global_subgraphs ),
2230 return !candidate->m_local_driver;
2242 [&](
const int a,
const int b)
2244 for( int ii = a; ii < b; ++ii )
2245 m_driver_subgraphs[ii]->UpdateItemConnections();
2255 if( !subgraph->m_dirty )
2258 wxLogTrace(
ConnTrace, wxS(
"Processing %lu (%s) for propagation" ), subgraph->m_code,
2259 subgraph->m_driver_connection->Name() );
2265 if( !subgraph->m_local_driver && subgraph->m_multiple_drivers )
2267 for(
SCH_ITEM* driver : subgraph->m_drivers )
2269 if( driver == subgraph->m_driver )
2272 const wxString& secondary_name = subgraph->GetNameForDriver( driver );
2274 if( secondary_name == subgraph->m_driver_connection->Name() )
2282 if( candidate == subgraph )
2285 if( !secondary_is_global && candidate->
m_sheet != subgraph->m_sheet )
2292 wxLogTrace(
ConnTrace, wxS(
"Global %lu (%s) promoted to %s" ),
2294 subgraph->m_driver_connection->Name() );
2316 if( subgraph->m_dirty )
2333 wxASSERT_MSG( !subgraph->m_dirty,
2334 wxS(
"Subgraph not processed by propagateToNeighbors!" ) );
2336 if( subgraph->m_bus_parents.size() < 2 )
2341 wxLogTrace(
ConnTrace, wxS(
"%lu (%s) has multiple bus parents" ),
2342 subgraph->m_code, conn->
Name() );
2345 wxCHECK2( conn->
IsNet(),
continue );
2347 for(
const auto& ii : subgraph->m_bus_parents )
2360 wxLogTrace(
ConnTrace, wxS(
"Warning: could not match %s inside %lu (%s)" ),
2365 if( conn->
Name() != match->
Name() )
2367 wxString old_name = match->
Name();
2369 wxLogTrace(
ConnTrace, wxS(
"Updating %lu (%s) member %s to %s" ),
2371 old_name, conn->
Name() );
2373 match->
Clone( *conn );
2392 auto updateItemConnectionsTask =
2396 if( !subgraph->m_strong_driver && subgraph->m_drivers.size() == 1 &&
2397 subgraph->m_driver->Type() ==
SCH_PIN_T )
2400 wxString
name =
pin->GetDefaultNetName( subgraph->m_sheet,
true );
2402 subgraph->m_driver_connection->ConfigureFromLabel(
name );
2405 subgraph->m_dirty =
false;
2406 subgraph->UpdateItemConnections();
2409 if( subgraph->m_driver_connection->IsBus() )
2414 if( subgraph->m_driver && subgraph->m_driver->Type() ==
SCH_SHEET_PIN_T )
2420 wxString pinText =
pin->GetShownText(
false );
2427 if( label->
GetShownText( &subgraph->m_sheet,
false ) == pinText )
2430 path.push_back( sheet );
2434 if( parent_conn && parent_conn->
IsBus() )
2435 subgraph->m_driver_connection->
SetType( CONNECTION_TYPE::BUS );
2441 if( subgraph->m_driver_connection->IsBus() )
2450 [&](
const int a,
const int b)
2452 for(
int ii = a; ii < b; ++ii )
2463 subgraph->m_driver_connection->NetCode() };
2470 std::map<wxString, std::set<wxString>> oldAssignments =
2471 netSettings->GetNetclassLabelAssignments();
2472 std::set<wxString> affectedNetclassNetAssignments;
2474 netSettings->ClearNetclassLabelAssignments();
2476 auto dirtySubgraphs =
2477 [&](
const std::vector<CONNECTION_SUBGRAPH*>& subgraphs )
2479 if( aChangedItemHandler )
2483 for(
SCH_ITEM* item : subgraph->m_items )
2484 (*aChangedItemHandler)( item );
2489 auto checkNetclassDrivers =
2490 [&](
const wxString& netName,
const std::vector<CONNECTION_SUBGRAPH*>& subgraphs )
2492 wxCHECK_RET( !subgraphs.empty(), wxS(
"Invalid empty subgraph" ) );
2494 std::set<wxString> netclasses;
2499 for(
SCH_ITEM* item : subgraph->m_items )
2501 std::vector<std::pair<wxString, SCH_ITEM*>> netclassesWithProviders =
2502 subgraph->GetNetclassesForDriver( item );
2504 for( std::pair<wxString, SCH_ITEM*>& ncPair : netclassesWithProviders )
2505 netclasses.insert( std::move( ncPair.first ) );
2512 if( subgraph->m_driver_connection->IsBus() )
2514 auto processBusMember = [&,
this](
const SCH_CONNECTION* member )
2516 if( !netclasses.empty() )
2518 netSettings->AppendNetclassLabelAssignment( member->Name(), netclasses );
2523 if( oldAssignments.count( member->Name() ) )
2525 if( oldAssignments[member->Name()] != netclasses )
2527 affectedNetclassNetAssignments.insert( member->Name() );
2530 dirtySubgraphs( ii->second );
2533 else if( !netclasses.empty() )
2535 affectedNetclassNetAssignments.insert( member->Name() );
2538 dirtySubgraphs( ii->second );
2542 for(
const std::shared_ptr<SCH_CONNECTION>& member :
2543 subgraph->m_driver_connection->Members() )
2548 if( member->IsBus() )
2550 for(
const std::shared_ptr<SCH_CONNECTION>& nestedMember :
2553 processBusMember( nestedMember.get() );
2558 processBusMember( member.get() );
2565 if( !netclasses.empty() )
2567 netSettings->AppendNetclassLabelAssignment( netName, netclasses );
2570 if( oldAssignments.count( netName ) )
2572 if( oldAssignments[netName] != netclasses )
2574 affectedNetclassNetAssignments.insert( netName );
2575 dirtySubgraphs( subgraphs );
2578 else if( !netclasses.empty() )
2580 affectedNetclassNetAssignments.insert( netName );
2581 dirtySubgraphs( subgraphs );
2587 checkNetclassDrivers( netname, subgraphs );
2589 if( !aUnconditional )
2591 for(
auto& [netname, netclasses] : oldAssignments )
2593 if( netSettings->GetNetclassLabelAssignments().count( netname )
2594 || affectedNetclassNetAssignments.count( netname ) )
2599 netSettings->SetNetclassLabelAssignment( netname, netclasses );
2637 std::vector<std::shared_ptr<SCH_CONNECTION>> connections_to_check( aConnection->
Members() );
2639 for(
unsigned i = 0; i < connections_to_check.size(); i++ )
2641 const std::shared_ptr<SCH_CONNECTION>& member = connections_to_check[i];
2643 if( member->IsBus() )
2645 connections_to_check.insert( connections_to_check.end(),
2646 member->Members().begin(),
2647 member->Members().end() );
2659 std::vector<CONNECTION_SUBGRAPH*> search_list;
2660 std::unordered_set<CONNECTION_SUBGRAPH*> visited;
2661 std::unordered_set<SCH_CONNECTION*> stale_bus_members;
2668 path.push_back(
pin->GetParent() );
2679 || visited.contains( candidate ) )
2688 wxLogTrace(
ConnTrace, wxS(
"%lu: found child %lu (%s)" ), aParent->m_code,
2696 wxASSERT( candidate->
m_graph == aParent->m_graph );
2698 search_list.push_back( candidate );
2718 || visited.contains( candidate )
2724 const KIID& last_parent_uuid = aParent->m_sheet.Last()->m_Uuid;
2729 if(
pin->GetParent()->m_Uuid != last_parent_uuid )
2735 if( pin_path != aParent->m_sheet )
2740 wxLogTrace(
ConnTrace, wxS(
"%lu: found additional parent %lu (%s)" ),
2741 aParent->m_code, candidate->
m_code,
2744 aParent->m_hier_children.insert( candidate );
2745 search_list.push_back( candidate );
2755 for(
const auto&
kv : aParentGraph->m_bus_neighbors )
2797 wxLogTrace(
ConnTrace, wxS(
"Could not match bus member %s in %s" ),
2798 kv.first->Name(), parent->
Name() );
2804 wxCHECK2( neighbor_conn,
continue );
2806 wxString neighbor_name = neighbor_conn->
Name();
2809 if( neighbor_name == member->
Name() )
2817 wxCHECK2_MSG( neighbor_conn->
IsNet(),
continue,
2818 wxS(
"\"" ) + neighbor_name + wxS(
"\" is not a net." ) );
2820 wxLogTrace(
ConnTrace, wxS(
"%lu (%s) connected to bus member %s (local %s)" ),
2827 member->
Clone( *neighbor_conn );
2828 stale_bus_members.insert( member );
2832 neighbor_conn->
Clone( *member );
2846 propagate_bus_neighbors( aSubgraph );
2853 wxLogTrace(
ConnTrace, wxS(
"%lu (%s) has both hier ports and pins; deferring processing" ),
2860 wxS(
"%lu (%s) has no hier pins or ports on sheet %s; marking clean" ),
2866 visited.insert( aSubgraph );
2868 wxLogTrace(
ConnTrace, wxS(
"Propagating %lu (%s) to subsheets" ),
2873 for(
unsigned i = 0; i < search_list.size(); i++ )
2875 auto child = search_list[i];
2877 if( visited.insert( child ).second )
2880 child->m_dirty =
false;
2895 if( subgraph == aSubgraph )
2902 wxString candidateName = subgraph->m_driver_connection->Name();
2903 bool shorterPath = subgraph->m_sheet.size() < bestDriver->
m_sheet.
size();
2904 bool asGoodPath = subgraph->m_sheet.size() <= bestDriver->
m_sheet.
size();
2914 ( !bestIsStrong && candidateStrong ) ||
2915 ( priority > highest && candidateStrong ) ||
2916 ( priority == highest && candidateStrong && shorterPath ) ||
2917 ( ( bestIsStrong == candidateStrong ) && asGoodPath && ( priority == highest ) &&
2918 ( candidateName < bestName ) ) )
2920 bestDriver = subgraph;
2922 bestIsStrong = candidateStrong;
2923 bestName = candidateName;
2928 if( bestDriver != aSubgraph )
2930 wxLogTrace(
ConnTrace, wxS(
"%lu (%s) overridden by new driver %lu (%s)" ),
2939 wxString old_name = subgraph->m_driver_connection->
Name();
2941 subgraph->m_driver_connection->Clone( *conn );
2943 if( old_name != conn->
Name() )
2947 propagate_bus_neighbors( subgraph );
2953 if( conn->
IsBus() && !stale_bus_members.empty() )
2955 std::unordered_set<SCH_CONNECTION*> cached_members = stale_bus_members;
2966 wxLogTrace(
ConnTrace, wxS(
"WARNING: failed to match stale member %s in %s." ),
2967 stale_member->Name(), subgraph->m_driver_connection->Name() );
2971 wxLogTrace(
ConnTrace, wxS(
"Updating %lu (%s) member %s to %s" ), subgraph->m_code,
2972 subgraph->m_driver_connection->Name(), member->
LocalName(),
2973 stale_member->Name() );
2975 member->
Clone( *stale_member );
2977 propagate_bus_neighbors( subgraph );
2989 std::shared_ptr<SCH_CONNECTION> c = std::shared_ptr<SCH_CONNECTION>(
nullptr );
2991 switch( aItem->
Type() )
2997 if(
pin->IsPower() )
2998 c = std::make_shared<SCH_CONNECTION>( aItem, aSubgraph->
m_sheet );
3007 c = std::make_shared<SCH_CONNECTION>( aItem, aSubgraph->
m_sheet );
3017 c->SetGraph(
this );
3029 wxASSERT( aBusConnection->
IsBus() );
3033 if( aBusConnection->
Type() == CONNECTION_TYPE::BUS )
3038 for(
const std::shared_ptr<SCH_CONNECTION>& bus_member : aBusConnection->
Members() )
3040 if( bus_member->VectorIndex() == aSearch->
VectorIndex() )
3042 match = bus_member.get();
3050 for(
const std::shared_ptr<SCH_CONNECTION>& c : aBusConnection->
Members() )
3055 if( c->Type() == CONNECTION_TYPE::BUS )
3057 for(
const std::shared_ptr<SCH_CONNECTION>& bus_member : c->Members() )
3059 if( bus_member->LocalName() == aSearch->
LocalName() )
3061 match = bus_member.get();
3066 else if( c->LocalName() == aSearch->
LocalName() )
3079 const wxString& aOldName )
3085 std::vector<CONNECTION_SUBGRAPH*>& vec = it->second;
3086 std::erase( vec, aSubgraph );
3089 wxLogTrace(
ConnTrace, wxS(
"recacheSubgraphName: %s => %s" ), aOldName,
3106 std::vector<const CONNECTION_SUBGRAPH*> ret;
3112 wxASSERT( !subgraph->m_dirty );
3114 if( !subgraph->m_driver )
3120 if( !connection->
IsBus() )
3123 auto labels = subgraph->GetVectorBusLabels();
3125 if( labels.size() > 1 )
3127 bool different =
false;
3128 wxString first =
static_cast<SCH_TEXT*
>( labels.at( 0 ) )->GetShownText( sheet,
false );
3130 for(
unsigned i = 1; i < labels.size(); ++i )
3143 wxLogTrace(
ConnTrace, wxS(
"SG %ld (%s) has multiple bus labels" ), subgraph->m_code,
3144 connection->
Name() );
3146 ret.push_back( subgraph );
3167 if( graph == aSubGraph )
3210 wxASSERT( !it->second.empty() );
3212 return it->second[0];
3228const std::vector<CONNECTION_SUBGRAPH*>&
3231 static const std::vector<CONNECTION_SUBGRAPH*> subgraphs;
3244 int error_count = 0;
3246 wxCHECK_MSG(
m_schematic,
true, wxS(
"Null m_schematic in CONNECTION_GRAPH::RunERC" ) );
3252 std::set<SCH_ITEM*> seenDriverInstances;
3257 wxCHECK2( subgraph,
continue );
3261 wxASSERT( !subgraph->m_dirty );
3263 if( subgraph->m_absorbed )
3266 if( seenDriverInstances.count( subgraph->m_driver ) )
3269 if( subgraph->m_driver )
3270 seenDriverInstances.insert( subgraph->m_driver );
3288 subgraph->ResolveDrivers(
false );
3359 wxCHECK( aSubgraph,
false );
3365 if( driver == aSubgraph->
m_driver )
3377 if( primaryName == secondaryName )
3380 wxString msg = wxString::Format(
_(
"Both %s and %s are attached to the same "
3381 "items; %s will be used in the netlist" ),
3382 primaryName, secondaryName, primaryName );
3385 ercItem->SetItems( aSubgraph->
m_driver, driver );
3386 ercItem->SetSheetSpecificPath( aSubgraph->
GetSheet() );
3387 ercItem->SetItemsSheetPaths( aSubgraph->
GetSheet(), aSubgraph->
m_sheet );
3388 ercItem->SetErrorMessage( msg );
3413 switch( item->
Type() )
3418 bus_item = ( !bus_item ) ? item : bus_item;
3420 net_item = ( !net_item ) ? item : net_item;
3435 bus_item = ( !bus_item ) ? item : bus_item;
3437 net_item = ( !net_item ) ? item : net_item;
3447 if( net_item && bus_item )
3450 ercItem->SetSheetSpecificPath( sheet );
3451 ercItem->SetItems( net_item, bus_item );
3454 screen->
Append( marker );
3473 switch( item->
Type() )
3504 if(
test != member && member->Name() ==
test->Name() )
3518 ercItem->SetSheetSpecificPath( sheet );
3519 ercItem->SetItems( label, port );
3522 screen->
Append( marker );
3534 bool conflict =
false;
3550 switch( item->
Type() )
3581 std::set<wxString> test_names;
3591 if( member->Type() == CONNECTION_TYPE::BUS )
3593 for(
const auto& sub_member : member->Members() )
3595 if( test_names.count( sub_member->FullLocalName() ) )
3599 else if( test_names.count( member->FullLocalName() ) )
3618 wxString msg = wxString::Format(
_(
"Net %s is graphically connected to bus %s but is not a"
3619 " member of that bus" ),
3623 ercItem->SetSheetSpecificPath( sheet );
3624 ercItem->SetItems( bus_entry, bus_wire );
3625 ercItem->SetErrorMessage( msg );
3628 screen->
Append( marker );
3645 std::set<SCH_PIN*> unique_pins;
3646 std::set<SCH_LABEL_BASE*> unique_labels;
3654 for(
SCH_ITEM* item : aProcessGraph->m_items )
3656 switch( item->
Type() )
3663 if( aProcessGraph == aSubgraph )
3666 if( std::none_of( unique_pins.begin(), unique_pins.end(),
3673 unique_pins.insert( test_pin );
3696 process_subgraph( subgraph );
3701 process_subgraph( aSubgraph );
3729 if( test_pin && test_pin->
GetType() == ELECTRICAL_PINTYPE::PT_NC )
3736 ercItem->SetSheetSpecificPath( sheet );
3737 ercItem->SetItemsSheetPaths( sheet );
3744 pos =
pin->GetPosition();
3753 screen->
Append( marker );
3758 if( unique_pins.empty() && unique_labels.empty() &&
3763 ercItem->SetSheetSpecificPath( sheet );
3764 ercItem->SetItemsSheetPaths( sheet );
3767 screen->
Append( marker );
3774 bool has_other_connections =
false;
3775 std::vector<SCH_PIN*> pins;
3782 switch( item->
Type() )
3789 if( !has_other_connections && !pins.empty()
3792 for(
SCH_PIN* other_pin : pins )
3796 has_other_connections =
true;
3802 pins.emplace_back(
static_cast<SCH_PIN*
>( item ) );
3809 has_other_connections =
true;
3816 pin = pins.empty() ? nullptr : pins[0];
3819 for(
SCH_PIN* test_pin : pins )
3824 if( test_pin->GetType() == ELECTRICAL_PINTYPE::PT_POWER_IN
3825 && !test_pin->IsPower() )
3836 if(
pin && !has_other_connections
3838 && !
pin->GetLibPin()->GetParentSymbol()->IsPower() )
3840 wxString
name =
pin->Connection( &sheet )->Name();
3841 wxString local_name =
pin->Connection( &sheet )->Name(
true );
3846 has_other_connections =
true;
3851 if(
pin && !has_other_connections
3852 &&
pin->GetType() != ELECTRICAL_PINTYPE::PT_NC
3853 &&
pin->GetType() != ELECTRICAL_PINTYPE::PT_NIC
3857 ercItem->SetSheetSpecificPath( sheet );
3858 ercItem->SetItemsSheetPaths( sheet );
3859 ercItem->SetItems(
pin );
3862 screen->
Append( marker );
3870 if( pins.size() > 1 )
3872 for(
SCH_PIN* testPin : pins )
3877 if( testPin->GetLibPin()->GetParentSymbol()->IsPower()
3878 && testPin->ConnectedItems( sheet ).empty()
3882 ercItem->SetSheetSpecificPath( sheet );
3883 ercItem->SetItemsSheetPaths( sheet );
3884 ercItem->SetItems( testPin );
3887 screen->
Append( marker );
3918 std::shared_ptr<ERC_ITEM> ercItem =
3921 ercItem->SetItems( line );
3922 ercItem->SetSheetSpecificPath( sheet );
3923 ercItem->SetErrorMessage(
_(
"Unconnected wire endpoint" ) );
3943 std::shared_ptr<ERC_ITEM> ercItem =
3946 ercItem->SetItems( entry );
3947 ercItem->SetSheetSpecificPath( sheet );
3948 ercItem->SetErrorMessage(
_(
"Unconnected wire to bus entry" ) );
3965 return err_count > 0;
3975 std::vector<SCH_ITEM*> wires;
3982 wires.emplace_back( item );
3984 wires.emplace_back( item );
3987 if( !wires.empty() )
3992 ercItem->SetSheetSpecificPath( sheet );
3993 ercItem->SetItems( wires[0],
3994 wires.size() > 1 ? wires[1] :
nullptr,
3995 wires.size() > 2 ? wires[2] :
nullptr,
3996 wires.size() > 3 ? wires[3] :
nullptr );
3999 screen->
Append( marker );
4027 size_t pinCount = 0;
4030 std::map<KICAD_T, std::vector<SCH_TEXT*>> label_map;
4036 return std::count_if( aLocSubgraph->m_items.begin(), aLocSubgraph->m_items.end(),
4039 return item->Type() == SCH_PIN_T;
4044 [&](
SCH_TEXT* aText,
int errCode )
4049 ercItem->SetSheetSpecificPath( sheet );
4050 ercItem->SetItems( aText );
4057 pinCount =
hasPins( aSubgraph );
4061 switch( item->
Type() )
4069 label_map[item->
Type()].push_back(
text );
4074 if(
text->IsDangling() )
4088 if( label_map.empty() )
4093 for(
auto& [ connection, subgraphs ] : aSubgraph->
m_bus_parents )
4097 if( busParent->m_no_connect )
4120 wxCHECK_MSG(
m_schematic,
true, wxS(
"Null m_schematic in CONNECTION_GRAPH::ercCheckLabels" ) );
4127 for(
auto& [type, label_vec] : label_map )
4131 size_t allPins = pinCount;
4139 if( neighbor == aSubgraph )
4145 allPins +=
hasPins( neighbor );
4149 if( allPins == 1 && !has_nc )
4171 std::map<wxString, std::tuple<int, const SCH_ITEM*, SCH_SHEET_PATH>> labelData;
4178 wxString resolvedLabelText =
4181 if( labelData.find( resolvedLabelText ) == labelData.end() )
4183 labelData[resolvedLabelText] = { 1, item, sheet };
4187 std::get<0>( labelData[resolvedLabelText] ) += 1;
4188 std::get<1>( labelData[resolvedLabelText] ) =
nullptr;
4189 std::get<2>( labelData[resolvedLabelText] ) = sheet;
4194 for(
const auto& label : labelData )
4196 if( std::get<0>( label.second ) == 1 )
4199 const SCH_ITEM* item = std::get<1>( label.second );
4202 ercItem->SetItems( std::get<1>( label.second ) );
4203 ercItem->SetSheetSpecificPath( sheet );
4204 ercItem->SetItemsSheetPaths( sheet );
4219 int error_count = 0;
4231 ercItem->SetSheetSpecificPath( sheet );
4232 ercItem->SetItems(
text );
4235 sheet.LastScreen()->Append( marker );
4255 if( sheet.Last()->IsRootSheet() )
4261 wxCHECK2( label,
continue );
4264 _(
"Hierarchical label '%s' in root sheet cannot be connected to non-existent parent sheet" ),
4267 ercItem->SetItems( item );
4268 ercItem->SetErrorMessage( msg );
4271 sheet.LastScreen()->Append( marker );
4282 parentSheetPath.
push_back( parentSheet );
4284 std::map<wxString, SCH_SHEET_PIN*> pins;
4285 std::map<wxString, SCH_HIERLABEL*> labels;
4290 pins[
pin->GetShownText( &parentSheetPath,
false ) ] =
pin;
4295 ercItem->SetItems(
pin );
4296 ercItem->SetSheetSpecificPath( sheet );
4297 ercItem->SetItemsSheetPaths( sheet );
4300 sheet.LastScreen()->Append( marker );
4308 std::set<wxString> matchedPins;
4315 wxString labelText = label->
GetShownText( &parentSheetPath,
false );
4317 if( !pins.count( labelText ) )
4318 labels[ labelText ] = label;
4320 matchedPins.insert( labelText );
4324 for(
const wxString& matched : matchedPins )
4325 pins.erase( matched );
4327 for(
const std::pair<const wxString, SCH_SHEET_PIN*>& unmatched : pins )
4329 msg.Printf(
_(
"Sheet pin %s has no matching hierarchical label inside the sheet" ),
4333 ercItem->SetItems( unmatched.second );
4334 ercItem->SetErrorMessage( msg );
4335 ercItem->SetSheetSpecificPath( sheet );
4336 ercItem->SetItemsSheetPaths( sheet );
4339 unmatched.second->GetPosition() );
4340 sheet.LastScreen()->Append( marker );
4345 for(
const std::pair<const wxString, SCH_HIERLABEL*>& unmatched : labels )
4347 msg.Printf(
_(
"Hierarchical label %s has no matching sheet pin in the parent sheet" ),
4351 ercItem->SetItems( unmatched.second );
4352 ercItem->SetErrorMessage( msg );
4353 ercItem->SetSheetSpecificPath( parentSheetPath );
4354 ercItem->SetItemsSheetPaths( parentSheetPath );
4357 unmatched.second->GetPosition() );
constexpr EDA_IU_SCALE schIUScale
This represents a sentry transaction which is used for time-performance metrics You start a transacti...
void StartSpan(const std::string &aOperation, const std::string &aDescription)
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.
void updateGenericItemConnectivity(const SCH_SHEET_PATH &aSheet, SCH_ITEM *aItem, std::map< VECTOR2I, std::vector< SCH_ITEM * > > &aConnectionMap)
Update the connectivity of items that are not pins or symbols.
std::unordered_map< SCH_SHEET_PATH, std::vector< CONNECTION_SUBGRAPH * > > m_sheet_to_subgraphs_map
Cache to lookup subgraphs in m_driver_subgraphs by sheet path.
void updateSymbolConnectivity(const SCH_SHEET_PATH &aSheet, SCH_SYMBOL *aSymbol, std::map< VECTOR2I, std::vector< SCH_ITEM * > > &aConnectionMap)
Update the connectivity of a symbol and its pins.
CONNECTION_SUBGRAPH * FindFirstSubgraphByName(const wxString &aNetName)
Retrieve a subgraph for the given net name, if one exists.
void propagateToNeighbors(CONNECTION_SUBGRAPH *aSubgraph, bool aForce)
Update all neighbors of a subgraph with this one's connectivity info.
void buildItemSubGraphs()
Generate individual item subgraphs on a per-sheet basis.
const std::vector< CONNECTION_SUBGRAPH * > & GetAllSubgraphs(const wxString &aNetName) const
bool ercCheckMultipleDrivers(const CONNECTION_SUBGRAPH *aSubgraph)
If the subgraph has multiple drivers of equal priority that are graphically connected,...
SCH_SHEET_LIST m_sheetList
All the sheets in the schematic (as long as we don't have partial updates).
void generateGlobalPowerPinSubGraphs()
Iterate through the global power pins to collect the global labels as drivers.
std::unordered_map< wxString, int > m_net_name_to_code_map
int ercCheckSingleGlobalLabel()
Check that a global label is instantiated more that once across the schematic hierarchy.
int ercCheckHierSheets()
Check that a hierarchical sheet has at least one matching label inside the sheet for each port on the...
bool ercCheckBusToNetConflicts(const CONNECTION_SUBGRAPH *aSubgraph)
Check one subgraph for conflicting connections between net and bus labels.
std::shared_ptr< SCH_CONNECTION > getDefaultConnection(SCH_ITEM *aItem, CONNECTION_SUBGRAPH *aSubgraph)
Build a new default connection for the given item based on its properties.
std::vector< const CONNECTION_SUBGRAPH * > GetBusesNeedingMigration()
Determine which subgraphs have more than one conflicting bus label.
void Recalculate(const SCH_SHEET_LIST &aSheetList, bool aUnconditional=false, std::function< void(SCH_ITEM *)> *aChangedItemHandler=nullptr, PROGRESS_REPORTER *aProgressReporter=nullptr)
Update the connection graph for the given list of sheets.
int assignNewNetCode(SCH_CONNECTION &aConnection)
Helper to assign a new net code to a connection.
std::map< std::pair< SCH_SHEET_PATH, wxString >, std::vector< const CONNECTION_SUBGRAPH * > > m_local_label_cache
int getOrCreateNetCode(const wxString &aNetName)
bool ercCheckDanglingWireEndpoints(const CONNECTION_SUBGRAPH *aSubgraph)
Check one subgraph for dangling wire endpoints.
void assignNetCodesToBus(SCH_CONNECTION *aConnection)
Ensure all members of the bus connection have a valid net code assigned.
std::unordered_map< wxString, int > m_bus_name_to_code_map
std::unordered_map< wxString, std::vector< const CONNECTION_SUBGRAPH * > > m_global_label_cache
std::vector< CONNECTION_SUBGRAPH * > m_subgraphs
The owner of all CONNECTION_SUBGRAPH objects.
std::vector< std::pair< SCH_SHEET_PATH, SCH_PIN * > > m_global_power_pins
bool ercCheckNoConnects(const CONNECTION_SUBGRAPH *aSubgraph)
Check one subgraph for proper presence or absence of no-connect symbols.
size_t hasPins(const CONNECTION_SUBGRAPH *aLocSubgraph)
Get the number of pins in a given subgraph.
std::vector< SCH_ITEM * > m_items
All connectable items in the schematic.
std::unordered_map< wxString, std::vector< CONNECTION_SUBGRAPH * > > m_net_name_to_subgraphs_map
std::shared_ptr< BUS_ALIAS > GetBusAlias(const wxString &aName)
Return a bus alias pointer for the given name if it exists (from cache)
void removeSubgraphs(std::set< CONNECTION_SUBGRAPH * > &aSubgraphs)
Remove references to the given subgraphs from all structures in the connection graph.
std::unordered_map< SCH_ITEM *, CONNECTION_SUBGRAPH * > m_item_to_subgraph_map
std::set< std::pair< SCH_SHEET_PATH, SCH_ITEM * > > ExtractAffectedItems(const std::set< SCH_ITEM * > &aItems)
For a set of items, this will remove the connected items and their associated data including subgraph...
wxString GetResolvedSubgraphName(const CONNECTION_SUBGRAPH *aSubGraph) const
Return the fully-resolved netname for a given subgraph.
bool ercCheckBusToBusEntryConflicts(const CONNECTION_SUBGRAPH *aSubgraph)
Check one subgraph for conflicting bus entry to bus connections.
std::vector< CONNECTION_SUBGRAPH * > m_driver_subgraphs
Cache of a subset of m_subgraphs.
void ExchangeItem(SCH_ITEM *aOldItem, SCH_ITEM *aNewItem)
Replace all references to #aOldItem with #aNewItem in the graph.
NET_MAP m_net_code_to_subgraphs_map
bool ercCheckFloatingWires(const CONNECTION_SUBGRAPH *aSubgraph)
Check one subgraph for floating wires.
void buildConnectionGraph(std::function< void(SCH_ITEM *)> *aChangedItemHandler, bool aUnconditional)
Generate the connection graph (after all item connectivity has been updated).
void Merge(CONNECTION_GRAPH &aGraph)
Combine the input graph contents into the current graph.
void updatePinConnectivity(const SCH_SHEET_PATH &aSheet, SCH_PIN *aPin, SCH_CONNECTION *aConnection)
Update the connectivity of a pin and its connections.
void resolveAllDrivers()
Find all subgraphs in the connection graph and calls ResolveDrivers() in parallel.
void updateItemConnectivity(const SCH_SHEET_PATH &aSheet, const std::vector< SCH_ITEM * > &aItemList)
Update the graphical connectivity between items (i.e.
CONNECTION_SUBGRAPH * GetSubgraphForItem(SCH_ITEM *aItem) const
void generateBusAliasMembers()
Iterate through labels to create placeholders for bus elements.
A subgraph is a set of items that are electrically connected on a single sheet.
wxString driverName(SCH_ITEM *aItem) const
PRIORITY GetDriverPriority()
bool m_strong_driver
True if the driver is "strong": a label or power object.
SCH_ITEM * m_no_connect
No-connect item in graph, if any.
std::set< CONNECTION_SUBGRAPH * > m_absorbed_subgraphs
Set of subgraphs that have been absorbed by this subgraph.
static PRIORITY GetDriverPriority(SCH_ITEM *aDriver)
Return the priority (higher is more important) of a candidate driver.
std::mutex m_driver_name_cache_mutex
A cache of escaped netnames from schematic items.
SCH_SHEET_PATH m_sheet
On which logical sheet is the subgraph contained.
void UpdateItemConnections()
Update all items to match the driver connection.
std::set< SCH_SHEET_PIN * > m_hier_pins
Cache for lookup of any hierarchical (sheet) pins on this subgraph (for referring down).
std::unordered_map< std::shared_ptr< SCH_CONNECTION >, std::unordered_set< CONNECTION_SUBGRAPH * > > m_bus_neighbors
If a subgraph is a bus, this map contains links between the bus members and any local sheet neighbors...
CONNECTION_GRAPH * m_graph
std::vector< SCH_ITEM * > GetAllBusLabels() const
Return all the all bus labels attached to this subgraph (if any).
std::unordered_map< SCH_ITEM *, wxString > m_driver_name_cache
const wxString & GetNameForDriver(SCH_ITEM *aItem) const
Return the candidate net name for a driver.
wxString GetNetName() const
Return the fully-qualified net name for this subgraph (if one exists)
std::vector< SCH_ITEM * > GetVectorBusLabels() const
Return all the vector-based bus labels attached to this subgraph (if any).
const SCH_SHEET_PATH & GetSheet() const
bool m_multiple_drivers
True if this subgraph contains more than one driver that should be shorted together in the netlist.
bool ResolveDrivers(bool aCheckMultipleDrivers=false)
Determine which potential driver should drive the subgraph.
std::set< SCH_ITEM * > m_drivers
bool m_absorbed
True if this subgraph has been absorbed into another. No pointers here are safe if so!
SCH_CONNECTION * m_driver_connection
Cache for driver connection.
CONNECTION_SUBGRAPH * m_absorbed_by
If this subgraph is absorbed, points to the absorbing (and valid) subgraph.
std::unordered_set< CONNECTION_SUBGRAPH * > m_hier_children
If not null, this indicates the subgraph(s) on a lower level sheet that are linked to this one.
void AddItem(SCH_ITEM *aItem)
Add a new item to the subgraph.
const std::vector< std::pair< wxString, SCH_ITEM * > > GetNetclassesForDriver(SCH_ITEM *aItem) const
Return the resolved netclasses for the item, and the source item providing the netclass.
void Absorb(CONNECTION_SUBGRAPH *aOther)
Combine another subgraph on the same sheet into this one.
std::set< SCH_ITEM * > m_items
Contents of the subgraph.
std::unordered_map< std::shared_ptr< SCH_CONNECTION >, std::unordered_set< CONNECTION_SUBGRAPH * > > m_bus_parents
If this is a net, this vector contains links to any same-sheet buses that contain it.
SCH_ITEM * m_driver
Fully-resolved driver for the subgraph (might not exist in this subgraph).
std::mutex m_driver_mutex
bool m_is_bus_member
True if the subgraph is not actually part of a net.
void ExchangeItem(SCH_ITEM *aOldItem, SCH_ITEM *aNewItem)
Replaces all references to #aOldItem with #aNewItem in the subgraph.
CONNECTION_SUBGRAPH * m_hier_parent
If not null, this indicates the subgraph on a higher level sheet that is linked to this one.
void RemoveItem(SCH_ITEM *aItem)
bool m_local_driver
True if the driver is a local (i.e. non-global) type.
std::set< SCH_HIERLABEL * > m_hier_ports
Cache for lookup of any hierarchical ports on this subgraph (for referring up).
void getAllConnectedItems(std::set< std::pair< SCH_SHEET_PATH, SCH_ITEM * > > &aItems, std::set< CONNECTION_SUBGRAPH * > &aSubgraphs)
Find all items in the subgraph as well as child subgraphs recursively.
virtual VECTOR2I GetPosition() const
virtual wxString GetItemDescription(UNITS_PROVIDER *aUnitsProvider, bool aFull) const
Return a user-visible description string of this item.
KICAD_T Type() const
Returns the type of object.
EE_TYPE Overlapping(const BOX2I &aRect) const
EE_TYPE OfType(KICAD_T aType) const
static std::shared_ptr< ERC_ITEM > Create(int aErrorCode)
Constructs an ERC_ITEM for the given error code.
Container for ERC settings.
bool IsTestEnabled(int aErrorCode) const
A small class to help profiling.
void Show(std::ostream &aStream=std::cerr)
Print the elapsed time (in a suitable unit) to a stream.
A progress reporter interface for use in multi-threaded environments.
virtual bool KeepRefreshing(bool aWait=false)=0
Update the UI (if any).
virtual void SetCurrentProgress(double aProgress)=0
Set the progress value to aProgress (0..1).
std::shared_ptr< NET_SETTINGS > m_NetSettings
Net settings for this project (owned here)
virtual PROJECT_FILE & GetProjectFile() const
PROJECT & Project() const
Return a reference to the project this schematic is part of.
SCH_SHEET_PATH & CurrentSheet() const
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...
bool IsStartDangling() const
VECTOR2I GetPosition() const override
bool IsEndDangling() const
std::vector< VECTOR2I > GetConnectionPoints() const override
Add all the connection points for this item to aPoints.
Class for a wire to bus entry.
SCH_ITEM * m_connected_bus_item
Pointer to the bus item (usually a bus wire) connected to this bus-wire entry, if it is connected to ...
Each graphical item can have a SCH_CONNECTION describing its logical connection (to a bus or net).
wxString FullLocalName() const
void ConfigureFromLabel(const wxString &aLabel)
Configures the connection given a label.
void SetSubgraphCode(int aCode)
void SetBusCode(int aCode)
void SetName(const wxString &aName)
SCH_SHEET_PATH Sheet() const
CONNECTION_TYPE Type() const
void SetNetCode(int aCode)
SCH_ITEM * m_driver
The SCH_ITEM that drives this connection's net.
bool IsDriver() const
Checks if the SCH_ITEM this connection is attached to can drive connections Drivers can be labels,...
void SetType(CONNECTION_TYPE aType)
wxString LocalName() const
wxString Name(bool aIgnoreSheet=false) const
bool IsSubsetOf(SCH_CONNECTION *aOther) const
Returns true if this connection is contained within aOther (but not the same as aOther)
void SetDriver(SCH_ITEM *aItem)
void Clone(const SCH_CONNECTION &aOther)
Copies connectivity information (but not parent) from another connection.
void SetGraph(CONNECTION_GRAPH *aGraph)
const std::vector< std::shared_ptr< SCH_CONNECTION > > & Members() const
Base class for any item which can be embedded within the SCHEMATIC container class,...
void ClearConnectedItems(const SCH_SHEET_PATH &aPath)
Clear all connections to this item.
virtual void RunOnChildren(const std::function< void(SCH_ITEM *)> &aFunction, RECURSE_MODE aMode)
const SYMBOL * GetParentSymbol() const
virtual const wxString & GetCachedDriverName() const
const std::unordered_set< SCH_RULE_AREA * > & GetRuleAreaCache() const
Get the cache of rule areas enclosing this item.
SCH_CONNECTION * InitializeConnection(const SCH_SHEET_PATH &aPath, CONNECTION_GRAPH *aGraph)
Create a new connection object associated with this object.
void AddConnectionTo(const SCH_SHEET_PATH &aPath, SCH_ITEM *aItem)
Add a connection link between this item and another.
SCH_LAYER_ID GetLayer() const
Return the layer this item is on.
void SetConnectionGraph(CONNECTION_GRAPH *aGraph)
Update the connection graph for all connections in this item.
virtual bool HasCachedDriverName() const
SCH_CONNECTION * GetOrInitConnection(const SCH_SHEET_PATH &aPath, CONNECTION_GRAPH *aGraph)
SCH_CONNECTION * Connection(const SCH_SHEET_PATH *aSheet=nullptr) const
Retrieve the connection associated with this object in the given sheet.
virtual std::vector< VECTOR2I > GetConnectionPoints() const
Add all the connection points for this item to aPoints.
wxString GetShownText(const SCH_SHEET_PATH *aPath, bool aAllowExtraText, int aDepth=0) const override
bool IsDangling() const override
LABEL_FLAG_SHAPE GetShape() const
Segment description base class to describe items which have 2 end points (track, wire,...
std::vector< VECTOR2I > GetConnectionPoints() const override
Add all the connection points for this item to aPoints.
bool IsStartDangling() const
bool IsEndDangling() const
bool IsGraphicLine() const
Return if the line is a graphic (non electrical line)
bool IsGlobalPower() const
Return whether this pin forms a global power connection: i.e., is part of a power symbol and of type ...
bool IsLocalPower() const
Local power pin is the same except that it is sheet-local and it does not support the legacy hidden p...
SCH_PIN * GetLibPin() const
bool IsStacked(const SCH_PIN *aPin) const
wxString GetDefaultNetName(const SCH_SHEET_PATH &aPath, bool aForceNoConnect=false)
bool IsPower() const
Check if the pin is either a global or local power pin.
ELECTRICAL_PINTYPE GetType() const
Container class that holds multiple SCH_SCREEN objects in a hierarchy.
void Append(SCH_ITEM *aItem, bool aUpdateLibSymbol=true)
EE_RTREE & Items()
Get the full RTree, usually for iterating.
SCH_LINE * GetBus(const VECTOR2I &aPosition, int aAccuracy=0, SCH_LINE_TEST_T aSearchType=ENTIRE_LENGTH_T) const
A container for handling SCH_SHEET_PATH objects in a flattened hierarchy.
Handle access to a stack of flattened SCH_SHEET objects by way of a path for creating a flattened sch...
const SCH_SHEET * GetSheet(unsigned aIndex) const
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) 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.
SCH_PIN * GetPin(const wxString &number) const
Find a symbol pin by number.
std::unique_ptr< LIB_SYMBOL > & GetLibSymbolRef()
VECTOR2I GetPosition() const override
virtual wxString GetShownText(const SCH_SHEET_PATH *aPath, bool aAllowExtraText, int aDepth=0) const
virtual bool IsGlobalPower() const =0
virtual bool IsLocalPower() const =0
virtual bool IsPower() const =0
bool GetExcludedFromBoard() const override
#define CONNECTIVITY_CANDIDATE
flag indicating that the structure is connected for connectivity
@ ERCE_DRIVER_CONFLICT
Conflicting drivers (labels, etc) on a subgraph.
@ ERCE_UNCONNECTED_WIRE_ENDPOINT
A label is connected to more than one wire.
@ ERCE_LABEL_NOT_CONNECTED
Label not connected to any pins.
@ ERCE_BUS_TO_BUS_CONFLICT
A connection between bus objects doesn't share at least one net.
@ ERCE_LABEL_SINGLE_PIN
A label is connected only to a single pin.
@ ERCE_BUS_ENTRY_CONFLICT
A wire connected to a bus doesn't match the bus.
@ ERCE_BUS_TO_NET_CONFLICT
A bus wire is graphically connected to a net port/pin (or vice versa).
@ ERCE_NOCONNECT_NOT_CONNECTED
A no connect symbol is not connected to anything.
@ ERCE_PIN_NOT_CONNECTED
Pin not connected and not no connect symbol.
@ ERCE_NOCONNECT_CONNECTED
A no connect symbol is connected to more than 1 pin.
@ ERCE_HIERACHICAL_LABEL
Mismatch between hierarchical labels and pins sheets.
@ ERCE_WIRE_DANGLING
Some wires are not connected to anything else.
@ ERCE_SINGLE_GLOBAL_LABEL
A label only exists once in the schematic.
static const wxChar DanglingProfileMask[]
Flag to enable connectivity profiling.
static const wxChar ConnTrace[]
Flag to enable connectivity tracing.
#define KI_FALLTHROUGH
The KI_FALLTHROUGH macro is to be used when switch statement cases should purposely fallthrough from ...
void remove_duplicates(_Container &__c)
Deletes all duplicate values from __c.
std::vector< SCH_ITEM * > SCH_ITEM_VEC
Definition of the SCH_SHEET_PATH and SCH_SHEET_LIST classes for Eeschema.
std::vector< FAB_LAYER_COLOR > dummy
wxString UnescapeString(const wxString &aSource)
wxString EscapeString(const wxString &aSource, ESCAPE_CONTEXT aContext)
The Escape/Unescape routines use HTML-entity-reference-style encoding to handle characters which are:...
thread_pool & GetKiCadThreadPool()
Get a reference to the current thread pool.
BS::thread_pool thread_pool
Functions to provide common constants and other functions to assist in making a consistent UI.