Centralize SPICE lib path resolution and support SPICE_LIB_DIR.

Fixes https://gitlab.com/kicad/code/kicad/issues/13081
This commit is contained in:
Jeff Young 2022-12-07 22:32:50 +00:00
parent bb6544914e
commit e8980e9024
8 changed files with 92 additions and 51 deletions

View File

@ -614,17 +614,12 @@ void DIALOG_SIM_MODEL<T>::loadLibrary( const wxString& aLibraryPath, bool aForce
{
auto libraries = m_libraryModelsMgr.GetLibraries();
// Loading the same library as previously should normally be a no-op except when done using the
// library browse button.
if( !aForceReload && libraries.size() >= 1 && libraries.begin()->first == aLibraryPath )
return;
DIALOG_IBIS_PARSER_REPORTER dlg( this );
dlg.m_messagePanel->Clear();
try
{
m_libraryModelsMgr.CreateLibrary( aLibraryPath, &dlg.m_messagePanel->Reporter() );
m_libraryModelsMgr.SetLibrary( aLibraryPath, &dlg.m_messagePanel->Reporter() );
}
catch( const IO_ERROR& e )
{

View File

@ -359,7 +359,7 @@ void NETLIST_EXPORTER_SPICE::ReadDirectives( unsigned aNetlistOptions, REPORTER&
try
{
m_libMgr.CreateLibrary( path, &aReporter );
m_libMgr.AddLibrary( path, &aReporter );
}
catch( const IO_ERROR& e )
{

View File

@ -46,14 +46,51 @@ void SIM_LIB_MGR::Clear()
}
SIM_LIBRARY& SIM_LIB_MGR::CreateLibrary( const wxString& aLibraryPath, REPORTER* aReporter )
wxString SIM_LIB_MGR::ResolveLibraryPath( const wxString& aLibraryPath, const PROJECT& aProject )
{
wxString path = ExpandEnvVarSubstitutions( aLibraryPath, &m_project );
wxString absolutePath = m_project.AbsolutePath( path );
wxString expandedPath = ExpandEnvVarSubstitutions( aLibraryPath, &aProject );
wxFileName fn( expandedPath );
if( fn.IsAbsolute() )
return fn.GetFullPath();
wxFileName projectFn( aProject.AbsolutePath( expandedPath ) );
if( projectFn.Exists() )
return projectFn.GetFullPath();
wxFileName spiceLibFn( expandedPath );
wxString spiceLibDir;
wxGetEnv( wxT( "SPICE_LIB_DIR" ), &spiceLibDir );
if( !spiceLibDir.IsEmpty() && spiceLibFn.MakeAbsolute( spiceLibDir ) && spiceLibFn.Exists() )
return spiceLibFn.GetFullPath();
THROW_IO_ERROR( wxString::Format( _( "Simulation model library not found at '%s' or '%s'" ),
projectFn.GetFullPath(),
spiceLibFn.GetFullPath() ) );
}
SIM_LIBRARY& SIM_LIB_MGR::AddLibrary( const wxString& aLibraryPath, REPORTER* aReporter )
{
// May throw an exception.
wxString path = ResolveLibraryPath( aLibraryPath, m_project );
// May throw an exception.
std::unique_ptr<SIM_LIBRARY> library = SIM_LIBRARY::Create( m_project.AbsolutePath( path ),
aReporter );
auto it = m_libraries.try_emplace( path, SIM_LIBRARY::Create( path, aReporter ) ) .first;
return *it->second;
}
SIM_LIBRARY& SIM_LIB_MGR::SetLibrary( const wxString& aLibraryPath, REPORTER* aReporter )
{
// May throw an exception.
wxString path = ResolveLibraryPath( aLibraryPath, m_project );
// May throw an exception.
std::unique_ptr<SIM_LIBRARY> library = SIM_LIBRARY::Create( path, aReporter );
Clear();
m_libraries[path] = std::move( library );
@ -150,21 +187,19 @@ SIM_LIBRARY::MODEL SIM_LIB_MGR::CreateModel( const wxString& aLibraryPath,
const std::vector<T>& aFields,
int aSymbolPinCount )
{
wxString path = ExpandEnvVarSubstitutions( aLibraryPath, &m_project );
wxString absolutePath = m_project.AbsolutePath( path );
wxString path = ResolveLibraryPath( aLibraryPath, m_project );
SIM_LIBRARY* library = nullptr;
try
{
auto it = m_libraries.try_emplace( path, SIM_LIBRARY::Create( absolutePath ) ).first;
auto it = m_libraries.try_emplace( path, SIM_LIBRARY::Create( path ) ).first;
library = &*it->second;
}
catch( const IO_ERROR& e )
{
THROW_IO_ERROR(
wxString::Format( _( "Error loading simulation model library '%s': %s" ),
absolutePath,
e.What() ) );
THROW_IO_ERROR( wxString::Format( _( "Error loading simulation model library '%s': %s" ),
path,
e.What() ) );
}
if( aBaseModelName == "" )
@ -180,7 +215,7 @@ SIM_LIBRARY::MODEL SIM_LIB_MGR::CreateModel( const wxString& aLibraryPath,
THROW_IO_ERROR( wxString::Format( _( "Error loading simulation model: could not find "
"base model '%s' in library '%s'" ),
aBaseModelName,
absolutePath ) );
path ) );
}
m_models.push_back( SIM_MODEL::Create( *baseModel, aSymbolPinCount, aFields ) );

View File

@ -45,7 +45,8 @@ public:
void Clear();
SIM_LIBRARY& CreateLibrary( const wxString& aLibraryPath, REPORTER* aReporter );
SIM_LIBRARY& AddLibrary( const wxString& aLibraryPath, REPORTER* aReporter );
SIM_LIBRARY& SetLibrary( const wxString& aLibraryPath, REPORTER* aReporter );
SIM_MODEL& CreateModel( SIM_MODEL::TYPE aType, int aSymbolPinCount );
@ -70,6 +71,8 @@ public:
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 );
private:
const PROJECT& m_project;
std::map<wxString, std::unique_ptr<SIM_LIBRARY>> m_libraries;

View File

@ -28,6 +28,7 @@
#include <fmt/core.h>
#include <wx/filename.h>
#include <kiway.h>
#include "sim_lib_mgr.h"
std::string SPICE_GENERATOR_KIBIS::ModelName( const SPICE_ITEM& aItem ) const
{
@ -67,16 +68,13 @@ std::string SPICE_GENERATOR_KIBIS::IbisDevice( const SPICE_ITEM& aItem, const PR
std::string ibisModelName = SIM_MODEL::GetFieldValue( &aItem.fields, SIM_LIBRARY_KIBIS::MODEL_FIELD );
bool diffMode = SIM_MODEL::GetFieldValue( &aItem.fields, SIM_LIBRARY_KIBIS::DIFF_FIELD ) == "1";
wxString path = ExpandEnvVarSubstitutions( ibisLibFilename, &aProject );
wxString absolutePath = aProject.AbsolutePath( path );
wxString path = SIM_LIB_MGR::ResolveLibraryPath( ibisLibFilename, aProject );
KIBIS kibis( std::string( absolutePath.c_str() ) );
KIBIS kibis( std::string( path.c_str() ) );
kibis.m_cacheDir = std::string( aCacheDir.c_str() );
if( !kibis.m_valid )
{
THROW_IO_ERROR( wxString::Format( _( "Invalid IBIS file '%s'" ), ibisLibFilename ) );
}
KIBIS_COMPONENT* kcomp = kibis.GetComponent( std::string( ibisCompName ) );
@ -87,10 +85,7 @@ std::string SPICE_GENERATOR_KIBIS::IbisDevice( const SPICE_ITEM& aItem, const PR
if( !kcomp->m_valid )
{
THROW_IO_ERROR( wxString::Format( _( "Invalid IBIS component '%s'" ),
ibisCompName ) );
}
THROW_IO_ERROR( wxString::Format( _( "Invalid IBIS component '%s'" ), ibisCompName ) );
if( !kpin )
{
@ -139,18 +134,15 @@ std::string SPICE_GENERATOR_KIBIS::IbisDevice( const SPICE_ITEM& aItem, const PR
if( paramValue == "hi-Z" )
{
kparams.m_waveform =
static_cast<KIBIS_WAVEFORM*>( new KIBIS_WAVEFORM_HIGH_Z( &kibis ) );
kparams.m_waveform = static_cast<KIBIS_WAVEFORM*>( new KIBIS_WAVEFORM_HIGH_Z( &kibis ) );
}
else if( paramValue == "low" )
{
kparams.m_waveform =
static_cast<KIBIS_WAVEFORM*>( new KIBIS_WAVEFORM_STUCK_LOW( &kibis ) );
kparams.m_waveform = static_cast<KIBIS_WAVEFORM*>( new KIBIS_WAVEFORM_STUCK_LOW( &kibis ) );
}
else if( paramValue == "high" )
{
kparams.m_waveform =
static_cast<KIBIS_WAVEFORM*>( new KIBIS_WAVEFORM_STUCK_HIGH( &kibis ) );
kparams.m_waveform = static_cast<KIBIS_WAVEFORM*>( new KIBIS_WAVEFORM_STUCK_HIGH( &kibis ) );
}
if( diffMode )

View File

@ -35,6 +35,16 @@ SIM_PLOT_FRAME_BASE::SIM_PLOT_FRAME_BASE( wxWindow* parent, wxWindowID id, const
m_fileMenu->AppendSeparator();
wxMenuItem* m_saveImage;
m_saveImage = new wxMenuItem( m_fileMenu, ID_SAVE_AS_IMAGE, wxString( _("Export Current Plot as PNG...") ) , wxEmptyString, wxITEM_NORMAL );
m_fileMenu->Append( m_saveImage );
wxMenuItem* m_saveCsv;
m_saveCsv = new wxMenuItem( m_fileMenu, ID_SAVE_AS_CSV, wxString( _("Export Current Plot as CSV...") ) , wxEmptyString, wxITEM_NORMAL );
m_fileMenu->Append( m_saveCsv );
m_fileMenu->AppendSeparator();
wxMenuItem* m_exitSim;
m_exitSim = new wxMenuItem( m_fileMenu, wxID_CLOSE, wxString( _("Close") ) + wxT('\t') + wxT("CTRL+W"), wxEmptyString, wxITEM_NORMAL );
m_fileMenu->Append( m_exitSim );
@ -270,6 +280,8 @@ SIM_PLOT_FRAME_BASE::SIM_PLOT_FRAME_BASE( wxWindow* parent, wxWindowID id, const
m_fileMenu->Bind(wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler( SIM_PLOT_FRAME_BASE::menuOpenWorkbook ), this, m_openWorkbook->GetId());
m_fileMenu->Bind(wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler( SIM_PLOT_FRAME_BASE::menuSaveWorkbook ), this, m_saveWorkbook->GetId());
m_fileMenu->Bind(wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler( SIM_PLOT_FRAME_BASE::menuSaveWorkbookAs ), this, m_saveWorkbookAs->GetId());
m_fileMenu->Bind(wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler( SIM_PLOT_FRAME_BASE::menuSaveImage ), this, m_saveImage->GetId());
m_fileMenu->Bind(wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler( SIM_PLOT_FRAME_BASE::menuSaveCsv ), this, m_saveCsv->GetId());
m_fileMenu->Bind(wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler( SIM_PLOT_FRAME_BASE::menuExit ), this, m_exitSim->GetId());
this->Connect( m_runSimulation->GetId(), wxEVT_UPDATE_UI, wxUpdateUIEventHandler( SIM_PLOT_FRAME_BASE::menuSimulateUpdate ) );
this->Connect( m_addSignals->GetId(), wxEVT_UPDATE_UI, wxUpdateUIEventHandler( SIM_PLOT_FRAME_BASE::menuAddSignalsUpdate ) );

View File

@ -107,7 +107,7 @@
<property name="help"></property>
<property name="id">wxID_OPEN</property>
<property name="kind">wxITEM_NORMAL</property>
<property name="label">Open...</property>
<property name="label">Open Workbook...</property>
<property name="name">m_openWorkbook</property>
<property name="permission">none</property>
<property name="shortcut"></property>
@ -121,7 +121,7 @@
<property name="help"></property>
<property name="id">wxID_SAVE</property>
<property name="kind">wxITEM_NORMAL</property>
<property name="label">Save</property>
<property name="label">Save Workbook</property>
<property name="name">m_saveWorkbook</property>
<property name="permission">none</property>
<property name="shortcut"></property>
@ -135,7 +135,7 @@
<property name="help"></property>
<property name="id">wxID_SAVEAS</property>
<property name="kind">wxITEM_NORMAL</property>
<property name="label">Save As...</property>
<property name="label">Save Workbook As...</property>
<property name="name">m_saveWorkbookAs</property>
<property name="permission">none</property>
<property name="shortcut">SHIFT+CTRL+S</property>
@ -153,7 +153,7 @@
<property name="help"></property>
<property name="id">ID_SAVE_AS_IMAGE</property>
<property name="kind">wxITEM_NORMAL</property>
<property name="label">Save as Image</property>
<property name="label">Export Current Plot as PNG...</property>
<property name="name">m_saveImage</property>
<property name="permission">none</property>
<property name="shortcut"></property>
@ -167,7 +167,7 @@
<property name="help"></property>
<property name="id">ID_SAVE_AS_CSV</property>
<property name="kind">wxITEM_NORMAL</property>
<property name="label">Save as .csv File</property>
<property name="label">Export Current Plot as CSV...</property>
<property name="name">m_saveCsv</property>
<property name="permission">none</property>
<property name="shortcut"></property>

View File

@ -35,16 +35,18 @@ class wxListView;
///////////////////////////////////////////////////////////////////////////
#define ID_MENU_RUN_SIM 1000
#define ID_MENU_ADD_SIGNAL 1001
#define ID_MENU_PROBE_SIGNALS 1002
#define ID_MENU_TUNE_SIGNALS 1003
#define ID_MENU_SHOW_NETLIST 1004
#define ID_MENU_SET_SIMUL 1005
#define ID_MENU_SHOW_GRID 1006
#define ID_MENU_SHOW_LEGEND 1007
#define ID_MENU_DOTTED 1008
#define ID_MENU_WHITE_BG 1009
#define ID_SAVE_AS_IMAGE 1000
#define ID_SAVE_AS_CSV 1001
#define ID_MENU_RUN_SIM 1002
#define ID_MENU_ADD_SIGNAL 1003
#define ID_MENU_PROBE_SIGNALS 1004
#define ID_MENU_TUNE_SIGNALS 1005
#define ID_MENU_SHOW_NETLIST 1006
#define ID_MENU_SET_SIMUL 1007
#define ID_MENU_SHOW_GRID 1008
#define ID_MENU_SHOW_LEGEND 1009
#define ID_MENU_DOTTED 1010
#define ID_MENU_WHITE_BG 1011
///////////////////////////////////////////////////////////////////////////////
/// Class SIM_PLOT_FRAME_BASE
@ -96,6 +98,8 @@ class SIM_PLOT_FRAME_BASE : public KIWAY_PLAYER
virtual void menuOpenWorkbook( wxCommandEvent& event ) { event.Skip(); }
virtual void menuSaveWorkbook( wxCommandEvent& event ) { event.Skip(); }
virtual void menuSaveWorkbookAs( wxCommandEvent& event ) { event.Skip(); }
virtual void menuSaveImage( wxCommandEvent& event ) { event.Skip(); }
virtual void menuSaveCsv( wxCommandEvent& event ) { event.Skip(); }
virtual void menuExit( wxCommandEvent& event ) { event.Skip(); }
virtual void menuSimulateUpdate( wxUpdateUIEvent& event ) { event.Skip(); }
virtual void menuAddSignalsUpdate( wxUpdateUIEvent& event ) { event.Skip(); }