Improve DRC status reporting.

1) Don't report on tests not run.
2) Don't cancel subsequent tests because the current test didn't
have any constraints
3) Exit a little bit quicker when cancelled

Fixes https://gitlab.com/kicad/code/kicad/issues/7724
This commit is contained in:
Jeff Young 2021-02-27 13:43:41 +00:00
parent 1f109ac6aa
commit 6d6765cdaf
14 changed files with 221 additions and 114 deletions

View File

@ -657,19 +657,6 @@ void DRC_ENGINE::RunTests( EDA_UNITS aUnits, bool aReportAllTrackErrors, bool aT
m_reportAllTrackErrors = aReportAllTrackErrors;
m_testFootprints = aTestFootprints;
if( m_progressReporter )
{
int phases = 1;
for( DRC_TEST_PROVIDER* provider : m_testProviders )
{
if( provider->IsEnabled() )
phases += provider->GetNumPhases();
}
m_progressReporter->AddPhases( phases );
}
for( int ii = DRCE_FIRST; ii < DRCE_LAST; ++ii )
{
if( m_designSettings->Ignore( ii ) )

View File

@ -69,16 +69,22 @@ public:
bool DRC_TEST_PROVIDER_ANNULUS::Run()
{
if( m_drcEngine->IsErrorLimitExceeded( DRCE_ANNULAR_WIDTH ) )
{
reportAux( "Annular width violations ignored. Skipping check." );
return true; // continue with other tests
}
const int delta = 250; // This is the number of tests between 2 calls to the progress bar
if( !m_drcEngine->HasRulesForConstraintType( ANNULAR_WIDTH_CONSTRAINT ) )
{
reportAux( "No annulus constraints found. Skipping check." );
return false;
reportAux( "No annulus constraints found. Tests not run." );
return true; // continue with other tests
}
if( !reportPhase( _( "Checking via annular rings..." ) ) )
return false;
return false; // DRC cancelled
auto checkAnnulus =
[&]( BOARD_ITEM* item ) -> bool
@ -148,7 +154,7 @@ bool DRC_TEST_PROVIDER_ANNULUS::Run()
break;
if( !checkAnnulus( item ) )
break;
return false; // DRC cancelled
}
reportRuleStatistics();

View File

@ -72,7 +72,7 @@ public:
bool DRC_TEST_PROVIDER_CONNECTIVITY::Run()
{
if( !reportPhase( _( "Checking pad, via and zone connections..." ) ) )
return false;
return false; // DRC cancelled
BOARD* board = m_drcEngine->GetBoard();
@ -126,7 +126,7 @@ bool DRC_TEST_PROVIDER_CONNECTIVITY::Run()
continue;
if( !reportProgress( ii++, count, delta ) )
break;
return false; // DRC cancelled
int netcode = zone->GetNetCode();
// a netcode < 0 or > 0 and no pad in net is a error or strange
@ -142,8 +142,11 @@ bool DRC_TEST_PROVIDER_CONNECTIVITY::Run()
}
}
if( m_drcEngine->IsErrorLimitExceeded( DRCE_UNCONNECTED_ITEMS ) )
return true; // continue with other tests
if( !reportPhase( _( "Checking net connections..." ) ) )
return false;
return false; // DRC cancelled
connectivity->RecalculateRatsnest();
std::vector<CN_EDGE> edges;
@ -159,7 +162,7 @@ bool DRC_TEST_PROVIDER_CONNECTIVITY::Run()
break;
if( !reportProgress( ii++, count, delta ) )
break;
return false; // DRC cancelled
std::shared_ptr<DRC_ITEM> drcItem = DRC_ITEM::Create( DRCE_UNCONNECTED_ITEMS );
drcItem->SetItems( edge.GetSourceNode()->Parent(), edge.GetTargetNode()->Parent() );

View File

@ -104,18 +104,15 @@ bool DRC_TEST_PROVIDER_COPPER_CLEARANCE::Run()
DRC_CONSTRAINT worstConstraint;
if( m_drcEngine->QueryWorstConstraint( CLEARANCE_CONSTRAINT, worstConstraint ) )
{
m_largestClearance = worstConstraint.GetValue().Min();
}
else
{
reportAux( "No Clearance constraints found..." );
return false;
}
if( m_drcEngine->QueryWorstConstraint( HOLE_CLEARANCE_CONSTRAINT, worstConstraint ) )
{
m_largestClearance = std::max( m_largestClearance, worstConstraint.GetValue().Min() );
if( m_largestClearance <= 0 )
{
reportAux( "No Clearance constraints found. Tests not run." );
return true; // continue with other tests
}
m_drcEpsilon = m_board->GetDesignSettings().GetDRCEpsilon();
@ -173,7 +170,7 @@ bool DRC_TEST_PROVIDER_COPPER_CLEARANCE::Run()
};
if( !reportPhase( _( "Gathering copper items..." ) ) )
return false;
return false; // DRC cancelled
static const std::vector<KICAD_T> itemTypes = {
PCB_TRACE_T, PCB_ARC_T, PCB_VIA_T, PCB_PAD_T, PCB_SHAPE_T, PCB_FP_SHAPE_T,
@ -186,20 +183,51 @@ bool DRC_TEST_PROVIDER_COPPER_CLEARANCE::Run()
reportAux( "Testing %d copper items and %d zones...", count, m_zones.size() );
if( !reportPhase( _( "Checking track & via clearances..." ) ) )
return false;
if( !m_drcEngine->IsErrorLimitExceeded( DRCE_CLEARANCE ) )
{
if( !reportPhase( _( "Checking track & via clearances..." ) ) )
return false; // DRC cancelled
testTrackClearances();
testTrackClearances();
}
else if( !m_drcEngine->IsErrorLimitExceeded( DRCE_HOLE_CLEARANCE ) )
{
if( !reportPhase( _( "Checking hole clearances..." ) ) )
return false; // DRC cancelled
if( !reportPhase( _( "Checking pad clearances..." ) ) )
return false;
testTrackClearances();
}
testPadClearances();
if( !m_drcEngine->IsErrorLimitExceeded( DRCE_CLEARANCE ) )
{
if( !reportPhase( _( "Checking pad clearances..." ) ) )
return false; // DRC cancelled
if( !reportPhase( _( "Checking copper zone clearances..." ) ) )
return false;
testPadClearances();
}
else if( !m_drcEngine->IsErrorLimitExceeded( DRCE_SHORTING_ITEMS )
|| !m_drcEngine->IsErrorLimitExceeded( DRCE_HOLE_CLEARANCE ) )
{
if( !reportPhase( _( "Checking pads..." ) ) )
return false; // DRC cancelled
testZones();
testPadClearances();
}
if( !m_drcEngine->IsErrorLimitExceeded( DRCE_CLEARANCE ) )
{
if( !reportPhase( _( "Checking copper zone clearances..." ) ) )
return false; // DRC cancelled
testZones();
}
else if( !m_drcEngine->IsErrorLimitExceeded( DRCE_ZONES_INTERSECT ) )
{
if( !reportPhase( _( "Checking zones..." ) ) )
return false; // DRC cancelled
testZones();
}
reportRuleStatistics();

View File

@ -66,26 +66,40 @@ public:
int GetNumPhases() const override;
private:
void testFootprintCourtyardDefinitions();
bool testFootprintCourtyardDefinitions();
void testCourtyardClearances();
bool testCourtyardClearances();
};
void DRC_TEST_PROVIDER_COURTYARD_CLEARANCE::testFootprintCourtyardDefinitions()
bool DRC_TEST_PROVIDER_COURTYARD_CLEARANCE::testFootprintCourtyardDefinitions()
{
const int delta = 100; // This is the number of tests between 2 calls to the progress bar
// Detects missing (or malformed) footprint courtyards
if( !reportPhase( _( "Checking footprint courtyard definitions..." ) ) )
return;
if( !m_drcEngine->IsErrorLimitExceeded( DRCE_MALFORMED_COURTYARD)
|| !m_drcEngine->IsErrorLimitExceeded( DRCE_MISSING_COURTYARD) )
{
if( !reportPhase( _( "Checking footprint courtyard definitions..." ) ) )
return false; // DRC cancelled
}
else if( !m_drcEngine->IsErrorLimitExceeded( DRCE_OVERLAPPING_FOOTPRINTS) )
{
if( !reportPhase( _( "Gathering footprint courtyards..." ) ) )
return false; // DRC cancelled
}
else
{
reportAux( "All courtyard violations ignored. Tests not run." );
return true; // continue with other tests
}
int ii = 0;
for( FOOTPRINT* footprint : m_board->Footprints() )
{
if( !reportProgress( ii++, m_board->Footprints().size(), delta ) )
return;
return false; // DRC cancelled
if( ( footprint->GetFlags() & MALFORMED_COURTYARDS ) != 0 )
{
@ -120,22 +134,27 @@ void DRC_TEST_PROVIDER_COURTYARD_CLEARANCE::testFootprintCourtyardDefinitions()
footprint->GetPolyCourtyardBack().BuildBBoxCaches();
}
}
return true;
}
void DRC_TEST_PROVIDER_COURTYARD_CLEARANCE::testCourtyardClearances()
bool DRC_TEST_PROVIDER_COURTYARD_CLEARANCE::testCourtyardClearances()
{
const int delta = 100; // This is the number of tests between 2 calls to the progress bar
if( m_drcEngine->IsErrorLimitExceeded( DRCE_OVERLAPPING_FOOTPRINTS) )
return true; // continue with other tests
if( !reportPhase( _( "Checking footprints for overlapping courtyards..." ) ) )
return;
return false; // DRC cancelled
int ii = 0;
for( auto it1 = m_board->Footprints().begin(); it1 != m_board->Footprints().end(); it1++ )
{
if( !reportProgress( ii++, m_board->Footprints().size(), delta ) )
break;
return false; // DRC cancelled
if( m_drcEngine->IsErrorLimitExceeded( DRCE_OVERLAPPING_FOOTPRINTS) )
break;
@ -218,6 +237,8 @@ void DRC_TEST_PROVIDER_COURTYARD_CLEARANCE::testCourtyardClearances()
}
}
}
return true;
}
@ -231,9 +252,11 @@ bool DRC_TEST_PROVIDER_COURTYARD_CLEARANCE::Run()
reportAux( "Worst courtyard clearance : %d nm", m_largestClearance );
testFootprintCourtyardDefinitions();
if( !testFootprintCourtyardDefinitions() )
return false;
testCourtyardClearances();
if( !testCourtyardClearances() )
return false;
return true;
}

View File

@ -64,14 +64,20 @@ public:
bool DRC_TEST_PROVIDER_DISALLOW::Run()
{
if( m_drcEngine->IsErrorLimitExceeded( DRCE_ALLOWED_ITEMS ) )
{
reportAux( "Disallow violations ignored. Tests not run." );
return true; // continue with other tests
}
if( !m_drcEngine->HasRulesForConstraintType( DISALLOW_CONSTRAINT ) )
{
reportAux( "No disallow constraints found. Skipping check." );
return false;
return true; // continue with other tests
}
if( !reportPhase( _( "Checking keepouts & disallow constraints..." ) ) )
return false;
return false; // DRC cancelled
auto doCheckItem =
[&]( BOARD_ITEM* item )

View File

@ -117,6 +117,22 @@ bool DRC_TEST_PROVIDER_EDGE_CLEARANCE::testAgainstEdge( BOARD_ITEM* item, SHAPE*
bool DRC_TEST_PROVIDER_EDGE_CLEARANCE::Run()
{
if( !m_drcEngine->IsErrorLimitExceeded( DRCE_COPPER_EDGE_CLEARANCE ) )
{
if( !reportPhase( _( "Checking copper to board edge clearances..." ) ) )
return false; // DRC cancelled
}
else if( m_drcEngine->IsErrorLimitExceeded( DRCE_SILK_MASK_CLEARANCE ) )
{
if( !reportPhase( _( "Checking silk to board edge clearances..." ) ) )
return false; // DRC cancelled
}
else
{
reportAux( "Edge clearance violations ignored. Tests not run." );
return true; // continue with other tests
}
m_board = m_drcEngine->GetBoard();
DRC_CONSTRAINT worstClearanceConstraint;
@ -126,9 +142,6 @@ bool DRC_TEST_PROVIDER_EDGE_CLEARANCE::Run()
reportAux( "Worst clearance : %d nm", m_largestClearance );
if( !reportPhase( _( "Checking board edge clearances..." ) ) )
return false;
std::vector<std::unique_ptr<PCB_SHAPE>> edges; // we own these
DRC_RTREE edgesTree;
std::vector<BOARD_ITEM*> boardItems; // we don't own these
@ -216,7 +229,7 @@ bool DRC_TEST_PROVIDER_EDGE_CLEARANCE::Run()
break;
if( !reportProgress( ii++, boardItems.size(), delta ) )
break;
return false; // DRC cancelled
const std::shared_ptr<SHAPE>& itemShape = item->GetEffectiveShape();

View File

@ -95,6 +95,12 @@ static std::shared_ptr<SHAPE_CIRCLE> getDrilledHoleShape( BOARD_ITEM* aItem )
bool DRC_TEST_PROVIDER_HOLE_CLEARANCE::Run()
{
if( m_drcEngine->IsErrorLimitExceeded( DRCE_DRILLED_HOLES_TOO_CLOSE ) )
{
reportAux( "Hole-to-hole violations ignored. Tests not run." );
return true; // continue with other tests
}
m_board = m_drcEngine->GetBoard();
DRC_CONSTRAINT worstClearanceConstraint;
@ -106,10 +112,13 @@ bool DRC_TEST_PROVIDER_HOLE_CLEARANCE::Run()
}
else
{
reportAux( "No hole to hole constraints found..." );
return false;
reportAux( "No hole to hole constraints found. Skipping check." );
return true; // continue with other tests
}
if( !reportPhase( _( "Checking hole to hole clearances..." ) ) )
return false; // DRC cancelled
// This is the number of tests between 2 calls to the progress bar
const size_t delta = 50;
size_t count = 0;
@ -154,9 +163,6 @@ bool DRC_TEST_PROVIDER_HOLE_CLEARANCE::Run()
return true;
};
if( !reportPhase( _( "Checking hole to hole clearances..." ) ) )
return false;
forEachGeometryItem( { PCB_PAD_T, PCB_VIA_T }, LSET::AllLayersMask(), countItems );
count *= 2; // One for adding to tree; one for checking
@ -173,7 +179,7 @@ bool DRC_TEST_PROVIDER_HOLE_CLEARANCE::Run()
VIA* via = static_cast<VIA*>( track );
if( !reportProgress( ii++, count, delta ) )
break;
return false; // DRC cancelled
// We only care about mechanically drilled (ie: non-laser) holes
if( via->GetViaType() == VIATYPE::THROUGH )
@ -218,7 +224,7 @@ bool DRC_TEST_PROVIDER_HOLE_CLEARANCE::Run()
for( PAD* pad : footprint->Pads() )
{
if( !reportProgress( ii++, count, delta ) )
break;
return false; // DRC cancelled
// We only care about drilled (ie: round) holes
if( pad->GetDrillSize().x && pad->GetDrillSize().x == pad->GetDrillSize().y )

View File

@ -73,46 +73,60 @@ private:
bool DRC_TEST_PROVIDER_HOLE_SIZE::Run()
{
if( !reportPhase( _( "Checking pad holes..." ) ) )
return false;
m_board = m_drcEngine->GetBoard();
for( FOOTPRINT* footprint : m_board->Footprints() )
if( !m_drcEngine->IsErrorLimitExceeded( DRCE_DRILL_OUT_OF_RANGE ) )
{
if( m_drcEngine->IsErrorLimitExceeded( DRCE_DRILL_OUT_OF_RANGE ) )
break;
if( !reportPhase( _( "Checking pad holes..." ) ) )
return false; // DRC cancelled
for( PAD* pad : footprint->Pads() )
m_board = m_drcEngine->GetBoard();
for( FOOTPRINT* footprint : m_board->Footprints() )
{
if( m_drcEngine->IsErrorLimitExceeded( DRCE_DRILL_OUT_OF_RANGE ) )
break;
checkPad( pad );
for( PAD* pad : footprint->Pads() )
{
if( m_drcEngine->IsErrorLimitExceeded( DRCE_DRILL_OUT_OF_RANGE ) )
break;
checkPad( pad );
}
}
}
if( !reportPhase( _( "Checking via holes..." ) ) )
return false;
std::vector<VIA*> vias;
for( TRACK* track : m_board->Tracks() )
if( !m_drcEngine->IsErrorLimitExceeded( DRCE_MICROVIA_DRILL_OUT_OF_RANGE )
|| !m_drcEngine->IsErrorLimitExceeded( DRCE_DRILL_OUT_OF_RANGE ) )
{
if( track->Type() == PCB_VIA_T )
vias.push_back( static_cast<VIA*>( track ) );
}
if( !m_drcEngine->IsErrorLimitExceeded( DRCE_DRILL_OUT_OF_RANGE ) )
{
if( !reportPhase( _( "Checking via holes..." ) ) )
return false; // DRC cancelled
}
else
{
if( !reportPhase( _( "Checking micro-via holes..." ) ) )
return false; // DRC cancelled
}
std::vector<VIA*> vias;
for( VIA* via : vias )
{
bool exceedMicro = m_drcEngine->IsErrorLimitExceeded( DRCE_MICROVIA_DRILL_OUT_OF_RANGE );
bool exceedStd = m_drcEngine->IsErrorLimitExceeded( DRCE_DRILL_OUT_OF_RANGE );
for( TRACK* track : m_board->Tracks() )
{
if( track->Type() == PCB_VIA_T )
vias.push_back( static_cast<VIA*>( track ) );
}
if( exceedMicro && exceedStd )
break;
for( VIA* via : vias )
{
bool exceedMicro = m_drcEngine->IsErrorLimitExceeded( DRCE_MICROVIA_DRILL_OUT_OF_RANGE );
bool exceedStd = m_drcEngine->IsErrorLimitExceeded( DRCE_DRILL_OUT_OF_RANGE );
checkVia( via, exceedMicro, exceedStd );
if( exceedMicro && exceedStd )
break;
checkVia( via, exceedMicro, exceedStd );
}
}
reportRuleStatistics();

View File

@ -213,20 +213,29 @@ bool DRC_TEST_PROVIDER_MISC::Run()
{
m_board = m_drcEngine->GetBoard();
if( !reportPhase( _( "Checking board outline..." ) ) )
return false;
if( !m_drcEngine->IsErrorLimitExceeded( DRCE_INVALID_OUTLINE ) )
{
if( !reportPhase( _( "Checking board outline..." ) ) )
return false; // DRC cancelled
testOutline();
testOutline();
}
if( !reportPhase( _( "Checking disabled layers..." ) ) )
return false;
if( !m_drcEngine->IsErrorLimitExceeded( DRCE_DISABLED_LAYER_ITEM ) )
{
if( !reportPhase( _( "Checking disabled layers..." ) ) )
return false; // DRC cancelled
testDisabledLayers();
testDisabledLayers();
}
if( !reportPhase( _( "Checking text variables..." ) ) )
return false;
if( !m_drcEngine->IsErrorLimitExceeded( DRCE_UNRESOLVED_VARIABLE ) )
{
if( !reportPhase( _( "Checking text variables..." ) ) )
return false; // DRC cancelled
testTextVars();
testTextVars();
}
return true;
}

View File

@ -85,24 +85,24 @@ bool DRC_TEST_PROVIDER_SILK_CLEARANCE::Run()
// This is the number of tests between 2 calls to the progress bar
const int delta = 2000;
if( m_drcEngine->IsErrorLimitExceeded( DRCE_OVERLAPPING_SILK ) )
{
reportAux( "Overlapping silk violations ignored. Tests not run." );
return true; // continue with other tests
}
m_board = m_drcEngine->GetBoard();
DRC_CONSTRAINT worstClearanceConstraint;
m_largestClearance = 0;
if( m_drcEngine->IsErrorLimitExceeded( DRCE_OVERLAPPING_SILK ) )
{
reportAux( "Silkscreen clearance testing not run." );
return true;
}
if( m_drcEngine->QueryWorstConstraint( SILK_CLEARANCE_CONSTRAINT, worstClearanceConstraint ) )
m_largestClearance = worstClearanceConstraint.m_Value.Min();
reportAux( "Worst clearance : %d nm", m_largestClearance );
if( !reportPhase( _( "Checking silkscreen for overlapping items..." ) ) )
return false;
return false; // DRC cancelled
DRC_RTREE silkTree;
DRC_RTREE targetTree;

View File

@ -84,8 +84,8 @@ bool DRC_TEST_PROVIDER_SILK_TO_MASK::Run()
if( m_drcEngine->IsErrorLimitExceeded( DRCE_SILK_MASK_CLEARANCE ) )
{
reportAux( "Silkscreen clipping tests not run." );
return true;
reportAux( "Silkscreen clipping violations ignored. Tests not run." );
return true; // continue with other tests
}
DRC_CONSTRAINT worstClearanceConstraint;
@ -97,7 +97,7 @@ bool DRC_TEST_PROVIDER_SILK_TO_MASK::Run()
reportAux( "Worst clearance : %d nm", m_largestClearance );
if( !reportPhase( _( "Checking silkscreen for potential soldermask clipping..." ) ) )
return false;
return false; // DRC cancelled
DRC_RTREE maskTree, silkTree;

View File

@ -67,14 +67,20 @@ bool DRC_TEST_PROVIDER_TRACK_WIDTH::Run()
{
const int delta = 100; // This is the number of tests between 2 calls to the progress bar
if( m_drcEngine->IsErrorLimitExceeded( DRCE_TRACK_WIDTH ) )
{
reportAux( "Track width violations ignored. Tests not run." );
return true; // continue with other tests
}
if( !m_drcEngine->HasRulesForConstraintType( TRACK_WIDTH_CONSTRAINT ) )
{
reportAux( "No track width constraints found. Skipping check." );
return false;
reportAux( "No track width constraints found. Tests not run." );
return true; // continue with other tests
}
if( !reportPhase( _( "Checking track widths..." ) ) )
return false;
return false; // DRC cancelled
auto checkTrackWidth =
[&]( BOARD_ITEM* item ) -> bool

View File

@ -66,14 +66,20 @@ bool DRC_TEST_PROVIDER_VIA_DIAMETER::Run()
{
const int delta = 100; // This is the number of tests between 2 calls to the progress bar
if( m_drcEngine->IsErrorLimitExceeded( DRCE_VIA_DIAMETER ) )
{
reportAux( "Via diameter violations ignored. Tests not run." );
return true; // continue with other tests
}
if( !m_drcEngine->HasRulesForConstraintType( VIA_DIAMETER_CONSTRAINT ) )
{
reportAux( "No diameter constraints found. Skipping check." );
return false;
reportAux( "No via diameter constraints found. Tests not run." );
return true; // continue with other tests
}
if( !reportPhase( _( "Checking via diameters..." ) ) )
return false;
return false; // DRC cancelled
auto checkViaDiameter =
[&]( BOARD_ITEM* item ) -> bool