Manual cherry-pick of much of 6d296038f3
This commit is contained in:
parent
c41b1e2f06
commit
70e86434ef
|
@ -136,6 +136,9 @@ bool DIALOG_SIM_MODEL<T_symbol, T_field>::TransferDataToWindow()
|
||||||
wxString pinMap;
|
wxString pinMap;
|
||||||
bool storeInValue = false;
|
bool storeInValue = false;
|
||||||
|
|
||||||
|
wxString msg;
|
||||||
|
WX_STRING_REPORTER reporter( &msg );
|
||||||
|
|
||||||
// Infer RLC and VI models if they aren't specified
|
// Infer RLC and VI models if they aren't specified
|
||||||
if( SIM_MODEL::InferSimModel( m_symbol, &m_fields, false, SIM_VALUE_GRAMMAR::NOTATION::SI,
|
if( SIM_MODEL::InferSimModel( m_symbol, &m_fields, false, SIM_VALUE_GRAMMAR::NOTATION::SI,
|
||||||
&deviceType, &modelType, &modelParams, &pinMap ) )
|
&deviceType, &modelType, &modelParams, &pinMap ) )
|
||||||
|
@ -180,7 +183,7 @@ bool DIALOG_SIM_MODEL<T_symbol, T_field>::TransferDataToWindow()
|
||||||
if( !loadLibrary( libraryFilename ) )
|
if( !loadLibrary( libraryFilename ) )
|
||||||
{
|
{
|
||||||
m_libraryPathText->ChangeValue( libraryFilename );
|
m_libraryPathText->ChangeValue( libraryFilename );
|
||||||
m_curModelType = SIM_MODEL::ReadTypeFromFields( m_fields );
|
m_curModelType = SIM_MODEL::ReadTypeFromFields( m_fields, &reporter );
|
||||||
m_libraryModelsMgr.CreateModel( nullptr, sourcePins, m_fields );
|
m_libraryModelsMgr.CreateModel( nullptr, sourcePins, m_fields );
|
||||||
|
|
||||||
m_modelNameChoice->Append( _( "<unknown>" ) );
|
m_modelNameChoice->Append( _( "<unknown>" ) );
|
||||||
|
@ -256,25 +259,32 @@ bool DIALOG_SIM_MODEL<T_symbol, T_field>::TransferDataToWindow()
|
||||||
{
|
{
|
||||||
// The model is sourced from the instance.
|
// The model is sourced from the instance.
|
||||||
m_useInstanceModelRadioButton->SetValue( true );
|
m_useInstanceModelRadioButton->SetValue( true );
|
||||||
m_curModelType = SIM_MODEL::ReadTypeFromFields( m_fields );
|
|
||||||
|
msg.clear();
|
||||||
|
m_curModelType = SIM_MODEL::ReadTypeFromFields( m_fields, &reporter );
|
||||||
|
|
||||||
|
if( reporter.HasMessage() )
|
||||||
|
DisplayErrorMessage( this, msg );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
m_builtinModelsMgr.SetReporter( &reporter );
|
||||||
|
|
||||||
for( SIM_MODEL::TYPE type : SIM_MODEL::TYPE_ITERATOR() )
|
for( SIM_MODEL::TYPE type : SIM_MODEL::TYPE_ITERATOR() )
|
||||||
{
|
{
|
||||||
wxString msg;
|
|
||||||
WX_STRING_REPORTER reporter( &msg );
|
|
||||||
|
|
||||||
m_builtinModelsMgr.SetReporter( &reporter );
|
|
||||||
|
|
||||||
if( m_useInstanceModelRadioButton->GetValue() && type == m_curModelType )
|
if( m_useInstanceModelRadioButton->GetValue() && type == m_curModelType )
|
||||||
m_builtinModelsMgr.CreateModel( m_fields, sourcePins, false );
|
|
||||||
else
|
|
||||||
m_builtinModelsMgr.CreateModel( type, sourcePins );
|
|
||||||
|
|
||||||
if( reporter.HasMessage() )
|
|
||||||
{
|
{
|
||||||
DisplayErrorMessage( this, _( "Failed to read simulation model from fields." )
|
msg.clear();
|
||||||
+ wxT( "\n\n" ) + msg );
|
m_builtinModelsMgr.CreateModel( m_fields, sourcePins, false );
|
||||||
|
|
||||||
|
if( reporter.HasMessage() )
|
||||||
|
{
|
||||||
|
DisplayErrorMessage( this, _( "Failed to read simulation model from fields." )
|
||||||
|
+ wxT( "\n\n" ) + msg );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
m_builtinModelsMgr.CreateModel( type, sourcePins );
|
||||||
}
|
}
|
||||||
|
|
||||||
SIM_MODEL::DEVICE_T deviceTypeT = SIM_MODEL::TypeInfo( type ).deviceType;
|
SIM_MODEL::DEVICE_T deviceTypeT = SIM_MODEL::TypeInfo( type ).deviceType;
|
||||||
|
@ -698,7 +708,7 @@ bool DIALOG_SIM_MODEL<T_symbol, T_field>::loadLibrary( const wxString& aLibraryP
|
||||||
|
|
||||||
std::string modelName = SIM_MODEL::GetFieldValue( &m_fields, SIM_LIBRARY::NAME_FIELD );
|
std::string modelName = SIM_MODEL::GetFieldValue( &m_fields, SIM_LIBRARY::NAME_FIELD );
|
||||||
|
|
||||||
for( auto& [baseModelName, baseModel] : library()->GetModels() )
|
for( const auto& [baseModelName, baseModel] : library()->GetModels() )
|
||||||
{
|
{
|
||||||
if( baseModelName == modelName )
|
if( baseModelName == modelName )
|
||||||
m_libraryModelsMgr.CreateModel( &baseModel, sourcePins, m_fields );
|
m_libraryModelsMgr.CreateModel( &baseModel, sourcePins, m_fields );
|
||||||
|
@ -714,7 +724,7 @@ bool DIALOG_SIM_MODEL<T_symbol, T_field>::loadLibrary( const wxString& aLibraryP
|
||||||
|
|
||||||
wxArrayString modelNames;
|
wxArrayString modelNames;
|
||||||
|
|
||||||
for( auto& [name, model] : library()->GetModels() )
|
for( const auto& [name, model] : library()->GetModels() )
|
||||||
modelNames.Add( name );
|
modelNames.Add( name );
|
||||||
|
|
||||||
m_modelNameChoice->Clear();
|
m_modelNameChoice->Clear();
|
||||||
|
@ -1407,22 +1417,16 @@ void DIALOG_SIM_MODEL<T_symbol, T_field>::adjustParamGridColumns( int aWidth, bo
|
||||||
|
|
||||||
for( size_t ii = 0; ii < grid->GetColumnCount(); ii++ )
|
for( size_t ii = 0; ii < grid->GetColumnCount(); ii++ )
|
||||||
{
|
{
|
||||||
if( ii == 0 )
|
if( ii == PARAM_COLUMN::DESCRIPTION )
|
||||||
colWidths.push_back( grid->GetState()->GetColumnWidth( ii ) + margin + indent );
|
colWidths.push_back( grid->GetState()->GetColumnWidth( ii ) + margin + indent );
|
||||||
else if( ii == 1 )
|
else if( ii == PARAM_COLUMN::VALUE )
|
||||||
colWidths.push_back( grid->GetState()->GetColumnWidth( ii ) + margin );
|
colWidths.push_back( std::max( 72, grid->GetState()->GetColumnWidth( ii ) ) + margin );
|
||||||
else
|
else
|
||||||
colWidths.push_back( 50 );
|
colWidths.push_back( 60 + margin );
|
||||||
|
|
||||||
aWidth -= colWidths[ ii ];
|
aWidth -= colWidths[ ii ];
|
||||||
}
|
}
|
||||||
|
|
||||||
// Account for scroll bars
|
|
||||||
aWidth -= ( grid->GetSize().x - grid->GetClientSize().x );
|
|
||||||
|
|
||||||
if( aWidth > 0 )
|
|
||||||
colWidths[ PARAM_COLUMN::VALUE ] += aWidth;
|
|
||||||
|
|
||||||
for( size_t ii = 0; ii < grid->GetColumnCount(); ii++ )
|
for( size_t ii = 0; ii < grid->GetColumnCount(); ii++ )
|
||||||
grid->SetColumnProportion( ii, colWidths[ ii ] );
|
grid->SetColumnProportion( ii, colWidths[ ii ] );
|
||||||
|
|
||||||
|
|
|
@ -83,20 +83,13 @@ namespace NETLIST_EXPORTER_SPICE_PARSER
|
||||||
|
|
||||||
std::string NAME_GENERATOR::Generate( const std::string& aProposedName )
|
std::string NAME_GENERATOR::Generate( const std::string& aProposedName )
|
||||||
{
|
{
|
||||||
if( !m_names.count( aProposedName ) )
|
std::string name = aProposedName;
|
||||||
return aProposedName;
|
int ii = 1;
|
||||||
|
|
||||||
for( uint64_t i = 1; i < UINT64_MAX; ++i )
|
while( m_names.count( name ) )
|
||||||
{
|
name = fmt::format( "{}#{}", aProposedName, ii++ );
|
||||||
std::string name = fmt::format( "{}#{}", aProposedName, i );
|
|
||||||
|
|
||||||
if( !m_names.count( name ) )
|
return name;
|
||||||
return name;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Should never happen.
|
|
||||||
THROW_IO_ERROR( wxString::Format( _( "Failed to generate a name for '%s': exceeded UINT64_MAX" ),
|
|
||||||
aProposedName ) );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -126,8 +119,7 @@ bool NETLIST_EXPORTER_SPICE::DoWriteNetlist( OUTPUTFORMATTER& aFormatter, unsign
|
||||||
// Cleanup list to avoid duplicate if the netlist exporter is run more than once.
|
// Cleanup list to avoid duplicate if the netlist exporter is run more than once.
|
||||||
m_rawIncludes.clear();
|
m_rawIncludes.clear();
|
||||||
|
|
||||||
if( !ReadSchematicAndLibraries( aNetlistOptions, aReporter ) )
|
bool result = ReadSchematicAndLibraries( aNetlistOptions, aReporter );
|
||||||
return false;
|
|
||||||
|
|
||||||
WriteHead( aFormatter, aNetlistOptions );
|
WriteHead( aFormatter, aNetlistOptions );
|
||||||
|
|
||||||
|
@ -142,7 +134,7 @@ bool NETLIST_EXPORTER_SPICE::DoWriteNetlist( OUTPUTFORMATTER& aFormatter, unsign
|
||||||
|
|
||||||
WriteTail( aFormatter, aNetlistOptions );
|
WriteTail( aFormatter, aNetlistOptions );
|
||||||
|
|
||||||
return true;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -165,6 +157,8 @@ bool NETLIST_EXPORTER_SPICE::ReadSchematicAndLibraries( unsigned aNetlistOptions
|
||||||
std::set<std::string> refNames; // Set of reference names to check for duplication.
|
std::set<std::string> refNames; // Set of reference names to check for duplication.
|
||||||
int ncCounter = 1;
|
int ncCounter = 1;
|
||||||
|
|
||||||
|
m_libMgr.SetReporter( &aReporter );
|
||||||
|
|
||||||
ReadDirectives( aNetlistOptions );
|
ReadDirectives( aNetlistOptions );
|
||||||
|
|
||||||
m_nets.clear();
|
m_nets.clear();
|
||||||
|
@ -240,50 +234,19 @@ bool NETLIST_EXPORTER_SPICE::ReadSchematicAndLibraries( unsigned aNetlistOptions
|
||||||
wxString modelParams;
|
wxString modelParams;
|
||||||
wxString pinMap;
|
wxString pinMap;
|
||||||
|
|
||||||
// JEY TODO: readModel() below will also do the inference, so I don't think this
|
readRefName( sheet, *symbol, spiceItem, refNames );
|
||||||
// accomplishes anything....
|
readModel( sheet, *symbol, spiceItem );
|
||||||
// Infer RLC and VI models if they aren't specified
|
readPinNumbers( *symbol, spiceItem, pins );
|
||||||
if( SIM_MODEL::InferSimModel( *symbol, &spiceItem.fields, true,
|
readPinNetNames( *symbol, spiceItem, pins, ncCounter );
|
||||||
SIM_VALUE_GRAMMAR::NOTATION::SPICE, &deviceType,
|
|
||||||
&modelType, &modelParams, &pinMap ) )
|
|
||||||
{
|
|
||||||
spiceItem.fields.emplace_back( symbol, -1, SIM_DEVICE_TYPE_FIELD );
|
|
||||||
spiceItem.fields.back().SetText( deviceType );
|
|
||||||
|
|
||||||
if( !modelType.IsEmpty() )
|
// TODO: transmission line handling?
|
||||||
{
|
|
||||||
spiceItem.fields.emplace_back( symbol, -1, SIM_TYPE_FIELD );
|
|
||||||
spiceItem.fields.back().SetText( modelType );
|
|
||||||
}
|
|
||||||
|
|
||||||
spiceItem.fields.emplace_back( symbol, -1, SIM_PARAMS_FIELD );
|
m_items.push_back( std::move( spiceItem ) );
|
||||||
spiceItem.fields.back().SetText( modelParams );
|
|
||||||
|
|
||||||
spiceItem.fields.emplace_back( symbol, -1, SIM_PINS_FIELD );
|
|
||||||
spiceItem.fields.back().SetText( pinMap );
|
|
||||||
}
|
|
||||||
|
|
||||||
try
|
|
||||||
{
|
|
||||||
readRefName( sheet, *symbol, spiceItem, refNames );
|
|
||||||
readModel( sheet, *symbol, spiceItem );
|
|
||||||
readPinNumbers( *symbol, spiceItem, pins );
|
|
||||||
readPinNetNames( *symbol, spiceItem, pins, ncCounter );
|
|
||||||
|
|
||||||
// TODO: transmission line handling?
|
|
||||||
|
|
||||||
m_items.push_back( std::move( spiceItem ) );
|
|
||||||
}
|
|
||||||
catch( const IO_ERROR& e )
|
|
||||||
{
|
|
||||||
msg.Printf( _( "Error reading simulation model from symbol '%s':\n%s" ),
|
|
||||||
symbol->GetRef( &sheet ),
|
|
||||||
e.Problem() );
|
|
||||||
aReporter.Report( msg, RPT_SEVERITY_ERROR );
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
m_libMgr.SetReporter( nullptr );
|
||||||
|
|
||||||
return !aReporter.HasMessage();
|
return !aReporter.HasMessage();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -595,7 +558,7 @@ void NETLIST_EXPORTER_SPICE::writeInclude( OUTPUTFORMATTER& aFormatter, unsigned
|
||||||
|
|
||||||
void NETLIST_EXPORTER_SPICE::writeIncludes( OUTPUTFORMATTER& aFormatter, unsigned aNetlistOptions )
|
void NETLIST_EXPORTER_SPICE::writeIncludes( OUTPUTFORMATTER& aFormatter, unsigned aNetlistOptions )
|
||||||
{
|
{
|
||||||
for( auto& [path, library] : m_libMgr.GetLibraries() )
|
for( const auto& [path, library] : m_libMgr.GetLibraries() )
|
||||||
{
|
{
|
||||||
if( dynamic_cast<const SIM_LIBRARY_SPICE*>( &library.get() ) )
|
if( dynamic_cast<const SIM_LIBRARY_SPICE*>( &library.get() ) )
|
||||||
writeInclude( aFormatter, aNetlistOptions, path );
|
writeInclude( aFormatter, aNetlistOptions, path );
|
||||||
|
|
|
@ -49,7 +49,7 @@ void SIM_LIBRARY_KIBIS::ReadFile( const std::string& aFilePath, REPORTER* aRepor
|
||||||
|
|
||||||
for( KIBIS_COMPONENT& kcomp : m_kibis.m_components )
|
for( KIBIS_COMPONENT& kcomp : m_kibis.m_components )
|
||||||
{
|
{
|
||||||
m_models.push_back( SIM_MODEL::Create( SIM_MODEL::TYPE::KIBIS_DEVICE, pins, nullptr ) );
|
m_models.push_back( SIM_MODEL::Create( SIM_MODEL::TYPE::KIBIS_DEVICE, pins, aReporter ) );
|
||||||
m_modelNames.emplace_back( kcomp.m_name );
|
m_modelNames.emplace_back( kcomp.m_name );
|
||||||
|
|
||||||
SIM_MODEL_KIBIS* libcomp = dynamic_cast<SIM_MODEL_KIBIS*>( m_models.back().get() );
|
SIM_MODEL_KIBIS* libcomp = dynamic_cast<SIM_MODEL_KIBIS*>( m_models.back().get() );
|
||||||
|
|
|
@ -361,11 +361,13 @@ SIM_MODEL::SPICE_INFO SIM_MODEL::SpiceInfo( TYPE aType )
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
template TYPE SIM_MODEL::ReadTypeFromFields( const std::vector<SCH_FIELD>& aFields );
|
template TYPE SIM_MODEL::ReadTypeFromFields( const std::vector<SCH_FIELD>& aFields,
|
||||||
template TYPE SIM_MODEL::ReadTypeFromFields( const std::vector<LIB_FIELD>& aFields );
|
REPORTER* aReporter );
|
||||||
|
template TYPE SIM_MODEL::ReadTypeFromFields( const std::vector<LIB_FIELD>& aFields,
|
||||||
|
REPORTER* aReporter );
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
TYPE SIM_MODEL::ReadTypeFromFields( const std::vector<T>& aFields )
|
TYPE SIM_MODEL::ReadTypeFromFields( const std::vector<T>& aFields, REPORTER* aReporter )
|
||||||
{
|
{
|
||||||
std::string deviceTypeFieldValue = GetFieldValue( &aFields, SIM_DEVICE_TYPE_FIELD );
|
std::string deviceTypeFieldValue = GetFieldValue( &aFields, SIM_DEVICE_TYPE_FIELD );
|
||||||
std::string typeFieldValue = GetFieldValue( &aFields, SIM_TYPE_FIELD );
|
std::string typeFieldValue = GetFieldValue( &aFields, SIM_TYPE_FIELD );
|
||||||
|
@ -392,6 +394,17 @@ TYPE SIM_MODEL::ReadTypeFromFields( const std::vector<T>& aFields )
|
||||||
if( typeFromLegacyFields != TYPE::NONE )
|
if( typeFromLegacyFields != TYPE::NONE )
|
||||||
return typeFromLegacyFields;
|
return typeFromLegacyFields;
|
||||||
|
|
||||||
|
if( aReporter )
|
||||||
|
{
|
||||||
|
if( aFields.size() > REFERENCE_FIELD )
|
||||||
|
{
|
||||||
|
aReporter->Report( wxString::Format( _( "Error reading simulation model from symbol '%s':\n%s" ),
|
||||||
|
aFields[REFERENCE_FIELD].GetText(),
|
||||||
|
_( "Failed to read simulation model from fields." ) ),
|
||||||
|
RPT_SEVERITY_ERROR );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return TYPE::NONE;
|
return TYPE::NONE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -506,7 +519,7 @@ std::unique_ptr<SIM_MODEL> SIM_MODEL::Create( const SIM_MODEL* aBaseModel,
|
||||||
const std::vector<T>& aFields,
|
const std::vector<T>& aFields,
|
||||||
REPORTER* aReporter )
|
REPORTER* aReporter )
|
||||||
{
|
{
|
||||||
TYPE type = ReadTypeFromFields( aFields );
|
TYPE type = ReadTypeFromFields( aFields, aReporter );
|
||||||
|
|
||||||
// If the model has a specified type, it takes priority over the type of its base class.
|
// If the model has a specified type, it takes priority over the type of its base class.
|
||||||
if( type == TYPE::NONE && aBaseModel )
|
if( type == TYPE::NONE && aBaseModel )
|
||||||
|
@ -533,9 +546,13 @@ std::unique_ptr<SIM_MODEL> SIM_MODEL::Create( const SIM_MODEL* aBaseModel,
|
||||||
catch( IO_ERROR& err )
|
catch( IO_ERROR& err )
|
||||||
{
|
{
|
||||||
if( aReporter )
|
if( aReporter )
|
||||||
aReporter->Report( err.What(), RPT_SEVERITY_ERROR );
|
{
|
||||||
else
|
aReporter->Report( wxString::Format( _( "Error reading simulation model from "
|
||||||
DisplayErrorMessage( nullptr, err.What() );
|
"symbol '%s':\n%s" ),
|
||||||
|
aFields[REFERENCE_FIELD].GetText(),
|
||||||
|
err.Problem() ),
|
||||||
|
RPT_SEVERITY_ERROR );
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return model;
|
return model;
|
||||||
|
@ -557,7 +574,7 @@ std::unique_ptr<SIM_MODEL> SIM_MODEL::Create( const std::vector<T>& aFields,
|
||||||
const std::vector<LIB_PIN*>& aPins,
|
const std::vector<LIB_PIN*>& aPins,
|
||||||
bool aResolved, REPORTER* aReporter )
|
bool aResolved, REPORTER* aReporter )
|
||||||
{
|
{
|
||||||
TYPE type = ReadTypeFromFields( aFields );
|
TYPE type = ReadTypeFromFields( aFields, aReporter );
|
||||||
std::unique_ptr<SIM_MODEL> model = SIM_MODEL::Create( type );
|
std::unique_ptr<SIM_MODEL> model = SIM_MODEL::Create( type );
|
||||||
|
|
||||||
try
|
try
|
||||||
|
@ -589,11 +606,15 @@ std::unique_ptr<SIM_MODEL> SIM_MODEL::Create( const std::vector<T>& aFields,
|
||||||
}
|
}
|
||||||
catch( const IO_ERROR& err )
|
catch( const IO_ERROR& err )
|
||||||
{
|
{
|
||||||
// We own the pin syntax, so if we can't parse it then there's an error, full stop.
|
// We own the pin syntax, so if we can't parse it then there's an error.
|
||||||
if( aReporter )
|
if( aReporter )
|
||||||
aReporter->Report( err.Problem(), RPT_SEVERITY_ERROR );
|
{
|
||||||
else
|
aReporter->Report( wxString::Format( _( "Error reading simulation model from "
|
||||||
THROW_IO_ERROR( err.Problem() );
|
"symbol '%s':\n%s" ),
|
||||||
|
aFields[REFERENCE_FIELD].GetText(),
|
||||||
|
err.Problem() ),
|
||||||
|
RPT_SEVERITY_ERROR );
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -726,21 +747,8 @@ void SIM_MODEL::AddParam( const PARAM::INFO& aInfo )
|
||||||
|
|
||||||
void SIM_MODEL::SetBaseModel( const SIM_MODEL& aBaseModel )
|
void SIM_MODEL::SetBaseModel( const SIM_MODEL& aBaseModel )
|
||||||
{
|
{
|
||||||
auto describe =
|
wxASSERT_MSG( GetType() == aBaseModel.GetType(),
|
||||||
[]( const SIM_MODEL* aModel )
|
wxS( "Simulation model type must be the same as its base class!" ) );
|
||||||
{
|
|
||||||
return fmt::format( "{} ({})",
|
|
||||||
aModel->GetDeviceInfo().fieldValue,
|
|
||||||
aModel->GetTypeInfo().description );
|
|
||||||
};
|
|
||||||
|
|
||||||
if( GetType() != aBaseModel.GetType() )
|
|
||||||
{
|
|
||||||
THROW_IO_ERROR( wxString::Format( _( "Simulation model type must be the same as of its "
|
|
||||||
"base class: '%s', but is '%s'" ),
|
|
||||||
describe( &aBaseModel ),
|
|
||||||
describe( this ) ) );
|
|
||||||
}
|
|
||||||
|
|
||||||
m_baseModel = &aBaseModel;
|
m_baseModel = &aBaseModel;
|
||||||
}
|
}
|
||||||
|
|
|
@ -384,7 +384,7 @@ public:
|
||||||
|
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
static TYPE ReadTypeFromFields( const std::vector<T>& aFields );
|
static TYPE ReadTypeFromFields( const std::vector<T>& aFields, REPORTER* aReporter );
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
static TYPE InferTypeFromLegacyFields( const std::vector<T>& aFields );
|
static TYPE InferTypeFromLegacyFields( const std::vector<T>& aFields );
|
||||||
|
|
|
@ -55,7 +55,6 @@ std::vector<std::string> SPICE_GENERATOR_NGSPICE::CurrentNames( const SPICE_ITEM
|
||||||
return SPICE_GENERATOR::CurrentNames( aItem );
|
return SPICE_GENERATOR::CurrentNames( aItem );
|
||||||
|
|
||||||
default:
|
default:
|
||||||
wxFAIL_MSG( "Unhandled model device type in SIM_MODEL_NGSPICE" );
|
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -95,6 +95,10 @@ std::string SPICE_GENERATOR::ModelLine( const SPICE_ITEM& aItem ) const
|
||||||
value ) );
|
value ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Don't send SPICE empty models.
|
||||||
|
if( result.length() == indentLength + 1 /* line ending */ )
|
||||||
|
result.clear();
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue