Connectivity: defer and parallelize item updates

Good for ~15% performance improvement in large designs
This commit is contained in:
Jon Evans 2021-01-14 10:14:09 -05:00
parent 6fb1ed2824
commit 654e9a77db
2 changed files with 585 additions and 551 deletions

View File

@ -1003,9 +1003,6 @@ void CONNECTION_GRAPH::buildConnectionGraph()
connection->SetSubgraphCode( subgraph->m_code );
}
for( auto it : invisible_pin_subgraphs )
it.second->UpdateItemConnections();
// Here we do all the local (sheet) processing of each subgraph, including assigning net
// codes, merging subgraphs together that use label connections, etc.
@ -1085,8 +1082,6 @@ void CONNECTION_GRAPH::buildConnectionGraph()
m_net_name_to_subgraphs_map[new_name].emplace_back( subgraph );
name = new_name;
subgraph->UpdateItemConnections();
}
else
{
@ -1161,8 +1156,6 @@ void CONNECTION_GRAPH::buildConnectionGraph()
assignNewNetCode( *connection );
}
subgraph->UpdateItemConnections();
// Reset the flag for the next loop below
subgraph->m_dirty = true;
@ -1332,8 +1325,6 @@ void CONNECTION_GRAPH::buildConnectionGraph()
else
assignNewNetCode( *subgraph->m_driver_connection );
subgraph->UpdateItemConnections();
wxLogTrace( ConnTrace, "Re-resolving drivers for %lu (%s)", subgraph->m_code,
subgraph->m_driver_connection->Name() );
}
@ -1361,6 +1352,34 @@ void CONNECTION_GRAPH::buildConnectionGraph()
for( CONNECTION_SUBGRAPH* subgraph : m_driver_subgraphs )
m_sheet_to_subgraphs_map[ subgraph->m_sheet ].emplace_back( subgraph );
// Update item connections at this point so that neighbor propagation works
nextSubgraph.store( 0 );
auto preliminaryUpdateTask =
[&]() -> size_t
{
for( size_t subgraphId = nextSubgraph++;
subgraphId < m_driver_subgraphs.size();
subgraphId = nextSubgraph++ )
{
m_driver_subgraphs[subgraphId]->UpdateItemConnections();
}
return 1;
};
if( parallelThreadCount == 1 )
preliminaryUpdateTask();
else
{
for( size_t ii = 0; ii < parallelThreadCount; ++ii )
returns[ii] = std::async( std::launch::async, preliminaryUpdateTask );
// Finalize the threads
for( size_t ii = 0; ii < parallelThreadCount; ++ii )
returns[ii].wait();
}
// Next time through the subgraphs, we do some post-processing to handle things like
// connecting bus members to their neighboring subgraphs, and then propagate connections
// through the hierarchy
@ -1405,7 +1424,6 @@ void CONNECTION_GRAPH::buildConnectionGraph()
conn->Name(), subgraph->m_driver_connection->Name() );
conn->Clone( *subgraph->m_driver_connection );
candidate->UpdateItemConnections();
candidate->m_dirty = false;
}
@ -1477,33 +1495,30 @@ void CONNECTION_GRAPH::buildConnectionGraph()
old_sg = old_sg->m_absorbed_by;
old_sg->m_driver_connection->Clone( *conn );
old_sg->UpdateItemConnections();
}
}
}
}
}
m_net_code_to_subgraphs_map.clear();
m_net_name_to_subgraphs_map.clear();
nextSubgraph.store( 0 );
for( CONNECTION_SUBGRAPH* subgraph : m_driver_subgraphs )
auto updateItemConnectionsTask =
[&]() -> size_t
{
// Every driven subgraph should have been marked by now
if( subgraph->m_dirty )
for( size_t subgraphId = nextSubgraph++;
subgraphId < m_driver_subgraphs.size();
subgraphId = nextSubgraph++ )
{
// TODO(JE) this should be caught by hierarchical sheet port/pin ERC, check this
// Reset to false so no complaints come up later
CONNECTION_SUBGRAPH* subgraph = m_driver_subgraphs[subgraphId];
subgraph->m_dirty = false;
}
subgraph->UpdateItemConnections();
if( subgraph->m_driver_connection->IsBus() )
{
// No other processing to do on buses
if( subgraph->m_driver_connection->IsBus() )
continue;
}
else
{
// As a visual aid, we can check sheet pins that are driven by themselves to see
// if they should be promoted to buses
@ -1514,10 +1529,11 @@ void CONNECTION_GRAPH::buildConnectionGraph()
if( SCH_SHEET* sheet = pin->GetParent() )
{
wxString pinText = pin->GetText();
SCH_SCREEN* screen = sheet->GetScreen();
for( auto item : sheet->GetScreen()->Items().OfType( SCH_HIER_LABEL_T ) )
for( SCH_ITEM* item : screen->Items().OfType( SCH_HIER_LABEL_T ) )
{
auto label = static_cast<SCH_HIERLABEL*>( item );
SCH_HIERLABEL* label = static_cast<SCH_HIERLABEL*>( item );
if( label->GetText() == pinText )
{
@ -1539,6 +1555,26 @@ void CONNECTION_GRAPH::buildConnectionGraph()
}
}
return 1;
};
if( parallelThreadCount == 1 )
updateItemConnectionsTask();
else
{
for( size_t ii = 0; ii < parallelThreadCount; ++ii )
returns[ii] = std::async( std::launch::async, updateItemConnectionsTask );
// Finalize the threads
for( size_t ii = 0; ii < parallelThreadCount; ++ii )
returns[ii].wait();
}
m_net_code_to_subgraphs_map.clear();
m_net_name_to_subgraphs_map.clear();
for( CONNECTION_SUBGRAPH* subgraph : m_driver_subgraphs )
{
auto key = std::make_pair( subgraph->GetNetName(),
subgraph->m_driver_connection->NetCode() );
m_net_code_to_subgraphs_map[ key ].push_back( subgraph );
@ -1752,7 +1788,6 @@ void CONNECTION_GRAPH::propagateToNeighbors( CONNECTION_SUBGRAPH* aSubgraph )
else
{
neighbor_conn->Clone( *member );
neighbor->UpdateItemConnections();
recacheSubgraphName( neighbor, neighbor_name );
@ -1853,7 +1888,6 @@ void CONNECTION_GRAPH::propagateToNeighbors( CONNECTION_SUBGRAPH* aSubgraph )
wxString old_name = subgraph->m_driver_connection->Name();
subgraph->m_driver_connection->Clone( *conn );
subgraph->UpdateItemConnections();
if( old_name != conn->Name() )
recacheSubgraphName( subgraph, old_name );

File diff suppressed because it is too large Load Diff