Gracefully fall back to raw spice when we can't parse the data.
Fixes https://gitlab.com/kicad/code/kicad/issues/13329
This commit is contained in:
parent
77b361a077
commit
55b8f0bc00
|
@ -568,9 +568,6 @@ void DIALOG_SIM_MODEL<T_symbol, T_field>::updateModelCodeTab()
|
|||
|
||||
text << model.SpiceGenerator().Preview( item );
|
||||
|
||||
if( SIM_MODEL_RAW_SPICE* rawSpice = dynamic_cast<SIM_MODEL_RAW_SPICE*>( &model ) )
|
||||
text << rawSpice->GetSource();
|
||||
|
||||
m_codePreview->SetText( text );
|
||||
m_codePreview->SelectNone();
|
||||
}
|
||||
|
|
|
@ -443,19 +443,20 @@ void SIM_MODEL::WriteFields( std::vector<LIB_FIELD>& aFields ) const
|
|||
}
|
||||
|
||||
|
||||
std::unique_ptr<SIM_MODEL> SIM_MODEL::CreateFallback( TYPE aType, const std::string& aSpiceCode )
|
||||
{
|
||||
std::unique_ptr<SIM_MODEL> model( new SIM_MODEL_SPICE_FALLBACK( aType, aSpiceCode ) );
|
||||
return model;
|
||||
}
|
||||
|
||||
|
||||
std::unique_ptr<SIM_MODEL> SIM_MODEL::Create( TYPE aType, const std::vector<LIB_PIN*>& aPins )
|
||||
{
|
||||
std::unique_ptr<SIM_MODEL> model = Create( aType );
|
||||
|
||||
// Passing nullptr to ReadDataFields will make it act as if all fields were empty.
|
||||
model->ReadDataFields( static_cast<const std::vector<SCH_FIELD>*>( nullptr ), aPins );
|
||||
try
|
||||
{
|
||||
// Passing nullptr to ReadDataFields will make it act as if all fields were empty.
|
||||
model->ReadDataFields( static_cast<const std::vector<SCH_FIELD>*>( nullptr ), aPins );
|
||||
}
|
||||
catch( ... )
|
||||
{
|
||||
// Shouldn't happen with nothing to read from fields
|
||||
}
|
||||
|
||||
return model;
|
||||
}
|
||||
|
||||
|
@ -466,12 +467,15 @@ std::unique_ptr<SIM_MODEL> SIM_MODEL::Create( const SIM_MODEL& aBaseModel,
|
|||
std::unique_ptr<SIM_MODEL> model;
|
||||
|
||||
if( dynamic_cast<const SIM_MODEL_SPICE_FALLBACK*>( &aBaseModel ) )
|
||||
model = CreateFallback( aBaseModel.GetType() );
|
||||
model = std::make_unique<SIM_MODEL_SPICE_FALLBACK>( aBaseModel.GetType() );
|
||||
else if( dynamic_cast< const SIM_MODEL_RAW_SPICE*>( &aBaseModel ) )
|
||||
model = std::make_unique<SIM_MODEL_RAW_SPICE>();
|
||||
else
|
||||
model = Create( aBaseModel.GetType() );
|
||||
|
||||
try
|
||||
{
|
||||
model->ReadDataFields( static_cast<const std::vector<SCH_FIELD>*>( nullptr ), aPins );
|
||||
model->SetBaseModel( aBaseModel );
|
||||
}
|
||||
catch( IO_ERROR& err )
|
||||
|
@ -479,7 +483,6 @@ std::unique_ptr<SIM_MODEL> SIM_MODEL::Create( const SIM_MODEL& aBaseModel,
|
|||
DisplayErrorMessage( nullptr, err.What() );
|
||||
}
|
||||
|
||||
model->ReadDataFields( static_cast<const std::vector<SCH_FIELD>*>( nullptr ), aPins );
|
||||
return model;
|
||||
}
|
||||
|
||||
|
@ -498,20 +501,22 @@ std::unique_ptr<SIM_MODEL> SIM_MODEL::Create( const SIM_MODEL& aBaseModel,
|
|||
std::unique_ptr<SIM_MODEL> model;
|
||||
|
||||
if( dynamic_cast<const SIM_MODEL_SPICE_FALLBACK*>( &aBaseModel ) )
|
||||
model = CreateFallback( type );
|
||||
model = std::make_unique<SIM_MODEL_SPICE_FALLBACK>( type );
|
||||
else if( dynamic_cast< const SIM_MODEL_RAW_SPICE*>( &aBaseModel ) )
|
||||
model = std::make_unique<SIM_MODEL_RAW_SPICE>();
|
||||
else
|
||||
model = Create( type );
|
||||
|
||||
try
|
||||
{
|
||||
model->SetBaseModel( aBaseModel );
|
||||
model->ReadDataFields( &aFields, aPins );
|
||||
}
|
||||
catch( IO_ERROR& err )
|
||||
{
|
||||
DisplayErrorMessage( nullptr, err.What() );
|
||||
}
|
||||
|
||||
model->ReadDataFields( &aFields, aPins );
|
||||
return model;
|
||||
}
|
||||
|
||||
|
@ -531,7 +536,34 @@ std::unique_ptr<SIM_MODEL> SIM_MODEL::Create( const std::vector<T>& aFields,
|
|||
TYPE type = ReadTypeFromFields( aFields );
|
||||
std::unique_ptr<SIM_MODEL> model = SIM_MODEL::Create( type );
|
||||
|
||||
model->ReadDataFields( &aFields, aPins );
|
||||
try
|
||||
{
|
||||
model->ReadDataFields( &aFields, aPins );
|
||||
}
|
||||
catch( const IO_ERROR& e )
|
||||
{
|
||||
// Just because we can't parse it doesn't mean that a SPICE interpreter can't. Fall
|
||||
// back to a raw spice code model.
|
||||
|
||||
std::string modelData = GetFieldValue( &aFields, PARAMS_FIELD );
|
||||
|
||||
if( modelData.empty() )
|
||||
modelData = GetFieldValue( &aFields, VALUE_FIELD );
|
||||
|
||||
model = std::make_unique<SIM_MODEL_RAW_SPICE>( modelData );
|
||||
|
||||
try
|
||||
{
|
||||
model->createPins( aPins );
|
||||
model->m_serializer->ParsePins( GetFieldValue( &aFields, PINS_FIELD ) );
|
||||
}
|
||||
catch( const IO_ERROR& e )
|
||||
{
|
||||
// We own the pin syntax, so if we can't parse it then there's an error, full stop.
|
||||
DisplayErrorMessage( nullptr, e.What() );
|
||||
}
|
||||
}
|
||||
|
||||
return model;
|
||||
}
|
||||
|
||||
|
@ -965,22 +997,15 @@ void SIM_MODEL::doReadDataFields( const std::vector<T>* aFields,
|
|||
bool diffMode = GetFieldValue( aFields, SIM_LIBRARY_KIBIS::DIFF_FIELD ) == "1";
|
||||
SwitchSingleEndedDiff( diffMode );
|
||||
|
||||
try
|
||||
{
|
||||
m_serializer->ParseEnable( GetFieldValue( aFields, ENABLE_FIELD ) );
|
||||
m_serializer->ParseEnable( GetFieldValue( aFields, ENABLE_FIELD ) );
|
||||
|
||||
createPins( aPins );
|
||||
m_serializer->ParsePins( GetFieldValue( aFields, PINS_FIELD ) );
|
||||
createPins( aPins );
|
||||
m_serializer->ParsePins( GetFieldValue( aFields, PINS_FIELD ) );
|
||||
|
||||
std::string paramsField = GetFieldValue( aFields, PARAMS_FIELD );
|
||||
std::string paramsField = GetFieldValue( aFields, PARAMS_FIELD );
|
||||
|
||||
if( !m_serializer->ParseParams( paramsField ) )
|
||||
m_serializer->ParseValue( GetFieldValue( aFields, VALUE_FIELD ) );
|
||||
}
|
||||
catch( IO_ERROR& err )
|
||||
{
|
||||
DisplayErrorMessage( nullptr, err.What() );
|
||||
}
|
||||
if( !m_serializer->ParseParams( paramsField ) )
|
||||
m_serializer->ParseValue( GetFieldValue( aFields, VALUE_FIELD ) );
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -414,9 +414,6 @@ public:
|
|||
static std::unique_ptr<SIM_MODEL> Create( const std::vector<T>& aFields,
|
||||
const std::vector<LIB_PIN*>& aPins );
|
||||
|
||||
static std::unique_ptr<SIM_MODEL> CreateFallback( TYPE aType,
|
||||
const std::string& aSpiceCode = "" );
|
||||
|
||||
template <typename T>
|
||||
static std::string GetFieldValue( const std::vector<T>* aFields, const std::string& aFieldName,
|
||||
bool aResolve = true );
|
||||
|
|
|
@ -112,13 +112,16 @@ std::string SPICE_GENERATOR_RAW_SPICE::Preview( const SPICE_ITEM& aItem ) const
|
|||
}
|
||||
|
||||
|
||||
SIM_MODEL_RAW_SPICE::SIM_MODEL_RAW_SPICE() :
|
||||
SIM_MODEL( TYPE::RAWSPICE, std::make_unique<SPICE_GENERATOR_RAW_SPICE>( *this ) )
|
||||
SIM_MODEL_RAW_SPICE::SIM_MODEL_RAW_SPICE( const std::string& aSpiceSource ) :
|
||||
SIM_MODEL( TYPE::RAWSPICE, std::make_unique<SPICE_GENERATOR_RAW_SPICE>( *this ) ),
|
||||
m_spiceCode( aSpiceSource )
|
||||
{
|
||||
static std::vector<PARAM::INFO> paramInfos = makeParamInfos();
|
||||
|
||||
for( const PARAM::INFO& paramInfo : paramInfos )
|
||||
AddParam( paramInfo );
|
||||
|
||||
SetParamValue( "model", aSpiceSource );
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -62,7 +62,7 @@ public:
|
|||
static constexpr auto LEGACY_ENABLED_FIELD = "Spice_Netlist_Enabled";
|
||||
static constexpr auto LEGACY_LIB_FIELD = "Spice_Lib_File";
|
||||
|
||||
SIM_MODEL_RAW_SPICE();
|
||||
SIM_MODEL_RAW_SPICE( const std::string& aSpiceSource = "" );
|
||||
|
||||
void SetSource( const std::string& aSpiceSource ) { m_spiceCode = aSpiceSource; }
|
||||
|
||||
|
|
|
@ -194,6 +194,7 @@ std::string SPICE_GENERATOR::Preview( const SPICE_ITEM& aItem ) const
|
|||
std::string spiceCode = ModelLine( aItem );
|
||||
|
||||
std::string itemLine = ItemLine( aItem );
|
||||
|
||||
if( spiceCode != "" )
|
||||
spiceCode.append( "\n" );
|
||||
|
||||
|
|
Loading…
Reference in New Issue