Fix a few issues with hierarchical propagation

This commit is contained in:
Jon Evans 2019-03-18 18:38:06 -04:00 committed by Wayne Stambaugh
parent 3c714f1d8c
commit e98debfeb2
4 changed files with 251 additions and 84 deletions

View File

@ -50,6 +50,13 @@ bool CONNECTION_SUBGRAPH::ResolveDrivers( bool aCreateMarkers )
m_driver = nullptr;
// Hierarchical labels are lower priority than local labels here,
// because on the first pass we want local labels to drive subgraphs
// so that we can identify same-sheet neighbors and link them together.
// Hierarchical labels will end up overriding the final net name if
// a higher-level sheet has a different name during the hierarchical
// pass.
for( auto item : m_drivers )
{
int item_priority = 0;
@ -57,8 +64,8 @@ bool CONNECTION_SUBGRAPH::ResolveDrivers( bool aCreateMarkers )
switch( item->Type() )
{
case SCH_SHEET_PIN_T: item_priority = 2; break;
case SCH_LABEL_T: item_priority = 3; break;
case SCH_HIERARCHICAL_LABEL_T: item_priority = 4; break;
case SCH_HIERARCHICAL_LABEL_T: item_priority = 3; break;
case SCH_LABEL_T: item_priority = 4; break;
case SCH_PIN_CONNECTION_T:
{
auto pin_connection = static_cast<SCH_PIN_CONNECTION*>( item );
@ -90,6 +97,9 @@ bool CONNECTION_SUBGRAPH::ResolveDrivers( bool aCreateMarkers )
}
}
if( highest_priority >= 4 )
m_strong_driver = true;
if( candidates.size() )
{
if( candidates.size() > 1 )
@ -109,8 +119,26 @@ bool CONNECTION_SUBGRAPH::ResolveDrivers( bool aCreateMarkers )
return name_a < name_b;
} );
}
if( highest_priority == 2 )
{
// We have multiple options, and they are all hierarchical
// sheet pins. Let's prefer outputs over inputs.
for( auto c : candidates )
{
auto p = static_cast<SCH_SHEET_PIN*>( c );
if( p->GetShape() == NET_OUTPUT )
{
m_driver = c;
break;
}
}
}
}
if( !m_driver )
m_driver = candidates[0];
}
@ -641,6 +669,56 @@ void CONNECTION_GRAPH::buildConnectionGraph()
while( threadsFinished < parallelThreadCount )
std::this_thread::sleep_for( std::chrono::milliseconds( 10 ) );
// Check for subgraphs with the same net name but only weak drivers.
// For example, two wires that are both connected to hierarchical
// sheet pins that happen to have the same name, but are not the same.
for( auto subgraph : m_subgraphs )
subgraph->m_dirty = true;
for( auto subgraph : m_subgraphs )
{
if( !subgraph->m_dirty )
continue;
subgraph->m_dirty = false;
if( !subgraph->m_driver || subgraph->m_strong_driver )
continue;
auto name = subgraph->m_driver->Connection( subgraph->m_sheet )->Name();
unsigned suffix = 1;
for( auto candidate : m_subgraphs )
{
if( !candidate->m_dirty )
continue;
if( candidate == subgraph || !candidate->m_driver || candidate->m_strong_driver )
continue;
auto conn = candidate->m_driver->Connection( candidate->m_sheet );
auto check_name = conn->Name();
if( check_name == name )
{
auto new_name = wxString::Format( _( "%s%u" ), name, suffix );
#ifdef CONNECTIVITY_DEBUG
wxLogDebug( "Subgraph %ld and %ld both have name %s. Changing %ld to %s.",
subgraph->m_code, candidate->m_code, name,
candidate->m_code, new_name );
#endif
conn->SetSuffix( wxString::Format( _( "%u" ), suffix ) );
candidate->m_dirty = false;
suffix++;
}
}
}
// Generate net codes
for( auto subgraph : m_subgraphs )
@ -721,6 +799,10 @@ void CONNECTION_GRAPH::buildConnectionGraph()
connections_to_check.push_back( std::make_shared<SCH_CONNECTION>( *connection ) );
}
// Look for "neighbors" for subgraphs that have hierarchical connections.
// These are usually other subgraphs that have local labels on the
// same sheet and so should be connected together.
for( unsigned i = 0; i < connections_to_check.size(); i++ )
{
auto member = connections_to_check[i];
@ -984,15 +1066,31 @@ void CONNECTION_GRAPH::buildConnectionGraph()
* 3) Recurse down onto any subsheets connected to the SSSG.
*/
for( auto item : subgraph->m_items )
std::vector<CONNECTION_SUBGRAPH*> child_subgraphs;
child_subgraphs.push_back( subgraph );
for( unsigned i = 0; i < child_subgraphs.size(); i++ )
{
// child_subgraphs[i] now refers to the "parent" subgraph that we
// are descending the hierarchy with. If there are multiple levels
// of hierarchy, those will get pushed onto child_subgraphs below.
for( auto item : child_subgraphs[i]->m_items )
{
if( item->Type() == SCH_SHEET_PIN_T )
{
auto sp = static_cast<SCH_SHEET_PIN*>( item );
auto sp_name = sp->GetText();
auto subsheet = sheet;
auto subsheet = child_subgraphs[i]->m_sheet;
subsheet.push_back( sp->GetParent() );
#ifdef CONNECTIVITY_DEBUG
wxLogDebug( wxT("Propagating sheet pin %s on %s with connection %s to subsheet %s"),
sp_name, child_subgraphs[i]->m_sheet.PathHumanReadable(),
connection->Name(), subsheet.PathHumanReadable() );
#endif
for( auto candidate : m_subgraphs )
{
if( !candidate->m_dirty )
@ -1000,22 +1098,37 @@ void CONNECTION_GRAPH::buildConnectionGraph()
if( candidate->m_sheet == subsheet && candidate->m_driver )
{
auto driver = candidate->m_driver;
SCH_ITEM* hier_label = nullptr;
if( ( driver->Type() == SCH_HIERARCHICAL_LABEL_T ) &&
( static_cast<SCH_HIERLABEL*>( driver )->GetText() == sp_name ) )
for( auto d : candidate->m_drivers )
{
if( ( d->Type() == SCH_HIERARCHICAL_LABEL_T ) &&
( static_cast<SCH_HIERLABEL*>( d )->GetText() == sp_name ) )
hier_label = d;
}
if( hier_label )
{
#ifdef CONNECTIVITY_DEBUG
wxLogDebug( "Found child %s", static_cast<SCH_HIERLABEL*>( hier_label )->GetText() );
#endif
// We found a subgraph that is a subsheet child of
// our top-level subgraph, so let's mark it
candidate->m_dirty = false;
auto type = driver->Connection( subsheet )->Type();
auto type = hier_label->Connection( subsheet )->Type();
bool candidate_has_sheet_pins = false;
// Directly update subsheet net connections
for( auto c_item : candidate->m_items )
{
if( c_item->Type() == SCH_SHEET_PIN_T )
candidate_has_sheet_pins = true;
auto c = c_item->Connection( subsheet );
wxASSERT( c );
@ -1035,6 +1148,11 @@ void CONNECTION_GRAPH::buildConnectionGraph()
auto member = kv.first;
std::shared_ptr<SCH_CONNECTION> top_level_conn;
#ifdef CONNECTIVITY_DEBUG
wxLogDebug( "Found child neighbor from member %s",
member->Name() );
#endif
if( type == CONNECTION_BUS_GROUP )
{
// Bus group: match parent by name
@ -1079,6 +1197,13 @@ void CONNECTION_GRAPH::buildConnectionGraph()
for( auto neighbor : kv.second )
{
#ifdef CONNECTIVITY_DEBUG
wxLogDebug( "Propagating to neighbor driven by %s",
neighbor->m_driver->GetSelectMenuText( MILLIMETRES ) );
#endif
bool neighbor_has_sheet_pins = false;
for( auto n_item : neighbor->m_items )
{
auto c = n_item->Connection( subsheet );
@ -1086,7 +1211,31 @@ void CONNECTION_GRAPH::buildConnectionGraph()
wxASSERT( c );
c->Clone( *top_level_conn );
if( n_item->Type() == SCH_SHEET_PIN_T )
neighbor_has_sheet_pins = true;
}
if( neighbor_has_sheet_pins )
{
#ifdef CONNECTIVITY_DEBUG
wxLogDebug( "Neighbor driven by %s has subsheet pins",
neighbor->m_driver->GetSelectMenuText( MILLIMETRES ) );
#endif
child_subgraphs.push_back( neighbor );
}
}
}
// Now, check to see if the candidate also has
// sheet pin members. If so, add to the queue.
if( candidate_has_sheet_pins)
{
#ifdef CONNECTIVITY_DEBUG
wxLogDebug( "Candidate %s has subsheet pins",
candidate->m_driver->GetSelectMenuText( MILLIMETRES ) );
#endif
child_subgraphs.push_back( candidate );
}
}
}

View File

@ -86,6 +86,9 @@ public:
/// True if this subgraph contains multiple power ports to join in one net
bool m_multiple_power_ports;
/// True if the driver is "strong": a label or power object
bool m_strong_driver;
/// No-connect item in graph, if any
SCH_ITEM* m_no_connect;

View File

@ -188,6 +188,7 @@ void SCH_CONNECTION::Reset()
m_type = CONNECTION_NONE;
m_name = "<NO NET>";
m_prefix = "";
m_suffix = "";
m_driver = nullptr;
m_members.clear();
m_dirty = true;
@ -208,6 +209,8 @@ void SCH_CONNECTION::Clone( SCH_CONNECTION& aOther )
m_sheet = aOther.Sheet();
m_name = aOther.Name( true );
m_prefix = aOther.Prefix();
// Don't clone suffix, it will be rolled into the name
//m_suffix = aOther.Suffix();
m_members = aOther.Members();
m_net_code = aOther.NetCode();
m_bus_code = aOther.BusCode();
@ -242,7 +245,7 @@ bool SCH_CONNECTION::IsDriver() const
wxString SCH_CONNECTION::Name( bool aIgnoreSheet ) const
{
wxString ret = m_name;
wxString ret = m_name + m_suffix;
if( !Parent() || m_type == CONNECTION_NONE )
return ret;
@ -277,7 +280,7 @@ void SCH_CONNECTION::AppendInfoToMsgPanel( MSG_PANEL_ITEMS& aList ) const
wxString msg, group_name;
std::vector<wxString> group_members;
aList.push_back( MSG_PANEL_ITEM( _( "Connection Name" ), m_name, BROWN ) );
aList.push_back( MSG_PANEL_ITEM( _( "Connection Name" ), Name(), BROWN ) );
msg.Printf( "%d", m_net_code );
aList.push_back( MSG_PANEL_ITEM( _( "Net Code" ), msg, BROWN ) );

View File

@ -152,11 +152,21 @@ public:
return m_prefix;
}
wxString Suffix() const
{
return m_suffix;
}
void SetPrefix( wxString aPrefix )
{
m_prefix = aPrefix;
}
void SetSuffix( wxString aSuffix )
{
m_suffix = aSuffix;
}
CONNECTION_TYPE Type() const
{
return m_type;
@ -318,6 +328,8 @@ private:
///< Prefix if connection is member of a labeled bus group (or "" if not)
wxString m_prefix;
wxString m_suffix; ///< Name suffix (used only for disambiguation)
int m_net_code; // TODO(JE) remove if unused
int m_bus_code; // TODO(JE) remove if unused