More performance enhancements for DRC.

This commit is contained in:
Jeff Young 2022-03-12 13:34:25 +00:00
parent e03b06927d
commit 89e61ff73b
8 changed files with 175 additions and 152 deletions

View File

@ -112,6 +112,8 @@ protected:
static std::vector<KICAD_T> s_allBasicItemsButZones;
EDA_UNITS userUnits() const;
protected:
DRC_ENGINE* m_drcEngine;
std::unordered_map<const DRC_RULE*, int> m_stats;
bool m_isRuleDriven = true;

View File

@ -142,9 +142,8 @@ bool DRC_TEST_PROVIDER_EDGE_CLEARANCE::Run()
reportAux( wxT( "Worst clearance : %d nm" ), m_largestClearance );
std::vector<std::unique_ptr<PCB_SHAPE>> edges; // we own these
std::vector<std::unique_ptr<PCB_SHAPE>> edges;
DRC_RTREE edgesTree;
std::vector<BOARD_ITEM*> boardItems; // we don't own these
forEachGeometryItem( { PCB_SHAPE_T, PCB_FP_SHAPE_T }, LSET( 2, Edge_Cuts, Margin ),
[&]( BOARD_ITEM *item ) -> bool
@ -205,36 +204,32 @@ bool DRC_TEST_PROVIDER_EDGE_CLEARANCE::Run()
}
}
// This is the number of tests between 2 calls to the progress bar
const int delta = 100;
int count = 0;
int ii = 0;
forEachGeometryItem( s_allBasicItemsButZones, LSET::AllLayersMask(),
[&]( BOARD_ITEM *item ) -> bool
{
if( !isInvisibleText( item ) )
boardItems.push_back( item );
count++;
return true;
} );
wxString val;
wxGetEnv( "WXTRACE", &val );
drc_dbg( 2, wxT( "outline: %d items, board: %d items\n" ),
(int) edges.size(),
(int) boardItems.size() );
// This is the number of tests between 2 calls to the progress bar
const int delta = 50;
int ii = 0;
for( BOARD_ITEM* item : boardItems )
forEachGeometryItem( s_allBasicItemsButZones, LSET::AllLayersMask(),
[&]( BOARD_ITEM *item ) -> bool
{
bool testCopper = !m_drcEngine->IsErrorLimitExceeded( DRCE_EDGE_CLEARANCE );
bool testSilk = !m_drcEngine->IsErrorLimitExceeded( DRCE_SILK_CLEARANCE );
if( !testCopper && !testSilk )
break;
return false; // We're done
if( !reportProgress( ii++, boardItems.size(), delta ) )
return false; // DRC cancelled
if( !reportProgress( ii++, count, delta ) )
return false; // DRC cancelled; we're done
if( isInvisibleText( item ) )
return true; // Continue with other items
const std::shared_ptr<SHAPE>& itemShape = item->GetEffectiveShape();
@ -271,7 +266,9 @@ bool DRC_TEST_PROVIDER_EDGE_CLEARANCE::Run()
}
}
}
}
return true;
} );
reportRuleStatistics();

View File

@ -102,15 +102,9 @@ bool DRC_TEST_PROVIDER_HOLE_SIZE::Run()
return false; // DRC cancelled
}
std::vector<PCB_VIA*> vias;
for( PCB_TRACK* track : m_drcEngine->GetBoard()->Tracks() )
{
if( track->Type() == PCB_VIA_T )
vias.push_back( static_cast<PCB_VIA*>( track ) );
}
for( PCB_VIA* via : vias )
{
bool exceedMicro = m_drcEngine->IsErrorLimitExceeded( DRCE_MICROVIA_DRILL_OUT_OF_RANGE );
bool exceedStd = m_drcEngine->IsErrorLimitExceeded( DRCE_DRILL_OUT_OF_RANGE );
@ -118,7 +112,8 @@ bool DRC_TEST_PROVIDER_HOLE_SIZE::Run()
if( exceedMicro && exceedStd )
break;
checkVia( via, exceedMicro, exceedStd );
checkVia( static_cast<PCB_VIA*>( track ), exceedMicro, exceedStd );
}
}
}

View File

@ -119,7 +119,7 @@ bool DRC_TEST_PROVIDER_HOLE_TO_HOLE::Run()
return false; // DRC cancelled
// This is the number of tests between 2 calls to the progress bar
const size_t delta = 50;
const size_t delta = 100;
size_t count = 0;
size_t ii = 0;
@ -128,11 +128,7 @@ bool DRC_TEST_PROVIDER_HOLE_TO_HOLE::Run()
forEachGeometryItem( { PCB_PAD_T, PCB_VIA_T }, LSET::AllLayersMask(),
[&]( BOARD_ITEM* item ) -> bool
{
if( item->Type() == PCB_PAD_T )
++count;
else if( item->Type() == PCB_VIA_T )
++count;
return true;
} );

View File

@ -23,7 +23,6 @@
#include <pad.h>
#include <pcb_track.h>
#include <drc/drc_engine.h>
#include <drc/drc_item.h>
#include <drc/drc_rule.h>
#include <drc/drc_test_provider.h>
@ -75,16 +74,19 @@ private:
using CONNECTION = DRC_LENGTH_REPORT::ENTRY;
void checkLengths( DRC_CONSTRAINT& aConstraint, std::vector<CONNECTION>& aMatchedConnections );
void checkSkews( DRC_CONSTRAINT& aConstraint, std::vector<CONNECTION>& aMatchedConnections );
void checkViaCounts( DRC_CONSTRAINT& aConstraint, std::vector<CONNECTION>& aMatchedConnections );
void checkLengths( const DRC_CONSTRAINT& aConstraint,
const std::vector<CONNECTION>& aMatchedConnections );
void checkSkews( const DRC_CONSTRAINT& aConstraint,
const std::vector<CONNECTION>& aMatchedConnections );
void checkViaCounts( const DRC_CONSTRAINT& aConstraint,
const std::vector<CONNECTION>& aMatchedConnections );
BOARD* m_board;
DRC_LENGTH_REPORT m_report;
};
void DRC_TEST_PROVIDER_MATCHED_LENGTH::checkLengths( DRC_CONSTRAINT& aConstraint,
std::vector<CONNECTION>& aMatchedConnections )
void DRC_TEST_PROVIDER_MATCHED_LENGTH::checkLengths( const DRC_CONSTRAINT& aConstraint,
const std::vector<CONNECTION>& aMatchedConnections )
{
for( const DRC_LENGTH_REPORT::ENTRY& ent : aMatchedConnections )
{
@ -136,8 +138,8 @@ void DRC_TEST_PROVIDER_MATCHED_LENGTH::checkLengths( DRC_CONSTRAINT& aConstraint
}
}
void DRC_TEST_PROVIDER_MATCHED_LENGTH::checkSkews( DRC_CONSTRAINT& aConstraint,
std::vector<CONNECTION>& aMatchedConnections )
void DRC_TEST_PROVIDER_MATCHED_LENGTH::checkSkews( const DRC_CONSTRAINT& aConstraint,
const std::vector<CONNECTION>& aMatchedConnections )
{
int avgLength = 0;
@ -174,8 +176,8 @@ void DRC_TEST_PROVIDER_MATCHED_LENGTH::checkSkews( DRC_CONSTRAINT& aConstraint,
}
void DRC_TEST_PROVIDER_MATCHED_LENGTH::checkViaCounts( DRC_CONSTRAINT& aConstraint,
std::vector<CONNECTION>& aMatchedConnections )
void DRC_TEST_PROVIDER_MATCHED_LENGTH::checkViaCounts( const DRC_CONSTRAINT& aConstraint,
const std::vector<CONNECTION>& aMatchedConnections )
{
for( const auto& ent : aMatchedConnections )
{
@ -225,9 +227,24 @@ bool DRC_TEST_PROVIDER_MATCHED_LENGTH::runInternal( bool aDelayReportMode )
ftCache->Rebuild( m_board );
// This is the number of tests between 2 calls to the progress bar
const size_t delta = 50;
size_t count = 0;
size_t ii = 0;
forEachGeometryItem( { PCB_TRACE_T, PCB_ARC_T, PCB_VIA_T }, LSET::AllCuMask(),
[&]( BOARD_ITEM *item ) -> bool
{
count++;
return true;
} );
forEachGeometryItem( { PCB_TRACE_T, PCB_ARC_T, PCB_VIA_T }, LSET::AllCuMask(),
[&]( BOARD_ITEM *item ) -> bool
{
if( !reportProgress( ii++, count, delta ) )
return false;
const DRC_CONSTRAINT_T constraintsToCheck[] = {
LENGTH_CONSTRAINT,
SKEW_CONSTRAINT,
@ -250,17 +267,16 @@ bool DRC_TEST_PROVIDER_MATCHED_LENGTH::runInternal( bool aDelayReportMode )
return true;
} );
std::map<DRC_RULE*, std::vector<CONNECTION> > matches;
std::map< DRC_RULE*, std::vector<CONNECTION> > matches;
for( auto it : itemSets )
for( const std::pair< DRC_RULE* const, std::set<BOARD_CONNECTED_ITEM*> >& it : itemSets )
{
std::map<int, std::set<BOARD_CONNECTED_ITEM*> > netMap;
for( auto citem : it.second )
for( BOARD_CONNECTED_ITEM* citem : it.second )
netMap[ citem->GetNetCode() ].insert( citem );
for( auto nitem : netMap )
for( const std::pair< const int, std::set<BOARD_CONNECTED_ITEM*> >& nitem : netMap )
{
CONNECTION ent;
ent.items = nitem.second;
@ -327,11 +343,20 @@ bool DRC_TEST_PROVIDER_MATCHED_LENGTH::runInternal( bool aDelayReportMode )
if( !aDelayReportMode )
{
for( auto it : matches )
if( !reportPhase( _( "Checking length constraints..." ) ) )
return false;
ii = 0;
count = matches.size();
for( std::pair< DRC_RULE* const, std::vector<CONNECTION> > it : matches )
{
DRC_RULE *rule = it.first;
auto& matchedConnections = it.second;
if( !reportProgress( ii++, count, delta ) )
return false;
std::sort( matchedConnections.begin(), matchedConnections.end(),
[] ( const CONNECTION&a, const CONNECTION&b ) -> int
{
@ -341,7 +366,7 @@ bool DRC_TEST_PROVIDER_MATCHED_LENGTH::runInternal( bool aDelayReportMode )
reportAux( wxString::Format( wxT( "Length-constrained traces for rule '%s':" ),
it.first->m_Name ) );
for( auto& ent : matchedConnections )
for( const DRC_LENGTH_REPORT::ENTRY& ent : matchedConnections )
{
reportAux(wxString::Format( wxT( " - net: %s, from: %s, to: %s, "
"%d matching items, "

View File

@ -83,7 +83,6 @@ private:
private:
DRC_RTREE m_itemTree;
std::vector<BOARD_ITEM*> m_items;
std::vector<ZONE*> m_zones;
};
@ -93,7 +92,7 @@ bool DRC_TEST_PROVIDER_MECHANICAL_CLEARANCE::Run()
m_board = m_drcEngine->GetBoard();
m_itemTree.clear();
m_zones.clear();
m_items.clear();
m_zones.reserve( m_board->Zones().size() );
int errorMax = m_board->GetDesignSettings().m_MaxError;
DRC_CONSTRAINT worstConstraint;
@ -137,7 +136,7 @@ bool DRC_TEST_PROVIDER_MECHANICAL_CLEARANCE::Run()
reportAux( wxT( "Worst clearance : %d nm" ), m_largestClearance );
// This is the number of tests between 2 calls to the progress bar
size_t delta = 50;
size_t delta = 100;
size_t count = 0;
size_t ii = 0;
@ -165,8 +164,6 @@ bool DRC_TEST_PROVIDER_MECHANICAL_CLEARANCE::Run()
if( !reportProgress( ii++, count, delta ) )
return false;
m_items.push_back( item );
LSET layers = item->GetLayerSet();
// Special-case pad holes which pierce all the copper layers
@ -185,6 +182,7 @@ bool DRC_TEST_PROVIDER_MECHANICAL_CLEARANCE::Run()
} );
std::map< std::pair<BOARD_ITEM*, BOARD_ITEM*>, int> checkedPairs;
ii = 0;
if( !m_drcEngine->IsErrorLimitExceeded( DRCE_CLEARANCE )
|| !m_drcEngine->IsErrorLimitExceeded( DRCE_HOLE_CLEARANCE ) )
@ -192,12 +190,11 @@ bool DRC_TEST_PROVIDER_MECHANICAL_CLEARANCE::Run()
if( !reportPhase( _( "Checking mechanical clearances..." ) ) )
return false; // DRC cancelled
ii = 0;
for( BOARD_ITEM* item : m_items )
forEachGeometryItem( itemTypes, LSET::AllLayersMask(),
[&]( BOARD_ITEM* item ) -> bool
{
if( !reportProgress( ii++, m_items.size(), delta ) )
break;
if( !reportProgress( ii++, count, delta ) )
return false;
for( PCB_LAYER_ID layer : item->GetLayerSet().Seq() )
{
@ -210,8 +207,8 @@ bool DRC_TEST_PROVIDER_MECHANICAL_CLEARANCE::Run()
BOARD_ITEM* a = item;
BOARD_ITEM* b = other;
// store canonical order so we don't collide in both directions
// (a:b and b:a)
// store canonical order so we don't collide in both
// directions (a:b and b:a)
if( static_cast<void*>( a ) > static_cast<void*>( b ) )
std::swap( a, b );
@ -228,13 +225,16 @@ bool DRC_TEST_PROVIDER_MECHANICAL_CLEARANCE::Run()
// Visitor:
[&]( BOARD_ITEM* other ) -> bool
{
return testItemAgainstItem( item, itemShape.get(), layer, other );
return testItemAgainstItem( item, itemShape.get(), layer,
other );
},
m_largestClearance );
testItemAgainstZones( item, layer );
}
}
return true;
} );
}
count = 0;

View File

@ -102,11 +102,17 @@ bool DRC_TEST_PROVIDER_SLIVER_CHECKER::Run()
}
}
// The first completion may be a long time coming, so this one gets us started.
zoneLayerCount++;
if( !m_drcEngine->ReportProgress( 1.0 / (double) zoneLayerCount ) )
return false; // DRC cancelled
std::vector<SHAPE_POLY_SET> layerPolys;
layerPolys.resize( layerCount );
std::atomic<size_t> next( 0 );
std::atomic<size_t> done( 0 );
std::atomic<size_t> done( 1 );
std::atomic<size_t> threads_finished( 0 );
size_t parallelThreadCount = std::max<size_t>( std::thread::hardware_concurrency(), 2 );
@ -131,7 +137,9 @@ bool DRC_TEST_PROVIDER_SLIVER_CHECKER::Run()
{
SHAPE_POLY_SET layerPoly = *zone->GetFill( layer );
layerPoly.Unfracture( SHAPE_POLY_SET::PM_FAST );
poly.BooleanAdd( layerPoly, SHAPE_POLY_SET::PM_FAST );
for( int jj = 0; jj < layerPoly.OutlineCount(); ++jj )
poly.AddOutline( layerPoly.Outline( jj ) );
// Report progress on board zones only. Everything
// else is in the noise.

View File

@ -180,8 +180,8 @@ void DRC_TEST_PROVIDER_SOLDER_MASK::buildRTrees()
LSET layers = { 4, F_Mask, B_Mask, F_Cu, B_Cu };
size_t delta = 50; // Number of tests between 2 calls to the progress bar
int itemCount = 0;
int itemIdx = 0;
int count = 0;
int ii = 0;
solderMask->GetFill( F_Mask )->RemoveAllContours();
solderMask->GetFill( B_Mask )->RemoveAllContours();
@ -193,14 +193,14 @@ void DRC_TEST_PROVIDER_SOLDER_MASK::buildRTrees()
forEachGeometryItem( s_allBasicItems, layers,
[&]( BOARD_ITEM* item ) -> bool
{
++itemCount;
++count;
return true;
} );
forEachGeometryItem( s_allBasicItems, layers,
[&]( BOARD_ITEM* item ) -> bool
{
if( !reportProgress( itemIdx++, itemCount, delta ) )
if( !reportProgress( ii++, count, delta ) )
return false;
addItemToRTrees( item );
@ -233,13 +233,13 @@ void DRC_TEST_PROVIDER_SOLDER_MASK::testSilkToMaskClearance()
LSET silkLayers = { 2, F_SilkS, B_SilkS };
size_t delta = 100; // Number of tests between 2 calls to the progress bar
int itemCount = 0;
int itemIdx = 0;
int count = 0;
int ii = 0;
forEachGeometryItem( s_allBasicItems, silkLayers,
[&]( BOARD_ITEM* item ) -> bool
{
++itemCount;
++count;
return true;
} );
@ -249,7 +249,7 @@ void DRC_TEST_PROVIDER_SOLDER_MASK::testSilkToMaskClearance()
if( m_drcEngine->IsErrorLimitExceeded( DRCE_SILK_CLEARANCE ) )
return false;
if( !reportProgress( itemIdx++, itemCount, delta ) )
if( !reportProgress( ii++, count, delta ) )
return false;
if( isInvisibleText( item ) )
@ -559,13 +559,13 @@ void DRC_TEST_PROVIDER_SOLDER_MASK::testMaskBridges()
LSET copperAndMaskLayers = { 4, F_Mask, B_Mask, F_Cu, B_Cu };
size_t delta = 50; // Number of tests between 2 calls to the progress bar
int itemCount = 0;
int itemIdx = 0;
int count = 0;
int ii = 0;
forEachGeometryItem( s_allBasicItemsButZones, copperAndMaskLayers,
[&]( BOARD_ITEM* item ) -> bool
{
++itemCount;
++count;
return true;
} );
@ -575,7 +575,7 @@ void DRC_TEST_PROVIDER_SOLDER_MASK::testMaskBridges()
if( m_drcEngine->IsErrorLimitExceeded( DRCE_SOLDERMASK_BRIDGE ) )
return false;
if( !reportProgress( itemIdx++, itemCount, delta ) )
if( !reportProgress( ii++, count, delta ) )
return false;
EDA_RECT itemBBox = item->GetBoundingBox();