Connectivity optimizations

Cache names of potential driving items
Change a few data structures based on profiling
This commit is contained in:
Jon Evans 2020-07-09 18:14:27 -04:00
parent fc92fb076e
commit 66bdd37637
2 changed files with 61 additions and 75 deletions

View File

@ -43,6 +43,13 @@
#include <advanced_config.h> // for realtime connectivity switch
/*
* Flag to enable connectivity profiling
* @ingroup trace_env_vars
*/
static const wxChar ConnProfileMask[] = wxT( "CONN_PROFILE" );
bool CONNECTION_SUBGRAPH::ResolveDrivers( bool aCreateMarkers )
{
PRIORITY highest_priority = PRIORITY::INVALID;
@ -227,16 +234,17 @@ std::vector<SCH_ITEM*> CONNECTION_SUBGRAPH::GetBusLabels() const
}
wxString CONNECTION_SUBGRAPH::GetNameForDriver( SCH_ITEM* aItem ) const
const wxString& CONNECTION_SUBGRAPH::GetNameForDriver( SCH_ITEM* aItem )
{
wxString name;
if( m_driver_name_cache.count( aItem ) )
return m_driver_name_cache.at( aItem );
switch( aItem->Type() )
{
case SCH_PIN_T:
{
SCH_PIN* pin = static_cast<SCH_PIN*>( aItem );
name = pin->GetDefaultNetName( m_sheet );
m_driver_name_cache[aItem] = pin->GetDefaultNetName( m_sheet );
break;
}
@ -245,15 +253,17 @@ wxString CONNECTION_SUBGRAPH::GetNameForDriver( SCH_ITEM* aItem ) const
case SCH_HIER_LABEL_T:
case SCH_SHEET_PIN_T:
{
name = EscapeString( static_cast<SCH_TEXT*>( aItem )->GetShownText(), CTX_NETNAME );
m_driver_name_cache[aItem] = EscapeString( static_cast<SCH_TEXT*>( aItem )->GetShownText(),
CTX_NETNAME );
break;
}
default:
wxFAIL_MSG( "Unhandled item type in GetNameForDriver" );
break;
}
return name;
return m_driver_name_cache.at( aItem );
}
@ -376,40 +386,45 @@ void CONNECTION_GRAPH::Reset()
void CONNECTION_GRAPH::Recalculate( const SCH_SHEET_LIST& aSheetList, bool aUnconditional )
{
PROF_COUNTER recalc_time;
PROF_COUNTER update_items;
PROF_COUNTER recalc_time( "CONNECTION_GRAPH::Recalculate" );
if( aUnconditional )
Reset();
PROF_COUNTER update_items( "updateItemConnectivity" );
for( const SCH_SHEET_PATH& sheet : aSheetList )
{
std::vector<SCH_ITEM*> items;
for( auto item : sheet.LastScreen()->Items() )
for( SCH_ITEM* item : sheet.LastScreen()->Items() )
{
if( item->IsConnectable() && ( aUnconditional || item->IsConnectivityDirty() ) )
items.push_back( item );
}
m_items.reserve( m_items.size() + items.size() );
updateItemConnectivity( sheet, items );
// UpdateDanglingState() also adds connected items for SCH_TEXT
sheet.LastScreen()->TestDanglingEnds( &sheet );
}
update_items.Stop();
wxLogTrace( "CONN_PROFILE", "UpdateItemConnectivity() %0.4f ms", update_items.msecs() );
if( wxLog::IsAllowedTraceMask( ConnProfileMask ) )
update_items.Show();
PROF_COUNTER build_graph;
PROF_COUNTER build_graph( "buildConnectionGraph" );
buildConnectionGraph();
build_graph.Stop();
wxLogTrace( "CONN_PROFILE", "BuildConnectionGraph() %0.4f ms", build_graph.msecs() );
if( wxLog::IsAllowedTraceMask( ConnProfileMask ) )
build_graph.Show();
recalc_time.Stop();
wxLogTrace( "CONN_PROFILE", "Recalculate time %0.4f ms", recalc_time.msecs() );
if( wxLog::IsAllowedTraceMask( ConnProfileMask ) )
recalc_time.Show();
#ifndef DEBUG
// Pressure relief valve for release builds
@ -427,7 +442,7 @@ void CONNECTION_GRAPH::Recalculate( const SCH_SHEET_LIST& aSheetList, bool aUnco
void CONNECTION_GRAPH::updateItemConnectivity( const SCH_SHEET_PATH& aSheet,
const std::vector<SCH_ITEM*>& aItemList )
{
std::unordered_map< wxPoint, std::vector<SCH_ITEM*> > connection_map;
std::map< wxPoint, std::vector<SCH_ITEM*> > connection_map;
for( SCH_ITEM* item : aItemList )
{
@ -446,7 +461,7 @@ void CONNECTION_GRAPH::updateItemConnectivity( const SCH_SHEET_PATH& aSheet,
pin->Connection( aSheet )->Reset();
connection_map[ pin->GetTextPos() ].push_back( pin );
m_items.insert( pin );
m_items.emplace_back( pin );
}
}
else if( item->Type() == SCH_COMPONENT_T )
@ -476,12 +491,12 @@ void CONNECTION_GRAPH::updateItemConnectivity( const SCH_SHEET_PATH& aSheet,
m_invisible_power_pins.emplace_back( std::make_pair( aSheet, pin ) );
connection_map[ pos ].push_back( pin );
m_items.insert( pin );
m_items.emplace_back( pin );
}
}
else
{
m_items.insert( item );
m_items.emplace_back( item );
auto conn = item->InitializeConnection( aSheet, this );
// Set bus/net property here so that the propagation code uses it
@ -803,37 +818,7 @@ void CONNECTION_GRAPH::buildConnectionGraph()
SCH_SHEET_PATH sheet = subgraph->m_sheet;
SCH_CONNECTION* connection = driver->Connection( sheet );
// TODO(JE) This should live in SCH_CONNECTION probably
switch( driver->Type() )
{
case SCH_LABEL_T:
case SCH_GLOBAL_LABEL_T:
case SCH_HIER_LABEL_T:
{
auto text = static_cast<SCH_TEXT*>( driver );
connection->ConfigureFromLabel( EscapeString( text->GetShownText(), CTX_NETNAME ) );
break;
}
case SCH_SHEET_PIN_T:
{
auto pin = static_cast<SCH_SHEET_PIN*>( driver );
connection->ConfigureFromLabel( EscapeString( pin->GetShownText(), CTX_NETNAME ) );
break;
}
case SCH_PIN_T:
{
auto pin = static_cast<SCH_PIN*>( driver );
// NOTE(JE) GetDefaultNetName is not thread-safe.
connection->ConfigureFromLabel( pin->GetDefaultNetName( sheet ) );
break;
}
default:
wxLogTrace( "CONN", "Driver type unsupported: %s",
driver->GetSelectMenuText( EDA_UNITS::MILLIMETRES ) );
break;
}
connection->ConfigureFromLabel( subgraph->GetNameForDriver( driver ) );
connection->SetDriver( driver );
connection->ClearDirty();
@ -1139,7 +1124,7 @@ void CONNECTION_GRAPH::buildConnectionGraph()
if( possible_driver == aSubgraph->m_driver )
continue;
auto c = getDefaultConnection( possible_driver, aSubgraph->m_sheet );
auto c = getDefaultConnection( possible_driver, aSubgraph );
if( c )
{
@ -1215,9 +1200,7 @@ void CONNECTION_GRAPH::buildConnectionGraph()
driver->Type() == SCH_GLOBAL_LABEL_T ||
driver->Type() == SCH_HIER_LABEL_T );
auto text = static_cast<SCH_TEXT*>( driver );
if( EscapeString( text->GetShownText(), CTX_NETNAME ) == test_name )
if( subgraph->GetNameForDriver( driver ) == test_name )
{
match = true;
break;
@ -1551,7 +1534,7 @@ void CONNECTION_GRAPH::propagateToNeighbors( CONNECTION_SUBGRAPH* aSubgraph )
if( !m_sheet_to_subgraphs_map.count( path ) )
continue;
for( auto candidate : m_sheet_to_subgraphs_map.at( path ) )
for( CONNECTION_SUBGRAPH* candidate : m_sheet_to_subgraphs_map.at( path ) )
{
if( !candidate->m_strong_driver ||
candidate->m_hier_ports.empty() ||
@ -1560,7 +1543,7 @@ void CONNECTION_GRAPH::propagateToNeighbors( CONNECTION_SUBGRAPH* aSubgraph )
for( SCH_HIERLABEL* label : candidate->m_hier_ports )
{
if( label->GetShownText() == pin->GetShownText() )
if( candidate->GetNameForDriver( label ) == aParent->GetNameForDriver( pin ) )
{
wxLogTrace( "CONN", "%lu: found child %lu (%s)", aParent->m_code,
candidate->m_code, candidate->m_driver_connection->Name() );
@ -1582,7 +1565,7 @@ void CONNECTION_GRAPH::propagateToNeighbors( CONNECTION_SUBGRAPH* aSubgraph )
if( !m_sheet_to_subgraphs_map.count( path ) )
continue;
for( auto candidate : m_sheet_to_subgraphs_map.at( path ) )
for( CONNECTION_SUBGRAPH* candidate : m_sheet_to_subgraphs_map.at( path ) )
{
if( candidate->m_hier_pins.empty() ||
visited.count( candidate ) ||
@ -1598,7 +1581,7 @@ void CONNECTION_GRAPH::propagateToNeighbors( CONNECTION_SUBGRAPH* aSubgraph )
if( pin_path != aParent->m_sheet )
continue;
if( label->GetShownText() == pin->GetShownText() )
if( aParent->GetNameForDriver( label ) == candidate->GetNameForDriver( pin ) )
{
wxLogTrace( "CONN", "%lu: found additional parent %lu (%s)",
aParent->m_code, candidate->m_code,
@ -1639,7 +1622,7 @@ void CONNECTION_GRAPH::propagateToNeighbors( CONNECTION_SUBGRAPH* aSubgraph )
for( SCH_ITEM* driver : sg->m_drivers )
{
auto c = getDefaultConnection( driver, sheet );
auto c = getDefaultConnection( driver, sg );
member = matchBusMember( parent, c.get() );
if( member )
@ -1807,8 +1790,8 @@ void CONNECTION_GRAPH::propagateToNeighbors( CONNECTION_SUBGRAPH* aSubgraph )
}
std::shared_ptr<SCH_CONNECTION>
CONNECTION_GRAPH::getDefaultConnection( SCH_ITEM* aItem, const SCH_SHEET_PATH& aSheet )
std::shared_ptr<SCH_CONNECTION> CONNECTION_GRAPH::getDefaultConnection( SCH_ITEM* aItem,
CONNECTION_SUBGRAPH* aSubgraph )
{
auto c = std::shared_ptr<SCH_CONNECTION>( nullptr );
@ -1819,11 +1802,8 @@ CONNECTION_GRAPH::getDefaultConnection( SCH_ITEM* aItem, const SCH_SHEET_PATH& a
auto pin = static_cast<SCH_PIN*>( aItem );
if( pin->IsPowerConnection() )
{
c = std::make_shared<SCH_CONNECTION>( aItem, aSheet );
c->SetGraph( this );
c->ConfigureFromLabel( pin->GetName() );
}
c = std::make_shared<SCH_CONNECTION>( aItem, aSubgraph->m_sheet );
break;
}
@ -1831,11 +1811,7 @@ CONNECTION_GRAPH::getDefaultConnection( SCH_ITEM* aItem, const SCH_SHEET_PATH& a
case SCH_HIER_LABEL_T:
case SCH_LABEL_T:
{
auto text = static_cast<SCH_TEXT*>( aItem );
c = std::make_shared<SCH_CONNECTION>( aItem, aSheet );
c->SetGraph( this );
c->ConfigureFromLabel( EscapeString( text->GetShownText(), CTX_NETNAME ) );
c = std::make_shared<SCH_CONNECTION>( aItem, aSubgraph->m_sheet );
break;
}
@ -1843,6 +1819,12 @@ CONNECTION_GRAPH::getDefaultConnection( SCH_ITEM* aItem, const SCH_SHEET_PATH& a
break;
}
if( c )
{
c->SetGraph( this );
c->ConfigureFromLabel( aSubgraph->GetNameForDriver( aItem ) );
}
return c;
}
@ -1899,8 +1881,8 @@ SCH_CONNECTION* CONNECTION_GRAPH::matchBusMember( SCH_CONNECTION* aBusConnection
}
void CONNECTION_GRAPH::recacheSubgraphName(
CONNECTION_SUBGRAPH* aSubgraph, const wxString& aOldName )
void CONNECTION_GRAPH::recacheSubgraphName( CONNECTION_SUBGRAPH* aSubgraph,
const wxString& aOldName )
{
if( m_net_name_to_subgraphs_map.count( aOldName ) )
{

View File

@ -110,7 +110,7 @@ public:
std::vector<SCH_ITEM*> GetBusLabels() const;
/// Returns the candidate net name for a driver
wxString GetNameForDriver( SCH_ITEM* aItem ) const;
const wxString& GetNameForDriver( SCH_ITEM* aItem );
/// Combines another subgraph on the same sheet into this one.
void Absorb( CONNECTION_SUBGRAPH* aOther );
@ -206,6 +206,9 @@ public:
// If not null, this indicates the subgraph on a higher level sheet that is linked to this one
CONNECTION_SUBGRAPH* m_hier_parent;
/// A cache of escaped netnames from schematic items
std::unordered_map<SCH_ITEM*, wxString> m_driver_name_cache;
};
/// Associates a net code with the final name of a net
@ -299,7 +302,7 @@ public:
private:
std::unordered_set<SCH_ITEM*> m_items;
std::vector<SCH_ITEM*> m_items;
// The owner of all CONNECTION_SUBGRAPH objects
std::vector<CONNECTION_SUBGRAPH*> m_subgraphs;
@ -423,10 +426,11 @@ private:
* Handles strong drivers (power pins and labels) only
*
* @param aItem is an item that can generate a connection name
* @param aSubgraph is used to determine the sheet to use and retrieve the cached name
* @return a connection generated from the item, or nullptr if item is not valid
*/
std::shared_ptr<SCH_CONNECTION> getDefaultConnection( SCH_ITEM* aItem,
const SCH_SHEET_PATH& aSheet );
CONNECTION_SUBGRAPH* aSubgraph );
void recacheSubgraphName( CONNECTION_SUBGRAPH* aSubgraph, const wxString& aOldName );