Defensive code against missing nets.

Also adds net re-parenting code to Repair Board.

Fixes https://gitlab.com/kicad/code/kicad/issues/5935
This commit is contained in:
Jeff Young 2020-10-10 16:10:04 +01:00
parent 527d5f1290
commit fdeb340d21
5 changed files with 67 additions and 41 deletions

View File

@ -837,9 +837,9 @@ static int matchDpSuffix( const wxString& aNetName, wxString& aComplementNet,
} }
int DRC_ENGINE::IsNetADiffPair( BOARD* aBoard, int aNet, int& aNetP, int& aNetN ) int DRC_ENGINE::IsNetADiffPair( BOARD* aBoard, NETINFO_ITEM* aNet, int& aNetP, int& aNetN )
{ {
wxString refName = aBoard->FindNet( aNet )->GetNetname(); wxString refName = aNet->GetNetname();
wxString dummy, coupledNetName; wxString dummy, coupledNetName;
if( int polarity = matchDpSuffix( refName, coupledNetName, dummy ) ) if( int polarity = matchDpSuffix( refName, coupledNetName, dummy ) )
@ -851,13 +851,13 @@ int DRC_ENGINE::IsNetADiffPair( BOARD* aBoard, int aNet, int& aNetP, int& aNetN
if( polarity > 0 ) if( polarity > 0 )
{ {
aNetP = aNet; aNetP = aNet->GetNet();
aNetN = net->GetNet(); aNetN = net->GetNet();
} }
else else
{ {
aNetP = net->GetNet(); aNetP = net->GetNet();
aNetN = aNet; aNetN = aNet->GetNet();
} }
return true; return true;

View File

@ -40,6 +40,7 @@ class ZONE_CONTAINER;
class MARKER_PCB; class MARKER_PCB;
class NETCLASS; class NETCLASS;
class NETLIST; class NETLIST;
class NETINFO_ITEM;
class PROGRESS_REPORTER; class PROGRESS_REPORTER;
class REPORTER; class REPORTER;
@ -177,7 +178,7 @@ public:
DRC_TEST_PROVIDER* GetTestProvider( const wxString& name ) const; DRC_TEST_PROVIDER* GetTestProvider( const wxString& name ) const;
static int IsNetADiffPair( BOARD* aBoard, int aNet, int& aNetP, int& aNetN ); static int IsNetADiffPair( BOARD* aBoard, NETINFO_ITEM* aNet, int& aNetP, int& aNetN );
private: private:
void addRule( DRC_RULE* rule ) void addRule( DRC_RULE* rule )

View File

@ -278,34 +278,36 @@ bool test::DRC_TEST_PROVIDER_DIFF_PAIR_COUPLING::Run()
[&]( BOARD_ITEM *item ) -> bool [&]( BOARD_ITEM *item ) -> bool
{ {
DIFF_PAIR_KEY key; DIFF_PAIR_KEY key;
auto citem = static_cast<BOARD_CONNECTED_ITEM*>( item ); BOARD_CONNECTED_ITEM* citem = static_cast<BOARD_CONNECTED_ITEM*>( item );
int refNet = citem->GetNetCode(); NETINFO_ITEM* refNet = citem->GetNet();
if( !DRC_ENGINE::IsNetADiffPair( m_board, refNet, key.netP, key.netN ) ) // not our business if( refNet && DRC_ENGINE::IsNetADiffPair( m_board, refNet, key.netP, key.netN ) )
return true;
drc_dbg(10, "eval dp %p\n", item );
const DRC_CONSTRAINT_TYPE_T constraintsToCheck[] = {
DRC_CONSTRAINT_TYPE_DIFF_PAIR_GAP,
DRC_CONSTRAINT_TYPE_DIFF_PAIR_MAX_UNCOUPLED
};
for( int i = 0; i < 2; i++ )
{ {
auto constraint = m_drcEngine->EvalRulesForItems( constraintsToCheck[i], item, nullptr, item->GetLayer() ); drc_dbg( 10, "eval dp %p\n", item );
if( constraint.IsNull() ) const DRC_CONSTRAINT_TYPE_T constraintsToCheck[] = {
continue; DRC_CONSTRAINT_TYPE_DIFF_PAIR_GAP,
DRC_CONSTRAINT_TYPE_DIFF_PAIR_MAX_UNCOUPLED
};
drc_dbg(10, "cns %d item %p\n", constraintsToCheck[i], item ); for( int i = 0; i < 2; i++ )
{
auto constraint = m_drcEngine->EvalRulesForItems( constraintsToCheck[i],
item, nullptr,
item->GetLayer() );
key.parentRule = constraint.GetParentRule(); if( constraint.IsNull() )
continue;
if( refNet == key.netN ) drc_dbg( 10, "cns %d item %p\n", constraintsToCheck[i], item );
dpRuleMatches[key].itemsN.insert( citem );
else key.parentRule = constraint.GetParentRule();
dpRuleMatches[key].itemsP.insert( citem );
if( refNet->GetNet() == key.netN )
dpRuleMatches[key].itemsN.insert( citem );
else
dpRuleMatches[key].itemsP.insert( citem );
}
} }
return true; return true;

View File

@ -335,12 +335,12 @@ static void isDiffPair( LIBEVAL::CONTEXT* aCtx, void* self )
result->Set( 0.0 ); result->Set( 0.0 );
aCtx->Push( result ); aCtx->Push( result );
if( item->IsConnected() ) if( item && item->IsConnected() )
{ {
int net = static_cast<BOARD_CONNECTED_ITEM*>( item )->GetNetCode(); NETINFO_ITEM* netinfo = static_cast<BOARD_CONNECTED_ITEM*>( item )->GetNet();
int net_p, net_n; int dummy_p, dummy_n;
if( DRC_ENGINE::IsNetADiffPair( item->GetBoard(), net, net_p, net_n ) ) if( netinfo && DRC_ENGINE::IsNetADiffPair( item->GetBoard(), netinfo, dummy_p, dummy_n ) )
result->Set( 1.0 ); result->Set( 1.0 );
} }
} }

View File

@ -374,22 +374,39 @@ int PCB_EDITOR_CONTROL::RepairBoard( const TOOL_EVENT& aEvent )
wxString details; wxString details;
/******************************* /*******************************
* Repair duplicate IDs * Repair duplicate IDs and missing nets
*/ */
std::set<KIID> ids; std::set<KIID> ids;
int duplicates = 0; int duplicates = 0;
auto processItem = [&]( EDA_ITEM* aItem ) auto processItem =
{ [&]( EDA_ITEM* aItem )
if( ids.count( aItem->m_Uuid ) ) {
{ if( ids.count( aItem->m_Uuid ) )
duplicates++; {
const_cast<KIID&>( aItem->m_Uuid ) = KIID(); duplicates++;
} const_cast<KIID&>( aItem->m_Uuid ) = KIID();
}
ids.insert( aItem->m_Uuid ); ids.insert( aItem->m_Uuid );
};
BOARD_CONNECTED_ITEM* cItem = dynamic_cast<BOARD_CONNECTED_ITEM*>( aItem );
if( cItem && cItem->GetNetCode() )
{
NETINFO_ITEM* netinfo = cItem->GetNet();
if( netinfo && !board()->FindNet( netinfo->GetNetname() ) )
{
board()->Add( netinfo );
details += wxString::Format( _( "Orphaned net %s re-parented.\n" ),
netinfo->GetNetname() );
errors++;
}
}
};
// Module IDs are the most important, so give them the first crack at "owning" a particular // Module IDs are the most important, so give them the first crack at "owning" a particular
// KIID. // KIID.
@ -421,6 +438,9 @@ int PCB_EDITOR_CONTROL::RepairBoard( const TOOL_EVENT& aEvent )
for( ZONE_CONTAINER* zone : module->Zones() ) for( ZONE_CONTAINER* zone : module->Zones() )
processItem( zone ); processItem( zone );
for( PCB_GROUP* group : module->Groups() )
processItem( group );
} }
for( BOARD_ITEM* drawing : board()->Drawings() ) for( BOARD_ITEM* drawing : board()->Drawings() )
@ -432,6 +452,9 @@ int PCB_EDITOR_CONTROL::RepairBoard( const TOOL_EVENT& aEvent )
for( MARKER_PCB* marker : board()->Markers() ) for( MARKER_PCB* marker : board()->Markers() )
processItem( marker ); processItem( marker );
for( PCB_GROUP* group : board()->Groups() )
processItem( group );
if( duplicates ) if( duplicates )
{ {
errors += duplicates; errors += duplicates;