From 1855885d1eb1e3accb52974a2489643a57b1261c Mon Sep 17 00:00:00 2001 From: Jeff Young Date: Sun, 4 Dec 2022 19:43:57 +0000 Subject: [PATCH] Gracefully handle spice models not recognized by KiCad. Fixes https://gitlab.com/kicad/code/kicad/issues/12689 --- eeschema/dialogs/dialog_sim_model.cpp | 54 +++++++--------------- eeschema/dialogs/dialog_sim_model_base.cpp | 12 ++--- eeschema/dialogs/dialog_sim_model_base.fbp | 2 +- eeschema/dialogs/dialog_sim_model_base.h | 2 +- eeschema/sim/sim_model_raw_spice.h | 13 +++++- eeschema/sim/sim_model_spice.cpp | 30 +++++++----- eeschema/sim/sim_model_spice.h | 4 +- 7 files changed, 57 insertions(+), 60 deletions(-) diff --git a/eeschema/dialogs/dialog_sim_model.cpp b/eeschema/dialogs/dialog_sim_model.cpp index 5cade2d821..fb06de5b28 100644 --- a/eeschema/dialogs/dialog_sim_model.cpp +++ b/eeschema/dialogs/dialog_sim_model.cpp @@ -375,6 +375,11 @@ void DIALOG_SIM_MODEL::updateInstanceWidgets() m_typeChoice->Enable( !m_useLibraryModelRadioButton->GetValue() || isIbisLoaded() ); + if( dynamic_cast( &curModel() ) ) + m_modelNotebook->SetSelection( 1 ); + else + m_modelNotebook->SetSelection( 0 ); + if( curModel().HasPrimaryValue() ) { const SIM_MODEL::PARAM& primary = curModel().GetParam( 0 ); @@ -489,46 +494,21 @@ void DIALOG_SIM_MODEL::updateModelParamsTab() template void DIALOG_SIM_MODEL::updateModelCodeTab() { + wxString text; SPICE_ITEM item; item.modelName = m_modelNameCombobox->GetStringSelection(); if( m_useInstanceModelRadioButton->GetValue() || item.modelName == "" ) item.modelName = m_fields.at( REFERENCE_FIELD ).GetText(); - m_codePreview->SetEditable( true ); // ??? + SIM_MODEL& model = curModel(); - if( dynamic_cast( &curModel() ) ) - { - // For raw Spice models display the whole file instead. + text << model.SpiceGenerator().Preview( item ); - wxString path = curModel().FindParam( "lib" )->value->ToString(); - wxString absolutePath = Prj().AbsolutePath( path ); - wxTextFile file; - wxString text; + if( SIM_MODEL_RAW_SPICE* rawSpice = dynamic_cast( &model ) ) + text << rawSpice->GetSource(); - 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 ); - } - } - else - { - m_codePreview->SetText( curModel().SpiceGenerator().Preview( item ) ); - } - - m_codePreview->SetEditable( false ); // ??? + m_codePreview->SetText( text ); m_wasCodePreviewUpdated = true; } @@ -644,7 +624,7 @@ void DIALOG_SIM_MODEL::loadLibrary( const wxString& aLibraryPath, bool aForce try { m_libraryModelsMgr.SetLibrary( std::string( aLibraryPath.ToUTF8() ), - &( dlg.m_messagePanel->Reporter() ) ); + &dlg.m_messagePanel->Reporter() ); } catch( const IO_ERROR& e ) { @@ -654,7 +634,9 @@ void DIALOG_SIM_MODEL::loadLibrary( const wxString& aLibraryPath, bool aForce dlg.ShowQuasiModal(); } else + { DisplayErrorMessage( this, e.What() ); + } return; } @@ -887,7 +869,9 @@ SIM_MODEL& DIALOG_SIM_MODEL::curModel() const return m_libraryModelsMgr.GetModels().at( m_modelNameCombobox->GetSelection() ).get(); } else + { return m_builtinModelsMgr.GetModels().at( static_cast( m_curModelType ) ); + } } @@ -1064,11 +1048,7 @@ void DIALOG_SIM_MODEL::onModelNameCombobox( wxCommandEvent& aEvent ) wxArrayString pinLabels; SIM_MODEL_KIBIS* modelkibis = dynamic_cast( &curModel() ); - if( !modelkibis ) - { - wxFAIL; - return; - } + wxCHECK2( modelkibis, return ); for( std::pair strs : modelkibis->GetIbisPins() ) pinLabels.Add( strs.first + wxT( " - " ) + strs.second ); diff --git a/eeschema/dialogs/dialog_sim_model_base.cpp b/eeschema/dialogs/dialog_sim_model_base.cpp index 58a32e867e..434e9fbcb5 100644 --- a/eeschema/dialogs/dialog_sim_model_base.cpp +++ b/eeschema/dialogs/dialog_sim_model_base.cpp @@ -125,8 +125,8 @@ DIALOG_SIM_MODEL_BASE::DIALOG_SIM_MODEL_BASE( wxWindow* parent, wxWindowID id, c bSizerMargins->Add( fgSizer16, 0, wxEXPAND|wxLEFT, 24 ); - m_notebook4 = new wxNotebook( m_modelPanel, wxID_ANY, wxDefaultPosition, wxDefaultSize, 0 ); - m_parametersPanel = new wxPanel( m_notebook4, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL ); + m_modelNotebook = new wxNotebook( m_modelPanel, wxID_ANY, wxDefaultPosition, wxDefaultSize, 0 ); + m_parametersPanel = new wxPanel( m_modelNotebook, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL ); m_parametersPanel->SetMinSize( wxSize( 500,-1 ) ); 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->Layout(); bSizer12->Fit( m_parametersPanel ); - m_notebook4->AddPage( m_parametersPanel, _("Parameters"), true ); - m_codePanel = new wxPanel( m_notebook4, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL ); + m_modelNotebook->AddPage( m_parametersPanel, _("Parameters"), true ); + m_codePanel = new wxPanel( m_modelNotebook, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL ); wxBoxSizer* bSizer5; 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->Layout(); 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 ); bSizerMargins->Add( m_saveInValueCheckbox, 0, wxALL, 6 ); diff --git a/eeschema/dialogs/dialog_sim_model_base.fbp b/eeschema/dialogs/dialog_sim_model_base.fbp index 88f74f39c0..f76c53f09c 100644 --- a/eeschema/dialogs/dialog_sim_model_base.fbp +++ b/eeschema/dialogs/dialog_sim_model_base.fbp @@ -1372,7 +1372,7 @@ 0 1 - m_notebook4 + m_modelNotebook 1 diff --git a/eeschema/dialogs/dialog_sim_model_base.h b/eeschema/dialogs/dialog_sim_model_base.h index 73a782f47d..ca9ea62e20 100644 --- a/eeschema/dialogs/dialog_sim_model_base.h +++ b/eeschema/dialogs/dialog_sim_model_base.h @@ -69,7 +69,7 @@ class DIALOG_SIM_MODEL_BASE : public DIALOG_SHIM wxChoice* m_deviceTypeChoice; wxStaticText* m_staticTextSpiceType; wxChoice* m_typeChoice; - wxNotebook* m_notebook4; + wxNotebook* m_modelNotebook; wxPanel* m_parametersPanel; wxPropertyGridManager* m_paramGridMgr; wxPropertyGridPage* m_paramGrid; diff --git a/eeschema/sim/sim_model_raw_spice.h b/eeschema/sim/sim_model_raw_spice.h index 958c21d637..f235280f89 100644 --- a/eeschema/sim/sim_model_raw_spice.h +++ b/eeschema/sim/sim_model_raw_spice.h @@ -64,6 +64,16 @@ public: SIM_MODEL_RAW_SPICE(); + void SetSource( const std::string& aSpiceSource ) { m_spiceCode = aSpiceSource; } + + std::string GetSource() const + { + if( m_baseModel ) + return static_cast( m_baseModel )->GetSource(); + + return m_spiceCode; + } + protected: void CreatePins( unsigned aSymbolPinCount ) override; @@ -71,7 +81,8 @@ private: static std::vector makeParamInfos(); bool requiresSpiceModelLine() const override { return false; } - std::vector> m_paramInfos; +private: + std::string m_spiceCode; }; #endif // SIM_MODEL_RAW_SPICE_H diff --git a/eeschema/sim/sim_model_spice.cpp b/eeschema/sim/sim_model_spice.cpp index 76663bffa4..2191188e36 100644 --- a/eeschema/sim/sim_model_spice.cpp +++ b/eeschema/sim/sim_model_spice.cpp @@ -54,30 +54,36 @@ std::string SPICE_GENERATOR_SPICE::Preview( const SPICE_ITEM& aItem ) const } -std::unique_ptr SIM_MODEL_SPICE::Create( const SIM_LIBRARY_SPICE& aLibrary, - const std::string& aSpiceCode ) +std::unique_ptr SIM_MODEL_SPICE::Create( const SIM_LIBRARY_SPICE& aLibrary, + const std::string& aSpiceCode ) { - auto model = dynamic_cast( - SIM_MODEL::Create( SPICE_MODEL_PARSER::ReadType( aLibrary, aSpiceCode ) ).release() ); + SIM_MODEL::TYPE modelType = SPICE_MODEL_PARSER::ReadType( aLibrary, aSpiceCode ); + SIM_MODEL* model = SIM_MODEL::Create( modelType ).release(); - if( !model ) - THROW_IO_ERROR( "Could not determine Spice model type" ); + if( SIM_MODEL_SPICE* spiceModel = dynamic_cast( model ) ) + { + spiceModel->m_spiceModelParser->ReadModel( aLibrary, aSpiceCode ); + return std::unique_ptr( spiceModel ); + } + else if( SIM_MODEL_RAW_SPICE* rawSpice = dynamic_cast( model ) ) + { + rawSpice->SetSource( aSpiceCode ); + return std::unique_ptr( rawSpice ); + } - model->m_spiceModelParser->ReadModel( aLibrary, aSpiceCode ); - return std::unique_ptr( model ); + delete model; + THROW_IO_ERROR( "Could not determine Spice model modelType" ); } -SIM_MODEL_SPICE::SIM_MODEL_SPICE( TYPE aType, - std::unique_ptr aSpiceGenerator ) : +SIM_MODEL_SPICE::SIM_MODEL_SPICE( TYPE aType, std::unique_ptr aSpiceGenerator ) : SIM_MODEL( aType, std::move( aSpiceGenerator ) ), m_spiceModelParser( std::make_unique( *this ) ) { } -SIM_MODEL_SPICE::SIM_MODEL_SPICE( TYPE aType, - std::unique_ptr aSpiceGenerator, +SIM_MODEL_SPICE::SIM_MODEL_SPICE( TYPE aType, std::unique_ptr aSpiceGenerator, std::unique_ptr aSpiceModelParser ) : SIM_MODEL( aType, std::move( aSpiceGenerator ) ), m_spiceModelParser( std::move( aSpiceModelParser ) ) diff --git a/eeschema/sim/sim_model_spice.h b/eeschema/sim/sim_model_spice.h index 0485bd4238..166a4c0bdc 100644 --- a/eeschema/sim/sim_model_spice.h +++ b/eeschema/sim/sim_model_spice.h @@ -47,8 +47,8 @@ public: friend class SPICE_GENERATOR_SPICE; friend class SPICE_MODEL_PARSER; - static std::unique_ptr Create( const SIM_LIBRARY_SPICE& aLibrary, - const std::string& aSpiceCode ); + static std::unique_ptr Create( const SIM_LIBRARY_SPICE& aLibrary, + const std::string& aSpiceCode ); SIM_MODEL_SPICE( TYPE aType, std::unique_ptr aSpiceGenerator );