Reduce reliance on exception processing -- it's waay too bugy at present.

This moves some stuff to REPORTER APIs.  Moving more stuff would be good,
but it probably too high-risk at present.  We'll wait for 8.0 for that....

Fixes https://gitlab.com/kicad/code/kicad/issues/13359
This commit is contained in:
Jeff Young 2023-01-03 15:29:45 +00:00
parent d1c2ab957b
commit 9b9795a87d
16 changed files with 258 additions and 213 deletions

View File

@ -3,7 +3,7 @@
* *
* Copyright (C) 2022 Mikolaj Wielgus * Copyright (C) 2022 Mikolaj Wielgus
* Copyright (C) 2022 CERN * Copyright (C) 2022 CERN
* Copyright (C) 2022 KiCad Developers, see AUTHORS.txt for contributors. * Copyright (C) 2022-2023 KiCad Developers, see AUTHORS.txt for contributors.
* *
* This program is free software; you can redistribute it and/or * This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License * modify it under the terms of the GNU General Public License
@ -185,7 +185,9 @@ bool DIALOG_SIM_MODEL<T_symbol, T_field>::TransferDataToWindow()
{ {
DisplayErrorMessage( this, wxString::Format( _( "No model named '%s' in library." ), DisplayErrorMessage( this, wxString::Format( _( "No model named '%s' in library." ),
modelName ) ); modelName ) );
m_modelNameChoice->SetSelection( -1 );
// Default to first item in library
m_modelNameChoice->SetSelection( 0 );
} }
else else
{ {
@ -257,18 +259,20 @@ bool DIALOG_SIM_MODEL<T_symbol, T_field>::TransferDataToWindow()
for( SIM_MODEL::TYPE type : SIM_MODEL::TYPE_ITERATOR() ) for( SIM_MODEL::TYPE type : SIM_MODEL::TYPE_ITERATOR() )
{ {
try wxString msg;
{ WX_STRING_REPORTER reporter( &msg );
if( m_useInstanceModelRadioButton->GetValue() && type == m_curModelType )
m_builtinModelsMgr.CreateModel( m_fields, sourcePins ); m_builtinModelsMgr.SetReporter( &reporter );
else
m_builtinModelsMgr.CreateModel( type, sourcePins ); if( m_useInstanceModelRadioButton->GetValue() && type == m_curModelType )
} m_builtinModelsMgr.CreateModel( m_fields, sourcePins, false );
catch( const IO_ERROR& e ) else
m_builtinModelsMgr.CreateModel( type, sourcePins );
if( reporter.HasMessage() )
{ {
DisplayErrorMessage( this, _( "Failed to read simulation model from fields." ) DisplayErrorMessage( this, _( "Failed to read simulation model from fields." )
+ wxT( "\n\n" ) + wxT( "\n\n" ) + msg );
+ e.What() );
} }
SIM_MODEL::DEVICE_T deviceTypeT = SIM_MODEL::TypeInfo( type ).deviceType; SIM_MODEL::DEVICE_T deviceTypeT = SIM_MODEL::TypeInfo( type ).deviceType;
@ -670,25 +674,15 @@ void DIALOG_SIM_MODEL<T_symbol, T_field>::loadLibrary( const wxString& aLibraryP
{ {
auto libraries = m_libraryModelsMgr.GetLibraries(); auto libraries = m_libraryModelsMgr.GetLibraries();
DIALOG_IBIS_PARSER_REPORTER dlg( this ); wxString msg;
dlg.m_messagePanel->Clear(); WX_STRING_REPORTER reporter( &msg );
try m_libraryModelsMgr.SetReporter( &reporter );
{ m_libraryModelsMgr.SetLibrary( aLibraryPath );
m_libraryModelsMgr.SetLibrary( aLibraryPath, &dlg.m_messagePanel->Reporter() );
}
catch( const IO_ERROR& e )
{
if( dlg.m_messagePanel->Reporter().HasMessage() )
{
dlg.m_messagePanel->Flush();
dlg.ShowQuasiModal();
}
else
{
DisplayErrorMessage( this, e.What() );
}
if( reporter.HasMessage() )
{
DisplayErrorMessage( this, msg );
return; return;
} }
@ -700,30 +694,26 @@ void DIALOG_SIM_MODEL<T_symbol, T_field>::loadLibrary( const wxString& aLibraryP
return StrNumCmp( lhs->GetNumber(), rhs->GetNumber(), true ) < 0; return StrNumCmp( lhs->GetNumber(), rhs->GetNumber(), true ) < 0;
} ); } );
try 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( auto& [baseModelName, baseModel] : library()->GetModels() )
{
if( baseModelName == modelName )
m_libraryModelsMgr.CreateModel( baseModel, sourcePins, m_fields );
else
m_libraryModelsMgr.CreateModel( baseModel, sourcePins );
}
}
catch( const IO_ERROR& e )
{ {
DisplayErrorMessage( this, e.What() ); if( baseModelName == modelName )
m_libraryModelsMgr.CreateModel( &baseModel, sourcePins, m_fields );
else
m_libraryModelsMgr.CreateModel( &baseModel, sourcePins );
} }
if( reporter.HasMessage() )
DisplayErrorMessage( this, msg );
m_useLibraryModelRadioButton->SetValue( true ); m_useLibraryModelRadioButton->SetValue( true );
m_libraryPathText->ChangeValue( aLibraryPath ); m_libraryPathText->ChangeValue( aLibraryPath );
wxArrayString modelNames; wxArrayString modelNames;
for( auto& [modelName, model] : library()->GetModels() ) for( auto& [name, model] : library()->GetModels() )
modelNames.Add( modelName ); modelNames.Add( name );
m_modelNameChoice->Clear(); m_modelNameChoice->Clear();
m_modelNameChoice->Append( modelNames ); m_modelNameChoice->Append( modelNames );

View File

@ -3,7 +3,7 @@
* *
* Copyright (C) 2015 Jean-Pierre Charras, jp.charras at wanadoo.fr * Copyright (C) 2015 Jean-Pierre Charras, jp.charras at wanadoo.fr
* Copyright (C) 2011 Wayne Stambaugh <stambaughw@gmail.com> * Copyright (C) 2011 Wayne Stambaugh <stambaughw@gmail.com>
* Copyright (C) 1992-2022 KiCad Developers, see AUTHORS.txt for contributors. * Copyright (C) 1992-2023 KiCad Developers, see AUTHORS.txt for contributors.
* *
* This program is free software; you can redistribute it and/or * This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License * modify it under the terms of the GNU General Public License
@ -1016,7 +1016,9 @@ int ERC_TESTER::TestSimModelIssues()
WX_STRING_REPORTER reporter( &msg ); WX_STRING_REPORTER reporter( &msg );
SCH_SHEET_LIST sheets = m_schematic->GetSheets(); SCH_SHEET_LIST sheets = m_schematic->GetSheets();
int err_count = 0; int err_count = 0;
SIM_LIB_MGR libMgr( &m_schematic->Prj(), &reporter ); SIM_LIB_MGR libMgr( &m_schematic->Prj() );
libMgr.SetReporter( &reporter );
for( SCH_SHEET_PATH& sheet : sheets ) for( SCH_SHEET_PATH& sheet : sheets )
{ {

View File

@ -3,7 +3,7 @@
* *
* Copyright (C) 1992-2013 jp.charras at wanadoo.fr * Copyright (C) 1992-2013 jp.charras at wanadoo.fr
* Copyright (C) 2013 SoftPLC Corporation, Dick Hollenbeck <dick@softplc.com> * Copyright (C) 2013 SoftPLC Corporation, Dick Hollenbeck <dick@softplc.com>
* Copyright (C) 1992-2022 KiCad Developers, see AUTHORS.TXT for contributors. * Copyright (C) 1992-2023 KiCad Developers, see AUTHORS.TXT for contributors.
* *
* This program is free software; you can redistribute it and/or * This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License * modify it under the terms of the GNU General Public License
@ -107,6 +107,7 @@ NETLIST_EXPORTER_SPICE::NETLIST_EXPORTER_SPICE( SCHEMATIC_IFACE* aSchematic ) :
bool NETLIST_EXPORTER_SPICE::WriteNetlist( const wxString& aOutFileName, unsigned aNetlistOptions, bool NETLIST_EXPORTER_SPICE::WriteNetlist( const wxString& aOutFileName, unsigned aNetlistOptions,
REPORTER& aReporter ) REPORTER& aReporter )
{ {
m_libMgr.SetReporter( &aReporter );
FILE_OUTPUTFORMATTER formatter( aOutFileName, wxT( "wt" ), '\'' ); FILE_OUTPUTFORMATTER formatter( aOutFileName, wxT( "wt" ), '\'' );
return DoWriteNetlist( formatter, aNetlistOptions, aReporter ); return DoWriteNetlist( formatter, aNetlistOptions, aReporter );
} }
@ -394,29 +395,11 @@ void NETLIST_EXPORTER_SPICE::ReadDirectives( unsigned aNetlistOptions, REPORTER&
for( const auto& node : root->children ) for( const auto& node : root->children )
{ {
if( node->is_type<NETLIST_EXPORTER_SPICE_PARSER::dotTitle>() ) if( node->is_type<NETLIST_EXPORTER_SPICE_PARSER::dotTitle>() )
{
m_title = node->children.at( 0 )->string(); m_title = node->children.at( 0 )->string();
}
else if( node->is_type<NETLIST_EXPORTER_SPICE_PARSER::dotInclude>() ) else if( node->is_type<NETLIST_EXPORTER_SPICE_PARSER::dotInclude>() )
{ m_libMgr.AddLibrary( node->children.at( 0 )->string() );
std::string path = node->children.at( 0 )->string();
try
{
m_libMgr.AddLibrary( path, &aReporter );
}
catch( const IO_ERROR& e )
{
msg.Printf( _( "Error reading simulation model library '%s':\n%s" ),
path,
e.What() );
aReporter.Report( msg, RPT_SEVERITY_ERROR );
}
}
else else
{
m_directives.emplace_back( node->string() ); m_directives.emplace_back( node->string() );
}
} }
} }
} }

View File

@ -2,7 +2,7 @@
* This program source code file is part of KiCad, a free EDA CAD application. * This program source code file is part of KiCad, a free EDA CAD application.
* *
* Copyright (C) 2022 Mikolaj Wielgus * Copyright (C) 2022 Mikolaj Wielgus
* Copyright (C) 2022 KiCad Developers, see AUTHORS.txt for contributors. * Copyright (C) 2022-2023 KiCad Developers, see AUTHORS.txt for contributors.
* *
* This program is free software; you can redistribute it and/or * This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License * modify it under the terms of the GNU General Public License
@ -36,9 +36,9 @@
#include <sim/sim_model.h> #include <sim/sim_model.h>
#include <sim/sim_model_ideal.h> #include <sim/sim_model_ideal.h>
SIM_LIB_MGR::SIM_LIB_MGR( const PROJECT* aPrj, REPORTER* aReporter ) : SIM_LIB_MGR::SIM_LIB_MGR( const PROJECT* aPrj ) :
m_project( aPrj ), m_project( aPrj ),
m_reporter( aReporter ) m_reporter( nullptr )
{ {
} }
@ -115,33 +115,42 @@ std::string SIM_LIB_MGR::ResolveEmbeddedLibraryPath( const std::string& aLibPath
} }
SIM_LIBRARY& SIM_LIB_MGR::AddLibrary( const wxString& aLibraryPath, REPORTER* aReporter ) void SIM_LIB_MGR::AddLibrary( const wxString& aLibraryPath )
{ {
// May throw an exception. try
wxString path = ResolveLibraryPath( aLibraryPath, m_project ); {
wxString path = ResolveLibraryPath( aLibraryPath, m_project );
std::function<std::string(const std::string&, const std::string&)> f2 = std::function<std::string(const std::string&, const std::string&)> f2 =
std::bind( &SIM_LIB_MGR::ResolveEmbeddedLibraryPath, this, std::placeholders::_1, std::placeholders::_2 ); std::bind( &SIM_LIB_MGR::ResolveEmbeddedLibraryPath, this, std::placeholders::_1, std::placeholders::_2 );
// May throw an exception. m_libraries.try_emplace( path, SIM_LIBRARY::Create( path, m_reporter, &f2 ) );
auto it = m_libraries.try_emplace( path, SIM_LIBRARY::Create( path, aReporter, &f2 ) ).first; }
return *it->second; catch( const IO_ERROR& e )
{
m_reporter->Report( e.What() );
}
} }
SIM_LIBRARY& SIM_LIB_MGR::SetLibrary( const wxString& aLibraryPath, REPORTER* aReporter ) void SIM_LIB_MGR::SetLibrary( const wxString& aLibraryPath )
{ {
// May throw an exception. try
wxString path = ResolveLibraryPath( aLibraryPath, m_project ); {
wxString path = ResolveLibraryPath( aLibraryPath, m_project );
std::function<std::string(const std::string&, const std::string&)> f2 = std::function<std::string(const std::string&, const std::string&)> f2 =
std::bind( &SIM_LIB_MGR::ResolveEmbeddedLibraryPath, this, std::placeholders::_1, std::placeholders::_2 ); std::bind( &SIM_LIB_MGR::ResolveEmbeddedLibraryPath, this, std::placeholders::_1, std::placeholders::_2 );
std::unique_ptr<SIM_LIBRARY> library = SIM_LIBRARY::Create( path, aReporter, &f2 ); std::unique_ptr<SIM_LIBRARY> library = SIM_LIBRARY::Create( path, m_reporter, &f2 );
Clear(); Clear();
m_libraries[path] = std::move( library ); m_libraries[path] = std::move( library );
return *m_libraries.at( path ); }
catch( const IO_ERROR& e )
{
m_reporter->Report( e.What() );
}
} }
@ -152,7 +161,7 @@ SIM_MODEL& SIM_LIB_MGR::CreateModel( SIM_MODEL::TYPE aType, const std::vector<LI
} }
SIM_MODEL& SIM_LIB_MGR::CreateModel( const SIM_MODEL& aBaseModel, SIM_MODEL& SIM_LIB_MGR::CreateModel( const SIM_MODEL* aBaseModel,
const std::vector<LIB_PIN*>& aPins ) const std::vector<LIB_PIN*>& aPins )
{ {
m_models.push_back( SIM_MODEL::Create( aBaseModel, aPins, m_reporter ) ); m_models.push_back( SIM_MODEL::Create( aBaseModel, aPins, m_reporter ) );
@ -161,7 +170,7 @@ SIM_MODEL& SIM_LIB_MGR::CreateModel( const SIM_MODEL& aBaseModel,
template <typename T> template <typename T>
SIM_MODEL& SIM_LIB_MGR::CreateModel( const SIM_MODEL& aBaseModel, SIM_MODEL& SIM_LIB_MGR::CreateModel( const SIM_MODEL* aBaseModel,
const std::vector<LIB_PIN*>& aPins, const std::vector<LIB_PIN*>& aPins,
const std::vector<T>& aFields ) const std::vector<T>& aFields )
{ {
@ -169,10 +178,10 @@ SIM_MODEL& SIM_LIB_MGR::CreateModel( const SIM_MODEL& aBaseModel,
return *m_models.back(); return *m_models.back();
} }
template SIM_MODEL& SIM_LIB_MGR::CreateModel( const SIM_MODEL& aBaseModel, template SIM_MODEL& SIM_LIB_MGR::CreateModel( const SIM_MODEL* aBaseModel,
const std::vector<LIB_PIN*>& aPins, const std::vector<LIB_PIN*>& aPins,
const std::vector<SCH_FIELD>& aFields ); const std::vector<SCH_FIELD>& aFields );
template SIM_MODEL& SIM_LIB_MGR::CreateModel( const SIM_MODEL& aBaseModel, template SIM_MODEL& SIM_LIB_MGR::CreateModel( const SIM_MODEL* aBaseModel,
const std::vector<LIB_PIN*>& aPins, const std::vector<LIB_PIN*>& aPins,
const std::vector<LIB_FIELD>& aFields ); const std::vector<LIB_FIELD>& aFields );
@ -234,7 +243,7 @@ SIM_LIBRARY::MODEL SIM_LIB_MGR::CreateModel( const SCH_SHEET_PATH* aSheetPath, S
return StrNumCmp( lhs->GetNumber(), rhs->GetNumber(), true ) < 0; return StrNumCmp( lhs->GetNumber(), rhs->GetNumber(), true ) < 0;
} ); } );
SIM_LIBRARY::MODEL model = CreateModel( fields, sourcePins ); SIM_LIBRARY::MODEL model = CreateModel( fields, sourcePins, true );
model.model.SetIsStoredInValue( storeInValue ); model.model.SetIsStoredInValue( storeInValue );
@ -244,7 +253,7 @@ SIM_LIBRARY::MODEL SIM_LIB_MGR::CreateModel( const SCH_SHEET_PATH* aSheetPath, S
template <typename T> template <typename T>
SIM_LIBRARY::MODEL SIM_LIB_MGR::CreateModel( const std::vector<T>& aFields, SIM_LIBRARY::MODEL SIM_LIB_MGR::CreateModel( const std::vector<T>& aFields,
const std::vector<LIB_PIN*>& aPins ) const std::vector<LIB_PIN*>& aPins, bool aResolved )
{ {
std::string libraryPath = SIM_MODEL::GetFieldValue( &aFields, SIM_LIBRARY::LIBRARY_FIELD ); std::string libraryPath = SIM_MODEL::GetFieldValue( &aFields, SIM_LIBRARY::LIBRARY_FIELD );
std::string baseModelName = SIM_MODEL::GetFieldValue( &aFields, SIM_LIBRARY::NAME_FIELD ); std::string baseModelName = SIM_MODEL::GetFieldValue( &aFields, SIM_LIBRARY::NAME_FIELD );
@ -255,15 +264,17 @@ SIM_LIBRARY::MODEL SIM_LIB_MGR::CreateModel( const std::vector<T>& aFields,
} }
else else
{ {
m_models.push_back( SIM_MODEL::Create( aFields, aPins, m_reporter ) ); m_models.push_back( SIM_MODEL::Create( aFields, aPins, aResolved, m_reporter ) );
return { baseModelName, *m_models.back() }; return { baseModelName, *m_models.back() };
} }
} }
template SIM_LIBRARY::MODEL SIM_LIB_MGR::CreateModel( const std::vector<SCH_FIELD>& aFields, template SIM_LIBRARY::MODEL SIM_LIB_MGR::CreateModel( const std::vector<SCH_FIELD>& aFields,
const std::vector<LIB_PIN*>& aPins ); const std::vector<LIB_PIN*>& aPins,
bool aResolved );
template SIM_LIBRARY::MODEL SIM_LIB_MGR::CreateModel( const std::vector<LIB_FIELD>& aFields, template SIM_LIBRARY::MODEL SIM_LIB_MGR::CreateModel( const std::vector<LIB_FIELD>& aFields,
const std::vector<LIB_PIN*>& aPins ); const std::vector<LIB_PIN*>& aPins,
bool aResolved );
template <typename T> template <typename T>
@ -272,16 +283,20 @@ SIM_LIBRARY::MODEL SIM_LIB_MGR::CreateModel( const wxString& aLibraryPath,
const std::vector<T>& aFields, const std::vector<T>& aFields,
const std::vector<LIB_PIN*>& aPins ) const std::vector<LIB_PIN*>& aPins )
{ {
wxString path = ResolveLibraryPath( aLibraryPath, m_project ); wxString path;
SIM_LIBRARY* library = nullptr;
wxString msg; wxString msg;
SIM_LIBRARY* library = nullptr;
std::function<std::string(const std::string&, const std::string&)> f2 = SIM_MODEL* baseModel = nullptr;
std::bind( &SIM_LIB_MGR::ResolveEmbeddedLibraryPath, this, std::placeholders::_1, std::placeholders::_2 ); std::string modelName;
try try
{ {
auto it = m_libraries.try_emplace( path, SIM_LIBRARY::Create( path, nullptr, &f2 ) ).first; path = ResolveLibraryPath( aLibraryPath, m_project );
std::function<std::string( const std::string&, const std::string& )> f2 =
std::bind( &SIM_LIB_MGR::ResolveEmbeddedLibraryPath, this, std::placeholders::_1, std::placeholders::_2 );
auto it = m_libraries.try_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 )
@ -305,25 +320,31 @@ SIM_LIBRARY::MODEL SIM_LIB_MGR::CreateModel( const wxString& aLibraryPath,
m_reporter->Report( msg, RPT_SEVERITY_ERROR ); m_reporter->Report( msg, RPT_SEVERITY_ERROR );
else else
THROW_IO_ERROR( msg ); THROW_IO_ERROR( msg );
modelName = _( "unknown" ).ToStdString();
} }
else if( library )
SIM_MODEL* baseModel = library->FindModel( aBaseModelName );
if( !baseModel )
{ {
msg.Printf( _( "Error loading simulation model: could not find base model '%s' in library '%s'" ), baseModel = library->FindModel( aBaseModelName );
aBaseModelName, modelName = aBaseModelName;
path );
if( m_reporter ) if( !baseModel )
m_reporter->Report( msg, RPT_SEVERITY_ERROR ); {
else msg.Printf( _( "Error loading simulation model: could not find base model '%s' "
THROW_IO_ERROR( msg ); "in library '%s'" ),
aBaseModelName,
path );
if( m_reporter )
m_reporter->Report( msg, RPT_SEVERITY_ERROR );
else
THROW_IO_ERROR( msg );
}
} }
m_models.push_back( SIM_MODEL::Create( *baseModel, aPins, aFields, m_reporter ) ); m_models.push_back( SIM_MODEL::Create( baseModel, aPins, aFields, m_reporter ) );
return { aBaseModelName, *m_models.back() }; return { modelName, *m_models.back() };
} }

View File

@ -2,7 +2,7 @@
* This program source code file is part of KiCad, a free EDA CAD application. * This program source code file is part of KiCad, a free EDA CAD application.
* *
* Copyright (C) 2022 Mikolaj Wielgus * Copyright (C) 2022 Mikolaj Wielgus
* Copyright (C) 2022 KiCad Developers, see AUTHORS.txt for contributors. * Copyright (C) 2022-2023 KiCad Developers, see AUTHORS.txt for contributors.
* *
* This program is free software; you can redistribute it and/or * This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License * modify it under the terms of the GNU General Public License
@ -40,20 +40,22 @@ class SCH_SYMBOL;
class SIM_LIB_MGR class SIM_LIB_MGR
{ {
public: public:
SIM_LIB_MGR( const PROJECT* aPrj, REPORTER* aReporter = nullptr ); SIM_LIB_MGR( const PROJECT* aPrj );
virtual ~SIM_LIB_MGR() = default; virtual ~SIM_LIB_MGR() = default;
void SetReporter( REPORTER* aReporter ) { m_reporter = aReporter; }
void Clear(); void Clear();
SIM_LIBRARY& AddLibrary( const wxString& aLibraryPath, REPORTER* aReporter ); void AddLibrary( const wxString& aLibraryPath );
SIM_LIBRARY& SetLibrary( const wxString& aLibraryPath, REPORTER* aReporter ); void SetLibrary( const wxString& aLibraryPath );
SIM_MODEL& CreateModel( SIM_MODEL::TYPE aType, const std::vector<LIB_PIN*>& aPins ); SIM_MODEL& CreateModel( SIM_MODEL::TYPE aType, const std::vector<LIB_PIN*>& aPins );
SIM_MODEL& CreateModel( const SIM_MODEL& aBaseModel, const std::vector<LIB_PIN*>& aPins ); SIM_MODEL& CreateModel( const SIM_MODEL* aBaseModel, const std::vector<LIB_PIN*>& aPins );
template <typename T> template <typename T>
SIM_MODEL& CreateModel( const SIM_MODEL& aBaseModel, const std::vector<LIB_PIN*>& aPins, SIM_MODEL& CreateModel( const SIM_MODEL* aBaseModel, const std::vector<LIB_PIN*>& aPins,
const std::vector<T>& aFields ); const std::vector<T>& aFields );
// TODO: The argument can be made const. // TODO: The argument can be made const.
@ -61,7 +63,7 @@ public:
template <typename T> template <typename T>
SIM_LIBRARY::MODEL CreateModel( const std::vector<T>& aFields, SIM_LIBRARY::MODEL CreateModel( const std::vector<T>& aFields,
const std::vector<LIB_PIN*>& aPins ); const std::vector<LIB_PIN*>& aPins, bool aResolved );
template <typename T> template <typename T>
SIM_LIBRARY::MODEL CreateModel( const wxString& aLibraryPath, SIM_LIBRARY::MODEL CreateModel( const wxString& aLibraryPath,

View File

@ -2,7 +2,7 @@
* This program source code file is part of KiCad, a free EDA CAD application. * This program source code file is part of KiCad, a free EDA CAD application.
* *
* Copyright (C) 2022 Mikolaj Wielgus * Copyright (C) 2022 Mikolaj Wielgus
* Copyright (C) 2022 KiCad Developers, see AUTHORS.txt for contributors. * Copyright (C) 2022-2023 KiCad Developers, see AUTHORS.txt for contributors.
* *
* This program is free software; you can redistribute it and/or * This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License * modify it under the terms of the GNU General Public License
@ -28,8 +28,8 @@
#include <boost/algorithm/string/case_conv.hpp> #include <boost/algorithm/string/case_conv.hpp>
std::unique_ptr<SIM_LIBRARY> SIM_LIBRARY::Create( const wxString &aFilePath, REPORTER *aReporter, std::unique_ptr<SIM_LIBRARY> SIM_LIBRARY::Create( const wxString& aFilePath, REPORTER* aReporter,
std::function<std::string( const std::string&, const std::string& )> *aResolver ) std::function<std::string( const std::string&, const std::string& )> *aResolver )
{ {
std::unique_ptr<SIM_LIBRARY> library; std::unique_ptr<SIM_LIBRARY> library;
@ -40,12 +40,12 @@ std::unique_ptr<SIM_LIBRARY> SIM_LIBRARY::Create( const wxString &aFilePath, REP
library->m_reporter = aReporter; library->m_reporter = aReporter;
library->m_pathResolver = aResolver; library->m_pathResolver = aResolver;
library->ReadFile( std::string( aFilePath.c_str() ) ); library->ReadFile( std::string( aFilePath.c_str() ), aReporter );
return library; return library;
} }
void SIM_LIBRARY::ReadFile( const std::string& aFilePath ) void SIM_LIBRARY::ReadFile( const std::string& aFilePath, REPORTER* aReporter )
{ {
m_filePath = aFilePath; m_filePath = aFilePath;
} }

View File

@ -2,7 +2,7 @@
* This program source code file is part of KiCad, a free EDA CAD application. * This program source code file is part of KiCad, a free EDA CAD application.
* *
* Copyright (C) 2022 Mikolaj Wielgus * Copyright (C) 2022 Mikolaj Wielgus
* Copyright (C) 2022 KiCad Developers, see AUTHORS.txt for contributors. * Copyright (C) 2022-2023 KiCad Developers, see AUTHORS.txt for contributors.
* *
* This program is free software; you can redistribute it and/or * This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License * modify it under the terms of the GNU General Public License
@ -54,7 +54,7 @@ public:
*/ */
static std::unique_ptr<SIM_LIBRARY> Create( const wxString& aFilePath, static std::unique_ptr<SIM_LIBRARY> Create( const wxString& aFilePath,
REPORTER* aReporter = nullptr, REPORTER* aReporter = nullptr,
std::function<std::string(const std::string&, const std::string&)>* aResolver = nullptr); std::function<std::string( const std::string&, const std::string& )>* aResolver = nullptr);
/** /**
* Read library from a source file. Must be in the format appropriate to the subclass, e.g. * Read library from a source file. Must be in the format appropriate to the subclass, e.g.
@ -63,7 +63,7 @@ public:
* @param aFilePath Path to the file. * @param aFilePath Path to the file.
* @throw IO_ERROR on read or parsing error. * @throw IO_ERROR on read or parsing error.
*/ */
virtual void ReadFile( const std::string& aFilePath ) = 0; virtual void ReadFile( const std::string& aFilePath, REPORTER* aReporter ) = 0;
/** /**
* Write library to a source file (e.g. in Spice format). * Write library to a source file (e.g. in Spice format).

View File

@ -1,7 +1,7 @@
/* /*
* This program source code file is part of KiCad, a free EDA CAD application. * This program source code file is part of KiCad, a free EDA CAD application.
* *
* Copyright (C) 2022 KiCad Developers, see AUTHORS.txt for contributors. * Copyright (C) 2022-2023 KiCad Developers, see AUTHORS.txt for contributors.
* *
* This program is free software; you can redistribute it and/or * This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License * modify it under the terms of the GNU General Public License
@ -23,21 +23,23 @@
#include <sim/sim_library_kibis.h> #include <sim/sim_library_kibis.h>
#include <sim/sim_model_kibis.h> #include <sim/sim_model_kibis.h>
#include <sim/spice_grammar.h>
#include <ki_exception.h> #include <ki_exception.h>
#include <locale_io.h> #include <locale_io.h>
#include <pegtl.hpp>
#include <pegtl/contrib/parse_tree.hpp> #include <pegtl/contrib/parse_tree.hpp>
#include <lib_pin.h> #include <lib_pin.h>
void SIM_LIBRARY_KIBIS::ReadFile( const std::string& aFilePath ) void SIM_LIBRARY_KIBIS::ReadFile( const std::string& aFilePath, REPORTER* aReporter )
{ {
SIM_LIBRARY::ReadFile( aFilePath ); SIM_LIBRARY::ReadFile( aFilePath, aReporter );
m_kibis = KIBIS( aFilePath, m_reporter ); m_kibis = KIBIS( aFilePath, m_reporter );
if( !m_kibis.m_valid ) if( !m_kibis.m_valid )
THROW_IO_ERROR( wxString::Format( "Invalid ibis file" ) ); {
aReporter->Report( wxString::Format( _( "Invalid IBIS file '%s'" ), aFilePath ),
RPT_SEVERITY_ERROR );
return;
}
LIB_PIN pinA( nullptr ); LIB_PIN pinA( nullptr );
LIB_PIN pinB( nullptr ); LIB_PIN pinB( nullptr );

View File

@ -1,7 +1,7 @@
/* /*
* This program source code file is part of KiCad, a free EDA CAD application. * This program source code file is part of KiCad, a free EDA CAD application.
* *
* Copyright (C) 2022 KiCad Developers, see AUTHORS.txt for contributors. * Copyright (C) 2022-2023 KiCad Developers, see AUTHORS.txt for contributors.
* *
* This program is free software; you can redistribute it and/or * This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License * modify it under the terms of the GNU General Public License
@ -38,7 +38,7 @@ public:
static constexpr auto DIFF_FIELD = "Sim.Ibis.Diff"; static constexpr auto DIFF_FIELD = "Sim.Ibis.Diff";
// @copydoc SIM_LIBRARY::ReadFile() // @copydoc SIM_LIBRARY::ReadFile()
void ReadFile( const std::string& aFilePath ) override; void ReadFile( const std::string& aFilePath, REPORTER* aReporter ) override;
// @copydoc SIM_LIBRARY::WriteFile() // @copydoc SIM_LIBRARY::WriteFile()
void WriteFile( const std::string& aFilePath ) override{}; void WriteFile( const std::string& aFilePath ) override{};

View File

@ -2,7 +2,7 @@
* This program source code file is part of KiCad, a free EDA CAD application. * This program source code file is part of KiCad, a free EDA CAD application.
* *
* Copyright (C) 2022 Mikolaj Wielgus * Copyright (C) 2022 Mikolaj Wielgus
* Copyright (C) 2022 KiCad Developers, see AUTHORS.txt for contributors. * Copyright (C) 2022-2023 KiCad Developers, see AUTHORS.txt for contributors.
* *
* This program is free software; you can redistribute it and/or * This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License * modify it under the terms of the GNU General Public License
@ -33,10 +33,10 @@ SIM_LIBRARY_SPICE::SIM_LIBRARY_SPICE() :
} }
void SIM_LIBRARY_SPICE::ReadFile( const std::string& aFilePath ) void SIM_LIBRARY_SPICE::ReadFile( const std::string& aFilePath, REPORTER* aReporter )
{ {
SIM_LIBRARY::ReadFile( aFilePath ); SIM_LIBRARY::ReadFile( aFilePath, aReporter );
m_spiceLibraryParser->ReadFile( aFilePath ); m_spiceLibraryParser->ReadFile( aFilePath, aReporter );
} }

View File

@ -2,7 +2,7 @@
* This program source code file is part of KiCad, a free EDA CAD application. * This program source code file is part of KiCad, a free EDA CAD application.
* *
* Copyright (C) 2022 Mikolaj Wielgus * Copyright (C) 2022 Mikolaj Wielgus
* Copyright (C) 2022 KiCad Developers, see AUTHORS.txt for contributors. * Copyright (C) 2022-2023 KiCad Developers, see AUTHORS.txt for contributors.
* *
* This program is free software; you can redistribute it and/or * This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License * modify it under the terms of the GNU General Public License
@ -37,7 +37,7 @@ public:
SIM_LIBRARY_SPICE(); SIM_LIBRARY_SPICE();
// @copydoc SIM_LIBRARY::ReadFile() // @copydoc SIM_LIBRARY::ReadFile()
void ReadFile( const std::string& aFilePath ) override; void ReadFile( const std::string& aFilePath, REPORTER* aReporter ) override;
// @copydoc SIM_LIBRARY::WriteFile() // @copydoc SIM_LIBRARY::WriteFile()
void WriteFile( const std::string& aFilePath ) override; void WriteFile( const std::string& aFilePath ) override;

View File

@ -465,23 +465,28 @@ std::unique_ptr<SIM_MODEL> SIM_MODEL::Create( TYPE aType, const std::vector<LIB_
} }
std::unique_ptr<SIM_MODEL> SIM_MODEL::Create( const SIM_MODEL& aBaseModel, std::unique_ptr<SIM_MODEL> SIM_MODEL::Create( const SIM_MODEL* aBaseModel,
const std::vector<LIB_PIN*>& aPins, const std::vector<LIB_PIN*>& aPins,
REPORTER* aReporter ) REPORTER* aReporter )
{ {
TYPE type = aBaseModel ? aBaseModel->GetType() : TYPE::NONE;
std::unique_ptr<SIM_MODEL> model; std::unique_ptr<SIM_MODEL> model;
if( dynamic_cast<const SIM_MODEL_SPICE_FALLBACK*>( &aBaseModel ) ) // A null base model means the model wasn't found in the library, so create a fallback
model = std::make_unique<SIM_MODEL_SPICE_FALLBACK>( aBaseModel.GetType() );
else if( dynamic_cast< const SIM_MODEL_RAW_SPICE*>( &aBaseModel ) ) if( !aBaseModel || dynamic_cast<const SIM_MODEL_SPICE_FALLBACK*>( aBaseModel ) )
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>(); model = std::make_unique<SIM_MODEL_RAW_SPICE>();
else else
model = Create( aBaseModel.GetType() ); model = Create( type );
try try
{ {
if( aBaseModel )
model->SetBaseModel( *aBaseModel );
model->ReadDataFields( static_cast<const std::vector<SCH_FIELD>*>( nullptr ), aPins ); model->ReadDataFields( static_cast<const std::vector<SCH_FIELD>*>( nullptr ), aPins );
model->SetBaseModel( aBaseModel );
} }
catch( IO_ERROR& err ) catch( IO_ERROR& err )
{ {
@ -496,7 +501,7 @@ std::unique_ptr<SIM_MODEL> SIM_MODEL::Create( const SIM_MODEL& aBaseModel,
template <typename T> template <typename T>
std::unique_ptr<SIM_MODEL> SIM_MODEL::Create( const SIM_MODEL& aBaseModel, std::unique_ptr<SIM_MODEL> SIM_MODEL::Create( const SIM_MODEL* aBaseModel,
const std::vector<LIB_PIN*>& aPins, const std::vector<LIB_PIN*>& aPins,
const std::vector<T>& aFields, const std::vector<T>& aFields,
REPORTER* aReporter ) REPORTER* aReporter )
@ -504,21 +509,25 @@ std::unique_ptr<SIM_MODEL> SIM_MODEL::Create( const SIM_MODEL& aBaseModel,
TYPE type = ReadTypeFromFields( aFields ); TYPE type = ReadTypeFromFields( aFields );
// 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 ) if( type == TYPE::NONE && aBaseModel )
type = aBaseModel.GetType(); type = aBaseModel->GetType();
std::unique_ptr<SIM_MODEL> model; std::unique_ptr<SIM_MODEL> model;
if( dynamic_cast<const SIM_MODEL_SPICE_FALLBACK*>( &aBaseModel ) ) // A null base model means the model wasn't found in the library, so create a fallback
if( !aBaseModel || dynamic_cast<const SIM_MODEL_SPICE_FALLBACK*>( aBaseModel ) )
model = std::make_unique<SIM_MODEL_SPICE_FALLBACK>( type ); model = std::make_unique<SIM_MODEL_SPICE_FALLBACK>( type );
else if( dynamic_cast< const SIM_MODEL_RAW_SPICE*>( &aBaseModel ) ) else if( dynamic_cast< const SIM_MODEL_RAW_SPICE*>( aBaseModel ) )
model = std::make_unique<SIM_MODEL_RAW_SPICE>(); model = std::make_unique<SIM_MODEL_RAW_SPICE>();
else else
model = Create( type ); model = Create( type );
try try
{ {
model->SetBaseModel( aBaseModel ); if( aBaseModel )
model->SetBaseModel( *aBaseModel );
model->ReadDataFields( &aFields, aPins ); model->ReadDataFields( &aFields, aPins );
} }
catch( IO_ERROR& err ) catch( IO_ERROR& err )
@ -532,12 +541,12 @@ std::unique_ptr<SIM_MODEL> SIM_MODEL::Create( const SIM_MODEL& aBaseModel,
return model; return model;
} }
template std::unique_ptr<SIM_MODEL> SIM_MODEL::Create( const SIM_MODEL& aBaseModel, template std::unique_ptr<SIM_MODEL> SIM_MODEL::Create( const SIM_MODEL* aBaseModel,
const std::vector<LIB_PIN*>& aPins, const std::vector<LIB_PIN*>& aPins,
const std::vector<SCH_FIELD>& aFields, const std::vector<SCH_FIELD>& aFields,
REPORTER* aReporter ); REPORTER* aReporter );
template std::unique_ptr<SIM_MODEL> SIM_MODEL::Create( const SIM_MODEL& aBaseModel, template std::unique_ptr<SIM_MODEL> SIM_MODEL::Create( const SIM_MODEL* aBaseModel,
const std::vector<LIB_PIN*>& aPins, const std::vector<LIB_PIN*>& aPins,
const std::vector<LIB_FIELD>& aFields, const std::vector<LIB_FIELD>& aFields,
REPORTER* aReporter ); REPORTER* aReporter );
@ -546,7 +555,7 @@ template std::unique_ptr<SIM_MODEL> SIM_MODEL::Create( const SIM_MODEL& aBaseMod
template <typename T> template <typename T>
std::unique_ptr<SIM_MODEL> SIM_MODEL::Create( const std::vector<T>& aFields, 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,
REPORTER* aReporter ) bool aResolved, REPORTER* aReporter )
{ {
TYPE type = ReadTypeFromFields( aFields ); TYPE type = ReadTypeFromFields( aFields );
std::unique_ptr<SIM_MODEL> model = SIM_MODEL::Create( type ); std::unique_ptr<SIM_MODEL> model = SIM_MODEL::Create( type );
@ -557,6 +566,12 @@ std::unique_ptr<SIM_MODEL> SIM_MODEL::Create( const std::vector<T>& aFields,
} }
catch( const IO_ERROR& parse_err ) catch( const IO_ERROR& parse_err )
{ {
if( !aResolved )
{
aReporter->Report( parse_err.What(), RPT_SEVERITY_ERROR );
return model;
}
// Just because we can't parse it doesn't mean that a SPICE interpreter can't. Fall // Just because we can't parse it doesn't mean that a SPICE interpreter can't. Fall
// back to a raw spice code model. // back to a raw spice code model.
@ -587,10 +602,10 @@ std::unique_ptr<SIM_MODEL> SIM_MODEL::Create( const std::vector<T>& aFields,
template std::unique_ptr<SIM_MODEL> SIM_MODEL::Create( const std::vector<SCH_FIELD>& aFields, template std::unique_ptr<SIM_MODEL> SIM_MODEL::Create( const std::vector<SCH_FIELD>& aFields,
const std::vector<LIB_PIN*>& aPins, const std::vector<LIB_PIN*>& aPins,
REPORTER* aReporter ); bool aResolved, REPORTER* aReporter );
template std::unique_ptr<SIM_MODEL> SIM_MODEL::Create( const std::vector<LIB_FIELD>& aFields, template std::unique_ptr<SIM_MODEL> SIM_MODEL::Create( const std::vector<LIB_FIELD>& aFields,
const std::vector<LIB_PIN*>& aPins, const std::vector<LIB_PIN*>& aPins,
REPORTER* aReporter ); bool aResolved, REPORTER* aReporter );
template <typename T> template <typename T>
@ -1560,13 +1575,18 @@ void SIM_MODEL::MigrateSimModel( T_symbol& aSymbol, const PROJECT* aProject )
{ {
wxString msg; wxString msg;
WX_STRING_REPORTER reporter( &msg ); WX_STRING_REPORTER reporter( &msg );
SIM_LIB_MGR libMgr( aProject, &reporter ); SIM_LIB_MGR libMgr( aProject );
std::vector<T_field> emptyFields; std::vector<T_field> emptyFields;
libMgr.SetReporter( &reporter );
SIM_LIBRARY::MODEL model = libMgr.CreateModel( spiceLib, spiceModel.ToStdString(), SIM_LIBRARY::MODEL model = libMgr.CreateModel( spiceLib, spiceModel.ToStdString(),
emptyFields, sourcePins ); emptyFields, sourcePins );
libraryModel = !reporter.HasMessage(); // Otherwise we'll fall back to raw spice model if( reporter.HasMessage() )
libraryModel = false; // Fall back to raw spice model
else
libraryModel = true;
if( pinMapInfo.IsEmpty() ) if( pinMapInfo.IsEmpty() )
{ {

View File

@ -404,12 +404,12 @@ public:
static std::unique_ptr<SIM_MODEL> Create( TYPE aType, const std::vector<LIB_PIN*>& aPins, static std::unique_ptr<SIM_MODEL> Create( TYPE aType, const std::vector<LIB_PIN*>& aPins,
REPORTER* aReporter ); REPORTER* aReporter );
static std::unique_ptr<SIM_MODEL> Create( const SIM_MODEL& aBaseModel, static std::unique_ptr<SIM_MODEL> Create( const SIM_MODEL* aBaseModel,
const std::vector<LIB_PIN*>& aPins, const std::vector<LIB_PIN*>& aPins,
REPORTER* aReporter ); REPORTER* aReporter );
template <typename T> template <typename T>
static std::unique_ptr<SIM_MODEL> Create( const SIM_MODEL& aBaseModel, static std::unique_ptr<SIM_MODEL> Create( const SIM_MODEL* aBaseModel,
const std::vector<LIB_PIN*>& aPins, const std::vector<LIB_PIN*>& aPins,
const std::vector<T>& aFields, const std::vector<T>& aFields,
REPORTER* aReporter ); REPORTER* aReporter );
@ -417,7 +417,7 @@ public:
template <typename T> template <typename T>
static std::unique_ptr<SIM_MODEL> Create( const std::vector<T>& aFields, static std::unique_ptr<SIM_MODEL> Create( const std::vector<T>& aFields,
const std::vector<LIB_PIN*>& aPins, const std::vector<LIB_PIN*>& aPins,
REPORTER* aReporter ); bool aResolved, REPORTER* aReporter );
template <typename T> template <typename T>
static std::string GetFieldValue( const std::vector<T>* aFields, const std::string& aFieldName, static std::string GetFieldValue( const std::vector<T>* aFields, const std::string& aFieldName,

View File

@ -2,7 +2,7 @@
* This program source code file is part of KiCad, a free EDA CAD application. * This program source code file is part of KiCad, a free EDA CAD application.
* *
* Copyright (C) 2022 Mikolaj Wielgus * Copyright (C) 2022 Mikolaj Wielgus
* Copyright (C) 2022 KiCad Developers, see AUTHORS.txt for contributors. * Copyright (C) 2022-2023 KiCad Developers, see AUTHORS.txt for contributors.
* *
* This program is free software; you can redistribute it and/or * This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License * modify it under the terms of the GNU General Public License
@ -57,65 +57,89 @@ namespace SIM_LIBRARY_SPICE_PARSER
}; };
void SPICE_LIBRARY_PARSER::readElement( const std::string &aFilePath ) void SPICE_LIBRARY_PARSER::readElement( const std::string &aFilePath, REPORTER& aReporter )
{ {
tao::pegtl::file_input in( aFilePath ); try
std::unique_ptr<tao::pegtl::parse_tree::node> root =
tao::pegtl::parse_tree::parse<SIM_LIBRARY_SPICE_PARSER::libraryGrammar,
SIM_LIBRARY_SPICE_PARSER::librarySelector,
tao::pegtl::nothing,
SIM_LIBRARY_SPICE_PARSER::control>( in );
for( const auto& node : root->children )
{ {
if( node->is_type<SIM_LIBRARY_SPICE_PARSER::modelUnit>() ) tao::pegtl::file_input in( aFilePath );
std::unique_ptr<tao::pegtl::parse_tree::node> root =
tao::pegtl::parse_tree::parse<SIM_LIBRARY_SPICE_PARSER::libraryGrammar,
SIM_LIBRARY_SPICE_PARSER::librarySelector,
tao::pegtl::nothing,
SIM_LIBRARY_SPICE_PARSER::control>
( in );
for( const auto& node : root->children )
{ {
try if( node->is_type<SIM_LIBRARY_SPICE_PARSER::modelUnit>() )
{ {
m_library.m_models.push_back( SIM_MODEL_SPICE::Create( m_library, node->string() ) ); std::string model = node->string();
m_library.m_modelNames.emplace_back( node->children.at( 0 )->string() ); std::string modelName = node->children.at( 0 )->string();
try
{
m_library.m_models.push_back( SIM_MODEL_SPICE::Create( m_library, model ) );
m_library.m_modelNames.emplace_back( modelName );
}
catch( const IO_ERROR& e )
{
aReporter.Report( e.What(), RPT_SEVERITY_ERROR );
}
} }
catch( const IO_ERROR& e ) else if( node->is_type<SIM_LIBRARY_SPICE_PARSER::dotInclude>() )
{ {
DisplayErrorMessage( nullptr, e.What() ); std::string lib = node->children.at( 0 )->string();
try
{
if( m_library.m_pathResolver )
lib = ( *m_library.m_pathResolver )( lib, aFilePath );
readElement( lib, aReporter );
}
catch( const IO_ERROR& e )
{
aReporter.Report( e.What(), RPT_SEVERITY_ERROR );
}
}
else if( node->is_type<SIM_LIBRARY_SPICE_PARSER::unknownLine>() )
{
// Do nothing.
}
else
{
wxFAIL_MSG( "Unhandled parse tree node" );
} }
} }
else if( node->is_type<SIM_LIBRARY_SPICE_PARSER::dotInclude>() ) }
{ catch( const std::filesystem::filesystem_error& e )
std::string lib = node->children.at( 0 )->string(); {
aReporter.Report( e.what(), RPT_SEVERITY_ERROR );
if( m_library.m_pathResolver ) }
lib = ( *m_library.m_pathResolver )( lib, aFilePath ); catch( const tao::pegtl::parse_error& e )
{
readElement( lib ); aReporter.Report( e.what(), RPT_SEVERITY_ERROR );
}
else if( node->is_type<SIM_LIBRARY_SPICE_PARSER::unknownLine>() )
{
// Do nothing.
}
else
{
wxFAIL_MSG( "Unhandled parse tree node" );
}
} }
} }
void SPICE_LIBRARY_PARSER::ReadFile( const std::string& aFilePath ) void SPICE_LIBRARY_PARSER::ReadFile( const std::string& aFilePath, REPORTER* aReporter )
{ {
m_library.m_models.clear(); m_library.m_models.clear();
m_library.m_modelNames.clear(); m_library.m_modelNames.clear();
try if( aReporter )
{ {
readElement( aFilePath ); readElement( aFilePath, *aReporter );
} }
catch( const std::filesystem::filesystem_error& e ) else
{ {
THROW_IO_ERROR( e.what() ); wxString msg;
} WX_STRING_REPORTER reporter( &msg );
catch( const tao::pegtl::parse_error& e )
{ readElement( aFilePath, reporter );
THROW_IO_ERROR( e.what() );
if( reporter.HasMessage() )
THROW_IO_ERROR( msg );
} }
} }

View File

@ -2,7 +2,7 @@
* This program source code file is part of KiCad, a free EDA CAD application. * This program source code file is part of KiCad, a free EDA CAD application.
* *
* Copyright (C) 2022 Mikolaj Wielgus * Copyright (C) 2022 Mikolaj Wielgus
* Copyright (C) 2022 KiCad Developers, see AUTHORS.txt for contributors. * Copyright (C) 2022-2023 KiCad Developers, see AUTHORS.txt for contributors.
* *
* This program is free software; you can redistribute it and/or * This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License * modify it under the terms of the GNU General Public License
@ -28,6 +28,7 @@
#include <wx/string.h> #include <wx/string.h>
class SIM_LIBRARY_SPICE; class SIM_LIBRARY_SPICE;
class REPORTER;
class SPICE_LIBRARY_PARSER class SPICE_LIBRARY_PARSER
{ {
@ -39,10 +40,10 @@ public:
virtual ~SPICE_LIBRARY_PARSER() virtual ~SPICE_LIBRARY_PARSER()
{}; {};
virtual void ReadFile( const std::string& aFilePath ); virtual void ReadFile( const std::string& aFilePath, REPORTER* aReporter );
protected: protected:
void readElement( const std::string& aFilePath ); void readElement( const std::string& aFilePath, REPORTER& aReporter );
private: private:
SIM_LIBRARY_SPICE& m_library; SIM_LIBRARY_SPICE& m_library;

View File

@ -1,7 +1,7 @@
/* /*
* This program source code file is part of KiCad, a free EDA CAD application. * This program source code file is part of KiCad, a free EDA CAD application.
* *
* Copyright (C) 2022 KiCad Developers, see AUTHORS.TXT for contributors. * Copyright (C) 2022-2023 KiCad Developers, see AUTHORS.TXT for contributors.
* *
* This program is free software; you can redistribute it and/or * This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License * modify it under the terms of the GNU General Public License
@ -48,7 +48,7 @@ public:
{ {
std::string path = GetLibraryPath( aBaseName ); std::string path = GetLibraryPath( aBaseName );
m_library = std::make_unique<SIM_LIBRARY_SPICE>(); m_library = std::make_unique<SIM_LIBRARY_SPICE>();
m_library->ReadFile( path ); m_library->ReadFile( path, nullptr );
} }
void CompareToUsualDiodeModel( const SIM_MODEL& aModel, const std::string& aModelName, int aModelIndex ) void CompareToUsualDiodeModel( const SIM_MODEL& aModel, const std::string& aModelName, int aModelIndex )