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;
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 )
{
aNetP = aNet;
aNetP = aNet->GetNet();
aNetN = net->GetNet();
}
else
{
aNetP = net->GetNet();
aNetN = aNet;
aNetN = aNet->GetNet();
}
return true;

View File

@ -40,6 +40,7 @@ class ZONE_CONTAINER;
class MARKER_PCB;
class NETCLASS;
class NETLIST;
class NETINFO_ITEM;
class PROGRESS_REPORTER;
class REPORTER;
@ -177,7 +178,7 @@ public:
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:
void addRule( DRC_RULE* rule )

View File

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

View File

@ -335,12 +335,12 @@ static void isDiffPair( LIBEVAL::CONTEXT* aCtx, void* self )
result->Set( 0.0 );
aCtx->Push( result );
if( item->IsConnected() )
if( item && item->IsConnected() )
{
int net = static_cast<BOARD_CONNECTED_ITEM*>( item )->GetNetCode();
int net_p, net_n;
NETINFO_ITEM* netinfo = static_cast<BOARD_CONNECTED_ITEM*>( item )->GetNet();
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 );
}
}

View File

@ -374,22 +374,39 @@ int PCB_EDITOR_CONTROL::RepairBoard( const TOOL_EVENT& aEvent )
wxString details;
/*******************************
* Repair duplicate IDs
* Repair duplicate IDs and missing nets
*/
std::set<KIID> ids;
int duplicates = 0;
auto processItem = [&]( EDA_ITEM* aItem )
{
if( ids.count( aItem->m_Uuid ) )
{
duplicates++;
const_cast<KIID&>( aItem->m_Uuid ) = KIID();
}
auto processItem =
[&]( EDA_ITEM* aItem )
{
if( ids.count( aItem->m_Uuid ) )
{
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
// KIID.
@ -421,6 +438,9 @@ int PCB_EDITOR_CONTROL::RepairBoard( const TOOL_EVENT& aEvent )
for( ZONE_CONTAINER* zone : module->Zones() )
processItem( zone );
for( PCB_GROUP* group : module->Groups() )
processItem( group );
}
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() )
processItem( marker );
for( PCB_GROUP* group : board()->Groups() )
processItem( group );
if( duplicates )
{
errors += duplicates;