From 999cd8cd11e5406db15385ff775f9b8fbf2f4255 Mon Sep 17 00:00:00 2001 From: Jeff Young Date: Sat, 22 Apr 2023 21:23:42 +0100 Subject: [PATCH] Simulator fixes. 1) Don't read libraries multiple times 2) VDMOS default is nchan if not specified 3) In the absence of a workbook default to LTSpice compatability 4) Don't attempt to write out a model line for a subckt; it never has a baseModel --- eeschema/sim/sim_lib_mgr.cpp | 12 +++++-- eeschema/sim/sim_model.cpp | 4 +++ eeschema/sim/spice_model_parser.cpp | 53 ++++++++++++++++------------- 3 files changed, 42 insertions(+), 27 deletions(-) diff --git a/eeschema/sim/sim_lib_mgr.cpp b/eeschema/sim/sim_lib_mgr.cpp index 3728d876b2..b51cc76f67 100644 --- a/eeschema/sim/sim_lib_mgr.cpp +++ b/eeschema/sim/sim_lib_mgr.cpp @@ -279,10 +279,16 @@ SIM_LIBRARY::MODEL SIM_LIB_MGR::CreateModel( const wxString& aLibraryPath, { path = ResolveLibraryPath( aLibraryPath, m_project ); - std::function f2 = - std::bind( &SIM_LIB_MGR::ResolveEmbeddedLibraryPath, this, _1, _2 ); + auto it = m_libraries.find( path ); + + if( it == m_libraries.end() ) + { + std::function f2 = + std::bind( &SIM_LIB_MGR::ResolveEmbeddedLibraryPath, this, _1, _2 ); + + it = m_libraries.emplace( path, SIM_LIBRARY::Create( path, m_reporter, &f2 ) ).first; + } - auto it = m_libraries.try_emplace( path, SIM_LIBRARY::Create( path, m_reporter, &f2 ) ).first; library = &*it->second; } catch( const IO_ERROR& e ) diff --git a/eeschema/sim/sim_model.cpp b/eeschema/sim/sim_model.cpp index 8b1968c86b..98be6b42b2 100644 --- a/eeschema/sim/sim_model.cpp +++ b/eeschema/sim/sim_model.cpp @@ -1076,6 +1076,10 @@ void SIM_MODEL::doWriteFields( std::vector& aFields ) const bool SIM_MODEL::requiresSpiceModelLine( const SPICE_ITEM& aItem ) const { + // SUBCKTs are a single level; there's never a baseModel. + if( m_type == TYPE::SUBCKT ) + return false; + // Model must be written if there's no base model or the base model is an internal model if( !m_baseModel || aItem.baseModelName == "" ) return true; diff --git a/eeschema/sim/spice_model_parser.cpp b/eeschema/sim/spice_model_parser.cpp index 76c242d9a0..a3d08851a0 100644 --- a/eeschema/sim/spice_model_parser.cpp +++ b/eeschema/sim/spice_model_parser.cpp @@ -265,44 +265,49 @@ SIM_MODEL::TYPE SPICE_MODEL_PARSER::ReadTypeFromSpiceStrings( const std::string& const std::string& aVersion, bool aSkipDefaultLevel ) { - std::string readLevel = wxString( aLevel ).BeforeFirst( '.' ).ToStdString(); + wxString input_level = wxString( aLevel ).BeforeFirst( '.' ); + wxString input_type( aTypeString ); + bool vdmos = false; + bool pchan = false; - for( SIM_MODEL::TYPE type : SIM_MODEL::TYPE_ITERATOR() ) + input_type.UpperCase(); + + if( input_type.StartsWith( wxS( "VDMOS" ) ) ) { - std::string typePrefix = SIM_MODEL::SpiceInfo( type ).modelType; - std::string level = SIM_MODEL::SpiceInfo( type ).level; - std::string version = SIM_MODEL::SpiceInfo( type ).version; - bool isDefaultLevel = SIM_MODEL::SpiceInfo( type ).isDefaultLevel; + vdmos = true; + pchan = input_type.Contains( wxS( "PCHAN" ) ); + } - if( typePrefix == "" ) + for( SIM_MODEL::TYPE candidate : SIM_MODEL::TYPE_ITERATOR() ) + { + wxString candidate_type = SIM_MODEL::SpiceInfo( candidate ).modelType; + wxString candidate_level = SIM_MODEL::SpiceInfo( candidate ).level; + wxString candidate_version = SIM_MODEL::SpiceInfo( candidate ).version; + bool candidate_isDefaultLevel = SIM_MODEL::SpiceInfo( candidate ).isDefaultLevel; + + if( candidate_type.IsEmpty() ) continue; - if( boost::starts_with( typePrefix, "VDMOS" ) ) + if( candidate_type.StartsWith( wxS( "VDMOS" ) ) && vdmos ) { - wxString deviceType = wxString( typePrefix ).BeforeFirst( ' ' ); // VDMOS - wxString channelType = wxString( typePrefix ).AfterFirst( ' ' ); // NCHAN or PCHAN - - wxStringTokenizer tokenizer( aTypeString, wxT( " \t\n\r+(" ), wxTOKEN_STRTOK ); - - if( tokenizer.HasMoreTokens() && tokenizer.GetNextToken().Upper() == deviceType - && tokenizer.HasMoreTokens() && tokenizer.GetNextToken().Upper() == channelType ) - { - return type; - } + if( vdmos && pchan && candidate_type.EndsWith( wxS( "PCHAN" ) ) ) + return candidate; + else if( vdmos && !pchan && candidate_type.EndsWith( wxS( "NCHAN" ) ) ) + return candidate; } - else if( boost::starts_with( boost::to_upper_copy( aTypeString ), typePrefix ) ) + else if( input_type.StartsWith( candidate_type ) ) { - if( version != aVersion ) + if( candidate_version != aVersion ) continue; - if( level == readLevel ) - return type; + if( candidate_level == input_level ) + return candidate; if( aSkipDefaultLevel ) continue; - if( isDefaultLevel && aLevel == "" ) - return type; + if( candidate_isDefaultLevel && aLevel == "" ) + return candidate; } }