diff --git a/eeschema/dialogs/dialog_signal_list.cpp b/eeschema/dialogs/dialog_signal_list.cpp index 335d87209b..31abb52b36 100644 --- a/eeschema/dialogs/dialog_signal_list.cpp +++ b/eeschema/dialogs/dialog_signal_list.cpp @@ -75,7 +75,7 @@ bool DIALOG_SIGNAL_LIST::TransferDataToWindow() for( const auto& item : m_circuitModel->GetItems() ) { // Add all possible currents for the primitive. - for( const auto& currentName : item.model->GenerateSpiceCurrentNames( item.refName ) ) + for( const auto& currentName : item.model->SpiceGenerator().CurrentNames( item.refName ) ) m_signals->Append( currentName ); } } diff --git a/eeschema/dialogs/dialog_sim_model.cpp b/eeschema/dialogs/dialog_sim_model.cpp index 305ee53e7e..94ecbc6207 100644 --- a/eeschema/dialogs/dialog_sim_model.cpp +++ b/eeschema/dialogs/dialog_sim_model.cpp @@ -338,7 +338,7 @@ void DIALOG_SIM_MODEL::updateModelCodeTab() wxTextFile file; wxString text; - text << curModel().GenerateSpicePreview( modelName ); + text << curModel().SpiceGenerator().Preview( modelName ); text << "\n"; text << "--- FILE SOURCE (" << path << ") ---\n"; text << "\n"; @@ -356,7 +356,7 @@ void DIALOG_SIM_MODEL::updateModelCodeTab() } } else - m_codePreview->SetText( curModel().GenerateSpicePreview( modelName ) ); + m_codePreview->SetText( curModel().SpiceGenerator().Preview( modelName ) ); m_codePreview->SetEditable( false ); // ??? m_wasCodePreviewUpdated = true; diff --git a/eeschema/netlist_exporters/netlist_exporter_spice.cpp b/eeschema/netlist_exporters/netlist_exporter_spice.cpp index c170d76790..607e637875 100644 --- a/eeschema/netlist_exporters/netlist_exporter_spice.cpp +++ b/eeschema/netlist_exporters/netlist_exporter_spice.cpp @@ -177,7 +177,7 @@ wxString NETLIST_EXPORTER_SPICE::GetItemName( const wxString& aRefName ) const if( it == spiceItems.end() ) return ""; - return it->model->GenerateSpiceItemName( aRefName ); + return it->model->SpiceGenerator().ItemName( aRefName ); } @@ -425,7 +425,7 @@ void NETLIST_EXPORTER_SPICE::writeModels( OUTPUTFORMATTER& aFormatter ) if( !item.model->IsEnabled() ) continue; - aFormatter.Print( 0, "%s", TO_UTF8( item.model->GenerateSpiceModelLine( item.modelName ) ) ); + aFormatter.Print( 0, "%s", TO_UTF8( item.model->SpiceGenerator().ModelLine( item.modelName ) ) ); } } @@ -438,10 +438,10 @@ void NETLIST_EXPORTER_SPICE::writeItems( OUTPUTFORMATTER& aFormatter ) continue; aFormatter.Print( 0, "%s", - TO_UTF8( item.model->GenerateSpiceItemLine( item.refName, - item.modelName, - item.pinNumbers, - item.pinNetNames ) ) ); + TO_UTF8( item.model->SpiceGenerator().ItemLine( item.refName, + item.modelName, + item.pinNumbers, + item.pinNetNames ) ) ); } } diff --git a/eeschema/sim/sim_model.cpp b/eeschema/sim/sim_model.cpp index 018ad6610e..cd32b01a85 100644 --- a/eeschema/sim/sim_model.cpp +++ b/eeschema/sim/sim_model.cpp @@ -42,6 +42,7 @@ #include +using SPICE_GENERATOR = SIM_MODEL::SPICE_GENERATOR; using DEVICE_TYPE = SIM_MODEL::DEVICE_TYPE_; using TYPE = SIM_MODEL::TYPE; @@ -83,36 +84,220 @@ namespace SIM_MODEL_SPICE_PARSER } +wxString SPICE_GENERATOR::ModelLine( const wxString& aModelName ) const +{ + LOCALE_IO toggle; + + if( !m_model.HasSpiceNonInstanceOverrides() && !m_model.requiresSpiceModelLine() ) + return ""; + + wxString result = ""; + + result << wxString::Format( ".model %s ", aModelName ); + size_t indentLength = result.Length(); + + result << wxString::Format( "%s \n", m_model.GetSpiceInfo().modelType ); + + for( const PARAM& param : m_model.GetParams() ) + { + if( param.info.isSpiceInstanceParam ) + continue; + + wxString name = ( param.info.spiceModelName == "" ) ? + param.info.name : param.info.spiceModelName; + wxString value = param.value->ToSpiceString(); + + if( value == "" ) + continue; + + result << wxString::Format( "+%s%s=%s\n", wxString( ' ', indentLength - 1 ), name, value ); + } + + return result; +} + + +wxString SPICE_GENERATOR::ItemLine( const wxString& aRefName, + const wxString& aModelName ) const +{ + // Use linear symbol pin numbers enumeration. Used in model preview. + + std::vector pinNumbers; + + for( int i = 0; i < m_model.GetPinCount(); ++i ) + pinNumbers.push_back( wxString::FromCDouble( i + 1 ) ); + + return ItemLine( aRefName, aModelName, pinNumbers ); +} + + +wxString SPICE_GENERATOR::ItemLine( const wxString& aRefName, + const wxString& aModelName, + const std::vector& aSymbolPinNumbers ) const +{ + std::vector pinNetNames; + + for( const PIN& pin : GetPins() ) + pinNetNames.push_back( pin.name ); + + return ItemLine( aRefName, aModelName, aSymbolPinNumbers, pinNetNames ); +} + + +wxString SPICE_GENERATOR::ItemLine( const wxString& aRefName, + const wxString& aModelName, + const std::vector& aSymbolPinNumbers, + const std::vector& aPinNetNames ) const +{ + wxString result; + result << ItemName( aRefName ); + result << ItemPins( aRefName, aModelName, aSymbolPinNumbers, aPinNetNames ); + result << ItemModelName( aModelName ); + result << ItemParams(); + result << "\n"; + return result; +} + + +wxString SPICE_GENERATOR::ItemName( const wxString& aRefName ) const +{ + if( aRefName != "" && aRefName.StartsWith( m_model.GetSpiceInfo().itemType ) ) + return aRefName; + else + return m_model.GetSpiceInfo().itemType + aRefName; +} + + +wxString SPICE_GENERATOR::ItemPins( const wxString& aRefName, + const wxString& aModelName, + const std::vector& aSymbolPinNumbers, + const std::vector& aPinNetNames ) const +{ + wxString result; + int ncCounter = 0; + + for( const PIN& pin : GetPins() ) + { + auto it = std::find( aSymbolPinNumbers.begin(), aSymbolPinNumbers.end(), + pin.symbolPinNumber ); + + if( it == aSymbolPinNumbers.end() ) + { + LOCALE_IO toggle; + result << wxString::Format( " NC-%s-%u", aRefName, ncCounter++ ); + } + else + { + long symbolPinIndex = std::distance( aSymbolPinNumbers.begin(), it ); + result << " " << aPinNetNames.at( symbolPinIndex ); + } + } + + return result; +} + + +wxString SPICE_GENERATOR::ItemModelName( const wxString& aModelName ) const +{ + return " " + aModelName; +} + + +wxString SPICE_GENERATOR::ItemParams() const +{ + wxString result; + + for( const PARAM& param : GetInstanceParams() ) + { + wxString name = ( param.info.spiceInstanceName == "" ) ? + param.info.name : param.info.spiceInstanceName; + wxString value = param.value->ToSpiceString(); + + if( value != "" ) + result << " " << name << "=" << value; + } + + return result; +} + + +wxString SPICE_GENERATOR::TuningLine( const wxString& aSymbol ) const +{ + // TODO. + return ""; +} + + +std::vector SPICE_GENERATOR::CurrentNames( const wxString& aRefName ) const +{ + LOCALE_IO toggle; + return { wxString::Format( "I(%s)", ItemName( aRefName ) ) }; +} + + +wxString SPICE_GENERATOR::Preview( const wxString& aModelName ) const +{ + wxString spiceCode = ModelLine( aModelName ); + + if( spiceCode == "" ) + spiceCode = m_model.m_spiceCode; + + if( spiceCode == "" && m_model.GetBaseModel() ) + spiceCode = m_model.GetBaseModel()->m_spiceCode; + + wxString itemLine = ItemLine( "", aModelName ); + if( spiceCode != "" ) + spiceCode << "\n"; + + spiceCode << itemLine; + return spiceCode.Trim(); +} + + +std::vector> SPICE_GENERATOR::GetInstanceParams() const +{ + std::vector> instanceParams; + + for( const PARAM& param : m_model.GetParams() ) + { + if( param.info.isSpiceInstanceParam ) + instanceParams.emplace_back( param ); + } + + return instanceParams; +} + + SIM_MODEL::DEVICE_INFO SIM_MODEL::DeviceTypeInfo( DEVICE_TYPE_ aDeviceType ) { switch( aDeviceType ) { - case DEVICE_TYPE_::NONE: return { "", "" }; - case DEVICE_TYPE_::R: return { "R", "Resistor" }; - case DEVICE_TYPE_::C: return { "C", "Capacitor" }; - case DEVICE_TYPE_::L: return { "L", "Inductor" }; - case DEVICE_TYPE_::TLINE: return { "TLINE", "Transmission Line" }; - case DEVICE_TYPE_::SW: return { "SW", "Switch" }; + case DEVICE_TYPE_::NONE: return { "", "" }; + case DEVICE_TYPE_::R: return { "R", "Resistor" }; + case DEVICE_TYPE_::C: return { "C", "Capacitor" }; + case DEVICE_TYPE_::L: return { "L", "Inductor" }; + case DEVICE_TYPE_::TLINE: return { "TLINE", "Transmission Line" }; + case DEVICE_TYPE_::SW: return { "SW", "Switch" }; - case DEVICE_TYPE_::D: return { "D", "Diode" }; - case DEVICE_TYPE_::NPN: return { "NPN", "NPN BJT" }; - case DEVICE_TYPE_::PNP: return { "PNP", "PNP BJT" }; + case DEVICE_TYPE_::D: return { "D", "Diode" }; + case DEVICE_TYPE_::NPN: return { "NPN", "NPN BJT" }; + case DEVICE_TYPE_::PNP: return { "PNP", "PNP BJT" }; - case DEVICE_TYPE_::NJFET: return { "NJFET", "N-channel JFET" }; - case DEVICE_TYPE_::PJFET: return { "PJFET", "P-channel JFET" }; + case DEVICE_TYPE_::NJFET: return { "NJFET", "N-channel JFET" }; + case DEVICE_TYPE_::PJFET: return { "PJFET", "P-channel JFET" }; - case DEVICE_TYPE_::NMOS: return { "NMOS", "N-channel MOSFET" }; - case DEVICE_TYPE_::PMOS: return { "PMOS", "P-channel MOSFET" }; - case DEVICE_TYPE_::NMES: return { "NMES", "N-channel MESFET" }; - case DEVICE_TYPE_::PMES: return { "PMES", "P-channel MESFET" }; + case DEVICE_TYPE_::NMOS: return { "NMOS", "N-channel MOSFET" }; + case DEVICE_TYPE_::PMOS: return { "PMOS", "P-channel MOSFET" }; + case DEVICE_TYPE_::NMES: return { "NMES", "N-channel MESFET" }; + case DEVICE_TYPE_::PMES: return { "PMES", "P-channel MESFET" }; - case DEVICE_TYPE_::V: return { "V", "Voltage Source" }; - case DEVICE_TYPE_::I: return { "I", "Current Source" }; + case DEVICE_TYPE_::V: return { "V", "Voltage Source" }; + case DEVICE_TYPE_::I: return { "I", "Current Source" }; - case DEVICE_TYPE_::SUBCKT: return { "SUBCKT", "Subcircuit" }; - case DEVICE_TYPE_::XSPICE: return { "XSPICE", "XSPICE Code Model" }; - case DEVICE_TYPE_::SPICE: return { "SPICE", "Raw Spice Element" }; - case DEVICE_TYPE_::_ENUM_END: break; + case DEVICE_TYPE_::SUBCKT: return { "SUBCKT", "Subcircuit" }; + case DEVICE_TYPE_::XSPICE: return { "XSPICE", "XSPICE Code Model" }; + case DEVICE_TYPE_::SPICE: return { "SPICE", "Raw Spice Element" }; + case DEVICE_TYPE_::_ENUM_END: break; } wxFAIL; @@ -907,123 +1092,6 @@ void SIM_MODEL::ReadSpiceCode( const wxString& aSpiceCode ) } -wxString SIM_MODEL::GenerateSpiceModelLine( const wxString& aModelName ) const -{ - LOCALE_IO toggle; - - if( !HasSpiceNonInstanceOverrides() && !requiresSpiceModelLine() ) - return ""; - - wxString result = ""; - - result << wxString::Format( ".model %s ", aModelName ); - size_t indentLength = result.Length(); - - result << wxString::Format( "%s \n", GetSpiceInfo().modelType ); - - for( const PARAM& param : GetParams() ) - { - if( param.info.isSpiceInstanceParam ) - continue; - - wxString name = ( param.info.spiceModelName == "" ) ? - param.info.name : param.info.spiceModelName; - wxString value = param.value->ToSpiceString(); - - if( value == "" ) - continue; - - result << wxString::Format( "+%s%s=%s\n", wxString( ' ', indentLength - 1 ), name, value ); - } - - return result; -} - - -wxString SIM_MODEL::GenerateSpiceItemName( const wxString& aRefName ) const -{ - if( aRefName != "" && aRefName.StartsWith( GetSpiceInfo().itemType ) ) - return aRefName; - else - return GetSpiceInfo().itemType + aRefName; -} - - -wxString SIM_MODEL::GenerateSpiceItemLine( const wxString& aRefName, - const wxString& aModelName ) const -{ - // Use linear symbol pin numbers enumeration. Used in model preview. - - std::vector pinNumbers; - - for( int i = 0; i < GetPinCount(); ++i ) - pinNumbers.push_back( wxString::FromCDouble( i + 1 ) ); - - return GenerateSpiceItemLine( aRefName, aModelName, pinNumbers ); -} - - -wxString SIM_MODEL::GenerateSpiceItemLine( const wxString& aRefName, - const wxString& aModelName, - const std::vector& aSymbolPinNumbers ) const -{ - std::vector pinNetNames; - - for( const PIN& pin : GetPins() ) - pinNetNames.push_back( pin.name ); - - return GenerateSpiceItemLine( aRefName, aModelName, aSymbolPinNumbers, pinNetNames ); -} - - -wxString SIM_MODEL::GenerateSpiceItemLine( const wxString& aRefName, - const wxString& aModelName, - const std::vector& aSymbolPinNumbers, - const std::vector& aPinNetNames ) const -{ - wxString result; - result << GenerateSpiceItemName( aRefName ); - result << GenerateSpiceItemPins( aRefName, aModelName, aSymbolPinNumbers, aPinNetNames ); - result << GenerateSpiceItemModelName( aModelName ); - result << GenerateSpiceItemParams(); - result << "\n"; - return result; -} - - -wxString SIM_MODEL::GenerateSpiceTuningLine( const wxString& aSymbol ) const -{ - // TODO. - return ""; -} - - -wxString SIM_MODEL::GenerateSpicePreview( const wxString& aModelName ) const -{ - wxString spiceCode = GenerateSpiceModelLine( aModelName ); - - if( spiceCode == "" ) - spiceCode = m_spiceCode; - - if( spiceCode == "" && GetBaseModel() ) - spiceCode = GetBaseModel()->m_spiceCode; - - wxString itemLine = GenerateSpiceItemLine( "", aModelName ); - if( spiceCode != "" ) - spiceCode << "\n"; - - spiceCode << itemLine; - return spiceCode.Trim(); -} - - -std::vector SIM_MODEL::GenerateSpiceCurrentNames( const wxString& aRefName ) const -{ - LOCALE_IO toggle; - return { wxString::Format( "I(%s)", GenerateSpiceItemName( aRefName ) ) }; -} - - void SIM_MODEL::AddPin( const PIN& aPin ) { m_pins.push_back( aPin ); @@ -1096,20 +1164,6 @@ std::vector> SIM_MODEL::GetParams } -std::vector> SIM_MODEL::GetSpiceInstanceParams() const -{ - std::vector> spiceInstanceParams; - - for( const PARAM& param : GetParams() ) - { - if( param.info.isSpiceInstanceParam ) - spiceInstanceParams.emplace_back( param ); - } - - return spiceInstanceParams; -} - - const SIM_MODEL::PARAM& SIM_MODEL::GetUnderlyingParam( unsigned aParamIndex ) const { return m_params.at( aParamIndex ); @@ -1190,8 +1244,12 @@ bool SIM_MODEL::HasSpiceNonInstanceOverrides() const } -SIM_MODEL::SIM_MODEL( TYPE aType ) : m_baseModel( nullptr ), m_type( aType ), - m_isEnabled( true ), m_isInferred( false ) +SIM_MODEL::SIM_MODEL( TYPE aType, std::unique_ptr aSpiceGenerator ) : + m_spiceGenerator( std::move( aSpiceGenerator ) ), + m_baseModel( nullptr ), + m_type( aType ), + m_isEnabled( true ), + m_isInferred( false ) { } @@ -1238,59 +1296,6 @@ void SIM_MODEL::WriteInferredDataFields( std::vector& aFields, const wxString } -wxString SIM_MODEL::GenerateSpiceItemPins( const wxString& aRefName, - const wxString& aModelName, - const std::vector& aSymbolPinNumbers, - const std::vector& aPinNetNames ) const -{ - wxString result; - int ncCounter = 0; - - for( const PIN& pin : GetSpicePins() ) - { - auto it = std::find( aSymbolPinNumbers.begin(), aSymbolPinNumbers.end(), - pin.symbolPinNumber ); - - if( it == aSymbolPinNumbers.end() ) - { - LOCALE_IO toggle; - result << wxString::Format( " NC-%s-%u", aRefName, ncCounter++ ); - } - else - { - long symbolPinIndex = std::distance( aSymbolPinNumbers.begin(), it ); - result << " " << aPinNetNames.at( symbolPinIndex ); - } - } - - return result; -} - - -wxString SIM_MODEL::GenerateSpiceItemModelName( const wxString& aModelName ) const -{ - return " " + aModelName; -} - - -wxString SIM_MODEL::GenerateSpiceItemParams() const -{ - wxString result; - - for( const PARAM& param : GetSpiceInstanceParams() ) - { - wxString name = ( param.info.spiceInstanceName == "" ) ? - param.info.name : param.info.spiceInstanceName; - wxString value = param.value->ToSpiceString(); - - if( value != "" ) - result << " " << name << "=" << value; - } - - return result; -} - - wxString SIM_MODEL::GenerateParamValuePair( const PARAM& aParam, bool& aIsFirst ) const { wxString result; diff --git a/eeschema/sim/sim_model.h b/eeschema/sim/sim_model.h index c3d477ac38..8101618968 100644 --- a/eeschema/sim/sim_model.h +++ b/eeschema/sim/sim_model.h @@ -108,6 +108,50 @@ namespace SIM_MODEL_GRAMMAR class SIM_MODEL { public: + struct PIN; + struct PARAM; + + class SPICE_GENERATOR + { + public: + SPICE_GENERATOR( const SIM_MODEL& aModel ) : m_model( aModel ) {} + + virtual wxString ModelLine( const wxString& aModelName ) const; + + wxString ItemLine( const wxString& aRefName, + const wxString& aModelName ) const; + wxString ItemLine( const wxString& aRefName, + const wxString& aModelName, + const std::vector& aSymbolPinNumbers ) const; + virtual wxString ItemLine( const wxString& aRefName, + const wxString& aModelName, + const std::vector& aSymbolPinNumbers, + const std::vector& aPinNetNames ) const; + virtual wxString ItemName( const wxString& aRefName ) const; + virtual wxString ItemPins( const wxString& aRefName, + const wxString& aModelName, + const std::vector& aSymbolPinNumbers, + const std::vector& aPinNetNames ) const; + virtual wxString ItemModelName( const wxString& aModelName ) const; + virtual wxString ItemParams() const; + + virtual wxString TuningLine( const wxString& aSymbol ) const; + + virtual std::vector CurrentNames( const wxString& aRefName ) const; + + virtual wxString Preview( const wxString& aModelName ) const; + + protected: + virtual std::vector> GetPins() const + { + return m_model.GetPins(); + } + + std::vector> GetInstanceParams() const; + + const SIM_MODEL& m_model; + }; + static constexpr auto REFERENCE_FIELD = "Reference"; static constexpr auto VALUE_FIELD = "Value"; @@ -463,6 +507,8 @@ public: static void SetFieldValue( std::vector& aFields, const wxString& aFieldName, const wxString& aValue ); + const SPICE_GENERATOR& SpiceGenerator() const { return *m_spiceGenerator; } + // Move semantics. // Rule of five. @@ -472,7 +518,6 @@ public: SIM_MODEL( SIM_MODEL&& aOther ) = default; SIM_MODEL& operator=(SIM_MODEL&& aOther ) = delete; - virtual void ReadSpiceCode( const wxString& aSpiceCode ); template @@ -493,23 +538,7 @@ public: virtual bool HasToIncludeSpiceLibrary() const { return GetBaseModel() && !HasOverrides(); } - virtual wxString GenerateSpiceModelLine( const wxString& aModelName ) const; - - virtual wxString GenerateSpiceItemName( const wxString& aRefName ) const; - wxString GenerateSpiceItemLine( const wxString& aRefName, const wxString& aModelName ) const; - wxString GenerateSpiceItemLine( const wxString& aRefName, const wxString& aModelName, - const std::vector& aSymbolPinNumbers ) const; - virtual wxString GenerateSpiceItemLine( const wxString& aRefName, - const wxString& aModelName, - const std::vector& aSymbolPinNumbers, - const std::vector& aPinNetNames ) const; - - virtual wxString GenerateSpiceTuningLine( const wxString& aSymbol ) const; - - virtual wxString GenerateSpicePreview( const wxString& aModelName ) const; - SPICE_INFO GetSpiceInfo() const { return SpiceInfo( GetType() ); } - virtual std::vector GenerateSpiceCurrentNames( const wxString& aRefName ) const; void AddPin( const PIN& aPin ); int FindModelPinIndex( const wxString& aSymbolPinNumber ); @@ -541,7 +570,6 @@ public: const PARAM* FindParam( const wxString& aParamName ) const; std::vector> GetParams() const; - std::vector> GetSpiceInstanceParams() const; const PARAM& GetUnderlyingParam( unsigned aParamIndex ) const; // Return the actual parameter. const PARAM& GetBaseParam( unsigned aParamIndex ) const; // Always return base parameter if it exists. @@ -564,20 +592,14 @@ public: bool IsEnabled() const { return m_isEnabled; } protected: - SIM_MODEL( TYPE aType ); + SIM_MODEL( TYPE aType ) : SIM_MODEL( aType, std::make_unique( *this ) ) {} + SIM_MODEL( TYPE aType, std::unique_ptr aSpiceGenerator ); virtual void CreatePins( unsigned aSymbolPinCount ); template void WriteInferredDataFields( std::vector& aFields, const wxString& aValue ) const; - virtual wxString GenerateSpiceItemPins( const wxString& aRefName, - const wxString& aModelName, - const std::vector& aSymbolPinNumbers, - const std::vector& aPinNetNames ) const; - virtual wxString GenerateSpiceItemModelName( const wxString& aModelName ) const; - virtual wxString GenerateSpiceItemParams() const; - virtual wxString GenerateParamValuePair( const PARAM& aParam, bool& aIsFirst ) const; wxString GenerateParamsField( const wxString& aPairSeparator ) const; @@ -586,11 +608,6 @@ protected: void ParsePinsField( unsigned aSymbolPinCount, const wxString& aPinsField ); void ParseDisabledField( const wxString& aDisabledField ); - virtual std::vector> GetSpicePins() const - { - return GetPins(); - } - virtual bool SetParamFromSpiceCode( const wxString& aParamName, const wxString& aParamValue, SIM_VALUE_GRAMMAR::NOTATION aNotation = SIM_VALUE_GRAMMAR::NOTATION::SPICE ); @@ -629,6 +646,7 @@ private: virtual std::vector getPinNames() const { return {}; } + std::unique_ptr m_spiceGenerator; const SIM_MODEL* m_baseModel; const TYPE m_type; diff --git a/eeschema/sim/sim_model_behavioral.cpp b/eeschema/sim/sim_model_behavioral.cpp index 43aee15a17..e98b1dab33 100644 --- a/eeschema/sim/sim_model_behavioral.cpp +++ b/eeschema/sim/sim_model_behavioral.cpp @@ -25,10 +25,54 @@ #include #include +using SPICE_GENERATOR = SIM_MODEL_BEHAVIORAL::SPICE_GENERATOR; -SIM_MODEL_BEHAVIORAL::SIM_MODEL_BEHAVIORAL( TYPE aType ) - : SIM_MODEL( aType ), - m_isInferred( false ) + +wxString SPICE_GENERATOR::ModelLine( const wxString& aModelName ) const +{ + return ""; +} + + +wxString SPICE_GENERATOR::ItemLine( const wxString& aRefName, + const wxString& aModelName, + const std::vector& aSymbolPinNumbers, + const std::vector& aPinNetNames ) const +{ + LOCALE_IO toggle; + + switch( m_model.GetType() ) + { + case TYPE::R_BEHAVIORAL: + case TYPE::C_BEHAVIORAL: + case TYPE::L_BEHAVIORAL: + return SIM_MODEL::SPICE_GENERATOR::ItemLine( aRefName, + m_model.GetParam( 0 ).value->ToString(), + aSymbolPinNumbers, + aPinNetNames ); + + case TYPE::V_BEHAVIORAL: + return SIM_MODEL::SPICE_GENERATOR::ItemLine( aRefName, + wxString::Format( "V=%s", m_model.GetParam( 0 ).value->ToString() ), + aSymbolPinNumbers, + aPinNetNames ); + + case TYPE::I_BEHAVIORAL: + return SIM_MODEL::SPICE_GENERATOR::ItemLine( aRefName, + wxString::Format( "I=%s", m_model.GetParam( 0 ).value->ToString() ), + aSymbolPinNumbers, + aPinNetNames ); + + default: + wxFAIL_MSG( "Unhandled SIM_MODEL type in SIM_MODEL_BEHAVIORAL" ); + return ""; + } +} + + +SIM_MODEL_BEHAVIORAL::SIM_MODEL_BEHAVIORAL( TYPE aType ) : + SIM_MODEL( aType, std::make_unique( *this ) ), + m_isInferred( false ) { static PARAM::INFO resistor = makeParams( "r", "Expression for resistance", "Ω" ); static PARAM::INFO capacitor = makeParams( "c", "Expression for capacitance", "F" ); @@ -87,46 +131,6 @@ void SIM_MODEL_BEHAVIORAL::WriteDataLibFields( std::vector& aFields ) } -wxString SIM_MODEL_BEHAVIORAL::GenerateSpiceModelLine( const wxString& aModelName ) const -{ - return ""; -} - - -wxString SIM_MODEL_BEHAVIORAL::GenerateSpiceItemLine( const wxString& aRefName, - const wxString& aModelName, - const std::vector& aSymbolPinNumbers, - const std::vector& aPinNetNames ) const -{ - LOCALE_IO toggle; - - switch( GetType() ) - { - case TYPE::R_BEHAVIORAL: - case TYPE::C_BEHAVIORAL: - case TYPE::L_BEHAVIORAL: - return SIM_MODEL::GenerateSpiceItemLine( aRefName, - GetParam( 0 ).value->ToString(), - aSymbolPinNumbers, - aPinNetNames ); - - case TYPE::V_BEHAVIORAL: - return SIM_MODEL::GenerateSpiceItemLine( aRefName, - wxString::Format( "V=%s", GetParam( 0 ).value->ToString() ), aSymbolPinNumbers, - aPinNetNames ); - - case TYPE::I_BEHAVIORAL: - return SIM_MODEL::GenerateSpiceItemLine( aRefName, - wxString::Format( "I=%s", GetParam( 0 ).value->ToString() ), aSymbolPinNumbers, - aPinNetNames ); - - default: - wxFAIL_MSG( "Unhandled SIM_MODEL type in SIM_MODEL_BEHAVIORAL" ); - return ""; - } -} - - bool SIM_MODEL_BEHAVIORAL::parseValueField( const wxString& aValueField ) { wxString expr = aValueField; diff --git a/eeschema/sim/sim_model_behavioral.h b/eeschema/sim/sim_model_behavioral.h index 7ebcced57a..974ada8956 100644 --- a/eeschema/sim/sim_model_behavioral.h +++ b/eeschema/sim/sim_model_behavioral.h @@ -31,6 +31,19 @@ class SIM_MODEL_BEHAVIORAL : public SIM_MODEL { public: + class SPICE_GENERATOR : public SIM_MODEL::SPICE_GENERATOR + { + public: + using SIM_MODEL::SPICE_GENERATOR::SPICE_GENERATOR; + + wxString ModelLine( const wxString& aModelName ) const override; + wxString ItemLine( const wxString& aRefName, + const wxString& aModelName, + const std::vector& aSymbolPinNumbers, + const std::vector& aPinNetNames ) const override; + }; + + SIM_MODEL_BEHAVIORAL( TYPE aType ); void ReadDataSchFields( unsigned aSymbolPinCount, @@ -41,12 +54,6 @@ public: void WriteDataSchFields( std::vector& aFields ) const override; void WriteDataLibFields( std::vector& aFields ) const override; - wxString GenerateSpiceModelLine( const wxString& aModelName ) const override; - - wxString GenerateSpiceItemLine( const wxString& aRefName, - const wxString& aModelName, - const std::vector& aSymbolPinNumbers, - const std::vector& aPinNetNames ) const override; private: bool parseValueField( const wxString& aValueField ); @@ -61,6 +68,7 @@ private: static PARAM::INFO makeParams( wxString aName, wxString aDescription, wxString aUnit ); + bool m_isInferred; }; diff --git a/eeschema/sim/sim_model_ideal.cpp b/eeschema/sim/sim_model_ideal.cpp index 35426a8a05..7fd6326c43 100644 --- a/eeschema/sim/sim_model_ideal.cpp +++ b/eeschema/sim/sim_model_ideal.cpp @@ -26,10 +26,33 @@ #include #include +using SPICE_GENERATOR = SIM_MODEL_IDEAL::SPICE_GENERATOR; -SIM_MODEL_IDEAL::SIM_MODEL_IDEAL( TYPE aType ) - : SIM_MODEL( aType ), - m_isInferred( false ) + +wxString SPICE_GENERATOR::ModelLine( const wxString& aModelName ) const +{ + return ""; +} + + +wxString SPICE_GENERATOR::ItemLine( const wxString& aRefName, + const wxString& aModelName, + const std::vector& aSymbolPinNumbers, + const std::vector& aPinNetNames ) const +{ + wxString valueStr = m_model.GetParam( 0 ).value->ToString( SIM_VALUE::NOTATION::SPICE ); + + if( valueStr != "" ) + return SIM_MODEL::SPICE_GENERATOR::ItemLine( aRefName, valueStr, aSymbolPinNumbers, + aPinNetNames ); + else + return ""; +} + + +SIM_MODEL_IDEAL::SIM_MODEL_IDEAL( TYPE aType ) : + SIM_MODEL( aType, std::make_unique( *this ) ), + m_isInferred( false ) { static PARAM::INFO resistor = makeParamInfo( "r", "Resistance", "Ω" ); static PARAM::INFO capacitor = makeParamInfo( "c", "Capacitance", "F" ); @@ -84,26 +107,6 @@ void SIM_MODEL_IDEAL::WriteDataLibFields( std::vector& aFields ) cons } -wxString SIM_MODEL_IDEAL::GenerateSpiceModelLine( const wxString& aModelName ) const -{ - return ""; -} - - -wxString SIM_MODEL_IDEAL::GenerateSpiceItemLine( const wxString& aRefName, - const wxString& aModelName, - const std::vector& aSymbolPinNumbers, - const std::vector& aPinNetNames ) const -{ - wxString valueStr = GetParam( 0 ).value->ToString( SIM_VALUE::NOTATION::SPICE ); - - if( valueStr != "" ) - return SIM_MODEL::GenerateSpiceItemLine( aRefName, valueStr, aSymbolPinNumbers, aPinNetNames ); - else - return ""; -} - - template void SIM_MODEL_IDEAL::inferredWriteDataFields( std::vector& aFields ) const { diff --git a/eeschema/sim/sim_model_ideal.h b/eeschema/sim/sim_model_ideal.h index 8492205b6e..5211f39428 100644 --- a/eeschema/sim/sim_model_ideal.h +++ b/eeschema/sim/sim_model_ideal.h @@ -31,6 +31,19 @@ class SIM_MODEL_IDEAL : public SIM_MODEL { public: + class SPICE_GENERATOR : public SIM_MODEL::SPICE_GENERATOR + { + public: + using SIM_MODEL::SPICE_GENERATOR::SPICE_GENERATOR; + + wxString ModelLine( const wxString& aModelName ) const override; + wxString ItemLine( const wxString& aRefName, + const wxString& aModelName, + const std::vector& aSymbolPinNumbers, + const std::vector& aPinNetNames ) const override; + }; + + SIM_MODEL_IDEAL( TYPE aType ); void ReadDataSchFields( unsigned aSymbolPinCount, const std::vector* aFields ) override; @@ -39,13 +52,6 @@ public: void WriteDataSchFields( std::vector& aFields ) const override; void WriteDataLibFields( std::vector& aFields ) const override; - wxString GenerateSpiceModelLine( const wxString& aModelName ) const override; - wxString GenerateSpiceItemLine( const wxString& aRefName, - const wxString& aModelName, - const std::vector& aSymbolPinNumbers, - const std::vector& aPinNetNames ) const override; - - private: template void inferredWriteDataFields( std::vector& aFields ) const; diff --git a/eeschema/sim/sim_model_mutual_inductor.cpp b/eeschema/sim/sim_model_mutual_inductor.cpp index ccdc86af91..784a69ae81 100644 --- a/eeschema/sim/sim_model_mutual_inductor.cpp +++ b/eeschema/sim/sim_model_mutual_inductor.cpp @@ -24,8 +24,22 @@ #include +using SPICE_GENERATOR = SIM_MODEL_MUTUAL_INDUCTOR::SPICE_GENERATOR; -SIM_MODEL_MUTUAL_INDUCTOR::SIM_MODEL_MUTUAL_INDUCTOR() : SIM_MODEL( SIM_MODEL::TYPE::L_MUTUAL ) + +wxString SPICE_GENERATOR::ItemParams() const +{ + wxString result; + + for( const PARAM& param : GetInstanceParams() ) + result << " " << param.value->ToSpiceString(); + + return result; +} + + +SIM_MODEL_MUTUAL_INDUCTOR::SIM_MODEL_MUTUAL_INDUCTOR() : + SIM_MODEL( SIM_MODEL::TYPE::L_MUTUAL, std::make_unique( *this ) ) { static std::vector paramInfos = makeParamInfos(); @@ -34,17 +48,6 @@ SIM_MODEL_MUTUAL_INDUCTOR::SIM_MODEL_MUTUAL_INDUCTOR() : SIM_MODEL( SIM_MODEL::T } -wxString SIM_MODEL_MUTUAL_INDUCTOR::GenerateSpiceItemParams() const -{ - wxString result; - - for( const PARAM& param : GetSpiceInstanceParams() ) - result << param.value->ToSimpleString() << " "; - - return result; -} - - const std::vector SIM_MODEL_MUTUAL_INDUCTOR::makeParamInfos() { std::vector paramInfos; diff --git a/eeschema/sim/sim_model_mutual_inductor.h b/eeschema/sim/sim_model_mutual_inductor.h index 4f0aa192ce..d4374ad589 100644 --- a/eeschema/sim/sim_model_mutual_inductor.h +++ b/eeschema/sim/sim_model_mutual_inductor.h @@ -31,9 +31,15 @@ class SIM_MODEL_MUTUAL_INDUCTOR : public SIM_MODEL { public: - SIM_MODEL_MUTUAL_INDUCTOR(); + class SPICE_GENERATOR : public SIM_MODEL::SPICE_GENERATOR + { + public: + using SIM_MODEL::SPICE_GENERATOR::SPICE_GENERATOR; - wxString GenerateSpiceItemParams() const override; + wxString ItemParams() const override; + }; + + SIM_MODEL_MUTUAL_INDUCTOR(); private: static const std::vector makeParamInfos(); diff --git a/eeschema/sim/sim_model_ngspice.cpp b/eeschema/sim/sim_model_ngspice.cpp index 15c0122745..3312796b8d 100644 --- a/eeschema/sim/sim_model_ngspice.cpp +++ b/eeschema/sim/sim_model_ngspice.cpp @@ -25,34 +25,15 @@ #include #include +using SPICE_GENERATOR = SIM_MODEL_NGSPICE::SPICE_GENERATOR; using TYPE = SIM_MODEL::TYPE; -SIM_MODEL_NGSPICE::SIM_MODEL_NGSPICE( TYPE aType ) - : SIM_MODEL( aType ) -{ - const MODEL_INFO& modelInfo = ModelInfo( getModelType() ); - - for( const SIM_MODEL::PARAM::INFO& paramInfo : modelInfo.instanceParams ) - { - // For now, only the geometry parameters. - if( paramInfo.category == SIM_MODEL::PARAM::CATEGORY::PRINCIPAL - || paramInfo.category == SIM_MODEL::PARAM::CATEGORY::GEOMETRY ) - { - AddParam( paramInfo, getIsOtherVariant() ); - } - } - - for( const SIM_MODEL::PARAM::INFO& paramInfo : modelInfo.modelParams ) - AddParam( paramInfo, getIsOtherVariant() ); -} - - -std::vector SIM_MODEL_NGSPICE::GenerateSpiceCurrentNames( const wxString& aRefName ) const +std::vector SPICE_GENERATOR::CurrentNames( const wxString& aRefName ) const { LOCALE_IO toggle; - switch( TypeInfo( GetType() ).deviceType ) + switch( m_model.GetTypeInfo().deviceType ) { case DEVICE_TYPE_::NPN: case DEVICE_TYPE_::PNP: @@ -74,7 +55,7 @@ std::vector SIM_MODEL_NGSPICE::GenerateSpiceCurrentNames( const wxStri case DEVICE_TYPE_::C: case DEVICE_TYPE_::L: case DEVICE_TYPE_::D: - return SIM_MODEL::GenerateSpiceCurrentNames( aRefName ); + return CurrentNames( aRefName ); default: wxFAIL_MSG( "Unhandled model device type in SIM_MODEL_NGSPICE" ); @@ -83,6 +64,26 @@ std::vector SIM_MODEL_NGSPICE::GenerateSpiceCurrentNames( const wxStri } +SIM_MODEL_NGSPICE::SIM_MODEL_NGSPICE( TYPE aType ) + : SIM_MODEL( aType, std::make_unique( *this ) ) +{ + const MODEL_INFO& modelInfo = ModelInfo( getModelType() ); + + for( const SIM_MODEL::PARAM::INFO& paramInfo : modelInfo.instanceParams ) + { + // For now, only the geometry parameters. + if( paramInfo.category == SIM_MODEL::PARAM::CATEGORY::PRINCIPAL + || paramInfo.category == SIM_MODEL::PARAM::CATEGORY::GEOMETRY ) + { + AddParam( paramInfo, getIsOtherVariant() ); + } + } + + for( const SIM_MODEL::PARAM::INFO& paramInfo : modelInfo.modelParams ) + AddParam( paramInfo, getIsOtherVariant() ); +} + + bool SIM_MODEL_NGSPICE::SetParamFromSpiceCode( const wxString& aParamName, const wxString& aParamValue, SIM_VALUE_GRAMMAR::NOTATION aNotation ) { diff --git a/eeschema/sim/sim_model_ngspice.h b/eeschema/sim/sim_model_ngspice.h index 401a7d2a92..419d05a287 100644 --- a/eeschema/sim/sim_model_ngspice.h +++ b/eeschema/sim/sim_model_ngspice.h @@ -33,9 +33,16 @@ class SIM_MODEL_NGSPICE : public SIM_MODEL public: friend struct MODEL_INFO_MAP; - SIM_MODEL_NGSPICE( TYPE aType ); + class SPICE_GENERATOR : public SIM_MODEL::SPICE_GENERATOR + { + public: + using SIM_MODEL::SPICE_GENERATOR::SPICE_GENERATOR; - std::vector GenerateSpiceCurrentNames( const wxString& aRefName ) const override; + std::vector CurrentNames( const wxString& aRefName ) const override; + }; + + + SIM_MODEL_NGSPICE( TYPE aType ); bool SetParamFromSpiceCode( const wxString& aParamName, const wxString& aParamValue, SIM_VALUE_GRAMMAR::NOTATION aNotation ) override; diff --git a/eeschema/sim/sim_model_source.cpp b/eeschema/sim/sim_model_source.cpp index 9a017e155e..d18df94519 100644 --- a/eeschema/sim/sim_model_source.cpp +++ b/eeschema/sim/sim_model_source.cpp @@ -27,6 +27,8 @@ #include #include +using SPICE_GENERATOR = SIM_MODEL_SOURCE::SPICE_GENERATOR; + namespace SIM_MODEL_SOURCE_PARSER { @@ -38,63 +40,36 @@ namespace SIM_MODEL_SOURCE_PARSER } -SIM_MODEL_SOURCE::SIM_MODEL_SOURCE( TYPE aType ) - : SIM_MODEL( aType ), - m_isInferred( false ) -{ - for( const SIM_MODEL::PARAM::INFO& paramInfo : makeParamInfos( aType ) ) - AddParam( paramInfo ); -} - - -void SIM_MODEL_SOURCE::WriteDataSchFields( std::vector& aFields ) const -{ - SIM_MODEL::WriteDataSchFields( aFields ); - - if( m_isInferred ) - inferredWriteDataFields( aFields ); -} - - -void SIM_MODEL_SOURCE::WriteDataLibFields( std::vector& aFields ) const -{ - SIM_MODEL::WriteDataLibFields( aFields ); - - if( m_isInferred ) - inferredWriteDataFields( aFields ); -} - - -wxString SIM_MODEL_SOURCE::GenerateSpiceModelLine( const wxString& aModelName ) const +wxString SPICE_GENERATOR::ModelLine( const wxString& aModelName ) const { return ""; } -wxString SIM_MODEL_SOURCE::GenerateSpiceItemLine( const wxString& aRefName, - const wxString& aModelName, - const std::vector& aSymbolPinNumbers, - const std::vector& aPinNetNames ) const +wxString SPICE_GENERATOR::ItemLine( const wxString& aRefName, + const wxString& aModelName, + const std::vector& aSymbolPinNumbers, + const std::vector& aPinNetNames ) const { LOCALE_IO toggle; wxString model; - wxString ac = FindParam( "ac" )->value->ToSpiceString(); - wxString ph = FindParam( "ph" )->value->ToSpiceString(); + wxString ac = m_model.FindParam( "ac" )->value->ToSpiceString(); + wxString ph = m_model.FindParam( "ph" )->value->ToSpiceString(); if( ac != "" ) model << wxString::Format( "AC %s %s ", ac, ph ); - if( GetSpiceInfo().inlineTypeString != "" ) + if( m_model.GetSpiceInfo().inlineTypeString != "" ) { wxString args = ""; - switch( GetType() ) + switch( m_model.GetType() ) { case TYPE::V_PWL: case TYPE::I_PWL: { - tao::pegtl::string_input<> in( GetParam( 0 ).value->ToString().ToUTF8(), + tao::pegtl::string_input<> in( m_model.GetParam( 0 ).value->ToString().ToUTF8(), "from_content" ); std::unique_ptr root; @@ -158,8 +133,8 @@ wxString SIM_MODEL_SOURCE::GenerateSpiceItemLine( const wxString& aRefName, args << getParamValueString( "dt", "0" ) << " "; args << getParamValueString( "td", "0" ) << " "; - auto min = dynamic_cast( *FindParam( "max" )->value ); - auto max = dynamic_cast( *FindParam( "min" )->value ); + auto min = dynamic_cast( *m_model.FindParam( "max" )->value ); + auto max = dynamic_cast( *m_model.FindParam( "min" )->value ); SIM_VALUE_FLOAT range = max - min; SIM_VALUE_FLOAT offset = ( max + min ) / SIM_VALUE_FLOAT( 2 ); @@ -196,7 +171,7 @@ wxString SIM_MODEL_SOURCE::GenerateSpiceItemLine( const wxString& aRefName, break;*/ default: - for( const PARAM& param : GetParams() ) + for( const PARAM& param : m_model.GetParams() ) { wxString argStr = param.value->ToString( SIM_VALUE_GRAMMAR::NOTATION::SPICE ); @@ -206,12 +181,51 @@ wxString SIM_MODEL_SOURCE::GenerateSpiceItemLine( const wxString& aRefName, break; } - model << wxString::Format( "%s( %s)", GetSpiceInfo().inlineTypeString, args ); + model << wxString::Format( "%s( %s)", m_model.GetSpiceInfo().inlineTypeString, args ); } else - model << GetParam( 0 ).value->ToSpiceString(); + model << m_model.GetParam( 0 ).value->ToSpiceString(); - return SIM_MODEL::GenerateSpiceItemLine( aRefName, model, aSymbolPinNumbers, aPinNetNames ); + return SIM_MODEL::SPICE_GENERATOR::ItemLine( aRefName, model, aSymbolPinNumbers, aPinNetNames ); +} + + +wxString SPICE_GENERATOR::getParamValueString( const wxString& aParamName, + const wxString& aDefaultValue ) const +{ + wxString result = m_model.FindParam( aParamName )->value->ToSpiceString(); + + if( result == "" ) + result = aDefaultValue; + + return result; +} + + +SIM_MODEL_SOURCE::SIM_MODEL_SOURCE( TYPE aType ) + : SIM_MODEL( aType, std::make_unique( *this ) ), + m_isInferred( false ) +{ + for( const SIM_MODEL::PARAM::INFO& paramInfo : makeParamInfos( aType ) ) + AddParam( paramInfo ); +} + + +void SIM_MODEL_SOURCE::WriteDataSchFields( std::vector& aFields ) const +{ + SIM_MODEL::WriteDataSchFields( aFields ); + + if( m_isInferred ) + inferredWriteDataFields( aFields ); +} + + +void SIM_MODEL_SOURCE::WriteDataLibFields( std::vector& aFields ) const +{ + SIM_MODEL::WriteDataLibFields( aFields ); + + if( m_isInferred ) + inferredWriteDataFields( aFields ); } @@ -263,18 +277,6 @@ void SIM_MODEL_SOURCE::inferredWriteDataFields( std::vector& aFields ) const } -wxString SIM_MODEL_SOURCE::getParamValueString( const wxString& aParamName, - const wxString& aDefaultValue ) const -{ - wxString result = FindParam( aParamName )->value->ToSpiceString(); - - if( result == "" ) - result = aDefaultValue; - - return result; -} - - const std::vector& SIM_MODEL_SOURCE::makeParamInfos( TYPE aType ) { static std::vector vdc = makeDcParamInfos( "y", "V" ); diff --git a/eeschema/sim/sim_model_source.h b/eeschema/sim/sim_model_source.h index 30b7d2ac26..708b838380 100644 --- a/eeschema/sim/sim_model_source.h +++ b/eeschema/sim/sim_model_source.h @@ -46,17 +46,28 @@ namespace SIM_MODEL_SOURCE_GRAMMAR class SIM_MODEL_SOURCE : public SIM_MODEL { public: + class SPICE_GENERATOR : public SIM_MODEL::SPICE_GENERATOR + { + public: + using SIM_MODEL::SPICE_GENERATOR::SPICE_GENERATOR; + + wxString ModelLine( const wxString& aModelName ) const override; + wxString ItemLine( const wxString& aRefName, + const wxString& aModelName, + const std::vector& aSymbolPinNumbers, + const std::vector& aPinNetNames ) const override; + + private: + wxString getParamValueString( const wxString& aParamName, + const wxString& aDefaultValue ) const; + }; + + SIM_MODEL_SOURCE( TYPE aType ); void WriteDataSchFields( std::vector& aFields ) const override; void WriteDataLibFields( std::vector& aFields ) const override; - wxString GenerateSpiceModelLine( const wxString& aModelName ) const override; - wxString GenerateSpiceItemLine( const wxString& aRefName, - const wxString& aModelName, - const std::vector& aSymbolPinNumbers, - const std::vector& aPinNetNames ) const override; - bool SetParamValue( unsigned aParamIndex, const wxString& aValue, SIM_VALUE_GRAMMAR::NOTATION aNotation = SIM_VALUE_GRAMMAR::NOTATION::SI ) override; @@ -72,8 +83,6 @@ private: std::vector getPinNames() const override { return { "+", "-" }; } - wxString getParamValueString( const wxString& aParamName, const wxString& aDefaultValue ) const; - static const std::vector& makeParamInfos( TYPE aType ); static std::vector makeDcParamInfos( wxString aPrefix, wxString aUnit ); @@ -94,6 +103,7 @@ private: static void appendAcParamInfos( std::vector& aParamInfos, wxString aUnit ); + bool m_isInferred; }; diff --git a/eeschema/sim/sim_model_spice.cpp b/eeschema/sim/sim_model_spice.cpp index d37b11281c..b924094bc8 100644 --- a/eeschema/sim/sim_model_spice.cpp +++ b/eeschema/sim/sim_model_spice.cpp @@ -26,6 +26,8 @@ #include #include +using SPICE_GENERATOR = SIM_MODEL_SPICE::SPICE_GENERATOR; + namespace SIM_MODEL_SPICE_PARSER { @@ -36,8 +38,85 @@ namespace SIM_MODEL_SPICE_PARSER } -SIM_MODEL_SPICE::SIM_MODEL_SPICE( TYPE aType ) - : SIM_MODEL( aType ) +wxString SPICE_GENERATOR::ModelLine( const wxString& aModelName ) const +{ + return ""; +} + + +wxString SPICE_GENERATOR::ItemName( const wxString& aRefName ) const +{ + wxString elementType = m_model.GetParam( static_cast( SPICE_PARAM::TYPE ) ).value->ToString(); + + if( aRefName != "" && aRefName.StartsWith( elementType ) ) + return aRefName; + else + return elementType + aRefName; +} + + +wxString SPICE_GENERATOR::ItemPins( const wxString& aRefName, + const wxString& aModelName, + const std::vector& aSymbolPinNumbers, + const std::vector& aPinNetNames ) const +{ + wxString result; + + for( const PIN& pin : GetPins() ) + { + auto it = std::find( aSymbolPinNumbers.begin(), aSymbolPinNumbers.end(), + pin.symbolPinNumber ); + + if( it != aSymbolPinNumbers.end() ) + { + long symbolPinIndex = std::distance( aSymbolPinNumbers.begin(), it ); + result << " " << aPinNetNames.at( symbolPinIndex ); + } + } + + return result; +} + + +wxString SPICE_GENERATOR::ItemModelName( const wxString& aModelName ) const +{ + return ""; +} + + +wxString SPICE_GENERATOR::ItemParams() const +{ + wxString result; + + for( const PARAM& param : GetInstanceParams() ) + { + if( param.info.name != "model" ) + result << ""; + else + result << " " << param.value->ToString(); + } + + return result; +} + + +wxString SPICE_GENERATOR::Preview( const wxString& aModelName ) const +{ + std::vector pinNumbers; + std::vector pinNetNames; + + for( int i = 0; i < m_model.GetPinCount(); ++i ) + { + pinNumbers.push_back( wxString::FromCDouble( i + 1 ) ); + pinNetNames.push_back( wxString::FromCDouble( i + 1 ) ); + } + + return ItemLine( "", aModelName, pinNumbers, pinNetNames ); +} + + +SIM_MODEL_SPICE::SIM_MODEL_SPICE( TYPE aType ) : + SIM_MODEL( aType, std::make_unique( *this ) ) { static std::vector paramInfos = makeParamInfos(); @@ -81,38 +160,6 @@ void SIM_MODEL_SPICE::WriteDataLibFields( std::vector& aFields ) cons } -wxString SIM_MODEL_SPICE::GenerateSpiceModelLine( const wxString& aModelName ) const -{ - return ""; -} - - -wxString SIM_MODEL_SPICE::GenerateSpiceItemName( const wxString& aRefName ) const -{ - wxString elementType = GetParam( static_cast( SPICE_PARAM::TYPE ) ).value->ToString(); - - if( aRefName != "" && aRefName.StartsWith( elementType ) ) - return aRefName; - else - return elementType + aRefName; -} - - -wxString SIM_MODEL_SPICE::GenerateSpicePreview( const wxString& aModelName ) const -{ - std::vector pinNumbers; - std::vector pinNetNames; - - for( int i = 0; i < GetPinCount(); ++i ) - { - pinNumbers.push_back( wxString::FromCDouble( i + 1 ) ); - pinNetNames.push_back( wxString::FromCDouble( i + 1 ) ); - } - - return GenerateSpiceItemLine( "", aModelName, pinNumbers, pinNetNames ); -} - - void SIM_MODEL_SPICE::CreatePins( unsigned aSymbolPinCount ) { for( unsigned symbolPinIndex = 0; symbolPinIndex < aSymbolPinCount; ++symbolPinIndex ) @@ -120,51 +167,6 @@ void SIM_MODEL_SPICE::CreatePins( unsigned aSymbolPinCount ) } -wxString SIM_MODEL_SPICE::GenerateSpiceItemPins( const wxString& aRefName, - const wxString& aModelName, - const std::vector& aSymbolPinNumbers, - const std::vector& aPinNetNames ) const -{ - wxString result; - - for( const PIN& pin : GetSpicePins() ) - { - auto it = std::find( aSymbolPinNumbers.begin(), aSymbolPinNumbers.end(), - pin.symbolPinNumber ); - - if( it != aSymbolPinNumbers.end() ) - { - long symbolPinIndex = std::distance( aSymbolPinNumbers.begin(), it ); - result << " " << aPinNetNames.at( symbolPinIndex ); - } - } - - return result; -} - - -wxString SIM_MODEL_SPICE::GenerateSpiceItemModelName( const wxString& aModelName ) const -{ - return ""; -} - - -wxString SIM_MODEL_SPICE::GenerateSpiceItemParams() const -{ - wxString result; - - for( const PARAM& param : GetSpiceInstanceParams() ) - { - if( param.info.name != "model" ) - result << ""; - else - result << " " << param.value->ToString(); - } - - return result; -} - - bool SIM_MODEL_SPICE::SetParamFromSpiceCode( const wxString& aParamName, const wxString& aParamValue, SIM_VALUE_GRAMMAR::NOTATION aNotation ) diff --git a/eeschema/sim/sim_model_spice.h b/eeschema/sim/sim_model_spice.h index b75042f9aa..6d68c9878c 100644 --- a/eeschema/sim/sim_model_spice.h +++ b/eeschema/sim/sim_model_spice.h @@ -31,6 +31,25 @@ class SIM_MODEL_SPICE : public SIM_MODEL { public: + class SPICE_GENERATOR : public SIM_MODEL::SPICE_GENERATOR + { + public: + using SIM_MODEL::SPICE_GENERATOR::SPICE_GENERATOR; + + wxString ModelLine( const wxString& aModelName ) const override; + + wxString ItemName( const wxString& aRefName ) const override; + wxString ItemPins( const wxString& aRefName, + const wxString& aModelName, + const std::vector& aSymbolPinNumbers, + const std::vector& aPinNetNames ) const override; + wxString ItemModelName( const wxString& aModelName ) const override; + wxString ItemParams() const override; + + wxString Preview( const wxString& aModelName ) const override; + }; + + DEFINE_ENUM_CLASS_WITH_ITERATOR( SPICE_PARAM, TYPE, MODEL, @@ -53,29 +72,16 @@ public: void WriteDataSchFields( std::vector& aFields ) const override; void WriteDataLibFields( std::vector& aFields ) const override; - - wxString GenerateSpiceModelLine( const wxString& aModelName ) const override; - wxString GenerateSpiceItemName( const wxString& aRefName ) const override; - wxString GenerateSpicePreview( const wxString& aModelName ) const override; - protected: void CreatePins( unsigned aSymbolPinCount ) override; - wxString GenerateSpiceItemPins( const wxString& aRefName, - const wxString& aModelName, - const std::vector& aSymbolPinNumbers, - const std::vector& aPinNetNames ) const override; - - wxString GenerateSpiceItemModelName( const wxString& aModelName ) const override; - - wxString GenerateSpiceItemParams() const override; bool SetParamFromSpiceCode( const wxString& aParamName, const wxString& aParamValue, SIM_VALUE_GRAMMAR::NOTATION aNotation = SIM_VALUE_GRAMMAR::NOTATION::SPICE ) override; private: - std::vector makeParamInfos(); + static std::vector makeParamInfos(); template void readLegacyDataFields( unsigned aSymbolPinCount, const std::vector* aFields ); @@ -84,6 +90,7 @@ private: bool requiresSpiceModelLine() const override { return false; } + std::vector> m_paramInfos; }; diff --git a/eeschema/sim/sim_model_subckt.cpp b/eeschema/sim/sim_model_subckt.cpp index d3446d0ff9..ae565aa125 100644 --- a/eeschema/sim/sim_model_subckt.cpp +++ b/eeschema/sim/sim_model_subckt.cpp @@ -27,6 +27,8 @@ #include #include +using SPICE_GENERATOR = SIM_MODEL_SUBCKT::SPICE_GENERATOR; + namespace SIM_MODEL_SUBCKT_SPICE_PARSER { @@ -46,8 +48,29 @@ namespace SIM_MODEL_SUBCKT_SPICE_PARSER } -SIM_MODEL_SUBCKT::SIM_MODEL_SUBCKT( TYPE aType ) - : SIM_MODEL( aType ) +wxString SPICE_GENERATOR::ModelLine( const wxString& aModelName ) const +{ + return ""; +} + + +std::vector SPICE_GENERATOR::CurrentNames( const wxString& aRefName ) const +{ + std::vector currentNames; + + for( const PIN& pin : GetPins() ) + { + currentNames.push_back( wxString::Format( "I(%s:%s)", + ItemName( aRefName ), + pin.name ) ); + } + + return currentNames; +} + + +SIM_MODEL_SUBCKT::SIM_MODEL_SUBCKT( TYPE aType ) : + SIM_MODEL( aType, std::make_unique( *this ) ) { } @@ -122,27 +145,6 @@ void SIM_MODEL_SUBCKT::ReadSpiceCode( const wxString& aSpiceCode ) } -wxString SIM_MODEL_SUBCKT::GenerateSpiceModelLine( const wxString& aModelName ) const -{ - return ""; -} - - -std::vector SIM_MODEL_SUBCKT::GenerateSpiceCurrentNames( const wxString& aRefName ) const -{ - std::vector currentNames; - - for( const PIN& pin : GetPins() ) - { - currentNames.push_back( wxString::Format( "I(%s:%s)", - GenerateSpiceItemName( aRefName ), - pin.name ) ); - } - - return currentNames; -} - - void SIM_MODEL_SUBCKT::SetBaseModel( const SIM_MODEL& aBaseModel ) { SIM_MODEL::SetBaseModel( aBaseModel ); diff --git a/eeschema/sim/sim_model_subckt.h b/eeschema/sim/sim_model_subckt.h index bbf69c3669..7545016f50 100644 --- a/eeschema/sim/sim_model_subckt.h +++ b/eeschema/sim/sim_model_subckt.h @@ -31,11 +31,19 @@ class SIM_MODEL_SUBCKT : public SIM_MODEL { public: + class SPICE_GENERATOR : public SIM_MODEL::SPICE_GENERATOR + { + public: + using SIM_MODEL::SPICE_GENERATOR::SPICE_GENERATOR; + + wxString ModelLine( const wxString& aModelName ) const override; + std::vector CurrentNames( const wxString& aRefName ) const override; + }; + + SIM_MODEL_SUBCKT( TYPE aType ); void ReadSpiceCode( const wxString& aSpiceCode ) override; - wxString GenerateSpiceModelLine( const wxString& aModelName ) const override; - std::vector GenerateSpiceCurrentNames( const wxString& aRefName ) const override; void SetBaseModel( const SIM_MODEL& aBaseModel ) override; protected: @@ -44,6 +52,7 @@ protected: private: bool requiresSpiceModelLine() const override { return true; } + std::vector> m_paramInfos; }; diff --git a/eeschema/sim/sim_model_switch.cpp b/eeschema/sim/sim_model_switch.cpp index f372c831fd..f645e41b73 100644 --- a/eeschema/sim/sim_model_switch.cpp +++ b/eeschema/sim/sim_model_switch.cpp @@ -24,8 +24,84 @@ #include +using SPICE_GENERATOR = SIM_MODEL_SWITCH::SPICE_GENERATOR; -SIM_MODEL_SWITCH::SIM_MODEL_SWITCH( TYPE aType ) : SIM_MODEL( aType ) + +wxString SPICE_GENERATOR::ItemLine( const wxString& aRefName, + const wxString& aModelName, + const std::vector& aSymbolPinNumbers, + const std::vector& aPinNetNames ) const +{ + wxString result; + + switch( m_model.GetType() ) + { + case TYPE::SW_V: + { + result << SIM_MODEL::SPICE_GENERATOR::ItemLine( aRefName, aModelName, aSymbolPinNumbers, + aPinNetNames ); + break; + } + + case TYPE::SW_I: + { + wxString vsourceName = "V__" + aRefName; + + // Current switches measure input current through a voltage source. + result << vsourceName << " " << aPinNetNames[0] << " " << aPinNetNames[1] << " 0\n"; + + result << SIM_MODEL::SPICE_GENERATOR::ItemLine( aRefName, vsourceName + " " + aModelName, + aSymbolPinNumbers, aPinNetNames ); + break; + } + + default: + wxFAIL_MSG( "Unhandled SIM_MODEL type in SIM_MODEL_SWITCH" ); + break; + } + + return result; +} + + +wxString SPICE_GENERATOR::ItemParams() const +{ + wxString result; + + for( const PARAM& param : GetInstanceParams() ) + { + // The only instance param is "ic", which is positional. + wxString value = param.value->ToSpiceString(); + + if( value == "none" ) + result << ""; + else + result << value; + } + + return result; +} + + +std::vector> SPICE_GENERATOR::GetPins() const +{ + switch( m_model.GetType() ) + { + case TYPE::SW_V: + return { m_model.GetPin( 2 ), m_model.GetPin( 3 ), m_model.GetPin( 0 ), m_model.GetPin( 1 ) }; + + case TYPE::SW_I: + return { m_model.GetPin( 2 ), m_model.GetPin( 3 ) }; + + default: + wxFAIL_MSG( "Unhandled SIM_MODEL type in SIM_MODEL_SWITCH" ); + return {}; + } +} + + +SIM_MODEL_SWITCH::SIM_MODEL_SWITCH( TYPE aType ) : + SIM_MODEL( aType, std::make_unique( *this ) ) { static std::vector vsw = makeSwVParamInfos(); static std::vector isw = makeSwIParamInfos(); @@ -51,62 +127,6 @@ SIM_MODEL_SWITCH::SIM_MODEL_SWITCH( TYPE aType ) : SIM_MODEL( aType ) } -wxString SIM_MODEL_SWITCH::GenerateSpiceItemParams() const -{ - wxString result; - - for( const PARAM& param : GetSpiceInstanceParams() ) - { - // The only instance param is "ic", which is positional. - wxString value = param.value->ToSpiceString(); - - if( value == "none" ) - result << ""; - else - result << value; - } - - return result; -} - - -wxString SIM_MODEL_SWITCH::GenerateSpiceItemLine( const wxString& aRefName, - const wxString& aModelName, - const std::vector& aSymbolPinNumbers, - const std::vector& aPinNetNames ) const -{ - wxString result; - - switch( GetType() ) - { - case TYPE::SW_V: - { - result << SIM_MODEL::GenerateSpiceItemLine( aRefName, aModelName, aSymbolPinNumbers, - aPinNetNames ); - break; - } - - case TYPE::SW_I: - { - wxString vsourceName = "V__" + aRefName; - - // Current switches measure input current through a voltage source. - result << vsourceName << " " << aPinNetNames[0] << " " << aPinNetNames[1] << " 0\n"; - - result << SIM_MODEL::GenerateSpiceItemLine( aRefName, vsourceName + " " + aModelName, - aSymbolPinNumbers, aPinNetNames ); - break; - } - - default: - wxFAIL_MSG( "Unhandled SIM_MODEL type in SIM_MODEL_SWITCH" ); - break; - } - - return result; -} - - wxString SIM_MODEL_SWITCH::GenerateParamValuePair( const PARAM& aParam, bool& aIsFirst ) const { if( aParam.info.name == "ic" && aParam.value->ToString() == "none" ) @@ -118,23 +138,6 @@ wxString SIM_MODEL_SWITCH::GenerateParamValuePair( const PARAM& aParam, bool& aI } -std::vector> SIM_MODEL_SWITCH::GetSpicePins() const -{ - switch( GetType() ) - { - case TYPE::SW_V: - return { GetPin( 2 ), GetPin( 3 ), GetPin( 0 ), GetPin( 1 ) }; - - case TYPE::SW_I: - return { GetPin( 2 ), GetPin( 3 ) }; - - default: - wxFAIL_MSG( "Unhandled SIM_MODEL type in SIM_MODEL_SWITCH" ); - return {}; - } -} - - const std::vector SIM_MODEL_SWITCH::makeSwVParamInfos() { std::vector paramInfos; diff --git a/eeschema/sim/sim_model_switch.h b/eeschema/sim/sim_model_switch.h index 8813da7164..e12cc25cfb 100644 --- a/eeschema/sim/sim_model_switch.h +++ b/eeschema/sim/sim_model_switch.h @@ -31,16 +31,23 @@ class SIM_MODEL_SWITCH : public SIM_MODEL { public: - SIM_MODEL_SWITCH( TYPE aType ); + class SPICE_GENERATOR : public SIM_MODEL::SPICE_GENERATOR + { + public: + using SIM_MODEL::SPICE_GENERATOR::SPICE_GENERATOR; - wxString GenerateSpiceItemParams() const override; - wxString GenerateSpiceItemLine( const wxString& aRefName, const wxString& aModelName, - const std::vector& aSymbolPinNumbers, - const std::vector& aPinNetNames ) const override; + wxString ItemLine( const wxString& aRefName, const wxString& aModelName, + const std::vector& aSymbolPinNumbers, + const std::vector& aPinNetNames ) const override; + wxString ItemParams() const override; + std::vector> GetPins() const override; + }; + + + SIM_MODEL_SWITCH( TYPE aType ); protected: wxString GenerateParamValuePair( const PARAM& aParam, bool& aIsFirst ) const override; - std::vector> GetSpicePins() const override; private: std::vector getPinNames() const override diff --git a/eeschema/sim/sim_model_tline.cpp b/eeschema/sim/sim_model_tline.cpp index 7325f9a8ba..93c92fd033 100644 --- a/eeschema/sim/sim_model_tline.cpp +++ b/eeschema/sim/sim_model_tline.cpp @@ -25,12 +25,53 @@ #include #include +using SPICE_GENERATOR = SIM_MODEL_TLINE::SPICE_GENERATOR; using PARAM = SIM_MODEL::PARAM; -SIM_MODEL_TLINE::SIM_MODEL_TLINE( TYPE aType ) - : SIM_MODEL( aType ), - m_isInferred( false ) +wxString SPICE_GENERATOR::ModelLine( const wxString& aModelName ) const +{ + wxString r, l, g, c, len; + + switch( m_model.GetType() ) + { + case TYPE::TLINE_Z0: + { + auto z0 = static_cast( *m_model.FindParam( "z0" )->value ); + auto td = static_cast( *m_model.FindParam( "td" )->value ); + + if( !z0.HasValue() || !td.HasValue() ) + return wxString::Format( ".model %s LTRA()\n", aModelName ); + + r = SIM_VALUE_FLOAT( 0 ).ToSpiceString(); + l = ( td * z0 ).ToSpiceString(); + g = SIM_VALUE_FLOAT( 0 ).ToSpiceString(); + c = ( td / z0 ).ToSpiceString(); + len = SIM_VALUE_FLOAT( 1 ).ToSpiceString(); + break; + } + + case TYPE::TLINE_RLGC: + r = m_model.FindParam( "r" )->value->ToSpiceString(); + l = m_model.FindParam( "l" )->value->ToSpiceString(); + g = m_model.FindParam( "g" )->value->ToSpiceString(); + c = m_model.FindParam( "c" )->value->ToSpiceString(); + len = m_model.FindParam( "len" )->value->ToSpiceString(); + break; + + default: + wxFAIL_MSG( "Unhandled SIM_MODEL type in SIM_MODEL_TLINE" ); + return ""; + } + + return wxString::Format( ".model %s LTRA( r=%s l=%s g=%s c=%s len=%s )\n", + aModelName, r, l, g, c, len ); +} + + +SIM_MODEL_TLINE::SIM_MODEL_TLINE( TYPE aType ) : + SIM_MODEL( aType, std::make_unique( *this ) ), + m_isInferred( false ) { static std::vector z0 = makeZ0ParamInfos(); static std::vector rlgc = makeRlgcParamInfos(); @@ -72,46 +113,6 @@ void SIM_MODEL_TLINE::WriteDataLibFields( std::vector& aFields ) cons } -wxString SIM_MODEL_TLINE::GenerateSpiceModelLine( const wxString& aModelName ) const -{ - wxString r, l, g, c, len; - - switch( GetType() ) - { - case TYPE::TLINE_Z0: - { - auto z0 = static_cast( *FindParam( "z0" )->value ); - auto td = static_cast( *FindParam( "td" )->value ); - - if( !z0.HasValue() || !td.HasValue() ) - return wxString::Format( ".model %s ltra()\n", aModelName ); - - r = SIM_VALUE_FLOAT( 0 ).ToSpiceString(); - l = ( td * z0 ).ToSpiceString(); - g = SIM_VALUE_FLOAT( 0 ).ToSpiceString(); - c = ( td / z0 ).ToSpiceString(); - len = SIM_VALUE_FLOAT( 1 ).ToSpiceString(); - break; - } - - case TYPE::TLINE_RLGC: - r = FindParam( "r" )->value->ToSpiceString(); - l = FindParam( "l" )->value->ToSpiceString(); - g = FindParam( "g" )->value->ToSpiceString(); - c = FindParam( "c" )->value->ToSpiceString(); - len = FindParam( "len" )->value->ToSpiceString(); - break; - - default: - wxFAIL_MSG( "Unhandled SIM_MODEL type in SIM_MODEL_TLINE" ); - return ""; - } - - return wxString::Format( ".model %s ltra( r=%s l=%s g=%s c=%s len=%s )\n", - aModelName, r, l, g, c, len ); -} - - template void SIM_MODEL_TLINE::inferredWriteDataFields( std::vector& aFields ) const { diff --git a/eeschema/sim/sim_model_tline.h b/eeschema/sim/sim_model_tline.h index ee9d8e0fbe..c56f496678 100644 --- a/eeschema/sim/sim_model_tline.h +++ b/eeschema/sim/sim_model_tline.h @@ -31,13 +31,20 @@ class SIM_MODEL_TLINE : public SIM_MODEL { public: + class SPICE_GENERATOR : public SIM_MODEL::SPICE_GENERATOR + { + public: + using SIM_MODEL::SPICE_GENERATOR::SPICE_GENERATOR; + + wxString ModelLine( const wxString& aModelName ) const override; + }; + + SIM_MODEL_TLINE( TYPE aType ); void WriteDataSchFields( std::vector& aFields ) const override; void WriteDataLibFields( std::vector& aFields ) const override; - wxString GenerateSpiceModelLine( const wxString& aModelName ) const override; - private: template void inferredReadDataFields( unsigned aSymbolPinCount, const std::vector* aFields ); diff --git a/eeschema/tools/sch_editor_control.cpp b/eeschema/tools/sch_editor_control.cpp index d17f7b51aa..d6afab7c27 100644 --- a/eeschema/tools/sch_editor_control.cpp +++ b/eeschema/tools/sch_editor_control.cpp @@ -823,7 +823,7 @@ int SCH_EDITOR_CONTROL::SimProbe( const TOOL_EVENT& aEvent ) symbol->GetFields() ); wxString ref = symbol->GetRef( &m_frame->GetCurrentSheet() ); - std::vector currentNames = model->GenerateSpiceCurrentNames( ref ); + std::vector currentNames = model->SpiceGenerator().CurrentNames( ref ); if( currentNames.size() == 0 ) return true;