KiCad PCB EDA Suite
NETLIST_EXPORTER_KICAD Class Reference

Generate the KiCad netlist format supported by Pcbnew. More...

#include <netlist_exporter_kicad.h>

Inheritance diagram for NETLIST_EXPORTER_KICAD:
NETLIST_EXPORTER_XML NETLIST_EXPORTER_BASE

Public Member Functions

 NETLIST_EXPORTER_KICAD (SCHEMATIC *aSchematic)
 
bool WriteNetlist (const wxString &aOutFileName, unsigned aNetlistOptions) override
 Write netlist to aOutFileName. More...
 
void Format (OUTPUTFORMATTER *aOutputFormatter, int aCtl)
 Output this s-expression netlist into aOutputFormatter. More...
 

Static Public Member Functions

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. More...
 

Protected Member Functions

XNODEnode (const wxString &aName, const wxString &aTextualContent=wxEmptyString)
 A convenience function that creates a new XNODE with an optional textual child. More...
 
XNODEmakeRoot (unsigned aCtl=GNL_ALL)
 Build the entire document tree for the generic export. More...
 
XNODEmakeSymbols (unsigned aCtl)
 
XNODEmakeDesignHeader ()
 Fill out a project "design" header into an XML node. More...
 
XNODEmakeLibParts ()
 Fill out an XML node with the unique library parts and returns it. More...
 
XNODEmakeListOfNets (unsigned aCtl)
 Fill out an XML node with a list of nets and returns it. More...
 
XNODEmakeLibraries ()
 Fill out an XML node with a list of used libraries and returns it. More...
 
void addSymbolFields (XNODE *aNode, SCH_SYMBOL *aSymbol, SCH_SHEET_PATH *aSheet)
 Holder for multi-unit symbol fields. More...
 
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. More...
 
SCH_SYMBOLfindNextSymbol (EDA_ITEM *aItem, SCH_SHEET_PATH *aSheetPath)
 Check if the given symbol should be processed for netlisting. More...
 
void eraseDuplicatePins ()
 Erase duplicate pins from m_sortedSymbolPinList (i.e. More...
 
void findAllUnitsOfSymbol (SCH_SYMBOL *aSchSymbol, LIB_SYMBOL *aLibSymbol, SCH_SHEET_PATH *aSheetPath, bool aKeepUnconnectedPins)
 Find all units for symbols with multiple symbols per package. More...
 

Protected Attributes

bool m_resolveTextVars
 
std::vector< PIN_INFOm_sortedSymbolPinList
 Used to temporarily store and filter the list of pins of a schematic symbol when generating schematic symbol data in netlist (comp section). More...
 
UNIQUE_STRINGS m_referencesAlreadyFound
 Used for "multiple symbols per package" symbols to avoid processing a lib symbol more than once. More...
 
std::set< LIB_SYMBOL *, LIB_SYMBOL_LESS_THANm_libParts
 unique library symbols used. LIB_SYMBOL items are sorted by names More...
 
SCHEMATIC_IFACEm_schematic
 The schematic we're generating a netlist for. More...
 
SCH_SHEET_PATH m_savedCurrentSheet
 The schematic's CurrentSheet when we entered. Restore on exiting. More...
 

Private Attributes

std::set< wxString > m_libraries
 

Detailed Description

Generate the KiCad netlist format supported by Pcbnew.

It is basically the XML netlist just formatted slightly different.

Definition at line 37 of file netlist_exporter_kicad.h.

Constructor & Destructor Documentation

◆ NETLIST_EXPORTER_KICAD()

NETLIST_EXPORTER_KICAD::NETLIST_EXPORTER_KICAD ( SCHEMATIC aSchematic)
inline

Definition at line 40 of file netlist_exporter_kicad.h.

40 :
41 NETLIST_EXPORTER_XML( aSchematic )
42 {}
NETLIST_EXPORTER_XML(SCHEMATIC *aSchematic)

Member Function Documentation

◆ addSymbolFields()

void NETLIST_EXPORTER_XML::addSymbolFields ( XNODE aNode,
SCH_SYMBOL aSymbol,
SCH_SHEET_PATH aSheet 
)
protectedinherited

Holder for multi-unit symbol fields.

Definition at line 92 of file netlist_exporter_xml.cpp.

94{
95 wxString value;
96 wxString datasheet;
97 wxString footprint;
98 std::map<wxString, wxString> userFields;
99
100 if( aSymbol->GetUnitCount() > 1 )
101 {
102 // Sadly, each unit of a symbol can have its own unique fields. This
103 // block finds the unit with the lowest number having a non blank field
104 // value and records it. Therefore user is best off setting fields
105 // into only the first unit. But this scavenger algorithm will find
106 // any non blank fields in all units and use the first non-blank field
107 // for each unique field name.
108
109 wxString ref = aSymbol->GetRef( aSheet );
110
111 SCH_SHEET_LIST sheetList = m_schematic->GetSheets();
112 int minUnit = aSymbol->GetUnit();
113
114 for( unsigned i = 0; i < sheetList.size(); i++ )
115 {
116 for( SCH_ITEM* item : sheetList[i].LastScreen()->Items().OfType( SCH_SYMBOL_T ) )
117 {
118 SCH_SYMBOL* symbol2 = (SCH_SYMBOL*) item;
119
120 wxString ref2 = symbol2->GetRef( &sheetList[i] );
121
122 if( ref2.CmpNoCase( ref ) != 0 )
123 continue;
124
125 int unit = symbol2->GetUnit();
126
127 // The lowest unit number wins. User should only set fields in any one unit.
128 // remark: IsVoid() returns true for empty strings or the "~" string (empty
129 // field value)
130 if( !symbol2->GetValue( &sheetList[i], m_resolveTextVars ).IsEmpty()
131 && ( unit < minUnit || value.IsEmpty() ) )
132 {
133 value = symbol2->GetValue( &sheetList[i], m_resolveTextVars );
134 }
135
136 if( !symbol2->GetFootprint( &sheetList[i], m_resolveTextVars ).IsEmpty()
137 && ( unit < minUnit || footprint.IsEmpty() ) )
138 {
139 footprint = symbol2->GetFootprint( &sheetList[i], m_resolveTextVars );
140 }
141
142 if( !symbol2->GetField( DATASHEET_FIELD )->IsVoid()
143 && ( unit < minUnit || datasheet.IsEmpty() ) )
144 {
147 else
148 datasheet = symbol2->GetField( DATASHEET_FIELD )->GetText();
149 }
150
151 for( int ii = MANDATORY_FIELDS; ii < symbol2->GetFieldCount(); ++ii )
152 {
153 const SCH_FIELD& f = symbol2->GetFields()[ ii ];
154
155 if( f.GetText().size()
156 && ( unit < minUnit || userFields.count( f.GetName() ) == 0 ) )
157 {
159 userFields[ f.GetName() ] = f.GetShownText();
160 else
161 userFields[ f.GetName() ] = f.GetText();
162 }
163 }
164
165 minUnit = std::min( unit, minUnit );
166 }
167 }
168 }
169 else
170 {
171 value = aSymbol->GetValue( aSheet, m_resolveTextVars );
172 footprint = aSymbol->GetFootprint( aSheet, m_resolveTextVars );
173
176 else
177 datasheet = aSymbol->GetField( DATASHEET_FIELD )->GetText();
178
179 for( int ii = MANDATORY_FIELDS; ii < aSymbol->GetFieldCount(); ++ii )
180 {
181 const SCH_FIELD& f = aSymbol->GetFields()[ ii ];
182
183 if( f.GetText().size() )
184 {
186 userFields[ f.GetName() ] = f.GetShownText();
187 else
188 userFields[ f.GetName() ] = f.GetText();
189 }
190 }
191 }
192
193 // Do not output field values blank in netlist:
194 if( value.size() )
195 aNode->AddChild( node( wxT( "value" ), UnescapeString( value ) ) );
196 else // value field always written in netlist
197 aNode->AddChild( node( wxT( "value" ), wxT( "~" ) ) );
198
199 if( footprint.size() )
200 aNode->AddChild( node( wxT( "footprint" ), UnescapeString( footprint ) ) );
201
202 if( datasheet.size() )
203 aNode->AddChild( node( wxT( "datasheet" ), UnescapeString( datasheet ) ) );
204
205 if( userFields.size() )
206 {
207 XNODE* xfields;
208 aNode->AddChild( xfields = node( wxT( "fields" ) ) );
209
210 // non MANDATORY fields are output alphabetically
211 for( const std::pair<const wxString, wxString>& f : userFields )
212 {
213 XNODE* xfield = node( wxT( "field" ), UnescapeString( f.second ) );
214 xfield->AddAttribute( wxT( "name" ), UnescapeString( f.first ) );
215 xfields->AddChild( xfield );
216 }
217 }
218}
virtual const wxString & GetText() const
Return the string associated with the text object.
Definition: eda_text.h:88
SCHEMATIC_IFACE * m_schematic
The schematic we're generating a netlist for.
XNODE * node(const wxString &aName, const wxString &aTextualContent=wxEmptyString)
A convenience function that creates a new XNODE with an optional textual child.
virtual SCH_SHEET_LIST GetSheets() const =0
Instances are attached to a symbol or sheet and provide a place for the symbol's value,...
Definition: sch_field.h:50
bool IsVoid() const
Definition: sch_field.cpp:527
wxString GetShownText(int aDepth=0) const override
Return the string actually shown after processing of the base text.
Definition: sch_field.cpp:165
wxString GetName(bool aUseDefaultName=true) const
Return the field name (not translated).
Definition: sch_field.cpp:791
Base class for any item which can be embedded within the SCHEMATIC container class,...
Definition: sch_item.h:145
A container for handling SCH_SHEET_PATH objects in a flattened hierarchy.
Schematic symbol object.
Definition: sch_symbol.h:79
int GetUnitCount() const
Return the number of units per package of the symbol.
Definition: sch_symbol.cpp:416
int GetUnit() const
Definition: sch_symbol.h:205
int GetFieldCount() const
Return the number of fields in this symbol.
Definition: sch_symbol.h:436
const wxString GetFootprint(const SCH_SHEET_PATH *sheet, bool aResolve) const
Return the instance-specific footprint assignment for the given sheet path.
Definition: sch_symbol.cpp:687
const wxString GetRef(const SCH_SHEET_PATH *aSheet, bool aIncludeUnit=false) const
Return the reference for the given sheet path.
Definition: sch_symbol.cpp:487
SCH_FIELD * GetField(MANDATORY_FIELD_T aFieldType)
Return a mandatory field in this symbol.
Definition: sch_symbol.cpp:746
const wxString GetValue(const SCH_SHEET_PATH *sheet, bool aResolve) const
Return the instance-specific value for the given sheet path.
Definition: sch_symbol.cpp:621
void GetFields(std::vector< SCH_FIELD * > &aVector, bool aVisibleOnly)
Populate a std::vector with SCH_FIELDs.
Definition: sch_symbol.cpp:782
Hold an XML or S-expression element.
Definition: xnode.h:44
wxString UnescapeString(const wxString &aSource)
@ DATASHEET_FIELD
name of datasheet
@ MANDATORY_FIELDS
The first 4 are mandatory, and must be instantiated in SCH_COMPONENT and LIB_PART constructors.
@ SCH_SYMBOL_T
Definition: typeinfo.h:147

References datasheet, DATASHEET_FIELD, SCH_SYMBOL::GetField(), SCH_SYMBOL::GetFieldCount(), SCH_SYMBOL::GetFields(), SCH_SYMBOL::GetFootprint(), SCH_FIELD::GetName(), SCH_SYMBOL::GetRef(), SCHEMATIC_IFACE::GetSheets(), SCH_FIELD::GetShownText(), EDA_TEXT::GetText(), SCH_SYMBOL::GetUnit(), SCH_SYMBOL::GetUnitCount(), SCH_SYMBOL::GetValue(), SCH_FIELD::IsVoid(), NETLIST_EXPORTER_XML::m_resolveTextVars, NETLIST_EXPORTER_BASE::m_schematic, MANDATORY_FIELDS, NETLIST_EXPORTER_XML::node(), SCH_SYMBOL_T, and UnescapeString().

Referenced by NETLIST_EXPORTER_XML::makeSymbols().

◆ CreatePinList()

void NETLIST_EXPORTER_BASE::CreatePinList ( SCH_SYMBOL aSymbol,
SCH_SHEET_PATH aSheetPath,
bool  aKeepUnconnectedPins 
)
protectedinherited

Find a symbol from the DrawList and builds its pin list in m_sortedSymbolPinList.

This list is sorted by pin number. The symbol is the next actual symbol after aSymbol. Power symbols and virtual symbols that have their reference designators starting with '#' are skipped. if aKeepUnconnectedPins = false, unconnected pins will be removed from list but usually we need all pins in netlists.

Definition at line 124 of file netlist_exporter_base.cpp.

127{
128 wxString ref( aSymbol->GetRef( aSheetPath ) );
129
130 // Power symbols and other symbols which have the reference starting with "#" are not
131 // included in netlist (pseudo or virtual symbols)
132
133 if( ref[0] == wxChar( '#' ) )
134 return;
135
136 // if( aSymbol->m_FlagControlMulti == 1 )
137 // continue; /* yes */
138 // removed because with multiple instances of one schematic (several sheets pointing to
139 // 1 screen), this will be erroneously be toggled.
140
141 if( !aSymbol->GetLibSymbolRef() )
142 return;
143
144 m_sortedSymbolPinList.clear();
145
146 // If symbol is a "multi parts per package" type
147 if( aSymbol->GetLibSymbolRef()->GetUnitCount() > 1 )
148 {
149 // Collect all pins for this reference designator by searching the entire design for
150 // other parts with the same reference designator.
151 // This is only done once, it would be too expensive otherwise.
152 findAllUnitsOfSymbol( aSymbol, aSymbol->GetLibSymbolRef().get(),
153 aSheetPath, aKeepUnconnectedPins );
154 }
155
156 else // GetUnitCount() <= 1 means one part per package
157 {
159
160 for( const SCH_PIN* pin : aSymbol->GetPins( aSheetPath ) )
161 {
162 if( SCH_CONNECTION* conn = pin->Connection( aSheetPath ) )
163 {
164 const wxString& netName = conn->Name();
165
166 if( !aKeepUnconnectedPins ) // Skip unconnected pins if requested
167 {
168 CONNECTION_SUBGRAPH* sg = graph->FindSubgraphByName( netName, *aSheetPath );
169
170 if( !sg || sg->m_no_connect || sg->m_items.size() < 2 )
171 continue;
172 }
173
174 m_sortedSymbolPinList.emplace_back( pin->GetShownNumber(), netName );
175 }
176 }
177 }
178
179 // Sort pins in m_SortedSymbolPinList by pin number
181
182 // Remove duplicate Pins in m_SortedSymbolPinList
184
185 // record the usage of this library symbol
186 m_libParts.insert( aSymbol->GetLibSymbolRef().get() ); // rejects non-unique pointers
187}
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.
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
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
Each graphical item can have a SCH_CONNECTION describing its logical connection (to a bus or net).
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:936
std::unique_ptr< LIB_SYMBOL > & GetLibSymbolRef()
Definition: sch_symbol.h:174
static bool sortPinsByNum(PIN_INFO &aPin1, PIN_INFO &aPin2)
Comparison routine for sorting by pin numbers.

References SCHEMATIC_IFACE::ConnectionGraph(), NETLIST_EXPORTER_BASE::eraseDuplicatePins(), NETLIST_EXPORTER_BASE::findAllUnitsOfSymbol(), CONNECTION_GRAPH::FindSubgraphByName(), SCH_SYMBOL::GetLibSymbolRef(), SCH_SYMBOL::GetPins(), SCH_SYMBOL::GetRef(), CONNECTION_SUBGRAPH::m_items, NETLIST_EXPORTER_BASE::m_libParts, CONNECTION_SUBGRAPH::m_no_connect, NETLIST_EXPORTER_BASE::m_schematic, NETLIST_EXPORTER_BASE::m_sortedSymbolPinList, pin, and sortPinsByNum().

Referenced by NETLIST_EXPORTER_SPICE::ReadSchematicAndLibraries(), and NETLIST_EXPORTER_ORCADPCB2::WriteNetlist().

◆ eraseDuplicatePins()

void NETLIST_EXPORTER_BASE::eraseDuplicatePins ( )
protectedinherited

Erase duplicate pins from m_sortedSymbolPinList (i.e.

set pointer in this list to NULL).

(This is a list of pins found in the whole schematic, for a single symbol.) These duplicate pins were put in list because some pins (power pins...) are found more than once when in "multiple symbols per package" symbols. For instance, a 74ls00 has 4 symbols, and therefore the VCC pin and GND pin appears 4 times in the list. Note: this list MUST be sorted by pin number (.m_PinNum member value) Also set the m_Flag member of "removed" NETLIST_OBJECT pin item to 1

Definition at line 190 of file netlist_exporter_base.cpp.

191{
192 for( unsigned ii = 0; ii < m_sortedSymbolPinList.size(); ii++ )
193 {
194 if( m_sortedSymbolPinList[ii].num.empty() ) /* already deleted */
195 continue;
196
197 /* Search for duplicated pins
198 * If found, remove duplicates. The priority is to keep connected pins
199 * and remove unconnected
200 * - So this allows (for instance when using multi op amps per package
201 * - to connect only one op amp to power
202 * Because the pin list is sorted by m_PinNum value, duplicated pins
203 * are necessary successive in list
204 */
205 int idxref = ii;
206
207 for( unsigned jj = ii + 1; jj < m_sortedSymbolPinList.size(); jj++ )
208 {
209 if( m_sortedSymbolPinList[jj].num.empty() ) // Already removed
210 continue;
211
212 // if other pin num, stop search,
213 // because all pins having the same number are consecutive in list.
214 if( m_sortedSymbolPinList[idxref].num != m_sortedSymbolPinList[jj].num )
215 break;
216
217 m_sortedSymbolPinList[jj].num.clear();
218 }
219 }
220}

References NETLIST_EXPORTER_BASE::m_sortedSymbolPinList.

Referenced by NETLIST_EXPORTER_BASE::CreatePinList().

◆ findAllUnitsOfSymbol()

void NETLIST_EXPORTER_BASE::findAllUnitsOfSymbol ( SCH_SYMBOL aSchSymbol,
LIB_SYMBOL aLibSymbol,
SCH_SHEET_PATH aSheetPath,
bool  aKeepUnconnectedPins 
)
protectedinherited

Find all units for symbols with multiple symbols per package.

Search the entire design for all units of aSymbol based on matching reference designator, and for each unit, add all its pins to the temporary sorted pin list, m_sortedSymbolPinList. if aKeepUnconnectedPins = false, unconnected pins will be removed from list but usually we need all pins in netlists.

Definition at line 223 of file netlist_exporter_base.cpp.

226{
227 wxString ref = aSchSymbol->GetRef( aSheetPath );
228 wxString ref2;
229
230 SCH_SHEET_LIST sheetList = m_schematic->GetSheets();
232
233 for( unsigned i = 0; i < sheetList.size(); i++ )
234 {
235 SCH_SHEET_PATH& sheet = sheetList[i];
236
237 for( SCH_ITEM* item : sheetList[i].LastScreen()->Items().OfType( SCH_SYMBOL_T ) )
238 {
239 SCH_SYMBOL* comp2 = static_cast<SCH_SYMBOL*>( item );
240
241 ref2 = comp2->GetRef( &sheet );
242
243 if( ref2.CmpNoCase( ref ) != 0 )
244 continue;
245
246 for( const SCH_PIN* pin : comp2->GetPins( &sheet ) )
247 {
248 if( SCH_CONNECTION* conn = pin->Connection( &sheet ) )
249 {
250 const wxString& netName = conn->Name();
251
252 if( !aKeepUnconnectedPins ) // Skip unconnected pins if requested
253 {
254 CONNECTION_SUBGRAPH* sg = graph->FindSubgraphByName( netName, sheet );
255
256 if( !sg || sg->m_no_connect || sg->m_items.size() < 2 )
257 continue;
258 }
259
260 m_sortedSymbolPinList.emplace_back( pin->GetShownNumber(), netName );
261 }
262 }
263 }
264 }
265}
Handle access to a stack of flattened SCH_SHEET objects by way of a path for creating a flattened sch...

References SCHEMATIC_IFACE::ConnectionGraph(), CONNECTION_GRAPH::FindSubgraphByName(), SCH_SYMBOL::GetPins(), SCH_SYMBOL::GetRef(), SCHEMATIC_IFACE::GetSheets(), CONNECTION_SUBGRAPH::m_items, CONNECTION_SUBGRAPH::m_no_connect, NETLIST_EXPORTER_BASE::m_schematic, NETLIST_EXPORTER_BASE::m_sortedSymbolPinList, pin, and SCH_SYMBOL_T.

Referenced by NETLIST_EXPORTER_BASE::CreatePinList().

◆ findNextSymbol()

SCH_SYMBOL * NETLIST_EXPORTER_BASE::findNextSymbol ( EDA_ITEM aItem,
SCH_SHEET_PATH aSheetPath 
)
protectedinherited

Check if the given symbol should be processed for netlisting.

Prevent processing multi-unit symbols more than once, etc.

Parameters
aItemis a symbol to check
aSheetPathis the sheet to check the symbol for
Returns
the symbol if it should be processed, or nullptr

Definition at line 73 of file netlist_exporter_base.cpp.

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}
KICAD_T Type() const
Returns the type of object.
Definition: eda_item.h:112
Define a library symbol object.
Definition: lib_symbol.h:99
int GetUnitCount() const override
For items with units, return the number of units.
UNIQUE_STRINGS m_referencesAlreadyFound
Used for "multiple symbols per package" symbols to avoid processing a lib symbol more than once.
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:452
SCH_SCREEN * LastScreen()
wxString GetSchSymbolLibraryName() const
Definition: sch_symbol.cpp:285
bool Lookup(const wxString &aString)

References SCH_SCREEN::GetLibSymbols(), SCH_SYMBOL::GetRef(), SCH_SYMBOL::GetSchSymbolLibraryName(), LIB_SYMBOL::GetUnitCount(), SCH_SHEET_PATH::LastScreen(), UNIQUE_STRINGS::Lookup(), NETLIST_EXPORTER_BASE::m_libParts, NETLIST_EXPORTER_BASE::m_referencesAlreadyFound, SCH_SYMBOL_T, and EDA_ITEM::Type().

Referenced by NETLIST_EXPORTER_XML::makeSymbols(), NETLIST_EXPORTER_SPICE::ReadSchematicAndLibraries(), NETLIST_EXPORTER_CADSTAR::WriteNetlist(), and NETLIST_EXPORTER_ORCADPCB2::WriteNetlist().

◆ Format()

void NETLIST_EXPORTER_KICAD::Format ( OUTPUTFORMATTER aOutputFormatter,
int  aCtl 
)

Output this s-expression netlist into aOutputFormatter.

Parameters
aOutputFormatteris the destination of the serialization to text.
aCtlis bit set composed by OR-ing together enum GNL bits, it allows outputting a subset of the full document model.
Exceptions
IO_ERRORif any problems.

Definition at line 53 of file netlist_exporter_kicad.cpp.

54{
55 std::unique_ptr<XNODE> xroot( makeRoot( aCtl ) );
56
57 xroot->Format( aOut, 0 );
58}
XNODE * makeRoot(unsigned aCtl=GNL_ALL)
Build the entire document tree for the generic export.

References NETLIST_EXPORTER_XML::makeRoot().

Referenced by SCH::generateSchematicNetlist(), SCH_EDIT_FRAME::KiwayMailIn(), SCH_EDIT_FRAME::sendNetlistToCvpcb(), and WriteNetlist().

◆ MakeCommandLine()

wxString NETLIST_EXPORTER_BASE::MakeCommandLine ( const wxString &  aFormatString,
const wxString &  aNetlistFile,
const wxString &  aFinalFile,
const wxString &  aProjectDirectory 
)
staticinherited

Build up a string that describes a command line for executing a child process.

The input and output file names along with any options to the executable are all possibly in the returned string.

Parameters
aFormatStringholds:
  • the name of the external program
  • any options needed by that program
  • formatting sequences, see below.
aNetlistFileis the name of the input file for the external program, that is a intermediate netlist file in xml format.
aFinalFileis the name of the output file that the user expects.
aProjectDirectoryis used for P replacement, it should omit the trailing '/'.

Supported formatting sequences and their meaning:

  • B => base filename of selected output file, minus path and extension.
  • I => complete filename and path of the temporary input file.
  • O => complete filename and path of the user chosen output file.
  • P => project directory, without name and without trailing '/'

Definition at line 37 of file netlist_exporter_base.cpp.

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}

Referenced by SCH_EDIT_FRAME::WriteNetListFile().

◆ makeDesignHeader()

XNODE * NETLIST_EXPORTER_XML::makeDesignHeader ( )
protectedinherited

Fill out a project "design" header into an XML node.

Returns
the design header

Definition at line 404 of file netlist_exporter_xml.cpp.

405{
406 SCH_SCREEN* screen;
407 XNODE* xdesign = node( wxT( "design" ) );
408 XNODE* xtitleBlock;
409 XNODE* xsheet;
410 XNODE* xcomment;
411 XNODE* xtextvar;
412 wxString sheetTxt;
413 wxFileName sourceFileName;
414
415 // the root sheet is a special sheet, call it source
416 xdesign->AddChild( node( wxT( "source" ), m_schematic->GetFileName() ) );
417
418 xdesign->AddChild( node( wxT( "date" ), DateAndTime() ) );
419
420 // which Eeschema tool
421 xdesign->AddChild( node( wxT( "tool" ), wxT( "Eeschema " ) + GetBuildVersion() ) );
422
423 const std::map<wxString, wxString>& properties = m_schematic->Prj().GetTextVars();
424
425 for( const std::pair<const wxString, wxString>& prop : properties )
426 {
427 xdesign->AddChild( xtextvar = node( wxT( "textvar" ), prop.second ) );
428 xtextvar->AddAttribute( wxT( "name" ), prop.first );
429 }
430
431 /*
432 * Export the sheets information
433 */
434 SCH_SHEET_LIST sheetList = m_schematic->GetSheets();
435
436 for( unsigned i = 0; i < sheetList.size(); i++ )
437 {
438 screen = sheetList[i].LastScreen();
439
440 xdesign->AddChild( xsheet = node( wxT( "sheet" ) ) );
441
442 // get the string representation of the sheet index number.
443 // Note that sheet->GetIndex() is zero index base and we need to increment the
444 // number by one to make it human readable
445 sheetTxt.Printf( wxT( "%u" ), i + 1 );
446 xsheet->AddAttribute( wxT( "number" ), sheetTxt );
447 xsheet->AddAttribute( wxT( "name" ), sheetList[i].PathHumanReadable() );
448 xsheet->AddAttribute( wxT( "tstamps" ), sheetList[i].PathAsString() );
449
450 TITLE_BLOCK tb = screen->GetTitleBlock();
451 PROJECT* prj = &m_schematic->Prj();
452
453 xsheet->AddChild( xtitleBlock = node( wxT( "title_block" ) ) );
454
455 xtitleBlock->AddChild( node( wxT( "title" ), ExpandTextVars( tb.GetTitle(), prj ) ) );
456 xtitleBlock->AddChild( node( wxT( "company" ), ExpandTextVars( tb.GetCompany(), prj ) ) );
457 xtitleBlock->AddChild( node( wxT( "rev" ), ExpandTextVars( tb.GetRevision(), prj ) ) );
458 xtitleBlock->AddChild( node( wxT( "date" ), ExpandTextVars( tb.GetDate(), prj ) ) );
459
460 // We are going to remove the fileName directories.
461 sourceFileName = wxFileName( screen->GetFileName() );
462 xtitleBlock->AddChild( node( wxT( "source" ), sourceFileName.GetFullName() ) );
463
464 xtitleBlock->AddChild( xcomment = node( wxT( "comment" ) ) );
465 xcomment->AddAttribute( wxT( "number" ), wxT( "1" ) );
466 xcomment->AddAttribute( wxT( "value" ), ExpandTextVars( tb.GetComment( 0 ), prj ) );
467
468 xtitleBlock->AddChild( xcomment = node( wxT( "comment" ) ) );
469 xcomment->AddAttribute( wxT( "number" ), wxT( "2" ) );
470 xcomment->AddAttribute( wxT( "value" ), ExpandTextVars( tb.GetComment( 1 ), prj ) );
471
472 xtitleBlock->AddChild( xcomment = node( wxT( "comment" ) ) );
473 xcomment->AddAttribute( wxT( "number" ), wxT( "3" ) );
474 xcomment->AddAttribute( wxT( "value" ), ExpandTextVars( tb.GetComment( 2 ), prj ) );
475
476 xtitleBlock->AddChild( xcomment = node( wxT( "comment" ) ) );
477 xcomment->AddAttribute( wxT( "number" ), wxT( "4" ) );
478 xcomment->AddAttribute( wxT( "value" ), ExpandTextVars( tb.GetComment( 3 ), prj ) );
479
480 xtitleBlock->AddChild( xcomment = node( wxT( "comment" ) ) );
481 xcomment->AddAttribute( wxT( "number" ), wxT( "5" ) );
482 xcomment->AddAttribute( wxT( "value" ), ExpandTextVars( tb.GetComment( 4 ), prj ) );
483
484 xtitleBlock->AddChild( xcomment = node( wxT( "comment" ) ) );
485 xcomment->AddAttribute( wxT( "number" ), wxT( "6" ) );
486 xcomment->AddAttribute( wxT( "value" ), ExpandTextVars( tb.GetComment( 5 ), prj ) );
487
488 xtitleBlock->AddChild( xcomment = node( wxT( "comment" ) ) );
489 xcomment->AddAttribute( wxT( "number" ), wxT( "7" ) );
490 xcomment->AddAttribute( wxT( "value" ), ExpandTextVars( tb.GetComment( 6 ), prj ) );
491
492 xtitleBlock->AddChild( xcomment = node( wxT( "comment" ) ) );
493 xcomment->AddAttribute( wxT( "number" ), wxT( "8" ) );
494 xcomment->AddAttribute( wxT( "value" ), ExpandTextVars( tb.GetComment( 7 ), prj ) );
495
496 xtitleBlock->AddChild( xcomment = node( wxT( "comment" ) ) );
497 xcomment->AddAttribute( wxT( "number" ), wxT( "9" ) );
498 xcomment->AddAttribute( wxT( "value" ), ExpandTextVars( tb.GetComment( 8 ), prj ) );
499 }
500
501 return xdesign;
502}
wxString GetBuildVersion()
Get the full KiCad version string.
Container for project specific data.
Definition: project.h:63
virtual std::map< wxString, wxString > & GetTextVars() const
Definition: project.cpp:78
virtual wxString GetFileName() const =0
virtual PROJECT & Prj() const =0
const wxString & GetFileName() const
Definition: sch_screen.h:142
const TITLE_BLOCK & GetTitleBlock() const
Definition: sch_screen.h:153
Hold the information shown in the lower right corner of a plot, printout, or editing view.
Definition: title_block.h:41
const wxString & GetCompany() const
Definition: title_block.h:96
const wxString & GetRevision() const
Definition: title_block.h:86
const wxString & GetDate() const
Definition: title_block.h:76
const wxString & GetComment(int aIdx) const
Definition: title_block.h:107
const wxString & GetTitle() const
Definition: title_block.h:63
wxString ExpandTextVars(const wxString &aSource, const PROJECT *aProject)
Definition: common.cpp:57
wxString DateAndTime()

References DateAndTime(), ExpandTextVars(), GetBuildVersion(), TITLE_BLOCK::GetComment(), TITLE_BLOCK::GetCompany(), TITLE_BLOCK::GetDate(), SCH_SCREEN::GetFileName(), SCHEMATIC_IFACE::GetFileName(), TITLE_BLOCK::GetRevision(), SCHEMATIC_IFACE::GetSheets(), PROJECT::GetTextVars(), TITLE_BLOCK::GetTitle(), SCH_SCREEN::GetTitleBlock(), NETLIST_EXPORTER_BASE::m_schematic, NETLIST_EXPORTER_XML::node(), and SCHEMATIC_IFACE::Prj().

Referenced by NETLIST_EXPORTER_XML::makeRoot().

◆ makeLibParts()

XNODE * NETLIST_EXPORTER_XML::makeLibParts ( )
protectedinherited

Fill out an XML node with the unique library parts and returns it.

Returns
the library parts nodes

Definition at line 529 of file netlist_exporter_xml.cpp.

530{
531 XNODE* xlibparts = node( wxT( "libparts" ) ); // auto_ptr
532
533 LIB_PINS pinList;
534 std::vector<LIB_FIELD*> fieldList;
535
536 m_libraries.clear();
537
538 for( LIB_SYMBOL* lcomp : m_libParts )
539 {
540 wxString libNickname = lcomp->GetLibId().GetLibNickname();;
541
542 // The library nickname will be empty if the cache library is used.
543 if( !libNickname.IsEmpty() )
544 m_libraries.insert( libNickname ); // inserts symbol's library if unique
545
546 XNODE* xlibpart;
547 xlibparts->AddChild( xlibpart = node( wxT( "libpart" ) ) );
548 xlibpart->AddAttribute( wxT( "lib" ), libNickname );
549 xlibpart->AddAttribute( wxT( "part" ), lcomp->GetName() );
550
551 //----- show the important properties -------------------------
552 if( !lcomp->GetDescription().IsEmpty() )
553 xlibpart->AddChild( node( wxT( "description" ), lcomp->GetDescription() ) );
554
555 if( !lcomp->GetDatasheetField().GetText().IsEmpty() )
556 xlibpart->AddChild( node( wxT( "docs" ), lcomp->GetDatasheetField().GetText() ) );
557
558 // Write the footprint list
559 if( lcomp->GetFPFilters().GetCount() )
560 {
561 XNODE* xfootprints;
562 xlibpart->AddChild( xfootprints = node( wxT( "footprints" ) ) );
563
564 for( unsigned i = 0; i < lcomp->GetFPFilters().GetCount(); ++i )
565 xfootprints->AddChild( node( wxT( "fp" ), lcomp->GetFPFilters()[i] ) );
566 }
567
568 //----- show the fields here ----------------------------------
569 fieldList.clear();
570 lcomp->GetFields( fieldList );
571
572 XNODE* xfields;
573 xlibpart->AddChild( xfields = node( "fields" ) );
574
575 for( const LIB_FIELD* field : fieldList )
576 {
577 if( !field->GetText().IsEmpty() )
578 {
579 XNODE* xfield;
580 xfields->AddChild( xfield = node( wxT( "field" ), field->GetText() ) );
581 xfield->AddAttribute( wxT( "name" ), field->GetCanonicalName() );
582 }
583 }
584
585 //----- show the pins here ------------------------------------
586 pinList.clear();
587 lcomp->GetPins( pinList, 0, 0 );
588
589 /*
590 * We must erase redundant Pins references in pinList
591 * These redundant pins exist because some pins are found more than one time when a
592 * symbol has multiple parts per package or has 2 representations (DeMorgan conversion).
593 * For instance, a 74ls00 has DeMorgan conversion, with different pin shapes, and
594 * therefore each pin appears 2 times in the list. Common pins (VCC, GND) can also be
595 * found more than once.
596 */
597 sort( pinList.begin(), pinList.end(), sortPinsByNumber );
598 for( int ii = 0; ii < (int)pinList.size()-1; ii++ )
599 {
600 if( pinList[ii]->GetNumber() == pinList[ii+1]->GetNumber() )
601 { // 2 pins have the same number, remove the redundant pin at index i+1
602 pinList.erase(pinList.begin() + ii + 1);
603 ii--;
604 }
605 }
606
607 if( pinList.size() )
608 {
609 XNODE* pins;
610
611 xlibpart->AddChild( pins = node( wxT( "pins" ) ) );
612 for( unsigned i=0; i<pinList.size(); ++i )
613 {
614 XNODE* pin;
615
616 pins->AddChild( pin = node( wxT( "pin" ) ) );
617 pin->AddAttribute( wxT( "num" ), pinList[i]->GetShownNumber() );
618 pin->AddAttribute( wxT( "name" ), pinList[i]->GetShownName() );
619 pin->AddAttribute( wxT( "type" ), pinList[i]->GetCanonicalElectricalTypeName() );
620
621 // caution: construction work site here, drive slowly
622 }
623 }
624 }
625
626 return xlibparts;
627}
Field object used in symbol libraries.
Definition: lib_field.h:60
std::set< wxString > m_libraries
std::vector< LIB_PIN * > LIB_PINS
Helper for defining a list of pin object pointers.
Definition: lib_item.h:55
static bool sortPinsByNumber(LIB_PIN *aPin1, LIB_PIN *aPin2)

References NETLIST_EXPORTER_BASE::m_libParts, NETLIST_EXPORTER_XML::m_libraries, NETLIST_EXPORTER_XML::node(), pin, and sortPinsByNumber().

Referenced by NETLIST_EXPORTER_XML::makeRoot().

◆ makeLibraries()

XNODE * NETLIST_EXPORTER_XML::makeLibraries ( )
protectedinherited

Fill out an XML node with a list of used libraries and returns it.

Must have called makeGenericLibParts() before this function.

Returns
the library nodes

Definition at line 505 of file netlist_exporter_xml.cpp.

506{
507 XNODE* xlibs = node( wxT( "libraries" ) ); // auto_ptr
508 SYMBOL_LIB_TABLE* symbolLibTable = m_schematic->Prj().SchSymbolLibTable();
509
510 for( std::set<wxString>::iterator it = m_libraries.begin(); it!=m_libraries.end(); ++it )
511 {
512 wxString libNickname = *it;
513 XNODE* xlibrary;
514
515 if( symbolLibTable->HasLibrary( libNickname ) )
516 {
517 xlibs->AddChild( xlibrary = node( wxT( "library" ) ) );
518 xlibrary->AddAttribute( wxT( "logical" ), libNickname );
519 xlibrary->AddChild( node( wxT( "uri" ), symbolLibTable->GetFullURI( libNickname ) ) );
520 }
521
522 // @todo: add more fun stuff here
523 }
524
525 return xlibs;
526}
bool HasLibrary(const wxString &aNickname, bool aCheckEnabled=false) const
Test for the existence of aNickname in the library table.
wxString GetFullURI(const wxString &aLibNickname, bool aExpandEnvVars=true) const
Return the full URI of the library mapped to aLibNickname.

References LIB_TABLE::GetFullURI(), LIB_TABLE::HasLibrary(), NETLIST_EXPORTER_XML::m_libraries, NETLIST_EXPORTER_BASE::m_schematic, NETLIST_EXPORTER_XML::node(), and SCHEMATIC_IFACE::Prj().

Referenced by NETLIST_EXPORTER_XML::makeRoot().

◆ makeListOfNets()

XNODE * NETLIST_EXPORTER_XML::makeListOfNets ( unsigned  aCtl)
protectedinherited

Fill out an XML node with a list of nets and returns it.

Returns
the list of nets nodes

Definition at line 630 of file netlist_exporter_xml.cpp.

631{
632 XNODE* xnets = node( wxT( "nets" ) ); // auto_ptr if exceptions ever get used.
633 wxString netCodeTxt;
634 wxString netName;
635 wxString ref;
636
637 XNODE* xnet = nullptr;
638
639 /* output:
640 <net code="123" name="/cfcard.sch/WAIT#">
641 <node ref="R23" pin="1"/>
642 <node ref="U18" pin="12"/>
643 </net>
644 */
645
646 struct NET_NODE
647 {
648 NET_NODE( SCH_PIN* aPin, const SCH_SHEET_PATH& aSheet, bool aNoConnect ) :
649 m_Pin( aPin ),
650 m_Sheet( aSheet ),
651 m_NoConnect( aNoConnect )
652 {}
653
654 SCH_PIN* m_Pin;
655 SCH_SHEET_PATH m_Sheet;
656 bool m_NoConnect;
657 };
658
659 struct NET_RECORD
660 {
661 NET_RECORD( const wxString& aName ) :
662 m_Name( aName )
663 {};
664
665 wxString m_Name;
666 std::vector<NET_NODE> m_Nodes;
667 };
668
669 std::vector<NET_RECORD*> nets;
670
671 for( const auto& it : m_schematic->ConnectionGraph()->GetNetMap() )
672 {
673 wxString net_name = it.first.Name;
674 const std::vector<CONNECTION_SUBGRAPH*>& subgraphs = it.second;
675 NET_RECORD* net_record = nullptr;
676
677 if( subgraphs.empty() )
678 continue;
679
680 nets.emplace_back( new NET_RECORD( net_name ) );
681 net_record = nets.back();
682
683 for( CONNECTION_SUBGRAPH* subgraph : subgraphs )
684 {
685 bool nc = subgraph->m_no_connect && subgraph->m_no_connect->Type() == SCH_NO_CONNECT_T;
686 const SCH_SHEET_PATH& sheet = subgraph->m_sheet;
687
688 for( SCH_ITEM* item : subgraph->m_items )
689 {
690 if( item->Type() == SCH_PIN_T )
691 {
692 SCH_PIN* pin = static_cast<SCH_PIN*>( item );
693 SCH_SYMBOL* symbol = pin->GetParentSymbol();
694
695 if( !symbol
696 || ( ( aCtl & GNL_OPT_BOM ) && !symbol->GetIncludeInBom() )
697 || ( ( aCtl & GNL_OPT_KICAD ) && !symbol->GetIncludeOnBoard() ) )
698 {
699 continue;
700 }
701
702 net_record->m_Nodes.emplace_back( pin, sheet, nc );
703 }
704 }
705 }
706 }
707
708 // Netlist ordering: Net name, then ref des, then pin name
709 std::sort( nets.begin(), nets.end(),
710 []( const NET_RECORD* a, const NET_RECORD*b )
711 {
712 return StrNumCmp( a->m_Name, b->m_Name ) < 0;
713 } );
714
715 for( int i = 0; i < (int) nets.size(); ++i )
716 {
717 NET_RECORD* net_record = nets[i];
718 bool added = false;
719 XNODE* xnode;
720
721 // Netlist ordering: Net name, then ref des, then pin name
722 std::sort( net_record->m_Nodes.begin(), net_record->m_Nodes.end(),
723 []( const NET_NODE& a, const NET_NODE& b )
724 {
725 wxString refA = a.m_Pin->GetParentSymbol()->GetRef( &a.m_Sheet );
726 wxString refB = b.m_Pin->GetParentSymbol()->GetRef( &b.m_Sheet );
727
728 if( refA == refB )
729 return a.m_Pin->GetShownNumber() < b.m_Pin->GetShownNumber();
730
731 return refA < refB;
732 } );
733
734 // Some duplicates can exist, for example on multi-unit parts with duplicated pins across
735 // units. If the user connects the pins on each unit, they will appear on separate
736 // subgraphs. Remove those here:
737 alg::remove_duplicates( net_record->m_Nodes,
738 []( const NET_NODE& a, const NET_NODE& b )
739 {
740 wxString refA = a.m_Pin->GetParentSymbol()->GetRef( &a.m_Sheet );
741 wxString refB = b.m_Pin->GetParentSymbol()->GetRef( &b.m_Sheet );
742
743 return refA == refB && a.m_Pin->GetShownNumber() == b.m_Pin->GetShownNumber();
744 } );
745
746 for( const NET_NODE& netNode : net_record->m_Nodes )
747 {
748 wxString refText = netNode.m_Pin->GetParentSymbol()->GetRef( &netNode.m_Sheet );
749 wxString pinText = netNode.m_Pin->GetShownNumber();
750
751 // Skip power symbols and virtual symbols
752 if( refText[0] == wxChar( '#' ) )
753 continue;
754
755 if( !added )
756 {
757 netCodeTxt.Printf( wxT( "%d" ), i + 1 );
758
759 xnets->AddChild( xnet = node( wxT( "net" ) ) );
760 xnet->AddAttribute( wxT( "code" ), netCodeTxt );
761 xnet->AddAttribute( wxT( "name" ), net_record->m_Name );
762
763 added = true;
764 }
765
766 xnet->AddChild( xnode = node( wxT( "node" ) ) );
767 xnode->AddAttribute( wxT( "ref" ), refText );
768 xnode->AddAttribute( wxT( "pin" ), pinText );
769
770 wxString pinName = netNode.m_Pin->GetShownName();
771 wxString pinType = netNode.m_Pin->GetCanonicalElectricalTypeName();
772
773 if( !pinName.IsEmpty() )
774 xnode->AddAttribute( wxT( "pinfunction" ), pinName );
775
776 if( netNode.m_NoConnect )
777 pinType += wxT( "+no_connect" );
778
779 xnode->AddAttribute( wxT( "pintype" ), pinType );
780 }
781 }
782
783 for( NET_RECORD* record : nets )
784 delete record;
785
786 return xnets;
787}
const NET_MAP & GetNetMap() const
bool GetIncludeOnBoard() const
Definition: sch_symbol.h:694
bool GetIncludeInBom() const
Definition: sch_symbol.h:691
void remove_duplicates(_Container &__c)
Deletes all duplicate values from __c.
Definition: kicad_algo.h:182
@ GNL_OPT_KICAD
@ GNL_OPT_BOM
@ SCH_NO_CONNECT_T
Definition: typeinfo.h:134
@ SCH_PIN_T
Definition: typeinfo.h:150

References SCHEMATIC_IFACE::ConnectionGraph(), SCH_SYMBOL::GetIncludeInBom(), SCH_SYMBOL::GetIncludeOnBoard(), CONNECTION_GRAPH::GetNetMap(), GNL_OPT_BOM, GNL_OPT_KICAD, NETLIST_EXPORTER_BASE::m_schematic, NETLIST_EXPORTER_XML::node(), pin, alg::remove_duplicates(), SCH_NO_CONNECT_T, SCH_PIN_T, and EDA_ITEM::Type().

Referenced by NETLIST_EXPORTER_XML::makeRoot().

◆ makeRoot()

XNODE * NETLIST_EXPORTER_XML::makeRoot ( unsigned  aCtl = GNL_ALL)
protectedinherited

Build the entire document tree for the generic export.

This is factored out here so we can write the tree in either S-expression file format or in XML if we put the tree built here into a wxXmlDocument.

Parameters
aCtla bitset or-ed together from GNL_ENUM values
Returns
the root nodes

Definition at line 62 of file netlist_exporter_xml.cpp.

63{
64 XNODE* xroot = node( wxT( "export" ) );
65
66 xroot->AddAttribute( wxT( "version" ), wxT( "E" ) );
67
68 if( aCtl & GNL_HEADER )
69 // add the "design" header
70 xroot->AddChild( makeDesignHeader() );
71
72 if( aCtl & GNL_SYMBOLS )
73 xroot->AddChild( makeSymbols( aCtl ) );
74
75 if( aCtl & GNL_PARTS )
76 xroot->AddChild( makeLibParts() );
77
78 if( aCtl & GNL_LIBRARIES )
79 // must follow makeGenericLibParts()
80 xroot->AddChild( makeLibraries() );
81
82 if( aCtl & GNL_NETS )
83 xroot->AddChild( makeListOfNets( aCtl ) );
84
85 return xroot;
86}
XNODE * makeDesignHeader()
Fill out a project "design" header into an XML node.
XNODE * makeLibraries()
Fill out an XML node with a list of used libraries and returns it.
XNODE * makeListOfNets(unsigned aCtl)
Fill out an XML node with a list of nets and returns it.
XNODE * makeSymbols(unsigned aCtl)
XNODE * makeLibParts()
Fill out an XML node with the unique library parts and returns it.
@ GNL_PARTS
@ GNL_LIBRARIES
@ GNL_SYMBOLS
@ GNL_HEADER
@ GNL_NETS

References GNL_HEADER, GNL_LIBRARIES, GNL_NETS, GNL_PARTS, GNL_SYMBOLS, NETLIST_EXPORTER_XML::makeDesignHeader(), NETLIST_EXPORTER_XML::makeLibParts(), NETLIST_EXPORTER_XML::makeLibraries(), NETLIST_EXPORTER_XML::makeListOfNets(), NETLIST_EXPORTER_XML::makeSymbols(), and NETLIST_EXPORTER_XML::node().

Referenced by Format(), and NETLIST_EXPORTER_XML::WriteNetlist().

◆ makeSymbols()

XNODE * NETLIST_EXPORTER_XML::makeSymbols ( unsigned  aCtl)
protectedinherited
Returns
a sub-tree holding all the schematic symbols.

Definition at line 221 of file netlist_exporter_xml.cpp.

222{
223 XNODE* xcomps = node( wxT( "components" ) );
224
226 m_libParts.clear();
227
228 SCH_SHEET_LIST sheetList = m_schematic->GetSheets();
229
230 // Output is xml, so there is no reason to remove spaces from the field values.
231 // And XML element names need not be translated to various languages.
232
233 for( unsigned ii = 0; ii < sheetList.size(); ii++ )
234 {
235 SCH_SHEET_PATH sheet = sheetList[ii];
237
238 auto cmp = [sheet]( SCH_SYMBOL* a, SCH_SYMBOL* b )
239 {
240 return ( StrNumCmp( a->GetRef( &sheet, false ),
241 b->GetRef( &sheet, false ), true ) < 0 );
242 };
243
244 std::set<SCH_SYMBOL*, decltype( cmp )> ordered_symbols( cmp );
245 std::multiset<SCH_SYMBOL*, decltype( cmp )> extra_units( cmp );
246
247 for( SCH_ITEM* item : sheet.LastScreen()->Items().OfType( SCH_SYMBOL_T ) )
248 {
249 SCH_SYMBOL* symbol = static_cast<SCH_SYMBOL*>( item );
250 auto test = ordered_symbols.insert( symbol );
251
252 if( !test.second )
253 {
254 if( ( *( test.first ) )->m_Uuid > symbol->m_Uuid )
255 {
256 extra_units.insert( *( test.first ) );
257 ordered_symbols.erase( test.first );
258 ordered_symbols.insert( symbol );
259 }
260 else
261 {
262 extra_units.insert( symbol );
263 }
264 }
265 }
266
267 for( EDA_ITEM* item : ordered_symbols )
268 {
269 SCH_SYMBOL* symbol = findNextSymbol( item, &sheet );
270
271 if( !symbol
272 || ( ( aCtl & GNL_OPT_BOM ) && !symbol->GetIncludeInBom() )
273 || ( ( aCtl & GNL_OPT_KICAD ) && !symbol->GetIncludeOnBoard() ) )
274 {
275 continue;
276 }
277
278 // Output the symbol's elements in order of expected access frequency. This may
279 // not always look best, but it will allow faster execution under XSL processing
280 // systems which do sequential searching within an element.
281
282 XNODE* xcomp; // current symbol being constructed
283 xcomps->AddChild( xcomp = node( wxT( "comp" ) ) );
284
285 xcomp->AddAttribute( wxT( "ref" ), symbol->GetRef( &sheet ) );
286 addSymbolFields( xcomp, symbol, &sheetList[ ii ] );
287
288 XNODE* xlibsource;
289 xcomp->AddChild( xlibsource = node( wxT( "libsource" ) ) );
290
291 // "logical" library name, which is in anticipation of a better search algorithm
292 // for parts based on "logical_lib.part" and where logical_lib is merely the library
293 // name minus path and extension.
294 wxString libName;
295 wxString partName;
296
297 if( symbol->UseLibIdLookup() )
298 {
299 libName = symbol->GetLibId().GetLibNickname();
300 partName = symbol->GetLibId().GetLibItemName();
301 }
302 else
303 {
304 partName = symbol->GetSchSymbolLibraryName();
305 }
306
307 xlibsource->AddAttribute( wxT( "lib" ), libName );
308
309 // We only want the symbol name, not the full LIB_ID.
310 xlibsource->AddAttribute( wxT( "part" ), partName );
311
312 xlibsource->AddAttribute( wxT( "description" ), symbol->GetDescription() );
313
314 XNODE* xproperty;
315
316 std::vector<SCH_FIELD>& fields = symbol->GetFields();
317
318 for( size_t jj = MANDATORY_FIELDS; jj < fields.size(); ++jj )
319 {
320 xcomp->AddChild( xproperty = node( wxT( "property" ) ) );
321 xproperty->AddAttribute( wxT( "name" ), fields[jj].GetCanonicalName() );
322
324 xproperty->AddAttribute( wxT( "value" ), fields[jj].GetShownText() );
325 else
326 xproperty->AddAttribute( wxT( "value" ), fields[jj].GetText() );
327 }
328
329 for( const SCH_FIELD& sheetField : sheet.Last()->GetFields() )
330 {
331 xcomp->AddChild( xproperty = node( wxT( "property" ) ) );
332 xproperty->AddAttribute( wxT( "name" ), sheetField.GetCanonicalName() );
333
335 xproperty->AddAttribute( wxT( "value" ), sheetField.GetShownText() );
336 else
337 xproperty->AddAttribute( wxT( "value" ), sheetField.GetText() );
338 }
339
340 if( !symbol->GetIncludeInBom() )
341 {
342 xcomp->AddChild( xproperty = node( wxT( "property" ) ) );
343 xproperty->AddAttribute( wxT( "name" ), wxT( "exclude_from_bom" ) );
344 }
345
346 if( !symbol->GetIncludeOnBoard() )
347 {
348 xcomp->AddChild( xproperty = node( wxT( "property" ) ) );
349 xproperty->AddAttribute( wxT( "name" ), wxT( "exclude_from_board" ) );
350 }
351
352 if( const std::unique_ptr<LIB_SYMBOL>& part = symbol->GetLibSymbolRef() )
353 {
354 if( part->GetDescription().size() )
355 {
356 xcomp->AddChild( xproperty = node( wxT( "property" ) ) );
357 xproperty->AddAttribute( wxT( "name" ), wxT( "ki_description" ) );
358 xproperty->AddAttribute( wxT( "value" ), part->GetDescription() );
359 }
360
361 if( part->GetKeyWords().size() )
362 {
363 xcomp->AddChild( xproperty = node( wxT( "property" ) ) );
364 xproperty->AddAttribute( wxT( "name" ), wxT( "ki_keywords" ) );
365 xproperty->AddAttribute( wxT( "value" ), part->GetKeyWords() );
366 }
367 }
368
369 XNODE* xsheetpath;
370 xcomp->AddChild( xsheetpath = node( wxT( "sheetpath" ) ) );
371
372 xsheetpath->AddAttribute( wxT( "names" ), sheet.PathHumanReadable() );
373 xsheetpath->AddAttribute( wxT( "tstamps" ), sheet.PathAsString() );
374
375 XNODE* xunits; // Node for extra units
376 xcomp->AddChild( xunits = node( wxT( "tstamps" ) ) );
377
378 auto range = extra_units.equal_range( symbol );
379 wxString uuid;
380
381 // Output a series of children with all UUIDs associated with the REFDES
382 for( auto it = range.first; it != range.second; ++it )
383 {
384 uuid = ( *it )->m_Uuid.AsString();
385
386 // Add a space between UUIDs, if not in KICAD mode (i.e.
387 // using wxXmlDocument::Save()). KICAD MODE has its own XNODE::Format function.
388 if( !( aCtl & GNL_OPT_KICAD ) ) // i.e. for .xml format
389 uuid += ' ';
390
391 xunits->AddChild( new XNODE( wxXML_TEXT_NODE, wxEmptyString, uuid ) );
392 }
393
394 // Output the primary UUID
395 uuid = symbol->m_Uuid.AsString();
396 xunits->AddChild( new XNODE( wxXML_TEXT_NODE, wxEmptyString, uuid ) );
397 }
398 }
399
400 return xcomps;
401}
A base class for most all the KiCad significant classes used in schematics and boards.
Definition: eda_item.h:100
const KIID m_Uuid
Definition: eda_item.h:494
EE_TYPE OfType(KICAD_T aType) const
Definition: sch_rtree.h:235
wxString AsString() const
Definition: kiid.cpp:249
const UTF8 & GetLibItemName() const
Definition: lib_id.h:104
const UTF8 & GetLibNickname() const
Return the logical library name portion of a LIB_ID.
Definition: lib_id.h:90
SCH_SYMBOL * findNextSymbol(EDA_ITEM *aItem, SCH_SHEET_PATH *aSheetPath)
Check if the given symbol should be processed for netlisting.
void addSymbolFields(XNODE *aNode, SCH_SYMBOL *aSymbol, SCH_SHEET_PATH *aSheet)
Holder for multi-unit symbol fields.
virtual void SetCurrentSheet(const SCH_SHEET_PATH &aPath)=0
EE_RTREE & Items()
Gets the full RTree, usually for iterating.
Definition: sch_screen.h:107
wxString PathHumanReadable(bool aUseShortRootName=true) const
Return the sheet path in a human readable form made from the sheet names.
wxString PathAsString() const
Return the path of time stamps which do not changes even when editing sheet parameters.
SCH_SHEET * Last() const
Return a pointer to the last SCH_SHEET of the list.
std::vector< SCH_FIELD > & GetFields()
Definition: sch_sheet.h:90
bool UseLibIdLookup() const
Definition: sch_symbol.h:172
wxString GetDescription() const
Return information about the aliased parts.
Definition: sch_symbol.cpp:303
const LIB_ID & GetLibId() const
Definition: sch_symbol.h:157
void Clear()
Erase the record.
int StrNumCmp(const wxString &aString1, const wxString &aString2, bool aIgnoreCase)
Compare two strings with alphanumerical content.

References NETLIST_EXPORTER_XML::addSymbolFields(), KIID::AsString(), UNIQUE_STRINGS::Clear(), NETLIST_EXPORTER_BASE::findNextSymbol(), SCH_SYMBOL::GetDescription(), SCH_SHEET::GetFields(), SCH_SYMBOL::GetFields(), SCH_SYMBOL::GetIncludeInBom(), SCH_SYMBOL::GetIncludeOnBoard(), SCH_SYMBOL::GetLibId(), LIB_ID::GetLibItemName(), LIB_ID::GetLibNickname(), SCH_SYMBOL::GetLibSymbolRef(), SCH_SYMBOL::GetRef(), SCH_SYMBOL::GetSchSymbolLibraryName(), SCHEMATIC_IFACE::GetSheets(), GNL_OPT_BOM, GNL_OPT_KICAD, SCH_SCREEN::Items(), SCH_SHEET_PATH::Last(), SCH_SHEET_PATH::LastScreen(), NETLIST_EXPORTER_BASE::m_libParts, NETLIST_EXPORTER_BASE::m_referencesAlreadyFound, NETLIST_EXPORTER_XML::m_resolveTextVars, NETLIST_EXPORTER_BASE::m_schematic, EDA_ITEM::m_Uuid, MANDATORY_FIELDS, NETLIST_EXPORTER_XML::node(), EE_RTREE::OfType(), SCH_SHEET_PATH::PathAsString(), SCH_SHEET_PATH::PathHumanReadable(), SCH_SYMBOL_T, SCHEMATIC_IFACE::SetCurrentSheet(), StrNumCmp(), and SCH_SYMBOL::UseLibIdLookup().

Referenced by NETLIST_EXPORTER_XML::makeRoot().

◆ node()

XNODE * NETLIST_EXPORTER_XML::node ( const wxString &  aName,
const wxString &  aTextualContent = wxEmptyString 
)
protectedinherited

A convenience function that creates a new XNODE with an optional textual child.

It also provides some insulation from a possible change in XML library.

Parameters
aNameis the name to associate with a new node of type wxXML_ELEMENT_NODE.
aTextualContentis optional, and if given is the text to include in a child of the returned node, and has type wxXML_TEXT_NODE.

Definition at line 790 of file netlist_exporter_xml.cpp.

792{
793 XNODE* n = new XNODE( wxXML_ELEMENT_NODE, aName );
794
795 if( aTextualContent.Len() > 0 ) // excludes wxEmptyString, the parameter's default value
796 n->AddChild( new XNODE( wxXML_TEXT_NODE, wxEmptyString, aTextualContent ) );
797
798 return n;
799}

Referenced by NETLIST_EXPORTER_XML::addSymbolFields(), NETLIST_EXPORTER_XML::makeDesignHeader(), NETLIST_EXPORTER_XML::makeLibParts(), NETLIST_EXPORTER_XML::makeLibraries(), NETLIST_EXPORTER_XML::makeListOfNets(), NETLIST_EXPORTER_XML::makeRoot(), and NETLIST_EXPORTER_XML::makeSymbols().

◆ WriteNetlist()

bool NETLIST_EXPORTER_KICAD::WriteNetlist ( const wxString &  aOutFileName,
unsigned  aNetlistOptions 
)
overridevirtual

Write netlist to aOutFileName.

Generate the KiCad netlist format supported by Pcbnew. It is basically the XML netlist just formatted slightly different.

Reimplemented from NETLIST_EXPORTER_BASE.

Definition at line 35 of file netlist_exporter_kicad.cpp.

36{
37 try
38 {
39 FILE_OUTPUTFORMATTER formatter( aOutFileName );
40 Format( &formatter, GNL_ALL | GNL_OPT_KICAD );
41 }
42
43 catch( const IO_ERROR& ioe )
44 {
45 DisplayError( nullptr, ioe.What() );
46 return false;
47 }
48
49 return true;
50}
Used for text file output.
Definition: richio.h:457
Hold an error message and may be used when throwing exceptions containing meaningful error messages.
Definition: ki_exception.h:76
virtual const wxString What() const
A composite of Problem() and Where()
Definition: exceptions.cpp:30
void Format(OUTPUTFORMATTER *aOutputFormatter, int aCtl)
Output this s-expression netlist into aOutputFormatter.
void DisplayError(wxWindow *aParent, const wxString &aText, int aDisplayTime)
Display an error or warning message box with aMessage.
Definition: confirm.cpp:280
#define GNL_ALL

References DisplayError(), Format(), GNL_ALL, GNL_OPT_KICAD, and IO_ERROR::What().

Member Data Documentation

◆ m_libParts

std::set<LIB_SYMBOL*, LIB_SYMBOL_LESS_THAN> NETLIST_EXPORTER_BASE::m_libParts
protectedinherited

◆ m_libraries

std::set<wxString> NETLIST_EXPORTER_XML::m_libraries
privateinherited

◆ m_referencesAlreadyFound

UNIQUE_STRINGS NETLIST_EXPORTER_BASE::m_referencesAlreadyFound
protectedinherited

Used for "multiple symbols per package" symbols to avoid processing a lib symbol more than once.

Definition at line 206 of file netlist_exporter_base.h.

Referenced by NETLIST_EXPORTER_BASE::findNextSymbol(), NETLIST_EXPORTER_XML::makeSymbols(), NETLIST_EXPORTER_CADSTAR::WriteNetlist(), and NETLIST_EXPORTER_ORCADPCB2::WriteNetlist().

◆ m_resolveTextVars

bool NETLIST_EXPORTER_XML::m_resolveTextVars
protectedinherited

◆ m_savedCurrentSheet

SCH_SHEET_PATH NETLIST_EXPORTER_BASE::m_savedCurrentSheet
protectedinherited

The schematic's CurrentSheet when we entered. Restore on exiting.

Definition at line 215 of file netlist_exporter_base.h.

Referenced by NETLIST_EXPORTER_BASE::NETLIST_EXPORTER_BASE(), and NETLIST_EXPORTER_BASE::~NETLIST_EXPORTER_BASE().

◆ m_schematic

◆ m_sortedSymbolPinList

std::vector<PIN_INFO> NETLIST_EXPORTER_BASE::m_sortedSymbolPinList
protectedinherited

Used to temporarily store and filter the list of pins of a schematic symbol when generating schematic symbol data in netlist (comp section).

No ownership of members. TODO(snh): Descope this object

Definition at line 202 of file netlist_exporter_base.h.

Referenced by NETLIST_EXPORTER_BASE::CreatePinList(), NETLIST_EXPORTER_BASE::eraseDuplicatePins(), NETLIST_EXPORTER_BASE::findAllUnitsOfSymbol(), NETLIST_EXPORTER_SPICE::readModel(), NETLIST_EXPORTER_SPICE::readNameField(), NETLIST_EXPORTER_SPICE::readPins(), and NETLIST_EXPORTER_ORCADPCB2::WriteNetlist().


The documentation for this class was generated from the following files: