LTSpice schematic import based on the work of Chetan Shinde.

This commit is contained in:
Jeff Young 2023-04-22 21:17:08 +01:00
parent 60b019591d
commit 69500bfcaa
24 changed files with 3382 additions and 39 deletions

View File

@ -3,7 +3,7 @@
*
* Copyright (C) 2018 Jean-Pierre Charras, jp.charras at wanadoo.fr
* Copyright (C) 2008 Wayne Stambaugh <stambaughw@gmail.com>
* Copyright (C) 1992-2022 KiCad Developers, see AUTHORS.txt for contributors.
* Copyright (C) 1992-2023 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
@ -128,6 +128,7 @@ const std::string KiCadSymbolLibFileExtension( "kicad_sym" );
const std::string SchematicSymbolFileExtension( "sym" );
const std::string LegacySymbolLibFileExtension( "lib" );
const std::string LegacySymbolDocumentFileExtension( "dcm" );
const std::string LtspiceSymbolExtension( "asy" );
const std::string VrmlFileExtension( "wrl" );
@ -140,6 +141,7 @@ const std::string CadstarSchematicFileExtension( "csa" );
const std::string CadstarPartsLibraryFileExtension( "lib" );
const std::string KiCadSchematicFileExtension( "kicad_sch" );
const std::string SpiceFileExtension( "cir" );
const std::string LtspiceSchematicExtension( "asc" );
const std::string CadstarNetlistFileExtension( "frp" );
const std::string OrCadPcb2NetlistFileExtension( "net" );
const std::string NetlistFileExtension( "net" );
@ -303,6 +305,12 @@ wxString EagleSchematicFileWildcard()
}
wxString LtspiceSchematicFileWildcard()
{
return _( "Ltspice schematic files" ) + AddFileExtListToFilter( { "asc" } );
}
wxString EagleFilesWildcard()
{
return _( "Eagle XML files" ) + AddFileExtListToFilter( { "sch", "brd" } );

View File

@ -53,6 +53,13 @@ set( EESCHEMA_SCH_PLUGINS_CADSTAR
sch_plugins/cadstar/cadstar_sch_archive_plugin.cpp
)
set( EESCHEMA_SCH_PLUGINS_LTSPICE
sch_plugins/ltSpice/ltspice_schematic.cpp
sch_plugins/ltSpice/ltspice_sch_parser.cpp
sch_plugins/ltSpice/ltspice_sch_plugin.cpp
)
set( EESCHEMA_DLGS
dialogs/dialog_annotate.cpp
dialogs/dialog_annotate_base.cpp
@ -243,6 +250,7 @@ set( EESCHEMA_SRCS
${EESCHEMA_LIBEDIT_SRCS}
${EESCHEMA_SCH_PLUGINS_ALTIUM}
${EESCHEMA_SCH_PLUGINS_CADSTAR}
${EESCHEMA_SCH_PLUGINS_LTSPICE}
${EESCHEMA_SIM_SRCS}
${EESCHEMA_WIDGETS}
annotate.cpp

View File

@ -698,6 +698,7 @@ bool DIALOG_SIM_MODEL<T_symbol, T_field>::loadLibrary( const wxString& aLibraryP
WX_STRING_REPORTER reporter( &msg );
m_libraryModelsMgr.SetReporter( &reporter );
m_libraryModelsMgr.SetForceFullParse();
m_libraryModelsMgr.SetLibrary( aLibraryPath );
if( reporter.HasMessage() )

View File

@ -608,6 +608,9 @@ void SCH_EDIT_FRAME::OnImportProject( wxCommandEvent& aEvent )
// Import Eagle schematic files.
loaders.emplace_back( EagleSchematicFileWildcard(), SCH_IO_MGR::SCH_EAGLE );
// Import LTspice schematic files.
loaders.emplace_back( LtspiceSchematicFileWildcard(), SCH_IO_MGR::SCH_LTSPICE );
wxString fileFilters;
wxString allWildcards;
@ -1210,6 +1213,7 @@ bool SCH_EDIT_FRAME::importFile( const wxString& aFileName, int aFileType )
case SCH_IO_MGR::SCH_ALTIUM:
case SCH_IO_MGR::SCH_CADSTAR_ARCHIVE:
case SCH_IO_MGR::SCH_EAGLE:
case SCH_IO_MGR::SCH_LTSPICE:
// We insist on caller sending us an absolute path, if it does not, we say it's a bug.
wxCHECK_MSG( filename.IsAbsolute(), false,
wxT( "Import schematic: path is not absolute!" ) );

View File

@ -2,7 +2,7 @@
* This program source code file is part of KiCad, a free EDA CAD application.
*
* Copyright (C) 2016 CERN
* Copyright (C) 2016-2021 KiCad Developers, see change_log.txt for contributors.
* Copyright (C) 2016-2023 KiCad Developers, see change_log.txt for contributors.
*
* @author Wayne Stambaugh <stambaughw@gmail.com>
*
@ -31,6 +31,7 @@
#include <sch_plugins/altium/sch_altium_plugin.h>
#include <sch_plugins/cadstar/cadstar_sch_archive_plugin.h>
#include <sch_plugins/database/sch_database_plugin.h>
#include <sch_plugins/ltSpice/ltspice_sch_plugin.h>
#include <wildcards_and_files_ext.h>
#define FMT_UNIMPLEMENTED _( "Plugin \"%s\" does not implement the \"%s\" function." )
@ -63,6 +64,7 @@ SCH_PLUGIN* SCH_IO_MGR::FindPlugin( SCH_FILE_T aFileType )
case SCH_CADSTAR_ARCHIVE: return new CADSTAR_SCH_ARCHIVE_PLUGIN();
case SCH_EAGLE: return new SCH_EAGLE_PLUGIN();
case SCH_DATABASE: return new SCH_DATABASE_PLUGIN();
case SCH_LTSPICE: return new SCH_LTSPICE_PLUGIN();
default: return nullptr;
}
}
@ -92,6 +94,7 @@ const wxString SCH_IO_MGR::ShowType( SCH_FILE_T aType )
case SCH_CADSTAR_ARCHIVE: return wxString( wxT( "CADSTAR Schematic Archive" ) );
case SCH_EAGLE: return wxString( wxT( "EAGLE" ) );
case SCH_DATABASE: return wxString( wxT( "Database" ) );
case SCH_LTSPICE: return wxString( wxT( "LTSpice Schematic" ) );
default: return wxString::Format( _( "Unknown SCH_FILE_T value: %d" ),
aType );
}

View File

@ -5,7 +5,7 @@
* This program source code file is part of KiCad, a free EDA CAD application.
*
* Copyright (C) 2016 CERN
* Copyright (C) 2016-2021 KiCad Developers, see AUTHORS.txt for contributors.
* Copyright (C) 2016-2023 KiCad Developers, see AUTHORS.txt for contributors.
*
* @author Wayne Stambaugh <stambaughw@gmail.com>
*
@ -56,11 +56,12 @@ public:
DEFINE_ENUM_VECTOR( SCH_FILE_T,
{
SCH_LEGACY, ///< Legacy Eeschema file formats prior to s-expression.
SCH_KICAD, ///< The s-expression version of the schematic file formats.
SCH_KICAD, ///< The s-expression version of the schematic.
SCH_ALTIUM, ///< Altium file format
SCH_CADSTAR_ARCHIVE, ///< CADSTAR Schematic Archive
SCH_EAGLE, ///< Autodesk Eagle file format
SCH_DATABASE, ///< KiCad database library
SCH_LTSPICE, /// LtSpice Schematic format
// Add your schematic type here.
SCH_FILE_UNKNOWN

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,306 @@
/*
* This program source code file is part of KiCad, a free EDA CAD application.
*
* Copyright (C) 2022 Chetan Subhash Shinde<chetanshinde2001@gmail.com>
* Copyright (C) 2023 CERN
* Copyright (C) 2022-2023 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 3 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, see <http://www.gnu.org/licenses/>.
*/
/**
* @brief Parses the datastructure produced by the LTSPICE_SCHEMATIC into a KiCad
* schematic file.
*/
#ifndef LTSPICE_SCH_PARSER_H
#define LTSPICE_SCH_PARSER_H
#include <sch_io_mgr.h>
#include <pin_type.h>
#include <layer_ids.h>
#include <wx/filename.h>
#include <plotters/plotter.h>
#include <sch_symbol.h>
#include <sch_text.h>
#include <sch_shape.h>
#include <lib_shape.h>
#include "ltspice_schematic.h"
/**
* The class is been used for loading the asc and asy files in intermediate data structure.
* <p>
* The intermediate data structure is a structure, from where the kicad objects will be
* initialised.
* <p>
* The intermediate datastructure is been defined below in the class, with comments for
* individual struct is in place.
* <p>
* parser() - This is the main function responsible for parsing the data into intermediate
* datastructure.
* <p>
* Data Processing Methods - The individual comments for function are given. In general.
* these methods are been used for manipulating the data.
* <p>
* Data Check Methods - The individual comments for functions under this section is given.
* In general these methods are been used for validating the data.
* <p>
* Enum Conversion Methods - The individual comments for functions under this section is
* given. In general these methods are used to convert the string into enum.
*/
class LTSPICE_SCH_PARSER
{
public:
// Size of tiny net labels which none present in original design
const int SMALL_LABEL_SIZE = KiROUND( (double) SCH_IU_PER_MM * 0.4 );
explicit LTSPICE_SCH_PARSER( const wxString& aFilename, LTSPICE_SCHEMATIC* aLTSchematic ) :
m_lt_schematic( aLTSchematic )
{ }
~LTSPICE_SCH_PARSER() {}
/**
* Method converts ltspice coordinate(i.e scale) to kicad coordinates
*
* @param aCoordinate coordinate(i.e scale) in ltspice.
*/
int ToKicadCoords( int aCoordinate );
VECTOR2I ToKicadCoords( const VECTOR2I& aPos );
VECTOR2I ToInvertedKicadCoords( const VECTOR2I& aPos );
VECTOR2I ToKicadFontSize( int aLTFontSize );
/**
* Method converts kicad coordinate(i.e scale) to ltspice coordinates
*
* @param aCoordinate coordinate(i.e scale) in ltspice.
*/
int ToLtSpiceCoords( int aCoordinate );
/**
* Function responsible for loading the .asc and .asy files in intermediate data structure.
*
* @param aSheet variable representing the current sheet.
* @param mapOfFiles a string map containing all the data from .asc and .asy files.
*/
void Parse( SCH_SHEET_PATH* aSheet, std::vector<LTSPICE_SCHEMATIC::LT_ASC>& outLT_ASCs,
const std::vector<wxString>& aAsyFileNames );
/**
* Method for plotting Lines from Asy files
*
* @param aAscfile object representing asc file.
* @param aIndex index.
*/
void CreateLines( LIB_SYMBOL* aSymbol, LTSPICE_SCHEMATIC::LT_SYMBOL& aLTSymbol, int aIndex,
LIB_SHAPE* aShape );
/**
* Method for plotting Schematic Lines from Asy files
*
* @param aAscfile object representing asc file.
* @param aIndex index.
* @param aSheet a object on which the circle is represented.
*/
void CreateLines( LTSPICE_SCHEMATIC::LT_SYMBOL& aLTSymbol, int aIndex, SCH_SHEET_PATH* aSheet );
/**
* Main Method for loading indermediate data to kicacd object from asy files
*
* @param aAscfiles array object representing asc files.
* @param aSheet a object on which the symbols are represented.
*/
void CreateKicadSYMBOLs( SCH_SHEET_PATH* aSheet,
std::vector<LTSPICE_SCHEMATIC::LT_ASC>& outLT_ASCs,
const std::vector<wxString>& aAsyFiles );
void CreateSymbol( LTSPICE_SCHEMATIC::LT_SYMBOL& schematicSymbol, LIB_SYMBOL* symbol );
/**
* Methods for rotating and mirroring objects
*/
void RotateMirror( LTSPICE_SCHEMATIC::LT_SYMBOL& aLTSymbol, SCH_SYMBOL* aSchSymbol );
void RotateMirrorShape( LTSPICE_SCHEMATIC::LT_SYMBOL& aLTSymbol, SCH_SHAPE* aShape );
/**
* Method for plotting wires
*
* @param aLTSymbol object representing asc file.
* @param aIndex index.
* @param aSheet a object on which the symbols is represented.
*/
void CreateWires( LTSPICE_SCHEMATIC::LT_SYMBOL& aLTSymbol, int aIndex,
SCH_SHEET_PATH* aSheet );
/**
* Main method for loading intermediate data structure from Asc file to kicad.
*
* @param outLT_ASCs
* @param aSheet a object on which the circle is represented.
*/
void CreateKicadSCH_ITEMs( SCH_SHEET_PATH* aSheet,
std::vector<LTSPICE_SCHEMATIC::LT_ASC>& outLT_ASCs );
/**
* Method for plotting Bustap from Asc files
*
* @param aAscfile object representing asc file.
* @param aIndex index.
* @param aSheet a object on which the circle is represented.
*/
void CreateBusEntry( LTSPICE_SCHEMATIC::LT_ASC& aAscfile, int aIndex, SCH_SHEET_PATH* aSheet );
/**
* Method for plotting Iopin from Asc files
*
* @param aAscfile object representing asc file.
* @param aIndex index.
* @param aSheet a object on which the circle is represented.
*/
void CreatePin( LTSPICE_SCHEMATIC::LT_ASC& aAscfile, int aIndex, SCH_SHEET_PATH* aSheet );
/**
* Method to get Label Shape in kicad
*
* @param aAscfile object representing asc file.
* @param aIndex index.
*/
LABEL_FLAG_SHAPE GetLabelShape( LTSPICE_SCHEMATIC::LT_ASC& aAscfile, int aIndex );
/**
* Method for plotting Line from Asc files
*
* @param aAscfile object representing asc file.
* @param aIndex index.
* @param aSheet a object on which the circle is represented.
*/
void CreateLine( LTSPICE_SCHEMATIC::LT_ASC& aAscfile, int aIndex, SCH_SHEET_PATH* aSheet );
/**
* Method for plotting circle from Asc files
*
* @param aAscfile object representing asc file.
* @param aIndex index.
* @param aSheet a object on which the circle is represented.
*/
void CreateCircle( LTSPICE_SCHEMATIC::LT_ASC& aAscfile, int aIndex, SCH_SHEET_PATH* aSheet );
/**
* Method for plotting Arc from Asc files
*
* @param aAscfile object representing asc file.
* @param aIndex index.
* @param aSheet a object on which the Arc is represented.
*/
void CreateArc( LTSPICE_SCHEMATIC::LT_ASC& aAscfile, int aIndex, SCH_SHEET_PATH* aSheet );
/**
* Method for setting Text Justification.
*
* @param aAscfile object representing asc file.
* @param aIndex index.
* @param aSheet a object on which the text is represented used for justification.
*/
void CreateRect( LTSPICE_SCHEMATIC::LT_ASC& aAscfile, int aIndex, SCH_SHEET_PATH* aSheet );
/**
* Create schematic text.
*/
void CreateText( LTSPICE_SCHEMATIC::LT_ASC& aAscfile, int aIndex, SCH_SHEET_PATH* aSheet );
/**
* Create a schematic wire.
*/
void CreateWire( LTSPICE_SCHEMATIC::LT_ASC& aAscfile, int aIndex, SCH_SHEET_PATH* aSheet,
SCH_LAYER_ID aLayer );
/**
* Create a power symbol from an LTspice flag
*/
void CreatePowerSymbol( LTSPICE_SCHEMATIC::LT_ASC& aAscfile, int aIndex,
SCH_SHEET_PATH* aSheet );
void CreateFields( LTSPICE_SCHEMATIC::LT_SYMBOL& aLTSymbol, SCH_SYMBOL* aSymbol,
SCH_SHEET_PATH* aSheet );
/**
* Method for plotting Window(i.e flags which are shown on screen ) from Asy files
*/
void CreateText( LTSPICE_SCHEMATIC::LT_SYMBOL& aLTSymbol, int aIndex, SCH_SHEET_PATH* aSheet );
/**
* Create a symbol rect.
*/
void CreateRect( LTSPICE_SCHEMATIC::LT_SYMBOL& aLTSymbol, int aIndex, LIB_SHAPE* aRectangle );
/**
* Create a schematic rect.
*/
void CreateRect( LTSPICE_SCHEMATIC::LT_SYMBOL& aLTSymbol, int aIndex, SCH_SHEET_PATH* aSheet );
/**
* Create a pin from an asy file.
*/
void CreatePin( LTSPICE_SCHEMATIC::LT_SYMBOL& aLTSymbol, int aIndex, LIB_PIN* aPin );
/**
* Create a symbol arc.
*/
void CreateArc( LTSPICE_SCHEMATIC::LT_SYMBOL& aLTSymbol, int aIndex, LIB_SHAPE* aArc );
/**
* Create a schematic arc.
*/
void CreateArc( LTSPICE_SCHEMATIC::LT_SYMBOL& aLTSymbol, int aIndex, SCH_SHEET_PATH* aSheet );
/**
* Create a symbol circle.
*/
void CreateCircle( LTSPICE_SCHEMATIC::LT_SYMBOL& aLTSymbol, int aIndex, LIB_SHAPE* aCircle );
/**
* Create a schematic circle.
*/
void CreateCircle( LTSPICE_SCHEMATIC::LT_SYMBOL& aLTSymbol, int aIndex, SCH_SHEET_PATH* aSheet );
private:
/**
* Method for setting Text Justification.
*
* @param aLineWidth object representing line width from ltspice.
*/
int getLineWidth( const LTSPICE_SCHEMATIC::LINEWIDTH& aLineWidth );
/**
* Method to get line Style For kicad.
*
* @param aLineStyle lineStyle from ltspice.
*/
PLOT_DASH_TYPE getLineStyle( const LTSPICE_SCHEMATIC::LINESTYLE& aLineStyle );
STROKE_PARAMS getStroke( const LTSPICE_SCHEMATIC::LINEWIDTH& aLineWidth,
const LTSPICE_SCHEMATIC::LINESTYLE& aLineStyle );
void readIncludes( std::vector<LTSPICE_SCHEMATIC::LT_ASC>& outLT_ASCs );
private:
LTSPICE_SCHEMATIC* m_lt_schematic;
wxFileName m_libraryFileName;
VECTOR2I m_originOffset;
std::map<wxString, wxString> m_includes;
};
#endif // LTSPICE_SCH_PARSER_H

View File

@ -0,0 +1,107 @@
/*
* This program source code file is part of KiCad, a free EDA CAD application.
*
* Copyright (C) 2022 Chetan Subhash Shinde<chetanshinde2001@gmail.com>
* Copyright (C) 2023 CERN
* Copyright (C) 2022-2023 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 3 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, see <http://www.gnu.org/licenses/>.
*/
#include <sch_plugins/ltSpice/ltspice_schematic.h>
#include <sch_plugins/ltSpice/ltspice_sch_plugin.h>
#include <sch_plugins/ltSpice/ltspice_sch_parser.h>
#include <schematic.h>
#include <sch_sheet.h>
#include <sch_screen.h>
#include <sch_line.h>
#include <wildcards_and_files_ext.h>
/**
* @brief schematic PLUGIN for Ltspice (*.asc) and (.asy) format.
*/
const wxString SCH_LTSPICE_PLUGIN::GetName() const
{
return wxT( "Ltspice Schematic Importer" );
}
const wxString SCH_LTSPICE_PLUGIN::GetFileExtension() const
{
return wxT( "asc" );
}
const wxString SCH_LTSPICE_PLUGIN::GetLibraryFileExtension() const
{
return wxT( "lib" );
}
int SCH_LTSPICE_PLUGIN::GetModifyHash() const
{
return 0;
}
SCH_SHEET* SCH_LTSPICE_PLUGIN::Load( const wxString& aFileName, SCHEMATIC* aSchematic,
SCH_SHEET* aAppendToMe, const STRING_UTF8_MAP* aProperties )
{
wxASSERT( !aFileName || aSchematic );
SCH_SHEET* rootSheet = nullptr;
if( aAppendToMe )
{
wxCHECK_MSG( aSchematic->IsValid(), nullptr, "Can't append to a schematic with no root!" );
rootSheet = &aSchematic->Root();
}
else
{
rootSheet = new SCH_SHEET( aSchematic );
rootSheet->SetFileName( aFileName );
aSchematic->SetRoot( rootSheet );
}
if( !rootSheet->GetScreen() )
{
SCH_SCREEN* screen = new SCH_SCREEN( aSchematic );
screen->SetFileName( aFileName );
rootSheet->SetScreen( screen );
}
SYMBOL_LIB_TABLE* libTable = aSchematic->Prj().SchSymbolLibTable();
wxCHECK_MSG( libTable, nullptr, "Could not load symbol lib table." );
LTSPICE_SCHEMATIC ascFile( aFileName );
SCH_PLUGIN::SCH_PLUGIN_RELEASER sch_plugin;
sch_plugin.set( SCH_IO_MGR::FindPlugin( SCH_IO_MGR::SCH_KICAD ) );
ascFile.Load( aSchematic, rootSheet, &sch_plugin, aFileName );
aSchematic->CurrentSheet().UpdateAllScreenReferences();
return rootSheet;
}
bool SCH_LTSPICE_PLUGIN::CheckHeader( const wxString& aFileName )
{
return true;
}

View File

@ -0,0 +1,72 @@
/*
* This program source code file is part of KiCad, a free EDA CAD application.
*
* Copyright (C) 2022 Chetan Subhash Shinde<chetanshinde2001@gmail.com>
* Copyright (C) 2023 CERN
* Copyright (C) 2022-2023 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 3 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, see <http://www.gnu.org/licenses/>.
*/
#ifndef SCH_LTSPICE_PLUGIN_H_
#define SCH_LTSPICE_PLUGIN_H_
#include <sch_io_mgr.h>
#include <reporter.h>
#include <wx/log.h>
class SCH_SHEET;
class SCH_SCREEN;
class SCH_LTSPICE_PLUGIN : public SCH_PLUGIN
{
public:
SCH_LTSPICE_PLUGIN()
{
m_reporter = &WXLOG_REPORTER::GetInstance();
m_progressReporter = nullptr;
}
~SCH_LTSPICE_PLUGIN()
{
}
const wxString GetName() const override;
void SetReporter( REPORTER* aReporter ) override { m_reporter = aReporter; }
void SetProgressReporter( PROGRESS_REPORTER* aReporter ) override
{
m_progressReporter = aReporter;
}
const wxString GetFileExtension() const override;
const wxString GetLibraryFileExtension() const override;
int GetModifyHash() const override;
SCH_SHEET* Load( const wxString& aFileName, SCHEMATIC* aSchematic,
SCH_SHEET* aAppendToMe = nullptr,
const STRING_UTF8_MAP* aProperties = nullptr ) override;
bool CheckHeader( const wxString& aFileName ) override;
private:
REPORTER* m_reporter; // current reporter for warnings/errors
PROGRESS_REPORTER* m_progressReporter; // optional; may be nullptr
};
#endif // SCH_LTSPICE_PLUGIN_H_

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,439 @@
/*
* This program source code file is part of KiCad, a free EDA CAD application.
*
* Copyright (C) 2022 Chetan Subhash Shinde<chetanshinde2001@gmail.com>
* Copyright (C) 2023 CERN
* Copyright (C) 2022-2023 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 3 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, see <http://www.gnu.org/licenses/>.
*/
#ifndef LTSPICE_SCHEMATIC_LOADER_H
#define LTSPICE_SCHEMATIC_LOADER_H
#include <sch_io_mgr.h>
#include <sch_sheet_path.h>
#include <pin_type.h>
#include <layer_ids.h>
#include <wx/filename.h>
#include <plotters/plotter.h>
struct LTSPICE_FILE
{
wxFileName Name;
VECTOR2I Offset;
int ParentIndex;
SCH_SHEET* Sheet;
SCH_SCREEN* Screen;
SCH_SHEET_PATH SheetPath;
LTSPICE_FILE( const wxFileName& aFilename, const VECTOR2I& aOffset ) :
Name( aFilename ),
Offset( aOffset )
{ }
bool operator<( const LTSPICE_FILE& t ) const
{
return this->Name.GetFullName() < t.Name.GetFullName();
}
};
class LTSPICE_SCHEMATIC
{
public:
enum class LINESTYLE
{
SOLID = 0,
DASH = 1,
DOT = 2,
DASHDOT = 3,
DASHDOTDOT = 4
};
enum class LINEWIDTH
{
Normal = 5,
Wide = 10
};
/**
* Polarity enum represents polarity of pin
*/
enum class POLARITY
{
INPUT, // IN POLARITY
OUTPUT, // OUT POLARITY
BIDIR // BI-DIRECTIONAL POLARITY
};
/**
* Type of Symbol loaded from asc and asy file
*
* NOTE: Currently we have only found CELL and BLOCK type of symbol components others, we
* are not able to reproduce till now.
*/
enum class SYMBOLTYPE
{
CELL,
BLOCK
};
/**
* Defines in what ways the PIN or TEXT can be justified
*/
enum class JUSTIFICATION
{
NONE,
BOTTOM,
LEFT,
RIGHT,
CENTER,
TOP,
VBOTTOM, // Vertical Bottom Justification
VLEFT, // Vertical Left Justification
VRIGHT, // Vertical Right Justification
VTOP // Vertical Top Justification.
};
/**
* Defines different types or rotation and mirror operation can be applied to a LT_SYMBOL.
*/
enum class ORIENTATION
{
R0, // 0 degree rotation
R90, // 90 degree rotatioin.
R180, // 180 degree rotation.
R270, // 270 degree rotation.
M0, // 0 degree mirror
M90, // 90 degree mirror
M180, // 180 degree mirror
M270 // 270 degree mirror
};
struct LINE
{
VECTOR2I Start;
VECTOR2I End;
LINEWIDTH LineWidth;
LINESTYLE LineStyle;
};
struct LT_PIN
{
VECTOR2I PinLocation;
JUSTIFICATION PinJustification;
int NameOffSet;
std::map<wxString, wxString> PinAttribute;
};
/**
* The CIRCLE is represented in Ltpsice inside a rectangle whose two opposite points and
* line style are given.
*/
struct CIRCLE
{
VECTOR2I TopLeft;
VECTOR2I BotRight;
LINEWIDTH LineWidth;
LINESTYLE LineStyle;
};
struct LT_WINDOW
{
int WindowNumber;
int FontSize;
VECTOR2I Position;
JUSTIFICATION Justification;
};
/**
* The ARC is represented inside a rectangle whose opposite site are given.
* To mark the starting and ending of the ARC two points are given on the rectangle
*/
struct ARC
{
VECTOR2I TopLeft;
VECTOR2I BotRight;
VECTOR2I ArcStart;
VECTOR2I ArcEnd;
LINEWIDTH LineWidth;
LINESTYLE LineStyle;
};
/**
* A 4-sided polygon with opposite equal sides, used in representing shapes
*/
struct RECTANGLE
{
VECTOR2I TopLeft;
VECTOR2I BotRight;
LINEWIDTH LineWidth;
LINESTYLE LineStyle;
};
/**
* A metallic connection, used for transfer, between two points or pin.
*/
struct WIRE
{
VECTOR2I Start;
VECTOR2I End;
};
/**
* A marker. used to specify certain position.
*/
struct FLAG
{
VECTOR2I Offset;
int FontSize;
wxString Value;
};
struct TEXT
{
VECTOR2I Offset;
JUSTIFICATION Justification;
int FontSize;
wxString Value;
};
/**
* IOPIN is special contact on symbol used for IO operations.
*/
struct IOPIN
{
VECTOR2I Location;
POLARITY Polarity;
};
struct BUSTAP
{
VECTOR2I Start;
VECTOR2I End;
};
/**
* A struct to hold SYMBOL definition
*/
struct LT_SYMBOL
{
wxString Name;
SYMBOLTYPE SymbolType;
VECTOR2I Offset;
std::map<wxString, wxString> SymAttributes;
std::vector<LT_PIN> Pins;
std::vector<LINE> Lines;
std::vector<CIRCLE> Circles;
std::vector<LT_WINDOW> Windows;
std::vector<ARC> Arcs;
std::vector<RECTANGLE> Rectangles;
std::vector<WIRE> Wires;
ORIENTATION SymbolOrientation;
};
/**
* A struct to hold .asc file definition
*/
struct LT_ASC
{
VECTOR2I SheetSize;
int Version;
int SheetNumber;
std::vector<LT_SYMBOL> Symbols;
std::vector<LINE> Lines;
std::vector<CIRCLE> Circles;
std::vector<LT_WINDOW> Windows;
std::vector<ARC> Arcs;
std::vector<RECTANGLE> Rectangles;
std::vector<WIRE> Wires;
std::vector<FLAG> Flags;
std::vector<IOPIN> Iopins;
std::vector<BUSTAP> Bustap;
std::vector<TEXT> Texts;
BOX2I BoundingBox;
};
explicit LTSPICE_SCHEMATIC( const wxString& aFilename, REPORTER* aReporter = nullptr,
PROGRESS_REPORTER* aProgressReporter = nullptr )
{
m_schematic = nullptr;
m_rootSheet = nullptr;
m_plugin = nullptr;
m_designCenter.x = 0;
m_designCenter.y = 0;
m_reporter = aReporter;
m_progressReporter = aProgressReporter;
}
~LTSPICE_SCHEMATIC() {}
/**
* The main function responsible for loading the .asc and .asy files.
*
* @param aSchematic is the schematic object.
* @param aRootSheet is the root sheet referencing variable.
* @param aSchPlugin is plugin releaser object, used to free memory when loading is done.
* @param aLibraryFileName is the name of the library which gets created when the plugin runs.
*/
void Load( SCHEMATIC* aSchematic, SCH_SHEET* aRootSheet,
SCH_PLUGIN::SCH_PLUGIN_RELEASER* aSchPlugin, const wxFileName& aLibraryFileName );
/**
* Used to check if the given symbol is subschematic or not.
*
* @param aSchematicElementsArray array which stores which elements names.
* @param aMapOfAscFiles map of string containing content from asc files.
* @param aSubSchematicList list of subschematic elements.
*/
void SubSchematicCheck( std::vector<LTSPICE_FILE>& aSchematicElementsArray,
std::map<wxString, wxString>& aMapOfAscFiles,
std::vector<LTSPICE_FILE>& aSubSchematicList );
/**
* Used to get file path for Asc and Asy files.
*
* @param aMapOfAscFiles map of string containing content from asc files.
* @param aMapOfAsyFiles map of string containing content from asy files.
*/
void GetAscAndAsyFilePaths( std::map<wxString, wxString>& aMapOfAscFiles,
std::map<wxString, wxString>& aMapOfAsyFiles,
const wxFileName& parentFileName );
/**
* Used to get symbols list present in asc file.
*
* @param aFilePath path where file to be read is kept.
* @param aReadType specifies in which type the file is to be read eg.
* r specifies file is use open for reading.
*/
std::vector<LTSPICE_FILE> GetSchematicElements( const wxString& aAscFile );
/**
* The function returns a map. This map has all the asy files in form of string. For asy files
* the key will be symbol name.
*
* @param aFilenames contains all the symbols for which we
* we have to load the .asy files
* @return a map of String having all .asy files
*/
std::map<wxString, wxString> ReadAsyFiles( const std::vector<LTSPICE_FILE>& aSourceFiles,
const std::map<wxString, wxString>& aAsyFileMap );
/**
* Build Intermediate data structure.
* @return LT_ASC struct filled with all info from asc and asy files.
*/
std::vector<LT_ASC> StructureBuilder();
LT_SYMBOL SymbolBuilder( const wxString& aAscFileName, LT_ASC& aAscFile );
LT_SYMBOL SymbolBuilder( const wxString& aAscFileName, const wxString& aAsyFileContent,
LT_ASC& aAscFile );
private:
/**
* Join value present across multiple tokens into one
*
* @param aTokens an array of tokenised data.
* @param aIndex from where the tokens should be concatenated.
*/
static void aggregateAttributeValue( wxArrayString& aTokens, int aIndex );
/**
* Used to check if the given token in integer or not.
*
* @param aToken token to be verified.
* @param aLineNumber gives on which line number the check is called.
* @param aFileName gives in which file the check is been called.
* @return the integer value.
* @throw IO_ERROR if the token is not an integer.
*/
static int integerCheck( const wxString& aToken, int aLineNumber, const wxString& aFileName );
static VECTOR2I pointCheck( const wxString& aTokenX, const wxString& aTokenY, int aLineNumber,
const wxString& aFileName );
/**
* Used to check size of the token generated from split function.
*
* @param aActualSize actual size of array of token.
* @param aExpectedMin expected lower range(i.e size) of array of token.
* @param aExpectedMax expected higher range(i.e size) of array of token.
* @param aLineNumber gives on which line number the check is called.
* @param aFileName gives in which file the check is been called.
* @throw IO_ERROR if the actualSize is not within expected lower range..higher range.
*/
static void tokensSizeRangeCheck( size_t aActualSize, int aExpectedMin, int aExpectedMax,
int aLineNumber, const wxString& aFileName );
static void removeCarriageReturn( wxString& elementFromLine );
/**
* @param aValue integer value between 0-3
* @return LINESTYLE enum
*/
static LINESTYLE getLineStyle( int aValue );
/**
* @param aValue string value
* @return LINEWIDTH enum
*/
static LINEWIDTH getLineWidth( const wxString& aValue );
/**
* @param aValue string value
* @return POLARITY enum
*/
static POLARITY getPolarity( const wxString& aValue );
/**
* @param aValue string value
* @return ORIENTATION enum
*/
static ORIENTATION getSymbolRotationOrMirror( const wxString& aValue );
/**
* @param aValue string value
* @return JUSTIFICATION enum
*/
static JUSTIFICATION getTextJustification( const wxString& aValue );
/**
* @param aValue string value
* @return JUSTIFICATION enum
*/
static JUSTIFICATION getPinJustification( const wxString& aValue );
/**
* @param aValue string value
* @return SYMBOLTYPE enum
*/
static SYMBOLTYPE getSymbolType( const wxString& aValue );
private:
REPORTER* m_reporter;
SCHEMATIC* m_schematic;
SCH_SHEET* m_rootSheet;
SCH_PLUGIN::SCH_PLUGIN_RELEASER* m_plugin;
wxFileName m_libraryFileName;
wxPoint m_designCenter; //< Used for calculating the required
//< offset to apply to the LTspice design
//< so that it fits in KiCad canvas
PROGRESS_REPORTER* m_progressReporter; // optional; may be nullptr
std::map<wxString, std::map<wxString, wxString>> m_fileCache;
};
#endif // LTSPICE_SCHEMATIC_LOADER_H

View File

@ -127,9 +127,8 @@ bool NGSPICE_CIRCUIT_MODEL::ParseDCCommand( const wxString& aCmd, SPICE_DC_PARAM
if( !aCmd.Lower().StartsWith( ".dc" ) )
return false;
wxString cmd = aCmd.Mid( 3 ).Trim().Trim( false );
wxStringTokenizer tokens( cmd );
wxString cmd = aCmd.Mid( 3 );
wxStringTokenizer tokens( cmd, wxS( " \t" ), wxTOKEN_STRTOK );
size_t num = tokens.CountTokens();

View File

@ -41,7 +41,8 @@ using namespace std::placeholders;
SIM_LIB_MGR::SIM_LIB_MGR( const PROJECT* aPrj, REPORTER* aReporter ) :
m_project( aPrj ),
m_reporter( aReporter )
m_reporter( aReporter ),
m_forceFullParse( false )
{
}
@ -136,7 +137,8 @@ void SIM_LIB_MGR::SetLibrary( const wxString& aLibraryPath )
std::function<wxString(const wxString&, const wxString&)> f2 =
std::bind( &SIM_LIB_MGR::ResolveEmbeddedLibraryPath, this, _1, _2 );
std::unique_ptr<SIM_LIBRARY> library = SIM_LIBRARY::Create( path, m_reporter, &f2 );
std::unique_ptr<SIM_LIBRARY> library = SIM_LIBRARY::Create( path, m_forceFullParse,
m_reporter, &f2 );
Clear();
m_libraries[path] = std::move( library );
@ -294,7 +296,8 @@ SIM_LIBRARY::MODEL SIM_LIB_MGR::CreateModel( const wxString& aLibraryPath,
std::function<wxString( const wxString&, const wxString& )> f2 =
std::bind( &SIM_LIB_MGR::ResolveEmbeddedLibraryPath, this, _1, _2 );
it = m_libraries.emplace( path, SIM_LIBRARY::Create( path, m_reporter, &f2 ) ).first;
it = m_libraries.emplace( path, SIM_LIBRARY::Create( path, m_forceFullParse,
m_reporter, &f2 ) ).first;
}
library = &*it->second;

View File

@ -44,6 +44,7 @@ public:
virtual ~SIM_LIB_MGR() = default;
void SetReporter( REPORTER* aReporter ) { m_reporter = aReporter; }
void SetForceFullParse() { m_forceFullParse = true; }
void Clear();
@ -81,6 +82,7 @@ public:
private:
const PROJECT* m_project;
REPORTER* m_reporter;
bool m_forceFullParse;
std::map<wxString, std::unique_ptr<SIM_LIBRARY>> m_libraries;
std::vector<std::unique_ptr<SIM_MODEL>> m_models;
};

View File

@ -30,7 +30,7 @@
std::unique_ptr<SIM_LIBRARY>
SIM_LIBRARY::Create( const wxString& aFilePath, REPORTER* aReporter,
SIM_LIBRARY::Create( const wxString& aFilePath, bool aForceFullParse, REPORTER* aReporter,
std::function<wxString( const wxString&, const wxString& )>* aResolver )
{
std::unique_ptr<SIM_LIBRARY> library;
@ -38,7 +38,7 @@ SIM_LIBRARY::Create( const wxString& aFilePath, REPORTER* aReporter,
if( aFilePath.EndsWith( ".ibs" ) )
library = std::make_unique<SIM_LIBRARY_KIBIS>();
else
library = std::make_unique<SIM_LIBRARY_SPICE>();
library = std::make_unique<SIM_LIBRARY_SPICE>( aForceFullParse );
library->m_reporter = aReporter;
library->m_pathResolver = aResolver;

View File

@ -50,10 +50,12 @@ public:
*
* @param aFilePath Path to the file.
* @param aReporter The reporter the library reports to
* @param aForceFullParse Caller requires fully parsed models. If false fallback models can
* be generarted for performance.
* @return The library loaded in a newly constructed object.
*/
static std::unique_ptr<SIM_LIBRARY>
Create( const wxString& aFilePath, REPORTER* aReporter,
Create( const wxString& aFilePath, bool aForceFullParse, REPORTER* aReporter,
std::function<wxString( const wxString&, const wxString& )>* aResolver );
/**

View File

@ -26,9 +26,9 @@
#include <sim/sim_model_spice.h>
SIM_LIBRARY_SPICE::SIM_LIBRARY_SPICE() :
SIM_LIBRARY_SPICE::SIM_LIBRARY_SPICE( bool aForceFullParse ) :
SIM_LIBRARY(),
m_spiceLibraryParser( std::make_unique<SPICE_LIBRARY_PARSER>( *this ) )
m_spiceLibraryParser( std::make_unique<SPICE_LIBRARY_PARSER>( *this, aForceFullParse ) )
{
}

View File

@ -34,7 +34,7 @@ class SIM_LIBRARY_SPICE : public SIM_LIBRARY
public:
friend class SPICE_LIBRARY_PARSER;
SIM_LIBRARY_SPICE();
SIM_LIBRARY_SPICE( bool aForceFullParse );
// @copydoc SIM_LIBRARY::ReadFile()
void ReadFile( const wxString& aFilePath, REPORTER* aReporter ) override;

View File

@ -28,6 +28,7 @@
#include <sim/sim_library_spice.h>
#include <sim/spice_grammar.h>
#include <sim/sim_model_spice.h>
#include <sim/sim_model_spice_fallback.h>
#include <ki_exception.h>
#include <pegtl.hpp>
@ -57,6 +58,82 @@ namespace SIM_LIBRARY_SPICE_PARSER
};
static SIM_MODEL::TYPE getFallbackType( const wxString& aToken, const wxString& aLine )
{
for( SIM_MODEL::TYPE candidate : SIM_MODEL::TYPE_ITERATOR() )
{
wxString candidate_type = SIM_MODEL::SpiceInfo( candidate ).modelType;
if( candidate_type.IsEmpty() )
continue;
if( SIM_MODEL::SpiceInfo( candidate ).level != ""
&& !SIM_MODEL::SpiceInfo( candidate ).isDefaultLevel )
{
continue;
}
if( candidate_type.StartsWith( wxS( "VDMOS" ) ) && aToken == wxS( "VDMOS" ) )
{
if( candidate_type.EndsWith( wxS( "PCHAN" ) ) )
{
if( aLine.Upper().Contains( wxS( "PCHAN" ) ) )
return candidate;
}
else
{
if( !aLine.Upper().Contains( wxS( "PCHAN" ) ) )
return candidate;
}
}
else if( aToken.StartsWith( candidate_type ) )
{
return candidate;
}
}
return SIM_MODEL::TYPE::NONE;
}
void SPICE_LIBRARY_PARSER::readFallbacks( const wxString& aFilePath, REPORTER& aReporter )
{
try
{
wxArrayString lines = wxSplit( SafeReadFile( aFilePath, wxS( "r" ) ), '\n' );
for( const wxString& line : lines )
{
wxStringTokenizer tokenizer( line, wxS( " ()\t\r\n" ), wxTOKEN_STRTOK );
wxString token = tokenizer.GetNextToken().Lower();
if( token == wxS( ".model" ) )
{
wxString name = tokenizer.GetNextToken();
wxString typeToken = tokenizer.GetNextToken().Upper();
SIM_MODEL::TYPE type = getFallbackType( typeToken, line );
m_library.m_models.push_back( std::make_unique<SIM_MODEL_SPICE_FALLBACK>( type ) );
m_library.m_modelNames.emplace_back( name );
}
else if( token == wxS( ".inc" ) )
{
wxString lib = tokenizer.GetNextToken();
if( m_library.m_pathResolver )
lib = ( *m_library.m_pathResolver )( lib, aFilePath );
parseFile( lib, aReporter );
}
}
}
catch( IO_ERROR& e )
{
aReporter.Report( e.What(), RPT_SEVERITY_ERROR );
}
}
void SPICE_LIBRARY_PARSER::parseFile( const wxString &aFilePath, REPORTER& aReporter )
{
try
@ -127,18 +204,12 @@ void SPICE_LIBRARY_PARSER::ReadFile( const wxString& aFilePath, REPORTER* aRepor
m_library.m_models.clear();
m_library.m_modelNames.clear();
if( aReporter )
{
parseFile( aFilePath, *aReporter );
}
// Aside from the simulation model editor dialog, about the only data we use from the
// complete models are the pin definitions for SUBCKTs. The standard LTSpice "cmp" libraries
// (cmp/standard.bjt, cmp/standard.mos, etc.) have copious error which trip up our parser,
// and our parser is *really* slow on such large files (nearly 5 seconds on my dev machine).
if( !m_forceFullParse && aFilePath.Contains( wxS( "/LTspiceXVII/lib/cmp/standard" ) ) )
readFallbacks( aFilePath, *aReporter );
else
{
wxString msg;
WX_STRING_REPORTER reporter( &msg );
parseFile( aFilePath, reporter );
if( reporter.HasMessage() )
THROW_IO_ERROR( msg );
}
parseFile( aFilePath, *aReporter );
}

View File

@ -33,7 +33,8 @@ class REPORTER;
class SPICE_LIBRARY_PARSER
{
public:
SPICE_LIBRARY_PARSER( SIM_LIBRARY_SPICE &aLibrary ) :
SPICE_LIBRARY_PARSER( SIM_LIBRARY_SPICE &aLibrary, bool aForceFullParse ) :
m_forceFullParse( aForceFullParse ),
m_library( aLibrary )
{};
@ -43,9 +44,11 @@ public:
virtual void ReadFile( const wxString& aFilePath, REPORTER* aReporter );
protected:
void readFallbacks( const wxString& aFilePath, REPORTER& aReporter );
void parseFile( const wxString& aFilePath, REPORTER& aReporter );
private:
bool m_forceFullParse;
SIM_LIBRARY_SPICE& m_library;
};

View File

@ -4,7 +4,7 @@
* Copyright (C) 2018 Jean-Pierre Charras, jp.charras at wanadoo.fr
* Copyright (C) 2007-2012 SoftPLC Corporation, Dick Hollenbeck <dick@softplc.com>
* Copyright (C) 2008 Wayne Stambaugh <stambaughw@gmail.com>
* Copyright (C) 1992-2020 KiCad Developers, see AUTHORS.txt for contributors.
* Copyright (C) 1992-2023 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
@ -157,6 +157,8 @@ extern const std::string FootprintPlaceFileExtension;
extern const std::string KiCadFootprintFileExtension;
extern const std::string KiCadFootprintLibPathExtension;
extern const std::string AltiumFootprintLibPathExtension;
extern const std::string LtspiceSchematicExtension;
extern const std::string LtspiceSymbolExtension;
extern const std::string GedaPcbFootprintLibFileExtension;
extern const std::string EagleFootprintLibPathExtension;
extern const std::string DrawingSheetFileExtension;
@ -218,6 +220,7 @@ extern wxString AltiumSchematicFileWildcard();
extern wxString CadstarSchematicArchiveFileWildcard();
extern wxString CadstarArchiveFilesWildcard();
extern wxString EagleSchematicFileWildcard();
extern wxString LtspiceSchematicFileWildcard();
extern wxString EagleFilesWildcard();
extern wxString PCadPcbFileWildcard();
extern wxString CadstarPcbArchiveFileWildcard();

View File

@ -204,7 +204,7 @@ BOOST_AUTO_TEST_CASE( EndconnectionPoints )
// make sure the pins made it in
BOOST_CHECK_EQUAL( pins.size(), pin_defs.size() );
// Check that the EndPoint getter gets the right things
// Check that the End getter gets the right things
{
std::vector<DANGLING_END_ITEM> expectedDangling;

View File

@ -47,7 +47,7 @@ public:
void LoadLibrary( const std::string& aBaseName )
{
std::string path = GetLibraryPath( aBaseName );
m_library = std::make_unique<SIM_LIBRARY_SPICE>();
m_library = std::make_unique<SIM_LIBRARY_SPICE>( true );
m_library->ReadFile( path, nullptr );
}