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:
parent
d1c2ab957b
commit
9b9795a87d
|
@ -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 );
|
||||||
|
|
|
@ -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 )
|
||||||
{
|
{
|
||||||
|
|
|
@ -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() );
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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() };
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -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,
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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).
|
||||||
|
|
|
@ -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 );
|
||||||
|
|
|
@ -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{};
|
||||||
|
|
|
@ -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 );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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() )
|
||||||
{
|
{
|
||||||
|
|
|
@ -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,
|
||||||
|
|
|
@ -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 );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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 )
|
||||||
|
|
Loading…
Reference in New Issue