Rip out parsing of SPICE libraries for netlisting.
We only need to parse the libraries for the Sim Model Editor dialog (so that we can determine the models to put in the popup). Doing it for netlisting just opens us up to incorrectly parsing the SPICE, and returns no value. This also means that a SIM_LIB_MGR manages a single library, and never multiple libraries. This also allows the tidying-up of some error reporting structures to better inform the user what went wrong. Fixes https://gitlab.com/kicad/code/kicad/issues/13431
This commit is contained in:
parent
595bf70d5d
commit
d839f11d49
|
@ -207,10 +207,9 @@ bool DIALOG_SIM_MODEL<T_symbol, T_field>::TransferDataToWindow()
|
|||
|
||||
for( const std::pair<std::string, std::string>& strs : kibismodel->GetIbisPins() )
|
||||
{
|
||||
if( strs.first
|
||||
== SIM_MODEL::GetFieldValue( &m_fields, SIM_LIBRARY_KIBIS::PIN_FIELD ) )
|
||||
if( strs.first == SIM_MODEL::GetFieldValue( &m_fields, SIM_LIBRARY_KIBIS::PIN_FIELD ) )
|
||||
{
|
||||
auto kibisLibrary = static_cast<const SIM_LIBRARY_KIBIS*>( library() );
|
||||
auto kibisLibrary = static_cast<const SIM_LIBRARY_KIBIS*>( m_libraryModelsMgr.GetLibrary() );
|
||||
|
||||
kibismodel->ChangePin( *kibisLibrary, strs.first );
|
||||
m_ibisPinCombobox->SetSelection( static_cast<int>( i ) );
|
||||
|
@ -310,7 +309,8 @@ bool DIALOG_SIM_MODEL<T_symbol, T_field>::TransferDataFromWindow()
|
|||
|
||||
std::string path;
|
||||
|
||||
if( ( library() && m_useLibraryModelRadioButton->GetValue() ) || isIbisLoaded() )
|
||||
if( ( m_libraryModelsMgr.GetLibrary() && m_useLibraryModelRadioButton->GetValue() )
|
||||
|| isIbisLoaded() )
|
||||
{
|
||||
path = m_libraryPathText->GetValue();
|
||||
wxFileName fn( path );
|
||||
|
@ -323,14 +323,14 @@ bool DIALOG_SIM_MODEL<T_symbol, T_field>::TransferDataFromWindow()
|
|||
|
||||
if( isIbisLoaded() )
|
||||
{
|
||||
SIM_MODEL_KIBIS* kibismodel = dynamic_cast<SIM_MODEL_KIBIS*>(
|
||||
SIM_MODEL_KIBIS* ibismodel = static_cast<SIM_MODEL_KIBIS*>(
|
||||
&m_libraryModelsMgr.GetModels().at( m_modelNameChoice->GetSelection() ).get() );
|
||||
|
||||
if( kibismodel )
|
||||
if( ibismodel )
|
||||
{
|
||||
SIM_MODEL::SetFieldValue(
|
||||
m_fields, SIM_LIBRARY_KIBIS::PIN_FIELD,
|
||||
kibismodel->GetIbisPins().at( m_ibisPinCombobox->GetSelection() ).first );
|
||||
ibismodel->GetIbisPins().at( m_ibisPinCombobox->GetSelection() ).first );
|
||||
|
||||
SIM_MODEL::SetFieldValue(
|
||||
m_fields, SIM_LIBRARY_KIBIS::MODEL_FIELD,
|
||||
|
@ -338,7 +338,7 @@ bool DIALOG_SIM_MODEL<T_symbol, T_field>::TransferDataFromWindow()
|
|||
|
||||
SIM_MODEL::SetFieldValue(
|
||||
m_fields, SIM_LIBRARY_KIBIS::DIFF_FIELD,
|
||||
( kibismodel->CanDifferential() && m_differentialCheckbox->GetValue() ) ? "1" : "" );
|
||||
ibismodel->CanDifferential() && m_differentialCheckbox->GetValue() ? "1" : "" );
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -675,8 +675,6 @@ template <typename T_symbol, typename T_field>
|
|||
void DIALOG_SIM_MODEL<T_symbol, T_field>::loadLibrary( const wxString& aLibraryPath,
|
||||
bool aForceReload )
|
||||
{
|
||||
auto libraries = m_libraryModelsMgr.GetLibraries();
|
||||
|
||||
wxString msg;
|
||||
WX_STRING_REPORTER reporter( &msg );
|
||||
|
||||
|
@ -699,7 +697,7 @@ void DIALOG_SIM_MODEL<T_symbol, T_field>::loadLibrary( const wxString& aLibraryP
|
|||
|
||||
std::string modelName = SIM_MODEL::GetFieldValue( &m_fields, SIM_LIBRARY::NAME_FIELD );
|
||||
|
||||
for( auto& [baseModelName, baseModel] : library()->GetModels() )
|
||||
for( auto& [baseModelName, baseModel] : m_libraryModelsMgr.GetLibrary()->GetModels() )
|
||||
{
|
||||
if( baseModelName == modelName )
|
||||
m_libraryModelsMgr.CreateModel( &baseModel, sourcePins, m_fields );
|
||||
|
@ -715,7 +713,7 @@ void DIALOG_SIM_MODEL<T_symbol, T_field>::loadLibrary( const wxString& aLibraryP
|
|||
|
||||
wxArrayString modelNames;
|
||||
|
||||
for( auto& [name, model] : library()->GetModels() )
|
||||
for( auto& [name, model] : m_libraryModelsMgr.GetLibrary()->GetModels() )
|
||||
modelNames.Add( name );
|
||||
|
||||
m_modelNameChoice->Clear();
|
||||
|
@ -924,16 +922,6 @@ SIM_MODEL& DIALOG_SIM_MODEL<T_symbol, T_field>::curModel() const
|
|||
}
|
||||
|
||||
|
||||
template <typename T_symbol, typename T_field>
|
||||
const SIM_LIBRARY* DIALOG_SIM_MODEL<T_symbol, T_field>::library() const
|
||||
{
|
||||
if( m_libraryModelsMgr.GetLibraries().size() == 1 )
|
||||
return &m_libraryModelsMgr.GetLibraries().begin()->second.get();
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
|
||||
template <typename T_symbol, typename T_field>
|
||||
wxString DIALOG_SIM_MODEL<T_symbol, T_field>::getSymbolPinString( int symbolPinIndex ) const
|
||||
{
|
||||
|
@ -1099,19 +1087,18 @@ void DIALOG_SIM_MODEL<T_symbol, T_field>::onIbisPinCombobox( wxCommandEvent& aEv
|
|||
{
|
||||
wxArrayString modelLabels;
|
||||
|
||||
SIM_MODEL_KIBIS& kibisModel = static_cast<SIM_MODEL_KIBIS&>( curModel() );
|
||||
SIM_MODEL_KIBIS& ibisModel = static_cast<SIM_MODEL_KIBIS&>( curModel() );
|
||||
|
||||
std::vector<std::pair<std::string, std::string>> strs = kibisModel.GetIbisPins();
|
||||
std::vector<std::pair<std::string, std::string>> strs = ibisModel.GetIbisPins();
|
||||
std::string pinNumber = strs.at( m_ibisPinCombobox->GetSelection() ).first;
|
||||
|
||||
const SIM_LIBRARY_KIBIS* kibisLibrary = dynamic_cast<const SIM_LIBRARY_KIBIS*>( library() );
|
||||
auto ibisLibrary = static_cast<const SIM_LIBRARY_KIBIS*>( m_libraryModelsMgr.GetLibrary() );
|
||||
|
||||
kibisModel.ChangePin( *kibisLibrary, pinNumber );
|
||||
ibisModel.ChangePin( *ibisLibrary, pinNumber );
|
||||
|
||||
kibisModel.m_enableDiff = static_cast<const SIM_LIBRARY_KIBIS*>( library() )
|
||||
->isPinDiff( kibisModel.GetComponentName(), pinNumber );
|
||||
ibisModel.m_enableDiff = ibisLibrary->isPinDiff( ibisModel.GetComponentName(), pinNumber );
|
||||
|
||||
for( wxString modelName : kibisModel.GetIbisModels() )
|
||||
for( wxString modelName : ibisModel.GetIbisModels() )
|
||||
modelLabels.Add( modelName );
|
||||
|
||||
m_ibisModelCombobox->Set( modelLabels );
|
||||
|
|
|
@ -86,7 +86,6 @@ private:
|
|||
int findSymbolPinRow( const wxString& aSymbolPinNumber ) const;
|
||||
|
||||
SIM_MODEL& curModel() const;
|
||||
const SIM_LIBRARY* library() const;
|
||||
|
||||
wxString getSymbolPinString( int aSymbolPinNumber ) const;
|
||||
wxString getModelPinString( int aModelPinIndex ) const;
|
||||
|
@ -114,7 +113,10 @@ private:
|
|||
|
||||
void adjustParamGridColumns( int aWidth, bool aForce );
|
||||
|
||||
bool isIbisLoaded() { return dynamic_cast<const SIM_LIBRARY_KIBIS*>( library() ); }
|
||||
bool isIbisLoaded()
|
||||
{
|
||||
return dynamic_cast<const SIM_LIBRARY_KIBIS*>( m_libraryModelsMgr.GetLibrary() ) != nullptr;
|
||||
}
|
||||
|
||||
private:
|
||||
T_symbol& m_symbol;
|
||||
|
|
|
@ -1016,9 +1016,7 @@ int ERC_TESTER::TestSimModelIssues()
|
|||
WX_STRING_REPORTER reporter( &msg );
|
||||
SCH_SHEET_LIST sheets = m_schematic->GetSheets();
|
||||
int err_count = 0;
|
||||
SIM_LIB_MGR libMgr( &m_schematic->Prj() );
|
||||
|
||||
libMgr.SetReporter( &reporter );
|
||||
SIM_LIB_MGR libMgr( &m_schematic->Prj(), &reporter );
|
||||
|
||||
for( SCH_SHEET_PATH& sheet : sheets )
|
||||
{
|
||||
|
|
|
@ -26,7 +26,6 @@
|
|||
#include <sim/kibis/kibis.h>
|
||||
#include <netlist_exporter_spice.h>
|
||||
#include <sim/ngspice_circuit_model.h>
|
||||
#include <sim/sim_library_spice.h>
|
||||
#include <sim/sim_model_raw_spice.h>
|
||||
#include <sim/sim_model_ideal.h>
|
||||
#include <sim/spice_grammar.h>
|
||||
|
@ -56,7 +55,7 @@ namespace NETLIST_EXPORTER_SPICE_PARSER
|
|||
{
|
||||
using namespace SPICE_GRAMMAR;
|
||||
|
||||
struct textGrammar : must<spiceSourceNothrow> {};
|
||||
struct textGrammar : must<spiceSource> {};
|
||||
|
||||
template <typename Rule> struct textSelector : std::false_type {};
|
||||
template <> struct textSelector<modelUnit> : std::true_type {};
|
||||
|
@ -162,7 +161,7 @@ bool NETLIST_EXPORTER_SPICE::ReadSchematicAndLibraries( unsigned aNetlistOptions
|
|||
std::set<std::string> refNames; // Set of reference names to check for duplication.
|
||||
int ncCounter = 1;
|
||||
|
||||
ReadDirectives( aNetlistOptions, aReporter );
|
||||
ReadDirectives( aNetlistOptions );
|
||||
|
||||
m_nets.clear();
|
||||
m_items.clear();
|
||||
|
@ -260,8 +259,6 @@ bool NETLIST_EXPORTER_SPICE::ReadSchematicAndLibraries( unsigned aNetlistOptions
|
|||
spiceItem.fields.back().SetText( pinMap );
|
||||
}
|
||||
|
||||
// JEY TODO: move from try/catch to REPORTER interface...
|
||||
// readModel() is the only one that throws, and it won't if m_libMgr has a REPORTER
|
||||
try
|
||||
{
|
||||
readRefName( sheet, *symbol, spiceItem, refNames );
|
||||
|
@ -277,7 +274,7 @@ bool NETLIST_EXPORTER_SPICE::ReadSchematicAndLibraries( unsigned aNetlistOptions
|
|||
{
|
||||
msg.Printf( _( "Error reading simulation model from symbol '%s':\n%s" ),
|
||||
symbol->GetRef( &sheet ),
|
||||
e.What() );
|
||||
e.Problem() );
|
||||
aReporter.Report( msg, RPT_SEVERITY_ERROR );
|
||||
}
|
||||
}
|
||||
|
@ -364,7 +361,7 @@ const SPICE_ITEM* NETLIST_EXPORTER_SPICE::FindItem( const std::string& aRefName
|
|||
}
|
||||
|
||||
|
||||
void NETLIST_EXPORTER_SPICE::ReadDirectives( unsigned aNetlistOptions, REPORTER& aReporter )
|
||||
void NETLIST_EXPORTER_SPICE::ReadDirectives( unsigned aNetlistOptions )
|
||||
{
|
||||
wxString msg;
|
||||
wxString text;
|
||||
|
@ -395,6 +392,10 @@ void NETLIST_EXPORTER_SPICE::ReadDirectives( unsigned aNetlistOptions, REPORTER&
|
|||
}
|
||||
catch( const tao::pegtl::parse_error& )
|
||||
{
|
||||
// If we couldn't parse it, but it -looks- like SPICE, then send it as raw SPICE
|
||||
if( text.StartsWith( "." ) || text.StartsWith( "*" ) )
|
||||
m_directives.emplace_back( text );
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
|
@ -404,8 +405,6 @@ void NETLIST_EXPORTER_SPICE::ReadDirectives( unsigned aNetlistOptions, REPORTER&
|
|||
{
|
||||
if( node->is_type<NETLIST_EXPORTER_SPICE_PARSER::dotTitle>() )
|
||||
m_title = node->children.at( 0 )->string();
|
||||
else if( node->is_type<NETLIST_EXPORTER_SPICE_PARSER::dotInclude>() )
|
||||
m_libMgr.AddLibrary( node->children.at( 0 )->string() );
|
||||
else
|
||||
m_directives.emplace_back( node->string() );
|
||||
}
|
||||
|
@ -415,8 +414,7 @@ void NETLIST_EXPORTER_SPICE::ReadDirectives( unsigned aNetlistOptions, REPORTER&
|
|||
|
||||
|
||||
void NETLIST_EXPORTER_SPICE::readRefName( SCH_SHEET_PATH& aSheet, SCH_SYMBOL& aSymbol,
|
||||
SPICE_ITEM& aItem,
|
||||
std::set<std::string>& aRefNames )
|
||||
SPICE_ITEM& aItem, std::set<std::string>& aRefNames )
|
||||
{
|
||||
aItem.refName = aSymbol.GetRef( &aSheet );
|
||||
|
||||
|
@ -524,12 +522,6 @@ void NETLIST_EXPORTER_SPICE::writeInclude( OUTPUTFORMATTER& aFormatter, unsigned
|
|||
|
||||
void NETLIST_EXPORTER_SPICE::writeIncludes( OUTPUTFORMATTER& aFormatter, unsigned aNetlistOptions )
|
||||
{
|
||||
for( auto& [path, library] : m_libMgr.GetLibraries() )
|
||||
{
|
||||
if( dynamic_cast<const SIM_LIBRARY_SPICE*>( &library.get() ) )
|
||||
writeInclude( aFormatter, aNetlistOptions, path );
|
||||
}
|
||||
|
||||
for( const wxString& path : m_rawIncludes )
|
||||
writeInclude( aFormatter, aNetlistOptions, path );
|
||||
}
|
||||
|
@ -560,7 +552,7 @@ void NETLIST_EXPORTER_SPICE::writeItems( OUTPUTFORMATTER& aFormatter )
|
|||
|
||||
|
||||
void NETLIST_EXPORTER_SPICE::WriteDirectives( OUTPUTFORMATTER& aFormatter,
|
||||
unsigned aNetlistOptions ) const
|
||||
unsigned aNetlistOptions ) const
|
||||
{
|
||||
if( aNetlistOptions & OPTION_SAVE_ALL_VOLTAGES )
|
||||
aFormatter.Print( 0, ".save all\n" );
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
*
|
||||
* Copyright (C) 1992-2013 jp.charras at wanadoo.fr
|
||||
* Copyright (C) 2013 SoftPLC Corporation, Dick Hollenbeck <dick@softplc.com>
|
||||
* Copyright (C) 1992-2021 KiCad Developers
|
||||
* Copyright (C) 1992-2023 KiCad Developers, see AUTHORS.TXT for contributors.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
|
@ -126,7 +126,7 @@ public:
|
|||
const std::vector<std::string>& GetDirectives() { return m_directives; }
|
||||
|
||||
protected:
|
||||
void ReadDirectives( unsigned aNetlistOptions, REPORTER& aReporter );
|
||||
void ReadDirectives( unsigned aNetlistOptions );
|
||||
virtual void WriteDirectives( OUTPUTFORMATTER& aFormatter, unsigned aNetlistOptions ) const;
|
||||
|
||||
virtual std::string GenerateItemPinNetName( const std::string& aNetName, int& aNcCounter ) const;
|
||||
|
|
|
@ -350,7 +350,8 @@ void SCH_SEXPR_PLUGIN::Save( const wxString& aFileName, SCH_SHEET* aSheet, SCHEM
|
|||
|
||||
Format( aSheet );
|
||||
|
||||
aSheet->GetScreen()->SetFileExists( true );
|
||||
if( aSheet->GetScreen() )
|
||||
aSheet->GetScreen()->SetFileExists( true );
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2016-2022 CERN
|
||||
* Copyright (C) 1992-2022 KiCad Developers, see AUTHORS.TXT for contributors.
|
||||
* Copyright (C) 1992-2023 KiCad Developers, see AUTHORS.TXT for contributors.
|
||||
* @author Maciej Suminski <maciej.suminski@cern.ch>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
|
@ -67,10 +67,9 @@ SIM_PLOT_TYPE NGSPICE_CIRCUIT_MODEL::VectorToSignal( const std::string& aVector,
|
|||
|
||||
wxString NGSPICE_CIRCUIT_MODEL::GetSheetSimCommand()
|
||||
{
|
||||
NULL_REPORTER devnull;
|
||||
wxString simCmd;
|
||||
|
||||
ReadDirectives( 0, devnull );
|
||||
ReadDirectives( 0 );
|
||||
|
||||
for( const std::string& directive : GetDirectives() )
|
||||
{
|
||||
|
|
|
@ -36,20 +36,16 @@
|
|||
#include <sim/sim_model.h>
|
||||
#include <sim/sim_model_ideal.h>
|
||||
|
||||
SIM_LIB_MGR::SIM_LIB_MGR( const PROJECT* aPrj ) :
|
||||
using namespace std::placeholders;
|
||||
|
||||
|
||||
SIM_LIB_MGR::SIM_LIB_MGR( const PROJECT* aPrj, REPORTER* aReporter ) :
|
||||
m_project( aPrj ),
|
||||
m_reporter( nullptr )
|
||||
m_reporter( aReporter )
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
void SIM_LIB_MGR::Clear()
|
||||
{
|
||||
m_libraries.clear();
|
||||
m_models.clear();
|
||||
}
|
||||
|
||||
|
||||
wxString SIM_LIB_MGR::ResolveLibraryPath( const wxString& aLibraryPath, const PROJECT* aProject )
|
||||
{
|
||||
wxString expandedPath = ExpandEnvVarSubstitutions( aLibraryPath, aProject );
|
||||
|
@ -77,7 +73,8 @@ wxString SIM_LIB_MGR::ResolveLibraryPath( const wxString& aLibraryPath, const PR
|
|||
}
|
||||
|
||||
|
||||
std::string SIM_LIB_MGR::ResolveEmbeddedLibraryPath( const std::string& aLibPath, const std::string& aRelativeLib )
|
||||
std::string SIM_LIB_MGR::ResolveEmbeddedLibraryPath( const std::string& aLibPath,
|
||||
const std::string& aRelativeLib )
|
||||
{
|
||||
wxFileName testPath( aLibPath );
|
||||
wxString fullPath( aLibPath );
|
||||
|
@ -115,37 +112,19 @@ std::string SIM_LIB_MGR::ResolveEmbeddedLibraryPath( const std::string& aLibPath
|
|||
}
|
||||
|
||||
|
||||
void SIM_LIB_MGR::AddLibrary( const wxString& aLibraryPath )
|
||||
{
|
||||
try
|
||||
{
|
||||
wxString 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 );
|
||||
|
||||
m_libraries.try_emplace( path, SIM_LIBRARY::Create( path, m_reporter, &f2 ) );
|
||||
}
|
||||
catch( const IO_ERROR& e )
|
||||
{
|
||||
m_reporter->Report( e.What() );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void SIM_LIB_MGR::SetLibrary( const wxString& aLibraryPath )
|
||||
{
|
||||
m_models.clear();
|
||||
m_library = nullptr;
|
||||
|
||||
try
|
||||
{
|
||||
wxString 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 );
|
||||
std::bind( &SIM_LIB_MGR::ResolveEmbeddedLibraryPath, this, _1, _2 );
|
||||
|
||||
std::unique_ptr<SIM_LIBRARY> library = SIM_LIBRARY::Create( path, m_reporter, &f2 );
|
||||
|
||||
Clear();
|
||||
m_libraries[path] = std::move( library );
|
||||
m_library = SIM_LIBRARY::Create( path, m_reporter, &f2 );
|
||||
}
|
||||
catch( const IO_ERROR& e )
|
||||
{
|
||||
|
@ -285,60 +264,60 @@ SIM_LIBRARY::MODEL SIM_LIB_MGR::CreateModel( const wxString& aLibraryPath,
|
|||
{
|
||||
wxString path;
|
||||
wxString msg;
|
||||
SIM_LIBRARY* library = nullptr;
|
||||
SIM_MODEL* baseModel = nullptr;
|
||||
std::string modelName;
|
||||
|
||||
wxASSERT( !m_library );
|
||||
|
||||
try
|
||||
{
|
||||
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 );
|
||||
std::bind( &SIM_LIB_MGR::ResolveEmbeddedLibraryPath, this, _1, _2 );
|
||||
|
||||
auto it = m_libraries.try_emplace( path, SIM_LIBRARY::Create( path, m_reporter, &f2 ) ).first;
|
||||
library = &*it->second;
|
||||
m_library = SIM_LIBRARY::Create( path, m_reporter, &f2 );
|
||||
}
|
||||
catch( const IO_ERROR& e )
|
||||
{
|
||||
msg.Printf( _( "Error loading simulation model library '%s': %s" ),
|
||||
path,
|
||||
e.What() );
|
||||
|
||||
if( m_reporter )
|
||||
{
|
||||
msg.Printf( _( "Error loading simulation model library '%s': %s" ),
|
||||
path,
|
||||
e.What() );
|
||||
|
||||
m_reporter->Report( msg, RPT_SEVERITY_ERROR );
|
||||
else
|
||||
THROW_IO_ERROR( msg );
|
||||
}
|
||||
}
|
||||
|
||||
if( aBaseModelName == "" )
|
||||
{
|
||||
msg.Printf( _( "Error loading simulation model: no '%s' field" ),
|
||||
SIM_LIBRARY::NAME_FIELD );
|
||||
|
||||
if( m_reporter )
|
||||
{
|
||||
msg.Printf( _( "Error loading simulation model: no '%s' field" ),
|
||||
SIM_LIBRARY::NAME_FIELD );
|
||||
|
||||
m_reporter->Report( msg, RPT_SEVERITY_ERROR );
|
||||
else
|
||||
THROW_IO_ERROR( msg );
|
||||
}
|
||||
|
||||
modelName = _( "unknown" ).ToStdString();
|
||||
}
|
||||
else if( library )
|
||||
else if( m_library )
|
||||
{
|
||||
baseModel = library->FindModel( aBaseModelName );
|
||||
baseModel = m_library->FindModel( aBaseModelName );
|
||||
modelName = aBaseModelName;
|
||||
|
||||
if( !baseModel )
|
||||
{
|
||||
msg.Printf( _( "Error loading simulation model: could not find base model '%s' "
|
||||
"in library '%s'" ),
|
||||
aBaseModelName,
|
||||
path );
|
||||
|
||||
if( m_reporter )
|
||||
{
|
||||
msg.Printf( _( "Error loading simulation model: could not find base model '%s' "
|
||||
"in library '%s'" ),
|
||||
aBaseModelName,
|
||||
path );
|
||||
|
||||
m_reporter->Report( msg, RPT_SEVERITY_ERROR );
|
||||
else
|
||||
THROW_IO_ERROR( msg );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -348,20 +327,15 @@ SIM_LIBRARY::MODEL SIM_LIB_MGR::CreateModel( const wxString& aLibraryPath,
|
|||
}
|
||||
|
||||
|
||||
void SIM_LIB_MGR::SetModel( int aIndex, std::unique_ptr<SIM_MODEL> aModel )
|
||||
const SIM_LIBRARY* SIM_LIB_MGR::GetLibrary() const
|
||||
{
|
||||
m_models.at( aIndex ) = std::move( aModel );
|
||||
return m_library.get();
|
||||
}
|
||||
|
||||
|
||||
std::map<wxString, std::reference_wrapper<const SIM_LIBRARY>> SIM_LIB_MGR::GetLibraries() const
|
||||
void SIM_LIB_MGR::SetModel( int aIndex, std::unique_ptr<SIM_MODEL> aModel )
|
||||
{
|
||||
std::map<wxString, std::reference_wrapper<const SIM_LIBRARY>> libraries;
|
||||
|
||||
for( auto& [path, library] : m_libraries )
|
||||
libraries.try_emplace( path, *library );
|
||||
|
||||
return libraries;
|
||||
m_models.at( aIndex ) = std::move( aModel );
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -40,15 +40,13 @@ class SCH_SYMBOL;
|
|||
class SIM_LIB_MGR
|
||||
{
|
||||
public:
|
||||
SIM_LIB_MGR( const PROJECT* aPrj );
|
||||
SIM_LIB_MGR( const PROJECT* aPrj, REPORTER* aReporter = nullptr );
|
||||
virtual ~SIM_LIB_MGR() = default;
|
||||
|
||||
void SetReporter( REPORTER* aReporter ) { m_reporter = aReporter; }
|
||||
|
||||
void Clear();
|
||||
|
||||
void AddLibrary( const wxString& aLibraryPath );
|
||||
void SetLibrary( const wxString& aLibraryPath );
|
||||
const SIM_LIBRARY* GetLibrary() const;
|
||||
|
||||
SIM_MODEL& CreateModel( SIM_MODEL::TYPE aType, const std::vector<LIB_PIN*>& aPins );
|
||||
|
||||
|
@ -73,18 +71,18 @@ public:
|
|||
|
||||
void SetModel( int aIndex, std::unique_ptr<SIM_MODEL> aModel );
|
||||
|
||||
std::map<wxString, std::reference_wrapper<const SIM_LIBRARY>> GetLibraries() const;
|
||||
std::vector<std::reference_wrapper<SIM_MODEL>> GetModels() const;
|
||||
|
||||
static wxString ResolveLibraryPath( const wxString& aLibraryPath, const PROJECT* aProject );
|
||||
|
||||
std::string ResolveEmbeddedLibraryPath( const std::string& aLibPath, const std::string& aRelativeLib );
|
||||
std::string ResolveEmbeddedLibraryPath( const std::string& aLibPath,
|
||||
const std::string& aRelativeLib );
|
||||
|
||||
private:
|
||||
const PROJECT* m_project;
|
||||
REPORTER* m_reporter;
|
||||
std::map<wxString, std::unique_ptr<SIM_LIBRARY>> m_libraries;
|
||||
std::vector<std::unique_ptr<SIM_MODEL>> m_models;
|
||||
const PROJECT* m_project;
|
||||
REPORTER* m_reporter;
|
||||
std::unique_ptr<SIM_LIBRARY> m_library;
|
||||
std::vector<std::unique_ptr<SIM_MODEL>> m_models;
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
*
|
||||
* Copyright (C) 2022 Mikolaj Wielgus
|
||||
* 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
|
||||
* modify it under the terms of the GNU General Public License
|
||||
|
@ -591,9 +591,9 @@ std::unique_ptr<SIM_MODEL> SIM_MODEL::Create( const std::vector<T>& aFields,
|
|||
{
|
||||
// We own the pin syntax, so if we can't parse it then there's an error, full stop.
|
||||
if( aReporter )
|
||||
aReporter->Report( err.What(), RPT_SEVERITY_ERROR );
|
||||
aReporter->Report( err.Problem(), RPT_SEVERITY_ERROR );
|
||||
else
|
||||
DisplayErrorMessage( nullptr, err.What() );
|
||||
THROW_IO_ERROR( err.Problem() );
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1575,11 +1575,9 @@ void SIM_MODEL::MigrateSimModel( T_symbol& aSymbol, const PROJECT* aProject )
|
|||
{
|
||||
wxString msg;
|
||||
WX_STRING_REPORTER reporter( &msg );
|
||||
SIM_LIB_MGR libMgr( aProject );
|
||||
SIM_LIB_MGR libMgr( aProject, &reporter );
|
||||
std::vector<T_field> emptyFields;
|
||||
|
||||
libMgr.SetReporter( &reporter );
|
||||
|
||||
SIM_LIBRARY::MODEL model = libMgr.CreateModel( spiceLib, spiceModel.ToStdString(),
|
||||
emptyFields, sourcePins );
|
||||
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* 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
|
||||
* modify it under the terms of the GNU General Public License
|
||||
|
@ -159,7 +159,7 @@ void SIM_MODEL_SERIALIZER::ParseValue( const std::string& aValue )
|
|||
{
|
||||
try
|
||||
{
|
||||
tao::pegtl::string_input<> in( aValue, "'Value' symbol field" );
|
||||
tao::pegtl::string_input<> in( aValue, "Value field" );
|
||||
auto root =
|
||||
tao::pegtl::parse_tree::parse<SIM_MODEL_SERIALIZER_PARSER::fieldInferValueGrammar,
|
||||
SIM_MODEL_SERIALIZER_PARSER::fieldInferValueSelector,
|
||||
|
@ -179,9 +179,7 @@ void SIM_MODEL_SERIALIZER::ParseValue( const std::string& aValue )
|
|||
}
|
||||
catch( const tao::pegtl::parse_error& e )
|
||||
{
|
||||
wxString msg;
|
||||
msg.Printf( wxT( "ParseValue: parse <%s>, error <%s>" ), aValue.c_str(), e.what() );
|
||||
THROW_IO_ERROR( msg );
|
||||
THROW_IO_ERROR( e.what() );
|
||||
}
|
||||
|
||||
m_model.SetIsStoredInValue( true );
|
||||
|
@ -190,7 +188,7 @@ void SIM_MODEL_SERIALIZER::ParseValue( const std::string& aValue )
|
|||
|
||||
bool SIM_MODEL_SERIALIZER::ParseParams( const std::string& aParams )
|
||||
{
|
||||
tao::pegtl::string_input<> in( aParams, "'Sim.Params' symbol field" );
|
||||
tao::pegtl::string_input<> in( aParams, "Sim.Params field" );
|
||||
std::unique_ptr<tao::pegtl::parse_tree::node> root;
|
||||
|
||||
try
|
||||
|
@ -205,9 +203,7 @@ bool SIM_MODEL_SERIALIZER::ParseParams( const std::string& aParams )
|
|||
}
|
||||
catch( const tao::pegtl::parse_error& e )
|
||||
{
|
||||
wxString msg;
|
||||
msg.Printf( wxT( "ParseParams: parse <%s>, error <%s>" ), aParams.c_str(), e.what() );
|
||||
THROW_IO_ERROR( msg );
|
||||
THROW_IO_ERROR( e.what() );
|
||||
}
|
||||
|
||||
std::string paramName;
|
||||
|
@ -254,7 +250,7 @@ void SIM_MODEL_SERIALIZER::ParsePins( const std::string& aPins )
|
|||
if( aPins == "" )
|
||||
return;
|
||||
|
||||
tao::pegtl::string_input<> in( aPins, "'Sim.Pins' symbol field" );
|
||||
tao::pegtl::string_input<> in( aPins, "Sim.Pins field" );
|
||||
std::unique_ptr<tao::pegtl::parse_tree::node> root;
|
||||
|
||||
try
|
||||
|
@ -275,9 +271,7 @@ void SIM_MODEL_SERIALIZER::ParsePins( const std::string& aPins )
|
|||
}
|
||||
catch( const tao::pegtl::parse_error& e )
|
||||
{
|
||||
wxString msg;
|
||||
msg.Printf( wxT( "ParsePins: parse <%s>, error <%s>" ), aPins.c_str(), e.what() );
|
||||
THROW_IO_ERROR( msg );
|
||||
THROW_IO_ERROR( e.what() );
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* 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
|
||||
* modify it under the terms of the GNU General Public License
|
||||
|
@ -260,7 +260,6 @@ namespace SPICE_GRAMMAR
|
|||
|
||||
|
||||
struct spiceSource : star<spiceUnit> {};
|
||||
struct spiceSourceNothrow : star<try_catch<spiceUnit>> {};
|
||||
struct spiceSourceGrammar : must<spiceSource> {};
|
||||
|
||||
|
||||
|
@ -289,8 +288,6 @@ namespace SPICE_GRAMMAR
|
|||
"expected Spice directive, item, subcircuit definitions, or empty or commented-out line";
|
||||
template <> inline constexpr auto errorMessage<spiceSource> =
|
||||
"expected zero or more Spice directives, items, subcircuit definitions, or empty or commented-out lines";
|
||||
template <> inline constexpr auto errorMessage<spiceSourceNothrow> =
|
||||
"expected zero or more Spice directives, items, subcircuit definitions, or empty or commented-out lines";
|
||||
|
||||
// We create a custom PEGTL control to modify the parser error messages.
|
||||
struct error
|
||||
|
|
|
@ -489,10 +489,15 @@ int SCH_EDITOR_CONTROL::SimProbe( const TOOL_EVENT& aEvent )
|
|||
LIB_PIN* pin = static_cast<SCH_PIN*>( item )->GetLibPin();
|
||||
SCH_SYMBOL* symbol = static_cast<SCH_SYMBOL*>( item->GetParent() );
|
||||
|
||||
// JEY TODO: move to reporter interface instead of try/catch....
|
||||
SIM_LIB_MGR mgr( &m_frame->Prj() );
|
||||
wxString msg;
|
||||
WX_STRING_REPORTER reporter( &msg );
|
||||
SIM_LIB_MGR mgr( &m_frame->Prj(), &reporter );
|
||||
|
||||
SIM_MODEL& model = mgr.CreateModel( &sheet, *symbol ).model;
|
||||
|
||||
if( reporter.HasMessage() )
|
||||
THROW_IO_ERROR( msg );
|
||||
|
||||
SPICE_ITEM spiceItem;
|
||||
spiceItem.refName = std::string( symbol->GetRef( &sheet ).ToUTF8() );
|
||||
std::vector<std::string> currentNames =
|
||||
|
|
Loading…
Reference in New Issue