KiCad PCB EDA Suite
Loading...
Searching...
No Matches
netlist_exporter_base.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 (C) 1992-2017 jp.charras at wanadoo.fr
5 * Copyright (C) 2013-2017 SoftPLC Corporation, Dick Hollenbeck <[email protected]>
6 * Copyright (C) 1992-2023, 2024 KiCad Developers, see AUTHORS.txt for contributors.
7 *
8 * This program is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU General Public License
10 * as published by the Free Software Foundation; either version 2
11 * of the License, or (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, you may find one here:
20 * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
21 * or you may search the http://www.gnu.org website for the version 2 license,
22 * or you may write to the Free Software Foundation, Inc.,
23 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
24 */
25
27
28#include <string_utils.h>
29
30#include <symbol_library.h>
31#include <connection_graph.h>
32#include <sch_reference_list.h>
33#include <sch_screen.h>
34#include <schematic.h>
35
36
37// a "less than" test on two LIB_SYMBOLs (.m_name wxStrings)
39 LIB_SYMBOL* const& libsymbol2 ) const
40{
41 // Use case specific GetName() wxString compare
42 return libsymbol1->GetLibId() < libsymbol2->GetLibId();
43}
44
45
46wxString NETLIST_EXPORTER_BASE::MakeCommandLine( const wxString& aFormatString,
47 const wxString& aNetlistFile,
48 const wxString& aFinalFile,
49 const wxString& aProjectPath )
50{
51 // Expand format symbols in the command line:
52 // %B => base filename of selected output file, minus path and extension.
53 // %P => project directory name, without trailing '/' or '\'.
54 // %I => full filename of the input file (the intermediate net file).
55 // %O => complete filename and path (but without extension) of the user chosen output file.
56
57 wxString ret = aFormatString;
58 wxFileName in = aNetlistFile;
59 wxFileName out = aFinalFile;
60 wxString str_out = out.GetFullPath();
61
62 ret.Replace( "%P", aProjectPath, true );
63 ret.Replace( "%B", out.GetName(), true );
64 ret.Replace( "%I", in.GetFullPath(), true );
65
66#ifdef __WINDOWS__
67 // A ugly hack to run xsltproc that has a serious bug on Window since a long time:
68 // the filename given after -o option (output filename) cannot use '\' in filename
69 // so replace if by '/' if possible (I mean if the filename does not start by "\\"
70 // that is a filename on a Windows server)
71
72 if( !str_out.StartsWith( "\\\\" ) )
73 str_out.Replace( "\\", "/" );
74#endif
75
76 ret.Replace( "%O", str_out, true );
77
78 return ret;
79}
80
81
83 const SCH_SHEET_PATH& aSheetPath )
84{
85 wxCHECK( aItem, nullptr );
86
87 wxString ref;
88
89 if( aItem->Type() != SCH_SYMBOL_T )
90 return nullptr;
91
92 // found next symbol
93 SCH_SYMBOL* symbol = (SCH_SYMBOL*) aItem;
94
95 // Power symbols and other symbols which have the reference starting with "#" are not
96 // included in netlist (pseudo or virtual symbols)
97 ref = symbol->GetRef( &aSheetPath );
98
99 if( ref[0] == wxChar( '#' ) )
100 return nullptr;
101
102 SCH_SCREEN* screen = aSheetPath.LastScreen();
103
104 wxCHECK( screen, nullptr );
105
106 auto it = screen->GetLibSymbols().find( symbol->GetSchSymbolLibraryName() );
107
108 if( it == screen->GetLibSymbols().end() )
109 return nullptr;
110
111 LIB_SYMBOL* libSymbol = it->second;
112
113 // If symbol is a "multi parts per package" type
114 if( libSymbol->GetUnitCount() > 1 )
115 {
116 // test if this reference has already been processed, and if so skip
118 return nullptr;
119 }
120
121 // record the usage of this library symbol entry.
122 m_libParts.insert( libSymbol ); // rejects non-unique pointers
123
124 return symbol;
125}
126
127
128std::vector<PIN_INFO> NETLIST_EXPORTER_BASE::CreatePinList( SCH_SYMBOL* aSymbol,
129 const SCH_SHEET_PATH& aSheetPath,
130 bool aKeepUnconnectedPins )
131{
132 std::vector<PIN_INFO> pins;
133
134 if( !aSymbol )
135 return pins;
136
137 wxString ref( aSymbol->GetRef( &aSheetPath ) );
138
139 // Power symbols and other symbols which have the reference starting with "#" are not
140 // included in netlist (pseudo or virtual symbols)
141 if( ( ref[0] == wxChar( '#' ) ) || aSymbol->IsPower() )
142 return pins;
143
144 // if( aSymbol->m_FlagControlMulti == 1 )
145 // continue; /* yes */
146 // removed because with multiple instances of one schematic (several sheets pointing to
147 // 1 screen), this will be erroneously be toggled.
148
149 if( !aSymbol->GetLibSymbolRef() )
150 return pins;
151
152 // If symbol is a "multi parts per package" type
153 if( aSymbol->GetLibSymbolRef()->GetUnitCount() > 1 )
154 {
155 // Collect all pins for this reference designator by searching the entire design for
156 // other parts with the same reference designator.
157 // This is only done once, it would be too expensive otherwise.
158 findAllUnitsOfSymbol( aSymbol, aSheetPath, pins, aKeepUnconnectedPins );
159 }
160
161 else // GetUnitCount() <= 1 means one part per package
162 {
164
165 for( const SCH_PIN* pin : aSymbol->GetPins( &aSheetPath ) )
166 {
167 if( SCH_CONNECTION* conn = pin->Connection( &aSheetPath ) )
168 {
169 const wxString& netName = conn->Name();
170
171 if( !aKeepUnconnectedPins ) // Skip unconnected pins if requested
172 {
173 CONNECTION_SUBGRAPH* sg = graph->FindSubgraphByName( netName, aSheetPath );
174
175 if( !sg || sg->GetNoConnect() || sg->GetItems().size() < 2 )
176 continue;
177 }
178
179 pins.emplace_back( pin->GetShownNumber(), netName );
180 }
181 }
182 }
183
184 // Sort pins in m_SortedSymbolPinList by pin number
185 std::sort( pins.begin(), pins.end(),
186 []( const PIN_INFO& lhs, const PIN_INFO& rhs )
187 {
188 return StrNumCmp( lhs.num, rhs.num, true ) < 0;
189 } );
190
191 // Remove duplicate Pins in m_SortedSymbolPinList
192 eraseDuplicatePins( pins );
193
194 // record the usage of this library symbol
195 m_libParts.insert( aSymbol->GetLibSymbolRef().get() ); // rejects non-unique pointers
196
197 return pins;
198}
199
200
201void NETLIST_EXPORTER_BASE::eraseDuplicatePins( std::vector<PIN_INFO>& aPins )
202{
203 for( unsigned ii = 0; ii < aPins.size(); ii++ )
204 {
205 if( aPins[ii].num.empty() ) /* already deleted */
206 continue;
207
208 /* Search for duplicated pins
209 * If found, remove duplicates. The priority is to keep connected pins
210 * and remove unconnected
211 * - So this allows (for instance when using multi op amps per package
212 * - to connect only one op amp to power
213 * Because the pin list is sorted by m_PinNum value, duplicated pins
214 * are necessary successive in list
215 */
216 int idxref = ii;
217
218 for( unsigned jj = ii + 1; jj < aPins.size(); jj++ )
219 {
220 if( aPins[jj].num.empty() ) // Already removed
221 continue;
222
223 // if other pin num, stop search,
224 // because all pins having the same number are consecutive in list.
225 if( aPins[idxref].num != aPins[jj].num )
226 break;
227
228 aPins[jj].num.clear();
229 }
230 }
231}
232
233
235 const SCH_SHEET_PATH& aSheetPath,
236 std::vector<PIN_INFO>& aPins,
237 bool aKeepUnconnectedPins )
238{
239 wxString ref = aSchSymbol->GetRef( &aSheetPath );
240 wxString ref2;
241
243
244 for( const SCH_SHEET_PATH& sheet : m_schematic->Hierarchy() )
245 {
246 for( SCH_ITEM* item : sheet.LastScreen()->Items().OfType( SCH_SYMBOL_T ) )
247 {
248 SCH_SYMBOL* comp2 = static_cast<SCH_SYMBOL*>( item );
249
250 ref2 = comp2->GetRef( &sheet );
251
252 if( ref2.CmpNoCase( ref ) != 0 )
253 continue;
254
255 for( const SCH_PIN* pin : comp2->GetPins( &sheet ) )
256 {
257 if( SCH_CONNECTION* conn = pin->Connection( &sheet ) )
258 {
259 const wxString& netName = conn->Name();
260
261 if( !aKeepUnconnectedPins ) // Skip unconnected pins if requested
262 {
263 CONNECTION_SUBGRAPH* sg = graph->FindSubgraphByName( netName, sheet );
264
265 if( !sg || sg->GetNoConnect() || sg->GetItems().size() < 2 )
266 continue;
267 }
268
269 aPins.emplace_back( pin->GetShownNumber(), netName );
270 }
271 }
272 }
273 }
274}
Calculate the connectivity of a schematic and generates netlists.
CONNECTION_SUBGRAPH * FindSubgraphByName(const wxString &aNetName, const SCH_SHEET_PATH &aPath)
Return the subgraph for a given net name on a given sheet.
A subgraph is a set of items that are electrically connected on a single sheet.
const std::set< SCH_ITEM * > & GetItems() const
Provide a read-only reference to the items in the subgraph.
const SCH_ITEM * GetNoConnect() const
A base class for most all the KiCad significant classes used in schematics and boards.
Definition: eda_item.h:89
KICAD_T Type() const
Returns the type of object.
Definition: eda_item.h:101
Define a library symbol object.
Definition: lib_symbol.h:78
const LIB_ID & GetLibId() const override
Definition: lib_symbol.h:143
int GetUnitCount() const override
std::vector< PIN_INFO > CreatePinList(SCH_SYMBOL *aSymbol, const SCH_SHEET_PATH &aSheetPath, bool aKeepUnconnectedPins)
Find a symbol from the DrawList and builds its pin list.
void findAllUnitsOfSymbol(SCH_SYMBOL *aSchSymbol, const SCH_SHEET_PATH &aSheetPath, std::vector< PIN_INFO > &aPins, bool aKeepUnconnectedPins)
Find all units for symbols with multiple symbols per package.
SCH_SYMBOL * findNextSymbol(EDA_ITEM *aItem, const SCH_SHEET_PATH &aSheetPath)
Check if the given symbol should be processed for netlisting.
std::set< LIB_SYMBOL *, LIB_SYMBOL_LESS_THAN > m_libParts
unique library symbols used. LIB_SYMBOL items are sorted by names
void eraseDuplicatePins(std::vector< PIN_INFO > &pins)
Erase duplicate pins.
UNIQUE_STRINGS m_referencesAlreadyFound
Used for "multiple symbols per package" symbols to avoid processing a lib symbol more than once.
static wxString MakeCommandLine(const wxString &aFormatString, const wxString &aNetlistFile, const wxString &aFinalFile, const wxString &aProjectDirectory)
Build up a string that describes a command line for executing a child process.
SCHEMATIC_IFACE * m_schematic
The schematic we're generating a netlist for.
virtual CONNECTION_GRAPH * ConnectionGraph() const =0
virtual SCH_SHEET_LIST Hierarchy() const =0
Each graphical item can have a SCH_CONNECTION describing its logical connection (to a bus or net).
Base class for any item which can be embedded within the SCHEMATIC container class,...
Definition: sch_item.h:166
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:480
Handle access to a stack of flattened SCH_SHEET objects by way of a path for creating a flattened sch...
SCH_SCREEN * LastScreen()
Schematic symbol object.
Definition: sch_symbol.h:104
wxString GetSchSymbolLibraryName() const
Definition: sch_symbol.cpp:270
std::vector< SCH_PIN * > GetPins(const SCH_SHEET_PATH *aSheet=nullptr) const
Retrieve a list of the SCH_PINs for the given sheet path.
std::unique_ptr< LIB_SYMBOL > & GetLibSymbolRef()
Definition: sch_symbol.h:212
const wxString GetRef(const SCH_SHEET_PATH *aSheet, bool aIncludeUnit=false) const override
Definition: sch_symbol.cpp:737
bool IsPower() const override
bool Lookup(const wxString &aString)
bool operator()(LIB_SYMBOL *const &libsymbol1, LIB_SYMBOL *const &libsymbol2) const
Definition for symbol library class.
@ SCH_SYMBOL_T
Definition: typeinfo.h:172