From fbb669aa75a25a654480f1ff52b5c8025a6c4367 Mon Sep 17 00:00:00 2001 From: Tomasz Wlostowski Date: Sun, 27 Sep 2020 17:50:57 +0200 Subject: [PATCH] drc: diff pair test provider reports gap & max uncoupled length violations. --- .../drc_test_provider_diff_pair_coupling.cpp | 128 +++++++++++++++++- 1 file changed, 122 insertions(+), 6 deletions(-) diff --git a/pcbnew/drc/drc_test_provider_diff_pair_coupling.cpp b/pcbnew/drc/drc_test_provider_diff_pair_coupling.cpp index 9a4c9d8b31..644a4f6d65 100644 --- a/pcbnew/drc/drc_test_provider_diff_pair_coupling.cpp +++ b/pcbnew/drc/drc_test_provider_diff_pair_coupling.cpp @@ -41,7 +41,10 @@ - DRCE_DIFF_PAIR_GAP_OUT_OF_RANGE - DRCE_DIFF_PAIR_UNCOUPLED_LENGTH_TOO_LONG - DRCE_TOO_MANY_VIAS - Todo: arc support. + Todo: + - arc support. + - improve recognition of coupled segments (now anything that's parallel is considered coupled, causing + DRC errors on meanders) */ namespace test { @@ -249,6 +252,8 @@ struct DIFF_PAIR_KEY { SEG coupledN, coupledP; TRACK* parentN, *parentP; + int computedGap; + bool couplingOK; }; struct DIFF_PAIR_ITEMS @@ -326,15 +331,13 @@ bool test::DRC_TEST_PROVIDER_DIFF_PAIR_COUPLING::Run() for( int i = 0; i < 2; i++ ) { - auto constraint = m_drcEngine->EvalRulesForItems( constraintsToCheck[i], item ); + auto constraint = m_drcEngine->EvalRulesForItems( constraintsToCheck[i], item, nullptr, item->GetLayer() ); if( constraint.IsNull() ) continue; key.parentRule = constraint.GetParentRule(); - printf("insert %d %d\n", key.netN, key.netP ); - if( refNet == key.netN ) dpRuleMatches[key].itemsN.insert( citem ); else @@ -371,7 +374,24 @@ bool test::DRC_TEST_PROVIDER_DIFF_PAIR_COUPLING::Run() it.second.totalLengthN = 0; it.second.totalLengthP = 0; - printf(" coupled prims : %d\n", it.second.coupled.size() ); + drc_dbg(10, " coupled prims : %d\n", (int) it.second.coupled.size() ); + + OPT gapConstraint = it.first.parentRule->FindConstraint( DRC_CONSTRAINT_TYPE_DIFF_PAIR_GAP ); + OPT maxUncoupledConstraint = it.first.parentRule->FindConstraint( DRC_CONSTRAINT_TYPE_DIFF_PAIR_MAX_UNCOUPLED ); + + for( auto& item : it.second.itemsN ) + { + // fixme: include vias + if( auto track = dyn_cast( item ) ) + it.second.totalLengthN += track->GetLength(); + } + + for( auto& item : it.second.itemsP ) + { + // fixme: include vias + if( auto track = dyn_cast( item ) ) + it.second.totalLengthP += track->GetLength(); + } for( auto& cpair : it.second.coupled ) { @@ -381,7 +401,103 @@ bool test::DRC_TEST_PROVIDER_DIFF_PAIR_COUPLING::Run() gap -= cpair.parentN->GetWidth() / 2; gap -= cpair.parentP->GetWidth() / 2; - printf(" len %d gap %d\n", length, gap); + cpair.computedGap = gap; + + drc_dbg(10, " len %d gap %d l %d\n", length, gap, cpair.parentP->GetLayer() ); + + if( gapConstraint ) + { + auto val = gapConstraint->GetValue(); + bool insideRange = true; + if ( val.HasMin() && gap < val.Min() ) + insideRange = false; + if ( val.HasMax() && gap > val.Max() ) + insideRange = false; + + +// if(val.HasMin() && val.HasMax() ) + // drc_dbg(10, "Vmin %d vmax %d\n", val.Min(), val.Max() ); + + cpair.couplingOK = insideRange; + + if( insideRange ) + it.second.totalCoupled += length; + } + } + + int totalLen = std::max( it.second.totalLengthN, it.second.totalLengthP ); + reportAux( wxString::Format( " - coupled length: %s, total length: %s", + + MessageTextFromValue( userUnits(), it.second.totalCoupled, false), + MessageTextFromValue( userUnits(), totalLen, false ) ) ); + + int totalUncoupled = totalLen - it.second.totalCoupled; + + bool uncoupledViolation = false; + + if( maxUncoupledConstraint ) + { + auto val = maxUncoupledConstraint->GetValue(); + + if ( val.HasMax() && totalUncoupled > val.Max() ) + { + std::shared_ptr drcItem = DRC_ITEM::Create( DRCE_DIFF_PAIR_UNCOUPLED_LENGTH_TOO_LONG ); + wxString msg = + drcItem->GetErrorText() + " (" + maxUncoupledConstraint->GetParentRule()->m_Name + " "; + + msg += wxString::Format( _( "maximum uncoupled length: %s; actual: %s)" ), + MessageTextFromValue( userUnits(), val.Max(), true ), + MessageTextFromValue( userUnits(), totalUncoupled, true ) ); + + drcItem->SetErrorMessage( msg ); + + for( auto offendingTrack : it.second.itemsP ) + drcItem->AddItem( offendingTrack ); + for( auto offendingTrack : it.second.itemsN ) + drcItem->AddItem( offendingTrack ); + + uncoupledViolation = true; + + drcItem->SetViolatingRule( maxUncoupledConstraint->GetParentRule() ); + + reportViolation( drcItem, (*it.second.itemsP.begin())->GetPosition() ); + } + } + + if ( gapConstraint && (uncoupledViolation || !maxUncoupledConstraint ) ) + { + for( auto& cpair : it.second.coupled ) + { + if( !cpair.couplingOK ) + { + auto val = gapConstraint->GetValue(); + + std::shared_ptr drcItem = DRC_ITEM::Create( DRCE_DIFF_PAIR_GAP_OUT_OF_RANGE ); + wxString msg = + drcItem->GetErrorText() + " (" + maxUncoupledConstraint->GetParentRule()->m_Name + " "; + + if( val.HasMin() ) + msg += wxString::Format( _( "minimum gap: %s; " ), + MessageTextFromValue( userUnits(), val.Min(), true ) ); + + if( val.HasMax() ) + msg += wxString::Format( _( "maximum gap: %s; " ), + MessageTextFromValue( userUnits(), val.Max(), true ) ); + + + msg += wxString::Format( _( "actual: %s)" ), + MessageTextFromValue( userUnits(), cpair.computedGap, true ) ); + + drcItem->SetErrorMessage( msg ); + + drcItem->AddItem( cpair.parentP ); + drcItem->AddItem( cpair.parentN ); + + drcItem->SetViolatingRule( gapConstraint->GetParentRule() ); + + reportViolation( drcItem, cpair.parentP->GetPosition() ); + } + } } }