440 lines
16 KiB
C++
440 lines
16 KiB
C++
#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 <boost/ptr_container/ptr_vector.hpp>
|
|
|
|
#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 for a footprint the footprint filter info,
|
|
* found in new format KiCad netlist.
|
|
* For CvPcb only
|
|
* Note: features for CvPcb are for a temporary use.
|
|
* They could be removed when CvPcb is modified
|
|
* (perhaps when it does not use anumore a netlist to build the component to footprint link)
|
|
*/
|
|
class LIPBART_INFO
|
|
{
|
|
public:
|
|
wxString m_Libpart; // the libpart name.
|
|
wxArrayString m_FootprintFilter; // an array of footprint filters found in netlist,
|
|
// for this footprint
|
|
|
|
public:
|
|
|
|
LIPBART_INFO( const wxString& aLibpart )
|
|
{
|
|
m_Libpart = aLibpart;
|
|
}
|
|
};
|
|
|
|
typedef std::vector <LIPBART_INFO *> LIPBART_INFO_LIST;
|
|
|
|
|
|
/*
|
|
* Helper class, to store components and footprints info found in netlist.
|
|
* (component reference and time stamp, footprint name ...
|
|
*/
|
|
class COMPONENT_INFO
|
|
{
|
|
public:
|
|
wxString m_Footprint; // the footprint name found in netlist, the in .cmp file
|
|
wxString m_Reference; // the schematic reference found in netlist
|
|
wxString m_Value; // the schematic value found in netlist
|
|
wxString m_TimeStamp; // the schematic full time stamp found in netlist
|
|
wxString m_Libpart; // the schematic libpart found in netlist
|
|
wxArrayString m_FootprintFilter; // a footprint filters list found in old format netlist
|
|
int m_pinCount; // the number of pins found in the netlist
|
|
|
|
public: COMPONENT_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;
|
|
m_pinCount = 0;
|
|
}
|
|
|
|
~COMPONENT_INFO() { };
|
|
};
|
|
|
|
enum typenetlist
|
|
{
|
|
NETLIST_TYPE_UNSPECIFIED = 0,
|
|
NETLIST_TYPE_ORCADPCB2, // the basic format used by pcbnew
|
|
NETLIST_TYPE_PCBNEW, // the format used by pcbnew, basic format + more info
|
|
NETLIST_TYPE_KICAD // new format using common S expression
|
|
};
|
|
|
|
|
|
typedef std::vector <COMPONENT_INFO*> COMPONENT_INFO_LIST;
|
|
/*
|
|
* Helper class, to read a netlist.
|
|
*/
|
|
class NETLIST_READER
|
|
{
|
|
private:
|
|
PCB_EDIT_FRAME* m_pcbframe; // the main Pcbnew frame (or NULL for CvPcb)
|
|
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
|
|
COMPONENT_INFO_LIST m_componentsInNetlist; // The list of footprints, found in netlist
|
|
// (must be loaded from libraries)
|
|
COMPONENT_INFO_LIST m_newModulesList; // The list of new footprints,
|
|
// found in netlist, but not on board
|
|
// (must be loaded from libraries)
|
|
LIPBART_INFO_LIST m_libpartList; // For Kicad new netlist format:
|
|
// list of libpart found in netlist
|
|
// A libpart contains the footprint filters for CvPcb
|
|
bool m_buildModuleListOnly; // if true read netlist, populates m_componentsInNetlist
|
|
// but do not read and change nets and modules on board
|
|
bool m_readLibpartSection; // if true read Libparts section,
|
|
// and therefore the footprints filters
|
|
enum typenetlist m_typeNetlist; // type opt the netlist currently read
|
|
|
|
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;
|
|
m_readLibpartSection = false;
|
|
m_typeNetlist = NETLIST_TYPE_UNSPECIFIED;
|
|
}
|
|
|
|
~NETLIST_READER()
|
|
{
|
|
// Free modules info list:
|
|
for( unsigned ii = 0; ii < m_newModulesList.size(); ii++ )
|
|
delete m_componentsInNetlist[ii];
|
|
|
|
m_componentsInNetlist.clear();
|
|
m_newModulesList.clear();
|
|
|
|
// Free libpart info list:
|
|
for( unsigned ii = 0; ii < m_libpartList.size(); ii++ )
|
|
delete m_libpartList[ii];
|
|
m_libpartList.clear();
|
|
}
|
|
|
|
/**
|
|
* Function GetNetlistType
|
|
* @return the type of netlist read:
|
|
* NETLIST_TYPE_UNSPECIFIED: Unknown format
|
|
* NETLIST_TYPE_ORCADPCB2: the basic format used by pcbnew
|
|
* NETLIST_TYPE_PCBNEW: the format used by pcbnew, basic format + more info
|
|
* NETLIST_TYPE_KICAD: the new format
|
|
*/
|
|
int GetNetlistType()
|
|
{
|
|
return m_typeNetlist;
|
|
}
|
|
|
|
/**
|
|
* Function GetComponentInfoList
|
|
* @return the component info list built from the netlist
|
|
*/
|
|
COMPONENT_INFO_LIST& GetComponentInfoList()
|
|
{
|
|
return m_componentsInNetlist;
|
|
}
|
|
|
|
/**
|
|
* Function GetComponentInfoList
|
|
* @return a reference to the libpart info corresponding to a given part
|
|
* @param aPartname = the name of the libpart
|
|
*/
|
|
LIPBART_INFO* GetLibpart(const wxString & aPartname);
|
|
|
|
/**
|
|
* Function IsCvPcbMode
|
|
* @return true if the netlist is read by CvPcb
|
|
* In cvpcb mode, nets are stored in module info,
|
|
* and the footprint filters list is read.
|
|
* There is also no board in CvPcb
|
|
*/
|
|
bool IsCvPcbMode() { return m_pcbframe == 0; }
|
|
|
|
/**
|
|
* 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( COMPONENT_INFO* aModInfo )
|
|
{
|
|
m_componentsInNetlist.push_back( aModInfo );
|
|
}
|
|
|
|
/**
|
|
* Function AddLibpartInfo
|
|
* LIPBART_INFO items (and therefore footprint filter strings) are stored in
|
|
* m_libpartList
|
|
* @param aPartInfo = a refernce to the LIPBART_INFO to add in list
|
|
*/
|
|
void AddLibpartInfo( LIPBART_INFO * aPartInfo )
|
|
{
|
|
m_libpartList.push_back( aPartInfo );
|
|
}
|
|
|
|
/**
|
|
* Function ReadLibpartSectionSetOpt
|
|
* Set to true or false the read Partlists section.
|
|
* footprint filters are found in this section
|
|
* When this option is false, the Partlists section is ignored
|
|
* When this option is true, the Partlists section is read,
|
|
* Libpart items (and therefore footprint filter strings) are stored in
|
|
* m_libpartList
|
|
* @param aOpt = the value of option
|
|
*/
|
|
void ReadLibpartSectionSetOpt( bool aOpt )
|
|
{
|
|
m_readLibpartSection = aOpt;
|
|
}
|
|
|
|
/**
|
|
* Function ReadLibpartSectionOpt
|
|
* @return the readPartlist option
|
|
*/
|
|
bool ReadLibpartSectionOpt() { return m_readLibpartSection; }
|
|
|
|
/**
|
|
* Function BuildModuleListOnlySetOpt
|
|
* 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 BuildModuleListOnlySetOpt( bool aOpt )
|
|
{
|
|
m_buildModuleListOnly = aOpt;
|
|
}
|
|
|
|
/**
|
|
* Function BuildModuleListOnlyOpt
|
|
* Get the Build Module List Only option state
|
|
* @return the state of option (true/false)
|
|
*/
|
|
bool BuildModuleListOnlyOpt()
|
|
{
|
|
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 ReadOldFmtFootprintFilterList
|
|
* Read the section "Allowed footprints" like:
|
|
* { Allowed footprints by component:
|
|
* $component R11
|
|
* R?
|
|
* SM0603
|
|
* SM0805
|
|
* R?-*
|
|
* SM1206
|
|
* $endlist
|
|
* $endfootprintlist
|
|
* }
|
|
*
|
|
* And add the strings giving the footprint filter to m_FootprintFilter
|
|
* of the corresponding module info
|
|
* <p>This section is used by CvPcb, and is not useful in Pcbnew,
|
|
* therefore it it not always read </p>
|
|
*/
|
|
bool ReadOldFmtFootprintFilterList( FILE_LINE_READER& aNetlistReader );
|
|
|
|
/**
|
|
* 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 SetPadsNetName
|
|
* Update pads netnames for a given module.
|
|
* Because a pad name can be found more than once in this module,
|
|
* all pads matching the pad name are updated
|
|
* @param aModule = module reference
|
|
* @param aPadname = pad name (pad num)
|
|
* @param aNetname = new net name of the pad
|
|
* @param aPadList = a std::vector<D_PAD*>& buffer where the updated pads can be stored
|
|
* @return the pad count
|
|
*/
|
|
int SetPadsNetName( const wxString & aModule, const wxString & aPadname,
|
|
const wxString & aNetname, std::vector<D_PAD*> & aPadList );
|
|
|
|
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 if aBuildList = true, a reference to the COMPONENT_INFO
|
|
* if aBuildList = false, a reference to the corresponding MODULE on board (NULL if not found)
|
|
*/
|
|
void* 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_componentsInNetlist,
|
|
* 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
|