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:
Jeff Young 2023-01-12 12:46:52 +00:00
parent 595bf70d5d
commit d839f11d49
13 changed files with 104 additions and 159 deletions

View File

@ -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 );

View File

@ -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;

View File

@ -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 )
{

View File

@ -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" );

View File

@ -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;

View File

@ -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 );
}

View File

@ -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() )
{

View File

@ -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 );
}

View File

@ -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;
};

View File

@ -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 );

View File

@ -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() );
}
}

View File

@ -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

View File

@ -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 =