Propagate nets within non-conflicting clusters immediately.

Fixes https://gitlab.com/kicad/code/kicad/issues/13601
This commit is contained in:
Jeff Young 2023-01-23 16:23:43 +00:00
parent ece775c53c
commit 509b39e9e4
8 changed files with 49 additions and 96 deletions

View File

@ -2,7 +2,7 @@
* This program source code file is part of KiCad, a free EDA CAD application.
*
* Copyright (C) 2016 CERN
* Copyright (C) 2020-2022 KiCad Developers, see AUTHORS.txt for contributors.
* Copyright (C) 2020-2023 KiCad Developers, see AUTHORS.txt for contributors.
* @author Tomasz Wlostowski <tomasz.wlostowski@cern.ch>
*
* This program is free software; you can redistribute it and/or
@ -42,14 +42,12 @@ using namespace std::placeholders;
BOARD_COMMIT::BOARD_COMMIT( TOOL_MANAGER* aToolMgr ) :
m_toolMgr( aToolMgr ),
m_isFootprintEditor( false ),
m_isBoardEditor( false ),
m_resolveNetConflicts( false )
m_isBoardEditor( false )
{
}
BOARD_COMMIT::BOARD_COMMIT( PCB_TOOL_BASE* aTool ) :
m_resolveNetConflicts( false )
BOARD_COMMIT::BOARD_COMMIT( PCB_TOOL_BASE* aTool )
{
m_toolMgr = aTool->GetManager();
m_isFootprintEditor = aTool->IsFootprintEditor();
@ -57,8 +55,7 @@ BOARD_COMMIT::BOARD_COMMIT( PCB_TOOL_BASE* aTool ) :
}
BOARD_COMMIT::BOARD_COMMIT( EDA_DRAW_FRAME* aFrame ) :
m_resolveNetConflicts( false )
BOARD_COMMIT::BOARD_COMMIT( EDA_DRAW_FRAME* aFrame )
{
m_toolMgr = aFrame->GetToolManager();
m_isFootprintEditor = aFrame->IsType( FRAME_FOOTPRINT_EDITOR );
@ -528,9 +525,6 @@ void BOARD_COMMIT::Push( const wxString& aMessage, int aCommitFlags )
}
else
{
if( m_resolveNetConflicts )
connectivity->PropagateNets( this, PROPAGATE_MODE::RESOLVE_CONFLICTS );
connectivity->RecalculateRatsnest( this );
board->UpdateRatsnestExclusions();
connectivity->ClearLocalRatsnest();

View File

@ -2,7 +2,7 @@
* This program source code file is part of KiCad, a free EDA CAD application.
*
* Copyright (C) 2016 CERN
* Copyright (C) 2016-2022 KiCad Developers, see AUTHORS.txt for contributors.
* Copyright (C) 2016-2023 KiCad Developers, see AUTHORS.txt for contributors.
* @author Tomasz Wlostowski <tomasz.wlostowski@cern.ch>
*
* This program is free software; you can redistribute it and/or
@ -62,16 +62,6 @@ public:
COMMIT& Stage( 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:
EDA_ITEM* parentObject( EDA_ITEM* aItem ) const override;
@ -83,7 +73,6 @@ private:
TOOL_MANAGER* m_toolMgr;
bool m_isFootprintEditor;
bool m_isBoardEditor;
bool m_resolveNetConflicts;
};
#endif

View File

@ -2,7 +2,7 @@
* This program source code file is part of KICAD, a free EDA CAD application.
*
* Copyright (C) 2016-2018 CERN
* Copyright (C) 2020-2022 KiCad Developers, see AUTHORS.txt for contributors.
* Copyright (C) 2020-2023 KiCad Developers, see AUTHORS.txt for contributors.
*
* @author Tomasz Wlostowski <tomasz.wlostowski@cern.ch>
*
@ -551,42 +551,21 @@ void CN_CONNECTIVITY_ALGO::LocalBuild( const std::vector<BOARD_ITEM*>& aItems )
}
void CN_CONNECTIVITY_ALGO::propagateConnections( BOARD_COMMIT* aCommit, PROPAGATE_MODE aMode )
void CN_CONNECTIVITY_ALGO::propagateConnections( BOARD_COMMIT* aCommit )
{
bool resolveConflicts = ( aMode != PROPAGATE_MODE::SKIP_CONFLICTS );
wxLogTrace( wxT( "CN" ), wxT( "propagateConnections: resolve conflicts? %d" ),
resolveConflicts );
for( const std::shared_ptr<CN_CLUSTER>& cluster : m_connClusters )
{
if( cluster->IsOrphaned() )
if( cluster->IsConflicting() )
{
wxLogTrace( wxT( "CN" ), wxT( "Skipping orphaned cluster %p [net: %s]" ),
cluster.get(),
(const char*) cluster->OriginNetName().c_str() );
// Conflicting pads in cluster: we don't know the user's intent so best to do
// nothing.
wxLogTrace( wxT( "CN" ), wxT( "Conflicting pads in cluster %p; skipping propagation" ),
cluster.get() );
}
else if( cluster->HasValidNet() )
{
if( cluster->IsConflicting() )
{
if( resolveConflicts )
{
wxLogTrace( wxT( "CN" ),
wxT( "Conflicting nets in cluster %p; chose %d (%s)" ),
cluster.get(),
cluster->OriginNet(),
cluster->OriginNetName() );
}
else
{
wxLogTrace( wxT( "CN" ),
wxT( "Conflicting nets in cluster %p; skipping update" ),
cluster.get() );
}
}
// normal cluster: just propagate from the pads
// Propagate from the origin (will be a pad if there are any, or another item if
// there are no pads).
int n_changed = 0;
for( CN_ITEM* item : *cluster )
@ -594,49 +573,43 @@ void CN_CONNECTIVITY_ALGO::propagateConnections( BOARD_COMMIT* aCommit, PROPAGAT
if( item->Valid() && item->CanChangeNet()
&& item->Parent()->GetNetCode() != cluster->OriginNet() )
{
bool isFreePad = item->Parent()->Type() == PCB_PAD_T
&& static_cast<PAD*>( item->Parent() )->IsFreePad();
MarkNetAsDirty( item->Parent()->GetNetCode() );
MarkNetAsDirty( cluster->OriginNet() );
if( !cluster->IsConflicting() || resolveConflicts || isFreePad )
{
MarkNetAsDirty( item->Parent()->GetNetCode() );
MarkNetAsDirty( cluster->OriginNet() );
if( aCommit )
aCommit->Modify( item->Parent() );
if( aCommit )
aCommit->Modify( item->Parent() );
item->Parent()->SetNetCode( cluster->OriginNet() );
n_changed++;
}
item->Parent()->SetNetCode( cluster->OriginNet() );
n_changed++;
}
}
if( n_changed )
{
wxLogTrace( wxT( "CN" ), wxT( "Cluster %p : net : %d %s" ),
wxLogTrace( wxT( "CN" ), wxT( "Cluster %p: net: %d %s" ),
cluster.get(),
cluster->OriginNet(),
(const char*) cluster->OriginNetName().c_str() );
}
else
{
wxLogTrace( wxT( "CN" ), wxT( "Cluster %p : nothing to propagate" ),
wxLogTrace( wxT( "CN" ), wxT( "Cluster %p: no changeable items to propagate to" ),
cluster.get() );
}
}
else
{
wxLogTrace( wxT( "CN" ), wxT( "Cluster %p : connected to unused net" ),
wxLogTrace( wxT( "CN" ), wxT( "Cluster %p: connected to unused net" ),
cluster.get() );
}
}
}
void CN_CONNECTIVITY_ALGO::PropagateNets( BOARD_COMMIT* aCommit, PROPAGATE_MODE aMode )
void CN_CONNECTIVITY_ALGO::PropagateNets( BOARD_COMMIT* aCommit )
{
m_connClusters = SearchClusters( CSM_PROPAGATE );
propagateConnections( aCommit, aMode );
propagateConnections( aCommit );
}

View File

@ -2,7 +2,7 @@
* This program source code file is part of KICAD, a free EDA CAD application.
*
* Copyright (C) 2013-2017 CERN
* Copyright (C) 2019-2022 KiCad Developers, see AUTHORS.txt for contributors.
* Copyright (C) 2019-2023 KiCad Developers, see AUTHORS.txt for contributors.
*
* @author Maciej Suminski <maciej.suminski@cern.ch>
* @author Tomasz Wlostowski <tomasz.wlostowski@cern.ch>
@ -213,10 +213,8 @@ public:
/**
* Propagate nets from pads to other items in clusters.
* @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,
PROPAGATE_MODE aMode = PROPAGATE_MODE::SKIP_CONFLICTS );
void PropagateNets( BOARD_COMMIT* aCommit = nullptr );
void FindIsolatedCopperIslands( ZONE* aZone, PCB_LAYER_ID aLayer, std::vector<int>& aIslands );
@ -261,8 +259,7 @@ public:
private:
void searchConnections();
void propagateConnections( BOARD_COMMIT* aCommit = nullptr,
PROPAGATE_MODE aMode = PROPAGATE_MODE::SKIP_CONFLICTS );
void propagateConnections( BOARD_COMMIT* aCommit = nullptr );
template <class Container, class BItem>
void add( Container& c, BItem brditem )

View File

@ -394,9 +394,9 @@ void CONNECTIVITY_DATA::HideLocalRatsnest()
}
void CONNECTIVITY_DATA::PropagateNets( BOARD_COMMIT* aCommit, PROPAGATE_MODE aMode )
void CONNECTIVITY_DATA::PropagateNets( BOARD_COMMIT* aCommit )
{
m_connAlgo->PropagateNets( aCommit, aMode );
m_connAlgo->PropagateNets( aCommit );
}

View File

@ -2,7 +2,7 @@
* This program source code file is part of KICAD, a free EDA CAD application.
*
* Copyright (C) 2013-2017 CERN
* Copyright (C) 2018-2022 KiCad Developers, see AUTHORS.txt for contributors.
* Copyright (C) 2018-2023 KiCad Developers, see AUTHORS.txt for contributors.
* @author Maciej Suminski <maciej.suminski@cern.ch>
* @author Tomasz Wlostowski <tomasz.wlostowski@cern.ch>
*
@ -173,8 +173,7 @@ public:
* @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( BOARD_COMMIT* aCommit = nullptr,
PROPAGATE_MODE aMode = PROPAGATE_MODE::SKIP_CONFLICTS );
void PropagateNets( BOARD_COMMIT* aCommit = nullptr );
/**
* Function FindIsolatedCopperIslands()

View File

@ -414,29 +414,31 @@ void CN_CLUSTER::Add( CN_ITEM* item )
return;
if( m_originNet <= 0 )
{
m_originNet = netCode;
m_netRanks[m_originNet] = 0;
}
if( item->Parent()->Type() == PCB_PAD_T && !static_cast<PAD*>( item->Parent() )->IsFreePad() )
{
if( m_netRanks.count( netCode ) )
{
m_netRanks[netCode]++;
int rank;
auto it = m_netRanks.find( netCode );
if( m_netRanks.count( m_originNet ) && m_netRanks[netCode] > m_netRanks[m_originNet] )
{
m_originPad = item;
m_originNet = netCode;
}
if( it == m_netRanks.end() )
{
m_netRanks[netCode] = 1;
rank = 1;
}
else
{
m_netRanks[netCode] = 1;
it->second++;
rank = it->second;
}
if( !m_originPad )
{
m_originPad = item;
m_originNet = netCode;
}
if( !m_originPad || rank > m_netRanks[m_originNet] )
{
m_originPad = item;
m_originNet = netCode;
}
if( m_originPad && item->Net() != m_originNet )

View File

@ -6,7 +6,7 @@
* Copyright (C) 2012 SoftPLC Corporation, Dick Hollenbeck <dick@softplc.com>
* Copyright (C) 2011 Wayne Stambaugh <stambaughw@gmail.com>
*
* Copyright (C) 1992-2022 KiCad Developers, see AUTHORS.txt for contributors.
* Copyright (C) 1992-2023 KiCad Developers, see AUTHORS.txt for contributors.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@ -1077,7 +1077,6 @@ bool BOARD_NETLIST_UPDATER::UpdateNetlist( NETLIST& aNetlist )
}
m_board->GetNetInfo().RemoveUnusedNets();
m_commit.SetResolveNetConflicts();
// When new footprints are added, the automatic zone refill is disabled because:
// * it creates crashes when calculating dynamic ratsnests if auto refill is enabled.