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 along
19 * with this program. If not, see <http://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_router.h"
35#include "pns_solid.h"
36
37
38namespace PNS {
39
41 MEANDER_PLACER_BASE( aRouter )
42{
43 m_world = nullptr;
44 m_currentNode = nullptr;
45
48
51
52 // Init temporary variables (do not leave uninitialized members)
53 m_initialSegment = nullptr;
54 m_lastLength = 0;
55 m_lastDelay = 0;
57
58 m_netClass = nullptr;
59}
60
61
65
66
68{
69 return m_currentTraceP;
70}
71
72
77
78
79NODE* DP_MEANDER_PLACER::CurrentNode( bool aLoopsRemoved ) const
80{
81 if( !m_currentNode )
82 return m_world;
83
84 return m_currentNode;
85}
86
87
88bool DP_MEANDER_PLACER::Start( const VECTOR2I& aP, ITEM* aStartItem )
89{
90 if( !aStartItem || !aStartItem->OfKind( ITEM::SEGMENT_T | ITEM::ARC_T ) )
91 {
92 Router()->SetFailureReason( _( "Please select a track whose length you want to tune." ) );
93 return false;
94 }
95
96 m_initialSegment = static_cast<LINKED_ITEM*>( aStartItem );
97 m_currentNode = nullptr;
99
100 m_world = Router()->GetWorld()->Branch();
101
102 TOPOLOGY topo( m_world );
103
105 {
106 Router()->SetFailureReason( _( "Unable to find complementary differential pair "
107 "net for length tuning. Make sure the names of the nets "
108 "belonging to a differential pair end with either _N/_P "
109 "or +/-." ) );
110 return false;
111 }
112
113 if( m_originPair.Gap() < 0 )
114 m_originPair.SetGap( Router()->Sizes().DiffPairGap() );
115
116 if( !m_originPair.PLine().SegmentCount() || !m_originPair.NLine().SegmentCount() )
117 return false;
118
119 m_tunedPathP = topo.AssembleTuningPath( Router()->GetInterface(), m_originPair.PLine().GetLink( 0 ), &m_startPad_p,
120 &m_endPad_p );
121
124
125 if( m_startPad_p )
126 {
127 m_padToDieLengthP += m_startPad_p->GetPadToDie();
128 m_padToDieDelayP += m_startPad_p->GetPadToDieDelay();
129 }
130
131 if( m_endPad_p )
132 {
133 m_padToDieLengthP += m_endPad_p->GetPadToDie();
134 m_padToDieDelayP += m_endPad_p->GetPadToDieDelay();
135 }
136
137 m_tunedPathN = topo.AssembleTuningPath( Router()->GetInterface(), m_originPair.NLine().GetLink( 0 ), &m_startPad_n,
138 &m_endPad_n );
139
142
143 if( m_startPad_n )
144 {
145 m_padToDieLengthN += m_startPad_n->GetPadToDie();
146 m_padToDieDelayN += m_startPad_n->GetPadToDieDelay();
147 }
148
149 if( m_endPad_n )
150 {
151 m_padToDieLengthN += m_endPad_n->GetPadToDie();
152 m_padToDieDelayN += m_endPad_n->GetPadToDieDelay();
153 }
154
155 m_world->Remove( m_originPair.PLine() );
156 m_world->Remove( m_originPair.NLine() );
157
159
160 const BOARD_CONNECTED_ITEM* conItem = static_cast<BOARD_CONNECTED_ITEM*>( aStartItem->GetSourceItem() );
161 m_netClass = conItem->GetEffectiveNetClass();
162
164 m_baselineDelay = m_settings.m_isTimeDomain ? origPathDelay() : 0;
165
167
169
170 return true;
171}
172
173
177
178
180{
183 return std::max( totalP, totalN );
184}
185
186
188{
189 const int64_t totalP = m_padToDieDelayP + lineDelay( m_tunedPathP, m_startPad_p, m_endPad_p );
190 const int64_t totalN = m_padToDieDelayN + lineDelay( m_tunedPathN, m_startPad_n, m_endPad_n );
191 return std::max( totalP, totalN );
192}
193
194
196{
197 const VECTOR2I a( ( aCoupledSegs.coupledP.A + aCoupledSegs.coupledN.A ) / 2 );
198 const VECTOR2I b( ( aCoupledSegs.coupledP.B + aCoupledSegs.coupledN.B ) / 2 );
199
200 return SEG( a, b );
201}
202
203
205{
206 VECTOR2I midp = ( aPair.coupledP.A + aPair.coupledN.A ) / 2;
207
208 //DrawDebugPoint(midp, 6);
209
210 return aPair.coupledP.Side( midp ) > 0;
211}
212
213
214bool DP_MEANDER_PLACER::Move( const VECTOR2I& aP, ITEM* aEndItem )
215{
216 // Reuse the chain-extras aggregate captured at Start(). Other nets in the chain are
217 // not edited during a tuning session, so we don't need to walk the BOARD again.
218 const long long extraDelay = m_chainExtrasValid ? m_chainExtrasDelay : 0;
219
220 m_settings.m_signalExtraDelay = extraDelay;
221
222 // Derive per-net budget from chain target, accounting for stubs not in the PNS path.
223 // Take the tighter of chain budget and existing per-net constraint.
224 if( m_settings.m_targetSignalLength.Opt() != MEANDER_SETTINGS::LENGTH_UNCONSTRAINED )
225 {
226 const long long otherLen = chainNarrowingOffset();
227
228 long long budgetMin = std::max( 0LL, m_settings.m_targetSignalLength.Min() - otherLen );
229 long long budgetOpt = std::max( 0LL, m_settings.m_targetSignalLength.Opt() - otherLen );
230 long long budgetMax = std::max( budgetOpt, m_settings.m_targetSignalLength.Max() - otherLen );
231
232 if( m_settings.m_targetLength.Opt() == MEANDER_SETTINGS::LENGTH_UNCONSTRAINED )
233 {
234 m_settings.m_targetLength.SetMin( budgetMin );
235 m_settings.m_targetLength.SetOpt( budgetOpt );
236 m_settings.m_targetLength.SetMax( budgetMax );
237 }
238 else
239 {
240 m_settings.m_targetLength.SetMin( std::max( m_settings.m_targetLength.Min(), budgetMin ) );
241 m_settings.m_targetLength.SetOpt( std::min( m_settings.m_targetLength.Opt(), budgetOpt ) );
242 m_settings.m_targetLength.SetMax( std::min( m_settings.m_targetLength.Max(), budgetMax ) );
243 }
244 }
245
247
248 if( m_currentStart == aP )
249 return false;
250
251 DIFF_PAIR::COUPLED_SEGMENTS_VEC coupledSegments;
252
253 if( m_currentNode )
254 delete m_currentNode;
255
256 m_currentNode = m_world->Branch();
257
258 SHAPE_LINE_CHAIN preP, tunedP, postP;
259 SHAPE_LINE_CHAIN preN, tunedN, postN;
260
261 m_originPair.CP().Split( m_currentStart, aP, preP, tunedP, postP );
262 m_originPair.CN().Split( m_currentStart, aP, preN, tunedN, postN );
263
264 tunedP.Simplify();
265 tunedN.Simplify();
266
267 // Bail out early if the tuned sections are empty (issue #22041). This can happen when the
268 // split points are too close together or outside the line chain.
269 if( tunedP.PointCount() == 0 || tunedN.PointCount() == 0 )
270 {
275
276 return false;
277 }
278
279 auto updateStatus =
280 [&]()
281 {
282 if( m_lastLength > m_settings.m_targetLength.Max() )
284 else if( m_lastLength < m_settings.m_targetLength.Min() )
286 else
288 };
289
290 DIFF_PAIR tuned( m_originPair );
291
292 tuned.SetShape( tunedP, tunedN );
293
294 tuned.CoupledSegmentPairs( coupledSegments );
295
296 if( coupledSegments.size() == 0 )
297 {
298 // Tuning started at an uncoupled area of the DP; we won't get a valid result until the
299 // cursor is moved far enough along a coupled area. Prevent the track from disappearing and
300 // the length from being zero by just using the original.
304 updateStatus();
305
306 return false;
307 }
308
309 m_result = MEANDERED_LINE( this, true );
310 m_result.SetWidth( tuned.Width() );
311
312 int offset = ( tuned.Gap() + tuned.Width() ) / 2;
313
314 if( pairOrientation( coupledSegments[0] ) )
315 offset *= -1;
316
317 m_result.SetBaselineOffset( offset );
318
319 for( const ITEM* item : m_tunedPathP.CItems() )
320 {
321 if( const LINE* l = dyn_cast<const LINE*>( item ) )
322 {
323 PNS_DBG( Dbg(), AddShape, &l->CLine(), YELLOW, 10000, wxT( "tuned-path-p" ) );
324
325 m_router->GetInterface()->DisplayPathLine( l->CLine(), 1 );
326 }
327 }
328
329 for( const ITEM* item : m_tunedPathN.CItems() )
330 {
331 if( const LINE* l = dyn_cast<const LINE*>( item ) )
332 {
333 PNS_DBG( Dbg(), AddShape, &l->CLine(), YELLOW, 10000, wxT( "tuned-path-n" ) );
334
335 m_router->GetInterface()->DisplayPathLine( l->CLine(), 1 );
336 }
337 }
338
339 struct GET_ITEM_RET
340 {
341 std::optional<SHAPE_ARC> arc;
342 VECTOR2I startPt;
343 VECTOR2I endPt;
344 };
345
346 auto getItem = [&]( const SHAPE_LINE_CHAIN& aChain, int aIndex, int aLastIndex )
347 {
348 std::optional<SHAPE_ARC> optArc;
349 VECTOR2I startPt;
350 VECTOR2I endPt;
351
352 if( aChain.IsArcSegment( aIndex ) )
353 {
354 SHAPE_ARC arc = aChain.Arc( aChain.ArcIndex( aIndex ) );
355 optArc = arc;
356 startPt = arc.GetStart();
357 endPt = arc.GetEnd();
358 }
359 else
360 {
361 SEG seg = aChain.GetSegment( aIndex );
362 startPt = seg.A;
363 endPt = seg.B;
364 }
365
366 return GET_ITEM_RET{ optArc, startPt, endPt };
367 };
368
369 auto checkIndex = [&]( bool& aOk, int aCurIndex, int aLastIndex ) -> bool
370 {
371 aOk = aCurIndex <= aLastIndex && aCurIndex != -1;
372 return aOk;
373 };
374
375 int curIndexP = 0, curIndexN = 0;
376
377 auto addCornersUntilIndex = [&]( int aLastIndexP, int aLastIndexN )
378 {
379 while( true )
380 {
381 bool p_ok, n_ok;
382 checkIndex( p_ok, curIndexP, aLastIndexP );
383 checkIndex( n_ok, curIndexN, aLastIndexN );
384
385 if( !p_ok && !n_ok )
386 break;
387
388 auto p_item = getItem( tunedP, curIndexP, aLastIndexP );
389 auto n_item = getItem( tunedN, curIndexN, aLastIndexN );
390
391 if( !p_item.arc && !n_item.arc )
392 {
393 m_result.AddCorner( p_item.startPt, n_item.startPt );
394 }
395 else if( p_item.arc && n_item.arc )
396 {
397 m_result.AddArc( *p_item.arc, *n_item.arc );
398 }
399 else if( p_item.arc && !n_item.arc )
400 {
401 m_result.AddCorner( p_item.startPt, n_item.startPt );
402
403 // Find arc in N
404 while( checkIndex( n_ok, curIndexN, aLastIndexN ) )
405 {
406 curIndexN = tunedN.NextShape( curIndexN );
407 n_item = getItem( tunedN, curIndexN, aLastIndexN );
408
409 if( n_item.arc )
410 {
411 m_result.AddArc( *p_item.arc, *n_item.arc );
412 break;
413 }
414 else
415 {
416 m_result.AddCorner( p_item.startPt, n_item.startPt );
417 }
418 }
419 }
420 else if( !p_item.arc && n_item.arc )
421 {
422 m_result.AddCorner( p_item.startPt, n_item.startPt );
423
424 // Find arc in P
425 while( checkIndex( p_ok, curIndexP, aLastIndexP ) )
426 {
427 curIndexP = tunedP.NextShape( curIndexP );
428 p_item = getItem( tunedP, curIndexP, aLastIndexP );
429
430 if( p_item.arc )
431 {
432 m_result.AddArc( *p_item.arc, *n_item.arc );
433 break;
434 }
435 else
436 {
437 m_result.AddCorner( p_item.startPt, n_item.startPt );
438 }
439 }
440 }
441
442 if( p_ok )
443 curIndexP = tunedP.NextShape( curIndexP );
444
445 if( n_ok )
446 curIndexN = tunedN.NextShape( curIndexN );
447 }
448 };
449
450 for( const DIFF_PAIR::COUPLED_SEGMENTS& sp : coupledSegments )
451 {
452 SEG base = baselineSegment( sp );
453 bool side = false;
454
455 if( m_settings.m_initialSide == 0 )
456 side = base.Side( aP ) < 0;
457 else
458 side = m_settings.m_initialSide < 0;
459
460 PNS_DBG( Dbg(), AddShape, base, GREEN, 10000, wxT( "dp-baseline" ) );
461
462 addCornersUntilIndex( sp.indexP, sp.indexN );
463
464 m_result.MeanderSegment( base, side );
465 }
466
467 addCornersUntilIndex( tunedP.PointCount() - 1, tunedN.PointCount() - 1 );
468
469 m_result.AddCorner( tunedP.CLastPoint(), tunedN.CLastPoint() );
470
471 long long int dpLen = origPathLength();
472 int64_t dpDelay = origPathDelay();
473
475
476 if( dpLen > m_settings.m_targetLength.Max() )
477 {
479 m_lastLength = dpLen;
480 m_lastDelay = dpDelay;
481 }
482 else
483 {
484 m_lastLength = dpLen - std::max( tunedP.Length(), tunedN.Length() );
485
486 if( m_settings.m_isTimeDomain )
487 {
488 int64_t tunedPDelay = m_router->GetInterface()->CalculateDelayForShapeLineChain(
489 tunedP, GetOriginPair().Width(), true, GetOriginPair().Gap(), m_router->GetCurrentLayer(),
490 m_netClass );
491 int64_t tunedNDelay = m_router->GetInterface()->CalculateDelayForShapeLineChain(
492 tunedN, GetOriginPair().Width(), true, GetOriginPair().Gap(), m_router->GetCurrentLayer(),
493 m_netClass );
494
495 m_lastDelay = dpDelay - std::max( tunedPDelay, tunedNDelay );
496 }
497
498 tuneLineLength( m_result, m_settings.m_targetLength.Opt() - dpLen );
499 }
500
501 if( m_lastStatus != TOO_LONG )
502 {
503 tunedP.Clear();
504 tunedN.Clear();
505
506 for( MEANDER_SHAPE* m : m_result.Meanders() )
507 {
508 if( m->Type() != MT_EMPTY )
509 {
510 tunedP.Append( m->CLine( 0 ) );
511 tunedN.Append( m->CLine( 1 ) );
512 }
513 }
514
515 m_lastLength += std::max( tunedP.Length(), tunedN.Length() );
516
517 if( m_settings.m_isTimeDomain )
518 {
519 int64_t tunedPDelay = m_router->GetInterface()->CalculateDelayForShapeLineChain(
520 tunedP, GetOriginPair().Width(), true, GetOriginPair().Gap(), m_router->GetCurrentLayer(),
521 m_netClass );
522 int64_t tunedNDelay = m_router->GetInterface()->CalculateDelayForShapeLineChain(
523 tunedN, GetOriginPair().Width(), true, GetOriginPair().Gap(), m_router->GetCurrentLayer(),
524 m_netClass );
525
526 m_lastDelay += std::max( tunedPDelay, tunedNDelay );
527 }
528
529 updateStatus();
530 }
531
532 m_finalShapeP.Clear();
533 m_finalShapeN.Clear();
534
535 if( m_settings.m_keepEndpoints )
536 {
537 preP.Simplify();
538 tunedP.Simplify();
539 postP.Simplify();
540
541 m_finalShapeP.Append( preP );
542 m_finalShapeP.Append( tunedP );
543 m_finalShapeP.Append( postP );
544
545 preN.Simplify();
546 tunedN.Simplify();
547 postN.Simplify();
548
549 m_finalShapeN.Append( preN );
550 m_finalShapeN.Append( tunedN );
551 m_finalShapeN.Append( postN );
552 }
553 else
554 {
555 m_finalShapeP.Append( preP );
556 m_finalShapeP.Append( tunedP );
557 m_finalShapeP.Append( postP );
558 m_finalShapeP.Simplify();
559
560 m_finalShapeN.Append( preN );
561 m_finalShapeN.Append( tunedN );
562 m_finalShapeN.Append( postN );
563 m_finalShapeN.Simplify();
564 }
565
566 return true;
567}
568
569
570bool DP_MEANDER_PLACER::FixRoute( const VECTOR2I& aP, ITEM* aEndItem, bool aForceFinish )
571{
572 LINE lP( m_originPair.PLine(), m_finalShapeP );
573 LINE lN( m_originPair.NLine(), m_finalShapeN );
574
575 m_currentNode->Add( lP );
576 m_currentNode->Add( lN );
577
579
580 return true;
581}
582
583
585{
586 m_world->KillChildren();
587 return true;
588}
589
590
592{
593 return m_originPair.CP().SegmentCount() > 0 || m_originPair.CN().SegmentCount() > 0;
594}
595
596
598{
599 if( m_currentNode )
601
602 m_currentNode = nullptr;
603 return true;
604}
605
606
608{
609 LINE l1( m_originPair.PLine(), aShape->CLine( 0 ) );
610 LINE l2( m_originPair.NLine(), aShape->CLine( 1 ) );
611
612 if( m_currentNode->CheckColliding( &l1 ) )
613 return false;
614
615 if( m_currentNode->CheckColliding( &l2 ) )
616 return false;
617
618 int w = aShape->Width();
619 int clearance = w + w * 3;
620
621 return m_result.CheckSelfIntersections( aShape, clearance );
622}
623
624
626{
629
630 ITEM_SET traces;
631
632 traces.Add( &m_currentTraceP );
633 traces.Add( &m_currentTraceN );
634
635 return traces;
636}
637
638
640{
641 ITEM_SET lines;
642
643 for( ITEM* item : m_tunedPathN )
644 lines.Add( item );
645
646 for( ITEM* item : m_tunedPathP )
647 lines.Add( item );
648
649 return lines;
650}
651
652
654{
655 return m_currentStart;
656}
657
658
660{
661 return m_currentEnd;
662}
663
664
666{
667 return m_initialSegment->Layers().Start();
668}
669
670
672{
673 if( m_lastLength )
674 return m_lastLength;
675 else
676 return origPathLength();
677}
678
679
681{
682 if( m_lastDelay )
683 return m_lastDelay;
684 else
685 return origPathDelay();
686}
687
688
693
694
695const std::vector<NET_HANDLE> DP_MEANDER_PLACER::CurrentNets() const
696{
697 std::vector<NET_HANDLE> rv;
698 rv.push_back( m_originPair.NetP() );
699 rv.push_back( m_originPair.NetN() );
700 return rv;
701}
702
703
705{
706 // If this is a time domain tuning, calculate the target length for the desired total delay
707 if( m_settings.m_isTimeDomain )
708 {
709 const int64_t curDelayChain = origPathDelay();
710 const int64_t curDelayPair = curDelayChain - m_settings.m_signalExtraDelay; // subtract other nets
711
712 bool useSignalTarget = ( m_settings.m_targetSignalLengthDelay.Opt() != MEANDER_SETTINGS::DELAY_UNCONSTRAINED );
713 const MINOPTMAX<long long int>& targetDelaySet = useSignalTarget ? m_settings.m_targetSignalLengthDelay
714 : m_settings.m_targetLengthDelay;
715
716 int64_t desiredDelayMin = targetDelaySet.Min();
717 int64_t desiredDelayOpt = targetDelaySet.Opt();
718 int64_t desiredDelayMax = targetDelaySet.Max();
719
720 if( useSignalTarget )
721 {
722 desiredDelayMin = std::max<int64_t>( 0, desiredDelayMin - m_settings.m_signalExtraDelay );
723 desiredDelayOpt = std::max<int64_t>( 0, desiredDelayOpt - m_settings.m_signalExtraDelay );
724 desiredDelayMax = std::max<int64_t>( desiredDelayOpt, desiredDelayMax - m_settings.m_signalExtraDelay );
725 }
726
727 const int64_t curDelay = useSignalTarget ? curDelayPair : curDelayChain;
728
729 const int64_t delayDifferenceOpt = desiredDelayOpt - curDelay;
730
731 const int64_t curLength = origPathLength();
732 const int64_t lengthDiffMin = m_router->GetInterface()->CalculateLengthForDelay(
733 desiredDelayOpt - desiredDelayMin, GetOriginPair().Width(), true, GetOriginPair().Gap(),
734 m_router->GetCurrentLayer(), m_netClass );
735 int64_t lengthDiffOpt = m_router->GetInterface()->CalculateLengthForDelay(
736 std::abs( delayDifferenceOpt ), GetOriginPair().Width(), true, GetOriginPair().Gap(),
737 m_router->GetCurrentLayer(), m_netClass );
738 const int64_t lengthDiffMax = m_router->GetInterface()->CalculateLengthForDelay(
739 desiredDelayMax - desiredDelayOpt, GetOriginPair().Width(), true, GetOriginPair().Gap(),
740 m_router->GetCurrentLayer(), m_netClass );
741
742 lengthDiffOpt = delayDifferenceOpt > 0 ? lengthDiffOpt : -lengthDiffOpt;
743
744 m_settings.m_targetLength.SetMin( curLength + lengthDiffOpt - lengthDiffMin );
745 m_settings.m_targetLength.SetOpt( curLength + lengthDiffOpt );
746 m_settings.m_targetLength.SetMax( curLength + lengthDiffOpt + lengthDiffMax );
747 }
748}
749}
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:33
T Max() const
Definition minoptmax.h:34
T Opt() const
Definition minoptmax.h:35
ROUTER * Router() const
Return current router settings.
ROUTER * m_router
DEBUG_DECORATOR * Dbg() const
Basic class for a differential pair.
int Width() const
std::vector< COUPLED_SEGMENTS > COUPLED_SEGMENTS_VEC
void SetShape(const SHAPE_LINE_CHAIN &aP, const SHAPE_LINE_CHAIN &aN, bool aSwapLanes=false)
int Gap() const
void CoupledSegmentPairs(COUPLED_SEGMENTS_VEC &aPairs) 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...
int64_t m_baselineDelay
Aggregate length/delay of other nets in the same chain, cached at Start().
TUNING_STATUS
< Result of the length tuning operation
int m_currentWidth
Meander settings.
bool m_chainExtrasValid
Pointer to world to search colliding items.
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).
VECTOR2I getSnappedStartPoint(LINKED_ITEM *aStartItem, VECTOR2I aStartPoint)
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:240
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:235
void CommitRouting()
NODE * GetWorld() const
Definition pns_router.h:186
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:42
VECTOR2I A
Definition seg.h:49
VECTOR2I B
Definition seg.h:50
int Side(const VECTOR2I &aP) const
Determine on which side of directed line passing via segment ends point aP lies.
Definition seg.h:143
VECTOR2I GetEnd() const override
Definition shape_arc.h:208
VECTOR2I GetStart() const override
Definition shape_arc.h:207
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:57
@ YELLOW
Definition color4d.h:67
#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:400
#define PNS_DBG(dbg, method,...)
int clearance
Casted dyn_cast(From aObject)
A lightweight dynamic downcast.
Definition typeinfo.h:60
VECTOR2< int32_t > VECTOR2I
Definition vector2d.h:687