Handle higher-priority connection drivers located in subsheets
Fixes: lp:1827850 * https://bugs.launchpad.net/kicad/+bug/1827850
This commit is contained in:
parent
f1a38a6d41
commit
316be464ab
|
@ -59,33 +59,13 @@ bool CONNECTION_SUBGRAPH::ResolveDrivers( bool aCreateMarkers )
|
||||||
|
|
||||||
for( auto item : m_drivers )
|
for( auto item : m_drivers )
|
||||||
{
|
{
|
||||||
int item_priority = 0;
|
PRIORITY item_priority = GetDriverPriority( item );
|
||||||
|
|
||||||
switch( item->Type() )
|
if( item_priority == PRIORITY_PIN &&
|
||||||
{
|
!static_cast<SCH_PIN*>( item )->GetParentComponent()->IsInNetlist() )
|
||||||
case SCH_SHEET_PIN_T: item_priority = 2; break;
|
|
||||||
case SCH_HIER_LABEL_T: item_priority = 3; break;
|
|
||||||
case SCH_LABEL_T: item_priority = 4; break;
|
|
||||||
case SCH_PIN_T:
|
|
||||||
{
|
|
||||||
auto sch_pin = static_cast<SCH_PIN*>( item );
|
|
||||||
|
|
||||||
if( sch_pin->IsPowerConnection() )
|
|
||||||
item_priority = 5;
|
|
||||||
else
|
|
||||||
item_priority = 1;
|
|
||||||
|
|
||||||
// Skip power flags, etc
|
|
||||||
if( item_priority == 1 && !sch_pin->GetParentComponent()->IsInNetlist() )
|
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
break;
|
if( item_priority >= PRIORITY_HIER_LABEL )
|
||||||
}
|
|
||||||
case SCH_GLOBAL_LABEL_T: item_priority = 6; break;
|
|
||||||
default: break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if( item_priority >= 3 )
|
|
||||||
strong_drivers.push_back( item );
|
strong_drivers.push_back( item );
|
||||||
|
|
||||||
if( item_priority > highest_priority )
|
if( item_priority > highest_priority )
|
||||||
|
@ -100,17 +80,17 @@ bool CONNECTION_SUBGRAPH::ResolveDrivers( bool aCreateMarkers )
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if( highest_priority >= 3 )
|
if( highest_priority >= PRIORITY_HIER_LABEL )
|
||||||
m_strong_driver = true;
|
m_strong_driver = true;
|
||||||
|
|
||||||
// Power pins are 5, global labels are 6
|
// Power pins are 5, global labels are 6
|
||||||
m_local_driver = ( highest_priority < 5 );
|
m_local_driver = ( highest_priority < PRIORITY_POWER_PIN );
|
||||||
|
|
||||||
if( !candidates.empty() )
|
if( !candidates.empty() )
|
||||||
{
|
{
|
||||||
if( candidates.size() > 1 )
|
if( candidates.size() > 1 )
|
||||||
{
|
{
|
||||||
if( highest_priority == 2 )
|
if( highest_priority == PRIORITY_SHEET_PIN )
|
||||||
{
|
{
|
||||||
// We have multiple options, and they are all hierarchical
|
// We have multiple options, and they are all hierarchical
|
||||||
// sheet pins. Let's prefer outputs over inputs.
|
// sheet pins. Let's prefer outputs over inputs.
|
||||||
|
@ -341,6 +321,32 @@ void CONNECTION_SUBGRAPH::UpdateItemConnections()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
CONNECTION_SUBGRAPH::PRIORITY CONNECTION_SUBGRAPH::GetDriverPriority( SCH_ITEM* aDriver )
|
||||||
|
{
|
||||||
|
if( !aDriver )
|
||||||
|
return PRIORITY_NONE;
|
||||||
|
|
||||||
|
switch( aDriver->Type() )
|
||||||
|
{
|
||||||
|
case SCH_SHEET_PIN_T: return PRIORITY_SHEET_PIN;
|
||||||
|
case SCH_HIER_LABEL_T: return PRIORITY_HIER_LABEL;
|
||||||
|
case SCH_LABEL_T: return PRIORITY_LOCAL_LABEL;
|
||||||
|
case SCH_GLOBAL_LABEL_T: return PRIORITY_GLOBAL;
|
||||||
|
case SCH_PIN_T:
|
||||||
|
{
|
||||||
|
auto sch_pin = static_cast<SCH_PIN*>( aDriver );
|
||||||
|
|
||||||
|
if( sch_pin->IsPowerConnection() )
|
||||||
|
return PRIORITY_POWER_PIN;
|
||||||
|
else
|
||||||
|
return PRIORITY_PIN;
|
||||||
|
}
|
||||||
|
|
||||||
|
default: return PRIORITY_NONE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
bool CONNECTION_GRAPH::m_allowRealTime = true;
|
bool CONNECTION_GRAPH::m_allowRealTime = true;
|
||||||
|
|
||||||
|
|
||||||
|
@ -1440,10 +1446,10 @@ void CONNECTION_GRAPH::assignNetCodesToBus( SCH_CONNECTION* aConnection )
|
||||||
void CONNECTION_GRAPH::propagateToNeighbors( CONNECTION_SUBGRAPH* aSubgraph )
|
void CONNECTION_GRAPH::propagateToNeighbors( CONNECTION_SUBGRAPH* aSubgraph )
|
||||||
{
|
{
|
||||||
SCH_CONNECTION* conn = aSubgraph->m_driver_connection;
|
SCH_CONNECTION* conn = aSubgraph->m_driver_connection;
|
||||||
std::vector<CONNECTION_SUBGRAPH*> children;
|
std::vector<CONNECTION_SUBGRAPH*> search_list;
|
||||||
std::vector<CONNECTION_SUBGRAPH*> visited;
|
std::unordered_set<CONNECTION_SUBGRAPH*> visited;
|
||||||
|
|
||||||
auto add_children = [&] ( CONNECTION_SUBGRAPH* aParent ) {
|
auto visit = [&] ( CONNECTION_SUBGRAPH* aParent ) {
|
||||||
for( SCH_SHEET_PIN* pin : aParent->m_hier_pins )
|
for( SCH_SHEET_PIN* pin : aParent->m_hier_pins )
|
||||||
{
|
{
|
||||||
SCH_SHEET_PATH path = aParent->m_sheet;
|
SCH_SHEET_PATH path = aParent->m_sheet;
|
||||||
|
@ -1465,7 +1471,42 @@ void CONNECTION_GRAPH::propagateToNeighbors( CONNECTION_SUBGRAPH* aSubgraph )
|
||||||
wxLogTrace( "CONN", "Found child %lu (%s)",
|
wxLogTrace( "CONN", "Found child %lu (%s)",
|
||||||
candidate->m_code, candidate->m_driver_connection->Name() );
|
candidate->m_code, candidate->m_driver_connection->Name() );
|
||||||
|
|
||||||
children.push_back( candidate );
|
search_list.push_back( candidate );
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for( SCH_HIERLABEL* label : aParent->m_hier_ports )
|
||||||
|
{
|
||||||
|
SCH_SHEET_PATH path = aParent->m_sheet;
|
||||||
|
path.pop_back();
|
||||||
|
|
||||||
|
if( !m_sheet_to_subgraphs_map.count( path ) )
|
||||||
|
continue;
|
||||||
|
|
||||||
|
for( auto candidate : m_sheet_to_subgraphs_map.at( path ) )
|
||||||
|
{
|
||||||
|
if( !candidate->m_strong_driver ||
|
||||||
|
candidate->m_hier_pins.empty() ||
|
||||||
|
visited.count( candidate ) )
|
||||||
|
continue;
|
||||||
|
|
||||||
|
for( SCH_SHEET_PIN* pin : candidate->m_hier_pins )
|
||||||
|
{
|
||||||
|
SCH_SHEET_PATH pin_path = path;
|
||||||
|
pin_path.push_back( pin->GetParent() );
|
||||||
|
|
||||||
|
if( pin_path != aParent->m_sheet )
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if( label->GetShownText() == pin->GetShownText() )
|
||||||
|
{
|
||||||
|
wxLogTrace( "CONN", "Found additional parent %lu (%s)",
|
||||||
|
candidate->m_code, candidate->m_driver_connection->Name() );
|
||||||
|
|
||||||
|
search_list.push_back( candidate );
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1530,7 +1571,7 @@ void CONNECTION_GRAPH::propagateToNeighbors( CONNECTION_SUBGRAPH* aSubgraph )
|
||||||
if( !aSubgraph->m_hier_ports.empty() )
|
if( !aSubgraph->m_hier_ports.empty() )
|
||||||
return;
|
return;
|
||||||
|
|
||||||
visited.push_back( aSubgraph );
|
visited.insert( aSubgraph );
|
||||||
|
|
||||||
// If we are a bus, we must propagate to local neighbors and then the hierarchy
|
// If we are a bus, we must propagate to local neighbors and then the hierarchy
|
||||||
if( conn->IsBus() )
|
if( conn->IsBus() )
|
||||||
|
@ -1539,22 +1580,51 @@ void CONNECTION_GRAPH::propagateToNeighbors( CONNECTION_SUBGRAPH* aSubgraph )
|
||||||
wxLogTrace( "CONN", "Propagating %lu (%s) to subsheets",
|
wxLogTrace( "CONN", "Propagating %lu (%s) to subsheets",
|
||||||
aSubgraph->m_code, aSubgraph->m_driver_connection->Name() );
|
aSubgraph->m_code, aSubgraph->m_driver_connection->Name() );
|
||||||
|
|
||||||
add_children( aSubgraph );
|
visit( aSubgraph );
|
||||||
|
|
||||||
for( unsigned i = 0; i < children.size(); i++ )
|
for( unsigned i = 0; i < search_list.size(); i++ )
|
||||||
{
|
{
|
||||||
auto child = children[i];
|
auto child = search_list[i];
|
||||||
|
|
||||||
if( !child->m_dirty )
|
visited.insert( child );
|
||||||
|
|
||||||
|
visit( child );
|
||||||
|
|
||||||
|
child->m_dirty = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Now, find the best driver for this chain of subgraphs
|
||||||
|
CONNECTION_SUBGRAPH* driver = aSubgraph;
|
||||||
|
CONNECTION_SUBGRAPH::PRIORITY highest =
|
||||||
|
CONNECTION_SUBGRAPH::GetDriverPriority( aSubgraph->m_driver );
|
||||||
|
|
||||||
|
// Check if a subsheet has a higher-priority connection to the same net
|
||||||
|
if( highest < CONNECTION_SUBGRAPH::PRIORITY_POWER_PIN )
|
||||||
{
|
{
|
||||||
wxLogTrace( "CONN", "Child %lu (%s) is not dirty, backpropagating it",
|
for( CONNECTION_SUBGRAPH* subgraph : visited )
|
||||||
child->m_code, child->m_driver_connection->Name() );
|
{
|
||||||
|
CONNECTION_SUBGRAPH::PRIORITY priority =
|
||||||
|
CONNECTION_SUBGRAPH::GetDriverPriority( subgraph->m_driver );
|
||||||
|
|
||||||
|
if( priority >= CONNECTION_SUBGRAPH::PRIORITY_POWER_PIN )
|
||||||
|
driver = subgraph;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if( driver != aSubgraph )
|
||||||
|
{
|
||||||
|
wxLogTrace( "CONN", "%lu (%s) overridden by new driver %lu (%s)",
|
||||||
|
aSubgraph->m_code, aSubgraph->m_driver_connection->Name(),
|
||||||
|
driver->m_code, driver->m_driver_connection->Name() );
|
||||||
|
}
|
||||||
|
|
||||||
|
conn = driver->m_driver_connection;
|
||||||
|
|
||||||
for( CONNECTION_SUBGRAPH* subgraph : visited )
|
for( CONNECTION_SUBGRAPH* subgraph : visited )
|
||||||
{
|
{
|
||||||
wxString old_name = subgraph->m_driver_connection->Name();
|
wxString old_name = subgraph->m_driver_connection->Name();
|
||||||
|
|
||||||
subgraph->m_driver_connection->Clone( *child->m_driver_connection );
|
subgraph->m_driver_connection->Clone( *conn );
|
||||||
subgraph->UpdateItemConnections();
|
subgraph->UpdateItemConnections();
|
||||||
|
|
||||||
recacheSubgraphName( subgraph, old_name );
|
recacheSubgraphName( subgraph, old_name );
|
||||||
|
@ -1563,28 +1633,6 @@ void CONNECTION_GRAPH::propagateToNeighbors( CONNECTION_SUBGRAPH* aSubgraph )
|
||||||
propagate_bus_neighbors( subgraph );
|
propagate_bus_neighbors( subgraph );
|
||||||
}
|
}
|
||||||
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
visited.push_back( child );
|
|
||||||
|
|
||||||
// Check for grandchildren
|
|
||||||
if( !child->m_hier_pins.empty() )
|
|
||||||
add_children( child );
|
|
||||||
|
|
||||||
wxString old_name = child->m_driver_connection->Name();
|
|
||||||
|
|
||||||
child->m_driver_connection->Clone( *conn );
|
|
||||||
child->UpdateItemConnections();
|
|
||||||
|
|
||||||
recacheSubgraphName( child, old_name );
|
|
||||||
|
|
||||||
child->m_dirty = false;
|
|
||||||
|
|
||||||
if( conn->IsBus() )
|
|
||||||
propagate_bus_neighbors( child );
|
|
||||||
}
|
|
||||||
|
|
||||||
aSubgraph->m_dirty = false;
|
aSubgraph->m_dirty = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -58,6 +58,17 @@ class SCH_SHEET_PIN;
|
||||||
class CONNECTION_SUBGRAPH
|
class CONNECTION_SUBGRAPH
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
enum PRIORITY {
|
||||||
|
PRIORITY_NONE = 0,
|
||||||
|
PRIORITY_PIN,
|
||||||
|
PRIORITY_SHEET_PIN,
|
||||||
|
PRIORITY_HIER_LABEL,
|
||||||
|
PRIORITY_LOCAL_LABEL,
|
||||||
|
PRIORITY_POWER_PIN,
|
||||||
|
PRIORITY_GLOBAL
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
CONNECTION_SUBGRAPH( SCH_EDIT_FRAME* aFrame ) :
|
CONNECTION_SUBGRAPH( SCH_EDIT_FRAME* aFrame ) :
|
||||||
m_dirty( false ), m_absorbed( false ), m_code( -1 ), m_multiple_drivers( false ),
|
m_dirty( false ), m_absorbed( false ), m_code( -1 ), m_multiple_drivers( false ),
|
||||||
m_strong_driver( false ), m_no_connect( nullptr ), m_bus_entry( nullptr ),
|
m_strong_driver( false ), m_no_connect( nullptr ), m_bus_entry( nullptr ),
|
||||||
|
@ -94,6 +105,22 @@ public:
|
||||||
/// Updates all items to match the driver connection
|
/// Updates all items to match the driver connection
|
||||||
void UpdateItemConnections();
|
void UpdateItemConnections();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the priority (higher is more important) of a candidate driver
|
||||||
|
*
|
||||||
|
* 0: Invalid driver
|
||||||
|
* 1: Component pin
|
||||||
|
* 2: Hierarchical sheet pin
|
||||||
|
* 3: Hierarchical label
|
||||||
|
* 4: Local label
|
||||||
|
* 5: Power pin
|
||||||
|
* 6: Global label
|
||||||
|
*
|
||||||
|
* @param aDriver is the item to inspect
|
||||||
|
* @return a PRIORITY
|
||||||
|
*/
|
||||||
|
static PRIORITY GetDriverPriority( SCH_ITEM* aDriver );
|
||||||
|
|
||||||
bool m_dirty;
|
bool m_dirty;
|
||||||
|
|
||||||
/// True if this subgraph has been absorbed into another. No pointers here are safe if so!
|
/// True if this subgraph has been absorbed into another. No pointers here are safe if so!
|
||||||
|
|
Loading…
Reference in New Issue