Gracefully handle spice models not recognized by KiCad.

Fixes https://gitlab.com/kicad/code/kicad/issues/12689
This commit is contained in:
Jeff Young 2022-12-04 19:43:57 +00:00
parent f29f0c5c0a
commit 1855885d1e
7 changed files with 57 additions and 60 deletions

View File

@ -375,6 +375,11 @@ void DIALOG_SIM_MODEL<T>::updateInstanceWidgets()
m_typeChoice->Enable( !m_useLibraryModelRadioButton->GetValue() || isIbisLoaded() ); m_typeChoice->Enable( !m_useLibraryModelRadioButton->GetValue() || isIbisLoaded() );
if( dynamic_cast<SIM_MODEL_RAW_SPICE*>( &curModel() ) )
m_modelNotebook->SetSelection( 1 );
else
m_modelNotebook->SetSelection( 0 );
if( curModel().HasPrimaryValue() ) if( curModel().HasPrimaryValue() )
{ {
const SIM_MODEL::PARAM& primary = curModel().GetParam( 0 ); const SIM_MODEL::PARAM& primary = curModel().GetParam( 0 );
@ -489,46 +494,21 @@ void DIALOG_SIM_MODEL<T>::updateModelParamsTab()
template <typename T> template <typename T>
void DIALOG_SIM_MODEL<T>::updateModelCodeTab() void DIALOG_SIM_MODEL<T>::updateModelCodeTab()
{ {
wxString text;
SPICE_ITEM item; SPICE_ITEM item;
item.modelName = m_modelNameCombobox->GetStringSelection(); item.modelName = m_modelNameCombobox->GetStringSelection();
if( m_useInstanceModelRadioButton->GetValue() || item.modelName == "" ) if( m_useInstanceModelRadioButton->GetValue() || item.modelName == "" )
item.modelName = m_fields.at( REFERENCE_FIELD ).GetText(); item.modelName = m_fields.at( REFERENCE_FIELD ).GetText();
m_codePreview->SetEditable( true ); // ??? SIM_MODEL& model = curModel();
if( dynamic_cast<SIM_MODEL_RAW_SPICE*>( &curModel() ) ) text << model.SpiceGenerator().Preview( item );
{
// For raw Spice models display the whole file instead.
wxString path = curModel().FindParam( "lib" )->value->ToString(); if( SIM_MODEL_RAW_SPICE* rawSpice = dynamic_cast<SIM_MODEL_RAW_SPICE*>( &model ) )
wxString absolutePath = Prj().AbsolutePath( path ); text << rawSpice->GetSource();
wxTextFile file;
wxString text;
text << curModel().SpiceGenerator().Preview( item );
text << "\n";
text << "--- FILE SOURCE (" << path << ") ---\n";
text << "\n";
if( wxFileExists( absolutePath ) && file.Open( absolutePath ) )
{
for( text << file.GetFirstLine() << "\n";
!file.Eof();
text << file.GetNextLine() << "\n" )
{
}
file.Close();
m_codePreview->SetText( text ); m_codePreview->SetText( text );
}
}
else
{
m_codePreview->SetText( curModel().SpiceGenerator().Preview( item ) );
}
m_codePreview->SetEditable( false ); // ???
m_wasCodePreviewUpdated = true; m_wasCodePreviewUpdated = true;
} }
@ -644,7 +624,7 @@ void DIALOG_SIM_MODEL<T>::loadLibrary( const wxString& aLibraryPath, bool aForce
try try
{ {
m_libraryModelsMgr.SetLibrary( std::string( aLibraryPath.ToUTF8() ), m_libraryModelsMgr.SetLibrary( std::string( aLibraryPath.ToUTF8() ),
&( dlg.m_messagePanel->Reporter() ) ); &dlg.m_messagePanel->Reporter() );
} }
catch( const IO_ERROR& e ) catch( const IO_ERROR& e )
{ {
@ -654,7 +634,9 @@ void DIALOG_SIM_MODEL<T>::loadLibrary( const wxString& aLibraryPath, bool aForce
dlg.ShowQuasiModal(); dlg.ShowQuasiModal();
} }
else else
{
DisplayErrorMessage( this, e.What() ); DisplayErrorMessage( this, e.What() );
}
return; return;
} }
@ -887,7 +869,9 @@ SIM_MODEL& DIALOG_SIM_MODEL<T>::curModel() const
return m_libraryModelsMgr.GetModels().at( m_modelNameCombobox->GetSelection() ).get(); return m_libraryModelsMgr.GetModels().at( m_modelNameCombobox->GetSelection() ).get();
} }
else else
{
return m_builtinModelsMgr.GetModels().at( static_cast<int>( m_curModelType ) ); return m_builtinModelsMgr.GetModels().at( static_cast<int>( m_curModelType ) );
}
} }
@ -1064,11 +1048,7 @@ void DIALOG_SIM_MODEL<T>::onModelNameCombobox( wxCommandEvent& aEvent )
wxArrayString pinLabels; wxArrayString pinLabels;
SIM_MODEL_KIBIS* modelkibis = dynamic_cast<SIM_MODEL_KIBIS*>( &curModel() ); SIM_MODEL_KIBIS* modelkibis = dynamic_cast<SIM_MODEL_KIBIS*>( &curModel() );
if( !modelkibis ) wxCHECK2( modelkibis, return );
{
wxFAIL;
return;
}
for( std::pair<wxString, wxString> strs : modelkibis->GetIbisPins() ) for( std::pair<wxString, wxString> strs : modelkibis->GetIbisPins() )
pinLabels.Add( strs.first + wxT( " - " ) + strs.second ); pinLabels.Add( strs.first + wxT( " - " ) + strs.second );

View File

@ -125,8 +125,8 @@ DIALOG_SIM_MODEL_BASE::DIALOG_SIM_MODEL_BASE( wxWindow* parent, wxWindowID id, c
bSizerMargins->Add( fgSizer16, 0, wxEXPAND|wxLEFT, 24 ); bSizerMargins->Add( fgSizer16, 0, wxEXPAND|wxLEFT, 24 );
m_notebook4 = new wxNotebook( m_modelPanel, wxID_ANY, wxDefaultPosition, wxDefaultSize, 0 ); m_modelNotebook = new wxNotebook( m_modelPanel, wxID_ANY, wxDefaultPosition, wxDefaultSize, 0 );
m_parametersPanel = new wxPanel( m_notebook4, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL ); m_parametersPanel = new wxPanel( m_modelNotebook, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL );
m_parametersPanel->SetMinSize( wxSize( 500,-1 ) ); m_parametersPanel->SetMinSize( wxSize( 500,-1 ) );
wxBoxSizer* bSizer12; wxBoxSizer* bSizer12;
@ -142,8 +142,8 @@ DIALOG_SIM_MODEL_BASE::DIALOG_SIM_MODEL_BASE( wxWindow* parent, wxWindowID id, c
m_parametersPanel->SetSizer( bSizer12 ); m_parametersPanel->SetSizer( bSizer12 );
m_parametersPanel->Layout(); m_parametersPanel->Layout();
bSizer12->Fit( m_parametersPanel ); bSizer12->Fit( m_parametersPanel );
m_notebook4->AddPage( m_parametersPanel, _("Parameters"), true ); m_modelNotebook->AddPage( m_parametersPanel, _("Parameters"), true );
m_codePanel = new wxPanel( m_notebook4, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL ); m_codePanel = new wxPanel( m_modelNotebook, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL );
wxBoxSizer* bSizer5; wxBoxSizer* bSizer5;
bSizer5 = new wxBoxSizer( wxVERTICAL ); bSizer5 = new wxBoxSizer( wxVERTICAL );
@ -189,9 +189,9 @@ DIALOG_SIM_MODEL_BASE::DIALOG_SIM_MODEL_BASE( wxWindow* parent, wxWindowID id, c
m_codePanel->SetSizer( bSizer5 ); m_codePanel->SetSizer( bSizer5 );
m_codePanel->Layout(); m_codePanel->Layout();
bSizer5->Fit( m_codePanel ); bSizer5->Fit( m_codePanel );
m_notebook4->AddPage( m_codePanel, _("Code"), false ); m_modelNotebook->AddPage( m_codePanel, _("Code"), false );
bSizerMargins->Add( m_notebook4, 1, wxEXPAND|wxTOP, 10 ); bSizerMargins->Add( m_modelNotebook, 1, wxEXPAND|wxTOP, 10 );
m_saveInValueCheckbox = new wxCheckBox( m_modelPanel, wxID_ANY, _("Save {} in Value field as \"{}\""), wxDefaultPosition, wxDefaultSize, 0 ); m_saveInValueCheckbox = new wxCheckBox( m_modelPanel, wxID_ANY, _("Save {} in Value field as \"{}\""), wxDefaultPosition, wxDefaultSize, 0 );
bSizerMargins->Add( m_saveInValueCheckbox, 0, wxALL, 6 ); bSizerMargins->Add( m_saveInValueCheckbox, 0, wxALL, 6 );

View File

@ -1372,7 +1372,7 @@
<property name="minimize_button">0</property> <property name="minimize_button">0</property>
<property name="minimum_size"></property> <property name="minimum_size"></property>
<property name="moveable">1</property> <property name="moveable">1</property>
<property name="name">m_notebook4</property> <property name="name">m_modelNotebook</property>
<property name="pane_border">1</property> <property name="pane_border">1</property>
<property name="pane_position"></property> <property name="pane_position"></property>
<property name="pane_size"></property> <property name="pane_size"></property>

View File

@ -69,7 +69,7 @@ class DIALOG_SIM_MODEL_BASE : public DIALOG_SHIM
wxChoice* m_deviceTypeChoice; wxChoice* m_deviceTypeChoice;
wxStaticText* m_staticTextSpiceType; wxStaticText* m_staticTextSpiceType;
wxChoice* m_typeChoice; wxChoice* m_typeChoice;
wxNotebook* m_notebook4; wxNotebook* m_modelNotebook;
wxPanel* m_parametersPanel; wxPanel* m_parametersPanel;
wxPropertyGridManager* m_paramGridMgr; wxPropertyGridManager* m_paramGridMgr;
wxPropertyGridPage* m_paramGrid; wxPropertyGridPage* m_paramGrid;

View File

@ -64,6 +64,16 @@ public:
SIM_MODEL_RAW_SPICE(); SIM_MODEL_RAW_SPICE();
void SetSource( const std::string& aSpiceSource ) { m_spiceCode = aSpiceSource; }
std::string GetSource() const
{
if( m_baseModel )
return static_cast<const SIM_MODEL_RAW_SPICE*>( m_baseModel )->GetSource();
return m_spiceCode;
}
protected: protected:
void CreatePins( unsigned aSymbolPinCount ) override; void CreatePins( unsigned aSymbolPinCount ) override;
@ -71,7 +81,8 @@ private:
static std::vector<PARAM::INFO> makeParamInfos(); static std::vector<PARAM::INFO> makeParamInfos();
bool requiresSpiceModelLine() const override { return false; } bool requiresSpiceModelLine() const override { return false; }
std::vector<std::unique_ptr<PARAM::INFO>> m_paramInfos; private:
std::string m_spiceCode;
}; };
#endif // SIM_MODEL_RAW_SPICE_H #endif // SIM_MODEL_RAW_SPICE_H

View File

@ -54,30 +54,36 @@ std::string SPICE_GENERATOR_SPICE::Preview( const SPICE_ITEM& aItem ) const
} }
std::unique_ptr<SIM_MODEL_SPICE> SIM_MODEL_SPICE::Create( const SIM_LIBRARY_SPICE& aLibrary, std::unique_ptr<SIM_MODEL> SIM_MODEL_SPICE::Create( const SIM_LIBRARY_SPICE& aLibrary,
const std::string& aSpiceCode ) const std::string& aSpiceCode )
{ {
auto model = dynamic_cast<SIM_MODEL_SPICE*>( SIM_MODEL::TYPE modelType = SPICE_MODEL_PARSER::ReadType( aLibrary, aSpiceCode );
SIM_MODEL::Create( SPICE_MODEL_PARSER::ReadType( aLibrary, aSpiceCode ) ).release() ); SIM_MODEL* model = SIM_MODEL::Create( modelType ).release();
if( !model ) if( SIM_MODEL_SPICE* spiceModel = dynamic_cast<SIM_MODEL_SPICE*>( model ) )
THROW_IO_ERROR( "Could not determine Spice model type" ); {
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 );
}
model->m_spiceModelParser->ReadModel( aLibrary, aSpiceCode ); delete model;
return std::unique_ptr<SIM_MODEL_SPICE>( model ); THROW_IO_ERROR( "Could not determine Spice model modelType" );
} }
SIM_MODEL_SPICE::SIM_MODEL_SPICE( TYPE aType, SIM_MODEL_SPICE::SIM_MODEL_SPICE( TYPE aType, std::unique_ptr<SPICE_GENERATOR> aSpiceGenerator ) :
std::unique_ptr<SPICE_GENERATOR> aSpiceGenerator ) :
SIM_MODEL( aType, std::move( aSpiceGenerator ) ), SIM_MODEL( aType, std::move( aSpiceGenerator ) ),
m_spiceModelParser( std::make_unique<SPICE_MODEL_PARSER>( *this ) ) m_spiceModelParser( std::make_unique<SPICE_MODEL_PARSER>( *this ) )
{ {
} }
SIM_MODEL_SPICE::SIM_MODEL_SPICE( TYPE aType, SIM_MODEL_SPICE::SIM_MODEL_SPICE( TYPE aType, std::unique_ptr<SPICE_GENERATOR> aSpiceGenerator,
std::unique_ptr<SPICE_GENERATOR> aSpiceGenerator,
std::unique_ptr<SPICE_MODEL_PARSER> aSpiceModelParser ) : std::unique_ptr<SPICE_MODEL_PARSER> aSpiceModelParser ) :
SIM_MODEL( aType, std::move( aSpiceGenerator ) ), SIM_MODEL( aType, std::move( aSpiceGenerator ) ),
m_spiceModelParser( std::move( aSpiceModelParser ) ) m_spiceModelParser( std::move( aSpiceModelParser ) )

View File

@ -47,7 +47,7 @@ public:
friend class SPICE_GENERATOR_SPICE; friend class SPICE_GENERATOR_SPICE;
friend class SPICE_MODEL_PARSER; friend class SPICE_MODEL_PARSER;
static std::unique_ptr<SIM_MODEL_SPICE> Create( const SIM_LIBRARY_SPICE& aLibrary, static std::unique_ptr<SIM_MODEL> Create( const SIM_LIBRARY_SPICE& aLibrary,
const std::string& aSpiceCode ); const std::string& aSpiceCode );
SIM_MODEL_SPICE( TYPE aType, SIM_MODEL_SPICE( TYPE aType,