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_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.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
160
161 const BOARD_CONNECTED_ITEM* conItem = static_cast<BOARD_CONNECTED_ITEM*>( aStartItem->GetSourceItem() );
162 m_netClass = conItem->GetEffectiveNetClass();
163
165 m_baselineDelay = m_settings.m_isTimeDomain ? origPathDelay() : 0;
166
168
170
171 return true;
172}
173
174
178
179
181{
184 return std::max( totalP, totalN );
185}
186
187
189{
190 const int64_t totalP = m_padToDieDelayP + lineDelay( m_tunedPathP, m_startPad_p, m_endPad_p );
191 const int64_t totalN = m_padToDieDelayN + lineDelay( m_tunedPathN, m_startPad_n, m_endPad_n );
192 return std::max( totalP, totalN );
193}
194
195
197{
198 const VECTOR2I a( ( aCoupledSegs.coupledP.A + aCoupledSegs.coupledN.A ) / 2 );
199 const VECTOR2I b( ( aCoupledSegs.coupledP.B + aCoupledSegs.coupledN.B ) / 2 );
200
201 return SEG( a, b );
202}
203
204
206{
207 VECTOR2I midp = ( aPair.coupledP.A + aPair.coupledN.A ) / 2;
208
209 //DrawDebugPoint(midp, 6);
210
211 return aPair.coupledP.Side( midp ) > 0;
212}
213
214
215bool DP_MEANDER_PLACER::Move( const VECTOR2I& aP, ITEM* aEndItem )
216{
217 // Reuse the chain-extras aggregate captured at Start(). Other nets in the chain are
218 // not edited during a tuning session, so we don't need to walk the BOARD again.
219 const long long extraDelay = m_chainExtrasValid ? m_chainExtrasDelay : 0;
220
221 m_settings.m_signalExtraDelay = extraDelay;
222
223 // Derive per-net budget from chain target, accounting for stubs not in the PNS path.
224 // Take the tighter of chain budget and existing per-net constraint.
225 if( m_settings.m_targetSignalLength.Opt() != MEANDER_SETTINGS::LENGTH_UNCONSTRAINED )
226 {
227 const long long otherLen = chainNarrowingOffset();
228
229 long long budgetMin = std::max( 0LL, m_settings.m_targetSignalLength.Min() - otherLen );
230 long long budgetOpt = std::max( 0LL, m_settings.m_targetSignalLength.Opt() - otherLen );
231 long long budgetMax = std::max( budgetOpt, m_settings.m_targetSignalLength.Max() - otherLen );
232
233 if( m_settings.m_targetLength.Opt() == MEANDER_SETTINGS::LENGTH_UNCONSTRAINED )
234 {
235 m_settings.m_targetLength.SetMin( budgetMin );
236 m_settings.m_targetLength.SetOpt( budgetOpt );
237 m_settings.m_targetLength.SetMax( budgetMax );
238 }
239 else
240 {
241 m_settings.m_targetLength.SetMin( std::max( m_settings.m_targetLength.Min(), budgetMin ) );
242 m_settings.m_targetLength.SetOpt( std::min( m_settings.m_targetLength.Opt(), budgetOpt ) );
243 m_settings.m_targetLength.SetMax( std::min( m_settings.m_targetLength.Max(), budgetMax ) );
244 }
245 }
246
248
249 if( m_currentStart == aP )
250 return false;
251
252 DIFF_PAIR::COUPLED_SEGMENTS_VEC coupledSegments;
253
254 if( m_currentNode )
255 delete m_currentNode;
256
257 m_currentNode = m_world->Branch();
258
259 SHAPE_LINE_CHAIN preP, tunedP, postP;
260 SHAPE_LINE_CHAIN preN, tunedN, postN;
261
262 m_originPair.CP().Split( m_currentStart, aP, preP, tunedP, postP );
263 m_originPair.CN().Split( m_currentStart, aP, preN, tunedN, postN );
264
265 tunedP.Simplify();
266 tunedN.Simplify();
267
268 // Bail out early if the tuned sections are empty (issue #22041). This can happen when the
269 // split points are too close together or outside the line chain.
270 if( tunedP.PointCount() == 0 || tunedN.PointCount() == 0 )
271 {
276
277 return false;
278 }
279
280 auto updateStatus =
281 [&]()
282 {
283 if( m_lastLength > m_settings.m_targetLength.Max() )
285 else if( m_lastLength < m_settings.m_targetLength.Min() )
287 else
289 };
290
291 DIFF_PAIR tuned( m_originPair );
292
293 tuned.SetShape( tunedP, tunedN );
294
295 tuned.CoupledSegmentPairs( coupledSegments );
296
297 if( coupledSegments.size() == 0 )
298 {
299 // Tuning started at an uncoupled area of the DP; we won't get a valid result until the
300 // cursor is moved far enough along a coupled area. Prevent the track from disappearing and
301 // the length from being zero by just using the original.
305 updateStatus();
306
307 return false;
308 }
309
310 m_result = MEANDERED_LINE( this, true );
311 m_result.SetWidth( tuned.Width() );
312
313 int offset = ( tuned.Gap() + tuned.Width() ) / 2;
314
315 if( pairOrientation( coupledSegments[0] ) )
316 offset *= -1;
317
318 m_result.SetBaselineOffset( offset );
319
320 for( const ITEM* item : m_tunedPathP.CItems() )
321 {
322 if( const LINE* l = dyn_cast<const LINE*>( item ) )
323 {
324 PNS_DBG( Dbg(), AddShape, &l->CLine(), YELLOW, 10000, wxT( "tuned-path-p" ) );
325
326 m_router->GetInterface()->DisplayPathLine( l->CLine(), 1 );
327 }
328 }
329
330 for( const ITEM* item : m_tunedPathN.CItems() )
331 {
332 if( const LINE* l = dyn_cast<const LINE*>( item ) )
333 {
334 PNS_DBG( Dbg(), AddShape, &l->CLine(), YELLOW, 10000, wxT( "tuned-path-n" ) );
335
336 m_router->GetInterface()->DisplayPathLine( l->CLine(), 1 );
337 }
338 }
339
340 struct GET_ITEM_RET
341 {
342 std::optional<SHAPE_ARC> arc;
343 VECTOR2I startPt;
344 VECTOR2I endPt;
345 };
346
347 auto getItem = [&]( const SHAPE_LINE_CHAIN& aChain, int aIndex, int aLastIndex )
348 {
349 std::optional<SHAPE_ARC> optArc;
350 VECTOR2I startPt;
351 VECTOR2I endPt;
352
353 if( aChain.IsArcSegment( aIndex ) )
354 {
355 SHAPE_ARC arc = aChain.Arc( aChain.ArcIndex( aIndex ) );
356 optArc = arc;
357 startPt = arc.GetStart();
358 endPt = arc.GetEnd();
359 }
360 else
361 {
362 SEG seg = aChain.GetSegment( aIndex );
363 startPt = seg.A;
364 endPt = seg.B;
365 }
366
367 return GET_ITEM_RET{ optArc, startPt, endPt };
368 };
369
370 auto checkIndex = [&]( bool& aOk, int aCurIndex, int aLastIndex ) -> bool
371 {
372 aOk = aCurIndex <= aLastIndex && aCurIndex != -1;
373 return aOk;
374 };
375
376 int curIndexP = 0, curIndexN = 0;
377
378 auto addCornersUntilIndex = [&]( int aLastIndexP, int aLastIndexN )
379 {
380 while( true )
381 {
382 bool p_ok, n_ok;
383 checkIndex( p_ok, curIndexP, aLastIndexP );
384 checkIndex( n_ok, curIndexN, aLastIndexN );
385
386 if( !p_ok && !n_ok )
387 break;
388
389 auto p_item = getItem( tunedP, curIndexP, aLastIndexP );
390 auto n_item = getItem( tunedN, curIndexN, aLastIndexN );
391
392 if( !p_item.arc && !n_item.arc )
393 {
394 m_result.AddCorner( p_item.startPt, n_item.startPt );
395 }
396 else if( p_item.arc && n_item.arc )
397 {
398 m_result.AddArc( *p_item.arc, *n_item.arc );
399 }
400 else if( p_item.arc && !n_item.arc )
401 {
402 m_result.AddCorner( p_item.startPt, n_item.startPt );
403
404 // Find arc in N
405 while( checkIndex( n_ok, curIndexN, aLastIndexN ) )
406 {
407 curIndexN = tunedN.NextShape( curIndexN );
408 n_item = getItem( tunedN, curIndexN, aLastIndexN );
409
410 if( n_item.arc )
411 {
412 m_result.AddArc( *p_item.arc, *n_item.arc );
413 break;
414 }
415 else
416 {
417 m_result.AddCorner( p_item.startPt, n_item.startPt );
418 }
419 }
420 }
421 else if( !p_item.arc && n_item.arc )
422 {
423 m_result.AddCorner( p_item.startPt, n_item.startPt );
424
425 // Find arc in P
426 while( checkIndex( p_ok, curIndexP, aLastIndexP ) )
427 {
428 curIndexP = tunedP.NextShape( curIndexP );
429 p_item = getItem( tunedP, curIndexP, aLastIndexP );
430
431 if( p_item.arc )
432 {
433 m_result.AddArc( *p_item.arc, *n_item.arc );
434 break;
435 }
436 else
437 {
438 m_result.AddCorner( p_item.startPt, n_item.startPt );
439 }
440 }
441 }
442
443 if( p_ok )
444 curIndexP = tunedP.NextShape( curIndexP );
445
446 if( n_ok )
447 curIndexN = tunedN.NextShape( curIndexN );
448 }
449 };
450
451 for( const DIFF_PAIR::COUPLED_SEGMENTS& sp : coupledSegments )
452 {
453 SEG base = baselineSegment( sp );
454 bool side = false;
455
456 if( m_settings.m_initialSide == 0 )
457 side = base.Side( aP ) < 0;
458 else
459 side = m_settings.m_initialSide < 0;
460
461 PNS_DBG( Dbg(), AddShape, base, GREEN, 10000, wxT( "dp-baseline" ) );
462
463 addCornersUntilIndex( sp.indexP, sp.indexN );
464
465 m_result.MeanderSegment( base, side );
466 }
467
468 addCornersUntilIndex( tunedP.PointCount() - 1, tunedN.PointCount() - 1 );
469
470 m_result.AddCorner( tunedP.CLastPoint(), tunedN.CLastPoint() );
471
472 long long int dpLen = origPathLength();
473 int64_t dpDelay = origPathDelay();
474
476
477 if( dpLen > m_settings.m_targetLength.Max() )
478 {
480 m_lastLength = dpLen;
481 m_lastDelay = dpDelay;
482 }
483 else
484 {
485 m_lastLength = dpLen - std::max( tunedP.Length(), tunedN.Length() );
486
487 if( m_settings.m_isTimeDomain )
488 {
489 int64_t tunedPDelay = m_router->GetInterface()->CalculateDelayForShapeLineChain(
490 tunedP, GetOriginPair().Width(), true, GetOriginPair().Gap(), m_router->GetCurrentLayer(),
491 m_netClass );
492 int64_t tunedNDelay = m_router->GetInterface()->CalculateDelayForShapeLineChain(
493 tunedN, GetOriginPair().Width(), true, GetOriginPair().Gap(), m_router->GetCurrentLayer(),
494 m_netClass );
495
496 m_lastDelay = dpDelay - std::max( tunedPDelay, tunedNDelay );
497 }
498
499 tuneLineLength( m_result, m_settings.m_targetLength.Opt() - dpLen );
500 }
501
502 if( m_lastStatus != TOO_LONG )
503 {
504 tunedP.Clear();
505 tunedN.Clear();
506
507 for( MEANDER_SHAPE* m : m_result.Meanders() )
508 {
509 if( m->Type() != MT_EMPTY )
510 {
511 tunedP.Append( m->CLine( 0 ) );
512 tunedN.Append( m->CLine( 1 ) );
513 }
514 }
515
516 m_lastLength += std::max( tunedP.Length(), tunedN.Length() );
517
518 if( m_settings.m_isTimeDomain )
519 {
520 int64_t tunedPDelay = m_router->GetInterface()->CalculateDelayForShapeLineChain(
521 tunedP, GetOriginPair().Width(), true, GetOriginPair().Gap(), m_router->GetCurrentLayer(),
522 m_netClass );
523 int64_t tunedNDelay = m_router->GetInterface()->CalculateDelayForShapeLineChain(
524 tunedN, GetOriginPair().Width(), true, GetOriginPair().Gap(), m_router->GetCurrentLayer(),
525 m_netClass );
526
527 m_lastDelay += std::max( tunedPDelay, tunedNDelay );
528 }
529
530 updateStatus();
531 }
532
533 m_finalShapeP.Clear();
534 m_finalShapeN.Clear();
535
536 if( m_settings.m_keepEndpoints )
537 {
538 preP.Simplify();
539 tunedP.Simplify();
540 postP.Simplify();
541
542 m_finalShapeP.Append( preP );
543 m_finalShapeP.Append( tunedP );
544 m_finalShapeP.Append( postP );
545
546 preN.Simplify();
547 tunedN.Simplify();
548 postN.Simplify();
549
550 m_finalShapeN.Append( preN );
551 m_finalShapeN.Append( tunedN );
552 m_finalShapeN.Append( postN );
553 }
554 else
555 {
556 m_finalShapeP.Append( preP );
557 m_finalShapeP.Append( tunedP );
558 m_finalShapeP.Append( postP );
559 m_finalShapeP.Simplify();
560
561 m_finalShapeN.Append( preN );
562 m_finalShapeN.Append( tunedN );
563 m_finalShapeN.Append( postN );
564 m_finalShapeN.Simplify();
565 }
566
567 return true;
568}
569
570
571bool DP_MEANDER_PLACER::FixRoute( const VECTOR2I& aP, ITEM* aEndItem, bool aForceFinish )
572{
573 LINE lP( m_originPair.PLine(), m_finalShapeP );
574 LINE lN( m_originPair.NLine(), m_finalShapeN );
575
576 m_currentNode->Add( lP );
577 m_currentNode->Add( lN );
578
580
581 return true;
582}
583
584
586{
587 m_world->KillChildren();
588 return true;
589}
590
591
593{
594 return m_originPair.CP().SegmentCount() > 0 || m_originPair.CN().SegmentCount() > 0;
595}
596
597
599{
600 if( m_currentNode )
602
603 m_currentNode = nullptr;
604 return true;
605}
606
607
609{
610 LINE l1( m_originPair.PLine(), aShape->CLine( 0 ) );
611 LINE l2( m_originPair.NLine(), aShape->CLine( 1 ) );
612
613 if( m_currentNode->CheckColliding( &l1 ) )
614 return false;
615
616 if( m_currentNode->CheckColliding( &l2 ) )
617 return false;
618
619 int w = aShape->Width();
620 int clearance = w + w * 3;
621
622 return m_result.CheckSelfIntersections( aShape, clearance );
623}
624
625
627{
630
631 ITEM_SET traces;
632
633 traces.Add( &m_currentTraceP );
634 traces.Add( &m_currentTraceN );
635
636 return traces;
637}
638
639
641{
642 ITEM_SET lines;
643
644 for( ITEM* item : m_tunedPathN )
645 lines.Add( item );
646
647 for( ITEM* item : m_tunedPathP )
648 lines.Add( item );
649
650 return lines;
651}
652
653
655{
656 return m_currentStart;
657}
658
659
661{
662 return m_currentEnd;
663}
664
665
667{
668 return m_initialSegment->Layers().Start();
669}
670
671
673{
674 if( m_lastLength )
675 return m_lastLength;
676 else
677 return origPathLength();
678}
679
680
682{
683 if( m_lastDelay )
684 return m_lastDelay;
685 else
686 return origPathDelay();
687}
688
689
694
695
696const std::vector<NET_HANDLE> DP_MEANDER_PLACER::CurrentNets() const
697{
698 std::vector<NET_HANDLE> rv;
699 rv.push_back( m_originPair.NetP() );
700 rv.push_back( m_originPair.NetN() );
701 return rv;
702}
703
704
706{
707 // If this is a time domain tuning, calculate the target length for the desired total delay
708 if( m_settings.m_isTimeDomain )
709 {
710 const int64_t curDelayChain = origPathDelay();
711 const int64_t curDelayPair = curDelayChain - m_settings.m_signalExtraDelay; // subtract other nets
712
713 bool useSignalTarget = ( m_settings.m_targetSignalLengthDelay.Opt() != MEANDER_SETTINGS::DELAY_UNCONSTRAINED );
714 const MINOPTMAX<long long int>& targetDelaySet = useSignalTarget ? m_settings.m_targetSignalLengthDelay
715 : m_settings.m_targetLengthDelay;
716
717 int64_t desiredDelayMin = targetDelaySet.Min();
718 int64_t desiredDelayOpt = targetDelaySet.Opt();
719 int64_t desiredDelayMax = targetDelaySet.Max();
720
721 if( useSignalTarget )
722 {
723 desiredDelayMin = std::max<int64_t>( 0, desiredDelayMin - m_settings.m_signalExtraDelay );
724 desiredDelayOpt = std::max<int64_t>( 0, desiredDelayOpt - m_settings.m_signalExtraDelay );
725 desiredDelayMax = std::max<int64_t>( desiredDelayOpt, desiredDelayMax - m_settings.m_signalExtraDelay );
726 }
727
728 const int64_t curDelay = useSignalTarget ? curDelayPair : curDelayChain;
729
730 const int64_t delayDifferenceOpt = desiredDelayOpt - curDelay;
731
732 const int64_t curLength = origPathLength();
733 const int64_t lengthDiffMin = m_router->GetInterface()->CalculateLengthForDelay(
734 desiredDelayOpt - desiredDelayMin, GetOriginPair().Width(), true, GetOriginPair().Gap(),
735 m_router->GetCurrentLayer(), m_netClass );
736 int64_t lengthDiffOpt = m_router->GetInterface()->CalculateLengthForDelay(
737 std::abs( delayDifferenceOpt ), GetOriginPair().Width(), true, GetOriginPair().Gap(),
738 m_router->GetCurrentLayer(), m_netClass );
739 const int64_t lengthDiffMax = m_router->GetInterface()->CalculateLengthForDelay(
740 desiredDelayMax - desiredDelayOpt, GetOriginPair().Width(), true, GetOriginPair().Gap(),
741 m_router->GetCurrentLayer(), m_netClass );
742
743 lengthDiffOpt = delayDifferenceOpt > 0 ? lengthDiffOpt : -lengthDiffOpt;
744
745 m_settings.m_targetLength.SetMin( curLength + lengthDiffOpt - lengthDiffMin );
746 m_settings.m_targetLength.SetOpt( curLength + lengthDiffOpt );
747 m_settings.m_targetLength.SetMax( curLength + lengthDiffOpt + lengthDiffMax );
748 }
749}
750}
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).
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:242
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,...)
static VECTOR2I GetSnappedStartPoint(LINKED_ITEM *aStartItem, VECTOR2I aStartPoint)
int clearance
Casted dyn_cast(From aObject)
A lightweight dynamic downcast.
Definition typeinfo.h:60
VECTOR2< int32_t > VECTOR2I
Definition vector2d.h:687