KiCad PCB EDA Suite
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-2021 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
37wxString NETLIST_EXPORTER_BASE::MakeCommandLine( const wxString& aFormatString,
38 const wxString& aNetlistFile,
39 const wxString& aFinalFile,
40 const wxString& aProjectPath )
41{
42 // Expand format symbols in the command line:
43 // %B => base filename of selected output file, minus path and extension.
44 // %P => project directory name, without trailing '/' or '\'.
45 // %I => full filename of the input file (the intermediate net file).
46 // %O => complete filename and path (but without extension) of the user chosen output file.
47
48 wxString ret = aFormatString;
49 wxFileName in = aNetlistFile;
50 wxFileName out = aFinalFile;
51 wxString str_out = out.GetFullPath();
52
53 ret.Replace( "%P", aProjectPath, true );
54 ret.Replace( "%B", out.GetName(), true );
55 ret.Replace( "%I", in.GetFullPath(), true );
56
57#ifdef __WINDOWS__
58 // A ugly hack to run xsltproc that has a serious bug on Window since a long time:
59 // the filename given after -o option (output filename) cannot use '\' in filename
60 // so replace if by '/' if possible (I mean if the filename does not start by "\\"
61 // that is a filename on a Windows server)
62
63 if( !str_out.StartsWith( "\\\\" ) )
64 str_out.Replace( "\\", "/" );
65#endif
66
67 ret.Replace( "%O", str_out, true );
68
69 return ret;
70}
71
72
74{
75 wxCHECK( aItem, nullptr );
76 wxCHECK( aSheetPath, nullptr );
77
78 wxString ref;
79
80 if( aItem->Type() != SCH_SYMBOL_T )
81 return nullptr;
82
83 // found next symbol
84 SCH_SYMBOL* symbol = (SCH_SYMBOL*) aItem;
85
86 // Power symbols and other symbols which have the reference starting with "#" are not
87 // included in netlist (pseudo or virtual symbols)
88 ref = symbol->GetRef( aSheetPath );
89
90 if( ref[0] == wxChar( '#' ) )
91 return nullptr;
92
93 SCH_SCREEN* screen = aSheetPath->LastScreen();
94
95 wxCHECK( screen, nullptr );
96
97 LIB_SYMBOL* libSymbol = screen->GetLibSymbols()[ symbol->GetSchSymbolLibraryName() ];
98
99 wxCHECK( libSymbol, nullptr );
100
101 // If symbol is a "multi parts per package" type
102 if( libSymbol->GetUnitCount() > 1 )
103 {
104 // test if this reference has already been processed, and if so skip
106 return nullptr;
107 }
108
109 // record the usage of this library symbol entry.
110 m_libParts.insert( libSymbol ); // rejects non-unique pointers
111
112 return symbol;
113}
114
115
117 SCH_SHEET_PATH* aSheetPath,
118 bool aKeepUnconnectedPins )
119{
120 wxString ref( aSymbol->GetRef( aSheetPath ) );
121
122 // Power symbols and other symbols which have the reference starting with "#" are not
123 // included in netlist (pseudo or virtual symbols)
124
125 if( ref[0] == wxChar( '#' ) )
126 return;
127
128 // if( aSymbol->m_FlagControlMulti == 1 )
129 // continue; /* yes */
130 // removed because with multiple instances of one schematic (several sheets pointing to
131 // 1 screen), this will be erroneously be toggled.
132
133 if( !aSymbol->GetLibSymbolRef() )
134 return;
135
136 m_sortedSymbolPinList.clear();
137
138 // If symbol is a "multi parts per package" type
139 if( aSymbol->GetLibSymbolRef()->GetUnitCount() > 1 )
140 {
141 // Collect all pins for this reference designator by searching the entire design for
142 // other parts with the same reference designator.
143 // This is only done once, it would be too expensive otherwise.
144 findAllUnitsOfSymbol( aSymbol, aSymbol->GetLibSymbolRef().get(),
145 aSheetPath, aKeepUnconnectedPins );
146 }
147
148 else // GetUnitCount() <= 1 means one part per package
149 {
151
152 for( const SCH_PIN* pin : aSymbol->GetPins( aSheetPath ) )
153 {
154 if( SCH_CONNECTION* conn = pin->Connection( aSheetPath ) )
155 {
156 const wxString& netName = conn->Name();
157
158 if( !aKeepUnconnectedPins ) // Skip unconnected pins if requested
159 {
160 CONNECTION_SUBGRAPH* sg = graph->FindSubgraphByName( netName, *aSheetPath );
161
162 if( !sg || sg->m_no_connect || sg->m_items.size() < 2 )
163 continue;
164 }
165
166 m_sortedSymbolPinList.emplace_back( pin->GetShownNumber(), netName );
167 }
168 }
169 }
170
171 // Sort pins in m_SortedSymbolPinList by pin number
172 std::sort( m_sortedSymbolPinList.begin(), m_sortedSymbolPinList.end(),
173 []( const PIN_INFO& lhs, const PIN_INFO& rhs )
174 {
175 return StrNumCmp( lhs.num, rhs.num, true ) < 0;
176 } );
177
178 // Remove duplicate Pins in m_SortedSymbolPinList
180
181 // record the usage of this library symbol
182 m_libParts.insert( aSymbol->GetLibSymbolRef().get() ); // rejects non-unique pointers
183}
184
185
187{
188 for( unsigned ii = 0; ii < m_sortedSymbolPinList.size(); ii++ )
189 {
190 if( m_sortedSymbolPinList[ii].num.empty() ) /* already deleted */
191 continue;
192
193 /* Search for duplicated pins
194 * If found, remove duplicates. The priority is to keep connected pins
195 * and remove unconnected
196 * - So this allows (for instance when using multi op amps per package
197 * - to connect only one op amp to power
198 * Because the pin list is sorted by m_PinNum value, duplicated pins
199 * are necessary successive in list
200 */
201 int idxref = ii;
202
203 for( unsigned jj = ii + 1; jj < m_sortedSymbolPinList.size(); jj++ )
204 {
205 if( m_sortedSymbolPinList[jj].num.empty() ) // Already removed
206 continue;
207
208 // if other pin num, stop search,
209 // because all pins having the same number are consecutive in list.
210 if( m_sortedSymbolPinList[idxref].num != m_sortedSymbolPinList[jj].num )
211 break;
212
213 m_sortedSymbolPinList[jj].num.clear();
214 }
215 }
216}
217
218
220 SCH_SHEET_PATH* aSheetPath,
221 bool aKeepUnconnectedPins )
222{
223 wxString ref = aSchSymbol->GetRef( aSheetPath );
224 wxString ref2;
225
226 SCH_SHEET_LIST sheetList = m_schematic->GetSheets();
228
229 for( unsigned i = 0; i < sheetList.size(); i++ )
230 {
231 SCH_SHEET_PATH& sheet = sheetList[i];
232
233 for( SCH_ITEM* item : sheetList[i].LastScreen()->Items().OfType( SCH_SYMBOL_T ) )
234 {
235 SCH_SYMBOL* comp2 = static_cast<SCH_SYMBOL*>( item );
236
237 ref2 = comp2->GetRef( &sheet );
238
239 if( ref2.CmpNoCase( ref ) != 0 )
240 continue;
241
242 for( const SCH_PIN* pin : comp2->GetPins( &sheet ) )
243 {
244 if( SCH_CONNECTION* conn = pin->Connection( &sheet ) )
245 {
246 const wxString& netName = conn->Name();
247
248 if( !aKeepUnconnectedPins ) // Skip unconnected pins if requested
249 {
250 CONNECTION_SUBGRAPH* sg = graph->FindSubgraphByName( netName, sheet );
251
252 if( !sg || sg->m_no_connect || sg->m_items.size() < 2 )
253 continue;
254 }
255
256 m_sortedSymbolPinList.emplace_back( pin->GetShownNumber(), netName );
257 }
258 }
259 }
260 }
261}
Calculates the connectivity of a schematic and generates netlists.
CONNECTION_SUBGRAPH * FindSubgraphByName(const wxString &aNetName, const SCH_SHEET_PATH &aPath)
Returns 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.
std::vector< SCH_ITEM * > m_items
SCH_ITEM * m_no_connect
No-connect item in graph, if any.
A base class for most all the KiCad significant classes used in schematics and boards.
Definition: eda_item.h:85
KICAD_T Type() const
Returns the type of object.
Definition: eda_item.h:97
Define a library symbol object.
Definition: lib_symbol.h:98
int GetUnitCount() const override
For items with units, return the number of units.
void CreatePinList(SCH_SYMBOL *aSymbol, SCH_SHEET_PATH *aSheetPath, bool aKeepUnconnectedPins)
Find a symbol from the DrawList and builds its pin list in m_sortedSymbolPinList.
void eraseDuplicatePins()
Erase duplicate pins from m_sortedSymbolPinList (i.e.
void findAllUnitsOfSymbol(SCH_SYMBOL *aSchSymbol, LIB_SYMBOL *aLibSymbol, SCH_SHEET_PATH *aSheetPath, bool aKeepUnconnectedPins)
Find all units for symbols with multiple symbols per package.
std::set< LIB_SYMBOL *, LIB_SYMBOL_LESS_THAN > m_libParts
unique library symbols used. LIB_SYMBOL items are sorted by names
UNIQUE_STRINGS m_referencesAlreadyFound
Used for "multiple symbols per package" symbols to avoid processing a lib symbol more than once.
SCH_SYMBOL * findNextSymbol(EDA_ITEM *aItem, SCH_SHEET_PATH *aSheetPath)
Check if the given symbol should be processed for netlisting.
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.
std::vector< PIN_INFO > m_sortedSymbolPinList
Used to temporarily store and filter the list of pins of a schematic symbol when generating schematic...
virtual CONNECTION_GRAPH * ConnectionGraph() const =0
virtual SCH_SHEET_LIST GetSheets() 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:147
std::map< wxString, LIB_SYMBOL * > & GetLibSymbols()
Fetch a list of unique LIB_SYMBOL object pointers required to properly render each SCH_SYMBOL in this...
Definition: sch_screen.h:453
A container for handling SCH_SHEET_PATH objects in a flattened hierarchy.
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:79
wxString GetSchSymbolLibraryName() const
Definition: sch_symbol.cpp:296
const wxString GetRef(const SCH_SHEET_PATH *aSheet, bool aIncludeUnit=false) const
Return the reference for the given sheet path.
Definition: sch_symbol.cpp:516
std::vector< SCH_PIN * > GetPins(const SCH_SHEET_PATH *aSheet=nullptr) const
Retrieve a list of the SCH_PINs for the given sheet path.
Definition: sch_symbol.cpp:972
std::unique_ptr< LIB_SYMBOL > & GetLibSymbolRef()
Definition: sch_symbol.h:189
bool Lookup(const wxString &aString)
Definition for symbol library class.
@ SCH_SYMBOL_T
Definition: typeinfo.h:155