139 std::map<PIN*, PIN*> pairs;
140 std::vector<PIN*> pref, ptgt;
145 for(
PIN* p : m.second->Pins() )
150 for(
PIN* p : m.first->Pins() )
166 if( pref.size() != ptgt.size() )
171 wxString::Format(
_(
"Component %s expects %lu matching pads but candidate %s provides %lu." ),
172 aReason.
m_reference,
static_cast<unsigned long>( pref.size() ),
173 aReason.
m_candidate,
static_cast<unsigned long>( ptgt.size() ) );
177 for(
unsigned int i = 0; i < pref.size(); i++ )
179 pairs[pref[i]] = ptgt[i];
182 for(
PIN* refPin : aRef->
Pins() )
187 std::optional<int> prevNet;
191 for(
PIN* ppin : refCmp->Pins() )
193 if ( ppin->GetNetCode() != refPin->GetNetCode() )
197 ppin->GetParent()->GetParent()->GetReferenceAsString(),
198 ppin->GetReference(), ppin->GetNetCode() );
200 auto tpin = pairs.find( ppin );
202 if( tpin != pairs.end() )
204 int nc = tpin->second->GetNetCode();
206 if( prevNet && ( *prevNet != nc ) )
218 if(
const NETINFO_ITEM* net = refBoard->FindNet( refPin->GetNetCode() ) )
219 refNetName = net->GetNetname();
225 tgtNetName = net->GetNetname();
228 if( refNetName.IsEmpty() )
229 refNetName = wxString::Format(
_(
"net %d" ), refPin->GetNetCode() );
231 if( tgtNetName.IsEmpty() )
232 tgtNetName = wxString::Format(
_(
"net %d" ), nc );
234 aReason.
m_reason = wxString::Format(
235 _(
"Pad %s of %s is on net %s but its match in candidate %s is on net %s." ),
255 std::vector<TOPOLOGY_MISMATCH_REASON>& aMismatchReasons )
257 aMismatchReasons.clear();
258 std::vector<COMPONENT*> matches;
262 if( partialMatches.
m_locked.find( cmpTarget ) != partialMatches.
m_locked.end() )
268 cmpTarget->m_reference );
274 localReason.
m_candidate = cmpTarget->GetParent()->GetReferenceAsString();
282 matches.push_back( cmpTarget );
286 wxLogTrace(
traceTopoMatch, wxT(
"Reject [net topo mismatch]\n") );
287 aMismatchReasons.push_back( localReason );
293 aMismatchReasons.push_back( localReason );
301 for(
int i=0;i<a->
m_pins.size();i++)
304 PIN* pb = b->m_pins[i];
310 return (
double)n / (double) a->
m_pins.size();
316 return padSimilarity( aRef,a ) > padSimilarity( aRef, b );
320 if( matches.empty() )
324 reason.
m_reason =
_(
"No compatible component found in the target area." );
326 if( aMismatchReasons.empty() )
327 aMismatchReasons.push_back( reason );
392 std::vector<TOPOLOGY_MISMATCH_REASON>& aMismatchReasons )
394 std::vector<BACKTRACK_STAGE> stack;
397 aMismatchReasons.clear();
399 std::vector<TOPOLOGY_MISMATCH_REASON> localReasons;
404 reason.
m_reason =
_(
"One or both of the areas has no components assigned." );
405 aMismatchReasons.push_back( reason );
412 reason.
m_reason =
_(
"Component count mismatch" );
413 aMismatchReasons.push_back( reason );
420 stack.push_back( top );
422 bool matchFound =
false;
425 while( !stack.empty() )
428 auto& current = stack.back();
430 for(
auto it = current.m_locked.begin(); it != current.m_locked.end(); it++ )
432 if (it->second == current.m_ref)
434 wxLogTrace(
traceTopoMatch, wxT(
"stk: Remove %s from locked\n" ),
435 current.m_ref->m_reference );
436 current.m_locked.erase( it );
446 reason.
m_reason =
_(
"Iteration count exceeded (timeout)" );
448 if( aMismatchReasons.empty() )
449 aMismatchReasons.push_back( reason );
451 aMismatchReasons.insert( aMismatchReasons.begin(), reason );
456 if( current.m_currentMatch < 0 )
458 localReasons.clear();
461 if( current.m_matches.empty() && aMismatchReasons.empty() && !localReasons.empty() )
462 aMismatchReasons = localReasons;
464 current.m_currentMatch = 0;
467 wxLogTrace(
traceTopoMatch, wxT(
"stk: Current '%s' stack %d cm %d/%d locked %d/%d\n" ),
468 current.m_ref->m_reference, (
int) stack.size(), current.m_currentMatch,
469 (
int) current.m_matches.size(), (
int) current.m_locked.size(),
472 if ( current.m_matches.empty() )
474 wxLogTrace(
traceTopoMatch, wxT(
"stk: No matches at all, going up [level=%d]\n" ),
475 (
int) stack.size() );
480 if( current.m_currentMatch >= 0 && current.m_currentMatch >= current.m_matches.size() )
482 wxLogTrace(
traceTopoMatch, wxT(
"stk: No more matches, going up [level=%d]\n" ),
483 (
int) stack.size() );
488 auto& match = current.m_matches[current.m_currentMatch];
490 wxLogTrace(
traceTopoMatch, wxT(
"stk: candidate '%s', match list : ( " ),
491 current.m_matches[current.m_currentMatch]->m_reference, current.m_refIndex );
493 for(
auto m : current.m_matches )
494 wxLogTrace(
traceTopoMatch, wxT(
"%s " ), m->GetParent()->GetReferenceAsString() );
498 current.m_currentMatch++;
499 current.m_locked[match] = current.m_ref;
503 current.m_nloops = nloops;
506 aMismatchReasons.clear();
508 for(
auto iter : current.m_locked )
509 aResult[ iter.second->GetParent() ] = iter.first->GetParent();
515 int minMatches = std::numeric_limits<int>::max();
518 int bestRefIndex = 0;
525 if( cmp == current.m_ref )
530 for(
auto it = current.m_locked.begin(); it != current.m_locked.end(); it++ )
532 if( it->second == cmp )
542 localReasons.clear();
545 int nMatches = matches.size();
553 else if( nMatches == 0 )
558 if( aMismatchReasons.empty() && !localReasons.empty() )
559 aMismatchReasons = localReasons;
561 else if( nMatches < minMatches )
563 minMatches = nMatches;
570 next.m_currentMatch = -1;
574 next.m_ref = bestNextRef;
575 next.m_refIndex = bestRefIndex;
579 next.m_ref = altNextRef;
580 next.m_refIndex = altRefIndex;
583 stack.push_back(
next );