KiCad PCB EDA Suite
Loading...
Searching...
No Matches
pns_dp_meander_placer.cpp
Go to the documentation of this file.
1/*
2 * KiRouter - a push-and-(sometimes-)shove PCB router
3 *
4 * Copyright (C) 2013-2014 CERN
5 * Copyright The 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
19 * along with this program. If not, see <https://www.gnu.org/licenses/>.
20 */
21
22#include <optional>
23#include <algorithm>
24
25#include <core/typeinfo.h>
26
28
29#include "pns_node.h"
30#include "pns_itemset.h"
31#include "pns_topology.h"
33#include "pns_diff_pair.h"
34#include "pns_helpers.h"
35#include "pns_router.h"
36#include "pns_solid.h"
37
38
39namespace PNS {
40
42 MEANDER_PLACER_BASE( aRouter )
43{
44 m_world = nullptr;
45 m_currentNode = nullptr;
46
49
52
53 // Init temporary variables (do not leave uninitialized members)
54 m_initialSegment = nullptr;
55 m_lastLength = 0;
56 m_lastDelay = 0;
58
59 m_netClass = nullptr;
60}
61
62
66
67
69{
70 return m_currentTraceP;
71}
72
73
78
79
80NODE* DP_MEANDER_PLACER::CurrentNode( bool aLoopsRemoved ) const
81{
82 if( !m_currentNode )
83 return m_world;
84
85 return m_currentNode;
86}
87
88
89bool DP_MEANDER_PLACER::Start( const VECTOR2I& aP, ITEM* aStartItem )
90{
91 if( !aStartItem || !aStartItem->OfKind( ITEM::SEGMENT_T | ITEM::ARC_T ) )
92 {
93 Router()->SetFailureReason( _( "Please select a track whose length you want to tune." ) );
94 return false;
95 }
96
97 m_initialSegment = static_cast<LINKED_ITEM*>( aStartItem );
98 m_currentNode = nullptr;
100
101 m_world = Router()->GetWorld()->Branch();
102
103 TOPOLOGY topo( m_world );
104
106 {
107 Router()->SetFailureReason( _( "Unable to find complementary differential pair "
108 "net for length tuning. Make sure the names of the nets "
109 "belonging to a differential pair end with either _N/_P "
110 "or +/-." ) );
111 return false;
112 }
113
114 if( m_originPair.Dimensions().Gap() < 0 )
115 m_originPair.SetGap( Router()->Sizes().DiffPairGap() );
116
117 if( !m_originPair.PLine().SegmentCount() || !m_originPair.NLine().SegmentCount() )
118 return false;
119
120 m_tunedPathP = topo.AssembleTuningPath( Router()->GetInterface(), m_originPair.PLine().GetLink( 0 ), &m_startPad_p,
121 &m_endPad_p );
122
125
126 if( m_startPad_p )
127 {
128 m_padToDieLengthP += m_startPad_p->GetPadToDie();
129 m_padToDieDelayP += m_startPad_p->GetPadToDieDelay();
130 }
131
132 if( m_endPad_p )
133 {
134 m_padToDieLengthP += m_endPad_p->GetPadToDie();
135 m_padToDieDelayP += m_endPad_p->GetPadToDieDelay();
136 }
137
138 m_tunedPathN = topo.AssembleTuningPath( Router()->GetInterface(), m_originPair.NLine().GetLink( 0 ), &m_startPad_n,
139 &m_endPad_n );
140
143
144 if( m_startPad_n )
145 {
146 m_padToDieLengthN += m_startPad_n->GetPadToDie();
147 m_padToDieDelayN += m_startPad_n->GetPadToDieDelay();
148 }
149
150 if( m_endPad_n )
151 {
152 m_padToDieLengthN += m_endPad_n->GetPadToDie();
153 m_padToDieDelayN += m_endPad_n->GetPadToDieDelay();
154 }
155
156 m_world->Remove( m_originPair.PLine() );
157 m_world->Remove( m_originPair.NLine() );
158
159 m_currentWidth = m_originPair.Dimensions().Width();
160
161 const BOARD_CONNECTED_ITEM* conItem = static_cast<BOARD_CONNECTED_ITEM*>( aStartItem->GetSourceItem() );
162 m_netClass = conItem->GetEffectiveNetClass();
163
166 m_baselineDelay = m_settings.m_isTimeDomain ? origPathDelay() : 0;
167 m_hasBaseline = true;
168
170
172
173 return true;
174}
175
176
180
181
183{
186 return std::max( totalP, totalN );
187}
188
189
191{
192 const int64_t totalP = m_padToDieDelayP + lineDelay( m_tunedPathP, m_startPad_p, m_endPad_p );
193 const int64_t totalN = m_padToDieDelayN + lineDelay( m_tunedPathN, m_startPad_n, m_endPad_n );
194 return std::max( totalP, totalN );
195}
196
197
199{
200 const VECTOR2I a( ( aCoupledSegs.coupledP.A + aCoupledSegs.coupledN.A ) / 2 );
201 const VECTOR2I b( ( aCoupledSegs.coupledP.B + aCoupledSegs.coupledN.B ) / 2 );
202
203 return SEG( a, b );
204}
205
206
208{
209 VECTOR2I midp = ( aPair.coupledP.A + aPair.coupledN.A ) / 2;
210
211 //DrawDebugPoint(midp, 6);
212
213 return aPair.coupledP.Side( midp ) > 0;
214}
215
216
217bool DP_MEANDER_PLACER::Move( const VECTOR2I& aP, ITEM* aEndItem )
218{
219 // Reuse the chain-extras aggregate captured at Start(). Other nets in the chain are
220 // not edited during a tuning session, so we don't need to walk the BOARD again.
221 const long long extraDelay = m_chainExtrasValid ? m_chainExtrasDelay : 0;
222
223 m_settings.m_signalExtraDelay = extraDelay;
224
225 // Derive per-net budget from chain target, accounting for stubs not in the PNS path.
226 // Take the tighter of chain budget and existing per-net constraint.
227 if( m_settings.m_targetSignalLength.Opt() != MEANDER_SETTINGS::LENGTH_UNCONSTRAINED )
228 {
229 const long long otherLen = chainNarrowingOffset();
230
231 long long budgetMin = std::max( 0LL, m_settings.m_targetSignalLength.Min() - otherLen );
232 long long budgetOpt = std::max( 0LL, m_settings.m_targetSignalLength.Opt() - otherLen );
233 long long budgetMax = std::max( budgetOpt, m_settings.m_targetSignalLength.Max() - otherLen );
234
235 if( m_settings.m_targetLength.Opt() == MEANDER_SETTINGS::LENGTH_UNCONSTRAINED )
236 {
237 m_settings.m_targetLength.SetMin( budgetMin );
238 m_settings.m_targetLength.SetOpt( budgetOpt );
239 m_settings.m_targetLength.SetMax( budgetMax );
240 }
241 else
242 {
243 m_settings.m_targetLength.SetMin( std::max( m_settings.m_targetLength.Min(), budgetMin ) );
244 m_settings.m_targetLength.SetOpt( std::min( m_settings.m_targetLength.Opt(), budgetOpt ) );
245 m_settings.m_targetLength.SetMax( std::min( m_settings.m_targetLength.Max(), budgetMax ) );
246 }
247 }
248
250
251 if( m_currentStart == aP )
252 return false;
253
254 DIFF_PAIR::COUPLED_SEGMENTS_VEC coupledSegments;
255
256 if( m_currentNode )
257 delete m_currentNode;
258
259 m_currentNode = m_world->Branch();
260
261 SHAPE_LINE_CHAIN preP, tunedP, postP;
262 SHAPE_LINE_CHAIN preN, tunedN, postN;
263
264 m_originPair.CP().Split( m_currentStart, aP, preP, tunedP, postP );
265 m_originPair.CN().Split( m_currentStart, aP, preN, tunedN, postN );
266
267 tunedP.Simplify();
268 tunedN.Simplify();
269
270 // Bail out early if the tuned sections are empty (issue #22041). This can happen when the
271 // split points are too close together or outside the line chain.
272 if( tunedP.PointCount() == 0 || tunedN.PointCount() == 0 )
273 {
278
279 return false;
280 }
281
282 auto updateStatus =
283 [&]()
284 {
285 if( m_lastLength > m_settings.m_targetLength.Max() )
287 else if( m_lastLength < m_settings.m_targetLength.Min() )
289 else
291 };
292
293 DIFF_PAIR tuned( m_originPair );
294
295 tuned.SetShape( tunedP, tunedN );
296
297 tuned.CoupledSegmentPairs( coupledSegments );
298
299 if( coupledSegments.size() == 0 )
300 {
301 // Tuning started at an uncoupled area of the DP; we won't get a valid result until the
302 // cursor is moved far enough along a coupled area. Prevent the track from disappearing and
303 // the length from being zero by just using the original.
307 updateStatus();
308
309 return false;
310 }
311
312 m_result = MEANDERED_LINE( this, true );
313 m_result.SetWidth( tuned.Dimensions().Width() );
314
315 int offset = ( tuned.Dimensions().Gap() + tuned.Dimensions().Width() ) / 2;
316
317 if( pairOrientation( coupledSegments[0] ) )
318 offset *= -1;
319
320 m_result.SetBaselineOffset( offset );
321
322 for( const ITEM* item : m_tunedPathP.CItems() )
323 {
324 if( const LINE* l = dyn_cast<const LINE*>( item ) )
325 {
326 PNS_DBG( Dbg(), AddShape, &l->CLine(), YELLOW, 10000, wxT( "tuned-path-p" ) );
327
328 m_router->GetInterface()->DisplayPathLine( l->CLine(), 1 );
329 }
330 }
331
332 for( const ITEM* item : m_tunedPathN.CItems() )
333 {
334 if( const LINE* l = dyn_cast<const LINE*>( item ) )
335 {
336 PNS_DBG( Dbg(), AddShape, &l->CLine(), YELLOW, 10000, wxT( "tuned-path-n" ) );
337
338 m_router->GetInterface()->DisplayPathLine( l->CLine(), 1 );
339 }
340 }
341
342 struct GET_ITEM_RET
343 {
344 std::optional<SHAPE_ARC> arc;
345 VECTOR2I startPt;
346 VECTOR2I endPt;
347 };
348
349 auto getItem = [&]( const SHAPE_LINE_CHAIN& aChain, int aIndex, int aLastIndex )
350 {
351 std::optional<SHAPE_ARC> optArc;
352 VECTOR2I startPt;
353 VECTOR2I endPt;
354
355 if( aChain.IsArcSegment( aIndex ) )
356 {
357 SHAPE_ARC arc = aChain.Arc( aChain.ArcIndex( aIndex ) );
358 optArc = arc;
359 startPt = arc.GetStart();
360 endPt = arc.GetEnd();
361 }
362 else
363 {
364 SEG seg = aChain.GetSegment( aIndex );
365 startPt = seg.A;
366 endPt = seg.B;
367 }
368
369 return GET_ITEM_RET{ optArc, startPt, endPt };
370 };
371
372 auto checkIndex = [&]( bool& aOk, int aCurIndex, int aLastIndex ) -> bool
373 {
374 aOk = aCurIndex <= aLastIndex && aCurIndex != -1;
375 return aOk;
376 };
377
378 int curIndexP = 0, curIndexN = 0;
379
380 auto addCornersUntilIndex = [&]( int aLastIndexP, int aLastIndexN )
381 {
382 while( true )
383 {
384 bool p_ok, n_ok;
385 checkIndex( p_ok, curIndexP, aLastIndexP );
386 checkIndex( n_ok, curIndexN, aLastIndexN );
387
388 if( !p_ok && !n_ok )
389 break;
390
391 auto p_item = getItem( tunedP, curIndexP, aLastIndexP );
392 auto n_item = getItem( tunedN, curIndexN, aLastIndexN );
393
394 if( !p_item.arc && !n_item.arc )
395 {
396 m_result.AddCorner( p_item.startPt, n_item.startPt );
397 }
398 else if( p_item.arc && n_item.arc )
399 {
400 m_result.AddArc( *p_item.arc, *n_item.arc );
401 }
402 else if( p_item.arc && !n_item.arc )
403 {
404 m_result.AddCorner( p_item.startPt, n_item.startPt );
405
406 // Find arc in N
407 while( checkIndex( n_ok, curIndexN, aLastIndexN ) )
408 {
409 curIndexN = tunedN.NextShape( curIndexN );
410 n_item = getItem( tunedN, curIndexN, aLastIndexN );
411
412 if( n_item.arc )
413 {
414 m_result.AddArc( *p_item.arc, *n_item.arc );
415 break;
416 }
417 else
418 {
419 m_result.AddCorner( p_item.startPt, n_item.startPt );
420 }
421 }
422 }
423 else if( !p_item.arc && n_item.arc )
424 {
425 m_result.AddCorner( p_item.startPt, n_item.startPt );
426
427 // Find arc in P
428 while( checkIndex( p_ok, curIndexP, aLastIndexP ) )
429 {
430 curIndexP = tunedP.NextShape( curIndexP );
431 p_item = getItem( tunedP, curIndexP, aLastIndexP );
432
433 if( p_item.arc )
434 {
435 m_result.AddArc( *p_item.arc, *n_item.arc );
436 break;
437 }
438 else
439 {
440 m_result.AddCorner( p_item.startPt, n_item.startPt );
441 }
442 }
443 }
444
445 if( p_ok )
446 curIndexP = tunedP.NextShape( curIndexP );
447
448 if( n_ok )
449 curIndexN = tunedN.NextShape( curIndexN );
450 }
451 };
452
453 for( const DIFF_PAIR::COUPLED_SEGMENTS& sp : coupledSegments )
454 {
455 SEG base = baselineSegment( sp );
456 bool side = false;
457
458 if( m_settings.m_initialSide == 0 )
459 side = base.Side( aP ) < 0;
460 else
461 side = m_settings.m_initialSide < 0;
462
463 PNS_DBG( Dbg(), AddShape, base, GREEN, 10000, wxT( "dp-baseline" ) );
464
465 addCornersUntilIndex( sp.indexP, sp.indexN );
466
467 m_result.MeanderSegment( base, side );
468 }
469
470 addCornersUntilIndex( tunedP.PointCount() - 1, tunedN.PointCount() - 1 );
471
472 m_result.AddCorner( tunedP.CLastPoint(), tunedN.CLastPoint() );
473
474 long long int dpLen = origPathLength();
475 int64_t dpDelay = origPathDelay();
476
478
479 if( dpLen > m_settings.m_targetLength.Max() )
480 {
482 m_lastLength = dpLen;
483 m_lastDelay = dpDelay;
484 }
485 else
486 {
487 m_lastLength = dpLen - std::max( tunedP.Length(), tunedN.Length() );
488
489 if( m_settings.m_isTimeDomain )
490 {
491 int64_t tunedPDelay = m_router->GetInterface()->CalculateDelayForShapeLineChain(
492 tunedP, GetOriginPair().Dimensions().Width(), true, GetOriginPair().Dimensions().Gap(), m_router->GetCurrentLayer(),
493 m_netClass );
494 int64_t tunedNDelay = m_router->GetInterface()->CalculateDelayForShapeLineChain(
495 tunedN, GetOriginPair().Dimensions().Width(), true, GetOriginPair().Dimensions().Gap(), m_router->GetCurrentLayer(),
496 m_netClass );
497
498 m_lastDelay = dpDelay - std::max( tunedPDelay, tunedNDelay );
499 }
500
501 tuneLineLength( m_result, m_settings.m_targetLength.Opt() - dpLen );
502 }
503
504 if( m_lastStatus != TOO_LONG )
505 {
506 tunedP.Clear();
507 tunedN.Clear();
508
509 for( MEANDER_SHAPE* m : m_result.Meanders() )
510 {
511 if( m->Type() != MT_EMPTY )
512 {
513 tunedP.Append( m->CLine( 0 ) );
514 tunedN.Append( m->CLine( 1 ) );
515 }
516 }
517
518 m_lastLength += std::max( tunedP.Length(), tunedN.Length() );
519
520 if( m_settings.m_isTimeDomain )
521 {
522 int64_t tunedPDelay = m_router->GetInterface()->CalculateDelayForShapeLineChain(
523 tunedP, GetOriginPair().Dimensions().Width(), true, GetOriginPair().Dimensions().Gap(), m_router->GetCurrentLayer(),
524 m_netClass );
525 int64_t tunedNDelay = m_router->GetInterface()->CalculateDelayForShapeLineChain(
526 tunedN, GetOriginPair().Dimensions().Width(), true, GetOriginPair().Dimensions().Gap(), m_router->GetCurrentLayer(),
527 m_netClass );
528
529 m_lastDelay += std::max( tunedPDelay, tunedNDelay );
530 }
531
532 updateStatus();
533 }
534
535 m_finalShapeP.Clear();
536 m_finalShapeN.Clear();
537
538 if( m_settings.m_keepEndpoints )
539 {
540 preP.Simplify();
541 tunedP.Simplify();
542 postP.Simplify();
543
544 m_finalShapeP.Append( preP );
545 m_finalShapeP.Append( tunedP );
546 m_finalShapeP.Append( postP );
547
548 preN.Simplify();
549 tunedN.Simplify();
550 postN.Simplify();
551
552 m_finalShapeN.Append( preN );
553 m_finalShapeN.Append( tunedN );
554 m_finalShapeN.Append( postN );
555 }
556 else
557 {
558 m_finalShapeP.Append( preP );
559 m_finalShapeP.Append( tunedP );
560 m_finalShapeP.Append( postP );
561 m_finalShapeP.Simplify();
562
563 m_finalShapeN.Append( preN );
564 m_finalShapeN.Append( tunedN );
565 m_finalShapeN.Append( postN );
566 m_finalShapeN.Simplify();
567 }
568
569 return true;
570}
571
572
573bool DP_MEANDER_PLACER::FixRoute( const VECTOR2I& aP, ITEM* aEndItem, bool aForceFinish )
574{
575 LINE lP( m_originPair.PLine(), m_finalShapeP );
576 LINE lN( m_originPair.NLine(), m_finalShapeN );
577
578 m_currentNode->Add( lP );
579 m_currentNode->Add( lN );
580
582
583 return true;
584}
585
586
588{
589 m_world->KillChildren();
590 return true;
591}
592
593
595{
596 return m_originPair.CP().SegmentCount() > 0 || m_originPair.CN().SegmentCount() > 0;
597}
598
599
601{
602 if( m_currentNode )
604
605 m_currentNode = nullptr;
606 return true;
607}
608
609
611{
612 LINE l1( m_originPair.PLine(), aShape->CLine( 0 ) );
613 LINE l2( m_originPair.NLine(), aShape->CLine( 1 ) );
614
615 if( m_currentNode->CheckColliding( &l1 ) )
616 return false;
617
618 if( m_currentNode->CheckColliding( &l2 ) )
619 return false;
620
621 int w = aShape->Width();
622 int clearance = w + w * 3;
623
624 return m_result.CheckSelfIntersections( aShape, clearance );
625}
626
627
629{
632
633 ITEM_SET traces;
634
635 traces.Add( &m_currentTraceP );
636 traces.Add( &m_currentTraceN );
637
638 return traces;
639}
640
641
643{
644 ITEM_SET lines;
645
646 for( ITEM* item : m_tunedPathN )
647 lines.Add( item );
648
649 for( ITEM* item : m_tunedPathP )
650 lines.Add( item );
651
652 return lines;
653}
654
655
657{
658 return m_currentStart;
659}
660
661
663{
664 return m_currentEnd;
665}
666
667
669{
670 return m_initialSegment->Layers().Start();
671}
672
673
675{
676 if( m_lastLength )
677 return m_lastLength;
678 else
679 return origPathLength();
680}
681
682
684{
685 if( m_lastDelay )
686 return m_lastDelay;
687 else
688 return origPathDelay();
689}
690
691
696
697
698const std::vector<NET_HANDLE> DP_MEANDER_PLACER::CurrentNets() const
699{
700 std::vector<NET_HANDLE> rv;
701 rv.push_back( m_originPair.NetP() );
702 rv.push_back( m_originPair.NetN() );
703 return rv;
704}
705
706
708{
709 // If this is a time domain tuning, calculate the target length for the desired total delay
710 if( m_settings.m_isTimeDomain )
711 {
712 const int64_t curDelayChain = origPathDelay();
713 const int64_t curDelayPair = curDelayChain - m_settings.m_signalExtraDelay; // subtract other nets
714
715 bool useSignalTarget = ( m_settings.m_targetSignalLengthDelay.Opt() != MEANDER_SETTINGS::DELAY_UNCONSTRAINED );
716 const MINOPTMAX<long long int>& targetDelaySet = useSignalTarget ? m_settings.m_targetSignalLengthDelay
717 : m_settings.m_targetLengthDelay;
718
719 int64_t desiredDelayMin = targetDelaySet.Min();
720 int64_t desiredDelayOpt = targetDelaySet.Opt();
721 int64_t desiredDelayMax = targetDelaySet.Max();
722
723 if( useSignalTarget )
724 {
725 desiredDelayMin = std::max<int64_t>( 0, desiredDelayMin - m_settings.m_signalExtraDelay );
726 desiredDelayOpt = std::max<int64_t>( 0, desiredDelayOpt - m_settings.m_signalExtraDelay );
727 desiredDelayMax = std::max<int64_t>( desiredDelayOpt, desiredDelayMax - m_settings.m_signalExtraDelay );
728 }
729
730 const int64_t curDelay = useSignalTarget ? curDelayPair : curDelayChain;
731
732 const int64_t delayDifferenceOpt = desiredDelayOpt - curDelay;
733
734 const int64_t curLength = origPathLength();
735 const int64_t lengthDiffMin = m_router->GetInterface()->CalculateLengthForDelay(
736 desiredDelayOpt - desiredDelayMin, GetOriginPair().Dimensions().Width(), true, GetOriginPair().Dimensions().Gap(),
737 m_router->GetCurrentLayer(), m_netClass );
738 int64_t lengthDiffOpt = m_router->GetInterface()->CalculateLengthForDelay(
739 std::abs( delayDifferenceOpt ), GetOriginPair().Dimensions().Width(), true, GetOriginPair().Dimensions().Gap(),
740 m_router->GetCurrentLayer(), m_netClass );
741 const int64_t lengthDiffMax = m_router->GetInterface()->CalculateLengthForDelay(
742 desiredDelayMax - desiredDelayOpt, GetOriginPair().Dimensions().Width(), true, GetOriginPair().Dimensions().Gap(),
743 m_router->GetCurrentLayer(), m_netClass );
744
745 lengthDiffOpt = delayDifferenceOpt > 0 ? lengthDiffOpt : -lengthDiffOpt;
746
747 m_settings.m_targetLength.SetMin( curLength + lengthDiffOpt - lengthDiffMin );
748 m_settings.m_targetLength.SetOpt( curLength + lengthDiffOpt );
749 m_settings.m_targetLength.SetMax( curLength + lengthDiffOpt + lengthDiffMax );
750 }
751}
752}
A base class derived from BOARD_ITEM for items that can be connected and have a net,...
virtual NETCLASS * GetEffectiveNetClass() const
Return the NETCLASS for this item.
T Min() const
Definition minoptmax.h:29
T Max() const
Definition minoptmax.h:30
T Opt() const
Definition minoptmax.h:31
ROUTER * Router() const
Return current router settings.
ROUTER * m_router
DEBUG_DECORATOR * Dbg() const
Basic class for a differential pair.
std::vector< COUPLED_SEGMENTS > COUPLED_SEGMENTS_VEC
const DP_DIMENSIONS & Dimensions() const
void SetShape(const SHAPE_LINE_CHAIN &aP, const SHAPE_LINE_CHAIN &aN, bool aSwapLanes=false)
void CoupledSegmentPairs(COUPLED_SEGMENTS_VEC &aPairs, bool aUseGapConstraint=true, const std::optional< DP_GAP_CONSTRAINT > &aOverrideGapConstraint=std::optional< DP_GAP_CONSTRAINT >()) const
bool Start(const VECTOR2I &aP, ITEM *aStartItem) override
Start routing a single track at point aP, taking item aStartItem as anchor (unless NULL).
bool CheckFit(MEANDER_SHAPE *aShape) override
Checks if it's OK to place the shape aShape (i.e.
const ITEM_SET Traces() override
Function Traces()
bool pairOrientation(const DIFF_PAIR::COUPLED_SEGMENTS &aPair)
void calculateTimeDomainTargets()
Current routing start point (end of tail, beginning of head).
VECTOR2I m_currentStart
Current world state.
bool FixRoute(const VECTOR2I &aP, ITEM *aEndItem, bool aForceFinish=false) override
Commit the currently routed track to the parent node, taking aP as the final end point and aEndItem a...
int CurrentLayer() const override
Function CurrentLayer()
TUNING_STATUS TuningStatus() const override
Return the tuning status (too short, too long, etc.) of the trace(s) being tuned.
long long int TuningLengthResult() const override
Return the resultant length or skew of the tuned traces.
const SEG baselineSegment(const DIFF_PAIR::COUPLED_SEGMENTS &aCoupledSegs)
const DIFF_PAIR & GetOriginPair()
const ITEM_SET TunedPath() override
bool HasPlacedAnything() const override
bool Move(const VECTOR2I &aP, ITEM *aEndItem) override
Move the end of the currently routed trace to the point aP, taking aEndItem as anchor (if not NULL).
const VECTOR2I & CurrentEnd() const override
Function CurrentEnd()
const VECTOR2I & CurrentStart() const override
Function CurrentStart()
int64_t TuningDelayResult() const override
Return the resultant delay or skew of the tuned traces.
long long int origPathLength() const
const std::vector< NET_HANDLE > CurrentNets() const override
Function CurrentNets()
NODE * CurrentNode(bool aLoopsRemoved=false) const override
Return the most recent world state.
void Add(const LINE &aLine)
Base class for PNS router board items.
Definition pns_item.h:98
BOARD_ITEM * GetSourceItem() const
Definition pns_item.h:202
bool OfKind(int aKindMask) const
Definition pns_item.h:181
Represents a track on a PCB, connecting two non-trivial joints (that is, vias, pads,...
Definition pns_line.h:62
Represent a set of meanders fitted over a single or two lines.
long long int chainNarrowingOffset() const
Return the length offset to subtract when converting a user-facing total signal length target into a ...
void tuneLineLength(MEANDERED_LINE &aTuned, long long int aElongation)
Take a set of meanders in aTuned and tunes their length to extend the original line length by aElonga...
TUNING_STATUS
< Result of the length tuning operation
int m_currentWidth
Meander settings.
bool m_hasBaseline
Active path length at Start().
bool m_chainExtrasValid
Pointer to world to search colliding items.
long long int m_startPathLength
Aggregate length/delay of other nets in the same chain, cached at Start().
void initChainExtras()
Cache the per-session chain-extras length/delay (other nets in the same chain) so per-Move use does n...
MEANDER_SETTINGS m_settings
The current end point.
int64_t lineDelay(const ITEM_SET &aLine, const SOLID *aStartPad, const SOLID *aEndPad) const
Calculate the total delay of the line represented by an item set (tracks and vias)
NODE * m_world
Width of the meandered trace(s).
long long int lineLength(const ITEM_SET &aLine, const SOLID *aStartPad, const SOLID *aEndPad) const
Calculate the total length of the line represented by an item set (tracks and vias)
static const long long int LENGTH_UNCONSTRAINED
Definition pns_meander.h:73
static const long long int DELAY_UNCONSTRAINED
Definition pns_meander.h:76
int Width() const
const SHAPE_LINE_CHAIN & CLine(int aShape) const
Keep the router "world" - i.e.
Definition pns_node.h:243
NODE * Branch()
Create a lightweight copy (called branch) of self that tracks the changes (added/removed items) wrs t...
Definition pns_node.cpp:157
void SetFailureReason(const wxString &aReason)
Definition pns_router.h:249
void CommitRouting()
NODE * GetWorld() const
Definition pns_router.h:200
const DIFF_PAIR AssembleDiffPair(SEGMENT *aStart)
const ITEM_SET AssembleTuningPath(ROUTER_IFACE *aRouterIface, ITEM *aStart, SOLID **aStartPad=nullptr, SOLID **aEndPad=nullptr)
Like AssembleTrivialPath, but follows the track length algorithm, which discards segments that are fu...
Definition seg.h:38
VECTOR2I A
Definition seg.h:45
VECTOR2I B
Definition seg.h:46
int Side(const VECTOR2I &aP) const
Determine on which side of directed line passing via segment ends point aP lies.
Definition seg.h:139
VECTOR2I GetEnd() const override
Definition shape_arc.h:204
VECTOR2I GetStart() const override
Definition shape_arc.h:203
Represent a polyline containing arcs as well as line segments: A chain of connected line and/or arc s...
const SHAPE_ARC & Arc(size_t aArc) const
int PointCount() const
Return the number of points (vertices) in this line chain.
ssize_t ArcIndex(size_t aSegment) const
Return the arc index for the given segment index.
void Clear()
Remove all points from the line chain.
void Simplify(int aTolerance=0)
Simplify the line chain by removing colinear adjacent segments and duplicate vertices.
int NextShape(int aPointIndex) const
Return the vertex index of the next shape in the chain, or -1 if aPointIndex is the last shape.
void Append(int aX, int aY, bool aAllowDuplication=false)
Append a new point at the end of the line chain.
virtual const SEG GetSegment(int aIndex) const override
const VECTOR2I & CLastPoint() const
Return the last point in the line chain.
bool IsArcSegment(size_t aSegment) const
long long int Length() const
Return length of the line chain in Euclidean metric.
@ GREEN
Definition color4d.h:53
@ YELLOW
Definition color4d.h:63
#define _(s)
Push and Shove diff pair dimensions (gap) settings dialog.
@ MT_EMPTY
Definition pns_meander.h:49
EDA_ANGLE abs(const EDA_ANGLE &aAngle)
Definition eda_angle.h:411
#define PNS_DBG(dbg, method,...)
static VECTOR2I GetSnappedStartPoint(LINKED_ITEM *aStartItem, VECTOR2I aStartPoint)
int clearance
Casted dyn_cast(From aObject)
A lightweight dynamic downcast.
Definition typeinfo.h:55
VECTOR2< int32_t > VECTOR2I
Definition vector2d.h:683