Fix connectivity to only resolve conflicts on netlist load

Fixes https://gitlab.com/kicad/code/kicad/-/issues/8007
This commit is contained in:
Jon Evans 2021-03-23 17:42:56 -04:00
parent a94ce75c02
commit f57dcf2a34
7 changed files with 54 additions and 14 deletions

View File

@ -37,14 +37,16 @@
using namespace std::placeholders; using namespace std::placeholders;
BOARD_COMMIT::BOARD_COMMIT( PCB_TOOL_BASE* aTool ) BOARD_COMMIT::BOARD_COMMIT( PCB_TOOL_BASE* aTool ) :
m_resolveNetConflicts( false )
{ {
m_toolMgr = aTool->GetManager(); m_toolMgr = aTool->GetManager();
m_isFootprintEditor = aTool->IsFootprintEditor(); m_isFootprintEditor = aTool->IsFootprintEditor();
} }
BOARD_COMMIT::BOARD_COMMIT( EDA_DRAW_FRAME* aFrame ) BOARD_COMMIT::BOARD_COMMIT( EDA_DRAW_FRAME* aFrame ) :
m_resolveNetConflicts( false )
{ {
m_toolMgr = aFrame->GetToolManager(); m_toolMgr = aFrame->GetToolManager();
m_isFootprintEditor = aFrame->IsType( FRAME_FOOTPRINT_EDITOR ); m_isFootprintEditor = aFrame->IsType( FRAME_FOOTPRINT_EDITOR );
@ -350,6 +352,9 @@ void BOARD_COMMIT::Push( const wxString& aMessage, bool aCreateUndoEntry, bool a
{ {
size_t num_changes = m_changes.size(); size_t num_changes = m_changes.size();
if( m_resolveNetConflicts )
connectivity->PropagateNets( this, PROPAGATE_MODE::RESOLVE_CONFLICTS );
connectivity->RecalculateRatsnest( this ); connectivity->RecalculateRatsnest( this );
connectivity->ClearDynamicRatsnest(); connectivity->ClearDynamicRatsnest();
frame->GetCanvas()->RedrawRatsnest(); frame->GetCanvas()->RedrawRatsnest();

View File

@ -51,12 +51,23 @@ public:
COMMIT& Stage( COMMIT& Stage(
const PICKED_ITEMS_LIST& aItems, UNDO_REDO aModFlag = UNDO_REDO::UNSPECIFIED ) override; const PICKED_ITEMS_LIST& aItems, UNDO_REDO aModFlag = UNDO_REDO::UNSPECIFIED ) override;
/**
* Sets a flag that will cause Push() to resolve net conflicts on track/via clusters instead
* of the default behavior which is to skip updating track/via clusters that have conflicts.
* This is used in the netlist updater to update any clusters that were changed due to pad nets
* changing, but should not be used for other changes as you typically don't want to change
* track/via nets due to temporary conflicts created by board editing operations.
* @param aResolve is true if this commit should resolve conflicting track/via net assignments
*/
void SetResolveNetConflicts( bool aResolve = true ) { m_resolveNetConflicts = aResolve; }
private: private:
virtual EDA_ITEM* parentObject( EDA_ITEM* aItem ) const override; virtual EDA_ITEM* parentObject( EDA_ITEM* aItem ) const override;
private: private:
TOOL_MANAGER* m_toolMgr; TOOL_MANAGER* m_toolMgr;
bool m_isFootprintEditor; bool m_isFootprintEditor;
bool m_resolveNetConflicts;
}; };
#endif #endif

View File

@ -477,11 +477,19 @@ void CN_CONNECTIVITY_ALGO::Build( const std::vector<BOARD_ITEM*>& aItems )
} }
void CN_CONNECTIVITY_ALGO::propagateConnections( BOARD_COMMIT* aCommit ) void CN_CONNECTIVITY_ALGO::propagateConnections( BOARD_COMMIT* aCommit, PROPAGATE_MODE aMode )
{ {
bool skipConflicts = ( aMode == PROPAGATE_MODE::SKIP_CONFLICTS );
wxLogTrace( "CN", "propagateConnections: propagate skip conflicts? %d", skipConflicts );
for( const auto& cluster : m_connClusters ) for( const auto& cluster : m_connClusters )
{ {
if( cluster->IsOrphaned() ) if( skipConflicts && cluster->IsConflicting() )
{
wxLogTrace( "CN", "Conflicting nets in cluster %p; skipping update", cluster.get() );
}
else if( cluster->IsOrphaned() )
{ {
wxLogTrace( "CN", "Skipping orphaned cluster %p [net: %s]", cluster.get(), wxLogTrace( "CN", "Skipping orphaned cluster %p [net: %s]", cluster.get(),
(const char*) cluster->OriginNetName().c_str() ); (const char*) cluster->OriginNetName().c_str() );
@ -531,10 +539,10 @@ void CN_CONNECTIVITY_ALGO::propagateConnections( BOARD_COMMIT* aCommit )
} }
void CN_CONNECTIVITY_ALGO::PropagateNets( BOARD_COMMIT* aCommit ) void CN_CONNECTIVITY_ALGO::PropagateNets( BOARD_COMMIT* aCommit, PROPAGATE_MODE aMode )
{ {
m_connClusters = SearchClusters( CSM_PROPAGATE ); m_connClusters = SearchClusters( CSM_PROPAGATE );
propagateConnections( aCommit ); propagateConnections( aCommit, aMode );
} }

View File

@ -168,7 +168,8 @@ private:
void searchConnections(); void searchConnections();
void propagateConnections( BOARD_COMMIT* aCommit = nullptr ); void propagateConnections( BOARD_COMMIT* aCommit = nullptr,
PROPAGATE_MODE aMode = PROPAGATE_MODE::SKIP_CONFLICTS );
template <class Container, class BItem> template <class Container, class BItem>
void add( Container& c, BItem brditem ) void add( Container& c, BItem brditem )
@ -239,8 +240,10 @@ public:
/** /**
* Propagates nets from pads to other items in clusters * Propagates nets from pads to other items in clusters
* @param aCommit is used to store undo information for items modified by the call * @param aCommit is used to store undo information for items modified by the call
* @param aMode controls how clusters with conflicting nets are resolved
*/ */
void PropagateNets( BOARD_COMMIT* aCommit = nullptr ); void PropagateNets( BOARD_COMMIT* aCommit = nullptr,
PROPAGATE_MODE aMode = PROPAGATE_MODE::SKIP_CONFLICTS );
void FindIsolatedCopperIslands( ZONE* aZone, PCB_LAYER_ID aLayer, std::vector<int>& aIslands ); void FindIsolatedCopperIslands( ZONE* aZone, PCB_LAYER_ID aLayer, std::vector<int>& aIslands );

View File

@ -339,11 +339,12 @@ void CONNECTIVITY_DATA::HideDynamicRatsnest()
} }
void CONNECTIVITY_DATA::PropagateNets() void CONNECTIVITY_DATA::PropagateNets( BOARD_COMMIT* aCommit, PROPAGATE_MODE aMode )
{ {
m_connAlgo->PropagateNets(); m_connAlgo->PropagateNets( aCommit, aMode );
} }
bool CONNECTIVITY_DATA::IsConnectedOnLayer( const BOARD_CONNECTED_ITEM *aItem, int aLayer, bool CONNECTIVITY_DATA::IsConnectedOnLayer( const BOARD_CONNECTED_ITEM *aItem, int aLayer,
std::vector<KICAD_T> aTypes ) const std::vector<KICAD_T> aTypes ) const
{ {

View File

@ -82,6 +82,15 @@ struct RN_DYNAMIC_LINE
VECTOR2I a, b; VECTOR2I a, b;
}; };
/**
* Controls how nets are propagated through clusters
*/
enum class PROPAGATE_MODE
{
SKIP_CONFLICTS, /// Clusters with conflicting drivers are not updated (default)
RESOLVE_CONFLICTS /// Clusters with conflicting drivers are updated to the most popular net
};
// a wrapper class encompassing the connectivity computation algorithm and the // a wrapper class encompassing the connectivity computation algorithm and the
class CONNECTIVITY_DATA class CONNECTIVITY_DATA
{ {
@ -155,10 +164,12 @@ public:
RN_NET* GetRatsnestForNet( int aNet ); RN_NET* GetRatsnestForNet( int aNet );
/** /**
* Function PropagateNets()
* Propagates the net codes from the source pads to the tracks/vias. * Propagates the net codes from the source pads to the tracks/vias.
* @param aCommit is used to save the undo state of items modified by this call
* @param aMode controls how conflicts between pads are resolved
*/ */
void PropagateNets(); void PropagateNets( BOARD_COMMIT* aCommit = nullptr,
PROPAGATE_MODE aMode = PROPAGATE_MODE::SKIP_CONFLICTS );
bool CheckConnectivity( std::vector<CN_DISJOINT_NET_ENTRY>& aReport ); bool CheckConnectivity( std::vector<CN_DISJOINT_NET_ENTRY>& aReport );
@ -202,10 +213,10 @@ public:
* @param aItem is the reference item to find other connected items. * @param aItem is the reference item to find other connected items.
* @param aAnchor is the position to find connected items on. * @param aAnchor is the position to find connected items on.
* @param aTypes allows one to filter by item types. * @param aTypes allows one to filter by item types.
* @return * @return
*/ */
const std::vector<BOARD_CONNECTED_ITEM*> GetConnectedItemsAtAnchor( const BOARD_CONNECTED_ITEM* aItem, const std::vector<BOARD_CONNECTED_ITEM*> GetConnectedItemsAtAnchor( const BOARD_CONNECTED_ITEM* aItem,
const VECTOR2I& aAnchor, const VECTOR2I& aAnchor,
const KICAD_T aTypes[] ) const; const KICAD_T aTypes[] ) const;
void GetUnconnectedEdges( std::vector<CN_EDGE>& aEdges ) const; void GetUnconnectedEdges( std::vector<CN_EDGE>& aEdges ) const;

View File

@ -1095,6 +1095,7 @@ bool BOARD_NETLIST_UPDATER::UpdateNetlist( NETLIST& aNetlist )
} }
m_board->GetNetInfo().RemoveUnusedNets(); m_board->GetNetInfo().RemoveUnusedNets();
m_commit.SetResolveNetConflicts();
m_commit.Push( _( "Update netlist" ) ); m_commit.Push( _( "Update netlist" ) );
m_board->SynchronizeNetsAndNetClasses(); m_board->SynchronizeNetsAndNetClasses();