23#include <unordered_map>
36 if( !aFootprint || aNetChain.
IsEmpty() )
39 std::vector<const PAD*> chainPads;
48 chainPads.push_back(
pad );
51 if( chainPads.size() < 2 )
54 int firstNet = chainPads.front()->GetNetCode();
56 auto crossesNet = [firstNet](
const PAD* p ) {
return p->GetNetCode() != firstNet; };
58 if( !std::any_of( chainPads.begin() + 1, chainPads.end(), crossesNet ) )
63 for(
size_t i = 0; i < chainPads.size(); ++i )
65 for(
size_t j = i + 1; j < chainPads.size(); ++j )
67 if( chainPads[i]->GetNetCode() == chainPads[j]->GetNetCode() )
71 -
VECTOR2D( chainPads[j]->GetCenter() );
72 maxSpan = std::max( maxSpan,
delta.EuclideanNorm() );
82 if( !aBoard || aNetChain.
IsEmpty() )
98 if( !aBoard || aNetChain.
IsEmpty() )
111 std::tie( std::ignore, tLen, std::ignore, tDelay, std::ignore ) =
114 if( tLen > 0.0 && tDelay > 0.0 )
116 delayIUPerMm = tDelay / ( tLen /
pcbIUScale.IU_PER_MM );
127 if( !aBoard || aNetChain.
IsEmpty() )
132 if( lengthIU <= 0.0 )
138 return { lengthIU, delayIU };
144 std::vector<CHAIN_BRIDGE> bridges;
146 if( !aBoard || aNetChain.
IsEmpty() )
156 std::vector<PAD*> chainPads;
158 for(
PAD*
pad : fp->Pads() )
163 chainPads.push_back(
pad );
166 if( chainPads.size() < 2 )
169 for(
size_t i = 0; i < chainPads.size(); ++i )
171 for(
size_t j = i + 1; j < chainPads.size(); ++j )
173 if( chainPads[i]->GetNetCode() == chainPads[j]->GetNetCode() )
177 -
VECTOR2D( chainPads[j]->GetCenter() );
178 double length =
delta.EuclideanNorm();
179 double delay = delayIUPerMm * length /
pcbIUScale.IU_PER_MM;
181 bridges.push_back(
CHAIN_BRIDGE{ chainPads[i], chainPads[j], length, delay } );
191 const PAD* aStartPad,
const PAD* aEndPad )
195 if( !aBoard || !aStartPad || !aEndPad || aStartPad == aEndPad )
211 if( !queryNetInfo || queryNetInfo->
GetNetChain().IsEmpty() )
219 if( aStartPad->
GetNet() != queryNetInfo )
225 if( aEndPad->
GetNet() != queryNetInfo )
231 const wxString& chainName = queryNetInfo->
GetNetChain();
237 std::unordered_map<int, std::set<int>> adjacency;
241 std::set<int> startSeeds;
242 std::set<int> endSeeds;
243 bool queryNetHasBridge =
false;
245 auto seedIfEndpoint = [&](
const PAD* aBridgePad,
int aNeighborNet,
246 const PAD* aQueryPad, std::set<int>& aSeeds )
248 if( aBridgePad == aQueryPad && aNeighborNet != aQueryNet )
249 aSeeds.insert( aNeighborNet );
254 if( !br.padA || !br.padB )
257 int netA = br.padA->GetNetCode();
258 int netB = br.padB->GetNetCode();
260 if( netA == aQueryNet || netB == aQueryNet )
262 queryNetHasBridge =
true;
263 seedIfEndpoint( br.padA, netB, aStartPad, startSeeds );
264 seedIfEndpoint( br.padB, netA, aStartPad, startSeeds );
265 seedIfEndpoint( br.padA, netB, aEndPad, endSeeds );
266 seedIfEndpoint( br.padB, netA, aEndPad, endSeeds );
270 adjacency[netA].insert( netB );
271 adjacency[netB].insert( netA );
276 if( !queryNetHasBridge )
282 auto bfsFill = [&](
const std::set<int>& aSeeds, std::set<int>& aOut )
284 std::queue<int> frontier;
286 for(
int seed : aSeeds )
288 if( aOut.insert(
seed ).second )
289 frontier.push(
seed );
292 while( !frontier.empty() )
294 int cur = frontier.front();
297 auto it = adjacency.find( cur );
299 if( it == adjacency.end() )
302 for(
int nbr : it->second )
304 if( aOut.insert( nbr ).second )
305 frontier.push( nbr );
310 bfsFill( startSeeds,
result.beforeStart );
311 bfsFill( endSeeds,
result.afterEnd );
313 for(
int net :
result.beforeStart )
315 if(
result.afterEnd.count( net ) )
constexpr EDA_IU_SCALE pcbIUScale
NETINFO_ITEM * GetNet() const
Return #NET_INFO object for a given item.
virtual const BOARD * GetBoard() const
Return the BOARD in which this BOARD_ITEM resides, or NULL if none.
Information pertinent to a Pcbnew printed circuit board.
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.
NETINFO_ITEM * FindNet(int aNetcode) const
Search for a net with the given netcode.
const FOOTPRINTS & Footprints() const
const TRACKS & Tracks() const
Handle the data for a net.
const wxString & GetNetChain() const
double ChainBridgingDelayPerMm(const BOARD *aBoard, const wxString &aNetChain)
Pick a single per-IU-per-mm delay for a given chain.
NET_CHAIN_PARTITION PartitionNetChainAroundNet(const BOARD *aBoard, int aQueryNet, const PAD *aStartPad, const PAD *aEndPad)
Partition the chain containing aQueryNet around it, cut at the bridges incident on aStartPad and aEnd...
std::tuple< double, double > BoardChainBridging(const BOARD *aBoard, const wxString &aNetChain)
Compute both the chain bridging length and its associated propagation delay (in internal delay IU,...
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...
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.
constexpr double DEFAULT_PROPAGATION_DELAY_PS_PER_MM
One series-component bridge edge inside a chain graph.
Result of PartitionNetChainAroundNet().
wxString result
Test unit parsing edge cases and error handling.
VECTOR2< double > VECTOR2D