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)
 Function MakeCommandLine builds 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 ()
 Fills 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_COMPONENT *aSymbol, SCH_SHEET_PATH *aSheet)
 
void CreatePinList (SCH_COMPONENT *aSymbol, SCH_SHEET_PATH *aSheetPath)
 Function findNextSymbolAndCreatePinList finds a symbol from the DrawList and builds its pin list in m_sortedSymbolPinList. More...
 
SCH_COMPONENTfindNextSymbol (EDA_ITEM *aItem, SCH_SHEET_PATH *aSheetPath)
 Checks if the given symbol should be processed for netlisting. More...
 
void eraseDuplicatePins ()
 Function eraseDuplicatePins erase duplicate Pins from m_sortedSymbolPinList (i.e. More...
 
void findAllUnitsOfSymbol (SCH_COMPONENT *aSymbol, LIB_PART *aPart, SCH_SHEET_PATH *aSheetPath)
 Function findAllUnitsOfSymbol is used for "multiple parts per package" symbols. 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 parts per package" symbols to avoid processing a lib part more than once. More...
 
std::set< LIB_PART *, LIB_PART_LESS_THANm_libParts
 unique library parts used. LIB_PART 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_COMPONENT aSymbol,
SCH_SHEET_PATH aSheet 
)
protectedinherited

Definition at line 90 of file netlist_exporter_xml.cpp.

92 {
93  COMP_FIELDS fields;
94 
95  if( aSymbol->GetUnitCount() > 1 )
96  {
97  // Sadly, each unit of a component can have its own unique fields. This
98  // block finds the unit with the lowest number having a non blank field
99  // value and records it. Therefore user is best off setting fields
100  // into only the first unit. But this scavenger algorithm will find
101  // any non blank fields in all units and use the first non-blank field
102  // for each unique field name.
103 
104  wxString ref = aSymbol->GetRef( aSheet );
105 
106  SCH_SHEET_LIST sheetList = m_schematic->GetSheets();
107  int minUnit = aSymbol->GetUnit();
108 
109  for( unsigned i = 0; i < sheetList.size(); i++ )
110  {
111  for( auto item : sheetList[i].LastScreen()->Items().OfType( SCH_COMPONENT_T ) )
112  {
113  SCH_COMPONENT* comp2 = (SCH_COMPONENT*) item;
114 
115  wxString ref2 = comp2->GetRef( &sheetList[i] );
116 
117  if( ref2.CmpNoCase( ref ) != 0 )
118  continue;
119 
120  int unit = comp2->GetUnit();
121 
122  // The lowest unit number wins. User should only set fields in any one unit.
123  // remark: IsVoid() returns true for empty strings or the "~" string (empty
124  // field value)
125  if( !comp2->GetValue( &sheetList[i], m_resolveTextVars ).IsEmpty()
126  && ( unit < minUnit || fields.value.IsEmpty() ) )
127  {
128  fields.value = comp2->GetValue( &sheetList[i], m_resolveTextVars );
129  }
130 
131  if( !comp2->GetFootprint( &sheetList[i], m_resolveTextVars ).IsEmpty()
132  && ( unit < minUnit || fields.footprint.IsEmpty() ) )
133  {
134  fields.footprint = comp2->GetFootprint( &sheetList[i], m_resolveTextVars );
135  }
136 
137  if( !comp2->GetField( DATASHEET_FIELD )->IsVoid()
138  && ( unit < minUnit || fields.datasheet.IsEmpty() ) )
139  {
140  if( m_resolveTextVars )
141  fields.datasheet = comp2->GetField( DATASHEET_FIELD )->GetShownText();
142  else
143  fields.datasheet = comp2->GetField( DATASHEET_FIELD )->GetText();
144  }
145 
146  for( int ii = MANDATORY_FIELDS; ii < comp2->GetFieldCount(); ++ii )
147  {
148  const SCH_FIELD& f = comp2->GetFields()[ ii ];
149 
150  if( f.GetText().size()
151  && ( unit < minUnit || fields.f.count( f.GetName() ) == 0 ) )
152  {
153  if( m_resolveTextVars )
154  fields.f[ f.GetName() ] = f.GetShownText();
155  else
156  fields.f[ f.GetName() ] = f.GetText();
157  }
158  }
159 
160  minUnit = std::min( unit, minUnit );
161  }
162  }
163  }
164  else
165  {
166  fields.value = aSymbol->GetValue( aSheet, m_resolveTextVars );
167  fields.footprint = aSymbol->GetFootprint( aSheet, m_resolveTextVars );
168 
169  if( m_resolveTextVars )
170  fields.datasheet = aSymbol->GetField( DATASHEET_FIELD )->GetShownText();
171  else
172  fields.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  {
180  if( m_resolveTextVars )
181  fields.f[ f.GetName() ] = f.GetShownText();
182  else
183  fields.f[ f.GetName() ] = f.GetText();
184  }
185  }
186  }
187 
188  // Do not output field values blank in netlist:
189  if( fields.value.size() )
190  aNode->AddChild( node( "value", fields.value ) );
191  else // value field always written in netlist
192  aNode->AddChild( node( "value", "~" ) );
193 
194  if( fields.footprint.size() )
195  aNode->AddChild( node( "footprint", fields.footprint ) );
196 
197  if( fields.datasheet.size() )
198  aNode->AddChild( node( "datasheet", fields.datasheet ) );
199 
200  if( fields.f.size() )
201  {
202  XNODE* xfields;
203  aNode->AddChild( xfields = node( "fields" ) );
204 
205  // non MANDATORY fields are output alphabetically
206  for( std::map< wxString, wxString >::const_iterator it = fields.f.begin();
207  it != fields.f.end(); ++it )
208  {
209  XNODE* xfield;
210  xfields->AddChild( xfield = node( "field", it->second ) );
211  xfield->AddAttribute( "name", it->first );
212  }
213  }
214 }
A container for handling SCH_SHEET_PATH objects in a flattened hierarchy.
SCH_FIELD instances are attached to a component and provide a place for the component's value,...
Definition: sch_field.h:51
SCH_FIELD * GetField(MANDATORY_FIELD_T aFieldType)
Returns a mandatory field in this symbol.
Definition: sch_symbol.cpp:688
int GetUnitCount() const
Return the number of units per package of the symbol.
Definition: sch_symbol.cpp:356
wxString GetShownText(int aDepth=0) const override
Return the string actually shown after processing of the base text.
Definition: sch_field.cpp:104
bool IsVoid() const
Function IsVoid returns true if the field is either empty or holds "~".
Definition: sch_field.cpp:321
name of datasheet
void GetFields(std::vector< SCH_FIELD * > &aVector, bool aVisibleOnly)
Populates a std::vector with SCH_FIELDs.
Definition: sch_symbol.cpp:724
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 wxString GetFootprint(const SCH_SHEET_PATH *sheet, bool aResolve) const
Definition: sch_symbol.cpp:638
int GetUnit() const
Definition: sch_symbol.h:236
const wxString GetValue(const SCH_SHEET_PATH *sheet, bool aResolve) const
Definition: sch_symbol.cpp:588
Holder for multi-unit component fields.
int GetFieldCount() const
Return the number of fields in this symbol.
Definition: sch_symbol.h:457
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.
wxString GetName(bool aUseDefaultName=true) const
Function GetName returns the field name.
Definition: sch_field.cpp:505
Schematic symbol object.
Definition: sch_symbol.h:78
std::map< wxString, wxString > f
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
const wxString GetRef(const SCH_SHEET_PATH *aSheet, bool aIncludeUnit=false) const
Return the reference for the given sheet path.
Definition: sch_symbol.cpp:427

References COMP_FIELDS::datasheet, DATASHEET_FIELD, COMP_FIELDS::f, COMP_FIELDS::footprint, SCH_COMPONENT::GetField(), SCH_COMPONENT::GetFieldCount(), SCH_COMPONENT::GetFields(), SCH_COMPONENT::GetFootprint(), SCH_FIELD::GetName(), SCH_COMPONENT::GetRef(), SCHEMATIC_IFACE::GetSheets(), SCH_FIELD::GetShownText(), EDA_TEXT::GetText(), SCH_COMPONENT::GetUnit(), SCH_COMPONENT::GetUnitCount(), SCH_COMPONENT::GetValue(), SCH_FIELD::IsVoid(), NETLIST_EXPORTER_XML::m_resolveTextVars, NETLIST_EXPORTER_BASE::m_schematic, MANDATORY_FIELDS, NETLIST_EXPORTER_XML::node(), SCH_COMPONENT_T, and COMP_FIELDS::value.

Referenced by NETLIST_EXPORTER_XML::makeSymbols().

◆ CreatePinList()

void NETLIST_EXPORTER_BASE::CreatePinList ( SCH_COMPONENT aSymbol,
SCH_SHEET_PATH aSheetPath 
)
protectedinherited

Function findNextSymbolAndCreatePinList finds a symbol from the DrawList and builds its pin list in m_sortedSymbolPinList.

This list is sorted by pin num. The symbol is the next actual symbol after aSymbol.

Power symbols and virtual symbols that have their reference designators starting with '#' are skipped.

Definition at line 122 of file netlist_exporter_base.cpp.

123 {
124  wxString ref( aSymbol->GetRef( aSheetPath ) );
125 
126  // Power symbols and other symbols which have the reference starting with "#" are not
127  // included in netlist (pseudo or virtual symbols)
128 
129  if( ref[0] == wxChar( '#' ) )
130  return;
131 
132  // if( aSymbol->m_FlagControlMulti == 1 )
133  // continue; /* yes */
134  // removed because with multiple instances of one schematic (several sheets pointing to
135  // 1 screen), this will be erroneously be toggled.
136 
137  if( !aSymbol->GetPartRef() )
138  return;
139 
140  m_sortedSymbolPinList.clear();
141 
142  // If symbol is a "multi parts per package" type
143  if( aSymbol->GetPartRef()->GetUnitCount() > 1 )
144  {
145  // Collect all pins for this reference designator by searching the entire design for
146  // other parts with the same reference designator.
147  // This is only done once, it would be too expensive otherwise.
148  findAllUnitsOfSymbol( aSymbol, aSymbol->GetPartRef().get(), aSheetPath );
149  }
150 
151  else // GetUnitCount() <= 1 means one part per package
152  {
154 
155  for( const SCH_PIN* pin : aSymbol->GetPins( aSheetPath ) )
156  {
157  if( SCH_CONNECTION* conn = pin->Connection( aSheetPath ) )
158  {
159  const wxString& netName = conn->Name();
160 
161  // Skip unconnected pins
162  CONNECTION_SUBGRAPH* sg = graph->FindSubgraphByName( netName, *aSheetPath );
163 
164  if( !sg || sg->m_no_connect || sg->m_items.size() < 2 )
165  continue;
166 
167  m_sortedSymbolPinList.emplace_back( pin->GetNumber(), netName );
168  }
169  }
170  }
171 
172  // Sort pins in m_SortedComponentPinList by pin number
174 
175  // Remove duplicate Pins in m_SortedComponentPinList
177 
178  // record the usage of this library component entry.
179  m_libParts.insert( aSymbol->GetPartRef().get() ); // rejects non-unique pointers
180 }
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()
Function eraseDuplicatePins erase duplicate Pins from m_sortedSymbolPinList (i.e.
virtual CONNECTION_GRAPH * ConnectionGraph() const =0
static bool sortPinsByNum(PIN_INFO &aPin1, PIN_INFO &aPin2)
Comparison routine for sorting by pin numbers.
void findAllUnitsOfSymbol(SCH_COMPONENT *aSymbol, LIB_PART *aPart, SCH_SHEET_PATH *aSheetPath)
Function findAllUnitsOfSymbol is used for "multiple parts per package" symbols.
std::set< LIB_PART *, LIB_PART_LESS_THAN > m_libParts
unique library parts used. LIB_PART items are sorted by names
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
std::unique_ptr< LIB_PART > & GetPartRef()
Definition: sch_symbol.h:205
std::vector< SCH_PIN * > GetPins(const SCH_SHEET_PATH *aSheet=nullptr) const
Retrieves a list of the SCH_PINs for the given sheet path.
Definition: sch_symbol.cpp:863
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.
const wxString GetRef(const SCH_SHEET_PATH *aSheet, bool aIncludeUnit=false) const
Return the reference for the given sheet path.
Definition: sch_symbol.cpp:427

References SCHEMATIC_IFACE::ConnectionGraph(), NETLIST_EXPORTER_BASE::eraseDuplicatePins(), NETLIST_EXPORTER_BASE::findAllUnitsOfSymbol(), CONNECTION_GRAPH::FindSubgraphByName(), SCH_COMPONENT::GetPartRef(), SCH_COMPONENT::GetPins(), SCH_COMPONENT::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 sortPinsByNum().

Referenced by NETLIST_EXPORTER_PSPICE::ProcessNetlist(), and NETLIST_EXPORTER_ORCADPCB2::WriteNetlist().

◆ eraseDuplicatePins()

void NETLIST_EXPORTER_BASE::eraseDuplicatePins ( )
protectedinherited

Function eraseDuplicatePins 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 parts per package" symbols. For instance, a 74ls00 has 4 parts, 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 183 of file netlist_exporter_base.cpp.

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

Function findAllUnitsOfSymbol is used for "multiple parts per package" symbols.

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.

Definition at line 216 of file netlist_exporter_base.cpp.

218 {
219  wxString ref = aSymbol->GetRef( aSheetPath );
220  wxString ref2;
221 
222  SCH_SHEET_LIST sheetList = m_schematic->GetSheets();
224 
225  for( unsigned i = 0; i < sheetList.size(); i++ )
226  {
227  SCH_SHEET_PATH& sheet = sheetList[i];
228 
229  for( SCH_ITEM* item : sheetList[i].LastScreen()->Items().OfType( SCH_COMPONENT_T ) )
230  {
231  SCH_COMPONENT* comp2 = static_cast<SCH_COMPONENT*>( item );
232 
233  ref2 = comp2->GetRef( &sheet );
234 
235  if( ref2.CmpNoCase( ref ) != 0 )
236  continue;
237 
238  for( const SCH_PIN* pin : comp2->GetPins( &sheet ) )
239  {
240  if( SCH_CONNECTION* conn = pin->Connection( &sheet ) )
241  {
242  const wxString& netName = conn->Name();
243 
244  // Skip unconnected pins
245  CONNECTION_SUBGRAPH* sg = graph->FindSubgraphByName( netName, sheet );
246 
247  if( !sg || sg->m_no_connect || sg->m_items.size() < 2 )
248  continue;
249 
250  m_sortedSymbolPinList.emplace_back( pin->GetNumber(), netName );
251  }
252  }
253  }
254  }
255 }
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
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...
std::vector< SCH_PIN * > GetPins(const SCH_SHEET_PATH *aSheet=nullptr) const
Retrieves a list of the SCH_PINs for the given sheet path.
Definition: sch_symbol.cpp:863
Each graphical item can have a SCH_CONNECTION describing its logical connection (to a bus or net).
Schematic symbol object.
Definition: sch_symbol.h:78
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:196
const wxString GetRef(const SCH_SHEET_PATH *aSheet, bool aIncludeUnit=false) const
Return the reference for the given sheet path.
Definition: sch_symbol.cpp:427

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

Referenced by NETLIST_EXPORTER_BASE::CreatePinList().

◆ findNextSymbol()

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

Checks if the given symbol should be processed for netlisting.

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

75 {
76  wxString ref;
77 
78  if( aItem->Type() != SCH_COMPONENT_T )
79  return nullptr;
80 
81  // found next component
82  SCH_COMPONENT* symbol = (SCH_COMPONENT*) aItem;
83 
84  // Power symbols and other symbols which have the reference starting with "#" are not
85  // included in netlist (pseudo or virtual symbols)
86  ref = symbol->GetRef( aSheetPath );
87 
88  if( ref[0] == wxChar( '#' ) )
89  return nullptr;
90 
91  // if( symbol->m_FlagControlMulti == 1 )
92  // continue; /* yes */
93  // removed because with multiple instances of one schematic (several sheets pointing to
94  // 1 screen), this will be erroneously be toggled.
95 
96  if( !symbol->GetPartRef() )
97  return nullptr;
98 
99  // If component is a "multi parts per package" type
100  if( symbol->GetPartRef()->GetUnitCount() > 1 )
101  {
102  // test if this reference has already been processed, and if so skip
103  if( m_referencesAlreadyFound.Lookup( ref ) )
104  return nullptr;
105  }
106 
107  // record the usage of this library component entry.
108  m_libParts.insert( symbol->GetPartRef().get() ); // rejects non-unique pointers
109 
110  return symbol;
111 }
bool Lookup(const wxString &aString)
Function Lookup returns true if aString already exists in the set, otherwise returns false and adds a...
std::set< LIB_PART *, LIB_PART_LESS_THAN > m_libParts
unique library parts used. LIB_PART items are sorted by names
UNIQUE_STRINGS m_referencesAlreadyFound
Used for "multiple parts per package" symbols to avoid processing a lib part more than once.
std::unique_ptr< LIB_PART > & GetPartRef()
Definition: sch_symbol.h:205
Schematic symbol object.
Definition: sch_symbol.h:78
KICAD_T Type() const
Returns the type of object.
Definition: eda_item.h:162
const wxString GetRef(const SCH_SHEET_PATH *aSheet, bool aIncludeUnit=false) const
Return the reference for the given sheet path.
Definition: sch_symbol.cpp:427

References SCH_COMPONENT::GetPartRef(), SCH_COMPONENT::GetRef(), UNIQUE_STRINGS::Lookup(), NETLIST_EXPORTER_BASE::m_libParts, NETLIST_EXPORTER_BASE::m_referencesAlreadyFound, SCH_COMPONENT_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 56 of file netlist_exporter_kicad.cpp.

57 {
58  std::unique_ptr<XNODE> xroot( makeRoot( aCtl ) );
59 
60  xroot->Format( aOut, 0 );
61 }
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

Function MakeCommandLine builds 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 38 of file netlist_exporter_base.cpp.

42 {
43  // Expand format symbols in the command line:
44  // %B => base filename of selected output file, minus path and extension.
45  // %P => project directory name, without trailing '/' or '\'.
46  // %I => full filename of the input file (the intermediate net file).
47  // %O => complete filename and path (but without extension) of the user chosen output file.
48 
49  wxString ret = aFormatString;
50  wxFileName in = aNetlistFile;
51  wxFileName out = aFinalFile;
52  wxString str_out = out.GetFullPath();
53 
54  ret.Replace( "%P", aProjectPath, true );
55  ret.Replace( "%B", out.GetName(), true );
56  ret.Replace( "%I", in.GetFullPath(), true );
57 
58 #ifdef __WINDOWS__
59  // A ugly hack to run xsltproc that has a serious bug on Window since a long time:
60  // the filename given after -o option (output filename) cannot use '\' in filename
61  // so replace if by '/' if possible (I mean if the filename does not start by "\\"
62  // that is a filename on a Windows server)
63 
64  if( !str_out.StartsWith( "\\\\" ) )
65  str_out.Replace( "\\", "/" );
66 #endif
67 
68  ret.Replace( "%O", str_out, true );
69 
70  return ret;
71 }

Referenced by SCH_EDIT_FRAME::WriteNetListFile().

◆ makeDesignHeader()

XNODE * NETLIST_EXPORTER_XML::makeDesignHeader ( )
protectedinherited

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

Returns
XNODE* - the design header

Definition at line 354 of file netlist_exporter_xml.cpp.

355 {
356  SCH_SCREEN* screen;
357  XNODE* xdesign = node( "design" );
358  XNODE* xtitleBlock;
359  XNODE* xsheet;
360  XNODE* xcomment;
361  XNODE* xtextvar;
362  wxString sheetTxt;
363  wxFileName sourceFileName;
364 
365  // the root sheet is a special sheet, call it source
366  xdesign->AddChild( node( "source", m_schematic->GetFileName() ) );
367 
368  xdesign->AddChild( node( "date", DateAndTime() ) );
369 
370  // which Eeschema tool
371  xdesign->AddChild( node( "tool", wxString( "Eeschema " ) + GetBuildVersion() ) );
372 
373  const std::map<wxString, wxString>& properties = m_schematic->Prj().GetTextVars();
374 
375  for( const std::pair<const wxString, wxString>& prop : properties )
376  {
377  xdesign->AddChild( xtextvar = node( "textvar", prop.second ) );
378  xtextvar->AddAttribute( "name", prop.first );
379  }
380 
381  /*
382  * Export the sheets information
383  */
384  SCH_SHEET_LIST sheetList = m_schematic->GetSheets();
385 
386  for( unsigned i = 0; i < sheetList.size(); i++ )
387  {
388  screen = sheetList[i].LastScreen();
389 
390  xdesign->AddChild( xsheet = node( "sheet" ) );
391 
392  // get the string representation of the sheet index number.
393  // Note that sheet->GetIndex() is zero index base and we need to increment the
394  // number by one to make it human readable
395  sheetTxt.Printf( "%u", i + 1 );
396  xsheet->AddAttribute( "number", sheetTxt );
397  xsheet->AddAttribute( "name", sheetList[i].PathHumanReadable() );
398  xsheet->AddAttribute( "tstamps", sheetList[i].PathAsString() );
399 
400  TITLE_BLOCK tb = screen->GetTitleBlock();
401  PROJECT* prj = &m_schematic->Prj();
402 
403  xsheet->AddChild( xtitleBlock = node( "title_block" ) );
404 
405  xtitleBlock->AddChild( node( "title", ExpandTextVars( tb.GetTitle(), prj ) ) );
406  xtitleBlock->AddChild( node( "company", ExpandTextVars( tb.GetCompany(), prj ) ) );
407  xtitleBlock->AddChild( node( "rev", ExpandTextVars( tb.GetRevision(), prj ) ) );
408  xtitleBlock->AddChild( node( "date", ExpandTextVars( tb.GetDate(), prj ) ) );
409 
410  // We are going to remove the fileName directories.
411  sourceFileName = wxFileName( screen->GetFileName() );
412  xtitleBlock->AddChild( node( "source", sourceFileName.GetFullName() ) );
413 
414  xtitleBlock->AddChild( xcomment = node( "comment" ) );
415  xcomment->AddAttribute( "number", "1" );
416  xcomment->AddAttribute( "value", ExpandTextVars( tb.GetComment( 0 ), prj ) );
417 
418  xtitleBlock->AddChild( xcomment = node( "comment" ) );
419  xcomment->AddAttribute( "number", "2" );
420  xcomment->AddAttribute( "value", ExpandTextVars( tb.GetComment( 1 ), prj ) );
421 
422  xtitleBlock->AddChild( xcomment = node( "comment" ) );
423  xcomment->AddAttribute( "number", "3" );
424  xcomment->AddAttribute( "value", ExpandTextVars( tb.GetComment( 2 ), prj ) );
425 
426  xtitleBlock->AddChild( xcomment = node( "comment" ) );
427  xcomment->AddAttribute( "number", "4" );
428  xcomment->AddAttribute( "value", ExpandTextVars( tb.GetComment( 3 ), prj ) );
429 
430  xtitleBlock->AddChild( xcomment = node( "comment" ) );
431  xcomment->AddAttribute( "number", "5" );
432  xcomment->AddAttribute( "value", ExpandTextVars( tb.GetComment( 4 ), prj ) );
433 
434  xtitleBlock->AddChild( xcomment = node( "comment" ) );
435  xcomment->AddAttribute( "number", "6" );
436  xcomment->AddAttribute( "value", ExpandTextVars( tb.GetComment( 5 ), prj ) );
437 
438  xtitleBlock->AddChild( xcomment = node( "comment" ) );
439  xcomment->AddAttribute( "number", "7" );
440  xcomment->AddAttribute( "value", ExpandTextVars( tb.GetComment( 6 ), prj ) );
441 
442  xtitleBlock->AddChild( xcomment = node( "comment" ) );
443  xcomment->AddAttribute( "number", "8" );
444  xcomment->AddAttribute( "value", ExpandTextVars( tb.GetComment( 7 ), prj ) );
445 
446  xtitleBlock->AddChild( xcomment = node( "comment" ) );
447  xcomment->AddAttribute( "number", "9" );
448  xcomment->AddAttribute( "value", ExpandTextVars( tb.GetComment( 8 ), prj ) );
449  }
450 
451  return xdesign;
452 }
A container for handling SCH_SHEET_PATH objects in a flattened hierarchy.
virtual std::map< wxString, wxString > & GetTextVars() const
const wxString & GetFileName() const
Definition: sch_screen.h:192
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:58
const wxString & GetComment(int aIdx) const
Definition: title_block.h:107
const TITLE_BLOCK & GetTitleBlock() const
Definition: sch_screen.h:197
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
virtual SCH_SHEET_LIST GetSheets() const =0
wxString DateAndTime()
Definition: string.cpp:411

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
XNODE* - the library parts nodes

Definition at line 479 of file netlist_exporter_xml.cpp.

480 {
481  XNODE* xlibparts = node( "libparts" ); // auto_ptr
482 
483  LIB_PINS pinList;
484  std::vector<LIB_FIELD*> fieldList;
485 
486  m_libraries.clear();
487 
488  for( auto lcomp : m_libParts )
489  {
490  wxString libNickname = lcomp->GetLibId().GetLibNickname();;
491 
492  // The library nickname will be empty if the cache library is used.
493  if( !libNickname.IsEmpty() )
494  m_libraries.insert( libNickname ); // inserts component's library if unique
495 
496  XNODE* xlibpart;
497  xlibparts->AddChild( xlibpart = node( "libpart" ) );
498  xlibpart->AddAttribute( "lib", libNickname );
499  xlibpart->AddAttribute( "part", lcomp->GetName() );
500 
501  //----- show the important properties -------------------------
502  if( !lcomp->GetDescription().IsEmpty() )
503  xlibpart->AddChild( node( "description", lcomp->GetDescription() ) );
504 
505  if( !lcomp->GetDatasheetField().GetText().IsEmpty() )
506  xlibpart->AddChild( node( "docs", lcomp->GetDatasheetField().GetText() ) );
507 
508  // Write the footprint list
509  if( lcomp->GetFPFilters().GetCount() )
510  {
511  XNODE* xfootprints;
512  xlibpart->AddChild( xfootprints = node( "footprints" ) );
513 
514  for( unsigned i = 0; i < lcomp->GetFPFilters().GetCount(); ++i )
515  xfootprints->AddChild( node( "fp", lcomp->GetFPFilters()[i] ) );
516  }
517 
518  //----- show the fields here ----------------------------------
519  fieldList.clear();
520  lcomp->GetFields( fieldList );
521 
522  XNODE* xfields;
523  xlibpart->AddChild( xfields = node( "fields" ) );
524 
525  for( const LIB_FIELD* field : fieldList )
526  {
527  if( !field->GetText().IsEmpty() )
528  {
529  XNODE* xfield;
530  xfields->AddChild( xfield = node( "field", field->GetText() ) );
531  xfield->AddAttribute( "name", field->GetCanonicalName() );
532  }
533  }
534 
535  //----- show the pins here ------------------------------------
536  pinList.clear();
537  lcomp->GetPins( pinList, 0, 0 );
538 
539  /* we must erase redundant Pins references in pinList
540  * These redundant pins exist because some pins
541  * are found more than one time when a component has
542  * multiple parts per package or has 2 representations (DeMorgan conversion)
543  * For instance, a 74ls00 has DeMorgan conversion, with different pin shapes,
544  * and therefore each pin appears 2 times in the list.
545  * Common pins (VCC, GND) can also be found more than once.
546  */
547  sort( pinList.begin(), pinList.end(), sortPinsByNumber );
548  for( int ii = 0; ii < (int)pinList.size()-1; ii++ )
549  {
550  if( pinList[ii]->GetNumber() == pinList[ii+1]->GetNumber() )
551  { // 2 pins have the same number, remove the redundant pin at index i+1
552  pinList.erase(pinList.begin() + ii + 1);
553  ii--;
554  }
555  }
556 
557  if( pinList.size() )
558  {
559  XNODE* pins;
560 
561  xlibpart->AddChild( pins = node( "pins" ) );
562  for( unsigned i=0; i<pinList.size(); ++i )
563  {
564  XNODE* pin;
565 
566  pins->AddChild( pin = node( "pin" ) );
567  pin->AddAttribute( "num", pinList[i]->GetNumber() );
568  pin->AddAttribute( "name", pinList[i]->GetName() );
569  pin->AddAttribute( "type", pinList[i]->GetCanonicalElectricalTypeName() );
570 
571  // caution: construction work site here, drive slowly
572  }
573  }
574  }
575 
576  return xlibparts;
577 }
std::vector< LIB_PIN * > LIB_PINS
Helper for defining a list of pin object pointers.
Definition: lib_item.h:56
Field object used in symbol libraries.
Definition: lib_field.h:59
std::set< LIB_PART *, LIB_PART_LESS_THAN > m_libParts
unique library parts used. LIB_PART items are sorted by names
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

References NETLIST_EXPORTER_BASE::m_libParts, NETLIST_EXPORTER_XML::m_libraries, NETLIST_EXPORTER_XML::node(), 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
XNODE* - the library nodes

Definition at line 455 of file netlist_exporter_xml.cpp.

456 {
457  XNODE* xlibs = node( "libraries" ); // auto_ptr
458  SYMBOL_LIB_TABLE* symbolLibTable = m_schematic->Prj().SchSymbolLibTable();
459 
460  for( std::set<wxString>::iterator it = m_libraries.begin(); it!=m_libraries.end(); ++it )
461  {
462  wxString libNickname = *it;
463  XNODE* xlibrary;
464 
465  if( symbolLibTable->HasLibrary( libNickname ) )
466  {
467  xlibs->AddChild( xlibrary = node( "library" ) );
468  xlibrary->AddAttribute( "logical", libNickname );
469  xlibrary->AddChild( node( "uri", symbolLibTable->GetFullURI( libNickname ) ) );
470  }
471 
472  // @todo: add more fun stuff here
473  }
474 
475  return xlibs;
476 }
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
XNODE* - the list of nets nodes

Definition at line 580 of file netlist_exporter_xml.cpp.

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

References SCHEMATIC_IFACE::ConnectionGraph(), SCH_COMPONENT::GetIncludeInBom(), SCH_COMPONENT::GetIncludeOnBoard(), CONNECTION_GRAPH::GetNetMap(), SCH_PIN::GetParentSymbol(), GNL_OPT_BOM, GNL_OPT_KICAD, NETLIST_EXPORTER_BASE::m_schematic, NETLIST_EXPORTER_XML::node(), 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
aCtl- a bitset or-ed together from GNL_ENUM values
Returns
XNODE* - the root nodes

Definition at line 52 of file netlist_exporter_xml.cpp.

53 {
54  XNODE* xroot = node( "export" );
55 
56  xroot->AddAttribute( "version", "E" );
57 
58  if( aCtl & GNL_HEADER )
59  // add the "design" header
60  xroot->AddChild( makeDesignHeader() );
61 
62  if( aCtl & GNL_COMPONENTS )
63  xroot->AddChild( makeSymbols( aCtl ) );
64 
65  if( aCtl & GNL_PARTS )
66  xroot->AddChild( makeLibParts() );
67 
68  if( aCtl & GNL_LIBRARIES )
69  // must follow makeGenericLibParts()
70  xroot->AddChild( makeLibraries() );
71 
72  if( aCtl & GNL_NETS )
73  xroot->AddChild( makeListOfNets( aCtl ) );
74 
75  return xroot;
76 }
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()
Fills out a project "design" header into an XML node.

References GNL_COMPONENTS, GNL_HEADER, GNL_LIBRARIES, GNL_NETS, GNL_PARTS, 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
XNODE* - returns a sub-tree holding all the schematic components.

Definition at line 217 of file netlist_exporter_xml.cpp.

218 {
219  XNODE* xcomps = node( "components" );
220 
222  m_libParts.clear();
223 
224  SCH_SHEET_LIST sheetList = m_schematic->GetSheets();
225 
226  // Output is xml, so there is no reason to remove spaces from the field values.
227  // And XML element names need not be translated to various languages.
228 
229  for( unsigned ii = 0; ii < sheetList.size(); ii++ )
230  {
231  SCH_SHEET_PATH sheet = sheetList[ii];
232  m_schematic->SetCurrentSheet( sheet );
233 
234  auto cmp = [sheet]( SCH_COMPONENT* a, SCH_COMPONENT* b )
235  {
236  return ( UTIL::RefDesStringCompare( a->GetRef( &sheet ),
237  b->GetRef( &sheet ) ) < 0 );
238  };
239 
240  std::set<SCH_COMPONENT*, decltype( cmp )> ordered_symbols( cmp );
241  std::multiset<SCH_COMPONENT*, decltype( cmp )> extra_units( cmp );
242 
243  for( SCH_ITEM* item : sheet.LastScreen()->Items().OfType( SCH_COMPONENT_T ) )
244  {
245  SCH_COMPONENT* symbol = static_cast<SCH_COMPONENT*>( item );
246  auto test = ordered_symbols.insert( symbol );
247 
248  if( !test.second )
249  {
250  if( ( *( test.first ) )->m_Uuid > symbol->m_Uuid )
251  {
252  extra_units.insert( *( test.first ) );
253  ordered_symbols.erase( test.first );
254  ordered_symbols.insert( symbol );
255  }
256  else
257  {
258  extra_units.insert( symbol );
259  }
260  }
261  }
262 
263  for( EDA_ITEM* item : ordered_symbols )
264  {
265  SCH_COMPONENT* symbol = findNextSymbol( item, &sheet );
266 
267  if( !symbol
268  || ( ( aCtl & GNL_OPT_BOM ) && !symbol->GetIncludeInBom() )
269  || ( ( aCtl & GNL_OPT_KICAD ) && !symbol->GetIncludeOnBoard() ) )
270  {
271  continue;
272  }
273 
274  // Output the symbol's elements in order of expected access frequency. This may
275  // not always look best, but it will allow faster execution under XSL processing
276  // systems which do sequential searching within an element.
277 
278  XNODE* xcomp; // current component being constructed
279  xcomps->AddChild( xcomp = node( "comp" ) );
280 
281  xcomp->AddAttribute( "ref", symbol->GetRef( &sheet ) );
282  addSymbolFields( xcomp, symbol, &sheetList[ ii ] );
283 
284  XNODE* xlibsource;
285  xcomp->AddChild( xlibsource = node( "libsource" ) );
286 
287  // "logical" library name, which is in anticipation of a better search algorithm
288  // for parts based on "logical_lib.part" and where logical_lib is merely the library
289  // name minus path and extension.
290  if( symbol->GetPartRef() )
291  xlibsource->AddAttribute( "lib", symbol->GetPartRef()->GetLibId().GetLibNickname() );
292 
293  // We only want the symbol name, not the full LIB_ID.
294  xlibsource->AddAttribute( "part", symbol->GetLibId().GetLibItemName() );
295 
296  xlibsource->AddAttribute( "description", symbol->GetDescription() );
297 
298  XNODE* xproperty;
299 
300  std::vector<SCH_FIELD>& fields = symbol->GetFields();
301 
302  for( size_t jj = MANDATORY_FIELDS; jj < fields.size(); ++jj )
303  {
304  xcomp->AddChild( xproperty = node( "property" ) );
305  xproperty->AddAttribute( "name", fields[jj].GetCanonicalName() );
306  xproperty->AddAttribute( "value", fields[jj].GetText() );
307  }
308 
309  for( const SCH_FIELD& sheetField : sheet.Last()->GetFields() )
310  {
311  xcomp->AddChild( xproperty = node( "property" ) );
312  xproperty->AddAttribute( "name", sheetField.GetCanonicalName() );
313  xproperty->AddAttribute( "value", sheetField.GetText() );
314  }
315 
316  if( !symbol->GetIncludeInBom() )
317  {
318  xcomp->AddChild( xproperty = node( "property" ) );
319  xproperty->AddAttribute( "name", "exclude_from_bom" );
320  }
321 
322  if( !symbol->GetIncludeOnBoard() )
323  {
324  xcomp->AddChild( xproperty = node( "property" ) );
325  xproperty->AddAttribute( "name", "exclude_from_board" );
326  }
327 
328  XNODE* xsheetpath;
329  xcomp->AddChild( xsheetpath = node( "sheetpath" ) );
330 
331  xsheetpath->AddAttribute( "names", sheet.PathHumanReadable() );
332  xsheetpath->AddAttribute( "tstamps", sheet.PathAsString() );
333 
334  XNODE* xunits; // Node for extra units
335  xcomp->AddChild( xunits = node( "tstamps" ) );
336 
337  auto range = extra_units.equal_range( symbol );
338 
339  // Output a series of children with all UUIDs associated with the REFDES
340  for( auto it = range.first; it != range.second; ++it )
341  xunits->AddChild(
342  new XNODE( wxXML_TEXT_NODE, wxEmptyString, ( *it )->m_Uuid.AsString() ) );
343 
344  // Output the primary UUID
345  xunits->AddChild(
346  new XNODE( wxXML_TEXT_NODE, wxEmptyString, symbol->m_Uuid.AsString() ) );
347  }
348  }
349 
350  return xcomps;
351 }
A container for handling SCH_SHEET_PATH objects in a flattened hierarchy.
EE_TYPE OfType(KICAD_T aType) const
Definition: sch_rtree.h:219
SCH_FIELD instances are attached to a component and provide a place for the component's value,...
Definition: sch_field.h:51
const UTF8 & GetLibItemName() const
Definition: lib_id.h:106
SCH_SHEET * Last() const
Return a pointer to the last SCH_SHEET of the list.
bool GetIncludeOnBoard() const
Definition: sch_symbol.h:701
wxString PathHumanReadable(bool aUseShortRootName=true) const
Return the sheet path in a human readable form made from the sheet names.
wxString AsString() const
Definition: kiid.cpp:213
wxString PathAsString() const
Return the path of time stamps which do not changes even when editing sheet parameters.
wxString GetDescription() const
Return information about the aliased parts.
Definition: sch_symbol.cpp:252
void Clear()
Function Clear erases the record.
std::set< LIB_PART *, LIB_PART_LESS_THAN > m_libParts
unique library parts used. LIB_PART items are sorted by names
void GetFields(std::vector< SCH_FIELD * > &aVector, bool aVisibleOnly)
Populates a std::vector with SCH_FIELDs.
Definition: sch_symbol.cpp:724
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 parts per package" symbols to avoid processing a lib part more than once.
int RefDesStringCompare(const wxString &aFirst, const wxString &aSecond)
Acts just like the strcmp function but treats numbers within the string text correctly for sorting.
std::vector< SCH_FIELD > & GetFields()
Definition: sch_sheet.h:270
SCH_COMPONENT * findNextSymbol(EDA_ITEM *aItem, SCH_SHEET_PATH *aSheetPath)
Checks if the given symbol should be processed for netlisting.
Handle access to a stack of flattened SCH_SHEET objects by way of a path for creating a flattened sch...
std::unique_ptr< LIB_PART > & GetPartRef()
Definition: sch_symbol.h:205
bool GetIncludeInBom() const
Definition: sch_symbol.h:698
virtual void SetCurrentSheet(const SCH_SHEET_PATH &aPath)=0
const KIID m_Uuid
Definition: eda_item.h:524
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.
SCH_SCREEN * LastScreen()
void addSymbolFields(XNODE *aNode, SCH_COMPONENT *aSymbol, SCH_SHEET_PATH *aSheet)
EE_RTREE & Items()
Definition: sch_screen.h:162
Schematic symbol object.
Definition: sch_symbol.h:78
A base class for most all the KiCad significant classes used in schematics and boards.
Definition: eda_item.h:149
const LIB_ID & GetLibId() const
Definition: sch_symbol.h:188
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:196
const wxString GetRef(const SCH_SHEET_PATH *aSheet, bool aIncludeUnit=false) const
Return the reference for the given sheet path.
Definition: sch_symbol.cpp:427

References NETLIST_EXPORTER_XML::addSymbolFields(), KIID::AsString(), UNIQUE_STRINGS::Clear(), NETLIST_EXPORTER_BASE::findNextSymbol(), SCH_COMPONENT::GetDescription(), SCH_SHEET::GetFields(), SCH_COMPONENT::GetFields(), SCH_COMPONENT::GetIncludeInBom(), SCH_COMPONENT::GetIncludeOnBoard(), SCH_COMPONENT::GetLibId(), LIB_ID::GetLibItemName(), SCH_COMPONENT::GetPartRef(), SCH_COMPONENT::GetRef(), 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(), UTIL::RefDesStringCompare(), SCH_COMPONENT_T, and SCHEMATIC_IFACE::SetCurrentSheet().

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

745 {
746  XNODE* n = new XNODE( wxXML_ELEMENT_NODE, aName );
747 
748  if( aTextualContent.Len() > 0 ) // excludes wxEmptyString, the parameter's default value
749  n->AddChild( new XNODE( wxXML_TEXT_NODE, wxEmptyString, aTextualContent ) );
750 
751  return n;
752 }
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 38 of file netlist_exporter_kicad.cpp.

39 {
40  try
41  {
42  FILE_OUTPUTFORMATTER formatter( aOutFileName );
43  Format( &formatter, GNL_ALL | GNL_OPT_KICAD );
44  }
45 
46  catch( const IO_ERROR& ioe )
47  {
48  DisplayError( NULL, ioe.What() );
49  return false;
50  }
51 
52  return true;
53 }
void DisplayError(wxWindow *aParent, const wxString &aText, int aDisplayTime)
Display an error or warning message box with aMessage.
Definition: confirm.cpp:252
void Format(OUTPUTFORMATTER *aOutputFormatter, int aCtl)
Output this s-expression netlist into aOutputFormatter.
#define NULL
virtual const wxString What() const
A composite of Problem() and Where()
Definition: exceptions.cpp:29
#define GNL_ALL
Used for text file output.
Definition: richio.h:453
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, NULL, and IO_ERROR::What().

Member Data Documentation

◆ m_libParts

std::set<LIB_PART*, LIB_PART_LESS_THAN> NETLIST_EXPORTER_BASE::m_libParts
protectedinherited

◆ m_referencesAlreadyFound

UNIQUE_STRINGS NETLIST_EXPORTER_BASE::m_referencesAlreadyFound
protectedinherited

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

Definition at line 105 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 114 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 101 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: