KiCad PCB EDA Suite
Loading...
Searching...
No Matches
test_pin_map_resolver.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 modify it
7 * under the terms of the GNU General Public License as published by the
8 * Free Software Foundation, either version 3 of the License, or (at your
9 * option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License along
17 * with this program. If not, see <http://www.gnu.org/licenses/>.
18 */
19
21
22#include <memory>
23#include <set>
24
25#include <pin_map.h>
26#include <lib_symbol.h>
27#include <sch_pin.h>
28#include <sch_symbol.h>
29#include <sch_sheet_path.h>
30#include <sch_sheet.h>
31#include <sch_screen.h>
32#include <schematic.h>
33
34
36
37
38namespace
39{
40LIB_ID makeFp( const wxString& aLibNick, const wxString& aName )
41{
42 LIB_ID id;
43 id.SetLibNickname( aLibNick );
44 id.SetLibItemName( aName );
45 return id;
46}
47
48
49SCH_PIN* addPin( LIB_SYMBOL& aSymbol, const wxString& aNumber )
50{
51 SCH_PIN* pin = new SCH_PIN( &aSymbol );
52 pin->SetNumber( aNumber );
54 aSymbol.AddDrawItem( pin );
55 return pin;
56}
57} // namespace
58
59
61{
63 {
64 m_dfn = makeFp( wxS( "Package_DFN_QFN" ), wxS( "DFN-8-1EP" ) );
65
66 m_lib = std::make_unique<LIB_SYMBOL>( wxS( "LM358" ), nullptr );
67 addPin( *m_lib, wxS( "1" ) ); // identity in DFN
68 addPin( *m_lib, wxS( "4" ) ); // mapped to [4,9]
69 addPin( *m_lib, wxS( "8" ) ); // not mapped, no pad -> UNMAPPED
70 addPin( *m_lib, wxS( "[2,3]" ) ); // stacked, both members are pads on the footprint
71 addPin( *m_lib, wxS( "[20,21]" ) ); // stacked, neither member is a pad
72
73 PIN_MAP map( wxS( "DFN-8-EP" ) );
74 map.SetEntry( wxS( "4" ), wxS( "[4,9]" ) );
75 m_lib->PinMaps().AddOrReplace( map );
76 m_lib->SetAssociatedFootprints( { { m_dfn, wxS( "DFN-8-EP" ) } } );
77
78 m_symbol = std::make_unique<SCH_SYMBOL>( *m_lib, m_lib->GetLibId(), nullptr, 0, 0,
79 VECTOR2I( 0, 0 ) );
80 m_symbol->UpdatePins();
81 }
82
83 SCH_PIN* pin( const wxString& aNumber ) const { return m_symbol->GetPin( aNumber ); }
84
86 std::unique_ptr<LIB_SYMBOL> m_lib;
87 std::unique_ptr<SCH_SYMBOL> m_symbol;
88 SCH_SHEET_PATH m_sheet; // empty path; no variant means base override
89};
90
91
92BOOST_FIXTURE_TEST_SUITE( PinMapResolver, PIN_MAP_RESOLVER_FIXTURE )
93
94
95BOOST_AUTO_TEST_CASE( ThreeResolutionStates )
96{
97 std::set<wxString> dfnPads = { wxS( "1" ), wxS( "2" ), wxS( "3" ), wxS( "4" ),
98 wxS( "5" ), wxS( "6" ), wxS( "7" ), wxS( "9" ) };
99
100 PAD_RESOLUTION state;
101
102 // MAPPED: pin 4 -> [4,9] via the library map (no footprint needed for MAPPED).
103 BOOST_CHECK_EQUAL( pin( wxS( "4" ) )->GetEffectivePadNumber( m_sheet, wxEmptyString, m_dfn,
104 &dfnPads, &state ),
105 wxS( "[4,9]" ) );
106 BOOST_CHECK( state == PAD_RESOLUTION::MAPPED );
107
108 // IDENTITY: pin 1 has no entry but pad 1 exists on the footprint.
109 BOOST_CHECK_EQUAL( pin( wxS( "1" ) )->GetEffectivePadNumber( m_sheet, wxEmptyString, m_dfn,
110 &dfnPads, &state ),
111 wxS( "1" ) );
112 BOOST_CHECK( state == PAD_RESOLUTION::IDENTITY );
113
114 // UNMAPPED: pin 8 has no entry and pad 8 is absent (set has 1-7 and 9).
115 BOOST_CHECK( pin( wxS( "8" ) )->GetEffectivePadNumber( m_sheet, wxEmptyString, m_dfn, &dfnPads,
116 &state ).IsEmpty() );
117 BOOST_CHECK( state == PAD_RESOLUTION::UNMAPPED );
118}
119
120
121BOOST_AUTO_TEST_CASE( StackedPinResolvesThroughFootprintPads )
122{
123 std::set<wxString> dfnPads = { wxS( "1" ), wxS( "2" ), wxS( "3" ), wxS( "4" ),
124 wxS( "5" ), wxS( "6" ), wxS( "7" ), wxS( "9" ) };
125
126 PAD_RESOLUTION state;
127
128 // A stacked pin's number is the whole list. The footprint carries its members as pads.
129 BOOST_CHECK_EQUAL( pin( wxS( "[2,3]" ) )->GetEffectivePadNumber( m_sheet, wxEmptyString, m_dfn, &dfnPads, &state ),
130 wxS( "[2,3]" ) );
131 BOOST_CHECK( state == PAD_RESOLUTION::IDENTITY );
132
133 // Brackets alone must not resolve. The members have to be pads on the footprint.
134 BOOST_CHECK( pin( wxS( "[20,21]" ) )
135 ->GetEffectivePadNumber( m_sheet, wxEmptyString, m_dfn, &dfnPads, &state )
136 .IsEmpty() );
137 BOOST_CHECK( state == PAD_RESOLUTION::UNMAPPED );
138}
139
140
141BOOST_AUTO_TEST_CASE( NoFootprintPathAssumesIdentity )
142{
143 PAD_RESOLUTION state;
144
145 // MAPPED entries still resolve with no footprint.
146 BOOST_CHECK_EQUAL( pin( wxS( "4" ) )->GetEffectivePadNumber( m_sheet, wxEmptyString, m_dfn,
147 nullptr, &state ),
148 wxS( "[4,9]" ) );
149 BOOST_CHECK( state == PAD_RESOLUTION::MAPPED );
150
151 // Everything unmapped is assumed identity (returns the pin number) on the painter path.
152 BOOST_CHECK_EQUAL( pin( wxS( "8" ) )->GetEffectivePadNumber( m_sheet, wxEmptyString, m_dfn,
153 nullptr, &state ),
154 wxS( "8" ) );
155 BOOST_CHECK( state == PAD_RESOLUTION::IDENTITY );
156}
157
158
159BOOST_AUTO_TEST_CASE( OverridePrecedence )
160{
161 PAD_RESOLUTION state;
162
163 // FORCE_IDENTITY ignores the library map: pin 4 falls through to identity/unmapped.
164 PIN_MAP_INSTANCE_OVERRIDE forceIdentity;
166 m_symbol->SetPinMapOverride( forceIdentity );
167
168 std::set<wxString> pads = { wxS( "4" ) };
169 BOOST_CHECK_EQUAL( pin( wxS( "4" ) )->GetEffectivePadNumber( m_sheet, wxEmptyString, m_dfn,
170 &pads, &state ),
171 wxS( "4" ) );
172 BOOST_CHECK( state == PAD_RESOLUTION::IDENTITY );
173
174 // Sparse edits are ignored under forced identity (PIN_MAP_INSTANCE_OVERRIDE contract).
175 forceIdentity.m_Edits.push_back( { wxS( "4" ), wxS( "99" ) } );
176 m_symbol->SetPinMapOverride( forceIdentity );
177 BOOST_CHECK_EQUAL( pin( wxS( "4" ) )->GetEffectivePadNumber( m_sheet, wxEmptyString, m_dfn,
178 &pads, &state ),
179 wxS( "4" ) );
180 BOOST_CHECK( state == PAD_RESOLUTION::IDENTITY );
181
182 // A sparse instance edit beats the library map.
185 edited.m_Edits.push_back( { wxS( "4" ), wxS( "99" ) } );
186 m_symbol->SetPinMapOverride( edited );
187
188 BOOST_CHECK_EQUAL( pin( wxS( "4" ) )->GetEffectivePadNumber( m_sheet, wxEmptyString, m_dfn,
189 nullptr, &state ),
190 wxS( "99" ) );
191 BOOST_CHECK( state == PAD_RESOLUTION::MAPPED );
192}
193
194
195BOOST_AUTO_TEST_CASE( NamedMapOverride )
196{
197 PAD_RESOLUTION state;
198
199 // USE_NAMED_MAP forces a specific map by name regardless of footprint association.
200 m_lib->PinMaps().AddOrReplace( PIN_MAP( wxS( "SWAP" ) ) );
201 m_lib->PinMaps().FindByName( wxS( "SWAP" ) )->SetEntry( wxS( "1" ), wxS( "8" ) );
202
203 // Rebuild the symbol so its flattened library reference carries the new map.
204 m_symbol = std::make_unique<SCH_SYMBOL>( *m_lib, m_lib->GetLibId(), nullptr, 0, 0,
205 VECTOR2I( 0, 0 ) );
206 m_symbol->UpdatePins();
207
210 named.m_ActiveMapName = wxS( "SWAP" );
211 m_symbol->SetPinMapOverride( named );
212
213 BOOST_CHECK_EQUAL( pin( wxS( "1" ) )->GetEffectivePadNumber( m_sheet, wxEmptyString, m_dfn,
214 nullptr, &state ),
215 wxS( "8" ) );
216 BOOST_CHECK( state == PAD_RESOLUTION::MAPPED );
217}
218
219
220BOOST_AUTO_TEST_CASE( SyncSharedLibSymbolCopies )
221{
222 SCHEMATIC schematic( nullptr );
223
224 SCH_SHEET* sheet = new SCH_SHEET( &schematic );
225 SCH_SCREEN* screen = new SCH_SCREEN( &schematic );
226
227 const_cast<KIID&>( sheet->m_Uuid ) = screen->GetUuid();
228 sheet->SetScreen( screen );
229 schematic.SetTopLevelSheets( { sheet } );
230
231 SCH_SYMBOL* unitA = new SCH_SYMBOL( *m_lib, m_lib->GetLibId(), nullptr, 1, 0, VECTOR2I( 0, 0 ) );
232 SCH_SYMBOL* unitB = new SCH_SYMBOL( *m_lib, m_lib->GetLibId(), nullptr, 2, 0, VECTOR2I( 0, 0 ) );
233
234 screen->Append( unitA );
235 screen->Append( unitB );
236
237 PIN_MAP edited( wxS( "EDITED" ) );
238 edited.SetEntry( wxS( "1" ), wxS( "X1" ) );
239 unitA->GetLibSymbolRef()->PinMaps().AddOrReplace( edited );
240 unitA->GetLibSymbolRef()->SetAssociatedFootprints( { { m_dfn, wxS( "EDITED" ) } } );
241
242 BOOST_REQUIRE( unitB->GetLibSymbolRef() );
243 BOOST_REQUIRE( !( unitB->GetLibSymbolRef()->GetPinMaps() == unitA->GetLibSymbolRef()->GetPinMaps() ) );
244
245 schematic.SyncLibSymbolPinMaps( unitA->GetSchSymbolLibraryName(), *unitA->GetLibSymbolRef(), nullptr );
246
247 BOOST_CHECK( unitB->GetLibSymbolRef()->GetPinMaps() == unitA->GetLibSymbolRef()->GetPinMaps() );
248 BOOST_CHECK( unitB->GetLibSymbolRef()->GetAssociatedFootprints()
250
251 auto it = screen->GetLibSymbols().find( unitA->GetSchSymbolLibraryName() );
252 BOOST_REQUIRE( it != screen->GetLibSymbols().end() );
253 BOOST_CHECK( it->second->GetPinMaps() == unitA->GetLibSymbolRef()->GetPinMaps() );
254 BOOST_CHECK( it->second->GetAssociatedFootprints() == unitA->GetLibSymbolRef()->GetAssociatedFootprints() );
255}
256
257
258BOOST_AUTO_TEST_CASE( OverrideSurvivesCopyAndAssign )
259{
262 named.m_ActiveMapName = wxS( "DFN-8-EP" );
263 m_symbol->SetPinMapOverride( named );
264
265 SCH_SYMBOL copy( *m_symbol );
266 BOOST_CHECK( copy.GetPinMapOverride() == named );
267
268 SCH_SYMBOL assigned( *m_lib, m_lib->GetLibId(), nullptr, 0, 0, VECTOR2I( 0, 0 ) );
269 assigned = *m_symbol;
270 BOOST_CHECK( assigned.GetPinMapOverride() == named );
271}
272
273
const KIID m_Uuid
Definition eda_item.h:597
Definition kiid.h:46
A logical library item identifier and consists of various portions much like a URI.
Definition lib_id.h:45
int SetLibNickname(const UTF8 &aLibNickname)
Override the logical library name portion of the LIB_ID to aLibNickname.
Definition lib_id.cpp:113
Define a library symbol object.
Definition lib_symbol.h:119
void SetAssociatedFootprints(std::vector< ASSOCIATED_FOOTPRINT > aList)
Definition lib_symbol.h:267
const PIN_MAP_SET & GetPinMaps() const
Pin-to-pad mapping (issue #2282).
Definition lib_symbol.h:261
PIN_MAP_SET & PinMaps()
Definition lib_symbol.h:262
void AddDrawItem(SCH_ITEM *aItem, bool aSort=true)
Add a new draw aItem to the draw object list and sort according to aSort.
const std::vector< ASSOCIATED_FOOTPRINT > & GetAssociatedFootprints() const
Definition lib_symbol.h:265
void AddOrReplace(PIN_MAP aMap)
Insert aMap, replacing any existing entry with the same name.
Definition pin_map.cpp:113
A named pin map.
Definition pin_map.h:65
void SetEntry(const wxString &aPinNumber, const wxString &aPadNumber)
Set the pad number for a symbol pin.
Definition pin_map.cpp:59
Holds all the data relating to one schematic.
Definition schematic.h:148
void SyncLibSymbolPinMaps(const wxString &aSchLibSymbolName, const LIB_SYMBOL &aSource, SCH_COMMIT *aCommit)
void SetTopLevelSheets(const std::vector< SCH_SHEET * > &aSheets)
Replace the top level sheets, rebuilding the hierarchy and connectivity around them.
PAD_RESOLUTION
Outcome of pin-to-pad resolution (issue #2282).
Definition sch_pin.h:173
void Append(SCH_ITEM *aItem, bool aUpdateLibSymbol=true)
const std::map< wxString, LIB_SYMBOL * > & GetLibSymbols() const
Fetch a list of unique LIB_SYMBOL object pointers required to properly render each SCH_SYMBOL in this...
Definition sch_screen.h:503
const KIID & GetUuid() const
Definition sch_screen.h:540
Handle access to a stack of flattened SCH_SHEET objects by way of a path for creating a flattened sch...
Sheet symbol placed in a schematic, and is the entry point for a sub schematic.
Definition sch_sheet.h:48
void SetScreen(SCH_SCREEN *aScreen)
Set the SCH_SCREEN associated with this sheet to aScreen.
Schematic symbol object.
Definition sch_symbol.h:75
wxString GetSchSymbolLibraryName() const
PIN_MAP_INSTANCE_OVERRIDE GetPinMapOverride(const SCH_SHEET_PATH *aInstance=nullptr, const wxString &aVariantName=wxEmptyString) const
std::unique_ptr< LIB_SYMBOL > & GetLibSymbolRef()
Definition sch_symbol.h:183
@ PT_PASSIVE
pin for passive symbols: must be connected, and can be connected to any pin.
Definition pin_type.h:39
Definition of the SCH_SHEET_PATH and SCH_SHEET_LIST classes for Eeschema.
Per-instance override of the active pin map and a sparse delta on top.
Definition pin_map.h:200
std::vector< PIN_MAP_ENTRY > m_Edits
Definition pin_map.h:203
PIN_MAP_OVERRIDE_MODE m_Mode
Definition pin_map.h:201
std::unique_ptr< SCH_SYMBOL > m_symbol
std::unique_ptr< LIB_SYMBOL > m_lib
SCH_PIN * pin(const wxString &aNumber) const
BOOST_AUTO_TEST_CASE(HorizontalAlignment)
BOOST_REQUIRE(intersection.has_value()==c.ExpectedIntersection.has_value())
BOOST_AUTO_TEST_SUITE_END()
KIBIS_PIN * pin
BOOST_AUTO_TEST_CASE(ThreeResolutionStates)
SCH_PIN::PAD_RESOLUTION PAD_RESOLUTION
BOOST_CHECK_EQUAL(result, "25.4")
VECTOR2< int32_t > VECTOR2I
Definition vector2d.h:683