KiCad PCB EDA Suite
Loading...
Searching...
No Matches
pns_meander_placer_base.cpp
Go to the documentation of this file.
1/*
2 * KiRouter - a push-and-(sometimes-)shove PCB router
3 *
4 * Copyright (C) 2013-2015 CERN
5 * Copyright 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#include <core/typeinfo.h>
22
24#include "pns_meander.h"
25#include "pns_router.h"
26#include "pns_segment.h"
27#include "pns_solid.h"
28#include "pns_arc.h"
29
30namespace PNS {
31
33
35 PLACEMENT_ALGO( aRouter )
36{
37 m_world = nullptr;
39 m_startPad_n = nullptr;
40 m_startPad_p = nullptr;
41 m_endPad_n = nullptr;
42 m_endPad_p = nullptr;
43}
44
45
49
50
52{
55 m_chainExtrasValid = false;
56
57 const std::vector<NET_HANDLE> startNets = CurrentNets();
58
59 if( startNets.empty() )
60 return;
61
62 NET_HANDLE first = startNets[0];
63 NET_HANDLE second = startNets.size() >= 2 ? startNets[1] : startNets[0];
64
65 long long extraLen = 0;
66 long long extraDelay = 0;
67
68 if( Router()->GetInterface()->GetSignalAggregate( first, second, extraLen, extraDelay ) )
69 {
70 m_chainExtrasLength = extraLen;
71 m_chainExtrasDelay = extraDelay;
72 }
73
74 m_chainExtrasValid = true;
75}
76
77
79{
81 return 0;
82
83 const std::vector<NET_HANDLE> nets = CurrentNets();
84
85 long long tunedNetBoardLen = 0;
86
87 if( !nets.empty() )
88 tunedNetBoardLen = Router()->GetInterface()->GetNetBoardLength( nets[0] );
89
90 long long unmeasured = std::max( 0LL, tunedNetBoardLen - m_baselineLength );
91
92 return m_chainExtrasLength + unmeasured;
93}
94
95
97{
98 int a = m_settings.m_maxAmplitude + aSign * m_settings.m_step;
99 a = std::max( a, m_settings.m_minAmplitude );
100
101 m_settings.m_maxAmplitude = a;
102}
103
104
106{
107 int s = m_settings.m_spacing + aSign * m_settings.m_step;
108 s = std::max( s, m_currentWidth + Clearance() );
109
110 m_settings.m_spacing = s;
111}
112
113
115{
116 // Assumption: All tracks are part of the same net class.
117 // It shouldn't matter which track we pick. They should all have the same clearance if
118 // they are part of the same net class. Therefore, pick the first one on the list.
119 ITEM* itemToCheck = Traces().CItems().front();
120 PNS::CONSTRAINT constraint;
121
123 nullptr, CurrentLayer(), &constraint );
124
125 wxCHECK_MSG( constraint.m_Value.HasMin(), m_currentWidth, wxT( "No minimum clearance?" ) );
126
127 return constraint.m_Value.Min();
128}
129
130
132{
133 m_settings = aSettings;
134}
135
136
137int findAmplitudeBinarySearch( MEANDER_SHAPE& aCopy, int targetLength, int minAmp, int maxAmp )
138{
139 if( minAmp == maxAmp )
140 return maxAmp;
141
142 aCopy.Resize( minAmp );
143 int minLen = aCopy.CurrentLength();
144
145 aCopy.Resize( maxAmp );
146 int maxLen = aCopy.CurrentLength();
147
148 if( minLen > targetLength )
149 return 0;
150
151 if( maxLen < targetLength )
152 return 0;
153
154 int minError = minLen - targetLength;
155 int maxError = maxLen - targetLength;
156
157 if( std::abs( minError ) < LENGTH_TARGET_TOLERANCE
158 || std::abs( maxError ) < LENGTH_TARGET_TOLERANCE )
159 {
160 return std::abs( minError ) < std::abs( maxError ) ? minAmp : maxAmp;
161 }
162 else
163 {
164 int left =
165 findAmplitudeBinarySearch( aCopy, targetLength, minAmp, ( minAmp + maxAmp ) / 2 );
166
167 if( left )
168 return left;
169
170 int right =
171 findAmplitudeBinarySearch( aCopy, targetLength, ( minAmp + maxAmp ) / 2, maxAmp );
172
173 if( right )
174 return right;
175 }
176
177 return 0;
178}
179
180
181int findAmplitudeForLength( MEANDER_SHAPE* m, int targetLength, int minAmp, int maxAmp )
182{
183 MEANDER_SHAPE copy = *m;
184
185 // Try to keep the same baseline length
186 copy.SetTargetBaselineLength( m->BaselineLength() );
187
188 long long initialGuess = m->Amplitude() - ( m->CurrentLength() - targetLength ) / 2;
189
190 if( initialGuess >= minAmp && initialGuess <= maxAmp )
191 {
192 copy.Resize( minAmp );
193
194 if( std::abs( copy.CurrentLength() - targetLength ) < LENGTH_TARGET_TOLERANCE )
195 return initialGuess;
196 }
197
198 // The length is non-trivial, use binary search
199 return findAmplitudeBinarySearch( copy, targetLength, minAmp, maxAmp );
200}
201
202
203void MEANDER_PLACER_BASE::tuneLineLength( MEANDERED_LINE& aTuned, long long int aElongation )
204{
205 long long int maxElongation = 0;
206 long long int minElongation = 0;
207 bool finished = false;
208
209 for( MEANDER_SHAPE* m : aTuned.Meanders() )
210 {
211 if( m->Type() != MT_CORNER && m->Type() != MT_ARC )
212 {
213 MEANDER_SHAPE end = *m;
214 MEANDER_TYPE endType;
215
216 if( m->Type() == MT_START || m->Type() == MT_SINGLE )
217 endType = MT_SINGLE;
218 else
219 endType = MT_FINISH;
220
221 end.SetType( endType );
222 end.Recalculate();
223
224 long long int maxEndElongation = end.CurrentLength() - end.BaselineLength();
225
226 if( maxElongation + maxEndElongation > aElongation )
227 {
228 if( !finished )
229 {
230 m->SetType( endType );
231 m->Recalculate();
232
233 if( endType == MT_SINGLE )
234 {
235 // Check if we need to fit this meander
236 long long int endMinElongation =
237 ( m->MinTunableLength() - m->BaselineLength() );
238
239 if( minElongation + endMinElongation >= aElongation )
240 m->MakeEmpty();
241 }
242
243 finished = true;
244 }
245 else
246 {
247 m->MakeEmpty();
248 }
249 }
250
251 maxElongation += m->CurrentLength() - m->BaselineLength();
252 minElongation += m->MinTunableLength() - m->BaselineLength();
253 }
254 }
255
256 long long int remainingElongation = aElongation;
257 int meanderCount = 0;
258
259 for( MEANDER_SHAPE* m : aTuned.Meanders() )
260 {
261 if( m->Type() != MT_CORNER && m->Type() != MT_ARC && m->Type() != MT_EMPTY )
262 {
263 remainingElongation -= m->CurrentLength() - m->BaselineLength();
264 meanderCount++;
265 }
266 }
267
268 long long int lenReductionLeft = -remainingElongation;
269 int meandersLeft = meanderCount;
270
271 if( lenReductionLeft < 0 || !meandersLeft )
272 return;
273
274 for( MEANDER_SHAPE* m : aTuned.Meanders() )
275 {
276 if( m->Type() != MT_CORNER && m->Type() != MT_ARC && m->Type() != MT_EMPTY )
277 {
278 long long int lenReductionHere = lenReductionLeft / meandersLeft;
279 long long int initialLen = m->CurrentLength();
280 int minAmpl = m->MinAmplitude();
281
282 int amp = findAmplitudeForLength( m, initialLen - lenReductionHere, minAmpl,
283 m->Amplitude() );
284
285 if( amp < minAmpl )
286 amp = minAmpl;
287
288 m->SetTargetBaselineLength( m->BaselineLength() );
289 m->Resize( amp );
290
291 lenReductionLeft -= initialLen - m->CurrentLength();
292 meandersLeft--;
293
294 if( !meandersLeft )
295 break;
296 }
297 }
298}
299
300
305
306
308{
309 if( aStartItem->Kind() == ITEM::SEGMENT_T )
310 {
311 return static_cast<SEGMENT*>( aStartItem )->Seg().NearestPoint( aStartPoint );
312 }
313 else
314 {
315 wxASSERT( aStartItem->Kind() == ITEM::ARC_T );
316 ARC* arc = static_cast<ARC*>( aStartItem );
317
318 if( ( VECTOR2I( arc->Anchor( 0 ) - aStartPoint ) ).SquaredEuclideanNorm() <=
319 ( VECTOR2I( arc->Anchor( 1 ) - aStartPoint ) ).SquaredEuclideanNorm() )
320 {
321 return arc->Anchor( 0 );
322 }
323 else
324 {
325 return arc->Anchor( 1 );
326 }
327 }
328}
329
330
331long long int MEANDER_PLACER_BASE::lineLength( const ITEM_SET& aLine, const SOLID* aStartPad, const SOLID* aEndPad ) const
332{
333 if( aLine.Empty() )
334 return 0;
335
336 ROUTER_IFACE* iface = Router()->GetInterface();
337 return iface->CalculateRoutedPathLength( aLine, aStartPad, aEndPad, m_settings.m_netClass );
338}
339
340
341int64_t MEANDER_PLACER_BASE::lineDelay( const ITEM_SET& aLine, const SOLID* aStartPad, const SOLID* aEndPad ) const
342{
343 if( aLine.Empty() )
344 return 0;
345
346 ROUTER_IFACE* iface = Router()->GetInterface();
347 return iface->CalculateRoutedPathDelay( aLine, aStartPad, aEndPad, m_settings.m_netClass );
348}
349}
T Min() const
Definition minoptmax.h:33
bool HasMin() const
Definition minoptmax.h:37
ROUTER * Router() const
Return current router settings.
virtual VECTOR2I Anchor(int n) const override
Definition pns_arc.h:100
bool Empty() const
Definition pns_itemset.h:82
const std::vector< ITEM * > & CItems() const
Definition pns_itemset.h:88
Base class for PNS router board items.
Definition pns_item.h:98
PnsKind Kind() const
Return the type (kind) of the item.
Definition pns_item.h:173
Represent a set of meanders fitted over a single or two lines.
std::vector< MEANDER_SHAPE * > & Meanders()
long long int chainNarrowingOffset() const
Return the length offset to subtract when converting a user-facing total signal length target into a ...
virtual void UpdateSettings(const MEANDER_SETTINGS &aSettings)
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...
virtual void SpacingStep(int aSign)
Increase/decrease the current meandering spacing by one step.
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)
virtual int Clearance()
Return the clearance of the track(s) being length tuned.
virtual const MEANDER_SETTINGS & MeanderSettings() const
Return the current meandering configuration.
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)
virtual void AmplitudeStep(int aSign)
Increase/decreases the current meandering amplitude by one step.
Dimensions for the meandering algorithm.
Definition pns_meander.h:70
The geometry of a single meander.
int Amplitude() const
long long int CurrentLength() const
void Resize(int aAmpl)
Change the amplitude of the meander shape to aAmpl and recalculates the resulting line chain.
int BaselineLength() const
virtual const ITEM_SET Traces()=0
Function Traces()
PLACEMENT_ALGO(ROUTER *aRouter)
virtual int CurrentLayer() const =0
Function CurrentLayer()
virtual const std::vector< NET_HANDLE > CurrentNets() const =0
Function CurrentNets()
virtual long long GetNetBoardLength(NET_HANDLE aNet) const
Definition pns_router.h:138
virtual long long int CalculateRoutedPathLength(const ITEM_SET &aLine, const SOLID *aStartPad, const SOLID *aEndPad, const NETCLASS *aNetClass)=0
virtual int64_t CalculateRoutedPathDelay(const ITEM_SET &aLine, const SOLID *aStartPad, const SOLID *aEndPad, const NETCLASS *aNetClass)=0
ROUTER_IFACE * GetInterface() const
Definition pns_router.h:240
RULE_RESOLVER * GetRuleResolver() const
Definition pns_router.h:202
virtual bool QueryConstraint(CONSTRAINT_TYPE aType, const ITEM *aItemA, const ITEM *aItemB, int aLayer, CONSTRAINT *aConstraint)=0
Push and Shove diff pair dimensions (gap) settings dialog.
MEANDER_TYPE
Shapes of available meanders.
Definition pns_meander.h:40
@ MT_ARC
Definition pns_meander.h:48
@ MT_START
Definition pns_meander.h:42
@ MT_FINISH
Definition pns_meander.h:43
@ MT_EMPTY
Definition pns_meander.h:49
@ MT_CORNER
Definition pns_meander.h:47
@ MT_SINGLE
Definition pns_meander.h:41
int findAmplitudeForLength(MEANDER_SHAPE *m, int targetLength, int minAmp, int maxAmp)
const int LENGTH_TARGET_TOLERANCE
int findAmplitudeBinarySearch(MEANDER_SHAPE &aCopy, int targetLength, int minAmp, int maxAmp)
void * NET_HANDLE
Definition pns_item.h:55
EDA_ANGLE abs(const EDA_ANGLE &aAngle)
Definition eda_angle.h:400
An abstract function object, returning a design rule (clearance, diff pair gap, etc) required between...
Definition pns_node.h:73
MINOPTMAX< int > m_Value
Definition pns_node.h:75
VECTOR2I end
VECTOR2< int32_t > VECTOR2I
Definition vector2d.h:687