Commit 7eb1a136 authored by jean-pierre charras's avatar jean-pierre charras

Pcbnew: First draft to use a new netlist format ( containing the same info as...

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.
parent 4cbb5c5e
...@@ -4,6 +4,16 @@ KiCad ChangeLog 2012 ...@@ -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>
================================================================================ ================================================================================
......
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.
# EESchema Netlist Version 1.1 created 21/02/2011 18:31:31 # EESchema Netlist Version 1.1 created 23/01/2012 08:38:24
( (
( /322D3011 BUS_PC BUS1 BUSPC ( /4A087146 $noname U3 74LS541 {Lib=74LS541}
( 1 GND ) ( 1 GND )
( 2 /PC-RST ) ( 2 /PC-A1 )
( 3 VCC ) ( 3 /PC-A0 )
( 4 ? ) ( 4 /PC-A2 )
( 5 ? ) ( 5 /PC-A3 )
( 6 ? ) ( 6 /PC-IOW )
( 7 ? ) ( 7 /PC-IOR )
( 8 ? ) ( 8 /PC-RST )
( 9 ? ) ( 9 /PC-RST )
( 10 ? ) ( 10 GND )
( 11 ? ) ( 11 ? )
( 12 ? ) ( 12 /RSTL )
( 13 /PC-IOW ) ( 13 /PC-RD )
( 14 /PC-IOR ) ( 14 /PC-WR )
( 15 ? ) ( 15 N-000111 )
( 16 ? ) ( 16 N-000110 )
( 17 ? ) ( 17 N-000109 )
( 18 ? ) ( 18 N-000108 )
( 19 ? ) ( 19 GND )
( 20 ? ) ( 20 VCC )
( 21 ? )
( 22 ? )
( 23 ? )
( 24 ? )
( 25 ? )
( 26 ? )
( 27 ? )
( 28 ? )
( 29 VCC )
( 30 ? )
( 31 GND )
( 32 ? )
( 33 /PC-DB7 )
( 34 /PC-DB6 )
( 35 /PC-DB5 )
( 36 /PC-DB4 )
( 37 /PC-DB3 )
( 38 /PC-DB2 )
( 39 /PC-DB1 )
( 40 /PC-DB0 )
( 41 ? )
( 42 /PC-AEN )
( 43 ? )
( 44 ? )
( 45 ? )
( 46 ? )
( 47 ? )
( 48 ? )
( 49 ? )
( 50 ? )
( 51 /PC-A11 )
( 52 /PC-A10 )
( 53 /PC-A9 )
( 54 /PC-A8 )
( 55 /PC-A7 )
( 56 /PC-A6 )
( 57 /PC-A5 )
( 58 /PC-A4 )
( 59 /PC-A3 )
( 60 /PC-A2 )
( 61 /PC-A1 )
( 62 /PC-A0 )
)
( /32307DE2 CP6 C1 47uF
( 1 VCC )
( 2 GND )
)
( /32307ECF C1 C2 47pF
( 1 N-000145 )
( 2 GND )
)
( /32307ED4 C1 C3 47pF
( 1 N-000146 )
( 2 GND )
)
( /32307DCF CP6 C4 47uF
( 1 VCC )
( 2 GND )
)
( /32307DCA CP6 C5 47uF
( 1 VCC )
( 2 GND )
)
( /32307DC0 CP6 C6 47uF
( 1 VCC )
( 2 GND )
)
( /322D32AC LEDV D1 LED
( 1 N-000105 )
( 2 GND )
)
( /322D32BE LEDV D2 LED
( 1 N-000104 )
( 2 GND )
) )
( /32568D1E pin_array_8x2 JP1 CONN_8X2 ( /32568D1E pin_array_8x2 JP1 CONN_8X2 {Lib=CONN_8X2}
( 1 GND ) ( 1 GND )
( 2 /REF10 ) ( 2 /REF10 )
( 3 GND ) ( 3 GND )
...@@ -114,7 +40,19 @@ ...@@ -114,7 +40,19 @@
( 15 GND ) ( 15 GND )
( 16 /REF5 ) ( 16 /REF5 )
) )
( /3256759C DB25FC P1 DB25FEMELLE ( /325679C1 r_pack9 RR1 9x1K {Lib=RR9}
( 1 VCC )
( 2 /REF5 )
( 3 /REF4 )
( 4 /REF8 )
( 5 /REF6 )
( 6 /REF9 )
( 7 /REF7 )
( 8 /REF11 )
( 9 /REF10 )
( 10 ? )
)
( /3256759C DB25FC P1 DB25FEMELLE {Lib=DB25}
( 1 /STROBE ) ( 1 /STROBE )
( 2 /BIT0 ) ( 2 /BIT0 )
( 3 /BIT1 ) ( 3 /BIT1 )
...@@ -141,105 +79,11 @@ ...@@ -141,105 +79,11 @@
( 24 GND ) ( 24 GND )
( 25 GND ) ( 25 GND )
) )
( /32307EA1 R3 R1 100K ( /324002E6 R3 R3 10K {Lib=R}
( 1 N-000146 ) ( 1 N-000072 )
( 2 N-000145 )
)
( /32307EAA R3 R2 1K
( 1 /8MH-OUT )
( 2 N-000146 )
)
( /324002E6 R3 R3 10K
( 1 N-000071 )
( 2 VCC ) ( 2 VCC )
) )
( /322D3295 R3 R4 330 ( /3240023F 32dip600 U5 628128 {Lib=628128}
( 1 N-000105 )
( 2 /LED1 )
)
( /322D32A0 R3 R5 330
( 1 N-000104 )
( 2 /LED2 )
)
( /325679C1 r_pack9 RR1 9x1K
( 1 VCC )
( 2 /REF5 )
( 3 /REF4 )
( 4 /REF8 )
( 5 /REF6 )
( 6 /REF9 )
( 7 /REF7 )
( 8 /REF11 )
( 9 /REF10 )
( 10 ? )
)
( /322D31F4 20dip300 U1 74LS245
( 1 /DIR )
( 2 /PC-DB0 )
( 3 /PC-DB1 )
( 4 /PC-DB2 )
( 5 /PC-DB3 )
( 6 /PC-DB4 )
( 7 /PC-DB5 )
( 8 /PC-DB6 )
( 9 /PC-DB7 )
( 10 GND )
( 11 /D7 )
( 12 /D6 )
( 13 /D5 )
( 14 /D4 )
( 15 /D3 )
( 16 /D2 )
( 17 /D1 )
( 18 /D0 )
( 19 /ENBBUF )
( 20 VCC )
)
( /322D35B4 20dip300 U2 74LS688
( 1 /PC-AEN )
( 2 /PC-A5 )
( 3 /REF5 )
( 4 /PC-A8 )
( 5 /REF8 )
( 6 /PC-A9 )
( 7 /REF9 )
( 8 /PC-A11 )
( 9 /REF11 )
( 10 GND )
( 11 /PC-A10 )
( 12 /REF10 )
( 13 /PC-A7 )
( 14 /REF7 )
( 15 /PC-A6 )
( 16 /REF6 )
( 17 /PC-A4 )
( 18 /REF4 )
( 19 /MATCHL )
( 20 VCC )
)
( /4A087146 $noname$ U3 74LS541
( 1 GND )
( 2 /PC-A1 )
( 3 /PC-A0 )
( 4 /PC-A2 )
( 5 /PC-A3 )
( 6 /PC-IOW )
( 7 /PC-IOR )
( 8 /PC-RST )
( 9 /PC-RST )
( 10 GND )
( 11 ? )
( 12 /RSTL )
( 13 /PC-RD )
( 14 /PC-WR )
( 15 N-000109 )
( 16 N-000108 )
( 17 N-000107 )
( 18 N-000106 )
( 19 GND )
( 20 VCC )
)
( /3240023F 32dip600 U5 628128
( 2 /MA16 ) ( 2 /MA16 )
( 3 /MA14 ) ( 3 /MA14 )
( 4 /MA12 ) ( 4 /MA12 )
...@@ -268,37 +112,69 @@ ...@@ -268,37 +112,69 @@
( 27 /MA8 ) ( 27 /MA8 )
( 28 /MA13 ) ( 28 /MA13 )
( 29 /WR- ) ( 29 /WR- )
( 30 N-000071 ) ( 30 N-000072 )
( 31 /MA15 ) ( 31 /MA15 )
( 32 VCC ) ( 32 VCC )
) )
( /322D321C 24dip300 U8 EP600 ( /32307ED4 C1 C3 47pF {Lib=C}
( 1 GND ) ( 1 N-000146 )
( 2 /MATCHL ) ( 2 GND )
( 3 N-000106 )
( 4 N-000107 )
( 5 N-000108 )
( 6 N-000109 )
( 7 /PC-WR )
( 8 ? )
( 9 ? )
( 10 ? )
( 11 /RSTL )
( 12 GND )
( 13 /WR_REG )
( 14 /PC-RD )
( 15 /WR_REG )
( 16 /CLKLCA )
( 17 /DIR )
( 18 /SEL_LPT )
( 19 /PROG- )
( 20 /DONE )
( 21 /D0 )
( 22 /ENBBUF )
( 23 VCC )
( 24 VCC )
) )
( /322D32FA PGA120 U9 4003APG120 ( /32307ECF C1 C2 47pF {Lib=C}
( 1 N-000145 )
( 2 GND )
)
( /32307EC0 HC-18UH X1 8MHz {Lib=CRYSTAL}
( 1 N-000145 )
( 2 N-000146 )
)
( /32307EAA R3 R2 1K {Lib=R}
( 1 /8MH-OUT )
( 2 N-000146 )
)
( /32307EA1 R3 R1 100K {Lib=R}
( 1 N-000146 )
( 2 N-000145 )
)
( /32307DE2 CP6 C1 47uF {Lib=CP}
( 1 VCC )
( 2 GND )
)
( /32307DCF CP6 C4 47uF {Lib=CP}
( 1 VCC )
( 2 GND )
)
( /32307DCA CP6 C5 47uF {Lib=CP}
( 1 VCC )
( 2 GND )
)
( /32307DC0 CP6 C6 47uF {Lib=CP}
( 1 VCC )
( 2 GND )
)
( /322D35B4 20dip300 U2 74LS688 {Lib=74LS688}
( 1 /PC-AEN )
( 2 /PC-A5 )
( 3 /REF5 )
( 4 /PC-A8 )
( 5 /REF8 )
( 6 /PC-A9 )
( 7 /REF9 )
( 8 /PC-A11 )
( 9 /REF11 )
( 10 GND )
( 11 /PC-A10 )
( 12 /REF10 )
( 13 /PC-A7 )
( 14 /REF7 )
( 15 /PC-A6 )
( 16 /REF6 )
( 17 /PC-A4 )
( 18 /REF4 )
( 19 /MATCHL )
( 20 VCC )
)
( /322D32FA PGA120 U9 4003APG120 {Lib=4003APG120}
( A1 ? ) ( A1 ? )
( A2 ? ) ( A2 ? )
( A3 ? ) ( A3 ? )
...@@ -417,27 +293,175 @@ ...@@ -417,27 +293,175 @@
( N12 ? ) ( N12 ? )
( N13 /SLCT+ ) ( N13 /SLCT+ )
) )
( /32307EC0 HC-18UH X1 8MHz ( /322D32BE LEDV D2 LED {Lib=LED}
( 1 N-000145 ) ( 1 N-000103 )
( 2 N-000146 ) ( 2 GND )
)
( /322D32AC LEDV D1 LED {Lib=LED}
( 1 N-000107 )
( 2 GND )
)
( /322D32A0 R3 R5 330 {Lib=R}
( 1 N-000103 )
( 2 /LED2 )
)
( /322D3295 R3 R4 330 {Lib=R}
( 1 N-000107 )
( 2 /LED1 )
)
( /322D321C 24dip300 U8 EP600 {Lib=EP600}
( 1 GND )
( 2 /MATCHL )
( 3 N-000108 )
( 4 N-000109 )
( 5 N-000110 )
( 6 N-000111 )
( 7 /PC-WR )
( 8 ? )
( 9 ? )
( 10 ? )
( 11 /RSTL )
( 12 GND )
( 13 /WR_REG )
( 14 /PC-RD )
( 15 /WR_REG )
( 16 /CLKLCA )
( 17 /DIR )
( 18 /SEL_LPT )
( 19 /PROG- )
( 20 /DONE )
( 21 /D0 )
( 22 /ENBBUF )
( 23 VCC )
( 24 VCC )
)
( /322D31F4 20dip300 U1 74LS245 {Lib=74LS245}
( 1 /DIR )
( 2 /PC-DB0 )
( 3 /PC-DB1 )
( 4 /PC-DB2 )
( 5 /PC-DB3 )
( 6 /PC-DB4 )
( 7 /PC-DB5 )
( 8 /PC-DB6 )
( 9 /PC-DB7 )
( 10 GND )
( 11 /D7 )
( 12 /D6 )
( 13 /D5 )
( 14 /D4 )
( 15 /D3 )
( 16 /D2 )
( 17 /D1 )
( 18 /D0 )
( 19 /ENBBUF )
( 20 VCC )
)
( /322D3011 BUS_PC BUS1 BUSPC {Lib=BUSPC}
( 1 GND )
( 2 /PC-RST )
( 3 VCC )
( 4 ? )
( 5 ? )
( 6 ? )
( 7 ? )
( 8 ? )
( 9 ? )
( 10 ? )
( 11 ? )
( 12 ? )
( 13 /PC-IOW )
( 14 /PC-IOR )
( 15 ? )
( 16 ? )
( 17 ? )
( 18 ? )
( 19 ? )
( 20 ? )
( 21 ? )
( 22 ? )
( 23 ? )
( 24 ? )
( 25 ? )
( 26 ? )
( 27 ? )
( 28 ? )
( 29 VCC )
( 30 ? )
( 31 GND )
( 32 ? )
( 33 /PC-DB7 )
( 34 /PC-DB6 )
( 35 /PC-DB5 )
( 36 /PC-DB4 )
( 37 /PC-DB3 )
( 38 /PC-DB2 )
( 39 /PC-DB1 )
( 40 /PC-DB0 )
( 41 ? )
( 42 /PC-AEN )
( 43 ? )
( 44 ? )
( 45 ? )
( 46 ? )
( 47 ? )
( 48 ? )
( 49 ? )
( 50 ? )
( 51 /PC-A11 )
( 52 /PC-A10 )
( 53 /PC-A9 )
( 54 /PC-A8 )
( 55 /PC-A7 )
( 56 /PC-A6 )
( 57 /PC-A5 )
( 58 /PC-A4 )
( 59 /PC-A3 )
( 60 /PC-A2 )
( 61 /PC-A1 )
( 62 /PC-A0 )
) )
) )
* *
{ Allowed footprints by component: { Allowed footprints by component:
$component C1 $component P1
CP* DB25*
SM*
$endlist $endlist
$component C2 $component R3
R?
SM0603
SM0805
R?-*
SM1206
$endlist
$component C3
SM* SM*
C? C?
C1-1 C1-1
$endlist $endlist
$component C3 $component C2
SM* SM*
C? C?
C1-1 C1-1
$endlist $endlist
$component R2
R?
SM0603
SM0805
R?-*
SM1206
$endlist
$component R1
R?
SM0603
SM0805
R?-*
SM1206
$endlist
$component C1
CP*
SM*
$endlist
$component C4 $component C4
CP* CP*
SM* SM*
...@@ -450,7 +474,7 @@ $component C6 ...@@ -450,7 +474,7 @@ $component C6
CP* CP*
SM* SM*
$endlist $endlist
$component D1 $component D2
LED-3MM LED-3MM
LED-5MM LED-5MM
LED-10MM LED-10MM
...@@ -459,7 +483,7 @@ $component D1 ...@@ -459,7 +483,7 @@ $component D1
LED-1206 LED-1206
LEDV LEDV
$endlist $endlist
$component D2 $component D1
LED-3MM LED-3MM
LED-5MM LED-5MM
LED-10MM LED-10MM
...@@ -468,24 +492,7 @@ $component D2 ...@@ -468,24 +492,7 @@ $component D2
LED-1206 LED-1206
LEDV LEDV
$endlist $endlist
$component P1 $component R5
DB25*
$endlist
$component R1
R?
SM0603
SM0805
R?-*
SM1206
$endlist
$component R2
R?
SM0603
SM0805
R?-*
SM1206
$endlist
$component R3
R? R?
SM0603 SM0603
SM0805 SM0805
...@@ -499,12 +506,428 @@ $component R4 ...@@ -499,12 +506,428 @@ $component R4
R?-* R?-*
SM1206 SM1206
$endlist $endlist
$component R5
R?
SM0603
SM0805
R?-*
SM1206
$endlist
$endfootprintlist $endfootprintlist
} }
{ Pin List by Nets
Net 15 "/PC-RST" "PC-RST"
BUS1 2
U3 8
U3 9
Net 16 "/PC-IOR" "PC-IOR"
BUS1 14
U3 7
Net 17 "/PC-IOW" "PC-IOW"
U3 6
BUS1 13
Net 19 "/PC-A1" "PC-A1"
BUS1 61
U9 N4
U3 2
Net 20 "/PC-A0" "PC-A0"
U9 M6
BUS1 62
U3 3
Net 21 "GND" "GND"
P1 18
U9 G11
U9 K11
U9 C10
U9 G2
BUS1 1
D2 2
U1 10
U9 C4
P1 20
D1 2
U9 K3
U8 1
U9 L7
U9 B7
JP1 13
JP1 11
P1 25
U5 16
P1 24
P1 23
JP1 15
U8 12
P1 22
P1 21
C1 2
C4 2
C5 2
C6 2
U2 10
C3 2
U3 10
U3 19
U3 1
JP1 7
JP1 5
JP1 3
JP1 1
C2 2
BUS1 31
P1 19
JP1 9
Net 22 "VCC" "VCC"
C1 1
C4 1
U8 24
C5 1
U8 23
C6 1
U2 20
U9 B12
U9 L3
U9 M7
U3 20
U9 D11
U1 20
U9 C11
U9 B11
R3 2
BUS1 3
BUS1 29
U9 G12
U5 32
U9 C3
U9 L10
RR1 1
Net 23 "/PC-AEN" "PC-AEN"
U9 N10
BUS1 42
U2 1
Net 52 "/MA8" "MA8"
U9 G1
U5 27
Net 53 "/MD4" "MD4"
U9 A7
U5 18
Net 54 "/MA13" "MA13"
U5 28
U9 C1
Net 55 "/MD5" "MD5"
U9 A8
U5 19
Net 56 "/WR-" "WR-"
U5 29
U9 A13
Net 57 "/MD3" "MD3"
U5 17
U9 A6
Net 61 "/RSTL" "RSTL"
U3 12
U8 11
Net 63 "/MA16" "MA16"
U9 C8
U5 2
Net 64 "/MA14" "MA14"
U5 3
U9 D1
Net 65 "/MA12" "MA12"
U9 F3
U5 4
Net 66 "/MA7" "MA7"
U5 5
U9 B3
Net 67 "/MA6" "MA6"
U9 F2
U5 6
Net 68 "/MA5" "MA5"
U9 C13
U5 7
Net 69 "/MA4" "MA4"
U9 E1
U5 8
Net 70 "/MA3" "MA3"
U5 9
U9 C2
Net 71 "/MD6" "MD6"
U9 A9
U5 20
Net 72 "" ""
R3 1
U5 30
Net 73 "/MD7" "MD7"
U5 21
U9 B8
Net 74 "/MA15" "MA15"
U5 31
U9 F1
Net 75 "/MA0" "MA0"
U5 12
U9 A11
Net 76 "/CS1-" "CS1-"
U9 A10
U5 22
Net 77 "/MD0" "MD0"
U9 C6
U5 13
Net 78 "/MA10" "MA10"
U5 23
U9 C9
Net 79 "/MD1" "MD1"
U5 14
U9 A5
Net 80 "/OE-" "OE-"
U5 24
U9 B9
Net 81 "/MD2" "MD2"
U5 15
U9 B6
Net 82 "/MA11" "MA11"
U5 25
U9 D2
Net 83 "/MA9" "MA9"
U5 26
U9 A4
Net 84 "/DIR" "DIR"
U8 17
U1 1
Net 85 "/ENBBUF" "ENBBUF"
U8 22
U1 19
Net 86 "/PC-RD" "PC-RD"
U8 14
U3 13
U9 M8
Net 87 "/SEL_LPT" "SEL_LPT"
U8 18
U9 L2
Net 88 "/PC-DB0" "PC-DB0"
U1 2
BUS1 40
Net 89 "/PC-DB1" "PC-DB1"
U1 3
BUS1 39
Net 90 "/PC-DB2" "PC-DB2"
U1 4
BUS1 38
Net 91 "/PC-DB3" "PC-DB3"
U1 5
BUS1 37
Net 92 "/PC-DB4" "PC-DB4"
BUS1 36
U1 6
Net 93 "/PC-DB5" "PC-DB5"
U1 7
BUS1 35
Net 94 "/PC-DB6" "PC-DB6"
U1 8
BUS1 34
Net 95 "/PC-DB7" "PC-DB7"
BUS1 33
U1 9
Net 96 "/D7" "D7"
U9 L12
U1 11
Net 97 "/D6" "D6"
U9 M11
U1 12
Net 98 "/D5" "D5"
U9 N11
U1 13
Net 99 "/D4" "D4"
U9 M10
U1 14
Net 100 "/D3" "D3"
U9 M9
U1 15
Net 101 "/D2" "D2"
U1 16
U9 N9
Net 102 "/D1" "D1"
U1 17
U9 N8
Net 103 "" ""
D2 1
R5 1
Net 105 "/LED2" "LED2"
R5 2
U9 F13
Net 106 "/D0" "D0"
U8 21
U9 N2
U1 18
Net 107 "" ""
D1 1
R4 1
Net 108 "" ""
U3 18
U8 3
Net 109 "" ""
U3 17
U8 4
Net 110 "" ""
U3 16
U8 5
Net 111 "" ""
U3 15
U8 6
Net 112 "/PC-WR" "PC-WR"
U8 7
U9 N6
U3 14
Net 113 "/PC-A6" "PC-A6"
U9 J1
BUS1 56
U2 15
Net 114 "/PC-A9" "PC-A9"
U9 N7
BUS1 53
U2 6
Net 115 "/PC-A8" "PC-A8"
U2 4
U9 H1
BUS1 54
Net 116 "/PC-A7" "PC-A7"
BUS1 55
U9 H2
U2 13
Net 117 "/PC-A5" "PC-A5"
BUS1 57
U2 2
U9 J2
Net 118 "/PC-A4" "PC-A4"
BUS1 58
U9 H3
U2 17
Net 119 "/PC-A3" "PC-A3"
U3 5
U9 K2
BUS1 59
Net 120 "/PC-A2" "PC-A2"
U3 4
U9 M5
BUS1 60
Net 121 "/PC-A11" "PC-A11"
U2 8
BUS1 51
Net 122 "/PC-A10" "PC-A10"
U9 L8
BUS1 52
U2 11
Net 123 "/LED1" "LED1"
U9 M3
R4 2
Net 125 "/MA2" "MA2"
U9 D3
U5 10
Net 128 "/CLKLCA" "CLKLCA"
U8 16
U9 L4
U9 M4
Net 131 "/MATCHL" "MATCHL"
U2 19
U8 2
Net 134 "/MA1" "MA1"
U5 11
U9 B2
Net 137 "/DONE" "DONE"
U8 20
U9 L11
Net 139 "/PROG-" "PROG-"
U8 19
U9 M12
Net 144 "/WR_REG" "WR_REG"
U8 13
U8 15
Net 145 "" ""
X1 1
C2 1
R1 2
U9 L1
Net 146 "" ""
X1 2
R1 1
C3 1
R2 2
Net 147 "/BIT6" "BIT6"
U9 J13
P1 8
Net 148 "/BIT7" "BIT7"
P1 9
U9 H11
Net 149 "/ACK" "ACK"
P1 10
U9 K13
Net 150 "/BUST+" "BUST+"
U9 J12
P1 11
Net 151 "/PE+" "PE+"
P1 12
U9 L13
Net 152 "/SLCT+" "SLCT+"
P1 13
U9 N13
Net 153 "/BIT5" "BIT5"
U9 H12
P1 7
Net 154 "/8MH-OUT" "8MH-OUT"
R2 1
U9 K1
Net 156 "/STROBE" "STROBE"
P1 1
U9 A12
Net 157 "/AUTOFD-" "AUTOFD-"
P1 14
U9 C12
Net 158 "/ERROR-" "ERROR-"
P1 15
U9 D13
Net 159 "/BIT2" "BIT2"
U9 F12
P1 4
Net 160 "/INIT-" "INIT-"
P1 16
U9 E12
Net 161 "/SLCTIN-" "SLCTIN-"
P1 17
U9 F11
Net 162 "/BIT0" "BIT0"
U9 D12
P1 2
Net 163 "/BIT1" "BIT1"
P1 3
U9 E13
Net 164 "/BIT3" "BIT3"
U9 G13
P1 5
Net 165 "/BIT4" "BIT4"
P1 6
U9 H13
Net 166 "/REF10" "REF10"
U2 12
JP1 2
RR1 9
Net 167 "/REF11" "REF11"
JP1 4
RR1 8
U2 9
Net 168 "/REF7" "REF7"
JP1 6
RR1 7
U2 14
Net 169 "/REF9" "REF9"
JP1 8
U2 7
RR1 6
Net 170 "/REF6" "REF6"
U2 16
RR1 5
JP1 10
Net 171 "/REF8" "REF8"
RR1 4
U2 5
JP1 12
Net 172 "/REF4" "REF4"
RR1 3
U2 18
JP1 14
Net 173 "/REF5" "REF5"
JP1 16
RR1 2
U2 3
}
#End
...@@ -24,7 +24,7 @@ ...@@ -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 @@ ...@@ -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 @@ ...@@ -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 ) ...@@ -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 ...@@ -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 ...@@ -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: ...@@ -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: ...@@ -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, ...@@ -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 ...@@ -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 ...@@ -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 ...@@ -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 ) ...@@ -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, ...@@ -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* ...@@ -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 ...@@ -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() ...@@ -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() ...@@ -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() ...@@ -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() ...@@ -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() ...@@ -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() ...@@ -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() ...@@ -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 ) ...@@ -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 ) ...@@ -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 ...@@ -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 ...@@ -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 ...@@ -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 ) ...@@ -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, ...@@ -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( ) ...@@ -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, ...@@ -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 ...@@ -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 ) ...@@ -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 ) ...@@ -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
ret |= fprintf( f, "\n%sEND\n", TO_UTF8( StartLine ) );
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 ...@@ -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 ...@@ -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 ...@@ -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;
} }
...@@ -126,6 +126,7 @@ NETLIST_PAGE_DIALOG::NETLIST_PAGE_DIALOG( wxNotebook* parent, ...@@ -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, ...@@ -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() ...@@ -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() ...@@ -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 ) ...@@ -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 ) ...@@ -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 ) ...@@ -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 ) ...@@ -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 ) ...@@ -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?" ) ) ) ...@@ -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 ) ...@@ -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 );
......
...@@ -7,8 +7,6 @@ ...@@ -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: ...@@ -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: ...@@ -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 { ...@@ -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: ...@@ -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:
......
...@@ -445,37 +445,43 @@ public: ...@@ -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
......
...@@ -1336,12 +1336,11 @@ public: ...@@ -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:
......
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.
...@@ -151,6 +151,8 @@ set(PCBNEW_SRCS ...@@ -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
......
...@@ -686,8 +686,12 @@ TRACK* MergeColinearSegmentIfPossible( BOARD* aPcb, TRACK* aTrackRef, TRACK* aCa ...@@ -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 ) ...@@ -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 ) ...@@ -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 pcbnew/netlist.cpp * @file pcbnew/netlist.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
*/
/* /*
* Functions to read a netlist. They are: * Functions to read a netlist:
* - Load new footprints and initialize net info * - Load new footprints and initialize net info
* - Test for missing or extra footprints * - Test for missing or extra footprints
* - Recalculate full connectivity info * - Recalculate full connectivity info
* *
* Important remark: * Important remark:
* When reading a netlist Pcbnew must identify existing footprints (link * When reading a netlist, Pcbnew must identify existing footprints (link
* between existing footprints an components in netlist) * between existing footprints an components in netlist)
* This identification can be from 2 fields: * This identification can be made from 2 fields:
* - The reference (U2, R5 ..): this is the normal mode * - The reference (U2, R5 ..): this is the normal mode
* - The Time Stamp (Signature Temporarily), useful after a full schematic * - The Time Stamp : useful after a full schematic
* reannotation because references can be changed for the same schematic. * reannotation because references can be changed for the component linked to its footprint.
* So when reading a netlist ReadPcbNetlist() can use references or time stamps * So when reading a netlist, ReadPcbNetlist() can use references or time stamps
* to identify footprints on board and the corresponding component in schematic. * to identify footprints on board and the corresponding component in schematic.
* If we want to fully reannotate a schematic this sequence must be used * If we want to fully reannotate a schematic this sequence must be used
* 1 - SAVE your board !!! * 1 - SAVE your board !!!
...@@ -26,6 +49,7 @@ ...@@ -26,6 +49,7 @@
* (that reinit the new references) * (that reinit the new references)
*/ */
#include <algorithm> #include <algorithm>
#include <fctsys.h> #include <fctsys.h>
...@@ -40,157 +64,10 @@ ...@@ -40,157 +64,10 @@
#include <class_board.h> #include <class_board.h>
#include <class_module.h> #include <class_module.h>
#include <pcbnew.h> #include <pcbnew.h>
#include <dialog_netlist.h> #include <dialog_netlist.h>
#include <netlist_reader.h>
// constants used by ReadNetlistModuleDescr():
#define TESTONLY true
#define READMODULE false
/*
* 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_LibName;
wxString m_CmpName;
wxString m_TimeStampPath;
public: MODULE_INFO( const wxString& libname,
const wxString& cmpname,
const wxString& timestamp_path )
{
m_LibName = libname;
m_CmpName = cmpname;
m_TimeStampPath = timestamp_path;
}
~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_newModulesList; // The list of new footprints,
// found in netlist, but not on board
// (must be loaded from libraries)
bool m_useCmpFile; // true to use .cmp files as component/footprint file link
// false to use netlist only to know component/footprint link
public:
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;
}
~NETLIST_READER()
{
// Free new modules list:
for( unsigned ii = 0; ii < m_newModulesList.size(); ii++ )
delete m_newModulesList[ii];
m_newModulesList.clear();
}
/**
* Function ReadNetList
* The main function to read a netlist, and update the board
* @param aFile = the already opened file (will be closed by ReadNetList)
* @param aNetlistFileName = the netlist full file name (*.net file)
* @param aCmplistFileName = the auxiliary component full file name (*.cmp file)
* If the aCmplistFileName file is not given or not found,
* the netlist is used to know the component/footprint link.
*/
bool ReadNetList( FILE* aFile, const wxString& aNetlistFileName,
const wxString& aCmplistFileName );
/**
* Function BuildComponentsListFromNetlist
* Fill aBufName with component references read from the netlist.
* @param aNetlistFilename = netlist full file name
* @param aBufName = wxArrayString to fill with component references
* @return the component count, or -1 if netlist file cannot opened
*/
int BuildComponentsListFromNetlist( const wxString& aNetlistFilename,
wxArrayString& aBufName );
/**
* function RemoveExtraFootprints
* Remove (delete) not locked footprints found on board, but not in netlist
* @param aNetlistFileName = the netlist full file name (*.net file)
*/
void RemoveExtraFootprints( const wxString& aNetlistFileName );
private:
/**
* 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 ReadNetlistModuleDescr
* Read the full description of a footprint, from the netlist
* and update the corresponding module.
* @param aTstOnly bool to switch between 2 modes:
* aTstOnly = false:
* if the module does not exist, it is added to m_newModulesList
* aTstOnly = true:
* if the module does not exist, it is loaded and added to the board module 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
*/
MODULE* ReadNetlistModuleDescr( char* aText, bool aTstOnly );
/**
* Function loadNewModules
* Load from libraries new modules found in netlist and add them to the current Board.
* @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 )
* giving the equivalence between footprint names and components
* to find the footprint name corresponding to aCmpIdent
* @return true and the module name in aFootprintName, false if not found
*
* @param aCmpIdent = component identification: schematic reference or time stamp
* @param aFootprintName the footprint name corresponding to the component identification
*/
bool readModuleComponentLinkfile( const wxString* aCmpIdent, wxString& aFootprintName );
};
/** /**
...@@ -200,7 +77,7 @@ private: ...@@ -200,7 +77,7 @@ private:
static FILE* OpenNetlistFile( const wxString& aFullFileName ) static FILE* OpenNetlistFile( const wxString& aFullFileName )
{ {
if( aFullFileName.IsEmpty() ) if( aFullFileName.IsEmpty() )
return false; // No filename: exit return NULL; // No filename: exit
FILE* file = wxFopen( aFullFileName, wxT( "rt" ) ); FILE* file = wxFopen( aFullFileName, wxT( "rt" ) );
...@@ -215,16 +92,6 @@ static FILE* OpenNetlistFile( const wxString& aFullFileName ) ...@@ -215,16 +92,6 @@ static FILE* OpenNetlistFile( const wxString& aFullFileName )
} }
/* Function to sort the footprint list.
* the given list is sorted by name
*/
static bool SortByLibName( MODULE_INFO* ref, MODULE_INFO* cmp )
{
int ii = ref->m_LibName.CmpNoCase( cmp->m_LibName );
return ii > 0;
}
/** /**
* Function ReadPcbNetlist * Function ReadPcbNetlist
...@@ -261,18 +128,27 @@ bool PCB_EDIT_FRAME::ReadPcbNetlist( const wxString& aNetlistFullFilename, ...@@ -261,18 +128,27 @@ bool PCB_EDIT_FRAME::ReadPcbNetlist( const wxString& aNetlistFullFilename,
SetLastNetListRead( aNetlistFullFilename ); SetLastNetListRead( aNetlistFullFilename );
bool useCmpfile = ! aCmpFullFileName.IsEmpty() && wxFileExists( aCmpFullFileName );
if( aMessageWindow ) if( aMessageWindow )
{ {
wxString msg; wxString msg;
msg.Printf( _( "Reading Netlist \"%s\"" ), GetChars( aNetlistFullFilename ) ); msg.Printf( _( "Reading Netlist \"%s\"" ), GetChars( aNetlistFullFilename ) );
aMessageWindow->AppendText( msg + wxT( "\n" ) ); aMessageWindow->AppendText( msg + wxT( "\n" ) );
if( ! aCmpFullFileName.IsEmpty() ) if( useCmpfile )
{ {
msg.Printf( _( "Using component/footprint link file \"%s\"" ), msg.Printf( _( "Using component/footprint link file \"%s\"" ),
GetChars( aCmpFullFileName ) ); GetChars( aCmpFullFileName ) );
aMessageWindow->AppendText( msg + wxT( "\n" ) ); aMessageWindow->AppendText( msg + wxT( "\n" ) );
} }
if( aSelect_By_Timestamp )
{
msg.Printf( _( "Using time stamp selection" ),
GetChars( aCmpFullFileName ) );
aMessageWindow->AppendText( msg + wxT( "\n" ) );
}
} }
// Clear undo and redo lists to avoid inconsistencies between lists // Clear undo and redo lists to avoid inconsistencies between lists
...@@ -289,12 +165,17 @@ bool PCB_EDIT_FRAME::ReadPcbNetlist( const wxString& aNetlistFullFilename, ...@@ -289,12 +165,17 @@ bool PCB_EDIT_FRAME::ReadPcbNetlist( const wxString& aNetlistFullFilename,
NETLIST_READER netList_Reader( this, aMessageWindow ); NETLIST_READER netList_Reader( this, aMessageWindow );
netList_Reader.m_UseTimeStamp = aSelect_By_Timestamp; netList_Reader.m_UseTimeStamp = aSelect_By_Timestamp;
netList_Reader.m_ChangeFootprints = aChangeFootprint; netList_Reader.m_ChangeFootprints = aChangeFootprint;
netList_Reader.ReadNetList( netfile, aNetlistFullFilename, aCmpFullFileName ); netList_Reader.m_UseCmpFile = useCmpfile;
netList_Reader.SetFilesnames( aNetlistFullFilename, aCmpFullFileName );
netList_Reader.ReadNetList( netfile );
// Delete footprints not found in netlist: // Delete footprints not found in netlist:
if( aDeleteExtraFootprints ) if( aDeleteExtraFootprints )
{ {
netList_Reader.RemoveExtraFootprints( aNetlistFullFilename ); if( IsOK( NULL,
_( "Ok to delete not locked footprints not found in netlist?" ) ) )
netList_Reader.RemoveExtraFootprints();
} }
// Rebuild the board connectivity: // Rebuild the board connectivity:
...@@ -303,7 +184,7 @@ bool PCB_EDIT_FRAME::ReadPcbNetlist( const wxString& aNetlistFullFilename, ...@@ -303,7 +184,7 @@ bool PCB_EDIT_FRAME::ReadPcbNetlist( const wxString& aNetlistFullFilename,
if( aDeleteBadTracks && GetBoard()->m_Track ) if( aDeleteBadTracks && GetBoard()->m_Track )
{ {
// Remove erroneous tracks // Remove erroneous tracks
RemoveMisConnectedTracks( NULL ); if( RemoveMisConnectedTracks() )
Compile_Ratsnest( NULL, true ); Compile_Ratsnest( NULL, true );
} }
...@@ -313,317 +194,121 @@ bool PCB_EDIT_FRAME::ReadPcbNetlist( const wxString& aNetlistFullFilename, ...@@ -313,317 +194,121 @@ bool PCB_EDIT_FRAME::ReadPcbNetlist( const wxString& aNetlistFullFilename,
return true; return true;
} }
/*
/* function RemoveExtraFootprints * Function ReadNetList
* Remove (delete) not locked footprints found on board, but not in netlist * The main function to detect the netlist format,and run the right netlist reader
* aFile = the already opened file (will be closed by the netlist reader)
*/ */
void NETLIST_READER::RemoveExtraFootprints( const wxString& aNetlistFileName ) bool NETLIST_READER::ReadNetList( FILE* aFile )
{ {
wxArrayString componentsInNetlist; // Try to determine the netlist type:
bool new_fmt = true;
// Build list of modules in the netlist std::string header( "(export" );
int modulesCount = BuildComponentsListFromNetlist( aNetlistFileName, componentsInNetlist ); for( unsigned ii = 0; ii < header.size(); ii++ )
if( modulesCount == 0 )
return;
MODULE* nextModule;
MODULE* module = m_pcbframe->GetBoard()->m_Modules;
bool ask_user = true;
for( ; module != NULL; module = nextModule )
{ {
int ii; int data;
nextModule = module->Next(); do
{
data = fgetc( aFile );
} while ( ( data == ' ' ) &&( EOF != data ) ) ;
if( module->m_ModuleStatus & MODULE_is_LOCKED ) if( (int)header[ii] == data )
continue; continue;
new_fmt = false;
for( ii = 0; ii < modulesCount; ii++ ) break;
{
if( module->m_Reference->m_Text.CmpNoCase( componentsInNetlist[ii] ) == 0 )
break; // Module is found in net list.
} }
if( ii == modulesCount ) // Module not found in netlist. rewind( aFile );
{
if( ask_user )
{
ask_user = false;
if( !IsOK( NULL, bool success;
_( "Ok to delete not locked footprints not found in netlist?" ) ) ) if( new_fmt )
break; success = ReadKicadNetList( aFile );
} else
success = ReadOldFmtdNetList( aFile );
module->DeleteStructure(); return success;
}
}
} }
/* bool NETLIST_READER::InitializeModules()
* Function ReadNetlist
* 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::ReadNetList( FILE* aFile,
const wxString& aNetlistFileName,
const wxString& aCmplistFileName )
{ {
int state = 0; if( m_UseCmpFile ) // Try to get footprint name from .cmp file
bool is_comment = false;
m_netlistFullName = aNetlistFileName;
m_cmplistFullName = aCmplistFileName;
m_useCmpFile = true;
/* First, read the netlist: Build the list of footprints to load (new
* footprints)
*/
// netlineReader dtor will close aFile
FILE_LINE_READER netlineReader( aFile, m_netlistFullName );
while( netlineReader.ReadLine() )
{ {
char* line = StrPurge( netlineReader.Line() ); readModuleComponentLinkfile();
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 == '(' ) for( unsigned ii = 0; ii < m_modulesInNetlist.size(); ii++ )
state++;
if( *line == ')' )
state--;
if( state == 2 )
{ {
ReadNetlistModuleDescr( line, TESTONLY ); MODULE_INFO* currmod_info = m_modulesInNetlist[ii];
continue; // Test if module is already loaded.
} wxString * idMod = m_UseTimeStamp?
&currmod_info->m_TimeStamp : &currmod_info->m_Reference;
if( state >= 3 ) // First pass: pad descriptions are not read here. MODULE* module = FindModule( *idMod );
if( module == NULL ) // not existing, load it
{ {
state--; m_newModulesList.push_back( currmod_info );
} }
} }
// Load new footprints
bool success = loadNewModules(); bool success = loadNewModules();
if( ! success ) // Update modules fields
wxMessageBox( _("Some footprints are not found in libraries") ); for( unsigned ii = 0; ii < m_modulesInNetlist.size(); ii++ )
/* Second read , All footprints are on board.
* One must update the schematic info (pad netnames)
*/
netlineReader.Rewind();
m_currModule = NULL;
state = 0;
is_comment = false;
while( netlineReader.ReadLine() )
{ {
char* line = StrPurge( netlineReader.Line() ); MODULE_INFO* currmod_info = m_modulesInNetlist[ii];
// Test if module is already loaded.
if( is_comment ) // we are reading a comment wxString * idMod = m_UseTimeStamp?
{ &currmod_info->m_TimeStamp : &currmod_info->m_Reference;
// 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 = ReadNetlistModuleDescr( line, READMODULE );
if( m_currModule == NULL ) // the module could not be created (perhaps MODULE* module = FindModule( *idMod );
if( module )
{ {
// footprint not found in library) // Update current module ( reference, value and "Time Stamp")
continue; module->m_Reference->m_Text = currmod_info->m_Reference;
module->m_Value->m_Text = currmod_info->m_Value;
module->SetPath( currmod_info->m_TimeStamp );
} }
else // clear pads netnames else // not existing
{
for( D_PAD* pad = m_currModule->m_Pads; pad; pad = pad->Next() )
{ {
pad->SetNetname( wxEmptyString );
} }
} }
continue; // clear pads netnames
} for( MODULE* module = m_pcbframe->GetBoard()->m_Modules; module; module = module->Next() )
if( state >= 3 )
{ {
if( m_currModule ) for( D_PAD* pad = module->m_Pads; pad; pad = pad->Next() )
SetPadNetName( line ); pad->SetNetname( wxEmptyString );
state--;
}
} }
return true; return success;
} }
void NETLIST_READER::TestFootprintsMatchingAndExchange()
/* Function ReadNetlistModuleDescr
* Read the full description of a footprint, from the netlist
* and update the corresponding module.
* param aTstOnly bool to switch between 2 modes:
* If aTstOnly == false:
* if the module does not exist, it is added to m_newModulesList
* If aTstOnly = true:
* if the module does not exist, it is loaded and added to the board module 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
* Analyze lines like:
* ( /40C08647 $noname R20 4.7K {Lib=R}
* (1 VCC)
* (2 MODB_1)
* )
*/
MODULE* NETLIST_READER::ReadNetlistModuleDescr( char* aText, bool aTstOnly )
{ {
char* text; for( MODULE* module = m_pcbframe->GetBoard()->m_Modules; module; module = module->Next() )
wxString timeStampPath; // the full time stamp read from netlist
wxString textFootprintName; // the footprint name read from netlist
wxString textValue; // the component value read from netlist
wxString textCmpReference; // the component schematic reference read from netlist
wxString cmpFootprintName; // the footprint name read from the *.cmp file
// giving the equivalence between footprint names and components
bool error = false;
char line[1024];
strcpy( line, aText );
textValue = 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
textFootprintName = FROM_UTF8( text );
// Read schematic reference (third word)
if( ( text = strtok( NULL, " ()\t\n" ) ) == NULL )
error = true;
else
textCmpReference = FROM_UTF8( text );
// Read schematic value (forth word)
if( ( text = strtok( NULL, " ()\t\n" ) ) == NULL )
error = true;
else
textValue = FROM_UTF8( text );
if( error )
return NULL;
// Test if module is already loaded.
wxString * identMod = &textCmpReference;
if( m_UseTimeStamp )
identMod = &timeStampPath;
MODULE* module = m_pcbframe->GetBoard()->m_Modules;
MODULE* nextModule;
bool found = false;
for( ; module != NULL; module = nextModule )
{ {
nextModule = module->Next(); // Search for the corresponding module info
MODULE_INFO * mod_info = NULL;
if( m_UseTimeStamp ) // identification by time stamp for( unsigned ii = 0; ii < m_modulesInNetlist.size(); ii++ )
{ {
if( timeStampPath.CmpNoCase( module->m_Path ) == 0 ) MODULE_INFO * candidate = m_modulesInNetlist[ii];
found = true; // Test if mod_info matches the current module:
} if( candidate->m_Reference.CmpNoCase( module->GetReference() ) == 0 )
else // identification by Reference
{ {
if( textCmpReference.CmpNoCase( module->m_Reference->m_Text ) == 0 ) mod_info = candidate;
found = true; break;
} }
if( found ) // The footprint corresponding to the component is already on board
{
// This footprint is already on board
// but if m_LibRef (existing footprint name) and the footprint name from netlist
// do not match, change this footprint on demand.
if( ! aTstOnly )
{
cmpFootprintName = textFootprintName; // Use footprint name from netlist
if( m_useCmpFile ) // Try to get footprint name from .cmp file
{
m_useCmpFile = readModuleComponentLinkfile( identMod, cmpFootprintName );
} }
if( mod_info == NULL ) // not found in netlist
continue;
/* Module mismatch: current footprint and footprint specified in if( module->GetLibRef().CmpNoCase( mod_info->m_Footprint ) != 0 )
* net list are different.
*/
if( module->m_LibRef.CmpNoCase( cmpFootprintName ) != 0 )
{ {
if( m_ChangeFootprints ) // footprint exchange allowed. if( m_ChangeFootprints ) // footprint exchange allowed.
{ {
MODULE* newModule = m_pcbframe->GetModuleLibrary( wxEmptyString, MODULE* newModule = m_pcbframe->GetModuleLibrary( wxEmptyString,
cmpFootprintName, mod_info->m_Footprint,
true ); false );
if( newModule ) if( newModule )
{ {
...@@ -631,116 +316,115 @@ MODULE* NETLIST_READER::ReadNetlistModuleDescr( char* aText, bool aTstOnly ) ...@@ -631,116 +316,115 @@ MODULE* NETLIST_READER::ReadNetlistModuleDescr( char* aText, bool aTstOnly )
m_pcbframe->Exchange_Module( module, newModule, NULL ); m_pcbframe->Exchange_Module( module, newModule, NULL );
module = newModule; module = newModule;
} }
} else if( m_messageWindow )
else
{ {
wxString msg; wxString msg;
msg.Printf( _( "Component \"%s\": Mismatch! module is [%s] and netlist said [%s]\n" ), msg.Printf( _( "Component \"%s\": module [%s] not found\n" ),
GetChars( textCmpReference ), GetChars( mod_info->m_Reference ),
GetChars( module->m_LibRef ), GetChars( mod_info->m_Footprint ) );
GetChars( cmpFootprintName ) );
if( m_messageWindow )
m_messageWindow->AppendText( msg ); m_messageWindow->AppendText( msg );
} }
} }
} else if( m_messageWindow )
{
wxString msg;
msg.Printf( _( "Component \"%s\": Mismatch! module is [%s] and netlist said [%s]\n" ),
GetChars( mod_info->m_Reference ),
GetChars( module->GetLibRef() ),
GetChars( mod_info->m_Footprint ) );
break; m_messageWindow->AppendText( msg );
} }
} }
if( module == NULL ) // a new module must be loaded from libs
{
cmpFootprintName = textFootprintName; // Use footprint name from netlist
if( m_useCmpFile ) // Try to get footprint name from .cmp file
{
m_useCmpFile = readModuleComponentLinkfile( identMod, cmpFootprintName );
} }
}
if( aTstOnly ) /**
* 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* NETLIST_READER::SetPadNetName( const wxString & aModule, const wxString & aPadname,
const wxString & aNetname )
{
MODULE* module = m_pcbframe->GetBoard()->FindModuleByReference( aModule );
if( module )
{ {
MODULE_INFO* newMod; D_PAD * pad = module->FindPadByName( aPadname );
newMod = new MODULE_INFO( cmpFootprintName, textCmpReference, timeStampPath ); if( pad )
m_newModulesList.push_back( newMod );
}
else
{ {
pad->SetNetname( aNetname );
return pad;
}
if( m_messageWindow ) if( m_messageWindow )
{ {
wxString msg; wxString msg;
msg.Printf( _( "Component [%s] not found" ), GetChars( textCmpReference ) ); msg.Printf( _( "Module [%s]: Pad [%s] not found" ),
GetChars( aModule ), GetChars( aPadname ) );
m_messageWindow->AppendText( msg + wxT( "\n" ) ); m_messageWindow->AppendText( msg + wxT( "\n" ) );
} }
} }
return NULL; // The module could not be loaded. return NULL;
}
// Update current module ( reference, value and "Time Stamp")
module->m_Reference->m_Text = textCmpReference;
module->m_Value->m_Text = textValue;
module->m_Path = timeStampPath;
return module;
} }
/* /* function RemoveExtraFootprints
* Function SetPadNetName * Remove (delete) not locked footprints found on board, but not in netlist
* 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 ) void NETLIST_READER::RemoveExtraFootprints()
{ {
char* p; MODULE* nextModule;
char line[256];
if( m_currModule == NULL )
return false;
strncpy( line, aText, sizeof(line) ); MODULE* module = m_pcbframe->GetBoard()->m_Modules;
for( ; module != NULL; module = nextModule )
{
unsigned ii;
nextModule = module->Next();
if( ( p = strtok( line, " ()\t\n" ) ) == NULL ) if( module->m_ModuleStatus & MODULE_is_LOCKED )
return false; continue;
wxString pinName = FROM_UTF8( p ); for( ii = 0; ii < m_modulesInNetlist.size(); ii++ )
{
MODULE_INFO* mod_info = m_modulesInNetlist[ii];
if( module->m_Reference->m_Text.CmpNoCase( mod_info->m_Reference ) == 0 )
break; // Module is found in net list.
}
if( ( p = strtok( NULL, " ()\t\n" ) ) == NULL ) if( ii == m_modulesInNetlist.size() ) // Module not found in netlist.
return false; module->DeleteStructure();
}
}
wxString netName = FROM_UTF8( p );
bool found = false; /* Search for a module id the modules existing in the current BOARD.
for( D_PAD* pad = m_currModule->m_Pads; pad; pad = pad->Next() ) * aId is a key to identify the module to find:
* The reference or the full time stamp, according to m_UseTimeStamp
* Returns the module is found, NULL otherwise.
*/
MODULE* NETLIST_READER::FindModule( const wxString& aId )
{
MODULE* module = m_pcbframe->GetBoard()->m_Modules;
for( ; module != NULL; module = module->Next() )
{ {
wxString padName = pad->GetPadName(); if( m_UseTimeStamp ) // identification by time stamp
if( padName == pinName )
{ {
found = true; if( aId.CmpNoCase( module->m_Path ) == 0 )
if( (char) netName[0] != '?' ) return module;
pad->SetNetname( netName );
else
pad->SetNetname( wxEmptyString );
}
} }
else // identification by Reference
if( !found )
{
if( m_messageWindow )
{ {
wxString msg; if( aId.CmpNoCase( module->m_Reference->m_Text ) == 0 )
msg.Printf( _( "Module [%s]: Pad [%s] not found" ), return module;
GetChars( m_currModule->m_Reference->m_Text ),
GetChars( pinName ) );
m_messageWindow->AppendText( msg + wxT( "\n" ) );
} }
} }
return found; return NULL;
} }
...@@ -796,11 +480,8 @@ MODULE* PCB_EDIT_FRAME::ListAndSelectModuleName( void ) ...@@ -796,11 +480,8 @@ MODULE* PCB_EDIT_FRAME::ListAndSelectModuleName( void )
void PCB_EDIT_FRAME::Test_Duplicate_Missing_And_Extra_Footprints( void PCB_EDIT_FRAME::Test_Duplicate_Missing_And_Extra_Footprints(
const wxString& aNetlistFullFilename ) const wxString& aNetlistFullFilename )
{ {
#define MAX_LEN_TXT 32 int nberr = 0;
int ii; wxArrayString list; // The list of messages to display
int NbModulesNetListe, nberr = 0;
wxArrayString tmp;
wxArrayString list;
if( GetBoard()->m_Modules == NULL ) if( GetBoard()->m_Modules == NULL )
{ {
...@@ -808,14 +489,21 @@ void PCB_EDIT_FRAME::Test_Duplicate_Missing_And_Extra_Footprints( ...@@ -808,14 +489,21 @@ void PCB_EDIT_FRAME::Test_Duplicate_Missing_And_Extra_Footprints(
return; return;
} }
FILE* netfile = OpenNetlistFile( aNetlistFullFilename );
if( !netfile )
return;
SetLastNetListRead( aNetlistFullFilename );
// Build the list of references of the net list modules. // Build the list of references of the net list modules.
NETLIST_READER netList_Reader( this ); NETLIST_READER netList_Reader( this );
NbModulesNetListe = netList_Reader.BuildComponentsListFromNetlist( aNetlistFullFilename, tmp ); netList_Reader.SetFilesnames( aNetlistFullFilename, wxEmptyString );
netList_Reader.BuildModuleListOnly( true );
if( ! netList_Reader.ReadNetList( netfile ) )
return; // error
if( NbModulesNetListe < 0 ) std::vector <MODULE_INFO*>& moduleInfoList = netList_Reader.GetModuleInfoList();
return; // File not found
if( NbModulesNetListe == 0 ) if( moduleInfoList.size() == 0 )
{ {
wxMessageBox( _( "No modules in NetList" ) ); wxMessageBox( _( "No modules in NetList" ) );
return; return;
...@@ -845,43 +533,35 @@ void PCB_EDIT_FRAME::Test_Duplicate_Missing_And_Extra_Footprints( ...@@ -845,43 +533,35 @@ void PCB_EDIT_FRAME::Test_Duplicate_Missing_And_Extra_Footprints(
} }
} }
// Search for the missing module by the net list. // Search for missing modules on board.
list.Add( _( "Missing:" ) ); list.Add( _( "Missing:" ) );
for( ii = 0; ii < NbModulesNetListe; ii++ ) for( unsigned ii = 0; ii < moduleInfoList.size(); ii++ )
{ {
module = (MODULE*) GetBoard()->m_Modules; MODULE_INFO* mod_info = moduleInfoList[ii];
module = GetBoard()->FindModuleByReference( mod_info->m_Reference );
for( ; module != NULL; module = module->Next() )
{
if( module->m_Reference->m_Text.CmpNoCase( tmp[ii] ) == 0 )
{
break;
}
}
if( module == NULL ) // Module missing, not found in board if( module == NULL ) // Module missing, not found in board
{ {
list.Add( tmp[ii] ); list.Add( mod_info->m_Reference );
nberr++; nberr++;
} }
} }
// Search for modules not in net list. // Search for modules found on board but not in net list.
list.Add( _( "Not in Netlist:" ) ); list.Add( _( "Not in Netlist:" ) );
module = GetBoard()->m_Modules; module = GetBoard()->m_Modules;
for( ; module != NULL; module = module->Next() ) for( ; module != NULL; module = module->Next() )
{ {
for( ii = 0; ii < NbModulesNetListe; ii++ ) unsigned ii;
{ for( ii = 0; ii < moduleInfoList.size(); ii++ )
if( module->m_Reference->m_Text.CmpNoCase( tmp[ii] ) == 0 )
{ {
MODULE_INFO* mod_info = moduleInfoList[ii];
if( module->m_Reference->m_Text.CmpNoCase( mod_info->m_Reference ) == 0 )
break; // Module is in net list. break; // Module is in net list.
} }
}
if( ii == NbModulesNetListe ) // Module not found in netlist if( ii == moduleInfoList.size() ) // Module not found in netlist
{ {
list.Add( module->m_Reference->m_Text ); list.Add( module->m_Reference->m_Text );
nberr++; nberr++;
...@@ -895,105 +575,17 @@ void PCB_EDIT_FRAME::Test_Duplicate_Missing_And_Extra_Footprints( ...@@ -895,105 +575,17 @@ void PCB_EDIT_FRAME::Test_Duplicate_Missing_And_Extra_Footprints(
} }
/**
* Function BuildComponentsListFromNetlist
* Fill aBufName with component references read from the netlist.
* @param aNetlistFilename = netlist full file name
* @param aBufName = wxArrayString to fill with component references
* @return component count, or -1 if netlist file cannot opened
*/
int NETLIST_READER::BuildComponentsListFromNetlist( const wxString& aNetlistFilename,
wxArrayString& aBufName )
{
int component_count;
int state;
bool is_comment;
char* text;
FILE* netfile = OpenNetlistFile( aNetlistFilename );
if( netfile == NULL )
return -1;
FILE_LINE_READER netlineReader( netfile, aNetlistFilename ); // ctor will close netfile
char* Line = netlineReader;
state = 0;
is_comment = false;
component_count = 0;
while( netlineReader.ReadLine() )
{
text = StrPurge( Line );
if( is_comment )
{
if( ( text = strchr( text, '}' ) ) == NULL )
continue;
is_comment = false;
}
if( *text == '{' ) // Comments.
{
is_comment = true;
if( ( text = strchr( text, '}' ) ) == NULL )
continue;
}
if( *text == '(' )
state++;
if( *text == ')' )
state--;
if( state == 2 )
{
// skip TimeStamp:
strtok( Line, " ()\t\n" );
// skip footprint name:
strtok( NULL, " ()\t\n" );
// Load the reference of the component:
text = strtok( NULL, " ()\t\n" );
component_count++;
aBufName.Add( FROM_UTF8( text ) );
continue;
}
if( state >= 3 )
{
state--;
}
}
return component_count;
}
/* /*
* function readModuleComponentLinkfile * function readModuleComponentLinkfile
* read the *.cmp file ( filename in m_cmplistFullName ) * read the *.cmp file ( filename in m_cmplistFullName )
* giving the equivalence Footprint_names / components * giving the equivalence Footprint_names / components
* to find the footprint name corresponding to aCmpIdent * to find the footprint name corresponding to aCmpIdent
* return true and the module name in aFootprintName, false if not found * return true if the file can be read
*
* param aCmpIdent = component identification: schematic reference or time stamp
* param aFootprintName the footprint name corresponding to the component identification
* *
* Sample file: * Sample file:
* *
* Cmp-Mod V01 Genere by Pcbnew 29/10/2003-13: 11:6 * * Cmp-Mod V01 Genere by Pcbnew 29/10/2003-13: 11:6 *
* BeginCmp * BeginCmp
* TimeStamp = /322D3011;
* Reference = BUS1;
* ValeurCmp = BUSPC;
* IdModule = BUS_PC;
* EndCmp
*
* BeginCmp
* TimeStamp = /32307DE2/AA450F67; * TimeStamp = /32307DE2/AA450F67;
* Reference = C1; * Reference = C1;
* ValeurCmp = 47uF; * ValeurCmp = 47uF;
...@@ -1001,12 +593,12 @@ int NETLIST_READER::BuildComponentsListFromNetlist( const wxString& aNetlistFile ...@@ -1001,12 +593,12 @@ int NETLIST_READER::BuildComponentsListFromNetlist( const wxString& aNetlistFile
* EndCmp * EndCmp
* *
*/ */
bool NETLIST_READER::readModuleComponentLinkfile( const wxString* aCmpIdent,
wxString& aFootprintName ) bool NETLIST_READER::readModuleComponentLinkfile()
{ {
wxString refcurrcmp; // Stores value read from line like Reference = BUS1; wxString refcurrcmp; // Stores value read from line like Reference = BUS1;
wxString timestamp; // Stores value read from line like TimeStamp = /32307DE2/AA450F67; wxString timestamp; // Stores value read from line like TimeStamp = /32307DE2/AA450F67;
wxString idmod; // Stores value read from line like IdModule = CP6; wxString footprint; // Stores value read from line like IdModule = CP6;
FILE* cmpFile = wxFopen( m_cmplistFullName, wxT( "rt" ) ); FILE* cmpFile = wxFopen( m_cmplistFullName, wxT( "rt" ) );
...@@ -1035,7 +627,7 @@ bool NETLIST_READER::readModuleComponentLinkfile( const wxString* aCmpIdent, ...@@ -1035,7 +627,7 @@ bool NETLIST_READER::readModuleComponentLinkfile( const wxString* aCmpIdent,
// Begin component description. // Begin component description.
refcurrcmp.Empty(); refcurrcmp.Empty();
idmod.Empty(); footprint.Empty();
timestamp.Empty(); timestamp.Empty();
while( netlineReader.ReadLine() ) while( netlineReader.ReadLine() )
...@@ -1059,7 +651,7 @@ bool NETLIST_READER::readModuleComponentLinkfile( const wxString* aCmpIdent, ...@@ -1059,7 +651,7 @@ bool NETLIST_READER::readModuleComponentLinkfile( const wxString* aCmpIdent,
if( buffer.StartsWith( wxT("IdModule =" ) ) ) if( buffer.StartsWith( wxT("IdModule =" ) ) )
{ {
idmod = value; footprint = value;
continue; continue;
} }
...@@ -1070,21 +662,28 @@ bool NETLIST_READER::readModuleComponentLinkfile( const wxString* aCmpIdent, ...@@ -1070,21 +662,28 @@ bool NETLIST_READER::readModuleComponentLinkfile( const wxString* aCmpIdent,
} }
} }
// Check if this component is the right component: // Find the corresponding item in module info list:
for( unsigned ii = 0; ii < m_modulesInNetlist.size(); ii++ )
{
MODULE_INFO * mod_info = m_modulesInNetlist[ii];
if( m_UseTimeStamp ) // Use schematic timestamp to locate the footprint if( m_UseTimeStamp ) // Use schematic timestamp to locate the footprint
{ {
if( aCmpIdent->CmpNoCase( timestamp ) == 0 && !timestamp.IsEmpty() ) if( mod_info->m_TimeStamp.CmpNoCase( timestamp ) == 0 &&
!timestamp.IsEmpty() )
{ // Found { // Found
aFootprintName = idmod; if( !footprint.IsEmpty() )
return true; mod_info->m_Footprint = footprint;
break;
} }
} }
else // Use schematic reference to locate the footprint else // Use schematic reference to locate the footprint
{ {
if( aCmpIdent->CmpNoCase( refcurrcmp ) == 0 ) // Found! if( mod_info->m_Reference.CmpNoCase( refcurrcmp ) == 0 ) // Found!
{ {
aFootprintName = idmod; if( !footprint.IsEmpty() )
return true; mod_info->m_Footprint = footprint;
break;
}
} }
} }
} }
...@@ -1093,6 +692,16 @@ bool NETLIST_READER::readModuleComponentLinkfile( const wxString* aCmpIdent, ...@@ -1093,6 +692,16 @@ bool NETLIST_READER::readModuleComponentLinkfile( const wxString* aCmpIdent,
} }
/* Function to sort the footprint list, used by loadNewModules.
* the given list is sorted by name
*/
static bool SortByLibName( MODULE_INFO* ref, MODULE_INFO* cmp )
{
int ii = ref->m_Footprint.CmpNoCase( cmp->m_Footprint );
return ii > 0;
}
/* Load new modules from library. /* Load new modules from library.
* If a new module is already loaded it is duplicated, which avoids multiple * If a new module is already loaded it is duplicated, which avoids multiple
* unnecessary disk or net access to read libraries. * unnecessary disk or net access to read libraries.
...@@ -1126,30 +735,25 @@ bool NETLIST_READER::loadNewModules() ...@@ -1126,30 +735,25 @@ bool NETLIST_READER::loadNewModules()
{ {
cmp = m_newModulesList[ii]; cmp = m_newModulesList[ii];
if( (ii == 0) || ( ref->m_LibName != cmp->m_LibName) ) if( (ii == 0) || ( ref->m_Footprint != cmp->m_Footprint) )
{ {
// New footprint : must be loaded from a library // New footprint : must be loaded from a library
Module = m_pcbframe->GetModuleLibrary( wxEmptyString, cmp->m_LibName, false ); Module = m_pcbframe->GetModuleLibrary( wxEmptyString, cmp->m_Footprint, false );
ref = cmp; ref = cmp;
if( Module == NULL ) if( Module == NULL )
{ {
success = false; success = false;
if( m_messageWindow )
{
wxString msg; wxString msg;
msg.Printf( _( "Component [%s]: footprint <%s> not found" ), msg.Printf( _( "Component [%s]: footprint <%s> not found" ),
GetChars( cmp->m_CmpName ), GetChars( cmp->m_Reference ),
GetChars( cmp->m_LibName ) ); GetChars( cmp->m_Footprint ) );
if( m_messageWindow )
{
msg += wxT("\n"); msg += wxT("\n");
m_messageWindow->AppendText( msg ); m_messageWindow->AppendText( msg );
} }
else
{
DisplayError( NULL, msg );
}
continue; continue;
} }
...@@ -1157,9 +761,9 @@ bool NETLIST_READER::loadNewModules() ...@@ -1157,9 +761,9 @@ bool NETLIST_READER::loadNewModules()
/* Update schematic links : reference "Time Stamp" and schematic /* Update schematic links : reference "Time Stamp" and schematic
* hierarchical path */ * hierarchical path */
Module->m_Reference->m_Text = cmp->m_CmpName; Module->m_Reference->m_Text = cmp->m_Reference;
Module->SetTimeStamp( GetNewTimeStamp() ); Module->SetTimeStamp( GetNewTimeStamp() );
Module->m_Path = cmp->m_TimeStampPath; Module->SetPath( cmp->m_TimeStamp );
} }
else else
{ {
...@@ -1173,9 +777,9 @@ bool NETLIST_READER::loadNewModules() ...@@ -1173,9 +777,9 @@ bool NETLIST_READER::loadNewModules()
pcb->Add( newmodule, ADD_APPEND ); pcb->Add( newmodule, ADD_APPEND );
Module = newmodule; Module = newmodule;
Module->m_Reference->m_Text = cmp->m_CmpName; Module->m_Reference->m_Text = cmp->m_Reference;
Module->SetTimeStamp( GetNewTimeStamp() ); Module->SetTimeStamp( GetNewTimeStamp() );
Module->m_Path = cmp->m_TimeStampPath; Module->SetPath( cmp->m_TimeStamp );
} }
} }
......
#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
/**
* @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;
}
/**
* @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;
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment