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 );
580 switch( aDriver->
Type() )
610 std::back_inserter(
m_items ) );
667 wxCHECK2( aOldItem->
Type() == aNewItem->
Type(),
return );
702 wxCHECK2( oldPins.size() == newPins.size(),
return );
704 for(
size_t ii = 0; ii < oldPins.size(); ii++ )
706 exchange( oldPins[ii], newPins[ii] );
717 if( subgraph->m_graph ==
this )
741 std::function<
void(
SCH_ITEM* )>* aChangedItemHandler,
745 PROF_TIMER recalc_time(
"CONNECTION_GRAPH::Recalculate" );
746 monitorTrans.
Start();
751 monitorTrans.
StartSpan(
"updateItemConnectivity",
"" );
752 PROF_TIMER update_items(
"updateItemConnectivity" );
755 std::set<SCH_ITEM*> dirty_items;
757 int count = aSheetList.size() * 2;
762 if( aProgressReporter )
768 std::vector<SCH_ITEM*> items;
771 std::vector<std::pair<SCH_SYMBOL*, int>> symbolsChanged;
773 for(
SCH_ITEM* item : sheet.LastScreen()->Items() )
775 if( item->IsConnectable() && ( aUnconditional || item->IsConnectivityDirty() ) )
777 wxLogTrace(
ConnTrace, wxT(
"Adding item %s to connectivity graph update" ),
778 item->GetTypeDesc() );
779 items.push_back( item );
780 dirty_items.insert( item );
789 if(
pin->IsConnectivityDirty() )
791 dirty_items.insert(
pin );
804 if(
pin->IsConnectivityDirty() )
806 items.push_back(
pin );
807 dirty_items.insert(
pin );
817 if(
pin->IsConnectivityDirty() )
819 items.push_back(
pin );
820 dirty_items.insert(
pin );
833 if( symbol->
GetUnit() != new_unit )
834 symbolsChanged.push_back( { symbol, symbol->
GetUnit() } );
844 if( aProgressReporter )
851 sheet.LastScreen()->TestDanglingEnds( &sheet, aChangedItemHandler );
854 for(
const auto& [ symbol, originalUnit ] : symbolsChanged )
855 symbol->SetUnit( originalUnit );
861 aChangedItemHandler );
864 item->SetConnectivityDirty(
false );
871 PROF_TIMER build_graph(
"buildConnectionGraph" );
872 monitorTrans.
StartSpan(
"BuildConnectionGraph",
"" );
891 const std::set<SCH_ITEM*> &aItems )
893 std::set<std::pair<SCH_SHEET_PATH, SCH_ITEM*>> retvals;
894 std::set<CONNECTION_SUBGRAPH*> subgraphs;
899 while( aSubgraph->m_absorbed_by )
902 wxASSERT( aSubgraph->m_graph == aSubgraph->m_absorbed_by->m_graph );
903 aSubgraph = aSubgraph->m_absorbed_by;
907 while( aSubgraph->m_hier_parent )
910 wxASSERT( aSubgraph->m_graph == aSubgraph->m_hier_parent->m_graph );
911 aSubgraph = aSubgraph->m_hier_parent;
915 aSubgraph->getAllConnectedItems( retvals, subgraphs );
918 auto extract_element = [&](
SCH_ITEM* aItem )
924 wxLogTrace(
ConnTrace, wxT(
"Item %s not found in connection graph" ),
925 aItem->GetTypeDesc() );
931 wxLogTrace(
ConnTrace, wxT(
"Item %s in subgraph %ld (%p) has no driver" ),
932 aItem->GetTypeDesc(), item_sg->
m_code, item_sg );
937 if( sg_to_scan.empty() )
939 wxLogTrace(
ConnTrace, wxT(
"Item %s in subgraph %ld with net %s has no neighbors" ),
941 sg_to_scan.push_back( item_sg );
945 wxT(
"Removing all item %s connections from subgraph %ld with net %s: Found "
952 traverse_subgraph( sg );
954 for(
auto& bus_it : sg->m_bus_neighbors )
957 traverse_subgraph( bus_sg );
960 for(
auto& bus_it : sg->m_bus_parents )
963 traverse_subgraph( bus_sg );
977 extract_element(
pin );
984 extract_element(
pin );
988 extract_element( item );
994 for(
const auto& [
path, item] : retvals )
1021 wxLogTrace(
ConnTrace, wxT(
"Removing %zu subgraphs" ), aSubgraphs.size() );
1024 std::set<int> codes_to_remove;
1028 std::sort( el.second.begin(), el.second.end() );
1033 for(
auto& it : sg->m_bus_neighbors )
1039 for(
auto test = parents.begin();
test != parents.end(); )
1047 if( parents.empty() )
1052 for(
auto& it : sg->m_bus_parents )
1058 for(
auto test = neighbors.begin();
test != neighbors.end(); )
1066 if( neighbors.empty() )
1087 auto it = std::lower_bound( el.second.begin(), el.second.end(), sg );
1089 while( it != el.second.end() && *it == sg )
1090 it = el.second.erase( it );
1093 auto remove_sg = [sg](
auto it ) ->
bool
1106 if( remove_sg( it ) )
1114 if( remove_sg( it ) )
1123 if( remove_sg( it ) )
1125 codes_to_remove.insert( it->first.Netcode );
1137 if( remove_sg( it ) )
1145 if( it->second == sg )
1156 if( codes_to_remove.contains( it->second ) )
1164 if( codes_to_remove.contains( it->second ) )
1173 sg->m_graph =
nullptr;
1181 std::map<
VECTOR2I, std::vector<SCH_ITEM*>>& aConnectionMap )
1191 aConn->SetName(
name );
1196 std::map<wxString, std::vector<SCH_PIN*>> pinNumberMap;
1202 updatePin(
pin, conn );
1203 aConnectionMap[
pin->GetPosition() ].push_back(
pin );
1204 pinNumberMap[
pin->GetNumber()].emplace_back(
pin );
1207 auto linkPinsInVec = [&](
const std::vector<SCH_PIN*>& aVec )
1209 for(
size_t i = 0; i < aVec.size(); ++i )
1211 for(
size_t j = i + 1; j < aVec.size(); ++j )
1213 aVec[i]->AddConnectionTo( aSheet, aVec[j] );
1214 aVec[j]->AddConnectionTo( aSheet, aVec[i] );
1223 for(
const auto& [number,
group] : pinNumberMap )
1224 linkPinsInVec(
group );
1229 std::vector<SCH_PIN*> pins;
1231 for(
const wxString& pinNumber :
group )
1232 pins.emplace_back( aSymbol->
GetPin( pinNumber ) );
1234 linkPinsInVec( pins );
1257 std::map<
VECTOR2I, std::vector<SCH_ITEM*>>& aConnectionMap )
1262 m_items.emplace_back( aItem );
1265 switch( aItem->
Type() )
1278 if( points.empty() )
1279 points = {
static_cast<SCH_PIN*
>( aItem )->GetPosition() };
1292 for(
const VECTOR2I& point : points )
1293 aConnectionMap[point].push_back( aItem );
1298 const std::vector<SCH_ITEM*>& aItemList )
1300 wxLogTrace( wxT(
"Updating connectivity for sheet %s with %zu items" ),
1302 std::map<VECTOR2I, std::vector<SCH_ITEM*>> connection_map;
1306 std::vector<VECTOR2I> points = item->GetConnectionPoints();
1307 item->ClearConnectedItems( aSheet );
1313 pin->InitializeConnection( aSheet,
this );
1315 pin->ClearConnectedItems( aSheet );
1317 connection_map[
pin->GetTextPos() ].push_back(
pin );
1334 VECTOR2I point = item->GetPosition();
1337 std::vector<SCH_ITEM*> overlapping_items;
1339 std::copy_if( items.begin(), items.end(), std::back_inserter( overlapping_items ),
1342 return test_item->Type() == SCH_LINE_T
1343 && test_item->HitTest( point, -1 );
1348 if( overlapping_items.size() < 2 )
continue;
1350 for(
SCH_ITEM* test_item : overlapping_items )
1351 connection_map[point].push_back( test_item );
1356 for(
const auto& it : connection_map )
1358 std::vector<SCH_ITEM*> connection_vec = it.second;
1359 std::sort( connection_vec.begin(), connection_vec.end() );
1365 for(
SCH_ITEM* connected_item : connection_vec )
1379 if( connection_vec.size() == 1 )
1396 if( it.first == bus_entry->GetPosition() )
1399 bus_entry->m_connected_bus_items[1] = busLine;
1413 for(
SCH_ITEM* test_item : connection_vec )
1415 bool bus_connection_ok =
true;
1417 if( test_item == connected_item )
1423 if( test_item->GetLayer() ==
LAYER_BUS )
1442 if( connected_item->ConnectionPropagatesTo( test_item ) &&
1443 test_item->ConnectionPropagatesTo( connected_item ) &&
1446 connected_item->AddConnectionTo( aSheet, test_item );
1457 if( !bus_entry->m_connected_bus_item )
1463 bus_entry->m_connected_bus_item = bus;
1474 wxCHECK_RET(
m_schematic, wxS(
"Connection graph cannot be built without schematic pointer" ) );
1480 for(
const std::shared_ptr<BUS_ALIAS>& alias : screen->GetBusAliases() )
1487 for(
const auto& it : item->m_connection_map )
1504 std::list<SCH_ITEM*> memberlist;
1509 SCH_CONNECTION* conn = aItem->GetOrInitConnection( sheet,
this );
1515 return ( unique && conn && ( conn->
SubgraphCode() == 0 ) );
1518 std::copy_if( item->ConnectedItems( sheet ).begin(),
1519 item->ConnectedItems( sheet ).end(),
1520 std::back_inserter( memberlist ), get_items );
1522 for(
SCH_ITEM* connected_item : memberlist )
1527 SCH_CONNECTION* connected_conn = connected_item->Connection( &sheet );
1529 wxCHECK2( connected_conn,
continue );
1535 subgraph->
AddItem( connected_item );
1536 const SCH_ITEM_VEC& citemset = connected_item->ConnectedItems( sheet );
1543 if( get_items( citem ) )
1544 memberlist.push_back( citem );
1549 for(
SCH_ITEM* connected_item : memberlist )
1564 std::vector<CONNECTION_SUBGRAPH*> dirty_graphs;
1569 return candidate->m_dirty;
1572 wxLogTrace(
ConnTrace, wxT(
"Resolving drivers for %zu subgraphs" ), dirty_graphs.size() );
1574 std::vector<std::future<size_t>> returns( dirty_graphs.size() );
1578 if( !subgraph->m_dirty )
1582 for(
SCH_ITEM* item : subgraph->m_items )
1584 switch( item->
Type() )
1587 subgraph->m_no_connect = item;
1591 subgraph->m_bus_entry = item;
1599 subgraph->m_no_connect = item;
1609 subgraph->ResolveDrivers(
true );
1610 subgraph->m_dirty =
false;
1617 auto results =
tp.submit_loop( 0, dirty_graphs.size(),
1620 update_lambda( dirty_graphs[ii] );
1629 return candidate->m_driver;
1642 wxString full_name = subgraph->m_driver_connection->Name();
1643 wxString
name = subgraph->m_driver_connection->Name(
true );
1652 wxString prefixOnly = full_name.BeforeFirst(
'[' ) + wxT(
"[]" );
1656 subgraph->m_dirty =
true;
1658 if( subgraph->m_strong_driver )
1660 SCH_ITEM* driver = subgraph->m_driver;
1663 switch( driver->
Type() )
1679 if(
pin->IsGlobalPower() )
1683 else if(
pin->IsLocalPower() )
1690 wxLogTrace(
ConnTrace, wxS(
"Unexpected normal pin %s" ),
1700 wxLogTrace(
ConnTrace, wxS(
"Unexpected strong driver %s" ),
1712 std::vector<CONNECTION_SUBGRAPH*> new_subgraphs;
1723 dummy.SetGraph(
this );
1726 wxLogTrace(
ConnTrace, wxS(
"new bus label (%s)" ),
1729 for(
const auto& conn :
dummy.Members() )
1731 wxString
name = conn->FullLocalName();
1742 subgraph->StoreImplicitConnection( new_conn );
1745 wxLogTrace(
ConnTrace, wxS(
"SG(%ld), Adding full local name (%s) with sg (%d) on subsheet %s" ),
1746 subgraph->m_code,
name, code, subgraph->m_sheet.PathHumanReadable() );
1759 new_subgraphs.push_back( new_sg );
1764 std::copy( new_subgraphs.begin(), new_subgraphs.end(),
1776 std::unordered_map<int, CONNECTION_SUBGRAPH*> global_power_pin_subgraphs;
1780 if( !
pin->ConnectedItems( sheet ).empty()
1781 && !
pin->GetLibPin()->GetParentSymbol()->IsGlobalPower() )
1796 if(
pin->GetLibPin()->GetParentSymbol()->IsGlobalPower() )
1797 connection->
SetName(
pin->GetParentSymbol()->GetValue(
true, &sheet,
false ) );
1806 auto jj = global_power_pin_subgraphs.find( code );
1808 if( jj != global_power_pin_subgraphs.end() )
1810 subgraph = jj->second;
1828 global_power_pin_subgraphs[code] = subgraph;
1845 std::unordered_set<CONNECTION_SUBGRAPH*> invalidated_subgraphs;
1849 if( subgraph->m_absorbed )
1854 wxString
name = connection->
Name();
1857 unsigned suffix = 1;
1859 auto create_new_name =
1863 wxString suffixStr = std::to_wstring( suffix );
1870 wxString prefix = aConn->BusPrefix();
1872 if( prefix.empty() )
1873 prefix = wxT(
"BUS" );
1875 wxString oldName = aConn->Name().AfterFirst(
'{' );
1877 newName << prefix << wxT(
"_" ) << suffixStr << wxT(
"{" ) << oldName;
1879 aConn->ConfigureFromLabel( newName );
1883 newName << aConn->Name() << wxT(
"_" ) << suffixStr;
1884 aConn->SetSuffix( wxString( wxT(
"_" ) ) << suffixStr );
1891 if( !subgraph->m_strong_driver )
1893 std::vector<CONNECTION_SUBGRAPH*> vec_empty;
1894 std::vector<CONNECTION_SUBGRAPH*>* vec = &vec_empty;
1903 wxString prefixOnly =
name.BeforeFirst(
'[' ) + wxT(
"[]" );
1909 if( vec->size() > 1 )
1911 wxString new_name = create_new_name( connection );
1914 new_name = create_new_name( connection );
1916 wxLogTrace(
ConnTrace, wxS(
"%ld (%s) is weakly driven and not unique. Changing to %s." ),
1917 subgraph->m_code,
name, new_name );
1919 std::erase( *vec, subgraph );
1925 else if( subgraph->m_driver )
1937 bool conflict =
false;
1938 wxString global_name = connection->
Name(
true );
1945 std::vector<CONNECTION_SUBGRAPH*>& candidates = kk->second;
1949 if( candidate->m_sheet == sheet )
1956 wxLogTrace(
ConnTrace, wxS(
"%ld (%s) skipped for promotion due to potential conflict" ),
1957 subgraph->m_code,
name );
1963 wxLogTrace(
ConnTrace, wxS(
"%ld (%s) weakly driven by unique sheet pin %s, promoting" ),
1964 subgraph->m_code,
name,
1965 subgraph->m_driver->GetItemDescription( &unitsProvider,
true ) );
1967 subgraph->m_strong_driver =
true;
1974 if( connection->
IsBus() )
1998 subgraph->m_dirty =
true;
2006 if( !subgraph->m_strong_driver )
2013 std::vector<CONNECTION_SUBGRAPH*> candidate_subgraphs;
2016 std::back_inserter( candidate_subgraphs ),
2019 return ( !candidate->m_absorbed &&
2020 candidate->m_strong_driver &&
2021 candidate != subgraph );
2027 std::vector< std::shared_ptr<SCH_CONNECTION> > connections_to_check;
2030 connections_to_check.push_back( std::make_shared<SCH_CONNECTION>( *connection ) );
2032 auto add_connections_to_check =
2035 for(
SCH_ITEM* possible_driver : aSubgraph->m_items )
2037 if( possible_driver == aSubgraph->m_driver )
2044 if( c->Type() != aSubgraph->m_driver_connection->Type() )
2047 if( c->Name(
true ) == aSubgraph->m_driver_connection->Name(
true ) )
2050 connections_to_check.push_back( c );
2051 wxLogTrace(
ConnTrace, wxS(
"%lu (%s): Adding secondary driver %s" ),
2053 aSubgraph->m_driver_connection->Name(
true ),
2062 add_connections_to_check( subgraph );
2064 std::set<SCH_CONNECTION*> checked_connections;
2066 for(
unsigned i = 0; i < connections_to_check.size(); i++ )
2068 auto member = connections_to_check[i];
2071 if( !checked_connections.insert( member.get() ).second )
2074 if( member->IsBus() )
2076 connections_to_check.insert( connections_to_check.end(),
2077 member->Members().begin(),
2078 member->Members().end() );
2081 wxString test_name = member->Name(
true );
2085 if( candidate->
m_absorbed || candidate == subgraph )
2101 if( driver == candidate->
m_driver )
2113 &&
pin->GetDefaultNetName( sheet ) == test_name )
2126 if( subgraph->GetNameForDriver( driver ) == test_name )
2139 wxLogTrace(
ConnTrace, wxS(
"%lu (%s) has bus child %lu (%s)" ),
2140 subgraph->m_code, connection->
Name(),
2141 candidate->
m_code, member->Name() );
2143 subgraph->m_bus_neighbors[member].insert( candidate );
2146 else if( !connection->
IsBus()
2149 wxLogTrace(
ConnTrace, wxS(
"%lu (%s) absorbs neighbor %lu (%s)" ),
2150 subgraph->m_code, connection->
Name(),
2154 add_connections_to_check( candidate );
2156 subgraph->Absorb( candidate );
2157 invalidated_subgraphs.insert( subgraph );
2167 if( subgraph->m_absorbed )
2170 if( !subgraph->ResolveDrivers() )
2173 if( subgraph->m_driver_connection->IsBus() )
2178 wxLogTrace(
ConnTrace, wxS(
"Re-resolving drivers for %lu (%s)" ),
2179 subgraph->m_code, subgraph->m_driver_connection->Name() );
2198 bool aUnconditional )
2201 wxCHECK_RET(
m_schematic, wxT(
"Connection graph cannot be built without schematic pointer" ) );
2207 for(
const std::shared_ptr<BUS_ALIAS>& alias : screen->GetBusAliases() )
2211 PROF_TIMER sub_graph(
"buildItemSubGraphs" );
2230 PROF_TIMER proc_sub_graph(
"ProcessSubGraphs" );
2234 proc_sub_graph.
Show();
2243 std::vector<CONNECTION_SUBGRAPH*> global_subgraphs;
2245 std::back_inserter( global_subgraphs ),
2248 return !candidate->m_local_driver;
2262 m_driver_subgraphs[ii]->UpdateItemConnections();
2272 if( !subgraph->m_dirty )
2275 wxLogTrace(
ConnTrace, wxS(
"Processing %lu (%s) for propagation" ),
2276 subgraph->m_code, subgraph->m_driver_connection->Name() );
2282 if( !subgraph->m_local_driver && subgraph->m_multiple_drivers )
2284 for(
SCH_ITEM* driver : subgraph->m_drivers )
2286 if( driver == subgraph->m_driver )
2289 const wxString& secondary_name = subgraph->GetNameForDriver( driver );
2291 if( secondary_name == subgraph->m_driver_connection->Name() )
2299 if( candidate == subgraph )
2302 if( !secondary_is_global && candidate->
m_sheet != subgraph->m_sheet )
2309 wxLogTrace(
ConnTrace, wxS(
"Global %lu (%s) promoted to %s" ),
2311 subgraph->m_driver_connection->Name() );
2333 if( subgraph->m_dirty )
2350 wxASSERT_MSG( !subgraph->m_dirty,
2351 wxS(
"Subgraph not processed by propagateToNeighbors!" ) );
2353 if( subgraph->m_bus_parents.size() < 2 )
2358 wxLogTrace(
ConnTrace, wxS(
"%lu (%s) has multiple bus parents" ),
2359 subgraph->m_code, conn->
Name() );
2362 wxCHECK2( conn->
IsNet(),
continue );
2364 for(
const auto& ii : subgraph->m_bus_parents )
2377 wxLogTrace(
ConnTrace, wxS(
"Warning: could not match %s inside %lu (%s)" ),
2382 if( conn->
Name() != match->
Name() )
2384 wxString old_name = match->
Name();
2386 wxLogTrace(
ConnTrace, wxS(
"Updating %lu (%s) member %s to %s" ),
2389 match->
Clone( *conn );
2408 auto updateItemConnectionsTask =
2412 if( !subgraph->m_strong_driver && subgraph->m_drivers.size() == 1 &&
2413 subgraph->m_driver->Type() ==
SCH_PIN_T )
2416 wxString
name =
pin->GetDefaultNetName( subgraph->m_sheet,
true );
2418 subgraph->m_driver_connection->ConfigureFromLabel(
name );
2421 subgraph->m_dirty =
false;
2422 subgraph->UpdateItemConnections();
2425 if( subgraph->m_driver_connection->IsBus() )
2430 if( subgraph->m_driver && subgraph->m_driver->Type() ==
SCH_SHEET_PIN_T )
2436 wxString pinText =
pin->GetShownText(
false );
2443 if( label->
GetShownText( &subgraph->m_sheet,
false ) == pinText )
2446 path.push_back( sheet );
2450 if( parent_conn && parent_conn->
IsBus() )
2457 if( subgraph->m_driver_connection->IsBus() )
2468 updateItemConnectionsTask( m_driver_subgraphs[ii] );
2478 subgraph->m_driver_connection->NetCode() };
2484 std::shared_ptr<NET_SETTINGS>& netSettings =
m_schematic->Project().GetProjectFile().m_NetSettings;
2485 std::map<wxString, std::set<wxString>> oldAssignments = netSettings->GetNetclassLabelAssignments();
2486 std::set<wxString> affectedNetclassNetAssignments;
2488 netSettings->ClearNetclassLabelAssignments();
2490 auto dirtySubgraphs =
2491 [&](
const std::vector<CONNECTION_SUBGRAPH*>& subgraphs )
2493 if( aChangedItemHandler )
2497 for(
SCH_ITEM* item : subgraph->m_items )
2498 (*aChangedItemHandler)( item );
2503 auto checkNetclassDrivers =
2504 [&](
const wxString& netName,
const std::vector<CONNECTION_SUBGRAPH*>& subgraphs )
2506 wxCHECK_RET( !subgraphs.empty(), wxS(
"Invalid empty subgraph" ) );
2508 std::set<wxString> netclasses;
2513 for(
SCH_ITEM* item : subgraph->m_items )
2515 for(
const auto& [
name, provider] : subgraph->GetNetclassesForDriver( item ) )
2516 netclasses.insert(
name );
2523 if( subgraph->m_driver_connection->IsBus() )
2525 auto processBusMember = [&,
this](
const SCH_CONNECTION* member )
2527 if( !netclasses.empty() )
2529 netSettings->AppendNetclassLabelAssignment( member->Name(), netclasses );
2534 if( oldAssignments.count( member->Name() ) )
2536 if( oldAssignments[member->Name()] != netclasses )
2538 affectedNetclassNetAssignments.insert( member->Name() );
2541 dirtySubgraphs( ii->second );
2544 else if( !netclasses.empty() )
2546 affectedNetclassNetAssignments.insert( member->Name() );
2549 dirtySubgraphs( ii->second );
2553 for(
const std::shared_ptr<SCH_CONNECTION>& member : subgraph->m_driver_connection->Members() )
2557 if( member->IsBus() )
2559 for(
const std::shared_ptr<SCH_CONNECTION>& nestedMember : member->Members() )
2560 processBusMember( nestedMember.get() );
2564 processBusMember( member.get() );
2571 if( !netclasses.empty() )
2573 netSettings->AppendNetclassLabelAssignment( netName, netclasses );
2576 if( oldAssignments.count( netName ) )
2578 if( oldAssignments[netName] != netclasses )
2580 affectedNetclassNetAssignments.insert( netName );
2581 dirtySubgraphs( subgraphs );
2584 else if( !netclasses.empty() )
2586 affectedNetclassNetAssignments.insert( netName );
2587 dirtySubgraphs( subgraphs );
2593 checkNetclassDrivers( netname, subgraphs );
2595 if( !aUnconditional )
2597 for(
auto& [netname, netclasses] : oldAssignments )
2599 if( netSettings->GetNetclassLabelAssignments().count( netname )
2600 || affectedNetclassNetAssignments.count( netname ) )
2605 netSettings->SetNetclassLabelAssignment( netname, netclasses );
2643 std::vector<std::shared_ptr<SCH_CONNECTION>> connections_to_check( aConnection->
Members() );
2645 for(
unsigned i = 0; i < connections_to_check.size(); i++ )
2647 const std::shared_ptr<SCH_CONNECTION>& member = connections_to_check[i];
2649 if( member->IsBus() )
2651 connections_to_check.insert( connections_to_check.end(),
2652 member->Members().begin(),
2653 member->Members().end() );
2665 std::vector<CONNECTION_SUBGRAPH*> search_list;
2666 std::unordered_set<CONNECTION_SUBGRAPH*> visited;
2667 std::unordered_set<SCH_CONNECTION*> stale_bus_members;
2674 path.push_back(
pin->GetParent() );
2685 || visited.contains( candidate ) )
2694 wxLogTrace(
ConnTrace, wxS(
"%lu: found child %lu (%s)" ), aParent->m_code,
2702 wxASSERT( candidate->
m_graph == aParent->m_graph );
2704 search_list.push_back( candidate );
2724 || visited.contains( candidate )
2730 const KIID& last_parent_uuid = aParent->m_sheet.Last()->m_Uuid;
2735 if(
pin->GetParent()->m_Uuid != last_parent_uuid )
2741 if( pin_path != aParent->m_sheet )
2746 wxLogTrace(
ConnTrace, wxS(
"%lu: found additional parent %lu (%s)" ),
2749 aParent->m_hier_children.insert( candidate );
2750 search_list.push_back( candidate );
2760 for(
const auto&
kv : aParentGraph->m_bus_neighbors )
2802 wxLogTrace(
ConnTrace, wxS(
"Could not match bus member %s in %s" ),
2803 kv.first->Name(), parent->
Name() );
2809 wxCHECK2( neighbor_conn,
continue );
2811 wxString neighbor_name = neighbor_conn->
Name();
2814 if( neighbor_name == member->
Name() )
2822 wxCHECK2_MSG( neighbor_conn->
IsNet(),
continue,
2823 wxS(
"\"" ) + neighbor_name + wxS(
"\" is not a net." ) );
2825 wxLogTrace(
ConnTrace, wxS(
"%lu (%s) connected to bus member %s (local %s)" ),
2832 member->
Clone( *neighbor_conn );
2833 stale_bus_members.insert( member );
2837 neighbor_conn->
Clone( *member );
2851 propagate_bus_neighbors( aSubgraph );
2858 wxLogTrace(
ConnTrace, wxS(
"%lu (%s) has both hier ports and pins; deferring processing" ),
2864 wxLogTrace(
ConnTrace, wxS(
"%lu (%s) has no hier pins or ports on sheet %s; marking clean" ),
2870 visited.insert( aSubgraph );
2872 wxLogTrace(
ConnTrace, wxS(
"Propagating %lu (%s) to subsheets" ),
2877 for(
unsigned i = 0; i < search_list.size(); i++ )
2879 auto child = search_list[i];
2881 if( visited.insert( child ).second )
2884 child->m_dirty =
false;
2898 if( subgraph == aSubgraph )
2905 wxString candidateName = subgraph->m_driver_connection->Name();
2906 bool shorterPath = subgraph->m_sheet.size() < bestDriver->
m_sheet.
size();
2907 bool asGoodPath = subgraph->m_sheet.size() <= bestDriver->
m_sheet.
size();
2917 ( !bestIsStrong && candidateStrong ) ||
2918 ( priority > highest && candidateStrong ) ||
2919 ( priority == highest && candidateStrong && shorterPath ) ||
2920 ( ( bestIsStrong == candidateStrong ) && asGoodPath && ( priority == highest ) &&
2921 ( candidateName < bestName ) ) )
2923 bestDriver = subgraph;
2925 bestIsStrong = candidateStrong;
2926 bestName = candidateName;
2931 if( bestDriver != aSubgraph )
2933 wxLogTrace(
ConnTrace, wxS(
"%lu (%s) overridden by new driver %lu (%s)" ),
2942 wxString old_name = subgraph->m_driver_connection->Name();
2944 subgraph->m_driver_connection->Clone( *conn );
2946 if( old_name != conn->
Name() )
2950 propagate_bus_neighbors( subgraph );
2956 if( conn->
IsBus() && !stale_bus_members.empty() )
2958 std::unordered_set<SCH_CONNECTION*> cached_members = stale_bus_members;
2968 wxLogTrace(
ConnTrace, wxS(
"WARNING: failed to match stale member %s in %s." ),
2969 stale_member->Name(), subgraph->m_driver_connection->Name() );
2973 wxLogTrace(
ConnTrace, wxS(
"Updating %lu (%s) member %s to %s" ), subgraph->m_code,
2974 subgraph->m_driver_connection->Name(), member->
LocalName(), stale_member->Name() );
2976 member->
Clone( *stale_member );
2978 propagate_bus_neighbors( subgraph );
2990 std::shared_ptr<SCH_CONNECTION> c = std::shared_ptr<SCH_CONNECTION>(
nullptr );
2992 switch( aItem->
Type() )
2995 if(
static_cast<SCH_PIN*
>( aItem )->IsPower() )
2996 c = std::make_shared<SCH_CONNECTION>( aItem, aSubgraph->
m_sheet );
3003 c = std::make_shared<SCH_CONNECTION>( aItem, aSubgraph->
m_sheet );
3012 c->SetGraph(
this );
3024 wxASSERT( aBusConnection->
IsBus() );
3033 for(
const std::shared_ptr<SCH_CONNECTION>& bus_member : aBusConnection->
Members() )
3035 if( bus_member->VectorIndex() == aSearch->
VectorIndex() )
3037 match = bus_member.get();
3045 for(
const std::shared_ptr<SCH_CONNECTION>& c : aBusConnection->
Members() )
3052 for(
const std::shared_ptr<SCH_CONNECTION>& bus_member : c->Members() )
3054 if( bus_member->LocalName() == aSearch->
LocalName() )
3056 match = bus_member.get();
3061 else if( c->LocalName() == aSearch->
LocalName() )
3079 std::vector<CONNECTION_SUBGRAPH*>& vec = it->second;
3080 std::erase( vec, aSubgraph );
3083 wxLogTrace(
ConnTrace, wxS(
"recacheSubgraphName: %s => %s" ), aOldName,
3100 std::vector<const CONNECTION_SUBGRAPH*> ret;
3106 wxASSERT( !subgraph->m_dirty );
3108 if( !subgraph->m_driver )
3114 if( !connection->
IsBus() )
3117 auto labels = subgraph->GetVectorBusLabels();
3119 if( labels.size() > 1 )
3121 bool different =
false;
3124 for(
unsigned i = 1; i < labels.size(); ++i )
3136 wxLogTrace(
ConnTrace, wxS(
"SG %ld (%s) has multiple bus labels" ), subgraph->m_code,
3137 connection->
Name() );
3139 ret.push_back( subgraph );
3160 if( graph == aSubGraph )
3203 wxASSERT( !it->second.empty() );
3205 return it->second[0];
3221const std::vector<CONNECTION_SUBGRAPH*>&
3224 static const std::vector<CONNECTION_SUBGRAPH*> subgraphs;
3237 int error_count = 0;
3239 wxCHECK_MSG(
m_schematic,
true, wxS(
"Null m_schematic in CONNECTION_GRAPH::RunERC" ) );
3245 std::set<SCH_ITEM*> seenDriverInstances;
3250 wxCHECK2( subgraph,
continue );
3254 wxASSERT( !subgraph->m_dirty );
3256 if( subgraph->m_absorbed )
3259 if( seenDriverInstances.count( subgraph->m_driver ) )
3262 if( subgraph->m_driver )
3263 seenDriverInstances.insert( subgraph->m_driver );
3281 subgraph->ResolveDrivers(
false );
3352 wxCHECK( aSubgraph,
false );
3358 if( driver == aSubgraph->
m_driver )
3369 if( primaryName == secondaryName )
3372 wxString msg = wxString::Format(
_(
"Both %s and %s are attached to the same "
3373 "items; %s will be used in the netlist" ),
3374 primaryName, secondaryName, primaryName );
3377 ercItem->SetItems( aSubgraph->
m_driver, driver );
3378 ercItem->SetSheetSpecificPath( aSubgraph->
GetSheet() );
3379 ercItem->SetItemsSheetPaths( aSubgraph->
GetSheet(), aSubgraph->
m_sheet );
3380 ercItem->SetErrorMessage( msg );
3405 switch( item->
Type() )
3410 bus_item = ( !bus_item ) ? item : bus_item;
3412 net_item = ( !net_item ) ? item : net_item;
3426 bus_item = ( !bus_item ) ? item : bus_item;
3428 net_item = ( !net_item ) ? item : net_item;
3438 if( net_item && bus_item )
3441 ercItem->SetSheetSpecificPath( sheet );
3442 ercItem->SetItems( net_item, bus_item );
3445 screen->
Append( marker );
3464 switch( item->
Type() )
3491 if(
test != member && member->Name() ==
test->Name() )
3505 ercItem->SetSheetSpecificPath( sheet );
3506 ercItem->SetItems( label, port );
3509 screen->
Append( marker );
3521 bool conflict =
false;
3537 switch( item->
Type() )
3567 std::set<wxString> test_names;
3579 for(
const auto& sub_member : member->Members() )
3581 if( test_names.count( sub_member->FullLocalName() ) )
3585 else if( test_names.count( member->FullLocalName() ) )
3604 wxString msg = wxString::Format(
_(
"Net %s is graphically connected to bus %s but is not a"
3605 " member of that bus" ),
3609 ercItem->SetSheetSpecificPath( sheet );
3610 ercItem->SetItems( bus_entry, bus_wire );
3611 ercItem->SetErrorMessage( msg );
3614 screen->
Append( marker );
3631 std::set<SCH_PIN*> unique_pins;
3632 std::set<SCH_LABEL_BASE*> unique_labels;
3640 for(
SCH_ITEM* item : aProcessGraph->m_items )
3642 switch( item->
Type() )
3649 if( aProcessGraph == aSubgraph )
3652 if( std::none_of( unique_pins.begin(), unique_pins.end(),
3655 return test_pin->IsStacked( aPin );
3659 unique_pins.insert( test_pin );
3682 process_subgraph( subgraph );
3687 process_subgraph( aSubgraph );
3722 ercItem->SetSheetSpecificPath( sheet );
3723 ercItem->SetItemsSheetPaths( sheet );
3730 pos =
pin->GetPosition();
3739 screen->
Append( marker );
3744 if( unique_pins.empty() && unique_labels.empty() &&
3749 ercItem->SetSheetSpecificPath( sheet );
3750 ercItem->SetItemsSheetPaths( sheet );
3753 screen->
Append( marker );
3760 bool has_other_connections =
false;
3761 std::vector<SCH_PIN*> pins;
3768 switch( item->
Type() )
3775 if( !has_other_connections && !pins.empty()
3778 for(
SCH_PIN* other_pin : pins )
3782 has_other_connections =
true;
3788 pins.emplace_back(
static_cast<SCH_PIN*
>( item ) );
3795 has_other_connections =
true;
3802 pin = pins.empty() ? nullptr : pins[0];
3805 for(
SCH_PIN* test_pin : pins )
3821 if(
pin && !has_other_connections
3823 && !
pin->GetLibPin()->GetParentSymbol()->IsPower() )
3825 wxString
name =
pin->Connection( &sheet )->Name();
3826 wxString local_name =
pin->Connection( &sheet )->Name(
true );
3831 has_other_connections =
true;
3836 if(
pin && !has_other_connections
3842 ercItem->SetSheetSpecificPath( sheet );
3843 ercItem->SetItemsSheetPaths( sheet );
3844 ercItem->SetItems(
pin );
3847 screen->
Append( marker );
3855 if( pins.size() > 1 )
3857 for(
SCH_PIN* testPin : pins )
3862 if( testPin->GetLibPin()->GetParentSymbol()->IsPower()
3863 && testPin->ConnectedItems( sheet ).empty()
3867 ercItem->SetSheetSpecificPath( sheet );
3868 ercItem->SetItemsSheetPaths( sheet );
3869 ercItem->SetItems( testPin );
3872 screen->
Append( marker );
3905 ercItem->SetItems( line );
3906 ercItem->SetSheetSpecificPath( sheet );
3907 ercItem->SetErrorMessage(
_(
"Unconnected wire endpoint" ) );
3929 ercItem->SetItems( entry );
3930 ercItem->SetSheetSpecificPath( sheet );
3931 ercItem->SetErrorMessage(
_(
"Unconnected wire to bus entry" ) );
3948 return err_count > 0;
3958 std::vector<SCH_ITEM*> wires;
3965 wires.emplace_back( item );
3967 wires.emplace_back( item );
3970 if( !wires.empty() )
3975 ercItem->SetSheetSpecificPath( sheet );
3976 ercItem->SetItems( wires[0],
3977 wires.size() > 1 ? wires[1] :
nullptr,
3978 wires.size() > 2 ? wires[2] :
nullptr,
3979 wires.size() > 3 ? wires[3] :
nullptr );
3982 screen->
Append( marker );
4010 size_t pinCount = 0;
4013 std::map<KICAD_T, std::vector<SCH_TEXT*>> label_map;
4019 return std::count_if( aLocSubgraph->m_items.begin(), aLocSubgraph->m_items.end(),
4022 return item->Type() == SCH_PIN_T;
4027 [&](
SCH_TEXT* aText,
int errCode )
4032 ercItem->SetSheetSpecificPath( sheet );
4033 ercItem->SetItems( aText );
4040 pinCount =
hasPins( aSubgraph );
4044 switch( item->
Type() )
4052 label_map[item->
Type()].push_back(
text );
4057 if(
text->IsDangling() )
4071 if( label_map.empty() )
4076 for(
auto& [ connection, subgraphs ] : aSubgraph->
m_bus_parents )
4080 if( busParent->m_no_connect )
4103 wxCHECK_MSG(
m_schematic,
true, wxS(
"Null m_schematic in CONNECTION_GRAPH::ercCheckLabels" ) );
4110 for(
auto& [type, label_vec] : label_map )
4114 size_t allPins = pinCount;
4122 if( neighbor == aSubgraph )
4128 allPins +=
hasPins( neighbor );
4132 if( allPins == 1 && !has_nc )
4154 std::map<wxString, std::tuple<int, const SCH_ITEM*, SCH_SHEET_PATH>> labelData;
4161 wxString resolvedLabelText =
4164 if( labelData.find( resolvedLabelText ) == labelData.end() )
4166 labelData[resolvedLabelText] = { 1, item, sheet };
4170 std::get<0>( labelData[resolvedLabelText] ) += 1;
4171 std::get<1>( labelData[resolvedLabelText] ) =
nullptr;
4172 std::get<2>( labelData[resolvedLabelText] ) = sheet;
4177 for(
const auto& label : labelData )
4179 if( std::get<0>( label.second ) == 1 )
4182 const SCH_ITEM* item = std::get<1>( label.second );
4185 ercItem->SetItems( std::get<1>( label.second ) );
4186 ercItem->SetSheetSpecificPath( sheet );
4187 ercItem->SetItemsSheetPaths( sheet );
4202 int error_count = 0;
4214 ercItem->SetSheetSpecificPath( sheet );
4215 ercItem->SetItems(
text );
4218 sheet.LastScreen()->Append( marker );
4238 if( sheet.Last()->IsRootSheet() )
4244 wxCHECK2( label,
continue );
4246 msg.Printf(
_(
"Hierarchical label '%s' in root sheet cannot be connected to non-existent "
4250 ercItem->SetItems( item );
4251 ercItem->SetErrorMessage( msg );
4254 sheet.LastScreen()->Append( marker );
4265 parentSheetPath.
push_back( parentSheet );
4267 std::map<wxString, SCH_SHEET_PIN*> pins;
4268 std::map<wxString, SCH_HIERLABEL*> labels;
4273 pins[
pin->GetShownText( &parentSheetPath,
false ) ] =
pin;
4278 ercItem->SetItems(
pin );
4279 ercItem->SetSheetSpecificPath( sheet );
4280 ercItem->SetItemsSheetPaths( sheet );
4283 sheet.LastScreen()->Append( marker );
4291 std::set<wxString> matchedPins;
4298 wxString labelText = label->
GetShownText( &parentSheetPath,
false );
4300 if( !pins.contains( labelText ) )
4301 labels[ labelText ] = label;
4303 matchedPins.insert( labelText );
4307 for(
const wxString& matched : matchedPins )
4308 pins.erase( matched );
4310 for(
const auto& [
name,
pin] : pins )
4312 msg.Printf(
_(
"Sheet pin %s has no matching hierarchical label inside the sheet" ),
4316 ercItem->SetItems(
pin );
4317 ercItem->SetErrorMessage( msg );
4318 ercItem->SetSheetSpecificPath( sheet );
4319 ercItem->SetItemsSheetPaths( sheet );
4322 sheet.LastScreen()->Append( marker );
4327 for(
const auto& [
name, label] : labels )
4329 msg.Printf(
_(
"Hierarchical label %s has no matching sheet pin in the parent sheet" ),
4333 ercItem->SetItems( label );
4334 ercItem->SetErrorMessage( msg );
4335 ercItem->SetSheetSpecificPath( parentSheetPath );
4336 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.
virtual const wxString & GetText() const
Return the string associated with the text 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.
SCH_FIELD & GetReferenceField()
Return reference to the reference designator field.
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
Container class that holds multiple SCH_SCREEN objects in a hierarchy.
void Append(SCH_ITEM *aItem, bool aUpdateLibSymbol=true)
EE_RTREE & Items()
Get the full RTree, usually for iterating.
SCH_LINE * GetBus(const VECTOR2I &aPosition, int aAccuracy=0, SCH_LINE_TEST_T aSearchType=ENTIRE_LENGTH_T) const
A container for handling SCH_SHEET_PATH objects in a flattened hierarchy.
Handle access to a stack of flattened SCH_SHEET objects by way of a path for creating a flattened sch...
const SCH_SHEET * GetSheet(unsigned aIndex) const
wxString PathHumanReadable(bool aUseShortRootName=true, bool aStripTrailingSeparator=false) const
Return the sheet path in a human readable form made from the sheet names.
SCH_SCREEN * LastScreen()
SCH_SHEET * Last() const
Return a pointer to the last SCH_SHEET of the list.
void push_back(SCH_SHEET *aSheet)
Forwarded method from std::vector.
size_t size() const
Forwarded method from std::vector.
Define a sheet pin (label) used in sheets to create hierarchical schematics.
SCH_SHEET * GetParent() const
Get the parent sheet object of this sheet pin.
Sheet symbol placed in a schematic, and is the entry point for a sub schematic.
wxString GetFileName() const
Return the filename corresponding to this sheet.
SCH_SCREEN * GetScreen() const
std::vector< SCH_SHEET_PIN * > & GetPins()
std::vector< SCH_PIN * > GetPins(const SCH_SHEET_PATH *aSheet) const
Retrieve a list of the SCH_PINs for the given sheet path.
int GetUnitSelection(const SCH_SHEET_PATH *aSheet) const
Return the instance-specific unit selection for the given sheet path.
SCH_PIN * GetPin(const wxString &number) const
Find a symbol pin by number.
std::unique_ptr< LIB_SYMBOL > & GetLibSymbolRef()
VECTOR2I GetPosition() const override
virtual wxString GetShownText(const SCH_SHEET_PATH *aPath, bool aAllowExtraText, int aDepth=0) const
virtual bool IsGlobalPower() const =0
virtual bool IsLocalPower() const =0
virtual bool IsPower() const =0
bool GetExcludedFromBoard() const override
#define CONNECTIVITY_CANDIDATE
flag indicating that the structure is connected for connectivity
@ ERCE_DRIVER_CONFLICT
Conflicting drivers (labels, etc) on a subgraph.
@ ERCE_UNCONNECTED_WIRE_ENDPOINT
A label is connected to more than one wire.
@ ERCE_LABEL_NOT_CONNECTED
Label not connected to any pins.
@ ERCE_BUS_TO_BUS_CONFLICT
A connection between bus objects doesn't share at least one net.
@ ERCE_LABEL_SINGLE_PIN
A label is connected only to a single pin.
@ ERCE_BUS_ENTRY_CONFLICT
A wire connected to a bus doesn't match the bus.
@ ERCE_BUS_TO_NET_CONFLICT
A bus wire is graphically connected to a net port/pin (or vice versa).
@ ERCE_NOCONNECT_NOT_CONNECTED
A no connect symbol is not connected to anything.
@ ERCE_PIN_NOT_CONNECTED
Pin not connected and not no connect symbol.
@ ERCE_NOCONNECT_CONNECTED
A no connect symbol is connected to more than 1 pin.
@ ERCE_HIERACHICAL_LABEL
Mismatch between hierarchical labels and pins sheets.
@ ERCE_WIRE_DANGLING
Some wires are not connected to anything else.
@ ERCE_SINGLE_GLOBAL_LABEL
A label only exists once in the schematic.
static const wxChar DanglingProfileMask[]
Flag to enable connectivity profiling.
static const wxChar ConnTrace[]
Flag to enable connectivity tracing.
#define KI_FALLTHROUGH
The KI_FALLTHROUGH macro is to be used when switch statement cases should purposely fallthrough from ...
void remove_duplicates(_Container &__c)
Deletes all duplicate values from __c.
@ 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::thread_pool< 0 > thread_pool
Functions to provide common constants and other functions to assist in making a consistent UI.
VECTOR2< int32_t > VECTOR2I