ADDED: Cadence Allegro PCB Designer netlist exporter
This commit is contained in:
parent
6d3f512e15
commit
4cb993d872
|
@ -145,6 +145,7 @@ const std::string LtspiceSchematicExtension( "asc" );
|
|||
const std::string CadstarNetlistFileExtension( "frp" );
|
||||
const std::string OrCadPcb2NetlistFileExtension( "net" );
|
||||
const std::string NetlistFileExtension( "net" );
|
||||
const std::string AllegroNetlistFileExtension( "txt" );
|
||||
const std::string FootprintAssignmentFileExtension( "cmp" );
|
||||
const std::string GerberFileExtension( "gbr" );
|
||||
const std::string GerberJobFileExtension( "gbrjob" );
|
||||
|
@ -330,6 +331,13 @@ wxString NetlistFileWildcard()
|
|||
}
|
||||
|
||||
|
||||
wxString AllegroNetlistFileWildcard()
|
||||
{
|
||||
return _( "Allegro netlist files" )
|
||||
+ AddFileExtListToFilter( { AllegroNetlistFileExtension } );
|
||||
}
|
||||
|
||||
|
||||
wxString LegacyPcbFileWildcard()
|
||||
{
|
||||
return _( "KiCad printed circuit board files" ) + AddFileExtListToFilter( { "brd" } );
|
||||
|
|
|
@ -355,6 +355,7 @@ set( EESCHEMA_SRCS
|
|||
toolbars_sch_editor.cpp
|
||||
toolbars_symbol_viewer.cpp
|
||||
|
||||
netlist_exporters/netlist_exporter_allegro.cpp
|
||||
netlist_exporters/netlist_exporter_base.cpp
|
||||
netlist_exporters/netlist_exporter_cadstar.cpp
|
||||
netlist_exporters/netlist_exporter_kicad.cpp
|
||||
|
|
|
@ -59,9 +59,11 @@
|
|||
|
||||
|
||||
/* panel (notebook page) identifiers */
|
||||
enum panel_netlist_index {
|
||||
enum panel_netlist_index
|
||||
{
|
||||
PANELPCBNEW = 0, /* Handle Netlist format Pcbnew */
|
||||
PANELORCADPCB2, /* Handle Netlist format OracdPcb2 */
|
||||
PANELALLEGRO, /* Handle Netlist format Allegro */
|
||||
PANELCADSTAR, /* Handle Netlist format CadStar */
|
||||
PANELSPICE, /* Handle Netlist format Spice */
|
||||
PANELSPICEMODEL, /* Handle Netlist format Spice Model (subcircuit) */
|
||||
|
@ -245,14 +247,17 @@ DIALOG_EXPORT_NETLIST::DIALOG_EXPORT_NETLIST( SCH_EDIT_FRAME* parent ) :
|
|||
page = nullptr;
|
||||
|
||||
// Add notebook pages:
|
||||
m_PanelNetType[PANELPCBNEW] = new EXPORT_NETLIST_PAGE( m_NoteBook, wxT( "KiCad" ),
|
||||
NET_TYPE_PCBNEW, false );
|
||||
m_PanelNetType[PANELPCBNEW] =
|
||||
new EXPORT_NETLIST_PAGE( m_NoteBook, wxT( "KiCad" ), NET_TYPE_PCBNEW, false );
|
||||
|
||||
m_PanelNetType[PANELORCADPCB2] = new EXPORT_NETLIST_PAGE( m_NoteBook, wxT( "OrcadPCB2" ),
|
||||
NET_TYPE_ORCADPCB2, false );
|
||||
m_PanelNetType[PANELORCADPCB2] =
|
||||
new EXPORT_NETLIST_PAGE( m_NoteBook, wxT( "OrcadPCB2" ), NET_TYPE_ORCADPCB2, false );
|
||||
|
||||
m_PanelNetType[PANELCADSTAR] = new EXPORT_NETLIST_PAGE( m_NoteBook, wxT( "CadStar" ),
|
||||
NET_TYPE_CADSTAR, false );
|
||||
m_PanelNetType[PANELALLEGRO] =
|
||||
new EXPORT_NETLIST_PAGE( m_NoteBook, wxT( "Allegro" ), NET_TYPE_ALLEGRO, false );
|
||||
|
||||
m_PanelNetType[PANELCADSTAR] =
|
||||
new EXPORT_NETLIST_PAGE( m_NoteBook, wxT( "CadStar" ), NET_TYPE_CADSTAR, false );
|
||||
|
||||
InstallPageSpice();
|
||||
InstallPageSpiceModel();
|
||||
|
@ -496,6 +501,9 @@ bool DIALOG_EXPORT_NETLIST::TransferDataFromWindow()
|
|||
case NET_TYPE_ORCADPCB2:
|
||||
break;
|
||||
|
||||
case NET_TYPE_ALLEGRO:
|
||||
break;
|
||||
|
||||
default: // custom, NET_TYPE_CUSTOM1 and greater
|
||||
{
|
||||
title.Printf( _( "%s Export" ), currPage->m_TitleStringCtrl->GetValue() );
|
||||
|
@ -629,6 +637,11 @@ bool DIALOG_EXPORT_NETLIST::FilenamePrms( NETLIST_TYPE_ID aType, wxString * aExt
|
|||
fileWildcard = NetlistFileWildcard();
|
||||
break;
|
||||
|
||||
case NET_TYPE_ALLEGRO:
|
||||
fileExt = AllegroNetlistFileExtension;
|
||||
fileWildcard = AllegroNetlistFileWildcard();
|
||||
break;
|
||||
|
||||
default: // custom, NET_TYPE_CUSTOM1 and greater
|
||||
fileWildcard = AllFilesWildcard();
|
||||
ret = false;
|
||||
|
|
|
@ -1242,25 +1242,43 @@ LIB_FIELD* LIB_SYMBOL::GetFieldById( int aId ) const
|
|||
}
|
||||
|
||||
|
||||
LIB_FIELD* LIB_SYMBOL::FindField( const wxString& aFieldName )
|
||||
LIB_FIELD* LIB_SYMBOL::FindField( const wxString& aFieldName, bool aCaseInsensitive )
|
||||
{
|
||||
for( LIB_ITEM& item : m_drawings[ LIB_FIELD_T ] )
|
||||
{
|
||||
if( aCaseInsensitive )
|
||||
{
|
||||
if( static_cast<LIB_FIELD*>( &item )->GetCanonicalName().Upper() == aFieldName.Upper() )
|
||||
return static_cast<LIB_FIELD*>( &item );
|
||||
}
|
||||
else
|
||||
{
|
||||
if( static_cast<LIB_FIELD*>( &item )->GetCanonicalName() == aFieldName )
|
||||
return static_cast<LIB_FIELD*>( &item );
|
||||
}
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
|
||||
const LIB_FIELD* LIB_SYMBOL::FindField( const wxString& aFieldName ) const
|
||||
const LIB_FIELD* LIB_SYMBOL::FindField( const wxString& aFieldName,
|
||||
const bool aCaseInsensitive ) const
|
||||
{
|
||||
for( const LIB_ITEM& item : m_drawings[ LIB_FIELD_T ] )
|
||||
{
|
||||
if( aCaseInsensitive )
|
||||
{
|
||||
if( static_cast<const LIB_FIELD*>( &item )->GetCanonicalName().Upper()
|
||||
== aFieldName.Upper() )
|
||||
return static_cast<const LIB_FIELD*>( &item );
|
||||
}
|
||||
else
|
||||
{
|
||||
if( static_cast<const LIB_FIELD*>( &item )->GetCanonicalName() == aFieldName )
|
||||
return static_cast<const LIB_FIELD*>( &item );
|
||||
}
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
|
|
@ -292,10 +292,15 @@ public:
|
|||
/**
|
||||
* Find a field within this symbol matching \a aFieldName and returns it
|
||||
* or NULL if not found.
|
||||
* @param aFieldName is the name of the field to find.
|
||||
* @param aCaseInsensitive ignore the filed name case if true.
|
||||
*
|
||||
* @return the field if found or NULL if the field was not found.
|
||||
*/
|
||||
LIB_FIELD* FindField( const wxString& aFieldName );
|
||||
LIB_FIELD* FindField( const wxString& aFieldName, bool aCaseInsensitive = false );
|
||||
|
||||
const LIB_FIELD* FindField( const wxString& aFieldName ) const;
|
||||
const LIB_FIELD* FindField( const wxString& aFieldName,
|
||||
const bool aCaseInsensitive = false ) const;
|
||||
|
||||
/**
|
||||
* Return pointer to the requested field.
|
||||
|
|
|
@ -40,6 +40,7 @@ enum NETLIST_TYPE_ID {
|
|||
NET_TYPE_CADSTAR,
|
||||
NET_TYPE_SPICE,
|
||||
NET_TYPE_SPICE_MODEL,
|
||||
NET_TYPE_ALLEGRO,
|
||||
NET_TYPE_CUSTOM1, /* NET_TYPE_CUSTOM1
|
||||
* is the first id for user netlist format
|
||||
* NET_TYPE_CUSTOM1+CUSTOMPANEL_COUNTMAX-1
|
||||
|
|
|
@ -0,0 +1,797 @@
|
|||
/*
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 1992-2018 jp.charras at wanadoo.fr
|
||||
* Copyright (C) 2013 SoftPLC Corporation, Dick Hollenbeck <dick@softplc.com>
|
||||
* Copyright (C) 1992-2021 KiCad Developers, see AUTHORS.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 <confirm.h>
|
||||
#include <refdes_utils.h>
|
||||
#include <sch_edit_frame.h>
|
||||
#include <sch_reference_list.h>
|
||||
#include <string_utils.h>
|
||||
#include <connection_graph.h>
|
||||
#include <core/kicad_algo.h>
|
||||
#include <symbol_library.h>
|
||||
#include <symbol_lib_table.h>
|
||||
#include <netlist.h>
|
||||
#include "netlist_exporter_allegro.h"
|
||||
#include "netlist_exporter_xml.h"
|
||||
#include <regex>
|
||||
|
||||
|
||||
bool NETLIST_EXPORTER_ALLEGRO::WriteNetlist( const wxString& aOutFileName,
|
||||
unsigned /* aNetlistOptions */,
|
||||
REPORTER& aReporter )
|
||||
{
|
||||
m_f = nullptr;
|
||||
wxString field;
|
||||
wxString footprint;
|
||||
int ret = 0; // zero now, OR in the sign bit on error
|
||||
wxString netName;
|
||||
|
||||
// Create the devices directory
|
||||
m_exportPath = wxFileName( aOutFileName ).GetPath( wxPATH_GET_VOLUME | wxPATH_GET_SEPARATOR )
|
||||
+ wxString( "devices" );
|
||||
if( !wxDirExists( m_exportPath ) )
|
||||
{
|
||||
if( !wxMkdir( m_exportPath, wxS_DIR_DEFAULT ) )
|
||||
{
|
||||
wxString msg = wxString::Format( _( "Failed to create directory 'devices' ." ) );
|
||||
aReporter.Report( msg, RPT_SEVERITY_ERROR );
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// Write the netlist file
|
||||
if( ( m_f = wxFopen( aOutFileName, wxT( "wt" ) ) ) == nullptr )
|
||||
{
|
||||
wxString msg = wxString::Format( _( "Failed to create file '%s'." ), aOutFileName );
|
||||
aReporter.Report( msg, RPT_SEVERITY_ERROR );
|
||||
return false;
|
||||
}
|
||||
|
||||
ret |= fprintf( m_f, "(Source: %s)\n", TO_UTF8( m_schematic->GetFileName() ) );
|
||||
ret |= fprintf( m_f, "(Date: %s)\n", TO_UTF8( DateAndTime() ) );
|
||||
|
||||
m_packageProperties.clear();
|
||||
m_componentGroups.clear();
|
||||
m_orderedSymbolsSheetpath.clear();
|
||||
m_netNameNodes.clear();
|
||||
|
||||
extractComponentsInfo();
|
||||
|
||||
// Start with package definitions, which we create from component groups.
|
||||
toAllegroPackages();
|
||||
|
||||
// Write out nets
|
||||
toAllegroNets();
|
||||
|
||||
// Write out package properties. NOTE: Allegro doesn't recognize much...
|
||||
toAllegroPackageProperties();
|
||||
|
||||
// Done with the netlist
|
||||
fclose( m_f );
|
||||
|
||||
m_f = nullptr;
|
||||
|
||||
return ret >= 0;
|
||||
}
|
||||
|
||||
|
||||
bool NETLIST_EXPORTER_ALLEGRO::CompareSymbolSheetpath(
|
||||
const std::pair<SCH_SYMBOL*, SCH_SHEET_PATH>& aItem1,
|
||||
const std::pair<SCH_SYMBOL*, SCH_SHEET_PATH>& aItem2 )
|
||||
{
|
||||
wxString refText1 = aItem1.first->GetRef( &aItem1.second );
|
||||
wxString refText2 = aItem2.first->GetRef( &aItem2.second );
|
||||
|
||||
if( refText1 == refText2 )
|
||||
{
|
||||
return aItem1.second.PathHumanReadable() < aItem2.second.PathHumanReadable();
|
||||
}
|
||||
|
||||
return CompareSymbolRef( refText1, refText2 );
|
||||
}
|
||||
|
||||
|
||||
bool NETLIST_EXPORTER_ALLEGRO::CompareSymbolRef( const wxString& aRefText1,
|
||||
const wxString& aRefText2 )
|
||||
{
|
||||
if( removeTailDigits( aRefText1 ) == removeTailDigits( aRefText2 ) )
|
||||
{
|
||||
return extractTailNumber( aRefText1 ) < extractTailNumber( aRefText2 );
|
||||
}
|
||||
|
||||
return aRefText1 < aRefText2;
|
||||
}
|
||||
|
||||
|
||||
bool NETLIST_EXPORTER_ALLEGRO::CompareLibPin( const LIB_PIN* aPin1, const LIB_PIN* aPin2 )
|
||||
{
|
||||
// return "lhs < rhs"
|
||||
return StrNumCmp( aPin1->GetShownNumber(), aPin2->GetShownNumber(), true ) < 0;
|
||||
}
|
||||
|
||||
|
||||
void NETLIST_EXPORTER_ALLEGRO::extractComponentsInfo()
|
||||
{
|
||||
m_referencesAlreadyFound.Clear();
|
||||
m_libParts.clear();
|
||||
|
||||
SCH_SHEET_LIST sheetList = m_schematic->GetSheets();
|
||||
|
||||
for( unsigned ii = 0; ii < sheetList.size(); ii++ )
|
||||
{
|
||||
SCH_SHEET_PATH sheet = sheetList[ii];
|
||||
m_schematic->SetCurrentSheet( sheet );
|
||||
|
||||
auto cmp = [sheet]( SCH_SYMBOL* a, SCH_SYMBOL* b )
|
||||
{
|
||||
return ( StrNumCmp( a->GetRef( &sheet, false ),
|
||||
b->GetRef( &sheet, false ), true ) < 0 );
|
||||
};
|
||||
|
||||
std::set<SCH_SYMBOL*, decltype( cmp )> ordered_symbols( cmp );
|
||||
std::multiset<SCH_SYMBOL*, decltype( cmp )> extra_units( cmp );
|
||||
|
||||
for( SCH_ITEM* item : sheet.LastScreen()->Items().OfType( SCH_SYMBOL_T ) )
|
||||
{
|
||||
SCH_SYMBOL* symbol = static_cast<SCH_SYMBOL*>( item );
|
||||
auto test = ordered_symbols.insert( symbol );
|
||||
|
||||
if( !test.second )
|
||||
{
|
||||
if( ( *( test.first ) )->m_Uuid > symbol->m_Uuid )
|
||||
{
|
||||
extra_units.insert( *( test.first ) );
|
||||
ordered_symbols.erase( test.first );
|
||||
ordered_symbols.insert( symbol );
|
||||
}
|
||||
else
|
||||
{
|
||||
extra_units.insert( symbol );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for( EDA_ITEM* item : ordered_symbols )
|
||||
{
|
||||
SCH_SYMBOL* symbol = findNextSymbol( item, &sheet );
|
||||
|
||||
if( !symbol || symbol->GetExcludedFromBoard() )
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
LIB_PINS pinList;
|
||||
pinList.clear();
|
||||
symbol->GetLibPins(pinList);
|
||||
|
||||
if( !pinList.size() )
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
m_packageProperties.insert(std::pair<wxString, wxString>(sheet.PathHumanReadable(), symbol->GetRef(&sheet)));
|
||||
m_orderedSymbolsSheetpath.push_back(std::pair<SCH_SYMBOL*, SCH_SHEET_PATH>(symbol, sheet));
|
||||
}
|
||||
}
|
||||
|
||||
wxString netCodeTxt;
|
||||
wxString netName;
|
||||
wxString ref;
|
||||
|
||||
struct NET_RECORD
|
||||
{
|
||||
NET_RECORD( const wxString& aName ) :
|
||||
m_Name( aName )
|
||||
{};
|
||||
|
||||
wxString m_Name;
|
||||
std::vector<NET_NODE> m_Nodes;
|
||||
};
|
||||
|
||||
std::vector<NET_RECORD*> nets;
|
||||
|
||||
for( const auto& it : m_schematic->ConnectionGraph()->GetNetMap() )
|
||||
{
|
||||
wxString net_name = it.first.Name;
|
||||
const std::vector<CONNECTION_SUBGRAPH*>& subgraphs = it.second;
|
||||
NET_RECORD* net_record = nullptr;
|
||||
|
||||
if( subgraphs.empty() )
|
||||
continue;
|
||||
|
||||
nets.emplace_back( new NET_RECORD( net_name ) );
|
||||
net_record = nets.back();
|
||||
|
||||
for( CONNECTION_SUBGRAPH* subgraph : subgraphs )
|
||||
{
|
||||
bool nc = subgraph->GetNoConnect() && subgraph->GetNoConnect()->Type() == SCH_NO_CONNECT_T;
|
||||
const SCH_SHEET_PATH& sheet = subgraph->GetSheet();
|
||||
|
||||
for( SCH_ITEM* item : subgraph->GetItems() )
|
||||
{
|
||||
if( item->Type() == SCH_PIN_T )
|
||||
{
|
||||
SCH_PIN* pin = static_cast<SCH_PIN*>( item );
|
||||
SCH_SYMBOL* symbol = pin->GetParentSymbol();
|
||||
|
||||
if( !symbol || symbol->GetExcludedFromBoard() )
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
net_record->m_Nodes.emplace_back( pin, sheet, nc );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Netlist ordering: Net name, then ref des, then pin name
|
||||
std::sort( nets.begin(), nets.end(),
|
||||
[]( const NET_RECORD* a, const NET_RECORD*b )
|
||||
{
|
||||
return StrNumCmp( a->m_Name, b->m_Name ) < 0;
|
||||
} );
|
||||
|
||||
for( int i = 0; i < (int) nets.size(); ++i )
|
||||
{
|
||||
NET_RECORD* net_record = nets[i];
|
||||
|
||||
// Netlist ordering: Net name, then ref des, then pin name
|
||||
std::sort( net_record->m_Nodes.begin(), net_record->m_Nodes.end(),
|
||||
[]( const NET_NODE& a, const NET_NODE& b )
|
||||
{
|
||||
wxString refA = a.m_Pin->GetParentSymbol()->GetRef( &a.m_Sheet );
|
||||
wxString refB = b.m_Pin->GetParentSymbol()->GetRef( &b.m_Sheet );
|
||||
|
||||
if( refA == refB )
|
||||
return a.m_Pin->GetShownNumber() < b.m_Pin->GetShownNumber();
|
||||
|
||||
return refA < refB;
|
||||
} );
|
||||
|
||||
// Some duplicates can exist, for example on multi-unit parts with duplicated pins across
|
||||
// units. If the user connects the pins on each unit, they will appear on separate
|
||||
// subgraphs. Remove those here:
|
||||
alg::remove_duplicates( net_record->m_Nodes,
|
||||
[]( const NET_NODE& a, const NET_NODE& b )
|
||||
{
|
||||
wxString refA = a.m_Pin->GetParentSymbol()->GetRef( &a.m_Sheet );
|
||||
wxString refB = b.m_Pin->GetParentSymbol()->GetRef( &b.m_Sheet );
|
||||
|
||||
return refA == refB && a.m_Pin->GetShownNumber() == b.m_Pin->GetShownNumber();
|
||||
} );
|
||||
|
||||
for( const NET_NODE& netNode : net_record->m_Nodes )
|
||||
{
|
||||
wxString refText = netNode.m_Pin->GetParentSymbol()->GetRef( &netNode.m_Sheet );
|
||||
wxString pinText = netNode.m_Pin->GetShownNumber();
|
||||
|
||||
// Skip power symbols and virtual symbols
|
||||
if( refText[0] == wxChar( '#' ) )
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
m_netNameNodes.insert( std::pair<wxString, NET_NODE>( net_record->m_Name, netNode ) );
|
||||
}
|
||||
}
|
||||
|
||||
for( NET_RECORD* record : nets )
|
||||
delete record;
|
||||
}
|
||||
|
||||
|
||||
void NETLIST_EXPORTER_ALLEGRO::toAllegroPackages()
|
||||
{
|
||||
int ret = 0; // zero now, OR in the sign bit on error
|
||||
int groupCount = 1;
|
||||
wxString deviceFileCreatingError = wxString( "" );
|
||||
|
||||
//Group the components......
|
||||
while(!m_orderedSymbolsSheetpath.empty())
|
||||
{
|
||||
std::pair<SCH_SYMBOL*, SCH_SHEET_PATH> first_ele = m_orderedSymbolsSheetpath.front();
|
||||
m_orderedSymbolsSheetpath.pop_front();
|
||||
m_componentGroups.insert(
|
||||
std::pair<int, std::pair<SCH_SYMBOL*, SCH_SHEET_PATH>>( groupCount, first_ele ) );
|
||||
|
||||
for( auto it = m_orderedSymbolsSheetpath.begin(); it != m_orderedSymbolsSheetpath.end();
|
||||
++it )
|
||||
{
|
||||
if( it->first->GetValueFieldText( false, &it->second, false )
|
||||
!= first_ele.first->GetValueFieldText( false, &first_ele.second, false ) )
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if( it->first->GetFootprintFieldText( false, &it->second, false )
|
||||
!= first_ele.first->GetFootprintFieldText( false, &first_ele.second, false ) )
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
wxString ref1 = it->first->GetRef( &it->second );
|
||||
wxString ref2 = first_ele.first->GetRef( &first_ele.second );
|
||||
if( removeTailDigits( ref1 ) == removeTailDigits( ref2 ) )
|
||||
{
|
||||
m_componentGroups.insert( std::pair<int, std::pair<SCH_SYMBOL*, SCH_SHEET_PATH>>(
|
||||
groupCount, ( *it ) ) );
|
||||
it = m_orderedSymbolsSheetpath.erase( it );
|
||||
if( std::distance( it, m_orderedSymbolsSheetpath.begin() ) > 0 )
|
||||
it--;
|
||||
else if( it == m_orderedSymbolsSheetpath.end() )
|
||||
break;
|
||||
}
|
||||
}
|
||||
groupCount++;
|
||||
}
|
||||
|
||||
ret |= fprintf( m_f, "%s\n", "$PACKAGES" );
|
||||
|
||||
struct COMP_PACKAGE_STRUCT
|
||||
{
|
||||
wxString m_value;
|
||||
wxString m_tolerance;
|
||||
std::vector<std::pair<SCH_SYMBOL*, SCH_SHEET_PATH>> m_symbolSheetpaths;
|
||||
};
|
||||
|
||||
COMP_PACKAGE_STRUCT compPackageStruct;
|
||||
std::map<wxString, COMP_PACKAGE_STRUCT> compPackageMap;
|
||||
|
||||
for( int groupIndex = 1; groupIndex < groupCount; groupIndex++ )
|
||||
{
|
||||
auto pairIter = m_componentGroups.equal_range(groupIndex);
|
||||
auto beginIter = pairIter.first;
|
||||
auto endIter = pairIter.second;
|
||||
|
||||
SCH_SYMBOL* sym = (beginIter->second).first;
|
||||
SCH_SHEET_PATH sheetPath = (beginIter->second).second;
|
||||
|
||||
wxString valueText = sym->GetValueFieldText( false, &sheetPath, false );
|
||||
wxString footprintText = sym->GetFootprintFieldText( false, &sheetPath, false);
|
||||
wxString deviceType = valueText + wxString("_") + footprintText;
|
||||
|
||||
while( deviceType.GetChar(deviceType.Length()-1) == '_' )
|
||||
{
|
||||
deviceType.RemoveLast();
|
||||
}
|
||||
|
||||
deviceType = formatDevice( deviceType );
|
||||
|
||||
wxArrayString fieldArray;
|
||||
fieldArray.Add("Spice_Model");
|
||||
fieldArray.Add("VALUE");
|
||||
|
||||
wxString value = getGroupField( groupIndex, fieldArray );
|
||||
|
||||
fieldArray.clear();
|
||||
fieldArray.Add("TOLERANCE");
|
||||
fieldArray.Add("TOL");
|
||||
wxString tol = getGroupField( groupIndex, fieldArray );
|
||||
|
||||
std::vector<std::pair<SCH_SYMBOL*, SCH_SHEET_PATH>> symbolSheetpaths;
|
||||
|
||||
for( auto iter = beginIter; iter != endIter; iter++ )
|
||||
{
|
||||
symbolSheetpaths.push_back( std::pair<SCH_SYMBOL*, SCH_SHEET_PATH>(
|
||||
iter->second.first, iter->second.second ) );
|
||||
}
|
||||
|
||||
std::stable_sort( symbolSheetpaths.begin(), symbolSheetpaths.end(),
|
||||
NETLIST_EXPORTER_ALLEGRO::CompareSymbolSheetpath );
|
||||
|
||||
compPackageStruct.m_value = value;
|
||||
compPackageStruct.m_tolerance = tol;
|
||||
compPackageStruct.m_symbolSheetpaths = symbolSheetpaths;
|
||||
compPackageMap.insert( std::pair( deviceType, compPackageStruct ) );
|
||||
|
||||
// Write out the corresponding device file
|
||||
FILE* d = nullptr;
|
||||
wxString deviceFileName = wxFileName(m_exportPath, deviceType, wxString("txt")).GetFullPath();
|
||||
if( ( d = wxFopen( deviceFileName, wxT( "wt" ) ) ) == nullptr )
|
||||
{
|
||||
wxString msg;
|
||||
msg.Printf( _( "Failed to create file '%s'.\n" ), deviceFileName );
|
||||
deviceFileCreatingError += msg;
|
||||
continue;
|
||||
}
|
||||
|
||||
footprintText = footprintText.AfterLast( ':' );
|
||||
|
||||
wxArrayString footprintAlt;
|
||||
wxArrayString footprintArray = sym->GetLibSymbolRef()->GetFPFilters();
|
||||
|
||||
for( auto fp : footprintArray )
|
||||
{
|
||||
if( ( fp.Find( '*' ) != wxNOT_FOUND ) || ( fp.Find( '?' ) != wxNOT_FOUND ) )
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
footprintAlt.Add( fp.AfterLast( ':' ) );
|
||||
}
|
||||
|
||||
if( footprintText.IsEmpty() )
|
||||
{
|
||||
if( !footprintAlt.IsEmpty() )
|
||||
{
|
||||
footprintText = footprintAlt[0];
|
||||
footprintAlt.RemoveAt( 0 );
|
||||
}
|
||||
else
|
||||
{
|
||||
footprintText = deviceType;
|
||||
}
|
||||
}
|
||||
|
||||
fprintf( d, "PACKAGE '%s'\n", TO_UTF8( formatDevice( footprintText ) ) );
|
||||
fprintf( d, "CLASS IC\n" );
|
||||
|
||||
LIB_PINS pinList;
|
||||
sym->GetLibSymbolRef()->GetPins( pinList, 0, 0 );
|
||||
|
||||
/*
|
||||
* We must erase redundant Pins references in pinList
|
||||
* These redundant pins exist because some pins are found more than one time when a
|
||||
* symbol has multiple parts per package or has 2 representations (DeMorgan conversion).
|
||||
* For instance, a 74ls00 has DeMorgan conversion, with different pin shapes, and
|
||||
* therefore each pin appears 2 times in the list. Common pins (VCC, GND) can also be
|
||||
* found more than once.
|
||||
*/
|
||||
sort( pinList.begin(), pinList.end(), NETLIST_EXPORTER_ALLEGRO::CompareLibPin );
|
||||
for( int ii = 0; ii < (int) pinList.size() - 1; ii++ )
|
||||
{
|
||||
if( pinList[ii]->GetNumber() == pinList[ii + 1]->GetNumber() )
|
||||
{ // 2 pins have the same number, remove the redundant pin at index i+1
|
||||
pinList.erase( pinList.begin() + ii + 1 );
|
||||
ii--;
|
||||
}
|
||||
}
|
||||
|
||||
unsigned int pinCount = pinList.size();
|
||||
fprintf( d, "PINCOUNT %u\n", pinCount );
|
||||
|
||||
if( pinCount > 0 )
|
||||
{
|
||||
fprintf( d, "%s", TO_UTF8( formatFunction( "main", pinList ) ) );
|
||||
}
|
||||
|
||||
if( !value.IsEmpty() )
|
||||
{
|
||||
fprintf( d, "PACKAGEPROP VALUE %s\n", TO_UTF8( value ) );
|
||||
}
|
||||
|
||||
if( !tol.IsEmpty() )
|
||||
{
|
||||
fprintf( d, "PACKAGEPROP TOL %s\n", TO_UTF8( tol ) );
|
||||
}
|
||||
|
||||
if( !footprintAlt.IsEmpty() )
|
||||
{
|
||||
fprintf( d, "PACKAGEPROP ALT_SYMBOLS '(" );
|
||||
|
||||
wxString footprintAltSymbolsText;
|
||||
for( auto fp : footprintAlt )
|
||||
{
|
||||
footprintAltSymbolsText += fp + wxString( "," );
|
||||
}
|
||||
footprintAltSymbolsText.Truncate( footprintAltSymbolsText.Length() - 1 );
|
||||
fprintf( d, "%s)'\n", TO_UTF8( footprintAltSymbolsText ) );
|
||||
}
|
||||
|
||||
wxArrayString propArray;
|
||||
propArray.Add( "PART_NUMBER" );
|
||||
propArray.Add( "mpn" );
|
||||
propArray.Add( "mfr_pn" );
|
||||
wxString data = getGroupField( groupIndex, propArray );
|
||||
if(!data.IsEmpty())
|
||||
{
|
||||
fprintf( d, "PACKAGEPROP %s %s\n", TO_UTF8( propArray[0] ), TO_UTF8( data ) );
|
||||
}
|
||||
|
||||
propArray.clear();
|
||||
propArray.Add( "HEIGHT" );
|
||||
data = getGroupField( groupIndex, propArray );
|
||||
if(!data.IsEmpty())
|
||||
{
|
||||
fprintf( d, "PACKAGEPROP %s %s\n", TO_UTF8( propArray[0] ), TO_UTF8( data ) );
|
||||
}
|
||||
|
||||
fprintf( d, "END\n" );
|
||||
|
||||
fclose( d );
|
||||
}
|
||||
|
||||
for( auto iter = compPackageMap.begin(); iter != compPackageMap.end(); iter++ )
|
||||
{
|
||||
wxString deviceType = iter->first;
|
||||
wxString value = iter->second.m_value;
|
||||
wxString tolerance = iter->second.m_tolerance;
|
||||
|
||||
if( value.IsEmpty() && tolerance.IsEmpty() )
|
||||
{
|
||||
ret |= fprintf( m_f, "!%s;", TO_UTF8( deviceType ) );
|
||||
}
|
||||
else if( tolerance.IsEmpty() )
|
||||
{
|
||||
ret |= fprintf( m_f, "!%s!%s;", TO_UTF8( deviceType ), TO_UTF8( value ) );
|
||||
}
|
||||
else
|
||||
{
|
||||
ret |= fprintf( m_f, "!%s!%s!%s;", TO_UTF8( deviceType ), TO_UTF8( value ),
|
||||
TO_UTF8( tolerance ) );
|
||||
}
|
||||
|
||||
std::vector<std::pair<SCH_SYMBOL*, SCH_SHEET_PATH>> symbolSheetpaths =
|
||||
iter->second.m_symbolSheetpaths;
|
||||
|
||||
for( auto it = symbolSheetpaths.begin(); it != symbolSheetpaths.end(); it++ )
|
||||
{
|
||||
SCH_SYMBOL* sym = it->first;
|
||||
SCH_SHEET_PATH sheetPath = it->second;
|
||||
wxString refText = sym->GetRef( &sheetPath );
|
||||
ret |= fprintf( m_f, ",\n\t%s", TO_UTF8( refText ) );
|
||||
}
|
||||
ret |= fprintf( m_f, "\n" );
|
||||
}
|
||||
|
||||
if( !deviceFileCreatingError.IsEmpty() )
|
||||
{
|
||||
DisplayError( nullptr, deviceFileCreatingError );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
wxString NETLIST_EXPORTER_ALLEGRO::formatText( wxString aString )
|
||||
{
|
||||
if( aString.IsEmpty() )
|
||||
{
|
||||
return wxString( "" );
|
||||
}
|
||||
|
||||
aString.Replace( "\u03BC", "u" );
|
||||
|
||||
std::regex reg( "[!']|[^ -~]" );
|
||||
wxString processedString = wxString( std::regex_replace( std::string( aString ), reg, "?" ) );
|
||||
|
||||
std::regex search_reg( "[^a-zA-Z0-9_/]" );
|
||||
if( std::regex_search( std::string( processedString ), search_reg ) )
|
||||
{
|
||||
return wxString( "'" ) + processedString + wxString( "'" );
|
||||
}
|
||||
|
||||
return processedString;
|
||||
}
|
||||
|
||||
|
||||
wxString NETLIST_EXPORTER_ALLEGRO::formatPin( const LIB_PIN& aPin )
|
||||
{
|
||||
wxString pinName4Telesis = aPin.GetName() + wxString( "__" ) + aPin.GetNumber();
|
||||
std::regex reg( "[^A-Za-z0-9_+?/-]" );
|
||||
return wxString( std::regex_replace( std::string( pinName4Telesis ), reg, "?" ) );
|
||||
}
|
||||
|
||||
|
||||
wxString NETLIST_EXPORTER_ALLEGRO::formatFunction( wxString aName, LIB_PINS aPinList )
|
||||
{
|
||||
aName.MakeUpper();
|
||||
std::list<wxString> pinNameList;
|
||||
|
||||
std::stable_sort( aPinList.begin(), aPinList.end(), NETLIST_EXPORTER_ALLEGRO::CompareLibPin );
|
||||
|
||||
for( auto pin : aPinList )
|
||||
{
|
||||
pinNameList.push_back( formatPin( *pin ) );
|
||||
}
|
||||
|
||||
wxString out_str = "";
|
||||
wxString str;
|
||||
|
||||
out_str.Printf( wxT( "PINORDER %s " ), TO_UTF8( aName ) );
|
||||
|
||||
for( auto pinName : pinNameList )
|
||||
{
|
||||
str.Printf( ",\n\t%s", TO_UTF8( pinName ) );
|
||||
out_str += str;
|
||||
}
|
||||
out_str += wxString( "\n" );
|
||||
|
||||
str.Printf( wxT( "FUNCTION %s %s " ), TO_UTF8( aName ), TO_UTF8( aName ) );
|
||||
out_str += str;
|
||||
|
||||
for( auto pin : aPinList )
|
||||
{
|
||||
str.Printf( ",\n\t%s", TO_UTF8( pin->GetNumber() ) );
|
||||
out_str += str;
|
||||
}
|
||||
out_str += wxString( "\n" );
|
||||
|
||||
return out_str;
|
||||
}
|
||||
|
||||
|
||||
wxString NETLIST_EXPORTER_ALLEGRO::getGroupField( int aGroupIndex, const wxArrayString& aFieldArray,
|
||||
bool aSanitize )
|
||||
{
|
||||
auto pairIter = m_componentGroups.equal_range( aGroupIndex );
|
||||
|
||||
for( auto iter = pairIter.first; iter != pairIter.second; ++iter )
|
||||
{
|
||||
SCH_SYMBOL* sym = ( iter->second ).first;
|
||||
SCH_SHEET_PATH sheetPath = ( iter->second ).second;
|
||||
|
||||
for( auto field : aFieldArray )
|
||||
{
|
||||
SCH_FIELD* fld = sym->FindField( field, true, true );
|
||||
if( fld != NULL )
|
||||
{
|
||||
wxString fieldText = fld->GetShownText( &sheetPath, true );
|
||||
if( !fieldText.IsEmpty() )
|
||||
{
|
||||
if( aSanitize )
|
||||
{
|
||||
return formatText( fieldText );
|
||||
}
|
||||
else
|
||||
{
|
||||
return fieldText;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for( auto iter = pairIter.first; iter != pairIter.second; ++iter )
|
||||
{
|
||||
SCH_SYMBOL* sym = ( iter->second ).first;
|
||||
SCH_SHEET_PATH sheetPath = ( iter->second ).second;
|
||||
|
||||
for( auto field : aFieldArray )
|
||||
{
|
||||
LIB_FIELD* fld = sym->GetLibSymbolRef()->FindField( field, true );
|
||||
if( fld != NULL )
|
||||
{
|
||||
wxString fieldText = fld->GetShownText( &sheetPath, true );
|
||||
if( !fieldText.IsEmpty() )
|
||||
{
|
||||
if( aSanitize )
|
||||
{
|
||||
return formatText( fieldText );
|
||||
}
|
||||
else
|
||||
{
|
||||
return fieldText;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return wxString( "" );
|
||||
}
|
||||
|
||||
wxString NETLIST_EXPORTER_ALLEGRO::formatDevice( wxString aString )
|
||||
{
|
||||
aString.MakeLower();
|
||||
std::regex reg( "[^a-z0-9_-]" );
|
||||
return wxString( std::regex_replace( std::string( aString ), reg, "_" ) );
|
||||
}
|
||||
|
||||
void NETLIST_EXPORTER_ALLEGRO::toAllegroPackageProperties()
|
||||
{
|
||||
int ret = 0; // zero now, OR in the sign bit on error
|
||||
|
||||
ret |= fprintf( m_f, "%s\n", "$PACKAGES" );
|
||||
ret |= fprintf( m_f, "%s\n", "$A_PROPERTIES" );
|
||||
|
||||
while( !m_packageProperties.empty() )
|
||||
{
|
||||
std::multimap<wxString, wxString>::iterator iter = m_packageProperties.begin();
|
||||
wxString sheetPathText = iter->first;
|
||||
|
||||
ret |= fprintf( m_f, "ROOM %s;", TO_UTF8( formatText( sheetPathText ) ) );
|
||||
|
||||
std::vector<wxString> refTexts;
|
||||
|
||||
auto pairIter = m_packageProperties.equal_range( sheetPathText );
|
||||
for( iter = pairIter.first; iter != pairIter.second; ++iter )
|
||||
{
|
||||
wxString refText = iter->second;
|
||||
refTexts.push_back( refText );
|
||||
}
|
||||
m_packageProperties.erase( pairIter.first, pairIter.second );
|
||||
|
||||
std::stable_sort( refTexts.begin(), refTexts.end(),
|
||||
NETLIST_EXPORTER_ALLEGRO::CompareSymbolRef );
|
||||
|
||||
for( auto it = refTexts.begin(); it != refTexts.end(); it++ )
|
||||
{
|
||||
ret |= fprintf( m_f, ",\n\t%s", TO_UTF8( *it ) );
|
||||
}
|
||||
ret |= fprintf( m_f, "\n" );
|
||||
}
|
||||
}
|
||||
|
||||
void NETLIST_EXPORTER_ALLEGRO::toAllegroNets()
|
||||
{
|
||||
int ret = 0; // zero now, OR in the sign bit on error
|
||||
|
||||
ret |= fprintf( m_f, "%s\n", "$NETS" );
|
||||
|
||||
while( !m_netNameNodes.empty() )
|
||||
{
|
||||
std::multimap<wxString, NET_NODE>::iterator iter = m_netNameNodes.begin();
|
||||
std::vector<NET_NODE> netNodes;
|
||||
|
||||
wxString netName = iter->first;
|
||||
|
||||
ret |= fprintf( m_f, "%s;", TO_UTF8( formatText( netName ).MakeUpper() ) );
|
||||
|
||||
auto pairIter = m_netNameNodes.equal_range( netName );
|
||||
for( iter = pairIter.first; iter != pairIter.second; ++iter )
|
||||
{
|
||||
NET_NODE netNode = iter->second;
|
||||
netNodes.push_back( netNode );
|
||||
}
|
||||
m_netNameNodes.erase( pairIter.first, pairIter.second );
|
||||
|
||||
std::stable_sort( netNodes.begin(), netNodes.end() );
|
||||
|
||||
for( auto it = netNodes.begin(); it != netNodes.end(); it++ )
|
||||
{
|
||||
NET_NODE netNode = *it;
|
||||
wxString refText = netNode.m_Pin->GetParentSymbol()->GetRef( &netNode.m_Sheet );
|
||||
wxString pinText = netNode.m_Pin->GetShownNumber();
|
||||
ret |= fprintf( m_f, ",\n\t%s.%s", TO_UTF8( refText ), TO_UTF8( pinText ) );
|
||||
}
|
||||
ret |= fprintf( m_f, "\n" );
|
||||
}
|
||||
}
|
||||
|
||||
wxString NETLIST_EXPORTER_ALLEGRO::removeTailDigits( wxString aString )
|
||||
{
|
||||
while( ( aString.GetChar( aString.Length() - 1 ) >= '0' )
|
||||
&& ( aString.GetChar( aString.Length() - 1 ) <= '9' ) )
|
||||
{
|
||||
aString.RemoveLast();
|
||||
}
|
||||
return aString;
|
||||
}
|
||||
|
||||
unsigned int NETLIST_EXPORTER_ALLEGRO::extractTailNumber( wxString aString )
|
||||
{
|
||||
wxString numString;
|
||||
while( ( aString.GetChar( aString.Length() - 1 ) >= '0' )
|
||||
&& ( aString.GetChar( aString.Length() - 1 ) <= '9' ) )
|
||||
{
|
||||
numString.insert( 0, aString.GetChar( aString.Length() - 1 ) );
|
||||
aString.RemoveLast();
|
||||
}
|
||||
|
||||
unsigned long val;
|
||||
//From wxWidgets 3.1.6, here we can use ToUInt instead of ToULong function.
|
||||
numString.ToULong( &val );
|
||||
return (unsigned int) val;
|
||||
}
|
|
@ -0,0 +1,215 @@
|
|||
/*
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 1992-2013 jp.charras at wanadoo.fr
|
||||
* Copyright (C) 2013 SoftPLC Corporation, Dick Hollenbeck <dick@softplc.com>
|
||||
* Copyright (C) 1992-2021 KiCad Developers, see AUTHORS.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
|
||||
*/
|
||||
|
||||
#ifndef NETLIST_EXPORTER_ALLEGRO_H
|
||||
#define NETLIST_EXPORTER_ALLEGRO_H
|
||||
|
||||
#include "netlist_exporter_base.h"
|
||||
|
||||
/**
|
||||
* Generate a netlist compatible with Allegro.
|
||||
*/
|
||||
class NETLIST_EXPORTER_ALLEGRO : public NETLIST_EXPORTER_BASE
|
||||
{
|
||||
public:
|
||||
NETLIST_EXPORTER_ALLEGRO( SCHEMATIC* aSchematic ) :
|
||||
NETLIST_EXPORTER_BASE( aSchematic )
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* Write netlist to \a aOutFileName.
|
||||
* Generate the Allegro netlist format supported by Allegro.
|
||||
*/
|
||||
bool WriteNetlist( const wxString& aOutFileName, unsigned aNetlistOptions,
|
||||
REPORTER& aReporter ) override;
|
||||
|
||||
/**
|
||||
* Compare two std::pair<SCH_SYMBOL*, SCH_SHEET_PATH> variables.
|
||||
*
|
||||
* @param aItem1 comparing object 1
|
||||
* @param aItem2 comparing object 2
|
||||
* @return true if aItem1 < aItem2
|
||||
*/
|
||||
static bool CompareSymbolSheetpath( const std::pair<SCH_SYMBOL*, SCH_SHEET_PATH>& aItem1,
|
||||
const std::pair<SCH_SYMBOL*, SCH_SHEET_PATH>& aItem2 );
|
||||
|
||||
/**
|
||||
* Compare two wxString variables.
|
||||
*
|
||||
* @param aRefText1
|
||||
* @param aRefText2
|
||||
* @return bool value
|
||||
*/
|
||||
static bool CompareSymbolRef( const wxString& aRefText1, const wxString& aRefText2 );
|
||||
|
||||
/**
|
||||
* Compare two LIB_PIN* variables.
|
||||
*
|
||||
* @param aPin1
|
||||
* @param aPin2
|
||||
* @return bool value
|
||||
*/
|
||||
static bool CompareLibPin( const LIB_PIN* aPin1, const LIB_PIN* aPin2 );
|
||||
|
||||
private:
|
||||
void extractComponentsInfo();
|
||||
|
||||
/**
|
||||
* Write the $PACKAGES section
|
||||
*
|
||||
*/
|
||||
void toAllegroPackages();
|
||||
|
||||
/**
|
||||
* Write the $NETS section
|
||||
*
|
||||
*/
|
||||
void toAllegroNets();
|
||||
|
||||
/**
|
||||
* Write $A_PROPERTIES section
|
||||
*
|
||||
*/
|
||||
void toAllegroPackageProperties();
|
||||
|
||||
/**
|
||||
* Converts a string into one safe for a Telesis device name.
|
||||
* These are all lowercase and have a more restricted set of characters.
|
||||
* FIXME: replace unsupported characters with an encoding instead
|
||||
*
|
||||
* @param aString wxString to be formatted.
|
||||
* @return a formatted wxString.
|
||||
*/
|
||||
wxString formatDevice( wxString aString );
|
||||
|
||||
/**
|
||||
* Convert a string into Telesis-safe format. Unsupported characters are
|
||||
* replaced with ?'s, and the string is quoted if necessary.
|
||||
* FIXME: replace unsupported characters with an encoding instead, to avoid
|
||||
* having similar strings mapped to each other.
|
||||
*
|
||||
* @param aString
|
||||
* @return wxString
|
||||
*/
|
||||
wxString formatText( wxString aString );
|
||||
|
||||
/**
|
||||
* Generates a Telesis-compatible pin name from a pin node.
|
||||
* Telesis requires all pin names to be unique, and doesn't have separate
|
||||
* fields for pin number and pin name/function, so we combine them together to
|
||||
* make a unique name that still describes its function if you check pin info.
|
||||
* FIXME: replace unsupported characters with an encoding instead
|
||||
*
|
||||
* @param aPin
|
||||
* @return wxString
|
||||
*/
|
||||
wxString formatPin( const LIB_PIN& aPin );
|
||||
|
||||
/**
|
||||
* Generates the definition of a function in Telesis format, which consists of
|
||||
* multiple declarations (PINORDER, PINSWAP, and FUNCTIONs).
|
||||
*
|
||||
* @param aName
|
||||
* @param aPinList
|
||||
* @return wxString
|
||||
*/
|
||||
wxString formatFunction( wxString aName, LIB_PINS aPinList );
|
||||
|
||||
/**
|
||||
* Look up a field for a component group, which may have mismatched case, or
|
||||
* the component group may not have the field defined and instead the library
|
||||
* entry has to be searched. Returns None if no fields exist.
|
||||
*
|
||||
* @param aGroupIndex the component group index to query
|
||||
* @param aFieldArray one or more (equivalent) fields to query, in the order specified.
|
||||
* first field that exists is returned.
|
||||
* @param aSanitize if true (default), will format/escape the field for Telesis output
|
||||
* @return return the found field, or return wxString("") if no field exist.
|
||||
*/
|
||||
wxString getGroupField( int aGroupIndex, const wxArrayString& aFieldArray,
|
||||
bool aSanitize = true );
|
||||
|
||||
/**
|
||||
* Remove the str's tailing digits.
|
||||
*
|
||||
* @param aString
|
||||
* @return wxString
|
||||
*/
|
||||
static wxString removeTailDigits( wxString aString );
|
||||
|
||||
/**
|
||||
* Extract the str's tailing number.
|
||||
*
|
||||
* @param aString
|
||||
* @return unsigned int
|
||||
*/
|
||||
static unsigned int extractTailNumber( wxString aString );
|
||||
|
||||
struct NET_NODE
|
||||
{
|
||||
NET_NODE( SCH_PIN* aPin, const SCH_SHEET_PATH& aSheet, bool aNoConnect ) :
|
||||
m_Pin( aPin ),
|
||||
m_Sheet( aSheet ),
|
||||
m_NoConnect( aNoConnect )
|
||||
{}
|
||||
|
||||
bool operator<( const NET_NODE& aNetNode ) const
|
||||
{
|
||||
wxString refText1 = m_Pin->GetParentSymbol()->GetRef( &m_Sheet );
|
||||
wxString refText2 = aNetNode.m_Pin->GetParentSymbol()->GetRef( &aNetNode.m_Sheet );
|
||||
if( refText1 == refText2 )
|
||||
{
|
||||
unsigned long val1, val2;
|
||||
//From wxWidgets 3.1.6, the function ToULong can be repalced with ToUInt
|
||||
bool convertingResult = m_Pin->GetShownNumber().ToULong( &val1 );
|
||||
convertingResult &= aNetNode.m_Pin->GetShownNumber().ToULong( &val2 );
|
||||
if( convertingResult )
|
||||
{
|
||||
return val1 < val2;
|
||||
}
|
||||
else
|
||||
{
|
||||
return m_Pin->GetShownNumber() < aNetNode.m_Pin->GetShownNumber();
|
||||
}
|
||||
}
|
||||
return CompareSymbolRef( refText1, refText2 );
|
||||
}
|
||||
|
||||
SCH_PIN* m_Pin;
|
||||
SCH_SHEET_PATH m_Sheet;
|
||||
bool m_NoConnect;
|
||||
};
|
||||
|
||||
FILE* m_f; ///< file pointer for netlist file writing operation
|
||||
wxString m_exportPath; ///< directory to store device files
|
||||
std::multimap<wxString, wxString> m_packageProperties;
|
||||
std::multimap<int, std::pair<SCH_SYMBOL*, SCH_SHEET_PATH> > m_componentGroups; ///< Store the component group
|
||||
std::list<std::pair<SCH_SYMBOL*, SCH_SHEET_PATH>>
|
||||
m_orderedSymbolsSheetpath; ///< Store the ordered symbols with sheetpath
|
||||
std::multimap<wxString, NET_NODE> m_netNameNodes; ///< Store the NET_NODE with the net name
|
||||
};
|
||||
|
||||
#endif
|
|
@ -41,6 +41,7 @@
|
|||
#include <netlist_exporter_spice.h>
|
||||
#include <netlist_exporter_spice_model.h>
|
||||
#include <netlist_exporter_kicad.h>
|
||||
#include <netlist_exporter_allegro.h>
|
||||
#include <netlist_exporter_xml.h>
|
||||
|
||||
|
||||
|
@ -88,6 +89,10 @@ bool SCH_EDIT_FRAME::WriteNetListFile( int aFormat, const wxString& aFullFileNam
|
|||
helper = new NETLIST_EXPORTER_SPICE_MODEL( sch );
|
||||
break;
|
||||
|
||||
case NET_TYPE_ALLEGRO:
|
||||
helper = new NETLIST_EXPORTER_ALLEGRO( sch );
|
||||
break;
|
||||
|
||||
case NET_TYPE_BOM:
|
||||
// When generating the BOM, we have a bare filename so don't strip
|
||||
// the extension or you might string a '.' from the middle of the filename
|
||||
|
|
|
@ -953,15 +953,24 @@ void SCH_SYMBOL::RemoveField( const wxString& aFieldName )
|
|||
}
|
||||
|
||||
|
||||
SCH_FIELD* SCH_SYMBOL::FindField( const wxString& aFieldName, bool aIncludeDefaultFields )
|
||||
SCH_FIELD* SCH_SYMBOL::FindField( const wxString& aFieldName, bool aIncludeDefaultFields,
|
||||
bool aCaseInsensitive )
|
||||
{
|
||||
unsigned start = aIncludeDefaultFields ? 0 : MANDATORY_FIELDS;
|
||||
|
||||
for( unsigned i = start; i < m_fields.size(); ++i )
|
||||
{
|
||||
if( aCaseInsensitive )
|
||||
{
|
||||
if( aFieldName.Upper() == m_fields[i].GetName( false ).Upper() )
|
||||
return &m_fields[i];
|
||||
}
|
||||
else
|
||||
{
|
||||
if( aFieldName == m_fields[i].GetName( false ) )
|
||||
return &m_fields[i];
|
||||
}
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
|
|
@ -458,10 +458,12 @@ public:
|
|||
*
|
||||
* @param aFieldName is the name of the field to find.
|
||||
* @param aIncludeDefaultFields searches the library symbol default fields if true.
|
||||
* @param aCaseInsensitive ignore the filed name case if true.
|
||||
*
|
||||
* @return the field if found or NULL if the field was not found.
|
||||
*/
|
||||
SCH_FIELD* FindField( const wxString& aFieldName, bool aIncludeDefaultFields = true );
|
||||
SCH_FIELD* FindField( const wxString& aFieldName, bool aIncludeDefaultFields = true,
|
||||
bool aCaseInsensitive = false );
|
||||
|
||||
const wxString GetValueFieldText( bool aResolve, const SCH_SHEET_PATH* aPath,
|
||||
bool aAllowExtraText ) const;
|
||||
|
|
|
@ -128,6 +128,7 @@ extern const std::string SpiceFileExtension;
|
|||
extern const std::string CadstarNetlistFileExtension;
|
||||
extern const std::string OrCadPcb2NetlistFileExtension;
|
||||
extern const std::string NetlistFileExtension;
|
||||
extern const std::string AllegroNetlistFileExtension;
|
||||
extern const std::string GerberFileExtension;
|
||||
extern const std::string GerberJobFileExtension;
|
||||
extern const std::string HtmlFileExtension;
|
||||
|
@ -211,6 +212,7 @@ extern wxString LegacySchematicFileWildcard();
|
|||
extern wxString BoardFileWildcard();
|
||||
extern wxString OrCadPcb2NetlistFileWildcard();
|
||||
extern wxString NetlistFileWildcard();
|
||||
extern wxString AllegroNetlistFileWildcard();
|
||||
extern wxString HtmlFileWildcard();
|
||||
extern wxString CsvFileWildcard();
|
||||
extern wxString LegacyPcbFileWildcard();
|
||||
|
|
Loading…
Reference in New Issue