Implement fallback models for SPICE .lib models that we can't parse.
This commit is contained in:
parent
d0d6dc6ce0
commit
7f60b87d1d
|
@ -299,6 +299,7 @@ set( EESCHEMA_SRCS
|
|||
sim/sim_model_raw_spice.cpp
|
||||
sim/sim_model_source.cpp
|
||||
sim/sim_model_spice.cpp
|
||||
sim/sim_model_spice_fallback.cpp
|
||||
sim/sim_model_subckt.cpp
|
||||
sim/sim_model_switch.cpp
|
||||
sim/sim_model_tline.cpp
|
||||
|
|
|
@ -31,6 +31,7 @@
|
|||
#include <sim/sim_model.h>
|
||||
#include <sim/sim_model_kibis.h>
|
||||
#include <sim/sim_model_raw_spice.h>
|
||||
#include <sim/sim_model_spice_fallback.h>
|
||||
#include <grid_tricks.h>
|
||||
#include <widgets/grid_icon_text_helpers.h>
|
||||
#include <widgets/std_bitmap_button.h>
|
||||
|
@ -40,6 +41,7 @@
|
|||
#include <locale_io.h>
|
||||
#include <wx/filedlg.h>
|
||||
#include <wx/textfile.h>
|
||||
#include "fmt/format.h"
|
||||
|
||||
using CATEGORY = SIM_MODEL::PARAM::CATEGORY;
|
||||
|
||||
|
@ -227,6 +229,8 @@ bool DIALOG_SIM_MODEL<T_symbol, T_field>::TransferDataToWindow()
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
m_curModelType = curModel().GetType();
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -413,10 +417,15 @@ void DIALOG_SIM_MODEL<T_symbol, T_field>::updateInstanceWidgets()
|
|||
|
||||
m_typeChoice->Enable( !m_useLibraryModelRadioButton->GetValue() || isIbisLoaded() );
|
||||
|
||||
if( dynamic_cast<SIM_MODEL_RAW_SPICE*>( &curModel() ) )
|
||||
if( dynamic_cast<SIM_MODEL_RAW_SPICE*>( &curModel() )
|
||||
|| dynamic_cast<SIM_MODEL_SPICE_FALLBACK*>( &curModel() ) )
|
||||
{
|
||||
m_modelNotebook->SetSelection( 1 );
|
||||
}
|
||||
else
|
||||
{
|
||||
m_modelNotebook->SetSelection( 0 );
|
||||
}
|
||||
|
||||
if( curModel().HasPrimaryValue() )
|
||||
{
|
||||
|
@ -535,9 +544,16 @@ template <typename T_symbol, typename T_field>
|
|||
void DIALOG_SIM_MODEL<T_symbol, T_field>::updateModelCodeTab()
|
||||
{
|
||||
wxString text;
|
||||
wxString pin( _( "Pin" ) );
|
||||
SPICE_ITEM item;
|
||||
item.modelName = m_modelNameChoice->GetStringSelection();
|
||||
|
||||
for( size_t ii = 1; ii <= m_symbol.GetFullPinCount(); ++ii )
|
||||
{
|
||||
item.pinNumbers.push_back( fmt::format( "{}", ii ) );
|
||||
item.pinNetNames.push_back( pin.ToStdString() + fmt::format( "{}", ii ) );
|
||||
}
|
||||
|
||||
if( m_useInstanceModelRadioButton->GetValue() || item.modelName == "" )
|
||||
item.modelName = m_fields.at( REFERENCE_FIELD ).GetText();
|
||||
|
||||
|
|
|
@ -140,7 +140,7 @@ DIALOG_SIM_MODEL_BASE::DIALOG_SIM_MODEL_BASE( wxWindow* parent, wxWindowID id, c
|
|||
|
||||
m_paramGridMgr = new wxPropertyGridManager(m_parametersPanel, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxPGMAN_DEFAULT_STYLE|wxPG_SPLITTER_AUTO_CENTER);
|
||||
m_paramGridMgr->SetExtraStyle( wxPG_EX_MODE_BUTTONS|wxPG_EX_NATIVE_DOUBLE_BUFFERING );
|
||||
m_paramGridMgr->SetMinSize( wxSize( 440,-1 ) );
|
||||
m_paramGridMgr->SetMinSize( wxSize( 500,-1 ) );
|
||||
|
||||
|
||||
m_paramGrid = m_paramGridMgr->AddPage( _("Page"), wxNullBitmap );
|
||||
|
|
|
@ -1493,7 +1493,7 @@
|
|||
<property name="maximum_size"></property>
|
||||
<property name="min_size"></property>
|
||||
<property name="minimize_button">0</property>
|
||||
<property name="minimum_size">440,-1</property>
|
||||
<property name="minimum_size">500,-1</property>
|
||||
<property name="moveable">1</property>
|
||||
<property name="name">m_paramGridMgr</property>
|
||||
<property name="pane_border">1</property>
|
||||
|
|
|
@ -25,6 +25,7 @@
|
|||
#include <sim/sim_library_kibis.h>
|
||||
#include <sim/sim_library.h>
|
||||
#include <sim/sim_library_spice.h>
|
||||
#include <boost/algorithm/string/case_conv.hpp>
|
||||
|
||||
|
||||
std::unique_ptr<SIM_LIBRARY> SIM_LIBRARY::Create( const wxString &aFilePath, REPORTER *aReporter,
|
||||
|
@ -52,11 +53,11 @@ void SIM_LIBRARY::ReadFile( const std::string& aFilePath )
|
|||
|
||||
SIM_MODEL* SIM_LIBRARY::FindModel( const std::string& aModelName ) const
|
||||
{
|
||||
std::string lowerName = boost::to_lower_copy( aModelName );
|
||||
|
||||
for( int i = 0; i < static_cast<int>( m_modelNames.size() ); ++i )
|
||||
{
|
||||
const std::string& modelName = m_modelNames.at( i );
|
||||
|
||||
if( modelName == aModelName )
|
||||
if( boost::to_lower_copy( m_modelNames.at( i ) ) == lowerName )
|
||||
return m_models.at( i ).get();
|
||||
}
|
||||
|
||||
|
|
|
@ -49,6 +49,7 @@
|
|||
#include <pegtl/contrib/parse_tree.hpp>
|
||||
|
||||
#include <iterator>
|
||||
#include "sim_model_spice_fallback.h"
|
||||
|
||||
using TYPE = SIM_MODEL::TYPE;
|
||||
|
||||
|
@ -442,6 +443,13 @@ void SIM_MODEL::WriteFields( std::vector<LIB_FIELD>& aFields ) const
|
|||
}
|
||||
|
||||
|
||||
std::unique_ptr<SIM_MODEL> SIM_MODEL::CreateFallback( TYPE aType, const std::string& aSpiceCode )
|
||||
{
|
||||
std::unique_ptr<SIM_MODEL> model( new SIM_MODEL_SPICE_FALLBACK( aType, aSpiceCode ) );
|
||||
return model;
|
||||
}
|
||||
|
||||
|
||||
std::unique_ptr<SIM_MODEL> SIM_MODEL::Create( TYPE aType, const std::vector<LIB_PIN*>& aPins )
|
||||
{
|
||||
std::unique_ptr<SIM_MODEL> model = Create( aType );
|
||||
|
@ -455,7 +463,12 @@ std::unique_ptr<SIM_MODEL> SIM_MODEL::Create( TYPE aType, const std::vector<LIB_
|
|||
std::unique_ptr<SIM_MODEL> SIM_MODEL::Create( const SIM_MODEL& aBaseModel,
|
||||
const std::vector<LIB_PIN*>& aPins)
|
||||
{
|
||||
std::unique_ptr<SIM_MODEL> model = Create( aBaseModel.GetType() );
|
||||
std::unique_ptr<SIM_MODEL> model;
|
||||
|
||||
if( dynamic_cast<const SIM_MODEL_SPICE_FALLBACK*>( &aBaseModel ) )
|
||||
model = CreateFallback( aBaseModel.GetType() );
|
||||
else
|
||||
model = Create( aBaseModel.GetType() );
|
||||
|
||||
try
|
||||
{
|
||||
|
@ -482,7 +495,12 @@ std::unique_ptr<SIM_MODEL> SIM_MODEL::Create( const SIM_MODEL& aBaseModel,
|
|||
if( type == TYPE::NONE )
|
||||
type = aBaseModel.GetType();
|
||||
|
||||
std::unique_ptr<SIM_MODEL> model = Create( type );
|
||||
std::unique_ptr<SIM_MODEL> model;
|
||||
|
||||
if( dynamic_cast<const SIM_MODEL_SPICE_FALLBACK*>( &aBaseModel ) )
|
||||
model = CreateFallback( type );
|
||||
else
|
||||
model = Create( type );
|
||||
|
||||
try
|
||||
{
|
||||
|
@ -655,13 +673,11 @@ void SIM_MODEL::SetPinSymbolPinNumber( int aPinIndex, const std::string& aSymbol
|
|||
void SIM_MODEL::SetPinSymbolPinNumber( const std::string& aPinName,
|
||||
const std::string& aSymbolPinNumber )
|
||||
{
|
||||
const std::vector<std::reference_wrapper<const PIN>> pins = GetPins();
|
||||
|
||||
for( int ii = 0; ii < (int) pins.size(); ++ii )
|
||||
for( PIN& pin : m_pins )
|
||||
{
|
||||
if( pins.at( ii ).get().name == aPinName )
|
||||
if( pin.name == aPinName )
|
||||
{
|
||||
SetPinSymbolPinNumber( ii, aSymbolPinNumber );
|
||||
pin.symbolPinNumber = aSymbolPinNumber;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
@ -678,7 +694,7 @@ void SIM_MODEL::SetPinSymbolPinNumber( const std::string& aPinName,
|
|||
GetTypeInfo().fieldValue ) );
|
||||
}
|
||||
|
||||
SetPinSymbolPinNumber( --aPinIndex /* convert to 0-based */, aSymbolPinNumber );
|
||||
m_pins[ --aPinIndex /* convert to 0-based */ ].symbolPinNumber = aSymbolPinNumber;
|
||||
}
|
||||
|
||||
|
||||
|
@ -915,7 +931,7 @@ SIM_MODEL::SIM_MODEL( TYPE aType, std::unique_ptr<SPICE_GENERATOR> aSpiceGenerat
|
|||
}
|
||||
|
||||
|
||||
void SIM_MODEL::CreatePins( const std::vector<LIB_PIN*>& aSymbolPins )
|
||||
void SIM_MODEL::createPins( const std::vector<LIB_PIN*>& aSymbolPins )
|
||||
{
|
||||
// Default pin sequence: model pins are the same as symbol pins.
|
||||
// Excess model pins are set as Not Connected.
|
||||
|
@ -952,7 +968,7 @@ void SIM_MODEL::doReadDataFields( const std::vector<T>* aFields,
|
|||
{
|
||||
m_serializer->ParseEnable( GetFieldValue( aFields, ENABLE_FIELD ) );
|
||||
|
||||
CreatePins( aPins );
|
||||
createPins( aPins );
|
||||
m_serializer->ParsePins( GetFieldValue( aFields, PINS_FIELD ) );
|
||||
|
||||
std::string paramsField = GetFieldValue( aFields, PARAMS_FIELD );
|
||||
|
@ -1476,7 +1492,7 @@ void SIM_MODEL::MigrateSimModel( T_symbol& aSymbol, const PROJECT* aProject )
|
|||
// Try to generate a default pin map from the SIM_MODEL's pins; if that fails,
|
||||
// generate one from the symbol's pins
|
||||
|
||||
model.model.SIM_MODEL::CreatePins( sourcePins );
|
||||
model.model.SIM_MODEL::createPins( sourcePins );
|
||||
pinMap = wxString( model.model.Serializer().GeneratePins() );
|
||||
|
||||
if( pinMap.IsEmpty() )
|
||||
|
@ -1536,7 +1552,7 @@ void SIM_MODEL::MigrateSimModel( T_symbol& aSymbol, const PROJECT* aProject )
|
|||
if( pinMap.IsEmpty() )
|
||||
{
|
||||
// Generate a default pin map from the SIM_MODEL's pins
|
||||
model->CreatePins( sourcePins );
|
||||
model->createPins( sourcePins );
|
||||
pinMap = wxString( model->Serializer().GeneratePins() );
|
||||
}
|
||||
}
|
||||
|
|
|
@ -414,6 +414,9 @@ public:
|
|||
static std::unique_ptr<SIM_MODEL> Create( const std::vector<T>& aFields,
|
||||
const std::vector<LIB_PIN*>& aPins );
|
||||
|
||||
static std::unique_ptr<SIM_MODEL> CreateFallback( TYPE aType,
|
||||
const std::string& aSpiceCode = "" );
|
||||
|
||||
template <typename T>
|
||||
static std::string GetFieldValue( const std::vector<T>* aFields, const std::string& aFieldName,
|
||||
bool aResolve = true );
|
||||
|
@ -476,7 +479,8 @@ public:
|
|||
std::vector<std::reference_wrapper<const PIN>> GetPins() const;
|
||||
|
||||
void SetPinSymbolPinNumber( int aPinIndex, const std::string& aSymbolPinNumber );
|
||||
void SetPinSymbolPinNumber( const std::string& aPinName, const std::string& aSymbolPinNumber );
|
||||
virtual void SetPinSymbolPinNumber( const std::string& aPinName,
|
||||
const std::string& aSymbolPinNumber );
|
||||
|
||||
|
||||
int GetParamCount() const { return static_cast<int>( m_params.size() ); }
|
||||
|
@ -534,7 +538,7 @@ protected:
|
|||
SIM_MODEL( TYPE aType, std::unique_ptr<SPICE_GENERATOR> aSpiceGenerator,
|
||||
std::unique_ptr<SIM_MODEL_SERIALIZER> aSerializer );
|
||||
|
||||
virtual void CreatePins( const std::vector<LIB_PIN*>& aSymbolPins );
|
||||
void createPins( const std::vector<LIB_PIN*>& aSymbolPins );
|
||||
|
||||
virtual int doFindParam( const std::string& aParamName ) const;
|
||||
|
||||
|
@ -551,6 +555,7 @@ private:
|
|||
|
||||
protected:
|
||||
std::vector<PARAM> m_params;
|
||||
std::vector<PIN> m_pins;
|
||||
const SIM_MODEL* m_baseModel;
|
||||
std::unique_ptr<SIM_MODEL_SERIALIZER> m_serializer;
|
||||
|
||||
|
@ -558,7 +563,6 @@ private:
|
|||
std::unique_ptr<SPICE_GENERATOR> m_spiceGenerator;
|
||||
|
||||
const TYPE m_type;
|
||||
std::vector<PIN> m_pins;
|
||||
bool m_isEnabled;
|
||||
bool m_isStoredInValue;
|
||||
};
|
||||
|
|
|
@ -24,7 +24,6 @@
|
|||
#include <sim/kibis/kibis.h>
|
||||
#include <sim/sim_model_kibis.h>
|
||||
#include <sim/sim_library_kibis.h>
|
||||
#include <common.h>
|
||||
#include <fmt/core.h>
|
||||
#include <wx/filename.h>
|
||||
#include <kiway.h>
|
||||
|
@ -297,17 +296,6 @@ SIM_MODEL_KIBIS::SIM_MODEL_KIBIS( TYPE aType, SIM_MODEL_KIBIS& aSource,
|
|||
}
|
||||
|
||||
|
||||
void SIM_MODEL_KIBIS::CreatePins( const std::vector<LIB_PIN*>& aSymbolPins )
|
||||
{
|
||||
SIM_MODEL::CreatePins( aSymbolPins );
|
||||
|
||||
// Reset the pins to Not Connected. Linear order is not as common, and reordering the pins is
|
||||
// more effort in the GUI than assigning them from scratch.
|
||||
for( int pinIndex = 0; pinIndex < GetPinCount(); ++pinIndex )
|
||||
SetPinSymbolPinNumber( pinIndex, "" );
|
||||
}
|
||||
|
||||
|
||||
bool SIM_MODEL_KIBIS::ChangePin( const SIM_LIBRARY_KIBIS& aLib, std::string aPinNumber )
|
||||
{
|
||||
KIBIS_COMPONENT* kcomp = aLib.m_kibis.GetComponent( std::string( GetComponentName() ) );
|
||||
|
|
|
@ -93,9 +93,6 @@ public:
|
|||
bool CanDifferential() const { return m_enableDiff; } ;
|
||||
bool m_enableDiff;
|
||||
|
||||
protected:
|
||||
void CreatePins( const std::vector<LIB_PIN*>& aSymbolPins ) override;
|
||||
|
||||
private:
|
||||
bool requiresSpiceModelLine() const override { return true; }
|
||||
|
||||
|
|
|
@ -122,10 +122,19 @@ SIM_MODEL_RAW_SPICE::SIM_MODEL_RAW_SPICE() :
|
|||
}
|
||||
|
||||
|
||||
void SIM_MODEL_RAW_SPICE::CreatePins( const std::vector<LIB_PIN*>& aSymbolPins )
|
||||
void SIM_MODEL_RAW_SPICE::SetPinSymbolPinNumber( const std::string& aPinName,
|
||||
const std::string& aSymbolPinNumber )
|
||||
{
|
||||
for( unsigned symbolPinIndex = 0; symbolPinIndex < aSymbolPins.size(); ++symbolPinIndex )
|
||||
AddPin( { fmt::format( "{}", symbolPinIndex + 1 ), "" } );
|
||||
for( PIN& pin : m_pins )
|
||||
{
|
||||
if( pin.name == aPinName )
|
||||
{
|
||||
pin.symbolPinNumber = aSymbolPinNumber;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
m_pins.push_back( { aPinName, aSymbolPinNumber } );
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -74,8 +74,8 @@ public:
|
|||
return m_spiceCode;
|
||||
}
|
||||
|
||||
protected:
|
||||
void CreatePins( const std::vector<LIB_PIN*>& aSymbolPins ) override;
|
||||
void SetPinSymbolPinNumber( const std::string& aPinName,
|
||||
const std::string& aSymbolPinNumber ) override;
|
||||
|
||||
private:
|
||||
static std::vector<PARAM::INFO> makeParamInfos();
|
||||
|
|
|
@ -25,7 +25,7 @@
|
|||
// Include simulator headers after wxWidgets headers to avoid conflicts with Windows headers
|
||||
// (especially on msys2 + wxWidgets 3.0.x)
|
||||
#include <sim/sim_model_spice.h>
|
||||
#include <sim/sim_model_raw_spice.h>
|
||||
#include <sim/sim_model_spice_fallback.h>
|
||||
#include <sim/spice_model_parser.h>
|
||||
#include <sim/sim_library_spice.h>
|
||||
|
||||
|
@ -46,47 +46,49 @@ std::string SPICE_GENERATOR_SPICE::Preview( const SPICE_ITEM& aItem ) const
|
|||
item.refName = "";
|
||||
std::string itemLine = ItemLine( item );
|
||||
|
||||
if( spiceCode != "" )
|
||||
spiceCode.append( "\n" );
|
||||
if( spiceCode != "" && itemLine != "" )
|
||||
spiceCode.append( "\n\n" );
|
||||
|
||||
spiceCode.append( itemLine );
|
||||
return boost::trim_copy( spiceCode );
|
||||
}
|
||||
|
||||
|
||||
std::unique_ptr<SIM_MODEL> SIM_MODEL_SPICE::Create( const SIM_LIBRARY_SPICE& aLibrary,
|
||||
const std::string& aSpiceCode )
|
||||
std::unique_ptr<SIM_MODEL_SPICE> SIM_MODEL_SPICE::Create( const SIM_LIBRARY_SPICE& aLibrary,
|
||||
const std::string& aSpiceCode )
|
||||
{
|
||||
SIM_MODEL::TYPE modelType = SPICE_MODEL_PARSER::ReadType( aLibrary, aSpiceCode );
|
||||
SIM_MODEL* model = SIM_MODEL::Create( modelType ).release();
|
||||
SIM_MODEL::TYPE modelType = SPICE_MODEL_PARSER::ReadType( aLibrary, aSpiceCode );
|
||||
std::unique_ptr<SIM_MODEL> model = SIM_MODEL::Create( modelType );
|
||||
|
||||
if( SIM_MODEL_SPICE* spiceModel = dynamic_cast<SIM_MODEL_SPICE*>( model ) )
|
||||
if( SIM_MODEL_SPICE* spiceModel = dynamic_cast<SIM_MODEL_SPICE*>( model.release() ) )
|
||||
{
|
||||
spiceModel->m_spiceModelParser->ReadModel( aLibrary, aSpiceCode );
|
||||
return std::unique_ptr<SIM_MODEL_SPICE>( spiceModel );
|
||||
}
|
||||
else if( SIM_MODEL_RAW_SPICE* rawSpice = dynamic_cast<SIM_MODEL_RAW_SPICE*>( model ) )
|
||||
{
|
||||
rawSpice->SetSource( aSpiceCode );
|
||||
return std::unique_ptr<SIM_MODEL_RAW_SPICE>( rawSpice );
|
||||
try
|
||||
{
|
||||
spiceModel->m_spiceModelParser->ReadModel( aLibrary, aSpiceCode );
|
||||
return std::unique_ptr<SIM_MODEL_SPICE>( spiceModel );
|
||||
}
|
||||
catch( const IO_ERROR& e )
|
||||
{
|
||||
// Fall back to raw spice code
|
||||
}
|
||||
}
|
||||
|
||||
delete model;
|
||||
THROW_IO_ERROR( "Could not determine Spice model modelType" );
|
||||
// Fall back to raw spice code
|
||||
return std::make_unique<SIM_MODEL_SPICE_FALLBACK>( modelType, aSpiceCode );
|
||||
}
|
||||
|
||||
|
||||
SIM_MODEL_SPICE::SIM_MODEL_SPICE( TYPE aType, std::unique_ptr<SPICE_GENERATOR> aSpiceGenerator ) :
|
||||
SIM_MODEL( aType, std::move( aSpiceGenerator ) ),
|
||||
m_spiceModelParser( std::make_unique<SPICE_MODEL_PARSER>( *this ) )
|
||||
SIM_MODEL( aType, std::move( aSpiceGenerator ) ),
|
||||
m_spiceModelParser( std::make_unique<SPICE_MODEL_PARSER>( *this ) )
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
SIM_MODEL_SPICE::SIM_MODEL_SPICE( TYPE aType, std::unique_ptr<SPICE_GENERATOR> aSpiceGenerator,
|
||||
std::unique_ptr<SPICE_MODEL_PARSER> aSpiceModelParser ) :
|
||||
SIM_MODEL( aType, std::move( aSpiceGenerator ) ),
|
||||
m_spiceModelParser( std::move( aSpiceModelParser ) )
|
||||
SIM_MODEL( aType, std::move( aSpiceGenerator ) ),
|
||||
m_spiceModelParser( std::move( aSpiceModelParser ) )
|
||||
{
|
||||
}
|
||||
|
||||
|
|
|
@ -47,8 +47,8 @@ public:
|
|||
friend class SPICE_GENERATOR_SPICE;
|
||||
friend class SPICE_MODEL_PARSER;
|
||||
|
||||
static std::unique_ptr<SIM_MODEL> Create( const SIM_LIBRARY_SPICE& aLibrary,
|
||||
const std::string& aSpiceCode );
|
||||
static std::unique_ptr<SIM_MODEL_SPICE> Create( const SIM_LIBRARY_SPICE& aLibrary,
|
||||
const std::string& aSpiceCode );
|
||||
|
||||
SIM_MODEL_SPICE( TYPE aType,
|
||||
std::unique_ptr<SPICE_GENERATOR> aSpiceGenerator );
|
||||
|
|
|
@ -0,0 +1,50 @@
|
|||
/*
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2022 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, you may find one here:
|
||||
* https://www.gnu.org/licenses/gpl-3.0.html
|
||||
* or you may search the http://www.gnu.org website for the version 3 license,
|
||||
* or you may write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
*/
|
||||
|
||||
#include <sim/sim_model_spice_fallback.h>
|
||||
#include <fmt/format.h>
|
||||
|
||||
|
||||
SIM_MODEL_SPICE_FALLBACK::SIM_MODEL_SPICE_FALLBACK( TYPE aType, const std::string& aRawSpiceCode ) :
|
||||
SIM_MODEL_SPICE( aType, std::make_unique<SPICE_GENERATOR_SPICE>( *this ) )
|
||||
{
|
||||
m_spiceCode = aRawSpiceCode;
|
||||
}
|
||||
|
||||
|
||||
void SIM_MODEL_SPICE_FALLBACK::SetPinSymbolPinNumber( const std::string& aPinName,
|
||||
const std::string& aSymbolPinNumber )
|
||||
{
|
||||
for( PIN& pin : m_pins )
|
||||
{
|
||||
if( pin.name == aPinName )
|
||||
{
|
||||
pin.symbolPinNumber = aSymbolPinNumber;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
m_pins.push_back( { aPinName, aSymbolPinNumber } );
|
||||
}
|
||||
|
||||
|
|
@ -0,0 +1,39 @@
|
|||
/*
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2022 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, you may find one here:
|
||||
* https://www.gnu.org/licenses/gpl-3.0.html
|
||||
* or you may search the http://www.gnu.org website for the version 3 license,
|
||||
* or you may write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
*/
|
||||
|
||||
#ifndef SIM_MODEL_SPICE_FALLBACK_H
|
||||
#define SIM_MODEL_SPICE_FALLBACK_H
|
||||
|
||||
#include <sim/sim_model_spice.h>
|
||||
|
||||
|
||||
class SIM_MODEL_SPICE_FALLBACK : public SIM_MODEL_SPICE
|
||||
{
|
||||
public:
|
||||
SIM_MODEL_SPICE_FALLBACK( TYPE aType, const std::string& aRawSpiceCode = "" );
|
||||
|
||||
void SetPinSymbolPinNumber( const std::string& aPinName,
|
||||
const std::string& aSymbolPinNumber ) override;
|
||||
};
|
||||
|
||||
#endif // SIM_MODEL_SPICE_FALLBACK_H
|
|
@ -136,8 +136,7 @@ void SPICE_MODEL_PARSER_SUBCKT::ReadModel( const SIM_LIBRARY_SPICE& aLibrary,
|
|||
|
||||
|
||||
SIM_MODEL_SUBCKT::SIM_MODEL_SUBCKT() :
|
||||
SIM_MODEL_SPICE( TYPE::SUBCKT,
|
||||
std::make_unique<SPICE_GENERATOR_SUBCKT>( *this ),
|
||||
SIM_MODEL_SPICE( TYPE::SUBCKT, std::make_unique<SPICE_GENERATOR_SUBCKT>( *this ),
|
||||
std::make_unique<SPICE_MODEL_PARSER_SUBCKT>( *this ) )
|
||||
{
|
||||
}
|
||||
|
@ -156,13 +155,3 @@ void SIM_MODEL_SUBCKT::SetBaseModel( const SIM_MODEL& aBaseModel )
|
|||
AddParam( param.info );
|
||||
}
|
||||
|
||||
|
||||
void SIM_MODEL_SUBCKT::CreatePins( const std::vector<LIB_PIN*>& aSymbolPins )
|
||||
{
|
||||
SIM_MODEL::CreatePins( aSymbolPins );
|
||||
|
||||
// Reset the pins to Not Connected. Linear order is not as common, and reordering the pins is
|
||||
// more effort in the GUI than assigning them from scratch.
|
||||
for( int pinIndex = 0; pinIndex < GetPinCount(); ++pinIndex )
|
||||
SetPinSymbolPinNumber( pinIndex, "" );
|
||||
}
|
||||
|
|
|
@ -57,9 +57,6 @@ public:
|
|||
|
||||
void SetBaseModel( const SIM_MODEL& aBaseModel ) override;
|
||||
|
||||
protected:
|
||||
void CreatePins( const std::vector<LIB_PIN*>& aSymbolPins ) override;
|
||||
|
||||
private:
|
||||
bool requiresSpiceModelLine() const override { return true; }
|
||||
|
||||
|
|
|
@ -137,7 +137,9 @@ std::string SPICE_GENERATOR::ItemPins( const SPICE_ITEM& aItem ) const
|
|||
pin.symbolPinNumber );
|
||||
|
||||
if( it == aItem.pinNumbers.end() )
|
||||
{
|
||||
result.append( fmt::format( " NC-{}-{}", aItem.refName, ncCounter++ ) );
|
||||
}
|
||||
else
|
||||
{
|
||||
long symbolPinIndex = std::distance( aItem.pinNumbers.begin(), it );
|
||||
|
|
Loading…
Reference in New Issue