KiCad PCB EDA Suite
NETLIST_EXPORTER_GENERIC Class Reference

NETLIST_EXPORTER_GENERIC generates a generic XML based netlist file. More...

#include <netlist_exporter_generic.h>

Inheritance diagram for NETLIST_EXPORTER_GENERIC:
NETLIST_EXPORTER NETLIST_EXPORTER_KICAD

Public Member Functions

 NETLIST_EXPORTER_GENERIC (SCHEMATIC *aSchematic)
 
bool WriteNetlist (const wxString &aOutFileName, unsigned aNetlistOptions) override
 Function WriteNetlist writes to specified output file. 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)
 Function node is a convenience function that creates a new XNODE with an optional textual child. More...
 
XNODEmakeRoot (int aCtl=GNL_ALL)
 Function makeGenericRoot builds the entire document tree for the generic export. More...
 
XNODEmakeComponents ()
 Function makeComponents. More...
 
XNODEmakeDesignHeader ()
 Function makeDesignHeader fills out a project "design" header into an XML node. More...
 
XNODEmakeLibParts ()
 Function makeLibParts fills out an XML node with the unique library parts and returns it. More...
 
XNODEmakeListOfNets ()
 Function makeListOfNets fills out an XML node with a list of nets and returns it. More...
 
XNODEmakeLibraries ()
 Function makeLibraries fills out an XML node with a list of used libraries and returns it. More...
 
void addComponentFields (XNODE *xcomp, SCH_COMPONENT *comp, SCH_SHEET_PATH *aSheet)
 
SCH_COMPONENTfindNextComponent (EDA_ITEM *aItem, SCH_SHEET_PATH *aSheetPath)
 Checks if the given component should be processed for netlisting. More...
 

Protected Attributes

UNIQUE_STRINGS m_ReferencesAlreadyFound
 Used for "multi parts per package" components, avoids processing a lib component 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...
 
SCHEMATICm_schematic
 The schematic we're generating a netlist for. More...
 

Private Attributes

std::set< wxString > m_libraries
 Set of library nicknames. More...
 

Detailed Description

NETLIST_EXPORTER_GENERIC generates a generic XML based netlist file.

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

Definition at line 60 of file netlist_exporter_generic.h.

Constructor & Destructor Documentation

◆ NETLIST_EXPORTER_GENERIC()

NETLIST_EXPORTER_GENERIC::NETLIST_EXPORTER_GENERIC ( SCHEMATIC aSchematic)
inline

Definition at line 66 of file netlist_exporter_generic.h.

66  :
67  NETLIST_EXPORTER( aSchematic )
68  {}
NETLIST_EXPORTER(SCHEMATIC *aSchematic)
Constructor.

Member Function Documentation

◆ addComponentFields()

void NETLIST_EXPORTER_GENERIC::addComponentFields ( XNODE xcomp,
SCH_COMPONENT comp,
SCH_SHEET_PATH aSheet 
)
protected

Definition at line 88 of file netlist_exporter_generic.cpp.

89 {
90  COMP_FIELDS fields;
91 
92  if( comp->GetUnitCount() > 1 )
93  {
94  // Sadly, each unit of a component can have its own unique fields. This
95  // block finds the unit with the lowest number having a non blank field
96  // value and records it. Therefore user is best off setting fields
97  // into only the first unit. But this scavenger algorithm will find
98  // any non blank fields in all units and use the first non-blank field
99  // for each unique field name.
100 
101  wxString ref = comp->GetRef( aSheet );
102 
103  SCH_SHEET_LIST sheetList = m_schematic->GetSheets();
104  int minUnit = comp->GetUnit();
105 
106  for( unsigned i = 0; i < sheetList.size(); i++ )
107  {
108  for( auto item : sheetList[i].LastScreen()->Items().OfType( SCH_COMPONENT_T ) )
109  {
110  SCH_COMPONENT* comp2 = (SCH_COMPONENT*) item;
111 
112  wxString ref2 = comp2->GetRef( &sheetList[i] );
113 
114  if( ref2.CmpNoCase( ref ) != 0 )
115  continue;
116 
117  int unit = comp2->GetUnit();
118 
119  // The lowest unit number wins. User should only set fields in any one unit.
120  // remark: IsVoid() returns true for empty strings or the "~" string (empty field value)
121  if( !comp2->GetField( VALUE )->IsVoid()
122  && ( unit < minUnit || fields.value.IsEmpty() ) )
123  fields.value = comp2->GetField( VALUE )->GetText();
124 
125  if( !comp2->GetField( FOOTPRINT )->IsVoid()
126  && ( unit < minUnit || fields.footprint.IsEmpty() ) )
127  fields.footprint = comp2->GetField( FOOTPRINT )->GetText();
128 
129  if( !comp2->GetField( DATASHEET )->IsVoid()
130  && ( unit < minUnit || fields.datasheet.IsEmpty() ) )
131  fields.datasheet = comp2->GetField( DATASHEET )->GetText();
132 
133  for( int fldNdx = MANDATORY_FIELDS; fldNdx < comp2->GetFieldCount(); ++fldNdx )
134  {
135  SCH_FIELD* f = comp2->GetField( fldNdx );
136 
137  if( f->GetText().size()
138  && ( unit < minUnit || fields.f.count( f->GetName() ) == 0 ) )
139  {
140  fields.f[ f->GetName() ] = f->GetText();
141  }
142  }
143 
144  minUnit = std::min( unit, minUnit );
145  }
146  }
147 
148  }
149  else
150  {
151  fields.value = comp->GetField( VALUE )->GetText();
152  fields.footprint = comp->GetField( FOOTPRINT )->GetText();
153  fields.datasheet = comp->GetField( DATASHEET )->GetText();
154 
155  for( int fldNdx = MANDATORY_FIELDS; fldNdx < comp->GetFieldCount(); ++fldNdx )
156  {
157  SCH_FIELD* f = comp->GetField( fldNdx );
158 
159  if( f->GetText().size() )
160  fields.f[ f->GetName() ] = f->GetText();
161  }
162  }
163 
164  // Do not output field values blank in netlist:
165  if( fields.value.size() )
166  xcomp->AddChild( node( "value", fields.value ) );
167  else // value field always written in netlist
168  xcomp->AddChild( node( "value", "~" ) );
169 
170  if( fields.footprint.size() )
171  xcomp->AddChild( node( "footprint", fields.footprint ) );
172 
173  if( fields.datasheet.size() )
174  xcomp->AddChild( node( "datasheet", fields.datasheet ) );
175 
176  if( fields.f.size() )
177  {
178  XNODE* xfields;
179  xcomp->AddChild( xfields = node( "fields" ) );
180 
181  // non MANDATORY fields are output alphabetically
182  for( std::map< wxString, wxString >::const_iterator it = fields.f.begin();
183  it != fields.f.end(); ++it )
184  {
185  XNODE* xfield;
186  xfields->AddChild( xfield = node( "field", it->second ) );
187  xfield->AddAttribute( "name", it->first );
188  }
189  }
190 }
SCH_SHEET_LIST.
SCH_FIELD instances are attached to a component and provide a place for the component's value,...
Definition: sch_field.h:52
name of datasheet
SCH_SHEET_LIST GetSheets() const
Builds and returns an updated schematic hierarchy TODO: can this be cached?
Definition: schematic.h:99
XNODE * node(const wxString &aName, const wxString &aTextualContent=wxEmptyString)
Function node is a convenience function that creates a new XNODE with an optional textual child.
SCHEMATIC * m_schematic
The schematic we're generating a netlist for.
The first 4 are mandatory, and must be instantiated in SCH_COMPONENT and LIB_PART constructors.
int GetUnitCount() const
Return the number of units per package of the symbol.
Field Name Module PCB, i.e. "16DIP300".
bool IsVoid() const
Function IsVoid returns true if the field is either empty or holds "~".
Definition: sch_field.cpp:293
#define VALUE
int GetUnit() const
Holder for multi-unit component fields.
const wxString GetRef(const SCH_SHEET_PATH *aSheet, bool aIncludeUnit=false)
Return the reference for the given sheet path.
int GetFieldCount() const
Return the number of fields in this symbol.
XNODE holds an XML or S-expression element.
Definition: xnode.h:43
SCH_FIELD * GetField(int aFieldNdx)
Returns a field in this symbol.
wxString GetName(bool aUseDefaultName=true) const
Function GetName returns the field name.
Definition: sch_field.cpp:420
Schematic symbol object.
Definition: sch_component.h:88
std::map< wxString, wxString > f
virtual const wxString & GetText() const
Return the string associated with the text object.
Definition: eda_text.h:126

References DATASHEET, COMP_FIELDS::datasheet, COMP_FIELDS::f, FOOTPRINT, COMP_FIELDS::footprint, SCH_COMPONENT::GetField(), SCH_COMPONENT::GetFieldCount(), SCH_FIELD::GetName(), SCH_COMPONENT::GetRef(), SCHEMATIC::GetSheets(), EDA_TEXT::GetText(), SCH_COMPONENT::GetUnit(), SCH_COMPONENT::GetUnitCount(), SCH_FIELD::IsVoid(), NETLIST_EXPORTER::m_schematic, MANDATORY_FIELDS, node(), SCH_COMPONENT_T, VALUE, and COMP_FIELDS::value.

Referenced by makeComponents().

◆ findNextComponent()

SCH_COMPONENT * NETLIST_EXPORTER::findNextComponent ( EDA_ITEM aItem,
SCH_SHEET_PATH aSheetPath 
)
protectedinherited

Checks if the given component should be processed for netlisting.

Prevents processing multi-unit components more than once, etc.

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

Definition at line 75 of file netlist_exporter.cpp.

76 {
77  wxString ref;
78 
79  if( aItem->Type() != SCH_COMPONENT_T )
80  return nullptr;
81 
82  // found next component
83  SCH_COMPONENT* comp = (SCH_COMPONENT*) aItem;
84 
85  // Power symbols and other components which have the reference starting
86  // with "#" are not included in netlist (pseudo or virtual components)
87  ref = comp->GetRef( aSheetPath );
88 
89  if( ref[0] == wxChar( '#' ) )
90  return nullptr;
91 
92  // if( Component->m_FlagControlMulti == 1 )
93  // continue; /* yes */
94  // removed because with multiple instances of one schematic
95  // (several sheets pointing to 1 screen), this will be erroneously be
96  // toggled.
97 
98  if( !comp->GetPartRef() )
99  return nullptr;
100 
101  // If component is a "multi parts per package" type
102  if( comp->GetPartRef()->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 component entry.
110  m_LibParts.insert( comp->GetPartRef().get() ); // rejects non-unique pointers
111 
112  return comp;
113 }
bool Lookup(const wxString &aString)
Function Lookup returns true if aString already exists in the set, otherwise returns false and adds a...
UNIQUE_STRINGS m_ReferencesAlreadyFound
Used for "multi parts per package" components, avoids processing a lib component more than once.
std::set< LIB_PART *, LIB_PART_LESS_THAN > m_LibParts
unique library parts used. LIB_PART items are sorted by names
std::unique_ptr< LIB_PART > & GetPartRef()
const wxString GetRef(const SCH_SHEET_PATH *aSheet, bool aIncludeUnit=false)
Return the reference for the given sheet path.
Schematic symbol object.
Definition: sch_component.h:88
KICAD_T Type() const
Function Type()
Definition: base_struct.h:197

References SCH_COMPONENT::GetPartRef(), SCH_COMPONENT::GetRef(), UNIQUE_STRINGS::Lookup(), NETLIST_EXPORTER::m_LibParts, NETLIST_EXPORTER::m_ReferencesAlreadyFound, SCH_COMPONENT_T, and EDA_ITEM::Type().

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

◆ MakeCommandLine()

wxString NETLIST_EXPORTER::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 41 of file netlist_exporter.cpp.

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

Referenced by SCH_EDIT_FRAME::WriteNetListFile().

◆ makeComponents()

XNODE * NETLIST_EXPORTER_GENERIC::makeComponents ( )
protected

Function makeComponents.

Returns
XNODE* - returns a sub-tree holding all the schematic components.

Definition at line 193 of file netlist_exporter_generic.cpp.

194 {
195  XNODE* xcomps = node( "components" );
196 
198  m_LibParts.clear();
199 
200  SCH_SHEET_LIST sheetList = m_schematic->GetSheets();
201 
202  // Output is xml, so there is no reason to remove spaces from the field values.
203  // And XML element names need not be translated to various languages.
204 
205  for( unsigned i = 0; i < sheetList.size(); i++ )
206  {
207  SCH_SHEET_PATH sheet = sheetList[i];
208 
209  auto cmp =
210  [sheet]( SCH_COMPONENT* a, SCH_COMPONENT* b )
211  {
212  return ( UTIL::RefDesStringCompare( a->GetRef( &sheet ),
213  b->GetRef( &sheet ) ) < 0 );
214  };
215 
216  std::set<SCH_COMPONENT*, decltype( cmp )> ordered_components( cmp );
217 
218  for( auto item : sheetList[i].LastScreen()->Items().OfType( SCH_COMPONENT_T ) )
219  {
220  auto comp = static_cast<SCH_COMPONENT*>( item );
221  auto test = ordered_components.insert( comp );
222 
223  if( !test.second )
224  {
225  if( ( *( test.first ) )->GetUnit() > comp->GetUnit() )
226  {
227  ordered_components.erase( test.first );
228  ordered_components.insert( comp );
229  }
230  }
231  }
232 
233  for( auto item : ordered_components )
234  {
235  SCH_COMPONENT* comp = findNextComponent( item, &sheet );
236 
237  if( !comp )
238  continue;
239 
240  XNODE* xcomp; // current component being constructed
241 
242  // Output the component's elements in order of expected access frequency.
243  // This may not always look best, but it will allow faster execution
244  // under XSL processing systems which do sequential searching within
245  // an element.
246 
247  xcomps->AddChild( xcomp = node( "comp" ) );
248  xcomp->AddAttribute( "ref", comp->GetRef( &sheet ) );
249 
250  addComponentFields( xcomp, comp, &sheetList[i] );
251 
252  XNODE* xlibsource;
253  xcomp->AddChild( xlibsource = node( "libsource" ) );
254 
255  // "logical" library name, which is in anticipation of a better search
256  // algorithm for parts based on "logical_lib.part" and where logical_lib
257  // is merely the library name minus path and extension.
258  if( comp->GetPartRef() )
259  xlibsource->AddAttribute( "lib", comp->GetPartRef()->GetLibId().GetLibNickname() );
260 
261  // We only want the symbol name, not the full LIB_ID.
262  xlibsource->AddAttribute( "part", comp->GetLibId().GetLibItemName() );
263 
264  xlibsource->AddAttribute( "description", comp->GetDescription() );
265 
266  XNODE* xsheetpath;
267 
268  xcomp->AddChild( xsheetpath = node( "sheetpath" ) );
269  xsheetpath->AddAttribute( "names", sheet.PathHumanReadable() );
270  xsheetpath->AddAttribute( "tstamps", sheet.PathAsString() );
271  xcomp->AddChild( node( "tstamp", comp->m_Uuid.AsString() ) );
272  }
273  }
274 
275  return xcomps;
276 }
SCH_SHEET_LIST.
const UTF8 & GetLibItemName() const
Definition: lib_id.h:114
SCH_SHEET_LIST GetSheets() const
Builds and returns an updated schematic hierarchy TODO: can this be cached?
Definition: schematic.h:99
UNIQUE_STRINGS m_ReferencesAlreadyFound
Used for "multi parts per package" components, avoids processing a lib component more than once.
XNODE * node(const wxString &aName, const wxString &aTextualContent=wxEmptyString)
Function node is a convenience function that creates a new XNODE with an optional textual child.
SCHEMATIC * m_schematic
The schematic we're generating a netlist for.
wxString AsString() const
Definition: common.cpp:157
wxString PathAsString() const
Function PathAsString the path uses the time stamps which do not changes even when editing sheet para...
wxString GetDescription() const
Return information about the aliased parts.
void Clear()
Function Clear erases the record.
SCH_COMPONENT * findNextComponent(EDA_ITEM *aItem, SCH_SHEET_PATH *aSheetPath)
Checks if the given component should be processed for netlisting.
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::set< LIB_PART *, LIB_PART_LESS_THAN > m_LibParts
unique library parts used. LIB_PART items are sorted by names
void addComponentFields(XNODE *xcomp, SCH_COMPONENT *comp, SCH_SHEET_PATH *aSheet)
SCH_SHEET_PATH.
std::unique_ptr< LIB_PART > & GetPartRef()
const wxString GetRef(const SCH_SHEET_PATH *aSheet, bool aIncludeUnit=false)
Return the reference for the given sheet path.
const KIID m_Uuid
Definition: base_struct.h:166
XNODE holds an XML or S-expression element.
Definition: xnode.h:43
Schematic symbol object.
Definition: sch_component.h:88
wxString PathHumanReadable() const
Function PathHumanReadable returns the sheet path in a human readable form, i.e.
const LIB_ID & GetLibId() const

References addComponentFields(), KIID::AsString(), UNIQUE_STRINGS::Clear(), NETLIST_EXPORTER::findNextComponent(), SCH_COMPONENT::GetDescription(), SCH_COMPONENT::GetLibId(), LIB_ID::GetLibItemName(), SCH_COMPONENT::GetPartRef(), SCH_COMPONENT::GetRef(), SCHEMATIC::GetSheets(), NETLIST_EXPORTER::m_LibParts, NETLIST_EXPORTER::m_ReferencesAlreadyFound, NETLIST_EXPORTER::m_schematic, EDA_ITEM::m_Uuid, node(), SCH_SHEET_PATH::PathAsString(), SCH_SHEET_PATH::PathHumanReadable(), UTIL::RefDesStringCompare(), and SCH_COMPONENT_T.

Referenced by makeRoot().

◆ makeDesignHeader()

XNODE * NETLIST_EXPORTER_GENERIC::makeDesignHeader ( )
protected

Function makeDesignHeader fills out a project "design" header into an XML node.

Returns
XNODE* - the design header

Definition at line 279 of file netlist_exporter_generic.cpp.

280 {
281  SCH_SCREEN* screen;
282  XNODE* xdesign = node( "design" );
283  XNODE* xtitleBlock;
284  XNODE* xsheet;
285  XNODE* xcomment;
286  wxString sheetTxt;
287  wxFileName sourceFileName;
288 
289  // the root sheet is a special sheet, call it source
290  xdesign->AddChild( node( "source", m_schematic->GetFileName() ) );
291 
292  xdesign->AddChild( node( "date", DateAndTime() ) );
293 
294  // which Eeschema tool
295  xdesign->AddChild( node( "tool", wxString( "Eeschema " ) + GetBuildVersion() ) );
296 
297  /*
298  Export the sheets information
299  */
300  SCH_SHEET_LIST sheetList = m_schematic->GetSheets();
301 
302  for( unsigned i = 0; i < sheetList.size(); i++ )
303  {
304  screen = sheetList[i].LastScreen();
305 
306  xdesign->AddChild( xsheet = node( "sheet" ) );
307 
308  // get the string representation of the sheet index number.
309  // Note that sheet->GetIndex() is zero index base and we need to increment the
310  // number by one to make it human readable
311  sheetTxt.Printf( "%u", i + 1 );
312  xsheet->AddAttribute( "number", sheetTxt );
313  xsheet->AddAttribute( "name", sheetList[i].PathHumanReadable() );
314  xsheet->AddAttribute( "tstamps", sheetList[i].PathAsString() );
315 
316 
317  TITLE_BLOCK tb = screen->GetTitleBlock();
318 
319  xsheet->AddChild( xtitleBlock = node( "title_block" ) );
320 
321  xtitleBlock->AddChild( node( "title", tb.GetTitle() ) );
322  xtitleBlock->AddChild( node( "company", tb.GetCompany() ) );
323  xtitleBlock->AddChild( node( "rev", tb.GetRevision() ) );
324  xtitleBlock->AddChild( node( "date", tb.GetDate() ) );
325 
326  // We are going to remove the fileName directories.
327  sourceFileName = wxFileName( screen->GetFileName() );
328  xtitleBlock->AddChild( node( "source", sourceFileName.GetFullName() ) );
329 
330  xtitleBlock->AddChild( xcomment = node( "comment" ) );
331  xcomment->AddAttribute( "number", "1" );
332  xcomment->AddAttribute( "value", tb.GetComment( 0 ) );
333 
334  xtitleBlock->AddChild( xcomment = node( "comment" ) );
335  xcomment->AddAttribute( "number", "2" );
336  xcomment->AddAttribute( "value", tb.GetComment( 1 ) );
337 
338  xtitleBlock->AddChild( xcomment = node( "comment" ) );
339  xcomment->AddAttribute( "number", "3" );
340  xcomment->AddAttribute( "value", tb.GetComment( 2 ) );
341 
342  xtitleBlock->AddChild( xcomment = node( "comment" ) );
343  xcomment->AddAttribute( "number", "4" );
344  xcomment->AddAttribute( "value", tb.GetComment( 3 ) );
345 
346  xtitleBlock->AddChild( xcomment = node( "comment" ) );
347  xcomment->AddAttribute( "number", "5" );
348  xcomment->AddAttribute( "value", tb.GetComment( 4 ) );
349 
350  xtitleBlock->AddChild( xcomment = node( "comment" ) );
351  xcomment->AddAttribute( "number", "6" );
352  xcomment->AddAttribute( "value", tb.GetComment( 5 ) );
353 
354  xtitleBlock->AddChild( xcomment = node( "comment" ) );
355  xcomment->AddAttribute( "number", "7" );
356  xcomment->AddAttribute( "value", tb.GetComment( 6 ) );
357 
358  xtitleBlock->AddChild( xcomment = node( "comment" ) );
359  xcomment->AddAttribute( "number", "8" );
360  xcomment->AddAttribute( "value", tb.GetComment( 7 ) );
361 
362  xtitleBlock->AddChild( xcomment = node( "comment" ) );
363  xcomment->AddAttribute( "number", "9" );
364  xcomment->AddAttribute( "value", tb.GetComment( 8 ) );
365  }
366 
367  return xdesign;
368 }
SCH_SHEET_LIST.
const wxString & GetFileName() const
Definition: sch_screen.h:196
SCH_SHEET_LIST GetSheets() const
Builds and returns an updated schematic hierarchy TODO: can this be cached?
Definition: schematic.h:99
XNODE * node(const wxString &aName, const wxString &aTextualContent=wxEmptyString)
Function node is a convenience function that creates a new XNODE with an optional textual child.
SCHEMATIC * m_schematic
The schematic we're generating a netlist for.
const wxString & GetComment(int aIdx) const
Definition: title_block.h:110
const TITLE_BLOCK & GetTitleBlock() const
Definition: sch_screen.h:201
wxString GetFileName() const
Helper to retrieve the filename from the root sheet screen.
Definition: schematic.cpp:74
TITLE_BLOCK holds the information shown in the lower right corner of a plot, printout,...
Definition: title_block.h:40
wxString GetBuildVersion()
Get the full KiCad version string.
const wxString & GetRevision() const
Definition: title_block.h:89
const wxString & GetCompany() const
Definition: title_block.h:99
XNODE holds an XML or S-expression element.
Definition: xnode.h:43
const wxString & GetDate() const
Definition: title_block.h:79
const wxString & GetTitle() const
Definition: title_block.h:65
wxString DateAndTime()
Definition: string.cpp:379

References DateAndTime(), GetBuildVersion(), TITLE_BLOCK::GetComment(), TITLE_BLOCK::GetCompany(), TITLE_BLOCK::GetDate(), SCHEMATIC::GetFileName(), SCH_SCREEN::GetFileName(), TITLE_BLOCK::GetRevision(), SCHEMATIC::GetSheets(), TITLE_BLOCK::GetTitle(), SCH_SCREEN::GetTitleBlock(), NETLIST_EXPORTER::m_schematic, and node().

Referenced by makeRoot().

◆ makeLibParts()

XNODE * NETLIST_EXPORTER_GENERIC::makeLibParts ( )
protected

Function makeLibParts fills out an XML node with the unique library parts and returns it.

Returns
XNODE* - the library parts nodes

Definition at line 395 of file netlist_exporter_generic.cpp.

396 {
397  XNODE* xlibparts = node( "libparts" ); // auto_ptr
398 
399  LIB_PINS pinList;
400  LIB_FIELDS fieldList;
401 
402  m_libraries.clear();
403 
404  for( auto lcomp : m_LibParts )
405  {
406  wxString libNickname = lcomp->GetLibId().GetLibNickname();;
407 
408  // The library nickname will be empty if the cache library is used.
409  if( !libNickname.IsEmpty() )
410  m_libraries.insert( libNickname ); // inserts component's library if unique
411 
412  XNODE* xlibpart;
413  xlibparts->AddChild( xlibpart = node( "libpart" ) );
414  xlibpart->AddAttribute( "lib", libNickname );
415  xlibpart->AddAttribute( "part", lcomp->GetName() );
416 
417  //----- show the important properties -------------------------
418  if( !lcomp->GetDescription().IsEmpty() )
419  xlibpart->AddChild( node( "description", lcomp->GetDescription() ) );
420 
421  if( !lcomp->GetDocFileName().IsEmpty() )
422  xlibpart->AddChild( node( "docs", lcomp->GetDocFileName() ) );
423 
424  // Write the footprint list
425  if( lcomp->GetFootprints().GetCount() )
426  {
427  XNODE* xfootprints;
428  xlibpart->AddChild( xfootprints = node( "footprints" ) );
429 
430  for( unsigned i=0; i<lcomp->GetFootprints().GetCount(); ++i )
431  {
432  xfootprints->AddChild( node( "fp", lcomp->GetFootprints()[i] ) );
433  }
434  }
435 
436  //----- show the fields here ----------------------------------
437  fieldList.clear();
438  lcomp->GetFields( fieldList );
439 
440  XNODE* xfields;
441  xlibpart->AddChild( xfields = node( "fields" ) );
442 
443  for( unsigned i=0; i<fieldList.size(); ++i )
444  {
445  if( !fieldList[i].GetText().IsEmpty() )
446  {
447  XNODE* xfield;
448  xfields->AddChild( xfield = node( "field", fieldList[i].GetText() ) );
449  xfield->AddAttribute( "name", fieldList[i].GetCanonicalName() );
450  }
451  }
452 
453  //----- show the pins here ------------------------------------
454  pinList.clear();
455  lcomp->GetPins( pinList, 0, 0 );
456 
457  /* we must erase redundant Pins references in pinList
458  * These redundant pins exist because some pins
459  * are found more than one time when a component has
460  * multiple parts per package or has 2 representations (DeMorgan conversion)
461  * For instance, a 74ls00 has DeMorgan conversion, with different pin shapes,
462  * and therefore each pin appears 2 times in the list.
463  * Common pins (VCC, GND) can also be found more than once.
464  */
465  sort( pinList.begin(), pinList.end(), sortPinsByNumber );
466  for( int ii = 0; ii < (int)pinList.size()-1; ii++ )
467  {
468  if( pinList[ii]->GetNumber() == pinList[ii+1]->GetNumber() )
469  { // 2 pins have the same number, remove the redundant pin at index i+1
470  pinList.erase(pinList.begin() + ii + 1);
471  ii--;
472  }
473  }
474 
475  if( pinList.size() )
476  {
477  XNODE* pins;
478 
479  xlibpart->AddChild( pins = node( "pins" ) );
480  for( unsigned i=0; i<pinList.size(); ++i )
481  {
482  XNODE* pin;
483 
484  pins->AddChild( pin = node( "pin" ) );
485  pin->AddAttribute( "num", pinList[i]->GetNumber() );
486  pin->AddAttribute( "name", pinList[i]->GetName() );
487  pin->AddAttribute( "type", pinList[i]->GetCanonicalElectricalTypeName() );
488 
489  // caution: construction work site here, drive slowly
490  }
491  }
492  }
493 
494  return xlibparts;
495 }
XNODE * node(const wxString &aName, const wxString &aTextualContent=wxEmptyString)
Function node is a convenience function that creates a new XNODE with an optional textual child.
std::vector< LIB_PIN * > LIB_PINS
Helper for defining a list of pin object pointers.
Definition: lib_item.h:55
std::set< LIB_PART *, LIB_PART_LESS_THAN > m_LibParts
unique library parts used. LIB_PART items are sorted by names
std::set< wxString > m_libraries
Set of library nicknames.
wxString GetText(GRAPHIC_PINSHAPE aShape)
Definition: pin_shape.cpp:58
XNODE holds an XML or S-expression element.
Definition: xnode.h:43
std::vector< LIB_FIELD > LIB_FIELDS
Definition: lib_field.h:218
static bool sortPinsByNumber(LIB_PIN *aPin1, LIB_PIN *aPin2)

References GetText(), NETLIST_EXPORTER::m_LibParts, m_libraries, node(), and sortPinsByNumber().

Referenced by makeRoot().

◆ makeLibraries()

XNODE * NETLIST_EXPORTER_GENERIC::makeLibraries ( )
protected

Function makeLibraries fills 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 371 of file netlist_exporter_generic.cpp.

372 {
373  XNODE* xlibs = node( "libraries" ); // auto_ptr
374 
375  for( std::set<wxString>::iterator it = m_libraries.begin(); it!=m_libraries.end(); ++it )
376  {
377  wxString libNickname = *it;
378  XNODE* xlibrary;
379 
380  if( m_schematic->Prj().SchSymbolLibTable()->HasLibrary( libNickname ) )
381  {
382  xlibs->AddChild( xlibrary = node( "library" ) );
383  xlibrary->AddAttribute( "logical", libNickname );
384  xlibrary->AddChild( node(
385  "uri", m_schematic->Prj().SchSymbolLibTable()->GetFullURI( libNickname ) ) );
386  }
387 
388  // @todo: add more fun stuff here
389  }
390 
391  return xlibs;
392 }
XNODE * node(const wxString &aName, const wxString &aTextualContent=wxEmptyString)
Function node is a convenience function that creates a new XNODE with an optional textual child.
SCHEMATIC * m_schematic
The schematic we're generating a netlist for.
std::set< wxString > m_libraries
Set of library nicknames.
XNODE holds an XML or S-expression element.
Definition: xnode.h:43
PROJECT & Prj() const
Return a reference to the project this schematic is part of.
Definition: schematic.h:84

References m_libraries, NETLIST_EXPORTER::m_schematic, node(), and SCHEMATIC::Prj().

Referenced by makeRoot().

◆ makeListOfNets()

XNODE * NETLIST_EXPORTER_GENERIC::makeListOfNets ( )
protected

Function makeListOfNets fills out an XML node with a list of nets and returns it.

Returns
XNODE* - the list of nets nodes

Definition at line 498 of file netlist_exporter_generic.cpp.

499 {
500  XNODE* xnets = node( "nets" ); // auto_ptr if exceptions ever get used.
501  wxString netCodeTxt;
502  wxString netName;
503  wxString ref;
504 
505  XNODE* xnet = 0;
506 
507  /* output:
508  <net code="123" name="/cfcard.sch/WAIT#">
509  <node ref="R23" pin="1"/>
510  <node ref="U18" pin="12"/>
511  </net>
512  */
513 
514  int code = 0;
515 
516  for( const auto& it : m_schematic->ConnectionGraph()->GetNetMap() )
517  {
518  bool added = false;
519  wxString net_name = it.first.first;
520  auto subgraphs = it.second;
521 
522  // Code starts at 1
523  code++;
524 
525  XNODE* xnode;
526  std::vector<std::pair<SCH_PIN*, SCH_SHEET_PATH>> sorted_items;
527 
528  for( auto subgraph : subgraphs )
529  {
530  auto sheet = subgraph->m_sheet;
531 
532  for( auto item : subgraph->m_items )
533  if( item->Type() == SCH_PIN_T )
534  sorted_items.emplace_back(
535  std::make_pair( static_cast<SCH_PIN*>( item ), sheet ) );
536  }
537 
538  // Netlist ordering: Net name, then ref des, then pin name
539  std::sort( sorted_items.begin(), sorted_items.end(), [] ( auto a, auto b ) {
540  auto ref_a = a.first->GetParentComponent()->GetRef( &a.second );
541  auto ref_b = b.first->GetParentComponent()->GetRef( &b.second );
542 
543  if( ref_a == ref_b )
544  return a.first->GetNumber() < b.first->GetNumber();
545 
546  return ref_a < ref_b;
547  } );
548 
549  // Some duplicates can exist, for example on multi-unit parts with duplicated
550  // pins across units. If the user connects the pins on each unit, they will
551  // appear on separate subgraphs. Remove those here:
552  sorted_items.erase( std::unique( sorted_items.begin(), sorted_items.end(),
553  [] ( auto a, auto b ) {
554  auto ref_a = a.first->GetParentComponent()->GetRef( &a.second );
555  auto ref_b = b.first->GetParentComponent()->GetRef( &b.second );
556 
557  return ref_a == ref_b && a.first->GetNumber() == b.first->GetNumber();
558  } ), sorted_items.end() );
559 
560  for( const auto& pair : sorted_items )
561  {
562  SCH_PIN* pin = pair.first;
563  SCH_SHEET_PATH sheet = pair.second;
564 
565  auto refText = pin->GetParentComponent()->GetRef( &sheet );
566  const auto& pinText = pin->GetNumber();
567 
568  // Skip power symbols and virtual components
569  if( refText[0] == wxChar( '#' ) )
570  continue;
571 
572  if( !added )
573  {
574  xnets->AddChild( xnet = node( "net" ) );
575  netCodeTxt.Printf( "%d", code );
576  xnet->AddAttribute( "code", netCodeTxt );
577  xnet->AddAttribute( "name", net_name );
578 
579  added = true;
580  }
581 
582  xnet->AddChild( xnode = node( "node" ) );
583  xnode->AddAttribute( "ref", refText );
584  xnode->AddAttribute( "pin", pinText );
585 
586  wxString pinName;
587 
588  if( pin->GetName() != "~" ) // ~ is a char used to code empty strings in libs.
589  pinName = pin->GetName();
590 
591  if( !pinName.IsEmpty() )
592  xnode->AddAttribute( "pinfunction", pinName );
593  }
594  }
595 
596  return xnets;
597 }
const wxString & GetName() const
Definition: sch_pin.h:102
XNODE * node(const wxString &aName, const wxString &aTextualContent=wxEmptyString)
Function node is a convenience function that creates a new XNODE with an optional textual child.
SCHEMATIC * m_schematic
The schematic we're generating a netlist for.
CONNECTION_GRAPH * ConnectionGraph() const
Definition: schematic.h:139
const wxString & GetNumber() const
Definition: sch_pin.h:104
const NET_MAP & GetNetMap() const
SCH_SHEET_PATH.
const wxString GetRef(const SCH_SHEET_PATH *aSheet, bool aIncludeUnit=false)
Return the reference for the given sheet path.
XNODE holds an XML or S-expression element.
Definition: xnode.h:43
SCH_COMPONENT * GetParentComponent() const
Definition: sch_pin.cpp:64

References SCHEMATIC::ConnectionGraph(), SCH_PIN::GetName(), CONNECTION_GRAPH::GetNetMap(), SCH_PIN::GetNumber(), SCH_PIN::GetParentComponent(), SCH_COMPONENT::GetRef(), NETLIST_EXPORTER::m_schematic, node(), and SCH_PIN_T.

Referenced by makeRoot().

◆ makeRoot()

XNODE * NETLIST_EXPORTER_GENERIC::makeRoot ( int  aCtl = GNL_ALL)
protected

Function makeGenericRoot builds 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 50 of file netlist_exporter_generic.cpp.

51 {
52  XNODE* xroot = node( "export" );
53 
54  xroot->AddAttribute( "version", "D" );
55 
56  if( aCtl & GNL_HEADER )
57  // add the "design" header
58  xroot->AddChild( makeDesignHeader() );
59 
60  if( aCtl & GNL_COMPONENTS )
61  xroot->AddChild( makeComponents() );
62 
63  if( aCtl & GNL_PARTS )
64  xroot->AddChild( makeLibParts() );
65 
66  if( aCtl & GNL_LIBRARIES )
67  // must follow makeGenericLibParts()
68  xroot->AddChild( makeLibraries() );
69 
70  if( aCtl & GNL_NETS )
71  xroot->AddChild( makeListOfNets() );
72 
73  return xroot;
74 }
XNODE * makeComponents()
Function makeComponents.
XNODE * node(const wxString &aName, const wxString &aTextualContent=wxEmptyString)
Function node is a convenience function that creates a new XNODE with an optional textual child.
XNODE * makeDesignHeader()
Function makeDesignHeader fills out a project "design" header into an XML node.
XNODE holds an XML or S-expression element.
Definition: xnode.h:43
XNODE * makeLibraries()
Function makeLibraries fills out an XML node with a list of used libraries and returns it.
XNODE * makeListOfNets()
Function makeListOfNets fills out an XML node with a list of nets and returns it.
XNODE * makeLibParts()
Function makeLibParts fills out an XML node with the unique library parts and returns it.

References GNL_COMPONENTS, GNL_HEADER, GNL_LIBRARIES, GNL_NETS, GNL_PARTS, makeComponents(), makeDesignHeader(), makeLibParts(), makeLibraries(), makeListOfNets(), and node().

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

◆ node()

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

Function node is 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 600 of file netlist_exporter_generic.cpp.

601 {
602  XNODE* n = new XNODE( wxXML_ELEMENT_NODE, aName );
603 
604  if( aTextualContent.Len() > 0 ) // excludes wxEmptyString, the parameter's default value
605  n->AddChild( new XNODE( wxXML_TEXT_NODE, wxEmptyString, aTextualContent ) );
606 
607  return n;
608 }
XNODE holds an XML or S-expression element.
Definition: xnode.h:43

Referenced by addComponentFields(), makeComponents(), makeDesignHeader(), makeLibParts(), makeLibraries(), makeListOfNets(), and makeRoot().

◆ WriteNetlist()

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

Function WriteNetlist writes to specified output file.

Reimplemented from NETLIST_EXPORTER.

Reimplemented in NETLIST_EXPORTER_KICAD.

Definition at line 39 of file netlist_exporter_generic.cpp.

40 {
41  // output the XML format netlist.
42  wxXmlDocument xdoc;
43 
44  xdoc.SetRoot( makeRoot( GNL_ALL ) );
45 
46  return xdoc.Save( aOutFileName, 2 /* indent bug, today was ignored by wxXml lib */ );
47 }
XNODE * makeRoot(int aCtl=GNL_ALL)
Function makeGenericRoot builds the entire document tree for the generic export.
#define GNL_ALL

References GNL_ALL, and makeRoot().

Member Data Documentation

◆ m_LibParts

std::set<LIB_PART*, LIB_PART_LESS_THAN> NETLIST_EXPORTER::m_LibParts
protectedinherited

unique library parts used. LIB_PART items are sorted by names

Definition at line 96 of file netlist_exporter.h.

Referenced by NETLIST_EXPORTER::findNextComponent(), makeComponents(), makeLibParts(), and NETLIST_EXPORTER_PSPICE::ProcessNetlist().

◆ m_libraries

std::set< wxString > NETLIST_EXPORTER_GENERIC::m_libraries
private

Set of library nicknames.

Definition at line 63 of file netlist_exporter_generic.h.

Referenced by makeLibParts(), and makeLibraries().

◆ m_ReferencesAlreadyFound

UNIQUE_STRINGS NETLIST_EXPORTER::m_ReferencesAlreadyFound
protectedinherited

Used for "multi parts per package" components, avoids processing a lib component more than once.

Definition at line 93 of file netlist_exporter.h.

Referenced by NETLIST_EXPORTER::findNextComponent(), makeComponents(), NETLIST_EXPORTER_PSPICE::ProcessNetlist(), NETLIST_EXPORTER_ORCADPCB2::WriteNetlist(), and NETLIST_EXPORTER_CADSTAR::WriteNetlist().

◆ m_schematic


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