27#include <unordered_map>
108 if( old_conn && new_conn )
110 new_conn->
Clone( *old_conn );
140 std::vector<SCH_ITEM*> candidates;
141 std::set<SCH_ITEM*> strong_drivers;
165 strong_drivers.insert( item );
167 if( item_priority > highest_priority )
170 candidates.push_back( item );
171 highest_priority = item_priority;
173 else if( !candidates.empty() && ( item_priority == highest_priority ) )
175 candidates.push_back( item );
185 if( !candidates.empty() )
219 if( aGlobal != bGlobal )
225 if( aLocal != bLocal )
246 bool a_lowQualityName = a_name.Contains(
"-Pad" );
247 bool b_lowQualityName = b_name.Contains(
"-Pad" );
249 if( a_lowQualityName != b_lowQualityName )
250 return !a_lowQualityName;
252 return a_name < b_name;
255 std::sort( candidates.begin(), candidates.end(), candidate_cmp );
260 if( strong_drivers.size() > 1 )
267 m_drivers.insert( strong_drivers.begin(), strong_drivers.end() );
289 std::set<CONNECTION_SUBGRAPH*>& aSubgraphs )
301 if( aSubgraphs.insert( sg ).second ==
false )
307 aItems.emplace(
m_sheet, item );
321#ifdef CONNECTIVITY_DEBUG
322 wxASSERT_MSG(
false, wxS(
"Tried to get the net name of an item with no connection" ) );
334 std::vector<SCH_ITEM*> labels;
338 switch( item->Type() )
347 labels.push_back( item );
363 std::vector<SCH_ITEM*> labels;
367 switch( item->Type() )
376 labels.push_back( item );
392 switch( aItem->
Type() )
399 return pin->GetDefaultNetName(
m_sheet, forceNoConnect );
426 wxFAIL_MSG( wxS(
"Unhandled item type in GetNameForDriver" ) );
427 return wxEmptyString;
447const std::vector<std::pair<wxString, SCH_ITEM*>>
450 std::vector<std::pair<wxString, SCH_ITEM*>> foundNetclasses;
452 const std::unordered_set<SCH_RULE_AREA*>& ruleAreaCache = aItem->
GetRuleAreaCache();
457 const std::vector<std::pair<wxString, SCH_ITEM*>> ruleNetclasses =
458 ruleArea->GetResolvedNetclasses();
460 if( ruleNetclasses.size() > 0 )
462 foundNetclasses.insert( foundNetclasses.end(), ruleNetclasses.begin(),
463 ruleNetclasses.end() );
479 if( netclass != wxEmptyString )
480 foundNetclasses.push_back( { netclass, aItem } );
487 foundNetclasses.begin(), foundNetclasses.end(),
488 [](
const std::pair<wxString, SCH_ITEM*>& i1,
const std::pair<wxString, SCH_ITEM*>& i2 )
490 return i1.first < i2.first;
493 return foundNetclasses;
519 child->m_absorbed_by =
this;
522 set_absorbed_by( subchild );
530 set_absorbed_by( aOther );
583 if(
const std::unique_ptr<LIB_SYMBOL>& part = symbol->GetLibSymbolRef() )
584 return part->GetReferenceField().GetText();
586 return wxEmptyString;
589 switch( aDriver->
Type() )
620 std::back_inserter(
m_items ) );
675 wxCHECK2( aOldItem->
Type() == aNewItem->
Type(),
return );
710 wxCHECK2( oldPins.size() == newPins.size(),
return );
712 for(
size_t ii = 0; ii < oldPins.size(); ii++ )
714 exchange( oldPins[ii], newPins[ii] );
725 if( subgraph->m_graph ==
this )
749 std::function<
void(
SCH_ITEM* )>* aChangedItemHandler,
753 PROF_TIMER recalc_time(
"CONNECTION_GRAPH::Recalculate" );
754 monitorTrans.
Start();
759 monitorTrans.
StartSpan(
"updateItemConnectivity",
"" );
760 PROF_TIMER update_items(
"updateItemConnectivity" );
763 std::set<SCH_ITEM*> dirty_items;
765 int count = aSheetList.size() * 2;
770 if( aProgressReporter )
776 std::vector<SCH_ITEM*> items;
779 std::vector<std::pair<SCH_SYMBOL*, int>> symbolsChanged;
781 for(
SCH_ITEM* item : sheet.LastScreen()->Items() )
783 if( item->IsConnectable() && ( aUnconditional || item->IsConnectivityDirty() ) )
785 wxLogTrace(
ConnTrace, wxT(
"Adding item %s to connectivity graph update" ),
786 item->GetTypeDesc() );
787 items.push_back( item );
788 dirty_items.insert( item );
797 if(
pin->IsConnectivityDirty() )
799 dirty_items.insert(
pin );
812 if(
pin->IsConnectivityDirty() )
814 items.push_back(
pin );
815 dirty_items.insert(
pin );
825 if(
pin->IsConnectivityDirty() )
827 items.push_back(
pin );
828 dirty_items.insert(
pin );
841 if( symbol->
GetUnit() != new_unit )
842 symbolsChanged.push_back( { symbol, symbol->
GetUnit() } );
852 if( aProgressReporter )
859 sheet.LastScreen()->TestDanglingEnds( &sheet, aChangedItemHandler );
862 for(
const auto& [ symbol, originalUnit ] : symbolsChanged )
863 symbol->SetUnit( originalUnit );
869 aChangedItemHandler );
872 item->SetConnectivityDirty(
false );
879 PROF_TIMER build_graph(
"buildConnectionGraph" );
880 monitorTrans.
StartSpan(
"BuildConnectionGraph",
"" );
899 const std::set<SCH_ITEM*> &aItems )
901 std::set<std::pair<SCH_SHEET_PATH, SCH_ITEM*>> retvals;
902 std::set<CONNECTION_SUBGRAPH*> subgraphs;
907 while( aSubgraph->m_absorbed_by )
910 wxASSERT( aSubgraph->m_graph == aSubgraph->m_absorbed_by->m_graph );
911 aSubgraph = aSubgraph->m_absorbed_by;
915 while( aSubgraph->m_hier_parent )
918 wxASSERT( aSubgraph->m_graph == aSubgraph->m_hier_parent->m_graph );
919 aSubgraph = aSubgraph->m_hier_parent;
923 aSubgraph->getAllConnectedItems( retvals, subgraphs );
926 auto extract_element = [&](
SCH_ITEM* aItem )
932 wxLogTrace(
ConnTrace, wxT(
"Item %s not found in connection graph" ),
933 aItem->GetTypeDesc() );
939 wxLogTrace(
ConnTrace, wxT(
"Item %s in subgraph %ld (%p) has no driver" ),
940 aItem->GetTypeDesc(), item_sg->
m_code, item_sg );
945 if( sg_to_scan.empty() )
947 wxLogTrace(
ConnTrace, wxT(
"Item %s in subgraph %ld with net %s has no neighbors" ),
949 sg_to_scan.push_back( item_sg );
953 wxT(
"Removing all item %s connections from subgraph %ld with net %s: Found "
960 traverse_subgraph( sg );
962 for(
auto& bus_it : sg->m_bus_neighbors )
965 traverse_subgraph( bus_sg );
968 for(
auto& bus_it : sg->m_bus_parents )
971 traverse_subgraph( bus_sg );
985 extract_element(
pin );
992 extract_element(
pin );
996 extract_element( item );
1002 for(
const auto& [
path, item] : retvals )
1029 wxLogTrace(
ConnTrace, wxT(
"Removing %zu subgraphs" ), aSubgraphs.size() );
1032 std::set<int> codes_to_remove;
1036 std::sort( el.second.begin(), el.second.end() );
1041 for(
auto& it : sg->m_bus_neighbors )
1047 for(
auto test = parents.begin();
test != parents.end(); )
1055 if( parents.empty() )
1060 for(
auto& it : sg->m_bus_parents )
1066 for(
auto test = neighbors.begin();
test != neighbors.end(); )
1074 if( neighbors.empty() )
1095 auto it = std::lower_bound( el.second.begin(), el.second.end(), sg );
1097 while( it != el.second.end() && *it == sg )
1098 it = el.second.erase( it );
1101 auto remove_sg = [sg](
auto it ) ->
bool
1114 if( remove_sg( it ) )
1122 if( remove_sg( it ) )
1131 if( remove_sg( it ) )
1133 codes_to_remove.insert( it->first.Netcode );
1145 if( remove_sg( it ) )
1153 if( it->second == sg )
1164 if( codes_to_remove.contains( it->second ) )
1172 if( codes_to_remove.contains( it->second ) )
1181 sg->m_graph =
nullptr;
1188 std::map<
VECTOR2I, std::vector<SCH_ITEM*>>& aConnectionMap )
1199 aConn->SetName(
name );
1204 std::map<wxString, std::vector<SCH_PIN*>> pinNumberMap;
1210 updatePin(
pin, conn );
1211 aConnectionMap[
pin->GetPosition() ].push_back(
pin );
1212 pinNumberMap[
pin->GetNumber()].emplace_back(
pin );
1215 auto linkPinsInVec =
1216 [&](
const std::vector<SCH_PIN*>& aVec )
1218 for(
size_t i = 0; i < aVec.size(); ++i )
1220 for(
size_t j = i + 1; j < aVec.size(); ++j )
1222 aVec[i]->AddConnectionTo( aSheet, aVec[j] );
1223 aVec[j]->AddConnectionTo( aSheet, aVec[i] );
1232 for(
const auto& [number,
group] : pinNumberMap )
1233 linkPinsInVec(
group );
1238 std::vector<SCH_PIN*> pins;
1240 for(
const wxString& pinNumber :
group )
1241 pins.emplace_back( aSymbol->
GetPin( pinNumber ) );
1243 linkPinsInVec( pins );
1266 std::map<
VECTOR2I, std::vector<SCH_ITEM*>>& aConnectionMap )
1271 m_items.emplace_back( aItem );
1274 switch( aItem->
Type() )
1287 if( points.empty() )
1288 points = {
static_cast<SCH_PIN*
>( aItem )->GetPosition() };
1301 for(
const VECTOR2I& point : points )
1302 aConnectionMap[point].push_back( aItem );
1307 const std::vector<SCH_ITEM*>& aItemList )
1309 wxLogTrace( wxT(
"Updating connectivity for sheet %s with %zu items" ),
1311 std::map<VECTOR2I, std::vector<SCH_ITEM*>> connection_map;
1315 std::vector<VECTOR2I> points = item->GetConnectionPoints();
1316 item->ClearConnectedItems( aSheet );
1322 pin->InitializeConnection( aSheet,
this );
1324 pin->ClearConnectedItems( aSheet );
1326 connection_map[
pin->GetTextPos() ].push_back(
pin );
1343 VECTOR2I point = item->GetPosition();
1346 std::vector<SCH_ITEM*> overlapping_items;
1348 std::copy_if( items.begin(), items.end(), std::back_inserter( overlapping_items ),
1351 return test_item->Type() == SCH_LINE_T
1352 && test_item->HitTest( point, -1 );
1357 if( overlapping_items.size() < 2 )
continue;
1359 for(
SCH_ITEM* test_item : overlapping_items )
1360 connection_map[point].push_back( test_item );
1365 for(
auto& [point, connection_vec] : connection_map )
1367 std::sort( connection_vec.begin(), connection_vec.end() );
1373 for(
SCH_ITEM* connected_item : connection_vec )
1387 if( connection_vec.size() == 1 )
1403 if( point == bus_entry->GetPosition() )
1406 bus_entry->m_connected_bus_items[1] = busLine;
1419 for(
SCH_ITEM* test_item : connection_vec )
1421 bool bus_connection_ok =
true;
1423 if( test_item == connected_item )
1429 if( test_item->GetLayer() ==
LAYER_BUS )
1448 if( connected_item->ConnectionPropagatesTo( test_item )
1449 && test_item->ConnectionPropagatesTo( connected_item )
1450 && bus_connection_ok )
1452 connected_item->AddConnectionTo( aSheet, test_item );
1463 if( !bus_entry->m_connected_bus_item )
1469 bus_entry->m_connected_bus_item = bus;
1480 wxCHECK_RET(
m_schematic, wxS(
"Connection graph cannot be built without schematic pointer" ) );
1484 for(
const std::shared_ptr<BUS_ALIAS>& alias :
m_schematic->GetAllBusAliases() )
1493 for(
const auto& [sheet, connection] : item->m_connection_map )
1495 if( connection->SubgraphCode() == 0 )
1504 connection->SetSubgraphCode( subgraph->
m_code );
1507 std::list<SCH_ITEM*> memberlist;
1512 SCH_CONNECTION* conn = aItem->GetOrInitConnection( sheet,
this );
1518 return ( unique && conn && ( conn->
SubgraphCode() == 0 ) );
1521 std::copy_if( item->ConnectedItems( sheet ).begin(),
1522 item->ConnectedItems( sheet ).end(),
1523 std::back_inserter( memberlist ), get_items );
1525 for(
SCH_ITEM* connected_item : memberlist )
1530 SCH_CONNECTION* connected_conn = connected_item->Connection( &sheet );
1532 wxCHECK2( connected_conn,
continue );
1538 subgraph->
AddItem( connected_item );
1539 const SCH_ITEM_VEC& citemset = connected_item->ConnectedItems( sheet );
1546 if( get_items( citem ) )
1547 memberlist.push_back( citem );
1552 for(
SCH_ITEM* connected_item : memberlist )
1566 std::vector<CONNECTION_SUBGRAPH*> dirty_graphs;
1571 return candidate->m_dirty;
1574 wxLogTrace(
ConnTrace, wxT(
"Resolving drivers for %zu subgraphs" ), dirty_graphs.size() );
1576 std::vector<std::future<size_t>> returns( dirty_graphs.size() );
1578 auto update_lambda =
1581 if( !subgraph->m_dirty )
1585 for(
SCH_ITEM* item : subgraph->m_items )
1587 switch( item->
Type() )
1590 subgraph->m_no_connect = item;
1594 subgraph->m_bus_entry = item;
1602 subgraph->m_no_connect = item;
1612 subgraph->ResolveDrivers(
true );
1613 subgraph->m_dirty =
false;
1620 auto results =
tp.submit_loop( 0, dirty_graphs.size(),
1623 update_lambda( dirty_graphs[ii] );
1632 return candidate->m_driver;
1645 wxString full_name = subgraph->m_driver_connection->Name();
1646 wxString
name = subgraph->m_driver_connection->Name(
true );
1655 wxString prefixOnly = full_name.BeforeFirst(
'[' ) + wxT(
"[]" );
1659 subgraph->m_dirty =
true;
1661 if( subgraph->m_strong_driver )
1663 SCH_ITEM* driver = subgraph->m_driver;
1666 switch( driver->
Type() )
1682 if(
pin->IsGlobalPower() )
1686 else if(
pin->IsLocalPower() )
1693 wxLogTrace(
ConnTrace, wxS(
"Unexpected normal pin %s" ),
1703 wxLogTrace(
ConnTrace, wxS(
"Unexpected strong driver %s" ),
1715 std::vector<CONNECTION_SUBGRAPH*> new_subgraphs;
1726 dummy.SetGraph(
this );
1729 wxLogTrace(
ConnTrace, wxS(
"new bus label (%s)" ),
1732 for(
const auto& conn :
dummy.Members() )
1734 wxString
name = conn->FullLocalName();
1745 subgraph->StoreImplicitConnection( new_conn );
1748 wxLogTrace(
ConnTrace, wxS(
"SG(%ld), Adding full local name (%s) with sg (%d) on subsheet %s" ),
1749 subgraph->m_code,
name, code, subgraph->m_sheet.PathHumanReadable() );
1762 new_subgraphs.push_back( new_sg );
1767 std::copy( new_subgraphs.begin(), new_subgraphs.end(),
1779 std::unordered_map<int, CONNECTION_SUBGRAPH*> global_power_pin_subgraphs;
1783 if( !
pin->ConnectedItems( sheet ).empty()
1784 && !
pin->GetLibPin()->GetParentSymbol()->IsGlobalPower() )
1799 if(
pin->GetLibPin()->GetParentSymbol()->IsGlobalPower() )
1800 connection->
SetName(
pin->GetParentSymbol()->GetValue(
true, &sheet,
false ) );
1809 auto jj = global_power_pin_subgraphs.find( code );
1811 if( jj != global_power_pin_subgraphs.end() )
1813 subgraph = jj->second;
1831 global_power_pin_subgraphs[code] = subgraph;
1848 std::unordered_set<CONNECTION_SUBGRAPH*> invalidated_subgraphs;
1852 if( subgraph->m_absorbed )
1857 wxString
name = connection->
Name();
1860 unsigned suffix = 1;
1862 auto create_new_name =
1866 wxString suffixStr = std::to_wstring( suffix );
1873 wxString prefix = aConn->BusPrefix();
1875 if( prefix.empty() )
1876 prefix = wxT(
"BUS" );
1878 wxString oldName = aConn->Name().AfterFirst(
'{' );
1880 newName << prefix << wxT(
"_" ) << suffixStr << wxT(
"{" ) << oldName;
1882 aConn->ConfigureFromLabel( newName );
1886 newName << aConn->Name() << wxT(
"_" ) << suffixStr;
1887 aConn->SetSuffix( wxString( wxT(
"_" ) ) << suffixStr );
1894 if( !subgraph->m_strong_driver )
1896 std::vector<CONNECTION_SUBGRAPH*> vec_empty;
1897 std::vector<CONNECTION_SUBGRAPH*>* vec = &vec_empty;
1906 wxString prefixOnly =
name.BeforeFirst(
'[' ) + wxT(
"[]" );
1912 if( vec->size() > 1 )
1914 wxString new_name = create_new_name( connection );
1917 new_name = create_new_name( connection );
1919 wxLogTrace(
ConnTrace, wxS(
"%ld (%s) is weakly driven and not unique. Changing to %s." ),
1920 subgraph->m_code,
name, new_name );
1922 std::erase( *vec, subgraph );
1928 else if( subgraph->m_driver )
1940 bool conflict =
false;
1941 wxString global_name = connection->
Name(
true );
1948 std::vector<CONNECTION_SUBGRAPH*>& candidates = kk->second;
1952 if( candidate->m_sheet == sheet )
1959 wxLogTrace(
ConnTrace, wxS(
"%ld (%s) skipped for promotion due to potential conflict" ),
1960 subgraph->m_code,
name );
1966 wxLogTrace(
ConnTrace, wxS(
"%ld (%s) weakly driven by unique sheet pin %s, promoting" ),
1967 subgraph->m_code,
name,
1968 subgraph->m_driver->GetItemDescription( &unitsProvider,
true ) );
1970 subgraph->m_strong_driver =
true;
1977 if( connection->
IsBus() )
2001 subgraph->m_dirty =
true;
2009 if( !subgraph->m_strong_driver )
2016 std::vector<CONNECTION_SUBGRAPH*> candidate_subgraphs;
2019 std::back_inserter( candidate_subgraphs ),
2022 return ( !candidate->m_absorbed &&
2023 candidate->m_strong_driver &&
2024 candidate != subgraph );
2030 std::vector< std::shared_ptr<SCH_CONNECTION> > connections_to_check;
2033 connections_to_check.push_back( std::make_shared<SCH_CONNECTION>( *connection ) );
2035 auto add_connections_to_check =
2038 for(
SCH_ITEM* possible_driver : aSubgraph->m_items )
2040 if( possible_driver == aSubgraph->m_driver )
2047 if( c->Type() != aSubgraph->m_driver_connection->Type() )
2050 if( c->Name(
true ) == aSubgraph->m_driver_connection->Name(
true ) )
2053 connections_to_check.push_back( c );
2054 wxLogTrace(
ConnTrace, wxS(
"%lu (%s): Adding secondary driver %s" ),
2056 aSubgraph->m_driver_connection->Name(
true ),
2065 add_connections_to_check( subgraph );
2067 std::set<SCH_CONNECTION*> checked_connections;
2069 for(
unsigned i = 0; i < connections_to_check.size(); i++ )
2071 auto member = connections_to_check[i];
2074 if( !checked_connections.insert( member.get() ).second )
2077 if( member->IsBus() )
2079 connections_to_check.insert( connections_to_check.end(),
2080 member->Members().begin(),
2081 member->Members().end() );
2084 wxString test_name = member->Name(
true );
2088 if( candidate->
m_absorbed || candidate == subgraph )
2104 if( driver == candidate->
m_driver )
2116 &&
pin->GetDefaultNetName( sheet ) == test_name )
2129 if( subgraph->GetNameForDriver( driver ) == test_name )
2142 wxLogTrace(
ConnTrace, wxS(
"%lu (%s) has bus child %lu (%s)" ),
2143 subgraph->m_code, connection->
Name(),
2144 candidate->
m_code, member->Name() );
2146 subgraph->m_bus_neighbors[member].insert( candidate );
2149 else if( !connection->
IsBus()
2152 wxLogTrace(
ConnTrace, wxS(
"%lu (%s) absorbs neighbor %lu (%s)" ),
2153 subgraph->m_code, connection->
Name(),
2157 add_connections_to_check( candidate );
2159 subgraph->Absorb( candidate );
2160 invalidated_subgraphs.insert( subgraph );
2170 if( subgraph->m_absorbed )
2173 if( !subgraph->ResolveDrivers() )
2176 if( subgraph->m_driver_connection->IsBus() )
2181 wxLogTrace(
ConnTrace, wxS(
"Re-resolving drivers for %lu (%s)" ),
2182 subgraph->m_code, subgraph->m_driver_connection->Name() );
2201 bool aUnconditional )
2204 wxCHECK_RET(
m_schematic, wxT(
"Connection graph cannot be built without schematic pointer" ) );
2208 for(
const std::shared_ptr<BUS_ALIAS>& alias :
m_schematic->GetAllBusAliases() )
2214 PROF_TIMER sub_graph(
"buildItemSubGraphs" );
2233 PROF_TIMER proc_sub_graph(
"ProcessSubGraphs" );
2237 proc_sub_graph.
Show();
2246 std::vector<CONNECTION_SUBGRAPH*> global_subgraphs;
2248 std::back_inserter( global_subgraphs ),
2251 return !candidate->m_local_driver;
2265 m_driver_subgraphs[ii]->UpdateItemConnections();
2275 if( !subgraph->m_dirty )
2278 wxLogTrace(
ConnTrace, wxS(
"Processing %lu (%s) for propagation" ),
2279 subgraph->m_code, subgraph->m_driver_connection->Name() );
2285 if( !subgraph->m_local_driver && subgraph->m_multiple_drivers )
2287 for(
SCH_ITEM* driver : subgraph->m_drivers )
2289 if( driver == subgraph->m_driver )
2292 const wxString& secondary_name = subgraph->GetNameForDriver( driver );
2294 if( secondary_name == subgraph->m_driver_connection->Name() )
2302 if( candidate == subgraph )
2305 if( !secondary_is_global && candidate->
m_sheet != subgraph->m_sheet )
2312 wxLogTrace(
ConnTrace, wxS(
"Global %lu (%s) promoted to %s" ),
2314 subgraph->m_driver_connection->Name() );
2336 if( subgraph->m_dirty )
2353 wxASSERT_MSG( !subgraph->m_dirty,
2354 wxS(
"Subgraph not processed by propagateToNeighbors!" ) );
2356 if( subgraph->m_bus_parents.size() < 2 )
2361 wxLogTrace(
ConnTrace, wxS(
"%lu (%s) has multiple bus parents" ),
2362 subgraph->m_code, conn->
Name() );
2365 wxCHECK2( conn->
IsNet(),
continue );
2367 for(
const auto& ii : subgraph->m_bus_parents )
2380 wxLogTrace(
ConnTrace, wxS(
"Warning: could not match %s inside %lu (%s)" ),
2385 if( conn->
Name() != match->
Name() )
2387 wxString old_name = match->
Name();
2389 wxLogTrace(
ConnTrace, wxS(
"Updating %lu (%s) member %s to %s" ),
2392 match->
Clone( *conn );
2411 auto updateItemConnectionsTask =
2415 if( !subgraph->m_strong_driver
2416 && subgraph->m_drivers.size() == 1
2417 && subgraph->m_driver->Type() ==
SCH_PIN_T )
2420 wxString
name =
pin->GetDefaultNetName( subgraph->m_sheet,
true );
2422 subgraph->m_driver_connection->ConfigureFromLabel(
name );
2425 subgraph->m_dirty =
false;
2426 subgraph->UpdateItemConnections();
2429 if( subgraph->m_driver_connection->IsBus() )
2434 if( subgraph->m_driver && subgraph->m_driver->Type() ==
SCH_SHEET_PIN_T )
2440 wxString pinText =
pin->GetShownText(
false );
2447 if( label->
GetShownText( &subgraph->m_sheet,
false ) == pinText )
2450 path.push_back( sheet );
2454 if( parent_conn && parent_conn->
IsBus() )
2461 if( subgraph->m_driver_connection->IsBus() )
2472 updateItemConnectionsTask( m_driver_subgraphs[ii] );
2482 subgraph->m_driver_connection->NetCode() };
2488 std::shared_ptr<NET_SETTINGS>& netSettings =
m_schematic->Project().GetProjectFile().m_NetSettings;
2489 std::map<wxString, std::set<wxString>> oldAssignments = netSettings->GetNetclassLabelAssignments();
2490 std::set<wxString> affectedNetclassNetAssignments;
2492 netSettings->ClearNetclassLabelAssignments();
2494 auto dirtySubgraphs =
2495 [&](
const std::vector<CONNECTION_SUBGRAPH*>& subgraphs )
2497 if( aChangedItemHandler )
2501 for(
SCH_ITEM* item : subgraph->m_items )
2502 (*aChangedItemHandler)( item );
2507 auto checkNetclassDrivers =
2508 [&](
const wxString& netName,
const std::vector<CONNECTION_SUBGRAPH*>& subgraphs )
2510 wxCHECK_RET( !subgraphs.empty(), wxS(
"Invalid empty subgraph" ) );
2512 std::set<wxString> netclasses;
2517 for(
SCH_ITEM* item : subgraph->m_items )
2519 for(
const auto& [
name, provider] : subgraph->GetNetclassesForDriver( item ) )
2520 netclasses.insert(
name );
2527 if( subgraph->m_driver_connection->IsBus() )
2529 auto processBusMember = [&,
this](
const SCH_CONNECTION* member )
2531 if( !netclasses.empty() )
2533 netSettings->AppendNetclassLabelAssignment( member->Name(), netclasses );
2538 if( oldAssignments.count( member->Name() ) )
2540 if( oldAssignments[member->Name()] != netclasses )
2542 affectedNetclassNetAssignments.insert( member->Name() );
2545 dirtySubgraphs( ii->second );
2548 else if( !netclasses.empty() )
2550 affectedNetclassNetAssignments.insert( member->Name() );
2553 dirtySubgraphs( ii->second );
2557 for(
const std::shared_ptr<SCH_CONNECTION>& member : subgraph->m_driver_connection->Members() )
2561 if( member->IsBus() )
2563 for(
const std::shared_ptr<SCH_CONNECTION>& nestedMember : member->Members() )
2564 processBusMember( nestedMember.get() );
2568 processBusMember( member.get() );
2575 if( !netclasses.empty() )
2577 netSettings->AppendNetclassLabelAssignment( netName, netclasses );
2580 if( oldAssignments.count( netName ) )
2582 if( oldAssignments[netName] != netclasses )
2584 affectedNetclassNetAssignments.insert( netName );
2585 dirtySubgraphs( subgraphs );
2588 else if( !netclasses.empty() )
2590 affectedNetclassNetAssignments.insert( netName );
2591 dirtySubgraphs( subgraphs );
2597 checkNetclassDrivers( netname, subgraphs );
2599 if( !aUnconditional )
2601 for(
auto& [netname, netclasses] : oldAssignments )
2603 if( netSettings->GetNetclassLabelAssignments().count( netname )
2604 || affectedNetclassNetAssignments.count( netname ) )
2609 netSettings->SetNetclassLabelAssignment( netname, netclasses );
2647 std::vector<std::shared_ptr<SCH_CONNECTION>> connections_to_check( aConnection->
Members() );
2649 for(
unsigned i = 0; i < connections_to_check.size(); i++ )
2651 const std::shared_ptr<SCH_CONNECTION>& member = connections_to_check[i];
2653 if( member->IsBus() )
2655 connections_to_check.insert( connections_to_check.end(),
2656 member->Members().begin(),
2657 member->Members().end() );
2669 std::vector<CONNECTION_SUBGRAPH*> search_list;
2670 std::unordered_set<CONNECTION_SUBGRAPH*> visited;
2671 std::unordered_set<SCH_CONNECTION*> stale_bus_members;
2678 path.push_back(
pin->GetParent() );
2689 || visited.contains( candidate ) )
2698 wxLogTrace(
ConnTrace, wxS(
"%lu: found child %lu (%s)" ), aParent->m_code,
2706 wxASSERT( candidate->
m_graph == aParent->m_graph );
2708 search_list.push_back( candidate );
2728 || visited.contains( candidate )
2734 const KIID& last_parent_uuid = aParent->m_sheet.Last()->m_Uuid;
2739 if(
pin->GetParent()->m_Uuid != last_parent_uuid )
2745 if( pin_path != aParent->m_sheet )
2750 wxLogTrace(
ConnTrace, wxS(
"%lu: found additional parent %lu (%s)" ),
2753 aParent->m_hier_children.insert( candidate );
2754 search_list.push_back( candidate );
2764 for(
const auto&
kv : aParentGraph->m_bus_neighbors )
2806 wxLogTrace(
ConnTrace, wxS(
"Could not match bus member %s in %s" ),
2807 kv.first->Name(), parent->
Name() );
2813 wxCHECK2( neighbor_conn,
continue );
2815 wxString neighbor_name = neighbor_conn->
Name();
2818 if( neighbor_name == member->
Name() )
2826 wxCHECK2_MSG( neighbor_conn->
IsNet(),
continue,
2827 wxS(
"\"" ) + neighbor_name + wxS(
"\" is not a net." ) );
2829 wxLogTrace(
ConnTrace, wxS(
"%lu (%s) connected to bus member %s (local %s)" ),
2836 member->
Clone( *neighbor_conn );
2837 stale_bus_members.insert( member );
2841 neighbor_conn->
Clone( *member );
2855 propagate_bus_neighbors( aSubgraph );
2862 wxLogTrace(
ConnTrace, wxS(
"%lu (%s) has both hier ports and pins; deferring processing" ),
2868 wxLogTrace(
ConnTrace, wxS(
"%lu (%s) has no hier pins or ports on sheet %s; marking clean" ),
2874 visited.insert( aSubgraph );
2876 wxLogTrace(
ConnTrace, wxS(
"Propagating %lu (%s) to subsheets" ),
2881 for(
unsigned i = 0; i < search_list.size(); i++ )
2883 auto child = search_list[i];
2885 if( visited.insert( child ).second )
2888 child->m_dirty =
false;
2902 if( subgraph == aSubgraph )
2909 wxString candidateName = subgraph->m_driver_connection->Name();
2910 bool shorterPath = subgraph->m_sheet.size() < bestDriver->
m_sheet.
size();
2911 bool asGoodPath = subgraph->m_sheet.size() <= bestDriver->
m_sheet.
size();
2921 ( !bestIsStrong && candidateStrong ) ||
2922 ( priority > highest && candidateStrong ) ||
2923 ( priority == highest && candidateStrong && shorterPath ) ||
2924 ( ( bestIsStrong == candidateStrong ) && asGoodPath && ( priority == highest ) &&
2925 ( candidateName < bestName ) ) )
2927 bestDriver = subgraph;
2929 bestIsStrong = candidateStrong;
2930 bestName = candidateName;
2935 if( bestDriver != aSubgraph )
2937 wxLogTrace(
ConnTrace, wxS(
"%lu (%s) overridden by new driver %lu (%s)" ),
2946 wxString old_name = subgraph->m_driver_connection->Name();
2948 subgraph->m_driver_connection->Clone( *conn );
2950 if( old_name != conn->
Name() )
2954 propagate_bus_neighbors( subgraph );
2960 if( conn->
IsBus() && !stale_bus_members.empty() )
2962 std::unordered_set<SCH_CONNECTION*> cached_members = stale_bus_members;
2972 wxLogTrace(
ConnTrace, wxS(
"WARNING: failed to match stale member %s in %s." ),
2973 stale_member->Name(), subgraph->m_driver_connection->Name() );
2977 wxLogTrace(
ConnTrace, wxS(
"Updating %lu (%s) member %s to %s" ), subgraph->m_code,
2978 subgraph->m_driver_connection->Name(), member->
LocalName(), stale_member->Name() );
2980 member->
Clone( *stale_member );
2982 propagate_bus_neighbors( subgraph );
2994 std::shared_ptr<SCH_CONNECTION> c = std::shared_ptr<SCH_CONNECTION>(
nullptr );
2996 switch( aItem->
Type() )
2999 if(
static_cast<SCH_PIN*
>( aItem )->IsPower() )
3000 c = std::make_shared<SCH_CONNECTION>( aItem, aSubgraph->
m_sheet );
3007 c = std::make_shared<SCH_CONNECTION>( aItem, aSubgraph->
m_sheet );
3016 c->SetGraph(
this );
3028 wxASSERT( aBusConnection->
IsBus() );
3037 for(
const std::shared_ptr<SCH_CONNECTION>& bus_member : aBusConnection->
Members() )
3039 if( bus_member->VectorIndex() == aSearch->
VectorIndex() )
3041 match = bus_member.get();
3049 for(
const std::shared_ptr<SCH_CONNECTION>& c : aBusConnection->
Members() )
3056 for(
const std::shared_ptr<SCH_CONNECTION>& bus_member : c->Members() )
3058 if( bus_member->LocalName() == aSearch->
LocalName() )
3060 match = bus_member.get();
3065 else if( c->LocalName() == aSearch->
LocalName() )
3083 std::vector<CONNECTION_SUBGRAPH*>& vec = it->second;
3084 std::erase( vec, aSubgraph );
3087 wxLogTrace(
ConnTrace, wxS(
"recacheSubgraphName: %s => %s" ), aOldName,
3104 std::vector<const CONNECTION_SUBGRAPH*> ret;
3110 wxASSERT( !subgraph->m_dirty );
3112 if( !subgraph->m_driver )
3118 if( !connection->
IsBus() )
3121 auto labels = subgraph->GetVectorBusLabels();
3123 if( labels.size() > 1 )
3125 bool different =
false;
3128 for(
unsigned i = 1; i < labels.size(); ++i )
3140 wxLogTrace(
ConnTrace, wxS(
"SG %ld (%s) has multiple bus labels" ), subgraph->m_code,
3141 connection->
Name() );
3143 ret.push_back( subgraph );
3164 if( graph == aSubGraph )
3207 wxASSERT( !it->second.empty() );
3209 return it->second[0];
3225const std::vector<CONNECTION_SUBGRAPH*>&
3228 static const std::vector<CONNECTION_SUBGRAPH*> subgraphs;
3241 int error_count = 0;
3243 wxCHECK_MSG(
m_schematic,
true, wxS(
"Null m_schematic in CONNECTION_GRAPH::RunERC" ) );
3249 std::set<SCH_ITEM*> seenDriverInstances;
3254 wxCHECK2( subgraph,
continue );
3258 wxASSERT( !subgraph->m_dirty );
3260 if( subgraph->m_absorbed )
3263 if( seenDriverInstances.count( subgraph->m_driver ) )
3266 if( subgraph->m_driver )
3267 seenDriverInstances.insert( subgraph->m_driver );
3285 subgraph->ResolveDrivers(
false );
3356 wxCHECK( aSubgraph,
false );
3362 if( driver == aSubgraph->
m_driver )
3373 if( primaryName == secondaryName )
3376 wxString msg = wxString::Format(
_(
"Both %s and %s are attached to the same "
3377 "items; %s will be used in the netlist" ),
3378 primaryName, secondaryName, primaryName );
3381 ercItem->SetItems( aSubgraph->
m_driver, driver );
3382 ercItem->SetSheetSpecificPath( aSubgraph->
GetSheet() );
3383 ercItem->SetItemsSheetPaths( aSubgraph->
GetSheet(), aSubgraph->
m_sheet );
3384 ercItem->SetErrorMessage( msg );
3409 switch( item->
Type() )
3414 bus_item = ( !bus_item ) ? item : bus_item;
3416 net_item = ( !net_item ) ? item : net_item;
3430 bus_item = ( !bus_item ) ? item : bus_item;
3432 net_item = ( !net_item ) ? item : net_item;
3442 if( net_item && bus_item )
3445 ercItem->SetSheetSpecificPath( sheet );
3446 ercItem->SetItems( net_item, bus_item );
3449 screen->
Append( marker );
3468 switch( item->
Type() )
3495 if(
test != member && member->Name() ==
test->Name() )
3509 ercItem->SetSheetSpecificPath( sheet );
3510 ercItem->SetItems( label, port );
3513 screen->
Append( marker );
3525 bool conflict =
false;
3541 switch( item->
Type() )
3571 std::set<wxString> test_names;
3583 for(
const auto& sub_member : member->Members() )
3585 if( test_names.count( sub_member->FullLocalName() ) )
3589 else if( test_names.count( member->FullLocalName() ) )
3608 wxString msg = wxString::Format(
_(
"Net %s is graphically connected to bus %s but is not a"
3609 " member of that bus" ),
3613 ercItem->SetSheetSpecificPath( sheet );
3614 ercItem->SetItems( bus_entry, bus_wire );
3615 ercItem->SetErrorMessage( msg );
3618 screen->
Append( marker );
3635 std::set<SCH_PIN*> unique_pins;
3636 std::set<SCH_LABEL_BASE*> unique_labels;
3644 for(
SCH_ITEM* item : aProcessGraph->m_items )
3646 switch( item->
Type() )
3653 if( aProcessGraph == aSubgraph )
3656 if( std::none_of( unique_pins.begin(), unique_pins.end(),
3659 return test_pin->IsStacked( aPin );
3663 unique_pins.insert( test_pin );
3686 process_subgraph( subgraph );
3691 process_subgraph( aSubgraph );
3726 ercItem->SetSheetSpecificPath( sheet );
3727 ercItem->SetItemsSheetPaths( sheet );
3734 pos =
pin->GetPosition();
3743 screen->
Append( marker );
3748 if( unique_pins.empty() && unique_labels.empty() &&
3753 ercItem->SetSheetSpecificPath( sheet );
3754 ercItem->SetItemsSheetPaths( sheet );
3757 screen->
Append( marker );
3764 bool has_other_connections =
false;
3765 std::vector<SCH_PIN*> pins;
3772 switch( item->
Type() )
3779 if( !has_other_connections && !pins.empty()
3782 for(
SCH_PIN* other_pin : pins )
3786 has_other_connections =
true;
3792 pins.emplace_back(
static_cast<SCH_PIN*
>( item ) );
3799 has_other_connections =
true;
3806 pin = pins.empty() ? nullptr : pins[0];
3809 for(
SCH_PIN* test_pin : pins )
3825 if(
pin && !has_other_connections
3827 && !
pin->GetLibPin()->GetParentSymbol()->IsPower() )
3829 wxString
name =
pin->Connection( &sheet )->Name();
3830 wxString local_name =
pin->Connection( &sheet )->Name(
true );
3835 has_other_connections =
true;
3840 if(
pin && !has_other_connections
3846 ercItem->SetSheetSpecificPath( sheet );
3847 ercItem->SetItemsSheetPaths( sheet );
3848 ercItem->SetItems(
pin );
3851 screen->
Append( marker );
3859 if( pins.size() > 1 )
3861 for(
SCH_PIN* testPin : pins )
3866 if( testPin->GetLibPin()->GetParentSymbol()->IsPower()
3867 && testPin->ConnectedItems( sheet ).empty()
3871 ercItem->SetSheetSpecificPath( sheet );
3872 ercItem->SetItemsSheetPaths( sheet );
3873 ercItem->SetItems( testPin );
3876 screen->
Append( marker );
3909 ercItem->SetItems( line );
3910 ercItem->SetSheetSpecificPath( sheet );
3911 ercItem->SetErrorMessage(
_(
"Unconnected wire endpoint" ) );
3933 ercItem->SetItems( entry );
3934 ercItem->SetSheetSpecificPath( sheet );
3935 ercItem->SetErrorMessage(
_(
"Unconnected wire to bus entry" ) );
3952 return err_count > 0;
3962 std::vector<SCH_ITEM*> wires;
3969 wires.emplace_back( item );
3971 wires.emplace_back( item );
3974 if( !wires.empty() )
3979 ercItem->SetSheetSpecificPath( sheet );
3980 ercItem->SetItems( wires[0],
3981 wires.size() > 1 ? wires[1] :
nullptr,
3982 wires.size() > 2 ? wires[2] :
nullptr,
3983 wires.size() > 3 ? wires[3] :
nullptr );
3986 screen->
Append( marker );
4014 size_t pinCount = 0;
4017 std::map<KICAD_T, std::vector<SCH_TEXT*>> label_map;
4023 return std::count_if( aLocSubgraph->m_items.begin(), aLocSubgraph->m_items.end(),
4026 return item->Type() == SCH_PIN_T;
4031 [&](
SCH_TEXT* aText,
int errCode )
4036 ercItem->SetSheetSpecificPath( sheet );
4037 ercItem->SetItems( aText );
4044 pinCount =
hasPins( aSubgraph );
4048 switch( item->
Type() )
4056 label_map[item->
Type()].push_back(
text );
4061 if(
text->IsDangling() )
4075 if( label_map.empty() )
4080 for(
auto& [ connection, subgraphs ] : aSubgraph->
m_bus_parents )
4084 if( busParent->m_no_connect )
4107 wxCHECK_MSG(
m_schematic,
true, wxS(
"Null m_schematic in CONNECTION_GRAPH::ercCheckLabels" ) );
4114 for(
auto& [type, label_vec] : label_map )
4118 size_t allPins = pinCount;
4126 if( neighbor == aSubgraph )
4132 allPins +=
hasPins( neighbor );
4136 if( allPins == 1 && !has_nc )
4158 std::map<wxString, std::tuple<int, const SCH_ITEM*, SCH_SHEET_PATH>> labelData;
4165 wxString resolvedLabelText =
4168 if( labelData.find( resolvedLabelText ) == labelData.end() )
4170 labelData[resolvedLabelText] = { 1, item, sheet };
4174 std::get<0>( labelData[resolvedLabelText] ) += 1;
4175 std::get<1>( labelData[resolvedLabelText] ) =
nullptr;
4176 std::get<2>( labelData[resolvedLabelText] ) = sheet;
4181 for(
const auto& label : labelData )
4183 if( std::get<0>( label.second ) == 1 )
4186 const SCH_ITEM* item = std::get<1>( label.second );
4189 ercItem->SetItems( std::get<1>( label.second ) );
4190 ercItem->SetSheetSpecificPath( sheet );
4191 ercItem->SetItemsSheetPaths( sheet );
4206 int error_count = 0;
4218 ercItem->SetSheetSpecificPath( sheet );
4219 ercItem->SetItems(
text );
4222 sheet.LastScreen()->Append( marker );
4242 if( sheet.Last()->IsRootSheet() )
4248 wxCHECK2( label,
continue );
4250 msg.Printf(
_(
"Hierarchical label '%s' in root sheet cannot be connected to non-existent "
4254 ercItem->SetItems( item );
4255 ercItem->SetErrorMessage( msg );
4258 sheet.LastScreen()->Append( marker );
4269 parentSheetPath.
push_back( parentSheet );
4271 std::map<wxString, SCH_SHEET_PIN*> pins;
4272 std::map<wxString, SCH_HIERLABEL*> labels;
4277 pins[
pin->GetShownText( &parentSheetPath,
false ) ] =
pin;
4282 ercItem->SetItems(
pin );
4283 ercItem->SetSheetSpecificPath( sheet );
4284 ercItem->SetItemsSheetPaths( sheet );
4287 sheet.LastScreen()->Append( marker );
4295 std::set<wxString> matchedPins;
4302 wxString labelText = label->
GetShownText( &parentSheetPath,
false );
4304 if( !pins.contains( labelText ) )
4305 labels[ labelText ] = label;
4307 matchedPins.insert( labelText );
4311 for(
const wxString& matched : matchedPins )
4312 pins.erase( matched );
4314 for(
const auto& [
name,
pin] : pins )
4316 msg.Printf(
_(
"Sheet pin %s has no matching hierarchical label inside the sheet" ),
4320 ercItem->SetItems(
pin );
4321 ercItem->SetErrorMessage( msg );
4322 ercItem->SetSheetSpecificPath( sheet );
4323 ercItem->SetItemsSheetPaths( sheet );
4326 sheet.LastScreen()->Append( marker );
4331 for(
const auto& [
name, label] : labels )
4333 msg.Printf(
_(
"Hierarchical label %s has no matching sheet pin in the parent sheet" ),
4337 ercItem->SetItems( label );
4338 ercItem->SetErrorMessage( msg );
4339 ercItem->SetSheetSpecificPath( parentSheetPath );
4340 ercItem->SetItemsSheetPaths( parentSheetPath );
constexpr EDA_IU_SCALE schIUScale
This represents a sentry transaction which is used for time-performance metrics You start a transacti...
void StartSpan(const std::string &aOperation, const std::string &aDescription)
int RunERC()
Run electrical rule checks on the connectivity graph.
bool ercCheckBusToBusConflicts(const CONNECTION_SUBGRAPH *aSubgraph)
Check one subgraph for conflicting connections between two bus items.
void processSubGraphs()
Process all subgraphs to assign netcodes and merge subgraphs based on labels.
bool ercCheckLabels(const CONNECTION_SUBGRAPH *aSubgraph)
Check one subgraph for proper connection of labels.
void RemoveItem(SCH_ITEM *aItem)
void collectAllDriverValues()
Map the driver values for each subgraph.
CONNECTION_SUBGRAPH * FindSubgraphByName(const wxString &aNetName, const SCH_SHEET_PATH &aPath)
Return the subgraph for a given net name on a given sheet.
int ercCheckDirectiveLabels()
Check directive labels should be connected to something.
void recacheSubgraphName(CONNECTION_SUBGRAPH *aSubgraph, const wxString &aOldName)
static SCH_CONNECTION * matchBusMember(SCH_CONNECTION *aBusConnection, SCH_CONNECTION *aSearch)
Search for a matching bus member inside a bus connection.
std::unordered_map< wxString, std::shared_ptr< BUS_ALIAS > > m_bus_alias_cache
SCHEMATIC * m_schematic
The schematic this graph represents.
void updateGenericItemConnectivity(const SCH_SHEET_PATH &aSheet, SCH_ITEM *aItem, std::map< VECTOR2I, std::vector< SCH_ITEM * > > &aConnectionMap)
Update the connectivity of items that are not pins or symbols.
std::unordered_map< SCH_SHEET_PATH, std::vector< CONNECTION_SUBGRAPH * > > m_sheet_to_subgraphs_map
Cache to lookup subgraphs in m_driver_subgraphs by sheet path.
void updateSymbolConnectivity(const SCH_SHEET_PATH &aSheet, SCH_SYMBOL *aSymbol, std::map< VECTOR2I, std::vector< SCH_ITEM * > > &aConnectionMap)
Update the connectivity of a symbol and its pins.
CONNECTION_SUBGRAPH * FindFirstSubgraphByName(const wxString &aNetName)
Retrieve a subgraph for the given net name, if one exists.
void propagateToNeighbors(CONNECTION_SUBGRAPH *aSubgraph, bool aForce)
Update all neighbors of a subgraph with this one's connectivity info.
void buildItemSubGraphs()
Generate individual item subgraphs on a per-sheet basis.
const std::vector< CONNECTION_SUBGRAPH * > & GetAllSubgraphs(const wxString &aNetName) const
bool ercCheckMultipleDrivers(const CONNECTION_SUBGRAPH *aSubgraph)
If the subgraph has multiple drivers of equal priority that are graphically connected,...
SCH_SHEET_LIST m_sheetList
All the sheets in the schematic (as long as we don't have partial updates).
void generateGlobalPowerPinSubGraphs()
Iterate through the global power pins to collect the global labels as drivers.
std::unordered_map< wxString, int > m_net_name_to_code_map
int ercCheckSingleGlobalLabel()
Check that a global label is instantiated more that once across the schematic hierarchy.
int ercCheckHierSheets()
Check that a hierarchical sheet has at least one matching label inside the sheet for each port on the...
bool ercCheckBusToNetConflicts(const CONNECTION_SUBGRAPH *aSubgraph)
Check one subgraph for conflicting connections between net and bus labels.
std::shared_ptr< SCH_CONNECTION > getDefaultConnection(SCH_ITEM *aItem, CONNECTION_SUBGRAPH *aSubgraph)
Build a new default connection for the given item based on its properties.
std::vector< const CONNECTION_SUBGRAPH * > GetBusesNeedingMigration()
Determine which subgraphs have more than one conflicting bus label.
void Recalculate(const SCH_SHEET_LIST &aSheetList, bool aUnconditional=false, std::function< void(SCH_ITEM *)> *aChangedItemHandler=nullptr, PROGRESS_REPORTER *aProgressReporter=nullptr)
Update the connection graph for the given list of sheets.
int assignNewNetCode(SCH_CONNECTION &aConnection)
Helper to assign a new net code to a connection.
std::map< std::pair< SCH_SHEET_PATH, wxString >, std::vector< const CONNECTION_SUBGRAPH * > > m_local_label_cache
int getOrCreateNetCode(const wxString &aNetName)
bool ercCheckDanglingWireEndpoints(const CONNECTION_SUBGRAPH *aSubgraph)
Check one subgraph for dangling wire endpoints.
void assignNetCodesToBus(SCH_CONNECTION *aConnection)
Ensure all members of the bus connection have a valid net code assigned.
std::unordered_map< wxString, int > m_bus_name_to_code_map
std::unordered_map< wxString, std::vector< const CONNECTION_SUBGRAPH * > > m_global_label_cache
std::vector< CONNECTION_SUBGRAPH * > m_subgraphs
The owner of all CONNECTION_SUBGRAPH objects.
std::vector< std::pair< SCH_SHEET_PATH, SCH_PIN * > > m_global_power_pins
CONNECTION_GRAPH(SCHEMATIC *aSchematic=nullptr)
bool ercCheckNoConnects(const CONNECTION_SUBGRAPH *aSubgraph)
Check one subgraph for proper presence or absence of no-connect symbols.
size_t hasPins(const CONNECTION_SUBGRAPH *aLocSubgraph)
Get the number of pins in a given subgraph.
std::vector< SCH_ITEM * > m_items
All connectable items in the schematic.
std::unordered_map< wxString, std::vector< CONNECTION_SUBGRAPH * > > m_net_name_to_subgraphs_map
std::shared_ptr< BUS_ALIAS > GetBusAlias(const wxString &aName)
Return a bus alias pointer for the given name if it exists (from cache)
void removeSubgraphs(std::set< CONNECTION_SUBGRAPH * > &aSubgraphs)
Remove references to the given subgraphs from all structures in the connection graph.
std::unordered_map< SCH_ITEM *, CONNECTION_SUBGRAPH * > m_item_to_subgraph_map
std::set< std::pair< SCH_SHEET_PATH, SCH_ITEM * > > ExtractAffectedItems(const std::set< SCH_ITEM * > &aItems)
For a set of items, this will remove the connected items and their associated data including subgraph...
wxString GetResolvedSubgraphName(const CONNECTION_SUBGRAPH *aSubGraph) const
Return the fully-resolved netname for a given subgraph.
bool ercCheckBusToBusEntryConflicts(const CONNECTION_SUBGRAPH *aSubgraph)
Check one subgraph for conflicting bus entry to bus connections.
std::vector< CONNECTION_SUBGRAPH * > m_driver_subgraphs
Cache of a subset of m_subgraphs.
void ExchangeItem(SCH_ITEM *aOldItem, SCH_ITEM *aNewItem)
Replace all references to #aOldItem with #aNewItem in the graph.
NET_MAP m_net_code_to_subgraphs_map
bool ercCheckFloatingWires(const CONNECTION_SUBGRAPH *aSubgraph)
Check one subgraph for floating wires.
void buildConnectionGraph(std::function< void(SCH_ITEM *)> *aChangedItemHandler, bool aUnconditional)
Generate the connection graph (after all item connectivity has been updated).
void Merge(CONNECTION_GRAPH &aGraph)
Combine the input graph contents into the current graph.
void updatePinConnectivity(const SCH_SHEET_PATH &aSheet, SCH_PIN *aPin, SCH_CONNECTION *aConnection)
Update the connectivity of a pin and its connections.
void resolveAllDrivers()
Find all subgraphs in the connection graph and calls ResolveDrivers() in parallel.
void updateItemConnectivity(const SCH_SHEET_PATH &aSheet, const std::vector< SCH_ITEM * > &aItemList)
Update the graphical connectivity between items (i.e.
CONNECTION_SUBGRAPH * GetSubgraphForItem(SCH_ITEM *aItem) const
void generateBusAliasMembers()
Iterate through labels to create placeholders for bus elements.
A subgraph is a set of items that are electrically connected on a single sheet.
wxString driverName(SCH_ITEM *aItem) const
PRIORITY GetDriverPriority()
bool m_strong_driver
True if the driver is "strong": a label or power object.
SCH_ITEM * m_no_connect
No-connect item in graph, if any.
std::set< CONNECTION_SUBGRAPH * > m_absorbed_subgraphs
Set of subgraphs that have been absorbed by this subgraph.
static PRIORITY GetDriverPriority(SCH_ITEM *aDriver)
Return the priority (higher is more important) of a candidate driver.
std::mutex m_driver_name_cache_mutex
A cache of escaped netnames from schematic items.
SCH_SHEET_PATH m_sheet
On which logical sheet is the subgraph contained.
void UpdateItemConnections()
Update all items to match the driver connection.
std::set< SCH_SHEET_PIN * > m_hier_pins
Cache for lookup of any hierarchical (sheet) pins on this subgraph (for referring down).
std::unordered_map< std::shared_ptr< SCH_CONNECTION >, std::unordered_set< CONNECTION_SUBGRAPH * > > m_bus_neighbors
If a subgraph is a bus, this map contains links between the bus members and any local sheet neighbors...
CONNECTION_GRAPH * m_graph
std::vector< SCH_ITEM * > GetAllBusLabels() const
Return all the all bus labels attached to this subgraph (if any).
std::unordered_map< SCH_ITEM *, wxString > m_driver_name_cache
const wxString & GetNameForDriver(SCH_ITEM *aItem) const
Return the candidate net name for a driver.
wxString GetNetName() const
Return the fully-qualified net name for this subgraph (if one exists)
std::vector< SCH_ITEM * > GetVectorBusLabels() const
Return all the vector-based bus labels attached to this subgraph (if any).
const SCH_SHEET_PATH & GetSheet() const
bool m_multiple_drivers
True if this subgraph contains more than one driver that should be shorted together in the netlist.
bool ResolveDrivers(bool aCheckMultipleDrivers=false)
Determine which potential driver should drive the subgraph.
std::set< SCH_ITEM * > m_drivers
bool m_absorbed
True if this subgraph has been absorbed into another. No pointers here are safe if so!
SCH_CONNECTION * m_driver_connection
Cache for driver connection.
CONNECTION_SUBGRAPH * m_absorbed_by
If this subgraph is absorbed, points to the absorbing (and valid) subgraph.
std::unordered_set< CONNECTION_SUBGRAPH * > m_hier_children
If not null, this indicates the subgraph(s) on a lower level sheet that are linked to this one.
void AddItem(SCH_ITEM *aItem)
Add a new item to the subgraph.
const std::vector< std::pair< wxString, SCH_ITEM * > > GetNetclassesForDriver(SCH_ITEM *aItem) const
Return the resolved netclasses for the item, and the source item providing the netclass.
void Absorb(CONNECTION_SUBGRAPH *aOther)
Combine another subgraph on the same sheet into this one.
std::set< SCH_ITEM * > m_items
Contents of the subgraph.
std::unordered_map< std::shared_ptr< SCH_CONNECTION >, std::unordered_set< CONNECTION_SUBGRAPH * > > m_bus_parents
If this is a net, this vector contains links to any same-sheet buses that contain it.
SCH_ITEM * m_driver
Fully-resolved driver for the subgraph (might not exist in this subgraph).
CONNECTION_SUBGRAPH(CONNECTION_GRAPH *aGraph)
std::mutex m_driver_mutex
bool m_is_bus_member
True if the subgraph is not actually part of a net.
void ExchangeItem(SCH_ITEM *aOldItem, SCH_ITEM *aNewItem)
Replaces all references to #aOldItem with #aNewItem in the subgraph.
CONNECTION_SUBGRAPH * m_hier_parent
If not null, this indicates the subgraph on a higher level sheet that is linked to this one.
void RemoveItem(SCH_ITEM *aItem)
bool m_local_driver
True if the driver is a local (i.e. non-global) type.
std::set< SCH_HIERLABEL * > m_hier_ports
Cache for lookup of any hierarchical ports on this subgraph (for referring up).
void getAllConnectedItems(std::set< std::pair< SCH_SHEET_PATH, SCH_ITEM * > > &aItems, std::set< CONNECTION_SUBGRAPH * > &aSubgraphs)
Find all items in the subgraph as well as child subgraphs recursively.
virtual VECTOR2I GetPosition() const
virtual wxString GetItemDescription(UNITS_PROVIDER *aUnitsProvider, bool aFull) const
Return a user-visible description string of this item.
KICAD_T Type() const
Returns the type of object.
EE_TYPE Overlapping(const BOX2I &aRect) const
EE_TYPE OfType(KICAD_T aType) const
static std::shared_ptr< ERC_ITEM > Create(int aErrorCode)
Constructs an ERC_ITEM for the given error code.
Container for ERC settings.
bool IsTestEnabled(int aErrorCode) const
bool GetDuplicatePinNumbersAreJumpers() const
std::vector< std::set< wxString > > & JumperPinGroups()
Each jumper pin group is a set of pin numbers that should be treated as internally connected.
A small class to help profiling.
void Show(std::ostream &aStream=std::cerr)
Print the elapsed time (in a suitable unit) to a stream.
void Stop()
Save the time when this function was called, and set the counter stane to stop.
A progress reporter interface for use in multi-threaded environments.
virtual bool KeepRefreshing(bool aWait=false)=0
Update the UI (if any).
virtual void SetCurrentProgress(double aProgress)=0
Set the progress value to aProgress (0..1).
Class for a bus to bus entry.
SCH_ITEM * m_connected_bus_items[2]
Pointer to the bus items (usually bus wires) connected to this bus-bus entry (either or both may be n...
bool IsStartDangling() const
VECTOR2I GetPosition() const override
bool IsEndDangling() const
std::vector< VECTOR2I > GetConnectionPoints() const override
Add all the connection points for this item to aPoints.
Class for a wire to bus entry.
SCH_ITEM * m_connected_bus_item
Pointer to the bus item (usually a bus wire) connected to this bus-wire entry, if it is connected to ...
Each graphical item can have a SCH_CONNECTION describing its logical connection (to a bus or net).
wxString FullLocalName() const
void ConfigureFromLabel(const wxString &aLabel)
Configures the connection given a label.
void SetSubgraphCode(int aCode)
void SetBusCode(int aCode)
void SetName(const wxString &aName)
SCH_SHEET_PATH Sheet() const
CONNECTION_TYPE Type() const
void SetNetCode(int aCode)
SCH_ITEM * m_driver
The SCH_ITEM that drives this connection's net.
bool IsDriver() const
Checks if the SCH_ITEM this connection is attached to can drive connections Drivers can be labels,...
void SetType(CONNECTION_TYPE aType)
wxString LocalName() const
wxString Name(bool aIgnoreSheet=false) const
bool IsSubsetOf(SCH_CONNECTION *aOther) const
Returns true if this connection is contained within aOther (but not the same as aOther)
void SetDriver(SCH_ITEM *aItem)
void Clone(const SCH_CONNECTION &aOther)
Copies connectivity information (but not parent) from another connection.
void SetGraph(CONNECTION_GRAPH *aGraph)
const std::vector< std::shared_ptr< SCH_CONNECTION > > & Members() const
wxString GetCanonicalName() const
Get a non-language-specific name for a field which can be used for storage, variable look-up,...
wxString GetShownText(const SCH_SHEET_PATH *aPath, bool aAllowExtraText, int aDepth=0) const
Base class for any item which can be embedded within the SCHEMATIC container class,...
void ClearConnectedItems(const SCH_SHEET_PATH &aPath)
Clear all connections to this item.
virtual void RunOnChildren(const std::function< void(SCH_ITEM *)> &aFunction, RECURSE_MODE aMode)
const SYMBOL * GetParentSymbol() const
virtual const wxString & GetCachedDriverName() const
const std::unordered_set< SCH_RULE_AREA * > & GetRuleAreaCache() const
Get the cache of rule areas enclosing this item.
SCH_CONNECTION * InitializeConnection(const SCH_SHEET_PATH &aPath, CONNECTION_GRAPH *aGraph)
Create a new connection object associated with this object.
void AddConnectionTo(const SCH_SHEET_PATH &aPath, SCH_ITEM *aItem)
Add a connection link between this item and another.
SCH_LAYER_ID GetLayer() const
Return the layer this item is on.
void SetConnectionGraph(CONNECTION_GRAPH *aGraph)
Update the connection graph for all connections in this item.
virtual void SetUnit(int aUnit)
virtual bool HasCachedDriverName() const
SCH_CONNECTION * GetOrInitConnection(const SCH_SHEET_PATH &aPath, CONNECTION_GRAPH *aGraph)
SCH_CONNECTION * Connection(const SCH_SHEET_PATH *aSheet=nullptr) const
Retrieve the connection associated with this object in the given sheet.
virtual std::vector< VECTOR2I > GetConnectionPoints() const
Add all the connection points for this item to aPoints.
wxString GetShownText(const SCH_SHEET_PATH *aPath, bool aAllowExtraText, int aDepth=0) const override
bool IsDangling() const override
LABEL_FLAG_SHAPE GetShape() const
Segment description base class to describe items which have 2 end points (track, wire,...
std::vector< VECTOR2I > GetConnectionPoints() const override
Add all the connection points for this item to aPoints.
bool IsStartDangling() const
bool IsEndDangling() const
bool IsGraphicLine() const
Return if the line is a graphic (non electrical line)
bool IsGlobalPower() const
Return whether this pin forms a global power connection: i.e., is part of a power symbol and of type ...
bool IsLocalPower() const
Local power pin is the same except that it is sheet-local and it does not support the legacy hidden p...
SCH_PIN * GetLibPin() const
bool IsStacked(const SCH_PIN *aPin) const
wxString GetDefaultNetName(const SCH_SHEET_PATH &aPath, bool aForceNoConnect=false)
bool IsPower() const
Check if the pin is either a global or local power pin.
ELECTRICAL_PINTYPE GetType() const
void Append(SCH_ITEM *aItem, bool aUpdateLibSymbol=true)
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