Performance (std::map -> std::unordered_map) and commenting.
This commit is contained in:
parent
03454684fa
commit
792d7babe3
|
@ -75,6 +75,17 @@ struct PTR_PTR_CACHE_KEY
|
|||
}
|
||||
};
|
||||
|
||||
struct PTR_LAYER_CACHE_KEY
|
||||
{
|
||||
BOARD_ITEM* A;
|
||||
PCB_LAYER_ID Layer;
|
||||
|
||||
bool operator==(const PTR_LAYER_CACHE_KEY& other) const
|
||||
{
|
||||
return A == other.A && Layer == other.Layer;
|
||||
}
|
||||
};
|
||||
|
||||
struct PTR_PTR_LAYER_CACHE_KEY
|
||||
{
|
||||
BOARD_ITEM* A;
|
||||
|
@ -98,12 +109,23 @@ namespace std
|
|||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
struct hash<PTR_LAYER_CACHE_KEY>
|
||||
{
|
||||
std::size_t operator()( const PTR_LAYER_CACHE_KEY& k ) const
|
||||
{
|
||||
constexpr std::size_t prime = 19937;
|
||||
|
||||
return hash<void*>()( k.A ) ^ ( hash<int>()( k.Layer ) * prime );
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
struct hash<PTR_PTR_LAYER_CACHE_KEY>
|
||||
{
|
||||
std::size_t operator()( const PTR_PTR_LAYER_CACHE_KEY& k ) const
|
||||
{
|
||||
const std::size_t prime = 19937;
|
||||
constexpr std::size_t prime = 19937;
|
||||
|
||||
return hash<void*>()( k.A ) ^ hash<void*>()( k.B ) ^ ( hash<int>()( k.Layer ) * prime );
|
||||
}
|
||||
|
|
|
@ -29,7 +29,6 @@
|
|||
|
||||
#include <wx/debug.h>
|
||||
|
||||
#include <advanced_config.h>
|
||||
#include <board.h>
|
||||
#include <board_connected_item.h>
|
||||
#include <board_design_settings.h>
|
||||
|
@ -57,6 +56,33 @@
|
|||
- DRCE_CONNECTION_WIDTH
|
||||
*/
|
||||
|
||||
struct NETCODE_LAYER_CACHE_KEY
|
||||
{
|
||||
int Netcode;
|
||||
PCB_LAYER_ID Layer;
|
||||
|
||||
bool operator==(const NETCODE_LAYER_CACHE_KEY& other) const
|
||||
{
|
||||
return Netcode == other.Netcode && Layer == other.Layer;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
namespace std
|
||||
{
|
||||
template <>
|
||||
struct hash<NETCODE_LAYER_CACHE_KEY>
|
||||
{
|
||||
std::size_t operator()( const NETCODE_LAYER_CACHE_KEY& k ) const
|
||||
{
|
||||
constexpr std::size_t prime = 19937;
|
||||
|
||||
return hash<int>()( k.Netcode ) ^ ( hash<int>()( k.Layer ) * prime );
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
class DRC_TEST_PROVIDER_CONNECTION_WIDTH : public DRC_TEST_PROVIDER
|
||||
{
|
||||
public:
|
||||
|
@ -597,7 +623,12 @@ bool DRC_TEST_PROVIDER_CONNECTION_WIDTH::Run()
|
|||
LSET copperLayerSet = m_drcEngine->GetBoard()->GetEnabledLayers() & LSET::AllCuMask();
|
||||
LSEQ copperLayers = copperLayerSet.Seq();
|
||||
BOARD* board = m_drcEngine->GetBoard();
|
||||
DRC_RTREE* tree = board->m_CopperItemRTreeCache.get();
|
||||
|
||||
/*
|
||||
* Build a set of distinct minWidths specified by various DRC rules. We'll run a test for
|
||||
* each distinct minWidth, and then decide if any copper which failed that minWidth actually
|
||||
* was required to abide by it or not.
|
||||
*/
|
||||
std::set<int> distinctMinWidths
|
||||
= m_drcEngine->QueryDistinctConstraints( CONNECTION_WIDTH_CONSTRAINT );
|
||||
|
||||
|
@ -606,11 +637,11 @@ bool DRC_TEST_PROVIDER_CONNECTION_WIDTH::Run()
|
|||
|
||||
struct ITEMS_POLY
|
||||
{
|
||||
std::set<BOARD_ITEM*> items;
|
||||
SHAPE_POLY_SET poly;
|
||||
std::set<BOARD_ITEM*> Items;
|
||||
SHAPE_POLY_SET Poly;
|
||||
};
|
||||
|
||||
std::map< std::pair<int, PCB_LAYER_ID>, ITEMS_POLY > dataset;
|
||||
std::unordered_map<NETCODE_LAYER_CACHE_KEY, ITEMS_POLY> dataset;
|
||||
std::atomic<size_t> done( 1 );
|
||||
|
||||
auto calc_effort =
|
||||
|
@ -634,72 +665,91 @@ bool DRC_TEST_PROVIDER_CONNECTION_WIDTH::Run()
|
|||
return effort;
|
||||
};
|
||||
|
||||
/*
|
||||
* For each net, on each layer, build a polygonSet which contains all the copper associated
|
||||
* with that net on that layer.
|
||||
*/
|
||||
auto build_netlayer_polys =
|
||||
[&]( int aNetcode, const PCB_LAYER_ID aLayer ) -> size_t
|
||||
{
|
||||
if( m_drcEngine->IsCancelled() )
|
||||
return 0;
|
||||
|
||||
ITEMS_POLY& data = dataset[ { aNetcode, aLayer } ];
|
||||
ITEMS_POLY& itemsPoly = dataset[ { aNetcode, aLayer } ];
|
||||
|
||||
for( BOARD_ITEM* item : data.items )
|
||||
for( BOARD_ITEM* item : itemsPoly.Items )
|
||||
{
|
||||
item->TransformShapeWithClearanceToPolygon( data.poly, aLayer, 0,
|
||||
item->TransformShapeWithClearanceToPolygon( itemsPoly.Poly, aLayer, 0,
|
||||
ARC_HIGH_DEF, ERROR_OUTSIDE );
|
||||
}
|
||||
|
||||
data.poly.Fracture( SHAPE_POLY_SET::PM_FAST );
|
||||
itemsPoly.Poly.Fracture( SHAPE_POLY_SET::PM_FAST );
|
||||
|
||||
done.fetch_add( calc_effort( data.items, aLayer ) );
|
||||
done.fetch_add( calc_effort( itemsPoly.Items, aLayer ) );
|
||||
|
||||
return 1;
|
||||
};
|
||||
|
||||
/*
|
||||
* Examine all necks in a given polygonSet which fail a given minWidth.
|
||||
*/
|
||||
auto min_checker =
|
||||
[&]( const ITEMS_POLY& aDataset, const PCB_LAYER_ID aLayer, int aMinWidth ) -> size_t
|
||||
[&]( const ITEMS_POLY& aItemsPoly, const PCB_LAYER_ID aLayer, int aMinWidth ) -> size_t
|
||||
{
|
||||
if( m_drcEngine->IsCancelled() )
|
||||
return 0;
|
||||
|
||||
POLYGON_TEST test( aMinWidth, m_drcEngine->GetDesignSettings()->m_MaxError );
|
||||
|
||||
for( int ii = 0; ii < aDataset.poly.OutlineCount(); ++ii )
|
||||
for( int ii = 0; ii < aItemsPoly.Poly.OutlineCount(); ++ii )
|
||||
{
|
||||
const SHAPE_LINE_CHAIN& chain = aDataset.poly.COutline( ii );
|
||||
const SHAPE_LINE_CHAIN& chain = aItemsPoly.Poly.COutline( ii );
|
||||
|
||||
test.FindPairs( chain );
|
||||
auto& ret = test.GetVertices();
|
||||
|
||||
for( const std::pair<int, int>& pt : ret )
|
||||
{
|
||||
SEG span( chain.CPoint( pt.first ), chain.CPoint( pt.second ) );
|
||||
/*
|
||||
* We've found a neck that fails the given aMinWidth. We now need to know
|
||||
* if the objects the produced the copper at this location are required to
|
||||
* abide by said aMinWidth or not. (If so, we have a violation.)
|
||||
*
|
||||
* We find the contributingItems by hit-testing at the choke point (the
|
||||
* centre point of the neck), and then run the rules engine on those
|
||||
* contributingItems. If the reported constraint matches aMinWidth, then
|
||||
* we've got a violation.
|
||||
*/
|
||||
SEG span( chain.CPoint( pt.first ), chain.CPoint( pt.second ) );
|
||||
VECTOR2I location = ( span.A + span.B ) / 2;
|
||||
int dist = ( span.A - span.B ).EuclideanNorm();
|
||||
std::set<BOARD_ITEM*> nearbyItems = tree->GetObjectsAt( location, aLayer,
|
||||
aMinWidth );
|
||||
int dist = ( span.A - span.B ).EuclideanNorm();
|
||||
|
||||
std::vector<BOARD_ITEM*> items;
|
||||
std::vector<BOARD_ITEM*> contributingItems;
|
||||
|
||||
for( BOARD_ITEM* item : nearbyItems )
|
||||
for( auto* item : board->m_CopperItemRTreeCache->GetObjectsAt( location,
|
||||
aLayer,
|
||||
aMinWidth ) )
|
||||
{
|
||||
if( item->HitTest( location, aMinWidth ) )
|
||||
items.push_back( item );
|
||||
contributingItems.push_back( item );
|
||||
}
|
||||
|
||||
for( auto& [ zone, rtree ] : board->m_CopperZoneRTreeCache )
|
||||
{
|
||||
if( !rtree->GetObjectsAt( location, aLayer, aMinWidth ).empty() &&
|
||||
zone->HitTestFilledArea( aLayer, location, aMinWidth ) )
|
||||
items.push_back( zone );
|
||||
if( !rtree->GetObjectsAt( location, aLayer, aMinWidth ).empty()
|
||||
&& zone->HitTestFilledArea( aLayer, location, aMinWidth ) )
|
||||
{
|
||||
contributingItems.push_back( zone );
|
||||
}
|
||||
}
|
||||
|
||||
if( !items.empty() )
|
||||
if( !contributingItems.empty() )
|
||||
{
|
||||
BOARD_ITEM* item1 = contributingItems[0];
|
||||
BOARD_ITEM* item2 = contributingItems.size() > 1 ? contributingItems[1]
|
||||
: nullptr;
|
||||
DRC_CONSTRAINT c = m_drcEngine->EvalRules( CONNECTION_WIDTH_CONSTRAINT,
|
||||
items[0],
|
||||
items.size() > 1 ? items[1]
|
||||
: nullptr,
|
||||
aLayer );
|
||||
item1, item2, aLayer );
|
||||
|
||||
if( c.Value().Min() == aMinWidth )
|
||||
{
|
||||
|
@ -713,7 +763,7 @@ bool DRC_TEST_PROVIDER_CONNECTION_WIDTH::Run()
|
|||
drce->SetErrorMessage( msg + wxS( " " ) + layerDesc( aLayer ) );
|
||||
drce->SetViolatingRule( c.GetParentRule() );
|
||||
|
||||
for( BOARD_ITEM* item : items )
|
||||
for( BOARD_ITEM* item : contributingItems )
|
||||
drce->AddItem( item );
|
||||
|
||||
reportViolation( drce, location, aLayer );
|
||||
|
@ -722,7 +772,7 @@ bool DRC_TEST_PROVIDER_CONNECTION_WIDTH::Run()
|
|||
}
|
||||
}
|
||||
|
||||
done.fetch_add( calc_effort( aDataset.items, aLayer ) );
|
||||
done.fetch_add( calc_effort( aItemsPoly.Items, aLayer ) );
|
||||
|
||||
return 1;
|
||||
};
|
||||
|
@ -732,7 +782,7 @@ bool DRC_TEST_PROVIDER_CONNECTION_WIDTH::Run()
|
|||
for( ZONE* zone : board->m_DRCCopperZones )
|
||||
{
|
||||
if( !zone->GetIsRuleArea() && zone->IsOnLayer( layer ) )
|
||||
dataset[ { zone->GetNetCode(), layer } ].items.emplace( zone );
|
||||
dataset[ { zone->GetNetCode(), layer } ].Items.emplace( zone );
|
||||
}
|
||||
|
||||
for( PCB_TRACK* track : board->Tracks() )
|
||||
|
@ -740,11 +790,11 @@ bool DRC_TEST_PROVIDER_CONNECTION_WIDTH::Run()
|
|||
if( PCB_VIA* via = dynamic_cast<PCB_VIA*>( track ) )
|
||||
{
|
||||
if( via->FlashLayer( static_cast<int>( layer ) ) )
|
||||
dataset[ { via->GetNetCode(), layer } ].items.emplace( via );
|
||||
dataset[ { via->GetNetCode(), layer } ].Items.emplace( via );
|
||||
}
|
||||
else if( track->IsOnLayer( layer ) )
|
||||
{
|
||||
dataset[ { track->GetNetCode(), layer } ].items.emplace( track );
|
||||
dataset[ { track->GetNetCode(), layer } ].Items.emplace( track );
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -753,7 +803,7 @@ bool DRC_TEST_PROVIDER_CONNECTION_WIDTH::Run()
|
|||
for( PAD* pad : fp->Pads() )
|
||||
{
|
||||
if( pad->FlashLayer( static_cast<int>( layer ) ) )
|
||||
dataset[ { pad->GetNetCode(), layer } ].items.emplace( pad );
|
||||
dataset[ { pad->GetNetCode(), layer } ].Items.emplace( pad );
|
||||
}
|
||||
|
||||
// Footprint zones are also in the m_DRCCopperZones cache
|
||||
|
@ -764,17 +814,16 @@ bool DRC_TEST_PROVIDER_CONNECTION_WIDTH::Run()
|
|||
std::vector<std::future<size_t>> returns;
|
||||
size_t total_effort = 0;
|
||||
|
||||
for( const std::pair<const std::pair<int, PCB_LAYER_ID>, ITEMS_POLY>& netLayer : dataset )
|
||||
total_effort += calc_effort( netLayer.second.items, netLayer.first.second );
|
||||
for( const auto& [ netLayer, itemsPoly ] : dataset )
|
||||
total_effort += calc_effort( itemsPoly.Items, netLayer.Layer );
|
||||
|
||||
total_effort += std::max( (size_t) 1, total_effort ) * distinctMinWidths.size();
|
||||
|
||||
returns.reserve( dataset.size() );
|
||||
|
||||
for( const std::pair<const std::pair<int, PCB_LAYER_ID>, ITEMS_POLY>& netLayer : dataset )
|
||||
for( const auto& [ netLayer, itemsPoly ] : dataset )
|
||||
{
|
||||
returns.emplace_back( tp.submit( build_netlayer_polys, netLayer.first.first,
|
||||
netLayer.first.second ) );
|
||||
returns.emplace_back( tp.submit( build_netlayer_polys, netLayer.Netcode, netLayer.Layer ) );
|
||||
}
|
||||
|
||||
for( std::future<size_t>& retval : returns )
|
||||
|
@ -792,13 +841,10 @@ bool DRC_TEST_PROVIDER_CONNECTION_WIDTH::Run()
|
|||
returns.clear();
|
||||
returns.reserve( dataset.size() * distinctMinWidths.size() );
|
||||
|
||||
for( const std::pair<const std::pair<int, PCB_LAYER_ID>, ITEMS_POLY>& netLayer : dataset )
|
||||
for( const auto& [ netLayer, itemsPoly ] : dataset )
|
||||
{
|
||||
for( int minWidth : distinctMinWidths )
|
||||
{
|
||||
returns.emplace_back( tp.submit( min_checker, netLayer.second, netLayer.first.second,
|
||||
minWidth ) );
|
||||
}
|
||||
returns.emplace_back( tp.submit( min_checker, itemsPoly, netLayer.Layer, minWidth ) );
|
||||
}
|
||||
|
||||
for( std::future<size_t>& retval : returns )
|
||||
|
|
|
@ -864,7 +864,7 @@ void DRC_TEST_PROVIDER_COPPER_CLEARANCE::testZonesToZones()
|
|||
}
|
||||
|
||||
// Iterate through all the segments of refSmoothedPoly
|
||||
std::map<VECTOR2I, int> conflictPoints;
|
||||
std::unordered_map<VECTOR2I, int> conflictPoints;
|
||||
|
||||
for( auto refIt = smoothed_polys[ia].IterateSegmentsWithHoles(); refIt; refIt++ )
|
||||
{
|
||||
|
|
|
@ -167,6 +167,9 @@ bool DRC_TEST_PROVIDER_EDGE_CLEARANCE::Run()
|
|||
|
||||
reportAux( wxT( "Worst clearance : %d nm" ), m_largestEdgeClearance );
|
||||
|
||||
/*
|
||||
* Build an RTree of the various edges (including NPTH holes) and margins found on the board.
|
||||
*/
|
||||
std::vector<std::unique_ptr<PCB_SHAPE>> edges;
|
||||
DRC_RTREE edgesTree;
|
||||
|
||||
|
@ -246,6 +249,9 @@ bool DRC_TEST_PROVIDER_EDGE_CLEARANCE::Run()
|
|||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Test copper and silk items against the set of edges.
|
||||
*/
|
||||
const int progressDelta = 200;
|
||||
int count = 0;
|
||||
int ii = 0;
|
||||
|
|
|
@ -105,7 +105,7 @@ private:
|
|||
// Shapes used to define solder mask apertures don't have nets, so we assign them the
|
||||
// first object+net that bridges their aperture (after which any other nets will generate
|
||||
// violations).
|
||||
std::map< std::pair<BOARD_ITEM*, PCB_LAYER_ID>, std::pair<BOARD_ITEM*, int> > m_maskApertureNetMap;
|
||||
std::unordered_map<PTR_LAYER_CACHE_KEY, std::pair<BOARD_ITEM*, int>> m_maskApertureNetMap;
|
||||
};
|
||||
|
||||
|
||||
|
@ -345,7 +345,7 @@ bool DRC_TEST_PROVIDER_SOLDER_MASK::checkMaskAperture( BOARD_ITEM* aMaskItem, BO
|
|||
return false;
|
||||
}
|
||||
|
||||
std::pair<BOARD_ITEM*, PCB_LAYER_ID> key = { aMaskItem, aTestLayer };
|
||||
PTR_LAYER_CACHE_KEY key = { aMaskItem, aTestLayer };
|
||||
|
||||
auto ii = m_maskApertureNetMap.find( key );
|
||||
|
||||
|
|
Loading…
Reference in New Issue