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
This commit is contained in:
Jeff Young 2023-04-22 21:23:42 +01:00
parent c2cc27c25c
commit 60b019591d
4 changed files with 48 additions and 27 deletions

View File

@ -287,10 +287,16 @@ SIM_LIBRARY::MODEL SIM_LIB_MGR::CreateModel( const wxString& aLibraryPath,
{ {
path = ResolveLibraryPath( aLibraryPath, m_project ); path = ResolveLibraryPath( aLibraryPath, m_project );
auto it = m_libraries.find( path );
if( it == m_libraries.end() )
{
std::function<wxString( const wxString&, const wxString& )> f2 = std::function<wxString( const wxString&, const wxString& )> f2 =
std::bind( &SIM_LIB_MGR::ResolveEmbeddedLibraryPath, this, _1, _2 ); std::bind( &SIM_LIB_MGR::ResolveEmbeddedLibraryPath, this, _1, _2 );
auto it = m_libraries.try_emplace( path, SIM_LIBRARY::Create( path, m_reporter, &f2 ) ).first; it = m_libraries.emplace( path, SIM_LIBRARY::Create( path, m_reporter, &f2 ) ).first;
}
library = &*it->second; library = &*it->second;
} }
catch( const IO_ERROR& e ) catch( const IO_ERROR& e )

View File

@ -1047,6 +1047,10 @@ void SIM_MODEL::doWriteFields( std::vector<T>& aFields ) const
bool SIM_MODEL::requiresSpiceModelLine( const SPICE_ITEM& aItem ) 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 // Model must be written if there's no base model or the base model is an internal model
if( !m_baseModel || aItem.baseModelName == "" ) if( !m_baseModel || aItem.baseModelName == "" )
return true; return true;

View File

@ -527,6 +527,12 @@ SIMULATOR_FRAME::SIMULATOR_FRAME( KIWAY* aKiway, wxWindow* aParent ) :
// Prepare the color list to plot traces // Prepare the color list to plot traces
SIM_PLOT_COLORS::FillDefaultColorList( m_darkMode ); SIM_PLOT_COLORS::FillDefaultColorList( m_darkMode );
NGSPICE_SIMULATOR_SETTINGS* settings =
dynamic_cast<NGSPICE_SIMULATOR_SETTINGS*>( m_simulator->Settings().get() );
if( settings->GetWorkbookFilename().IsEmpty() )
settings->SetModelMode( NGSPICE_MODEL_MODE::LT_PSPICE );
m_simulator->Init(); m_simulator->Init();
m_reporter = new SIM_THREAD_REPORTER( this ); m_reporter = new SIM_THREAD_REPORTER( this );

View File

@ -266,44 +266,49 @@ SIM_MODEL::TYPE SPICE_MODEL_PARSER::ReadTypeFromSpiceStrings( const std::string&
const std::string& aVersion, const std::string& aVersion,
bool aSkipDefaultLevel ) 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; vdmos = true;
std::string level = SIM_MODEL::SpiceInfo( type ).level; pchan = input_type.Contains( wxS( "PCHAN" ) );
std::string version = SIM_MODEL::SpiceInfo( type ).version; }
bool isDefaultLevel = SIM_MODEL::SpiceInfo( type ).isDefaultLevel;
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; continue;
if( boost::starts_with( typePrefix, "VDMOS" ) ) if( candidate_type.StartsWith( wxS( "VDMOS" ) ) && vdmos )
{ {
wxString deviceType = wxString( typePrefix ).BeforeFirst( ' ' ); // VDMOS if( vdmos && pchan && candidate_type.EndsWith( wxS( "PCHAN" ) ) )
wxString channelType = wxString( typePrefix ).AfterFirst( ' ' ); // NCHAN or PCHAN return candidate;
else if( vdmos && !pchan && candidate_type.EndsWith( wxS( "NCHAN" ) ) )
wxStringTokenizer tokenizer( aTypeString, wxT( " \t\n\r+(" ), wxTOKEN_STRTOK ); return candidate;
if( tokenizer.HasMoreTokens() && tokenizer.GetNextToken().Upper() == deviceType
&& tokenizer.HasMoreTokens() && tokenizer.GetNextToken().Upper() == channelType )
{
return type;
} }
} else if( input_type.StartsWith( candidate_type ) )
else if( boost::starts_with( boost::to_upper_copy( aTypeString ), typePrefix ) )
{ {
if( version != aVersion ) if( candidate_version != aVersion )
continue; continue;
if( level == readLevel ) if( candidate_level == input_level )
return type; return candidate;
if( aSkipDefaultLevel ) if( aSkipDefaultLevel )
continue; continue;
if( isDefaultLevel && aLevel == "" ) if( candidate_isDefaultLevel && aLevel == "" )
return type; return candidate;
} }
} }