From b95f4ec6bb4017dab9d62be295c8a088918f1b21 Mon Sep 17 00:00:00 2001 From: Mikolaj Wielgus Date: Thu, 6 Oct 2022 09:47:03 +0200 Subject: [PATCH] Sim: Use the new library manager class in Spice netlist exporter Temporarily comment out IBIS processing. --- .../netlist_exporter_spice.cpp | 143 +++++------------- .../netlist_exporter_spice.h | 17 +-- eeschema/sim/sim_lib_mgr.cpp | 28 +++- eeschema/sim/sim_lib_mgr.h | 6 +- eeschema/tools/sch_editor_control.cpp | 53 ++++--- 5 files changed, 103 insertions(+), 144 deletions(-) diff --git a/eeschema/netlist_exporters/netlist_exporter_spice.cpp b/eeschema/netlist_exporters/netlist_exporter_spice.cpp index c3ff9fe655..b900977bd6 100644 --- a/eeschema/netlist_exporters/netlist_exporter_spice.cpp +++ b/eeschema/netlist_exporters/netlist_exporter_spice.cpp @@ -74,6 +74,13 @@ namespace NETLIST_EXPORTER_SPICE_PARSER } +NETLIST_EXPORTER_SPICE::NETLIST_EXPORTER_SPICE( SCHEMATIC_IFACE* aSchematic ) : + NETLIST_EXPORTER_BASE( aSchematic ), + m_libMgr( aSchematic->Prj() ) +{ +} + + bool NETLIST_EXPORTER_SPICE::WriteNetlist( const wxString& aOutFileName, unsigned aNetlistOptions ) { FILE_OUTPUTFORMATTER formatter( aOutFileName, wxT( "wt" ), '\'' ); @@ -181,7 +188,7 @@ bool NETLIST_EXPORTER_SPICE::ReadSchematicAndLibraries( unsigned aNetlistOptions ITEM spiceItem; // @TODO This is to be removed once ngspice gets ibis support - if( SIM_MODEL::GetFieldValue( &( symbol->GetFields() ), SIM_MODEL::DEVICE_TYPE_FIELD ) + /*if( SIM_MODEL::GetFieldValue( &( symbol->GetFields() ), SIM_MODEL::DEVICE_TYPE_FIELD ) == "IBIS" ) { if( !readRefName( sheet, *symbol, spiceItem, refNames ) ) @@ -433,23 +440,26 @@ bool NETLIST_EXPORTER_SPICE::ReadSchematicAndLibraries( unsigned aNetlistOptions m_items.push_back( std::move( spiceItem ) ); continue; + }*/ + + try + { + if( !readRefName( sheet, *symbol, spiceItem, refNames ) ) + return false; + + readModel( *symbol, spiceItem ); + + readPinNumbers( *symbol, spiceItem ); + readPinNetNames( *symbol, spiceItem, ncCounter ); + + // TODO: transmission line handling? + + m_items.push_back( std::move( spiceItem ) ); + } + catch( const IO_ERROR& e ) + { + DisplayErrorMessage( nullptr, e.What() ); } - - if( !readRefName( sheet, *symbol, spiceItem, refNames ) ) - return false; - - readLibraryField( *symbol, spiceItem ); - readNameField( *symbol, spiceItem ); - - if( !readModel( *symbol, spiceItem ) ) - continue; - - readPinNumbers( *symbol, spiceItem ); - readPinNetNames( *symbol, spiceItem, ncCounter ); - - // TODO: transmission line handling? - - m_items.push_back( std::move( spiceItem ) ); } } @@ -528,7 +538,7 @@ void NETLIST_EXPORTER_SPICE::ReadDirectives( unsigned aNetlistOptions ) try { - m_libraries.try_emplace( path, SIM_LIBRARY::Create( path ) ); + m_libMgr.CreateLibrary( path ); } catch( const IO_ERROR& e ) { @@ -545,72 +555,6 @@ void NETLIST_EXPORTER_SPICE::ReadDirectives( unsigned aNetlistOptions ) } -void NETLIST_EXPORTER_SPICE::readLibraryField( SCH_SYMBOL& aSymbol, ITEM& aItem ) -{ - SCH_FIELD* field = aSymbol.FindField( SIM_LIBRARY::LIBRARY_FIELD ); - std::string path; - - if( field ) - path = std::string( field->GetShownText().ToUTF8() ); - - if( path == "" ) - return; - - wxString absolutePath = m_schematic->Prj().AbsolutePath( path ); - - try - { - m_libraries.try_emplace( path, SIM_LIBRARY::Create( std::string( absolutePath.ToUTF8() ) ) ); - } - catch( const IO_ERROR& e ) - { - DisplayErrorMessage( nullptr, wxString::Format( "Failed reading model library '%s'.", - absolutePath ), - e.What() ); - } - - aItem.libraryPath = path; -} - - -void NETLIST_EXPORTER_SPICE::readNameField( SCH_SYMBOL& aSymbol, ITEM& aItem ) -{ - if( m_libraries.count( aItem.libraryPath ) ) - { - SCH_FIELD* field = aSymbol.FindField( SIM_LIBRARY::NAME_FIELD ); - - if( !field ) - return; - - std::string modelName = std::string( field->GetShownText().ToUTF8() ); - const SIM_LIBRARY& library = *m_libraries.at( aItem.libraryPath ); - const SIM_MODEL* baseModel = library.FindModel( modelName ); - - if( baseModel ) - { - try - { - aItem.model = SIM_MODEL::Create( *baseModel, - m_sortedSymbolPinList.size(), - aSymbol.GetFields() ); - } - catch( const IO_ERROR& e ) - { - DisplayErrorMessage( nullptr, - wxString::Format( "Failed reading %s simulation model.", aItem.refName ), - e.What() ); - return; - } - - aItem.modelName = modelName; - return; - } - } - else - aItem.modelName = "__" + aItem.refName; -} - - bool NETLIST_EXPORTER_SPICE::readRefName( SCH_SHEET_PATH& aSheet, SCH_SYMBOL& aSymbol, ITEM& aItem, std::set& aRefNames ) @@ -630,35 +574,20 @@ bool NETLIST_EXPORTER_SPICE::readRefName( SCH_SHEET_PATH& aSheet, SCH_SYMBOL& aS } -bool NETLIST_EXPORTER_SPICE::readModel( SCH_SYMBOL& aSymbol, ITEM& aItem ) +void NETLIST_EXPORTER_SPICE::readModel( SCH_SYMBOL& aSymbol, ITEM& aItem ) { - if( !aItem.model.get() ) - { - try - { - aItem.model = SIM_MODEL::Create( - static_cast( m_sortedSymbolPinList.size() ), aSymbol.GetFields() ); - } - catch( const IO_ERROR& e ) - { - DisplayErrorMessage( nullptr, - wxString::Format( _( "Failed reading %s simulation model." ), aItem.refName ), - e.What() ); - return false; - } - } + auto [modelName, model] = m_libMgr.CreateModel( aSymbol ); + aItem.modelName = ( modelName != "" ) ? modelName : ( "__" + aItem.refName ); + aItem.model = &model; - // Special case for legacy models. - if( auto model = dynamic_cast( aItem.model.get() ) ) + if( auto rawSpiceModel = dynamic_cast( aItem.model ) ) { - unsigned libParamIndex = static_cast( SIM_MODEL_RAW_SPICE::SPICE_PARAM::LIB ); - std::string path = model->GetParam( libParamIndex ).value->ToString(); + int libParamIndex = static_cast( SIM_MODEL_RAW_SPICE::SPICE_PARAM::LIB ); + std::string path = rawSpiceModel->GetParam( libParamIndex ).value->ToString(); if( path != "" ) m_rawIncludes.insert( path ); } - - return true; } @@ -713,7 +642,7 @@ void NETLIST_EXPORTER_SPICE::writeInclude( OUTPUTFORMATTER& aFormatter, unsigned void NETLIST_EXPORTER_SPICE::writeIncludes( OUTPUTFORMATTER& aFormatter, unsigned aNetlistOptions ) { - for( auto&& [path, library] : m_libraries ) + for( auto&& [path, library] : m_libMgr.GetLibraries() ) writeInclude( aFormatter, aNetlistOptions, path ); for( const std::string& path : m_rawIncludes ) diff --git a/eeschema/netlist_exporters/netlist_exporter_spice.h b/eeschema/netlist_exporters/netlist_exporter_spice.h index d737e7efc8..b13136faca 100644 --- a/eeschema/netlist_exporters/netlist_exporter_spice.h +++ b/eeschema/netlist_exporters/netlist_exporter_spice.h @@ -27,8 +27,9 @@ #define NETLIST_EXPORTER_SPICE_H #include "netlist_exporter_base.h" -#include +#include #include +#include class NETLIST_EXPORTER_SPICE : public NETLIST_EXPORTER_BASE @@ -53,11 +54,11 @@ public: std::string libraryPath; std::vector pinNumbers; std::vector pinNetNames; - std::unique_ptr model; + const SIM_MODEL* model; std::string modelName; }; - NETLIST_EXPORTER_SPICE( SCHEMATIC_IFACE* aSchematic ) : NETLIST_EXPORTER_BASE( aSchematic ) {} + NETLIST_EXPORTER_SPICE( SCHEMATIC_IFACE* aSchematic ); /** * Write to specified output file. @@ -128,12 +129,9 @@ protected: SCH_SHEET_LIST GetSheets( unsigned aNetlistOptions = 0 ) const; private: - void readLibraryField( SCH_SYMBOL& aSymbol, ITEM& aItem ); - void readNameField( SCH_SYMBOL& aSymbol, ITEM& aItem ); - void readEnabledField( SCH_SYMBOL& aSymbol, ITEM& aItem ); bool readRefName( SCH_SHEET_PATH& aSheet, SCH_SYMBOL& aSymbol, ITEM& aItem, std::set& aRefNames ); - bool readModel( SCH_SYMBOL& aSymbol, ITEM& aItem ); + void readModel( SCH_SYMBOL& aSymbol, ITEM& aItem ); void readPinNumbers( SCH_SYMBOL& aSymbol, ITEM& aItem ); void readPinNetNames( SCH_SYMBOL& aSymbol, ITEM& aItem, int& aNcCounter ); @@ -144,12 +142,13 @@ private: void writeModels( OUTPUTFORMATTER& aFormatter ); void writeItems( OUTPUTFORMATTER& aFormatter ); + SIM_LIB_MGR m_libMgr; ///< Holds libraries and models std::string m_title; ///< Spice simulation title found in the schematic sheet std::vector m_directives; ///< Spice directives found in the schematic sheet - std::map> m_libraries; ///< Spice libraries + //std::map> m_libraries; ///< Spice libraries std::set m_rawIncludes; ///< include directives found in symbols std::set m_nets; - std::list m_items; ///< Items representing schematic symbols in Spice world + std::list m_items; ///< Items representing schematic symbols in Spice world }; diff --git a/eeschema/sim/sim_lib_mgr.cpp b/eeschema/sim/sim_lib_mgr.cpp index 0a5cfc8c8e..197b793018 100644 --- a/eeschema/sim/sim_lib_mgr.cpp +++ b/eeschema/sim/sim_lib_mgr.cpp @@ -27,6 +27,7 @@ #include #include #include +#include SIM_LIB_MGR::SIM_LIB_MGR( const PROJECT& aPrj ) : m_project( aPrj ) @@ -34,10 +35,11 @@ SIM_LIB_MGR::SIM_LIB_MGR( const PROJECT& aPrj ) : m_project( aPrj ) } -SIM_MODEL& SIM_LIB_MGR::CreateModel( SCH_SYMBOL& aSymbol ) +std::pair SIM_LIB_MGR::CreateModel( SCH_SYMBOL& aSymbol ) { std::vector pins = aSymbol.GetLibPins(); SCH_FIELD* libraryField = aSymbol.FindField( SIM_LIBRARY::LIBRARY_FIELD ); + std::string baseModelName; if( libraryField ) { @@ -54,7 +56,7 @@ SIM_MODEL& SIM_LIB_MGR::CreateModel( SCH_SYMBOL& aSymbol ) catch( const IO_ERROR& e ) { THROW_IO_ERROR( - wxString::Format( _( "Error loading simulation model library '%s'.\n%s" ), + wxString::Format( _( "Error loading simulation model library '%s': %s" ), absolutePath, e.What() ) ); } @@ -67,7 +69,7 @@ SIM_MODEL& SIM_LIB_MGR::CreateModel( SCH_SYMBOL& aSymbol ) SIM_LIBRARY::NAME_FIELD ) ); } - std::string baseModelName = std::string( nameField->GetShownText().ToUTF8() ); + baseModelName = std::string( nameField->GetShownText().ToUTF8() ); SIM_MODEL* baseModel = library->FindModel( baseModelName ); if( !baseModel ) @@ -88,5 +90,23 @@ SIM_MODEL& SIM_LIB_MGR::CreateModel( SCH_SYMBOL& aSymbol ) aSymbol.GetFields() ) ); } - return *m_models.back(); + return std::pair( baseModelName, *m_models.back() ); +} + + +SIM_LIBRARY& SIM_LIB_MGR::CreateLibrary( const std::string& aLibraryPath ) +{ + auto it = m_libraries.try_emplace( aLibraryPath, SIM_LIBRARY::Create( aLibraryPath ) ).first; + return *it->second; +} + + +std::map> SIM_LIB_MGR::GetLibraries() const +{ + std::map> result; + + for( auto&& [path, library] : m_libraries ) + result.try_emplace( path, *library ); + + return result; } diff --git a/eeschema/sim/sim_lib_mgr.h b/eeschema/sim/sim_lib_mgr.h index 648b115586..6e071069a1 100644 --- a/eeschema/sim/sim_lib_mgr.h +++ b/eeschema/sim/sim_lib_mgr.h @@ -40,10 +40,14 @@ class SIM_LIB_MGR { public: SIM_LIB_MGR( const PROJECT& aPrj ); + virtual ~SIM_LIB_MGR() = default; // TODO: The argument can be made const. - SIM_MODEL& CreateModel( SCH_SYMBOL& aSymbol ); + std::pair CreateModel( SCH_SYMBOL& aSymbol ); + SIM_LIBRARY& CreateLibrary( const std::string& aLibraryPath ); + + std::map> GetLibraries() const; private: const PROJECT& m_project; diff --git a/eeschema/tools/sch_editor_control.cpp b/eeschema/tools/sch_editor_control.cpp index eba280aaea..776930f485 100644 --- a/eeschema/tools/sch_editor_control.cpp +++ b/eeschema/tools/sch_editor_control.cpp @@ -880,32 +880,39 @@ int SCH_EDITOR_CONTROL::SimProbe( const TOOL_EVENT& aEvent ) if( item->Type() == SCH_PIN_T ) { - LIB_PIN* pin = static_cast( item )->GetLibPin(); - SCH_SYMBOL* symbol = static_cast( item->GetParent() ); - std::vector pins = symbol->GetLibPins(); - - SIM_LIB_MGR mgr( m_frame->Prj() ); - SIM_MODEL& model = mgr.CreateModel( *symbol ); - - auto ref = std::string( symbol->GetRef( &m_frame->GetCurrentSheet() ).ToUTF8() ); - std::vector currentNames = - model.SpiceGenerator().CurrentNames( ref ); - - if( currentNames.size() == 0 ) - return true; - else if( currentNames.size() == 1 ) + try { - simFrame->AddCurrentPlot( currentNames.at( 0 ) ); - return true; + LIB_PIN* pin = static_cast( item )->GetLibPin(); + SCH_SYMBOL* symbol = static_cast( item->GetParent() ); + std::vector pins = symbol->GetLibPins(); + + SIM_LIB_MGR mgr( m_frame->Prj() ); + SIM_MODEL& model = mgr.CreateModel( *symbol ).second; + + auto ref = std::string( symbol->GetRef( &m_frame->GetCurrentSheet() ).ToUTF8() ); + std::vector currentNames = + model.SpiceGenerator().CurrentNames( ref ); + + if( currentNames.size() == 0 ) + return true; + else if( currentNames.size() == 1 ) + { + simFrame->AddCurrentPlot( currentNames.at( 0 ) ); + return true; + } + + int modelPinIndex = + model.FindModelPinIndex( std::string( pin->GetNumber().ToUTF8() ) ); + + if( modelPinIndex != SIM_MODEL::PIN::NOT_CONNECTED ) + { + wxString name = currentNames.at( modelPinIndex ); + simFrame->AddCurrentPlot( name ); + } } - - int modelPinIndex = - model.FindModelPinIndex( std::string( pin->GetNumber().ToUTF8() ) ); - - if( modelPinIndex != SIM_MODEL::PIN::NOT_CONNECTED ) + catch( const IO_ERROR& e ) { - wxString name = currentNames.at( modelPinIndex ); - simFrame->AddCurrentPlot( name ); + DisplayErrorMessage( m_frame, e.What() ); } } else if( item->IsType( { SCH_ITEM_LOCATE_WIRE_T } ) )