KiCad PCB EDA Suite
NETLIST_EXPORTER_XML Class Reference

Generate a generic XML based netlist file. More...

#include <netlist_exporter_xml.h>

Inheritance diagram for NETLIST_EXPORTER_XML:
NETLIST_EXPORTER_BASE NETLIST_EXPORTER_KICAD

Public Member Functions

 NETLIST_EXPORTER_XML (SCHEMATIC *aSchematic)
 
bool WriteNetlist (const wxString &aOutFileName, unsigned aNetlistOptions, REPORTER &aReporter) override
 Write generic netlist to aOutFileName. 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, 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...
 

Private Attributes

std::set< wxString > m_libraries
 

Detailed Description

Generate a generic XML based netlist file.

This allows using XSLT or other methods to transform the XML to other netlist formats outside of the C++ codebase.

Definition at line 62 of file netlist_exporter_xml.h.

Constructor & Destructor Documentation

◆ NETLIST_EXPORTER_XML()

NETLIST_EXPORTER_XML::NETLIST_EXPORTER_XML ( SCHEMATIC aSchematic)
inline

Definition at line 65 of file netlist_exporter_xml.h.

65 :
66 NETLIST_EXPORTER_BASE( aSchematic ),
67 m_resolveTextVars( true )
68 {}
NETLIST_EXPORTER_BASE(SCHEMATIC_IFACE *aSchematic)

Member Function Documentation

◆ addSymbolFields()

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

Holder for multi-unit symbol fields.

Definition at line 93 of file netlist_exporter_xml.cpp.

95{
96 wxString value;
97 wxString datasheet;
98 wxString footprint;
99 wxString candidate;
100 std::map<wxString, wxString> userFields;
101
102 if( aSymbol->GetUnitCount() > 1 )
103 {
104 // Sadly, each unit of a symbol can have its own unique fields. This
105 // block finds the unit with the lowest number having a non blank field
106 // value and records it. Therefore user is best off setting fields
107 // into only the first unit. But this scavenger algorithm will find
108 // any non blank fields in all units and use the first non-blank field
109 // for each unique field name.
110
111 wxString ref = aSymbol->GetRef( aSheet );
112
113 SCH_SHEET_LIST sheetList = m_schematic->GetSheets();
114 int minUnit = aSymbol->GetUnitSelection( aSheet );
115
116 for( unsigned i = 0; i < sheetList.size(); i++ )
117 {
118 for( SCH_ITEM* item : sheetList[i].LastScreen()->Items().OfType( SCH_SYMBOL_T ) )
119 {
120 SCH_SYMBOL* symbol2 = (SCH_SYMBOL*) item;
121
122 wxString ref2 = symbol2->GetRef( &sheetList[i] );
123
124 if( ref2.CmpNoCase( ref ) != 0 )
125 continue;
126
127 int unit = symbol2->GetUnitSelection( aSheet );
128
129 // The lowest unit number wins. User should only set fields in any one unit.
130 candidate = symbol2->GetValueFieldText( m_resolveTextVars );
131
132 if( !candidate.IsEmpty() && ( unit < minUnit || value.IsEmpty() ) )
133 value = candidate;
134
135 candidate = symbol2->GetFootprintFieldText( m_resolveTextVars );
136
137 if( !candidate.IsEmpty() && ( unit < minUnit || footprint.IsEmpty() ) )
138 footprint = candidate;
139
140 candidate = m_resolveTextVars ? symbol2->GetField( DATASHEET_FIELD )->GetShownText()
141 : symbol2->GetField( DATASHEET_FIELD )->GetText();
142
143 if( !candidate.IsEmpty() && ( unit < minUnit || datasheet.IsEmpty() ) )
144 datasheet = candidate;
145
146 for( int ii = MANDATORY_FIELDS; ii < symbol2->GetFieldCount(); ++ii )
147 {
148 const SCH_FIELD& f = symbol2->GetFields()[ ii ];
149
150 if( f.GetText().size()
151 && ( unit < minUnit || userFields.count( f.GetName() ) == 0 ) )
152 {
154 userFields[ f.GetName() ] = f.GetShownText();
155 else
156 userFields[ f.GetName() ] = f.GetText();
157 }
158 }
159
160 minUnit = std::min( unit, minUnit );
161 }
162 }
163 }
164 else
165 {
166 value = aSymbol->GetValueFieldText( m_resolveTextVars );
167 footprint = aSymbol->GetFootprintFieldText( m_resolveTextVars );
168
171 else
172 datasheet = aSymbol->GetField( DATASHEET_FIELD )->GetText();
173
174 for( int ii = MANDATORY_FIELDS; ii < aSymbol->GetFieldCount(); ++ii )
175 {
176 const SCH_FIELD& f = aSymbol->GetFields()[ ii ];
177
178 if( f.GetText().size() )
179 {
181 userFields[ f.GetName() ] = f.GetShownText();
182 else
183 userFields[ f.GetName() ] = f.GetText();
184 }
185 }
186 }
187
188 // Do not output field values blank in netlist:
189 if( value.size() )
190 aNode->AddChild( node( wxT( "value" ), UnescapeString( value ) ) );
191 else // value field always written in netlist
192 aNode->AddChild( node( wxT( "value" ), wxT( "~" ) ) );
193
194 if( footprint.size() )
195 aNode->AddChild( node( wxT( "footprint" ), UnescapeString( footprint ) ) );
196
197 if( datasheet.size() )
198 aNode->AddChild( node( wxT( "datasheet" ), UnescapeString( datasheet ) ) );
199
200 if( userFields.size() )
201 {
202 XNODE* xfields;
203 aNode->AddChild( xfields = node( wxT( "fields" ) ) );
204
205 // non MANDATORY fields are output alphabetically
206 for( const std::pair<const wxString, wxString>& f : userFields )
207 {
208 XNODE* xfield = node( wxT( "field" ), UnescapeString( f.second ) );
209 xfield->AddAttribute( wxT( "name" ), UnescapeString( f.first ) );
210 xfields->AddChild( xfield );
211 }
212 }
213}
virtual const wxString & GetText() const
Return the string associated with the text object.
Definition: eda_text.h:87
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
wxString GetShownText(int aDepth=0, bool aAllowExtraText=true) const override
Return the string actually shown after processing of the base text.
Definition: sch_field.cpp:169
wxString GetName(bool aUseDefaultName=true) const
Return the field name (not translated).
Definition: sch_field.cpp:827
Base class for any item which can be embedded within the SCHEMATIC container class,...
Definition: sch_item.h:147
A container for handling SCH_SHEET_PATH objects in a flattened hierarchy.
Schematic symbol object.
Definition: sch_symbol.h:80
int GetUnitCount() const
Return the number of units per package of the symbol.
Definition: sch_symbol.cpp:419
int GetFieldCount() const
Return the number of fields in this symbol.
Definition: sch_symbol.h:478
const wxString GetRef(const SCH_SHEET_PATH *aSheet, bool aIncludeUnit=false) const
Return the reference for the given sheet path.
Definition: sch_symbol.cpp:624
SCH_FIELD * GetField(MANDATORY_FIELD_T aFieldType)
Return a mandatory field in this symbol.
Definition: sch_symbol.cpp:788
const wxString GetFootprintFieldText(bool aResolve) const
Definition: sch_symbol.cpp:773
const wxString GetValueFieldText(bool aResolve) const
Definition: sch_symbol.cpp:758
int GetUnitSelection(const SCH_SHEET_PATH *aSheet) const
Return the instance-specific unit selection for the given sheet path.
Definition: sch_symbol.cpp:716
void GetFields(std::vector< SCH_FIELD * > &aVector, bool aVisibleOnly)
Populate a std::vector with SCH_FIELDs.
Definition: sch_symbol.cpp:824
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:156

References datasheet, DATASHEET_FIELD, SCH_SYMBOL::GetField(), SCH_SYMBOL::GetFieldCount(), SCH_SYMBOL::GetFields(), SCH_SYMBOL::GetFootprintFieldText(), SCH_FIELD::GetName(), SCH_SYMBOL::GetRef(), SCHEMATIC_IFACE::GetSheets(), SCH_FIELD::GetShownText(), EDA_TEXT::GetText(), SCH_SYMBOL::GetUnitCount(), SCH_SYMBOL::GetUnitSelection(), SCH_SYMBOL::GetValueFieldText(), m_resolveTextVars, NETLIST_EXPORTER_BASE::m_schematic, MANDATORY_FIELDS, node(), SCH_SYMBOL_T, and UnescapeString().

Referenced by 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 116 of file netlist_exporter_base.cpp.

118{
119 wxString ref( aSymbol->GetRef( aSheetPath ) );
120
121 // Power symbols and other symbols which have the reference starting with "#" are not
122 // included in netlist (pseudo or virtual symbols)
123
124 if( ref[0] == wxChar( '#' ) )
125 return;
126
127 // if( aSymbol->m_FlagControlMulti == 1 )
128 // continue; /* yes */
129 // removed because with multiple instances of one schematic (several sheets pointing to
130 // 1 screen), this will be erroneously be toggled.
131
132 if( !aSymbol->GetLibSymbolRef() )
133 return;
134
135 m_sortedSymbolPinList.clear();
136
137 // If symbol is a "multi parts per package" type
138 if( aSymbol->GetLibSymbolRef()->GetUnitCount() > 1 )
139 {
140 // Collect all pins for this reference designator by searching the entire design for
141 // other parts with the same reference designator.
142 // This is only done once, it would be too expensive otherwise.
143 findAllUnitsOfSymbol( aSymbol, aSheetPath, aKeepUnconnectedPins );
144 }
145
146 else // GetUnitCount() <= 1 means one part per package
147 {
149
150 for( const SCH_PIN* pin : aSymbol->GetPins( aSheetPath ) )
151 {
152 if( SCH_CONNECTION* conn = pin->Connection( aSheetPath ) )
153 {
154 const wxString& netName = conn->Name();
155
156 if( !aKeepUnconnectedPins ) // Skip unconnected pins if requested
157 {
158 CONNECTION_SUBGRAPH* sg = graph->FindSubgraphByName( netName, *aSheetPath );
159
160 if( !sg || sg->m_no_connect || sg->m_items.size() < 2 )
161 continue;
162 }
163
164 m_sortedSymbolPinList.emplace_back( pin->GetShownNumber(), netName );
165 }
166 }
167 }
168
169 // Sort pins in m_SortedSymbolPinList by pin number
170 std::sort( m_sortedSymbolPinList.begin(), m_sortedSymbolPinList.end(),
171 []( const PIN_INFO& lhs, const PIN_INFO& rhs )
172 {
173 return StrNumCmp( lhs.num, rhs.num, true ) < 0;
174 } );
175
176 // Remove duplicate Pins in m_SortedSymbolPinList
178
179 // record the usage of this library symbol
180 m_libParts.insert( aSymbol->GetLibSymbolRef().get() ); // rejects non-unique pointers
181}
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.
std::set< LIB_SYMBOL *, LIB_SYMBOL_LESS_THAN > m_libParts
unique library symbols used. LIB_SYMBOL items are sorted by names
void findAllUnitsOfSymbol(SCH_SYMBOL *aSchSymbol, SCH_SHEET_PATH *aSheetPath, bool aKeepUnconnectedPins)
Find all units for symbols with multiple symbols per package.
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:989
std::unique_ptr< LIB_SYMBOL > & GetLibSymbolRef()
Definition: sch_symbol.h:191

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, and pin.

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 184 of file netlist_exporter_base.cpp.

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

References NETLIST_EXPORTER_BASE::m_sortedSymbolPinList.

Referenced by NETLIST_EXPORTER_BASE::CreatePinList().

◆ findAllUnitsOfSymbol()

void NETLIST_EXPORTER_BASE::findAllUnitsOfSymbol ( SCH_SYMBOL aSchSymbol,
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 217 of file netlist_exporter_base.cpp.

220{
221 wxString ref = aSchSymbol->GetRef( aSheetPath );
222 wxString ref2;
223
224 SCH_SHEET_LIST sheetList = m_schematic->GetSheets();
226
227 for( unsigned i = 0; i < sheetList.size(); i++ )
228 {
229 SCH_SHEET_PATH& sheet = sheetList[i];
230
231 for( SCH_ITEM* item : sheetList[i].LastScreen()->Items().OfType( SCH_SYMBOL_T ) )
232 {
233 SCH_SYMBOL* comp2 = static_cast<SCH_SYMBOL*>( item );
234
235 ref2 = comp2->GetRef( &sheet );
236
237 if( ref2.CmpNoCase( ref ) != 0 )
238 continue;
239
240 for( const SCH_PIN* pin : comp2->GetPins( &sheet ) )
241 {
242 if( SCH_CONNECTION* conn = pin->Connection( &sheet ) )
243 {
244 const wxString& netName = conn->Name();
245
246 if( !aKeepUnconnectedPins ) // Skip unconnected pins if requested
247 {
248 CONNECTION_SUBGRAPH* sg = graph->FindSubgraphByName( netName, sheet );
249
250 if( !sg || sg->m_no_connect || sg->m_items.size() < 2 )
251 continue;
252 }
253
254 m_sortedSymbolPinList.emplace_back( pin->GetShownNumber(), netName );
255 }
256 }
257 }
258 }
259}
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:97
Define a library symbol object.
Definition: lib_symbol.h:98
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:454
SCH_SCREEN * LastScreen()
wxString GetSchSymbolLibraryName() const
Definition: sch_symbol.cpp:286
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 makeSymbols(), NETLIST_EXPORTER_SPICE::ReadSchematicAndLibraries(), NETLIST_EXPORTER_CADSTAR::WriteNetlist(), and NETLIST_EXPORTER_ORCADPCB2::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 ( )
protected

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

Returns
the design header

Definition at line 406 of file netlist_exporter_xml.cpp.

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

Referenced by makeRoot().

◆ makeLibParts()

XNODE * NETLIST_EXPORTER_XML::makeLibParts ( )
protected

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

Returns
the library parts nodes

Definition at line 531 of file netlist_exporter_xml.cpp.

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

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

Referenced by makeRoot().

◆ makeLibraries()

XNODE * NETLIST_EXPORTER_XML::makeLibraries ( )
protected

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 507 of file netlist_exporter_xml.cpp.

508{
509 XNODE* xlibs = node( wxT( "libraries" ) ); // auto_ptr
510 SYMBOL_LIB_TABLE* symbolLibTable = m_schematic->Prj().SchSymbolLibTable();
511
512 for( std::set<wxString>::iterator it = m_libraries.begin(); it!=m_libraries.end(); ++it )
513 {
514 wxString libNickname = *it;
515 XNODE* xlibrary;
516
517 if( symbolLibTable->HasLibrary( libNickname ) )
518 {
519 xlibs->AddChild( xlibrary = node( wxT( "library" ) ) );
520 xlibrary->AddAttribute( wxT( "logical" ), libNickname );
521 xlibrary->AddChild( node( wxT( "uri" ), symbolLibTable->GetFullURI( libNickname ) ) );
522 }
523
524 // @todo: add more fun stuff here
525 }
526
527 return xlibs;
528}
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(), m_libraries, NETLIST_EXPORTER_BASE::m_schematic, node(), and SCHEMATIC_IFACE::Prj().

Referenced by makeRoot().

◆ makeListOfNets()

XNODE * NETLIST_EXPORTER_XML::makeListOfNets ( unsigned  aCtl)
protected

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

Returns
the list of nets nodes

Definition at line 632 of file netlist_exporter_xml.cpp.

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

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

Referenced by makeRoot().

◆ makeRoot()

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

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 63 of file netlist_exporter_xml.cpp.

64{
65 XNODE* xroot = node( wxT( "export" ) );
66
67 xroot->AddAttribute( wxT( "version" ), wxT( "E" ) );
68
69 if( aCtl & GNL_HEADER )
70 // add the "design" header
71 xroot->AddChild( makeDesignHeader() );
72
73 if( aCtl & GNL_SYMBOLS )
74 xroot->AddChild( makeSymbols( aCtl ) );
75
76 if( aCtl & GNL_PARTS )
77 xroot->AddChild( makeLibParts() );
78
79 if( aCtl & GNL_LIBRARIES )
80 // must follow makeGenericLibParts()
81 xroot->AddChild( makeLibraries() );
82
83 if( aCtl & GNL_NETS )
84 xroot->AddChild( makeListOfNets( aCtl ) );
85
86 return xroot;
87}
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, makeDesignHeader(), makeLibParts(), makeLibraries(), makeListOfNets(), makeSymbols(), and node().

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

◆ makeSymbols()

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

Definition at line 216 of file netlist_exporter_xml.cpp.

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

References addSymbolFields(), KIID::AsString(), UNIQUE_STRINGS::Clear(), NETLIST_EXPORTER_BASE::findNextSymbol(), SCH_SYMBOL::GetDescription(), SCH_SYMBOL::GetDNP(), 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(), EDA_UNIT_UTILS::GetText(), 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, m_resolveTextVars, NETLIST_EXPORTER_BASE::m_schematic, EDA_ITEM::m_Uuid, MANDATORY_FIELDS, node(), EE_RTREE::OfType(), SCH_SHEET_PATH::PathAsString(), SCH_SHEET_PATH::PathHumanReadable(), SCH_SYMBOL_T, StrNumCmp(), and SCH_SYMBOL::UseLibIdLookup().

Referenced by makeRoot().

◆ node()

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

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 791 of file netlist_exporter_xml.cpp.

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

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

◆ WriteNetlist()

bool NETLIST_EXPORTER_XML::WriteNetlist ( const wxString &  aOutFileName,
unsigned  aNetlistOptions,
REPORTER aReporter 
)
overridevirtual

Write generic netlist to aOutFileName.

Parameters
aOutFileNameis the file name to write.
aNetlistOptionsare the options used to control the netlist output.
Returns
true if the netlist was written successfully.

Reimplemented from NETLIST_EXPORTER_BASE.

Definition at line 44 of file netlist_exporter_xml.cpp.

46{
47 // output the XML format netlist.
48
49 // declare the stream ourselves to use the buffered FILE api
50 // instead of letting wx use the syscall variant
51 wxFFileOutputStream stream( aOutFileName );
52
53 if( !stream.IsOk() )
54 return false;
55
56 wxXmlDocument xdoc;
57 xdoc.SetRoot( makeRoot( GNL_ALL | aNetlistOptions ) );
58
59 return xdoc.Save( stream, 2 /* indent bug, today was ignored by wxXml lib */ );
60}
XNODE * makeRoot(unsigned aCtl=GNL_ALL)
Build the entire document tree for the generic export.
#define GNL_ALL

References GNL_ALL, and makeRoot().

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
private

Definition at line 138 of file netlist_exporter_xml.h.

Referenced by makeLibParts(), and makeLibraries().

◆ 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 203 of file netlist_exporter_base.h.

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

◆ m_resolveTextVars

bool NETLIST_EXPORTER_XML::m_resolveTextVars
protected

Definition at line 135 of file netlist_exporter_xml.h.

Referenced by addSymbolFields(), and makeSymbols().

◆ 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 199 of file netlist_exporter_base.h.

Referenced by NETLIST_EXPORTER_BASE::CreatePinList(), NETLIST_EXPORTER_BASE::eraseDuplicatePins(), NETLIST_EXPORTER_BASE::findAllUnitsOfSymbol(), NETLIST_EXPORTER_SPICE::readPinNetNames(), NETLIST_EXPORTER_SPICE::readPinNumbers(), and NETLIST_EXPORTER_ORCADPCB2::WriteNetlist().


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