Add PADS netlist format export

This commit is contained in:
Marek Roszko 2024-03-09 09:57:24 -05:00
parent c5a02fc266
commit cb01bca1f4
8 changed files with 293 additions and 1 deletions

View File

@ -145,6 +145,7 @@ const std::string FILEEXT::CadstarNetlistFileExtension( "frp" );
const std::string FILEEXT::OrCadPcb2NetlistFileExtension( "net" ); const std::string FILEEXT::OrCadPcb2NetlistFileExtension( "net" );
const std::string FILEEXT::NetlistFileExtension( "net" ); const std::string FILEEXT::NetlistFileExtension( "net" );
const std::string FILEEXT::AllegroNetlistFileExtension( "txt" ); const std::string FILEEXT::AllegroNetlistFileExtension( "txt" );
const std::string FILEEXT::PADSNetlistFileExtension( "asc" );
const std::string FILEEXT::FootprintAssignmentFileExtension( "cmp" ); const std::string FILEEXT::FootprintAssignmentFileExtension( "cmp" );
const std::string FILEEXT::GerberFileExtension( "gbr" ); const std::string FILEEXT::GerberFileExtension( "gbr" );
const std::string FILEEXT::GerberJobFileExtension( "gbrjob" ); const std::string FILEEXT::GerberJobFileExtension( "gbrjob" );
@ -293,6 +294,12 @@ wxString FILEEXT::AllegroNetlistFileWildcard()
} }
wxString FILEEXT::PADSNetlistFileWildcard()
{
return _( "PADS netlist files" ) + AddFileExtListToFilter( { PADSNetlistFileExtension } );
}
wxString FILEEXT::EasyEdaArchiveWildcard() wxString FILEEXT::EasyEdaArchiveWildcard()
{ {
return _( "EasyEDA (JLCEDA) Std backup archive" ) + AddFileExtListToFilter( { "zip" } ); return _( "EasyEDA (JLCEDA) Std backup archive" ) + AddFileExtListToFilter( { "zip" } );

View File

@ -424,6 +424,7 @@ set( EESCHEMA_SRCS
netlist_exporters/netlist_exporter_base.cpp netlist_exporters/netlist_exporter_base.cpp
netlist_exporters/netlist_exporter_cadstar.cpp netlist_exporters/netlist_exporter_cadstar.cpp
netlist_exporters/netlist_exporter_kicad.cpp netlist_exporters/netlist_exporter_kicad.cpp
netlist_exporters/netlist_exporter_pads.cpp
netlist_exporters/netlist_exporter_orcadpcb2.cpp netlist_exporters/netlist_exporter_orcadpcb2.cpp
netlist_exporters/netlist_exporter_spice.cpp netlist_exporters/netlist_exporter_spice.cpp
netlist_exporters/netlist_exporter_spice_model.cpp netlist_exporters/netlist_exporter_spice_model.cpp

View File

@ -70,6 +70,7 @@ enum PANEL_NETLIST_INDEX
PANELORCADPCB2, /* Handle Netlist format OracdPcb2 */ PANELORCADPCB2, /* Handle Netlist format OracdPcb2 */
PANELALLEGRO, /* Handle Netlist format Allegro */ PANELALLEGRO, /* Handle Netlist format Allegro */
PANELCADSTAR, /* Handle Netlist format CadStar */ PANELCADSTAR, /* Handle Netlist format CadStar */
PANELPADS, /* Handle Netlist format PADS */
PANELSPICE, /* Handle Netlist format Spice */ PANELSPICE, /* Handle Netlist format Spice */
PANELSPICEMODEL, /* Handle Netlist format Spice Model (subcircuit) */ PANELSPICEMODEL, /* Handle Netlist format Spice Model (subcircuit) */
PANELCUSTOMBASE /* First auxiliary panel (custom netlists). PANELCUSTOMBASE /* First auxiliary panel (custom netlists).
@ -264,6 +265,9 @@ DIALOG_EXPORT_NETLIST::DIALOG_EXPORT_NETLIST( SCH_EDIT_FRAME* parent ) :
m_PanelNetType[PANELALLEGRO] = m_PanelNetType[PANELALLEGRO] =
new EXPORT_NETLIST_PAGE( m_NoteBook, wxT( "Allegro" ), NET_TYPE_ALLEGRO, false ); new EXPORT_NETLIST_PAGE( m_NoteBook, wxT( "Allegro" ), NET_TYPE_ALLEGRO, false );
m_PanelNetType[PANELPADS] =
new EXPORT_NETLIST_PAGE( m_NoteBook, wxT( "PADS" ), NET_TYPE_PADS, false );
m_PanelNetType[PANELCADSTAR] = m_PanelNetType[PANELCADSTAR] =
new EXPORT_NETLIST_PAGE( m_NoteBook, wxT( "CadStar" ), NET_TYPE_CADSTAR, false ); new EXPORT_NETLIST_PAGE( m_NoteBook, wxT( "CadStar" ), NET_TYPE_CADSTAR, false );
@ -512,6 +516,9 @@ bool DIALOG_EXPORT_NETLIST::TransferDataFromWindow()
case NET_TYPE_ALLEGRO: case NET_TYPE_ALLEGRO:
break; break;
case NET_TYPE_PADS:
break;
default: // custom, NET_TYPE_CUSTOM1 and greater default: // custom, NET_TYPE_CUSTOM1 and greater
{ {
title.Printf( _( "%s Export" ), currPage->m_TitleStringCtrl->GetValue() ); title.Printf( _( "%s Export" ), currPage->m_TitleStringCtrl->GetValue() );
@ -671,6 +678,12 @@ bool DIALOG_EXPORT_NETLIST::FilenamePrms( NETLIST_TYPE_ID aType, wxString * aExt
fileWildcard = FILEEXT::AllegroNetlistFileWildcard(); fileWildcard = FILEEXT::AllegroNetlistFileWildcard();
break; break;
case NET_TYPE_PADS:
fileExt = FILEEXT::PADSNetlistFileExtension;
fileWildcard = FILEEXT::PADSNetlistFileWildcard();
break;
default: // custom, NET_TYPE_CUSTOM1 and greater default: // custom, NET_TYPE_CUSTOM1 and greater
fileWildcard = FILEEXT::AllFilesWildcard(); fileWildcard = FILEEXT::AllFilesWildcard();
ret = false; ret = false;

View File

@ -41,6 +41,7 @@ enum NETLIST_TYPE_ID {
NET_TYPE_SPICE, NET_TYPE_SPICE,
NET_TYPE_SPICE_MODEL, NET_TYPE_SPICE_MODEL,
NET_TYPE_ALLEGRO, NET_TYPE_ALLEGRO,
NET_TYPE_PADS,
NET_TYPE_CUSTOM1, /* NET_TYPE_CUSTOM1 NET_TYPE_CUSTOM1, /* NET_TYPE_CUSTOM1
* is the first id for user netlist format * is the first id for user netlist format
* NET_TYPE_CUSTOM1+CUSTOMPANEL_COUNTMAX-1 * NET_TYPE_CUSTOM1+CUSTOMPANEL_COUNTMAX-1

View File

@ -0,0 +1,204 @@
/*
* This program source code file is part of KiCad, a free EDA CAD application.
*
* Copyright (C) 2024 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 <build_version.h>
#include <confirm.h>
#include <connection_graph.h>
#include <string_utils.h>
#include <sch_edit_frame.h>
#include <sch_reference_list.h>
#include "netlist_exporter_pads.h"
bool NETLIST_EXPORTER_PADS::WriteNetlist( const wxString& aOutFileName,
unsigned /* aNetlistOptions */,
REPORTER& aReporter )
{
int ret = 0;
FILE* f = nullptr;
if( ( f = wxFopen( aOutFileName, wxT( "wt" ) ) ) == nullptr )
{
wxString msg = wxString::Format( _( "Failed to create file '%s'." ), aOutFileName );
aReporter.Report( msg, RPT_SEVERITY_ERROR );
return false;
}
wxString msg;
wxString footprint;
SCH_SYMBOL* symbol;
ret |= fputs( "*PADS-PCB*\n", f );
ret |= fputs( "*PART*\n", f );
// Create netlist footprints section
m_referencesAlreadyFound.Clear();
SCH_SHEET_LIST sheetList = m_schematic->GetSheets();
for( unsigned i = 0; i < sheetList.size(); i++ )
{
for( SCH_ITEM* item : sheetList[i].LastScreen()->Items().OfType( SCH_SYMBOL_T ) )
{
symbol = findNextSymbol( item, &sheetList[ i ] );
if( !symbol )
continue;
if( symbol->GetExcludedFromBoard() )
continue;
footprint = symbol->GetFootprintFieldText( true, &sheetList[ i ], false );
footprint = footprint.Trim( true );
footprint = footprint.Trim( false );
footprint.Replace( wxT( " " ), wxT( "_" ) );
if( footprint.IsEmpty() )
{
// fall back to value field
footprint = symbol->GetValueFieldText( true, &sheetList[i], false );
footprint.Replace( wxT( " " ), wxT( "_" ) );
footprint = footprint.Trim( true );
footprint = footprint.Trim( false );
}
msg = symbol->GetRef( &sheetList[i] );
ret |= fprintf( f, "%-16s %s\n", TO_UTF8( msg ), TO_UTF8( footprint ) );
}
}
ret |= fputs( "\n", f );
if( !writeListOfNets( f ) )
ret = -1; // set error
fclose( f );
return ret >= 0;
}
bool NETLIST_EXPORTER_PADS::writeListOfNets( FILE* f )
{
int ret = 0;
int print_ter = 0;
wxString initialSignalLine;
wxString netName;
ret |= fputs( "*NET*\n", f );
for( const auto& [ key, subgraphs ] : m_schematic->ConnectionGraph()->GetNetMap() )
{
netName = key.Name;
std::vector<std::pair<SCH_PIN*, SCH_SHEET_PATH>> sorted_items;
for( CONNECTION_SUBGRAPH* subgraph : subgraphs )
{
SCH_SHEET_PATH sheet = subgraph->GetSheet();
for( SCH_ITEM* item : subgraph->GetItems() )
{
if( item->Type() == SCH_PIN_T )
sorted_items.emplace_back( static_cast<SCH_PIN*>( item ), sheet );
}
}
// Netlist ordering: Net name, then ref des, then pin name
std::sort( sorted_items.begin(), sorted_items.end(),
[]( std::pair<SCH_PIN*, SCH_SHEET_PATH> a, std::pair<SCH_PIN*, SCH_SHEET_PATH> b )
{
wxString ref_a = a.first->GetParentSymbol()->GetRef( &a.second );
wxString ref_b = b.first->GetParentSymbol()->GetRef( &b.second );
if( ref_a == ref_b )
return a.first->GetShownNumber() < b.first->GetShownNumber();
return ref_a < ref_b;
} );
// 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:
sorted_items.erase( std::unique( sorted_items.begin(), sorted_items.end(),
[]( std::pair<SCH_PIN*, SCH_SHEET_PATH> a, std::pair<SCH_PIN*, SCH_SHEET_PATH> b )
{
wxString ref_a = a.first->GetParentSymbol()->GetRef( &a.second );
wxString ref_b = b.first->GetParentSymbol()->GetRef( &b.second );
return ref_a == ref_b && a.first->GetShownNumber() == b.first->GetShownNumber();
} ),
sorted_items.end() );
print_ter = 0;
std::vector<wxString> netConns;
for( const std::pair<SCH_PIN*, SCH_SHEET_PATH>& pair : sorted_items )
{
SCH_PIN* pin = pair.first;
SCH_SHEET_PATH sheet = pair.second;
wxString refText = pin->GetParentSymbol()->GetRef( &sheet );
wxString pinText = pin->GetShownNumber();
// Skip power symbols and virtual symbols
if( refText[0] == wxChar( '#' ) )
continue;
netConns.push_back(
wxString::Format( "%s.%.4s", refText, pinText ) );
}
// format it such that there are 6 net connections per line
// which seems to be the standard everyone follows
if( netConns .size() > 1 )
{
ret |= fprintf( f, "*SIGNAL* %s\n", TO_UTF8(netName) );
int cnt = 0;
for( wxString& netConn : netConns )
{
ret |= fputs( TO_UTF8( netConn ), f );
if( cnt != 0 && cnt % 6 == 0 )
{
ret |= fputc( '\n', f );
}
else
{
ret |= fputc( ' ', f );
}
cnt++;
}
ret |= fputc( '\n', f );
}
}
ret |= fprintf( f, "*END*\n" );
return ret >= 0;
}

View File

@ -0,0 +1,59 @@
/*
* This program source code file is part of KiCad, a free EDA CAD application.
*
* Copyright (C) 2024 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_PADS_H
#define NETLIST_EXPORTER_PADS_H
#include "netlist_exporter_base.h"
/**
* Generate a netlist compatible with PADS.
*/
class NETLIST_EXPORTER_PADS : public NETLIST_EXPORTER_BASE
{
public:
NETLIST_EXPORTER_PADS( SCHEMATIC* aSchematic ) :
NETLIST_EXPORTER_BASE( aSchematic )
{
}
/**
* Write to specified output file.
*/
bool WriteNetlist( const wxString& aOutFileName, unsigned aNetlistOptions,
REPORTER& aReporter ) override;
private:
/**
* Write a net list (ranked by Netcode), and pins connected to it.
*
* Format:
* - ADD_TER RR2 6 \"$42\"
* - B U1 100
* - 6 CA
*/
bool writeListOfNets( FILE* f );
};
#endif

View File

@ -42,6 +42,7 @@
#include <netlist_exporter_spice_model.h> #include <netlist_exporter_spice_model.h>
#include <netlist_exporter_kicad.h> #include <netlist_exporter_kicad.h>
#include <netlist_exporter_allegro.h> #include <netlist_exporter_allegro.h>
#include <netlist_exporter_pads.h>
#include <netlist_exporter_xml.h> #include <netlist_exporter_xml.h>
@ -91,7 +92,11 @@ bool SCH_EDIT_FRAME::WriteNetListFile( int aFormat, const wxString& aFullFileNam
case NET_TYPE_ALLEGRO: case NET_TYPE_ALLEGRO:
helper = new NETLIST_EXPORTER_ALLEGRO( sch ); helper = new NETLIST_EXPORTER_ALLEGRO( sch );
break; break;
case NET_TYPE_PADS:
helper = new NETLIST_EXPORTER_PADS( sch );
break;
case NET_TYPE_BOM: case NET_TYPE_BOM:
// When generating the BOM, we have a bare filename so don't strip // When generating the BOM, we have a bare filename so don't strip

View File

@ -135,6 +135,7 @@ public:
static const std::string OrCadPcb2NetlistFileExtension; static const std::string OrCadPcb2NetlistFileExtension;
static const std::string NetlistFileExtension; static const std::string NetlistFileExtension;
static const std::string AllegroNetlistFileExtension; static const std::string AllegroNetlistFileExtension;
static const std::string PADSNetlistFileExtension;
static const std::string GerberFileExtension; static const std::string GerberFileExtension;
static const std::string GerberJobFileExtension; static const std::string GerberJobFileExtension;
static const std::string HtmlFileExtension; static const std::string HtmlFileExtension;
@ -219,6 +220,7 @@ public:
static wxString OrCadPcb2NetlistFileWildcard(); static wxString OrCadPcb2NetlistFileWildcard();
static wxString NetlistFileWildcard(); static wxString NetlistFileWildcard();
static wxString AllegroNetlistFileWildcard(); static wxString AllegroNetlistFileWildcard();
static wxString PADSNetlistFileWildcard();
static wxString HtmlFileWildcard(); static wxString HtmlFileWildcard();
static wxString CsvFileWildcard(); static wxString CsvFileWildcard();
static wxString PcbFileWildcard(); static wxString PcbFileWildcard();