Pcbnew: First draft to use a new netlist format ( containing the same info as the intermediate netlist, but using S expressions)

* Eeschema can generate this netlist format.
*   Pcbnew can use (automatic identification) the current format or the new format.
*   Cvpcb does not use yet the new format.
This commit is contained in:
jean-pierre charras 2012-01-26 10:37:36 +01:00
parent 4cbb5c5e94
commit 7eb1a136f1
15 changed files with 2392 additions and 1508 deletions

View File

@ -4,6 +4,16 @@ KiCad ChangeLog 2012
Please add newer entries at the top, list the date and your name with Please add newer entries at the top, list the date and your name with
email address. email address.
2012-Jan-26, UPDATE Jean-Pierre Charras <jp.charras@wanadoo.fr>
================================================================================
Pcbnew:
First draft to use a new netlist format (using S expressions)
Eeschema can generate this netlist format.
Pcbnew can use (automatic identification) the current format or the new format.
Cvpcb does not use yet the new format.
To do:
New format in Cvpcb: how to use the .cmp file with the new netlist format
2012-Jan-22 UPDATE Dick Hollenbeck <dick@softplc.com> 2012-Jan-22 UPDATE Dick Hollenbeck <dick@softplc.com>
================================================================================ ================================================================================

View File

@ -1,207 +0,0 @@
KiCad installation
==================
The parts of KiCad
------------------
KiCad consists of 3 packages:
kicad - KiCad programs and core files.
kicad-doc - Documentation and interactive help (optional package).
kicad-library - KiCad schematic, pcb & 3D-model libraries (optional package).
Installation from binary packages
---------------------------------
KiCad binary packages exist for Linux and Windows (XP, 2000).
Data files (schematic, boards, libraries) are compatible with all platforms.
*.zip - KiCad packages for Windows.
*.tbz2 - KiCad for Linux.
Installation from binary packages for Windows
---------------------------------------------
KiCad can be installed in 'C:\kicad', 'D:\kicad', 'C:\Program files\kicad',
'D:\Program files\kicad'.
For example, for an installation in the folder 'C:\kicad', unzip KiCad
packages:
kicad-{version}.zip
kicad-doc-{version}.zip
kicad-library-{version}.zip
to the folder 'C:\kicad'.
The main program is the project manager (kicad.exe) and from it you can run
the other programs (schematic editor - eeschema, pcb editor - pcbnew,
utilities: cvpcb and gerbview).
You can create a shortcut to 'C:\kicad\bin\kicad.exe'.
Installation from binary packages for Linux
-------------------------------------------
KiCad can be installed in '/usr' or '/usr/local'.
You must have "root" access for installation.
cd /
tar -xjf kicad-{version}.tbz2
tar -xjf kicad-doc-{version}.tbz2
tar -xjf kicad-library-{version}.tbz2
The main program is '/usr/bin/kicad'.
Windows KiCad tree
------------------
kicad/bin - Binaries (executable files).
kicad/doc - Various documentation.
kicad/doc/help - Interactive help.
kicad/share/demos - Sample schematics and printed boards.
kicad/share/internat - Interface localization files.
kicad/share/library - Libraries for schematic.
kicad/share/modules - Module libraries for printed boards.
kicad/share/modules/packages3d - 3D component models (.wrl and .wings format).
Files '*.mod' are libraries, and files '*.brd' are printed boards you can
view with pcbnew.
Files *.brd show the existing modules (and 3D shapes) in libraries.
Linux KiCad tree
----------------
/usr/bin - Binaries (executable files).
/usr/share/doc/kicad/ - Various documentation.
/usr/share/doc/kicad/help - Interactive help.
/usr/share/kicad/demos - Sample schematics and printed boards.
/usr/share/kicad/internat - Dictionaries for interface localization.
/usr/share/kicad/library - Interface localization files.
/usr/share/kicad/modules - Module libraries for printed boards.
/usr/share/kicad/modules/packages3d - 3D component models (.wrl and .wings format).
if not found search kicad in
/usr/local/
and if found, kicad uses the same tree as the Windows KiCad tree above
Files '*.mod' are the libraries, and files '*.brd' are printed boards you can
view with pcbnew.
Files *.brd show the existing modules (and 3D shapes) in libraries.
Warning:
Do not change the KiCad tree, or the location of binary files,
else KiCad will not be able to find its required files (configuration,
libraries, etc.).
Mac OS X KiCad tree
-------------------
System wide files
/Library/Application Support/kicad/demos
/Library/Application Support/kicad/internat
/Library/Application Support/kicad/library
/Library/Application Support/kicad/modules
/Library/Application Support/kicad/modules/packages3d
User files can be the same as the system wide files but only inside the users home directory.
$HOME/Library/Application Support/kicad
Warning:
These paths are hardcoded into KiCad, if you put them somewhere else KiCad will not find them when a new
project is created.
Installation from source code
-----------------------------
Some dependencies must be satisfied for the correct installation of KiCad:
wxWidgets >= 2.8.11 http://www.wxwidgets.org/
CMake >= 2.6.4 http://www.cmake.org/
Boost C++ Libraries (files used by kicad are provided in kicad sources) http://www.boost.org/
OpenGL
Linux: Mesa 3D Graphics Library http://www.mesa3d.org/
Windows: built-in
Zlib Compression Library http://www.zlib.net/
In source-tree-build are mostly unwanted, so make a subdir called "build" and
change to it.
Call cmake with the path to KiCad. E.g., when your build-folder is "build"
within source-tree, type "cmake ../".
Now your system get checked if it is able compiling KiCad and cmake generates
the Makefiles.
After calling cmake just type "make" and build begins.
It is easy to build only a specific binary such as pcbnew alone:
make pcbnew
After "make" type "make install" and install begins.
You may install to a temporary-root with
make install DESTDIR=<temproot>
If you want to uninstall KiCad again type "make uninstall" from within the
build directory.
Important parameters to cmake
-----------------------------
-DCMAKE_BUILD_TYPE=<buildtype>
<buildtype> may current one of "Debug" and "Release".
-DCMAKE_INSTALL_PREFIX=<prefix>
Default to "/usr/local".
-DwxWidgets_ROOT_DIR=<wxInstallDir>
Required for Windows platform.
-DwxWidgets_USE_DEBUG=ON
Can be used only with -DCMAKE_BUILD_TYPE=Debug
-DwxWidgets_USE_STATIC=ON
For building statically linked executables. Can be used only if wxWidgets
configured and builded with "--enable-monolithic --disable-shared" parameters.
-DwxWidgets_USE_STATIC=OFF
For building dinamically linked executables. Can be used only if wxWidgets
configured and builded with "--disable-monolithic --enable-shared" parameters.
-DwxUSE_UNICODE=ON
Require on locale utf8 for build the KiCad with cyrillic fonts support.
-DKICAD_GOST=ON
Build the KiCad with russian GOST support.
-DKICAD_KEEPCASE=ON
Build the KiCad with no component name conversion to uppercase (if you want your
ADuC.../Si.../bq... components named as just so).
-DCMAKE_CXX_FLAGS=<some extra flags>
Extra flags for the c++ compiler for your system required.
-DCMAKE_VERBOSE_MAKEFILE=ON
When more output is wanted use this cmake parameter or call "make VERBOSE=1".
Extra CFLAGS and linker flags
-----------------------------
If you require extra flags for compiler and linker you may give them via
environment variables
"CXXFLAGS" (c++ compiler)
"LDFLAGS" (for linker)
"CFLAGS" (for c-compiler, not needed in kdesvn build)
eg., it may usefull on 64bit systems "-m64" to CXXFLAGS and LDFLAGS.

File diff suppressed because it is too large Load Diff

View File

@ -24,7 +24,7 @@
*/ */
/** /**
* @file netform.cpp * @file eeschema/netform.cpp
* @brief Net list generation code. * @brief Net list generation code.
*/ */
@ -47,8 +47,6 @@
#include <wx/tokenzr.h> #include <wx/tokenzr.h>
#include <xnode.h> // also nests: <wx/xml/xml.h> #include <xnode.h> // also nests: <wx/xml/xml.h>
#include <build_version.h> #include <build_version.h>
@ -57,13 +55,6 @@
#include <set> #include <set>
/**
* @bug - Every place in this file where fprintf() is used and the return
* is not checked is a bug. The fprintf() function can fail and
* returns a value less than 0 when it does.
*/
/** /**
* Class UNIQUE_STRINGS * Class UNIQUE_STRINGS
* tracks unique wxStrings and is useful in telling if a string * tracks unique wxStrings and is useful in telling if a string
@ -99,18 +90,19 @@ bool UNIQUE_STRINGS::Lookup( const wxString& aString )
/** /**
* Class EXPORT_HELP * Class NETLIST_EXPORT_TOOL
* is a private implementation class used in this source file to keep track * is a private implementation class used in this source file to keep track
* of and recycle datastructures used in the generation of various exported netlist * of and recycle datastructures used in the generation of various exported netlist
* files. Since it is private it is not in a header file. * files. Since it is private it is not in a header file.
*/ */
class EXPORT_HELP class NETLIST_EXPORT_TOOL
{ {
/// Used to temporary store and filter the list of pins of a schematic component /// Used to temporary store and filter the list of pins of a schematic component
/// when generating schematic component data in netlist (comp section) /// when generating schematic component data in netlist (comp section)
NETLIST_OBJECT_LIST m_SortedComponentPinList; NETLIST_OBJECT_LIST m_SortedComponentPinList;
/// Used for "multi parts per package" components, avoids processing a lib component more than once. /// Used for "multi parts per package" components,
/// avoids processing a lib component more than once.
UNIQUE_STRINGS m_ReferencesAlreadyFound; UNIQUE_STRINGS m_ReferencesAlreadyFound;
// share a code generated std::set<void*> to reduce code volume // share a code generated std::set<void*> to reduce code volume
@ -196,7 +188,7 @@ class EXPORT_HELP
* - 6 CA * - 6 CA
* </p> * </p>
*/ */
void writeListOfNetsCADSTAR( FILE* f, NETLIST_OBJECT_LIST& aObjectsList ); bool writeListOfNetsCADSTAR( FILE* f, NETLIST_OBJECT_LIST& aObjectsList );
/** /**
* Function makeGenericRoot * Function makeGenericRoot
@ -240,6 +232,16 @@ class EXPORT_HELP
public: public:
/**
* Function WriteKiCadNetList
* creates a netlist, using the S expressions.
* the netlist creates the same data as the generic XML netlist,
* but using SWEET (or S expression), more easy to read and faster to parse
* @param aOutFileName = the full filename of the file to create
* @return bool - true if there were no errors, else false.
*/
bool WriteKiCadNetList( const wxString& aOutFileName );
/** /**
* Function WriteGENERICNetList * Function WriteGENERICNetList
* creates a generic netlist, now in XML. * creates a generic netlist, now in XML.
@ -286,7 +288,7 @@ public:
* .. B * T3 1 * .. B * T3 1
*U1 * 14 *U1 * 14
*/ */
void WriteNetListCADSTAR( FILE* f ); bool WriteNetListCADSTAR( FILE* f );
/** /**
* Function WriteNetListPspice * Function WriteNetListPspice
@ -338,7 +340,7 @@ public:
}; };
wxString EXPORT_HELP::MakeCommandLine( const wxString& aFormatString, wxString NETLIST_EXPORT_TOOL::MakeCommandLine( const wxString& aFormatString,
const wxString& aTempfile, const wxString& aFinalFile ) const wxString& aTempfile, const wxString& aFinalFile )
{ {
wxString ret = aFormatString; wxString ret = aFormatString;
@ -353,26 +355,29 @@ wxString EXPORT_HELP::MakeCommandLine( const wxString& aFormatString,
} }
/** /* Function WriteNetListFile
* Function WriteNetListFile
* creates the netlist file. Netlist info must be existing * creates the netlist file. Netlist info must be existing
* @param aFormat = netlist format (NET_TYPE_PCBNEW ...) * param aFormat = netlist format (NET_TYPE_PCBNEW ...)
* @param aFullFileName = full netlist file name * param aFullFileName = full netlist file name
* @param aUse_netnames = bool. if true, use net names from labels in schematic * param aNetlistOptions = netlist options using OR'ed bits.
* if false, use net numbers (net codes) * For SPICE netlist only:
* bool aUse_netnames is used only for Spice netlist * if NET_USE_NETNAMES is set, use net names from labels in schematic
* @param aUsePrefix = true, adds an 'X' prefix to any reference designator starting with "U" or "IC", * else use net numbers (net codes)
* false to leave reference designator unchanged. * if NET_USE_X_PREFIX is set : change "U" and "IC" refernce prefix to "X"
* @return true if success. * return true if success.
*/ */
bool SCH_EDIT_FRAME::WriteNetListFile( int aFormat, const wxString& aFullFileName, bool SCH_EDIT_FRAME::WriteNetListFile( int aFormat, const wxString& aFullFileName,
bool aUse_netnames, bool aUsePrefix ) unsigned aNetlistOptions )
{ {
bool ret = true; bool ret = true;
FILE* f = NULL; FILE* f = NULL;
EXPORT_HELP helper; NETLIST_EXPORT_TOOL helper;
if( aFormat < NET_TYPE_CUSTOM1 ) bool open_file = aFormat < NET_TYPE_CUSTOM1;
if( (aFormat == NET_TYPE_PCBNEW) && (aNetlistOptions & NET_PCBNEW_USE_NEW_FORMAT ) )
open_file = false;
if( open_file )
{ {
if( ( f = wxFopen( aFullFileName, wxT( "wt" ) ) ) == NULL ) if( ( f = wxFopen( aFullFileName, wxT( "wt" ) ) ) == NULL )
{ {
@ -387,8 +392,13 @@ bool SCH_EDIT_FRAME::WriteNetListFile( int aFormat, const wxString& aFullFileNam
switch( aFormat ) switch( aFormat )
{ {
case NET_TYPE_PCBNEW: case NET_TYPE_PCBNEW:
if( (aNetlistOptions & NET_PCBNEW_USE_NEW_FORMAT ) )
ret = helper.WriteKiCadNetList( aFullFileName );
else
{
ret = helper.WriteNetListPCBNEW( f, true ); ret = helper.WriteNetListPCBNEW( f, true );
fclose( f ); fclose( f );
}
break; break;
case NET_TYPE_ORCADPCB2: case NET_TYPE_ORCADPCB2:
@ -397,12 +407,14 @@ bool SCH_EDIT_FRAME::WriteNetListFile( int aFormat, const wxString& aFullFileNam
break; break;
case NET_TYPE_CADSTAR: case NET_TYPE_CADSTAR:
helper.WriteNetListCADSTAR( f ); ret = helper.WriteNetListCADSTAR( f );
fclose( f ); fclose( f );
break; break;
case NET_TYPE_SPICE: case NET_TYPE_SPICE:
ret = helper.WriteNetListPspice( f, aUse_netnames, aUsePrefix ); ret = helper.WriteNetListPspice( f,
aNetlistOptions & NET_USE_NETNAMES,
aNetlistOptions & NET_USE_X_PREFIX );
fclose( f ); fclose( f );
break; break;
@ -425,7 +437,7 @@ bool SCH_EDIT_FRAME::WriteNetListFile( int aFormat, const wxString& aFullFileNam
// "xsltproc -o %O /usr/local/lib/kicad/plugins/netlist_form_pads-pcb.xsl %I" // "xsltproc -o %O /usr/local/lib/kicad/plugins/netlist_form_pads-pcb.xsl %I"
// becomes, after the user selects /tmp/s1.net as the output file from the file dialog: // becomes, after the user selects /tmp/s1.net as the output file from the file dialog:
// "xsltproc -o /tmp/s1.net /usr/local/lib/kicad/plugins/netlist_form_pads-pcb.xsl /tmp/s1.xml" // "xsltproc -o /tmp/s1.net /usr/local/lib/kicad/plugins/netlist_form_pads-pcb.xsl /tmp/s1.xml"
wxString commandLine = EXPORT_HELP::MakeCommandLine( m_netListerCommand, wxString commandLine = NETLIST_EXPORT_TOOL::MakeCommandLine( m_netListerCommand,
tmpFile.GetFullPath(), tmpFile.GetFullPath(),
aFullFileName ); aFullFileName );
@ -456,7 +468,7 @@ static bool sortPinsByNumber( LIB_PIN* aPin1, LIB_PIN* aPin2 )
} }
void EXPORT_HELP::sprintPinNetName( wxString* aResult, void NETLIST_EXPORT_TOOL::sprintPinNetName( wxString* aResult,
const wxString& aNetNameFormat, NETLIST_OBJECT* aPin ) const wxString& aNetNameFormat, NETLIST_OBJECT* aPin )
{ {
int netcode = aPin->GetNet(); int netcode = aPin->GetNet();
@ -496,7 +508,7 @@ void EXPORT_HELP::sprintPinNetName( wxString* aResult,
} }
SCH_COMPONENT* EXPORT_HELP::findNextComponent( EDA_ITEM* aItem, SCH_SHEET_PATH* aSheetPath ) SCH_COMPONENT* NETLIST_EXPORT_TOOL::findNextComponent( EDA_ITEM* aItem, SCH_SHEET_PATH* aSheetPath )
{ {
wxString ref; wxString ref;
@ -543,7 +555,7 @@ SCH_COMPONENT* EXPORT_HELP::findNextComponent( EDA_ITEM* aItem, SCH_SHEET_PATH*
} }
SCH_COMPONENT* EXPORT_HELP::findNextComponentAndCreatePinList( EDA_ITEM* aItem, SCH_COMPONENT* NETLIST_EXPORT_TOOL::findNextComponentAndCreatePinList( EDA_ITEM* aItem,
SCH_SHEET_PATH* aSheetPath ) SCH_SHEET_PATH* aSheetPath )
{ {
wxString ref; wxString ref;
@ -643,7 +655,7 @@ static XNODE* node( const wxString& aName, const wxString& aTextualContent = wxE
} }
XNODE* EXPORT_HELP::makeGenericDesignHeader() XNODE* NETLIST_EXPORT_TOOL::makeGenericDesignHeader()
{ {
XNODE* xdesign = node( wxT("design") ); XNODE* xdesign = node( wxT("design") );
@ -682,7 +694,7 @@ XNODE* EXPORT_HELP::makeGenericDesignHeader()
} }
XNODE* EXPORT_HELP::makeGenericLibraries() XNODE* NETLIST_EXPORT_TOOL::makeGenericLibraries()
{ {
XNODE* xlibs = node( wxT( "libraries" ) ); // auto_ptr XNODE* xlibs = node( wxT( "libraries" ) ); // auto_ptr
@ -702,7 +714,7 @@ XNODE* EXPORT_HELP::makeGenericLibraries()
} }
XNODE* EXPORT_HELP::makeGenericLibParts() XNODE* NETLIST_EXPORT_TOOL::makeGenericLibParts()
{ {
XNODE* xlibparts = node( wxT( "libparts" ) ); // auto_ptr XNODE* xlibparts = node( wxT( "libparts" ) ); // auto_ptr
wxString sLibpart = wxT( "libpart" ); wxString sLibpart = wxT( "libpart" );
@ -780,8 +792,8 @@ XNODE* EXPORT_HELP::makeGenericLibParts()
/* we must erase redundant Pins references in pinList /* we must erase redundant Pins references in pinList
* These redundant pins exist because some pins * These redundant pins exist because some pins
* are found more than one time when we have a component * are found more than one time when a component has
* multiple parts per package or have 2 representations (DeMorgan conversion) * multiple parts per package or has 2 representations (DeMorgan conversion)
* For instance, a 74ls00 has DeMorgan conversion, with different pin shapes, * For instance, a 74ls00 has DeMorgan conversion, with different pin shapes,
* and therefore each pin appears 2 times in the list. * and therefore each pin appears 2 times in the list.
* Common pins (VCC, GND) can also be found more than once. * Common pins (VCC, GND) can also be found more than once.
@ -819,7 +831,7 @@ XNODE* EXPORT_HELP::makeGenericLibParts()
} }
XNODE* EXPORT_HELP::makeGenericListOfNets() XNODE* NETLIST_EXPORT_TOOL::makeGenericListOfNets()
{ {
XNODE* xnets = node( wxT( "nets" ) ); // auto_ptr if exceptions ever get used. XNODE* xnets = node( wxT( "nets" ) ); // auto_ptr if exceptions ever get used.
wxString netCodeTxt; wxString netCodeTxt;
@ -908,7 +920,7 @@ XNODE* EXPORT_HELP::makeGenericListOfNets()
} }
XNODE* EXPORT_HELP::makeGenericRoot() XNODE* NETLIST_EXPORT_TOOL::makeGenericRoot()
{ {
XNODE* xroot = node( wxT( "export" ) ); XNODE* xroot = node( wxT( "export" ) );
@ -930,7 +942,7 @@ XNODE* EXPORT_HELP::makeGenericRoot()
} }
XNODE* EXPORT_HELP::makeGenericComponents() XNODE* NETLIST_EXPORT_TOOL::makeGenericComponents()
{ {
XNODE* xcomps = node( wxT( "components" ) ); XNODE* xcomps = node( wxT( "components" ) );
@ -1045,16 +1057,12 @@ XNODE* EXPORT_HELP::makeGenericComponents()
#include <wx/wfstream.h> // wxFFileOutputStream #include <wx/wfstream.h> // wxFFileOutputStream
bool EXPORT_HELP::WriteGENERICNetList( const wxString& aOutFileName ) bool NETLIST_EXPORT_TOOL::WriteKiCadNetList( const wxString& aOutFileName )
{ {
// Prepare list of nets generation // Prepare list of nets generation
for( unsigned ii = 0; ii < g_NetObjectslist.size(); ii++ ) for( unsigned ii = 0; ii < g_NetObjectslist.size(); ii++ )
g_NetObjectslist[ii]->m_Flag = 0; g_NetObjectslist[ii]->m_Flag = 0;
#if 0
// this code seems to work now, for S-expression support.
bool rc = false; bool rc = false;
wxFFileOutputStream os( aOutFileName, wxT( "wt" ) ); wxFFileOutputStream os( aOutFileName, wxT( "wt" ) );
@ -1084,8 +1092,15 @@ bool EXPORT_HELP::WriteGENERICNetList( const wxString& aOutFileName )
} }
return rc; return rc;
}
#elif 1 bool NETLIST_EXPORT_TOOL::WriteGENERICNetList( const wxString& aOutFileName )
{
// Prepare list of nets generation
for( unsigned ii = 0; ii < g_NetObjectslist.size(); ii++ )
g_NetObjectslist[ii]->m_Flag = 0;
#if 1
// output the XML format netlist. // output the XML format netlist.
wxXmlDocument xdoc; wxXmlDocument xdoc;
@ -1187,7 +1202,7 @@ bool EXPORT_HELP::WriteGENERICNetList( const wxString& aOutFileName )
} }
bool EXPORT_HELP::WriteNetListPspice( FILE* f, bool use_netnames, bool aUsePrefix ) bool NETLIST_EXPORT_TOOL::WriteNetListPspice( FILE* f, bool use_netnames, bool aUsePrefix )
{ {
int ret = 0; int ret = 0;
int nbitems; int nbitems;
@ -1289,7 +1304,7 @@ bool EXPORT_HELP::WriteNetListPspice( FILE* f, bool use_netnames, bool aUsePrefi
for( SCH_SHEET_PATH* sheet = sheetList.GetFirst(); sheet; sheet = sheetList.GetNext() ) for( SCH_SHEET_PATH* sheet = sheetList.GetFirst(); sheet; sheet = sheetList.GetNext() )
{ {
fprintf( f, "*Sheet Name:%s\n", TO_UTF8( sheet->PathHumanReadable() ) ); ret |= fprintf( f, "*Sheet Name:%s\n", TO_UTF8( sheet->PathHumanReadable() ) );
for( EDA_ITEM* item = sheet->LastDrawList(); item; item = item->Next() ) for( EDA_ITEM* item = sheet->LastDrawList(); item; item = item->Next() )
{ {
@ -1439,14 +1454,14 @@ bool EXPORT_HELP::WriteNetListPspice( FILE* f, bool use_netnames, bool aUsePrefi
for( unsigned i = 0; i < pinSequence.size(); ++i ) for( unsigned i = 0; i < pinSequence.size(); ++i )
{ {
if( i==0 ) if( i==0 )
fprintf( f, ";Node Sequence Spec.<" ); ret |= fprintf( f, ";Node Sequence Spec.<" );
fprintf( f, "%s", TO_UTF8( stdPinNameArray.Item( pinSequence[i] ) ) ); ret |= fprintf( f, "%s", TO_UTF8( stdPinNameArray.Item( pinSequence[i] ) ) );
if( i < pinSequence.size()-1 ) if( i < pinSequence.size()-1 )
fprintf( f, "," ); ret |= fprintf( f, "," );
else else
fprintf( f, ">" ); ret |= fprintf( f, ">" );
} }
// Next Netlist line record: // Next Netlist line record:
@ -1478,7 +1493,7 @@ bool EXPORT_HELP::WriteNetListPspice( FILE* f, bool use_netnames, bool aUsePrefi
} }
bool EXPORT_HELP::WriteNetListPCBNEW( FILE* f, bool with_pcbnew ) bool NETLIST_EXPORT_TOOL::WriteNetListPCBNEW( FILE* f, bool with_pcbnew )
{ {
wxString field; wxString field;
wxString footprint; wxString footprint;
@ -1623,7 +1638,7 @@ bool EXPORT_HELP::WriteNetListPCBNEW( FILE* f, bool with_pcbnew )
} }
bool EXPORT_HELP::addPinToComponentPinList( SCH_COMPONENT* aComponent, bool NETLIST_EXPORT_TOOL::addPinToComponentPinList( SCH_COMPONENT* aComponent,
SCH_SHEET_PATH* aSheetPath, LIB_PIN* aPin ) SCH_SHEET_PATH* aSheetPath, LIB_PIN* aPin )
{ {
// Search the PIN description for Pin in g_NetObjectslist // Search the PIN description for Pin in g_NetObjectslist
@ -1662,12 +1677,12 @@ bool EXPORT_HELP::addPinToComponentPinList( SCH_COMPONENT* aComponent,
* remove duplicate pins from aPinList (list of pins relative to a given component) * remove duplicate pins from aPinList (list of pins relative to a given component)
* (i.e. set pointer to duplicate pins to NULL in this list). * (i.e. set pointer to duplicate pins to NULL in this list).
* also set .m_Flag member of "removed" NETLIST_OBJECT pins to 1 * also set .m_Flag member of "removed" NETLIST_OBJECT pins to 1
* When pins are duplicated, not connected duplicate is removed
* (for instance when a multiple part per package component has its power pins connected
* only on a part).
*/ */
void EXPORT_HELP::eraseDuplicatePins( ) void NETLIST_EXPORT_TOOL::eraseDuplicatePins( )
{ {
if( m_SortedComponentPinList.size() == 0 ) // Trivial case: component with no pin
return;
for( unsigned ii = 0; ii < m_SortedComponentPinList.size(); ii++ ) for( unsigned ii = 0; ii < m_SortedComponentPinList.size(); ii++ )
{ {
if( m_SortedComponentPinList[ii] == NULL ) /* already deleted */ if( m_SortedComponentPinList[ii] == NULL ) /* already deleted */
@ -1717,7 +1732,7 @@ void EXPORT_HELP::eraseDuplicatePins( )
} }
void EXPORT_HELP::findAllInstancesOfComponent( SCH_COMPONENT* aComponent, void NETLIST_EXPORT_TOOL::findAllInstancesOfComponent( SCH_COMPONENT* aComponent,
LIB_COMPONENT* aEntry, LIB_COMPONENT* aEntry,
SCH_SHEET_PATH* aSheetPath ) SCH_SHEET_PATH* aSheetPath )
{ {
@ -1759,7 +1774,7 @@ void EXPORT_HELP::findAllInstancesOfComponent( SCH_COMPONENT* aComponent,
} }
bool EXPORT_HELP::writeGENERICListOfNets( FILE* f, NETLIST_OBJECT_LIST& aObjectsList ) bool NETLIST_EXPORT_TOOL::writeGENERICListOfNets( FILE* f, NETLIST_OBJECT_LIST& aObjectsList )
{ {
int ret = 0; int ret = 0;
int netCode; int netCode;
@ -1852,8 +1867,9 @@ bool EXPORT_HELP::writeGENERICListOfNets( FILE* f, NETLIST_OBJECT_LIST& aObjects
static wxString StartLine( wxT( "." ) ); static wxString StartLine( wxT( "." ) );
void EXPORT_HELP::WriteNetListCADSTAR( FILE* f ) bool NETLIST_EXPORT_TOOL::WriteNetListCADSTAR( FILE* f )
{ {
int ret = 0;
wxString StartCmpDesc = StartLine + wxT( "ADD_COM" ); wxString StartCmpDesc = StartLine + wxT( "ADD_COM" );
wxString msg; wxString msg;
wxString footprint; wxString footprint;
@ -1862,11 +1878,11 @@ void EXPORT_HELP::WriteNetListCADSTAR( FILE* f )
SCH_COMPONENT* Component; SCH_COMPONENT* Component;
wxString Title = wxGetApp().GetAppName() + wxT( " " ) + GetBuildVersion(); wxString Title = wxGetApp().GetAppName() + wxT( " " ) + GetBuildVersion();
fprintf( f, "%sHEA\n", TO_UTF8( StartLine ) ); ret |= fprintf( f, "%sHEA\n", TO_UTF8( StartLine ) );
fprintf( f, "%sTIM %s\n", TO_UTF8( StartLine ), TO_UTF8( DateAndTime() ) ); ret |= fprintf( f, "%sTIM %s\n", TO_UTF8( StartLine ), TO_UTF8( DateAndTime() ) );
fprintf( f, "%sAPP ", TO_UTF8( StartLine ) ); ret |= fprintf( f, "%sAPP ", TO_UTF8( StartLine ) );
fprintf( f, "\"%s\"\n", TO_UTF8( Title ) ); ret |= fprintf( f, "\"%s\"\n", TO_UTF8( Title ) );
fprintf( f, "\n" ); ret |= fprintf( f, "\n" );
// Prepare list of nets generation // Prepare list of nets generation
for( unsigned ii = 0; ii < g_NetObjectslist.size(); ii++ ) for( unsigned ii = 0; ii < g_NetObjectslist.size(); ii++ )
@ -1898,28 +1914,32 @@ void EXPORT_HELP::WriteNetListCADSTAR( FILE* f )
*/ */
msg = Component->GetRef( sheet ); msg = Component->GetRef( sheet );
fprintf( f, "%s ", TO_UTF8( StartCmpDesc ) ); ret |= fprintf( f, "%s ", TO_UTF8( StartCmpDesc ) );
fprintf( f, "%s", TO_UTF8( msg ) ); ret |= fprintf( f, "%s", TO_UTF8( msg ) );
msg = Component->GetField( VALUE )->m_Text; msg = Component->GetField( VALUE )->m_Text;
msg.Replace( wxT( " " ), wxT( "_" ) ); msg.Replace( wxT( " " ), wxT( "_" ) );
fprintf( f, " \"%s\"", TO_UTF8( msg ) ); ret |= fprintf( f, " \"%s\"", TO_UTF8( msg ) );
fprintf( f, "\n" ); ret |= fprintf( f, "\n" );
} }
} }
fprintf( f, "\n" ); ret |= fprintf( f, "\n" );
m_SortedComponentPinList.clear(); m_SortedComponentPinList.clear();
writeListOfNetsCADSTAR( f, g_NetObjectslist ); if( ! writeListOfNetsCADSTAR( f, g_NetObjectslist ) )
ret = -1; // set error
fprintf( f, "\n%sEND\n", TO_UTF8( StartLine ) ); ret |= fprintf( f, "\n%sEND\n", TO_UTF8( StartLine ) );
return ret >= 0;
} }
void EXPORT_HELP::writeListOfNetsCADSTAR( FILE* f, NETLIST_OBJECT_LIST& aObjectsList ) bool NETLIST_EXPORT_TOOL::writeListOfNetsCADSTAR( FILE* f, NETLIST_OBJECT_LIST& aObjectsList )
{ {
int ret = 0;
wxString InitNetDesc = StartLine + wxT( "ADD_TER" ); wxString InitNetDesc = StartLine + wxT( "ADD_TER" );
wxString StartNetDesc = StartLine + wxT( "TER" ); wxString StartNetDesc = StartLine + wxT( "TER" );
wxString netcodeName, InitNetDescLine; wxString netcodeName, InitNetDescLine;
@ -1991,8 +2011,8 @@ void EXPORT_HELP::writeListOfNetsCADSTAR( FILE* f, NETLIST_OBJECT_LIST& aObjects
break; break;
case 1: case 1:
fprintf( f, "%s\n", TO_UTF8( InitNetDescLine ) ); ret |= fprintf( f, "%s\n", TO_UTF8( InitNetDescLine ) );
fprintf( f, "%s %s %.4s\n", ret |= fprintf( f, "%s %s %.4s\n",
TO_UTF8( StartNetDesc ), TO_UTF8( StartNetDesc ),
TO_UTF8( refstr ), TO_UTF8( refstr ),
(char*) &aObjectsList[ii]->m_PinNum ); (char*) &aObjectsList[ii]->m_PinNum );
@ -2000,7 +2020,7 @@ void EXPORT_HELP::writeListOfNetsCADSTAR( FILE* f, NETLIST_OBJECT_LIST& aObjects
break; break;
default: default:
fprintf( f, " %s %.4s\n", ret |= fprintf( f, " %s %.4s\n",
TO_UTF8( refstr ), TO_UTF8( refstr ),
(char*) &aObjectsList[ii]->m_PinNum ); (char*) &aObjectsList[ii]->m_PinNum );
break; break;
@ -2008,4 +2028,6 @@ void EXPORT_HELP::writeListOfNetsCADSTAR( FILE* f, NETLIST_OBJECT_LIST& aObjects
aObjectsList[ii]->m_Flag = 1; aObjectsList[ii]->m_Flag = 1;
} }
return ret >= 0;
} }

View File

@ -126,6 +126,7 @@ NETLIST_PAGE_DIALOG::NETLIST_PAGE_DIALOG( wxNotebook* parent,
m_IsCurrentFormat = NULL; m_IsCurrentFormat = NULL;
m_AddSubPrefix = NULL; m_AddSubPrefix = NULL;
m_ButtonCancel = NULL; m_ButtonCancel = NULL;
m_NetOption = NULL;
parent->AddPage( this, title, selected ); parent->AddPage( this, title, selected );
@ -153,7 +154,18 @@ NETLIST_PAGE_DIALOG::NETLIST_PAGE_DIALOG( wxNotebook* parent,
m_IsCurrentFormat->SetValue( selected ); m_IsCurrentFormat->SetValue( selected );
} }
/* Create the buttons: Create Neltist or browse Plugin and Cancel if( id_NetType == NET_TYPE_PCBNEW )
{
wxString netlist_opt[2] = { _( "Pcbnew Format" ), _( "Advanced Format" ) };
m_NetOption = new wxRadioBox( this, -1, _( "Netlist Options:" ),
wxDefaultPosition, wxDefaultSize,
2, netlist_opt, 1,
wxRA_SPECIFY_COLS );
m_LeftBoxSizer->Add( m_NetOption, 0, wxGROW | wxALL, 5 );
}
/* Create the buttons: Create Netlist or browse Plugin and Cancel
* and a third button for plugins : Remove or Ok button */ * and a third button for plugins : Remove or Ok button */
if( idCreateFile ) if( idCreateFile )
{ {
@ -275,15 +287,15 @@ void NETLIST_DIALOG::InstallPageSpice()
wxString netlist_opt[2] = { _( "Use Net Names" ), _( "Use Net Numbers" ) }; wxString netlist_opt[2] = { _( "Use Net Names" ), _( "Use Net Numbers" ) };
m_UseNetNamesInNetlist = new wxRadioBox( page, -1, _( "Netlist Options:" ), page->m_NetOption = new wxRadioBox( page, -1, _( "Netlist Options:" ),
wxDefaultPosition, wxDefaultSize, wxDefaultPosition, wxDefaultSize,
2, netlist_opt, 1, 2, netlist_opt, 1,
wxRA_SPECIFY_COLS ); wxRA_SPECIFY_COLS );
if( !g_OptNetListUseNames ) if( !g_OptNetListUseNames )
m_UseNetNamesInNetlist->SetSelection( 1 ); page->m_NetOption->SetSelection( 1 );
page->m_LeftBoxSizer->Add( m_UseNetNamesInNetlist, 0, wxGROW | wxALL, 5 ); page->m_LeftBoxSizer->Add( page->m_NetOption, 0, wxGROW | wxALL, 5 );
page->m_LowBoxSizer->Add( new wxStaticText( page, -1, _( "Simulator command:" ) ), 0, page->m_LowBoxSizer->Add( new wxStaticText( page, -1, _( "Simulator command:" ) ), 0,
wxGROW | wxLEFT | wxRIGHT | wxTOP | wxADJUST_MINSIZE, 5 ); wxGROW | wxLEFT | wxRIGHT | wxTOP | wxADJUST_MINSIZE, 5 );
@ -496,7 +508,7 @@ void NETLIST_DIALOG::NetlistUpdateOpt()
g_OptNetListUseNames = true; // Used for pspice, gnucap g_OptNetListUseNames = true; // Used for pspice, gnucap
if( m_UseNetNamesInNetlist->GetSelection() == 1 ) if( m_PanelNetType[PANELSPICE]->m_NetOption->GetSelection() == 1 )
g_OptNetListUseNames = false; g_OptNetListUseNames = false;
} }
@ -519,6 +531,8 @@ void NETLIST_DIALOG::GenNetlist( wxCommandEvent& event )
NETLIST_PAGE_DIALOG* CurrPage; NETLIST_PAGE_DIALOG* CurrPage;
CurrPage = (NETLIST_PAGE_DIALOG*) m_NoteBook->GetCurrentPage(); CurrPage = (NETLIST_PAGE_DIALOG*) m_NoteBook->GetCurrentPage();
unsigned netlist_opt = 0;
/* Calculate the netlist filename */ /* Calculate the netlist filename */
fn = g_RootSheet->GetScreen()->GetFileName(); fn = g_RootSheet->GetScreen()->GetFileName();
@ -527,6 +541,11 @@ void NETLIST_DIALOG::GenNetlist( wxCommandEvent& event )
case NET_TYPE_SPICE: case NET_TYPE_SPICE:
fileExt = wxT( "cir" ); fileExt = wxT( "cir" );
fileWildcard = _( "SPICE netlist file (.cir)|*.cir" ); fileWildcard = _( "SPICE netlist file (.cir)|*.cir" );
// Set spice netlist options:
if( g_OptNetListUseNames )
netlist_opt |= NET_USE_NETNAMES;
if( CurrPage->m_AddSubPrefix->GetValue() )
netlist_opt |= NET_USE_X_PREFIX;
break; break;
case NET_TYPE_CADSTAR: case NET_TYPE_CADSTAR:
@ -535,13 +554,19 @@ void NETLIST_DIALOG::GenNetlist( wxCommandEvent& event )
break; break;
case NET_TYPE_PCBNEW: case NET_TYPE_PCBNEW:
if( CurrPage->m_NetOption->GetSelection() != 0 )
netlist_opt = NET_PCBNEW_USE_NEW_FORMAT;
fileExt = NetlistFileExtension;
fileWildcard = NetlistFileWildcard;
break;
case NET_TYPE_ORCADPCB2: case NET_TYPE_ORCADPCB2:
fileExt = NetlistFileExtension; fileExt = NetlistFileExtension;
fileWildcard = NetlistFileWildcard; fileWildcard = NetlistFileWildcard;
break; break;
default: // custom, NET_TYPE_CUSTOM1 and greater default: // custom, NET_TYPE_CUSTOM1 and greater
fileExt = wxEmptyString; // wxT( "" ); fileExt = wxEmptyString;
fileWildcard = AllFilesWildcard; fileWildcard = AllFilesWildcard;
title.Printf( _( "%s Export" ), CurrPage->m_TitleStringCtrl->GetValue().GetData() ); title.Printf( _( "%s Export" ), CurrPage->m_TitleStringCtrl->GetValue().GetData() );
} }
@ -562,12 +587,7 @@ void NETLIST_DIALOG::GenNetlist( wxCommandEvent& event )
else else
m_Parent->SetNetListerCommand( wxEmptyString ); m_Parent->SetNetListerCommand( wxEmptyString );
bool addSubPrefix = false; m_Parent->CreateNetlist( CurrPage->m_IdNetType, dlg.GetPath(), netlist_opt );
if( CurrPage->m_AddSubPrefix )
addSubPrefix = CurrPage->m_AddSubPrefix->GetValue();
m_Parent->CreateNetlist( CurrPage->m_IdNetType, dlg.GetPath(), g_OptNetListUseNames,
addSubPrefix );
WriteCurrentNetlistSetup(); WriteCurrentNetlistSetup();
@ -575,22 +595,17 @@ void NETLIST_DIALOG::GenNetlist( wxCommandEvent& event )
} }
/** /* Function CreateNetlist
* Function CreateNetlist * > test for some issues (missing or duplicate references and sheet names)
* Create a netlist file: * > build netlist info
* build netlist info * > create the netlist file
* test issues * param aFormat = netlist format (NET_TYPE_PCBNEW ...)
* create file * param aFullFileName = full netlist file name
* @param aFormat = netlist format (NET_TYPE_PCBNEW ...) * param aNetlistOptions = netlist options using OR'ed bits (see WriteNetListFile).
* @param aFullFileName = full netlist file name * return true if success.
* @param aUse_netnames = bool. if true, use net names from labels in schematic
* if false, use net numbers (net codes)
* bool aUse_netnames is used only for Spice netlist
* @return true if success.
*/ */
bool SCH_EDIT_FRAME::CreateNetlist( int aFormat, const wxString& aFullFileName, bool SCH_EDIT_FRAME::CreateNetlist( int aFormat, const wxString& aFullFileName,
bool aUse_netnames, unsigned aNetlistOptions )
bool aUsePrefix )
{ {
SCH_SHEET_LIST sheets; SCH_SHEET_LIST sheets;
sheets.AnnotatePowerSymbols(); sheets.AnnotatePowerSymbols();
@ -622,7 +637,7 @@ Do you want to annotate schematic?" ) ) )
screens.SchematicCleanUp(); screens.SchematicCleanUp();
BuildNetListBase(); BuildNetListBase();
bool success = WriteNetListFile( aFormat, aFullFileName, g_OptNetListUseNames, aUsePrefix ); bool success = WriteNetListFile( aFormat, aFullFileName, aNetlistOptions );
return success; return success;
} }
@ -651,17 +666,20 @@ void NETLIST_DIALOG::RunSimulator( wxCommandEvent& event )
fn.SetExt( wxT( "cir" ) ); fn.SetExt( wxT( "cir" ) );
CommandLine += wxT( " \"" ) + fn.GetFullPath() + wxT( "\"" ); CommandLine += wxT( " \"" ) + fn.GetFullPath() + wxT( "\"" );
g_OptNetListUseNames = m_UseNetNamesInNetlist->GetSelection() == 0;
NETLIST_PAGE_DIALOG* CurrPage; NETLIST_PAGE_DIALOG* CurrPage;
CurrPage = (NETLIST_PAGE_DIALOG*) m_NoteBook->GetCurrentPage(); CurrPage = (NETLIST_PAGE_DIALOG*) m_NoteBook->GetCurrentPage();
g_OptNetListUseNames = CurrPage->m_NetOption->GetSelection() == 0;
bool addSubPrefix = false; // Set spice netlist options:
unsigned netlist_opt = 0;
if( CurrPage->m_AddSubPrefix ) if( g_OptNetListUseNames )
addSubPrefix = CurrPage->m_AddSubPrefix->GetValue(); netlist_opt |= NET_USE_NETNAMES;
if( CurrPage->m_AddSubPrefix && CurrPage->m_AddSubPrefix->GetValue() )
netlist_opt |= NET_USE_X_PREFIX;
if( ! m_Parent->CreateNetlist( CurrPage->m_IdNetType, fn.GetFullPath(), if( ! m_Parent->CreateNetlist( CurrPage->m_IdNetType, fn.GetFullPath(),
g_OptNetListUseNames,addSubPrefix ) ) netlist_opt ) )
return; return;
ExecuteFile( this, ExecFile, CommandLine ); ExecuteFile( this, ExecFile, CommandLine );

View File

@ -7,8 +7,6 @@
#ifndef _NETLIST_CONTROL_H_ #ifndef _NETLIST_CONTROL_H_
#define _NETLIST_CONTROL_H_ #define _NETLIST_CONTROL_H_
class WinEDA_EnterText;
/* Event id for notebook page buttons: */ /* Event id for notebook page buttons: */
enum id_netlist { enum id_netlist {
@ -55,7 +53,9 @@ public:
wxBoxSizer* m_RightBoxSizer; wxBoxSizer* m_RightBoxSizer;
wxBoxSizer* m_RightOptionsBoxSizer; wxBoxSizer* m_RightOptionsBoxSizer;
wxBoxSizer* m_LowBoxSizer; wxBoxSizer* m_LowBoxSizer;
wxRadioBox* m_NetOption;
public:
/** Contructor to create a setup page for one netlist format. /** Contructor to create a setup page for one netlist format.
* Used in Netlist format Dialog box creation * Used in Netlist format Dialog box creation
* @param parent = wxNotebook * parent * @param parent = wxNotebook * parent
@ -75,7 +75,7 @@ public:
#define CUSTOMPANEL_COUNTMAX 8 // Max number of netlist plugins #define CUSTOMPANEL_COUNTMAX 8 // Max number of netlist plugins
/* Id to select netlist type */ // Id to select netlist type
enum TypeNetForm { enum TypeNetForm {
NET_TYPE_UNINIT = 0, NET_TYPE_UNINIT = 0,
NET_TYPE_PCBNEW, NET_TYPE_PCBNEW,
@ -90,6 +90,12 @@ enum TypeNetForm {
NET_TYPE_CUSTOM_MAX = NET_TYPE_CUSTOM1 + CUSTOMPANEL_COUNTMAX - 1 NET_TYPE_CUSTOM_MAX = NET_TYPE_CUSTOM1 + CUSTOMPANEL_COUNTMAX - 1
}; };
// Options for Spice netlist generation (OR'ed bits
enum netlistOptions {
NET_USE_NETNAMES = 1, // for Spice netlist : use netnames instead of numbers
NET_USE_X_PREFIX = 2, // for Spice netlist : change "U" and "IC" refernce prefix to "X"
NET_PCBNEW_USE_NEW_FORMAT = 1, // For Pcbnew use the new format (S expression and SWEET)
};
/* Dialog frame for creating netlists */ /* Dialog frame for creating netlists */
class NETLIST_DIALOG : public wxDialog class NETLIST_DIALOG : public wxDialog
@ -98,7 +104,6 @@ public:
SCH_EDIT_FRAME* m_Parent; SCH_EDIT_FRAME* m_Parent;
wxNotebook* m_NoteBook; wxNotebook* m_NoteBook;
NETLIST_PAGE_DIALOG* m_PanelNetType[4 + CUSTOMPANEL_COUNTMAX]; NETLIST_PAGE_DIALOG* m_PanelNetType[4 + CUSTOMPANEL_COUNTMAX];
wxRadioBox* m_UseNetNamesInNetlist;
public: public:

View File

@ -445,37 +445,43 @@ public:
/** /**
* Function CreateNetlist * Function CreateNetlist
* Create a netlist file: * <ul>
* build netlist info * <li> test for some issues (missing or duplicate references and sheet names)
* test issues * <li> build netlist info
* create file * <li> create the netlist file (different formats)
* </ul>
* @param aFormat = netlist format (NET_TYPE_PCBNEW ...) * @param aFormat = netlist format (NET_TYPE_PCBNEW ...)
* @param aFullFileName = full netlist file name * @param aFullFileName = full netlist file name
* @param aUse_netnames = bool. if true, use net names from labels in schematic * @param aNetlistOptions = netlist options using OR'ed bits.
* if false, use net numbers (net codes) * <p>
* bool aUse_netnames is used only for Spice netlist * For SPICE netlist only:
* @param aUsePrefix Prefix reference designator with an 'X' for spice output. * if NET_USE_NETNAMES is set, use net names from labels in schematic
* else use net numbers (net codes)
* if NET_USE_X_PREFIX is set : change "U" and "IC" refernce prefix to "X"
* </p>
* @return true if success. * @return true if success.
*/ */
bool CreateNetlist( int aFormat, bool CreateNetlist( int aFormat,
const wxString& aFullFileName, const wxString& aFullFileName,
bool aUse_netnames, unsigned aNetlistOptions );
bool aUsePrefix );
/** /**
* Function WriteNetListFile * Function WriteNetListFile
* Create the netlist file. Netlist info must be existing * Create the netlist file. Netlist info must be existing
* @param aFormat = netlist format (NET_TYPE_PCBNEW ...) * @param aFormat = netlist format (NET_TYPE_PCBNEW ...)
* @param aFullFileName = full netlist file name * @param aFullFileName = full netlist file name
* @param aUse_netnames = bool. if true, use net names from labels in schematic * @param aNetlistOptions = netlist options using OR'ed bits.
* if false, use net numbers (net codes) * <p>
* bool aUse_netnames is used only for Spice netlist * For SPICE netlist only:
* if NET_USE_NETNAMES is set, use net names from labels in schematic
* else use net numbers (net codes)
* if NET_USE_X_PREFIX is set : change "U" and "IC" refernce prefix to "X"
* </p>
* @return true if success. * @return true if success.
*/ */
bool WriteNetListFile( int aFormat, bool WriteNetListFile( int aFormat,
const wxString& aFullFileName, const wxString& aFullFileName,
bool aUse_netnames, unsigned aNetlistOptions );
bool aUsePrefix );
/** /**
* Function DeleteAnnotation * Function DeleteAnnotation

View File

@ -1336,12 +1336,11 @@ public:
/** /**
* Function RemoveMisConnectedTracks * Function RemoveMisConnectedTracks
* finds all track segments which are mis-connected (to more than one net). * finds all track segments which are mis-connected (to more than one net).
* When such a bad segment is found, mark it as needing to be removed. * When such a bad segment is found, it is flagged to be removed.
* and remove all tracks having at least one flagged segment. * All tracks having at least one flagged segment are removed.
* @param aDC = the current device context (can be NULL)
* @return true if any change is made * @return true if any change is made
*/ */
bool RemoveMisConnectedTracks( wxDC* aDC ); bool RemoveMisConnectedTracks();
// Autoplacement: // Autoplacement:

View File

@ -0,0 +1,61 @@
KiCad Free Documentation Licence
================================
Copyright (c) jean-pierre Charras
Copyright (C) KiCad Developers
Everyone is permitted to copy and distribute verbatim copies
of this licence document, but changing it is not allowed.
KICAD FREE DOCUMENTATION LICENCE
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
1. Permission is granted to make and distribute verbatim copies of this
manual or piece of documentation provided any copyright notice and this
permission notice are preserved on all copies.
2. Permission is granted to process this file or document through a
document processing system and, at your option and the option of any third
party, print the results, provided a printed document carries a copying
permission notice identical to this one.
3. Permission is granted to copy and distribute modified versions of this
manual or piece of documentation under the conditions for verbatim
copying, provided also that any sections describing licensing conditions
for this manual, such as, in particular, the GNU General Public Licence,
the GNU Library General Public Licence, and any wxWindows Licence are
included exactly as in the original, and provided that the entire
resulting derived work is distributed under the terms of a permission
notice identical to this one.
4. Permission is granted to copy and distribute translations of this
manual or piece of documentation into another language, under the above
conditions for modified versions, except that sections related to
licensing, including this paragraph, may also be included in translations
approved by the copyright holders of the respective licence documents in
addition to the original French or English.
WARRANTY DISCLAIMER
5. BECAUSE THIS MANUAL OR PIECE OF DOCUMENTATION IS LICENSED FREE OF CHARGE,
THERE IS NO WARRANTY FOR IT, TO THE EXTENT PERMITTED BY APPLICABLE LAW.
EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER
PARTIES PROVIDE THIS MANUAL OR PIECE OF DOCUMENTATION "AS IS" WITHOUT
WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF
THE MANUAL OR PIECE OF DOCUMENTATION IS WITH YOU. SHOULD THE MANUAL OR
PIECE OF DOCUMENTATION PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL
NECESSARY SERVICING, REPAIR OR CORRECTION.
6. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL
ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
REDISTRIBUTE THE MANUAL OR PIECE OF DOCUMENTATION AS PERMITTED ABOVE, BE
LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR
CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE
MANUAL OR PIECE OF DOCUMENTATION (INCLUDING BUT NOT LIMITED TO LOSS OF
DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
PARTIES OR A FAILURE OF A PROGRAM BASED ON THE MANUAL OR PIECE OF
DOCUMENTATION TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR
OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.

View File

@ -151,6 +151,8 @@ set(PCBNEW_SRCS
muonde.cpp muonde.cpp
muwave_command.cpp muwave_command.cpp
netlist.cpp netlist.cpp
netlist_reader_firstformat.cpp
netlist_reader_kicad.cpp
onleftclick.cpp onleftclick.cpp
onrightclick.cpp onrightclick.cpp
pcb_plot_params.cpp pcb_plot_params.cpp

View File

@ -686,8 +686,12 @@ TRACK* MergeColinearSegmentIfPossible( BOARD* aPcb, TRACK* aTrackRef, TRACK* aCa
} }
bool PCB_EDIT_FRAME::RemoveMisConnectedTracks( wxDC* aDC ) bool PCB_EDIT_FRAME::RemoveMisConnectedTracks()
{ {
/* finds all track segments which are mis-connected (to more than one net).
* When such a bad segment is found, it is flagged to be removed.
* All tracks having at least one flagged segment are removed.
*/
TRACK* segment; TRACK* segment;
TRACK* other; TRACK* other;
TRACK* next; TRACK* next;
@ -735,14 +739,14 @@ bool PCB_EDIT_FRAME::RemoveMisConnectedTracks( wxDC* aDC )
if( net_code_e < 0 ) if( net_code_e < 0 )
continue; // the "end" of segment is not connected continue; // the "end" of segment is not connected
// Netcodes do not agree, so mark the segment as needed to be removed // Netcodes do not agree, so mark the segment as "to be removed"
if( net_code_s != net_code_e ) if( net_code_s != net_code_e )
{ {
segment->SetState( FLAG0, ON ); segment->SetState( FLAG0, ON );
} }
} }
// Remove flagged segments // Remove tracks having a flagged segment
for( segment = GetBoard()->m_Track; segment; segment = next ) for( segment = GetBoard()->m_Track; segment; segment = next )
{ {
next = (TRACK*) segment->Next(); next = (TRACK*) segment->Next();
@ -752,9 +756,11 @@ bool PCB_EDIT_FRAME::RemoveMisConnectedTracks( wxDC* aDC )
segment->SetState( FLAG0, OFF ); segment->SetState( FLAG0, OFF );
isModified = true; isModified = true;
GetBoard()->m_Status_Pcb = 0; GetBoard()->m_Status_Pcb = 0;
Remove_One_Track( aDC, segment ); Remove_One_Track( NULL, segment );
// the current segment could be deleted, so restart to the beginning // the current segment is deleted,
// we do not know the next "not yet tested" segment,
// so restart to the beginning
next = GetBoard()->m_Track; next = GetBoard()->m_Track;
} }
} }

File diff suppressed because it is too large Load Diff

295
pcbnew/netlist_reader.h Normal file
View File

@ -0,0 +1,295 @@
#ifndef NETLIST_READER_H
#define NETLIST_READER_H
/**
* @file netlist_reader.h
*/
/*
* This program source code file is part of KiCad, a free EDA CAD application.
*
* Copyright (C) 2012 Jean-Pierre Charras.
* Copyright (C) 2012 KiCad Developers, see CHANGELOG.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 <algorithm>
#include <fctsys.h>
#include <kicad_string.h>
#include <wxPcbStruct.h>
#include <richio.h>
#include <macros.h>
#include <class_board.h>
#include <class_module.h>
#include <pcbnew.h>
/*
* Helper class, to store new footprints info found in netlist.
* New footprints are footprints relative to new components found in netlist
*/
class MODULE_INFO
{
public:
wxString m_Footprint;
wxString m_Reference;
wxString m_Value;
wxString m_TimeStamp;
public: MODULE_INFO( const wxString& libname,
const wxString& cmpname,
const wxString& value,
const wxString& timestamp )
{
m_Footprint = libname;
m_Reference = cmpname;
m_Value = value;
m_TimeStamp = timestamp;
}
~MODULE_INFO() { };
};
/*
* Helper class, to read a netlist.
*/
class NETLIST_READER
{
private:
PCB_EDIT_FRAME* m_pcbframe; // the main Pcbnew frame
wxTextCtrl* m_messageWindow; // a textctrl to show messages (can be NULL)
wxString m_netlistFullName; // The full netlist filename
wxString m_cmplistFullName; // The full component/footprint association filename
MODULE* m_currModule; // The footprint currently being read in netlist
std::vector <MODULE_INFO*> m_modulesInNetlist; // The list of footprints, found in netlist
// (must be loaded from libraries)
std::vector <MODULE_INFO*> m_newModulesList; // The list of new footprints,
// found in netlist, but not on board
// (must be loaded from libraries)
bool m_BuildModuleListOnly; // if true read netlist, populates m_modulesInNetlist
// but do not read and change nets and modules on board
public:
bool m_UseCmpFile; // true to use .cmp files as component/footprint file link
// false to use netlist only to know component/footprint link
bool m_UseTimeStamp; // Set to true to identify footprints by time stamp
// false to use schematic reference
bool m_ChangeFootprints; // Set to true to change existing footprints to new ones
// when netlist gives a different footprint name
public: NETLIST_READER( PCB_EDIT_FRAME* aFrame, wxTextCtrl* aMessageWindow = NULL )
{
m_pcbframe = aFrame;
m_messageWindow = aMessageWindow;
m_UseTimeStamp = false;
m_ChangeFootprints = false;
m_UseCmpFile = true;
m_BuildModuleListOnly = false;
}
~NETLIST_READER()
{
// Free modules info list:
for( unsigned ii = 0; ii < m_newModulesList.size(); ii++ )
delete m_modulesInNetlist[ii];
m_modulesInNetlist.clear();
m_newModulesList.clear();
}
std::vector <MODULE_INFO*>& GetModuleInfoList()
{
return m_modulesInNetlist;
}
/**
* Function AddModuleInfo
* Add a new module info to the main list of modules ifo
* @param aModInfo = a reference to the item to add
*/
void AddModuleInfo( MODULE_INFO* aModInfo )
{
m_modulesInNetlist.push_back( aModInfo );
}
/**
* Function BuildModuleListOnly
* Set to true or false the Build Module List Only option
* When this option is false, a full netlist read is made,
* and modules are added/modified
* When this option is true, a partial netlist read is made
* and only the list of modules found in netlist is built
* @param aOpt = the value of option
*/
void BuildModuleListOnly( bool aOpt )
{
m_BuildModuleListOnly = aOpt;
}
/**
* Function BuildModuleListOnly
* Get the Build Module List Only option state
* @return the state of option (true/false)
*/
bool BuildModuleListOnly()
{
return m_BuildModuleListOnly;
}
/**
* Function InitializeModules
* Called when reading a netlist and after the module info list is populated
* Load new module and clear pads netnames
* return true if all modules are loaded, false if some are missing
*/
bool InitializeModules();
/**
* Function TestFootprintsMatchingAndExchange
* Called when reading a netlist, after the module info list is populated
* module reference updated (after a call to InitializeModules)
* Test, for each module, if the current footprint matches the footprint
* given by the netlist (or the cmp file, if used)
* print a list of mismatches od exchange footprints i
* m_ChangeFootprints == true
*/
void TestFootprintsMatchingAndExchange();
/**
* Function SetFilesnames
* initialize filenames
* @param aNetlistFileName = full filename of netlist
* @param aCmplistFileName = full filename of components file (can be empty)
* and the components file will be non used
*/
void SetFilesnames( const wxString& aNetlistFileName,
const wxString& aCmplistFileName )
{
m_netlistFullName = aNetlistFileName;
m_cmplistFullName = aCmplistFileName;
}
/**
* Function ReadNetList
* The main function to detect a netlist format, read the netlist,
* and update the board
* depending on the detected format, calls ReadOldFmtdNetList or ReadKicadNetList
* @param aFile = the already opened file (will be closed by the netlist reader)
* @return true if success
*/
bool ReadNetList( FILE* aFile );
/**
* Function ReadOldFmtdNetList
* The main function to read a netlist (old netlist format),
* and update the board
* @param aFile = the already opened file (will be closed by ReadOldFmtdNetList)
* @return true if success
*/
bool ReadOldFmtdNetList( FILE* aFile );
/**
* Function ReadKicadNetList
* The main function to read a netlist (new netlist format, using S expressions),
* and update the board
* @param aFile = the already opened file (will be closed by ReadKicadNetList)
* @return true if success
*/
bool ReadKicadNetList( FILE* aFile );
/**
* function RemoveExtraFootprints
* Remove (delete) not locked footprints found on board, but not in netlist
* The netlist is expected to be read, and the main module list info up to date
*/
void RemoveExtraFootprints( );
/**
* Function SetPadNetName
* Update a pad netname
* @param aModule = module reference
* @param aPadname = pad name (pad num)
* @param aNetname = new net name of the pad
* @return a pointer to the pad or NULL if the pad is not found
*/
D_PAD* SetPadNetName( const wxString & aModule, const wxString & aPadname,
const wxString & aNetname );
private:
/**
* Function FindModule
* search for a module id the modules existing in the current BOARD.
* @param aId = the key to identify the module to find:
* The reference or the full time stamp, according to m_UseTimeStamp
* @return the module found, or NULL.
*/
MODULE* FindModule( const wxString& aId );
/**
* Function SetPadNetName
* Update a pad netname using the current footprint
* from the netlist (line format: ( \<pad number\> \<net name\> ) )
* @param aText = current line read from netlist
*/
bool SetPadNetName( char* aText );
/**
* Function ReadOldFmtNetlistModuleDescr
* Read the full description of a footprint, from the netlist
* and update the corresponding module.
* @param aBuildList bool to switch between 2 modes:
* aBuildList = true:
* add module info added to m_newModulesList
* aBuildList = false:
* The module is searched in the board modules list
* @param aText contains the first line of description
* This function uses m_useFichCmp as a flag to know the footprint name:
* If true: component file *.cmp is used
* If false: the netlist only is used
* This flag is reset to false if the .cmp file is not found
* @return a reference to the corresponding module on board (NULL if not found)
*/
MODULE* ReadOldFmtNetlistModuleDescr( char* aText, bool aBuildList );
/**
* Function loadNewModules
* Load from libraries new modules found in netlist and add them to the current Board.
* modules to load come from m_newModulesList
* @return false if a footprint is not found, true if all footprints are loaded
*/
bool loadNewModules();
/**
* function readModuleComponentLinkfile
* read the *.cmp file ( filename in m_cmplistFullName )
* and initialize the m_Footprint member of each item in m_modulesInNetlist,
* when it is found in file, and with a non empty footprint value
* giving the equivalence between footprint names and components
* to find the footprint name corresponding to aCmpIdent
* @return true and the file can be read
*/
bool readModuleComponentLinkfile();
};
#endif // NETLIST_READER_H

View File

@ -0,0 +1,315 @@
/**
* @file pcbnew/netlist_reader_firstformat.cpp
*/
/*
* This program source code file is part of KiCad, a free EDA CAD application.
*
* Copyright (C) 1992-2011 Jean-Pierre Charras.
* Copyright (C) 1992-2011 KiCad Developers, see change_log.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
*/
/*
* Netlist reader using the first format of pcbnew netlist.
* This netlist reader build the list of modules found in netlist
* (list in m_modulesInNetlist)
* and update pads netnames
*/
#include <fctsys.h>
#include <kicad_string.h>
#include <wxPcbStruct.h>
#include <richio.h>
#include <class_board.h>
#include <class_module.h>
#include <pcbnew.h>
#include <netlist_reader.h>
// constants used by ReadOldFmtNetlistModuleDescr():
#define BUILDLIST true
#define READMODULE false
/*
* Function ReadOldFmtdNetList
* Update footprints (load missing footprints and delete on request extra
* footprints)
* Update References, values, "TIME STAMP" and connectivity data
* return true if Ok
*
* the format of the netlist is something like:
* # EESchema Netlist Version 1.0 generee le 18/5/2005-12:30:22
* (
* ( 40C08647 $noname R20 4,7K {Lib=R}
* ( 1 VCC )
* ( 2 MODB_1 )
* )
* ( 40C0863F $noname R18 4,7_k {Lib=R}
* ( 1 VCC )
* ( 2 MODA_1 )
* )
* }
* #End
*/
bool NETLIST_READER::ReadOldFmtdNetList( FILE* aFile )
{
int state = 0;
bool is_comment = false;
/* First, read the netlist: Build the list of footprints found in netlist
*/
// netlineReader dtor will close aFile
FILE_LINE_READER netlineReader( aFile, m_netlistFullName );
while( netlineReader.ReadLine() )
{
char* line = StrPurge( netlineReader.Line() );
if( is_comment ) // Comments in progress
{
// Test for end of the current comment
if( ( line = strchr( line, '}' ) ) == NULL )
continue;
is_comment = false;
}
if( *line == '{' ) // Start Comment
{
is_comment = true;
if( ( line = strchr( line, '}' ) ) == NULL )
continue;
}
if( *line == '(' )
state++;
if( *line == ')' )
state--;
if( state == 2 )
{
ReadOldFmtNetlistModuleDescr( line, BUILDLIST );
continue;
}
if( state >= 3 ) // First pass: pad descriptions are not read here.
{
state--;
}
}
if( BuildModuleListOnly() )
return true; // at this point, the module list is read and built.
// Load new footprints
bool success = InitializeModules();
if( ! success )
wxMessageBox( _("Some footprints are not found in libraries") );
TestFootprintsMatchingAndExchange();
/* Second read , All footprints are on board.
* Update the schematic info (pad netnames)
*/
netlineReader.Rewind();
m_currModule = NULL;
state = 0;
is_comment = false;
while( netlineReader.ReadLine() )
{
char* line = StrPurge( netlineReader.Line() );
if( is_comment ) // we are reading a comment
{
// Test for end of the current comment
if( ( line = strchr( line, '}' ) ) == NULL )
continue;
is_comment = false;
}
if( *line == '{' ) // this is the beginning of a comment
{
is_comment = true;
if( ( line = strchr( line, '}' ) ) == NULL )
continue;
}
if( *line == '(' )
state++;
if( *line == ')' )
state--;
if( state == 2 )
{
m_currModule = ReadOldFmtNetlistModuleDescr( line, READMODULE );
continue;
}
if( state >= 3 )
{
if( m_currModule )
SetPadNetName( line );
state--;
}
}
return true;
}
/* Function ReadOldFmtNetlistModuleDescr
* Read the beginning of a footprint description, from the netlist
* and add a module info to m_modulesInNetlist
* Analyze lines like:
* ( /40C08647 $noname R20 4.7K {Lib=R}
* (1 VCC)
* (2 MODB_1)
* )
*/
MODULE* NETLIST_READER::ReadOldFmtNetlistModuleDescr( char* aText, bool aBuildList )
{
char* text;
wxString timeStampPath; // the full time stamp read from netlist
wxString footprintName; // the footprint name read from netlist
wxString cmpValue; // the component value read from netlist
wxString cmpReference; // the component schematic reference read from netlist
bool error = false;
char line[1024];
strcpy( line, aText );
cmpValue = wxT( "~" );
// Read descr line like /40C08647 $noname R20 4.7K {Lib=R}
// Read time stamp (first word)
if( ( text = strtok( line, " ()\t\n" ) ) == NULL )
error = true;
else
timeStampPath = FROM_UTF8( text );
// Read footprint name (second word)
if( ( text = strtok( NULL, " ()\t\n" ) ) == NULL )
error = true;
else
footprintName = FROM_UTF8( text );
// Read schematic reference (third word)
if( ( text = strtok( NULL, " ()\t\n" ) ) == NULL )
error = true;
else
cmpReference = FROM_UTF8( text );
// Read schematic value (forth word)
if( ( text = strtok( NULL, " ()\t\n" ) ) == NULL )
error = true;
else
cmpValue = FROM_UTF8( text );
if( error )
return NULL;
if( aBuildList )
{
MODULE_INFO* mod_info = new MODULE_INFO( footprintName, cmpReference,
cmpValue, timeStampPath );
AddModuleInfo( mod_info );
return NULL;
}
// search the module loaded on board
// reference and time stamps are already updated so we can used search by reference
MODULE* module = m_pcbframe->GetBoard()->FindModuleByReference( cmpReference );
if( module == NULL )
{
if( m_messageWindow )
{
wxString msg;
msg.Printf( _( "Component [%s] not found" ), GetChars( cmpReference ) );
m_messageWindow->AppendText( msg + wxT( "\n" ) );
}
}
return module;
}
/*
* Function SetPadNetName
* Update a pad netname using the current footprint
* Line format: ( <pad number> = <net name> )
* Param aText = current line read from netlist
*/
bool NETLIST_READER::SetPadNetName( char* aText )
{
char* p;
char line[256];
if( m_currModule == NULL )
return false;
strncpy( line, aText, sizeof(line) );
if( ( p = strtok( line, " ()\t\n" ) ) == NULL )
return false;
wxString pinName = FROM_UTF8( p );
if( ( p = strtok( NULL, " ()\t\n" ) ) == NULL )
return false;
wxString netName = FROM_UTF8( p );
bool found = false;
for( D_PAD* pad = m_currModule->m_Pads; pad; pad = pad->Next() )
{
wxString padName = pad->GetPadName();
if( padName == pinName )
{
found = true;
if( (char) netName[0] != '?' )
pad->SetNetname( netName );
else
pad->SetNetname( wxEmptyString );
}
}
if( !found )
{
if( m_messageWindow )
{
wxString msg;
msg.Printf( _( "Module [%s]: Pad [%s] not found" ),
GetChars( m_currModule->m_Reference->m_Text ),
GetChars( pinName ) );
m_messageWindow->AppendText( msg + wxT( "\n" ) );
}
}
return found;
}

View File

@ -0,0 +1,325 @@
/**
* @file pcbnew/netlist_reader_kicad.cpp
*/
/*
* This program source code file is part of KiCad, a free EDA CAD application.
*
* Copyright (C) 1992-2011 Jean-Pierre Charras.
* Copyright (C) 1992-2011 KiCad Developers, see change_log.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 <wx/wx.h>
#include <netlist_lexer.h> // netlist_lexer is common to Eeschema and Pcbnew
#include <netlist_reader.h>
using namespace NL_T;
/**
* Class PCB_PLOT_PARAMS_PARSER
* is the parser class for PCB_PLOT_PARAMS.
*/
class NETLIST_READER_KICAD_PARSER : public NETLIST_LEXER
{
private:
T token;
NETLIST_READER * netlist_reader;
public:
NETLIST_READER_KICAD_PARSER( FILE_LINE_READER* aReader, NETLIST_READER *aNetlistReader );
/**
* Function Parse
* parse the full netlist
*/
void Parse( BOARD * aBrd ) throw( IO_ERROR, PARSE_ERROR );
/**
* Function ParseComp
* parse the comp description like
* (comp (ref P1)
* (value DB25FEMELLE)
* (footprint DB25FC)
* (libsource (lib conn) (part DB25))
* (sheetpath (names /) (tstamps /))
* (tstamp 3256759C))
*/
MODULE_INFO* ParseComp() throw( IO_ERROR, PARSE_ERROR );
void ParseNet( BOARD * aBrd ) throw( IO_ERROR, PARSE_ERROR );
/**
* Function SkipCurrent
* Skip the current token level, i.e
* search for the RIGHT parenthesis which closes the current description
*/
void SkipCurrent() throw( IO_ERROR, PARSE_ERROR );
// Useful for debug only:
const char* getTokenName( T aTok )
{
return NETLIST_LEXER::TokenName( aTok );
}
};
bool NETLIST_READER::ReadKicadNetList( FILE* aFile )
{
bool success = true;
BOARD * brd = m_pcbframe->GetBoard();
// netlineReader dtor will close aFile
FILE_LINE_READER netlineReader( aFile, m_netlistFullName );
NETLIST_READER_KICAD_PARSER netlist_parser( &netlineReader, this );
netlist_parser.Parse( brd );
return success;
}
// NETLIST_READER_KICAD_PARSER
NETLIST_READER_KICAD_PARSER::NETLIST_READER_KICAD_PARSER( FILE_LINE_READER* aReader,
NETLIST_READER *aNetlistReader ) :
NETLIST_LEXER( aReader )
{
netlist_reader = aNetlistReader;
}
/**
* Function SkipCurrent
* Skip the current token level, i.e
* search for the RIGHT parenthesis which closes the current description
*/
void NETLIST_READER_KICAD_PARSER::SkipCurrent() throw( IO_ERROR, PARSE_ERROR )
{
int curr_level = 0;
while( ( token = NextTok() ) != T_EOF )
{
if( token == T_LEFT )
curr_level--;
if( token == T_RIGHT )
{
curr_level++;
if( curr_level > 0 )
return;
}
}
}
void NETLIST_READER_KICAD_PARSER::Parse( BOARD * aBrd )
throw( IO_ERROR, PARSE_ERROR )
{
wxString text;
while( ( token = NextTok() ) != T_EOF )
{
if( token == T_LEFT )
token = NextTok();
if( token == T_components )
{
// The section comp starts here.
while( ( token = NextTok() ) != T_RIGHT )
{
if( token == T_LEFT )
token = NextTok();
if( token == T_comp )
{
// A comp section if found. Read it
MODULE_INFO* mod_info = ParseComp();
netlist_reader->AddModuleInfo( mod_info );
}
}
if( netlist_reader->BuildModuleListOnly() )
return; // at this point, the module list is read and built.
// Load new footprints
netlist_reader->InitializeModules();
netlist_reader->TestFootprintsMatchingAndExchange();
}
if( token == T_nets )
{
// The section nets starts here.
while( ( token = NextTok() ) != T_RIGHT )
{
if( token == T_LEFT )
token = NextTok();
if( token == T_net )
{
// A net section if found. Read it
ParseNet( aBrd );
}
}
}
}
}
void NETLIST_READER_KICAD_PARSER::ParseNet( BOARD * aBrd )
throw( IO_ERROR, PARSE_ERROR )
{
/* Parses a section like
* (net (code 20) (name /PC-A0)
* (node (ref BUS1) (pin 62))
* (node (ref U3) (pin 3))
* (node (ref U9) (pin M6)))
*/
wxString code;
wxString name;
wxString cmpref;
wxString pin;
D_PAD * pad = NULL;
int nodecount = 0;
// The token net was read, so the next data is (code <number>)
while( (token = NextTok()) != T_RIGHT )
{
if( token == T_LEFT )
token = NextTok();
switch( token )
{
case T_code:
NeedSYMBOLorNUMBER();
code = FROM_UTF8( CurText() );
NeedRIGHT();
break;
case T_name:
NeedSYMBOLorNUMBER();
name = FROM_UTF8( CurText() );
NeedRIGHT();
if( name.IsEmpty() ) // Give a dummy net name like N-000109
name = wxT("N-00000") + code;
break;
case T_node:
while( (token = NextTok()) != T_RIGHT )
{
if( token == T_LEFT )
token = NextTok();
switch( token )
{
case T_ref:
NeedSYMBOLorNUMBER();
cmpref = FROM_UTF8( CurText() );
NeedRIGHT();
break;
case T_pin:
NeedSYMBOLorNUMBER();
pin = FROM_UTF8( CurText() );
NeedRIGHT();
break;
default:
SkipCurrent();
break;
}
}
pad = netlist_reader->SetPadNetName( cmpref, pin, name );
nodecount++;
break;
default:
SkipCurrent();
break;
}
}
// When there is onlu one item in net, clear pad netname
if( nodecount < 2 && pad )
pad->SetNetname( wxEmptyString );
}
MODULE_INFO* NETLIST_READER_KICAD_PARSER::ParseComp()
throw( IO_ERROR, PARSE_ERROR )
{
/* Parses a section like
* (comp (ref P1)
* (value DB25FEMELLE)
* (footprint DB25FC)
* (libsource (lib conn) (part DB25))
* (sheetpath (names /) (tstamps /))
* (tstamp 3256759C))
*
* other fields (unused) are skipped
* A component need a reference, value, foorprint name and a full time stamp
* The full time stamp is the sheetpath time stamp + the component time stamp
*/
wxString ref;
wxString value;
wxString footprint;
wxString pathtimestamp, timestamp;
// The token comp was read, so the next data is (ref P1)
while( (token = NextTok()) != T_RIGHT )
{
if( token == T_LEFT )
token = NextTok();
switch( token )
{
case T_ref:
NeedSYMBOLorNUMBER();
ref = FROM_UTF8( CurText() );
NeedRIGHT();
break;
case T_value:
NeedSYMBOLorNUMBER();
value = FROM_UTF8( CurText() );
NeedRIGHT();
break;
case T_footprint:
NeedSYMBOLorNUMBER();
footprint = FROM_UTF8( CurText() );
NeedRIGHT();
break;
case T_libsource:
// Currently not used data, skip it
SkipCurrent();
break;
case T_sheetpath:
while( ( token = NextTok() ) != T_tstamps );
NeedSYMBOLorNUMBER();
pathtimestamp = FROM_UTF8( CurText() );
NeedRIGHT();
NeedRIGHT();
break;
case T_tstamp:
NeedSYMBOLorNUMBER();
timestamp = FROM_UTF8( CurText() );
NeedRIGHT();
break;
default:
// Skip not used data (i.e all other tokens)
SkipCurrent();
break;
}
}
pathtimestamp += timestamp;
MODULE_INFO* mod_info = new MODULE_INFO( footprint, ref, value, pathtimestamp );
return mod_info;
}