Handle DP checks for board minimum rules

Fixes https://gitlab.com/kicad/code/kicad/-/issues/13640
This commit is contained in:
Jon Evans 2023-01-23 17:45:16 -05:00
parent 442ee52905
commit 12b0a12d74
1 changed files with 42 additions and 26 deletions

View File

@ -140,13 +140,20 @@ struct DIFF_PAIR_KEY
return true; return true;
else if( netN > b.netN ) else if( netN > b.netN )
return false; return false;
else if( gapRuleName.IsEmpty() )
return gapRuleName < b.gapRuleName;
else else
return parentRule < b.parentRule; return uncoupledRuleName < b.uncoupledRuleName;
} }
} }
int netP, netN; int netP, netN;
DRC_RULE* parentRule; wxString gapRuleName;
wxString uncoupledRuleName;
std::optional<MINOPTMAX<int>> gapConstraint;
DRC_RULE* gapRule;
std::optional<MINOPTMAX<int>> uncoupledConstraint;
DRC_RULE* uncoupledRule;
}; };
struct DIFF_PAIR_COUPLED_SEGMENTS struct DIFF_PAIR_COUPLED_SEGMENTS
@ -304,7 +311,26 @@ bool test::DRC_TEST_PROVIDER_DIFF_PAIR_COUPLING::Run()
drc_dbg( 10, wxT( "cns %d item %p\n" ), constraintsToCheck[i], item ); drc_dbg( 10, wxT( "cns %d item %p\n" ), constraintsToCheck[i], item );
key.parentRule = constraint.GetParentRule(); DRC_RULE* parentRule = constraint.GetParentRule();
wxString ruleName = parentRule ? parentRule->m_Name : constraint.GetName();
switch( constraintsToCheck[i] )
{
case DIFF_PAIR_GAP_CONSTRAINT:
key.gapConstraint = constraint.GetValue();
key.gapRule = parentRule;
key.gapRuleName = ruleName;
break;
case DIFF_PAIR_MAX_UNCOUPLED_CONSTRAINT:
key.uncoupledConstraint = constraint.GetValue();
key.uncoupledRule = parentRule;
key.uncoupledRuleName = ruleName;
break;
default:
break;
}
if( refNet->GetNetCode() == key.netN ) if( refNet->GetNetCode() == key.netN )
dpRuleMatches[key].itemsN.insert( citem ); dpRuleMatches[key].itemsN.insert( citem );
@ -337,9 +363,7 @@ bool test::DRC_TEST_PROVIDER_DIFF_PAIR_COUPLING::Run()
wxString nameN = niN->GetNetname(); wxString nameN = niN->GetNetname();
reportAux( wxString::Format( wxT( "Rule '%s', DP: (+) %s - (-) %s" ), reportAux( wxString::Format( wxT( "Rule '%s', DP: (+) %s - (-) %s" ),
key.parentRule->m_Name, key.gapRuleName, nameP, nameN ) );
nameP,
nameN ) );
extractDiffPairCoupledItems( itemSet ); extractDiffPairCoupledItems( itemSet );
@ -349,12 +373,6 @@ bool test::DRC_TEST_PROVIDER_DIFF_PAIR_COUPLING::Run()
drc_dbg(10, wxT( " coupled prims : %d\n" ), (int) itemSet.coupled.size() ); drc_dbg(10, wxT( " coupled prims : %d\n" ), (int) itemSet.coupled.size() );
std::optional<DRC_CONSTRAINT> gapConstraint
= key.parentRule->FindConstraint( DIFF_PAIR_GAP_CONSTRAINT );
std::optional<DRC_CONSTRAINT> maxUncoupledConstraint
= key.parentRule->FindConstraint( DIFF_PAIR_MAX_UNCOUPLED_CONSTRAINT );
for( BOARD_CONNECTED_ITEM* item : itemSet.itemsN ) for( BOARD_CONNECTED_ITEM* item : itemSet.itemsN )
{ {
// fixme: include vias // fixme: include vias
@ -397,14 +415,12 @@ bool test::DRC_TEST_PROVIDER_DIFF_PAIR_COUPLING::Run()
gap, gap,
dp.parentP->GetLayer() ); dp.parentP->GetLayer() );
if( gapConstraint ) if( key.gapConstraint )
{ {
const MINOPTMAX<int>& val = gapConstraint->GetValue(); if( key.gapConstraint->HasMin() && gap < key.gapConstraint->Min() - epsilon )
if( val.HasMin() && gap < val.Min() - epsilon )
dp.couplingFailMin = true; dp.couplingFailMin = true;
if( val.HasMax() && gap > val.Max() + epsilon ) if( key.gapConstraint->HasMax() && gap > key.gapConstraint->Max() + epsilon )
dp.couplingFailMax = true; dp.couplingFailMax = true;
} }
@ -421,15 +437,15 @@ bool test::DRC_TEST_PROVIDER_DIFF_PAIR_COUPLING::Run()
bool uncoupledViolation = false; bool uncoupledViolation = false;
if( maxUncoupledConstraint && ( !itemSet.itemsP.empty() || !itemSet.itemsN.empty() ) ) if( key.uncoupledConstraint && ( !itemSet.itemsP.empty() || !itemSet.itemsN.empty() ) )
{ {
const MINOPTMAX<int>& val = maxUncoupledConstraint->GetValue(); const MINOPTMAX<int>& val = *key.uncoupledConstraint;
if ( val.HasMax() && totalUncoupled > val.Max() ) if ( val.HasMax() && totalUncoupled > val.Max() )
{ {
auto drce = DRC_ITEM::Create( DRCE_DIFF_PAIR_UNCOUPLED_LENGTH_TOO_LONG ); auto drce = DRC_ITEM::Create( DRCE_DIFF_PAIR_UNCOUPLED_LENGTH_TOO_LONG );
wxString msg = formatMsg( _( "(%s maximum uncoupled length %s; actual %s)" ), wxString msg = formatMsg( _( "(%s maximum uncoupled length %s; actual %s)" ),
maxUncoupledConstraint->GetParentRule()->m_Name, key.uncoupledRuleName,
val.Max(), val.Max(),
totalUncoupled ); totalUncoupled );
@ -461,33 +477,33 @@ bool test::DRC_TEST_PROVIDER_DIFF_PAIR_COUPLING::Run()
uncoupledViolation = true; uncoupledViolation = true;
drce->SetViolatingRule( maxUncoupledConstraint->GetParentRule() ); drce->SetViolatingRule( key.uncoupledRule );
reportViolation( drce, item->GetPosition(), item->GetLayer() ); reportViolation( drce, item->GetPosition(), item->GetLayer() );
} }
} }
if( gapConstraint && ( uncoupledViolation || !maxUncoupledConstraint ) ) if( key.gapConstraint && ( uncoupledViolation || !key.uncoupledConstraint ) )
{ {
for( DIFF_PAIR_COUPLED_SEGMENTS& dp : itemSet.coupled ) for( DIFF_PAIR_COUPLED_SEGMENTS& dp : itemSet.coupled )
{ {
if( ( dp.couplingFailMin || dp.couplingFailMax ) && ( dp.parentP || dp.parentN ) ) if( ( dp.couplingFailMin || dp.couplingFailMax ) && ( dp.parentP || dp.parentN ) )
{ {
MINOPTMAX<int> val = gapConstraint->GetValue(); MINOPTMAX<int> val = *key.gapConstraint;
auto drcItem = DRC_ITEM::Create( DRCE_DIFF_PAIR_GAP_OUT_OF_RANGE ); auto drcItem = DRC_ITEM::Create( DRCE_DIFF_PAIR_GAP_OUT_OF_RANGE );
wxString msg; wxString msg;
if( dp.couplingFailMin ) if( dp.couplingFailMin )
{ {
msg = formatMsg( _( "(%s minimum gap %s; actual %s)" ), msg = formatMsg( _( "(%s minimum gap %s; actual %s)" ),
gapConstraint->GetParentRule()->m_Name, key.gapRuleName,
val.Min(), val.Min(),
dp.computedGap ); dp.computedGap );
} }
else if( dp.couplingFailMax ) else if( dp.couplingFailMax )
{ {
msg = formatMsg( _( "(%s maximum gap %s; actual %s)" ), msg = formatMsg( _( "(%s maximum gap %s; actual %s)" ),
gapConstraint->GetParentRule()->m_Name, key.gapRuleName,
val.Max(), val.Max(),
dp.computedGap ); dp.computedGap );
} }
@ -508,7 +524,7 @@ bool test::DRC_TEST_PROVIDER_DIFF_PAIR_COUPLING::Run()
drcItem->AddItem( dp.parentN ); drcItem->AddItem( dp.parentN );
} }
drcItem->SetViolatingRule( gapConstraint->GetParentRule() ); drcItem->SetViolatingRule( key.gapRule );
reportViolation( drcItem, item->GetPosition(), item->GetLayer() ); reportViolation( drcItem, item->GetPosition(), item->GetLayer() );
} }