KiCad PCB EDA Suite
Loading...
Searching...
No Matches
length_delay_calculation.cpp
Go to the documentation of this file.
1/*
2* This program source code file is part of KiCad, a free EDA CAD application.
3 *
4 * Copyright The KiCad Developers, see AUTHORS.txt for contributors.
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * as published by the Free Software Foundation; either version 2
9 * of the License, or (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, you may find one here:
18 * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
19 * or you may search the http://www.gnu.org website for the version 2 license,
20 * or you may write to the Free Software Foundation, Inc.,
21 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
22 */
23
25
26#include <board.h>
29
30
32 bool aForward )
33{
34 const int start = aForward ? 0 : aLine.PointCount() - 1;
35 const int delta = aForward ? 1 : -1;
36
37 // Note: we don't apply the clip-to-pad optimization if an arc ends in a pad
38 // Room for future improvement.
39 if( aLine.IsPtOnArc( start ) )
40 return;
41
42 const auto& shape = aPad->GetEffectivePolygon( aLayer, ERROR_INSIDE );
43
44 // Skip the "first" (or last) vertex, we already know it's contained in the pad
45 int clip = start;
46
47 for( int vertex = start + delta; aForward ? vertex < aLine.PointCount() : vertex >= 0; vertex += delta )
48 {
49 SEG seg( aLine.GetPoint( vertex ), aLine.GetPoint( vertex - delta ) );
50
51 bool containsA = shape->Contains( seg.A );
52 bool containsB = shape->Contains( seg.B );
53
54 if( containsA && containsB )
55 {
56 // Whole segment is inside: clip out this segment
57 clip = vertex;
58 }
59 else if( containsB )
60 {
61 // Only one point inside: Find the intersection
62 VECTOR2I loc;
63
64 if( shape->Collide( seg, 0, nullptr, &loc ) )
65 {
66 aLine.Replace( vertex - delta, vertex - delta, loc );
67 }
68 }
69 }
70
71 if( !aForward && clip < start )
72 aLine.Remove( clip + 1, start );
73 else if( clip > start )
74 aLine.Remove( start, clip - 1 );
75
76 // Now connect the dots
77 aLine.Insert( aForward ? 0 : aLine.PointCount(), aPad->GetPosition() );
78}
79
80
81LENGTH_DELAY_STATS LENGTH_DELAY_CALCULATION::CalculateLengthDetails( std::vector<LENGTH_DELAY_CALCULATION_ITEM>& aItems,
82 const PATH_OPTIMISATIONS aOptimisations,
83 const PAD* aStartPad, const PAD* aEndPad,
84 const LENGTH_DELAY_LAYER_OPT aLayerOpt,
85 const LENGTH_DELAY_DOMAIN_OPT aDomain ) const
86{
87 // If this set of items has not been optimised, optimise for shortest electrical path
88 if( aOptimisations.OptimiseViaLayers || aOptimisations.MergeTracks || aOptimisations.MergeTracks )
89 {
90 std::vector<LENGTH_DELAY_CALCULATION_ITEM*> pads;
91 std::vector<LENGTH_DELAY_CALCULATION_ITEM*> lines;
92 std::vector<LENGTH_DELAY_CALCULATION_ITEM*> vias;
93
94 // Map of line endpoints to line objects
95 std::map<VECTOR2I, std::unordered_set<LENGTH_DELAY_CALCULATION_ITEM*>> linesPositionMap;
96
97 // Map of pad positions to pad objects
98 std::map<VECTOR2I, std::unordered_set<LENGTH_DELAY_CALCULATION_ITEM*>> padsPositionMap;
99
100 for( LENGTH_DELAY_CALCULATION_ITEM& item : aItems )
101 {
102 if( item.Type() == LENGTH_DELAY_CALCULATION_ITEM::TYPE::PAD )
103 {
104 pads.emplace_back( &item );
105 padsPositionMap[item.GetPad()->GetPosition()].insert( &item );
106 }
107 else if( item.Type() == LENGTH_DELAY_CALCULATION_ITEM::TYPE::VIA )
108 {
109 vias.emplace_back( &item );
110 }
111 else if( item.Type() == LENGTH_DELAY_CALCULATION_ITEM::TYPE::LINE )
112 {
113 lines.emplace_back( &item );
114 linesPositionMap[item.GetLine().CPoint( 0 )].insert( &item );
115 linesPositionMap[item.GetLine().CLastPoint()].insert( &item );
116 }
117 }
118
119 if( aOptimisations.OptimiseViaLayers )
120 optimiseViaLayers( vias, lines, linesPositionMap, padsPositionMap );
121
122 if( aOptimisations.MergeTracks )
123 mergeLines( lines, linesPositionMap );
124
125 if( aOptimisations.OptimiseTracesInPads )
126 optimiseTracesInPads( pads, lines );
127 }
128
129 LENGTH_DELAY_STATS details;
130
131 // Create the layer detail maps if required
132 if( aLayerOpt == LENGTH_DELAY_LAYER_OPT::WITH_LAYER_DETAIL )
133 {
134 details.LayerLengths = std::make_unique<std::map<PCB_LAYER_ID, int64_t>>();
135
136 if( aDomain == LENGTH_DELAY_DOMAIN_OPT::WITH_DELAY_DETAIL )
137 details.LayerDelays = std::make_unique<std::map<PCB_LAYER_ID, int64_t>>();
138 }
139
140 const bool useHeight = m_board->GetDesignSettings().m_UseHeightForLengthCalcs;
141
142 // If this is a contiguous set of items, check if we have an inferred fanout via at either end. Note that this
143 // condition only arises as a result of how PNS assembles tuning paths - for DRC / net inspector calculations these
144 // fanout vias will be present in the object set and therefore do not need to be inferred
145 if( aOptimisations.InferViaInPad && useHeight )
146 {
147 inferViaInPad( aStartPad, aItems.front(), details );
148 inferViaInPad( aEndPad, aItems.back(), details );
149 }
150
151 // Add stats for each item
152 for( const LENGTH_DELAY_CALCULATION_ITEM& item : aItems )
153 {
154 // Don't include merged items
156 || item.Type() == LENGTH_DELAY_CALCULATION_ITEM::TYPE::UNKNOWN )
157 {
158 continue;
159 }
160
161 // Calculate the space domain statistics
162 if( item.Type() == LENGTH_DELAY_CALCULATION_ITEM::TYPE::LINE )
163 {
164 const int64_t length = item.GetLine().Length();
165
166 details.TrackLength += length;
167
168 if( details.LayerLengths )
169 ( *details.LayerLengths )[item.GetStartLayer()] += length;
170 }
171 else if( item.Type() == LENGTH_DELAY_CALCULATION_ITEM::TYPE::VIA && useHeight )
172 {
173 const auto [layerStart, layerEnd] = item.GetLayers();
174 details.ViaLength += StackupHeight( layerStart, layerEnd );
175 details.NumVias += 1;
176 }
177 else if( item.Type() == LENGTH_DELAY_CALCULATION_ITEM::TYPE::PAD )
178 {
179 details.PadToDieLength += item.GetPad()->GetPadToDieLength();
180 details.NumPads += 1;
181 }
182 }
183
184 // Calculate the time domain statistics if required
185 if( aDomain == LENGTH_DELAY_DOMAIN_OPT::WITH_DELAY_DETAIL && !aItems.empty() )
186 {
187 // TODO(JJ): Populate this
189 ctx.NetClass = aItems.front().GetEffectiveNetClass(); // We don't care if this is merged for net class lookup
190
191 const std::vector<int64_t> itemDelays = m_timeDomainParameters->GetPropagationDelays( aItems, ctx );
192
193 wxASSERT( itemDelays.size() == aItems.size() );
194
195 for( size_t i = 0; i < aItems.size(); ++i )
196 {
197 const LENGTH_DELAY_CALCULATION_ITEM& item = aItems[i];
198
199 if( item.Type() == LENGTH_DELAY_CALCULATION_ITEM::TYPE::LINE )
200 {
201 details.TrackDelay += itemDelays[i];
202
203 if( details.LayerDelays )
204 ( *details.LayerDelays )[item.GetStartLayer()] += itemDelays[i];
205 }
206 else if( item.Type() == LENGTH_DELAY_CALCULATION_ITEM::TYPE::VIA && useHeight )
207 {
208 details.ViaDelay += itemDelays[i];
209 }
210 else if( item.Type() == LENGTH_DELAY_CALCULATION_ITEM::TYPE::PAD )
211 {
212 details.PadToDieDelay += itemDelays[i];
213 }
214 }
215 }
216
217 return details;
218}
219
220
222 LENGTH_DELAY_STATS& aDetails ) const
223{
224 if( aPad && aItem.Type() == LENGTH_DELAY_CALCULATION_ITEM::TYPE::LINE )
225 {
226 const PCB_LAYER_ID startBottomLayer = aItem.GetStartLayer();
227 const LSET padLayers = aPad->Padstack().LayerSet();
228
229 if( !padLayers.Contains( startBottomLayer ) )
230 {
231 // This must be either F_Cu or B_Cu
232 const PCB_LAYER_ID padLayer = padLayers.Contains( F_Cu ) ? F_Cu : B_Cu;
233
234 aDetails.NumVias += 1;
235 aDetails.ViaLength += StackupHeight( startBottomLayer, padLayer );
236 }
237 }
238}
239
240
241int64_t LENGTH_DELAY_CALCULATION::CalculateLength( std::vector<LENGTH_DELAY_CALCULATION_ITEM>& aItems,
242 const PATH_OPTIMISATIONS aOptimisations, const PAD* aStartPad,
243 const PAD* aEndPad ) const
244{
245 return CalculateLengthDetails( aItems, aOptimisations, aStartPad, aEndPad ).TotalLength();
246}
247
248
249int64_t LENGTH_DELAY_CALCULATION::CalculateDelay( std::vector<LENGTH_DELAY_CALCULATION_ITEM>& aItems,
250 const PATH_OPTIMISATIONS aOptimisations, const PAD* aStartPad,
251 const PAD* aEndPad ) const
252{
253 return CalculateLengthDetails( aItems, aOptimisations, aStartPad, aEndPad, LENGTH_DELAY_LAYER_OPT::NO_LAYER_DETAIL,
254 LENGTH_DELAY_DOMAIN_OPT::WITH_DELAY_DETAIL )
255 .TotalDelay();
256}
257
258
259int LENGTH_DELAY_CALCULATION::StackupHeight( const PCB_LAYER_ID aFirstLayer, const PCB_LAYER_ID aSecondLayer ) const
260{
262 return 0;
263
265 {
267 return stackup.GetLayerDistance( aFirstLayer, aSecondLayer );
268 }
269 else
270 {
271 BOARD_STACKUP stackup;
273 return stackup.GetLayerDistance( aFirstLayer, aSecondLayer );
274 }
275}
276
277
279 std::vector<LENGTH_DELAY_CALCULATION_ITEM*>& aLines,
280 std::map<VECTOR2I, std::unordered_set<LENGTH_DELAY_CALCULATION_ITEM*>>& aLinesPositionMap )
281{
282 // Vector of pads, and an associated flag to indicate whether they have been visited by the clustering algorithm
283 std::vector<LENGTH_DELAY_CALCULATION_ITEM*> pads;
284
285 auto removeFromPositionMap = [&aLinesPositionMap]( LENGTH_DELAY_CALCULATION_ITEM* line )
286 {
287 aLinesPositionMap[line->GetLine().CPoint( 0 )].erase( line );
288 aLinesPositionMap[line->GetLine().CLastPoint()].erase( line );
289 };
290
291 // Attempts to merge unmerged lines in to aPrimaryLine
292 auto tryMerge = [&removeFromPositionMap, &aLinesPositionMap]( const MERGE_POINT aMergePoint,
293 const VECTOR2I& aMergePos,
294 const LENGTH_DELAY_CALCULATION_ITEM* aPrimaryItem,
295 SHAPE_LINE_CHAIN& aPrimaryLine, bool* aDidMerge )
296 {
297 const auto startItr = aLinesPositionMap.find( aMergePos );
298
299 if( startItr == aLinesPositionMap.end() )
300 return;
301
302 std::unordered_set<LENGTH_DELAY_CALCULATION_ITEM*>& startItems = startItr->second;
303
304 if( startItems.size() != 1 )
305 return;
306
307 LENGTH_DELAY_CALCULATION_ITEM* lineToMerge = *startItems.begin();
308
309 // Don't merge if line is an arc
310 if( !lineToMerge->GetLine().CArcs().empty() )
311 return;
312
313 // Don't merge if lines are on different layers
314 if( aPrimaryItem->GetStartLayer() != lineToMerge->GetStartLayer() )
315 return;
316
317 // Merge the lines
319 mergeShapeLineChains( aPrimaryLine, lineToMerge->GetLine(), aMergePoint );
320 removeFromPositionMap( lineToMerge );
321 *aDidMerge = true;
322 };
323
324 // Cluster all lines in to contiguous entities
325 for( LENGTH_DELAY_CALCULATION_ITEM* primaryItem : aLines )
326 {
327 // Don't start with an already merged line
328 if( primaryItem->GetMergeStatus() != LENGTH_DELAY_CALCULATION_ITEM::MERGE_STATUS::UNMERGED )
329 continue;
330
331 // Remove starting line from the position map
332 removeFromPositionMap( primaryItem );
333
334 SHAPE_LINE_CHAIN& primaryLine = primaryItem->GetLine();
335
336 // Merge all endpoints
338 bool mergeComplete = false;
339
340 while( !mergeComplete )
341 {
342 bool startMerged = false;
343 bool endMerged = false;
344
345 VECTOR2I startPos = primaryLine.CPoint( 0 );
346 VECTOR2I endPos = primaryLine.CLastPoint();
347
348 tryMerge( MERGE_POINT::START, startPos, primaryItem, primaryLine, &startMerged );
349 tryMerge( MERGE_POINT::END, endPos, primaryItem, primaryLine, &endMerged );
350
351 mergeComplete = !startMerged && !endMerged;
352 }
353 }
354}
355
356
358 const MERGE_POINT aMergePoint )
359{
360 if( aMergePoint == MERGE_POINT::START )
361 {
362 if( aSecondary.GetPoint( 0 ) == aPrimary.GetPoint( 0 ) )
363 {
364 for( auto itr = aSecondary.CPoints().begin() + 1; itr != aSecondary.CPoints().end(); ++itr )
365 aPrimary.Insert( 0, *itr );
366 }
367 else
368 {
369 wxASSERT( aSecondary.CLastPoint() == aPrimary.GetPoint( 0 ) );
370
371 for( auto itr = aSecondary.CPoints().rbegin() + 1; itr != aSecondary.CPoints().rend(); ++itr )
372 aPrimary.Insert( 0, *itr );
373 }
374 }
375 else
376 {
377 if( aSecondary.GetPoint( 0 ) == aPrimary.CLastPoint() )
378 {
379 for( auto itr = aSecondary.CPoints().begin() + 1; itr != aSecondary.CPoints().end(); ++itr )
380 aPrimary.Append( *itr );
381 }
382 else
383 {
384 wxASSERT( aSecondary.CLastPoint() == aPrimary.CLastPoint() );
385
386 for( auto itr = aSecondary.CPoints().rbegin() + 1; itr != aSecondary.CPoints().rend(); ++itr )
387 aPrimary.Append( *itr );
388 }
389 }
390}
391
392
393void LENGTH_DELAY_CALCULATION::optimiseTracesInPads( const std::vector<LENGTH_DELAY_CALCULATION_ITEM*>& aPads,
394 const std::vector<LENGTH_DELAY_CALCULATION_ITEM*>& aLines )
395{
396 for( LENGTH_DELAY_CALCULATION_ITEM* padItem : aPads )
397 {
398 const PAD* pad = padItem->GetPad();
399
400 for( LENGTH_DELAY_CALCULATION_ITEM* lineItem : aLines )
401 {
402 // Ignore merged lines
403 if( lineItem->GetMergeStatus() != LENGTH_DELAY_CALCULATION_ITEM::MERGE_STATUS::MERGED_IN_USE )
404 continue;
405
406 const PCB_LAYER_ID pcbLayer = lineItem->GetStartLayer();
407 SHAPE_LINE_CHAIN& line = lineItem->GetLine();
408
409 OptimiseTraceInPad( line, pad, pcbLayer );
410 }
411 }
412}
413
414
416 const std::vector<LENGTH_DELAY_CALCULATION_ITEM*>& aVias, std::vector<LENGTH_DELAY_CALCULATION_ITEM*>& aLines,
417 std::map<VECTOR2I, std::unordered_set<LENGTH_DELAY_CALCULATION_ITEM*>>& aLinesPositionMap,
418 const std::map<VECTOR2I, std::unordered_set<LENGTH_DELAY_CALCULATION_ITEM*>>& aPadsPositionMap )
419{
420 for( LENGTH_DELAY_CALCULATION_ITEM* via : aVias )
421 {
422 auto lineItr = aLinesPositionMap.find( via->GetVia()->GetPosition() );
423
424 if( lineItr == aLinesPositionMap.end() )
425 continue;
426
427 std::unordered_set<LENGTH_DELAY_CALCULATION_ITEM*>& connectedLines = lineItr->second;
428
429 if( connectedLines.empty() )
430 {
431 // No connected lines - this via is floating. Set both layers to the same
432 via->SetLayers( via->GetVia()->GetLayer(), via->GetVia()->GetLayer() );
433 }
434 else if( connectedLines.size() == 1 )
435 {
436 // This is either a via stub, or a via-in-pad
437 bool isViaInPad = false;
438 const PCB_LAYER_ID lineLayer = ( *connectedLines.begin() )->GetStartLayer();
439
440 auto padItr = aPadsPositionMap.find( via->GetVia()->GetPosition() );
441
442 if( padItr != aPadsPositionMap.end() )
443 {
444 // This could be a via-in-pad - check for overlapping pads which are not on the line layer
445 const std::unordered_set<LENGTH_DELAY_CALCULATION_ITEM*>& pads = padItr->second;
446
447 if( pads.size() == 1 )
448 {
449 const LENGTH_DELAY_CALCULATION_ITEM* padItem = *pads.begin();
450
451 if( !padItem->GetPad()->Padstack().LayerSet().Contains( lineLayer ) )
452 {
453 // This is probably a via-in-pad
454 isViaInPad = true;
455 via->SetLayers( lineLayer, padItem->GetStartLayer() );
456 }
457 }
458 }
459
460 if( !isViaInPad )
461 {
462 // This is a via stub - make its electrical length 0
463 via->SetLayers( lineLayer, lineLayer );
464 }
465 }
466 else
467 {
468 // This via has more than one track ending at it. Calculate the connected layer span (which may be shorter
469 // than the overall via span)
470 LSET layers;
471
472 for( const LENGTH_DELAY_CALCULATION_ITEM* lineItem : connectedLines )
473 layers.set( lineItem->GetStartLayer() );
474
475 LSEQ cuStack = layers.CuStack();
476
477 PCB_LAYER_ID firstLayer = UNDEFINED_LAYER;
478 PCB_LAYER_ID lastLayer = UNDEFINED_LAYER;
479
480 for( PCB_LAYER_ID layer : cuStack )
481 {
482 if( firstLayer == UNDEFINED_LAYER )
483 firstLayer = layer;
484 else
485 lastLayer = layer;
486 }
487
488 if( lastLayer == UNDEFINED_LAYER )
489 via->SetLayers( firstLayer, firstLayer );
490 else
491 via->SetLayers( firstLayer, lastLayer );
492 }
493 }
494}
495
496
498 const PCB_LAYER_ID aPcbLayer )
499{
500 // Only consider lines which terminate in the pad
501 if( aLine.CPoint( 0 ) != aPad->GetPosition() && aLine.CLastPoint() != aPad->GetPosition() )
502 return;
503
504 if( !aPad->FlashLayer( aPcbLayer ) )
505 return;
506
507 const auto& shape = aPad->GetEffectivePolygon( aPcbLayer, ERROR_INSIDE );
508
509 if( shape->Contains( aLine.CPoint( 0 ) ) )
510 clipLineToPad( aLine, aPad, aPcbLayer, true );
511 else if( shape->Contains( aLine.CPoint( -1 ) ) )
512 clipLineToPad( aLine, aPad, aPcbLayer, false );
513}
514
515
518{
519 if( const PCB_TRACK* track = dynamic_cast<const PCB_TRACK*>( aBoardItem ) )
520 {
521 if( track->Type() == PCB_VIA_T )
522 {
523 const PCB_VIA* via = static_cast<const PCB_VIA*>( track );
524
526 item.SetVia( via );
528 item.SetEffectiveNetClass( via->GetEffectiveNetClass() );
529
530 return item;
531 }
532
533 if( track->Type() == PCB_ARC_T )
534 {
535 const PCB_ARC* arcParent = static_cast<const PCB_ARC*>( track );
536 SHAPE_ARC shapeArc( arcParent->GetStart(), arcParent->GetMid(), arcParent->GetEnd(),
537 arcParent->GetWidth() );
538 SHAPE_LINE_CHAIN chainArc( shapeArc );
539
541 item.SetLine( chainArc );
542 item.SetLayers( track->GetLayer() );
543 item.SetEffectiveNetClass( arcParent->GetEffectiveNetClass() );
544
545 return item;
546 }
547
548 if( track->Type() == PCB_TRACE_T )
549 {
550 std::vector<VECTOR2I> points{ track->GetStart(), track->GetEnd() };
551 SHAPE_LINE_CHAIN shape( points );
552
554 item.SetLine( shape );
555 item.SetLayers( track->GetLayer() );
556 item.SetEffectiveNetClass( track->GetEffectiveNetClass() );
557
558 return item;
559 }
560 }
561 else if( const PAD* pad = dynamic_cast<const PAD*>( aBoardItem ) )
562 {
564 item.SetPad( pad );
565
566 const LSET& layers = pad->Padstack().LayerSet();
567 PCB_LAYER_ID firstLayer = UNDEFINED_LAYER;
568 PCB_LAYER_ID secondLayer = UNDEFINED_LAYER;
569
570 for( auto itr = layers.copper_layers_begin(); itr != layers.copper_layers_end(); ++itr )
571 {
572 if( firstLayer == UNDEFINED_LAYER )
573 firstLayer = *itr;
574 else
575 secondLayer = *itr;
576 }
577
578 item.SetLayers( firstLayer, secondLayer );
579 item.SetEffectiveNetClass( pad->GetEffectiveNetClass() );
580
581 return item;
582 }
583
584 return {};
585}
586
587
589 std::unique_ptr<TIME_DOMAIN_PARAMETERS_IFACE>&& aProvider )
590{
591 m_timeDomainParameters = std::move( aProvider );
592}
593
594
596{
597 m_timeDomainParameters->OnSettingsChanged();
598}
599
600
601int64_t LENGTH_DELAY_CALCULATION::CalculateLengthForDelay( const int64_t aDesiredDelay,
602 const TIME_DOMAIN_GEOMETRY_CONTEXT& aCtx ) const
603{
604 return m_timeDomainParameters->GetTrackLengthForPropagationDelay( aDesiredDelay, aCtx );
605}
606
607
608int64_t
610 const TIME_DOMAIN_GEOMETRY_CONTEXT& aCtx ) const
611{
612 return m_timeDomainParameters->CalculatePropagationDelayForShapeLineChain( aShape, aCtx );
613}
@ ERROR_INSIDE
Definition: approximation.h:34
BASE_SET & set(size_t pos)
Definition: base_set.h:116
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.
BOARD_STACKUP & GetStackupDescriptor()
bool m_UseHeightForLengthCalcs
Enable inclusion of stackup height in track length measurements and length tuning.
Manage layers needed to make a physical board.
void BuildDefaultStackupList(const BOARD_DESIGN_SETTINGS *aSettings, int aActiveCopperLayersCount=0)
Create a default stackup, according to the current BOARD_DESIGN_SETTINGS settings.
int GetLayerDistance(PCB_LAYER_ID aFirstLayer, PCB_LAYER_ID aSecondLayer) const
Calculate the distance (height) between the two given copper layers.
int GetCopperLayerCount() const
Definition: board.cpp:781
BOARD_DESIGN_SETTINGS & GetDesignSettings() const
Definition: board.cpp:946
Lightweight class which holds a pad, via, or a routed trace outline.
void SetLine(const SHAPE_LINE_CHAIN &aLine)
Sets the source SHAPE_LINE_CHAIN of this item.
void SetVia(const PCB_VIA *aVia)
Sets the VIA associated with this item.
TYPE Type() const
Gets the routing item type.
void SetPad(const PAD *aPad)
Sets the parent PAD associated with this item.
void SetMergeStatus(const MERGE_STATUS aStatus)
Sets the MERGE_STATUS of this item.
SHAPE_LINE_CHAIN & GetLine() const
Gets the SHAPE_LINE_CHAIN associated with this item.
const PAD * GetPad() const
Gets the parent PAD associated with this item.
PCB_LAYER_ID GetStartLayer() const
Gets the start board layer for the proxied item.
void SetEffectiveNetClass(const NETCLASS *aNetClass)
Sets the effective net class for the item.
void CalculateViaLayers(const BOARD *aBoard)
Calculates active via payers for a proxied VIA object.
void SetLayers(const PCB_LAYER_ID aStart, const PCB_LAYER_ID aEnd=PCB_LAYER_ID::UNDEFINED_LAYER)
Sets the first and last layers associated with this item.
int64_t CalculateLengthForDelay(int64_t aDesiredDelay, const TIME_DOMAIN_GEOMETRY_CONTEXT &aCtx) const
Calculates the length of track required for the given delay in a specific geometry context.
void SynchronizeTimeDomainProperties() const
Ensure time domain properties provider is synced with board / project settings if required.
static void clipLineToPad(SHAPE_LINE_CHAIN &aLine, const PAD *aPad, PCB_LAYER_ID aLayer, bool aForward=true)
Clips the given line to the minimal direct electrical length within the pad.
MERGE_POINT
Enum to describe whether track merging is attempted from the start or end of a track segment.
int64_t CalculatePropagationDelayForShapeLineChain(const SHAPE_LINE_CHAIN &aShape, const TIME_DOMAIN_GEOMETRY_CONTEXT &aCtx) const
Gets the propagation delay for the given shape line chain.
void inferViaInPad(const PAD *aPad, const LENGTH_DELAY_CALCULATION_ITEM &aItem, LENGTH_DELAY_STATS &aDetails) const
Infers if there is a via in the given pad.
static void optimiseTracesInPads(const std::vector< LENGTH_DELAY_CALCULATION_ITEM * > &aPads, const std::vector< LENGTH_DELAY_CALCULATION_ITEM * > &aLines)
Optimises the given set of items to minimise the electrical path length.
static void mergeLines(std::vector< LENGTH_DELAY_CALCULATION_ITEM * > &aLines, std::map< VECTOR2I, std::unordered_set< LENGTH_DELAY_CALCULATION_ITEM * > > &aLinesPositionMap)
Merges any lines (traces) that are contiguous, on one layer, and with no junctions.
int64_t CalculateDelay(std::vector< LENGTH_DELAY_CALCULATION_ITEM > &aItems, PATH_OPTIMISATIONS aOptimisations, const PAD *aStartPad=nullptr, const PAD *aEndPad=nullptr) const
Calculates the electrical propagation delay of the given items.
int64_t CalculateLength(std::vector< LENGTH_DELAY_CALCULATION_ITEM > &aItems, PATH_OPTIMISATIONS aOptimisations, const PAD *aStartPad=nullptr, const PAD *aEndPad=nullptr) const
Calculates the electrical length of the given items.
int StackupHeight(PCB_LAYER_ID aFirstLayer, PCB_LAYER_ID aSecondLayer) const
Returns the stackup distance between the two given layers.
void SetTimeDomainParametersProvider(std::unique_ptr< TIME_DOMAIN_PARAMETERS_IFACE > &&aProvider)
Sets the provider for time domain parameter resolution.
BOARD * m_board
The parent board for all items.
LENGTH_DELAY_CALCULATION_ITEM GetLengthCalculationItem(const BOARD_CONNECTED_ITEM *aBoardItem) const
Return a LENGTH_CALCULATION_ITEM constructed from the given BOARD_CONNECTED_ITEM.
static void optimiseViaLayers(const std::vector< LENGTH_DELAY_CALCULATION_ITEM * > &aVias, std::vector< LENGTH_DELAY_CALCULATION_ITEM * > &aLines, std::map< VECTOR2I, std::unordered_set< LENGTH_DELAY_CALCULATION_ITEM * > > &aLinesPositionMap, const std::map< VECTOR2I, std::unordered_set< LENGTH_DELAY_CALCULATION_ITEM * > > &aPadsPositionMap)
Optimises the via layers.
static void mergeShapeLineChains(SHAPE_LINE_CHAIN &aPrimary, const SHAPE_LINE_CHAIN &aSecondary, MERGE_POINT aMergePoint)
Merges two SHAPE_LINE_CHAINs where there is a shared endpoing.
LENGTH_DELAY_STATS CalculateLengthDetails(std::vector< LENGTH_DELAY_CALCULATION_ITEM > &aItems, PATH_OPTIMISATIONS aOptimisations, const PAD *aStartPad=nullptr, const PAD *aEndPad=nullptr, LENGTH_DELAY_LAYER_OPT aLayerOpt=LENGTH_DELAY_LAYER_OPT::NO_LAYER_DETAIL, LENGTH_DELAY_DOMAIN_OPT aDomain=LENGTH_DELAY_DOMAIN_OPT::NO_DELAY_DETAIL) const
Calculates the electrical length of the given items.
static void OptimiseTraceInPad(SHAPE_LINE_CHAIN &aLine, const PAD *aPad, PCB_LAYER_ID aPcbLayer)
Optimises the given trace / line to minimise the electrical path length within the given pad.
std::unique_ptr< TIME_DOMAIN_PARAMETERS_IFACE > m_timeDomainParameters
The active provider of time domain parameters.
LSEQ is a sequence (and therefore also a set) of PCB_LAYER_IDs.
Definition: lseq.h:47
LSET is a set of PCB_LAYER_IDs.
Definition: lset.h:37
copper_layers_iterator copper_layers_end() const
Definition: lset.cpp:916
LSEQ CuStack() const
Return a sequence of copper layers in starting from the front/top and extending to the back/bottom.
Definition: lset.cpp:247
copper_layers_iterator copper_layers_begin() const
Definition: lset.cpp:910
bool Contains(PCB_LAYER_ID aLayer) const
See if the layer set contains a PCB layer.
Definition: lset.h:63
const LSET & LayerSet() const
Definition: padstack.h:280
Definition: pad.h:54
bool FlashLayer(int aLayer, bool aOnlyCheckIfPermitted=false) const
Check to see whether the pad should be flashed on the specific layer.
Definition: pad.cpp:356
VECTOR2I GetPosition() const override
Definition: pad.h:208
const PADSTACK & Padstack() const
Definition: pad.h:321
const std::shared_ptr< SHAPE_POLY_SET > & GetEffectivePolygon(PCB_LAYER_ID aLayer, ERROR_LOC aErrorLoc=ERROR_INSIDE) const
Definition: pad.cpp:514
const VECTOR2I & GetMid() const
Definition: pcb_track.h:344
const VECTOR2I & GetStart() const
Definition: pcb_track.h:152
const VECTOR2I & GetEnd() const
Definition: pcb_track.h:149
virtual int GetWidth() const
Definition: pcb_track.h:146
Definition: seg.h:42
VECTOR2I A
Definition: seg.h:49
VECTOR2I B
Definition: seg.h:50
Represent a polyline containing arcs as well as line segments: A chain of connected line and/or arc s...
bool IsPtOnArc(size_t aPtIndex) const
virtual const VECTOR2I GetPoint(int aIndex) const override
int PointCount() const
Return the number of points (vertices) in this line chain.
void Replace(int aStartIndex, int aEndIndex, const VECTOR2I &aP)
Replace points with indices in range [start_index, end_index] with a single point aP.
const std::vector< SHAPE_ARC > & CArcs() const
void Append(int aX, int aY, bool aAllowDuplication=false)
Append a new point at the end of the line chain.
const VECTOR2I & CPoint(int aIndex) const
Return a reference to a given point in the line chain.
const VECTOR2I & CLastPoint() const
Return the last point in the line chain.
void Remove(int aStartIndex, int aEndIndex)
Remove the range of points [start_index, end_index] from the line chain.
void Insert(size_t aVertex, const VECTOR2I &aP)
const std::vector< VECTOR2I > & CPoints() const
a few functions useful in geometry calculations.
PCB_LAYER_ID
A quick note on layer IDs:
Definition: layer_ids.h:60
@ B_Cu
Definition: layer_ids.h:65
@ UNDEFINED_LAYER
Definition: layer_ids.h:61
@ F_Cu
Definition: layer_ids.h:64
LENGTH_DELAY_DOMAIN_OPT
Enum which controls the calculation domain of the length / delay calculation methods.
LENGTH_DELAY_LAYER_OPT
Enum which controls the level of detail returned by the length / delay calculation methods.
Holds length measurement result details and statistics.
std::unique_ptr< std::map< PCB_LAYER_ID, int64_t > > LayerDelays
int64_t TotalLength() const
Calculates the total electrical length for this set of statistics.
std::unique_ptr< std::map< PCB_LAYER_ID, int64_t > > LayerLengths
int64_t TotalDelay() const
Calculates the total electrical propagation delay for this set of statistics.
Struct to control which optimisations the length calculation code runs on the given path objects.
bool InferViaInPad
Determines if there is a via-in-pad present on the board but not in the item set.
bool OptimiseViaLayers
Optimise via layers for height calculations, ensuring only the distance between routed segments is co...
bool MergeTracks
Merges all contiguous (end-to-end, same layer) tracks.
bool OptimiseTracesInPads
Optimises the electrical length of tracks within pads.
A data structure to contain basic geometry data which can affect signal propagation calculations.
const NETCLASS * NetClass
The net class this track belongs to.
constexpr int delta
@ PCB_VIA_T
class PCB_VIA, a via (like a track segment on a copper layer)
Definition: typeinfo.h:97
@ PCB_ARC_T
class PCB_ARC, an arc track segment on a copper layer
Definition: typeinfo.h:98
@ PCB_TRACE_T
class PCB_TRACK, a track segment (segment on a copper layer)
Definition: typeinfo.h:96