Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
K
kicad-source-mirror
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Commits
Open sidebar
Elphel
kicad-source-mirror
Commits
2b3b2fc0
Commit
2b3b2fc0
authored
Feb 01, 2012
by
jean-pierre charras
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
commint forgotten file
parent
f9e2f9dc
Changes
1
Hide whitespace changes
Inline
Side-by-side
Showing
1 changed file
with
550 additions
and
0 deletions
+550
-0
netlist_reader_common.cpp
pcbnew/netlist_reader_common.cpp
+550
-0
No files found.
pcbnew/netlist_reader_common.cpp
0 → 100644
View file @
2b3b2fc0
/**
* @file pcbnew/netlist_reader_common.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 <fctsys.h>
#include <wxPcbStruct.h>
#include <richio.h>
#include <macros.h>
#include <class_board.h>
#include <class_module.h>
#include <pcbnew.h>
#include <netlist_reader.h>
#include <algorithm>
/*
* Function ReadNetList
* 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)
*/
bool
NETLIST_READER
::
ReadNetList
(
FILE
*
aFile
)
{
// Try to determine the netlist type:
// Beginning of the first line of known formats, without spaces
#define HEADERS_COUNT 3
#define HEADER_ORCADPCB "({EESchemaNetlist"
#define HEADER_PCBNEW "#EESchemaNetlist"
#define HEADER_KICAD_NETFMT "(export"
const
std
::
string
headers
[
HEADERS_COUNT
]
=
{
HEADER_ORCADPCB
,
HEADER_PCBNEW
,
HEADER_KICAD_NETFMT
};
int
format
=
-
1
;
for
(
int
jj
=
0
;
jj
<
HEADERS_COUNT
;
jj
++
)
{
int
imax
=
headers
[
jj
].
size
();
int
ii
=
0
;
for
(
;
ii
<
imax
;
ii
++
)
{
int
data
;
// Read header, and skip blanks to avoid errors if an header changes
do
{
data
=
fgetc
(
aFile
);
}
while
(
(
data
==
' '
)
&&
(
EOF
!=
data
)
)
;
if
(
(
int
)
headers
[
jj
][
ii
]
==
data
)
continue
;
break
;
}
if
(
ii
==
imax
)
// header found
{
format
=
jj
;
break
;
}
rewind
(
aFile
);
}
rewind
(
aFile
);
bool
success
=
false
;
switch
(
format
)
{
case
0
:
m_typeNetlist
=
NETLIST_TYPE_ORCADPCB2
;
success
=
ReadOldFmtdNetList
(
aFile
);
break
;
case
1
:
m_typeNetlist
=
NETLIST_TYPE_PCBNEW
;
success
=
ReadOldFmtdNetList
(
aFile
);
break
;
case
2
:
m_typeNetlist
=
NETLIST_TYPE_KICAD
;
success
=
ReadKicadNetList
(
aFile
);
break
;
default
:
// Unrecognized format:
break
;
}
return
success
;
}
/**
* Function GetComponentInfoList
* @return a reference to the libpart info corresponding to a given part
* @param aPartname = the name of the libpart
*/
LIPBART_INFO
*
NETLIST_READER
::
GetLibpart
(
const
wxString
&
aPartname
)
{
for
(
unsigned
ii
=
0
;
ii
<
m_libpartList
.
size
();
ii
++
)
{
if
(
m_libpartList
[
ii
]
->
m_Libpart
==
aPartname
)
return
m_libpartList
[
ii
];
}
return
NULL
;
}
bool
NETLIST_READER
::
InitializeModules
()
{
if
(
m_UseCmpFile
)
// Try to get footprint name from .cmp file
{
readModuleComponentLinkfile
();
}
if
(
m_pcbframe
==
NULL
)
return
true
;
for
(
unsigned
ii
=
0
;
ii
<
m_componentsInNetlist
.
size
();
ii
++
)
{
COMPONENT_INFO
*
currcmp_info
=
m_componentsInNetlist
[
ii
];
// Test if module is already loaded.
wxString
*
idMod
=
m_UseTimeStamp
?
&
currcmp_info
->
m_TimeStamp
:
&
currcmp_info
->
m_Reference
;
MODULE
*
module
=
FindModule
(
*
idMod
);
if
(
module
==
NULL
)
// not existing, load it
{
m_newModulesList
.
push_back
(
currcmp_info
);
}
}
bool
success
=
loadNewModules
();
// Update modules fields
for
(
unsigned
ii
=
0
;
ii
<
m_componentsInNetlist
.
size
();
ii
++
)
{
COMPONENT_INFO
*
currcmp_info
=
m_componentsInNetlist
[
ii
];
// Test if module is already loaded.
wxString
*
idMod
=
m_UseTimeStamp
?
&
currcmp_info
->
m_TimeStamp
:
&
currcmp_info
->
m_Reference
;
MODULE
*
module
=
FindModule
(
*
idMod
);
if
(
module
)
{
// Update current module ( reference, value and "Time Stamp")
module
->
m_Reference
->
m_Text
=
currcmp_info
->
m_Reference
;
module
->
m_Value
->
m_Text
=
currcmp_info
->
m_Value
;
module
->
SetPath
(
currcmp_info
->
m_TimeStamp
);
}
else
// not existing
{
}
}
// clear pads netnames
for
(
MODULE
*
module
=
m_pcbframe
->
GetBoard
()
->
m_Modules
;
module
;
module
=
module
->
Next
()
)
{
for
(
D_PAD
*
pad
=
module
->
m_Pads
;
pad
;
pad
=
pad
->
Next
()
)
pad
->
SetNetname
(
wxEmptyString
);
}
return
success
;
}
void
NETLIST_READER
::
TestFootprintsMatchingAndExchange
()
{
#ifdef PCBNEW
for
(
MODULE
*
module
=
m_pcbframe
->
GetBoard
()
->
m_Modules
;
module
;
module
=
module
->
Next
()
)
{
// Search for the corresponding module info
COMPONENT_INFO
*
cmp_info
=
NULL
;
for
(
unsigned
ii
=
0
;
ii
<
m_componentsInNetlist
.
size
();
ii
++
)
{
COMPONENT_INFO
*
candidate
=
m_componentsInNetlist
[
ii
];
// Test if cmp_info matches the current module:
if
(
candidate
->
m_Reference
.
CmpNoCase
(
module
->
GetReference
()
)
==
0
)
{
cmp_info
=
candidate
;
break
;
}
}
if
(
cmp_info
==
NULL
)
// not found in netlist
continue
;
if
(
module
->
GetLibRef
().
CmpNoCase
(
cmp_info
->
m_Footprint
)
!=
0
)
{
if
(
m_ChangeFootprints
)
// footprint exchange allowed.
{
MODULE
*
newModule
=
m_pcbframe
->
GetModuleLibrary
(
wxEmptyString
,
cmp_info
->
m_Footprint
,
false
);
if
(
newModule
)
{
// Change old module to the new module (and delete the old one)
m_pcbframe
->
Exchange_Module
(
module
,
newModule
,
NULL
);
module
=
newModule
;
}
else
if
(
m_messageWindow
)
{
wxString
msg
;
msg
.
Printf
(
_
(
"Component
\"
%s
\"
: module [%s] not found
\n
"
),
GetChars
(
cmp_info
->
m_Reference
),
GetChars
(
cmp_info
->
m_Footprint
)
);
m_messageWindow
->
AppendText
(
msg
);
}
}
else
if
(
m_messageWindow
)
{
wxString
msg
;
msg
.
Printf
(
_
(
"Component
\"
%s
\"
: Mismatch! module is [%s] and netlist said [%s]
\n
"
),
GetChars
(
cmp_info
->
m_Reference
),
GetChars
(
module
->
GetLibRef
()
),
GetChars
(
cmp_info
->
m_Footprint
)
);
m_messageWindow
->
AppendText
(
msg
);
}
}
}
#endif
}
/**
* 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
)
{
if
(
m_pcbframe
==
NULL
)
return
NULL
;
MODULE
*
module
=
m_pcbframe
->
GetBoard
()
->
FindModuleByReference
(
aModule
);
if
(
module
)
{
D_PAD
*
pad
=
module
->
FindPadByName
(
aPadname
);
if
(
pad
)
{
pad
->
SetNetname
(
aNetname
);
return
pad
;
}
if
(
m_messageWindow
)
{
wxString
msg
;
msg
.
Printf
(
_
(
"Module [%s]: Pad [%s] not found"
),
GetChars
(
aModule
),
GetChars
(
aPadname
)
);
m_messageWindow
->
AppendText
(
msg
+
wxT
(
"
\n
"
)
);
}
}
return
NULL
;
}
/* function RemoveExtraFootprints
* Remove (delete) not locked footprints found on board, but not in netlist
*/
void
NETLIST_READER
::
RemoveExtraFootprints
()
{
MODULE
*
nextModule
;
MODULE
*
module
=
m_pcbframe
->
GetBoard
()
->
m_Modules
;
for
(
;
module
!=
NULL
;
module
=
nextModule
)
{
unsigned
ii
;
nextModule
=
module
->
Next
();
if
(
module
->
m_ModuleStatus
&
MODULE_is_LOCKED
)
continue
;
for
(
ii
=
0
;
ii
<
m_componentsInNetlist
.
size
();
ii
++
)
{
COMPONENT_INFO
*
cmp_info
=
m_componentsInNetlist
[
ii
];
if
(
module
->
m_Reference
->
m_Text
.
CmpNoCase
(
cmp_info
->
m_Reference
)
==
0
)
break
;
// Module is found in net list.
}
if
(
ii
==
m_componentsInNetlist
.
size
()
)
// Module not found in netlist.
module
->
DeleteStructure
();
}
}
/* Search for a module id the modules existing in the current BOARD.
* 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
()
)
{
if
(
m_UseTimeStamp
)
// identification by time stamp
{
if
(
aId
.
CmpNoCase
(
module
->
m_Path
)
==
0
)
return
module
;
}
else
// identification by Reference
{
if
(
aId
.
CmpNoCase
(
module
->
m_Reference
->
m_Text
)
==
0
)
return
module
;
}
}
return
NULL
;
}
/*
* function readModuleComponentLinkfile
* read the *.cmp file ( filename in m_cmplistFullName )
* giving the equivalence Footprint_names / components
* to find the footprint name corresponding to aCmpIdent
* return true if the file can be read
*
* Sample file:
*
* Cmp-Mod V01 Genere by Pcbnew 29/10/2003-13: 11:6 *
* BeginCmp
* TimeStamp = /32307DE2/AA450F67;
* Reference = C1;
* ValeurCmp = 47uF;
* IdModule = CP6;
* EndCmp
*
*/
bool
NETLIST_READER
::
readModuleComponentLinkfile
()
{
wxString
refcurrcmp
;
// Stores value read from line like Reference = BUS1;
wxString
timestamp
;
// Stores value read from line like TimeStamp = /32307DE2/AA450F67;
wxString
footprint
;
// Stores value read from line like IdModule = CP6;
FILE
*
cmpFile
=
wxFopen
(
m_cmplistFullName
,
wxT
(
"rt"
)
);
if
(
cmpFile
==
NULL
)
{
wxString
msg
;
msg
.
Printf
(
_
(
"File <%s> not found, use Netlist for footprints selection"
),
GetChars
(
m_cmplistFullName
)
);
if
(
m_messageWindow
)
m_messageWindow
->
AppendText
(
msg
);
return
false
;
}
// netlineReader dtor will close cmpFile
FILE_LINE_READER
netlineReader
(
cmpFile
,
m_cmplistFullName
);
wxString
buffer
;
wxString
value
;
while
(
netlineReader
.
ReadLine
()
)
{
buffer
=
FROM_UTF8
(
netlineReader
.
Line
()
);
if
(
!
buffer
.
StartsWith
(
wxT
(
"BeginCmp"
)
)
)
continue
;
// Begin component description.
refcurrcmp
.
Empty
();
footprint
.
Empty
();
timestamp
.
Empty
();
while
(
netlineReader
.
ReadLine
()
)
{
buffer
=
FROM_UTF8
(
netlineReader
.
Line
()
);
if
(
buffer
.
StartsWith
(
wxT
(
"EndCmp"
)
)
)
break
;
// store string value, stored between '=' and ';' delimiters.
value
=
buffer
.
AfterFirst
(
'='
);
value
=
value
.
BeforeLast
(
';'
);
value
.
Trim
(
true
);
value
.
Trim
(
false
);
if
(
buffer
.
StartsWith
(
wxT
(
"Reference"
)
)
)
{
refcurrcmp
=
value
;
continue
;
}
if
(
buffer
.
StartsWith
(
wxT
(
"IdModule ="
)
)
)
{
footprint
=
value
;
continue
;
}
if
(
buffer
.
StartsWith
(
wxT
(
"TimeStamp ="
)
)
)
{
timestamp
=
value
;
continue
;
}
}
// Find the corresponding item in module info list:
for
(
unsigned
ii
=
0
;
ii
<
m_componentsInNetlist
.
size
();
ii
++
)
{
COMPONENT_INFO
*
cmp_info
=
m_componentsInNetlist
[
ii
];
if
(
m_UseTimeStamp
)
// Use schematic timestamp to locate the footprint
{
if
(
cmp_info
->
m_TimeStamp
.
CmpNoCase
(
timestamp
)
==
0
&&
!
timestamp
.
IsEmpty
()
)
{
// Found
if
(
!
footprint
.
IsEmpty
()
)
cmp_info
->
m_Footprint
=
footprint
;
break
;
}
}
else
// Use schematic reference to locate the footprint
{
if
(
cmp_info
->
m_Reference
.
CmpNoCase
(
refcurrcmp
)
==
0
)
// Found!
{
if
(
!
footprint
.
IsEmpty
()
)
cmp_info
->
m_Footprint
=
footprint
;
break
;
}
}
}
}
return
true
;
}
/* Function to sort the footprint list, used by loadNewModules.
* the given list is sorted by name
*/
#ifdef PCBNEW
static
bool
SortByLibName
(
COMPONENT_INFO
*
ref
,
COMPONENT_INFO
*
cmp
)
{
int
ii
=
ref
->
m_Footprint
.
CmpNoCase
(
cmp
->
m_Footprint
);
return
ii
>
0
;
}
#endif
/* Load new modules from library.
* If a new module is already loaded it is duplicated, which avoid multiple
* unnecessary disk or net access to read libraries.
* return false if a footprint is not found, true if OK
*/
bool
NETLIST_READER
::
loadNewModules
()
{
bool
success
=
true
;
#ifdef PCBNEW
COMPONENT_INFO
*
ref
,
*
cmp
;
MODULE
*
Module
=
NULL
;
wxPoint
ModuleBestPosition
;
BOARD
*
pcb
=
m_pcbframe
->
GetBoard
();
if
(
m_newModulesList
.
size
()
==
0
)
return
true
;
sort
(
m_newModulesList
.
begin
(),
m_newModulesList
.
end
(),
SortByLibName
);
// Calculate the footprint "best" position:
EDA_RECT
bbbox
=
pcb
->
ComputeBoundingBox
(
true
);
if
(
bbbox
.
GetWidth
()
||
bbbox
.
GetHeight
()
)
{
ModuleBestPosition
=
bbbox
.
GetEnd
();
ModuleBestPosition
.
y
+=
5000
;
}
ref
=
cmp
=
m_newModulesList
[
0
];
for
(
unsigned
ii
=
0
;
ii
<
m_newModulesList
.
size
();
ii
++
)
{
cmp
=
m_newModulesList
[
ii
];
if
(
(
ii
==
0
)
||
(
ref
->
m_Footprint
!=
cmp
->
m_Footprint
)
)
{
// New footprint : must be loaded from a library
Module
=
m_pcbframe
->
GetModuleLibrary
(
wxEmptyString
,
cmp
->
m_Footprint
,
false
);
ref
=
cmp
;
if
(
Module
==
NULL
)
{
success
=
false
;
if
(
m_messageWindow
)
{
wxString
msg
;
msg
.
Printf
(
_
(
"Component [%s]: footprint <%s> not found"
),
GetChars
(
cmp
->
m_Reference
),
GetChars
(
cmp
->
m_Footprint
)
);
msg
+=
wxT
(
"
\n
"
);
m_messageWindow
->
AppendText
(
msg
);
}
continue
;
}
Module
->
SetPosition
(
ModuleBestPosition
);
/* Update schematic links : reference "Time Stamp" and schematic
* hierarchical path */
Module
->
m_Reference
->
m_Text
=
cmp
->
m_Reference
;
Module
->
SetTimeStamp
(
GetNewTimeStamp
()
);
Module
->
SetPath
(
cmp
->
m_TimeStamp
);
}
else
{
// Footprint already loaded from a library, duplicate it (faster)
if
(
Module
==
NULL
)
continue
;
// Module does not exist in library.
MODULE
*
newmodule
=
new
MODULE
(
*
Module
);
newmodule
->
SetParent
(
pcb
);
pcb
->
Add
(
newmodule
,
ADD_APPEND
);
Module
=
newmodule
;
Module
->
m_Reference
->
m_Text
=
cmp
->
m_Reference
;
Module
->
SetTimeStamp
(
GetNewTimeStamp
()
);
Module
->
SetPath
(
cmp
->
m_TimeStamp
);
}
}
#endif
return
success
;
}
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment