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

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  {
43  m_resolveTextVars = false;
44  }
NETLIST_EXPORTER_XML(SCHEMATIC *aSchematic)

References NETLIST_EXPORTER_XML::m_resolveTextVars.

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( auto 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  {
145  if( m_resolveTextVars )
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  {
158  if( m_resolveTextVars )
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 
174  if( m_resolveTextVars )
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  {
185  if( m_resolveTextVars )
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( "value", UnescapeString( value ) ) );
196  else // value field always written in netlist
197  aNode->AddChild( node( "value", "~" ) );
198 
199  if( footprint.size() )
200  aNode->AddChild( node( "footprint", UnescapeString( footprint ) ) );
201 
202  if( datasheet.size() )
203  aNode->AddChild( node( "datasheet", UnescapeString( datasheet ) ) );
204 
205  if( userFields.size() )
206  {
207  XNODE* xfields;
208  aNode->AddChild( xfields = node( "fields" ) );
209 
210  // non MANDATORY fields are output alphabetically
211  for( const std::pair<const wxString, wxString>& f : userFields )
212  {
213  XNODE* xfield = node( "field", UnescapeString( f.second ) );
214  xfield->AddAttribute( "name", UnescapeString( f.first ) );
215  xfields->AddChild( xfield );
216  }
217  }
218 }
A container for handling SCH_SHEET_PATH objects in a flattened hierarchy.
Instances are attached to a symbol or sheet and provide a place for the symbol's value,...
Definition: sch_field.h:49
SCH_FIELD * GetField(MANDATORY_FIELD_T aFieldType)
Return a mandatory field in this symbol.
Definition: sch_symbol.cpp:675
int GetUnitCount() const
Return the number of units per package of the symbol.
Definition: sch_symbol.cpp:370
void GetFields(std::vector< SCH_FIELD * > &aVector, bool aVisibleOnly)
Populate a std::vector with SCH_FIELDs.
Definition: sch_symbol.cpp:711
const wxString GetRef(const SCH_SHEET_PATH *aSheet, bool aIncludeUnit=false) const
Return the reference for the given sheet path.
Definition: sch_symbol.cpp:441
wxString GetShownText(int aDepth=0) const override
Return the string actually shown after processing of the base text.
Definition: sch_field.cpp:105
bool IsVoid() const
Definition: sch_field.cpp:325
name of datasheet
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.
int GetFieldCount() const
Return the number of fields in this symbol.
Definition: sch_symbol.h:421
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:573
wxString UnescapeString(const wxString &aSource)
Hold an XML or S-expression element.
Definition: xnode.h:43
The first 4 are mandatory, and must be instantiated in SCH_COMPONENT and LIB_PART constructors.
Schematic symbol object.
Definition: sch_symbol.h:78
wxString GetName(bool aUseDefaultName=true) const
Return the field name.
Definition: sch_field.cpp:544
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:624
int GetUnit() const
Definition: sch_symbol.h:195
virtual SCH_SHEET_LIST GetSheets() const =0
virtual const wxString & GetText() const
Return the string associated with the text object.
Definition: eda_text.h:133

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 }
CONNECTION_SUBGRAPH * FindSubgraphByName(const wxString &aNetName, const SCH_SHEET_PATH &aPath)
Returns the subgraph for a given net name on a given sheet.
std::vector< PIN_INFO > m_sortedSymbolPinList
Used to temporarily store and filter the list of pins of a schematic symbol when generating schematic...
Calculates the connectivity of a schematic and generates netlists.
void eraseDuplicatePins()
Erase duplicate pins from m_sortedSymbolPinList (i.e.
virtual CONNECTION_GRAPH * ConnectionGraph() const =0
const wxString GetRef(const SCH_SHEET_PATH *aSheet, bool aIncludeUnit=false) const
Return the reference for the given sheet path.
Definition: sch_symbol.cpp:441
static bool sortPinsByNum(PIN_INFO &aPin1, PIN_INFO &aPin2)
Comparison routine for sorting by pin numbers.
A subgraph is a set of items that are electrically connected on a single sheet.
std::unique_ptr< LIB_SYMBOL > & GetLibSymbolRef()
Definition: sch_symbol.h:164
SCHEMATIC_IFACE * m_schematic
The schematic we're generating a netlist for.
std::vector< SCH_ITEM * > m_items
Each graphical item can have a SCH_CONNECTION describing its logical connection (to a bus or net).
void findAllUnitsOfSymbol(SCH_SYMBOL *aSchSymbol, LIB_SYMBOL *aLibSymbol, SCH_SHEET_PATH *aSheetPath, bool aKeepUnconnectedPins)
Find all units for symbols with multiple symbols per package.
SCH_ITEM * m_no_connect
No-connect item in graph, if any.
std::set< LIB_SYMBOL *, LIB_SYMBOL_LESS_THAN > m_libParts
unique library symbols used. LIB_SYMBOL items are sorted by names
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:866

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_PSPICE::ProcessNetlist(), 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 }
std::vector< PIN_INFO > m_sortedSymbolPinList
Used to temporarily store and filter the list of pins of a schematic symbol when generating schematic...

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 }
CONNECTION_SUBGRAPH * FindSubgraphByName(const wxString &aNetName, const SCH_SHEET_PATH &aPath)
Returns the subgraph for a given net name on a given sheet.
A container for handling SCH_SHEET_PATH objects in a flattened hierarchy.
std::vector< PIN_INFO > m_sortedSymbolPinList
Used to temporarily store and filter the list of pins of a schematic symbol when generating schematic...
Calculates the connectivity of a schematic and generates netlists.
virtual CONNECTION_GRAPH * ConnectionGraph() const =0
const wxString GetRef(const SCH_SHEET_PATH *aSheet, bool aIncludeUnit=false) const
Return the reference for the given sheet path.
Definition: sch_symbol.cpp:441
A subgraph is a set of items that are electrically connected on a single sheet.
SCHEMATIC_IFACE * m_schematic
The schematic we're generating a netlist for.
std::vector< SCH_ITEM * > m_items
Handle access to a stack of flattened SCH_SHEET objects by way of a path for creating a flattened sch...
Schematic symbol object.
Definition: sch_symbol.h:78
Each graphical item can have a SCH_CONNECTION describing its logical connection (to a bus or net).
SCH_ITEM * m_no_connect
No-connect item in graph, if any.
virtual SCH_SHEET_LIST GetSheets() const =0
Base class for any item which can be embedded within the SCHEMATIC container class,...
Definition: sch_item.h:193
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:866

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
105  if( m_referencesAlreadyFound.Lookup( ref ) )
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 }
bool Lookup(const wxString &aString)
const wxString GetRef(const SCH_SHEET_PATH *aSheet, bool aIncludeUnit=false) const
Return the reference for the given sheet path.
Definition: sch_symbol.cpp:441
Define a library symbol object.
Definition: lib_symbol.h:96
UNIQUE_STRINGS m_referencesAlreadyFound
Used for "multiple symbols per package" symbols to avoid processing a lib symbol more than once.
wxString GetSchSymbolLibraryName() const
Definition: sch_symbol.cpp:248
int GetUnitCount() const override
For items with units, return the number of units.
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:424
Schematic symbol object.
Definition: sch_symbol.h:78
SCH_SCREEN * LastScreen()
std::set< LIB_SYMBOL *, LIB_SYMBOL_LESS_THAN > m_libParts
unique library symbols used. LIB_SYMBOL items are sorted by names
KICAD_T Type() const
Returns the type of object.
Definition: eda_item.h:113

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_PSPICE::ProcessNetlist(), NETLIST_EXPORTER_ORCADPCB2::WriteNetlist(), and NETLIST_EXPORTER_CADSTAR::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_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 378 of file netlist_exporter_xml.cpp.

379 {
380  SCH_SCREEN* screen;
381  XNODE* xdesign = node( "design" );
382  XNODE* xtitleBlock;
383  XNODE* xsheet;
384  XNODE* xcomment;
385  XNODE* xtextvar;
386  wxString sheetTxt;
387  wxFileName sourceFileName;
388 
389  // the root sheet is a special sheet, call it source
390  xdesign->AddChild( node( "source", m_schematic->GetFileName() ) );
391 
392  xdesign->AddChild( node( "date", DateAndTime() ) );
393 
394  // which Eeschema tool
395  xdesign->AddChild( node( "tool", wxString( "Eeschema " ) + GetBuildVersion() ) );
396 
397  const std::map<wxString, wxString>& properties = m_schematic->Prj().GetTextVars();
398 
399  for( const std::pair<const wxString, wxString>& prop : properties )
400  {
401  xdesign->AddChild( xtextvar = node( "textvar", prop.second ) );
402  xtextvar->AddAttribute( "name", prop.first );
403  }
404 
405  /*
406  * Export the sheets information
407  */
408  SCH_SHEET_LIST sheetList = m_schematic->GetSheets();
409 
410  for( unsigned i = 0; i < sheetList.size(); i++ )
411  {
412  screen = sheetList[i].LastScreen();
413 
414  xdesign->AddChild( xsheet = node( "sheet" ) );
415 
416  // get the string representation of the sheet index number.
417  // Note that sheet->GetIndex() is zero index base and we need to increment the
418  // number by one to make it human readable
419  sheetTxt.Printf( "%u", i + 1 );
420  xsheet->AddAttribute( "number", sheetTxt );
421  xsheet->AddAttribute( "name", sheetList[i].PathHumanReadable() );
422  xsheet->AddAttribute( "tstamps", sheetList[i].PathAsString() );
423 
424  TITLE_BLOCK tb = screen->GetTitleBlock();
425  PROJECT* prj = &m_schematic->Prj();
426 
427  xsheet->AddChild( xtitleBlock = node( "title_block" ) );
428 
429  xtitleBlock->AddChild( node( "title", ExpandTextVars( tb.GetTitle(), prj ) ) );
430  xtitleBlock->AddChild( node( "company", ExpandTextVars( tb.GetCompany(), prj ) ) );
431  xtitleBlock->AddChild( node( "rev", ExpandTextVars( tb.GetRevision(), prj ) ) );
432  xtitleBlock->AddChild( node( "date", ExpandTextVars( tb.GetDate(), prj ) ) );
433 
434  // We are going to remove the fileName directories.
435  sourceFileName = wxFileName( screen->GetFileName() );
436  xtitleBlock->AddChild( node( "source", sourceFileName.GetFullName() ) );
437 
438  xtitleBlock->AddChild( xcomment = node( "comment" ) );
439  xcomment->AddAttribute( "number", "1" );
440  xcomment->AddAttribute( "value", ExpandTextVars( tb.GetComment( 0 ), prj ) );
441 
442  xtitleBlock->AddChild( xcomment = node( "comment" ) );
443  xcomment->AddAttribute( "number", "2" );
444  xcomment->AddAttribute( "value", ExpandTextVars( tb.GetComment( 1 ), prj ) );
445 
446  xtitleBlock->AddChild( xcomment = node( "comment" ) );
447  xcomment->AddAttribute( "number", "3" );
448  xcomment->AddAttribute( "value", ExpandTextVars( tb.GetComment( 2 ), prj ) );
449 
450  xtitleBlock->AddChild( xcomment = node( "comment" ) );
451  xcomment->AddAttribute( "number", "4" );
452  xcomment->AddAttribute( "value", ExpandTextVars( tb.GetComment( 3 ), prj ) );
453 
454  xtitleBlock->AddChild( xcomment = node( "comment" ) );
455  xcomment->AddAttribute( "number", "5" );
456  xcomment->AddAttribute( "value", ExpandTextVars( tb.GetComment( 4 ), prj ) );
457 
458  xtitleBlock->AddChild( xcomment = node( "comment" ) );
459  xcomment->AddAttribute( "number", "6" );
460  xcomment->AddAttribute( "value", ExpandTextVars( tb.GetComment( 5 ), prj ) );
461 
462  xtitleBlock->AddChild( xcomment = node( "comment" ) );
463  xcomment->AddAttribute( "number", "7" );
464  xcomment->AddAttribute( "value", ExpandTextVars( tb.GetComment( 6 ), prj ) );
465 
466  xtitleBlock->AddChild( xcomment = node( "comment" ) );
467  xcomment->AddAttribute( "number", "8" );
468  xcomment->AddAttribute( "value", ExpandTextVars( tb.GetComment( 7 ), prj ) );
469 
470  xtitleBlock->AddChild( xcomment = node( "comment" ) );
471  xcomment->AddAttribute( "number", "9" );
472  xcomment->AddAttribute( "value", ExpandTextVars( tb.GetComment( 8 ), prj ) );
473  }
474 
475  return xdesign;
476 }
A container for handling SCH_SHEET_PATH objects in a flattened hierarchy.
virtual std::map< wxString, wxString > & GetTextVars() const
Definition: project.cpp:78
const wxString & GetFileName() const
Definition: sch_screen.h:145
virtual wxString GetFileName() const =0
Container for project specific data.
Definition: project.h:62
wxString ExpandTextVars(const wxString &aSource, const PROJECT *aProject)
Definition: common.cpp:64
const wxString & GetComment(int aIdx) const
Definition: title_block.h:107
const TITLE_BLOCK & GetTitleBlock() const
Definition: sch_screen.h:150
Hold the information shown in the lower right corner of a plot, printout, or editing view.
Definition: title_block.h:40
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 PROJECT & Prj() const =0
wxString GetBuildVersion()
Get the full KiCad version string.
const wxString & GetRevision() const
Definition: title_block.h:86
const wxString & GetCompany() const
Definition: title_block.h:96
Hold an XML or S-expression element.
Definition: xnode.h:43
const wxString & GetDate() const
Definition: title_block.h:76
const wxString & GetTitle() const
Definition: title_block.h:63
wxString DateAndTime()
virtual SCH_SHEET_LIST GetSheets() const =0

References DateAndTime(), ExpandTextVars(), GetBuildVersion(), TITLE_BLOCK::GetComment(), TITLE_BLOCK::GetCompany(), TITLE_BLOCK::GetDate(), SCHEMATIC_IFACE::GetFileName(), SCH_SCREEN::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 503 of file netlist_exporter_xml.cpp.

504 {
505  XNODE* xlibparts = node( "libparts" ); // auto_ptr
506 
507  LIB_PINS pinList;
508  std::vector<LIB_FIELD*> fieldList;
509 
510  m_libraries.clear();
511 
512  for( auto lcomp : m_libParts )
513  {
514  wxString libNickname = lcomp->GetLibId().GetLibNickname();;
515 
516  // The library nickname will be empty if the cache library is used.
517  if( !libNickname.IsEmpty() )
518  m_libraries.insert( libNickname ); // inserts symbol's library if unique
519 
520  XNODE* xlibpart;
521  xlibparts->AddChild( xlibpart = node( "libpart" ) );
522  xlibpart->AddAttribute( "lib", libNickname );
523  xlibpart->AddAttribute( "part", lcomp->GetName() );
524 
525  //----- show the important properties -------------------------
526  if( !lcomp->GetDescription().IsEmpty() )
527  xlibpart->AddChild( node( "description", lcomp->GetDescription() ) );
528 
529  if( !lcomp->GetDatasheetField().GetText().IsEmpty() )
530  xlibpart->AddChild( node( "docs", lcomp->GetDatasheetField().GetText() ) );
531 
532  // Write the footprint list
533  if( lcomp->GetFPFilters().GetCount() )
534  {
535  XNODE* xfootprints;
536  xlibpart->AddChild( xfootprints = node( "footprints" ) );
537 
538  for( unsigned i = 0; i < lcomp->GetFPFilters().GetCount(); ++i )
539  xfootprints->AddChild( node( "fp", lcomp->GetFPFilters()[i] ) );
540  }
541 
542  //----- show the fields here ----------------------------------
543  fieldList.clear();
544  lcomp->GetFields( fieldList );
545 
546  XNODE* xfields;
547  xlibpart->AddChild( xfields = node( "fields" ) );
548 
549  for( const LIB_FIELD* field : fieldList )
550  {
551  if( !field->GetText().IsEmpty() )
552  {
553  XNODE* xfield;
554  xfields->AddChild( xfield = node( "field", field->GetText() ) );
555  xfield->AddAttribute( "name", field->GetCanonicalName() );
556  }
557  }
558 
559  //----- show the pins here ------------------------------------
560  pinList.clear();
561  lcomp->GetPins( pinList, 0, 0 );
562 
563  /* we must erase redundant Pins references in pinList
564  * These redundant pins exist because some pins
565  * are found more than one time when a symbol has
566  * multiple parts per package or has 2 representations (DeMorgan conversion)
567  * For instance, a 74ls00 has DeMorgan conversion, with different pin shapes,
568  * and therefore each pin appears 2 times in the list.
569  * Common pins (VCC, GND) can also be found more than once.
570  */
571  sort( pinList.begin(), pinList.end(), sortPinsByNumber );
572  for( int ii = 0; ii < (int)pinList.size()-1; ii++ )
573  {
574  if( pinList[ii]->GetNumber() == pinList[ii+1]->GetNumber() )
575  { // 2 pins have the same number, remove the redundant pin at index i+1
576  pinList.erase(pinList.begin() + ii + 1);
577  ii--;
578  }
579  }
580 
581  if( pinList.size() )
582  {
583  XNODE* pins;
584 
585  xlibpart->AddChild( pins = node( "pins" ) );
586  for( unsigned i=0; i<pinList.size(); ++i )
587  {
588  XNODE* pin;
589 
590  pins->AddChild( pin = node( "pin" ) );
591  pin->AddAttribute( "num", pinList[i]->GetShownNumber() );
592  pin->AddAttribute( "name", pinList[i]->GetShownName() );
593  pin->AddAttribute( "type", pinList[i]->GetCanonicalElectricalTypeName() );
594 
595  // caution: construction work site here, drive slowly
596  }
597  }
598  }
599 
600  return xlibparts;
601 }
std::vector< LIB_PIN * > LIB_PINS
Helper for defining a list of pin object pointers.
Definition: lib_item.h:55
Field object used in symbol libraries.
Definition: lib_field.h:59
XNODE * node(const wxString &aName, const wxString &aTextualContent=wxEmptyString)
A convenience function that creates a new XNODE with an optional textual child.
static bool sortPinsByNumber(LIB_PIN *aPin1, LIB_PIN *aPin2)
Hold an XML or S-expression element.
Definition: xnode.h:43
std::set< wxString > m_libraries
std::set< LIB_SYMBOL *, LIB_SYMBOL_LESS_THAN > m_libParts
unique library symbols used. LIB_SYMBOL items are sorted by names

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

480 {
481  XNODE* xlibs = node( "libraries" ); // auto_ptr
482  SYMBOL_LIB_TABLE* symbolLibTable = m_schematic->Prj().SchSymbolLibTable();
483 
484  for( std::set<wxString>::iterator it = m_libraries.begin(); it!=m_libraries.end(); ++it )
485  {
486  wxString libNickname = *it;
487  XNODE* xlibrary;
488 
489  if( symbolLibTable->HasLibrary( libNickname ) )
490  {
491  xlibs->AddChild( xlibrary = node( "library" ) );
492  xlibrary->AddAttribute( "logical", libNickname );
493  xlibrary->AddChild( node( "uri", symbolLibTable->GetFullURI( libNickname ) ) );
494  }
495 
496  // @todo: add more fun stuff here
497  }
498 
499  return xlibs;
500 }
bool HasLibrary(const wxString &aNickname, bool aCheckEnabled=false) const
Test for the existence of aNickname in the library table.
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 PROJECT & Prj() const =0
wxString GetFullURI(const wxString &aLibNickname, bool aExpandEnvVars=true) const
Return the full URI of the library mapped to aLibNickname.
Hold an XML or S-expression element.
Definition: xnode.h:43
std::set< wxString > m_libraries

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

605 {
606  XNODE* xnets = node( "nets" ); // auto_ptr if exceptions ever get used.
607  wxString netCodeTxt;
608  wxString netName;
609  wxString ref;
610 
611  XNODE* xnet = nullptr;
612 
613  /* output:
614  <net code="123" name="/cfcard.sch/WAIT#">
615  <node ref="R23" pin="1"/>
616  <node ref="U18" pin="12"/>
617  </net>
618  */
619 
620  struct NET_NODE
621  {
622  NET_NODE( SCH_PIN* aPin, const SCH_SHEET_PATH& aSheet, bool aNoConnect ) :
623  m_Pin( aPin ),
624  m_Sheet( aSheet ),
625  m_NoConnect( aNoConnect )
626  {}
627 
628  SCH_PIN* m_Pin;
629  SCH_SHEET_PATH m_Sheet;
630  bool m_NoConnect;
631  };
632 
633  struct NET_RECORD
634  {
635  NET_RECORD( const wxString& aName ) :
636  m_Name( aName )
637  {};
638 
639  wxString m_Name;
640  std::vector<NET_NODE> m_Nodes;
641  };
642 
643  std::vector<NET_RECORD*> nets;
644 
645  for( const auto& it : m_schematic->ConnectionGraph()->GetNetMap() )
646  {
647  wxString net_name = it.first.first;
648  auto subgraphs = it.second;
649  NET_RECORD* net_record;
650 
651  if( subgraphs.empty() )
652  continue;
653 
654  nets.emplace_back( new NET_RECORD( net_name ) );
655  net_record = nets.back();
656 
657  for( CONNECTION_SUBGRAPH* subgraph : subgraphs )
658  {
659  bool nc = subgraph->m_no_connect && subgraph->m_no_connect->Type() == SCH_NO_CONNECT_T;
660  const SCH_SHEET_PATH& sheet = subgraph->m_sheet;
661 
662  for( SCH_ITEM* item : subgraph->m_items )
663  {
664  if( item->Type() == SCH_PIN_T )
665  {
666  SCH_PIN* pin = static_cast<SCH_PIN*>( item );
667  SCH_SYMBOL* symbol = pin->GetParentSymbol();
668 
669  if( !symbol
670  || ( ( aCtl & GNL_OPT_BOM ) && !symbol->GetIncludeInBom() )
671  || ( ( aCtl & GNL_OPT_KICAD ) && !symbol->GetIncludeOnBoard() ) )
672  {
673  continue;
674  }
675 
676  net_record->m_Nodes.emplace_back( pin, sheet, nc );
677  }
678  }
679  }
680  }
681 
682  // Netlist ordering: Net name, then ref des, then pin name
683  std::sort( nets.begin(), nets.end(),
684  []( const NET_RECORD* a, const NET_RECORD*b )
685  {
686  return StrNumCmp( a->m_Name, b->m_Name ) < 0;
687  } );
688 
689  for( int i = 0; i < (int) nets.size(); ++i )
690  {
691  NET_RECORD* net_record = nets[i];
692  bool added = false;
693  XNODE* xnode;
694 
695  // Netlist ordering: Net name, then ref des, then pin name
696  std::sort( net_record->m_Nodes.begin(), net_record->m_Nodes.end(),
697  []( const NET_NODE& a, const NET_NODE& b )
698  {
699  wxString refA = a.m_Pin->GetParentSymbol()->GetRef( &a.m_Sheet );
700  wxString refB = b.m_Pin->GetParentSymbol()->GetRef( &b.m_Sheet );
701 
702  if( refA == refB )
703  return a.m_Pin->GetShownNumber() < b.m_Pin->GetShownNumber();
704 
705  return refA < refB;
706  } );
707 
708  // Some duplicates can exist, for example on multi-unit parts with duplicated
709  // pins across units. If the user connects the pins on each unit, they will
710  // appear on separate subgraphs. Remove those here:
711  net_record->m_Nodes.erase(
712  std::unique( net_record->m_Nodes.begin(), net_record->m_Nodes.end(),
713  []( const NET_NODE& a, const NET_NODE& b )
714  {
715  wxString refA = a.m_Pin->GetParentSymbol()->GetRef( &a.m_Sheet );
716  wxString refB = b.m_Pin->GetParentSymbol()->GetRef( &b.m_Sheet );
717 
718  return refA == refB
719  && a.m_Pin->GetShownNumber() == b.m_Pin->GetShownNumber();
720  } ),
721  net_record->m_Nodes.end() );
722 
723  for( const NET_NODE& netNode : net_record->m_Nodes )
724  {
725  wxString refText = netNode.m_Pin->GetParentSymbol()->GetRef( &netNode.m_Sheet );
726  wxString pinText = netNode.m_Pin->GetShownNumber();
727 
728  // Skip power symbols and virtual symbols
729  if( refText[0] == wxChar( '#' ) )
730  continue;
731 
732  if( !added )
733  {
734  netCodeTxt.Printf( "%d", i + 1 );
735 
736  xnets->AddChild( xnet = node( "net" ) );
737  xnet->AddAttribute( "code", netCodeTxt );
738  xnet->AddAttribute( "name", net_record->m_Name );
739 
740  added = true;
741  }
742 
743  xnet->AddChild( xnode = node( "node" ) );
744  xnode->AddAttribute( "ref", refText );
745  xnode->AddAttribute( "pin", pinText );
746 
747  wxString pinName = netNode.m_Pin->GetShownName();
748  wxString pinType = netNode.m_Pin->GetCanonicalElectricalTypeName();
749 
750  if( !pinName.IsEmpty() )
751  xnode->AddAttribute( "pinfunction", pinName );
752 
753  if( netNode.m_NoConnect )
754  pinType += "+no_connect";
755 
756  xnode->AddAttribute( "pintype", pinType );
757  }
758  }
759 
760  for( NET_RECORD* record : nets )
761  delete record;
762 
763  return xnets;
764 }
bool GetIncludeInBom() const
Definition: sch_symbol.h:659
virtual CONNECTION_GRAPH * ConnectionGraph() const =0
A subgraph is a set of items that are electrically connected on a single sheet.
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.
const NET_MAP & GetNetMap() const
Handle access to a stack of flattened SCH_SHEET objects by way of a path for creating a flattened sch...
Hold an XML or S-expression element.
Definition: xnode.h:43
Schematic symbol object.
Definition: sch_symbol.h:78
bool GetIncludeOnBoard() const
Definition: sch_symbol.h:662
int StrNumCmp(const wxString &aString1, const wxString &aString2, bool aIgnoreCase)
Compare two strings with alphanumerical content.
Base class for any item which can be embedded within the SCHEMATIC container class,...
Definition: sch_item.h:193
KICAD_T Type() const
Returns the type of object.
Definition: eda_item.h:113

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, SCH_NO_CONNECT_T, SCH_PIN_T, StrNumCmp(), 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( "export" );
65 
66  xroot->AddAttribute( "version", "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 * makeLibParts()
Fill out an XML node with the unique library parts and returns it.
XNODE * node(const wxString &aName, const wxString &aTextualContent=wxEmptyString)
A convenience function that creates a new XNODE with an optional textual child.
XNODE * makeListOfNets(unsigned aCtl)
Fill out an XML node with a list of nets and returns it.
Hold an XML or S-expression element.
Definition: xnode.h:43
XNODE * makeSymbols(unsigned aCtl)
XNODE * makeLibraries()
Fill out an XML node with a list of used libraries and returns it.
XNODE * makeDesignHeader()
Fill out a project "design" header into an XML node.

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( "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];
236  m_schematic->SetCurrentSheet( sheet );
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( "comp" ) );
284 
285  xcomp->AddAttribute( "ref", symbol->GetRef( &sheet ) );
286  addSymbolFields( xcomp, symbol, &sheetList[ ii ] );
287 
288  XNODE* xlibsource;
289  xcomp->AddChild( xlibsource = node( "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( "lib", libName );
308 
309  // We only want the symbol name, not the full LIB_ID.
310  xlibsource->AddAttribute( "part", partName );
311 
312  xlibsource->AddAttribute( "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( "property" ) );
321  xproperty->AddAttribute( "name", fields[jj].GetCanonicalName() );
322  xproperty->AddAttribute( "value", fields[jj].GetText() );
323  }
324 
325  for( const SCH_FIELD& sheetField : sheet.Last()->GetFields() )
326  {
327  xcomp->AddChild( xproperty = node( "property" ) );
328  xproperty->AddAttribute( "name", sheetField.GetCanonicalName() );
329  xproperty->AddAttribute( "value", sheetField.GetText() );
330  }
331 
332  if( !symbol->GetIncludeInBom() )
333  {
334  xcomp->AddChild( xproperty = node( "property" ) );
335  xproperty->AddAttribute( "name", "exclude_from_bom" );
336  }
337 
338  if( !symbol->GetIncludeOnBoard() )
339  {
340  xcomp->AddChild( xproperty = node( "property" ) );
341  xproperty->AddAttribute( "name", "exclude_from_board" );
342  }
343 
344  XNODE* xsheetpath;
345  xcomp->AddChild( xsheetpath = node( "sheetpath" ) );
346 
347  xsheetpath->AddAttribute( "names", sheet.PathHumanReadable() );
348  xsheetpath->AddAttribute( "tstamps", sheet.PathAsString() );
349 
350  XNODE* xunits; // Node for extra units
351  xcomp->AddChild( xunits = node( "tstamps" ) );
352 
353  auto range = extra_units.equal_range( symbol );
354 
355  // Output a series of children with all UUIDs associated with the REFDES
356  for( auto it = range.first; it != range.second; ++it )
357  {
358  wxString uuid = ( *it )->m_Uuid.AsString();
359 
360  // Add a space between UUIDs, if not in KICAD mode (i.e.
361  // using wxXmlDocument::Save()). KICAD MODE has its own XNODE::Format function.
362  if( !( aCtl & GNL_OPT_KICAD ) ) // i.e. for .xml format
363  uuid += ' ';
364 
365  xunits->AddChild( new XNODE( wxXML_TEXT_NODE, wxEmptyString, uuid ) );
366  }
367 
368  // Output the primary UUID
369  xunits->AddChild(
370  new XNODE( wxXML_TEXT_NODE, wxEmptyString, symbol->m_Uuid.AsString() ) );
371  }
372  }
373 
374  return xcomps;
375 }
A container for handling SCH_SHEET_PATH objects in a flattened hierarchy.
EE_TYPE OfType(KICAD_T aType) const
Definition: sch_rtree.h:216
Instances are attached to a symbol or sheet and provide a place for the symbol's value,...
Definition: sch_field.h:49
const UTF8 & GetLibItemName() const
Definition: lib_id.h:104
SCH_SHEET * Last() const
Return a pointer to the last SCH_SHEET of the list.
wxString PathHumanReadable(bool aUseShortRootName=true) const
Return the sheet path in a human readable form made from the sheet names.
void GetFields(std::vector< SCH_FIELD * > &aVector, bool aVisibleOnly)
Populate a std::vector with SCH_FIELDs.
Definition: sch_symbol.cpp:711
bool GetIncludeInBom() const
Definition: sch_symbol.h:659
wxString AsString() const
Definition: kiid.cpp:218
wxString PathAsString() const
Return the path of time stamps which do not changes even when editing sheet parameters.
void Clear()
Erase the record.
const wxString GetRef(const SCH_SHEET_PATH *aSheet, bool aIncludeUnit=false) const
Return the reference for the given sheet path.
Definition: sch_symbol.cpp:441
SCH_SYMBOL * findNextSymbol(EDA_ITEM *aItem, SCH_SHEET_PATH *aSheetPath)
Check if the given symbol should be processed for netlisting.
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.
UNIQUE_STRINGS m_referencesAlreadyFound
Used for "multiple symbols per package" symbols to avoid processing a lib symbol more than once.
std::vector< SCH_FIELD > & GetFields()
Definition: sch_sheet.h:88
wxString GetSchSymbolLibraryName() const
Definition: sch_symbol.cpp:248
const UTF8 & GetLibNickname() const
Return the logical library name portion of a LIB_ID.
Definition: lib_id.h:90
Handle access to a stack of flattened SCH_SHEET objects by way of a path for creating a flattened sch...
virtual void SetCurrentSheet(const SCH_SHEET_PATH &aPath)=0
const KIID m_Uuid
Definition: eda_item.h:475
Hold an XML or S-expression element.
Definition: xnode.h:43
The first 4 are mandatory, and must be instantiated in SCH_COMPONENT and LIB_PART constructors.
void addSymbolFields(XNODE *aNode, SCH_SYMBOL *aSymbol, SCH_SHEET_PATH *aSheet)
Holder for multi-unit symbol fields.
Schematic symbol object.
Definition: sch_symbol.h:78
SCH_SCREEN * LastScreen()
EE_RTREE & Items()
Gets the full RTree, usually for iterating.
Definition: sch_screen.h:110
A base class for most all the KiCad significant classes used in schematics and boards.
Definition: eda_item.h:100
bool GetIncludeOnBoard() const
Definition: sch_symbol.h:662
wxString GetDescription() const
Return information about the aliased parts.
Definition: sch_symbol.cpp:266
int StrNumCmp(const wxString &aString1, const wxString &aString2, bool aIgnoreCase)
Compare two strings with alphanumerical content.
std::set< LIB_SYMBOL *, LIB_SYMBOL_LESS_THAN > m_libParts
unique library symbols used. LIB_SYMBOL items are sorted by names
virtual SCH_SHEET_LIST GetSheets() const =0
Base class for any item which can be embedded within the SCHEMATIC container class,...
Definition: sch_item.h:193
bool UseLibIdLookup() const
Definition: sch_symbol.h:162
const LIB_ID & GetLibId() const
Definition: sch_symbol.h:147

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::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_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 767 of file netlist_exporter_xml.cpp.

769 {
770  XNODE* n = new XNODE( wxXML_ELEMENT_NODE, aName );
771 
772  if( aTextualContent.Len() > 0 ) // excludes wxEmptyString, the parameter's default value
773  n->AddChild( new XNODE( wxXML_TEXT_NODE, wxEmptyString, aTextualContent ) );
774 
775  return n;
776 }
Hold an XML or S-expression element.
Definition: xnode.h:43

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 }
void DisplayError(wxWindow *aParent, const wxString &aText, int aDisplayTime)
Display an error or warning message box with aMessage.
Definition: confirm.cpp:271
void Format(OUTPUTFORMATTER *aOutputFormatter, int aCtl)
Output this s-expression netlist into aOutputFormatter.
virtual const wxString What() const
A composite of Problem() and Where()
Definition: exceptions.cpp:30
#define GNL_ALL
Used for text file output.
Definition: richio.h:456
Hold an error message and may be used when throwing exceptions containing meaningful error messages.
Definition: ki_exception.h:75

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_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_PSPICE::ProcessNetlist(), NETLIST_EXPORTER_ORCADPCB2::WriteNetlist(), and NETLIST_EXPORTER_CADSTAR::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_PSPICE::ProcessNetlist(), and NETLIST_EXPORTER_ORCADPCB2::WriteNetlist().


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