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() )
219 if( aGlobal != bGlobal )
225 if( aLocal != bLocal )
246 bool a_lowQualityName = a_name.Contains(
"-Pad" );
247 bool b_lowQualityName = b_name.Contains(
"-Pad" );
249 if( a_lowQualityName != b_lowQualityName )
250 return !a_lowQualityName;
252 return a_name < b_name;
255 std::sort( candidates.begin(), candidates.end(), candidate_cmp );
260 if( strong_drivers.size() > 1 )
267 m_drivers.insert( strong_drivers.begin(), strong_drivers.end() );
289 std::set<CONNECTION_SUBGRAPH*>& aSubgraphs )
301 if( aSubgraphs.insert( sg ).second ==
false )
307 aItems.emplace(
m_sheet, item );
321#ifdef CONNECTIVITY_DEBUG
322 wxASSERT_MSG(
false, wxS(
"Tried to get the net name of an item with no connection" ) );
334 std::vector<SCH_ITEM*> labels;
338 switch( item->Type() )
347 labels.push_back( item );
363 std::vector<SCH_ITEM*> labels;
367 switch( item->Type() )
376 labels.push_back( item );
392 switch( aItem->
Type() )
399 return pin->GetDefaultNetName(
m_sheet, forceNoConnect );
426 wxFAIL_MSG( wxS(
"Unhandled item type in GetNameForDriver" ) );
427 return wxEmptyString;
447const std::vector<std::pair<wxString, SCH_ITEM*>>
450 std::vector<std::pair<wxString, SCH_ITEM*>> foundNetclasses;
452 const std::unordered_set<SCH_RULE_AREA*>& ruleAreaCache = aItem->
GetRuleAreaCache();
457 const std::vector<std::pair<wxString, SCH_ITEM*>> ruleNetclasses =
458 ruleArea->GetResolvedNetclasses();
460 if( ruleNetclasses.size() > 0 )
462 foundNetclasses.insert( foundNetclasses.end(), ruleNetclasses.begin(),
463 ruleNetclasses.end() );
479 if( netclass != wxEmptyString )
480 foundNetclasses.push_back( { netclass, aItem } );
487 foundNetclasses.begin(), foundNetclasses.end(),
488 [](
const std::pair<wxString, SCH_ITEM*>& i1,
const std::pair<wxString, SCH_ITEM*>& i2 )
490 return i1.first < i2.first;
493 return foundNetclasses;
519 child->m_absorbed_by =
this;
522 set_absorbed_by( subchild );
530 set_absorbed_by( aOther );
583 if(
const std::unique_ptr<LIB_SYMBOL>& part = symbol->GetLibSymbolRef() )
584 return part->GetReferenceField().GetText();
586 return wxEmptyString;
589 switch( aDriver->
Type() )
620 std::back_inserter(
m_items ) );
675 wxCHECK2( aOldItem->
Type() == aNewItem->
Type(),
return );
710 wxCHECK2( oldPins.size() == newPins.size(),
return );
712 for(
size_t ii = 0; ii < oldPins.size(); ii++ )
714 exchange( oldPins[ii], newPins[ii] );
725 if( subgraph->m_graph ==
this )
749 std::function<
void(
SCH_ITEM* )>* aChangedItemHandler,
753 PROF_TIMER recalc_time(
"CONNECTION_GRAPH::Recalculate" );
754 monitorTrans.
Start();
759 monitorTrans.
StartSpan(
"updateItemConnectivity",
"" );
760 PROF_TIMER update_items(
"updateItemConnectivity" );
763 std::set<SCH_ITEM*> dirty_items;
765 int count = aSheetList.size() * 2;
770 if( aProgressReporter )
776 std::vector<SCH_ITEM*> items;
779 std::vector<std::pair<SCH_SYMBOL*, int>> symbolsChanged;
781 for(
SCH_ITEM* item : sheet.LastScreen()->Items() )
783 if( item->IsConnectable() && ( aUnconditional || item->IsConnectivityDirty() ) )
785 wxLogTrace(
ConnTrace, wxT(
"Adding item %s to connectivity graph update" ),
786 item->GetTypeDesc() );
787 items.push_back( item );
788 dirty_items.insert( item );
797 if(
pin->IsConnectivityDirty() )
799 dirty_items.insert(
pin );
812 if(
pin->IsConnectivityDirty() )
814 items.push_back(
pin );
815 dirty_items.insert(
pin );
825 if(
pin->IsConnectivityDirty() )
827 items.push_back(
pin );
828 dirty_items.insert(
pin );
841 if( symbol->
GetUnit() != new_unit )
842 symbolsChanged.push_back( { symbol, symbol->
GetUnit() } );
852 if( aProgressReporter )
859 sheet.LastScreen()->TestDanglingEnds( &sheet, aChangedItemHandler );
862 for(
const auto& [ symbol, originalUnit ] : symbolsChanged )
863 symbol->SetUnit( originalUnit );
874 item->SetConnectivityDirty(
false );
881 PROF_TIMER build_graph(
"buildConnectionGraph" );
882 monitorTrans.
StartSpan(
"BuildConnectionGraph",
"" );
901 const std::set<SCH_ITEM*> &aItems )
903 std::set<std::pair<SCH_SHEET_PATH, SCH_ITEM*>> retvals;
904 std::set<CONNECTION_SUBGRAPH*> subgraphs;
909 while( aSubgraph->m_absorbed_by )
912 wxASSERT( aSubgraph->m_graph == aSubgraph->m_absorbed_by->m_graph );
913 aSubgraph = aSubgraph->m_absorbed_by;
917 while( aSubgraph->m_hier_parent )
920 wxASSERT( aSubgraph->m_graph == aSubgraph->m_hier_parent->m_graph );
921 aSubgraph = aSubgraph->m_hier_parent;
925 aSubgraph->getAllConnectedItems( retvals, subgraphs );
928 auto extract_element = [&](
SCH_ITEM* aItem )
934 wxLogTrace(
ConnTrace, wxT(
"Item %s not found in connection graph" ),
935 aItem->GetTypeDesc() );
941 wxLogTrace(
ConnTrace, wxT(
"Item %s in subgraph %ld (%p) has no driver" ),
942 aItem->GetTypeDesc(), item_sg->
m_code, item_sg );
947 if( sg_to_scan.empty() )
949 wxLogTrace(
ConnTrace, wxT(
"Item %s in subgraph %ld with net %s has no neighbors" ),
951 sg_to_scan.push_back( item_sg );
955 wxT(
"Removing all item %s connections from subgraph %ld with net %s: Found "
962 traverse_subgraph( sg );
964 for(
auto& bus_it : sg->m_bus_neighbors )
967 traverse_subgraph( bus_sg );
970 for(
auto& bus_it : sg->m_bus_parents )
973 traverse_subgraph( bus_sg );
987 extract_element(
pin );
994 extract_element(
pin );
998 extract_element( item );
1004 for(
const auto& [
path, item] : retvals )
1031 wxLogTrace(
ConnTrace, wxT(
"Removing %zu subgraphs" ), aSubgraphs.size() );
1034 std::set<int> codes_to_remove;
1038 std::sort( el.second.begin(), el.second.end() );
1043 for(
auto& it : sg->m_bus_neighbors )
1049 for(
auto test = parents.begin();
test != parents.end(); )
1057 if( parents.empty() )
1062 for(
auto& it : sg->m_bus_parents )
1068 for(
auto test = neighbors.begin();
test != neighbors.end(); )
1076 if( neighbors.empty() )
1097 auto it = std::lower_bound( el.second.begin(), el.second.end(), sg );
1099 while( it != el.second.end() && *it == sg )
1100 it = el.second.erase( it );
1103 auto remove_sg = [sg](
auto it ) ->
bool
1116 if( remove_sg( it ) )
1124 if( remove_sg( it ) )
1133 if( remove_sg( it ) )
1135 codes_to_remove.insert( it->first.Netcode );
1147 if( remove_sg( it ) )
1155 if( it->second == sg )
1166 if( codes_to_remove.contains( it->second ) )
1174 if( codes_to_remove.contains( it->second ) )
1183 sg->m_graph =
nullptr;
1190 std::map<
VECTOR2I, std::vector<SCH_ITEM*>>& aConnectionMap )
1201 aConn->SetName(
name );
1206 std::map<wxString, std::vector<SCH_PIN*>> pinNumberMap;
1212 updatePin(
pin, conn );
1213 aConnectionMap[
pin->GetPosition() ].push_back(
pin );
1214 pinNumberMap[
pin->GetNumber()].emplace_back(
pin );
1217 auto linkPinsInVec =
1218 [&](
const std::vector<SCH_PIN*>& aVec )
1220 for(
size_t i = 0; i < aVec.size(); ++i )
1222 for(
size_t j = i + 1; j < aVec.size(); ++j )
1224 aVec[i]->AddConnectionTo( aSheet, aVec[j] );
1225 aVec[j]->AddConnectionTo( aSheet, aVec[i] );
1234 for(
const auto& [number,
group] : pinNumberMap )
1235 linkPinsInVec(
group );
1240 std::vector<SCH_PIN*> pins;
1242 for(
const wxString& pinNumber :
group )
1243 pins.emplace_back( aSymbol->
GetPin( pinNumber ) );
1245 linkPinsInVec( pins );
1268 std::map<
VECTOR2I, std::vector<SCH_ITEM*>>& aConnectionMap )
1273 m_items.emplace_back( aItem );
1276 switch( aItem->
Type() )
1289 if( points.empty() )
1290 points = {
static_cast<SCH_PIN*
>( aItem )->GetPosition() };
1303 for(
const VECTOR2I& point : points )
1304 aConnectionMap[point].push_back( aItem );
1309 const std::vector<SCH_ITEM*>& aItemList )
1311 wxLogTrace( wxT(
"Updating connectivity for sheet %s with %zu items" ),
1313 std::map<VECTOR2I, std::vector<SCH_ITEM*>> connection_map;
1317 std::vector<VECTOR2I> points = item->GetConnectionPoints();
1318 item->ClearConnectedItems( aSheet );
1324 pin->InitializeConnection( aSheet,
this );
1326 pin->ClearConnectedItems( aSheet );
1328 connection_map[
pin->GetTextPos() ].push_back(
pin );
1345 VECTOR2I point = item->GetPosition();
1348 std::vector<SCH_ITEM*> overlapping_items;
1350 std::copy_if( items.begin(), items.end(), std::back_inserter( overlapping_items ),
1353 return test_item->Type() == SCH_LINE_T
1354 && test_item->HitTest( point, -1 );
1359 if( overlapping_items.size() < 2 )
continue;
1361 for(
SCH_ITEM* test_item : overlapping_items )
1362 connection_map[point].push_back( test_item );
1367 for(
auto& [point, connection_vec] : connection_map )
1369 std::sort( connection_vec.begin(), connection_vec.end() );
1375 for(
SCH_ITEM* connected_item : connection_vec )
1389 if( connection_vec.size() == 1 )
1405 if( point == bus_entry->GetPosition() )
1408 bus_entry->m_connected_bus_items[1] = busLine;
1421 for(
SCH_ITEM* test_item : connection_vec )
1423 bool bus_connection_ok =
true;
1425 if( test_item == connected_item )
1431 if( test_item->GetLayer() ==
LAYER_BUS )
1450 if( connected_item->ConnectionPropagatesTo( test_item )
1451 && test_item->ConnectionPropagatesTo( connected_item )
1452 && bus_connection_ok )
1454 connected_item->AddConnectionTo( aSheet, test_item );
1465 if( !bus_entry->m_connected_bus_item )
1471 bus_entry->m_connected_bus_item = bus;
1482 wxCHECK_RET(
m_schematic, wxS(
"Connection graph cannot be built without schematic pointer" ) );
1486 for(
const std::shared_ptr<BUS_ALIAS>& alias :
m_schematic->GetAllBusAliases() )
1495 for(
const auto& [sheet, connection] : item->m_connection_map )
1497 if( connection->SubgraphCode() == 0 )
1506 connection->SetSubgraphCode( subgraph->
m_code );
1509 std::list<SCH_ITEM*> memberlist;
1514 SCH_CONNECTION* conn = aItem->GetOrInitConnection( sheet,
this );
1520 return ( unique && conn && ( conn->
SubgraphCode() == 0 ) );
1523 std::copy_if( item->ConnectedItems( sheet ).begin(),
1524 item->ConnectedItems( sheet ).end(),
1525 std::back_inserter( memberlist ), get_items );
1527 for(
SCH_ITEM* connected_item : memberlist )
1532 SCH_CONNECTION* connected_conn = connected_item->Connection( &sheet );
1534 wxCHECK2( connected_conn,
continue );
1540 subgraph->
AddItem( connected_item );
1541 const SCH_ITEM_VEC& citemset = connected_item->ConnectedItems( sheet );
1548 if( get_items( citem ) )
1549 memberlist.push_back( citem );
1554 for(
SCH_ITEM* connected_item : memberlist )
1568 std::vector<CONNECTION_SUBGRAPH*> dirty_graphs;
1573 return candidate->m_dirty;
1576 wxLogTrace(
ConnTrace, wxT(
"Resolving drivers for %zu subgraphs" ), dirty_graphs.size() );
1578 std::vector<std::future<size_t>> returns( dirty_graphs.size() );
1580 auto update_lambda =
1583 if( !subgraph->m_dirty )
1587 for(
SCH_ITEM* item : subgraph->m_items )
1589 switch( item->
Type() )
1592 subgraph->m_no_connect = item;
1596 subgraph->m_bus_entry = item;
1604 subgraph->m_no_connect = item;
1614 subgraph->ResolveDrivers(
true );
1615 subgraph->m_dirty =
false;
1622 auto results =
tp.submit_loop( 0, dirty_graphs.size(),
1625 update_lambda( dirty_graphs[ii] );
1634 return candidate->m_driver;
1647 wxString full_name = subgraph->m_driver_connection->Name();
1648 wxString
name = subgraph->m_driver_connection->Name(
true );
1657 wxString prefixOnly = full_name.BeforeFirst(
'[' ) + wxT(
"[]" );
1661 subgraph->m_dirty =
true;
1663 if( subgraph->m_strong_driver )
1665 SCH_ITEM* driver = subgraph->m_driver;
1668 switch( driver->
Type() )
1684 if(
pin->IsGlobalPower() )
1688 else if(
pin->IsLocalPower() )
1695 wxLogTrace(
ConnTrace, wxS(
"Unexpected normal pin %s" ),
1705 wxLogTrace(
ConnTrace, wxS(
"Unexpected strong driver %s" ),
1717 std::vector<CONNECTION_SUBGRAPH*> new_subgraphs;
1728 dummy.SetGraph(
this );
1731 wxLogTrace(
ConnTrace, wxS(
"new bus label (%s)" ),
1734 for(
const auto& conn :
dummy.Members() )
1736 wxString
name = conn->FullLocalName();
1747 subgraph->StoreImplicitConnection( new_conn );
1750 wxLogTrace(
ConnTrace, wxS(
"SG(%ld), Adding full local name (%s) with sg (%d) on subsheet %s" ),
1751 subgraph->m_code,
name, code, subgraph->m_sheet.PathHumanReadable() );
1764 new_subgraphs.push_back( new_sg );
1769 std::copy( new_subgraphs.begin(), new_subgraphs.end(),
1781 std::unordered_map<int, CONNECTION_SUBGRAPH*> global_power_pin_subgraphs;
1785 if( !
pin->ConnectedItems( sheet ).empty()
1786 && !
pin->GetLibPin()->GetParentSymbol()->IsGlobalPower() )
1801 if(
pin->GetLibPin()->GetParentSymbol()->IsGlobalPower() )
1802 connection->
SetName(
pin->GetParentSymbol()->GetValue(
true, &sheet,
false ) );
1811 auto jj = global_power_pin_subgraphs.find( code );
1813 if( jj != global_power_pin_subgraphs.end() )
1815 subgraph = jj->second;
1833 global_power_pin_subgraphs[code] = subgraph;
1850 std::unordered_set<CONNECTION_SUBGRAPH*> invalidated_subgraphs;
1854 if( subgraph->m_absorbed )
1859 wxString
name = connection->
Name();
1862 unsigned suffix = 1;
1864 auto create_new_name =
1868 wxString suffixStr = std::to_wstring( suffix );
1875 wxString prefix = aConn->BusPrefix();
1877 if( prefix.empty() )
1878 prefix = wxT(
"BUS" );
1880 wxString oldName = aConn->Name().AfterFirst(
'{' );
1882 newName << prefix << wxT(
"_" ) << suffixStr << wxT(
"{" ) << oldName;
1884 aConn->ConfigureFromLabel( newName );
1888 newName << aConn->Name() << wxT(
"_" ) << suffixStr;
1889 aConn->SetSuffix( wxString( wxT(
"_" ) ) << suffixStr );
1896 if( !subgraph->m_strong_driver )
1898 std::vector<CONNECTION_SUBGRAPH*> vec_empty;
1899 std::vector<CONNECTION_SUBGRAPH*>* vec = &vec_empty;
1908 wxString prefixOnly =
name.BeforeFirst(
'[' ) + wxT(
"[]" );
1914 if( vec->size() > 1 )
1916 wxString new_name = create_new_name( connection );
1919 new_name = create_new_name( connection );
1921 wxLogTrace(
ConnTrace, wxS(
"%ld (%s) is weakly driven and not unique. Changing to %s." ),
1922 subgraph->m_code,
name, new_name );
1924 std::erase( *vec, subgraph );
1930 else if( subgraph->m_driver )
1942 bool conflict =
false;
1943 wxString global_name = connection->
Name(
true );
1950 std::vector<CONNECTION_SUBGRAPH*>& candidates = kk->second;
1954 if( candidate->m_sheet == sheet )
1961 wxLogTrace(
ConnTrace, wxS(
"%ld (%s) skipped for promotion due to potential conflict" ),
1962 subgraph->m_code,
name );
1968 wxLogTrace(
ConnTrace, wxS(
"%ld (%s) weakly driven by unique sheet pin %s, promoting" ),
1969 subgraph->m_code,
name,
1970 subgraph->m_driver->GetItemDescription( &unitsProvider,
true ) );
1972 subgraph->m_strong_driver =
true;
1979 if( connection->
IsBus() )
2003 subgraph->m_dirty =
true;
2011 if( !subgraph->m_strong_driver )
2018 std::vector<CONNECTION_SUBGRAPH*> candidate_subgraphs;
2021 std::back_inserter( candidate_subgraphs ),
2024 return ( !candidate->m_absorbed &&
2025 candidate->m_strong_driver &&
2026 candidate != subgraph );
2032 std::vector< std::shared_ptr<SCH_CONNECTION> > connections_to_check;
2035 connections_to_check.push_back( std::make_shared<SCH_CONNECTION>( *connection ) );
2037 auto add_connections_to_check =
2040 for(
SCH_ITEM* possible_driver : aSubgraph->m_items )
2042 if( possible_driver == aSubgraph->m_driver )
2049 if( c->Type() != aSubgraph->m_driver_connection->Type() )
2052 if( c->Name(
true ) == aSubgraph->m_driver_connection->Name(
true ) )
2055 connections_to_check.push_back( c );
2056 wxLogTrace(
ConnTrace, wxS(
"%lu (%s): Adding secondary driver %s" ),
2058 aSubgraph->m_driver_connection->Name(
true ),
2067 add_connections_to_check( subgraph );
2069 std::set<SCH_CONNECTION*> checked_connections;
2071 for(
unsigned i = 0; i < connections_to_check.size(); i++ )
2073 auto member = connections_to_check[i];
2076 if( !checked_connections.insert( member.get() ).second )
2079 if( member->IsBus() )
2081 connections_to_check.insert( connections_to_check.end(),
2082 member->Members().begin(),
2083 member->Members().end() );
2086 wxString test_name = member->Name(
true );
2090 if( candidate->
m_absorbed || candidate == subgraph )
2106 if( driver == candidate->
m_driver )
2118 &&
pin->GetDefaultNetName( sheet ) == test_name )
2131 if( subgraph->GetNameForDriver( driver ) == test_name )
2144 wxLogTrace(
ConnTrace, wxS(
"%lu (%s) has bus child %lu (%s)" ),
2145 subgraph->m_code, connection->
Name(),
2146 candidate->
m_code, member->Name() );
2148 subgraph->m_bus_neighbors[member].insert( candidate );
2151 else if( !connection->
IsBus()
2154 wxLogTrace(
ConnTrace, wxS(
"%lu (%s) absorbs neighbor %lu (%s)" ),
2155 subgraph->m_code, connection->
Name(),
2159 add_connections_to_check( candidate );
2161 subgraph->Absorb( candidate );
2162 invalidated_subgraphs.insert( subgraph );
2172 if( subgraph->m_absorbed )
2175 if( !subgraph->ResolveDrivers() )
2178 if( subgraph->m_driver_connection->IsBus() )
2183 wxLogTrace(
ConnTrace, wxS(
"Re-resolving drivers for %lu (%s)" ),
2184 subgraph->m_code, subgraph->m_driver_connection->Name() );
2203 bool aUnconditional )
2206 wxCHECK_RET(
m_schematic, wxT(
"Connection graph cannot be built without schematic pointer" ) );
2210 for(
const std::shared_ptr<BUS_ALIAS>& alias :
m_schematic->GetAllBusAliases() )
2216 PROF_TIMER sub_graph(
"buildItemSubGraphs" );
2235 PROF_TIMER proc_sub_graph(
"ProcessSubGraphs" );
2239 proc_sub_graph.
Show();
2248 std::vector<CONNECTION_SUBGRAPH*> global_subgraphs;
2250 std::back_inserter( global_subgraphs ),
2253 return !candidate->m_local_driver;
2267 m_driver_subgraphs[ii]->UpdateItemConnections();
2277 if( !subgraph->m_dirty )
2280 wxLogTrace(
ConnTrace, wxS(
"Processing %lu (%s) for propagation" ),
2281 subgraph->m_code, subgraph->m_driver_connection->Name() );
2287 if( !subgraph->m_local_driver && subgraph->m_multiple_drivers )
2289 for(
SCH_ITEM* driver : subgraph->m_drivers )
2291 if( driver == subgraph->m_driver )
2294 const wxString& secondary_name = subgraph->GetNameForDriver( driver );
2296 if( secondary_name == subgraph->m_driver_connection->Name() )
2304 if( candidate == subgraph )
2307 if( !secondary_is_global && candidate->
m_sheet != subgraph->m_sheet )
2314 wxLogTrace(
ConnTrace, wxS(
"Global %lu (%s) promoted to %s" ),
2316 subgraph->m_driver_connection->Name() );
2338 if( subgraph->m_dirty )
2355 wxASSERT_MSG( !subgraph->m_dirty,
2356 wxS(
"Subgraph not processed by propagateToNeighbors!" ) );
2358 if( subgraph->m_bus_parents.size() < 2 )
2363 wxLogTrace(
ConnTrace, wxS(
"%lu (%s) has multiple bus parents" ),
2364 subgraph->m_code, conn->
Name() );
2367 wxCHECK2( conn->
IsNet(),
continue );
2369 for(
const auto& ii : subgraph->m_bus_parents )
2382 wxLogTrace(
ConnTrace, wxS(
"Warning: could not match %s inside %lu (%s)" ),
2387 if( conn->
Name() != match->
Name() )
2389 wxString old_name = match->
Name();
2391 wxLogTrace(
ConnTrace, wxS(
"Updating %lu (%s) member %s to %s" ),
2394 match->
Clone( *conn );
2413 auto updateItemConnectionsTask =
2417 if( !subgraph->m_strong_driver
2418 && subgraph->m_drivers.size() == 1
2419 && subgraph->m_driver->Type() ==
SCH_PIN_T )
2422 wxString
name =
pin->GetDefaultNetName( subgraph->m_sheet,
true );
2424 subgraph->m_driver_connection->ConfigureFromLabel(
name );
2427 subgraph->m_dirty =
false;
2428 subgraph->UpdateItemConnections();
2431 if( subgraph->m_driver_connection->IsBus() )
2436 if( subgraph->m_driver && subgraph->m_driver->Type() ==
SCH_SHEET_PIN_T )
2442 wxString pinText =
pin->GetShownText(
false );
2449 if( label->
GetShownText( &subgraph->m_sheet,
false ) == pinText )
2452 path.push_back( sheet );
2456 if( parent_conn && parent_conn->
IsBus() )
2463 if( subgraph->m_driver_connection->IsBus() )
2474 updateItemConnectionsTask( m_driver_subgraphs[ii] );
2484 subgraph->m_driver_connection->NetCode() };
2490 std::shared_ptr<NET_SETTINGS>& netSettings =
m_schematic->Project().GetProjectFile().m_NetSettings;
2491 std::map<wxString, std::set<wxString>> oldAssignments = netSettings->GetNetclassLabelAssignments();
2492 std::set<wxString> affectedNetclassNetAssignments;
2494 netSettings->ClearNetclassLabelAssignments();
2496 auto dirtySubgraphs =
2497 [&](
const std::vector<CONNECTION_SUBGRAPH*>& subgraphs )
2499 if( aChangedItemHandler )
2503 for(
SCH_ITEM* item : subgraph->m_items )
2504 (*aChangedItemHandler)( item );
2509 auto checkNetclassDrivers =
2510 [&](
const wxString& netName,
const std::vector<CONNECTION_SUBGRAPH*>& subgraphs )
2512 wxCHECK_RET( !subgraphs.empty(), wxS(
"Invalid empty subgraph" ) );
2514 std::set<wxString> netclasses;
2519 for(
SCH_ITEM* item : subgraph->m_items )
2521 for(
const auto& [
name, provider] : subgraph->GetNetclassesForDriver( item ) )
2522 netclasses.insert(
name );
2529 if( subgraph->m_driver_connection->IsBus() )
2531 auto processBusMember = [&,
this](
const SCH_CONNECTION* member )
2533 if( !netclasses.empty() )
2535 netSettings->AppendNetclassLabelAssignment( member->Name(), netclasses );
2540 if( oldAssignments.count( member->Name() ) )
2542 if( oldAssignments[member->Name()] != netclasses )
2544 affectedNetclassNetAssignments.insert( member->Name() );
2547 dirtySubgraphs( ii->second );
2550 else if( !netclasses.empty() )
2552 affectedNetclassNetAssignments.insert( member->Name() );
2555 dirtySubgraphs( ii->second );
2559 for(
const std::shared_ptr<SCH_CONNECTION>& member : subgraph->m_driver_connection->Members() )
2563 if( member->IsBus() )
2565 for(
const std::shared_ptr<SCH_CONNECTION>& nestedMember : member->Members() )
2566 processBusMember( nestedMember.get() );
2570 processBusMember( member.get() );
2577 if( !netclasses.empty() )
2579 netSettings->AppendNetclassLabelAssignment( netName, netclasses );
2582 if( oldAssignments.count( netName ) )
2584 if( oldAssignments[netName] != netclasses )
2586 affectedNetclassNetAssignments.insert( netName );
2587 dirtySubgraphs( subgraphs );
2590 else if( !netclasses.empty() )
2592 affectedNetclassNetAssignments.insert( netName );
2593 dirtySubgraphs( subgraphs );
2599 checkNetclassDrivers( netname, subgraphs );
2601 if( !aUnconditional )
2603 for(
auto& [netname, netclasses] : oldAssignments )
2605 if( netSettings->GetNetclassLabelAssignments().count( netname )
2606 || affectedNetclassNetAssignments.count( netname ) )
2611 netSettings->SetNetclassLabelAssignment( netname, netclasses );
2649 std::vector<std::shared_ptr<SCH_CONNECTION>> connections_to_check( aConnection->
Members() );
2651 for(
unsigned i = 0; i < connections_to_check.size(); i++ )
2653 const std::shared_ptr<SCH_CONNECTION>& member = connections_to_check[i];
2655 if( member->IsBus() )
2657 connections_to_check.insert( connections_to_check.end(),
2658 member->Members().begin(),
2659 member->Members().end() );
2671 std::vector<CONNECTION_SUBGRAPH*> search_list;
2672 std::unordered_set<CONNECTION_SUBGRAPH*> visited;
2673 std::unordered_set<SCH_CONNECTION*> stale_bus_members;
2680 path.push_back(
pin->GetParent() );
2691 || visited.contains( candidate ) )
2700 wxLogTrace(
ConnTrace, wxS(
"%lu: found child %lu (%s)" ), aParent->m_code,
2708 wxASSERT( candidate->
m_graph == aParent->m_graph );
2710 search_list.push_back( candidate );
2730 || visited.contains( candidate )
2736 const KIID& last_parent_uuid = aParent->m_sheet.Last()->m_Uuid;
2741 if(
pin->GetParent()->m_Uuid != last_parent_uuid )
2747 if( pin_path != aParent->m_sheet )
2752 wxLogTrace(
ConnTrace, wxS(
"%lu: found additional parent %lu (%s)" ),
2755 aParent->m_hier_children.insert( candidate );
2756 search_list.push_back( candidate );
2766 for(
const auto&
kv : aParentGraph->m_bus_neighbors )
2808 wxLogTrace(
ConnTrace, wxS(
"Could not match bus member %s in %s" ),
2809 kv.first->Name(), parent->
Name() );
2815 wxCHECK2( neighbor_conn,
continue );
2817 wxString neighbor_name = neighbor_conn->
Name();
2820 if( neighbor_name == member->
Name() )
2828 wxCHECK2_MSG( neighbor_conn->
IsNet(),
continue,
2829 wxS(
"\"" ) + neighbor_name + wxS(
"\" is not a net." ) );
2831 wxLogTrace(
ConnTrace, wxS(
"%lu (%s) connected to bus member %s (local %s)" ),
2838 member->
Clone( *neighbor_conn );
2839 stale_bus_members.insert( member );
2843 neighbor_conn->
Clone( *member );
2857 propagate_bus_neighbors( aSubgraph );
2864 wxLogTrace(
ConnTrace, wxS(
"%lu (%s) has both hier ports and pins; deferring processing" ),
2870 wxLogTrace(
ConnTrace, wxS(
"%lu (%s) has no hier pins or ports on sheet %s; marking clean" ),
2876 visited.insert( aSubgraph );
2878 wxLogTrace(
ConnTrace, wxS(
"Propagating %lu (%s) to subsheets" ),
2883 for(
unsigned i = 0; i < search_list.size(); i++ )
2885 auto child = search_list[i];
2887 if( visited.insert( child ).second )
2890 child->m_dirty =
false;
2904 if( subgraph == aSubgraph )
2911 wxString candidateName = subgraph->m_driver_connection->Name();
2912 bool shorterPath = subgraph->m_sheet.size() < bestDriver->
m_sheet.
size();
2913 bool asGoodPath = subgraph->m_sheet.size() <= bestDriver->
m_sheet.
size();
2923 ( !bestIsStrong && candidateStrong ) ||
2924 ( priority > highest && candidateStrong ) ||
2925 ( priority == highest && candidateStrong && shorterPath ) ||
2926 ( ( bestIsStrong == candidateStrong ) && asGoodPath && ( priority == highest ) &&
2927 ( candidateName < bestName ) ) )
2929 bestDriver = subgraph;
2931 bestIsStrong = candidateStrong;
2932 bestName = candidateName;
2937 if( bestDriver != aSubgraph )
2939 wxLogTrace(
ConnTrace, wxS(
"%lu (%s) overridden by new driver %lu (%s)" ),
2948 wxString old_name = subgraph->m_driver_connection->Name();
2950 subgraph->m_driver_connection->Clone( *conn );
2952 if( old_name != conn->
Name() )
2956 propagate_bus_neighbors( subgraph );
2962 if( conn->
IsBus() && !stale_bus_members.empty() )
2964 std::unordered_set<SCH_CONNECTION*> cached_members = stale_bus_members;
2974 wxLogTrace(
ConnTrace, wxS(
"WARNING: failed to match stale member %s in %s." ),
2975 stale_member->Name(), subgraph->m_driver_connection->Name() );
2979 wxLogTrace(
ConnTrace, wxS(
"Updating %lu (%s) member %s to %s" ), subgraph->m_code,
2980 subgraph->m_driver_connection->Name(), member->
LocalName(), stale_member->Name() );
2982 member->
Clone( *stale_member );
2984 propagate_bus_neighbors( subgraph );
2996 std::shared_ptr<SCH_CONNECTION> c = std::shared_ptr<SCH_CONNECTION>(
nullptr );
2998 switch( aItem->
Type() )
3001 if(
static_cast<SCH_PIN*
>( aItem )->IsPower() )
3002 c = std::make_shared<SCH_CONNECTION>( aItem, aSubgraph->
m_sheet );
3009 c = std::make_shared<SCH_CONNECTION>( aItem, aSubgraph->
m_sheet );
3018 c->SetGraph(
this );
3030 wxASSERT( aBusConnection->
IsBus() );
3039 for(
const std::shared_ptr<SCH_CONNECTION>& bus_member : aBusConnection->
Members() )
3041 if( bus_member->VectorIndex() == aSearch->
VectorIndex() )
3043 match = bus_member.get();
3051 for(
const std::shared_ptr<SCH_CONNECTION>& c : aBusConnection->
Members() )
3058 for(
const std::shared_ptr<SCH_CONNECTION>& bus_member : c->Members() )
3060 if( bus_member->LocalName() == aSearch->
LocalName() )
3062 match = bus_member.get();
3067 else if( c->LocalName() == aSearch->
LocalName() )
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;
3130 for(
unsigned i = 1; i < labels.size(); ++i )
3142 wxLogTrace(
ConnTrace, wxS(
"SG %ld (%s) has multiple bus labels" ), subgraph->m_code,
3143 connection->
Name() );
3145 ret.push_back( subgraph );
3166 if( graph == aSubGraph )
3209 wxASSERT( !it->second.empty() );
3211 return it->second[0];
3227const std::vector<CONNECTION_SUBGRAPH*>&
3230 static const std::vector<CONNECTION_SUBGRAPH*> subgraphs;
3243 int error_count = 0;
3245 wxCHECK_MSG(
m_schematic,
true, wxS(
"Null m_schematic in CONNECTION_GRAPH::RunERC" ) );
3251 std::set<SCH_ITEM*> seenDriverInstances;
3256 wxCHECK2( subgraph,
continue );
3260 wxASSERT( !subgraph->m_dirty );
3262 if( subgraph->m_absorbed )
3265 if( seenDriverInstances.count( subgraph->m_driver ) )
3268 if( subgraph->m_driver )
3269 seenDriverInstances.insert( subgraph->m_driver );
3287 subgraph->ResolveDrivers(
false );
3358 wxCHECK( aSubgraph,
false );
3364 if( driver == aSubgraph->
m_driver )
3375 if( primaryName == secondaryName )
3378 wxString msg = wxString::Format(
_(
"Both %s and %s are attached to the same "
3379 "items; %s will be used in the netlist" ),
3380 primaryName, secondaryName, primaryName );
3383 ercItem->SetItems( aSubgraph->
m_driver, driver );
3384 ercItem->SetSheetSpecificPath( aSubgraph->
GetSheet() );
3385 ercItem->SetItemsSheetPaths( aSubgraph->
GetSheet(), aSubgraph->
m_sheet );
3386 ercItem->SetErrorMessage( msg );
3411 switch( item->
Type() )
3416 bus_item = ( !bus_item ) ? item : bus_item;
3418 net_item = ( !net_item ) ? item : net_item;
3432 bus_item = ( !bus_item ) ? item : bus_item;
3434 net_item = ( !net_item ) ? item : net_item;
3444 if( net_item && bus_item )
3447 ercItem->SetSheetSpecificPath( sheet );
3448 ercItem->SetItems( net_item, bus_item );
3451 screen->
Append( marker );
3470 switch( item->
Type() )
3497 if(
test != member && member->Name() ==
test->Name() )
3511 ercItem->SetSheetSpecificPath( sheet );
3512 ercItem->SetItems( label, port );
3515 screen->
Append( marker );
3527 bool conflict =
false;
3543 switch( item->
Type() )
3573 std::set<wxString> test_names;
3585 for(
const auto& sub_member : member->Members() )
3587 if( test_names.count( sub_member->FullLocalName() ) )
3591 else if( test_names.count( member->FullLocalName() ) )
3610 wxString msg = wxString::Format(
_(
"Net %s is graphically connected to bus %s but is not a"
3611 " member of that bus" ),
3615 ercItem->SetSheetSpecificPath( sheet );
3616 ercItem->SetItems( bus_entry, bus_wire );
3617 ercItem->SetErrorMessage( msg );
3620 screen->
Append( marker );
3637 std::set<SCH_PIN*> unique_pins;
3638 std::set<SCH_LABEL_BASE*> unique_labels;
3646 for(
SCH_ITEM* item : aProcessGraph->m_items )
3648 switch( item->
Type() )
3655 if( aProcessGraph == aSubgraph )
3658 if( std::none_of( unique_pins.begin(), unique_pins.end(),
3661 return test_pin->IsStacked( aPin );
3665 unique_pins.insert( test_pin );
3688 process_subgraph( subgraph );
3693 process_subgraph( aSubgraph );
3728 ercItem->SetSheetSpecificPath( sheet );
3729 ercItem->SetItemsSheetPaths( sheet );
3736 pos =
pin->GetPosition();
3745 screen->
Append( marker );
3750 if( unique_pins.empty() && unique_labels.empty() &&
3755 ercItem->SetSheetSpecificPath( sheet );
3756 ercItem->SetItemsSheetPaths( sheet );
3759 screen->
Append( marker );
3766 bool has_other_connections =
false;
3767 std::vector<SCH_PIN*> pins;
3774 switch( item->
Type() )
3781 if( !has_other_connections && !pins.empty()
3784 for(
SCH_PIN* other_pin : pins )
3788 has_other_connections =
true;
3794 pins.emplace_back(
static_cast<SCH_PIN*
>( item ) );
3801 has_other_connections =
true;
3808 pin = pins.empty() ? nullptr : pins[0];
3811 for(
SCH_PIN* test_pin : pins )
3827 if(
pin && !has_other_connections
3829 && !
pin->GetLibPin()->GetParentSymbol()->IsPower() )
3831 wxString
name =
pin->Connection( &sheet )->Name();
3832 wxString local_name =
pin->Connection( &sheet )->Name(
true );
3837 has_other_connections =
true;
3842 if(
pin && !has_other_connections
3848 ercItem->SetSheetSpecificPath( sheet );
3849 ercItem->SetItemsSheetPaths( sheet );
3850 ercItem->SetItems(
pin );
3853 screen->
Append( marker );
3861 if( pins.size() > 1 )
3863 for(
SCH_PIN* testPin : pins )
3868 if( testPin->GetLibPin()->GetParentSymbol()->IsPower()
3869 && testPin->ConnectedItems( sheet ).empty()
3873 ercItem->SetSheetSpecificPath( sheet );
3874 ercItem->SetItemsSheetPaths( sheet );
3875 ercItem->SetItems( testPin );
3878 screen->
Append( marker );
3911 ercItem->SetItems( line );
3912 ercItem->SetSheetSpecificPath( sheet );
3913 ercItem->SetErrorMessage(
_(
"Unconnected wire endpoint" ) );
3935 ercItem->SetItems( entry );
3936 ercItem->SetSheetSpecificPath( sheet );
3937 ercItem->SetErrorMessage(
_(
"Unconnected wire to bus entry" ) );
3954 return err_count > 0;
3964 std::vector<SCH_ITEM*> wires;
3971 wires.emplace_back( item );
3973 wires.emplace_back( item );
3976 if( !wires.empty() )
3981 ercItem->SetSheetSpecificPath( sheet );
3982 ercItem->SetItems( wires[0],
3983 wires.size() > 1 ? wires[1] :
nullptr,
3984 wires.size() > 2 ? wires[2] :
nullptr,
3985 wires.size() > 3 ? wires[3] :
nullptr );
3988 screen->
Append( marker );
4016 size_t pinCount = 0;
4019 std::map<KICAD_T, std::vector<SCH_TEXT*>> label_map;
4025 return std::count_if( aLocSubgraph->m_items.begin(), aLocSubgraph->m_items.end(),
4028 return item->Type() == SCH_PIN_T;
4033 [&](
SCH_TEXT* aText,
int errCode )
4038 ercItem->SetSheetSpecificPath( sheet );
4039 ercItem->SetItems( aText );
4046 pinCount =
hasPins( aSubgraph );
4050 switch( item->
Type() )
4058 label_map[item->
Type()].push_back(
text );
4063 if(
text->IsDangling() )
4077 if( label_map.empty() )
4082 for(
auto& [ connection, subgraphs ] : aSubgraph->
m_bus_parents )
4086 if( busParent->m_no_connect )
4109 wxCHECK_MSG(
m_schematic,
true, wxS(
"Null m_schematic in CONNECTION_GRAPH::ercCheckLabels" ) );
4116 for(
auto& [type, label_vec] : label_map )
4120 size_t allPins = pinCount;
4128 if( neighbor == aSubgraph )
4134 allPins +=
hasPins( neighbor );
4138 if( allPins == 1 && !has_nc )
4160 std::map<wxString, std::tuple<int, const SCH_ITEM*, SCH_SHEET_PATH>> labelData;
4167 wxString resolvedLabelText =
4170 if( labelData.find( resolvedLabelText ) == labelData.end() )
4172 labelData[resolvedLabelText] = { 1, item, sheet };
4176 std::get<0>( labelData[resolvedLabelText] ) += 1;
4177 std::get<1>( labelData[resolvedLabelText] ) =
nullptr;
4178 std::get<2>( labelData[resolvedLabelText] ) = sheet;
4183 for(
const auto& label : labelData )
4185 if( std::get<0>( label.second ) == 1 )
4188 const SCH_ITEM* item = std::get<1>( label.second );
4191 ercItem->SetItems( std::get<1>( label.second ) );
4192 ercItem->SetSheetSpecificPath( sheet );
4193 ercItem->SetItemsSheetPaths( sheet );
4208 int error_count = 0;
4220 ercItem->SetSheetSpecificPath( sheet );
4221 ercItem->SetItems(
text );
4224 sheet.LastScreen()->Append( marker );
4244 if( sheet.Last()->IsTopLevelSheet() )
4250 wxCHECK2( label,
continue );
4252 msg.Printf(
_(
"Hierarchical label '%s' in root sheet cannot be connected to non-existent "
4256 ercItem->SetItems( item );
4257 ercItem->SetErrorMessage( msg );
4260 sheet.LastScreen()->Append( marker );
4271 parentSheetPath.
push_back( parentSheet );
4273 std::map<wxString, SCH_SHEET_PIN*> pins;
4274 std::map<wxString, SCH_HIERLABEL*> labels;
4279 pins[
pin->GetShownText( &parentSheetPath,
false ) ] =
pin;
4284 ercItem->SetItems(
pin );
4285 ercItem->SetSheetSpecificPath( sheet );
4286 ercItem->SetItemsSheetPaths( sheet );
4289 sheet.LastScreen()->Append( marker );
4297 std::set<wxString> matchedPins;
4304 wxString labelText = label->
GetShownText( &parentSheetPath,
false );
4306 if( !pins.contains( labelText ) )
4307 labels[ labelText ] = label;
4309 matchedPins.insert( labelText );
4313 for(
const wxString& matched : matchedPins )
4314 pins.erase( matched );
4316 for(
const auto& [
name,
pin] : pins )
4318 msg.Printf(
_(
"Sheet pin %s has no matching hierarchical label inside the sheet" ),
4322 ercItem->SetItems(
pin );
4323 ercItem->SetErrorMessage( msg );
4324 ercItem->SetSheetSpecificPath( sheet );
4325 ercItem->SetItemsSheetPaths( sheet );
4328 sheet.LastScreen()->Append( marker );
4333 for(
const auto& [
name, label] : labels )
4335 msg.Printf(
_(
"Hierarchical label %s has no matching sheet pin in the parent sheet" ),
4339 ercItem->SetItems( label );
4340 ercItem->SetErrorMessage( msg );
4341 ercItem->SetSheetSpecificPath( parentSheetPath );
4342 ercItem->SetItemsSheetPaths( parentSheetPath );
constexpr EDA_IU_SCALE schIUScale
This represents a sentry transaction which is used for time-performance metrics You start a transacti...
void StartSpan(const std::string &aOperation, const std::string &aDescription)
int RunERC()
Run electrical rule checks on the connectivity graph.
bool ercCheckBusToBusConflicts(const CONNECTION_SUBGRAPH *aSubgraph)
Check one subgraph for conflicting connections between two bus items.
void processSubGraphs()
Process all subgraphs to assign netcodes and merge subgraphs based on labels.
bool ercCheckLabels(const CONNECTION_SUBGRAPH *aSubgraph)
Check one subgraph for proper connection of labels.
void RemoveItem(SCH_ITEM *aItem)
void collectAllDriverValues()
Map the driver values for each subgraph.
CONNECTION_SUBGRAPH * FindSubgraphByName(const wxString &aNetName, const SCH_SHEET_PATH &aPath)
Return the subgraph for a given net name on a given sheet.
int ercCheckDirectiveLabels()
Check directive labels should be connected to something.
void recacheSubgraphName(CONNECTION_SUBGRAPH *aSubgraph, const wxString &aOldName)
static SCH_CONNECTION * matchBusMember(SCH_CONNECTION *aBusConnection, SCH_CONNECTION *aSearch)
Search for a matching bus member inside a bus connection.
std::unordered_map< wxString, std::shared_ptr< BUS_ALIAS > > m_bus_alias_cache
SCHEMATIC * m_schematic
The schematic this graph represents.
void updateGenericItemConnectivity(const SCH_SHEET_PATH &aSheet, SCH_ITEM *aItem, std::map< VECTOR2I, std::vector< SCH_ITEM * > > &aConnectionMap)
Update the connectivity of items that are not pins or symbols.
std::unordered_map< SCH_SHEET_PATH, std::vector< CONNECTION_SUBGRAPH * > > m_sheet_to_subgraphs_map
Cache to lookup subgraphs in m_driver_subgraphs by sheet path.
void updateSymbolConnectivity(const SCH_SHEET_PATH &aSheet, SCH_SYMBOL *aSymbol, std::map< VECTOR2I, std::vector< SCH_ITEM * > > &aConnectionMap)
Update the connectivity of a symbol and its pins.
CONNECTION_SUBGRAPH * FindFirstSubgraphByName(const wxString &aNetName)
Retrieve a subgraph for the given net name, if one exists.
void propagateToNeighbors(CONNECTION_SUBGRAPH *aSubgraph, bool aForce)
Update all neighbors of a subgraph with this one's connectivity info.
void buildItemSubGraphs()
Generate individual item subgraphs on a per-sheet basis.
const std::vector< CONNECTION_SUBGRAPH * > & GetAllSubgraphs(const wxString &aNetName) const
bool ercCheckMultipleDrivers(const CONNECTION_SUBGRAPH *aSubgraph)
If the subgraph has multiple drivers of equal priority that are graphically connected,...
SCH_SHEET_LIST m_sheetList
All the sheets in the schematic (as long as we don't have partial updates).
void generateGlobalPowerPinSubGraphs()
Iterate through the global power pins to collect the global labels as drivers.
std::unordered_map< wxString, int > m_net_name_to_code_map
int ercCheckSingleGlobalLabel()
Check that a global label is instantiated more that once across the schematic hierarchy.
int ercCheckHierSheets()
Check that a hierarchical sheet has at least one matching label inside the sheet for each port on the...
bool ercCheckBusToNetConflicts(const CONNECTION_SUBGRAPH *aSubgraph)
Check one subgraph for conflicting connections between net and bus labels.
std::shared_ptr< SCH_CONNECTION > getDefaultConnection(SCH_ITEM *aItem, CONNECTION_SUBGRAPH *aSubgraph)
Build a new default connection for the given item based on its properties.
std::vector< const CONNECTION_SUBGRAPH * > GetBusesNeedingMigration()
Determine which subgraphs have more than one conflicting bus label.
void Recalculate(const SCH_SHEET_LIST &aSheetList, bool aUnconditional=false, std::function< void(SCH_ITEM *)> *aChangedItemHandler=nullptr, PROGRESS_REPORTER *aProgressReporter=nullptr)
Update the connection graph for the given list of sheets.
int assignNewNetCode(SCH_CONNECTION &aConnection)
Helper to assign a new net code to a connection.
std::map< std::pair< SCH_SHEET_PATH, wxString >, std::vector< const CONNECTION_SUBGRAPH * > > m_local_label_cache
int getOrCreateNetCode(const wxString &aNetName)
bool ercCheckDanglingWireEndpoints(const CONNECTION_SUBGRAPH *aSubgraph)
Check one subgraph for dangling wire endpoints.
void assignNetCodesToBus(SCH_CONNECTION *aConnection)
Ensure all members of the bus connection have a valid net code assigned.
std::unordered_map< wxString, int > m_bus_name_to_code_map
std::unordered_map< wxString, std::vector< const CONNECTION_SUBGRAPH * > > m_global_label_cache
std::vector< CONNECTION_SUBGRAPH * > m_subgraphs
The owner of all CONNECTION_SUBGRAPH objects.
std::vector< std::pair< SCH_SHEET_PATH, SCH_PIN * > > m_global_power_pins
CONNECTION_GRAPH(SCHEMATIC *aSchematic=nullptr)
bool ercCheckNoConnects(const CONNECTION_SUBGRAPH *aSubgraph)
Check one subgraph for proper presence or absence of no-connect symbols.
size_t hasPins(const CONNECTION_SUBGRAPH *aLocSubgraph)
Get the number of pins in a given subgraph.
std::vector< SCH_ITEM * > m_items
All connectable items in the schematic.
std::unordered_map< wxString, std::vector< CONNECTION_SUBGRAPH * > > m_net_name_to_subgraphs_map
std::shared_ptr< BUS_ALIAS > GetBusAlias(const wxString &aName)
Return a bus alias pointer for the given name if it exists (from cache)
void removeSubgraphs(std::set< CONNECTION_SUBGRAPH * > &aSubgraphs)
Remove references to the given subgraphs from all structures in the connection graph.
std::unordered_map< SCH_ITEM *, CONNECTION_SUBGRAPH * > m_item_to_subgraph_map
std::set< std::pair< SCH_SHEET_PATH, SCH_ITEM * > > ExtractAffectedItems(const std::set< SCH_ITEM * > &aItems)
For a set of items, this will remove the connected items and their associated data including subgraph...
wxString GetResolvedSubgraphName(const CONNECTION_SUBGRAPH *aSubGraph) const
Return the fully-resolved netname for a given subgraph.
bool ercCheckBusToBusEntryConflicts(const CONNECTION_SUBGRAPH *aSubgraph)
Check one subgraph for conflicting bus entry to bus connections.
std::vector< CONNECTION_SUBGRAPH * > m_driver_subgraphs
Cache of a subset of m_subgraphs.
void ExchangeItem(SCH_ITEM *aOldItem, SCH_ITEM *aNewItem)
Replace all references to #aOldItem with #aNewItem in the graph.
NET_MAP m_net_code_to_subgraphs_map
bool ercCheckFloatingWires(const CONNECTION_SUBGRAPH *aSubgraph)
Check one subgraph for floating wires.
void buildConnectionGraph(std::function< void(SCH_ITEM *)> *aChangedItemHandler, bool aUnconditional)
Generate the connection graph (after all item connectivity has been updated).
void Merge(CONNECTION_GRAPH &aGraph)
Combine the input graph contents into the current graph.
void updatePinConnectivity(const SCH_SHEET_PATH &aSheet, SCH_PIN *aPin, SCH_CONNECTION *aConnection)
Update the connectivity of a pin and its connections.
void resolveAllDrivers()
Find all subgraphs in the connection graph and calls ResolveDrivers() in parallel.
void updateItemConnectivity(const SCH_SHEET_PATH &aSheet, const std::vector< SCH_ITEM * > &aItemList)
Update the graphical connectivity between items (i.e.
CONNECTION_SUBGRAPH * GetSubgraphForItem(SCH_ITEM *aItem) const
void generateBusAliasMembers()
Iterate through labels to create placeholders for bus elements.
A subgraph is a set of items that are electrically connected on a single sheet.
wxString driverName(SCH_ITEM *aItem) const
PRIORITY GetDriverPriority()
bool m_strong_driver
True if the driver is "strong": a label or power object.
SCH_ITEM * m_no_connect
No-connect item in graph, if any.
std::set< CONNECTION_SUBGRAPH * > m_absorbed_subgraphs
Set of subgraphs that have been absorbed by this subgraph.
static PRIORITY GetDriverPriority(SCH_ITEM *aDriver)
Return the priority (higher is more important) of a candidate driver.
std::mutex m_driver_name_cache_mutex
A cache of escaped netnames from schematic items.
SCH_SHEET_PATH m_sheet
On which logical sheet is the subgraph contained.
void UpdateItemConnections()
Update all items to match the driver connection.
std::set< SCH_SHEET_PIN * > m_hier_pins
Cache for lookup of any hierarchical (sheet) pins on this subgraph (for referring down).
std::unordered_map< std::shared_ptr< SCH_CONNECTION >, std::unordered_set< CONNECTION_SUBGRAPH * > > m_bus_neighbors
If a subgraph is a bus, this map contains links between the bus members and any local sheet neighbors...
CONNECTION_GRAPH * m_graph
std::vector< SCH_ITEM * > GetAllBusLabels() const
Return all the all bus labels attached to this subgraph (if any).
std::unordered_map< SCH_ITEM *, wxString > m_driver_name_cache
const wxString & GetNameForDriver(SCH_ITEM *aItem) const
Return the candidate net name for a driver.
wxString GetNetName() const
Return the fully-qualified net name for this subgraph (if one exists)
std::vector< SCH_ITEM * > GetVectorBusLabels() const
Return all the vector-based bus labels attached to this subgraph (if any).
const SCH_SHEET_PATH & GetSheet() const
bool m_multiple_drivers
True if this subgraph contains more than one driver that should be shorted together in the netlist.
bool ResolveDrivers(bool aCheckMultipleDrivers=false)
Determine which potential driver should drive the subgraph.
std::set< SCH_ITEM * > m_drivers
bool m_absorbed
True if this subgraph has been absorbed into another. No pointers here are safe if so!
SCH_CONNECTION * m_driver_connection
Cache for driver connection.
CONNECTION_SUBGRAPH * m_absorbed_by
If this subgraph is absorbed, points to the absorbing (and valid) subgraph.
std::unordered_set< CONNECTION_SUBGRAPH * > m_hier_children
If not null, this indicates the subgraph(s) on a lower level sheet that are linked to this one.
void AddItem(SCH_ITEM *aItem)
Add a new item to the subgraph.
const std::vector< std::pair< wxString, SCH_ITEM * > > GetNetclassesForDriver(SCH_ITEM *aItem) const
Return the resolved netclasses for the item, and the source item providing the netclass.
void Absorb(CONNECTION_SUBGRAPH *aOther)
Combine another subgraph on the same sheet into this one.
std::set< SCH_ITEM * > m_items
Contents of the subgraph.
std::unordered_map< std::shared_ptr< SCH_CONNECTION >, std::unordered_set< CONNECTION_SUBGRAPH * > > m_bus_parents
If this is a net, this vector contains links to any same-sheet buses that contain it.
SCH_ITEM * m_driver
Fully-resolved driver for the subgraph (might not exist in this subgraph).
CONNECTION_SUBGRAPH(CONNECTION_GRAPH *aGraph)
std::mutex m_driver_mutex
bool m_is_bus_member
True if the subgraph is not actually part of a net.
void ExchangeItem(SCH_ITEM *aOldItem, SCH_ITEM *aNewItem)
Replaces all references to #aOldItem with #aNewItem in the subgraph.
CONNECTION_SUBGRAPH * m_hier_parent
If not null, this indicates the subgraph on a higher level sheet that is linked to this one.
void RemoveItem(SCH_ITEM *aItem)
bool m_local_driver
True if the driver is a local (i.e. non-global) type.
std::set< SCH_HIERLABEL * > m_hier_ports
Cache for lookup of any hierarchical ports on this subgraph (for referring up).
void getAllConnectedItems(std::set< std::pair< SCH_SHEET_PATH, SCH_ITEM * > > &aItems, std::set< CONNECTION_SUBGRAPH * > &aSubgraphs)
Find all items in the subgraph as well as child subgraphs recursively.
virtual VECTOR2I GetPosition() const
virtual wxString GetItemDescription(UNITS_PROVIDER *aUnitsProvider, bool aFull) const
Return a user-visible description string of this item.
KICAD_T Type() const
Returns the type of object.
EE_TYPE Overlapping(const BOX2I &aRect) const
EE_TYPE OfType(KICAD_T aType) const
static std::shared_ptr< ERC_ITEM > Create(int aErrorCode)
Constructs an ERC_ITEM for the given error code.
Container for ERC settings.
bool IsTestEnabled(int aErrorCode) const
bool GetDuplicatePinNumbersAreJumpers() const
std::vector< std::set< wxString > > & JumperPinGroups()
Each jumper pin group is a set of pin numbers that should be treated as internally connected.
A small class to help profiling.
void Show(std::ostream &aStream=std::cerr)
Print the elapsed time (in a suitable unit) to a stream.
void Stop()
Save the time when this function was called, and set the counter stane to stop.
A progress reporter interface for use in multi-threaded environments.
virtual bool KeepRefreshing(bool aWait=false)=0
Update the UI (if any).
virtual void SetCurrentProgress(double aProgress)=0
Set the progress value to aProgress (0..1).
Class for a bus to bus entry.
SCH_ITEM * m_connected_bus_items[2]
Pointer to the bus items (usually bus wires) connected to this bus-bus entry (either or both may be n...
bool IsStartDangling() const
VECTOR2I GetPosition() const override
bool IsEndDangling() const
std::vector< VECTOR2I > GetConnectionPoints() const override
Add all the connection points for this item to aPoints.
Class for a wire to bus entry.
SCH_ITEM * m_connected_bus_item
Pointer to the bus item (usually a bus wire) connected to this bus-wire entry, if it is connected to ...
Each graphical item can have a SCH_CONNECTION describing its logical connection (to a bus or net).
wxString FullLocalName() const
void ConfigureFromLabel(const wxString &aLabel)
Configures the connection given a label.
void SetSubgraphCode(int aCode)
void SetBusCode(int aCode)
void SetName(const wxString &aName)
SCH_SHEET_PATH Sheet() const
CONNECTION_TYPE Type() const
void SetNetCode(int aCode)
SCH_ITEM * m_driver
The SCH_ITEM that drives this connection's net.
bool IsDriver() const
Checks if the SCH_ITEM this connection is attached to can drive connections Drivers can be labels,...
void SetType(CONNECTION_TYPE aType)
wxString LocalName() const
wxString Name(bool aIgnoreSheet=false) const
bool IsSubsetOf(SCH_CONNECTION *aOther) const
Returns true if this connection is contained within aOther (but not the same as aOther)
void SetDriver(SCH_ITEM *aItem)
void Clone(const SCH_CONNECTION &aOther)
Copies connectivity information (but not parent) from another connection.
void SetGraph(CONNECTION_GRAPH *aGraph)
const std::vector< std::shared_ptr< SCH_CONNECTION > > & Members() const
wxString GetCanonicalName() const
Get a non-language-specific name for a field which can be used for storage, variable look-up,...
wxString GetShownText(const SCH_SHEET_PATH *aPath, bool aAllowExtraText, int aDepth=0) const
Base class for any item which can be embedded within the SCHEMATIC container class,...
void ClearConnectedItems(const SCH_SHEET_PATH &aPath)
Clear all connections to this item.
virtual void RunOnChildren(const std::function< void(SCH_ITEM *)> &aFunction, RECURSE_MODE aMode)
const SYMBOL * GetParentSymbol() const
virtual const wxString & GetCachedDriverName() const
const std::unordered_set< SCH_RULE_AREA * > & GetRuleAreaCache() const
Get the cache of rule areas enclosing this item.
SCH_CONNECTION * InitializeConnection(const SCH_SHEET_PATH &aPath, CONNECTION_GRAPH *aGraph)
Create a new connection object associated with this object.
void AddConnectionTo(const SCH_SHEET_PATH &aPath, SCH_ITEM *aItem)
Add a connection link between this item and another.
SCH_LAYER_ID GetLayer() const
Return the layer this item is on.
void SetConnectionGraph(CONNECTION_GRAPH *aGraph)
Update the connection graph for all connections in this item.
virtual void SetUnit(int aUnit)
virtual bool HasCachedDriverName() const
SCH_CONNECTION * GetOrInitConnection(const SCH_SHEET_PATH &aPath, CONNECTION_GRAPH *aGraph)
SCH_CONNECTION * Connection(const SCH_SHEET_PATH *aSheet=nullptr) const
Retrieve the connection associated with this object in the given sheet.
virtual std::vector< VECTOR2I > GetConnectionPoints() const
Add all the connection points for this item to aPoints.
wxString GetShownText(const SCH_SHEET_PATH *aPath, bool aAllowExtraText, int aDepth=0) const override
bool IsDangling() const override
LABEL_FLAG_SHAPE GetShape() const
Segment description base class to describe items which have 2 end points (track, wire,...
std::vector< VECTOR2I > GetConnectionPoints() const override
Add all the connection points for this item to aPoints.
bool IsStartDangling() const
bool IsEndDangling() const
bool IsGraphicLine() const
Return if the line is a graphic (non electrical line)
bool IsGlobalPower() const
Return whether this pin forms a global power connection: i.e., is part of a power symbol and of type ...
bool IsLocalPower() const
Local power pin is the same except that it is sheet-local and it does not support the legacy hidden p...
SCH_PIN * GetLibPin() const
bool IsStacked(const SCH_PIN *aPin) const
wxString GetDefaultNetName(const SCH_SHEET_PATH &aPath, bool aForceNoConnect=false)
bool IsPower() const
Check if the pin is either a global or local power pin.
ELECTRICAL_PINTYPE GetType() const
void Append(SCH_ITEM *aItem, bool aUpdateLibSymbol=true)
void TestDanglingEnds(const SCH_SHEET_PATH *aPath=nullptr, std::function< void(SCH_ITEM *)> *aChangedHandler=nullptr) const
Test all of the connectable objects in the schematic for unused connection points.
EE_RTREE & Items()
Get the full RTree, usually for iterating.
SCH_LINE * GetBus(const VECTOR2I &aPosition, int aAccuracy=0, SCH_LINE_TEST_T aSearchType=ENTIRE_LENGTH_T) const
A container for handling SCH_SHEET_PATH objects in a flattened hierarchy.
Handle access to a stack of flattened SCH_SHEET objects by way of a path for creating a flattened sch...
const SCH_SHEET * GetSheet(unsigned aIndex) const
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.
@ PT_NC
not connected (must be left open)
@ PT_NIC
not internally connected (may be connected to anything)
@ PT_POWER_IN
power input (GND, VCC for ICs). Must be connected to a power output.
@ BUS
This item represents a bus vector.
@ NET
This item represents a net.
@ BUS_GROUP
This item represents a bus group.
std::vector< SCH_ITEM * > SCH_ITEM_VEC
Definition of the SCH_SHEET_PATH and SCH_SHEET_LIST classes for Eeschema.
std::vector< FAB_LAYER_COLOR > dummy
wxString UnescapeString(const wxString &aSource)
wxString EscapeString(const wxString &aSource, ESCAPE_CONTEXT aContext)
The Escape/Unescape routines use HTML-entity-reference-style encoding to handle characters which are:...
thread_pool & GetKiCadThreadPool()
Get a reference to the current thread pool.
BS::priority_thread_pool thread_pool
Functions to provide common constants and other functions to assist in making a consistent UI.
VECTOR2< int32_t > VECTOR2I