KiCad PCB EDA Suite
Loading...
Searching...
No Matches
net_chain_bridging.h
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 */
20
21#ifndef PCBNEW_NET_CHAIN_BRIDGING_H
22#define PCBNEW_NET_CHAIN_BRIDGING_H
23
24#include <algorithm>
25#include <limits>
26#include <tuple>
27#include <vector>
28
29#include <wx/string.h>
30
31#include <base_units.h>
32#include <board.h>
33#include <footprint.h>
34#include <math/vector2d.h>
35#include <netinfo.h>
36#include <pad.h>
37#include <pcb_track.h>
38
39
40constexpr double DEFAULT_PROPAGATION_DELAY_PS_PER_MM = 5.9; // 150 ps/in fallback when no track delay sample is available
41
42
58inline double FootprintChainBridgingLength( const FOOTPRINT* aFootprint, const wxString& aNetChain )
59{
60 if( !aFootprint || aNetChain.IsEmpty() )
61 return 0.0;
62
63 std::vector<const PAD*> chainPads;
64
65 for( const PAD* pad : aFootprint->Pads() )
66 {
67 const NETINFO_ITEM* pn = pad->GetNet();
68
69 if( !pn || pn->GetNetChain() != aNetChain )
70 continue;
71
72 chainPads.push_back( pad );
73 }
74
75 if( chainPads.size() < 2 )
76 return 0.0;
77
78 int firstNet = chainPads.front()->GetNetCode();
79
80 auto crossesNet = [firstNet]( const PAD* p ) { return p->GetNetCode() != firstNet; };
81
82 if( !std::any_of( chainPads.begin() + 1, chainPads.end(), crossesNet ) )
83 return 0.0;
84
85 double maxSpan = 0.0;
86
87 for( size_t i = 0; i < chainPads.size(); ++i )
88 {
89 for( size_t j = i + 1; j < chainPads.size(); ++j )
90 {
91 if( chainPads[i]->GetNetCode() == chainPads[j]->GetNetCode() )
92 continue;
93
94 VECTOR2D delta = VECTOR2D( chainPads[i]->GetCenter() )
95 - VECTOR2D( chainPads[j]->GetCenter() );
96 maxSpan = std::max( maxSpan, delta.EuclideanNorm() );
97 }
98 }
99
100 return maxSpan;
101}
102
103
107inline double BoardChainBridgingLength( const BOARD* aBoard, const wxString& aNetChain )
108{
109 if( !aBoard || aNetChain.IsEmpty() )
110 return 0.0;
111
112 double total = 0.0;
113
114 for( const FOOTPRINT* fp : aBoard->Footprints() )
115 total += FootprintChainBridgingLength( fp, aNetChain );
116
117 return total;
118}
119
120
131// Forward declaration; defined below.
132inline double ChainBridgingDelayPerMm( const BOARD* aBoard, const wxString& aNetChain );
133
134
135inline std::tuple<double, double> BoardChainBridging( const BOARD* aBoard, const wxString& aNetChain )
136{
137 if( !aBoard || aNetChain.IsEmpty() )
138 return { 0.0, 0.0 };
139
140 double lengthIU = BoardChainBridgingLength( aBoard, aNetChain );
141
142 if( lengthIU <= 0.0 )
143 return { 0.0, 0.0 };
144
145 double delayIU = ChainBridgingDelayPerMm( aBoard, aNetChain ) * lengthIU
146 / pcbIUScale.IU_PER_MM;
147
148 return { lengthIU, delayIU };
149}
150
151
157inline int SubtractBridgingClamped( int aValue, long long aDelta )
158{
159 long long adjusted = static_cast<long long>( aValue ) - aDelta;
160
161 return static_cast<int>( std::clamp( adjusted,
162 0LL,
163 static_cast<long long>( std::numeric_limits<int>::max() ) ) );
164}
165
166
176{
179 double length;
180 double delay;
181};
182
183
190inline double ChainBridgingDelayPerMm( const BOARD* aBoard, const wxString& aNetChain )
191{
192 double delayIUPerMm = DEFAULT_PROPAGATION_DELAY_PS_PER_MM * pcbIUScale.IU_PER_PS;
193
194 if( !aBoard || aNetChain.IsEmpty() )
195 return delayIUPerMm;
196
197 for( const PCB_TRACK* track : aBoard->Tracks() )
198 {
199 const NETINFO_ITEM* ninfo = track->GetNet();
200
201 if( !ninfo || ninfo->GetNetChain() != aNetChain )
202 continue;
203
204 double tLen = 0.0;
205 double tDelay = 0.0;
206
207 std::tie( std::ignore, tLen, std::ignore, tDelay, std::ignore ) =
208 aBoard->GetTrackLength( *track );
209
210 if( tLen > 0.0 && tDelay > 0.0 )
211 {
212 delayIUPerMm = tDelay / ( tLen / pcbIUScale.IU_PER_MM );
213 break;
214 }
215 }
216
217 return delayIUPerMm;
218}
219
220
228inline std::vector<CHAIN_BRIDGE>
229EnumerateChainBridges( const BOARD* aBoard, const wxString& aNetChain )
230{
231 std::vector<CHAIN_BRIDGE> bridges;
232
233 if( !aBoard || aNetChain.IsEmpty() )
234 return bridges;
235
236 const double delayIUPerMm = ChainBridgingDelayPerMm( aBoard, aNetChain );
237
238 for( FOOTPRINT* fp : aBoard->Footprints() )
239 {
240 if( !fp )
241 continue;
242
243 std::vector<PAD*> chainPads;
244
245 for( PAD* pad : fp->Pads() )
246 {
247 const NETINFO_ITEM* pn = pad->GetNet();
248
249 if( pn && pn->GetNetChain() == aNetChain )
250 chainPads.push_back( pad );
251 }
252
253 if( chainPads.size() < 2 )
254 continue;
255
256 for( size_t i = 0; i < chainPads.size(); ++i )
257 {
258 for( size_t j = i + 1; j < chainPads.size(); ++j )
259 {
260 if( chainPads[i]->GetNetCode() == chainPads[j]->GetNetCode() )
261 continue;
262
263 VECTOR2D delta = VECTOR2D( chainPads[i]->GetCenter() )
264 - VECTOR2D( chainPads[j]->GetCenter() );
265 double length = delta.EuclideanNorm();
266 double delay = delayIUPerMm * length / pcbIUScale.IU_PER_MM;
267
268 bridges.push_back( CHAIN_BRIDGE{ chainPads[i], chainPads[j], length, delay } );
269 }
270 }
271 }
272
273 return bridges;
274}
275
276
277#endif // PCBNEW_NET_CHAIN_BRIDGING_H
constexpr EDA_IU_SCALE pcbIUScale
Definition base_units.h:125
Information pertinent to a Pcbnew printed circuit board.
Definition board.h:323
std::tuple< int, double, double, double, double > GetTrackLength(const PCB_TRACK &aTrack) const
Return data on the length and number of track segments connected to a given track.
Definition board.cpp:3187
const FOOTPRINTS & Footprints() const
Definition board.h:364
const TRACKS & Tracks() const
Definition board.h:362
bool IsEmpty() const
Definition board.cpp:614
bool IsEmpty() const
std::deque< PAD * > & Pads()
Definition footprint.h:377
Handle the data for a net.
Definition netinfo.h:50
const wxString & GetNetChain() const
Definition netinfo.h:115
Definition pad.h:55
double ChainBridgingDelayPerMm(const BOARD *aBoard, const wxString &aNetChain)
Compute both the chain bridging length and its associated propagation delay (in internal delay IU,...
constexpr double DEFAULT_PROPAGATION_DELAY_PS_PER_MM
std::tuple< double, double > BoardChainBridging(const BOARD *aBoard, const wxString &aNetChain)
std::vector< CHAIN_BRIDGE > EnumerateChainBridges(const BOARD *aBoard, const wxString &aNetChain)
Enumerate every per-pad-pair bridge edge contributed by every footprint on the board to the named cha...
int SubtractBridgingClamped(int aValue, long long aDelta)
Saturating subtract for bridge-adjusting MINOPTMAX<int> bounds without overflow when the delta is in ...
double BoardChainBridgingLength(const BOARD *aBoard, const wxString &aNetChain)
Sum chain bridging length across every footprint on the board.
double FootprintChainBridgingLength(const FOOTPRINT *aFootprint, const wxString &aNetChain)
Compute the bridging length contributed by a single footprint to a net chain.
One series-component bridge edge inside a chain graph.
int delta
VECTOR2< double > VECTOR2D
Definition vector2d.h:686