diff options
author | saurabhb17 | 2020-02-26 15:57:49 +0530 |
---|---|---|
committer | saurabhb17 | 2020-02-26 15:57:49 +0530 |
commit | aa35045840b78d3f48212db45da59a2e5c69b223 (patch) | |
tree | 6acee185a4dc19113fcbf0f9a3d6941085dedaf7 /eeschema/netlist_exporters | |
parent | 0db48f6533517ecebfd9f0693f89deca28408b76 (diff) | |
download | KiCad-eSim-aa35045840b78d3f48212db45da59a2e5c69b223.tar.gz KiCad-eSim-aa35045840b78d3f48212db45da59a2e5c69b223.tar.bz2 KiCad-eSim-aa35045840b78d3f48212db45da59a2e5c69b223.zip |
Added main execs
Diffstat (limited to 'eeschema/netlist_exporters')
-rw-r--r-- | eeschema/netlist_exporters/netlist_exporter.cpp | 364 | ||||
-rw-r--r-- | eeschema/netlist_exporters/netlist_exporter.h | 235 | ||||
-rw-r--r-- | eeschema/netlist_exporters/netlist_exporter_cadstar.cpp | 204 | ||||
-rw-r--r-- | eeschema/netlist_exporters/netlist_exporter_cadstar.h | 62 | ||||
-rw-r--r-- | eeschema/netlist_exporters/netlist_exporter_generic.cpp | 580 | ||||
-rw-r--r-- | eeschema/netlist_exporters/netlist_exporter_generic.h | 135 | ||||
-rw-r--r-- | eeschema/netlist_exporters/netlist_exporter_kicad.cpp | 77 | ||||
-rw-r--r-- | eeschema/netlist_exporters/netlist_exporter_kicad.h | 63 | ||||
-rw-r--r-- | eeschema/netlist_exporters/netlist_exporter_orcadpcb2.cpp | 145 | ||||
-rw-r--r-- | eeschema/netlist_exporters/netlist_exporter_orcadpcb2.h | 46 | ||||
-rw-r--r-- | eeschema/netlist_exporters/netlist_exporter_pspice.cpp | 358 | ||||
-rw-r--r-- | eeschema/netlist_exporters/netlist_exporter_pspice.h | 50 |
12 files changed, 2319 insertions, 0 deletions
diff --git a/eeschema/netlist_exporters/netlist_exporter.cpp b/eeschema/netlist_exporters/netlist_exporter.cpp new file mode 100644 index 0000000..62e39cc --- /dev/null +++ b/eeschema/netlist_exporters/netlist_exporter.cpp @@ -0,0 +1,364 @@ +/* + * This program source code file is part of KiCad, a free EDA CAD application. + * + * Copyright (C) 1992-2013 jp.charras at wanadoo.fr + * Copyright (C) 2013 SoftPLC Corporation, Dick Hollenbeck <dick@softplc.com> + * Copyright (C) 1992-2015 KiCad Developers, see AUTHORS.TXT for contributors. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, you may find one here: + * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html + * or you may search the http://www.gnu.org website for the version 2 license, + * or you may write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + */ + + +/** + * @file netlist_exporter.cpp + */ + +#include <fctsys.h> +#include <confirm.h> +#include <kicad_string.h> +#include <gestfich.h> +#include <pgm_base.h> + +#include <sch_reference_list.h> +#include <class_netlist_object.h> +#include <class_library.h> +#include <lib_pin.h> +#include <sch_component.h> +#include <sch_text.h> +#include <sch_sheet.h> + +#include <netlist.h> +#include <netlist_exporter.h> + + + +wxString NETLIST_EXPORTER::MakeCommandLine( const wxString& aFormatString, + const wxString& aTempfile, const wxString& aFinalFile, const wxString& aProjectPath ) +{ + // Expand format symbols in the command line: + // %B => base filename of selected output file, minus path and extension. + // %P => project directory name, without trailing '/' or '\'. + // %I => full filename of the input file (the intermediate net file). + // %O => complete filename and path (but without extension) of the user chosen output file. + + wxString ret = aFormatString; + wxFileName in = aTempfile; + wxFileName out = aFinalFile; + + ret.Replace( wxT( "%P" ), aProjectPath.GetData(), true ); + ret.Replace( wxT( "%B" ), out.GetName().GetData(), true ); + ret.Replace( wxT( "%I" ), in.GetFullPath().GetData(), true ); + ret.Replace( wxT( "%O" ), out.GetFullPath().GetData(), true ); + + // Use Unix like notation, which always works + ret.Replace( wxT( "\\" ), "/", true ); + + return ret; +} + + +void NETLIST_EXPORTER::sprintPinNetName( wxString& aResult, + const wxString& aNetNameFormat, NETLIST_OBJECT* aPin, + bool aUseNetcodeAsNetName ) +{ + int netcode = aPin->GetNet(); + + // Not wxString::Clear(), which would free memory. We want the worst + // case wxString memory to grow to avoid reallocation from within the + // caller's loop. + aResult.Empty(); + + if( netcode != 0 && aPin->GetConnectionType() == PAD_CONNECT ) + { + if( aUseNetcodeAsNetName ) + { + aResult.Printf( wxT("%d"), netcode ); + } + else + { + aResult = aPin->GetNetName(); + + if( aResult.IsEmpty() ) // No net name: give a name from net code + aResult.Printf( aNetNameFormat.GetData(), netcode ); + } + } +} + + +SCH_COMPONENT* NETLIST_EXPORTER::findNextComponent( EDA_ITEM* aItem, SCH_SHEET_PATH* aSheetPath ) +{ + wxString ref; + + // continue searching from the middle of a linked list (the draw list) + for( ; aItem; aItem = aItem->Next() ) + { + if( aItem->Type() != SCH_COMPONENT_T ) + continue; + + // found next component + SCH_COMPONENT* comp = (SCH_COMPONENT*) aItem; + + // Power symbols and other components which have the reference starting + // with "#" are not included in netlist (pseudo or virtual components) + ref = comp->GetRef( aSheetPath ); + if( ref[0] == wxChar( '#' ) ) + continue; + + // if( Component->m_FlagControlMulti == 1 ) + // continue; /* yes */ + // removed because with multiple instances of one schematic + // (several sheets pointing to 1 screen), this will be erroneously be + // toggled. + + LIB_PART* part = m_libs->FindLibPart( comp->GetPartName() ); + if( !part ) + continue; + + // If component is a "multi parts per package" type + if( part->GetUnitCount() > 1 ) + { + // test if this reference has already been processed, and if so skip + if( m_ReferencesAlreadyFound.Lookup( ref ) ) + continue; + } + + // record the usage of this library component entry. + m_LibParts.insert( part ); // rejects non-unique pointers + + return comp; + } + + return NULL; +} + + +/// Comparison routine for sorting by pin numbers. +static bool sortPinsByNum( NETLIST_OBJECT* aPin1, NETLIST_OBJECT* aPin2 ) +{ + // return "lhs < rhs" + return RefDesStringCompare( aPin1->GetPinNumText(), aPin2->GetPinNumText() ) < 0; +} + + +SCH_COMPONENT* NETLIST_EXPORTER::findNextComponentAndCreatePinList( EDA_ITEM* aItem, + SCH_SHEET_PATH* aSheetPath ) +{ + wxString ref; + + m_SortedComponentPinList.clear(); + + // continue searching from the middle of a linked list (the draw list) + for( ; aItem; aItem = aItem->Next() ) + { + if( aItem->Type() != SCH_COMPONENT_T ) + continue; + + // found next component + SCH_COMPONENT* comp = (SCH_COMPONENT*) aItem; + + // Power symbols and other components which have the reference starting + // with "#" are not included in netlist (pseudo or virtual components) + ref = comp->GetRef( aSheetPath ); + + if( ref[0] == wxChar( '#' ) ) + continue; + + // if( Component->m_FlagControlMulti == 1 ) + // continue; /* yes */ + // removed because with multiple instances of one schematic + // (several sheets pointing to 1 screen), this will be erroneously be + // toggled. + + LIB_PART* part = m_libs->FindLibPart( comp->GetPartName() ); + + if( !part ) + continue; + + // If component is a "multi parts per package" type + if( part->GetUnitCount() > 1 ) + { + // test if this reference has already been processed, and if so skip + if( m_ReferencesAlreadyFound.Lookup( ref ) ) + continue; + + // Collect all pins for this reference designator by searching + // the entire design for other parts with the same reference designator. + // This is only done once, it would be too expensive otherwise. + findAllInstancesOfComponent( comp, part, aSheetPath ); + } + + else // entry->GetUnitCount() <= 1 means one part per package + { + LIB_PINS pins; // constructed once here + + part->GetPins( pins, comp->GetUnitSelection( aSheetPath ), comp->GetConvert() ); + + for( size_t i = 0; i < pins.size(); i++ ) + { + LIB_PIN* pin = pins[i]; + + wxASSERT( pin->Type() == LIB_PIN_T ); + + addPinToComponentPinList( comp, aSheetPath, pin ); + } + } + + // Sort pins in m_SortedComponentPinList by pin number + sort( m_SortedComponentPinList.begin(), + m_SortedComponentPinList.end(), sortPinsByNum ); + + // Remove duplicate Pins in m_SortedComponentPinList + eraseDuplicatePins( ); + + // record the usage of this library component entry. + m_LibParts.insert( part ); // rejects non-unique pointers + + return comp; + } + + return NULL; +} + +bool NETLIST_EXPORTER::addPinToComponentPinList( SCH_COMPONENT* aComponent, + SCH_SHEET_PATH* aSheetPath, LIB_PIN* aPin ) +{ + // Search the PIN description for Pin in g_NetObjectslist + for( unsigned ii = 0; ii < m_masterList->size(); ii++ ) + { + NETLIST_OBJECT* pin = m_masterList->GetItem( ii ); + + if( pin->m_Type != NET_PIN ) + continue; + + if( pin->m_Link != aComponent ) + continue; + + if( pin->m_PinNum != aPin->GetNumber() ) + continue; + + // most expensive test at the end. + if( pin->m_SheetPath != *aSheetPath ) + continue; + + m_SortedComponentPinList.push_back( pin ); + + if( m_SortedComponentPinList.size() >= MAXPIN ) + { + // Log message for Internal error + DisplayError( NULL, wxT( "addPinToComponentPinList err: MAXPIN reached" ) ); + } + + return true; // we're done, we appended. + } + + return false; +} + + +void NETLIST_EXPORTER::eraseDuplicatePins() +{ + for( unsigned ii = 0; ii < m_SortedComponentPinList.size(); ii++ ) + { + if( m_SortedComponentPinList[ii] == NULL ) /* already deleted */ + continue; + + /* Search for duplicated pins + * If found, remove duplicates. The priority is to keep connected pins + * and remove unconnected + * - So this allows (for instance when using multi op amps per package + * - to connect only one op amp to power + * Because the pin list is sorted by m_PinNum value, duplicated pins + * are necessary successive in list + */ + int idxref = ii; + for( unsigned jj = ii + 1; jj < m_SortedComponentPinList.size(); jj++ ) + { + if( m_SortedComponentPinList[jj] == NULL ) // Already removed + continue; + + // if other pin num, stop search, + // because all pins having the same number are consecutive in list. + if( m_SortedComponentPinList[idxref]->m_PinNum != m_SortedComponentPinList[jj]->m_PinNum ) + break; + + if( m_SortedComponentPinList[idxref]->GetConnectionType() == PAD_CONNECT ) + { + m_SortedComponentPinList[jj]->m_Flag = 1; + m_SortedComponentPinList[jj] = NULL; + } + else /* the reference pin is not connected: remove this pin if the + * other pin is connected */ + { + if( m_SortedComponentPinList[jj]->GetConnectionType() == PAD_CONNECT ) + { + m_SortedComponentPinList[idxref]->m_Flag = 1; + m_SortedComponentPinList[idxref] = NULL; + idxref = jj; + } + else // the 2 pins are not connected: remove the tested pin, + { // and continue ... + m_SortedComponentPinList[jj]->m_Flag = 1; + m_SortedComponentPinList[jj] = NULL; + } + } + } + } +} + + +void NETLIST_EXPORTER::findAllInstancesOfComponent( SCH_COMPONENT* aComponent, + LIB_PART* aEntry, + SCH_SHEET_PATH* aSheetPath ) +{ + wxString ref = aComponent->GetRef( aSheetPath ); + wxString ref2; + + SCH_SHEET_LIST sheetList; + + for( SCH_SHEET_PATH* sheet = sheetList.GetFirst(); sheet; sheet = sheetList.GetNext() ) + { + for( EDA_ITEM* item = sheet->LastDrawList(); item; item = item->Next() ) + { + if( item->Type() != SCH_COMPONENT_T ) + continue; + + SCH_COMPONENT* comp2 = (SCH_COMPONENT*) item; + + ref2 = comp2->GetRef( sheet ); + if( ref2.CmpNoCase( ref ) != 0 ) + continue; + + int unit2 = comp2->GetUnitSelection( sheet ); // slow + + for( LIB_PIN* pin = aEntry->GetNextPin(); pin; pin = aEntry->GetNextPin( pin ) ) + { + wxASSERT( pin->Type() == LIB_PIN_T ); + + if( pin->GetUnit() && pin->GetUnit() != unit2 ) + continue; + + if( pin->GetConvert() && pin->GetConvert() != comp2->GetConvert() ) + continue; + + // A suitable pin is found: add it to the current list + addPinToComponentPinList( comp2, sheet, pin ); + } + } + } +} + diff --git a/eeschema/netlist_exporters/netlist_exporter.h b/eeschema/netlist_exporters/netlist_exporter.h new file mode 100644 index 0000000..dc3ebb0 --- /dev/null +++ b/eeschema/netlist_exporters/netlist_exporter.h @@ -0,0 +1,235 @@ +/* + * This program source code file is part of KiCad, a free EDA CAD application. + * + * Copyright (C) 1992-2013 jp.charras at wanadoo.fr + * Copyright (C) 2013 SoftPLC Corporation, Dick Hollenbeck <dick@softplc.com> + * Copyright (C) 1992-2015 KiCad Developers + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, you may find one here: + * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html + * or you may search the http://www.gnu.org website for the version 2 license, + * or you may write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#ifndef NETLIST_EXPORTER_H +#define NETLIST_EXPORTER_H + +#include <kicad_string.h> + +#include <class_libentry.h> +#include <class_netlist_object.h> +#include <lib_pin.h> +#include <sch_component.h> +#include <sch_text.h> +#include <sch_sheet.h> + +/** + * Class UNIQUE_STRINGS + * tracks unique wxStrings and is useful in telling if a string + * has been seen before. + */ +class UNIQUE_STRINGS +{ + std::set<wxString> m_set; ///< set of wxStrings already found + + typedef std::set<wxString>::iterator us_iterator; + +public: + /** + * Function Clear + * erases the record. + */ + void Clear() { m_set.clear(); } + + /** + * Function Lookup + * returns true if \a aString already exists in the set, otherwise returns + * false and adds \a aString to the set for next time. + */ + bool Lookup( const wxString& aString ) + { + std::pair<us_iterator, bool> pair = m_set.insert( aString ); + + return !pair.second; + } +}; + +/** + * Struct LIB_PART_LESS_THAN + * is used by std:set<LIB_PART*> instantiation which uses LIB_PART name as its key. + */ +struct LIB_PART_LESS_THAN +{ + // a "less than" test on two LIB_PARTs (.m_name wxStrings) + bool operator()( LIB_PART* const& libpart1, LIB_PART* const& libpart2 ) const + { + // Use case specific GetName() wxString compare + return libpart1->GetName().Cmp( libpart2->GetName() ) < 0; + } +}; + +/** + * Class NETLIST_EXPORTER + * is a abstract class used for the netlist exporters that eeschema supports. + */ +class NETLIST_EXPORTER +{ +protected: + NETLIST_OBJECT_LIST* m_masterList; /// yes ownership, connected items flat list + + PART_LIBS* m_libs; /// no ownership + + /// Used to temporary store and filter the list of pins of a schematic component + /// when generating schematic component data in netlist (comp section). No ownership + /// of members. + NETLIST_OBJECTS m_SortedComponentPinList; + + /// Used for "multi parts per package" components, + /// avoids processing a lib component more than once. + UNIQUE_STRINGS m_ReferencesAlreadyFound; + + /// unique library parts used. LIB_PART items are sorted by names + std::set<LIB_PART*, LIB_PART_LESS_THAN> m_LibParts; + + // share a code generated std::set<void*> to reduce code volume + std::set<void*> m_Libraries; ///< unique libraries used + + /** + * Function sprintPinNetName + * formats the net name for \a aPin using \a aNetNameFormat into \a aResult. + * <p> + * Net name is: + * <ul> + * <li> "?" if pin not connected + * <li> "netname" for global net (like gnd, vcc .. + * <li> "/path/netname" for the usual nets + * </ul> + * if aUseNetcodeAsNetName is true, the net name is just the net code (SPICE only) + */ + static void sprintPinNetName( wxString& aResult, const wxString& aNetNameFormat, + NETLIST_OBJECT* aPin, bool aUseNetcodeAsNetName = false ); + + /** + * Function findNextComponentAndCreatePinList + * finds a component from the DrawList and builds + * its pin list in m_SortedComponentPinList. This list is sorted by pin num. + * the component is the next actual component after aItem + * (power symbols and virtual components that have their reference starting by '#'are skipped). + */ + SCH_COMPONENT* findNextComponentAndCreatePinList( EDA_ITEM* aItem, SCH_SHEET_PATH* aSheetPath ); + + SCH_COMPONENT* findNextComponent( EDA_ITEM* aItem, SCH_SHEET_PATH* aSheetPath ); + + + /** + * Function eraseDuplicatePins + * erase duplicate Pins from m_SortedComponentPinList (i.e. set pointer in this list to NULL). + * (This is a list of pins found in the whole schematic, for a single + * component.) These duplicate pins were put in list because some pins (powers... ) + * are found more than one time when we have a multiple parts per package + * component. 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 + */ + void eraseDuplicatePins(); + + /** + * Function addPinToComponentPinList + * adds a new pin description to the pin list m_SortedComponentPinList. + * A pin description is a pointer to the corresponding structure + * created by BuildNetList() in the table g_NetObjectslist. + */ + bool addPinToComponentPinList( SCH_COMPONENT* Component, + SCH_SHEET_PATH* sheet, + LIB_PIN* PinEntry ); + + /** + * Function findAllInstancesOfComponent + * is used for "multiple parts per package" components. + * <p> + * Search the entire design for all instances of \a aComponent based on + * matching reference designator, and for each part, add all its pins + * to the temporary sorted pin list. + */ + void findAllInstancesOfComponent( SCH_COMPONENT* aComponent, + LIB_PART* aEntry, + SCH_SHEET_PATH* aSheetPath ); + +public: + + /** + * Constructor + * @param aMasterList we take ownership of this here. + */ + NETLIST_EXPORTER( NETLIST_OBJECT_LIST* aMasterList, PART_LIBS* aLibs ) : + m_masterList( aMasterList ), + m_libs( aLibs ) + { + } + + virtual ~NETLIST_EXPORTER() + { + delete m_masterList; // I own the list itself in this instance. + } + + /** + * Function WriteNetlist + * writes to specified output file + */ + virtual bool WriteNetlist( const wxString& aOutFileName, unsigned aNetlistOptions ) + { + return false; + } + + /** + * 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. + * + * @param aFormatString holds: + * <ul> + * <li>the name of the external program + * <li>any options needed by that program + * <li>formatting sequences, see below. + * </ul> + * + * @param aTempfile is the name of an input file to the + * external program. + * @param aFinalFile is the name of an output file that + * the user expects. + * @param aProjectDirectory is used for %P replacement, it should omit + * the trailing '/'. + * + * <p> Supported formatting sequences and their meaning: + * <ul> + * <li> %B => base filename of selected output file, minus + * path and extension. + * <li> %I => complete filename and path of the temporary + * input file. + * <li> %O => complete filename and path of the user chosen + * output file. + * <li> %P => project directory, without name and without trailing '/' + * </ul> + */ + static wxString MakeCommandLine( const wxString& aFormatString, + const wxString& aTempfile, const wxString& aFinalFile, + const wxString& aProjectDirectory + ); +}; + +#endif diff --git a/eeschema/netlist_exporters/netlist_exporter_cadstar.cpp b/eeschema/netlist_exporters/netlist_exporter_cadstar.cpp new file mode 100644 index 0000000..2b5b7fb --- /dev/null +++ b/eeschema/netlist_exporters/netlist_exporter_cadstar.cpp @@ -0,0 +1,204 @@ +/* + * This program source code file is part of KiCad, a free EDA CAD application. + * + * Copyright (C) 1992-2013 jp.charras at wanadoo.fr + * Copyright (C) 2013 SoftPLC Corporation, Dick Hollenbeck <dick@softplc.com> + * Copyright (C) 1992-2015 KiCad Developers, see AUTHORS.TXT for contributors. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, you may find one here: + * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html + * or you may search the http://www.gnu.org website for the version 2 license, + * or you may write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#include <fctsys.h> +#include <build_version.h> +#include <confirm.h> + +#include <schframe.h> +#include <sch_reference_list.h> +#include <class_netlist_object.h> + +#include "netlist_exporter_cadstar.h" + +/* Generate CADSTAR net list. */ +static wxString StartLine( wxT( "." ) ); + +bool NETLIST_EXPORTER_CADSTAR::WriteNetlist( const wxString& aOutFileName, unsigned aNetlistOptions ) +{ + (void)aNetlistOptions; //unused + int ret = 0; + FILE* f = NULL; + + if( ( f = wxFopen( aOutFileName, wxT( "wt" ) ) ) == NULL ) + { + wxString msg; + msg.Printf( _( "Failed to create file '%s'" ), + GetChars( aOutFileName ) ); + DisplayError( NULL, msg ); + return false; + } + + wxString StartCmpDesc = StartLine + wxT( "ADD_COM" ); + wxString msg; + SCH_SHEET_PATH* sheet; + EDA_ITEM* DrawList; + SCH_COMPONENT* component; + wxString title = wxT( "Eeschema " ) + GetBuildVersion(); + + ret |= fprintf( f, "%sHEA\n", TO_UTF8( StartLine ) ); + ret |= fprintf( f, "%sTIM %s\n", TO_UTF8( StartLine ), TO_UTF8( DateAndTime() ) ); + ret |= fprintf( f, "%sAPP ", TO_UTF8( StartLine ) ); + ret |= fprintf( f, "\"%s\"\n", TO_UTF8( title ) ); + ret |= fprintf( f, "\n" ); + + // Prepare list of nets generation + for( unsigned ii = 0; ii < m_masterList->size(); ii++ ) + m_masterList->GetItem( ii )->m_Flag = 0; + + // Create netlist module section + m_ReferencesAlreadyFound.Clear(); + + SCH_SHEET_LIST SheetList; + + for( sheet = SheetList.GetFirst(); sheet != NULL; sheet = SheetList.GetNext() ) + { + for( DrawList = sheet->LastDrawList(); DrawList != NULL; DrawList = DrawList->Next() ) + { + DrawList = component = findNextComponentAndCreatePinList( DrawList, sheet ); + + if( component == NULL ) + break; + + /* + doing nothing with footprint + if( !component->GetField( FOOTPRINT )->IsVoid() ) + { + footprint = component->GetField( FOOTPRINT )->m_Text; + footprint.Replace( wxT( " " ), wxT( "_" ) ); + } + else + footprint = wxT( "$noname" ); + */ + + msg = component->GetRef( sheet ); + ret |= fprintf( f, "%s ", TO_UTF8( StartCmpDesc ) ); + ret |= fprintf( f, "%s", TO_UTF8( msg ) ); + + msg = component->GetField( VALUE )->GetText(); + msg.Replace( wxT( " " ), wxT( "_" ) ); + ret |= fprintf( f, " \"%s\"", TO_UTF8( msg ) ); + ret |= fprintf( f, "\n" ); + } + } + + ret |= fprintf( f, "\n" ); + + m_SortedComponentPinList.clear(); + + if( ! writeListOfNets( f ) ) + ret = -1; // set error + + ret |= fprintf( f, "\n%sEND\n", TO_UTF8( StartLine ) ); + + fclose( f ); + + return ret >= 0; +} + + +bool NETLIST_EXPORTER_CADSTAR::writeListOfNets( FILE* f ) +{ + int ret = 0; + wxString InitNetDesc = StartLine + wxT( "ADD_TER" ); + wxString StartNetDesc = StartLine + wxT( "TER" ); + wxString netcodeName, InitNetDescLine; + unsigned ii; + int print_ter = 0; + int NetCode, lastNetCode = -1; + SCH_COMPONENT* Cmp; + wxString netName; + + for( ii = 0; ii < m_masterList->size(); ii++ ) + { + NETLIST_OBJECT* nitem = m_masterList->GetItem( ii ); + + // Get the NetName of the current net : + if( ( NetCode = nitem->GetNet() ) != lastNetCode ) + { + netName = nitem->GetNetName(); + netcodeName = wxT( "\"" ); + + if( !netName.IsEmpty() ) + netcodeName << netName; + else // this net has no name: create a default name $<net number> + netcodeName << wxT( "$" ) << NetCode; + + netcodeName += wxT( "\"" ); + lastNetCode = NetCode; + print_ter = 0; + } + + + if( nitem->m_Type != NET_PIN ) + continue; + + if( nitem->m_Flag != 0 ) + continue; + + Cmp = nitem->GetComponentParent(); + wxString refstr = Cmp->GetRef( &nitem->m_SheetPath ); + if( refstr[0] == '#' ) + continue; // Power supply symbols. + + switch( print_ter ) + { + case 0: + { + char buf[5]; + wxString str_pinnum; + strncpy( buf, (char*) &nitem->m_PinNum, 4 ); + buf[4] = 0; + str_pinnum = FROM_UTF8( buf ); + InitNetDescLine.Printf( wxT( "\n%s %s %.4s %s" ), + GetChars( InitNetDesc ), + GetChars( refstr ), + GetChars( str_pinnum ), + GetChars( netcodeName ) ); + } + print_ter++; + break; + + case 1: + ret |= fprintf( f, "%s\n", TO_UTF8( InitNetDescLine ) ); + ret |= fprintf( f, "%s %s %.4s\n", + TO_UTF8( StartNetDesc ), + TO_UTF8( refstr ), + (char*) &nitem->m_PinNum ); + print_ter++; + break; + + default: + ret |= fprintf( f, " %s %.4s\n", + TO_UTF8( refstr ), + (char*) &nitem->m_PinNum ); + break; + } + + nitem->m_Flag = 1; + } + + return ret >= 0; +} diff --git a/eeschema/netlist_exporters/netlist_exporter_cadstar.h b/eeschema/netlist_exporters/netlist_exporter_cadstar.h new file mode 100644 index 0000000..909e1bd --- /dev/null +++ b/eeschema/netlist_exporters/netlist_exporter_cadstar.h @@ -0,0 +1,62 @@ +/* + * This program source code file is part of KiCad, a free EDA CAD application. + * + * Copyright (C) 1992-2013 jp.charras at wanadoo.fr + * Copyright (C) 2013 SoftPLC Corporation, Dick Hollenbeck <dick@softplc.com> + * Copyright (C) 1992-2015 KiCad Developers + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, you may find one here: + * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html + * or you may search the http://www.gnu.org website for the version 2 license, + * or you may write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#ifndef NETLIST_EXPORTER_CADSTAR_H +#define NETLIST_EXPORTER_CADSTAR_H + +#include "netlist_exporter.h" + +/** + * Class NETLIST_EXPORTER_CADSTAR + * generates a netlist compatible with CADSTAR + */ +class NETLIST_EXPORTER_CADSTAR : public NETLIST_EXPORTER +{ + /** + * Function writeListOfNetsCADSTAR + * writes a net list (ranked by Netcode), and pins connected to it. + * <p> + * Format: + * - ADD_TER RR2 6 \"$42\" + * - B U1 100 + * - 6 CA + * </p> + */ + bool writeListOfNets( FILE* f ); + +public: + NETLIST_EXPORTER_CADSTAR( NETLIST_OBJECT_LIST* aMasterList, PART_LIBS* aLibs ) : + NETLIST_EXPORTER( aMasterList, aLibs ) + { + } + + /** + * Function WriteList + * writes to specified output file + */ + bool WriteNetlist( const wxString& aOutFileName, unsigned aNetlistOptions ); +}; + +#endif diff --git a/eeschema/netlist_exporters/netlist_exporter_generic.cpp b/eeschema/netlist_exporters/netlist_exporter_generic.cpp new file mode 100644 index 0000000..921e0fc --- /dev/null +++ b/eeschema/netlist_exporters/netlist_exporter_generic.cpp @@ -0,0 +1,580 @@ +/* + * This program source code file is part of KiCad, a free EDA CAD application. + * + * Copyright (C) 1992-2013 jp.charras at wanadoo.fr + * Copyright (C) 2013 SoftPLC Corporation, Dick Hollenbeck <dick@softplc.com> + * Copyright (C) 1992-2015 KiCad Developers, see AUTHORS.TXT for contributors. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, you may find one here: + * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html + * or you may search the http://www.gnu.org website for the version 2 license, + * or you may write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#include <build_version.h> +#include <sch_base_frame.h> +#include <class_library.h> + +#include <schframe.h> +#include "netlist_exporter_generic.h" + +static bool sortPinsByNumber( LIB_PIN* aPin1, LIB_PIN* aPin2 ); + +bool NETLIST_EXPORTER_GENERIC::WriteNetlist( const wxString& aOutFileName, unsigned aNetlistOptions ) +{ + // Prepare list of nets generation + for( unsigned ii = 0; ii < m_masterList->size(); ii++ ) + m_masterList->GetItem( ii )->m_Flag = 0; + + // output the XML format netlist. + wxXmlDocument xdoc; + + xdoc.SetRoot( makeRoot( GNL_ALL ) ); + + return xdoc.Save( aOutFileName, 2 /* indent bug, today was ignored by wxXml lib */ ); +} + + +XNODE* NETLIST_EXPORTER_GENERIC::makeRoot( int aCtl ) +{ + XNODE* xroot = node( wxT( "export" ) ); + + xroot->AddAttribute( wxT( "version" ), wxT( "D" ) ); + + if( aCtl & GNL_HEADER ) + // add the "design" header + xroot->AddChild( makeDesignHeader() ); + + if( aCtl & GNL_COMPONENTS ) + xroot->AddChild( makeComponents() ); + + if( aCtl & GNL_PARTS ) + xroot->AddChild( makeLibParts() ); + + if( aCtl & GNL_LIBRARIES ) + // must follow makeGenericLibParts() + xroot->AddChild( makeLibraries() ); + + if( aCtl & GNL_NETS ) + xroot->AddChild( makeListOfNets() ); + + return xroot; +} + + +XNODE* NETLIST_EXPORTER_GENERIC::makeComponents() +{ + XNODE* xcomps = node( wxT( "components" ) ); + + wxString timeStamp; + + // some strings we need many times, but don't want to construct more + // than once for performance. These are used within loops so the + // enclosing wxString constructor would fire on each loop iteration if + // they were in a nested scope. + + // these are actually constructor invocations, not assignments as it appears: + wxString sFields = wxT( "fields" ); + wxString sField = wxT( "field" ); + wxString sComponent = wxT( "comp" ); // use "part" ? + wxString sName = wxT( "name" ); + wxString sRef = wxT( "ref" ); + wxString sPins = wxT( "pins" ); + wxString sPin = wxT( "pin" ); + wxString sValue = wxT( "value" ); + wxString sSheetPath = wxT( "sheetpath" ); + wxString sFootprint = wxT( "footprint" ); + wxString sDatasheet = wxT( "datasheet" ); + wxString sTStamp = wxT( "tstamp" ); + wxString sTStamps = wxT( "tstamps" ); + wxString sTSFmt = wxT( "%8.8lX" ); // comp->m_TimeStamp + wxString sLibSource = wxT( "libsource" ); + wxString sLibPart = wxT( "libpart" ); + wxString sLib = wxT( "lib" ); + wxString sPart = wxT( "part" ); + wxString sNames = wxT( "names" ); + + m_ReferencesAlreadyFound.Clear(); + + SCH_SHEET_LIST sheetList; + + // Output is xml, so there is no reason to remove spaces from the field values. + // And XML element names need not be translated to various languages. + + for( SCH_SHEET_PATH* path = sheetList.GetFirst(); path; path = sheetList.GetNext() ) + { + for( EDA_ITEM* schItem = path->LastDrawList(); schItem; schItem = schItem->Next() ) + { + SCH_COMPONENT* comp = findNextComponentAndCreatePinList( schItem, path ); + if( !comp ) + break; // No component left + + schItem = comp; + + XNODE* xcomp; // current component being constructed + + // Output the component's elements in order of expected access frequency. + // This may not always look best, but it will allow faster execution + // under XSL processing systems which do sequential searching within + // an element. + + xcomps->AddChild( xcomp = node( sComponent ) ); + xcomp->AddAttribute( sRef, comp->GetRef( path ) ); + + xcomp->AddChild( node( sValue, comp->GetField( VALUE )->GetText() ) ); + + if( !comp->GetField( FOOTPRINT )->IsVoid() ) + xcomp->AddChild( node( sFootprint, comp->GetField( FOOTPRINT )->GetText() ) ); + + if( !comp->GetField( DATASHEET )->IsVoid() ) + xcomp->AddChild( node( sDatasheet, comp->GetField( DATASHEET )->GetText() ) ); + + // Export all user defined fields within the component, + // which start at field index MANDATORY_FIELDS. Only output the <fields> + // container element if there are any <field>s. + if( comp->GetFieldCount() > MANDATORY_FIELDS ) + { + XNODE* xfields; + xcomp->AddChild( xfields = node( sFields ) ); + + for( int fldNdx = MANDATORY_FIELDS; fldNdx < comp->GetFieldCount(); ++fldNdx ) + { + SCH_FIELD* f = comp->GetField( fldNdx ); + + // only output a field if non empty and not just "~" + if( !f->IsVoid() ) + { + XNODE* xfield; + xfields->AddChild( xfield = node( sField, f->GetText() ) ); + xfield->AddAttribute( sName, f->GetName() ); + } + } + } + + XNODE* xlibsource; + xcomp->AddChild( xlibsource = node( sLibSource ) ); + + // "logical" library name, which is in anticipation of a better search + // algorithm for parts based on "logical_lib.part" and where logical_lib + // is merely the library name minus path and extension. + LIB_PART* part = m_libs->FindLibPart( comp->GetPartName() ); + if( part ) + xlibsource->AddAttribute( sLib, part->GetLib()->GetLogicalName() ); + + xlibsource->AddAttribute( sPart, comp->GetPartName() ); + + XNODE* xsheetpath; + + xcomp->AddChild( xsheetpath = node( sSheetPath ) ); + xsheetpath->AddAttribute( sNames, path->PathHumanReadable() ); + xsheetpath->AddAttribute( sTStamps, path->Path() ); + + timeStamp.Printf( sTSFmt, (unsigned long)comp->GetTimeStamp() ); + xcomp->AddChild( node( sTStamp, timeStamp ) ); + } + } + + return xcomps; +} + + +XNODE* NETLIST_EXPORTER_GENERIC::makeDesignHeader() +{ + SCH_SCREEN* screen; + XNODE* xdesign = node( wxT("design") ); + XNODE* xtitleBlock; + XNODE* xsheet; + XNODE* xcomment; + wxString sheetTxt; + wxFileName sourceFileName; + + // the root sheet is a special sheet, call it source + xdesign->AddChild( node( wxT( "source" ), g_RootSheet->GetScreen()->GetFileName() ) ); + + xdesign->AddChild( node( wxT( "date" ), DateAndTime() ) ); + + // which Eeschema tool + xdesign->AddChild( node( wxT( "tool" ), wxT( "Eeschema " ) + GetBuildVersion() ) ); + + /* + Export the sheets information + */ + SCH_SHEET_LIST sheetList; + + for( SCH_SHEET_PATH* sheet = sheetList.GetFirst(); sheet; sheet = sheetList.GetNext() ) + { + screen = sheet->LastScreen(); + + xdesign->AddChild( xsheet = node( wxT( "sheet" ) ) ); + + // get the string representation of the sheet index number. + // Note that sheet->GetIndex() is zero index base and we need to increment the number by one to make + // human readable + sheetTxt.Printf( wxT( "%d" ), ( sheetList.GetIndex() + 1 ) ); + xsheet->AddAttribute( wxT( "number" ), sheetTxt ); + xsheet->AddAttribute( wxT( "name" ), sheet->PathHumanReadable() ); + xsheet->AddAttribute( wxT( "tstamps" ), sheet->Path() ); + + + TITLE_BLOCK tb = screen->GetTitleBlock(); + + xsheet->AddChild( xtitleBlock = node( wxT( "title_block" ) ) ); + + xtitleBlock->AddChild( node( wxT( "title" ), tb.GetTitle() ) ); + xtitleBlock->AddChild( node( wxT( "company" ), tb.GetCompany() ) ); + xtitleBlock->AddChild( node( wxT( "rev" ), tb.GetRevision() ) ); + xtitleBlock->AddChild( node( wxT( "date" ), tb.GetDate() ) ); + + // We are going to remove the fileName directories. + sourceFileName = wxFileName( screen->GetFileName() ); + xtitleBlock->AddChild( node( wxT( "source" ), sourceFileName.GetFullName() ) ); + + xtitleBlock->AddChild( xcomment = node( wxT( "comment" ) ) ); + xcomment->AddAttribute( wxT("number"), wxT("1") ); + xcomment->AddAttribute( wxT( "value" ), tb.GetComment1() ); + + xtitleBlock->AddChild( xcomment = node( wxT( "comment" ) ) ); + xcomment->AddAttribute( wxT("number"), wxT("2") ); + xcomment->AddAttribute( wxT( "value" ), tb.GetComment2() ); + + xtitleBlock->AddChild( xcomment = node( wxT( "comment" ) ) ); + xcomment->AddAttribute( wxT("number"), wxT("3") ); + xcomment->AddAttribute( wxT( "value" ), tb.GetComment3() ); + + xtitleBlock->AddChild( xcomment = node( wxT( "comment" ) ) ); + xcomment->AddAttribute( wxT("number"), wxT("4") ); + xcomment->AddAttribute( wxT( "value" ), tb.GetComment4() ); + } + + return xdesign; +} + + +XNODE* NETLIST_EXPORTER_GENERIC::makeLibraries() +{ + XNODE* xlibs = node( wxT( "libraries" ) ); // auto_ptr + + for( std::set<void*>::iterator it = m_Libraries.begin(); it!=m_Libraries.end(); ++it ) + { + PART_LIB* lib = (PART_LIB*) *it; + XNODE* xlibrary; + + xlibs->AddChild( xlibrary = node( wxT( "library" ) ) ); + xlibrary->AddAttribute( wxT( "logical" ), lib->GetLogicalName() ); + xlibrary->AddChild( node( wxT( "uri" ), lib->GetFullFileName() ) ); + + // @todo: add more fun stuff here + } + + return xlibs; +} + + +XNODE* NETLIST_EXPORTER_GENERIC::makeLibParts() +{ + XNODE* xlibparts = node( wxT( "libparts" ) ); // auto_ptr + wxString sLibpart = wxT( "libpart" ); + wxString sLib = wxT( "lib" ); + wxString sPart = wxT( "part" ); + wxString sAliases = wxT( "aliases" ); + wxString sAlias = wxT( "alias" ); + wxString sPins = wxT( "pins" ); // key for library component pins list + wxString sPin = wxT( "pin" ); // key for one library component pin descr + wxString sPinNum = wxT( "num" ); // key for one library component pin num + wxString sPinName = wxT( "name" ); // key for one library component pin name + wxString sPinType = wxT( "type" ); // key for one library component pin electrical type + wxString sName = wxT( "name" ); + wxString sField = wxT( "field" ); + wxString sFields = wxT( "fields" ); + wxString sDescr = wxT( "description" ); + wxString sDocs = wxT( "docs" ); + wxString sFprints = wxT( "footprints" ); + wxString sFp = wxT( "fp" ); + + LIB_PINS pinList; + LIB_FIELDS fieldList; + + m_Libraries.clear(); + + for( std::set<LIB_PART*>::iterator it = m_LibParts.begin(); it!=m_LibParts.end(); ++it ) + { + LIB_PART* lcomp = *it; + PART_LIB* library = lcomp->GetLib(); + + m_Libraries.insert( library ); // inserts component's library if unique + + XNODE* xlibpart; + xlibparts->AddChild( xlibpart = node( sLibpart ) ); + xlibpart->AddAttribute( sLib, library->GetLogicalName() ); + xlibpart->AddAttribute( sPart, lcomp->GetName() ); + + if( lcomp->GetAliasCount() ) + { + wxArrayString aliases = lcomp->GetAliasNames( false ); + if( aliases.GetCount() ) + { + XNODE* xaliases = node( sAliases ); + xlibpart->AddChild( xaliases ); + for( unsigned i=0; i<aliases.GetCount(); ++i ) + { + xaliases->AddChild( node( sAlias, aliases[i] ) ); + } + } + } + + //----- show the important properties ------------------------- + if( !lcomp->GetAlias( 0 )->GetDescription().IsEmpty() ) + xlibpart->AddChild( node( sDescr, lcomp->GetAlias( 0 )->GetDescription() ) ); + + if( !lcomp->GetAlias( 0 )->GetDocFileName().IsEmpty() ) + xlibpart->AddChild( node( sDocs, lcomp->GetAlias( 0 )->GetDocFileName() ) ); + + // Write the footprint list + if( lcomp->GetFootPrints().GetCount() ) + { + XNODE* xfootprints; + xlibpart->AddChild( xfootprints = node( sFprints ) ); + + for( unsigned i=0; i<lcomp->GetFootPrints().GetCount(); ++i ) + { + xfootprints->AddChild( node( sFp, lcomp->GetFootPrints()[i] ) ); + } + } + + //----- show the fields here ---------------------------------- + fieldList.clear(); + lcomp->GetFields( fieldList ); + + XNODE* xfields; + xlibpart->AddChild( xfields = node( sFields ) ); + + for( unsigned i=0; i<fieldList.size(); ++i ) + { + if( !fieldList[i].GetText().IsEmpty() ) + { + XNODE* xfield; + xfields->AddChild( xfield = node( sField, fieldList[i].GetText() ) ); + xfield->AddAttribute( sName, fieldList[i].GetName(false) ); + } + } + + //----- show the pins here ------------------------------------ + pinList.clear(); + lcomp->GetPins( pinList, 0, 0 ); + + /* we must erase redundant Pins references in pinList + * These redundant pins exist because some pins + * are found more than one time when a component has + * multiple parts per package or has 2 representations (DeMorgan conversion) + * For instance, a 74ls00 has DeMorgan conversion, with different pin shapes, + * and therefore each pin appears 2 times in the list. + * Common pins (VCC, GND) can also be found more than once. + */ + sort( pinList.begin(), pinList.end(), sortPinsByNumber ); + for( int ii = 0; ii < (int)pinList.size()-1; ii++ ) + { + if( pinList[ii]->GetNumber() == pinList[ii+1]->GetNumber() ) + { // 2 pins have the same number, remove the redundant pin at index i+1 + pinList.erase(pinList.begin() + ii + 1); + ii--; + } + } + + if( pinList.size() ) + { + XNODE* pins; + + xlibpart->AddChild( pins = node( sPins ) ); + for( unsigned i=0; i<pinList.size(); ++i ) + { + XNODE* pin; + + pins->AddChild( pin = node( sPin ) ); + pin->AddAttribute( sPinNum, pinList[i]->GetNumberString() ); + pin->AddAttribute( sPinName, pinList[i]->GetName() ); + pin->AddAttribute( sPinType, pinList[i]->GetCanonicalElectricalTypeName() ); + + // caution: construction work site here, drive slowly + } + } + } + + return xlibparts; +} + + +XNODE* NETLIST_EXPORTER_GENERIC::makeListOfNets() +{ + XNODE* xnets = node( wxT( "nets" ) ); // auto_ptr if exceptions ever get used. + wxString netCodeTxt; + wxString netName; + wxString ref; + + wxString sNet = wxT( "net" ); + wxString sName = wxT( "name" ); + wxString sCode = wxT( "code" ); + wxString sRef = wxT( "ref" ); + wxString sPin = wxT( "pin" ); + wxString sNode = wxT( "node" ); + wxString sFmtd = wxT( "%d" ); + + XNODE* xnet = 0; + int netCode; + int lastNetCode = -1; + int sameNetcodeCount = 0; + + + /* output: + <net code="123" name="/cfcard.sch/WAIT#"> + <node ref="R23" pin="1"/> + <node ref="U18" pin="12"/> + </net> + */ + + m_LibParts.clear(); // must call this function before using m_LibParts. + + for( unsigned ii = 0; ii < m_masterList->size(); ii++ ) + { + NETLIST_OBJECT* nitem = m_masterList->GetItem( ii ); + SCH_COMPONENT* comp; + + // New net found, write net id; + if( ( netCode = nitem->GetNet() ) != lastNetCode ) + { + sameNetcodeCount = 0; // item count for this net + netName = nitem->GetNetName(); + lastNetCode = netCode; + } + + if( nitem->m_Type != NET_PIN ) + continue; + + if( nitem->m_Flag != 0 ) // Redundant pin, skip it + continue; + + comp = nitem->GetComponentParent(); + + // Get the reference for the net name and the main parent component + ref = comp->GetRef( &nitem->m_SheetPath ); + if( ref[0] == wxChar( '#' ) ) + continue; + + if( ++sameNetcodeCount == 1 ) + { + xnets->AddChild( xnet = node( sNet ) ); + netCodeTxt.Printf( sFmtd, netCode ); + xnet->AddAttribute( sCode, netCodeTxt ); + xnet->AddAttribute( sName, netName ); + } + + XNODE* xnode; + xnet->AddChild( xnode = node( sNode ) ); + xnode->AddAttribute( sRef, ref ); + xnode->AddAttribute( sPin, nitem->GetPinNumText() ); + } + + return xnets; +} + + +bool NETLIST_EXPORTER_GENERIC::writeListOfNets( FILE* f, NETLIST_OBJECT_LIST& aObjectsList ) +{ + int ret = 0; + int netCode; + int lastNetCode = -1; + int sameNetcodeCount = 0; + wxString netName; + wxString ref; + wxString netcodeName; + char firstItemInNet[256]; + + for( unsigned ii = 0; ii < aObjectsList.size(); ii++ ) + { + SCH_COMPONENT* comp; + NETLIST_OBJECT* nitem = aObjectsList[ii]; + + // New net found, write net id; + if( ( netCode = nitem->GetNet() ) != lastNetCode ) + { + sameNetcodeCount = 0; // Items count for this net + netName = nitem->GetNetName(); + + netcodeName.Printf( wxT( "Net %d " ), netCode ); + netcodeName << wxT( "\"" ) << netName << wxT( "\"" ); + + // Add the netname without prefix, in cases we need only the + // "short" netname + netcodeName += wxT( " \"" ) + nitem->GetShortNetName() + wxT( "\"" ); + lastNetCode = netCode; + } + + if( nitem->m_Type != NET_PIN ) + continue; + + if( nitem->m_Flag != 0 ) // Redundant pin, skip it + continue; + + comp = nitem->GetComponentParent(); + + // Get the reference for the net name and the main parent component + ref = comp->GetRef( &nitem->m_SheetPath ); + if( ref[0] == wxChar( '#' ) ) + continue; // Pseudo component (Like Power symbol) + + // Print the pin list for this net, use special handling if + // 2 or more items are connected: + + // if first item for this net found, defer printing this connection + // until a second item will is found + if( ++sameNetcodeCount == 1 ) + { + snprintf( firstItemInNet, sizeof(firstItemInNet), " %s %.4s\n", + TO_UTF8( ref ), + (const char*) &aObjectsList[ii]->m_PinNum ); + } + + // Second item for this net found, print the Net name, and the + // first item + if( sameNetcodeCount == 2 ) + { + ret |= fprintf( f, "%s\n", TO_UTF8( netcodeName ) ); + ret |= fputs( firstItemInNet, f ); + } + + if( sameNetcodeCount >= 2 ) + ret |= fprintf( f, " %s %.4s\n", TO_UTF8( ref ), + (const char*) &nitem->m_PinNum ); + } + + return ret >= 0; +} + + +XNODE* NETLIST_EXPORTER_GENERIC::node( const wxString& aName, const wxString& aTextualContent /* = wxEmptyString*/ ) +{ + XNODE* n = new XNODE( wxXML_ELEMENT_NODE, aName ); + + if( aTextualContent.Len() > 0 ) // excludes wxEmptyString, the parameter's default value + n->AddChild( new XNODE( wxXML_TEXT_NODE, wxEmptyString, aTextualContent ) ); + + return n; +} + + +static bool sortPinsByNumber( LIB_PIN* aPin1, LIB_PIN* aPin2 ) +{ + // return "lhs < rhs" + return RefDesStringCompare( aPin1->GetNumberString(), aPin2->GetNumberString() ) < 0; +} diff --git a/eeschema/netlist_exporters/netlist_exporter_generic.h b/eeschema/netlist_exporters/netlist_exporter_generic.h new file mode 100644 index 0000000..89d57d5 --- /dev/null +++ b/eeschema/netlist_exporters/netlist_exporter_generic.h @@ -0,0 +1,135 @@ +/* + * This program source code file is part of KiCad, a free EDA CAD application. + * + * Copyright (C) 1992-2013 jp.charras at wanadoo.fr + * Copyright (C) 2013 SoftPLC Corporation, Dick Hollenbeck <dick@softplc.com> + * Copyright (C) 1992-2015 KiCad Developers + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, you may find one here: + * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html + * or you may search the http://www.gnu.org website for the version 2 license, + * or you may write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#ifndef NETLIST_EXPORT_GENERIC_H +#define NETLIST_EXPORT_GENERIC_H + +#include <netlist_exporter.h> + +#include <xnode.h> // also nests: <wx/xml/xml.h> + +#define GENERIC_INTERMEDIATE_NETLIST_EXT wxT( "xml" ) + +/** + * Enum GNL + * is a set of bit which control the totality of the tree built by makeRoot() + */ +enum GNL_T +{ + GNL_LIBRARIES = 1 << 0, + GNL_COMPONENTS = 1 << 1, + GNL_PARTS = 1 << 2, + GNL_HEADER = 1 << 3, + GNL_NETS = 1 << 4, +}; + + +/** + * Class 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. + */ +class NETLIST_EXPORTER_GENERIC : public NETLIST_EXPORTER +{ +public: + NETLIST_EXPORTER_GENERIC( NETLIST_OBJECT_LIST* aMasterList, PART_LIBS* aLibs ) : + NETLIST_EXPORTER( aMasterList, aLibs ) + { + } + + /** + * Function WriteNetlist + * writes to specified output file + */ + bool WriteNetlist( const wxString& aOutFileName, unsigned aNetlistOptions ); + +#define GNL_ALL ( GNL_LIBRARIES | GNL_COMPONENTS | GNL_PARTS | GNL_HEADER | GNL_NETS ) + +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. + * + * @param aName is the name to associate with a new node of type wxXML_ELEMENT_NODE. + * @param aTextualContent is optional, and if given is the text to include in a child + * of the returned node, and has type wxXML_TEXT_NODE. + */ + XNODE* node( const wxString& aName, const wxString& aTextualContent = wxEmptyString ); + + /** + * Function writeGENERICListOfNets + * writes out nets (ranked by Netcode), and elements that are + * connected as part of that net. + */ + bool writeListOfNets( FILE* f, NETLIST_OBJECT_LIST& aObjectsList ); + + /** + * 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. + * @param aCtl - a bitset or-ed together from GNL_ENUM values + * @return XNODE* - the root nodes + */ + XNODE* makeRoot( int aCtl = GNL_ALL ); + + /** + * Function makeComponents + * @return XNODE* - returns a sub-tree holding all the schematic components. + */ + XNODE* makeComponents(); + + /** + * Function makeDesignHeader + * fills out a project "design" header into an XML node. + * @return XNODE* - the design header + */ + XNODE* makeDesignHeader(); + + /** + * Function makeLibParts + * fills out an XML node with the unique library parts and returns it. + * @return XNODE* - the library parts nodes + */ + XNODE* makeLibParts(); + + /** + * Function makeListOfNets + * fills out an XML node with a list of nets and returns it. + * @return XNODE* - the list of nets nodes + */ + XNODE* makeListOfNets(); + + /** + * Function makeLibraries + * fills out an XML node with a list of used libraries and returns it. + * Must have called makeGenericLibParts() before this function. + * @return XNODE* - the library nodes + */ + XNODE* makeLibraries(); +}; + +#endif diff --git a/eeschema/netlist_exporters/netlist_exporter_kicad.cpp b/eeschema/netlist_exporters/netlist_exporter_kicad.cpp new file mode 100644 index 0000000..e4b624c --- /dev/null +++ b/eeschema/netlist_exporters/netlist_exporter_kicad.cpp @@ -0,0 +1,77 @@ +/* + * This program source code file is part of KiCad, a free EDA CAD application. + * + * Copyright (C) 1992-2013 jp.charras at wanadoo.fr + * Copyright (C) 2013 SoftPLC Corporation, Dick Hollenbeck <dick@softplc.com> + * Copyright (C) 1992-2015 KiCad Developers, see AUTHORS.TXT for contributors. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, you may find one here: + * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html + * or you may search the http://www.gnu.org website for the version 2 license, + * or you may write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + */ + + +#include <fctsys.h> +#include <build_version.h> +#include <confirm.h> + +#include <schframe.h> +#include "netlist_exporter_kicad.h" + +bool NETLIST_EXPORTER_KICAD::WriteNetlist( const wxString& aOutFileName, unsigned aNetlistOptions ) +{ +#if 0 + // Prepare list of nets generation + for( unsigned ii = 0; ii < m_masterList->size(); ii++ ) + m_masterList->GetItem( ii )->m_Flag = 0; + + std::auto_ptr<XNODE> xroot( makeRoot() ); + + try + { + FILE_OUTPUTFORMATTER formatter( aOutFileName ); + + xroot->Format( &formatter, 0 ); + } +#else + try + { + FILE_OUTPUTFORMATTER formatter( aOutFileName ); + + Format( &formatter, GNL_ALL ); + } +#endif + + catch( const IO_ERROR& ioe ) + { + DisplayError( NULL, ioe.errorText ); + return false; + } + + return true; +} + + +void NETLIST_EXPORTER_KICAD::Format( OUTPUTFORMATTER* aOut, int aCtl ) +{ + // Prepare list of nets generation + for( unsigned ii = 0; ii < m_masterList->size(); ii++ ) + m_masterList->GetItem( ii )->m_Flag = 0; + + std::auto_ptr<XNODE> xroot( makeRoot( aCtl ) ); + + xroot->Format( aOut, 0 ); +} diff --git a/eeschema/netlist_exporters/netlist_exporter_kicad.h b/eeschema/netlist_exporters/netlist_exporter_kicad.h new file mode 100644 index 0000000..433d12c --- /dev/null +++ b/eeschema/netlist_exporters/netlist_exporter_kicad.h @@ -0,0 +1,63 @@ +/* + * This program source code file is part of KiCad, a free EDA CAD application. + * + * Copyright (C) 1992-2013 jp.charras at wanadoo.fr + * Copyright (C) 2013 SoftPLC Corporation, Dick Hollenbeck <dick@softplc.com> + * Copyright (C) 1992-2015 KiCad Developers + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, you may find one here: + * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html + * or you may search the http://www.gnu.org website for the version 2 license, + * or you may write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#ifndef NETLIST_EXPORTER_KICAD_H +#define NETLIST_EXPORTER_KICAD_H + +#include <netlist_exporter_generic.h> + +class OUTPUTFORMATTER; + +/** + * Class NETLIST_EXPORTER_KICAD + * generates the kicad netlist format supported by pcbnew. It is basically + * the generic netlist format just formatted slightly different. + */ +class NETLIST_EXPORTER_KICAD : public NETLIST_EXPORTER_GENERIC +{ +public: + NETLIST_EXPORTER_KICAD( NETLIST_OBJECT_LIST* aMasterList, PART_LIBS* aLibs ) : + NETLIST_EXPORTER_GENERIC( aMasterList, aLibs ) + { + } + + /** + * Function WriteNetlist + * writes to specified output file + */ + bool WriteNetlist( const wxString& aOutFileName, unsigned aNetlistOptions ); // OVERRIDE + + /** + * Function Format + * outputs this s-expression netlist into @a aOutputFormatter. + * @param aOutputFormatter is the destination of the serialization to text. + * @param aCtl is bit set composed by OR-ing together enum GNL bits, it allows ouputting + * a subset of the full document model. + * @throw IO_ERROR if any problems. + */ + void Format( OUTPUTFORMATTER* aOutputFormatter, int aCtl ); +}; + +#endif diff --git a/eeschema/netlist_exporters/netlist_exporter_orcadpcb2.cpp b/eeschema/netlist_exporters/netlist_exporter_orcadpcb2.cpp new file mode 100644 index 0000000..0aeaccc --- /dev/null +++ b/eeschema/netlist_exporters/netlist_exporter_orcadpcb2.cpp @@ -0,0 +1,145 @@ +/* + * This program source code file is part of KiCad, a free EDA CAD application. + * + * Copyright (C) 1992-2013 jp.charras at wanadoo.fr + * Copyright (C) 2013 SoftPLC Corporation, Dick Hollenbeck <dick@softplc.com> + * Copyright (C) 1992-2015 KiCad Developers, see AUTHORS.TXT for contributors. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, you may find one here: + * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html + * or you may search the http://www.gnu.org website for the version 2 license, + * or you may write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#include <fctsys.h> +#include <build_version.h> +#include <confirm.h> + +#include <schframe.h> +#include <sch_reference_list.h> +#include <class_library.h> +#include <class_netlist_object.h> + +#include <netlist.h> +#include "netlist_exporter_orcadpcb2.h" + +bool NETLIST_EXPORTER_ORCADPCB2::WriteNetlist( const wxString& aOutFileName, unsigned aNetlistOptions ) +{ + (void)aNetlistOptions; //unused + FILE* f = NULL; + wxString field; + wxString footprint; + int ret = 0; // zero now, OR in the sign bit on error + wxString netName; + + + if( ( f = wxFopen( aOutFileName, wxT( "wt" ) ) ) == NULL ) + { + wxString msg; + msg.Printf( _( "Failed to create file '%s'" ), + GetChars( aOutFileName ) ); + DisplayError( NULL, msg ); + return false; + } + + std::vector< SCH_REFERENCE > cmpList; + + ret |= fprintf( f, "( { %s created %s }\n", + NETLIST_HEAD_STRING, TO_UTF8( DateAndTime() ) ); + + // Prepare list of nets generation + for( unsigned ii = 0; ii < m_masterList->size(); ii++ ) + m_masterList->GetItem( ii )->m_Flag = 0; + + // Create netlist module section + m_ReferencesAlreadyFound.Clear(); + + SCH_SHEET_LIST sheetList; + + for( SCH_SHEET_PATH* path = sheetList.GetFirst(); path; path = sheetList.GetNext() ) + { + for( EDA_ITEM* item = path->LastDrawList(); item; item = item->Next() ) + { + SCH_COMPONENT* comp = findNextComponentAndCreatePinList( item, path ); + + if( !comp ) + break; + + item = comp; + + // Get the Component FootprintFilter and put the component in + // cmpList if filter is present + LIB_PART* part = m_libs->FindLibPart( comp->GetPartName() ); + + if( part ) + { + if( part->GetFootPrints().GetCount() != 0 ) // Put in list + { + cmpList.push_back( SCH_REFERENCE( comp, part, *path ) ); + } + } + + if( !comp->GetField( FOOTPRINT )->IsVoid() ) + { + footprint = comp->GetField( FOOTPRINT )->GetText(); + footprint.Replace( wxT( " " ), wxT( "_" ) ); + } + else + footprint = wxT( "$noname" ); + + field = comp->GetRef( path ); + + ret |= fprintf( f, " ( %s %s", + TO_UTF8( comp->GetPath( path ) ), + TO_UTF8( footprint ) ); + + ret |= fprintf( f, " %s", TO_UTF8( field ) ); + + field = comp->GetField( VALUE )->GetText(); + field.Replace( wxT( " " ), wxT( "_" ) ); + ret |= fprintf( f, " %s", TO_UTF8( field ) ); + + ret |= fprintf( f, "\n" ); + + // Write pin list: + for( unsigned ii = 0; ii < m_SortedComponentPinList.size(); ii++ ) + { + NETLIST_OBJECT* pin = m_SortedComponentPinList[ii]; + + if( !pin ) + continue; + + sprintPinNetName( netName, wxT( "N-%.6d" ), pin ); + + if( netName.IsEmpty() ) + netName = wxT( "?" ); + + netName.Replace( wxT( " " ), wxT( "_" ) ); + + ret |= fprintf( f, " ( %4.4s %s )\n", (char*) &pin->m_PinNum, + TO_UTF8( netName ) ); + } + + ret |= fprintf( f, " )\n" ); + } + } + + ret |= fprintf( f, ")\n*\n" ); + + fclose( f ); + + m_SortedComponentPinList.clear(); + return ret >= 0; +} diff --git a/eeschema/netlist_exporters/netlist_exporter_orcadpcb2.h b/eeschema/netlist_exporters/netlist_exporter_orcadpcb2.h new file mode 100644 index 0000000..06fcf10 --- /dev/null +++ b/eeschema/netlist_exporters/netlist_exporter_orcadpcb2.h @@ -0,0 +1,46 @@ +/* + * This program source code file is part of KiCad, a free EDA CAD application. + * + * Copyright (C) 1992-2013 jp.charras at wanadoo.fr + * Copyright (C) 2013 SoftPLC Corporation, Dick Hollenbeck <dick@softplc.com> + * Copyright (C) 1992-2015 KiCad Developers + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, you may find one here: + * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html + * or you may search the http://www.gnu.org website for the version 2 license, + * or you may write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#ifndef NETLIST_EXPORTER_ORCADPCB2_H +#define NETLIST_EXPORTER_ORCADPCB2_H + +#include "netlist_exporter.h" + +/** + * Class NETLIST_EXPORTER_ORCADPCB2 + * generates a netlist compatible with OrCAD + */ +class NETLIST_EXPORTER_ORCADPCB2 : public NETLIST_EXPORTER +{ +public: + NETLIST_EXPORTER_ORCADPCB2( NETLIST_OBJECT_LIST* aMasterList, PART_LIBS* aLibs ) : + NETLIST_EXPORTER( aMasterList, aLibs ) + { + } + + bool WriteNetlist( const wxString& aOutFileName, unsigned aNetlistOptions ); +}; + +#endif diff --git a/eeschema/netlist_exporters/netlist_exporter_pspice.cpp b/eeschema/netlist_exporters/netlist_exporter_pspice.cpp new file mode 100644 index 0000000..7158bd4 --- /dev/null +++ b/eeschema/netlist_exporters/netlist_exporter_pspice.cpp @@ -0,0 +1,358 @@ +/* + * This program source code file is part of KiCad, a free EDA CAD application. + * + * Copyright (C) 1992-2013 jp.charras at wanadoo.fr + * Copyright (C) 2013 SoftPLC Corporation, Dick Hollenbeck <dick@softplc.com> + * Copyright (C) 1992-2015 KiCad Developers, see AUTHORS.TXT for contributors. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, you may find one here: + * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html + * or you may search the http://www.gnu.org website for the version 2 license, + * or you may write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#include <fctsys.h> +#include <build_version.h> +#include <confirm.h> + +#include <schframe.h> +#include <netlist.h> +#include <sch_reference_list.h> +#include <class_netlist_object.h> +#include <wx/tokenzr.h> +#include "netlist_exporter_pspice.h" + +bool NETLIST_EXPORTER_PSPICE::WriteNetlist( const wxString& aOutFileName, unsigned aNetlistOptions ) +{ + FILE* f = NULL; + bool aUsePrefix = aNetlistOptions & NET_USE_X_PREFIX; + bool aUseNetcodeAsNetName = aNetlistOptions & NET_USE_NETCODES_AS_NETNAMES; + + int ret = 0; + int nbitems; + wxString text; + wxArrayString spiceCommandAtBeginFile; + wxArrayString spiceCommandAtEndFile; + wxString msg; + wxString netName; + + #define BUFYPOS_LEN 4 + wxChar bufnum[BUFYPOS_LEN + 1]; + std::vector<int> pinSequence; // numeric indices into m_SortedComponentPinList + wxArrayString stdPinNameArray; // Array containing Standard Pin Names + wxString delimeters = wxT( "{:,; }" ); + wxString disableStr = wxT( "N" ); + + if( ( f = wxFopen( aOutFileName, wxT( "wt" ) ) ) == NULL ) + { + wxString msg; + msg.Printf( _( "Failed to create file '%s'" ), + GetChars( aOutFileName ) ); + DisplayError( NULL, msg ); + return false; + } + + ret |= fprintf( f, "* %s\n\n", TO_UTF8( aOutFileName ) ); + ret |= fprintf( f, "* %s (Spice format) creation date: %s\n\n", + NETLIST_HEAD_STRING, TO_UTF8( DateAndTime() ) ); + + // Prepare list of nets generation (not used here, but... + for( unsigned ii = 0; ii < m_masterList->size(); ii++ ) + m_masterList->GetItem( ii )->m_Flag = 0; + + ret |= fprintf( f, "* To exclude a component from the Spice Netlist add [Spice_Netlist_Enabled] user FIELD set to: N\n" ); + ret |= fprintf( f, "* To reorder the component spice node sequence add [Spice_Node_Sequence] user FIELD and define sequence: 2,1,0\n" ); + + // Create text list starting by [.-]pspice , or [.-]gnucap (simulator + // commands) and create text list starting by [+]pspice , or [+]gnucap + // (simulator commands) + bufnum[BUFYPOS_LEN] = 0; + SCH_SHEET_LIST sheetList; + + for( SCH_SHEET_PATH* sheet = sheetList.GetFirst(); sheet; sheet = sheetList.GetNext() ) + { + for( EDA_ITEM* item = sheet->LastDrawList(); item; item = item->Next() ) + { + size_t l1, l2; + wxChar ident; + + if( item->Type() != SCH_TEXT_T ) + continue; + + SCH_TEXT* drawText = (SCH_TEXT*) item; + + text = drawText->GetText(); + + if( text.IsEmpty() ) + continue; + + ident = text.GetChar( 0 ); + + if( ident != '.' && ident != '-' && ident != '+' ) + continue; + + text.Remove( 0, 1 ); // Remove the first char. + text.Remove( 6 ); // text contains 6 char. + text.MakeLower(); + + if( text != wxT( "pspice" ) && text != wxT( "gnucap" ) ) + continue; + + text = drawText->GetText().Mid( 7 ); + l1 = text.Length(); + text.Trim( false ); + l2 = text.Length(); + + if( l1 == l2 ) + continue; // no whitespace after ident text + + { + // Put the Y position as an ascii string, for sort by vertical + // position, using usual sort string by alphabetic value + int ypos = drawText->GetPosition().y; + + for( int ii = 0; ii < BUFYPOS_LEN; ii++ ) + { + bufnum[BUFYPOS_LEN - 1 - ii] = (ypos & 63) + ' '; + ypos >>= 6; + } + + // First BUFYPOS_LEN char are the Y position. + msg.Printf( wxT( "%s %s" ), bufnum, text.GetData() ); + + if( ident == '+' ) + spiceCommandAtEndFile.Add( msg ); + else + spiceCommandAtBeginFile.Add( msg ); + } + } + } + + // Print texts starting by [.-]pspice , ou [.-]gnucap (of course, without + // the Y position string) + nbitems = spiceCommandAtBeginFile.GetCount(); + + if( nbitems ) + { + spiceCommandAtBeginFile.Sort(); + + for( int ii = 0; ii < nbitems; ii++ ) + { + spiceCommandAtBeginFile[ii].Remove( 0, BUFYPOS_LEN ); + spiceCommandAtBeginFile[ii].Trim( true ); + spiceCommandAtBeginFile[ii].Trim( false ); + ret |= fprintf( f, "%s\n", TO_UTF8( spiceCommandAtBeginFile[ii] ) ); + } + } + ret |= fprintf( f, "\n" ); + + // Create component list + + m_ReferencesAlreadyFound.Clear(); + + for( SCH_SHEET_PATH* sheet = sheetList.GetFirst(); sheet; sheet = sheetList.GetNext() ) + { + ret |= fprintf( f, "* Sheet Name: %s\n", TO_UTF8( sheet->PathHumanReadable() ) ); + + for( EDA_ITEM* item = sheet->LastDrawList(); item; item = item->Next() ) + { + SCH_COMPONENT* comp = findNextComponentAndCreatePinList( item, sheet ); + + if( !comp ) + break; + + item = comp; + + // Reset NodeSeqIndex Count: + pinSequence.clear(); + + // Check to see if component should be removed from Spice Netlist: + SCH_FIELD* netlistEnabledField = comp->FindField( wxT( "Spice_Netlist_Enabled" ) ); + + if( netlistEnabledField ) + { + wxString netlistEnabled = netlistEnabledField->GetText(); + + if( netlistEnabled.CmpNoCase( disableStr ) == 0 ) + continue; + } + + // Check if Alternative Pin Sequence is Available: + SCH_FIELD* spiceSeqField = comp->FindField( wxT( "Spice_Node_Sequence" ) ); + + if( spiceSeqField ) + { + // Get String containing the Sequence of Nodes: + wxString nodeSeqIndexLineStr = spiceSeqField->GetText(); + + // Verify Field Exists and is not empty: + if( !nodeSeqIndexLineStr.IsEmpty() ) + { + + // Create an Array of Standard Pin Names from part definition: + stdPinNameArray.Clear(); + + for( unsigned ii = 0; ii < m_SortedComponentPinList.size(); ii++ ) + { + NETLIST_OBJECT* pin = m_SortedComponentPinList[ii]; + + if( !pin ) + continue; + + stdPinNameArray.Add( pin->GetPinNumText() ); + } + + // Get Alt Pin Name Array From User: + wxStringTokenizer tkz( nodeSeqIndexLineStr, delimeters ); + + while( tkz.HasMoreTokens() ) + { + wxString pinIndex = tkz.GetNextToken(); + int seq; + + // Find PinName In Standard List assign Standard List Index to Name: + seq = stdPinNameArray.Index(pinIndex); + + if( seq != wxNOT_FOUND ) + { + pinSequence.push_back( seq ); + } + } + + } + } + + //Get Standard Reference Designator: + wxString RefName = comp->GetRef( sheet ); + + //Conditionally add Prefix only for devices that begin with U or IC: + if( aUsePrefix ) + { + if( RefName.StartsWith( wxT( "U" ) ) || RefName.StartsWith( wxT( "IC" ) ) ) + RefName = wxT( "X" ) + RefName; + } + + ret |= fprintf( f, "%s ", TO_UTF8( RefName ) ); + + // Write pin list: + int activePinIndex = 0; + + for( unsigned ii = 0; ii < m_SortedComponentPinList.size(); ii++ ) + { + // Case of Alt Sequence definition with Unused/Invalid Node index: + // Valid used Node Indexes are in the set + // {0,1,2,...m_SortedComponentPinList.size()-1} + if( pinSequence.size() ) + { + // All Vector values must be less <= max package size + // And Total Vector size should be <= package size + if( ( (unsigned) pinSequence[ii] < m_SortedComponentPinList.size() ) + && ( ii < pinSequence.size() ) ) + { + // Case of Alt Pin Sequence in control good Index: + activePinIndex = pinSequence[ii]; + } + else + { + // Case of Alt Pin Sequence in control Bad Index or not using all + // pins for simulation: + continue; + } + } + // Case of Standard Pin Sequence in control: + else + { + activePinIndex = ii; + } + + NETLIST_OBJECT* pin = m_SortedComponentPinList[activePinIndex]; + + if( !pin ) + continue; + + sprintPinNetName( netName , wxT( "N-%.6d" ), pin, aUseNetcodeAsNetName ); + + //Replace parenthesis with underscore to prevent parse issues with Simulators: + netName.Replace( wxT( "(" ), wxT( "_" ) ); + netName.Replace( wxT( ")" ), wxT( "_" ) ); + + if( netName.IsEmpty() ) + netName = wxT( "?" ); + + ret |= fprintf( f, " %s", TO_UTF8( netName ) ); + } + + // Get Component Value Name: + wxString CompValue = comp->GetField( VALUE )->GetText(); + + // Check if Override Model Name is Provided: + SCH_FIELD* spiceModelField = comp->FindField( wxT( "spice_model" ) ); + + if( spiceModelField ) + { + // Get Model Name String: + wxString ModelNameStr = spiceModelField->GetText(); + + // Verify Field Exists and is not empty: + if( !ModelNameStr.IsEmpty() ) + CompValue = ModelNameStr; + } + + // Print Component Value: + ret |= fprintf( f, " %s\t\t",TO_UTF8( CompValue ) ); + + // Show Seq Spec on same line as component using line-comment ";": + for( unsigned i = 0; i < pinSequence.size(); ++i ) + { + if( i==0 ) + ret |= fprintf( f, ";Node Sequence Spec.<" ); + + ret |= fprintf( f, "%s", TO_UTF8( stdPinNameArray.Item( pinSequence[i] ) ) ); + + if( i < pinSequence.size()-1 ) + ret |= fprintf( f, "," ); + else + ret |= fprintf( f, ">" ); + } + + // Next Netlist line record: + ret |= fprintf( f, "\n" ); + } + } + + m_SortedComponentPinList.clear(); + + // Print texts starting with [+]pspice or [+]gnucap + nbitems = spiceCommandAtEndFile.GetCount(); + + if( nbitems ) + { + ret |= fprintf( f, "\n" ); + spiceCommandAtEndFile.Sort(); + + for( int ii = 0; ii < nbitems; ii++ ) + { + spiceCommandAtEndFile[ii].Remove( 0, +BUFYPOS_LEN ); + spiceCommandAtEndFile[ii].Trim( true ); + spiceCommandAtEndFile[ii].Trim( false ); + ret |= fprintf( f, "%s\n", TO_UTF8( spiceCommandAtEndFile[ii] ) ); + } + } + + ret |= fprintf( f, "\n.end\n" ); + fclose( f ); + + return ret >= 0; +} diff --git a/eeschema/netlist_exporters/netlist_exporter_pspice.h b/eeschema/netlist_exporters/netlist_exporter_pspice.h new file mode 100644 index 0000000..c57938f --- /dev/null +++ b/eeschema/netlist_exporters/netlist_exporter_pspice.h @@ -0,0 +1,50 @@ +/* + * This program source code file is part of KiCad, a free EDA CAD application. + * + * Copyright (C) 1992-2013 jp.charras at wanadoo.fr + * Copyright (C) 2013 SoftPLC Corporation, Dick Hollenbeck <dick@softplc.com> + * Copyright (C) 1992-2015 KiCad Developers + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, you may find one here: + * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html + * or you may search the http://www.gnu.org website for the version 2 license, + * or you may write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#ifndef NETLIST_EXPORTER_PSPICE_H +#define NETLIST_EXPORTER_PSPICE_H + +#include "netlist_exporter.h" + +/** + * Class NETLIST_EXPORTER_PSPICE + * generates a PSPICE compatible netlist + */ +class NETLIST_EXPORTER_PSPICE : public NETLIST_EXPORTER +{ +public: + NETLIST_EXPORTER_PSPICE( NETLIST_OBJECT_LIST* aMasterList, PART_LIBS* aLibs ) : + NETLIST_EXPORTER( aMasterList, aLibs ) + { + } + + /** + * Function WriteNetlist + * writes to specified output file + */ + bool WriteNetlist( const wxString& aOutFileName, unsigned aNetlistOptions ); +}; + +#endif |