Thread pad & graphic clearance testing.
This allows us to poll the event loop & update the progress on a time interval rather than on an items-completed interval (the later of which can't easily take host machine performance into account). Also fixes a bug where we'd bail out of QueryColliding if we ever found !testClearance && !testShorting && !testHoles.
This commit is contained in:
parent
8993cd12a6
commit
1e71899611
|
@ -95,7 +95,7 @@ private:
|
|||
|
||||
void testTrackClearances();
|
||||
|
||||
bool testPadAgainstItem( PAD* pad, SHAPE* padShape, PCB_LAYER_ID layer, BOARD_ITEM* other );
|
||||
void testPadAgainstItem( PAD* pad, SHAPE* padShape, PCB_LAYER_ID layer, BOARD_ITEM* other );
|
||||
|
||||
void testPadClearances();
|
||||
|
||||
|
@ -557,16 +557,14 @@ void DRC_TEST_PROVIDER_COPPER_CLEARANCE::testKnockoutTextAgainstZone( BOARD_ITEM
|
|||
|
||||
void DRC_TEST_PROVIDER_COPPER_CLEARANCE::testTrackClearances()
|
||||
{
|
||||
// This is the number of tests between 2 calls to the progress bar
|
||||
const int progressDelta = 100;
|
||||
|
||||
reportAux( wxT( "Testing %d tracks & vias..." ), m_board->Tracks().size() );
|
||||
|
||||
std::map<BOARD_ITEM*, int> freePadsUsageMap;
|
||||
std::unordered_map<PTR_PTR_CACHE_KEY, layers_checked> checkedPairs;
|
||||
std::mutex checkedPairsMutex;
|
||||
std::mutex freePadsUsageMapMutex;
|
||||
std::atomic<int> tracks_checked( 0 );
|
||||
std::atomic<size_t> done( 0 );
|
||||
size_t count = m_board->Tracks().size();
|
||||
|
||||
reportAux( wxT( "Testing %d tracks & vias..." ), count );
|
||||
|
||||
LSET boardCopperLayers = LSET::AllCuMask( m_board->GetCopperLayerCount() );
|
||||
|
||||
|
@ -668,7 +666,7 @@ void DRC_TEST_PROVIDER_COPPER_CLEARANCE::testTrackClearances()
|
|||
}
|
||||
}
|
||||
|
||||
++tracks_checked;
|
||||
done.fetch_add( 1 );
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -676,20 +674,22 @@ void DRC_TEST_PROVIDER_COPPER_CLEARANCE::testTrackClearances()
|
|||
|
||||
tp.push_loop( m_board->Tracks().size(), testTrack );
|
||||
|
||||
while( tracks_checked < static_cast<int>( m_board->Tracks().size() ) )
|
||||
while( done < count )
|
||||
{
|
||||
if( !reportProgress( tracks_checked, m_board->Tracks().size(), progressDelta ) )
|
||||
m_drcEngine->ReportProgress( static_cast<double>( done ) / count );
|
||||
|
||||
if( m_drcEngine->IsCancelled() )
|
||||
{
|
||||
tp.wait_for_tasks();
|
||||
break;
|
||||
}
|
||||
|
||||
std::this_thread::sleep_for( std::chrono::milliseconds( 100 ) );
|
||||
std::this_thread::sleep_for( std::chrono::milliseconds( 250 ) );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
bool DRC_TEST_PROVIDER_COPPER_CLEARANCE::testPadAgainstItem( PAD* pad, SHAPE* padShape,
|
||||
void DRC_TEST_PROVIDER_COPPER_CLEARANCE::testPadAgainstItem( PAD* pad, SHAPE* padShape,
|
||||
PCB_LAYER_ID aLayer,
|
||||
BOARD_ITEM* other )
|
||||
{
|
||||
|
@ -763,7 +763,7 @@ bool DRC_TEST_PROVIDER_COPPER_CLEARANCE::testPadAgainstItem( PAD* pad, SHAPE* pa
|
|||
}
|
||||
|
||||
if( !testClearance && !testShorting && !testHoles )
|
||||
return false;
|
||||
return;
|
||||
|
||||
std::shared_ptr<SHAPE> otherShape = other->GetEffectiveShape( aLayer );
|
||||
DRC_CONSTRAINT constraint;
|
||||
|
@ -779,12 +779,12 @@ bool DRC_TEST_PROVIDER_COPPER_CLEARANCE::testPadAgainstItem( PAD* pad, SHAPE* pa
|
|||
if( testShorting )
|
||||
{
|
||||
if( pad->GetNetCode() == 0 || pad->GetNetCode() == otherPad->GetNetCode() )
|
||||
return !m_drcEngine->IsCancelled();
|
||||
return;
|
||||
|
||||
if( pad->GetShortNetname().StartsWith( wxS( "unconnected-(" ) )
|
||||
&& otherPad->GetShortNetname().StartsWith( wxS( "unconnected-(" ) ) )
|
||||
{
|
||||
return !m_drcEngine->IsCancelled();
|
||||
return;
|
||||
}
|
||||
|
||||
std::shared_ptr<DRC_ITEM> drce = DRC_ITEM::Create( DRCE_SHORTING_ITEMS );
|
||||
|
@ -800,7 +800,7 @@ bool DRC_TEST_PROVIDER_COPPER_CLEARANCE::testPadAgainstItem( PAD* pad, SHAPE* pa
|
|||
reportViolation( drce, otherPad->GetPosition(), aLayer );
|
||||
}
|
||||
|
||||
return !m_drcEngine->IsCancelled();
|
||||
return;
|
||||
}
|
||||
|
||||
if( testClearance || testShorting )
|
||||
|
@ -923,15 +923,15 @@ bool DRC_TEST_PROVIDER_COPPER_CLEARANCE::testPadAgainstItem( PAD* pad, SHAPE* pa
|
|||
}
|
||||
}
|
||||
|
||||
return !m_drcEngine->IsCancelled();
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
void DRC_TEST_PROVIDER_COPPER_CLEARANCE::testPadClearances( )
|
||||
{
|
||||
const int progressDelta = 100;
|
||||
size_t count = 0;
|
||||
int ii = 0;
|
||||
thread_pool& tp = GetKiCadThreadPool();
|
||||
size_t count = 0;
|
||||
std::atomic<size_t> done( 1 );
|
||||
|
||||
for( FOOTPRINT* footprint : m_board->Footprints() )
|
||||
count += footprint->Pads().size();
|
||||
|
@ -942,67 +942,80 @@ void DRC_TEST_PROVIDER_COPPER_CLEARANCE::testPadClearances( )
|
|||
|
||||
LSET boardCopperLayers = LSET::AllCuMask( m_board->GetCopperLayerCount() );
|
||||
|
||||
for( FOOTPRINT* footprint : m_board->Footprints() )
|
||||
{
|
||||
for( PAD* pad : footprint->Pads() )
|
||||
{
|
||||
for( PCB_LAYER_ID layer : LSET( pad->GetLayerSet() & boardCopperLayers ).Seq() )
|
||||
std::future<void> retn = tp.submit(
|
||||
[&]()
|
||||
{
|
||||
std::shared_ptr<SHAPE> padShape = pad->GetEffectiveShape( layer );
|
||||
|
||||
m_board->m_CopperItemRTreeCache->QueryColliding( pad, layer, layer,
|
||||
// Filter:
|
||||
[&]( BOARD_ITEM* other ) -> bool
|
||||
{
|
||||
BOARD_ITEM* a = pad;
|
||||
BOARD_ITEM* b = other;
|
||||
|
||||
// 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 );
|
||||
|
||||
if( checkedPairs.find( { a, b } ) != checkedPairs.end() )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
checkedPairs[ { a, b } ] = 1;
|
||||
return true;
|
||||
}
|
||||
},
|
||||
// Visitor
|
||||
[&]( BOARD_ITEM* other ) -> bool
|
||||
{
|
||||
return testPadAgainstItem( pad, padShape.get(), layer, other );
|
||||
},
|
||||
m_board->m_DRCMaxClearance );
|
||||
|
||||
for( ZONE* zone : m_board->m_DRCCopperZones )
|
||||
for( FOOTPRINT* footprint : m_board->Footprints() )
|
||||
{
|
||||
testItemAgainstZone( pad, zone, layer );
|
||||
for( PAD* pad : footprint->Pads() )
|
||||
{
|
||||
for( PCB_LAYER_ID layer : LSET( pad->GetLayerSet() & boardCopperLayers ).Seq() )
|
||||
{
|
||||
if( m_drcEngine->IsCancelled() )
|
||||
return;
|
||||
|
||||
if( m_drcEngine->IsCancelled() )
|
||||
return;
|
||||
std::shared_ptr<SHAPE> padShape = pad->GetEffectiveShape( layer );
|
||||
|
||||
m_board->m_CopperItemRTreeCache->QueryColliding( pad, layer, layer,
|
||||
// Filter:
|
||||
[&]( BOARD_ITEM* other ) -> bool
|
||||
{
|
||||
BOARD_ITEM* a = pad;
|
||||
BOARD_ITEM* b = other;
|
||||
|
||||
// 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 );
|
||||
|
||||
if( checkedPairs.find( { a, b } ) != checkedPairs.end() )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
checkedPairs[ { a, b } ] = 1;
|
||||
return true;
|
||||
}
|
||||
},
|
||||
// Visitor
|
||||
[&]( BOARD_ITEM* other ) -> bool
|
||||
{
|
||||
testPadAgainstItem( pad, padShape.get(), layer, other );
|
||||
|
||||
return !m_drcEngine->IsCancelled();
|
||||
},
|
||||
m_board->m_DRCMaxClearance );
|
||||
|
||||
for( ZONE* zone : m_board->m_DRCCopperZones )
|
||||
{
|
||||
testItemAgainstZone( pad, zone, layer );
|
||||
|
||||
if( m_drcEngine->IsCancelled() )
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
done.fetch_add( 1 );
|
||||
}
|
||||
}
|
||||
}
|
||||
} );
|
||||
|
||||
if( !reportProgress( ii++, (int) count, progressDelta ) )
|
||||
return;
|
||||
}
|
||||
std::future_status status = retn.wait_for( std::chrono::milliseconds( 250 ) );
|
||||
|
||||
if( m_drcEngine->IsCancelled() )
|
||||
return;
|
||||
while( status != std::future_status::ready )
|
||||
{
|
||||
m_drcEngine->ReportProgress( static_cast<double>( done ) / count );
|
||||
status = retn.wait_for( std::chrono::milliseconds( 250 ) );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void DRC_TEST_PROVIDER_COPPER_CLEARANCE::testGraphicClearances( )
|
||||
{
|
||||
const int progressDelta = 100;
|
||||
size_t count = m_board->Drawings().size();
|
||||
int ii = 0;
|
||||
thread_pool& tp = GetKiCadThreadPool();
|
||||
size_t count = m_board->Drawings().size();
|
||||
std::atomic<size_t> done( 1 );
|
||||
|
||||
for( FOOTPRINT* footprint : m_board->Footprints() )
|
||||
count += footprint->GraphicalItems().size();
|
||||
|
@ -1110,53 +1123,65 @@ void DRC_TEST_PROVIDER_COPPER_CLEARANCE::testGraphicClearances( )
|
|||
m_board->m_DRCMaxClearance );
|
||||
};
|
||||
|
||||
for( BOARD_ITEM* item : m_board->Drawings() )
|
||||
std::future<void> retn = tp.submit(
|
||||
[&]()
|
||||
{
|
||||
for( BOARD_ITEM* item : m_board->Drawings() )
|
||||
{
|
||||
testGraphicAgainstZone( item );
|
||||
|
||||
if( item->Type() == PCB_SHAPE_T && item->IsOnCopperLayer() )
|
||||
testCopperGraphic( static_cast<PCB_SHAPE*>( item ) );
|
||||
|
||||
done.fetch_add( 1 );
|
||||
|
||||
if( m_drcEngine->IsCancelled() )
|
||||
break;
|
||||
}
|
||||
|
||||
for( FOOTPRINT* footprint : m_board->Footprints() )
|
||||
{
|
||||
for( BOARD_ITEM* item : footprint->GraphicalItems() )
|
||||
{
|
||||
testGraphicAgainstZone( item );
|
||||
|
||||
done.fetch_add( 1 );
|
||||
|
||||
if( m_drcEngine->IsCancelled() )
|
||||
break;
|
||||
}
|
||||
}
|
||||
} );
|
||||
|
||||
std::future_status status = retn.wait_for( std::chrono::milliseconds( 250 ) );
|
||||
|
||||
while( status != std::future_status::ready )
|
||||
{
|
||||
testGraphicAgainstZone( item );
|
||||
|
||||
if( item->Type() == PCB_SHAPE_T && item->IsOnCopperLayer() )
|
||||
testCopperGraphic( static_cast<PCB_SHAPE*>( item ) );
|
||||
|
||||
if( !reportProgress( ii++, (int) count, progressDelta ) )
|
||||
return;
|
||||
}
|
||||
|
||||
for( FOOTPRINT* footprint : m_board->Footprints() )
|
||||
{
|
||||
for( BOARD_ITEM* item : footprint->GraphicalItems() )
|
||||
{
|
||||
testGraphicAgainstZone( item );
|
||||
|
||||
if( !reportProgress( ii++, (int) count, progressDelta ) )
|
||||
return;
|
||||
}
|
||||
m_drcEngine->ReportProgress( static_cast<double>( done ) / count );
|
||||
status = retn.wait_for( std::chrono::milliseconds( 250 ) );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void DRC_TEST_PROVIDER_COPPER_CLEARANCE::testZonesToZones()
|
||||
{
|
||||
const int progressDelta = 50;
|
||||
bool testClearance = !m_drcEngine->IsErrorLimitExceeded( DRCE_CLEARANCE );
|
||||
bool testIntersects = !m_drcEngine->IsErrorLimitExceeded( DRCE_ZONES_INTERSECT );
|
||||
DRC_CONSTRAINT constraint;
|
||||
|
||||
bool testClearance = !m_drcEngine->IsErrorLimitExceeded( DRCE_CLEARANCE );
|
||||
bool testIntersects = !m_drcEngine->IsErrorLimitExceeded( DRCE_ZONES_INTERSECT );
|
||||
|
||||
DRC_CONSTRAINT constraint;
|
||||
bool cancelled = false;
|
||||
std::vector<std::map<PCB_LAYER_ID, std::vector<SEG>>> poly_segments;
|
||||
|
||||
poly_segments.resize( m_board->m_DRCCopperZones.size() );
|
||||
|
||||
// Contains the index for zoneA, zoneB, the conflict point, the actual clearance, the
|
||||
// required clearance, and the layer
|
||||
using report_data = std::tuple<int, int, VECTOR2I, int, int, PCB_LAYER_ID>;
|
||||
const int invalid_zone = -1;
|
||||
|
||||
std::vector<std::future<report_data>> futures;
|
||||
thread_pool& tp = GetKiCadThreadPool();
|
||||
thread_pool& tp = GetKiCadThreadPool();
|
||||
std::atomic<size_t> done( 1 );
|
||||
|
||||
auto checkZones =
|
||||
[testClearance, testIntersects, &poly_segments, &cancelled, invalid_zone]
|
||||
[this, testClearance, testIntersects, &poly_segments, &done]
|
||||
( int zoneA, int zoneB, int clearance, PCB_LAYER_ID layer ) -> report_data
|
||||
{
|
||||
// Iterate through all the segments of refSmoothedPoly
|
||||
|
@ -1165,8 +1190,7 @@ void DRC_TEST_PROVIDER_COPPER_CLEARANCE::testZonesToZones()
|
|||
std::vector<SEG>& refSegments = poly_segments[zoneA][layer];
|
||||
std::vector<SEG>& testSegments = poly_segments[zoneB][layer];
|
||||
bool reported = false;
|
||||
auto invalid_result = std::make_tuple( invalid_zone, invalid_zone, VECTOR2I(),
|
||||
0, 0, F_Cu );
|
||||
auto invalid_result = std::make_tuple( -1, -1, VECTOR2I(), 0, 0, F_Cu );
|
||||
|
||||
for( SEG& refSegment : refSegments )
|
||||
{
|
||||
|
@ -1204,14 +1228,18 @@ void DRC_TEST_PROVIDER_COPPER_CLEARANCE::testZonesToZones()
|
|||
reported = true;
|
||||
|
||||
if( reported )
|
||||
{
|
||||
done.fetch_add( 1 );
|
||||
return std::make_tuple( zoneA, zoneB, pt, d, clearance, layer );
|
||||
}
|
||||
}
|
||||
|
||||
if( cancelled )
|
||||
if( m_drcEngine->IsCancelled() )
|
||||
return invalid_result;
|
||||
}
|
||||
}
|
||||
|
||||
done.fetch_add( 1 );
|
||||
return invalid_result;
|
||||
};
|
||||
|
||||
|
@ -1229,10 +1257,10 @@ void DRC_TEST_PROVIDER_COPPER_CLEARANCE::testZonesToZones()
|
|||
if( m_board->m_DRCCopperZones[ii]->IsOnLayer( layer ) )
|
||||
{
|
||||
SHAPE_POLY_SET poly = *m_board->m_DRCCopperZones[ii]->GetFilledPolysList( layer );
|
||||
std::vector<SEG>& poly_segs = poly_segments[ii][layer];
|
||||
std::vector<SEG>& zone_layer_poly_segs = poly_segments[ii][layer];
|
||||
|
||||
poly.BuildBBoxCaches();
|
||||
poly_segs.reserve( poly.FullPointCount() );
|
||||
zone_layer_poly_segs.reserve( poly.FullPointCount() );
|
||||
|
||||
for( auto it = poly.IterateSegmentsWithHoles(); it; it++ )
|
||||
{
|
||||
|
@ -1241,10 +1269,10 @@ void DRC_TEST_PROVIDER_COPPER_CLEARANCE::testZonesToZones()
|
|||
if( seg.A.x > seg.B.x )
|
||||
seg.Reverse();
|
||||
|
||||
poly_segs.push_back( seg );
|
||||
zone_layer_poly_segs.push_back( seg );
|
||||
}
|
||||
|
||||
std::sort( poly_segs.begin(), poly_segs.end() );
|
||||
std::sort( zone_layer_poly_segs.begin(), zone_layer_poly_segs.end() );
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1252,12 +1280,6 @@ void DRC_TEST_PROVIDER_COPPER_CLEARANCE::testZonesToZones()
|
|||
|
||||
for( size_t ia = 0; ia < m_board->m_DRCCopperZones.size(); ia++ )
|
||||
{
|
||||
if( !reportProgress( layer_id * m_board->m_DRCCopperZones.size() + ia,
|
||||
B_Cu * m_board->m_DRCCopperZones.size(), progressDelta ) )
|
||||
{
|
||||
return; // DRC cancelled
|
||||
}
|
||||
|
||||
ZONE* zoneA = m_board->m_DRCCopperZones[ia];
|
||||
|
||||
if( !zoneA->IsOnLayer( layer ) )
|
||||
|
@ -1298,6 +1320,8 @@ void DRC_TEST_PROVIDER_COPPER_CLEARANCE::testZonesToZones()
|
|||
}
|
||||
}
|
||||
|
||||
size_t count = futures.size();
|
||||
|
||||
for( auto& task : futures )
|
||||
{
|
||||
if( !task.valid() )
|
||||
|
@ -1307,28 +1331,27 @@ void DRC_TEST_PROVIDER_COPPER_CLEARANCE::testZonesToZones()
|
|||
|
||||
while( true )
|
||||
{
|
||||
result = task.wait_for( std::chrono::milliseconds( 200 ) );
|
||||
result = task.wait_for( std::chrono::milliseconds( 250 ) );
|
||||
|
||||
m_drcEngine->ReportProgress( static_cast<double>( done ) / count );
|
||||
|
||||
if( m_drcEngine->IsCancelled() )
|
||||
{
|
||||
cancelled = true;
|
||||
break;
|
||||
}
|
||||
|
||||
if( result == std::future_status::ready )
|
||||
{
|
||||
report_data data = task.get();
|
||||
int zoneA_id = std::get<0>( data );
|
||||
int zoneB_id = std::get<1>( data );
|
||||
VECTOR2I pt = std::get<2>( data );
|
||||
int actual = std::get<3>( data );
|
||||
int required = std::get<4>( data );
|
||||
report_data data = task.get();
|
||||
int zoneA_idx = std::get<0>( data );
|
||||
int zoneB_idx = std::get<1>( data );
|
||||
VECTOR2I pt = std::get<2>( data );
|
||||
int actual = std::get<3>( data );
|
||||
int required = std::get<4>( data );
|
||||
PCB_LAYER_ID layer = std::get<5>( data );
|
||||
|
||||
if( zoneA_id != invalid_zone )
|
||||
if( zoneA_idx >= 0 )
|
||||
{
|
||||
ZONE* zoneA = m_board->m_DRCCopperZones[zoneA_id];
|
||||
ZONE* zoneB = m_board->m_DRCCopperZones[zoneB_id];
|
||||
ZONE* zoneA = m_board->m_DRCCopperZones[zoneA_idx];
|
||||
ZONE* zoneB = m_board->m_DRCCopperZones[zoneB_idx];
|
||||
|
||||
constraint = m_drcEngine->EvalRules( CLEARANCE_CONSTRAINT, zoneA, zoneB, layer );
|
||||
std::shared_ptr<DRC_ITEM> drce;
|
||||
|
@ -1359,7 +1382,6 @@ void DRC_TEST_PROVIDER_COPPER_CLEARANCE::testZonesToZones()
|
|||
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue