KiCad PCB EDA Suite
Loading...
Searching...
No Matches
topo_match.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, see <https://www.gnu.org/licenses/>.
18 */
19
20#ifndef __TOPO_MATCH_H
21#define __TOPO_MATCH_H
22
23#include <atomic>
24#include <vector>
25#include <map>
26#include <unordered_map>
27#include <unordered_set>
28#include <optional>
29
30#include <kiid.h>
31#include <wx/string.h>
32
33class FOOTPRINT;
34
35/* A very simple (but working) partial connection graph isomorphism algorithm,
36 operating on sets of footprints and connections between their pads.
37*/
38
39namespace TMATCH
40{
41
42class PIN;
44
46{
47 std::atomic<bool>* m_cancelled = nullptr;
48 std::atomic<int>* m_matchedComponents = nullptr;
49 std::atomic<int>* m_totalComponents = nullptr;
50};
51
53{
54 wxString m_reference;
55 wxString m_candidate;
56 wxString m_reason;
57};
58
60{
61 friend class PIN;
62 friend class CONNECTION_GRAPH;
63
64public:
65 COMPONENT( const wxString& aRef, FOOTPRINT* aParentFp, std::optional<VECTOR2I> aRaOffset = std::optional<VECTOR2I>() );
66 ~COMPONENT();
67
68 bool IsSameKind( const COMPONENT& b ) const;
69 void AddPin( PIN* p );
70 int GetPinCount() const { return m_pins.size(); }
72 std::vector<PIN*>& Pins() { return m_pins; }
74
75 bool HasRAOffset() const { return m_raOffset.has_value(); }
76 const VECTOR2I GetRAOffset() const { return *m_raOffset; }
77
78private:
79 void sortPinsByName();
80
87 static bool isChannelSuffix( const wxString& aSuffix );
88
96 static bool prefixesShareCommonBase( const wxString& aPrefixA, const wxString& aPrefixB );
97
102 static bool isUnannotatedRef( const wxString& aRef );
103
104 std::optional<VECTOR2I> m_raOffset;
105 wxString m_reference;
106 wxString m_prefix;
108 std::vector<PIN*> m_pins;
109};
110
111class PIN
112{
113 friend class CONNECTION_GRAPH;
114
115public:
116 PIN() : m_netcode( 0 ), m_parent( nullptr ) {}
117 ~PIN() {}
118
119 void SetParent( COMPONENT* parent ) { m_parent = parent; }
120
121 const wxString Format() const { return m_parent->m_reference + wxT( "-" ) + m_ref; }
122
123 void AddConnection( PIN* pin ) { m_conns.push_back( pin ); }
124
125 bool IsTopologicallySimilar( const PIN& b ) const
126 {
127 wxASSERT( m_parent != b.m_parent );
128
129 if( !m_parent->IsSameKind( *b.m_parent ) )
130 return false;
131
132 return m_ref == b.m_ref;
133 }
134
135 bool IsIsomorphic( const PIN& b, TOPOLOGY_MISMATCH_REASON& aDetail ) const;
136
137 int GetNetCode() const { return m_netcode; }
138
139 const wxString& GetReference() const { return m_ref; }
140
141 COMPONENT* GetParent() const { return m_parent; }
142
143private:
144
145 wxString m_ref;
148 std::vector<PIN*> m_conns;
149};
150
152{
153 friend class CONNECTION_GRAPH;
154
155public:
157 {
158 m_ref = nullptr;
159 m_currentMatch = -1;
160 m_nloops = 0;
161 m_refIndex = 0;
162 }
163
165 {
167 m_ref = other.m_ref;
168 m_matches = other.m_matches;
169 m_locked = other.m_locked;
170 m_nloops = other.m_nloops;
171 m_refIndex = other.m_refIndex;
172 }
173
174 const std::unordered_map<COMPONENT*, COMPONENT*>& GetMatchingComponentPairs() const
175 {
176 return m_locked;
177 }
178
179private:
183 std::vector<COMPONENT*> m_matches;
184 std::unordered_map<COMPONENT*, COMPONENT*> m_locked;
186};
187
188typedef std::map<FOOTPRINT*, FOOTPRINT*> COMPONENT_MATCHES;
189
199size_t CommonPathTailLength( const KIID_PATH& aA, const KIID_PATH& aB );
200
202{
203public:
204 const int c_ITER_LIMIT = 10000;
205
208
209 void BuildConnectivity( const std::unordered_set<int>& aExternalNets = {} );
210 void AddFootprint( FOOTPRINT* aFp, const VECTOR2I& aOffset );
212 std::vector<TOPOLOGY_MISMATCH_REASON>& aFailureDetails,
213 const ISOMORPHISM_PARAMS& aParams = {} );
221 static std::unique_ptr<CONNECTION_GRAPH> BuildFromFootprintSet( const std::set<FOOTPRINT*>& aFps,
222 const std::set<FOOTPRINT*>& aOtherChannelFps = {},
223 const std::unordered_set<int>& aGlobalNets = {} );
224 std::vector<COMPONENT*> &Components() { return m_components; }
225
226private:
232 void breakTie( COMPONENT* aRef, std::vector<COMPONENT*>& aMatches ) const;
237 bool breakTieBySymbolPath( COMPONENT* aRef, std::vector<COMPONENT*>& aMatches ) const;
238
243 bool breakTieByValue( COMPONENT* aRef, std::vector<COMPONENT*>& aMatches ) const;
244
245 void sortByPinCount();
246
247
248 std::vector<COMPONENT*> findMatchingComponents( COMPONENT* ref,
249 const std::vector<COMPONENT*>& aStructuralMatches,
250 const TOPOLOGY_MISMATCH_REASON& aStructuralReason,
251 const BACKTRACK_STAGE& partialMatches,
252 std::vector<TOPOLOGY_MISMATCH_REASON>& aFailureDetails,
253 const std::atomic<bool>* aCancelled = nullptr );
254
255 std::vector<COMPONENT*> m_components;
256 std::unordered_set<int> m_externalNets;
257
258};
259
260}; // namespace TMATCH
261
262#endif
friend class CONNECTION_GRAPH
Definition topo_match.h:153
const std::unordered_map< COMPONENT *, COMPONENT * > & GetMatchingComponentPairs() const
Definition topo_match.h:174
std::unordered_map< COMPONENT *, COMPONENT * > m_locked
Definition topo_match.h:184
std::vector< COMPONENT * > m_matches
Definition topo_match.h:183
BACKTRACK_STAGE(const BACKTRACK_STAGE &other)
Definition topo_match.h:164
static bool prefixesShareCommonBase(const wxString &aPrefixA, const wxString &aPrefixB)
Check if two prefixes share a common starting sequence.
static bool isUnannotatedRef(const wxString &aRef)
True for un-annotated placeholder refs like REF** that match any counterpart on FPID and topology alo...
friend class CONNECTION_GRAPH
Definition topo_match.h:62
bool IsSameKind(const COMPONENT &b) const
const VECTOR2I GetRAOffset() const
Definition topo_match.h:76
int GetPinCount() const
Definition topo_match.h:70
COMPONENT(const wxString &aRef, FOOTPRINT *aParentFp, std::optional< VECTOR2I > aRaOffset=std::optional< VECTOR2I >())
bool HasRAOffset() const
Definition topo_match.h:75
FOOTPRINT * m_parentFootprint
Definition topo_match.h:107
std::optional< VECTOR2I > m_raOffset
Definition topo_match.h:104
bool MatchesWith(COMPONENT *b, TOPOLOGY_MISMATCH_REASON &aDetail)
void AddPin(PIN *p)
std::vector< PIN * > & Pins()
Definition topo_match.h:72
friend class PIN
Definition topo_match.h:61
wxString m_reference
Definition topo_match.h:105
static bool isChannelSuffix(const wxString &aSuffix)
Check if a suffix looks like a channel identifier.
std::vector< PIN * > m_pins
Definition topo_match.h:108
FOOTPRINT * GetParent() const
Definition topo_match.h:73
std::vector< COMPONENT * > findMatchingComponents(COMPONENT *ref, const std::vector< COMPONENT * > &aStructuralMatches, const TOPOLOGY_MISMATCH_REASON &aStructuralReason, const BACKTRACK_STAGE &partialMatches, std::vector< TOPOLOGY_MISMATCH_REASON > &aFailureDetails, const std::atomic< bool > *aCancelled=nullptr)
bool FindIsomorphism(CONNECTION_GRAPH *target, COMPONENT_MATCHES &result, std::vector< TOPOLOGY_MISMATCH_REASON > &aFailureDetails, const ISOMORPHISM_PARAMS &aParams={})
std::vector< COMPONENT * > & Components()
Definition topo_match.h:224
void BuildConnectivity(const std::unordered_set< int > &aExternalNets={})
static std::unique_ptr< CONNECTION_GRAPH > BuildFromFootprintSet(const std::set< FOOTPRINT * > &aFps, const std::set< FOOTPRINT * > &aOtherChannelFps={}, const std::unordered_set< int > &aGlobalNets={})
bool breakTieByValue(COMPONENT *aRef, std::vector< COMPONENT * > &aMatches) const
Break a tie by footprint value when the symbol UUID can't, e.g.
std::vector< COMPONENT * > m_components
Definition topo_match.h:255
void AddFootprint(FOOTPRINT *aFp, const VECTOR2I &aOffset)
bool breakTieBySymbolPath(COMPONENT *aRef, std::vector< COMPONENT * > &aMatches) const
The most useful tie breaker is based on symbol/sheet instances, since multiple channels in a design a...
void breakTie(COMPONENT *aRef, std::vector< COMPONENT * > &aMatches) const
Many times components are electrically/topologically identical, e.g.
std::unordered_set< int > m_externalNets
Definition topo_match.h:256
std::vector< PIN * > m_conns
Definition topo_match.h:148
friend class CONNECTION_GRAPH
Definition topo_match.h:113
void SetParent(COMPONENT *parent)
Definition topo_match.h:119
COMPONENT * m_parent
Definition topo_match.h:147
bool IsTopologicallySimilar(const PIN &b) const
Definition topo_match.h:125
const wxString & GetReference() const
Definition topo_match.h:139
bool IsIsomorphic(const PIN &b, TOPOLOGY_MISMATCH_REASON &aDetail) const
void AddConnection(PIN *pin)
Definition topo_match.h:123
COMPONENT * GetParent() const
Definition topo_match.h:141
int GetNetCode() const
Definition topo_match.h:137
const wxString Format() const
Definition topo_match.h:121
wxString m_ref
Definition topo_match.h:145
std::map< FOOTPRINT *, FOOTPRINT * > COMPONENT_MATCHES
Definition topo_match.h:188
size_t CommonPathTailLength(const KIID_PATH &aA, const KIID_PATH &aB)
Count the trailing elements two symbol instance paths share.
std::atomic< bool > * m_cancelled
Definition topo_match.h:47
std::atomic< int > * m_matchedComponents
Definition topo_match.h:48
std::atomic< int > * m_totalComponents
Definition topo_match.h:49
KIBIS_PIN * pin
wxString result
Test unit parsing edge cases and error handling.
VECTOR2< int32_t > VECTOR2I
Definition vector2d.h:708