KiCad PCB EDA Suite
Loading...
Searching...
No Matches
variant_symbol_utils.cpp
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 * or you may search the http://www.gnu.org website for the version 2 license,
20 * or you may write to the Free Software Foundation, Inc.,
21 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
22 */
23
25
26#include <lib_symbol.h>
28#include <span>
29#include <pin_type.h>
30#include <sch_pin.h>
31
32#include <algorithm>
33
34
35bool VariantSymbolPinsMatch( const SCH_PIN& aBase, const SCH_PIN& aCandidate )
36{
37 return aBase.GetNumber() == aCandidate.GetNumber()
38 && aBase.GetUnit() == aCandidate.GetUnit()
39 && aBase.GetBodyStyle() == aCandidate.GetBodyStyle()
40 && aBase.GetPosition() == aCandidate.GetPosition();
41}
42
43
44static std::vector<VARIANT_COMPAT_RESULT> validateCompatibility(
45 int aBaseUnits, int aBaseBodyStyles, std::span<const PIN_COMPARISON_DATA> basePins,
46 int aCandidateUnits, int aCandidateBodyStyles, std::span<const PIN_COMPARISON_DATA> candidatePins )
47{
48 std::vector<VARIANT_COMPAT_RESULT> results;
49
50 int baseUnits = std::max( aBaseUnits, 1 );
51 int candUnits = std::max( aCandidateUnits, 1 );
52
53 if( candUnits < baseUnits )
54 {
57 result.detail = wxString::Format( _( "Candidate has %d unit(s), base requires %d" ),
58 candUnits, baseUnits );
59 results.push_back( result );
60 }
61
62 int baseBodyStyles = aBaseBodyStyles;
63
64 if( baseBodyStyles > 1 && aCandidateBodyStyles < baseBodyStyles )
65 {
68 result.detail = wxString::Format( _( "Candidate has %d body style(s), base requires %d" ),
69 aCandidateBodyStyles, baseBodyStyles );
70 results.push_back( result );
71 }
72
73 // Library pins without a concrete type resolve to unspecified, as with SCH_PIN::GetType().
74 const auto type = []( const PIN_COMPARISON_DATA& pin )
75 {
77 };
78
79 std::vector<bool> matched( candidatePins.size(), false );
80
81 for( const PIN_COMPARISON_DATA& basePin : basePins )
82 {
83 auto sameSlot = [&]( const PIN_COMPARISON_DATA& aCandidatePin )
84 {
85 return basePin.number == aCandidatePin.number
86 && basePin.unit == aCandidatePin.unit
87 && basePin.bodyStyle == aCandidatePin.bodyStyle;
88 };
89
90 auto findCandidate = [&]( bool aRequirePosition, bool aRequireType )
91 {
92 for( size_t i = 0; i < candidatePins.size(); ++i )
93 {
94 if( matched[i] || !sameSlot( candidatePins[i] ) )
95 continue;
96
97 if( aRequirePosition && candidatePins[i].position != basePin.position )
98 continue;
99
100 if( aRequireType && type( candidatePins[i] ) != type( basePin ) )
101 continue;
102
103 return i;
104 }
105
106 return candidatePins.size();
107 };
108
109 size_t candidateIndex = findCandidate( true, true );
110
111 if( candidateIndex == candidatePins.size() )
112 candidateIndex = findCandidate( true, false );
113
114 if( candidateIndex == candidatePins.size() )
115 candidateIndex = findCandidate( false, false );
116
117 if( candidateIndex == candidatePins.size() )
118 {
121 result.pinNumber = basePin.number;
122 result.unit = basePin.unit;
123 result.bodyStyle = basePin.bodyStyle;
124 result.detail = wxString::Format(
125 _( "Unit %d, body style %d: pin '%s' not found in candidate" ),
126 result.unit, result.bodyStyle, result.pinNumber );
127 results.push_back( result );
128 continue;
129 }
130
131 matched[candidateIndex] = true;
132 const auto& candidatePin = candidatePins[candidateIndex];
133
134 if( candidatePin.position != basePin.position )
135 {
138 result.pinNumber = basePin.number;
139 result.unit = basePin.unit;
140 result.bodyStyle = basePin.bodyStyle;
141 result.detail = wxString::Format(
142 _( "Unit %d, body style %d: pin '%s' position mismatch "
143 "(%d,%d) vs (%d,%d)" ),
144 result.unit, result.bodyStyle, result.pinNumber,
145 basePin.position.x, basePin.position.y,
146 candidatePin.position.x, candidatePin.position.y );
147 results.push_back( result );
148 }
149
150 if( type( candidatePin ) != type( basePin ) )
151 {
154 result.pinNumber = basePin.number;
155 result.unit = basePin.unit;
156 result.bodyStyle = basePin.bodyStyle;
157 result.detail = wxString::Format(
158 _( "Unit %d, body style %d: pin '%s' type mismatch ('%s' vs '%s')" ),
159 result.unit, result.bodyStyle, result.pinNumber,
160 GetCanonicalElectricalTypeName( type( basePin ) ),
161 GetCanonicalElectricalTypeName( type( candidatePin ) ) );
162 results.push_back( result );
163 }
164 }
165
166 for( size_t i = 0; i < candidatePins.size(); ++i )
167 {
168 if( !matched[i] )
169 {
170 const auto& candidatePin = candidatePins[i];
173 result.pinNumber = candidatePin.number;
174 result.unit = candidatePin.unit;
175 result.bodyStyle = candidatePin.bodyStyle;
176 result.detail = wxString::Format(
177 _( "Unit %d, body style %d: candidate has extra pin '%s'" ),
178 result.unit, result.bodyStyle, result.pinNumber );
179 results.push_back( result );
180 }
181 }
182
183 return results;
184}
185
186
187static std::vector<PIN_COMPARISON_DATA> variantPins( const LIB_SYMBOL& aSymbol )
188{
189 std::vector<PIN_COMPARISON_DATA> result;
190
191 for( const SCH_PIN* pin : aSymbol.GetGraphicalPins() )
192 result.push_back( pin->ComparisonData() );
193
194 return result;
195}
196
197
198std::vector<VARIANT_COMPAT_RESULT> ValidateVariantSymbolCompatibility( const LIB_SYMBOL& aBase,
199 const LIB_SYMBOL& aCandidate )
200{
201 return validateCompatibility( aBase.GetUnitCount(), aBase.GetBodyStyleCount(), variantPins( aBase ),
202 aCandidate.GetUnitCount(), aCandidate.GetBodyStyleCount(), variantPins( aCandidate ) );
203}
204
205
206std::vector<VARIANT_COMPAT_RESULT> ValidateVariantSymbolCompatibility(
207 const SCH_CONNECTIVITY::LIBRARY_SYMBOL_FACT& aBase, const LIB_SYMBOL& aCandidate )
208{
210 aBase.inheritedPins ? *aBase.inheritedPins : aBase.pins,
211 aCandidate.GetUnitCount(), aCandidate.GetBodyStyleCount(),
212 variantPins( aCandidate ) );
213}
Define a library symbol object.
Definition lib_symbol.h:114
int GetBodyStyleCount() const override
The body styles are a property of the drawings, which a derived symbol inherits from its root symbol ...
int GetUnitCount() const override
std::vector< SCH_PIN * > GetGraphicalPins(int aUnit=0, int aBodyStyle=0) const override
Graphical pins: Return schematic pin objects as drawn (unexpanded), filtered by unit/body.
int GetBodyStyle() const
Definition sch_item.h:253
int GetUnit() const
Definition sch_item.h:243
VECTOR2I GetPosition() const override
Definition sch_pin.cpp:378
const wxString & GetNumber() const
Definition sch_pin.h:144
#define _(s)
@ PT_UNSPECIFIED
unknown electrical properties: creates always a warning when connected
Definition pin_type.h:41
wxString GetCanonicalElectricalTypeName(ELECTRICAL_PINTYPE aType)
Definition pin_type.h:54
Owned library-pin inputs; no parent, layout cache or schematic pointers.
std::vector< PIN_COMPARISON_DATA > pins
Definition conn_facts.h:230
std::optional< std::vector< PIN_COMPARISON_DATA > > inheritedPins
Definition conn_facts.h:234
KIBIS_PIN * pin
wxString result
Test unit parsing edge cases and error handling.
std::vector< VARIANT_COMPAT_RESULT > ValidateVariantSymbolCompatibility(const LIB_SYMBOL &aBase, const LIB_SYMBOL &aCandidate)
Check whether aCandidate can be used as a variant symbol override for aBase.
bool VariantSymbolPinsMatch(const SCH_PIN &aBase, const SCH_PIN &aCandidate)
Check whether two graphical pins occupy the same variant-symbol connection slot.
static std::vector< PIN_COMPARISON_DATA > variantPins(const LIB_SYMBOL &aSymbol)
static std::vector< VARIANT_COMPAT_RESULT > validateCompatibility(int aBaseUnits, int aBaseBodyStyles, std::span< const PIN_COMPARISON_DATA > basePins, int aCandidateUnits, int aCandidateBodyStyles, std::span< const PIN_COMPARISON_DATA > candidatePins)
@ PIN_POSITION_MISMATCH
A matching pin number has a different position in library coordinates.
@ PIN_TYPE_MISMATCH
A matching pin number has a different electrical type.
@ EXTRA_PIN_NUMBER
Candidate has a pin occurrence that is absent from the base.
@ MISSING_BODY_STYLE
Base uses alternate body styles but candidate does not.
@ MISSING_PIN_NUMBER
A base pin number is absent from the candidate for a given unit/body style.
@ INSUFFICIENT_UNITS
Candidate has fewer units than the base.