From eb99d460a319edd0625e567471e1e63f1c4a6999 Mon Sep 17 00:00:00 2001 From: jean-pierre charras Date: Wed, 1 Feb 2012 21:17:43 +0100 Subject: [PATCH] commint forgotten file --- pcbnew/netlist_reader_common.cpp | 550 +++++++++++++++++++++++++++++++ 1 file changed, 550 insertions(+) create mode 100644 pcbnew/netlist_reader_common.cpp diff --git a/pcbnew/netlist_reader_common.cpp b/pcbnew/netlist_reader_common.cpp new file mode 100644 index 0000000000..4d3454ec49 --- /dev/null +++ b/pcbnew/netlist_reader_common.cpp @@ -0,0 +1,550 @@ +/** + * @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 +#include +#include +#include + +#include +#include +#include + +#include + +#include + +/* + * 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; +}