31#include <unordered_map>
32#include <unordered_set>
130 if( old_conn && new_conn )
132 new_conn->
Clone( *old_conn );
166 owner =
pin->GetParentSymbol()->m_Uuid;
167 number =
pin->GetNumber();
200 return pa > pb ? -1 : 1;
207 if( b_in_a && !a_in_b )
210 if( a_in_b && !b_in_a )
219 SYMBOL* parentA =
pinA->GetLibPin() ?
pinA->GetLibPin()->GetParentSymbol() :
nullptr;
225 if( aGlobal != bGlobal )
226 return aGlobal ? -1 : 1;
231 if( aLocal != bLocal )
232 return aLocal ? -1 : 1;
250 bool aLowQuality = aAName.Contains( wxS(
"-Pad" ) );
251 bool bLowQuality = aBName.Contains( wxS(
"-Pad" ) );
253 if( aLowQuality != bLowQuality )
254 return aLowQuality ? 1 : -1;
256 if( aAName < aBName )
259 if( aBName < aAName )
274 std::vector<SCH_ITEM*> candidates;
275 std::set<SCH_ITEM*> strong_drivers;
299 strong_drivers.insert( item );
301 if( item_priority > highest_priority )
304 candidates.push_back( item );
305 highest_priority = item_priority;
307 else if( !candidates.empty() && ( item_priority == highest_priority ) )
309 candidates.push_back( item );
319 if( !candidates.empty() )
332 std::sort( candidates.begin(), candidates.end(), candidate_cmp );
337 if( strong_drivers.size() > 1 )
344 m_drivers.insert( strong_drivers.begin(), strong_drivers.end() );
366 std::set<CONNECTION_SUBGRAPH*>& aSubgraphs )
378 if( aSubgraphs.insert( sg ).second ==
false )
384 aItems.emplace(
m_sheet, item );
398#ifdef CONNECTIVITY_DEBUG
399 wxASSERT_MSG(
false, wxS(
"Tried to get the net name of an item with no connection" ) );
411 std::vector<SCH_ITEM*> labels;
415 switch( item->Type() )
425 labels.push_back( item );
441 std::vector<SCH_ITEM*> labels;
445 switch( item->Type() )
455 labels.push_back( item );
471 switch( aItem->
Type() )
478 return pin->GetDefaultNetName(
m_sheet, forceNoConnect );
505 wxFAIL_MSG( wxS(
"Unhandled item type in GetNameForDriver" ) );
506 return wxEmptyString;
526const std::vector<std::pair<wxString, SCH_ITEM*>>
529 std::vector<std::pair<wxString, SCH_ITEM*>> foundNetclasses;
531 const std::unordered_set<SCH_RULE_AREA*>& ruleAreaCache = aItem->
GetRuleAreaCache();
536 const std::vector<std::pair<wxString, SCH_ITEM*>> ruleAreaNetclasses =
537 ruleArea->GetResolvedNetclasses( &
m_sheet );
539 if( ruleAreaNetclasses.size() > 0 )
541 foundNetclasses.insert( foundNetclasses.end(), ruleAreaNetclasses.begin(),
542 ruleAreaNetclasses.end() );
558 if( netclass != wxEmptyString )
559 foundNetclasses.push_back( { netclass, aItem } );
566 foundNetclasses.begin(), foundNetclasses.end(),
567 [](
const std::pair<wxString, SCH_ITEM*>& i1,
const std::pair<wxString, SCH_ITEM*>& i2 )
569 return i1.first < i2.first;
572 return foundNetclasses;
598 child->m_absorbed_by =
this;
601 set_absorbed_by( subchild );
609 set_absorbed_by( aOther );
659 if(
const std::unique_ptr<LIB_SYMBOL>& part = symbol->GetLibSymbolRef() )
660 return part->GetReferenceField().GetText();
662 return wxEmptyString;
665 switch( aDriver->
Type() )
696 std::back_inserter(
m_items ) );
747 existing.push_back( sg );
768 wxCHECK2( aOldItem->
Type() == aNewItem->
Type(),
return );
777 std::vector<CONNECTION_SUBGRAPH*> sgs = std::move( it->second );
780 sg->ExchangeItem( aOld, aNew );
784 aNew->registerConnectivityOwner(
m_lifetime );
805 wxCHECK2( oldPins.size() == newPins.size(),
return );
807 for(
size_t ii = 0; ii < oldPins.size(); ii++ )
809 exchange( oldPins[ii], newPins[ii] );
820 if( subgraph->m_graph ==
this )
846 std::function<
void(
SCH_ITEM* )>* aChangedItemHandler,
850 PROF_TIMER recalc_time(
"CONNECTION_GRAPH::Recalculate" );
851 monitorTrans.
Start();
856 monitorTrans.
StartSpan(
"updateItemConnectivity",
"" );
857 PROF_TIMER update_items(
"updateItemConnectivity" );
860 std::set<SCH_ITEM*> dirty_items;
862 int count = aSheetList.size() * 2;
867 if( aProgressReporter )
873 std::vector<SCH_ITEM*> items;
876 std::vector<std::pair<SCH_SYMBOL*, int>> symbolsChanged;
878 for(
SCH_ITEM* item : sheet.LastScreen()->Items() )
880 if( item->IsConnectable() && ( aUnconditional || item->IsConnectivityDirty() ) )
882 wxLogTrace(
ConnTrace, wxT(
"Adding item %s to connectivity graph update" ),
883 item->GetTypeDesc() );
884 items.push_back( item );
885 dirty_items.insert( item );
894 if(
pin->IsConnectivityDirty() )
896 dirty_items.insert(
pin );
908 if(
pin->IsConnectivityDirty() )
910 dirty_items.insert(
pin );
923 if(
pin->IsConnectivityDirty() )
925 items.push_back(
pin );
926 dirty_items.insert(
pin );
936 if(
pin->IsConnectivityDirty() )
938 items.push_back(
pin );
939 dirty_items.insert(
pin );
952 if( symbol->
GetUnit() != new_unit )
953 symbolsChanged.push_back( { symbol, symbol->
GetUnit() } );
963 if( aProgressReporter )
970 sheet.LastScreen()->TestDanglingEnds( &sheet, aChangedItemHandler );
973 for(
const auto& [ symbol, originalUnit ] : symbolsChanged )
974 symbol->SetUnit( originalUnit );
985 item->SetConnectivityDirty(
false );
992 PROF_TIMER build_graph(
"buildConnectionGraph" );
993 monitorTrans.
StartSpan(
"BuildConnectionGraph",
"" );
1012 const std::set<SCH_ITEM*> &aItems )
1014 std::set<std::pair<SCH_SHEET_PATH, SCH_ITEM*>> retvals;
1015 std::set<CONNECTION_SUBGRAPH*> subgraphs;
1020 while( aSubgraph->m_absorbed_by )
1023 wxASSERT( aSubgraph->m_graph == aSubgraph->m_absorbed_by->m_graph );
1024 aSubgraph = aSubgraph->m_absorbed_by;
1028 while( aSubgraph->m_hier_parent )
1031 wxASSERT( aSubgraph->m_graph == aSubgraph->m_hier_parent->m_graph );
1032 aSubgraph = aSubgraph->m_hier_parent;
1036 aSubgraph->getAllConnectedItems( retvals, subgraphs );
1039 auto scan_subgraphs = [&traverse_subgraph](
const std::vector<CONNECTION_SUBGRAPH*>& aScanList )
1043 traverse_subgraph( sg );
1045 for(
auto& bus_it : sg->m_bus_neighbors )
1048 traverse_subgraph( bus_sg );
1051 for(
auto& bus_it : sg->m_bus_parents )
1054 traverse_subgraph( bus_sg );
1059 auto extract_element = [&](
SCH_ITEM* aItem )
1065 wxLogTrace(
ConnTrace, wxT(
"Item %s not found in connection graph" ),
1066 aItem->GetTypeDesc() );
1070 if( aItem->HasCachedDriverName() )
1078 wxLogTrace(
ConnTrace, wxT(
"Item %s in subgraph %ld (%p) has no driver" ),
1079 aItem->GetTypeDesc(), item_sg->
m_code, item_sg );
1084 if( sg_to_scan.empty() )
1086 wxLogTrace(
ConnTrace, wxT(
"Item %s in subgraph %ld with net %s has no neighbors" ),
1088 sg_to_scan.push_back( item_sg );
1092 wxT(
"Removing all item %s connections from subgraph %ld with net %s: Found "
1095 sg_to_scan.size() );
1097 scan_subgraphs( sg_to_scan );
1109 extract_element(
pin );
1116 extract_element(
pin );
1120 extract_element( item );
1126 for(
const auto& [
path, item] : retvals )
1158 wxLogTrace(
ConnTrace, wxT(
"Removing %zu subgraphs" ), aSubgraphs.size() );
1161 std::set<int> codes_to_remove;
1165 std::sort( el.second.begin(), el.second.end() );
1170 for(
auto& it : sg->m_bus_neighbors )
1176 for(
auto test = parents.begin();
test != parents.end(); )
1184 if( parents.empty() )
1189 for(
auto& it : sg->m_bus_parents )
1195 for(
auto test = neighbors.begin();
test != neighbors.end(); )
1203 if( neighbors.empty() )
1224 auto it = std::lower_bound( el.second.begin(), el.second.end(), sg );
1226 while( it != el.second.end() && *it == sg )
1227 it = el.second.erase( it );
1230 auto remove_sg = [sg](
auto it ) ->
bool
1243 if( remove_sg( it ) )
1251 if( remove_sg( it ) )
1260 if( remove_sg( it ) )
1262 codes_to_remove.insert( it->first.Netcode );
1274 if( remove_sg( it ) )
1282 std::erase( it->second, sg );
1284 if( it->second.empty() )
1295 if( codes_to_remove.contains( it->second ) )
1303 if( codes_to_remove.contains( it->second ) )
1312 sg->m_graph =
nullptr;
1319 std::map<
VECTOR2I, std::vector<SCH_ITEM*>>& aConnectionMap )
1330 aConn->SetName(
name );
1335 std::map<wxString, std::vector<SCH_PIN*>> pinNumberMap;
1341 updatePin(
pin, conn );
1342 aConnectionMap[
pin->GetPosition() ].push_back(
pin );
1343 pinNumberMap[
pin->GetNumber()].emplace_back(
pin );
1346 auto linkPinsInVec =
1347 [&](
const std::vector<SCH_PIN*>& aVec )
1349 for(
size_t i = 0; i < aVec.size(); ++i )
1351 for(
size_t j = i + 1; j < aVec.size(); ++j )
1353 aVec[i]->AddConnectionTo( aSheet, aVec[j] );
1354 aVec[j]->AddConnectionTo( aSheet, aVec[i] );
1363 for(
const auto& [number,
group] : pinNumberMap )
1364 linkPinsInVec(
group );
1369 std::vector<SCH_PIN*> pins;
1371 for(
const wxString& pinNumber :
group )
1390 pins.emplace_back( found );
1393 linkPinsInVec( pins );
1416 std::map<
VECTOR2I, std::vector<SCH_ITEM*>>& aConnectionMap )
1421 m_items.emplace_back( aItem );
1424 switch( aItem->
Type() )
1437 if( points.empty() )
1438 points = {
static_cast<SCH_PIN*
>( aItem )->GetPosition() };
1451 for(
const VECTOR2I& point : points )
1452 aConnectionMap[point].push_back( aItem );
1457 const std::vector<SCH_ITEM*>& aItemList )
1459 wxLogTrace( wxT(
"Updating connectivity for sheet %s with %zu items" ),
1461 std::map<VECTOR2I, std::vector<SCH_ITEM*>> connection_map;
1465 std::vector<VECTOR2I> points = item->GetConnectionPoints();
1466 item->ClearConnectedItems( aSheet );
1471 pin->InitializeConnection( aSheet,
this );
1473 pin->ClearConnectedItems( aSheet );
1475 connection_map[
pin->GetTextPos() ].push_back(
pin );
1492 VECTOR2I point = item->GetPosition();
1495 std::vector<SCH_ITEM*> overlapping_items;
1497 std::copy_if( items.begin(), items.end(), std::back_inserter( overlapping_items ),
1500 return test_item->Type() == SCH_LINE_T
1501 && test_item->HitTest( point, -1 );
1506 if( overlapping_items.size() < 2 )
continue;
1508 for(
SCH_ITEM* test_item : overlapping_items )
1509 connection_map[point].push_back( test_item );
1518 VECTOR2I point = item->GetPosition();
1522 connection_map[point].push_back( wire );
1527 for(
auto& [point, connection_vec] : connection_map )
1529 std::sort( connection_vec.begin(), connection_vec.end() );
1535 for(
SCH_ITEM* connected_item : connection_vec )
1549 if( connection_vec.size() == 1 )
1565 if( point == bus_entry->GetPosition() )
1568 bus_entry->m_connected_bus_items[1] = busLine;
1581 for(
SCH_ITEM* test_item : connection_vec )
1583 bool bus_connection_ok =
true;
1585 if( test_item == connected_item )
1591 if( test_item->GetLayer() ==
LAYER_BUS )
1610 if( connected_item->ConnectionPropagatesTo( test_item )
1611 && test_item->ConnectionPropagatesTo( connected_item )
1612 && bus_connection_ok )
1614 connected_item->AddConnectionTo( aSheet, test_item );
1625 if( !bus_entry->m_connected_bus_item )
1631 bus_entry->m_connected_bus_item = bus;
1642 wxCHECK_RET(
m_schematic, wxS(
"Connection graph cannot be built without schematic pointer" ) );
1646 for(
const std::shared_ptr<BUS_ALIAS>& alias :
m_schematic->GetAllBusAliases() )
1655 std::unordered_map<SCH_SHEET_PATH, size_t> sheetOrder;
1664 auto it = sheetOrder.find( aSheet );
1666 return ( it == sheetOrder.end() ) ? std::numeric_limits<size_t>::max()
1672 std::vector<std::tuple<size_t, SCH_SHEET_PATH, SCH_CONNECTION*>> ordered;
1677 ordered.reserve( item->m_connection_map.size() );
1681 for(
const auto& [sheet, connection] : item->m_connection_map )
1682 ordered.emplace_back( sheetRank( sheet ), sheet, connection );
1684 std::sort( ordered.begin(), ordered.end(),
1685 [](
const auto& a,
const auto& b )
1687 return std::get<0>( a ) < std::get<0>( b );
1690 for(
const auto& [rank, sheet, connection] : ordered )
1692 if( connection->SubgraphCode() == 0 )
1701 connection->SetSubgraphCode( subgraph->
m_code );
1703 item->registerConnectivityOwner(
m_lifetime );
1705 std::list<SCH_ITEM*> memberlist;
1710 SCH_CONNECTION* conn = aItem->GetOrInitConnection( sheet,
this );
1716 return ( unique && conn && ( conn->
SubgraphCode() == 0 ) );
1719 std::copy_if( item->ConnectedItems( sheet ).begin(),
1720 item->ConnectedItems( sheet ).end(),
1721 std::back_inserter( memberlist ), get_items );
1723 for(
SCH_ITEM* connected_item : memberlist )
1728 SCH_CONNECTION* connected_conn = connected_item->Connection( &sheet );
1730 wxCHECK2( connected_conn,
continue );
1736 connected_item->registerConnectivityOwner(
m_lifetime );
1737 subgraph->
AddItem( connected_item );
1744 if( get_items( citem ) )
1745 memberlist.push_back( citem );
1750 for(
SCH_ITEM* connected_item : memberlist )
1764 std::vector<CONNECTION_SUBGRAPH*> dirty_graphs;
1769 return candidate->m_dirty;
1772 wxLogTrace(
ConnTrace, wxT(
"Resolving drivers for %zu subgraphs" ), dirty_graphs.size() );
1774 std::vector<std::future<size_t>> returns( dirty_graphs.size() );
1776 auto update_lambda =
1779 if( !subgraph->m_dirty )
1783 for(
SCH_ITEM* item : subgraph->m_items )
1785 switch( item->
Type() )
1788 subgraph->m_no_connect = item;
1792 subgraph->m_bus_entry = item;
1800 subgraph->m_no_connect = item;
1810 subgraph->ResolveDrivers(
true );
1811 subgraph->m_dirty =
false;
1818 auto results =
tp.submit_loop( 0, dirty_graphs.size(),
1821 update_lambda( dirty_graphs[ii] );
1830 return candidate->m_driver;
1843 wxString full_name = subgraph->m_driver_connection->Name();
1844 wxString
name = subgraph->m_driver_connection->Name(
true );
1853 wxString prefixOnly = full_name.BeforeFirst(
'[' ) + wxT(
"[]" );
1857 subgraph->m_dirty =
true;
1859 if( subgraph->m_strong_driver )
1861 SCH_ITEM* driver = subgraph->m_driver;
1864 switch( driver->
Type() )
1880 if(
pin->IsGlobalPower() )
1884 else if(
pin->IsLocalPower() )
1891 wxLogTrace(
ConnTrace, wxS(
"Unexpected normal pin %s" ),
1901 wxLogTrace(
ConnTrace, wxS(
"Unexpected strong driver %s" ),
1913 std::vector<CONNECTION_SUBGRAPH*> new_subgraphs;
1917 for(
SCH_ITEM* item : subgraph->GetAllBusLabels() )
1922 dummy.SetGraph(
this );
1925 wxLogTrace(
ConnTrace, wxS(
"new bus label (%s)" ),
1928 for(
const auto& conn :
dummy.Members() )
1931 if( !conn->IsNet() )
1934 wxString
name = conn->FullLocalName();
1941 auto new_conn = std::make_unique<SCH_CONNECTION>( item, subgraph->m_sheet );
1942 new_conn->SetGraph(
this );
1943 new_conn->SetName(
name );
1946 SCH_CONNECTION* new_conn_ptr = subgraph->StoreImplicitConnection( std::move( new_conn ) );
1949 wxLogTrace(
ConnTrace, wxS(
"SG(%ld), Adding full local name (%s) with sg (%d) on subsheet %s" ),
1950 subgraph->m_code,
name, code, subgraph->m_sheet.PathHumanReadable() );
1963 new_subgraphs.push_back( new_sg );
1968 std::copy( new_subgraphs.begin(), new_subgraphs.end(),
1984 [](
const std::pair<SCH_SHEET_PATH, SCH_PIN*>& a,
1985 const std::pair<SCH_SHEET_PATH, SCH_PIN*>& b )
1987 int pathCmp = a.first.Cmp( b.first );
1992 const SCH_SYMBOL* symA = static_cast<const SCH_SYMBOL*>( a.second->GetParentSymbol() );
1993 const SCH_SYMBOL* symB = static_cast<const SCH_SYMBOL*>( b.second->GetParentSymbol() );
1995 wxString refA = symA ? symA->GetRef( &a.first, false ) : wxString();
1996 wxString refB = symB ? symB->GetRef( &b.first, false ) : wxString();
1998 int refCmp = refA.Cmp( refB );
2003 return a.second->GetNumber().Cmp( b.second->GetNumber() ) < 0;
2006 std::unordered_map<int, CONNECTION_SUBGRAPH*> global_power_pin_subgraphs;
2010 SYMBOL* libParent =
pin->GetLibPin() ?
pin->GetLibPin()->GetParentSymbol() :
nullptr;
2012 if( !
pin->ConnectedItems( sheet ).empty()
2038 auto jj = global_power_pin_subgraphs.find( code );
2040 if( jj != global_power_pin_subgraphs.end() )
2042 subgraph = jj->second;
2060 global_power_pin_subgraphs[code] = subgraph;
2073 std::unordered_map<wxString, std::vector<size_t>> weakConflicts;
2082 const wxString
name = connection->
Name();
2086 weakConflicts[
name].push_back( i );
2092 for(
const auto& [
name, positions] : weakConflicts )
2094 if( positions.size() < 2 )
2099 std::vector<std::pair<SUBGRAPH_IDENTITY, CONNECTION_SUBGRAPH*>> ordered;
2100 ordered.reserve( positions.size() );
2102 for(
size_t position : positions )
2110 std::sort( ordered.begin(), ordered.end(),
2111 [](
const auto&
left,
const auto&
right )
2113 return left.first < right.first;
2116 for(
size_t i = 0; i < positions.size(); ++i )
2124 std::unordered_set<CONNECTION_SUBGRAPH*> invalidated_subgraphs;
2128 if( subgraph->m_absorbed )
2133 wxString
name = connection->
Name();
2136 unsigned suffix = 1;
2138 wxString base_name = connection->
Name();
2140 auto create_new_name =
2143 wxString suffixStr = std::to_wstring( suffix );
2150 wxString prefix = aConn->BusPrefix();
2152 if( prefix.empty() )
2153 prefix = wxT(
"BUS" );
2158 wxString members = base_name.Mid( aConn->BusPrefix().length() );
2161 newName << prefix << wxT(
"_" ) << suffixStr << members;
2163 aConn->ConfigureFromLabel( newName );
2169 aConn->SetSuffix( wxString( wxT(
"_" ) ) << suffixStr );
2173 return aConn->Name();
2180 auto promote_sheet_pin_driver =
2183 if( !subgraph->m_driver || subgraph->m_driver->Type() !=
SCH_SHEET_PIN_T )
2186 wxString global_name = connection->
Name(
true );
2193 if( candidate->
m_sheet == sheet )
2196 wxS(
"%ld (%s) skipped for promotion due to potential conflict" ),
2197 subgraph->m_code, connection->
Name() );
2203 subgraph->m_strong_driver =
true;
2206 if( !subgraph->m_strong_driver )
2208 std::vector<CONNECTION_SUBGRAPH*> vec_empty;
2209 std::vector<CONNECTION_SUBGRAPH*>* vec = &vec_empty;
2218 wxString prefixOnly =
name.BeforeFirst(
'[' ) + wxT(
"[]" );
2224 if( vec->size() > 1 )
2226 wxString new_name = create_new_name( connection );
2229 new_name = create_new_name( connection );
2231 wxLogTrace(
ConnTrace, wxS(
"%ld (%s) is weakly driven and not unique. Changing to %s." ),
2232 subgraph->m_code,
name, new_name );
2234 std::erase( *vec, subgraph );
2242 promote_sheet_pin_driver();
2244 else if( subgraph->m_driver )
2246 promote_sheet_pin_driver();
2251 if( connection->
IsBus() )
2275 subgraph->m_dirty =
true;
2283 if( !subgraph->m_strong_driver )
2290 std::vector<CONNECTION_SUBGRAPH*> candidate_subgraphs;
2293 std::back_inserter( candidate_subgraphs ),
2296 return ( !candidate->m_absorbed &&
2297 candidate->m_strong_driver &&
2298 candidate != subgraph );
2304 std::vector< std::shared_ptr<SCH_CONNECTION> > connections_to_check;
2307 connections_to_check.push_back( std::make_shared<SCH_CONNECTION>( *connection ) );
2309 auto add_connections_to_check =
2312 for(
SCH_ITEM* possible_driver : aSubgraph->m_items )
2314 if( possible_driver == aSubgraph->m_driver )
2321 if( c->Type() != aSubgraph->m_driver_connection->Type() )
2324 if( c->Name(
true ) == aSubgraph->m_driver_connection->Name(
true ) )
2327 connections_to_check.push_back( c );
2328 wxLogTrace(
ConnTrace, wxS(
"%lu (%s): Adding secondary driver %s" ),
2330 aSubgraph->m_driver_connection->Name(
true ),
2339 add_connections_to_check( subgraph );
2341 std::set<SCH_CONNECTION*> checked_connections;
2343 for(
unsigned i = 0; i < connections_to_check.size(); i++ )
2345 auto member = connections_to_check[i];
2348 if( !checked_connections.insert( member.get() ).second )
2351 if( member->IsBus() )
2353 connections_to_check.insert( connections_to_check.end(),
2354 member->Members().begin(),
2355 member->Members().end() );
2358 wxString test_name = member->Name(
true );
2362 if( candidate->
m_absorbed || candidate == subgraph )
2378 if( driver == candidate->
m_driver )
2390 &&
pin->GetDefaultNetName( sheet ) == test_name )
2403 if( subgraph->GetNameForDriver( driver ) == test_name )
2416 wxLogTrace(
ConnTrace, wxS(
"%lu (%s) has bus child %lu (%s)" ),
2417 subgraph->m_code, connection->
Name(),
2418 candidate->
m_code, member->Name() );
2420 subgraph->m_bus_neighbors[member].insert( candidate );
2423 else if( ( !connection->
IsBus()
2427 wxLogTrace(
ConnTrace, wxS(
"%lu (%s) absorbs neighbor %lu (%s)" ),
2428 subgraph->m_code, connection->
Name(),
2432 add_connections_to_check( candidate );
2434 subgraph->Absorb( candidate );
2435 invalidated_subgraphs.insert( subgraph );
2445 if( subgraph->m_absorbed )
2448 if( !subgraph->ResolveDrivers() )
2451 if( subgraph->m_driver_connection->IsBus() )
2456 wxLogTrace(
ConnTrace, wxS(
"Re-resolving drivers for %lu (%s)" ),
2457 subgraph->m_code, subgraph->m_driver_connection->Name() );
2476 bool aUnconditional )
2479 wxCHECK_RET(
m_schematic, wxT(
"Connection graph cannot be built without schematic pointer" ) );
2483 for(
const std::shared_ptr<BUS_ALIAS>& alias :
m_schematic->GetAllBusAliases() )
2489 PROF_TIMER sub_graph(
"buildItemSubGraphs" );
2508 PROF_TIMER proc_sub_graph(
"ProcessSubGraphs" );
2512 proc_sub_graph.
Show();
2521 std::vector<CONNECTION_SUBGRAPH*> global_subgraphs;
2523 std::back_inserter( global_subgraphs ),
2526 return !candidate->m_local_driver;
2540 m_driver_subgraphs[ii]->UpdateItemConnections();
2562 if( !global_subgraphs.empty() )
2564 std::unordered_map<CONNECTION_SUBGRAPH*, CONNECTION_SUBGRAPH*> sg_root;
2573 auto it = sg_root.find( cur );
2575 if( it == sg_root.end() || it->second == cur )
2580 auto parent_it = sg_root.find( it->second );
2582 if( parent_it != sg_root.end() && parent_it->second != it->second )
2583 it->second = parent_it->second;
2593 auto prefer_as_representative =
2598 aB->m_driver, aB->m_driver_connection,
2599 aB->m_driver_connection->Name() ) < 0;
2605 sg_root.try_emplace( aA, aA );
2606 sg_root.try_emplace( aB, aB );
2611 if( root_a == root_b )
2614 if( prefer_as_representative( root_a, root_b ) )
2615 sg_root[root_b] = root_a;
2617 sg_root[root_a] = root_b;
2620 std::unordered_map<wxString, std::vector<CONNECTION_SUBGRAPH*>> name_to_sgs;
2624 for(
SCH_ITEM* driver : subgraph->m_drivers )
2632 name_to_sgs[subgraph->GetNameForDriver( driver )].push_back( subgraph );
2636 for(
auto& [
name, sgs] : name_to_sgs )
2638 if( sgs.size() < 2 )
2641 for(
size_t ii = 1; ii < sgs.size(); ++ii )
2642 union_sgs( sgs[0], sgs[ii] );
2648 for(
const auto& entry : sg_root )
2659 wxLogTrace(
ConnTrace, wxS(
"Global %lu (%s) canonicalized to %lu (%s)" ),
2672 if( !subgraph->m_dirty )
2675 wxLogTrace(
ConnTrace, wxS(
"Processing %lu (%s) for propagation" ),
2676 subgraph->m_code, subgraph->m_driver_connection->Name() );
2682 if( !subgraph->m_local_driver && subgraph->m_multiple_drivers )
2684 for(
SCH_ITEM* driver : subgraph->m_drivers )
2686 if( driver == subgraph->m_driver )
2689 const wxString& secondary_name = subgraph->GetNameForDriver( driver );
2691 if( secondary_name == subgraph->m_driver_connection->Name() )
2699 if( candidate == subgraph )
2702 if( !secondary_is_global && candidate->
m_sheet != subgraph->m_sheet )
2709 wxLogTrace(
ConnTrace, wxS(
"Global %lu (%s) promoted to %s" ),
2711 subgraph->m_driver_connection->Name() );
2733 if( subgraph->m_dirty )
2750 wxASSERT_MSG( !subgraph->m_dirty,
2751 wxS(
"Subgraph not processed by propagateToNeighbors!" ) );
2753 if( subgraph->m_bus_parents.size() < 2 )
2758 wxLogTrace(
ConnTrace, wxS(
"%lu (%s) has multiple bus parents" ),
2759 subgraph->m_code, conn->
Name() );
2762 wxCHECK2( conn->
IsNet(),
continue );
2764 for(
const auto& ii : subgraph->m_bus_parents )
2777 wxLogTrace(
ConnTrace, wxS(
"Warning: could not match %s inside %lu (%s)" ),
2782 if( conn->
Name() != match->
Name() )
2784 wxString old_name = match->
Name();
2786 wxLogTrace(
ConnTrace, wxS(
"Updating %lu (%s) member %s to %s" ),
2789 match->
Clone( *conn );
2797 std::vector<CONNECTION_SUBGRAPH*> old_subgraphs = jj->second;
2801 while( old_sg->m_absorbed )
2802 old_sg = old_sg->m_absorbed_by;
2804 wxString old_sg_name = old_sg->m_driver_connection->Name();
2805 old_sg->m_driver_connection->Clone( *conn );
2807 if( old_sg_name != old_sg->m_driver_connection->Name() )
2818 auto propagateConnectionsTask =
2822 if( !subgraph->m_strong_driver
2823 && subgraph->m_drivers.size() == 1
2824 && subgraph->m_driver->Type() ==
SCH_PIN_T )
2827 wxString
name =
pin->GetDefaultNetName( subgraph->m_sheet,
true );
2829 subgraph->m_driver_connection->ConfigureFromLabel(
name );
2832 subgraph->m_dirty =
false;
2833 subgraph->UpdateItemConnections();
2839 propagateConnectionsTask( m_driver_subgraphs[ii] );
2848 if( subgraph->m_driver_connection->IsBus() )
2851 if( !subgraph->m_driver || subgraph->m_driver->Type() !=
SCH_SHEET_PIN_T )
2870 path.push_back( sheet );
2874 if( parent_conn && parent_conn->
IsBus() )
2888 subgraph->m_driver_connection->NetCode() };
2894 std::shared_ptr<NET_SETTINGS>& netSettings =
m_schematic->Project().GetProjectFile().m_NetSettings;
2895 std::map<wxString, std::set<wxString>> oldAssignments = netSettings->GetNetclassLabelAssignments();
2896 std::set<wxString> affectedNetclassNetAssignments;
2898 netSettings->ClearNetclassLabelAssignments();
2900 auto dirtySubgraphs =
2901 [&](
const std::vector<CONNECTION_SUBGRAPH*>& subgraphs )
2903 if( aChangedItemHandler )
2907 for(
SCH_ITEM* item : subgraph->m_items )
2908 (*aChangedItemHandler)( item );
2913 auto checkNetclassDrivers =
2914 [&](
const wxString& netName,
const std::vector<CONNECTION_SUBGRAPH*>& subgraphs )
2916 wxCHECK_RET( !subgraphs.empty(), wxS(
"Invalid empty subgraph" ) );
2918 std::set<wxString> netclasses;
2923 for(
SCH_ITEM* item : subgraph->m_items )
2925 for(
const auto& [
name, provider] : subgraph->GetNetclassesForDriver( item ) )
2926 netclasses.insert(
name );
2933 if( subgraph->m_driver_connection->IsBus() )
2935 auto processBusMember = [&,
this](
const SCH_CONNECTION* member )
2937 if( !netclasses.empty() )
2939 netSettings->AppendNetclassLabelAssignment( member->Name(), netclasses );
2944 if( oldAssignments.count( member->Name() ) )
2946 if( oldAssignments[member->Name()] != netclasses )
2948 affectedNetclassNetAssignments.insert( member->Name() );
2951 dirtySubgraphs( ii->second );
2954 else if( !netclasses.empty() )
2956 affectedNetclassNetAssignments.insert( member->Name() );
2959 dirtySubgraphs( ii->second );
2963 for(
const std::shared_ptr<SCH_CONNECTION>& member : subgraph->m_driver_connection->Members() )
2967 if( member->IsBus() )
2969 for(
const std::shared_ptr<SCH_CONNECTION>& nestedMember : member->Members() )
2970 processBusMember( nestedMember.get() );
2974 processBusMember( member.get() );
2981 if( !netclasses.empty() )
2983 netSettings->AppendNetclassLabelAssignment( netName, netclasses );
2986 if( oldAssignments.count( netName ) )
2988 if( oldAssignments[netName] != netclasses )
2990 affectedNetclassNetAssignments.insert( netName );
2991 dirtySubgraphs( subgraphs );
2994 else if( !netclasses.empty() )
2996 affectedNetclassNetAssignments.insert( netName );
2997 dirtySubgraphs( subgraphs );
3003 checkNetclassDrivers( netname, subgraphs );
3005 if( !aUnconditional )
3007 for(
auto& [netname, netclasses] : oldAssignments )
3009 if( netSettings->GetNetclassLabelAssignments().count( netname )
3010 || affectedNetclassNetAssignments.count( netname ) )
3015 netSettings->SetNetclassLabelAssignment( netname, netclasses );
3038 std::unordered_map<SCH_SHEET_PATH, SCH_CONNECTIVITY::NETCHAIN_INPUT::SHEET*> sheets;
3043 sheets.emplace(
path, &connectivity.
sheets.back() );
3056 const auto sheet = sheets.find( subgraph->GetSheet() );
3058 if( sheet == sheets.end() )
3061 while( subgraph && subgraph->m_absorbed )
3062 subgraph = subgraph->m_absorbed_by;
3066 const wxString
name = subgraph->GetNetName();
3067 sheet->second->nets.insert_or_assign(
3080 const std::map<std::pair<wxString, wxString>, wxString>& aRefPinToNet,
3081 const std::vector<std::unique_ptr<SCH_NETCHAIN>>& aPotentials,
3082 const wxString& aChainName )
3085 aTermRefs, aRefPinToNet, aPotentials, aChainName );
3100 return m_netChains->DeleteCommittedNetChain( aName );
3105 return m_netChains->RenameCommittedNetChain( aOld, aNew );
3117 return m_netChains->CreateNetChainFromPotential( aPotential, aName );
3121 const std::set<SCH_SYMBOL*>& aSymbols,
const std::set<wxString>& aNets,
3122 const KIID& aTerminalPinA,
const KIID& aTerminalPinB,
3123 const wxString& aRefA,
const wxString& aPinNumA,
3124 const wxString& aRefB,
const wxString& aPinNumB )
3126 return m_netChains->CreateManualNetChain( aName, aSymbols, aNets, aTerminalPinA, aTerminalPinB,
3127 aRefA, aPinNumA, aRefB, aPinNumB );
3163 std::vector<std::shared_ptr<SCH_CONNECTION>> connections_to_check( aConnection->
Members() );
3165 for(
unsigned i = 0; i < connections_to_check.size(); i++ )
3167 const std::shared_ptr<SCH_CONNECTION>& member = connections_to_check[i];
3169 if( member->IsBus() )
3171 connections_to_check.insert( connections_to_check.end(),
3172 member->Members().begin(),
3173 member->Members().end() );
3185 std::vector<CONNECTION_SUBGRAPH*> search_list;
3186 std::unordered_set<CONNECTION_SUBGRAPH*> visited;
3187 std::unordered_set<SCH_CONNECTION*> stale_bus_members;
3194 path.push_back(
pin->GetParent() );
3205 || visited.contains( candidate ) )
3214 wxLogTrace(
ConnTrace, wxS(
"%lu: found child %lu (%s)" ), aParent->m_code,
3222 wxASSERT( candidate->
m_graph == aParent->m_graph );
3224 search_list.push_back( candidate );
3244 || visited.contains( candidate )
3250 const KIID& last_parent_uuid = aParent->m_sheet.Last()->m_Uuid;
3255 if(
pin->GetParent()->m_Uuid != last_parent_uuid )
3261 if( pin_path != aParent->m_sheet )
3266 wxLogTrace(
ConnTrace, wxS(
"%lu: found additional parent %lu (%s)" ),
3269 aParent->m_hier_children.insert( candidate );
3270 search_list.push_back( candidate );
3284 std::vector<std::shared_ptr<SCH_CONNECTION>> sortedMembers;
3286 for(
const auto&
kv : aParentGraph->m_bus_neighbors )
3287 sortedMembers.push_back(
kv.first );
3289 std::sort( sortedMembers.begin(), sortedMembers.end(),
3290 [](
const std::shared_ptr<SCH_CONNECTION>& a,
3291 const std::shared_ptr<SCH_CONNECTION>& b )
3293 return a->Name() < b->Name();
3296 for(
const std::shared_ptr<SCH_CONNECTION>& member_conn : sortedMembers )
3298 const auto& kv_it = aParentGraph->m_bus_neighbors.find( member_conn );
3300 if( kv_it == aParentGraph->m_bus_neighbors.end() )
3343 wxLogTrace(
ConnTrace, wxS(
"Could not match bus member %s in %s" ),
3344 member_conn->Name(), parent->
Name() );
3350 wxCHECK2( neighbor_conn,
continue );
3352 wxString neighbor_name = neighbor_conn->
Name();
3355 if( neighbor_name == member->
Name() )
3365 if( neighbor_conn->
Sheet() != parent->
Sheet() )
3376 bool alreadyUpdatedByBusMember =
false;
3378 for(
const auto& m : parent->
Members() )
3380 if( m->Name() == neighbor_name )
3382 alreadyUpdatedByBusMember =
true;
3387 if( alreadyUpdatedByBusMember )
3392 wxCHECK2_MSG( neighbor_conn->
IsNet(),
continue,
3393 wxS(
"\"" ) + neighbor_name + wxS(
"\" is not a net." ) );
3395 wxLogTrace(
ConnTrace, wxS(
"%lu (%s) connected to bus member %s (local %s)" ),
3402 member->
Clone( *neighbor_conn );
3403 stale_bus_members.insert( member );
3407 neighbor_conn->
Clone( *member );
3420 if( neighbor_conn->
Name() != member->
Name() )
3422 member->
Clone( *neighbor_conn );
3423 stale_bus_members.insert( member );
3432 propagate_bus_neighbors( aSubgraph );
3439 wxLogTrace(
ConnTrace, wxS(
"%lu (%s) has both hier ports and pins; deferring processing" ),
3445 wxLogTrace(
ConnTrace, wxS(
"%lu (%s) has no hier pins or ports on sheet %s; marking clean" ),
3451 visited.insert( aSubgraph );
3453 wxLogTrace(
ConnTrace, wxS(
"Propagating %lu (%s) to subsheets" ),
3458 for(
unsigned i = 0; i < search_list.size(); i++ )
3460 auto child = search_list[i];
3462 if( visited.insert( child ).second )
3465 child->m_dirty =
false;
3479 if( subgraph == aSubgraph )
3486 wxString candidateName = subgraph->m_driver_connection->Name();
3487 bool shorterPath = subgraph->m_sheet.size() < bestDriver->
m_sheet.
size();
3488 bool asGoodPath = subgraph->m_sheet.size() <= bestDriver->
m_sheet.
size();
3496 if( ( !bestIsStrong && candidateStrong ) ||
3497 ( priority > highest && candidateStrong ) ||
3498 ( priority == highest && candidateStrong && shorterPath ) ||
3499 ( ( bestIsStrong == candidateStrong ) && asGoodPath && ( priority == highest ) &&
3500 ( candidateName < bestName ) ) )
3502 bestDriver = subgraph;
3504 bestIsStrong = candidateStrong;
3505 bestName = candidateName;
3510 if( bestDriver != aSubgraph )
3512 wxLogTrace(
ConnTrace, wxS(
"%lu (%s) overridden by new driver %lu (%s)" ),
3521 wxString old_name = subgraph->m_driver_connection->Name();
3523 subgraph->m_driver_connection->Clone( *conn );
3525 if( old_name != conn->
Name() )
3529 propagate_bus_neighbors( subgraph );
3535 if( conn->
IsBus() && !stale_bus_members.empty() )
3537 std::unordered_set<SCH_CONNECTION*> cached_members = stale_bus_members;
3547 wxLogTrace(
ConnTrace, wxS(
"WARNING: failed to match stale member %s in %s." ),
3548 stale_member->Name(), subgraph->m_driver_connection->Name() );
3552 wxLogTrace(
ConnTrace, wxS(
"Updating %lu (%s) member %s to %s" ), subgraph->m_code,
3553 subgraph->m_driver_connection->Name(), member->
LocalName(), stale_member->Name() );
3555 member->
Clone( *stale_member );
3557 propagate_bus_neighbors( subgraph );
3569 std::shared_ptr<SCH_CONNECTION> c = std::shared_ptr<SCH_CONNECTION>(
nullptr );
3571 switch( aItem->
Type() )
3574 if(
static_cast<SCH_PIN*
>( aItem )->IsPower() )
3575 c = std::make_shared<SCH_CONNECTION>( aItem, aSubgraph->
m_sheet );
3582 c = std::make_shared<SCH_CONNECTION>( aItem, aSubgraph->
m_sheet );
3591 c->SetGraph(
this );
3602 if( !aBusConnection->
IsBus() )
3612 for(
const std::shared_ptr<SCH_CONNECTION>& bus_member : aBusConnection->
Members() )
3614 if( bus_member->VectorIndex() == aSearch->
VectorIndex() )
3616 match = bus_member.get();
3624 for(
const std::shared_ptr<SCH_CONNECTION>& c : aBusConnection->
Members() )
3631 for(
const std::shared_ptr<SCH_CONNECTION>& bus_member : c->Members() )
3633 if( bus_member->LocalName() == aSearch->
LocalName() )
3635 match = bus_member.get();
3640 else if( c->LocalName() == aSearch->
LocalName() )
3651 for(
const std::shared_ptr<SCH_CONNECTION>& c : aBusConnection->
Members() )
3655 for(
const std::shared_ptr<SCH_CONNECTION>& bus_member : c->Members() )
3659 match = bus_member.get();
3693 std::vector<CONNECTION_SUBGRAPH*>& vec = it->second;
3694 std::erase( vec, aSubgraph );
3697 wxLogTrace(
ConnTrace, wxS(
"recacheSubgraphName: %s => %s" ), aOldName,
3714 std::vector<const CONNECTION_SUBGRAPH*> ret;
3720 wxASSERT( !subgraph->m_dirty );
3722 if( !subgraph->m_driver )
3728 if( !connection->
IsBus() )
3731 auto labels = subgraph->GetVectorBusLabels();
3733 if( labels.size() > 1 )
3735 bool different =
false;
3738 for(
unsigned i = 1; i < labels.size(); ++i )
3750 wxLogTrace(
ConnTrace, wxS(
"SG %ld (%s) has multiple bus labels" ), subgraph->m_code,
3751 connection->
Name() );
3753 ret.push_back( subgraph );
3774 if( graph == aSubGraph )
3795 wxASSERT( !it->second.empty() );
3797 return it->second[0];
3818const std::vector<CONNECTION_SUBGRAPH*>&
3821 static const std::vector<CONNECTION_SUBGRAPH*> subgraphs;
3834 std::vector<wxString> equivalents;
3840 wxString
group = aBusName;
3841 size_t lastSlash = aBusName.find_last_of(
'/' );
3843 if( lastSlash != wxString::npos )
3845 path = aBusName.Left( lastSlash + 1 );
3846 group = aBusName.Mid( lastSlash + 1 );
3850 std::vector<wxString> members;
3856 if( !prefix.IsEmpty() )
3861 for( wxString& member : members )
3863 member.Replace( wxT(
"\\ " ), wxT(
" " ) );
3870 if( members.size() == 1 )
3876 selfAlias = members[0];
3877 members = aliasIt->second->Members();
3882 wxString expandedLabel =
path + wxT(
"{" );
3884 for(
size_t i = 0; i < members.size(); ++i )
3887 expandedLabel += wxT(
" " );
3890 escaped.Replace( wxT(
" " ), wxT(
"\\ " ) );
3891 expandedLabel += escaped;
3894 expandedLabel += wxT(
"}" );
3896 if( expandedLabel != aBusName )
3897 equivalents.push_back( expandedLabel );
3900 std::multiset<wxString> memberSet( members.begin(), members.end() );
3904 if( aliasName == selfAlias || alias->Members().size() != members.size() )
3907 std::multiset<wxString> aliasMembers( alias->Members().begin(), alias->Members().end() );
3909 if( memberSet == aliasMembers )
3910 equivalents.push_back(
path + wxT(
"{" ) + aliasName + wxT(
"}" ) );
3919 int error_count = 0;
3921 wxCHECK_MSG(
m_schematic, 0, wxS(
"Null m_schematic in CONNECTION_GRAPH::RunERC" ) );
3927 std::set<SCH_ITEM*> seenDriverInstances;
3932 wxCHECK2( subgraph,
continue );
3936 wxASSERT( !subgraph->m_dirty );
3938 if( subgraph->m_absorbed )
3941 if( seenDriverInstances.count( subgraph->m_driver ) )
3944 if( subgraph->m_driver )
3945 seenDriverInstances.insert( subgraph->m_driver );
3963 subgraph->ResolveDrivers(
false );
4034 wxCHECK( aSubgraph,
false );
4040 if( driver == aSubgraph->
m_driver )
4051 if( primaryName == secondaryName )
4054 wxString msg = wxString::Format(
_(
"Both %s and %s are attached to the same "
4055 "items; %s will be used in the netlist" ),
4056 primaryName, secondaryName, primaryName );
4059 ercItem->SetItems( aSubgraph->
m_driver, driver );
4060 ercItem->SetSheetSpecificPath( aSubgraph->
GetSheet() );
4061 ercItem->SetItemsSheetPaths( aSubgraph->
GetSheet(), aSubgraph->
m_sheet );
4062 ercItem->SetErrorMessage( msg );
4087 switch( item->
Type() )
4092 bus_item = ( !bus_item ) ? item : bus_item;
4094 net_item = ( !net_item ) ? item : net_item;
4108 bus_item = ( !bus_item ) ? item : bus_item;
4110 net_item = ( !net_item ) ? item : net_item;
4120 if( net_item && bus_item )
4123 ercItem->SetSheetSpecificPath( sheet );
4124 ercItem->SetItems( net_item, bus_item );
4127 screen->
Append( marker );
4146 switch( item->
Type() )
4173 if(
test != member && member->Name() ==
test->Name() )
4187 ercItem->SetSheetSpecificPath( sheet );
4188 ercItem->SetItems( label, port );
4191 screen->
Append( marker );
4203 bool conflict =
false;
4219 switch( item->
Type() )
4249 std::set<wxString> test_names;
4261 for(
const auto& sub_member : member->Members() )
4263 if( test_names.count( sub_member->FullLocalName() ) )
4267 else if( test_names.count( member->FullLocalName() ) )
4286 wxString msg = wxString::Format(
_(
"Net %s is graphically connected to bus %s but is not a"
4287 " member of that bus" ),
4291 ercItem->SetSheetSpecificPath( sheet );
4292 ercItem->SetItems( bus_entry, bus_wire );
4293 ercItem->SetErrorMessage( msg );
4296 screen->
Append( marker );
4313 std::set<SCH_PIN*> unique_pins;
4314 std::set<SCH_LABEL_BASE*> unique_labels;
4322 for(
SCH_ITEM* item : aProcessGraph->m_items )
4324 switch( item->
Type() )
4331 if( aProcessGraph == aSubgraph )
4334 if( std::none_of( unique_pins.begin(), unique_pins.end(),
4337 return test_pin->IsStacked( aPin );
4341 unique_pins.insert( test_pin );
4364 process_subgraph( subgraph );
4369 process_subgraph( aSubgraph );
4385 switch( item->
Type() )
4432 ercItem->SetSheetSpecificPath( sheet );
4433 ercItem->SetItemsSheetPaths( sheet );
4440 pos =
pin->GetPosition();
4449 screen->
Append( marker );
4454 if( unique_pins.empty() && unique_labels.empty() &&
4459 ercItem->SetSheetSpecificPath( sheet );
4460 ercItem->SetItemsSheetPaths( sheet );
4463 screen->
Append( marker );
4470 bool has_other_connections =
false;
4471 std::vector<SCH_PIN*> pins;
4478 switch( item->
Type() )
4485 if( !has_other_connections && !pins.empty()
4488 for(
SCH_PIN* other_pin : pins )
4492 has_other_connections =
true;
4498 pins.emplace_back(
static_cast<SCH_PIN*
>( item ) );
4505 has_other_connections =
true;
4512 pin = pins.empty() ? nullptr : pins[0];
4515 for(
SCH_PIN* test_pin : pins )
4532 ?
pin->GetLibPin()->GetParentSymbol() :
nullptr;
4534 if(
pin && !has_other_connections
4536 && ( !pinLibParent || !pinLibParent->
IsPower() ) )
4538 wxString
name =
pin->Connection( &sheet )->Name();
4539 wxString local_name =
pin->Connection( &sheet )->Name(
true );
4544 has_other_connections =
true;
4549 if(
pin && !has_other_connections
4555 ercItem->SetSheetSpecificPath( sheet );
4556 ercItem->SetItemsSheetPaths( sheet );
4557 ercItem->SetItems(
pin );
4560 screen->
Append( marker );
4568 if( pins.size() > 1 )
4570 for(
SCH_PIN* testPin : pins )
4575 SYMBOL* testLibParent = testPin->GetLibPin()
4579 if( testLibParent && testLibParent->
IsPower()
4580 && testPin->ConnectedItems( sheet ).empty()
4584 ercItem->SetSheetSpecificPath( sheet );
4585 ercItem->SetItemsSheetPaths( sheet );
4586 ercItem->SetItems( testPin );
4589 screen->
Append( marker );
4622 ercItem->SetItems( line );
4623 ercItem->SetSheetSpecificPath( sheet );
4624 ercItem->SetErrorMessage(
_(
"Unconnected wire endpoint" ) );
4646 ercItem->SetItems( entry );
4647 ercItem->SetSheetSpecificPath( sheet );
4648 ercItem->SetErrorMessage(
_(
"Unconnected wire to bus entry" ) );
4665 return err_count > 0;
4675 std::vector<SCH_ITEM*> wires;
4682 wires.emplace_back( item );
4684 wires.emplace_back( item );
4687 if( !wires.empty() )
4692 ercItem->SetSheetSpecificPath( sheet );
4693 ercItem->SetItems( wires[0],
4694 wires.size() > 1 ? wires[1] :
nullptr,
4695 wires.size() > 2 ? wires[2] :
nullptr,
4696 wires.size() > 3 ? wires[3] :
nullptr );
4699 screen->
Append( marker );
4709 std::unordered_set<const CONNECTION_SUBGRAPH*>& aOut )
const
4711 while( aBusParent && aBusParent->
m_absorbed )
4724 for(
const auto& [sibMemberConn, sibMembers] : siblingBus->
m_bus_neighbors )
4726 if( sibMemberConn->Name() != aMemberName )
4730 aOut.insert( sibling );
4755 size_t pinCount = 0;
4758 std::map<KICAD_T, std::vector<SCH_TEXT*>> label_map;
4764 return std::count_if( aLocSubgraph->m_items.begin(), aLocSubgraph->m_items.end(),
4767 return item->Type() == SCH_PIN_T;
4772 [&](
SCH_TEXT* aText,
int errCode )
4777 ercItem->SetSheetSpecificPath( sheet );
4778 ercItem->SetItems( aText );
4785 pinCount =
hasPins( aSubgraph );
4789 switch( item->
Type() )
4797 label_map[item->
Type()].push_back(
text );
4802 if(
text->IsDangling() )
4816 if( label_map.empty() )
4822 std::unordered_set<const CONNECTION_SUBGRAPH*> busMemberSiblings;
4824 for(
auto& [memberConn, busParents] : aSubgraph->
m_bus_parents )
4826 wxString memberName = memberConn->Name();
4830 if( busParent->m_no_connect )
4835 if( hp->m_no_connect )
4845 wxCHECK_MSG(
m_schematic,
true, wxS(
"Null m_schematic in CONNECTION_GRAPH::ercCheckLabels" ) );
4852 for(
auto& [type, label_vec] : label_map )
4856 size_t allPins = pinCount;
4857 size_t localPins = pinCount;
4858 bool hasLocalHierarchy =
false;
4866 std::set<wxString> uniquePortNames;
4870 if( aSubgraph->
m_hier_pins.size() + uniquePortNames.size() > 1 )
4872 hasLocalHierarchy =
true;
4877 for(
auto& [connection, busParents] : aSubgraph->
m_bus_parents )
4881 if( busParent->m_sheet == sheet
4882 && ( !busParent->m_hier_pins.empty()
4883 || !busParent->m_hier_ports.empty() ) )
4885 hasLocalHierarchy =
true;
4890 if( hasLocalHierarchy )
4895 std::unordered_set<const CONNECTION_SUBGRAPH*> creditedNeighbors;
4896 creditedNeighbors.insert( aSubgraph );
4900 if( !creditedNeighbors.insert( neighbor ).second )
4903 if( neighbor->m_no_connect )
4906 size_t neighborPins =
hasPins( neighbor );
4907 allPins += neighborPins;
4909 if( neighbor->m_sheet == sheet )
4911 localPins += neighborPins;
4913 if( !neighbor->m_hier_pins.empty() || !neighbor->m_hier_ports.empty() )
4915 hasLocalHierarchy =
true;
4925 creditNeighbor( neighbor );
4929 creditNeighbor( sibling );
4931 if( allPins == 1 && !has_nc )
4942 || ( type ==
SCH_LABEL_T && localPins == 0 && allPins > 1
4943 && !has_nc && !hasLocalHierarchy ) )
4959 std::map<wxString, std::tuple<int, const SCH_ITEM*, SCH_SHEET_PATH>> labelData;
4968 if( labelData.find( resolvedLabelText ) == labelData.end() )
4970 labelData[resolvedLabelText] = { 1, item, sheet };
4974 std::get<0>( labelData[resolvedLabelText] ) += 1;
4975 std::get<1>( labelData[resolvedLabelText] ) =
nullptr;
4976 std::get<2>( labelData[resolvedLabelText] ) = sheet;
4981 for(
const auto& label : labelData )
4983 if( std::get<0>( label.second ) == 1 )
4986 const SCH_ITEM* item = std::get<1>( label.second );
4989 ercItem->SetItems( std::get<1>( label.second ) );
4990 ercItem->SetSheetSpecificPath( sheet );
4991 ercItem->SetItemsSheetPaths( sheet );
5006 int error_count = 0;
5018 ercItem->SetSheetSpecificPath( sheet );
5019 ercItem->SetItems(
text );
5022 sheet.LastScreen()->Append( marker );
5042 if( sheet.Last()->IsTopLevelSheet() )
5048 wxCHECK2( label,
continue );
5050 msg.Printf(
_(
"Hierarchical label '%s' in root sheet cannot be connected to non-existent "
5054 ercItem->SetItems( item );
5055 ercItem->SetErrorMessage( msg );
5058 sheet.LastScreen()->Append( marker );
5069 parentSheetPath.
push_back( parentSheet );
5071 std::map<wxString, SCH_SHEET_PIN*> pins;
5072 std::map<wxString, SCH_HIERLABEL*> labels;
5082 ercItem->SetItems(
pin );
5083 ercItem->SetSheetSpecificPath( sheet );
5084 ercItem->SetItemsSheetPaths( sheet );
5087 sheet.LastScreen()->Append( marker );
5095 std::set<wxString> matchedPins;
5104 if( !pins.contains( labelText ) )
5105 labels[ labelText ] = label;
5107 matchedPins.insert( labelText );
5111 for(
const wxString& matched : matchedPins )
5112 pins.erase( matched );
5114 for(
const auto& [
name,
pin] : pins )
5116 msg.Printf(
_(
"Sheet pin %s has no matching hierarchical label inside the sheet" ),
5120 ercItem->SetItems(
pin );
5121 ercItem->SetErrorMessage( msg );
5122 ercItem->SetSheetSpecificPath( sheet );
5123 ercItem->SetItemsSheetPaths( sheet );
5126 sheet.LastScreen()->Append( marker );
5131 for(
const auto& [
name, label] : labels )
5133 msg.Printf(
_(
"Hierarchical label %s has no matching sheet pin in the parent sheet" ),
5137 ercItem->SetItems( label );
5138 ercItem->SetErrorMessage( msg );
5139 ercItem->SetSheetSpecificPath( parentSheetPath );
5140 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)
static SCH_NETCHAIN * resolvePotentialChainByTerminals(const CHAIN_TERMINAL_REFS &aTermRefs, const std::map< std::pair< wxString, wxString >, wxString > &aRefPinToNet, const std::vector< std::unique_ptr< SCH_NETCHAIN > > &aPotentials, const wxString &aChainName)
Disambiguate the saved (refA.pinA, refB.pinB) terminal pair against the current set of potential net ...
int RunERC()
Run electrical rule checks on the connectivity graph.
std::shared_ptr< CONNECTION_GRAPH_LIFETIME > m_lifetime
Retired before graph teardown so late item destruction cannot enter this 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.
SCH_NETCHAIN * GetNetChainByName(const wxString &aName)
bool ercCheckLabels(const CONNECTION_SUBGRAPH *aSubgraph)
Check one subgraph for proper connection of labels.
std::unordered_map< SCH_ITEM *, std::vector< CONNECTION_SUBGRAPH * > > m_item_to_subgraph_map
Every subgraph referencing the item, one per instantiating sheet path for items on shared screens.
void RemoveItem(SCH_ITEM *aItem)
void collectAllDriverValues()
Map the driver values for each subgraph.
int ercCheckDirectiveLabels()
Check directive labels should be connected to something.
void recacheSubgraphName(CONNECTION_SUBGRAPH *aSubgraph, const wxString &aOldName)
CONNECTION_GRAPH(SCHEMATIC *aSchematic=nullptr, SCH_CONNECTIVITY::NETCHAIN_MANAGER *aNetChains=nullptr)
static std::function< void(SCH_CONNECTIVITY::NETCHAIN_MANAGER &)> & RebuildNetChainsTestHook()
QA hook receives candidate state before publication and may throw to test rollback.
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.
SCH_NETCHAIN * GetNetChainForNet(const wxString &aNet)
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.
SCH_NETCHAIN * CreateNetChainFromPotential(SCH_NETCHAIN *aPotential, const wxString &aName)
Promote a potential net chain to an actual user net chain with the provided name.
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.
bool RenameCommittedNetChain(const wxString &aOld, const wxString &aNew)
Rename a committed net chain.
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)
void collectBusMemberSiblings(const CONNECTION_SUBGRAPH *aBusParent, const wxString &aMemberName, std::unordered_set< const CONNECTION_SUBGRAPH * > &aOut) const
Find bus members on other sheets that share aBusParent's bus and member name.
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
SCH_NETCHAIN * CreateManualNetChain(const wxString &aName, const std::set< class SCH_SYMBOL * > &aSymbols, const std::set< wxString > &aNets, const KIID &aTerminalPinA, const KIID &aTerminalPinB, const wxString &aRefA, const wxString &aPinNumA, const wxString &aRefB, const wxString &aPinNumB)
Commit a manually-defined net chain that the inferred-potential pass did not produce.
bool ercCheckNoConnects(const CONNECTION_SUBGRAPH *aSubgraph)
Check one subgraph for proper presence or absence of no-connect symbols.
SCH_CONNECTIVITY::NETCHAIN_MANAGER::CHAIN_TERMINAL_REFS CHAIN_TERMINAL_REFS
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.
SCH_CONNECTIVITY::NETCHAIN_MANAGER * m_netChains
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.
std::vector< wxString > GetEquivalentBusNames(const wxString &aBusName) const
Map a bus group name between its alias and expanded forms ({MIXED_BUS} <-> {FOO BAR HAM EGGS}...
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 ApplyNetChainNetclasses()
Mirror each committed net chain's netclass override into the project NET_SETTINGS as a chain-derived ...
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.
bool DeleteCommittedNetChain(const wxString &aName)
Delete a committed net chain by name.
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.
static bool ParseBusGroup(const wxString &aGroup, wxString *name, std::vector< wxString > *aMemberList, size_t *aPrefixEnd=nullptr)
Parse a bus group label into the name and a list of components.
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
Persistent chain configuration and the derived chains for one schematic.
static SCH_NETCHAIN * resolvePotentialChainByTerminals(const CHAIN_TERMINAL_REFS &aTermRefs, const std::map< std::pair< wxString, wxString >, wxString > &aRefPinToNet, const std::vector< std::unique_ptr< SCH_NETCHAIN > > &aPotentials, const wxString &aChainName)
Disambiguate the saved (refA.pinA, refB.pinB) terminal pair against the current set of potential net ...
wxString GetUntranslatedName() const
Get the untranslated field name for storage, variable look-up, etc.
wxString GetShownText(const SCH_SHEET_PATH *aPath, RESOLUTION_CONTEXT aContext, const wxString &aVariantName=wxEmptyString, 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.
const std::vector< SCH_ITEM * > & ConnectedItems(const SCH_SHEET_PATH &aPath) const
Retrieve the set of items connected to this item on the given sheet.
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
void registerConnectivityOwner(const std::shared_ptr< CONNECTION_GRAPH_LIFETIME > &aOwner)
Graph membership belongs to this item identity and must not propagate to clones.
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.
bool IsDangling() const override
LABEL_FLAG_SHAPE GetShape() const
wxString GetShownText(const SCH_SHEET_PATH *aPath, RESOLUTION_CONTEXT aContext, int aDepth=0) const override
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)
A net chain is a collection of nets that are connected together through passive components.
static wxString MakeKey(const wxString &aName, uint32_t aComponent)
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.
std::vector< SCH_LINE * > GetBusesAndWires(const VECTOR2I &aPosition, bool aIgnoreEndpoints=false) const
Return buses and wires passing through aPosition.
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
KIID_PATH Path() const
Get the sheet path as an KIID_PATH.
SCH_SCREEN * LastScreen()
wxString PathHumanReadable(bool aUseShortRootName=true, bool aStripTrailingSeparator=false, bool aEscapeSheetNames=false) const
Return the sheet path in a human readable form made from the sheet names.
SCH_SHEET * Last() const
Return a pointer to the last SCH_SHEET of the list.
void push_back(SCH_SHEET *aSheet)
Forwarded method from std::vector.
size_t size() const
Forwarded method from std::vector.
Define a sheet pin (label) used in sheets to create hierarchical schematics.
SCH_SHEET * GetParent() const
Get the parent sheet object of this sheet pin.
Sheet symbol placed in a schematic, and is the entry point for a sub schematic.
wxString GetFileName() const
Return the filename corresponding to this sheet.
SCH_SCREEN * GetScreen() const
std::vector< SCH_SHEET_PIN * > & GetPins()
std::vector< const SCH_PIN * > GetPins(const SCH_SHEET_PATH *aSheet) const
Retrieve a list of the SCH_PINs for the given sheet path.
bool GetExcludedFromBoard(const SCH_SHEET_PATH *aInstance=nullptr, const wxString &aVariantName=wxEmptyString) const override
int GetUnitSelection(const SCH_SHEET_PATH *aSheet) const
Return the instance-specific unit selection for the given sheet path.
SCH_PIN * GetPin(const wxString &number) const
Find a symbol pin by number.
std::unique_ptr< LIB_SYMBOL > & GetLibSymbolRef()
VECTOR2I GetPosition() const override
virtual wxString GetShownText(const SCH_SHEET_PATH *aPath, RESOLUTION_CONTEXT aContext, int aDepth=0) const
A base class for LIB_SYMBOL and SCH_SYMBOL.
virtual bool IsGlobalPower() const =0
virtual bool IsLocalPower() const =0
virtual bool IsPower() const =0
std::pair< KIID_PATH, DRIVER_IDENTITY > SUBGRAPH_IDENTITY
static int compareDrivers(SCH_ITEM *aA, SCH_CONNECTION *aAConn, const wxString &aAName, SCH_ITEM *aB, SCH_CONNECTION *aBConn, const wxString &aBName)
Unified driver ranking used by CONNECTION_SUBGRAPH::ResolveDrivers (within a single subgraph) and by ...
static DRIVER_IDENTITY stableDriverIdentity(SCH_ITEM *aDriver)
std::tuple< KIID, wxString, int, VECTOR2I > DRIVER_IDENTITY
#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.
bool contains(const _Container &__container, _Value __value)
Returns true if the container contains the given value.
@ 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.
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
wxLogTrace helper definitions.
Functions to provide common constants and other functions to assist in making a consistent UI.
VECTOR2< int32_t > VECTOR2I