KiCad PCB EDA Suite
Loading...
Searching...
No Matches
pns_diff_pair.h
Go to the documentation of this file.
1/*
2 * KiRouter - a push-and-(sometimes-)shove PCB router
3 *
4 * Copyright (C) 2013-2015 CERN
5 * Copyright (C) 2016-2023 KiCad Developers, see AUTHORS.txt for contributors.
6 * Author: Tomasz Wlostowski <[email protected]>
7 *
8 * This program is free software: you can redistribute it and/or modify it
9 * under the terms of the GNU General Public License as published by the
10 * Free Software Foundation, either version 3 of the License, or (at your
11 * option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful, but
14 * WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License along
19 * with this program. If not, see <http://www.gnu.org/licenses/>.
20 */
21
22
23#ifndef __PNS_DIFF_PAIR_H
24#define __PNS_DIFF_PAIR_H
25
26#include <vector>
27
28#include "pns_line.h"
29#include "pns_via.h"
30#include "pns_link_holder.h"
31
32#include "ranged_num.h"
33
34namespace PNS {
35
36class DIFF_PAIR;
37
44{
45public:
46 DP_GATEWAY( const VECTOR2I& aAnchorP, const VECTOR2I& aAnchorN, bool aIsDiagonal,
47 int aAllowedEntryAngles = DIRECTION_45::ANG_OBTUSE, int aPriority = 0 ) :
48 m_anchorP( aAnchorP ),
49 m_anchorN( aAnchorN ), m_isDiagonal( aIsDiagonal ),
50 m_allowedEntryAngles( aAllowedEntryAngles ), m_priority( aPriority )
51 {
52 m_hasEntryLines = false;
53 }
54
56 {
57 }
58
62 bool IsDiagonal() const
63 {
64 return m_isDiagonal;
65 }
66
67 const VECTOR2I& AnchorP() const { return m_anchorP; }
68
69 const VECTOR2I& AnchorN() const { return m_anchorN; }
70
74 int AllowedAngles () const { return m_allowedEntryAngles; }
75
79 int Priority() const
80 {
81 return m_priority;
82 }
83
84 void SetPriority(int aPriority)
85 {
86 m_priority = aPriority;
87 }
88
89 void SetEntryLines( const SHAPE_LINE_CHAIN& aEntryP, const SHAPE_LINE_CHAIN& aEntryN )
90 {
91 m_entryP = aEntryP;
92 m_entryN = aEntryN;
93 m_hasEntryLines = true;
94 }
95
96 const SHAPE_LINE_CHAIN& EntryP() const { return m_entryP; }
97 const SHAPE_LINE_CHAIN& EntryN() const { return m_entryN; }
98 const DIFF_PAIR Entry() const ;
99
100 void Reverse();
101
102 bool HasEntryLines () const
103 {
104 return m_hasEntryLines;
105 }
106
107private:
114};
115
120{
121public:
123 m_primP( nullptr ), m_primN( nullptr ) {};
124
125 DP_PRIMITIVE_PAIR( const DP_PRIMITIVE_PAIR& aOther );
126 DP_PRIMITIVE_PAIR( ITEM* aPrimP, ITEM* aPrimN );
127 DP_PRIMITIVE_PAIR( const VECTOR2I& aAnchorP, const VECTOR2I& aAnchorN );
128
130
131 void SetAnchors( const VECTOR2I& aAnchorP, const VECTOR2I& aAnchorN );
132
133 const VECTOR2I& AnchorP() const { return m_anchorP; }
134 const VECTOR2I& AnchorN() const { return m_anchorN; }
135
137
138 ITEM* PrimP() const { return m_primP; }
139 ITEM* PrimN() const { return m_primN; }
140
141 bool Directional() const;
142
143 DIRECTION_45 DirP() const;
144 DIRECTION_45 DirN() const;
145
146
147 void CursorOrientation( const VECTOR2I& aCursorPos, VECTOR2I& aMidpoint,
148 VECTOR2I& aDirection ) const;
149
150 void dump()
151 {
152 printf( "-- Prim-P %p anchor [%d, %d]\n", m_primP, m_anchorP.x, m_anchorP.y );
153 printf( "-- Prim-N %p anchor [%d, %d]\n", m_primN, m_anchorN.x, m_anchorN.y );
154 }
155
156private:
157 DIRECTION_45 anchorDirection( const ITEM* aItem, const VECTOR2I& aP ) const;
158
162};
163
168{
169public:
170 DP_GATEWAYS( int aGap ):
171 m_gap( aGap ),
172 m_viaGap( aGap )
173 {
174 // Do not leave uninitialized members, and keep static analyzer quiet:
175 m_viaDiameter = 0;
176 m_fitVias = true;
177 }
178
179 void Clear() { m_gateways.clear(); }
180
181 void SetFitVias( bool aEnable, int aDiameter = 0, int aViaGap = -1 )
182 {
183 m_fitVias = aEnable;
184 m_viaDiameter = aDiameter;
185
186 if( aViaGap < 0 )
187 m_viaGap = m_gap;
188 else
189 m_viaGap = aViaGap;
190 }
191
192
193 void BuildForCursor( const VECTOR2I& aCursorPos );
194 void BuildOrthoProjections( DP_GATEWAYS& aEntries, const VECTOR2I& aCursorPos,
195 int aOrthoScore );
196 void BuildGeneric( const VECTOR2I& p0_p, const VECTOR2I& p0_n, bool aBuildEntries = false,
197 bool aViaMode = false );
198 void BuildFromPrimitivePair( const DP_PRIMITIVE_PAIR& aPair, bool aPreferDiagonal );
199
200 bool FitGateways( DP_GATEWAYS& aEntry, DP_GATEWAYS& aTarget, bool aPrefDiagonal,
201 DIFF_PAIR& aDp );
202
203 std::vector<DP_GATEWAY>& Gateways() { return m_gateways; }
204
205 const std::vector<DP_GATEWAY>& CGateways() const { return m_gateways; }
206
207 void FilterByOrientation( int aAngleMask, DIRECTION_45 aRefOrientation );
208
209private:
211 {
214 int score;
215 };
216
217 bool checkDiagonalAlignment( const VECTOR2I& a, const VECTOR2I& b ) const;
218 void buildDpContinuation( const DP_PRIMITIVE_PAIR& aPair, bool aIsDiagonal );
219 void buildEntries( const VECTOR2I& p0_p, const VECTOR2I& p0_n );
220
221 int m_gap;
225
226 std::vector<DP_GATEWAY> m_gateways;
227};
228
229
234class DIFF_PAIR : public LINK_HOLDER
235{
236public:
238 {
239 COUPLED_SEGMENTS ( const SEG& aCoupledP, const SEG& aParentP, int aIndexP,
240 const SEG& aCoupledN, const SEG& aParentN, int aIndexN ) :
241 coupledP( aCoupledP ),
242 coupledN( aCoupledN ),
243 parentP( aParentP ),
244 parentN( aParentN ),
245 indexP( aIndexP ),
246 indexN( aIndexN )
247 {}
248
255 };
256
257 typedef std::vector<COUPLED_SEGMENTS> COUPLED_SEGMENTS_VEC;
258
261 m_hasVias( false )
262 {
263 // Initialize some members, to avoid uninitialized variables.
264 m_net_p = 0;
265 m_net_n = 0;;
266 m_width = 0;
267 m_gap = 0;
268 m_viaGap = 0;
270 m_chamferLimit = 0;
271 }
272
273 DIFF_PAIR( int aGap ) :
275 m_hasVias( false )
276 {
277 m_gapConstraint = aGap;
278
279 // Initialize other members, to avoid uninitialized variables.
280 m_net_p = 0;
281 m_net_n = 0;;
282 m_width = 0;
283 m_gap = 0;
284 m_viaGap = 0;
286 m_chamferLimit = 0;
287 }
288
289 DIFF_PAIR( const SHAPE_LINE_CHAIN &aP, const SHAPE_LINE_CHAIN& aN, int aGap = 0 ) :
291 m_n( aN ),
292 m_p( aP ),
293 m_hasVias( false )
294 {
295 m_gapConstraint = aGap;
296
297 // Initialize other members, to avoid uninitialized variables.
298 m_net_p = 0;
299 m_net_n = 0;;
300 m_width = 0;
301 m_gap = 0;
302 m_viaGap = 0;
304 m_chamferLimit = 0;
305 }
306
307 DIFF_PAIR( const LINE &aLineP, const LINE &aLineN, int aGap = 0 ) :
309 m_line_p( aLineP ),
310 m_line_n( aLineN ),
311 m_hasVias( false )
312 {
313 m_gapConstraint = aGap;
314 m_net_p = aLineP.Net();
315 m_net_n = aLineN.Net();
316 m_p = aLineP.CLine();
317 m_n = aLineN.CLine();
318
319 // Do not leave uninitialized members, and keep static analyzer quiet:
320 m_width = 0;
321 m_gap = 0;
322 m_viaGap = 0;
324 m_chamferLimit = 0;
325 }
326
327 static inline bool ClassOf( const ITEM* aItem )
328 {
329 return aItem && ITEM::DIFF_PAIR_T == aItem->Kind();
330 }
331
332 DIFF_PAIR* Clone() const override
333 {
334 assert( false );
335 return nullptr;
336 }
337
338 virtual void ClearLinks() override
339 {
340 m_links.clear();
343 }
344
345 static DIFF_PAIR* AssembleDp( LINE *aLine );
346
347 void SetShape( const SHAPE_LINE_CHAIN &aP, const SHAPE_LINE_CHAIN& aN, bool aSwapLanes = false )
348 {
349 if( aSwapLanes )
350 {
351 m_p = aN;
352 m_n = aP;
353 }
354 else
355 {
356 m_p = aP;
357 m_n = aN;
358 }
359 }
360
361 void SetShape( const DIFF_PAIR& aPair )
362 {
363 m_p = aPair.m_p;
364 m_n = aPair.m_n;
365 }
366
368 {
369 m_net_p = aP;
370 m_net_n = aN;
371 }
372
373 void SetWidth( int aWidth )
374 {
375 m_width = aWidth;
376 m_n.SetWidth( aWidth );
377 m_p.SetWidth( aWidth );
378 }
379
380 int Width() const { return m_width; }
381
382 void SetGap( int aGap )
383 {
384 m_gap = aGap;
385 m_gapConstraint = RANGED_NUM<int>( m_gap, 10000, 10000 );
386 }
387
388 int Gap() const
389 {
390 return m_gap;
391 }
392
393 void AppendVias( const VIA &aViaP, const VIA& aViaN )
394 {
395 m_hasVias = true;
396 m_via_p = aViaP;
397 m_via_p.SetHole( aViaP.Hole()->Clone() );
398 m_via_n = aViaN;
399 m_via_n.SetHole( aViaN.Hole()->Clone() );
400 }
401
403 {
404 m_hasVias = false;
407 }
408
409 bool EndsWithVias() const
410 {
411 return m_hasVias;
412 }
413
414 void SetViaDiameter( int aDiameter )
415 {
416 m_via_p.SetDiameter( VIA::ALL_LAYERS, aDiameter );
417 m_via_n.SetDiameter( VIA::ALL_LAYERS, aDiameter );
418 }
419
420 void SetViaDrill( int aDrill )
421 {
422 m_via_p.SetDrill( aDrill );
423 m_via_n.SetDrill( aDrill );
424 }
425
427 {
428 return m_net_p;
429 }
430
432 {
433 return m_net_n;
434 }
435
437 {
438 if( !m_line_p.IsLinked() )
440
441 return m_line_p;
442 }
443
445 {
446 if( !m_line_n.IsLinked() )
448
449 return m_line_n;
450 }
451
453
454 double CoupledLength() const;
455 double TotalLength() const;
456 double CoupledLengthFactor() const;
457 double Skew() const;
458
459 void CoupledSegmentPairs( COUPLED_SEGMENTS_VEC& aPairs ) const;
460
461 void Clear()
462 {
463 m_n.Clear();
464 m_p.Clear();
465 }
466
467 void Append( const DIFF_PAIR& aOther )
468 {
469 m_n.Append( aOther.m_n );
470 m_p.Append( aOther.m_p );
471 }
472
473 bool Empty() const
474 {
475 return ( m_n.SegmentCount() == 0 ) || ( m_p.SegmentCount() == 0 );
476 }
477
478 const SHAPE_LINE_CHAIN& CP() const { return m_p; }
479 const SHAPE_LINE_CHAIN& CN() const { return m_n; }
480
481 bool BuildInitial( const DP_GATEWAY& aEntry, const DP_GATEWAY& aTarget, bool aPrefDiagonal );
482 bool CheckConnectionAngle( const DIFF_PAIR &aOther, int allowedAngles ) const;
483 int CoupledLength( const SEG& aP, const SEG& aN ) const;
484
485 int64_t CoupledLength( const SHAPE_LINE_CHAIN& aP, const SHAPE_LINE_CHAIN& aN ) const;
486
488 {
489 return m_gapConstraint;
490 }
491
492private:
493 void updateLine( LINE &aLine, const SHAPE_LINE_CHAIN& aShape, NET_HANDLE aNet, const VIA& aVia )
494 {
495 aLine.SetShape( aShape );
496 aLine.SetWidth( m_width );
497 aLine.SetNet( aNet );
498 aLine.SetLayer( Layers().Start() );
499
500 if( m_hasVias )
501 aLine.AppendVia( aVia );
502 }
503
507
511 int m_gap;
516};
517
518}
519
520#endif
Represent route directions & corner angles in a 45-degree metric.
Definition: direction45.h:37
Basic class for a differential pair.
bool CheckConnectionAngle(const DIFF_PAIR &aOther, int allowedAngles) const
void AppendVias(const VIA &aViaP, const VIA &aViaN)
SHAPE_LINE_CHAIN m_p
const SHAPE_LINE_CHAIN & CN() const
static DIFF_PAIR * AssembleDp(LINE *aLine)
DP_PRIMITIVE_PAIR EndingPrimitives()
int Width() const
std::vector< COUPLED_SEGMENTS > COUPLED_SEGMENTS_VEC
NET_HANDLE m_net_p
const RANGED_NUM< int > GapConstraint() const
double CoupledLength() const
bool BuildInitial(const DP_GATEWAY &aEntry, const DP_GATEWAY &aTarget, bool aPrefDiagonal)
void Append(const DIFF_PAIR &aOther)
double Skew() const
void SetViaDiameter(int aDiameter)
DIFF_PAIR(int aGap)
RANGED_NUM< int > m_gapConstraint
void updateLine(LINE &aLine, const SHAPE_LINE_CHAIN &aShape, NET_HANDLE aNet, const VIA &aVia)
double TotalLength() const
void SetViaDrill(int aDrill)
virtual void ClearLinks() override
Return the number of segments that were assembled together to form this line.
void SetShape(const DIFF_PAIR &aPair)
double CoupledLengthFactor() const
void SetShape(const SHAPE_LINE_CHAIN &aP, const SHAPE_LINE_CHAIN &aN, bool aSwapLanes=false)
int Gap() const
bool EndsWithVias() const
NET_HANDLE NetP() const
DIFF_PAIR(const LINE &aLineP, const LINE &aLineN, int aGap=0)
NET_HANDLE m_net_n
bool Empty() const
DIFF_PAIR * Clone() const override
Return a deep copy of the item.
static bool ClassOf(const ITEM *aItem)
void SetGap(int aGap)
SHAPE_LINE_CHAIN m_n
void SetNets(NET_HANDLE aP, NET_HANDLE aN)
const SHAPE_LINE_CHAIN & CP() const
DIFF_PAIR(const SHAPE_LINE_CHAIN &aP, const SHAPE_LINE_CHAIN &aN, int aGap=0)
void CoupledSegmentPairs(COUPLED_SEGMENTS_VEC &aPairs) const
NET_HANDLE NetN() const
void SetWidth(int aWidth)
A set of gateways calculated for the cursor or starting/ending primitive pair.
void SetFitVias(bool aEnable, int aDiameter=0, int aViaGap=-1)
void BuildFromPrimitivePair(const DP_PRIMITIVE_PAIR &aPair, bool aPreferDiagonal)
DP_GATEWAYS(int aGap)
bool FitGateways(DP_GATEWAYS &aEntry, DP_GATEWAYS &aTarget, bool aPrefDiagonal, DIFF_PAIR &aDp)
void BuildGeneric(const VECTOR2I &p0_p, const VECTOR2I &p0_n, bool aBuildEntries=false, bool aViaMode=false)
std::vector< DP_GATEWAY > & Gateways()
bool checkDiagonalAlignment(const VECTOR2I &a, const VECTOR2I &b) const
void BuildOrthoProjections(DP_GATEWAYS &aEntries, const VECTOR2I &aCursorPos, int aOrthoScore)
void buildDpContinuation(const DP_PRIMITIVE_PAIR &aPair, bool aIsDiagonal)
std::vector< DP_GATEWAY > m_gateways
const std::vector< DP_GATEWAY > & CGateways() const
void FilterByOrientation(int aAngleMask, DIRECTION_45 aRefOrientation)
void BuildForCursor(const VECTOR2I &aCursorPos)
void buildEntries(const VECTOR2I &p0_p, const VECTOR2I &p0_n)
Define a "gateway" for routing a differential pair - e.g.
Definition: pns_diff_pair.h:44
SHAPE_LINE_CHAIN m_entryP
bool IsDiagonal() const
Definition: pns_diff_pair.h:62
const SHAPE_LINE_CHAIN & EntryP() const
Definition: pns_diff_pair.h:96
bool HasEntryLines() const
int AllowedAngles() const
Definition: pns_diff_pair.h:74
const VECTOR2I & AnchorN() const
Definition: pns_diff_pair.h:69
VECTOR2I m_anchorP
SHAPE_LINE_CHAIN m_entryN
VECTOR2I m_anchorN
void SetEntryLines(const SHAPE_LINE_CHAIN &aEntryP, const SHAPE_LINE_CHAIN &aEntryN)
Definition: pns_diff_pair.h:89
const VECTOR2I & AnchorP() const
Definition: pns_diff_pair.h:67
const SHAPE_LINE_CHAIN & EntryN() const
Definition: pns_diff_pair.h:97
const DIFF_PAIR Entry() const
DP_GATEWAY(const VECTOR2I &aAnchorP, const VECTOR2I &aAnchorN, bool aIsDiagonal, int aAllowedEntryAngles=DIRECTION_45::ANG_OBTUSE, int aPriority=0)
Definition: pns_diff_pair.h:46
int Priority() const
Definition: pns_diff_pair.h:79
void SetPriority(int aPriority)
Definition: pns_diff_pair.h:84
Store starting/ending primitives (pads, vias or segments) for a differential pair.
DIRECTION_45 DirN() const
const VECTOR2I & AnchorN() const
ITEM * PrimN() const
const VECTOR2I & AnchorP() const
DIRECTION_45 anchorDirection(const ITEM *aItem, const VECTOR2I &aP) const
void CursorOrientation(const VECTOR2I &aCursorPos, VECTOR2I &aMidpoint, VECTOR2I &aDirection) const
DP_PRIMITIVE_PAIR & operator=(const DP_PRIMITIVE_PAIR &aOther)
ITEM * PrimP() const
void SetAnchors(const VECTOR2I &aAnchorP, const VECTOR2I &aAnchorN)
DIRECTION_45 DirP() const
virtual HOLE * Clone() const override
Return a deep copy of the item.
Definition: pns_hole.cpp:41
Base class for PNS router board items.
Definition: pns_item.h:97
const PNS_LAYER_RANGE & Layers() const
Definition: pns_item.h:199
virtual NET_HANDLE Net() const
Definition: pns_item.h:197
PnsKind Kind() const
Return the type (kind) of the item.
Definition: pns_item.h:170
void SetNet(NET_HANDLE aNet)
Definition: pns_item.h:196
void SetLayer(int aLayer)
Definition: pns_item.h:202
@ DIFF_PAIR_T
Definition: pns_item.h:109
Represents a track on a PCB, connecting two non-trivial joints (that is, vias, pads,...
Definition: pns_line.h:62
void SetShape(const SHAPE_LINE_CHAIN &aLine)
Return the shape of the line.
Definition: pns_line.h:127
const SHAPE_LINE_CHAIN & CLine() const
Definition: pns_line.h:138
void RemoveVia()
Definition: pns_line.cpp:1315
void AppendVia(const VIA &aVia)
Definition: pns_line.cpp:1082
void SetWidth(int aWidth)
Return line width.
Definition: pns_line.h:150
void SetDiameter(int aLayer, int aDiameter)
Definition: pns_via.h:198
virtual void SetHole(HOLE *aHole) override
Definition: pns_via.h:255
virtual HOLE * Hole() const override
Definition: pns_via.h:268
void SetDrill(int aDrill)
Definition: pns_via.h:213
static constexpr int ALL_LAYERS
Definition: pns_via.h:76
Definition: seg.h:42
Represent a polyline containing arcs as well as line segments: A chain of connected line and/or arc s...
void Clear()
Remove all points from the line chain.
void Append(int aX, int aY, bool aAllowDuplication=false)
Append a new point at the end of the line chain.
int SegmentCount() const
Return the number of segments in this line chain.
void SetWidth(int aWidth)
Set the width of all segments in the chain.
Push and Shove diff pair dimensions (gap) settings dialog.
void * NET_HANDLE
Definition: pns_item.h:54
@ DIFF_PAIR
COUPLED_SEGMENTS(const SEG &aCoupledP, const SEG &aParentP, int aIndexP, const SEG &aCoupledN, const SEG &aParentN, int aIndexN)