64 virtual bool Run()
override;
66 virtual const wxString
GetName()
const override
68 return wxT(
"diff_pair_coupling" );
73 return wxT(
"Tests differential pair coupling" );
88 int64_t t_b = p.
TCoef( p.
B );
90 int64_t tproj_a = p.
TCoef( n_proj_p.
A );
91 int64_t tproj_b = p.
TCoef( n_proj_p.
B );
94 std::swap( t_b, t_a );
96 if( tproj_b < tproj_a )
97 std::swap( tproj_b, tproj_a );
106 std::vector<int64_t> tv( t, t + 4 );
107 std::sort( tv.begin(), tv.end() );
112 pClip.
A.
x = p.
A.
x +
rescale( (int64_t)dp.
x, tv[1], pLenSq );
113 pClip.
A.
y = p.
A.
y +
rescale( (int64_t)dp.
y, tv[1], pLenSq );
115 pClip.
B.
x = p.
A.
x +
rescale( (int64_t)dp.
x, tv[2], pLenSq );
116 pClip.
B.
y = p.
A.
y +
rescale( (int64_t)dp.
y, tv[2], pLenSq );
184 std::vector<DIFF_PAIR_COUPLED_SEGMENTS>
coupled;
195 PCB_TRACK* sp = dyn_cast<PCB_TRACK*>( itemP );
196 std::optional<DIFF_PAIR_COUPLED_SEGMENTS> bestCoupled;
197 int bestGap = std::numeric_limits<int>::max();
204 PCB_TRACK* sn = dyn_cast<PCB_TRACK*> ( itemN );
244 if( aItem == bestCoupled->parentN || aItem == bestCoupled->parentP )
253 if( bci->GetNetCode() == bestCoupled->parentN->GetNetCode()
254 || bci->GetNetCode() == bestCoupled->parentP->GetNetCode() )
261 SHAPE_SEGMENT checkSegStart( bestCoupled->coupledP.A, bestCoupled->coupledN.A );
262 SHAPE_SEGMENT checkSegEnd( bestCoupled->coupledP.B, bestCoupled->coupledN.B );
263 DRC_RTREE* tree = bestCoupled->parentP->GetBoard()->m_CopperItemRTreeCache.get();
271 aDp.
coupled.push_back( *bestCoupled );
285 std::map<DIFF_PAIR_KEY, DIFF_PAIR_ITEMS> dpRuleMatches;
287 auto evaluateDpConstraints =
296 drc_dbg( 10, wxT(
"eval dp %p\n" ), item );
303 for(
int i = 0; i < 2; i++ )
312 drc_dbg( 10, wxT(
"cns %d item %p\n" ), constraintsToCheck[i], item );
315 wxString ruleName = parentRule ? parentRule->
m_Name : constraint.
GetName();
317 switch( constraintsToCheck[i] )
336 dpRuleMatches[key].itemsN.insert( citem );
338 dpRuleMatches[key].itemsP.insert( citem );
348 evaluateDpConstraints );
350 drc_dbg( 10, wxT(
"dp rule matches %d\n" ), (
int) dpRuleMatches.size() );
354 for(
auto& [ key, itemSet ] : dpRuleMatches )
365 reportAux( wxString::Format( wxT(
"Rule '%s', DP: (+) %s - (-) %s" ),
366 key.gapRuleName, nameP, nameN ) );
370 itemSet.totalCoupled = 0;
371 itemSet.totalLengthN = 0;
372 itemSet.totalLengthP = 0;
374 drc_dbg(10, wxT(
" coupled prims : %d\n" ), (
int) itemSet.coupled.size() );
379 if(
PCB_TRACK* track = dyn_cast<PCB_TRACK*>( item ) )
380 itemSet.totalLengthN += track->GetLength();
386 if(
PCB_TRACK* track = dyn_cast<PCB_TRACK*>( item ) )
387 itemSet.totalLengthP += track->GetLength();
409 overlay->SetLineWidth( 100000 );
415 drc_dbg( 10, wxT(
" len %d gap %d l %d\n" ),
420 if( key.gapConstraint )
422 if( key.gapConstraint->HasMin()
423 && key.gapConstraint->Min() >= 0
424 && ( gap < key.gapConstraint->Min() - epsilon ) )
429 if( key.gapConstraint->HasMax()
430 && key.gapConstraint->Max() >= 0
431 && ( gap > key.gapConstraint->Max() + epsilon ) )
438 itemSet.totalCoupled += length;
441 int totalLen = std::max( itemSet.totalLengthN, itemSet.totalLengthP );
442 reportAux( wxString::Format( wxT(
" - coupled length: %s, total length: %s" ),
446 int totalUncoupled = totalLen - itemSet.totalCoupled;
448 bool uncoupledViolation =
false;
450 if( key.uncoupledConstraint && ( !itemSet.itemsP.empty() || !itemSet.itemsN.empty() ) )
454 if( val.
HasMax() && val.
Max() >= 0 && totalUncoupled > val.
Max() )
457 wxString msg =
formatMsg(
_(
"(%s maximum uncoupled length %s; actual %s)" ),
458 key.uncoupledRuleName,
462 drce->SetErrorMessage( drce->GetErrorText() + wxS(
" " ) + msg );
465 auto p_it = itemSet.itemsP.begin();
466 auto n_it = itemSet.itemsN.begin();
468 if( p_it != itemSet.itemsP.end() )
471 drce->AddItem( *p_it );
475 if( n_it != itemSet.itemsN.end() )
478 drce->AddItem( *n_it );
482 while( p_it != itemSet.itemsP.end() )
483 drce->AddItem( *p_it++ );
485 while( n_it != itemSet.itemsN.end() )
486 drce->AddItem( *n_it++ );
488 uncoupledViolation =
true;
490 drce->SetViolatingRule( key.uncoupledRule );
496 if( key.gapConstraint && ( uncoupledViolation || !key.uncoupledConstraint ) )
525 msg =
formatMsg(
_(
"(%s minimum gap %s; actual %s)" ),
532 msg =
formatMsg(
_(
"(%s maximum gap %s; actual %s)" ),
538 drcItem->SetErrorMessage( drcItem->GetErrorText() + wxS(
" " ) + msg );
545 drcItem->AddItem( dp.
parentP );
551 drcItem->AddItem( dp.
parentN );
554 drcItem->SetViolatingRule( key.gapRule );
A base class derived from BOARD_ITEM for items that can be connected and have a net,...
NETINFO_ITEM * GetNet() const
Return #NET_INFO object for a given item.
int GetDRCEpsilon() const
A base class for any item which can be embedded within the BOARD container class, and therefore insta...
virtual PCB_LAYER_ID GetLayer() const
Return the primary layer this item is on.
virtual LSET GetLayerSet() const
Return a std::bitset of all layers on which the item physically resides.
Information pertinent to a Pcbnew printed circuit board.
const NETINFO_LIST & GetNetInfo() const
BOARD_DESIGN_SETTINGS & GetDesignSettings() const
std::shared_ptr< CONNECTIVITY_DATA > GetConnectivity() const
Return a list of missing connections between components/tracks.
SEVERITY GetSeverity() const
const MINOPTMAX< int > & GetValue() const
DRC_RULE * GetParentRule() const
std::shared_ptr< KIGFX::VIEW_OVERLAY > GetDebugOverlay() const
DRC_CONSTRAINT EvalRules(DRC_CONSTRAINT_T aConstraintType, const BOARD_ITEM *a, const BOARD_ITEM *b, PCB_LAYER_ID aLayer, REPORTER *aReporter=nullptr)
static bool IsNetADiffPair(BOARD *aBoard, NETINFO_ITEM *aNet, int &aNetP, int &aNetN)
static std::shared_ptr< DRC_ITEM > Create(int aErrorCode)
Constructs a DRC_ITEM for the given error code.
Implement an R-tree for fast spatial and layer indexing of connectable items.
bool CheckColliding(SHAPE *aRefShape, PCB_LAYER_ID aTargetLayer, int aClearance=0, std::function< bool(BOARD_ITEM *)> aFilter=nullptr) const
Represent a DRC "provider" which runs some DRC functions over a BOARD and spits out DRC_ITEM and posi...
int forEachGeometryItem(const std::vector< KICAD_T > &aTypes, LSET aLayers, const std::function< bool(BOARD_ITEM *)> &aFunc)
virtual void reportViolation(std::shared_ptr< DRC_ITEM > &item, const VECTOR2I &aMarkerPos, int aMarkerLayer)
void reportAux(const wxString &aMsg)
wxString formatMsg(const wxString &aFormatString, const wxString &aSource, int aConstraint, int aActual)
virtual void reportRuleStatistics()
virtual VECTOR2I GetPosition() const
static LSET AllCuMask(int aCuLayerCount=MAX_CU_LAYERS)
Return a mask holding the requested number of Cu PCB_LAYER_IDs.
Handle the data for a net.
const wxString & GetNetname() const
NETINFO_ITEM * GetNetItem(int aNetCode) const
const VECTOR2I & GetStart() const
const VECTOR2I & GetEnd() const
int Length() const
Return the length (this).
bool ApproxParallel(const SEG &aSeg, int aDistanceThreshold=1) const
ecoord TCoef(const VECTOR2I &aP) const
ecoord SquaredLength() const
int Distance(const SEG &aSeg) const
Compute minimum Euclidean distance to segment aSeg.
VECTOR2I LineProject(const VECTOR2I &aP) const
Compute the perpendicular projection point of aP on a line passing through ends of the segment.
wxString MessageTextFromValue(double aValue, bool aAddUnitLabel=true, EDA_DATA_TYPE aType=EDA_DATA_TYPE::DISTANCE)
A lower-precision version of StringFromValue().
DRC_TEST_PROVIDER_DIFF_PAIR_COUPLING()
virtual const wxString GetName() const override
virtual const wxString GetDescription() const override
virtual bool Run() override
Run this provider against the given PCB with configured options (if any).
virtual ~DRC_TEST_PROVIDER_DIFF_PAIR_COUPLING()
#define drc_dbg(level, fmt,...)
@ DRCE_DIFF_PAIR_GAP_OUT_OF_RANGE
@ DRCE_DIFF_PAIR_UNCOUPLED_LENGTH_TOO_LONG
@ DIFF_PAIR_MAX_UNCOUPLED_CONSTRAINT
@ DIFF_PAIR_GAP_CONSTRAINT
static bool commonParallelProjection(SEG p, SEG n, SEG &pClip, SEG &nClip)
static void extractDiffPairCoupledItems(DIFF_PAIR_ITEMS &aDp)
PCB_LAYER_ID
A quick note on layer IDs:
std::shared_ptr< PNS_LOG_VIEWER_OVERLAY > overlay
std::vector< FAB_LAYER_COLOR > dummy
DIFF_PAIR_COUPLED_SEGMENTS()
std::set< BOARD_CONNECTED_ITEM * > itemsN
std::vector< DIFF_PAIR_COUPLED_SEGMENTS > coupled
std::set< BOARD_CONNECTED_ITEM * > itemsP
wxString uncoupledRuleName
std::optional< MINOPTMAX< int > > uncoupledConstraint
std::optional< MINOPTMAX< int > > gapConstraint
bool operator<(const DIFF_PAIR_KEY &b) const
double EuclideanNorm(const VECTOR2I &vector)
@ PCB_VIA_T
class PCB_VIA, a via (like a track segment on a copper layer)
@ PCB_ARC_T
class PCB_ARC, an arc track segment on a copper layer
@ PCB_TRACE_T
class PCB_TRACK, a track segment (segment on a copper layer)
T rescale(T aNumerator, T aValue, T aDenominator)
Scale a number (value) by rational (numerator/denominator).